From 6a1f5b6cb39eab5cbd4afa4f8b0b927543234d04 Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Fri, 17 Feb 2017 17:17:07 +0000 Subject: [PATCH] Import mutter_3.22.3.orig.tar.xz [dgit import orig mutter_3.22.3.orig.tar.xz] --- ABOUT-NLS | 1410 + COPYING | 339 + Makefile.am | 11 + Makefile.in | 897 + NEWS | 4908 ++++ aclocal.m4 | 1871 ++ build-aux/compile | 347 + build-aux/config.guess | 1421 + build-aux/config.rpath | 684 + build-aux/config.sub | 1807 ++ build-aux/depcomp | 791 + build-aux/install-sh | 501 + build-aux/ltmain.sh | 11147 +++++++ build-aux/missing | 215 + clutter/Makefile.am | 53 + clutter/Makefile.in | 912 + clutter/aclocal.m4 | 1648 ++ clutter/build/Makefile.am | 1 + clutter/build/Makefile.in | 695 + clutter/build/autotools/Makefile.am | 10 + clutter/build/autotools/Makefile.in | 523 + clutter/build/autotools/as-compiler-flag.m4 | 62 + clutter/build/autotools/glib-tap.mk | 134 + clutter/build/autotools/glibtests.m4 | 28 + clutter/build/autotools/introspection.m4 | 96 + clutter/build/autotools/libtool.m4 | 8372 ++++++ clutter/build/autotools/ltoptions.m4 | 437 + clutter/build/autotools/ltsugar.m4 | 124 + clutter/build/autotools/ltversion.m4 | 23 + clutter/build/autotools/lt~obsolete.m4 | 99 + clutter/build/autotools/tap-driver.sh | 652 + clutter/build/autotools/tap-test | 5 + clutter/build/compile | 347 + clutter/build/config.guess | 1421 + clutter/build/config.sub | 1807 ++ clutter/build/depcomp | 791 + clutter/build/install-sh | 501 + clutter/build/ltmain.sh | 11147 +++++++ clutter/build/missing | 215 + clutter/build/test-driver | 148 + clutter/clutter/Makefile.am | 710 + clutter/clutter/Makefile.am.enums | 52 + clutter/clutter/Makefile.am.marshal | 52 + clutter/clutter/Makefile.in | 2450 ++ clutter/clutter/cally/cally-actor-private.h | 42 + clutter/clutter/cally/cally-actor.c | 1248 + clutter/clutter/cally/cally-actor.h | 160 + clutter/clutter/cally/cally-clone.c | 132 + clutter/clutter/cally/cally-clone.h | 84 + clutter/clutter/cally/cally-factory.h | 117 + clutter/clutter/cally/cally-group.c | 147 + clutter/clutter/cally/cally-group.h | 87 + clutter/clutter/cally/cally-main.h | 44 + clutter/clutter/cally/cally-rectangle.c | 98 + clutter/clutter/cally/cally-rectangle.h | 84 + clutter/clutter/cally/cally-root.c | 294 + clutter/clutter/cally/cally-root.h | 84 + clutter/clutter/cally/cally-stage.c | 260 + clutter/clutter/cally/cally-stage.h | 84 + clutter/clutter/cally/cally-text.c | 2334 ++ clutter/clutter/cally/cally-text.h | 84 + clutter/clutter/cally/cally-texture.c | 98 + clutter/clutter/cally/cally-texture.h | 84 + clutter/clutter/cally/cally-util.c | 452 + clutter/clutter/cally/cally-util.h | 84 + clutter/clutter/cally/cally.c | 108 + clutter/clutter/cally/cally.h | 40 + clutter/clutter/clutter-action.c | 63 + clutter/clutter/clutter-action.h | 111 + clutter/clutter/clutter-actor-box.c | 550 + clutter/clutter/clutter-actor-meta-private.h | 97 + clutter/clutter/clutter-actor-meta.c | 664 + clutter/clutter/clutter-actor-meta.h | 119 + clutter/clutter/clutter-actor-private.h | 327 + clutter/clutter/clutter-actor.c | 21136 +++++++++++++ clutter/clutter/clutter-actor.h | 901 + clutter/clutter/clutter-align-constraint.c | 542 + clutter/clutter/clutter-align-constraint.h | 77 + clutter/clutter/clutter-animatable.c | 286 + clutter/clutter/clutter-animatable.h | 121 + clutter/clutter/clutter-autocleanups.h | 106 + clutter/clutter/clutter-backend-private.h | 158 + clutter/clutter/clutter-backend.c | 1365 + clutter/clutter/clutter-backend.h | 79 + clutter/clutter/clutter-base-types.c | 1468 + clutter/clutter/clutter-bezier.c | 514 + clutter/clutter/clutter-bezier.h | 65 + clutter/clutter/clutter-bin-layout.c | 886 + clutter/clutter/clutter-bin-layout.h | 86 + clutter/clutter/clutter-bind-constraint.c | 591 + clutter/clutter/clutter-bind-constraint.h | 77 + clutter/clutter/clutter-binding-pool.c | 938 + clutter/clutter/clutter-binding-pool.h | 135 + clutter/clutter/clutter-blur-effect.c | 278 + clutter/clutter/clutter-blur-effect.h | 59 + clutter/clutter/clutter-box-layout.c | 2333 ++ clutter/clutter/clutter-box-layout.h | 168 + .../clutter-brightness-contrast-effect.c | 657 + .../clutter-brightness-contrast-effect.h | 88 + clutter/clutter/clutter-build-config.h.in | 100 + clutter/clutter/clutter-cairo.c | 92 + clutter/clutter/clutter-cairo.h | 61 + clutter/clutter/clutter-canvas.c | 716 + clutter/clutter/clutter-canvas.h | 106 + clutter/clutter/clutter-child-meta.c | 192 + clutter/clutter/clutter-child-meta.h | 122 + clutter/clutter/clutter-click-action.c | 831 + clutter/clutter/clutter-click-action.h | 120 + clutter/clutter/clutter-clone.c | 442 + clutter/clutter/clutter-clone.h | 94 + clutter/clutter/clutter-color-static.h | 79 + clutter/clutter/clutter-color.c | 1195 + clutter/clutter/clutter-color.h | 200 + clutter/clutter/clutter-colorize-effect.c | 372 + clutter/clutter/clutter-colorize-effect.h | 67 + clutter/clutter/clutter-config.h.in | 16 + clutter/clutter/clutter-constraint-private.h | 42 + clutter/clutter/clutter-constraint.c | 243 + clutter/clutter/clutter-constraint.h | 129 + clutter/clutter/clutter-container.c | 1450 + clutter/clutter/clutter-container.h | 196 + clutter/clutter/clutter-content-private.h | 43 + clutter/clutter/clutter-content.c | 305 + clutter/clutter/clutter-content.h | 103 + clutter/clutter/clutter-debug.h | 88 + clutter/clutter/clutter-deform-effect.c | 813 + clutter/clutter/clutter-deform-effect.h | 117 + clutter/clutter/clutter-deprecated.h | 45 + clutter/clutter/clutter-desaturate-effect.c | 382 + clutter/clutter/clutter-desaturate-effect.h | 65 + .../clutter/clutter-device-manager-private.h | 264 + clutter/clutter/clutter-device-manager.c | 477 + clutter/clutter/clutter-device-manager.h | 119 + clutter/clutter/clutter-drag-action.c | 1322 + clutter/clutter/clutter-drag-action.h | 152 + clutter/clutter/clutter-drop-action.c | 533 + clutter/clutter/clutter-drop-action.h | 115 + clutter/clutter/clutter-easing.c | 555 + clutter/clutter/clutter-easing.h | 142 + clutter/clutter/clutter-effect-private.h | 19 + clutter/clutter/clutter-effect.c | 368 + clutter/clutter/clutter-effect.h | 130 + clutter/clutter/clutter-enum-types.c.in | 41 + clutter/clutter/clutter-enum-types.h.in | 29 + clutter/clutter/clutter-enums.h | 1541 + clutter/clutter/clutter-event-private.h | 36 + clutter/clutter/clutter-event-translator.c | 38 + clutter/clutter/clutter-event-translator.h | 41 + clutter/clutter/clutter-event.c | 2175 ++ clutter/clutter/clutter-event.h | 780 + clutter/clutter/clutter-feature.c | 163 + clutter/clutter/clutter-feature.h | 42 + clutter/clutter/clutter-fixed-layout.c | 180 + clutter/clutter/clutter-fixed-layout.h | 82 + clutter/clutter/clutter-flatten-effect.c | 56 + clutter/clutter/clutter-flatten-effect.h | 73 + clutter/clutter/clutter-flow-layout.c | 1537 + clutter/clutter/clutter-flow-layout.h | 129 + .../clutter/clutter-gesture-action-private.h | 31 + clutter/clutter/clutter-gesture-action.c | 1368 + clutter/clutter/clutter-gesture-action.h | 179 + clutter/clutter/clutter-grid-layout.c | 2206 ++ clutter/clutter/clutter-grid-layout.h | 161 + clutter/clutter/clutter-group.h | 96 + clutter/clutter/clutter-id-pool.c | 131 + clutter/clutter/clutter-id-pool.h | 50 + clutter/clutter/clutter-image.c | 429 + clutter/clutter/clutter-image.h | 139 + clutter/clutter/clutter-input-device-tool.c | 207 + clutter/clutter/clutter-input-device-tool.h | 69 + clutter/clutter/clutter-input-device.c | 2211 ++ clutter/clutter/clutter-input-device.h | 162 + clutter/clutter/clutter-interval.c | 1232 + clutter/clutter/clutter-interval.h | 159 + clutter/clutter/clutter-keyframe-transition.c | 731 + clutter/clutter/clutter-keyframe-transition.h | 122 + clutter/clutter/clutter-keysyms-table.c | 1681 ++ clutter/clutter/clutter-keysyms-update.pl | 217 + clutter/clutter/clutter-keysyms.h | 2309 ++ clutter/clutter/clutter-layout-manager.c | 1112 + clutter/clutter/clutter-layout-manager.h | 227 + clutter/clutter/clutter-layout-meta.c | 147 + clutter/clutter/clutter-layout-meta.h | 103 + clutter/clutter/clutter-macros.h | 395 + clutter/clutter/clutter-main.c | 3735 +++ clutter/clutter/clutter-main.h | 184 + clutter/clutter/clutter-marshal.list | 37 + .../clutter/clutter-master-clock-default.c | 691 + .../clutter/clutter-master-clock-default.h | 48 + clutter/clutter/clutter-master-clock.c | 138 + clutter/clutter/clutter-master-clock.h | 74 + clutter/clutter/clutter-mutter.h | 45 + .../clutter-offscreen-effect-private.h | 10 + clutter/clutter/clutter-offscreen-effect.c | 669 + clutter/clutter/clutter-offscreen-effect.h | 121 + clutter/clutter/clutter-page-turn-effect.c | 424 + clutter/clutter/clutter-page-turn-effect.h | 80 + clutter/clutter/clutter-paint-node-private.h | 171 + clutter/clutter/clutter-paint-node.c | 1147 + clutter/clutter/clutter-paint-node.h | 101 + clutter/clutter/clutter-paint-nodes.c | 1299 + clutter/clutter/clutter-paint-nodes.h | 148 + .../clutter/clutter-paint-volume-private.h | 138 + clutter/clutter/clutter-paint-volume.c | 1236 + clutter/clutter/clutter-pan-action.c | 1019 + clutter/clutter/clutter-pan-action.h | 152 + clutter/clutter/clutter-path-constraint.c | 396 + clutter/clutter/clutter-path-constraint.h | 72 + clutter/clutter/clutter-path.c | 1604 + clutter/clutter/clutter-path.h | 181 + clutter/clutter/clutter-private.h | 312 + clutter/clutter/clutter-property-transition.c | 360 + clutter/clutter/clutter-property-transition.h | 91 + clutter/clutter/clutter-rotate-action.c | 252 + clutter/clutter/clutter-rotate-action.h | 100 + clutter/clutter/clutter-script-parser.c | 2256 ++ clutter/clutter/clutter-script-private.h | 172 + clutter/clutter/clutter-script.c | 1689 ++ clutter/clutter/clutter-script.h | 220 + clutter/clutter/clutter-scriptable.c | 185 + clutter/clutter/clutter-scriptable.h | 112 + clutter/clutter/clutter-scroll-actor.c | 436 + clutter/clutter/clutter-scroll-actor.h | 97 + clutter/clutter/clutter-settings-private.h | 20 + clutter/clutter/clutter-settings.c | 892 + clutter/clutter/clutter-settings.h | 27 + clutter/clutter/clutter-shader-effect.c | 923 + clutter/clutter/clutter-shader-effect.h | 121 + clutter/clutter/clutter-shader-types.c | 566 + clutter/clutter/clutter-shader-types.h | 104 + clutter/clutter/clutter-snap-constraint.c | 604 + clutter/clutter/clutter-snap-constraint.h | 81 + .../clutter/clutter-stage-manager-private.h | 49 + clutter/clutter/clutter-stage-manager.c | 323 + clutter/clutter/clutter-stage-manager.h | 86 + clutter/clutter/clutter-stage-private.h | 134 + clutter/clutter/clutter-stage-view.c | 319 + clutter/clutter/clutter-stage-view.h | 73 + clutter/clutter/clutter-stage-window.c | 359 + clutter/clutter/clutter-stage-window.h | 155 + clutter/clutter/clutter-stage.c | 4772 +++ clutter/clutter/clutter-stage.h | 270 + clutter/clutter/clutter-swipe-action.c | 280 + clutter/clutter/clutter-swipe-action.h | 109 + clutter/clutter/clutter-tap-action.c | 151 + clutter/clutter/clutter-tap-action.h | 102 + clutter/clutter/clutter-test-utils.c | 467 + clutter/clutter/clutter-test-utils.h | 164 + clutter/clutter/clutter-text-buffer.c | 766 + clutter/clutter/clutter-text-buffer.h | 172 + clutter/clutter/clutter-text.c | 6300 ++++ clutter/clutter/clutter-text.h | 307 + clutter/clutter/clutter-texture.h | 130 + clutter/clutter/clutter-timeline.c | 2555 ++ clutter/clutter/clutter-timeline.h | 226 + clutter/clutter/clutter-transition-group.c | 252 + clutter/clutter/clutter-transition-group.h | 95 + clutter/clutter/clutter-transition.c | 683 + clutter/clutter/clutter-transition.h | 132 + clutter/clutter/clutter-types.h | 776 + clutter/clutter/clutter-units.c | 934 + clutter/clutter/clutter-units.h | 184 + clutter/clutter/clutter-util.c | 682 + clutter/clutter/clutter-version.h | 347 + clutter/clutter/clutter-version.h.in | 347 + .../clutter/clutter-virtual-input-device.c | 222 + .../clutter/clutter-virtual-input-device.h | 116 + clutter/clutter/clutter-zoom-action.c | 517 + clutter/clutter/clutter-zoom-action.h | 114 + clutter/clutter/clutter.h | 119 + clutter/clutter/cogl/clutter-stage-cogl.c | 907 + clutter/clutter/cogl/clutter-stage-cogl.h | 86 + .../deprecated/clutter-actor-deprecated.c | 411 + clutter/clutter/deprecated/clutter-actor.h | 161 + clutter/clutter/deprecated/clutter-alpha.c | 952 + clutter/clutter/deprecated/clutter-alpha.h | 150 + .../clutter/deprecated/clutter-animatable.h | 47 + .../clutter/deprecated/clutter-animation.c | 2632 ++ .../clutter/deprecated/clutter-animation.h | 210 + clutter/clutter/deprecated/clutter-animator.c | 2166 ++ clutter/clutter/deprecated/clutter-animator.h | 188 + clutter/clutter/deprecated/clutter-backend.h | 64 + .../deprecated/clutter-behaviour-depth.c | 305 + .../deprecated/clutter-behaviour-depth.h | 101 + .../deprecated/clutter-behaviour-ellipse.c | 1061 + .../deprecated/clutter-behaviour-ellipse.h | 159 + .../deprecated/clutter-behaviour-opacity.c | 312 + .../deprecated/clutter-behaviour-opacity.h | 115 + .../deprecated/clutter-behaviour-path.c | 467 + .../deprecated/clutter-behaviour-path.h | 135 + .../deprecated/clutter-behaviour-rotate.c | 690 + .../deprecated/clutter-behaviour-rotate.h | 119 + .../deprecated/clutter-behaviour-scale.c | 439 + .../deprecated/clutter-behaviour-scale.h | 107 + .../clutter/deprecated/clutter-behaviour.c | 660 + .../clutter/deprecated/clutter-behaviour.h | 170 + .../clutter/deprecated/clutter-bin-layout.h | 56 + clutter/clutter/deprecated/clutter-box.c | 747 + clutter/clutter/deprecated/clutter-box.h | 143 + .../deprecated/clutter-cairo-texture.c | 1165 + .../deprecated/clutter-cairo-texture.h | 139 + .../clutter/deprecated/clutter-container.h | 93 + .../clutter/deprecated/clutter-frame-source.c | 263 + .../clutter/deprecated/clutter-frame-source.h | 49 + clutter/clutter/deprecated/clutter-group.c | 564 + clutter/clutter/deprecated/clutter-group.h | 62 + .../clutter-input-device-deprecated.c | 38 + .../clutter/deprecated/clutter-input-device.h | 41 + clutter/clutter/deprecated/clutter-keysyms.h | 2311 ++ .../clutter-layout-manager-deprecated.c | 89 + .../clutter/deprecated/clutter-list-model.c | 836 + .../clutter/deprecated/clutter-list-model.h | 95 + clutter/clutter/deprecated/clutter-main.h | 96 + clutter/clutter/deprecated/clutter-media.c | 666 + clutter/clutter/deprecated/clutter-media.h | 121 + .../deprecated/clutter-model-private.h | 52 + clutter/clutter/deprecated/clutter-model.c | 2477 ++ clutter/clutter/deprecated/clutter-model.h | 436 + .../clutter/deprecated/clutter-rectangle.c | 602 + .../clutter/deprecated/clutter-rectangle.h | 117 + clutter/clutter/deprecated/clutter-score.c | 1168 + clutter/clutter/deprecated/clutter-score.h | 144 + clutter/clutter/deprecated/clutter-shader.c | 933 + clutter/clutter/deprecated/clutter-shader.h | 182 + .../deprecated/clutter-stage-manager.h | 42 + clutter/clutter/deprecated/clutter-stage.h | 105 + clutter/clutter/deprecated/clutter-state.c | 2310 ++ clutter/clutter/deprecated/clutter-state.h | 187 + .../clutter/deprecated/clutter-table-layout.c | 2611 ++ .../clutter/deprecated/clutter-table-layout.h | 172 + clutter/clutter/deprecated/clutter-texture.c | 3106 ++ clutter/clutter/deprecated/clutter-texture.h | 136 + clutter/clutter/deprecated/clutter-timeline.h | 41 + .../deprecated/clutter-timeout-interval.c | 142 + .../deprecated/clutter-timeout-interval.h | 58 + .../clutter/deprecated/clutter-timeout-pool.c | 500 + .../clutter/deprecated/clutter-timeout-pool.h | 69 + clutter/clutter/deprecated/clutter-util.h | 40 + .../clutter/egl/clutter-backend-eglnative.c | 214 + .../clutter/egl/clutter-backend-eglnative.h | 78 + clutter/clutter/egl/clutter-egl-headers.h | 41 + clutter/clutter/egl/clutter-egl.h | 102 + .../evdev/clutter-device-manager-evdev.c | 2779 ++ .../evdev/clutter-device-manager-evdev.h | 101 + clutter/clutter/evdev/clutter-evdev.h | 155 + clutter/clutter/evdev/clutter-event-evdev.c | 191 + .../evdev/clutter-input-device-evdev.c | 315 + .../evdev/clutter-input-device-evdev.h | 107 + .../evdev/clutter-input-device-tool-evdev.c | 72 + .../evdev/clutter-input-device-tool-evdev.h | 77 + clutter/clutter/evdev/clutter-seat-evdev.c | 594 + clutter/clutter/evdev/clutter-seat-evdev.h | 132 + .../clutter-virtual-input-device-evdev.c | 495 + .../clutter-virtual-input-device-evdev.h | 35 + clutter/clutter/evdev/clutter-xkb-utils.c | 115 + clutter/clutter/evdev/clutter-xkb-utils.h | 46 + clutter/clutter/mutter-clutter.pc.in | 24 + .../wayland/clutter-wayland-compositor.h | 45 + .../clutter/wayland/clutter-wayland-surface.c | 652 + .../clutter/wayland/clutter-wayland-surface.h | 117 + clutter/clutter/x11/clutter-backend-x11.c | 1501 + clutter/clutter/x11/clutter-backend-x11.h | 148 + .../x11/clutter-device-manager-core-x11.c | 544 + .../x11/clutter-device-manager-core-x11.h | 70 + .../clutter/x11/clutter-device-manager-xi2.c | 1716 ++ .../clutter/x11/clutter-device-manager-xi2.h | 64 + clutter/clutter/x11/clutter-event-x11.c | 394 + .../x11/clutter-input-device-core-x11.c | 78 + .../x11/clutter-input-device-core-x11.h | 44 + .../clutter/x11/clutter-input-device-xi2.c | 174 + .../clutter/x11/clutter-input-device-xi2.h | 47 + clutter/clutter/x11/clutter-keymap-x11.c | 667 + clutter/clutter/x11/clutter-keymap-x11.h | 56 + clutter/clutter/x11/clutter-settings-x11.h | 28 + clutter/clutter/x11/clutter-stage-x11.c | 1633 ++ clutter/clutter/x11/clutter-stage-x11.h | 100 + .../x11/clutter-virtual-input-device-x11.c | 89 + .../x11/clutter-virtual-input-device-x11.h | 35 + .../clutter/x11/clutter-x11-texture-pixmap.c | 1270 + .../clutter/x11/clutter-x11-texture-pixmap.h | 116 + clutter/clutter/x11/clutter-x11.h | 169 + .../clutter/x11/xsettings/xsettings-client.c | 609 + .../clutter/x11/xsettings/xsettings-client.h | 79 + .../clutter/x11/xsettings/xsettings-common.c | 265 + .../clutter/x11/xsettings/xsettings-common.h | 132 + clutter/configure | 17419 +++++++++++ clutter/configure.ac | 833 + clutter/examples/Makefile.am | 36 + clutter/examples/Makefile.in | 876 + clutter/examples/README | 10 + clutter/examples/actor-model.c | 522 + clutter/examples/basic-actor.c | 153 + clutter/examples/bin-layout.c | 307 + clutter/examples/box-layout.c | 314 + clutter/examples/canvas.c | 170 + clutter/examples/constraints.c | 90 + clutter/examples/drag-action.c | 249 + clutter/examples/drop-action.c | 263 + clutter/examples/easing-modes.c | 241 + clutter/examples/flow-layout.c | 164 + clutter/examples/grid-layout.c | 378 + clutter/examples/image-content.c | 110 + clutter/examples/layout-manager.c | 461 + clutter/examples/pan-action.c | 194 + clutter/examples/redhand.png | Bin 0 -> 8250 bytes clutter/examples/rounded-rectangle.c | 110 + clutter/examples/scroll-actor.c | 193 + clutter/examples/threads.c | 292 + clutter/tests/Makefile.am | 3 + clutter/tests/Makefile.in | 695 + clutter/tests/README | 38 + clutter/tests/accessibility/Makefile.am | 36 + clutter/tests/accessibility/Makefile.in | 750 + .../cally-atkcomponent-example.c | 94 + .../cally-atkeditabletext-example.c | 268 + .../accessibility/cally-atkevents-example.c | 196 + .../accessibility/cally-atktext-example.c | 268 + .../tests/accessibility/cally-clone-example.c | 116 + .../tests/accessibility/cally-examples-util.c | 146 + .../tests/accessibility/cally-examples-util.h | 24 + clutter/tests/clutter-1.0.suppressions | 173 + clutter/tests/conform/Makefile.am | 97 + clutter/tests/conform/Makefile.in | 1955 ++ clutter/tests/conform/actor-anchors.c | 741 + clutter/tests/conform/actor-destroy.c | 195 + clutter/tests/conform/actor-graph.c | 549 + clutter/tests/conform/actor-invariants.c | 371 + clutter/tests/conform/actor-iter.c | 218 + clutter/tests/conform/actor-layout.c | 92 + clutter/tests/conform/actor-meta.c | 40 + .../conform/actor-offscreen-limit-max-size.c | 119 + .../tests/conform/actor-offscreen-redirect.c | 348 + clutter/tests/conform/actor-paint-opacity.c | 141 + clutter/tests/conform/actor-pick.c | 311 + clutter/tests/conform/actor-shader-effect.c | 284 + clutter/tests/conform/actor-size.c | 216 + clutter/tests/conform/animator.c | 199 + clutter/tests/conform/behaviours.c | 80 + clutter/tests/conform/binding-pool.c | 297 + clutter/tests/conform/color.c | 319 + clutter/tests/conform/events-touch.c | 392 + clutter/tests/conform/group.c | 60 + clutter/tests/conform/interval.c | 117 + clutter/tests/conform/model.c | 528 + clutter/tests/conform/rectangle.c | 51 + clutter/tests/conform/script-parser.c | 427 + .../conform/scripts/test-animator-1.json | 5 + .../conform/scripts/test-animator-2.json | 29 + .../conform/scripts/test-animator-3.json | 40 + .../scripts/test-script-animation.json | 14 + .../conform/scripts/test-script-child.json | 21 + .../scripts/test-script-implicit-alpha.json | 8 + .../conform/scripts/test-script-interval.json | 16 + .../scripts/test-script-layout-property.json | 21 + .../conform/scripts/test-script-margin.json | 22 + .../conform/scripts/test-script-model.json | 17 + .../scripts/test-script-named-object.json | 44 + .../scripts/test-script-object-property.json | 13 + .../conform/scripts/test-script-single.json | 10 + .../scripts/test-script-timeline-markers.json | 12 + .../tests/conform/scripts/test-state-1.json | 33 + clutter/tests/conform/text.c | 550 + clutter/tests/conform/texture.c | 84 + clutter/tests/conform/units.c | 131 + clutter/tests/interactive/Makefile.am | 147 + clutter/tests/interactive/Makefile.in | 1602 + clutter/tests/interactive/redhand.png | Bin 0 -> 8250 bytes clutter/tests/interactive/test-actors.c | 316 + clutter/tests/interactive/test-animation.c | 126 + clutter/tests/interactive/test-animator.c | 138 + .../tests/interactive/test-bind-constraint.c | 252 + clutter/tests/interactive/test-binding-pool.c | 308 + clutter/tests/interactive/test-cairo-clock.c | 119 + .../tests/interactive/test-cairo-flowers.c | 256 + .../interactive/test-cogl-multitexture.c | 238 + .../tests/interactive/test-cogl-offscreen.c | 333 + .../interactive/test-cogl-point-sprites.c | 288 + .../interactive/test-cogl-shader-arbfp.c | 407 + .../tests/interactive/test-cogl-shader-glsl.c | 365 + .../tests/interactive/test-cogl-tex-convert.c | 225 + .../tests/interactive/test-cogl-tex-foreign.c | 272 + .../tests/interactive/test-cogl-tex-polygon.c | 421 + .../tests/interactive/test-cogl-tex-tile.c | 219 + .../interactive/test-cogl-vertex-buffer.c | 390 + clutter/tests/interactive/test-content.c | 233 + clutter/tests/interactive/test-devices.c | 286 + clutter/tests/interactive/test-easing.c | 270 + clutter/tests/interactive/test-events.c | 502 + clutter/tests/interactive/test-fbo.c | 105 + clutter/tests/interactive/test-grab.c | 251 + clutter/tests/interactive/test-image.c | 252 + .../interactive/test-keyframe-transition.c | 108 + clutter/tests/interactive/test-layout.c | 687 + clutter/tests/interactive/test-main.c | 221 + clutter/tests/interactive/test-multistage.c | 149 + .../tests/interactive/test-paint-wrapper.c | 370 + .../tests/interactive/test-path-constraint.c | 133 + clutter/tests/interactive/test-pixmap.c | 331 + clutter/tests/interactive/test-rotate-zoom.c | 94 + clutter/tests/interactive/test-scale.c | 119 + .../interactive/test-script-signals.json | 68 + clutter/tests/interactive/test-script.c | 207 + clutter/tests/interactive/test-script.json | 74 + clutter/tests/interactive/test-scrolling.c | 134 + .../tests/interactive/test-shader-effects.c | 83 + .../interactive/test-stage-read-pixels.c | 168 + clutter/tests/interactive/test-stage-sizing.c | 141 + .../tests/interactive/test-state-animator.c | 144 + clutter/tests/interactive/test-state-script.c | 53 + clutter/tests/interactive/test-state.c | 206 + clutter/tests/interactive/test-swipe-action.c | 194 + clutter/tests/interactive/test-table-layout.c | 284 + clutter/tests/interactive/test-text-field.c | 331 + clutter/tests/interactive/test-text.c | 94 + .../tests/interactive/test-texture-async.c | 156 + .../tests/interactive/test-texture-material.c | 46 + .../tests/interactive/test-texture-quality.c | 116 + .../tests/interactive/test-texture-slicing.c | 125 + clutter/tests/interactive/test-touch-events.c | 193 + clutter/tests/interactive/wrapper.sh.in | 15 + clutter/tests/micro-bench/Makefile.am | 34 + clutter/tests/micro-bench/Makefile.in | 731 + clutter/tests/micro-bench/test-cogl-perf.c | 158 + clutter/tests/micro-bench/test-picking.c | 140 + clutter/tests/micro-bench/test-random-text.c | 105 + clutter/tests/micro-bench/test-text-perf.c | 187 + clutter/tests/micro-bench/test-text.c | 120 + clutter/tests/performance/Makefile-retrospect | 66 + clutter/tests/performance/Makefile-tests | 15 + clutter/tests/performance/Makefile.am | 42 + clutter/tests/performance/Makefile.in | 759 + clutter/tests/performance/create-report.rb | 179 + clutter/tests/performance/test-common.h | 130 + clutter/tests/performance/test-picking.c | 134 + clutter/tests/performance/test-state-hidden.c | 150 + .../performance/test-state-interactive.c | 194 + clutter/tests/performance/test-state-mini.c | 153 + clutter/tests/performance/test-state-pick.c | 159 + clutter/tests/performance/test-state.c | 158 + clutter/tests/performance/test-text-perf.c | 167 + cogl/Makefile.am | 37 + cogl/Makefile.in | 926 + cogl/aclocal.m4 | 1647 ++ cogl/build/autotools/Makefile.am.enums | 52 + cogl/build/autotools/as-compiler-flag.m4 | 62 + cogl/build/autotools/introspection.m4 | 94 + cogl/build/autotools/libtool.m4 | 8372 ++++++ cogl/build/autotools/ltoptions.m4 | 437 + cogl/build/autotools/ltsugar.m4 | 124 + cogl/build/autotools/ltversion.m4 | 23 + cogl/build/autotools/lt~obsolete.m4 | 99 + cogl/build/compile | 347 + cogl/build/config.guess | 1421 + cogl/build/config.sub | 1807 ++ cogl/build/depcomp | 791 + cogl/build/install-sh | 501 + cogl/build/ltmain.sh | 11147 +++++++ cogl/build/missing | 215 + cogl/cogl-config.h.in | 149 + cogl/cogl-gles2/GLES2/gl2.h | 169 + cogl/cogl-gles2/GLES2/gl2ext.h | 1498 + cogl/cogl-gles2/GLES2/gl2platform.h | 28 + cogl/cogl-gles2/Makefile.am | 31 + cogl/cogl-gles2/Makefile.in | 808 + cogl/cogl-gles2/cogl-gles2-api.c | 1048 + cogl/cogl-gles2/mutter-cogl-gles2-1.0.pc.in | 13 + cogl/cogl-mutter-config.h.in | 17 + cogl/cogl-pango/Makefile.am | 93 + cogl/cogl-pango/Makefile.in | 956 + cogl/cogl-pango/cogl-pango-display-list.c | 499 + cogl/cogl-pango/cogl-pango-display-list.h | 84 + cogl/cogl-pango/cogl-pango-fontmap.c | 184 + cogl/cogl-pango/cogl-pango-glyph-cache.c | 433 + cogl/cogl-pango/cogl-pango-glyph-cache.h | 100 + cogl/cogl-pango/cogl-pango-pipeline-cache.c | 242 + cogl/cogl-pango/cogl-pango-pipeline-cache.h | 72 + cogl/cogl-pango/cogl-pango-private.h | 65 + cogl/cogl-pango/cogl-pango-render.c | 929 + cogl/cogl-pango/cogl-pango.h | 299 + cogl/cogl-pango/cogl-pango.symbols | 12 + cogl/cogl-pango/mutter-cogl-pango-1.0.pc.in | 13 + cogl/cogl-path/Makefile.am | 102 + cogl/cogl-path/Makefile.in | 1097 + cogl/cogl-path/cogl-path-enum-types.c.in | 50 + cogl/cogl-path/cogl-path-enum-types.h.in | 25 + cogl/cogl-path/cogl-path-functions.h | 541 + cogl/cogl-path/cogl-path-private.h | 126 + cogl/cogl-path/cogl-path-types.h | 85 + cogl/cogl-path/cogl-path.c | 1602 + cogl/cogl-path/cogl-path.h | 60 + cogl/cogl-path/cogl-path.symbols | 59 + cogl/cogl-path/mutter-cogl-path-1.0.pc.in | 13 + cogl/cogl-path/tesselator/GL/glu.h | 47 + cogl/cogl-path/tesselator/README | 446 + cogl/cogl-path/tesselator/dict-list.h | 100 + cogl/cogl-path/tesselator/dict.c | 111 + cogl/cogl-path/tesselator/dict.h | 100 + cogl/cogl-path/tesselator/geom.c | 264 + cogl/cogl-path/tesselator/geom.h | 84 + cogl/cogl-path/tesselator/gluos.h | 1 + cogl/cogl-path/tesselator/memalloc.h | 49 + cogl/cogl-path/tesselator/mesh.c | 798 + cogl/cogl-path/tesselator/mesh.h | 266 + cogl/cogl-path/tesselator/normal.c | 257 + cogl/cogl-path/tesselator/normal.h | 45 + cogl/cogl-path/tesselator/priorityq-heap.c | 256 + cogl/cogl-path/tesselator/priorityq-heap.h | 107 + cogl/cogl-path/tesselator/priorityq-sort.h | 117 + cogl/cogl-path/tesselator/priorityq.c | 261 + cogl/cogl-path/tesselator/priorityq.h | 117 + cogl/cogl-path/tesselator/render.c | 502 + cogl/cogl-path/tesselator/render.h | 52 + cogl/cogl-path/tesselator/sweep.c | 1361 + cogl/cogl-path/tesselator/sweep.h | 77 + cogl/cogl-path/tesselator/tess.c | 632 + cogl/cogl-path/tesselator/tess.h | 165 + cogl/cogl-path/tesselator/tesselator.h | 122 + cogl/cogl-path/tesselator/tessmono.c | 201 + cogl/cogl-path/tesselator/tessmono.h | 71 + cogl/cogl/Makefile.am | 510 + cogl/cogl/Makefile.in | 1837 ++ cogl/cogl/cogl-atlas-texture-private.h | 81 + cogl/cogl/cogl-atlas-texture.c | 1047 + cogl/cogl/cogl-atlas-texture.h | 254 + cogl/cogl/cogl-atlas.c | 690 + cogl/cogl/cogl-atlas.h | 105 + cogl/cogl/cogl-attribute-buffer-private.h | 44 + cogl/cogl/cogl-attribute-buffer.c | 104 + cogl/cogl/cogl-attribute-buffer.h | 148 + cogl/cogl/cogl-attribute-private.h | 140 + cogl/cogl/cogl-attribute.c | 687 + cogl/cogl/cogl-attribute.h | 554 + cogl/cogl/cogl-bitmap-conversion.c | 748 + cogl/cogl/cogl-bitmap-packing.h | 767 + cogl/cogl/cogl-bitmap-pixbuf.c | 136 + cogl/cogl/cogl-bitmap-private.h | 201 + cogl/cogl/cogl-bitmap.c | 522 + cogl/cogl/cogl-bitmap.h | 302 + cogl/cogl/cogl-bitmask.c | 489 + cogl/cogl/cogl-bitmask.h | 312 + cogl/cogl/cogl-blend-string.c | 1003 + cogl/cogl/cogl-blend-string.h | 144 + cogl/cogl/cogl-blit.c | 438 + cogl/cogl/cogl-blit.h | 101 + cogl/cogl/cogl-boxed-value.c | 377 + cogl/cogl/cogl-boxed-value.h | 117 + cogl/cogl/cogl-buffer-private.h | 180 + cogl/cogl/cogl-buffer.c | 411 + cogl/cogl/cogl-buffer.h | 325 + cogl/cogl/cogl-clip-stack.c | 412 + cogl/cogl/cogl-clip-stack.h | 213 + cogl/cogl/cogl-closure-list-private.h | 118 + cogl/cogl/cogl-closure-list.c | 71 + cogl/cogl/cogl-color-private.h | 51 + cogl/cogl/cogl-color.c | 448 + cogl/cogl/cogl-color.h | 600 + cogl/cogl/cogl-config-private.h | 45 + cogl/cogl/cogl-config.c | 135 + cogl/cogl/cogl-context-private.h | 407 + cogl/cogl/cogl-context.c | 816 + cogl/cogl/cogl-context.h | 411 + cogl/cogl/cogl-debug-options.h | 199 + cogl/cogl/cogl-debug.c | 302 + cogl/cogl/cogl-debug.h | 123 + cogl/cogl/cogl-defines.h.in | 45 + cogl/cogl/cogl-deprecated.h | 43 + cogl/cogl/cogl-depth-state-private.h | 38 + cogl/cogl/cogl-depth-state.c | 116 + cogl/cogl/cogl-depth-state.h | 270 + cogl/cogl/cogl-display-private.h | 54 + cogl/cogl/cogl-display.c | 167 + cogl/cogl/cogl-display.h | 210 + cogl/cogl/cogl-driver.h | 268 + cogl/cogl/cogl-egl-defines.h.in | 40 + cogl/cogl/cogl-egl-private.h | 40 + cogl/cogl/cogl-egl.h | 118 + cogl/cogl/cogl-error-private.h | 57 + cogl/cogl/cogl-error.c | 128 + cogl/cogl/cogl-error.h | 169 + cogl/cogl/cogl-euler.c | 198 + cogl/cogl/cogl-euler.h | 265 + cogl/cogl/cogl-feature-private.c | 234 + cogl/cogl/cogl-feature-private.h | 106 + cogl/cogl/cogl-fence-private.h | 66 + cogl/cogl/cogl-fence.c | 236 + cogl/cogl/cogl-fence.h | 143 + cogl/cogl/cogl-flags.h | 130 + cogl/cogl/cogl-frame-info-private.h | 52 + cogl/cogl/cogl-frame-info.c | 87 + cogl/cogl/cogl-frame-info.h | 149 + cogl/cogl/cogl-framebuffer-private.h | 514 + cogl/cogl/cogl-framebuffer.c | 2550 ++ cogl/cogl/cogl-framebuffer.h | 1850 ++ cogl/cogl/cogl-gl-header.h.in | 46 + cogl/cogl/cogl-gles2-context-private.h | 201 + cogl/cogl/cogl-gles2-context.c | 1966 ++ cogl/cogl/cogl-gles2-types.h | 474 + cogl/cogl/cogl-gles2.h | 416 + cogl/cogl/cogl-glib-source.c | 195 + cogl/cogl/cogl-glib-source.h | 97 + cogl/cogl/cogl-glsl-shader-boilerplate.h | 86 + cogl/cogl/cogl-glsl-shader-private.h | 41 + cogl/cogl/cogl-glsl-shader.c | 192 + cogl/cogl/cogl-glx-display-private.h | 62 + cogl/cogl/cogl-glx-renderer-private.h | 108 + cogl/cogl/cogl-glx.h | 96 + cogl/cogl/cogl-gpu-info-private.h | 117 + cogl/cogl/cogl-gpu-info.c | 581 + cogl/cogl/cogl-gtype-private.h | 278 + cogl/cogl/cogl-gtype.c | 153 + cogl/cogl/cogl-i18n-private.h | 39 + cogl/cogl/cogl-index-buffer-private.h | 44 + cogl/cogl/cogl-index-buffer.c | 112 + cogl/cogl/cogl-index-buffer.h | 103 + cogl/cogl/cogl-indices-private.h | 60 + cogl/cogl/cogl-indices.c | 271 + cogl/cogl/cogl-indices.h | 161 + cogl/cogl/cogl-journal-private.h | 121 + cogl/cogl/cogl-journal.c | 1853 ++ cogl/cogl/cogl-list.c | 94 + cogl/cogl/cogl-list.h | 129 + cogl/cogl/cogl-macros.h | 287 + cogl/cogl/cogl-magazine-private.h | 81 + cogl/cogl/cogl-magazine.c | 84 + cogl/cogl/cogl-matrix-private.h | 58 + cogl/cogl/cogl-matrix-stack-private.h | 200 + cogl/cogl/cogl-matrix-stack.c | 1211 + cogl/cogl/cogl-matrix-stack.h | 641 + cogl/cogl/cogl-matrix.c | 2311 ++ cogl/cogl/cogl-matrix.h | 799 + cogl/cogl/cogl-memory-stack-private.h | 50 + cogl/cogl/cogl-memory-stack.c | 196 + cogl/cogl/cogl-meta-texture.c | 642 + cogl/cogl/cogl-meta-texture.h | 195 + cogl/cogl/cogl-mutter.h | 48 + cogl/cogl/cogl-node-private.h | 89 + cogl/cogl/cogl-node.c | 110 + cogl/cogl/cogl-object-private.h | 317 + cogl/cogl/cogl-object.c | 304 + cogl/cogl/cogl-object.h | 236 + cogl/cogl/cogl-offscreen.h | 174 + cogl/cogl/cogl-onscreen-private.h | 115 + cogl/cogl/cogl-onscreen-template-private.h | 45 + cogl/cogl/cogl-onscreen-template.c | 105 + cogl/cogl/cogl-onscreen-template.h | 139 + cogl/cogl/cogl-onscreen.c | 720 + cogl/cogl/cogl-onscreen.h | 901 + cogl/cogl/cogl-output-private.h | 57 + cogl/cogl/cogl-output.c | 119 + cogl/cogl/cogl-output.h | 257 + cogl/cogl/cogl-pango.h | 36 + cogl/cogl/cogl-pipeline-cache.c | 216 + cogl/cogl/cogl-pipeline-cache.h | 93 + cogl/cogl/cogl-pipeline-debug.c | 301 + cogl/cogl/cogl-pipeline-hash-table.c | 233 + cogl/cogl/cogl-pipeline-hash-table.h | 81 + cogl/cogl/cogl-pipeline-layer-private.h | 390 + cogl/cogl/cogl-pipeline-layer-state-private.h | 141 + cogl/cogl/cogl-pipeline-layer-state.c | 1814 ++ cogl/cogl/cogl-pipeline-layer-state.h | 616 + cogl/cogl/cogl-pipeline-layer.c | 942 + cogl/cogl/cogl-pipeline-private.h | 998 + cogl/cogl/cogl-pipeline-snippet-private.h | 116 + cogl/cogl/cogl-pipeline-snippet.c | 286 + cogl/cogl/cogl-pipeline-state-private.h | 196 + cogl/cogl/cogl-pipeline-state.c | 2171 ++ cogl/cogl/cogl-pipeline-state.h | 976 + cogl/cogl/cogl-pipeline.c | 3174 ++ cogl/cogl/cogl-pipeline.h | 185 + cogl/cogl/cogl-pixel-buffer-private.h | 52 + cogl/cogl/cogl-pixel-buffer.c | 134 + cogl/cogl/cogl-pixel-buffer.h | 138 + cogl/cogl/cogl-point-in-poly-private.h | 46 + cogl/cogl/cogl-point-in-poly.c | 101 + cogl/cogl/cogl-poll-private.h | 77 + cogl/cogl/cogl-poll.c | 267 + cogl/cogl/cogl-poll.h | 195 + cogl/cogl/cogl-primitive-private.h | 73 + cogl/cogl/cogl-primitive-texture.c | 60 + cogl/cogl/cogl-primitive-texture.h | 112 + cogl/cogl/cogl-primitive.c | 645 + cogl/cogl/cogl-primitive.h | 944 + cogl/cogl/cogl-primitives-private.h | 67 + cogl/cogl/cogl-primitives.c | 1148 + cogl/cogl/cogl-primitives.h | 197 + cogl/cogl/cogl-private.h | 170 + cogl/cogl/cogl-profile.c | 124 + cogl/cogl/cogl-profile.h | 68 + cogl/cogl/cogl-quaternion-private.h | 44 + cogl/cogl/cogl-quaternion.c | 673 + cogl/cogl/cogl-quaternion.h | 560 + cogl/cogl/cogl-rectangle-map.c | 764 + cogl/cogl/cogl-rectangle-map.h | 84 + cogl/cogl/cogl-renderer-private.h | 111 + cogl/cogl/cogl-renderer.c | 846 + cogl/cogl/cogl-renderer.h | 427 + cogl/cogl/cogl-sampler-cache-private.h | 96 + cogl/cogl/cogl-sampler-cache.c | 371 + cogl/cogl/cogl-snippet-private.h | 77 + cogl/cogl/cogl-snippet.c | 187 + cogl/cogl/cogl-snippet.h | 864 + cogl/cogl/cogl-spans.c | 183 + cogl/cogl/cogl-spans.h | 81 + cogl/cogl/cogl-sub-texture-private.h | 62 + cogl/cogl/cogl-sub-texture.c | 480 + cogl/cogl/cogl-sub-texture.h | 134 + cogl/cogl/cogl-swap-chain-private.h | 45 + cogl/cogl/cogl-swap-chain.c | 76 + cogl/cogl/cogl-swap-chain.h | 67 + cogl/cogl/cogl-texture-2d-gl.h | 78 + cogl/cogl/cogl-texture-2d-private.h | 134 + cogl/cogl/cogl-texture-2d-sliced-private.h | 67 + cogl/cogl/cogl-texture-2d-sliced.c | 1546 + cogl/cogl/cogl-texture-2d-sliced.h | 299 + cogl/cogl/cogl-texture-2d.c | 695 + cogl/cogl/cogl-texture-2d.h | 232 + cogl/cogl/cogl-texture-3d-private.h | 66 + cogl/cogl/cogl-texture-3d.c | 759 + cogl/cogl/cogl-texture-3d.h | 202 + cogl/cogl/cogl-texture-driver.h | 206 + cogl/cogl/cogl-texture-private.h | 409 + cogl/cogl/cogl-texture-rectangle-private.h | 66 + cogl/cogl/cogl-texture-rectangle.c | 777 + cogl/cogl/cogl-texture-rectangle.h | 216 + cogl/cogl/cogl-texture.c | 1540 + cogl/cogl/cogl-texture.h | 516 + cogl/cogl/cogl-types.h | 898 + cogl/cogl/cogl-util.c | 286 + cogl/cogl/cogl-util.h | 258 + cogl/cogl/cogl-vector.c | 300 + cogl/cogl/cogl-vector.h | 356 + cogl/cogl/cogl-version.h | 358 + cogl/cogl/cogl-wayland-server.h | 163 + cogl/cogl/cogl-x11-renderer-private.h | 40 + cogl/cogl/cogl-xlib-private.h | 54 + cogl/cogl/cogl-xlib-renderer-private.h | 103 + cogl/cogl/cogl-xlib-renderer.c | 677 + cogl/cogl/cogl-xlib-renderer.h | 238 + cogl/cogl/cogl-xlib.c | 112 + cogl/cogl/cogl-xlib.h | 132 + cogl/cogl/cogl.c | 820 + cogl/cogl/cogl.h | 177 + cogl/cogl/cogl.symbols | 1087 + cogl/cogl/cogl1-context.h | 862 + cogl/cogl/deprecated/cogl-auto-texture.c | 419 + cogl/cogl/deprecated/cogl-auto-texture.h | 223 + cogl/cogl/deprecated/cogl-clutter-xlib.h | 50 + cogl/cogl/deprecated/cogl-clutter.c | 114 + cogl/cogl/deprecated/cogl-clutter.h | 54 + .../deprecated/cogl-framebuffer-deprecated.c | 295 + .../deprecated/cogl-framebuffer-deprecated.h | 265 + cogl/cogl/deprecated/cogl-material-compat.c | 464 + cogl/cogl/deprecated/cogl-material-compat.h | 1391 + cogl/cogl/deprecated/cogl-program-private.h | 88 + cogl/cogl/deprecated/cogl-program.c | 503 + cogl/cogl/deprecated/cogl-shader-private.h | 72 + cogl/cogl/deprecated/cogl-shader.c | 376 + cogl/cogl/deprecated/cogl-shader.h | 703 + cogl/cogl/deprecated/cogl-type-casts.h | 55 + .../deprecated/cogl-vertex-buffer-private.h | 165 + cogl/cogl/deprecated/cogl-vertex-buffer.c | 1795 ++ cogl/cogl/deprecated/cogl-vertex-buffer.h | 451 + .../driver/gl/cogl-attribute-gl-private.h | 53 + cogl/cogl/driver/gl/cogl-attribute-gl.c | 541 + cogl/cogl/driver/gl/cogl-buffer-gl-private.h | 74 + cogl/cogl/driver/gl/cogl-buffer-gl.c | 435 + .../driver/gl/cogl-clip-stack-gl-private.h | 45 + cogl/cogl/driver/gl/cogl-clip-stack-gl.c | 627 + .../driver/gl/cogl-framebuffer-gl-private.h | 102 + cogl/cogl/driver/gl/cogl-framebuffer-gl.c | 1624 + .../gl/cogl-pipeline-fragend-fixed-private.h | 42 + .../driver/gl/cogl-pipeline-fragend-fixed.c | 435 + .../gl/cogl-pipeline-fragend-glsl-private.h | 45 + .../driver/gl/cogl-pipeline-fragend-glsl.c | 1149 + .../driver/gl/cogl-pipeline-opengl-private.h | 158 + cogl/cogl/driver/gl/cogl-pipeline-opengl.c | 1481 + .../gl/cogl-pipeline-progend-fixed-private.h | 42 + .../driver/gl/cogl-pipeline-progend-fixed.c | 112 + .../gl/cogl-pipeline-progend-glsl-private.h | 47 + .../driver/gl/cogl-pipeline-progend-glsl.c | 1074 + .../gl/cogl-pipeline-vertend-fixed-private.h | 42 + .../driver/gl/cogl-pipeline-vertend-fixed.c | 121 + .../gl/cogl-pipeline-vertend-glsl-private.h | 45 + .../driver/gl/cogl-pipeline-vertend-glsl.c | 680 + .../driver/gl/cogl-texture-2d-gl-private.h | 119 + cogl/cogl/driver/gl/cogl-texture-2d-gl.c | 750 + cogl/cogl/driver/gl/cogl-texture-gl-private.h | 66 + cogl/cogl/driver/gl/cogl-texture-gl.c | 158 + cogl/cogl/driver/gl/cogl-util-gl-private.h | 99 + cogl/cogl/driver/gl/cogl-util-gl.c | 206 + cogl/cogl/driver/gl/gl/cogl-driver-gl.c | 699 + .../gl/cogl-pipeline-fragend-arbfp-private.h | 42 + .../gl/gl/cogl-pipeline-fragend-arbfp.c | 988 + ...ogl-pipeline-progend-fixed-arbfp-private.h | 42 + .../gl/gl/cogl-pipeline-progend-fixed-arbfp.c | 121 + .../driver/gl/gl/cogl-texture-driver-gl.c | 549 + cogl/cogl/driver/gl/gles/cogl-driver-gles.c | 487 + .../driver/gl/gles/cogl-texture-driver-gles.c | 644 + .../driver/nop/cogl-attribute-nop-private.h | 48 + cogl/cogl/driver/nop/cogl-attribute-nop.c | 49 + .../driver/nop/cogl-clip-stack-nop-private.h | 44 + cogl/cogl/driver/nop/cogl-clip-stack-nop.c | 43 + cogl/cogl/driver/nop/cogl-driver-nop.c | 86 + .../driver/nop/cogl-framebuffer-nop-private.h | 100 + cogl/cogl/driver/nop/cogl-framebuffer-nop.c | 121 + .../driver/nop/cogl-texture-2d-nop-private.h | 103 + cogl/cogl/driver/nop/cogl-texture-2d-nop.c | 132 + cogl/cogl/gl-prototypes/cogl-all-functions.h | 336 + cogl/cogl/gl-prototypes/cogl-core-functions.h | 198 + .../cogl/gl-prototypes/cogl-fixed-functions.h | 119 + .../cogl/gl-prototypes/cogl-gles1-functions.h | 43 + .../cogl/gl-prototypes/cogl-gles2-functions.h | 43 + cogl/cogl/gl-prototypes/cogl-glsl-functions.h | 286 + .../cogl-in-gles-core-functions.h | 148 + .../cogl-in-gles1-core-functions.h | 78 + .../cogl-in-gles2-core-functions.h | 186 + cogl/cogl/mutter-cogl-1.0.pc.in | 13 + .../winsys/cogl-texture-pixmap-x11-private.h | 103 + cogl/cogl/winsys/cogl-texture-pixmap-x11.c | 1184 + cogl/cogl/winsys/cogl-texture-pixmap-x11.h | 286 + .../cogl-winsys-egl-feature-functions.h | 149 + cogl/cogl/winsys/cogl-winsys-egl-private.h | 203 + .../cogl/winsys/cogl-winsys-egl-x11-private.h | 39 + cogl/cogl/winsys/cogl-winsys-egl-x11.c | 888 + cogl/cogl/winsys/cogl-winsys-egl.c | 1092 + .../cogl-winsys-glx-feature-functions.h | 210 + cogl/cogl/winsys/cogl-winsys-glx-private.h | 37 + cogl/cogl/winsys/cogl-winsys-glx.c | 2791 ++ cogl/cogl/winsys/cogl-winsys-private.h | 198 + cogl/cogl/winsys/cogl-winsys-stub-private.h | 37 + cogl/cogl/winsys/cogl-winsys-stub.c | 197 + cogl/cogl/winsys/cogl-winsys.c | 52 + cogl/config-custom.h | 32 + cogl/configure | 24416 ++++++++++++++++ cogl/configure.ac | 1014 + cogl/test-fixtures/Makefile.am | 21 + cogl/test-fixtures/Makefile.in | 686 + cogl/test-fixtures/test-unit.h | 31 + cogl/test-fixtures/test-utils.c | 535 + cogl/test-fixtures/test-utils.h | 287 + cogl/tests/Makefile.am | 31 + cogl/tests/Makefile.in | 809 + cogl/tests/README | 63 + cogl/tests/config.env.in | 3 + cogl/tests/conform/Makefile.am | 177 + cogl/tests/conform/Makefile.in | 1703 ++ cogl/tests/conform/test-alpha-test.c | 73 + cogl/tests/conform/test-alpha-textures.c | 123 + cogl/tests/conform/test-atlas-migration.c | 145 + cogl/tests/conform/test-backface-culling.c | 311 + cogl/tests/conform/test-blend-strings.c | 430 + cogl/tests/conform/test-blend.c | 64 + cogl/tests/conform/test-color-hsl.c | 45 + cogl/tests/conform/test-color-mask.c | 110 + cogl/tests/conform/test-conform-main.c | 157 + .../tests/conform/test-copy-replace-texture.c | 120 + cogl/tests/conform/test-custom-attributes.c | 301 + cogl/tests/conform/test-depth-test.c | 301 + cogl/tests/conform/test-euler-quaternion.c | 81 + cogl/tests/conform/test-fence.c | 59 + .../tests/conform/test-framebuffer-get-bits.c | 40 + cogl/tests/conform/test-gles2-context.c | 962 + cogl/tests/conform/test-just-vertex-shader.c | 205 + cogl/tests/conform/test-layer-remove.c | 145 + cogl/tests/conform/test-map-buffer-range.c | 123 + cogl/tests/conform/test-no-gl-header.c | 16 + cogl/tests/conform/test-npot-texture.c | 170 + cogl/tests/conform/test-offscreen.c | 199 + cogl/tests/conform/test-path-clip.c | 67 + cogl/tests/conform/test-path.c | 214 + .../test-pipeline-cache-unrefs-texture.c | 91 + .../conform/test-pipeline-shader-state.c | 93 + cogl/tests/conform/test-pipeline-uniforms.c | 415 + .../tests/conform/test-pipeline-user-matrix.c | 140 + cogl/tests/conform/test-pixel-buffer.c | 269 + .../tests/conform/test-point-size-attribute.c | 166 + cogl/tests/conform/test-point-size.c | 99 + cogl/tests/conform/test-point-sprite.c | 194 + cogl/tests/conform/test-premult.c | 301 + .../conform/test-primitive-and-journal.c | 122 + cogl/tests/conform/test-primitive.c | 334 + .../tests/conform/test-read-texture-formats.c | 222 + cogl/tests/conform/test-snippets.c | 815 + cogl/tests/conform/test-sparse-pipeline.c | 62 + cogl/tests/conform/test-sub-texture.c | 325 + cogl/tests/conform/test-texture-3d.c | 274 + .../tests/conform/test-texture-get-set-data.c | 144 + cogl/tests/conform/test-texture-no-allocate.c | 80 + cogl/tests/conform/test-texture-rg.c | 74 + cogl/tests/conform/test-version.c | 81 + cogl/tests/conform/test-wrap-modes.c | 296 + .../conform/test-wrap-rectangle-textures.c | 175 + .../conform/test-write-texture-formats.c | 184 + cogl/tests/data/Makefile.am | 3 + cogl/tests/data/Makefile.in | 517 + cogl/tests/data/valgrind.suppressions | 173 + cogl/tests/micro-perf/Makefile.am | 23 + cogl/tests/micro-perf/Makefile.in | 683 + cogl/tests/micro-perf/test-journal.c | 190 + cogl/tests/run-tests.sh | 157 + cogl/tests/test-launcher.sh | 39 + cogl/tests/unit/Makefile.am | 84 + cogl/tests/unit/Makefile.in | 760 + cogl/tests/unit/test-unit-main.c | 45 + config.h.in | 166 + configure | 20850 +++++++++++++ configure.ac | 497 + data/50-mutter-navigation.xml | 140 + data/50-mutter-system.xml | 13 + data/50-mutter-windows.xml | 50 + data/Makefile.am | 37 + data/Makefile.in | 643 + data/mutter-schemas.convert | 5 + data/mutter.desktop.in | 17 + data/org.gnome.mutter.gschema.xml.in | 129 + data/org.gnome.mutter.wayland.gschema.xml.in | 53 + doc/Makefile.am | 4 + doc/Makefile.in | 688 + doc/code-overview.txt | 185 + doc/dialogs.txt | 32 + doc/how-to-get-focus-right.txt | 252 + doc/man/Makefile.am | 3 + doc/man/Makefile.in | 586 + doc/man/mutter.1 | 60 + doc/rationales.txt | 79 + m4/gettext.m4 | 405 + m4/iconv.m4 | 271 + m4/intlmacosx.m4 | 56 + m4/lib-ld.m4 | 119 + m4/lib-link.m4 | 777 + m4/lib-prefix.m4 | 224 + m4/libtool.m4 | 8372 ++++++ m4/ltoptions.m4 | 437 + m4/ltsugar.m4 | 124 + m4/ltversion.m4 | 23 + m4/lt~obsolete.m4 | 99 + m4/nls.m4 | 32 + m4/po.m4 | 453 + m4/progtest.m4 | 91 + po/ChangeLog | 5062 ++++ po/LINGUAS | 98 + po/Makefile.in.in | 478 + po/Makevars | 68 + po/POTFILES.in | 30 + po/Rules-quot | 58 + po/am.gmo | Bin 0 -> 4536 bytes po/am.po | 2696 ++ po/ar.gmo | Bin 0 -> 9880 bytes po/ar.po | 1595 + po/as.gmo | Bin 0 -> 46706 bytes po/as.po | 1964 ++ po/ast.gmo | Bin 0 -> 40881 bytes po/ast.po | 2571 ++ po/az.gmo | Bin 0 -> 101227 bytes po/az.po | 3172 ++ po/be.gmo | Bin 0 -> 44858 bytes po/be.po | 1600 + po/be@latin.gmo | Bin 0 -> 58830 bytes po/be@latin.po | 3886 +++ po/bg.gmo | Bin 0 -> 5301 bytes po/bg.po | 537 + po/bn.gmo | Bin 0 -> 132007 bytes po/bn.po | 3231 ++ po/bn_IN.gmo | Bin 0 -> 48662 bytes po/bn_IN.po | 1758 ++ po/boldquot.sed | 10 + po/br.gmo | Bin 0 -> 12354 bytes po/br.po | 1836 ++ po/bs.gmo | Bin 0 -> 13728 bytes po/bs.po | 612 + po/ca.gmo | Bin 0 -> 14794 bytes po/ca.po | 1121 + po/ca@valencia.gmo | Bin 0 -> 31422 bytes po/ca@valencia.po | 1310 + po/cs.gmo | Bin 0 -> 14343 bytes po/cs.po | 1291 + po/cy.gmo | Bin 0 -> 118517 bytes po/cy.po | 3805 +++ po/da.gmo | Bin 0 -> 13694 bytes po/da.po | 1717 ++ po/de.gmo | Bin 0 -> 14843 bytes po/de.po | 1786 ++ po/dz.gmo | Bin 0 -> 223712 bytes po/dz.po | 2577 ++ po/el.gmo | Bin 0 -> 19769 bytes po/el.po | 1614 + po/en@boldquot.header | 25 + po/en@quot.header | 22 + po/en_CA.gmo | Bin 0 -> 116763 bytes po/en_CA.po | 3632 +++ po/en_GB.gmo | Bin 0 -> 13355 bytes po/en_GB.po | 3612 +++ po/eo.gmo | Bin 0 -> 6979 bytes po/eo.po | 1049 + po/es.gmo | Bin 0 -> 14667 bytes po/es.po | 3675 +++ po/et.gmo | Bin 0 -> 33293 bytes po/et.po | 1438 + po/eu.gmo | Bin 0 -> 13880 bytes po/eu.po | 1752 ++ po/fa.gmo | Bin 0 -> 31789 bytes po/fa.po | 3387 +++ po/fi.gmo | Bin 0 -> 10508 bytes po/fi.po | 1082 + po/fr.gmo | Bin 0 -> 15348 bytes po/fr.po | 648 + po/fur.gmo | Bin 0 -> 14035 bytes po/fur.po | 625 + po/ga.gmo | Bin 0 -> 5209 bytes po/ga.po | 1477 + po/gd.gmo | Bin 0 -> 5430 bytes po/gd.po | 574 + po/gl.gmo | Bin 0 -> 14367 bytes po/gl.po | 1817 ++ po/gu.gmo | Bin 0 -> 44747 bytes po/gu.po | 1860 ++ po/ha.gmo | Bin 0 -> 38023 bytes po/ha.po | 3600 +++ po/he.gmo | Bin 0 -> 14596 bytes po/he.po | 1877 ++ po/hi.gmo | Bin 0 -> 45529 bytes po/hi.po | 2479 ++ po/hr.gmo | Bin 0 -> 112987 bytes po/hr.po | 3680 +++ po/hu.gmo | Bin 0 -> 14685 bytes po/hu.po | 1747 ++ po/hy.gmo | Bin 0 -> 41731 bytes po/hy.po | 2854 ++ po/id.gmo | Bin 0 -> 9118 bytes po/id.po | 387 + po/ig.gmo | Bin 0 -> 41546 bytes po/ig.po | 3514 +++ po/insert-header.sin | 23 + po/is.gmo | Bin 0 -> 11128 bytes po/is.po | 2721 ++ po/it.gmo | Bin 0 -> 14524 bytes po/it.po | 641 + po/ja.gmo | Bin 0 -> 10353 bytes po/ja.po | 1734 ++ po/ka.gmo | Bin 0 -> 12985 bytes po/ka.po | 3418 +++ po/kk.gmo | Bin 0 -> 9961 bytes po/kk.po | 666 + po/kn.gmo | Bin 0 -> 51463 bytes po/kn.po | 1745 ++ po/ko.gmo | Bin 0 -> 14409 bytes po/ko.po | 626 + po/ku.gmo | Bin 0 -> 19324 bytes po/ku.po | 2505 ++ po/la.gmo | Bin 0 -> 1731 bytes po/la.po | 2183 ++ po/lt.gmo | Bin 0 -> 14273 bytes po/lt.po | 1113 + po/lv.gmo | Bin 0 -> 14163 bytes po/lv.po | 630 + po/mai.gmo | Bin 0 -> 70026 bytes po/mai.po | 2273 ++ po/mg.gmo | Bin 0 -> 115670 bytes po/mg.po | 3485 +++ po/mk.gmo | Bin 0 -> 154508 bytes po/mk.po | 3611 +++ po/ml.gmo | Bin 0 -> 21567 bytes po/ml.po | 1998 ++ po/mn.gmo | Bin 0 -> 67583 bytes po/mn.po | 3313 +++ po/mr.gmo | Bin 0 -> 44615 bytes po/mr.po | 2497 ++ po/ms.gmo | Bin 0 -> 33695 bytes po/ms.po | 2755 ++ po/mutter.pot | 588 + po/nb.gmo | Bin 0 -> 3832 bytes po/nb.po | 904 + po/nds.gmo | Bin 0 -> 7982 bytes po/nds.po | 1815 ++ po/ne.gmo | Bin 0 -> 196460 bytes po/ne.po | 3339 +++ po/nl.gmo | Bin 0 -> 14117 bytes po/nl.po | 1715 ++ po/nn.gmo | Bin 0 -> 119905 bytes po/nn.po | 3529 +++ po/oc.gmo | Bin 0 -> 14987 bytes po/oc.po | 623 + po/or.gmo | Bin 0 -> 48199 bytes po/or.po | 2442 ++ po/pa.gmo | Bin 0 -> 19854 bytes po/pa.po | 2210 ++ po/pl.gmo | Bin 0 -> 15137 bytes po/pl.po | 637 + po/pt.gmo | Bin 0 -> 14538 bytes po/pt.po | 3756 +++ po/pt_BR.gmo | Bin 0 -> 14633 bytes po/pt_BR.po | 3745 +++ po/quot.sed | 6 + po/remove-potcdate.sin | 19 + po/ro.gmo | Bin 0 -> 14212 bytes po/ro.po | 3662 +++ po/ru.gmo | Bin 0 -> 19429 bytes po/ru.po | 1119 + po/rw.gmo | Bin 0 -> 962 bytes po/rw.po | 3241 ++ po/si.gmo | Bin 0 -> 3017 bytes po/si.po | 2988 ++ po/sk.gmo | Bin 0 -> 14493 bytes po/sk.po | 1446 + po/sl.gmo | Bin 0 -> 13772 bytes po/sl.po | 650 + po/sq.gmo | Bin 0 -> 126366 bytes po/sq.po | 4000 +++ po/sr.gmo | Bin 0 -> 18551 bytes po/sr.po | 1332 + po/sr@latin.gmo | Bin 0 -> 14209 bytes po/sr@latin.po | 1332 + po/stamp-po | 1 + po/sv.gmo | Bin 0 -> 13932 bytes po/sv.po | 625 + po/ta.gmo | Bin 0 -> 48658 bytes po/ta.po | 2539 ++ po/te.gmo | Bin 0 -> 51445 bytes po/te.po | 1979 ++ po/tg.gmo | Bin 0 -> 2309 bytes po/tg.po | 1663 ++ po/th.gmo | Bin 0 -> 21285 bytes po/th.po | 601 + po/tk.gmo | Bin 0 -> 1881 bytes po/tk.po | 2680 ++ po/tr.gmo | Bin 0 -> 14374 bytes po/tr.po | 2243 ++ po/ug.gmo | Bin 0 -> 48046 bytes po/ug.po | 1935 ++ po/uk.gmo | Bin 0 -> 17709 bytes po/uk.po | 3459 +++ po/vi.gmo | Bin 0 -> 15296 bytes po/vi.po | 1307 + po/wa.gmo | Bin 0 -> 11799 bytes po/wa.po | 2716 ++ po/xh.gmo | Bin 0 -> 105636 bytes po/xh.po | 3295 +++ po/yo.gmo | Bin 0 -> 47398 bytes po/yo.po | 3494 +++ po/zh_CN.gmo | Bin 0 -> 12972 bytes po/zh_CN.po | 3271 +++ po/zh_HK.gmo | Bin 0 -> 29083 bytes po/zh_HK.po | 1253 + po/zh_TW.gmo | Bin 0 -> 12896 bytes po/zh_TW.po | 1061 + src/Makefile-tests.am | 55 + src/Makefile.am | 595 + src/Makefile.in | 2602 ++ src/backends/edid-parse.c | 539 + src/backends/edid.h | 193 + src/backends/meta-backend-private.h | 155 + src/backends/meta-backend.c | 812 + src/backends/meta-barrier-private.h | 76 + src/backends/meta-barrier.c | 355 + src/backends/meta-cursor-renderer.c | 292 + src/backends/meta-cursor-renderer.h | 84 + src/backends/meta-cursor-tracker-private.h | 72 + src/backends/meta-cursor-tracker.c | 438 + src/backends/meta-cursor.c | 368 + src/backends/meta-cursor.h | 75 + src/backends/meta-display-config-shared.h | 38 + src/backends/meta-idle-monitor-dbus.c | 289 + src/backends/meta-idle-monitor-dbus.h | 28 + src/backends/meta-idle-monitor-private.h | 65 + src/backends/meta-idle-monitor.c | 318 + src/backends/meta-input-settings-private.h | 155 + src/backends/meta-input-settings.c | 1920 ++ src/backends/meta-monitor-config.c | 2054 ++ src/backends/meta-monitor-config.h | 54 + src/backends/meta-monitor-manager-dummy.c | 298 + src/backends/meta-monitor-manager-dummy.h | 40 + src/backends/meta-monitor-manager-private.h | 431 + src/backends/meta-monitor-manager.c | 1618 + src/backends/meta-pointer-constraint.c | 57 + src/backends/meta-pointer-constraint.h | 60 + src/backends/meta-renderer-view.c | 202 + src/backends/meta-renderer-view.h | 31 + src/backends/meta-renderer.c | 119 + src/backends/meta-renderer.h | 56 + src/backends/meta-stage.c | 303 + src/backends/meta-stage.h | 71 + src/backends/native/dbus-utils.c | 107 + src/backends/native/dbus-utils.h | 32 + src/backends/native/gen-default-modes.py | 89 + .../native/meta-backend-native-private.h | 32 + src/backends/native/meta-backend-native.c | 508 + src/backends/native/meta-backend-native.h | 55 + src/backends/native/meta-barrier-native.c | 617 + src/backends/native/meta-barrier-native.h | 68 + .../native/meta-clutter-backend-native.c | 94 + .../native/meta-clutter-backend-native.h | 41 + .../native/meta-cursor-renderer-native.c | 717 + .../native/meta-cursor-renderer-native.h | 56 + src/backends/native/meta-default-modes.h | 29 + .../native/meta-idle-monitor-native.c | 200 + .../native/meta-idle-monitor-native.h | 43 + .../native/meta-input-settings-native.c | 441 + .../native/meta-input-settings-native.h | 49 + src/backends/native/meta-launcher.c | 512 + src/backends/native/meta-launcher.h | 39 + .../native/meta-monitor-manager-kms.c | 1758 ++ .../native/meta-monitor-manager-kms.h | 65 + src/backends/native/meta-renderer-native.c | 1349 + src/backends/native/meta-renderer-native.h | 63 + src/backends/native/meta-stage-native.c | 338 + src/backends/native/meta-stage-native.h | 40 + src/backends/x11/meta-backend-x11.c | 940 + src/backends/x11/meta-backend-x11.h | 60 + src/backends/x11/meta-barrier-x11.c | 219 + src/backends/x11/meta-barrier-x11.h | 59 + src/backends/x11/meta-clutter-backend-x11.c | 93 + src/backends/x11/meta-clutter-backend-x11.h | 38 + src/backends/x11/meta-cursor-renderer-x11.c | 108 + src/backends/x11/meta-cursor-renderer-x11.h | 52 + src/backends/x11/meta-idle-monitor-xsync.c | 373 + src/backends/x11/meta-idle-monitor-xsync.h | 47 + src/backends/x11/meta-input-settings-x11.c | 576 + src/backends/x11/meta-input-settings-x11.h | 49 + .../x11/meta-monitor-manager-xrandr.c | 1512 + .../x11/meta-monitor-manager-xrandr.h | 43 + src/backends/x11/meta-renderer-x11.c | 111 + src/backends/x11/meta-renderer-x11.h | 37 + src/backends/x11/meta-stage-x11-nested.c | 180 + src/backends/x11/meta-stage-x11-nested.h | 34 + .../nested/meta-cursor-renderer-x11-nested.c | 89 + .../nested/meta-cursor-renderer-x11-nested.h | 38 + src/compositor/clutter-utils.c | 190 + src/compositor/clutter-utils.h | 39 + src/compositor/cogl-utils.c | 141 + src/compositor/cogl-utils.h | 38 + src/compositor/compositor-private.h | 65 + src/compositor/compositor.c | 1410 + .../meta-background-actor-private.h | 11 + src/compositor/meta-background-actor.c | 782 + src/compositor/meta-background-group.c | 66 + src/compositor/meta-background-image.c | 359 + src/compositor/meta-background-private.h | 15 + src/compositor/meta-background.c | 967 + src/compositor/meta-cullable.c | 201 + src/compositor/meta-cullable.h | 66 + src/compositor/meta-dnd-actor-private.h | 64 + src/compositor/meta-dnd-actor.c | 231 + src/compositor/meta-feedback-actor-private.h | 74 + src/compositor/meta-feedback-actor.c | 249 + src/compositor/meta-module.c | 204 + src/compositor/meta-module.h | 55 + src/compositor/meta-plugin-manager.c | 367 + src/compositor/meta-plugin-manager.h | 92 + src/compositor/meta-plugin.c | 225 + src/compositor/meta-shadow-factory.c | 1062 + src/compositor/meta-shaped-texture-private.h | 41 + src/compositor/meta-shaped-texture.c | 950 + src/compositor/meta-surface-actor-wayland.c | 488 + src/compositor/meta-surface-actor-wayland.h | 87 + src/compositor/meta-surface-actor-x11.c | 481 + src/compositor/meta-surface-actor-x11.h | 69 + src/compositor/meta-surface-actor.c | 380 + src/compositor/meta-surface-actor.h | 81 + src/compositor/meta-sync-ring.c | 592 + src/compositor/meta-sync-ring.h | 14 + src/compositor/meta-texture-rectangle.c | 61 + src/compositor/meta-texture-rectangle.h | 36 + src/compositor/meta-texture-tower.c | 492 + src/compositor/meta-texture-tower.h | 67 + src/compositor/meta-window-actor-private.h | 62 + src/compositor/meta-window-actor.c | 2148 ++ src/compositor/meta-window-group.c | 211 + src/compositor/meta-window-group.h | 37 + src/compositor/meta-window-shape.c | 258 + src/compositor/plugins/Makefile.am | 39 + src/compositor/plugins/Makefile.in | 756 + src/compositor/plugins/default.c | 822 + src/compositor/region-utils.c | 340 + src/compositor/region-utils.h | 102 + src/core/bell.c | 305 + src/core/bell.h | 88 + src/core/boxes-private.h | 218 + src/core/boxes.c | 2015 ++ src/core/constraints.c | 1661 ++ src/core/constraints.h | 36 + src/core/core.c | 290 + src/core/core.h | 83 + src/core/delete.c | 215 + src/core/display-private.h | 499 + src/core/display.c | 3204 ++ src/core/edge-resistance.c | 1256 + src/core/edge-resistance.h | 42 + src/core/errors.c | 62 + src/core/events.c | 418 + src/core/events.h | 31 + src/core/frame.c | 404 + src/core/frame.h | 86 + src/core/keybindings-private.h | 141 + src/core/keybindings.c | 4083 +++ src/core/main.c | 623 + src/core/meta-accel-parse.c | 357 + src/core/meta-accel-parse.h | 43 + src/core/meta-border.c | 154 + src/core/meta-border.h | 84 + src/core/meta-gesture-tracker-private.h | 75 + src/core/meta-gesture-tracker.c | 582 + src/core/mutter.c | 86 + src/core/place.c | 945 + src/core/place.h | 39 + src/core/prefs.c | 2307 ++ src/core/restart-helper.c | 82 + src/core/restart.c | 212 + src/core/screen-private.h | 220 + src/core/screen.c | 2948 ++ src/core/stack-tracker.c | 1141 + src/core/stack-tracker.h | 85 + src/core/stack.c | 1473 + src/core/stack.h | 418 + src/core/startup-notification-private.h | 48 + src/core/startup-notification.c | 770 + src/core/testboxes.c | 1410 + src/core/util-private.h | 53 + src/core/util.c | 996 + src/core/window-private.h | 751 + src/core/window.c | 7991 +++++ src/core/workspace-private.h | 99 + src/core/workspace.c | 1311 + src/libmutter.pc.in | 13 + src/meta-enum-types.c.in | 40 + src/meta-enum-types.h.in | 26 + src/meta/barrier.h | 115 + src/meta/boxes.h | 141 + src/meta/common.h | 539 + src/meta/compositor-mutter.h | 52 + src/meta/compositor.h | 135 + src/meta/display.h | 199 + src/meta/errors.h | 37 + src/meta/group.h | 55 + src/meta/keybindings.h | 36 + src/meta/main.h | 57 + src/meta/meta-backend.h | 54 + src/meta/meta-background-actor.h | 75 + src/meta/meta-background-group.h | 37 + src/meta/meta-background-image.h | 76 + src/meta/meta-background.h | 81 + src/meta/meta-cursor-tracker.h | 56 + src/meta/meta-idle-monitor.h | 60 + src/meta/meta-monitor-manager.h | 39 + src/meta/meta-plugin.h | 405 + src/meta/meta-shadow-factory.h | 122 + src/meta/meta-shaped-texture.h | 86 + src/meta/meta-version.h.in | 28 + src/meta/meta-window-actor.h | 72 + src/meta/meta-window-shape.h | 60 + src/meta/prefs.h | 404 + src/meta/screen.h | 131 + src/meta/theme.h | 37 + src/meta/types.h | 41 + src/meta/util.h | 194 + src/meta/window.h | 264 + src/meta/workspace.h | 58 + src/org.freedesktop.login1.xml | 46 + src/org.gnome.Mutter.DisplayConfig.xml | 294 + src/org.gnome.Mutter.IdleMonitor.xml | 35 + src/tests/mutter-all.test.in | 5 + src/tests/stacking/basic-wayland.metatest | 22 + src/tests/stacking/basic-x11.metatest | 19 + src/tests/stacking/minimized.metatest | 18 + src/tests/stacking/mixed-windows.metatest | 26 + src/tests/stacking/override-redirect.metatest | 19 + src/tests/stacking/set-parent.metatest | 14 + src/tests/test-client.c | 435 + src/tests/test-runner.c | 1173 + src/tests/unit-tests.c | 238 + src/ui/frames.c | 1722 ++ src/ui/frames.h | 141 + src/ui/theme-private.h | 282 + src/ui/theme.c | 1392 + src/ui/ui.c | 313 + src/ui/ui.h | 83 + .../meta-pointer-confinement-wayland.c | 707 + .../meta-pointer-confinement-wayland.h | 45 + src/wayland/meta-pointer-lock-wayland.c | 72 + src/wayland/meta-pointer-lock-wayland.h | 42 + src/wayland/meta-wayland-buffer.c | 186 + src/wayland/meta-wayland-buffer.h | 53 + .../meta-wayland-data-device-private.h | 40 + src/wayland/meta-wayland-data-device.c | 1962 ++ src/wayland/meta-wayland-data-device.h | 137 + src/wayland/meta-wayland-gtk-shell.c | 289 + src/wayland/meta-wayland-gtk-shell.h | 27 + src/wayland/meta-wayland-input-device.c | 129 + src/wayland/meta-wayland-input-device.h | 48 + src/wayland/meta-wayland-keyboard.c | 982 + src/wayland/meta-wayland-keyboard.h | 135 + src/wayland/meta-wayland-outputs.c | 304 + src/wayland/meta-wayland-outputs.h | 49 + .../meta-wayland-pointer-constraints.c | 1177 + .../meta-wayland-pointer-constraints.h | 47 + .../meta-wayland-pointer-gesture-pinch.c | 163 + .../meta-wayland-pointer-gesture-pinch.h | 39 + .../meta-wayland-pointer-gesture-swipe.c | 159 + .../meta-wayland-pointer-gesture-swipe.h | 39 + src/wayland/meta-wayland-pointer-gestures.c | 80 + src/wayland/meta-wayland-pointer-gestures.h | 32 + src/wayland/meta-wayland-pointer.c | 1266 + src/wayland/meta-wayland-pointer.h | 161 + src/wayland/meta-wayland-popup.c | 308 + src/wayland/meta-wayland-popup.h | 62 + src/wayland/meta-wayland-private.h | 76 + src/wayland/meta-wayland-region.c | 105 + src/wayland/meta-wayland-region.h | 40 + src/wayland/meta-wayland-seat.c | 471 + src/wayland/meta-wayland-seat.h | 79 + .../meta-wayland-surface-role-cursor.c | 372 + .../meta-wayland-surface-role-cursor.h | 52 + .../meta-wayland-surface-role-tablet-cursor.c | 42 + .../meta-wayland-surface-role-tablet-cursor.h | 33 + src/wayland/meta-wayland-surface.c | 2134 ++ src/wayland/meta-wayland-surface.h | 327 + src/wayland/meta-wayland-tablet-manager.c | 277 + src/wayland/meta-wayland-tablet-manager.h | 57 + src/wayland/meta-wayland-tablet-pad-group.c | 458 + src/wayland/meta-wayland-tablet-pad-group.h | 74 + src/wayland/meta-wayland-tablet-pad-ring.c | 207 + src/wayland/meta-wayland-tablet-pad-ring.h | 60 + src/wayland/meta-wayland-tablet-pad-strip.c | 206 + src/wayland/meta-wayland-tablet-pad-strip.h | 60 + src/wayland/meta-wayland-tablet-pad.c | 639 + src/wayland/meta-wayland-tablet-pad.h | 82 + src/wayland/meta-wayland-tablet-seat.c | 572 + src/wayland/meta-wayland-tablet-seat.h | 80 + src/wayland/meta-wayland-tablet-tool.c | 980 + src/wayland/meta-wayland-tablet-tool.h | 83 + src/wayland/meta-wayland-tablet.c | 123 + src/wayland/meta-wayland-tablet.h | 58 + src/wayland/meta-wayland-touch.c | 646 + src/wayland/meta-wayland-touch.h | 81 + src/wayland/meta-wayland-types.h | 61 + src/wayland/meta-wayland-versions.h | 51 + src/wayland/meta-wayland-wl-shell.c | 753 + src/wayland/meta-wayland-wl-shell.h | 33 + src/wayland/meta-wayland-xdg-foreign.c | 464 + src/wayland/meta-wayland-xdg-foreign.h | 34 + src/wayland/meta-wayland-xdg-shell.c | 1915 ++ src/wayland/meta-wayland-xdg-shell.h | 52 + src/wayland/meta-wayland.c | 376 + src/wayland/meta-wayland.h | 60 + src/wayland/meta-window-wayland.c | 815 + src/wayland/meta-window-wayland.h | 82 + src/wayland/meta-xwayland-private.h | 44 + src/wayland/meta-xwayland-selection-private.h | 34 + src/wayland/meta-xwayland-selection.c | 1770 ++ src/wayland/meta-xwayland.c | 674 + src/wayland/meta-xwayland.h | 40 + .../protocol/gtk-primary-selection.xml | 225 + src/wayland/protocol/gtk-shell.xml | 61 + src/x11/atomnames.h | 181 + src/x11/events.c | 1824 ++ src/x11/events.h | 31 + src/x11/group-private.h | 41 + src/x11/group-props.c | 232 + src/x11/group-props.h | 36 + src/x11/group.c | 327 + src/x11/iconcache.c | 592 + src/x11/iconcache.h | 75 + src/x11/mutter-Xatomtype.h | 136 + src/x11/session.c | 1830 ++ src/x11/session.h | 89 + src/x11/window-props.c | 1901 ++ src/x11/window-props.h | 95 + src/x11/window-x11-private.h | 71 + src/x11/window-x11.c | 3405 +++ src/x11/window-x11.h | 75 + src/x11/xprops.c | 1116 + src/x11/xprops.h | 198 + 1571 files changed, 867679 insertions(+) create mode 100644 ABOUT-NLS create mode 100644 COPYING create mode 100644 Makefile.am create mode 100644 Makefile.in create mode 100644 NEWS create mode 100644 aclocal.m4 create mode 100755 build-aux/compile create mode 100755 build-aux/config.guess create mode 100755 build-aux/config.rpath create mode 100755 build-aux/config.sub create mode 100755 build-aux/depcomp create mode 100755 build-aux/install-sh create mode 100644 build-aux/ltmain.sh create mode 100755 build-aux/missing create mode 100644 clutter/Makefile.am create mode 100644 clutter/Makefile.in create mode 100644 clutter/aclocal.m4 create mode 100644 clutter/build/Makefile.am create mode 100644 clutter/build/Makefile.in create mode 100644 clutter/build/autotools/Makefile.am create mode 100644 clutter/build/autotools/Makefile.in create mode 100644 clutter/build/autotools/as-compiler-flag.m4 create mode 100644 clutter/build/autotools/glib-tap.mk create mode 100644 clutter/build/autotools/glibtests.m4 create mode 100644 clutter/build/autotools/introspection.m4 create mode 100644 clutter/build/autotools/libtool.m4 create mode 100644 clutter/build/autotools/ltoptions.m4 create mode 100644 clutter/build/autotools/ltsugar.m4 create mode 100644 clutter/build/autotools/ltversion.m4 create mode 100644 clutter/build/autotools/lt~obsolete.m4 create mode 100755 clutter/build/autotools/tap-driver.sh create mode 100755 clutter/build/autotools/tap-test create mode 100755 clutter/build/compile create mode 100755 clutter/build/config.guess create mode 100755 clutter/build/config.sub create mode 100755 clutter/build/depcomp create mode 100755 clutter/build/install-sh create mode 100644 clutter/build/ltmain.sh create mode 100755 clutter/build/missing create mode 100755 clutter/build/test-driver create mode 100644 clutter/clutter/Makefile.am create mode 100644 clutter/clutter/Makefile.am.enums create mode 100644 clutter/clutter/Makefile.am.marshal create mode 100644 clutter/clutter/Makefile.in create mode 100644 clutter/clutter/cally/cally-actor-private.h create mode 100644 clutter/clutter/cally/cally-actor.c create mode 100644 clutter/clutter/cally/cally-actor.h create mode 100644 clutter/clutter/cally/cally-clone.c create mode 100644 clutter/clutter/cally/cally-clone.h create mode 100644 clutter/clutter/cally/cally-factory.h create mode 100644 clutter/clutter/cally/cally-group.c create mode 100644 clutter/clutter/cally/cally-group.h create mode 100644 clutter/clutter/cally/cally-main.h create mode 100644 clutter/clutter/cally/cally-rectangle.c create mode 100644 clutter/clutter/cally/cally-rectangle.h create mode 100644 clutter/clutter/cally/cally-root.c create mode 100644 clutter/clutter/cally/cally-root.h create mode 100644 clutter/clutter/cally/cally-stage.c create mode 100644 clutter/clutter/cally/cally-stage.h create mode 100644 clutter/clutter/cally/cally-text.c create mode 100644 clutter/clutter/cally/cally-text.h create mode 100644 clutter/clutter/cally/cally-texture.c create mode 100644 clutter/clutter/cally/cally-texture.h create mode 100644 clutter/clutter/cally/cally-util.c create mode 100644 clutter/clutter/cally/cally-util.h create mode 100644 clutter/clutter/cally/cally.c create mode 100644 clutter/clutter/cally/cally.h create mode 100644 clutter/clutter/clutter-action.c create mode 100644 clutter/clutter/clutter-action.h create mode 100644 clutter/clutter/clutter-actor-box.c create mode 100644 clutter/clutter/clutter-actor-meta-private.h create mode 100644 clutter/clutter/clutter-actor-meta.c create mode 100644 clutter/clutter/clutter-actor-meta.h create mode 100644 clutter/clutter/clutter-actor-private.h create mode 100644 clutter/clutter/clutter-actor.c create mode 100644 clutter/clutter/clutter-actor.h create mode 100644 clutter/clutter/clutter-align-constraint.c create mode 100644 clutter/clutter/clutter-align-constraint.h create mode 100644 clutter/clutter/clutter-animatable.c create mode 100644 clutter/clutter/clutter-animatable.h create mode 100644 clutter/clutter/clutter-autocleanups.h create mode 100644 clutter/clutter/clutter-backend-private.h create mode 100644 clutter/clutter/clutter-backend.c create mode 100644 clutter/clutter/clutter-backend.h create mode 100644 clutter/clutter/clutter-base-types.c create mode 100644 clutter/clutter/clutter-bezier.c create mode 100644 clutter/clutter/clutter-bezier.h create mode 100644 clutter/clutter/clutter-bin-layout.c create mode 100644 clutter/clutter/clutter-bin-layout.h create mode 100644 clutter/clutter/clutter-bind-constraint.c create mode 100644 clutter/clutter/clutter-bind-constraint.h create mode 100644 clutter/clutter/clutter-binding-pool.c create mode 100644 clutter/clutter/clutter-binding-pool.h create mode 100644 clutter/clutter/clutter-blur-effect.c create mode 100644 clutter/clutter/clutter-blur-effect.h create mode 100644 clutter/clutter/clutter-box-layout.c create mode 100644 clutter/clutter/clutter-box-layout.h create mode 100644 clutter/clutter/clutter-brightness-contrast-effect.c create mode 100644 clutter/clutter/clutter-brightness-contrast-effect.h create mode 100644 clutter/clutter/clutter-build-config.h.in create mode 100644 clutter/clutter/clutter-cairo.c create mode 100644 clutter/clutter/clutter-cairo.h create mode 100644 clutter/clutter/clutter-canvas.c create mode 100644 clutter/clutter/clutter-canvas.h create mode 100644 clutter/clutter/clutter-child-meta.c create mode 100644 clutter/clutter/clutter-child-meta.h create mode 100644 clutter/clutter/clutter-click-action.c create mode 100644 clutter/clutter/clutter-click-action.h create mode 100644 clutter/clutter/clutter-clone.c create mode 100644 clutter/clutter/clutter-clone.h create mode 100644 clutter/clutter/clutter-color-static.h create mode 100644 clutter/clutter/clutter-color.c create mode 100644 clutter/clutter/clutter-color.h create mode 100644 clutter/clutter/clutter-colorize-effect.c create mode 100644 clutter/clutter/clutter-colorize-effect.h create mode 100644 clutter/clutter/clutter-config.h.in create mode 100644 clutter/clutter/clutter-constraint-private.h create mode 100644 clutter/clutter/clutter-constraint.c create mode 100644 clutter/clutter/clutter-constraint.h create mode 100644 clutter/clutter/clutter-container.c create mode 100644 clutter/clutter/clutter-container.h create mode 100644 clutter/clutter/clutter-content-private.h create mode 100644 clutter/clutter/clutter-content.c create mode 100644 clutter/clutter/clutter-content.h create mode 100644 clutter/clutter/clutter-debug.h create mode 100644 clutter/clutter/clutter-deform-effect.c create mode 100644 clutter/clutter/clutter-deform-effect.h create mode 100644 clutter/clutter/clutter-deprecated.h create mode 100644 clutter/clutter/clutter-desaturate-effect.c create mode 100644 clutter/clutter/clutter-desaturate-effect.h create mode 100644 clutter/clutter/clutter-device-manager-private.h create mode 100644 clutter/clutter/clutter-device-manager.c create mode 100644 clutter/clutter/clutter-device-manager.h create mode 100644 clutter/clutter/clutter-drag-action.c create mode 100644 clutter/clutter/clutter-drag-action.h create mode 100644 clutter/clutter/clutter-drop-action.c create mode 100644 clutter/clutter/clutter-drop-action.h create mode 100644 clutter/clutter/clutter-easing.c create mode 100644 clutter/clutter/clutter-easing.h create mode 100644 clutter/clutter/clutter-effect-private.h create mode 100644 clutter/clutter/clutter-effect.c create mode 100644 clutter/clutter/clutter-effect.h create mode 100644 clutter/clutter/clutter-enum-types.c.in create mode 100644 clutter/clutter/clutter-enum-types.h.in create mode 100644 clutter/clutter/clutter-enums.h create mode 100644 clutter/clutter/clutter-event-private.h create mode 100644 clutter/clutter/clutter-event-translator.c create mode 100644 clutter/clutter/clutter-event-translator.h create mode 100644 clutter/clutter/clutter-event.c create mode 100644 clutter/clutter/clutter-event.h create mode 100644 clutter/clutter/clutter-feature.c create mode 100644 clutter/clutter/clutter-feature.h create mode 100644 clutter/clutter/clutter-fixed-layout.c create mode 100644 clutter/clutter/clutter-fixed-layout.h create mode 100644 clutter/clutter/clutter-flatten-effect.c create mode 100644 clutter/clutter/clutter-flatten-effect.h create mode 100644 clutter/clutter/clutter-flow-layout.c create mode 100644 clutter/clutter/clutter-flow-layout.h create mode 100644 clutter/clutter/clutter-gesture-action-private.h create mode 100644 clutter/clutter/clutter-gesture-action.c create mode 100644 clutter/clutter/clutter-gesture-action.h create mode 100644 clutter/clutter/clutter-grid-layout.c create mode 100644 clutter/clutter/clutter-grid-layout.h create mode 100644 clutter/clutter/clutter-group.h create mode 100644 clutter/clutter/clutter-id-pool.c create mode 100644 clutter/clutter/clutter-id-pool.h create mode 100644 clutter/clutter/clutter-image.c create mode 100644 clutter/clutter/clutter-image.h create mode 100644 clutter/clutter/clutter-input-device-tool.c create mode 100644 clutter/clutter/clutter-input-device-tool.h create mode 100644 clutter/clutter/clutter-input-device.c create mode 100644 clutter/clutter/clutter-input-device.h create mode 100644 clutter/clutter/clutter-interval.c create mode 100644 clutter/clutter/clutter-interval.h create mode 100644 clutter/clutter/clutter-keyframe-transition.c create mode 100644 clutter/clutter/clutter-keyframe-transition.h create mode 100644 clutter/clutter/clutter-keysyms-table.c create mode 100755 clutter/clutter/clutter-keysyms-update.pl create mode 100644 clutter/clutter/clutter-keysyms.h create mode 100644 clutter/clutter/clutter-layout-manager.c create mode 100644 clutter/clutter/clutter-layout-manager.h create mode 100644 clutter/clutter/clutter-layout-meta.c create mode 100644 clutter/clutter/clutter-layout-meta.h create mode 100644 clutter/clutter/clutter-macros.h create mode 100644 clutter/clutter/clutter-main.c create mode 100644 clutter/clutter/clutter-main.h create mode 100644 clutter/clutter/clutter-marshal.list create mode 100644 clutter/clutter/clutter-master-clock-default.c create mode 100644 clutter/clutter/clutter-master-clock-default.h create mode 100644 clutter/clutter/clutter-master-clock.c create mode 100644 clutter/clutter/clutter-master-clock.h create mode 100644 clutter/clutter/clutter-mutter.h create mode 100644 clutter/clutter/clutter-offscreen-effect-private.h create mode 100644 clutter/clutter/clutter-offscreen-effect.c create mode 100644 clutter/clutter/clutter-offscreen-effect.h create mode 100644 clutter/clutter/clutter-page-turn-effect.c create mode 100644 clutter/clutter/clutter-page-turn-effect.h create mode 100644 clutter/clutter/clutter-paint-node-private.h create mode 100644 clutter/clutter/clutter-paint-node.c create mode 100644 clutter/clutter/clutter-paint-node.h create mode 100644 clutter/clutter/clutter-paint-nodes.c create mode 100644 clutter/clutter/clutter-paint-nodes.h create mode 100644 clutter/clutter/clutter-paint-volume-private.h create mode 100644 clutter/clutter/clutter-paint-volume.c create mode 100644 clutter/clutter/clutter-pan-action.c create mode 100644 clutter/clutter/clutter-pan-action.h create mode 100644 clutter/clutter/clutter-path-constraint.c create mode 100644 clutter/clutter/clutter-path-constraint.h create mode 100644 clutter/clutter/clutter-path.c create mode 100644 clutter/clutter/clutter-path.h create mode 100644 clutter/clutter/clutter-private.h create mode 100644 clutter/clutter/clutter-property-transition.c create mode 100644 clutter/clutter/clutter-property-transition.h create mode 100644 clutter/clutter/clutter-rotate-action.c create mode 100644 clutter/clutter/clutter-rotate-action.h create mode 100644 clutter/clutter/clutter-script-parser.c create mode 100644 clutter/clutter/clutter-script-private.h create mode 100644 clutter/clutter/clutter-script.c create mode 100644 clutter/clutter/clutter-script.h create mode 100644 clutter/clutter/clutter-scriptable.c create mode 100644 clutter/clutter/clutter-scriptable.h create mode 100644 clutter/clutter/clutter-scroll-actor.c create mode 100644 clutter/clutter/clutter-scroll-actor.h create mode 100644 clutter/clutter/clutter-settings-private.h create mode 100644 clutter/clutter/clutter-settings.c create mode 100644 clutter/clutter/clutter-settings.h create mode 100644 clutter/clutter/clutter-shader-effect.c create mode 100644 clutter/clutter/clutter-shader-effect.h create mode 100644 clutter/clutter/clutter-shader-types.c create mode 100644 clutter/clutter/clutter-shader-types.h create mode 100644 clutter/clutter/clutter-snap-constraint.c create mode 100644 clutter/clutter/clutter-snap-constraint.h create mode 100644 clutter/clutter/clutter-stage-manager-private.h create mode 100644 clutter/clutter/clutter-stage-manager.c create mode 100644 clutter/clutter/clutter-stage-manager.h create mode 100644 clutter/clutter/clutter-stage-private.h create mode 100644 clutter/clutter/clutter-stage-view.c create mode 100644 clutter/clutter/clutter-stage-view.h create mode 100644 clutter/clutter/clutter-stage-window.c create mode 100644 clutter/clutter/clutter-stage-window.h create mode 100644 clutter/clutter/clutter-stage.c create mode 100644 clutter/clutter/clutter-stage.h create mode 100644 clutter/clutter/clutter-swipe-action.c create mode 100644 clutter/clutter/clutter-swipe-action.h create mode 100644 clutter/clutter/clutter-tap-action.c create mode 100644 clutter/clutter/clutter-tap-action.h create mode 100644 clutter/clutter/clutter-test-utils.c create mode 100644 clutter/clutter/clutter-test-utils.h create mode 100644 clutter/clutter/clutter-text-buffer.c create mode 100644 clutter/clutter/clutter-text-buffer.h create mode 100644 clutter/clutter/clutter-text.c create mode 100644 clutter/clutter/clutter-text.h create mode 100644 clutter/clutter/clutter-texture.h create mode 100644 clutter/clutter/clutter-timeline.c create mode 100644 clutter/clutter/clutter-timeline.h create mode 100644 clutter/clutter/clutter-transition-group.c create mode 100644 clutter/clutter/clutter-transition-group.h create mode 100644 clutter/clutter/clutter-transition.c create mode 100644 clutter/clutter/clutter-transition.h create mode 100644 clutter/clutter/clutter-types.h create mode 100644 clutter/clutter/clutter-units.c create mode 100644 clutter/clutter/clutter-units.h create mode 100644 clutter/clutter/clutter-util.c create mode 100644 clutter/clutter/clutter-version.h create mode 100644 clutter/clutter/clutter-version.h.in create mode 100644 clutter/clutter/clutter-virtual-input-device.c create mode 100644 clutter/clutter/clutter-virtual-input-device.h create mode 100644 clutter/clutter/clutter-zoom-action.c create mode 100644 clutter/clutter/clutter-zoom-action.h create mode 100644 clutter/clutter/clutter.h create mode 100644 clutter/clutter/cogl/clutter-stage-cogl.c create mode 100644 clutter/clutter/cogl/clutter-stage-cogl.h create mode 100644 clutter/clutter/deprecated/clutter-actor-deprecated.c create mode 100644 clutter/clutter/deprecated/clutter-actor.h create mode 100644 clutter/clutter/deprecated/clutter-alpha.c create mode 100644 clutter/clutter/deprecated/clutter-alpha.h create mode 100644 clutter/clutter/deprecated/clutter-animatable.h create mode 100644 clutter/clutter/deprecated/clutter-animation.c create mode 100644 clutter/clutter/deprecated/clutter-animation.h create mode 100644 clutter/clutter/deprecated/clutter-animator.c create mode 100644 clutter/clutter/deprecated/clutter-animator.h create mode 100644 clutter/clutter/deprecated/clutter-backend.h create mode 100644 clutter/clutter/deprecated/clutter-behaviour-depth.c create mode 100644 clutter/clutter/deprecated/clutter-behaviour-depth.h create mode 100644 clutter/clutter/deprecated/clutter-behaviour-ellipse.c create mode 100644 clutter/clutter/deprecated/clutter-behaviour-ellipse.h create mode 100644 clutter/clutter/deprecated/clutter-behaviour-opacity.c create mode 100644 clutter/clutter/deprecated/clutter-behaviour-opacity.h create mode 100644 clutter/clutter/deprecated/clutter-behaviour-path.c create mode 100644 clutter/clutter/deprecated/clutter-behaviour-path.h create mode 100644 clutter/clutter/deprecated/clutter-behaviour-rotate.c create mode 100644 clutter/clutter/deprecated/clutter-behaviour-rotate.h create mode 100644 clutter/clutter/deprecated/clutter-behaviour-scale.c create mode 100644 clutter/clutter/deprecated/clutter-behaviour-scale.h create mode 100644 clutter/clutter/deprecated/clutter-behaviour.c create mode 100644 clutter/clutter/deprecated/clutter-behaviour.h create mode 100644 clutter/clutter/deprecated/clutter-bin-layout.h create mode 100644 clutter/clutter/deprecated/clutter-box.c create mode 100644 clutter/clutter/deprecated/clutter-box.h create mode 100644 clutter/clutter/deprecated/clutter-cairo-texture.c create mode 100644 clutter/clutter/deprecated/clutter-cairo-texture.h create mode 100644 clutter/clutter/deprecated/clutter-container.h create mode 100644 clutter/clutter/deprecated/clutter-frame-source.c create mode 100644 clutter/clutter/deprecated/clutter-frame-source.h create mode 100644 clutter/clutter/deprecated/clutter-group.c create mode 100644 clutter/clutter/deprecated/clutter-group.h create mode 100644 clutter/clutter/deprecated/clutter-input-device-deprecated.c create mode 100644 clutter/clutter/deprecated/clutter-input-device.h create mode 100644 clutter/clutter/deprecated/clutter-keysyms.h create mode 100644 clutter/clutter/deprecated/clutter-layout-manager-deprecated.c create mode 100644 clutter/clutter/deprecated/clutter-list-model.c create mode 100644 clutter/clutter/deprecated/clutter-list-model.h create mode 100644 clutter/clutter/deprecated/clutter-main.h create mode 100644 clutter/clutter/deprecated/clutter-media.c create mode 100644 clutter/clutter/deprecated/clutter-media.h create mode 100644 clutter/clutter/deprecated/clutter-model-private.h create mode 100644 clutter/clutter/deprecated/clutter-model.c create mode 100644 clutter/clutter/deprecated/clutter-model.h create mode 100644 clutter/clutter/deprecated/clutter-rectangle.c create mode 100644 clutter/clutter/deprecated/clutter-rectangle.h create mode 100644 clutter/clutter/deprecated/clutter-score.c create mode 100644 clutter/clutter/deprecated/clutter-score.h create mode 100644 clutter/clutter/deprecated/clutter-shader.c create mode 100644 clutter/clutter/deprecated/clutter-shader.h create mode 100644 clutter/clutter/deprecated/clutter-stage-manager.h create mode 100644 clutter/clutter/deprecated/clutter-stage.h create mode 100644 clutter/clutter/deprecated/clutter-state.c create mode 100644 clutter/clutter/deprecated/clutter-state.h create mode 100644 clutter/clutter/deprecated/clutter-table-layout.c create mode 100644 clutter/clutter/deprecated/clutter-table-layout.h create mode 100644 clutter/clutter/deprecated/clutter-texture.c create mode 100644 clutter/clutter/deprecated/clutter-texture.h create mode 100644 clutter/clutter/deprecated/clutter-timeline.h create mode 100644 clutter/clutter/deprecated/clutter-timeout-interval.c create mode 100644 clutter/clutter/deprecated/clutter-timeout-interval.h create mode 100644 clutter/clutter/deprecated/clutter-timeout-pool.c create mode 100644 clutter/clutter/deprecated/clutter-timeout-pool.h create mode 100644 clutter/clutter/deprecated/clutter-util.h create mode 100644 clutter/clutter/egl/clutter-backend-eglnative.c create mode 100644 clutter/clutter/egl/clutter-backend-eglnative.h create mode 100644 clutter/clutter/egl/clutter-egl-headers.h create mode 100644 clutter/clutter/egl/clutter-egl.h create mode 100644 clutter/clutter/evdev/clutter-device-manager-evdev.c create mode 100644 clutter/clutter/evdev/clutter-device-manager-evdev.h create mode 100644 clutter/clutter/evdev/clutter-evdev.h create mode 100644 clutter/clutter/evdev/clutter-event-evdev.c create mode 100644 clutter/clutter/evdev/clutter-input-device-evdev.c create mode 100644 clutter/clutter/evdev/clutter-input-device-evdev.h create mode 100644 clutter/clutter/evdev/clutter-input-device-tool-evdev.c create mode 100644 clutter/clutter/evdev/clutter-input-device-tool-evdev.h create mode 100644 clutter/clutter/evdev/clutter-seat-evdev.c create mode 100644 clutter/clutter/evdev/clutter-seat-evdev.h create mode 100644 clutter/clutter/evdev/clutter-virtual-input-device-evdev.c create mode 100644 clutter/clutter/evdev/clutter-virtual-input-device-evdev.h create mode 100644 clutter/clutter/evdev/clutter-xkb-utils.c create mode 100644 clutter/clutter/evdev/clutter-xkb-utils.h create mode 100644 clutter/clutter/mutter-clutter.pc.in create mode 100644 clutter/clutter/wayland/clutter-wayland-compositor.h create mode 100644 clutter/clutter/wayland/clutter-wayland-surface.c create mode 100644 clutter/clutter/wayland/clutter-wayland-surface.h create mode 100644 clutter/clutter/x11/clutter-backend-x11.c create mode 100644 clutter/clutter/x11/clutter-backend-x11.h create mode 100644 clutter/clutter/x11/clutter-device-manager-core-x11.c create mode 100644 clutter/clutter/x11/clutter-device-manager-core-x11.h create mode 100644 clutter/clutter/x11/clutter-device-manager-xi2.c create mode 100644 clutter/clutter/x11/clutter-device-manager-xi2.h create mode 100644 clutter/clutter/x11/clutter-event-x11.c create mode 100644 clutter/clutter/x11/clutter-input-device-core-x11.c create mode 100644 clutter/clutter/x11/clutter-input-device-core-x11.h create mode 100644 clutter/clutter/x11/clutter-input-device-xi2.c create mode 100644 clutter/clutter/x11/clutter-input-device-xi2.h create mode 100644 clutter/clutter/x11/clutter-keymap-x11.c create mode 100644 clutter/clutter/x11/clutter-keymap-x11.h create mode 100644 clutter/clutter/x11/clutter-settings-x11.h create mode 100644 clutter/clutter/x11/clutter-stage-x11.c create mode 100644 clutter/clutter/x11/clutter-stage-x11.h create mode 100644 clutter/clutter/x11/clutter-virtual-input-device-x11.c create mode 100644 clutter/clutter/x11/clutter-virtual-input-device-x11.h create mode 100644 clutter/clutter/x11/clutter-x11-texture-pixmap.c create mode 100644 clutter/clutter/x11/clutter-x11-texture-pixmap.h create mode 100644 clutter/clutter/x11/clutter-x11.h create mode 100644 clutter/clutter/x11/xsettings/xsettings-client.c create mode 100644 clutter/clutter/x11/xsettings/xsettings-client.h create mode 100644 clutter/clutter/x11/xsettings/xsettings-common.c create mode 100644 clutter/clutter/x11/xsettings/xsettings-common.h create mode 100755 clutter/configure create mode 100644 clutter/configure.ac create mode 100644 clutter/examples/Makefile.am create mode 100644 clutter/examples/Makefile.in create mode 100644 clutter/examples/README create mode 100644 clutter/examples/actor-model.c create mode 100644 clutter/examples/basic-actor.c create mode 100644 clutter/examples/bin-layout.c create mode 100644 clutter/examples/box-layout.c create mode 100644 clutter/examples/canvas.c create mode 100644 clutter/examples/constraints.c create mode 100644 clutter/examples/drag-action.c create mode 100644 clutter/examples/drop-action.c create mode 100644 clutter/examples/easing-modes.c create mode 100644 clutter/examples/flow-layout.c create mode 100644 clutter/examples/grid-layout.c create mode 100644 clutter/examples/image-content.c create mode 100644 clutter/examples/layout-manager.c create mode 100644 clutter/examples/pan-action.c create mode 100644 clutter/examples/redhand.png create mode 100644 clutter/examples/rounded-rectangle.c create mode 100644 clutter/examples/scroll-actor.c create mode 100644 clutter/examples/threads.c create mode 100644 clutter/tests/Makefile.am create mode 100644 clutter/tests/Makefile.in create mode 100644 clutter/tests/README create mode 100644 clutter/tests/accessibility/Makefile.am create mode 100644 clutter/tests/accessibility/Makefile.in create mode 100644 clutter/tests/accessibility/cally-atkcomponent-example.c create mode 100644 clutter/tests/accessibility/cally-atkeditabletext-example.c create mode 100644 clutter/tests/accessibility/cally-atkevents-example.c create mode 100644 clutter/tests/accessibility/cally-atktext-example.c create mode 100644 clutter/tests/accessibility/cally-clone-example.c create mode 100644 clutter/tests/accessibility/cally-examples-util.c create mode 100644 clutter/tests/accessibility/cally-examples-util.h create mode 100644 clutter/tests/clutter-1.0.suppressions create mode 100644 clutter/tests/conform/Makefile.am create mode 100644 clutter/tests/conform/Makefile.in create mode 100644 clutter/tests/conform/actor-anchors.c create mode 100644 clutter/tests/conform/actor-destroy.c create mode 100644 clutter/tests/conform/actor-graph.c create mode 100644 clutter/tests/conform/actor-invariants.c create mode 100644 clutter/tests/conform/actor-iter.c create mode 100644 clutter/tests/conform/actor-layout.c create mode 100644 clutter/tests/conform/actor-meta.c create mode 100644 clutter/tests/conform/actor-offscreen-limit-max-size.c create mode 100644 clutter/tests/conform/actor-offscreen-redirect.c create mode 100644 clutter/tests/conform/actor-paint-opacity.c create mode 100644 clutter/tests/conform/actor-pick.c create mode 100644 clutter/tests/conform/actor-shader-effect.c create mode 100644 clutter/tests/conform/actor-size.c create mode 100644 clutter/tests/conform/animator.c create mode 100644 clutter/tests/conform/behaviours.c create mode 100644 clutter/tests/conform/binding-pool.c create mode 100644 clutter/tests/conform/color.c create mode 100644 clutter/tests/conform/events-touch.c create mode 100644 clutter/tests/conform/group.c create mode 100644 clutter/tests/conform/interval.c create mode 100644 clutter/tests/conform/model.c create mode 100644 clutter/tests/conform/rectangle.c create mode 100644 clutter/tests/conform/script-parser.c create mode 100644 clutter/tests/conform/scripts/test-animator-1.json create mode 100644 clutter/tests/conform/scripts/test-animator-2.json create mode 100644 clutter/tests/conform/scripts/test-animator-3.json create mode 100644 clutter/tests/conform/scripts/test-script-animation.json create mode 100644 clutter/tests/conform/scripts/test-script-child.json create mode 100644 clutter/tests/conform/scripts/test-script-implicit-alpha.json create mode 100644 clutter/tests/conform/scripts/test-script-interval.json create mode 100644 clutter/tests/conform/scripts/test-script-layout-property.json create mode 100644 clutter/tests/conform/scripts/test-script-margin.json create mode 100644 clutter/tests/conform/scripts/test-script-model.json create mode 100644 clutter/tests/conform/scripts/test-script-named-object.json create mode 100644 clutter/tests/conform/scripts/test-script-object-property.json create mode 100644 clutter/tests/conform/scripts/test-script-single.json create mode 100644 clutter/tests/conform/scripts/test-script-timeline-markers.json create mode 100644 clutter/tests/conform/scripts/test-state-1.json create mode 100644 clutter/tests/conform/text.c create mode 100644 clutter/tests/conform/texture.c create mode 100644 clutter/tests/conform/units.c create mode 100644 clutter/tests/interactive/Makefile.am create mode 100644 clutter/tests/interactive/Makefile.in create mode 100644 clutter/tests/interactive/redhand.png create mode 100644 clutter/tests/interactive/test-actors.c create mode 100644 clutter/tests/interactive/test-animation.c create mode 100644 clutter/tests/interactive/test-animator.c create mode 100644 clutter/tests/interactive/test-bind-constraint.c create mode 100644 clutter/tests/interactive/test-binding-pool.c create mode 100644 clutter/tests/interactive/test-cairo-clock.c create mode 100644 clutter/tests/interactive/test-cairo-flowers.c create mode 100644 clutter/tests/interactive/test-cogl-multitexture.c create mode 100644 clutter/tests/interactive/test-cogl-offscreen.c create mode 100644 clutter/tests/interactive/test-cogl-point-sprites.c create mode 100644 clutter/tests/interactive/test-cogl-shader-arbfp.c create mode 100644 clutter/tests/interactive/test-cogl-shader-glsl.c create mode 100644 clutter/tests/interactive/test-cogl-tex-convert.c create mode 100644 clutter/tests/interactive/test-cogl-tex-foreign.c create mode 100644 clutter/tests/interactive/test-cogl-tex-polygon.c create mode 100644 clutter/tests/interactive/test-cogl-tex-tile.c create mode 100644 clutter/tests/interactive/test-cogl-vertex-buffer.c create mode 100644 clutter/tests/interactive/test-content.c create mode 100644 clutter/tests/interactive/test-devices.c create mode 100644 clutter/tests/interactive/test-easing.c create mode 100644 clutter/tests/interactive/test-events.c create mode 100644 clutter/tests/interactive/test-fbo.c create mode 100644 clutter/tests/interactive/test-grab.c create mode 100644 clutter/tests/interactive/test-image.c create mode 100644 clutter/tests/interactive/test-keyframe-transition.c create mode 100644 clutter/tests/interactive/test-layout.c create mode 100644 clutter/tests/interactive/test-main.c create mode 100644 clutter/tests/interactive/test-multistage.c create mode 100644 clutter/tests/interactive/test-paint-wrapper.c create mode 100644 clutter/tests/interactive/test-path-constraint.c create mode 100644 clutter/tests/interactive/test-pixmap.c create mode 100644 clutter/tests/interactive/test-rotate-zoom.c create mode 100644 clutter/tests/interactive/test-scale.c create mode 100644 clutter/tests/interactive/test-script-signals.json create mode 100644 clutter/tests/interactive/test-script.c create mode 100644 clutter/tests/interactive/test-script.json create mode 100644 clutter/tests/interactive/test-scrolling.c create mode 100644 clutter/tests/interactive/test-shader-effects.c create mode 100644 clutter/tests/interactive/test-stage-read-pixels.c create mode 100644 clutter/tests/interactive/test-stage-sizing.c create mode 100644 clutter/tests/interactive/test-state-animator.c create mode 100644 clutter/tests/interactive/test-state-script.c create mode 100644 clutter/tests/interactive/test-state.c create mode 100644 clutter/tests/interactive/test-swipe-action.c create mode 100644 clutter/tests/interactive/test-table-layout.c create mode 100644 clutter/tests/interactive/test-text-field.c create mode 100644 clutter/tests/interactive/test-text.c create mode 100644 clutter/tests/interactive/test-texture-async.c create mode 100644 clutter/tests/interactive/test-texture-material.c create mode 100644 clutter/tests/interactive/test-texture-quality.c create mode 100644 clutter/tests/interactive/test-texture-slicing.c create mode 100644 clutter/tests/interactive/test-touch-events.c create mode 100755 clutter/tests/interactive/wrapper.sh.in create mode 100644 clutter/tests/micro-bench/Makefile.am create mode 100644 clutter/tests/micro-bench/Makefile.in create mode 100644 clutter/tests/micro-bench/test-cogl-perf.c create mode 100644 clutter/tests/micro-bench/test-picking.c create mode 100644 clutter/tests/micro-bench/test-random-text.c create mode 100644 clutter/tests/micro-bench/test-text-perf.c create mode 100644 clutter/tests/micro-bench/test-text.c create mode 100644 clutter/tests/performance/Makefile-retrospect create mode 100644 clutter/tests/performance/Makefile-tests create mode 100644 clutter/tests/performance/Makefile.am create mode 100644 clutter/tests/performance/Makefile.in create mode 100755 clutter/tests/performance/create-report.rb create mode 100644 clutter/tests/performance/test-common.h create mode 100644 clutter/tests/performance/test-picking.c create mode 100644 clutter/tests/performance/test-state-hidden.c create mode 100644 clutter/tests/performance/test-state-interactive.c create mode 100644 clutter/tests/performance/test-state-mini.c create mode 100644 clutter/tests/performance/test-state-pick.c create mode 100644 clutter/tests/performance/test-state.c create mode 100644 clutter/tests/performance/test-text-perf.c create mode 100644 cogl/Makefile.am create mode 100644 cogl/Makefile.in create mode 100644 cogl/aclocal.m4 create mode 100644 cogl/build/autotools/Makefile.am.enums create mode 100644 cogl/build/autotools/as-compiler-flag.m4 create mode 100644 cogl/build/autotools/introspection.m4 create mode 100644 cogl/build/autotools/libtool.m4 create mode 100644 cogl/build/autotools/ltoptions.m4 create mode 100644 cogl/build/autotools/ltsugar.m4 create mode 100644 cogl/build/autotools/ltversion.m4 create mode 100644 cogl/build/autotools/lt~obsolete.m4 create mode 100755 cogl/build/compile create mode 100755 cogl/build/config.guess create mode 100755 cogl/build/config.sub create mode 100755 cogl/build/depcomp create mode 100755 cogl/build/install-sh create mode 100644 cogl/build/ltmain.sh create mode 100755 cogl/build/missing create mode 100644 cogl/cogl-config.h.in create mode 100644 cogl/cogl-gles2/GLES2/gl2.h create mode 100644 cogl/cogl-gles2/GLES2/gl2ext.h create mode 100644 cogl/cogl-gles2/GLES2/gl2platform.h create mode 100644 cogl/cogl-gles2/Makefile.am create mode 100644 cogl/cogl-gles2/Makefile.in create mode 100644 cogl/cogl-gles2/cogl-gles2-api.c create mode 100644 cogl/cogl-gles2/mutter-cogl-gles2-1.0.pc.in create mode 100644 cogl/cogl-mutter-config.h.in create mode 100644 cogl/cogl-pango/Makefile.am create mode 100644 cogl/cogl-pango/Makefile.in create mode 100644 cogl/cogl-pango/cogl-pango-display-list.c create mode 100644 cogl/cogl-pango/cogl-pango-display-list.h create mode 100644 cogl/cogl-pango/cogl-pango-fontmap.c create mode 100644 cogl/cogl-pango/cogl-pango-glyph-cache.c create mode 100644 cogl/cogl-pango/cogl-pango-glyph-cache.h create mode 100644 cogl/cogl-pango/cogl-pango-pipeline-cache.c create mode 100644 cogl/cogl-pango/cogl-pango-pipeline-cache.h create mode 100644 cogl/cogl-pango/cogl-pango-private.h create mode 100644 cogl/cogl-pango/cogl-pango-render.c create mode 100644 cogl/cogl-pango/cogl-pango.h create mode 100644 cogl/cogl-pango/cogl-pango.symbols create mode 100644 cogl/cogl-pango/mutter-cogl-pango-1.0.pc.in create mode 100644 cogl/cogl-path/Makefile.am create mode 100644 cogl/cogl-path/Makefile.in create mode 100644 cogl/cogl-path/cogl-path-enum-types.c.in create mode 100644 cogl/cogl-path/cogl-path-enum-types.h.in create mode 100644 cogl/cogl-path/cogl-path-functions.h create mode 100644 cogl/cogl-path/cogl-path-private.h create mode 100644 cogl/cogl-path/cogl-path-types.h create mode 100644 cogl/cogl-path/cogl-path.c create mode 100644 cogl/cogl-path/cogl-path.h create mode 100644 cogl/cogl-path/cogl-path.symbols create mode 100644 cogl/cogl-path/mutter-cogl-path-1.0.pc.in create mode 100644 cogl/cogl-path/tesselator/GL/glu.h create mode 100644 cogl/cogl-path/tesselator/README create mode 100644 cogl/cogl-path/tesselator/dict-list.h create mode 100644 cogl/cogl-path/tesselator/dict.c create mode 100644 cogl/cogl-path/tesselator/dict.h create mode 100644 cogl/cogl-path/tesselator/geom.c create mode 100644 cogl/cogl-path/tesselator/geom.h create mode 100644 cogl/cogl-path/tesselator/gluos.h create mode 100644 cogl/cogl-path/tesselator/memalloc.h create mode 100644 cogl/cogl-path/tesselator/mesh.c create mode 100644 cogl/cogl-path/tesselator/mesh.h create mode 100644 cogl/cogl-path/tesselator/normal.c create mode 100644 cogl/cogl-path/tesselator/normal.h create mode 100644 cogl/cogl-path/tesselator/priorityq-heap.c create mode 100644 cogl/cogl-path/tesselator/priorityq-heap.h create mode 100644 cogl/cogl-path/tesselator/priorityq-sort.h create mode 100644 cogl/cogl-path/tesselator/priorityq.c create mode 100644 cogl/cogl-path/tesselator/priorityq.h create mode 100644 cogl/cogl-path/tesselator/render.c create mode 100644 cogl/cogl-path/tesselator/render.h create mode 100644 cogl/cogl-path/tesselator/sweep.c create mode 100644 cogl/cogl-path/tesselator/sweep.h create mode 100644 cogl/cogl-path/tesselator/tess.c create mode 100644 cogl/cogl-path/tesselator/tess.h create mode 100644 cogl/cogl-path/tesselator/tesselator.h create mode 100644 cogl/cogl-path/tesselator/tessmono.c create mode 100644 cogl/cogl-path/tesselator/tessmono.h create mode 100644 cogl/cogl/Makefile.am create mode 100644 cogl/cogl/Makefile.in create mode 100644 cogl/cogl/cogl-atlas-texture-private.h create mode 100644 cogl/cogl/cogl-atlas-texture.c create mode 100644 cogl/cogl/cogl-atlas-texture.h create mode 100644 cogl/cogl/cogl-atlas.c create mode 100644 cogl/cogl/cogl-atlas.h create mode 100644 cogl/cogl/cogl-attribute-buffer-private.h create mode 100644 cogl/cogl/cogl-attribute-buffer.c create mode 100644 cogl/cogl/cogl-attribute-buffer.h create mode 100644 cogl/cogl/cogl-attribute-private.h create mode 100644 cogl/cogl/cogl-attribute.c create mode 100644 cogl/cogl/cogl-attribute.h create mode 100644 cogl/cogl/cogl-bitmap-conversion.c create mode 100644 cogl/cogl/cogl-bitmap-packing.h create mode 100644 cogl/cogl/cogl-bitmap-pixbuf.c create mode 100644 cogl/cogl/cogl-bitmap-private.h create mode 100644 cogl/cogl/cogl-bitmap.c create mode 100644 cogl/cogl/cogl-bitmap.h create mode 100644 cogl/cogl/cogl-bitmask.c create mode 100644 cogl/cogl/cogl-bitmask.h create mode 100644 cogl/cogl/cogl-blend-string.c create mode 100644 cogl/cogl/cogl-blend-string.h create mode 100644 cogl/cogl/cogl-blit.c create mode 100644 cogl/cogl/cogl-blit.h create mode 100644 cogl/cogl/cogl-boxed-value.c create mode 100644 cogl/cogl/cogl-boxed-value.h create mode 100644 cogl/cogl/cogl-buffer-private.h create mode 100644 cogl/cogl/cogl-buffer.c create mode 100644 cogl/cogl/cogl-buffer.h create mode 100644 cogl/cogl/cogl-clip-stack.c create mode 100644 cogl/cogl/cogl-clip-stack.h create mode 100644 cogl/cogl/cogl-closure-list-private.h create mode 100644 cogl/cogl/cogl-closure-list.c create mode 100644 cogl/cogl/cogl-color-private.h create mode 100644 cogl/cogl/cogl-color.c create mode 100644 cogl/cogl/cogl-color.h create mode 100644 cogl/cogl/cogl-config-private.h create mode 100644 cogl/cogl/cogl-config.c create mode 100644 cogl/cogl/cogl-context-private.h create mode 100644 cogl/cogl/cogl-context.c create mode 100644 cogl/cogl/cogl-context.h create mode 100644 cogl/cogl/cogl-debug-options.h create mode 100644 cogl/cogl/cogl-debug.c create mode 100644 cogl/cogl/cogl-debug.h create mode 100644 cogl/cogl/cogl-defines.h.in create mode 100644 cogl/cogl/cogl-deprecated.h create mode 100644 cogl/cogl/cogl-depth-state-private.h create mode 100644 cogl/cogl/cogl-depth-state.c create mode 100644 cogl/cogl/cogl-depth-state.h create mode 100644 cogl/cogl/cogl-display-private.h create mode 100644 cogl/cogl/cogl-display.c create mode 100644 cogl/cogl/cogl-display.h create mode 100644 cogl/cogl/cogl-driver.h create mode 100644 cogl/cogl/cogl-egl-defines.h.in create mode 100644 cogl/cogl/cogl-egl-private.h create mode 100644 cogl/cogl/cogl-egl.h create mode 100644 cogl/cogl/cogl-error-private.h create mode 100644 cogl/cogl/cogl-error.c create mode 100644 cogl/cogl/cogl-error.h create mode 100644 cogl/cogl/cogl-euler.c create mode 100644 cogl/cogl/cogl-euler.h create mode 100644 cogl/cogl/cogl-feature-private.c create mode 100644 cogl/cogl/cogl-feature-private.h create mode 100644 cogl/cogl/cogl-fence-private.h create mode 100644 cogl/cogl/cogl-fence.c create mode 100644 cogl/cogl/cogl-fence.h create mode 100644 cogl/cogl/cogl-flags.h create mode 100644 cogl/cogl/cogl-frame-info-private.h create mode 100644 cogl/cogl/cogl-frame-info.c create mode 100644 cogl/cogl/cogl-frame-info.h create mode 100644 cogl/cogl/cogl-framebuffer-private.h create mode 100644 cogl/cogl/cogl-framebuffer.c create mode 100644 cogl/cogl/cogl-framebuffer.h create mode 100644 cogl/cogl/cogl-gl-header.h.in create mode 100644 cogl/cogl/cogl-gles2-context-private.h create mode 100644 cogl/cogl/cogl-gles2-context.c create mode 100644 cogl/cogl/cogl-gles2-types.h create mode 100644 cogl/cogl/cogl-gles2.h create mode 100644 cogl/cogl/cogl-glib-source.c create mode 100644 cogl/cogl/cogl-glib-source.h create mode 100644 cogl/cogl/cogl-glsl-shader-boilerplate.h create mode 100644 cogl/cogl/cogl-glsl-shader-private.h create mode 100644 cogl/cogl/cogl-glsl-shader.c create mode 100644 cogl/cogl/cogl-glx-display-private.h create mode 100644 cogl/cogl/cogl-glx-renderer-private.h create mode 100644 cogl/cogl/cogl-glx.h create mode 100644 cogl/cogl/cogl-gpu-info-private.h create mode 100644 cogl/cogl/cogl-gpu-info.c create mode 100644 cogl/cogl/cogl-gtype-private.h create mode 100644 cogl/cogl/cogl-gtype.c create mode 100644 cogl/cogl/cogl-i18n-private.h create mode 100644 cogl/cogl/cogl-index-buffer-private.h create mode 100644 cogl/cogl/cogl-index-buffer.c create mode 100644 cogl/cogl/cogl-index-buffer.h create mode 100644 cogl/cogl/cogl-indices-private.h create mode 100644 cogl/cogl/cogl-indices.c create mode 100644 cogl/cogl/cogl-indices.h create mode 100644 cogl/cogl/cogl-journal-private.h create mode 100644 cogl/cogl/cogl-journal.c create mode 100644 cogl/cogl/cogl-list.c create mode 100644 cogl/cogl/cogl-list.h create mode 100644 cogl/cogl/cogl-macros.h create mode 100644 cogl/cogl/cogl-magazine-private.h create mode 100644 cogl/cogl/cogl-magazine.c create mode 100644 cogl/cogl/cogl-matrix-private.h create mode 100644 cogl/cogl/cogl-matrix-stack-private.h create mode 100644 cogl/cogl/cogl-matrix-stack.c create mode 100644 cogl/cogl/cogl-matrix-stack.h create mode 100644 cogl/cogl/cogl-matrix.c create mode 100644 cogl/cogl/cogl-matrix.h create mode 100644 cogl/cogl/cogl-memory-stack-private.h create mode 100644 cogl/cogl/cogl-memory-stack.c create mode 100644 cogl/cogl/cogl-meta-texture.c create mode 100644 cogl/cogl/cogl-meta-texture.h create mode 100644 cogl/cogl/cogl-mutter.h create mode 100644 cogl/cogl/cogl-node-private.h create mode 100644 cogl/cogl/cogl-node.c create mode 100644 cogl/cogl/cogl-object-private.h create mode 100644 cogl/cogl/cogl-object.c create mode 100644 cogl/cogl/cogl-object.h create mode 100644 cogl/cogl/cogl-offscreen.h create mode 100644 cogl/cogl/cogl-onscreen-private.h create mode 100644 cogl/cogl/cogl-onscreen-template-private.h create mode 100644 cogl/cogl/cogl-onscreen-template.c create mode 100644 cogl/cogl/cogl-onscreen-template.h create mode 100644 cogl/cogl/cogl-onscreen.c create mode 100644 cogl/cogl/cogl-onscreen.h create mode 100644 cogl/cogl/cogl-output-private.h create mode 100644 cogl/cogl/cogl-output.c create mode 100644 cogl/cogl/cogl-output.h create mode 100644 cogl/cogl/cogl-pango.h create mode 100644 cogl/cogl/cogl-pipeline-cache.c create mode 100644 cogl/cogl/cogl-pipeline-cache.h create mode 100644 cogl/cogl/cogl-pipeline-debug.c create mode 100644 cogl/cogl/cogl-pipeline-hash-table.c create mode 100644 cogl/cogl/cogl-pipeline-hash-table.h create mode 100644 cogl/cogl/cogl-pipeline-layer-private.h create mode 100644 cogl/cogl/cogl-pipeline-layer-state-private.h create mode 100644 cogl/cogl/cogl-pipeline-layer-state.c create mode 100644 cogl/cogl/cogl-pipeline-layer-state.h create mode 100644 cogl/cogl/cogl-pipeline-layer.c create mode 100644 cogl/cogl/cogl-pipeline-private.h create mode 100644 cogl/cogl/cogl-pipeline-snippet-private.h create mode 100644 cogl/cogl/cogl-pipeline-snippet.c create mode 100644 cogl/cogl/cogl-pipeline-state-private.h create mode 100644 cogl/cogl/cogl-pipeline-state.c create mode 100644 cogl/cogl/cogl-pipeline-state.h create mode 100644 cogl/cogl/cogl-pipeline.c create mode 100644 cogl/cogl/cogl-pipeline.h create mode 100644 cogl/cogl/cogl-pixel-buffer-private.h create mode 100644 cogl/cogl/cogl-pixel-buffer.c create mode 100644 cogl/cogl/cogl-pixel-buffer.h create mode 100644 cogl/cogl/cogl-point-in-poly-private.h create mode 100644 cogl/cogl/cogl-point-in-poly.c create mode 100644 cogl/cogl/cogl-poll-private.h create mode 100644 cogl/cogl/cogl-poll.c create mode 100644 cogl/cogl/cogl-poll.h create mode 100644 cogl/cogl/cogl-primitive-private.h create mode 100644 cogl/cogl/cogl-primitive-texture.c create mode 100644 cogl/cogl/cogl-primitive-texture.h create mode 100644 cogl/cogl/cogl-primitive.c create mode 100644 cogl/cogl/cogl-primitive.h create mode 100644 cogl/cogl/cogl-primitives-private.h create mode 100644 cogl/cogl/cogl-primitives.c create mode 100644 cogl/cogl/cogl-primitives.h create mode 100644 cogl/cogl/cogl-private.h create mode 100644 cogl/cogl/cogl-profile.c create mode 100644 cogl/cogl/cogl-profile.h create mode 100644 cogl/cogl/cogl-quaternion-private.h create mode 100644 cogl/cogl/cogl-quaternion.c create mode 100644 cogl/cogl/cogl-quaternion.h create mode 100644 cogl/cogl/cogl-rectangle-map.c create mode 100644 cogl/cogl/cogl-rectangle-map.h create mode 100644 cogl/cogl/cogl-renderer-private.h create mode 100644 cogl/cogl/cogl-renderer.c create mode 100644 cogl/cogl/cogl-renderer.h create mode 100644 cogl/cogl/cogl-sampler-cache-private.h create mode 100644 cogl/cogl/cogl-sampler-cache.c create mode 100644 cogl/cogl/cogl-snippet-private.h create mode 100644 cogl/cogl/cogl-snippet.c create mode 100644 cogl/cogl/cogl-snippet.h create mode 100644 cogl/cogl/cogl-spans.c create mode 100644 cogl/cogl/cogl-spans.h create mode 100644 cogl/cogl/cogl-sub-texture-private.h create mode 100644 cogl/cogl/cogl-sub-texture.c create mode 100644 cogl/cogl/cogl-sub-texture.h create mode 100644 cogl/cogl/cogl-swap-chain-private.h create mode 100644 cogl/cogl/cogl-swap-chain.c create mode 100644 cogl/cogl/cogl-swap-chain.h create mode 100644 cogl/cogl/cogl-texture-2d-gl.h create mode 100644 cogl/cogl/cogl-texture-2d-private.h create mode 100644 cogl/cogl/cogl-texture-2d-sliced-private.h create mode 100644 cogl/cogl/cogl-texture-2d-sliced.c create mode 100644 cogl/cogl/cogl-texture-2d-sliced.h create mode 100644 cogl/cogl/cogl-texture-2d.c create mode 100644 cogl/cogl/cogl-texture-2d.h create mode 100644 cogl/cogl/cogl-texture-3d-private.h create mode 100644 cogl/cogl/cogl-texture-3d.c create mode 100644 cogl/cogl/cogl-texture-3d.h create mode 100644 cogl/cogl/cogl-texture-driver.h create mode 100644 cogl/cogl/cogl-texture-private.h create mode 100644 cogl/cogl/cogl-texture-rectangle-private.h create mode 100644 cogl/cogl/cogl-texture-rectangle.c create mode 100644 cogl/cogl/cogl-texture-rectangle.h create mode 100644 cogl/cogl/cogl-texture.c create mode 100644 cogl/cogl/cogl-texture.h create mode 100644 cogl/cogl/cogl-types.h create mode 100644 cogl/cogl/cogl-util.c create mode 100644 cogl/cogl/cogl-util.h create mode 100644 cogl/cogl/cogl-vector.c create mode 100644 cogl/cogl/cogl-vector.h create mode 100644 cogl/cogl/cogl-version.h create mode 100644 cogl/cogl/cogl-wayland-server.h create mode 100644 cogl/cogl/cogl-x11-renderer-private.h create mode 100644 cogl/cogl/cogl-xlib-private.h create mode 100644 cogl/cogl/cogl-xlib-renderer-private.h create mode 100644 cogl/cogl/cogl-xlib-renderer.c create mode 100644 cogl/cogl/cogl-xlib-renderer.h create mode 100644 cogl/cogl/cogl-xlib.c create mode 100644 cogl/cogl/cogl-xlib.h create mode 100644 cogl/cogl/cogl.c create mode 100644 cogl/cogl/cogl.h create mode 100644 cogl/cogl/cogl.symbols create mode 100644 cogl/cogl/cogl1-context.h create mode 100644 cogl/cogl/deprecated/cogl-auto-texture.c create mode 100644 cogl/cogl/deprecated/cogl-auto-texture.h create mode 100644 cogl/cogl/deprecated/cogl-clutter-xlib.h create mode 100644 cogl/cogl/deprecated/cogl-clutter.c create mode 100644 cogl/cogl/deprecated/cogl-clutter.h create mode 100644 cogl/cogl/deprecated/cogl-framebuffer-deprecated.c create mode 100644 cogl/cogl/deprecated/cogl-framebuffer-deprecated.h create mode 100644 cogl/cogl/deprecated/cogl-material-compat.c create mode 100644 cogl/cogl/deprecated/cogl-material-compat.h create mode 100644 cogl/cogl/deprecated/cogl-program-private.h create mode 100644 cogl/cogl/deprecated/cogl-program.c create mode 100644 cogl/cogl/deprecated/cogl-shader-private.h create mode 100644 cogl/cogl/deprecated/cogl-shader.c create mode 100644 cogl/cogl/deprecated/cogl-shader.h create mode 100644 cogl/cogl/deprecated/cogl-type-casts.h create mode 100644 cogl/cogl/deprecated/cogl-vertex-buffer-private.h create mode 100644 cogl/cogl/deprecated/cogl-vertex-buffer.c create mode 100644 cogl/cogl/deprecated/cogl-vertex-buffer.h create mode 100644 cogl/cogl/driver/gl/cogl-attribute-gl-private.h create mode 100644 cogl/cogl/driver/gl/cogl-attribute-gl.c create mode 100644 cogl/cogl/driver/gl/cogl-buffer-gl-private.h create mode 100644 cogl/cogl/driver/gl/cogl-buffer-gl.c create mode 100644 cogl/cogl/driver/gl/cogl-clip-stack-gl-private.h create mode 100644 cogl/cogl/driver/gl/cogl-clip-stack-gl.c create mode 100644 cogl/cogl/driver/gl/cogl-framebuffer-gl-private.h create mode 100644 cogl/cogl/driver/gl/cogl-framebuffer-gl.c create mode 100644 cogl/cogl/driver/gl/cogl-pipeline-fragend-fixed-private.h create mode 100644 cogl/cogl/driver/gl/cogl-pipeline-fragend-fixed.c create mode 100644 cogl/cogl/driver/gl/cogl-pipeline-fragend-glsl-private.h create mode 100644 cogl/cogl/driver/gl/cogl-pipeline-fragend-glsl.c create mode 100644 cogl/cogl/driver/gl/cogl-pipeline-opengl-private.h create mode 100644 cogl/cogl/driver/gl/cogl-pipeline-opengl.c create mode 100644 cogl/cogl/driver/gl/cogl-pipeline-progend-fixed-private.h create mode 100644 cogl/cogl/driver/gl/cogl-pipeline-progend-fixed.c create mode 100644 cogl/cogl/driver/gl/cogl-pipeline-progend-glsl-private.h create mode 100644 cogl/cogl/driver/gl/cogl-pipeline-progend-glsl.c create mode 100644 cogl/cogl/driver/gl/cogl-pipeline-vertend-fixed-private.h create mode 100644 cogl/cogl/driver/gl/cogl-pipeline-vertend-fixed.c create mode 100644 cogl/cogl/driver/gl/cogl-pipeline-vertend-glsl-private.h create mode 100644 cogl/cogl/driver/gl/cogl-pipeline-vertend-glsl.c create mode 100644 cogl/cogl/driver/gl/cogl-texture-2d-gl-private.h create mode 100644 cogl/cogl/driver/gl/cogl-texture-2d-gl.c create mode 100644 cogl/cogl/driver/gl/cogl-texture-gl-private.h create mode 100644 cogl/cogl/driver/gl/cogl-texture-gl.c create mode 100644 cogl/cogl/driver/gl/cogl-util-gl-private.h create mode 100644 cogl/cogl/driver/gl/cogl-util-gl.c create mode 100644 cogl/cogl/driver/gl/gl/cogl-driver-gl.c create mode 100644 cogl/cogl/driver/gl/gl/cogl-pipeline-fragend-arbfp-private.h create mode 100644 cogl/cogl/driver/gl/gl/cogl-pipeline-fragend-arbfp.c create mode 100644 cogl/cogl/driver/gl/gl/cogl-pipeline-progend-fixed-arbfp-private.h create mode 100644 cogl/cogl/driver/gl/gl/cogl-pipeline-progend-fixed-arbfp.c create mode 100644 cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c create mode 100644 cogl/cogl/driver/gl/gles/cogl-driver-gles.c create mode 100644 cogl/cogl/driver/gl/gles/cogl-texture-driver-gles.c create mode 100644 cogl/cogl/driver/nop/cogl-attribute-nop-private.h create mode 100644 cogl/cogl/driver/nop/cogl-attribute-nop.c create mode 100644 cogl/cogl/driver/nop/cogl-clip-stack-nop-private.h create mode 100644 cogl/cogl/driver/nop/cogl-clip-stack-nop.c create mode 100644 cogl/cogl/driver/nop/cogl-driver-nop.c create mode 100644 cogl/cogl/driver/nop/cogl-framebuffer-nop-private.h create mode 100644 cogl/cogl/driver/nop/cogl-framebuffer-nop.c create mode 100644 cogl/cogl/driver/nop/cogl-texture-2d-nop-private.h create mode 100644 cogl/cogl/driver/nop/cogl-texture-2d-nop.c create mode 100644 cogl/cogl/gl-prototypes/cogl-all-functions.h create mode 100644 cogl/cogl/gl-prototypes/cogl-core-functions.h create mode 100644 cogl/cogl/gl-prototypes/cogl-fixed-functions.h create mode 100644 cogl/cogl/gl-prototypes/cogl-gles1-functions.h create mode 100644 cogl/cogl/gl-prototypes/cogl-gles2-functions.h create mode 100644 cogl/cogl/gl-prototypes/cogl-glsl-functions.h create mode 100644 cogl/cogl/gl-prototypes/cogl-in-gles-core-functions.h create mode 100644 cogl/cogl/gl-prototypes/cogl-in-gles1-core-functions.h create mode 100644 cogl/cogl/gl-prototypes/cogl-in-gles2-core-functions.h create mode 100644 cogl/cogl/mutter-cogl-1.0.pc.in create mode 100644 cogl/cogl/winsys/cogl-texture-pixmap-x11-private.h create mode 100644 cogl/cogl/winsys/cogl-texture-pixmap-x11.c create mode 100644 cogl/cogl/winsys/cogl-texture-pixmap-x11.h create mode 100644 cogl/cogl/winsys/cogl-winsys-egl-feature-functions.h create mode 100644 cogl/cogl/winsys/cogl-winsys-egl-private.h create mode 100644 cogl/cogl/winsys/cogl-winsys-egl-x11-private.h create mode 100644 cogl/cogl/winsys/cogl-winsys-egl-x11.c create mode 100644 cogl/cogl/winsys/cogl-winsys-egl.c create mode 100644 cogl/cogl/winsys/cogl-winsys-glx-feature-functions.h create mode 100644 cogl/cogl/winsys/cogl-winsys-glx-private.h create mode 100644 cogl/cogl/winsys/cogl-winsys-glx.c create mode 100644 cogl/cogl/winsys/cogl-winsys-private.h create mode 100644 cogl/cogl/winsys/cogl-winsys-stub-private.h create mode 100644 cogl/cogl/winsys/cogl-winsys-stub.c create mode 100644 cogl/cogl/winsys/cogl-winsys.c create mode 100644 cogl/config-custom.h create mode 100755 cogl/configure create mode 100644 cogl/configure.ac create mode 100644 cogl/test-fixtures/Makefile.am create mode 100644 cogl/test-fixtures/Makefile.in create mode 100644 cogl/test-fixtures/test-unit.h create mode 100644 cogl/test-fixtures/test-utils.c create mode 100644 cogl/test-fixtures/test-utils.h create mode 100644 cogl/tests/Makefile.am create mode 100644 cogl/tests/Makefile.in create mode 100644 cogl/tests/README create mode 100644 cogl/tests/config.env.in create mode 100644 cogl/tests/conform/Makefile.am create mode 100644 cogl/tests/conform/Makefile.in create mode 100644 cogl/tests/conform/test-alpha-test.c create mode 100644 cogl/tests/conform/test-alpha-textures.c create mode 100644 cogl/tests/conform/test-atlas-migration.c create mode 100644 cogl/tests/conform/test-backface-culling.c create mode 100644 cogl/tests/conform/test-blend-strings.c create mode 100644 cogl/tests/conform/test-blend.c create mode 100644 cogl/tests/conform/test-color-hsl.c create mode 100644 cogl/tests/conform/test-color-mask.c create mode 100644 cogl/tests/conform/test-conform-main.c create mode 100644 cogl/tests/conform/test-copy-replace-texture.c create mode 100644 cogl/tests/conform/test-custom-attributes.c create mode 100644 cogl/tests/conform/test-depth-test.c create mode 100644 cogl/tests/conform/test-euler-quaternion.c create mode 100644 cogl/tests/conform/test-fence.c create mode 100644 cogl/tests/conform/test-framebuffer-get-bits.c create mode 100644 cogl/tests/conform/test-gles2-context.c create mode 100644 cogl/tests/conform/test-just-vertex-shader.c create mode 100644 cogl/tests/conform/test-layer-remove.c create mode 100644 cogl/tests/conform/test-map-buffer-range.c create mode 100644 cogl/tests/conform/test-no-gl-header.c create mode 100644 cogl/tests/conform/test-npot-texture.c create mode 100644 cogl/tests/conform/test-offscreen.c create mode 100644 cogl/tests/conform/test-path-clip.c create mode 100644 cogl/tests/conform/test-path.c create mode 100644 cogl/tests/conform/test-pipeline-cache-unrefs-texture.c create mode 100644 cogl/tests/conform/test-pipeline-shader-state.c create mode 100644 cogl/tests/conform/test-pipeline-uniforms.c create mode 100644 cogl/tests/conform/test-pipeline-user-matrix.c create mode 100644 cogl/tests/conform/test-pixel-buffer.c create mode 100644 cogl/tests/conform/test-point-size-attribute.c create mode 100644 cogl/tests/conform/test-point-size.c create mode 100644 cogl/tests/conform/test-point-sprite.c create mode 100644 cogl/tests/conform/test-premult.c create mode 100644 cogl/tests/conform/test-primitive-and-journal.c create mode 100644 cogl/tests/conform/test-primitive.c create mode 100644 cogl/tests/conform/test-read-texture-formats.c create mode 100644 cogl/tests/conform/test-snippets.c create mode 100644 cogl/tests/conform/test-sparse-pipeline.c create mode 100644 cogl/tests/conform/test-sub-texture.c create mode 100644 cogl/tests/conform/test-texture-3d.c create mode 100644 cogl/tests/conform/test-texture-get-set-data.c create mode 100644 cogl/tests/conform/test-texture-no-allocate.c create mode 100644 cogl/tests/conform/test-texture-rg.c create mode 100644 cogl/tests/conform/test-version.c create mode 100644 cogl/tests/conform/test-wrap-modes.c create mode 100644 cogl/tests/conform/test-wrap-rectangle-textures.c create mode 100644 cogl/tests/conform/test-write-texture-formats.c create mode 100644 cogl/tests/data/Makefile.am create mode 100644 cogl/tests/data/Makefile.in create mode 100644 cogl/tests/data/valgrind.suppressions create mode 100644 cogl/tests/micro-perf/Makefile.am create mode 100644 cogl/tests/micro-perf/Makefile.in create mode 100644 cogl/tests/micro-perf/test-journal.c create mode 100755 cogl/tests/run-tests.sh create mode 100755 cogl/tests/test-launcher.sh create mode 100644 cogl/tests/unit/Makefile.am create mode 100644 cogl/tests/unit/Makefile.in create mode 100644 cogl/tests/unit/test-unit-main.c create mode 100644 config.h.in create mode 100755 configure create mode 100644 configure.ac create mode 100644 data/50-mutter-navigation.xml create mode 100644 data/50-mutter-system.xml create mode 100644 data/50-mutter-windows.xml create mode 100644 data/Makefile.am create mode 100644 data/Makefile.in create mode 100644 data/mutter-schemas.convert create mode 100644 data/mutter.desktop.in create mode 100644 data/org.gnome.mutter.gschema.xml.in create mode 100644 data/org.gnome.mutter.wayland.gschema.xml.in create mode 100644 doc/Makefile.am create mode 100644 doc/Makefile.in create mode 100644 doc/code-overview.txt create mode 100644 doc/dialogs.txt create mode 100644 doc/how-to-get-focus-right.txt create mode 100644 doc/man/Makefile.am create mode 100644 doc/man/Makefile.in create mode 100644 doc/man/mutter.1 create mode 100644 doc/rationales.txt create mode 100644 m4/gettext.m4 create mode 100644 m4/iconv.m4 create mode 100644 m4/intlmacosx.m4 create mode 100644 m4/lib-ld.m4 create mode 100644 m4/lib-link.m4 create mode 100644 m4/lib-prefix.m4 create mode 100644 m4/libtool.m4 create mode 100644 m4/ltoptions.m4 create mode 100644 m4/ltsugar.m4 create mode 100644 m4/ltversion.m4 create mode 100644 m4/lt~obsolete.m4 create mode 100644 m4/nls.m4 create mode 100644 m4/po.m4 create mode 100644 m4/progtest.m4 create mode 100644 po/ChangeLog create mode 100644 po/LINGUAS create mode 100644 po/Makefile.in.in create mode 100644 po/Makevars create mode 100644 po/POTFILES.in create mode 100644 po/Rules-quot create mode 100644 po/am.gmo create mode 100644 po/am.po create mode 100644 po/ar.gmo create mode 100644 po/ar.po create mode 100644 po/as.gmo create mode 100644 po/as.po create mode 100644 po/ast.gmo create mode 100644 po/ast.po create mode 100644 po/az.gmo create mode 100644 po/az.po create mode 100644 po/be.gmo create mode 100644 po/be.po create mode 100644 po/be@latin.gmo create mode 100644 po/be@latin.po create mode 100644 po/bg.gmo create mode 100644 po/bg.po create mode 100644 po/bn.gmo create mode 100644 po/bn.po create mode 100644 po/bn_IN.gmo create mode 100644 po/bn_IN.po create mode 100644 po/boldquot.sed create mode 100644 po/br.gmo create mode 100644 po/br.po create mode 100644 po/bs.gmo create mode 100644 po/bs.po create mode 100644 po/ca.gmo create mode 100644 po/ca.po create mode 100644 po/ca@valencia.gmo create mode 100644 po/ca@valencia.po create mode 100644 po/cs.gmo create mode 100644 po/cs.po create mode 100644 po/cy.gmo create mode 100644 po/cy.po create mode 100644 po/da.gmo create mode 100644 po/da.po create mode 100644 po/de.gmo create mode 100644 po/de.po create mode 100644 po/dz.gmo create mode 100644 po/dz.po create mode 100644 po/el.gmo create mode 100644 po/el.po create mode 100644 po/en@boldquot.header create mode 100644 po/en@quot.header create mode 100644 po/en_CA.gmo create mode 100644 po/en_CA.po create mode 100644 po/en_GB.gmo create mode 100644 po/en_GB.po create mode 100644 po/eo.gmo create mode 100644 po/eo.po create mode 100644 po/es.gmo create mode 100644 po/es.po create mode 100644 po/et.gmo create mode 100644 po/et.po create mode 100644 po/eu.gmo create mode 100644 po/eu.po create mode 100644 po/fa.gmo create mode 100644 po/fa.po create mode 100644 po/fi.gmo create mode 100644 po/fi.po create mode 100644 po/fr.gmo create mode 100644 po/fr.po create mode 100644 po/fur.gmo create mode 100644 po/fur.po create mode 100644 po/ga.gmo create mode 100644 po/ga.po create mode 100644 po/gd.gmo create mode 100644 po/gd.po create mode 100644 po/gl.gmo create mode 100644 po/gl.po create mode 100644 po/gu.gmo create mode 100644 po/gu.po create mode 100644 po/ha.gmo create mode 100644 po/ha.po create mode 100644 po/he.gmo create mode 100644 po/he.po create mode 100644 po/hi.gmo create mode 100644 po/hi.po create mode 100644 po/hr.gmo create mode 100644 po/hr.po create mode 100644 po/hu.gmo create mode 100644 po/hu.po create mode 100644 po/hy.gmo create mode 100644 po/hy.po create mode 100644 po/id.gmo create mode 100644 po/id.po create mode 100644 po/ig.gmo create mode 100644 po/ig.po create mode 100644 po/insert-header.sin create mode 100644 po/is.gmo create mode 100644 po/is.po create mode 100644 po/it.gmo create mode 100644 po/it.po create mode 100644 po/ja.gmo create mode 100644 po/ja.po create mode 100644 po/ka.gmo create mode 100644 po/ka.po create mode 100644 po/kk.gmo create mode 100644 po/kk.po create mode 100644 po/kn.gmo create mode 100644 po/kn.po create mode 100644 po/ko.gmo create mode 100644 po/ko.po create mode 100644 po/ku.gmo create mode 100644 po/ku.po create mode 100644 po/la.gmo create mode 100644 po/la.po create mode 100644 po/lt.gmo create mode 100644 po/lt.po create mode 100644 po/lv.gmo create mode 100644 po/lv.po create mode 100644 po/mai.gmo create mode 100644 po/mai.po create mode 100644 po/mg.gmo create mode 100644 po/mg.po create mode 100644 po/mk.gmo create mode 100644 po/mk.po create mode 100644 po/ml.gmo create mode 100644 po/ml.po create mode 100644 po/mn.gmo create mode 100644 po/mn.po create mode 100644 po/mr.gmo create mode 100644 po/mr.po create mode 100644 po/ms.gmo create mode 100644 po/ms.po create mode 100644 po/mutter.pot create mode 100644 po/nb.gmo create mode 100644 po/nb.po create mode 100644 po/nds.gmo create mode 100644 po/nds.po create mode 100644 po/ne.gmo create mode 100644 po/ne.po create mode 100644 po/nl.gmo create mode 100644 po/nl.po create mode 100644 po/nn.gmo create mode 100644 po/nn.po create mode 100644 po/oc.gmo create mode 100644 po/oc.po create mode 100644 po/or.gmo create mode 100644 po/or.po create mode 100644 po/pa.gmo create mode 100644 po/pa.po create mode 100644 po/pl.gmo create mode 100644 po/pl.po create mode 100644 po/pt.gmo create mode 100644 po/pt.po create mode 100644 po/pt_BR.gmo create mode 100644 po/pt_BR.po create mode 100644 po/quot.sed create mode 100644 po/remove-potcdate.sin create mode 100644 po/ro.gmo create mode 100644 po/ro.po create mode 100644 po/ru.gmo create mode 100644 po/ru.po create mode 100644 po/rw.gmo create mode 100644 po/rw.po create mode 100644 po/si.gmo create mode 100644 po/si.po create mode 100644 po/sk.gmo create mode 100644 po/sk.po create mode 100644 po/sl.gmo create mode 100644 po/sl.po create mode 100644 po/sq.gmo create mode 100644 po/sq.po create mode 100644 po/sr.gmo create mode 100644 po/sr.po create mode 100644 po/sr@latin.gmo create mode 100644 po/sr@latin.po create mode 100644 po/stamp-po create mode 100644 po/sv.gmo create mode 100644 po/sv.po create mode 100644 po/ta.gmo create mode 100644 po/ta.po create mode 100644 po/te.gmo create mode 100644 po/te.po create mode 100644 po/tg.gmo create mode 100644 po/tg.po create mode 100644 po/th.gmo create mode 100644 po/th.po create mode 100644 po/tk.gmo create mode 100644 po/tk.po create mode 100644 po/tr.gmo create mode 100644 po/tr.po create mode 100644 po/ug.gmo create mode 100644 po/ug.po create mode 100644 po/uk.gmo create mode 100644 po/uk.po create mode 100644 po/vi.gmo create mode 100644 po/vi.po create mode 100644 po/wa.gmo create mode 100644 po/wa.po create mode 100644 po/xh.gmo create mode 100644 po/xh.po create mode 100644 po/yo.gmo create mode 100644 po/yo.po create mode 100644 po/zh_CN.gmo create mode 100644 po/zh_CN.po create mode 100644 po/zh_HK.gmo create mode 100644 po/zh_HK.po create mode 100644 po/zh_TW.gmo create mode 100644 po/zh_TW.po create mode 100644 src/Makefile-tests.am create mode 100644 src/Makefile.am create mode 100644 src/Makefile.in create mode 100644 src/backends/edid-parse.c create mode 100644 src/backends/edid.h create mode 100644 src/backends/meta-backend-private.h create mode 100644 src/backends/meta-backend.c create mode 100644 src/backends/meta-barrier-private.h create mode 100644 src/backends/meta-barrier.c create mode 100644 src/backends/meta-cursor-renderer.c create mode 100644 src/backends/meta-cursor-renderer.h create mode 100644 src/backends/meta-cursor-tracker-private.h create mode 100644 src/backends/meta-cursor-tracker.c create mode 100644 src/backends/meta-cursor.c create mode 100644 src/backends/meta-cursor.h create mode 100644 src/backends/meta-display-config-shared.h create mode 100644 src/backends/meta-idle-monitor-dbus.c create mode 100644 src/backends/meta-idle-monitor-dbus.h create mode 100644 src/backends/meta-idle-monitor-private.h create mode 100644 src/backends/meta-idle-monitor.c create mode 100644 src/backends/meta-input-settings-private.h create mode 100644 src/backends/meta-input-settings.c create mode 100644 src/backends/meta-monitor-config.c create mode 100644 src/backends/meta-monitor-config.h create mode 100644 src/backends/meta-monitor-manager-dummy.c create mode 100644 src/backends/meta-monitor-manager-dummy.h create mode 100644 src/backends/meta-monitor-manager-private.h create mode 100644 src/backends/meta-monitor-manager.c create mode 100644 src/backends/meta-pointer-constraint.c create mode 100644 src/backends/meta-pointer-constraint.h create mode 100644 src/backends/meta-renderer-view.c create mode 100644 src/backends/meta-renderer-view.h create mode 100644 src/backends/meta-renderer.c create mode 100644 src/backends/meta-renderer.h create mode 100644 src/backends/meta-stage.c create mode 100644 src/backends/meta-stage.h create mode 100644 src/backends/native/dbus-utils.c create mode 100644 src/backends/native/dbus-utils.h create mode 100644 src/backends/native/gen-default-modes.py create mode 100644 src/backends/native/meta-backend-native-private.h create mode 100644 src/backends/native/meta-backend-native.c create mode 100644 src/backends/native/meta-backend-native.h create mode 100644 src/backends/native/meta-barrier-native.c create mode 100644 src/backends/native/meta-barrier-native.h create mode 100644 src/backends/native/meta-clutter-backend-native.c create mode 100644 src/backends/native/meta-clutter-backend-native.h create mode 100644 src/backends/native/meta-cursor-renderer-native.c create mode 100644 src/backends/native/meta-cursor-renderer-native.h create mode 100644 src/backends/native/meta-default-modes.h create mode 100644 src/backends/native/meta-idle-monitor-native.c create mode 100644 src/backends/native/meta-idle-monitor-native.h create mode 100644 src/backends/native/meta-input-settings-native.c create mode 100644 src/backends/native/meta-input-settings-native.h create mode 100644 src/backends/native/meta-launcher.c create mode 100644 src/backends/native/meta-launcher.h create mode 100644 src/backends/native/meta-monitor-manager-kms.c create mode 100644 src/backends/native/meta-monitor-manager-kms.h create mode 100644 src/backends/native/meta-renderer-native.c create mode 100644 src/backends/native/meta-renderer-native.h create mode 100644 src/backends/native/meta-stage-native.c create mode 100644 src/backends/native/meta-stage-native.h create mode 100644 src/backends/x11/meta-backend-x11.c create mode 100644 src/backends/x11/meta-backend-x11.h create mode 100644 src/backends/x11/meta-barrier-x11.c create mode 100644 src/backends/x11/meta-barrier-x11.h create mode 100644 src/backends/x11/meta-clutter-backend-x11.c create mode 100644 src/backends/x11/meta-clutter-backend-x11.h create mode 100644 src/backends/x11/meta-cursor-renderer-x11.c create mode 100644 src/backends/x11/meta-cursor-renderer-x11.h create mode 100644 src/backends/x11/meta-idle-monitor-xsync.c create mode 100644 src/backends/x11/meta-idle-monitor-xsync.h create mode 100644 src/backends/x11/meta-input-settings-x11.c create mode 100644 src/backends/x11/meta-input-settings-x11.h create mode 100644 src/backends/x11/meta-monitor-manager-xrandr.c create mode 100644 src/backends/x11/meta-monitor-manager-xrandr.h create mode 100644 src/backends/x11/meta-renderer-x11.c create mode 100644 src/backends/x11/meta-renderer-x11.h create mode 100644 src/backends/x11/meta-stage-x11-nested.c create mode 100644 src/backends/x11/meta-stage-x11-nested.h create mode 100644 src/backends/x11/nested/meta-cursor-renderer-x11-nested.c create mode 100644 src/backends/x11/nested/meta-cursor-renderer-x11-nested.h create mode 100644 src/compositor/clutter-utils.c create mode 100644 src/compositor/clutter-utils.h create mode 100644 src/compositor/cogl-utils.c create mode 100644 src/compositor/cogl-utils.h create mode 100644 src/compositor/compositor-private.h create mode 100644 src/compositor/compositor.c create mode 100644 src/compositor/meta-background-actor-private.h create mode 100644 src/compositor/meta-background-actor.c create mode 100644 src/compositor/meta-background-group.c create mode 100644 src/compositor/meta-background-image.c create mode 100644 src/compositor/meta-background-private.h create mode 100644 src/compositor/meta-background.c create mode 100644 src/compositor/meta-cullable.c create mode 100644 src/compositor/meta-cullable.h create mode 100644 src/compositor/meta-dnd-actor-private.h create mode 100644 src/compositor/meta-dnd-actor.c create mode 100644 src/compositor/meta-feedback-actor-private.h create mode 100644 src/compositor/meta-feedback-actor.c create mode 100644 src/compositor/meta-module.c create mode 100644 src/compositor/meta-module.h create mode 100644 src/compositor/meta-plugin-manager.c create mode 100644 src/compositor/meta-plugin-manager.h create mode 100644 src/compositor/meta-plugin.c create mode 100644 src/compositor/meta-shadow-factory.c create mode 100644 src/compositor/meta-shaped-texture-private.h create mode 100644 src/compositor/meta-shaped-texture.c create mode 100644 src/compositor/meta-surface-actor-wayland.c create mode 100644 src/compositor/meta-surface-actor-wayland.h create mode 100644 src/compositor/meta-surface-actor-x11.c create mode 100644 src/compositor/meta-surface-actor-x11.h create mode 100644 src/compositor/meta-surface-actor.c create mode 100644 src/compositor/meta-surface-actor.h create mode 100644 src/compositor/meta-sync-ring.c create mode 100644 src/compositor/meta-sync-ring.h create mode 100644 src/compositor/meta-texture-rectangle.c create mode 100644 src/compositor/meta-texture-rectangle.h create mode 100644 src/compositor/meta-texture-tower.c create mode 100644 src/compositor/meta-texture-tower.h create mode 100644 src/compositor/meta-window-actor-private.h create mode 100644 src/compositor/meta-window-actor.c create mode 100644 src/compositor/meta-window-group.c create mode 100644 src/compositor/meta-window-group.h create mode 100644 src/compositor/meta-window-shape.c create mode 100644 src/compositor/plugins/Makefile.am create mode 100644 src/compositor/plugins/Makefile.in create mode 100644 src/compositor/plugins/default.c create mode 100644 src/compositor/region-utils.c create mode 100644 src/compositor/region-utils.h create mode 100644 src/core/bell.c create mode 100644 src/core/bell.h create mode 100644 src/core/boxes-private.h create mode 100644 src/core/boxes.c create mode 100644 src/core/constraints.c create mode 100644 src/core/constraints.h create mode 100644 src/core/core.c create mode 100644 src/core/core.h create mode 100644 src/core/delete.c create mode 100644 src/core/display-private.h create mode 100644 src/core/display.c create mode 100644 src/core/edge-resistance.c create mode 100644 src/core/edge-resistance.h create mode 100644 src/core/errors.c create mode 100644 src/core/events.c create mode 100644 src/core/events.h create mode 100644 src/core/frame.c create mode 100644 src/core/frame.h create mode 100644 src/core/keybindings-private.h create mode 100644 src/core/keybindings.c create mode 100644 src/core/main.c create mode 100644 src/core/meta-accel-parse.c create mode 100644 src/core/meta-accel-parse.h create mode 100644 src/core/meta-border.c create mode 100644 src/core/meta-border.h create mode 100644 src/core/meta-gesture-tracker-private.h create mode 100644 src/core/meta-gesture-tracker.c create mode 100644 src/core/mutter.c create mode 100644 src/core/place.c create mode 100644 src/core/place.h create mode 100644 src/core/prefs.c create mode 100644 src/core/restart-helper.c create mode 100644 src/core/restart.c create mode 100644 src/core/screen-private.h create mode 100644 src/core/screen.c create mode 100644 src/core/stack-tracker.c create mode 100644 src/core/stack-tracker.h create mode 100644 src/core/stack.c create mode 100644 src/core/stack.h create mode 100644 src/core/startup-notification-private.h create mode 100644 src/core/startup-notification.c create mode 100644 src/core/testboxes.c create mode 100644 src/core/util-private.h create mode 100644 src/core/util.c create mode 100644 src/core/window-private.h create mode 100644 src/core/window.c create mode 100644 src/core/workspace-private.h create mode 100644 src/core/workspace.c create mode 100644 src/libmutter.pc.in create mode 100644 src/meta-enum-types.c.in create mode 100644 src/meta-enum-types.h.in create mode 100644 src/meta/barrier.h create mode 100644 src/meta/boxes.h create mode 100644 src/meta/common.h create mode 100644 src/meta/compositor-mutter.h create mode 100644 src/meta/compositor.h create mode 100644 src/meta/display.h create mode 100644 src/meta/errors.h create mode 100644 src/meta/group.h create mode 100644 src/meta/keybindings.h create mode 100644 src/meta/main.h create mode 100644 src/meta/meta-backend.h create mode 100644 src/meta/meta-background-actor.h create mode 100644 src/meta/meta-background-group.h create mode 100644 src/meta/meta-background-image.h create mode 100644 src/meta/meta-background.h create mode 100644 src/meta/meta-cursor-tracker.h create mode 100644 src/meta/meta-idle-monitor.h create mode 100644 src/meta/meta-monitor-manager.h create mode 100644 src/meta/meta-plugin.h create mode 100644 src/meta/meta-shadow-factory.h create mode 100644 src/meta/meta-shaped-texture.h create mode 100644 src/meta/meta-version.h.in create mode 100644 src/meta/meta-window-actor.h create mode 100644 src/meta/meta-window-shape.h create mode 100644 src/meta/prefs.h create mode 100644 src/meta/screen.h create mode 100644 src/meta/theme.h create mode 100644 src/meta/types.h create mode 100644 src/meta/util.h create mode 100644 src/meta/window.h create mode 100644 src/meta/workspace.h create mode 100644 src/org.freedesktop.login1.xml create mode 100644 src/org.gnome.Mutter.DisplayConfig.xml create mode 100644 src/org.gnome.Mutter.IdleMonitor.xml create mode 100644 src/tests/mutter-all.test.in create mode 100644 src/tests/stacking/basic-wayland.metatest create mode 100644 src/tests/stacking/basic-x11.metatest create mode 100644 src/tests/stacking/minimized.metatest create mode 100644 src/tests/stacking/mixed-windows.metatest create mode 100644 src/tests/stacking/override-redirect.metatest create mode 100644 src/tests/stacking/set-parent.metatest create mode 100644 src/tests/test-client.c create mode 100644 src/tests/test-runner.c create mode 100644 src/tests/unit-tests.c create mode 100644 src/ui/frames.c create mode 100644 src/ui/frames.h create mode 100644 src/ui/theme-private.h create mode 100644 src/ui/theme.c create mode 100644 src/ui/ui.c create mode 100644 src/ui/ui.h create mode 100644 src/wayland/meta-pointer-confinement-wayland.c create mode 100644 src/wayland/meta-pointer-confinement-wayland.h create mode 100644 src/wayland/meta-pointer-lock-wayland.c create mode 100644 src/wayland/meta-pointer-lock-wayland.h create mode 100644 src/wayland/meta-wayland-buffer.c create mode 100644 src/wayland/meta-wayland-buffer.h create mode 100644 src/wayland/meta-wayland-data-device-private.h create mode 100644 src/wayland/meta-wayland-data-device.c create mode 100644 src/wayland/meta-wayland-data-device.h create mode 100644 src/wayland/meta-wayland-gtk-shell.c create mode 100644 src/wayland/meta-wayland-gtk-shell.h create mode 100644 src/wayland/meta-wayland-input-device.c create mode 100644 src/wayland/meta-wayland-input-device.h create mode 100644 src/wayland/meta-wayland-keyboard.c create mode 100644 src/wayland/meta-wayland-keyboard.h create mode 100644 src/wayland/meta-wayland-outputs.c create mode 100644 src/wayland/meta-wayland-outputs.h create mode 100644 src/wayland/meta-wayland-pointer-constraints.c create mode 100644 src/wayland/meta-wayland-pointer-constraints.h create mode 100644 src/wayland/meta-wayland-pointer-gesture-pinch.c create mode 100644 src/wayland/meta-wayland-pointer-gesture-pinch.h create mode 100644 src/wayland/meta-wayland-pointer-gesture-swipe.c create mode 100644 src/wayland/meta-wayland-pointer-gesture-swipe.h create mode 100644 src/wayland/meta-wayland-pointer-gestures.c create mode 100644 src/wayland/meta-wayland-pointer-gestures.h create mode 100644 src/wayland/meta-wayland-pointer.c create mode 100644 src/wayland/meta-wayland-pointer.h create mode 100644 src/wayland/meta-wayland-popup.c create mode 100644 src/wayland/meta-wayland-popup.h create mode 100644 src/wayland/meta-wayland-private.h create mode 100644 src/wayland/meta-wayland-region.c create mode 100644 src/wayland/meta-wayland-region.h create mode 100644 src/wayland/meta-wayland-seat.c create mode 100644 src/wayland/meta-wayland-seat.h create mode 100644 src/wayland/meta-wayland-surface-role-cursor.c create mode 100644 src/wayland/meta-wayland-surface-role-cursor.h create mode 100644 src/wayland/meta-wayland-surface-role-tablet-cursor.c create mode 100644 src/wayland/meta-wayland-surface-role-tablet-cursor.h create mode 100644 src/wayland/meta-wayland-surface.c create mode 100644 src/wayland/meta-wayland-surface.h create mode 100644 src/wayland/meta-wayland-tablet-manager.c create mode 100644 src/wayland/meta-wayland-tablet-manager.h create mode 100644 src/wayland/meta-wayland-tablet-pad-group.c create mode 100644 src/wayland/meta-wayland-tablet-pad-group.h create mode 100644 src/wayland/meta-wayland-tablet-pad-ring.c create mode 100644 src/wayland/meta-wayland-tablet-pad-ring.h create mode 100644 src/wayland/meta-wayland-tablet-pad-strip.c create mode 100644 src/wayland/meta-wayland-tablet-pad-strip.h create mode 100644 src/wayland/meta-wayland-tablet-pad.c create mode 100644 src/wayland/meta-wayland-tablet-pad.h create mode 100644 src/wayland/meta-wayland-tablet-seat.c create mode 100644 src/wayland/meta-wayland-tablet-seat.h create mode 100644 src/wayland/meta-wayland-tablet-tool.c create mode 100644 src/wayland/meta-wayland-tablet-tool.h create mode 100644 src/wayland/meta-wayland-tablet.c create mode 100644 src/wayland/meta-wayland-tablet.h create mode 100644 src/wayland/meta-wayland-touch.c create mode 100644 src/wayland/meta-wayland-touch.h create mode 100644 src/wayland/meta-wayland-types.h create mode 100644 src/wayland/meta-wayland-versions.h create mode 100644 src/wayland/meta-wayland-wl-shell.c create mode 100644 src/wayland/meta-wayland-wl-shell.h create mode 100644 src/wayland/meta-wayland-xdg-foreign.c create mode 100644 src/wayland/meta-wayland-xdg-foreign.h create mode 100644 src/wayland/meta-wayland-xdg-shell.c create mode 100644 src/wayland/meta-wayland-xdg-shell.h create mode 100644 src/wayland/meta-wayland.c create mode 100644 src/wayland/meta-wayland.h create mode 100644 src/wayland/meta-window-wayland.c create mode 100644 src/wayland/meta-window-wayland.h create mode 100644 src/wayland/meta-xwayland-private.h create mode 100644 src/wayland/meta-xwayland-selection-private.h create mode 100644 src/wayland/meta-xwayland-selection.c create mode 100644 src/wayland/meta-xwayland.c create mode 100644 src/wayland/meta-xwayland.h create mode 100644 src/wayland/protocol/gtk-primary-selection.xml create mode 100644 src/wayland/protocol/gtk-shell.xml create mode 100644 src/x11/atomnames.h create mode 100644 src/x11/events.c create mode 100644 src/x11/events.h create mode 100644 src/x11/group-private.h create mode 100644 src/x11/group-props.c create mode 100644 src/x11/group-props.h create mode 100644 src/x11/group.c create mode 100644 src/x11/iconcache.c create mode 100644 src/x11/iconcache.h create mode 100644 src/x11/mutter-Xatomtype.h create mode 100644 src/x11/session.c create mode 100644 src/x11/session.h create mode 100644 src/x11/window-props.c create mode 100644 src/x11/window-props.h create mode 100644 src/x11/window-x11-private.h create mode 100644 src/x11/window-x11.c create mode 100644 src/x11/window-x11.h create mode 100644 src/x11/xprops.c create mode 100644 src/x11/xprops.h diff --git a/ABOUT-NLS b/ABOUT-NLS new file mode 100644 index 0000000..ac4111a --- /dev/null +++ b/ABOUT-NLS @@ -0,0 +1,1410 @@ +1 Notes on the Free Translation Project +*************************************** + +Free software is going international! The Free Translation Project is +a way to get maintainers of free software, translators, and users all +together, so that free software will gradually become able to speak many +languages. A few packages already provide translations for their +messages. + + If you found this `ABOUT-NLS' file inside a distribution, you may +assume that the distributed package does use GNU `gettext' internally, +itself available at your nearest GNU archive site. But you do _not_ +need to install GNU `gettext' prior to configuring, installing or using +this package with messages translated. + + Installers will find here some useful hints. These notes also +explain how users should proceed for getting the programs to use the +available translations. They tell how people wanting to contribute and +work on translations can contact the appropriate team. + +1.1 INSTALL Matters +=================== + +Some packages are "localizable" when properly installed; the programs +they contain can be made to speak your own native language. Most such +packages use GNU `gettext'. Other packages have their own ways to +internationalization, predating GNU `gettext'. + + By default, this package will be installed to allow translation of +messages. It will automatically detect whether the system already +provides the GNU `gettext' functions. Installers may use special +options at configuration time for changing the default behaviour. The +command: + + ./configure --disable-nls + +will _totally_ disable translation of messages. + + When you already have GNU `gettext' installed on your system and run +configure without an option for your new package, `configure' will +probably detect the previously built and installed `libintl' library +and will decide to use it. If not, you may have to to use the +`--with-libintl-prefix' option to tell `configure' where to look for it. + + Internationalized packages usually have many `po/LL.po' files, where +LL gives an ISO 639 two-letter code identifying the language. Unless +translations have been forbidden at `configure' time by using the +`--disable-nls' switch, all available translations are installed +together with the package. However, the environment variable `LINGUAS' +may be set, prior to configuration, to limit the installed set. +`LINGUAS' should then contain a space separated list of two-letter +codes, stating which languages are allowed. + +1.2 Using This Package +====================== + +As a user, if your language has been installed for this package, you +only have to set the `LANG' environment variable to the appropriate +`LL_CC' combination. If you happen to have the `LC_ALL' or some other +`LC_xxx' environment variables set, you should unset them before +setting `LANG', otherwise the setting of `LANG' will not have the +desired effect. Here `LL' is an ISO 639 two-letter language code, and +`CC' is an ISO 3166 two-letter country code. For example, let's +suppose that you speak German and live in Germany. At the shell +prompt, merely execute `setenv LANG de_DE' (in `csh'), +`export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash'). +This can be done from your `.login' or `.profile' file, once and for +all. + + You might think that the country code specification is redundant. +But in fact, some languages have dialects in different countries. For +example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The +country code serves to distinguish the dialects. + + The locale naming convention of `LL_CC', with `LL' denoting the +language and `CC' denoting the country, is the one use on systems based +on GNU libc. On other systems, some variations of this scheme are +used, such as `LL' or `LL_CC.ENCODING'. You can get the list of +locales supported by your system for your language by running the +command `locale -a | grep '^LL''. + + Not all programs have translations for all languages. By default, an +English message is shown in place of a nonexistent translation. If you +understand other languages, you can set up a priority list of languages. +This is done through a different environment variable, called +`LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG' +for the purpose of message handling, but you still need to have `LANG' +set to the primary language; this is required by other parts of the +system libraries. For example, some Swedish users who would rather +read translations in German than English for when Swedish is not +available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'. + + Special advice for Norwegian users: The language code for Norwegian +bokma*l changed from `no' to `nb' recently (in 2003). During the +transition period, while some message catalogs for this language are +installed under `nb' and some older ones under `no', it's recommended +for Norwegian users to set `LANGUAGE' to `nb:no' so that both newer and +older translations are used. + + In the `LANGUAGE' environment variable, but not in the `LANG' +environment variable, `LL_CC' combinations can be abbreviated as `LL' +to denote the language's main dialect. For example, `de' is equivalent +to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT' +(Portuguese as spoken in Portugal) in this context. + +1.3 Translating Teams +===================== + +For the Free Translation Project to be a success, we need interested +people who like their own language and write it well, and who are also +able to synergize with other translators speaking the same language. +Each translation team has its own mailing list. The up-to-date list of +teams can be found at the Free Translation Project's homepage, +`http://translationproject.org/', in the "Teams" area. + + If you'd like to volunteer to _work_ at translating messages, you +should become a member of the translating team for your own language. +The subscribing address is _not_ the same as the list itself, it has +`-request' appended. For example, speakers of Swedish can send a +message to `sv-request@li.org', having this message body: + + subscribe + + Keep in mind that team members are expected to participate +_actively_ in translations, or at solving translational difficulties, +rather than merely lurking around. If your team does not exist yet and +you want to start one, or if you are unsure about what to do or how to +get started, please write to `coordinator@translationproject.org' to +reach the coordinator for all translator teams. + + The English team is special. It works at improving and uniformizing +the terminology in use. Proven linguistic skills are praised more than +programming skills, here. + +1.4 Available Packages +====================== + +Languages are not equally supported in all packages. The following +matrix shows the current state of internationalization, as of June +2010. The matrix shows, in regard of each package, for which languages +PO files have been submitted to translation coordination, with a +translation percentage of at least 50%. + + Ready PO files af am an ar as ast az be bg bn bn_IN bs ca crh cs + +---------------------------------------------------+ + a2ps | [] [] [] | + aegis | | + anubis | | + aspell | [] [] [] | + bash | [] [] [] | + bfd | | + binutils | [] | + bison | | + bison-runtime | [] | + buzztrax | [] | + ccd2cue | | + ccide | | + cflow | | + clisp | | + coreutils | [] [] | + cpio | | + cppi | | + cpplib | [] | + cryptsetup | [] | + datamash | | + denemo | [] [] | + dfarc | [] | + dialog | [] [] [] | + dico | | + diffutils | [] | + dink | [] | + direvent | | + doodle | [] | + dos2unix | | + dos2unix-man | | + e2fsprogs | [] [] | + enscript | [] | + exif | [] | + fetchmail | [] [] | + findutils | [] | + flex | [] | + freedink | [] [] | + fusionforge | | + gas | | + gawk | [] | + gcal | [] | + gcc | | + gdbm | | + gettext-examples | [] [] [] [] [] | + gettext-runtime | [] [] [] | + gettext-tools | [] [] | + gip | [] [] | + gjay | | + glunarclock | [] [] [] | + gnubiff | [] | + gnubik | [] | + gnucash | () () [] | + gnuchess | | + gnulib | [] | + gnunet | | + gnunet-gtk | | + gold | | + gphoto2 | [] | + gprof | [] | + gpsdrive | | + gramadoir | | + grep | [] [] | + grub | [] | + gsasl | | + gss | | + gst-plugins-bad | [] | + gst-plugins-base | [] [] [] | + gst-plugins-good | [] [] [] | + gst-plugins-ugly | [] [] [] | + gstreamer | [] [] [] [] | + gtick | [] | + gtkam | [] [] | + gtkorphan | [] [] | + gtkspell | [] [] [] [] [] | + guix | | + guix-packages | | + gutenprint | [] | + hello | [] | + help2man | | + help2man-texi | | + hylafax | | + idutils | | + iso_15924 | [] | + iso_3166 | [] [] [] [] [] [] [] [] [] [] | + iso_3166_2 | | + iso_4217 | [] | + iso_639 | [] [] [] [] [] [] [] [] [] | + iso_639_3 | [] [] | + iso_639_5 | | + jwhois | | + kbd | [] | + klavaro | [] [] [] [] [] | + latrine | | + ld | [] | + leafpad | [] [] [] [] | + libc | [] [] [] | + libexif | () | + libextractor | | + libgnutls | [] | + libgpg-error | [] | + libgphoto2 | [] | + libgphoto2_port | [] | + libgsasl | | + libiconv | [] [] | + libidn | [] | + liferea | [] [] [] [] | + lilypond | [] [] | + lordsawar | [] | + lprng | | + lynx | [] [] | + m4 | [] | + mailfromd | | + mailutils | | + make | [] | + man-db | [] [] | + man-db-manpages | | + midi-instruments | [] [] [] | + minicom | [] | + mkisofs | [] | + myserver | [] | + nano | [] [] [] | + opcodes | | + parted | [] | + pies | | + popt | [] | + procps-ng | | + procps-ng-man | | + psmisc | [] | + pspp | [] | + pushover | [] | + pwdutils | | + pyspread | | + radius | [] | + recode | [] [] [] | + recutils | | + rpm | | + rush | | + sarg | | + sed | [] [] [] | + sharutils | [] | + shishi | | + skribilo | | + solfege | [] | + solfege-manual | | + spotmachine | | + sudo | [] [] | + sudoers | [] [] | + sysstat | [] | + tar | [] [] [] | + texinfo | [] [] | + texinfo_document | [] | + tigervnc | [] | + tin | | + tin-man | | + tracgoogleappsa... | | + trader | | + util-linux | [] | + ve | | + vice | | + vmm | | + vorbis-tools | [] | + wastesedge | | + wcd | | + wcd-man | | + wdiff | [] [] | + wget | [] [] | + wyslij-po | | + xboard | | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] | + +---------------------------------------------------+ + af am an ar as ast az be bg bn bn_IN bs ca crh cs + 4 0 2 4 3 11 0 8 24 3 3 1 55 4 76 + + da de el en en_GB en_ZA eo es et eu fa fi fr + +--------------------------------------------------+ + a2ps | [] [] [] [] [] [] [] [] [] | + aegis | [] [] [] [] | + anubis | [] [] [] [] [] | + aspell | [] [] [] [] [] [] [] | + bash | [] [] [] [] [] | + bfd | [] [] [] [] | + binutils | [] [] [] | + bison | [] [] [] [] [] [] [] [] | + bison-runtime | [] [] [] [] [] [] [] [] | + buzztrax | [] [] [] [] | + ccd2cue | [] [] [] | + ccide | [] [] [] [] [] [] | + cflow | [] [] [] [] [] | + clisp | [] [] [] [] [] | + coreutils | [] [] [] [] [] | + cpio | [] [] [] [] [] | + cppi | [] [] [] [] [] | + cpplib | [] [] [] [] [] [] | + cryptsetup | [] [] [] [] [] | + datamash | [] [] [] [] | + denemo | | + dfarc | [] [] [] [] [] [] | + dialog | [] [] [] [] [] [] [] [] [] | + dico | [] [] [] [] | + diffutils | [] [] [] [] [] [] | + dink | [] [] [] [] [] [] | + direvent | [] [] [] [] | + doodle | [] [] [] [] | + dos2unix | [] [] [] [] [] | + dos2unix-man | [] [] [] | + e2fsprogs | [] [] [] [] [] | + enscript | [] [] [] [] [] [] | + exif | [] [] [] [] [] [] | + fetchmail | [] () [] [] [] [] [] | + findutils | [] [] [] [] [] [] [] [] | + flex | [] [] [] [] [] [] | + freedink | [] [] [] [] [] [] [] [] | + fusionforge | [] [] [] | + gas | [] [] [] | + gawk | [] [] [] [] [] | + gcal | [] [] [] [] | + gcc | [] [] | + gdbm | [] [] [] [] [] | + gettext-examples | [] [] [] [] [] [] [] | + gettext-runtime | [] [] [] [] [] [] | + gettext-tools | [] [] [] [] [] | + gip | [] [] [] [] [] [] [] | + gjay | [] [] [] [] | + glunarclock | [] [] [] [] [] | + gnubiff | () [] [] () | + gnubik | [] [] [] [] [] | + gnucash | [] () () () () () () | + gnuchess | [] [] [] [] | + gnulib | [] [] [] [] [] [] [] | + gnunet | [] | + gnunet-gtk | [] | + gold | [] [] [] | + gphoto2 | [] () [] [] | + gprof | [] [] [] [] [] [] | + gpsdrive | [] [] [] [] | + gramadoir | [] [] [] [] [] | + grep | [] [] [] [] [] [] [] | + grub | [] [] [] [] [] | + gsasl | [] [] [] [] [] | + gss | [] [] [] [] [] | + gst-plugins-bad | [] [] | + gst-plugins-base | [] [] [] [] [] [] | + gst-plugins-good | [] [] [] [] [] [] [] | + gst-plugins-ugly | [] [] [] [] [] [] [] [] | + gstreamer | [] [] [] [] [] [] [] | + gtick | [] () [] [] [] | + gtkam | [] () [] [] [] [] | + gtkorphan | [] [] [] [] [] | + gtkspell | [] [] [] [] [] [] [] [] | + guix | [] [] [] | + guix-packages | | + gutenprint | [] [] [] [] | + hello | [] [] [] [] [] [] [] [] | + help2man | [] [] [] [] [] [] [] | + help2man-texi | [] [] [] | + hylafax | [] [] | + idutils | [] [] [] [] [] | + iso_15924 | [] () [] [] () [] () | + iso_3166 | [] () [] [] [] [] () [] () | + iso_3166_2 | [] () () () | + iso_4217 | [] () [] [] [] () [] () | + iso_639 | [] () [] [] () [] () | + iso_639_3 | () () () | + iso_639_5 | () () () | + jwhois | [] [] [] [] [] | + kbd | [] [] [] [] [] [] | + klavaro | [] [] [] [] [] [] [] | + latrine | [] () [] [] | + ld | [] [] [] [] | + leafpad | [] [] [] [] [] [] [] [] | + libc | [] [] [] [] [] | + libexif | [] [] () [] [] | + libextractor | [] | + libgnutls | [] [] [] [] | + libgpg-error | [] [] [] | + libgphoto2 | [] () [] | + libgphoto2_port | [] () [] [] [] [] | + libgsasl | [] [] [] [] [] | + libiconv | [] [] [] [] [] [] [] | + libidn | [] [] [] [] [] | + liferea | [] () [] [] [] [] [] | + lilypond | [] [] [] [] [] [] | + lordsawar | [] [] | + lprng | | + lynx | [] [] [] [] [] [] | + m4 | [] [] [] [] [] [] | + mailfromd | [] | + mailutils | [] [] [] [] | + make | [] [] [] [] [] | + man-db | [] [] [] [] | + man-db-manpages | [] [] | + midi-instruments | [] [] [] [] [] [] [] [] [] | + minicom | [] [] [] [] [] | + mkisofs | [] [] [] | + myserver | [] [] [] [] | + nano | [] [] [] [] [] [] [] | + opcodes | [] [] [] [] [] | + parted | [] [] [] | + pies | [] | + popt | [] [] [] [] [] [] | + procps-ng | [] [] | + procps-ng-man | [] [] | + psmisc | [] [] [] [] [] [] [] | + pspp | [] [] [] | + pushover | () [] [] [] | + pwdutils | [] [] [] | + pyspread | [] [] | + radius | [] [] | + recode | [] [] [] [] [] [] [] | + recutils | [] [] [] [] | + rpm | [] [] [] [] [] | + rush | [] [] [] | + sarg | [] [] | + sed | [] [] [] [] [] [] [] [] | + sharutils | [] [] [] [] | + shishi | [] [] [] | + skribilo | [] [] | + solfege | [] [] [] [] [] [] [] [] | + solfege-manual | [] [] [] [] [] | + spotmachine | [] [] [] [] | + sudo | [] [] [] [] [] [] | + sudoers | [] [] [] [] [] [] | + sysstat | [] [] [] [] [] [] | + tar | [] [] [] [] [] [] [] | + texinfo | [] [] [] [] [] | + texinfo_document | [] [] [] [] | + tigervnc | [] [] [] [] [] [] | + tin | [] [] [] [] | + tin-man | [] | + tracgoogleappsa... | [] [] [] [] [] | + trader | [] [] [] [] [] [] | + util-linux | [] [] [] [] | + ve | [] [] [] [] [] | + vice | () () () | + vmm | [] [] | + vorbis-tools | [] [] [] [] | + wastesedge | [] () | + wcd | [] [] [] [] | + wcd-man | [] | + wdiff | [] [] [] [] [] [] [] | + wget | [] [] [] [] [] [] | + wyslij-po | [] [] [] [] | + xboard | [] [] [] [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] [] [] [] [] | + +--------------------------------------------------+ + da de el en en_GB en_ZA eo es et eu fa fi fr + 123 134 32 1 6 0 97 97 23 14 4 106 139 + + ga gd gl gu he hi hr hu hy ia id is it ja ka kk + +-------------------------------------------------+ + a2ps | [] [] [] [] | + aegis | [] | + anubis | [] [] [] [] | + aspell | [] [] [] [] [] | + bash | [] [] [] [] | + bfd | [] [] | + binutils | [] [] [] | + bison | [] | + bison-runtime | [] [] [] [] [] [] [] [] | + buzztrax | | + ccd2cue | [] | + ccide | [] [] | + cflow | [] [] [] | + clisp | | + coreutils | [] [] [] | + cpio | [] [] [] [] [] [] | + cppi | [] [] [] [] [] | + cpplib | [] [] | + cryptsetup | [] | + datamash | | + denemo | [] | + dfarc | [] [] [] | + dialog | [] [] [] [] [] [] [] [] [] [] | + dico | | + diffutils | [] [] [] [] | + dink | [] | + direvent | [] | + doodle | [] [] | + dos2unix | [] [] | + dos2unix-man | | + e2fsprogs | [] | + enscript | [] [] [] | + exif | [] [] [] [] [] [] | + fetchmail | [] [] [] | + findutils | [] [] [] [] [] [] [] | + flex | [] | + freedink | [] [] [] [] | + fusionforge | | + gas | [] | + gawk | [] () [] | + gcal | | + gcc | | + gdbm | | + gettext-examples | [] [] [] [] [] [] [] | + gettext-runtime | [] [] [] [] [] [] [] | + gettext-tools | [] [] [] | + gip | [] [] [] [] [] [] | + gjay | [] | + glunarclock | [] [] [] [] [] [] | + gnubiff | [] [] () | + gnubik | [] [] [] | + gnucash | () () () () () [] | + gnuchess | | + gnulib | [] [] [] [] [] | + gnunet | | + gnunet-gtk | | + gold | [] [] | + gphoto2 | [] [] [] [] | + gprof | [] [] [] [] | + gpsdrive | [] [] [] [] | + gramadoir | [] [] [] | + grep | [] [] [] [] [] [] [] | + grub | [] [] [] | + gsasl | [] [] [] [] [] | + gss | [] [] [] [] [] | + gst-plugins-bad | [] | + gst-plugins-base | [] [] [] [] | + gst-plugins-good | [] [] [] [] [] [] | + gst-plugins-ugly | [] [] [] [] [] [] | + gstreamer | [] [] [] [] [] | + gtick | [] [] [] [] [] | + gtkam | [] [] [] [] [] | + gtkorphan | [] [] [] [] | + gtkspell | [] [] [] [] [] [] [] [] [] [] | + guix | [] | + guix-packages | | + gutenprint | [] [] [] | + hello | [] [] [] [] [] | + help2man | [] [] [] | + help2man-texi | | + hylafax | [] | + idutils | [] [] | + iso_15924 | [] [] [] [] [] [] | + iso_3166 | [] [] [] [] [] [] [] [] [] [] [] [] [] | + iso_3166_2 | [] [] | + iso_4217 | [] [] [] [] [] [] | + iso_639 | [] [] [] [] [] [] [] [] [] | + iso_639_3 | [] [] | + iso_639_5 | | + jwhois | [] [] [] [] | + kbd | [] [] [] | + klavaro | [] [] [] [] | + latrine | [] | + ld | [] [] [] [] | + leafpad | [] [] [] [] [] [] [] () | + libc | [] [] [] [] [] | + libexif | [] | + libextractor | | + libgnutls | [] | + libgpg-error | [] [] [] | + libgphoto2 | [] [] | + libgphoto2_port | [] [] | + libgsasl | [] [] [] [] | + libiconv | [] [] [] [] [] [] [] | + libidn | [] [] [] [] | + liferea | [] [] [] [] [] | + lilypond | [] | + lordsawar | | + lprng | [] | + lynx | [] [] [] [] | + m4 | [] [] [] [] [] | + mailfromd | | + mailutils | | + make | [] [] [] [] | + man-db | [] [] | + man-db-manpages | [] [] | + midi-instruments | [] [] [] [] [] [] [] [] [] | + minicom | [] [] [] | + mkisofs | [] [] | + myserver | [] | + nano | [] [] [] [] [] | + opcodes | [] [] [] | + parted | [] [] [] [] | + pies | | + popt | [] [] [] [] [] [] [] [] [] [] | + procps-ng | | + procps-ng-man | | + psmisc | [] [] [] [] | + pspp | [] [] | + pushover | [] | + pwdutils | [] | + pyspread | | + radius | [] | + recode | [] [] [] [] [] [] [] | + recutils | | + rpm | [] | + rush | [] | + sarg | | + sed | [] [] [] [] [] [] [] | + sharutils | | + shishi | | + skribilo | [] | + solfege | [] [] | + solfege-manual | | + spotmachine | | + sudo | [] [] [] [] | + sudoers | [] [] [] | + sysstat | [] [] [] | + tar | [] [] [] [] [] [] | + texinfo | [] [] [] | + texinfo_document | [] [] | + tigervnc | | + tin | | + tin-man | | + tracgoogleappsa... | [] [] [] [] | + trader | [] [] | + util-linux | [] | + ve | [] | + vice | () () | + vmm | | + vorbis-tools | [] [] | + wastesedge | () | + wcd | | + wcd-man | | + wdiff | [] [] [] | + wget | [] [] [] [] | + wyslij-po | [] [] [] | + xboard | | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] [] [] | + +-------------------------------------------------+ + ga gd gl gu he hi hr hu hy ia id is it ja ka kk + 36 2 49 4 8 2 54 75 2 6 84 11 89 60 0 3 + + kn ko ku ky lg lt lv mk ml mn mr ms mt nb ne nl + +--------------------------------------------------+ + a2ps | [] [] | + aegis | [] | + anubis | [] [] [] | + aspell | [] [] | + bash | [] [] | + bfd | | + binutils | | + bison | [] | + bison-runtime | [] [] [] [] [] [] | + buzztrax | | + ccd2cue | | + ccide | [] [] | + cflow | [] | + clisp | [] | + coreutils | [] [] | + cpio | [] | + cppi | | + cpplib | [] | + cryptsetup | [] | + datamash | [] [] | + denemo | | + dfarc | [] [] | + dialog | [] [] [] [] [] [] | + dico | | + diffutils | [] [] [] | + dink | [] | + direvent | [] | + doodle | [] | + dos2unix | [] [] | + dos2unix-man | [] | + e2fsprogs | [] | + enscript | [] | + exif | [] [] | + fetchmail | [] | + findutils | [] [] | + flex | [] | + freedink | [] [] | + fusionforge | | + gas | | + gawk | [] | + gcal | | + gcc | | + gdbm | | + gettext-examples | [] [] [] [] [] [] | + gettext-runtime | [] [] | + gettext-tools | [] | + gip | [] [] [] | + gjay | | + glunarclock | [] [] | + gnubiff | [] | + gnubik | [] [] | + gnucash | () () () () () () () [] | + gnuchess | [] [] | + gnulib | [] | + gnunet | | + gnunet-gtk | | + gold | | + gphoto2 | [] | + gprof | [] [] | + gpsdrive | [] | + gramadoir | [] | + grep | [] [] | + grub | [] [] [] | + gsasl | [] | + gss | | + gst-plugins-bad | [] | + gst-plugins-base | [] [] [] | + gst-plugins-good | [] [] [] [] | + gst-plugins-ugly | [] [] [] [] [] | + gstreamer | [] [] | + gtick | [] | + gtkam | [] [] | + gtkorphan | [] [] | + gtkspell | [] [] [] [] [] [] [] | + guix | | + guix-packages | | + gutenprint | [] | + hello | [] [] [] | + help2man | [] | + help2man-texi | | + hylafax | [] | + idutils | [] | + iso_15924 | () [] [] | + iso_3166 | [] [] [] () [] [] [] [] [] [] | + iso_3166_2 | () [] | + iso_4217 | () [] [] [] | + iso_639 | [] [] () [] [] [] [] | + iso_639_3 | [] () [] | + iso_639_5 | () | + jwhois | [] [] | + kbd | [] | + klavaro | [] [] | + latrine | | + ld | | + leafpad | [] [] [] [] [] | + libc | [] [] | + libexif | [] | + libextractor | [] | + libgnutls | [] [] | + libgpg-error | [] | + libgphoto2 | [] | + libgphoto2_port | [] | + libgsasl | [] | + libiconv | [] [] | + libidn | [] | + liferea | [] [] [] | + lilypond | | + lordsawar | | + lprng | | + lynx | [] | + m4 | [] | + mailfromd | | + mailutils | | + make | [] [] | + man-db | [] | + man-db-manpages | [] | + midi-instruments | [] [] [] [] [] [] [] | + minicom | [] | + mkisofs | [] | + myserver | | + nano | [] [] [] | + opcodes | [] | + parted | [] | + pies | | + popt | [] [] [] [] [] | + procps-ng | | + procps-ng-man | | + psmisc | [] | + pspp | [] [] | + pushover | | + pwdutils | [] | + pyspread | | + radius | [] | + recode | [] [] | + recutils | [] | + rpm | [] | + rush | [] | + sarg | | + sed | [] [] | + sharutils | [] | + shishi | | + skribilo | | + solfege | [] [] | + solfege-manual | [] | + spotmachine | [] | + sudo | [] [] | + sudoers | [] [] | + sysstat | [] [] | + tar | [] [] [] | + texinfo | [] | + texinfo_document | [] | + tigervnc | [] | + tin | | + tin-man | | + tracgoogleappsa... | [] [] [] | + trader | [] | + util-linux | [] | + ve | [] | + vice | [] | + vmm | [] | + vorbis-tools | [] | + wastesedge | [] | + wcd | [] | + wcd-man | [] | + wdiff | [] | + wget | [] [] | + wyslij-po | [] | + xboard | [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] | + +--------------------------------------------------+ + kn ko ku ky lg lt lv mk ml mn mr ms mt nb ne nl + 5 11 4 6 0 13 24 3 3 3 4 12 2 40 1 126 + + nn or os pa pl ps pt pt_BR ro ru rw sk sl sq sr + +--------------------------------------------------+ + a2ps | [] [] [] [] [] [] [] | + aegis | [] [] | + anubis | [] [] [] | + aspell | [] [] [] [] [] [] [] | + bash | [] [] [] [] [] | + bfd | [] | + binutils | [] [] | + bison | [] [] [] | + bison-runtime | [] [] [] [] [] [] [] [] | + buzztrax | | + ccd2cue | [] | + ccide | [] [] [] | + cflow | [] [] | + clisp | [] | + coreutils | [] [] [] [] | + cpio | [] [] [] | + cppi | [] [] [] | + cpplib | [] [] [] | + cryptsetup | [] [] | + datamash | [] [] | + denemo | | + dfarc | [] [] [] | + dialog | [] [] [] [] [] [] [] | + dico | [] | + diffutils | [] [] | + dink | | + direvent | [] [] | + doodle | [] [] | + dos2unix | [] [] [] [] | + dos2unix-man | [] [] | + e2fsprogs | [] | + enscript | [] [] [] [] [] [] | + exif | [] [] [] [] [] [] | + fetchmail | [] [] [] | + findutils | [] [] [] [] [] | + flex | [] [] [] [] [] | + freedink | [] [] [] [] [] | + fusionforge | | + gas | | + gawk | [] | + gcal | | + gcc | | + gdbm | [] [] [] | + gettext-examples | [] [] [] [] [] [] [] [] | + gettext-runtime | [] [] [] [] [] [] [] [] [] | + gettext-tools | [] [] [] [] [] [] [] | + gip | [] [] [] [] [] | + gjay | [] | + glunarclock | [] [] [] [] [] [] | + gnubiff | [] | + gnubik | [] [] [] [] | + gnucash | () () () () [] | + gnuchess | [] [] | + gnulib | [] [] [] [] [] | + gnunet | | + gnunet-gtk | | + gold | | + gphoto2 | [] [] [] [] [] | + gprof | [] [] [] [] | + gpsdrive | [] | + gramadoir | [] [] | + grep | [] [] [] [] [] [] | + grub | [] [] [] [] [] | + gsasl | [] [] [] | + gss | [] [] [] [] | + gst-plugins-bad | [] [] [] [] | + gst-plugins-base | [] [] [] [] [] [] | + gst-plugins-good | [] [] [] [] [] [] [] | + gst-plugins-ugly | [] [] [] [] [] [] [] | + gstreamer | [] [] [] [] [] [] [] | + gtick | [] [] [] [] [] | + gtkam | [] [] [] [] [] [] | + gtkorphan | [] [] [] [] | + gtkspell | [] [] [] [] [] [] [] [] [] | + guix | | + guix-packages | | + gutenprint | [] | + hello | [] [] [] [] [] [] | + help2man | [] [] [] [] | + help2man-texi | [] | + hylafax | | + idutils | [] [] [] | + iso_15924 | [] () [] [] [] [] | + iso_3166 | [] [] [] [] () [] [] [] [] [] [] [] [] | + iso_3166_2 | [] () [] | + iso_4217 | [] [] () [] [] [] [] [] | + iso_639 | [] [] [] () [] [] [] [] [] [] | + iso_639_3 | [] () | + iso_639_5 | () [] | + jwhois | [] [] [] [] | + kbd | [] [] | + klavaro | [] [] [] [] [] | + latrine | [] | + ld | | + leafpad | [] [] [] [] [] [] [] [] [] | + libc | [] [] [] | + libexif | [] () [] | + libextractor | [] | + libgnutls | [] | + libgpg-error | [] [] [] | + libgphoto2 | [] | + libgphoto2_port | [] [] [] [] [] | + libgsasl | [] [] [] [] | + libiconv | [] [] [] [] [] | + libidn | [] [] [] | + liferea | [] [] [] [] () [] [] | + lilypond | | + lordsawar | | + lprng | [] | + lynx | [] [] | + m4 | [] [] [] [] [] | + mailfromd | [] | + mailutils | [] | + make | [] [] [] | + man-db | [] [] [] | + man-db-manpages | [] [] [] | + midi-instruments | [] [] [] [] [] [] [] [] | + minicom | [] [] [] [] | + mkisofs | [] [] [] | + myserver | [] [] | + nano | [] [] [] [] [] [] | + opcodes | | + parted | [] [] [] [] [] [] | + pies | [] | + popt | [] [] [] [] [] [] | + procps-ng | [] | + procps-ng-man | [] | + psmisc | [] [] [] [] | + pspp | [] [] | + pushover | | + pwdutils | [] | + pyspread | [] [] | + radius | [] [] | + recode | [] [] [] [] [] [] [] [] | + recutils | [] | + rpm | [] | + rush | [] [] [] | + sarg | [] [] | + sed | [] [] [] [] [] [] [] [] | + sharutils | [] [] [] | + shishi | [] [] | + skribilo | | + solfege | [] [] [] | + solfege-manual | [] [] | + spotmachine | [] [] | + sudo | [] [] [] [] [] | + sudoers | [] [] [] [] | + sysstat | [] [] [] [] [] | + tar | [] [] [] [] [] | + texinfo | [] [] [] | + texinfo_document | [] [] | + tigervnc | | + tin | [] | + tin-man | | + tracgoogleappsa... | [] [] [] [] | + trader | [] | + util-linux | [] [] | + ve | [] [] [] | + vice | | + vmm | | + vorbis-tools | [] [] [] | + wastesedge | | + wcd | | + wcd-man | | + wdiff | [] [] [] [] [] | + wget | [] [] [] [] [] | + wyslij-po | [] [] [] [] | + xboard | [] [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] [] | + +--------------------------------------------------+ + nn or os pa pl ps pt pt_BR ro ru rw sk sl sq sr + 7 3 1 6 117 1 12 84 33 82 3 37 45 7 98 + + sv sw ta te tg th tr uk ur vi wa wo zh_CN zh_HK + +---------------------------------------------------+ + a2ps | [] [] [] [] [] | + aegis | [] | + anubis | [] [] [] [] | + aspell | [] [] [] [] | + bash | [] [] [] [] [] | + bfd | [] [] | + binutils | [] [] [] | + bison | [] [] [] [] | + bison-runtime | [] [] [] [] [] [] | + buzztrax | [] [] [] | + ccd2cue | [] [] | + ccide | [] [] [] | + cflow | [] [] [] [] | + clisp | | + coreutils | [] [] [] [] | + cpio | [] [] [] [] [] | + cppi | [] [] [] | + cpplib | [] [] [] [] [] | + cryptsetup | [] [] [] | + datamash | [] [] [] | + denemo | | + dfarc | [] | + dialog | [] [] [] [] [] [] | + dico | [] | + diffutils | [] [] [] [] [] | + dink | | + direvent | [] [] | + doodle | [] [] | + dos2unix | [] [] [] | + dos2unix-man | [] [] | + e2fsprogs | [] [] [] [] | + enscript | [] [] [] [] | + exif | [] [] [] [] [] | + fetchmail | [] [] [] [] | + findutils | [] [] [] [] [] | + flex | [] [] [] | + freedink | [] [] | + fusionforge | | + gas | [] | + gawk | [] [] | + gcal | [] [] | + gcc | [] [] | + gdbm | [] [] | + gettext-examples | [] [] [] [] [] [] | + gettext-runtime | [] [] [] [] [] [] | + gettext-tools | [] [] [] [] [] | + gip | [] [] [] [] | + gjay | [] [] | + glunarclock | [] [] [] [] | + gnubiff | [] [] | + gnubik | [] [] [] | + gnucash | () () () () [] | + gnuchess | [] [] | + gnulib | [] [] [] [] | + gnunet | | + gnunet-gtk | | + gold | [] [] | + gphoto2 | [] [] [] [] | + gprof | [] [] [] [] | + gpsdrive | [] [] [] | + gramadoir | [] [] [] | + grep | [] [] [] [] [] | + grub | [] [] [] [] | + gsasl | [] [] [] [] | + gss | [] [] [] | + gst-plugins-bad | [] [] [] [] | + gst-plugins-base | [] [] [] [] [] | + gst-plugins-good | [] [] [] [] [] | + gst-plugins-ugly | [] [] [] [] [] | + gstreamer | [] [] [] [] [] | + gtick | [] [] [] | + gtkam | [] [] [] [] | + gtkorphan | [] [] [] | + gtkspell | [] [] [] [] [] [] [] [] | + guix | [] | + guix-packages | | + gutenprint | [] [] [] | + hello | [] [] [] [] [] | + help2man | [] [] [] | + help2man-texi | [] | + hylafax | [] | + idutils | [] [] [] | + iso_15924 | [] () [] [] () [] | + iso_3166 | [] [] () [] [] () [] [] [] | + iso_3166_2 | () [] [] () [] | + iso_4217 | [] () [] [] () [] [] | + iso_639 | [] [] [] () [] [] () [] [] [] | + iso_639_3 | [] () [] [] () | + iso_639_5 | () [] () | + jwhois | [] [] [] [] | + kbd | [] [] [] | + klavaro | [] [] [] [] [] [] | + latrine | [] [] | + ld | [] [] [] [] [] | + leafpad | [] [] [] [] [] [] | + libc | [] [] [] [] [] | + libexif | [] () | + libextractor | [] [] | + libgnutls | [] [] [] [] | + libgpg-error | [] [] [] [] | + libgphoto2 | [] [] | + libgphoto2_port | [] [] [] [] | + libgsasl | [] [] [] [] | + libiconv | [] [] [] [] [] | + libidn | () [] [] [] | + liferea | [] [] [] [] [] | + lilypond | [] | + lordsawar | | + lprng | [] | + lynx | [] [] [] [] | + m4 | [] [] [] | + mailfromd | [] [] | + mailutils | [] | + make | [] [] [] | + man-db | [] [] | + man-db-manpages | [] | + midi-instruments | [] [] [] [] [] [] | + minicom | [] [] | + mkisofs | [] [] [] | + myserver | [] | + nano | [] [] [] [] | + opcodes | [] [] | + parted | [] [] [] [] [] | + pies | [] [] | + popt | [] [] [] [] [] [] [] | + procps-ng | [] [] | + procps-ng-man | [] | + psmisc | [] [] [] | + pspp | [] [] [] | + pushover | [] | + pwdutils | [] [] | + pyspread | [] | + radius | [] [] | + recode | [] [] [] [] | + recutils | [] [] [] | + rpm | [] [] [] [] | + rush | [] [] | + sarg | | + sed | [] [] [] [] [] | + sharutils | [] [] [] | + shishi | [] | + skribilo | | + solfege | [] [] [] | + solfege-manual | [] | + spotmachine | [] [] | + sudo | [] [] [] [] | + sudoers | [] [] [] | + sysstat | [] [] [] [] | + tar | [] [] [] [] [] | + texinfo | [] [] [] | + texinfo_document | [] | + tigervnc | [] [] | + tin | [] | + tin-man | | + tracgoogleappsa... | [] [] [] [] [] | + trader | [] | + util-linux | [] [] [] | + ve | [] [] [] [] | + vice | () () | + vmm | | + vorbis-tools | [] [] | + wastesedge | | + wcd | [] [] | + wcd-man | [] | + wdiff | [] [] [] | + wget | [] [] [] | + wyslij-po | [] [] | + xboard | [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] [] | + +---------------------------------------------------+ + sv sw ta te tg th tr uk ur vi wa wo zh_CN zh_HK + 87 1 4 3 0 14 52 114 1 130 7 1 88 7 + + zh_TW + +-------+ + a2ps | | 30 + aegis | | 9 + anubis | | 19 + aspell | | 28 + bash | [] | 25 + bfd | | 9 + binutils | | 12 + bison | [] | 18 + bison-runtime | [] | 38 + buzztrax | | 8 + ccd2cue | | 7 + ccide | | 16 + cflow | | 15 + clisp | | 10 + coreutils | | 20 + cpio | [] | 21 + cppi | | 16 + cpplib | [] | 19 + cryptsetup | | 13 + datamash | | 11 + denemo | | 3 + dfarc | | 16 + dialog | [] | 42 + dico | | 6 + diffutils | | 21 + dink | | 9 + direvent | | 10 + doodle | | 12 + dos2unix | [] | 17 + dos2unix-man | | 8 + e2fsprogs | | 14 + enscript | | 21 + exif | | 26 + fetchmail | | 19 + findutils | | 28 + flex | [] | 18 + freedink | | 23 + fusionforge | | 3 + gas | | 5 + gawk | | 12 + gcal | | 7 + gcc | | 4 + gdbm | | 10 + gettext-examples | [] | 40 + gettext-runtime | [] | 34 + gettext-tools | [] | 24 + gip | [] | 28 + gjay | | 8 + glunarclock | [] | 27 + gnubiff | | 9 + gnubik | | 18 + gnucash | () | 6 + gnuchess | | 10 + gnulib | | 23 + gnunet | | 1 + gnunet-gtk | | 1 + gold | | 7 + gphoto2 | [] | 19 + gprof | | 21 + gpsdrive | | 13 + gramadoir | | 14 + grep | [] | 30 + grub | | 21 + gsasl | [] | 19 + gss | | 17 + gst-plugins-bad | | 13 + gst-plugins-base | | 27 + gst-plugins-good | | 32 + gst-plugins-ugly | | 34 + gstreamer | [] | 31 + gtick | | 19 + gtkam | | 24 + gtkorphan | | 20 + gtkspell | [] | 48 + guix | | 5 + guix-packages | | 0 + gutenprint | | 13 + hello | [] | 29 + help2man | | 18 + help2man-texi | | 5 + hylafax | | 5 + idutils | | 14 + iso_15924 | [] | 23 + iso_3166 | [] | 58 + iso_3166_2 | | 9 + iso_4217 | [] | 28 + iso_639 | [] | 46 + iso_639_3 | | 10 + iso_639_5 | | 2 + jwhois | [] | 20 + kbd | | 16 + klavaro | | 29 + latrine | | 7 + ld | [] | 15 + leafpad | [] | 40 + libc | [] | 24 + libexif | | 9 + libextractor | | 5 + libgnutls | | 13 + libgpg-error | | 15 + libgphoto2 | | 9 + libgphoto2_port | [] | 19 + libgsasl | | 18 + libiconv | [] | 29 + libidn | | 17 + liferea | | 29 + lilypond | | 10 + lordsawar | | 3 + lprng | | 3 + lynx | | 19 + m4 | [] | 22 + mailfromd | | 4 + mailutils | | 6 + make | | 18 + man-db | | 14 + man-db-manpages | | 9 + midi-instruments | [] | 43 + minicom | [] | 17 + mkisofs | | 13 + myserver | | 9 + nano | [] | 29 + opcodes | | 11 + parted | [] | 21 + pies | | 4 + popt | [] | 36 + procps-ng | | 5 + procps-ng-man | | 4 + psmisc | [] | 21 + pspp | | 13 + pushover | | 6 + pwdutils | | 8 + pyspread | | 5 + radius | | 9 + recode | | 31 + recutils | | 9 + rpm | [] | 13 + rush | | 10 + sarg | | 4 + sed | [] | 34 + sharutils | | 12 + shishi | | 6 + skribilo | | 3 + solfege | | 19 + solfege-manual | | 9 + spotmachine | | 9 + sudo | | 23 + sudoers | | 20 + sysstat | | 21 + tar | [] | 30 + texinfo | | 17 + texinfo_document | | 11 + tigervnc | | 10 + tin | [] | 7 + tin-man | | 1 + tracgoogleappsa... | [] | 22 + trader | | 11 + util-linux | | 12 + ve | | 14 + vice | | 1 + vmm | | 3 + vorbis-tools | | 13 + wastesedge | | 2 + wcd | | 7 + wcd-man | | 3 + wdiff | [] | 22 + wget | | 22 + wyslij-po | | 14 + xboard | | 8 + xdg-user-dirs | [] | 68 + xkeyboard-config | [] | 27 + +-------+ + 90 teams zh_TW + 170 domains 44 2805 + + Some counters in the preceding matrix are higher than the number of +visible blocks let us expect. This is because a few extra PO files are +used for implementing regional variants of languages, or language +dialects. + + For a PO file in the matrix above to be effective, the package to +which it applies should also have been internationalized and +distributed as such by its maintainer. There might be an observable +lag between the mere existence a PO file and its wide availability in a +distribution. + + If June 2010 seems to be old, you may fetch a more recent copy of +this `ABOUT-NLS' file on most GNU archive sites. The most up-to-date +matrix with full percentage details can be found at +`http://translationproject.org/extra/matrix.html'. + +1.5 Using `gettext' in new packages +=================================== + +If you are writing a freely available program and want to +internationalize it you are welcome to use GNU `gettext' in your +package. Of course you have to respect the GNU Library General Public +License which covers the use of the GNU `gettext' library. This means +in particular that even non-free programs can use `libintl' as a shared +library, whereas only free software can use `libintl' as a static +library or use modified versions of `libintl'. + + Once the sources are changed appropriately and the setup can handle +the use of `gettext' the only thing missing are the translations. The +Free Translation Project is also available for packages which are not +developed inside the GNU project. Therefore the information given above +applies also for every other Free Software Project. Contact +`coordinator@translationproject.org' to make the `.pot' files available +to the translation teams. + diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..cc6a26e --- /dev/null +++ b/Makefile.am @@ -0,0 +1,11 @@ + +SUBDIRS = cogl clutter data src po doc + +ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} + +DISTCLEANFILES = \ + intltool-extract \ + intltool-merge \ + intltool-update \ + po/stamp-it \ + po/.intltool-merge-cache diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..b86dd42 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,897 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = . +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(am__DIST_COMMON) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = src/meta/meta-version.h +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + cscope distdir dist dist-all distcheck +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ + $(LISP)config.h.in +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +CSCOPE = cscope +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(top_srcdir)/build-aux/compile \ + $(top_srcdir)/build-aux/config.guess \ + $(top_srcdir)/build-aux/config.rpath \ + $(top_srcdir)/build-aux/config.sub \ + $(top_srcdir)/build-aux/install-sh \ + $(top_srcdir)/build-aux/ltmain.sh \ + $(top_srcdir)/build-aux/missing \ + $(top_srcdir)/src/meta/meta-version.h.in ABOUT-NLS COPYING \ + NEWS build-aux/compile build-aux/config.guess \ + build-aux/config.rpath build-aux/config.sub build-aux/depcomp \ + build-aux/install-sh build-aux/ltmain.sh build-aux/missing +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +GZIP_ENV = --best +DIST_ARCHIVES = $(distdir).tar.xz +DIST_TARGETS = dist-xz +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CVT = @CVT@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_COMPILE_SCHEMAS = @GLIB_COMPILE_SCHEMAS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNOME_KEYBINDINGS_KEYSDIR = @GNOME_KEYBINDINGS_KEYSDIR@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GSETTINGS_DISABLE_SCHEMAS_COMPILE = @GSETTINGS_DISABLE_SCHEMAS_COMPILE@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +META_GIR = @META_GIR@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +MUTTER_CFLAGS = @MUTTER_CFLAGS@ +MUTTER_LIBS = @MUTTER_LIBS@ +MUTTER_MAJOR_VERSION = @MUTTER_MAJOR_VERSION@ +MUTTER_MICRO_VERSION = @MUTTER_MICRO_VERSION@ +MUTTER_MINOR_VERSION = @MUTTER_MINOR_VERSION@ +MUTTER_NATIVE_BACKEND_CFLAGS = @MUTTER_NATIVE_BACKEND_CFLAGS@ +MUTTER_NATIVE_BACKEND_LIBS = @MUTTER_NATIVE_BACKEND_LIBS@ +MUTTER_PLUGIN_API_VERSION = @MUTTER_PLUGIN_API_VERSION@ +MUTTER_PLUGIN_DIR = @MUTTER_PLUGIN_DIR@ +MUTTER_WAYLAND_CFLAGS = @MUTTER_WAYLAND_CFLAGS@ +MUTTER_WAYLAND_LIBS = @MUTTER_WAYLAND_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WAYLAND_PROTOCOLS_CFLAGS = @WAYLAND_PROTOCOLS_CFLAGS@ +WAYLAND_PROTOCOLS_DATADIR = @WAYLAND_PROTOCOLS_DATADIR@ +WAYLAND_PROTOCOLS_LIBS = @WAYLAND_PROTOCOLS_LIBS@ +WAYLAND_SCANNER = @WAYLAND_SCANNER@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +XMKMF = @XMKMF@ +XWAYLAND_PATH = @XWAYLAND_PATH@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +ZENITY = @ZENITY@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gsettingsschemadir = @gsettingsschemadir@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = cogl clutter data src po doc +DISTCLEANFILES = \ + intltool-extract \ + intltool-merge \ + intltool-update \ + po/stamp-it \ + po/.intltool-merge-cache + +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @test -f $@ || rm -f stamp-h1 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 +src/meta/meta-version.h: $(top_builddir)/config.status $(top_srcdir)/src/meta/meta-version.h.in + cd $(top_builddir) && $(SHELL) ./config.status $@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) +clean-cscope: + -rm -f cscope.files +cscope.files: clean-cscope cscopelist +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz + $(am__post_remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__post_remove_distdir) + +dist-tarZ: distdir + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__post_remove_distdir) + +dist-shar: distdir + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz + $(am__post_remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__post_remove_distdir) + +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + --srcdir=../.. --prefix="$$dc_install_base" \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__post_remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile config.h +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-hdr \ + distclean-libtool distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) all install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--refresh check check-am clean clean-cscope clean-generic \ + clean-libtool cscope cscopelist-am ctags ctags-am dist \ + dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ + dist-xz dist-zip distcheck distclean distclean-generic \ + distclean-hdr distclean-libtool distclean-tags distcleancheck \ + distdir distuninstallcheck dvi dvi-am html html-am info \ + info-am install install-am install-data install-data-am \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..ffc7882 --- /dev/null +++ b/NEWS @@ -0,0 +1,4908 @@ +3.22.3 +====== +* Fix switching between two finger- and edge scrolling on wayland [Rui; #771744] +* Fix frequent freezes in multihead setups on wayland [Rui; #774557] +* Preserve root window mask on XSelectionRequest [Olivier; #776128] +* Fix window menu placement with HiDPI [Jonas; #776055] +* Fix HiDPI detection on vertical monitor layouts [Carlos; #777687] +* Fix erroneous key event repeats [Rui; #774989] +* Fix "ghost" cursors in multi-monitor setups [Jonas; #771056] +* Use eglGetPlatformDisplay [Adam; #772422] +* Fix erratic raise_or_lower behavior [Jose; #705200] +* Extend tablet device checks [Carlos; #773779] +* Set right scale for tablet tool cursors on HiDPI [Carlos; #778474] +* Allow edge-scrolling without 2fg-scroll capable devices [Rui; #778554] +* Misc. bug fixes [Jonas, Rui, Carlos, Peter; #771297, #774135, #775986, + #777691, #777470, #778262, #776919] + +Contributors: + Jonas Ådahl, Olivier Fourdan, Carlos Garnacho, Peter Hutterer, Adam Jackson, + Jose Marino, Rui Matos + +Translations: + Mandy Wang [zh_CN] + +3.22.2 +====== +* Really fix framebuffer capture origin offset [Rui; #771502] +* Fix session going into idle mode immediately on startup [Rui; #772839] +* Fix mirror mode with stage views [Rui; #773115] +* Improve pointer constraints support [Jonas; #771859] +* Stack docks below other windows on fullscreen monitors [Rui; #772937] +* Fix switching between two finger- and edge scrolling on wayland [Rui; #771744] +* Fix popup grabs blocking screen lock on wayland [Rui; #771235] +* Fix various crashes on wayland [Jonas; #771646, #771858] +* Fix various placement issues on wayland [Jonas, Sjoerd, Olivier; #768039, + #771841, #773141, #772729] +* Misc. bug fixes [Rui, Jonas, Olivier; #771019, #773116, #772914, #773210] + +Contributors: + Jonas Ådahl, Olivier Fourdan, Rui Matos, Sjoerd Simons + +Translations: + Theppitak Karoonboonyanan [th], Kjartan Maraas [nb], liushuyu [zh_CN], + YunQiang Su [zh_CN] + +3.22.1 +====== +* Fix feedback loop between StClipboard and X11 bridge [Carlos; #760745] +* Fall back gracefully if DRM plane rotation fails [Carlos; #772512] +* Approximate native monitor backend behavior to X [Rui; #772176] +* Fix crash on VT switch on wayland [Jonas; #771646] +* Expose Flatpak ID for application matching [Florian; #772613, #772614] + +Contributors: + Jonas Ådahl, Carlos Garnacho, Rui Matos, Florian Müllner, Olav Vitters + +Translations: + Inaki Larranaga Murgoitio [eu], Milo Casagrande [it] + +3.22.0 +====== +* Fix wayland crashes [Jonas; #771305, #771345, #770940, #771495] +* Fix display rotation on wayland [Jonas; #770672] +* Fix framebuffer capture origin offset [Rui; #771502] +* Misc. bug fixes [Jonas, Florian, Carlos; #770937, #771536, #771628, #771549] + +Contributors: + Jonas Ådahl, Carlos Garnacho, Rui Matos, Florian Müllner + +Translations: + Ask Hjorth Larsen [da], Charles Monzat [fr], Stas Solovey [ru], + Tom Tryfonidis [el], David King [en_GB] + +3.21.92 +======= +* Fix absolute pointer motion events on wayland [Jonas; #770557] +* Default to using stage views [Jonas; #770366] +* Fix animated cursors on wayland [Rui; #749913] +* Fix various crashes on wayland [Jonas; #757568, #770727, #770992] +* Fix screen capture for stage views not at (0, 0) [Jonas; #770127] +* Compress motion events instead of discarding them [Jonas; #771049] +* Fix XWayland pointer warp emulation [Jonas; #771050] +* Add common monitor modes in KMS backend [Rui; #744544] +* Temporarily use g-s-d schemas for tablet configuration [Carlos; #771315] +* Misc. bug fixes [Jonas, Carlos; #770402, #770647, #770991, #770994, #770929] + +Contributors: + Jonas Ådahl, Olivier Fourdan, Carlos Garnacho, Rui Matos, Florian Müllner + +Translations: + Changwoo Ryu [ko], Baurzhan Muftakhidinov [kk], Anders Jonsson [sv], + Tiago Santos [pt], Rafael Fontenelle [pt_BR], Mario Blättermann [de], + Alexander Shopov [bg], RÅ«dolfs Mazurs [lv], Fran Dieguez [gl], + Trần Ngọc Quân [vi], Piotr Drąg [pl], Мирослав Николић [sr, sr@latin] + +3.21.91 +======= +* Add support for xdg-foreign protocol [Jonas; #769786] +* Support monitor rotation on wayland [Carlos; #745079] +* Port xdg-shell implementation to unstable v6 [Jonas; #769936] +* Handle unsupported buffer sizes more gracefully [Olivier; #770387] +* Use the same output naming logic as the X server on wayland [Rui; #770338] +* Fix replies in gnome-shell's chat notifications on wayland [Florian; #758167] +* Misc. bug fixes and cleanups [Bastien, Sjoerd, Jonas; #769276, #769636, + #770131, #770324, #769731] + +Contributors: + Jonas Ådahl, Olivier Fourdan, Carlos Garnacho, Rui Matos, Florian Müllner, + Bastien Nocera, Sjoerd Simons + +Translations: + Piotr Drąg [pl], Mario Blättermann [de], Andika Triwidada [id], + Enrico Nicoletto [pt_BR], Мирослав Николић [sr, sr@latin] + +3.21.90 +======= +* Consider XDG_SESSION_TYPE when determining session type [Jouke; #759388] +* Re-add support for edge scrolling on some touchpads [Bastien; #768245] +* Support mouse and trackball acceleration profile [Jonas; #769179] +* Draw monitor contentn to individual framebuffer [Jonas; #768976] +* Support virtual input devices [Jonas, Carlos; #765009] +* Set correct output scale on hotplug [Jonas; #769505] +* Misc. bug fixes and cleanups [Florian, Jonas, Thomas, Bastien, Carlos; + #769014, #769024, #769054, #769070, #769036, #769305, #769578, #769800, + #769073] + +Contributors: + Jonas Ådahl, Carlos Garnacho, Thomas Hindoe Paaboel Andersen, Simon McVittie, + Alberts Muktupāvels, Florian Müllner, Bastien Nocera, Jouke Witteveen + +Translations: + Daniel Mustieles [es], Aurimas Černius [lt], DuÅ¡an Kazik [sk], + Fabio Tomat [fur], Balázs Úr [hu], Yosef Or Boczko [he], Marek Černocký [cs], + Matej Urbančič [sl] + +3.21.4 +====== +* Fix missing frame border around GTK+ dialogs [Florian; #745060] +* Improve X11 <-> wayland copy and paste interaction [Carlos; #768007] +* Add support for NV_robustness_video_memory_purge extension [Rui; #739178] +* Fix restoring the old focused window on restart [Owen; #766243] +* Fix fullscreen windows on other monitors stealing focus after closing + a window [Rui; #768221] +* Draw monitor content to individual framebuffer [Jonas; #768976] +* Provide screen capture API [Jonas; #768978] +* Misc. bug fixes and cleanups [Rui, Owen, Luca, Olivier, Jonas, Carlos; + #767969, #768243, #762407, #767997, #768039, #768977, #768977] + +Contributors: + Jonas Ådahl, Luca Bruno, Olivier Fourdan, Carlos Garnacho, Rui Matos, + Florian Müllner, Owen W. Taylor + +Translations: + Andika Triwidada [id] + +3.21.3 +====== +* Don't create invalid UTF-8 window description strings [Rui; #765535] +* Convert window titles and wm_class to UTF-8 [Rui; #752788] +* Communicate tiled state to GTK+ on wayland [Olivier; #766860] +* Use kill() to force-quit unresponsive wayland clients [Olivier; #767464] +* Fix window position when unmaximizing via DND on wayland [Olivier; #764180] +* Avoid full window redraws when using extended frame sync [Florian; #767798] + +Contributors: + Olivier Fourdan, Rui Matos, Florian Müllner + +Translations: + Cédric Valmary [oc] + +3.21.2 +====== +* Clean up surface <-> shell interaction [Jonas; #763431] +* Fix grabbing random keys for disabled shortcuts [Rui; #766270] +* Fix stacking of hidden windows on wayland [Rui; #764844] +* Misc. bug fixes [Victor, Florian, Marek, Rui; #766306, #766326, #751847, + #763832, #766528] + +Contributors: + Jonas Ådahl, Emmanuele Bassi, Marek Chalupa, Matthias Clasen, + Carlos Garnacho, Rui Matos, Florian Müllner, Victor Toso + +Translations: + Tiago Santos [pt], Cédric Valmary [oc], Muhammet Kara [tr] + +3.21.1 +====== +* Notify clients of pending modifier state changes [Rui; #748526] +* Add get_is_builtin_display_on() method [Florian; #765267] +* Fix 2-finger titlebar taps on wayland [Carlos; #764519] +* Merge clutter and cogl forks into mutter [Rui; #760439] +* Misc. bug fixes [Florian, Victor, Jonas; #765058, #765252, #765062] + +Contributors: + Jonas Ådahl, Emmanuele Bassi, Olivier Fourdan, Carlos Garnacho, Rui Matos, + Florian Müllner, Victor Toso, Rico Tzschichholz + +Translations: + GNOME Translation Robot [ja, gd] + +3.20.1 +====== +* Constrain window move/resizes on wayland as on X11 [Rui; #748819] +* Don't crash with invalid previous monitor configurations [Rui; #764286] +* Misc. bug fixes and cleanups [Jonas, Cosimo; #762828, #764807] + +Contributors: + Jonas Ådahl, Cosimo Cecchi, Rui Matos, Jasper St. Pierre + +Translations: + Inaki Larranaga Murgoitio [eu], Reinout van Schouwen [nl], Fabio Tomat [fur], + Trần Ngọc Quân [vi] + +3.20.0 +====== +* Fix crash when using visual bell [Jonas; #763858] + +Contributors: + Jonas Ådahl, Jasper St. Pierre + +Translations: + Milo Casagrande [it], Ask Hjorth Larsen [da] + +3.19.92 +======= +* Add system bell support on wayland [Jonas; #763284] +* Add gtk_surface.present to gtk-shell [Jonas; #763295] +* Handle DND drops on the root window [Carlos; #762104] +* Misc. bug fixes [Jonas, Carlos, Rui; #762828, #760745, #763125, #762763, + #762661, #762639, #763159] + +Contributors: + Jonas Ådahl, Carlos Garnacho, Rui Matos, Florian Müllner + +Translations: + RÅ«dolfs Mazurs [lv], Balázs Úr [hu], Claude Paroz [fr], Matej Urbančič [sl], + Мирослав Николић [sr, sr@latin], Sebastian Rasmussen [sv], Changwoo Ryu [ko], + Gil Forcada [ca], Tom Tryfonidis [el] + +3.19.91 +======= +* Add --nested CLI argument to fix nested wayland session [Jonas; #758658] +* Fix stack - scene graph stacking synchronization issues [Jonas; #755605] +* Rate-limit last-device changes to fix freezes [Carlos; #753527] +* Implement primary selection protocol [Carlos; #762560] +* Misc. bug fixes [Carlos, Jonas; #762878, #762716] + +Contributors: + Jonas Ådahl, Carlos Garnacho, Tim Lunn + +Translations: + Piotr Drąg [pl], Artur de Aquino Morais [pt_BR], Marek Černocký [cs], + Cédric Valmary [oc], Mario Blättermann [de], DuÅ¡an Kazik [sk], + Fran Dieguez [gl], Aurimas Černius [lt], Daniel Mustieles [es], + Stas Solovey [ru], Yosef Or Boczko [he] + +3.19.90 +======= +* Release buffer after processing commit [Ray; #761312, #761613] +* Implement pointer motion, locks and confinement on wayland [Jonas; #744104] +* Add basic startup notification support on wayland [Carlos; #762268] +* Misc. bug fixes [Rui, Alberts, Florian; #760670, #761543, #752794, #761557] + +Contributors: + Jonas Ådahl, Olivier Fourdan, Carlos Garnacho, Rui Matos, + Alberts Muktupāvels, Florian Müllner, Jasper St. Pierre, Ray Strode + +3.19.4 +====== +* Fix updating stacking order when setting transient_for [Jonas; #755606] +* Support screen rotation when supported by the driver [Carlos; #745079] +* Protect against broken WM_CLASS property implementations [Sebastian; #759658] +* Handle wl_pointer v5 events on wayland [Carlos; #760637] +* Implement DND actions on wayland [Carlos; #760805] +* Misc. bug fixes [Jonas, Rui, Ray, Marek; #754711, #756789, #759297, #758613, + #760330, #760476, #759222, #760670] + +Contributors: + Jonas Ådahl, Marek Chalupa, Carlos Garnacho, Sebastian Keller, Rui Matos, + Florian Müllner, Jasper St. Pierre, Ray Strode + +Translations: + Aurimas Černius [lt] + +3.19.3 +====== +* Correct refresh rate units on KMS/Wayland [Daniel; #758653] +* Fix crash when initial cursor position is not on a monitor [Marek; #756698] +* Fix crash when more CRTs are enabled than outputs connected [Rui; #751638] +* Fix touch pointer emulation on wayland [Carlos; #756754] +* Allow minimizing windows that don't advertise supporting it [Jasper; #758186] +* Force 2-finger scroll by default if available [Bastien; #759304] +* Fix crash during XWayland initialization [Marek; #751845] +* Ensure to send a ConfigureNotify to just mapped windows [Rui; #759492] +* Misc. bug fixes and cleanups [Carlos, Jonas, Lionel; #758239, #758633, + #755503, #759374] + +Contributors: + Jonas Ådahl, Marek Chalupa, Carlos Garnacho, Lionel Landwerlin, Rui Matos, + Bastien Nocera, Daniel Stone, Jasper St. Pierre + +3.19.2 +====== +* Fix crash on monitor unplug [Rui; #756796] +* Exit cleanly on initialization errors [Owen; #757311] +* Allow to determine backend setting from session type [Ray; #741666] +* Fix DRM device detection for non-PCI devices [Alban; #754911] +* Don't force placement of windows without buffer on wayland [Marek; #751887] +* Fix initialization of bypass compositor hint [Rui; #758544] + +Contributors: + Alban Browaeys, Marek Chalupa, Rui Matos, Florian Müllner, Ray Strode, + Owen W. Taylor + +3.19.1 +====== +* wayland: Allow to trigger popups through keyboard/touch [Carlos; #756296] +* Fix modifiers-only input source switching on Ubuntu [Alberts; #756543] +* Misc. bug fixes [Jonas, Rui, Giovanni, Florian; #756675, #756660, #746420, + #756548, #756796, #757101, #757148] + +Contributors: + Jonas Ådahl, Giovanni Campagna, Carlos Garnacho, Rui Matos, + Alberts Muktupāvels, Florian Müllner + +Translations: + Daniel Șerbănescu [ro] + +3.18.1 +====== +* Misc. crash fixes [Jonas, Rui, Carlos, Owen, Florian; #755096, #754979, + #755490, #754357, #745785, #756642] +* Improve HiDPI support on wayland [Jonas; #755097] +* Fix doubly-scaled cursor on XWayland HiDPI [Jonas; #755099] +* Stop hiding titlebar buttons in dialogs [Florian; #641630] +* Add support for fullscreen/unfullscreen animations [Cosimo; #707248] +* Misc. bug fixes [Rui, Colin, Florian; #743339, #752047, #756074, #756649] + +Contributors: + Jonas Ådahl, Cosimo Cecchi, Carlos Garnacho, Rui Matos, Florian Müllner, + Jasper St. Pierre, Colin Walters, Owen W. Taylor + +3.18.0 +====== +* Misc. fixes [Florian, Jonas; #753434] + +Contributors: + Jonas Ådahl, Florian Müllner + +Translations: + RÅ«dolfs Mazurs [lv] + +3.17.92 +======= +* Don't omit the background color for backgrounds that don't fill the screen + [Ray; #754476] +* Fix up key state on FocusIn when running nested [Owen; #753948] +* Find the right DRM device instead of hardcoding card0 [Marek; #753434] +* Scale cursor on HiDPI screens [Jonas; #744932] +* Misc. fixes and cleanups [Lan, Jonas, Javier, Olivier; #754545, #754215, + #754621, #754715] + +Contributors: + Jonas Ådahl, Marek Chalupa, Olivier Fourdan, Javier Jardón, Ting-Wei Lan, + Ray Strode, Owen W. Taylor + +3.17.91 +======= +* Send error on pointer-gesture protocol version mismatch [Jonas; #753855] +* Misc. cleanups [Jonas; #744932] + +Contributors: + Jonas Ådahl + +Translations: + Chao-Hsiung Liao [zh_TW], Piotr Drąg [pl] + +3.17.90 +======= +* Fix glitch with some fullscreen apps [Rui; #753020] +* Fix screen update issue with NVidia driver [Aaron, Rui; #728464] +* Only call frame callbacks for surfaces that get drawn [Adel; #739163] +* Misc. bug fixes and cleanups [Jonas, Rui, Ting-Wei; #753222, #752753, #753237, + #753380, #744104, #744932] + +Contributors: + Jonas Ådahl, Adel Gadllah, Carlos Garnacho, Ting-Wei Lan, Rui Matos, + Florian Müllner, Aaron Plattner, Jasper St. Pierre + +Translations: + Akom Chotiphantawanon [th] + +3.17.4 +====== +* nested: Allow basic configuration of dummy outputs [Jonas; #747089] +* Send wl_surface.enter and wl_surface.leave on output changes [Jonas; #744453] +* Improve HiDPI handling on wayland [Jonas; #745655, #744934] +* Implement compositor-side animated cursors [Carlos; #752342] +* Misc. bug fixes [Peter, Marek, Carlos, Matthias, Rui; #750816, #751884, + #752248, #752551, #752552, #752673, #752674] + +Contributors: + Jonas Ådahl, Marek Chalupa, Matthias Clasen, Carlos Garnacho, Peter Hutterer, + Rui Matos, Florian Müllner, Jasper St. Pierre + +3.17.3 +====== +* Add X11/wayland clipboard interaction [Carlos; #738312] +* Support VM monitor layout hints on wayland [Thomas; #750363] +* Misc. bug fixes [Rui, Jonas, Olivier, Carlos, Ting-Wei, Peter, Florian; + #749994, #750256, #749716, #748705, #750552, #751036, #750007, #751136, + #750552, #751471, #751715, #750680] + +Contributors: + Jonas Ådahl, Dave Airlie, Cosimo Cecchi, Olivier Fourdan, Carlos Garnacho, + Thomas Hellstrom, Peter Hutterer, Ting-Wei Lan, Jasper Lievisse Adriaanse, + Rui Matos, Florian Müllner, Jasper St. Pierre + +Translations: + Marek Černocký [cs], Christian Kirbach [de], Pedro Albuquerque [pt] + +3.17.2 +====== +* Honor default value for click method setting [Rui; #746290] +* Add X11/wayland clipboard interoperation [Carlos; #738312] +* Misc. bug fixes [Rui; #749076, #749711] + +Contributors: + Carlos Garnacho, Rui Matos, Jasper St. Pierre + +3.17.1 +====== +* Add public method to get neighboring monitor [Florian; #633994] +* Apply the right settings to the right input devices [Carlos; #747886] +* Fix scroll button setting [Ondrej; #747967] +* Add support for modal hint on wayland [Jonas; #745720] +* Don't reset idle time for non-hardware events [Rui; #748541] +* Misc. bug fixes [Ray, Rui; #748380, #748478] + +Contributors: + Jonas Ådahl, Carlos Garnacho, Ondrej Holy, Rui Matos, Florian Müllner, + Jasper St. Pierre, Ray Strode, Tomeu Vizoso + +3.16.1 +====== +* Add function to refresh all background instances [Rui; #739178] +* Fix swapped scroll methods on wayland [Ondrej; #746870] +* Manually activate stage to fix accessibility on wayland [Ray, Rui; #746670] +* Center pointer on primary monitor on startup [Carlos; #746896] +* wayland: Reword synchronized state application semantics [Jonas; #743617] +* Ensure input settings are applied on startup [Rui; #747434] +* Misc. bug fixes [Jonas, Giovanni, Calvin, Ray, Rui; #744932, #746509, #746692, + #746510, #746545, #747263] + +Contributors: + Jonas Ådahl, Giovanni Campagna, Carlos Garnacho, Ondrej Holy, Rui Matos, + Jasper St. Pierre, Ray Strode, Calvin Walton + +Translations: + Khaled Hosny [ar], Marek Černocký [cs] + +3.16.0 +====== +* wayland: Don't skip notifying about initial maximized state [Jonas; #745303] + +Contributors: + Jonas Ådahl + +Translations: + Kjartan Maraas [nb], Jiri Grönroos [fi], Andika Triwidada [id], + Inaki Larranaga Murgoitio [eu], Ask H. Larsen [da], Muhammet Kara [tr] + +3.15.92 +======= +* Ensure pointer visibility on monitor changes [Rui, Marek; #745121, #745752] +* Fix geometry of shaded windows [Florian; #746145] +* Take over cursor visibility handling from gsd [Carlos; #712775] +* Fix touch interaction on window decorations [Carlos; #745335] +* Add options for libinput_config_click_method [Carlos; #746290] +* Scale window decorations on HiDPI displays [Florian; #744354] +* Misc. bug fixes [Carlos, Ray, Rui; #745163, #746295, #746098, #745734] + +Contributors: + Marek Chalupa, Carlos Garnacho, Rui Matos, Florian Müllner, + Jasper St. Pierre, Ray Strode + +Translations: + Piotr Drąg [pl], Milo Casagrande [it], Changwoo Ryu [ko], + Daniel Korostil [uk], Baurzhan Muftakhidinov [kk], Trần Ngọc Quân [vi], + Alexander Shopov [bg], Jordi Mas [ca], Samir Ribic [bs], A S Alam [pa], + Matej Urbančič [sl] + +3.15.91 +======= +* wayland: Fix nested compositor mode [Jonas; #745401] +* wayland: Fix pointer constraining [Marek; #727337] +* wayland: Fix input region on HiDPI [Jonas; #744933] +* Allow themes to style buttons differently based on function [Horst; #745108] +* Misc. bug fixes and cleanups [Ray, Rui, Alban; #745141, #745118, #745476, + #745442] + +Contributors: + Jonas Ådahl, Alban Browaeys, Marek Chalupa, Horst, Rui Matos, + Jasper St. Pierre, Ray Strode + +Translations: + Chao-Hsiung Liao [zh_TW], Efstathios Iosifidis [el], DuÅ¡an Kazik [sk], + Balázs Úr [hu], Daniel Mustieles [es], Claude Paroz [fr], Stas Solovey [ru], + Yosef Or Boczko [he], Rafael Ferreira [pt_BR], Aurimas Černius [lt], + Fran Dieguez [gl], Anders Jonsson [sv], Мирослав Николић [sr, sr@latin] + +3.15.90 +======= +* Initialize MetaOutput even when we can't get the EDID [Rui; #743412] +* Expose MetaMonitorManager to introspection [Rui; #743745] +* Fix flash on unredirection [Chris; #743858] +* Update xdg-shell implementation to v5 [Jonas; #744452] +* Do not try to use seat devices that aren't (yet) present [Ray; #744640] +* Add keybindings for switching to VT8-VT12 [Ray; #744800] +* Misc bug fixes [Jonas, Cosimo; #743678, #744500] + +Contributors: + Jonas Ådahl, Cosimo Cecchi, Carlos Garnacho, Rui Matos, Jasper St. Pierre, + Ray Strode, Chris Wilson + +Translations: + Yosef Or Boczko [he], Yuri Myasoedov [ru], Kristjan SCHMIDT [eo], + Matej Urbančič [sl], DuÅ¡an Kazik [sk] + +3.15.4 +====== +* Use GTK+ theme for window decorations instead of metacity [Florian; #741917] +* Export the same EDID information on X11 and wayland [Carlos; #742882] +* Apply input device configuration on wayland [Carlos; #739397] +* Implement pointer barriers on wayland [Jonas; #706655] +* Misc. bug fixes (Ting-Wei, Rui, Ikey, Florian, Marek, Jonas; #741829, + #738630, #737463, #698995, #727893, #742825, #742824, #742841, #743173, + #743189, #743217, #743254] + +Contributors: + Jonas Ådahl, Giovanni Campagna, Marek Chalupa, Ikey Doherty, Adel Gadllah, + Carlos Garnacho, Ting-Wei Lan, Rui Matos, Florian Müllner, Jasper St. Pierre, + Rico Tzschichholz + +Translations: + Matej Urbančič [sl], Balázs Úr [hu], Marek Černocký [cs], + Inaki Larranaga Murgoitio [eu], Rafael Ferreira [pt_BR], + Daniel Mustieles [es], Fran Dieguez [gl] + +3.15.3 +====== +* Don't leave left-over frames queued [Owen; #738686] +* Set CRTC configuration even if it might be redundant [Rui; #740838] + +Contributors: + Rui Matos, Jasper St. Pierre, Rico Tzschichholz, Owen W. Taylor + +Translations: + Trần Ngọc Quân [vi], Muhammet Kara [tr] + +3.15.2 +====== +* Don't enable hiDPI on monitors with broken EDID [Bastien; #734839] +* Prevent crash applying monitor config for a closed lid [Rui; #739450] +* Fix "flicker" during startup transition [Ray; #740377] +* Misc. bug fixes [Lan, Florian, Carlos; #731521, #740133, #738890] + +Contributors: + Emmanuele Bassi, Carlos Garnacho, Jonathon Jongsma, Ting-Wei Lan, Rui Matos, + Florian Müllner, Bastien Nocera, Jasper St. Pierre, Ray Strode + +Translations: + Kjartan Maraas [nb] + +3.15.1 +====== +* Use GResources for theme loading [Cosimo; #736936] +* Fix headerbar drag getting stuck on xwayland [Carlos; #738411] +* Fix wayland hiDPI regressions [Adel; #739161] +* Misc bug fixes and cleanups [Jasper, Rui, Carlos; #662962, #738630, #738888, + #738890] + +Contributors: + Cosimo Cecchi, Adel Gadllah, Carlos Garnacho, Rui Matos, Florian Müllner, + Jasper St. Pierre + +3.14.1 +====== +* Fix move-titlebar-onscreen function [Florian; #736915] +* Fix stacking of the guard window [Owen; #737233] +* Fix keycode lookup for non-default layouts [Rui; #737134] +* Fix workspaces-only-on-primary handling [Florian; #737178] +* Don't unstick sticky windows on workspace removal [Florian; #737625] +* Do not auto-minimize fullscreen windows [Jasper; #705177] +* Upload keymap to newly added keyboard devices [Rui; #737673] +* Apply keyboard repeat settings [Rui; #728055] +* Don't send pressed keys on enter [Rui; #727178] +* Fix build without wayland/native [Rico; #738225] +* Send modifiers after the key event [Rui; #738238] +* Fix unredirect heuristic [Adel; #738271] +* Do not show system chrome over fullscreen windows [Florian; #693991] +* Misc. bug fixes [Florian, Adel, Tom; #737135, #737581, #738146, #738384] + +Contributors: + Tom Beckmann, Adel Gadllah, Carlos Garnacho, Rui Matos, Florian Müllner, + Jasper St. Pierre, Rico Tzschichholz, Owen W. Taylor + +Translations: + Krishnababu Krothapalli [te], Мирослав Николић [sr, sr@latin], + Alexander Shopov [bg], Saibal Ray [bn_IN], Milo Casagrande [it], + RÅ«dolfs Mazurs [lv] + +3.14.0 +====== +* Fix placement of popup windows on wayland [Jasper; #736812] +* Only increment serial once per event [Jasper; #736840] +* Fix window positioning regression with non-GTK+ toolkits [Owen; #736719] + +Contributors: + Jasper St. Pierre, Owen W. Taylor + +Translations: + Saibal Ray [bn_IN], DuÅ¡an Kazik [sk], Manoj Kumar Giri [or], + Christian Kirbach [de], Ask H. Larsen [da], YunQiang Su [zh_CN], + Bernd Homuth [de], Shankar Prasad [kn], Petr Kovar [cs], Rajesh Ranjan [hi] + +3.13.92 +======= +* Rewrite background code [Owen; #735637, #736568] +* Fix size in nested mode [Owen; #736279] +* Fix destroy animation of background windows [Florian; #735927] +* Wire keymap changes up to the wayland frontend [Rui; #736433] +* Add a test framework and stacking tests [Owen; #736505] +* Simplify handling of the merged X and wayland stack [Owen; #736559] +* Fix cursor size on HiDPI [Adel; #729337] +* Misc. bug fixes [Owen; #735632, #736589, #736694] + +Contributors: + Adel Gadllah, Rui Matos, Florian Müllner, Jasper St. Pierre, Owen W. Taylor + +Translations: + Andika Triwidada [id], Piotr Drąg [pl], Changwoo Ryu [ko], + Kjartan Maraas [nb], Ville-Pekka Vainio [fi], Yuri Myasoedov [ru], + Aurimas Černius [lt], Balázs Úr [hu], Sweta Kothari [gu], A S Alam [pa], + Sandeep Sheshrao Shedmake [mr], Shantha kumar [ta], Gil Forcada [ca], + Carles Ferrando [ca@valencia], Mattias Eriksson [sv] + +3.13.91 +======= +* Misc. bug fixes [Carlos; #735452] + +Contributors: + Adel Gadllah, Carlos Garnacho, Rui Matos, Jasper St. Pierre, + Rico Tzschichholz + +Translations: + Chao-Hsiung Liao po/zh_HK, zh_TW.po, Enrico Nicoletto [pt_BR], + Kjartan Maraas [nb], Fran Diéguez [gl], Yosef Or Boczko [he], + Maria Mavridou [el], Claude Paroz [fr] + +3.13.90 +======= +* Only call XSync() once per frame [Rui; #728464] +* Update capabilities on device list changes [Carlos; #733563] +* Make use of GLSL optional [Adel; #733623] +* Handle gestures and touch events on wayland [Carlos; #733631] +* Add support for unminimize compositor effects [Cosimo; #733789] +* Always set the frame background to None [Giovanni; #734054] +* Add backend methods to handle keymaps [Rui; #734301] +* Actually mark revalidated MetaTextureTower levels as valid [Owen; #734400] +* Rely on explicit -backward switcher keybindings instead of -magic + [Christophe; #732295, #732385] +* Misc. bug fixes and cleanups [Rui, Adel, Christophe; #727178, #734852, + #734960] + +Contributors: + Emmanuele Bassi, Giovanni Campagna, Cosimo Cecchi, Piotr Drąg, + Christophe Fergeau, Adel Gadllah, Carlos Garnacho, Rui Matos, + Florian Müllner, Jasper St. Pierre, Rico Tzschichholz, Olav Vitters, + Owen W. Taylor + +Translations: + Kjartan Maraas [nb], Inaki Larranaga Murgoitio [eu], Lasse Liehu [fi], + ngoswami [as], Daniel Mustieles [es] + +3.13.4 +====== +* Fix move/resize operations for wayland clients [Marek; #731237] +* Add ::first-frame signal to MetaWindowActor [Owen; #732343] +* Handle keysyms without the XF86 prefix [Owen; #727993] +* Add touch gesture support [Carlos] +* Fix a deadlock when exiting [Owen; #733068] +* Add framework for restarting the compositor with nice visuals + [Owen; #733026] +* Toggle seat capabilities on VT switch [Carlos; #733563] +* Misc bug fixes [Florian, Owen; #732695, #732350] + +Contributors: + Tom Beckmann, Giovanni Campagna, Marek Chalupa, Adel Gadllah, + Carlos Garnacho, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz, + Owen W. Taylor + +Translations: + Yuri Myasoedov [ru], Fran Diéguez [gl], Aurimas Černius [lt], MarMav [el], + Enrico Nicoletto [pt_BR] + +3.13.3 +====== +* Improve behavior of window buttons with compositor menus [Florian; #731058] +* Implement touch support on wayland [Carlos; #724442] +* Update window shadows [Nikita; #731866] +* Keep windows on the preferred output [Florian; #731760] +* Misc bug fixes [Jonas, Florian, Jasper; #729601, #730681, #731353, #731332, + #730527, #662962] + +Contributors: + Jonas Ådahl, Nikita Churaev, Carlos Garnacho, Florian Müllner, + Jasper St. Pierre, Rico Tzschichholz + +3.13.2 +====== +* Add basic HiDPI support on wayland [Adel; #728902] +* Fix crash when monitors change during suspend [Giovanni; #725637] +* Replace mutter-launch with logind integration [Jasper; #724604] +* Move window menu into the compositor [Jasper; #726352] +* Fix delayed focus-follows-mouse support [Florian; #730541] +* Support fallback app menu in window decorations [Florian; #730752] +* Misc. bug fixes and cleanups [Giovanni, Jonas, Jasper; #729732, #729602, + #726714] + +Contributors: + Jonas Ådahl, Giovanni Campagna, Adel Gadllah, Florian Müllner, + Jasper St. Pierre, Rico Tzschichholz + +Translations: + Pau Iranzo [ca], Daniel Mustieles [es] + +3.13.1 +====== +* Fix opacity values from _NET_WM_WINDOW_OPACITY [Nirbheek; #727874] +* Merge wayland branch [Jasper, Giovanni, Robert B., Neil, Adel, Rui, Jonas, + Lionel, Tim, Owen, Florian, Colin W., Cosimo, Ray, Kalev, Pavel, Robert A., + Magdalen, Marek, Matthias, Alban, Seán, Daniel, Stefano, Carlos, Colin G., + Andreas, Alexander, Ryan, Marc-André, Asad, Alberto, Bastien, Hans, + Debarshi, Sindhu, Andika, Rico, Olav] +* Don't prevent workspace switches for present_with_time() [Florian; #728018] +* Add shortcuts for switching to the last workspace [Elad; #659288] +* Make move/resize menu items behave like the keybindings [Jasper; #728617] +* Misc. bug fixes and cleanups [Jasper, Bastien, Florian, Adel; #720631, + #727979, #728423, #728395, #729044] + +Contributors: + Jonas Ådahl, Elad Alfassa, Robert Ancell, Magdalen Berns, Robert Bragg, + Giovanni Campagna, Cosimo Cecchi, Marek Chalupa, Nirbheek Chauhan, + Matthias Clasen, Alban Crequy, Seán de Búrca, Daniel Drake, Jason Ekstrand, + Stefano Facchini, Adel Gadllah, Carlos Garnacho, Colin Guthrie, + Andreas Heider, Lionel Landwerlin, Alexander Larsson, Kalev Lember, + Ryan Lortie, Tim Lunn, Marc-André Lureau, Rui Matos, Asad Mehmood, + Alberto Milone, Florian Müllner, Bastien Nocera, Hans Petter Jansson, + Debarshi Ray, Neil Roberts, Sindhu S, Jasper St. Pierre, Ray Strode, + Andika Triwidada, Rico Tzschichholz, Pavel Vasin, Olav Vitters, + Colin Walters, A. Walton, Owen W. Taylor + +Translations: + Inaki Larranaga Murgoitio [eu], marablack3 [el], Daniel Mustieles [es], + Fran Diéguez [gl], Yosef Or Boczko [he], Dirgita [id] + +3.12.0 +====== +* Fix grab issue with SSD xwayland windows [Rui; #726123] +* Misc. bug fixes [Jasper, Ray, Rui, Florian; #727011] + +Contributors: + Rui Matos, Florian Müllner, Jasper St. Pierre, Ray Strode + +3.11.92 +======= +* Fix identification of CSD windows [Owen; #723029] +* Update keyboard state unconditionally [Rui; #722847] +* Misc bug fixes and cleanups [Owen, Rui, Giovanni, Matthias, Adel, Ryan, + Jasper, Marek, Florian; #723580, #726123, #726683] + +Contributors: + Giovanni Campagna, Marek Chalupa, Matthias Clasen, Adel Gadllah, Ryan Lortie, + Rui Matos, Florian Müllner, Jasper St. Pierre, Owen W. Taylor + +3.11.91 +======= +* Don't use keysym to match keybindings [Rui; #678001] +* Fix message tray icons showing up blank (again) [Adel; #725180] +* Improve keybinding lookups [Rui; #725588] +* Fix dynamic updates of titlebar style properties [Owen; #725751] +* Fix positioning of manually positioned windows [Owen; #724049] +* Misc bug fixes and cleanups [Jasper, Carlos, Adel, Giovanni, Florian; #720631, + #724969, #725216, #724402, #722266, #725338, #725525] + +Contributors: + Giovanni Campagna, Adel Gadllah, Carlos Garnacho, Rui Matos, Florian Müllner, + Jasper St. Pierre, Owen W. Taylor + +3.11.90 +======= +* Fix double-scaling on high DPI resolutions [Adel; #723931] +* Make tile previews a compositor effect [Stefano, Florian; #665758] +* Misc. bug fixes and cleanups [Ryan, Giovanni, Jasper, Adel; #722530, #724257, + #724258, #720631, #724364, #724472] + +Contributors: + Giovanni Campagna, Marek Chalupa, Stefano Facchini, Adel Gadllah, + Ryan Lortie, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz + +3.11.5 +====== +* Fix CSD titlebars being placed off-screen [Jasper; #719772] +* Add support for subsurfaces [Jonas; #705502] +* Expose MetaWindow:skip-taskbar property [Florian; #723307] +* Fix legacy tray icons showing up blank [Adel; #721596] +* Fix configuration of cloned monitors [Adel; #710610] +* Misc bug fixes and cleanups [Jasper, Adel, Marek, Jonas; #720631, #723468, + #720818, #723563, #723564] + +Contributors: + Jonas Ådahl, Marek Ch, Adel Gadllah, Florian Müllner, Jasper St. Pierre + +3.11.4 +====== +* Don't leave focus on windows that are being unmanaged [Owen; #711618] +* Reduce server grabs [Daniel Drake; #721345, #721709] +* Improve heuristic to determine display output name [Cosimo Cecchi; #721674] +* Atomically unmaximize both directions [Jasper; #722108] +* Misc bug fixes [Debarshi, Andika, Florian; #721517, #721674, #722347] + +Contributors: + Cosimo Cecchi, Daniel Drake, Florian Müllner, Debarshi Ray, Jasper St. Pierre, + Andika Triwidada, Owen W. Taylor + +3.11.3 +====== +* Fix focus issues with external OSKs[Jasper; #715030] +* Add a MetaCullable interface [Jasper; #714706] +* Fix window keybindings [Rui; #719724] +* Fix settings keyboard/pointer focus for new clients [Rui; #719725] +* Fix window group paint volume [Owen; #719669] +* Fix frame extents problems [Owen; #714707] +* Add shortcut to move windows between monitors [Florian; #671054] +* Fix problems with focus tracking [Owen; #720558] +* Misc. bug fixes and cleanups: [Rui, Colin, Lionel, Jasper, Owen; #712833, + #719557, #719695, #719833, #678989, #720417, #720630] + +Contributors: + Lionel Landwerlin, Rui Matos, Alberto Milone, Florian Müllner, + Jasper St. Pierre, Rico Tzschichholz, Owen W. Taylor, Colin Walters + +3.11.2 +====== +* Support setting a NULL opaque region [Andreas; #711518] +* Sync keymap from X to wayland [Giovanni; #707446] +* Implement support for subsurfaces [Jonas; #705502] +* Don't focus the no-focus-window for globally active windows [Jasper; #710296] +* Support "hotplug_mode_update" property [Marc-André; #711216] +* Fix resize operations using mouse-button-modifier [Lionel; #710251] +* Fix position of attached modals for CSD windows [Giovanni, Owen; #707194] +* Misc. bug fixes [Rui, Jasper, Neil, Florian; #712247, #711731] + +Contributors: + Giovanni Campagna, Andreas Heider, Lionel Landwerlin, Marc-André Lureau, + Rui Matos, Florian Müllner, Neil Roberts, Sindhu S, Jasper St. Pierre, + Rico Tzschichholz, Owen W. Taylor, Jonas Ådahl + +3.11.1 +====== +* Fix tile previews getting stuck on right click during drags [Lionel; #704759] +* Use new UPower API [Bastien] +* Set hot spot when cursor set from wl_buffer [Jonas; #709593] +* Expose min-backlight-step [Asad; #710380] +* Misc. bug fixes and cleanups [Jasper, Olav, Magdalen; #709776] + +Contributors: + Magdalen Berns, Lionel Landwerlin, Asad Mehmood, Bastien Nocera, + Jasper St. Pierre, Olav Vitters, Jonas Ådahl + +3.10.1 +====== +* Don't apply fullscreen workarounds to CSD windows [Giovanni; #708718] +* Fix hangs during DND operations [Adel; #709340] +* Misc bug fixes [Dan, Giovanni, Jasper; #708813, #708420] + +Contributors: + Giovanni Campagna, Adel Gadllah, Dan Horák, Hans Petter Jansson, + Jasper St. Pierre + +3.10.0.1 +======== +* Fix bug when a window changed size twice in a single frame - this + can happen with GTK+ client-side decorations [Giovanni, Owen; #708367] + +Contributors: + Giovanni Campagna, Owen Taylor + +3.10.0 +====== +* Update dependencies [Giovanni; #708210] + +3.9.92 +====== +* Constrain the pointer position onto visible monitors [Giovanni; #706655] +* Fix keyboard state handling in face of event compression [Giovanni; #706963] +* Extend the MetaCursorTracker API with query pointer and cursor visibility [Giovanni; #707474] +* Be stricter in checking and exposing the wayland protocol version [#707851] +* Don't require plugins to pass event to Clutter [Giovanni; #707482] +* Move the --wayland option from the binary to the library [Giovanni; #707897] +* Implement running from gnome-session (environment variable setting, process group + handling, Clutter backend variables) [Giovanni; #706421] +* Add support for more cursor types [Giovanni; #707919] +* Drop man pages for removed utilities [Kalev; #706579] +* Implement monitor configuration on KMS [Giovanni; #706308] +* Implement HW cursors [Giovanni; #707573] +* Implement minimal support for resizing and maximizing wayland clients [Giovanni; #707401] +* Implement transient hints for wayland clients [Giovanni; #707401] +* Implement popup menu surfaces and grabs [Giovanni; #707863] +* Immediately fire idle watches that are already expired [Giovanni; #707302] +* Remove holes generated by disabling the laptop lid [Giovanni; #707473] +* Misc bug fixes [Giovanni, Pavel, Adel; #707649, #706124, #707584, #707851, #707929, + #708070] + +Contributors: + Adel Gadllah, Giovanni Campagna, Kalev Lember, Pavel Vasin + +Translations: + Мирослав Николић po/sr, sr@latin.po, Мирослав Николић [sr, sr@latin], + Chao-Hsiung Liao [zh_HK, zh_TW], Yuri Myasoedov [ru], + Ville-Pekka Vainio [fi], Changwoo Ryu [ko], A S Alam [pa], + Mattias Põldaru [et], RÅ«dolfs Mazurs [lv], Ihar Hrachyshka [be], + Nilamdyuti Goswami [as], Andika Triwidada [id], Baurzhan Muftakhidinov [kk], + Benjamin Steinwender [de] + +3.9.91 +====== +* Drop man pages for removed utilities [Kalev; #706579] +* Add support for idle tracking [Giovanni, Cosimo; #706005, #707250] +* Skip CRTC reconfigurations that have no effect [Giovanni; #706672] +* Ignore skip-taskbar hints on parentless dialogs [Giovanni; #673399] +* Don't save pixbuf data in user data [Tim; #706777] +* Don't queue redraws for obscured regions [Adel; #703332] +* Suppor the opaque region hints for wayland clients [Jasper; #707019] +* Turn blending off when drawing entirely opaque regions [Jasper; #707019] +* Check event timestamps before reconfiguring [Giovanni; #706735] +* Merge the DBus API for display configuration in the wayland branch [Giovanni] +* Install an X IO error handler for XWayland [Giovanni; #706962] +* Use the clutter xkbcommon integration for the wayland keyboard [Giovanni; #705862] +* Add a setuid helper for running on KMS+evdev [Giovanni, Colin; #705861] +* Add keybindings for switching VT [Giovanni; #705861] +* Implement plugin modality when running as a wayland compositor [Giovanni; #705917] +* Add support for the application menu for wayland clients [Giovanni; #707128] +* Several Coverity spotted fixes [Jasper] +* Don't create a dummy texture for the texture template [Neil; #707458] +* Use a more conservative paint volume for obscured windows [Adel] +* Misc bug fixes [Giovanni, Colin, Seán, Jasper, Cosimo; #706582, #706598, + #706787, #706729, #706825, #707081, #707090, #707267, #706982, #706289] + +Contributors: + Giovanni Campagna, Cosimo Cecchi, Adel Gadllah, Colin Guthrie, Kalev Lember, + Tim Lunn, Jasper St. Pierre, Neil Roberts, Rico Tzschichholz, Seán de Búrca + +Translations: + Piotr Drąg [pl], Alexandre Franke [fr], Kjartan Maraas [nb], + Milo Casagrande [it], Balázs Úr [hu], Seán de Búrca [ga], Fran Diéguez [gl], + Daniel Mustieles [es], Aurimas Černius [lt], Gil Forcada [ca] + +3.9.90 +====== +* First release from the wayland branch, includes basic support for running + as a wayland compositor [Robert, Neil, Giovanni] +* Add support for _GTK_FRAME_EXTENTS [Jasper; #705766] +* Fix quick consecutive presses breaking keyboard input [Alban; #666101] +* Work towards running as wayland compositor [Giovanni] + - Add DBus API for display configuration + [#705670, #706231, #706233, #706322, #706382] + - Add abstraction layer for cursor tracking [#705911] + - Add support for plugin modality under wayland [#705917] +* Disable GTK+ scaling [Alexander; #706388] +* Disable blending while updating tower [Robert] +* Misc bug fixes and cleanups [Adel, Jasper, Giovanni, Colin, Rico, Florian; + #703332, #704437, #706207] + +Contributors: + Robert Bragg, Giovanni Campagna, Alban Crequy, Adel Gadllah, + Alexander Larsson, Florian Müllner, Jasper St. Pierre, Neil Roberts, + Rico Tzschichholz, Colin Walters + +Translations: + Jiro Matsuzawa [ja], Kjartan Maraas [nb], Matej Urbančič [sl], + Marek Černocký [cs], Daniel Mustieles [es], Rafael Ferreira [pt_BR], + Yaron Shahrabani [he], Ján Kyselica [sk] + +3.9.5 +===== +* Don't select for touch events on the stage [Jasper; #697192] +* Don't queue redraws for obscured regions [Adel; #703332] +* Export timestamp of global keybinding events [Bastien; #704858] +* Misc bug fixes and cleanups [Jasper, Rico; #703970] + +Contributors: + Adel Gadllah, Bastien Nocera, Jasper St. Pierre, Rico Tzschichholz + +3.9.4 +===== +* Tweak window shadows [Allan; #702141] +* Ignore our own focus events for focus prediction [Jasper; #701017] +* Add API to query if the stage is focused [Jasper; #700735] +* Add API to query the monitor for a given position [Adel] +* Don't force attached dialogs to be border-only [Florian; #702764] +* Allow slicing of backgrounds to avoid texture size limits [Ray; #702283] +* Miscellaneous bug fixes and cleanups [Adel; #701224, #702564] + +Contributors: + Allan Day, Adel Gadllah, Florian Müllner, Jasper St. Pierre, Ray Strode + +3.9.3 +===== +* Ensure events are always reported to the grab window [Rui; #701219] +* Use new clutter_stage_set_paint_callback() function to prevent dropping + frames with frame synced toolkits [Owen; #698794] + +Contributors: + Rui Matos, Owen W. Taylor + +3.9.2 +===== +* Add meta_window_can_close() function [Jasper; #699269] +* Add support for string-array preferences [Florian; #700223] +* Fix a potential race condition with _NET_WM_MOVERESIZE [Jasper; #699777] +* Fix shade window action [Stef; #693714] +* Remove overlay_group [Giovanni; #700735] +* Improve tracking of the focus window [Dan, Jasper; #647706] +* Add API to freeze/unfreeze the keyboard [Rui; #697001] +* Grab and emit a signal when XK_ISO_Next_Group is pressed [Rui; #697002] +* Misc bug fixes and cleanups [Dieter, Jasper, Rui; #699636, #700735, #697000] + +Contributors: + Giovanni Campagna, Rui Matos, Florian Müllner, Jasper St. Pierre, + Dieter Verfaillie, Stef Walter, Dan Winship + +Translations: + Kjartan Maraas [nb], Ján Kyselica [sk] + +3.9.1 +===== +* Fix miscellaneous memory leaks [Pavel; #698710] +* Misc fixes and cleanups [Stef, Simon; #698179, #697758] + +Contributors: + Simon McVittie, Pavel Vasin, Stef Walter + +3.8.1 +===== +* Fix crash when getting default font [Bastien; #696814] +* Fix ungrabbing of keybindings [Rui; #697003] +* Misc fixes and cleanups [Jasper, Simon; #697758] + +Contributors: + Jasper Lievisse Adriaanse, Rui Matos, Simon McVittie, Bastien Nocera + +Translations: + Guillaume Desmottes [fr], Shankar Prasad [kn], Bruce Cowan [en_GB], + Andika Triwidada [id], Yaron Shahrabani [he], Kjartan Maraas [nb], + Gheyret Kenji [ug] + +3.8.0 +===== +* Address major memory leak when changing backgrounds [Ray; #696157] + +Contributors: + Ray Strode + +Translations: + Sandeep Sheshrao Shedmake [mr], Victor Ibragimov [tg], Gabor Kelemen [hu], + Ville-Pekka Vainio [fi], Rajesh Ranjan [hi], Dr.T.Vasudevan [ta], + ManojKumar Giri [or], Yuri Myasoedov [ru], Petr Kovar [cs], + Jiro Matsuzawa [ja], Krishnababu Krothapalli [te], Ani Peter [ml], + Inaki Larranaga Murgoitio [eu] + +3.7.92 +====== +* Build and improve reference docs [Tomeu; #676856, #695641, #695935] +* Add tracking of whether there are fullscreen windows [Owen; 649748] +* Misc bug fixes and cleanups [Adel, Giovanni, Owen, Jasper, Florian; #695269, + #695711, #694046, #695813, #695881, #676856, #696053, #682779, #696089, + #696091, #696087] + +Contributors: + Giovanni Campagna, Adel Gadllah, Florian Müllner, Jasper St. Pierre, + Tomeu Vizoso, Owen W. Taylor + +Translations: + Chao-Hsiung Liao [zh_HK, zh_TW], Rafael Ferreira [pt_BR], + Ihar Hrachyshka [be], Nilamdyuti Goswami [as], Matej Urbančič [sl], + Dimitris Spingos [el], Jan Kyselica [sk], Khaled Hosny [ar], + Мирослав Николић [sr, sr@latin], Duarte Loreto [pt], Sweta Kothari [gu], + Milo Casagrande [it], Changwoo Ryu [ko], Gil Forcada [ca], + Carles Ferrando [ca@valencia], Mattias Põldaru [et], Alexandre Franke [fr], + Ask H. Larsen [da], RÅ«dolfs Mazurs [lv], Nguyễn Thái Ngọc Duy [vi] + +3.7.91 +====== +* Fix windows being treated as remote after hostname changes [Ray; #688716] +* Add meta_window_get_all_monitors() method [Adel; #646861] +* Add grab API for externally defined accelerators [Florian; #643111] +* Make session registration an explicit step [Ray; #694876] +* Avoid unnecessary stage redraws [Adel; #694988, #695006] +* Misc fixes [Giovanni, Ray, Jasper, Rui, Pavel, Owen; #694801, #694725, + #694641, #694393, #678917, #695093, #694837, #695135, #694771, #694321] + +Contributors: + Giovanni Campagna, Adel Gadllah, Rui Matos, Florian Müllner, + Jasper St. Pierre, Ray Strode, Owen Taylor, Pavel Vasin + +Translations: + Daniel Mustieles [es], Yaron Shahrabani [he], A S Alam [pa], Piotr Drąg [pl], + Gheyret Kenji [ug], Alexandre Franke [fr], Milo Casagrande [it], + Fran Diéguez [gl], Dimitris Spingos [el], Мирослав Николић [sr, sr@latin], + Chao-Hsiung Liao [zh_HK, zh_TW], Nguyễn Thái Ngọc Duy [vi], + Aurimas Černius [lt], Mario Blättermann [de], Kjartan Maraas [nb] + +3.7.90 +====== +* Support _NET_WM_OPAQUE_REGION [Jasper, Adel; #679901] +* Add wrapper for XI2.3 pointer barriers [Jasper; #677215] +* Update style of resize popups [Cosimo; #692741] +* Implement compositor <-> application frame synchronization [Owen; #685463] +* Handle animated backgrounds [Ray; #682427] +* Add a new window group for override-redirect windows [Gayan; #633620] +* Pass on pointer events on guard window to Clutter [Jasper; #681540] +* Show correct shortcut in window menus [Giovanni; #694045] +* Don't put minimized windows at the back of alt-tab [Jasper; #693991] +* Misc bug fixes and cleanups [Jasper, Rico, Adel, Florian, Rui, Giovanni, + Owen; #692679, #693354, #690581, #693439, #692718, #693475, #693482, #693540, + #690580, #680990, #693833, #693922, #693854, #694224] + +Contributors: + Giovanni Campagna, Cosimo Cecchi, Adel Gadllah, Rui Matos, Florian Müllner, + Gayan Perera, Jasper St. Pierre, Ray Strode, Owen Taylor, Rico Tzschichholz + +Translations: + Fran Diéguez [gl], A S Alam [pa], Alexandre Franke [fr], Aurimas Černius [lt], + Мирослав Николић [sr, sr@latin], Fran Diéguez [gl], Piotr Drąg [pl], + Luca Ferretti [it], Daniel Mustieles [es] + +3.7.5 +===== +* Don't allow multiline window titles [Jon; #683056] +* Make meta_window_located_on_workspace() public [Jasper; #691744] +* Request XI2.3 [Colin; #692877] +* Add meta_window_set_icon_geometry() method [Florian; #692997] +* Require XFixes 5.0 [Jasper; #677215] +* Change unredirection hints to match spec changes [Adel; #693064] +* Improve unredict heuristicts [Adel; #683786] +* Misc bug fixes and cleanups [Florian, Jasper, Adel; #691874, #679901, + #692952, #693042] + +Contributors: + Adel Gadllah, William Jon McCann, Florian Müllner, Jasper St. Pierre, + Colin Walters + +Translations: + Daniel Mustieles [es], Ihar Hrachyshka [be], Nilamdyuti Goswami [as], + Gheyret Kenji [ug], Kjartan Maraas [nb], Yaron Shahrabani [he], + Piotr Drąg [pl], Chao-Hsiung Liao [zh_HK,zh_TW], Milo Casagrande [it] + +3.7.4 +===== +* Add support for bypass compositor hints [Adel; #683020] +* Make automaximization optional [Adel; #680990] +* Add method for checking if the application is responding [Giovanni; #684340] +* Expose the xinput opcode [Jasper; #690590] +* Rebrand "minimize" as "hide" [Florian; #682887] +* Misc bug fixes and cleanups [Giovanni, Ray, Jasper, Matthias, Debarshi, + Florian, Rui; #690454, #690573, #690593, #690956, #691363, #690609, #690317, + #689263] + +Contributors: + Giovanni Campagna, Matthias Clasen, Adel Gadllah, Rui Matos, Florian Müllner, + Debarshi Ray, Jasper St. Pierre, Ray Strode + +Translations: + Mattias Põldaru [et], Yaron Shahrabani [he], Daniel Mustieles [es], + Khaled Hosny [ar], Fran Diéguez [gl], A S Alam [pa], Piotr Drąg [pl], + Rafael Ferreira [pt_BR], Nilamdyuti Goswami [as], Alexander Shopov [bg], + Matej Urbančič [sl] + +3.7.3 +===== +* Fix maximized windows jumping to other monitors [Alban; #556696] +* Add 'switch-applications' keybinding [Florian; #688913] +* Add a convenience method to focus the default window [Jasper; #689652] +* Increase typical icon size to 96 [Jasper; #689651] +* Port to XInput2 [Jasper; #688779] +* Give dynamic keybindings a keybinding action [Florian; #682315] +* Misc. fixes and cleanups [Jasper, Rui; #688777] + +Contributors: + Alban Crequy, Rui Matos, Florian Müllner, Jasper St. Pierre + +Translations: + Nilamdyuti Goswami [as], Piotr Drąg [pl], Yaron Shahrabani [he], + Dr.T.Vasudevan [ta], ManojKumar Giri [or], Shankar Prasad [kn] + +3.7.2 +===== +* Fix spurious focus changes when showing desktop [Florian; #686928] +* MetaPluginManager: don't send events to Clutter twice [Owen; #686406] +* Add the ability to add shader hooks to MetaBackgroundActor [Giovanni; #669798] +* Only process keyboard mapping events for the core X keyboard [Rui; #674859] +* Import keybinding files from Metacity [Florian; #687672] +* Add compositor hook to process keybindings selectively [Florian; #688202] +* MetaBackgroundActor: add a setter for GLSL uniforms [Giovanni; #682536] +* Misc. fixes and cleanups [Jasper, Rui, Florian, Rico; #688182] + +Contributors: + Giovanni Campagna, Rui Matos, Florian Müllner, Jasper St. Pierre, + Owen Taylor, Rico Tzschichholz + +Translations: + Rafael Ferreira [pt_BR], Tobias Endrigkeit [de], Yaron Shahrabani [he] + +3.7.1 +===== +* screen: Ignore num-workspaces when using dynamic workspaces [Florian; #685439] + +Contributors: + Florian Müllner + +Translations: + Mattias Põldaru [et], Kjartan Maraas [nb], Мирослав Николић [sr, sr@latin], + Marek Černocký [cs], Andika Triwidada [id], Daniel Mustieles [es], + Fran Diéguez [gl], Matej Urbančič [sl] + +3.6.1 +===== +* Fix crash when opening large popup menus [Jasper; #681676] +* window: Don't move the desktop window after monitor hotplug [Jasper; #681159] +* Expose MetaPlugin to introspection [Evan; #671098] +* Optionally delay focus changes in focus-follows-mouse mode [Florian; #678169] +* Resize the guard window when the X screen is resized [Benjamin; #670396] +* display: Only manage the default X screen [Jürg; #648156] +* Misc cleanups: [Owen; #587255] + +Contributors: + Benjamin Berg, Jürg Billeter, Evan Broder, Florian Müllner, Jasper St. Pierre, + Owen Taylor + +Translations: + Alexandre Franke [fr], Theppitak Karoonboonyanan [th], Sayak Sarkar [bn_IN], + Sandeep Sheshrao Shedmake [mr], Ask H. Larsen [da], Shankar Prasad [kn], + Alexander Shopov [bg], Aurimas Černius [lt], Ihar Hrachyshka [be], + Kjartan Maraas [nb], Daniel Mustieles [es], Changwoo Ryu [ko], + Yuri Myasoedov [ru], Tom Tryfonidis [el], RÅ«dolfs Mazurs [lv], + Chris Leonard [en_GB], Piotr Drąg [pl], Fran Diéguez [gl], Gil Forcada [ca], + Matej Urbančič [sl], Andika Triwidada [id], Carles Ferrando [ca] + +3.6.0 +===== + +Translations: + Alexander Shopov [bg], Daniel Korostil [uk], Rajesh Ranjan [hi], + Krishnababu Krothapalli [te], Ani Peter [ml], RÅ«dolfs Mazurs [lv], + Sweta Kothari [gu], Ihar Hrachyshka [be], Noriko Mizumoto [ja], + Timo Jyrinki [fi], Mattias Põldaru [et] + +3.5.92 +====== +* screen: Allow NULL out arguments in meta_screen_get_size [Tomeu] +* display: Add API to set wm_name / wm_keybindings [Florian; #671010] +* Improve the not responding dialog [Jon, Florian; #684306] +* Misc. bugfixes [Jasper] + +Contributors: + William Jon McCann, Florian Müllner, Jasper St. Pierre, Tomeu Vizoso + +Translations: + Gabor Kelemen [hu], Piotr Drąg [pl], Dr.T.Vasudevan [ta], Bruce Cowan [en_GB], + Alexandre Franke [fr], Theppitak Karoonboonyanan [th], Gil Forcada [ca], + Carles Ferrando [ca@valencia], Tobias Endrigkeit [de], Tom Tryfonidis [el], + Nguyễn Thái Ngọc Duy [vi], Changwoo Ryu [ko], Ask H. Larsen [da], + Rafael Ferreira [pt_BR], Marek Černocký [cs] + +3.5.91 +====== +* Do not include markup in app not responding dialog [Alex] +* Fix subtracting unredirected windows from visible region [Jasper; #677116] +* Minor improvements and bugfixes [Jasper, Florian; #682648, #682993] + +Contributors: + Alexander Larsson, Florian Müllner, Jasper St. Pierre + +Translations: + Dirgita [id], Piotr Drąg [pl], A S Alam [pa], Yuri Myasoedov [ru], + Milo Casagrande [it], Nilamdyuti Goswami [as], Tom Tryfonidis [el], + Duarte Loreto [pt], Fran Diéguez [gl], Nguyễn Thái Ngọc Duy [vi], + Aurimas Černius [lt], Daniel Nylander [sv] + +3.5.90 +====== +* Fix logic for handling translations of the windows group [Owen; #681221] +* Handle painting inside a Clutter clone [Owen; #681953] +* Update overlay-key on settings changes [Florian; #681906] +* Add keybinding for overlay-key [Florian; #665547] +* Minor fixes and improvements [Javier, Florian] + +Contributors: + Javier Jardón, Florian Müllner, Owen Taylor + +Translations: + Sweta Kothari [gu], Muhammet Kara [tr], Khaled Hosny [ar], + Sandeep Sheshrao Shedmake [mr] + +3.5.5 +===== +* Fix flickering around windows when using window group [Tom; #681221] + +Contributor(s): + Tom Beckmann + +Translations: + Chao-Hsiung Liao [zh_HK, zh_TW], Matej Urbančič [sl], Fran Diéguez [gl], + Мирослав Николић [sr, sr@latin], Yaron Shahrabani [he], Kjartan Maraas [nb] + +3.5.4 +===== +* Make it possible to reimplement move-to-workspace keybindings from plugins + [Giovanni; #674104] +* Add a preference to ignore hide-titlebar-when-maximized hint [Rico; #678947] +* window: Also use hide-titlebar-when-maximized when tiled [Florian; #679290] +* Center modal dialogs on their parent instead [Florian; #674499] +* Reduce amount of markup in translated messages [Matthias; #679660] +* Fix focus problem after closing a window with focus-follows-mouse + [Jasper; #675982] +* Handle changes of the attach-modal-dialogs preference [Florian; #679904] +* Do not restore tiling on unmaximize [Florian; #677565] +* Misc. fixes and cleanups [Jasper Adriaanse, Jasper, Debarshi, Pavel; + #679153, 673824] + +Contributors: + Jasper Lievisse Adriaanse, Giovanni Campagna, Matthias Clasen, Florian Müllner, + Debarshi Ray, Jasper St. Pierre, Rico Tzschichholz, Pavel Vasin + +Translations: + Alexander Shopov [bg], Kjartan Maraas [nb], Yaron Shahrabani [he], + Nilamdyuti Goswami [as], Ihar Hrachyshka [be], Daniel Mustieles [es] + +3.5.3 +===== +* Simplify plugin system [Jasper; #676855] +* meta-window-actor: Don't unredirect shaped windows [Jasper; #677657] +* screen: Add new public meta_screen_get_current_monitor API [Tim; #642591] +* frames: Increase the size of resize corners [Jasper; #677669] +* window: Make some window methods public [Jasper; #678126] +* Fix crash when running mutter stand-alone [Jasper; #678238] +* meta-window-actor: Fix potential crash in shaping code [Jasper; #677977] +* Misc. fixes [Jasper, Marc-Antoine, Rico] + +Contributors: + Tim L, Marc-Antoine Perennou, Jasper St. Pierre, Rico Tzschichholz + +Translations: + + Daniel Mustieles [es], Matej Urbančič [sl], Khaled Hosny [ar], + Bruno Brouard [fr], Fran Diéguez [gl] + +3.5.2 +===== +* keybindings: Remove 'toggle-recording' binding [Florian; #674376] +* Switch to gtk-doc syntax [Jasper; #673752] +* shaped-texture: never slice shape mask texture [Robert; #674731] +* Make Mutter stop relying on Cogl including a GL header [Neil; #672711] +* Make support for "XFree86" Xinerama mandatory [Owen; #674727] +* meta_window_move_frame(): fix crash when frame is NULL [Owen; #675254] +* Fix memory leaks [Pavel; #672640] +* Code cleanups [Jasper; #671104 #674876 #676052] +* Look for themes in XDG user data dir [Jasper; #675316] +* Remove frame pixel caching [Jasper; #675111] +* stack: Ignore keep-on-top property on maximized windows [Florian; #673581] +* Misc. fixes [Javier, Jasper, Owen, Rico] + +Contributors: + Robert Bragg, Javier Járdon, Florian Müllner, Neil Roberts, Jasper St. Pierre, + Owen Taylor, Rico Tzschichholz, Pavel Vasin + +Translations: + Praveen Illa [te], Luca Ferretti [it], Daniel Mustieles [es] + +3.4.1 +===== +* API change: the meta_display_add_keybinding() function added in 3.4 + wasn't usable from a GNOME Shell extension, so has been changed to take + a GSettings object rather than the name of a schema [Jasper; #673014] +* Don't try to auto-maximize not-maximizable windows; this fixes the problem + with the Nautilus desktop window being mis-positioned when enabled + [Owen; #673566] +* Fix a crash in the default plugin (not used in GNOME) [Giovanni; #673809] +* Make the key work when set as the mouse button modifier + [Florian; #662476] + +Contributors: + Giovanni Campagna, Florian Muellner, Jasper St. Pierre, Owen Taylor + +Translations: + Khaled Hosny [ar], Jordi Serratosa [ca], Carles Ferrando [ca@valencia], + Christian Kirbach [de], Kristjan Schmidt [eo], Arash Mousavi [fa], + Jiro Matsuzawa [ja], Shankar Prasad [kn], Aurimas Černius [lt], + Yinghua Wang [zh_CN] + +3.4.0 +===== +* Fix crash when a full-screen window is opened [Jasper; #672797] +* Fix memory leaks [Pavel; #672640] + +Contributors: + Jasper St. Pierre, Pavel Vasin + +Translations: + Marek Černocký, Petr Kovar [cz], Bruno Brouard [fr], Sweta Kothari [gu], + Yaron Shahrabani [he], Changwoo Ryu [kr], Enrico Nicoletto [pt_BR], + Yuri Myasoedov [ru], Muhammet Kara [tr], Nguyễn Thái Ngọc Duy [vi] + +3.3.92 +====== +* Automaximize large windows on map [Adel; #671677] +* When unmaximizing windows, make sure the unminimized size + is signficantly less than the maximized size [Adel; #671677] +* Don't offer maximize option for windows larger than the screen + [Jasper; #643606] +* Always focus the window immediately underneath without restacking + when closing a window [Jasper; #620744] +* Avoid drawing shadows when two windows are tiled together [Rui; #643075] +* Remove tooltips for window decorations [Florian; #645101] +* Add org.gnome.mutter.dynamic-workspaces GSetting - when this is set + to true, workspace counts are never saved to GSettings, avoiding + pointless disk traffic for GNOME dynamic workspaces [Florian; #671568] +* Add ::grab-op-begin, ::grab-op-end signals to MetaDisplay [Jasper; #670658] +* Add meta_display_get_ignored_modifier_mask() [Florian; #665215] +* Remove pointless wrapper methods on MetaPlugin [Jasper; #671103] +* Fix frame drawing with 3.3.x GTK+ releases [Florian; #671796] +* Build fixes [Jasper, Rico, Rui] +* Misc bug fixes [Damien, Jasper, Lionel, Marius, Owen, Rui; + #661256, #667437, #671601, #671087, #672374] + +Contributors: + Stefano Facchini, Adel Gadllah, Lionel Landwerlin, Mariusz Libera, + Rui Matos, Florian Müllner, Jasper St. Pierre, Damien Radtke, Owen Taylor, + Rico Tzschichholz + +Translations: + Nilamdyuti Goswami [as], Ihar Hrachyshka [be], Alexander Shopov [bg], + David Planella [ca], Carles Ferrando [ca@valencia], Kenneth Nielsen [dk], + Bruce Cowan [en_GB], Daniel Mustieles [es], Mattias Põldaru [et], + Inaki Larranaga Murgoitio [eu], Timo Jyrinki [fi], Fran Diéguez [gl], + Gabor Kelemen [hu], Changwoo Ryu [ko], Anita Reitere [lv], + Kjartan Maraas [nb], Wouter Bolsterlee [nl], A S Alam [pa], Piotr Drąg [pl], + Duarte Loreto [pt], Yuri Myasoedov [ru], Daniel Nylander [se], + Matej Urbančič [sl], Miroslav Nikolić [sr], Tirumurti Vasudevan [ta], + Sasi Bhushan [te], Daniel Korostil [uk], Nguyễn Thái Ngọc Duy [vi], + YunQiang Su [zh_CN], Chao-Hsiung Liao [zh_HK, zh_TW] + +3.3.90 +====== +* Update for Cogl API changes [Robert] +* Bug fixes [Adel, Jasper; #659643] +* Build fixes [Jasper, Owen] + +Contributors: + Robert Bragg, Adel Gadllah, Jasper St. Pierre, Owen Taylor + +Translations: + Ask H. Larsen [dk], Miroslav Nikolić [sr] + +3.3.5 +===== +* MetaShapedTexture no longer is a ClutterTexture subclass [Jasper; #660941] +* Add meta_shaped_texture_get_image() [Jasper; #660941] +* Cleanups [Rui, Jasper; #657639] +* Depend on GTK+ 3.3.7 [Rico] + +Contributors: + Rui Matos, Jasper St. Pierre, Rico Tzschichholz + +Translations: + Kjartan Maraas [nb], Chao-Hsiung Liao [zh_HK, zh_TW] + +3.3.4 +===== +* Adapt to changes in GtkStateFlags [Owen] +* Redo properties for applications menu corresponding to GTK+ changes - + they are now _GTK_* not DBUS_*. [Ryan] +* Fix crash on gnome-shell restart when a modal dialog is open [Owen; #668299] +* Code cleanup [Florian; #666039] + +Contributors: + Ryan Lortie, Florian Müllner, Owen Taylor + +Translations: + Alexander Shopov [bg], Fran Diéguez [gl] + +3.3.3 +===== +* Add keybindings for tiling to left or right [Florian; #648700] +* Support GTK+'s hide-titlebar-when-maximized hint [Florian; #665617] +* Load _DBUS_APPLICATION_ID, _DBUS_UNIQUE_NAME, _DBUS_OBJECT_PATH + property [Colin, Ryan; #664851] +* Handle changes to workspaces-only-on-primary GSetting [Florian; #664853] +* Don't use the Clutter default stage [Jasper; #664028] +* Fix compilation with --disable-introspection [Lionel; #661871] +* Fix problem where stage could end up mis-sized on startup with + multiple monitors [Lionel] +* Misc bug fixes [Adel, Lionel, Jasper; #666015] + +Contributors: + Adel Gadllah, Lionel Landwerlin, Florian Müllner, Jasper St. Pierre + +Translations: + Daniel Mustieles [es], Yaron Shahrabani [he], Kjartan Maraas [nb], + Matej Urbančič [sk], Muhammet Kara [tr] + +3.3.2 +===== + +* Move from GConf to GSettings for preferences [Florian; #635378] +* Add meta_display_add_keybinding()/meta_display_remove_keybinding() + to allow creating new keybindings at runtime [Florian; #663428] +* Add suport for new _NET_WM_STATE_FOCUSED atom in _NET_WM_STATE + to allow applications to draw unfocused windows differently + [Rui; #661427] +* Add meta_window_move_resize_frame() to allow specifying the + size and position of a window via the outside dimensions of the + window frame. +* Don't activate window tiling when moving in snap mode + [Rui; #662270] +* Remove the ability to resize a window from the inner edge of + the titlebar [Jasper; #660129] +* Fix for deprecations in GTK+ [Jasper, Rico; #662574, #662895] +* Misc bug fixes [Jasper, Rico, Rui; #662895, #642652, #660941, #662225] + +Contributors: + Tim Cuthbertson, Rui Matos, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz + +Translations: + Jorge González (es), Kjartan Maraas (nb), Krishnababu Krothapalli (te), Nguyễn Thái Ngọc Duy (vi) + +3.2.1 +===== +* Allow keyboard window switching (alt-Tab) during drag-and-drop + [Matthias, #660457] +* Don't add invisible resize borders to fullscreen windows + [Jasper, Owen; #659854] +* Fix crash when toplevel windows were set to unexpected window types + [Owen; #599988] +* Correct problems with windows moving when restarting or switching + window managers [Jasper; #660848] +* Fix interaction of tiled windows with multiple monitors + [Rui; #642580, #657519] +* Make meta_display_unmanage_screen() public [Jasper; #660848] +* Fix problem with turning off window decorations on the fly [Rui; #660773] +* Fix spurious assertion failures with themes such as Nodoka [Sandro; #661286] +* Misc bug fixes [Adel, Jasper, Rui; #660464, #660854, #662053] + +Contributors: + Matthias Clasen, Sandro Mani, Rui Matos, Jasper St. Pierre, Owen Taylor + +Translations: + Tommi Vainikainen [fi], Miroslav Nikolić [sr, sr@latin], Muhammet Kara [tr] + +3.2.0 +===== +* Fix _NET_WM_FRAME_EXTENTS not to include invisible borders [Jasper; #659848] +* Fix application-specified window placement (-geometry) for + invisible borders [Jasper; #659848] + +Contributors: + Jasper St. Pierre + +Translations: + Nilamdyuti Goswami [as], Carles Ferrando [ca@valencia], Petr Kovar [cz], + Mario Blättermann [de], Inaki Larranaga [eu], Gabor Kelemen [hu], + Takayoshi Okano [ja], Changwoo Ryu [ko], Djavan Fagundes [pt_BR] + +3.1.92 +====== +* Fix bug with unredirecting full-screen windows on multi-monitor - + notably affected gnome-screensaver [Adel; #657869] +* Disable top resizing of attached dialogs [Jasper; #657795] +* Code cleanup [Jasper, Rui] +* Misc bug fixes [Adel, Florian, Jasper, Rui; + #658069, #659266, #659523, #659477] + +Contributors: + Adel Gadllah, Rui Matos, Florian Müllner, Jasper St. Pierre + +Translations: + Joan Duran [ca], Joe Hansen [dk], Jiro Matsuzawa [ja], Daniel Korostil [uk] + +3.1.91.1 +======== +* Fix problem where certain application updates would get lost [#657071, Owen] +* Fix a problem where after resuming from the screensaver, things got + slow [#658228, Jasper, Adel] +* When a monitor is plugged or unplugged, keep existing windows on their + current monitor [#645408, Alex] +* Remove 'Mutter' title from alerts such as + "The widow '%s' is not responding" [Matthias] +* Remove pointless warning: + Received a _NET_WM_MOVERESIZE message for %s; these + messages lack timestamps and therefore suck. + [Rui] +* Misc bug fixes [Jasper] +* Build fixes [Javier] + +Contributors: + Matthias Clasen, Adel Gadllah, Javier Jardón, Alex Larsson, Rui Matos, + Jasper St. Pierre, Owen Taylor + +Translations: + Ihar Hrachyshka [be], Bruce Cowan [en_FB], Daniel Mustieles [es], + Claude Paroz [fr], Andika Triwidada [id], Luca Ferretti [it], + Rudolfs Mazurs [lt], Piotr Drąg [pl], Duarte Loreto [pt], + Matej Urbančič [sl], Tirumurti Vasudevan [ta], Chao-Hsiung Liao [zh_KH, TW] + +3.1.90.1 +======== +* Fix crash when no windows are open [Adel; #657692] +* Fix annotations for new strictness in gobject-introspection [Jasper, Owen] +* Fix some errors with rounded frame drawing [Jasper; #657661] + +Contributors: + Adel Gadllah, Jasper St. Pierre, Owen Taylor + +3.1.90 +====== +* Extend the draggable portion of window borders outside the visible frame + for easy resizing with thin borders. (New draggable_border_width GConf key + controls the total width of visible and invisible borders.) + [Jasper; #644930] +* Draw rounded window corners with antialising [Jasper; #628195] +* Unredirect override-redirect fullscreen windows, such as full-screen + 3D games to avoid any performance impact [Adel; #597014] +* Add :resizable and :above properties to MetaWindow. [Tim; #653858] +* Add MUTTER_DISABLE_FALLBACK_COLOR environment variable to allow visualizing + places where a color is missing for gtk:custom() colors [Florian; #656112] +* Don't attach modal dialogs to special windows like the desktop; + add meta_window_is_attached_dialog() [Dan, #646761] +* Make MetaBackgroundActor public, allow creating multiple instances + (sharing a common texture), and add a :dim-factor property + [Rui, Owen; #656433] +* Fix attached dialogs to not be resizable from the top and to be + position correctly [Jasper; #656619] +* Misc bug fixes [Jasper, Rui; #656335, #657583] + +Contributors: + Tim Cuthbertson, Adel Gadllah, Rui Matos, Florian Müllner, Jasper St. Pierre, + Owen Taylor, Dan Winship + +Translations: + Alexander Shopov [bg], Jorge González [es], Fran Dieguez [gl], + Yaron Shahrabani [he], Takeshi Aihana [ja], Aurimas Černius [lt], + Kjartan Maraas [nb], A S Alam [pa], Yuri Kozlov [ru], Daniel Nylander [se], + Theppitak Karoonboonyanan [th], Abduxukur Abdurixit [ug], Aron Xu [zh_CN] + +3.1.4 +===== +* Use better, much more subtle shadow definitions [Jakub; #649374] +* Add the ability to use named GTK+ colors in theme files as + gtk:custom(name,fallback) [Florian; #648709] +* Port from GdkColor to GdkRGBA and from GtkStyle to GtkStyleContext + [Florian; #650586] +* Try to fix window bindings using the Super key [Owen; #624869] +* Update to using more modern Cogl and Clutter APIs + [Adel, Emmanuele, Neil; #654551 #654729 #654730 #655064] +* Fix for srcdir != builddir builds [Thierry; #624910] +* Make handling of focus appearance for attached dialogs more robust + [Dan; #647712] +* Misc bug fixes + [Dan, Florian, Jasper, Owen, Rui; #642957 #649374 #650661 #654489 #654539] + +Contributors: + Emmanuele Bassi, Adel Gadllah, Rui Matos, Florian Müllner, Neil Roberts, + Jasper St. Pierre, Jakub Steiner, Owen Taylor + +Translations: + Ihar Hrachyshka [be], Jorge González, Daniel Mustieles [es], + Fran Dieguez [gl], Yaron Shahrabani [he], Takeshi Aihana [ja], + Kjartan Maraas [nb], Rudolfs Mazurs [lv], Matej Urbančič [sl], + Abduxukur Abdurixit [ug], Nguyễn Thái Ngọc Duy [vi] + +3.1.3.1 +======= +* Back API version down to "3.0" - the change to Meta-3.1.gir + was unintentional [Owen] + +Translations: + Yaron Shahrabani [he], Kjartan Maraas [nb], Muhammet Kara [tr] + +3.1.3 +===== +* Support dark window theme variants for windows with a dark + widget theme; this is selected by the _GTK_THEME_VARIANT + property [Florian, #645355] +* Don't draw a shadow under windows with an alpha-channel - this + fixes transparency for GNOME Terminal [Owen, Jasper; #635268] +* Add a MetaWindow:wm-class property for notification [Jasper; #649315] +* Add a MetaWindow:minimized property for notification [Florian] +* Fix handing of unusual window shapes that Wine was setting + causing some applications to draw wrong [Jasper; #627880] +* Improve replacing another compositor and being replaced: + release compositor selection in the right order and wait for + compositors that get it wrong. [Colin, Owen; #653121] +* Remove behavior where left clicking on a window border with + the titlebar offscreen gave the window menu [Florian; #652369] +* Don't set the global default textdomain, since Mutter is + a library as well as an application [Dan; #649202] +* Exit with the right (success or failure) exit status [Dan] +* Code cleanup [Florian] +* Miscellaneous bug fixes [Owen; #649114, #652507] + +Contributors: + Florian Müllner, Jasper St. Pierre, Owen Taylor, Colin Walters, Dan Winship + +Translations: + Ihar Hrachyshka [be], Daniel Mustieles [es], Yaron Shahrabani [he], + Carles Ferrando [ca@valencia], Takeshi Aihana [ja], Fran Diéguez [gl], + Matej Urbančič [sl], Miroslav Nikolic [sr], Muhammet Kara [tr], + Daniel Korostil [uk] + +3.0.2.1 +======= +* When saving the session, use the "program name" rather than + harcoding mutter, fixing session saving for gnome-shell [Matthias] + https://bugzilla.gnome.org/show_bug.cgi?id=648828 + +Contributors: + Matthias Clasen + +3.0.2 +===== + +* Fix a crash when running without XKB support [Adam] + https://bugzilla.gnome.org/show_bug.cgi?id=647777 +* Fix smallish memory leaks [Colin] + https://bugzilla.gnome.org/show_bug.cgi?id=649500 + https://bugzilla.gnome.org/show_bug.cgi?id=649504 +* Ignore mirrored monitors when listing monitors, fixing + drag-and-drop problems in GNOME Shell [Owen] + https://bugzilla.gnome.org/show_bug.cgi?id=649299 +* Don't allow side-by-side tiling of non-maximizable windows + like dialogs and utility windows [Dan] +* Fix interaction of _NET_WM_WINDOW_OPACITY with window effects, + making it work again with GNOME Shell + https://bugzilla.gnome.org/show_bug.cgi?id=648613 + +Contributors: + Adam Jackson, Colin Walters, Dan Winship + +Translations: + Abduxukur Abdurixit [ug] + +3.0.1 +===== + +* If WM_CLIENT_MACHINE isn't set, don't assume a window is remote; + fixes behavior of Fox toolkit applications under GNOME Shell. + https://bugzilla.gnome.org/show_bug.cgi?id=647662 [Colin] +* Fix cases where windows could get stuck drawing as focused after + an attached modal dialog was closed. [Dan] + https://bugzilla.gnome.org/show_bug.cgi?id=647613 +* Fix a bug where a window that is too big to be tiled side-by-side + would behave strangely when using the gesture of dragging to + the top to maximize. [Florian] + +Contributors: + Florian Müllner, Colin Walters, Dan Winship + +Translations: + Amitakhya Phukan [as], Kristjan Schmidt [eo], Muhammet Kara [tr] + +3.0.0 +===== + +* Avoid crashing when you have a single window and try to move it between + workspaces. [Dan] + https://bugzilla.gnome.org/show_bug.cgi?id=642957 + +Contributors: + Dan Winship + +Translations: + Jordi Serratosa [ca], Petr Kovar [cz], Ask H. Larsen [da], Bruce Cowan [en_GB], + Inaki Larranaga Murgoitio [eu], Gabor Kelemen [hu], Dirgita [id], Shankar Prasad [kn], + Changwoo Ryu [ko], Wouter Bolsterlee [nl], Duarte Loreto [pt], + Antonio Fernandes C. Neto, Rodrigo Padula de Oliveira [pt_BR], T. Vasudevan [ta], + Nguyễn Thái Ngọc Duy [vi], Chao-Hsiung Liao [zh_HK, zh_TW] + +2.91.93 +======= + +* Fix bug where, when a monitor was hot-plugged, all workspaces + would collapse to a single workspace. (There are still issues + when a secondary monitor is hot-plugged to the left of the + primary monitor.) [Alex] + https://bugzilla.gnome.org/show_bug.cgi?id=645408) + +* Fix a crash for the cycle_group action [Jasper] + https://bugzilla.gnome.org/show_bug.cgi?id=645843 + +* Fix misdrawing of window shadows on some focus changes [Dan] + https://bugzilla.gnome.org/show_bug.cgi?id=636904 + +* Export meta_get_replace_current_wm() to allow fixing a + GNOME Shell bug with --replace [Colin] + https://bugzilla.gnome.org/show_bug.cgi?id=645590 + +Contributors: + Alexander Larsson, Jasper St. Pierre, Colin Walters, Dan Winship + +Translations: + Alexander Shopov [bg], Christian Kirbach [de], Yaron Shahrabani [he], + Rudolfs Mazurs [lv], A S Alam [pa], Yuri Myasoedov [ru], Daniel Nylander [se], + Abduxukur Abdurixit [ug], Daniel Korostil [uj], Aron Xu [zh_CN] + +2.91.92 +======= + + * Add a workspaces_only_on_primary preferences. When set, this makes + workspaces switching only apply to windows on the primary monitor, + while windows on other monitors are unaffected. + * Export API for monitor handling [Alex] + MetaScreen::monitors-changed signal + meta_screen_get_primary_monitor() + meta_window_is_on_primary_monitor() + meta_window_get_monitor() + MetaWindow::window-entered-monitor, Above_Tab from being a cycle_group binding to + a switch_group binding [Rui] + * Make plugin-loading failure fatal [Colin] + * Add 'position-changed' signal to MetaWindowActor [Owen] + * When 'live_hidden_previews' is enabled, position hidden windows + to allow the creation of workspace previews [Owen] + * Fix bug with opacity of MetaBackgroundActor + +Contributors: + Rui Matos, Owen Taylor, Colin Walters + +Translations: + Jorge González [es], Mattias Põldaru [et], Sweta Kothari [gu], Luca Ferretti [it], + Changwoo Ryu [ko], Nguyễn Thái Ngọc Duy [vi] + +Bugs fixed: + 641309 When live_hidden_previews is set, force placement for hidden windows + 641310 MetaWindowActor: Add a 'positioned-changed' signal + 641979 Visual glitch on workspace selector closing overview mode + 641384 Make plugin loading failure fatal + 642426 Don't pass handled key events to GTK+ + +2.91.6 +====== + + * Add meta_screen_override_window_layout() to let a plugin set the workspace + layout [Owen] + * Add a 'size-changed' signal to MetaWindowActor [Florian] + * Add meta_window_actor_is_destroyed() [Adel] + * Fix problems with window tile previews when cancelling a move [Florian] + * Port theme elements that use GTK+ drawing to use GtkStyleContext instead + of the deprecated GtkStyle. [Florian] + * Fix compiler warnings that were causing compilation failures [Jasper, Owen] + * Misc bug fixes [Gabor, Jasper, Owen, Rui] + +Contributors: + Adel Gadllah, Gabor Kelemen, Rui Matos, Florian Müllner, Jasper St. Pierre, + Owen Taylor + +Translations: + Khaled Hosny [ar], Alexander Shopov [bg], Petr Kovar [cz], Fran Diéguez [gl], + Marios Zindilis [gr], Gabor Kelemen [hu], Kjartan Maraas [nb], A S Alam [pa], + Daniel Nylander [se], Chao-Hsiung Liao [zh_HK, zh_TW] + +2.91.5 +====== + +* Add a Above_Tab key symbol that can be used in key bindings to mean + the key above the Tab key. This is now the default binding for + cycle_group in both Mutter and Metacity. [Owen] +* Add new frame states for tiled-on-the-left and tiled-on-the-right [Florian] +* Add new background drawing functions that can be defined in a theme + for single buttons. [Florian] +* Draw the right button backgrounds for all custom button layouts [Florian] +* Remove vestigal --composite/--no-composite command line options [Nickolas] +* Fix building on GLES [Andreas] +* Code cleanups [Adel, Owen] + +Contributors: + Adel Gadllah, Nickolas Lloyd, Andreas Mueller, Florian Müllner, Owen Taylor + +Translations: + Mattias Põldaru, Ivar Smolin [et], Gheyret T. Kenji [ug] + +Bugs fixed: + 613124 Invalid visibility-related asserts in MutterWindow + 626875 Fix handling of --composite and --no-composite command line options + 629282 [PATCH] Fix errors building for gles-systems (clutter-eglx) + 635569 Add an "Above_Tab" pseudo-keysym + 635683 add specific button background for single button (per side) case + 635686 button backgrounds broken with rtl locales + 637330 [PATCH] theme: Add tiled_left/tiled_right frame states + +2.91.4 +====== + +* Update for GTK+ 3 changes [Benjamin, Colin, Emmanuele, Florian] +* Support maximizing a window by dragging to the top of the screen + in the same way you can tile by dragging to the edge of the screen. + [Ray, Florian] +* Misc bug fixes [Milan, Owen] + +Contributors: + Emmanuele Bassi, Milan Bouchet-Valat, Florian Müllner, Benjamin Otte, + Ray Strode, Owen Taylor, Colin Walters + +Translations: + Matej Urbančič [sl], Nguyễn Thái Ngọc Duy [vi] + +Bugs fixed: + 630548 gnome-shell could auto-maximize windows when dragged to top edge of screen + 636083 workspace: Consider text direction when switching + 636301 Port testgradient example to GTK3 + 636302 Replace some GDK X11 calls with future-proof ones + 636491 valgrind: meta_window_shape_new (meta-window-shape.c:79) + 637802 ui: Adapt to GDK API changes + +2.91.3 +====== + +* Better shadows: [Owen] + - Shadows can be different for different window types and focus states + - Shadows are larger by default, especially for the currently active + window + - Shadows for attached modal dialogs and menus are drawn not to + overlap the attachment point. + - Shadows follow the shape of shaped windows + * Optimization: [Owen] + - Avoid repainting in situations when windows are potentially restacked + but aren't actually restacked. + - Pay attention to partial stage repaints in obscured window calculations + - Better optimization of painting obscured shadows; turn off shadows + for maximized windows. + - Move background repainting into Mutter; doing it here rather than + in plugins allows not painting obscured parts of the background. + * A new frame type 'attached' is added for attached modal dialogs + and can be referenced in theme files with a theme version of 3.2. + * Fix updating key bindings when the keyboard layout changes + [Derek, Owen, Thomas] + * Bug fixes [Adel, Florian] + * Build fixes [Dan Williams, Diego, Javier, Owen] + +Contributors: + Adel Gadllah, Javier Jardón, Florian Müllner, Derek Poon, Owen Taylor, + Thomas Thurman, Diego Escalante Urrelo, Dan Williams + +Translations: + Khaled Hosny [ar], Jorge González [es], Fran Diéguez [gl], + Yaron Shahrabani [he], Kjartan Maraas [nb], Gheyret T. Kenji [ug] + +Bugs fixed: + 634779 MetaWindowGroup: further optimize paints by using current scissor + 634833 Draw the root window background + 592382 improve shadow effect + 628199 Add antialising to arc and line drawing operations + 633002 meta-actor-window: Use G_UNLIKELY for TFP check + 634771 MetaStackTracker: Avoid queueing resync for obvious no-ops + 635421 Fix crash in check_needs_shadow + 635493 configure.in: it's git, not Subversion + 635528 configure.ac: move call to AM_GNU_GLIB_GETTEXT above cflags modification + 635575 meta-window-actor: remove unused meta_window_actor_get_shadow_bounds + 636083 workspace: Consider text direction when switching + +2.91.2 +====== + +* Remove support for GTK+ 2 [Florian] +* Adapt to deprecation of size_request deprecation in GTK+ [Matthias] +* Include change from Metacity to fix confusion of mouse + tracking when double-clicking on title bar [Owen] +* Fix bug with the the window menu getting stuck when you alt-Tab [Owen] + +Contributors: + Matthias Clasen, Florian Müllner, Owen Taylor + +Translations: + Petr Kovar [cz] + +Bugs fixed: + 633133 Remove compatibility for GTK+-2.0 + 633352 prepare for the demise of size_request + 633398 Fix check for events on UI widgets + 633401 Fix warning from synthesized events with GdkDevice + +2.91.1 +====== + +* Default build is now GTK+ 3 build +* Mutter namespace prefix is removed, in favor of consistent + meta_ namespace prefixing [Owen]. Naming changes: + MutterWindow => MetaWindowActor + mutter_get_windows => meta_get_window_actors + mutter_plugin_get_windows => meta_plugin_get_window_actors +* Add missing values in MetaKeyBindingAction - this fixes a problem where + key binding lookup wasn't working properly for some key bindings. [Dan] +* Remove keysym parameter to meta_display_get_keybinding_action() - the + function expected the default keysym for the keycode to always be passed [Dan] +* Clean up installed header files - in particular, theme-parser.h is merged + into a new public-only theme.h and private internals are moved to + theme-private.h. +* Fix problems with antialiased rendering of themes [Brandon, Owen, Nickolas] +* Fix problem with parsing color constants in themes [Jon, Owen] +* Build fixes [Colin] +* Miscellaneous bug fixes [Giovanni, Rico] + +Contributors: + Giovanni Campagna, Nickolas Lloyd, William Jon McCann, Owen Taylor, + Rico Tzschichholz, Colin Walters, Dan Winship, Brandon Wright + +Translations: + Fran Diéguez [gl], Yinghua Wang [zh_CN] + +Fixed bugs: + 628401 tint and line draw ops rendering issues + 628520 unfortunate namespacing + 631487 Fix drawing of theme elements + 632116 don't clobber gerrors + 632149 Fill in missing MetaKeyBindingAction values + 632155 meta_display_get_keybinding_action: remove keysym parameter + 632474 Remove MetaRegion + 632494 introspection: remove --allow-unprefixed + +2.91.0 +====== + + * Enable side-by-side tiling via a gesture of dragging to the left or right + edge of the screen. (enabled with an off-by-default GConf key) [Florian] + * Allow breaking out of maximization/tiling using a alt-middle-button window + resize [Owen, Florian] + * Add the ability to have modal dialogs attached to their parent window + (enabled with an off-by-default GConf key) [Maxim] + * Draw with Cairo rather than GDK [Florian, Benjamin] + * Add compatibility for changes in GTK+ 3 + [Benjamin, Alban, Florian, Jasper, Matthias, Owen, Thierry] + - libmutter-private is now only installed for GTK+ 3 builds + - Theme parts of libmutter-private API are changed to take cairo_t + rather than GdkDrawable + * Update introspection build and annotations for new behavior of + g-ir-scanner [Colin] + * Fix bug that caused window menu options not to work [Owen] + * Fix misbehavior of Wine windows [Owen, Alban] + * Fix crashes from missing error traps [Adel] + * Build fixes [Colin, Florian, Owen, Rob, Tomas] + * Misc bug fixes [Adel, Jon, Owen, Nickolas, Tomas] + * Cleanups [Adel, Benjamin, Florian] + +Contributors: + Alban Browaeys, Matthias Clasen, Maxim Ermilov, Tomas Frydrych, Adel Gadllah, + Nickolas Lloyd, William Jon McCann, Florian Muellner, Benjamin Otte, + Thierry Reding, Rob Staudinger, Jasper St. Pierre, Owen Taylor, Colin Walters + +Translations: + Alexander Shopov [bg], Mario Blättermann [de], Ask H. Larsen [dk], + Michael Kotsarinis [el], Philip Withnall [en_UK], Jorge González [es], + Fran Diéguez [gl], Bruno Brouard, Claude Paroz [fr], Yaron Shahrabani [he], + Gabor Kelemen [hu], Luca Ferretti [it], Nils-Christoph Fiedler [nds], + Kjartan Maraas [nb], A S Alam [pa], Piotr Drąg [pl], Duarte Loreto [pt], + Antonio Fernandes C. Neto [pt_BR], Matej Urbančič [sl], + MiloÅ¡ Popović [sr, sr@latin], Tirumurti Vasudevan [ta], Aron Xu [zh_CN], + Chao-Hsiung Liao [zh_HK, zh_TW] + +Fixed Bugs: + 597763 With >2 workspaces, Window menu "Move to Another Workspace" menu doesn't work + 598603 displays window size when moving terminal window + 606158 "Always on top" triggers Window manager warning: + Log level 8: meta_window_set_user_time: assertion `!window->override_redirect' failed + 610575 make meta_screen_set_cursor public + 613126 Do not cancel Alt+Tab grab due to Shift key events + 623235 BadDamage error from XSubtractDamage + 624757 Check for TFP usage after actually setting the pixmap + 625712 [mutter-shaped-texture] Remove material_workaround + 626583 Replace Gdk drawing API with cairo + 627087 Mipmap emulation not working + 627210 Crash with X error + 628544 introspection: Build with --warn-fatal, drop fix-meta-rectangle.py hack + 629127 build problem with recent gtk3 + 629232 Multiple syntax errors in file mutter-message.c when building Mutter for + GNOME Shell dependencies + 629350 [mutter-shaped-texture] Use a base material for all instances + 629931 Allow breaking out from maximization/tiling during a mouse resize + 630195 Use GDK error trapping straight-up + 630203 Prepare mutter code for GTK3 rendering-cleanup + 630671 prepare mutter for the demise of GtkObject + 630843 gtk_window_set_visual was replaced by gtk_widget_set_visua + 631147 Adapt to GTK API changes + 631175 Mutter error compiling Gnome Shell + +2.31.5 +====== + +* Support building with GTK+ 3.0 [Florian] +* Remove deprecated usages for compatibility with GTK+ 3.0 + [Claudio, Florian, Nickolas] +* Export a boxed type for MetaRectangle [Owen] +* Allow disabling -Werror with --enable-compile-warnings=yes [Nickolas] +* Build fixes [Andreas, Florian, Owen] + +Contributors: + Nickolas Lloyd, Andreas Mueller, Florian Müllner, Claudio Saavedra, + Owen Taylor + +Translations: + Petr Kovar [cz], Jorge González [es], Fran Diéguez [gl], + Yaron Shahrabani [he], Matej Urbančič [sl] + +Fixed Bugs: + 587991 - Remove deprecated GTK+ symbols + 616275 - -Werror should not be enabled by default (or should be possible to disable) + 622303 - Allow building with Gtk+-3.0 + 622800 - Make mutter more gtk+ 3.0 friendly + 623335 - Make MetaRectangle a boxed type + 623639 - Work around g-ir-scanner problem with Gdk.Rectangle + 624166 - src/core/util.c: Fix warning in case WITH_VERBOSE_MODE is not set + +2.31.4 +====== + +* Clean up MutterPlugin effect interface [Maxim] +* Track damage as the bounding box, a significant optimizations + for rapidly drawing clients [Robert] +* Add meta_window_is_remote() [Colin] +* Add meta_add_debug_topic() for turning on logging of + specific topics [Colin] +* Fix bug with window unmaximization [Owen] + +Contributors: + Robert Bragg, Maxim Ermilov, Owen Taylor, Colin Walters + +Translations: + Yaron Shahrabani (he), Fran Diéguez (gl), Kjartan Maraas (nb), A S Alam (pa) + +Fixed Bugs: + 611838 - expose sub-stage redraws by streaming raw updates to ClutterX11TexturePixmap + 620585 - Add meta_window_is_remote + 620860 - function ‘meta_display_open’ + 621082 - MutterPluginManager should call plugin->switch_workspace, + when screen doesn't have any window. Or function should be renamed. + 621413 - Maximize/Unmaximize not behaving properly for some non-gnome based programs + +2.31.2 +====== + +* Theme enhancements [Owen] + - Add a flexible version mechanism for themes - + metacity-theme-3.xml is now supported, and can include + version="> 3.2" type attributes on the root element or + any subelement. + - Add frame_x_center/frame_y_center variables + - Allow a theme to turn on title ellipsization +* Performance enhancements: + - Stream raw damage updates to ClutterX11TexturePixmap + to enable partial stage updates when windos change [Robert] + - Don't trap XErrors in meta_compositor_process_event [Adel] +* Add meta_prefs_override_preference_location(); this allows + a plugin like GNOME Shell to redirect preferences to a + plugin-specific location. [Owen] +* Support a _MUTTER_HINTS window property; this is a string + property holding key-value pairs with plugin-specific + interpretation [Tomas] +* Build with GSEAL_ENABLE [Florian, Javier] +* Add meta_display_get_leader_window() [Tomas] +* Add meta_display_sort_windows_by_stacking [Colin] +* Export + meta_display_get_last_user_time() + meta_display_xserver_time_is_before() + meta_window_foreach_ancestor(), + meta_window_foreach_transient() + meta_window_lower() + meta_window_raise() + meta_window_set_demands_attention() + meta_window_unset_demands_attention() [Colin] +* Bug fixes [Dan, Edward, Owen, Tomas] +* Build fixes [Owen, Dominique, Vincent] + +Contributors: + Robert Bragg, Adel Gadllah, Tomas Frydrych, Javier Jardón, + Dominique Leuenberger, Florian Müllner, Edward Sheldrake, + Owen Taylor, Vincent Untz, Colin Walters, Dan Winship + +Translations: + Xandru Armesto Fernandez (ast), Khaled Hosny (ar), Petr Kovar (cz), + Mario Blättermann, (de), Jorge González (es), + Inaki Larranaga Murgoitio [eu), Claude Paroz (fr), Luca Ferretti (it), + Gintautas Miliauskas (lt), Pavol Å imo (sk), Matej Urbančič (sl) + +Fixed Bugs: + 591842 - ellipsize titles when oversize + 592503 - Add a flexible version mechanism + 595496 - Use accessor functions instead direct access (use GSEAL GnomeGoal) + 596659 - Fix handling of grabbed key events + 613123 - Framework for plugin-specific per-window hint + 613125 - Add meta_display_get_leader_window() + 613127 - Keep num_workspaces key in sync with the actual workspace number + 613136 - remove over-restrictive assert from meta_prefs_get_workspace_name() + 613398 - Don't trap XErrors in meta_compositor_process_event + 615586 - Allow redirecting preferences to a different GConf key + 615672 - cant' compile mutter error: dereferencing pointer ‘p’ does break + strict-aliasing rules + 616050 - alt-tab infrastructure patches + 616274 - mutter from git fails with gcc 4.5 (on new warning) + 616546 - On dual screen maximized windows dragged to the second screen no + longer update their contents + 618138 - Work around COGL bug causing flash for new windows + 618613 - Fix crash with --sync option + +2.29.1 +====== + +* Support and require Clutter 1.2 (Owen) +* Add meta_display_get_keybinding_action() (Colin, Dan) +* Add meta_window_get_wm_class_instance() (Tomas) +* Remove workaround for bug fixed in intel driver Q2/2009 release (Robert) +* Build fixes (Owen, Brian, Nguyễn Thái Ngọc Duy) + +Contributors: + Robert Bragg, Brian Cameron, Tomas Frydrych, Nguyễn Thái Ngọc Duy, + Owen Taylor, Colin Walters, Dan Winship + +Translations: + Alexander Shopov (bg), Mario Blättermann (de), Bruno Brouard (fr), + Nils-Christoph Fiedler (nds), Piotr Drąg (pl), Aron Xu (zh_CN) + +Fixed Bugs: + + 610862 Support and require Clutter 1.1 + 612506 mutter 2.29.0 fails to compile on Solaris + 613100 [MetaDisplay] Expose meta_display_get_keybinding_action + 613121 Remove workaround for multitexturing with old intel drivers + 613128 [MetaWindow] Accessor for the instance part of WM_CLASS property + 613278 meta_display_get_keybinding_action: strip out uninteresting modifiers + +2.29.0 +====== + +* Improve appearance of scaled down windows using mipmap emulation (Owen) +* Added signals: MetaDisplay::window-created, MetaDisplay::window-marked-urgent, + MetaDisplay::window-demands-attention, MetaWindow::unmanaged (Colin, Tomas) +* Added properties: MetaWindow:demands-attention, MetaWindow:urgent, + MetaWindow:maximized-horizontally, MetaWindow:maximized-vertically (Florian, Tomas) +* Fix nasty crash when workspace "struts" changed during a window move (Jon, Owen) +* Bug fixes (Dan, Maxim, Neil, Owen, Tomas) +* Build fixes (Colin, Emmanuele, Nickolas, Owen, Richard) +* Merge Metacity changes since 2.26. Includes themable sound support + via libcanberra (Owen) + +Contributors + Emmanuele Bassi, Maxim Ermilov, Tomas Frydrych, Richard Hughes, Nickolas Lloyd, + Florian Müllner, Jon Nettleton, Neil Roberts, Owen Taylor, Colin Walters, + Dan Winship + +Additional Metacity contributors: + Thomas Hindoe Paaboel Andersen, Peter Bloomfield, Matthias Clasen, + Matt Kraai, Claude Paroz, Lennart Poettering, Ray Strode, Thomas Thurman, + Vincent Untz, Tomislav Vujec, Tomeu Vizoso, Travis Watkins, 'alexisdm59' + +Translations: + Khaled Hosny (ar), Petr Kovar (cz), Kjartan Maraas (nb), Djavan Fagundes (pt_BR), + Nils-Christoph Fiedler (nds), Matej Urbančič (sl), Vincent Untz + +Fixed Bugs: + + 588065 Adds demands-attention signal to the window class + 591913 Fails to skip current window on alt+tab when another window is asking for attention + 592567 Dereferencing NULL in mutter_window_get_workspace() + 597052 Add signal to MetaDisplay so we know when a window has demanded-attention + 598289 Add "window-created" signal to MetaDisplay, "unmanaged" signal for MetaWindow + 598473 "XXX specified twice for this theme" messages not in sync with metacity. + 598600 "Visual Bell" option in Metacity causes Mutter to crash + 600068 notifications for window urgency hint + 601228 rdesktop does not get keypress signals + 602349 [PATCH] trivial - fix compilation warning in mutter + 602740 Remove XOR gc only used in removed reduced-resources mode + 602870 Fix compilation with older libGL + 604200 Compile issue: Use of deprecated clutter functions + 606388 mutter fails to build when using ld with --no-add-needed + 607125 Fails to build with latest introspection data + 607398 Do not use CGL_* symbols + 607746 reduce gconf roundtrips at startup + 608800 alt-dragging gimp windows crashes gnome-shell + 609350 Mutter does not support the COGL_DEBUG environment variable + 609546 meta_workspace_set_builtin_struts(): optimize out non-changes + 609585 Merge libcanberra usage from Metacity + 609657 Use cogl multitexture API when drawing MutterShapedTexture + 609665 Bug fixes from Fedora RPM + 609710 screencast recording broke + 610391 Fix crash on startup with list bindings + +2.28.0 +====== + +* New exported API: + meta_window_get_stable_sequence() [Colin] + meta_window_get_transient_for_as_xid() [Tomas] + MutterScreen::workareas-changed signal [Tomas] +* Fix a problem where changes processed from a Clutter event + callback wouldn't get handled before the screen was next + repainted, causing flashing [Owen] +* Remove MetaAltTabHandler as no longer needed [Dan] +* Bug fixes [Colin, Owen] + +Contributors: + Tomas Frydrych, Owen Taylor, Colin Walters, Dan Winship + +Translations: + Christian Kirbach (de), Claude Paroz (fr) + +2.27.5 +====== + + * Fix bug in GConf schemas where the overview activation key was specified as + '' not 'Super_L'. + +Contributors: + + Colin Walters + +Translation: + + Denis Arnaud (br) + +2.27.4 +====== + +* Big code cleanup: when talking about multiple monitors, call them + "monitors", not "xineramas". [Dan] + +* Accessors added or made public: + + meta_screen_get_n_monitors(), meta_screen_get_monitor_geometry() + meta_window_get_user_time() and MetaWindow:user-time property. + + [Colin, Dan] + +* Set _GNOME_WM_KEYBINDINGS=Metacity,Mutter on the _NET_SUPPORTING_WM_CHECK + window so that gnome-keybinding-properties can figure out to show the + Metacity keybindings when Mutter is running. [Owen] + +* Bug and build fixes [Colin, Owen] + +Contributors: + + Owen Taylor, Colin Walters, Dan Winship + +Translation: + + Jorge González (es), Inaki Larranaga Murgoitio (eu), Gabor Kelemen (hu) + +Bugs fixed: + + 592393 - Clicking on a minimized window in the overview doesn't focus the window + 593399 - Add meta_display_get_grab_op() + 593404 - Make MUTTER_DEBUG_XINERAMA override active Xinerama + 593407 - Add 'skip-taskbar' accessor to MetaWindow. + 593686 - Add meta_screen_get_monitors() + 594067 - Export a _GNOME_WM_KEYBINDINGS property + +2.27.3 +====== + +* Key handling improvements: + + - enforce that every key is handled no more than once. + - mutter_plugin_begin_modal() and mutter_plugin_begin_modal() allow + putting a plugin into a "modal" state where it has exclusive access + to key and pointer events. + - Add "tab_popup_select", "tab_pop_cancel" pseudo-keypress-handlers + that plugins can use to get notification when Alt-Tab ends + + [Owen] + +* Accessors added or made public: + + meta_window_is_override_redirect(), meta_window_is_mapped(), + meta_display_xwindow_is_a_no_focus_window(), + meta_display_get_grab_op(), meta_window_is_skip_taskbar(), + meta_window_is_modal(), all of errors.h + + [Colin, Owen, Michael, Steve, Tomas] + +* Fix for various GTK+ deprecations [Javier] +* Bug fixes [Colin, Frédéric, Owen, Thomas, Tomas, Volker] + +Contributors: + + Javier Jardón, Steve Frécinaux, Tomas Frydrych, Michael Meeks, + Frédéric Péters, Volker Sobek, Owen Taylor, Thomas Thurman, + Colin Walters + +Translation: + + Fran Dieguez (gl), Gabor Kelemen (hu), Daniel Nylander (se) + +Bugs fixed: + + 589457 - Fix up window property notification for "title" + 590911 - Do not run plugin effects on WM startup + 590978 - API to query whether window is in modal state + 591367 - Be silent by default + 591566 - install errors.h header ... + 591788 - Add meta_window_is_override_redirect + 591836 - mutter mishandles opacity + 591913 - Fails to skip current window on alt+tab when another window is asking for attention + 592393 - Clicking on a minimized window in the overview doesn't focus the window + 592699 - Remove deprecated Encoding key from desktop files + 592742 - Avoid accessing freed memory when being replaced + 593399 - Add meta_display_get_grab_op() + 593404 - Make MUTTER_DEBUG_XINERAMA override active Xinerama + 593407 - Add 'skip-taskbar' accessor to MetaWindow. + +----------------------------- Older Metacity News ----------------------------- + +2.26.0 +====== + +Thanks to Luca Ferretti, Matt Kraai, and Neil Jagdish Patel for +improvements in this version. + + - queue frame resize on window undecorate (Neil) + - fix description of desktop background (Luca) (#569649) + - wrap g_error calls in braces (Matt) + +Translations + Amitakhya Phukan (as), Mikel González (ast), Ihar Hrachyshka (be@latin), Runa + Bhattacharjee (bn_IN), David Planella (ca), Petr Kovar (cs), Ask Hjorth + Larsen (da), Christian Kirbach (de), Jennie Petoumenou (el), David Lodge (en_GB), + Jorge González (es), Mattias Põldaru (et), Iñaki Larrañaga Murgoitio (eu), + Ilkka Tuohela (fi), Claude Paroz (fr), Ankit Patel (gu), Mark Krapivner (he), + Rajesh Ranjan (hi), Gabor Kelemen (hu), Luca Ferretti (it), Takeshi AIHANA (ja), + Changwoo Ryu (ko), Gintautas Miliauskas (lt), Sangeeta Kumari (mai), Sandeep + Shedmake (mr), Wouter Bolsterlee (nl), Manoj Kumar Giri (or), Duarte Loreto (pt), + Leonardo Ferreira Fontenelle (pt_BR), Adi Roiban (ro), Yuriy Penkin (ru), Daniel + Nylander (sv), I. Felix (ta), Krishna Babu K (te), Theppitak Karoonboonyanan (th), + Clytie Siddall (vi), Chao-Hsiung Liao (zh_HK), Chao-Hsiung Liao (zh_TW) + +2.25.144 +======== + +Thanks to Matthias Claesen, Matt Kraai, Elijah Newren, Owen Taylor, and Thomas +Thurman for improvements in this version. + + - Optimise window property lookup (Thomas) (#549886) + - Fix slip in the above (Matt) + - Several memory leaks fixed (Matthias) (#552303, #552973, #552307) + - Fix longstanding crasher about colourmaps (Owen) (#568365) + - Alt+middle/right buttons can be switched (Thomas) (#437910) + - Support _NET_WM_MOVERESIZE_CANCEL (Elijah) + - minor fix paving the way for a theme editor (Thomas) + +Translations + David Planella (ca), Jorge González (es), Mattias Põldaru (et), saudat + mohammed (ha), Yuval Tanny\n (he), Gabor Kelemen (hu), Onye, Sylvester (ig), + Changwoo Ryu (ko), Raivis Dejus (lv), Kjartan Maraas (nb), Daniel Nylander (sv), + Fajuyitan, Sunday Ayo (yo), 甘露 (Gan Lu) (zh_CN) + +2.25.89 +======= + +Thanks to Yanko Kaneti, Frederic Peters, Thomas Thurman, and Colin Walters for +improvements in this version. + + - The maximisation key is a toggle. (Thomas) (#343824) + - "Unmaximise" is now called "restore". (Thomas) (#343824) + - New thread handling call for gconf (Frederic) (#565517) + - Add screenshot commands back which had been removed (Yanko) (#565343) + - move_to_corner_se keybinding fixed (Thomas) + - Windows on other workspaces which attempt to present themselves + are marked as needing attention (Colin) (#482354) + - End the grab op when the user clicks the titlebar (Thomas) (#401028) + +Translations + Jorge González (es) + +2.25.55 +======= + +Thanks to Erwann Chenede for improvements in this version. + + - Fix build on Solaris (Erwann) (#564123) + +Translations + Mattias Põldaru (et), Luca Ferretti (it) + +2.25.34 +======= + +Thanks to Matt Kraai for improvements in this version. + + - Fixes to Thomas's earlier fixes (Matt) (#562939) + +Translations + None + +2.25.21 +======= + +Thanks to Thomas Thurman for improvements in this version. + + - Fixes to allow building without compositor again (Thomas) + - Fixes for -Wall problems (Thomas) + - Various tool updates (Thomas) + +Translations: none + + +2.25.13 +======= + +Thanks to Thomas Thurman for improvements in this version. + + - Add casts to fix failure to build from source on 64bit hosts (Thomas) (#562106) + - Added script to produce annoucements (Thomas) + +Translations + Jorge González (es) + +2.25.8 +====== + +Thanks to Brian Cameron, Maxim Ermilov, Daniel Macks, Elijah Newren, Frederic +Peters, Thomas Thurman, David Trowbridge, and Olav Vitters for improvements in +this version. + + - Reorder compiler flags (Daniel) (#562033) + - Fix compositor switch (Daniel) (#560990) + - Remove spurious warnings about operations on window "none" (Thomas) + - Fix _POSIX_C_SOURCE which was breaking OS X builds (Thomas) (#561962) + - -Werror -Wall and -ansi are now standard compile flags (Thomas) + - Merge screen and window keybindings files; fix minor alt-tab bug + in the process (Thomas) (#528337) + - Support _NET_WM_FULLSCREEN_MONITORS (David) + - Remove some deprecated calls (Thomas) (#560445) + - Clean up #includes (Maxim) (#560449) + - Update description of raise_on_click (Elijah) + - First dialogue delegated to zenity (Thomas) + - fix theme-parser typo (Olav) + - double-quote variable names in messages (Thomas) (#558309) + - fix accidental renaming of run_command_terminal (Thomas) (#557943) + - some null checks; problems exposed by new GDM (Brian) (#558058) + - ignore mouse button modifier if it's missing (Thomas) (Launchpad 258054, Launchpad 266929) + - fix docbook markup (Frederic) + +Translations + Astur (ast), Jorge González (es), Thomas Thurman (la), Leonardo Ferreira + Fontenelle (pt_BR), Daniel Nylander (sv) + +2.25.5 +====== + +Thanks to Thomas Thurman for improvements in this version. + + - Allow third-party apps to decide whether a window appears + on all workspaces (Thomas) (#557536) + - Fixed keybindings script (again) (Thomas) + +Translations + David Planella (ca), Robert Millan (ca@valencia) + +2.25.3 +====== + +Brown paper bag release which fixes numerous build problems from last night's +release of 2.25.2. Apologies. + +Thanks to Murray Cumming, Thomas Thurman, and Götz Waschk for improvements +in this version. + + - Fix distcheck (Thomas) (#557356) + - add libm reference (Götz) (#557357) + - fix docbook tags (Murray) (#557337) + +Translations + Yavor Doganov (bg), David Planella (ca), Robert Millan (ca@valencia), Kenneth + Nielsen (da), Hendrik Richter (de), Ivar Smolin (et), Claude Paroz (fr), Seán de + Búrca (ga), Launchpad Translations Administrators (hr), Gabor Kelemen (hu), + Thomas Thurman (la), Žygimantas Beručka (lt), Kjartan Maraas (nb), Duarte + Loreto (pt), Djavan Fagundes (pt_BR), Mugurel Tudor (ro), Pavol Å imo (sk), + Laurent Dhima (sq), Горан Ракић (sr), Theppitak Karoonboonyanan (th), + Funda Wang (zh_CN) + +2.25.2 +====== + +Thanks to Joe Marcus Clarke, Murray Cumming, Tomas Frydrych, William Lachance, +Matthew Martin, Christian Persch, Thomas Thurman, and Vincent Untz for +improvements in this version. + + - Add handler for SIGTERM (Joe) (#553980) + - Minimised windows are necessarily obscured (Matthew) (#528927) + - Build fixes with the above (Christian, Tomas, Thomas) (#557335) + (#557201) (#469361) + - Changed keybindings to be in a single place (Thomas) (#469361) + - Add new document about themes (Murray) + - Remove obsolete support for fallback icons (Thomas) + - Pass modified mouse events to panels (William) (#554428) + - Change where desktop files should go (Vincent) (#549479) + +Translations + Yavor Doganov (bg), David Planella (ca), Kenneth Nielsen (da), Hendrik + Richter (de), Ivar Smolin (et), Claude Paroz (fr), Seán de Búrca (ga), Launchpad + Translations Administrators (hr), Gabor Kelemen (hu), Thomas Thurman (la), + Žygimantas Beručka (lt), Kjartan Maraas (nb), Duarte Loreto (pt), Djavan + Fagundes (pt_BR), Mugurel Tudor (ro), Pavol Å imo (sk), Laurent Dhima (sq), + Горан Ракић (sr), Theppitak Karoonboonyanan (th), Funda Wang (zh_CN) +2.25.1 +====== + +Thanks to Thomas Thurman for improvements in this version. + + - Fix small memory leak, found by Matthias Clasen (Thomas) (#549952) + - Added move_to_center keybinding suggested by + Khanh-Dang Nguyen Thu Lam (Thomas) (#549979) + - Compositor can be turned on and off from the command line + (#545323) (Thomas) + +Translations + Khaled Hosny (ar), Petr Kovar (cs), Iñaki Larrañaga Murgoitio (eu), Ilkka + Tuohela (fi), Žygimantas Beručka (lt), Duarte Loreto (pt), Djavan + Fagundes (pt_BR), Laurent Dhima (sq) + +2.25.0 +====== + +Thanks to Patrick Niklaus, Ted Percival, Eric Piel, Akira TAGOH, and Thomas +Thurman for improvements in this version. + + - Fix memory allocation problem in struts (Eric) (probably #468075) + - Ensure windows which start maximised know where to jump back + to, so they don't warp to other screens (Ted) (#504692) + - Added header comments to some files (Thomas) + - Icons for windows which are uncooperative enough not to provide + an icon are taken from the theme, not built in (Patrick) (#524343) + - Added manual page for metacity-message (Akira, from Debian downstream) + +Translations + Khaled Hosny (ar), Petr Kovar (cs), Ilkka Tuohela (fi), Duarte Loreto (pt), Djavan + Fagundes (pt_BR) + +2.23.89 +======= + +Thanks to Thomas Thurman for improvements in this version. + + - Added DOAP file. (Thomas) + +Translations + Khaled Hosny (ar), Luca Ferretti (it), Takeshi AIHANA (ja), Wouter + Bolsterlee (nl), Vladimir Melo (pt_BR), Daniel Nylander (sv) + +2.23.55 +======= + +Thanks to Elijah Newren and Thomas Thurman for improvements in this version. + +Contrary to rumour, this release does not add tabbing to everything. + + - Display theme name in title bar of theme viewer (Thomas) (#430198) + - Allow toggling of non-compositor effects (Thomas) (#92867) + - Add some extra null checks (Thomas) (#422242) + - Check for double-freeing at the time of workspace freeing (Elijah) (#361804) + - Don't generate log messages unless we're logging (Thomas) + - Two windows which don't belong to any application can't be considered to + belong to the same application (Thomas) + - Various tidyings (Thomas) + +Translations + Yavor Doganov (bg), Gabor Kelemen (hu), Kjartan Maraas (nb), Matej + Urbančič (sl), Daniel Nylander (sv), Theppitak Karoonboonyanan (th) + + +2.23.34 +======= + +Thanks to Thomas Thurman for improvements in this version. + + - Commenting and tidying (Thomas) + - Fix possible compositor crash (Thomas) (#530702) + +Translations + Khaled Hosny (ar), Yavor Doganov (bg), Jorge González (es), Kjartan Maraas (nb), + Yannig Marchegay (Kokoyaya) (oc), Theppitak Karoonboonyanan (th), Clytie + Siddall (vi) + +2.23.34 +======= + +Thanks to Thomas Thurman for improvements in this version. + + - Commenting and tidying (Thomas) + - Fix possible compositor crash (Thomas) (#530702) + +Translations + Khaled Hosny (ar), Yavor Doganov (bg), Jorge González (es), Kjartan Maraas (nb), + Yannig Marchegay (Kokoyaya) (oc), Theppitak Karoonboonyanan (th), Clytie + Siddall (vi) + +2.23.34 +======= + +Thanks to Thomas Thurman for improvements in this version. + + - Various commenting (Thomas) + - Ensure you can turn off compositor with "configure" (Thomas) + - Ensure you can turn off gconf with "configure" (Thomas) (#530870) + +Translations + Clytie Siddall (vi) + +2.23.21 +======= + +Thanks to Robert Escriva, Iain Holmes, Matt Krai, Thomas Thurman, +and Chris Wang for improvements in this version. + + - Add shadow ability for menus and tooltips (Iain) (#517442) (#517524) + - Fix possible crashes in compositor (Iain) (#534569) (#528787) + - Major reorganisation of compositor code (Iain) + - Initial version of XRender backend for the compositor (Iain) + - New basic public API for compositor (Iain) + - Window decoration updates colour when GTK theme changes (Robert) (#511826) + - Minor code cleanup for pedantic compilers (Thomas) + - Further code cleanup for pedantic compilers (Matt) (#526049) + - The atom list appears only once in the code (Thomas) (#530843) + - Don't attempt to read attributes of invalid windows (Chris) (#530485) + +Translations + Khaled Hosny (ar), Gabor Kelemen (hu), Kjartan Maraas (nb), Tino Meinen (nl), + Theppitak Karoonboonyanan (th) +2.23.13 +======= + +Thanks to Erwann Chenede and Carlos Garnacho for improvements +in this version. + + - Re-enable cascading (Erwann) (#529925) + - Propagate opacity to frame windows (spec compliance!) (Carlos) + +Translations + - None this time! + +2.23.8 +====== + +Thanks to Lucas Rocha, Iain Holmes, and Jens Granseuer for improvements +in this version. + + * No need to symlink to .desktop files (Lucas) + * Fixes to compositor's dealings with overlay windows (Iain) + * C89 fixes (Jens) + +Translators: +Khaled Hosny (ar), Amitakhya Phukan (as), Ihar Hrachyshka (be@latin), +Petr Kovar (cs), Rhys Jones (cy), Kenneth Nielsen (da), Andre Klapper (de), +Jorge González (es), Iñaki Larrañaga Murgoitio (eu), Ilkka Tuohela (fi), +Claude Paroz (fr), Seán de Búrca (ga), Ignacio Casal Quinteiro (gl), +Yuval Tanny (he), Gabor Kelemen (hu), Luca Ferretti (it), Takeshi AIHANA (ja), +Shankar Prasad (kn), Changwoo Ryu (ko), Arangel Angov (mk), sandeep shedmake (mr), +Kjartan Maraas (nb), Nabin Gautam (ne), Wouter Bolsterlee (nl), +Eskild Hustvedt (nn), Yannig Marchegay (Kokoyaya) (oc), Tomasz Dominikowski (pl), +Duarte Loreto (pt), Vasiliy Faronov (ru), Daniel Nylander (sv), +Theppitak Karoonboonyanan (th), Baris Cicek (tr), Maxim Dziumanenko (uk), +Clytie Siddall (vi), Woodman Tuen (zh_HK), Woodman Tuen (zh_TW) +2.23.5 +====== + +Thanks to Lucas Rocha, Owen Taylor, and Thomas Thurman for improvements in this +version. + + - Updates of useless preferences don't crash (Thomas) (#526016) + - Compliance with new gnome-session (Lucas) (#525051) + - Preview widget doesn't crash on broken themes (Thomas) (Launchpad 199402) + - Initially iconic windows don't unminimise (Owen) (#491090) + - Move ~/.metacity to ~/.config/metacity (Thomas) (#518596) + - Metacity doesn't stay around when replaced (Thomas) + - Extra check for null return in a function (Thomas) + - Displays are singletons, simplifying code (Thomas) (#499301) + +Translations + Jorge González (es), Eskild Hustvedt (nn), Baris Cicek (tr), Clytie Siddall (vi) + +2.23.3 +====== + +Thanks to Marco Pesenti Gritti, Iain Holmes, Josh Lee, Thomas Thurman, and +Matthew Wilson for improvements in this version. + + - Workspaces whose name is the same as the standard name, plus some string, + are not cut off. (Thomas) (#453678) + - Improve compositor performance (Iain) (#522166) + - Draw wallpaper correctly when we start up with compositor + (Iain) (#522599) + - Several other smaller compositor fixes (Iain) + - Don't draw shadows on shaped windows unless they have frames + (Iain) (#505333) + - Newly-created keep-above windows get focus (Marco) (#519188) + - Allow moving workspace when dragging with modifier key (Matthew) + (#474195) + +Translations + Kenneth Nielsen (da), Gabor Kelemen (hu), Vasiliy Faronov (ru), Daniel + Nylander (sv), Maxim Dziumanenko (uk), Woodman Tuen (zh_HK) + +2.23.2 +====== + +Removed some debug statements introduced in 2.23.1. Brown paper bag release. + + +2.23.1 +====== + +Thanks to Cosimo Cecchi, Jens Granseuer, Jim Huang, Andrea Del Signore, and +Thomas Thurman for improvements in this version. + +(Cosimo's patch was very similar to another received from Jason Ribero.) + + - Allow horizontal and vertical maximisation using the mouse (Cosimo/Jason) + (#358674) + - Allow "spacer" as a value for buttons, for blank space (Andrea) (#509165) + - Remove unused code (Jim) + - refactor preferences handling (Thomas) + - make sure we're valid C89 (Jens) (#518917) + - some messing with tool scripts (Thomas) + +Translations + Jorge González (es), Claude Paroz (fr), Woodman Tuen (zh_HK), Woodman + Tuen (zh_TW) + +2.23.0 +====== + +Thanks to Matthias Clasen, Mikkel Kamstrup Erlandsen, Jim Huang, Thomas Thurman, +and Thomas Wood for improvements in this version. + + - the preview widget can draw shaped windows properly! (Thomas W, #460018) + - refactored handling of boolean and enumerated gconf preferences; + refactoring of string and integer preferences will follow shortly (Thomas T) + - Applications asking to move and resize windows at the same time have + both their requests granted (Mikkel) (#448183) + - Windows marked "skip taskbar" don't appear in the ctrl-alt-tab list + (Matthias) (#106249) + - fix session management detection (Thomas T) (#328210) + - when resizing with the keyboard, the cursor stays on a window edge if + you escape, whichever direction you were going (Thomas T) (#436257) + - fix major breakage when gconf was turned off in configure (Jim) (#515019) + - fix major breakage when verbose was turned off in configure (Jim) (#515152) + - fix name of verbose option in help (Thomas T) + - various bits of messing around with release scripts (Thomas T) + +Translations + Ihar Hrachyshka (be@latin), Ilkka Tuohela (fi), Ignacio Casal Quinteiro (gl), + Shankar Prasad (kn), Changwoo Ryu (ko), Nabin Gautam (ne), Wouter Bolsterlee (nl) + +2.21.13 +======= + +Thanks to Michael Meeks and Thomas Thurman for improvements in this version. + + - Only use compositor version if we have a compositor (Thomas) (#514453) + - Remove workaround for a problem in an ancient GTK version (Thomas) (#513737) + - Compositor efficiency fixes (Michael) + - Various tools added (Thomas) + +Translations + Amitakhya Phukan (as), Rhys Jones (cy), Andre Klapper (de), Takeshi AIHANA (ja), + Arangel Angov (mk), Tomasz Dominikowski (pl), Duarte Loreto (pt) + +2.21.8 +====== + +Thanks to Paolo Borelli, Iain Holmes, Havoc Pennington, Christian Persch, Thomas +Thurman, and Alex R.M. Turner for improvements in this version. + + - Windows on other workspaces which need attention appear in the alt-tab + list too (Alex) (#333548) + - Remove deprecated function call (Christian) (#512561) + - New release script (Thomas) + - Made a start at improving the general number of comments (Thomas) + - Updated copyright year to 2008, and some other tiny fixes (Thomas) + - Don't do anything unusual when the compositor frees a window (Iain) + - Mapping windows doesn't mark them as damaged (Iain) + - Compositor uses the overlay window and not the root window (Iain) + - Fixed several list leaks (Paolo) + - Fixed warnings about printf formats (Havoc) + - Move source files into subdirectories of the src directory (Havoc) + +Translations + Khaled Hosny (ar), Ihar Hrachyshka (be@latin), Petr Kovar (cs), Andre + Klapper (de), Jorge González (es), Iñaki Larrañaga Murgoitio (eu), Seán de + Búrca (ga), Yuval Tanny (he), Luca Ferretti (it), Takeshi AIHANA (ja), Arangel + Angov (mk), sandeep shedmake (mr), Kjartan Maraas (nb), Yannig + Marchegay (Kokoyaya) (oc), Daniel Nylander (sv), Theppitak Karoonboonyanan (th), + Baris Cicek (tr), Clytie Siddall (vi) +2.21.5 +====== + +Thanks to Iain Holmes and Thomas Thurman for improvements in this version. +This contains the new compositor; downstream maintainers should note that +its GConf key is initially turned off in src/metacity.schemas.in and consider +whether to turn it on by default in their packages. + + - merge compositor branch! (Iain) (499081) + - print "Subversion" and not "CVS" when building (Thomas) + +Translations + Jorge González (es), Kjartan Maraas (nb), Daniel Nylander (sv) + +2.21.3 +====== + +Thanks to Matthias Clasen, Martin Meyer, Kjartan Maraas, Thomas Thurman, +and Lucas Rocha for improvements in this version. + + - remove dead code (pointed out by Kjartan) (501365) + - rewrote long key binding description for the sake of + the translators (Thomas) (474889) + - check for null before adding menu (Matthias) (496054) + - let keys which end a grab also begin a grab (Thomas) (112560) + - check the right variable in theme sanity check (Martin) (501362) + - get session ID from environment if it's not passed in on the command + line (Lucas) (498033) + +Translations + Ihar Hrachyshka (be@latin), Petr Kovar (cs), Jorge González (es), + Ignacio Casal Quinteiro (gl), Rodrigo Flores (pt_BR), Pavol Å imo (sk), + Matej Urbančič (sl) + +2.21.2 +====== + +Thanks to Benjamin Gramlich, Thomas Thurman, and Peter Bloomfield +for improvements in this release. + + - Theme parser is compliant to XDG Base Directory Specification + in searching for theme files. (Benjamin) (#480026) + - Some source files which didn't get used were removed (Thomas) + (#496947) + - Fullscreen and maximise windows don't try to save their position + (Peter) (#461927) + +Translations + Matej Urbančič (sl) + +2.21.1 +====== + +Thanks to Elijah Newren, Alex R.M. Turner, Peter Bloomfield, Iain Holmes, +Jans Granseuer, Federico Mena Quintero and Thomas Thurman for improvements +in this release. + + - Add --sync option, like all other GTK apps (Iain) + - Don't save window's position if it's maximised (Peter) (#461927) + - Memory leak fix in preview (Jans) (#469682) + - Truncate tab popup string correctly, and refactor function (Alex) + - Windows which pop up under always-on-top windows don't get the + focus, but do get the "needs attention" hint (Thomas) (#486445) + - Fix error in function call which caused focus problems (Federico) + (partial fix of #488468) + +Translations + Djihed Afifi (ar), Metin Amiroff (az), Alexander Shopov (bg), + Jordi Mallach (ca), David Lodge (en_GB), Jorge González (es), + Iñaki Larrañaga Murgoitio (eu), Vincent Untz (fr), Alastair McKinstry (ga), + Ankit Patel (gu), Rajesh Ranjan (hi), auto (hr), Changwoo Ryu (ko), + Raivis Dejus (lv), Wouter Bolsterlee (nl), Gora Mohanty (or), + ASB (pa), wadim dziedzic (pl), Duarte Loreto (pt), + Og Maciel (pt_BR), Peter Tuhársky (sk), Matej Urbančič (sl), + Daniel Nylander (sv), Maxim Dziumanenko (uk), Funda Wang (zh_CN) + +2.20.0 +====== + +Thanks to Alexey Rusakov for the fix in this release. + + - prevent a crash on logout with metacity subsequently not being + restored in future sessions (Alexey) [#433253] + +Translations + Khaled Hosny (ar), Ihar Hrachyshka (be@latin), Ask Hjorth Larsen (da), + Adam Weinberger (en_CA), Iñaki Larrañaga Murgoitio (eu), Ilkka + Tuohela (fi), Vincent Untz (fr), Ankit Patel (gu), Gabor Kelemen (hu), + Luca Ferretti (it), Takeshi AIHANA (ja), Žygimantas Beručka (lt), Jovan + Naumovski (mk), Ani Peter (ml), Og Maciel (pt_BR), Duarte Loreto (pt), + Mugurel Tudor (ro), Nickolay V. Shmyrev (ru), Peter Tuhársky (sk), Горан + Ракић (sr), Daniel Nylander (sv), Dr.T.Vasudevan (ta), Maxim + Dziumanenko (uk), Clytie Siddall (vi) + +2.19.55 +======= + +Thanks to Frederic Crozat, Matthias Clasen, and Thomas Thurman for improvements +in this release. + + - Noninteger auto-raise delay is not assumed to be zero (Thomas) (#377491) + - Fix mangled window title in "Force Quit" (Frederic) (#462734) + - "Close" can appear at any point in the window menu, and now appears + at the bottom (Thomas) (#104026) + - Windows which are always on top have "stick" insensitive (Thomas) (#460997) + - All bitfields in window structure are together for optimisation (Thomas) + (#450271) + - Use the correct directory when installing keybindings (Matthias) (#454055) + +Translations + Alexander Shopov (bg), Jorge González (es), Iñaki Larrañaga Murgoitio (eu), + Ilkka Tuohela (fi), Theppitak Karoonboonyanan (th) + +2.19.34 +======= + +Thanks to Rob Bradford, Cosimo Cecchi, Yair Hershkovitz and Thomas Thurman +for improvements in this release. + + - Fix a bug where the window can be focused without being raised + if the maximize is aborted. (Rob) [#459027] + - Unset fullscreen is an allowed action where relevant. (Cosimo) [#449427] + - Reverse window buttons and align them to the left for RTL locales. + (Yair) [#92212] + - Put all bitfields in window data together to help with optimisation. + (Thomas) [#450271] + +Translations + Jorge Gonzalez (es), Ilkka Tyohela (fi), Gabor Kelemen (hu), + Takeshi AIHANA (ja), Kjartan Maraas (nb), Vincent van Adrighem (nl), + Daniel Nylander (sv), Theppitak Karoonbooyana (th), + Nguyễn Thái Ngọc Duy (vi) + +2.19.21 +======= + +Thanks to Damien Carbery and Thomas Thurman for improvements in +this release. + + - Fixed build on Solaris (Damien) [#397296, #446535] + - Only activate windows which change their startup ID if the + new ID differs from the old. (This fixes the bug where KDE + apps gained the attention hint when switching workspaces.) + (Thomas) [#400167] + - Open new windows on the current xinerama. (Thomas) [#145503]. + +Translations + Tshewang Norbu (dz), Jorge González (es), Funda Wang (zh_CN) + +2.19.13 +======= + +Thanks to Elijah Newren and Thomas Thurman for improvements in +this release. + + - Updated the description of raise_on_click (Elijah) [#445447, + #389923] + - Refactor queueing code in window.c (Thomas) [#376760] + - Added switch_group to the keybindings file (Thomas) [#444879] + - New window information accessor function (Thomas) [#377495] + +2.19.8 +====== + +Thanks to Linus Torvalds, Yair Hershkovitz and Thomas Thurman for +improvements in this release. + + - Lots of fixups for various alignments in RTL locales (Yair) + [#387893] + - Add code to configure what happens on right or middle click + of titlebar (Linus) [#408904] + - Fix layout for titlebars with mixed LTR/RTL scripts (Thomas) + [#433400] + - Fix window menu layout for RTL scripts (Thomas) [#433400] + +Translations + Khaled Hosny (ar), Ihar Hrachyshka (be@latin), Jovan Naumovski (mk), + Theppitak Karoonboonyanan (th) + + [ Apologies to these translators who didn't get credited in the + version of 2.19.8 that shipped. ] + +2.19.5 +====== + + - Prevent metacity from "forgetting" which machine a window is on + (Elijah) [#418552] + - Prevent nasty flickering an placement problem introduced in + metacity 2.19.2 (Elijah) [fix side-effect of change in #426519] + - Fix some uninitialized memory usage errors (Elijah) [#427385] + +Translations + David Lodge (en_GB), Jorge González (es), Ignacio Casal Quinteiro (gl), + Daniel Nylander (sv) + +2.19.3 +====== + +Thanks to Magnus Therning, Elijah Newren, Thomas Thurman, and Bruno +Boaventura for improvements in this release. + + - Add support for _NET_MOVERESIZE_WINDOW (Magnus, Elijah) [#344521] + - EWMH compliance: set _NET_WM_ALLOWED_ACTIONS so that pagers know + which actions we support (Elijah) [#115247] + - Fix crash with apps trying to open an insanely huge window + (Thomas) [#399529] + - Fix temporary hang/pause with libXt by making sure apps get a + ConfigureNotify on unmap (Elijah) [#399552] + - do not auto-maximize windows larger than the workarea in only a + single direction (Elijah) [#419810] + - Don't show the current workspace as a possible workspace to switch + to (Bruno) [#426791] + - Preserve stacking order across restarts (Elijah) + +Translations + Khaled Hosny (ar), Kjartan Maraas (nb) + +2.19.2 +====== + +Thanks to Bastien Nocera, Thomas Thurman, and Elijah Newren for +improvements in this release. + + - Add new control-center key bindings definitions (Bastien) [#420145] + - Prevent metacity from crashing when trying to use invalid themes + (Thomas) [#423855] + - Fix invalid free causing crash on metacity close introduced in + 2.19.1 (Elijah) [#427385] + - Add special keybinding just for debugging spew marks, unbound and + not even listed in schemas (Elijah) + - Fix move/resize events in relation to combinations of + ConfigureRequest and WM_NORMAL_HINTS change notifications (Elijah) + [#426519] + - Remove what we believe to be an ancient attempt at working around + sloppy/mouse focus bugs that we believe have since been correctly + fixed. May fix some ugly race conditions. May also cause nasty + bugs in sloppy/mouse focus modes. Only one way to find + out... (Elijah) [#304430] + +Translations + Raivis Dejus (lv) + +2.19.1 +====== + +Thanks to Jaap Haitsma, Linus Torvalds, Charlie Brej, Kjartan Maraas, +Arthur Taylor, Elijah Newren, Josselin Mouette, Havoc Pennington, +Benjamin Berg, and Carlo Wood for improvements in this release. + + - new icon for the force-quit dialog (Jaap) [#396655] + - add configureable mouse click action abilities, and clean up lots of + related code (Linus) [#408899, #408902, others] + - add schemeas for middle and right click titlebar actions (Charlie) + [#408903] + - remove pango/pangox.h include since it's not needed and not + installed anymore (Kjartan) + - adjust rounded corners so that they fit nicely with the arcs + around them (Arthur) [#399373] + - fix session hang when metacity .sm file is missing (Josselin) + [#407981] + - add support for _NET_WM_USER_TIME_WINDOW in order to cut down on + context switches (Elijah, Havoc) [#354213] + - prevent nasty metacity/gdk interactions causing hangs with gtk + trunk (Elijah) [offshoots of #354213] + - fix button middle fallback and the prelight state (Benjamin) [#419043] + - Lots of code cleanup for the strut lists (Elijah) + - fix handling of unidirectional maximization and partial struts + + some miscellaneous cleanups (Carlo) [#358311] + - avoid some crashes when dragging windows partially offscreen + (Elijah) [#353513] + - avoid mousenav vs. keynav focus problems with the run application + dialog in mouse/sloppy focus modes (Elijah) [#374752] + - _NET_ACTIVE_WINDOW property on the root window should be a single + xwindow id, not two (Elijah) + - Fix unidirection unmaximization causing jumps (Elijah) [#355497] + - fix unfullscreening and unmaximizing with size increment/size + constraint windows (such as gnome-terminal) possibly not returning + to their "original position" (Elijah) [#329152] + - fix some issues with min/max and size increment constraints + (Elijah) [#418395] + - send synthetic configure notify events in response to appropriate + MapRequest events too (Elijah) [#322840] + +Translations + Ihar Hrachyshka (be@latin), Jordi Mallach (ca), Jakub Friedl (cs), + norbu (dz), David Lodge (en_GB), Ivar Smolin (et), Gabor Kelemen (hu), + Luca Ferretti (it), Takeshi AIHANA (ja), Erdal Ronahi (ku), Gintautas + Miliauskas (lt), Jovan Naumovski (mk), Kjartan Maraas (nb), Reinout van + Schouwen (nl), wadim dziedzic (pl), raulpereira (pt_BR), Nickolay V. + Shmyrev (ru), Горан Ракић (sr), Woodman Tuen (zh_HK), Woodman Tuen (zh_TW) + +2.17.5 +====== + +Thanks to Bruno Boaventura, Mad Alex, and Thomas Thurman for +improvements in this release. + + - make window menu arrangement more sensible. (Bruno) [#382962] + - unmaximise button keeps pressed appearance when moved off and + back. (Alex) [#395560] + - fix a couple of compositor crashes (Thomas) [#387761] + - new environment variables checked if the compositor is enabled; + see the new file doc/compositor-control.txt for details. (Thomas) + +Translations + Djihed Afifi (ar), Ales Nyakhaychyk (be), Jordi Mallach (ca), + Jakub Friedl (cs), David Lodge (en_GB), Raivis Dejus (lv), + Kjartan Maraas (nb), Mugurel Tudor (ro), Daniel Nylander (sv), + Theppitak Karoonboonyanan (th) + +2.17.3 +====== + +Thanks to Christof Krüger, Federico Mena Quintero, Bruno Boaventura, +and Björn Lindqvist for improvements in this release. + + - fix longstanding problem about windows flickering in and out of + maximised state when dragging between xineramas (Christof) [#358715] + - grab server when switching workspaces (Federico) [#381127] + - replace changing text on window menu with pairs of radio buttons + and checkboxes (Bruno, Björn) [#343108] + +Translations + Kjartan Maraas (nb), Jakub Friedl (cs), Yuval Tanny (he), Ivar Smolin (et), + Duarte Loreto (pt), Francisco Javier F. Serrador (es) + +2.17.2 +====== + +Thanks to Priit Laes, Bruno Boaventura, Kjartan Maraas, Justin Mason, +Elijah Newren and Dan Mick for improvements in this release. + + - implement handle_move_to_{side|corner}_* to allow the user to flip a + window to the side or corner of the screen. (Justin) [#317884] + - fix strict focus mode by picking up on res_class (Dan) [#361054] + - remove deprecated gtk stuff (Priit, Bruno) + - string fixes (Kjartan) [#363354, #363355] + +Translations + Jakub Friedl (cs), Francisco Javier F. Serrador (es), Ilkka Tuohela (fi), + Christophe Merlet (RedFox) (fr), Kjartan Maraas (nb) + +2.17.1 +====== + +Thanks to Bruno Boaventura and Carlo Wood for improvements in this +release. + + - sync metacity workspace previous with libwnck (Bruno) [#341893] + - fix cases when titlebar is allowed offscreen and shouldn't be, and + vice-versa (Carlo) [#333995] + +Translations + Ilkka Tuohela (fi) + +2.17.0 +====== + +Thanks to Elijah Newren, Jens Granseuer, Bruno Boaventura, Carlo Wood, +and Thomas Thurman for changes in this release. + + - version 2 of theme format: stick, shade and above buttons on titlebar, + variable rounding on corners, variable transparency on window + backgrounds, stock icons in themes, can remove all titlebar buttons + from certain classes of window, and more (Thomas) [#102547 and + dependencies] + - improve "Force Quit" dialog (Bruno) [#121936] + - ignore edge resistance when resizing with keyboard (Elijah) [#346782] + - maintain window size and placement across restarts (Carlo) [#358042] + - prevent crash when closing certain remote apps (Elijah) [#358514] + - longstanding mouse-focus bug fixed which affected firefox's + autocompletion (Elijah) [#357695] + - ignore maximum size constraints when maximising (Elijah) [#327543] + - warn translators to keep translations in sync with libwnck (Bruno) + [#355620] + - fixes for compilation warnings, etc (Elijah, Jens) [#348067, #356631] + +Translators + Ivar Smolin (et), Gabor Kelemen (hu), Luca Ferretti (it), + Runa Bhattacharjee (bn_IN) + +2.16.2 +====== + +Thanks to Eljah Newren, Maik Beckmann, Christian Hamar, Thomas Andersen, +and Bruno Boaventura de Oliveira for changes in this release. + + - partial audit to fix timestamp usage (Elijah) [part of #355180] + - remove compilation warnings (Maik) [#355876]; (Bruno) [#355490, + #355489] + - automatic detection of stable/unstable in configure script + (Christian/Elijah) [#356122] + - make windows be stacked correctly before showing them (Thomas) + [#332385] + - use guint32 for timestamps (Elijah) [#348305] + +Translators + Wouter Bolsterlee (nl), Matic Žgur (sl), Francisco Javier F. Serrador (es), + Vladimir Petkov (bg), Jordi Mallach (ca), Ilkka Tuohela (fi), + Rajesh Ranjan (hi), Woodman Tuen (zh_HK, zh_TW), Ani Peter (ml), + Felix (ta), Ankit Patel (gu), Mohammad DAMT (id) + +2.16.1 +====== + +Thanks to Elijah Newren, Colin Watson, and Bruno Boaventura de Oliveira +Lacerda for changes in this release. + + - fix stuck grab, letting focus be transferred between windows (Elijah) + [#354422 partial] + - windows returning from fullscreen are constrained to be onscreen + (Elijah) [#353699] + - Clear the transient_for flag of a window after emitting a warning + (Colin) + - Replace copy_of_gdk_x11_window_set_user_time() with the real thing + (Bruno) [#352293] + +Translators + David Lodge (en_GB), Ivar Smolin (et), Matic Žgur (sl), + Vasiliy Faronov (ru) + +2.16.0 +== + +Thanks to Jens Granseuer for changes in this release. + + - Fix the build with c89/gcc 2.95. + +Translators + Rahul Bhalerao (mr), Runa Bhattacharjee (bn_IN), Woodman Tuen + (zh_HK, zh_TW), Kostas Papadimas (el), Ani Peter (ml), + Jonathan Ernst (fr), Горан Ракић (sr, Gabor Kelemen (hu), + Maxim Dziumanenko (uk), Duarte Loreto (pt), Jordi Mallach (ca), + Gintautas Miliauskas (lt) + +2.15.34 +== + +Thanks to Stéphane Rosi, Vytautus Liuolia, Will Walker, Baptiste +Mille-Mathias, Elijah Newren, Ed Catmur, and Thomas Andersen for fixes +in this release. + + - allow moving maximized windows between xineramas again (Stéphane) + [#338660] + - fix an uninitialized-usage bug with net_wm_user_time that breaks + focus with new windows (Vytautus) + - re-fix accessibility events for the alt-tab popup (Will) [#350624] + - update the close pixmap to fit better with the other pixmaps of the + menu (Baptiste) [#345498] + - fix several fullscreen handling bugs I introduced, causing + fullscreen windows to not actually be shown fullscreen (Elijah) + [#343115] + - fix keybindings with hex-values, coming from special extended + keyboard keys (Ed) [#140448] + - fix metacity-dialog handling of arguments (Thomas) [#340690] + +Translators + Vladimir Petkov (bg), Jordi Mallach (ca), Gabor Kelemen (hu), + Mohammad DAMT (id), Wouter Bolsterlee (nl), Daniel Nylander (sv), + Funda Wang (zh_CN) + +2.15.21 +== + +Thanks to Vincent Untz, Jens Granseuer, Björn Lindqvist, Dmitry +Timoshkov, Thomas Thurman, Vytautas Liuolia, Thomas Andersen, Chris +Ball, and Elijah Newren for fixes in this release. + + - kill usage of libegg (Vincent) [#348633] + - fix another C89 vs. C99 issue (Jens) [#347621] + - make it so maximized windows do not have rounded corners (Björn) + [#336850] + - fix the heuristic for determining if windows can be made + fullscreen, needed for WINE and possible also some legacy + applications (Dmitry) [#346927] + - make sure window features get recalculated when the screen is + resized via XRandR (Dmitry) [#346927] + - fitts' law fixes for titlebar buttons on maximized windows (Thomas + Thurman) [#97703] + - react to _NET_STARTUP_ID changes, as proposed for the new + startup-notification/EWMH spec (Vytautas) [#347515] + - return the window to maximized state if the window was "shaken + loose" from maximized state during a resize but the resize is later + aborted (Thomas Andersen) [#346719] + - fix button lighting with dragged clicks (Björn) [#321474] + - don't minimize in response to double clicks on the titlebar when + minimiziation should not be allowed (Chris) [#347377] + - fix some titlebar-not-on-screen constraint issues (Elijah) + [#333328, #345522] + +Translators + Mahay Alam Khan (bn_IN), Jakub Friedl (cs), Iñaki Larrañaga + Murgoitio (eu), Yuval Tanny (he), Rajesh Ranjan (hi), Jovan + Naumovski (mk) Kjartan Maraas (nb), Leonid Kanter (ru) + +2.15.13 +== + +Thanks to Björn Lindqvist and Thomas Thurman for improvements in this +release. + + - grab alt+shift+button1 when trying to snap-move windows (Björn) + - avoid a case where memory is written after it's freed (Thomas) + +Translators + Hendrik Richter (de), Kostas Papadimas (el), Jonathan Ernst (fr), + Satoru SATOH (ja) + +2.15.8 +== + +Known as the "Elijah sucks for not reviewing a couple dozen patches" +release. And for not getting on IRC soon enough to catch Marnanel and +show him how to do the release. So, just translations this time. + +Translations + + Mahay Alam Khan (bn_IN), Rhys Jones (cy), Francisco Javier + F. Serrador (es), Ilkka Tuohela (fi), Rajesh Ranjan (hi), Changwoo + Ryu (ko), Fano Rajaonarisoa (mg), Sanlig Badral (mn), Слободан Д. + Средојевић (sr), Funda Wang (zh_CN) + +2.15.5 +== + +Thanks to Björn Lindqvist, Søren Sandmann, Adam Jackson, Elijah +Newren, and Aidan Delaney for improvements in this release. + + - code cleanup in resizepopup.c (Björn) [#341648] + - fix a logic bug so that the whole titlebar becomes sensitive to + mouse clicks (Björn) [#336320] + - make mouse cursor when moving windows become a hand (Björn) [#337376] + - lots and lots of compositor improvements -- beginning of a new + layer to abstract transition effects, shrinking and minimizing and + exploding effects, fading in and out, unminimize animation that + reverses minimize one, translucent menus, bounce on window focus, + and all kinds of stuff I don't understand and can't summarize well + (Søren, Adam) + - Fix a crash on exit/logout from assuming a compositor would always + exist (Elijah) [#342166] + - code cleanup in tabpopup.c (Aidan Delaney) [#166890] + +Translations + Pema Geyleg (dz), Iñaki Larrañaga Murgoitio (eu), Theppitak + Karoonboonyanan (th), Clytie Siddall (vi) + +2.15.3 +== + +Thanks to Søren Sandmann, Elijah Newren, Paolo Borelli, Björn +Lindqvist, jylefort at FreeBSD org, + + - various code cleanups (Søren) + - prevent long titles from "sticking" in the tasklist (Elijah) [#330671] + - handle sync counter notifications in the compositor (Søren) + - notes/documentation updates (Elijah) + - plug a small leak (Paolo) + - remove a lot of dead code obsoleted by the new edge-resistance + stuff (Björn) [#341561] + - prevent a crash when changing resolution (jylefort) [#340847] + - revert an accessibility module loading workaround from Gnome 2.6 + that has long since been fixed for us in gtk+ (Elijah) [#123372] + +Translations + Francisco Javier F. Serrador (es), Ignacio Casal Quinteiro (gl), + Raivis Dejus (lv), Kjartan Maraas (nb), Funda Wang (zh_CN), Woodman + Tuen (zh_HK), Woodman Tuen (zh_TW) + +2.15.2 +== + +Here's hoping that "third time's a charm." ;-) This release just +fixes the translations-not-included issue. See +http://mail.gnome.org/archives/desktop-devel-list/2006-April/msg00483.html +for more details. + + - Use gnome-autogen.sh like most other modules (Rodney) + +2.15.1 +== + +This release just fixes the control-center build (which depends upon +libmetacity-private). Thanks to Vincent for catching the problem. + + - Include boxes.h in the includes dir (Elijah) [#339708] + +2.15.0 +== + +Thanks to Thomas Thurman, Elijah Newren, Havoc Pennington, Björn +Lindqvist, Gora Mohanty, Alejandro Andres, Andy Morum, Dan Sanders, +Thomas Andersen, Brian Pepple, and Søren Sandmann for improvements in +this release. (Note that "Thomas" below refers to Thomas Thurman if +last name isn't specified) + + - An endless array of compositor updates, not all of which are well + explained in the ChangeLog. ;-) Includes an ability to enable and + disable the compositor at runtime, fixed up wobbling effect and new + explosion effect, special magnification handling, different opacity + for different window types like menus, a way of scaling windows, + handling of foreign displays, improved handling of window + moving/resizing, various code restructuring, special runtime checks + for correct extensions and other compositors, lots of bug fixes, + and possibly other stuff I'm missing or not understanding (Søren) + - Removed "move to another workspace" menu when there are exactly two + workspaces (Thomas) [#151183] + - fix type for compositing_manager schema entry (Elijah) [#335901] + - Port more properties to our async system for code cleanliness and + speed improvements (Havoc, Thomas) + - Lots of code cleanup, even more code cleanup, wow our code was + messy (Björn) [#335177, #337507, #336890, #338359] + - Abstract out the functions for setting/unsetting demands attention + hint and avoid doing it when the window isn't obscured (Thomas) + [#305882] + - Change strings to make them more readable, and more + translatable (Gora) [#335720] + - Reduce compiling warnings -- add a number of casts and change + signedness on a number of variables (Björn) [#336032] + - Fixed broken links in README (Alejandro) [#333303] + - Add a tabbing function, bound to alt-f6 by default, to cycle + through the windows of the current application (Thomas) [#94682] + - Fix the build with --disable-xsync (Andy) [#336605] + - Raise windows on maximize/unmaximize (Dan) [#335076] + - Don't have confirmation windows make applications appear to be + locked when closing via the window list (Dan) [#334899] + - Allow any keybinding pref to be specified either with , a + string, or _list, a list of strings, or both (Thomas) + [#164831] + - warn and ignore if transient_for is set to a non-top-level window + (Thomas Andersen) [#335524] + - Use po/LINGUAS for listing supported languages (Brian) [#337951] + +Translations + Vladimir Petkov (bg), Jordi Mallach (ca), Miloslav Trmac (cs), Rhys + Jones (cy), Lasse Bang Mikkelsen (da), Frank Arnold (de), Kostas + Papadimas (el), Francisco Javier F. Serrador (es), Ivar Smolin (et), Iñaki + Larrañaga (eu), Farzaneh Sarafraz (fa), Ilkka Tuohela (fi), Ignacio Casal + Quinteiro (gl), Ankit Patel (gu), Rajesh Ranjan (hi), Gabor Kelemen (hu), + Satoru SATOH (ja), Alexander Didebulidze (ka), Žygimantas Beručka (lt), + Kjartan Maraas (nb), Michiel Sikkes (nl), Åsmund Skjæveland (nn), Gora + Mohanty (or), Raphael Higino (pt_BR), Duarte Loreto (pt), Mugurel Tudor (ro), + Leonid Kanter (ru), Steve Murphy (rw), Laurent Dhima (sq), Слободан Д. + Средојевић (sr), Daniel Nylander (sv), Theppitak Karoonboonyanan (th), Maxim + Dziumanenko (uk), Clytie Siddall (vi), Funda Wang (zh_CN) + +2.14.3 +== + +This release just reverts the widely hated new focus behavior of Metacity +2.14.x to the behavior found in 2.12.x. Patch came from Ron Yorston. +See http://blogs.gnome.org/view/newren/2006/04/13/0 and +http://mail.gnome.org/archives/release-team/2006-April/msg00025.html for +more details. + + - Add a focus_new_windows gconf key, change the default to 'smart' (2.12 + behavior) and add a 'strict' option to get 2.14 behavior. (Ron) + [#326159] + +Translations + Vladimir Petkov (bg), Miloslav Trmac (cs), Frank Arnold (de), Francisco + Javier F. Serrador (es), Ilkka Tuohela (fi), Tino Meinen (nl), Åsmund + Skjæveland (nn), Raphael Higino (pt_BR), Daniel Nylander (sv) + +2.14.2 +== + +Thanks to Thomas Thurman, Paolo Borelli, Björn Lindqvist, and +Elijah Newren for fixes in this release. + + - Fix constraints bug causing negative width windows and crashes + (Elijah) [#336651] + - Fix window grouping with parent/child windows (Björn) [#336184] + - use g_str_has_prefix instead of a local copy of the function + (Paolo) [#334643] + - Make sure pager can refresh when window is minimized on a different + workspace (Thomas) [#315142] + - Add debugging information for edge resistance (Elijah) + +Translations + + Vladimir Petkov (bg), tangi.bzh (br), Jordi Mallach (ca), Miloslav + Trmac (cs), Rhys Jones (cy), Lasse Bang Mikkelsen (da), Frank + Arnold (de), Mindu Dorji (dz), Kostas Papadimas (el), Francisco + Javier F. Serrador (es), Ivar Smolin (et), Iñaki Larrañaga + Murgoitio (eu), Elnaz Sarbar (fa), Ilkka Tuohela (fi), + Ignacio Casal Quinteiro (gl), Ankit Patel (gu), Rajesh Ranjan (hi) + Gabor Kelemen (hu), Luca Ferretti (it), Satoru SATOH (ja), Vladimer + Sichinava (ka), Žygimantas Beručka (lt), Kjartan Maraas (nb), + Tino Meinen (nl), Kjartan Maraas (no), Gora Mohanty (or), Gnome PL + Team (pl), Evandro Fernandes Giovanini (pt_BR), Duarte Loreto (pt), + Mugurel Tudor (ro), Leonid Kanter (ru), Laurent Dhima (sq), + Слободан Д. Средојевић (sr), Daniel Nylander (sv), Theppitak + Karoonboonyanan (th), Maxim Dziumanenko (uk), Clytie Siddall (vi), + Funda Wang (zh_CN) + +2.14.1 +== + +The only change since 2.14.0 is to remove the "This is the UNSTABLE +branch" warning from configure for those compiling Metacity from +source. + +2.14.0 +== + +Thanks to Ryan Lortie and Thomas Thurman for fixes in this release. + + - Mark the app-running-remotely-window-title string for translation + (Thomas) [#334332] + - Only unmaximise window before freeing if the window is actually + maximised (Ryan) [#333563] + +Translations + Jordi Mallach (ca), Frank Arnold (de), Luca Ferretti (it), Evandro + Fernandes Giovanini (pt_BR), Theppitak Karoonboonyanan (th) + +2.13.144 +== + +Thanks to Jens Granseuer, Kristian, Søren Sandmann, Sylvain +Bertrand, and Thomas Thurman for improvements in this release. + + - Fix build with gcc 2.95 (Jens) [#331166] + - Compositor improvements [remember, still off by default]: add + unused wobbly (un)minimize animation (Kristian), add support for + turning updates on and off (Søren), use sync counter to make + composited resizing tear free (Søren), add ability to unmanage + the screen (Søren), + - Fix build issue with library search order (Sylvain) [#330695] + - Work around buggy application grouping with transient windows + (Thomas) [#328211] + - Prevent setting cycle_windows to keybindings that won't work. + (Thomas) [#329676] + +2.13.89 +== + +Thanks to Søren Sandmann, Thomas Thurman, Thom May, Akira Tagoh, +Luke Morton, and Philip O'Brien for improvements in this release. + + - Compositor improvements [remember that the compositor is still + disabled by default]: New fancy minimize animation that fades in + and out, new debug stuff, various bug fixes (Søren) + - When buggy apps create synthetic button or keypresses without a + timestamp, produce a warning instead of failing an assertion + (Thomas) [#313490] + - Avoid a memory leak when checking which workspace(s) a window is + on (Thomas) [#322059] + - Add a man page for metacity (Thom, Akira, Luke, Philip) [#321279] + - Disable alt-f7 if a window can't be moved, and alt-f8 if it can't + be resized (Thomas) [#328920] + - Allow alt-escape to cancel alt-tabbing, and vice versa (Thomas) + [#141425] + +Translations + Miloslav Trmac (cs), Kjartan Maraas (nb), Tino Meinen (nl), + Kjartan Maraas (no), Слободан Д. Средојевић (sr), Funda Wang (zh_CN) + +2.13.55 +== + +Thanks to Dick Marinus, Christian Kirbach, and Elijah Newren for +improvements in this release. + + - Add a minimize and none double-click-titlebar-action (Dick) + [#300210] + - Prevent a critical warning crasher when switching themes + (Christian) [#327847] + - Fix some uninitialized value problems (Elijah) + - If the mouse enters a window on a different screen, activate the + default window on the new screen (Elijah) [#319348] + +Translations + Jordi Mallach (ca), Adam Weinberger (en_CA), Francisco Javier + F. Serrador (es), Ilkka Tuohela (fi), Ignacio Casal Quinteiro (gl), + Ankit Patel (gu), Kjartan Maraas (nb), Kjartan Maraas (no), Evandro + Fernandes Giovanini (pt_BR), Theppitak Karoonboonyanan (th), Clytie + Siddall (vi), Funda Wang (zh_CN) + +2.13.34 +== + +Thanks to Damien Carbery, Havoc Pennington, Søren Sandmann, +Björn Lindqvist, Kjartan Maraas, Elijah Newren for improvements in +this release. + + - manually define HOST_NAME_MAX if not already defined to fix Solaris + compilation issue (Damien, Havoc) [#326745] + - compositor improvements: port to changes in libcm, do it again, fix + unrefing, make minimize animation update again (all done by Søren) + - make sure an outline border is shown even if a window decoration's + width is 0 (Björn) [#98340] + - correctly handle window alt-tab outlines in showing desktop mode + (Björn) [#98340] + - fix lots of tiny issues spotted by the intel compiler (Kjartan) + [#321439] + - prevent rapidly repeated visual bells from hanging metacity + (Elijah) [#322032] + - more careful error handling of values returned by GConf (Elijah) + [#326615] + - fix various initialization and default issues, especially for + running with --disable-gconf. Make --disable-gconf actually work. + (Elijah) [#326661] + - fix some reading-from-free'd-data errors (Søren) [#327575] + - fix an unitialized value problem when in raise-on-click mode + (Søren) [#327572] + - avoid flashing original-sized window when closing a maximized + window (Elijah) [#317254] + - prevent windows from sometimes getting shoved and smashed by + sliding (and possibly auto-hiding) panels (Elijah) [#327822] + +Translations + Ilkka Tuohela (fi), Ignacio Casal Quinteiro (gl), Tino Meinen (nl), + Funda Wang (zh_CN) + +2.13.21 +== + +Thanks to Damien Carbery, Ray Strode, Søren Sandmann, Elijah +Newren, Jens Granseuer, and Kyle Ambroff for improvements in this +release. + + - Fix Solaris compilation issues (Ray, Damien) [#326281, #326746] + - Merge compositor work from branches to get the beginnings of an openGL + based compositor. Still not ready and thus disabled by default. + (Søren) + - Composite fixes: Only update composite on damage events (Søren), get + non-composite compilation working again (Elijah), Really turn off + draw-in-a-loop (Søren) + - Don't dereference a NULL string (Elijah) [#327013] + - GCC 2.95 fix; remove more C99 style variable initiailizations (Jens) + [#327050] + - Fix accidental overzealous focus holding by the terminal (introduced in + last release) so that windows launched from panel icons, the panel + menu, or global keybindings should get focus now. (Elijah) [#326159] + - If no valid window is found in the MRU list, then set focus to the + desktop window. (Kyle) [#317405] + +Translations + Adam Weinberger (en_CA), Francisco Javier F. Serrador (es), Ankit + Patel (gu), Takeshi AIHANA (ja), Theppitak Karoonboonyanan (th), + Clytie Siddall (vi) + +2.13.13 +== + +Thanks to Jens Granseuer, Björn Lindqvist, and Elijah Newren for +improvements in this release. + + - Remove C99 style variable initiailization (Jens) [#322622] + - Fix a logic error (Björn) [#322149] + - Plug a few leaks (Elijah) [#309178] + - Allow edge resistance at both sides of a window and also when edges + don't overlap but are a single pixel away from doing so (Elijah) + [part of #321905] + - Remove the timeout resistance at screen/xinerama edges (Elijah) + [part of #321905] + - Revert to the old edge resistance behavior for keyboard + movement/resizing based resistance (Elijah) [part of #321905] + - Remove the "pull-away" edge resistance (Elijah) [part of #321905] + - Avoid crashing when visual bell is in use and focus window is + closed (Elijah) [#322031] + - Be more strict about what is considered a valid region with partial + struts (Elijah) [#322070] + - Fix reduced resources resize handling for windows with sizing or + resizing constraints (Elijah) [#325774] + - Fix window outline for minimized windows when using alt-esc + (Elijah) [#325092] + - Make the taskbar less flash happy and fix up some related stacking + issues (Elijah) [#326035] + - More thorough handling of source indication (Elijah) [part of #326041] + - Don't "steal" focus from terminal windows for new window mappings + as the difference in usage between terminals and other apps seems + to suggest this difference in treatment. See bug #326159 for + details, feedback welcome (Elijah) [#326159] + - Add a raise on click option, basically only because all the major + distros are patching it in anyway (though each and every one of + them has bugs in their implementations). (Elijah) [#326156] + +Translations + Kjartan Maraas (nb), Kjartan Maraas (no) + +2.13.8 +== + +Thanks to Kang Jeong-Hee and Elijah Newren for improvements in this +release. + + - Fix some compilation warnings and issues (Kang) + - Escape the title since it is going to be treated as Markup (Elijah) + [#324846] + - Make the workspace switcher work with dual-head (non-xinerama) + setups (Elijah) [#319423] + +Translations + Ilkka Tuohela (fi), Ankit Patel (gu), Kang Joeng-Hee (ko) + +2.13.5 +== + +Thanks to Davyd Madeley, Kjartan Maraas, and Björn Lindqvist for +improvements in this release. + + - Make a debugging message actually correspond to the code (Björn) + [#322051] + - Make the wireframe a bit slimmer (Kjartan) [#320051] + - Display hostname in titlebar for remote X clients (Davyd) [#322202] + +Translations + Miloslav Trmac (cs), Adam Weinberger (en_CA), Ankit Patel (gu), + Kjartan Maraas (nb), Kjartan Maraas (no), Marcel Telka (sk) + +2.13.3 +== + +This is a special edition release just for gicmo, code-named 'elijah, +please do a release so magic seb can bring it to me'. It fixes a +number of issues due to the major constraints changes found since the +last release. + +Thanks to Davyd Madeley and Elijah Newren for improvements in this release. + + - Differentiate between movement towards an edge and movement away from + one for edge-resistance. Pick smaller constants for movement away from + an edge (Elijah) + - Use GPOINTER_TO_INT() macro instead of cast to allow compilation on + 64-bit architectures without warning (Davyd) + - compute the frame geometry due to maximization only after actually + maximizing (Elijah) [#321902] + - add some developer documentation on updating struts, workareas, regions, + and edges (Elijah) + - When updating the xinerama due to placement, update which + maximal/spanning rect set to use as well (Elijah) [#322068] + - Relax the partially onscreen constraint to allow the titlebar to touch + the bottom panel in order to make the new constraints code function the + same as the old version (Elijah) [#322071] + - Don't allow removing a window from maximized or fullscreened state to + place the titlebar under the top panel (Elijah) [#322075] + +Translations + Vladimir Petkov (bg), Francisco Javier F. Serrador (es), Ignacio Casal + Quinteiro (gl), Takeshi AIHANA (ja), Theppitak Karoonboonyanan (th) + +2.13.2 +== + +This release just contains a merge of all the changes on the +constraints_experiments branch. + +Thanks to Havoc Pennington for reviewing the gargantuan patch and +suggesting lots of little fixes for making it better, to Rob Adams and +Soeren Sandmann for grilling me on how some of the difficult internals work +-- allowing me to improve the documentation, to Olav Vitters for finding an +easy-to-fix crasher bug in early testing and for repeatedly extending my +deadline for switching from working on Metacity to Bugzilla, to Ray Strode +for finding two crashers and fixing one of them in early testing, to Bryan +Clark for usability advice, to Davyd Madeley and Christian Kellner for +testing Xinerama stuff, to Sebastien Bacher for packaging an early version +and finding some obscure bugs (that I unfortunately still can't duplicate +and will probably still need to fix once I can), + +Bugs fixed: + unfiled - constraints.c is overly complicated[1] + unfiled - constraints.c is not robust when all constraints cannot + simultaneously be met (constraints need to be prioritized) + unfiled - keep-titlebar-onscreen constraint is decoration unaware (since + get_outermost_onscreen_positions() forgets to include + decorations) + unfiled - keyboard snap-moving and snap-resizing snap to hidden edges + 86644 - resize should have a shift option like move does + 109553 - gravity w/ simultaneous move & resize doesn't work + 113601 - maximize vertical and horizontal should toggle and be + constrained + 122196 - windows show up under vertical panels + 122670 - jerky/random resizing of window via keyboard[2] + 124582 - keyboard and mouse snap-resizing and snap-moving erroneously + moves the window multidimensionally + 136307 - don't allow apps to resize themselves off the screen (*cough* + filechooser *cough*) + 142016, 143784 - windows should not span multiple xineramas unless + placed there by the user + 143145 - clamp new windows to screensize and force them onscreen, if + they'll fit + 144126 - Handle pathological strut lists sanely[3] + 149867 - fixed aspect ratio windows are difficult to resize[4] + 152898 - make screen edges consistent; allow easy slamming of windows + into the left, right, and bottom edges of the screen too. + 154706 - bouncing weirdness at screen edge with keyboard moving or + resizing + 156699 - avoid struts when placing windows, if possible (nasty a11y + blocker) + 302456 - dragging offscreen too restrictive + 304857 - wireframe moving off the top of the screen is misleading + 308521 - make uni-directional resizing easier with alt-middle-drag and + prevent the occasional super annoying resize-the-wrong-side(s) + behavior + 312007 - snap-resize moves windows with a minimum size constraint + 312104 - resizing the top of a window can cause the bottom to grow + 319351 - don't instantly snap on mouse-move-snapping, remove + braindeadedness of having order of releasing shift and + releasing button press matter so much + + [1] fixed in my opinion, anyway. + [2] Actually, it's not totally fixed--it's just annoying + instead of almost completely unusable. Matthias had a + suggestion that may fix the remainder of the problems (see + http://tinyurl.com/bwzuu). + [3] This bug was originally about not-quite-so-pathological + cases but was left open for the worse cases. The code from + the branch handles the remainder of the cases mentioned in + this bug. + [4] Actually, although it's far better there's still some minor + issues left: a slight drift that's only noticeable after + lots of resizing, and potential problems with partially + onscreen constraints due to not clearing any + fixed_directions flags (aspect ratio windows get resized in + both directions and thus aren't fixed in one of them) + +New feature: + 81704 - edge resistance for user move and resize operations; in + particular 3 different kinds of resistance are implemented: + Pixel-Distance: window movement is resisted when it aligns with an + edge unless the movement is greater than a threshold number of + pixels + Timeout: window movement past an edge is prevented until a certain + amount of time has elapsed during the operation since the first + request to move it past that edge + Keyboard-Buildup: when moving or resizing with the keyboard, once a + window is aligned with a certain edge it cannot move past until the + correct direction has been pressed enough times (e.g. 2 or 3 times) + +Major code changes: + - constraints.c has been rewritten; very few lines of code from the old + version remain. There is a comment near the top of the function + explaining the basics of how the new framework works. A more detailed + explanation can be found in doc/how-constraints-works.txt + - edge-resistance.[ch] are new files implementing edge-resistance. + - boxes.[ch] are new files containing low-level error-prone functions + used heavily in constraints.c and edge-resistance.c, among various + places throughout the code. testboxes.c contains a thorough testsuite + for the boxes.[ch] functions compiled into a program, testboxes. + - meta_window_move_resize_internal() *must* be told the gravity of the + associated operation (if it's just a move operation, the gravity will + be ignored, but for resize and move+resize the correct value is needed) + - the craziness of different values that + meta_window_move_resize_internal() accepts has been documented in a + large comment at the beginning of the function. It may be possible to + clean this up some, but until then things will remain as they were + before--caller beware. + - screen and xinerama usable areas (i.e. places not covered by + e.g. panels) are cached in the workspace now, as are the screen and + xinerama edges. These get updated with the workarea in + src/workspace.c:ensure_work_areas_validated() + +Translation + Michiel Sikkes (nl) + +2.13.1 +== + +Thanks to Philip O'Brien, Kjartan Maraas, and Aidan Delaney for +improvements in this release. + + - add handling for META_PREF_CURSOR_THEME and META_PREF_CURSOR_SIZE + for more complete debug info (Philip) [#318976] + - Remove possible g_source leak in #ifdef'd out code, in case anyone uses + it in the future (Kjartan) [#320050] + - Changed the 'minimized' field of the MetaTabEntry struct to 'hidden' + (Aidan) [#168455] + +Translations + Miloslav Trmac (cs), Francisco Javier F. Serrador (es), Takeshi AIHANA (ja), + Erdal Ronahi (ku), Theppitak Karoonboonyanan (th) + +2.13.0 +== + +Thanks to Björn Lindqvist, Kjartan Maraas, Søren Sandmann, +Elijah Newren, Ross Cohen, and Muktha for improvements in this release +since 2.12.1. + + - Mave ancestors come along with the transient when moving the window from + one workspace to another (Björn) [#314977] + - Fix the workspace switcher tabpopup to display the right windows and to + fix the pick-a-new-window-to-focus algorithm in order to not select + windows that aren't showing (Björn) [#170475] + - Fix a couple memory leaks (Kjartan, Søren, Elijah) [#313030] + - Make alt-esc (the "switch between windows immediately" keybinding) + actually show minimized windows too (Ross) [#107072] + - Make alt-esc consistent with alt-tab by leaving stacking of unselected + windows unchanged (Ross) [#314285] + - Clarify the meaning of the auto_raise preference (Elijah) [#312421] + - Fix a crash that occurs when removing some virtual desktops and windows + happen to be on those desktops (Elijah) [#318306] + - Make the unfocussed Simple window border visible with high contrast + inverse theme (Muktha) [#121361] + - Fix edge snapping for multi-screen (non-xinerama) setups (Elijah) + [#319425] + +Translations + Vladimir Petkov (bg), Kostas Papadimas (el), Adam Weinberger (en_CA), + Ivar Smolin (et), Michiel Sikkes (nl), Marcel Telka (sk), Funda + Wang (zh_CN) + +2.12.1 +== + +Thanks to Ray Strode, Havoc Pennington, and Elijah Newren for +improvements in this release. + + - Truncate ridiculously long titles to avoid crashing or letting the + pager crash (Ray, Havoc, Elijah) [#315070] + - Get the tabbing window outline to work with gtk+ 2.8.4 again + (Elijah) [#317528] + +Translations + Mahay Alam Khan (bn), Francisco Javier F. Serrador (es), Ivar Smolin (et), + Iñaki Larrañaga Murgoitio (eu), Luca Ferretti (it), Christian Rose (sv), + Clytie Siddall (vi), Funda Wang (zh_CN) + +2.12.0 +== + +Thanks to Brent Smith for finding the crasher in the release candidate! + + - Fix an uninitialized variable problem causing crashes (Brent) [#315000] + +Translations + Bryn Salisbury (cy), Hendrik Richter (de), Christophe Merlet (RedFox) (fr), + Ignacio Casal Quinteiro (gl), Norayr Chilingaryan (hy), Young-Ho Cha (ko), + Žygimantas Berucka (lt), Michiel Sikkes (nl), Leonid Kanter (ru), Danilo + Å egan (sr), Baris Cicek (tr) + +2.11.3 +== + +Thanks to Björn Lindqvist and Elijah Newren for improvements in +this release. + + - Check for the right versions of glib and gtk+ (Björn) [#314116] + - Avoid obscuring centered-on-desktop windows which are denied focus + (Elijah) [#313234] + +Translations + Vladimir Petkov (bg), Jordi Mallach (ca), Kostas Papadimas (el), + Ivar Smolin (et), Gabor Kelemen (hu), Mohammad DAMT (id), Duarte + Loreto (pt), Mugurel Tudor (ro), Laurent Dhima (sq), Maxim + Dziumanenko (uk) + +2.11.2 +== + +Thanks to Elijah Newren, Jaap Haitsma, Ray Strode, and Brent Smith for +improvements in this release. + + - Fix an easy to trigger crasher in 2.11.1 caused by unneeded + debugging spew (Elijah) [#311819] + - Make sure that Metacity dialogs have icons (Jaap) [#309876] + - Fix an infinite restacking flicker loop in sloppy and mouse focus + with fullscreen windows (Elijah) [#311400] + - Change default theme from Simple to Clearlooks (Elijah) + - Vastly improve the behavior of keyboard move/resize and edge + snapping (Ray) [#310888] + - Remove a duplicate string (Brent) [#309774] + +Translations + Yuval Tanny (he), Gnome PL Team (pl), Raphael Higino (pt_BR), + Chao-Hsiung Liao (zh_TW) + +2.11.1 +== + +Thanks to Elijah Newren, Ken Harris, Matthias Clasen, Christian +Persch, and Billy Biggs for improvements in this release. + + - Fix a miscoloring of parts of the titlebar introduced in the last + unstable release (Elijah) [follow-up to #169982] + - Provide a more lenient threshold for drawing rounded corners (Ken) + [#122065] + - Make the Xcursor changes in the last unstable release effective + (Matthias) [follow-up to #308106] + - Revert the _NET_ACTIVE_WINDOW behavior change made in the 2.9.x + unstable series; activation includes changing a window to the + current workspace again (Elijah) [reversion of #128380] + - Restore original window size if the window was maximized upon + withdrawing it (Elijah, Christian) [#137185] + - Fix a raising bug with a window that has more than one child window + (Elijah, Billy) [part of #307875] + - Try to place windows denied focus near the focus window and fix a + xinerama bug with the placement (Elijah) [part of #307875] + - Avoid modal dialogs being obscured in somewhat pathologically + strange circumstances that Eclipse seems to be good at triggering + (Elijah) [part of #307875] + +Translations + Miloslav Trmac (cs), Kostas Papadimas (el), Adam Weinberger (en_CA), + Francisco Javier F. Serrador (es), Ilkka Tuohela (fi), Christophe + Merlet (RedFox) (fr), Ignacio Casal Quinteiro (gl), Ankit + Patel (gu), Yair Hershkovitz (he), Takeshi AIHANA (ja), Kjartan + Maraas (nb), Kjartan Maraas (no), Marcel Telka (sk), Theppitak + Karoonboonyanan (th), Clytie Siddall (vi), Funda Wang (zh_CN) + +2.11.0 +== + +This release contains all fixes up to Metacity 2.10.2 plus some new goodies. + +Thanks to Matthias Clasen, Aivars Kalvans, Björn Lindqvist, and +Andrew Johnson for improvements in this release. + + - React to cursor theme changes (Matthias) [#308106] + - Plug a small leak with xinerama information (Aivars) [#307884] + - Split up main() into more manageable chunks and make use of GOpt + (Björn) [#305331] + - Speed up vertical gradients (Andrew) [#169982] + +Translations + Hendrik Richter (de), Ivar Smolin (et), Ignacio Casal + Quinteiro (gl), Clytie Siddall (vi) + +2.10.2 +== + +Thanks to Billy Biggs, Greg Hudson, Elijah Newren, Ray Strode, Ryan +Lortie, and Soeren Sandmann for improvements in this release. + + - Makes metacity a bit faster when dragging windows around (Soeren) [#141813] + - Fix simple memory error, using the address of a local variable as a + hash key (Ryan) [#307209] + - Fix a small leak in the case of a SYNC_COUNTER property value and + HAVE_XSYNC not defined (Ryan) [#307214] + - Cleanup font data when done with it (Ray) [#306720] + - If the window has a modal transient which is being unmanaged, don't + focus it (Elijah) [#305362] + - Make sure window position is calculated correctly for reconfigure + requests when part of the XWindowChanges structure is uninitialized + (Greg) [#305257] + - Add a resize popup when resizing constrained windows (Ray) [#305564] + - Don't accidentally treat maximize vertically as maximize in both + directions (Elijah) [#302204] + - Put all transients of the new window, if any exist, in the + calc_showing queue (Elijah, Billy) [#303284] + +Translations + Kostas Papadimas (el), Priit Laes (et), Pauli Virtanen (fi), Ignacio + Casal Quinteiro (gl), Theppitak Karoonboonyanan (th), Canonical + Ltd (xh), Woodman Tuen (zh_TW) + +2.10.1 +== + +This is a stable release to coincide with the release of Gnome 2.10.0. + +Thanks to Dan Winship and Lex Hider for fixes in this release. + + - Make sure the "Close" button has the focus in the + buggy-session-management-applications-warning dialog instead of the + table (Dan) [#172703] + - add doc/code-overview.txt and doc/how-to-get-focus-right.txt to the + distributed files (Lex) [#170519] + +Translations + Adam Weinberger (en_CA), Christopher Orr (en_GB), Elnaz Sarbar (fa), + Gabor Kelemen (hu), Jyotsna Shrestha (ne), Steve Murphy (rw), + Baris Cicek (tr), Canonical Ltd (xh) + +2.10.0 +== + +This is a stable release to coincide with the release of Gnome 2.10.0. +The only difference between this version and 2.9.34 is some +translation updates. + +Translations + Vladimir Petkov (bg), Gabor Kelemen (hu), Žygimantas Berucka (lt), + Reinout van Schouwen (nl), Mugurel Tudor (ro), Danilo Å egan (sr), + Woodman Tuen (zh_TW) + +2.9.34 +== + +This is an unstable release to coincide with the release of Gnome +2.10.0 release candidate 1 (2.9.92). + +Thanks to Aidan Delaney, Elijah Newren, and Joe Marcus Clarke for +fixes in this release. + + - Fix crash that occurs when stupid apps claim that a window is its + own parent (Elijah, Joe) [#168207] + - Prevent the visual bell from changing the focus window (Elijah) + [#123366] + - Make sure that icons in the alt-tab popup are dimmed for all hidden + windows, not just minimized ones (Aidan) [#168455] + +Translations + Elnaz Sarbar (fa), Ankit Patel (gu), Luca Ferretti (it), + Reinout van Schouwen (nl), Gnome PL Team (pl), + Alexandre Folle de Menezes (pt_BR) + +2.9.21 +== + +This is an unstable release heading towards Gnome 2.10. Since there +have been an awful lot of fixes since Gnome 2.10 Beta 2, we are hoping +to get an extra week of wider testing of all these changes before hard +code freeze. + +Thanks to Aidan Delaney, Crispin Flowerday, Elijah Newren, and Joe +Marcus Clarke for fixes in this release. + + - Make sure we get a valid timestamp if one doesn't come with the + _NET_ACTIVE_WINDOW message (Elijah, Crispin) [#166728] + - Avoid sending CurrentTime to our XSetInputFocus wrappers, but + handle it better in case we miss any cases (Elijah) [#166732] + - Remove useless function call (Aidan) [#166730] + - Avoid new windows being obscured by the focus window and thus + possibly lost (Elijah) [#166524] + - Don't unconditionally place not-to-be-focused windows, such as + splashscreens, below the focus window (Elijah) [#167042] + - Raise the ancestor of a window instead of the window itself + (Elijah) [#166894] + - Cover half a dozen issues needed to fix a variety of rare timestamp + bugs (Elijah) [#167358] + - Fix a possible crash on logout (Joe) [#167935] + - Fix an obscure xinerama placement bug with windows that are too + large to fit in the workarea in both dimensions (Elijah) [#166757] + - Ignore all focus and focus-stealing-prevention code in + meta_window_show when not showing the window for the first time + (Elijah) [#167199] + - when receiving a _NET_ACTIVE_WINDOW message, switch to the desktop + where the window is located before activating instead of moving the + window to the current desktop (Elijah) [#128380] + - Handle _NET_CURRENT_DESKTOP messages that come with timestamps + (Elijah) [#161361] + - Handle keynav vs. mousenav in mouse and sloppy focus modes (Elijah) + [#167545] + +Translations + Jordi Mallach (ca), Martin Willemoes Hansen (da), + Kostas Papadimas (el), David Lodge (en_GB), + Francisco Javier F. Serrador (es), Tõivo Leedjärv (et), + Christophe Merlet (RedFox) (fr), Takeshi AIHANA (ja), + Young-Ho, Cha (ko), Kjartan Maraas (nb), Michiel Sikkes (nl), + Kjartan Maraas (no), Duarte Loreto (pt), Leonid Kanter (ru), + Marcel Telka (sk), Laurent Dhima (sq), Maxim Dziumanenko (uk) + +2.9.13 +== + +This is an unstable release to coincide with the release of Gnome +2.10.0 Beta 2 (2.9.91). + +Thanks to Elijah Newren, Balamurali Viswanathan, Stephane Loeuillet, +Benjamin Kahn, Garrett (LeSage?), Jose Moya, Dave Ahlswede, Arvind +Samptur, John Paul Wallington, Tim Herold, Muktha Narayan, Sinisa +Segvic, Owen Taylor, Crispin Flowerday, "RHEL-3", KWin, and Google for +improvements in this release. + + - Refuse to focus a window with a modal transient, and focus the + transient instead (Elijah) [#164716] + - Make sure we get gconf notifications about the terminal command + changing (Balamurali) [#160934] + - Specify encoding of src/metacity.desktop.in (Stephane) [#151850] + - New 48x48 default icon (Benjamin, Garrett) [#160660] + - Add man pages for metacity-window-demo and metacity-theme-viewer + (Jose, Dave) [#143513] + - Fix minimized window display in workspace switcher after relogin + with a saved session (Elijah) [#164677] + - Ignore sticky windows for non-active workspaces (Elijah) [#165259] + - Don't wireframe when accessibility is on, it apparently causes a + desktop wide freeze. (Arvind) [#159538] + - Keep tooltip on screen horizontally for xinerama (John) [#165261] + - Stick and unstick transients with their parent automatically + (Elijah) [#152283] + - Shaded windows should not show up in pagers (Elijah) [#165377] + - Treat splashscreens same as other windows for stacking (Elijah) + [#165243] + - Plug a pair of leaks (Elijah) [#165378] + - Take into account the appropriate list of windows when placing a + new one (Elijah) [#165381] + - Correct misleading and inaccurate wording (Elijah) [#165380] + - Handle xcomposite pkgconfig version regression (Tim) [#149368] + - Make the warn-about-buggy-session-management-apps dialog be sticky + (Elijah) [#164745] + - Fix the problem with fullscreen windows on a different xinerama + monitor not staying on top ("RHEL-3") [#156511] + - Make the unfocussed title bar distinguishable in cases where it + otherwise isn't for the Atlanta, Simple, and Bright themes (Muktha) + [#125291] + - Correct the stacking when returning from fullscreen mode (Elijah) + [#165718] + - Focus parents of dismissed transient windows in preference to the + window that most recently had keyboard focus (Elijah) [#157360] + - Make sure window->border_only is initialized so we don't get random + windows without decorations (Elijah, Sinisa, Owen) [#145131] + - Add period to the end of reduced_resources' description (Dave) + [#165780] + - If activation requests are too old, set the demands_attention hint + instead of actually activating (Elijah, Crispin) [#166395] + - Ignore xconfigurerequest events for stacking when it should be safe + to do so (Elijah, Crispin, KWin, Google) [#166395] + - Set a _METACITY_VERSION property (a utf8 string) on the WM check + window (Elijah) [#165350] + +Translations + Vladimir Petkov (bg), Miloslav Trmac (cs), Frank Arnold (de), + Adam Weinberger (en_CA), David Lodge (en_GB), + Francisco Javier F. Serrador (es), Pauli Virtanen (fi), + Young-Ho, Changwoo Ryu (ko), Žygimantas Berucka (lt), + Kjartan Maraas (nb), Kjartan Maraas (no), Duarte Loreto (pt), + Marcel Telka (sk), Christian Rose (sv), + Theppitak Karoonboonyanan (th) + +2.9.8 +== + +This is a brown paper bag release to cover up the crash I introduced +in version 2.9.5. Thanks to Sebastien Bacher and the bleeding edge +Ubuntu users for quickly catching the occasional crash that my fix in +#123576 could cause, and for verifying that the patch I made fixed +this issue (I couldn't duplicate). + + - Don't forget to initialize display->grab_old_window_stacking + [#165093] + +2.9.5 +== + +This is an unstable release to coincide with the release of Gnome +2.10.0 Beta 1 (2.9.90). + +Thanks to Vincent Noel, Elijah Newren, and John Paul Wallington for +fixes in this release. + + - Restore original stacking when aborting an alt-esc window switch + operation (Elijah) [#123576] + - Fix vertical maximization for second screen (John) [#163420] + - Show labels in bold for windows that demand attention (Vincent) + [#164590] + - In the tab task switcher popup, dim the window icon and put its + name between brackets when the window is minimized (Vincent) + [#136666] + - Correct highlighting of windows in workspace switcher popup + (Elijah) [#163450] + +Translations + zh_CN (Funda Wang), nb (Kjartan Maraas), nn (Kjartan Maraas), de + (Frank Arnold) + +2.9.3 +== + +This is an unstable release to coincide with the release of Gnome 2.9.4. + +Thanks to Leena Gunda, Thomas Fitzsimmons, and mild7 users sourceforge +net, and Elijah Newren for fixes in this release. + + - Don't focus the panel on click (Elijah) [#160470, and others] + - Make sure the save session dialog appears focused (Elijah) [#162983] + - Correctly restore size of window when double clicking the titlebar + to unmaximize (Leena) [#161236] + - Install schema data from builddir not srcdir (Thomas) [#161417] + - Provide more documentation to make it easier for people to + contribute to Metacity (Elijah) [#162646] + - Allow users to move the window around immediately after + double-clicking to shade (Elijah) [#90290] + - Focus windows that manually position themselves too (Elijah) [#107347] + - Don't show window menu if all options are invalid (Elijah) [#148915] + - Exclude windows with skip_taskbar hint set from the alt-tab list; + they'll appear in the ctrl-alt-tab list instead. (mild7 users + sourceforge net) [#106249] + - Wrap XSetInputFocus to make display->expected_focus_window more + reliable (Elijah) [#154598] + - Remove conflict between windows on multiple workspaces and hidden + being a global quantity (Elijah) [#156182] + +Translations + es (Francisco Javier F. Serrador), sv (Christian Rose), cs (Miloslav + Trmac), ja (Takeshi AIHANA) + +2.9.2 +== + +This is an unstable release to coincide with the release of Gnome 2.9.3. + +Thanks to Alex Duggan, ash AT contact bg, Elijah Newren, and Baptiste +Mille-Mathias for fixes in this release. + + - Add a missing period at the end of a sentence (Baptiste) [#158210] + - When snap-moving don't snap to hidden windows, such as transients + of minimized windows (Elijah) [#157180] + - Focus the desktop when showing it (Elijah) [#159257] + - Remove deprecated capplet (Alex, ash) [#160753] + +Translations + da (Martin Willemoes Hansen), bg (Alexander Shopov), en_CA (Adam + Weinberger) + +2.9.1 +== + +This is an unstable release heading towards Gnome 2.10, released a +little late for Gnome 2.9.2 but there weren't many changes anyway this +time... + +Thanks to Benjamin Kahn, Marco Pesenti Gritti, James Henstridge, and +Vincent Untz for fixes/features in this release. + + - gnome-panel-screenshot was renamed to gnome-screenshot (Vincent) [#157529] + - Update build stuff (use newer automake, etc.) (James) + - Fix build out of src directory (Marco) [#158325] + - Use a better default application icon (Benjamin) [#160373] + +Translations + da (Martin Willemoes Hansen), fr(Christophe Merlet, Baptiste + Mille-Mathias), lt(Žygimantas Berucka), ja(Takeshi AIHANA) + +2.9.0 +== + +This is an unstable release heading towards Gnome 2.10. + +Thanks to Rob Adams, Anders Carlsson, Elijah Newren, Soeren Sandmann, +and Vincent Untz for fixes and features in this release. + + - Add a keybinding to launch a terminal (Vincent) [#154232] + - Correct the requested number of keycodes (Rob) [#155247] + - Add tracker bugs to rationales.txt file + - Make the "showing desktop" mode be per-workspace instead of + per-screen. (Elijah) [#142198] + - Don't try to use an ARGB visual at all if the depth isn't + 32-bit. This caused major slowdowns with Composite + enabled. (Anders) + - Fix the modifier key breakage introduced by an Xorg + change. (Soeren) [#151554] + - Update _NET_WM_STATE_HIDDEN so the pager on the panel will know + whether to display windows as visible or hidden (Elijah) [#105665] + - Fix the alt-tab order--if the most recently used window is not + focused, start alt tabbing with that window instead of the one + after it (Elijah) [#156251] + - Don't lower newly mapped windows when they're denied focus if they + are transients of the focused window. Instead, defocus the + currently focused window (Elijah) [#151996] + - Re-enable focus stealing prevention (Elijah) + +Translations + es(Francisco Javier F. Serrador), sq(Laurent Dhima), sr(Danilo Å egan), + cs(Miloslav Trmac), en_CA(Adam Weinberger), en_GB(David Lodge) + +2.8.6 +== + +This is a stable release for Gnome 2.8.1. + +Thanks to the Ken Harris, Kjartan Maraas, and the tireless efforts of +Elijah Newren for fixes in this release. + +Fixes + * Ensure the correct window is focused when minimizing (Elijah) + * Fix keynav with mouse focus (Elijah) + * Fix several race conditions in window focusing (Elijah) + * Focus the top window when lowering by frame click (Ken) + * Fix some compiler warnings (Kjartan) + * Fix some valgrind-reported errors (Elijah) + * Fix some potential issues with autoraising windows (Elijah) + +Translations + * en_CA(Adam Weinberger), it(Luca Ferretti) + +2.8.5 +== + +This is a stable release for Gnome 2.8. Only translations and some +new developer documentation were added since the last unstable release. +This release boasts improved standards-compliance and a number of +bug fixes since the last stable release. + +Translations + + * ar(Abdulaziz Al-Arfaj), cs(Miloslav Trmac), cy(Dafydd Harries), + en_GB(David Lodge), fr(Christophe Merlet (RedFox)), + nn(Åsmund Skjæveland), or(Gora Mohanty), + pr_BR(Gustavo Noronha Silva), ro(Mugurel Tudor), + th(Paisa Seeluangsawat), tr(Baris Cicek), zh_TW(Woodman Tuen) + +2.8.4 +== + +This release features a number of bug fixes, and also the disabling of +the focus-stealing-prevention code (we're entering hard code freeze in +Gnome so it's too late to fix the remaining issues, especially since +it requires several patches to modules other than Metacity). + +Thanks to Havoc Pennington, Soeren Sandmann, Elijah Newren, and Rich +Wareham for fixes in this release + +Fixes + * track the last_xor_rect, for wireframe painting (Havoc) + * Move wireframe code before grab is released to prevent endless + loops with fullscreen windows. (Soeren) + * Make dialogs that Metacity shows follow focus-stealing-prevention + conventions. (Elijah; part of #149028) + * add render extension check to the display, don't build the + compositing manager by default, use an ARGB visual when available + for the window frame (Rich Wareham; various tweaks added later by + Havoc) + * move the have_xrender variable initialization up in the file since + it can be set as part of composite check (Havoc) + * make argb stuff compile, add some code from xcompmgr (Havoc) + * fix an assertion failure that would occur after increasing the + number of workspaces; fix stacking order when a window is denied + focus (Elijah; #150615) + * disable some compositor code that wasn't working, don't grab the + server during repaint, various set_background fixes and + refactoring (Havoc) + +Translations + * az(Metin Amiroff), bs(Kemal Sanjta), ca(Jordi Mallach), + el(Kostas Papadimas), es(Francisco Javier F. Serrador), + eu(Iñaki Larrañaga Murgoitio), fi(Pauli Virtanen), + nb(Kjartan Maraas), sq(Laurent Dhima), uk(Maxim Dziumanenko) + + +2.8.3 +== + +Some important bug fixes in this release, including somy a11y bugs, +and a compile issue on Solaris. + +Thanks to Rob Adams, Bill Haneman, Peter O'Shea, Mike Castle, Soeren +Sandman, Elijah Newren, and Havoc Pennington for fixes in this +release. + +Fixes + * Adjust the MRU list when preventing focus stealing (Elijah) + * Ensure that we maintain a focus window when switching workspaces + in mouse focus mode (Elijah) + * Some improvements in the showing desktop mode, and window + activation (Elijah) + * Make sure cursors changes are handled correctly (Havoc, Soeren) + * Some fixes to the window menu (Rob) + * Fix a compile issue on Solaris (Peter, Mike) + * Allow struts to go past the middle of the screen, provided there's + a gap between them, fixing an issue with gnome magnifier (Bill) + +Translations + * fi (Pauli Virtanen), ja (Takeshi AIHANA), ko (Young-Ho, Cha), + pl (Gnome PL Team), ru (Dmitry G. Mastrukov), sr (Danilo Å egan), + tk (Gurban M. Tewekgeli), zh_CN (Funda Wang) + +2.8.2 +=== + +Many bugfixes and better support for the freedesktop.org EWMH spec. + +Thanks to Rob Adams, Anders Carlsson, Elijah Newren, Soeren Sandmann, +Emil Soleyman-Zomalan, Michael Terry, and Jeff Waugh for fixes in this +release. + + - set titlebar_uses_system_font = false (it was ugly) + - make naming for "move a window"/"move the window"/"move window" + more consistent (fixes #142235) + - Add trailing quotes to keybinding explanation text. + - support for EWMH update counter spec & add compensation events + when events are ignored. (fixes #143333 and #109362) + - Fix focus bugs: remove race condition on window close/minimize + (#131582), make focus choice consistent for each focus mode + (#135810), choose correct focus window when "un-showing the + desktop (#144900), make sure correct window is focused when using + the workspace switcher (#120100). + - Use meta_topic instead of meta_warning when failing to connect to + a session manager; reduces metacity verbosity. (fixes #136218) + - Make meta_window_delete take a timestamp, and be sure to pass it + one. + - Add support for EWMH _NET_WM_USER_TIME spec. This enables part of + preventing focus stealing. (bug #118372) Also fix bug with + windows not being focused on unminimizing caused by original + patch. (also bug #118372) + - Fix some support for EWMH hints, and fix USER_TIME support to + include the DEMANDS_ATTENTION hint. Also includes some code for + implementing _NET_RESTACK_WINDOW and _NET_MOVERESIZE_WINDOW, but + this is disabled pending feature thaw. + +2.8.1 +=== + +Thanks to Olivier Crete, Jarrod Johnson, Neil Muller, Elijah Newren, +Mark McLoughlin, Rob Adams, and foser AT gentoo.org for fixes in this +release. + + - make the --enable-xinerama switch work properly + - prevent unwanted grab op from occurring + - don't down-size nitems from a gulong to an int + - add a value type check for the visual/audible bell gconf settings + - make the no sm support warning resizable + - more translations + +2.8.0 +=== + +No code changes in this release, but some new translations. + +2.7.1 +=== + +Thanks to Rob Adams for fixes in this release. + + - bug #122016 - fix a focus race + - Change move_to_workspace_left/right/up/down keybindings to + arrow to avoid conflicting with new + keybindings in spacial nautilus. + - fix dialog stacking order issues so e.g. panel properties + dialog is above the panel + +2.7.0 +=== + +First unstable release tarball for GNOME 2.6. + +Thanks to Anders Carlsson, Elijah Newren, Rob Adams, James Cape, +Thomas Fitzimmons, Calum Benson for fixes in this release. + +2.6.2 +=== + +Thanks to Yukihiro Nakai, Rached Ben Mustapha, Gwenole Beauchesne, +Padraig O'Briain, Laurent Vivier, Rob Adams for contributions to this +release. + + - fix to repaint after resize always, so on maximize + and theme changes we get things drawn properly + - fix a compile issue on HPUX + - fix translations of metacity-message output + - fix to update window icons when they change + - put a limit on number of characters displayed in + window titles during Alt+tab + - fix configure check for Xrandr + - fix 64-bit bug in property reading that broke + things badly on 64-bit + - don't move focus when clicking close button on a window + - fix a crash in getting pixmap icons + - spawn dialogs and child processes on the proper + screen in multihead situations + - if the focus gets set to None, set it back to + something sane + - load accessibility modules and set accessibility roles + - fix hang after displaying warning dialogs + - fix a memory corruption when sticking/unsticking windows + that lead to a frequent crash and windows appearing + in Alt+tab improperly + - fix some handling of partial-width panel struts + - more translations + +2.6.1 +=== + + - rebuild with fixed glib-gettext.m4 + +2.6.0 +=== + + - some additional translations + +2.5.5 +=== + + Thanks to Rob Adams, Arvind Samptur, Andreas Volz, Ray Strode, John + Paul Wallington, Soeren Sandmann for contributions to this release. + And as always thanks to the translators. + + - fix aspect ratio handling + - fix "shake loose" functionality for maximized windows + - handle Xrandr size changes properly again + - fix fullscreen window detection + - fix workspace name handling + - don't steal button press events on root window + - nuke metacity.spec due to nonmaintenance + - allow too-large-for-screen windows to move their titlebar offscreen + - keep an MRU list of windows per-workspace and use it to focus + the next window when the focused window disappears + - fix cursor when moving + - improve appearance of opaque resize + - make BELOW window state work + - fix a crash when gdk_pixmap_foreign_new() returned NULL + +2.5.3 +=== + + Thanks to Jordi Mallach, Padraig O'Briain, Rob Adams, Julio Merino, + Ben Jansens, Jurg Billeter, Ray Strode, marcus@freebsd.org, James + Laska, for contributions to this release. Thanks also to + all the tireless translators. + + - fixups to .desktop file + - activate window prior to grab end, avoiding + extra focus events + - add support for partial-width panels (fixes corner panel + and xinerama window position constraints) + - added keybinding to toggle window as "always on top" + - support --disable-schemas-install option to configure + - destroy support for legacy GNOME 1.x hints; metacity + no longer works with GNOME 1.x + - disable raise-on-click for mouse focus modes + - fix bug that broke many Javascript popup menus with mozilla + - allow "shaking loose" maximized windows, to move them + between Xinerama heads or whatever + - honor desktop-wide double click timeout + - handle window placement properly for windows that + start out maximized + - integrate Ximian patch to go ahead and log out after 4 minutes + even if a dialog is open + - fix a segfault + - fix bug where window groups weren't always kept up to date + - fix bug where focus got confused when switching workspaces + with mouse focus mode + - fix 64-bit crash on s390x + - chdir to user's homedir on startup + - keep window in fullscreen layer when its transients are focused + - fix keybindings bug when you had ScrollLock enabled + - many translation updates + +2.5.2 +=== + + Thanks to David Santiago, Julien Olivier, Anders Carlsson, Rob Adams + for fixes in this release. + + - improved wording/UI for some dialogs + - while clicking a window button, if you move the mouse outside + the button such that releasing the mouse button won't activate + the window button, visually indicate by "popping out" the button. + - fix some valgrind errors + - change "show desktop mode" to convert to "everything is minimized + mode" if you open a new window while showing desktop, rather + than previous behavior of simply leaving show desktop mode. + - fix a trivial memory leak + - change "move to workspace N" so it doesn't switch workspaces, + just moves the window. + - translation updates + +2.5.1 +=== + + Thanks to Rob Adams, Peter O'Shea, Dafydd Harries, Masahiro Sakai, + Soeren Sandmann for fixes in this release. + + - fix bug where fullscreen windows were below top panels + - build fix for Solaris + - support diagonal window movement with numeric keypad + - multihead fix + - build fix for Cygwin + - place on xinerama containing the pointer + - fix totally hosed window placement/movement for frameless + windows + - improvement to smoothness of window move/resize + +2.5.0 +=== + + Thanks to Rob Adams, Owen Taylor, Frederic Crozat, Arvind Samptur, + Bill Haneman, Akira Tagoh for help with fixes in this release. + + - many new translations + - fix an infinite loop while holding a server grab triggered by + some recent Qt versions doing weird stuff + - fix bug where Alt+rightclick repeatedly on titlebar resulted + in zillions of menus + - fix Alt+Tab to *actually* put minimized windows at the end, + though this was always intended + - rewrite size/positions constraint code (currently known + to be quite buggy, e.g. xmms is hosed) + - enforce size of at least 1x1 on windows + - reduce latency of managing new windows still further + by using async properties code in more places + - don't grab keybindings on docks, so gnome-panel + can handle them + - suck in the panel's screenshot and run dialog global + bindings + - lots of improvements to window placement + - sync max number of workspaces with pager applet + - fix to keep focus when inside window frame in + strict mouse focus mode + - make it possible to start a reverse tab with + shift+alt+tab (vs. alt+tab then shift) + - fix a multihead issue with constraints between two + windows on different heads + - require GTK+ 2.2.0 and fontconfig + - default theme is now Simple + - add visual bell feature + - incorporate many fixes from 2.4.34 + - other stuff + +2.4.13 +=== + + - we were making all dialogs skip the taskbar, even non-transient + ones, though this was supposedly fixed a while ago. Now really + fixed. + - change back to Alt+click by default for the window drag feature. + - assign Alt+F12 to shade window + - fix not deleting enough workspaces when the number + was reduced via the pager config dialog (readams@hmc.edu) + - don't allow windows under the top panel ever, even if they + are tall windows (Arvind) + - fix up the window layout for directional workspace nav, + so you always stop at the edges and always end up + where you expect (hp, with tweaks from readams@hmc.edu) + - focus new windows in mouse focus mode (readams@hmc.edu) + - support xeyes, oclock, etc. by applying shape mask + to the window manager frame (yeah it resizes slow, deal) + - fix vertical/horizontal maximize + - handle crossing events resizing for more opaque resize goodness + (Soeren) + - add wacky _METACITY_UPDATE_COUNTER experimental extension + to do nice opaque resizing (does nothing without a GTK patch) + - fix a crash setting workspace names + - fix internationalized WM_NAME reading + diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..5a914b1 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,1871 @@ +# generated automatically by aclocal 1.15 -*- Autoconf -*- + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. + +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, +[m4_warning([this file was generated for autoconf 2.69. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically 'autoreconf'.])]) + +dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +dnl serial 11 (pkg-config-0.29.1) +dnl +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29.1]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])dnl PKG_PROG_PKG_CONFIG + +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])dnl _PKG_CONFIG + +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])dnl _PKG_SHORT_ERRORS_SUPPORTED + + +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR + +# Configure paths for GLIB +# Owen Taylor 1997-2001 + +dnl AM_PATH_GLIB_2_0([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]]) +dnl Test for GLIB, and define GLIB_CFLAGS and GLIB_LIBS, if gmodule, gobject, +dnl gthread, or gio is specified in MODULES, pass to pkg-config +dnl +AC_DEFUN([AM_PATH_GLIB_2_0], +[dnl +dnl Get the cflags and libraries from pkg-config +dnl +AC_ARG_ENABLE(glibtest, [ --disable-glibtest do not try to compile and run a test GLIB program], + , enable_glibtest=yes) + + pkg_config_args=glib-2.0 + for module in . $4 + do + case "$module" in + gmodule) + pkg_config_args="$pkg_config_args gmodule-2.0" + ;; + gmodule-no-export) + pkg_config_args="$pkg_config_args gmodule-no-export-2.0" + ;; + gobject) + pkg_config_args="$pkg_config_args gobject-2.0" + ;; + gthread) + pkg_config_args="$pkg_config_args gthread-2.0" + ;; + gio*) + pkg_config_args="$pkg_config_args $module-2.0" + ;; + esac + done + + PKG_PROG_PKG_CONFIG([0.16]) + + no_glib="" + + if test "x$PKG_CONFIG" = x ; then + no_glib=yes + PKG_CONFIG=no + fi + + min_glib_version=ifelse([$1], ,2.0.0,$1) + AC_MSG_CHECKING(for GLIB - version >= $min_glib_version) + + if test x$PKG_CONFIG != xno ; then + ## don't try to run the test against uninstalled libtool libs + if $PKG_CONFIG --uninstalled $pkg_config_args; then + echo "Will use uninstalled version of GLib found in PKG_CONFIG_PATH" + enable_glibtest=no + fi + + if $PKG_CONFIG --atleast-version $min_glib_version $pkg_config_args; then + : + else + no_glib=yes + fi + fi + + if test x"$no_glib" = x ; then + GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0` + GOBJECT_QUERY=`$PKG_CONFIG --variable=gobject_query glib-2.0` + GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0` + GLIB_COMPILE_RESOURCES=`$PKG_CONFIG --variable=glib_compile_resources gio-2.0` + + GLIB_CFLAGS=`$PKG_CONFIG --cflags $pkg_config_args` + GLIB_LIBS=`$PKG_CONFIG --libs $pkg_config_args` + glib_config_major_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + glib_config_minor_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + glib_config_micro_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + if test "x$enable_glibtest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GLIB_CFLAGS" + LIBS="$GLIB_LIBS $LIBS" +dnl +dnl Now check if the installed GLIB is sufficiently new. (Also sanity +dnl checks the results of pkg-config to some extent) +dnl + rm -f conf.glibtest + AC_TRY_RUN([ +#include +#include +#include + +int +main () +{ + unsigned int major, minor, micro; + + fclose (fopen ("conf.glibtest", "w")); + + if (sscanf("$min_glib_version", "%u.%u.%u", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_glib_version"); + exit(1); + } + + if ((glib_major_version != $glib_config_major_version) || + (glib_minor_version != $glib_config_minor_version) || + (glib_micro_version != $glib_config_micro_version)) + { + printf("\n*** 'pkg-config --modversion glib-2.0' returned %d.%d.%d, but GLIB (%d.%d.%d)\n", + $glib_config_major_version, $glib_config_minor_version, $glib_config_micro_version, + glib_major_version, glib_minor_version, glib_micro_version); + printf ("*** was found! If pkg-config was correct, then it is best\n"); + printf ("*** to remove the old version of GLib. You may also be able to fix the error\n"); + printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); + printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); + printf("*** required on your system.\n"); + printf("*** If pkg-config was wrong, set the environment variable PKG_CONFIG_PATH\n"); + printf("*** to point to the correct configuration files\n"); + } + else if ((glib_major_version != GLIB_MAJOR_VERSION) || + (glib_minor_version != GLIB_MINOR_VERSION) || + (glib_micro_version != GLIB_MICRO_VERSION)) + { + printf("*** GLIB header files (version %d.%d.%d) do not match\n", + GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION); + printf("*** library (version %d.%d.%d)\n", + glib_major_version, glib_minor_version, glib_micro_version); + } + else + { + if ((glib_major_version > major) || + ((glib_major_version == major) && (glib_minor_version > minor)) || + ((glib_major_version == major) && (glib_minor_version == minor) && (glib_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** An old version of GLIB (%u.%u.%u) was found.\n", + glib_major_version, glib_minor_version, glib_micro_version); + printf("*** You need a version of GLIB newer than %u.%u.%u. The latest version of\n", + major, minor, micro); + printf("*** GLIB is always available from ftp://ftp.gtk.org.\n"); + printf("***\n"); + printf("*** If you have already installed a sufficiently new version, this error\n"); + printf("*** probably means that the wrong copy of the pkg-config shell script is\n"); + printf("*** being found. The easiest way to fix this is to remove the old version\n"); + printf("*** of GLIB, but you can also set the PKG_CONFIG environment to point to the\n"); + printf("*** correct copy of pkg-config. (In this case, you will have to\n"); + printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); + printf("*** so that the correct libraries are found at run-time))\n"); + } + } + return 1; +} +],, no_glib=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_glib" = x ; then + AC_MSG_RESULT(yes (version $glib_config_major_version.$glib_config_minor_version.$glib_config_micro_version)) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$PKG_CONFIG" = "no" ; then + echo "*** A new enough version of pkg-config was not found." + echo "*** See http://www.freedesktop.org/software/pkgconfig/" + else + if test -f conf.glibtest ; then + : + else + echo "*** Could not run GLIB test program, checking why..." + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GLIB_CFLAGS" + LIBS="$LIBS $GLIB_LIBS" + AC_TRY_LINK([ +#include +#include +], [ return ((glib_major_version) || (glib_minor_version) || (glib_micro_version)); ], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding GLIB or finding the wrong" + echo "*** version of GLIB. If it is not finding GLIB, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means GLIB is incorrectly installed."]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + GLIB_CFLAGS="" + GLIB_LIBS="" + GLIB_GENMARSHAL="" + GOBJECT_QUERY="" + GLIB_MKENUMS="" + GLIB_COMPILE_RESOURCES="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(GLIB_CFLAGS) + AC_SUBST(GLIB_LIBS) + AC_SUBST(GLIB_GENMARSHAL) + AC_SUBST(GOBJECT_QUERY) + AC_SUBST(GLIB_MKENUMS) + AC_SUBST(GLIB_COMPILE_RESOURCES) + rm -f conf.glibtest +]) + +dnl GLIB_GSETTINGS +dnl Defines GSETTINGS_SCHEMAS_INSTALL which controls whether +dnl the schema should be compiled +dnl + +AC_DEFUN([GLIB_GSETTINGS], +[ + m4_pattern_allow([AM_V_GEN]) + AC_ARG_ENABLE(schemas-compile, + AS_HELP_STRING([--disable-schemas-compile], + [Disable regeneration of gschemas.compiled on install]), + [case ${enableval} in + yes) GSETTINGS_DISABLE_SCHEMAS_COMPILE="" ;; + no) GSETTINGS_DISABLE_SCHEMAS_COMPILE="1" ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-schemas-compile]) ;; + esac]) + AC_SUBST([GSETTINGS_DISABLE_SCHEMAS_COMPILE]) + PKG_PROG_PKG_CONFIG([0.16]) + AC_SUBST(gsettingsschemadir, [${datadir}/glib-2.0/schemas]) + if test x$cross_compiling != xyes; then + GLIB_COMPILE_SCHEMAS=`$PKG_CONFIG --variable glib_compile_schemas gio-2.0` + else + AC_PATH_PROG(GLIB_COMPILE_SCHEMAS, glib-compile-schemas) + fi + AC_SUBST(GLIB_COMPILE_SCHEMAS) + if test "x$GLIB_COMPILE_SCHEMAS" = "x"; then + ifelse([$2],,[AC_MSG_ERROR([glib-compile-schemas not found.])],[$2]) + else + ifelse([$1],,[:],[$1]) + fi + + GSETTINGS_RULES=' +.PHONY : uninstall-gsettings-schemas install-gsettings-schemas clean-gsettings-schemas + +mostlyclean-am: clean-gsettings-schemas + +gsettings__enum_file = $(addsuffix .enums.xml,$(gsettings_ENUM_NAMESPACE)) + +%.gschema.valid: %.gschema.xml $(gsettings__enum_file) + $(AM_V_GEN) $(GLIB_COMPILE_SCHEMAS) --strict --dry-run $(addprefix --schema-file=,$(gsettings__enum_file)) --schema-file=$< && mkdir -p [$](@D) && touch [$]@ + +all-am: $(gsettings_SCHEMAS:.xml=.valid) +uninstall-am: uninstall-gsettings-schemas +install-data-am: install-gsettings-schemas + +.SECONDARY: $(gsettings_SCHEMAS) + +install-gsettings-schemas: $(gsettings_SCHEMAS) $(gsettings__enum_file) + @$(NORMAL_INSTALL) + if test -n "$^"; then \ + test -z "$(gsettingsschemadir)" || $(MKDIR_P) "$(DESTDIR)$(gsettingsschemadir)"; \ + $(INSTALL_DATA) $^ "$(DESTDIR)$(gsettingsschemadir)"; \ + test -n "$(GSETTINGS_DISABLE_SCHEMAS_COMPILE)$(DESTDIR)" || $(GLIB_COMPILE_SCHEMAS) $(gsettingsschemadir); \ + fi + +uninstall-gsettings-schemas: + @$(NORMAL_UNINSTALL) + @list='\''$(gsettings_SCHEMAS) $(gsettings__enum_file)'\''; test -n "$(gsettingsschemadir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e '\''s|^.*/||'\''`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '\''$(DESTDIR)$(gsettingsschemadir)'\'' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(gsettingsschemadir)" && rm -f $$files + test -n "$(GSETTINGS_DISABLE_SCHEMAS_COMPILE)$(DESTDIR)" || $(GLIB_COMPILE_SCHEMAS) $(gsettingsschemadir) + +clean-gsettings-schemas: + rm -f $(gsettings_SCHEMAS:.xml=.valid) $(gsettings__enum_file) + +ifdef gsettings_ENUM_NAMESPACE +$(gsettings__enum_file): $(gsettings_ENUM_FILES) + $(AM_V_GEN) glib-mkenums --comments '\'''\'' --fhead "" --vhead " <@type@ id='\''$(gsettings_ENUM_NAMESPACE).@EnumName@'\''>" --vprod " " --vtail " " --ftail "" [$]^ > [$]@.tmp && mv [$]@.tmp [$]@ +endif +' + _GSETTINGS_SUBST(GSETTINGS_RULES) +]) + +dnl _GSETTINGS_SUBST(VARIABLE) +dnl Abstract macro to do either _AM_SUBST_NOTMAKE or AC_SUBST +AC_DEFUN([_GSETTINGS_SUBST], +[ +AC_SUBST([$1]) +m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([$1])]) +] +) + +dnl -*- mode: autoconf -*- +dnl Copyright 2009 Johan Dahlin +dnl +dnl This file is free software; the author(s) gives unlimited +dnl permission to copy and/or distribute it, with or without +dnl modifications, as long as this notice is preserved. +dnl + +# serial 1 + +m4_define([_GOBJECT_INTROSPECTION_CHECK_INTERNAL], +[ + AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first + AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first + AC_BEFORE([LT_INIT],[$0])dnl setup libtool first + + dnl enable/disable introspection + m4_if([$2], [require], + [dnl + enable_introspection=yes + ],[dnl + AC_ARG_ENABLE(introspection, + AS_HELP_STRING([--enable-introspection[=@<:@no/auto/yes@:>@]], + [Enable introspection for this build]),, + [enable_introspection=auto]) + ])dnl + + AC_MSG_CHECKING([for gobject-introspection]) + + dnl presence/version checking + AS_CASE([$enable_introspection], + [no], [dnl + found_introspection="no (disabled, use --enable-introspection to enable)" + ],dnl + [yes],[dnl + PKG_CHECK_EXISTS([gobject-introspection-1.0],, + AC_MSG_ERROR([gobject-introspection-1.0 is not installed])) + PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], + found_introspection=yes, + AC_MSG_ERROR([You need to have gobject-introspection >= $1 installed to build AC_PACKAGE_NAME])) + ],dnl + [auto],[dnl + PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], found_introspection=yes, found_introspection=no) + dnl Canonicalize enable_introspection + enable_introspection=$found_introspection + ],dnl + [dnl + AC_MSG_ERROR([invalid argument passed to --enable-introspection, should be one of @<:@no/auto/yes@:>@]) + ])dnl + + AC_MSG_RESULT([$found_introspection]) + + INTROSPECTION_SCANNER= + INTROSPECTION_COMPILER= + INTROSPECTION_GENERATE= + INTROSPECTION_GIRDIR= + INTROSPECTION_TYPELIBDIR= + if test "x$found_introspection" = "xyes"; then + INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0` + INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0` + INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0` + INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0` + INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)" + INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0` + INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0` + INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection + fi + AC_SUBST(INTROSPECTION_SCANNER) + AC_SUBST(INTROSPECTION_COMPILER) + AC_SUBST(INTROSPECTION_GENERATE) + AC_SUBST(INTROSPECTION_GIRDIR) + AC_SUBST(INTROSPECTION_TYPELIBDIR) + AC_SUBST(INTROSPECTION_CFLAGS) + AC_SUBST(INTROSPECTION_LIBS) + AC_SUBST(INTROSPECTION_MAKEFILE) + + AM_CONDITIONAL(HAVE_INTROSPECTION, test "x$found_introspection" = "xyes") +]) + + +dnl Usage: +dnl GOBJECT_INTROSPECTION_CHECK([minimum-g-i-version]) + +AC_DEFUN([GOBJECT_INTROSPECTION_CHECK], +[ + _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1]) +]) + +dnl Usage: +dnl GOBJECT_INTROSPECTION_REQUIRE([minimum-g-i-version]) + + +AC_DEFUN([GOBJECT_INTROSPECTION_REQUIRE], +[ + _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1], [require]) +]) + +# Copyright (C) 2002-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.15' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.15], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.15])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to +# '$srcdir', '$srcdir/..', or '$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is '.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ([2.52])dnl + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], + [$1], [CXX], [depcc="$CXX" am_compiler_list=], + [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], + [$1], [UPC], [depcc="$UPC" am_compiler_list=], + [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES. +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE([dependency-tracking], [dnl +AS_HELP_STRING( + [--enable-dependency-tracking], + [do not reject slow dependency extractors]) +AS_HELP_STRING( + [--disable-dependency-tracking], + [speeds up one-time build])]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "$am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each '.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. +m4_define([AC_PROG_CC], +m4_defn([AC_PROG_CC]) +[_AM_PROG_CC_C_O +]) + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.65])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[AC_DIAGNOSE([obsolete], + [$0: two- and three-arguments forms are deprecated.]) +m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if( + m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), + [ok:ok],, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) + AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) +AM_MISSING_PROG([AUTOCONF], [autoconf]) +AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) +AM_MISSING_PROG([AUTOHEADER], [autoheader]) +AM_MISSING_PROG([MAKEINFO], [makeinfo]) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +AC_SUBST([mkdir_p], ['$(MKDIR_P)']) +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES([CC])], + [m4_define([AC_PROG_CC], + m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES([CXX])], + [m4_define([AC_PROG_CXX], + m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES([OBJC])], + [m4_define([AC_PROG_OBJC], + m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], + [_AM_DEPENDENCIES([OBJCXX])], + [m4_define([AC_PROG_OBJCXX], + m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl +]) +AC_REQUIRE([AM_SILENT_RULES])dnl +dnl The testsuite driver may need to know about EXEEXT, so add the +dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This +dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) + fi +fi +dnl The trailing newline in this macro's definition is deliberate, for +dnl backward compatibility and to allow trailing 'dnl'-style comments +dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. +]) + +dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST([install_sh])]) + +# Copyright (C) 2003-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Add --enable-maintainer-mode option to configure. -*- Autoconf -*- +# From Jim Meyering + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MAINTAINER_MODE([DEFAULT-MODE]) +# ---------------------------------- +# Control maintainer-specific portions of Makefiles. +# Default is to disable them, unless 'enable' is passed literally. +# For symmetry, 'disable' may be passed as well. Anyway, the user +# can override the default with the --enable/--disable switch. +AC_DEFUN([AM_MAINTAINER_MODE], +[m4_case(m4_default([$1], [disable]), + [enable], [m4_define([am_maintainer_other], [disable])], + [disable], [m4_define([am_maintainer_other], [enable])], + [m4_define([am_maintainer_other], [enable]) + m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) +AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) + dnl maintainer-mode's default is 'disable' unless 'enable' is passed + AC_ARG_ENABLE([maintainer-mode], + [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode], + am_maintainer_other[ make rules and dependencies not useful + (and sometimes confusing) to the casual installer])], + [USE_MAINTAINER_MODE=$enableval], + [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) + AC_MSG_RESULT([$USE_MAINTAINER_MODE]) + AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST([MAINT])dnl +] +) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it is modern enough. +# If it is, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + AC_MSG_WARN(['missing' script is too old or missing]) +fi +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_CC_C_O +# --------------- +# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC +# to automatically call this. +AC_DEFUN([_AM_PROG_CC_C_O], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +AC_LANG_PUSH([C])dnl +AC_CACHE_CHECK( + [whether $CC understands -c and -o together], + [am_cv_prog_cc_c_o], + [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i]) +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +AC_LANG_POP([C])]) + +# For backward compatibility. +AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_RUN_LOG(COMMAND) +# ------------------- +# Run COMMAND, save the exit status in ac_status, and log it. +# (This has been adapted from Autoconf's _AC_RUN_LOG macro.) +AC_DEFUN([AM_RUN_LOG], +[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD + ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + (exit $ac_status); }]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken + alias in your environment]) + fi + if test "$[2]" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT([yes]) +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi +AC_CONFIG_COMMANDS_PRE( + [AC_MSG_CHECKING([that generated files are newer than configure]) + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + AC_MSG_RESULT([done])]) +rm -f conftest.file +]) + +# Copyright (C) 2009-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SILENT_RULES([DEFAULT]) +# -------------------------- +# Enable less verbose build rules; with the default set to DEFAULT +# ("yes" being less verbose, "no" or empty being verbose). +AC_DEFUN([AM_SILENT_RULES], +[AC_ARG_ENABLE([silent-rules], [dnl +AS_HELP_STRING( + [--enable-silent-rules], + [less verbose build output (undo: "make V=1")]) +AS_HELP_STRING( + [--disable-silent-rules], + [verbose build output (undo: "make V=0")])dnl +]) +case $enable_silent_rules in @%:@ ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; +esac +dnl +dnl A few 'make' implementations (e.g., NonStop OS and NextStep) +dnl do not support nested variable expansions. +dnl See automake bug#9928 and bug#10237. +am_make=${MAKE-make} +AC_CACHE_CHECK([whether $am_make supports nested variables], + [am_cv_make_support_nested_variables], + [if AS_ECHO([['TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi]) +if test $am_cv_make_support_nested_variables = yes; then + dnl Using '$V' instead of '$(V)' breaks IRIX make. + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AC_SUBST([AM_V])dnl +AM_SUBST_NOTMAKE([AM_V])dnl +AC_SUBST([AM_DEFAULT_V])dnl +AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl +AC_SUBST([AM_DEFAULT_VERBOSITY])dnl +AM_BACKSLASH='\' +AC_SUBST([AM_BACKSLASH])dnl +_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl +]) + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor 'install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in "make install-strip", and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of 'v7', 'ustar', or 'pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +# +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' + +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + + [m4_case([$1], + [ustar], + [# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) + if test $am_uid -le $am_max_uid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi + AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) + if test $am_gid -le $am_max_gid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi], + + [pax], + [], + + [m4_fatal([Unknown tar format])]) + + AC_MSG_CHECKING([how to create a $1 tar archive]) + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_$1-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi + done + rm -rf conftest.dir + + AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) + AC_MSG_RESULT([$am_cv_prog_tar_$1])]) + +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +m4_include([m4/gettext.m4]) +m4_include([m4/iconv.m4]) +m4_include([m4/intlmacosx.m4]) +m4_include([m4/lib-ld.m4]) +m4_include([m4/lib-link.m4]) +m4_include([m4/lib-prefix.m4]) +m4_include([m4/libtool.m4]) +m4_include([m4/ltoptions.m4]) +m4_include([m4/ltsugar.m4]) +m4_include([m4/ltversion.m4]) +m4_include([m4/lt~obsolete.m4]) +m4_include([m4/nls.m4]) +m4_include([m4/po.m4]) +m4_include([m4/progtest.m4]) diff --git a/build-aux/compile b/build-aux/compile new file mode 100755 index 0000000..a85b723 --- /dev/null +++ b/build-aux/compile @@ -0,0 +1,347 @@ +#! /bin/sh +# Wrapper for compilers which do not understand '-c -o'. + +scriptversion=2012-10-14.11; # UTC + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Written by Tom Tromey . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +nl=' +' + +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent tools from complaining about whitespace usage. +IFS=" "" $nl" + +file_conv= + +# func_file_conv build_file lazy +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. If the determined conversion +# type is listed in (the comma separated) LAZY, no conversion will +# take place. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv/,$2, in + *,$file_conv,*) + ;; + mingw/*) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin/*) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine/*) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + if test -f "$dir/lib$lib.a"; then + found=yes + lib=$dir/lib$lib.a + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + +# func_cl_wrapper cl arg... +# Adjust compile command to suit cl +func_cl_wrapper () +{ + # Assume a capable shell + lib_path= + shared=: + linker_opts= + for arg + do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + eat=1 + case $2 in + *.o | *.[oO][bB][jJ]) + func_file_conv "$2" + set x "$@" -Fo"$file" + shift + ;; + *) + func_file_conv "$2" + set x "$@" -Fe"$file" + shift + ;; + esac + ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; + -I*) + func_file_conv "${1#-I}" mingw + set x "$@" -I"$file" + shift + ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; + -l*) + func_cl_dashl "${1#-l}" + set x "$@" "$lib" + shift + ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; + -L*) + func_cl_dashL "${1#-L}" + ;; + -static) + shared=false + ;; + -Wl,*) + arg=${1#-Wl,} + save_ifs="$IFS"; IFS=',' + for flag in $arg; do + IFS="$save_ifs" + linker_opts="$linker_opts $flag" + done + IFS="$save_ifs" + ;; + -Xlinker) + eat=1 + linker_opts="$linker_opts $2" + ;; + -*) + set x "$@" "$1" + shift + ;; + *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) + func_file_conv "$1" + set x "$@" -Tp"$file" + shift + ;; + *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) + func_file_conv "$1" mingw + set x "$@" "$file" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift + done + if test -n "$linker_opts"; then + linker_opts="-link$linker_opts" + fi + exec "$@" $linker_opts + exit 1 +} + +eat= + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand '-c -o'. +Remove '-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file 'INSTALL'. + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) + func_cl_wrapper "$@" # Doesn't return... + ;; +esac + +ofile= +cfile= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + # So we strip '-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no '-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # '.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use '[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/build-aux/config.guess b/build-aux/config.guess new file mode 100755 index 0000000..dbfb978 --- /dev/null +++ b/build-aux/config.guess @@ -0,0 +1,1421 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2015 Free Software Foundation, Inc. + +timestamp='2015-01-01' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program 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 +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +# +# Please send patches to . + + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright 1992-2015 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +case "${UNAME_SYSTEM}" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval $set_cc_for_build + cat <<-EOF > $dummy.c + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + ;; +esac + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW64*:*) + echo ${UNAME_MACHINE}-pc-mingw64 + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + *:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="gnulibc1" ; fi + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + else + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-${LIBC} + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-${LIBC} + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; + PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; + *) echo hppa-unknown-linux-${LIBC} ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-${LIBC} + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-${LIBC} + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-${LIBC} + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-${LIBC} + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-${LIBC} + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + eval $set_cc_for_build + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + fi + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; +esac + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/build-aux/config.rpath b/build-aux/config.rpath new file mode 100755 index 0000000..a3e25c8 --- /dev/null +++ b/build-aux/config.rpath @@ -0,0 +1,684 @@ +#! /bin/sh +# Output a system dependent set of variables, describing how to set the +# run time search path of shared libraries in an executable. +# +# Copyright 1996-2015 Free Software Foundation, Inc. +# Taken from GNU libtool, 2001 +# Originally by Gordon Matzigkeit , 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# The first argument passed to this file is the canonical host specification, +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld +# should be set by the caller. +# +# The set of defined variables is at the end of this script. + +# Known limitations: +# - On IRIX 6.5 with CC="cc", the run time search patch must not be longer +# than 256 bytes, otherwise the compiler driver will dump core. The only +# known workaround is to choose shorter directory names for the build +# directory and/or the installation directory. + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a +shrext=.so + +host="$1" +host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + +# Code taken from libtool.m4's _LT_CC_BASENAME. + +for cc_temp in $CC""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'` + +# Code taken from libtool.m4's _LT_COMPILER_PIC. + +wl= +if test "$GCC" = yes; then + wl='-Wl,' +else + case "$host_os" in + aix*) + wl='-Wl,' + ;; + mingw* | cygwin* | pw32* | os2* | cegcc*) + ;; + hpux9* | hpux10* | hpux11*) + wl='-Wl,' + ;; + irix5* | irix6* | nonstopux*) + wl='-Wl,' + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + ecc*) + wl='-Wl,' + ;; + icc* | ifort*) + wl='-Wl,' + ;; + lf95*) + wl='-Wl,' + ;; + nagfor*) + wl='-Wl,-Wl,,' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + wl='-Wl,' + ;; + ccc*) + wl='-Wl,' + ;; + xl* | bgxl* | bgf* | mpixl*) + wl='-Wl,' + ;; + como) + wl='-lopt=' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ F* | *Sun*Fortran*) + wl= + ;; + *Sun\ C*) + wl='-Wl,' + ;; + esac + ;; + esac + ;; + newsos6) + ;; + *nto* | *qnx*) + ;; + osf3* | osf4* | osf5*) + wl='-Wl,' + ;; + rdos*) + ;; + solaris*) + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + wl='-Qoption ld ' + ;; + *) + wl='-Wl,' + ;; + esac + ;; + sunos4*) + wl='-Qoption ld ' + ;; + sysv4 | sysv4.2uw2* | sysv4.3*) + wl='-Wl,' + ;; + sysv4*MP*) + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + wl='-Wl,' + ;; + unicos*) + wl='-Wl,' + ;; + uts4*) + ;; + esac +fi + +# Code taken from libtool.m4's _LT_LINKER_SHLIBS. + +hardcode_libdir_flag_spec= +hardcode_libdir_separator= +hardcode_direct=no +hardcode_minus_L=no + +case "$host_os" in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; +esac + +ld_shlibs=yes +if test "$with_gnu_ld" = yes; then + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + # Unlike libtool, we use -rpath here, not --rpath, since the documented + # option of GNU ld is called -rpath, not --rpath. + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + case "$host_os" in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + fi + ;; + amigaos*) + case "$host_cpu" in + powerpc) + ;; + m68k) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + cygwin* | mingw* | pw32* | cegcc*) + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + haiku*) + ;; + interix[3-9]*) + hardcode_direct=no + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + netbsd*) + ;; + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + else + ld_shlibs=no + fi + ;; + esac + ;; + sunos4*) + hardcode_direct=yes + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + esac + if test "$ld_shlibs" = no; then + hardcode_libdir_flag_spec= + fi +else + case "$host_os" in + aix3*) + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + aix[4-9]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + else + aix_use_runtimelinking=no + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + fi + hardcode_direct=yes + hardcode_libdir_separator=':' + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + fi + # Begin _LT_AC_SYS_LIBPATH_AIX. + echo 'int main () { return 0; }' > conftest.c + ${CC} ${LDFLAGS} conftest.c -o conftest + aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` + if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` + fi + if test -z "$aix_libpath"; then + aix_libpath="/usr/lib:/lib" + fi + rm -f conftest.c conftest + # End _LT_AC_SYS_LIBPATH_AIX. + if test "$aix_use_runtimelinking" = yes; then + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + else + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + fi + fi + ;; + amigaos*) + case "$host_cpu" in + powerpc) + ;; + m68k) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + bsdi[45]*) + ;; + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec=' ' + libext=lib + ;; + darwin* | rhapsody*) + hardcode_direct=no + if { case $cc_basename in ifort*) true;; *) test "$GCC" = yes;; esac; }; then + : + else + ld_shlibs=no + fi + ;; + dgux*) + hardcode_libdir_flag_spec='-L$libdir' + ;; + freebsd2.[01]*) + hardcode_direct=yes + hardcode_minus_L=yes + ;; + freebsd* | dragonfly*) + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + ;; + hpux9*) + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + hpux10*) + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + hpux11*) + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + ;; + *) + hardcode_direct=yes + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + irix5* | irix6* | nonstopux*) + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + netbsd*) + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + ;; + newsos6) + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + *nto* | *qnx*) + ;; + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + else + case "$host_os" in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + else + ld_shlibs=no + fi + ;; + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + osf3*) + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + osf4* | osf5*) + if test "$GCC" = yes; then + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + # Both cc and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + hardcode_libdir_separator=: + ;; + solaris*) + hardcode_libdir_flag_spec='-R$libdir' + ;; + sunos4*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + ;; + sysv4) + case $host_vendor in + sni) + hardcode_direct=yes # is this really true??? + ;; + siemens) + hardcode_direct=no + ;; + motorola) + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + ;; + sysv4.3*) + ;; + sysv4*MP*) + if test -d /usr/nec; then + ld_shlibs=yes + fi + ;; + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + ;; + sysv5* | sco3.2v5* | sco5v6*) + hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator=':' + ;; + uts4*) + hardcode_libdir_flag_spec='-L$libdir' + ;; + *) + ld_shlibs=no + ;; + esac +fi + +# Check dynamic linker characteristics +# Code taken from libtool.m4's _LT_SYS_DYNAMIC_LINKER. +# Unlike libtool.m4, here we don't care about _all_ names of the library, but +# only about the one the linker finds when passed -lNAME. This is the last +# element of library_names_spec in libtool.m4, or possibly two of them if the +# linker has special search rules. +library_names_spec= # the last element of library_names_spec in libtool.m4 +libname_spec='lib$name' +case "$host_os" in + aix3*) + library_names_spec='$libname.a' + ;; + aix[4-9]*) + library_names_spec='$libname$shrext' + ;; + amigaos*) + case "$host_cpu" in + powerpc*) + library_names_spec='$libname$shrext' ;; + m68k) + library_names_spec='$libname.a' ;; + esac + ;; + beos*) + library_names_spec='$libname$shrext' + ;; + bsdi[45]*) + library_names_spec='$libname$shrext' + ;; + cygwin* | mingw* | pw32* | cegcc*) + shrext=.dll + library_names_spec='$libname.dll.a $libname.lib' + ;; + darwin* | rhapsody*) + shrext=.dylib + library_names_spec='$libname$shrext' + ;; + dgux*) + library_names_spec='$libname$shrext' + ;; + freebsd[23].*) + library_names_spec='$libname$shrext$versuffix' + ;; + freebsd* | dragonfly*) + library_names_spec='$libname$shrext' + ;; + gnu*) + library_names_spec='$libname$shrext' + ;; + haiku*) + library_names_spec='$libname$shrext' + ;; + hpux9* | hpux10* | hpux11*) + case $host_cpu in + ia64*) + shrext=.so + ;; + hppa*64*) + shrext=.sl + ;; + *) + shrext=.sl + ;; + esac + library_names_spec='$libname$shrext' + ;; + interix[3-9]*) + library_names_spec='$libname$shrext' + ;; + irix5* | irix6* | nonstopux*) + library_names_spec='$libname$shrext' + case "$host_os" in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;; + *) libsuff= shlibsuff= ;; + esac + ;; + esac + ;; + linux*oldld* | linux*aout* | linux*coff*) + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu) + library_names_spec='$libname$shrext' + ;; + knetbsd*-gnu) + library_names_spec='$libname$shrext' + ;; + netbsd*) + library_names_spec='$libname$shrext' + ;; + newsos6) + library_names_spec='$libname$shrext' + ;; + *nto* | *qnx*) + library_names_spec='$libname$shrext' + ;; + openbsd*) + library_names_spec='$libname$shrext$versuffix' + ;; + os2*) + libname_spec='$name' + shrext=.dll + library_names_spec='$libname.a' + ;; + osf3* | osf4* | osf5*) + library_names_spec='$libname$shrext' + ;; + rdos*) + ;; + solaris*) + library_names_spec='$libname$shrext' + ;; + sunos4*) + library_names_spec='$libname$shrext$versuffix' + ;; + sysv4 | sysv4.3*) + library_names_spec='$libname$shrext' + ;; + sysv4*MP*) + library_names_spec='$libname$shrext' + ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + library_names_spec='$libname$shrext' + ;; + tpf*) + library_names_spec='$libname$shrext' + ;; + uts4*) + library_names_spec='$libname$shrext' + ;; +esac + +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' +escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"` +shlibext=`echo "$shrext" | sed -e 's,^\.,,'` +escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` +escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` +escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` + +LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + + +# Please send patches to . +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright 1992-2015 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze*) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | be32 | be64 \ + | bfin \ + | c4x | c8051 | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | epiphany \ + | fido | fr30 | frv | ft32 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ + | ns16k | ns32k \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | riscv32 | riscv64 \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | k1om-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | or1k*-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | visium-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + mingw32) + basic_machine=i686-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i686-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-* | ppc64p7-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* | -plan9* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/build-aux/depcomp b/build-aux/depcomp new file mode 100755 index 0000000..fc98710 --- /dev/null +++ b/build-aux/depcomp @@ -0,0 +1,791 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2013-05-30.07; # UTC + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program 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 General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by 'PROGRAMS ARGS'. + object Object file output by 'PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputting dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +# Get the directory component of the given path, and save it in the +# global variables '$dir'. Note that this directory component will +# be either empty or ending with a '/' character. This is deliberate. +set_dir_from () +{ + case $1 in + */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; + *) dir=;; + esac +} + +# Get the suffix-stripped basename of the given path, and save it the +# global variable '$base'. +set_base_from () +{ + base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` +} + +# If no dependency file was actually created by the compiler invocation, +# we still have to create a dummy depfile, to avoid errors with the +# Makefile "include basename.Plo" scheme. +make_dummy_depfile () +{ + echo "#dummy" > "$depfile" +} + +# Factor out some common post-processing of the generated depfile. +# Requires the auxiliary global variable '$tmpdepfile' to be set. +aix_post_process_depfile () +{ + # If the compiler actually managed to produce a dependency file, + # post-process it. + if test -f "$tmpdepfile"; then + # Each line is of the form 'foo.o: dependency.h'. + # Do two passes, one to just change these to + # $object: dependency.h + # and one to simply output + # dependency.h: + # which is needed to avoid the deleted-header problem. + { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" + sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" + } > "$depfile" + rm -f "$tmpdepfile" + else + make_dummy_depfile + fi +} + +# A tabulation character. +tab=' ' +# A newline character. +nl=' +' +# Character ranges might be problematic outside the C locale. +# These definitions help. +upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ +lower=abcdefghijklmnopqrstuvwxyz +digits=0123456789 +alpha=${upper}${lower} + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Avoid interferences from the environment. +gccflag= dashmflag= + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvisualcpp +fi + +if test "$depmode" = msvc7msys; then + # This is just like msvc7 but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvc7 +fi + +if test "$depmode" = xlc; then + # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. + gccflag=-qmakedep=gcc,-MF + depmode=gcc +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. +## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. +## (see the conditional assignment to $gccflag above). +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). Also, it might not be +## supported by the other compilers which use the 'gcc' depmode. +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The second -e expression handles DOS-style file names with drive + # letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the "deleted header file" problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. +## Some versions of gcc put a space before the ':'. On the theory +## that the space means something, we add a space to the output as +## well. hp depmode also adds that space, but also prefixes the VPATH +## to the object. Take care to not repeat it in the output. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like '#:fec' to the end of the + # dependency line. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ + | tr "$nl" ' ' >> "$depfile" + echo >> "$depfile" + # The second pass generates a dummy entry for each header file. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" + ;; + +xlc) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts '$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + aix_post_process_depfile + ;; + +tcc) + # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 + # FIXME: That version still under development at the moment of writing. + # Make that this statement remains true also for stable, released + # versions. + # It will wrap lines (doesn't matter whether long or short) with a + # trailing '\', as in: + # + # foo.o : \ + # foo.c \ + # foo.h \ + # + # It will put a trailing '\' even on the last line, and will use leading + # spaces rather than leading tabs (at least since its commit 0394caf7 + # "Emit spaces for -MD"). + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. + # We have to change lines of the first kind to '$object: \'. + sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" + # And for each line of the second kind, we have to emit a 'dep.h:' + # dummy dependency, to avoid the deleted-header problem. + sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" + rm -f "$tmpdepfile" + ;; + +## The order of this option in the case statement is important, since the +## shell code in configure will try each of these formats in the order +## listed in this file. A plain '-MD' option would be understood by many +## compilers, so we must ensure this comes after the gcc and icc options. +pgcc) + # Portland's C compiler understands '-MD'. + # Will always output deps to 'file.d' where file is the root name of the + # source file under compilation, even if file resides in a subdirectory. + # The object file name does not affect the name of the '.d' file. + # pgcc 10.2 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using '\' : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + set_dir_from "$object" + # Use the source, not the object, to determine the base name, since + # that's sadly what pgcc will do too. + set_base_from "$source" + tmpdepfile=$base.d + + # For projects that build the same source file twice into different object + # files, the pgcc approach of using the *source* file root name can cause + # problems in parallel builds. Use a locking strategy to avoid stomping on + # the same $tmpdepfile. + lockdir=$base.d-lock + trap " + echo '$0: caught signal, cleaning up...' >&2 + rmdir '$lockdir' + exit 1 + " 1 2 13 15 + numtries=100 + i=$numtries + while test $i -gt 0; do + # mkdir is a portable test-and-set. + if mkdir "$lockdir" 2>/dev/null; then + # This process acquired the lock. + "$@" -MD + stat=$? + # Release the lock. + rmdir "$lockdir" + break + else + # If the lock is being held by a different process, wait + # until the winning process is done or we timeout. + while test -d "$lockdir" && test $i -gt 0; do + sleep 1 + i=`expr $i - 1` + done + fi + i=`expr $i - 1` + done + trap - 1 2 13 15 + if test $i -le 0; then + echo "$0: failed to acquire lock after $numtries attempts" >&2 + echo "$0: check lockdir '$lockdir'" >&2 + exit 1 + fi + + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" + # Add 'dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in 'foo.d' instead, so we check for that too. + # Subdirectories are respected. + set_dir_from "$object" + set_base_from "$object" + + if test "$libtool" = yes; then + # Libtool generates 2 separate objects for the 2 libraries. These + # two compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir$base.o.d # libtool 1.5 + tmpdepfile2=$dir.libs/$base.o.d # Likewise. + tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + # Same post-processing that is required for AIX mode. + aix_post_process_depfile + ;; + +msvc7) + if test "$libtool" = yes; then + showIncludes=-Wc,-showIncludes + else + showIncludes=-showIncludes + fi + "$@" $showIncludes > "$tmpdepfile" + stat=$? + grep -v '^Note: including file: ' "$tmpdepfile" + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The first sed program below extracts the file names and escapes + # backslashes for cygpath. The second sed program outputs the file + # name when reading, but also accumulates all include files in the + # hold buffer in order to output them again at the end. This only + # works with sed implementations that can handle large buffers. + sed < "$tmpdepfile" -n ' +/^Note: including file: *\(.*\)/ { + s//\1/ + s/\\/\\\\/g + p +}' | $cygpath_u | sort -u | sed -n ' +s/ /\\ /g +s/\(.*\)/'"$tab"'\1 \\/p +s/.\(.*\) \\/\1:/ +H +$ { + s/.*/'"$tab"'/ + G + p +}' >> "$depfile" + echo >> "$depfile" # make sure the fragment doesn't end with a backslash + rm -f "$tmpdepfile" + ;; + +msvc7msys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for ':' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. + "$@" $dashmflag | + sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this sed invocation + # correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + # makedepend may prepend the VPATH from the source file name to the object. + # No need to regex-escape $object, excess matching of '.' is harmless. + sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process the last invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed '1,2d' "$tmpdepfile" \ + | tr ' ' "$nl" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E \ + | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + | sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" + echo "$tab" >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/build-aux/install-sh b/build-aux/install-sh new file mode 100755 index 0000000..0b0fdcb --- /dev/null +++ b/build-aux/install-sh @@ -0,0 +1,501 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2013-12-25.23; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# 'make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +tab=' ' +nl=' +' +IFS=" $tab$nl" + +# Set DOITPROG to "echo" to test this script. + +doit=${DOITPROG-} +doit_exec=${doit:-exec} + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +is_target_a_directory=possibly + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) is_target_a_directory=never;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi +fi + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + dstdir=`dirname "$dst"` + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + oIFS=$IFS + IFS=/ + set -f + set fnord $dstdir + shift + set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + set +f && + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/build-aux/ltmain.sh b/build-aux/ltmain.sh new file mode 100644 index 0000000..0f0a2da --- /dev/null +++ b/build-aux/ltmain.sh @@ -0,0 +1,11147 @@ +#! /bin/sh +## DO NOT EDIT - This file generated from ./build-aux/ltmain.in +## by inline-source v2014-01-03.01 + +# libtool (GNU libtool) 2.4.6 +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool 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 +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +PROGRAM=libtool +PACKAGE=libtool +VERSION=2.4.6 +package_revision=2.4.6 + + +## ------ ## +## Usage. ## +## ------ ## + +# Run './libtool --help' for help with using this script from the +# command line. + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# After configure completes, it has a better idea of some of the +# shell tools we need than the defaults used by the functions shared +# with bootstrap, so set those here where they can still be over- +# ridden by the user, but otherwise take precedence. + +: ${AUTOCONF="autoconf"} +: ${AUTOMAKE="automake"} + + +## -------------------------- ## +## Source external libraries. ## +## -------------------------- ## + +# Much of our low-level functionality needs to be sourced from external +# libraries, which are installed to $pkgauxdir. + +# Set a version string for this script. +scriptversion=2015-01-20.17; # UTC + +# General shell script boiler plate, and helper functions. +# Written by Gary V. Vaughan, 2004 + +# Copyright (C) 2004-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# As a special exception to the GNU General Public License, if you distribute +# this file as part of a program or library that is built using GNU Libtool, +# you may include this file under the same distribution terms that you use +# for the rest of that program. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNES FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# Evaluate this file near the top of your script to gain access to +# the functions and variables defined here: +# +# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh +# +# If you need to override any of the default environment variable +# settings, do that before evaluating this file. + + +## -------------------- ## +## Shell normalisation. ## +## -------------------- ## + +# Some shells need a little help to be as Bourne compatible as possible. +# Before doing anything else, make sure all that help has been provided! + +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac +fi + +# NLS nuisances: We save the old values in case they are required later. +_G_user_locale= +_G_safe_locale= +for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test set = \"\${$_G_var+set}\"; then + save_$_G_var=\$$_G_var + $_G_var=C + export $_G_var + _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" + _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" + fi" +done + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Make sure IFS has a sensible default +sp=' ' +nl=' +' +IFS="$sp $nl" + +# There are apparently some retarded systems that use ';' as a PATH separator! +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + + +## ------------------------- ## +## Locate command utilities. ## +## ------------------------- ## + + +# func_executable_p FILE +# ---------------------- +# Check that FILE is an executable regular file. +func_executable_p () +{ + test -f "$1" && test -x "$1" +} + + +# func_path_progs PROGS_LIST CHECK_FUNC [PATH] +# -------------------------------------------- +# Search for either a program that responds to --version with output +# containing "GNU", or else returned by CHECK_FUNC otherwise, by +# trying all the directories in PATH with each of the elements of +# PROGS_LIST. +# +# CHECK_FUNC should accept the path to a candidate program, and +# set $func_check_prog_result if it truncates its output less than +# $_G_path_prog_max characters. +func_path_progs () +{ + _G_progs_list=$1 + _G_check_func=$2 + _G_PATH=${3-"$PATH"} + + _G_path_prog_max=0 + _G_path_prog_found=false + _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} + for _G_dir in $_G_PATH; do + IFS=$_G_save_IFS + test -z "$_G_dir" && _G_dir=. + for _G_prog_name in $_G_progs_list; do + for _exeext in '' .EXE; do + _G_path_prog=$_G_dir/$_G_prog_name$_exeext + func_executable_p "$_G_path_prog" || continue + case `"$_G_path_prog" --version 2>&1` in + *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; + *) $_G_check_func $_G_path_prog + func_path_progs_result=$func_check_prog_result + ;; + esac + $_G_path_prog_found && break 3 + done + done + done + IFS=$_G_save_IFS + test -z "$func_path_progs_result" && { + echo "no acceptable sed could be found in \$PATH" >&2 + exit 1 + } +} + + +# We want to be able to use the functions in this file before configure +# has figured out where the best binaries are kept, which means we have +# to search for them ourselves - except when the results are already set +# where we skip the searches. + +# Unless the user overrides by setting SED, search the path for either GNU +# sed, or the sed that truncates its output the least. +test -z "$SED" && { + _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for _G_i in 1 2 3 4 5 6 7; do + _G_sed_script=$_G_sed_script$nl$_G_sed_script + done + echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed + _G_sed_script= + + func_check_prog_sed () + { + _G_path_prog=$1 + + _G_count=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo '' >> conftest.nl + "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin + rm -f conftest.sed + SED=$func_path_progs_result +} + + +# Unless the user overrides by setting GREP, search the path for either GNU +# grep, or the grep that truncates its output the least. +test -z "$GREP" && { + func_check_prog_grep () + { + _G_path_prog=$1 + + _G_count=0 + _G_path_prog_max=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo 'GREP' >> conftest.nl + "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin + GREP=$func_path_progs_result +} + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# All uppercase variable names are used for environment variables. These +# variables can be overridden by the user before calling a script that +# uses them if a suitable command of that name is not already available +# in the command search PATH. + +: ${CP="cp -f"} +: ${ECHO="printf %s\n"} +: ${EGREP="$GREP -E"} +: ${FGREP="$GREP -F"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} + + +## -------------------- ## +## Useful sed snippets. ## +## -------------------- ## + +sed_dirname='s|/[^/]*$||' +sed_basename='s|^.*/||' + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Same as above, but do not quote variable references. +sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' + +# Sed substitution that converts a w32 file name or path +# that contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-'\' parameter expansions in output of sed_double_quote_subst that +# were '\'-ed in input to the same. If an odd number of '\' preceded a +# '$' in input to sed_double_quote_subst, that '$' was protected from +# expansion. Since each input '\' is now two '\'s, look for any number +# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. +_G_bs='\\' +_G_bs2='\\\\' +_G_bs4='\\\\\\\\' +_G_dollar='\$' +sed_double_backslash="\ + s/$_G_bs4/&\\ +/g + s/^$_G_bs2$_G_dollar/$_G_bs&/ + s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g + s/\n//g" + + +## ----------------- ## +## Global variables. ## +## ----------------- ## + +# Except for the global variables explicitly listed below, the following +# functions in the '^func_' namespace, and the '^require_' namespace +# variables initialised in the 'Resource management' section, sourcing +# this file will not pollute your global namespace with anything +# else. There's no portable way to scope variables in Bourne shell +# though, so actually running these functions will sometimes place +# results into a variable named after the function, and often use +# temporary variables in the '^_G_' namespace. If you are careful to +# avoid using those namespaces casually in your sourcing script, things +# should continue to work as you expect. And, of course, you can freely +# overwrite any of the functions or variables defined here before +# calling anything to customize them. + +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +# Allow overriding, eg assuming that you follow the convention of +# putting '$debug_cmd' at the start of all your functions, you can get +# bash to show function call trace with: +# +# debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name +debug_cmd=${debug_cmd-":"} +exit_cmd=: + +# By convention, finish your script with: +# +# exit $exit_status +# +# so that you can set exit_status to non-zero if you want to indicate +# something went wrong during execution without actually bailing out at +# the point of failure. +exit_status=$EXIT_SUCCESS + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath=$0 + +# The name of this program. +progname=`$ECHO "$progpath" |$SED "$sed_basename"` + +# Make sure we have an absolute progpath for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` + progdir=`cd "$progdir" && pwd` + progpath=$progdir/$progname + ;; + *) + _G_IFS=$IFS + IFS=${PATH_SEPARATOR-:} + for progdir in $PATH; do + IFS=$_G_IFS + test -x "$progdir/$progname" && break + done + IFS=$_G_IFS + test -n "$progdir" || progdir=`pwd` + progpath=$progdir/$progname + ;; +esac + + +## ----------------- ## +## Standard options. ## +## ----------------- ## + +# The following options affect the operation of the functions defined +# below, and should be set appropriately depending on run-time para- +# meters passed on the command line. + +opt_dry_run=false +opt_quiet=false +opt_verbose=false + +# Categories 'all' and 'none' are always available. Append any others +# you will pass as the first argument to func_warning from your own +# code. +warning_categories= + +# By default, display warnings according to 'opt_warning_types'. Set +# 'warning_func' to ':' to elide all warnings, or func_fatal_error to +# treat the next displayed warning as a fatal error. +warning_func=func_warn_and_continue + +# Set to 'all' to display all warnings, 'none' to suppress all +# warnings, or a space delimited list of some subset of +# 'warning_categories' to display only the listed warnings. +opt_warning_types=all + + +## -------------------- ## +## Resource management. ## +## -------------------- ## + +# This section contains definitions for functions that each ensure a +# particular resource (a file, or a non-empty configuration variable for +# example) is available, and if appropriate to extract default values +# from pertinent package files. Call them using their associated +# 'require_*' variable to ensure that they are executed, at most, once. +# +# It's entirely deliberate that calling these functions can set +# variables that don't obey the namespace limitations obeyed by the rest +# of this file, in order that that they be as useful as possible to +# callers. + + +# require_term_colors +# ------------------- +# Allow display of bold text on terminals that support it. +require_term_colors=func_require_term_colors +func_require_term_colors () +{ + $debug_cmd + + test -t 1 && { + # COLORTERM and USE_ANSI_COLORS environment variables take + # precedence, because most terminfo databases neglect to describe + # whether color sequences are supported. + test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} + + if test 1 = "$USE_ANSI_COLORS"; then + # Standard ANSI escape sequences + tc_reset='' + tc_bold=''; tc_standout='' + tc_red=''; tc_green='' + tc_blue=''; tc_cyan='' + else + # Otherwise trust the terminfo database after all. + test -n "`tput sgr0 2>/dev/null`" && { + tc_reset=`tput sgr0` + test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` + tc_standout=$tc_bold + test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` + test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` + test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` + test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` + test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` + } + fi + } + + require_term_colors=: +} + + +## ----------------- ## +## Function library. ## +## ----------------- ## + +# This section contains a variety of useful functions to call in your +# scripts. Take note of the portable wrappers for features provided by +# some modern shells, which will fall back to slower equivalents on +# less featureful shells. + + +# func_append VAR VALUE +# --------------------- +# Append VALUE onto the existing contents of VAR. + + # We should try to minimise forks, especially on Windows where they are + # unreasonably slow, so skip the feature probes when bash or zsh are + # being used: + if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then + : ${_G_HAVE_ARITH_OP="yes"} + : ${_G_HAVE_XSI_OPS="yes"} + # The += operator was introduced in bash 3.1 + case $BASH_VERSION in + [12].* | 3.0 | 3.0*) ;; + *) + : ${_G_HAVE_PLUSEQ_OP="yes"} + ;; + esac + fi + + # _G_HAVE_PLUSEQ_OP + # Can be empty, in which case the shell is probed, "yes" if += is + # useable or anything else if it does not work. + test -z "$_G_HAVE_PLUSEQ_OP" \ + && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ + && _G_HAVE_PLUSEQ_OP=yes + +if test yes = "$_G_HAVE_PLUSEQ_OP" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_append () + { + $debug_cmd + + eval "$1+=\$2" + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_append () + { + $debug_cmd + + eval "$1=\$$1\$2" + } +fi + + +# func_append_quoted VAR VALUE +# ---------------------------- +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +if test yes = "$_G_HAVE_PLUSEQ_OP"; then + eval 'func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1+=\\ \$func_quote_for_eval_result" + }' +else + func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1=\$$1\\ \$func_quote_for_eval_result" + } +fi + + +# func_append_uniq VAR VALUE +# -------------------------- +# Append unique VALUE onto the existing contents of VAR, assuming +# entries are delimited by the first character of VALUE. For example: +# +# func_append_uniq options " --another-option option-argument" +# +# will only append to $options if " --another-option option-argument " +# is not already present somewhere in $options already (note spaces at +# each end implied by leading space in second argument). +func_append_uniq () +{ + $debug_cmd + + eval _G_current_value='`$ECHO $'$1'`' + _G_delim=`expr "$2" : '\(.\)'` + + case $_G_delim$_G_current_value$_G_delim in + *"$2$_G_delim"*) ;; + *) func_append "$@" ;; + esac +} + + +# func_arith TERM... +# ------------------ +# Set func_arith_result to the result of evaluating TERMs. + test -z "$_G_HAVE_ARITH_OP" \ + && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ + && _G_HAVE_ARITH_OP=yes + +if test yes = "$_G_HAVE_ARITH_OP"; then + eval 'func_arith () + { + $debug_cmd + + func_arith_result=$(( $* )) + }' +else + func_arith () + { + $debug_cmd + + func_arith_result=`expr "$@"` + } +fi + + +# func_basename FILE +# ------------------ +# Set func_basename_result to FILE with everything up to and including +# the last / stripped. +if test yes = "$_G_HAVE_XSI_OPS"; then + # If this shell supports suffix pattern removal, then use it to avoid + # forking. Hide the definitions single quotes in case the shell chokes + # on unsupported syntax... + _b='func_basename_result=${1##*/}' + _d='case $1 in + */*) func_dirname_result=${1%/*}$2 ;; + * ) func_dirname_result=$3 ;; + esac' + +else + # ...otherwise fall back to using sed. + _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' + _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` + if test "X$func_dirname_result" = "X$1"; then + func_dirname_result=$3 + else + func_append func_dirname_result "$2" + fi' +fi + +eval 'func_basename () +{ + $debug_cmd + + '"$_b"' +}' + + +# func_dirname FILE APPEND NONDIR_REPLACEMENT +# ------------------------------------------- +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +eval 'func_dirname () +{ + $debug_cmd + + '"$_d"' +}' + + +# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT +# -------------------------------------------------------- +# Perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# For efficiency, we do not delegate to the functions above but instead +# duplicate the functionality here. +eval 'func_dirname_and_basename () +{ + $debug_cmd + + '"$_b"' + '"$_d"' +}' + + +# func_echo ARG... +# ---------------- +# Echo program name prefixed message. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_echo_all ARG... +# -------------------- +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + + +# func_echo_infix_1 INFIX ARG... +# ------------------------------ +# Echo program name, followed by INFIX on the first line, with any +# additional lines not showing INFIX. +func_echo_infix_1 () +{ + $debug_cmd + + $require_term_colors + + _G_infix=$1; shift + _G_indent=$_G_infix + _G_prefix="$progname: $_G_infix: " + _G_message=$* + + # Strip color escape sequences before counting printable length + for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" + do + test -n "$_G_tc" && { + _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` + _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` + } + done + _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes + + func_echo_infix_1_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_infix_1_IFS + $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 + _G_prefix=$_G_indent + done + IFS=$func_echo_infix_1_IFS +} + + +# func_error ARG... +# ----------------- +# Echo program name prefixed message to standard error. +func_error () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 +} + + +# func_fatal_error ARG... +# ----------------------- +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + $debug_cmd + + func_error "$*" + exit $EXIT_FAILURE +} + + +# func_grep EXPRESSION FILENAME +# ----------------------------- +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $debug_cmd + + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_len STRING +# --------------- +# Set func_len_result to the length of STRING. STRING may not +# start with a hyphen. + test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_len () + { + $debug_cmd + + func_len_result=${#1} + }' +else + func_len () + { + $debug_cmd + + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` + } +fi + + +# func_mkdir_p DIRECTORY-PATH +# --------------------------- +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + $debug_cmd + + _G_directory_path=$1 + _G_dir_list= + + if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then + + # Protect directory names starting with '-' + case $_G_directory_path in + -*) _G_directory_path=./$_G_directory_path ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$_G_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + _G_dir_list=$_G_directory_path:$_G_dir_list + + # If the last portion added has no slash in it, the list is done + case $_G_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` + done + _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` + + func_mkdir_p_IFS=$IFS; IFS=: + for _G_dir in $_G_dir_list; do + IFS=$func_mkdir_p_IFS + # mkdir can fail with a 'File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$_G_dir" 2>/dev/null || : + done + IFS=$func_mkdir_p_IFS + + # Bail out if we (or some other process) failed to create a directory. + test -d "$_G_directory_path" || \ + func_fatal_error "Failed to create '$1'" + fi +} + + +# func_mktempdir [BASENAME] +# ------------------------- +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, BASENAME is the basename for that directory. +func_mktempdir () +{ + $debug_cmd + + _G_template=${TMPDIR-/tmp}/${1-$progname} + + if test : = "$opt_dry_run"; then + # Return a directory name, but don't create it in dry-run mode + _G_tmpdir=$_G_template-$$ + else + + # If mktemp works, use that first and foremost + _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` + + if test ! -d "$_G_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + _G_tmpdir=$_G_template-${RANDOM-0}$$ + + func_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$_G_tmpdir" + umask $func_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$_G_tmpdir" || \ + func_fatal_error "cannot create temporary directory '$_G_tmpdir'" + fi + + $ECHO "$_G_tmpdir" +} + + +# func_normal_abspath PATH +# ------------------------ +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +func_normal_abspath () +{ + $debug_cmd + + # These SED scripts presuppose an absolute path with a trailing slash. + _G_pathcar='s|^/\([^/]*\).*$|\1|' + _G_pathcdr='s|^/[^/]*||' + _G_removedotparts=':dotsl + s|/\./|/|g + t dotsl + s|/\.$|/|' + _G_collapseslashes='s|/\{1,\}|/|g' + _G_finalslash='s|/*$|/|' + + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` + while :; do + # Processed it all yet? + if test / = "$func_normal_abspath_tpath"; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result"; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + + +# func_notquiet ARG... +# -------------------- +# Echo program name prefixed message only when not in quiet mode. +func_notquiet () +{ + $debug_cmd + + $opt_quiet || func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + + +# func_relative_path SRCDIR DSTDIR +# -------------------------------- +# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. +func_relative_path () +{ + $debug_cmd + + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=$func_dirname_result + if test -z "$func_relative_path_tlibdir"; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test -n "$func_stripname_result"; then + func_append func_relative_path_result "/$func_stripname_result" + fi + + # Normalisation. If bindir is libdir, return '.' else relative path. + if test -n "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + fi + + test -n "$func_relative_path_result" || func_relative_path_result=. + + : +} + + +# func_quote_for_eval ARG... +# -------------------------- +# Aesthetically quote ARGs to be evaled later. +# This function returns two values: +# i) func_quote_for_eval_result +# double-quoted, suitable for a subsequent eval +# ii) func_quote_for_eval_unquoted_result +# has all characters that are still active within double +# quotes backslashified. +func_quote_for_eval () +{ + $debug_cmd + + func_quote_for_eval_unquoted_result= + func_quote_for_eval_result= + while test 0 -lt $#; do + case $1 in + *[\\\`\"\$]*) + _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; + *) + _G_unquoted_arg=$1 ;; + esac + if test -n "$func_quote_for_eval_unquoted_result"; then + func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" + else + func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" + fi + + case $_G_unquoted_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and variable expansion + # for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_quoted_arg=\"$_G_unquoted_arg\" + ;; + *) + _G_quoted_arg=$_G_unquoted_arg + ;; + esac + + if test -n "$func_quote_for_eval_result"; then + func_append func_quote_for_eval_result " $_G_quoted_arg" + else + func_append func_quote_for_eval_result "$_G_quoted_arg" + fi + shift + done +} + + +# func_quote_for_expand ARG +# ------------------------- +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + $debug_cmd + + case $1 in + *[\\\`\"]*) + _G_arg=`$ECHO "$1" | $SED \ + -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; + *) + _G_arg=$1 ;; + esac + + case $_G_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_arg=\"$_G_arg\" + ;; + esac + + func_quote_for_expand_result=$_G_arg +} + + +# func_stripname PREFIX SUFFIX NAME +# --------------------------------- +# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_stripname () + { + $debug_cmd + + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary variable first. + func_stripname_result=$3 + func_stripname_result=${func_stripname_result#"$1"} + func_stripname_result=${func_stripname_result%"$2"} + }' +else + func_stripname () + { + $debug_cmd + + case $2 in + .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; + *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; + esac + } +fi + + +# func_show_eval CMD [FAIL_EXP] +# ----------------------------- +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + func_quote_for_expand "$_G_cmd" + eval "func_notquiet $func_quote_for_expand_result" + + $opt_dry_run || { + eval "$_G_cmd" + _G_status=$? + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_show_eval_locale CMD [FAIL_EXP] +# ------------------------------------ +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + $opt_quiet || { + func_quote_for_expand "$_G_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + $opt_dry_run || { + eval "$_G_user_locale + $_G_cmd" + _G_status=$? + eval "$_G_safe_locale" + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_tr_sh +# ---------- +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + $debug_cmd + + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_verbose ARG... +# ------------------- +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $debug_cmd + + $opt_verbose && func_echo "$*" + + : +} + + +# func_warn_and_continue ARG... +# ----------------------------- +# Echo program name prefixed warning message to standard error. +func_warn_and_continue () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 +} + + +# func_warning CATEGORY ARG... +# ---------------------------- +# Echo program name prefixed warning message to standard error. Warning +# messages can be filtered according to CATEGORY, where this function +# elides messages where CATEGORY is not listed in the global variable +# 'opt_warning_types'. +func_warning () +{ + $debug_cmd + + # CATEGORY must be in the warning_categories list! + case " $warning_categories " in + *" $1 "*) ;; + *) func_internal_error "invalid warning category '$1'" ;; + esac + + _G_category=$1 + shift + + case " $opt_warning_types " in + *" $_G_category "*) $warning_func ${1+"$@"} ;; + esac +} + + +# func_sort_ver VER1 VER2 +# ----------------------- +# 'sort -V' is not generally available. +# Note this deviates from the version comparison in automake +# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a +# but this should suffice as we won't be specifying old +# version formats or redundant trailing .0 in bootstrap.conf. +# If we did want full compatibility then we should probably +# use m4_version_compare from autoconf. +func_sort_ver () +{ + $debug_cmd + + printf '%s\n%s\n' "$1" "$2" \ + | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n +} + +# func_lt_ver PREV CURR +# --------------------- +# Return true if PREV and CURR are in the correct order according to +# func_sort_ver, otherwise false. Use it like this: +# +# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." +func_lt_ver () +{ + $debug_cmd + + test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: +#! /bin/sh + +# Set a version string for this script. +scriptversion=2014-01-07.03; # UTC + +# A portable, pluggable option parser for Bourne shell. +# Written by Gary V. Vaughan, 2010 + +# Copyright (C) 2010-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program 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 General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# This file is a library for parsing options in your shell scripts along +# with assorted other useful supporting features that you can make use +# of too. +# +# For the simplest scripts you might need only: +# +# #!/bin/sh +# . relative/path/to/funclib.sh +# . relative/path/to/options-parser +# scriptversion=1.0 +# func_options ${1+"$@"} +# eval set dummy "$func_options_result"; shift +# ...rest of your script... +# +# In order for the '--version' option to work, you will need to have a +# suitably formatted comment like the one at the top of this file +# starting with '# Written by ' and ending with '# warranty; '. +# +# For '-h' and '--help' to work, you will also need a one line +# description of your script's purpose in a comment directly above the +# '# Written by ' line, like the one at the top of this file. +# +# The default options also support '--debug', which will turn on shell +# execution tracing (see the comment above debug_cmd below for another +# use), and '--verbose' and the func_verbose function to allow your script +# to display verbose messages only when your user has specified +# '--verbose'. +# +# After sourcing this file, you can plug processing for additional +# options by amending the variables from the 'Configuration' section +# below, and following the instructions in the 'Option parsing' +# section further down. + +## -------------- ## +## Configuration. ## +## -------------- ## + +# You should override these variables in your script after sourcing this +# file so that they reflect the customisations you have added to the +# option parser. + +# The usage line for option parsing errors and the start of '-h' and +# '--help' output messages. You can embed shell variables for delayed +# expansion at the time the message is displayed, but you will need to +# quote other shell meta-characters carefully to prevent them being +# expanded when the contents are evaled. +usage='$progpath [OPTION]...' + +# Short help message in response to '-h' and '--help'. Add to this or +# override it after sourcing this library to reflect the full set of +# options your script accepts. +usage_message="\ + --debug enable verbose shell tracing + -W, --warnings=CATEGORY + report the warnings falling in CATEGORY [all] + -v, --verbose verbosely report processing + --version print version information and exit + -h, --help print short or long help message and exit +" + +# Additional text appended to 'usage_message' in response to '--help'. +long_help_message=" +Warning categories include: + 'all' show all warnings + 'none' turn off all the warnings + 'error' warnings are treated as fatal errors" + +# Help message printed before fatal option parsing errors. +fatal_help="Try '\$progname --help' for more information." + + + +## ------------------------- ## +## Hook function management. ## +## ------------------------- ## + +# This section contains functions for adding, removing, and running hooks +# to the main code. A hook is just a named list of of function, that can +# be run in order later on. + +# func_hookable FUNC_NAME +# ----------------------- +# Declare that FUNC_NAME will run hooks added with +# 'func_add_hook FUNC_NAME ...'. +func_hookable () +{ + $debug_cmd + + func_append hookable_fns " $1" +} + + +# func_add_hook FUNC_NAME HOOK_FUNC +# --------------------------------- +# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must +# first have been declared "hookable" by a call to 'func_hookable'. +func_add_hook () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not accept hook functions." ;; + esac + + eval func_append ${1}_hooks '" $2"' +} + + +# func_remove_hook FUNC_NAME HOOK_FUNC +# ------------------------------------ +# Remove HOOK_FUNC from the list of functions called by FUNC_NAME. +func_remove_hook () +{ + $debug_cmd + + eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' +} + + +# func_run_hooks FUNC_NAME [ARG]... +# --------------------------------- +# Run all hook functions registered to FUNC_NAME. +# It is assumed that the list of hook functions contains nothing more +# than a whitespace-delimited list of legal shell function names, and +# no effort is wasted trying to catch shell meta-characters or preserve +# whitespace. +func_run_hooks () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not support hook funcions.n" ;; + esac + + eval _G_hook_fns=\$$1_hooks; shift + + for _G_hook in $_G_hook_fns; do + eval $_G_hook '"$@"' + + # store returned options list back into positional + # parameters for next 'cmd' execution. + eval _G_hook_result=\$${_G_hook}_result + eval set dummy "$_G_hook_result"; shift + done + + func_quote_for_eval ${1+"$@"} + func_run_hooks_result=$func_quote_for_eval_result +} + + + +## --------------- ## +## Option parsing. ## +## --------------- ## + +# In order to add your own option parsing hooks, you must accept the +# full positional parameter list in your hook function, remove any +# options that you action, and then pass back the remaining unprocessed +# options in '_result', escaped suitably for +# 'eval'. Like this: +# +# my_options_prep () +# { +# $debug_cmd +# +# # Extend the existing usage message. +# usage_message=$usage_message' +# -s, --silent don'\''t print informational messages +# ' +# +# func_quote_for_eval ${1+"$@"} +# my_options_prep_result=$func_quote_for_eval_result +# } +# func_add_hook func_options_prep my_options_prep +# +# +# my_silent_option () +# { +# $debug_cmd +# +# # Note that for efficiency, we parse as many options as we can +# # recognise in a loop before passing the remainder back to the +# # caller on the first unrecognised argument we encounter. +# while test $# -gt 0; do +# opt=$1; shift +# case $opt in +# --silent|-s) opt_silent=: ;; +# # Separate non-argument short options: +# -s*) func_split_short_opt "$_G_opt" +# set dummy "$func_split_short_opt_name" \ +# "-$func_split_short_opt_arg" ${1+"$@"} +# shift +# ;; +# *) set dummy "$_G_opt" "$*"; shift; break ;; +# esac +# done +# +# func_quote_for_eval ${1+"$@"} +# my_silent_option_result=$func_quote_for_eval_result +# } +# func_add_hook func_parse_options my_silent_option +# +# +# my_option_validation () +# { +# $debug_cmd +# +# $opt_silent && $opt_verbose && func_fatal_help "\ +# '--silent' and '--verbose' options are mutually exclusive." +# +# func_quote_for_eval ${1+"$@"} +# my_option_validation_result=$func_quote_for_eval_result +# } +# func_add_hook func_validate_options my_option_validation +# +# You'll alse need to manually amend $usage_message to reflect the extra +# options you parse. It's preferable to append if you can, so that +# multiple option parsing hooks can be added safely. + + +# func_options [ARG]... +# --------------------- +# All the functions called inside func_options are hookable. See the +# individual implementations for details. +func_hookable func_options +func_options () +{ + $debug_cmd + + func_options_prep ${1+"$@"} + eval func_parse_options \ + ${func_options_prep_result+"$func_options_prep_result"} + eval func_validate_options \ + ${func_parse_options_result+"$func_parse_options_result"} + + eval func_run_hooks func_options \ + ${func_validate_options_result+"$func_validate_options_result"} + + # save modified positional parameters for caller + func_options_result=$func_run_hooks_result +} + + +# func_options_prep [ARG]... +# -------------------------- +# All initialisations required before starting the option parse loop. +# Note that when calling hook functions, we pass through the list of +# positional parameters. If a hook function modifies that list, and +# needs to propogate that back to rest of this script, then the complete +# modified list must be put in 'func_run_hooks_result' before +# returning. +func_hookable func_options_prep +func_options_prep () +{ + $debug_cmd + + # Option defaults: + opt_verbose=false + opt_warning_types= + + func_run_hooks func_options_prep ${1+"$@"} + + # save modified positional parameters for caller + func_options_prep_result=$func_run_hooks_result +} + + +# func_parse_options [ARG]... +# --------------------------- +# The main option parsing loop. +func_hookable func_parse_options +func_parse_options () +{ + $debug_cmd + + func_parse_options_result= + + # this just eases exit handling + while test $# -gt 0; do + # Defer to hook functions for initial option parsing, so they + # get priority in the event of reusing an option name. + func_run_hooks func_parse_options ${1+"$@"} + + # Adjust func_parse_options positional parameters to match + eval set dummy "$func_run_hooks_result"; shift + + # Break out of the loop if we already parsed every option. + test $# -gt 0 || break + + _G_opt=$1 + shift + case $_G_opt in + --debug|-x) debug_cmd='set -x' + func_echo "enabling shell trace mode" + $debug_cmd + ;; + + --no-warnings|--no-warning|--no-warn) + set dummy --warnings none ${1+"$@"} + shift + ;; + + --warnings|--warning|-W) + test $# = 0 && func_missing_arg $_G_opt && break + case " $warning_categories $1" in + *" $1 "*) + # trailing space prevents matching last $1 above + func_append_uniq opt_warning_types " $1" + ;; + *all) + opt_warning_types=$warning_categories + ;; + *none) + opt_warning_types=none + warning_func=: + ;; + *error) + opt_warning_types=$warning_categories + warning_func=func_fatal_error + ;; + *) + func_fatal_error \ + "unsupported warning category: '$1'" + ;; + esac + shift + ;; + + --verbose|-v) opt_verbose=: ;; + --version) func_version ;; + -\?|-h) func_usage ;; + --help) func_help ;; + + # Separate optargs to long options (plugins may need this): + --*=*) func_split_equals "$_G_opt" + set dummy "$func_split_equals_lhs" \ + "$func_split_equals_rhs" ${1+"$@"} + shift + ;; + + # Separate optargs to short options: + -W*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-v*|-x*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) break ;; + -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + esac + done + + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + func_parse_options_result=$func_quote_for_eval_result +} + + +# func_validate_options [ARG]... +# ------------------------------ +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +func_hookable func_validate_options +func_validate_options () +{ + $debug_cmd + + # Display all warnings if -W was not given. + test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" + + func_run_hooks func_validate_options ${1+"$@"} + + # Bail if the options were screwed! + $exit_cmd $EXIT_FAILURE + + # save modified positional parameters for caller + func_validate_options_result=$func_run_hooks_result +} + + + +## ----------------- ## +## Helper functions. ## +## ----------------- ## + +# This section contains the helper functions used by the rest of the +# hookable option parser framework in ascii-betical order. + + +# func_fatal_help ARG... +# ---------------------- +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + eval \$ECHO \""$fatal_help"\" + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + + +# func_help +# --------- +# Echo long help message to standard output and exit. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message" + exit 0 +} + + +# func_missing_arg ARGNAME +# ------------------------ +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $debug_cmd + + func_error "Missing argument for '$1'." + exit_cmd=exit +} + + +# func_split_equals STRING +# ------------------------ +# Set func_split_equals_lhs and func_split_equals_rhs shell variables after +# splitting STRING at the '=' sign. +test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=${1%%=*} + func_split_equals_rhs=${1#*=} + test "x$func_split_equals_lhs" = "x$1" \ + && func_split_equals_rhs= + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` + func_split_equals_rhs= + test "x$func_split_equals_lhs" = "x$1" \ + || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` + } +fi #func_split_equals + + +# func_split_short_opt SHORTOPT +# ----------------------------- +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"} + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` + func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` + } +fi #func_split_short_opt + + +# func_usage +# ---------- +# Echo short help message to standard output and exit. +func_usage () +{ + $debug_cmd + + func_usage_message + $ECHO "Run '$progname --help |${PAGER-more}' for full usage" + exit 0 +} + + +# func_usage_message +# ------------------ +# Echo short help message to standard output. +func_usage_message () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + echo + $SED -n 's|^# || + /^Written by/{ + x;p;x + } + h + /^Written by/q' < "$progpath" + echo + eval \$ECHO \""$usage_message"\" +} + + +# func_version +# ------------ +# Echo version message to standard output and exit. +func_version () +{ + $debug_cmd + + printf '%s\n' "$progname $scriptversion" + $SED -n ' + /(C)/!b go + :more + /\./!{ + N + s|\n# | | + b more + } + :go + /^# Written by /,/# warranty; / { + s|^# || + s|^# *$|| + s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| + p + } + /^# Written by / { + s|^# || + p + } + /^warranty; /q' < "$progpath" + + exit $? +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: + +# Set a version string. +scriptversion='(GNU libtool) 2.4.6' + + +# func_echo ARG... +# ---------------- +# Libtool also displays the current mode in messages, so override +# funclib.sh func_echo with this custom definition. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_warning ARG... +# ------------------- +# Libtool warnings are not categorized, so override funclib.sh +# func_warning with this simpler definition. +func_warning () +{ + $debug_cmd + + $warning_func ${1+"$@"} +} + + +## ---------------- ## +## Options parsing. ## +## ---------------- ## + +# Hook in the functions to make sure our own options are parsed during +# the option parsing loop. + +usage='$progpath [OPTION]... [MODE-ARG]...' + +# Short help message in response to '-h'. +usage_message="Options: + --config show all configuration variables + --debug enable verbose shell tracing + -n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --mode=MODE use operation mode MODE + --no-warnings equivalent to '-Wnone' + --preserve-dup-deps don't remove duplicate dependency libraries + --quiet, --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + -v, --verbose print more informational messages than default + --version print version information + -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] + -h, --help, --help-all print short, long, or detailed help message +" + +# Additional text appended to 'usage_message' in response to '--help'. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. When passed as first option, +'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. +Try '$progname --help --mode=MODE' for a more detailed description of MODE. + +When reporting a bug, please describe a test case to reproduce it and +include the following information: + + host-triplet: $host + shell: $SHELL + compiler: $LTCC + compiler flags: $LTCFLAGS + linker: $LD (gnu? $with_gnu_ld) + version: $progname (GNU libtool) 2.4.6 + automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` + autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` + +Report bugs to . +GNU libtool home page: . +General help using GNU software: ." + exit 0 +} + + +# func_lo2o OBJECT-NAME +# --------------------- +# Transform OBJECT-NAME from a '.lo' suffix to the platform specific +# object suffix. + +lo2o=s/\\.lo\$/.$objext/ +o2lo=s/\\.$objext\$/.lo/ + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_lo2o () + { + case $1 in + *.lo) func_lo2o_result=${1%.lo}.$objext ;; + * ) func_lo2o_result=$1 ;; + esac + }' + + # func_xform LIBOBJ-OR-SOURCE + # --------------------------- + # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) + # suffix to a '.lo' libtool-object suffix. + eval 'func_xform () + { + func_xform_result=${1%.*}.lo + }' +else + # ...otherwise fall back to using sed. + func_lo2o () + { + func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` + } + + func_xform () + { + func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` + } +fi + + +# func_fatal_configuration ARG... +# ------------------------------- +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func__fatal_error ${1+"$@"} \ + "See the $PACKAGE documentation for more information." \ + "Fatal configuration error." +} + + +# func_config +# ----------- +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + + +# func_features +# ------------- +# Display the features supported by this script. +func_features () +{ + echo "host: $host" + if test yes = "$build_libtool_libs"; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test yes = "$build_old_libs"; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + + exit $? +} + + +# func_enable_tag TAGNAME +# ----------------------- +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname=$1 + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf=/$re_begincf/,/$re_endcf/p + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + + +# func_check_version_match +# ------------------------ +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# libtool_options_prep [ARG]... +# ----------------------------- +# Preparation for options parsed by libtool. +libtool_options_prep () +{ + $debug_mode + + # Option defaults: + opt_config=false + opt_dlopen= + opt_dry_run=false + opt_help=false + opt_mode= + opt_preserve_dup_deps=false + opt_quiet=false + + nonopt= + preserve_args= + + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; + esac + + # Pass back the list of options. + func_quote_for_eval ${1+"$@"} + libtool_options_prep_result=$func_quote_for_eval_result +} +func_add_hook func_options_prep libtool_options_prep + + +# libtool_parse_options [ARG]... +# --------------------------------- +# Provide handling for libtool specific options. +libtool_parse_options () +{ + $debug_cmd + + # Perform our own loop to consume as many options as possible in + # each iteration. + while test $# -gt 0; do + _G_opt=$1 + shift + case $_G_opt in + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + + --config) func_config ;; + + --dlopen|-dlopen) + opt_dlopen="${opt_dlopen+$opt_dlopen +}$1" + shift + ;; + + --preserve-dup-deps) + opt_preserve_dup_deps=: ;; + + --features) func_features ;; + + --finish) set dummy --mode finish ${1+"$@"}; shift ;; + + --help) opt_help=: ;; + + --help-all) opt_help=': help-all' ;; + + --mode) test $# = 0 && func_missing_arg $_G_opt && break + opt_mode=$1 + case $1 in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $_G_opt" + exit_cmd=exit + break + ;; + esac + shift + ;; + + --no-silent|--no-quiet) + opt_quiet=false + func_append preserve_args " $_G_opt" + ;; + + --no-warnings|--no-warning|--no-warn) + opt_warning=false + func_append preserve_args " $_G_opt" + ;; + + --no-verbose) + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --silent|--quiet) + opt_quiet=: + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --tag) test $# = 0 && func_missing_arg $_G_opt && break + opt_tag=$1 + func_append preserve_args " $_G_opt $1" + func_enable_tag "$1" + shift + ;; + + --verbose|-v) opt_quiet=false + opt_verbose=: + func_append preserve_args " $_G_opt" + ;; + + # An option not handled by this hook function: + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + esac + done + + + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + libtool_parse_options_result=$func_quote_for_eval_result +} +func_add_hook func_parse_options libtool_parse_options + + + +# libtool_validate_options [ARG]... +# --------------------------------- +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +libtool_validate_options () +{ + # save first non-option argument + if test 0 -lt $#; then + nonopt=$1 + shift + fi + + # preserve --debug + test : = "$debug_cmd" || func_append preserve_args " --debug" + + case $host in + # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 + # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 + *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + test yes != "$build_libtool_libs" \ + && test yes != "$build_old_libs" \ + && func_fatal_configuration "not configured to build any kind of library" + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test execute != "$opt_mode"; then + func_error "unrecognized option '-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help=$help + help="Try '$progname --help --mode=$opt_mode' for more information." + } + + # Pass back the unparsed argument list + func_quote_for_eval ${1+"$@"} + libtool_validate_options_result=$func_quote_for_eval_result +} +func_add_hook func_validate_options libtool_validate_options + + +# Process options as early as possible so that --help and --version +# can return quickly. +func_options ${1+"$@"} +eval set dummy "$func_options_result"; shift + + + +## ----------- ## +## Main. ## +## ----------- ## + +magic='%%%MAGIC variable%%%' +magic_exe='%%%MAGIC EXE variable%%%' + +# Global variables. +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# func_generated_by_libtool +# True iff stdin has been generated by Libtool. This function is only +# a basic sanity check; it will hardly flush out determined imposters. +func_generated_by_libtool_p () +{ + $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if 'file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case $lalib_p_line in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test yes = "$lalib_p" +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + test -f "$1" && + $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $debug_cmd + + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# 'FILE.' does not work on cygwin managed mounts. +func_source () +{ + $debug_cmd + + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case $lt_sysroot:$1 in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result='='$func_stripname_result + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $debug_cmd + + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with '--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=$1 + if test yes = "$build_libtool_libs"; then + write_lobj=\'$2\' + else + write_lobj=none + fi + + if test yes = "$build_old_libs"; then + write_oldobj=\'$3\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T </dev/null` + if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $debug_cmd + + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result= + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result"; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $debug_cmd + + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $debug_cmd + + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $debug_cmd + + if test -z "$2" && test -n "$1"; then + func_error "Could not determine host file name corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result=$1 + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $debug_cmd + + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " '$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result=$3 + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $debug_cmd + + case $4 in + $1 ) func_to_host_path_result=$3$func_to_host_path_result + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via '$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $debug_cmd + + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $debug_cmd + + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result=$1 +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result=$func_convert_core_msys_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result=$func_convert_core_file_wine_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via '$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $debug_cmd + + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd=func_convert_path_$func_stripname_result + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $debug_cmd + + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result=$1 +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_msys_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_path_wine_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_dll_def_p FILE +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with _LT_DLL_DEF_P in libtool.m4 +func_dll_def_p () +{ + $debug_cmd + + func_dll_def_p_tmp=`$SED -n \ + -e 's/^[ ]*//' \ + -e '/^\(;.*\)*$/d' \ + -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ + -e q \ + "$1"` + test DEF = "$func_dll_def_p_tmp" +} + + +# func_mode_compile arg... +func_mode_compile () +{ + $debug_cmd + + # Get the compilation command and the source file. + base_compile= + srcfile=$nonopt # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg=$arg + arg_mode=normal + ;; + + target ) + libobj=$arg + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify '-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append later " $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs=$IFS; IFS=, + for arg in $args; do + IFS=$save_ifs + func_append_quoted lastarg "$arg" + done + IFS=$save_ifs + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append base_compile " $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg=$srcfile + srcfile=$arg + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with '-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj=$func_basename_result + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from '$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test yes = "$build_libtool_libs" \ + || func_fatal_configuration "cannot build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_for_eval "$libobj" + test "X$libobj" != "X$func_quote_for_eval_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name '$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname=$func_basename_result + xdir=$func_dirname_result + lobj=$xdir$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test yes = "$build_old_libs"; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test no = "$compiler_c_o"; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext + lockfile=$output_obj.lock + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test yes = "$need_locks"; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test warn = "$need_locks"; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test yes = "$build_libtool_libs"; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test no != "$pic_mode"; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test yes = "$suppress_opt"; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test yes = "$build_old_libs"; then + if test yes != "$pic_mode"; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test yes = "$compiler_c_o"; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test no != "$need_locks"; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test compile = "$opt_mode" && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a '.o' file suitable for static linking + -static only build a '.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +COMPILE-COMMAND is a command to be used in creating a 'standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix '.c' with the +library object suffix, '.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to '-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the '--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the 'install' or 'cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE use a list of object files found in FILE to specify objects + -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +All other options (arguments beginning with '-') are ignored. + +Every other argument is treated as a filename. Files ending in '.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in '.la', then a libtool library is created, +only library objects ('.lo' files) may be specified, and '-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created +using 'ar' and 'ranlib', or on Windows using 'lib'. + +If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode '$opt_mode'" + ;; + esac + + echo + $ECHO "Try '$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test : = "$opt_help"; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | $SED -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + $SED '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $debug_cmd + + # The first argument is the command name. + cmd=$nonopt + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "'$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "'$file' was not linked with '-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir=$func_dirname_result + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir=$func_dirname_result + ;; + + *) + func_warning "'-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir=$absdir + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic=$magic + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file=$progdir/$program + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file=$progdir/$program + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if $opt_dry_run; then + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + else + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd=\$cmd$args + fi +} + +test execute = "$opt_mode" && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $debug_cmd + + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "'$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument '$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and '=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_quiet && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the '-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the '$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the '$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the '$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" + fi + echo + + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test finish = "$opt_mode" && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $debug_cmd + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || + # Allow the use of GNU shtool's install command. + case $nonopt in *shtool*) :;; *) false;; esac + then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + func_append install_prog "$func_quote_for_eval_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=false + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=: ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test X-m = "X$prev" && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + func_append install_prog " $func_quote_for_eval_result" + if test -n "$arg2"; then + func_quote_for_eval "$arg2" + fi + func_append install_shared_prog " $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the '$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_for_eval "$install_override_mode" + func_append install_shared_prog " -m $func_quote_for_eval_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=: + if $isdir; then + destdir=$dest + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir=$func_dirname_result + destname=$func_basename_result + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "'$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "'$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir=$func_dirname_result + func_append dir "$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking '$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname=$1 + shift + + srcname=$realname + test -n "$relink_command" && srcname=${realname}T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme=$stripme + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme= + ;; + esac + ;; + os2*) + case $realname in + *_dll.a) + tstripme= + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try 'ln -sf' first, because the 'ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib=$destdir/$realname + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name=$func_basename_result + instname=$dir/${name}i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append staticlibs " $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest=$destfile + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to '$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test yes = "$build_old_libs"; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext= + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=.exe + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script '$wrapper'" + + finalize=: + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "'$lib' has not been installed in '$libdir'" + finalize=false + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test no = "$fast_install" && test -n "$relink_command"; then + $opt_dry_run || { + if $finalize; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file=$func_basename_result + outputname=$tmpdir/$file + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_quiet || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink '$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file=$outputname + else + func_warning "cannot relink '$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name=$func_basename_result + + # Set up the ranlib parameters. + oldlib=$destdir/$name + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $tool_oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run '$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test install = "$opt_mode" && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $debug_cmd + + my_outputname=$1 + my_originator=$2 + my_pic_p=${3-false} + my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms=${my_outputname}S.c + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist=$output_objdir/$my_outputname.nm + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* External symbol declarations for the compiler. */\ +" + + if test yes = "$dlself"; then + func_verbose "generating symbol list for '$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from '$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols=$output_objdir/$outputname.exp + $opt_dry_run || { + $RM $export_symbols + eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from '$dlprefile'" + func_basename "$dlprefile" + name=$func_basename_result + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename= + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname"; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename=$func_basename_result + else + # no lafile. user explicitly requested -dlpreopen . + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename"; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + func_show_eval '$RM "${nlist}I"' + if test -n "$global_symbol_to_import"; then + eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[];\ +" + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ +static void lt_syminit(void) +{ + LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; + for (; symbol->name; ++symbol) + {" + $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" + echo >> "$output_objdir/$my_dlsyms" "\ + } +}" + fi + echo >> "$output_objdir/$my_dlsyms" "\ +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{ {\"$my_originator\", (void *) 0}," + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ + {\"@INIT@\", (void *) <_syminit}," + fi + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + $my_pic_p && pic_flag_for_symtable=" $pic_flag" + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' + + # Transform the symbol file into the correct name. + symfileobj=$output_objdir/${my_outputname}S.$objext + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for '$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $debug_cmd + + win32_libid_type=unknown + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + case $nm_interface in + "MS dumpbin") + if func_cygming_ms_implib_p "$1" || + func_cygming_gnu_implib_p "$1" + then + win32_nmres=import + else + win32_nmres= + fi + ;; + *) + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' + 1,100{ + / I /{ + s|.*|import| + p + q + } + }'` + ;; + esac + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $debug_cmd + + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $debug_cmd + + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive that possess that section. Heuristic: eliminate + # all those that have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $debug_cmd + + if func_cygming_gnu_implib_p "$1"; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1"; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result= + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $debug_cmd + + f_ex_an_ar_dir=$1; shift + f_ex_an_ar_oldlib=$1 + if test yes = "$lock_old_archive_extraction"; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test yes = "$lock_old_archive_extraction"; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $debug_cmd + + my_gentop=$1; shift + my_oldlibs=${1+"$@"} + my_oldobjs= + my_xlib= + my_xabs= + my_xdir= + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib=$func_basename_result + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir=$my_gentop/$my_xlib_u + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + func_basename "$darwin_archive" + darwin_base_archive=$func_basename_result + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches; do + func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" + $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" + cd "unfat-$$/$darwin_base_archive-$darwin_arch" + func_extract_an_archive "`pwd`" "$darwin_base_archive" + cd "$darwin_curdir" + $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result=$my_oldobjs +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory where it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + file=\"\$0\"" + + qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=\"$qECHO\" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case \" \$* \" in + *\\ --lt-*) + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done ;; + esac + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test yes = "$fast_install"; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + \$ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +#else +# include +# include +# ifdef __CYGWIN__ +# include +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* declarations of non-ANSI functions */ +#if defined __MINGW32__ +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined __CYGWIN__ +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined other_platform || defined ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined _MSC_VER +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +#elif defined __MINGW32__ +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined __CYGWIN__ +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined other platforms ... */ +#endif + +#if defined PATH_MAX +# define LT_PATHMAX PATH_MAX +#elif defined MAXPATHLEN +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ + defined __OS2__ +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free (stale); stale = 0; } \ +} while (0) + +#if defined LT_DEBUGWRAPPER +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + size_t tmp_len; + char *concat_name; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined HAVE_DOS_BASED_FILE_SYSTEM + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined HAVE_DOS_BASED_FILE_SYSTEM + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = (size_t) (q - p); + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (STREQ (str, pat)) + *str = '\0'; + } + return str; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + size_t len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + size_t orig_value_len = strlen (orig_value); + size_t add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + size_t len = strlen (new_value); + while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[--len] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -n -e ' +s/^\(.\{79\}\)\(..*\)/\1\ +\2/ +h +s/\([\\"]\)/\\\1/g +s/$/\\n/ +s/\([^\n]*\).*/ fputs ("\1", f);/p +g +D' + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $debug_cmd + + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_suncc_cstd_abi +# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! +# Several compiler flags select an ABI that is incompatible with the +# Cstd library. Avoid specifying it if any are in CXXFLAGS. +func_suncc_cstd_abi () +{ + $debug_cmd + + case " $compile_command " in + *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) + suncc_use_cstd_abi=no + ;; + *) + suncc_use_cstd_abi=yes + ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $debug_cmd + + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # what system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll that has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + os2dllname= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=false + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module=$wl-single_module + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test yes != "$build_libtool_libs" \ + && func_fatal_configuration "cannot build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg=$1 + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir=$arg + prev= + continue + ;; + dlfiles|dlprefiles) + $preload || { + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=: + } + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test no = "$dlself"; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test dlprefiles = "$prev"; then + dlself=yes + elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test dlfiles = "$prev"; then + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols=$arg + test -f "$arg" \ + || func_fatal_error "symbol file '$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex=$arg + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir=$arg + prev= + continue + ;; + mllvm) + # Clang does not use LLVM to link, so we can simply discard any + # '-mllvm $arg' options when doing the link step. + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + if test none != "$pic_object"; then + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + fi + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file '$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + os2dllname) + os2dllname=$arg + prev= + continue + ;; + precious_regex) + precious_files_regex=$arg + prev= + continue + ;; + release) + release=-$arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test rpath = "$prev"; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds=$arg + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg=$arg + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "'-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test X-export-symbols = "X$arg"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between '-L' and '$1'" + else + func_fatal_error "need path for '-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of '$dir'" + dir=$absdir + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test X-lc = "X$arg" || test X-lm = "X$arg"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test X-lc = "X$arg" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc due to us having libc/libc_r. + test X-lc = "X$arg" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + func_append deplibs " System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test X-lc = "X$arg" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test X-lc = "X$arg" && continue + ;; + esac + elif test X-lc_r = "X$arg"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + func_append deplibs " $arg" + continue + ;; + + -mllvm) + prev=mllvm + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module=$wl-multi_module + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "'-no-install' is ignored for $host" + func_warning "assuming '-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -os2dllname) + prev=os2dllname + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $func_quote_for_eval_result" + func_append compiler_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $wl$func_quote_for_eval_result" + func_append compiler_flags " $wl$func_quote_for_eval_result" + func_append linker_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # -fstack-protector* stack protector flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -stdlib=* select c++ std lib with clang + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + -Z*) + if test os2 = "`expr $host : '.*\(os2\)'`"; then + # OS/2 uses -Zxxx to specify OS/2-specific options + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case $arg in + -Zlinker | -Zstack) + prev=xcompiler + ;; + esac + continue + else + # Otherwise treat like 'Some other compiler flag' below + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + fi + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + test none = "$pic_object" || { + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + } + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test dlfiles = "$prev"; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test dlprefiles = "$prev"; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the '$prevarg' option requires an argument" + + if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname=$func_basename_result + libobjs_save=$libobjs + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + # Definition is injected by LT_CONFIG during libtool generation. + func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" + + func_dirname "$output" "/" "" + output_objdir=$func_dirname_result$objdir + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_preserve_dup_deps; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append libs " $deplib" + done + + if test lib = "$linkmode"; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append pre_post_deps " $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=false + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test lib,link = "$linkmode,$pass"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs=$tmp_deplibs + fi + + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass"; then + libs=$deplibs + deplibs= + fi + if test prog = "$linkmode"; then + case $pass in + dlopen) libs=$dlfiles ;; + dlpreopen) libs=$dlprefiles ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + esac + fi + if test lib,dlpreopen = "$linkmode,$pass"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs=$dlprefiles + fi + if test dlopen = "$pass"; then + # Collect dlpreopened libraries + save_deplibs=$deplibs + deplibs= + fi + + for deplib in $libs; do + lib= + found=false + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test lib != "$linkmode" && test prog != "$linkmode"; then + func_warning "'-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test lib = "$linkmode"; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib=$searchdir/lib$name$search_ext + if test -f "$lib"; then + if test .la = "$search_ext"; then + found=: + else + found=false + fi + break 2 + fi + done + done + if $found; then + # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll=$l + done + if test "X$ll" = "X$old_library"; then # only static version available + found=false + func_dirname "$lib" "" "." + ladir=$func_dirname_result + lib=$ladir/$old_library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + else + # deplib doesn't seem to be a libtool library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + ;; # -l + *.ltframework) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test conv = "$pass" && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + prog) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + if test scan = "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "'-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test link = "$pass"; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=false + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=: + fi + ;; + pass_all) + valid_a_lib=: + ;; + esac + if $valid_a_lib; then + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + else + echo + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." + fi + ;; + esac + continue + ;; + prog) + if test link != "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + elif test prog = "$linkmode"; then + if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=: + continue + ;; + esac # case $deplib + + $found || test -f "$lib" \ + || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "'$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir=$func_dirname_result + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass" || + { test prog != "$linkmode" && test lib != "$linkmode"; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" + fi + + if test conv = "$pass"; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + elif test prog != "$linkmode" && test lib != "$linkmode"; then + func_fatal_error "'$lib' is not a convenience library" + fi + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test yes = "$prefer_static_libs" || + test built,no = "$prefer_static_libs,$installed"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib=$l + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + + # This library was specified with -dlopen. + if test dlopen = "$pass"; then + test -z "$libdir" \ + && func_fatal_error "cannot -dlopen a convenience library: '$lib'" + if test -z "$dlname" || + test yes != "$dlopen_support" || + test no = "$build_libtool_libs" + then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + func_append dlprefiles " $lib $dependency_libs" + else + func_append newdlfiles " $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of '$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir=$ladir + fi + ;; + esac + func_basename "$lib" + laname=$func_basename_result + + # Find the relevant object directory and library name. + if test yes = "$installed"; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library '$lib' was moved." + dir=$ladir + absdir=$abs_ladir + libdir=$abs_ladir + else + dir=$lt_sysroot$libdir + absdir=$lt_sysroot$libdir + fi + test yes = "$hardcode_automatic" && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir=$ladir + absdir=$abs_ladir + # Remove this search path later + func_append notinst_path " $abs_ladir" + else + dir=$ladir/$objdir + absdir=$abs_ladir/$objdir + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test dlpreopen = "$pass"; then + if test -z "$libdir" && test prog = "$linkmode"; then + func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" + fi + case $host in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test lib = "$linkmode"; then + deplibs="$dir/$old_library $deplibs" + elif test prog,link = "$linkmode,$pass"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test prog = "$linkmode" && test link != "$pass"; then + func_append newlib_search_path " $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=false + if test no != "$link_all_deplibs" || test -z "$library_names" || + test no = "$build_libtool_libs"; then + linkalldeplibs=: + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + esac + # Need to link against all dependency_libs? + if $linkalldeplibs; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test prog,link = "$linkmode,$pass"; then + if test -n "$library_names" && + { { test no = "$prefer_static_libs" || + test built,yes = "$prefer_static_libs,$installed"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then + # Make sure the rpath contains only unique directories. + case $temp_rpath: in + *"$absdir:"*) ;; + *) func_append temp_rpath "$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if $alldeplibs && + { test pass_all = "$deplibs_check_method" || + { test yes = "$build_libtool_libs" && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test built = "$use_static_libs" && test yes = "$installed"; then + use_static_libs=no + fi + if test -n "$library_names" && + { test no = "$use_static_libs" || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc* | *os2*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test no = "$installed"; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule= + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule=$dlpremoduletest + break + fi + done + if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then + echo + if test prog = "$linkmode"; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test lib = "$linkmode" && + test yes = "$hardcode_into_libs"; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname=$1 + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname=$dlname + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc* | *os2*) + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + esac + eval soname=\"$soname_spec\" + else + soname=$realname + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot=$soname + func_basename "$soroot" + soname=$func_basename_result + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from '$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for '$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test prog = "$linkmode" || test relink != "$opt_mode"; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test no = "$hardcode_direct"; then + add=$dir/$linklib + case $host in + *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; + *-*-sysv4*uw2*) add_dir=-L$dir ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir=-L$dir ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we cannot + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library"; then + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" + else + add=$dir/$old_library + fi + elif test -n "$old_library"; then + add=$dir/$old_library + fi + fi + esac + elif test no = "$hardcode_minus_L"; then + case $host in + *-*-sunos*) add_shlibpath=$dir ;; + esac + add_dir=-L$dir + add=-l$name + elif test no = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + relink) + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$dir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$absdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test yes != "$lib_linked"; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; + esac + fi + if test prog = "$linkmode"; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test yes != "$hardcode_direct" && + test yes != "$hardcode_minus_L" && + test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test prog = "$linkmode" || test relink = "$opt_mode"; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$libdir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$libdir + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + add=-l$name + elif test yes = "$hardcode_automatic"; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib"; then + add=$inst_prefix_dir$libdir/$linklib + else + add=$libdir/$linklib + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir=-L$libdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + fi + + if test prog = "$linkmode"; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test prog = "$linkmode"; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test unsupported != "$hardcode_direct"; then + test -n "$old_library" && linklib=$old_library + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test yes = "$build_libtool_libs"; then + # Not a shared library + if test pass_all != "$deplibs_check_method"; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + $ECHO "*** Warning: This system cannot link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test yes = "$module"; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test lib = "$linkmode"; then + if test -n "$dependency_libs" && + { test yes != "$hardcode_into_libs" || + test yes = "$build_old_libs" || + test yes = "$link_static"; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs=$temp_deplibs + fi + + func_append newlib_search_path " $absdir" + # Link against this library + test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test no != "$link_all_deplibs"; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path=$deplib ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of '$dir'" + absdir=$dir + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names"; then + for tmp in $deplibrary_names; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl"; then + depdepl=$absdir/$objdir/$depdepl + darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" + func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" + path= + fi + fi + ;; + *) + path=-L$absdir/$objdir + ;; + esac + else + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "'$deplib' seems to be moved" + + path=-L$absdir + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test link = "$pass"; then + if test prog = "$linkmode"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs=$newdependency_libs + if test dlpreopen = "$pass"; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test dlopen != "$pass"; then + test conv = "$pass" || { + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) func_append lib_search_path " $dir" ;; + esac + done + newlib_search_path= + } + + if test prog,link = "$linkmode,$pass"; then + vars="compile_deplibs finalize_deplibs" + else + vars=deplibs + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append tmp_libs " $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + + # Add Sun CC postdeps if required: + test CXX = "$tagname" && { + case $host_os in + linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C++ 5.9 + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + + solaris*) + func_cc_basename "$CC" + case $func_cc_basename_result in + CC* | sunCC*) + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + esac + } + + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i= + ;; + esac + if test -n "$i"; then + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test prog = "$linkmode"; then + dlfiles=$newdlfiles + fi + if test prog = "$linkmode" || test lib = "$linkmode"; then + dlprefiles=$newdlprefiles + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "'-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "'-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs=$output + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form 'libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test no = "$module" \ + && func_fatal_help "libtool library '$output' must begin with 'lib'" + + if test no != "$need_lib_prefix"; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test pass_all != "$deplibs_check_method"; then + func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test no = "$dlself" \ + || func_warning "'-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test 1 -lt "$#" \ + && func_warning "ignoring multiple '-rpath's for a libtool library" + + install_libdir=$1 + + oldlibs= + if test -z "$rpath"; then + if test yes = "$build_libtool_libs"; then + # Building a libtool convenience library. + # Some compilers have problems with a '.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "'-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs=$IFS; IFS=: + set dummy $vinfo 0 0 0 + shift + IFS=$save_ifs + + test -n "$7" && \ + func_fatal_help "too many parameters to '-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major=$1 + number_minor=$2 + number_revision=$3 + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # that has an extra 1 added just for fun + # + case $version_type in + # correct linux to gnu/linux during the next big refactor + darwin|freebsd-elf|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_revision + ;; + freebsd-aout|qnx|sunos) + current=$number_major + revision=$number_minor + age=0 + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_minor + lt_irix_increment=no + ;; + esac + ;; + no) + current=$1 + revision=$2 + age=$3 + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT '$current' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION '$revision' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE '$age' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE '$age' is greater than the current interface number '$current'" + func_fatal_error "'$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + # On Darwin other compilers + case $CC in + nagfor*) + verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + ;; + *) + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + esac + ;; + + freebsd-aout) + major=.$current + versuffix=.$current.$revision + ;; + + freebsd-elf) + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + irix | nonstopux) + if test no = "$lt_irix_increment"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring=$verstring_prefix$major.$revision + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test 0 -ne "$loop"; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring_prefix$major.$iface:$verstring + done + + # Before this point, $major must not contain '.'. + major=.$major + versuffix=$major.$revision + ;; + + linux) # correct to gnu/linux during the next big refactor + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=.$current.$age.$revision + verstring=$current.$age.$revision + + # Add in all the interfaces that we are compatible with. + loop=$age + while test 0 -ne "$loop"; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring:$iface.0 + done + + # Make executables depend on our current version. + func_append verstring ":$current.0" + ;; + + qnx) + major=.$current + versuffix=.$current + ;; + + sco) + major=.$current + versuffix=.$current + ;; + + sunos) + major=.$current + versuffix=.$current.$revision + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 file systems. + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + + *) + func_fatal_configuration "unknown library version type '$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring=0.0 + ;; + esac + if test no = "$need_version"; then + versuffix= + else + versuffix=.0.0 + fi + fi + + # Remove version info from name if versioning should be avoided + if test yes,no = "$avoid_version,$need_version"; then + major= + versuffix= + verstring= + fi + + # Check to see if the archive will have undefined symbols. + if test yes = "$allow_undefined"; then + if test unsupported = "$allow_undefined_flag"; then + if test yes = "$build_old_libs"; then + func_warning "undefined symbols not allowed in $host shared libraries; building static only" + build_libtool_libs=no + else + func_fatal_error "can't build $host shared library unless -no-undefined is specified" + fi + fi + else + # Don't allow undefined symbols. + allow_undefined_flag=$no_undefined_flag + fi + + fi + + func_generate_dlsyms "$libname" "$libname" : + func_append libobjs " $symfileobj" + test " " = "$libobjs" && libobjs= + + if test relink != "$opt_mode"; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) + if test -n "$precious_files_regex"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles=$dlfiles + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) func_append dlfiles " $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles=$dlprefiles + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test yes = "$build_libtool_libs"; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test yes = "$build_libtool_need_lc"; then + func_append deplibs " -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release= + versuffix= + major= + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib=$potent_lib + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | $SED 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; + *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib= + ;; + esac + fi + if test -n "$a_deplib"; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib=$potent_lib # see symlink-check above in file_magic test + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs= + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + for i in $predeps $postdeps; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + echo + if test none = "$deplibs_check_method"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + ;; + esac + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + if test yes = "$droppeddeps"; then + if test yes = "$module"; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test no = "$allow_undefined"; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + deplibs=$new_libs + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test yes = "$build_libtool_libs"; then + # Remove $wl instances when linking with ld. + # FIXME: should test the right _cmds variable. + case $archive_cmds in + *\$LD\ *) wl= ;; + esac + if test yes = "$hardcode_into_libs"; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath=$finalize_rpath + test relink = "$opt_mode" || rpath=$compile_rpath$rpath + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath=$finalize_shlibpath + test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname=$1 + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname=$realname + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib=$output_objdir/$realname + linknames= + for link + do + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols=$output_objdir/$libname.uexp + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + func_dll_def_p "$export_symbols" || { + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols=$export_symbols + export_symbols= + always_export_symbols=yes + } + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs=$IFS; IFS='~' + for cmd1 in $cmds; do + IFS=$save_ifs + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test yes = "$try_normal_branch" \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=$output_objdir/$output_la.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS=$save_ifs + if test -n "$export_symbols_regex" && test : != "$skipped_export"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test : != "$skipped_export" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs=$tmp_deplibs + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test yes = "$compiler_needs_object" && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test : != "$skipped_export" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then + output=$output_objdir/$output_la.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then + output=$output_objdir/$output_la.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test yes = "$compiler_needs_object"; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-$k.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test -z "$objlist" || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test 1 -eq "$k"; then + # The first file doesn't have a previous command to add. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-$k.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-$k.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + ${skipped_export-false} && { + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + } + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs=$IFS; IFS='~' + for cmd in $concat_cmds; do + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + ${skipped_export-false} && { + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + } + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs=$IFS; IFS='~' + for cmd in $cmds; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test yes = "$module" || test yes = "$export_dynamic"; then + # On all known operating systems, these are identical. + dlname=$soname + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "'-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object '$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj=$output + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # if reload_cmds runs $LD directly, get rid of -Wl from + # whole_archive_flag_spec and hope we can get by with turning comma + # into space. + case $reload_cmds in + *\$LD[\ \$]*) wl= ;; + esac + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags + else + gentop=$output_objdir/${obj}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test yes = "$build_libtool_libs" || libobjs=$non_pic_objects + + # Create the old-style object. + reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs + + output=$obj + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + test yes = "$build_libtool_libs" || { + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + } + + if test -n "$pic_flag" || test default != "$pic_mode"; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output=$libobj + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "'-release' is ignored for programs" + + $preload \ + && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ + && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test CXX = "$tagname"; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " $wl-bind_at_load" + func_append finalize_command " $wl-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs=$new_libs + + + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath=$rpath + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append finalize_perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath=$rpath + + if test -n "$libobjs" && test yes = "$build_old_libs"; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" false + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=: + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=false + ;; + *cygwin* | *mingw* ) + test yes = "$build_libtool_libs" || wrappers_required=false + ;; + *) + if test no = "$need_relink" || test yes != "$build_libtool_libs"; then + wrappers_required=false + fi + ;; + esac + $wrappers_required || { + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command=$compile_command$compile_rpath + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.$objext"; then + func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' + fi + + exit $exit_status + } + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + func_append rpath "$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test yes = "$no_install"; then + # We don't need to create a wrapper script. + link_command=$compile_var$compile_command$compile_rpath + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + exit $EXIT_SUCCESS + fi + + case $hardcode_action,$fast_install in + relink,*) + # Fast installation is not supported + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "'$output' will be relinked during installation" + ;; + *,yes) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + ;; + *,no) + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + ;; + *,needless) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command= + ;; + esac + + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource=$output_path/$objdir/lt-$output_name.c + cwrapper=$output_path/$output_name.exe + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host"; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + case $build_libtool_libs in + convenience) + oldobjs="$libobjs_save $symfileobj" + addlibs=$convenience + build_libtool_libs=no + ;; + module) + oldobjs=$libobjs_save + addlibs=$old_convenience + build_libtool_libs=no + ;; + *) + oldobjs="$old_deplibs $non_pic_objects" + $preload && test -f "$symfileobj" \ + && func_append oldobjs " $symfileobj" + addlibs=$old_convenience + ;; + esac + + if test -n "$addlibs"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append oldobjs " $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase=$func_basename_result + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj"; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test -z "$oldobjs"; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test yes = "$build_old_libs" && old_library=$libname.$libext + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + if test yes = "$hardcode_automatic"; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test yes = "$installed"; then + if test -z "$install_libdir"; then + break + fi + output=$output_objdir/${outputname}i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name=$func_basename_result + func_resolve_sysroot "$deplib" + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs=$newdependency_libs + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles=$newdlprefiles + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles=$newdlprefiles + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test -n "$bindir"; then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result/$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test no,yes = "$installed,$need_relink"; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +if test link = "$opt_mode" || test relink = "$opt_mode"; then + func_mode_link ${1+"$@"} +fi + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $debug_cmd + + RM=$nonopt + files= + rmforce=false + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + for arg + do + case $arg in + -f) func_append RM " $arg"; rmforce=: ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir=$func_dirname_result + if test . = "$dir"; then + odir=$objdir + else + odir=$dir/$objdir + fi + func_basename "$file" + name=$func_basename_result + test uninstall = "$opt_mode" && odir=$dir + + # Remember odir for removal later, being careful to avoid duplicates + if test clean = "$opt_mode"; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif $rmforce; then + continue + fi + + rmfiles=$file + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case $opt_mode in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && test none != "$pic_object"; then + func_append rmfiles " $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && test none != "$non_pic_object"; then + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test clean = "$opt_mode"; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.$objext" + if test yes = "$fast_install" && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name" + fi + if test "X$noexename" != "X$name"; then + func_append rmfiles " $odir/lt-$noexename.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the $objdir's in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then + func_mode_uninstall ${1+"$@"} +fi + +test -z "$opt_mode" && { + help=$generic_help + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode '$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# where we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/build-aux/missing b/build-aux/missing new file mode 100755 index 0000000..f62bbae --- /dev/null +++ b/build-aux/missing @@ -0,0 +1,215 @@ +#! /bin/sh +# Common wrapper for a few potentially missing GNU programs. + +scriptversion=2013-10-28.13; # UTC + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Originally written by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program 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 General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try '$0 --help' for more information" + exit 1 +fi + +case $1 in + + --is-lightweight) + # Used by our autoconf macros to check whether the available missing + # script is modern enough. + exit 0 + ;; + + --run) + # Back-compat with the calling convention used by older automake. + shift + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due +to PROGRAM being missing or too old. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal autoconf autoheader autom4te automake makeinfo + bison yacc flex lex help2man + +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" + exit 1 + ;; + +esac + +# Run the given program, remember its exit status. +"$@"; st=$? + +# If it succeeded, we are done. +test $st -eq 0 && exit 0 + +# Also exit now if we it failed (or wasn't found), and '--version' was +# passed; such an option is passed most likely to detect whether the +# program is present and works. +case $2 in --version|--help) exit $st;; esac + +# Exit code 63 means version mismatch. This often happens when the user +# tries to use an ancient version of a tool on a file that requires a +# minimum version. +if test $st -eq 63; then + msg="probably too old" +elif test $st -eq 127; then + # Program was missing. + msg="missing on your system" +else + # Program was found and executed, but failed. Give up. + exit $st +fi + +perl_URL=http://www.perl.org/ +flex_URL=http://flex.sourceforge.net/ +gnu_software_URL=http://www.gnu.org/software + +program_details () +{ + case $1 in + aclocal|automake) + echo "The '$1' program is part of the GNU Automake package:" + echo "<$gnu_software_URL/automake>" + echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/autoconf>" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + autoconf|autom4te|autoheader) + echo "The '$1' program is part of the GNU Autoconf package:" + echo "<$gnu_software_URL/autoconf/>" + echo "It also requires GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + esac +} + +give_advice () +{ + # Normalize program name to check for. + normalized_program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + + printf '%s\n' "'$1' is $msg." + + configure_deps="'configure.ac' or m4 files included by 'configure.ac'" + case $normalized_program in + autoconf*) + echo "You should only need it if you modified 'configure.ac'," + echo "or m4 files included by it." + program_details 'autoconf' + ;; + autoheader*) + echo "You should only need it if you modified 'acconfig.h' or" + echo "$configure_deps." + program_details 'autoheader' + ;; + automake*) + echo "You should only need it if you modified 'Makefile.am' or" + echo "$configure_deps." + program_details 'automake' + ;; + aclocal*) + echo "You should only need it if you modified 'acinclude.m4' or" + echo "$configure_deps." + program_details 'aclocal' + ;; + autom4te*) + echo "You might have modified some maintainer files that require" + echo "the 'autom4te' program to be rebuilt." + program_details 'autom4te' + ;; + bison*|yacc*) + echo "You should only need it if you modified a '.y' file." + echo "You may want to install the GNU Bison package:" + echo "<$gnu_software_URL/bison/>" + ;; + lex*|flex*) + echo "You should only need it if you modified a '.l' file." + echo "You may want to install the Fast Lexical Analyzer package:" + echo "<$flex_URL>" + ;; + help2man*) + echo "You should only need it if you modified a dependency" \ + "of a man page." + echo "You may want to install the GNU Help2man package:" + echo "<$gnu_software_URL/help2man/>" + ;; + makeinfo*) + echo "You should only need it if you modified a '.texi' file, or" + echo "any other file indirectly affecting the aspect of the manual." + echo "You might want to install the Texinfo package:" + echo "<$gnu_software_URL/texinfo/>" + echo "The spurious makeinfo call might also be the consequence of" + echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" + echo "want to install GNU make:" + echo "<$gnu_software_URL/make/>" + ;; + *) + echo "You might have modified some files without having the proper" + echo "tools for further handling them. Check the 'README' file, it" + echo "often tells you about the needed prerequisites for installing" + echo "this package. You may also peek at any GNU archive site, in" + echo "case some other package contains this missing '$1' program." + ;; + esac +} + +give_advice "$1" | sed -e '1s/^/WARNING: /' \ + -e '2,$s/^/ /' >&2 + +# Propagate the correct exit status (expected to be 127 for a program +# not found, 63 for a program that failed due to version mismatch). +exit $st + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/clutter/Makefile.am b/clutter/Makefile.am new file mode 100644 index 0000000..eeaa722 --- /dev/null +++ b/clutter/Makefile.am @@ -0,0 +1,53 @@ +NULL = + +SUBDIRS = build clutter tests + +if BUILD_EXAMPLES +SUBDIRS += examples +endif + +DIST_SUBDIRS = clutter tests examples build + +# XXX - this is a massive hack to make autoreconf honour the ACLOCAL_FLAGS +# that jhbuild sets while still retaining build/autotools as the authoritative +# source for m4 macros +ACLOCAL_AMFLAGS = -I build/autotools ${ACLOCAL_FLAGS} + +CLEANFILES = $(pcfiles) + +DISTCLEANFILES = + +DISTCHECK_CONFIGURE_FLAGS = --enable-maintainer-flags + +# proxy rules for tests +test-report full-report: + $(MAKE) -C tests/conform $(@) + +perf-report: + $(MAKE) -C tests/performance $(@) + +if ENABLE_GCOV +# use recursive makes in order to ignore errors during check/perf +lcov: + -$(MAKE) $(AM_MAKEFLAGS) -C clutter check + -$(MAKE) $(AM_MAKEFLAGS) -C tests/conform test + $(MAKE) $(AM_MAKEFLAGS) genlcov + +# we have to massage the lcov.info file slightly to hide the effect of libtool +# placing the objects files in the .libs/ directory separate from the *.c +genlcov: + $(LTP) --directory $(top_builddir) --capture --output-file clutter-lcov.info --test-name CLUTTER_TEST --no-checksum + $(SED) -e 's#.libs/##' < clutter-lcov.info > clutter-lcov.info.tmp + LANG=C $(LTP_GENHTML) --prefix $(top_builddir) --output-directory clutter-lcov --title "Clutter Code Coverage" --show-details clutter-lcov.info.tmp + rm -f clutter-lcov.info.tmp + +lcov-clean: + -$(LTP) --directory $(top_builddir) -z + -$(RM) -rf clutter-lcov.info clutter-lcov +else +lcov genlcov lcov-clean: + @echo You need to configure Clutter with support for gcov enabled. + @echo e.g., ./configure --enable-gcov +endif + +.PHONY: test-report full-report perf-report lcov genlcov lcov-clean diff --git a/clutter/Makefile.in b/clutter/Makefile.in new file mode 100644 index 0000000..7d0194a --- /dev/null +++ b/clutter/Makefile.in @@ -0,0 +1,912 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@BUILD_EXAMPLES_TRUE@am__append_1 = examples +subdir = . +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/build/autotools/as-compiler-flag.m4 \ + $(top_srcdir)/build/autotools/glibtests.m4 \ + $(top_srcdir)/build/autotools/introspection.m4 \ + $(top_srcdir)/build/autotools/libtool.m4 \ + $(top_srcdir)/build/autotools/ltoptions.m4 \ + $(top_srcdir)/build/autotools/ltsugar.m4 \ + $(top_srcdir)/build/autotools/ltversion.m4 \ + $(top_srcdir)/build/autotools/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(am__DIST_COMMON) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/clutter/clutter-build-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + cscope distdir dist dist-all distcheck +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +CSCOPE = cscope +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/build/compile \ + $(top_srcdir)/build/config.guess \ + $(top_srcdir)/build/config.sub $(top_srcdir)/build/install-sh \ + $(top_srcdir)/build/ltmain.sh $(top_srcdir)/build/missing +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +GZIP_ENV = --best +DIST_ARCHIVES = $(distdir).tar.xz +DIST_TARGETS = dist-xz +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ATK_REQ_VERSION = @ATK_REQ_VERSION@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_REQ_VERSION = @CAIRO_REQ_VERSION@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CLUTTER_API_VERSION = @CLUTTER_API_VERSION@ +CLUTTER_API_VERSION_AM = @CLUTTER_API_VERSION_AM@ +CLUTTER_BACKENDS = @CLUTTER_BACKENDS@ +CLUTTER_CFLAGS = @CLUTTER_CFLAGS@ +CLUTTER_COGL = @CLUTTER_COGL@ +CLUTTER_CONFIG_DEFINES = @CLUTTER_CONFIG_DEFINES@ +CLUTTER_DEBUG_CFLAGS = @CLUTTER_DEBUG_CFLAGS@ +CLUTTER_DEPRECATED_CFLAGS = @CLUTTER_DEPRECATED_CFLAGS@ +CLUTTER_DEPS_CFLAGS = @CLUTTER_DEPS_CFLAGS@ +CLUTTER_DEPS_LIBS = @CLUTTER_DEPS_LIBS@ +CLUTTER_DEPS_PRIVATE_CFLAGS = @CLUTTER_DEPS_PRIVATE_CFLAGS@ +CLUTTER_DEPS_PRIVATE_LIBS = @CLUTTER_DEPS_PRIVATE_LIBS@ +CLUTTER_FLAVOUR = @CLUTTER_FLAVOUR@ +CLUTTER_GCOV_CFLAGS = @CLUTTER_GCOV_CFLAGS@ +CLUTTER_GCOV_LDADD = @CLUTTER_GCOV_LDADD@ +CLUTTER_HIDDEN_VISIBILITY_CFLAGS = @CLUTTER_HIDDEN_VISIBILITY_CFLAGS@ +CLUTTER_INPUT_BACKENDS = @CLUTTER_INPUT_BACKENDS@ +CLUTTER_LIBS = @CLUTTER_LIBS@ +CLUTTER_LINK_FLAGS = @CLUTTER_LINK_FLAGS@ +CLUTTER_LT_CURRENT = @CLUTTER_LT_CURRENT@ +CLUTTER_LT_LDFLAGS = @CLUTTER_LT_LDFLAGS@ +CLUTTER_LT_REVISION = @CLUTTER_LT_REVISION@ +CLUTTER_LT_VERSION = @CLUTTER_LT_VERSION@ +CLUTTER_MAJOR_VERSION = @CLUTTER_MAJOR_VERSION@ +CLUTTER_MICRO_VERSION = @CLUTTER_MICRO_VERSION@ +CLUTTER_MINOR_VERSION = @CLUTTER_MINOR_VERSION@ +CLUTTER_RELEASE_STATUS = @CLUTTER_RELEASE_STATUS@ +CLUTTER_REQUIRES = @CLUTTER_REQUIRES@ +CLUTTER_REQUIRES_PRIVATE = @CLUTTER_REQUIRES_PRIVATE@ +CLUTTER_SONAME_INFIX = @CLUTTER_SONAME_INFIX@ +CLUTTER_STAGE_TYPE = @CLUTTER_STAGE_TYPE@ +CLUTTER_VERSION = @CLUTTER_VERSION@ +CLUTTER_WINSYS = @CLUTTER_WINSYS@ +CLUTTER_WINSYS_BASE = @CLUTTER_WINSYS_BASE@ +COGL_DRIVER = @COGL_DRIVER@ +COGL_REQ_VERSION = @COGL_REQ_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@ +GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@ +GDK_REQ_VERSION = @GDK_REQ_VERSION@ +GI_REQ_VERSION = @GI_REQ_VERSION@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQ_VERSION = @GLIB_REQ_VERSION@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +JSON_GLIB_REQ_VERSION = @JSON_GLIB_REQ_VERSION@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBINPUT_REQ_VERSION = @LIBINPUT_REQ_VERSION@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUDEV_REQ_VERSION = @LIBUDEV_REQ_VERSION@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTP = @LTP@ +LTP_GENHTML = @LTP_GENHTML@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINTAINER_CFLAGS = @MAINTAINER_CFLAGS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGO_REQ_VERSION = @PANGO_REQ_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SHTOOL = @SHTOOL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +XCOMPOSITE_REQ_VERSION = @XCOMPOSITE_REQ_VERSION@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +installed_test_metadir = @installed_test_metadir@ +installed_testdir = @installed_testdir@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = +SUBDIRS = build clutter tests $(am__append_1) +DIST_SUBDIRS = clutter tests examples build + +# XXX - this is a massive hack to make autoreconf honour the ACLOCAL_FLAGS +# that jhbuild sets while still retaining build/autotools as the authoritative +# source for m4 macros +ACLOCAL_AMFLAGS = -I build/autotools ${ACLOCAL_FLAGS} +CLEANFILES = $(pcfiles) +DISTCLEANFILES = +DISTCHECK_CONFIGURE_FLAGS = --enable-maintainer-flags +all: all-recursive + +.SUFFIXES: +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) +clean-cscope: + -rm -f cscope.files +cscope.files: clean-cscope cscopelist +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz + $(am__post_remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__post_remove_distdir) + +dist-tarZ: distdir + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__post_remove_distdir) + +dist-shar: distdir + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz + $(am__post_remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__post_remove_distdir) + +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + --srcdir=../.. --prefix="$$dc_install_base" \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__post_remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-libtool \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--refresh check check-am clean clean-cscope clean-generic \ + clean-libtool cscope cscopelist-am ctags ctags-am dist \ + dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ + dist-xz dist-zip distcheck distclean distclean-generic \ + distclean-libtool distclean-tags distcleancheck distdir \ + distuninstallcheck dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# proxy rules for tests +test-report full-report: + $(MAKE) -C tests/conform $(@) + +perf-report: + $(MAKE) -C tests/performance $(@) + +# use recursive makes in order to ignore errors during check/perf +@ENABLE_GCOV_TRUE@lcov: +@ENABLE_GCOV_TRUE@ -$(MAKE) $(AM_MAKEFLAGS) -C clutter check +@ENABLE_GCOV_TRUE@ -$(MAKE) $(AM_MAKEFLAGS) -C tests/conform test +@ENABLE_GCOV_TRUE@ $(MAKE) $(AM_MAKEFLAGS) genlcov + +# we have to massage the lcov.info file slightly to hide the effect of libtool +# placing the objects files in the .libs/ directory separate from the *.c +@ENABLE_GCOV_TRUE@genlcov: +@ENABLE_GCOV_TRUE@ $(LTP) --directory $(top_builddir) --capture --output-file clutter-lcov.info --test-name CLUTTER_TEST --no-checksum +@ENABLE_GCOV_TRUE@ $(SED) -e 's#.libs/##' < clutter-lcov.info > clutter-lcov.info.tmp +@ENABLE_GCOV_TRUE@ LANG=C $(LTP_GENHTML) --prefix $(top_builddir) --output-directory clutter-lcov --title "Clutter Code Coverage" --show-details clutter-lcov.info.tmp +@ENABLE_GCOV_TRUE@ rm -f clutter-lcov.info.tmp + +@ENABLE_GCOV_TRUE@lcov-clean: +@ENABLE_GCOV_TRUE@ -$(LTP) --directory $(top_builddir) -z +@ENABLE_GCOV_TRUE@ -$(RM) -rf clutter-lcov.info clutter-lcov +@ENABLE_GCOV_FALSE@lcov genlcov lcov-clean: +@ENABLE_GCOV_FALSE@ @echo You need to configure Clutter with support for gcov enabled. +@ENABLE_GCOV_FALSE@ @echo e.g., ./configure --enable-gcov + +.PHONY: test-report full-report perf-report lcov genlcov lcov-clean + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/clutter/aclocal.m4 b/clutter/aclocal.m4 new file mode 100644 index 0000000..bc679a0 --- /dev/null +++ b/clutter/aclocal.m4 @@ -0,0 +1,1648 @@ +# generated automatically by aclocal 1.15 -*- Autoconf -*- + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. + +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, +[m4_warning([this file was generated for autoconf 2.69. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically 'autoreconf'.])]) + +dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +dnl serial 11 (pkg-config-0.29.1) +dnl +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29.1]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])dnl PKG_PROG_PKG_CONFIG + +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])dnl _PKG_CONFIG + +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])dnl _PKG_SHORT_ERRORS_SUPPORTED + + +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR + +# Configure paths for GLIB +# Owen Taylor 1997-2001 + +dnl AM_PATH_GLIB_2_0([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]]) +dnl Test for GLIB, and define GLIB_CFLAGS and GLIB_LIBS, if gmodule, gobject, +dnl gthread, or gio is specified in MODULES, pass to pkg-config +dnl +AC_DEFUN([AM_PATH_GLIB_2_0], +[dnl +dnl Get the cflags and libraries from pkg-config +dnl +AC_ARG_ENABLE(glibtest, [ --disable-glibtest do not try to compile and run a test GLIB program], + , enable_glibtest=yes) + + pkg_config_args=glib-2.0 + for module in . $4 + do + case "$module" in + gmodule) + pkg_config_args="$pkg_config_args gmodule-2.0" + ;; + gmodule-no-export) + pkg_config_args="$pkg_config_args gmodule-no-export-2.0" + ;; + gobject) + pkg_config_args="$pkg_config_args gobject-2.0" + ;; + gthread) + pkg_config_args="$pkg_config_args gthread-2.0" + ;; + gio*) + pkg_config_args="$pkg_config_args $module-2.0" + ;; + esac + done + + PKG_PROG_PKG_CONFIG([0.16]) + + no_glib="" + + if test "x$PKG_CONFIG" = x ; then + no_glib=yes + PKG_CONFIG=no + fi + + min_glib_version=ifelse([$1], ,2.0.0,$1) + AC_MSG_CHECKING(for GLIB - version >= $min_glib_version) + + if test x$PKG_CONFIG != xno ; then + ## don't try to run the test against uninstalled libtool libs + if $PKG_CONFIG --uninstalled $pkg_config_args; then + echo "Will use uninstalled version of GLib found in PKG_CONFIG_PATH" + enable_glibtest=no + fi + + if $PKG_CONFIG --atleast-version $min_glib_version $pkg_config_args; then + : + else + no_glib=yes + fi + fi + + if test x"$no_glib" = x ; then + GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0` + GOBJECT_QUERY=`$PKG_CONFIG --variable=gobject_query glib-2.0` + GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0` + GLIB_COMPILE_RESOURCES=`$PKG_CONFIG --variable=glib_compile_resources gio-2.0` + + GLIB_CFLAGS=`$PKG_CONFIG --cflags $pkg_config_args` + GLIB_LIBS=`$PKG_CONFIG --libs $pkg_config_args` + glib_config_major_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + glib_config_minor_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + glib_config_micro_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + if test "x$enable_glibtest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GLIB_CFLAGS" + LIBS="$GLIB_LIBS $LIBS" +dnl +dnl Now check if the installed GLIB is sufficiently new. (Also sanity +dnl checks the results of pkg-config to some extent) +dnl + rm -f conf.glibtest + AC_TRY_RUN([ +#include +#include +#include + +int +main () +{ + unsigned int major, minor, micro; + + fclose (fopen ("conf.glibtest", "w")); + + if (sscanf("$min_glib_version", "%u.%u.%u", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_glib_version"); + exit(1); + } + + if ((glib_major_version != $glib_config_major_version) || + (glib_minor_version != $glib_config_minor_version) || + (glib_micro_version != $glib_config_micro_version)) + { + printf("\n*** 'pkg-config --modversion glib-2.0' returned %d.%d.%d, but GLIB (%d.%d.%d)\n", + $glib_config_major_version, $glib_config_minor_version, $glib_config_micro_version, + glib_major_version, glib_minor_version, glib_micro_version); + printf ("*** was found! If pkg-config was correct, then it is best\n"); + printf ("*** to remove the old version of GLib. You may also be able to fix the error\n"); + printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); + printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); + printf("*** required on your system.\n"); + printf("*** If pkg-config was wrong, set the environment variable PKG_CONFIG_PATH\n"); + printf("*** to point to the correct configuration files\n"); + } + else if ((glib_major_version != GLIB_MAJOR_VERSION) || + (glib_minor_version != GLIB_MINOR_VERSION) || + (glib_micro_version != GLIB_MICRO_VERSION)) + { + printf("*** GLIB header files (version %d.%d.%d) do not match\n", + GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION); + printf("*** library (version %d.%d.%d)\n", + glib_major_version, glib_minor_version, glib_micro_version); + } + else + { + if ((glib_major_version > major) || + ((glib_major_version == major) && (glib_minor_version > minor)) || + ((glib_major_version == major) && (glib_minor_version == minor) && (glib_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** An old version of GLIB (%u.%u.%u) was found.\n", + glib_major_version, glib_minor_version, glib_micro_version); + printf("*** You need a version of GLIB newer than %u.%u.%u. The latest version of\n", + major, minor, micro); + printf("*** GLIB is always available from ftp://ftp.gtk.org.\n"); + printf("***\n"); + printf("*** If you have already installed a sufficiently new version, this error\n"); + printf("*** probably means that the wrong copy of the pkg-config shell script is\n"); + printf("*** being found. The easiest way to fix this is to remove the old version\n"); + printf("*** of GLIB, but you can also set the PKG_CONFIG environment to point to the\n"); + printf("*** correct copy of pkg-config. (In this case, you will have to\n"); + printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); + printf("*** so that the correct libraries are found at run-time))\n"); + } + } + return 1; +} +],, no_glib=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_glib" = x ; then + AC_MSG_RESULT(yes (version $glib_config_major_version.$glib_config_minor_version.$glib_config_micro_version)) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$PKG_CONFIG" = "no" ; then + echo "*** A new enough version of pkg-config was not found." + echo "*** See http://www.freedesktop.org/software/pkgconfig/" + else + if test -f conf.glibtest ; then + : + else + echo "*** Could not run GLIB test program, checking why..." + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GLIB_CFLAGS" + LIBS="$LIBS $GLIB_LIBS" + AC_TRY_LINK([ +#include +#include +], [ return ((glib_major_version) || (glib_minor_version) || (glib_micro_version)); ], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding GLIB or finding the wrong" + echo "*** version of GLIB. If it is not finding GLIB, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means GLIB is incorrectly installed."]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + GLIB_CFLAGS="" + GLIB_LIBS="" + GLIB_GENMARSHAL="" + GOBJECT_QUERY="" + GLIB_MKENUMS="" + GLIB_COMPILE_RESOURCES="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(GLIB_CFLAGS) + AC_SUBST(GLIB_LIBS) + AC_SUBST(GLIB_GENMARSHAL) + AC_SUBST(GOBJECT_QUERY) + AC_SUBST(GLIB_MKENUMS) + AC_SUBST(GLIB_COMPILE_RESOURCES) + rm -f conf.glibtest +]) + +# Copyright (C) 2002-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.15' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.15], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.15])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to +# '$srcdir', '$srcdir/..', or '$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is '.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ([2.52])dnl + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], + [$1], [CXX], [depcc="$CXX" am_compiler_list=], + [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], + [$1], [UPC], [depcc="$UPC" am_compiler_list=], + [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES. +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE([dependency-tracking], [dnl +AS_HELP_STRING( + [--enable-dependency-tracking], + [do not reject slow dependency extractors]) +AS_HELP_STRING( + [--disable-dependency-tracking], + [speeds up one-time build])]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "$am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each '.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. +m4_define([AC_PROG_CC], +m4_defn([AC_PROG_CC]) +[_AM_PROG_CC_C_O +]) + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.65])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[AC_DIAGNOSE([obsolete], + [$0: two- and three-arguments forms are deprecated.]) +m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if( + m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), + [ok:ok],, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) + AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) +AM_MISSING_PROG([AUTOCONF], [autoconf]) +AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) +AM_MISSING_PROG([AUTOHEADER], [autoheader]) +AM_MISSING_PROG([MAKEINFO], [makeinfo]) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +AC_SUBST([mkdir_p], ['$(MKDIR_P)']) +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES([CC])], + [m4_define([AC_PROG_CC], + m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES([CXX])], + [m4_define([AC_PROG_CXX], + m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES([OBJC])], + [m4_define([AC_PROG_OBJC], + m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], + [_AM_DEPENDENCIES([OBJCXX])], + [m4_define([AC_PROG_OBJCXX], + m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl +]) +AC_REQUIRE([AM_SILENT_RULES])dnl +dnl The testsuite driver may need to know about EXEEXT, so add the +dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This +dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) + fi +fi +dnl The trailing newline in this macro's definition is deliberate, for +dnl backward compatibility and to allow trailing 'dnl'-style comments +dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. +]) + +dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST([install_sh])]) + +# Copyright (C) 2003-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it is modern enough. +# If it is, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + AC_MSG_WARN(['missing' script is too old or missing]) +fi +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_CC_C_O +# --------------- +# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC +# to automatically call this. +AC_DEFUN([_AM_PROG_CC_C_O], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +AC_LANG_PUSH([C])dnl +AC_CACHE_CHECK( + [whether $CC understands -c and -o together], + [am_cv_prog_cc_c_o], + [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i]) +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +AC_LANG_POP([C])]) + +# For backward compatibility. +AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_RUN_LOG(COMMAND) +# ------------------- +# Run COMMAND, save the exit status in ac_status, and log it. +# (This has been adapted from Autoconf's _AC_RUN_LOG macro.) +AC_DEFUN([AM_RUN_LOG], +[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD + ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + (exit $ac_status); }]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken + alias in your environment]) + fi + if test "$[2]" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT([yes]) +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi +AC_CONFIG_COMMANDS_PRE( + [AC_MSG_CHECKING([that generated files are newer than configure]) + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + AC_MSG_RESULT([done])]) +rm -f conftest.file +]) + +# Copyright (C) 2009-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SILENT_RULES([DEFAULT]) +# -------------------------- +# Enable less verbose build rules; with the default set to DEFAULT +# ("yes" being less verbose, "no" or empty being verbose). +AC_DEFUN([AM_SILENT_RULES], +[AC_ARG_ENABLE([silent-rules], [dnl +AS_HELP_STRING( + [--enable-silent-rules], + [less verbose build output (undo: "make V=1")]) +AS_HELP_STRING( + [--disable-silent-rules], + [verbose build output (undo: "make V=0")])dnl +]) +case $enable_silent_rules in @%:@ ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; +esac +dnl +dnl A few 'make' implementations (e.g., NonStop OS and NextStep) +dnl do not support nested variable expansions. +dnl See automake bug#9928 and bug#10237. +am_make=${MAKE-make} +AC_CACHE_CHECK([whether $am_make supports nested variables], + [am_cv_make_support_nested_variables], + [if AS_ECHO([['TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi]) +if test $am_cv_make_support_nested_variables = yes; then + dnl Using '$V' instead of '$(V)' breaks IRIX make. + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AC_SUBST([AM_V])dnl +AM_SUBST_NOTMAKE([AM_V])dnl +AC_SUBST([AM_DEFAULT_V])dnl +AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl +AC_SUBST([AM_DEFAULT_VERBOSITY])dnl +AM_BACKSLASH='\' +AC_SUBST([AM_BACKSLASH])dnl +_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl +]) + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor 'install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in "make install-strip", and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of 'v7', 'ustar', or 'pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +# +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' + +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + + [m4_case([$1], + [ustar], + [# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) + if test $am_uid -le $am_max_uid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi + AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) + if test $am_gid -le $am_max_gid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi], + + [pax], + [], + + [m4_fatal([Unknown tar format])]) + + AC_MSG_CHECKING([how to create a $1 tar archive]) + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_$1-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi + done + rm -rf conftest.dir + + AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) + AC_MSG_RESULT([$am_cv_prog_tar_$1])]) + +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +m4_include([build/autotools/as-compiler-flag.m4]) +m4_include([build/autotools/glibtests.m4]) +m4_include([build/autotools/introspection.m4]) +m4_include([build/autotools/libtool.m4]) +m4_include([build/autotools/ltoptions.m4]) +m4_include([build/autotools/ltsugar.m4]) +m4_include([build/autotools/ltversion.m4]) +m4_include([build/autotools/lt~obsolete.m4]) diff --git a/clutter/build/Makefile.am b/clutter/build/Makefile.am new file mode 100644 index 0000000..8c90237 --- /dev/null +++ b/clutter/build/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = autotools diff --git a/clutter/build/Makefile.in b/clutter/build/Makefile.in new file mode 100644 index 0000000..4dc619a --- /dev/null +++ b/clutter/build/Makefile.in @@ -0,0 +1,695 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = build +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/build/autotools/as-compiler-flag.m4 \ + $(top_srcdir)/build/autotools/glibtests.m4 \ + $(top_srcdir)/build/autotools/introspection.m4 \ + $(top_srcdir)/build/autotools/libtool.m4 \ + $(top_srcdir)/build/autotools/ltoptions.m4 \ + $(top_srcdir)/build/autotools/ltsugar.m4 \ + $(top_srcdir)/build/autotools/ltversion.m4 \ + $(top_srcdir)/build/autotools/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/clutter/clutter-build-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in compile config.guess \ + config.sub install-sh ltmain.sh missing +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ATK_REQ_VERSION = @ATK_REQ_VERSION@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_REQ_VERSION = @CAIRO_REQ_VERSION@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CLUTTER_API_VERSION = @CLUTTER_API_VERSION@ +CLUTTER_API_VERSION_AM = @CLUTTER_API_VERSION_AM@ +CLUTTER_BACKENDS = @CLUTTER_BACKENDS@ +CLUTTER_CFLAGS = @CLUTTER_CFLAGS@ +CLUTTER_COGL = @CLUTTER_COGL@ +CLUTTER_CONFIG_DEFINES = @CLUTTER_CONFIG_DEFINES@ +CLUTTER_DEBUG_CFLAGS = @CLUTTER_DEBUG_CFLAGS@ +CLUTTER_DEPRECATED_CFLAGS = @CLUTTER_DEPRECATED_CFLAGS@ +CLUTTER_DEPS_CFLAGS = @CLUTTER_DEPS_CFLAGS@ +CLUTTER_DEPS_LIBS = @CLUTTER_DEPS_LIBS@ +CLUTTER_DEPS_PRIVATE_CFLAGS = @CLUTTER_DEPS_PRIVATE_CFLAGS@ +CLUTTER_DEPS_PRIVATE_LIBS = @CLUTTER_DEPS_PRIVATE_LIBS@ +CLUTTER_FLAVOUR = @CLUTTER_FLAVOUR@ +CLUTTER_GCOV_CFLAGS = @CLUTTER_GCOV_CFLAGS@ +CLUTTER_GCOV_LDADD = @CLUTTER_GCOV_LDADD@ +CLUTTER_HIDDEN_VISIBILITY_CFLAGS = @CLUTTER_HIDDEN_VISIBILITY_CFLAGS@ +CLUTTER_INPUT_BACKENDS = @CLUTTER_INPUT_BACKENDS@ +CLUTTER_LIBS = @CLUTTER_LIBS@ +CLUTTER_LINK_FLAGS = @CLUTTER_LINK_FLAGS@ +CLUTTER_LT_CURRENT = @CLUTTER_LT_CURRENT@ +CLUTTER_LT_LDFLAGS = @CLUTTER_LT_LDFLAGS@ +CLUTTER_LT_REVISION = @CLUTTER_LT_REVISION@ +CLUTTER_LT_VERSION = @CLUTTER_LT_VERSION@ +CLUTTER_MAJOR_VERSION = @CLUTTER_MAJOR_VERSION@ +CLUTTER_MICRO_VERSION = @CLUTTER_MICRO_VERSION@ +CLUTTER_MINOR_VERSION = @CLUTTER_MINOR_VERSION@ +CLUTTER_RELEASE_STATUS = @CLUTTER_RELEASE_STATUS@ +CLUTTER_REQUIRES = @CLUTTER_REQUIRES@ +CLUTTER_REQUIRES_PRIVATE = @CLUTTER_REQUIRES_PRIVATE@ +CLUTTER_SONAME_INFIX = @CLUTTER_SONAME_INFIX@ +CLUTTER_STAGE_TYPE = @CLUTTER_STAGE_TYPE@ +CLUTTER_VERSION = @CLUTTER_VERSION@ +CLUTTER_WINSYS = @CLUTTER_WINSYS@ +CLUTTER_WINSYS_BASE = @CLUTTER_WINSYS_BASE@ +COGL_DRIVER = @COGL_DRIVER@ +COGL_REQ_VERSION = @COGL_REQ_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@ +GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@ +GDK_REQ_VERSION = @GDK_REQ_VERSION@ +GI_REQ_VERSION = @GI_REQ_VERSION@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQ_VERSION = @GLIB_REQ_VERSION@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +JSON_GLIB_REQ_VERSION = @JSON_GLIB_REQ_VERSION@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBINPUT_REQ_VERSION = @LIBINPUT_REQ_VERSION@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUDEV_REQ_VERSION = @LIBUDEV_REQ_VERSION@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTP = @LTP@ +LTP_GENHTML = @LTP_GENHTML@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINTAINER_CFLAGS = @MAINTAINER_CFLAGS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGO_REQ_VERSION = @PANGO_REQ_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SHTOOL = @SHTOOL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +XCOMPOSITE_REQ_VERSION = @XCOMPOSITE_REQ_VERSION@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +installed_test_metadir = @installed_test_metadir@ +installed_testdir = @installed_testdir@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = autotools +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign build/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign build/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/clutter/build/autotools/Makefile.am b/clutter/build/autotools/Makefile.am new file mode 100644 index 0000000..0a74d82 --- /dev/null +++ b/clutter/build/autotools/Makefile.am @@ -0,0 +1,10 @@ +NULL = + +EXTRA_DIST = \ + introspection.m4 \ + as-compiler-flag.m4 \ + glibtests.m4 \ + glib-tap.mk \ + tap-driver.sh \ + tap-test \ + $(NULL) diff --git a/clutter/build/autotools/Makefile.in b/clutter/build/autotools/Makefile.in new file mode 100644 index 0000000..7d4c292 --- /dev/null +++ b/clutter/build/autotools/Makefile.in @@ -0,0 +1,523 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = build/autotools +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/build/autotools/as-compiler-flag.m4 \ + $(top_srcdir)/build/autotools/glibtests.m4 \ + $(top_srcdir)/build/autotools/introspection.m4 \ + $(top_srcdir)/build/autotools/libtool.m4 \ + $(top_srcdir)/build/autotools/ltoptions.m4 \ + $(top_srcdir)/build/autotools/ltsugar.m4 \ + $(top_srcdir)/build/autotools/ltversion.m4 \ + $(top_srcdir)/build/autotools/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/clutter/clutter-build-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ATK_REQ_VERSION = @ATK_REQ_VERSION@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_REQ_VERSION = @CAIRO_REQ_VERSION@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CLUTTER_API_VERSION = @CLUTTER_API_VERSION@ +CLUTTER_API_VERSION_AM = @CLUTTER_API_VERSION_AM@ +CLUTTER_BACKENDS = @CLUTTER_BACKENDS@ +CLUTTER_CFLAGS = @CLUTTER_CFLAGS@ +CLUTTER_COGL = @CLUTTER_COGL@ +CLUTTER_CONFIG_DEFINES = @CLUTTER_CONFIG_DEFINES@ +CLUTTER_DEBUG_CFLAGS = @CLUTTER_DEBUG_CFLAGS@ +CLUTTER_DEPRECATED_CFLAGS = @CLUTTER_DEPRECATED_CFLAGS@ +CLUTTER_DEPS_CFLAGS = @CLUTTER_DEPS_CFLAGS@ +CLUTTER_DEPS_LIBS = @CLUTTER_DEPS_LIBS@ +CLUTTER_DEPS_PRIVATE_CFLAGS = @CLUTTER_DEPS_PRIVATE_CFLAGS@ +CLUTTER_DEPS_PRIVATE_LIBS = @CLUTTER_DEPS_PRIVATE_LIBS@ +CLUTTER_FLAVOUR = @CLUTTER_FLAVOUR@ +CLUTTER_GCOV_CFLAGS = @CLUTTER_GCOV_CFLAGS@ +CLUTTER_GCOV_LDADD = @CLUTTER_GCOV_LDADD@ +CLUTTER_HIDDEN_VISIBILITY_CFLAGS = @CLUTTER_HIDDEN_VISIBILITY_CFLAGS@ +CLUTTER_INPUT_BACKENDS = @CLUTTER_INPUT_BACKENDS@ +CLUTTER_LIBS = @CLUTTER_LIBS@ +CLUTTER_LINK_FLAGS = @CLUTTER_LINK_FLAGS@ +CLUTTER_LT_CURRENT = @CLUTTER_LT_CURRENT@ +CLUTTER_LT_LDFLAGS = @CLUTTER_LT_LDFLAGS@ +CLUTTER_LT_REVISION = @CLUTTER_LT_REVISION@ +CLUTTER_LT_VERSION = @CLUTTER_LT_VERSION@ +CLUTTER_MAJOR_VERSION = @CLUTTER_MAJOR_VERSION@ +CLUTTER_MICRO_VERSION = @CLUTTER_MICRO_VERSION@ +CLUTTER_MINOR_VERSION = @CLUTTER_MINOR_VERSION@ +CLUTTER_RELEASE_STATUS = @CLUTTER_RELEASE_STATUS@ +CLUTTER_REQUIRES = @CLUTTER_REQUIRES@ +CLUTTER_REQUIRES_PRIVATE = @CLUTTER_REQUIRES_PRIVATE@ +CLUTTER_SONAME_INFIX = @CLUTTER_SONAME_INFIX@ +CLUTTER_STAGE_TYPE = @CLUTTER_STAGE_TYPE@ +CLUTTER_VERSION = @CLUTTER_VERSION@ +CLUTTER_WINSYS = @CLUTTER_WINSYS@ +CLUTTER_WINSYS_BASE = @CLUTTER_WINSYS_BASE@ +COGL_DRIVER = @COGL_DRIVER@ +COGL_REQ_VERSION = @COGL_REQ_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@ +GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@ +GDK_REQ_VERSION = @GDK_REQ_VERSION@ +GI_REQ_VERSION = @GI_REQ_VERSION@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQ_VERSION = @GLIB_REQ_VERSION@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +JSON_GLIB_REQ_VERSION = @JSON_GLIB_REQ_VERSION@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBINPUT_REQ_VERSION = @LIBINPUT_REQ_VERSION@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUDEV_REQ_VERSION = @LIBUDEV_REQ_VERSION@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTP = @LTP@ +LTP_GENHTML = @LTP_GENHTML@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINTAINER_CFLAGS = @MAINTAINER_CFLAGS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGO_REQ_VERSION = @PANGO_REQ_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SHTOOL = @SHTOOL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +XCOMPOSITE_REQ_VERSION = @XCOMPOSITE_REQ_VERSION@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +installed_test_metadir = @installed_test_metadir@ +installed_testdir = @installed_testdir@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = +EXTRA_DIST = \ + introspection.m4 \ + as-compiler-flag.m4 \ + glibtests.m4 \ + glib-tap.mk \ + tap-driver.sh \ + tap-test \ + $(NULL) + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign build/autotools/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign build/autotools/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/clutter/build/autotools/as-compiler-flag.m4 b/clutter/build/autotools/as-compiler-flag.m4 new file mode 100644 index 0000000..0f660cf --- /dev/null +++ b/clutter/build/autotools/as-compiler-flag.m4 @@ -0,0 +1,62 @@ +dnl as-compiler-flag.m4 0.1.0 + +dnl autostars m4 macro for detection of compiler flags + +dnl David Schleef + +dnl $Id: as-compiler-flag.m4,v 1.1 2005/12/15 23:35:19 ds Exp $ + +dnl AS_COMPILER_FLAG(CFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED]) +dnl Tries to compile with the given CFLAGS. +dnl Runs ACTION-IF-ACCEPTED if the compiler can compile with the flags, +dnl and ACTION-IF-NOT-ACCEPTED otherwise. + +AC_DEFUN([AS_COMPILER_FLAG], +[ + AC_MSG_CHECKING([to see if compiler understands $1]) + + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $1" + + AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no]) + CFLAGS="$save_CFLAGS" + + if test "X$flag_ok" = Xyes ; then + m4_ifvaln([$2],[$2]) + true + else + m4_ifvaln([$3],[$3]) + true + fi + AC_MSG_RESULT([$flag_ok]) +]) + +dnl AS_COMPILER_FLAGS(VAR, FLAGS) +dnl Tries to compile with the given CFLAGS. + +AC_DEFUN([AS_COMPILER_FLAGS], +[ + list=$2 + flags_supported="" + flags_unsupported="" + AC_MSG_CHECKING([for supported compiler flags]) + for each in $list + do + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $each" + AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no]) + CFLAGS="$save_CFLAGS" + + if test "X$flag_ok" = Xyes ; then + flags_supported="$flags_supported $each" + else + flags_unsupported="$flags_unsupported $each" + fi + done + AC_MSG_RESULT([$flags_supported]) + if test "X$flags_unsupported" != X ; then + AC_MSG_WARN([unsupported compiler flags: $flags_unsupported]) + fi + $1="$$1 $flags_supported" +]) + diff --git a/clutter/build/autotools/glib-tap.mk b/clutter/build/autotools/glib-tap.mk new file mode 100644 index 0000000..7c5f82b --- /dev/null +++ b/clutter/build/autotools/glib-tap.mk @@ -0,0 +1,134 @@ +# GLIB - Library of useful C routines + +TESTS_ENVIRONMENT= \ + G_TEST_SRCDIR="$(abs_srcdir)" \ + G_TEST_BUILDDIR="$(abs_builddir)" \ + G_DEBUG=gc-friendly \ + MALLOC_CHECK_=2 \ + MALLOC_PERTURB_=$$(($${RANDOM:-256} % 256)) +LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) $(top_srcdir)/build/autotools/tap-driver.sh +LOG_COMPILER = $(top_srcdir)/build/autotools/tap-test + +NULL = + +# initialize variables for unconditional += appending +BUILT_SOURCES = +BUILT_EXTRA_DIST = +CLEANFILES = *.log *.trs +DISTCLEANFILES = +MAINTAINERCLEANFILES = +EXTRA_DIST = +TESTS = + +installed_test_LTLIBRARIES = +installed_test_PROGRAMS = +installed_test_SCRIPTS = +nobase_installed_test_DATA = + +noinst_LTLIBRARIES = +noinst_PROGRAMS = +noinst_SCRIPTS = +noinst_DATA = + +check_LTLIBRARIES = +check_PROGRAMS = +check_SCRIPTS = +check_DATA = + +# We support a fairly large range of possible variables. It is expected that all types of files in a test suite +# will belong in exactly one of the following variables. +# +# First, we support the usual automake suffixes, but in lowercase, with the customary meaning: +# +# test_programs, test_scripts, test_data, test_ltlibraries +# +# The above are used to list files that are involved in both uninstalled and installed testing. The +# test_programs and test_scripts are taken to be actual testcases and will be run as part of the test suite. +# Note that _data is always used with the nobase_ automake variable name to ensure that installed test data is +# installed in the same way as it appears in the package layout. +# +# In order to mark a particular file as being only for one type of testing, use 'installed' or 'uninstalled', +# like so: +# +# installed_test_programs, uninstalled_test_programs +# installed_test_scripts, uninstalled_test_scripts +# installed_test_data, uninstalled_test_data +# installed_test_ltlibraries, uninstalled_test_ltlibraries +# +# Additionally, we support 'extra' infixes for programs and scripts. This is used for support programs/scripts +# that should not themselves be run as testcases (but exist to be used from other testcases): +# +# test_extra_programs, installed_test_extra_programs, uninstalled_test_extra_programs +# test_extra_scripts, installed_test_extra_scripts, uninstalled_test_extra_scripts +# +# Additionally, for _scripts and _data, we support the customary dist_ prefix so that the named script or data +# file automatically end up in the tarball. +# +# dist_test_scripts, dist_test_data, dist_test_extra_scripts +# dist_installed_test_scripts, dist_installed_test_data, dist_installed_test_extra_scripts +# dist_uninstalled_test_scripts, dist_uninstalled_test_data, dist_uninstalled_test_extra_scripts +# +# Note that no file is automatically disted unless it appears in one of the dist_ variables. This follows the +# standard automake convention of not disting programs scripts or data by default. +# +# test_programs, test_scripts, uninstalled_test_programs and uninstalled_test_scripts (as well as their disted +# variants) will be run as part of the in-tree 'make check'. These are all assumed to be runnable under +# gtester. That's a bit strange for scripts, but it's possible. + +TESTS += $(test_programs) $(test_scripts) $(uninstalled_test_programs) $(uninstalled_test_scripts) \ + $(dist_test_scripts) $(dist_uninstalled_test_scripts) + +# Note: build even the installed-only targets during 'make check' to ensure that they still work. +# We need to do a bit of trickery here and manage disting via EXTRA_DIST instead of using dist_ prefixes to +# prevent automake from mistreating gmake functions like $(wildcard ...) and $(addprefix ...) as if they were +# filenames, including removing duplicate instances of the opening part before the space, eg. '$(addprefix'. +all_test_programs = $(test_programs) $(uninstalled_test_programs) $(installed_test_programs) \ + $(test_extra_programs) $(uninstalled_test_extra_programs) $(installed_test_extra_programs) +all_test_scripts = $(test_scripts) $(uninstalled_test_scripts) $(installed_test_scripts) \ + $(test_extra_scripts) $(uninstalled_test_extra_scripts) $(installed_test_extra_scripts) +all_dist_test_scripts = $(dist_test_scripts) $(dist_uninstalled_test_scripts) $(dist_installed_test_scripts) \ + $(dist_test_extra_scripts) $(dist_uninstalled_test_extra_scripts) $(dist_installed_test_extra_scripts) +all_test_scripts += $(all_dist_test_scripts) +EXTRA_DIST += $(all_dist_test_scripts) +all_test_data = $(test_data) $(uninstalled_test_data) $(installed_test_data) +all_dist_test_data = $(dist_test_data) $(dist_uninstalled_test_data) $(dist_installed_test_data) +all_test_data += $(all_dist_test_data) +EXTRA_DIST += $(all_dist_test_data) +all_test_ltlibs = $(test_ltlibraries) $(uninstalled_test_ltlibraries) $(installed_test_ltlibraries) + +if ENABLE_ALWAYS_BUILD_TESTS +noinst_LTLIBRARIES += $(all_test_ltlibs) +noinst_PROGRAMS += $(all_test_programs) +noinst_SCRIPTS += $(all_test_scripts) +noinst_DATA += $(all_test_data) +else +check_LTLIBRARIES += $(all_test_ltlibs) +check_PROGRAMS += $(all_test_programs) +check_SCRIPTS += $(all_test_scripts) +check_DATA += $(all_test_data) +endif + +if ENABLE_INSTALLED_TESTS +installed_test_PROGRAMS += $(test_programs) $(installed_test_programs) \ + $(test_extra_programs) $(installed_test_extra_programs) +installed_test_SCRIPTS += $(test_scripts) $(installed_test_scripts) \ + $(test_extra_scripts) $(test_installed_extra_scripts) +installed_test_SCRIPTS += $(dist_test_scripts) $(dist_test_extra_scripts) \ + $(dist_installed_test_scripts) $(dist_installed_test_extra_scripts) +nobase_installed_test_DATA += $(test_data) $(installed_test_data) +nobase_installed_test_DATA += $(dist_test_data) $(dist_installed_test_data) +installed_test_LTLIBRARIES += $(test_ltlibraries) $(installed_test_ltlibraries) +installed_testcases = $(test_programs) $(installed_test_programs) \ + $(test_scripts) $(installed_test_scripts) \ + $(dist_test_scripts) $(dist_installed_test_scripts) + +installed_test_meta_DATA = $(installed_testcases:=.test) + +%.test: %$(EXEEXT) Makefile + $(AM_V_GEN) (echo '[Test]' > $@.tmp; \ + echo 'Type=session' >> $@.tmp; \ + echo 'Exec=env G_ENABLE_DIAGNOSTIC=0 CLUTTER_ENABLE_DIAGNOSTIC=0 $(installed_testdir)/$<' >> $@.tmp; \ + mv $@.tmp $@) + +CLEANFILES += $(installed_test_meta_DATA) +endif diff --git a/clutter/build/autotools/glibtests.m4 b/clutter/build/autotools/glibtests.m4 new file mode 100644 index 0000000..7d5920a --- /dev/null +++ b/clutter/build/autotools/glibtests.m4 @@ -0,0 +1,28 @@ +dnl GLIB_TESTS +dnl + +AC_DEFUN([GLIB_TESTS], +[ + AC_ARG_ENABLE(installed-tests, + AS_HELP_STRING([--enable-installed-tests], + [Enable installation of some test cases]), + [case ${enableval} in + yes) ENABLE_INSTALLED_TESTS="1" ;; + no) ENABLE_INSTALLED_TESTS="" ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-installed-tests]) ;; + esac]) + AM_CONDITIONAL([ENABLE_INSTALLED_TESTS], test "$ENABLE_INSTALLED_TESTS" = "1") + AC_ARG_ENABLE(always-build-tests, + AS_HELP_STRING([--enable-always-build-tests], + [Enable always building tests during 'make all']), + [case ${enableval} in + yes) ENABLE_ALWAYS_BUILD_TESTS="1" ;; + no) ENABLE_ALWAYS_BUILD_TESTS="" ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-always-build-tests]) ;; + esac]) + AM_CONDITIONAL([ENABLE_ALWAYS_BUILD_TESTS], test "$ENABLE_ALWAYS_BUILD_TESTS" = "1") + if test "$ENABLE_INSTALLED_TESTS" = "1"; then + AC_SUBST(installed_test_metadir, [${datadir}/installed-tests/]AC_PACKAGE_NAME) + AC_SUBST(installed_testdir, [${libexecdir}/installed-tests/]AC_PACKAGE_NAME) + fi +]) diff --git a/clutter/build/autotools/introspection.m4 b/clutter/build/autotools/introspection.m4 new file mode 100644 index 0000000..d89c3d9 --- /dev/null +++ b/clutter/build/autotools/introspection.m4 @@ -0,0 +1,96 @@ +dnl -*- mode: autoconf -*- +dnl Copyright 2009 Johan Dahlin +dnl +dnl This file is free software; the author(s) gives unlimited +dnl permission to copy and/or distribute it, with or without +dnl modifications, as long as this notice is preserved. +dnl + +# serial 1 + +m4_define([_GOBJECT_INTROSPECTION_CHECK_INTERNAL], +[ + AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first + AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first + AC_BEFORE([LT_INIT],[$0])dnl setup libtool first + + dnl enable/disable introspection + m4_if([$2], [require], + [dnl + enable_introspection=yes + ],[dnl + AC_ARG_ENABLE(introspection, + AS_HELP_STRING([--enable-introspection[=@<:@no/auto/yes@:>@]], + [Enable introspection for this build]),, + [enable_introspection=auto]) + ])dnl + + AC_MSG_CHECKING([for gobject-introspection]) + + dnl presence/version checking + AS_CASE([$enable_introspection], + [no], [dnl + found_introspection="no (disabled, use --enable-introspection to enable)" + ],dnl + [yes],[dnl + PKG_CHECK_EXISTS([gobject-introspection-1.0],, + AC_MSG_ERROR([gobject-introspection-1.0 is not installed])) + PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], + found_introspection=yes, + AC_MSG_ERROR([You need to have gobject-introspection >= $1 installed to build AC_PACKAGE_NAME])) + ],dnl + [auto],[dnl + PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], found_introspection=yes, found_introspection=no) + dnl Canonicalize enable_introspection + enable_introspection=$found_introspection + ],dnl + [dnl + AC_MSG_ERROR([invalid argument passed to --enable-introspection, should be one of @<:@no/auto/yes@:>@]) + ])dnl + + AC_MSG_RESULT([$found_introspection]) + + INTROSPECTION_SCANNER= + INTROSPECTION_COMPILER= + INTROSPECTION_GENERATE= + INTROSPECTION_GIRDIR= + INTROSPECTION_TYPELIBDIR= + if test "x$found_introspection" = "xyes"; then + INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0` + INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0` + INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0` + INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0` + INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)" + INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0` + INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0` + INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection + fi + AC_SUBST(INTROSPECTION_SCANNER) + AC_SUBST(INTROSPECTION_COMPILER) + AC_SUBST(INTROSPECTION_GENERATE) + AC_SUBST(INTROSPECTION_GIRDIR) + AC_SUBST(INTROSPECTION_TYPELIBDIR) + AC_SUBST(INTROSPECTION_CFLAGS) + AC_SUBST(INTROSPECTION_LIBS) + AC_SUBST(INTROSPECTION_MAKEFILE) + + AM_CONDITIONAL(HAVE_INTROSPECTION, test "x$found_introspection" = "xyes") +]) + + +dnl Usage: +dnl GOBJECT_INTROSPECTION_CHECK([minimum-g-i-version]) + +AC_DEFUN([GOBJECT_INTROSPECTION_CHECK], +[ + _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1]) +]) + +dnl Usage: +dnl GOBJECT_INTROSPECTION_REQUIRE([minimum-g-i-version]) + + +AC_DEFUN([GOBJECT_INTROSPECTION_REQUIRE], +[ + _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1], [require]) +]) diff --git a/clutter/build/autotools/libtool.m4 b/clutter/build/autotools/libtool.m4 new file mode 100644 index 0000000..a644432 --- /dev/null +++ b/clutter/build/autotools/libtool.m4 @@ -0,0 +1,8372 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +# +# Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +m4_define([_LT_COPYING], [dnl +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +]) + +# serial 58 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_PREPARE_CC_BASENAME +# ----------------------- +m4_defun([_LT_PREPARE_CC_BASENAME], [ +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in @S|@*""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} +])# _LT_PREPARE_CC_BASENAME + + +# _LT_CC_BASENAME(CC) +# ------------------- +# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, +# but that macro is also expanded into generated libtool script, which +# arranges for $SED and $ECHO to be set by different means. +m4_defun([_LT_CC_BASENAME], +[m4_require([_LT_PREPARE_CC_BASENAME])dnl +AC_REQUIRE([_LT_DECL_SED])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl +func_cc_basename $1 +cc_basename=$func_cc_basename_result +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + +_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl +dnl +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_WITH_SYSROOT])dnl +m4_require([_LT_CMD_TRUNCATE])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from 'configure', and 'config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# 'config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain=$ac_aux_dir/ltmain.sh +])# _LT_PROG_LTMAIN + + +## ------------------------------------- ## +## Accumulate code for creating libtool. ## +## ------------------------------------- ## + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the 'libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + +## ------------------------ ## +## FIXME: Eliminate VARNAME ## +## ------------------------ ## + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to 'config.status' so that its +# declaration there will have the same value as in 'configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags='_LT_TAGS'dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into 'config.status', and then the shell code to quote escape them in +# for loops in 'config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +_LT_OUTPUT_LIBTOOL_INIT +]) + +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# '#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test 0 = "$lt_write_fail" && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), incase it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) + +cat >>"$CONFIG_LT" <<\_LTEOF +lt_cl_silent=false +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +'$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to ." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2011 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test 0 != $[#] +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try '$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try '$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +lt_cl_success=: +test yes = "$silent" && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +_LT_COPYING +_LT_LIBTOOL_TAGS + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +_LT_PREPARE_MUNGE_PATH_LIST +_LT_PREPARE_CC_BASENAME + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Go], [_LT_LANG(GO)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +m4_ifndef([AC_PROG_GO], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_GO. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +m4_defun([AC_PROG_GO], +[AC_LANG_PUSH(Go)dnl +AC_ARG_VAR([GOC], [Go compiler command])dnl +AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl +_AC_ARG_VAR_LDFLAGS()dnl +AC_CHECK_TOOL(GOC, gccgo) +if test -z "$GOC"; then + if test -n "$ac_tool_prefix"; then + AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) + fi +fi +if test -z "$GOC"; then + AC_CHECK_PROG(GOC, gccgo, gccgo, false) +fi +])#m4_defun +])#m4_ifndef + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([AC_PROG_GO], + [LT_LANG(GO)], + [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS=$save_LDFLAGS + ]) + + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[[012]][[,.]]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES([TAG]) +# --------------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + if test yes = "$lt_cv_ld_force_load"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], + [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + m4_if([$1], [CXX], +[ if test yes != "$lt_cv_apple_cc_single_mod"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) +# ---------------------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +# Store the results from the different compilers for each TAGNAME. +# Allow to override them for all tags through lt_cv_aix_libpath. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], + [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ + lt_aix_libpath_sed='[ + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }]' + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi],[]) + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib + fi + ]) + aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) +fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script that will find a shell with a builtin +# printf (that we can use as an echo command). +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +case $ECHO in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac + +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) + +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_WITH_SYSROOT +# ---------------- +AC_DEFUN([_LT_WITH_SYSROOT], +[AC_MSG_CHECKING([for sysroot]) +AC_ARG_WITH([sysroot], +[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], + [Search for dependent libraries within DIR (or the compiler's sysroot + if not specified).])], +[], [with_sysroot=no]) + +dnl lt_sysroot will always be passed unquoted. We quote it here +dnl in case the user passed a directory name. +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + AC_MSG_RESULT([$with_sysroot]) + AC_MSG_ERROR([The sysroot must be an absolute path.]) + ;; +esac + + AC_MSG_RESULT([${lt_sysroot:-no}]) +_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl +[dependent libraries, and where our libraries should be installed.])]) + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock +])# _LT_ENABLE_LOCK + + +# _LT_PROG_AR +# ----------- +m4_defun([_LT_PROG_AR], +[AC_CHECK_TOOLS(AR, [ar], false) +: ${AR=ar} +: ${AR_FLAGS=cru} +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], + [lt_cv_ar_at_file=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([lt_ar_try]) + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + AC_TRY_EVAL([lt_ar_try]) + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + ]) + ]) + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi +_LT_DECL([], [archiver_list_spec], [1], + [How to feed a file listing to the archiver]) +])# _LT_PROG_AR + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[_LT_PROG_AR + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test yes = "[$]$2"; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS +]) + +if test yes = "[$]$2"; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n "$lt_cv_sys_max_cmd_len"; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes = "$cross_compiling"; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen=shl_load], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen=dlopen], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links=nottested +if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test no = "$hard_links"; then + AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", + [Define to the sub-directory where libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then + + # We can hardcode non-existent directories. + if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && + test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || + test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_PREPARE_MUNGE_PATH_LIST +# --------------------------- +# Make sure func_munge_path_list() is defined correctly. +m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], +[[# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x@S|@2 in + x) + ;; + *:) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" + ;; + x:*) + eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" + ;; + *) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + esac +} +]])# _LT_PREPARE_PATH_LIST + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +AC_ARG_VAR([LT_SYS_LIBRARY_PATH], +[User-defined run-time library search path.]) + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[[4-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a[(]lib.so.V[)]' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[23]].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[[3-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Add ABI-specific directories to the system library path. + sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[List of archive names. First name is the real one, the rest are links. + The last name is the one that the linker finds with -lNAME]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], + [Detected run-time system search path for libraries]) +_LT_DECL([], [configure_time_lt_sys_library_path], [2], + [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program that can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$1"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac]) +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program that can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test no = "$withval" || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], +[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi]) +rm -f conftest.i conftest2.i conftest.out]) +])# _LT_PATH_DD + + +# _LT_CMD_TRUNCATE +# ---------------- +# find command to truncate a binary pipe +m4_defun([_LT_CMD_TRUNCATE], +[m4_require([_LT_PATH_DD]) +AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], +[printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) +_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], + [Command to truncate a binary pipe]) +])# _LT_CMD_TRUNCATE + + +# _LT_CHECK_MAGIC_METHOD +# ---------------------- +# how to check for library dependencies +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_MAGIC_METHOD], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +AC_CACHE_CHECK([how to recognize dependent libraries], +lt_cv_deplibs_check_method, +[lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[[4-9]]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[[45]]*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method = "file_magic"]) +_LT_DECL([], [file_magic_glob], [1], + [How to find potential files when deplibs_check_method = "file_magic"]) +_LT_DECL([], [want_nocaseglob], [1], + [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi]) +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + AC_SUBST([DUMPBIN]) + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + +# _LT_CHECK_SHAREDLIB_FROM_LINKLIB +# -------------------------------- +# how to determine the name of the shared library +# associated with a specific link library. +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +m4_require([_LT_DECL_DLLTOOL]) +AC_CACHE_CHECK([how to associate runtime and link libraries], +lt_cv_sharedlib_from_linklib_cmd, +[lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac +]) +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + +_LT_DECL([], [sharedlib_from_linklib_cmd], [1], + [Command to associate shared and link libraries]) +])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB + + +# _LT_PATH_MANIFEST_TOOL +# ---------------------- +# locate the manifest tool +m4_defun([_LT_PATH_MANIFEST_TOOL], +[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], + [lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&AS_MESSAGE_LOG_FD + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest*]) +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi +_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl +])# _LT_PATH_MANIFEST_TOOL + + +# _LT_DLL_DEF_P([FILE]) +# --------------------- +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with func_dll_def_p in the libtool script +AC_DEFUN([_LT_DLL_DEF_P], +[dnl + test DEF = "`$SED -n dnl + -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace + -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments + -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl + -e q dnl Only consider the first "real" line + $1`" dnl +])# _LT_DLL_DEF_P + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM=-lm) + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[[ABCDEGRST]]' + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT@&t@_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT@&t@_DLSYM_CONST +#else +# define LT@&t@_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT@&t@_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], + [Transform the output of nm into a list of symbols to manually relocate]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([nm_interface], [lt_cv_nm_interface], [1], + [The name lister interface]) +_LT_DECL([], [nm_file_list_spec], [1], + [Specify filename containing input files for $NM]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64, which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test yes = "$GCC"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + *Sun\ F* | *Sun*Fortran*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + *Intel*\ [[CF]]*Compiler*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + *Portland\ Group*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +AC_CACHE_CHECK([for $compiler option to produce PIC], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + case $host_os in + aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + ;; + esac + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + esac + + _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + esac + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + ;; + esac + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], + [lt_cv_irix_exported_symbol], + [save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + AC_LINK_IFELSE( + [AC_LANG_SOURCE( + [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], + [C++], [[int foo (void) { return 0; }]], + [Fortran 77], [[ + subroutine foo + end]], + [Fortran], [[ + subroutine foo + end]])])], + [lt_cv_irix_exported_symbol=yes], + [lt_cv_irix_exported_symbol=no]) + LDFLAGS=$save_LDFLAGS]) + if test yes = "$lt_cv_irix_exported_symbol"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(ld_shlibs, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + osf3*) + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $_LT_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting $shlibpath_var if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [postlink_cmds], [2], + [Commands necessary for finishing linking programs]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC=$CC +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report what library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC=$lt_save_CC +])# _LT_LANG_C_CONFIG + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +if test -n "$CXX" && ( test no != "$CXX" && + ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || + (test g++ != "$CXX"))); then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_caught_CXX_error"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test yes = "$GXX"; then + # Set up default GNU C++ configuration + + LT_PATH_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test yes = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='$wl' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GXX"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag=$shared_flag' $wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + # The "-G" linker flag allows undefined symbols. + _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared + # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd2.*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ + $RM $lib.exp' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require '-G' NOT '-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + + _LT_TAGVAR(GCC, $1)=$GXX + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test yes != "$_lt_caught_CXX_error" + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_FUNC_STRIPNAME_CNF +# ---------------------- +# func_stripname_cnf prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# +# This function is identical to the (non-XSI) version of func_stripname, +# except this one can be used by m4 code that may be executed by configure, +# rather than the libtool script. +m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl +AC_REQUIRE([_LT_DECL_SED]) +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) +func_stripname_cnf () +{ + case @S|@2 in + .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; + *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; + esac +} # func_stripname_cnf +])# _LT_FUNC_STRIPNAME_CNF + + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF +package foo +func foo() { +} +_LT_EOF +]) + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case $prev$p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test x-L = "$p" || + test x-R = "$p"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test no = "$pre_test_object_deps_done"; then + case $prev in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)=$prev$p + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test no = "$pre_test_object_deps_done"; then + if test -z "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)=$p + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)=$p + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test no = "$F77"; then + _lt_disable_F77=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_F77"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${F77-"f77"} + CFLAGS=$FFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$G77 + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_F77" + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test no = "$FC"; then + _lt_disable_FC=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_FC"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${FC-"f95"} + CFLAGS=$FCFLAGS + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_FC" + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +CFLAGS=$GCJFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_GO_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Go compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GO_CONFIG], +[AC_REQUIRE([LT_PROG_GO])dnl +AC_LANG_SAVE + +# Source file extension for Go test sources. +ac_ext=go + +# Object file extension for compiled Go test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="package main; func main() { }" + +# Code to be used in simple link tests +lt_simple_link_test_code='package main; func main() { }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GOC-"gccgo"} +CFLAGS=$GOFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# Go did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GO_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code=$lt_simple_compile_test_code + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +CFLAGS= +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_GO +# ---------- +AC_DEFUN([LT_PROG_GO], +[AC_CHECK_TOOL(GOC, gccgo,) +]) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + +# _LT_DECL_DLLTOOL +# ---------------- +# Ensure DLLTOOL variable is set. +m4_defun([_LT_DECL_DLLTOOL], +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) +AC_SUBST([DLLTOOL]) +]) + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f "$lt_ac_sed" && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test 10 -lt "$lt_ac_count" && break + lt_ac_count=`expr $lt_ac_count + 1` + if test "$lt_ac_count" -gt "$lt_ac_max"; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PATH_CONVERSION_FUNCTIONS +# ----------------------------- +# Determine what file name conversion functions should be used by +# func_to_host_file (and, implicitly, by func_to_host_path). These are needed +# for certain cross-compile configurations and native mingw. +m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_MSG_CHECKING([how to convert $build file names to $host format]) +AC_CACHE_VAL(lt_cv_to_host_file_cmd, +[case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac +]) +to_host_file_cmd=$lt_cv_to_host_file_cmd +AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) +_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], + [0], [convert $build file names to $host format])dnl + +AC_MSG_CHECKING([how to convert $build file names to toolchain format]) +AC_CACHE_VAL(lt_cv_to_tool_file_cmd, +[#assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac +]) +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) +_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], + [0], [convert $build files to toolchain format])dnl +])# _LT_PATH_CONVERSION_FUNCTIONS diff --git a/clutter/build/autotools/ltoptions.m4 b/clutter/build/autotools/ltoptions.m4 new file mode 100644 index 0000000..94b0829 --- /dev/null +++ b/clutter/build/autotools/ltoptions.m4 @@ -0,0 +1,437 @@ +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 8 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option '$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl 'shared' nor 'disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], + [_LT_WITH_AIX_SONAME([aix])]) + ]) +])# _LT_SET_OPTIONS + + +## --------------------------------- ## +## Macros to handle LT_INIT options. ## +## --------------------------------- ## + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [1], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the 'shared' and +# 'disable-shared' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the 'static' and +# 'disable-static' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the 'fast-install' +# and 'disable-fast-install' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_AIX_SONAME([DEFAULT]) +# ---------------------------------- +# implement the --with-aix-soname flag, and support the `aix-soname=aix' +# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT +# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. +m4_define([_LT_WITH_AIX_SONAME], +[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl +shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[[5-9]]*,yes) + AC_MSG_CHECKING([which variant of shared library versioning to provide]) + AC_ARG_WITH([aix-soname], + [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], + [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], + [case $withval in + aix|svr4|both) + ;; + *) + AC_MSG_ERROR([Unknown argument to --with-aix-soname]) + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname], + [AC_CACHE_VAL([lt_cv_with_aix_soname], + [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) + with_aix_soname=$lt_cv_with_aix_soname]) + AC_MSG_RESULT([$with_aix_soname]) + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + +_LT_DECL([], [shared_archive_member_spec], [0], + [Shared archive member basename, for filename based shared library versioning on AIX])dnl +])# _LT_WITH_AIX_SONAME + +LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the 'pic-only' and 'no-pic' +# LT_INIT options. +# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [pic_mode=m4_default([$1], [default])]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + +## ----------------- ## +## LTDL_INIT Options ## +## ----------------- ## + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) diff --git a/clutter/build/autotools/ltsugar.m4 b/clutter/build/autotools/ltsugar.m4 new file mode 100644 index 0000000..48bc934 --- /dev/null +++ b/clutter/build/autotools/ltsugar.m4 @@ -0,0 +1,124 @@ +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59, which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) diff --git a/clutter/build/autotools/ltversion.m4 b/clutter/build/autotools/ltversion.m4 new file mode 100644 index 0000000..fa04b52 --- /dev/null +++ b/clutter/build/autotools/ltversion.m4 @@ -0,0 +1,23 @@ +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# @configure_input@ + +# serial 4179 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.4.6]) +m4_define([LT_PACKAGE_REVISION], [2.4.6]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.4.6' +macro_revision='2.4.6' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) diff --git a/clutter/build/autotools/lt~obsolete.m4 b/clutter/build/autotools/lt~obsolete.m4 new file mode 100644 index 0000000..c6b26f8 --- /dev/null +++ b/clutter/build/autotools/lt~obsolete.m4 @@ -0,0 +1,99 @@ +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 5 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) diff --git a/clutter/build/autotools/tap-driver.sh b/clutter/build/autotools/tap-driver.sh new file mode 100755 index 0000000..19aa531 --- /dev/null +++ b/clutter/build/autotools/tap-driver.sh @@ -0,0 +1,652 @@ +#! /bin/sh +# Copyright (C) 2011-2013 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +scriptversion=2011-12-27.17; # UTC + +# Make unconditional expansion of undefined variables an error. This +# helps a lot in preventing typo-related bugs. +set -u + +me=tap-driver.sh + +fatal () +{ + echo "$me: fatal: $*" >&2 + exit 1 +} + +usage_error () +{ + echo "$me: $*" >&2 + print_usage >&2 + exit 2 +} + +print_usage () +{ + cat < + # + trap : 1 3 2 13 15 + if test $merge -gt 0; then + exec 2>&1 + else + exec 2>&3 + fi + "$@" + echo $? + ) | LC_ALL=C ${AM_TAP_AWK-awk} \ + -v me="$me" \ + -v test_script_name="$test_name" \ + -v log_file="$log_file" \ + -v trs_file="$trs_file" \ + -v expect_failure="$expect_failure" \ + -v merge="$merge" \ + -v ignore_exit="$ignore_exit" \ + -v comments="$comments" \ + -v diag_string="$diag_string" \ +' +# FIXME: the usages of "cat >&3" below could be optimized when using +# FIXME: GNU awk, and/on on systems that supports /dev/fd/. + +# Implementation note: in what follows, `result_obj` will be an +# associative array that (partly) simulates a TAP result object +# from the `TAP::Parser` perl module. + +## ----------- ## +## FUNCTIONS ## +## ----------- ## + +function fatal(msg) +{ + print me ": " msg | "cat >&2" + exit 1 +} + +function abort(where) +{ + fatal("internal error " where) +} + +# Convert a boolean to a "yes"/"no" string. +function yn(bool) +{ + return bool ? "yes" : "no"; +} + +function add_test_result(result) +{ + if (!test_results_index) + test_results_index = 0 + test_results_list[test_results_index] = result + test_results_index += 1 + test_results_seen[result] = 1; +} + +# Whether the test script should be re-run by "make recheck". +function must_recheck() +{ + for (k in test_results_seen) + if (k != "XFAIL" && k != "PASS" && k != "SKIP") + return 1 + return 0 +} + +# Whether the content of the log file associated to this test should +# be copied into the "global" test-suite.log. +function copy_in_global_log() +{ + for (k in test_results_seen) + if (k != "PASS") + return 1 + return 0 +} + +# FIXME: this can certainly be improved ... +function get_global_test_result() +{ + if ("ERROR" in test_results_seen) + return "ERROR" + if ("FAIL" in test_results_seen || "XPASS" in test_results_seen) + return "FAIL" + all_skipped = 1 + for (k in test_results_seen) + if (k != "SKIP") + all_skipped = 0 + if (all_skipped) + return "SKIP" + return "PASS"; +} + +function stringify_result_obj(result_obj) +{ + if (result_obj["is_unplanned"] || result_obj["number"] != testno) + return "ERROR" + + if (plan_seen == LATE_PLAN) + return "ERROR" + + if (result_obj["directive"] == "TODO") + return result_obj["is_ok"] ? "XPASS" : "XFAIL" + + if (result_obj["directive"] == "SKIP") + return result_obj["is_ok"] ? "SKIP" : COOKED_FAIL; + + if (length(result_obj["directive"])) + abort("in function stringify_result_obj()") + + return result_obj["is_ok"] ? COOKED_PASS : COOKED_FAIL +} + +function decorate_result(result) +{ + color_name = color_for_result[result] + if (color_name) + return color_map[color_name] "" result "" color_map["std"] + # If we are not using colorized output, or if we do not know how + # to colorize the given result, we should return it unchanged. + return result +} + +function report(result, details) +{ + if (result ~ /^(X?(PASS|FAIL)|SKIP|ERROR)/) + { + msg = ": " test_script_name + add_test_result(result) + } + else if (result == "#") + { + msg = " " test_script_name ":" + } + else + { + abort("in function report()") + } + if (length(details)) + msg = msg " " details + # Output on console might be colorized. + print decorate_result(result) msg + # Log the result in the log file too, to help debugging (this is + # especially true when said result is a TAP error or "Bail out!"). + print result msg | "cat >&3"; +} + +function testsuite_error(error_message) +{ + report("ERROR", "- " error_message) +} + +function handle_tap_result() +{ + details = result_obj["number"]; + if (length(result_obj["description"])) + details = details " " result_obj["description"] + + if (plan_seen == LATE_PLAN) + { + details = details " # AFTER LATE PLAN"; + } + else if (result_obj["is_unplanned"]) + { + details = details " # UNPLANNED"; + } + else if (result_obj["number"] != testno) + { + details = sprintf("%s # OUT-OF-ORDER (expecting %d)", + details, testno); + } + else if (result_obj["directive"]) + { + details = details " # " result_obj["directive"]; + if (length(result_obj["explanation"])) + details = details " " result_obj["explanation"] + } + + report(stringify_result_obj(result_obj), details) +} + +# `skip_reason` should be empty whenever planned > 0. +function handle_tap_plan(planned, skip_reason) +{ + planned += 0 # Avoid getting confused if, say, `planned` is "00" + if (length(skip_reason) && planned > 0) + abort("in function handle_tap_plan()") + if (plan_seen) + { + # Error, only one plan per stream is acceptable. + testsuite_error("multiple test plans") + return; + } + planned_tests = planned + # The TAP plan can come before or after *all* the TAP results; we speak + # respectively of an "early" or a "late" plan. If we see the plan line + # after at least one TAP result has been seen, assume we have a late + # plan; in this case, any further test result seen after the plan will + # be flagged as an error. + plan_seen = (testno >= 1 ? LATE_PLAN : EARLY_PLAN) + # If testno > 0, we have an error ("too many tests run") that will be + # automatically dealt with later, so do not worry about it here. If + # $plan_seen is true, we have an error due to a repeated plan, and that + # has already been dealt with above. Otherwise, we have a valid "plan + # with SKIP" specification, and should report it as a particular kind + # of SKIP result. + if (planned == 0 && testno == 0) + { + if (length(skip_reason)) + skip_reason = "- " skip_reason; + report("SKIP", skip_reason); + } +} + +function extract_tap_comment(line) +{ + if (index(line, diag_string) == 1) + { + # Strip leading `diag_string` from `line`. + line = substr(line, length(diag_string) + 1) + # And strip any leading and trailing whitespace left. + sub("^[ \t]*", "", line) + sub("[ \t]*$", "", line) + # Return what is left (if any). + return line; + } + return ""; +} + +# When this function is called, we know that line is a TAP result line, +# so that it matches the (perl) RE "^(not )?ok\b". +function setup_result_obj(line) +{ + # Get the result, and remove it from the line. + result_obj["is_ok"] = (substr(line, 1, 2) == "ok" ? 1 : 0) + sub("^(not )?ok[ \t]*", "", line) + + # If the result has an explicit number, get it and strip it; otherwise, + # automatically assing the next progresive number to it. + if (line ~ /^[0-9]+$/ || line ~ /^[0-9]+[^a-zA-Z0-9_]/) + { + match(line, "^[0-9]+") + # The final `+ 0` is to normalize numbers with leading zeros. + result_obj["number"] = substr(line, 1, RLENGTH) + 0 + line = substr(line, RLENGTH + 1) + } + else + { + result_obj["number"] = testno + } + + if (plan_seen == LATE_PLAN) + # No further test results are acceptable after a "late" TAP plan + # has been seen. + result_obj["is_unplanned"] = 1 + else if (plan_seen && testno > planned_tests) + result_obj["is_unplanned"] = 1 + else + result_obj["is_unplanned"] = 0 + + # Strip trailing and leading whitespace. + sub("^[ \t]*", "", line) + sub("[ \t]*$", "", line) + + # This will have to be corrected if we have a "TODO"/"SKIP" directive. + result_obj["description"] = line + result_obj["directive"] = "" + result_obj["explanation"] = "" + + if (index(line, "#") == 0) + return # No possible directive, nothing more to do. + + # Directives are case-insensitive. + rx = "[ \t]*#[ \t]*([tT][oO][dD][oO]|[sS][kK][iI][pP])[ \t]*" + + # See whether we have the directive, and if yes, where. + pos = match(line, rx "$") + if (!pos) + pos = match(line, rx "[^a-zA-Z0-9_]") + + # If there was no TAP directive, we have nothing more to do. + if (!pos) + return + + # Let`s now see if the TAP directive has been escaped. For example: + # escaped: ok \# SKIP + # not escaped: ok \\# SKIP + # escaped: ok \\\\\# SKIP + # not escaped: ok \ # SKIP + if (substr(line, pos, 1) == "#") + { + bslash_count = 0 + for (i = pos; i > 1 && substr(line, i - 1, 1) == "\\"; i--) + bslash_count += 1 + if (bslash_count % 2) + return # Directive was escaped. + } + + # Strip the directive and its explanation (if any) from the test + # description. + result_obj["description"] = substr(line, 1, pos - 1) + # Now remove the test description from the line, that has been dealt + # with already. + line = substr(line, pos) + # Strip the directive, and save its value (normalized to upper case). + sub("^[ \t]*#[ \t]*", "", line) + result_obj["directive"] = toupper(substr(line, 1, 4)) + line = substr(line, 5) + # Now get the explanation for the directive (if any), with leading + # and trailing whitespace removed. + sub("^[ \t]*", "", line) + sub("[ \t]*$", "", line) + result_obj["explanation"] = line +} + +function get_test_exit_message(status) +{ + if (status == 0) + return "" + if (status !~ /^[1-9][0-9]*$/) + abort("getting exit status") + if (status < 127) + exit_details = "" + else if (status == 127) + exit_details = " (command not found?)" + else if (status >= 128 && status <= 255) + exit_details = sprintf(" (terminated by signal %d?)", status - 128) + else if (status > 256 && status <= 384) + # We used to report an "abnormal termination" here, but some Korn + # shells, when a child process die due to signal number n, can leave + # in $? an exit status of 256+n instead of the more standard 128+n. + # Apparently, both behaviours are allowed by POSIX (2008), so be + # prepared to handle them both. See also Austing Group report ID + # 0000051 + exit_details = sprintf(" (terminated by signal %d?)", status - 256) + else + # Never seen in practice. + exit_details = " (abnormal termination)" + return sprintf("exited with status %d%s", status, exit_details) +} + +function write_test_results() +{ + print ":global-test-result: " get_global_test_result() > trs_file + print ":recheck: " yn(must_recheck()) > trs_file + print ":copy-in-global-log: " yn(copy_in_global_log()) > trs_file + for (i = 0; i < test_results_index; i += 1) + print ":test-result: " test_results_list[i] > trs_file + close(trs_file); +} + +BEGIN { + +## ------- ## +## SETUP ## +## ------- ## + +'"$init_colors"' + +# Properly initialized once the TAP plan is seen. +planned_tests = 0 + +COOKED_PASS = expect_failure ? "XPASS": "PASS"; +COOKED_FAIL = expect_failure ? "XFAIL": "FAIL"; + +# Enumeration-like constants to remember which kind of plan (if any) +# has been seen. It is important that NO_PLAN evaluates "false" as +# a boolean. +NO_PLAN = 0 +EARLY_PLAN = 1 +LATE_PLAN = 2 + +testno = 0 # Number of test results seen so far. +bailed_out = 0 # Whether a "Bail out!" directive has been seen. + +# Whether the TAP plan has been seen or not, and if yes, which kind +# it is ("early" is seen before any test result, "late" otherwise). +plan_seen = NO_PLAN + +## --------- ## +## PARSING ## +## --------- ## + +is_first_read = 1 + +while (1) + { + # Involutions required so that we are able to read the exit status + # from the last input line. + st = getline + if (st < 0) # I/O error. + fatal("I/O error while reading from input stream") + else if (st == 0) # End-of-input + { + if (is_first_read) + abort("in input loop: only one input line") + break + } + if (is_first_read) + { + is_first_read = 0 + nextline = $0 + continue + } + else + { + curline = nextline + nextline = $0 + $0 = curline + } + # Copy any input line verbatim into the log file. + print | "cat >&3" + # Parsing of TAP input should stop after a "Bail out!" directive. + if (bailed_out) + continue + + # TAP test result. + if ($0 ~ /^(not )?ok$/ || $0 ~ /^(not )?ok[^a-zA-Z0-9_]/) + { + testno += 1 + setup_result_obj($0) + handle_tap_result() + } + # TAP plan (normal or "SKIP" without explanation). + else if ($0 ~ /^1\.\.[0-9]+[ \t]*$/) + { + # The next two lines will put the number of planned tests in $0. + sub("^1\\.\\.", "") + sub("[^0-9]*$", "") + handle_tap_plan($0, "") + continue + } + # TAP "SKIP" plan, with an explanation. + else if ($0 ~ /^1\.\.0+[ \t]*#/) + { + # The next lines will put the skip explanation in $0, stripping + # any leading and trailing whitespace. This is a little more + # tricky in truth, since we want to also strip a potential leading + # "SKIP" string from the message. + sub("^[^#]*#[ \t]*(SKIP[: \t][ \t]*)?", "") + sub("[ \t]*$", ""); + handle_tap_plan(0, $0) + } + # "Bail out!" magic. + # Older versions of prove and TAP::Harness (e.g., 3.17) did not + # recognize a "Bail out!" directive when preceded by leading + # whitespace, but more modern versions (e.g., 3.23) do. So we + # emulate the latter, "more modern" behaviour. + else if ($0 ~ /^[ \t]*Bail out!/) + { + bailed_out = 1 + # Get the bailout message (if any), with leading and trailing + # whitespace stripped. The message remains stored in `$0`. + sub("^[ \t]*Bail out![ \t]*", ""); + sub("[ \t]*$", ""); + # Format the error message for the + bailout_message = "Bail out!" + if (length($0)) + bailout_message = bailout_message " " $0 + testsuite_error(bailout_message) + } + # Maybe we have too look for dianogtic comments too. + else if (comments != 0) + { + comment = extract_tap_comment($0); + if (length(comment)) + report("#", comment); + } + } + +## -------- ## +## FINISH ## +## -------- ## + +# A "Bail out!" directive should cause us to ignore any following TAP +# error, as well as a non-zero exit status from the TAP producer. +if (!bailed_out) + { + if (!plan_seen) + { + testsuite_error("missing test plan") + } + else if (planned_tests != testno) + { + bad_amount = testno > planned_tests ? "many" : "few" + testsuite_error(sprintf("too %s tests run (expected %d, got %d)", + bad_amount, planned_tests, testno)) + } + if (!ignore_exit) + { + # Fetch exit status from the last line. + exit_message = get_test_exit_message(nextline) + if (exit_message) + testsuite_error(exit_message) + } + } + +write_test_results() + +exit 0 + +} # End of "BEGIN" block. +' + +# TODO: document that we consume the file descriptor 3 :-( +} 3>"$log_file" + +test $? -eq 0 || fatal "I/O or internal error" + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/clutter/build/autotools/tap-test b/clutter/build/autotools/tap-test new file mode 100755 index 0000000..481e333 --- /dev/null +++ b/clutter/build/autotools/tap-test @@ -0,0 +1,5 @@ +#! /bin/sh + +# run a GTest in tap mode. The test binary is passed as $1 + +$1 -k --tap diff --git a/clutter/build/compile b/clutter/build/compile new file mode 100755 index 0000000..a85b723 --- /dev/null +++ b/clutter/build/compile @@ -0,0 +1,347 @@ +#! /bin/sh +# Wrapper for compilers which do not understand '-c -o'. + +scriptversion=2012-10-14.11; # UTC + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Written by Tom Tromey . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +nl=' +' + +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent tools from complaining about whitespace usage. +IFS=" "" $nl" + +file_conv= + +# func_file_conv build_file lazy +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. If the determined conversion +# type is listed in (the comma separated) LAZY, no conversion will +# take place. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv/,$2, in + *,$file_conv,*) + ;; + mingw/*) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin/*) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine/*) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + if test -f "$dir/lib$lib.a"; then + found=yes + lib=$dir/lib$lib.a + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + +# func_cl_wrapper cl arg... +# Adjust compile command to suit cl +func_cl_wrapper () +{ + # Assume a capable shell + lib_path= + shared=: + linker_opts= + for arg + do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + eat=1 + case $2 in + *.o | *.[oO][bB][jJ]) + func_file_conv "$2" + set x "$@" -Fo"$file" + shift + ;; + *) + func_file_conv "$2" + set x "$@" -Fe"$file" + shift + ;; + esac + ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; + -I*) + func_file_conv "${1#-I}" mingw + set x "$@" -I"$file" + shift + ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; + -l*) + func_cl_dashl "${1#-l}" + set x "$@" "$lib" + shift + ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; + -L*) + func_cl_dashL "${1#-L}" + ;; + -static) + shared=false + ;; + -Wl,*) + arg=${1#-Wl,} + save_ifs="$IFS"; IFS=',' + for flag in $arg; do + IFS="$save_ifs" + linker_opts="$linker_opts $flag" + done + IFS="$save_ifs" + ;; + -Xlinker) + eat=1 + linker_opts="$linker_opts $2" + ;; + -*) + set x "$@" "$1" + shift + ;; + *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) + func_file_conv "$1" + set x "$@" -Tp"$file" + shift + ;; + *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) + func_file_conv "$1" mingw + set x "$@" "$file" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift + done + if test -n "$linker_opts"; then + linker_opts="-link$linker_opts" + fi + exec "$@" $linker_opts + exit 1 +} + +eat= + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand '-c -o'. +Remove '-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file 'INSTALL'. + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) + func_cl_wrapper "$@" # Doesn't return... + ;; +esac + +ofile= +cfile= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + # So we strip '-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no '-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # '.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use '[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/clutter/build/config.guess b/clutter/build/config.guess new file mode 100755 index 0000000..dbfb978 --- /dev/null +++ b/clutter/build/config.guess @@ -0,0 +1,1421 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2015 Free Software Foundation, Inc. + +timestamp='2015-01-01' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program 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 +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +# +# Please send patches to . + + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright 1992-2015 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +case "${UNAME_SYSTEM}" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval $set_cc_for_build + cat <<-EOF > $dummy.c + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + ;; +esac + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW64*:*) + echo ${UNAME_MACHINE}-pc-mingw64 + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + *:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="gnulibc1" ; fi + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + else + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-${LIBC} + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-${LIBC} + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; + PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; + *) echo hppa-unknown-linux-${LIBC} ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-${LIBC} + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-${LIBC} + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-${LIBC} + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-${LIBC} + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-${LIBC} + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + eval $set_cc_for_build + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + fi + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; +esac + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/clutter/build/config.sub b/clutter/build/config.sub new file mode 100755 index 0000000..6467c95 --- /dev/null +++ b/clutter/build/config.sub @@ -0,0 +1,1807 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright 1992-2015 Free Software Foundation, Inc. + +timestamp='2015-01-01' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program 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 +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + + +# Please send patches to . +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright 1992-2015 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze*) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | be32 | be64 \ + | bfin \ + | c4x | c8051 | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | epiphany \ + | fido | fr30 | frv | ft32 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ + | ns16k | ns32k \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | riscv32 | riscv64 \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | k1om-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | or1k*-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | visium-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + mingw32) + basic_machine=i686-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i686-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-* | ppc64p7-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* | -plan9* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/clutter/build/depcomp b/clutter/build/depcomp new file mode 100755 index 0000000..fc98710 --- /dev/null +++ b/clutter/build/depcomp @@ -0,0 +1,791 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2013-05-30.07; # UTC + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program 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 General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by 'PROGRAMS ARGS'. + object Object file output by 'PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputting dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +# Get the directory component of the given path, and save it in the +# global variables '$dir'. Note that this directory component will +# be either empty or ending with a '/' character. This is deliberate. +set_dir_from () +{ + case $1 in + */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; + *) dir=;; + esac +} + +# Get the suffix-stripped basename of the given path, and save it the +# global variable '$base'. +set_base_from () +{ + base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` +} + +# If no dependency file was actually created by the compiler invocation, +# we still have to create a dummy depfile, to avoid errors with the +# Makefile "include basename.Plo" scheme. +make_dummy_depfile () +{ + echo "#dummy" > "$depfile" +} + +# Factor out some common post-processing of the generated depfile. +# Requires the auxiliary global variable '$tmpdepfile' to be set. +aix_post_process_depfile () +{ + # If the compiler actually managed to produce a dependency file, + # post-process it. + if test -f "$tmpdepfile"; then + # Each line is of the form 'foo.o: dependency.h'. + # Do two passes, one to just change these to + # $object: dependency.h + # and one to simply output + # dependency.h: + # which is needed to avoid the deleted-header problem. + { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" + sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" + } > "$depfile" + rm -f "$tmpdepfile" + else + make_dummy_depfile + fi +} + +# A tabulation character. +tab=' ' +# A newline character. +nl=' +' +# Character ranges might be problematic outside the C locale. +# These definitions help. +upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ +lower=abcdefghijklmnopqrstuvwxyz +digits=0123456789 +alpha=${upper}${lower} + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Avoid interferences from the environment. +gccflag= dashmflag= + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvisualcpp +fi + +if test "$depmode" = msvc7msys; then + # This is just like msvc7 but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvc7 +fi + +if test "$depmode" = xlc; then + # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. + gccflag=-qmakedep=gcc,-MF + depmode=gcc +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. +## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. +## (see the conditional assignment to $gccflag above). +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). Also, it might not be +## supported by the other compilers which use the 'gcc' depmode. +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The second -e expression handles DOS-style file names with drive + # letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the "deleted header file" problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. +## Some versions of gcc put a space before the ':'. On the theory +## that the space means something, we add a space to the output as +## well. hp depmode also adds that space, but also prefixes the VPATH +## to the object. Take care to not repeat it in the output. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like '#:fec' to the end of the + # dependency line. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ + | tr "$nl" ' ' >> "$depfile" + echo >> "$depfile" + # The second pass generates a dummy entry for each header file. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" + ;; + +xlc) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts '$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + aix_post_process_depfile + ;; + +tcc) + # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 + # FIXME: That version still under development at the moment of writing. + # Make that this statement remains true also for stable, released + # versions. + # It will wrap lines (doesn't matter whether long or short) with a + # trailing '\', as in: + # + # foo.o : \ + # foo.c \ + # foo.h \ + # + # It will put a trailing '\' even on the last line, and will use leading + # spaces rather than leading tabs (at least since its commit 0394caf7 + # "Emit spaces for -MD"). + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. + # We have to change lines of the first kind to '$object: \'. + sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" + # And for each line of the second kind, we have to emit a 'dep.h:' + # dummy dependency, to avoid the deleted-header problem. + sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" + rm -f "$tmpdepfile" + ;; + +## The order of this option in the case statement is important, since the +## shell code in configure will try each of these formats in the order +## listed in this file. A plain '-MD' option would be understood by many +## compilers, so we must ensure this comes after the gcc and icc options. +pgcc) + # Portland's C compiler understands '-MD'. + # Will always output deps to 'file.d' where file is the root name of the + # source file under compilation, even if file resides in a subdirectory. + # The object file name does not affect the name of the '.d' file. + # pgcc 10.2 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using '\' : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + set_dir_from "$object" + # Use the source, not the object, to determine the base name, since + # that's sadly what pgcc will do too. + set_base_from "$source" + tmpdepfile=$base.d + + # For projects that build the same source file twice into different object + # files, the pgcc approach of using the *source* file root name can cause + # problems in parallel builds. Use a locking strategy to avoid stomping on + # the same $tmpdepfile. + lockdir=$base.d-lock + trap " + echo '$0: caught signal, cleaning up...' >&2 + rmdir '$lockdir' + exit 1 + " 1 2 13 15 + numtries=100 + i=$numtries + while test $i -gt 0; do + # mkdir is a portable test-and-set. + if mkdir "$lockdir" 2>/dev/null; then + # This process acquired the lock. + "$@" -MD + stat=$? + # Release the lock. + rmdir "$lockdir" + break + else + # If the lock is being held by a different process, wait + # until the winning process is done or we timeout. + while test -d "$lockdir" && test $i -gt 0; do + sleep 1 + i=`expr $i - 1` + done + fi + i=`expr $i - 1` + done + trap - 1 2 13 15 + if test $i -le 0; then + echo "$0: failed to acquire lock after $numtries attempts" >&2 + echo "$0: check lockdir '$lockdir'" >&2 + exit 1 + fi + + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" + # Add 'dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in 'foo.d' instead, so we check for that too. + # Subdirectories are respected. + set_dir_from "$object" + set_base_from "$object" + + if test "$libtool" = yes; then + # Libtool generates 2 separate objects for the 2 libraries. These + # two compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir$base.o.d # libtool 1.5 + tmpdepfile2=$dir.libs/$base.o.d # Likewise. + tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + # Same post-processing that is required for AIX mode. + aix_post_process_depfile + ;; + +msvc7) + if test "$libtool" = yes; then + showIncludes=-Wc,-showIncludes + else + showIncludes=-showIncludes + fi + "$@" $showIncludes > "$tmpdepfile" + stat=$? + grep -v '^Note: including file: ' "$tmpdepfile" + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The first sed program below extracts the file names and escapes + # backslashes for cygpath. The second sed program outputs the file + # name when reading, but also accumulates all include files in the + # hold buffer in order to output them again at the end. This only + # works with sed implementations that can handle large buffers. + sed < "$tmpdepfile" -n ' +/^Note: including file: *\(.*\)/ { + s//\1/ + s/\\/\\\\/g + p +}' | $cygpath_u | sort -u | sed -n ' +s/ /\\ /g +s/\(.*\)/'"$tab"'\1 \\/p +s/.\(.*\) \\/\1:/ +H +$ { + s/.*/'"$tab"'/ + G + p +}' >> "$depfile" + echo >> "$depfile" # make sure the fragment doesn't end with a backslash + rm -f "$tmpdepfile" + ;; + +msvc7msys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for ':' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. + "$@" $dashmflag | + sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this sed invocation + # correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + # makedepend may prepend the VPATH from the source file name to the object. + # No need to regex-escape $object, excess matching of '.' is harmless. + sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process the last invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed '1,2d' "$tmpdepfile" \ + | tr ' ' "$nl" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E \ + | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + | sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" + echo "$tab" >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/clutter/build/install-sh b/clutter/build/install-sh new file mode 100755 index 0000000..0b0fdcb --- /dev/null +++ b/clutter/build/install-sh @@ -0,0 +1,501 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2013-12-25.23; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# 'make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +tab=' ' +nl=' +' +IFS=" $tab$nl" + +# Set DOITPROG to "echo" to test this script. + +doit=${DOITPROG-} +doit_exec=${doit:-exec} + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +is_target_a_directory=possibly + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) is_target_a_directory=never;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi +fi + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + dstdir=`dirname "$dst"` + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + oIFS=$IFS + IFS=/ + set -f + set fnord $dstdir + shift + set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + set +f && + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/clutter/build/ltmain.sh b/clutter/build/ltmain.sh new file mode 100644 index 0000000..0f0a2da --- /dev/null +++ b/clutter/build/ltmain.sh @@ -0,0 +1,11147 @@ +#! /bin/sh +## DO NOT EDIT - This file generated from ./build-aux/ltmain.in +## by inline-source v2014-01-03.01 + +# libtool (GNU libtool) 2.4.6 +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool 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 +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +PROGRAM=libtool +PACKAGE=libtool +VERSION=2.4.6 +package_revision=2.4.6 + + +## ------ ## +## Usage. ## +## ------ ## + +# Run './libtool --help' for help with using this script from the +# command line. + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# After configure completes, it has a better idea of some of the +# shell tools we need than the defaults used by the functions shared +# with bootstrap, so set those here where they can still be over- +# ridden by the user, but otherwise take precedence. + +: ${AUTOCONF="autoconf"} +: ${AUTOMAKE="automake"} + + +## -------------------------- ## +## Source external libraries. ## +## -------------------------- ## + +# Much of our low-level functionality needs to be sourced from external +# libraries, which are installed to $pkgauxdir. + +# Set a version string for this script. +scriptversion=2015-01-20.17; # UTC + +# General shell script boiler plate, and helper functions. +# Written by Gary V. Vaughan, 2004 + +# Copyright (C) 2004-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# As a special exception to the GNU General Public License, if you distribute +# this file as part of a program or library that is built using GNU Libtool, +# you may include this file under the same distribution terms that you use +# for the rest of that program. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNES FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# Evaluate this file near the top of your script to gain access to +# the functions and variables defined here: +# +# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh +# +# If you need to override any of the default environment variable +# settings, do that before evaluating this file. + + +## -------------------- ## +## Shell normalisation. ## +## -------------------- ## + +# Some shells need a little help to be as Bourne compatible as possible. +# Before doing anything else, make sure all that help has been provided! + +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac +fi + +# NLS nuisances: We save the old values in case they are required later. +_G_user_locale= +_G_safe_locale= +for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test set = \"\${$_G_var+set}\"; then + save_$_G_var=\$$_G_var + $_G_var=C + export $_G_var + _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" + _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" + fi" +done + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Make sure IFS has a sensible default +sp=' ' +nl=' +' +IFS="$sp $nl" + +# There are apparently some retarded systems that use ';' as a PATH separator! +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + + +## ------------------------- ## +## Locate command utilities. ## +## ------------------------- ## + + +# func_executable_p FILE +# ---------------------- +# Check that FILE is an executable regular file. +func_executable_p () +{ + test -f "$1" && test -x "$1" +} + + +# func_path_progs PROGS_LIST CHECK_FUNC [PATH] +# -------------------------------------------- +# Search for either a program that responds to --version with output +# containing "GNU", or else returned by CHECK_FUNC otherwise, by +# trying all the directories in PATH with each of the elements of +# PROGS_LIST. +# +# CHECK_FUNC should accept the path to a candidate program, and +# set $func_check_prog_result if it truncates its output less than +# $_G_path_prog_max characters. +func_path_progs () +{ + _G_progs_list=$1 + _G_check_func=$2 + _G_PATH=${3-"$PATH"} + + _G_path_prog_max=0 + _G_path_prog_found=false + _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} + for _G_dir in $_G_PATH; do + IFS=$_G_save_IFS + test -z "$_G_dir" && _G_dir=. + for _G_prog_name in $_G_progs_list; do + for _exeext in '' .EXE; do + _G_path_prog=$_G_dir/$_G_prog_name$_exeext + func_executable_p "$_G_path_prog" || continue + case `"$_G_path_prog" --version 2>&1` in + *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; + *) $_G_check_func $_G_path_prog + func_path_progs_result=$func_check_prog_result + ;; + esac + $_G_path_prog_found && break 3 + done + done + done + IFS=$_G_save_IFS + test -z "$func_path_progs_result" && { + echo "no acceptable sed could be found in \$PATH" >&2 + exit 1 + } +} + + +# We want to be able to use the functions in this file before configure +# has figured out where the best binaries are kept, which means we have +# to search for them ourselves - except when the results are already set +# where we skip the searches. + +# Unless the user overrides by setting SED, search the path for either GNU +# sed, or the sed that truncates its output the least. +test -z "$SED" && { + _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for _G_i in 1 2 3 4 5 6 7; do + _G_sed_script=$_G_sed_script$nl$_G_sed_script + done + echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed + _G_sed_script= + + func_check_prog_sed () + { + _G_path_prog=$1 + + _G_count=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo '' >> conftest.nl + "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin + rm -f conftest.sed + SED=$func_path_progs_result +} + + +# Unless the user overrides by setting GREP, search the path for either GNU +# grep, or the grep that truncates its output the least. +test -z "$GREP" && { + func_check_prog_grep () + { + _G_path_prog=$1 + + _G_count=0 + _G_path_prog_max=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo 'GREP' >> conftest.nl + "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin + GREP=$func_path_progs_result +} + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# All uppercase variable names are used for environment variables. These +# variables can be overridden by the user before calling a script that +# uses them if a suitable command of that name is not already available +# in the command search PATH. + +: ${CP="cp -f"} +: ${ECHO="printf %s\n"} +: ${EGREP="$GREP -E"} +: ${FGREP="$GREP -F"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} + + +## -------------------- ## +## Useful sed snippets. ## +## -------------------- ## + +sed_dirname='s|/[^/]*$||' +sed_basename='s|^.*/||' + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Same as above, but do not quote variable references. +sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' + +# Sed substitution that converts a w32 file name or path +# that contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-'\' parameter expansions in output of sed_double_quote_subst that +# were '\'-ed in input to the same. If an odd number of '\' preceded a +# '$' in input to sed_double_quote_subst, that '$' was protected from +# expansion. Since each input '\' is now two '\'s, look for any number +# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. +_G_bs='\\' +_G_bs2='\\\\' +_G_bs4='\\\\\\\\' +_G_dollar='\$' +sed_double_backslash="\ + s/$_G_bs4/&\\ +/g + s/^$_G_bs2$_G_dollar/$_G_bs&/ + s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g + s/\n//g" + + +## ----------------- ## +## Global variables. ## +## ----------------- ## + +# Except for the global variables explicitly listed below, the following +# functions in the '^func_' namespace, and the '^require_' namespace +# variables initialised in the 'Resource management' section, sourcing +# this file will not pollute your global namespace with anything +# else. There's no portable way to scope variables in Bourne shell +# though, so actually running these functions will sometimes place +# results into a variable named after the function, and often use +# temporary variables in the '^_G_' namespace. If you are careful to +# avoid using those namespaces casually in your sourcing script, things +# should continue to work as you expect. And, of course, you can freely +# overwrite any of the functions or variables defined here before +# calling anything to customize them. + +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +# Allow overriding, eg assuming that you follow the convention of +# putting '$debug_cmd' at the start of all your functions, you can get +# bash to show function call trace with: +# +# debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name +debug_cmd=${debug_cmd-":"} +exit_cmd=: + +# By convention, finish your script with: +# +# exit $exit_status +# +# so that you can set exit_status to non-zero if you want to indicate +# something went wrong during execution without actually bailing out at +# the point of failure. +exit_status=$EXIT_SUCCESS + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath=$0 + +# The name of this program. +progname=`$ECHO "$progpath" |$SED "$sed_basename"` + +# Make sure we have an absolute progpath for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` + progdir=`cd "$progdir" && pwd` + progpath=$progdir/$progname + ;; + *) + _G_IFS=$IFS + IFS=${PATH_SEPARATOR-:} + for progdir in $PATH; do + IFS=$_G_IFS + test -x "$progdir/$progname" && break + done + IFS=$_G_IFS + test -n "$progdir" || progdir=`pwd` + progpath=$progdir/$progname + ;; +esac + + +## ----------------- ## +## Standard options. ## +## ----------------- ## + +# The following options affect the operation of the functions defined +# below, and should be set appropriately depending on run-time para- +# meters passed on the command line. + +opt_dry_run=false +opt_quiet=false +opt_verbose=false + +# Categories 'all' and 'none' are always available. Append any others +# you will pass as the first argument to func_warning from your own +# code. +warning_categories= + +# By default, display warnings according to 'opt_warning_types'. Set +# 'warning_func' to ':' to elide all warnings, or func_fatal_error to +# treat the next displayed warning as a fatal error. +warning_func=func_warn_and_continue + +# Set to 'all' to display all warnings, 'none' to suppress all +# warnings, or a space delimited list of some subset of +# 'warning_categories' to display only the listed warnings. +opt_warning_types=all + + +## -------------------- ## +## Resource management. ## +## -------------------- ## + +# This section contains definitions for functions that each ensure a +# particular resource (a file, or a non-empty configuration variable for +# example) is available, and if appropriate to extract default values +# from pertinent package files. Call them using their associated +# 'require_*' variable to ensure that they are executed, at most, once. +# +# It's entirely deliberate that calling these functions can set +# variables that don't obey the namespace limitations obeyed by the rest +# of this file, in order that that they be as useful as possible to +# callers. + + +# require_term_colors +# ------------------- +# Allow display of bold text on terminals that support it. +require_term_colors=func_require_term_colors +func_require_term_colors () +{ + $debug_cmd + + test -t 1 && { + # COLORTERM and USE_ANSI_COLORS environment variables take + # precedence, because most terminfo databases neglect to describe + # whether color sequences are supported. + test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} + + if test 1 = "$USE_ANSI_COLORS"; then + # Standard ANSI escape sequences + tc_reset='' + tc_bold=''; tc_standout='' + tc_red=''; tc_green='' + tc_blue=''; tc_cyan='' + else + # Otherwise trust the terminfo database after all. + test -n "`tput sgr0 2>/dev/null`" && { + tc_reset=`tput sgr0` + test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` + tc_standout=$tc_bold + test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` + test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` + test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` + test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` + test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` + } + fi + } + + require_term_colors=: +} + + +## ----------------- ## +## Function library. ## +## ----------------- ## + +# This section contains a variety of useful functions to call in your +# scripts. Take note of the portable wrappers for features provided by +# some modern shells, which will fall back to slower equivalents on +# less featureful shells. + + +# func_append VAR VALUE +# --------------------- +# Append VALUE onto the existing contents of VAR. + + # We should try to minimise forks, especially on Windows where they are + # unreasonably slow, so skip the feature probes when bash or zsh are + # being used: + if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then + : ${_G_HAVE_ARITH_OP="yes"} + : ${_G_HAVE_XSI_OPS="yes"} + # The += operator was introduced in bash 3.1 + case $BASH_VERSION in + [12].* | 3.0 | 3.0*) ;; + *) + : ${_G_HAVE_PLUSEQ_OP="yes"} + ;; + esac + fi + + # _G_HAVE_PLUSEQ_OP + # Can be empty, in which case the shell is probed, "yes" if += is + # useable or anything else if it does not work. + test -z "$_G_HAVE_PLUSEQ_OP" \ + && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ + && _G_HAVE_PLUSEQ_OP=yes + +if test yes = "$_G_HAVE_PLUSEQ_OP" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_append () + { + $debug_cmd + + eval "$1+=\$2" + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_append () + { + $debug_cmd + + eval "$1=\$$1\$2" + } +fi + + +# func_append_quoted VAR VALUE +# ---------------------------- +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +if test yes = "$_G_HAVE_PLUSEQ_OP"; then + eval 'func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1+=\\ \$func_quote_for_eval_result" + }' +else + func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1=\$$1\\ \$func_quote_for_eval_result" + } +fi + + +# func_append_uniq VAR VALUE +# -------------------------- +# Append unique VALUE onto the existing contents of VAR, assuming +# entries are delimited by the first character of VALUE. For example: +# +# func_append_uniq options " --another-option option-argument" +# +# will only append to $options if " --another-option option-argument " +# is not already present somewhere in $options already (note spaces at +# each end implied by leading space in second argument). +func_append_uniq () +{ + $debug_cmd + + eval _G_current_value='`$ECHO $'$1'`' + _G_delim=`expr "$2" : '\(.\)'` + + case $_G_delim$_G_current_value$_G_delim in + *"$2$_G_delim"*) ;; + *) func_append "$@" ;; + esac +} + + +# func_arith TERM... +# ------------------ +# Set func_arith_result to the result of evaluating TERMs. + test -z "$_G_HAVE_ARITH_OP" \ + && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ + && _G_HAVE_ARITH_OP=yes + +if test yes = "$_G_HAVE_ARITH_OP"; then + eval 'func_arith () + { + $debug_cmd + + func_arith_result=$(( $* )) + }' +else + func_arith () + { + $debug_cmd + + func_arith_result=`expr "$@"` + } +fi + + +# func_basename FILE +# ------------------ +# Set func_basename_result to FILE with everything up to and including +# the last / stripped. +if test yes = "$_G_HAVE_XSI_OPS"; then + # If this shell supports suffix pattern removal, then use it to avoid + # forking. Hide the definitions single quotes in case the shell chokes + # on unsupported syntax... + _b='func_basename_result=${1##*/}' + _d='case $1 in + */*) func_dirname_result=${1%/*}$2 ;; + * ) func_dirname_result=$3 ;; + esac' + +else + # ...otherwise fall back to using sed. + _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' + _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` + if test "X$func_dirname_result" = "X$1"; then + func_dirname_result=$3 + else + func_append func_dirname_result "$2" + fi' +fi + +eval 'func_basename () +{ + $debug_cmd + + '"$_b"' +}' + + +# func_dirname FILE APPEND NONDIR_REPLACEMENT +# ------------------------------------------- +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +eval 'func_dirname () +{ + $debug_cmd + + '"$_d"' +}' + + +# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT +# -------------------------------------------------------- +# Perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# For efficiency, we do not delegate to the functions above but instead +# duplicate the functionality here. +eval 'func_dirname_and_basename () +{ + $debug_cmd + + '"$_b"' + '"$_d"' +}' + + +# func_echo ARG... +# ---------------- +# Echo program name prefixed message. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_echo_all ARG... +# -------------------- +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + + +# func_echo_infix_1 INFIX ARG... +# ------------------------------ +# Echo program name, followed by INFIX on the first line, with any +# additional lines not showing INFIX. +func_echo_infix_1 () +{ + $debug_cmd + + $require_term_colors + + _G_infix=$1; shift + _G_indent=$_G_infix + _G_prefix="$progname: $_G_infix: " + _G_message=$* + + # Strip color escape sequences before counting printable length + for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" + do + test -n "$_G_tc" && { + _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` + _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` + } + done + _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes + + func_echo_infix_1_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_infix_1_IFS + $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 + _G_prefix=$_G_indent + done + IFS=$func_echo_infix_1_IFS +} + + +# func_error ARG... +# ----------------- +# Echo program name prefixed message to standard error. +func_error () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 +} + + +# func_fatal_error ARG... +# ----------------------- +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + $debug_cmd + + func_error "$*" + exit $EXIT_FAILURE +} + + +# func_grep EXPRESSION FILENAME +# ----------------------------- +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $debug_cmd + + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_len STRING +# --------------- +# Set func_len_result to the length of STRING. STRING may not +# start with a hyphen. + test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_len () + { + $debug_cmd + + func_len_result=${#1} + }' +else + func_len () + { + $debug_cmd + + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` + } +fi + + +# func_mkdir_p DIRECTORY-PATH +# --------------------------- +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + $debug_cmd + + _G_directory_path=$1 + _G_dir_list= + + if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then + + # Protect directory names starting with '-' + case $_G_directory_path in + -*) _G_directory_path=./$_G_directory_path ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$_G_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + _G_dir_list=$_G_directory_path:$_G_dir_list + + # If the last portion added has no slash in it, the list is done + case $_G_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` + done + _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` + + func_mkdir_p_IFS=$IFS; IFS=: + for _G_dir in $_G_dir_list; do + IFS=$func_mkdir_p_IFS + # mkdir can fail with a 'File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$_G_dir" 2>/dev/null || : + done + IFS=$func_mkdir_p_IFS + + # Bail out if we (or some other process) failed to create a directory. + test -d "$_G_directory_path" || \ + func_fatal_error "Failed to create '$1'" + fi +} + + +# func_mktempdir [BASENAME] +# ------------------------- +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, BASENAME is the basename for that directory. +func_mktempdir () +{ + $debug_cmd + + _G_template=${TMPDIR-/tmp}/${1-$progname} + + if test : = "$opt_dry_run"; then + # Return a directory name, but don't create it in dry-run mode + _G_tmpdir=$_G_template-$$ + else + + # If mktemp works, use that first and foremost + _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` + + if test ! -d "$_G_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + _G_tmpdir=$_G_template-${RANDOM-0}$$ + + func_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$_G_tmpdir" + umask $func_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$_G_tmpdir" || \ + func_fatal_error "cannot create temporary directory '$_G_tmpdir'" + fi + + $ECHO "$_G_tmpdir" +} + + +# func_normal_abspath PATH +# ------------------------ +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +func_normal_abspath () +{ + $debug_cmd + + # These SED scripts presuppose an absolute path with a trailing slash. + _G_pathcar='s|^/\([^/]*\).*$|\1|' + _G_pathcdr='s|^/[^/]*||' + _G_removedotparts=':dotsl + s|/\./|/|g + t dotsl + s|/\.$|/|' + _G_collapseslashes='s|/\{1,\}|/|g' + _G_finalslash='s|/*$|/|' + + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` + while :; do + # Processed it all yet? + if test / = "$func_normal_abspath_tpath"; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result"; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + + +# func_notquiet ARG... +# -------------------- +# Echo program name prefixed message only when not in quiet mode. +func_notquiet () +{ + $debug_cmd + + $opt_quiet || func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + + +# func_relative_path SRCDIR DSTDIR +# -------------------------------- +# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. +func_relative_path () +{ + $debug_cmd + + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=$func_dirname_result + if test -z "$func_relative_path_tlibdir"; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test -n "$func_stripname_result"; then + func_append func_relative_path_result "/$func_stripname_result" + fi + + # Normalisation. If bindir is libdir, return '.' else relative path. + if test -n "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + fi + + test -n "$func_relative_path_result" || func_relative_path_result=. + + : +} + + +# func_quote_for_eval ARG... +# -------------------------- +# Aesthetically quote ARGs to be evaled later. +# This function returns two values: +# i) func_quote_for_eval_result +# double-quoted, suitable for a subsequent eval +# ii) func_quote_for_eval_unquoted_result +# has all characters that are still active within double +# quotes backslashified. +func_quote_for_eval () +{ + $debug_cmd + + func_quote_for_eval_unquoted_result= + func_quote_for_eval_result= + while test 0 -lt $#; do + case $1 in + *[\\\`\"\$]*) + _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; + *) + _G_unquoted_arg=$1 ;; + esac + if test -n "$func_quote_for_eval_unquoted_result"; then + func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" + else + func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" + fi + + case $_G_unquoted_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and variable expansion + # for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_quoted_arg=\"$_G_unquoted_arg\" + ;; + *) + _G_quoted_arg=$_G_unquoted_arg + ;; + esac + + if test -n "$func_quote_for_eval_result"; then + func_append func_quote_for_eval_result " $_G_quoted_arg" + else + func_append func_quote_for_eval_result "$_G_quoted_arg" + fi + shift + done +} + + +# func_quote_for_expand ARG +# ------------------------- +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + $debug_cmd + + case $1 in + *[\\\`\"]*) + _G_arg=`$ECHO "$1" | $SED \ + -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; + *) + _G_arg=$1 ;; + esac + + case $_G_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_arg=\"$_G_arg\" + ;; + esac + + func_quote_for_expand_result=$_G_arg +} + + +# func_stripname PREFIX SUFFIX NAME +# --------------------------------- +# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_stripname () + { + $debug_cmd + + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary variable first. + func_stripname_result=$3 + func_stripname_result=${func_stripname_result#"$1"} + func_stripname_result=${func_stripname_result%"$2"} + }' +else + func_stripname () + { + $debug_cmd + + case $2 in + .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; + *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; + esac + } +fi + + +# func_show_eval CMD [FAIL_EXP] +# ----------------------------- +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + func_quote_for_expand "$_G_cmd" + eval "func_notquiet $func_quote_for_expand_result" + + $opt_dry_run || { + eval "$_G_cmd" + _G_status=$? + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_show_eval_locale CMD [FAIL_EXP] +# ------------------------------------ +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + $opt_quiet || { + func_quote_for_expand "$_G_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + $opt_dry_run || { + eval "$_G_user_locale + $_G_cmd" + _G_status=$? + eval "$_G_safe_locale" + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_tr_sh +# ---------- +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + $debug_cmd + + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_verbose ARG... +# ------------------- +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $debug_cmd + + $opt_verbose && func_echo "$*" + + : +} + + +# func_warn_and_continue ARG... +# ----------------------------- +# Echo program name prefixed warning message to standard error. +func_warn_and_continue () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 +} + + +# func_warning CATEGORY ARG... +# ---------------------------- +# Echo program name prefixed warning message to standard error. Warning +# messages can be filtered according to CATEGORY, where this function +# elides messages where CATEGORY is not listed in the global variable +# 'opt_warning_types'. +func_warning () +{ + $debug_cmd + + # CATEGORY must be in the warning_categories list! + case " $warning_categories " in + *" $1 "*) ;; + *) func_internal_error "invalid warning category '$1'" ;; + esac + + _G_category=$1 + shift + + case " $opt_warning_types " in + *" $_G_category "*) $warning_func ${1+"$@"} ;; + esac +} + + +# func_sort_ver VER1 VER2 +# ----------------------- +# 'sort -V' is not generally available. +# Note this deviates from the version comparison in automake +# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a +# but this should suffice as we won't be specifying old +# version formats or redundant trailing .0 in bootstrap.conf. +# If we did want full compatibility then we should probably +# use m4_version_compare from autoconf. +func_sort_ver () +{ + $debug_cmd + + printf '%s\n%s\n' "$1" "$2" \ + | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n +} + +# func_lt_ver PREV CURR +# --------------------- +# Return true if PREV and CURR are in the correct order according to +# func_sort_ver, otherwise false. Use it like this: +# +# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." +func_lt_ver () +{ + $debug_cmd + + test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: +#! /bin/sh + +# Set a version string for this script. +scriptversion=2014-01-07.03; # UTC + +# A portable, pluggable option parser for Bourne shell. +# Written by Gary V. Vaughan, 2010 + +# Copyright (C) 2010-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program 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 General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# This file is a library for parsing options in your shell scripts along +# with assorted other useful supporting features that you can make use +# of too. +# +# For the simplest scripts you might need only: +# +# #!/bin/sh +# . relative/path/to/funclib.sh +# . relative/path/to/options-parser +# scriptversion=1.0 +# func_options ${1+"$@"} +# eval set dummy "$func_options_result"; shift +# ...rest of your script... +# +# In order for the '--version' option to work, you will need to have a +# suitably formatted comment like the one at the top of this file +# starting with '# Written by ' and ending with '# warranty; '. +# +# For '-h' and '--help' to work, you will also need a one line +# description of your script's purpose in a comment directly above the +# '# Written by ' line, like the one at the top of this file. +# +# The default options also support '--debug', which will turn on shell +# execution tracing (see the comment above debug_cmd below for another +# use), and '--verbose' and the func_verbose function to allow your script +# to display verbose messages only when your user has specified +# '--verbose'. +# +# After sourcing this file, you can plug processing for additional +# options by amending the variables from the 'Configuration' section +# below, and following the instructions in the 'Option parsing' +# section further down. + +## -------------- ## +## Configuration. ## +## -------------- ## + +# You should override these variables in your script after sourcing this +# file so that they reflect the customisations you have added to the +# option parser. + +# The usage line for option parsing errors and the start of '-h' and +# '--help' output messages. You can embed shell variables for delayed +# expansion at the time the message is displayed, but you will need to +# quote other shell meta-characters carefully to prevent them being +# expanded when the contents are evaled. +usage='$progpath [OPTION]...' + +# Short help message in response to '-h' and '--help'. Add to this or +# override it after sourcing this library to reflect the full set of +# options your script accepts. +usage_message="\ + --debug enable verbose shell tracing + -W, --warnings=CATEGORY + report the warnings falling in CATEGORY [all] + -v, --verbose verbosely report processing + --version print version information and exit + -h, --help print short or long help message and exit +" + +# Additional text appended to 'usage_message' in response to '--help'. +long_help_message=" +Warning categories include: + 'all' show all warnings + 'none' turn off all the warnings + 'error' warnings are treated as fatal errors" + +# Help message printed before fatal option parsing errors. +fatal_help="Try '\$progname --help' for more information." + + + +## ------------------------- ## +## Hook function management. ## +## ------------------------- ## + +# This section contains functions for adding, removing, and running hooks +# to the main code. A hook is just a named list of of function, that can +# be run in order later on. + +# func_hookable FUNC_NAME +# ----------------------- +# Declare that FUNC_NAME will run hooks added with +# 'func_add_hook FUNC_NAME ...'. +func_hookable () +{ + $debug_cmd + + func_append hookable_fns " $1" +} + + +# func_add_hook FUNC_NAME HOOK_FUNC +# --------------------------------- +# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must +# first have been declared "hookable" by a call to 'func_hookable'. +func_add_hook () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not accept hook functions." ;; + esac + + eval func_append ${1}_hooks '" $2"' +} + + +# func_remove_hook FUNC_NAME HOOK_FUNC +# ------------------------------------ +# Remove HOOK_FUNC from the list of functions called by FUNC_NAME. +func_remove_hook () +{ + $debug_cmd + + eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' +} + + +# func_run_hooks FUNC_NAME [ARG]... +# --------------------------------- +# Run all hook functions registered to FUNC_NAME. +# It is assumed that the list of hook functions contains nothing more +# than a whitespace-delimited list of legal shell function names, and +# no effort is wasted trying to catch shell meta-characters or preserve +# whitespace. +func_run_hooks () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not support hook funcions.n" ;; + esac + + eval _G_hook_fns=\$$1_hooks; shift + + for _G_hook in $_G_hook_fns; do + eval $_G_hook '"$@"' + + # store returned options list back into positional + # parameters for next 'cmd' execution. + eval _G_hook_result=\$${_G_hook}_result + eval set dummy "$_G_hook_result"; shift + done + + func_quote_for_eval ${1+"$@"} + func_run_hooks_result=$func_quote_for_eval_result +} + + + +## --------------- ## +## Option parsing. ## +## --------------- ## + +# In order to add your own option parsing hooks, you must accept the +# full positional parameter list in your hook function, remove any +# options that you action, and then pass back the remaining unprocessed +# options in '_result', escaped suitably for +# 'eval'. Like this: +# +# my_options_prep () +# { +# $debug_cmd +# +# # Extend the existing usage message. +# usage_message=$usage_message' +# -s, --silent don'\''t print informational messages +# ' +# +# func_quote_for_eval ${1+"$@"} +# my_options_prep_result=$func_quote_for_eval_result +# } +# func_add_hook func_options_prep my_options_prep +# +# +# my_silent_option () +# { +# $debug_cmd +# +# # Note that for efficiency, we parse as many options as we can +# # recognise in a loop before passing the remainder back to the +# # caller on the first unrecognised argument we encounter. +# while test $# -gt 0; do +# opt=$1; shift +# case $opt in +# --silent|-s) opt_silent=: ;; +# # Separate non-argument short options: +# -s*) func_split_short_opt "$_G_opt" +# set dummy "$func_split_short_opt_name" \ +# "-$func_split_short_opt_arg" ${1+"$@"} +# shift +# ;; +# *) set dummy "$_G_opt" "$*"; shift; break ;; +# esac +# done +# +# func_quote_for_eval ${1+"$@"} +# my_silent_option_result=$func_quote_for_eval_result +# } +# func_add_hook func_parse_options my_silent_option +# +# +# my_option_validation () +# { +# $debug_cmd +# +# $opt_silent && $opt_verbose && func_fatal_help "\ +# '--silent' and '--verbose' options are mutually exclusive." +# +# func_quote_for_eval ${1+"$@"} +# my_option_validation_result=$func_quote_for_eval_result +# } +# func_add_hook func_validate_options my_option_validation +# +# You'll alse need to manually amend $usage_message to reflect the extra +# options you parse. It's preferable to append if you can, so that +# multiple option parsing hooks can be added safely. + + +# func_options [ARG]... +# --------------------- +# All the functions called inside func_options are hookable. See the +# individual implementations for details. +func_hookable func_options +func_options () +{ + $debug_cmd + + func_options_prep ${1+"$@"} + eval func_parse_options \ + ${func_options_prep_result+"$func_options_prep_result"} + eval func_validate_options \ + ${func_parse_options_result+"$func_parse_options_result"} + + eval func_run_hooks func_options \ + ${func_validate_options_result+"$func_validate_options_result"} + + # save modified positional parameters for caller + func_options_result=$func_run_hooks_result +} + + +# func_options_prep [ARG]... +# -------------------------- +# All initialisations required before starting the option parse loop. +# Note that when calling hook functions, we pass through the list of +# positional parameters. If a hook function modifies that list, and +# needs to propogate that back to rest of this script, then the complete +# modified list must be put in 'func_run_hooks_result' before +# returning. +func_hookable func_options_prep +func_options_prep () +{ + $debug_cmd + + # Option defaults: + opt_verbose=false + opt_warning_types= + + func_run_hooks func_options_prep ${1+"$@"} + + # save modified positional parameters for caller + func_options_prep_result=$func_run_hooks_result +} + + +# func_parse_options [ARG]... +# --------------------------- +# The main option parsing loop. +func_hookable func_parse_options +func_parse_options () +{ + $debug_cmd + + func_parse_options_result= + + # this just eases exit handling + while test $# -gt 0; do + # Defer to hook functions for initial option parsing, so they + # get priority in the event of reusing an option name. + func_run_hooks func_parse_options ${1+"$@"} + + # Adjust func_parse_options positional parameters to match + eval set dummy "$func_run_hooks_result"; shift + + # Break out of the loop if we already parsed every option. + test $# -gt 0 || break + + _G_opt=$1 + shift + case $_G_opt in + --debug|-x) debug_cmd='set -x' + func_echo "enabling shell trace mode" + $debug_cmd + ;; + + --no-warnings|--no-warning|--no-warn) + set dummy --warnings none ${1+"$@"} + shift + ;; + + --warnings|--warning|-W) + test $# = 0 && func_missing_arg $_G_opt && break + case " $warning_categories $1" in + *" $1 "*) + # trailing space prevents matching last $1 above + func_append_uniq opt_warning_types " $1" + ;; + *all) + opt_warning_types=$warning_categories + ;; + *none) + opt_warning_types=none + warning_func=: + ;; + *error) + opt_warning_types=$warning_categories + warning_func=func_fatal_error + ;; + *) + func_fatal_error \ + "unsupported warning category: '$1'" + ;; + esac + shift + ;; + + --verbose|-v) opt_verbose=: ;; + --version) func_version ;; + -\?|-h) func_usage ;; + --help) func_help ;; + + # Separate optargs to long options (plugins may need this): + --*=*) func_split_equals "$_G_opt" + set dummy "$func_split_equals_lhs" \ + "$func_split_equals_rhs" ${1+"$@"} + shift + ;; + + # Separate optargs to short options: + -W*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-v*|-x*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) break ;; + -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + esac + done + + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + func_parse_options_result=$func_quote_for_eval_result +} + + +# func_validate_options [ARG]... +# ------------------------------ +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +func_hookable func_validate_options +func_validate_options () +{ + $debug_cmd + + # Display all warnings if -W was not given. + test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" + + func_run_hooks func_validate_options ${1+"$@"} + + # Bail if the options were screwed! + $exit_cmd $EXIT_FAILURE + + # save modified positional parameters for caller + func_validate_options_result=$func_run_hooks_result +} + + + +## ----------------- ## +## Helper functions. ## +## ----------------- ## + +# This section contains the helper functions used by the rest of the +# hookable option parser framework in ascii-betical order. + + +# func_fatal_help ARG... +# ---------------------- +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + eval \$ECHO \""$fatal_help"\" + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + + +# func_help +# --------- +# Echo long help message to standard output and exit. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message" + exit 0 +} + + +# func_missing_arg ARGNAME +# ------------------------ +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $debug_cmd + + func_error "Missing argument for '$1'." + exit_cmd=exit +} + + +# func_split_equals STRING +# ------------------------ +# Set func_split_equals_lhs and func_split_equals_rhs shell variables after +# splitting STRING at the '=' sign. +test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=${1%%=*} + func_split_equals_rhs=${1#*=} + test "x$func_split_equals_lhs" = "x$1" \ + && func_split_equals_rhs= + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` + func_split_equals_rhs= + test "x$func_split_equals_lhs" = "x$1" \ + || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` + } +fi #func_split_equals + + +# func_split_short_opt SHORTOPT +# ----------------------------- +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"} + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` + func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` + } +fi #func_split_short_opt + + +# func_usage +# ---------- +# Echo short help message to standard output and exit. +func_usage () +{ + $debug_cmd + + func_usage_message + $ECHO "Run '$progname --help |${PAGER-more}' for full usage" + exit 0 +} + + +# func_usage_message +# ------------------ +# Echo short help message to standard output. +func_usage_message () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + echo + $SED -n 's|^# || + /^Written by/{ + x;p;x + } + h + /^Written by/q' < "$progpath" + echo + eval \$ECHO \""$usage_message"\" +} + + +# func_version +# ------------ +# Echo version message to standard output and exit. +func_version () +{ + $debug_cmd + + printf '%s\n' "$progname $scriptversion" + $SED -n ' + /(C)/!b go + :more + /\./!{ + N + s|\n# | | + b more + } + :go + /^# Written by /,/# warranty; / { + s|^# || + s|^# *$|| + s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| + p + } + /^# Written by / { + s|^# || + p + } + /^warranty; /q' < "$progpath" + + exit $? +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: + +# Set a version string. +scriptversion='(GNU libtool) 2.4.6' + + +# func_echo ARG... +# ---------------- +# Libtool also displays the current mode in messages, so override +# funclib.sh func_echo with this custom definition. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_warning ARG... +# ------------------- +# Libtool warnings are not categorized, so override funclib.sh +# func_warning with this simpler definition. +func_warning () +{ + $debug_cmd + + $warning_func ${1+"$@"} +} + + +## ---------------- ## +## Options parsing. ## +## ---------------- ## + +# Hook in the functions to make sure our own options are parsed during +# the option parsing loop. + +usage='$progpath [OPTION]... [MODE-ARG]...' + +# Short help message in response to '-h'. +usage_message="Options: + --config show all configuration variables + --debug enable verbose shell tracing + -n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --mode=MODE use operation mode MODE + --no-warnings equivalent to '-Wnone' + --preserve-dup-deps don't remove duplicate dependency libraries + --quiet, --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + -v, --verbose print more informational messages than default + --version print version information + -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] + -h, --help, --help-all print short, long, or detailed help message +" + +# Additional text appended to 'usage_message' in response to '--help'. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. When passed as first option, +'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. +Try '$progname --help --mode=MODE' for a more detailed description of MODE. + +When reporting a bug, please describe a test case to reproduce it and +include the following information: + + host-triplet: $host + shell: $SHELL + compiler: $LTCC + compiler flags: $LTCFLAGS + linker: $LD (gnu? $with_gnu_ld) + version: $progname (GNU libtool) 2.4.6 + automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` + autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` + +Report bugs to . +GNU libtool home page: . +General help using GNU software: ." + exit 0 +} + + +# func_lo2o OBJECT-NAME +# --------------------- +# Transform OBJECT-NAME from a '.lo' suffix to the platform specific +# object suffix. + +lo2o=s/\\.lo\$/.$objext/ +o2lo=s/\\.$objext\$/.lo/ + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_lo2o () + { + case $1 in + *.lo) func_lo2o_result=${1%.lo}.$objext ;; + * ) func_lo2o_result=$1 ;; + esac + }' + + # func_xform LIBOBJ-OR-SOURCE + # --------------------------- + # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) + # suffix to a '.lo' libtool-object suffix. + eval 'func_xform () + { + func_xform_result=${1%.*}.lo + }' +else + # ...otherwise fall back to using sed. + func_lo2o () + { + func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` + } + + func_xform () + { + func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` + } +fi + + +# func_fatal_configuration ARG... +# ------------------------------- +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func__fatal_error ${1+"$@"} \ + "See the $PACKAGE documentation for more information." \ + "Fatal configuration error." +} + + +# func_config +# ----------- +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + + +# func_features +# ------------- +# Display the features supported by this script. +func_features () +{ + echo "host: $host" + if test yes = "$build_libtool_libs"; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test yes = "$build_old_libs"; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + + exit $? +} + + +# func_enable_tag TAGNAME +# ----------------------- +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname=$1 + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf=/$re_begincf/,/$re_endcf/p + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + + +# func_check_version_match +# ------------------------ +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# libtool_options_prep [ARG]... +# ----------------------------- +# Preparation for options parsed by libtool. +libtool_options_prep () +{ + $debug_mode + + # Option defaults: + opt_config=false + opt_dlopen= + opt_dry_run=false + opt_help=false + opt_mode= + opt_preserve_dup_deps=false + opt_quiet=false + + nonopt= + preserve_args= + + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; + esac + + # Pass back the list of options. + func_quote_for_eval ${1+"$@"} + libtool_options_prep_result=$func_quote_for_eval_result +} +func_add_hook func_options_prep libtool_options_prep + + +# libtool_parse_options [ARG]... +# --------------------------------- +# Provide handling for libtool specific options. +libtool_parse_options () +{ + $debug_cmd + + # Perform our own loop to consume as many options as possible in + # each iteration. + while test $# -gt 0; do + _G_opt=$1 + shift + case $_G_opt in + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + + --config) func_config ;; + + --dlopen|-dlopen) + opt_dlopen="${opt_dlopen+$opt_dlopen +}$1" + shift + ;; + + --preserve-dup-deps) + opt_preserve_dup_deps=: ;; + + --features) func_features ;; + + --finish) set dummy --mode finish ${1+"$@"}; shift ;; + + --help) opt_help=: ;; + + --help-all) opt_help=': help-all' ;; + + --mode) test $# = 0 && func_missing_arg $_G_opt && break + opt_mode=$1 + case $1 in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $_G_opt" + exit_cmd=exit + break + ;; + esac + shift + ;; + + --no-silent|--no-quiet) + opt_quiet=false + func_append preserve_args " $_G_opt" + ;; + + --no-warnings|--no-warning|--no-warn) + opt_warning=false + func_append preserve_args " $_G_opt" + ;; + + --no-verbose) + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --silent|--quiet) + opt_quiet=: + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --tag) test $# = 0 && func_missing_arg $_G_opt && break + opt_tag=$1 + func_append preserve_args " $_G_opt $1" + func_enable_tag "$1" + shift + ;; + + --verbose|-v) opt_quiet=false + opt_verbose=: + func_append preserve_args " $_G_opt" + ;; + + # An option not handled by this hook function: + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + esac + done + + + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + libtool_parse_options_result=$func_quote_for_eval_result +} +func_add_hook func_parse_options libtool_parse_options + + + +# libtool_validate_options [ARG]... +# --------------------------------- +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +libtool_validate_options () +{ + # save first non-option argument + if test 0 -lt $#; then + nonopt=$1 + shift + fi + + # preserve --debug + test : = "$debug_cmd" || func_append preserve_args " --debug" + + case $host in + # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 + # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 + *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + test yes != "$build_libtool_libs" \ + && test yes != "$build_old_libs" \ + && func_fatal_configuration "not configured to build any kind of library" + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test execute != "$opt_mode"; then + func_error "unrecognized option '-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help=$help + help="Try '$progname --help --mode=$opt_mode' for more information." + } + + # Pass back the unparsed argument list + func_quote_for_eval ${1+"$@"} + libtool_validate_options_result=$func_quote_for_eval_result +} +func_add_hook func_validate_options libtool_validate_options + + +# Process options as early as possible so that --help and --version +# can return quickly. +func_options ${1+"$@"} +eval set dummy "$func_options_result"; shift + + + +## ----------- ## +## Main. ## +## ----------- ## + +magic='%%%MAGIC variable%%%' +magic_exe='%%%MAGIC EXE variable%%%' + +# Global variables. +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# func_generated_by_libtool +# True iff stdin has been generated by Libtool. This function is only +# a basic sanity check; it will hardly flush out determined imposters. +func_generated_by_libtool_p () +{ + $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if 'file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case $lalib_p_line in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test yes = "$lalib_p" +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + test -f "$1" && + $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $debug_cmd + + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# 'FILE.' does not work on cygwin managed mounts. +func_source () +{ + $debug_cmd + + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case $lt_sysroot:$1 in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result='='$func_stripname_result + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $debug_cmd + + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with '--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=$1 + if test yes = "$build_libtool_libs"; then + write_lobj=\'$2\' + else + write_lobj=none + fi + + if test yes = "$build_old_libs"; then + write_oldobj=\'$3\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T </dev/null` + if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $debug_cmd + + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result= + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result"; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $debug_cmd + + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $debug_cmd + + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $debug_cmd + + if test -z "$2" && test -n "$1"; then + func_error "Could not determine host file name corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result=$1 + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $debug_cmd + + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " '$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result=$3 + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $debug_cmd + + case $4 in + $1 ) func_to_host_path_result=$3$func_to_host_path_result + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via '$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $debug_cmd + + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $debug_cmd + + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result=$1 +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result=$func_convert_core_msys_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result=$func_convert_core_file_wine_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via '$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $debug_cmd + + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd=func_convert_path_$func_stripname_result + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $debug_cmd + + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result=$1 +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_msys_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_path_wine_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_dll_def_p FILE +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with _LT_DLL_DEF_P in libtool.m4 +func_dll_def_p () +{ + $debug_cmd + + func_dll_def_p_tmp=`$SED -n \ + -e 's/^[ ]*//' \ + -e '/^\(;.*\)*$/d' \ + -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ + -e q \ + "$1"` + test DEF = "$func_dll_def_p_tmp" +} + + +# func_mode_compile arg... +func_mode_compile () +{ + $debug_cmd + + # Get the compilation command and the source file. + base_compile= + srcfile=$nonopt # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg=$arg + arg_mode=normal + ;; + + target ) + libobj=$arg + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify '-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append later " $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs=$IFS; IFS=, + for arg in $args; do + IFS=$save_ifs + func_append_quoted lastarg "$arg" + done + IFS=$save_ifs + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append base_compile " $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg=$srcfile + srcfile=$arg + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with '-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj=$func_basename_result + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from '$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test yes = "$build_libtool_libs" \ + || func_fatal_configuration "cannot build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_for_eval "$libobj" + test "X$libobj" != "X$func_quote_for_eval_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name '$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname=$func_basename_result + xdir=$func_dirname_result + lobj=$xdir$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test yes = "$build_old_libs"; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test no = "$compiler_c_o"; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext + lockfile=$output_obj.lock + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test yes = "$need_locks"; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test warn = "$need_locks"; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test yes = "$build_libtool_libs"; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test no != "$pic_mode"; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test yes = "$suppress_opt"; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test yes = "$build_old_libs"; then + if test yes != "$pic_mode"; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test yes = "$compiler_c_o"; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test no != "$need_locks"; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test compile = "$opt_mode" && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a '.o' file suitable for static linking + -static only build a '.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +COMPILE-COMMAND is a command to be used in creating a 'standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix '.c' with the +library object suffix, '.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to '-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the '--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the 'install' or 'cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE use a list of object files found in FILE to specify objects + -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +All other options (arguments beginning with '-') are ignored. + +Every other argument is treated as a filename. Files ending in '.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in '.la', then a libtool library is created, +only library objects ('.lo' files) may be specified, and '-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created +using 'ar' and 'ranlib', or on Windows using 'lib'. + +If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode '$opt_mode'" + ;; + esac + + echo + $ECHO "Try '$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test : = "$opt_help"; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | $SED -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + $SED '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $debug_cmd + + # The first argument is the command name. + cmd=$nonopt + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "'$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "'$file' was not linked with '-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir=$func_dirname_result + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir=$func_dirname_result + ;; + + *) + func_warning "'-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir=$absdir + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic=$magic + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file=$progdir/$program + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file=$progdir/$program + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if $opt_dry_run; then + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + else + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd=\$cmd$args + fi +} + +test execute = "$opt_mode" && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $debug_cmd + + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "'$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument '$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and '=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_quiet && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the '-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the '$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the '$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the '$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" + fi + echo + + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test finish = "$opt_mode" && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $debug_cmd + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || + # Allow the use of GNU shtool's install command. + case $nonopt in *shtool*) :;; *) false;; esac + then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + func_append install_prog "$func_quote_for_eval_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=false + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=: ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test X-m = "X$prev" && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + func_append install_prog " $func_quote_for_eval_result" + if test -n "$arg2"; then + func_quote_for_eval "$arg2" + fi + func_append install_shared_prog " $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the '$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_for_eval "$install_override_mode" + func_append install_shared_prog " -m $func_quote_for_eval_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=: + if $isdir; then + destdir=$dest + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir=$func_dirname_result + destname=$func_basename_result + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "'$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "'$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir=$func_dirname_result + func_append dir "$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking '$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname=$1 + shift + + srcname=$realname + test -n "$relink_command" && srcname=${realname}T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme=$stripme + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme= + ;; + esac + ;; + os2*) + case $realname in + *_dll.a) + tstripme= + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try 'ln -sf' first, because the 'ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib=$destdir/$realname + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name=$func_basename_result + instname=$dir/${name}i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append staticlibs " $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest=$destfile + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to '$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test yes = "$build_old_libs"; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext= + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=.exe + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script '$wrapper'" + + finalize=: + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "'$lib' has not been installed in '$libdir'" + finalize=false + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test no = "$fast_install" && test -n "$relink_command"; then + $opt_dry_run || { + if $finalize; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file=$func_basename_result + outputname=$tmpdir/$file + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_quiet || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink '$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file=$outputname + else + func_warning "cannot relink '$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name=$func_basename_result + + # Set up the ranlib parameters. + oldlib=$destdir/$name + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $tool_oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run '$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test install = "$opt_mode" && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $debug_cmd + + my_outputname=$1 + my_originator=$2 + my_pic_p=${3-false} + my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms=${my_outputname}S.c + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist=$output_objdir/$my_outputname.nm + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* External symbol declarations for the compiler. */\ +" + + if test yes = "$dlself"; then + func_verbose "generating symbol list for '$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from '$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols=$output_objdir/$outputname.exp + $opt_dry_run || { + $RM $export_symbols + eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from '$dlprefile'" + func_basename "$dlprefile" + name=$func_basename_result + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename= + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname"; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename=$func_basename_result + else + # no lafile. user explicitly requested -dlpreopen . + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename"; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + func_show_eval '$RM "${nlist}I"' + if test -n "$global_symbol_to_import"; then + eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[];\ +" + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ +static void lt_syminit(void) +{ + LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; + for (; symbol->name; ++symbol) + {" + $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" + echo >> "$output_objdir/$my_dlsyms" "\ + } +}" + fi + echo >> "$output_objdir/$my_dlsyms" "\ +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{ {\"$my_originator\", (void *) 0}," + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ + {\"@INIT@\", (void *) <_syminit}," + fi + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + $my_pic_p && pic_flag_for_symtable=" $pic_flag" + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' + + # Transform the symbol file into the correct name. + symfileobj=$output_objdir/${my_outputname}S.$objext + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for '$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $debug_cmd + + win32_libid_type=unknown + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + case $nm_interface in + "MS dumpbin") + if func_cygming_ms_implib_p "$1" || + func_cygming_gnu_implib_p "$1" + then + win32_nmres=import + else + win32_nmres= + fi + ;; + *) + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' + 1,100{ + / I /{ + s|.*|import| + p + q + } + }'` + ;; + esac + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $debug_cmd + + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $debug_cmd + + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive that possess that section. Heuristic: eliminate + # all those that have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $debug_cmd + + if func_cygming_gnu_implib_p "$1"; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1"; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result= + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $debug_cmd + + f_ex_an_ar_dir=$1; shift + f_ex_an_ar_oldlib=$1 + if test yes = "$lock_old_archive_extraction"; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test yes = "$lock_old_archive_extraction"; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $debug_cmd + + my_gentop=$1; shift + my_oldlibs=${1+"$@"} + my_oldobjs= + my_xlib= + my_xabs= + my_xdir= + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib=$func_basename_result + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir=$my_gentop/$my_xlib_u + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + func_basename "$darwin_archive" + darwin_base_archive=$func_basename_result + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches; do + func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" + $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" + cd "unfat-$$/$darwin_base_archive-$darwin_arch" + func_extract_an_archive "`pwd`" "$darwin_base_archive" + cd "$darwin_curdir" + $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result=$my_oldobjs +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory where it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + file=\"\$0\"" + + qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=\"$qECHO\" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case \" \$* \" in + *\\ --lt-*) + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done ;; + esac + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test yes = "$fast_install"; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + \$ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +#else +# include +# include +# ifdef __CYGWIN__ +# include +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* declarations of non-ANSI functions */ +#if defined __MINGW32__ +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined __CYGWIN__ +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined other_platform || defined ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined _MSC_VER +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +#elif defined __MINGW32__ +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined __CYGWIN__ +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined other platforms ... */ +#endif + +#if defined PATH_MAX +# define LT_PATHMAX PATH_MAX +#elif defined MAXPATHLEN +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ + defined __OS2__ +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free (stale); stale = 0; } \ +} while (0) + +#if defined LT_DEBUGWRAPPER +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + size_t tmp_len; + char *concat_name; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined HAVE_DOS_BASED_FILE_SYSTEM + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined HAVE_DOS_BASED_FILE_SYSTEM + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = (size_t) (q - p); + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (STREQ (str, pat)) + *str = '\0'; + } + return str; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + size_t len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + size_t orig_value_len = strlen (orig_value); + size_t add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + size_t len = strlen (new_value); + while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[--len] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -n -e ' +s/^\(.\{79\}\)\(..*\)/\1\ +\2/ +h +s/\([\\"]\)/\\\1/g +s/$/\\n/ +s/\([^\n]*\).*/ fputs ("\1", f);/p +g +D' + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $debug_cmd + + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_suncc_cstd_abi +# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! +# Several compiler flags select an ABI that is incompatible with the +# Cstd library. Avoid specifying it if any are in CXXFLAGS. +func_suncc_cstd_abi () +{ + $debug_cmd + + case " $compile_command " in + *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) + suncc_use_cstd_abi=no + ;; + *) + suncc_use_cstd_abi=yes + ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $debug_cmd + + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # what system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll that has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + os2dllname= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=false + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module=$wl-single_module + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test yes != "$build_libtool_libs" \ + && func_fatal_configuration "cannot build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg=$1 + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir=$arg + prev= + continue + ;; + dlfiles|dlprefiles) + $preload || { + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=: + } + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test no = "$dlself"; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test dlprefiles = "$prev"; then + dlself=yes + elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test dlfiles = "$prev"; then + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols=$arg + test -f "$arg" \ + || func_fatal_error "symbol file '$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex=$arg + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir=$arg + prev= + continue + ;; + mllvm) + # Clang does not use LLVM to link, so we can simply discard any + # '-mllvm $arg' options when doing the link step. + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + if test none != "$pic_object"; then + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + fi + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file '$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + os2dllname) + os2dllname=$arg + prev= + continue + ;; + precious_regex) + precious_files_regex=$arg + prev= + continue + ;; + release) + release=-$arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test rpath = "$prev"; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds=$arg + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg=$arg + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "'-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test X-export-symbols = "X$arg"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between '-L' and '$1'" + else + func_fatal_error "need path for '-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of '$dir'" + dir=$absdir + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test X-lc = "X$arg" || test X-lm = "X$arg"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test X-lc = "X$arg" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc due to us having libc/libc_r. + test X-lc = "X$arg" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + func_append deplibs " System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test X-lc = "X$arg" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test X-lc = "X$arg" && continue + ;; + esac + elif test X-lc_r = "X$arg"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + func_append deplibs " $arg" + continue + ;; + + -mllvm) + prev=mllvm + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module=$wl-multi_module + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "'-no-install' is ignored for $host" + func_warning "assuming '-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -os2dllname) + prev=os2dllname + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $func_quote_for_eval_result" + func_append compiler_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $wl$func_quote_for_eval_result" + func_append compiler_flags " $wl$func_quote_for_eval_result" + func_append linker_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # -fstack-protector* stack protector flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -stdlib=* select c++ std lib with clang + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + -Z*) + if test os2 = "`expr $host : '.*\(os2\)'`"; then + # OS/2 uses -Zxxx to specify OS/2-specific options + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case $arg in + -Zlinker | -Zstack) + prev=xcompiler + ;; + esac + continue + else + # Otherwise treat like 'Some other compiler flag' below + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + fi + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + test none = "$pic_object" || { + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + } + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test dlfiles = "$prev"; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test dlprefiles = "$prev"; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the '$prevarg' option requires an argument" + + if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname=$func_basename_result + libobjs_save=$libobjs + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + # Definition is injected by LT_CONFIG during libtool generation. + func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" + + func_dirname "$output" "/" "" + output_objdir=$func_dirname_result$objdir + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_preserve_dup_deps; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append libs " $deplib" + done + + if test lib = "$linkmode"; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append pre_post_deps " $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=false + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test lib,link = "$linkmode,$pass"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs=$tmp_deplibs + fi + + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass"; then + libs=$deplibs + deplibs= + fi + if test prog = "$linkmode"; then + case $pass in + dlopen) libs=$dlfiles ;; + dlpreopen) libs=$dlprefiles ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + esac + fi + if test lib,dlpreopen = "$linkmode,$pass"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs=$dlprefiles + fi + if test dlopen = "$pass"; then + # Collect dlpreopened libraries + save_deplibs=$deplibs + deplibs= + fi + + for deplib in $libs; do + lib= + found=false + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test lib != "$linkmode" && test prog != "$linkmode"; then + func_warning "'-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test lib = "$linkmode"; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib=$searchdir/lib$name$search_ext + if test -f "$lib"; then + if test .la = "$search_ext"; then + found=: + else + found=false + fi + break 2 + fi + done + done + if $found; then + # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll=$l + done + if test "X$ll" = "X$old_library"; then # only static version available + found=false + func_dirname "$lib" "" "." + ladir=$func_dirname_result + lib=$ladir/$old_library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + else + # deplib doesn't seem to be a libtool library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + ;; # -l + *.ltframework) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test conv = "$pass" && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + prog) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + if test scan = "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "'-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test link = "$pass"; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=false + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=: + fi + ;; + pass_all) + valid_a_lib=: + ;; + esac + if $valid_a_lib; then + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + else + echo + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." + fi + ;; + esac + continue + ;; + prog) + if test link != "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + elif test prog = "$linkmode"; then + if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=: + continue + ;; + esac # case $deplib + + $found || test -f "$lib" \ + || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "'$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir=$func_dirname_result + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass" || + { test prog != "$linkmode" && test lib != "$linkmode"; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" + fi + + if test conv = "$pass"; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + elif test prog != "$linkmode" && test lib != "$linkmode"; then + func_fatal_error "'$lib' is not a convenience library" + fi + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test yes = "$prefer_static_libs" || + test built,no = "$prefer_static_libs,$installed"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib=$l + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + + # This library was specified with -dlopen. + if test dlopen = "$pass"; then + test -z "$libdir" \ + && func_fatal_error "cannot -dlopen a convenience library: '$lib'" + if test -z "$dlname" || + test yes != "$dlopen_support" || + test no = "$build_libtool_libs" + then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + func_append dlprefiles " $lib $dependency_libs" + else + func_append newdlfiles " $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of '$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir=$ladir + fi + ;; + esac + func_basename "$lib" + laname=$func_basename_result + + # Find the relevant object directory and library name. + if test yes = "$installed"; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library '$lib' was moved." + dir=$ladir + absdir=$abs_ladir + libdir=$abs_ladir + else + dir=$lt_sysroot$libdir + absdir=$lt_sysroot$libdir + fi + test yes = "$hardcode_automatic" && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir=$ladir + absdir=$abs_ladir + # Remove this search path later + func_append notinst_path " $abs_ladir" + else + dir=$ladir/$objdir + absdir=$abs_ladir/$objdir + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test dlpreopen = "$pass"; then + if test -z "$libdir" && test prog = "$linkmode"; then + func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" + fi + case $host in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test lib = "$linkmode"; then + deplibs="$dir/$old_library $deplibs" + elif test prog,link = "$linkmode,$pass"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test prog = "$linkmode" && test link != "$pass"; then + func_append newlib_search_path " $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=false + if test no != "$link_all_deplibs" || test -z "$library_names" || + test no = "$build_libtool_libs"; then + linkalldeplibs=: + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + esac + # Need to link against all dependency_libs? + if $linkalldeplibs; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test prog,link = "$linkmode,$pass"; then + if test -n "$library_names" && + { { test no = "$prefer_static_libs" || + test built,yes = "$prefer_static_libs,$installed"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then + # Make sure the rpath contains only unique directories. + case $temp_rpath: in + *"$absdir:"*) ;; + *) func_append temp_rpath "$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if $alldeplibs && + { test pass_all = "$deplibs_check_method" || + { test yes = "$build_libtool_libs" && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test built = "$use_static_libs" && test yes = "$installed"; then + use_static_libs=no + fi + if test -n "$library_names" && + { test no = "$use_static_libs" || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc* | *os2*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test no = "$installed"; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule= + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule=$dlpremoduletest + break + fi + done + if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then + echo + if test prog = "$linkmode"; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test lib = "$linkmode" && + test yes = "$hardcode_into_libs"; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname=$1 + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname=$dlname + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc* | *os2*) + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + esac + eval soname=\"$soname_spec\" + else + soname=$realname + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot=$soname + func_basename "$soroot" + soname=$func_basename_result + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from '$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for '$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test prog = "$linkmode" || test relink != "$opt_mode"; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test no = "$hardcode_direct"; then + add=$dir/$linklib + case $host in + *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; + *-*-sysv4*uw2*) add_dir=-L$dir ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir=-L$dir ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we cannot + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library"; then + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" + else + add=$dir/$old_library + fi + elif test -n "$old_library"; then + add=$dir/$old_library + fi + fi + esac + elif test no = "$hardcode_minus_L"; then + case $host in + *-*-sunos*) add_shlibpath=$dir ;; + esac + add_dir=-L$dir + add=-l$name + elif test no = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + relink) + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$dir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$absdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test yes != "$lib_linked"; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; + esac + fi + if test prog = "$linkmode"; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test yes != "$hardcode_direct" && + test yes != "$hardcode_minus_L" && + test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test prog = "$linkmode" || test relink = "$opt_mode"; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$libdir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$libdir + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + add=-l$name + elif test yes = "$hardcode_automatic"; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib"; then + add=$inst_prefix_dir$libdir/$linklib + else + add=$libdir/$linklib + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir=-L$libdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + fi + + if test prog = "$linkmode"; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test prog = "$linkmode"; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test unsupported != "$hardcode_direct"; then + test -n "$old_library" && linklib=$old_library + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test yes = "$build_libtool_libs"; then + # Not a shared library + if test pass_all != "$deplibs_check_method"; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + $ECHO "*** Warning: This system cannot link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test yes = "$module"; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test lib = "$linkmode"; then + if test -n "$dependency_libs" && + { test yes != "$hardcode_into_libs" || + test yes = "$build_old_libs" || + test yes = "$link_static"; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs=$temp_deplibs + fi + + func_append newlib_search_path " $absdir" + # Link against this library + test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test no != "$link_all_deplibs"; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path=$deplib ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of '$dir'" + absdir=$dir + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names"; then + for tmp in $deplibrary_names; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl"; then + depdepl=$absdir/$objdir/$depdepl + darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" + func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" + path= + fi + fi + ;; + *) + path=-L$absdir/$objdir + ;; + esac + else + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "'$deplib' seems to be moved" + + path=-L$absdir + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test link = "$pass"; then + if test prog = "$linkmode"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs=$newdependency_libs + if test dlpreopen = "$pass"; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test dlopen != "$pass"; then + test conv = "$pass" || { + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) func_append lib_search_path " $dir" ;; + esac + done + newlib_search_path= + } + + if test prog,link = "$linkmode,$pass"; then + vars="compile_deplibs finalize_deplibs" + else + vars=deplibs + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append tmp_libs " $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + + # Add Sun CC postdeps if required: + test CXX = "$tagname" && { + case $host_os in + linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C++ 5.9 + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + + solaris*) + func_cc_basename "$CC" + case $func_cc_basename_result in + CC* | sunCC*) + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + esac + } + + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i= + ;; + esac + if test -n "$i"; then + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test prog = "$linkmode"; then + dlfiles=$newdlfiles + fi + if test prog = "$linkmode" || test lib = "$linkmode"; then + dlprefiles=$newdlprefiles + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "'-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "'-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs=$output + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form 'libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test no = "$module" \ + && func_fatal_help "libtool library '$output' must begin with 'lib'" + + if test no != "$need_lib_prefix"; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test pass_all != "$deplibs_check_method"; then + func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test no = "$dlself" \ + || func_warning "'-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test 1 -lt "$#" \ + && func_warning "ignoring multiple '-rpath's for a libtool library" + + install_libdir=$1 + + oldlibs= + if test -z "$rpath"; then + if test yes = "$build_libtool_libs"; then + # Building a libtool convenience library. + # Some compilers have problems with a '.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "'-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs=$IFS; IFS=: + set dummy $vinfo 0 0 0 + shift + IFS=$save_ifs + + test -n "$7" && \ + func_fatal_help "too many parameters to '-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major=$1 + number_minor=$2 + number_revision=$3 + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # that has an extra 1 added just for fun + # + case $version_type in + # correct linux to gnu/linux during the next big refactor + darwin|freebsd-elf|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_revision + ;; + freebsd-aout|qnx|sunos) + current=$number_major + revision=$number_minor + age=0 + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_minor + lt_irix_increment=no + ;; + esac + ;; + no) + current=$1 + revision=$2 + age=$3 + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT '$current' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION '$revision' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE '$age' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE '$age' is greater than the current interface number '$current'" + func_fatal_error "'$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + # On Darwin other compilers + case $CC in + nagfor*) + verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + ;; + *) + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + esac + ;; + + freebsd-aout) + major=.$current + versuffix=.$current.$revision + ;; + + freebsd-elf) + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + irix | nonstopux) + if test no = "$lt_irix_increment"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring=$verstring_prefix$major.$revision + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test 0 -ne "$loop"; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring_prefix$major.$iface:$verstring + done + + # Before this point, $major must not contain '.'. + major=.$major + versuffix=$major.$revision + ;; + + linux) # correct to gnu/linux during the next big refactor + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=.$current.$age.$revision + verstring=$current.$age.$revision + + # Add in all the interfaces that we are compatible with. + loop=$age + while test 0 -ne "$loop"; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring:$iface.0 + done + + # Make executables depend on our current version. + func_append verstring ":$current.0" + ;; + + qnx) + major=.$current + versuffix=.$current + ;; + + sco) + major=.$current + versuffix=.$current + ;; + + sunos) + major=.$current + versuffix=.$current.$revision + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 file systems. + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + + *) + func_fatal_configuration "unknown library version type '$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring=0.0 + ;; + esac + if test no = "$need_version"; then + versuffix= + else + versuffix=.0.0 + fi + fi + + # Remove version info from name if versioning should be avoided + if test yes,no = "$avoid_version,$need_version"; then + major= + versuffix= + verstring= + fi + + # Check to see if the archive will have undefined symbols. + if test yes = "$allow_undefined"; then + if test unsupported = "$allow_undefined_flag"; then + if test yes = "$build_old_libs"; then + func_warning "undefined symbols not allowed in $host shared libraries; building static only" + build_libtool_libs=no + else + func_fatal_error "can't build $host shared library unless -no-undefined is specified" + fi + fi + else + # Don't allow undefined symbols. + allow_undefined_flag=$no_undefined_flag + fi + + fi + + func_generate_dlsyms "$libname" "$libname" : + func_append libobjs " $symfileobj" + test " " = "$libobjs" && libobjs= + + if test relink != "$opt_mode"; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) + if test -n "$precious_files_regex"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles=$dlfiles + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) func_append dlfiles " $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles=$dlprefiles + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test yes = "$build_libtool_libs"; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test yes = "$build_libtool_need_lc"; then + func_append deplibs " -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release= + versuffix= + major= + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib=$potent_lib + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | $SED 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; + *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib= + ;; + esac + fi + if test -n "$a_deplib"; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib=$potent_lib # see symlink-check above in file_magic test + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs= + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + for i in $predeps $postdeps; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + echo + if test none = "$deplibs_check_method"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + ;; + esac + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + if test yes = "$droppeddeps"; then + if test yes = "$module"; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test no = "$allow_undefined"; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + deplibs=$new_libs + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test yes = "$build_libtool_libs"; then + # Remove $wl instances when linking with ld. + # FIXME: should test the right _cmds variable. + case $archive_cmds in + *\$LD\ *) wl= ;; + esac + if test yes = "$hardcode_into_libs"; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath=$finalize_rpath + test relink = "$opt_mode" || rpath=$compile_rpath$rpath + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath=$finalize_shlibpath + test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname=$1 + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname=$realname + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib=$output_objdir/$realname + linknames= + for link + do + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols=$output_objdir/$libname.uexp + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + func_dll_def_p "$export_symbols" || { + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols=$export_symbols + export_symbols= + always_export_symbols=yes + } + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs=$IFS; IFS='~' + for cmd1 in $cmds; do + IFS=$save_ifs + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test yes = "$try_normal_branch" \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=$output_objdir/$output_la.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS=$save_ifs + if test -n "$export_symbols_regex" && test : != "$skipped_export"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test : != "$skipped_export" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs=$tmp_deplibs + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test yes = "$compiler_needs_object" && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test : != "$skipped_export" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then + output=$output_objdir/$output_la.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then + output=$output_objdir/$output_la.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test yes = "$compiler_needs_object"; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-$k.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test -z "$objlist" || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test 1 -eq "$k"; then + # The first file doesn't have a previous command to add. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-$k.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-$k.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + ${skipped_export-false} && { + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + } + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs=$IFS; IFS='~' + for cmd in $concat_cmds; do + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + ${skipped_export-false} && { + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + } + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs=$IFS; IFS='~' + for cmd in $cmds; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test yes = "$module" || test yes = "$export_dynamic"; then + # On all known operating systems, these are identical. + dlname=$soname + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "'-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object '$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj=$output + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # if reload_cmds runs $LD directly, get rid of -Wl from + # whole_archive_flag_spec and hope we can get by with turning comma + # into space. + case $reload_cmds in + *\$LD[\ \$]*) wl= ;; + esac + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags + else + gentop=$output_objdir/${obj}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test yes = "$build_libtool_libs" || libobjs=$non_pic_objects + + # Create the old-style object. + reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs + + output=$obj + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + test yes = "$build_libtool_libs" || { + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + } + + if test -n "$pic_flag" || test default != "$pic_mode"; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output=$libobj + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "'-release' is ignored for programs" + + $preload \ + && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ + && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test CXX = "$tagname"; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " $wl-bind_at_load" + func_append finalize_command " $wl-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs=$new_libs + + + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath=$rpath + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append finalize_perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath=$rpath + + if test -n "$libobjs" && test yes = "$build_old_libs"; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" false + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=: + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=false + ;; + *cygwin* | *mingw* ) + test yes = "$build_libtool_libs" || wrappers_required=false + ;; + *) + if test no = "$need_relink" || test yes != "$build_libtool_libs"; then + wrappers_required=false + fi + ;; + esac + $wrappers_required || { + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command=$compile_command$compile_rpath + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.$objext"; then + func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' + fi + + exit $exit_status + } + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + func_append rpath "$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test yes = "$no_install"; then + # We don't need to create a wrapper script. + link_command=$compile_var$compile_command$compile_rpath + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + exit $EXIT_SUCCESS + fi + + case $hardcode_action,$fast_install in + relink,*) + # Fast installation is not supported + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "'$output' will be relinked during installation" + ;; + *,yes) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + ;; + *,no) + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + ;; + *,needless) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command= + ;; + esac + + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource=$output_path/$objdir/lt-$output_name.c + cwrapper=$output_path/$output_name.exe + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host"; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + case $build_libtool_libs in + convenience) + oldobjs="$libobjs_save $symfileobj" + addlibs=$convenience + build_libtool_libs=no + ;; + module) + oldobjs=$libobjs_save + addlibs=$old_convenience + build_libtool_libs=no + ;; + *) + oldobjs="$old_deplibs $non_pic_objects" + $preload && test -f "$symfileobj" \ + && func_append oldobjs " $symfileobj" + addlibs=$old_convenience + ;; + esac + + if test -n "$addlibs"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append oldobjs " $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase=$func_basename_result + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj"; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test -z "$oldobjs"; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test yes = "$build_old_libs" && old_library=$libname.$libext + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + if test yes = "$hardcode_automatic"; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test yes = "$installed"; then + if test -z "$install_libdir"; then + break + fi + output=$output_objdir/${outputname}i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name=$func_basename_result + func_resolve_sysroot "$deplib" + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs=$newdependency_libs + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles=$newdlprefiles + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles=$newdlprefiles + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test -n "$bindir"; then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result/$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test no,yes = "$installed,$need_relink"; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +if test link = "$opt_mode" || test relink = "$opt_mode"; then + func_mode_link ${1+"$@"} +fi + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $debug_cmd + + RM=$nonopt + files= + rmforce=false + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + for arg + do + case $arg in + -f) func_append RM " $arg"; rmforce=: ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir=$func_dirname_result + if test . = "$dir"; then + odir=$objdir + else + odir=$dir/$objdir + fi + func_basename "$file" + name=$func_basename_result + test uninstall = "$opt_mode" && odir=$dir + + # Remember odir for removal later, being careful to avoid duplicates + if test clean = "$opt_mode"; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif $rmforce; then + continue + fi + + rmfiles=$file + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case $opt_mode in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && test none != "$pic_object"; then + func_append rmfiles " $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && test none != "$non_pic_object"; then + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test clean = "$opt_mode"; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.$objext" + if test yes = "$fast_install" && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name" + fi + if test "X$noexename" != "X$name"; then + func_append rmfiles " $odir/lt-$noexename.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the $objdir's in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then + func_mode_uninstall ${1+"$@"} +fi + +test -z "$opt_mode" && { + help=$generic_help + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode '$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# where we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/clutter/build/missing b/clutter/build/missing new file mode 100755 index 0000000..f62bbae --- /dev/null +++ b/clutter/build/missing @@ -0,0 +1,215 @@ +#! /bin/sh +# Common wrapper for a few potentially missing GNU programs. + +scriptversion=2013-10-28.13; # UTC + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Originally written by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program 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 General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try '$0 --help' for more information" + exit 1 +fi + +case $1 in + + --is-lightweight) + # Used by our autoconf macros to check whether the available missing + # script is modern enough. + exit 0 + ;; + + --run) + # Back-compat with the calling convention used by older automake. + shift + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due +to PROGRAM being missing or too old. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal autoconf autoheader autom4te automake makeinfo + bison yacc flex lex help2man + +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" + exit 1 + ;; + +esac + +# Run the given program, remember its exit status. +"$@"; st=$? + +# If it succeeded, we are done. +test $st -eq 0 && exit 0 + +# Also exit now if we it failed (or wasn't found), and '--version' was +# passed; such an option is passed most likely to detect whether the +# program is present and works. +case $2 in --version|--help) exit $st;; esac + +# Exit code 63 means version mismatch. This often happens when the user +# tries to use an ancient version of a tool on a file that requires a +# minimum version. +if test $st -eq 63; then + msg="probably too old" +elif test $st -eq 127; then + # Program was missing. + msg="missing on your system" +else + # Program was found and executed, but failed. Give up. + exit $st +fi + +perl_URL=http://www.perl.org/ +flex_URL=http://flex.sourceforge.net/ +gnu_software_URL=http://www.gnu.org/software + +program_details () +{ + case $1 in + aclocal|automake) + echo "The '$1' program is part of the GNU Automake package:" + echo "<$gnu_software_URL/automake>" + echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/autoconf>" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + autoconf|autom4te|autoheader) + echo "The '$1' program is part of the GNU Autoconf package:" + echo "<$gnu_software_URL/autoconf/>" + echo "It also requires GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + esac +} + +give_advice () +{ + # Normalize program name to check for. + normalized_program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + + printf '%s\n' "'$1' is $msg." + + configure_deps="'configure.ac' or m4 files included by 'configure.ac'" + case $normalized_program in + autoconf*) + echo "You should only need it if you modified 'configure.ac'," + echo "or m4 files included by it." + program_details 'autoconf' + ;; + autoheader*) + echo "You should only need it if you modified 'acconfig.h' or" + echo "$configure_deps." + program_details 'autoheader' + ;; + automake*) + echo "You should only need it if you modified 'Makefile.am' or" + echo "$configure_deps." + program_details 'automake' + ;; + aclocal*) + echo "You should only need it if you modified 'acinclude.m4' or" + echo "$configure_deps." + program_details 'aclocal' + ;; + autom4te*) + echo "You might have modified some maintainer files that require" + echo "the 'autom4te' program to be rebuilt." + program_details 'autom4te' + ;; + bison*|yacc*) + echo "You should only need it if you modified a '.y' file." + echo "You may want to install the GNU Bison package:" + echo "<$gnu_software_URL/bison/>" + ;; + lex*|flex*) + echo "You should only need it if you modified a '.l' file." + echo "You may want to install the Fast Lexical Analyzer package:" + echo "<$flex_URL>" + ;; + help2man*) + echo "You should only need it if you modified a dependency" \ + "of a man page." + echo "You may want to install the GNU Help2man package:" + echo "<$gnu_software_URL/help2man/>" + ;; + makeinfo*) + echo "You should only need it if you modified a '.texi' file, or" + echo "any other file indirectly affecting the aspect of the manual." + echo "You might want to install the Texinfo package:" + echo "<$gnu_software_URL/texinfo/>" + echo "The spurious makeinfo call might also be the consequence of" + echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" + echo "want to install GNU make:" + echo "<$gnu_software_URL/make/>" + ;; + *) + echo "You might have modified some files without having the proper" + echo "tools for further handling them. Check the 'README' file, it" + echo "often tells you about the needed prerequisites for installing" + echo "this package. You may also peek at any GNU archive site, in" + echo "case some other package contains this missing '$1' program." + ;; + esac +} + +give_advice "$1" | sed -e '1s/^/WARNING: /' \ + -e '2,$s/^/ /' >&2 + +# Propagate the correct exit status (expected to be 127 for a program +# not found, 63 for a program that failed due to version mismatch). +exit $st + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/clutter/build/test-driver b/clutter/build/test-driver new file mode 100755 index 0000000..8e575b0 --- /dev/null +++ b/clutter/build/test-driver @@ -0,0 +1,148 @@ +#! /bin/sh +# test-driver - basic testsuite driver script. + +scriptversion=2013-07-13.22; # UTC + +# Copyright (C) 2011-2014 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +# Make unconditional expansion of undefined variables an error. This +# helps a lot in preventing typo-related bugs. +set -u + +usage_error () +{ + echo "$0: $*" >&2 + print_usage >&2 + exit 2 +} + +print_usage () +{ + cat <$log_file 2>&1 +estatus=$? + +if test $enable_hard_errors = no && test $estatus -eq 99; then + tweaked_estatus=1 +else + tweaked_estatus=$estatus +fi + +case $tweaked_estatus:$expect_failure in + 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; + 0:*) col=$grn res=PASS recheck=no gcopy=no;; + 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; + 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; + *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; + *:*) col=$red res=FAIL recheck=yes gcopy=yes;; +esac + +# Report the test outcome and exit status in the logs, so that one can +# know whether the test passed or failed simply by looking at the '.log' +# file, without the need of also peaking into the corresponding '.trs' +# file (automake bug#11814). +echo "$res $test_name (exit status: $estatus)" >>$log_file + +# Report outcome to console. +echo "${col}${res}${std}: $test_name" + +# Register the test result, and other relevant metadata. +echo ":test-result: $res" > $trs_file +echo ":global-test-result: $res" >> $trs_file +echo ":recheck: $recheck" >> $trs_file +echo ":copy-in-global-log: $gcopy" >> $trs_file + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/clutter/clutter/Makefile.am b/clutter/clutter/Makefile.am new file mode 100644 index 0000000..2f7e6c3 --- /dev/null +++ b/clutter/clutter/Makefile.am @@ -0,0 +1,710 @@ +AUTOMAKE_OPTIONS = subdir-objects + +# preamble +NULL = + +# common definitions +CLEANFILES = +DISTCLEANFILES = +EXTRA_DIST = +BUILT_SOURCES = + +AM_CPPFLAGS = \ + -DCLUTTER_PREFIX=\""$(prefix)"\" \ + -DCLUTTER_LIBDIR=\""$(libdir)"\" \ + -DCLUTTER_DATADIR=\""$(datadir)"\" \ + -DCLUTTER_LOCALEDIR=\""$(localedir)"\" \ + -DCLUTTER_SYSCONFDIR=\""$(sysconfdir)"\" \ + -DCLUTTER_COMPILATION=1 \ + -DCOGL_DISABLE_DEPRECATION_WARNINGS \ + -DG_LOG_DOMAIN=\"Clutter\" \ + -I$(top_srcdir) \ + -I$(top_srcdir)/clutter \ + -I$(top_srcdir)/clutter/cally \ + -I$(top_builddir) \ + -I$(top_builddir)/clutter \ + -I$(top_srcdir)/../cogl \ + -I$(top_builddir)/../cogl \ + $(CLUTTER_DEPRECATED_CFLAGS) \ + $(CLUTTER_DEBUG_CFLAGS) \ + $(CLUTTER_HIDDEN_VISIBILITY_CFLAGS) \ + $(NULL) + +AM_CFLAGS = $(CLUTTER_CFLAGS) $(MAINTAINER_CFLAGS) + +# these are the gir files we generate using g-ir-scanner +INTROSPECTION_GIRS = + +# the base include path for headers +clutter_base_includedir = $(includedir)/mutter/clutter-$(CLUTTER_API_VERSION) +clutter_includedir = $(clutter_base_includedir)/clutter +clutter_deprecateddir = $(clutter_base_includedir)/clutter/deprecated + +# pkg-config files +pc_files = + +# common sources - please, keep these sorted alphabetically +source_h = \ + clutter-action.h \ + clutter-actor-meta.h \ + clutter-actor.h \ + clutter-align-constraint.h \ + clutter-animatable.h \ + clutter-backend.h \ + clutter-bind-constraint.h \ + clutter-binding-pool.h \ + clutter-bin-layout.h \ + clutter-blur-effect.h \ + clutter-box-layout.h \ + clutter-brightness-contrast-effect.h \ + clutter-cairo.h \ + clutter-canvas.h \ + clutter-child-meta.h \ + clutter-click-action.h \ + clutter-clone.h \ + clutter-color-static.h \ + clutter-color.h \ + clutter-colorize-effect.h \ + clutter-constraint.h \ + clutter-container.h \ + clutter-content.h \ + clutter-deform-effect.h \ + clutter-deprecated.h \ + clutter-desaturate-effect.h \ + clutter-device-manager.h \ + clutter-drag-action.h \ + clutter-drop-action.h \ + clutter-effect.h \ + clutter-enums.h \ + clutter-event.h \ + clutter-feature.h \ + clutter-fixed-layout.h \ + clutter-flow-layout.h \ + clutter-gesture-action.h \ + clutter-grid-layout.h \ + clutter-group.h \ + clutter-image.h \ + clutter-input-device.h \ + clutter-input-device-tool.h \ + clutter-interval.h \ + clutter-keyframe-transition.h \ + clutter-keysyms.h \ + clutter-layout-manager.h \ + clutter-layout-meta.h \ + clutter-macros.h \ + clutter-main.h \ + clutter-offscreen-effect.h \ + clutter-page-turn-effect.h \ + clutter-paint-nodes.h \ + clutter-paint-node.h \ + clutter-pan-action.h \ + clutter-path-constraint.h \ + clutter-path.h \ + clutter-property-transition.h \ + clutter-rotate-action.h \ + clutter-script.h \ + clutter-scriptable.h \ + clutter-scroll-actor.h \ + clutter-settings.h \ + clutter-shader-effect.h \ + clutter-shader-types.h \ + clutter-swipe-action.h \ + clutter-snap-constraint.h \ + clutter-stage.h \ + clutter-stage-manager.h \ + clutter-stage-view.h \ + clutter-tap-action.h \ + clutter-test-utils.h \ + clutter-texture.h \ + clutter-text.h \ + clutter-text-buffer.h \ + clutter-timeline.h \ + clutter-transition-group.h \ + clutter-transition.h \ + clutter-types.h \ + clutter-units.h \ + clutter-virtual-input-device.h \ + clutter-zoom-action.h \ + $(NULL) + +source_c = \ + clutter-action.c \ + clutter-actor-box.c \ + clutter-actor-meta.c \ + clutter-actor.c \ + clutter-align-constraint.c \ + clutter-animatable.c \ + clutter-backend.c \ + clutter-base-types.c \ + clutter-bezier.c \ + clutter-bind-constraint.c \ + clutter-binding-pool.c \ + clutter-bin-layout.c \ + clutter-blur-effect.c \ + clutter-box-layout.c \ + clutter-brightness-contrast-effect.c \ + clutter-cairo.c \ + clutter-canvas.c \ + clutter-child-meta.c \ + clutter-click-action.c \ + clutter-clone.c \ + clutter-color.c \ + clutter-colorize-effect.c \ + clutter-constraint.c \ + clutter-container.c \ + clutter-content.c \ + clutter-deform-effect.c \ + clutter-desaturate-effect.c \ + clutter-device-manager.c \ + clutter-drag-action.c \ + clutter-drop-action.c \ + clutter-effect.c \ + clutter-event.c \ + clutter-feature.c \ + clutter-fixed-layout.c \ + clutter-flatten-effect.c \ + clutter-flow-layout.c \ + clutter-gesture-action.c \ + clutter-grid-layout.c \ + clutter-image.c \ + clutter-input-device.c \ + clutter-input-device-tool.c \ + clutter-virtual-input-device.c \ + clutter-interval.c \ + clutter-keyframe-transition.c \ + clutter-keysyms-table.c \ + clutter-layout-manager.c \ + clutter-layout-meta.c \ + clutter-main.c \ + clutter-master-clock.c \ + clutter-master-clock-default.c \ + clutter-offscreen-effect.c \ + clutter-page-turn-effect.c \ + clutter-paint-nodes.c \ + clutter-paint-node.c \ + clutter-pan-action.c \ + clutter-path-constraint.c \ + clutter-path.c \ + clutter-property-transition.c \ + clutter-rotate-action.c \ + clutter-script.c \ + clutter-script-parser.c \ + clutter-scriptable.c \ + clutter-scroll-actor.c \ + clutter-settings.c \ + clutter-shader-effect.c \ + clutter-shader-types.c \ + clutter-swipe-action.c \ + clutter-snap-constraint.c \ + clutter-stage.c \ + clutter-stage-manager.c \ + clutter-stage-view.c \ + clutter-stage-window.c \ + clutter-tap-action.c \ + clutter-test-utils.c \ + clutter-text.c \ + clutter-text-buffer.c \ + clutter-transition-group.c \ + clutter-transition.c \ + clutter-timeline.c \ + clutter-units.c \ + clutter-util.c \ + clutter-paint-volume.c \ + clutter-zoom-action.c \ + $(NULL) + +# private headers; these should not be distributed or introspected +source_h_priv = \ + clutter-actor-meta-private.h \ + clutter-actor-private.h \ + clutter-backend-private.h \ + clutter-bezier.h \ + clutter-constraint-private.h \ + clutter-content-private.h \ + clutter-debug.h \ + clutter-device-manager-private.h \ + clutter-easing.h \ + clutter-effect-private.h \ + clutter-event-translator.h \ + clutter-event-private.h \ + clutter-flatten-effect.h \ + clutter-gesture-action-private.h \ + clutter-id-pool.h \ + clutter-master-clock.h \ + clutter-master-clock-default.h \ + clutter-offscreen-effect-private.h \ + clutter-paint-node-private.h \ + clutter-paint-volume-private.h \ + clutter-private.h \ + clutter-script-private.h \ + clutter-settings-private.h \ + clutter-stage-manager-private.h \ + clutter-stage-private.h \ + clutter-stage-window.h \ + $(NULL) + +# private source code; these should not be introspected +source_c_priv = \ + clutter-easing.c \ + clutter-event-translator.c \ + clutter-id-pool.c \ + $(NULL) + +# deprecated installed headers +deprecated_h = \ + deprecated/clutter-actor.h \ + deprecated/clutter-alpha.h \ + deprecated/clutter-animatable.h \ + deprecated/clutter-animation.h \ + deprecated/clutter-animator.h \ + deprecated/clutter-backend.h \ + deprecated/clutter-behaviour.h \ + deprecated/clutter-behaviour-depth.h \ + deprecated/clutter-behaviour-ellipse.h \ + deprecated/clutter-behaviour-opacity.h \ + deprecated/clutter-behaviour-path.h \ + deprecated/clutter-behaviour-rotate.h \ + deprecated/clutter-behaviour-scale.h \ + deprecated/clutter-bin-layout.h \ + deprecated/clutter-box.h \ + deprecated/clutter-cairo-texture.h \ + deprecated/clutter-container.h \ + deprecated/clutter-frame-source.h \ + deprecated/clutter-group.h \ + deprecated/clutter-input-device.h \ + deprecated/clutter-keysyms.h \ + deprecated/clutter-list-model.h \ + deprecated/clutter-main.h \ + deprecated/clutter-media.h \ + deprecated/clutter-model.h \ + deprecated/clutter-rectangle.h \ + deprecated/clutter-score.h \ + deprecated/clutter-shader.h \ + deprecated/clutter-stage-manager.h \ + deprecated/clutter-stage.h \ + deprecated/clutter-state.h \ + deprecated/clutter-table-layout.h \ + deprecated/clutter-texture.h \ + deprecated/clutter-timeline.h \ + deprecated/clutter-timeout-pool.h \ + deprecated/clutter-util.h \ + $(NULL) + +# deprecated source code +deprecated_c = \ + deprecated/clutter-actor-deprecated.c \ + deprecated/clutter-alpha.c \ + deprecated/clutter-animation.c \ + deprecated/clutter-animator.c \ + deprecated/clutter-behaviour.c \ + deprecated/clutter-behaviour-depth.c \ + deprecated/clutter-behaviour-ellipse.c \ + deprecated/clutter-behaviour-opacity.c \ + deprecated/clutter-behaviour-path.c \ + deprecated/clutter-behaviour-rotate.c \ + deprecated/clutter-behaviour-scale.c \ + deprecated/clutter-box.c \ + deprecated/clutter-cairo-texture.c \ + deprecated/clutter-frame-source.c \ + deprecated/clutter-group.c \ + deprecated/clutter-input-device-deprecated.c \ + deprecated/clutter-layout-manager-deprecated.c \ + deprecated/clutter-list-model.c \ + deprecated/clutter-media.c \ + deprecated/clutter-model.c \ + deprecated/clutter-rectangle.c \ + deprecated/clutter-score.c \ + deprecated/clutter-shader.c \ + deprecated/clutter-state.c \ + deprecated/clutter-table-layout.c \ + deprecated/clutter-texture.c \ + deprecated/clutter-timeout-pool.c \ + $(NULL) + +# deprecated private headers; these should not be installed +deprecated_h_priv = \ + deprecated/clutter-model-private.h \ + deprecated/clutter-timeout-interval.h \ + $(NULL) + +# deprecated private source code; these should not be introspected +deprecated_c_priv = \ + deprecated/clutter-timeout-interval.c \ + $(NULL) + +# built sources +built_source_c = \ + clutter-enum-types.c \ + clutter-marshal.c \ + $(NULL) + +# built headers +built_source_h = \ + clutter-enum-types.h \ + clutter-marshal.h \ + $(NULL) + +# config header +DISTCLEANFILES += clutter-config.h +EXTRA_DIST += clutter-config.h.in + +# version header +DISTCLEANFILES += clutter-version.h +EXTRA_DIST += clutter-version.h.in clutter-version.h + +# key symbol update script +EXTRA_DIST += clutter-keysyms-update.pl + +pc_files += mutter-clutter-$(CLUTTER_API_VERSION).pc + +# in order to be compatible with Clutter < 1.10, when we shipped a single +# shared library whose name was determined by the single backend it +# supported, we need to install symbolic links so that existing applications +# using Clutter won't break in the Brave New World of multi-backend support +# in the same shared object. +compat_libs = + +# backends source listings +# +# backend_source_c := source code +# backend_source_h := installed public headers +# backend_source_c_priv := source that should not be scanned by g-i +# backend_source_h_priv := private headers +# backend_source_built := built sources +# +backend_source_c = +backend_source_h = +backend_source_c_priv = +backend_source_h_priv = +backend_source_built = + +# X11 backend rules +x11_source_c = \ + x11/clutter-backend-x11.c \ + x11/clutter-device-manager-core-x11.c \ + x11/clutter-event-x11.c \ + x11/clutter-input-device-core-x11.c \ + x11/clutter-keymap-x11.c \ + x11/clutter-stage-x11.c \ + x11/clutter-x11-texture-pixmap.c \ + $(NULL) + +x11_source_h = \ + x11/clutter-x11.h \ + x11/clutter-x11-texture-pixmap.h \ + $(NULL) + +x11_source_h_priv = \ + x11/clutter-backend-x11.h \ + x11/clutter-device-manager-core-x11.h \ + x11/clutter-input-device-core-x11.h \ + x11/clutter-keymap-x11.h \ + x11/clutter-settings-x11.h \ + x11/clutter-stage-x11.h \ + $(NULL) + +x11_source_c_priv = \ + x11/xsettings/xsettings-client.c \ + x11/xsettings/xsettings-client.h \ + x11/xsettings/xsettings-common.c \ + x11/xsettings/xsettings-common.h \ + $(NULL) + +x11_source_c += \ + x11/clutter-device-manager-xi2.c \ + x11/clutter-input-device-xi2.c \ + $(NULL) + +x11_source_h_priv += \ + x11/clutter-device-manager-xi2.h \ + x11/clutter-input-device-xi2.h \ + $(NULL) + +x11_source_c += \ + x11/clutter-virtual-input-device-x11.c \ + $(NULL) + +x11_source_h_priv += \ + x11/clutter-virtual-input-device-x11.h \ + $(NULL) + +backend_source_h += $(x11_source_h) +backend_source_c += $(x11_source_c) +backend_source_h_priv += $(x11_source_h_priv) +backend_source_c_priv += $(x11_source_c_priv) + +# the list of files we want to introspect on X11 +x11_introspection = $(x11_source_c) $(x11_source_h) + +clutterx11_includedir = $(clutter_includedir)/x11 +clutterx11_include_HEADERS = $(x11_source_h) + +mutter-clutter-x11-$(CLUTTER_API_VERSION).pc: mutter-clutter-$(CLUTTER_API_VERSION).pc + $(QUIET_GEN)cp -f $< $(@F) + +pc_files += mutter-clutter-x11-$(CLUTTER_API_VERSION).pc + +# Shared cogl backend files +cogl_source_h = + +cogl_source_c = \ + cogl/clutter-stage-cogl.c \ + $(NULL) + +cogl_source_h_priv = \ + cogl/clutter-stage-cogl.h \ + $(NULL) + +cogl_source_c_priv = + +backend_source_h += $(cogl_source_h) +backend_source_c += $(cogl_source_c) +backend_source_h_priv += $(cogl_source_h_priv) +backend_source_c_priv += $(cogl_source_c_priv) + +backend_source_h += $(glx_source_h) +backend_source_c += $(glx_source_c) + +evdev_c_priv = \ + evdev/clutter-device-manager-evdev.c \ + evdev/clutter-input-device-evdev.c \ + evdev/clutter-seat-evdev.c \ + evdev/clutter-virtual-input-device-evdev.c \ + evdev/clutter-event-evdev.c \ + evdev/clutter-input-device-tool-evdev.c \ + $(NULL) +evdev_h_priv = \ + evdev/clutter-device-manager-evdev.h \ + evdev/clutter-input-device-evdev.h \ + evdev/clutter-seat-evdev.h \ + evdev/clutter-input-device-tool-evdev.h \ + evdev/clutter-virtual-input-device-evdev.h \ + $(NULL) +evdev_h = evdev/clutter-evdev.h + +if SUPPORT_WAYLAND +backend_source_c_priv += $(evdev_c_priv) +backend_source_h_priv += $(evdev_h_priv) +backend_source_h += $(evdev_h) + +clutterevdev_includedir = $(clutter_includedir)/evdev +clutterevdev_include_HEADERS = $(evdev_h) + +backend_source_c += evdev/clutter-xkb-utils.c +backend_source_h_priv += evdev/clutter-xkb-utils.h + +# EGL backend rules +egl_source_h = \ + egl/clutter-egl-headers.h \ + egl/clutter-egl.h \ + $(NULL) + +egl_source_h_priv = egl/clutter-backend-eglnative.h +egl_source_c = egl/clutter-backend-eglnative.c + +wayland_compositor_source_h = \ + wayland/clutter-wayland-compositor.h \ + wayland/clutter-wayland-surface.h +backend_source_h += $(wayland_compositor_source_h) +backend_source_c += \ + wayland/clutter-wayland-surface.c + +wayland_compositor_includedir = $(clutter_includedir)/wayland +wayland_compositor_include_HEADERS = $(wayland_compositor_source_h) + +backend_source_h += $(egl_source_h) +backend_source_c += $(egl_source_c) +backend_source_h_priv += $(egl_source_h_priv) + +clutteregl_includedir = $(clutter_includedir)/egl +clutteregl_include_HEADERS = $(egl_source_h) +endif # SUPPORT_WAYLAND + +# cally +cally_sources_h = \ + cally/cally-actor.h \ + cally/cally-clone.h \ + cally/cally-factory.h \ + cally/cally-group.h \ + cally/cally.h \ + cally/cally-main.h \ + cally/cally-rectangle.h \ + cally/cally-root.h \ + cally/cally-stage.h \ + cally/cally-text.h \ + cally/cally-texture.h \ + cally/cally-util.h \ + $(NULL) + +cally_sources_c = \ + cally/cally-actor.c \ + cally/cally.c \ + cally/cally-clone.c \ + cally/cally-group.c \ + cally/cally-rectangle.c \ + cally/cally-root.c \ + cally/cally-stage.c \ + cally/cally-text.c \ + cally/cally-texture.c \ + cally/cally-util.c \ + $(NULL) + +cally_sources_private = \ + cally/cally-actor-private.h \ + $(NULL) + +cally_includedir = $(clutter_base_includedir)/cally +cally_include_HEADERS = $(cally_sources_h) + +# general build rules: +# you should not need to modify anything below this point + +# glib-genmarshal rules +glib_marshal_list = clutter-marshal.list +glib_marshal_prefix = _clutter_marshal +include $(srcdir)/Makefile.am.marshal + +# glib-mkenums rules +glib_enum_h = clutter-enum-types.h +glib_enum_c = clutter-enum-types.c +glib_enum_headers = $(source_h) $(deprecated_h) +include $(srcdir)/Makefile.am.enums + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = $(pc_files) +DISTCLEANFILES += $(pc_files) + +clutter_include_HEADERS = $(source_h) clutter.h clutter-version.h clutter-autocleanups.h clutter-mutter.h +nodist_clutter_include_HEADERS = clutter-config.h $(built_source_h) + +clutter_deprecated_HEADERS = $(deprecated_h) + +mutterlibdir = $(libdir)/mutter +mutterlib_LTLIBRARIES = libmutter-clutter-@CLUTTER_API_VERSION@.la + +libmutter_clutter_@CLUTTER_API_VERSION@_la_LIBADD = \ + $(LIBM) \ + $(CLUTTER_LIBS) \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/../cogl/cogl-pango/libmutter-cogl-pango.la \ + $(top_builddir)/../cogl/cogl-path/libmutter-cogl-path.la \ + $(NULL) + +libmutter_clutter_@CLUTTER_API_VERSION@_la_SOURCES = \ + $(backend_source_c) \ + $(backend_source_h) \ + $(backend_source_c_priv) \ + $(backend_source_h_priv) \ + $(source_c) \ + $(source_h) \ + $(source_c_priv) \ + $(source_h_priv) \ + $(deprecated_c) \ + $(deprecated_h) \ + $(deprecated_c_priv) \ + $(deprecated_h_priv) \ + $(cally_sources_c) \ + $(cally_sources_h) \ + $(cally_sources_private) \ + $(NULL) + +nodist_libmutter_clutter_@CLUTTER_API_VERSION@_la_SOURCES = \ + $(backend_source_built) \ + $(built_source_c) \ + $(built_source_h) + +libmutter_clutter_@CLUTTER_API_VERSION@_la_LDFLAGS = \ + $(CLUTTER_LINK_FLAGS) \ + $(CLUTTER_LT_LDFLAGS) \ + -export-dynamic \ + -rpath $(mutterlibdir) \ + $(NULL) + +install-exec-local: + test -z "$(mutterlibdir)" || $(MKDIR_P) "$(DESTDIR)$(mutterlibdir)" + for lib in `echo $(compat_libs)`; do \ + (cd $(DESTDIR)$(mutterlibdir) && \ + rm -f $$lib.0.$(CLUTTER_LT_CURRENT).$(CLUTTER_LT_REVISION); \ + ) ; \ + (cd $(DESTDIR)$(mutterlibdir) && \ + { ln -s -f libmutter-clutter-$(CLUTTER_API_VERSION).so.0.$(CLUTTER_LT_CURRENT).$(CLUTTER_LT_REVISION) $$lib.0 || \ + { rm -f $$lib.0 && ln -s libmutter-clutter-1.0.so.0.$(CLUTTER_LT_CURRENT).$(CLUTTER_LT_REVISION) $$lib.0; }; \ + } \ + ) ; \ + (cd $(DESTDIR)$(mutterlibdir) && \ + { ln -s -f libmutter-clutter-$(CLUTTER_API_VERSION).so.0.$(CLUTTER_LT_CURRENT).$(CLUTTER_LT_REVISION) $$lib || \ + { rm -f $$lib && ln -s libmutter-clutter-1.0.so.0.$(CLUTTER_LT_CURRENT).$(CLUTTER_LT_REVISION) $$lib; }; \ + } \ + ) ; \ + done + +# gobject-introspection rules +-include $(INTROSPECTION_MAKEFILE) + +INTROSPECTION_SCANNER_ARGS = --add-include-path=$(top_builddir)/../cogl/cogl --add-include-path=$(top_builddir)/../cogl/cogl-pango +INTROSPECTION_COMPILER_ARGS = --includedir=$(top_builddir)/../cogl/cogl --includedir=$(top_builddir)/../cogl/cogl-pango + +Clutter-@CLUTTER_API_VERSION@.gir: libmutter-clutter-@CLUTTER_API_VERSION@.la Makefile + +Clutter_@CLUTTER_API_VERSION_AM@_gir_NAMESPACE = Clutter +Clutter_@CLUTTER_API_VERSION_AM@_gir_VERSION = @CLUTTER_API_VERSION@ +Clutter_@CLUTTER_API_VERSION_AM@_gir_LIBS = libmutter-clutter-@CLUTTER_API_VERSION@.la +Clutter_@CLUTTER_API_VERSION_AM@_gir_FILES = \ + $(clutter_include_HEADERS) \ + $(clutter_deprecated_HEADERS) \ + $(nodist_clutter_include_HEADERS) \ + $(source_c) \ + $(deprecated_c) \ + $(built_source_c) +Clutter_@CLUTTER_API_VERSION_AM@_gir_CFLAGS = $(AM_CPPFLAGS) $(CLUTTER_CFLAGS) +Clutter_@CLUTTER_API_VERSION_AM@_gir_INCLUDES = GL-1.0 GObject-2.0 cairo-1.0 Cogl-1.0 CoglPango-1.0 Atk-1.0 Json-1.0 +Clutter_@CLUTTER_API_VERSION_AM@_gir_SCANNERFLAGS = \ + --warn-all \ + --c-include='clutter/clutter.h' \ + --pkg-export=mutter-clutter-@CLUTTER_API_VERSION@ + +INTROSPECTION_GIRS += Clutter-@CLUTTER_API_VERSION@.gir + +Cally-@CLUTTER_API_VERSION@.gir: Makefile Clutter-@CLUTTER_API_VERSION@.gir + +Cally_@CLUTTER_API_VERSION_AM@_gir_NAMESPACE = Cally +Cally_@CLUTTER_API_VERSION_AM@_gir_VERSION = @CLUTTER_API_VERSION@ +Cally_@CLUTTER_API_VERSION_AM@_gir_LIBS = libmutter-clutter-@CLUTTER_API_VERSION@.la +Cally_@CLUTTER_API_VERSION_AM@_gir_FILES = $(cally_sources_h) $(cally_sources_c) +Cally_@CLUTTER_API_VERSION_AM@_gir_CFLAGS = $(AM_CPPFLAGS) $(CLUTTER_CFLAGS) +Cally_@CLUTTER_API_VERSION_AM@_gir_SCANNERFLAGS = \ + --warn-all \ + --c-include='cally/cally.h' \ + --pkg-export=mutter-cally-@CLUTTER_API_VERSION@ \ + --include-uninstalled=$(top_builddir)/clutter/Clutter-@CLUTTER_API_VERSION@.gir + +INTROSPECTION_GIRS += Cally-@CLUTTER_API_VERSION@.gir + +ClutterX11-@CLUTTER_API_VERSION@.gir: Makefile Clutter-@CLUTTER_API_VERSION@.gir + +ClutterX11_@CLUTTER_API_VERSION_AM@_gir_NAMESPACE = ClutterX11 +ClutterX11_@CLUTTER_API_VERSION_AM@_gir_INCLUDES = xlib-2.0 +ClutterX11_@CLUTTER_API_VERSION_AM@_gir_LIBS = libmutter-clutter-@CLUTTER_API_VERSION@.la +ClutterX11_@CLUTTER_API_VERSION_AM@_gir_FILES = $(x11_introspection) +ClutterX11_@CLUTTER_API_VERSION_AM@_gir_CFLAGS = $(AM_CPPFLAGS) $(CLUTTER_CFLAGS) +ClutterX11_@CLUTTER_API_VERSION_AM@_gir_SCANNERFLAGS = \ + --warn-all \ + --c-include='clutter/x11/clutter-x11.h' \ + --pkg-export=mutter-clutter-x11-@CLUTTER_API_VERSION@ \ + --include-uninstalled=$(top_builddir)/clutter/Clutter-@CLUTTER_API_VERSION@.gir + +INTROSPECTION_GIRS += ClutterX11-@CLUTTER_API_VERSION@.gir + +# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to +# install anything - we need to install inside our prefix. +girdir = $(mutterlibdir) +gir_DATA = $(INTROSPECTION_GIRS) + +typelibdir = $(mutterlibdir) +typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib) + +EXTRA_DIST += \ + Makefile.am.marshal \ + Makefile.am.enums + +CLEANFILES += $(gir_DATA) $(typelib_DATA) diff --git a/clutter/clutter/Makefile.am.enums b/clutter/clutter/Makefile.am.enums new file mode 100644 index 0000000..2fd69d5 --- /dev/null +++ b/clutter/clutter/Makefile.am.enums @@ -0,0 +1,52 @@ +# Rules for generating enumeration types using glib-mkenums +# +# Define: +# glib_enum_h = header template file +# glib_enum_c = source template file +# glib_enum_headers = list of headers to parse +# +# before including Makefile.am.enums. You will also need to have +# the following targets already defined: +# +# CLEANFILES +# DISTCLEANFILES +# BUILT_SOURCES +# EXTRA_DIST +# +# Author: Emmanuele Bassi + +# Basic sanity checks +$(if $(GLIB_MKENUMS),,$(error Need to define GLIB_MKENUMS)) + +$(if $(or $(glib_enum_h), \ + $(glib_enum_c)),, \ + $(error Need to define glib_enum_h and glib_enum_c)) + +$(if $(glib_enum_headers),,$(error Need to define glib_enum_headers)) + +enum_tmpl_h=$(addprefix $(srcdir)/, $(glib_enum_h:.h=.h.in)) +enum_tmpl_c=$(addprefix $(srcdir)/, $(glib_enum_c:.c=.c.in)) +enum_headers=$(addprefix $(srcdir)/, $(glib_enum_headers)) + +CLEANFILES += stamp-enum-types +DISTCLEANFILES += $(glib_enum_h) $(glib_enum_c) +BUILT_SOURCES += $(glib_enum_h) $(glib_enum_c) +EXTRA_DIST += $(enum_tmpl_h) $(enum_tmpl_c) + +stamp-enum-types: $(enum_headers) $(enum_tmpl_h) + $(AM_V_GEN)$(GLIB_MKENUMS) \ + --template $(enum_tmpl_h) \ + $(enum_headers) > xgen-eh \ + && (cmp -s xgen-eh $(glib_enum_h) || cp -f xgen-eh $(glib_enum_h)) \ + && rm -f xgen-eh \ + && echo timestamp > $(@F) + +$(glib_enum_h): stamp-enum-types + @true + +$(glib_enum_c): $(enum_headers) $(enum_tmpl_h) $(enum_tmpl_c) + $(AM_V_GEN)$(GLIB_MKENUMS) \ + --template $(enum_tmpl_c) \ + $(enum_headers) > xgen-ec \ + && cp -f xgen-ec $(glib_enum_c) \ + && rm -f xgen-ec diff --git a/clutter/clutter/Makefile.am.marshal b/clutter/clutter/Makefile.am.marshal new file mode 100644 index 0000000..89d3222 --- /dev/null +++ b/clutter/clutter/Makefile.am.marshal @@ -0,0 +1,52 @@ +# Rules for generating marshal files using glib-genmarshal +# +# Define: +# glib_marshal_list = marshal list file +# glib_marshal_prefix = prefix for marshal functions +# +# before including Makefile.am.marshal. You will also need to have +# the following targets already defined: +# +# CLEANFILES +# DISTCLEANFILES +# BUILT_SOURCES +# EXTRA_DIST +# +# Author: Emmanuele Bassi + +# Basic sanity checks +$(if $(GLIB_GENMARSHAL),,$(error Need to define GLIB_GENMARSHAL)) + +$(if $(or $(glib_marshal_list), \ + $(glib_marshal_prefix)),, \ + $(error Need to define glib_marshal_list and glib_marshal_prefix)) + +marshal_h = $(glib_marshal_list:.list=.h) +marshal_c = $(glib_marshal_list:.list=.c) +marshal_list = $(addprefix $(srcdir)/, $(glib_marshal_list)) + +CLEANFILES += stamp-marshal +DISTCLEANFILES += $(marshal_h) $(marshal_c) +BUILT_SOURCES += $(marshal_h) $(marshal_c) +EXTRA_DIST += $(marshal_list) + +stamp-marshal: $(marshal_list) + $(AM_V_GEN)$(GLIB_GENMARSHAL) \ + --prefix=$(glib_marshal_prefix) \ + --header \ + $(marshal_list) > xgen-mh \ + && (cmp -s xgen-mh $(marshal_h) || cp -f xgen-mh $(marshal_h)) \ + && rm -f xgen-mh \ + && echo timestamp > $(@F) + +$(marshal_h): stamp-marshal + @true + +$(marshal_c): $(marshal_h) + $(AM_V_GEN)(echo "#include \"$(marshal_h)\"" ; \ + $(GLIB_GENMARSHAL) \ + --prefix=$(glib_marshal_prefix) \ + --body \ + $(marshal_list)) > xgen-mc \ + && cp xgen-mc $(marshal_c) \ + && rm -f xgen-mc diff --git a/clutter/clutter/Makefile.in b/clutter/clutter/Makefile.in new file mode 100644 index 0000000..e477e84 --- /dev/null +++ b/clutter/clutter/Makefile.in @@ -0,0 +1,2450 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Rules for generating marshal files using glib-genmarshal +# +# Define: +# glib_marshal_list = marshal list file +# glib_marshal_prefix = prefix for marshal functions +# +# before including Makefile.am.marshal. You will also need to have +# the following targets already defined: +# +# CLEANFILES +# DISTCLEANFILES +# BUILT_SOURCES +# EXTRA_DIST +# +# Author: Emmanuele Bassi + +# Rules for generating enumeration types using glib-mkenums +# +# Define: +# glib_enum_h = header template file +# glib_enum_c = source template file +# glib_enum_headers = list of headers to parse +# +# before including Makefile.am.enums. You will also need to have +# the following targets already defined: +# +# CLEANFILES +# DISTCLEANFILES +# BUILT_SOURCES +# EXTRA_DIST +# +# Author: Emmanuele Bassi + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@SUPPORT_WAYLAND_TRUE@am__append_1 = $(evdev_c_priv) +@SUPPORT_WAYLAND_TRUE@am__append_2 = $(evdev_h_priv) \ +@SUPPORT_WAYLAND_TRUE@ evdev/clutter-xkb-utils.h \ +@SUPPORT_WAYLAND_TRUE@ $(egl_source_h_priv) +@SUPPORT_WAYLAND_TRUE@am__append_3 = $(evdev_h) \ +@SUPPORT_WAYLAND_TRUE@ $(wayland_compositor_source_h) \ +@SUPPORT_WAYLAND_TRUE@ $(egl_source_h) +@SUPPORT_WAYLAND_TRUE@am__append_4 = evdev/clutter-xkb-utils.c \ +@SUPPORT_WAYLAND_TRUE@ wayland/clutter-wayland-surface.c \ +@SUPPORT_WAYLAND_TRUE@ $(egl_source_c) +subdir = clutter +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/build/autotools/as-compiler-flag.m4 \ + $(top_srcdir)/build/autotools/glibtests.m4 \ + $(top_srcdir)/build/autotools/introspection.m4 \ + $(top_srcdir)/build/autotools/libtool.m4 \ + $(top_srcdir)/build/autotools/ltoptions.m4 \ + $(top_srcdir)/build/autotools/ltsugar.m4 \ + $(top_srcdir)/build/autotools/ltversion.m4 \ + $(top_srcdir)/build/autotools/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(cally_include_HEADERS) \ + $(clutter_deprecated_HEADERS) $(clutter_include_HEADERS) \ + $(am__clutteregl_include_HEADERS_DIST) \ + $(am__clutterevdev_include_HEADERS_DIST) \ + $(clutterx11_include_HEADERS) \ + $(am__wayland_compositor_include_HEADERS_DIST) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = clutter-build-config.h +CONFIG_CLEAN_FILES = clutter-config.h clutter-version.h +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(mutterlibdir)" "$(DESTDIR)$(girdir)" \ + "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(typelibdir)" \ + "$(DESTDIR)$(cally_includedir)" \ + "$(DESTDIR)$(clutter_deprecateddir)" \ + "$(DESTDIR)$(clutter_includedir)" \ + "$(DESTDIR)$(clutteregl_includedir)" \ + "$(DESTDIR)$(clutterevdev_includedir)" \ + "$(DESTDIR)$(clutterx11_includedir)" \ + "$(DESTDIR)$(clutter_includedir)" \ + "$(DESTDIR)$(wayland_compositor_includedir)" +LTLIBRARIES = $(mutterlib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libmutter_clutter_@CLUTTER_API_VERSION@_la_DEPENDENCIES = \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/../cogl/cogl-pango/libmutter-cogl-pango.la \ + $(top_builddir)/../cogl/cogl-path/libmutter-cogl-path.la \ + $(am__DEPENDENCIES_1) +am__libmutter_clutter_@CLUTTER_API_VERSION@_la_SOURCES_DIST = \ + x11/clutter-backend-x11.c \ + x11/clutter-device-manager-core-x11.c x11/clutter-event-x11.c \ + x11/clutter-input-device-core-x11.c x11/clutter-keymap-x11.c \ + x11/clutter-stage-x11.c x11/clutter-x11-texture-pixmap.c \ + x11/clutter-device-manager-xi2.c \ + x11/clutter-input-device-xi2.c \ + x11/clutter-virtual-input-device-x11.c \ + cogl/clutter-stage-cogl.c evdev/clutter-xkb-utils.c \ + wayland/clutter-wayland-surface.c \ + egl/clutter-backend-eglnative.c x11/clutter-x11.h \ + x11/clutter-x11-texture-pixmap.h evdev/clutter-evdev.h \ + wayland/clutter-wayland-compositor.h \ + wayland/clutter-wayland-surface.h egl/clutter-egl-headers.h \ + egl/clutter-egl.h x11/xsettings/xsettings-client.c \ + x11/xsettings/xsettings-client.h \ + x11/xsettings/xsettings-common.c \ + x11/xsettings/xsettings-common.h \ + evdev/clutter-device-manager-evdev.c \ + evdev/clutter-input-device-evdev.c evdev/clutter-seat-evdev.c \ + evdev/clutter-virtual-input-device-evdev.c \ + evdev/clutter-event-evdev.c \ + evdev/clutter-input-device-tool-evdev.c \ + x11/clutter-backend-x11.h \ + x11/clutter-device-manager-core-x11.h \ + x11/clutter-input-device-core-x11.h x11/clutter-keymap-x11.h \ + x11/clutter-settings-x11.h x11/clutter-stage-x11.h \ + x11/clutter-device-manager-xi2.h \ + x11/clutter-input-device-xi2.h \ + x11/clutter-virtual-input-device-x11.h \ + cogl/clutter-stage-cogl.h evdev/clutter-device-manager-evdev.h \ + evdev/clutter-input-device-evdev.h evdev/clutter-seat-evdev.h \ + evdev/clutter-input-device-tool-evdev.h \ + evdev/clutter-virtual-input-device-evdev.h \ + evdev/clutter-xkb-utils.h egl/clutter-backend-eglnative.h \ + clutter-action.c clutter-actor-box.c clutter-actor-meta.c \ + clutter-actor.c clutter-align-constraint.c \ + clutter-animatable.c clutter-backend.c clutter-base-types.c \ + clutter-bezier.c clutter-bind-constraint.c \ + clutter-binding-pool.c clutter-bin-layout.c \ + clutter-blur-effect.c clutter-box-layout.c \ + clutter-brightness-contrast-effect.c clutter-cairo.c \ + clutter-canvas.c clutter-child-meta.c clutter-click-action.c \ + clutter-clone.c clutter-color.c clutter-colorize-effect.c \ + clutter-constraint.c clutter-container.c clutter-content.c \ + clutter-deform-effect.c clutter-desaturate-effect.c \ + clutter-device-manager.c clutter-drag-action.c \ + clutter-drop-action.c clutter-effect.c clutter-event.c \ + clutter-feature.c clutter-fixed-layout.c \ + clutter-flatten-effect.c clutter-flow-layout.c \ + clutter-gesture-action.c clutter-grid-layout.c clutter-image.c \ + clutter-input-device.c clutter-input-device-tool.c \ + clutter-virtual-input-device.c clutter-interval.c \ + clutter-keyframe-transition.c clutter-keysyms-table.c \ + clutter-layout-manager.c clutter-layout-meta.c clutter-main.c \ + clutter-master-clock.c clutter-master-clock-default.c \ + clutter-offscreen-effect.c clutter-page-turn-effect.c \ + clutter-paint-nodes.c clutter-paint-node.c \ + clutter-pan-action.c clutter-path-constraint.c clutter-path.c \ + clutter-property-transition.c clutter-rotate-action.c \ + clutter-script.c clutter-script-parser.c clutter-scriptable.c \ + clutter-scroll-actor.c clutter-settings.c \ + clutter-shader-effect.c clutter-shader-types.c \ + clutter-swipe-action.c clutter-snap-constraint.c \ + clutter-stage.c clutter-stage-manager.c clutter-stage-view.c \ + clutter-stage-window.c clutter-tap-action.c \ + clutter-test-utils.c clutter-text.c clutter-text-buffer.c \ + clutter-transition-group.c clutter-transition.c \ + clutter-timeline.c clutter-units.c clutter-util.c \ + clutter-paint-volume.c clutter-zoom-action.c clutter-action.h \ + clutter-actor-meta.h clutter-actor.h \ + clutter-align-constraint.h clutter-animatable.h \ + clutter-backend.h clutter-bind-constraint.h \ + clutter-binding-pool.h clutter-bin-layout.h \ + clutter-blur-effect.h clutter-box-layout.h \ + clutter-brightness-contrast-effect.h clutter-cairo.h \ + clutter-canvas.h clutter-child-meta.h clutter-click-action.h \ + clutter-clone.h clutter-color-static.h clutter-color.h \ + clutter-colorize-effect.h clutter-constraint.h \ + clutter-container.h clutter-content.h clutter-deform-effect.h \ + clutter-deprecated.h clutter-desaturate-effect.h \ + clutter-device-manager.h clutter-drag-action.h \ + clutter-drop-action.h clutter-effect.h clutter-enums.h \ + clutter-event.h clutter-feature.h clutter-fixed-layout.h \ + clutter-flow-layout.h clutter-gesture-action.h \ + clutter-grid-layout.h clutter-group.h clutter-image.h \ + clutter-input-device.h clutter-input-device-tool.h \ + clutter-interval.h clutter-keyframe-transition.h \ + clutter-keysyms.h clutter-layout-manager.h \ + clutter-layout-meta.h clutter-macros.h clutter-main.h \ + clutter-offscreen-effect.h clutter-page-turn-effect.h \ + clutter-paint-nodes.h clutter-paint-node.h \ + clutter-pan-action.h clutter-path-constraint.h clutter-path.h \ + clutter-property-transition.h clutter-rotate-action.h \ + clutter-script.h clutter-scriptable.h clutter-scroll-actor.h \ + clutter-settings.h clutter-shader-effect.h \ + clutter-shader-types.h clutter-swipe-action.h \ + clutter-snap-constraint.h clutter-stage.h \ + clutter-stage-manager.h clutter-stage-view.h \ + clutter-tap-action.h clutter-test-utils.h clutter-texture.h \ + clutter-text.h clutter-text-buffer.h clutter-timeline.h \ + clutter-transition-group.h clutter-transition.h \ + clutter-types.h clutter-units.h clutter-virtual-input-device.h \ + clutter-zoom-action.h clutter-easing.c \ + clutter-event-translator.c clutter-id-pool.c \ + clutter-actor-meta-private.h clutter-actor-private.h \ + clutter-backend-private.h clutter-bezier.h \ + clutter-constraint-private.h clutter-content-private.h \ + clutter-debug.h clutter-device-manager-private.h \ + clutter-easing.h clutter-effect-private.h \ + clutter-event-translator.h clutter-event-private.h \ + clutter-flatten-effect.h clutter-gesture-action-private.h \ + clutter-id-pool.h clutter-master-clock.h \ + clutter-master-clock-default.h \ + clutter-offscreen-effect-private.h \ + clutter-paint-node-private.h clutter-paint-volume-private.h \ + clutter-private.h clutter-script-private.h \ + clutter-settings-private.h clutter-stage-manager-private.h \ + clutter-stage-private.h clutter-stage-window.h \ + deprecated/clutter-actor-deprecated.c \ + deprecated/clutter-alpha.c deprecated/clutter-animation.c \ + deprecated/clutter-animator.c deprecated/clutter-behaviour.c \ + deprecated/clutter-behaviour-depth.c \ + deprecated/clutter-behaviour-ellipse.c \ + deprecated/clutter-behaviour-opacity.c \ + deprecated/clutter-behaviour-path.c \ + deprecated/clutter-behaviour-rotate.c \ + deprecated/clutter-behaviour-scale.c deprecated/clutter-box.c \ + deprecated/clutter-cairo-texture.c \ + deprecated/clutter-frame-source.c deprecated/clutter-group.c \ + deprecated/clutter-input-device-deprecated.c \ + deprecated/clutter-layout-manager-deprecated.c \ + deprecated/clutter-list-model.c deprecated/clutter-media.c \ + deprecated/clutter-model.c deprecated/clutter-rectangle.c \ + deprecated/clutter-score.c deprecated/clutter-shader.c \ + deprecated/clutter-state.c deprecated/clutter-table-layout.c \ + deprecated/clutter-texture.c deprecated/clutter-timeout-pool.c \ + deprecated/clutter-actor.h deprecated/clutter-alpha.h \ + deprecated/clutter-animatable.h deprecated/clutter-animation.h \ + deprecated/clutter-animator.h deprecated/clutter-backend.h \ + deprecated/clutter-behaviour.h \ + deprecated/clutter-behaviour-depth.h \ + deprecated/clutter-behaviour-ellipse.h \ + deprecated/clutter-behaviour-opacity.h \ + deprecated/clutter-behaviour-path.h \ + deprecated/clutter-behaviour-rotate.h \ + deprecated/clutter-behaviour-scale.h \ + deprecated/clutter-bin-layout.h deprecated/clutter-box.h \ + deprecated/clutter-cairo-texture.h \ + deprecated/clutter-container.h \ + deprecated/clutter-frame-source.h deprecated/clutter-group.h \ + deprecated/clutter-input-device.h deprecated/clutter-keysyms.h \ + deprecated/clutter-list-model.h deprecated/clutter-main.h \ + deprecated/clutter-media.h deprecated/clutter-model.h \ + deprecated/clutter-rectangle.h deprecated/clutter-score.h \ + deprecated/clutter-shader.h deprecated/clutter-stage-manager.h \ + deprecated/clutter-stage.h deprecated/clutter-state.h \ + deprecated/clutter-table-layout.h deprecated/clutter-texture.h \ + deprecated/clutter-timeline.h \ + deprecated/clutter-timeout-pool.h deprecated/clutter-util.h \ + deprecated/clutter-timeout-interval.c \ + deprecated/clutter-model-private.h \ + deprecated/clutter-timeout-interval.h cally/cally-actor.c \ + cally/cally.c cally/cally-clone.c cally/cally-group.c \ + cally/cally-rectangle.c cally/cally-root.c cally/cally-stage.c \ + cally/cally-text.c cally/cally-texture.c cally/cally-util.c \ + cally/cally-actor.h cally/cally-clone.h cally/cally-factory.h \ + cally/cally-group.h cally/cally.h cally/cally-main.h \ + cally/cally-rectangle.h cally/cally-root.h cally/cally-stage.h \ + cally/cally-text.h cally/cally-texture.h cally/cally-util.h \ + cally/cally-actor-private.h +am__dirstamp = $(am__leading_dot)dirstamp +am__objects_1 = +am__objects_2 = x11/clutter-backend-x11.lo \ + x11/clutter-device-manager-core-x11.lo \ + x11/clutter-event-x11.lo x11/clutter-input-device-core-x11.lo \ + x11/clutter-keymap-x11.lo x11/clutter-stage-x11.lo \ + x11/clutter-x11-texture-pixmap.lo $(am__objects_1) \ + x11/clutter-device-manager-xi2.lo \ + x11/clutter-input-device-xi2.lo $(am__objects_1) \ + x11/clutter-virtual-input-device-x11.lo $(am__objects_1) +am__objects_3 = cogl/clutter-stage-cogl.lo $(am__objects_1) +@SUPPORT_WAYLAND_TRUE@am__objects_4 = \ +@SUPPORT_WAYLAND_TRUE@ egl/clutter-backend-eglnative.lo +@SUPPORT_WAYLAND_TRUE@am__objects_5 = evdev/clutter-xkb-utils.lo \ +@SUPPORT_WAYLAND_TRUE@ wayland/clutter-wayland-surface.lo \ +@SUPPORT_WAYLAND_TRUE@ $(am__objects_4) +am__objects_6 = $(am__objects_2) $(am__objects_3) $(am__objects_5) +am__objects_7 = $(am__objects_1) +@SUPPORT_WAYLAND_TRUE@am__objects_8 = $(am__objects_1) +@SUPPORT_WAYLAND_TRUE@am__objects_9 = $(am__objects_1) \ +@SUPPORT_WAYLAND_TRUE@ $(am__objects_1) $(am__objects_8) +am__objects_10 = $(am__objects_7) $(am__objects_1) $(am__objects_9) +am__objects_11 = x11/xsettings/xsettings-client.lo \ + x11/xsettings/xsettings-common.lo $(am__objects_1) +am__objects_12 = evdev/clutter-device-manager-evdev.lo \ + evdev/clutter-input-device-evdev.lo \ + evdev/clutter-seat-evdev.lo \ + evdev/clutter-virtual-input-device-evdev.lo \ + evdev/clutter-event-evdev.lo \ + evdev/clutter-input-device-tool-evdev.lo $(am__objects_1) +@SUPPORT_WAYLAND_TRUE@am__objects_13 = $(am__objects_12) +am__objects_14 = $(am__objects_11) $(am__objects_1) $(am__objects_13) +am__objects_15 = $(am__objects_1) $(am__objects_1) $(am__objects_1) +@SUPPORT_WAYLAND_TRUE@am__objects_16 = $(am__objects_7) \ +@SUPPORT_WAYLAND_TRUE@ $(am__objects_1) +am__objects_17 = $(am__objects_15) $(am__objects_7) $(am__objects_16) +am__objects_18 = clutter-action.lo clutter-actor-box.lo \ + clutter-actor-meta.lo clutter-actor.lo \ + clutter-align-constraint.lo clutter-animatable.lo \ + clutter-backend.lo clutter-base-types.lo clutter-bezier.lo \ + clutter-bind-constraint.lo clutter-binding-pool.lo \ + clutter-bin-layout.lo clutter-blur-effect.lo \ + clutter-box-layout.lo clutter-brightness-contrast-effect.lo \ + clutter-cairo.lo clutter-canvas.lo clutter-child-meta.lo \ + clutter-click-action.lo clutter-clone.lo clutter-color.lo \ + clutter-colorize-effect.lo clutter-constraint.lo \ + clutter-container.lo clutter-content.lo \ + clutter-deform-effect.lo clutter-desaturate-effect.lo \ + clutter-device-manager.lo clutter-drag-action.lo \ + clutter-drop-action.lo clutter-effect.lo clutter-event.lo \ + clutter-feature.lo clutter-fixed-layout.lo \ + clutter-flatten-effect.lo clutter-flow-layout.lo \ + clutter-gesture-action.lo clutter-grid-layout.lo \ + clutter-image.lo clutter-input-device.lo \ + clutter-input-device-tool.lo clutter-virtual-input-device.lo \ + clutter-interval.lo clutter-keyframe-transition.lo \ + clutter-keysyms-table.lo clutter-layout-manager.lo \ + clutter-layout-meta.lo clutter-main.lo clutter-master-clock.lo \ + clutter-master-clock-default.lo clutter-offscreen-effect.lo \ + clutter-page-turn-effect.lo clutter-paint-nodes.lo \ + clutter-paint-node.lo clutter-pan-action.lo \ + clutter-path-constraint.lo clutter-path.lo \ + clutter-property-transition.lo clutter-rotate-action.lo \ + clutter-script.lo clutter-script-parser.lo \ + clutter-scriptable.lo clutter-scroll-actor.lo \ + clutter-settings.lo clutter-shader-effect.lo \ + clutter-shader-types.lo clutter-swipe-action.lo \ + clutter-snap-constraint.lo clutter-stage.lo \ + clutter-stage-manager.lo clutter-stage-view.lo \ + clutter-stage-window.lo clutter-tap-action.lo \ + clutter-test-utils.lo clutter-text.lo clutter-text-buffer.lo \ + clutter-transition-group.lo clutter-transition.lo \ + clutter-timeline.lo clutter-units.lo clutter-util.lo \ + clutter-paint-volume.lo clutter-zoom-action.lo \ + $(am__objects_1) +am__objects_19 = clutter-easing.lo clutter-event-translator.lo \ + clutter-id-pool.lo $(am__objects_1) +am__objects_20 = deprecated/clutter-actor-deprecated.lo \ + deprecated/clutter-alpha.lo deprecated/clutter-animation.lo \ + deprecated/clutter-animator.lo deprecated/clutter-behaviour.lo \ + deprecated/clutter-behaviour-depth.lo \ + deprecated/clutter-behaviour-ellipse.lo \ + deprecated/clutter-behaviour-opacity.lo \ + deprecated/clutter-behaviour-path.lo \ + deprecated/clutter-behaviour-rotate.lo \ + deprecated/clutter-behaviour-scale.lo \ + deprecated/clutter-box.lo deprecated/clutter-cairo-texture.lo \ + deprecated/clutter-frame-source.lo deprecated/clutter-group.lo \ + deprecated/clutter-input-device-deprecated.lo \ + deprecated/clutter-layout-manager-deprecated.lo \ + deprecated/clutter-list-model.lo deprecated/clutter-media.lo \ + deprecated/clutter-model.lo deprecated/clutter-rectangle.lo \ + deprecated/clutter-score.lo deprecated/clutter-shader.lo \ + deprecated/clutter-state.lo deprecated/clutter-table-layout.lo \ + deprecated/clutter-texture.lo \ + deprecated/clutter-timeout-pool.lo $(am__objects_1) +am__objects_21 = deprecated/clutter-timeout-interval.lo \ + $(am__objects_1) +am__objects_22 = cally/cally-actor.lo cally/cally.lo \ + cally/cally-clone.lo cally/cally-group.lo \ + cally/cally-rectangle.lo cally/cally-root.lo \ + cally/cally-stage.lo cally/cally-text.lo \ + cally/cally-texture.lo cally/cally-util.lo $(am__objects_1) +am_libmutter_clutter_@CLUTTER_API_VERSION@_la_OBJECTS = \ + $(am__objects_6) $(am__objects_10) $(am__objects_14) \ + $(am__objects_17) $(am__objects_18) $(am__objects_7) \ + $(am__objects_19) $(am__objects_7) $(am__objects_20) \ + $(am__objects_7) $(am__objects_21) $(am__objects_7) \ + $(am__objects_22) $(am__objects_7) $(am__objects_7) \ + $(am__objects_1) +am__objects_23 = clutter-enum-types.lo clutter-marshal.lo \ + $(am__objects_1) +nodist_libmutter_clutter_@CLUTTER_API_VERSION@_la_OBJECTS = \ + $(am__objects_1) $(am__objects_23) $(am__objects_7) +libmutter_clutter_@CLUTTER_API_VERSION@_la_OBJECTS = \ + $(am_libmutter_clutter_@CLUTTER_API_VERSION@_la_OBJECTS) \ + $(nodist_libmutter_clutter_@CLUTTER_API_VERSION@_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libmutter_clutter_@CLUTTER_API_VERSION@_la_LINK = $(LIBTOOL) \ + $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libmutter_clutter_@CLUTTER_API_VERSION@_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/build/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libmutter_clutter_@CLUTTER_API_VERSION@_la_SOURCES) \ + $(nodist_libmutter_clutter_@CLUTTER_API_VERSION@_la_SOURCES) +DIST_SOURCES = $(am__libmutter_clutter_@CLUTTER_API_VERSION@_la_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(gir_DATA) $(pkgconfig_DATA) $(typelib_DATA) +am__clutteregl_include_HEADERS_DIST = egl/clutter-egl-headers.h \ + egl/clutter-egl.h +am__clutterevdev_include_HEADERS_DIST = evdev/clutter-evdev.h +am__wayland_compositor_include_HEADERS_DIST = \ + wayland/clutter-wayland-compositor.h \ + wayland/clutter-wayland-surface.h +HEADERS = $(cally_include_HEADERS) $(clutter_deprecated_HEADERS) \ + $(clutter_include_HEADERS) $(clutteregl_include_HEADERS) \ + $(clutterevdev_include_HEADERS) $(clutterx11_include_HEADERS) \ + $(nodist_clutter_include_HEADERS) \ + $(wayland_compositor_include_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ + $(LISP)clutter-build-config.h.in +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.am.enums \ + $(srcdir)/Makefile.am.marshal $(srcdir)/Makefile.in \ + $(srcdir)/clutter-build-config.h.in \ + $(srcdir)/clutter-config.h.in $(srcdir)/clutter-version.h.in \ + $(srcdir)/mutter-clutter.pc.in $(top_srcdir)/build/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ATK_REQ_VERSION = @ATK_REQ_VERSION@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_REQ_VERSION = @CAIRO_REQ_VERSION@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CLUTTER_API_VERSION = @CLUTTER_API_VERSION@ +CLUTTER_API_VERSION_AM = @CLUTTER_API_VERSION_AM@ +CLUTTER_BACKENDS = @CLUTTER_BACKENDS@ +CLUTTER_CFLAGS = @CLUTTER_CFLAGS@ +CLUTTER_COGL = @CLUTTER_COGL@ +CLUTTER_CONFIG_DEFINES = @CLUTTER_CONFIG_DEFINES@ +CLUTTER_DEBUG_CFLAGS = @CLUTTER_DEBUG_CFLAGS@ +CLUTTER_DEPRECATED_CFLAGS = @CLUTTER_DEPRECATED_CFLAGS@ +CLUTTER_DEPS_CFLAGS = @CLUTTER_DEPS_CFLAGS@ +CLUTTER_DEPS_LIBS = @CLUTTER_DEPS_LIBS@ +CLUTTER_DEPS_PRIVATE_CFLAGS = @CLUTTER_DEPS_PRIVATE_CFLAGS@ +CLUTTER_DEPS_PRIVATE_LIBS = @CLUTTER_DEPS_PRIVATE_LIBS@ +CLUTTER_FLAVOUR = @CLUTTER_FLAVOUR@ +CLUTTER_GCOV_CFLAGS = @CLUTTER_GCOV_CFLAGS@ +CLUTTER_GCOV_LDADD = @CLUTTER_GCOV_LDADD@ +CLUTTER_HIDDEN_VISIBILITY_CFLAGS = @CLUTTER_HIDDEN_VISIBILITY_CFLAGS@ +CLUTTER_INPUT_BACKENDS = @CLUTTER_INPUT_BACKENDS@ +CLUTTER_LIBS = @CLUTTER_LIBS@ +CLUTTER_LINK_FLAGS = @CLUTTER_LINK_FLAGS@ +CLUTTER_LT_CURRENT = @CLUTTER_LT_CURRENT@ +CLUTTER_LT_LDFLAGS = @CLUTTER_LT_LDFLAGS@ +CLUTTER_LT_REVISION = @CLUTTER_LT_REVISION@ +CLUTTER_LT_VERSION = @CLUTTER_LT_VERSION@ +CLUTTER_MAJOR_VERSION = @CLUTTER_MAJOR_VERSION@ +CLUTTER_MICRO_VERSION = @CLUTTER_MICRO_VERSION@ +CLUTTER_MINOR_VERSION = @CLUTTER_MINOR_VERSION@ +CLUTTER_RELEASE_STATUS = @CLUTTER_RELEASE_STATUS@ +CLUTTER_REQUIRES = @CLUTTER_REQUIRES@ +CLUTTER_REQUIRES_PRIVATE = @CLUTTER_REQUIRES_PRIVATE@ +CLUTTER_SONAME_INFIX = @CLUTTER_SONAME_INFIX@ +CLUTTER_STAGE_TYPE = @CLUTTER_STAGE_TYPE@ +CLUTTER_VERSION = @CLUTTER_VERSION@ +CLUTTER_WINSYS = @CLUTTER_WINSYS@ +CLUTTER_WINSYS_BASE = @CLUTTER_WINSYS_BASE@ +COGL_DRIVER = @COGL_DRIVER@ +COGL_REQ_VERSION = @COGL_REQ_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@ +GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@ +GDK_REQ_VERSION = @GDK_REQ_VERSION@ +GI_REQ_VERSION = @GI_REQ_VERSION@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQ_VERSION = @GLIB_REQ_VERSION@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +JSON_GLIB_REQ_VERSION = @JSON_GLIB_REQ_VERSION@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBINPUT_REQ_VERSION = @LIBINPUT_REQ_VERSION@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUDEV_REQ_VERSION = @LIBUDEV_REQ_VERSION@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTP = @LTP@ +LTP_GENHTML = @LTP_GENHTML@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINTAINER_CFLAGS = @MAINTAINER_CFLAGS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGO_REQ_VERSION = @PANGO_REQ_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SHTOOL = @SHTOOL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +XCOMPOSITE_REQ_VERSION = @XCOMPOSITE_REQ_VERSION@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +installed_test_metadir = @installed_test_metadir@ +installed_testdir = @installed_testdir@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = subdir-objects + +# preamble +NULL = + +# common definitions +CLEANFILES = stamp-marshal stamp-enum-types $(gir_DATA) \ + $(typelib_DATA) + +# config header + +# version header +DISTCLEANFILES = clutter-config.h clutter-version.h $(marshal_h) \ + $(marshal_c) $(glib_enum_h) $(glib_enum_c) $(pc_files) + +# key symbol update script +EXTRA_DIST = clutter-config.h.in clutter-version.h.in \ + clutter-version.h clutter-keysyms-update.pl $(marshal_list) \ + $(enum_tmpl_h) $(enum_tmpl_c) Makefile.am.marshal \ + Makefile.am.enums +BUILT_SOURCES = $(marshal_h) $(marshal_c) $(glib_enum_h) \ + $(glib_enum_c) +AM_CPPFLAGS = \ + -DCLUTTER_PREFIX=\""$(prefix)"\" \ + -DCLUTTER_LIBDIR=\""$(libdir)"\" \ + -DCLUTTER_DATADIR=\""$(datadir)"\" \ + -DCLUTTER_LOCALEDIR=\""$(localedir)"\" \ + -DCLUTTER_SYSCONFDIR=\""$(sysconfdir)"\" \ + -DCLUTTER_COMPILATION=1 \ + -DCOGL_DISABLE_DEPRECATION_WARNINGS \ + -DG_LOG_DOMAIN=\"Clutter\" \ + -I$(top_srcdir) \ + -I$(top_srcdir)/clutter \ + -I$(top_srcdir)/clutter/cally \ + -I$(top_builddir) \ + -I$(top_builddir)/clutter \ + -I$(top_srcdir)/../cogl \ + -I$(top_builddir)/../cogl \ + $(CLUTTER_DEPRECATED_CFLAGS) \ + $(CLUTTER_DEBUG_CFLAGS) \ + $(CLUTTER_HIDDEN_VISIBILITY_CFLAGS) \ + $(NULL) + +AM_CFLAGS = $(CLUTTER_CFLAGS) $(MAINTAINER_CFLAGS) + +# these are the gir files we generate using g-ir-scanner +INTROSPECTION_GIRS = Clutter-@CLUTTER_API_VERSION@.gir \ + Cally-@CLUTTER_API_VERSION@.gir \ + ClutterX11-@CLUTTER_API_VERSION@.gir + +# the base include path for headers +clutter_base_includedir = $(includedir)/mutter/clutter-$(CLUTTER_API_VERSION) +clutter_includedir = $(clutter_base_includedir)/clutter +clutter_deprecateddir = $(clutter_base_includedir)/clutter/deprecated + +# pkg-config files +pc_files = mutter-clutter-$(CLUTTER_API_VERSION).pc \ + mutter-clutter-x11-$(CLUTTER_API_VERSION).pc + +# common sources - please, keep these sorted alphabetically +source_h = \ + clutter-action.h \ + clutter-actor-meta.h \ + clutter-actor.h \ + clutter-align-constraint.h \ + clutter-animatable.h \ + clutter-backend.h \ + clutter-bind-constraint.h \ + clutter-binding-pool.h \ + clutter-bin-layout.h \ + clutter-blur-effect.h \ + clutter-box-layout.h \ + clutter-brightness-contrast-effect.h \ + clutter-cairo.h \ + clutter-canvas.h \ + clutter-child-meta.h \ + clutter-click-action.h \ + clutter-clone.h \ + clutter-color-static.h \ + clutter-color.h \ + clutter-colorize-effect.h \ + clutter-constraint.h \ + clutter-container.h \ + clutter-content.h \ + clutter-deform-effect.h \ + clutter-deprecated.h \ + clutter-desaturate-effect.h \ + clutter-device-manager.h \ + clutter-drag-action.h \ + clutter-drop-action.h \ + clutter-effect.h \ + clutter-enums.h \ + clutter-event.h \ + clutter-feature.h \ + clutter-fixed-layout.h \ + clutter-flow-layout.h \ + clutter-gesture-action.h \ + clutter-grid-layout.h \ + clutter-group.h \ + clutter-image.h \ + clutter-input-device.h \ + clutter-input-device-tool.h \ + clutter-interval.h \ + clutter-keyframe-transition.h \ + clutter-keysyms.h \ + clutter-layout-manager.h \ + clutter-layout-meta.h \ + clutter-macros.h \ + clutter-main.h \ + clutter-offscreen-effect.h \ + clutter-page-turn-effect.h \ + clutter-paint-nodes.h \ + clutter-paint-node.h \ + clutter-pan-action.h \ + clutter-path-constraint.h \ + clutter-path.h \ + clutter-property-transition.h \ + clutter-rotate-action.h \ + clutter-script.h \ + clutter-scriptable.h \ + clutter-scroll-actor.h \ + clutter-settings.h \ + clutter-shader-effect.h \ + clutter-shader-types.h \ + clutter-swipe-action.h \ + clutter-snap-constraint.h \ + clutter-stage.h \ + clutter-stage-manager.h \ + clutter-stage-view.h \ + clutter-tap-action.h \ + clutter-test-utils.h \ + clutter-texture.h \ + clutter-text.h \ + clutter-text-buffer.h \ + clutter-timeline.h \ + clutter-transition-group.h \ + clutter-transition.h \ + clutter-types.h \ + clutter-units.h \ + clutter-virtual-input-device.h \ + clutter-zoom-action.h \ + $(NULL) + +source_c = \ + clutter-action.c \ + clutter-actor-box.c \ + clutter-actor-meta.c \ + clutter-actor.c \ + clutter-align-constraint.c \ + clutter-animatable.c \ + clutter-backend.c \ + clutter-base-types.c \ + clutter-bezier.c \ + clutter-bind-constraint.c \ + clutter-binding-pool.c \ + clutter-bin-layout.c \ + clutter-blur-effect.c \ + clutter-box-layout.c \ + clutter-brightness-contrast-effect.c \ + clutter-cairo.c \ + clutter-canvas.c \ + clutter-child-meta.c \ + clutter-click-action.c \ + clutter-clone.c \ + clutter-color.c \ + clutter-colorize-effect.c \ + clutter-constraint.c \ + clutter-container.c \ + clutter-content.c \ + clutter-deform-effect.c \ + clutter-desaturate-effect.c \ + clutter-device-manager.c \ + clutter-drag-action.c \ + clutter-drop-action.c \ + clutter-effect.c \ + clutter-event.c \ + clutter-feature.c \ + clutter-fixed-layout.c \ + clutter-flatten-effect.c \ + clutter-flow-layout.c \ + clutter-gesture-action.c \ + clutter-grid-layout.c \ + clutter-image.c \ + clutter-input-device.c \ + clutter-input-device-tool.c \ + clutter-virtual-input-device.c \ + clutter-interval.c \ + clutter-keyframe-transition.c \ + clutter-keysyms-table.c \ + clutter-layout-manager.c \ + clutter-layout-meta.c \ + clutter-main.c \ + clutter-master-clock.c \ + clutter-master-clock-default.c \ + clutter-offscreen-effect.c \ + clutter-page-turn-effect.c \ + clutter-paint-nodes.c \ + clutter-paint-node.c \ + clutter-pan-action.c \ + clutter-path-constraint.c \ + clutter-path.c \ + clutter-property-transition.c \ + clutter-rotate-action.c \ + clutter-script.c \ + clutter-script-parser.c \ + clutter-scriptable.c \ + clutter-scroll-actor.c \ + clutter-settings.c \ + clutter-shader-effect.c \ + clutter-shader-types.c \ + clutter-swipe-action.c \ + clutter-snap-constraint.c \ + clutter-stage.c \ + clutter-stage-manager.c \ + clutter-stage-view.c \ + clutter-stage-window.c \ + clutter-tap-action.c \ + clutter-test-utils.c \ + clutter-text.c \ + clutter-text-buffer.c \ + clutter-transition-group.c \ + clutter-transition.c \ + clutter-timeline.c \ + clutter-units.c \ + clutter-util.c \ + clutter-paint-volume.c \ + clutter-zoom-action.c \ + $(NULL) + + +# private headers; these should not be distributed or introspected +source_h_priv = \ + clutter-actor-meta-private.h \ + clutter-actor-private.h \ + clutter-backend-private.h \ + clutter-bezier.h \ + clutter-constraint-private.h \ + clutter-content-private.h \ + clutter-debug.h \ + clutter-device-manager-private.h \ + clutter-easing.h \ + clutter-effect-private.h \ + clutter-event-translator.h \ + clutter-event-private.h \ + clutter-flatten-effect.h \ + clutter-gesture-action-private.h \ + clutter-id-pool.h \ + clutter-master-clock.h \ + clutter-master-clock-default.h \ + clutter-offscreen-effect-private.h \ + clutter-paint-node-private.h \ + clutter-paint-volume-private.h \ + clutter-private.h \ + clutter-script-private.h \ + clutter-settings-private.h \ + clutter-stage-manager-private.h \ + clutter-stage-private.h \ + clutter-stage-window.h \ + $(NULL) + + +# private source code; these should not be introspected +source_c_priv = \ + clutter-easing.c \ + clutter-event-translator.c \ + clutter-id-pool.c \ + $(NULL) + + +# deprecated installed headers +deprecated_h = \ + deprecated/clutter-actor.h \ + deprecated/clutter-alpha.h \ + deprecated/clutter-animatable.h \ + deprecated/clutter-animation.h \ + deprecated/clutter-animator.h \ + deprecated/clutter-backend.h \ + deprecated/clutter-behaviour.h \ + deprecated/clutter-behaviour-depth.h \ + deprecated/clutter-behaviour-ellipse.h \ + deprecated/clutter-behaviour-opacity.h \ + deprecated/clutter-behaviour-path.h \ + deprecated/clutter-behaviour-rotate.h \ + deprecated/clutter-behaviour-scale.h \ + deprecated/clutter-bin-layout.h \ + deprecated/clutter-box.h \ + deprecated/clutter-cairo-texture.h \ + deprecated/clutter-container.h \ + deprecated/clutter-frame-source.h \ + deprecated/clutter-group.h \ + deprecated/clutter-input-device.h \ + deprecated/clutter-keysyms.h \ + deprecated/clutter-list-model.h \ + deprecated/clutter-main.h \ + deprecated/clutter-media.h \ + deprecated/clutter-model.h \ + deprecated/clutter-rectangle.h \ + deprecated/clutter-score.h \ + deprecated/clutter-shader.h \ + deprecated/clutter-stage-manager.h \ + deprecated/clutter-stage.h \ + deprecated/clutter-state.h \ + deprecated/clutter-table-layout.h \ + deprecated/clutter-texture.h \ + deprecated/clutter-timeline.h \ + deprecated/clutter-timeout-pool.h \ + deprecated/clutter-util.h \ + $(NULL) + + +# deprecated source code +deprecated_c = \ + deprecated/clutter-actor-deprecated.c \ + deprecated/clutter-alpha.c \ + deprecated/clutter-animation.c \ + deprecated/clutter-animator.c \ + deprecated/clutter-behaviour.c \ + deprecated/clutter-behaviour-depth.c \ + deprecated/clutter-behaviour-ellipse.c \ + deprecated/clutter-behaviour-opacity.c \ + deprecated/clutter-behaviour-path.c \ + deprecated/clutter-behaviour-rotate.c \ + deprecated/clutter-behaviour-scale.c \ + deprecated/clutter-box.c \ + deprecated/clutter-cairo-texture.c \ + deprecated/clutter-frame-source.c \ + deprecated/clutter-group.c \ + deprecated/clutter-input-device-deprecated.c \ + deprecated/clutter-layout-manager-deprecated.c \ + deprecated/clutter-list-model.c \ + deprecated/clutter-media.c \ + deprecated/clutter-model.c \ + deprecated/clutter-rectangle.c \ + deprecated/clutter-score.c \ + deprecated/clutter-shader.c \ + deprecated/clutter-state.c \ + deprecated/clutter-table-layout.c \ + deprecated/clutter-texture.c \ + deprecated/clutter-timeout-pool.c \ + $(NULL) + + +# deprecated private headers; these should not be installed +deprecated_h_priv = \ + deprecated/clutter-model-private.h \ + deprecated/clutter-timeout-interval.h \ + $(NULL) + + +# deprecated private source code; these should not be introspected +deprecated_c_priv = \ + deprecated/clutter-timeout-interval.c \ + $(NULL) + + +# built sources +built_source_c = \ + clutter-enum-types.c \ + clutter-marshal.c \ + $(NULL) + + +# built headers +built_source_h = \ + clutter-enum-types.h \ + clutter-marshal.h \ + $(NULL) + + +# in order to be compatible with Clutter < 1.10, when we shipped a single +# shared library whose name was determined by the single backend it +# supported, we need to install symbolic links so that existing applications +# using Clutter won't break in the Brave New World of multi-backend support +# in the same shared object. +compat_libs = + +# backends source listings +# +# backend_source_c := source code +# backend_source_h := installed public headers +# backend_source_c_priv := source that should not be scanned by g-i +# backend_source_h_priv := private headers +# backend_source_built := built sources +# +backend_source_c = $(x11_source_c) $(cogl_source_c) $(glx_source_c) \ + $(am__append_4) +backend_source_h = $(x11_source_h) $(cogl_source_h) $(glx_source_h) \ + $(am__append_3) +backend_source_c_priv = $(x11_source_c_priv) $(cogl_source_c_priv) \ + $(am__append_1) +backend_source_h_priv = $(x11_source_h_priv) $(cogl_source_h_priv) \ + $(am__append_2) +backend_source_built = + +# X11 backend rules +x11_source_c = x11/clutter-backend-x11.c \ + x11/clutter-device-manager-core-x11.c x11/clutter-event-x11.c \ + x11/clutter-input-device-core-x11.c x11/clutter-keymap-x11.c \ + x11/clutter-stage-x11.c x11/clutter-x11-texture-pixmap.c \ + $(NULL) x11/clutter-device-manager-xi2.c \ + x11/clutter-input-device-xi2.c $(NULL) \ + x11/clutter-virtual-input-device-x11.c $(NULL) +x11_source_h = \ + x11/clutter-x11.h \ + x11/clutter-x11-texture-pixmap.h \ + $(NULL) + +x11_source_h_priv = x11/clutter-backend-x11.h \ + x11/clutter-device-manager-core-x11.h \ + x11/clutter-input-device-core-x11.h x11/clutter-keymap-x11.h \ + x11/clutter-settings-x11.h x11/clutter-stage-x11.h $(NULL) \ + x11/clutter-device-manager-xi2.h \ + x11/clutter-input-device-xi2.h $(NULL) \ + x11/clutter-virtual-input-device-x11.h $(NULL) +x11_source_c_priv = \ + x11/xsettings/xsettings-client.c \ + x11/xsettings/xsettings-client.h \ + x11/xsettings/xsettings-common.c \ + x11/xsettings/xsettings-common.h \ + $(NULL) + + +# the list of files we want to introspect on X11 +x11_introspection = $(x11_source_c) $(x11_source_h) +clutterx11_includedir = $(clutter_includedir)/x11 +clutterx11_include_HEADERS = $(x11_source_h) + +# Shared cogl backend files +cogl_source_h = +cogl_source_c = \ + cogl/clutter-stage-cogl.c \ + $(NULL) + +cogl_source_h_priv = \ + cogl/clutter-stage-cogl.h \ + $(NULL) + +cogl_source_c_priv = +evdev_c_priv = \ + evdev/clutter-device-manager-evdev.c \ + evdev/clutter-input-device-evdev.c \ + evdev/clutter-seat-evdev.c \ + evdev/clutter-virtual-input-device-evdev.c \ + evdev/clutter-event-evdev.c \ + evdev/clutter-input-device-tool-evdev.c \ + $(NULL) + +evdev_h_priv = \ + evdev/clutter-device-manager-evdev.h \ + evdev/clutter-input-device-evdev.h \ + evdev/clutter-seat-evdev.h \ + evdev/clutter-input-device-tool-evdev.h \ + evdev/clutter-virtual-input-device-evdev.h \ + $(NULL) + +evdev_h = evdev/clutter-evdev.h +@SUPPORT_WAYLAND_TRUE@clutterevdev_includedir = $(clutter_includedir)/evdev +@SUPPORT_WAYLAND_TRUE@clutterevdev_include_HEADERS = $(evdev_h) + +# EGL backend rules +@SUPPORT_WAYLAND_TRUE@egl_source_h = \ +@SUPPORT_WAYLAND_TRUE@ egl/clutter-egl-headers.h \ +@SUPPORT_WAYLAND_TRUE@ egl/clutter-egl.h \ +@SUPPORT_WAYLAND_TRUE@ $(NULL) + +@SUPPORT_WAYLAND_TRUE@egl_source_h_priv = egl/clutter-backend-eglnative.h +@SUPPORT_WAYLAND_TRUE@egl_source_c = egl/clutter-backend-eglnative.c +@SUPPORT_WAYLAND_TRUE@wayland_compositor_source_h = \ +@SUPPORT_WAYLAND_TRUE@ wayland/clutter-wayland-compositor.h \ +@SUPPORT_WAYLAND_TRUE@ wayland/clutter-wayland-surface.h + +@SUPPORT_WAYLAND_TRUE@wayland_compositor_includedir = $(clutter_includedir)/wayland +@SUPPORT_WAYLAND_TRUE@wayland_compositor_include_HEADERS = $(wayland_compositor_source_h) +@SUPPORT_WAYLAND_TRUE@clutteregl_includedir = $(clutter_includedir)/egl +@SUPPORT_WAYLAND_TRUE@clutteregl_include_HEADERS = $(egl_source_h) + +# cally +cally_sources_h = \ + cally/cally-actor.h \ + cally/cally-clone.h \ + cally/cally-factory.h \ + cally/cally-group.h \ + cally/cally.h \ + cally/cally-main.h \ + cally/cally-rectangle.h \ + cally/cally-root.h \ + cally/cally-stage.h \ + cally/cally-text.h \ + cally/cally-texture.h \ + cally/cally-util.h \ + $(NULL) + +cally_sources_c = \ + cally/cally-actor.c \ + cally/cally.c \ + cally/cally-clone.c \ + cally/cally-group.c \ + cally/cally-rectangle.c \ + cally/cally-root.c \ + cally/cally-stage.c \ + cally/cally-text.c \ + cally/cally-texture.c \ + cally/cally-util.c \ + $(NULL) + +cally_sources_private = \ + cally/cally-actor-private.h \ + $(NULL) + +cally_includedir = $(clutter_base_includedir)/cally +cally_include_HEADERS = $(cally_sources_h) + +# general build rules: +# you should not need to modify anything below this point + +# glib-genmarshal rules +glib_marshal_list = clutter-marshal.list +glib_marshal_prefix = _clutter_marshal +marshal_h = $(glib_marshal_list:.list=.h) +marshal_c = $(glib_marshal_list:.list=.c) +marshal_list = $(addprefix $(srcdir)/, $(glib_marshal_list)) + +# glib-mkenums rules +glib_enum_h = clutter-enum-types.h +glib_enum_c = clutter-enum-types.c +glib_enum_headers = $(source_h) $(deprecated_h) +enum_tmpl_h = $(addprefix $(srcdir)/, $(glib_enum_h:.h=.h.in)) +enum_tmpl_c = $(addprefix $(srcdir)/, $(glib_enum_c:.c=.c.in)) +enum_headers = $(addprefix $(srcdir)/, $(glib_enum_headers)) +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = $(pc_files) +clutter_include_HEADERS = $(source_h) clutter.h clutter-version.h clutter-autocleanups.h clutter-mutter.h +nodist_clutter_include_HEADERS = clutter-config.h $(built_source_h) +clutter_deprecated_HEADERS = $(deprecated_h) +mutterlibdir = $(libdir)/mutter +mutterlib_LTLIBRARIES = libmutter-clutter-@CLUTTER_API_VERSION@.la +libmutter_clutter_@CLUTTER_API_VERSION@_la_LIBADD = \ + $(LIBM) \ + $(CLUTTER_LIBS) \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/../cogl/cogl-pango/libmutter-cogl-pango.la \ + $(top_builddir)/../cogl/cogl-path/libmutter-cogl-path.la \ + $(NULL) + +libmutter_clutter_@CLUTTER_API_VERSION@_la_SOURCES = \ + $(backend_source_c) \ + $(backend_source_h) \ + $(backend_source_c_priv) \ + $(backend_source_h_priv) \ + $(source_c) \ + $(source_h) \ + $(source_c_priv) \ + $(source_h_priv) \ + $(deprecated_c) \ + $(deprecated_h) \ + $(deprecated_c_priv) \ + $(deprecated_h_priv) \ + $(cally_sources_c) \ + $(cally_sources_h) \ + $(cally_sources_private) \ + $(NULL) + +nodist_libmutter_clutter_@CLUTTER_API_VERSION@_la_SOURCES = \ + $(backend_source_built) \ + $(built_source_c) \ + $(built_source_h) + +libmutter_clutter_@CLUTTER_API_VERSION@_la_LDFLAGS = \ + $(CLUTTER_LINK_FLAGS) \ + $(CLUTTER_LT_LDFLAGS) \ + -export-dynamic \ + -rpath $(mutterlibdir) \ + $(NULL) + +INTROSPECTION_SCANNER_ARGS = --add-include-path=$(top_builddir)/../cogl/cogl --add-include-path=$(top_builddir)/../cogl/cogl-pango +INTROSPECTION_COMPILER_ARGS = --includedir=$(top_builddir)/../cogl/cogl --includedir=$(top_builddir)/../cogl/cogl-pango +Clutter_@CLUTTER_API_VERSION_AM@_gir_NAMESPACE = Clutter +Clutter_@CLUTTER_API_VERSION_AM@_gir_VERSION = @CLUTTER_API_VERSION@ +Clutter_@CLUTTER_API_VERSION_AM@_gir_LIBS = libmutter-clutter-@CLUTTER_API_VERSION@.la +Clutter_@CLUTTER_API_VERSION_AM@_gir_FILES = \ + $(clutter_include_HEADERS) \ + $(clutter_deprecated_HEADERS) \ + $(nodist_clutter_include_HEADERS) \ + $(source_c) \ + $(deprecated_c) \ + $(built_source_c) + +Clutter_@CLUTTER_API_VERSION_AM@_gir_CFLAGS = $(AM_CPPFLAGS) $(CLUTTER_CFLAGS) +Clutter_@CLUTTER_API_VERSION_AM@_gir_INCLUDES = GL-1.0 GObject-2.0 cairo-1.0 Cogl-1.0 CoglPango-1.0 Atk-1.0 Json-1.0 +Clutter_@CLUTTER_API_VERSION_AM@_gir_SCANNERFLAGS = \ + --warn-all \ + --c-include='clutter/clutter.h' \ + --pkg-export=mutter-clutter-@CLUTTER_API_VERSION@ + +Cally_@CLUTTER_API_VERSION_AM@_gir_NAMESPACE = Cally +Cally_@CLUTTER_API_VERSION_AM@_gir_VERSION = @CLUTTER_API_VERSION@ +Cally_@CLUTTER_API_VERSION_AM@_gir_LIBS = libmutter-clutter-@CLUTTER_API_VERSION@.la +Cally_@CLUTTER_API_VERSION_AM@_gir_FILES = $(cally_sources_h) $(cally_sources_c) +Cally_@CLUTTER_API_VERSION_AM@_gir_CFLAGS = $(AM_CPPFLAGS) $(CLUTTER_CFLAGS) +Cally_@CLUTTER_API_VERSION_AM@_gir_SCANNERFLAGS = \ + --warn-all \ + --c-include='cally/cally.h' \ + --pkg-export=mutter-cally-@CLUTTER_API_VERSION@ \ + --include-uninstalled=$(top_builddir)/clutter/Clutter-@CLUTTER_API_VERSION@.gir + +ClutterX11_@CLUTTER_API_VERSION_AM@_gir_NAMESPACE = ClutterX11 +ClutterX11_@CLUTTER_API_VERSION_AM@_gir_INCLUDES = xlib-2.0 +ClutterX11_@CLUTTER_API_VERSION_AM@_gir_LIBS = libmutter-clutter-@CLUTTER_API_VERSION@.la +ClutterX11_@CLUTTER_API_VERSION_AM@_gir_FILES = $(x11_introspection) +ClutterX11_@CLUTTER_API_VERSION_AM@_gir_CFLAGS = $(AM_CPPFLAGS) $(CLUTTER_CFLAGS) +ClutterX11_@CLUTTER_API_VERSION_AM@_gir_SCANNERFLAGS = \ + --warn-all \ + --c-include='clutter/x11/clutter-x11.h' \ + --pkg-export=mutter-clutter-x11-@CLUTTER_API_VERSION@ \ + --include-uninstalled=$(top_builddir)/clutter/Clutter-@CLUTTER_API_VERSION@.gir + + +# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to +# install anything - we need to install inside our prefix. +girdir = $(mutterlibdir) +gir_DATA = $(INTROSPECTION_GIRS) +typelibdir = $(mutterlibdir) +typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib) +all: $(BUILT_SOURCES) clutter-build-config.h + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/Makefile.am.marshal $(srcdir)/Makefile.am.enums $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign clutter/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign clutter/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(srcdir)/Makefile.am.marshal $(srcdir)/Makefile.am.enums $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clutter-build-config.h: stamp-h1 + @test -f $@ || rm -f stamp-h1 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 + +stamp-h1: $(srcdir)/clutter-build-config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status clutter/clutter-build-config.h +$(srcdir)/clutter-build-config.h.in: $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f clutter-build-config.h stamp-h1 +clutter-config.h: $(top_builddir)/config.status $(srcdir)/clutter-config.h.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +clutter-version.h: $(top_builddir)/config.status $(srcdir)/clutter-version.h.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +install-mutterlibLTLIBRARIES: $(mutterlib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(mutterlib_LTLIBRARIES)'; test -n "$(mutterlibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(mutterlibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(mutterlibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(mutterlibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(mutterlibdir)"; \ + } + +uninstall-mutterlibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(mutterlib_LTLIBRARIES)'; test -n "$(mutterlibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(mutterlibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(mutterlibdir)/$$f"; \ + done + +clean-mutterlibLTLIBRARIES: + -test -z "$(mutterlib_LTLIBRARIES)" || rm -f $(mutterlib_LTLIBRARIES) + @list='$(mutterlib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +x11/$(am__dirstamp): + @$(MKDIR_P) x11 + @: > x11/$(am__dirstamp) +x11/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) x11/$(DEPDIR) + @: > x11/$(DEPDIR)/$(am__dirstamp) +x11/clutter-backend-x11.lo: x11/$(am__dirstamp) \ + x11/$(DEPDIR)/$(am__dirstamp) +x11/clutter-device-manager-core-x11.lo: x11/$(am__dirstamp) \ + x11/$(DEPDIR)/$(am__dirstamp) +x11/clutter-event-x11.lo: x11/$(am__dirstamp) \ + x11/$(DEPDIR)/$(am__dirstamp) +x11/clutter-input-device-core-x11.lo: x11/$(am__dirstamp) \ + x11/$(DEPDIR)/$(am__dirstamp) +x11/clutter-keymap-x11.lo: x11/$(am__dirstamp) \ + x11/$(DEPDIR)/$(am__dirstamp) +x11/clutter-stage-x11.lo: x11/$(am__dirstamp) \ + x11/$(DEPDIR)/$(am__dirstamp) +x11/clutter-x11-texture-pixmap.lo: x11/$(am__dirstamp) \ + x11/$(DEPDIR)/$(am__dirstamp) +x11/clutter-device-manager-xi2.lo: x11/$(am__dirstamp) \ + x11/$(DEPDIR)/$(am__dirstamp) +x11/clutter-input-device-xi2.lo: x11/$(am__dirstamp) \ + x11/$(DEPDIR)/$(am__dirstamp) +x11/clutter-virtual-input-device-x11.lo: x11/$(am__dirstamp) \ + x11/$(DEPDIR)/$(am__dirstamp) +cogl/$(am__dirstamp): + @$(MKDIR_P) cogl + @: > cogl/$(am__dirstamp) +cogl/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) cogl/$(DEPDIR) + @: > cogl/$(DEPDIR)/$(am__dirstamp) +cogl/clutter-stage-cogl.lo: cogl/$(am__dirstamp) \ + cogl/$(DEPDIR)/$(am__dirstamp) +evdev/$(am__dirstamp): + @$(MKDIR_P) evdev + @: > evdev/$(am__dirstamp) +evdev/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) evdev/$(DEPDIR) + @: > evdev/$(DEPDIR)/$(am__dirstamp) +evdev/clutter-xkb-utils.lo: evdev/$(am__dirstamp) \ + evdev/$(DEPDIR)/$(am__dirstamp) +wayland/$(am__dirstamp): + @$(MKDIR_P) wayland + @: > wayland/$(am__dirstamp) +wayland/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) wayland/$(DEPDIR) + @: > wayland/$(DEPDIR)/$(am__dirstamp) +wayland/clutter-wayland-surface.lo: wayland/$(am__dirstamp) \ + wayland/$(DEPDIR)/$(am__dirstamp) +egl/$(am__dirstamp): + @$(MKDIR_P) egl + @: > egl/$(am__dirstamp) +egl/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) egl/$(DEPDIR) + @: > egl/$(DEPDIR)/$(am__dirstamp) +egl/clutter-backend-eglnative.lo: egl/$(am__dirstamp) \ + egl/$(DEPDIR)/$(am__dirstamp) +x11/xsettings/$(am__dirstamp): + @$(MKDIR_P) x11/xsettings + @: > x11/xsettings/$(am__dirstamp) +x11/xsettings/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) x11/xsettings/$(DEPDIR) + @: > x11/xsettings/$(DEPDIR)/$(am__dirstamp) +x11/xsettings/xsettings-client.lo: x11/xsettings/$(am__dirstamp) \ + x11/xsettings/$(DEPDIR)/$(am__dirstamp) +x11/xsettings/xsettings-common.lo: x11/xsettings/$(am__dirstamp) \ + x11/xsettings/$(DEPDIR)/$(am__dirstamp) +evdev/clutter-device-manager-evdev.lo: evdev/$(am__dirstamp) \ + evdev/$(DEPDIR)/$(am__dirstamp) +evdev/clutter-input-device-evdev.lo: evdev/$(am__dirstamp) \ + evdev/$(DEPDIR)/$(am__dirstamp) +evdev/clutter-seat-evdev.lo: evdev/$(am__dirstamp) \ + evdev/$(DEPDIR)/$(am__dirstamp) +evdev/clutter-virtual-input-device-evdev.lo: evdev/$(am__dirstamp) \ + evdev/$(DEPDIR)/$(am__dirstamp) +evdev/clutter-event-evdev.lo: evdev/$(am__dirstamp) \ + evdev/$(DEPDIR)/$(am__dirstamp) +evdev/clutter-input-device-tool-evdev.lo: evdev/$(am__dirstamp) \ + evdev/$(DEPDIR)/$(am__dirstamp) +deprecated/$(am__dirstamp): + @$(MKDIR_P) deprecated + @: > deprecated/$(am__dirstamp) +deprecated/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) deprecated/$(DEPDIR) + @: > deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-actor-deprecated.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-alpha.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-animation.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-animator.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-behaviour.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-behaviour-depth.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-behaviour-ellipse.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-behaviour-opacity.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-behaviour-path.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-behaviour-rotate.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-behaviour-scale.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-box.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-cairo-texture.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-frame-source.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-group.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-input-device-deprecated.lo: \ + deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-layout-manager-deprecated.lo: \ + deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-list-model.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-media.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-model.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-rectangle.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-score.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-shader.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-state.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-table-layout.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-texture.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-timeout-pool.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/clutter-timeout-interval.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +cally/$(am__dirstamp): + @$(MKDIR_P) cally + @: > cally/$(am__dirstamp) +cally/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) cally/$(DEPDIR) + @: > cally/$(DEPDIR)/$(am__dirstamp) +cally/cally-actor.lo: cally/$(am__dirstamp) \ + cally/$(DEPDIR)/$(am__dirstamp) +cally/cally.lo: cally/$(am__dirstamp) cally/$(DEPDIR)/$(am__dirstamp) +cally/cally-clone.lo: cally/$(am__dirstamp) \ + cally/$(DEPDIR)/$(am__dirstamp) +cally/cally-group.lo: cally/$(am__dirstamp) \ + cally/$(DEPDIR)/$(am__dirstamp) +cally/cally-rectangle.lo: cally/$(am__dirstamp) \ + cally/$(DEPDIR)/$(am__dirstamp) +cally/cally-root.lo: cally/$(am__dirstamp) \ + cally/$(DEPDIR)/$(am__dirstamp) +cally/cally-stage.lo: cally/$(am__dirstamp) \ + cally/$(DEPDIR)/$(am__dirstamp) +cally/cally-text.lo: cally/$(am__dirstamp) \ + cally/$(DEPDIR)/$(am__dirstamp) +cally/cally-texture.lo: cally/$(am__dirstamp) \ + cally/$(DEPDIR)/$(am__dirstamp) +cally/cally-util.lo: cally/$(am__dirstamp) \ + cally/$(DEPDIR)/$(am__dirstamp) + +libmutter-clutter-@CLUTTER_API_VERSION@.la: $(libmutter_clutter_@CLUTTER_API_VERSION@_la_OBJECTS) $(libmutter_clutter_@CLUTTER_API_VERSION@_la_DEPENDENCIES) $(EXTRA_libmutter_clutter_@CLUTTER_API_VERSION@_la_DEPENDENCIES) + $(AM_V_CCLD)$(libmutter_clutter_@CLUTTER_API_VERSION@_la_LINK) -rpath $(mutterlibdir) $(libmutter_clutter_@CLUTTER_API_VERSION@_la_OBJECTS) $(libmutter_clutter_@CLUTTER_API_VERSION@_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f cally/*.$(OBJEXT) + -rm -f cally/*.lo + -rm -f cogl/*.$(OBJEXT) + -rm -f cogl/*.lo + -rm -f deprecated/*.$(OBJEXT) + -rm -f deprecated/*.lo + -rm -f egl/*.$(OBJEXT) + -rm -f egl/*.lo + -rm -f evdev/*.$(OBJEXT) + -rm -f evdev/*.lo + -rm -f wayland/*.$(OBJEXT) + -rm -f wayland/*.lo + -rm -f x11/*.$(OBJEXT) + -rm -f x11/*.lo + -rm -f x11/xsettings/*.$(OBJEXT) + -rm -f x11/xsettings/*.lo + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-action.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-actor-box.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-actor-meta.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-actor.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-align-constraint.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-animatable.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-backend.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-base-types.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-bezier.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-bin-layout.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-bind-constraint.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-binding-pool.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-blur-effect.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-box-layout.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-brightness-contrast-effect.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-cairo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-canvas.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-child-meta.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-click-action.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-clone.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-color.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-colorize-effect.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-constraint.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-container.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-content.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-deform-effect.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-desaturate-effect.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-device-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-drag-action.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-drop-action.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-easing.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-effect.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-enum-types.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-event-translator.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-event.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-feature.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-fixed-layout.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-flatten-effect.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-flow-layout.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-gesture-action.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-grid-layout.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-id-pool.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-image.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-input-device-tool.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-input-device.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-interval.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-keyframe-transition.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-keysyms-table.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-layout-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-layout-meta.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-main.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-marshal.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-master-clock-default.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-master-clock.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-offscreen-effect.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-page-turn-effect.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-paint-node.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-paint-nodes.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-paint-volume.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-pan-action.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-path-constraint.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-path.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-property-transition.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-rotate-action.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-script-parser.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-script.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-scriptable.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-scroll-actor.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-settings.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-shader-effect.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-shader-types.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-snap-constraint.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-stage-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-stage-view.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-stage-window.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-stage.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-swipe-action.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-tap-action.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-test-utils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-text-buffer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-text.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-timeline.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-transition-group.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-transition.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-units.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-util.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-virtual-input-device.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clutter-zoom-action.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cally/$(DEPDIR)/cally-actor.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cally/$(DEPDIR)/cally-clone.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cally/$(DEPDIR)/cally-group.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cally/$(DEPDIR)/cally-rectangle.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cally/$(DEPDIR)/cally-root.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cally/$(DEPDIR)/cally-stage.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cally/$(DEPDIR)/cally-text.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cally/$(DEPDIR)/cally-texture.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cally/$(DEPDIR)/cally-util.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cally/$(DEPDIR)/cally.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@cogl/$(DEPDIR)/clutter-stage-cogl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-actor-deprecated.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-alpha.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-animation.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-animator.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-behaviour-depth.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-behaviour-ellipse.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-behaviour-opacity.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-behaviour-path.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-behaviour-rotate.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-behaviour-scale.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-behaviour.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-box.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-cairo-texture.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-frame-source.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-group.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-input-device-deprecated.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-layout-manager-deprecated.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-list-model.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-media.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-model.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-rectangle.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-score.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-shader.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-state.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-table-layout.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-texture.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-timeout-interval.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/clutter-timeout-pool.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@egl/$(DEPDIR)/clutter-backend-eglnative.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@evdev/$(DEPDIR)/clutter-device-manager-evdev.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@evdev/$(DEPDIR)/clutter-event-evdev.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@evdev/$(DEPDIR)/clutter-input-device-evdev.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@evdev/$(DEPDIR)/clutter-input-device-tool-evdev.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@evdev/$(DEPDIR)/clutter-seat-evdev.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@evdev/$(DEPDIR)/clutter-virtual-input-device-evdev.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@evdev/$(DEPDIR)/clutter-xkb-utils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@wayland/$(DEPDIR)/clutter-wayland-surface.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@x11/$(DEPDIR)/clutter-backend-x11.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@x11/$(DEPDIR)/clutter-device-manager-core-x11.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@x11/$(DEPDIR)/clutter-device-manager-xi2.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@x11/$(DEPDIR)/clutter-event-x11.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@x11/$(DEPDIR)/clutter-input-device-core-x11.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@x11/$(DEPDIR)/clutter-input-device-xi2.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@x11/$(DEPDIR)/clutter-keymap-x11.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@x11/$(DEPDIR)/clutter-stage-x11.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@x11/$(DEPDIR)/clutter-virtual-input-device-x11.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@x11/$(DEPDIR)/clutter-x11-texture-pixmap.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@x11/xsettings/$(DEPDIR)/xsettings-client.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@x11/xsettings/$(DEPDIR)/xsettings-common.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + -rm -rf cally/.libs cally/_libs + -rm -rf cogl/.libs cogl/_libs + -rm -rf deprecated/.libs deprecated/_libs + -rm -rf egl/.libs egl/_libs + -rm -rf evdev/.libs evdev/_libs + -rm -rf wayland/.libs wayland/_libs + -rm -rf x11/.libs x11/_libs + -rm -rf x11/xsettings/.libs x11/xsettings/_libs +install-girDATA: $(gir_DATA) + @$(NORMAL_INSTALL) + @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(girdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(girdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(girdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(girdir)" || exit $$?; \ + done + +uninstall-girDATA: + @$(NORMAL_UNINSTALL) + @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(girdir)'; $(am__uninstall_files_from_dir) +install-pkgconfigDATA: $(pkgconfig_DATA) + @$(NORMAL_INSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ + done + +uninstall-pkgconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) +install-typelibDATA: $(typelib_DATA) + @$(NORMAL_INSTALL) + @list='$(typelib_DATA)'; test -n "$(typelibdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(typelibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(typelibdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(typelibdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(typelibdir)" || exit $$?; \ + done + +uninstall-typelibDATA: + @$(NORMAL_UNINSTALL) + @list='$(typelib_DATA)'; test -n "$(typelibdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(typelibdir)'; $(am__uninstall_files_from_dir) +install-cally_includeHEADERS: $(cally_include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(cally_include_HEADERS)'; test -n "$(cally_includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(cally_includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(cally_includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(cally_includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(cally_includedir)" || exit $$?; \ + done + +uninstall-cally_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(cally_include_HEADERS)'; test -n "$(cally_includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(cally_includedir)'; $(am__uninstall_files_from_dir) +install-clutter_deprecatedHEADERS: $(clutter_deprecated_HEADERS) + @$(NORMAL_INSTALL) + @list='$(clutter_deprecated_HEADERS)'; test -n "$(clutter_deprecateddir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(clutter_deprecateddir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(clutter_deprecateddir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(clutter_deprecateddir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(clutter_deprecateddir)" || exit $$?; \ + done + +uninstall-clutter_deprecatedHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(clutter_deprecated_HEADERS)'; test -n "$(clutter_deprecateddir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(clutter_deprecateddir)'; $(am__uninstall_files_from_dir) +install-clutter_includeHEADERS: $(clutter_include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(clutter_include_HEADERS)'; test -n "$(clutter_includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(clutter_includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(clutter_includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(clutter_includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(clutter_includedir)" || exit $$?; \ + done + +uninstall-clutter_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(clutter_include_HEADERS)'; test -n "$(clutter_includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(clutter_includedir)'; $(am__uninstall_files_from_dir) +install-clutteregl_includeHEADERS: $(clutteregl_include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(clutteregl_include_HEADERS)'; test -n "$(clutteregl_includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(clutteregl_includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(clutteregl_includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(clutteregl_includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(clutteregl_includedir)" || exit $$?; \ + done + +uninstall-clutteregl_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(clutteregl_include_HEADERS)'; test -n "$(clutteregl_includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(clutteregl_includedir)'; $(am__uninstall_files_from_dir) +install-clutterevdev_includeHEADERS: $(clutterevdev_include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(clutterevdev_include_HEADERS)'; test -n "$(clutterevdev_includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(clutterevdev_includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(clutterevdev_includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(clutterevdev_includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(clutterevdev_includedir)" || exit $$?; \ + done + +uninstall-clutterevdev_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(clutterevdev_include_HEADERS)'; test -n "$(clutterevdev_includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(clutterevdev_includedir)'; $(am__uninstall_files_from_dir) +install-clutterx11_includeHEADERS: $(clutterx11_include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(clutterx11_include_HEADERS)'; test -n "$(clutterx11_includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(clutterx11_includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(clutterx11_includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(clutterx11_includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(clutterx11_includedir)" || exit $$?; \ + done + +uninstall-clutterx11_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(clutterx11_include_HEADERS)'; test -n "$(clutterx11_includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(clutterx11_includedir)'; $(am__uninstall_files_from_dir) +install-nodist_clutter_includeHEADERS: $(nodist_clutter_include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(nodist_clutter_include_HEADERS)'; test -n "$(clutter_includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(clutter_includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(clutter_includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(clutter_includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(clutter_includedir)" || exit $$?; \ + done + +uninstall-nodist_clutter_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nodist_clutter_include_HEADERS)'; test -n "$(clutter_includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(clutter_includedir)'; $(am__uninstall_files_from_dir) +install-wayland_compositor_includeHEADERS: $(wayland_compositor_include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(wayland_compositor_include_HEADERS)'; test -n "$(wayland_compositor_includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(wayland_compositor_includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(wayland_compositor_includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(wayland_compositor_includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(wayland_compositor_includedir)" || exit $$?; \ + done + +uninstall-wayland_compositor_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(wayland_compositor_include_HEADERS)'; test -n "$(wayland_compositor_includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(wayland_compositor_includedir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) \ + clutter-build-config.h +installdirs: + for dir in "$(DESTDIR)$(mutterlibdir)" "$(DESTDIR)$(girdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(typelibdir)" "$(DESTDIR)$(cally_includedir)" "$(DESTDIR)$(clutter_deprecateddir)" "$(DESTDIR)$(clutter_includedir)" "$(DESTDIR)$(clutteregl_includedir)" "$(DESTDIR)$(clutterevdev_includedir)" "$(DESTDIR)$(clutterx11_includedir)" "$(DESTDIR)$(clutter_includedir)" "$(DESTDIR)$(wayland_compositor_includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f cally/$(DEPDIR)/$(am__dirstamp) + -rm -f cally/$(am__dirstamp) + -rm -f cogl/$(DEPDIR)/$(am__dirstamp) + -rm -f cogl/$(am__dirstamp) + -rm -f deprecated/$(DEPDIR)/$(am__dirstamp) + -rm -f deprecated/$(am__dirstamp) + -rm -f egl/$(DEPDIR)/$(am__dirstamp) + -rm -f egl/$(am__dirstamp) + -rm -f evdev/$(DEPDIR)/$(am__dirstamp) + -rm -f evdev/$(am__dirstamp) + -rm -f wayland/$(DEPDIR)/$(am__dirstamp) + -rm -f wayland/$(am__dirstamp) + -rm -f x11/$(DEPDIR)/$(am__dirstamp) + -rm -f x11/$(am__dirstamp) + -rm -f x11/xsettings/$(DEPDIR)/$(am__dirstamp) + -rm -f x11/xsettings/$(am__dirstamp) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-mutterlibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) cally/$(DEPDIR) cogl/$(DEPDIR) deprecated/$(DEPDIR) egl/$(DEPDIR) evdev/$(DEPDIR) wayland/$(DEPDIR) x11/$(DEPDIR) x11/xsettings/$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-hdr distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-cally_includeHEADERS \ + install-clutter_deprecatedHEADERS \ + install-clutter_includeHEADERS \ + install-clutteregl_includeHEADERS \ + install-clutterevdev_includeHEADERS \ + install-clutterx11_includeHEADERS install-girDATA \ + install-mutterlibLTLIBRARIES \ + install-nodist_clutter_includeHEADERS install-pkgconfigDATA \ + install-typelibDATA install-wayland_compositor_includeHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-exec-local + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) cally/$(DEPDIR) cogl/$(DEPDIR) deprecated/$(DEPDIR) egl/$(DEPDIR) evdev/$(DEPDIR) wayland/$(DEPDIR) x11/$(DEPDIR) x11/xsettings/$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-cally_includeHEADERS \ + uninstall-clutter_deprecatedHEADERS \ + uninstall-clutter_includeHEADERS \ + uninstall-clutteregl_includeHEADERS \ + uninstall-clutterevdev_includeHEADERS \ + uninstall-clutterx11_includeHEADERS uninstall-girDATA \ + uninstall-mutterlibLTLIBRARIES \ + uninstall-nodist_clutter_includeHEADERS \ + uninstall-pkgconfigDATA uninstall-typelibDATA \ + uninstall-wayland_compositor_includeHEADERS + +.MAKE: all check install install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-mutterlibLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-hdr distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-cally_includeHEADERS install-clutter_deprecatedHEADERS \ + install-clutter_includeHEADERS \ + install-clutteregl_includeHEADERS \ + install-clutterevdev_includeHEADERS \ + install-clutterx11_includeHEADERS install-data install-data-am \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-exec-local install-girDATA install-html \ + install-html-am install-info install-info-am install-man \ + install-mutterlibLTLIBRARIES \ + install-nodist_clutter_includeHEADERS install-pdf \ + install-pdf-am install-pkgconfigDATA install-ps install-ps-am \ + install-strip install-typelibDATA \ + install-wayland_compositor_includeHEADERS installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am \ + uninstall-cally_includeHEADERS \ + uninstall-clutter_deprecatedHEADERS \ + uninstall-clutter_includeHEADERS \ + uninstall-clutteregl_includeHEADERS \ + uninstall-clutterevdev_includeHEADERS \ + uninstall-clutterx11_includeHEADERS uninstall-girDATA \ + uninstall-mutterlibLTLIBRARIES \ + uninstall-nodist_clutter_includeHEADERS \ + uninstall-pkgconfigDATA uninstall-typelibDATA \ + uninstall-wayland_compositor_includeHEADERS + +.PRECIOUS: Makefile + + +mutter-clutter-x11-$(CLUTTER_API_VERSION).pc: mutter-clutter-$(CLUTTER_API_VERSION).pc + $(QUIET_GEN)cp -f $< $(@F) + +# Basic sanity checks +$(if $(GLIB_GENMARSHAL),,$(error Need to define GLIB_GENMARSHAL)) + +$(if $(or $(glib_marshal_list), \ + $(glib_marshal_prefix)),, \ + $(error Need to define glib_marshal_list and glib_marshal_prefix)) + +stamp-marshal: $(marshal_list) + $(AM_V_GEN)$(GLIB_GENMARSHAL) \ + --prefix=$(glib_marshal_prefix) \ + --header \ + $(marshal_list) > xgen-mh \ + && (cmp -s xgen-mh $(marshal_h) || cp -f xgen-mh $(marshal_h)) \ + && rm -f xgen-mh \ + && echo timestamp > $(@F) + +$(marshal_h): stamp-marshal + @true + +$(marshal_c): $(marshal_h) + $(AM_V_GEN)(echo "#include \"$(marshal_h)\"" ; \ + $(GLIB_GENMARSHAL) \ + --prefix=$(glib_marshal_prefix) \ + --body \ + $(marshal_list)) > xgen-mc \ + && cp xgen-mc $(marshal_c) \ + && rm -f xgen-mc + +# Basic sanity checks +$(if $(GLIB_MKENUMS),,$(error Need to define GLIB_MKENUMS)) + +$(if $(or $(glib_enum_h), \ + $(glib_enum_c)),, \ + $(error Need to define glib_enum_h and glib_enum_c)) + +$(if $(glib_enum_headers),,$(error Need to define glib_enum_headers)) + +stamp-enum-types: $(enum_headers) $(enum_tmpl_h) + $(AM_V_GEN)$(GLIB_MKENUMS) \ + --template $(enum_tmpl_h) \ + $(enum_headers) > xgen-eh \ + && (cmp -s xgen-eh $(glib_enum_h) || cp -f xgen-eh $(glib_enum_h)) \ + && rm -f xgen-eh \ + && echo timestamp > $(@F) + +$(glib_enum_h): stamp-enum-types + @true + +$(glib_enum_c): $(enum_headers) $(enum_tmpl_h) $(enum_tmpl_c) + $(AM_V_GEN)$(GLIB_MKENUMS) \ + --template $(enum_tmpl_c) \ + $(enum_headers) > xgen-ec \ + && cp -f xgen-ec $(glib_enum_c) \ + && rm -f xgen-ec + +install-exec-local: + test -z "$(mutterlibdir)" || $(MKDIR_P) "$(DESTDIR)$(mutterlibdir)" + for lib in `echo $(compat_libs)`; do \ + (cd $(DESTDIR)$(mutterlibdir) && \ + rm -f $$lib.0.$(CLUTTER_LT_CURRENT).$(CLUTTER_LT_REVISION); \ + ) ; \ + (cd $(DESTDIR)$(mutterlibdir) && \ + { ln -s -f libmutter-clutter-$(CLUTTER_API_VERSION).so.0.$(CLUTTER_LT_CURRENT).$(CLUTTER_LT_REVISION) $$lib.0 || \ + { rm -f $$lib.0 && ln -s libmutter-clutter-1.0.so.0.$(CLUTTER_LT_CURRENT).$(CLUTTER_LT_REVISION) $$lib.0; }; \ + } \ + ) ; \ + (cd $(DESTDIR)$(mutterlibdir) && \ + { ln -s -f libmutter-clutter-$(CLUTTER_API_VERSION).so.0.$(CLUTTER_LT_CURRENT).$(CLUTTER_LT_REVISION) $$lib || \ + { rm -f $$lib && ln -s libmutter-clutter-1.0.so.0.$(CLUTTER_LT_CURRENT).$(CLUTTER_LT_REVISION) $$lib; }; \ + } \ + ) ; \ + done + +# gobject-introspection rules +-include $(INTROSPECTION_MAKEFILE) + +Clutter-@CLUTTER_API_VERSION@.gir: libmutter-clutter-@CLUTTER_API_VERSION@.la Makefile + +Cally-@CLUTTER_API_VERSION@.gir: Makefile Clutter-@CLUTTER_API_VERSION@.gir + +ClutterX11-@CLUTTER_API_VERSION@.gir: Makefile Clutter-@CLUTTER_API_VERSION@.gir + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/clutter/clutter/cally/cally-actor-private.h b/clutter/clutter/cally/cally-actor-private.h new file mode 100644 index 0000000..7e99278 --- /dev/null +++ b/clutter/clutter/cally/cally-actor-private.h @@ -0,0 +1,42 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2008 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * Some parts are based on GailWidget from GAIL + * GAIL - The GNOME Accessibility Implementation Library + * Copyright 2001, 2002, 2003 Sun Microsystems Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __CALLY_ACTOR_PRIVATE_H__ +#define __CALLY_ACTOR_PRIVATE_H__ + +#include "cally-actor.h" + +/* + * Auxiliar define, in order to get the clutter actor from the AtkObject using + * AtkGObject methods + * + */ +#define CALLY_GET_CLUTTER_ACTOR(cally_object) \ + (CLUTTER_ACTOR (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (cally_object)))) + +void _cally_actor_get_top_level_origin (ClutterActor *actor, + gint *x, + gint *y); + +#endif /* __CALLY_ACTOR_PRIVATE_H__ */ diff --git a/clutter/clutter/cally/cally-actor.c b/clutter/clutter/cally/cally-actor.c new file mode 100644 index 0000000..fe3e274 --- /dev/null +++ b/clutter/clutter/cally/cally-actor.c @@ -0,0 +1,1248 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2008 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * Some parts are based on GailWidget from GAIL + * GAIL - The GNOME Accessibility Implementation Library + * Copyright 2001, 2002, 2003 Sun Microsystems Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +/** + * SECTION:cally-actor + * @Title: CallyActor + * @short_description: Implementation of the ATK interfaces for #ClutterActor + * @see_also: #ClutterActor + * + * #CallyActor implements the required ATK interfaces of #ClutterActor + * exposing the common elements on each actor (position, extents, etc). + */ + +/* + * + * IMPLEMENTATION NOTES: + * + * #### + * + * Focus: clutter hasn't got the focus concept in the same way that GTK, but it + * has a key focus managed by the stage. Basically any actor can be focused using + * clutter_stage_set_key_focus. So, we will use this approach: all actors are + * focusable, and we get the currently focused using clutter_stage_get_key_focus + * This affects focus related stateset and some atk_componenet focus methods (like + * grab focus). + * + * In the same way, we will manage the focus state change management + * on the cally-stage object. The reason is avoid missing a focus + * state change event if the object is focused just before the + * accessibility object being created. + * + * #AtkAction implementation: on previous releases ClutterActor added + * the actions "press", "release" and "click", as at that time some + * general-purpose actors like textures were directly used as buttons. + * + * But now, new toolkits appeared, providing high-level widgets, like + * buttons. So in this environment, it doesn't make sense to keep + * adding them as default. + * + * Anyway, current implementation of AtkAction is done at CallyActor + * providing methods to add and remove actions. This is based on the + * one used at gailcell, and proposed as a change on #AtkAction + * interface: + * + * https://bugzilla.gnome.org/show_bug.cgi?id=649804 + * + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include +#include + +#ifdef CLUTTER_WINDOWING_X11 +#include +#endif + +#include + +#include "cally-actor.h" +#include "cally-actor-private.h" + +typedef struct _CallyActorActionInfo CallyActorActionInfo; + +/*< private > + * CallyActorActionInfo: + * @name: name of the action + * @description: description of the action + * @keybinding: keybinding related to the action + * @do_action_func: callback + * @user_data: data to be passed to @do_action_func + * @notify: function to be called when removing the action + * + * Utility structure to maintain the different actions added to the + * #CallyActor + */ +struct _CallyActorActionInfo +{ + gchar *name; + gchar *description; + gchar *keybinding; + + CallyActionCallback do_action_func; + gpointer user_data; + GDestroyNotify notify; +}; + +static void cally_actor_initialize (AtkObject *obj, + gpointer data); +static void cally_actor_finalize (GObject *obj); + +/* AtkObject.h */ +static AtkObject* cally_actor_get_parent (AtkObject *obj); +static gint cally_actor_get_index_in_parent (AtkObject *obj); +static AtkStateSet* cally_actor_ref_state_set (AtkObject *obj); +static gint cally_actor_get_n_children (AtkObject *obj); +static AtkObject* cally_actor_ref_child (AtkObject *obj, + gint i); +static AtkAttributeSet * cally_actor_get_attributes (AtkObject *obj); + +/* ClutterContainer */ +static gint cally_actor_add_actor (ClutterActor *container, + ClutterActor *actor, + gpointer data); +static gint cally_actor_remove_actor (ClutterActor *container, + ClutterActor *actor, + gpointer data); +static gint cally_actor_real_add_actor (ClutterActor *container, + ClutterActor *actor, + gpointer data); +static gint cally_actor_real_remove_actor (ClutterActor *container, + ClutterActor *actor, + gpointer data); + +/* AtkComponent.h */ +static void cally_actor_component_interface_init (AtkComponentIface *iface); +static void cally_actor_get_extents (AtkComponent *component, + gint *x, + gint *y, + gint *width, + gint *height, + AtkCoordType coord_type); +static gint cally_actor_get_mdi_zorder (AtkComponent *component); +static gboolean cally_actor_grab_focus (AtkComponent *component); + +/* AtkAction.h */ +static void cally_actor_action_interface_init (AtkActionIface *iface); +static gboolean cally_actor_action_do_action (AtkAction *action, + gint i); +static gboolean idle_do_action (gpointer data); +static gint cally_actor_action_get_n_actions (AtkAction *action); +static const gchar* cally_actor_action_get_description (AtkAction *action, + gint i); +static const gchar* cally_actor_action_get_keybinding (AtkAction *action, + gint i); +static const gchar* cally_actor_action_get_name (AtkAction *action, + gint i); +static gboolean cally_actor_action_set_description (AtkAction *action, + gint i, + const gchar *desc); +static void _cally_actor_destroy_action_info (gpointer action_info, + gpointer user_data); +static void _cally_actor_clean_action_list (CallyActor *cally_actor); + +static CallyActorActionInfo* _cally_actor_get_action_info (CallyActor *cally_actor, + gint index); +/* Misc functions */ +static void cally_actor_notify_clutter (GObject *obj, + GParamSpec *pspec); +static void cally_actor_real_notify_clutter (GObject *obj, + GParamSpec *pspec); + +struct _CallyActorPrivate +{ + GQueue *action_queue; + guint action_idle_handler; + GList *action_list; + + GList *children; +}; + +G_DEFINE_TYPE_WITH_CODE (CallyActor, + cally_actor, + ATK_TYPE_GOBJECT_ACCESSIBLE, + G_ADD_PRIVATE (CallyActor) + G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT, + cally_actor_component_interface_init) + G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, + cally_actor_action_interface_init)); + +/** + * cally_actor_new: + * @actor: a #ClutterActor + * + * Creates a new #CallyActor for the given @actor + * + * Return value: the newly created #AtkObject + * + * Since: 1.4 + */ +AtkObject * +cally_actor_new (ClutterActor *actor) +{ + gpointer object; + AtkObject *atk_object; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), NULL); + + object = g_object_new (CALLY_TYPE_ACTOR, NULL); + + atk_object = ATK_OBJECT (object); + atk_object_initialize (atk_object, actor); + + return atk_object; +} + +static void +cally_actor_initialize (AtkObject *obj, + gpointer data) +{ + CallyActor *self = NULL; + CallyActorPrivate *priv = NULL; + ClutterActor *actor = NULL; + guint handler_id; + + ATK_OBJECT_CLASS (cally_actor_parent_class)->initialize (obj, data); + + self = CALLY_ACTOR(obj); + priv = self->priv; + actor = CLUTTER_ACTOR (data); + + g_signal_connect (actor, + "notify", + G_CALLBACK (cally_actor_notify_clutter), + NULL); + + g_object_set_data (G_OBJECT (obj), "atk-component-layer", + GINT_TO_POINTER (ATK_LAYER_MDI)); + + priv->children = clutter_actor_get_children (actor); + + /* + * We store the handler ids for these signals in case some objects + * need to remove these handlers. + */ + handler_id = g_signal_connect (actor, + "actor-added", + G_CALLBACK (cally_actor_add_actor), + obj); + g_object_set_data (G_OBJECT (obj), "cally-add-handler-id", + GUINT_TO_POINTER (handler_id)); + handler_id = g_signal_connect (actor, + "actor-removed", + G_CALLBACK (cally_actor_remove_actor), + obj); + g_object_set_data (G_OBJECT (obj), "cally-remove-handler-id", + GUINT_TO_POINTER (handler_id)); + + obj->role = ATK_ROLE_PANEL; /* typically objects implementing ClutterContainer + interface would be a panel */ +} + +static void +cally_actor_class_init (CallyActorClass *klass) +{ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + klass->notify_clutter = cally_actor_real_notify_clutter; + klass->add_actor = cally_actor_real_add_actor; + klass->remove_actor = cally_actor_real_remove_actor; + + /* GObject */ + gobject_class->finalize = cally_actor_finalize; + + /* AtkObject */ + class->get_parent = cally_actor_get_parent; + class->get_index_in_parent = cally_actor_get_index_in_parent; + class->ref_state_set = cally_actor_ref_state_set; + class->initialize = cally_actor_initialize; + class->get_n_children = cally_actor_get_n_children; + class->ref_child = cally_actor_ref_child; + class->get_attributes = cally_actor_get_attributes; +} + +static void +cally_actor_init (CallyActor *cally_actor) +{ + CallyActorPrivate *priv = cally_actor_get_instance_private (cally_actor); + + cally_actor->priv = priv; + + priv->action_queue = NULL; + priv->action_idle_handler = 0; + + priv->action_list = NULL; + + priv->children = NULL; +} + +static void +cally_actor_finalize (GObject *obj) +{ + CallyActor *cally_actor = NULL; + CallyActorPrivate *priv = NULL; + + cally_actor = CALLY_ACTOR (obj); + priv = cally_actor->priv; + + _cally_actor_clean_action_list (cally_actor); + + if (priv->action_idle_handler) + { + g_source_remove (priv->action_idle_handler); + priv->action_idle_handler = 0; + } + + if (priv->action_queue) + { + g_queue_free (priv->action_queue); + } + + if (priv->children) + { + g_list_free (priv->children); + priv->children = NULL; + } + + G_OBJECT_CLASS (cally_actor_parent_class)->finalize (obj); +} + +/* AtkObject */ + +static AtkObject * +cally_actor_get_parent (AtkObject *obj) +{ + ClutterActor *parent_actor = NULL; + AtkObject *parent = NULL; + ClutterActor *actor = NULL; + CallyActor *cally_actor = NULL; + + g_return_val_if_fail (CALLY_IS_ACTOR (obj), NULL); + + /* Check if we have and assigned parent */ + if (obj->accessible_parent) + return obj->accessible_parent; + + /* Try to get it from the clutter parent */ + cally_actor = CALLY_ACTOR (obj); + actor = CALLY_GET_CLUTTER_ACTOR (cally_actor); + if (actor == NULL) /* Object is defunct */ + return NULL; + + parent_actor = clutter_actor_get_parent (actor); + if (parent_actor == NULL) + return NULL; + + parent = clutter_actor_get_accessible (parent_actor); + + /* FIXME: I need to review the clutter-embed, to check if in this case I + * should get the widget accessible + */ + + return parent; +} + +static gint +cally_actor_get_index_in_parent (AtkObject *obj) +{ + CallyActor *cally_actor = NULL; + ClutterActor *actor = NULL; + ClutterActor *parent_actor = NULL; + ClutterActor *iter; + gint index = -1; + + g_return_val_if_fail (CALLY_IS_ACTOR (obj), -1); + + if (obj->accessible_parent) + { + gint n_children, i; + gboolean found = FALSE; + + n_children = atk_object_get_n_accessible_children (obj->accessible_parent); + for (i = 0; i < n_children; i++) + { + AtkObject *child; + + child = atk_object_ref_accessible_child (obj->accessible_parent, i); + if (child == obj) + found = TRUE; + + g_object_unref (child); + if (found) + return i; + } + return -1; + } + + cally_actor = CALLY_ACTOR (obj); + actor = CALLY_GET_CLUTTER_ACTOR (cally_actor); + if (actor == NULL) /* Object is defunct */ + return -1; + + index = 0; + parent_actor = clutter_actor_get_parent (actor); + if (parent_actor == NULL) + return -1; + + for (iter = clutter_actor_get_first_child (parent_actor); + iter != NULL && iter != actor; + iter = clutter_actor_get_next_sibling (iter)) + { + index += 1; + } + + return index; +} + +static AtkStateSet* +cally_actor_ref_state_set (AtkObject *obj) +{ + ClutterActor *actor = NULL; + AtkStateSet *state_set = NULL; + ClutterStage *stage = NULL; + ClutterActor *focus_actor = NULL; + CallyActor *cally_actor = NULL; + + g_return_val_if_fail (CALLY_IS_ACTOR (obj), NULL); + cally_actor = CALLY_ACTOR (obj); + + state_set = ATK_OBJECT_CLASS (cally_actor_parent_class)->ref_state_set (obj); + + actor = CALLY_GET_CLUTTER_ACTOR (cally_actor); + + if (actor == NULL) /* Object is defunct */ + { + atk_state_set_add_state (state_set, ATK_STATE_DEFUNCT); + } + else + { + if (clutter_actor_get_reactive (actor)) + { + atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE); + atk_state_set_add_state (state_set, ATK_STATE_ENABLED); + } + + if (clutter_actor_is_visible (actor)) + { + atk_state_set_add_state (state_set, ATK_STATE_VISIBLE); + + /* It would be good to also check if the actor is on screen, + like the old and removed clutter_actor_is_on_stage*/ + if (clutter_actor_get_paint_visibility (actor)) + atk_state_set_add_state (state_set, ATK_STATE_SHOWING); + + } + + /* See focus section on implementation notes */ + atk_state_set_add_state (state_set, ATK_STATE_FOCUSABLE); + + stage = CLUTTER_STAGE (clutter_actor_get_stage (actor)); + if (stage != NULL) + { + focus_actor = clutter_stage_get_key_focus (stage); + if (focus_actor == actor) + atk_state_set_add_state (state_set, ATK_STATE_FOCUSED); + } + } + + return state_set; +} + +static gint +cally_actor_get_n_children (AtkObject *obj) +{ + ClutterActor *actor = NULL; + + g_return_val_if_fail (CALLY_IS_ACTOR (obj), 0); + + actor = CALLY_GET_CLUTTER_ACTOR (obj); + + if (actor == NULL) /* State is defunct */ + return 0; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), 0); + + return clutter_actor_get_n_children (actor); +} + +static AtkObject* +cally_actor_ref_child (AtkObject *obj, + gint i) +{ + ClutterActor *actor = NULL; + ClutterActor *child = NULL; + + g_return_val_if_fail (CALLY_IS_ACTOR (obj), NULL); + + actor = CALLY_GET_CLUTTER_ACTOR (obj); + if (actor == NULL) /* State is defunct */ + return NULL; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), NULL); + + if (i >= clutter_actor_get_n_children (actor)) + return NULL; + + child = clutter_actor_get_child_at_index (actor, i); + if (child == NULL) + return NULL; + + return g_object_ref (clutter_actor_get_accessible (child)); +} + +static AtkAttributeSet * +cally_actor_get_attributes (AtkObject *obj) +{ + AtkAttributeSet *attributes; + AtkAttribute *toolkit; + + toolkit = g_new (AtkAttribute, 1); + toolkit->name = g_strdup ("toolkit"); + toolkit->value = g_strdup ("clutter"); + + attributes = g_slist_append (NULL, toolkit); + + return attributes; +} + +/* ClutterContainer */ +static gint +cally_actor_add_actor (ClutterActor *container, + ClutterActor *actor, + gpointer data) +{ + CallyActor *cally_actor = CALLY_ACTOR (data); + CallyActorClass *klass = NULL; + + klass = CALLY_ACTOR_GET_CLASS (cally_actor); + + if (klass->add_actor) + return klass->add_actor (container, actor, data); + else + return 1; +} + +static gint +cally_actor_remove_actor (ClutterActor *container, + ClutterActor *actor, + gpointer data) +{ + CallyActor *cally_actor = CALLY_ACTOR (data); + CallyActorClass *klass = NULL; + + klass = CALLY_ACTOR_GET_CLASS (cally_actor); + + if (klass->remove_actor) + return klass->remove_actor (container, actor, data); + else + return 1; +} + + +static gint +cally_actor_real_add_actor (ClutterActor *container, + ClutterActor *actor, + gpointer data) +{ + AtkObject *atk_parent = ATK_OBJECT (data); + AtkObject *atk_child = clutter_actor_get_accessible (actor); + CallyActor *cally_actor = CALLY_ACTOR (atk_parent); + CallyActorPrivate *priv = cally_actor->priv; + gint index; + + g_return_val_if_fail (CLUTTER_IS_CONTAINER (container), 0); + g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), 0); + + g_object_notify (G_OBJECT (atk_child), "accessible_parent"); + + g_list_free (priv->children); + + priv->children = clutter_actor_get_children (CLUTTER_ACTOR (container)); + + index = g_list_index (priv->children, actor); + g_signal_emit_by_name (atk_parent, "children_changed::add", + index, atk_child, NULL); + + return 1; +} + +static gint +cally_actor_real_remove_actor (ClutterActor *container, + ClutterActor *actor, + gpointer data) +{ + AtkPropertyValues values = { NULL }; + AtkObject* atk_parent = NULL; + AtkObject *atk_child = NULL; + CallyActorPrivate *priv = NULL; + gint index; + + g_return_val_if_fail (CLUTTER_IS_CONTAINER (container), 0); + g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), 0); + + atk_parent = ATK_OBJECT (data); + atk_child = clutter_actor_get_accessible (actor); + + if (atk_child) + { + g_value_init (&values.old_value, G_TYPE_POINTER); + g_value_set_pointer (&values.old_value, atk_parent); + + values.property_name = "accessible-parent"; + + g_object_ref (atk_child); + g_signal_emit_by_name (atk_child, + "property_change::accessible-parent", &values, NULL); + g_object_unref (atk_child); + } + + priv = CALLY_ACTOR (atk_parent)->priv; + index = g_list_index (priv->children, actor); + g_list_free (priv->children); + + priv->children = clutter_actor_get_children (CLUTTER_ACTOR (container)); + + if (index >= 0 && index <= g_list_length (priv->children)) + g_signal_emit_by_name (atk_parent, "children_changed::remove", + index, atk_child, NULL); + + return 1; +} + +/* AtkComponent implementation */ +static void +cally_actor_component_interface_init (AtkComponentIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->get_extents = cally_actor_get_extents; + iface->get_mdi_zorder = cally_actor_get_mdi_zorder; + + /* focus management */ + iface->grab_focus = cally_actor_grab_focus; +} + +static void +cally_actor_get_extents (AtkComponent *component, + gint *x, + gint *y, + gint *width, + gint *height, + AtkCoordType coord_type) +{ + CallyActor *cally_actor = NULL; + ClutterActor *actor = NULL; + gint top_level_x, top_level_y; + gfloat f_width, f_height; + ClutterVertex verts[4]; + ClutterActor *stage = NULL; + + g_return_if_fail (CALLY_IS_ACTOR (component)); + + cally_actor = CALLY_ACTOR (component); + actor = CALLY_GET_CLUTTER_ACTOR (cally_actor); + + if (actor == NULL) /* actor is defunct */ + return; + + /* If the actor is not placed in any stage, we can't compute the + * extents */ + stage = clutter_actor_get_stage (actor); + if (stage == NULL) + return; + + clutter_actor_get_abs_allocation_vertices (actor, verts); + clutter_actor_get_transformed_size (actor, &f_width, &f_height); + + *x = verts[0].x; + *y = verts[0].y; + *width = ceilf (f_width); + *height = ceilf (f_height); + + /* In the ATK_XY_WINDOW case, we consider the stage as the + * "top-level-window" + * + * http://library.gnome.org/devel/atk/stable/AtkUtil.html#AtkCoordType + */ + + if (coord_type == ATK_XY_SCREEN) + { + _cally_actor_get_top_level_origin (actor, &top_level_x, &top_level_y); + + *x += top_level_x; + *y += top_level_y; + } + + return; +} + +static gint +cally_actor_get_mdi_zorder (AtkComponent *component) +{ + CallyActor *cally_actor = NULL; + ClutterActor *actor = NULL; + + g_return_val_if_fail (CALLY_IS_ACTOR (component), G_MININT); + + cally_actor = CALLY_ACTOR(component); + actor = CALLY_GET_CLUTTER_ACTOR (cally_actor); + + return clutter_actor_get_z_position (actor); +} + +static gboolean +cally_actor_grab_focus (AtkComponent *component) +{ + ClutterActor *actor = NULL; + ClutterActor *stage = NULL; + CallyActor *cally_actor = NULL; + + g_return_val_if_fail (CALLY_IS_ACTOR (component), FALSE); + + /* See focus section on implementation notes */ + cally_actor = CALLY_ACTOR(component); + actor = CALLY_GET_CLUTTER_ACTOR (cally_actor); + stage = clutter_actor_get_stage (actor); + + clutter_stage_set_key_focus (CLUTTER_STAGE (stage), + actor); + + return TRUE; +} + +/* + * + * This gets the top level origin, it is, the position of the stage in + * the global screen. You can see it as the absolute display position + * of the stage. + * + * FIXME: only the case with x11 is implemented, other backends are + * required + * + */ +void +_cally_actor_get_top_level_origin (ClutterActor *actor, + gint *xp, + gint *yp) +{ + /* default values */ + gint x = 0; + gint y = 0; + +#ifdef CLUTTER_WINDOWING_X11 + if (clutter_check_windowing_backend (CLUTTER_WINDOWING_X11)) + { + ClutterActor *stage = NULL; + Display *display = NULL; + Window root_window; + Window stage_window; + Window child; + gint return_val = 0; + + stage = clutter_actor_get_stage (actor); + + /* FIXME: what happens if you use another display with + clutter_backend_x11_set_display ?*/ + display = clutter_x11_get_default_display (); + root_window = clutter_x11_get_root_window (); + stage_window = clutter_x11_get_stage_window (CLUTTER_STAGE (stage)); + + return_val = XTranslateCoordinates (display, stage_window, root_window, + 0, 0, &x, &y, + &child); + + if (!return_val) + g_warning ("[x11] We were not able to get proper absolute " + "position of the stage"); + } + else +#else + { + static gboolean yet_warned = FALSE; + + if (!yet_warned) + { + yet_warned = TRUE; + + g_warning ("The current Clutter backend does not support using " + "atk_component_get_extents() with ATK_XY_SCREEN."); + } + } +#endif + + if (xp) + *xp = x; + + if (yp) + *yp = y; +} + +/* AtkAction implementation */ +static void +cally_actor_action_interface_init (AtkActionIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->do_action = cally_actor_action_do_action; + iface->get_n_actions = cally_actor_action_get_n_actions; + iface->get_description = cally_actor_action_get_description; + iface->get_keybinding = cally_actor_action_get_keybinding; + iface->get_name = cally_actor_action_get_name; + iface->set_description = cally_actor_action_set_description; +} + +static gboolean +cally_actor_action_do_action (AtkAction *action, + gint index) +{ + CallyActor *cally_actor = NULL; + AtkStateSet *set = NULL; + CallyActorPrivate *priv = NULL; + CallyActorActionInfo *info = NULL; + + cally_actor = CALLY_ACTOR (action); + priv = cally_actor->priv; + + set = atk_object_ref_state_set (ATK_OBJECT (cally_actor)); + + if (atk_state_set_contains_state (set, ATK_STATE_DEFUNCT)) + return FALSE; + + if (!atk_state_set_contains_state (set, ATK_STATE_SENSITIVE) || + !atk_state_set_contains_state (set, ATK_STATE_SHOWING)) + return FALSE; + + g_object_unref (set); + + info = _cally_actor_get_action_info (cally_actor, index); + + if (info == NULL) + return FALSE; + + if (info->do_action_func == NULL) + return FALSE; + + if (!priv->action_queue) + priv->action_queue = g_queue_new (); + + g_queue_push_head (priv->action_queue, info); + + if (!priv->action_idle_handler) + priv->action_idle_handler = g_idle_add (idle_do_action, cally_actor); + + return TRUE; +} + +static gboolean +idle_do_action (gpointer data) +{ + CallyActor *cally_actor = NULL; + CallyActorPrivate *priv = NULL; + ClutterActor *actor = NULL; + + cally_actor = CALLY_ACTOR (data); + priv = cally_actor->priv; + actor = CALLY_GET_CLUTTER_ACTOR (cally_actor); + priv->action_idle_handler = 0; + + if (actor == NULL) /* state is defunct*/ + return FALSE; + + while (!g_queue_is_empty (priv->action_queue)) + { + CallyActorActionInfo *info = NULL; + + info = (CallyActorActionInfo *) g_queue_pop_head (priv->action_queue); + + info->do_action_func (cally_actor, info->user_data); + } + + return FALSE; +} + +static gint +cally_actor_action_get_n_actions (AtkAction *action) +{ + CallyActor *cally_actor = NULL; + CallyActorPrivate *priv = NULL; + + g_return_val_if_fail (CALLY_IS_ACTOR (action), 0); + + cally_actor = CALLY_ACTOR (action); + priv = cally_actor->priv; + + return g_list_length (priv->action_list); +} + +static const gchar* +cally_actor_action_get_name (AtkAction *action, + gint i) +{ + CallyActor *cally_actor = NULL; + CallyActorActionInfo *info = NULL; + + g_return_val_if_fail (CALLY_IS_ACTOR (action), NULL); + cally_actor = CALLY_ACTOR (action); + info = _cally_actor_get_action_info (cally_actor, i); + + if (info == NULL) + return NULL; + + return info->name; +} + +static const gchar* +cally_actor_action_get_description (AtkAction *action, + gint i) +{ + CallyActor *cally_actor = NULL; + CallyActorActionInfo *info = NULL; + + g_return_val_if_fail (CALLY_IS_ACTOR (action), NULL); + cally_actor = CALLY_ACTOR (action); + info = _cally_actor_get_action_info (cally_actor, i); + + if (info == NULL) + return NULL; + + return info->description; +} + +static gboolean +cally_actor_action_set_description (AtkAction *action, + gint i, + const gchar *desc) +{ + CallyActor *cally_actor = NULL; + CallyActorActionInfo *info = NULL; + + g_return_val_if_fail (CALLY_IS_ACTOR (action), FALSE); + cally_actor = CALLY_ACTOR (action); + info = _cally_actor_get_action_info (cally_actor, i); + + if (info == NULL) + return FALSE; + + g_free (info->description); + info->description = g_strdup (desc); + + return TRUE; +} + +static const gchar* +cally_actor_action_get_keybinding (AtkAction *action, + gint i) +{ + CallyActor *cally_actor = NULL; + CallyActorActionInfo *info = NULL; + + g_return_val_if_fail (CALLY_IS_ACTOR (action), NULL); + cally_actor = CALLY_ACTOR (action); + info = _cally_actor_get_action_info (cally_actor, i); + + if (info == NULL) + return NULL; + + return info->keybinding; +} + +/* Misc functions */ + +/* + * This function is a signal handler for notify signal which gets emitted + * when a property changes value on the ClutterActor associated with the object. + * + * It calls a function for the CallyActor type + */ +static void +cally_actor_notify_clutter (GObject *obj, + GParamSpec *pspec) +{ + CallyActor *cally_actor = NULL; + CallyActorClass *klass = NULL; + + cally_actor = CALLY_ACTOR (clutter_actor_get_accessible (CLUTTER_ACTOR (obj))); + klass = CALLY_ACTOR_GET_CLASS (cally_actor); + + if (klass->notify_clutter) + klass->notify_clutter (obj, pspec); +} + +/* + * This function is a signal handler for notify signal which gets emitted + * when a property changes value on the ClutterActor associated with a CallyActor + * + * It constructs an AtkPropertyValues structure and emits a "property_changed" + * signal which causes the user specified AtkPropertyChangeHandler + * to be called. + */ +static void +cally_actor_real_notify_clutter (GObject *obj, + GParamSpec *pspec) +{ + ClutterActor* actor = CLUTTER_ACTOR (obj); + AtkObject* atk_obj = clutter_actor_get_accessible (CLUTTER_ACTOR(obj)); + AtkState state; + gboolean value; + + if (g_strcmp0 (pspec->name, "visible") == 0) + { + state = ATK_STATE_VISIBLE; + value = clutter_actor_is_visible (actor); + } + else if (g_strcmp0 (pspec->name, "mapped") == 0) + { + /* Clones may temporarily map an actor in order to + * paint it; we don't want this to generate an ATK + * state change + */ + if (clutter_actor_is_in_clone_paint (actor)) + return; + + state = ATK_STATE_SHOWING; + value = clutter_actor_is_mapped (actor); + } + else if (g_strcmp0 (pspec->name, "reactive") == 0) + { + state = ATK_STATE_SENSITIVE; + value = clutter_actor_get_reactive (actor); + } + else + return; + + atk_object_notify_state_change (atk_obj, state, value); +} + +static void +_cally_actor_clean_action_list (CallyActor *cally_actor) +{ + CallyActorPrivate *priv = NULL; + + priv = cally_actor->priv; + + if (priv->action_list) + { + g_list_foreach (priv->action_list, + (GFunc) _cally_actor_destroy_action_info, + NULL); + g_list_free (priv->action_list); + priv->action_list = NULL; + } +} + +static CallyActorActionInfo * +_cally_actor_get_action_info (CallyActor *cally_actor, + gint index) +{ + CallyActorPrivate *priv = NULL; + GList *node = NULL; + + g_return_val_if_fail (CALLY_IS_ACTOR (cally_actor), NULL); + + priv = cally_actor->priv; + + if (priv->action_list == NULL) + return NULL; + + node = g_list_nth (priv->action_list, index); + + if (node == NULL) + return NULL; + + return (CallyActorActionInfo *)(node->data); +} + +/** + * cally_actor_add_action: (skip) + * @cally_actor: a #CallyActor + * @action_name: the action name + * @action_description: the action description + * @action_keybinding: the action keybinding + * @action_func: the callback of the action, to be executed with do_action + * + * Adds a new action to be accessed with the #AtkAction interface. + * + * Return value: added action id, or -1 if failure + * + * Since: 1.4 + */ +guint +cally_actor_add_action (CallyActor *cally_actor, + const gchar *action_name, + const gchar *action_description, + const gchar *action_keybinding, + CallyActionFunc action_func) +{ + return cally_actor_add_action_full (cally_actor, + action_name, + action_description, + action_keybinding, + (CallyActionCallback) action_func, + NULL, NULL); +} + +/** + * cally_actor_add_action_full: (rename-to cally_actor_add_action) + * @cally_actor: a #CallyActor + * @action_name: the action name + * @action_description: the action description + * @action_keybinding: the action keybinding + * @callback: (scope notified): the callback of the action + * @user_data: (closure): data to be passed to @callback + * @notify: function to be called when removing the action + * + * Adds a new action to be accessed with the #AtkAction interface. + * + * Return value: added action id, or -1 if failure + * + * Since: 1.6 + */ +guint +cally_actor_add_action_full (CallyActor *cally_actor, + const gchar *action_name, + const gchar *action_description, + const gchar *action_keybinding, + CallyActionCallback callback, + gpointer user_data, + GDestroyNotify notify) +{ + CallyActorActionInfo *info = NULL; + CallyActorPrivate *priv = NULL; + + g_return_val_if_fail (CALLY_IS_ACTOR (cally_actor), -1); + g_return_val_if_fail (callback != NULL, -1); + + priv = cally_actor->priv; + + info = g_slice_new (CallyActorActionInfo); + info->name = g_strdup (action_name); + info->description = g_strdup (action_description); + info->keybinding = g_strdup (action_keybinding); + info->do_action_func = callback; + info->user_data = user_data; + info->notify = notify; + + priv->action_list = g_list_append (priv->action_list, info); + + return g_list_length (priv->action_list); +} + +/** + * cally_actor_remove_action: + * @cally_actor: a #CallyActor + * @action_id: the action id + * + * Removes a action, using the @action_id returned by cally_actor_add_action() + * + * Return value: %TRUE if the operation was succesful, %FALSE otherwise + * + * Since: 1.4 + */ +gboolean +cally_actor_remove_action (CallyActor *cally_actor, + gint action_id) +{ + GList *list_node = NULL; + CallyActorPrivate *priv = NULL; + + g_return_val_if_fail (CALLY_IS_ACTOR (cally_actor), FALSE); + priv = cally_actor->priv; + + list_node = g_list_nth (priv->action_list, action_id - 1); + + if (!list_node) + return FALSE; + + _cally_actor_destroy_action_info (list_node->data, NULL); + + priv->action_list = g_list_remove_link (priv->action_list, list_node); + + return TRUE; +} + +/** + * cally_actor_remove_action_by_name: + * @cally_actor: a #CallyActor + * @action_name: the name of the action to remove + * + * Removes an action, using the @action_name used when the action was added + * with cally_actor_add_action() + * + * Return value: %TRUE if the operation was succesful, %FALSE otherwise + * + * Since: 1.4 + */ +gboolean +cally_actor_remove_action_by_name (CallyActor *cally_actor, + const gchar *action_name) +{ + GList *node = NULL; + gboolean action_found = FALSE; + CallyActorPrivate *priv = NULL; + + g_return_val_if_fail (CALLY_IS_ACTOR (cally_actor), FALSE); + priv = CALLY_ACTOR (cally_actor)->priv; + + for (node = priv->action_list; node && !action_found; + node = node->next) + { + CallyActorActionInfo *ainfo = node->data; + + if (!g_ascii_strcasecmp (ainfo->name, action_name)) + { + action_found = TRUE; + break; + } + } + if (!action_found) + return FALSE; + + _cally_actor_destroy_action_info (node->data, NULL); + priv->action_list = g_list_remove_link (priv->action_list, node); + + return TRUE; +} + + +static void +_cally_actor_destroy_action_info (gpointer action_info, + gpointer user_data) +{ + CallyActorActionInfo *info = action_info; + + g_assert (info != NULL); + + g_free (info->name); + g_free (info->description); + g_free (info->keybinding); + + if (info->notify) + info->notify (info->user_data); + + g_slice_free (CallyActorActionInfo, info); +} diff --git a/clutter/clutter/cally/cally-actor.h b/clutter/clutter/cally/cally-actor.h new file mode 100644 index 0000000..c17c26e --- /dev/null +++ b/clutter/clutter/cally/cally-actor.h @@ -0,0 +1,160 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2008 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * Some parts are based on GailWidget from GAIL + * GAIL - The GNOME Accessibility Implementation Library + * Copyright 2001, 2002, 2003 Sun Microsystems Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __CALLY_ACTOR_H__ +#define __CALLY_ACTOR_H__ + +#if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CALLY_TYPE_ACTOR (cally_actor_get_type ()) +#define CALLY_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CALLY_TYPE_ACTOR, CallyActor)) +#define CALLY_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CALLY_TYPE_ACTOR, CallyActorClass)) +#define CALLY_IS_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CALLY_TYPE_ACTOR)) +#define CALLY_IS_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CALLY_TYPE_ACTOR)) +#define CALLY_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CALLY_TYPE_ACTOR, CallyActorClass)) + +typedef struct _CallyActor CallyActor; +typedef struct _CallyActorClass CallyActorClass; +typedef struct _CallyActorPrivate CallyActorPrivate; + +/** + * CallyActionFunc: + * @cally_actor: a #CallyActor + * + * Action function, to be used on #AtkAction implementations as a individual + * action + * + * Since: 1.4 + */ +typedef void (* CallyActionFunc) (CallyActor *cally_actor); + +/** + * CallyActionCallback: + * @cally_actor: a #CallyActor + * @user_data: user data passed to the function + * + * Action function, to be used on #AtkAction implementations as + * an individual action. Unlike #CallyActionFunc, this function + * uses the @user_data argument passed to cally_actor_add_action_full(). + * + * Since: 1.6 + */ +typedef void (* CallyActionCallback) (CallyActor *cally_actor, + gpointer user_data); + +/** + * CallyActor: + * + * The CallyActor structure contains only private + * data and should be accessed using the provided API + * + * Since: 1.4 + */ +struct _CallyActor +{ + /*< private >*/ + AtkGObjectAccessible parent; + + CallyActorPrivate *priv; +}; + +/** + * CallyActorClass: + * @notify_clutter: Signal handler for notify signal on Clutter actor + * @focus_clutter: Signal handler for key-focus-in and key-focus-out + * signal on Clutter actor. This virtual functions is deprecated. + * @add_actor: Signal handler for actor-added signal on + * ClutterContainer interface + * @remove_actor: Signal handler for actor-added signal on + * ClutterContainer interface + * + * The CallyActorClass structure contains + * only private data + * + * Since: 1.4 + */ +struct _CallyActorClass +{ + /*< private >*/ + AtkGObjectAccessibleClass parent_class; + + /*< public >*/ + void (*notify_clutter) (GObject *object, + GParamSpec *pspec); + + gboolean (*focus_clutter) (ClutterActor *actor, + gpointer data); + + gint (*add_actor) (ClutterActor *container, + ClutterActor *actor, + gpointer data); + + gint (*remove_actor) (ClutterActor *container, + ClutterActor *actor, + gpointer data); + + /*< private >*/ + /* padding for future expansion */ + gpointer _padding_dummy[32]; +}; + +CLUTTER_AVAILABLE_IN_1_4 +GType cally_actor_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_4 +AtkObject* cally_actor_new (ClutterActor *actor); + +CLUTTER_AVAILABLE_IN_1_4 +guint cally_actor_add_action (CallyActor *cally_actor, + const gchar *action_name, + const gchar *action_description, + const gchar *action_keybinding, + CallyActionFunc action_func); +CLUTTER_AVAILABLE_IN_1_6 +guint cally_actor_add_action_full (CallyActor *cally_actor, + const gchar *action_name, + const gchar *action_description, + const gchar *action_keybinding, + CallyActionCallback callback, + gpointer user_data, + GDestroyNotify notify); + +CLUTTER_AVAILABLE_IN_1_4 +gboolean cally_actor_remove_action (CallyActor *cally_actor, + gint action_id); + +CLUTTER_AVAILABLE_IN_1_4 +gboolean cally_actor_remove_action_by_name (CallyActor *cally_actor, + const gchar *action_name); + +G_END_DECLS + +#endif /* __CALLY_ACTOR_H__ */ diff --git a/clutter/clutter/cally/cally-clone.c b/clutter/clutter/cally/cally-clone.c new file mode 100644 index 0000000..f1832a5 --- /dev/null +++ b/clutter/clutter/cally/cally-clone.c @@ -0,0 +1,132 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2010 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * 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. + */ + +/** + * SECTION:cally-clone + * @Title: CallyClone + * @short_description: Implementation of the ATK interfaces for a #ClutterClone + * @see_also: #ClutterClone + * + * #CallyClone implements the required ATK interfaces of #ClutterClone + * + * In particular it sets a proper role for the clone, as just a image, + * as it is the sanest and simplest approach. + */ + +/* Design rationale for CallyClone: + * + * In the old times, it was just ClutterCloneTexture. So, from a a11y POV + * CallyCloneTexture was just another image, like ClutterTexture, and if + * it was a clone was irrevelant. So on cally-0.8, CallyCloneTexture + * expose a object with role ATK_ROLE_IMAGE. But now, ClutterClone is more + * general. You can clone any object, including groups, and made things + * like have one text entry, and a clone with different properties in the + * same window, updated both at once. + * + * The question is if the idea is have a ClutterClone as a "first-class" + * citizen inside the stage hierarchy (full clone), or it is just supposed + * to be a mirror image of the original object. + * + * In the case of the a11y POV this would mean that if the text changes on + * the source, the clone should emit as well the text-changing signals. + * + * As ClutterClone smartly just paint the same object with different + * parameters, this would mean that it should be the cally object the one + * that should replicate the source clutter hierarchy to do that, + * something that just sound crazy. + * + * Taking into account that: + * + * - ClutterClone doesn't re-emit mirrored signals from the source + * I think that likely the answer would be "yes, it is just a + * mirrored image, not a real full clone". + * + * - You can't interact directly with the clone (ie: focus, and so on). + * Its basic usage (right now) is clone textures. + * + * Any other solution could be overwhelming. + * + * I think that the final solution would be that ClutterClone from the + * a11y POV should still be managed as a image (with the proper properties, + * position, size, etc.). + */ +#include "clutter-build-config.h" + +#include "cally-clone.h" +#include "cally-actor-private.h" + +/* AtkObject */ +static void cally_clone_real_initialize (AtkObject *obj, + gpointer data); + +G_DEFINE_TYPE (CallyClone, cally_clone, CALLY_TYPE_ACTOR) + +static void +cally_clone_class_init (CallyCloneClass *klass) +{ +/* GObjectClass *gobject_class = G_OBJECT_CLASS (klass); */ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + + class->initialize = cally_clone_real_initialize; +} + +static void +cally_clone_init (CallyClone *clone) +{ + /* nothing to do yet */ +} + +/** + * cally_clone_new: + * @actor: a #ClutterActor + * + * Creates a new #CallyClone for the given @actor. @actor must be a + * #ClutterClone. + * + * Return value: the newly created #AtkObject + * + * Since: 1.4 + */ +AtkObject* +cally_clone_new (ClutterActor *actor) +{ + GObject *object = NULL; + AtkObject *accessible = NULL; + + g_return_val_if_fail (CLUTTER_IS_CLONE (actor), NULL); + + object = g_object_new (CALLY_TYPE_CLONE, NULL); + + accessible = ATK_OBJECT (object); + atk_object_initialize (accessible, actor); + + return accessible; +} + +static void +cally_clone_real_initialize (AtkObject *obj, + gpointer data) +{ + ATK_OBJECT_CLASS (cally_clone_parent_class)->initialize (obj, data); + + obj->role = ATK_ROLE_IMAGE; +} diff --git a/clutter/clutter/cally/cally-clone.h b/clutter/clutter/cally/cally-clone.h new file mode 100644 index 0000000..3a37770 --- /dev/null +++ b/clutter/clutter/cally/cally-clone.h @@ -0,0 +1,84 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2010 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * 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 . + */ + +#ifndef __CALLY_CLONE_H__ +#define __CALLY_CLONE_H__ + +#if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CALLY_TYPE_CLONE (cally_clone_get_type ()) +#define CALLY_CLONE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CALLY_TYPE_CLONE, CallyClone)) +#define CALLY_CLONE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CALLY_TYPE_CLONE, CallyCloneClass)) +#define CALLY_IS_CLONE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CALLY_TYPE_CLONE)) +#define CALLY_IS_CLONE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CALLY_TYPE_CLONE)) +#define CALLY_CLONE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CALLY_TYPE_CLONE, CallyCloneClass)) + +typedef struct _CallyClone CallyClone; +typedef struct _CallyCloneClass CallyCloneClass; +typedef struct _CallyClonePrivate CallyClonePrivate; + +/** + * CallyClone: + * + * The CallyClone structure contains only private + * data and should be accessed using the provided API + * + * Since: 1.4 + */ +struct _CallyClone +{ + /*< private >*/ + CallyActor parent; + + CallyClonePrivate *priv; +}; + +/** + * CallyCloneClass: + * + * The CallyCloneClass structure contains only + * private data + * + * Since: 1.4 + */ +struct _CallyCloneClass +{ + /*< private >*/ + CallyActorClass parent_class; + + /* padding for future expansion */ + gpointer _padding_dummy[8]; +}; + +CLUTTER_AVAILABLE_IN_1_4 +GType cally_clone_get_type (void) G_GNUC_CONST; +CLUTTER_AVAILABLE_IN_1_4 +AtkObject *cally_clone_new (ClutterActor *actor); + +G_END_DECLS + +#endif /* __CALLY_CLONE_H__ */ diff --git a/clutter/clutter/cally/cally-factory.h b/clutter/clutter/cally/cally-factory.h new file mode 100644 index 0000000..432844f --- /dev/null +++ b/clutter/clutter/cally/cally-factory.h @@ -0,0 +1,117 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2008 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * Based on gailfactory.h from GAIL + * Copyright 2001, 2002, 2003 Sun Microsystems Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _CALLY_FACTORY_H__ +#define _CALLY_FACTORY_H__ + +#include +#include + +/** + * CALLY_ACCESSIBLE_FACTORY: + * @type: GType of the accessible which is created by the factory + * @type_as_function: prefix of the accessible object methods + * @opt_create_accessible: method to instantiate the accessibility object + * + * Defines a new #AtkObjectFactory factory to create accessible + * objects of a specific GType. It defines the factory GType and also + * overrides the proper #AtkObjectFactory methods. + * + * It assumes that the accessibility object provides a + * @opt_create_accessible method in order to create the accessibility + * object. It returns a @type GType object. + * + * Since: 1.4 + */ +#define CALLY_ACCESSIBLE_FACTORY(type, type_as_function, opt_create_accessible) \ + \ +static GType \ +type_as_function ## _factory_get_accessible_type (void) \ +{ \ + return type; \ +} \ + \ +static AtkObject* \ +type_as_function ## _factory_create_accessible (GObject *obj) \ +{ \ + ClutterActor *actor; \ + AtkObject *accessible; \ + \ + g_return_val_if_fail (CLUTTER_ACTOR (obj), NULL); \ + \ + actor = CLUTTER_ACTOR (obj); \ + \ + accessible = opt_create_accessible (actor); \ + \ + return accessible; \ +} \ + \ +static void \ +type_as_function ## _factory_class_init (AtkObjectFactoryClass *klass) \ +{ \ + klass->create_accessible = type_as_function ## _factory_create_accessible; \ + klass->get_accessible_type = type_as_function ## _factory_get_accessible_type;\ +} \ + \ +static GType \ +type_as_function ## _factory_get_type (void) \ +{ \ + static GType t = 0; \ + \ + if (!t) \ + { \ + char *name; \ + static const GTypeInfo tinfo = \ + { \ + sizeof (AtkObjectFactoryClass), \ + NULL, NULL, (GClassInitFunc) type_as_function ## _factory_class_init, \ + NULL, NULL, sizeof (AtkObjectFactory), 0, NULL, NULL \ + }; \ + \ + name = g_strconcat (g_type_name (type), "Factory", NULL); \ + t = g_type_register_static ( \ + ATK_TYPE_OBJECT_FACTORY, name, &tinfo, 0); \ + g_free (name); \ + } \ + \ + return t; \ +} + +/** + * CALLY_ACTOR_SET_FACTORY: + * @widget_type: GType of the clutter actor + * @type_as_function: prefix of the accessible object methods + * + * Sets the #AtkObjectFactory to be used in order to instantiate + * accessibility objects for the actor which GType is @widget_type. + * + * Since: 1.4 + */ +#define CALLY_ACTOR_SET_FACTORY(widget_type, type_as_function) \ + atk_registry_set_factory_type (atk_get_default_registry (), \ + widget_type, \ + type_as_function ## _factory_get_type ()) + +#endif /* _CALLY_FACTORY_H__ */ diff --git a/clutter/clutter/cally/cally-group.c b/clutter/clutter/cally/cally-group.c new file mode 100644 index 0000000..5d0cce5 --- /dev/null +++ b/clutter/clutter/cally/cally-group.c @@ -0,0 +1,147 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2008 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * Based on GailContainer from GAIL + * Copyright 2001, 2002, 2003 Sun Microsystems Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:cally-group + * @Title: CallyGroup + * @short_description: Implementation of the ATK interfaces for a #ClutterGroup + * @see_also: #ClutterGroup + * + * #CallyGroup implements the required ATK interfaces of #ClutterGroup + * In particular it exposes each of the Clutter actors contained in the + * group. + */ + +#include "clutter-build-config.h" + +#include "cally-group.h" +#include "cally-actor-private.h" + +static gint cally_group_get_n_children (AtkObject *obj); +static AtkObject* cally_group_ref_child (AtkObject *obj, + gint i); +static void cally_group_real_initialize (AtkObject *obj, + gpointer data); + +G_DEFINE_TYPE (CallyGroup, cally_group, CALLY_TYPE_ACTOR) + +static void +cally_group_class_init (CallyGroupClass *klass) +{ +/* GObjectClass *gobject_class = G_OBJECT_CLASS (klass); */ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + + class->get_n_children = cally_group_get_n_children; + class->ref_child = cally_group_ref_child; + class->initialize = cally_group_real_initialize; +} + +static void +cally_group_init (CallyGroup *group) +{ + /* nothing to do yet */ +} + +/** + * cally_group_new: + * @actor: a #ClutterGroup + * + * Creates a #CallyGroup for @actor + * + * Return value: the newly created #CallyGroup + * + * Since: 1.4 + */ +AtkObject * +cally_group_new (ClutterActor *actor) +{ + GObject *object = NULL; + AtkObject *accessible = NULL; + + g_return_val_if_fail (CLUTTER_IS_GROUP (actor), NULL); + + object = g_object_new (CALLY_TYPE_GROUP, NULL); + + accessible = ATK_OBJECT (object); + atk_object_initialize (accessible, actor); + + return accessible; +} + +static gint +cally_group_get_n_children (AtkObject *obj) +{ + ClutterActor *actor = NULL; + gint count = 0; + + g_return_val_if_fail (CALLY_IS_GROUP (obj), count); + + actor = CALLY_GET_CLUTTER_ACTOR (obj); + + if (actor == NULL) /* defunct */ + return 0; + + g_return_val_if_fail (CLUTTER_IS_GROUP(actor), count); + + count = clutter_actor_get_n_children (actor); + + return count; +} + +static AtkObject* +cally_group_ref_child (AtkObject *obj, + gint i) +{ + AtkObject *accessible = NULL; + ClutterActor *actor = NULL; + ClutterActor *child = NULL; + + g_return_val_if_fail (CALLY_IS_GROUP (obj), NULL); + g_return_val_if_fail ((i >= 0), NULL); + + actor = CALLY_GET_CLUTTER_ACTOR (obj); + + g_return_val_if_fail (CLUTTER_IS_GROUP(actor), NULL); + child = clutter_actor_get_child_at_index (actor, i); + + if (!child) + return NULL; + + accessible = clutter_actor_get_accessible (child); + + if (accessible != NULL) + g_object_ref (accessible); + + return accessible; +} + +static void +cally_group_real_initialize (AtkObject *obj, + gpointer data) +{ + ATK_OBJECT_CLASS (cally_group_parent_class)->initialize (obj, data); + + obj->role = ATK_ROLE_PANEL; +} diff --git a/clutter/clutter/cally/cally-group.h b/clutter/clutter/cally/cally-group.h new file mode 100644 index 0000000..4efd259 --- /dev/null +++ b/clutter/clutter/cally/cally-group.h @@ -0,0 +1,87 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2008 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * Based on GailContainer from GAIL + * Copyright 2001, 2002, 2003 Sun Microsystems Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __CALLY_GROUP_H__ +#define __CALLY_GROUP_H__ + +#if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CALLY_TYPE_GROUP (cally_group_get_type ()) +#define CALLY_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CALLY_TYPE_GROUP, CallyGroup)) +#define CALLY_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CALLY_TYPE_GROUP, CallyGroupClass)) +#define CALLY_IS_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CALLY_TYPE_GROUP)) +#define CALLY_IS_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CALLY_TYPE_GROUP)) +#define CALLY_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CALLY_TYPE_GROUP, CallyGroupClass)) + +typedef struct _CallyGroup CallyGroup; +typedef struct _CallyGroupClass CallyGroupClass; +typedef struct _CallyGroupPrivate CallyGroupPrivate; + +/** + * CallyGroup: + * + * The CallyGroup structure contains only + * private data and should be accessed using the provided API + * + * Since: 1.4 + */ +struct _CallyGroup +{ + /*< private >*/ + CallyActor parent; + + CallyGroupPrivate *priv; +}; + +/** + * CallyGroupClass: + * + * The CallyGroupClass structure contains only + * private data + * + * Since: 1.4 + */ +struct _CallyGroupClass +{ + /*< private >*/ + CallyActorClass parent_class; + + /* padding for future expansion */ + gpointer _padding_dummy[8]; +}; + +CLUTTER_AVAILABLE_IN_1_4 +GType cally_group_get_type (void) G_GNUC_CONST; +CLUTTER_AVAILABLE_IN_1_4 +AtkObject* cally_group_new (ClutterActor *actor); + +G_END_DECLS + +#endif /* __CALLY_GROUP_H__ */ diff --git a/clutter/clutter/cally/cally-main.h b/clutter/clutter/cally/cally-main.h new file mode 100644 index 0000000..6293197 --- /dev/null +++ b/clutter/clutter/cally/cally-main.h @@ -0,0 +1,44 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2008 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * Some parts are based on GailWidget from GAIL + * GAIL - The GNOME Accessibility Implementation Library + * Copyright 2001, 2002, 2003 Sun Microsystems Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __CALLY_MAIN_H__ +#define __CALLY_MAIN_H__ + +#if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +CLUTTER_AVAILABLE_IN_1_4 +gboolean cally_get_cally_initialized (void); +CLUTTER_AVAILABLE_IN_1_4 +gboolean cally_accessibility_init (void); + +G_END_DECLS + +#endif /* __CALLY_MAIN_H__ */ diff --git a/clutter/clutter/cally/cally-rectangle.c b/clutter/clutter/cally/cally-rectangle.c new file mode 100644 index 0000000..e02f886 --- /dev/null +++ b/clutter/clutter/cally/cally-rectangle.c @@ -0,0 +1,98 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2009 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * 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. + */ + +/** + * SECTION:cally-rectangle + * @short_description: Implementation of the ATK interfaces for a #ClutterRectangle + * @see_also: #ClutterRectangle + * + * #CallyRectangle implements the required ATK interfaces of #ClutterRectangle + * + * In particular it sets a proper role for the rectangle. + */ + +#include "clutter-build-config.h" + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS + +#include "cally-rectangle.h" +#include "cally-actor-private.h" + +#include "clutter-color.h" +#include "deprecated/clutter-rectangle.h" + +/* AtkObject */ +static void cally_rectangle_real_initialize (AtkObject *obj, + gpointer data); + +G_DEFINE_TYPE (CallyRectangle, cally_rectangle, CALLY_TYPE_ACTOR) + +static void +cally_rectangle_class_init (CallyRectangleClass *klass) +{ +/* GObjectClass *gobject_class = G_OBJECT_CLASS (klass); */ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + + class->initialize = cally_rectangle_real_initialize; +} + +static void +cally_rectangle_init (CallyRectangle *rectangle) +{ + /* nothing to do yet */ +} + +/** + * cally_rectangle_new: + * @actor: a #ClutterActor + * + * Creates a new #CallyRectangle for the given @actor. @actor must be + * a #ClutterRectangle. + * + * Return value: the newly created #AtkObject + * + * Since: 1.4 + */ +AtkObject* +cally_rectangle_new (ClutterActor *actor) +{ + GObject *object = NULL; + AtkObject *accessible = NULL; + + g_return_val_if_fail (CLUTTER_IS_RECTANGLE (actor), NULL); + + object = g_object_new (CALLY_TYPE_RECTANGLE, NULL); + + accessible = ATK_OBJECT (object); + atk_object_initialize (accessible, actor); + + return accessible; +} + +static void +cally_rectangle_real_initialize (AtkObject *obj, + gpointer data) +{ + ATK_OBJECT_CLASS (cally_rectangle_parent_class)->initialize (obj, data); + + obj->role = ATK_ROLE_IMAGE; +} diff --git a/clutter/clutter/cally/cally-rectangle.h b/clutter/clutter/cally/cally-rectangle.h new file mode 100644 index 0000000..0a205c5 --- /dev/null +++ b/clutter/clutter/cally/cally-rectangle.h @@ -0,0 +1,84 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2009 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * 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 . + */ + +#ifndef __CALLY_RECTANGLE_H__ +#define __CALLY_RECTANGLE_H__ + +#if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CALLY_TYPE_RECTANGLE (cally_rectangle_get_type ()) +#define CALLY_RECTANGLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CALLY_TYPE_RECTANGLE, CallyRectangle)) +#define CALLY_RECTANGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CALLY_TYPE_RECTANGLE, CallyRectangleClass)) +#define CALLY_IS_RECTANGLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CALLY_TYPE_RECTANGLE)) +#define CALLY_IS_RECTANGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CALLY_TYPE_RECTANGLE)) +#define CALLY_RECTANGLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CALLY_TYPE_RECTANGLE, CallyRectangleClass)) + +typedef struct _CallyRectangle CallyRectangle; +typedef struct _CallyRectangleClass CallyRectangleClass; +typedef struct _CallyRectanglePrivate CallyRectanglePrivate; + +/** + * CallyRectangle: + * + * The CallyRectangle structure contains only private + * data and should be accessed using the provided API + * + * Since: 1.4 + */ +struct _CallyRectangle +{ + /*< private >*/ + CallyActor parent; + + CallyRectanglePrivate *priv; +}; + +/** + * CallyRectangleClass: + * + * The CallyRectangleClass structure contains + * only private data + * + * Since: 1.4 + */ +struct _CallyRectangleClass +{ + /*< private >*/ + CallyActorClass parent_class; + + /* padding for future expansion */ + gpointer _padding_dummy[8]; +}; + +CLUTTER_AVAILABLE_IN_1_4 +GType cally_rectangle_get_type (void) G_GNUC_CONST; +CLUTTER_AVAILABLE_IN_1_4 +AtkObject* cally_rectangle_new (ClutterActor *actor); + +G_END_DECLS + +#endif /* __CALLY_RECTANGLE_H__ */ diff --git a/clutter/clutter/cally/cally-root.c b/clutter/clutter/cally/cally-root.c new file mode 100644 index 0000000..2f16296 --- /dev/null +++ b/clutter/clutter/cally/cally-root.c @@ -0,0 +1,294 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2008 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * 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. + */ + +/** + * SECTION:cally-root + * @short_description: Root object for the Cally toolkit + * @see_also: #ClutterStage + * + * #CallyRoot is the root object of the accessibility tree-like + * hierarchy, exposing the application level. + * + * Somewhat equivalent to #GailTopLevel. We consider that this class + * expose the a11y information of the #ClutterStageManager, as the + * children of this object are the different ClutterStage managed (so + * the #GObject used in the atk_object_initialize() is the + * #ClutterStageManager). + */ + +#include "clutter-build-config.h" + +#include "cally-root.h" + +#include "clutter-actor.h" +#include "clutter-stage-private.h" +#include "clutter-stage-manager.h" + + +/* GObject */ +static void cally_root_finalize (GObject *object); + +/* AtkObject.h */ +static void cally_root_initialize (AtkObject *accessible, + gpointer data); +static gint cally_root_get_n_children (AtkObject *obj); +static AtkObject * cally_root_ref_child (AtkObject *obj, + gint i); +static AtkObject * cally_root_get_parent (AtkObject *obj); +static const char * cally_root_get_name (AtkObject *obj); + +/* Private */ +static void cally_util_stage_added_cb (ClutterStageManager *stage_manager, + ClutterStage *stage, + gpointer data); +static void cally_util_stage_removed_cb (ClutterStageManager *stage_manager, + ClutterStage *stage, + gpointer data); + +struct _CallyRootPrivate +{ +/* We save the CallyStage objects. Other option could save the stage + * list, and then just get the a11y object on the ref_child, etc. But + * the ref_child is more common that the init and the stage-add, + * stage-remove, so we avoid getting the accessible object + * constantly + */ + GSList *stage_list; + + /* signals id */ + guint stage_added_id; + guint stage_removed_id; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (CallyRoot, cally_root, ATK_TYPE_GOBJECT_ACCESSIBLE) + +static void +cally_root_class_init (CallyRootClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + + gobject_class->finalize = cally_root_finalize; + + /* AtkObject */ + class->get_n_children = cally_root_get_n_children; + class->ref_child = cally_root_ref_child; + class->get_parent = cally_root_get_parent; + class->initialize = cally_root_initialize; + class->get_name = cally_root_get_name; +} + +static void +cally_root_init (CallyRoot *root) +{ + root->priv = cally_root_get_instance_private (root); + + root->priv->stage_list = NULL; + root->priv->stage_added_id = 0; + root->priv->stage_removed_id = 0; +} + +/** + * cally_root_new: + * + * Creates a new #CallyRoot object. + * + * Return value: the newly created #AtkObject + * + * Since: 1.4 + */ +AtkObject* +cally_root_new (void) +{ + GObject *object = NULL; + AtkObject *accessible = NULL; + ClutterStageManager *stage_manager = NULL; + + object = g_object_new (CALLY_TYPE_ROOT, NULL); + + accessible = ATK_OBJECT (object); + stage_manager = clutter_stage_manager_get_default (); + + atk_object_initialize (accessible, stage_manager); + + return accessible; +} + +static void +cally_root_finalize (GObject *object) +{ + CallyRoot *root = CALLY_ROOT (object); + GObject *stage_manager = NULL; + + g_return_if_fail (CALLY_IS_ROOT (object)); + + if (root->priv->stage_list) + { + g_slist_free (root->priv->stage_list); + root->priv->stage_list = NULL; + } + + stage_manager = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (root)); + + g_signal_handler_disconnect (stage_manager, + root->priv->stage_added_id); + + g_signal_handler_disconnect (stage_manager, + root->priv->stage_added_id); + + G_OBJECT_CLASS (cally_root_parent_class)->finalize (object); +} + +/* AtkObject.h */ +static void +cally_root_initialize (AtkObject *accessible, + gpointer data) +{ + ClutterStageManager *stage_manager = NULL; + const GSList *iter = NULL; + const GSList *stage_list = NULL; + ClutterStage *clutter_stage = NULL; + AtkObject *cally_stage = NULL; + CallyRoot *root = NULL; + + accessible->role = ATK_ROLE_APPLICATION; + accessible->accessible_parent = NULL; + + /* children initialization */ + root = CALLY_ROOT (accessible); + stage_manager = CLUTTER_STAGE_MANAGER (data); + stage_list = clutter_stage_manager_peek_stages (stage_manager); + + for (iter = stage_list; iter != NULL; iter = g_slist_next (iter)) + { + clutter_stage = CLUTTER_STAGE (iter->data); + cally_stage = clutter_actor_get_accessible (CLUTTER_ACTOR (clutter_stage)); + + atk_object_set_parent (cally_stage, ATK_OBJECT (root)); + + root->priv->stage_list = g_slist_append (root->priv->stage_list, + cally_stage); + } + + root->priv->stage_added_id = + g_signal_connect (G_OBJECT (stage_manager), "stage-added", + G_CALLBACK (cally_util_stage_added_cb), root); + + root->priv->stage_removed_id = + g_signal_connect (G_OBJECT (stage_manager), "stage-removed", + G_CALLBACK (cally_util_stage_removed_cb), root); + + ATK_OBJECT_CLASS (cally_root_parent_class)->initialize (accessible, data); +} + + +static gint +cally_root_get_n_children (AtkObject *obj) +{ + CallyRoot *root = CALLY_ROOT (obj); + + return g_slist_length (root->priv->stage_list); +} + +static AtkObject* +cally_root_ref_child (AtkObject *obj, + gint i) +{ + CallyRoot *cally_root = NULL; + GSList *stage_list = NULL; + gint num = 0; + AtkObject *item = NULL; + + cally_root = CALLY_ROOT (obj); + stage_list = cally_root->priv->stage_list; + num = g_slist_length (stage_list); + + g_return_val_if_fail ((i < num)&&(i >= 0), NULL); + + item = g_slist_nth_data (stage_list, i); + if (!item) + { + return NULL; + } + + g_object_ref (item); + + return item; +} + +static AtkObject* +cally_root_get_parent (AtkObject *obj) +{ + return NULL; +} + +static const char * +cally_root_get_name (AtkObject *obj) +{ + return g_get_prgname (); +} + +/* -------------------------------- PRIVATE --------------------------------- */ + +static void +cally_util_stage_added_cb (ClutterStageManager *stage_manager, + ClutterStage *stage, + gpointer data) +{ + CallyRoot *root = CALLY_ROOT (data); + AtkObject *cally_stage = NULL; + gint index = -1; + + cally_stage = clutter_actor_get_accessible (CLUTTER_ACTOR (stage)); + + atk_object_set_parent (cally_stage, ATK_OBJECT (root)); + + root->priv->stage_list = g_slist_append (root->priv->stage_list, + cally_stage); + + index = g_slist_index (root->priv->stage_list, cally_stage); + g_signal_emit_by_name (root, "children_changed::add", + index, cally_stage, NULL); + g_signal_emit_by_name (cally_stage, "create", 0); +} + +static void +cally_util_stage_removed_cb (ClutterStageManager *stage_manager, + ClutterStage *stage, + gpointer data) +{ + CallyRoot *root = CALLY_ROOT (data); + AtkObject *cally_stage = NULL; + gint index = -1; + + cally_stage = clutter_actor_get_accessible (CLUTTER_ACTOR (stage)); + + index = g_slist_index (root->priv->stage_list, cally_stage); + + root->priv->stage_list = g_slist_remove (root->priv->stage_list, + cally_stage); + + index = g_slist_index (root->priv->stage_list, cally_stage); + g_signal_emit_by_name (root, "children_changed::remove", + index, cally_stage, NULL); + g_signal_emit_by_name (cally_stage, "destroy", 0); +} diff --git a/clutter/clutter/cally/cally-root.h b/clutter/clutter/cally/cally-root.h new file mode 100644 index 0000000..1067494 --- /dev/null +++ b/clutter/clutter/cally/cally-root.h @@ -0,0 +1,84 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2009 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * 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 . + */ + +#ifndef __CALLY_ROOT_H__ +#define __CALLY_ROOT_H__ + +#if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CALLY_TYPE_ROOT (cally_root_get_type ()) +#define CALLY_ROOT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CALLY_TYPE_ROOT, CallyRoot)) +#define CALLY_ROOT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CALLY_TYPE_ROOT, CallyRootClass)) +#define CALLY_IS_ROOT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CALLY_TYPE_ROOT)) +#define CALLY_IS_ROOT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CALLY_TYPE_ROOT)) +#define CALLY_ROOT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CALLY_TYPE_ROOT, CallyRootClass)) + +typedef struct _CallyRoot CallyRoot; +typedef struct _CallyRootClass CallyRootClass; +typedef struct _CallyRootPrivate CallyRootPrivate; + +/** + * CallyRoot: + * + * The CallyRoot structure contains only private + * data and should be accessed using the provided API + * + * Since: 1.4 + */ +struct _CallyRoot +{ + /*< private >*/ + AtkGObjectAccessible parent; + + CallyRootPrivate *priv; +}; + +/** + * CallyRootClass: + * + * The CallyRootClass structure contains only + * private data + * + * Since: 1.4 + */ +struct _CallyRootClass +{ + /*< private >*/ + AtkGObjectAccessibleClass parent_class; + + /* padding for future expansion */ + gpointer _padding_dummy[16]; +}; + +CLUTTER_AVAILABLE_IN_1_4 +GType cally_root_get_type (void) G_GNUC_CONST; +CLUTTER_AVAILABLE_IN_1_4 +AtkObject *cally_root_new (void); + +G_END_DECLS + +#endif /* __CALLY_ROOT_H__ */ diff --git a/clutter/clutter/cally/cally-stage.c b/clutter/clutter/cally/cally-stage.c new file mode 100644 index 0000000..7c100aa --- /dev/null +++ b/clutter/clutter/cally/cally-stage.c @@ -0,0 +1,260 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2008 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * 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. + */ + +/** + * SECTION:cally-stage + * @Title: CallyStage + * @short_description: Implementation of the ATK interfaces for a #ClutterStage + * @see_also: #ClutterStage + * + * #CallyStage implements the required ATK interfaces for #ClutterStage + * + * Some implementation details: at this moment #CallyStage is used as + * the most similar Window object in this toolkit (ie: emitting window + * related signals), although the real purpose of #ClutterStage is + * being a canvas. Anyway, this is required for applications using + * just clutter, or directly #ClutterStage + */ +#include "clutter-build-config.h" + +#include "cally-stage.h" +#include "cally-actor-private.h" + +/* AtkObject.h */ +static void cally_stage_real_initialize (AtkObject *obj, + gpointer data); +static AtkStateSet* cally_stage_ref_state_set (AtkObject *obj); + +/* AtkWindow */ +static void cally_stage_window_interface_init (AtkWindowIface *iface); + +/* Auxiliar */ +static void cally_stage_activate_cb (ClutterStage *stage, + gpointer data); +static void cally_stage_deactivate_cb (ClutterStage *stage, + gpointer data); + +struct _CallyStagePrivate +{ + /* NULL means that the stage will receive the focus */ + ClutterActor *key_focus; + + gboolean active; +}; + +G_DEFINE_TYPE_WITH_CODE (CallyStage, + cally_stage, + CALLY_TYPE_GROUP, + G_ADD_PRIVATE (CallyStage) + G_IMPLEMENT_INTERFACE (ATK_TYPE_WINDOW, + cally_stage_window_interface_init)); + +static void +cally_stage_class_init (CallyStageClass *klass) +{ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + + /* AtkObject */ + class->initialize = cally_stage_real_initialize; + class->ref_state_set = cally_stage_ref_state_set; +} + +static void +cally_stage_init (CallyStage *cally_stage) +{ + CallyStagePrivate *priv = cally_stage_get_instance_private (cally_stage); + + cally_stage->priv = priv; + + priv->active = FALSE; +} + +/** + * cally_stage_new: + * @actor: a #ClutterActor + * + * Creates a new #CallyStage for the given @actor. @actor should be a + * #ClutterStage. + * + * Return value: the newly created #AtkObject + * + * Since: 1.4 + */ +AtkObject* +cally_stage_new (ClutterActor *actor) +{ + GObject *object = NULL; + AtkObject *accessible = NULL; + + g_return_val_if_fail (CLUTTER_IS_STAGE (actor), NULL); + + object = g_object_new (CALLY_TYPE_STAGE, NULL); + + accessible = ATK_OBJECT (object); + atk_object_initialize (accessible, actor); + + return accessible; +} + +static void +cally_stage_notify_key_focus_cb (ClutterStage *stage, + GParamSpec *pspec, + CallyStage *self) +{ + ClutterActor *key_focus = NULL; + AtkObject *new = NULL; + + if (self->priv->active == FALSE) + return; + + key_focus = clutter_stage_get_key_focus (stage); + + if (key_focus != self->priv->key_focus) + { + AtkObject *old = NULL; + + if (self->priv->key_focus != NULL) + { + g_object_remove_weak_pointer (G_OBJECT (self->priv->key_focus), + (gpointer *) &self->priv->key_focus); + old = clutter_actor_get_accessible (self->priv->key_focus); + } + else + old = clutter_actor_get_accessible (CLUTTER_ACTOR (stage)); + + atk_object_notify_state_change (old, + ATK_STATE_FOCUSED, + FALSE); + } + + /* we keep notifying the focus gain without checking previous + * key-focus to avoid some missing events due timing + */ + self->priv->key_focus = key_focus; + + if (key_focus != NULL) + { + /* ensure that if the key focus goes away, the field inside + * CallyStage is reset. see bug: + * + * https://bugzilla.gnome.org/show_bug.cgi?id=692706 + * + * we remove the weak pointer above. + */ + g_object_add_weak_pointer (G_OBJECT (self->priv->key_focus), + (gpointer *) &self->priv->key_focus); + + new = clutter_actor_get_accessible (key_focus); + } + else + new = clutter_actor_get_accessible (CLUTTER_ACTOR (stage)); + + atk_object_notify_state_change (new, + ATK_STATE_FOCUSED, + TRUE); +} + +static void +cally_stage_real_initialize (AtkObject *obj, + gpointer data) +{ + ClutterStage *stage = NULL; + + g_return_if_fail (CALLY_IS_STAGE (obj)); + + ATK_OBJECT_CLASS (cally_stage_parent_class)->initialize (obj, data); + + stage = CLUTTER_STAGE (CALLY_GET_CLUTTER_ACTOR (obj)); + + g_signal_connect (stage, "activate", G_CALLBACK (cally_stage_activate_cb), obj); + g_signal_connect (stage, "deactivate", G_CALLBACK (cally_stage_deactivate_cb), obj); + g_signal_connect (stage, "notify::key-focus", + G_CALLBACK (cally_stage_notify_key_focus_cb), obj); + + atk_object_set_role (obj, ATK_ROLE_WINDOW); +} + +static AtkStateSet* +cally_stage_ref_state_set (AtkObject *obj) +{ + CallyStage *cally_stage = NULL; + AtkStateSet *state_set = NULL; + ClutterStage *stage = NULL; + + g_return_val_if_fail (CALLY_IS_STAGE (obj), NULL); + cally_stage = CALLY_STAGE (obj); + + state_set = ATK_OBJECT_CLASS (cally_stage_parent_class)->ref_state_set (obj); + stage = CLUTTER_STAGE (CALLY_GET_CLUTTER_ACTOR (cally_stage)); + + if (stage == NULL) + return state_set; + + if (cally_stage->priv->active) + atk_state_set_add_state (state_set, ATK_STATE_ACTIVE); + + return state_set; +} + +/* AtkWindow */ +static void +cally_stage_window_interface_init (AtkWindowIface *iface) +{ + /* At this moment AtkWindow is just about signals */ +} + +/* Auxiliar */ +static void +cally_stage_activate_cb (ClutterStage *stage, + gpointer data) +{ + CallyStage *cally_stage = NULL; + + g_return_if_fail (CALLY_IS_STAGE (data)); + + cally_stage = CALLY_STAGE (data); + + cally_stage->priv->active = TRUE; + + atk_object_notify_state_change (ATK_OBJECT (cally_stage), + ATK_STATE_ACTIVE, TRUE); + + g_signal_emit_by_name (cally_stage, "activate", 0); +} + +static void +cally_stage_deactivate_cb (ClutterStage *stage, + gpointer data) +{ + CallyStage *cally_stage = NULL; + + g_return_if_fail (CALLY_IS_STAGE (data)); + + cally_stage = CALLY_STAGE (data); + + cally_stage->priv->active = FALSE; + + atk_object_notify_state_change (ATK_OBJECT (cally_stage), + ATK_STATE_ACTIVE, FALSE); + + g_signal_emit_by_name (cally_stage, "deactivate", 0); +} diff --git a/clutter/clutter/cally/cally-stage.h b/clutter/clutter/cally/cally-stage.h new file mode 100644 index 0000000..c95d2ca --- /dev/null +++ b/clutter/clutter/cally/cally-stage.h @@ -0,0 +1,84 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2008 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * 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 . + */ + +#ifndef __CALLY_STAGE_H__ +#define __CALLY_STAGE_H__ + +#if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CALLY_TYPE_STAGE (cally_stage_get_type ()) +#define CALLY_STAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CALLY_TYPE_STAGE, CallyStage)) +#define CALLY_STAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CALLY_TYPE_STAGE, CallyStageClass)) +#define CALLY_IS_STAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CALLY_TYPE_STAGE)) +#define CALLY_IS_STAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CALLY_TYPE_STAGE)) +#define CALLY_STAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CALLY_TYPE_STAGE, CallyStageClass)) + +typedef struct _CallyStage CallyStage; +typedef struct _CallyStageClass CallyStageClass; +typedef struct _CallyStagePrivate CallyStagePrivate; + +/** + * CallyStage: + * + * The CallyStage structure contains only + * private data and should be accessed using the provided API + * + * Since: 1.4 + */ +struct _CallyStage +{ + /*< private >*/ + CallyGroup parent; + + CallyStagePrivate *priv; +}; + +/** + * CallyStageClass: + * + * The CallyStageClass structure contains only + * private data + * + * Since: 1.4 + */ +struct _CallyStageClass +{ + /*< private >*/ + CallyGroupClass parent_class; + + /* padding for future expansion */ + gpointer _padding_dummy[16]; +}; + +CLUTTER_AVAILABLE_IN_1_4 +GType cally_stage_get_type (void) G_GNUC_CONST; +CLUTTER_AVAILABLE_IN_1_4 +AtkObject *cally_stage_new (ClutterActor *actor); + +G_END_DECLS + +#endif /* __CALLY_STAGE_H__ */ diff --git a/clutter/clutter/cally/cally-text.c b/clutter/clutter/cally/cally-text.c new file mode 100644 index 0000000..43523ce --- /dev/null +++ b/clutter/clutter/cally/cally-text.c @@ -0,0 +1,2334 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2009 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * Some parts are based on GailLabel, GailEntry, GailTextView from GAIL + * GAIL - The GNOME Accessibility Implementation Library + * Copyright 2001, 2002, 2003 Sun Microsystems Inc. + * + * Implementation of atk_text_get_text_[before/at/after]_offset + * copied from gtkpango.c, part of GTK+ project + * Copyright (c) 2010 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:cally-text + * @short_description: Implementation of the ATK interfaces for a #ClutterText + * @see_also: #ClutterText + * + * #CallyText implements the required ATK interfaces of + * #ClutterText, #AtkText and #AtkEditableText + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "cally-text.h" +#include "cally-actor-private.h" + +#include "clutter-color.h" +#include "clutter-main.h" +#include "clutter-text.h" + +static void cally_text_finalize (GObject *obj); + +/* AtkObject */ +static void cally_text_real_initialize (AtkObject *obj, + gpointer data); +static AtkStateSet* cally_text_ref_state_set (AtkObject *obj); + +/* atkaction */ + +static void _cally_text_activate_action (CallyActor *cally_actor); +static void _check_activate_action (CallyText *cally_text, + ClutterText *clutter_text); + +/* AtkText */ +static void cally_text_text_interface_init (AtkTextIface *iface); +static gchar* cally_text_get_text (AtkText *text, + gint start_offset, + gint end_offset); +static gunichar cally_text_get_character_at_offset (AtkText *text, + gint offset); +static gchar* cally_text_get_text_before_offset (AtkText *text, + gint offset, + AtkTextBoundary boundary_type, + gint *start_offset, + gint *end_offset); +static gchar* cally_text_get_text_at_offset (AtkText *text, + gint offset, + AtkTextBoundary boundary_type, + gint *start_offset, + gint *end_offset); +static gchar* cally_text_get_text_after_offset (AtkText *text, + gint offset, + AtkTextBoundary boundary_type, + gint *start_offset, + gint *end_offset); +static gint cally_text_get_caret_offset (AtkText *text); +static gboolean cally_text_set_caret_offset (AtkText *text, + gint offset); +static gint cally_text_get_character_count (AtkText *text); +static gint cally_text_get_n_selections (AtkText *text); +static gchar* cally_text_get_selection (AtkText *text, + gint selection_num, + gint *start_offset, + gint *end_offset); +static gboolean cally_text_add_selection (AtkText *text, + gint start_offset, + gint end_offset); +static gboolean cally_text_remove_selection (AtkText *text, + gint selection_num); +static gboolean cally_text_set_selection (AtkText *text, + gint selection_num, + gint start_offset, + gint end_offset); +static AtkAttributeSet* cally_text_get_run_attributes (AtkText *text, + gint offset, + gint *start_offset, + gint *end_offset); +static AtkAttributeSet* cally_text_get_default_attributes (AtkText *text); +static void cally_text_get_character_extents (AtkText *text, + gint offset, + gint *x, + gint *y, + gint *width, + gint *height, + AtkCoordType coords); +static gint cally_text_get_offset_at_point (AtkText *text, + gint x, + gint y, + AtkCoordType coords); + +static void _cally_text_get_selection_bounds (ClutterText *clutter_text, + gint *start_offset, + gint *end_offset); +static void _cally_text_insert_text_cb (ClutterText *clutter_text, + gchar *new_text, + gint new_text_length, + gint *position, + gpointer data); +static void _cally_text_delete_text_cb (ClutterText *clutter_text, + gint start_pos, + gint end_pos, + gpointer data); +static gboolean _idle_notify_insert (gpointer data); +static void _notify_insert (CallyText *cally_text); +static void _notify_delete (CallyText *cally_text); + +/* AtkEditableText */ +static void cally_text_editable_text_interface_init (AtkEditableTextIface *iface); +static void cally_text_set_text_contents (AtkEditableText *text, + const gchar *string); +static void cally_text_insert_text (AtkEditableText *text, + const gchar *string, + gint length, + gint *position); +static void cally_text_delete_text (AtkEditableText *text, + gint start_pos, + gint end_pos); + +/* CallyActor */ +static void cally_text_notify_clutter (GObject *obj, + GParamSpec *pspec); + +static gboolean _check_for_selection_change (CallyText *cally_text, + ClutterText *clutter_text); + +/* Misc functions */ +static AtkAttributeSet* _cally_misc_add_attribute (AtkAttributeSet *attrib_set, + AtkTextAttribute attr, + gchar *value); + +static AtkAttributeSet* _cally_misc_layout_get_run_attributes (AtkAttributeSet *attrib_set, + ClutterText *clutter_text, + gint offset, + gint *start_offset, + gint *end_offset); + +static AtkAttributeSet* _cally_misc_layout_get_default_attributes (AtkAttributeSet *attrib_set, + ClutterText *text); + +static int _cally_misc_get_index_at_point (ClutterText *clutter_text, + gint x, + gint y, + AtkCoordType coords); + +struct _CallyTextPrivate +{ + /* Cached ClutterText values*/ + gint cursor_position; + gint selection_bound; + + /* text_changed::insert stuff */ + const gchar *signal_name_insert; + gint position_insert; + gint length_insert; + guint insert_idle_handler; + + /* text_changed::delete stuff */ + const gchar *signal_name_delete; + gint position_delete; + gint length_delete; + + /* action */ + guint activate_action_id; +}; + +G_DEFINE_TYPE_WITH_CODE (CallyText, + cally_text, + CALLY_TYPE_ACTOR, + G_ADD_PRIVATE (CallyText) + G_IMPLEMENT_INTERFACE (ATK_TYPE_TEXT, + cally_text_text_interface_init) + G_IMPLEMENT_INTERFACE (ATK_TYPE_EDITABLE_TEXT, + cally_text_editable_text_interface_init)); + +static void +cally_text_class_init (CallyTextClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + CallyActorClass *cally_class = CALLY_ACTOR_CLASS (klass); + + gobject_class->finalize = cally_text_finalize; + + class->initialize = cally_text_real_initialize; + class->ref_state_set = cally_text_ref_state_set; + + cally_class->notify_clutter = cally_text_notify_clutter; +} + +static void +cally_text_init (CallyText *cally_text) +{ + CallyTextPrivate *priv = cally_text_get_instance_private (cally_text); + + cally_text->priv = priv; + + priv->cursor_position = 0; + priv->selection_bound = 0; + + priv->signal_name_insert = NULL; + priv->position_insert = -1; + priv->length_insert = -1; + priv->insert_idle_handler = 0; + + priv->signal_name_delete = NULL; + priv->position_delete = -1; + priv->length_delete = -1; + + priv->activate_action_id = 0; +} + +static void +cally_text_finalize (GObject *obj) +{ + CallyText *cally_text = CALLY_TEXT (obj); + +/* g_object_unref (cally_text->priv->textutil); */ +/* cally_text->priv->textutil = NULL; */ + + if (cally_text->priv->insert_idle_handler) + { + g_source_remove (cally_text->priv->insert_idle_handler); + cally_text->priv->insert_idle_handler = 0; + } + + G_OBJECT_CLASS (cally_text_parent_class)->finalize (obj); +} + +/** + * cally_text_new: + * @actor: a #ClutterActor + * + * Creates a new #CallyText for the given @actor. @actor must be a + * #ClutterText. + * + * Return value: the newly created #AtkObject + * + * Since: 1.4 + */ +AtkObject* +cally_text_new (ClutterActor *actor) +{ + GObject *object = NULL; + AtkObject *accessible = NULL; + + g_return_val_if_fail (CLUTTER_IS_TEXT (actor), NULL); + + object = g_object_new (CALLY_TYPE_TEXT, NULL); + + accessible = ATK_OBJECT (object); + atk_object_initialize (accessible, actor); + + return accessible; +} + +/* atkobject.h */ + +static void +cally_text_real_initialize(AtkObject *obj, + gpointer data) +{ + ClutterText *clutter_text = NULL; + CallyText *cally_text = NULL; + + ATK_OBJECT_CLASS (cally_text_parent_class)->initialize (obj, data); + + g_return_if_fail (CLUTTER_TEXT (data)); + + cally_text = CALLY_TEXT (obj); + clutter_text = CLUTTER_TEXT (data); + + cally_text->priv->cursor_position = clutter_text_get_cursor_position (clutter_text); + cally_text->priv->selection_bound = clutter_text_get_selection_bound (clutter_text); + + g_signal_connect (clutter_text, "insert-text", + G_CALLBACK (_cally_text_insert_text_cb), + cally_text); + g_signal_connect (clutter_text, "delete-text", + G_CALLBACK (_cally_text_delete_text_cb), + cally_text); + + _check_activate_action (cally_text, clutter_text); + + if (clutter_text_get_password_char (clutter_text) != 0) + atk_object_set_role (obj, ATK_ROLE_PASSWORD_TEXT); + else + atk_object_set_role (obj, ATK_ROLE_TEXT); +} + +static AtkStateSet* +cally_text_ref_state_set (AtkObject *obj) +{ + AtkStateSet *result = NULL; + ClutterActor *actor = NULL; + + result = ATK_OBJECT_CLASS (cally_text_parent_class)->ref_state_set (obj); + + actor = CALLY_GET_CLUTTER_ACTOR (obj); + + if (actor == NULL) + return result; + + if (clutter_text_get_editable (CLUTTER_TEXT (actor))) + atk_state_set_add_state (result, ATK_STATE_EDITABLE); + + if (clutter_text_get_selectable (CLUTTER_TEXT (actor))) + atk_state_set_add_state (result, ATK_STATE_SELECTABLE_TEXT); + + return result; +} + +/***** pango stuff **** + * + * FIXME: all this pango related code used to implement + * atk_text_get_text_[before/at/after]_offset was copied from GTK, and + * should be on a common library (like pango itself). + * + *********************/ + +/* + * _gtk_pango_move_chars: + * @layout: a #PangoLayout + * @offset: a character offset in @layout + * @count: the number of characters to move from @offset + * + * Returns the position that is @count characters from the + * given @offset. @count may be positive or negative. + * + * For the purpose of this function, characters are defined + * by what Pango considers cursor positions. + * + * Returns: the new position + */ +static gint +_gtk_pango_move_chars (PangoLayout *layout, + gint offset, + gint count) +{ + const PangoLogAttr *attrs; + gint n_attrs; + + attrs = pango_layout_get_log_attrs_readonly (layout, &n_attrs); + + while (count > 0 && offset < n_attrs - 1) + { + do + offset++; + while (offset < n_attrs - 1 && !attrs[offset].is_cursor_position); + + count--; + } + while (count < 0 && offset > 0) + { + do + offset--; + while (offset > 0 && !attrs[offset].is_cursor_position); + + count++; + } + + return offset; +} + +/* + * _gtk_pango_move_words: + * @layout: a #PangoLayout + * @offset: a character offset in @layout + * @count: the number of words to move from @offset + * + * Returns the position that is @count words from the + * given @offset. @count may be positive or negative. + * + * If @count is positive, the returned position will + * be a word end, otherwise it will be a word start. + * See the Pango documentation for details on how + * word starts and ends are defined. + * + * Returns: the new position + */ +static gint +_gtk_pango_move_words (PangoLayout *layout, + gint offset, + gint count) +{ + const PangoLogAttr *attrs; + gint n_attrs; + + attrs = pango_layout_get_log_attrs_readonly (layout, &n_attrs); + + while (count > 0 && offset < n_attrs - 1) + { + do + offset++; + while (offset < n_attrs - 1 && !attrs[offset].is_word_end); + + count--; + } + while (count < 0 && offset > 0) + { + do + offset--; + while (offset > 0 && !attrs[offset].is_word_start); + + count++; + } + + return offset; +} + +/* + * _gtk_pango_move_sentences: + * @layout: a #PangoLayout + * @offset: a character offset in @layout + * @count: the number of sentences to move from @offset + * + * Returns the position that is @count sentences from the + * given @offset. @count may be positive or negative. + * + * If @count is positive, the returned position will + * be a sentence end, otherwise it will be a sentence start. + * See the Pango documentation for details on how + * sentence starts and ends are defined. + * + * Returns: the new position + */ +static gint +_gtk_pango_move_sentences (PangoLayout *layout, + gint offset, + gint count) +{ + const PangoLogAttr *attrs; + gint n_attrs; + + attrs = pango_layout_get_log_attrs_readonly (layout, &n_attrs); + + while (count > 0 && offset < n_attrs - 1) + { + do + offset++; + while (offset < n_attrs - 1 && !attrs[offset].is_sentence_end); + + count--; + } + while (count < 0 && offset > 0) + { + do + offset--; + while (offset > 0 && !attrs[offset].is_sentence_start); + + count++; + } + + return offset; +} + +/* + * _gtk_pango_is_inside_word: + * @layout: a #PangoLayout + * @offset: a character offset in @layout + * + * Returns whether the given position is inside + * a word. + * + * Returns: %TRUE if @offset is inside a word + */ +static gboolean +_gtk_pango_is_inside_word (PangoLayout *layout, + gint offset) +{ + const PangoLogAttr *attrs; + gint n_attrs; + + attrs = pango_layout_get_log_attrs_readonly (layout, &n_attrs); + + while (offset >= 0 && + !(attrs[offset].is_word_start || attrs[offset].is_word_end)) + offset--; + + if (offset >= 0) + return attrs[offset].is_word_start; + + return FALSE; +} + +/* + * _gtk_pango_is_inside_sentence: + * @layout: a #PangoLayout + * @offset: a character offset in @layout + * + * Returns whether the given position is inside + * a sentence. + * + * Returns: %TRUE if @offset is inside a sentence + */ +static gboolean +_gtk_pango_is_inside_sentence (PangoLayout *layout, + gint offset) +{ + const PangoLogAttr *attrs; + gint n_attrs; + + attrs = pango_layout_get_log_attrs_readonly (layout, &n_attrs); + + while (offset >= 0 && + !(attrs[offset].is_sentence_start || attrs[offset].is_sentence_end)) + offset--; + + if (offset >= 0) + return attrs[offset].is_sentence_start; + + return FALSE; +} + +static void +pango_layout_get_line_before (PangoLayout *layout, + AtkTextBoundary boundary_type, + gint offset, + gint *start_offset, + gint *end_offset) +{ + PangoLayoutIter *iter; + PangoLayoutLine *line, *prev_line = NULL, *prev_prev_line = NULL; + gint index, start_index, end_index; + const gchar *text; + gboolean found = FALSE; + + text = pango_layout_get_text (layout); + index = g_utf8_offset_to_pointer (text, offset) - text; + iter = pango_layout_get_iter (layout); + do + { + line = pango_layout_iter_get_line (iter); + start_index = line->start_index; + end_index = start_index + line->length; + + if (index >= start_index && index <= end_index) + { + /* Found line for offset */ + if (prev_line) + { + switch (boundary_type) + { + case ATK_TEXT_BOUNDARY_LINE_START: + end_index = start_index; + start_index = prev_line->start_index; + break; + case ATK_TEXT_BOUNDARY_LINE_END: + if (prev_prev_line) + start_index = prev_prev_line->start_index + prev_prev_line->length; + else + start_index = 0; + end_index = prev_line->start_index + prev_line->length; + break; + default: + g_assert_not_reached(); + } + } + else + start_index = end_index = 0; + + found = TRUE; + break; + } + + prev_prev_line = prev_line; + prev_line = line; + } + while (pango_layout_iter_next_line (iter)); + + if (!found) + { + start_index = prev_line->start_index + prev_line->length; + end_index = start_index; + } + pango_layout_iter_free (iter); + + *start_offset = g_utf8_pointer_to_offset (text, text + start_index); + *end_offset = g_utf8_pointer_to_offset (text, text + end_index); +} + +static void +pango_layout_get_line_at (PangoLayout *layout, + AtkTextBoundary boundary_type, + gint offset, + gint *start_offset, + gint *end_offset) +{ + PangoLayoutIter *iter; + PangoLayoutLine *line, *prev_line = NULL; + gint index, start_index, end_index; + const gchar *text; + gboolean found = FALSE; + + text = pango_layout_get_text (layout); + index = g_utf8_offset_to_pointer (text, offset) - text; + iter = pango_layout_get_iter (layout); + do + { + line = pango_layout_iter_get_line (iter); + start_index = line->start_index; + end_index = start_index + line->length; + + if (index >= start_index && index <= end_index) + { + /* Found line for offset */ + switch (boundary_type) + { + case ATK_TEXT_BOUNDARY_LINE_START: + if (pango_layout_iter_next_line (iter)) + end_index = pango_layout_iter_get_line (iter)->start_index; + break; + case ATK_TEXT_BOUNDARY_LINE_END: + if (prev_line) + start_index = prev_line->start_index + prev_line->length; + break; + default: + g_assert_not_reached(); + } + + found = TRUE; + break; + } + + prev_line = line; + } + while (pango_layout_iter_next_line (iter)); + + if (!found) + { + start_index = prev_line->start_index + prev_line->length; + end_index = start_index; + } + pango_layout_iter_free (iter); + + *start_offset = g_utf8_pointer_to_offset (text, text + start_index); + *end_offset = g_utf8_pointer_to_offset (text, text + end_index); +} + +static void +pango_layout_get_line_after (PangoLayout *layout, + AtkTextBoundary boundary_type, + gint offset, + gint *start_offset, + gint *end_offset) +{ + PangoLayoutIter *iter; + PangoLayoutLine *line, *prev_line = NULL; + gint index, start_index, end_index; + const gchar *text; + gboolean found = FALSE; + + text = pango_layout_get_text (layout); + index = g_utf8_offset_to_pointer (text, offset) - text; + iter = pango_layout_get_iter (layout); + do + { + line = pango_layout_iter_get_line (iter); + start_index = line->start_index; + end_index = start_index + line->length; + + if (index >= start_index && index <= end_index) + { + /* Found line for offset */ + if (pango_layout_iter_next_line (iter)) + { + line = pango_layout_iter_get_line (iter); + switch (boundary_type) + { + case ATK_TEXT_BOUNDARY_LINE_START: + start_index = line->start_index; + if (pango_layout_iter_next_line (iter)) + end_index = pango_layout_iter_get_line (iter)->start_index; + else + end_index = start_index + line->length; + break; + case ATK_TEXT_BOUNDARY_LINE_END: + start_index = end_index; + end_index = line->start_index + line->length; + break; + default: + g_assert_not_reached(); + } + } + else + start_index = end_index; + + found = TRUE; + break; + } + + prev_line = line; + } + while (pango_layout_iter_next_line (iter)); + + if (!found) + { + start_index = prev_line->start_index + prev_line->length; + end_index = start_index; + } + pango_layout_iter_free (iter); + + *start_offset = g_utf8_pointer_to_offset (text, text + start_index); + *end_offset = g_utf8_pointer_to_offset (text, text + end_index); +} + +/* + * _gtk_pango_get_text_at: + * @layout: a #PangoLayout + * @boundary_type: a #AtkTextBoundary + * @offset: a character offset in @layout + * @start_offset: return location for the start of the returned text + * @end_offset: return location for the end of the return text + * + * Gets a slice of the text from @layout at @offset. + * + * The @boundary_type determines the size of the returned slice of + * text. For the exact semantics of this function, see + * atk_text_get_text_after_offset(). + * + * Returns: a newly allocated string containing a slice of text + * from layout. Free with g_free(). + */ +static gchar * +_gtk_pango_get_text_at (PangoLayout *layout, + AtkTextBoundary boundary_type, + gint offset, + gint *start_offset, + gint *end_offset) +{ + const gchar *text; + gint start, end; + const PangoLogAttr *attrs; + gint n_attrs; + + text = pango_layout_get_text (layout); + + if (text[0] == 0) + { + *start_offset = 0; + *end_offset = 0; + return g_strdup (""); + } + + attrs = pango_layout_get_log_attrs_readonly (layout, &n_attrs); + + start = offset; + end = start; + + switch (boundary_type) + { + case ATK_TEXT_BOUNDARY_CHAR: + end = _gtk_pango_move_chars (layout, end, 1); + break; + + case ATK_TEXT_BOUNDARY_WORD_START: + if (!attrs[start].is_word_start) + start = _gtk_pango_move_words (layout, start, -1); + if (_gtk_pango_is_inside_word (layout, end)) + end = _gtk_pango_move_words (layout, end, 1); + while (!attrs[end].is_word_start && end < n_attrs - 1) + end = _gtk_pango_move_chars (layout, end, 1); + break; + + case ATK_TEXT_BOUNDARY_WORD_END: + if (_gtk_pango_is_inside_word (layout, start) && + !attrs[start].is_word_start) + start = _gtk_pango_move_words (layout, start, -1); + while (!attrs[start].is_word_end && start > 0) + start = _gtk_pango_move_chars (layout, start, -1); + end = _gtk_pango_move_words (layout, end, 1); + break; + + case ATK_TEXT_BOUNDARY_SENTENCE_START: + if (!attrs[start].is_sentence_start) + start = _gtk_pango_move_sentences (layout, start, -1); + if (_gtk_pango_is_inside_sentence (layout, end)) + end = _gtk_pango_move_sentences (layout, end, 1); + while (!attrs[end].is_sentence_start && end < n_attrs - 1) + end = _gtk_pango_move_chars (layout, end, 1); + break; + + case ATK_TEXT_BOUNDARY_SENTENCE_END: + if (_gtk_pango_is_inside_sentence (layout, start) && + !attrs[start].is_sentence_start) + start = _gtk_pango_move_sentences (layout, start, -1); + while (!attrs[start].is_sentence_end && start > 0) + start = _gtk_pango_move_chars (layout, start, -1); + end = _gtk_pango_move_sentences (layout, end, 1); + break; + + case ATK_TEXT_BOUNDARY_LINE_START: + case ATK_TEXT_BOUNDARY_LINE_END: + pango_layout_get_line_at (layout, boundary_type, offset, &start, &end); + break; + } + + *start_offset = start; + *end_offset = end; + + g_assert (start <= end); + + return g_utf8_substring (text, start, end); +} + +/* + * _gtk_pango_get_text_before: + * @layout: a #PangoLayout + * @boundary_type: a #AtkTextBoundary + * @offset: a character offset in @layout + * @start_offset: return location for the start of the returned text + * @end_offset: return location for the end of the return text + * + * Gets a slice of the text from @layout before @offset. + * + * The @boundary_type determines the size of the returned slice of + * text. For the exact semantics of this function, see + * atk_text_get_text_before_offset(). + * + * Returns: a newly allocated string containing a slice of text + * from layout. Free with g_free(). + */ +static gchar * +_gtk_pango_get_text_before (PangoLayout *layout, + AtkTextBoundary boundary_type, + gint offset, + gint *start_offset, + gint *end_offset) +{ + const gchar *text; + gint start, end; + const PangoLogAttr *attrs; + gint n_attrs; + + text = pango_layout_get_text (layout); + + if (text[0] == 0) + { + *start_offset = 0; + *end_offset = 0; + return g_strdup (""); + } + + attrs = pango_layout_get_log_attrs_readonly (layout, &n_attrs); + + start = offset; + end = start; + + switch (boundary_type) + { + case ATK_TEXT_BOUNDARY_CHAR: + start = _gtk_pango_move_chars (layout, start, -1); + break; + + case ATK_TEXT_BOUNDARY_WORD_START: + if (!attrs[start].is_word_start) + start = _gtk_pango_move_words (layout, start, -1); + end = start; + start = _gtk_pango_move_words (layout, start, -1); + break; + + case ATK_TEXT_BOUNDARY_WORD_END: + if (_gtk_pango_is_inside_word (layout, start) && + !attrs[start].is_word_start) + start = _gtk_pango_move_words (layout, start, -1); + while (!attrs[start].is_word_end && start > 0) + start = _gtk_pango_move_chars (layout, start, -1); + end = start; + start = _gtk_pango_move_words (layout, start, -1); + while (!attrs[start].is_word_end && start > 0) + start = _gtk_pango_move_chars (layout, start, -1); + break; + + case ATK_TEXT_BOUNDARY_SENTENCE_START: + if (!attrs[start].is_sentence_start) + start = _gtk_pango_move_sentences (layout, start, -1); + end = start; + start = _gtk_pango_move_sentences (layout, start, -1); + break; + + case ATK_TEXT_BOUNDARY_SENTENCE_END: + if (_gtk_pango_is_inside_sentence (layout, start) && + !attrs[start].is_sentence_start) + start = _gtk_pango_move_sentences (layout, start, -1); + while (!attrs[start].is_sentence_end && start > 0) + start = _gtk_pango_move_chars (layout, start, -1); + end = start; + start = _gtk_pango_move_sentences (layout, start, -1); + while (!attrs[start].is_sentence_end && start > 0) + start = _gtk_pango_move_chars (layout, start, -1); + break; + + case ATK_TEXT_BOUNDARY_LINE_START: + case ATK_TEXT_BOUNDARY_LINE_END: + pango_layout_get_line_before (layout, boundary_type, offset, &start, &end); + break; + } + + *start_offset = start; + *end_offset = end; + + g_assert (start <= end); + + return g_utf8_substring (text, start, end); +} + +/* + * _gtk_pango_get_text_after: + * @layout: a #PangoLayout + * @boundary_type: a #AtkTextBoundary + * @offset: a character offset in @layout + * @start_offset: return location for the start of the returned text + * @end_offset: return location for the end of the return text + * + * Gets a slice of the text from @layout after @offset. + * + * The @boundary_type determines the size of the returned slice of + * text. For the exact semantics of this function, see + * atk_text_get_text_after_offset(). + * + * Returns: a newly allocated string containing a slice of text + * from layout. Free with g_free(). + */ +static gchar * +_gtk_pango_get_text_after (PangoLayout *layout, + AtkTextBoundary boundary_type, + gint offset, + gint *start_offset, + gint *end_offset) +{ + const gchar *text; + gint start, end; + const PangoLogAttr *attrs; + gint n_attrs; + + text = pango_layout_get_text (layout); + + if (text[0] == 0) + { + *start_offset = 0; + *end_offset = 0; + return g_strdup (""); + } + + attrs = pango_layout_get_log_attrs_readonly (layout, &n_attrs); + + start = offset; + end = start; + + switch (boundary_type) + { + case ATK_TEXT_BOUNDARY_CHAR: + start = _gtk_pango_move_chars (layout, start, 1); + end = start; + end = _gtk_pango_move_chars (layout, end, 1); + break; + + case ATK_TEXT_BOUNDARY_WORD_START: + if (_gtk_pango_is_inside_word (layout, end)) + end = _gtk_pango_move_words (layout, end, 1); + while (!attrs[end].is_word_start && end < n_attrs - 1) + end = _gtk_pango_move_chars (layout, end, 1); + start = end; + if (end < n_attrs - 1) + { + end = _gtk_pango_move_words (layout, end, 1); + while (!attrs[end].is_word_start && end < n_attrs - 1) + end = _gtk_pango_move_chars (layout, end, 1); + } + break; + + case ATK_TEXT_BOUNDARY_WORD_END: + end = _gtk_pango_move_words (layout, end, 1); + start = end; + if (end < n_attrs - 1) + end = _gtk_pango_move_words (layout, end, 1); + break; + + case ATK_TEXT_BOUNDARY_SENTENCE_START: + if (_gtk_pango_is_inside_sentence (layout, end)) + end = _gtk_pango_move_sentences (layout, end, 1); + while (!attrs[end].is_sentence_start && end < n_attrs - 1) + end = _gtk_pango_move_chars (layout, end, 1); + start = end; + if (end < n_attrs - 1) + { + end = _gtk_pango_move_sentences (layout, end, 1); + while (!attrs[end].is_sentence_start && end < n_attrs - 1) + end = _gtk_pango_move_chars (layout, end, 1); + } + break; + + case ATK_TEXT_BOUNDARY_SENTENCE_END: + end = _gtk_pango_move_sentences (layout, end, 1); + start = end; + if (end < n_attrs - 1) + end = _gtk_pango_move_sentences (layout, end, 1); + break; + + case ATK_TEXT_BOUNDARY_LINE_START: + case ATK_TEXT_BOUNDARY_LINE_END: + pango_layout_get_line_after (layout, boundary_type, offset, &start, &end); + break; + } + + *start_offset = start; + *end_offset = end; + + g_assert (start <= end); + + return g_utf8_substring (text, start, end); +} + +/***** atktext.h ******/ + +static void +cally_text_text_interface_init (AtkTextIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->get_text = cally_text_get_text; + iface->get_character_at_offset = cally_text_get_character_at_offset; + iface->get_text_before_offset = cally_text_get_text_before_offset; + iface->get_text_at_offset = cally_text_get_text_at_offset; + iface->get_text_after_offset = cally_text_get_text_after_offset; + iface->get_character_count = cally_text_get_character_count; + iface->get_caret_offset = cally_text_get_caret_offset; + iface->set_caret_offset = cally_text_set_caret_offset; + iface->get_n_selections = cally_text_get_n_selections; + iface->get_selection = cally_text_get_selection; + iface->add_selection = cally_text_add_selection; + iface->remove_selection = cally_text_remove_selection; + iface->set_selection = cally_text_set_selection; + iface->get_run_attributes = cally_text_get_run_attributes; + iface->get_default_attributes = cally_text_get_default_attributes; + iface->get_character_extents = cally_text_get_character_extents; + iface->get_offset_at_point = cally_text_get_offset_at_point; + +} + +static gchar* +cally_text_get_text (AtkText *text, + gint start_offset, + gint end_offset) +{ + ClutterActor *actor = NULL; + PangoLayout *layout = NULL; + const gchar *string = NULL; + gint character_count = 0; + + actor = CALLY_GET_CLUTTER_ACTOR (text); + if (actor == NULL) /* Object is defunct */ + return NULL; + + /* we use the pango layout instead of clutter_text_get_chars because + it take into account password-char */ + + layout = clutter_text_get_layout (CLUTTER_TEXT (actor)); + string = pango_layout_get_text (layout); + character_count = pango_layout_get_character_count (layout); + + if (end_offset == -1 || end_offset > character_count) + end_offset = character_count; + + if (string[0] == 0) + return g_strdup(""); + else + return g_utf8_substring (string, start_offset, end_offset); +} + +static gunichar +cally_text_get_character_at_offset (AtkText *text, + gint offset) +{ + ClutterActor *actor = NULL; + const gchar *string = NULL; + gchar *index = NULL; + gunichar unichar; + PangoLayout *layout = NULL; + + actor = CALLY_GET_CLUTTER_ACTOR (text); + if (actor == NULL) /* State is defunct */ + return '\0'; + + /* we use the pango layout instead of clutter_text_get_chars because + it take into account password-char */ + + layout = clutter_text_get_layout (CLUTTER_TEXT (actor)); + string = pango_layout_get_text (layout); + + if (offset >= g_utf8_strlen (string, -1)) + { + unichar = '\0'; + } + else + { + index = g_utf8_offset_to_pointer (string, offset); + + unichar = g_utf8_get_char (index); + } + + return unichar; +} + +static gchar* +cally_text_get_text_before_offset (AtkText *text, + gint offset, + AtkTextBoundary boundary_type, + gint *start_offset, + gint *end_offset) +{ + ClutterActor *actor = NULL; + + actor = CALLY_GET_CLUTTER_ACTOR (text); + if (actor == NULL) /* State is defunct */ + return NULL; + + return _gtk_pango_get_text_before (clutter_text_get_layout (CLUTTER_TEXT (actor)), + boundary_type, offset, + start_offset, end_offset); +} + +static gchar* +cally_text_get_text_at_offset (AtkText *text, + gint offset, + AtkTextBoundary boundary_type, + gint *start_offset, + gint *end_offset) +{ + ClutterActor *actor = NULL; + + actor = CALLY_GET_CLUTTER_ACTOR (text); + if (actor == NULL) /* State is defunct */ + return NULL; + + return _gtk_pango_get_text_at (clutter_text_get_layout (CLUTTER_TEXT (actor)), + boundary_type, offset, + start_offset, end_offset); +} + +static gchar* +cally_text_get_text_after_offset (AtkText *text, + gint offset, + AtkTextBoundary boundary_type, + gint *start_offset, + gint *end_offset) +{ + ClutterActor *actor = NULL; + + actor = CALLY_GET_CLUTTER_ACTOR (text); + if (actor == NULL) /* State is defunct */ + return NULL; + + return _gtk_pango_get_text_after (clutter_text_get_layout (CLUTTER_TEXT (actor)), + boundary_type, offset, + start_offset, end_offset); +} + +static gint +cally_text_get_caret_offset (AtkText *text) +{ + ClutterActor *actor = NULL; + + actor = CALLY_GET_CLUTTER_ACTOR (text); + if (actor == NULL) /* State is defunct */ + return -1; + + return clutter_text_get_cursor_position (CLUTTER_TEXT (actor)); +} + +static gboolean +cally_text_set_caret_offset (AtkText *text, + gint offset) +{ + ClutterActor *actor = NULL; + + actor = CALLY_GET_CLUTTER_ACTOR (text); + if (actor == NULL) /* State is defunct */ + return FALSE; + + clutter_text_set_cursor_position (CLUTTER_TEXT (actor), offset); + + /* like in gailentry, we suppose that this always works, as clutter text + doesn't return anything */ + return TRUE; +} + +static gint +cally_text_get_character_count (AtkText *text) +{ + ClutterActor *actor = NULL; + ClutterText *clutter_text = NULL; + + actor = CALLY_GET_CLUTTER_ACTOR (text); + if (actor == NULL) /* State is defunct */ + return 0; + + clutter_text = CLUTTER_TEXT (actor); + return g_utf8_strlen (clutter_text_get_text (clutter_text), -1); +} + +static gint +cally_text_get_n_selections (AtkText *text) +{ + ClutterActor *actor = NULL; + gint selection_bound = -1; + gint cursor_position = -1; + + actor = CALLY_GET_CLUTTER_ACTOR (text); + if (actor == NULL) /* State is defunct */ + return 0; + + if (!clutter_text_get_selectable (CLUTTER_TEXT (actor))) + return 0; + + selection_bound = clutter_text_get_selection_bound (CLUTTER_TEXT (actor)); + cursor_position = clutter_text_get_cursor_position (CLUTTER_TEXT (actor)); + + if (selection_bound == cursor_position) + return 0; + else + return 1; +} + +static gchar* +cally_text_get_selection (AtkText *text, + gint selection_num, + gint *start_offset, + gint *end_offset) +{ + ClutterActor *actor = NULL; + + actor = CALLY_GET_CLUTTER_ACTOR (text); + if (actor == NULL) /* State is defunct */ + return NULL; + + /* As in gailentry, only let the user get the selection if one is set, and if + * the selection_num is 0. + */ + if (selection_num != 0) + return NULL; + + _cally_text_get_selection_bounds (CLUTTER_TEXT (actor), start_offset, end_offset); + + if (*start_offset != *end_offset) + return clutter_text_get_selection (CLUTTER_TEXT (actor)); + else + return NULL; +} + +/* ClutterText only allows one selection. So this method will set the selection + if no selection exists, but as in gailentry, it will not change the current + selection */ +static gboolean +cally_text_add_selection (AtkText *text, + gint start_offset, + gint end_offset) +{ + ClutterActor *actor; + gint select_start, select_end; + + actor = CALLY_GET_CLUTTER_ACTOR (text); + if (actor == NULL) /* State is defunct */ + return FALSE; + + _cally_text_get_selection_bounds (CLUTTER_TEXT (actor), + &select_start, &select_end); + + /* Like in gailentry, if there is already a selection, then don't allow another + * to be added, since ClutterText only supports one selected region. + */ + if (select_start == select_end) + { + clutter_text_set_selection (CLUTTER_TEXT (actor), + start_offset, end_offset); + + return TRUE; + } + else + return FALSE; +} + + +static gboolean +cally_text_remove_selection (AtkText *text, + gint selection_num) +{ + ClutterActor *actor = NULL; + gint caret_pos = -1; + gint select_start = -1; + gint select_end = -1; + + actor = CALLY_GET_CLUTTER_ACTOR (text); + if (actor == NULL) /* State is defunct */ + return FALSE; + + /* only one selection is allowed */ + if (selection_num != 0) + return FALSE; + + _cally_text_get_selection_bounds (CLUTTER_TEXT (actor), + &select_start, &select_end); + + if (select_start != select_end) + { + /* Setting the start & end of the selected region to the caret position + * turns off the selection. + */ + caret_pos = clutter_text_get_cursor_position (CLUTTER_TEXT (actor)); + clutter_text_set_selection (CLUTTER_TEXT (actor), + caret_pos, caret_pos); + return TRUE; + } + else + return FALSE; +} + +static gboolean +cally_text_set_selection (AtkText *text, + gint selection_num, + gint start_offset, + gint end_offset) +{ + ClutterActor *actor = NULL; + gint select_start = -1; + gint select_end = -1; + + actor = CALLY_GET_CLUTTER_ACTOR (text); + if (actor == NULL) /* State is defunct */ + return FALSE; + + /* Like in gailentry, only let the user move the selection if one is set, + * and if the selection_num is 0 + */ + if (selection_num != 0) + return FALSE; + + _cally_text_get_selection_bounds (CLUTTER_TEXT (actor), + &select_start, &select_end); + + if (select_start != select_end) + { + clutter_text_set_selection (CLUTTER_TEXT (actor), + start_offset, end_offset); + return TRUE; + } + else + return FALSE; +} + +static AtkAttributeSet* +cally_text_get_run_attributes (AtkText *text, + gint offset, + gint *start_offset, + gint *end_offset) +{ + ClutterActor *actor = NULL; + ClutterText *clutter_text = NULL; + AtkAttributeSet *at_set = NULL; + + actor = CALLY_GET_CLUTTER_ACTOR (text); + if (actor == NULL) /* State is defunct */ + return NULL; + + /* Clutter don't have any reference to the direction*/ + + clutter_text = CLUTTER_TEXT (actor); + + at_set = _cally_misc_layout_get_run_attributes (at_set, + clutter_text, + offset, + start_offset, + end_offset); + + return at_set; +} + +static AtkAttributeSet* +cally_text_get_default_attributes (AtkText *text) +{ + ClutterActor *actor = NULL; + ClutterText *clutter_text = NULL; + AtkAttributeSet *at_set = NULL; + + actor = CALLY_GET_CLUTTER_ACTOR (text); + if (actor == NULL) /* State is defunct */ + return NULL; + + clutter_text = CLUTTER_TEXT (actor); + + at_set = _cally_misc_layout_get_default_attributes (at_set, clutter_text); + + return at_set; +} + +static void cally_text_get_character_extents (AtkText *text, + gint offset, + gint *xp, + gint *yp, + gint *widthp, + gint *heightp, + AtkCoordType coords) +{ + ClutterActor *actor = NULL; + ClutterText *clutter_text = NULL; + gint x = 0, y = 0, width = 0, height = 0; + gint index, x_window, y_window, x_toplevel, y_toplevel; + gint x_layout, y_layout; + PangoLayout *layout; + PangoRectangle extents; + const gchar *text_value; + ClutterVertex verts[4]; + + actor = CALLY_GET_CLUTTER_ACTOR (text); + if (actor == NULL) /* State is defunct */ + goto done; + + clutter_text = CLUTTER_TEXT (actor); + + text_value = clutter_text_get_text (clutter_text); + index = g_utf8_offset_to_pointer (text_value, offset) - text_value; + + layout = clutter_text_get_layout (clutter_text); + pango_layout_index_to_pos (layout, index, &extents); + + /* handle RTL text layout */ + if (extents.width < 0) + { + extents.x += extents.width; + extents.width = -extents.width; + } + + clutter_actor_get_abs_allocation_vertices (actor, verts); + x_window = verts[0].x; + y_window = verts[0].y; + + clutter_text_get_layout_offsets (clutter_text, &x_layout, &y_layout); + + x = (extents.x / PANGO_SCALE) + x_layout + x_window; + y = (extents.y / PANGO_SCALE) + y_layout + y_window; + width = extents.width / PANGO_SCALE; + height = extents.height / PANGO_SCALE; + + if (coords == ATK_XY_SCREEN) + { + _cally_actor_get_top_level_origin (actor, &x_toplevel, &y_toplevel); + x += x_toplevel; + y += y_toplevel; + } + +done: + if (widthp) + *widthp = width; + + if (heightp) + *heightp = height; + + if (xp) + *xp = x; + + if (yp) + *yp = y; +} + +static gint +cally_text_get_offset_at_point (AtkText *text, + gint x, + gint y, + AtkCoordType coords) +{ + ClutterActor *actor = NULL; + ClutterText *clutter_text = NULL; + const gchar *text_value; + gint index; + + actor = CALLY_GET_CLUTTER_ACTOR (text); + if (actor == NULL) /* State is defunct */ + return -1; + + clutter_text = CLUTTER_TEXT (actor); + + index = _cally_misc_get_index_at_point (clutter_text, x, y, coords); + text_value = clutter_text_get_text (clutter_text); + if (index == -1) + return g_utf8_strlen (text_value, -1); + else + return g_utf8_pointer_to_offset (text_value, text_value + index); +} + + +/******** Auxiliar private methods ******/ + +/* ClutterText only maintains the current cursor position and a extra selection + bound, but this could be before or after the cursor. This method returns + the start and end positions in a proper order (so start<=end). This is + similar to the function gtk_editable_get_selection_bounds */ +static void +_cally_text_get_selection_bounds (ClutterText *clutter_text, + gint *start_offset, + gint *end_offset) +{ + gint pos = -1; + gint selection_bound = -1; + + pos = clutter_text_get_cursor_position (clutter_text); + selection_bound = clutter_text_get_selection_bound (clutter_text); + + if (pos < selection_bound) + { + *start_offset = pos; + *end_offset = selection_bound; + } + else + { + *start_offset = selection_bound; + *end_offset = pos; + } +} + +static void +_cally_text_delete_text_cb (ClutterText *clutter_text, + gint start_pos, + gint end_pos, + gpointer data) +{ + CallyText *cally_text = NULL; + + g_return_if_fail (CALLY_IS_TEXT (data)); + + /* Ignore zero lengh deletions */ + if (end_pos - start_pos == 0) + return; + + cally_text = CALLY_TEXT (data); + + if (!cally_text->priv->signal_name_delete) + { + cally_text->priv->signal_name_delete = "text_changed::delete"; + cally_text->priv->position_delete = start_pos; + cally_text->priv->length_delete = end_pos - start_pos; + } + + _notify_delete (cally_text); +} + +static void +_cally_text_insert_text_cb (ClutterText *clutter_text, + gchar *new_text, + gint new_text_length, + gint *position, + gpointer data) +{ + CallyText *cally_text = NULL; + + g_return_if_fail (CALLY_IS_TEXT (data)); + + cally_text = CALLY_TEXT (data); + + if (!cally_text->priv->signal_name_insert) + { + cally_text->priv->signal_name_insert = "text_changed::insert"; + cally_text->priv->position_insert = *position; + cally_text->priv->length_insert = g_utf8_strlen (new_text, new_text_length); + } + + /* + * The signal will be emitted when the cursor position is updated, + * or in an idle handler if it not updated. + */ + if (cally_text->priv->insert_idle_handler == 0) + cally_text->priv->insert_idle_handler = clutter_threads_add_idle (_idle_notify_insert, + cally_text); +} + +/***** atkeditabletext.h ******/ + +static void +cally_text_editable_text_interface_init (AtkEditableTextIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->set_text_contents = cally_text_set_text_contents; + iface->insert_text = cally_text_insert_text; + iface->delete_text = cally_text_delete_text; + + iface->set_run_attributes = NULL; + iface->copy_text = NULL; + iface->cut_text = NULL; + iface->paste_text = NULL; +} + +static void +cally_text_set_text_contents (AtkEditableText *text, + const gchar *string) +{ + ClutterActor *actor = NULL; + + actor = CALLY_GET_CLUTTER_ACTOR (text); + if (actor == NULL) + return; + + if (!clutter_text_get_editable (CLUTTER_TEXT (actor))) + return; + + clutter_text_set_text (CLUTTER_TEXT (actor), + string); +} + + +static void +cally_text_insert_text (AtkEditableText *text, + const gchar *string, + gint length, + gint *position) +{ + ClutterActor *actor = NULL; + + actor = CALLY_GET_CLUTTER_ACTOR (text); + if (actor == NULL) + return; + + if (!clutter_text_get_editable (CLUTTER_TEXT (actor))) + return; + + if (length < 0) + length = g_utf8_strlen (string, -1); + + clutter_text_insert_text (CLUTTER_TEXT (actor), + string, *position); + + /* we suppose that the text insertion will be succesful, + clutter-text doesn't warn about it. A option would be search for + the text, but it seems not really required */ + *position += length; +} + +static void cally_text_delete_text (AtkEditableText *text, + gint start_pos, + gint end_pos) +{ + ClutterActor *actor = NULL; + + actor = CALLY_GET_CLUTTER_ACTOR (text); + if (actor == NULL) + return; + + if (!clutter_text_get_editable (CLUTTER_TEXT (actor))) + return; + + clutter_text_delete_text (CLUTTER_TEXT (actor), + start_pos, end_pos); +} + +/* CallyActor */ +static void +cally_text_notify_clutter (GObject *obj, + GParamSpec *pspec) +{ + ClutterText *clutter_text = NULL; + CallyText *cally_text = NULL; + AtkObject *atk_obj = NULL; + + clutter_text = CLUTTER_TEXT (obj); + atk_obj = clutter_actor_get_accessible (CLUTTER_ACTOR (obj)); + cally_text = CALLY_TEXT (atk_obj); + + if (g_strcmp0 (pspec->name, "position") == 0) + { + /* the selection can change also for the cursor position */ + if (_check_for_selection_change (cally_text, clutter_text)) + g_signal_emit_by_name (atk_obj, "text_selection_changed"); + + g_signal_emit_by_name (atk_obj, "text_caret_moved", + clutter_text_get_cursor_position (clutter_text)); + } + else if (g_strcmp0 (pspec->name, "selection-bound") == 0) + { + if (_check_for_selection_change (cally_text, clutter_text)) + g_signal_emit_by_name (atk_obj, "text_selection_changed"); + } + else if (g_strcmp0 (pspec->name, "editable") == 0) + { + atk_object_notify_state_change (atk_obj, ATK_STATE_EDITABLE, + clutter_text_get_editable (clutter_text)); + } + else if (g_strcmp0 (pspec->name, "activatable") == 0) + { + _check_activate_action (cally_text, clutter_text); + } + else if (g_strcmp0 (pspec->name, "password-char") == 0) + { + if (clutter_text_get_password_char (clutter_text) != 0) + atk_object_set_role (atk_obj, ATK_ROLE_PASSWORD_TEXT); + else + atk_object_set_role (atk_obj, ATK_ROLE_TEXT); + } + else + { + CALLY_ACTOR_CLASS (cally_text_parent_class)->notify_clutter (obj, pspec); + } +} + +static gboolean +_check_for_selection_change (CallyText *cally_text, + ClutterText *clutter_text) +{ + gboolean ret_val = FALSE; + gint clutter_pos = -1; + gint clutter_bound = -1; + + clutter_pos = clutter_text_get_cursor_position (clutter_text); + clutter_bound = clutter_text_get_selection_bound (clutter_text); + + if (clutter_pos != clutter_bound) + { + if (clutter_pos != cally_text->priv->cursor_position || + clutter_bound != cally_text->priv->selection_bound) + /* + * This check is here as this function can be called for + * notification of selection_bound and current_pos. The + * values of current_pos and selection_bound may be the same + * for both notifications and we only want to generate one + * text_selection_changed signal. + */ + ret_val = TRUE; + } + else + { + /* We had a selection */ + ret_val = (cally_text->priv->cursor_position != cally_text->priv->selection_bound); + } + + cally_text->priv->cursor_position = clutter_pos; + cally_text->priv->selection_bound = clutter_bound; + + return ret_val; +} + +static gboolean +_idle_notify_insert (gpointer data) +{ + CallyText *cally_text = NULL; + + cally_text = CALLY_TEXT (data); + cally_text->priv->insert_idle_handler = 0; + + _notify_insert (cally_text); + + return FALSE; +} + +static void +_notify_insert (CallyText *cally_text) +{ + if (cally_text->priv->signal_name_insert) + { + g_signal_emit_by_name (cally_text, + cally_text->priv->signal_name_insert, + cally_text->priv->position_insert, + cally_text->priv->length_insert); + cally_text->priv->signal_name_insert = NULL; + } +} + +static void +_notify_delete (CallyText *cally_text) +{ + if (cally_text->priv->signal_name_delete) + { + g_signal_emit_by_name (cally_text, + cally_text->priv->signal_name_delete, + cally_text->priv->position_delete, + cally_text->priv->length_delete); + cally_text->priv->signal_name_delete = NULL; + } +} +/* atkaction */ + +static void +_cally_text_activate_action (CallyActor *cally_actor) +{ + ClutterActor *actor = NULL; + + actor = CALLY_GET_CLUTTER_ACTOR (cally_actor); + + clutter_text_activate (CLUTTER_TEXT (actor)); +} + +static void +_check_activate_action (CallyText *cally_text, + ClutterText *clutter_text) +{ + + if (clutter_text_get_activatable (clutter_text)) + { + if (cally_text->priv->activate_action_id != 0) + return; + + cally_text->priv->activate_action_id = cally_actor_add_action (CALLY_ACTOR (cally_text), + "activate", NULL, NULL, + _cally_text_activate_action); + } + else + { + if (cally_text->priv->activate_action_id == 0) + return; + + if (cally_actor_remove_action (CALLY_ACTOR (cally_text), + cally_text->priv->activate_action_id)) + { + cally_text->priv->activate_action_id = 0; + } + } +} + +/* GailTextUtil/GailMisc reimplementation methods */ + +/** + * _cally_misc_add_attribute: + * + * Reimplementation of gail_misc_layout_get_run_attributes (check this + * function for more documentation). + * + * Returns: A pointer to the new #AtkAttributeSet. + **/ +static AtkAttributeSet* +_cally_misc_add_attribute (AtkAttributeSet *attrib_set, + AtkTextAttribute attr, + gchar *value) +{ + AtkAttributeSet *return_set; + AtkAttribute *at = g_malloc (sizeof (AtkAttribute)); + at->name = g_strdup (atk_text_attribute_get_name (attr)); + at->value = value; + return_set = g_slist_prepend(attrib_set, at); + return return_set; +} + + +static gint +_cally_atk_attribute_lookup_func (gconstpointer data, + gconstpointer user_data) +{ + AtkTextAttribute attr = (AtkTextAttribute) user_data; + AtkAttribute *at = (AtkAttribute *) data; + if (!g_strcmp0 (at->name, atk_text_attribute_get_name (attr))) + return 0; + return -1; +} + +static gboolean +_cally_misc_find_atk_attribute (AtkAttributeSet *attrib_set, + AtkTextAttribute attr) +{ + GSList* result = g_slist_find_custom ((GSList*) attrib_set, + (gconstpointer) attr, + _cally_atk_attribute_lookup_func); + return (result != NULL); +} + +/** + * _cally_misc_layout_atk_attributes_from_pango: + * + * Store the pango attributes as their ATK equivalent in an existing + * #AtkAttributeSet. + * + * Returns: A pointer to the updated #AtkAttributeSet. + **/ +static AtkAttributeSet* +_cally_misc_layout_atk_attributes_from_pango (AtkAttributeSet *attrib_set, + PangoAttrIterator *iter) +{ + PangoAttrString *pango_string; + PangoAttrInt *pango_int; + PangoAttrColor *pango_color; + PangoAttrLanguage *pango_lang; + PangoAttrFloat *pango_float; + gchar *value = NULL; + + if ((pango_string = (PangoAttrString*) pango_attr_iterator_get (iter, + PANGO_ATTR_FAMILY)) != NULL) + { + value = g_strdup_printf("%s", pango_string->value); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_FAMILY_NAME, + value); + } + if ((pango_int = (PangoAttrInt*) pango_attr_iterator_get (iter, + PANGO_ATTR_STYLE)) != NULL) + { + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_STYLE, + g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_STYLE, pango_int->value))); + } + if ((pango_int = (PangoAttrInt*) pango_attr_iterator_get (iter, + PANGO_ATTR_WEIGHT)) != NULL) + { + value = g_strdup_printf("%i", pango_int->value); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_WEIGHT, + value); + } + if ((pango_int = (PangoAttrInt*) pango_attr_iterator_get (iter, + PANGO_ATTR_VARIANT)) != NULL) + { + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_VARIANT, + g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_VARIANT, pango_int->value))); + } + if ((pango_int = (PangoAttrInt*) pango_attr_iterator_get (iter, + PANGO_ATTR_STRETCH)) != NULL) + { + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_STRETCH, + g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_STRETCH, pango_int->value))); + } + if ((pango_int = (PangoAttrInt*) pango_attr_iterator_get (iter, + PANGO_ATTR_SIZE)) != NULL) + { + value = g_strdup_printf("%i", pango_int->value / PANGO_SCALE); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_SIZE, + value); + } + if ((pango_int = (PangoAttrInt*) pango_attr_iterator_get (iter, + PANGO_ATTR_UNDERLINE)) != NULL) + { + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_UNDERLINE, + g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_UNDERLINE, pango_int->value))); + } + if ((pango_int = (PangoAttrInt*) pango_attr_iterator_get (iter, + PANGO_ATTR_STRIKETHROUGH)) != NULL) + { + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_STRIKETHROUGH, + g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_STRIKETHROUGH, pango_int->value))); + } + if ((pango_int = (PangoAttrInt*) pango_attr_iterator_get (iter, + PANGO_ATTR_RISE)) != NULL) + { + value = g_strdup_printf("%i", pango_int->value); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_RISE, + value); + } + if ((pango_lang = (PangoAttrLanguage*) pango_attr_iterator_get (iter, + PANGO_ATTR_LANGUAGE)) != NULL) + { + value = g_strdup( pango_language_to_string( pango_lang->value)); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_LANGUAGE, + value); + } + if ((pango_float = (PangoAttrFloat*) pango_attr_iterator_get (iter, + PANGO_ATTR_SCALE)) != NULL) + { + value = g_strdup_printf("%g", pango_float->value); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_SCALE, + value); + } + if ((pango_color = (PangoAttrColor*) pango_attr_iterator_get (iter, + PANGO_ATTR_FOREGROUND)) != NULL) + { + value = g_strdup_printf ("%u,%u,%u", + pango_color->color.red, + pango_color->color.green, + pango_color->color.blue); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_FG_COLOR, + value); + } + if ((pango_color = (PangoAttrColor*) pango_attr_iterator_get (iter, + PANGO_ATTR_BACKGROUND)) != NULL) + { + value = g_strdup_printf ("%u,%u,%u", + pango_color->color.red, + pango_color->color.green, + pango_color->color.blue); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_BG_COLOR, + value); + } + + return attrib_set; +} + +static AtkAttributeSet* +_cally_misc_add_actor_color_to_attribute_set (AtkAttributeSet *attrib_set, + ClutterText *clutter_text) +{ + ClutterColor color; + gchar *value; + + clutter_text_get_color (clutter_text, &color); + value = g_strdup_printf ("%u,%u,%u", + (guint) (color.red * 65535 / 255), + (guint) (color.green * 65535 / 255), + (guint) (color.blue * 65535 / 255)); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_FG_COLOR, + value); + return attrib_set; +} + + +/** + * _cally_misc_layout_get_run_attributes: + * + * Reimplementation of gail_misc_layout_get_run_attributes (check this + * function for more documentation). + * + * Returns: A pointer to the #AtkAttributeSet. + **/ +static AtkAttributeSet* +_cally_misc_layout_get_run_attributes (AtkAttributeSet *attrib_set, + ClutterText *clutter_text, + gint offset, + gint *start_offset, + gint *end_offset) +{ + PangoAttrIterator *iter; + PangoAttrList *attr; + gint index, start_index, end_index; + gboolean is_next = TRUE; + glong len; + PangoLayout *layout = clutter_text_get_layout (clutter_text); + gchar *text = (gchar*) clutter_text_get_text (clutter_text); + + len = g_utf8_strlen (text, -1); + /* Grab the attributes of the PangoLayout, if any */ + if ((attr = pango_layout_get_attributes (layout)) == NULL) + { + *start_offset = 0; + *end_offset = len; + _cally_misc_add_actor_color_to_attribute_set (attrib_set, clutter_text); + } + else + { + iter = pango_attr_list_get_iterator (attr); + /* Get invariant range offsets */ + /* If offset out of range, set offset in range */ + if (offset > len) + offset = len; + else if (offset < 0) + offset = 0; + + index = g_utf8_offset_to_pointer (text, offset) - text; + pango_attr_iterator_range (iter, &start_index, &end_index); + while (is_next) + { + if (index >= start_index && index < end_index) + { + *start_offset = g_utf8_pointer_to_offset (text, + text + start_index); + if (end_index == G_MAXINT) + /* Last iterator */ + end_index = len; + + *end_offset = g_utf8_pointer_to_offset (text, + text + end_index); + break; + } + is_next = pango_attr_iterator_next (iter); + pango_attr_iterator_range (iter, &start_index, &end_index); + } + + /* Get attributes */ + attrib_set = _cally_misc_layout_atk_attributes_from_pango (attrib_set, iter); + pango_attr_iterator_destroy (iter); + } + + if (!_cally_misc_find_atk_attribute (attrib_set, ATK_TEXT_ATTR_FG_COLOR)) + attrib_set = _cally_misc_add_actor_color_to_attribute_set (attrib_set, clutter_text); + + return attrib_set; +} + + +/** + * _cally_misc_layout_get_default_attributes: + * + * Reimplementation of gail_misc_layout_get_default_attributes (check this + * function for more documentation). + * + * Returns: A pointer to the #AtkAttributeSet. + **/ +static AtkAttributeSet* +_cally_misc_layout_get_default_attributes (AtkAttributeSet *attrib_set, + ClutterText *clutter_text) +{ + PangoLayout *layout; + PangoContext *context; + PangoLanguage* language; + PangoFontDescription* font; + PangoWrapMode mode; + gchar *value = NULL; + gint int_value; + ClutterTextDirection text_direction; + PangoAttrIterator *iter; + PangoAttrList *attr; + + text_direction = clutter_actor_get_text_direction (CLUTTER_ACTOR (clutter_text)); + switch (text_direction) + { + case CLUTTER_TEXT_DIRECTION_DEFAULT: + value = g_strdup ("none"); + break; + + case CLUTTER_TEXT_DIRECTION_LTR: + value = g_strdup ("ltr"); + break; + + case CLUTTER_TEXT_DIRECTION_RTL: + value = g_strdup ("rtl"); + break; + + default: + value = g_strdup ("none"); + break; + } + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_DIRECTION, + value); + + layout = clutter_text_get_layout (clutter_text); + context = pango_layout_get_context (layout); + if (context) + { + if ((language = pango_context_get_language (context))) + { + value = g_strdup (pango_language_to_string (language)); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_LANGUAGE, value); + } + + if ((font = pango_context_get_font_description (context))) + { + value = g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_STYLE, + pango_font_description_get_style (font))); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_STYLE, + value); + + value = g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_VARIANT, + pango_font_description_get_variant (font))); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_VARIANT, value); + + value = g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_STRETCH, + pango_font_description_get_stretch (font))); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_STRETCH, value); + + value = g_strdup (pango_font_description_get_family (font)); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_FAMILY_NAME, value); + value = g_strdup_printf ("%d", pango_font_description_get_weight (font)); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_WEIGHT, value); + + value = g_strdup_printf ("%i", pango_font_description_get_size (font) / PANGO_SCALE); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_SIZE, value); + + } + + } + + if (pango_layout_get_justify (layout)) + int_value = 3; + else + { + PangoAlignment align; + + align = pango_layout_get_alignment (layout); + if (align == PANGO_ALIGN_LEFT) + int_value = 0; + else if (align == PANGO_ALIGN_CENTER) + int_value = 2; + else /* if (align == PANGO_ALIGN_RIGHT) */ + int_value = 1; + } + value = g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_JUSTIFICATION, + int_value)); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_JUSTIFICATION, + value); + + mode = pango_layout_get_wrap (layout); + if (mode == PANGO_WRAP_WORD) + int_value = 2; + else /* if (mode == PANGO_WRAP_CHAR) */ + int_value = 1; + value = g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_WRAP_MODE, + int_value)); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_WRAP_MODE, value); + + if ((attr = clutter_text_get_attributes (clutter_text))) + { + iter = pango_attr_list_get_iterator (attr); + /* Get attributes */ + attrib_set = _cally_misc_layout_atk_attributes_from_pango (attrib_set, iter); + pango_attr_iterator_destroy (iter); + } + + + if (!_cally_misc_find_atk_attribute (attrib_set, ATK_TEXT_ATTR_FG_COLOR)) + attrib_set = _cally_misc_add_actor_color_to_attribute_set (attrib_set, + clutter_text); + + value = g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_FG_STIPPLE, 0)); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_FG_STIPPLE, + value); + + value = g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_BG_STIPPLE, 0)); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_BG_STIPPLE, + value); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_BG_FULL_HEIGHT, + g_strdup_printf ("%i", 0)); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_PIXELS_INSIDE_WRAP, + g_strdup_printf ("%i", 0)); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_PIXELS_BELOW_LINES, + g_strdup_printf ("%i", 0)); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_PIXELS_ABOVE_LINES, + g_strdup_printf ("%i", 0)); + value = g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_EDITABLE, + clutter_text_get_editable (clutter_text))); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_EDITABLE, + value); + + value = g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_INVISIBLE, + !clutter_actor_is_visible (CLUTTER_ACTOR (clutter_text)))); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_INVISIBLE, value); + + value = g_strdup_printf ("%i", pango_layout_get_indent (layout)); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_INDENT, value); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_RIGHT_MARGIN, + g_strdup_printf ("%i", 0)); + attrib_set = _cally_misc_add_attribute (attrib_set, + ATK_TEXT_ATTR_LEFT_MARGIN, + g_strdup_printf ("%i", 0)); + + return attrib_set; +} + +static int +_cally_misc_get_index_at_point (ClutterText *clutter_text, + gint x, + gint y, + AtkCoordType coords) +{ + gint index, x_window, y_window, x_toplevel, y_toplevel; + gint x_temp, y_temp; + gboolean ret; + ClutterVertex verts[4]; + PangoLayout *layout; + gint x_layout, y_layout; + + clutter_text_get_layout_offsets (clutter_text, &x_layout, &y_layout); + + clutter_actor_get_abs_allocation_vertices (CLUTTER_ACTOR (clutter_text), verts); + x_window = verts[0].x; + y_window = verts[0].y; + + x_temp = x - x_layout - x_window; + y_temp = y - y_layout - y_window; + + if (coords == ATK_XY_SCREEN) + { + _cally_actor_get_top_level_origin (CLUTTER_ACTOR (clutter_text), &x_toplevel, + &y_toplevel); + x_temp -= x_toplevel; + y_temp -= y_toplevel; + } + + layout = clutter_text_get_layout (clutter_text); + ret = pango_layout_xy_to_index (layout, + x_temp * PANGO_SCALE, + y_temp * PANGO_SCALE, + &index, NULL); + + if (!ret) + { + if (x_temp < 0 || y_temp < 0) + index = 0; + else + index = -1; + } + return index; +} diff --git a/clutter/clutter/cally/cally-text.h b/clutter/clutter/cally/cally-text.h new file mode 100644 index 0000000..ce3c0cb --- /dev/null +++ b/clutter/clutter/cally/cally-text.h @@ -0,0 +1,84 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2009 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * 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 . + */ + +#ifndef __CALLY_TEXT_H__ +#define __CALLY_TEXT_H__ + +#if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CALLY_TYPE_TEXT (cally_text_get_type ()) +#define CALLY_TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CALLY_TYPE_TEXT, CallyText)) +#define CALLY_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CALLY_TYPE_TEXT, CallyTextClass)) +#define CALLY_IS_TEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CALLY_TYPE_TEXT)) +#define CALLY_IS_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CALLY_TYPE_TEXT)) +#define CALLY_TEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CALLY_TYPE_TEXT, CallyTextClass)) + +typedef struct _CallyText CallyText; +typedef struct _CallyTextClass CallyTextClass; +typedef struct _CallyTextPrivate CallyTextPrivate; + +/** + * CallyText: + * + * The CallyText structure contains only private + * data and should be accessed using the provided API + * + * Since: 1.4 + */ +struct _CallyText +{ + /*< private >*/ + CallyActor parent; + + CallyTextPrivate *priv; +}; + +/** + * CallyTextClass: + * + * The CallyTextClass structure contains only + * private data + * + * Since: 1.4 + */ +struct _CallyTextClass +{ + /*< private >*/ + CallyActorClass parent_class; + + /* padding for future expansion */ + gpointer _padding_dummy[8]; +}; + +CLUTTER_AVAILABLE_IN_1_4 +GType cally_text_get_type (void) G_GNUC_CONST; +CLUTTER_AVAILABLE_IN_1_4 +AtkObject* cally_text_new (ClutterActor *actor); + +G_END_DECLS + +#endif /* __CALLY_TEXT_H__ */ diff --git a/clutter/clutter/cally/cally-texture.c b/clutter/clutter/cally/cally-texture.c new file mode 100644 index 0000000..e7df619 --- /dev/null +++ b/clutter/clutter/cally/cally-texture.c @@ -0,0 +1,98 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2009 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * 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. + */ + +/** + * SECTION:cally-texture + * @Title: CallyTexture + * @short_description: Implementation of the ATK interfaces for a #ClutterTexture + * @see_also: #ClutterTexture + * + * #CallyTexture implements the required ATK interfaces of #ClutterTexture + * + * In particular it sets a proper role for the texture. + */ +#include "clutter-build-config.h" + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS + +#include "cally-texture.h" +#include "cally-actor-private.h" + +#include "deprecated/clutter-texture.h" + +/* AtkObject */ +static void cally_texture_real_initialize (AtkObject *obj, + gpointer data); + +G_DEFINE_TYPE (CallyTexture, cally_texture, CALLY_TYPE_ACTOR) + +static void +cally_texture_class_init (CallyTextureClass *klass) +{ +/* GObjectClass *gobject_class = G_OBJECT_CLASS (klass); */ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + + class->initialize = cally_texture_real_initialize; +} + +static void +cally_texture_init (CallyTexture *texture) +{ + /* nothing to do yet */ +} + +/** + * cally_texture_new: + * @actor: a #ClutterActor + * + * Creates a new #CallyTexture for the given @actor. @actor must be + * a #ClutterTexture. + * + * Return value: the newly created #AtkObject + * + * Since: 1.4 + */ +AtkObject* +cally_texture_new (ClutterActor *actor) +{ + GObject *object = NULL; + AtkObject *accessible = NULL; + + g_return_val_if_fail (CLUTTER_IS_TEXTURE (actor), NULL); + + object = g_object_new (CALLY_TYPE_TEXTURE, NULL); + + accessible = ATK_OBJECT (object); + atk_object_initialize (accessible, actor); + + return accessible; +} + +static void +cally_texture_real_initialize (AtkObject *obj, + gpointer data) +{ + ATK_OBJECT_CLASS (cally_texture_parent_class)->initialize (obj, data); + + /* default role */ + obj->role = ATK_ROLE_IMAGE; +} diff --git a/clutter/clutter/cally/cally-texture.h b/clutter/clutter/cally/cally-texture.h new file mode 100644 index 0000000..dad576c --- /dev/null +++ b/clutter/clutter/cally/cally-texture.h @@ -0,0 +1,84 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2009 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * 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 . + */ + +#ifndef __CALLY_TEXTURE_H__ +#define __CALLY_TEXTURE_H__ + +#if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CALLY_TYPE_TEXTURE (cally_texture_get_type ()) +#define CALLY_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CALLY_TYPE_TEXTURE, CallyTexture)) +#define CALLY_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CALLY_TYPE_TEXTURE, CallyTextureClass)) +#define CALLY_IS_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CALLY_TYPE_TEXTURE)) +#define CALLY_IS_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CALLY_TYPE_TEXTURE)) +#define CALLY_TEXTURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CALLY_TYPE_TEXTURE, CallyTextureClass)) + +typedef struct _CallyTexture CallyTexture; +typedef struct _CallyTextureClass CallyTextureClass; +typedef struct _CallyTexturePrivate CallyTexturePrivate; + +/** + * CallyTexture: + * + * The CallyTexture structure contains only + * private data and should be accessed using the provided API + * + * Since: 1.4 + */ +struct _CallyTexture +{ + /*< private >*/ + CallyActor parent; + + CallyTexturePrivate *priv; +}; + +/** + * CallyTextureClass: + * + * The CallyTextureClass structure contains + * only private data + * + * Since: 1.4 + */ +struct _CallyTextureClass +{ + /*< private >*/ + CallyActorClass parent_class; + + /* padding for future expansion */ + gpointer _padding_dummy[8]; +}; + +CLUTTER_AVAILABLE_IN_1_4 +GType cally_texture_get_type (void) G_GNUC_CONST; +CLUTTER_AVAILABLE_IN_1_4 +AtkObject *cally_texture_new (ClutterActor *actor); + +G_END_DECLS + +#endif /* __CALLY_TEXTURE_H__ */ diff --git a/clutter/clutter/cally/cally-util.c b/clutter/clutter/cally/cally-util.c new file mode 100644 index 0000000..8ffd207 --- /dev/null +++ b/clutter/clutter/cally/cally-util.c @@ -0,0 +1,452 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2008 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * Based on GailUtil from GAIL + * Copyright 2001, 2002, 2003 Sun Microsystems Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:cally-util + * @Title: CallyUtil + * @short_description: #AtkUtil implementation + * @see_also: #ClutterActor + * + * #CallyUtil implements #AtkUtil abstract methods. Although it + * includes the name "Util" it is in fact one of the most important + * interfaces to be implemented in any ATK toolkit implementation. + + * For instance, it defines atk_get_root(), the method that returns + * the root object in the hierarchy. Without it, you don't have + * available any accessible object. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include +#include +#include + +#include "cally-util.h" +#include "cally-root.h" +#include "cally-stage.h" + +#define DEFAULT_PASSWORD_CHAR '*' + +/* atkutil.h */ + +static guint cally_util_add_key_event_listener (AtkKeySnoopFunc listener, + gpointer data); +static void cally_util_remove_key_event_listener (guint remove_listener); +static AtkObject* cally_util_get_root (void); +static const gchar * cally_util_get_toolkit_name (void); +static const gchar * cally_util_get_toolkit_version (void); + +/* private */ +static void cally_util_simulate_snooper_install (void); +static void cally_util_simulate_snooper_remove (void); +static gboolean cally_key_snooper (ClutterActor *actor, + ClutterEvent *event, + gpointer user_data); +static void cally_util_stage_added_cb (ClutterStageManager *stage_manager, + ClutterStage *stage, + gpointer data); +static void cally_util_stage_removed_cb (ClutterStageManager *stage_manager, + ClutterStage *stage, + gpointer data); +static gboolean notify_hf (gpointer key, + gpointer value, + gpointer data); +static void insert_hf (gpointer key, + gpointer value, + gpointer data); + +/* This is just a copy of the Gail one, a shared library or place to + define it could be a good idea. */ +typedef struct _CallyKeyEventInfo CallyKeyEventInfo; + +struct _CallyKeyEventInfo +{ + AtkKeySnoopFunc listener; + gpointer func_data; +}; + +static AtkObject* root = NULL; +static GHashTable *key_listener_list = NULL; + + +G_DEFINE_TYPE (CallyUtil, cally_util, ATK_TYPE_UTIL); + +static void +cally_util_class_init (CallyUtilClass *klass) +{ + AtkUtilClass *atk_class; + gpointer data; + + data = g_type_class_peek (ATK_TYPE_UTIL); + atk_class = ATK_UTIL_CLASS (data); + + atk_class->add_key_event_listener = cally_util_add_key_event_listener; + atk_class->remove_key_event_listener = cally_util_remove_key_event_listener; + atk_class->get_root = cally_util_get_root; + atk_class->get_toolkit_name = cally_util_get_toolkit_name; + atk_class->get_toolkit_version = cally_util_get_toolkit_version; + + /* FIXME: Instead of create this on the class, I think that would + worth to implement CallyUtil as a singleton instance, so the + class methods will access this instance. This will be a good + future enhancement, meanwhile, just using the same *working* + implementation used on GailUtil */ +} + +static void +cally_util_init (CallyUtil *cally_util) +{ + /* instance init: usually not required */ +} + +/* ------------------------------ ATK UTIL METHODS -------------------------- */ + +static AtkObject* +cally_util_get_root (void) +{ + if (!root) + root = cally_root_new (); + + return root; +} + +static const gchar * +cally_util_get_toolkit_name (void) +{ + return "clutter"; +} + +static const gchar * +cally_util_get_toolkit_version (void) +{ + return CLUTTER_VERSION_S; +} + +static guint +cally_util_add_key_event_listener (AtkKeySnoopFunc listener, + gpointer data) +{ + static guint key = 1; + CallyKeyEventInfo *event_info = NULL; + + if (!key_listener_list) + { + key_listener_list = g_hash_table_new_full (NULL, NULL, NULL, g_free); + + cally_util_simulate_snooper_install (); + } + + event_info = g_new (CallyKeyEventInfo, 1); + event_info->listener = listener; + event_info->func_data = data; + + g_hash_table_insert (key_listener_list, GUINT_TO_POINTER (key++), event_info); + /* XXX: we don't check to see if n_listeners > MAXUINT */ + return key - 1; +} + +static void +cally_util_remove_key_event_listener (guint remove_listener) +{ + if (!g_hash_table_remove (key_listener_list, GUINT_TO_POINTER (remove_listener))) { + g_warning ("Not able to remove listener with id %i", remove_listener); + } + + if (g_hash_table_size (key_listener_list) == 0) + { + g_hash_table_destroy (key_listener_list); + key_listener_list = NULL; + cally_util_simulate_snooper_remove (); + } +} + +/* ------------------------------ PRIVATE FUNCTIONS ------------------------- */ + +/* Trying to emulate gtk_key_snooper install (a kind of wrapper). This + could be implemented without it, but I will maintain it in this + way, so if in the future clutter implements it natively it would be + easier the transition */ +static void +cally_util_simulate_snooper_install (void) +{ + ClutterStageManager *stage_manager = NULL; + ClutterStage *stage = NULL; + GSList *stage_list = NULL; + GSList *iter = NULL; + + stage_manager = clutter_stage_manager_get_default (); + stage_list = clutter_stage_manager_list_stages (stage_manager); + + for (iter = stage_list; iter != NULL; iter = g_slist_next (iter)) + { + stage = CLUTTER_STAGE (iter->data); + + g_signal_connect (G_OBJECT (stage), "captured-event", + G_CALLBACK (cally_key_snooper), NULL); + } + + g_signal_connect (G_OBJECT (stage_manager), "stage-added", + G_CALLBACK (cally_util_stage_added_cb), cally_key_snooper); + g_signal_connect (G_OBJECT (stage_manager), "stage-removed", + G_CALLBACK (cally_util_stage_removed_cb), cally_key_snooper); +} + +static void +cally_util_simulate_snooper_remove (void) +{ + ClutterStageManager *stage_manager = NULL; + ClutterStage *stage = NULL; + GSList *stage_list = NULL; + GSList *iter = NULL; + gint num = 0; + + stage_manager = clutter_stage_manager_get_default (); + stage_list = clutter_stage_manager_list_stages (stage_manager); + + for (iter = stage_list; iter != NULL; iter = g_slist_next (iter)) + { + stage = CLUTTER_STAGE (iter->data); + + num += g_signal_handlers_disconnect_by_func (stage, cally_key_snooper, NULL); + } + + g_signal_handlers_disconnect_by_func (G_OBJECT (stage_manager), + G_CALLBACK (cally_util_stage_added_cb), + cally_key_snooper); + + g_signal_handlers_disconnect_by_func (G_OBJECT (stage_manager), + G_CALLBACK (cally_util_stage_removed_cb), + cally_key_snooper); + +#ifdef CALLY_DEBUG + g_print ("Number of snooper callbacks disconnected: %i\n", num); +#endif +} + +static AtkKeyEventStruct * +atk_key_event_from_clutter_event_key (ClutterKeyEvent *clutter_event, + gunichar password_char) +{ + AtkKeyEventStruct *atk_event = g_new0 (AtkKeyEventStruct, 1); + gunichar key_unichar; + + switch (clutter_event->type) + { + case CLUTTER_KEY_PRESS: + atk_event->type = ATK_KEY_EVENT_PRESS; + break; + case CLUTTER_KEY_RELEASE: + atk_event->type = ATK_KEY_EVENT_RELEASE; + break; + default: + g_assert_not_reached (); + return NULL; + } + + if (password_char) + atk_event->state = 0; + else + atk_event->state = clutter_event->modifier_state; + + /* We emit the clutter keyval. This is not exactly the one expected + by AtkKeyEventStruct, as it expects a Gdk-like event, with the + modifiers applied. But to avoid a dependency to gdk, we delegate + that on the AT application. + More information: Bug 1952 and bug 2072 + */ + if (password_char) + atk_event->keyval = clutter_unicode_to_keysym (password_char); + else + atk_event->keyval = clutter_event->keyval; + + /* It is expected to store a key defining string here (ie "Space" in + case you press a space). Anyway, there are no function on clutter + to obtain that, and we want to avoid a gdk dependency here, so we + delegate on the AT application to obtain that string using the + rest of the data on the ATK event struct. + + More information: Bug 1952 and 2072 + */ + + if (password_char) + key_unichar = password_char; + else + key_unichar = clutter_event_get_key_unicode ((ClutterEvent *) clutter_event); + + if (g_unichar_validate (key_unichar) && !g_unichar_iscntrl (key_unichar)) + { + GString *new = NULL; + + new = g_string_new (""); + new = g_string_insert_unichar (new, 0, key_unichar); + atk_event->string = new->str; + g_string_free (new, FALSE); + } + else + atk_event->string = NULL; + + atk_event->length = 0; + + /* Computing the hardware keycode from the password-char is + difficult. But we are in a password situation. We are already a + unichar that it is not the original one. Providing a "almost + real" keycode is irrelevant */ + if (password_char) + atk_event->keycode = 0; + else + atk_event->keycode = clutter_event->hardware_keycode; + + atk_event->timestamp = clutter_event->time; + +#ifdef CALLY_DEBUG + + g_debug ("CallyKeyEvent:\tsym 0x%x\n\t\tmods %x\n\t\tcode %u\n\t\ttime %lx \n\t\tstring %s\n", + (unsigned int) atk_event->keyval, + (unsigned int) atk_event->state, + (unsigned int) atk_event->keycode, + (unsigned long int) atk_event->timestamp, + atk_event->string); +#endif + + return atk_event; +} + + +static gboolean +notify_hf (gpointer key, gpointer value, gpointer data) +{ + CallyKeyEventInfo *info = (CallyKeyEventInfo *) value; + AtkKeyEventStruct *key_event = (AtkKeyEventStruct *)data; + + return (*(AtkKeySnoopFunc) info->listener) (key_event, info->func_data) ? TRUE : FALSE; +} + +static void +insert_hf (gpointer key, gpointer value, gpointer data) +{ + GHashTable *new_table = (GHashTable *) data; + g_hash_table_insert (new_table, key, value); +} + + +/* + * 0 if the key of that event is visible, in other case the password + * char + */ +static gunichar +check_key_visibility (ClutterEvent *event) +{ + ClutterKeyEvent *key_event = (ClutterKeyEvent *)event; + AtkObject *accessible = clutter_actor_get_accessible (key_event->source); + + g_return_val_if_fail (accessible != NULL, 0); + + if (atk_object_get_role (accessible) != ATK_ROLE_PASSWORD_TEXT) + return 0; + + /* If it is a clutter text, we use his password char. Note that + although at Clutter toolkit itself, only ClutterText exposes a + password role, nothing prevents on any derived toolkit (like st) + to create a new actor that can behave like a password entry. And + the key event will still be emitted here. Although in that case + we would lose any password char from the derived toolkit, it is + still better fill this with a default unichar that the original + one */ + + if (CLUTTER_IS_TEXT (key_event->source)) + return clutter_text_get_password_char (CLUTTER_TEXT (key_event->source)); + else + return DEFAULT_PASSWORD_CHAR; +} + +static gboolean +cally_key_snooper (ClutterActor *actor, + ClutterEvent *event, + gpointer user_data) +{ + AtkKeyEventStruct *key_event = NULL; + gint consumed = 0; + gunichar password_char = 0; + + /* filter key events */ + if ((event->type != CLUTTER_KEY_PRESS) && (event->type != CLUTTER_KEY_RELEASE)) + { + return FALSE; + } + + password_char = check_key_visibility (event); + + if (key_listener_list) + { + GHashTable *new_hash = g_hash_table_new (NULL, NULL); + + g_hash_table_foreach (key_listener_list, insert_hf, new_hash); + key_event = atk_key_event_from_clutter_event_key ((ClutterKeyEvent *)event, + password_char); + /* func data is inside the hash table */ + consumed = g_hash_table_foreach_steal (new_hash, notify_hf, key_event); + g_hash_table_destroy (new_hash); + + g_free (key_event->string); + g_free (key_event); + } + + return (consumed ? 1 : 0); +} + +static void +cally_util_stage_added_cb (ClutterStageManager *stage_manager, + ClutterStage *stage, + gpointer data) +{ + GCallback cally_key_snooper_cb = G_CALLBACK (data); + + g_signal_connect (G_OBJECT (stage), "captured-event", cally_key_snooper_cb, NULL); +} + +static void +cally_util_stage_removed_cb (ClutterStageManager *stage_manager, + ClutterStage *stage, + gpointer data) +{ + GCallback cally_key_snooper_cb = G_CALLBACK (data); + + g_signal_handlers_disconnect_by_func (stage, cally_key_snooper_cb, NULL); +} + +void +_cally_util_override_atk_util (void) +{ + AtkUtilClass *atk_class = ATK_UTIL_CLASS (g_type_class_ref (ATK_TYPE_UTIL)); + + atk_class->add_key_event_listener = cally_util_add_key_event_listener; + atk_class->remove_key_event_listener = cally_util_remove_key_event_listener; + atk_class->get_root = cally_util_get_root; + atk_class->get_toolkit_name = cally_util_get_toolkit_name; + atk_class->get_toolkit_version = cally_util_get_toolkit_version; +} diff --git a/clutter/clutter/cally/cally-util.h b/clutter/clutter/cally/cally-util.h new file mode 100644 index 0000000..76f36be --- /dev/null +++ b/clutter/clutter/cally/cally-util.h @@ -0,0 +1,84 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2008 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * 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 . + */ + +#ifndef __CALLY_UTIL_H__ +#define __CALLY_UTIL_H__ + +#if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CALLY_TYPE_UTIL (cally_util_get_type ()) +#define CALLY_UTIL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CALLY_TYPE_UTIL, CallyUtil)) +#define CALLY_UTIL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CALLY_TYPE_UTIL, CallyUtilClass)) +#define CALLY_IS_UTIL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CALLY_TYPE_UTIL)) +#define CALLY_IS_UTIL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CALLY_TYPE_UTIL)) +#define CALLY_UTIL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CALLY_TYPE_UTIL, CallyUtilClass)) + +typedef struct _CallyUtil CallyUtil; +typedef struct _CallyUtilClass CallyUtilClass; +typedef struct _CallyUtilPrivate CallyUtilPrivate; + +/** + * CallyUtil: + * + * The CallyUtil structure contains only + * private data and should be accessed using the provided API + * + * Since: 1.4 + */ +struct _CallyUtil +{ + /*< private >*/ + AtkUtil parent; + + CallyUtilPrivate *priv; +}; + +/** + * CallyUtilClass: + * + * The CallyUtilClass structure contains only + * private data + * + * Since: 1.4 + */ +struct _CallyUtilClass +{ + /*< private >*/ + AtkUtilClass parent_class; + + /* padding for future expansion */ + gpointer _padding_dummy[8]; +}; + +CLUTTER_AVAILABLE_IN_1_4 +GType cally_util_get_type (void) G_GNUC_CONST; + +void _cally_util_override_atk_util (void); + +G_END_DECLS + +#endif /* __CALLY_UTIL_H__ */ diff --git a/clutter/clutter/cally/cally.c b/clutter/clutter/cally/cally.c new file mode 100644 index 0000000..8cee69a --- /dev/null +++ b/clutter/clutter/cally/cally.c @@ -0,0 +1,108 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2008 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * 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. + */ + +/** + * SECTION:cally + * @Title: Cally + * @short_description: Cally initialization methods. + * + * Cally initialization methods. + * + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS + +#include "cally.h" + +#include "cally-actor.h" +#include "cally-group.h" +#include "cally-stage.h" +#include "cally-text.h" +#include "cally-texture.h" +#include "cally-rectangle.h" +#include "cally-clone.h" + +#include "cally-factory.h" +#include "cally-util.h" + +#include "clutter.h" + +#include "clutter-debug.h" +#include "clutter-private.h" + +/* factories initialization*/ +CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_ACTOR, cally_actor, cally_actor_new) +CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_GROUP, cally_group, cally_group_new) +CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_STAGE, cally_stage, cally_stage_new) +CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_TEXT, cally_text, cally_text_new) +CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_TEXTURE, cally_texture, cally_texture_new) +CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_RECTANGLE, cally_rectangle, cally_rectangle_new) +CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_CLONE, cally_clone, cally_clone_new) + +/** + * cally_accessibility_init: + * + * Initializes the accessibility support. + * + * Return value: %TRUE if accessibility support has been correctly + * initialized. + * + * Since: 1.4 + */ +gboolean +cally_accessibility_init (void) +{ + /* setting the factories */ + CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_ACTOR, cally_actor); + CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_GROUP, cally_group); + CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_STAGE, cally_stage); + CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_TEXT, cally_text); + CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_TEXTURE, cally_texture); + CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_RECTANGLE, cally_rectangle); + CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_CLONE, cally_clone); + + /* Initialize the CallyUtility class */ + _cally_util_override_atk_util (); + + CLUTTER_NOTE (MISC, "Clutter Accessibility initialized"); + + return TRUE; +} + +/** + * cally_get_cally_initialized: + * + * Returns if the accessibility support using cally is enabled. + * + * Return value: %TRUE if accessibility support has been correctly + * initialized. + * + * Since: 1.4 + */ +gboolean cally_get_cally_initialized (void) +{ + return !g_strcmp0 (atk_get_toolkit_name (), "clutter"); +} diff --git a/clutter/clutter/cally/cally.h b/clutter/clutter/cally/cally.h new file mode 100644 index 0000000..11fa9fc --- /dev/null +++ b/clutter/clutter/cally/cally.h @@ -0,0 +1,40 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2008 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * 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 . + */ + +#ifndef __CALLY_H__ +#define __CALLY_H__ + +#define __CALLY_H_INSIDE__ + +#include "cally-actor.h" +#include "cally-clone.h" +#include "cally-factory.h" +#include "cally-group.h" +#include "cally-main.h" +#include "cally-rectangle.h" +#include "cally-root.h" +#include "cally-stage.h" +#include "cally-text.h" +#include "cally-texture.h" +#include "cally-util.h" + +#undef __CALLY_H_INSIDE__ + +#endif /* __CALLY_H__ */ diff --git a/clutter/clutter/clutter-action.c b/clutter/clutter/clutter-action.c new file mode 100644 index 0000000..020b37f --- /dev/null +++ b/clutter/clutter/clutter-action.c @@ -0,0 +1,63 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-action + * @Title: ClutterAction + * @Short_Description: Abstract class for event-related logic + * @See_Also: #ClutterConstraint + * + * #ClutterAction is an abstract base class for event-related actions that + * modify the user interaction of a #ClutterActor, just like + * #ClutterConstraint is an abstract class for modifiers of an actor's + * position or size. + * + * Implementations of #ClutterAction are associated to an actor and can + * provide behavioral changes when dealing with user input - for instance + * drag and drop capabilities, or scrolling, or panning - by using the + * various event-related signals provided by #ClutterActor itself. + * + * #ClutterAction is available since Clutter 1.4 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-action.h" + +#include "clutter-debug.h" +#include "clutter-private.h" + +G_DEFINE_ABSTRACT_TYPE (ClutterAction, clutter_action, CLUTTER_TYPE_ACTOR_META); + +static void +clutter_action_class_init (ClutterActionClass *klass) +{ +} + +static void +clutter_action_init (ClutterAction *self) +{ +} diff --git a/clutter/clutter/clutter-action.h b/clutter/clutter/clutter-action.h new file mode 100644 index 0000000..fe9f19f --- /dev/null +++ b/clutter/clutter/clutter-action.h @@ -0,0 +1,111 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_ACTION_H__ +#define __CLUTTER_ACTION_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_ACTION (clutter_action_get_type ()) +#define CLUTTER_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ACTION, ClutterAction)) +#define CLUTTER_IS_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ACTION)) +#define CLUTTER_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_ACTION, ClutterActionClass)) +#define CLUTTER_IS_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_ACTION)) +#define CLUTTER_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_ACTION, ClutterActionClass)) + +typedef struct _ClutterActionClass ClutterActionClass; + +/** + * ClutterAction: + * + * The #ClutterAction structure contains only private data and + * should be accessed using the provided API. + * + * Since: 1.4 + */ +struct _ClutterAction +{ + /*< private >*/ + ClutterActorMeta parent_instance; +}; + +/** + * ClutterActionClass: + * + * The ClutterActionClass structure contains only private data + * + * Since: 1.4 + */ +struct _ClutterActionClass +{ + /*< private >*/ + ClutterActorMetaClass parent_class; + + void (* _clutter_action1) (void); + void (* _clutter_action2) (void); + void (* _clutter_action3) (void); + void (* _clutter_action4) (void); + void (* _clutter_action5) (void); + void (* _clutter_action6) (void); + void (* _clutter_action7) (void); + void (* _clutter_action8) (void); +}; + +CLUTTER_AVAILABLE_IN_1_4 +GType clutter_action_get_type (void) G_GNUC_CONST; + +/* ClutterActor API */ +CLUTTER_AVAILABLE_IN_1_4 +void clutter_actor_add_action (ClutterActor *self, + ClutterAction *action); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_actor_add_action_with_name (ClutterActor *self, + const gchar *name, + ClutterAction *action); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_actor_remove_action (ClutterActor *self, + ClutterAction *action); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_actor_remove_action_by_name (ClutterActor *self, + const gchar *name); +CLUTTER_AVAILABLE_IN_1_4 +ClutterAction *clutter_actor_get_action (ClutterActor *self, + const gchar *name); +CLUTTER_AVAILABLE_IN_1_4 +GList * clutter_actor_get_actions (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_actor_clear_actions (ClutterActor *self); + +CLUTTER_AVAILABLE_IN_1_10 +gboolean clutter_actor_has_actions (ClutterActor *self); + +G_END_DECLS + +#endif /* __CLUTTER_ACTION_H__ */ diff --git a/clutter/clutter/clutter-actor-box.c b/clutter/clutter/clutter-actor-box.c new file mode 100644 index 0000000..2991066 --- /dev/null +++ b/clutter/clutter/clutter-actor-box.c @@ -0,0 +1,550 @@ +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#include "clutter-types.h" +#include "clutter-interval.h" +#include "clutter-private.h" + +/** + * clutter_actor_box_new: + * @x_1: X coordinate of the top left point + * @y_1: Y coordinate of the top left point + * @x_2: X coordinate of the bottom right point + * @y_2: Y coordinate of the bottom right point + * + * Allocates a new #ClutterActorBox using the passed coordinates + * for the top left and bottom right points. + * + * This function is the logical equivalent of: + * + * |[ + * clutter_actor_box_init (clutter_actor_box_alloc (), + * x_1, y_1, + * x_2, y_2); + * ]| + * + * Return value: (transfer full): the newly allocated #ClutterActorBox. + * Use clutter_actor_box_free() to free the resources + * + * Since: 1.0 + */ +ClutterActorBox * +clutter_actor_box_new (gfloat x_1, + gfloat y_1, + gfloat x_2, + gfloat y_2) +{ + return clutter_actor_box_init (clutter_actor_box_alloc (), + x_1, y_1, + x_2, y_2); +} + +/** + * clutter_actor_box_alloc: + * + * Allocates a new #ClutterActorBox. + * + * Return value: (transfer full): the newly allocated #ClutterActorBox. + * Use clutter_actor_box_free() to free its resources + * + * Since: 1.12 + */ +ClutterActorBox * +clutter_actor_box_alloc (void) +{ + return g_slice_new0 (ClutterActorBox); +} + +/** + * clutter_actor_box_init: + * @box: a #ClutterActorBox + * @x_1: X coordinate of the top left point + * @y_1: Y coordinate of the top left point + * @x_2: X coordinate of the bottom right point + * @y_2: Y coordinate of the bottom right point + * + * Initializes @box with the given coordinates. + * + * Return value: (transfer none): the initialized #ClutterActorBox + * + * Since: 1.10 + */ +ClutterActorBox * +clutter_actor_box_init (ClutterActorBox *box, + gfloat x_1, + gfloat y_1, + gfloat x_2, + gfloat y_2) +{ + g_return_val_if_fail (box != NULL, NULL); + + box->x1 = x_1; + box->y1 = y_1; + box->x2 = x_2; + box->y2 = y_2; + + return box; +} + +/** + * clutter_actor_box_init_rect: + * @box: a #ClutterActorBox + * @x: X coordinate of the origin + * @y: Y coordinate of the origin + * @width: width of the box + * @height: height of the box + * + * Initializes @box with the given origin and size. + * + * Since: 1.10 + */ +void +clutter_actor_box_init_rect (ClutterActorBox *box, + gfloat x, + gfloat y, + gfloat width, + gfloat height) +{ + g_return_if_fail (box != NULL); + + box->x1 = x; + box->y1 = y; + box->x2 = box->x1 + width; + box->y2 = box->y1 + height; +} + +/** + * clutter_actor_box_copy: + * @box: a #ClutterActorBox + * + * Copies @box + * + * Return value: a newly allocated copy of #ClutterActorBox. Use + * clutter_actor_box_free() to free the allocated resources + * + * Since: 1.0 + */ +ClutterActorBox * +clutter_actor_box_copy (const ClutterActorBox *box) +{ + if (G_LIKELY (box != NULL)) + return g_slice_dup (ClutterActorBox, box); + + return NULL; +} + +/** + * clutter_actor_box_free: + * @box: a #ClutterActorBox + * + * Frees a #ClutterActorBox allocated using clutter_actor_box_new() + * or clutter_actor_box_copy() + * + * Since: 1.0 + */ +void +clutter_actor_box_free (ClutterActorBox *box) +{ + if (G_LIKELY (box != NULL)) + g_slice_free (ClutterActorBox, box); +} + +/** + * clutter_actor_box_equal: + * @box_a: a #ClutterActorBox + * @box_b: a #ClutterActorBox + * + * Checks @box_a and @box_b for equality + * + * Return value: %TRUE if the passed #ClutterActorBox are equal + * + * Since: 1.0 + */ +gboolean +clutter_actor_box_equal (const ClutterActorBox *box_a, + const ClutterActorBox *box_b) +{ + g_return_val_if_fail (box_a != NULL && box_b != NULL, FALSE); + + if (box_a == box_b) + return TRUE; + + return box_a->x1 == box_b->x1 && box_a->y1 == box_b->y1 && + box_a->x2 == box_b->x2 && box_a->y2 == box_b->y2; +} + +/** + * clutter_actor_box_get_x: + * @box: a #ClutterActorBox + * + * Retrieves the X coordinate of the origin of @box + * + * Return value: the X coordinate of the origin + * + * Since: 1.0 + */ +gfloat +clutter_actor_box_get_x (const ClutterActorBox *box) +{ + g_return_val_if_fail (box != NULL, 0.); + + return box->x1; +} + +/** + * clutter_actor_box_get_y: + * @box: a #ClutterActorBox + * + * Retrieves the Y coordinate of the origin of @box + * + * Return value: the Y coordinate of the origin + * + * Since: 1.0 + */ +gfloat +clutter_actor_box_get_y (const ClutterActorBox *box) +{ + g_return_val_if_fail (box != NULL, 0.); + + return box->y1; +} + +/** + * clutter_actor_box_get_width: + * @box: a #ClutterActorBox + * + * Retrieves the width of the @box + * + * Return value: the width of the box + * + * Since: 1.0 + */ +gfloat +clutter_actor_box_get_width (const ClutterActorBox *box) +{ + g_return_val_if_fail (box != NULL, 0.); + + return box->x2 - box->x1; +} + +/** + * clutter_actor_box_get_height: + * @box: a #ClutterActorBox + * + * Retrieves the height of the @box + * + * Return value: the height of the box + * + * Since: 1.0 + */ +gfloat +clutter_actor_box_get_height (const ClutterActorBox *box) +{ + g_return_val_if_fail (box != NULL, 0.); + + return box->y2 - box->y1; +} + +/** + * clutter_actor_box_get_origin: + * @box: a #ClutterActorBox + * @x: (out) (allow-none): return location for the X coordinate, or %NULL + * @y: (out) (allow-none): return location for the Y coordinate, or %NULL + * + * Retrieves the origin of @box + * + * Since: 1.0 + */ +void +clutter_actor_box_get_origin (const ClutterActorBox *box, + gfloat *x, + gfloat *y) +{ + g_return_if_fail (box != NULL); + + if (x) + *x = box->x1; + + if (y) + *y = box->y1; +} + +/** + * clutter_actor_box_get_size: + * @box: a #ClutterActorBox + * @width: (out) (allow-none): return location for the width, or %NULL + * @height: (out) (allow-none): return location for the height, or %NULL + * + * Retrieves the size of @box + * + * Since: 1.0 + */ +void +clutter_actor_box_get_size (const ClutterActorBox *box, + gfloat *width, + gfloat *height) +{ + g_return_if_fail (box != NULL); + + if (width) + *width = box->x2 - box->x1; + + if (height) + *height = box->y2 - box->y1; +} + +/** + * clutter_actor_box_get_area: + * @box: a #ClutterActorBox + * + * Retrieves the area of @box + * + * Return value: the area of a #ClutterActorBox, in pixels + * + * Since: 1.0 + */ +gfloat +clutter_actor_box_get_area (const ClutterActorBox *box) +{ + g_return_val_if_fail (box != NULL, 0.); + + return (box->x2 - box->x1) * (box->y2 - box->y1); +} + +/** + * clutter_actor_box_contains: + * @box: a #ClutterActorBox + * @x: X coordinate of the point + * @y: Y coordinate of the point + * + * Checks whether a point with @x, @y coordinates is contained + * withing @box + * + * Return value: %TRUE if the point is contained by the #ClutterActorBox + * + * Since: 1.0 + */ +gboolean +clutter_actor_box_contains (const ClutterActorBox *box, + gfloat x, + gfloat y) +{ + g_return_val_if_fail (box != NULL, FALSE); + + return (x > box->x1 && x < box->x2) && + (y > box->y1 && y < box->y2); +} + +/** + * clutter_actor_box_from_vertices: + * @box: a #ClutterActorBox + * @verts: (array fixed-size=4): array of four #ClutterVertex + * + * Calculates the bounding box represented by the four vertices; for details + * of the vertex array see clutter_actor_get_abs_allocation_vertices(). + * + * Since: 1.0 + */ +void +clutter_actor_box_from_vertices (ClutterActorBox *box, + const ClutterVertex verts[]) +{ + gfloat x_1, x_2, y_1, y_2; + + g_return_if_fail (box != NULL); + g_return_if_fail (verts != NULL); + + /* 4-way min/max */ + x_1 = verts[0].x; + y_1 = verts[0].y; + + if (verts[1].x < x_1) + x_1 = verts[1].x; + + if (verts[2].x < x_1) + x_1 = verts[2].x; + + if (verts[3].x < x_1) + x_1 = verts[3].x; + + if (verts[1].y < y_1) + y_1 = verts[1].y; + + if (verts[2].y < y_1) + y_1 = verts[2].y; + + if (verts[3].y < y_1) + y_1 = verts[3].y; + + x_2 = verts[0].x; + y_2 = verts[0].y; + + if (verts[1].x > x_2) + x_2 = verts[1].x; + + if (verts[2].x > x_2) + x_2 = verts[2].x; + + if (verts[3].x > x_2) + x_2 = verts[3].x; + + if (verts[1].y > y_2) + y_2 = verts[1].y; + + if (verts[2].y > y_2) + y_2 = verts[2].y; + + if (verts[3].y > y_2) + y_2 = verts[3].y; + + box->x1 = x_1; + box->x2 = x_2; + box->y1 = y_1; + box->y2 = y_2; +} + +/** + * clutter_actor_box_interpolate: + * @initial: the initial #ClutterActorBox + * @final: the final #ClutterActorBox + * @progress: the interpolation progress + * @result: (out): return location for the interpolation + * + * Interpolates between @initial and @final #ClutterActorBoxes + * using @progress + * + * Since: 1.2 + */ +void +clutter_actor_box_interpolate (const ClutterActorBox *initial, + const ClutterActorBox *final, + gdouble progress, + ClutterActorBox *result) +{ + g_return_if_fail (initial != NULL); + g_return_if_fail (final != NULL); + g_return_if_fail (result != NULL); + + result->x1 = initial->x1 + (final->x1 - initial->x1) * progress; + result->y1 = initial->y1 + (final->y1 - initial->y1) * progress; + result->x2 = initial->x2 + (final->x2 - initial->x2) * progress; + result->y2 = initial->y2 + (final->y2 - initial->y2) * progress; +} + +/** + * clutter_actor_box_clamp_to_pixel: + * @box: (inout): the #ClutterActorBox to clamp + * + * Clamps the components of @box to the nearest integer + * + * Since: 1.2 + */ +void +clutter_actor_box_clamp_to_pixel (ClutterActorBox *box) +{ + g_return_if_fail (box != NULL); + + box->x1 = floorf (box->x1); + box->y1 = floorf (box->y1); + box->x2 = ceilf (box->x2); + box->y2 = ceilf (box->y2); +} + +/** + * clutter_actor_box_union: + * @a: (in): the first #ClutterActorBox + * @b: (in): the second #ClutterActorBox + * @result: (out): the #ClutterActorBox representing a union + * of @a and @b + * + * Unions the two boxes @a and @b and stores the result in @result. + * + * Since: 1.4 + */ +void +clutter_actor_box_union (const ClutterActorBox *a, + const ClutterActorBox *b, + ClutterActorBox *result) +{ + g_return_if_fail (a != NULL); + g_return_if_fail (b != NULL); + g_return_if_fail (result != NULL); + + result->x1 = MIN (a->x1, b->x1); + result->y1 = MIN (a->y1, b->y1); + + result->x2 = MAX (a->x2, b->x2); + result->y2 = MAX (a->y2, b->y2); +} + +static gboolean +clutter_actor_box_progress (const GValue *a, + const GValue *b, + gdouble factor, + GValue *retval) +{ + ClutterActorBox res = { 0, }; + + clutter_actor_box_interpolate (g_value_get_boxed (a), + g_value_get_boxed (b), + factor, + &res); + + g_value_set_boxed (retval, &res); + + return TRUE; +} + +/** + * clutter_actor_box_set_origin: + * @box: a #ClutterActorBox + * @x: the X coordinate of the new origin + * @y: the Y coordinate of the new origin + * + * Changes the origin of @box, maintaining the size of the #ClutterActorBox. + * + * Since: 1.6 + */ +void +clutter_actor_box_set_origin (ClutterActorBox *box, + gfloat x, + gfloat y) +{ + gfloat width, height; + + g_return_if_fail (box != NULL); + + width = box->x2 - box->x1; + height = box->y2 - box->y1; + + clutter_actor_box_init_rect (box, x, y, width, height); +} + +/** + * clutter_actor_box_set_size: + * @box: a #ClutterActorBox + * @width: the new width + * @height: the new height + * + * Sets the size of @box, maintaining the origin of the #ClutterActorBox. + * + * Since: 1.6 + */ +void +clutter_actor_box_set_size (ClutterActorBox *box, + gfloat width, + gfloat height) +{ + g_return_if_fail (box != NULL); + + box->x2 = box->x1 + width; + box->y2 = box->y1 + height; +} + +G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterActorBox, clutter_actor_box, + clutter_actor_box_copy, + clutter_actor_box_free, + CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_actor_box_progress)); diff --git a/clutter/clutter/clutter-actor-meta-private.h b/clutter/clutter/clutter-actor-meta-private.h new file mode 100644 index 0000000..661c352 --- /dev/null +++ b/clutter/clutter/clutter-actor-meta-private.h @@ -0,0 +1,97 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_ACTOR_META_PRIVATE_H__ +#define __CLUTTER_ACTOR_META_PRIVATE_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_META_GROUP (_clutter_meta_group_get_type ()) +#define CLUTTER_META_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_META_GROUP, ClutterMetaGroup)) +#define CLUTTER_IS_META_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_META_GROUP)) + +typedef struct _ClutterMetaGroup ClutterMetaGroup; +typedef struct _ClutterMetaGroupClass ClutterMetaGroupClass; + +struct _ClutterMetaGroup +{ + GObject parent_instance; + + ClutterActor *actor; + + GList *meta; +}; + +struct _ClutterMetaGroupClass +{ + GObjectClass parent_class; +}; + +/* Each actor meta has a priority with zero as a default. A higher + number means higher priority. Higher priority metas stay at the + beginning of the list. The priority can be negative to give lower + priority than the default. */ + +#define CLUTTER_ACTOR_META_PRIORITY_DEFAULT 0 + +/* Any value greater than this is considered an 'internal' priority + and if we expose the priority property publicly then an application + would not be able to use these values. */ + +#define CLUTTER_ACTOR_META_PRIORITY_INTERNAL_HIGH (G_MAXINT / 2) +#define CLUTTER_ACTOR_META_PRIORITY_INTERNAL_LOW (G_MININT / 2) + +GType _clutter_meta_group_get_type (void) G_GNUC_CONST; + +void _clutter_meta_group_add_meta (ClutterMetaGroup *group, + ClutterActorMeta *meta); +void _clutter_meta_group_remove_meta (ClutterMetaGroup *group, + ClutterActorMeta *meta); +const GList * _clutter_meta_group_peek_metas (ClutterMetaGroup *group); +void _clutter_meta_group_clear_metas (ClutterMetaGroup *group); +ClutterActorMeta * _clutter_meta_group_get_meta (ClutterMetaGroup *group, + const gchar *name); + +gboolean _clutter_meta_group_has_metas_no_internal (ClutterMetaGroup *group); + +GList * _clutter_meta_group_get_metas_no_internal (ClutterMetaGroup *group); +void _clutter_meta_group_clear_metas_no_internal (ClutterMetaGroup *group); + +/* ActorMeta */ +void _clutter_actor_meta_set_actor (ClutterActorMeta *meta, + ClutterActor *actor); + +const gchar * _clutter_actor_meta_get_debug_name (ClutterActorMeta *meta); + +void _clutter_actor_meta_set_priority (ClutterActorMeta *meta, + gint priority); +int _clutter_actor_meta_get_priority (ClutterActorMeta *meta); + +gboolean _clutter_actor_meta_is_internal (ClutterActorMeta *meta); + +G_END_DECLS + +#endif /* __CLUTTER_ACTOR_META_PRIVATE_H__ */ diff --git a/clutter/clutter/clutter-actor-meta.c b/clutter/clutter/clutter-actor-meta.c new file mode 100644 index 0000000..085f2f6 --- /dev/null +++ b/clutter/clutter/clutter-actor-meta.c @@ -0,0 +1,664 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-actor-meta + * @Title: ClutterActorMeta + * @Short_Description: Base class of actor modifiers + * @See_Also: #ClutterAction, #ClutterConstraint + * + * #ClutterActorMeta is an abstract class providing a common API for + * modifiers of #ClutterActor behaviour, appearance or layout. + * + * A #ClutterActorMeta can only be owned by a single #ClutterActor at + * any time. + * + * Every sub-class of #ClutterActorMeta should check if the + * #ClutterActorMeta:enabled property is set to %TRUE before applying + * any kind of modification. + * + * #ClutterActorMeta is available since Clutter 1.4 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-actor-meta-private.h" + +#include "clutter-debug.h" +#include "clutter-private.h" + +struct _ClutterActorMetaPrivate +{ + ClutterActor *actor; + guint destroy_id; + + gchar *name; + + guint is_enabled : 1; + + gint priority; +}; + +enum +{ + PROP_0, + + PROP_ACTOR, + PROP_NAME, + PROP_ENABLED, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterActorMeta, + clutter_actor_meta, + G_TYPE_INITIALLY_UNOWNED) + +static void +on_actor_destroy (ClutterActor *actor, + ClutterActorMeta *meta) +{ + meta->priv->actor = NULL; +} + +static void +clutter_actor_meta_real_set_actor (ClutterActorMeta *meta, + ClutterActor *actor) +{ + if (meta->priv->actor == actor) + return; + + if (meta->priv->destroy_id != 0) + { + g_signal_handler_disconnect (meta->priv->actor, meta->priv->destroy_id); + meta->priv->destroy_id = 0; + } + + meta->priv->actor = actor; + + if (meta->priv->actor != NULL) + meta->priv->destroy_id = g_signal_connect (meta->priv->actor, "destroy", + G_CALLBACK (on_actor_destroy), + meta); +} + +static void +clutter_actor_meta_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterActorMeta *meta = CLUTTER_ACTOR_META (gobject); + + switch (prop_id) + { + case PROP_NAME: + clutter_actor_meta_set_name (meta, g_value_get_string (value)); + break; + + case PROP_ENABLED: + clutter_actor_meta_set_enabled (meta, g_value_get_boolean (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_actor_meta_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterActorMeta *meta = CLUTTER_ACTOR_META (gobject); + + switch (prop_id) + { + case PROP_ACTOR: + g_value_set_object (value, meta->priv->actor); + break; + + case PROP_NAME: + g_value_set_string (value, meta->priv->name); + break; + + case PROP_ENABLED: + g_value_set_boolean (value, meta->priv->is_enabled); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_actor_meta_finalize (GObject *gobject) +{ + ClutterActorMetaPrivate *priv = CLUTTER_ACTOR_META (gobject)->priv; + + if (priv->destroy_id != 0 && priv->actor != NULL) + g_signal_handler_disconnect (priv->actor, priv->destroy_id); + + g_free (priv->name); + + G_OBJECT_CLASS (clutter_actor_meta_parent_class)->finalize (gobject); +} + +void +clutter_actor_meta_class_init (ClutterActorMetaClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + klass->set_actor = clutter_actor_meta_real_set_actor; + + /** + * ClutterActorMeta:actor: + * + * The #ClutterActor attached to the #ClutterActorMeta instance + * + * Since: 1.4 + */ + obj_props[PROP_ACTOR] = + g_param_spec_object ("actor", + P_("Actor"), + P_("The actor attached to the meta"), + CLUTTER_TYPE_ACTOR, + CLUTTER_PARAM_READABLE); + + /** + * ClutterActorMeta:name: + * + * The unique name to access the #ClutterActorMeta + * + * Since: 1.4 + */ + obj_props[PROP_NAME] = + g_param_spec_string ("name", + P_("Name"), + P_("The name of the meta"), + NULL, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActorMeta:enabled: + * + * Whether or not the #ClutterActorMeta is enabled + * + * Since: 1.4 + */ + obj_props[PROP_ENABLED] = + g_param_spec_boolean ("enabled", + P_("Enabled"), + P_("Whether the meta is enabled"), + TRUE, + CLUTTER_PARAM_READWRITE); + + gobject_class->finalize = clutter_actor_meta_finalize; + gobject_class->set_property = clutter_actor_meta_set_property; + gobject_class->get_property = clutter_actor_meta_get_property; + g_object_class_install_properties (gobject_class, + PROP_LAST, + obj_props); +} + +void +clutter_actor_meta_init (ClutterActorMeta *self) +{ + self->priv = clutter_actor_meta_get_instance_private (self); + self->priv->is_enabled = TRUE; + self->priv->priority = CLUTTER_ACTOR_META_PRIORITY_DEFAULT; +} + +/** + * clutter_actor_meta_set_name: + * @meta: a #ClutterActorMeta + * @name: the name of @meta + * + * Sets the name of @meta + * + * The name can be used to identify the #ClutterActorMeta instance + * + * Since: 1.4 + */ +void +clutter_actor_meta_set_name (ClutterActorMeta *meta, + const gchar *name) +{ + g_return_if_fail (CLUTTER_IS_ACTOR_META (meta)); + + if (g_strcmp0 (meta->priv->name, name) == 0) + return; + + g_free (meta->priv->name); + meta->priv->name = g_strdup (name); + + g_object_notify_by_pspec (G_OBJECT (meta), obj_props[PROP_NAME]); +} + +/** + * clutter_actor_meta_get_name: + * @meta: a #ClutterActorMeta + * + * Retrieves the name set using clutter_actor_meta_set_name() + * + * Return value: (transfer none): the name of the #ClutterActorMeta + * instance, or %NULL if none was set. The returned string is owned + * by the #ClutterActorMeta instance and it should not be modified + * or freed + * + * Since: 1.4 + */ +const gchar * +clutter_actor_meta_get_name (ClutterActorMeta *meta) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR_META (meta), NULL); + + return meta->priv->name; +} + +/** + * clutter_actor_meta_set_enabled: + * @meta: a #ClutterActorMeta + * @is_enabled: whether @meta is enabled + * + * Sets whether @meta should be enabled or not + * + * Since: 1.4 + */ +void +clutter_actor_meta_set_enabled (ClutterActorMeta *meta, + gboolean is_enabled) +{ + g_return_if_fail (CLUTTER_IS_ACTOR_META (meta)); + + is_enabled = !!is_enabled; + + if (meta->priv->is_enabled == is_enabled) + return; + + meta->priv->is_enabled = is_enabled; + + g_object_notify_by_pspec (G_OBJECT (meta), obj_props[PROP_ENABLED]); +} + +/** + * clutter_actor_meta_get_enabled: + * @meta: a #ClutterActorMeta + * + * Retrieves whether @meta is enabled + * + * Return value: %TRUE if the #ClutterActorMeta instance is enabled + * + * Since: 1.4 + */ +gboolean +clutter_actor_meta_get_enabled (ClutterActorMeta *meta) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR_META (meta), FALSE); + + return meta->priv->is_enabled; +} + +/* + * _clutter_actor_meta_set_actor + * @meta: a #ClutterActorMeta + * @actor: a #ClutterActor or %NULL + * + * Sets or unsets a back pointer to the #ClutterActor that owns + * the @meta + * + * Since: 1.4 + */ +void +_clutter_actor_meta_set_actor (ClutterActorMeta *meta, + ClutterActor *actor) +{ + g_return_if_fail (CLUTTER_IS_ACTOR_META (meta)); + g_return_if_fail (actor == NULL || CLUTTER_IS_ACTOR (actor)); + + CLUTTER_ACTOR_META_GET_CLASS (meta)->set_actor (meta, actor); +} + +/** + * clutter_actor_meta_get_actor: + * @meta: a #ClutterActorMeta + * + * Retrieves a pointer to the #ClutterActor that owns @meta + * + * Return value: (transfer none): a pointer to a #ClutterActor or %NULL + * + * Since: 1.4 + */ +ClutterActor * +clutter_actor_meta_get_actor (ClutterActorMeta *meta) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR_META (meta), NULL); + + return meta->priv->actor; +} + +void +_clutter_actor_meta_set_priority (ClutterActorMeta *meta, + gint priority) +{ + g_return_if_fail (CLUTTER_IS_ACTOR_META (meta)); + + /* This property shouldn't be modified after the actor meta is in + use because ClutterMetaGroup doesn't resort the list when it + changes. If we made the priority public then we could either make + the priority a construct-only property or listen for + notifications on the property from the ClutterMetaGroup and + resort. */ + g_return_if_fail (meta->priv->actor == NULL); + + meta->priv->priority = priority; +} + +gint +_clutter_actor_meta_get_priority (ClutterActorMeta *meta) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR_META (meta), 0); + + return meta->priv->priority; +} + +gboolean +_clutter_actor_meta_is_internal (ClutterActorMeta *meta) +{ + gint priority = meta->priv->priority; + + return (priority <= CLUTTER_ACTOR_META_PRIORITY_INTERNAL_LOW || + priority >= CLUTTER_ACTOR_META_PRIORITY_INTERNAL_HIGH); +} + +/* + * ClutterMetaGroup: a collection of ClutterActorMeta instances + */ + +G_DEFINE_TYPE (ClutterMetaGroup, _clutter_meta_group, G_TYPE_OBJECT); + +static void +_clutter_meta_group_dispose (GObject *gobject) +{ + _clutter_meta_group_clear_metas (CLUTTER_META_GROUP (gobject)); + + G_OBJECT_CLASS (_clutter_meta_group_parent_class)->dispose (gobject); +} + +static void +_clutter_meta_group_class_init (ClutterMetaGroupClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->dispose = _clutter_meta_group_dispose; +} + +static void +_clutter_meta_group_init (ClutterMetaGroup *self) +{ +} + +/* + * _clutter_meta_group_add_meta: + * @group: a #ClutterMetaGroup + * @meta: a #ClutterActorMeta to add + * + * Adds @meta to @group + * + * This function will remove the floating reference of @meta or, if the + * floating reference has already been sunk, add a reference to it + */ +void +_clutter_meta_group_add_meta (ClutterMetaGroup *group, + ClutterActorMeta *meta) +{ + GList *prev = NULL, *l; + + if (meta->priv->actor != NULL) + { + g_warning ("The meta of type '%s' with name '%s' is " + "already attached to actor '%s'", + G_OBJECT_TYPE_NAME (meta), + meta->priv->name != NULL + ? meta->priv->name + : "", + clutter_actor_get_name (meta->priv->actor) != NULL + ? clutter_actor_get_name (meta->priv->actor) + : G_OBJECT_TYPE_NAME (meta->priv->actor)); + return; + } + + /* Find a meta that has lower priority and insert before that */ + for (l = group->meta; l; l = l->next) + if (_clutter_actor_meta_get_priority (l->data) < + _clutter_actor_meta_get_priority (meta)) + break; + else + prev = l; + + if (prev == NULL) + group->meta = g_list_prepend (group->meta, meta); + else + { + prev->next = g_list_prepend (prev->next, meta); + prev->next->prev = prev; + } + + g_object_ref_sink (meta); + + _clutter_actor_meta_set_actor (meta, group->actor); +} + +/* + * _clutter_meta_group_remove_meta: + * @group: a #ClutterMetaGroup + * @meta: a #ClutterActorMeta to remove + * + * Removes @meta from @group and releases the reference being held on it + */ +void +_clutter_meta_group_remove_meta (ClutterMetaGroup *group, + ClutterActorMeta *meta) +{ + if (meta->priv->actor != group->actor) + { + g_warning ("The meta of type '%s' with name '%s' is not " + "attached to the actor '%s'", + G_OBJECT_TYPE_NAME (meta), + meta->priv->name != NULL + ? meta->priv->name + : "", + clutter_actor_get_name (group->actor) != NULL + ? clutter_actor_get_name (group->actor) + : G_OBJECT_TYPE_NAME (group->actor)); + return; + } + + _clutter_actor_meta_set_actor (meta, NULL); + + group->meta = g_list_remove (group->meta, meta); + g_object_unref (meta); +} + +/* + * _clutter_meta_group_peek_metas: + * @group: a #ClutterMetaGroup + * + * Returns a pointer to the #ClutterActorMeta list + * + * Return value: a const pointer to the #GList of #ClutterActorMeta + */ +const GList * +_clutter_meta_group_peek_metas (ClutterMetaGroup *group) +{ + return group->meta; +} + +/* + * _clutter_meta_group_get_metas_no_internal: + * @group: a #ClutterMetaGroup + * + * Returns a new allocated list containing all of the metas that don't + * have an internal priority. + * + * Return value: A GList containing non-internal metas. Free with + * g_list_free. + */ +GList * +_clutter_meta_group_get_metas_no_internal (ClutterMetaGroup *group) +{ + GList *ret = NULL; + GList *l; + + /* Build a new list filtering out the internal metas */ + for (l = group->meta; l; l = l->next) + if (!_clutter_actor_meta_is_internal (l->data)) + ret = g_list_prepend (ret, l->data); + + return g_list_reverse (ret); +} + +/* + * _clutter_meta_group_has_metas_no_internal: + * @group: a #ClutterMetaGroup + * + * Returns whether the group has any metas that don't have an internal priority. + * + * Return value: %TRUE if metas without internal priority exist + * %FALSE otherwise + */ +gboolean +_clutter_meta_group_has_metas_no_internal (ClutterMetaGroup *group) +{ + GList *l; + + for (l = group->meta; l; l = l->next) + if (!_clutter_actor_meta_is_internal (l->data)) + return TRUE; + + return FALSE; +} + +/* + * _clutter_meta_group_clear_metas: + * @group: a #ClutterMetaGroup + * + * Clears @group of all #ClutterActorMeta instances and releases + * the reference on them + */ +void +_clutter_meta_group_clear_metas (ClutterMetaGroup *group) +{ + g_list_foreach (group->meta, (GFunc) _clutter_actor_meta_set_actor, NULL); + + g_list_foreach (group->meta, (GFunc) g_object_unref, NULL); + g_list_free (group->meta); + group->meta = NULL; +} + +/* + * _clutter_meta_group_clear_metas_no_internal: + * @group: a #ClutterMetaGroup + * + * Clears @group of all #ClutterActorMeta instances that don't have an + * internal priority and releases the reference on them + */ +void +_clutter_meta_group_clear_metas_no_internal (ClutterMetaGroup *group) +{ + GList *internal_list = NULL; + GList *l, *next; + + for (l = group->meta; l; l = next) + { + next = l->next; + + if (_clutter_actor_meta_is_internal (l->data)) + { + if (internal_list) + internal_list->prev = l; + l->next = internal_list; + l->prev = NULL; + internal_list = l; + } + else + { + _clutter_actor_meta_set_actor (l->data, NULL); + g_object_unref (l->data); + g_list_free_1 (l); + } + } + + group->meta = g_list_reverse (internal_list); +} + +/* + * _clutter_meta_group_get_meta: + * @group: a #ClutterMetaGroup + * @name: the name of the #ClutterActorMeta to retrieve + * + * Retrieves a named #ClutterActorMeta from @group + * + * Return value: a #ClutterActorMeta for the given name, or %NULL + */ +ClutterActorMeta * +_clutter_meta_group_get_meta (ClutterMetaGroup *group, + const gchar *name) +{ + GList *l; + + for (l = group->meta; l != NULL; l = l->next) + { + ClutterActorMeta *meta = l->data; + + if (g_strcmp0 (meta->priv->name, name) == 0) + return meta; + } + + return NULL; +} + +/*< private > + * clutter_actor_meta_get_debug_name: + * @meta: a #ClutterActorMeta + * + * Retrieves the name of the @meta for debugging purposes. + * + * Return value: (transfer none): the name of the @meta. The returned + * string is owned by the @meta instance and it should not be + * modified or freed + */ +const gchar * +_clutter_actor_meta_get_debug_name (ClutterActorMeta *meta) +{ + return meta->priv->name != NULL ? meta->priv->name + : G_OBJECT_TYPE_NAME (meta); +} diff --git a/clutter/clutter/clutter-actor-meta.h b/clutter/clutter/clutter-actor-meta.h new file mode 100644 index 0000000..e954f36 --- /dev/null +++ b/clutter/clutter/clutter-actor-meta.h @@ -0,0 +1,119 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_ACTOR_META_H__ +#define __CLUTTER_ACTOR_META_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_ACTOR_META (clutter_actor_meta_get_type ()) +#define CLUTTER_ACTOR_META(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ACTOR_META, ClutterActorMeta)) +#define CLUTTER_IS_ACTOR_META(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ACTOR_META)) +#define CLUTTER_ACTOR_META_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_ACTOR_META, ClutterActorMetaClass)) +#define CLUTTER_IS_ACTOR_META_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_ACTOR_META)) +#define CLUTTER_ACTOR_META_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_ACTOR_META, ClutterActorMetaClass)) + +typedef struct _ClutterActorMetaPrivate ClutterActorMetaPrivate; +typedef struct _ClutterActorMetaClass ClutterActorMetaClass; + +/** + * ClutterActorMeta: + * + * The #ClutterActorMeta structure contains only + * private data and should be accessed using the provided API + * + * Since: 1.4 + */ +struct _ClutterActorMeta +{ + /*< private >*/ + GInitiallyUnowned parent_instance; + + ClutterActorMetaPrivate *priv; +}; + +/** + * ClutterActorMetaClass: + * @set_actor: virtual function, invoked when attaching and detaching + * a #ClutterActorMeta instance to a #ClutterActor + * + * The #ClutterActorMetaClass structure contains + * only private data + * + * Since: 1.4 + */ +struct _ClutterActorMetaClass +{ + /*< private >*/ + GInitiallyUnownedClass parent_class; + + /*< public >*/ + + /** + * ClutterActorMetaClass::set_actor: + * @meta: a #ClutterActorMeta + * @actor: (allow-none): the actor attached to @meta, or %NULL + * + * Virtual function, called when @meta is attached or detached + * from a #ClutterActor. + */ + void (* set_actor) (ClutterActorMeta *meta, + ClutterActor *actor); + + /*< private >*/ + void (* _clutter_meta1) (void); + void (* _clutter_meta2) (void); + void (* _clutter_meta3) (void); + void (* _clutter_meta4) (void); + void (* _clutter_meta5) (void); + void (* _clutter_meta6) (void); + void (* _clutter_meta7) (void); +}; + +CLUTTER_AVAILABLE_IN_1_4 +GType clutter_actor_meta_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_4 +void clutter_actor_meta_set_name (ClutterActorMeta *meta, + const gchar *name); +CLUTTER_AVAILABLE_IN_1_4 +const gchar * clutter_actor_meta_get_name (ClutterActorMeta *meta); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_actor_meta_set_enabled (ClutterActorMeta *meta, + gboolean is_enabled); +CLUTTER_AVAILABLE_IN_1_4 +gboolean clutter_actor_meta_get_enabled (ClutterActorMeta *meta); + +CLUTTER_AVAILABLE_IN_1_4 +ClutterActor * clutter_actor_meta_get_actor (ClutterActorMeta *meta); + +G_END_DECLS + +#endif /* __CLUTTER_ACTOR_META_H__ */ diff --git a/clutter/clutter/clutter-actor-private.h b/clutter/clutter/clutter-actor-private.h new file mode 100644 index 0000000..4dc767b --- /dev/null +++ b/clutter/clutter/clutter-actor-private.h @@ -0,0 +1,327 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __CLUTTER_ACTOR_PRIVATE_H__ +#define __CLUTTER_ACTOR_PRIVATE_H__ + +#include + +G_BEGIN_DECLS + +/*< private > + * ClutterRedrawFlags: + * @CLUTTER_REDRAW_CLIPPED_TO_ALLOCATION: Tells clutter the maximum + * extents of what needs to be redrawn lies within the actors + * current allocation. (Only use this for 2D actors though because + * any actor with depth may be projected outside of its allocation) + * + * Flags passed to the clutter_actor_queue_redraw_with_clip () + * function + * + * Since: 1.6 + */ +typedef enum +{ + CLUTTER_REDRAW_CLIPPED_TO_ALLOCATION = 1 << 0 +} ClutterRedrawFlags; + +/*< private > + * ClutterActorTraverseFlags: + * CLUTTER_ACTOR_TRAVERSE_DEPTH_FIRST: Traverse the graph in + * a depth first order. + * CLUTTER_ACTOR_TRAVERSE_BREADTH_FIRST: Traverse the graph in a + * breadth first order. + * + * Controls some options for how clutter_actor_traverse() iterates + * through the graph. + */ +typedef enum { + CLUTTER_ACTOR_TRAVERSE_DEPTH_FIRST = 1L<<0, + CLUTTER_ACTOR_TRAVERSE_BREADTH_FIRST = 1L<<1 +} ClutterActorTraverseFlags; + +/*< private > + * ClutterActorTraverseVisitFlags: + * CLUTTER_ACTOR_TRAVERSE_VISIT_CONTINUE: Continue traversing as + * normal + * CLUTTER_ACTOR_TRAVERSE_VISIT_SKIP_CHILDREN: Don't traverse the + * children of the last visited actor. (Not applicable when using + * %CLUTTER_ACTOR_TRAVERSE_DEPTH_FIRST_POST_ORDER since the children + * are visited before having an opportunity to bail out) + * CLUTTER_ACTOR_TRAVERSE_VISIT_BREAK: Immediately bail out without + * visiting any more actors. + * + * Each time an actor is visited during a scenegraph traversal the + * ClutterTraverseCallback can return a set of flags that may affect + * the continuing traversal. It may stop traversal completely, just + * skip over children for the current actor or continue as normal. + */ +typedef enum { + CLUTTER_ACTOR_TRAVERSE_VISIT_CONTINUE = 1L<<0, + CLUTTER_ACTOR_TRAVERSE_VISIT_SKIP_CHILDREN = 1L<<1, + CLUTTER_ACTOR_TRAVERSE_VISIT_BREAK = 1L<<2 +} ClutterActorTraverseVisitFlags; + +/*< private > + * ClutterTraverseCallback: + * + * The callback prototype used with clutter_actor_traverse. The + * returned flags can be used to affect the continuing traversal + * either by continuing as normal, skipping over children of an + * actor or bailing out completely. + */ +typedef ClutterActorTraverseVisitFlags (*ClutterTraverseCallback) (ClutterActor *actor, + gint depth, + gpointer user_data); + +/*< private > + * ClutterForeachCallback: + * @actor: The actor being iterated + * @user_data: The private data specified when starting the iteration + * + * A generic callback for iterating over actor, such as with + * _clutter_actor_foreach_child. The difference when compared to + * #ClutterCallback is that it returns a boolean so it is possible to break + * out of an iteration early. + * + * Return value: %TRUE to continue iterating or %FALSE to break iteration + * early. + */ +typedef gboolean (*ClutterForeachCallback) (ClutterActor *actor, + gpointer user_data); + +typedef struct _AnchorCoord AnchorCoord; +typedef struct _SizeRequest SizeRequest; + +typedef struct _ClutterLayoutInfo ClutterLayoutInfo; +typedef struct _ClutterTransformInfo ClutterTransformInfo; +typedef struct _ClutterAnimationInfo ClutterAnimationInfo; + +/* Internal helper struct to represent a point that can be stored in + either direct pixel coordinates or as a fraction of the actor's + size. It is used for the anchor point, scale center and rotation + centers. */ +struct _AnchorCoord +{ + gboolean is_fractional; + + union + { + /* Used when is_fractional == TRUE */ + struct + { + gdouble x; + gdouble y; + } fraction; + + /* Use when is_fractional == FALSE */ + ClutterVertex units; + } v; +}; + +struct _SizeRequest +{ + guint age; + gfloat for_size; + gfloat min_size; + gfloat natural_size; +}; + +/*< private > + * ClutterLayoutInfo: + * @fixed_pos: the fixed position of the actor + * @margin: the composed margin of the actor + * @x_align: the horizontal alignment, if the actor expands horizontally + * @y_align: the vertical alignment, if the actor expands vertically + * @x_expand: whether the actor should expand horizontally + * @y_expand: whether the actor should expand vertically + * @minimum: the fixed minimum size + * @natural: the fixed natural size + * + * Ancillary layout information for an actor. + */ +struct _ClutterLayoutInfo +{ + /* fixed position coordinates */ + ClutterPoint fixed_pos; + + ClutterMargin margin; + + guint x_align : 4; + guint y_align : 4; + + guint x_expand : 1; + guint y_expand : 1; + + ClutterSize minimum; + ClutterSize natural; +}; + +const ClutterLayoutInfo * _clutter_actor_get_layout_info_or_defaults (ClutterActor *self); +ClutterLayoutInfo * _clutter_actor_get_layout_info (ClutterActor *self); +ClutterLayoutInfo * _clutter_actor_peek_layout_info (ClutterActor *self); + +struct _ClutterTransformInfo +{ + /* rotation (angle and center) */ + gdouble rx_angle; + AnchorCoord rx_center; + + gdouble ry_angle; + AnchorCoord ry_center; + + gdouble rz_angle; + AnchorCoord rz_center; + + /* scaling */ + gdouble scale_x; + gdouble scale_y; + gdouble scale_z; + AnchorCoord scale_center; + + /* anchor point */ + AnchorCoord anchor; + + /* translation */ + ClutterVertex translation; + + /* z_position */ + gfloat z_position; + + /* transformation center */ + ClutterPoint pivot; + gfloat pivot_z; + + CoglMatrix transform; + guint transform_set : 1; + + CoglMatrix child_transform; + guint child_transform_set : 1; +}; + +const ClutterTransformInfo * _clutter_actor_get_transform_info_or_defaults (ClutterActor *self); +ClutterTransformInfo * _clutter_actor_get_transform_info (ClutterActor *self); + +typedef struct _AState { + guint easing_duration; + guint easing_delay; + ClutterAnimationMode easing_mode; +} AState; + +struct _ClutterAnimationInfo +{ + GArray *states; + AState *cur_state; + + GHashTable *transitions; +}; + +const ClutterAnimationInfo * _clutter_actor_get_animation_info_or_defaults (ClutterActor *self); +ClutterAnimationInfo * _clutter_actor_get_animation_info (ClutterActor *self); + +ClutterTransition * _clutter_actor_create_transition (ClutterActor *self, + GParamSpec *pspec, + ...); +ClutterTransition * _clutter_actor_get_transition (ClutterActor *self, + GParamSpec *pspec); + +gboolean _clutter_actor_foreach_child (ClutterActor *self, + ClutterForeachCallback callback, + gpointer user_data); +void _clutter_actor_traverse (ClutterActor *actor, + ClutterActorTraverseFlags flags, + ClutterTraverseCallback before_children_callback, + ClutterTraverseCallback after_children_callback, + gpointer user_data); +ClutterActor * _clutter_actor_get_stage_internal (ClutterActor *actor); + +void _clutter_actor_apply_modelview_transform (ClutterActor *self, + CoglMatrix *matrix); +void _clutter_actor_apply_relative_transformation_matrix (ClutterActor *self, + ClutterActor *ancestor, + CoglMatrix *matrix); + +void _clutter_actor_rerealize (ClutterActor *self, + ClutterCallback callback, + gpointer data); + +void _clutter_actor_set_in_clone_paint (ClutterActor *self, + gboolean is_in_clone_paint); + +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_actor_set_has_pointer (ClutterActor *self, + gboolean has_pointer); + +void _clutter_actor_queue_redraw_with_clip (ClutterActor *self, + ClutterRedrawFlags flags, + ClutterPaintVolume *clip_volume); +void _clutter_actor_queue_redraw_full (ClutterActor *self, + ClutterRedrawFlags flags, + ClutterPaintVolume *volume, + ClutterEffect *effect); + +ClutterPaintVolume * _clutter_actor_get_queue_redraw_clip (ClutterActor *self); +void _clutter_actor_set_queue_redraw_clip (ClutterActor *self, + ClutterPaintVolume *clip_volume); +void _clutter_actor_finish_queue_redraw (ClutterActor *self, + ClutterPaintVolume *clip); + +gboolean _clutter_actor_set_default_paint_volume (ClutterActor *self, + GType check_gtype, + ClutterPaintVolume *volume); + +const gchar * _clutter_actor_get_debug_name (ClutterActor *self); + +void _clutter_actor_push_clone_paint (void); +void _clutter_actor_pop_clone_paint (void); + +guint32 _clutter_actor_get_pick_id (ClutterActor *self); + +void _clutter_actor_shader_pre_paint (ClutterActor *actor, + gboolean repeat); +void _clutter_actor_shader_post_paint (ClutterActor *actor); + +ClutterActorAlign _clutter_actor_get_effective_x_align (ClutterActor *self); + +void _clutter_actor_handle_event (ClutterActor *actor, + const ClutterEvent *event); + +void _clutter_actor_attach_clone (ClutterActor *actor, + ClutterActor *clone); +void _clutter_actor_detach_clone (ClutterActor *actor, + ClutterActor *clone); +void _clutter_actor_queue_redraw_on_clones (ClutterActor *actor); +void _clutter_actor_queue_relayout_on_clones (ClutterActor *actor); +void _clutter_actor_queue_only_relayout (ClutterActor *actor); + +CoglFramebuffer * _clutter_actor_get_active_framebuffer (ClutterActor *actor); + +ClutterPaintNode * clutter_actor_create_texture_paint_node (ClutterActor *self, + CoglTexture *texture); + +G_END_DECLS + +#endif /* __CLUTTER_ACTOR_PRIVATE_H__ */ diff --git a/clutter/clutter/clutter-actor.c b/clutter/clutter/clutter-actor.c new file mode 100644 index 0000000..196d1ad --- /dev/null +++ b/clutter/clutter/clutter-actor.c @@ -0,0 +1,21136 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006, 2007, 2008 OpenedHand Ltd + * Copyright (C) 2009, 2010, 2011, 2012 Intel Corp + * + * 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 . + */ + +/** + * SECTION:clutter-actor + * @short_description: The basic element of the scene graph + * + * The ClutterActor class is the basic element of the scene graph in Clutter, + * and it encapsulates the position, size, and transformations of a node in + * the graph. + * + * ## Actor transformations ## {#clutter-actor-transformations} + * + * Each actor can be transformed using methods like clutter_actor_set_scale() + * or clutter_actor_set_rotation(). The order in which the transformations are + * applied is decided by Clutter and it is the following: + * + * 1. translation by the origin of the #ClutterActor:allocation property + * 2. translation by the actor's #ClutterActor:z-position property + * 3. translation by the actor's #ClutterActor:pivot-point property + * 4. scaling by the #ClutterActor:scale-x and #ClutterActor:scale-y factors + * 5. rotation around the #ClutterActor:rotation-angle-x and #ClutterActor:rotation-center-x + * 6. rotation around the #ClutterActor:rotation-angle-y and #ClutterActor:rotation-center-y + * 7. rotation around the #ClutterActor:rotation-angle-z and #ClutterActor:rotation-center-z + * 8. negative translation by the #ClutterActor:anchor-x and #ClutterActor:anchor-y point. + * 9. negative translation by the actor's #ClutterActor:pivot-point + * + * ## Modifying an actor's geometry ## {#clutter-actor-geometry} + * + * Each actor has a bounding box, called #ClutterActor:allocation + * which is either set by its parent or explicitly through the + * clutter_actor_set_position() and clutter_actor_set_size() methods. + * Each actor also has an implicit preferred size. + * + * An actor’s preferred size can be defined by any subclass by + * overriding the #ClutterActorClass.get_preferred_width() and the + * #ClutterActorClass.get_preferred_height() virtual functions, or it can + * be explicitly set by using clutter_actor_set_width() and + * clutter_actor_set_height(). + * + * An actor’s position can be set explicitly by using + * clutter_actor_set_x() and clutter_actor_set_y(); the coordinates are + * relative to the origin of the actor’s parent. + * + * ## Managing actor children ## {#clutter-actor-children} + * + * Each actor can have multiple children, by calling + * clutter_actor_add_child() to add a new child actor, and + * clutter_actor_remove_child() to remove an existing child. #ClutterActor + * will hold a reference on each child actor, which will be released when + * the child is removed from its parent, or destroyed using + * clutter_actor_destroy(). + * + * |[ + * ClutterActor *actor = clutter_actor_new (); + * + * // set the bounding box of the actor + * clutter_actor_set_position (actor, 0, 0); + * clutter_actor_set_size (actor, 480, 640); + * + * // set the background color of the actor + * clutter_actor_set_background_color (actor, CLUTTER_COLOR_Orange); + * + * // set the bounding box of the child, relative to the parent + * ClutterActor *child = clutter_actor_new (); + * clutter_actor_set_position (child, 20, 20); + * clutter_actor_set_size (child, 80, 240); + * + * // set the background color of the child + * clutter_actor_set_background_color (child, CLUTTER_COLOR_Blue); + * + * // add the child to the actor + * clutter_actor_add_child (actor, child); + * ]| + * + * Children can be inserted at a given index, or above and below + * another child actor. The order of insertion determines the order of the + * children when iterating over them. Iterating over children is performed + * by using clutter_actor_get_first_child(), clutter_actor_get_previous_sibling(), + * clutter_actor_get_next_sibling(), and clutter_actor_get_last_child(). It is + * also possible to retrieve a list of children by using + * clutter_actor_get_children(), as well as retrieving a specific child at a + * given index by using clutter_actor_get_child_at_index(). + * + * If you need to track additions of children to a #ClutterActor, use + * the #ClutterContainer::actor-added signal; similarly, to track removals + * of children from a ClutterActor, use the #ClutterContainer::actor-removed + * signal. + * + * See [basic-actor.c](https://git.gnome.org/browse/clutter/tree/examples/basic-actor.c?h=clutter-1.18). + * + * ## Painting an actor ## {#clutter-actor-painting} + * + * There are three ways to paint an actor: + * + * - set a delegate #ClutterContent as the value for the #ClutterActor:content property of the actor + * - subclass #ClutterActor and override the #ClutterActorClass.paint_node() virtual function + * - subclass #ClutterActor and override the #ClutterActorClass.paint() virtual function. + * + * A #ClutterContent is a delegate object that takes over the painting + * operations of one, or more actors. The #ClutterContent painting will + * be performed on top of the #ClutterActor:background-color of the actor, + * and before calling the actor's own implementation of the + * #ClutterActorClass.paint_node() virtual function. + * + * |[ + * ClutterActor *actor = clutter_actor_new (); + * + * // set the bounding box + * clutter_actor_set_position (actor, 50, 50); + * clutter_actor_set_size (actor, 100, 100); + * + * // set the content; the image_content variable is set elsewhere + * clutter_actor_set_content (actor, image_content); + * ]| + * + * The #ClutterActorClass.paint_node() virtual function is invoked whenever + * an actor needs to be painted. The implementation of the virtual function + * must only paint the contents of the actor itself, and not the contents of + * its children, if the actor has any. + * + * The #ClutterPaintNode passed to the virtual function is the local root of + * the render tree; any node added to it will be rendered at the correct + * position, as defined by the actor's #ClutterActor:allocation. + * + * |[ + * static void + * my_actor_paint_node (ClutterActor *actor, + * ClutterPaintNode *root) + * { + * ClutterPaintNode *node; + * ClutterActorBox box; + * + * // where the content of the actor should be painted + * clutter_actor_get_allocation_box (actor, &box); + * + * // the cogl_texture variable is set elsewhere + * node = clutter_texture_node_new (cogl_texture, CLUTTER_COLOR_White, + * CLUTTER_SCALING_FILTER_TRILINEAR, + * CLUTTER_SCALING_FILTER_LINEAR); + * + * // paint the content of the node using the allocation + * clutter_paint_node_add_rectangle (node, &box); + * + * // add the node, and transfer ownership + * clutter_paint_node_add_child (root, node); + * clutter_paint_node_unref (node); + * } + * + * The #ClutterActorClass.paint() virtual function is invoked when the + * #ClutterActor::paint signal is emitted, and after the other signal + * handlers have been invoked. Overriding the paint virtual function + * gives total control to the paint sequence of the actor itself, + * including the children of the actor, if any. + * + * It is strongly discouraged to override the #ClutterActorClass.paint() + * virtual function, as well as connecting to the #ClutterActor::paint + * signal. These hooks into the paint sequence are considered legacy, and + * will be removed when the Clutter API changes. + * + * ## Handling events on an actor ## {#clutter-actor-event-handling} + * + * A #ClutterActor can receive and handle input device events, for + * instance pointer events and key events, as long as its + * #ClutterActor:reactive property is set to %TRUE. + * + * Once an actor has been determined to be the source of an event, + * Clutter will traverse the scene graph from the top-level actor towards the + * event source, emitting the #ClutterActor::captured-event signal on each + * ancestor until it reaches the source; this phase is also called + * the "capture" phase. If the event propagation was not stopped, the graph + * is walked backwards, from the source actor to the top-level, and the + * #ClutterActor::event signal is emitted, alongside eventual event-specific + * signals like #ClutterActor::button-press-event or #ClutterActor::motion-event; + * this phase is also called the "bubble" phase. + * + * At any point of the signal emission, signal handlers can stop the propagation + * through the scene graph by returning %CLUTTER_EVENT_STOP; otherwise, they can + * continue the propagation by returning %CLUTTER_EVENT_PROPAGATE. + * + * ## Animation ## {#clutter-actor-animation} + * + * Animation is a core concept of modern user interfaces; Clutter provides a + * complete and powerful animation framework that automatically tweens the + * actor's state without requiring direct, frame by frame manipulation from + * your application code. You have two models at your disposal: + * + * - an implicit animation model + * - an explicit animation model + * + * The implicit animation model of Clutter assumes that all the + * changes in an actor state should be gradual and asynchronous; Clutter + * will automatically transition an actor's property change between the + * current state and the desired one without manual intervention, if the + * property is defined to be animatable in its documentation. + * + * By default, in the 1.0 API series, the transition happens with a duration + * of zero milliseconds, and the implicit animation is an opt in feature to + * retain backwards compatibility. + * + * Implicit animations depend on the current easing state; in order to use + * the default easing state for an actor you should call the + * clutter_actor_save_easing_state() function: + * + * |[ + * // assume that the actor is currently positioned at (100, 100) + * + * // store the current easing state and reset the new easing state to + * // its default values + * clutter_actor_save_easing_state (actor); + * + * // change the actor's position + * clutter_actor_set_position (actor, 500, 500); + * + * // restore the previously saved easing state + * clutter_actor_restore_easing_state (actor); + * ]| + * + * The example above will trigger an implicit animation of the + * actor between its current position to a new position. + * + * Implicit animations use a default duration of 250 milliseconds, + * and a default easing mode of %CLUTTER_EASE_OUT_CUBIC, unless you call + * clutter_actor_set_easing_mode() and clutter_actor_set_easing_duration() + * after changing the easing state of the actor. + * + * It is possible to animate multiple properties of an actor + * at the same time, and you can animate multiple actors at the same + * time as well, for instance: + * + * |[ + * clutter_actor_save_easing_state (actor); + * + * // animate the actor's opacity and depth + * clutter_actor_set_opacity (actor, 0); + * clutter_actor_set_depth (actor, -100); + * + * clutter_actor_restore_easing_state (actor); + * + * clutter_actor_save_easing_state (another_actor); + * + * // animate another actor's opacity + * clutter_actor_set_opacity (another_actor, 255); + * clutter_actor_set_depth (another_actor, 100); + * + * clutter_actor_restore_easing_state (another_actor); + * ]| + * + * Changing the easing state will affect all the following property + * transitions, but will not affect existing transitions. + * + * It is important to note that if you modify the state on an + * animatable property while a transition is in flight, the transition's + * final value will be updated, as well as its duration and progress + * mode by using the current easing state; for instance, in the following + * example: + * + * |[ + * clutter_actor_save_easing_state (actor); + * clutter_actor_set_easing_duration (actor, 1000); + * clutter_actor_set_x (actor, 200); + * clutter_actor_restore_easing_state (actor); + * + * clutter_actor_save_easing_state (actor); + * clutter_actor_set_easing_duration (actor, 500); + * clutter_actor_set_x (actor, 100); + * clutter_actor_restore_easing_state (actor); + * ]| + * + * the first call to clutter_actor_set_x() will begin a transition + * of the #ClutterActor:x property from the current value to the value of + * 200 over a duration of one second; the second call to clutter_actor_set_x() + * will change the transition's final value to 100 and the duration to 500 + * milliseconds. + * + * It is possible to receive a notification of the completion of an + * implicit transition by using the #ClutterActor::transition-stopped + * signal, decorated with the name of the property. In case you want to + * know when all the currently in flight transitions are complete, use + * the #ClutterActor::transitions-completed signal instead. + * + * It is possible to retrieve the #ClutterTransition used by the + * animatable properties by using clutter_actor_get_transition() and using + * the property name as the transition name. + * + * The explicit animation model supported by Clutter requires that + * you create a #ClutterTransition object, and optionally set the initial + * and final values. The transition will not start unless you add it to the + * #ClutterActor. + * + * |[ + * ClutterTransition *transition; + * + * transition = clutter_property_transition_new ("opacity"); + * clutter_timeline_set_duration (CLUTTER_TIMELINE (transition), 3000); + * clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (transition), 2); + * clutter_timeline_set_auto_reverse (CLUTTER_TIMELINE (transition), TRUE); + * clutter_transition_set_from (transition, G_TYPE_UINT, 255); + * clutter_transition_set_to (transition, G_TYPE_UINT, 0); + * + * clutter_actor_add_transition (actor, "animate-opacity", transition); + * ]| + * + * The example above will animate the #ClutterActor:opacity property + * of an actor between fully opaque and fully transparent, and back, over + * a span of 3 seconds. The animation does not begin until it is added to + * the actor. + * + * The explicit animation API applies to all #GObject properties, + * as well as the custom properties defined through the #ClutterAnimatable + * interface, regardless of whether they are defined as implicitly + * animatable or not. + * + * The explicit animation API should also be used when using custom + * animatable properties for #ClutterAction, #ClutterConstraint, and + * #ClutterEffect instances associated to an actor; see the section on + * custom animatable properties below for an example. + * + * Finally, explicit animations are useful for creating animations + * that run continuously, for instance: + * + * |[ + * // this animation will pulse the actor's opacity continuously + * ClutterTransition *transition; + * ClutterInterval *interval; + * + * transition = clutter_property_transition_new ("opacity"); + * + * // we want to animate the opacity between 0 and 255 + * clutter_transition_set_from (transition, G_TYPE_UINT, 0); + * clutter_transition_set_to (transition, G_TYPE_UINT, 255); + * + * // over a one second duration, running an infinite amount of times + * clutter_timeline_set_duration (CLUTTER_TIMELINE (transition), 1000); + * clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (transition), -1); + * + * // we want to fade in and out, so we need to auto-reverse the transition + * clutter_timeline_set_auto_reverse (CLUTTER_TIMELINE (transition), TRUE); + * + * // and we want to use an easing function that eases both in and out + * clutter_timeline_set_progress_mode (CLUTTER_TIMELINE (transition), + * CLUTTER_EASE_IN_OUT_CUBIC); + * + * // add the transition to the desired actor to start it + * clutter_actor_add_transition (actor, "opacityAnimation", transition); + * ]| + * + * ## Implementing an actor ## {#clutter-actor-implementing} + * + * Careful consideration should be given when deciding to implement + * a #ClutterActor sub-class. It is generally recommended to implement a + * sub-class of #ClutterActor only for actors that should be used as leaf + * nodes of a scene graph. + * + * If your actor should be painted in a custom way, you should + * override the #ClutterActor::paint signal class handler. You can either + * opt to chain up to the parent class implementation or decide to fully + * override the default paint implementation; Clutter will set up the + * transformations and clip regions prior to emitting the #ClutterActor::paint + * signal. + * + * By overriding the #ClutterActorClass.get_preferred_width() and + * #ClutterActorClass.get_preferred_height() virtual functions it is + * possible to change or provide the preferred size of an actor; similarly, + * by overriding the #ClutterActorClass.allocate() virtual function it is + * possible to control the layout of the children of an actor. Make sure to + * always chain up to the parent implementation of the + * #ClutterActorClass.allocate() virtual function. + * + * In general, it is strongly encouraged to use delegation and composition + * instead of direct subclassing. + * + * ## ClutterActor custom properties for ClutterScript ## {#clutter-actor-custom-script} + * + * #ClutterActor defines a custom "rotation" property which allows a short-hand + * description of the rotations to be applied to an actor. + * + * The syntax of the "rotation" property is the following: + * + * |[ + * "rotation" : [ { "" : [ , [ ] ] } ] + * ]| + * + * where: + * + * - axis is the name of an enumeration value of type #ClutterRotateAxis + * - angle is a floating point value representing the rotation angle on the given axis in degrees + * - center-point is an optional array, and if present it must contain the center of rotation as described by two coordinates: + * - Y and Z for "x-axis" + * - X and Z for "y-axis" + * - X and Y for "z-axis". + * + * #ClutterActor also defines a scriptable "margin" property which follows the CSS "margin" shorthand. + * + * |[ + * // 4 values + * "margin" : [ top, right, bottom, left ] + * // 3 values + * "margin" : [ top, left/right, bottom ] + * // 2 values + * "margin" : [ top/bottom, left/right ] + * // 1 value + * "margin" : [ top/right/bottom/left ] + * ]| + * + * #ClutterActor will also parse every positional and dimensional + * property defined as a string through clutter_units_from_string(); you + * should read the documentation for the #ClutterUnits parser format for + * the valid units and syntax. + * + * ## Custom animatable properties + * + * #ClutterActor allows accessing properties of #ClutterAction, + * #ClutterEffect, and #ClutterConstraint instances associated to an actor + * instance for animation purposes. + * + * In order to access a specific #ClutterAction or a #ClutterConstraint + * property it is necessary to set the #ClutterActorMeta:name property on the + * given action or constraint. + * + * The property can be accessed using the following syntax: + * + * |[ + * @
.. + * ]| + * + * - the initial `@` is mandatory + * - the `section` fragment can be one between "actions", "constraints" and "effects" + * - the `meta-name` fragment is the name of the action, effect, or constraint, as + * specified by the #ClutterActorMeta:name property of #ClutterActorMeta + * - the `property-name` fragment is the name of the action, effect, or constraint + * property to be animated. + * + * The example below animates a #ClutterBindConstraint applied to an actor + * using an explicit transition. The `rect` actor has a binding constraint + * on the `origin` actor, and in its initial state is overlapping the actor + * to which is bound to. + * + * |[ + * constraint = clutter_bind_constraint_new (origin, CLUTTER_BIND_X, 0.0); + * clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "bind-x"); + * clutter_actor_add_constraint (rect, constraint); + * + * constraint = clutter_bind_constraint_new (origin, CLUTTER_BIND_Y, 0.0); + * clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "bind-y"); + * clutter_actor_add_constraint (rect, constraint); + * + * clutter_actor_set_reactive (origin, TRUE); + * + * g_signal_connect (origin, "button-press-event", + * G_CALLBACK (on_button_press), + * rect); + * ]| + * + * On button press, the rectangle "slides" from behind the actor to + * which is bound to, using the #ClutterBindConstraint:offset property to + * achieve the effect: + * + * |[ + * gboolean + * on_button_press (ClutterActor *origin, + * ClutterEvent *event, + * ClutterActor *rect) + * { + * ClutterTransition *transition; + * + * // the offset that we want to apply; this will make the actor + * // slide in from behind the origin and rest at the right of + * // the origin, plus a padding value + * float new_offset = clutter_actor_get_width (origin) + h_padding; + * + * // the property we wish to animate; the "@constraints" section + * // tells Clutter to check inside the constraints associated + * // with the actor; the "bind-x" section is the name of the + * // constraint; and the "offset" is the name of the property + * // on the constraint + * const char *prop = "@constraints.bind-x.offset"; + * + * // create a new transition for the given property + * transition = clutter_property_transition_new (prop); + * + * // set the easing mode and duration + * clutter_timeline_set_progress_mode (CLUTTER_TIMELINE (transition), + * CLUTTER_EASE_OUT_CUBIC); + * clutter_timeline_set_duration (CLUTTER_TIMELINE (transition), 500); + * + * // create the interval with the initial and final values + * clutter_transition_set_from (transition, G_TYPE_FLOAT, 0.f); + * clutter_transition_set_to (transition, G_TYPE_FLOAT, new_offset); + * + * // add the transition to the actor; this causes the animation + * // to start. the name "offsetAnimation" can be used to retrieve + * // the transition later + * clutter_actor_add_transition (rect, "offsetAnimation", transition); + * + * // we handled the event + * return CLUTTER_EVENT_STOP; + * } + * ]| + */ + +/** + * CLUTTER_ACTOR_IS_MAPPED: + * @a: a #ClutterActor + * + * Evaluates to %TRUE if the %CLUTTER_ACTOR_MAPPED flag is set. + * + * The mapped state is set when the actor is visible and all its parents up + * to a top-level (e.g. a #ClutterStage) are visible, realized, and mapped. + * + * This check can be used to see if an actor is going to be painted, as only + * actors with the %CLUTTER_ACTOR_MAPPED flag set are going to be painted. + * + * The %CLUTTER_ACTOR_MAPPED flag is managed by Clutter itself, and it should + * not be checked directly; instead, the recommended usage is to connect a + * handler on the #GObject::notify signal for the #ClutterActor:mapped + * property of #ClutterActor, and check the presence of + * the %CLUTTER_ACTOR_MAPPED flag on state changes. + * + * It is also important to note that Clutter may delay the changes of + * the %CLUTTER_ACTOR_MAPPED flag on top-levels due to backend-specific + * limitations, or during the reparenting of an actor, to optimize + * unnecessary (and potentially expensive) state changes. + * + * Since: 0.2 + * + * Deprecated: 1.24: Use clutter_actor_is_mapped() or the #ClutterActor:mapped + * property instead of this macro. + */ + +/** + * CLUTTER_ACTOR_IS_REALIZED: + * @a: a #ClutterActor + * + * Evaluates to %TRUE if the %CLUTTER_ACTOR_REALIZED flag is set. + * + * The realized state has an actor-dependant interpretation. If an + * actor wants to delay allocating resources until it is attached to a + * stage, it may use the realize state to do so. However it is + * perfectly acceptable for an actor to allocate Cogl resources before + * being realized because there is only one drawing context used by Clutter + * so any resources will work on any stage. If an actor is mapped it + * must also be realized, but an actor can be realized and unmapped + * (this is so hiding an actor temporarily doesn't do an expensive + * unrealize/realize). + * + * To be realized an actor must be inside a stage, and all its parents + * must be realized. + * + * Since: 0.2 + * + * Deprecated: 1.24: Use clutter_actor_is_realized() or the #ClutterActor:realized + * property instead of this macro. + */ + +/** + * CLUTTER_ACTOR_IS_VISIBLE: + * @a: a #ClutterActor + * + * Evaluates to %TRUE if the actor has been shown, %FALSE if it's hidden. + * Equivalent to the ClutterActor::visible object property. + * + * Note that an actor is only painted onscreen if it's mapped, which + * means it's visible, and all its parents are visible, and one of the + * parents is a toplevel stage; see also %CLUTTER_ACTOR_IS_MAPPED. + * + * Since: 0.2 + * + * Deprecated: 1.24: Use clutter_actor_is_visible() or the #ClutterActor:visible + * property instead of this macro. + */ + +/** + * CLUTTER_ACTOR_IS_REACTIVE: + * @a: a #ClutterActor + * + * Evaluates to %TRUE if the %CLUTTER_ACTOR_REACTIVE flag is set. + * + * Only reactive actors will receive event-related signals. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use clutter_actor_get_reactive() or the + * #ClutterActor:reactive property instead of this macro. + */ + +#include "clutter-build-config.h" + +#include + +#include + +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#define CLUTTER_ENABLE_EXPERIMENTAL_API + +#include "clutter-actor-private.h" + +#include "clutter-action.h" +#include "clutter-actor-meta-private.h" +#include "clutter-animatable.h" +#include "clutter-color-static.h" +#include "clutter-color.h" +#include "clutter-constraint-private.h" +#include "clutter-container.h" +#include "clutter-content-private.h" +#include "clutter-debug.h" +#include "clutter-easing.h" +#include "clutter-effect-private.h" +#include "clutter-enum-types.h" +#include "clutter-fixed-layout.h" +#include "clutter-flatten-effect.h" +#include "clutter-interval.h" +#include "clutter-main.h" +#include "clutter-marshal.h" +#include "clutter-paint-nodes.h" +#include "clutter-paint-node-private.h" +#include "clutter-paint-volume-private.h" +#include "clutter-private.h" +#include "clutter-property-transition.h" +#include "clutter-scriptable.h" +#include "clutter-script-private.h" +#include "clutter-stage-private.h" +#include "clutter-timeline.h" +#include "clutter-transition.h" +#include "clutter-units.h" + +#include "deprecated/clutter-actor.h" +#include "deprecated/clutter-behaviour.h" +#include "deprecated/clutter-container.h" + +/* Internal enum used to control mapped state update. This is a hint + * which indicates when to do something other than just enforce + * invariants. + */ +typedef enum { + MAP_STATE_CHECK, /* just enforce invariants. */ + MAP_STATE_MAKE_UNREALIZED, /* force unrealize, ignoring invariants, + * used when about to unparent. + */ + MAP_STATE_MAKE_MAPPED, /* set mapped, error if invariants not met; + * used to set mapped on toplevels. + */ + MAP_STATE_MAKE_UNMAPPED /* set unmapped, even if parent is mapped, + * used just before unmapping parent. + */ +} MapStateChange; + +/* 3 entries should be a good compromise, few layout managers + * will ask for 3 different preferred size in each allocation cycle */ +#define N_CACHED_SIZE_REQUESTS 3 + +struct _ClutterActorPrivate +{ + /* request mode */ + ClutterRequestMode request_mode; + + /* our cached size requests for different width / height */ + SizeRequest width_requests[N_CACHED_SIZE_REQUESTS]; + SizeRequest height_requests[N_CACHED_SIZE_REQUESTS]; + + /* An age of 0 means the entry is not set */ + guint cached_height_age; + guint cached_width_age; + + /* the bounding box of the actor, relative to the parent's + * allocation + */ + ClutterActorBox allocation; + ClutterAllocationFlags allocation_flags; + + /* clip, in actor coordinates */ + ClutterRect clip; + + /* the cached transformation matrix; see apply_transform() */ + CoglMatrix transform; + + guint8 opacity; + gint opacity_override; + + ClutterOffscreenRedirect offscreen_redirect; + + /* This is an internal effect used to implement the + offscreen-redirect property */ + ClutterEffect *flatten_effect; + + /* scene graph */ + ClutterActor *parent; + ClutterActor *prev_sibling; + ClutterActor *next_sibling; + ClutterActor *first_child; + ClutterActor *last_child; + + gint n_children; + + /* tracks whenever the children of an actor are changed; the + * age is incremented by 1 whenever an actor is added or + * removed. the age is not incremented when the first or the + * last child pointers are changed, or when grandchildren of + * an actor are changed. + */ + gint age; + + gchar *name; /* a non-unique name, used for debugging */ + + gint32 pick_id; /* per-stage unique id, used for picking */ + + /* a back-pointer to the Pango context that we can use + * to create pre-configured PangoLayout + */ + PangoContext *pango_context; + + /* the text direction configured for this child - either by + * application code, or by the actor's parent + */ + ClutterTextDirection text_direction; + + /* a counter used to toggle the CLUTTER_INTERNAL_CHILD flag */ + gint internal_child; + + /* meta classes */ + ClutterMetaGroup *actions; + ClutterMetaGroup *constraints; + ClutterMetaGroup *effects; + + /* delegate object used to allocate the children of this actor */ + ClutterLayoutManager *layout_manager; + + /* delegate object used to paint the contents of this actor */ + ClutterContent *content; + + ClutterActorBox content_box; + ClutterContentGravity content_gravity; + ClutterScalingFilter min_filter; + ClutterScalingFilter mag_filter; + ClutterContentRepeat content_repeat; + + /* used when painting, to update the paint volume */ + ClutterEffect *current_effect; + + /* This is used to store an effect which needs to be redrawn. A + redraw can be queued to start from a particular effect. This is + used by parametrised effects that can cache an image of the + actor. If a parameter of the effect changes then it only needs to + redraw the cached image, not the actual actor. The pointer is + only valid if is_dirty == TRUE. If the pointer is NULL then the + whole actor is dirty. */ + ClutterEffect *effect_to_redraw; + + /* This is used when painting effects to implement the + clutter_actor_continue_paint() function. It points to the node in + the list of effects that is next in the chain */ + const GList *next_effect_to_paint; + + ClutterPaintVolume paint_volume; + + /* NB: This volume isn't relative to this actor, it is in eye + * coordinates so that it can remain valid after the actor changes. + */ + ClutterPaintVolume last_paint_volume; + + ClutterStageQueueRedrawEntry *queue_redraw_entry; + + ClutterColor bg_color; + +#ifdef CLUTTER_ENABLE_DEBUG + /* a string used for debugging messages */ + gchar *debug_name; +#endif + + /* a set of clones of the actor */ + GHashTable *clones; + + /* whether the actor is inside a cloned branch; this + * value is propagated to all the actor's children + */ + gulong in_cloned_branch; + + GListModel *child_model; + ClutterActorCreateChildFunc create_child_func; + gpointer create_child_data; + GDestroyNotify create_child_notify; + + /* bitfields: KEEP AT THE END */ + + /* fixed position and sizes */ + guint position_set : 1; + guint min_width_set : 1; + guint min_height_set : 1; + guint natural_width_set : 1; + guint natural_height_set : 1; + /* cached request is invalid (implies allocation is too) */ + guint needs_width_request : 1; + /* cached request is invalid (implies allocation is too) */ + guint needs_height_request : 1; + /* cached allocation is invalid (request has changed, probably) */ + guint needs_allocation : 1; + guint show_on_set_parent : 1; + guint has_clip : 1; + guint clip_to_allocation : 1; + guint enable_model_view_transform : 1; + guint enable_paint_unmapped : 1; + guint has_pointer : 1; + guint propagated_one_redraw : 1; + guint paint_volume_valid : 1; + guint last_paint_volume_valid : 1; + guint in_clone_paint : 1; + guint transform_valid : 1; + /* This is TRUE if anything has queued a redraw since we were last + painted. In this case effect_to_redraw will point to an effect + the redraw was queued from or it will be NULL if the redraw was + queued without an effect. */ + guint is_dirty : 1; + guint bg_color_set : 1; + guint content_box_valid : 1; + guint x_expand_set : 1; + guint y_expand_set : 1; + guint needs_compute_expand : 1; + guint needs_x_expand : 1; + guint needs_y_expand : 1; +}; + +enum +{ + PROP_0, + + PROP_NAME, + + /* X, Y, WIDTH, HEIGHT are "do what I mean" properties; + * when set they force a size request, when gotten they + * get the allocation if the allocation is valid, and the + * request otherwise + */ + PROP_X, + PROP_Y, + PROP_WIDTH, + PROP_HEIGHT, + + PROP_POSITION, + PROP_SIZE, + + /* Then the rest of these size-related properties are the "actual" + * underlying properties set or gotten by X, Y, WIDTH, HEIGHT + */ + PROP_FIXED_X, + PROP_FIXED_Y, + + PROP_FIXED_POSITION_SET, + + PROP_MIN_WIDTH, + PROP_MIN_WIDTH_SET, + + PROP_MIN_HEIGHT, + PROP_MIN_HEIGHT_SET, + + PROP_NATURAL_WIDTH, + PROP_NATURAL_WIDTH_SET, + + PROP_NATURAL_HEIGHT, + PROP_NATURAL_HEIGHT_SET, + + PROP_REQUEST_MODE, + + /* Allocation properties are read-only */ + PROP_ALLOCATION, + + PROP_DEPTH, /* XXX:2.0 remove */ + PROP_Z_POSITION, + + PROP_CLIP, /* XXX:2.0 remove */ + PROP_CLIP_RECT, + PROP_HAS_CLIP, + PROP_CLIP_TO_ALLOCATION, + + PROP_OPACITY, + + PROP_OFFSCREEN_REDIRECT, + + PROP_VISIBLE, + PROP_MAPPED, + PROP_REALIZED, + PROP_REACTIVE, + + PROP_PIVOT_POINT, + PROP_PIVOT_POINT_Z, + + PROP_SCALE_X, + PROP_SCALE_Y, + PROP_SCALE_Z, + PROP_SCALE_CENTER_X, /* XXX:2.0 remove */ + PROP_SCALE_CENTER_Y, /* XXX:2.0 remove */ + PROP_SCALE_GRAVITY, /* XXX:2.0 remove */ + + PROP_ROTATION_ANGLE_X, /* XXX:2.0 rename to rotation-x */ + PROP_ROTATION_ANGLE_Y, /* XXX:2.0 rename to rotation-y */ + PROP_ROTATION_ANGLE_Z, /* XXX:2.0 rename to rotation-z */ + PROP_ROTATION_CENTER_X, /* XXX:2.0 remove */ + PROP_ROTATION_CENTER_Y, /* XXX:2.0 remove */ + PROP_ROTATION_CENTER_Z, /* XXX:2.0 remove */ + /* This property only makes sense for the z rotation because the + others would depend on the actor having a size along the + z-axis */ + PROP_ROTATION_CENTER_Z_GRAVITY, /* XXX:2.0 remove */ + + PROP_ANCHOR_X, /* XXX:2.0 remove */ + PROP_ANCHOR_Y, /* XXX:2.0 remove */ + PROP_ANCHOR_GRAVITY, /*XXX:2.0 remove */ + + PROP_TRANSLATION_X, + PROP_TRANSLATION_Y, + PROP_TRANSLATION_Z, + + PROP_TRANSFORM, + PROP_TRANSFORM_SET, + PROP_CHILD_TRANSFORM, + PROP_CHILD_TRANSFORM_SET, + + PROP_SHOW_ON_SET_PARENT, /*XXX:2.0 remove */ + + PROP_TEXT_DIRECTION, + PROP_HAS_POINTER, + + PROP_ACTIONS, + PROP_CONSTRAINTS, + PROP_EFFECT, + + PROP_LAYOUT_MANAGER, + + PROP_X_EXPAND, + PROP_Y_EXPAND, + PROP_X_ALIGN, + PROP_Y_ALIGN, + PROP_MARGIN_TOP, + PROP_MARGIN_BOTTOM, + PROP_MARGIN_LEFT, + PROP_MARGIN_RIGHT, + + PROP_BACKGROUND_COLOR, + PROP_BACKGROUND_COLOR_SET, + + PROP_FIRST_CHILD, + PROP_LAST_CHILD, + + PROP_CONTENT, + PROP_CONTENT_GRAVITY, + PROP_CONTENT_BOX, + PROP_MINIFICATION_FILTER, + PROP_MAGNIFICATION_FILTER, + PROP_CONTENT_REPEAT, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +enum +{ + SHOW, + HIDE, + DESTROY, + PARENT_SET, + KEY_FOCUS_IN, + KEY_FOCUS_OUT, + PAINT, + PICK, + REALIZE, + UNREALIZE, + QUEUE_REDRAW, + QUEUE_RELAYOUT, + EVENT, + CAPTURED_EVENT, + BUTTON_PRESS_EVENT, + BUTTON_RELEASE_EVENT, + SCROLL_EVENT, + KEY_PRESS_EVENT, + KEY_RELEASE_EVENT, + MOTION_EVENT, + ENTER_EVENT, + LEAVE_EVENT, + ALLOCATION_CHANGED, + TRANSITIONS_COMPLETED, + TOUCH_EVENT, + TRANSITION_STOPPED, + + LAST_SIGNAL +}; + +static guint actor_signals[LAST_SIGNAL] = { 0, }; + +typedef struct _TransitionClosure +{ + ClutterActor *actor; + ClutterTransition *transition; + gchar *name; + gulong completed_id; + guint is_implicit : 1; +} TransitionClosure; + +static void clutter_container_iface_init (ClutterContainerIface *iface); +static void clutter_scriptable_iface_init (ClutterScriptableIface *iface); +static void clutter_animatable_iface_init (ClutterAnimatableIface *iface); +static void atk_implementor_iface_init (AtkImplementorIface *iface); + +/* These setters are all static for now, maybe they should be in the + * public API, but they are perhaps obscure enough to leave only as + * properties + */ +static void clutter_actor_set_min_width (ClutterActor *self, + gfloat min_width); +static void clutter_actor_set_min_height (ClutterActor *self, + gfloat min_height); +static void clutter_actor_set_natural_width (ClutterActor *self, + gfloat natural_width); +static void clutter_actor_set_natural_height (ClutterActor *self, + gfloat natural_height); +static void clutter_actor_set_min_width_set (ClutterActor *self, + gboolean use_min_width); +static void clutter_actor_set_min_height_set (ClutterActor *self, + gboolean use_min_height); +static void clutter_actor_set_natural_width_set (ClutterActor *self, + gboolean use_natural_width); +static void clutter_actor_set_natural_height_set (ClutterActor *self, + gboolean use_natural_height); +static void clutter_actor_update_map_state (ClutterActor *self, + MapStateChange change); +static void clutter_actor_unrealize_not_hiding (ClutterActor *self); + +/* Helper routines for managing anchor coords */ +static void clutter_anchor_coord_get_units (ClutterActor *self, + const AnchorCoord *coord, + gfloat *x, + gfloat *y, + gfloat *z); +static void clutter_anchor_coord_set_units (AnchorCoord *coord, + gfloat x, + gfloat y, + gfloat z); + +static ClutterGravity clutter_anchor_coord_get_gravity (const AnchorCoord *coord); +static void clutter_anchor_coord_set_gravity (AnchorCoord *coord, + ClutterGravity gravity); + +static gboolean clutter_anchor_coord_is_zero (const AnchorCoord *coord); + +static void _clutter_actor_get_relative_transformation_matrix (ClutterActor *self, + ClutterActor *ancestor, + CoglMatrix *matrix); + +static ClutterPaintVolume *_clutter_actor_get_paint_volume_mutable (ClutterActor *self); + +static guint8 clutter_actor_get_paint_opacity_internal (ClutterActor *self); + +static inline void clutter_actor_set_background_color_internal (ClutterActor *self, + const ClutterColor *color); + +static void on_layout_manager_changed (ClutterLayoutManager *manager, + ClutterActor *self); + +static inline void clutter_actor_queue_compute_expand (ClutterActor *self); + +static inline void clutter_actor_set_margin_internal (ClutterActor *self, + gfloat margin, + GParamSpec *pspec); + +static void clutter_actor_set_transform_internal (ClutterActor *self, + const ClutterMatrix *transform); +static void clutter_actor_set_child_transform_internal (ClutterActor *self, + const ClutterMatrix *transform); + +static void clutter_actor_realize_internal (ClutterActor *self); +static void clutter_actor_unrealize_internal (ClutterActor *self); + +/* Helper macro which translates by the anchor coord, applies the + given transformation and then translates back */ +#define TRANSFORM_ABOUT_ANCHOR_COORD(a,m,c,_transform) G_STMT_START { \ + gfloat _tx, _ty, _tz; \ + clutter_anchor_coord_get_units ((a), (c), &_tx, &_ty, &_tz); \ + cogl_matrix_translate ((m), _tx, _ty, _tz); \ + { _transform; } \ + cogl_matrix_translate ((m), -_tx, -_ty, -_tz); } G_STMT_END + +static GQuark quark_shader_data = 0; +static GQuark quark_actor_layout_info = 0; +static GQuark quark_actor_transform_info = 0; +static GQuark quark_actor_animation_info = 0; + +G_DEFINE_TYPE_WITH_CODE (ClutterActor, + clutter_actor, + G_TYPE_INITIALLY_UNOWNED, + G_ADD_PRIVATE (ClutterActor) + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER, + clutter_container_iface_init) + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_SCRIPTABLE, + clutter_scriptable_iface_init) + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_ANIMATABLE, + clutter_animatable_iface_init) + G_IMPLEMENT_INTERFACE (ATK_TYPE_IMPLEMENTOR, + atk_implementor_iface_init)); + +/*< private > + * clutter_actor_get_debug_name: + * @actor: a #ClutterActor + * + * Retrieves a printable name of @actor for debugging messages + * + * Return value: a string with a printable name + */ +const gchar * +_clutter_actor_get_debug_name (ClutterActor *actor) +{ + ClutterActorPrivate *priv = actor->priv; + const gchar *retval; + +#ifdef CLUTTER_ENABLE_DEBUG + if (G_UNLIKELY (priv->debug_name == NULL)) + { + priv->debug_name = g_strdup_printf ("<%s>[<%s>:%p]", + priv->name != NULL ? priv->name + : "unnamed", + G_OBJECT_TYPE_NAME (actor), + actor); + } + + retval = priv->debug_name; +#else + retval = priv->name != NULL + ? priv->name + : G_OBJECT_TYPE_NAME (actor); +#endif + + return retval; +} + +#ifdef CLUTTER_ENABLE_DEBUG +/* XXX - this is for debugging only, remove once working (or leave + * in only in some debug mode). Should leave it for a little while + * until we're confident in the new map/realize/visible handling. + */ +static inline void +clutter_actor_verify_map_state (ClutterActor *self) +{ + ClutterActorPrivate *priv = self->priv; + + if (CLUTTER_ACTOR_IS_REALIZED (self)) + { + /* all bets are off during reparent when we're potentially realized, + * but should not be according to invariants + */ + if (!CLUTTER_ACTOR_IN_REPARENT (self)) + { + if (priv->parent == NULL) + { + if (CLUTTER_ACTOR_IS_TOPLEVEL (self)) + { + } + else + g_warning ("Realized non-toplevel actor '%s' should " + "have a parent", + _clutter_actor_get_debug_name (self)); + } + else if (!CLUTTER_ACTOR_IS_REALIZED (priv->parent)) + { + g_warning ("Realized actor %s has an unrealized parent %s", + _clutter_actor_get_debug_name (self), + _clutter_actor_get_debug_name (priv->parent)); + } + } + } + + if (CLUTTER_ACTOR_IS_MAPPED (self)) + { + if (!CLUTTER_ACTOR_IS_REALIZED (self)) + g_warning ("Actor '%s' is mapped but not realized", + _clutter_actor_get_debug_name (self)); + + /* remaining bets are off during reparent when we're potentially + * mapped, but should not be according to invariants + */ + if (!CLUTTER_ACTOR_IN_REPARENT (self)) + { + if (priv->parent == NULL) + { + if (CLUTTER_ACTOR_IS_TOPLEVEL (self)) + { + if (!CLUTTER_ACTOR_IS_VISIBLE (self) && + !CLUTTER_ACTOR_IN_DESTRUCTION (self)) + { + g_warning ("Toplevel actor '%s' is mapped " + "but not visible", + _clutter_actor_get_debug_name (self)); + } + } + else + { + g_warning ("Mapped actor '%s' should have a parent", + _clutter_actor_get_debug_name (self)); + } + } + else + { + ClutterActor *iter = self; + + /* check for the enable_paint_unmapped flag on the actor + * and parents; if the flag is enabled at any point of this + * branch of the scene graph then all the later checks + * become pointless + */ + while (iter != NULL) + { + if (iter->priv->enable_paint_unmapped) + return; + + iter = iter->priv->parent; + } + + if (!CLUTTER_ACTOR_IS_VISIBLE (priv->parent)) + { + g_warning ("Actor '%s' should not be mapped if parent '%s'" + "is not visible", + _clutter_actor_get_debug_name (self), + _clutter_actor_get_debug_name (priv->parent)); + } + + if (!CLUTTER_ACTOR_IS_REALIZED (priv->parent)) + { + g_warning ("Actor '%s' should not be mapped if parent '%s'" + "is not realized", + _clutter_actor_get_debug_name (self), + _clutter_actor_get_debug_name (priv->parent)); + } + + if (!CLUTTER_ACTOR_IS_TOPLEVEL (priv->parent)) + { + if (!CLUTTER_ACTOR_IS_MAPPED (priv->parent)) + g_warning ("Actor '%s' is mapped but its non-toplevel " + "parent '%s' is not mapped", + _clutter_actor_get_debug_name (self), + _clutter_actor_get_debug_name (priv->parent)); + } + } + } + } +} + +#endif /* CLUTTER_ENABLE_DEBUG */ + +static void +clutter_actor_set_mapped (ClutterActor *self, + gboolean mapped) +{ + if (CLUTTER_ACTOR_IS_MAPPED (self) == mapped) + return; + + if (mapped) + { + CLUTTER_ACTOR_GET_CLASS (self)->map (self); + g_assert (CLUTTER_ACTOR_IS_MAPPED (self)); + } + else + { + CLUTTER_ACTOR_GET_CLASS (self)->unmap (self); + g_assert (!CLUTTER_ACTOR_IS_MAPPED (self)); + } +} + +/* this function updates the mapped and realized states according to + * invariants, in the appropriate order. + */ +static void +clutter_actor_update_map_state (ClutterActor *self, + MapStateChange change) +{ + gboolean was_mapped; + + was_mapped = CLUTTER_ACTOR_IS_MAPPED (self); + + if (CLUTTER_ACTOR_IS_TOPLEVEL (self)) + { + /* the mapped flag on top-level actors must be set by the + * per-backend implementation because it might be asynchronous. + * + * That is, the MAPPED flag on toplevels currently tracks the X + * server mapped-ness of the window, while the expected behavior + * (if used to GTK) may be to track WM_STATE!=WithdrawnState. + * This creates some weird complexity by breaking the invariant + * that if we're visible and all ancestors shown then we are + * also mapped - instead, we are mapped if all ancestors + * _possibly excepting_ the stage are mapped. The stage + * will map/unmap for example when it is minimized or + * moved to another workspace. + * + * So, the only invariant on the stage is that if visible it + * should be realized, and that it has to be visible to be + * mapped. + */ + if (CLUTTER_ACTOR_IS_VISIBLE (self)) + clutter_actor_realize (self); + + switch (change) + { + case MAP_STATE_CHECK: + break; + + case MAP_STATE_MAKE_MAPPED: + g_assert (!was_mapped); + clutter_actor_set_mapped (self, TRUE); + break; + + case MAP_STATE_MAKE_UNMAPPED: + g_assert (was_mapped); + clutter_actor_set_mapped (self, FALSE); + break; + + case MAP_STATE_MAKE_UNREALIZED: + /* we only use MAKE_UNREALIZED in unparent, + * and unparenting a stage isn't possible. + * If someone wants to just unrealize a stage + * then clutter_actor_unrealize() doesn't + * go through this codepath. + */ + g_warning ("Trying to force unrealize stage is not allowed"); + break; + } + + if (CLUTTER_ACTOR_IS_MAPPED (self) && + !CLUTTER_ACTOR_IS_VISIBLE (self) && + !CLUTTER_ACTOR_IN_DESTRUCTION (self)) + { + g_warning ("Clutter toplevel of type '%s' is not visible, but " + "it is somehow still mapped", + _clutter_actor_get_debug_name (self)); + } + } + else + { + ClutterActorPrivate *priv = self->priv; + ClutterActor *parent = priv->parent; + gboolean should_be_mapped; + gboolean may_be_realized; + gboolean must_be_realized; + + should_be_mapped = FALSE; + may_be_realized = TRUE; + must_be_realized = FALSE; + + if (parent == NULL || change == MAP_STATE_MAKE_UNREALIZED) + { + may_be_realized = FALSE; + } + else + { + /* Maintain invariant that if parent is mapped, and we are + * visible, then we are mapped ... unless parent is a + * stage, in which case we map regardless of parent's map + * state but do require stage to be visible and realized. + * + * If parent is realized, that does not force us to be + * realized; but if parent is unrealized, that does force + * us to be unrealized. + * + * The reason we don't force children to realize with + * parents is _clutter_actor_rerealize(); if we require that + * a realized parent means children are realized, then to + * unrealize an actor we would have to unrealize its + * parents, which would end up meaning unrealizing and + * hiding the entire stage. So we allow unrealizing a + * child (as long as that child is not mapped) while that + * child still has a realized parent. + * + * Also, if we unrealize from leaf nodes to root, and + * realize from root to leaf, the invariants are never + * violated if we allow children to be unrealized + * while parents are realized. + * + * When unmapping, MAP_STATE_MAKE_UNMAPPED is specified + * to force us to unmap, even though parent is still + * mapped. This is because we're unmapping from leaf nodes + * up to root nodes. + */ + if (CLUTTER_ACTOR_IS_VISIBLE (self) && + change != MAP_STATE_MAKE_UNMAPPED) + { + gboolean parent_is_visible_realized_toplevel; + + parent_is_visible_realized_toplevel = + (CLUTTER_ACTOR_IS_TOPLEVEL (parent) && + CLUTTER_ACTOR_IS_VISIBLE (parent) && + CLUTTER_ACTOR_IS_REALIZED (parent)); + + if (CLUTTER_ACTOR_IS_MAPPED (parent) || + parent_is_visible_realized_toplevel) + { + must_be_realized = TRUE; + should_be_mapped = TRUE; + } + } + + /* if the actor has been set to be painted even if unmapped + * then we should map it and check for realization as well; + * this is an override for the branch of the scene graph + * which begins with this node + */ + if (priv->enable_paint_unmapped) + { + should_be_mapped = TRUE; + must_be_realized = TRUE; + } + + if (!CLUTTER_ACTOR_IS_REALIZED (parent)) + may_be_realized = FALSE; + } + + if (change == MAP_STATE_MAKE_MAPPED && !should_be_mapped) + { + if (parent == NULL) + g_warning ("Attempting to map a child that does not " + "meet the necessary invariants: the actor '%s' " + "has no parent", + _clutter_actor_get_debug_name (self)); + else + g_warning ("Attempting to map a child that does not " + "meet the necessary invariants: the actor '%s' " + "is parented to an unmapped actor '%s'", + _clutter_actor_get_debug_name (self), + _clutter_actor_get_debug_name (priv->parent)); + } + + /* If in reparent, we temporarily suspend unmap and unrealize. + * + * We want to go in the order "realize, map" and "unmap, unrealize" + */ + + /* Unmap */ + if (!should_be_mapped && !CLUTTER_ACTOR_IN_REPARENT (self)) + clutter_actor_set_mapped (self, FALSE); + + /* Realize */ + if (must_be_realized) + clutter_actor_realize (self); + + /* if we must be realized then we may be, presumably */ + g_assert (!(must_be_realized && !may_be_realized)); + + /* Unrealize */ + if (!may_be_realized && !CLUTTER_ACTOR_IN_REPARENT (self)) + clutter_actor_unrealize_not_hiding (self); + + /* Map */ + if (should_be_mapped) + { + if (!must_be_realized) + g_warning ("Somehow we think actor '%s' should be mapped but " + "not realized, which isn't allowed", + _clutter_actor_get_debug_name (self)); + + /* realization is allowed to fail (though I don't know what + * an app is supposed to do about that - shouldn't it just + * be a g_error? anyway, we have to avoid mapping if this + * happens) + */ + if (CLUTTER_ACTOR_IS_REALIZED (self)) + clutter_actor_set_mapped (self, TRUE); + } + } + +#ifdef CLUTTER_ENABLE_DEBUG + /* check all invariants were kept */ + clutter_actor_verify_map_state (self); +#endif +} + +static void +clutter_actor_real_map (ClutterActor *self) +{ + ClutterActorPrivate *priv = self->priv; + ClutterActor *stage, *iter; + + g_assert (!CLUTTER_ACTOR_IS_MAPPED (self)); + + CLUTTER_NOTE (ACTOR, "Mapping actor '%s'", + _clutter_actor_get_debug_name (self)); + + CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_MAPPED); + + stage = _clutter_actor_get_stage_internal (self); + priv->pick_id = _clutter_stage_acquire_pick_id (CLUTTER_STAGE (stage), self); + + CLUTTER_NOTE (ACTOR, "Pick id '%d' for actor '%s'", + priv->pick_id, + _clutter_actor_get_debug_name (self)); + + /* notify on parent mapped before potentially mapping + * children, so apps see a top-down notification. + */ + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_MAPPED]); + + for (iter = self->priv->first_child; + iter != NULL; + iter = iter->priv->next_sibling) + { + clutter_actor_map (iter); + } +} + +/** + * clutter_actor_map: + * @self: A #ClutterActor + * + * Sets the %CLUTTER_ACTOR_MAPPED flag on the actor and possibly maps + * and realizes its children if they are visible. Does nothing if the + * actor is not visible. + * + * Calling this function is strongly disencouraged: the default + * implementation of #ClutterActorClass.map() will map all the children + * of an actor when mapping its parent. + * + * When overriding map, it is mandatory to chain up to the parent + * implementation. + * + * Since: 1.0 + */ +void +clutter_actor_map (ClutterActor *self) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + if (CLUTTER_ACTOR_IS_MAPPED (self)) + return; + + if (!CLUTTER_ACTOR_IS_VISIBLE (self)) + return; + + clutter_actor_update_map_state (self, MAP_STATE_MAKE_MAPPED); +} + +/** + * clutter_actor_is_mapped: + * @self: a #ClutterActor + * + * Checks whether a #ClutterActor has been set as mapped. + * + * See also %CLUTTER_ACTOR_IS_MAPPED and #ClutterActor:mapped + * + * Returns: %TRUE if the actor is mapped + * + * Since: 1.24 + */ +gboolean +clutter_actor_is_mapped (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); + + return CLUTTER_ACTOR_IS_MAPPED (self); +} + +static void +clutter_actor_real_unmap (ClutterActor *self) +{ + ClutterActorPrivate *priv = self->priv; + ClutterActor *iter; + + g_assert (CLUTTER_ACTOR_IS_MAPPED (self)); + + CLUTTER_NOTE (ACTOR, "Unmapping actor '%s'", + _clutter_actor_get_debug_name (self)); + + for (iter = self->priv->first_child; + iter != NULL; + iter = iter->priv->next_sibling) + { + clutter_actor_unmap (iter); + } + + CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_MAPPED); + + /* clear the contents of the last paint volume, so that hiding + moving + + * showing will not result in the wrong area being repainted + */ + _clutter_paint_volume_init_static (&priv->last_paint_volume, NULL); + priv->last_paint_volume_valid = TRUE; + + /* notify on parent mapped after potentially unmapping + * children, so apps see a bottom-up notification. + */ + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_MAPPED]); + + /* relinquish keyboard focus if we were unmapped while owning it */ + if (!CLUTTER_ACTOR_IS_TOPLEVEL (self)) + { + ClutterStage *stage; + + stage = CLUTTER_STAGE (_clutter_actor_get_stage_internal (self)); + + if (stage != NULL) + _clutter_stage_release_pick_id (stage, priv->pick_id); + + priv->pick_id = -1; + + if (stage != NULL && + clutter_stage_get_key_focus (stage) == self) + { + clutter_stage_set_key_focus (stage, NULL); + } + } +} + +/** + * clutter_actor_unmap: + * @self: A #ClutterActor + * + * Unsets the %CLUTTER_ACTOR_MAPPED flag on the actor and possibly + * unmaps its children if they were mapped. + * + * Calling this function is not encouraged: the default #ClutterActor + * implementation of #ClutterActorClass.unmap() will also unmap any + * eventual children by default when their parent is unmapped. + * + * When overriding #ClutterActorClass.unmap(), it is mandatory to + * chain up to the parent implementation. + * + * It is important to note that the implementation of the + * #ClutterActorClass.unmap() virtual function may be called after + * the #ClutterActorClass.destroy() or the #GObjectClass.dispose() + * implementation, but it is guaranteed to be called before the + * #GObjectClass.finalize() implementation. + * + * Since: 1.0 + */ +void +clutter_actor_unmap (ClutterActor *self) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + if (!CLUTTER_ACTOR_IS_MAPPED (self)) + return; + + clutter_actor_update_map_state (self, MAP_STATE_MAKE_UNMAPPED); +} + +static void +clutter_actor_real_show (ClutterActor *self) +{ + ClutterActorPrivate *priv = self->priv; + + if (CLUTTER_ACTOR_IS_VISIBLE (self)) + return; + + CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_VISIBLE); + + /* we notify on the "visible" flag in the clutter_actor_show() + * wrapper so the entire show signal emission completes first, + * and the branch of the scene graph is in a stable state + */ + clutter_actor_update_map_state (self, MAP_STATE_CHECK); + + /* we queue a relayout unless the actor is inside a + * container that explicitly told us not to + */ + if (priv->parent != NULL && + (!(priv->parent->flags & CLUTTER_ACTOR_NO_LAYOUT))) + { + /* While an actor is hidden the parent may not have + * allocated/requested so we need to start from scratch + * and avoid the short-circuiting in + * clutter_actor_queue_relayout(). + */ + priv->needs_width_request = FALSE; + priv->needs_height_request = FALSE; + priv->needs_allocation = FALSE; + + clutter_actor_queue_relayout (self); + } +} + +static inline void +set_show_on_set_parent (ClutterActor *self, + gboolean set_show) +{ + ClutterActorPrivate *priv = self->priv; + + set_show = !!set_show; + + if (priv->show_on_set_parent == set_show) + return; + + if (priv->parent == NULL) + { + priv->show_on_set_parent = set_show; + g_object_notify_by_pspec (G_OBJECT (self), + obj_props[PROP_SHOW_ON_SET_PARENT]); + } +} + +/** + * clutter_actor_show: + * @self: A #ClutterActor + * + * Flags an actor to be displayed. An actor that isn't shown will not + * be rendered on the stage. + * + * Actors are visible by default. + * + * If this function is called on an actor without a parent, the + * #ClutterActor:show-on-set-parent will be set to %TRUE as a side + * effect. + */ +void +clutter_actor_show (ClutterActor *self) +{ + ClutterActorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + /* simple optimization */ + if (CLUTTER_ACTOR_IS_VISIBLE (self)) + { + /* we still need to set the :show-on-set-parent property, in + * case show() is called on an unparented actor + */ + set_show_on_set_parent (self, TRUE); + return; + } + +#ifdef CLUTTER_ENABLE_DEBUG + clutter_actor_verify_map_state (self); +#endif + + priv = self->priv; + + g_object_freeze_notify (G_OBJECT (self)); + + set_show_on_set_parent (self, TRUE); + + /* if we're showing a child that needs to expand, or may + * expand, then we need to recompute the expand flags for + * its parent as well + */ + if (priv->needs_compute_expand || + priv->needs_x_expand || + priv->needs_y_expand) + { + clutter_actor_queue_compute_expand (self); + } + + g_signal_emit (self, actor_signals[SHOW], 0); + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_VISIBLE]); + + if (priv->parent != NULL) + clutter_actor_queue_redraw (priv->parent); + + g_object_thaw_notify (G_OBJECT (self)); +} + +/** + * clutter_actor_is_visible: + * @self: a #ClutterActor + * + * Checks whether an actor is marked as visible. + * + * See also %CLUTTER_ACTOR_IS_VISIBLE and #ClutterActor:visible. + * + * Returns: %TRUE if the actor visible + * + * Since: 1.24 + */ +gboolean +clutter_actor_is_visible (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); + + return CLUTTER_ACTOR_IS_VISIBLE (self); +} + +/** + * clutter_actor_show_all: + * @self: a #ClutterActor + * + * Calls clutter_actor_show() on all children of an actor (if any). + * + * Since: 0.2 + * + * Deprecated: 1.10: Actors are visible by default + */ +void +clutter_actor_show_all (ClutterActor *self) +{ + ClutterActorClass *klass; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + klass = CLUTTER_ACTOR_GET_CLASS (self); + if (klass->show_all) + klass->show_all (self); +} + +static void +clutter_actor_real_hide (ClutterActor *self) +{ + ClutterActorPrivate *priv = self->priv; + + if (!CLUTTER_ACTOR_IS_VISIBLE (self)) + return; + + CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_VISIBLE); + + /* we notify on the "visible" flag in the clutter_actor_hide() + * wrapper so the entire hide signal emission completes first, + * and the branch of the scene graph is in a stable state + */ + clutter_actor_update_map_state (self, MAP_STATE_CHECK); + + /* we queue a relayout unless the actor is inside a + * container that explicitly told us not to + */ + if (priv->parent != NULL && + (!(priv->parent->flags & CLUTTER_ACTOR_NO_LAYOUT))) + clutter_actor_queue_relayout (priv->parent); +} + +/** + * clutter_actor_hide: + * @self: A #ClutterActor + * + * Flags an actor to be hidden. A hidden actor will not be + * rendered on the stage. + * + * Actors are visible by default. + * + * If this function is called on an actor without a parent, the + * #ClutterActor:show-on-set-parent property will be set to %FALSE + * as a side-effect. + */ +void +clutter_actor_hide (ClutterActor *self) +{ + ClutterActorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + /* simple optimization */ + if (!CLUTTER_ACTOR_IS_VISIBLE (self)) + { + /* we still need to set the :show-on-set-parent property, in + * case hide() is called on an unparented actor + */ + set_show_on_set_parent (self, FALSE); + return; + } + +#ifdef CLUTTER_ENABLE_DEBUG + clutter_actor_verify_map_state (self); +#endif + + priv = self->priv; + + g_object_freeze_notify (G_OBJECT (self)); + + set_show_on_set_parent (self, FALSE); + + /* if we're hiding a child that needs to expand, or may + * expand, then we need to recompute the expand flags for + * its parent as well + */ + if (priv->needs_compute_expand || + priv->needs_x_expand || + priv->needs_y_expand) + { + clutter_actor_queue_compute_expand (self); + } + + g_signal_emit (self, actor_signals[HIDE], 0); + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_VISIBLE]); + + if (priv->parent != NULL) + clutter_actor_queue_redraw (priv->parent); + + g_object_thaw_notify (G_OBJECT (self)); +} + +/** + * clutter_actor_hide_all: + * @self: a #ClutterActor + * + * Calls clutter_actor_hide() on all child actors (if any). + * + * Since: 0.2 + * + * Deprecated: 1.10: Using clutter_actor_hide() on the actor will + * prevent its children from being painted as well. + */ +void +clutter_actor_hide_all (ClutterActor *self) +{ + ClutterActorClass *klass; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + klass = CLUTTER_ACTOR_GET_CLASS (self); + if (klass->hide_all) + klass->hide_all (self); +} + +/** + * clutter_actor_realize: + * @self: A #ClutterActor + * + * Realization informs the actor that it is attached to a stage. It + * can use this to allocate resources if it wanted to delay allocation + * until it would be rendered. However it is perfectly acceptable for + * an actor to create resources before being realized because Clutter + * only ever has a single rendering context so that actor is free to + * be moved from one stage to another. + * + * This function does nothing if the actor is already realized. + * + * Because a realized actor must have realized parent actors, calling + * clutter_actor_realize() will also realize all parents of the actor. + * + * This function does not realize child actors, except in the special + * case that realizing the stage, when the stage is visible, will + * suddenly map (and thus realize) the children of the stage. + * + * Deprecated: 1.16: Actors are automatically realized, and nothing + * requires explicit realization. + */ +void +clutter_actor_realize (ClutterActor *self) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + clutter_actor_realize_internal (self); +} + +/** + * clutter_actor_is_realized: + * @self: a #ClutterActor + * + * Checks whether a #ClutterActor is realized. + * + * See also %CLUTTER_ACTOR_IS_REALIZED and #ClutterActor:realized. + * + * Returns: %TRUE if the actor is realized + * + * Since: 1.24 + */ +gboolean +clutter_actor_is_realized (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); + + return CLUTTER_ACTOR_IS_REALIZED (self); +} + +static void +clutter_actor_realize_internal (ClutterActor *self) +{ + ClutterActorPrivate *priv = self->priv; + +#ifdef CLUTTER_ENABLE_DEBUG + clutter_actor_verify_map_state (self); +#endif + + if (CLUTTER_ACTOR_IS_REALIZED (self)) + return; + + /* To be realized, our parent actors must be realized first. + * This will only succeed if we're inside a toplevel. + */ + if (priv->parent != NULL) + clutter_actor_realize (priv->parent); + + if (CLUTTER_ACTOR_IS_TOPLEVEL (self)) + { + /* toplevels can be realized at any time */ + } + else + { + /* "Fail" the realization if parent is missing or unrealized; + * this should really be a g_warning() not some kind of runtime + * failure; how can an app possibly recover? Instead it's a bug + * in the app and the app should get an explanatory warning so + * someone can fix it. But for now it's too hard to fix this + * because e.g. ClutterTexture needs reworking. + */ + if (priv->parent == NULL || + !CLUTTER_ACTOR_IS_REALIZED (priv->parent)) + return; + } + + CLUTTER_NOTE (ACTOR, "Realizing actor '%s'", _clutter_actor_get_debug_name (self)); + + CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_REALIZED); + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_REALIZED]); + + g_signal_emit (self, actor_signals[REALIZE], 0); + + /* Stage actor is allowed to unset the realized flag again in its + * default signal handler, though that is a pathological situation. + */ + + /* If realization "failed" we'll have to update child state. */ + clutter_actor_update_map_state (self, MAP_STATE_CHECK); +} + +static void +clutter_actor_real_unrealize (ClutterActor *self) +{ + /* we must be unmapped (implying our children are also unmapped) */ + g_assert (!CLUTTER_ACTOR_IS_MAPPED (self)); +} + +/** + * clutter_actor_unrealize: + * @self: A #ClutterActor + * + * Unrealization informs the actor that it may be being destroyed or + * moved to another stage. The actor may want to destroy any + * underlying graphics resources at this point. However it is + * perfectly acceptable for it to retain the resources until the actor + * is destroyed because Clutter only ever uses a single rendering + * context and all of the graphics resources are valid on any stage. + * + * Because mapped actors must be realized, actors may not be + * unrealized if they are mapped. This function hides the actor to be + * sure it isn't mapped, an application-visible side effect that you + * may not be expecting. + * + * This function should not be called by application code. + * + * This function should not really be in the public API, because + * there isn't a good reason to call it. ClutterActor will already + * unrealize things for you when it's important to do so. + * + * If you were using clutter_actor_unrealize() in a dispose + * implementation, then don't, just chain up to ClutterActor's + * dispose. + * + * If you were using clutter_actor_unrealize() to implement + * unrealizing children of your container, then don't, ClutterActor + * will already take care of that. + * + * Deprecated: 1.16: Actors are automatically unrealized, and nothing + * requires explicit realization. + */ +void +clutter_actor_unrealize (ClutterActor *self) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (!CLUTTER_ACTOR_IS_MAPPED (self)); + + clutter_actor_unrealize_internal (self); +} + +/* If you were using clutter_actor_unrealize() to re-realize to + * create your resources in a different way, then use + * _clutter_actor_rerealize() (inside Clutter) or just call your + * code that recreates your resources directly (outside Clutter). + */ +static void +clutter_actor_unrealize_internal (ClutterActor *self) +{ +#ifdef CLUTTER_ENABLE_DEBUG + clutter_actor_verify_map_state (self); +#endif + + clutter_actor_hide (self); + + clutter_actor_unrealize_not_hiding (self); +} + +static ClutterActorTraverseVisitFlags +unrealize_actor_before_children_cb (ClutterActor *self, + int depth, + void *user_data) +{ + /* If an actor is already unrealized we know its children have also + * already been unrealized... */ + if (!CLUTTER_ACTOR_IS_REALIZED (self)) + return CLUTTER_ACTOR_TRAVERSE_VISIT_SKIP_CHILDREN; + + g_signal_emit (self, actor_signals[UNREALIZE], 0); + + return CLUTTER_ACTOR_TRAVERSE_VISIT_CONTINUE; +} + +static ClutterActorTraverseVisitFlags +unrealize_actor_after_children_cb (ClutterActor *self, + int depth, + void *user_data) +{ + /* We want to unset the realized flag only _after_ + * child actors are unrealized, to maintain invariants. + */ + CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED); + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_REALIZED]); + return CLUTTER_ACTOR_TRAVERSE_VISIT_CONTINUE; +} + +/* + * clutter_actor_unrealize_not_hiding: + * @self: A #ClutterActor + * + * Unrealization informs the actor that it may be being destroyed or + * moved to another stage. The actor may want to destroy any + * underlying graphics resources at this point. However it is + * perfectly acceptable for it to retain the resources until the actor + * is destroyed because Clutter only ever uses a single rendering + * context and all of the graphics resources are valid on any stage. + * + * Because mapped actors must be realized, actors may not be + * unrealized if they are mapped. You must hide the actor or one of + * its parents before attempting to unrealize. + * + * This function is separate from clutter_actor_unrealize() because it + * does not automatically hide the actor. + * Actors need not be hidden to be unrealized, they just need to + * be unmapped. In fact we don't want to mess up the application's + * setting of the "visible" flag, so hiding is very undesirable. + * + * clutter_actor_unrealize() does a clutter_actor_hide() just for + * backward compatibility. + */ +static void +clutter_actor_unrealize_not_hiding (ClutterActor *self) +{ + _clutter_actor_traverse (self, + CLUTTER_ACTOR_TRAVERSE_DEPTH_FIRST, + unrealize_actor_before_children_cb, + unrealize_actor_after_children_cb, + NULL); +} + +/* + * _clutter_actor_rerealize: + * @self: A #ClutterActor + * @callback: Function to call while unrealized + * @data: data for callback + * + * If an actor is already unrealized, this just calls the callback. + * + * If it is realized, it unrealizes temporarily, calls the callback, + * and then re-realizes the actor. + * + * As a side effect, leaves all children of the actor unrealized if + * the actor was realized but not showing. This is because when we + * unrealize the actor temporarily we must unrealize its children + * (e.g. children of a stage can't be realized if stage window is + * gone). And we aren't clever enough to save the realization state of + * all children. In most cases this should not matter, because + * the children will automatically realize when they next become mapped. + */ +void +_clutter_actor_rerealize (ClutterActor *self, + ClutterCallback callback, + void *data) +{ + gboolean was_mapped; + gboolean was_showing; + gboolean was_realized; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + +#ifdef CLUTTER_ENABLE_DEBUG + clutter_actor_verify_map_state (self); +#endif + + was_realized = CLUTTER_ACTOR_IS_REALIZED (self); + was_mapped = CLUTTER_ACTOR_IS_MAPPED (self); + was_showing = CLUTTER_ACTOR_IS_VISIBLE (self); + + /* Must be unmapped to unrealize. Note we only have to hide this + * actor if it was mapped (if all parents were showing). If actor + * is merely visible (but not mapped), then that's fine, we can + * leave it visible. + */ + if (was_mapped) + clutter_actor_hide (self); + + g_assert (!CLUTTER_ACTOR_IS_MAPPED (self)); + + /* unrealize self and all children */ + clutter_actor_unrealize_not_hiding (self); + + if (callback != NULL) + { + (* callback) (self, data); + } + + if (was_showing) + clutter_actor_show (self); /* will realize only if mapping implies it */ + else if (was_realized) + clutter_actor_realize (self); /* realize self and all parents */ +} + +static void +clutter_actor_real_pick (ClutterActor *self, + const ClutterColor *color) +{ + /* the default implementation is just to paint a rectangle + * with the same size of the actor using the passed color + */ + if (clutter_actor_should_pick_paint (self)) + { + ClutterActorBox box = { 0, }; + float width, height; + + clutter_actor_get_allocation_box (self, &box); + + width = box.x2 - box.x1; + height = box.y2 - box.y1; + + cogl_set_source_color4ub (color->red, + color->green, + color->blue, + color->alpha); + + cogl_rectangle (0, 0, width, height); + } + + /* XXX - this thoroughly sucks, but we need to maintain compatibility + * with existing container classes that override the pick() virtual + * and chain up to the default implementation - otherwise we'll end up + * painting our children twice. + * + * this has to go away for 2.0; hopefully along the pick() itself. + */ + if (CLUTTER_ACTOR_GET_CLASS (self)->pick == clutter_actor_real_pick) + { + ClutterActor *iter; + + for (iter = self->priv->first_child; + iter != NULL; + iter = iter->priv->next_sibling) + clutter_actor_paint (iter); + } +} + +/** + * clutter_actor_should_pick_paint: + * @self: A #ClutterActor + * + * Should be called inside the implementation of the + * #ClutterActor::pick virtual function in order to check whether + * the actor should paint itself in pick mode or not. + * + * This function should never be called directly by applications. + * + * Return value: %TRUE if the actor should paint its silhouette, + * %FALSE otherwise + */ +gboolean +clutter_actor_should_pick_paint (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); + + if (CLUTTER_ACTOR_IS_MAPPED (self) && + (_clutter_context_get_pick_mode () == CLUTTER_PICK_ALL || + CLUTTER_ACTOR_IS_REACTIVE (self))) + return TRUE; + + return FALSE; +} + +static void +clutter_actor_real_get_preferred_width (ClutterActor *self, + gfloat for_height, + gfloat *min_width_p, + gfloat *natural_width_p) +{ + ClutterActorPrivate *priv = self->priv; + + if (priv->n_children != 0 && + priv->layout_manager != NULL) + { + ClutterContainer *container = CLUTTER_CONTAINER (self); + + CLUTTER_NOTE (LAYOUT, "Querying the layout manager '%s'[%p] " + "for the preferred width", + G_OBJECT_TYPE_NAME (priv->layout_manager), + priv->layout_manager); + + clutter_layout_manager_get_preferred_width (priv->layout_manager, + container, + for_height, + min_width_p, + natural_width_p); + + return; + } + + /* Default implementation is always 0x0, usually an actor + * using this default is relying on someone to set the + * request manually + */ + CLUTTER_NOTE (LAYOUT, "Default preferred width: 0, 0"); + + if (min_width_p) + *min_width_p = 0; + + if (natural_width_p) + *natural_width_p = 0; +} + +static void +clutter_actor_real_get_preferred_height (ClutterActor *self, + gfloat for_width, + gfloat *min_height_p, + gfloat *natural_height_p) +{ + ClutterActorPrivate *priv = self->priv; + + if (priv->n_children != 0 && + priv->layout_manager != NULL) + { + ClutterContainer *container = CLUTTER_CONTAINER (self); + + CLUTTER_NOTE (LAYOUT, "Querying the layout manager '%s'[%p] " + "for the preferred height", + G_OBJECT_TYPE_NAME (priv->layout_manager), + priv->layout_manager); + + clutter_layout_manager_get_preferred_height (priv->layout_manager, + container, + for_width, + min_height_p, + natural_height_p); + + return; + } + /* Default implementation is always 0x0, usually an actor + * using this default is relying on someone to set the + * request manually + */ + CLUTTER_NOTE (LAYOUT, "Default preferred height: 0, 0"); + + if (min_height_p) + *min_height_p = 0; + + if (natural_height_p) + *natural_height_p = 0; +} + +static void +clutter_actor_store_old_geometry (ClutterActor *self, + ClutterActorBox *box) +{ + *box = self->priv->allocation; +} + +static inline void +clutter_actor_notify_if_geometry_changed (ClutterActor *self, + const ClutterActorBox *old) +{ + ClutterActorPrivate *priv = self->priv; + GObject *obj = G_OBJECT (self); + + g_object_freeze_notify (obj); + + /* to avoid excessive requisition or allocation cycles we + * use the cached values. + * + * - if we don't have an allocation we assume that we need + * to notify anyway + * - if we don't have a width or a height request we notify + * width and height + * - if we have a valid allocation then we check the old + * bounding box with the current allocation and we notify + * the changes + */ + if (priv->needs_allocation) + { + g_object_notify_by_pspec (obj, obj_props[PROP_X]); + g_object_notify_by_pspec (obj, obj_props[PROP_Y]); + g_object_notify_by_pspec (obj, obj_props[PROP_POSITION]); + g_object_notify_by_pspec (obj, obj_props[PROP_WIDTH]); + g_object_notify_by_pspec (obj, obj_props[PROP_HEIGHT]); + g_object_notify_by_pspec (obj, obj_props[PROP_SIZE]); + } + else if (priv->needs_width_request || priv->needs_height_request) + { + g_object_notify_by_pspec (obj, obj_props[PROP_WIDTH]); + g_object_notify_by_pspec (obj, obj_props[PROP_HEIGHT]); + g_object_notify_by_pspec (obj, obj_props[PROP_SIZE]); + } + else + { + gfloat x, y; + gfloat width, height; + + x = priv->allocation.x1; + y = priv->allocation.y1; + width = priv->allocation.x2 - priv->allocation.x1; + height = priv->allocation.y2 - priv->allocation.y1; + + if (x != old->x1) + { + g_object_notify_by_pspec (obj, obj_props[PROP_X]); + g_object_notify_by_pspec (obj, obj_props[PROP_POSITION]); + } + + if (y != old->y1) + { + g_object_notify_by_pspec (obj, obj_props[PROP_Y]); + g_object_notify_by_pspec (obj, obj_props[PROP_POSITION]); + } + + if (width != (old->x2 - old->x1)) + { + g_object_notify_by_pspec (obj, obj_props[PROP_WIDTH]); + g_object_notify_by_pspec (obj, obj_props[PROP_SIZE]); + } + + if (height != (old->y2 - old->y1)) + { + g_object_notify_by_pspec (obj, obj_props[PROP_HEIGHT]); + g_object_notify_by_pspec (obj, obj_props[PROP_SIZE]); + } + } + + g_object_thaw_notify (obj); +} + +/*< private > + * clutter_actor_set_allocation_internal: + * @self: a #ClutterActor + * @box: a #ClutterActorBox + * @flags: allocation flags + * + * Stores the allocation of @self. + * + * This function only performs basic storage and property notification. + * + * This function should be called by clutter_actor_set_allocation() + * and by the default implementation of #ClutterActorClass.allocate(). + * + * Return value: %TRUE if the allocation of the #ClutterActor has been + * changed, and %FALSE otherwise + */ +static inline gboolean +clutter_actor_set_allocation_internal (ClutterActor *self, + const ClutterActorBox *box, + ClutterAllocationFlags flags) +{ + ClutterActorPrivate *priv = self->priv; + GObject *obj; + gboolean x1_changed, y1_changed, x2_changed, y2_changed; + gboolean retval; + ClutterActorBox old_alloc = { 0, }; + + obj = G_OBJECT (self); + + g_object_freeze_notify (obj); + + clutter_actor_store_old_geometry (self, &old_alloc); + + x1_changed = priv->allocation.x1 != box->x1; + y1_changed = priv->allocation.y1 != box->y1; + x2_changed = priv->allocation.x2 != box->x2; + y2_changed = priv->allocation.y2 != box->y2; + + priv->allocation = *box; + priv->allocation_flags = flags; + + /* allocation is authoritative */ + priv->needs_width_request = FALSE; + priv->needs_height_request = FALSE; + priv->needs_allocation = FALSE; + + if (x1_changed || + y1_changed || + x2_changed || + y2_changed) + { + CLUTTER_NOTE (LAYOUT, "Allocation for '%s' changed", + _clutter_actor_get_debug_name (self)); + + priv->transform_valid = FALSE; + + g_object_notify_by_pspec (obj, obj_props[PROP_ALLOCATION]); + + /* if the allocation changes, so does the content box */ + if (priv->content != NULL) + { + priv->content_box_valid = FALSE; + g_object_notify_by_pspec (obj, obj_props[PROP_CONTENT_BOX]); + } + + retval = TRUE; + } + else + retval = FALSE; + + clutter_actor_notify_if_geometry_changed (self, &old_alloc); + + g_object_thaw_notify (obj); + + return retval; +} + +static void clutter_actor_real_allocate (ClutterActor *self, + const ClutterActorBox *box, + ClutterAllocationFlags flags); + +static inline void +clutter_actor_maybe_layout_children (ClutterActor *self, + const ClutterActorBox *allocation, + ClutterAllocationFlags flags) +{ + ClutterActorPrivate *priv = self->priv; + + /* this is going to be a bit hard to follow, so let's put an explanation + * here. + * + * we want ClutterActor to have a default layout manager if the actor was + * created using "g_object_new (CLUTTER_TYPE_ACTOR, NULL)". + * + * we also want any subclass of ClutterActor that does not override the + * ::allocate() virtual function to delegate to a layout manager. + * + * finally, we want to allow people subclassing ClutterActor and overriding + * the ::allocate() vfunc to let Clutter delegate to the layout manager. + * + * on the other hand, we want existing actor subclasses overriding the + * ::allocate() virtual function and chaining up to the parent's + * implementation to continue working without allocating their children + * twice, or without entering an allocation loop. + * + * for the first two points, we check if the class of the actor is + * overridding the ::allocate() virtual function; if it isn't, then we + * follow through with checking whether we have children and a layout + * manager, and eventually calling clutter_layout_manager_allocate(). + * + * for the third point, we check the CLUTTER_DELEGATE_LAYOUT flag in the + * allocation flags that we got passed, and if it is present, we continue + * with the check above. + * + * if neither of these two checks yields a positive result, we just + * assume that the ::allocate() virtual function that resulted in this + * function being called will also allocate the children of the actor. + */ + + if (CLUTTER_ACTOR_GET_CLASS (self)->allocate == clutter_actor_real_allocate) + goto check_layout; + + if ((flags & CLUTTER_DELEGATE_LAYOUT) != 0) + goto check_layout; + + return; + +check_layout: + if (priv->n_children != 0 && + priv->layout_manager != NULL) + { + ClutterContainer *container = CLUTTER_CONTAINER (self); + ClutterAllocationFlags children_flags; + ClutterActorBox children_box; + + /* normalize the box passed to the layout manager */ + children_box.x1 = children_box.y1 = 0.f; + children_box.x2 = (allocation->x2 - allocation->x1); + children_box.y2 = (allocation->y2 - allocation->y1); + + /* remove the DELEGATE_LAYOUT flag; this won't be passed to + * the actor's children, since it refers only to the current + * actor's allocation. + */ + children_flags = flags; + children_flags &= ~CLUTTER_DELEGATE_LAYOUT; + + CLUTTER_NOTE (LAYOUT, + "Allocating %d children of %s " + "at { %.2f, %.2f - %.2f x %.2f } " + "using %s", + priv->n_children, + _clutter_actor_get_debug_name (self), + allocation->x1, + allocation->y1, + (allocation->x2 - allocation->x1), + (allocation->y2 - allocation->y1), + G_OBJECT_TYPE_NAME (priv->layout_manager)); + + clutter_layout_manager_allocate (priv->layout_manager, + container, + &children_box, + children_flags); + } +} + +static void +clutter_actor_real_allocate (ClutterActor *self, + const ClutterActorBox *box, + ClutterAllocationFlags flags) +{ + ClutterActorPrivate *priv = self->priv; + gboolean changed; + + g_object_freeze_notify (G_OBJECT (self)); + + changed = clutter_actor_set_allocation_internal (self, box, flags); + + /* we allocate our children before we notify changes in our geometry, + * so that people connecting to properties will be able to get valid + * data out of the sub-tree of the scene graph that has this actor at + * the root. + */ + clutter_actor_maybe_layout_children (self, box, flags); + + if (changed) + { + ClutterActorBox signal_box = priv->allocation; + ClutterAllocationFlags signal_flags = priv->allocation_flags; + + g_signal_emit (self, actor_signals[ALLOCATION_CHANGED], 0, + &signal_box, + signal_flags); + } + + g_object_thaw_notify (G_OBJECT (self)); +} + +static void +_clutter_actor_signal_queue_redraw (ClutterActor *self, + ClutterActor *origin) +{ + /* no point in queuing a redraw on a destroyed actor */ + if (CLUTTER_ACTOR_IN_DESTRUCTION (self)) + return; + + /* NB: We can't bail out early here if the actor is hidden in case + * the actor bas been cloned. In this case the clone will need to + * receive the signal so it can queue its own redraw. + */ + + _clutter_actor_queue_redraw_on_clones (self); + + /* calls klass->queue_redraw in default handler */ + g_signal_emit (self, actor_signals[QUEUE_REDRAW], 0, origin); +} + +static void +clutter_actor_real_queue_redraw (ClutterActor *self, + ClutterActor *origin) +{ + ClutterActor *parent; + + CLUTTER_NOTE (PAINT, "Redraw queued on '%s' (from: '%s')", + _clutter_actor_get_debug_name (self), + origin != NULL ? _clutter_actor_get_debug_name (origin) + : "same actor"); + + /* no point in queuing a redraw on a destroyed actor */ + if (CLUTTER_ACTOR_IN_DESTRUCTION (self)) + return; + + /* If the queue redraw is coming from a child then the actor has + become dirty and any queued effect is no longer valid */ + if (self != origin) + { + self->priv->is_dirty = TRUE; + self->priv->effect_to_redraw = NULL; + } + + /* If the actor isn't visible, we still had to emit the signal + * to allow for a ClutterClone, but the appearance of the parent + * won't change so we don't have to propagate up the hierarchy. + */ + if (!CLUTTER_ACTOR_IS_VISIBLE (self)) + return; + + /* Although we could determine here that a full stage redraw + * has already been queued and immediately bail out, we actually + * guarantee that we will propagate a queue-redraw signal to our + * parent at least once so that it's possible to implement a + * container that tracks which of its children have queued a + * redraw. + */ + if (self->priv->propagated_one_redraw) + { + ClutterActor *stage = _clutter_actor_get_stage_internal (self); + if (stage != NULL && + _clutter_stage_has_full_redraw_queued (CLUTTER_STAGE (stage))) + return; + } + + self->priv->propagated_one_redraw = TRUE; + + /* notify parents, if they are all visible eventually we'll + * queue redraw on the stage, which queues the redraw idle. + */ + parent = clutter_actor_get_parent (self); + if (parent != NULL) + { + /* this will go up recursively */ + _clutter_actor_signal_queue_redraw (parent, origin); + } +} + +static void +clutter_actor_real_queue_relayout (ClutterActor *self) +{ + ClutterActorPrivate *priv = self->priv; + + /* no point in queueing a redraw on a destroyed actor */ + if (CLUTTER_ACTOR_IN_DESTRUCTION (self)) + return; + + priv->needs_width_request = TRUE; + priv->needs_height_request = TRUE; + priv->needs_allocation = TRUE; + + /* reset the cached size requests */ + memset (priv->width_requests, 0, + N_CACHED_SIZE_REQUESTS * sizeof (SizeRequest)); + memset (priv->height_requests, 0, + N_CACHED_SIZE_REQUESTS * sizeof (SizeRequest)); + + /* We need to go all the way up the hierarchy */ + if (priv->parent != NULL) + _clutter_actor_queue_only_relayout (priv->parent); +} + +/** + * clutter_actor_apply_relative_transform_to_point: + * @self: A #ClutterActor + * @ancestor: (allow-none): A #ClutterActor ancestor, or %NULL to use the + * default #ClutterStage + * @point: A point as #ClutterVertex + * @vertex: (out caller-allocates): The translated #ClutterVertex + * + * Transforms @point in coordinates relative to the actor into + * ancestor-relative coordinates using the relevant transform + * stack (i.e. scale, rotation, etc). + * + * If @ancestor is %NULL the ancestor will be the #ClutterStage. In + * this case, the coordinates returned will be the coordinates on + * the stage before the projection is applied. This is different from + * the behaviour of clutter_actor_apply_transform_to_point(). + * + * Since: 0.6 + */ +void +clutter_actor_apply_relative_transform_to_point (ClutterActor *self, + ClutterActor *ancestor, + const ClutterVertex *point, + ClutterVertex *vertex) +{ + gfloat w; + CoglMatrix matrix; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (ancestor == NULL || CLUTTER_IS_ACTOR (ancestor)); + g_return_if_fail (point != NULL); + g_return_if_fail (vertex != NULL); + + *vertex = *point; + w = 1.0; + + if (ancestor == NULL) + ancestor = _clutter_actor_get_stage_internal (self); + + if (ancestor == NULL) + { + *vertex = *point; + return; + } + + _clutter_actor_get_relative_transformation_matrix (self, ancestor, &matrix); + cogl_matrix_transform_point (&matrix, &vertex->x, &vertex->y, &vertex->z, &w); +} + +static gboolean +_clutter_actor_fully_transform_vertices (ClutterActor *self, + const ClutterVertex *vertices_in, + ClutterVertex *vertices_out, + int n_vertices) +{ + ClutterActor *stage; + CoglMatrix modelview; + CoglMatrix projection; + float viewport[4]; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); + + stage = _clutter_actor_get_stage_internal (self); + + /* We really can't do anything meaningful in this case so don't try + * to do any transform */ + if (stage == NULL) + return FALSE; + + /* Note: we pass NULL as the ancestor because we don't just want the modelview + * that gets us to stage coordinates, we want to go all the way to eye + * coordinates */ + _clutter_actor_apply_relative_transformation_matrix (self, NULL, &modelview); + + /* Fetch the projection and viewport */ + _clutter_stage_get_projection_matrix (CLUTTER_STAGE (stage), &projection); + _clutter_stage_get_viewport (CLUTTER_STAGE (stage), + &viewport[0], + &viewport[1], + &viewport[2], + &viewport[3]); + + _clutter_util_fully_transform_vertices (&modelview, + &projection, + viewport, + vertices_in, + vertices_out, + n_vertices); + + return TRUE; +} + +/** + * clutter_actor_apply_transform_to_point: + * @self: A #ClutterActor + * @point: A point as #ClutterVertex + * @vertex: (out caller-allocates): The translated #ClutterVertex + * + * Transforms @point in coordinates relative to the actor + * into screen-relative coordinates with the current actor + * transformation (i.e. scale, rotation, etc) + * + * Since: 0.4 + **/ +void +clutter_actor_apply_transform_to_point (ClutterActor *self, + const ClutterVertex *point, + ClutterVertex *vertex) +{ + g_return_if_fail (point != NULL); + g_return_if_fail (vertex != NULL); + _clutter_actor_fully_transform_vertices (self, point, vertex, 1); +} + +/* + * _clutter_actor_get_relative_transformation_matrix: + * @self: The actor whose coordinate space you want to transform from. + * @ancestor: The ancestor actor whose coordinate space you want to transform too + * or %NULL if you want to transform all the way to eye coordinates. + * @matrix: A #CoglMatrix to store the transformation + * + * This gets a transformation @matrix that will transform coordinates from the + * coordinate space of @self into the coordinate space of @ancestor. + * + * For example if you need a matrix that can transform the local actor + * coordinates of @self into stage coordinates you would pass the actor's stage + * pointer as the @ancestor. + * + * If you pass %NULL then the transformation will take you all the way through + * to eye coordinates. This can be useful if you want to extract the entire + * modelview transform that Clutter applies before applying the projection + * transformation. If you want to explicitly set a modelview on a CoglFramebuffer + * using cogl_set_modelview_matrix() for example then you would want a matrix + * that transforms into eye coordinates. + * + * Note: This function explicitly initializes the given @matrix. If you just + * want clutter to multiply a relative transformation with an existing matrix + * you can use clutter_actor_apply_relative_transformation_matrix() + * instead. + * + */ +/* XXX: We should consider caching the stage relative modelview along with + * the actor itself */ +static void +_clutter_actor_get_relative_transformation_matrix (ClutterActor *self, + ClutterActor *ancestor, + CoglMatrix *matrix) +{ + cogl_matrix_init_identity (matrix); + + _clutter_actor_apply_relative_transformation_matrix (self, ancestor, matrix); +} + +/* Project the given @box into stage window coordinates, writing the + * transformed vertices to @verts[]. */ +static gboolean +_clutter_actor_transform_and_project_box (ClutterActor *self, + const ClutterActorBox *box, + ClutterVertex verts[]) +{ + ClutterVertex box_vertices[4]; + + box_vertices[0].x = box->x1; + box_vertices[0].y = box->y1; + box_vertices[0].z = 0; + box_vertices[1].x = box->x2; + box_vertices[1].y = box->y1; + box_vertices[1].z = 0; + box_vertices[2].x = box->x1; + box_vertices[2].y = box->y2; + box_vertices[2].z = 0; + box_vertices[3].x = box->x2; + box_vertices[3].y = box->y2; + box_vertices[3].z = 0; + + return + _clutter_actor_fully_transform_vertices (self, box_vertices, verts, 4); +} + +/** + * clutter_actor_get_allocation_vertices: + * @self: A #ClutterActor + * @ancestor: (allow-none): A #ClutterActor to calculate the vertices + * against, or %NULL to use the #ClutterStage + * @verts: (out) (array fixed-size=4) (element-type Clutter.Vertex): return + * location for an array of 4 #ClutterVertex in which to store the result + * + * Calculates the transformed coordinates of the four corners of the + * actor in the plane of @ancestor. The returned vertices relate to + * the #ClutterActorBox coordinates as follows: + * + * - @verts[0] contains (x1, y1) + * - @verts[1] contains (x2, y1) + * - @verts[2] contains (x1, y2) + * - @verts[3] contains (x2, y2) + * + * If @ancestor is %NULL the ancestor will be the #ClutterStage. In + * this case, the coordinates returned will be the coordinates on + * the stage before the projection is applied. This is different from + * the behaviour of clutter_actor_get_abs_allocation_vertices(). + * + * Since: 0.6 + */ +void +clutter_actor_get_allocation_vertices (ClutterActor *self, + ClutterActor *ancestor, + ClutterVertex verts[]) +{ + ClutterActorPrivate *priv; + ClutterActorBox box; + ClutterVertex vertices[4]; + CoglMatrix modelview; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (ancestor == NULL || CLUTTER_IS_ACTOR (ancestor)); + + if (ancestor == NULL) + ancestor = _clutter_actor_get_stage_internal (self); + + /* Fallback to a NOP transform if the actor isn't parented under a + * stage. */ + if (ancestor == NULL) + ancestor = self; + + priv = self->priv; + + /* if the actor needs to be allocated we force a relayout, so that + * we will have valid values to use in the transformations */ + if (priv->needs_allocation) + { + ClutterActor *stage = _clutter_actor_get_stage_internal (self); + if (stage) + _clutter_stage_maybe_relayout (stage); + else + { + box.x1 = box.y1 = 0; + /* The result isn't really meaningful in this case but at + * least try to do something *vaguely* reasonable... */ + clutter_actor_get_size (self, &box.x2, &box.y2); + } + } + + clutter_actor_get_allocation_box (self, &box); + + vertices[0].x = box.x1; + vertices[0].y = box.y1; + vertices[0].z = 0; + vertices[1].x = box.x2; + vertices[1].y = box.y1; + vertices[1].z = 0; + vertices[2].x = box.x1; + vertices[2].y = box.y2; + vertices[2].z = 0; + vertices[3].x = box.x2; + vertices[3].y = box.y2; + vertices[3].z = 0; + + _clutter_actor_get_relative_transformation_matrix (self, ancestor, + &modelview); + + cogl_matrix_transform_points (&modelview, + 3, + sizeof (ClutterVertex), + vertices, + sizeof (ClutterVertex), + vertices, + 4); +} + +/** + * clutter_actor_get_abs_allocation_vertices: + * @self: A #ClutterActor + * @verts: (out) (array fixed-size=4): Pointer to a location of an array + * of 4 #ClutterVertex where to store the result. + * + * Calculates the transformed screen coordinates of the four corners of + * the actor; the returned vertices relate to the #ClutterActorBox + * coordinates as follows: + * + * - v[0] contains (x1, y1) + * - v[1] contains (x2, y1) + * - v[2] contains (x1, y2) + * - v[3] contains (x2, y2) + * + * Since: 0.4 + */ +void +clutter_actor_get_abs_allocation_vertices (ClutterActor *self, + ClutterVertex verts[]) +{ + ClutterActorPrivate *priv; + ClutterActorBox actor_space_allocation; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + priv = self->priv; + + /* if the actor needs to be allocated we force a relayout, so that + * the actor allocation box will be valid for + * _clutter_actor_transform_and_project_box() + */ + if (priv->needs_allocation) + { + ClutterActor *stage = _clutter_actor_get_stage_internal (self); + /* There's nothing meaningful we can do now */ + if (!stage) + return; + + _clutter_stage_maybe_relayout (stage); + } + + /* NB: _clutter_actor_transform_and_project_box expects a box in the actor's + * own coordinate space... */ + actor_space_allocation.x1 = 0; + actor_space_allocation.y1 = 0; + actor_space_allocation.x2 = priv->allocation.x2 - priv->allocation.x1; + actor_space_allocation.y2 = priv->allocation.y2 - priv->allocation.y1; + _clutter_actor_transform_and_project_box (self, + &actor_space_allocation, + verts); +} + +static void +clutter_actor_real_apply_transform (ClutterActor *self, + ClutterMatrix *matrix) +{ + ClutterActorPrivate *priv = self->priv; + CoglMatrix *transform = &priv->transform; + const ClutterTransformInfo *info; + float pivot_x = 0.f, pivot_y = 0.f; + + /* we already have a cached transformation */ + if (priv->transform_valid) + goto multiply_and_return; + + info = _clutter_actor_get_transform_info_or_defaults (self); + + /* compute the pivot point given the allocated size */ + pivot_x = (priv->allocation.x2 - priv->allocation.x1) + * info->pivot.x; + pivot_y = (priv->allocation.y2 - priv->allocation.y1) + * info->pivot.y; + + CLUTTER_NOTE (PAINT, + "Allocation: (%.2f, %2.f), " + "pivot: (%.2f, %.2f), " + "translation: (%.2f, %.2f) -> " + "new origin: (%.2f, %.2f)", + priv->allocation.x1, priv->allocation.y1, + info->pivot.x, info->pivot.y, + info->translation.x, info->translation.y, + priv->allocation.x1 + pivot_x + info->translation.x, + priv->allocation.y1 + pivot_y + info->translation.y); + + /* we apply the :child-transform from the parent actor, if we have one */ + if (priv->parent != NULL) + { + const ClutterTransformInfo *parent_info; + + parent_info = _clutter_actor_get_transform_info_or_defaults (priv->parent); + clutter_matrix_init_from_matrix (transform, &(parent_info->child_transform)); + } + else + clutter_matrix_init_identity (transform); + + /* if we have an overriding transformation, we use that, and get out */ + if (info->transform_set) + { + /* we still need to apply the :allocation's origin and :pivot-point + * translations, since :transform is relative to the actor's coordinate + * space, and to the pivot point + */ + cogl_matrix_translate (transform, + priv->allocation.x1 + pivot_x, + priv->allocation.y1 + pivot_y, + info->pivot_z); + cogl_matrix_multiply (transform, transform, &info->transform); + goto roll_back_pivot; + } + + /* basic translation: :allocation's origin and :z-position; instead + * of decomposing the pivot and translation info separate operations, + * we just compose everything into a single translation + */ + cogl_matrix_translate (transform, + priv->allocation.x1 + pivot_x + info->translation.x, + priv->allocation.y1 + pivot_y + info->translation.y, + info->z_position + info->pivot_z + info->translation.z); + + /* because the rotation involves translations, we must scale + * before applying the rotations (if we apply the scale after + * the rotations, the translations included in the rotation are + * not scaled and so the entire object will move on the screen + * as a result of rotating it). + * + * XXX:2.0 the comment has to be reworded once we remove the + * per-transformation centers; we also may want to apply rotation + * first and scaling after, to match the matrix decomposition + * code we use when interpolating transformations + */ + if (info->scale_x != 1.0 || info->scale_y != 1.0 || info->scale_z != 1.0) + { + /* XXX:2.0 remove anchor coord */ + TRANSFORM_ABOUT_ANCHOR_COORD (self, transform, + &info->scale_center, + cogl_matrix_scale (transform, + info->scale_x, + info->scale_y, + info->scale_z)); + } + + if (info->rz_angle) + { + /* XXX:2.0 remove anchor coord */ + TRANSFORM_ABOUT_ANCHOR_COORD (self, transform, + &info->rz_center, + cogl_matrix_rotate (transform, + info->rz_angle, + 0, 0, 1.0)); + } + + if (info->ry_angle) + { + /* XXX:2.0 remove anchor coord */ + TRANSFORM_ABOUT_ANCHOR_COORD (self, transform, + &info->ry_center, + cogl_matrix_rotate (transform, + info->ry_angle, + 0, 1.0, 0)); + } + + if (info->rx_angle) + { + /* XXX:2.0 remove anchor coord */ + TRANSFORM_ABOUT_ANCHOR_COORD (self, transform, + &info->rx_center, + cogl_matrix_rotate (transform, + info->rx_angle, + 1.0, 0, 0)); + } + + /* XXX:2.0 remove anchor point translation */ + if (!clutter_anchor_coord_is_zero (&info->anchor)) + { + gfloat x, y, z; + + clutter_anchor_coord_get_units (self, &info->anchor, &x, &y, &z); + cogl_matrix_translate (transform, -x, -y, -z); + } + +roll_back_pivot: + /* roll back the pivot translation */ + if (pivot_x != 0.f || pivot_y != 0.f || info->pivot_z != 0.f) + cogl_matrix_translate (transform, -pivot_x, -pivot_y, -info->pivot_z); + + /* we have a valid modelview */ + priv->transform_valid = TRUE; + +multiply_and_return: + cogl_matrix_multiply (matrix, matrix, &priv->transform); +} + +/* Applies the transforms associated with this actor to the given + * matrix. */ +void +_clutter_actor_apply_modelview_transform (ClutterActor *self, + ClutterMatrix *matrix) +{ + CLUTTER_ACTOR_GET_CLASS (self)->apply_transform (self, matrix); +} + +/* + * clutter_actor_apply_relative_transformation_matrix: + * @self: The actor whose coordinate space you want to transform from. + * @ancestor: The ancestor actor whose coordinate space you want to transform too + * or %NULL if you want to transform all the way to eye coordinates. + * @matrix: A #ClutterMatrix to apply the transformation too. + * + * This multiplies a transform with @matrix that will transform coordinates + * from the coordinate space of @self into the coordinate space of @ancestor. + * + * For example if you need a matrix that can transform the local actor + * coordinates of @self into stage coordinates you would pass the actor's stage + * pointer as the @ancestor. + * + * If you pass %NULL then the transformation will take you all the way through + * to eye coordinates. This can be useful if you want to extract the entire + * modelview transform that Clutter applies before applying the projection + * transformation. If you want to explicitly set a modelview on a CoglFramebuffer + * using cogl_set_modelview_matrix() for example then you would want a matrix + * that transforms into eye coordinates. + * + * This function doesn't initialize the given @matrix, it simply + * multiplies the requested transformation matrix with the existing contents of + * @matrix. You can use cogl_matrix_init_identity() to initialize the @matrix + * before calling this function, or you can use + * clutter_actor_get_relative_transformation_matrix() instead. + */ +void +_clutter_actor_apply_relative_transformation_matrix (ClutterActor *self, + ClutterActor *ancestor, + CoglMatrix *matrix) +{ + ClutterActor *parent; + + /* Note we terminate before ever calling stage->apply_transform() + * since that would conceptually be relative to the underlying + * window OpenGL coordinates so we'd need a special @ancestor + * value to represent the fake parent of the stage. */ + if (self == ancestor) + return; + + parent = clutter_actor_get_parent (self); + + if (parent != NULL) + _clutter_actor_apply_relative_transformation_matrix (parent, ancestor, + matrix); + + _clutter_actor_apply_modelview_transform (self, matrix); +} + +static void +_clutter_actor_draw_paint_volume_full (ClutterActor *self, + ClutterPaintVolume *pv, + const char *label, + const CoglColor *color) +{ + static CoglPipeline *outline = NULL; + CoglPrimitive *prim; + ClutterVertex line_ends[12 * 2]; + int n_vertices; + CoglContext *ctx = + clutter_backend_get_cogl_context (clutter_get_default_backend ()); + /* XXX: at some point we'll query this from the stage but we can't + * do that until the osx backend uses Cogl natively. */ + CoglFramebuffer *fb = cogl_get_draw_framebuffer (); + + if (outline == NULL) + outline = cogl_pipeline_new (ctx); + + _clutter_paint_volume_complete (pv); + + n_vertices = pv->is_2d ? 4 * 2 : 12 * 2; + + /* Front face */ + line_ends[0] = pv->vertices[0]; line_ends[1] = pv->vertices[1]; + line_ends[2] = pv->vertices[1]; line_ends[3] = pv->vertices[2]; + line_ends[4] = pv->vertices[2]; line_ends[5] = pv->vertices[3]; + line_ends[6] = pv->vertices[3]; line_ends[7] = pv->vertices[0]; + + if (!pv->is_2d) + { + /* Back face */ + line_ends[8] = pv->vertices[4]; line_ends[9] = pv->vertices[5]; + line_ends[10] = pv->vertices[5]; line_ends[11] = pv->vertices[6]; + line_ends[12] = pv->vertices[6]; line_ends[13] = pv->vertices[7]; + line_ends[14] = pv->vertices[7]; line_ends[15] = pv->vertices[4]; + + /* Lines connecting front face to back face */ + line_ends[16] = pv->vertices[0]; line_ends[17] = pv->vertices[4]; + line_ends[18] = pv->vertices[1]; line_ends[19] = pv->vertices[5]; + line_ends[20] = pv->vertices[2]; line_ends[21] = pv->vertices[6]; + line_ends[22] = pv->vertices[3]; line_ends[23] = pv->vertices[7]; + } + + prim = cogl_primitive_new_p3 (ctx, COGL_VERTICES_MODE_LINES, + n_vertices, + (CoglVertexP3 *)line_ends); + + cogl_pipeline_set_color (outline, color); + cogl_framebuffer_draw_primitive (fb, outline, prim); + cogl_object_unref (prim); + + if (label) + { + PangoLayout *layout; + layout = pango_layout_new (clutter_actor_get_pango_context (self)); + pango_layout_set_text (layout, label, -1); + cogl_pango_render_layout (layout, + pv->vertices[0].x, + pv->vertices[0].y, + color, + 0); + g_object_unref (layout); + } +} + +static void +_clutter_actor_draw_paint_volume (ClutterActor *self) +{ + ClutterPaintVolume *pv; + CoglColor color; + + pv = _clutter_actor_get_paint_volume_mutable (self); + if (!pv) + { + gfloat width, height; + ClutterPaintVolume fake_pv; + + ClutterActor *stage = _clutter_actor_get_stage_internal (self); + _clutter_paint_volume_init_static (&fake_pv, stage); + + clutter_actor_get_size (self, &width, &height); + clutter_paint_volume_set_width (&fake_pv, width); + clutter_paint_volume_set_height (&fake_pv, height); + + cogl_color_init_from_4f (&color, 0, 0, 1, 1); + _clutter_actor_draw_paint_volume_full (self, &fake_pv, + _clutter_actor_get_debug_name (self), + &color); + + clutter_paint_volume_free (&fake_pv); + } + else + { + cogl_color_init_from_4f (&color, 0, 1, 0, 1); + _clutter_actor_draw_paint_volume_full (self, pv, + _clutter_actor_get_debug_name (self), + &color); + } +} + +static void +_clutter_actor_paint_cull_result (ClutterActor *self, + gboolean success, + ClutterCullResult result) +{ + ClutterPaintVolume *pv; + CoglColor color; + + if (success) + { + if (result == CLUTTER_CULL_RESULT_IN) + cogl_color_init_from_4f (&color, 0, 1, 0, 1); + else if (result == CLUTTER_CULL_RESULT_OUT) + cogl_color_init_from_4f (&color, 0, 0, 1, 1); + else + cogl_color_init_from_4f (&color, 0, 1, 1, 1); + } + else + cogl_color_init_from_4f (&color, 1, 1, 1, 1); + + if (success && (pv = _clutter_actor_get_paint_volume_mutable (self))) + _clutter_actor_draw_paint_volume_full (self, pv, + _clutter_actor_get_debug_name (self), + &color); + else + { + PangoLayout *layout; + char *label = + g_strdup_printf ("CULL FAILURE: %s", _clutter_actor_get_debug_name (self)); + cogl_color_init_from_4f (&color, 1, 1, 1, 1); + cogl_set_source_color (&color); + + layout = pango_layout_new (clutter_actor_get_pango_context (self)); + pango_layout_set_text (layout, label, -1); + cogl_pango_render_layout (layout, + 0, + 0, + &color, + 0); + g_free (label); + g_object_unref (layout); + } +} + +static int clone_paint_level = 0; + +void +_clutter_actor_push_clone_paint (void) +{ + clone_paint_level++; +} + +void +_clutter_actor_pop_clone_paint (void) +{ + clone_paint_level--; +} + +static gboolean +in_clone_paint (void) +{ + return clone_paint_level > 0; +} + +/* Returns TRUE if the actor can be ignored */ +/* FIXME: we should return a ClutterCullResult, and + * clutter_actor_paint should understand that a CLUTTER_CULL_RESULT_IN + * means there's no point in trying to cull descendants of the current + * node. */ +static gboolean +cull_actor (ClutterActor *self, + ClutterCullResult *result_out) +{ + ClutterActorPrivate *priv = self->priv; + ClutterStage *stage; + const ClutterPlane *stage_clip; + + if (!priv->last_paint_volume_valid) + { + CLUTTER_NOTE (CLIPPING, "Bail from cull_actor without culling (%s): " + "->last_paint_volume_valid == FALSE", + _clutter_actor_get_debug_name (self)); + return FALSE; + } + + if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_DISABLE_CULLING)) + return FALSE; + + stage = (ClutterStage *) _clutter_actor_get_stage_internal (self); + stage_clip = _clutter_stage_get_clip (stage); + if (G_UNLIKELY (!stage_clip)) + { + CLUTTER_NOTE (CLIPPING, "Bail from cull_actor without culling (%s): " + "No stage clip set", + _clutter_actor_get_debug_name (self)); + return FALSE; + } + + if (cogl_get_draw_framebuffer () != _clutter_stage_get_active_framebuffer (stage)) + { + CLUTTER_NOTE (CLIPPING, "Bail from cull_actor without culling (%s): " + "Current framebuffer doesn't correspond to stage", + _clutter_actor_get_debug_name (self)); + return FALSE; + } + + *result_out = + _clutter_paint_volume_cull (&priv->last_paint_volume, stage_clip); + + return TRUE; +} + +static void +_clutter_actor_update_last_paint_volume (ClutterActor *self) +{ + ClutterActorPrivate *priv = self->priv; + const ClutterPaintVolume *pv; + + if (priv->last_paint_volume_valid) + { + clutter_paint_volume_free (&priv->last_paint_volume); + priv->last_paint_volume_valid = FALSE; + } + + pv = clutter_actor_get_paint_volume (self); + if (!pv) + { + CLUTTER_NOTE (CLIPPING, "Bail from update_last_paint_volume (%s): " + "Actor failed to report a paint volume", + _clutter_actor_get_debug_name (self)); + return; + } + + _clutter_paint_volume_copy_static (pv, &priv->last_paint_volume); + + _clutter_paint_volume_transform_relative (&priv->last_paint_volume, + NULL); /* eye coordinates */ + + priv->last_paint_volume_valid = TRUE; +} + +static inline gboolean +actor_has_shader_data (ClutterActor *self) +{ + return g_object_get_qdata (G_OBJECT (self), quark_shader_data) != NULL; +} + +guint32 +_clutter_actor_get_pick_id (ClutterActor *self) +{ + if (self->priv->pick_id < 0) + return 0; + + return self->priv->pick_id; +} + +/* This is the same as clutter_actor_add_effect except that it doesn't + queue a redraw and it doesn't notify on the effect property */ +static void +_clutter_actor_add_effect_internal (ClutterActor *self, + ClutterEffect *effect) +{ + ClutterActorPrivate *priv = self->priv; + + if (priv->effects == NULL) + { + priv->effects = g_object_new (CLUTTER_TYPE_META_GROUP, NULL); + priv->effects->actor = self; + } + + _clutter_meta_group_add_meta (priv->effects, CLUTTER_ACTOR_META (effect)); +} + +/* This is the same as clutter_actor_remove_effect except that it doesn't + queue a redraw and it doesn't notify on the effect property */ +static void +_clutter_actor_remove_effect_internal (ClutterActor *self, + ClutterEffect *effect) +{ + ClutterActorPrivate *priv = self->priv; + + if (priv->effects == NULL) + return; + + _clutter_meta_group_remove_meta (priv->effects, CLUTTER_ACTOR_META (effect)); + + if (_clutter_meta_group_peek_metas (priv->effects) == NULL) + g_clear_object (&priv->effects); +} + +static gboolean +needs_flatten_effect (ClutterActor *self) +{ + ClutterActorPrivate *priv = self->priv; + + if (G_UNLIKELY (clutter_paint_debug_flags & + CLUTTER_DEBUG_DISABLE_OFFSCREEN_REDIRECT)) + return FALSE; + + if (priv->offscreen_redirect & CLUTTER_OFFSCREEN_REDIRECT_ALWAYS) + return TRUE; + else if (priv->offscreen_redirect & CLUTTER_OFFSCREEN_REDIRECT_AUTOMATIC_FOR_OPACITY) + { + if (clutter_actor_get_paint_opacity (self) < 255 && + clutter_actor_has_overlaps (self)) + return TRUE; + } + + return FALSE; +} + +static void +add_or_remove_flatten_effect (ClutterActor *self) +{ + ClutterActorPrivate *priv = self->priv; + + /* Add or remove the flatten effect depending on the + offscreen-redirect property. */ + if (needs_flatten_effect (self)) + { + if (priv->flatten_effect == NULL) + { + ClutterActorMeta *actor_meta; + gint priority; + + priv->flatten_effect = _clutter_flatten_effect_new (); + /* Keep a reference to the effect so that we can queue + redraws from it */ + g_object_ref_sink (priv->flatten_effect); + + /* Set the priority of the effect to high so that it will + always be applied to the actor first. It uses an internal + priority so that it won't be visible to applications */ + actor_meta = CLUTTER_ACTOR_META (priv->flatten_effect); + priority = CLUTTER_ACTOR_META_PRIORITY_INTERNAL_HIGH; + _clutter_actor_meta_set_priority (actor_meta, priority); + + /* This will add the effect without queueing a redraw */ + _clutter_actor_add_effect_internal (self, priv->flatten_effect); + } + } + else + { + if (priv->flatten_effect != NULL) + { + /* Destroy the effect so that it will lose its fbo cache of + the actor */ + _clutter_actor_remove_effect_internal (self, priv->flatten_effect); + g_clear_object (&priv->flatten_effect); + } + } +} + +static void +clutter_actor_real_paint (ClutterActor *actor) +{ + ClutterActorPrivate *priv = actor->priv; + ClutterActor *iter; + + for (iter = priv->first_child; + iter != NULL; + iter = iter->priv->next_sibling) + { + CLUTTER_NOTE (PAINT, "Painting %s, child of %s, at { %.2f, %.2f - %.2f x %.2f }", + _clutter_actor_get_debug_name (iter), + _clutter_actor_get_debug_name (actor), + iter->priv->allocation.x1, + iter->priv->allocation.y1, + iter->priv->allocation.x2 - iter->priv->allocation.x1, + iter->priv->allocation.y2 - iter->priv->allocation.y1); + + clutter_actor_paint (iter); + } +} + +static gboolean +clutter_actor_paint_node (ClutterActor *actor, + ClutterPaintNode *root) +{ + ClutterActorPrivate *priv = actor->priv; + ClutterActorBox box; + ClutterColor bg_color; + + if (root == NULL) + return FALSE; + + box.x1 = 0.f; + box.y1 = 0.f; + box.x2 = clutter_actor_box_get_width (&priv->allocation); + box.y2 = clutter_actor_box_get_height (&priv->allocation); + + bg_color = priv->bg_color; + + if (CLUTTER_ACTOR_IS_TOPLEVEL (actor)) + { + ClutterPaintNode *node; + CoglFramebuffer *fb; + CoglBufferBit clear_flags; + + fb = _clutter_stage_get_active_framebuffer (CLUTTER_STAGE (actor)); + + if (clutter_stage_get_use_alpha (CLUTTER_STAGE (actor))) + { + bg_color.alpha = priv->opacity + * priv->bg_color.alpha + / 255; + } + else + bg_color.alpha = 255; + + CLUTTER_NOTE (PAINT, "Stage clear color: (%d, %d, %d, %d)", + bg_color.red, + bg_color.green, + bg_color.blue, + bg_color.alpha); + + clear_flags = COGL_BUFFER_BIT_DEPTH; + if (!clutter_stage_get_no_clear_hint (CLUTTER_STAGE (actor))) + clear_flags |= COGL_BUFFER_BIT_COLOR; + + node = _clutter_root_node_new (fb, &bg_color, clear_flags); + clutter_paint_node_set_name (node, "stageClear"); + clutter_paint_node_add_rectangle (node, &box); + clutter_paint_node_add_child (root, node); + clutter_paint_node_unref (node); + } + else if (priv->bg_color_set && + !clutter_color_equal (&priv->bg_color, CLUTTER_COLOR_Transparent)) + { + ClutterPaintNode *node; + + bg_color.alpha = clutter_actor_get_paint_opacity_internal (actor) + * priv->bg_color.alpha + / 255; + + node = clutter_color_node_new (&bg_color); + clutter_paint_node_set_name (node, "backgroundColor"); + clutter_paint_node_add_rectangle (node, &box); + clutter_paint_node_add_child (root, node); + clutter_paint_node_unref (node); + } + + if (priv->content != NULL) + _clutter_content_paint_content (priv->content, actor, root); + + if (CLUTTER_ACTOR_GET_CLASS (actor)->paint_node != NULL) + CLUTTER_ACTOR_GET_CLASS (actor)->paint_node (actor, root); + + if (clutter_paint_node_get_n_children (root) == 0) + return FALSE; + +#ifdef CLUTTER_ENABLE_DEBUG + if (CLUTTER_HAS_DEBUG (PAINT)) + { + /* dump the tree only if we have one */ + _clutter_paint_node_dump_tree (root); + } +#endif /* CLUTTER_ENABLE_DEBUG */ + + _clutter_paint_node_paint (root); + + return TRUE; +} + +/** + * clutter_actor_paint: + * @self: A #ClutterActor + * + * Renders the actor to display. + * + * This function should not be called directly by applications. + * Call clutter_actor_queue_redraw() to queue paints, instead. + * + * This function is context-aware, and will either cause a + * regular paint or a pick paint. + * + * This function will emit the #ClutterActor::paint signal or + * the #ClutterActor::pick signal, depending on the context. + * + * This function does not paint the actor if the actor is set to 0, + * unless it is performing a pick paint. + */ +void +clutter_actor_paint (ClutterActor *self) +{ + ClutterActorPrivate *priv; + ClutterPickMode pick_mode; + gboolean clip_set = FALSE; + gboolean shader_applied = FALSE; + ClutterStage *stage; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + if (CLUTTER_ACTOR_IN_DESTRUCTION (self)) + return; + + priv = self->priv; + + pick_mode = _clutter_context_get_pick_mode (); + + if (pick_mode == CLUTTER_PICK_NONE) + priv->propagated_one_redraw = FALSE; + + /* It's an important optimization that we consider painting of + * actors with 0 opacity to be a NOP... */ + if (pick_mode == CLUTTER_PICK_NONE && + /* ignore top-levels, since they might be transparent */ + !CLUTTER_ACTOR_IS_TOPLEVEL (self) && + /* Use the override opacity if its been set */ + ((priv->opacity_override >= 0) ? + priv->opacity_override : priv->opacity) == 0) + return; + + /* if we aren't paintable (not in a toplevel with all + * parents paintable) then do nothing. + */ + if (!CLUTTER_ACTOR_IS_MAPPED (self)) + return; + + stage = (ClutterStage *) _clutter_actor_get_stage_internal (self); + + /* mark that we are in the paint process */ + CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_IN_PAINT); + + cogl_push_matrix (); + + if (priv->enable_model_view_transform) + { + CoglMatrix matrix; + + /* XXX: It could be better to cache the modelview with the actor + * instead of progressively building up the transformations on + * the matrix stack every time we paint. */ + cogl_get_modelview_matrix (&matrix); + _clutter_actor_apply_modelview_transform (self, &matrix); + +#ifdef CLUTTER_ENABLE_DEBUG + /* Catch when out-of-band transforms have been made by actors not as part + * of an apply_transform vfunc... */ + if (G_UNLIKELY (clutter_debug_flags & CLUTTER_DEBUG_OOB_TRANSFORMS)) + { + CoglMatrix expected_matrix; + + _clutter_actor_get_relative_transformation_matrix (self, NULL, + &expected_matrix); + + if (!cogl_matrix_equal (&matrix, &expected_matrix)) + { + GString *buf = g_string_sized_new (1024); + ClutterActor *parent; + + parent = self; + while (parent != NULL) + { + g_string_append (buf, _clutter_actor_get_debug_name (parent)); + + if (parent->priv->parent != NULL) + g_string_append (buf, "->"); + + parent = parent->priv->parent; + } + + g_warning ("Unexpected transform found when painting actor " + "\"%s\". This will be caused by one of the actor's " + "ancestors (%s) using the Cogl API directly to transform " + "children instead of using ::apply_transform().", + _clutter_actor_get_debug_name (self), + buf->str); + + g_string_free (buf, TRUE); + } + } +#endif /* CLUTTER_ENABLE_DEBUG */ + + cogl_set_modelview_matrix (&matrix); + } + + if (priv->has_clip) + { + CoglFramebuffer *fb = _clutter_stage_get_active_framebuffer (stage); + cogl_framebuffer_push_rectangle_clip (fb, + priv->clip.origin.x, + priv->clip.origin.y, + priv->clip.origin.x + priv->clip.size.width, + priv->clip.origin.y + priv->clip.size.height); + clip_set = TRUE; + } + else if (priv->clip_to_allocation) + { + CoglFramebuffer *fb = _clutter_stage_get_active_framebuffer (stage); + gfloat width, height; + + width = priv->allocation.x2 - priv->allocation.x1; + height = priv->allocation.y2 - priv->allocation.y1; + + cogl_framebuffer_push_rectangle_clip (fb, 0, 0, width, height); + clip_set = TRUE; + } + + if (pick_mode == CLUTTER_PICK_NONE) + { + /* We check whether we need to add the flatten effect before + each paint so that we can avoid having a mechanism for + applications to notify when the value of the + has_overlaps virtual changes. */ + add_or_remove_flatten_effect (self); + } + + /* We save the current paint volume so that the next time the + * actor queues a redraw we can constrain the redraw to just + * cover the union of the new bounding box and the old. + * + * We also fetch the current paint volume to perform culling so + * we can avoid painting actors outside the current clip region. + * + * If we are painting inside a clone, we should neither update + * the paint volume or use it to cull painting, since the paint + * box represents the location of the source actor on the + * screen. + * + * XXX: We are starting to do a lot of vertex transforms on + * the CPU in a typical paint, so at some point we should + * audit these and consider caching some things. + * + * NB: We don't perform culling while picking at this point because + * clutter-stage.c doesn't setup the clipping planes appropriately. + * + * NB: We don't want to update the last-paint-volume during picking + * because the last-paint-volume is used to determine the old screen + * space location of an actor that has moved so we can know the + * minimal region to redraw to clear an old view of the actor. If we + * update this during picking then by the time we come around to + * paint then the last-paint-volume would likely represent the new + * actor position not the old. + */ + if (!in_clone_paint () && pick_mode == CLUTTER_PICK_NONE) + { + gboolean success; + /* annoyingly gcc warns if uninitialized even though + * the initialization is redundant :-( */ + ClutterCullResult result = CLUTTER_CULL_RESULT_IN; + + if (G_LIKELY ((clutter_paint_debug_flags & + (CLUTTER_DEBUG_DISABLE_CULLING | + CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS)) != + (CLUTTER_DEBUG_DISABLE_CULLING | + CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS))) + _clutter_actor_update_last_paint_volume (self); + + success = cull_actor (self, &result); + + if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_REDRAWS)) + _clutter_actor_paint_cull_result (self, success, result); + else if (result == CLUTTER_CULL_RESULT_OUT && success) + goto done; + } + + if (priv->effects == NULL) + { + if (pick_mode == CLUTTER_PICK_NONE && + actor_has_shader_data (self)) + { + _clutter_actor_shader_pre_paint (self, FALSE); + shader_applied = TRUE; + } + + priv->next_effect_to_paint = NULL; + } + else + priv->next_effect_to_paint = + _clutter_meta_group_peek_metas (priv->effects); + + clutter_actor_continue_paint (self); + + if (shader_applied) + _clutter_actor_shader_post_paint (self); + + if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_VOLUMES && + pick_mode == CLUTTER_PICK_NONE)) + _clutter_actor_draw_paint_volume (self); + +done: + /* If we make it here then the actor has run through a complete + paint run including all the effects so it's no longer dirty */ + if (pick_mode == CLUTTER_PICK_NONE) + priv->is_dirty = FALSE; + + if (clip_set) + { + CoglFramebuffer *fb = _clutter_stage_get_active_framebuffer (stage); + + cogl_framebuffer_pop_clip (fb); + } + + cogl_pop_matrix (); + + /* paint sequence complete */ + CLUTTER_UNSET_PRIVATE_FLAGS (self, CLUTTER_IN_PAINT); +} + +/** + * clutter_actor_continue_paint: + * @self: A #ClutterActor + * + * Run the next stage of the paint sequence. This function should only + * be called within the implementation of the ‘run’ virtual of a + * #ClutterEffect. It will cause the run method of the next effect to + * be applied, or it will paint the actual actor if the current effect + * is the last effect in the chain. + * + * Since: 1.8 + */ +void +clutter_actor_continue_paint (ClutterActor *self) +{ + ClutterActorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + /* This should only be called from with in the ‘run’ implementation + of a ClutterEffect */ + g_return_if_fail (CLUTTER_ACTOR_IN_PAINT (self)); + + priv = self->priv; + + /* Skip any effects that are disabled */ + while (priv->next_effect_to_paint && + !clutter_actor_meta_get_enabled (priv->next_effect_to_paint->data)) + priv->next_effect_to_paint = priv->next_effect_to_paint->next; + + /* If this has come from the last effect then we'll just paint the + actual actor */ + if (priv->next_effect_to_paint == NULL) + { + if (_clutter_context_get_pick_mode () == CLUTTER_PICK_NONE) + { + ClutterPaintNode *dummy; + + /* XXX - this will go away in 2.0, when we can get rid of this + * stuff and switch to a pure retained render tree of PaintNodes + * for the entire frame, starting from the Stage; the paint() + * virtual function can then be called directly. + */ + dummy = _clutter_dummy_node_new (self); + clutter_paint_node_set_name (dummy, "Root"); + + /* XXX - for 1.12, we use the return value of paint_node() to + * decide whether we should emit the ::paint signal. + */ + clutter_actor_paint_node (self, dummy); + clutter_paint_node_unref (dummy); + + /* XXX:2.0 - Call the paint() virtual directly */ + g_signal_emit (self, actor_signals[PAINT], 0); + } + else + { + ClutterColor col = { 0, }; + + _clutter_id_to_color (_clutter_actor_get_pick_id (self), &col); + + /* Actor will then paint silhouette of itself in supplied + * color. See clutter_stage_get_actor_at_pos() for where + * picking is enabled. + * + * XXX:2.0 - Call the pick() virtual directly + */ + g_signal_emit (self, actor_signals[PICK], 0, &col); + } + } + else + { + ClutterEffect *old_current_effect; + ClutterEffectPaintFlags run_flags = 0; + + /* Cache the current effect so that we can put it back before + returning */ + old_current_effect = priv->current_effect; + + priv->current_effect = priv->next_effect_to_paint->data; + priv->next_effect_to_paint = priv->next_effect_to_paint->next; + + if (_clutter_context_get_pick_mode () == CLUTTER_PICK_NONE) + { + if (priv->is_dirty) + { + /* If there's an effect queued with this redraw then all + effects up to that one will be considered dirty. It + is expected the queued effect will paint the cached + image and not call clutter_actor_continue_paint again + (although it should work ok if it does) */ + if (priv->effect_to_redraw == NULL || + priv->current_effect != priv->effect_to_redraw) + run_flags |= CLUTTER_EFFECT_PAINT_ACTOR_DIRTY; + } + + _clutter_effect_paint (priv->current_effect, run_flags); + } + else + { + /* We can't determine when an actor has been modified since + its last pick so lets just assume it has always been + modified */ + run_flags |= CLUTTER_EFFECT_PAINT_ACTOR_DIRTY; + + _clutter_effect_pick (priv->current_effect, run_flags); + } + + priv->current_effect = old_current_effect; + } +} + +static void +_clutter_actor_stop_transitions (ClutterActor *self) +{ + const ClutterAnimationInfo *info; + GHashTableIter iter; + gpointer value; + + info = _clutter_actor_get_animation_info_or_defaults (self); + if (info->transitions == NULL) + return; + + g_hash_table_iter_init (&iter, info->transitions); + while (g_hash_table_iter_next (&iter, NULL, &value)) + { + TransitionClosure *closure = value; + + /* implicit transitions, and automatically managed explicit ones, + * should be removed at this point + */ + if (closure->is_implicit || + clutter_transition_get_remove_on_complete (closure->transition)) + { + g_hash_table_iter_remove (&iter); + } + else + { + /* otherwise we stop it, and the transition will be removed + * later, either by the actor's destruction or by explicit + * removal + */ + clutter_timeline_stop (CLUTTER_TIMELINE (closure->transition)); + } + } +} + +static ClutterActorTraverseVisitFlags +invalidate_queue_redraw_entry (ClutterActor *self, + int depth, + gpointer user_data) +{ + ClutterActorPrivate *priv = self->priv; + + if (priv->queue_redraw_entry != NULL) + { + _clutter_stage_queue_redraw_entry_invalidate (priv->queue_redraw_entry); + priv->queue_redraw_entry = NULL; + } + + return CLUTTER_ACTOR_TRAVERSE_VISIT_CONTINUE; +} + +static inline void +remove_child (ClutterActor *self, + ClutterActor *child) +{ + ClutterActor *prev_sibling, *next_sibling; + + prev_sibling = child->priv->prev_sibling; + next_sibling = child->priv->next_sibling; + + if (prev_sibling != NULL) + prev_sibling->priv->next_sibling = next_sibling; + + if (next_sibling != NULL) + next_sibling->priv->prev_sibling = prev_sibling; + + if (self->priv->first_child == child) + self->priv->first_child = next_sibling; + + if (self->priv->last_child == child) + self->priv->last_child = prev_sibling; + + child->priv->parent = NULL; + child->priv->prev_sibling = NULL; + child->priv->next_sibling = NULL; +} + +typedef enum { + REMOVE_CHILD_DESTROY_META = 1 << 0, + REMOVE_CHILD_EMIT_PARENT_SET = 1 << 1, + REMOVE_CHILD_EMIT_ACTOR_REMOVED = 1 << 2, + REMOVE_CHILD_CHECK_STATE = 1 << 3, + REMOVE_CHILD_FLUSH_QUEUE = 1 << 4, + REMOVE_CHILD_NOTIFY_FIRST_LAST = 1 << 5, + REMOVE_CHILD_STOP_TRANSITIONS = 1 << 6, + + /* default flags for public API */ + REMOVE_CHILD_DEFAULT_FLAGS = REMOVE_CHILD_STOP_TRANSITIONS | + REMOVE_CHILD_DESTROY_META | + REMOVE_CHILD_EMIT_PARENT_SET | + REMOVE_CHILD_EMIT_ACTOR_REMOVED | + REMOVE_CHILD_CHECK_STATE | + REMOVE_CHILD_FLUSH_QUEUE | + REMOVE_CHILD_NOTIFY_FIRST_LAST, + + /* flags for legacy/deprecated API */ + REMOVE_CHILD_LEGACY_FLAGS = REMOVE_CHILD_STOP_TRANSITIONS | + REMOVE_CHILD_CHECK_STATE | + REMOVE_CHILD_FLUSH_QUEUE | + REMOVE_CHILD_EMIT_PARENT_SET | + REMOVE_CHILD_NOTIFY_FIRST_LAST +} ClutterActorRemoveChildFlags; + +/*< private > + * clutter_actor_remove_child_internal: + * @self: a #ClutterActor + * @child: the child of @self that has to be removed + * @flags: control the removal operations + * + * Removes @child from the list of children of @self. + */ +static void +clutter_actor_remove_child_internal (ClutterActor *self, + ClutterActor *child, + ClutterActorRemoveChildFlags flags) +{ + ClutterActor *old_first, *old_last; + gboolean destroy_meta, emit_parent_set, emit_actor_removed, check_state; + gboolean flush_queue; + gboolean notify_first_last; + gboolean was_mapped; + gboolean stop_transitions; + GObject *obj; + + if (self == child) + { + g_warning ("Cannot remove actor '%s' from itself.", + _clutter_actor_get_debug_name (self)); + return; + } + + destroy_meta = (flags & REMOVE_CHILD_DESTROY_META) != 0; + emit_parent_set = (flags & REMOVE_CHILD_EMIT_PARENT_SET) != 0; + emit_actor_removed = (flags & REMOVE_CHILD_EMIT_ACTOR_REMOVED) != 0; + check_state = (flags & REMOVE_CHILD_CHECK_STATE) != 0; + flush_queue = (flags & REMOVE_CHILD_FLUSH_QUEUE) != 0; + notify_first_last = (flags & REMOVE_CHILD_NOTIFY_FIRST_LAST) != 0; + stop_transitions = (flags & REMOVE_CHILD_STOP_TRANSITIONS) != 0; + + obj = G_OBJECT (self); + g_object_freeze_notify (obj); + + if (stop_transitions) + _clutter_actor_stop_transitions (child); + + if (destroy_meta) + clutter_container_destroy_child_meta (CLUTTER_CONTAINER (self), child); + + if (check_state) + { + was_mapped = CLUTTER_ACTOR_IS_MAPPED (child); + + /* we need to unrealize *before* we set parent_actor to NULL, + * because in an unrealize method actors are dissociating from the + * stage, which means they need to be able to + * clutter_actor_get_stage(). + * + * yhis should unmap and unrealize, unless we're reparenting. + */ + clutter_actor_update_map_state (child, MAP_STATE_MAKE_UNREALIZED); + } + else + was_mapped = FALSE; + + if (flush_queue) + { + /* We take this opportunity to invalidate any queue redraw entry + * associated with the actor and descendants since we won't be able to + * determine the appropriate stage after this. + * + * we do this after we updated the mapped state because actors might + * end up queueing redraws inside their mapped/unmapped virtual + * functions, and if we invalidate the redraw entry we could end up + * with an inconsistent state and weird memory corruption. see + * bugs: + * + * http://bugzilla.clutter-project.org/show_bug.cgi?id=2621 + * https://bugzilla.gnome.org/show_bug.cgi?id=652036 + */ + _clutter_actor_traverse (child, + 0, + invalidate_queue_redraw_entry, + NULL, + NULL); + } + + old_first = self->priv->first_child; + old_last = self->priv->last_child; + + remove_child (self, child); + + self->priv->n_children -= 1; + + self->priv->age += 1; + + /* if the child that got removed was visible and set to + * expand then we want to reset the parent's state in + * case the child was the only thing that was making it + * expand. + */ + if (CLUTTER_ACTOR_IS_VISIBLE (child) && + (child->priv->needs_compute_expand || + child->priv->needs_x_expand || + child->priv->needs_y_expand)) + { + clutter_actor_queue_compute_expand (self); + } + + /* clutter_actor_reparent() will emit ::parent-set for us */ + if (emit_parent_set && !CLUTTER_ACTOR_IN_REPARENT (child)) + g_signal_emit (child, actor_signals[PARENT_SET], 0, self); + + /* if the child was mapped then we need to relayout ourselves to account + * for the removed child + */ + if (was_mapped) + clutter_actor_queue_relayout (self); + + /* we need to emit the signal before dropping the reference */ + if (emit_actor_removed) + g_signal_emit_by_name (self, "actor-removed", child); + + if (notify_first_last) + { + if (old_first != self->priv->first_child) + g_object_notify_by_pspec (obj, obj_props[PROP_FIRST_CHILD]); + + if (old_last != self->priv->last_child) + g_object_notify_by_pspec (obj, obj_props[PROP_LAST_CHILD]); + } + + g_object_thaw_notify (obj); + + /* remove the reference we acquired in clutter_actor_add_child() */ + g_object_unref (child); +} + +static const ClutterTransformInfo default_transform_info = { + 0.0, { 0, }, /* rotation-x */ + 0.0, { 0, }, /* rotation-y */ + 0.0, { 0, }, /* rotation-z */ + + 1.0, 1.0, 1.0, { 0, }, /* scale */ + + { 0, }, /* anchor XXX:2.0 - remove*/ + + CLUTTER_VERTEX_INIT_ZERO, /* translation */ + + 0.f, /* z-position */ + + CLUTTER_POINT_INIT_ZERO, /* pivot */ + 0.f, /* pivot-z */ + + CLUTTER_MATRIX_INIT_IDENTITY, + FALSE, /* transform */ + CLUTTER_MATRIX_INIT_IDENTITY, + FALSE, /* child-transform */ +}; + +/*< private > + * _clutter_actor_get_transform_info_or_defaults: + * @self: a #ClutterActor + * + * Retrieves the ClutterTransformInfo structure associated to an actor. + * + * If the actor does not have a ClutterTransformInfo structure associated + * to it, then the default structure will be returned. + * + * This function should only be used for getters. + * + * Return value: a const pointer to the ClutterTransformInfo structure + */ +const ClutterTransformInfo * +_clutter_actor_get_transform_info_or_defaults (ClutterActor *self) +{ + ClutterTransformInfo *info; + + info = g_object_get_qdata (G_OBJECT (self), quark_actor_transform_info); + if (info != NULL) + return info; + + return &default_transform_info; +} + +static void +clutter_transform_info_free (gpointer data) +{ + if (data != NULL) + g_slice_free (ClutterTransformInfo, data); +} + +/*< private > + * _clutter_actor_get_transform_info: + * @self: a #ClutterActor + * + * Retrieves a pointer to the ClutterTransformInfo structure. + * + * If the actor does not have a ClutterTransformInfo associated to it, one + * will be created and initialized to the default values. + * + * This function should be used for setters. + * + * For getters, you should use _clutter_actor_get_transform_info_or_defaults() + * instead. + * + * Return value: (transfer none): a pointer to the ClutterTransformInfo + * structure + */ +ClutterTransformInfo * +_clutter_actor_get_transform_info (ClutterActor *self) +{ + ClutterTransformInfo *info; + + info = g_object_get_qdata (G_OBJECT (self), quark_actor_transform_info); + if (info == NULL) + { + info = g_slice_new (ClutterTransformInfo); + + *info = default_transform_info; + + g_object_set_qdata_full (G_OBJECT (self), quark_actor_transform_info, + info, + clutter_transform_info_free); + } + + return info; +} + +static inline void +clutter_actor_set_pivot_point_internal (ClutterActor *self, + const ClutterPoint *pivot) +{ + ClutterTransformInfo *info; + + info = _clutter_actor_get_transform_info (self); + info->pivot = *pivot; + + self->priv->transform_valid = FALSE; + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_PIVOT_POINT]); + + clutter_actor_queue_redraw (self); +} + +static inline void +clutter_actor_set_pivot_point_z_internal (ClutterActor *self, + float pivot_z) +{ + ClutterTransformInfo *info; + + info = _clutter_actor_get_transform_info (self); + info->pivot_z = pivot_z; + + self->priv->transform_valid = FALSE; + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_PIVOT_POINT_Z]); + + clutter_actor_queue_redraw (self); +} + +/*< private > + * clutter_actor_set_translation_internal: + * @self: a #ClutterActor + * @axis: the axis of the translation to change + * @angle: the translation as a value along @axis + * + * Sets the translation on the given @axis + */ +static void +clutter_actor_set_translation_internal (ClutterActor *self, + gfloat value, + GParamSpec *pspec) +{ + GObject *obj = G_OBJECT (self); + ClutterTransformInfo *info; + + info = _clutter_actor_get_transform_info (self); + + if (pspec == obj_props[PROP_TRANSLATION_X]) + info->translation.x = value; + else if (pspec == obj_props[PROP_TRANSLATION_Y]) + info->translation.y = value; + else if (pspec == obj_props[PROP_TRANSLATION_Z]) + info->translation.z = value; + else + g_assert_not_reached (); + + self->priv->transform_valid = FALSE; + clutter_actor_queue_redraw (self); + g_object_notify_by_pspec (obj, pspec); +} + +static inline void +clutter_actor_set_translation_factor (ClutterActor *self, + ClutterRotateAxis axis, + gdouble value) +{ + const ClutterTransformInfo *info; + const float *translate_p = NULL; + GParamSpec *pspec = NULL; + + info = _clutter_actor_get_transform_info_or_defaults (self); + + switch (axis) + { + case CLUTTER_X_AXIS: + pspec = obj_props[PROP_TRANSLATION_X]; + translate_p = &info->translation.x; + break; + + case CLUTTER_Y_AXIS: + pspec = obj_props[PROP_TRANSLATION_Y]; + translate_p = &info->translation.y; + break; + + case CLUTTER_Z_AXIS: + pspec = obj_props[PROP_TRANSLATION_Z]; + translate_p = &info->translation.z; + break; + } + + g_assert (pspec != NULL); + g_assert (translate_p != NULL); + + _clutter_actor_create_transition (self, pspec, *translate_p, value); +} + +/** + * clutter_actor_set_translation: + * @self: a #ClutterActor + * @translate_x: the translation along the X axis + * @translate_y: the translation along the Y axis + * @translate_z: the translation along the Z axis + * + * Sets an additional translation transformation on a #ClutterActor, + * relative to the #ClutterActor:pivot-point. + * + * Since: 1.12 + */ +void +clutter_actor_set_translation (ClutterActor *self, + gfloat translate_x, + gfloat translate_y, + gfloat translate_z) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + g_object_freeze_notify (G_OBJECT (self)); + + clutter_actor_set_translation_factor (self, CLUTTER_X_AXIS, translate_x); + clutter_actor_set_translation_factor (self, CLUTTER_Y_AXIS, translate_y); + clutter_actor_set_translation_factor (self, CLUTTER_Z_AXIS, translate_z); + + g_object_thaw_notify (G_OBJECT (self)); +} + +/** + * clutter_actor_get_translation: + * @self: a #ClutterActor + * @translate_x: (out) (allow-none): return location for the X component + * of the translation, or %NULL + * @translate_y: (out) (allow-none): return location for the Y component + * of the translation, or %NULL + * @translate_z: (out) (allow-none): return location for the Z component + * of the translation, or %NULL + * + * Retrieves the translation set using clutter_actor_set_translation(). + * + * Since: 1.12 + */ +void +clutter_actor_get_translation (ClutterActor *self, + gfloat *translate_x, + gfloat *translate_y, + gfloat *translate_z) +{ + const ClutterTransformInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + info = _clutter_actor_get_transform_info_or_defaults (self); + + if (translate_x != NULL) + *translate_x = info->translation.x; + + if (translate_y != NULL) + *translate_y = info->translation.y; + + if (translate_z != NULL) + *translate_z = info->translation.z; +} + +/*< private > + * clutter_actor_set_rotation_angle_internal: + * @self: a #ClutterActor + * @angle: the angle of rotation + * @pspec: the #GParamSpec of the property + * + * Sets the rotation angle on the given axis without affecting the + * rotation center point. + */ +static inline void +clutter_actor_set_rotation_angle_internal (ClutterActor *self, + gdouble angle, + GParamSpec *pspec) +{ + ClutterTransformInfo *info; + + info = _clutter_actor_get_transform_info (self); + + if (pspec == obj_props[PROP_ROTATION_ANGLE_X]) + info->rx_angle = angle; + else if (pspec == obj_props[PROP_ROTATION_ANGLE_Y]) + info->ry_angle = angle; + else if (pspec == obj_props[PROP_ROTATION_ANGLE_Z]) + info->rz_angle = angle; + else + g_assert_not_reached (); + + self->priv->transform_valid = FALSE; + + clutter_actor_queue_redraw (self); + + g_object_notify_by_pspec (G_OBJECT (self), pspec); +} + +/** + * clutter_actor_set_rotation_angle: + * @self: a #ClutterActor + * @axis: the axis to set the angle one + * @angle: the angle of rotation, in degrees + * + * Sets the @angle of rotation of a #ClutterActor on the given @axis. + * + * This function is a convenience for setting the rotation properties + * #ClutterActor:rotation-angle-x, #ClutterActor:rotation-angle-y, + * and #ClutterActor:rotation-angle-z. + * + * The center of rotation is established by the #ClutterActor:pivot-point + * property. + * + * Since: 1.12 + */ +void +clutter_actor_set_rotation_angle (ClutterActor *self, + ClutterRotateAxis axis, + gdouble angle) +{ + const ClutterTransformInfo *info; + const double *cur_angle_p = NULL; + GParamSpec *pspec = NULL; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + info = _clutter_actor_get_transform_info_or_defaults (self); + + switch (axis) + { + case CLUTTER_X_AXIS: + cur_angle_p = &info->rx_angle; + pspec = obj_props[PROP_ROTATION_ANGLE_X]; + break; + + case CLUTTER_Y_AXIS: + cur_angle_p = &info->ry_angle; + pspec = obj_props[PROP_ROTATION_ANGLE_Y]; + break; + + case CLUTTER_Z_AXIS: + cur_angle_p = &info->rz_angle; + pspec = obj_props[PROP_ROTATION_ANGLE_Z]; + break; + } + + g_assert (pspec != NULL); + g_assert (cur_angle_p != NULL); + + _clutter_actor_create_transition (self, pspec, *cur_angle_p, angle); +} + +/** + * clutter_actor_get_rotation_angle: + * @self: a #ClutterActor + * @axis: the axis of the rotation + * + * Retrieves the angle of rotation set by clutter_actor_set_rotation_angle(). + * + * Return value: the angle of rotation, in degrees + * + * Since: 1.12 + */ +gdouble +clutter_actor_get_rotation_angle (ClutterActor *self, + ClutterRotateAxis axis) +{ + const ClutterTransformInfo *info; + gdouble retval; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0.0); + + info = _clutter_actor_get_transform_info_or_defaults (self); + + switch (axis) + { + case CLUTTER_X_AXIS: + retval = info->rx_angle; + break; + + case CLUTTER_Y_AXIS: + retval = info->ry_angle; + break; + + case CLUTTER_Z_AXIS: + retval = info->rz_angle; + break; + + default: + g_warn_if_reached (); + retval = 0.0; + break; + } + + return retval; +} + +/*< private > + * clutter_actor_set_rotation_center_internal: + * @self: a #ClutterActor + * @axis: the axis of the center to change + * @center: the coordinates of the rotation center + * + * Sets the rotation center on the given axis without affecting the + * rotation angle. + */ +static inline void +clutter_actor_set_rotation_center_internal (ClutterActor *self, + ClutterRotateAxis axis, + const ClutterVertex *center) +{ + ClutterVertex v = CLUTTER_VERTEX_INIT_ZERO; + GObject *obj = G_OBJECT (self); + ClutterTransformInfo *info; + + info = _clutter_actor_get_transform_info (self); + + if (center != NULL) + v = *center; + + g_object_freeze_notify (obj); + + switch (axis) + { + case CLUTTER_X_AXIS: + clutter_anchor_coord_set_units (&info->rx_center, v.x, v.y, v.z); + g_object_notify_by_pspec (obj, obj_props[PROP_ROTATION_CENTER_X]); + break; + + case CLUTTER_Y_AXIS: + clutter_anchor_coord_set_units (&info->ry_center, v.x, v.y, v.z); + g_object_notify_by_pspec (obj, obj_props[PROP_ROTATION_CENTER_Y]); + break; + + case CLUTTER_Z_AXIS: + /* if the previously set rotation center was fractional, then + * setting explicit coordinates will have to notify the + * :rotation-center-z-gravity property as well + */ + if (info->rz_center.is_fractional) + g_object_notify_by_pspec (obj, obj_props[PROP_ROTATION_CENTER_Z_GRAVITY]); + + clutter_anchor_coord_set_units (&info->rz_center, v.x, v.y, v.z); + g_object_notify_by_pspec (obj, obj_props[PROP_ROTATION_CENTER_Z]); + break; + } + + self->priv->transform_valid = FALSE; + + g_object_thaw_notify (obj); + + clutter_actor_queue_redraw (self); +} + +static void +clutter_actor_set_scale_factor_internal (ClutterActor *self, + double factor, + GParamSpec *pspec) +{ + GObject *obj = G_OBJECT (self); + ClutterTransformInfo *info; + + info = _clutter_actor_get_transform_info (self); + + if (pspec == obj_props[PROP_SCALE_X]) + info->scale_x = factor; + else if (pspec == obj_props[PROP_SCALE_Y]) + info->scale_y = factor; + else if (pspec == obj_props[PROP_SCALE_Z]) + info->scale_z = factor; + else + g_assert_not_reached (); + + self->priv->transform_valid = FALSE; + clutter_actor_queue_redraw (self); + g_object_notify_by_pspec (obj, pspec); +} + +static inline void +clutter_actor_set_scale_factor (ClutterActor *self, + ClutterRotateAxis axis, + gdouble factor) +{ + const ClutterTransformInfo *info; + const double *scale_p = NULL; + GParamSpec *pspec = NULL; + + info = _clutter_actor_get_transform_info_or_defaults (self); + + switch (axis) + { + case CLUTTER_X_AXIS: + pspec = obj_props[PROP_SCALE_X]; + scale_p = &info->scale_x; + break; + + case CLUTTER_Y_AXIS: + pspec = obj_props[PROP_SCALE_Y]; + scale_p = &info->scale_y; + break; + + case CLUTTER_Z_AXIS: + pspec = obj_props[PROP_SCALE_Z]; + scale_p = &info->scale_z; + break; + } + + g_assert (pspec != NULL); + g_assert (scale_p != NULL); + + _clutter_actor_create_transition (self, pspec, *scale_p, factor); +} + +static inline void +clutter_actor_set_scale_center (ClutterActor *self, + ClutterRotateAxis axis, + gfloat coord) +{ + GObject *obj = G_OBJECT (self); + ClutterTransformInfo *info; + gfloat center_x, center_y; + + info = _clutter_actor_get_transform_info (self); + + g_object_freeze_notify (obj); + + /* get the current scale center coordinates */ + clutter_anchor_coord_get_units (self, &info->scale_center, + ¢er_x, + ¢er_y, + NULL); + + /* we need to notify this too, because setting explicit coordinates will + * change the gravity as a side effect + */ + if (info->scale_center.is_fractional) + g_object_notify_by_pspec (obj, obj_props[PROP_SCALE_GRAVITY]); + + switch (axis) + { + case CLUTTER_X_AXIS: + clutter_anchor_coord_set_units (&info->scale_center, coord, center_y, 0); + g_object_notify_by_pspec (obj, obj_props[PROP_SCALE_CENTER_X]); + break; + + case CLUTTER_Y_AXIS: + clutter_anchor_coord_set_units (&info->scale_center, center_x, coord, 0); + g_object_notify_by_pspec (obj, obj_props[PROP_SCALE_CENTER_Y]); + break; + + default: + g_assert_not_reached (); + } + + self->priv->transform_valid = FALSE; + + clutter_actor_queue_redraw (self); + + g_object_thaw_notify (obj); +} + +static inline void +clutter_actor_set_scale_gravity (ClutterActor *self, + ClutterGravity gravity) +{ + ClutterTransformInfo *info; + GObject *obj; + + info = _clutter_actor_get_transform_info (self); + obj = G_OBJECT (self); + + if (gravity == CLUTTER_GRAVITY_NONE) + clutter_anchor_coord_set_units (&info->scale_center, 0, 0, 0); + else + clutter_anchor_coord_set_gravity (&info->scale_center, gravity); + + self->priv->transform_valid = FALSE; + + g_object_notify_by_pspec (obj, obj_props[PROP_SCALE_CENTER_X]); + g_object_notify_by_pspec (obj, obj_props[PROP_SCALE_CENTER_Y]); + g_object_notify_by_pspec (obj, obj_props[PROP_SCALE_GRAVITY]); + + clutter_actor_queue_redraw (self); +} + +/* XXX:2.0 - remove */ +static inline void +clutter_actor_set_anchor_coord (ClutterActor *self, + ClutterRotateAxis axis, + gfloat coord) +{ + GObject *obj = G_OBJECT (self); + ClutterTransformInfo *info; + gfloat anchor_x, anchor_y; + + info = _clutter_actor_get_transform_info (self); + + g_object_freeze_notify (obj); + + clutter_anchor_coord_get_units (self, &info->anchor, + &anchor_x, + &anchor_y, + NULL); + + if (info->anchor.is_fractional) + g_object_notify_by_pspec (obj, obj_props[PROP_ANCHOR_GRAVITY]); + + switch (axis) + { + case CLUTTER_X_AXIS: + clutter_anchor_coord_set_units (&info->anchor, + coord, + anchor_y, + 0.0); + g_object_notify_by_pspec (obj, obj_props[PROP_ANCHOR_X]); + break; + + case CLUTTER_Y_AXIS: + clutter_anchor_coord_set_units (&info->anchor, + anchor_x, + coord, + 0.0); + g_object_notify_by_pspec (obj, obj_props[PROP_ANCHOR_Y]); + break; + + default: + g_assert_not_reached (); + } + + self->priv->transform_valid = FALSE; + + clutter_actor_queue_redraw (self); + + g_object_thaw_notify (obj); +} + +static void +clutter_actor_set_clip_rect (ClutterActor *self, + const ClutterRect *clip) +{ + ClutterActorPrivate *priv = self->priv; + GObject *obj = G_OBJECT (self); + + if (clip != NULL) + { + priv->clip = *clip; + priv->has_clip = TRUE; + } + else + priv->has_clip = FALSE; + + clutter_actor_queue_redraw (self); + + g_object_notify_by_pspec (obj, obj_props[PROP_CLIP]); /* XXX:2.0 - remove */ + g_object_notify_by_pspec (obj, obj_props[PROP_CLIP_RECT]); + g_object_notify_by_pspec (obj, obj_props[PROP_HAS_CLIP]); +} + +static void +clutter_actor_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterActor *actor = CLUTTER_ACTOR (object); + ClutterActorPrivate *priv = actor->priv; + + switch (prop_id) + { + case PROP_X: + clutter_actor_set_x (actor, g_value_get_float (value)); + break; + + case PROP_Y: + clutter_actor_set_y (actor, g_value_get_float (value)); + break; + + case PROP_POSITION: + { + const ClutterPoint *pos = g_value_get_boxed (value); + + if (pos != NULL) + clutter_actor_set_position (actor, pos->x, pos->y); + else + clutter_actor_set_fixed_position_set (actor, FALSE); + } + break; + + case PROP_WIDTH: + clutter_actor_set_width (actor, g_value_get_float (value)); + break; + + case PROP_HEIGHT: + clutter_actor_set_height (actor, g_value_get_float (value)); + break; + + case PROP_SIZE: + { + const ClutterSize *size = g_value_get_boxed (value); + + if (size != NULL) + clutter_actor_set_size (actor, size->width, size->height); + else + clutter_actor_set_size (actor, -1, -1); + } + break; + + case PROP_FIXED_X: + clutter_actor_set_x (actor, g_value_get_float (value)); + break; + + case PROP_FIXED_Y: + clutter_actor_set_y (actor, g_value_get_float (value)); + break; + + case PROP_FIXED_POSITION_SET: + clutter_actor_set_fixed_position_set (actor, g_value_get_boolean (value)); + break; + + case PROP_MIN_WIDTH: + clutter_actor_set_min_width (actor, g_value_get_float (value)); + break; + + case PROP_MIN_HEIGHT: + clutter_actor_set_min_height (actor, g_value_get_float (value)); + break; + + case PROP_NATURAL_WIDTH: + clutter_actor_set_natural_width (actor, g_value_get_float (value)); + break; + + case PROP_NATURAL_HEIGHT: + clutter_actor_set_natural_height (actor, g_value_get_float (value)); + break; + + case PROP_MIN_WIDTH_SET: + clutter_actor_set_min_width_set (actor, g_value_get_boolean (value)); + break; + + case PROP_MIN_HEIGHT_SET: + clutter_actor_set_min_height_set (actor, g_value_get_boolean (value)); + break; + + case PROP_NATURAL_WIDTH_SET: + clutter_actor_set_natural_width_set (actor, g_value_get_boolean (value)); + break; + + case PROP_NATURAL_HEIGHT_SET: + clutter_actor_set_natural_height_set (actor, g_value_get_boolean (value)); + break; + + case PROP_REQUEST_MODE: + clutter_actor_set_request_mode (actor, g_value_get_enum (value)); + break; + + case PROP_DEPTH: /* XXX:2.0 - remove */ + clutter_actor_set_depth (actor, g_value_get_float (value)); + break; + + case PROP_Z_POSITION: + clutter_actor_set_z_position (actor, g_value_get_float (value)); + break; + + case PROP_OPACITY: + clutter_actor_set_opacity (actor, g_value_get_uint (value)); + break; + + case PROP_OFFSCREEN_REDIRECT: + clutter_actor_set_offscreen_redirect (actor, g_value_get_enum (value)); + break; + + case PROP_NAME: + clutter_actor_set_name (actor, g_value_get_string (value)); + break; + + case PROP_VISIBLE: + if (g_value_get_boolean (value) == TRUE) + clutter_actor_show (actor); + else + clutter_actor_hide (actor); + break; + + case PROP_PIVOT_POINT: + { + const ClutterPoint *pivot = g_value_get_boxed (value); + + if (pivot == NULL) + pivot = clutter_point_zero (); + + clutter_actor_set_pivot_point (actor, pivot->x, pivot->y); + } + break; + + case PROP_PIVOT_POINT_Z: + clutter_actor_set_pivot_point_z (actor, g_value_get_float (value)); + break; + + case PROP_TRANSLATION_X: + clutter_actor_set_translation_factor (actor, CLUTTER_X_AXIS, + g_value_get_float (value)); + break; + + case PROP_TRANSLATION_Y: + clutter_actor_set_translation_factor (actor, CLUTTER_Y_AXIS, + g_value_get_float (value)); + break; + + case PROP_TRANSLATION_Z: + clutter_actor_set_translation_factor (actor, CLUTTER_Z_AXIS, + g_value_get_float (value)); + break; + + case PROP_SCALE_X: + clutter_actor_set_scale_factor (actor, CLUTTER_X_AXIS, + g_value_get_double (value)); + break; + + case PROP_SCALE_Y: + clutter_actor_set_scale_factor (actor, CLUTTER_Y_AXIS, + g_value_get_double (value)); + break; + + case PROP_SCALE_Z: + clutter_actor_set_scale_factor (actor, CLUTTER_Z_AXIS, + g_value_get_double (value)); + break; + + case PROP_SCALE_CENTER_X: /* XXX:2.0 - remove */ + clutter_actor_set_scale_center (actor, CLUTTER_X_AXIS, + g_value_get_float (value)); + break; + + case PROP_SCALE_CENTER_Y: /* XXX:2.0 - remove */ + clutter_actor_set_scale_center (actor, CLUTTER_Y_AXIS, + g_value_get_float (value)); + break; + + case PROP_SCALE_GRAVITY: /* XXX:2.0 - remove */ + clutter_actor_set_scale_gravity (actor, g_value_get_enum (value)); + break; + + case PROP_CLIP: /* XXX:2.0 - remove */ + { + const ClutterGeometry *geom = g_value_get_boxed (value); + + clutter_actor_set_clip (actor, + geom->x, geom->y, + geom->width, geom->height); + } + break; + + case PROP_CLIP_RECT: + clutter_actor_set_clip_rect (actor, g_value_get_boxed (value)); + break; + + case PROP_CLIP_TO_ALLOCATION: + clutter_actor_set_clip_to_allocation (actor, g_value_get_boolean (value)); + break; + + case PROP_REACTIVE: + clutter_actor_set_reactive (actor, g_value_get_boolean (value)); + break; + + case PROP_ROTATION_ANGLE_X: + clutter_actor_set_rotation_angle (actor, + CLUTTER_X_AXIS, + g_value_get_double (value)); + break; + + case PROP_ROTATION_ANGLE_Y: + clutter_actor_set_rotation_angle (actor, + CLUTTER_Y_AXIS, + g_value_get_double (value)); + break; + + case PROP_ROTATION_ANGLE_Z: + clutter_actor_set_rotation_angle (actor, + CLUTTER_Z_AXIS, + g_value_get_double (value)); + break; + + case PROP_ROTATION_CENTER_X: /* XXX:2.0 - remove */ + clutter_actor_set_rotation_center_internal (actor, + CLUTTER_X_AXIS, + g_value_get_boxed (value)); + break; + + case PROP_ROTATION_CENTER_Y: /* XXX:2.0 - remove */ + clutter_actor_set_rotation_center_internal (actor, + CLUTTER_Y_AXIS, + g_value_get_boxed (value)); + break; + + case PROP_ROTATION_CENTER_Z: /* XXX:2.0 - remove */ + clutter_actor_set_rotation_center_internal (actor, + CLUTTER_Z_AXIS, + g_value_get_boxed (value)); + break; + + case PROP_ROTATION_CENTER_Z_GRAVITY: /* XXX:2.0 - remove */ + { + const ClutterTransformInfo *info; + + info = _clutter_actor_get_transform_info_or_defaults (actor); + clutter_actor_set_z_rotation_from_gravity (actor, info->rz_angle, + g_value_get_enum (value)); + } + break; + + case PROP_ANCHOR_X: /* XXX:2.0 - remove */ + clutter_actor_set_anchor_coord (actor, CLUTTER_X_AXIS, + g_value_get_float (value)); + break; + + case PROP_ANCHOR_Y: /* XXX:2.0 - remove */ + clutter_actor_set_anchor_coord (actor, CLUTTER_Y_AXIS, + g_value_get_float (value)); + break; + + case PROP_ANCHOR_GRAVITY: /* XXX:2.0 - remove */ + clutter_actor_set_anchor_point_from_gravity (actor, + g_value_get_enum (value)); + break; + + case PROP_TRANSFORM: + clutter_actor_set_transform (actor, g_value_get_boxed (value)); + break; + + case PROP_CHILD_TRANSFORM: + clutter_actor_set_child_transform (actor, g_value_get_boxed (value)); + break; + + case PROP_SHOW_ON_SET_PARENT: /* XXX:2.0 - remove */ + priv->show_on_set_parent = g_value_get_boolean (value); + break; + + case PROP_TEXT_DIRECTION: + clutter_actor_set_text_direction (actor, g_value_get_enum (value)); + break; + + case PROP_ACTIONS: + clutter_actor_add_action (actor, g_value_get_object (value)); + break; + + case PROP_CONSTRAINTS: + clutter_actor_add_constraint (actor, g_value_get_object (value)); + break; + + case PROP_EFFECT: + clutter_actor_add_effect (actor, g_value_get_object (value)); + break; + + case PROP_LAYOUT_MANAGER: + clutter_actor_set_layout_manager (actor, g_value_get_object (value)); + break; + + case PROP_X_EXPAND: + clutter_actor_set_x_expand (actor, g_value_get_boolean (value)); + break; + + case PROP_Y_EXPAND: + clutter_actor_set_y_expand (actor, g_value_get_boolean (value)); + break; + + case PROP_X_ALIGN: + clutter_actor_set_x_align (actor, g_value_get_enum (value)); + break; + + case PROP_Y_ALIGN: + clutter_actor_set_y_align (actor, g_value_get_enum (value)); + break; + + case PROP_MARGIN_TOP: + clutter_actor_set_margin_top (actor, g_value_get_float (value)); + break; + + case PROP_MARGIN_BOTTOM: + clutter_actor_set_margin_bottom (actor, g_value_get_float (value)); + break; + + case PROP_MARGIN_LEFT: + clutter_actor_set_margin_left (actor, g_value_get_float (value)); + break; + + case PROP_MARGIN_RIGHT: + clutter_actor_set_margin_right (actor, g_value_get_float (value)); + break; + + case PROP_BACKGROUND_COLOR: + clutter_actor_set_background_color (actor, g_value_get_boxed (value)); + break; + + case PROP_CONTENT: + clutter_actor_set_content (actor, g_value_get_object (value)); + break; + + case PROP_CONTENT_GRAVITY: + clutter_actor_set_content_gravity (actor, g_value_get_enum (value)); + break; + + case PROP_MINIFICATION_FILTER: + clutter_actor_set_content_scaling_filters (actor, + g_value_get_enum (value), + actor->priv->mag_filter); + break; + + case PROP_MAGNIFICATION_FILTER: + clutter_actor_set_content_scaling_filters (actor, + actor->priv->min_filter, + g_value_get_enum (value)); + break; + + case PROP_CONTENT_REPEAT: + clutter_actor_set_content_repeat (actor, g_value_get_flags (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_actor_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterActor *actor = CLUTTER_ACTOR (object); + ClutterActorPrivate *priv = actor->priv; + + switch (prop_id) + { + case PROP_X: + g_value_set_float (value, clutter_actor_get_x (actor)); + break; + + case PROP_Y: + g_value_set_float (value, clutter_actor_get_y (actor)); + break; + + case PROP_POSITION: + { + ClutterPoint position; + + clutter_point_init (&position, + clutter_actor_get_x (actor), + clutter_actor_get_y (actor)); + g_value_set_boxed (value, &position); + } + break; + + case PROP_WIDTH: + g_value_set_float (value, clutter_actor_get_width (actor)); + break; + + case PROP_HEIGHT: + g_value_set_float (value, clutter_actor_get_height (actor)); + break; + + case PROP_SIZE: + { + ClutterSize size; + + clutter_size_init (&size, + clutter_actor_get_width (actor), + clutter_actor_get_height (actor)); + g_value_set_boxed (value, &size); + } + break; + + case PROP_FIXED_X: + { + const ClutterLayoutInfo *info; + + info = _clutter_actor_get_layout_info_or_defaults (actor); + g_value_set_float (value, info->fixed_pos.x); + } + break; + + case PROP_FIXED_Y: + { + const ClutterLayoutInfo *info; + + info = _clutter_actor_get_layout_info_or_defaults (actor); + g_value_set_float (value, info->fixed_pos.y); + } + break; + + case PROP_FIXED_POSITION_SET: + g_value_set_boolean (value, priv->position_set); + break; + + case PROP_MIN_WIDTH: + { + const ClutterLayoutInfo *info; + + info = _clutter_actor_get_layout_info_or_defaults (actor); + g_value_set_float (value, info->minimum.width); + } + break; + + case PROP_MIN_HEIGHT: + { + const ClutterLayoutInfo *info; + + info = _clutter_actor_get_layout_info_or_defaults (actor); + g_value_set_float (value, info->minimum.height); + } + break; + + case PROP_NATURAL_WIDTH: + { + const ClutterLayoutInfo *info; + + info = _clutter_actor_get_layout_info_or_defaults (actor); + g_value_set_float (value, info->natural.width); + } + break; + + case PROP_NATURAL_HEIGHT: + { + const ClutterLayoutInfo *info; + + info = _clutter_actor_get_layout_info_or_defaults (actor); + g_value_set_float (value, info->natural.height); + } + break; + + case PROP_MIN_WIDTH_SET: + g_value_set_boolean (value, priv->min_width_set); + break; + + case PROP_MIN_HEIGHT_SET: + g_value_set_boolean (value, priv->min_height_set); + break; + + case PROP_NATURAL_WIDTH_SET: + g_value_set_boolean (value, priv->natural_width_set); + break; + + case PROP_NATURAL_HEIGHT_SET: + g_value_set_boolean (value, priv->natural_height_set); + break; + + case PROP_REQUEST_MODE: + g_value_set_enum (value, priv->request_mode); + break; + + case PROP_ALLOCATION: + g_value_set_boxed (value, &priv->allocation); + break; + + case PROP_DEPTH: /* XXX:2.0 - remove */ + g_value_set_float (value, clutter_actor_get_depth (actor)); + break; + + case PROP_Z_POSITION: + g_value_set_float (value, clutter_actor_get_z_position (actor)); + break; + + case PROP_OPACITY: + g_value_set_uint (value, priv->opacity); + break; + + case PROP_OFFSCREEN_REDIRECT: + g_value_set_flags (value, priv->offscreen_redirect); + break; + + case PROP_NAME: + g_value_set_string (value, priv->name); + break; + + case PROP_VISIBLE: + g_value_set_boolean (value, CLUTTER_ACTOR_IS_VISIBLE (actor)); + break; + + case PROP_MAPPED: + g_value_set_boolean (value, CLUTTER_ACTOR_IS_MAPPED (actor)); + break; + + case PROP_REALIZED: + g_value_set_boolean (value, CLUTTER_ACTOR_IS_REALIZED (actor)); + break; + + case PROP_HAS_CLIP: + g_value_set_boolean (value, priv->has_clip); + break; + + case PROP_CLIP: /* XXX:2.0 - remove */ + { + ClutterGeometry clip; + + clip.x = CLUTTER_NEARBYINT (priv->clip.origin.x); + clip.y = CLUTTER_NEARBYINT (priv->clip.origin.y); + clip.width = CLUTTER_NEARBYINT (priv->clip.size.width); + clip.height = CLUTTER_NEARBYINT (priv->clip.size.height); + + g_value_set_boxed (value, &clip); + } + break; + + case PROP_CLIP_RECT: + g_value_set_boxed (value, &priv->clip); + break; + + case PROP_CLIP_TO_ALLOCATION: + g_value_set_boolean (value, priv->clip_to_allocation); + break; + + case PROP_PIVOT_POINT: + { + const ClutterTransformInfo *info; + + info = _clutter_actor_get_transform_info_or_defaults (actor); + g_value_set_boxed (value, &info->pivot); + } + break; + + case PROP_PIVOT_POINT_Z: + { + const ClutterTransformInfo *info; + + info = _clutter_actor_get_transform_info_or_defaults (actor); + g_value_set_float (value, info->pivot_z); + } + break; + + case PROP_TRANSLATION_X: + { + const ClutterTransformInfo *info; + + info = _clutter_actor_get_transform_info_or_defaults (actor); + g_value_set_float (value, info->translation.x); + } + break; + + case PROP_TRANSLATION_Y: + { + const ClutterTransformInfo *info; + + info = _clutter_actor_get_transform_info_or_defaults (actor); + g_value_set_float (value, info->translation.y); + } + break; + + case PROP_TRANSLATION_Z: + { + const ClutterTransformInfo *info; + + info = _clutter_actor_get_transform_info_or_defaults (actor); + g_value_set_float (value, info->translation.z); + } + break; + + case PROP_SCALE_X: + { + const ClutterTransformInfo *info; + + info = _clutter_actor_get_transform_info_or_defaults (actor); + g_value_set_double (value, info->scale_x); + } + break; + + case PROP_SCALE_Y: + { + const ClutterTransformInfo *info; + + info = _clutter_actor_get_transform_info_or_defaults (actor); + g_value_set_double (value, info->scale_y); + } + break; + + case PROP_SCALE_Z: + { + const ClutterTransformInfo *info; + + info = _clutter_actor_get_transform_info_or_defaults (actor); + g_value_set_double (value, info->scale_z); + } + break; + + case PROP_SCALE_CENTER_X: /* XXX:2.0 - remove */ + { + gfloat center; + + clutter_actor_get_scale_center (actor, ¢er, NULL); + + g_value_set_float (value, center); + } + break; + + case PROP_SCALE_CENTER_Y: /* XXX:2.0 - remove */ + { + gfloat center; + + clutter_actor_get_scale_center (actor, NULL, ¢er); + + g_value_set_float (value, center); + } + break; + + case PROP_SCALE_GRAVITY: /* XXX:2.0 - remove */ + g_value_set_enum (value, clutter_actor_get_scale_gravity (actor)); + break; + + case PROP_REACTIVE: + g_value_set_boolean (value, clutter_actor_get_reactive (actor)); + break; + + case PROP_ROTATION_ANGLE_X: + { + const ClutterTransformInfo *info; + + info = _clutter_actor_get_transform_info_or_defaults (actor); + g_value_set_double (value, info->rx_angle); + } + break; + + case PROP_ROTATION_ANGLE_Y: + { + const ClutterTransformInfo *info; + + info = _clutter_actor_get_transform_info_or_defaults (actor); + g_value_set_double (value, info->ry_angle); + } + break; + + case PROP_ROTATION_ANGLE_Z: + { + const ClutterTransformInfo *info; + + info = _clutter_actor_get_transform_info_or_defaults (actor); + g_value_set_double (value, info->rz_angle); + } + break; + + case PROP_ROTATION_CENTER_X: /* XXX:2.0 - remove */ + { + ClutterVertex center; + + clutter_actor_get_rotation (actor, CLUTTER_X_AXIS, + ¢er.x, + ¢er.y, + ¢er.z); + + g_value_set_boxed (value, ¢er); + } + break; + + case PROP_ROTATION_CENTER_Y: /* XXX:2.0 - remove */ + { + ClutterVertex center; + + clutter_actor_get_rotation (actor, CLUTTER_Y_AXIS, + ¢er.x, + ¢er.y, + ¢er.z); + + g_value_set_boxed (value, ¢er); + } + break; + + case PROP_ROTATION_CENTER_Z: /* XXX:2.0 - remove */ + { + ClutterVertex center; + + clutter_actor_get_rotation (actor, CLUTTER_Z_AXIS, + ¢er.x, + ¢er.y, + ¢er.z); + + g_value_set_boxed (value, ¢er); + } + break; + + case PROP_ROTATION_CENTER_Z_GRAVITY: /* XXX:2.0 - remove */ + g_value_set_enum (value, clutter_actor_get_z_rotation_gravity (actor)); + break; + + case PROP_ANCHOR_X: /* XXX:2.0 - remove */ + { + const ClutterTransformInfo *info; + gfloat anchor_x; + + info = _clutter_actor_get_transform_info_or_defaults (actor); + clutter_anchor_coord_get_units (actor, &info->anchor, + &anchor_x, + NULL, + NULL); + g_value_set_float (value, anchor_x); + } + break; + + case PROP_ANCHOR_Y: /* XXX:2.0 - remove */ + { + const ClutterTransformInfo *info; + gfloat anchor_y; + + info = _clutter_actor_get_transform_info_or_defaults (actor); + clutter_anchor_coord_get_units (actor, &info->anchor, + NULL, + &anchor_y, + NULL); + g_value_set_float (value, anchor_y); + } + break; + + case PROP_ANCHOR_GRAVITY: /* XXX:2.0 - remove */ + g_value_set_enum (value, clutter_actor_get_anchor_point_gravity (actor)); + break; + + case PROP_TRANSFORM: + { + ClutterMatrix m; + + clutter_actor_get_transform (actor, &m); + g_value_set_boxed (value, &m); + } + break; + + case PROP_TRANSFORM_SET: + { + const ClutterTransformInfo *info; + + info = _clutter_actor_get_transform_info_or_defaults (actor); + g_value_set_boolean (value, info->transform_set); + } + break; + + case PROP_CHILD_TRANSFORM: + { + ClutterMatrix m; + + clutter_actor_get_child_transform (actor, &m); + g_value_set_boxed (value, &m); + } + break; + + case PROP_CHILD_TRANSFORM_SET: + { + const ClutterTransformInfo *info; + + info = _clutter_actor_get_transform_info_or_defaults (actor); + g_value_set_boolean (value, info->child_transform_set); + } + break; + + case PROP_SHOW_ON_SET_PARENT: /* XXX:2.0 - remove */ + g_value_set_boolean (value, priv->show_on_set_parent); + break; + + case PROP_TEXT_DIRECTION: + g_value_set_enum (value, priv->text_direction); + break; + + case PROP_HAS_POINTER: + g_value_set_boolean (value, priv->has_pointer); + break; + + case PROP_LAYOUT_MANAGER: + g_value_set_object (value, priv->layout_manager); + break; + + case PROP_X_EXPAND: + { + const ClutterLayoutInfo *info; + + info = _clutter_actor_get_layout_info_or_defaults (actor); + g_value_set_boolean (value, info->x_expand); + } + break; + + case PROP_Y_EXPAND: + { + const ClutterLayoutInfo *info; + + info = _clutter_actor_get_layout_info_or_defaults (actor); + g_value_set_boolean (value, info->y_expand); + } + break; + + case PROP_X_ALIGN: + { + const ClutterLayoutInfo *info; + + info = _clutter_actor_get_layout_info_or_defaults (actor); + g_value_set_enum (value, info->x_align); + } + break; + + case PROP_Y_ALIGN: + { + const ClutterLayoutInfo *info; + + info = _clutter_actor_get_layout_info_or_defaults (actor); + g_value_set_enum (value, info->y_align); + } + break; + + case PROP_MARGIN_TOP: + { + const ClutterLayoutInfo *info; + + info = _clutter_actor_get_layout_info_or_defaults (actor); + g_value_set_float (value, info->margin.top); + } + break; + + case PROP_MARGIN_BOTTOM: + { + const ClutterLayoutInfo *info; + + info = _clutter_actor_get_layout_info_or_defaults (actor); + g_value_set_float (value, info->margin.bottom); + } + break; + + case PROP_MARGIN_LEFT: + { + const ClutterLayoutInfo *info; + + info = _clutter_actor_get_layout_info_or_defaults (actor); + g_value_set_float (value, info->margin.left); + } + break; + + case PROP_MARGIN_RIGHT: + { + const ClutterLayoutInfo *info; + + info = _clutter_actor_get_layout_info_or_defaults (actor); + g_value_set_float (value, info->margin.right); + } + break; + + case PROP_BACKGROUND_COLOR_SET: + g_value_set_boolean (value, priv->bg_color_set); + break; + + case PROP_BACKGROUND_COLOR: + g_value_set_boxed (value, &priv->bg_color); + break; + + case PROP_FIRST_CHILD: + g_value_set_object (value, priv->first_child); + break; + + case PROP_LAST_CHILD: + g_value_set_object (value, priv->last_child); + break; + + case PROP_CONTENT: + g_value_set_object (value, priv->content); + break; + + case PROP_CONTENT_GRAVITY: + g_value_set_enum (value, priv->content_gravity); + break; + + case PROP_CONTENT_BOX: + { + ClutterActorBox box = { 0, }; + + clutter_actor_get_content_box (actor, &box); + g_value_set_boxed (value, &box); + } + break; + + case PROP_MINIFICATION_FILTER: + g_value_set_enum (value, priv->min_filter); + break; + + case PROP_MAGNIFICATION_FILTER: + g_value_set_enum (value, priv->mag_filter); + break; + + case PROP_CONTENT_REPEAT: + g_value_set_flags (value, priv->content_repeat); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_actor_dispose (GObject *object) +{ + ClutterActor *self = CLUTTER_ACTOR (object); + ClutterActorPrivate *priv = self->priv; + + CLUTTER_NOTE (MISC, "Dispose actor (name='%s', ref_count:%d) of type '%s'", + _clutter_actor_get_debug_name (self), + object->ref_count, + g_type_name (G_OBJECT_TYPE (self))); + + g_signal_emit (self, actor_signals[DESTROY], 0); + + /* avoid recursing when called from clutter_actor_destroy() */ + if (priv->parent != NULL) + { + ClutterActor *parent = priv->parent; + + /* go through the Container implementation unless this + * is an internal child and has been marked as such. + * + * removing the actor from its parent will reset the + * realized and mapped states. + */ + if (!CLUTTER_ACTOR_IS_INTERNAL_CHILD (self)) + clutter_container_remove_actor (CLUTTER_CONTAINER (parent), self); + else + clutter_actor_remove_child_internal (parent, self, + REMOVE_CHILD_LEGACY_FLAGS); + } + + /* parent must be gone at this point */ + g_assert (priv->parent == NULL); + + if (!CLUTTER_ACTOR_IS_TOPLEVEL (self)) + { + /* can't be mapped or realized with no parent */ + g_assert (!CLUTTER_ACTOR_IS_MAPPED (self)); + g_assert (!CLUTTER_ACTOR_IS_REALIZED (self)); + } + + g_clear_object (&priv->pango_context); + g_clear_object (&priv->actions); + g_clear_object (&priv->constraints); + g_clear_object (&priv->effects); + g_clear_object (&priv->flatten_effect); + + if (priv->child_model != NULL) + { + if (priv->create_child_notify != NULL) + priv->create_child_notify (priv->create_child_data); + + priv->create_child_func = NULL; + priv->create_child_data = NULL; + priv->create_child_notify = NULL; + + g_clear_object (&priv->child_model); + } + + if (priv->layout_manager != NULL) + { + clutter_layout_manager_set_container (priv->layout_manager, NULL); + g_clear_object (&priv->layout_manager); + } + + if (priv->content != NULL) + { + _clutter_content_detached (priv->content, self); + g_clear_object (&priv->content); + } + + if (priv->clones != NULL) + { + g_hash_table_unref (priv->clones); + priv->clones = NULL; + } + + G_OBJECT_CLASS (clutter_actor_parent_class)->dispose (object); +} + +static void +clutter_actor_finalize (GObject *object) +{ + ClutterActorPrivate *priv = CLUTTER_ACTOR (object)->priv; + + CLUTTER_NOTE (MISC, "Finalize actor (name='%s') of type '%s'", + _clutter_actor_get_debug_name ((ClutterActor *) object), + g_type_name (G_OBJECT_TYPE (object))); + + g_free (priv->name); + +#ifdef CLUTTER_ENABLE_DEBUG + g_free (priv->debug_name); +#endif + + G_OBJECT_CLASS (clutter_actor_parent_class)->finalize (object); +} + + +/** + * clutter_actor_get_accessible: + * @self: a #ClutterActor + * + * Returns the accessible object that describes the actor to an + * assistive technology. + * + * If no class-specific #AtkObject implementation is available for the + * actor instance in question, it will inherit an #AtkObject + * implementation from the first ancestor class for which such an + * implementation is defined. + * + * The documentation of the ATK + * library contains more information about accessible objects and + * their uses. + * + * Returns: (transfer none): the #AtkObject associated with @actor + */ +AtkObject * +clutter_actor_get_accessible (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + + return CLUTTER_ACTOR_GET_CLASS (self)->get_accessible (self); +} + +static AtkObject * +clutter_actor_real_get_accessible (ClutterActor *actor) +{ + return atk_gobject_accessible_for_object (G_OBJECT (actor)); +} + +static AtkObject * +_clutter_actor_ref_accessible (AtkImplementor *implementor) +{ + AtkObject *accessible; + + accessible = clutter_actor_get_accessible (CLUTTER_ACTOR (implementor)); + if (accessible != NULL) + g_object_ref (accessible); + + return accessible; +} + +static void +atk_implementor_iface_init (AtkImplementorIface *iface) +{ + iface->ref_accessible = _clutter_actor_ref_accessible; +} + +static gboolean +clutter_actor_update_default_paint_volume (ClutterActor *self, + ClutterPaintVolume *volume) +{ + ClutterActorPrivate *priv = self->priv; + gboolean res = TRUE; + + /* this should be checked before we call this function, but it's a + * good idea to be explicit when it costs us nothing + */ + if (priv->needs_allocation) + return FALSE; + + /* we start from the allocation */ + clutter_paint_volume_set_width (volume, + priv->allocation.x2 - priv->allocation.x1); + clutter_paint_volume_set_height (volume, + priv->allocation.y2 - priv->allocation.y1); + + /* if the actor has a clip set then we have a pretty definite + * size for the paint volume: the actor cannot possibly paint + * outside the clip region. + */ + if (priv->clip_to_allocation) + { + /* the allocation has already been set, so we just flip the + * return value + */ + res = TRUE; + } + else + { + ClutterActor *child; + + if (priv->has_clip && + priv->clip.size.width >= 0 && + priv->clip.size.height >= 0) + { + ClutterVertex origin; + + origin.x = priv->clip.origin.x; + origin.y = priv->clip.origin.y; + origin.z = 0; + + clutter_paint_volume_set_origin (volume, &origin); + clutter_paint_volume_set_width (volume, priv->clip.size.width); + clutter_paint_volume_set_height (volume, priv->clip.size.height); + + res = TRUE; + } + + /* if we don't have children we just bail out here... */ + if (priv->n_children == 0) + return res; + + /* ...but if we have children then we ask for their paint volume in + * our coordinates. if any of our children replies that it doesn't + * have a paint volume, we bail out + */ + for (child = priv->first_child; + child != NULL; + child = child->priv->next_sibling) + { + const ClutterPaintVolume *child_volume; + + /* we ignore unmapped children, since they won't be painted. + * + * XXX: we also have to ignore mapped children without a valid + * allocation, because apparently some code above Clutter allows + * them. + */ + if (!CLUTTER_ACTOR_IS_MAPPED (child) || !clutter_actor_has_allocation (child)) + continue; + + child_volume = clutter_actor_get_transformed_paint_volume (child, self); + if (child_volume == NULL) + { + res = FALSE; + break; + } + + clutter_paint_volume_union (volume, child_volume); + res = TRUE; + } + } + + return res; + +} + +static gboolean +clutter_actor_real_get_paint_volume (ClutterActor *self, + ClutterPaintVolume *volume) +{ + ClutterActorClass *klass; + gboolean res; + + klass = CLUTTER_ACTOR_GET_CLASS (self); + + /* XXX - this thoroughly sucks, but we don't want to penalize users + * who use ClutterActor as a "new ClutterGroup" by forcing a full-stage + * redraw. This should go away in 2.0. + */ + if (klass->paint == clutter_actor_real_paint && + klass->get_paint_volume == clutter_actor_real_get_paint_volume) + { + res = TRUE; + } + else + { + /* this is the default return value: we cannot know if a class + * is going to paint outside its allocation, so we take the + * conservative approach. + */ + res = FALSE; + } + + /* update_default_paint_volume() should only fail if one of the children + * reported an invalid, or no, paint volume + */ + if (!clutter_actor_update_default_paint_volume (self, volume)) + return FALSE; + + return res; +} + +/** + * clutter_actor_get_default_paint_volume: + * @self: a #ClutterActor + * + * Retrieves the default paint volume for @self. + * + * This function provides the same #ClutterPaintVolume that would be + * computed by the default implementation inside #ClutterActor of the + * #ClutterActorClass.get_paint_volume() virtual function. + * + * This function should only be used by #ClutterActor subclasses that + * cannot chain up to the parent implementation when computing their + * paint volume. + * + * Return value: (transfer none): a pointer to the default + * #ClutterPaintVolume, relative to the #ClutterActor, or %NULL if + * the actor could not compute a valid paint volume. The returned value + * is not guaranteed to be stable across multiple frames, so if you + * want to retain it, you will need to copy it using + * clutter_paint_volume_copy(). + * + * Since: 1.10 + */ +const ClutterPaintVolume * +clutter_actor_get_default_paint_volume (ClutterActor *self) +{ + ClutterPaintVolume volume; + ClutterPaintVolume *res; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + + res = NULL; + _clutter_paint_volume_init_static (&volume, self); + if (clutter_actor_update_default_paint_volume (self, &volume)) + { + ClutterActor *stage = _clutter_actor_get_stage_internal (self); + + if (stage != NULL) + { + res = _clutter_stage_paint_volume_stack_allocate (CLUTTER_STAGE (stage)); + _clutter_paint_volume_copy_static (&volume, res); + } + } + + clutter_paint_volume_free (&volume); + + return res; +} + +static gboolean +clutter_actor_real_has_overlaps (ClutterActor *self) +{ + /* By default we'll assume that all actors need an offscreen redirect to get + * the correct opacity. Actors such as ClutterTexture that would never need + * an offscreen redirect can override this to return FALSE. */ + return TRUE; +} + +static void +clutter_actor_real_destroy (ClutterActor *actor) +{ + ClutterActorIter iter; + + g_object_freeze_notify (G_OBJECT (actor)); + + clutter_actor_iter_init (&iter, actor); + while (clutter_actor_iter_next (&iter, NULL)) + clutter_actor_iter_destroy (&iter); + + g_object_thaw_notify (G_OBJECT (actor)); +} + +static GObject * +clutter_actor_constructor (GType gtype, + guint n_props, + GObjectConstructParam *props) +{ + GObjectClass *gobject_class; + ClutterActor *self; + GObject *retval; + + gobject_class = G_OBJECT_CLASS (clutter_actor_parent_class); + retval = gobject_class->constructor (gtype, n_props, props); + self = CLUTTER_ACTOR (retval); + + if (self->priv->layout_manager == NULL) + { + ClutterLayoutManager *default_layout; + + CLUTTER_NOTE (LAYOUT, "Creating default layout manager"); + + default_layout = clutter_fixed_layout_new (); + clutter_actor_set_layout_manager (self, default_layout); + } + + return retval; +} + +static void +clutter_actor_class_init (ClutterActorClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + quark_shader_data = g_quark_from_static_string ("-clutter-actor-shader-data"); + quark_actor_layout_info = g_quark_from_static_string ("-clutter-actor-layout-info"); + quark_actor_transform_info = g_quark_from_static_string ("-clutter-actor-transform-info"); + quark_actor_animation_info = g_quark_from_static_string ("-clutter-actor-animation-info"); + + object_class->constructor = clutter_actor_constructor; + object_class->set_property = clutter_actor_set_property; + object_class->get_property = clutter_actor_get_property; + object_class->dispose = clutter_actor_dispose; + object_class->finalize = clutter_actor_finalize; + + klass->show = clutter_actor_real_show; + klass->show_all = clutter_actor_show; + klass->hide = clutter_actor_real_hide; + klass->hide_all = clutter_actor_hide; + klass->map = clutter_actor_real_map; + klass->unmap = clutter_actor_real_unmap; + klass->unrealize = clutter_actor_real_unrealize; + klass->pick = clutter_actor_real_pick; + klass->get_preferred_width = clutter_actor_real_get_preferred_width; + klass->get_preferred_height = clutter_actor_real_get_preferred_height; + klass->allocate = clutter_actor_real_allocate; + klass->queue_redraw = clutter_actor_real_queue_redraw; + klass->queue_relayout = clutter_actor_real_queue_relayout; + klass->apply_transform = clutter_actor_real_apply_transform; + klass->get_accessible = clutter_actor_real_get_accessible; + klass->get_paint_volume = clutter_actor_real_get_paint_volume; + klass->has_overlaps = clutter_actor_real_has_overlaps; + klass->paint = clutter_actor_real_paint; + klass->destroy = clutter_actor_real_destroy; + + /** + * ClutterActor:x: + * + * X coordinate of the actor in pixels. If written, forces a fixed + * position for the actor. If read, returns the fixed position if any, + * otherwise the allocation if available, otherwise 0. + * + * The #ClutterActor:x property is animatable. + */ + obj_props[PROP_X] = + g_param_spec_float ("x", + P_("X coordinate"), + P_("X coordinate of the actor"), + -G_MAXFLOAT, G_MAXFLOAT, + 0.0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:y: + * + * Y coordinate of the actor in pixels. If written, forces a fixed + * position for the actor. If read, returns the fixed position if + * any, otherwise the allocation if available, otherwise 0. + * + * The #ClutterActor:y property is animatable. + */ + obj_props[PROP_Y] = + g_param_spec_float ("y", + P_("Y coordinate"), + P_("Y coordinate of the actor"), + -G_MAXFLOAT, G_MAXFLOAT, + 0.0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:position: + * + * The position of the origin of the actor. + * + * This property is a shorthand for setting and getting the + * #ClutterActor:x and #ClutterActor:y properties at the same + * time. + * + * The #ClutterActor:position property is animatable. + * + * Since: 1.12 + */ + obj_props[PROP_POSITION] = + g_param_spec_boxed ("position", + P_("Position"), + P_("The position of the origin of the actor"), + CLUTTER_TYPE_POINT, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:width: + * + * Width of the actor (in pixels). If written, forces the minimum and + * natural size request of the actor to the given width. If read, returns + * the allocated width if available, otherwise the width request. + * + * The #ClutterActor:width property is animatable. + */ + obj_props[PROP_WIDTH] = + g_param_spec_float ("width", + P_("Width"), + P_("Width of the actor"), + 0.0, G_MAXFLOAT, + 0.0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:height: + * + * Height of the actor (in pixels). If written, forces the minimum and + * natural size request of the actor to the given height. If read, returns + * the allocated height if available, otherwise the height request. + * + * The #ClutterActor:height property is animatable. + */ + obj_props[PROP_HEIGHT] = + g_param_spec_float ("height", + P_("Height"), + P_("Height of the actor"), + 0.0, G_MAXFLOAT, + 0.0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:size: + * + * The size of the actor. + * + * This property is a shorthand for setting and getting the + * #ClutterActor:width and #ClutterActor:height at the same time. + * + * The #ClutterActor:size property is animatable. + * + * Since: 1.12 + */ + obj_props[PROP_SIZE] = + g_param_spec_boxed ("size", + P_("Size"), + P_("The size of the actor"), + CLUTTER_TYPE_SIZE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:fixed-x: + * + * The fixed X position of the actor in pixels. + * + * Writing this property sets #ClutterActor:fixed-position-set + * property as well, as a side effect + * + * Since: 0.8 + */ + obj_props[PROP_FIXED_X] = + g_param_spec_float ("fixed-x", + P_("Fixed X"), + P_("Forced X position of the actor"), + -G_MAXFLOAT, G_MAXFLOAT, + 0.0, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActor:fixed-y: + * + * The fixed Y position of the actor in pixels. + * + * Writing this property sets the #ClutterActor:fixed-position-set + * property as well, as a side effect + * + * Since: 0.8 + */ + obj_props[PROP_FIXED_Y] = + g_param_spec_float ("fixed-y", + P_("Fixed Y"), + P_("Forced Y position of the actor"), + -G_MAXFLOAT, G_MAXFLOAT, + 0, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActor:fixed-position-set: + * + * This flag controls whether the #ClutterActor:fixed-x and + * #ClutterActor:fixed-y properties are used + * + * Since: 0.8 + */ + obj_props[PROP_FIXED_POSITION_SET] = + g_param_spec_boolean ("fixed-position-set", + P_("Fixed position set"), + P_("Whether to use fixed positioning for the actor"), + FALSE, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActor:min-width: + * + * A forced minimum width request for the actor, in pixels + * + * Writing this property sets the #ClutterActor:min-width-set property + * as well, as a side effect. + * + *This property overrides the usual width request of the actor. + * + * Since: 0.8 + */ + obj_props[PROP_MIN_WIDTH] = + g_param_spec_float ("min-width", + P_("Min Width"), + P_("Forced minimum width request for the actor"), + 0.0, G_MAXFLOAT, + 0.0, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActor:min-height: + * + * A forced minimum height request for the actor, in pixels + * + * Writing this property sets the #ClutterActor:min-height-set property + * as well, as a side effect. This property overrides the usual height + * request of the actor. + * + * Since: 0.8 + */ + obj_props[PROP_MIN_HEIGHT] = + g_param_spec_float ("min-height", + P_("Min Height"), + P_("Forced minimum height request for the actor"), + 0.0, G_MAXFLOAT, + 0.0, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActor:natural-width: + * + * A forced natural width request for the actor, in pixels + * + * Writing this property sets the #ClutterActor:natural-width-set + * property as well, as a side effect. This property overrides the + * usual width request of the actor + * + * Since: 0.8 + */ + obj_props[PROP_NATURAL_WIDTH] = + g_param_spec_float ("natural-width", + P_("Natural Width"), + P_("Forced natural width request for the actor"), + 0.0, G_MAXFLOAT, + 0.0, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActor:natural-height: + * + * A forced natural height request for the actor, in pixels + * + * Writing this property sets the #ClutterActor:natural-height-set + * property as well, as a side effect. This property overrides the + * usual height request of the actor + * + * Since: 0.8 + */ + obj_props[PROP_NATURAL_HEIGHT] = + g_param_spec_float ("natural-height", + P_("Natural Height"), + P_("Forced natural height request for the actor"), + 0.0, G_MAXFLOAT, + 0.0, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActor:min-width-set: + * + * This flag controls whether the #ClutterActor:min-width property + * is used + * + * Since: 0.8 + */ + obj_props[PROP_MIN_WIDTH_SET] = + g_param_spec_boolean ("min-width-set", + P_("Minimum width set"), + P_("Whether to use the min-width property"), + FALSE, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActor:min-height-set: + * + * This flag controls whether the #ClutterActor:min-height property + * is used + * + * Since: 0.8 + */ + obj_props[PROP_MIN_HEIGHT_SET] = + g_param_spec_boolean ("min-height-set", + P_("Minimum height set"), + P_("Whether to use the min-height property"), + FALSE, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActor:natural-width-set: + * + * This flag controls whether the #ClutterActor:natural-width property + * is used + * + * Since: 0.8 + */ + obj_props[PROP_NATURAL_WIDTH_SET] = + g_param_spec_boolean ("natural-width-set", + P_("Natural width set"), + P_("Whether to use the natural-width property"), + FALSE, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActor:natural-height-set: + * + * This flag controls whether the #ClutterActor:natural-height property + * is used + * + * Since: 0.8 + */ + obj_props[PROP_NATURAL_HEIGHT_SET] = + g_param_spec_boolean ("natural-height-set", + P_("Natural height set"), + P_("Whether to use the natural-height property"), + FALSE, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActor:allocation: + * + * The allocation for the actor, in pixels + * + * This is property is read-only, but you might monitor it to know when an + * actor moves or resizes + * + * Since: 0.8 + */ + obj_props[PROP_ALLOCATION] = + g_param_spec_boxed ("allocation", + P_("Allocation"), + P_("The actor's allocation"), + CLUTTER_TYPE_ACTOR_BOX, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:request-mode: + * + * Request mode for the #ClutterActor. The request mode determines the + * type of geometry management used by the actor, either height for width + * (the default) or width for height. + * + * For actors implementing height for width, the parent container should get + * the preferred width first, and then the preferred height for that width. + * + * For actors implementing width for height, the parent container should get + * the preferred height first, and then the preferred width for that height. + * + * For instance: + * + * |[ + * ClutterRequestMode mode; + * gfloat natural_width, min_width; + * gfloat natural_height, min_height; + * + * mode = clutter_actor_get_request_mode (child); + * if (mode == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH) + * { + * clutter_actor_get_preferred_width (child, -1, + * &min_width, + * &natural_width); + * clutter_actor_get_preferred_height (child, natural_width, + * &min_height, + * &natural_height); + * } + * else if (mode == CLUTTER_REQUEST_WIDTH_FOR_HEIGHT) + * { + * clutter_actor_get_preferred_height (child, -1, + * &min_height, + * &natural_height); + * clutter_actor_get_preferred_width (child, natural_height, + * &min_width, + * &natural_width); + * } + * else if (mode == CLUTTER_REQUEST_CONTENT_SIZE) + * { + * ClutterContent *content = clutter_actor_get_content (child); + * + * min_width, min_height = 0; + * natural_width = natural_height = 0; + * + * if (content != NULL) + * clutter_content_get_preferred_size (content, &natural_width, &natural_height); + * } + * ]| + * + * will retrieve the minimum and natural width and height depending on the + * preferred request mode of the #ClutterActor "child". + * + * The clutter_actor_get_preferred_size() function will implement this + * check for you. + * + * Since: 0.8 + */ + obj_props[PROP_REQUEST_MODE] = + g_param_spec_enum ("request-mode", + P_("Request Mode"), + P_("The actor's request mode"), + CLUTTER_TYPE_REQUEST_MODE, + CLUTTER_REQUEST_HEIGHT_FOR_WIDTH, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActor:depth: + * + * The position of the actor on the Z axis. + * + * The #ClutterActor:depth property is relative to the parent's + * modelview matrix. + * + * Setting this property will call #ClutterContainerIface.sort_depth_order() + * which is usually a no-op, and it's most likely not what you want. + * + * The #ClutterActor:depth property is animatable. + * + * Since: 0.6 + * + * Deprecated: 1.12: Use #ClutterActor:z-position instead. + */ + obj_props[PROP_DEPTH] = + g_param_spec_float ("depth", + P_("Depth"), + P_("Position on the Z axis"), + -G_MAXFLOAT, G_MAXFLOAT, + 0.0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + G_PARAM_DEPRECATED | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:z-position: + * + * The actor's position on the Z axis, relative to the parent's + * transformations. + * + * Positive values will bring the actor's position nearer to the user, + * whereas negative values will bring the actor's position farther from + * the user. + * + * The #ClutterActor:z-position does not affect the paint or allocation + * order. + * + * The #ClutterActor:z-position property is animatable. + * + * Since: 1.12 + */ + obj_props[PROP_Z_POSITION] = + g_param_spec_float ("z-position", + P_("Z Position"), + P_("The actor's position on the Z axis"), + -G_MAXFLOAT, G_MAXFLOAT, + 0.0f, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:opacity: + * + * Opacity of an actor, between 0 (fully transparent) and + * 255 (fully opaque) + * + * The #ClutterActor:opacity property is animatable. + */ + obj_props[PROP_OPACITY] = + g_param_spec_uint ("opacity", + P_("Opacity"), + P_("Opacity of an actor"), + 0, 255, + 255, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:offscreen-redirect: + * + * Determines the conditions in which the actor will be redirected + * to an offscreen framebuffer while being painted. For example this + * can be used to cache an actor in a framebuffer or for improved + * handling of transparent actors. See + * clutter_actor_set_offscreen_redirect() for details. + * + * Since: 1.8 + */ + obj_props[PROP_OFFSCREEN_REDIRECT] = + g_param_spec_flags ("offscreen-redirect", + P_("Offscreen redirect"), + P_("Flags controlling when to flatten the actor into a single image"), + CLUTTER_TYPE_OFFSCREEN_REDIRECT, + 0, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActor:visible: + * + * Whether the actor is set to be visible or not + * + * See also #ClutterActor:mapped + */ + obj_props[PROP_VISIBLE] = + g_param_spec_boolean ("visible", + P_("Visible"), + P_("Whether the actor is visible or not"), + FALSE, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActor:mapped: + * + * Whether the actor is mapped (will be painted when the stage + * to which it belongs is mapped) + * + * Since: 1.0 + */ + obj_props[PROP_MAPPED] = + g_param_spec_boolean ("mapped", + P_("Mapped"), + P_("Whether the actor will be painted"), + FALSE, + CLUTTER_PARAM_READABLE); + + /** + * ClutterActor:realized: + * + * Whether the actor has been realized + * + * Since: 1.0 + */ + obj_props[PROP_REALIZED] = + g_param_spec_boolean ("realized", + P_("Realized"), + P_("Whether the actor has been realized"), + FALSE, + CLUTTER_PARAM_READABLE); + + /** + * ClutterActor:reactive: + * + * Whether the actor is reactive to events or not + * + * Only reactive actors will emit event-related signals + * + * Since: 0.6 + */ + obj_props[PROP_REACTIVE] = + g_param_spec_boolean ("reactive", + P_("Reactive"), + P_("Whether the actor is reactive to events"), + FALSE, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActor:has-clip: + * + * Whether the actor has the #ClutterActor:clip property set or not + */ + obj_props[PROP_HAS_CLIP] = + g_param_spec_boolean ("has-clip", + P_("Has Clip"), + P_("Whether the actor has a clip set"), + FALSE, + CLUTTER_PARAM_READABLE); + + /** + * ClutterActor:clip: + * + * The visible region of the actor, in actor-relative coordinates + * + * Deprecated: 1.12: Use #ClutterActor:clip-rect instead. + */ + obj_props[PROP_CLIP] = /* XXX:2.0 - remove */ + g_param_spec_boxed ("clip", + P_("Clip"), + P_("The clip region for the actor"), + CLUTTER_TYPE_GEOMETRY, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActor:clip-rect: + * + * The visible region of the actor, in actor-relative coordinates, + * expressed as a #ClutterRect. + * + * Setting this property to %NULL will unset the existing clip. + * + * Setting this property will change the #ClutterActor:has-clip + * property as a side effect. + * + * Since: 1.12 + */ + obj_props[PROP_CLIP_RECT] = + g_param_spec_boxed ("clip-rect", + P_("Clip Rectangle"), + P_("The visible region of the actor"), + CLUTTER_TYPE_RECT, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + /** + * ClutterActor:name: + * + * The name of the actor + * + * Since: 0.2 + */ + obj_props[PROP_NAME] = + g_param_spec_string ("name", + P_("Name"), + P_("Name of the actor"), + NULL, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActor:pivot-point: + * + * The point around which the scaling and rotation transformations occur. + * + * The pivot point is expressed in normalized coordinates space, with (0, 0) + * being the top left corner of the actor and (1, 1) the bottom right corner + * of the actor. + * + * The default pivot point is located at (0, 0). + * + * The #ClutterActor:pivot-point property is animatable. + * + * Since: 1.12 + */ + obj_props[PROP_PIVOT_POINT] = + g_param_spec_boxed ("pivot-point", + P_("Pivot Point"), + P_("The point around which the scaling and rotation occur"), + CLUTTER_TYPE_POINT, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:pivot-point-z: + * + * The Z component of the #ClutterActor:pivot-point, expressed as a value + * along the Z axis. + * + * The #ClutterActor:pivot-point-z property is animatable. + * + * Since: 1.12 + */ + obj_props[PROP_PIVOT_POINT_Z] = + g_param_spec_float ("pivot-point-z", + P_("Pivot Point Z"), + P_("Z component of the pivot point"), + -G_MAXFLOAT, G_MAXFLOAT, + 0.f, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:scale-x: + * + * The horizontal scale of the actor. + * + * The #ClutterActor:scale-x property is animatable. + * + * Since: 0.6 + */ + obj_props[PROP_SCALE_X] = + g_param_spec_double ("scale-x", + P_("Scale X"), + P_("Scale factor on the X axis"), + -G_MAXDOUBLE, G_MAXDOUBLE, + 1.0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:scale-y: + * + * The vertical scale of the actor. + * + * The #ClutterActor:scale-y property is animatable. + * + * Since: 0.6 + */ + obj_props[PROP_SCALE_Y] = + g_param_spec_double ("scale-y", + P_("Scale Y"), + P_("Scale factor on the Y axis"), + -G_MAXDOUBLE, G_MAXDOUBLE, + 1.0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:scale-z: + * + * The scale factor of the actor along the Z axis. + * + * The #ClutterActor:scale-y property is animatable. + * + * Since: 1.12 + */ + obj_props[PROP_SCALE_Z] = + g_param_spec_double ("scale-z", + P_("Scale Z"), + P_("Scale factor on the Z axis"), + -G_MAXDOUBLE, G_MAXDOUBLE, + 1.0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:scale-center-x: + * + * The horizontal center point for scaling + * + * Since: 1.0 + * + * Deprecated: 1.12: Use #ClutterActor:pivot-point instead + */ + obj_props[PROP_SCALE_CENTER_X] = /* XXX:2.0 - remove */ + g_param_spec_float ("scale-center-x", + P_("Scale Center X"), + P_("Horizontal scale center"), + -G_MAXFLOAT, G_MAXFLOAT, + 0.0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + G_PARAM_DEPRECATED); + + /** + * ClutterActor:scale-center-y: + * + * The vertical center point for scaling + * + * Since: 1.0 + * + * Deprecated: 1.12: Use #ClutterActor:pivot-point instead + */ + obj_props[PROP_SCALE_CENTER_Y] = /* XXX:2.0 - remove */ + g_param_spec_float ("scale-center-y", + P_("Scale Center Y"), + P_("Vertical scale center"), + -G_MAXFLOAT, G_MAXFLOAT, + 0.0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + G_PARAM_DEPRECATED); + + /** + * ClutterActor:scale-gravity: + * + * The center point for scaling expressed as a #ClutterGravity + * + * Since: 1.0 + * + * Deprecated: 1.12: Use #ClutterActor:pivot-point instead + */ + obj_props[PROP_SCALE_GRAVITY] = /* XXX:2.0 - remove */ + g_param_spec_enum ("scale-gravity", + P_("Scale Gravity"), + P_("The center of scaling"), + CLUTTER_TYPE_GRAVITY, + CLUTTER_GRAVITY_NONE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + G_PARAM_DEPRECATED); + + /** + * ClutterActor:rotation-angle-x: + * + * The rotation angle on the X axis. + * + * The #ClutterActor:rotation-angle-x property is animatable. + * + * Since: 0.6 + */ + obj_props[PROP_ROTATION_ANGLE_X] = + g_param_spec_double ("rotation-angle-x", + P_("Rotation Angle X"), + P_("The rotation angle on the X axis"), + -G_MAXDOUBLE, G_MAXDOUBLE, + 0.0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:rotation-angle-y: + * + * The rotation angle on the Y axis + * + * The #ClutterActor:rotation-angle-y property is animatable. + * + * Since: 0.6 + */ + obj_props[PROP_ROTATION_ANGLE_Y] = + g_param_spec_double ("rotation-angle-y", + P_("Rotation Angle Y"), + P_("The rotation angle on the Y axis"), + -G_MAXDOUBLE, G_MAXDOUBLE, + 0.0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:rotation-angle-z: + * + * The rotation angle on the Z axis + * + * The #ClutterActor:rotation-angle-z property is animatable. + * + * Since: 0.6 + */ + obj_props[PROP_ROTATION_ANGLE_Z] = + g_param_spec_double ("rotation-angle-z", + P_("Rotation Angle Z"), + P_("The rotation angle on the Z axis"), + -G_MAXDOUBLE, G_MAXDOUBLE, + 0.0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:rotation-center-x: + * + * The rotation center on the X axis. + * + * Since: 0.6 + * + * Deprecated: 1.12: Use #ClutterActor:pivot-point instead + */ + obj_props[PROP_ROTATION_CENTER_X] = /* XXX:2.0 - remove */ + g_param_spec_boxed ("rotation-center-x", + P_("Rotation Center X"), + P_("The rotation center on the X axis"), + CLUTTER_TYPE_VERTEX, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + G_PARAM_DEPRECATED); + + /** + * ClutterActor:rotation-center-y: + * + * The rotation center on the Y axis. + * + * Since: 0.6 + * + * Deprecated: 1.12: Use #ClutterActor:pivot-point instead + */ + obj_props[PROP_ROTATION_CENTER_Y] = /* XXX:2.0 - remove */ + g_param_spec_boxed ("rotation-center-y", + P_("Rotation Center Y"), + P_("The rotation center on the Y axis"), + CLUTTER_TYPE_VERTEX, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + G_PARAM_DEPRECATED); + + /** + * ClutterActor:rotation-center-z: + * + * The rotation center on the Z axis. + * + * Since: 0.6 + * + * Deprecated: 1.12: Use #ClutterActor:pivot-point instead + */ + obj_props[PROP_ROTATION_CENTER_Z] = /* XXX:2.0 - remove */ + g_param_spec_boxed ("rotation-center-z", + P_("Rotation Center Z"), + P_("The rotation center on the Z axis"), + CLUTTER_TYPE_VERTEX, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + G_PARAM_DEPRECATED); + + /** + * ClutterActor:rotation-center-z-gravity: + * + * The rotation center on the Z axis expressed as a #ClutterGravity. + * + * Since: 1.0 + * + * Deprecated: 1.12: Use #ClutterActor:pivot-point instead + */ + obj_props[PROP_ROTATION_CENTER_Z_GRAVITY] = /* XXX:2.0 - remove */ + g_param_spec_enum ("rotation-center-z-gravity", + P_("Rotation Center Z Gravity"), + P_("Center point for rotation around the Z axis"), + CLUTTER_TYPE_GRAVITY, + CLUTTER_GRAVITY_NONE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + G_PARAM_DEPRECATED); + + /** + * ClutterActor:anchor-x: + * + * The X coordinate of an actor's anchor point, relative to + * the actor coordinate space, in pixels. + * + * It is highly recommended not to use #ClutterActor:anchor-x, + * #ClutterActor:anchor-y, and #ClutterActor:anchor-gravity in newly + * written code; the anchor point adds an additional translation that + * will affect the actor's relative position with regards to its + * parent, as well as the position of its children. This change needs + * to always be taken into account when positioning the actor. It is + * recommended to use the #ClutterActor:pivot-point property instead, + * as it will affect only the transformations. + * + * Since: 0.8 + * + * Deprecated: 1.12: Use #ClutterActor:pivot-point instead + */ + obj_props[PROP_ANCHOR_X] = /* XXX:2.0 - remove */ + g_param_spec_float ("anchor-x", + P_("Anchor X"), + P_("X coordinate of the anchor point"), + -G_MAXFLOAT, G_MAXFLOAT, + 0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + G_PARAM_DEPRECATED); + + /** + * ClutterActor:anchor-y: + * + * The Y coordinate of an actor's anchor point, relative to + * the actor coordinate space, in pixels + * + * It is highly recommended not to use #ClutterActor:anchor-x, + * #ClutterActor:anchor-y, and #ClutterActor:anchor-gravity in newly + * written code; the anchor point adds an additional translation that + * will affect the actor's relative position with regards to its + * parent, as well as the position of its children. This change needs + * to always be taken into account when positioning the actor. It is + * recommended to use the #ClutterActor:pivot-point property instead, + * as it will affect only the transformations. + * + * Since: 0.8 + * + * Deprecated: 1.12: Use #ClutterActor:pivot-point instead + */ + obj_props[PROP_ANCHOR_Y] = /* XXX:2.0 - remove */ + g_param_spec_float ("anchor-y", + P_("Anchor Y"), + P_("Y coordinate of the anchor point"), + -G_MAXFLOAT, G_MAXFLOAT, + 0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + G_PARAM_DEPRECATED); + + /** + * ClutterActor:anchor-gravity: + * + * The anchor point expressed as a #ClutterGravity + * + * It is highly recommended not to use #ClutterActor:anchor-x, + * #ClutterActor:anchor-y, and #ClutterActor:anchor-gravity in newly + * written code; the anchor point adds an additional translation that + * will affect the actor's relative position with regards to its + * parent, as well as the position of its children. This change needs + * to always be taken into account when positioning the actor. It is + * recommended to use the #ClutterActor:pivot-point property instead, + * as it will affect only the transformations. + * + * Since: 1.0 + * + * Deprecated: 1.12: Use #ClutterActor:pivot-point instead + */ + obj_props[PROP_ANCHOR_GRAVITY] = /* XXX:2.0 - remove */ + g_param_spec_enum ("anchor-gravity", + P_("Anchor Gravity"), + P_("The anchor point as a ClutterGravity"), + CLUTTER_TYPE_GRAVITY, + CLUTTER_GRAVITY_NONE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + G_PARAM_DEPRECATED); + + /** + * ClutterActor:translation-x: + * + * An additional translation applied along the X axis, relative + * to the actor's #ClutterActor:pivot-point. + * + * The #ClutterActor:translation-x property is animatable. + * + * Since: 1.12 + */ + obj_props[PROP_TRANSLATION_X] = + g_param_spec_float ("translation-x", + P_("Translation X"), + P_("Translation along the X axis"), + -G_MAXFLOAT, G_MAXFLOAT, + 0.f, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:translation-y: + * + * An additional translation applied along the Y axis, relative + * to the actor's #ClutterActor:pivot-point. + * + * The #ClutterActor:translation-y property is animatable. + * + * Since: 1.12 + */ + obj_props[PROP_TRANSLATION_Y] = + g_param_spec_float ("translation-y", + P_("Translation Y"), + P_("Translation along the Y axis"), + -G_MAXFLOAT, G_MAXFLOAT, + 0.f, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:translation-z: + * + * An additional translation applied along the Z axis, relative + * to the actor's #ClutterActor:pivot-point. + * + * The #ClutterActor:translation-z property is animatable. + * + * Since: 1.12 + */ + obj_props[PROP_TRANSLATION_Z] = + g_param_spec_float ("translation-z", + P_("Translation Z"), + P_("Translation along the Z axis"), + -G_MAXFLOAT, G_MAXFLOAT, + 0.f, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:transform: + * + * Overrides the transformations of a #ClutterActor with a custom + * matrix. + * + * The matrix specified by the #ClutterActor:transform property is + * applied to the actor and its children relative to the actor's + * #ClutterActor:allocation and #ClutterActor:pivot-point. + * + * Application code should rarely need to use this function directly. + * + * Setting this property with a #ClutterMatrix will set the + * #ClutterActor:transform-set property to %TRUE as a side effect; + * setting this property with %NULL will set the + * #ClutterActor:transform-set property to %FALSE. + * + * The #ClutterActor:transform property is animatable. + * + * Since: 1.12 + */ + obj_props[PROP_TRANSFORM] = + g_param_spec_boxed ("transform", + P_("Transform"), + P_("Transformation matrix"), + CLUTTER_TYPE_MATRIX, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:transform-set: + * + * Whether the #ClutterActor:transform property is set. + * + * Since: 1.12 + */ + obj_props[PROP_TRANSFORM_SET] = + g_param_spec_boolean ("transform-set", + P_("Transform Set"), + P_("Whether the transform property is set"), + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + /** + * ClutterActor:child-transform: + * + * Applies a transformation matrix on each child of an actor. + * + * Setting this property with a #ClutterMatrix will set the + * #ClutterActor:child-transform-set property to %TRUE as a side effect; + * setting this property with %NULL will set the + * #ClutterActor:child-transform-set property to %FALSE. + * + * The #ClutterActor:child-transform property is animatable. + * + * Since: 1.12 + */ + obj_props[PROP_CHILD_TRANSFORM] = + g_param_spec_boxed ("child-transform", + P_("Child Transform"), + P_("Children transformation matrix"), + CLUTTER_TYPE_MATRIX, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:child-transform-set: + * + * Whether the #ClutterActor:child-transform property is set. + * + * Since: 1.12 + */ + obj_props[PROP_CHILD_TRANSFORM_SET] = + g_param_spec_boolean ("child-transform-set", + P_("Child Transform Set"), + P_("Whether the child-transform property is set"), + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + /** + * ClutterActor:show-on-set-parent: + * + * If %TRUE, the actor is automatically shown when parented. + * + * Calling clutter_actor_hide() on an actor which has not been + * parented will set this property to %FALSE as a side effect. + * + * Since: 0.8 + */ + obj_props[PROP_SHOW_ON_SET_PARENT] = /* XXX:2.0 - remove */ + g_param_spec_boolean ("show-on-set-parent", + P_("Show on set parent"), + P_("Whether the actor is shown when parented"), + TRUE, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActor:clip-to-allocation: + * + * Whether the clip region should track the allocated area + * of the actor. + * + * This property is ignored if a clip area has been explicitly + * set using clutter_actor_set_clip(). + * + * Since: 1.0 + */ + obj_props[PROP_CLIP_TO_ALLOCATION] = + g_param_spec_boolean ("clip-to-allocation", + P_("Clip to Allocation"), + P_("Sets the clip region to track the actor's allocation"), + FALSE, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActor:text-direction: + * + * The direction of the text inside a #ClutterActor. + * + * Since: 1.0 + */ + obj_props[PROP_TEXT_DIRECTION] = + g_param_spec_enum ("text-direction", + P_("Text Direction"), + P_("Direction of the text"), + CLUTTER_TYPE_TEXT_DIRECTION, + CLUTTER_TEXT_DIRECTION_LTR, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActor:has-pointer: + * + * Whether the actor contains the pointer of a #ClutterInputDevice + * or not. + * + * Since: 1.2 + */ + obj_props[PROP_HAS_POINTER] = + g_param_spec_boolean ("has-pointer", + P_("Has Pointer"), + P_("Whether the actor contains the pointer of an input device"), + FALSE, + CLUTTER_PARAM_READABLE); + + /** + * ClutterActor:actions: + * + * Adds a #ClutterAction to the actor + * + * Since: 1.4 + */ + obj_props[PROP_ACTIONS] = + g_param_spec_object ("actions", + P_("Actions"), + P_("Adds an action to the actor"), + CLUTTER_TYPE_ACTION, + CLUTTER_PARAM_WRITABLE); + + /** + * ClutterActor:constraints: + * + * Adds a #ClutterConstraint to the actor + * + * Since: 1.4 + */ + obj_props[PROP_CONSTRAINTS] = + g_param_spec_object ("constraints", + P_("Constraints"), + P_("Adds a constraint to the actor"), + CLUTTER_TYPE_CONSTRAINT, + CLUTTER_PARAM_WRITABLE); + + /** + * ClutterActor:effect: + * + * Adds #ClutterEffect to the list of effects be applied on a #ClutterActor + * + * Since: 1.4 + */ + obj_props[PROP_EFFECT] = + g_param_spec_object ("effect", + P_("Effect"), + P_("Add an effect to be applied on the actor"), + CLUTTER_TYPE_EFFECT, + CLUTTER_PARAM_WRITABLE); + + /** + * ClutterActor:layout-manager: + * + * A delegate object for controlling the layout of the children of + * an actor. + * + * Since: 1.10 + */ + obj_props[PROP_LAYOUT_MANAGER] = + g_param_spec_object ("layout-manager", + P_("Layout Manager"), + P_("The object controlling the layout of an actor's children"), + CLUTTER_TYPE_LAYOUT_MANAGER, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActor:x-expand: + * + * Whether a layout manager should assign more space to the actor on + * the X axis. + * + * Since: 1.12 + */ + obj_props[PROP_X_EXPAND] = + g_param_spec_boolean ("x-expand", + P_("X Expand"), + P_("Whether extra horizontal space should be assigned to the actor"), + FALSE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + /** + * ClutterActor:y-expand: + * + * Whether a layout manager should assign more space to the actor on + * the Y axis. + * + * Since: 1.12 + */ + obj_props[PROP_Y_EXPAND] = + g_param_spec_boolean ("y-expand", + P_("Y Expand"), + P_("Whether extra vertical space should be assigned to the actor"), + FALSE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + /** + * ClutterActor:x-align: + * + * The alignment of an actor on the X axis, if the actor has been given + * extra space for its allocation. See also the #ClutterActor:x-expand + * property. + * + * Since: 1.10 + */ + obj_props[PROP_X_ALIGN] = + g_param_spec_enum ("x-align", + P_("X Alignment"), + P_("The alignment of the actor on the X axis within its allocation"), + CLUTTER_TYPE_ACTOR_ALIGN, + CLUTTER_ACTOR_ALIGN_FILL, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActor:y-align: + * + * The alignment of an actor on the Y axis, if the actor has been given + * extra space for its allocation. + * + * Since: 1.10 + */ + obj_props[PROP_Y_ALIGN] = + g_param_spec_enum ("y-align", + P_("Y Alignment"), + P_("The alignment of the actor on the Y axis within its allocation"), + CLUTTER_TYPE_ACTOR_ALIGN, + CLUTTER_ACTOR_ALIGN_FILL, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActor:margin-top: + * + * The margin (in pixels) from the top of the actor. + * + * This property adds a margin to the actor's preferred size; the margin + * will be automatically taken into account when allocating the actor. + * + * The #ClutterActor:margin-top property is animatable. + * + * Since: 1.10 + */ + obj_props[PROP_MARGIN_TOP] = + g_param_spec_float ("margin-top", + P_("Margin Top"), + P_("Extra space at the top"), + 0.0, G_MAXFLOAT, + 0.0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:margin-bottom: + * + * The margin (in pixels) from the bottom of the actor. + * + * This property adds a margin to the actor's preferred size; the margin + * will be automatically taken into account when allocating the actor. + * + * The #ClutterActor:margin-bottom property is animatable. + * + * Since: 1.10 + */ + obj_props[PROP_MARGIN_BOTTOM] = + g_param_spec_float ("margin-bottom", + P_("Margin Bottom"), + P_("Extra space at the bottom"), + 0.0, G_MAXFLOAT, + 0.0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:margin-left: + * + * The margin (in pixels) from the left of the actor. + * + * This property adds a margin to the actor's preferred size; the margin + * will be automatically taken into account when allocating the actor. + * + * The #ClutterActor:margin-left property is animatable. + * + * Since: 1.10 + */ + obj_props[PROP_MARGIN_LEFT] = + g_param_spec_float ("margin-left", + P_("Margin Left"), + P_("Extra space at the left"), + 0.0, G_MAXFLOAT, + 0.0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:margin-right: + * + * The margin (in pixels) from the right of the actor. + * + * This property adds a margin to the actor's preferred size; the margin + * will be automatically taken into account when allocating the actor. + * + * The #ClutterActor:margin-right property is animatable. + * + * Since: 1.10 + */ + obj_props[PROP_MARGIN_RIGHT] = + g_param_spec_float ("margin-right", + P_("Margin Right"), + P_("Extra space at the right"), + 0.0, G_MAXFLOAT, + 0.0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:background-color-set: + * + * Whether the #ClutterActor:background-color property has been set. + * + * Since: 1.10 + */ + obj_props[PROP_BACKGROUND_COLOR_SET] = + g_param_spec_boolean ("background-color-set", + P_("Background Color Set"), + P_("Whether the background color is set"), + FALSE, + CLUTTER_PARAM_READABLE); + + /** + * ClutterActor:background-color: + * + * Paints a solid fill of the actor's allocation using the specified + * color. + * + * The #ClutterActor:background-color property is animatable. + * + * Since: 1.10 + */ + obj_props[PROP_BACKGROUND_COLOR] = + clutter_param_spec_color ("background-color", + P_("Background color"), + P_("The actor's background color"), + CLUTTER_COLOR_Transparent, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + /** + * ClutterActor:first-child: + * + * The actor's first child. + * + * Since: 1.10 + */ + obj_props[PROP_FIRST_CHILD] = + g_param_spec_object ("first-child", + P_("First Child"), + P_("The actor's first child"), + CLUTTER_TYPE_ACTOR, + CLUTTER_PARAM_READABLE); + + /** + * ClutterActor:last-child: + * + * The actor's last child. + * + * Since: 1.10 + */ + obj_props[PROP_LAST_CHILD] = + g_param_spec_object ("last-child", + P_("Last Child"), + P_("The actor's last child"), + CLUTTER_TYPE_ACTOR, + CLUTTER_PARAM_READABLE); + + /** + * ClutterActor:content: + * + * The #ClutterContent implementation that controls the content + * of the actor. + * + * Since: 1.10 + */ + obj_props[PROP_CONTENT] = + g_param_spec_object ("content", + P_("Content"), + P_("Delegate object for painting the actor's content"), + CLUTTER_TYPE_CONTENT, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActor:content-gravity: + * + * The alignment that should be honoured by the #ClutterContent + * set with the #ClutterActor:content property. + * + * Changing the value of this property will change the bounding box of + * the content; you can use the #ClutterActor:content-box property to + * get the position and size of the content within the actor's + * allocation. + * + * This property is meaningful only for #ClutterContent implementations + * that have a preferred size, and if the preferred size is smaller than + * the actor's allocation. + * + * The #ClutterActor:content-gravity property is animatable. + * + * Since: 1.10 + */ + obj_props[PROP_CONTENT_GRAVITY] = + g_param_spec_enum ("content-gravity", + P_("Content Gravity"), + P_("Alignment of the actor's content"), + CLUTTER_TYPE_CONTENT_GRAVITY, + CLUTTER_CONTENT_GRAVITY_RESIZE_FILL, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActor:content-box: + * + * The bounding box for the #ClutterContent used by the actor. + * + * The value of this property is controlled by the #ClutterActor:allocation + * and #ClutterActor:content-gravity properties of #ClutterActor. + * + * The bounding box for the content is guaranteed to never exceed the + * allocation's of the actor. + * + * Since: 1.10 + */ + obj_props[PROP_CONTENT_BOX] = + g_param_spec_boxed ("content-box", + P_("Content Box"), + P_("The bounding box of the actor's content"), + CLUTTER_TYPE_ACTOR_BOX, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + obj_props[PROP_MINIFICATION_FILTER] = + g_param_spec_enum ("minification-filter", + P_("Minification Filter"), + P_("The filter used when reducing the size of the content"), + CLUTTER_TYPE_SCALING_FILTER, + CLUTTER_SCALING_FILTER_LINEAR, + CLUTTER_PARAM_READWRITE); + + obj_props[PROP_MAGNIFICATION_FILTER] = + g_param_spec_enum ("magnification-filter", + P_("Magnification Filter"), + P_("The filter used when increasing the size of the content"), + CLUTTER_TYPE_SCALING_FILTER, + CLUTTER_SCALING_FILTER_LINEAR, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterActor:content-repeat: + * + * The repeat policy for the actor's #ClutterActor:content. + * + * Since: 1.12 + */ + obj_props[PROP_CONTENT_REPEAT] = + g_param_spec_flags ("content-repeat", + P_("Content Repeat"), + P_("The repeat policy for the actor's content"), + CLUTTER_TYPE_CONTENT_REPEAT, + CLUTTER_REPEAT_NONE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, PROP_LAST, obj_props); + + /** + * ClutterActor::destroy: + * @actor: the #ClutterActor which emitted the signal + * + * The ::destroy signal notifies that all references held on the + * actor which emitted it should be released. + * + * The ::destroy signal should be used by all holders of a reference + * on @actor. + * + * This signal might result in the finalization of the #ClutterActor + * if all references are released. + * + * Composite actors and actors implementing the #ClutterContainer + * interface should override the default implementation of the + * class handler of this signal and call clutter_actor_destroy() on + * their children. When overriding the default class handler, it is + * required to chain up to the parent's implementation. + * + * Since: 0.2 + */ + actor_signals[DESTROY] = + g_signal_new (I_("destroy"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, + G_STRUCT_OFFSET (ClutterActorClass, destroy), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + /** + * ClutterActor::show: + * @actor: the object which received the signal + * + * The ::show signal is emitted when an actor is visible and + * rendered on the stage. + * + * Since: 0.2 + */ + actor_signals[SHOW] = + g_signal_new (I_("show"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ClutterActorClass, show), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + /** + * ClutterActor::hide: + * @actor: the object which received the signal + * + * The ::hide signal is emitted when an actor is no longer rendered + * on the stage. + * + * Since: 0.2 + */ + actor_signals[HIDE] = + g_signal_new (I_("hide"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ClutterActorClass, hide), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + /** + * ClutterActor::parent-set: + * @actor: the object which received the signal + * @old_parent: (allow-none): the previous parent of the actor, or %NULL + * + * This signal is emitted when the parent of the actor changes. + * + * Since: 0.2 + */ + actor_signals[PARENT_SET] = + g_signal_new (I_("parent-set"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterActorClass, parent_set), + NULL, NULL, + _clutter_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CLUTTER_TYPE_ACTOR); + + /** + * ClutterActor::queue-redraw: + * @actor: the actor we're bubbling the redraw request through + * @origin: the actor which initiated the redraw request + * + * The ::queue_redraw signal is emitted when clutter_actor_queue_redraw() + * is called on @origin. + * + * The default implementation for #ClutterActor chains up to the + * parent actor and queues a redraw on the parent, thus "bubbling" + * the redraw queue up through the actor graph. The default + * implementation for #ClutterStage queues a clutter_stage_ensure_redraw() + * in a main loop idle handler. + * + * Note that the @origin actor may be the stage, or a container; it + * does not have to be a leaf node in the actor graph. + * + * Toolkits embedding a #ClutterStage which require a redraw and + * relayout cycle can stop the emission of this signal using the + * GSignal API, redraw the UI and then call clutter_stage_ensure_redraw() + * themselves, like: + * + * |[ + * static void + * on_redraw_complete (gpointer data) + * { + * ClutterStage *stage = data; + * + * // execute the Clutter drawing pipeline + * clutter_stage_ensure_redraw (stage); + * } + * + * static void + * on_stage_queue_redraw (ClutterStage *stage) + * { + * // this prevents the default handler to run + * g_signal_stop_emission_by_name (stage, "queue-redraw"); + * + * // queue a redraw with the host toolkit and call + * // a function when the redraw has been completed + * queue_a_redraw (G_CALLBACK (on_redraw_complete), stage); + * } + * ]| + * + * Note: This signal is emitted before the Clutter paint + * pipeline is executed. If you want to know when the pipeline has + * been completed you should use clutter_threads_add_repaint_func() + * or clutter_threads_add_repaint_func_full(). + * + * Since: 1.0 + */ + actor_signals[QUEUE_REDRAW] = + g_signal_new (I_("queue-redraw"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST | + G_SIGNAL_NO_HOOKS, + G_STRUCT_OFFSET (ClutterActorClass, queue_redraw), + NULL, NULL, + _clutter_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CLUTTER_TYPE_ACTOR); + + /** + * ClutterActor::queue-relayout: + * @actor: the actor being queued for relayout + * + * The ::queue_layout signal is emitted when clutter_actor_queue_relayout() + * is called on an actor. + * + * The default implementation for #ClutterActor chains up to the + * parent actor and queues a relayout on the parent, thus "bubbling" + * the relayout queue up through the actor graph. + * + * The main purpose of this signal is to allow relayout to be propagated + * properly in the procense of #ClutterClone actors. Applications will + * not normally need to connect to this signal. + * + * Since: 1.2 + */ + actor_signals[QUEUE_RELAYOUT] = + g_signal_new (I_("queue-relayout"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST | + G_SIGNAL_NO_HOOKS, + G_STRUCT_OFFSET (ClutterActorClass, queue_relayout), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * ClutterActor::event: + * @actor: the actor which received the event + * @event: a #ClutterEvent + * + * The ::event signal is emitted each time an event is received + * by the @actor. This signal will be emitted on every actor, + * following the hierarchy chain, until it reaches the top-level + * container (the #ClutterStage). + * + * Return value: %TRUE if the event has been handled by the actor, + * or %FALSE to continue the emission. + * + * Since: 0.6 + */ + actor_signals[EVENT] = + g_signal_new (I_("event"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterActorClass, event), + _clutter_boolean_handled_accumulator, NULL, + _clutter_marshal_BOOLEAN__BOXED, + G_TYPE_BOOLEAN, 1, + CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); + /** + * ClutterActor::button-press-event: + * @actor: the actor which received the event + * @event: (type ClutterButtonEvent): a #ClutterButtonEvent + * + * The ::button-press-event signal is emitted each time a mouse button + * is pressed on @actor. + * + * Return value: %TRUE if the event has been handled by the actor, + * or %FALSE to continue the emission. + * + * Since: 0.6 + */ + actor_signals[BUTTON_PRESS_EVENT] = + g_signal_new (I_("button-press-event"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterActorClass, button_press_event), + _clutter_boolean_handled_accumulator, NULL, + _clutter_marshal_BOOLEAN__BOXED, + G_TYPE_BOOLEAN, 1, + CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); + /** + * ClutterActor::button-release-event: + * @actor: the actor which received the event + * @event: (type ClutterButtonEvent): a #ClutterButtonEvent + * + * The ::button-release-event signal is emitted each time a mouse button + * is released on @actor. + * + * Return value: %TRUE if the event has been handled by the actor, + * or %FALSE to continue the emission. + * + * Since: 0.6 + */ + actor_signals[BUTTON_RELEASE_EVENT] = + g_signal_new (I_("button-release-event"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterActorClass, button_release_event), + _clutter_boolean_handled_accumulator, NULL, + _clutter_marshal_BOOLEAN__BOXED, + G_TYPE_BOOLEAN, 1, + CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); + /** + * ClutterActor::scroll-event: + * @actor: the actor which received the event + * @event: (type ClutterScrollEvent): a #ClutterScrollEvent + * + * The ::scroll-event signal is emitted each time the mouse is + * scrolled on @actor + * + * Return value: %TRUE if the event has been handled by the actor, + * or %FALSE to continue the emission. + * + * Since: 0.6 + */ + actor_signals[SCROLL_EVENT] = + g_signal_new (I_("scroll-event"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterActorClass, scroll_event), + _clutter_boolean_handled_accumulator, NULL, + _clutter_marshal_BOOLEAN__BOXED, + G_TYPE_BOOLEAN, 1, + CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); + /** + * ClutterActor::key-press-event: + * @actor: the actor which received the event + * @event: (type ClutterKeyEvent): a #ClutterKeyEvent + * + * The ::key-press-event signal is emitted each time a keyboard button + * is pressed while @actor has key focus (see clutter_stage_set_key_focus()). + * + * Return value: %TRUE if the event has been handled by the actor, + * or %FALSE to continue the emission. + * + * Since: 0.6 + */ + actor_signals[KEY_PRESS_EVENT] = + g_signal_new (I_("key-press-event"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterActorClass, key_press_event), + _clutter_boolean_handled_accumulator, NULL, + _clutter_marshal_BOOLEAN__BOXED, + G_TYPE_BOOLEAN, 1, + CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); + /** + * ClutterActor::key-release-event: + * @actor: the actor which received the event + * @event: (type ClutterKeyEvent): a #ClutterKeyEvent + * + * The ::key-release-event signal is emitted each time a keyboard button + * is released while @actor has key focus (see + * clutter_stage_set_key_focus()). + * + * Return value: %TRUE if the event has been handled by the actor, + * or %FALSE to continue the emission. + * + * Since: 0.6 + */ + actor_signals[KEY_RELEASE_EVENT] = + g_signal_new (I_("key-release-event"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterActorClass, key_release_event), + _clutter_boolean_handled_accumulator, NULL, + _clutter_marshal_BOOLEAN__BOXED, + G_TYPE_BOOLEAN, 1, + CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); + /** + * ClutterActor::motion-event: + * @actor: the actor which received the event + * @event: (type ClutterMotionEvent): a #ClutterMotionEvent + * + * The ::motion-event signal is emitted each time the mouse pointer is + * moved over @actor. + * + * Return value: %TRUE if the event has been handled by the actor, + * or %FALSE to continue the emission. + * + * Since: 0.6 + */ + actor_signals[MOTION_EVENT] = + g_signal_new (I_("motion-event"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterActorClass, motion_event), + _clutter_boolean_handled_accumulator, NULL, + _clutter_marshal_BOOLEAN__BOXED, + G_TYPE_BOOLEAN, 1, + CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); + + /** + * ClutterActor::key-focus-in: + * @actor: the actor which now has key focus + * + * The ::key-focus-in signal is emitted when @actor receives key focus. + * + * Since: 0.6 + */ + actor_signals[KEY_FOCUS_IN] = + g_signal_new (I_("key-focus-in"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterActorClass, key_focus_in), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * ClutterActor::key-focus-out: + * @actor: the actor which now has key focus + * + * The ::key-focus-out signal is emitted when @actor loses key focus. + * + * Since: 0.6 + */ + actor_signals[KEY_FOCUS_OUT] = + g_signal_new (I_("key-focus-out"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterActorClass, key_focus_out), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * ClutterActor::enter-event: + * @actor: the actor which the pointer has entered. + * @event: (type ClutterCrossingEvent): a #ClutterCrossingEvent + * + * The ::enter-event signal is emitted when the pointer enters the @actor + * + * Return value: %TRUE if the event has been handled by the actor, + * or %FALSE to continue the emission. + * + * Since: 0.6 + */ + actor_signals[ENTER_EVENT] = + g_signal_new (I_("enter-event"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterActorClass, enter_event), + _clutter_boolean_handled_accumulator, NULL, + _clutter_marshal_BOOLEAN__BOXED, + G_TYPE_BOOLEAN, 1, + CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); + + /** + * ClutterActor::leave-event: + * @actor: the actor which the pointer has left + * @event: (type ClutterCrossingEvent): a #ClutterCrossingEvent + * + * The ::leave-event signal is emitted when the pointer leaves the @actor. + * + * Return value: %TRUE if the event has been handled by the actor, + * or %FALSE to continue the emission. + * + * Since: 0.6 + */ + actor_signals[LEAVE_EVENT] = + g_signal_new (I_("leave-event"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterActorClass, leave_event), + _clutter_boolean_handled_accumulator, NULL, + _clutter_marshal_BOOLEAN__BOXED, + G_TYPE_BOOLEAN, 1, + CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); + + /** + * ClutterActor::captured-event: + * @actor: the actor which received the signal + * @event: a #ClutterEvent + * + * The ::captured-event signal is emitted when an event is captured + * by Clutter. This signal will be emitted starting from the top-level + * container (the #ClutterStage) to the actor which received the event + * going down the hierarchy. This signal can be used to intercept every + * event before the specialized events (like + * ClutterActor::button-press-event or ::key-released-event) are + * emitted. + * + * Return value: %TRUE if the event has been handled by the actor, + * or %FALSE to continue the emission. + * + * Since: 0.6 + */ + actor_signals[CAPTURED_EVENT] = + g_signal_new (I_("captured-event"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterActorClass, captured_event), + _clutter_boolean_handled_accumulator, NULL, + _clutter_marshal_BOOLEAN__BOXED, + G_TYPE_BOOLEAN, 1, + CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); + + /** + * ClutterActor::paint: + * @actor: the #ClutterActor that received the signal + * + * The ::paint signal is emitted each time an actor is being painted. + * + * Subclasses of #ClutterActor should override the #ClutterActorClass.paint + * virtual function paint themselves in that function. + * + * It is strongly discouraged to connect a signal handler to + * the #ClutterActor::paint signal; if you want to change the paint + * sequence of an existing #ClutterActor instance, either create a new + * #ClutterActor class and override the #ClutterActorClass.paint virtual + * function, or use a #ClutterEffect. The #ClutterActor::paint signal + * will be removed in a future version of Clutter. + * + * Since: 0.8 + * + * Deprecated: 1.12: Override the #ClutterActorClass.paint virtual + * function, use a #ClutterContent implementation, or a #ClutterEffect + * instead of connecting to this signal. + */ + actor_signals[PAINT] = + g_signal_new (I_("paint"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST | + G_SIGNAL_NO_HOOKS | + G_SIGNAL_DEPRECATED, + G_STRUCT_OFFSET (ClutterActorClass, paint), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + /** + * ClutterActor::realize: + * @actor: the #ClutterActor that received the signal + * + * The ::realize signal is emitted each time an actor is being + * realized. + * + * Since: 0.8 + * + * Deprecated: 1.16: The signal should not be used in newly + * written code + */ + actor_signals[REALIZE] = + g_signal_new (I_("realize"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_DEPRECATED, + G_STRUCT_OFFSET (ClutterActorClass, realize), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + /** + * ClutterActor::unrealize: + * @actor: the #ClutterActor that received the signal + * + * The ::unrealize signal is emitted each time an actor is being + * unrealized. + * + * Since: 0.8 + * + * Deprecated: 1.16: The signal should not be used in newly + * written code + */ + actor_signals[UNREALIZE] = + g_signal_new (I_("unrealize"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_DEPRECATED, + G_STRUCT_OFFSET (ClutterActorClass, unrealize), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * ClutterActor::pick: + * @actor: the #ClutterActor that received the signal + * @color: the #ClutterColor to be used when picking + * + * The ::pick signal is emitted each time an actor is being painted + * in "pick mode". The pick mode is used to identify the actor during + * the event handling phase, or by clutter_stage_get_actor_at_pos(). + * The actor should paint its shape using the passed @pick_color. + * + * Subclasses of #ClutterActor should override the class signal handler + * and paint themselves in that function. + * + * It is possible to connect a handler to the ::pick signal in order + * to set up some custom aspect of a paint in pick mode. + * + * Since: 1.0 + * Deprecated: 1.12: Override the #ClutterActorClass.pick virtual function + * instead. + */ + actor_signals[PICK] = + g_signal_new (I_("pick"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_DEPRECATED, + G_STRUCT_OFFSET (ClutterActorClass, pick), + NULL, NULL, + _clutter_marshal_VOID__BOXED, + G_TYPE_NONE, 1, + CLUTTER_TYPE_COLOR | G_SIGNAL_TYPE_STATIC_SCOPE); + + /** + * ClutterActor::allocation-changed: + * @actor: the #ClutterActor that emitted the signal + * @box: a #ClutterActorBox with the new allocation + * @flags: #ClutterAllocationFlags for the allocation + * + * The ::allocation-changed signal is emitted when the + * #ClutterActor:allocation property changes. Usually, application + * code should just use the notifications for the :allocation property + * but if you want to track the allocation flags as well, for instance + * to know whether the absolute origin of @actor changed, then you might + * want use this signal instead. + * + * Since: 1.0 + */ + actor_signals[ALLOCATION_CHANGED] = + g_signal_new (I_("allocation-changed"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + _clutter_marshal_VOID__BOXED_FLAGS, + G_TYPE_NONE, 2, + CLUTTER_TYPE_ACTOR_BOX | G_SIGNAL_TYPE_STATIC_SCOPE, + CLUTTER_TYPE_ALLOCATION_FLAGS); + + /** + * ClutterActor::transitions-completed: + * @actor: a #ClutterActor + * + * The ::transitions-completed signal is emitted once all transitions + * involving @actor are complete. + * + * Since: 1.10 + */ + actor_signals[TRANSITIONS_COMPLETED] = + g_signal_new (I_("transitions-completed"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * ClutterActor::transition-stopped: + * @actor: a #ClutterActor + * @name: the name of the transition + * @is_finished: whether the transition was finished, or stopped + * + * The ::transition-stopped signal is emitted once a transition + * is stopped; a transition is stopped once it reached its total + * duration (including eventual repeats), it has been stopped + * using clutter_timeline_stop(), or it has been removed from the + * transitions applied on @actor, using clutter_actor_remove_transition(). + * + * Since: 1.12 + */ + actor_signals[TRANSITION_STOPPED] = + g_signal_new (I_("transition-stopped"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | + G_SIGNAL_NO_HOOKS | G_SIGNAL_DETAILED, + 0, + NULL, NULL, + _clutter_marshal_VOID__STRING_BOOLEAN, + G_TYPE_NONE, 2, + G_TYPE_STRING, + G_TYPE_BOOLEAN); + + /** + * ClutterActor::touch-event: + * @actor: a #ClutterActor + * @event: a #ClutterEvent + * + * The ::touch-event signal is emitted each time a touch + * begin/end/update/cancel event. + * + * Return value: %CLUTTER_EVENT_STOP if the event has been handled by + * the actor, or %CLUTTER_EVENT_PROPAGATE to continue the emission. + * + * Since: 1.12 + */ + actor_signals[TOUCH_EVENT] = + g_signal_new (I_("touch-event"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterActorClass, touch_event), + _clutter_boolean_handled_accumulator, NULL, + _clutter_marshal_BOOLEAN__BOXED, + G_TYPE_BOOLEAN, 1, + CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); +} + +static void +clutter_actor_init (ClutterActor *self) +{ + ClutterActorPrivate *priv; + + self->priv = priv = clutter_actor_get_instance_private (self); + + priv->pick_id = -1; + + priv->opacity = 0xff; + priv->show_on_set_parent = TRUE; + + priv->needs_width_request = TRUE; + priv->needs_height_request = TRUE; + priv->needs_allocation = TRUE; + + priv->cached_width_age = 1; + priv->cached_height_age = 1; + + priv->opacity_override = -1; + priv->enable_model_view_transform = TRUE; + + /* Initialize an empty paint volume to start with */ + _clutter_paint_volume_init_static (&priv->last_paint_volume, NULL); + priv->last_paint_volume_valid = TRUE; + + priv->transform_valid = FALSE; + + /* the default is to stretch the content, to match the + * current behaviour of basically all actors. also, it's + * the easiest thing to compute. + */ + priv->content_gravity = CLUTTER_CONTENT_GRAVITY_RESIZE_FILL; + priv->min_filter = CLUTTER_SCALING_FILTER_LINEAR; + priv->mag_filter = CLUTTER_SCALING_FILTER_LINEAR; + + /* this flag will be set to TRUE if the actor gets a child + * or if the [xy]-expand flags are explicitly set; until + * then, the actor does not need to expand. + * + * this also allows us to avoid computing the expand flag + * when building up a scene. + */ + priv->needs_compute_expand = FALSE; + + /* we start with an easing state with duration forcibly set + * to 0, for backward compatibility. + */ + clutter_actor_save_easing_state (self); + clutter_actor_set_easing_duration (self, 0); +} + +/** + * clutter_actor_new: + * + * Creates a new #ClutterActor. + * + * A newly created actor has a floating reference, which will be sunk + * when it is added to another actor. + * + * Return value: the newly created #ClutterActor + * + * Since: 1.10 + */ +ClutterActor * +clutter_actor_new (void) +{ + return g_object_new (CLUTTER_TYPE_ACTOR, NULL); +} + +/** + * clutter_actor_destroy: + * @self: a #ClutterActor + * + * Destroys an actor. When an actor is destroyed, it will break any + * references it holds to other objects. If the actor is inside a + * container, the actor will be removed. + * + * When you destroy a container, its children will be destroyed as well. + * + * Note: you cannot destroy the #ClutterStage returned by + * clutter_stage_get_default(). + */ +void +clutter_actor_destroy (ClutterActor *self) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + g_object_ref (self); + + /* avoid recursion while destroying */ + if (!CLUTTER_ACTOR_IN_DESTRUCTION (self)) + { + CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_IN_DESTRUCTION); + + g_object_run_dispose (G_OBJECT (self)); + + CLUTTER_UNSET_PRIVATE_FLAGS (self, CLUTTER_IN_DESTRUCTION); + } + + g_object_unref (self); +} + +void +_clutter_actor_finish_queue_redraw (ClutterActor *self, + ClutterPaintVolume *clip) +{ + ClutterActorPrivate *priv = self->priv; + ClutterPaintVolume *pv; + gboolean clipped; + + /* Remove queue entry early in the process, otherwise a new + queue_redraw() during signal handling could put back this + object in the stage redraw list (but the entry is freed as + soon as we return from this function, causing a segfault + later) + */ + priv->queue_redraw_entry = NULL; + + /* If we've been explicitly passed a clip volume then there's + * nothing more to calculate, but otherwise the only thing we know + * is that the change is constrained to the given actor. + * + * The idea is that if we know the paint volume for where the actor + * was last drawn (in eye coordinates) and we also have the paint + * volume for where it will be drawn next (in actor coordinates) + * then if we queue a redraw for both these volumes that will cover + * everything that needs to be redrawn to clear the old view and + * show the latest view of the actor. + * + * Don't clip this redraw if we don't know what position we had for + * the previous redraw since we don't know where to set the clip so + * it will clear the actor as it is currently. + */ + if (clip) + { + _clutter_actor_set_queue_redraw_clip (self, clip); + clipped = TRUE; + } + else if (G_LIKELY (priv->last_paint_volume_valid)) + { + pv = _clutter_actor_get_paint_volume_mutable (self); + if (pv) + { + ClutterActor *stage = _clutter_actor_get_stage_internal (self); + + /* make sure we redraw the actors old position... */ + _clutter_actor_set_queue_redraw_clip (stage, + &priv->last_paint_volume); + _clutter_actor_signal_queue_redraw (stage, stage); + _clutter_actor_set_queue_redraw_clip (stage, NULL); + + /* XXX: Ideally the redraw signal would take a clip volume + * argument, but that would be an ABI break. Until we can + * break the ABI we pass the argument out-of-band + */ + + /* setup the clip for the actors new position... */ + _clutter_actor_set_queue_redraw_clip (self, pv); + clipped = TRUE; + } + else + clipped = FALSE; + } + else + clipped = FALSE; + + _clutter_actor_signal_queue_redraw (self, self); + + /* Just in case anyone is manually firing redraw signals without + * using the public queue_redraw() API we are careful to ensure that + * our out-of-band clip member is cleared before returning... + * + * Note: A NULL clip denotes a full-stage, un-clipped redraw + */ + if (G_LIKELY (clipped)) + _clutter_actor_set_queue_redraw_clip (self, NULL); +} + +static void +_clutter_actor_get_allocation_clip (ClutterActor *self, + ClutterActorBox *clip) +{ + ClutterActorBox allocation; + + /* XXX: we don't care if we get an out of date allocation here + * because clutter_actor_queue_redraw_with_clip knows to ignore + * the clip if the actor's allocation is invalid. + * + * This is noted because clutter_actor_get_allocation_box does some + * unnecessary work to support buggy code with a comment suggesting + * that it could be changed later which would be good for this use + * case! + */ + clutter_actor_get_allocation_box (self, &allocation); + + /* NB: clutter_actor_queue_redraw_with_clip expects a box in the + * actor's own coordinate space but the allocation is in parent + * coordinates */ + clip->x1 = 0; + clip->y1 = 0; + clip->x2 = allocation.x2 - allocation.x1; + clip->y2 = allocation.y2 - allocation.y1; +} + +void +_clutter_actor_queue_redraw_full (ClutterActor *self, + ClutterRedrawFlags flags, + ClutterPaintVolume *volume, + ClutterEffect *effect) +{ + ClutterActorPrivate *priv = self->priv; + ClutterPaintVolume allocation_pv; + ClutterPaintVolume *pv; + gboolean should_free_pv; + ClutterActor *stage; + + /* Here's an outline of the actor queue redraw mechanism: + * + * The process starts in one of the following two functions which + * are wrappers for this function: + * + * clutter_actor_queue_redraw() + * _clutter_actor_queue_redraw_with_clip() + * + * additionally, an effect can queue a redraw by wrapping this + * function in clutter_effect_queue_repaint(). + * + * This functions queues an entry in a list associated with the + * stage which is a list of actors that queued a redraw while + * updating the timelines, performing layouting and processing other + * mainloop sources before the next paint starts. + * + * We aim to minimize the processing done at this point because + * there is a good chance other events will happen while updating + * the scenegraph that would invalidate any expensive work we might + * otherwise try to do here. For example we don't try and resolve + * the screen space bounding box of an actor at this stage so as to + * minimize how much of the screen redraw because it's possible + * something else will happen which will force a full redraw anyway. + * + * When all updates are complete and we come to paint the stage then + * we iterate this list and actually emit the "queue-redraw" signals + * for each of the listed actors which will bubble up to the stage + * for each actor and at that point we will transform the actors + * paint volume into screen coordinates to determine the clip region + * for what needs to be redrawn in the next paint. + * + * Besides minimizing redundant work another reason for this + * deferred design is that it's more likely we will be able to + * determine the paint volume of an actor once we've finished + * updating the scenegraph because its allocation should be up to + * date. NB: If we can't determine an actors paint volume then we + * can't automatically queue a clipped redraw which can make a big + * difference to performance. + * + * So the control flow goes like this: + * One of clutter_actor_queue_redraw(), + * _clutter_actor_queue_redraw_with_clip(), + * or clutter_effect_queue_repaint() + * + * then control moves to: + * _clutter_stage_queue_actor_redraw() + * + * later during _clutter_stage_do_update(), once relayouting is done + * and the scenegraph has been updated we will call: + * _clutter_stage_finish_queue_redraws(). + * + * _clutter_stage_finish_queue_redraws() will call + * _clutter_actor_finish_queue_redraw() for each listed actor. + * + * Note: actors *are* allowed to queue further redraws during this + * process (considering clone actors or texture_new_from_actor which + * respond to their source queueing a redraw by queuing a redraw + * themselves). We repeat the process until the list is empty. + * + * This will result in the "queue-redraw" signal being fired for + * each actor which will pass control to the default signal handler: + * clutter_actor_real_queue_redraw() + * + * This will bubble up to the stages handler: + * clutter_stage_real_queue_redraw() + * + * clutter_stage_real_queue_redraw() will transform the actors paint + * volume into screen space and add it as a clip region for the next + * paint. + */ + + /* ignore queueing a redraw for actors being destroyed */ + if (CLUTTER_ACTOR_IN_DESTRUCTION (self)) + return; + + /* we can ignore unmapped actors, unless they have at least one + * mapped clone or they are inside a cloned branch of the scene + * graph, as unmapped actors will simply be left unpainted. + * + * this allows us to ignore redraws queued on leaf nodes when one + * of their parents has been hidden + */ + if (!CLUTTER_ACTOR_IS_MAPPED (self) && + self->priv->in_cloned_branch == 0 && + !clutter_actor_has_mapped_clones (self)) + { + CLUTTER_NOTE (PAINT, + "Skipping queue_redraw('%s'): mapped=%s, " + "mapped_clones=%s, " + "in_cloned_branch=%s", + _clutter_actor_get_debug_name (self), + CLUTTER_ACTOR_IS_MAPPED (self) ? "yes" : "no", + clutter_actor_has_mapped_clones (self) ? "yes" : "no", + self->priv->in_cloned_branch != 0 ? "yes" : "no"); + return; + } + + /* given the check above we could end up queueing a redraw on an + * unmapped actor with mapped clones, so we cannot assume that + * get_stage() will return a Stage + */ + stage = _clutter_actor_get_stage_internal (self); + if (stage == NULL) + return; + + /* ignore queueing a redraw on stages that are being destroyed */ + if (CLUTTER_ACTOR_IN_DESTRUCTION (stage)) + return; + + if (flags & CLUTTER_REDRAW_CLIPPED_TO_ALLOCATION) + { + ClutterActorBox allocation_clip; + ClutterVertex origin; + + /* If the actor doesn't have a valid allocation then we will + * queue a full stage redraw. */ + if (priv->needs_allocation) + { + /* NB: NULL denotes an undefined clip which will result in a + * full redraw... */ + _clutter_actor_set_queue_redraw_clip (self, NULL); + _clutter_actor_signal_queue_redraw (self, self); + return; + } + + _clutter_paint_volume_init_static (&allocation_pv, self); + pv = &allocation_pv; + + _clutter_actor_get_allocation_clip (self, &allocation_clip); + + origin.x = allocation_clip.x1; + origin.y = allocation_clip.y1; + origin.z = 0; + clutter_paint_volume_set_origin (pv, &origin); + clutter_paint_volume_set_width (pv, + allocation_clip.x2 - allocation_clip.x1); + clutter_paint_volume_set_height (pv, + allocation_clip.y2 - + allocation_clip.y1); + should_free_pv = TRUE; + } + else + { + pv = volume; + should_free_pv = FALSE; + } + + self->priv->queue_redraw_entry = + _clutter_stage_queue_actor_redraw (CLUTTER_STAGE (stage), + priv->queue_redraw_entry, + self, + pv); + + if (should_free_pv) + clutter_paint_volume_free (pv); + + /* If this is the first redraw queued then we can directly use the + effect parameter */ + if (!priv->is_dirty) + priv->effect_to_redraw = effect; + /* Otherwise we need to merge it with the existing effect parameter */ + else if (effect != NULL) + { + /* If there's already an effect then we need to use whichever is + later in the chain of actors. Otherwise a full redraw has + already been queued on the actor so we need to ignore the + effect parameter */ + if (priv->effect_to_redraw != NULL) + { + if (priv->effects == NULL) + g_warning ("Redraw queued with an effect that is " + "not applied to the actor"); + else + { + const GList *l; + + for (l = _clutter_meta_group_peek_metas (priv->effects); + l != NULL; + l = l->next) + { + if (l->data == priv->effect_to_redraw || + l->data == effect) + priv->effect_to_redraw = l->data; + } + } + } + } + else + { + /* If no effect is specified then we need to redraw the whole + actor */ + priv->effect_to_redraw = NULL; + } + + priv->is_dirty = TRUE; +} + +/** + * clutter_actor_queue_redraw: + * @self: A #ClutterActor + * + * Queues up a redraw of an actor and any children. The redraw occurs + * once the main loop becomes idle (after the current batch of events + * has been processed, roughly). + * + * Applications rarely need to call this, as redraws are handled + * automatically by modification functions. + * + * This function will not do anything if @self is not visible, or + * if the actor is inside an invisible part of the scenegraph. + * + * Also be aware that painting is a NOP for actors with an opacity of + * 0 + * + * When you are implementing a custom actor you must queue a redraw + * whenever some private state changes that will affect painting or + * picking of your actor. + */ +void +clutter_actor_queue_redraw (ClutterActor *self) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + _clutter_actor_queue_redraw_full (self, + 0, /* flags */ + NULL, /* clip volume */ + NULL /* effect */); +} + +/*< private > + * _clutter_actor_queue_redraw_with_clip: + * @self: A #ClutterActor + * @flags: A mask of #ClutterRedrawFlags controlling the behaviour of + * this queue redraw. + * @volume: A #ClutterPaintVolume describing the bounds of what needs to be + * redrawn or %NULL if you are just using a @flag to state your + * desired clipping. + * + * Queues up a clipped redraw of an actor and any children. The redraw + * occurs once the main loop becomes idle (after the current batch of + * events has been processed, roughly). + * + * If no flags are given the clip volume is defined by @volume + * specified in actor coordinates and tells Clutter that only content + * within this volume has been changed so Clutter can optionally + * optimize the redraw. + * + * If the %CLUTTER_REDRAW_CLIPPED_TO_ALLOCATION @flag is used, @volume + * should be %NULL and this tells Clutter to use the actor's current + * allocation as a clip box. This flag can only be used for 2D actors, + * because any actor with depth may be projected outside its + * allocation. + * + * Applications rarely need to call this, as redraws are handled + * automatically by modification functions. + * + * This function will not do anything if @self is not visible, or if + * the actor is inside an invisible part of the scenegraph. + * + * Also be aware that painting is a NOP for actors with an opacity of + * 0 + * + * When you are implementing a custom actor you must queue a redraw + * whenever some private state changes that will affect painting or + * picking of your actor. + */ +void +_clutter_actor_queue_redraw_with_clip (ClutterActor *self, + ClutterRedrawFlags flags, + ClutterPaintVolume *volume) +{ + _clutter_actor_queue_redraw_full (self, + flags, /* flags */ + volume, /* clip volume */ + NULL /* effect */); +} + +void +_clutter_actor_queue_only_relayout (ClutterActor *self) +{ + ClutterActorPrivate *priv = self->priv; + + if (CLUTTER_ACTOR_IN_DESTRUCTION (self)) + return; + + if (priv->needs_width_request && + priv->needs_height_request && + priv->needs_allocation) + return; /* save some cpu cycles */ + +#if CLUTTER_ENABLE_DEBUG + if (!CLUTTER_ACTOR_IS_TOPLEVEL (self) && CLUTTER_ACTOR_IN_RELAYOUT (self)) + { + g_warning ("The actor '%s' is currently inside an allocation " + "cycle; calling clutter_actor_queue_relayout() is " + "not recommended", + _clutter_actor_get_debug_name (self)); + } +#endif /* CLUTTER_ENABLE_DEBUG */ + + _clutter_actor_queue_relayout_on_clones (self); + + g_signal_emit (self, actor_signals[QUEUE_RELAYOUT], 0); +} + +/** + * clutter_actor_queue_redraw_with_clip: + * @self: a #ClutterActor + * @clip: (allow-none): a rectangular clip region, or %NULL + * + * Queues a redraw on @self limited to a specific, actor-relative + * rectangular area. + * + * If @clip is %NULL this function is equivalent to + * clutter_actor_queue_redraw(). + * + * Since: 1.10 + */ +void +clutter_actor_queue_redraw_with_clip (ClutterActor *self, + const cairo_rectangle_int_t *clip) +{ + ClutterPaintVolume volume; + ClutterVertex origin; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + if (clip == NULL) + { + clutter_actor_queue_redraw (self); + return; + } + + _clutter_paint_volume_init_static (&volume, self); + + origin.x = clip->x; + origin.y = clip->y; + origin.z = 0.0f; + + clutter_paint_volume_set_origin (&volume, &origin); + clutter_paint_volume_set_width (&volume, clip->width); + clutter_paint_volume_set_height (&volume, clip->height); + + _clutter_actor_queue_redraw_full (self, 0, &volume, NULL); + + clutter_paint_volume_free (&volume); +} + +/** + * clutter_actor_queue_relayout: + * @self: A #ClutterActor + * + * Indicates that the actor's size request or other layout-affecting + * properties may have changed. This function is used inside #ClutterActor + * subclass implementations, not by applications directly. + * + * Queueing a new layout automatically queues a redraw as well. + * + * Since: 0.8 + */ +void +clutter_actor_queue_relayout (ClutterActor *self) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + _clutter_actor_queue_only_relayout (self); + clutter_actor_queue_redraw (self); +} + +/** + * clutter_actor_get_preferred_size: + * @self: a #ClutterActor + * @min_width_p: (out) (allow-none): return location for the minimum + * width, or %NULL + * @min_height_p: (out) (allow-none): return location for the minimum + * height, or %NULL + * @natural_width_p: (out) (allow-none): return location for the natural + * width, or %NULL + * @natural_height_p: (out) (allow-none): return location for the natural + * height, or %NULL + * + * Computes the preferred minimum and natural size of an actor, taking into + * account the actor's geometry management (either height-for-width + * or width-for-height). + * + * The width and height used to compute the preferred height and preferred + * width are the actor's natural ones. + * + * If you need to control the height for the preferred width, or the width for + * the preferred height, you should use clutter_actor_get_preferred_width() + * and clutter_actor_get_preferred_height(), and check the actor's preferred + * geometry management using the #ClutterActor:request-mode property. + * + * Since: 0.8 + */ +void +clutter_actor_get_preferred_size (ClutterActor *self, + gfloat *min_width_p, + gfloat *min_height_p, + gfloat *natural_width_p, + gfloat *natural_height_p) +{ + ClutterActorPrivate *priv; + gfloat min_width, min_height; + gfloat natural_width, natural_height; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + priv = self->priv; + + min_width = min_height = 0; + natural_width = natural_height = 0; + + if (priv->request_mode == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH) + { + CLUTTER_NOTE (LAYOUT, "Preferred size (height-for-width)"); + clutter_actor_get_preferred_width (self, -1, + &min_width, + &natural_width); + clutter_actor_get_preferred_height (self, natural_width, + &min_height, + &natural_height); + } + else if (priv->request_mode == CLUTTER_REQUEST_WIDTH_FOR_HEIGHT) + { + CLUTTER_NOTE (LAYOUT, "Preferred size (width-for-height)"); + clutter_actor_get_preferred_height (self, -1, + &min_height, + &natural_height); + clutter_actor_get_preferred_width (self, natural_height, + &min_width, + &natural_width); + } + else if (priv->request_mode == CLUTTER_REQUEST_CONTENT_SIZE) + { + CLUTTER_NOTE (LAYOUT, "Preferred size (content-size)"); + + if (priv->content != NULL) + clutter_content_get_preferred_size (priv->content, &natural_width, &natural_height); + } + else + { + CLUTTER_NOTE (LAYOUT, "Unknown request mode"); + } + + if (min_width_p) + *min_width_p = min_width; + + if (min_height_p) + *min_height_p = min_height; + + if (natural_width_p) + *natural_width_p = natural_width; + + if (natural_height_p) + *natural_height_p = natural_height; +} + +/*< private > + * effective_align: + * @align: a #ClutterActorAlign + * @direction: a #ClutterTextDirection + * + * Retrieves the correct alignment depending on the text direction + * + * Return value: the effective alignment + */ +static ClutterActorAlign +effective_align (ClutterActorAlign align, + ClutterTextDirection direction) +{ + ClutterActorAlign res; + + switch (align) + { + case CLUTTER_ACTOR_ALIGN_START: + res = (direction == CLUTTER_TEXT_DIRECTION_RTL) + ? CLUTTER_ACTOR_ALIGN_END + : CLUTTER_ACTOR_ALIGN_START; + break; + + case CLUTTER_ACTOR_ALIGN_END: + res = (direction == CLUTTER_TEXT_DIRECTION_RTL) + ? CLUTTER_ACTOR_ALIGN_START + : CLUTTER_ACTOR_ALIGN_END; + break; + + default: + res = align; + break; + } + + return res; +} + +/*< private > + * _clutter_actor_get_effective_x_align: + * @self: a #ClutterActor + * + * Retrieves the effective horizontal alignment, taking into + * consideration the text direction of @self. + * + * Return value: the effective horizontal alignment + */ +ClutterActorAlign +_clutter_actor_get_effective_x_align (ClutterActor *self) +{ + return effective_align (clutter_actor_get_x_align (self), + clutter_actor_get_text_direction (self)); +} + +static inline void +adjust_for_margin (float margin_start, + float margin_end, + float *minimum_size, + float *natural_size, + float *allocated_start, + float *allocated_end) +{ + float min_size = *minimum_size; + float nat_size = *natural_size; + float start = *allocated_start; + float end = *allocated_end; + + min_size = MAX (min_size - (margin_start + margin_end), 0); + nat_size = MAX (nat_size - (margin_start + margin_end), 0); + + *minimum_size = min_size; + *natural_size = nat_size; + + start += margin_start; + end -= margin_end; + + if (end - start >= 0) + { + *allocated_start = start; + *allocated_end = end; + } +} + +static inline void +adjust_for_alignment (ClutterActorAlign alignment, + float natural_size, + float *allocated_start, + float *allocated_end) +{ + float allocated_size = *allocated_end - *allocated_start; + + if (allocated_size <= 0.f) + return; + + switch (alignment) + { + case CLUTTER_ACTOR_ALIGN_FILL: + /* do nothing */ + break; + + case CLUTTER_ACTOR_ALIGN_START: + /* keep start */ + *allocated_end = *allocated_start + MIN (natural_size, allocated_size); + break; + + case CLUTTER_ACTOR_ALIGN_END: + if (allocated_size > natural_size) + { + *allocated_start += (allocated_size - natural_size); + *allocated_end = *allocated_start + natural_size; + } + break; + + case CLUTTER_ACTOR_ALIGN_CENTER: + if (allocated_size > natural_size) + { + *allocated_start += floorf ((allocated_size - natural_size) / 2); + *allocated_end = *allocated_start + MIN (allocated_size, natural_size); + } + break; + } +} + +/*< private > + * clutter_actor_adjust_width: + * @self: a #ClutterActor + * @minimum_width: (inout): the actor's preferred minimum width, which + * will be adjusted depending on the margin + * @natural_width: (inout): the actor's preferred natural width, which + * will be adjusted depending on the margin + * @adjusted_x1: (out): the adjusted x1 for the actor's bounding box + * @adjusted_x2: (out): the adjusted x2 for the actor's bounding box + * + * Adjusts the preferred and allocated position and size of an actor, + * depending on the margin and alignment properties. + */ +static void +clutter_actor_adjust_width (ClutterActor *self, + gfloat *minimum_width, + gfloat *natural_width, + gfloat *adjusted_x1, + gfloat *adjusted_x2) +{ + ClutterTextDirection text_dir; + const ClutterLayoutInfo *info; + + info = _clutter_actor_get_layout_info_or_defaults (self); + text_dir = clutter_actor_get_text_direction (self); + + CLUTTER_NOTE (LAYOUT, "Adjusting allocated X and width"); + + /* this will tweak natural_width to remove the margin, so that + * adjust_for_alignment() will use the correct size + */ + adjust_for_margin (info->margin.left, info->margin.right, + minimum_width, natural_width, + adjusted_x1, adjusted_x2); + + adjust_for_alignment (effective_align (info->x_align, text_dir), + *natural_width, + adjusted_x1, adjusted_x2); +} + +/*< private > + * clutter_actor_adjust_height: + * @self: a #ClutterActor + * @minimum_height: (inout): the actor's preferred minimum height, which + * will be adjusted depending on the margin + * @natural_height: (inout): the actor's preferred natural height, which + * will be adjusted depending on the margin + * @adjusted_y1: (out): the adjusted y1 for the actor's bounding box + * @adjusted_y2: (out): the adjusted y2 for the actor's bounding box + * + * Adjusts the preferred and allocated position and size of an actor, + * depending on the margin and alignment properties. + */ +static void +clutter_actor_adjust_height (ClutterActor *self, + gfloat *minimum_height, + gfloat *natural_height, + gfloat *adjusted_y1, + gfloat *adjusted_y2) +{ + const ClutterLayoutInfo *info; + + info = _clutter_actor_get_layout_info_or_defaults (self); + + CLUTTER_NOTE (LAYOUT, "Adjusting allocated Y and height"); + + /* this will tweak natural_height to remove the margin, so that + * adjust_for_alignment() will use the correct size + */ + adjust_for_margin (info->margin.top, info->margin.bottom, + minimum_height, natural_height, + adjusted_y1, + adjusted_y2); + + /* we don't use effective_align() here, because text direction + * only affects the horizontal axis + */ + adjust_for_alignment (info->y_align, + *natural_height, + adjusted_y1, + adjusted_y2); + +} + +/* looks for a cached size request for this for_size. If not + * found, returns the oldest entry so it can be overwritten */ +static gboolean +_clutter_actor_get_cached_size_request (gfloat for_size, + SizeRequest *cached_size_requests, + SizeRequest **result) +{ + guint i; + + *result = &cached_size_requests[0]; + + for (i = 0; i < N_CACHED_SIZE_REQUESTS; i++) + { + SizeRequest *sr; + + sr = &cached_size_requests[i]; + + if (sr->age > 0 && + sr->for_size == for_size) + { + CLUTTER_NOTE (LAYOUT, "Size cache hit for size: %.2f", for_size); + *result = sr; + return TRUE; + } + else if (sr->age < (*result)->age) + { + *result = sr; + } + } + + CLUTTER_NOTE (LAYOUT, "Size cache miss for size: %.2f", for_size); + + return FALSE; +} + +static void +clutter_actor_update_preferred_size_for_constraints (ClutterActor *self, + ClutterOrientation direction, + float for_size, + float *minimum_size, + float *natural_size) +{ + ClutterActorPrivate *priv = self->priv; + const GList *constraints, *l; + + if (priv->constraints == NULL) + return; + + constraints = _clutter_meta_group_peek_metas (priv->constraints); + for (l = constraints; l != NULL; l = l->next) + { + ClutterConstraint *constraint = l->data; + ClutterActorMeta *meta = l->data; + + if (!clutter_actor_meta_get_enabled (meta)) + continue; + + clutter_constraint_update_preferred_size (constraint, self, + direction, + for_size, + minimum_size, + natural_size); + + CLUTTER_NOTE (LAYOUT, + "Preferred %s of '%s' after constraint '%s': " + "{ min:%.2f, nat:%.2f }", + direction == CLUTTER_ORIENTATION_HORIZONTAL + ? "width" + : "height", + _clutter_actor_get_debug_name (self), + _clutter_actor_meta_get_debug_name (meta), + *minimum_size, *natural_size); + } +} + +/** + * clutter_actor_get_preferred_width: + * @self: A #ClutterActor + * @for_height: available height when computing the preferred width, + * or a negative value to indicate that no height is defined + * @min_width_p: (out) (allow-none): return location for minimum width, + * or %NULL + * @natural_width_p: (out) (allow-none): return location for the natural + * width, or %NULL + * + * Computes the requested minimum and natural widths for an actor, + * optionally depending on the specified height, or if they are + * already computed, returns the cached values. + * + * An actor may not get its request - depending on the layout + * manager that's in effect. + * + * A request should not incorporate the actor's scale or anchor point; + * those transformations do not affect layout, only rendering. + * + * Since: 0.8 + */ +void +clutter_actor_get_preferred_width (ClutterActor *self, + gfloat for_height, + gfloat *min_width_p, + gfloat *natural_width_p) +{ + float request_min_width, request_natural_width; + SizeRequest *cached_size_request; + const ClutterLayoutInfo *info; + ClutterActorPrivate *priv; + gboolean found_in_cache; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + priv = self->priv; + + info = _clutter_actor_get_layout_info_or_defaults (self); + + /* we shortcircuit the case of a fixed size set using set_width() */ + if (priv->min_width_set && priv->natural_width_set) + { + if (min_width_p != NULL) + *min_width_p = info->minimum.width + (info->margin.left + info->margin.right); + + if (natural_width_p != NULL) + *natural_width_p = info->natural.width + (info->margin.left + info->margin.right); + + return; + } + + /* the remaining cases are: + * + * - either min_width or natural_width have been set + * - neither min_width or natural_width have been set + * + * in both cases, we go through the cache (and through the actor in case + * of cache misses) and determine the authoritative value depending on + * the *_set flags. + */ + + if (!priv->needs_width_request) + { + found_in_cache = + _clutter_actor_get_cached_size_request (for_height, + priv->width_requests, + &cached_size_request); + } + else + { + /* if the actor needs a width request we use the first slot */ + found_in_cache = FALSE; + cached_size_request = &priv->width_requests[0]; + } + + if (!found_in_cache) + { + gfloat minimum_width, natural_width; + ClutterActorClass *klass; + + minimum_width = natural_width = 0; + + /* adjust for the margin */ + if (for_height >= 0) + { + for_height -= (info->margin.top + info->margin.bottom); + if (for_height < 0) + for_height = 0; + } + + CLUTTER_NOTE (LAYOUT, "Width request for %.2f px", for_height); + + klass = CLUTTER_ACTOR_GET_CLASS (self); + klass->get_preferred_width (self, for_height, + &minimum_width, + &natural_width); + + /* adjust for constraints */ + clutter_actor_update_preferred_size_for_constraints (self, + CLUTTER_ORIENTATION_HORIZONTAL, + for_height, + &minimum_width, + &natural_width); + + /* adjust for the margin */ + minimum_width += (info->margin.left + info->margin.right); + natural_width += (info->margin.left + info->margin.right); + + /* Due to accumulated float errors, it's better not to warn + * on this, but just fix it. + */ + if (natural_width < minimum_width) + natural_width = minimum_width; + + cached_size_request->min_size = minimum_width; + cached_size_request->natural_size = natural_width; + cached_size_request->for_size = for_height; + cached_size_request->age = priv->cached_width_age; + + priv->cached_width_age += 1; + priv->needs_width_request = FALSE; + } + + if (!priv->min_width_set) + request_min_width = cached_size_request->min_size; + else + request_min_width = info->margin.left + + info->minimum.width + + info->margin.right; + + if (!priv->natural_width_set) + request_natural_width = cached_size_request->natural_size; + else + request_natural_width = info->margin.left + + info->natural.width + + info->margin.right; + + if (min_width_p) + *min_width_p = request_min_width; + + if (natural_width_p) + *natural_width_p = request_natural_width; +} + +/** + * clutter_actor_get_preferred_height: + * @self: A #ClutterActor + * @for_width: available width to assume in computing desired height, + * or a negative value to indicate that no width is defined + * @min_height_p: (out) (allow-none): return location for minimum height, + * or %NULL + * @natural_height_p: (out) (allow-none): return location for natural + * height, or %NULL + * + * Computes the requested minimum and natural heights for an actor, + * or if they are already computed, returns the cached values. + * + * An actor may not get its request - depending on the layout + * manager that's in effect. + * + * A request should not incorporate the actor's scale or anchor point; + * those transformations do not affect layout, only rendering. + * + * Since: 0.8 + */ +void +clutter_actor_get_preferred_height (ClutterActor *self, + gfloat for_width, + gfloat *min_height_p, + gfloat *natural_height_p) +{ + float request_min_height, request_natural_height; + SizeRequest *cached_size_request; + const ClutterLayoutInfo *info; + ClutterActorPrivate *priv; + gboolean found_in_cache; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + priv = self->priv; + + info = _clutter_actor_get_layout_info_or_defaults (self); + + /* we shortcircuit the case of a fixed size set using set_height() */ + if (priv->min_height_set && priv->natural_height_set) + { + if (min_height_p != NULL) + *min_height_p = info->minimum.height + (info->margin.top + info->margin.bottom); + + if (natural_height_p != NULL) + *natural_height_p = info->natural.height + (info->margin.top + info->margin.bottom); + + return; + } + + /* the remaining cases are: + * + * - either min_height or natural_height have been set + * - neither min_height or natural_height have been set + * + * in both cases, we go through the cache (and through the actor in case + * of cache misses) and determine the authoritative value depending on + * the *_set flags. + */ + + if (!priv->needs_height_request) + { + found_in_cache = + _clutter_actor_get_cached_size_request (for_width, + priv->height_requests, + &cached_size_request); + } + else + { + found_in_cache = FALSE; + cached_size_request = &priv->height_requests[0]; + } + + if (!found_in_cache) + { + gfloat minimum_height, natural_height; + ClutterActorClass *klass; + + minimum_height = natural_height = 0; + + CLUTTER_NOTE (LAYOUT, "Height request for %.2f px", for_width); + + /* adjust for margin */ + if (for_width >= 0) + { + for_width -= (info->margin.left + info->margin.right); + if (for_width < 0) + for_width = 0; + } + + klass = CLUTTER_ACTOR_GET_CLASS (self); + klass->get_preferred_height (self, for_width, + &minimum_height, + &natural_height); + + /* adjust for constraints */ + clutter_actor_update_preferred_size_for_constraints (self, + CLUTTER_ORIENTATION_VERTICAL, + for_width, + &minimum_height, + &natural_height); + + /* adjust for margin */ + minimum_height += (info->margin.top + info->margin.bottom); + natural_height += (info->margin.top + info->margin.bottom); + + /* Due to accumulated float errors, it's better not to warn + * on this, but just fix it. + */ + if (natural_height < minimum_height) + natural_height = minimum_height; + + cached_size_request->min_size = minimum_height; + cached_size_request->natural_size = natural_height; + cached_size_request->for_size = for_width; + cached_size_request->age = priv->cached_height_age; + + priv->cached_height_age += 1; + priv->needs_height_request = FALSE; + } + + if (!priv->min_height_set) + request_min_height = cached_size_request->min_size; + else + request_min_height = info->margin.top + + info->minimum.height + + info->margin.bottom; + + if (!priv->natural_height_set) + request_natural_height = cached_size_request->natural_size; + else + request_natural_height = info->margin.top + + info->natural.height + + info->margin.bottom; + + if (min_height_p) + *min_height_p = request_min_height; + + if (natural_height_p) + *natural_height_p = request_natural_height; +} + +/** + * clutter_actor_get_allocation_box: + * @self: A #ClutterActor + * @box: (out): the function fills this in with the actor's allocation + * + * Gets the layout box an actor has been assigned. The allocation can + * only be assumed valid inside a paint() method; anywhere else, it + * may be out-of-date. + * + * An allocation does not incorporate the actor's scale or anchor point; + * those transformations do not affect layout, only rendering. + * + * Do not call any of the clutter_actor_get_allocation_*() family + * of functions inside the implementation of the get_preferred_width() + * or get_preferred_height() virtual functions. + * + * Since: 0.8 + */ +void +clutter_actor_get_allocation_box (ClutterActor *self, + ClutterActorBox *box) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + /* XXX - if needs_allocation=TRUE, we can either 1) g_return_if_fail, + * which limits calling get_allocation to inside paint() basically; or + * we can 2) force a layout, which could be expensive if someone calls + * get_allocation somewhere silly; or we can 3) just return the latest + * value, allowing it to be out-of-date, and assume people know what + * they are doing. + * + * The least-surprises approach that keeps existing code working is + * likely to be 2). People can end up doing some inefficient things, + * though, and in general code that requires 2) is probably broken. + */ + + /* this implements 2) */ + if (G_UNLIKELY (self->priv->needs_allocation)) + { + ClutterActor *stage = _clutter_actor_get_stage_internal (self); + + /* do not queue a relayout on an unparented actor */ + if (stage) + _clutter_stage_maybe_relayout (stage); + } + + /* commenting out the code above and just keeping this assigment + * implements 3) + */ + *box = self->priv->allocation; +} + +static void +clutter_actor_update_constraints (ClutterActor *self, + ClutterActorBox *allocation) +{ + ClutterActorPrivate *priv = self->priv; + const GList *constraints, *l; + + if (priv->constraints == NULL) + return; + + constraints = _clutter_meta_group_peek_metas (priv->constraints); + for (l = constraints; l != NULL; l = l->next) + { + ClutterConstraint *constraint = l->data; + ClutterActorMeta *meta = l->data; + gboolean changed = FALSE; + + if (clutter_actor_meta_get_enabled (meta)) + { + changed |= + clutter_constraint_update_allocation (constraint, + self, + allocation); + + CLUTTER_NOTE (LAYOUT, + "Allocation of '%s' after constraint '%s': " + "{ %.2f, %.2f, %.2f, %.2f } (changed:%s)", + _clutter_actor_get_debug_name (self), + _clutter_actor_meta_get_debug_name (meta), + allocation->x1, + allocation->y1, + allocation->x2, + allocation->y2, + changed ? "yes" : "no"); + } + } +} + +/*< private > + * clutter_actor_adjust_allocation: + * @self: a #ClutterActor + * @allocation: (inout): the allocation to adjust + * + * Adjusts the passed allocation box taking into account the actor's + * layout information, like alignment, expansion, and margin. + */ +static void +clutter_actor_adjust_allocation (ClutterActor *self, + ClutterActorBox *allocation) +{ + ClutterActorBox adj_allocation; + float alloc_width, alloc_height; + float min_width, min_height; + float nat_width, nat_height; + ClutterRequestMode req_mode; + + adj_allocation = *allocation; + + clutter_actor_box_get_size (allocation, &alloc_width, &alloc_height); + + /* There's no point in trying to adjust a zero-sized actor */ + if (alloc_width == 0.f && alloc_height == 0.f) + return; + + /* we want to hit the cache, so we use the public API */ + req_mode = clutter_actor_get_request_mode (self); + + if (req_mode == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH) + { + clutter_actor_get_preferred_width (self, -1, + &min_width, + &nat_width); + clutter_actor_get_preferred_height (self, alloc_width, + &min_height, + &nat_height); + } + else if (req_mode == CLUTTER_REQUEST_WIDTH_FOR_HEIGHT) + { + clutter_actor_get_preferred_height (self, -1, + &min_height, + &nat_height); + clutter_actor_get_preferred_width (self, alloc_height, + &min_width, + &nat_width); + } + else if (req_mode == CLUTTER_REQUEST_CONTENT_SIZE) + { + min_width = min_height = 0; + nat_width = nat_height = 0; + + if (self->priv->content != NULL) + clutter_content_get_preferred_size (self->priv->content, &nat_width, &nat_height); + } + +#ifdef CLUTTER_ENABLE_DEBUG + /* warn about underallocations */ + if (_clutter_diagnostic_enabled () && + (floorf (min_width - alloc_width) > 0 || + floorf (min_height - alloc_height) > 0)) + { + ClutterActor *parent = clutter_actor_get_parent (self); + + /* the only actors that are allowed to be underallocated are the Stage, + * as it doesn't have an implicit size, and Actors that specifically + * told us that they want to opt-out from layout control mechanisms + * through the NO_LAYOUT escape hatch. + */ + if (parent != NULL && + !(self->flags & CLUTTER_ACTOR_NO_LAYOUT) != 0) + { + g_warning (G_STRLOC ": The actor '%s' is getting an allocation " + "of %.2f x %.2f from its parent actor '%s', but its " + "requested minimum size is of %.2f x %.2f", + _clutter_actor_get_debug_name (self), + alloc_width, alloc_height, + _clutter_actor_get_debug_name (parent), + min_width, min_height); + } + } +#endif + + clutter_actor_adjust_width (self, + &min_width, + &nat_width, + &adj_allocation.x1, + &adj_allocation.x2); + + clutter_actor_adjust_height (self, + &min_height, + &nat_height, + &adj_allocation.y1, + &adj_allocation.y2); + + /* we maintain the invariant that an allocation cannot be adjusted + * to be outside the parent-given box + */ + if (adj_allocation.x1 < allocation->x1 || + adj_allocation.y1 < allocation->y1 || + adj_allocation.x2 > allocation->x2 || + adj_allocation.y2 > allocation->y2) + { + g_warning (G_STRLOC ": The actor '%s' tried to adjust its allocation " + "to { %.2f, %.2f, %.2f, %.2f }, which is outside of its " + "original allocation of { %.2f, %.2f, %.2f, %.2f }", + _clutter_actor_get_debug_name (self), + adj_allocation.x1, adj_allocation.y1, + adj_allocation.x2 - adj_allocation.x1, + adj_allocation.y2 - adj_allocation.y1, + allocation->x1, allocation->y1, + allocation->x2 - allocation->x1, + allocation->y2 - allocation->y1); + return; + } + + *allocation = adj_allocation; +} + +static void +clutter_actor_allocate_internal (ClutterActor *self, + const ClutterActorBox *allocation, + ClutterAllocationFlags flags) +{ + ClutterActorClass *klass; + + CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_IN_RELAYOUT); + + CLUTTER_NOTE (LAYOUT, "Calling %s::allocate()", + _clutter_actor_get_debug_name (self)); + + klass = CLUTTER_ACTOR_GET_CLASS (self); + klass->allocate (self, allocation, flags); + + CLUTTER_UNSET_PRIVATE_FLAGS (self, CLUTTER_IN_RELAYOUT); + + /* Caller should call clutter_actor_queue_redraw() if needed + * for that particular case. + */ +} + +/** + * clutter_actor_allocate: + * @self: A #ClutterActor + * @box: new allocation of the actor, in parent-relative coordinates + * @flags: flags that control the allocation + * + * Assigns the size of a #ClutterActor from the given @box. + * + * This function should only be called on the children of an actor when + * overriding the #ClutterActorClass.allocate() virtual function. + * + * This function will adjust the stored allocation to take into account + * the alignment flags set in the #ClutterActor:x-align and + * #ClutterActor:y-align properties, as well as the margin values set in + * the #ClutterActor:margin-top, #ClutterActor:margin-right, + * #ClutterActor:margin-bottom, and #ClutterActor:margin-left properties. + * + * This function will respect the easing state of the #ClutterActor and + * interpolate between the current allocation and the new one if the + * easing state duration is a positive value. + * + * Actors can know from their allocation box whether they have moved + * with respect to their parent actor. The @flags parameter describes + * additional information about the allocation, for instance whether + * the parent has moved with respect to the stage, for example because + * a grandparent's origin has moved. + * + * Since: 0.8 + */ +void +clutter_actor_allocate (ClutterActor *self, + const ClutterActorBox *box, + ClutterAllocationFlags flags) +{ + ClutterActorBox old_allocation, real_allocation; + gboolean origin_changed, child_moved, size_changed; + gboolean stage_allocation_changed; + ClutterActorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + if (G_UNLIKELY (_clutter_actor_get_stage_internal (self) == NULL)) + { + g_warning ("Spurious clutter_actor_allocate called for actor %p/%s " + "which isn't a descendent of the stage!\n", + self, _clutter_actor_get_debug_name (self)); + return; + } + + priv = self->priv; + + old_allocation = priv->allocation; + real_allocation = *box; + + /* constraints are allowed to modify the allocation only here; we do + * this prior to all the other checks so that we can bail out if the + * allocation did not change + */ + clutter_actor_update_constraints (self, &real_allocation); + + /* adjust the allocation depending on the align/margin properties */ + clutter_actor_adjust_allocation (self, &real_allocation); + + if (real_allocation.x2 < real_allocation.x1 || + real_allocation.y2 < real_allocation.y1) + { + g_warning (G_STRLOC ": Actor '%s' tried to allocate a size of %.2f x %.2f", + _clutter_actor_get_debug_name (self), + real_allocation.x2 - real_allocation.x1, + real_allocation.y2 - real_allocation.y1); + } + + /* we allow 0-sized actors, but not negative-sized ones */ + real_allocation.x2 = MAX (real_allocation.x2, real_allocation.x1); + real_allocation.y2 = MAX (real_allocation.y2, real_allocation.y1); + + origin_changed = (flags & CLUTTER_ABSOLUTE_ORIGIN_CHANGED); + + child_moved = (real_allocation.x1 != old_allocation.x1 || + real_allocation.y1 != old_allocation.y1); + + size_changed = (real_allocation.x2 != old_allocation.x2 || + real_allocation.y2 != old_allocation.y2); + + if (origin_changed || child_moved || size_changed) + stage_allocation_changed = TRUE; + else + stage_allocation_changed = FALSE; + + /* If we get an allocation "out of the blue" + * (we did not queue relayout), then we want to + * ignore it. But if we have needs_allocation set, + * we want to guarantee that allocate() virtual + * method is always called, i.e. that queue_relayout() + * always results in an allocate() invocation on + * an actor. + * + * The optimization here is to avoid re-allocating + * actors that did not queue relayout and were + * not moved. + */ + if (!priv->needs_allocation && !stage_allocation_changed) + { + CLUTTER_NOTE (LAYOUT, "No allocation needed"); + return; + } + + if (!stage_allocation_changed) + { + /* If the actor didn't move but needs_allocation is set, we just + * need to allocate the children */ + clutter_actor_allocate_internal (self, &real_allocation, flags); + return; + } + + /* When ABSOLUTE_ORIGIN_CHANGED is passed in to + * clutter_actor_allocate(), it indicates whether the parent has its + * absolute origin moved; when passed in to ClutterActor::allocate() + * virtual method though, it indicates whether the child has its + * absolute origin moved. So we set it when child_moved is TRUE + */ + if (child_moved) + flags |= CLUTTER_ABSOLUTE_ORIGIN_CHANGED; + + /* store the flags here, so that they can be propagated by the + * transition code + */ + self->priv->allocation_flags = flags; + + _clutter_actor_create_transition (self, obj_props[PROP_ALLOCATION], + &priv->allocation, + &real_allocation); +} + +/** + * clutter_actor_set_allocation: + * @self: a #ClutterActor + * @box: a #ClutterActorBox + * @flags: allocation flags + * + * Stores the allocation of @self as defined by @box. + * + * This function can only be called from within the implementation of + * the #ClutterActorClass.allocate() virtual function. + * + * The allocation should have been adjusted to take into account constraints, + * alignment, and margin properties. If you are implementing a #ClutterActor + * subclass that provides its own layout management policy for its children + * instead of using a #ClutterLayoutManager delegate, you should not call + * this function on the children of @self; instead, you should call + * clutter_actor_allocate(), which will adjust the allocation box for + * you. + * + * This function should only be used by subclasses of #ClutterActor + * that wish to store their allocation but cannot chain up to the + * parent's implementation; the default implementation of the + * #ClutterActorClass.allocate() virtual function will call this + * function. + * + * It is important to note that, while chaining up was the recommended + * behaviour for #ClutterActor subclasses prior to the introduction of + * this function, it is recommended to call clutter_actor_set_allocation() + * instead. + * + * If the #ClutterActor is using a #ClutterLayoutManager delegate object + * to handle the allocation of its children, this function will call + * the clutter_layout_manager_allocate() function only if the + * %CLUTTER_DELEGATE_LAYOUT flag is set on @flags, otherwise it is + * expected that the subclass will call clutter_layout_manager_allocate() + * by itself. For instance, the following code: + * + * |[ + * static void + * my_actor_allocate (ClutterActor *actor, + * const ClutterActorBox *allocation, + * ClutterAllocationFlags flags) + * { + * ClutterActorBox new_alloc; + * ClutterAllocationFlags new_flags; + * + * adjust_allocation (allocation, &new_alloc); + * + * new_flags = flags | CLUTTER_DELEGATE_LAYOUT; + * + * // this will use the layout manager set on the actor + * clutter_actor_set_allocation (actor, &new_alloc, new_flags); + * } + * ]| + * + * is equivalent to this: + * + * |[ + * static void + * my_actor_allocate (ClutterActor *actor, + * const ClutterActorBox *allocation, + * ClutterAllocationFlags flags) + * { + * ClutterLayoutManager *layout; + * ClutterActorBox new_alloc; + * + * adjust_allocation (allocation, &new_alloc); + * + * clutter_actor_set_allocation (actor, &new_alloc, flags); + * + * layout = clutter_actor_get_layout_manager (actor); + * clutter_layout_manager_allocate (layout, + * CLUTTER_CONTAINER (actor), + * &new_alloc, + * flags); + * } + * ]| + * + * Since: 1.10 + */ +void +clutter_actor_set_allocation (ClutterActor *self, + const ClutterActorBox *box, + ClutterAllocationFlags flags) +{ + ClutterActorPrivate *priv; + gboolean changed; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (box != NULL); + + if (G_UNLIKELY (!CLUTTER_ACTOR_IN_RELAYOUT (self))) + { + g_critical (G_STRLOC ": The clutter_actor_set_allocation() function " + "can only be called from within the implementation of " + "the ClutterActor::allocate() virtual function."); + return; + } + + priv = self->priv; + + g_object_freeze_notify (G_OBJECT (self)); + + changed = clutter_actor_set_allocation_internal (self, box, flags); + + /* we allocate our children before we notify changes in our geometry, + * so that people connecting to properties will be able to get valid + * data out of the sub-tree of the scene graph that has this actor at + * the root. + */ + clutter_actor_maybe_layout_children (self, box, flags); + + if (changed) + { + ClutterActorBox signal_box = priv->allocation; + ClutterAllocationFlags signal_flags = priv->allocation_flags; + + g_signal_emit (self, actor_signals[ALLOCATION_CHANGED], 0, + &signal_box, + signal_flags); + } + + g_object_thaw_notify (G_OBJECT (self)); +} + +/** + * clutter_actor_set_position: + * @self: A #ClutterActor + * @x: New left position of actor in pixels. + * @y: New top position of actor in pixels. + * + * Sets the actor's fixed position in pixels relative to any parent + * actor. + * + * If a layout manager is in use, this position will override the + * layout manager and force a fixed position. + */ +void +clutter_actor_set_position (ClutterActor *self, + gfloat x, + gfloat y) +{ + ClutterPoint new_position; + ClutterPoint cur_position; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + clutter_point_init (&new_position, x, y); + + cur_position.x = clutter_actor_get_x (self); + cur_position.y = clutter_actor_get_y (self); + + _clutter_actor_create_transition (self, obj_props[PROP_POSITION], + &cur_position, + &new_position); +} + +/** + * clutter_actor_get_fixed_position_set: + * @self: A #ClutterActor + * + * Checks whether an actor has a fixed position set (and will thus be + * unaffected by any layout manager). + * + * Return value: %TRUE if the fixed position is set on the actor + * + * Since: 0.8 + */ +gboolean +clutter_actor_get_fixed_position_set (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); + + return self->priv->position_set; +} + +/** + * clutter_actor_set_fixed_position_set: + * @self: A #ClutterActor + * @is_set: whether to use fixed position + * + * Sets whether an actor has a fixed position set (and will thus be + * unaffected by any layout manager). + * + * Since: 0.8 + */ +void +clutter_actor_set_fixed_position_set (ClutterActor *self, + gboolean is_set) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + if (self->priv->position_set == (is_set != FALSE)) + return; + + if (!is_set) + { + ClutterLayoutInfo *info; + + /* Ensure we set back the default fixed position of 0,0 so that setting + just one of x/y always atomically gets 0 for the other */ + info = _clutter_actor_peek_layout_info (self); + if (info != NULL) + { + info->fixed_pos.x = 0; + info->fixed_pos.y = 0; + } + } + + self->priv->position_set = is_set != FALSE; + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_FIXED_POSITION_SET]); + + clutter_actor_queue_relayout (self); +} + +/** + * clutter_actor_move_by: + * @self: A #ClutterActor + * @dx: Distance to move Actor on X axis. + * @dy: Distance to move Actor on Y axis. + * + * Moves an actor by the specified distance relative to its current + * position in pixels. + * + * This function modifies the fixed position of an actor and thus removes + * it from any layout management. Another way to move an actor is with an + * anchor point, see clutter_actor_set_anchor_point(), or with an additional + * translation, using clutter_actor_set_translation(). + * + * Since: 0.2 + */ +void +clutter_actor_move_by (ClutterActor *self, + gfloat dx, + gfloat dy) +{ + const ClutterLayoutInfo *info; + gfloat x, y; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + info = _clutter_actor_get_layout_info_or_defaults (self); + x = info->fixed_pos.x; + y = info->fixed_pos.y; + + clutter_actor_set_position (self, x + dx, y + dy); +} + +static void +clutter_actor_set_min_width (ClutterActor *self, + gfloat min_width) +{ + ClutterActorPrivate *priv = self->priv; + ClutterActorBox old = { 0, }; + ClutterLayoutInfo *info; + + /* if we are setting the size on a top-level actor and the + * backend only supports static top-levels (e.g. framebuffers) + * then we ignore the passed value and we override it with + * the stage implementation's preferred size. + */ + if (CLUTTER_ACTOR_IS_TOPLEVEL (self) && + clutter_feature_available (CLUTTER_FEATURE_STAGE_STATIC)) + return; + + info = _clutter_actor_get_layout_info (self); + + if (priv->min_width_set && min_width == info->minimum.width) + return; + + g_object_freeze_notify (G_OBJECT (self)); + + clutter_actor_store_old_geometry (self, &old); + + info->minimum.width = min_width; + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_MIN_WIDTH]); + clutter_actor_set_min_width_set (self, TRUE); + + clutter_actor_notify_if_geometry_changed (self, &old); + + g_object_thaw_notify (G_OBJECT (self)); + + clutter_actor_queue_relayout (self); +} + +static void +clutter_actor_set_min_height (ClutterActor *self, + gfloat min_height) + +{ + ClutterActorPrivate *priv = self->priv; + ClutterActorBox old = { 0, }; + ClutterLayoutInfo *info; + + /* if we are setting the size on a top-level actor and the + * backend only supports static top-levels (e.g. framebuffers) + * then we ignore the passed value and we override it with + * the stage implementation's preferred size. + */ + if (CLUTTER_ACTOR_IS_TOPLEVEL (self) && + clutter_feature_available (CLUTTER_FEATURE_STAGE_STATIC)) + return; + + info = _clutter_actor_get_layout_info (self); + + if (priv->min_height_set && min_height == info->minimum.height) + return; + + g_object_freeze_notify (G_OBJECT (self)); + + clutter_actor_store_old_geometry (self, &old); + + info->minimum.height = min_height; + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_MIN_HEIGHT]); + clutter_actor_set_min_height_set (self, TRUE); + + clutter_actor_notify_if_geometry_changed (self, &old); + + g_object_thaw_notify (G_OBJECT (self)); + + clutter_actor_queue_relayout (self); +} + +static void +clutter_actor_set_natural_width (ClutterActor *self, + gfloat natural_width) +{ + ClutterActorPrivate *priv = self->priv; + ClutterActorBox old = { 0, }; + ClutterLayoutInfo *info; + + /* if we are setting the size on a top-level actor and the + * backend only supports static top-levels (e.g. framebuffers) + * then we ignore the passed value and we override it with + * the stage implementation's preferred size. + */ + if (CLUTTER_ACTOR_IS_TOPLEVEL (self) && + clutter_feature_available (CLUTTER_FEATURE_STAGE_STATIC)) + return; + + info = _clutter_actor_get_layout_info (self); + + if (priv->natural_width_set && natural_width == info->natural.width) + return; + + g_object_freeze_notify (G_OBJECT (self)); + + clutter_actor_store_old_geometry (self, &old); + + info->natural.width = natural_width; + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_NATURAL_WIDTH]); + clutter_actor_set_natural_width_set (self, TRUE); + + clutter_actor_notify_if_geometry_changed (self, &old); + + g_object_thaw_notify (G_OBJECT (self)); + + clutter_actor_queue_relayout (self); +} + +static void +clutter_actor_set_natural_height (ClutterActor *self, + gfloat natural_height) +{ + ClutterActorPrivate *priv = self->priv; + ClutterActorBox old = { 0, }; + ClutterLayoutInfo *info; + + /* if we are setting the size on a top-level actor and the + * backend only supports static top-levels (e.g. framebuffers) + * then we ignore the passed value and we override it with + * the stage implementation's preferred size. + */ + if (CLUTTER_ACTOR_IS_TOPLEVEL (self) && + clutter_feature_available (CLUTTER_FEATURE_STAGE_STATIC)) + return; + + info = _clutter_actor_get_layout_info (self); + + if (priv->natural_height_set && natural_height == info->natural.height) + return; + + g_object_freeze_notify (G_OBJECT (self)); + + clutter_actor_store_old_geometry (self, &old); + + info->natural.height = natural_height; + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_NATURAL_HEIGHT]); + clutter_actor_set_natural_height_set (self, TRUE); + + clutter_actor_notify_if_geometry_changed (self, &old); + + g_object_thaw_notify (G_OBJECT (self)); + + clutter_actor_queue_relayout (self); +} + +static void +clutter_actor_set_min_width_set (ClutterActor *self, + gboolean use_min_width) +{ + ClutterActorPrivate *priv = self->priv; + ClutterActorBox old = { 0, }; + + if (priv->min_width_set == (use_min_width != FALSE)) + return; + + clutter_actor_store_old_geometry (self, &old); + + priv->min_width_set = use_min_width != FALSE; + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_MIN_WIDTH_SET]); + + clutter_actor_notify_if_geometry_changed (self, &old); + + clutter_actor_queue_relayout (self); +} + +static void +clutter_actor_set_min_height_set (ClutterActor *self, + gboolean use_min_height) +{ + ClutterActorPrivate *priv = self->priv; + ClutterActorBox old = { 0, }; + + if (priv->min_height_set == (use_min_height != FALSE)) + return; + + clutter_actor_store_old_geometry (self, &old); + + priv->min_height_set = use_min_height != FALSE; + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_MIN_HEIGHT_SET]); + + clutter_actor_notify_if_geometry_changed (self, &old); + + clutter_actor_queue_relayout (self); +} + +static void +clutter_actor_set_natural_width_set (ClutterActor *self, + gboolean use_natural_width) +{ + ClutterActorPrivate *priv = self->priv; + ClutterActorBox old = { 0, }; + + if (priv->natural_width_set == (use_natural_width != FALSE)) + return; + + clutter_actor_store_old_geometry (self, &old); + + priv->natural_width_set = use_natural_width != FALSE; + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_NATURAL_WIDTH_SET]); + + clutter_actor_notify_if_geometry_changed (self, &old); + + clutter_actor_queue_relayout (self); +} + +static void +clutter_actor_set_natural_height_set (ClutterActor *self, + gboolean use_natural_height) +{ + ClutterActorPrivate *priv = self->priv; + ClutterActorBox old = { 0, }; + + if (priv->natural_height_set == (use_natural_height != FALSE)) + return; + + clutter_actor_store_old_geometry (self, &old); + + priv->natural_height_set = use_natural_height != FALSE; + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_NATURAL_HEIGHT_SET]); + + clutter_actor_notify_if_geometry_changed (self, &old); + + clutter_actor_queue_relayout (self); +} + +/** + * clutter_actor_set_request_mode: + * @self: a #ClutterActor + * @mode: the request mode + * + * Sets the geometry request mode of @self. + * + * The @mode determines the order for invoking + * clutter_actor_get_preferred_width() and + * clutter_actor_get_preferred_height() + * + * Since: 1.2 + */ +void +clutter_actor_set_request_mode (ClutterActor *self, + ClutterRequestMode mode) +{ + ClutterActorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + priv = self->priv; + + if (priv->request_mode == mode) + return; + + priv->request_mode = mode; + + priv->needs_width_request = TRUE; + priv->needs_height_request = TRUE; + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_REQUEST_MODE]); + + clutter_actor_queue_relayout (self); +} + +/** + * clutter_actor_get_request_mode: + * @self: a #ClutterActor + * + * Retrieves the geometry request mode of @self + * + * Return value: the request mode for the actor + * + * Since: 1.2 + */ +ClutterRequestMode +clutter_actor_get_request_mode (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), + CLUTTER_REQUEST_HEIGHT_FOR_WIDTH); + + return self->priv->request_mode; +} + +/* variant of set_width() without checks and without notification + * freeze+thaw, for internal usage only + */ +static inline void +clutter_actor_set_width_internal (ClutterActor *self, + gfloat width) +{ + if (width >= 0) + { + /* the Stage will use the :min-width to control the minimum + * width to be resized to, so we should not be setting it + * along with the :natural-width + */ + if (!CLUTTER_ACTOR_IS_TOPLEVEL (self)) + clutter_actor_set_min_width (self, width); + + clutter_actor_set_natural_width (self, width); + } + else + { + /* we only unset the :natural-width for the Stage */ + if (!CLUTTER_ACTOR_IS_TOPLEVEL (self)) + clutter_actor_set_min_width_set (self, FALSE); + + clutter_actor_set_natural_width_set (self, FALSE); + } +} + +/* variant of set_height() without checks and without notification + * freeze+thaw, for internal usage only + */ +static inline void +clutter_actor_set_height_internal (ClutterActor *self, + gfloat height) +{ + if (height >= 0) + { + /* see the comment above in set_width_internal() */ + if (!CLUTTER_ACTOR_IS_TOPLEVEL (self)) + clutter_actor_set_min_height (self, height); + + clutter_actor_set_natural_height (self, height); + } + else + { + /* see the comment above in set_width_internal() */ + if (!CLUTTER_ACTOR_IS_TOPLEVEL (self)) + clutter_actor_set_min_height_set (self, FALSE); + + clutter_actor_set_natural_height_set (self, FALSE); + } +} + +static void +clutter_actor_set_size_internal (ClutterActor *self, + const ClutterSize *size) +{ + if (size != NULL) + { + clutter_actor_set_width_internal (self, size->width); + clutter_actor_set_height_internal (self, size->height); + } + else + { + clutter_actor_set_width_internal (self, -1); + clutter_actor_set_height_internal (self, -1); + } +} + +/** + * clutter_actor_set_size: + * @self: A #ClutterActor + * @width: New width of actor in pixels, or -1 + * @height: New height of actor in pixels, or -1 + * + * Sets the actor's size request in pixels. This overrides any + * "normal" size request the actor would have. For example + * a text actor might normally request the size of the text; + * this function would force a specific size instead. + * + * If @width and/or @height are -1 the actor will use its + * "normal" size request instead of overriding it, i.e. + * you can "unset" the size with -1. + * + * This function sets or unsets both the minimum and natural size. + */ +void +clutter_actor_set_size (ClutterActor *self, + gfloat width, + gfloat height) +{ + ClutterSize new_size; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + clutter_size_init (&new_size, width, height); + + /* minor optimization: if we don't have a duration then we can + * skip the get_size() below, to avoid the chance of going through + * get_preferred_width() and get_preferred_height() just to jump to + * a new desired size + */ + if (clutter_actor_get_easing_duration (self) == 0) + { + g_object_freeze_notify (G_OBJECT (self)); + + clutter_actor_set_size_internal (self, &new_size); + + g_object_thaw_notify (G_OBJECT (self)); + + return; + } + else + { + ClutterSize cur_size; + + clutter_size_init (&cur_size, + clutter_actor_get_width (self), + clutter_actor_get_height (self)); + + _clutter_actor_create_transition (self, + obj_props[PROP_SIZE], + &cur_size, + &new_size); + } +} + +/** + * clutter_actor_get_size: + * @self: A #ClutterActor + * @width: (out) (allow-none): return location for the width, or %NULL. + * @height: (out) (allow-none): return location for the height, or %NULL. + * + * This function tries to "do what you mean" and return + * the size an actor will have. If the actor has a valid + * allocation, the allocation will be returned; otherwise, + * the actors natural size request will be returned. + * + * If you care whether you get the request vs. the allocation, you + * should probably call a different function like + * clutter_actor_get_allocation_box() or + * clutter_actor_get_preferred_width(). + * + * Since: 0.2 + */ +void +clutter_actor_get_size (ClutterActor *self, + gfloat *width, + gfloat *height) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + if (width) + *width = clutter_actor_get_width (self); + + if (height) + *height = clutter_actor_get_height (self); +} + +/** + * clutter_actor_get_position: + * @self: a #ClutterActor + * @x: (out) (allow-none): return location for the X coordinate, or %NULL + * @y: (out) (allow-none): return location for the Y coordinate, or %NULL + * + * This function tries to "do what you mean" and tell you where the + * actor is, prior to any transformations. Retrieves the fixed + * position of an actor in pixels, if one has been set; otherwise, if + * the allocation is valid, returns the actor's allocated position; + * otherwise, returns 0,0. + * + * The returned position is in pixels. + * + * Since: 0.6 + */ +void +clutter_actor_get_position (ClutterActor *self, + gfloat *x, + gfloat *y) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + if (x) + *x = clutter_actor_get_x (self); + + if (y) + *y = clutter_actor_get_y (self); +} + +/** + * clutter_actor_get_transformed_position: + * @self: A #ClutterActor + * @x: (out) (allow-none): return location for the X coordinate, or %NULL + * @y: (out) (allow-none): return location for the Y coordinate, or %NULL + * + * Gets the absolute position of an actor, in pixels relative to the stage. + * + * Since: 0.8 + */ +void +clutter_actor_get_transformed_position (ClutterActor *self, + gfloat *x, + gfloat *y) +{ + ClutterVertex v1; + ClutterVertex v2; + + v1.x = v1.y = v1.z = 0; + clutter_actor_apply_transform_to_point (self, &v1, &v2); + + if (x) + *x = v2.x; + + if (y) + *y = v2.y; +} + +/** + * clutter_actor_get_transformed_size: + * @self: A #ClutterActor + * @width: (out) (allow-none): return location for the width, or %NULL + * @height: (out) (allow-none): return location for the height, or %NULL + * + * Gets the absolute size of an actor in pixels, taking into account the + * scaling factors. + * + * If the actor has a valid allocation, the allocated size will be used. + * If the actor has not a valid allocation then the preferred size will + * be transformed and returned. + * + * If you want the transformed allocation, see + * clutter_actor_get_abs_allocation_vertices() instead. + * + * When the actor (or one of its ancestors) is rotated around the + * X or Y axis, it no longer appears as on the stage as a rectangle, but + * as a generic quadrangle; in that case this function returns the size + * of the smallest rectangle that encapsulates the entire quad. Please + * note that in this case no assumptions can be made about the relative + * position of this envelope to the absolute position of the actor, as + * returned by clutter_actor_get_transformed_position(); if you need this + * information, you need to use clutter_actor_get_abs_allocation_vertices() + * to get the coords of the actual quadrangle. + * + * Since: 0.8 + */ +void +clutter_actor_get_transformed_size (ClutterActor *self, + gfloat *width, + gfloat *height) +{ + ClutterActorPrivate *priv; + ClutterVertex v[4]; + gfloat x_min, x_max, y_min, y_max; + gint i; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + priv = self->priv; + + /* if the actor hasn't been allocated yet, get the preferred + * size and transform that + */ + if (priv->needs_allocation) + { + gfloat natural_width, natural_height; + ClutterActorBox box; + + /* Make a fake allocation to transform. + * + * NB: _clutter_actor_transform_and_project_box expects a box in + * the actor's coordinate space... */ + + box.x1 = 0; + box.y1 = 0; + + natural_width = natural_height = 0; + clutter_actor_get_preferred_size (self, NULL, NULL, + &natural_width, + &natural_height); + + box.x2 = natural_width; + box.y2 = natural_height; + + _clutter_actor_transform_and_project_box (self, &box, v); + } + else + clutter_actor_get_abs_allocation_vertices (self, v); + + x_min = x_max = v[0].x; + y_min = y_max = v[0].y; + + for (i = 1; i < G_N_ELEMENTS (v); ++i) + { + if (v[i].x < x_min) + x_min = v[i].x; + + if (v[i].x > x_max) + x_max = v[i].x; + + if (v[i].y < y_min) + y_min = v[i].y; + + if (v[i].y > y_max) + y_max = v[i].y; + } + + if (width) + *width = x_max - x_min; + + if (height) + *height = y_max - y_min; +} + +/** + * clutter_actor_get_width: + * @self: A #ClutterActor + * + * Retrieves the width of a #ClutterActor. + * + * If the actor has a valid allocation, this function will return the + * width of the allocated area given to the actor. + * + * If the actor does not have a valid allocation, this function will + * return the actor's natural width, that is the preferred width of + * the actor. + * + * If you care whether you get the preferred width or the width that + * has been assigned to the actor, you should probably call a different + * function like clutter_actor_get_allocation_box() to retrieve the + * allocated size or clutter_actor_get_preferred_width() to retrieve the + * preferred width. + * + * If an actor has a fixed width, for instance a width that has been + * assigned using clutter_actor_set_width(), the width returned will + * be the same value. + * + * Return value: the width of the actor, in pixels + */ +gfloat +clutter_actor_get_width (ClutterActor *self) +{ + ClutterActorPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0); + + priv = self->priv; + + if (priv->needs_allocation) + { + gfloat natural_width = 0; + + if (priv->request_mode == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH) + { + clutter_actor_get_preferred_width (self, -1, NULL, &natural_width); + } + else if (priv->request_mode == CLUTTER_REQUEST_WIDTH_FOR_HEIGHT) + { + gfloat natural_height = 0; + + clutter_actor_get_preferred_height (self, -1, NULL, &natural_height); + clutter_actor_get_preferred_width (self, natural_height, + NULL, + &natural_width); + } + else if (priv->request_mode == CLUTTER_REQUEST_CONTENT_SIZE && priv->content != NULL) + { + clutter_content_get_preferred_size (priv->content, &natural_width, NULL); + } + + return natural_width; + } + else + return priv->allocation.x2 - priv->allocation.x1; +} + +/** + * clutter_actor_get_height: + * @self: A #ClutterActor + * + * Retrieves the height of a #ClutterActor. + * + * If the actor has a valid allocation, this function will return the + * height of the allocated area given to the actor. + * + * If the actor does not have a valid allocation, this function will + * return the actor's natural height, that is the preferred height of + * the actor. + * + * If you care whether you get the preferred height or the height that + * has been assigned to the actor, you should probably call a different + * function like clutter_actor_get_allocation_box() to retrieve the + * allocated size or clutter_actor_get_preferred_height() to retrieve the + * preferred height. + * + * If an actor has a fixed height, for instance a height that has been + * assigned using clutter_actor_set_height(), the height returned will + * be the same value. + * + * Return value: the height of the actor, in pixels + */ +gfloat +clutter_actor_get_height (ClutterActor *self) +{ + ClutterActorPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0); + + priv = self->priv; + + if (priv->needs_allocation) + { + gfloat natural_height = 0; + + if (priv->request_mode == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH) + { + gfloat natural_width = 0; + + clutter_actor_get_preferred_width (self, -1, NULL, &natural_width); + clutter_actor_get_preferred_height (self, natural_width, + NULL, &natural_height); + } + else if (priv->request_mode == CLUTTER_REQUEST_WIDTH_FOR_HEIGHT) + { + clutter_actor_get_preferred_height (self, -1, NULL, &natural_height); + } + else if (priv->request_mode == CLUTTER_REQUEST_CONTENT_SIZE && priv->content != NULL) + { + clutter_content_get_preferred_size (priv->content, NULL, &natural_height); + } + + return natural_height; + } + else + return priv->allocation.y2 - priv->allocation.y1; +} + +/** + * clutter_actor_set_width: + * @self: A #ClutterActor + * @width: Requested new width for the actor, in pixels, or -1 + * + * Forces a width on an actor, causing the actor's preferred width + * and height (if any) to be ignored. + * + * If @width is -1 the actor will use its preferred width request + * instead of overriding it, i.e. you can "unset" the width with -1. + * + * This function sets both the minimum and natural size of the actor. + * + * since: 0.2 + */ +void +clutter_actor_set_width (ClutterActor *self, + gfloat width) +{ + float cur_size; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + /* minor optimization: if we don't have a duration + * then we can skip the get_width() below, to avoid + * the chance of going through get_preferred_width() + * just to jump to a new desired width. + */ + if (clutter_actor_get_easing_duration (self) == 0) + { + g_object_freeze_notify (G_OBJECT (self)); + + clutter_actor_set_width_internal (self, width); + + g_object_thaw_notify (G_OBJECT (self)); + + return; + } + else + cur_size = clutter_actor_get_width (self); + + _clutter_actor_create_transition (self, + obj_props[PROP_WIDTH], + cur_size, + width); +} + +/** + * clutter_actor_set_height: + * @self: A #ClutterActor + * @height: Requested new height for the actor, in pixels, or -1 + * + * Forces a height on an actor, causing the actor's preferred width + * and height (if any) to be ignored. + * + * If @height is -1 the actor will use its preferred height instead of + * overriding it, i.e. you can "unset" the height with -1. + * + * This function sets both the minimum and natural size of the actor. + * + * since: 0.2 + */ +void +clutter_actor_set_height (ClutterActor *self, + gfloat height) +{ + float cur_size; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + /* see the comment in clutter_actor_set_width() above */ + if (clutter_actor_get_easing_duration (self) == 0) + { + g_object_freeze_notify (G_OBJECT (self)); + + clutter_actor_set_height_internal (self, height); + + g_object_thaw_notify (G_OBJECT (self)); + + return; + } + else + cur_size = clutter_actor_get_height (self); + + _clutter_actor_create_transition (self, + obj_props[PROP_HEIGHT], + cur_size, + height); +} + +static inline void +clutter_actor_set_x_internal (ClutterActor *self, + float x) +{ + ClutterActorPrivate *priv = self->priv; + ClutterLayoutInfo *linfo; + ClutterActorBox old = { 0, }; + + linfo = _clutter_actor_get_layout_info (self); + + if (priv->position_set && linfo->fixed_pos.x == x) + return; + + clutter_actor_store_old_geometry (self, &old); + + linfo->fixed_pos.x = x; + clutter_actor_set_fixed_position_set (self, TRUE); + + clutter_actor_notify_if_geometry_changed (self, &old); + + clutter_actor_queue_relayout (self); +} + +static inline void +clutter_actor_set_y_internal (ClutterActor *self, + float y) +{ + ClutterActorPrivate *priv = self->priv; + ClutterLayoutInfo *linfo; + ClutterActorBox old = { 0, }; + + linfo = _clutter_actor_get_layout_info (self); + + if (priv->position_set && linfo->fixed_pos.y == y) + return; + + clutter_actor_store_old_geometry (self, &old); + + linfo->fixed_pos.y = y; + clutter_actor_set_fixed_position_set (self, TRUE); + + clutter_actor_notify_if_geometry_changed (self, &old); + + clutter_actor_queue_relayout (self); +} + +static void +clutter_actor_set_position_internal (ClutterActor *self, + const ClutterPoint *position) +{ + ClutterActorPrivate *priv = self->priv; + ClutterLayoutInfo *linfo; + ClutterActorBox old = { 0, }; + + linfo = _clutter_actor_get_layout_info (self); + + if (priv->position_set && + clutter_point_equals (position, &linfo->fixed_pos)) + return; + + clutter_actor_store_old_geometry (self, &old); + + if (position != NULL) + { + linfo->fixed_pos = *position; + clutter_actor_set_fixed_position_set (self, TRUE); + } + else + clutter_actor_set_fixed_position_set (self, FALSE); + + clutter_actor_notify_if_geometry_changed (self, &old); + + clutter_actor_queue_relayout (self); +} + +/** + * clutter_actor_set_x: + * @self: a #ClutterActor + * @x: the actor's position on the X axis + * + * Sets the actor's X coordinate, relative to its parent, in pixels. + * + * Overrides any layout manager and forces a fixed position for + * the actor. + * + * The #ClutterActor:x property is animatable. + * + * Since: 0.6 + */ +void +clutter_actor_set_x (ClutterActor *self, + gfloat x) +{ + float cur_position = clutter_actor_get_x (self); + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + _clutter_actor_create_transition (self, obj_props[PROP_X], + cur_position, + x); +} + +/** + * clutter_actor_set_y: + * @self: a #ClutterActor + * @y: the actor's position on the Y axis + * + * Sets the actor's Y coordinate, relative to its parent, in pixels.# + * + * Overrides any layout manager and forces a fixed position for + * the actor. + * + * The #ClutterActor:y property is animatable. + * + * Since: 0.6 + */ +void +clutter_actor_set_y (ClutterActor *self, + gfloat y) +{ + float cur_position = clutter_actor_get_y (self); + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + _clutter_actor_create_transition (self, obj_props[PROP_Y], + cur_position, + y); +} + +/** + * clutter_actor_get_x: + * @self: A #ClutterActor + * + * Retrieves the X coordinate of a #ClutterActor. + * + * This function tries to "do what you mean", by returning the + * correct value depending on the actor's state. + * + * If the actor has a valid allocation, this function will return + * the X coordinate of the origin of the allocation box. + * + * If the actor has any fixed coordinate set using clutter_actor_set_x(), + * clutter_actor_set_position() or clutter_actor_set_geometry(), this + * function will return that coordinate. + * + * If both the allocation and a fixed position are missing, this function + * will return 0. + * + * Return value: the X coordinate, in pixels, ignoring any + * transformation (i.e. scaling, rotation) + */ +gfloat +clutter_actor_get_x (ClutterActor *self) +{ + ClutterActorPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0); + + priv = self->priv; + + if (priv->needs_allocation) + { + if (priv->position_set) + { + const ClutterLayoutInfo *info; + + info = _clutter_actor_get_layout_info_or_defaults (self); + + return info->fixed_pos.x; + } + else + return 0; + } + else + return priv->allocation.x1; +} + +/** + * clutter_actor_get_y: + * @self: A #ClutterActor + * + * Retrieves the Y coordinate of a #ClutterActor. + * + * This function tries to "do what you mean", by returning the + * correct value depending on the actor's state. + * + * If the actor has a valid allocation, this function will return + * the Y coordinate of the origin of the allocation box. + * + * If the actor has any fixed coordinate set using clutter_actor_set_y(), + * clutter_actor_set_position() or clutter_actor_set_geometry(), this + * function will return that coordinate. + * + * If both the allocation and a fixed position are missing, this function + * will return 0. + * + * Return value: the Y coordinate, in pixels, ignoring any + * transformation (i.e. scaling, rotation) + */ +gfloat +clutter_actor_get_y (ClutterActor *self) +{ + ClutterActorPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0); + + priv = self->priv; + + if (priv->needs_allocation) + { + if (priv->position_set) + { + const ClutterLayoutInfo *info; + + info = _clutter_actor_get_layout_info_or_defaults (self); + + return info->fixed_pos.y; + } + else + return 0; + } + else + return priv->allocation.y1; +} + +/** + * clutter_actor_set_scale: + * @self: A #ClutterActor + * @scale_x: double factor to scale actor by horizontally. + * @scale_y: double factor to scale actor by vertically. + * + * Scales an actor with the given factors. + * + * The scale transformation is relative the the #ClutterActor:pivot-point. + * + * The #ClutterActor:scale-x and #ClutterActor:scale-y properties are + * animatable. + * + * Since: 0.2 + */ +void +clutter_actor_set_scale (ClutterActor *self, + gdouble scale_x, + gdouble scale_y) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + g_object_freeze_notify (G_OBJECT (self)); + + clutter_actor_set_scale_factor (self, CLUTTER_X_AXIS, scale_x); + clutter_actor_set_scale_factor (self, CLUTTER_Y_AXIS, scale_y); + + g_object_thaw_notify (G_OBJECT (self)); +} + +/** + * clutter_actor_set_scale_z: + * @self: a #ClutterActor + * @scale_z: the scaling factor along the Z axis + * + * Scales an actor on the Z axis by the given @scale_z factor. + * + * The scale transformation is relative the the #ClutterActor:pivot-point. + * + * The #ClutterActor:scale-z property is animatable. + * + * Since: 1.12 + */ +void +clutter_actor_set_scale_z (ClutterActor *self, + gdouble scale_z) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + clutter_actor_set_scale_factor (self, CLUTTER_Z_AXIS, scale_z); +} + +/** + * clutter_actor_set_scale_full: + * @self: A #ClutterActor + * @scale_x: double factor to scale actor by horizontally. + * @scale_y: double factor to scale actor by vertically. + * @center_x: X coordinate of the center of the scaling + * @center_y: Y coordinate of the center of the scaling + * + * Scales an actor with the given factors around the given center + * point. The center point is specified in pixels relative to the + * anchor point (usually the top left corner of the actor). + * + * The #ClutterActor:scale-x and #ClutterActor:scale-y properties + * are animatable. + * + * Since: 1.0 + * + * Deprecated: 1.12: Use clutter_actor_set_pivot_point() to control + * the scale center + */ +void +clutter_actor_set_scale_full (ClutterActor *self, + gdouble scale_x, + gdouble scale_y, + gfloat center_x, + gfloat center_y) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + g_object_freeze_notify (G_OBJECT (self)); + + clutter_actor_set_scale_factor (self, CLUTTER_X_AXIS, scale_x); + clutter_actor_set_scale_factor (self, CLUTTER_Y_AXIS, scale_y); + clutter_actor_set_scale_center (self, CLUTTER_X_AXIS, center_x); + clutter_actor_set_scale_center (self, CLUTTER_Y_AXIS, center_y); + + g_object_thaw_notify (G_OBJECT (self)); +} + +/** + * clutter_actor_set_scale_with_gravity: + * @self: A #ClutterActor + * @scale_x: double factor to scale actor by horizontally. + * @scale_y: double factor to scale actor by vertically. + * @gravity: the location of the scale center expressed as a compass + * direction. + * + * Scales an actor with the given factors around the given + * center point. The center point is specified as one of the compass + * directions in #ClutterGravity. For example, setting it to north + * will cause the top of the actor to remain unchanged and the rest of + * the actor to expand left, right and downwards. + * + * The #ClutterActor:scale-x and #ClutterActor:scale-y properties are + * animatable. + * + * Since: 1.0 + * + * Deprecated: 1.12: Use clutter_actor_set_pivot_point() to set the + * scale center using normalized coordinates instead. + */ +void +clutter_actor_set_scale_with_gravity (ClutterActor *self, + gdouble scale_x, + gdouble scale_y, + ClutterGravity gravity) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + g_object_freeze_notify (G_OBJECT (self)); + + clutter_actor_set_scale_factor (self, CLUTTER_X_AXIS, scale_x); + clutter_actor_set_scale_factor (self, CLUTTER_Y_AXIS, scale_y); + clutter_actor_set_scale_gravity (self, gravity); + + g_object_thaw_notify (G_OBJECT (self)); +} + +/** + * clutter_actor_get_scale: + * @self: A #ClutterActor + * @scale_x: (out) (allow-none): Location to store horizonal + * scale factor, or %NULL. + * @scale_y: (out) (allow-none): Location to store vertical + * scale factor, or %NULL. + * + * Retrieves an actors scale factors. + * + * Since: 0.2 + */ +void +clutter_actor_get_scale (ClutterActor *self, + gdouble *scale_x, + gdouble *scale_y) +{ + const ClutterTransformInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + info = _clutter_actor_get_transform_info_or_defaults (self); + + if (scale_x) + *scale_x = info->scale_x; + + if (scale_y) + *scale_y = info->scale_y; +} + +/** + * clutter_actor_get_scale_z: + * @self: A #ClutterActor + * + * Retrieves the scaling factor along the Z axis, as set using + * clutter_actor_set_scale_z(). + * + * Return value: the scaling factor along the Z axis + * + * Since: 1.12 + */ +gdouble +clutter_actor_get_scale_z (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 1.0); + + return _clutter_actor_get_transform_info_or_defaults (self)->scale_z; +} + +/** + * clutter_actor_get_scale_center: + * @self: A #ClutterActor + * @center_x: (out) (allow-none): Location to store the X position + * of the scale center, or %NULL. + * @center_y: (out) (allow-none): Location to store the Y position + * of the scale center, or %NULL. + * + * Retrieves the scale center coordinate in pixels relative to the top + * left corner of the actor. If the scale center was specified using a + * #ClutterGravity this will calculate the pixel offset using the + * current size of the actor. + * + * Since: 1.0 + * + * Deprecated: 1.12: Use clutter_actor_get_pivot_point() instead. + */ +void +clutter_actor_get_scale_center (ClutterActor *self, + gfloat *center_x, + gfloat *center_y) +{ + const ClutterTransformInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + info = _clutter_actor_get_transform_info_or_defaults (self); + + clutter_anchor_coord_get_units (self, &info->scale_center, + center_x, + center_y, + NULL); +} + +/** + * clutter_actor_get_scale_gravity: + * @self: A #ClutterActor + * + * Retrieves the scale center as a compass direction. If the scale + * center was specified in pixels or units this will return + * %CLUTTER_GRAVITY_NONE. + * + * Return value: the scale gravity + * + * Since: 1.0 + * + * Deprecated: 1.12: Use clutter_actor_get_pivot_point() instead. + */ +ClutterGravity +clutter_actor_get_scale_gravity (ClutterActor *self) +{ + const ClutterTransformInfo *info; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), CLUTTER_GRAVITY_NONE); + + info = _clutter_actor_get_transform_info_or_defaults (self); + + return clutter_anchor_coord_get_gravity (&info->scale_center); +} + +static inline void +clutter_actor_set_opacity_internal (ClutterActor *self, + guint8 opacity) +{ + ClutterActorPrivate *priv = self->priv; + + if (priv->opacity != opacity) + { + priv->opacity = opacity; + + /* Queue a redraw from the flatten effect so that it can use + its cached image if available instead of having to redraw the + actual actor. If it doesn't end up using the FBO then the + effect is still able to continue the paint anyway. If there + is no flatten effect yet then this is equivalent to queueing + a full redraw */ + _clutter_actor_queue_redraw_full (self, + 0, /* flags */ + NULL, /* clip */ + priv->flatten_effect); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_OPACITY]); + } +} + +/** + * clutter_actor_set_opacity: + * @self: A #ClutterActor + * @opacity: New opacity value for the actor. + * + * Sets the actor's opacity, with zero being completely transparent and + * 255 (0xff) being fully opaque. + * + * The #ClutterActor:opacity property is animatable. + */ +void +clutter_actor_set_opacity (ClutterActor *self, + guint8 opacity) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + _clutter_actor_create_transition (self, obj_props[PROP_OPACITY], + self->priv->opacity, + opacity); +} + +/* + * clutter_actor_get_paint_opacity_internal: + * @self: a #ClutterActor + * + * Retrieves the absolute opacity of the actor, as it appears on the stage + * + * This function does not do type checks + * + * Return value: the absolute opacity of the actor + */ +static guint8 +clutter_actor_get_paint_opacity_internal (ClutterActor *self) +{ + ClutterActorPrivate *priv = self->priv; + ClutterActor *parent; + + /* override the top-level opacity to always be 255; even in + * case of ClutterStage:use-alpha being TRUE we want the rest + * of the scene to be painted + */ + if (CLUTTER_ACTOR_IS_TOPLEVEL (self)) + return 255; + + if (priv->opacity_override >= 0) + return priv->opacity_override; + + parent = priv->parent; + + /* Factor in the actual actors opacity with parents */ + if (parent != NULL) + { + guint8 opacity = clutter_actor_get_paint_opacity_internal (parent); + + if (opacity != 0xff) + return (opacity * priv->opacity) / 0xff; + } + + return priv->opacity; + +} + +/** + * clutter_actor_get_paint_opacity: + * @self: A #ClutterActor + * + * Retrieves the absolute opacity of the actor, as it appears on the stage. + * + * This function traverses the hierarchy chain and composites the opacity of + * the actor with that of its parents. + * + * This function is intended for subclasses to use in the paint virtual + * function, to paint themselves with the correct opacity. + * + * Return value: The actor opacity value. + * + * Since: 0.8 + */ +guint8 +clutter_actor_get_paint_opacity (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0); + + return clutter_actor_get_paint_opacity_internal (self); +} + +/** + * clutter_actor_get_opacity: + * @self: a #ClutterActor + * + * Retrieves the opacity value of an actor, as set by + * clutter_actor_set_opacity(). + * + * For retrieving the absolute opacity of the actor inside a paint + * virtual function, see clutter_actor_get_paint_opacity(). + * + * Return value: the opacity of the actor + */ +guint8 +clutter_actor_get_opacity (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0); + + return self->priv->opacity; +} + +/** + * clutter_actor_set_offscreen_redirect: + * @self: A #ClutterActor + * @redirect: New offscreen redirect flags for the actor. + * + * Defines the circumstances where the actor should be redirected into + * an offscreen image. The offscreen image is used to flatten the + * actor into a single image while painting for two main reasons. + * Firstly, when the actor is painted a second time without any of its + * contents changing it can simply repaint the cached image without + * descending further down the actor hierarchy. Secondly, it will make + * the opacity look correct even if there are overlapping primitives + * in the actor. + * + * Caching the actor could in some cases be a performance win and in + * some cases be a performance lose so it is important to determine + * which value is right for an actor before modifying this value. For + * example, there is never any reason to flatten an actor that is just + * a single texture (such as a #ClutterTexture) because it is + * effectively already cached in an image so the offscreen would be + * redundant. Also if the actor contains primitives that are far apart + * with a large transparent area in the middle (such as a large + * CluterGroup with a small actor in the top left and a small actor in + * the bottom right) then the cached image will contain the entire + * image of the large area and the paint will waste time blending all + * of the transparent pixels in the middle. + * + * The default method of implementing opacity on a container simply + * forwards on the opacity to all of the children. If the children are + * overlapping then it will appear as if they are two separate glassy + * objects and there will be a break in the color where they + * overlap. By redirecting to an offscreen buffer it will be as if the + * two opaque objects are combined into one and then made transparent + * which is usually what is expected. + * + * The image below demonstrates the difference between redirecting and + * not. The image shows two Clutter groups, each containing a red and + * a green rectangle which overlap. The opacity on the group is set to + * 128 (which is 50%). When the offscreen redirect is not used, the + * red rectangle can be seen through the blue rectangle as if the two + * rectangles were separately transparent. When the redirect is used + * the group as a whole is transparent instead so the red rectangle is + * not visible where they overlap. + * + *
+ * Sample of using an offscreen redirect for transparency + * + *
+ * + * The default value for this property is 0, so we effectively will + * never redirect an actor offscreen by default. This means that there + * are times that transparent actors may look glassy as described + * above. The reason this is the default is because there is a + * performance trade off between quality and performance here. In many + * cases the default form of glassy opacity looks good enough, but if + * it's not you will need to set the + * %CLUTTER_OFFSCREEN_REDIRECT_AUTOMATIC_FOR_OPACITY flag to enable + * redirection for opacity. + * + * Custom actors that don't contain any overlapping primitives are + * recommended to override the has_overlaps() virtual to return %FALSE + * for maximum efficiency. + * + * Since: 1.8 + */ +void +clutter_actor_set_offscreen_redirect (ClutterActor *self, + ClutterOffscreenRedirect redirect) +{ + ClutterActorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + priv = self->priv; + + if (priv->offscreen_redirect != redirect) + { + priv->offscreen_redirect = redirect; + + /* Queue a redraw from the effect so that it can use its cached + image if available instead of having to redraw the actual + actor. If it doesn't end up using the FBO then the effect is + still able to continue the paint anyway. If there is no + effect then this is equivalent to queuing a full redraw */ + _clutter_actor_queue_redraw_full (self, + 0, /* flags */ + NULL, /* clip */ + priv->flatten_effect); + + g_object_notify_by_pspec (G_OBJECT (self), + obj_props[PROP_OFFSCREEN_REDIRECT]); + } +} + +/** + * clutter_actor_get_offscreen_redirect: + * @self: a #ClutterActor + * + * Retrieves whether to redirect the actor to an offscreen buffer, as + * set by clutter_actor_set_offscreen_redirect(). + * + * Return value: the value of the offscreen-redirect property of the actor + * + * Since: 1.8 + */ +ClutterOffscreenRedirect +clutter_actor_get_offscreen_redirect (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0); + + return self->priv->offscreen_redirect; +} + +/** + * clutter_actor_set_name: + * @self: A #ClutterActor + * @name: Textual tag to apply to actor + * + * Sets the given name to @self. The name can be used to identify + * a #ClutterActor. + */ +void +clutter_actor_set_name (ClutterActor *self, + const gchar *name) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + g_free (self->priv->name); + self->priv->name = g_strdup (name); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_NAME]); +} + +/** + * clutter_actor_get_name: + * @self: A #ClutterActor + * + * Retrieves the name of @self. + * + * Return value: the name of the actor, or %NULL. The returned string is + * owned by the actor and should not be modified or freed. + */ +const gchar * +clutter_actor_get_name (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + + return self->priv->name; +} + +/** + * clutter_actor_get_gid: + * @self: A #ClutterActor + * + * Retrieves the unique id for @self. + * + * Return value: Globally unique value for this object instance. + * + * Since: 0.6 + * + * Deprecated: 1.8: The id is not used any longer, and this function + * always returns 0. + */ +guint32 +clutter_actor_get_gid (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0); + + return 0; +} + +static inline void +clutter_actor_set_depth_internal (ClutterActor *self, + float depth) +{ + ClutterTransformInfo *info; + + info = _clutter_actor_get_transform_info (self); + + if (info->z_position != depth) + { + /* Sets Z value - XXX 2.0: should we invert? */ + info->z_position = depth; + + self->priv->transform_valid = FALSE; + + /* FIXME - remove this crap; sadly, there are still containers + * in Clutter that depend on this utter brain damage + */ + clutter_container_sort_depth_order (CLUTTER_CONTAINER (self)); + + clutter_actor_queue_redraw (self); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_DEPTH]); + } +} + +static inline void +clutter_actor_set_z_position_internal (ClutterActor *self, + float z_position) +{ + ClutterTransformInfo *info; + + info = _clutter_actor_get_transform_info (self); + + if (memcmp (&info->z_position, &z_position, sizeof (float)) != 0) + { + info->z_position = z_position; + + self->priv->transform_valid = FALSE; + + clutter_actor_queue_redraw (self); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_Z_POSITION]); + } +} + +/** + * clutter_actor_set_z_position: + * @self: a #ClutterActor + * @z_position: the position on the Z axis + * + * Sets the actor's position on the Z axis. + * + * See #ClutterActor:z-position. + * + * Since: 1.12 + */ +void +clutter_actor_set_z_position (ClutterActor *self, + gfloat z_position) +{ + const ClutterTransformInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + info = _clutter_actor_get_transform_info_or_defaults (self); + + _clutter_actor_create_transition (self, obj_props[PROP_Z_POSITION], + info->z_position, + z_position); +} + +/** + * clutter_actor_get_z_position: + * @self: a #ClutterActor + * + * Retrieves the actor's position on the Z axis. + * + * Return value: the position on the Z axis. + * + * Since: 1.12 + */ +gfloat +clutter_actor_get_z_position (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0.f); + + return _clutter_actor_get_transform_info_or_defaults (self)->z_position; +} + +/** + * clutter_actor_set_pivot_point: + * @self: a #ClutterActor + * @pivot_x: the normalized X coordinate of the pivot point + * @pivot_y: the normalized Y coordinate of the pivot point + * + * Sets the position of the #ClutterActor:pivot-point around which the + * scaling and rotation transformations occur. + * + * The pivot point's coordinates are in normalized space, with the (0, 0) + * point being the top left corner of the actor, and the (1, 1) point being + * the bottom right corner. + * + * Since: 1.12 + */ +void +clutter_actor_set_pivot_point (ClutterActor *self, + gfloat pivot_x, + gfloat pivot_y) +{ + ClutterPoint pivot = CLUTTER_POINT_INIT (pivot_x, pivot_y); + const ClutterTransformInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + info = _clutter_actor_get_transform_info_or_defaults (self); + _clutter_actor_create_transition (self, obj_props[PROP_PIVOT_POINT], + &info->pivot, + &pivot); +} + +/** + * clutter_actor_get_pivot_point: + * @self: a #ClutterActor + * @pivot_x: (out) (allow-none): return location for the normalized X + * coordinate of the pivot point, or %NULL + * @pivot_y: (out) (allow-none): return location for the normalized Y + * coordinate of the pivot point, or %NULL + * + * Retrieves the coordinates of the #ClutterActor:pivot-point. + * + * Since: 1.12 + */ +void +clutter_actor_get_pivot_point (ClutterActor *self, + gfloat *pivot_x, + gfloat *pivot_y) +{ + const ClutterTransformInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + info = _clutter_actor_get_transform_info_or_defaults (self); + + if (pivot_x != NULL) + *pivot_x = info->pivot.x; + + if (pivot_y != NULL) + *pivot_y = info->pivot.y; +} + +/** + * clutter_actor_set_pivot_point_z: + * @self: a #ClutterActor + * @pivot_z: the Z coordinate of the actor's pivot point + * + * Sets the component on the Z axis of the #ClutterActor:pivot-point around + * which the scaling and rotation transformations occur. + * + * The @pivot_z value is expressed as a distance along the Z axis. + * + * Since: 1.12 + */ +void +clutter_actor_set_pivot_point_z (ClutterActor *self, + gfloat pivot_z) +{ + const ClutterTransformInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + info = _clutter_actor_get_transform_info_or_defaults (self); + _clutter_actor_create_transition (self, obj_props[PROP_PIVOT_POINT_Z], + info->pivot_z, + pivot_z); +} + +/** + * clutter_actor_get_pivot_point_z: + * @self: a #ClutterActor + * + * Retrieves the Z component of the #ClutterActor:pivot-point. + * + * Since: 1.12 + */ +gfloat +clutter_actor_get_pivot_point_z (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0.f); + + return _clutter_actor_get_transform_info_or_defaults (self)->pivot_z; +} + +/** + * clutter_actor_set_depth: + * @self: a #ClutterActor + * @depth: Z co-ord + * + * Sets the Z coordinate of @self to @depth. + * + * The unit used by @depth is dependant on the perspective setup. See + * also clutter_stage_set_perspective(). + * + * Deprecated: 1.12: Use clutter_actor_set_z_position() instead. + */ +void +clutter_actor_set_depth (ClutterActor *self, + gfloat depth) +{ + const ClutterTransformInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + info = _clutter_actor_get_transform_info_or_defaults (self); + _clutter_actor_create_transition (self, obj_props[PROP_DEPTH], + info->z_position, + depth); +} + +/** + * clutter_actor_get_depth: + * @self: a #ClutterActor + * + * Retrieves the depth of @self. + * + * Return value: the depth of the actor + * + * Deprecated: 1.12: Use clutter_actor_get_z_position() instead. + */ +gfloat +clutter_actor_get_depth (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0.0); + + return _clutter_actor_get_transform_info_or_defaults (self)->z_position; +} + +/** + * clutter_actor_set_rotation: + * @self: a #ClutterActor + * @axis: the axis of rotation + * @angle: the angle of rotation + * @x: X coordinate of the rotation center + * @y: Y coordinate of the rotation center + * @z: Z coordinate of the rotation center + * + * Sets the rotation angle of @self around the given axis. + * + * The rotation center coordinates used depend on the value of @axis: + * + * - %CLUTTER_X_AXIS requires @y and @z + * - %CLUTTER_Y_AXIS requires @x and @z + * - %CLUTTER_Z_AXIS requires @x and @y + * + * The rotation coordinates are relative to the anchor point of the + * actor, set using clutter_actor_set_anchor_point(). If no anchor + * point is set, the upper left corner is assumed as the origin. + * + * Since: 0.8 + * + * Deprecated: 1.12: Use clutter_actor_set_rotation_angle() and + * clutter_actor_set_pivot_point() instead. + */ +void +clutter_actor_set_rotation (ClutterActor *self, + ClutterRotateAxis axis, + gdouble angle, + gfloat x, + gfloat y, + gfloat z) +{ + ClutterVertex v; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + v.x = x; + v.y = y; + v.z = z; + + g_object_freeze_notify (G_OBJECT (self)); + + clutter_actor_set_rotation_angle (self, axis, angle); + clutter_actor_set_rotation_center_internal (self, axis, &v); + + g_object_thaw_notify (G_OBJECT (self)); +} + +/** + * clutter_actor_set_z_rotation_from_gravity: + * @self: a #ClutterActor + * @angle: the angle of rotation + * @gravity: the center point of the rotation + * + * Sets the rotation angle of @self around the Z axis using the center + * point specified as a compass point. For example to rotate such that + * the center of the actor remains static you can use + * %CLUTTER_GRAVITY_CENTER. If the actor changes size the center point + * will move accordingly. + * + * Since: 1.0 + * + * Deprecated: 1.12: Use clutter_actor_set_rotation_angle() and + * clutter_actor_set_pivot_point() instead. + */ +void +clutter_actor_set_z_rotation_from_gravity (ClutterActor *self, + gdouble angle, + ClutterGravity gravity) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + if (gravity == CLUTTER_GRAVITY_NONE) + clutter_actor_set_rotation (self, CLUTTER_Z_AXIS, angle, 0, 0, 0); + else + { + GObject *obj = G_OBJECT (self); + ClutterTransformInfo *info; + GParamSpec *pspec; + + pspec = obj_props[PROP_ROTATION_ANGLE_Z]; + info = _clutter_actor_get_transform_info (self); + + g_object_freeze_notify (obj); + + clutter_actor_set_rotation_angle_internal (self, angle, pspec); + + clutter_anchor_coord_set_gravity (&info->rz_center, gravity); + g_object_notify_by_pspec (obj, obj_props[PROP_ROTATION_CENTER_Z_GRAVITY]); + g_object_notify_by_pspec (obj, obj_props[PROP_ROTATION_CENTER_Z]); + + g_object_thaw_notify (obj); + } +} + +/** + * clutter_actor_get_rotation: + * @self: a #ClutterActor + * @axis: the axis of rotation + * @x: (out): return value for the X coordinate of the center of rotation + * @y: (out): return value for the Y coordinate of the center of rotation + * @z: (out): return value for the Z coordinate of the center of rotation + * + * Retrieves the angle and center of rotation on the given axis, + * set using clutter_actor_set_rotation(). + * + * Return value: the angle of rotation + * + * Since: 0.8 + * + * Deprecated: 1.12: Use clutter_actor_get_rotation_angle() and + * clutter_actor_get_pivot_point() instead. + */ +gdouble +clutter_actor_get_rotation (ClutterActor *self, + ClutterRotateAxis axis, + gfloat *x, + gfloat *y, + gfloat *z) +{ + const ClutterTransformInfo *info; + const AnchorCoord *anchor_coord; + gdouble retval = 0; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0); + + info = _clutter_actor_get_transform_info_or_defaults (self); + + switch (axis) + { + case CLUTTER_X_AXIS: + anchor_coord = &info->rx_center; + retval = info->rx_angle; + break; + + case CLUTTER_Y_AXIS: + anchor_coord = &info->ry_center; + retval = info->ry_angle; + break; + + case CLUTTER_Z_AXIS: + anchor_coord = &info->rz_center; + retval = info->rz_angle; + break; + + default: + anchor_coord = NULL; + retval = 0.0; + break; + } + + clutter_anchor_coord_get_units (self, anchor_coord, x, y, z); + + return retval; +} + +/** + * clutter_actor_get_z_rotation_gravity: + * @self: A #ClutterActor + * + * Retrieves the center for the rotation around the Z axis as a + * compass direction. If the center was specified in pixels or units + * this will return %CLUTTER_GRAVITY_NONE. + * + * Return value: the Z rotation center + * + * Since: 1.0 + * + * Deprecated: 1.12: Use the #ClutterActor:pivot-point instead of + * a #ClutterGravity + */ +ClutterGravity +clutter_actor_get_z_rotation_gravity (ClutterActor *self) +{ + const ClutterTransformInfo *info; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), CLUTTER_GRAVITY_NONE); + + info = _clutter_actor_get_transform_info_or_defaults (self); + + return clutter_anchor_coord_get_gravity (&info->rz_center); +} + +/** + * clutter_actor_set_clip: + * @self: A #ClutterActor + * @xoff: X offset of the clip rectangle + * @yoff: Y offset of the clip rectangle + * @width: Width of the clip rectangle + * @height: Height of the clip rectangle + * + * Sets clip area for @self. The clip area is always computed from the + * upper left corner of the actor, even if the anchor point is set + * otherwise. + * + * Since: 0.6 + */ +void +clutter_actor_set_clip (ClutterActor *self, + gfloat xoff, + gfloat yoff, + gfloat width, + gfloat height) +{ + ClutterActorPrivate *priv; + GObject *obj; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + priv = self->priv; + + if (priv->has_clip && + priv->clip.origin.x == xoff && + priv->clip.origin.y == yoff && + priv->clip.size.width == width && + priv->clip.size.height == height) + return; + + obj = G_OBJECT (self); + + priv->clip.origin.x = xoff; + priv->clip.origin.y = yoff; + priv->clip.size.width = width; + priv->clip.size.height = height; + + priv->has_clip = TRUE; + + clutter_actor_queue_redraw (self); + + g_object_notify_by_pspec (obj, obj_props[PROP_CLIP]); + g_object_notify_by_pspec (obj, obj_props[PROP_CLIP_RECT]); + g_object_notify_by_pspec (obj, obj_props[PROP_HAS_CLIP]); +} + +/** + * clutter_actor_remove_clip: + * @self: A #ClutterActor + * + * Removes clip area from @self. + */ +void +clutter_actor_remove_clip (ClutterActor *self) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + if (!self->priv->has_clip) + return; + + self->priv->has_clip = FALSE; + + clutter_actor_queue_redraw (self); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_HAS_CLIP]); +} + +/** + * clutter_actor_has_clip: + * @self: a #ClutterActor + * + * Determines whether the actor has a clip area set or not. + * + * Return value: %TRUE if the actor has a clip area set. + * + * Since: 0.2 + */ +gboolean +clutter_actor_has_clip (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); + + return self->priv->has_clip; +} + +/** + * clutter_actor_get_clip: + * @self: a #ClutterActor + * @xoff: (out) (allow-none): return location for the X offset of + * the clip rectangle, or %NULL + * @yoff: (out) (allow-none): return location for the Y offset of + * the clip rectangle, or %NULL + * @width: (out) (allow-none): return location for the width of + * the clip rectangle, or %NULL + * @height: (out) (allow-none): return location for the height of + * the clip rectangle, or %NULL + * + * Gets the clip area for @self, if any is set. + * + * Since: 0.6 + */ +void +clutter_actor_get_clip (ClutterActor *self, + gfloat *xoff, + gfloat *yoff, + gfloat *width, + gfloat *height) +{ + ClutterActorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + priv = self->priv; + + if (!priv->has_clip) + return; + + if (xoff != NULL) + *xoff = priv->clip.origin.x; + + if (yoff != NULL) + *yoff = priv->clip.origin.y; + + if (width != NULL) + *width = priv->clip.size.width; + + if (height != NULL) + *height = priv->clip.size.height; +} + +/** + * clutter_actor_get_children: + * @self: a #ClutterActor + * + * Retrieves the list of children of @self. + * + * Return value: (transfer container) (element-type ClutterActor): A newly + * allocated #GList of #ClutterActors. Use g_list_free() when + * done. + * + * Since: 1.10 + */ +GList * +clutter_actor_get_children (ClutterActor *self) +{ + ClutterActor *iter; + GList *res; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + + /* we walk the list backward so that we can use prepend(), + * which is O(1) + */ + for (iter = self->priv->last_child, res = NULL; + iter != NULL; + iter = iter->priv->prev_sibling) + { + res = g_list_prepend (res, iter); + } + + return res; +} + +/*< private > + * insert_child_at_depth: + * @self: a #ClutterActor + * @child: a #ClutterActor + * + * Inserts @child inside the list of children held by @self, using + * the depth as the insertion criteria. + * + * This sadly makes the insertion not O(1), but we can keep the + * list sorted so that the painters algorithm we use for painting + * the children will work correctly. + */ +static void +insert_child_at_depth (ClutterActor *self, + ClutterActor *child, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterActor *iter; + float child_depth; + + child->priv->parent = self; + + child_depth = + _clutter_actor_get_transform_info_or_defaults (child)->z_position; + + /* special-case the first child */ + if (self->priv->n_children == 0) + { + self->priv->first_child = child; + self->priv->last_child = child; + + child->priv->next_sibling = NULL; + child->priv->prev_sibling = NULL; + + return; + } + + /* Find the right place to insert the child so that it will still be + sorted and the child will be after all of the actors at the same + dept */ + for (iter = self->priv->first_child; + iter != NULL; + iter = iter->priv->next_sibling) + { + float iter_depth; + + iter_depth = + _clutter_actor_get_transform_info_or_defaults (iter)->z_position; + + if (iter_depth > child_depth) + break; + } + + if (iter != NULL) + { + ClutterActor *tmp = iter->priv->prev_sibling; + + if (tmp != NULL) + tmp->priv->next_sibling = child; + + /* Insert the node before the found one */ + child->priv->prev_sibling = iter->priv->prev_sibling; + child->priv->next_sibling = iter; + iter->priv->prev_sibling = child; + } + else + { + ClutterActor *tmp = self->priv->last_child; + + if (tmp != NULL) + tmp->priv->next_sibling = child; + + /* insert the node at the end of the list */ + child->priv->prev_sibling = self->priv->last_child; + child->priv->next_sibling = NULL; + } + + if (child->priv->prev_sibling == NULL) + self->priv->first_child = child; + + if (child->priv->next_sibling == NULL) + self->priv->last_child = child; +} + +static void +insert_child_at_index (ClutterActor *self, + ClutterActor *child, + gpointer data_) +{ + gint index_ = GPOINTER_TO_INT (data_); + + child->priv->parent = self; + + if (index_ == 0) + { + ClutterActor *tmp = self->priv->first_child; + + if (tmp != NULL) + tmp->priv->prev_sibling = child; + + child->priv->prev_sibling = NULL; + child->priv->next_sibling = tmp; + } + else if (index_ < 0 || index_ >= self->priv->n_children) + { + ClutterActor *tmp = self->priv->last_child; + + if (tmp != NULL) + tmp->priv->next_sibling = child; + + child->priv->prev_sibling = tmp; + child->priv->next_sibling = NULL; + } + else + { + ClutterActor *iter; + int i; + + for (iter = self->priv->first_child, i = 0; + iter != NULL; + iter = iter->priv->next_sibling, i += 1) + { + if (index_ == i) + { + ClutterActor *tmp = iter->priv->prev_sibling; + + child->priv->prev_sibling = tmp; + child->priv->next_sibling = iter; + + iter->priv->prev_sibling = child; + + if (tmp != NULL) + tmp->priv->next_sibling = child; + + break; + } + } + } + + if (child->priv->prev_sibling == NULL) + self->priv->first_child = child; + + if (child->priv->next_sibling == NULL) + self->priv->last_child = child; +} + +static void +insert_child_above (ClutterActor *self, + ClutterActor *child, + gpointer data) +{ + ClutterActor *sibling = data; + + child->priv->parent = self; + + if (sibling == NULL) + sibling = self->priv->last_child; + + child->priv->prev_sibling = sibling; + + if (sibling != NULL) + { + ClutterActor *tmp = sibling->priv->next_sibling; + + child->priv->next_sibling = tmp; + + if (tmp != NULL) + tmp->priv->prev_sibling = child; + + sibling->priv->next_sibling = child; + } + else + child->priv->next_sibling = NULL; + + if (child->priv->prev_sibling == NULL) + self->priv->first_child = child; + + if (child->priv->next_sibling == NULL) + self->priv->last_child = child; +} + +static void +insert_child_below (ClutterActor *self, + ClutterActor *child, + gpointer data) +{ + ClutterActor *sibling = data; + + child->priv->parent = self; + + if (sibling == NULL) + sibling = self->priv->first_child; + + child->priv->next_sibling = sibling; + + if (sibling != NULL) + { + ClutterActor *tmp = sibling->priv->prev_sibling; + + child->priv->prev_sibling = tmp; + + if (tmp != NULL) + tmp->priv->next_sibling = child; + + sibling->priv->prev_sibling = child; + } + else + child->priv->prev_sibling = NULL; + + if (child->priv->prev_sibling == NULL) + self->priv->first_child = child; + + if (child->priv->next_sibling == NULL) + self->priv->last_child = child; +} + +typedef void (* ClutterActorAddChildFunc) (ClutterActor *parent, + ClutterActor *child, + gpointer data); + +typedef enum { + ADD_CHILD_CREATE_META = 1 << 0, + ADD_CHILD_EMIT_PARENT_SET = 1 << 1, + ADD_CHILD_EMIT_ACTOR_ADDED = 1 << 2, + ADD_CHILD_CHECK_STATE = 1 << 3, + ADD_CHILD_NOTIFY_FIRST_LAST = 1 << 4, + ADD_CHILD_SHOW_ON_SET_PARENT = 1 << 5, + + /* default flags for public API */ + ADD_CHILD_DEFAULT_FLAGS = ADD_CHILD_CREATE_META | + ADD_CHILD_EMIT_PARENT_SET | + ADD_CHILD_EMIT_ACTOR_ADDED | + ADD_CHILD_CHECK_STATE | + ADD_CHILD_NOTIFY_FIRST_LAST | + ADD_CHILD_SHOW_ON_SET_PARENT, + + /* flags for legacy/deprecated API */ + ADD_CHILD_LEGACY_FLAGS = ADD_CHILD_EMIT_PARENT_SET | + ADD_CHILD_CHECK_STATE | + ADD_CHILD_NOTIFY_FIRST_LAST | + ADD_CHILD_SHOW_ON_SET_PARENT +} ClutterActorAddChildFlags; + +/*< private > + * clutter_actor_add_child_internal: + * @self: a #ClutterActor + * @child: a #ClutterActor + * @flags: control flags for actions + * @add_func: delegate function + * @data: (closure): data to pass to @add_func + * + * Adds @child to the list of children of @self. + * + * The actual insertion inside the list is delegated to @add_func: this + * function will just set up the state, perform basic checks, and emit + * signals. + * + * The @flags argument is used to perform additional operations. + */ +static inline void +clutter_actor_add_child_internal (ClutterActor *self, + ClutterActor *child, + ClutterActorAddChildFlags flags, + ClutterActorAddChildFunc add_func, + gpointer data) +{ + ClutterTextDirection text_dir; + gboolean create_meta; + gboolean emit_parent_set, emit_actor_added; + gboolean check_state; + gboolean notify_first_last; + gboolean show_on_set_parent; + ClutterActor *old_first_child, *old_last_child; + GObject *obj; + + if (self == child) + { + g_warning ("Cannot add the actor '%s' to itself.", + _clutter_actor_get_debug_name (self)); + return; + } + + if (child->priv->parent != NULL) + { + g_warning ("The actor '%s' already has a parent, '%s'. You must " + "use clutter_actor_remove_child() first.", + _clutter_actor_get_debug_name (child), + _clutter_actor_get_debug_name (child->priv->parent)); + return; + } + + if (CLUTTER_ACTOR_IS_TOPLEVEL (child)) + { + g_warning ("The actor '%s' is a top-level actor, and cannot be " + "a child of another actor.", + _clutter_actor_get_debug_name (child)); + return; + } + + /* the following check disallows calling methods that change the stacking + * order within the destruction sequence, by triggering a critical + * warning first, and leaving the actor in an undefined state, which + * then ends up being caught by an assertion. + * + * the reproducible sequence is: + * + * - actor gets destroyed; + * - another actor, linked to the first, will try to change the + * stacking order of the first actor; + * - changing the stacking order is a composite operation composed + * by the following steps: + * 1. ref() the child; + * 2. remove_child_internal(), which removes the reference; + * 3. add_child_internal(), which adds a reference; + * - the state of the actor is not changed between (2) and (3), as + * it could be an expensive recomputation; + * - if (3) bails out, then the actor is in an undefined state, but + * still alive; + * - the destruction sequence terminates, but the actor is unparented + * while its state indicates being parented instead. + * - assertion failure. + * + * the obvious fix would be to decompose each set_child_*_sibling() + * method into proper remove_child()/add_child(), with state validation; + * this may cause excessive work, though, and trigger a cascade of other + * bugs in code that assumes that a change in the stacking order is an + * atomic operation. + * + * another potential fix is to just remove this check here, and let + * code doing stacking order changes inside the destruction sequence + * of an actor continue doing the stacking changes as before; this + * option still performs more work than necessary. + * + * the third fix is to silently bail out early from every + * set_child_*_sibling() and set_child_at_index() method, and avoid + * doing stack changes altogether; Clutter implements this last option. + * + * see bug: https://bugzilla.gnome.org/show_bug.cgi?id=670647 + */ + if (CLUTTER_ACTOR_IN_DESTRUCTION (child)) + { + g_warning ("The actor '%s' is currently being destroyed, and " + "cannot be added as a child of another actor.", + _clutter_actor_get_debug_name (child)); + return; + } + + create_meta = (flags & ADD_CHILD_CREATE_META) != 0; + emit_parent_set = (flags & ADD_CHILD_EMIT_PARENT_SET) != 0; + emit_actor_added = (flags & ADD_CHILD_EMIT_ACTOR_ADDED) != 0; + check_state = (flags & ADD_CHILD_CHECK_STATE) != 0; + notify_first_last = (flags & ADD_CHILD_NOTIFY_FIRST_LAST) != 0; + show_on_set_parent = (flags & ADD_CHILD_SHOW_ON_SET_PARENT) != 0; + + old_first_child = self->priv->first_child; + old_last_child = self->priv->last_child; + + obj = G_OBJECT (self); + g_object_freeze_notify (obj); + + if (create_meta) + clutter_container_create_child_meta (CLUTTER_CONTAINER (self), child); + + g_object_ref_sink (child); + child->priv->parent = NULL; + child->priv->next_sibling = NULL; + child->priv->prev_sibling = NULL; + + /* delegate the actual insertion */ + add_func (self, child, data); + + g_assert (child->priv->parent == self); + + self->priv->n_children += 1; + + self->priv->age += 1; + + /* if push_internal() has been called then we automatically set + * the flag on the actor + */ + if (self->priv->internal_child) + CLUTTER_SET_PRIVATE_FLAGS (child, CLUTTER_INTERNAL_CHILD); + + /* children may cause their parent to expand, if they are set + * to expand; if a child is not expanded then it cannot change + * its parent's state. any further change later on will queue + * an expand state check. + * + * this check, with the initial state of the needs_compute_expand + * flag set to FALSE, should avoid recomputing the expand flags + * state while building the actor tree. + */ + if (CLUTTER_ACTOR_IS_VISIBLE (child) && + (child->priv->needs_compute_expand || + child->priv->needs_x_expand || + child->priv->needs_y_expand)) + { + clutter_actor_queue_compute_expand (self); + } + + /* clutter_actor_reparent() will emit ::parent-set for us */ + if (emit_parent_set && !CLUTTER_ACTOR_IN_REPARENT (child)) + g_signal_emit (child, actor_signals[PARENT_SET], 0, NULL); + + if (check_state) + { + /* If parent is mapped or realized, we need to also be mapped or + * realized once we're inside the parent. + */ + clutter_actor_update_map_state (child, MAP_STATE_CHECK); + + /* propagate the parent's text direction to the child */ + text_dir = clutter_actor_get_text_direction (self); + clutter_actor_set_text_direction (child, text_dir); + } + + /* this may end up queueing a redraw, in case the actor is + * not visible but the show-on-set-parent property is still + * set. + * + * XXX:2.0 - remove this check and unconditionally show() the + * actor once we remove the show-on-set-parent property + */ + if (show_on_set_parent && child->priv->show_on_set_parent) + clutter_actor_show (child); + + /* on the other hand, this will catch any other case where + * the actor is supposed to be visible when it's added + */ + if (CLUTTER_ACTOR_IS_MAPPED (child)) + clutter_actor_queue_redraw (child); + + /* maintain the invariant that if an actor needs layout, + * its parents do as well + */ + if (child->priv->needs_width_request || + child->priv->needs_height_request || + child->priv->needs_allocation) + { + /* we work around the short-circuiting we do + * in clutter_actor_queue_relayout() since we + * want to force a relayout + */ + child->priv->needs_width_request = TRUE; + child->priv->needs_height_request = TRUE; + child->priv->needs_allocation = TRUE; + + /* we only queue a relayout here, because any possible + * redraw has already been queued either by show() or + * by our call to queue_redraw() above + */ + _clutter_actor_queue_only_relayout (child->priv->parent); + } + + if (emit_actor_added) + g_signal_emit_by_name (self, "actor-added", child); + + if (notify_first_last) + { + if (old_first_child != self->priv->first_child) + g_object_notify_by_pspec (obj, obj_props[PROP_FIRST_CHILD]); + + if (old_last_child != self->priv->last_child) + g_object_notify_by_pspec (obj, obj_props[PROP_LAST_CHILD]); + } + + g_object_thaw_notify (obj); +} + +/** + * clutter_actor_add_child: + * @self: a #ClutterActor + * @child: a #ClutterActor + * + * Adds @child to the children of @self. + * + * This function will acquire a reference on @child that will only + * be released when calling clutter_actor_remove_child(). + * + * This function will take into consideration the #ClutterActor:depth + * of @child, and will keep the list of children sorted. + * + * This function will emit the #ClutterContainer::actor-added signal + * on @self. + * + * Since: 1.10 + */ +void +clutter_actor_add_child (ClutterActor *self, + ClutterActor *child) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (CLUTTER_IS_ACTOR (child)); + g_return_if_fail (self != child); + g_return_if_fail (child->priv->parent == NULL); + + clutter_actor_add_child_internal (self, child, + ADD_CHILD_DEFAULT_FLAGS, + insert_child_at_depth, + NULL); +} + +/** + * clutter_actor_insert_child_at_index: + * @self: a #ClutterActor + * @child: a #ClutterActor + * @index_: the index + * + * Inserts @child into the list of children of @self, using the + * given @index_. If @index_ is greater than the number of children + * in @self, or is less than 0, then the new child is added at the end. + * + * This function will acquire a reference on @child that will only + * be released when calling clutter_actor_remove_child(). + * + * This function will not take into consideration the #ClutterActor:depth + * of @child. + * + * This function will emit the #ClutterContainer::actor-added signal + * on @self. + * + * Since: 1.10 + */ +void +clutter_actor_insert_child_at_index (ClutterActor *self, + ClutterActor *child, + gint index_) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (CLUTTER_IS_ACTOR (child)); + g_return_if_fail (self != child); + g_return_if_fail (child->priv->parent == NULL); + + clutter_actor_add_child_internal (self, child, + ADD_CHILD_DEFAULT_FLAGS, + insert_child_at_index, + GINT_TO_POINTER (index_)); +} + +/** + * clutter_actor_insert_child_above: + * @self: a #ClutterActor + * @child: a #ClutterActor + * @sibling: (allow-none): a child of @self, or %NULL + * + * Inserts @child into the list of children of @self, above another + * child of @self or, if @sibling is %NULL, above all the children + * of @self. + * + * This function will acquire a reference on @child that will only + * be released when calling clutter_actor_remove_child(). + * + * This function will not take into consideration the #ClutterActor:depth + * of @child. + * + * This function will emit the #ClutterContainer::actor-added signal + * on @self. + * + * Since: 1.10 + */ +void +clutter_actor_insert_child_above (ClutterActor *self, + ClutterActor *child, + ClutterActor *sibling) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (CLUTTER_IS_ACTOR (child)); + g_return_if_fail (self != child); + g_return_if_fail (child != sibling); + g_return_if_fail (child->priv->parent == NULL); + g_return_if_fail (sibling == NULL || + (CLUTTER_IS_ACTOR (sibling) && + sibling->priv->parent == self)); + + clutter_actor_add_child_internal (self, child, + ADD_CHILD_DEFAULT_FLAGS, + insert_child_above, + sibling); +} + +/** + * clutter_actor_insert_child_below: + * @self: a #ClutterActor + * @child: a #ClutterActor + * @sibling: (allow-none): a child of @self, or %NULL + * + * Inserts @child into the list of children of @self, below another + * child of @self or, if @sibling is %NULL, below all the children + * of @self. + * + * This function will acquire a reference on @child that will only + * be released when calling clutter_actor_remove_child(). + * + * This function will not take into consideration the #ClutterActor:depth + * of @child. + * + * This function will emit the #ClutterContainer::actor-added signal + * on @self. + * + * Since: 1.10 + */ +void +clutter_actor_insert_child_below (ClutterActor *self, + ClutterActor *child, + ClutterActor *sibling) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (CLUTTER_IS_ACTOR (child)); + g_return_if_fail (self != child); + g_return_if_fail (child != sibling); + g_return_if_fail (child->priv->parent == NULL); + g_return_if_fail (sibling == NULL || + (CLUTTER_IS_ACTOR (sibling) && + sibling->priv->parent == self)); + + clutter_actor_add_child_internal (self, child, + ADD_CHILD_DEFAULT_FLAGS, + insert_child_below, + sibling); +} + +/** + * clutter_actor_set_parent: + * @self: A #ClutterActor + * @parent: A new #ClutterActor parent + * + * Sets the parent of @self to @parent. + * + * This function will result in @parent acquiring a reference on @self, + * eventually by sinking its floating reference first. The reference + * will be released by clutter_actor_unparent(). + * + * This function should only be called by legacy #ClutterActors + * implementing the #ClutterContainer interface. + * + * Deprecated: 1.10: Use clutter_actor_add_child() instead. + */ +void +clutter_actor_set_parent (ClutterActor *self, + ClutterActor *parent) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (CLUTTER_IS_ACTOR (parent)); + g_return_if_fail (self != parent); + g_return_if_fail (self->priv->parent == NULL); + + /* as this function will be called inside ClutterContainer::add + * implementations or when building up a composite actor, we have + * to preserve the old behaviour, and not create child meta or + * emit the ::actor-added signal, to avoid recursion or double + * emissions + */ + clutter_actor_add_child_internal (parent, self, + ADD_CHILD_LEGACY_FLAGS, + insert_child_at_depth, + NULL); +} + +/** + * clutter_actor_get_parent: + * @self: A #ClutterActor + * + * Retrieves the parent of @self. + * + * Return Value: (transfer none): The #ClutterActor parent, or %NULL + * if no parent is set + */ +ClutterActor * +clutter_actor_get_parent (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + + return self->priv->parent; +} + +/** + * clutter_actor_get_paint_visibility: + * @self: A #ClutterActor + * + * Retrieves the 'paint' visibility of an actor recursively checking for non + * visible parents. + * + * This is by definition the same as %CLUTTER_ACTOR_IS_MAPPED. + * + * Return Value: %TRUE if the actor is visibile and will be painted. + * + * Since: 0.8 + */ +gboolean +clutter_actor_get_paint_visibility (ClutterActor *actor) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), FALSE); + + return CLUTTER_ACTOR_IS_MAPPED (actor); +} + +/** + * clutter_actor_remove_child: + * @self: a #ClutterActor + * @child: a #ClutterActor + * + * Removes @child from the children of @self. + * + * This function will release the reference added by + * clutter_actor_add_child(), so if you want to keep using @child + * you will have to acquire a referenced on it before calling this + * function. + * + * This function will emit the #ClutterContainer::actor-removed + * signal on @self. + * + * Since: 1.10 + */ +void +clutter_actor_remove_child (ClutterActor *self, + ClutterActor *child) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (CLUTTER_IS_ACTOR (child)); + g_return_if_fail (self != child); + g_return_if_fail (child->priv->parent != NULL); + g_return_if_fail (child->priv->parent == self); + + clutter_actor_remove_child_internal (self, child, + REMOVE_CHILD_DEFAULT_FLAGS); +} + +/** + * clutter_actor_remove_all_children: + * @self: a #ClutterActor + * + * Removes all children of @self. + * + * This function releases the reference added by inserting a child actor + * in the list of children of @self. + * + * If the reference count of a child drops to zero, the child will be + * destroyed. If you want to ensure the destruction of all the children + * of @self, use clutter_actor_destroy_all_children(). + * + * Since: 1.10 + */ +void +clutter_actor_remove_all_children (ClutterActor *self) +{ + ClutterActorIter iter; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + if (self->priv->n_children == 0) + return; + + g_object_freeze_notify (G_OBJECT (self)); + + clutter_actor_iter_init (&iter, self); + while (clutter_actor_iter_next (&iter, NULL)) + clutter_actor_iter_remove (&iter); + + g_object_thaw_notify (G_OBJECT (self)); + + /* sanity check */ + g_assert (self->priv->first_child == NULL); + g_assert (self->priv->last_child == NULL); + g_assert (self->priv->n_children == 0); +} + +/** + * clutter_actor_destroy_all_children: + * @self: a #ClutterActor + * + * Destroys all children of @self. + * + * This function releases the reference added by inserting a child + * actor in the list of children of @self, and ensures that the + * #ClutterActor::destroy signal is emitted on each child of the + * actor. + * + * By default, #ClutterActor will emit the #ClutterActor::destroy signal + * when its reference count drops to 0; the default handler of the + * #ClutterActor::destroy signal will destroy all the children of an + * actor. This function ensures that all children are destroyed, instead + * of just removed from @self, unlike clutter_actor_remove_all_children() + * which will merely release the reference and remove each child. + * + * Unless you acquired an additional reference on each child of @self + * prior to calling clutter_actor_remove_all_children() and want to reuse + * the actors, you should use clutter_actor_destroy_all_children() in + * order to make sure that children are destroyed and signal handlers + * are disconnected even in cases where circular references prevent this + * from automatically happening through reference counting alone. + * + * Since: 1.10 + */ +void +clutter_actor_destroy_all_children (ClutterActor *self) +{ + ClutterActorIter iter; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + if (self->priv->n_children == 0) + return; + + g_object_freeze_notify (G_OBJECT (self)); + + clutter_actor_iter_init (&iter, self); + while (clutter_actor_iter_next (&iter, NULL)) + clutter_actor_iter_destroy (&iter); + + g_object_thaw_notify (G_OBJECT (self)); + + /* sanity check */ + g_assert (self->priv->first_child == NULL); + g_assert (self->priv->last_child == NULL); + g_assert (self->priv->n_children == 0); +} + +typedef struct _InsertBetweenData { + ClutterActor *prev_sibling; + ClutterActor *next_sibling; +} InsertBetweenData; + +static void +insert_child_between (ClutterActor *self, + ClutterActor *child, + gpointer data_) +{ + InsertBetweenData *data = data_; + ClutterActor *prev_sibling = data->prev_sibling; + ClutterActor *next_sibling = data->next_sibling; + + child->priv->parent = self; + child->priv->prev_sibling = prev_sibling; + child->priv->next_sibling = next_sibling; + + if (prev_sibling != NULL) + prev_sibling->priv->next_sibling = child; + + if (next_sibling != NULL) + next_sibling->priv->prev_sibling = child; + + if (child->priv->prev_sibling == NULL) + self->priv->first_child = child; + + if (child->priv->next_sibling == NULL) + self->priv->last_child = child; +} + +/** + * clutter_actor_replace_child: + * @self: a #ClutterActor + * @old_child: the child of @self to replace + * @new_child: the #ClutterActor to replace @old_child + * + * Replaces @old_child with @new_child in the list of children of @self. + * + * Since: 1.10 + */ +void +clutter_actor_replace_child (ClutterActor *self, + ClutterActor *old_child, + ClutterActor *new_child) +{ + ClutterActor *prev_sibling, *next_sibling; + InsertBetweenData clos; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (CLUTTER_IS_ACTOR (old_child)); + g_return_if_fail (old_child->priv->parent == self); + g_return_if_fail (CLUTTER_IS_ACTOR (new_child)); + g_return_if_fail (old_child != new_child); + g_return_if_fail (new_child != self); + g_return_if_fail (new_child->priv->parent == NULL); + + prev_sibling = old_child->priv->prev_sibling; + next_sibling = old_child->priv->next_sibling; + clutter_actor_remove_child_internal (self, old_child, + REMOVE_CHILD_DEFAULT_FLAGS); + + clos.prev_sibling = prev_sibling; + clos.next_sibling = next_sibling; + clutter_actor_add_child_internal (self, new_child, + ADD_CHILD_DEFAULT_FLAGS, + insert_child_between, + &clos); +} + +/** + * clutter_actor_unparent: + * @self: a #ClutterActor + * + * Removes the parent of @self. + * + * This will cause the parent of @self to release the reference + * acquired when calling clutter_actor_set_parent(), so if you + * want to keep @self you will have to acquire a reference of + * your own, through g_object_ref(). + * + * This function should only be called by legacy #ClutterActors + * implementing the #ClutterContainer interface. + * + * Since: 0.2 + * + * Deprecated: 1.10: Use clutter_actor_remove_child() instead. + */ +void +clutter_actor_unparent (ClutterActor *self) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + if (self->priv->parent == NULL) + return; + + clutter_actor_remove_child_internal (self->priv->parent, self, + REMOVE_CHILD_LEGACY_FLAGS); +} + +/** + * clutter_actor_reparent: + * @self: a #ClutterActor + * @new_parent: the new #ClutterActor parent + * + * Resets the parent actor of @self. + * + * This function is logically equivalent to calling clutter_actor_unparent() + * and clutter_actor_set_parent(), but more efficiently implemented, as it + * ensures the child is not finalized when unparented, and emits the + * #ClutterActor::parent-set signal only once. + * + * In reality, calling this function is less useful than it sounds, as some + * application code may rely on changes in the intermediate state between + * removal and addition of the actor from its old parent to the @new_parent. + * Thus, it is strongly encouraged to avoid using this function in application + * code. + * + * Since: 0.2 + * + * Deprecated: 1.10: Use clutter_actor_remove_child() and + * clutter_actor_add_child() instead; remember to take a reference on + * the actor being removed before calling clutter_actor_remove_child() + * to avoid the reference count dropping to zero and the actor being + * destroyed. + */ +void +clutter_actor_reparent (ClutterActor *self, + ClutterActor *new_parent) +{ + ClutterActorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (CLUTTER_IS_ACTOR (new_parent)); + g_return_if_fail (self != new_parent); + + if (CLUTTER_ACTOR_IS_TOPLEVEL (self)) + { + g_warning ("Cannot set a parent on a toplevel actor"); + return; + } + + if (CLUTTER_ACTOR_IN_DESTRUCTION (self)) + { + g_warning ("Cannot set a parent currently being destroyed"); + return; + } + + priv = self->priv; + + if (priv->parent != new_parent) + { + ClutterActor *old_parent; + + CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_IN_REPARENT); + + old_parent = priv->parent; + + g_object_ref (self); + + if (old_parent != NULL) + { + /* go through the Container implementation if this is a regular + * child and not an internal one + */ + if (!CLUTTER_ACTOR_IS_INTERNAL_CHILD (self)) + { + ClutterContainer *parent = CLUTTER_CONTAINER (old_parent); + + /* this will have to call unparent() */ + clutter_container_remove_actor (parent, self); + } + else + clutter_actor_remove_child_internal (old_parent, self, + REMOVE_CHILD_LEGACY_FLAGS); + } + + /* Note, will call set_parent() */ + if (!CLUTTER_ACTOR_IS_INTERNAL_CHILD (self)) + clutter_container_add_actor (CLUTTER_CONTAINER (new_parent), self); + else + clutter_actor_add_child_internal (new_parent, self, + ADD_CHILD_LEGACY_FLAGS, + insert_child_at_depth, + NULL); + + /* we emit the ::parent-set signal once */ + g_signal_emit (self, actor_signals[PARENT_SET], 0, old_parent); + + CLUTTER_UNSET_PRIVATE_FLAGS (self, CLUTTER_IN_REPARENT); + + /* the IN_REPARENT flag suspends state updates */ + clutter_actor_update_map_state (self, MAP_STATE_CHECK); + + g_object_unref (self); + } +} + +/** + * clutter_actor_contains: + * @self: A #ClutterActor + * @descendant: A #ClutterActor, possibly contained in @self + * + * Determines if @descendant is contained inside @self (either as an + * immediate child, or as a deeper descendant). If @self and + * @descendant point to the same actor then it will also return %TRUE. + * + * Return value: whether @descendent is contained within @self + * + * Since: 1.4 + */ +gboolean +clutter_actor_contains (ClutterActor *self, + ClutterActor *descendant) +{ + ClutterActor *actor; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); + g_return_val_if_fail (CLUTTER_IS_ACTOR (descendant), FALSE); + + for (actor = descendant; actor; actor = actor->priv->parent) + if (actor == self) + return TRUE; + + return FALSE; +} + +/** + * clutter_actor_set_child_above_sibling: + * @self: a #ClutterActor + * @child: a #ClutterActor child of @self + * @sibling: (allow-none): a #ClutterActor child of @self, or %NULL + * + * Sets @child to be above @sibling in the list of children of @self. + * + * If @sibling is %NULL, @child will be the new last child of @self. + * + * This function is logically equivalent to removing @child and using + * clutter_actor_insert_child_above(), but it will not emit signals + * or change state on @child. + * + * Since: 1.10 + */ +void +clutter_actor_set_child_above_sibling (ClutterActor *self, + ClutterActor *child, + ClutterActor *sibling) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (CLUTTER_IS_ACTOR (child)); + g_return_if_fail (child->priv->parent == self); + g_return_if_fail (child != sibling); + g_return_if_fail (sibling == NULL || CLUTTER_IS_ACTOR (sibling)); + + if (sibling != NULL) + g_return_if_fail (sibling->priv->parent == self); + + if (CLUTTER_ACTOR_IN_DESTRUCTION (self) || + CLUTTER_ACTOR_IN_DESTRUCTION (child) || + (sibling != NULL && CLUTTER_ACTOR_IN_DESTRUCTION (sibling))) + return; + + /* we don't want to change the state of child, or emit signals, or + * regenerate ChildMeta instances here, but we still want to follow + * the correct sequence of steps encoded in remove_child() and + * add_child(), so that correctness is ensured, and we only go + * through one known code path. + */ + g_object_ref (child); + clutter_actor_remove_child_internal (self, child, 0); + clutter_actor_add_child_internal (self, child, + ADD_CHILD_NOTIFY_FIRST_LAST, + insert_child_above, + sibling); + g_object_unref(child); + + clutter_actor_queue_relayout (self); +} + +/** + * clutter_actor_set_child_below_sibling: + * @self: a #ClutterActor + * @child: a #ClutterActor child of @self + * @sibling: (allow-none): a #ClutterActor child of @self, or %NULL + * + * Sets @child to be below @sibling in the list of children of @self. + * + * If @sibling is %NULL, @child will be the new first child of @self. + * + * This function is logically equivalent to removing @self and using + * clutter_actor_insert_child_below(), but it will not emit signals + * or change state on @child. + * + * Since: 1.10 + */ +void +clutter_actor_set_child_below_sibling (ClutterActor *self, + ClutterActor *child, + ClutterActor *sibling) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (CLUTTER_IS_ACTOR (child)); + g_return_if_fail (child->priv->parent == self); + g_return_if_fail (child != sibling); + g_return_if_fail (sibling == NULL || CLUTTER_IS_ACTOR (sibling)); + + if (sibling != NULL) + g_return_if_fail (sibling->priv->parent == self); + + if (CLUTTER_ACTOR_IN_DESTRUCTION (self) || + CLUTTER_ACTOR_IN_DESTRUCTION (child) || + (sibling != NULL && CLUTTER_ACTOR_IN_DESTRUCTION (sibling))) + return; + + /* see the comment in set_child_above_sibling() */ + g_object_ref (child); + clutter_actor_remove_child_internal (self, child, 0); + clutter_actor_add_child_internal (self, child, + ADD_CHILD_NOTIFY_FIRST_LAST, + insert_child_below, + sibling); + g_object_unref(child); + + clutter_actor_queue_relayout (self); +} + +/** + * clutter_actor_set_child_at_index: + * @self: a #ClutterActor + * @child: a #ClutterActor child of @self + * @index_: the new index for @child + * + * Changes the index of @child in the list of children of @self. + * + * This function is logically equivalent to removing @child and + * calling clutter_actor_insert_child_at_index(), but it will not + * emit signals or change state on @child. + * + * Since: 1.10 + */ +void +clutter_actor_set_child_at_index (ClutterActor *self, + ClutterActor *child, + gint index_) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (CLUTTER_IS_ACTOR (child)); + g_return_if_fail (child->priv->parent == self); + g_return_if_fail (index_ <= self->priv->n_children); + + if (CLUTTER_ACTOR_IN_DESTRUCTION (self) || + CLUTTER_ACTOR_IN_DESTRUCTION (child)) + return; + + g_object_ref (child); + clutter_actor_remove_child_internal (self, child, 0); + clutter_actor_add_child_internal (self, child, + ADD_CHILD_NOTIFY_FIRST_LAST, + insert_child_at_index, + GINT_TO_POINTER (index_)); + g_object_unref (child); + + clutter_actor_queue_relayout (self); +} + +/** + * clutter_actor_raise: + * @self: A #ClutterActor + * @below: (allow-none): A #ClutterActor to raise above. + * + * Puts @self above @below. + * + * Both actors must have the same parent, and the parent must implement + * the #ClutterContainer interface + * + * This function calls clutter_container_raise_child() internally. + * + * Deprecated: 1.10: Use clutter_actor_set_child_above_sibling() instead. + */ +void +clutter_actor_raise (ClutterActor *self, + ClutterActor *below) +{ + ClutterActor *parent; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + parent = clutter_actor_get_parent (self); + if (parent == NULL) + { + g_warning ("%s: Actor '%s' is not inside a container", + G_STRFUNC, + _clutter_actor_get_debug_name (self)); + return; + } + + if (below != NULL) + { + if (parent != clutter_actor_get_parent (below)) + { + g_warning ("%s Actor '%s' is not in the same container as " + "actor '%s'", + G_STRFUNC, + _clutter_actor_get_debug_name (self), + _clutter_actor_get_debug_name (below)); + return; + } + } + + clutter_container_raise_child (CLUTTER_CONTAINER (parent), self, below); +} + +/** + * clutter_actor_lower: + * @self: A #ClutterActor + * @above: (allow-none): A #ClutterActor to lower below + * + * Puts @self below @above. + * + * Both actors must have the same parent, and the parent must implement + * the #ClutterContainer interface. + * + * This function calls clutter_container_lower_child() internally. + * + * Deprecated: 1.10: Use clutter_actor_set_child_below_sibling() instead. + */ +void +clutter_actor_lower (ClutterActor *self, + ClutterActor *above) +{ + ClutterActor *parent; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + parent = clutter_actor_get_parent (self); + if (parent == NULL) + { + g_warning ("%s: Actor of type %s is not inside a container", + G_STRFUNC, + _clutter_actor_get_debug_name (self)); + return; + } + + if (above) + { + if (parent != clutter_actor_get_parent (above)) + { + g_warning ("%s: Actor '%s' is not in the same container as " + "actor '%s'", + G_STRFUNC, + _clutter_actor_get_debug_name (self), + _clutter_actor_get_debug_name (above)); + return; + } + } + + clutter_container_lower_child (CLUTTER_CONTAINER (parent), self, above); +} + +/** + * clutter_actor_raise_top: + * @self: A #ClutterActor + * + * Raises @self to the top. + * + * This function calls clutter_actor_raise() internally. + * + * Deprecated: 1.10: Use clutter_actor_set_child_above_sibling() with + * a %NULL sibling, instead. + */ +void +clutter_actor_raise_top (ClutterActor *self) +{ + clutter_actor_raise (self, NULL); +} + +/** + * clutter_actor_lower_bottom: + * @self: A #ClutterActor + * + * Lowers @self to the bottom. + * + * This function calls clutter_actor_lower() internally. + * + * Deprecated: 1.10: Use clutter_actor_set_child_below_sibling() with + * a %NULL sibling, instead. + */ +void +clutter_actor_lower_bottom (ClutterActor *self) +{ + clutter_actor_lower (self, NULL); +} + +/* + * Event handling + */ + +/** + * clutter_actor_event: + * @actor: a #ClutterActor + * @event: a #ClutterEvent + * @capture: %TRUE if event in in capture phase, %FALSE otherwise. + * + * This function is used to emit an event on the main stage. + * You should rarely need to use this function, except for + * synthetising events. + * + * Return value: the return value from the signal emission: %TRUE + * if the actor handled the event, or %FALSE if the event was + * not handled + * + * Since: 0.6 + */ +gboolean +clutter_actor_event (ClutterActor *actor, + const ClutterEvent *event, + gboolean capture) +{ + gboolean retval = FALSE; + gint signal_num = -1; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + g_object_ref (actor); + + if (capture) + { + g_signal_emit (actor, actor_signals[CAPTURED_EVENT], 0, + event, + &retval); + goto out; + } + + g_signal_emit (actor, actor_signals[EVENT], 0, event, &retval); + + if (!retval) + { + switch (event->type) + { + case CLUTTER_NOTHING: + break; + case CLUTTER_BUTTON_PRESS: + signal_num = BUTTON_PRESS_EVENT; + break; + case CLUTTER_BUTTON_RELEASE: + signal_num = BUTTON_RELEASE_EVENT; + break; + case CLUTTER_SCROLL: + signal_num = SCROLL_EVENT; + break; + case CLUTTER_KEY_PRESS: + signal_num = KEY_PRESS_EVENT; + break; + case CLUTTER_KEY_RELEASE: + signal_num = KEY_RELEASE_EVENT; + break; + case CLUTTER_MOTION: + signal_num = MOTION_EVENT; + break; + case CLUTTER_ENTER: + signal_num = ENTER_EVENT; + break; + case CLUTTER_LEAVE: + signal_num = LEAVE_EVENT; + break; + case CLUTTER_TOUCH_BEGIN: + case CLUTTER_TOUCH_END: + case CLUTTER_TOUCH_UPDATE: + case CLUTTER_TOUCH_CANCEL: + signal_num = TOUCH_EVENT; + break; + case CLUTTER_DELETE: + case CLUTTER_DESTROY_NOTIFY: + case CLUTTER_CLIENT_MESSAGE: + default: + signal_num = -1; + break; + } + + if (signal_num != -1) + g_signal_emit (actor, actor_signals[signal_num], 0, + event, &retval); + } + +out: + g_object_unref (actor); + + return retval; +} + +/** + * clutter_actor_set_reactive: + * @actor: a #ClutterActor + * @reactive: whether the actor should be reactive to events + * + * Sets @actor as reactive. Reactive actors will receive events. + * + * Since: 0.6 + */ +void +clutter_actor_set_reactive (ClutterActor *actor, + gboolean reactive) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + if (reactive == CLUTTER_ACTOR_IS_REACTIVE (actor)) + return; + + if (reactive) + CLUTTER_ACTOR_SET_FLAGS (actor, CLUTTER_ACTOR_REACTIVE); + else + CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REACTIVE); + + g_object_notify_by_pspec (G_OBJECT (actor), obj_props[PROP_REACTIVE]); +} + +/** + * clutter_actor_get_reactive: + * @actor: a #ClutterActor + * + * Checks whether @actor is marked as reactive. + * + * Return value: %TRUE if the actor is reactive + * + * Since: 0.6 + */ +gboolean +clutter_actor_get_reactive (ClutterActor *actor) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), FALSE); + + return CLUTTER_ACTOR_IS_REACTIVE (actor) ? TRUE : FALSE; +} + +/** + * clutter_actor_get_anchor_point: + * @self: a #ClutterActor + * @anchor_x: (out): return location for the X coordinate of the anchor point + * @anchor_y: (out): return location for the Y coordinate of the anchor point + * + * Gets the current anchor point of the @actor in pixels. + * + * Since: 0.6 + * + * Deprecated: 1.12: Use #ClutterActor:pivot-point instead + */ +void +clutter_actor_get_anchor_point (ClutterActor *self, + gfloat *anchor_x, + gfloat *anchor_y) +{ + const ClutterTransformInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + info = _clutter_actor_get_transform_info_or_defaults (self); + clutter_anchor_coord_get_units (self, &info->anchor, + anchor_x, + anchor_y, + NULL); +} + +/** + * clutter_actor_set_anchor_point: + * @self: a #ClutterActor + * @anchor_x: X coordinate of the anchor point + * @anchor_y: Y coordinate of the anchor point + * + * Sets an anchor point for @self. The anchor point is a point in the + * coordinate space of an actor to which the actor position within its + * parent is relative; the default is (0, 0), i.e. the top-left corner + * of the actor. + * + * Since: 0.6 + * + * Deprecated: 1.12: Use #ClutterActor:pivot-point instead. + */ +void +clutter_actor_set_anchor_point (ClutterActor *self, + gfloat anchor_x, + gfloat anchor_y) +{ + ClutterTransformInfo *info; + ClutterActorPrivate *priv; + gboolean changed = FALSE; + gfloat old_anchor_x, old_anchor_y; + GObject *obj; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + obj = G_OBJECT (self); + priv = self->priv; + info = _clutter_actor_get_transform_info (self); + + g_object_freeze_notify (obj); + + clutter_anchor_coord_get_units (self, &info->anchor, + &old_anchor_x, + &old_anchor_y, + NULL); + + if (info->anchor.is_fractional) + g_object_notify_by_pspec (obj, obj_props[PROP_ANCHOR_GRAVITY]); + + if (old_anchor_x != anchor_x) + { + g_object_notify_by_pspec (obj, obj_props[PROP_ANCHOR_X]); + changed = TRUE; + } + + if (old_anchor_y != anchor_y) + { + g_object_notify_by_pspec (obj, obj_props[PROP_ANCHOR_Y]); + changed = TRUE; + } + + clutter_anchor_coord_set_units (&info->anchor, anchor_x, anchor_y, 0); + + if (changed) + { + priv->transform_valid = FALSE; + clutter_actor_queue_redraw (self); + } + + g_object_thaw_notify (obj); +} + +/** + * clutter_actor_get_anchor_point_gravity: + * @self: a #ClutterActor + * + * Retrieves the anchor position expressed as a #ClutterGravity. If + * the anchor point was specified using pixels or units this will + * return %CLUTTER_GRAVITY_NONE. + * + * Return value: the #ClutterGravity used by the anchor point + * + * Since: 1.0 + * + * Deprecated: 1.12: Use #ClutterActor:pivot-point instead. + */ +ClutterGravity +clutter_actor_get_anchor_point_gravity (ClutterActor *self) +{ + const ClutterTransformInfo *info; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), CLUTTER_GRAVITY_NONE); + + info = _clutter_actor_get_transform_info_or_defaults (self); + + return clutter_anchor_coord_get_gravity (&info->anchor); +} + +/** + * clutter_actor_move_anchor_point: + * @self: a #ClutterActor + * @anchor_x: X coordinate of the anchor point + * @anchor_y: Y coordinate of the anchor point + * + * Sets an anchor point for the actor, and adjusts the actor postion so that + * the relative position of the actor toward its parent remains the same. + * + * Since: 0.6 + * + * Deprecated: 1.12: Use #ClutterActor:pivot-point and + * clutter_actor_set_translation() instead. + */ +void +clutter_actor_move_anchor_point (ClutterActor *self, + gfloat anchor_x, + gfloat anchor_y) +{ + gfloat old_anchor_x, old_anchor_y; + const ClutterTransformInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + info = _clutter_actor_get_transform_info (self); + clutter_anchor_coord_get_units (self, &info->anchor, + &old_anchor_x, + &old_anchor_y, + NULL); + + g_object_freeze_notify (G_OBJECT (self)); + + clutter_actor_set_anchor_point (self, anchor_x, anchor_y); + + if (self->priv->position_set) + clutter_actor_move_by (self, + anchor_x - old_anchor_x, + anchor_y - old_anchor_y); + + g_object_thaw_notify (G_OBJECT (self)); +} + +/** + * clutter_actor_move_anchor_point_from_gravity: + * @self: a #ClutterActor + * @gravity: #ClutterGravity. + * + * Sets an anchor point on the actor based on the given gravity, adjusting the + * actor postion so that its relative position within its parent remains + * unchanged. + * + * Since version 1.0 the anchor point will be stored as a gravity so + * that if the actor changes size then the anchor point will move. For + * example, if you set the anchor point to %CLUTTER_GRAVITY_SOUTH_EAST + * and later double the size of the actor, the anchor point will move + * to the bottom right. + * + * Since: 0.6 + * + * Deprecated: 1.12: Use #ClutterActor:pivot-point and + * clutter_actor_set_translation() instead. + */ +void +clutter_actor_move_anchor_point_from_gravity (ClutterActor *self, + ClutterGravity gravity) +{ + gfloat old_anchor_x, old_anchor_y, new_anchor_x, new_anchor_y; + const ClutterTransformInfo *info; + ClutterActorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + priv = self->priv; + info = _clutter_actor_get_transform_info (self); + + g_object_freeze_notify (G_OBJECT (self)); + + clutter_anchor_coord_get_units (self, &info->anchor, + &old_anchor_x, + &old_anchor_y, + NULL); + clutter_actor_set_anchor_point_from_gravity (self, gravity); + clutter_anchor_coord_get_units (self, &info->anchor, + &new_anchor_x, + &new_anchor_y, + NULL); + + if (priv->position_set) + clutter_actor_move_by (self, + new_anchor_x - old_anchor_x, + new_anchor_y - old_anchor_y); + + g_object_thaw_notify (G_OBJECT (self)); +} + +/** + * clutter_actor_set_anchor_point_from_gravity: + * @self: a #ClutterActor + * @gravity: #ClutterGravity. + * + * Sets an anchor point on the actor, based on the given gravity (this is a + * convenience function wrapping clutter_actor_set_anchor_point()). + * + * Since version 1.0 the anchor point will be stored as a gravity so + * that if the actor changes size then the anchor point will move. For + * example, if you set the anchor point to %CLUTTER_GRAVITY_SOUTH_EAST + * and later double the size of the actor, the anchor point will move + * to the bottom right. + * + * Since: 0.6 + * + * Deprecated: 1.12: Use #ClutterActor:pivot-point and + * clutter_actor_set_translation() instead. E.g. For %CLUTTER_GRAVITY_CENTER set + * pivot_point to (0.5,0.5) and the translation to (width/2,height/2). + */ +void +clutter_actor_set_anchor_point_from_gravity (ClutterActor *self, + ClutterGravity gravity) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + if (gravity == CLUTTER_GRAVITY_NONE) + clutter_actor_set_anchor_point (self, 0, 0); + else + { + GObject *obj = G_OBJECT (self); + ClutterTransformInfo *info; + + g_object_freeze_notify (obj); + + info = _clutter_actor_get_transform_info (self); + clutter_anchor_coord_set_gravity (&info->anchor, gravity); + + g_object_notify_by_pspec (obj, obj_props[PROP_ANCHOR_GRAVITY]); + g_object_notify_by_pspec (obj, obj_props[PROP_ANCHOR_X]); + g_object_notify_by_pspec (obj, obj_props[PROP_ANCHOR_Y]); + + self->priv->transform_valid = FALSE; + + clutter_actor_queue_redraw (self); + + g_object_thaw_notify (obj); + } +} + +static void +clutter_actor_store_content_box (ClutterActor *self, + const ClutterActorBox *box) +{ + if (box != NULL) + { + self->priv->content_box = *box; + self->priv->content_box_valid = TRUE; + } + else + self->priv->content_box_valid = FALSE; + + clutter_actor_queue_redraw (self); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_CONTENT_BOX]); +} + +static void +clutter_container_iface_init (ClutterContainerIface *iface) +{ + /* we don't override anything, as ClutterContainer already has a default + * implementation that we can use, and which calls into our own API. + */ +} + +typedef enum +{ + PARSE_X, + PARSE_Y, + PARSE_WIDTH, + PARSE_HEIGHT, + PARSE_ANCHOR_X, + PARSE_ANCHOR_Y +} ParseDimension; + +static gfloat +parse_units (ClutterActor *self, + ParseDimension dimension, + JsonNode *node) +{ + GValue value = G_VALUE_INIT; + gfloat retval = 0; + + if (JSON_NODE_TYPE (node) != JSON_NODE_VALUE) + return 0; + + json_node_get_value (node, &value); + + if (G_VALUE_HOLDS (&value, G_TYPE_INT64)) + { + retval = (gfloat) g_value_get_int64 (&value); + } + else if (G_VALUE_HOLDS (&value, G_TYPE_DOUBLE)) + { + retval = g_value_get_double (&value); + } + else if (G_VALUE_HOLDS (&value, G_TYPE_STRING)) + { + ClutterUnits units; + gboolean res; + + res = clutter_units_from_string (&units, g_value_get_string (&value)); + if (res) + retval = clutter_units_to_pixels (&units); + else + { + g_warning ("Invalid value '%s': integers, strings or floating point " + "values can be used for the x, y, width and height " + "properties. Valid modifiers for strings are 'px', 'mm', " + "'pt' and 'em'.", + g_value_get_string (&value)); + retval = 0; + } + } + else + { + g_warning ("Invalid value of type '%s': integers, strings of floating " + "point values can be used for the x, y, width, height " + "anchor-x and anchor-y properties.", + g_type_name (G_VALUE_TYPE (&value))); + } + + g_value_unset (&value); + + return retval; +} + +typedef struct { + ClutterRotateAxis axis; + + gdouble angle; + + gfloat center_x; + gfloat center_y; + gfloat center_z; +} RotationInfo; + +static inline gboolean +parse_rotation_array (ClutterActor *actor, + JsonArray *array, + RotationInfo *info) +{ + JsonNode *element; + + if (json_array_get_length (array) != 2) + return FALSE; + + /* angle */ + element = json_array_get_element (array, 0); + if (JSON_NODE_TYPE (element) == JSON_NODE_VALUE) + info->angle = json_node_get_double (element); + else + return FALSE; + + /* center */ + element = json_array_get_element (array, 1); + if (JSON_NODE_TYPE (element) == JSON_NODE_ARRAY) + { + JsonArray *center = json_node_get_array (element); + + if (json_array_get_length (center) != 2) + return FALSE; + + switch (info->axis) + { + case CLUTTER_X_AXIS: + info->center_y = parse_units (actor, PARSE_Y, + json_array_get_element (center, 0)); + info->center_z = parse_units (actor, PARSE_Y, + json_array_get_element (center, 1)); + return TRUE; + + case CLUTTER_Y_AXIS: + info->center_x = parse_units (actor, PARSE_X, + json_array_get_element (center, 0)); + info->center_z = parse_units (actor, PARSE_X, + json_array_get_element (center, 1)); + return TRUE; + + case CLUTTER_Z_AXIS: + info->center_x = parse_units (actor, PARSE_X, + json_array_get_element (center, 0)); + info->center_y = parse_units (actor, PARSE_Y, + json_array_get_element (center, 1)); + return TRUE; + } + } + + return FALSE; +} + +static gboolean +parse_rotation (ClutterActor *actor, + JsonNode *node, + RotationInfo *info) +{ + JsonArray *array; + guint len, i; + gboolean retval = FALSE; + + if (JSON_NODE_TYPE (node) != JSON_NODE_ARRAY) + { + g_warning ("Invalid node of type '%s' found, expecting an array", + json_node_type_name (node)); + return FALSE; + } + + array = json_node_get_array (node); + len = json_array_get_length (array); + + for (i = 0; i < len; i++) + { + JsonNode *element = json_array_get_element (array, i); + JsonObject *object; + JsonNode *member; + + if (JSON_NODE_TYPE (element) != JSON_NODE_OBJECT) + { + g_warning ("Invalid node of type '%s' found, expecting an object", + json_node_type_name (element)); + return FALSE; + } + + object = json_node_get_object (element); + + if (json_object_has_member (object, "x-axis")) + { + member = json_object_get_member (object, "x-axis"); + + info->axis = CLUTTER_X_AXIS; + + if (JSON_NODE_TYPE (member) == JSON_NODE_VALUE) + { + info->angle = json_node_get_double (member); + retval = TRUE; + } + else if (JSON_NODE_TYPE (member) == JSON_NODE_ARRAY) + retval = parse_rotation_array (actor, + json_node_get_array (member), + info); + else + retval = FALSE; + } + else if (json_object_has_member (object, "y-axis")) + { + member = json_object_get_member (object, "y-axis"); + + info->axis = CLUTTER_Y_AXIS; + + if (JSON_NODE_TYPE (member) == JSON_NODE_VALUE) + { + info->angle = json_node_get_double (member); + retval = TRUE; + } + else if (JSON_NODE_TYPE (member) == JSON_NODE_ARRAY) + retval = parse_rotation_array (actor, + json_node_get_array (member), + info); + else + retval = FALSE; + } + else if (json_object_has_member (object, "z-axis")) + { + member = json_object_get_member (object, "z-axis"); + + info->axis = CLUTTER_Z_AXIS; + + if (JSON_NODE_TYPE (member) == JSON_NODE_VALUE) + { + info->angle = json_node_get_double (member); + retval = TRUE; + } + else if (JSON_NODE_TYPE (member) == JSON_NODE_ARRAY) + retval = parse_rotation_array (actor, + json_node_get_array (member), + info); + else + retval = FALSE; + } + } + + return retval; +} + +static GSList * +parse_actor_metas (ClutterScript *script, + ClutterActor *actor, + JsonNode *node) +{ + GList *elements, *l; + GSList *retval = NULL; + + if (!JSON_NODE_HOLDS_ARRAY (node)) + return NULL; + + elements = json_array_get_elements (json_node_get_array (node)); + + for (l = elements; l != NULL; l = l->next) + { + JsonNode *element = l->data; + const gchar *id_ = _clutter_script_get_id_from_node (element); + GObject *meta; + + if (id_ == NULL || *id_ == '\0') + continue; + + meta = clutter_script_get_object (script, id_); + if (meta == NULL) + continue; + + retval = g_slist_prepend (retval, meta); + } + + g_list_free (elements); + + return g_slist_reverse (retval); +} + +static GSList * +parse_behaviours (ClutterScript *script, + ClutterActor *actor, + JsonNode *node) +{ + GList *elements, *l; + GSList *retval = NULL; + + if (!JSON_NODE_HOLDS_ARRAY (node)) + return NULL; + + elements = json_array_get_elements (json_node_get_array (node)); + + for (l = elements; l != NULL; l = l->next) + { + JsonNode *element = l->data; + const gchar *id_ = _clutter_script_get_id_from_node (element); + GObject *behaviour; + + if (id_ == NULL || *id_ == '\0') + continue; + + behaviour = clutter_script_get_object (script, id_); + if (behaviour == NULL) + continue; + + retval = g_slist_prepend (retval, behaviour); + } + + g_list_free (elements); + + return g_slist_reverse (retval); +} + +static ClutterMargin * +parse_margin (ClutterActor *self, + JsonNode *node) +{ + ClutterMargin *margin; + JsonArray *array; + + if (!JSON_NODE_HOLDS_ARRAY (node)) + { + g_warning ("The margin property must be an array of 1 to 4 elements"); + return NULL; + } + + margin = clutter_margin_new (); + array = json_node_get_array (node); + switch (json_array_get_length (array)) + { + case 1: + margin->top = margin->right = margin->bottom = margin->left = + parse_units (self, 0, json_array_get_element (array, 0)); + break; + + case 2: + margin->top = margin->bottom = + parse_units (self, 0, json_array_get_element (array, 0)); + margin->right = margin->left = + parse_units (self, 0, json_array_get_element (array, 1)); + break; + + case 3: + margin->top = + parse_units (self, 0, json_array_get_element (array, 0)); + margin->right = margin->left = + parse_units (self, 0, json_array_get_element (array, 1)); + margin->bottom = + parse_units (self, 0, json_array_get_element (array, 2)); + break; + + case 4: + margin->top = + parse_units (self, 0, json_array_get_element (array, 0)); + margin->right = + parse_units (self, 0, json_array_get_element (array, 1)); + margin->bottom = + parse_units (self, 0, json_array_get_element (array, 2)); + margin->left = + parse_units (self, 0, json_array_get_element (array, 3)); + break; + + default: + g_warning ("The margin property must be an array of 1 to 4 elements"); + clutter_margin_free (margin); + return NULL; + } + return margin; +} + +static gboolean +clutter_actor_parse_custom_node (ClutterScriptable *scriptable, + ClutterScript *script, + GValue *value, + const gchar *name, + JsonNode *node) +{ + ClutterActor *actor = CLUTTER_ACTOR (scriptable); + gboolean retval = FALSE; + + if ((name[0] == 'x' && name[1] == '\0') || + (name[0] == 'y' && name[1] == '\0') || + (strcmp (name, "width") == 0) || + (strcmp (name, "height") == 0) || + (strcmp (name, "anchor_x") == 0) || + (strcmp (name, "anchor_y") == 0)) + { + ParseDimension dimension; + gfloat units; + + if (name[0] == 'x') + dimension = PARSE_X; + else if (name[0] == 'y') + dimension = PARSE_Y; + else if (name[0] == 'w') + dimension = PARSE_WIDTH; + else if (name[0] == 'h') + dimension = PARSE_HEIGHT; + else if (name[0] == 'a' && name[7] == 'x') + dimension = PARSE_ANCHOR_X; + else if (name[0] == 'a' && name[7] == 'y') + dimension = PARSE_ANCHOR_Y; + else + return FALSE; + + units = parse_units (actor, dimension, node); + + /* convert back to pixels: all properties are pixel-based */ + g_value_init (value, G_TYPE_FLOAT); + g_value_set_float (value, units); + + retval = TRUE; + } + else if (strcmp (name, "rotation") == 0) + { + RotationInfo *info; + + info = g_slice_new0 (RotationInfo); + retval = parse_rotation (actor, node, info); + + if (retval) + { + g_value_init (value, G_TYPE_POINTER); + g_value_set_pointer (value, info); + } + else + g_slice_free (RotationInfo, info); + } + else if (strcmp (name, "behaviours") == 0) + { + GSList *l; + +#ifdef CLUTTER_ENABLE_DEBUG + if (G_UNLIKELY (_clutter_diagnostic_enabled ())) + _clutter_diagnostic_message ("The 'behaviours' key is deprecated " + "and it should not be used in newly " + "written ClutterScript definitions."); +#endif + + l = parse_behaviours (script, actor, node); + + g_value_init (value, G_TYPE_POINTER); + g_value_set_pointer (value, l); + + retval = TRUE; + } + else if (strcmp (name, "actions") == 0 || + strcmp (name, "constraints") == 0 || + strcmp (name, "effects") == 0) + { + GSList *l; + + l = parse_actor_metas (script, actor, node); + + g_value_init (value, G_TYPE_POINTER); + g_value_set_pointer (value, l); + + retval = TRUE; + } + else if (strcmp (name, "margin") == 0) + { + ClutterMargin *margin = parse_margin (actor, node); + + if (margin) + { + g_value_init (value, CLUTTER_TYPE_MARGIN); + g_value_set_boxed (value, margin); + retval = TRUE; + } + } + + return retval; +} + +static void +clutter_actor_set_custom_property (ClutterScriptable *scriptable, + ClutterScript *script, + const gchar *name, + const GValue *value) +{ + ClutterActor *actor = CLUTTER_ACTOR (scriptable); + +#ifdef CLUTTER_ENABLE_DEBUG + if (G_UNLIKELY (CLUTTER_HAS_DEBUG (SCRIPT))) + { + gchar *tmp = g_strdup_value_contents (value); + + CLUTTER_NOTE (SCRIPT, + "in ClutterActor::set_custom_property('%s') = %s", + name, + tmp); + + g_free (tmp); + } +#endif /* CLUTTER_ENABLE_DEBUG */ + + if (strcmp (name, "rotation") == 0) + { + RotationInfo *info; + + if (!G_VALUE_HOLDS (value, G_TYPE_POINTER)) + return; + + info = g_value_get_pointer (value); + + clutter_actor_set_rotation (actor, + info->axis, info->angle, + info->center_x, + info->center_y, + info->center_z); + + g_slice_free (RotationInfo, info); + + return; + } + + if (strcmp (name, "behaviours") == 0) + { + GSList *behaviours, *l; + + if (!G_VALUE_HOLDS (value, G_TYPE_POINTER)) + return; + + behaviours = g_value_get_pointer (value); + for (l = behaviours; l != NULL; l = l->next) + { + ClutterBehaviour *behaviour = l->data; + + clutter_behaviour_apply (behaviour, actor); + } + + g_slist_free (behaviours); + + return; + } + + if (strcmp (name, "actions") == 0 || + strcmp (name, "constraints") == 0 || + strcmp (name, "effects") == 0) + { + GSList *metas, *l; + + if (!G_VALUE_HOLDS (value, G_TYPE_POINTER)) + return; + + metas = g_value_get_pointer (value); + for (l = metas; l != NULL; l = l->next) + { + if (name[0] == 'a') + clutter_actor_add_action (actor, l->data); + + if (name[0] == 'c') + clutter_actor_add_constraint (actor, l->data); + + if (name[0] == 'e') + clutter_actor_add_effect (actor, l->data); + } + + g_slist_free (metas); + + return; + } + if (strcmp (name, "margin") == 0) + { + clutter_actor_set_margin (actor, g_value_get_boxed (value)); + return; + } + + g_object_set_property (G_OBJECT (scriptable), name, value); +} + +static void +clutter_scriptable_iface_init (ClutterScriptableIface *iface) +{ + iface->parse_custom_node = clutter_actor_parse_custom_node; + iface->set_custom_property = clutter_actor_set_custom_property; +} + +static ClutterActorMeta * +get_meta_from_animation_property (ClutterActor *actor, + const gchar *name, + gchar **name_p) +{ + ClutterActorPrivate *priv = actor->priv; + ClutterActorMeta *meta = NULL; + gchar **tokens; + + /* if this is not a special property, fall through */ + if (name[0] != '@') + return NULL; + + /* detect the properties named using the following spec: + * + * @
.. + * + * where
can be one of the following: + * + * - actions + * - constraints + * - effects + * + * and is the name set on a specific ActorMeta + */ + + tokens = g_strsplit (name + 1, ".", -1); + if (tokens == NULL || g_strv_length (tokens) != 3) + { + CLUTTER_NOTE (ANIMATION, "Invalid property name '%s'", + name + 1); + g_strfreev (tokens); + return NULL; + } + + if (strcmp (tokens[0], "actions") == 0) + meta = _clutter_meta_group_get_meta (priv->actions, tokens[1]); + + if (strcmp (tokens[0], "constraints") == 0) + meta = _clutter_meta_group_get_meta (priv->constraints, tokens[1]); + + if (strcmp (tokens[0], "effects") == 0) + meta = _clutter_meta_group_get_meta (priv->effects, tokens[1]); + + if (name_p != NULL) + *name_p = g_strdup (tokens[2]); + + CLUTTER_NOTE (ANIMATION, + "Looking for property '%s' of object '%s' in section '%s'", + tokens[2], + tokens[1], + tokens[0]); + + g_strfreev (tokens); + + return meta; +} + +static GParamSpec * +clutter_actor_find_property (ClutterAnimatable *animatable, + const gchar *property_name) +{ + ClutterActorMeta *meta = NULL; + GObjectClass *klass = NULL; + GParamSpec *pspec = NULL; + gchar *p_name = NULL; + + meta = get_meta_from_animation_property (CLUTTER_ACTOR (animatable), + property_name, + &p_name); + + if (meta != NULL) + { + klass = G_OBJECT_GET_CLASS (meta); + + pspec = g_object_class_find_property (klass, p_name); + } + else + { + klass = G_OBJECT_GET_CLASS (animatable); + + pspec = g_object_class_find_property (klass, property_name); + } + + g_free (p_name); + + return pspec; +} + +static void +clutter_actor_get_initial_state (ClutterAnimatable *animatable, + const gchar *property_name, + GValue *initial) +{ + ClutterActorMeta *meta = NULL; + gchar *p_name = NULL; + + meta = get_meta_from_animation_property (CLUTTER_ACTOR (animatable), + property_name, + &p_name); + + if (meta != NULL) + g_object_get_property (G_OBJECT (meta), p_name, initial); + else + g_object_get_property (G_OBJECT (animatable), property_name, initial); + + g_free (p_name); +} + +/* + * clutter_actor_set_animatable_property: + * @actor: a #ClutterActor + * @prop_id: the paramspec id + * @value: the value to set + * @pspec: the paramspec + * + * Sets values of animatable properties. + * + * This is a variant of clutter_actor_set_property() that gets called + * by the #ClutterAnimatable implementation of #ClutterActor for the + * properties with the %CLUTTER_PARAM_ANIMATABLE flag set on their + * #GParamSpec. + * + * Unlike the implementation of #GObjectClass.set_property(), this + * function will not update the interval if a transition involving an + * animatable property is in progress - this avoids cycles with the + * transition API calling the public API. + */ +static void +clutter_actor_set_animatable_property (ClutterActor *actor, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GObject *obj = G_OBJECT (actor); + + g_object_freeze_notify (obj); + + switch (prop_id) + { + case PROP_X: + clutter_actor_set_x_internal (actor, g_value_get_float (value)); + break; + + case PROP_Y: + clutter_actor_set_y_internal (actor, g_value_get_float (value)); + break; + + case PROP_POSITION: + clutter_actor_set_position_internal (actor, g_value_get_boxed (value)); + break; + + case PROP_WIDTH: + clutter_actor_set_width_internal (actor, g_value_get_float (value)); + break; + + case PROP_HEIGHT: + clutter_actor_set_height_internal (actor, g_value_get_float (value)); + break; + + case PROP_SIZE: + clutter_actor_set_size_internal (actor, g_value_get_boxed (value)); + break; + + case PROP_ALLOCATION: + clutter_actor_allocate_internal (actor, + g_value_get_boxed (value), + actor->priv->allocation_flags); + clutter_actor_queue_redraw (actor); + break; + + case PROP_DEPTH: + clutter_actor_set_depth_internal (actor, g_value_get_float (value)); + break; + + case PROP_Z_POSITION: + clutter_actor_set_z_position_internal (actor, g_value_get_float (value)); + break; + + case PROP_OPACITY: + clutter_actor_set_opacity_internal (actor, g_value_get_uint (value)); + break; + + case PROP_BACKGROUND_COLOR: + clutter_actor_set_background_color_internal (actor, clutter_value_get_color (value)); + break; + + case PROP_PIVOT_POINT: + clutter_actor_set_pivot_point_internal (actor, g_value_get_boxed (value)); + break; + + case PROP_PIVOT_POINT_Z: + clutter_actor_set_pivot_point_z_internal (actor, g_value_get_float (value)); + break; + + case PROP_TRANSLATION_X: + case PROP_TRANSLATION_Y: + case PROP_TRANSLATION_Z: + clutter_actor_set_translation_internal (actor, + g_value_get_float (value), + pspec); + break; + + case PROP_SCALE_X: + case PROP_SCALE_Y: + case PROP_SCALE_Z: + clutter_actor_set_scale_factor_internal (actor, + g_value_get_double (value), + pspec); + break; + + case PROP_ROTATION_ANGLE_X: + case PROP_ROTATION_ANGLE_Y: + case PROP_ROTATION_ANGLE_Z: + clutter_actor_set_rotation_angle_internal (actor, + g_value_get_double (value), + pspec); + break; + + case PROP_CONTENT_BOX: + clutter_actor_store_content_box (actor, g_value_get_boxed (value)); + break; + + case PROP_MARGIN_TOP: + case PROP_MARGIN_BOTTOM: + case PROP_MARGIN_LEFT: + case PROP_MARGIN_RIGHT: + clutter_actor_set_margin_internal (actor, g_value_get_float (value), + pspec); + break; + + case PROP_TRANSFORM: + clutter_actor_set_transform_internal (actor, g_value_get_boxed (value)); + break; + + case PROP_CHILD_TRANSFORM: + clutter_actor_set_child_transform_internal (actor, g_value_get_boxed (value)); + break; + + default: + g_object_set_property (obj, pspec->name, value); + break; + } + + g_object_thaw_notify (obj); +} + +static void +clutter_actor_set_final_state (ClutterAnimatable *animatable, + const gchar *property_name, + const GValue *final) +{ + ClutterActor *actor = CLUTTER_ACTOR (animatable); + ClutterActorMeta *meta = NULL; + gchar *p_name = NULL; + + meta = get_meta_from_animation_property (actor, + property_name, + &p_name); + if (meta != NULL) + g_object_set_property (G_OBJECT (meta), p_name, final); + else + { + GObjectClass *obj_class = G_OBJECT_GET_CLASS (animatable); + GParamSpec *pspec; + + pspec = g_object_class_find_property (obj_class, property_name); + + if (pspec != NULL) + { + if ((pspec->flags & CLUTTER_PARAM_ANIMATABLE) != 0) + { + /* XXX - I'm going to the special hell for this */ + clutter_actor_set_animatable_property (actor, pspec->param_id, final, pspec); + } + else + g_object_set_property (G_OBJECT (animatable), pspec->name, final); + } + } + + g_free (p_name); +} + +static void +clutter_animatable_iface_init (ClutterAnimatableIface *iface) +{ + iface->find_property = clutter_actor_find_property; + iface->get_initial_state = clutter_actor_get_initial_state; + iface->set_final_state = clutter_actor_set_final_state; +} + +/** + * clutter_actor_transform_stage_point: + * @self: A #ClutterActor + * @x: (in): x screen coordinate of the point to unproject + * @y: (in): y screen coordinate of the point to unproject + * @x_out: (out): return location for the unprojected x coordinance + * @y_out: (out): return location for the unprojected y coordinance + * + * This function translates screen coordinates (@x, @y) to + * coordinates relative to the actor. For example, it can be used to translate + * screen events from global screen coordinates into actor-local coordinates. + * + * The conversion can fail, notably if the transform stack results in the + * actor being projected on the screen as a mere line. + * + * The conversion should not be expected to be pixel-perfect due to the + * nature of the operation. In general the error grows when the skewing + * of the actor rectangle on screen increases. + * + * This function can be computationally intensive. + * + * This function only works when the allocation is up-to-date, i.e. inside of + * the #ClutterActorClass.paint() implementation + * + * Return value: %TRUE if conversion was successful. + * + * Since: 0.6 + */ +gboolean +clutter_actor_transform_stage_point (ClutterActor *self, + gfloat x, + gfloat y, + gfloat *x_out, + gfloat *y_out) +{ + ClutterVertex v[4]; + double ST[3][3]; + double RQ[3][3]; + int du, dv; + double px, py; + double det; + float xf, yf, wf; + ClutterActorPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); + + priv = self->priv; + + /* This implementation is based on the quad -> quad projection algorithm + * described by Paul Heckbert in: + * + * http://www.cs.cmu.edu/~ph/texfund/texfund.pdf + * + * and the sample implementation at: + * + * http://www.cs.cmu.edu/~ph/src/texfund/ + * + * Our texture is a rectangle with origin [0, 0], so we are mapping from + * quad to rectangle only, which significantly simplifies things; the + * function calls have been unrolled, and most of the math is done in fixed + * point. + */ + clutter_actor_get_abs_allocation_vertices (self, v); + + /* Keeping these as ints simplifies the multiplication (no significant + * loss of precision here). + */ + du = ceilf (priv->allocation.x2 - priv->allocation.x1); + dv = ceilf (priv->allocation.y2 - priv->allocation.y1); + + if (du == 0 || dv == 0) + return FALSE; + +#define DET(a,b,c,d) (((a) * (d)) - ((b) * (c))) + + /* First, find mapping from unit uv square to xy quadrilateral; this + * equivalent to the pmap_square_quad() functions in the sample + * implementation, which we can simplify, since our target is always + * a rectangle. + */ + px = v[0].x - v[1].x + v[3].x - v[2].x; + py = v[0].y - v[1].y + v[3].y - v[2].y; + + if ((int) px == 0 && (int) py == 0) + { + /* affine transform */ + RQ[0][0] = v[1].x - v[0].x; + RQ[1][0] = v[3].x - v[1].x; + RQ[2][0] = v[0].x; + RQ[0][1] = v[1].y - v[0].y; + RQ[1][1] = v[3].y - v[1].y; + RQ[2][1] = v[0].y; + RQ[0][2] = 0.0; + RQ[1][2] = 0.0; + RQ[2][2] = 1.0; + } + else + { + /* projective transform */ + double dx1, dx2, dy1, dy2; + + dx1 = v[1].x - v[3].x; + dx2 = v[2].x - v[3].x; + dy1 = v[1].y - v[3].y; + dy2 = v[2].y - v[3].y; + + det = DET (dx1, dx2, dy1, dy2); + if (fabs (det) <= DBL_EPSILON) + return FALSE; + + RQ[0][2] = DET (px, dx2, py, dy2) / det; + RQ[1][2] = DET (dx1, px, dy1, py) / det; + RQ[1][2] = DET (dx1, px, dy1, py) / det; + RQ[2][2] = 1.0; + RQ[0][0] = v[1].x - v[0].x + (RQ[0][2] * v[1].x); + RQ[1][0] = v[2].x - v[0].x + (RQ[1][2] * v[2].x); + RQ[2][0] = v[0].x; + RQ[0][1] = v[1].y - v[0].y + (RQ[0][2] * v[1].y); + RQ[1][1] = v[2].y - v[0].y + (RQ[1][2] * v[2].y); + RQ[2][1] = v[0].y; + } + + /* + * Now combine with transform from our rectangle (u0,v0,u1,v1) to unit + * square. Since our rectangle is based at 0,0 we only need to scale. + */ + RQ[0][0] /= du; + RQ[1][0] /= dv; + RQ[0][1] /= du; + RQ[1][1] /= dv; + RQ[0][2] /= du; + RQ[1][2] /= dv; + + /* + * Now RQ is transform from uv rectangle to xy quadrilateral; we need an + * inverse of that. + */ + ST[0][0] = DET (RQ[1][1], RQ[1][2], RQ[2][1], RQ[2][2]); + ST[1][0] = DET (RQ[1][2], RQ[1][0], RQ[2][2], RQ[2][0]); + ST[2][0] = DET (RQ[1][0], RQ[1][1], RQ[2][0], RQ[2][1]); + ST[0][1] = DET (RQ[2][1], RQ[2][2], RQ[0][1], RQ[0][2]); + ST[1][1] = DET (RQ[2][2], RQ[2][0], RQ[0][2], RQ[0][0]); + ST[2][1] = DET (RQ[2][0], RQ[2][1], RQ[0][0], RQ[0][1]); + ST[0][2] = DET (RQ[0][1], RQ[0][2], RQ[1][1], RQ[1][2]); + ST[1][2] = DET (RQ[0][2], RQ[0][0], RQ[1][2], RQ[1][0]); + ST[2][2] = DET (RQ[0][0], RQ[0][1], RQ[1][0], RQ[1][1]); + + /* + * Check the resulting matrix is OK. + */ + det = (RQ[0][0] * ST[0][0]) + + (RQ[0][1] * ST[0][1]) + + (RQ[0][2] * ST[0][2]); + if (fabs (det) <= DBL_EPSILON) + return FALSE; + + /* + * Now transform our point with the ST matrix; the notional w + * coordinate is 1, hence the last part is simply added. + */ + xf = x * ST[0][0] + y * ST[1][0] + ST[2][0]; + yf = x * ST[0][1] + y * ST[1][1] + ST[2][1]; + wf = x * ST[0][2] + y * ST[1][2] + ST[2][2]; + + if (x_out) + *x_out = xf / wf; + + if (y_out) + *y_out = yf / wf; + +#undef DET + + return TRUE; +} + +/** + * clutter_actor_is_rotated: + * @self: a #ClutterActor + * + * Checks whether any rotation is applied to the actor. + * + * Return value: %TRUE if the actor is rotated. + * + * Since: 0.6 + */ +gboolean +clutter_actor_is_rotated (ClutterActor *self) +{ + const ClutterTransformInfo *info; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); + + info = _clutter_actor_get_transform_info_or_defaults (self); + + if (info->rx_angle || info->ry_angle || info->rz_angle) + return TRUE; + + return FALSE; +} + +/** + * clutter_actor_is_scaled: + * @self: a #ClutterActor + * + * Checks whether the actor is scaled in either dimension. + * + * Return value: %TRUE if the actor is scaled. + * + * Since: 0.6 + */ +gboolean +clutter_actor_is_scaled (ClutterActor *self) +{ + const ClutterTransformInfo *info; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); + + info = _clutter_actor_get_transform_info_or_defaults (self); + + if (info->scale_x != 1.0 || info->scale_y != 1.0) + return TRUE; + + return FALSE; +} + +ClutterActor * +_clutter_actor_get_stage_internal (ClutterActor *actor) +{ + while (actor && !CLUTTER_ACTOR_IS_TOPLEVEL (actor)) + actor = actor->priv->parent; + + return actor; +} + +/** + * clutter_actor_get_stage: + * @actor: a #ClutterActor + * + * Retrieves the #ClutterStage where @actor is contained. + * + * Return value: (transfer none) (type Clutter.Stage): the stage + * containing the actor, or %NULL + * + * Since: 0.8 + */ +ClutterActor * +clutter_actor_get_stage (ClutterActor *actor) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), NULL); + + return _clutter_actor_get_stage_internal (actor); +} + +/** + * clutter_actor_allocate_available_size: + * @self: a #ClutterActor + * @x: the actor's X coordinate + * @y: the actor's Y coordinate + * @available_width: the maximum available width, or -1 to use the + * actor's natural width + * @available_height: the maximum available height, or -1 to use the + * actor's natural height + * @flags: flags controlling the allocation + * + * Allocates @self taking into account the #ClutterActor's + * preferred size, but limiting it to the maximum available width + * and height provided. + * + * This function will do the right thing when dealing with the + * actor's request mode. + * + * The implementation of this function is equivalent to: + * + * |[ + * if (request_mode == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH) + * { + * clutter_actor_get_preferred_width (self, available_height, + * &min_width, + * &natural_width); + * width = CLAMP (natural_width, min_width, available_width); + * + * clutter_actor_get_preferred_height (self, width, + * &min_height, + * &natural_height); + * height = CLAMP (natural_height, min_height, available_height); + * } + * else if (request_mode == CLUTTER_REQUEST_WIDTH_FOR_HEIGHT) + * { + * clutter_actor_get_preferred_height (self, available_width, + * &min_height, + * &natural_height); + * height = CLAMP (natural_height, min_height, available_height); + * + * clutter_actor_get_preferred_width (self, height, + * &min_width, + * &natural_width); + * width = CLAMP (natural_width, min_width, available_width); + * } + * else if (request_mode == CLUTTER_REQUEST_CONTENT_SIZE) + * { + * clutter_content_get_preferred_size (content, &natural_width, &natural_height); + * + * width = CLAMP (natural_width, 0, available_width); + * height = CLAMP (natural_height, 0, available_height); + * } + * + * box.x1 = x; box.y1 = y; + * box.x2 = box.x1 + available_width; + * box.y2 = box.y1 + available_height; + * clutter_actor_allocate (self, &box, flags); + * ]| + * + * This function can be used by fluid layout managers to allocate + * an actor's preferred size without making it bigger than the area + * available for the container. + * + * Since: 1.0 + */ +void +clutter_actor_allocate_available_size (ClutterActor *self, + gfloat x, + gfloat y, + gfloat available_width, + gfloat available_height, + ClutterAllocationFlags flags) +{ + ClutterActorPrivate *priv; + gfloat width, height; + gfloat min_width, min_height; + gfloat natural_width, natural_height; + ClutterActorBox box; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + priv = self->priv; + + width = height = 0.0; + + switch (priv->request_mode) + { + case CLUTTER_REQUEST_HEIGHT_FOR_WIDTH: + clutter_actor_get_preferred_width (self, available_height, + &min_width, + &natural_width); + width = CLAMP (natural_width, min_width, available_width); + + clutter_actor_get_preferred_height (self, width, + &min_height, + &natural_height); + height = CLAMP (natural_height, min_height, available_height); + break; + + case CLUTTER_REQUEST_WIDTH_FOR_HEIGHT: + clutter_actor_get_preferred_height (self, available_width, + &min_height, + &natural_height); + height = CLAMP (natural_height, min_height, available_height); + + clutter_actor_get_preferred_width (self, height, + &min_width, + &natural_width); + width = CLAMP (natural_width, min_width, available_width); + break; + + case CLUTTER_REQUEST_CONTENT_SIZE: + if (priv->content != NULL) + { + clutter_content_get_preferred_size (priv->content, &natural_width, &natural_height); + + width = CLAMP (natural_width, 0, available_width); + height = CLAMP (natural_height, 0, available_height); + } + break; + } + + + box.x1 = x; + box.y1 = y; + box.x2 = box.x1 + width; + box.y2 = box.y1 + height; + clutter_actor_allocate (self, &box, flags); +} + +/** + * clutter_actor_allocate_preferred_size: + * @self: a #ClutterActor + * @flags: flags controlling the allocation + * + * Allocates the natural size of @self. + * + * This function is a utility call for #ClutterActor implementations + * that allocates the actor's preferred natural size. It can be used + * by fixed layout managers (like #ClutterGroup or so called + * 'composite actors') inside the ClutterActor::allocate + * implementation to give each child exactly how much space it + * requires, regardless of the size of the parent. + * + * This function is not meant to be used by applications. It is also + * not meant to be used outside the implementation of the + * #ClutterActorClass.allocate virtual function. + * + * Since: 0.8 + */ +void +clutter_actor_allocate_preferred_size (ClutterActor *self, + ClutterAllocationFlags flags) +{ + gfloat actor_x, actor_y; + gfloat natural_width, natural_height; + ClutterActorBox actor_box; + ClutterActorPrivate *priv; + const ClutterLayoutInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + priv = self->priv; + + if (priv->position_set) + { + info = _clutter_actor_get_layout_info_or_defaults (self); + actor_x = info->fixed_pos.x; + actor_y = info->fixed_pos.y; + } + else + { + actor_x = 0; + actor_y = 0; + } + + clutter_actor_get_preferred_size (self, + NULL, NULL, + &natural_width, + &natural_height); + + actor_box.x1 = actor_x; + actor_box.y1 = actor_y; + actor_box.x2 = actor_box.x1 + natural_width; + actor_box.y2 = actor_box.y1 + natural_height; + + clutter_actor_allocate (self, &actor_box, flags); +} + +/** + * clutter_actor_allocate_align_fill: + * @self: a #ClutterActor + * @box: a #ClutterActorBox, containing the available width and height + * @x_align: the horizontal alignment, between 0 and 1 + * @y_align: the vertical alignment, between 0 and 1 + * @x_fill: whether the actor should fill horizontally + * @y_fill: whether the actor should fill vertically + * @flags: allocation flags to be passed to clutter_actor_allocate() + * + * Allocates @self by taking into consideration the available allocation + * area; an alignment factor on either axis; and whether the actor should + * fill the allocation on either axis. + * + * The @box should contain the available allocation width and height; + * if the x1 and y1 members of #ClutterActorBox are not set to 0, the + * allocation will be offset by their value. + * + * This function takes into consideration the geometry request specified by + * the #ClutterActor:request-mode property, and the text direction. + * + * This function is useful for fluid layout managers using legacy alignment + * flags. Newly written layout managers should use the #ClutterActor:x-align + * and #ClutterActor:y-align properties, instead, and just call + * clutter_actor_allocate() inside their #ClutterActorClass.allocate() + * implementation. + * + * Since: 1.4 + */ +void +clutter_actor_allocate_align_fill (ClutterActor *self, + const ClutterActorBox *box, + gdouble x_align, + gdouble y_align, + gboolean x_fill, + gboolean y_fill, + ClutterAllocationFlags flags) +{ + ClutterActorPrivate *priv; + ClutterActorBox allocation = CLUTTER_ACTOR_BOX_INIT_ZERO; + gfloat x_offset, y_offset; + gfloat available_width, available_height; + gfloat child_width = 0.f, child_height = 0.f; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (box != NULL); + g_return_if_fail (x_align >= 0.0 && x_align <= 1.0); + g_return_if_fail (y_align >= 0.0 && y_align <= 1.0); + + priv = self->priv; + + clutter_actor_box_get_origin (box, &x_offset, &y_offset); + clutter_actor_box_get_size (box, &available_width, &available_height); + + if (available_width <= 0) + available_width = 0.f; + + if (available_height <= 0) + available_height = 0.f; + + allocation.x1 = x_offset; + allocation.y1 = y_offset; + + if (available_width == 0.f && available_height == 0.f) + goto out; + + if (x_fill) + child_width = available_width; + + if (y_fill) + child_height = available_height; + + /* if we are filling horizontally and vertically then we're done */ + if (x_fill && y_fill) + goto out; + + if (priv->request_mode == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH) + { + gfloat min_width, natural_width; + gfloat min_height, natural_height; + + if (!x_fill) + { + clutter_actor_get_preferred_width (self, available_height, + &min_width, + &natural_width); + + child_width = CLAMP (natural_width, min_width, available_width); + } + + if (!y_fill) + { + clutter_actor_get_preferred_height (self, child_width, + &min_height, + &natural_height); + + child_height = CLAMP (natural_height, min_height, available_height); + } + } + else if (priv->request_mode == CLUTTER_REQUEST_WIDTH_FOR_HEIGHT) + { + gfloat min_width, natural_width; + gfloat min_height, natural_height; + + if (!y_fill) + { + clutter_actor_get_preferred_height (self, available_width, + &min_height, + &natural_height); + + child_height = CLAMP (natural_height, min_height, available_height); + } + + if (!x_fill) + { + clutter_actor_get_preferred_width (self, child_height, + &min_width, + &natural_width); + + child_width = CLAMP (natural_width, min_width, available_width); + } + } + else if (priv->request_mode == CLUTTER_REQUEST_CONTENT_SIZE && priv->content != NULL) + { + gfloat natural_width, natural_height; + + clutter_content_get_preferred_size (priv->content, &natural_width, &natural_height); + + if (!x_fill) + child_width = CLAMP (natural_width, 0, available_width); + + if (!y_fill) + child_height = CLAMP (natural_height, 0, available_height); + } + + /* invert the horizontal alignment for RTL languages */ + if (priv->text_direction == CLUTTER_TEXT_DIRECTION_RTL) + x_align = 1.0 - x_align; + + if (!x_fill) + allocation.x1 += ((available_width - child_width) * x_align); + + if (!y_fill) + allocation.y1 += ((available_height - child_height) * y_align); + +out: + + allocation.x1 = floorf (allocation.x1); + allocation.y1 = floorf (allocation.y1); + allocation.x2 = ceilf (allocation.x1 + MAX (child_width, 0)); + allocation.y2 = ceilf (allocation.y1 + MAX (child_height, 0)); + + clutter_actor_allocate (self, &allocation, flags); +} + +/** + * clutter_actor_grab_key_focus: + * @self: a #ClutterActor + * + * Sets the key focus of the #ClutterStage including @self + * to this #ClutterActor. + * + * Since: 1.0 + */ +void +clutter_actor_grab_key_focus (ClutterActor *self) +{ + ClutterActor *stage; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + stage = _clutter_actor_get_stage_internal (self); + if (stage != NULL) + clutter_stage_set_key_focus (CLUTTER_STAGE (stage), self); +} + +static void +update_pango_context (ClutterBackend *backend, + PangoContext *context) +{ + ClutterSettings *settings; + PangoFontDescription *font_desc; + const cairo_font_options_t *font_options; + gchar *font_name; + PangoDirection pango_dir; + gdouble resolution; + + settings = clutter_settings_get_default (); + + /* update the text direction */ + if (clutter_get_default_text_direction () == CLUTTER_TEXT_DIRECTION_RTL) + pango_dir = PANGO_DIRECTION_RTL; + else + pango_dir = PANGO_DIRECTION_LTR; + + pango_context_set_base_dir (context, pango_dir); + + g_object_get (settings, "font-name", &font_name, NULL); + + /* get the configuration for the PangoContext from the backend */ + font_options = clutter_backend_get_font_options (backend); + resolution = clutter_backend_get_resolution (backend); + + font_desc = pango_font_description_from_string (font_name); + + if (resolution < 0) + resolution = 96.0; /* fall back */ + + pango_context_set_font_description (context, font_desc); + pango_cairo_context_set_font_options (context, font_options); + pango_cairo_context_set_resolution (context, resolution); + + pango_font_description_free (font_desc); + g_free (font_name); +} + +/** + * clutter_actor_get_pango_context: + * @self: a #ClutterActor + * + * Retrieves the #PangoContext for @self. The actor's #PangoContext + * is already configured using the appropriate font map, resolution + * and font options. + * + * Unlike clutter_actor_create_pango_context(), this context is owend + * by the #ClutterActor and it will be updated each time the options + * stored by the #ClutterBackend change. + * + * You can use the returned #PangoContext to create a #PangoLayout + * and render text using cogl_pango_render_layout() to reuse the + * glyphs cache also used by Clutter. + * + * Return value: (transfer none): the #PangoContext for a #ClutterActor. + * The returned #PangoContext is owned by the actor and should not be + * unreferenced by the application code + * + * Since: 1.0 + */ +PangoContext * +clutter_actor_get_pango_context (ClutterActor *self) +{ + ClutterActorPrivate *priv; + ClutterBackend *backend = clutter_get_default_backend (); + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + + priv = self->priv; + + if (G_UNLIKELY (priv->pango_context == NULL)) + { + priv->pango_context = clutter_actor_create_pango_context (self); + + g_signal_connect_object (backend, "resolution-changed", + G_CALLBACK (update_pango_context), priv->pango_context, 0); + g_signal_connect_object (backend, "font-changed", + G_CALLBACK (update_pango_context), priv->pango_context, 0); + } + else + update_pango_context (backend, priv->pango_context); + + return priv->pango_context; +} + +/** + * clutter_actor_create_pango_context: + * @self: a #ClutterActor + * + * Creates a #PangoContext for the given actor. The #PangoContext + * is already configured using the appropriate font map, resolution + * and font options. + * + * See also clutter_actor_get_pango_context(). + * + * Return value: (transfer full): the newly created #PangoContext. + * Use g_object_unref() on the returned value to deallocate its + * resources + * + * Since: 1.0 + */ +PangoContext * +clutter_actor_create_pango_context (ClutterActor *self) +{ + CoglPangoFontMap *font_map; + PangoContext *context; + + font_map = COGL_PANGO_FONT_MAP (clutter_get_font_map ()); + + context = cogl_pango_font_map_create_context (font_map); + update_pango_context (clutter_get_default_backend (), context); + pango_context_set_language (context, pango_language_get_default ()); + + return context; +} + +/** + * clutter_actor_create_pango_layout: + * @self: a #ClutterActor + * @text: (allow-none): the text to set on the #PangoLayout, or %NULL + * + * Creates a new #PangoLayout from the same #PangoContext used + * by the #ClutterActor. The #PangoLayout is already configured + * with the font map, resolution and font options, and the + * given @text. + * + * If you want to keep around a #PangoLayout created by this + * function you will have to connect to the #ClutterBackend::font-changed + * and #ClutterBackend::resolution-changed signals, and call + * pango_layout_context_changed() in response to them. + * + * Return value: (transfer full): the newly created #PangoLayout. + * Use g_object_unref() when done + * + * Since: 1.0 + */ +PangoLayout * +clutter_actor_create_pango_layout (ClutterActor *self, + const gchar *text) +{ + PangoContext *context; + PangoLayout *layout; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + + context = clutter_actor_get_pango_context (self); + layout = pango_layout_new (context); + + if (text) + pango_layout_set_text (layout, text, -1); + + return layout; +} + +/** + * clutter_actor_set_opacity_override: + * @self: a #ClutterActor + * @opacity: the override opacity value, or -1 to reset + * + * Allows overriding the calculated paint opacity (as returned by + * clutter_actor_get_paint_opacity()). This is used internally by + * ClutterClone and ClutterOffscreenEffect, and should be used by + * actors that need to mimick those. + * + * In almost all cases this should not used by applications. + * + * Stability: unstable + */ +void +clutter_actor_set_opacity_override (ClutterActor *self, + gint opacity) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + /* ensure bounds */ + if (opacity >= 0) + opacity = CLAMP (opacity, 0, 255); + else + opacity = -1; + + self->priv->opacity_override = opacity; +} + +/** + * clutter_actor_get_opacity_override: + * @self: a #ClutterActor + * + * See clutter_actor_set_opacity_override() + * + * Returns: the override value for the actor's opacity, or -1 if no override + * is set. + * + * Since: 1.22 + * + * Stability: unstable + */ +gint +clutter_actor_get_opacity_override (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), -1); + + return self->priv->opacity_override; +} + +/* Allows you to disable applying the actors model view transform during + * a paint. Used by ClutterClone. */ +void +_clutter_actor_set_enable_model_view_transform (ClutterActor *self, + gboolean enable) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + self->priv->enable_model_view_transform = enable; +} + +void +_clutter_actor_set_enable_paint_unmapped (ClutterActor *self, + gboolean enable) +{ + ClutterActorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + priv = self->priv; + + priv->enable_paint_unmapped = enable; + + if (priv->enable_paint_unmapped) + { + /* Make sure that the parents of the widget are realized first; + * otherwise checks in clutter_actor_update_map_state() will + * fail. + */ + clutter_actor_realize (self); + + /* If the actor isn't ultimately connected to a toplevel, it can't be + * realized or painted. + */ + if (CLUTTER_ACTOR_IS_REALIZED (self)) + clutter_actor_update_map_state (self, MAP_STATE_MAKE_MAPPED); + } + else + { + clutter_actor_update_map_state (self, MAP_STATE_CHECK); + } +} + +static void +clutter_anchor_coord_get_units (ClutterActor *self, + const AnchorCoord *coord, + gfloat *x, + gfloat *y, + gfloat *z) +{ + if (coord->is_fractional) + { + gfloat actor_width, actor_height; + + clutter_actor_get_size (self, &actor_width, &actor_height); + + if (x) + *x = actor_width * coord->v.fraction.x; + + if (y) + *y = actor_height * coord->v.fraction.y; + + if (z) + *z = 0; + } + else + { + if (x) + *x = coord->v.units.x; + + if (y) + *y = coord->v.units.y; + + if (z) + *z = coord->v.units.z; + } +} + +static void +clutter_anchor_coord_set_units (AnchorCoord *coord, + gfloat x, + gfloat y, + gfloat z) +{ + coord->is_fractional = FALSE; + coord->v.units.x = x; + coord->v.units.y = y; + coord->v.units.z = z; +} + +static ClutterGravity +clutter_anchor_coord_get_gravity (const AnchorCoord *coord) +{ + if (coord->is_fractional) + { + if (coord->v.fraction.x == 0.0) + { + if (coord->v.fraction.y == 0.0) + return CLUTTER_GRAVITY_NORTH_WEST; + else if (coord->v.fraction.y == 0.5) + return CLUTTER_GRAVITY_WEST; + else if (coord->v.fraction.y == 1.0) + return CLUTTER_GRAVITY_SOUTH_WEST; + else + return CLUTTER_GRAVITY_NONE; + } + else if (coord->v.fraction.x == 0.5) + { + if (coord->v.fraction.y == 0.0) + return CLUTTER_GRAVITY_NORTH; + else if (coord->v.fraction.y == 0.5) + return CLUTTER_GRAVITY_CENTER; + else if (coord->v.fraction.y == 1.0) + return CLUTTER_GRAVITY_SOUTH; + else + return CLUTTER_GRAVITY_NONE; + } + else if (coord->v.fraction.x == 1.0) + { + if (coord->v.fraction.y == 0.0) + return CLUTTER_GRAVITY_NORTH_EAST; + else if (coord->v.fraction.y == 0.5) + return CLUTTER_GRAVITY_EAST; + else if (coord->v.fraction.y == 1.0) + return CLUTTER_GRAVITY_SOUTH_EAST; + else + return CLUTTER_GRAVITY_NONE; + } + else + return CLUTTER_GRAVITY_NONE; + } + else + return CLUTTER_GRAVITY_NONE; +} + +static void +clutter_anchor_coord_set_gravity (AnchorCoord *coord, + ClutterGravity gravity) +{ + switch (gravity) + { + case CLUTTER_GRAVITY_NORTH: + coord->v.fraction.x = 0.5; + coord->v.fraction.y = 0.0; + break; + + case CLUTTER_GRAVITY_NORTH_EAST: + coord->v.fraction.x = 1.0; + coord->v.fraction.y = 0.0; + break; + + case CLUTTER_GRAVITY_EAST: + coord->v.fraction.x = 1.0; + coord->v.fraction.y = 0.5; + break; + + case CLUTTER_GRAVITY_SOUTH_EAST: + coord->v.fraction.x = 1.0; + coord->v.fraction.y = 1.0; + break; + + case CLUTTER_GRAVITY_SOUTH: + coord->v.fraction.x = 0.5; + coord->v.fraction.y = 1.0; + break; + + case CLUTTER_GRAVITY_SOUTH_WEST: + coord->v.fraction.x = 0.0; + coord->v.fraction.y = 1.0; + break; + + case CLUTTER_GRAVITY_WEST: + coord->v.fraction.x = 0.0; + coord->v.fraction.y = 0.5; + break; + + case CLUTTER_GRAVITY_NORTH_WEST: + coord->v.fraction.x = 0.0; + coord->v.fraction.y = 0.0; + break; + + case CLUTTER_GRAVITY_CENTER: + coord->v.fraction.x = 0.5; + coord->v.fraction.y = 0.5; + break; + + default: + coord->v.fraction.x = 0.0; + coord->v.fraction.y = 0.0; + break; + } + + coord->is_fractional = TRUE; +} + +static gboolean +clutter_anchor_coord_is_zero (const AnchorCoord *coord) +{ + if (coord->is_fractional) + return coord->v.fraction.x == 0.0 && coord->v.fraction.y == 0.0; + else + return (coord->v.units.x == 0.0 + && coord->v.units.y == 0.0 + && coord->v.units.z == 0.0); +} + +/** + * clutter_actor_get_flags: + * @self: a #ClutterActor + * + * Retrieves the flags set on @self + * + * Return value: a bitwise or of #ClutterActorFlags or 0 + * + * Since: 1.0 + */ +ClutterActorFlags +clutter_actor_get_flags (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0); + + return self->flags; +} + +/** + * clutter_actor_set_flags: + * @self: a #ClutterActor + * @flags: the flags to set + * + * Sets @flags on @self + * + * This function will emit notifications for the changed properties + * + * Since: 1.0 + */ +void +clutter_actor_set_flags (ClutterActor *self, + ClutterActorFlags flags) +{ + ClutterActorFlags old_flags; + GObject *obj; + gboolean was_reactive_set, reactive_set; + gboolean was_realized_set, realized_set; + gboolean was_mapped_set, mapped_set; + gboolean was_visible_set, visible_set; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + if (self->flags == flags) + return; + + obj = G_OBJECT (self); + g_object_ref (obj); + g_object_freeze_notify (obj); + + old_flags = self->flags; + + was_reactive_set = ((old_flags & CLUTTER_ACTOR_REACTIVE) != 0); + was_realized_set = ((old_flags & CLUTTER_ACTOR_REALIZED) != 0); + was_mapped_set = ((old_flags & CLUTTER_ACTOR_MAPPED) != 0); + was_visible_set = ((old_flags & CLUTTER_ACTOR_VISIBLE) != 0); + + self->flags |= flags; + + reactive_set = ((self->flags & CLUTTER_ACTOR_REACTIVE) != 0); + realized_set = ((self->flags & CLUTTER_ACTOR_REALIZED) != 0); + mapped_set = ((self->flags & CLUTTER_ACTOR_MAPPED) != 0); + visible_set = ((self->flags & CLUTTER_ACTOR_VISIBLE) != 0); + + if (reactive_set != was_reactive_set) + g_object_notify_by_pspec (obj, obj_props[PROP_REACTIVE]); + + if (realized_set != was_realized_set) + g_object_notify_by_pspec (obj, obj_props[PROP_REALIZED]); + + if (mapped_set != was_mapped_set) + g_object_notify_by_pspec (obj, obj_props[PROP_MAPPED]); + + if (visible_set != was_visible_set) + g_object_notify_by_pspec (obj, obj_props[PROP_VISIBLE]); + + g_object_thaw_notify (obj); + g_object_unref (obj); +} + +/** + * clutter_actor_unset_flags: + * @self: a #ClutterActor + * @flags: the flags to unset + * + * Unsets @flags on @self + * + * This function will emit notifications for the changed properties + * + * Since: 1.0 + */ +void +clutter_actor_unset_flags (ClutterActor *self, + ClutterActorFlags flags) +{ + ClutterActorFlags old_flags; + GObject *obj; + gboolean was_reactive_set, reactive_set; + gboolean was_realized_set, realized_set; + gboolean was_mapped_set, mapped_set; + gboolean was_visible_set, visible_set; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + obj = G_OBJECT (self); + g_object_freeze_notify (obj); + + old_flags = self->flags; + + was_reactive_set = ((old_flags & CLUTTER_ACTOR_REACTIVE) != 0); + was_realized_set = ((old_flags & CLUTTER_ACTOR_REALIZED) != 0); + was_mapped_set = ((old_flags & CLUTTER_ACTOR_MAPPED) != 0); + was_visible_set = ((old_flags & CLUTTER_ACTOR_VISIBLE) != 0); + + self->flags &= ~flags; + + if (self->flags == old_flags) + return; + + reactive_set = ((self->flags & CLUTTER_ACTOR_REACTIVE) != 0); + realized_set = ((self->flags & CLUTTER_ACTOR_REALIZED) != 0); + mapped_set = ((self->flags & CLUTTER_ACTOR_MAPPED) != 0); + visible_set = ((self->flags & CLUTTER_ACTOR_VISIBLE) != 0); + + if (reactive_set != was_reactive_set) + g_object_notify_by_pspec (obj, obj_props[PROP_REACTIVE]); + + if (realized_set != was_realized_set) + g_object_notify_by_pspec (obj, obj_props[PROP_REALIZED]); + + if (mapped_set != was_mapped_set) + g_object_notify_by_pspec (obj, obj_props[PROP_MAPPED]); + + if (visible_set != was_visible_set) + g_object_notify_by_pspec (obj, obj_props[PROP_VISIBLE]); + + g_object_thaw_notify (obj); +} + +/** + * clutter_actor_get_transformation_matrix: + * @self: a #ClutterActor + * @matrix: (out caller-allocates): the return location for a #ClutterMatrix + * + * Retrieves the transformations applied to @self relative to its + * parent. + * + * Since: 1.0 + * + * Deprecated: 1.12: Use clutter_actor_get_transform() instead + */ +void +clutter_actor_get_transformation_matrix (ClutterActor *self, + ClutterMatrix *matrix) +{ + clutter_actor_get_transform (self, matrix); +} + +static void +clutter_actor_set_transform_internal (ClutterActor *self, + const ClutterMatrix *transform) +{ + ClutterTransformInfo *info; + gboolean was_set; + GObject *obj; + + obj = G_OBJECT (self); + + info = _clutter_actor_get_transform_info (self); + + was_set = info->transform_set; + + info->transform = *transform; + info->transform_set = !cogl_matrix_is_identity (&info->transform); + + self->priv->transform_valid = FALSE; + + clutter_actor_queue_redraw (self); + + g_object_notify_by_pspec (obj, obj_props[PROP_TRANSFORM]); + + if (was_set != info->transform_set) + g_object_notify_by_pspec (obj, obj_props[PROP_TRANSFORM_SET]); +} + +/** + * clutter_actor_set_transform: + * @self: a #ClutterActor + * @transform: (allow-none): a #ClutterMatrix, or %NULL to + * unset a custom transformation + * + * Overrides the transformations of a #ClutterActor with a custom + * matrix, which will be applied relative to the origin of the + * actor's allocation and to the actor's pivot point. + * + * The #ClutterActor:transform property is animatable. + * + * Since: 1.12 + */ +void +clutter_actor_set_transform (ClutterActor *self, + const ClutterMatrix *transform) +{ + const ClutterTransformInfo *info; + ClutterMatrix new_transform; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + info = _clutter_actor_get_transform_info_or_defaults (self); + + if (transform != NULL) + clutter_matrix_init_from_matrix (&new_transform, transform); + else + clutter_matrix_init_identity (&new_transform); + + _clutter_actor_create_transition (self, obj_props[PROP_TRANSFORM], + &info->transform, + &new_transform); +} + +/** + * clutter_actor_get_transform: + * @self: a #ClutterActor + * @transform: (out caller-allocates): a #ClutterMatrix + * + * Retrieves the current transformation matrix of a #ClutterActor. + * + * Since: 1.12 + */ +void +clutter_actor_get_transform (ClutterActor *self, + ClutterMatrix *transform) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (transform != NULL); + + cogl_matrix_init_identity (transform); + _clutter_actor_apply_modelview_transform (self, transform); +} + +void +_clutter_actor_set_in_clone_paint (ClutterActor *self, + gboolean is_in_clone_paint) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + self->priv->in_clone_paint = is_in_clone_paint; +} + +/** + * clutter_actor_is_in_clone_paint: + * @self: a #ClutterActor + * + * Checks whether @self is being currently painted by a #ClutterClone + * + * This function is useful only inside the ::paint virtual function + * implementations or within handlers for the #ClutterActor::paint + * signal + * + * This function should not be used by applications + * + * Return value: %TRUE if the #ClutterActor is currently being painted + * by a #ClutterClone, and %FALSE otherwise + * + * Since: 1.0 + */ +gboolean +clutter_actor_is_in_clone_paint (ClutterActor *self) +{ + ClutterActor *parent; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); + + if (self->priv->in_clone_paint) + return TRUE; + + if (self->priv->in_cloned_branch == 0) + return FALSE; + + parent = self->priv->parent; + while (parent != NULL) + { + if (parent->priv->in_cloned_branch == 0) + break; + + if (parent->priv->in_clone_paint) + return TRUE; + + parent = parent->priv->parent; + } + + return FALSE; +} + +static gboolean +set_direction_recursive (ClutterActor *actor, + gpointer user_data) +{ + ClutterTextDirection text_dir = GPOINTER_TO_INT (user_data); + + clutter_actor_set_text_direction (actor, text_dir); + + return TRUE; +} + +/** + * clutter_actor_set_text_direction: + * @self: a #ClutterActor + * @text_dir: the text direction for @self + * + * Sets the #ClutterTextDirection for an actor + * + * The passed text direction must not be %CLUTTER_TEXT_DIRECTION_DEFAULT + * + * If @self implements #ClutterContainer then this function will recurse + * inside all the children of @self (including the internal ones). + * + * Composite actors not implementing #ClutterContainer, or actors requiring + * special handling when the text direction changes, should connect to + * the #GObject::notify signal for the #ClutterActor:text-direction property + * + * Since: 1.2 + */ +void +clutter_actor_set_text_direction (ClutterActor *self, + ClutterTextDirection text_dir) +{ + ClutterActorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (text_dir != CLUTTER_TEXT_DIRECTION_DEFAULT); + + priv = self->priv; + + if (priv->text_direction != text_dir) + { + priv->text_direction = text_dir; + + /* we need to emit the notify::text-direction first, so that + * the sub-classes can catch that and do specific handling of + * the text direction; see clutter_text_direction_changed_cb() + * inside clutter-text.c + */ + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_TEXT_DIRECTION]); + + _clutter_actor_foreach_child (self, set_direction_recursive, + GINT_TO_POINTER (text_dir)); + + clutter_actor_queue_relayout (self); + } +} + +void +_clutter_actor_set_has_pointer (ClutterActor *self, + gboolean has_pointer) +{ + ClutterActorPrivate *priv = self->priv; + + if (priv->has_pointer != has_pointer) + { + priv->has_pointer = has_pointer; + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_HAS_POINTER]); + } +} + +/** + * clutter_actor_get_text_direction: + * @self: a #ClutterActor + * + * Retrieves the value set using clutter_actor_set_text_direction() + * + * If no text direction has been previously set, the default text + * direction, as returned by clutter_get_default_text_direction(), will + * be returned instead + * + * Return value: the #ClutterTextDirection for the actor + * + * Since: 1.2 + */ +ClutterTextDirection +clutter_actor_get_text_direction (ClutterActor *self) +{ + ClutterActorPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), + CLUTTER_TEXT_DIRECTION_LTR); + + priv = self->priv; + + /* if no direction has been set yet use the default */ + if (priv->text_direction == CLUTTER_TEXT_DIRECTION_DEFAULT) + priv->text_direction = clutter_get_default_text_direction (); + + return priv->text_direction; +} + +/** + * clutter_actor_push_internal: + * @self: a #ClutterActor + * + * Should be used by actors implementing the #ClutterContainer and with + * internal children added through clutter_actor_set_parent(), for instance: + * + * |[ + * static void + * my_actor_init (MyActor *self) + * { + * self->priv = my_actor_get_instance_private (self); + * + * clutter_actor_push_internal (CLUTTER_ACTOR (self)); + * + * // calling clutter_actor_set_parent() now will result in + * // the internal flag being set on a child of MyActor + * + * // internal child - a background texture + * self->priv->background_tex = clutter_texture_new (); + * clutter_actor_set_parent (self->priv->background_tex, + * CLUTTER_ACTOR (self)); + * + * // internal child - a label + * self->priv->label = clutter_text_new (); + * clutter_actor_set_parent (self->priv->label, + * CLUTTER_ACTOR (self)); + * + * clutter_actor_pop_internal (CLUTTER_ACTOR (self)); + * + * // calling clutter_actor_set_parent() now will not result in + * // the internal flag being set on a child of MyActor + * } + * ]| + * + * This function will be used by Clutter to toggle an "internal child" + * flag whenever clutter_actor_set_parent() is called; internal children + * are handled differently by Clutter, specifically when destroying their + * parent. + * + * Call clutter_actor_pop_internal() when you finished adding internal + * children. + * + * Nested calls to clutter_actor_push_internal() are allowed, but each + * one must by followed by a clutter_actor_pop_internal() call. + * + * Since: 1.2 + * + * Deprecated: 1.10: All children of an actor are accessible through + * the #ClutterActor API, and #ClutterActor implements the + * #ClutterContainer interface, so this function is only useful + * for legacy containers overriding the default implementation. + */ +void +clutter_actor_push_internal (ClutterActor *self) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + self->priv->internal_child += 1; +} + +/** + * clutter_actor_pop_internal: + * @self: a #ClutterActor + * + * Disables the effects of clutter_actor_push_internal(). + * + * Since: 1.2 + * + * Deprecated: 1.10: All children of an actor are accessible through + * the #ClutterActor API. This function is only useful for legacy + * containers overriding the default implementation of the + * #ClutterContainer interface. + */ +void +clutter_actor_pop_internal (ClutterActor *self) +{ + ClutterActorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + priv = self->priv; + + if (priv->internal_child == 0) + { + g_warning ("Mismatched %s: you need to call " + "clutter_actor_push_composite() at least once before " + "calling this function", G_STRFUNC); + return; + } + + priv->internal_child -= 1; +} + +/** + * clutter_actor_has_pointer: + * @self: a #ClutterActor + * + * Checks whether an actor contains the pointer of a + * #ClutterInputDevice + * + * Return value: %TRUE if the actor contains the pointer, and + * %FALSE otherwise + * + * Since: 1.2 + */ +gboolean +clutter_actor_has_pointer (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); + + return self->priv->has_pointer; +} + +/* XXX: This is a workaround for not being able to break the ABI of + * the QUEUE_REDRAW signal. It is an out-of-band argument. See + * clutter_actor_queue_clipped_redraw() for details. + */ +ClutterPaintVolume * +_clutter_actor_get_queue_redraw_clip (ClutterActor *self) +{ + return g_object_get_data (G_OBJECT (self), + "-clutter-actor-queue-redraw-clip"); +} + +void +_clutter_actor_set_queue_redraw_clip (ClutterActor *self, + ClutterPaintVolume *clip) +{ + g_object_set_data (G_OBJECT (self), + "-clutter-actor-queue-redraw-clip", + clip); +} + +/** + * clutter_actor_has_allocation: + * @self: a #ClutterActor + * + * Checks if the actor has an up-to-date allocation assigned to + * it. This means that the actor should have an allocation: it's + * visible and has a parent. It also means that there is no + * outstanding relayout request in progress for the actor or its + * children (There might be other outstanding layout requests in + * progress that will cause the actor to get a new allocation + * when the stage is laid out, however). + * + * If this function returns %FALSE, then the actor will normally + * be allocated before it is next drawn on the screen. + * + * Return value: %TRUE if the actor has an up-to-date allocation + * + * Since: 1.4 + */ +gboolean +clutter_actor_has_allocation (ClutterActor *self) +{ + ClutterActorPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); + + priv = self->priv; + + return priv->parent != NULL && + CLUTTER_ACTOR_IS_VISIBLE (self) && + !priv->needs_allocation; +} + +/** + * clutter_actor_add_action: + * @self: a #ClutterActor + * @action: a #ClutterAction + * + * Adds @action to the list of actions applied to @self + * + * A #ClutterAction can only belong to one actor at a time + * + * The #ClutterActor will hold a reference on @action until either + * clutter_actor_remove_action() or clutter_actor_clear_actions() + * is called + * + * Since: 1.4 + */ +void +clutter_actor_add_action (ClutterActor *self, + ClutterAction *action) +{ + ClutterActorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (CLUTTER_IS_ACTION (action)); + + priv = self->priv; + + if (priv->actions == NULL) + { + priv->actions = g_object_new (CLUTTER_TYPE_META_GROUP, NULL); + priv->actions->actor = self; + } + + _clutter_meta_group_add_meta (priv->actions, CLUTTER_ACTOR_META (action)); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ACTIONS]); +} + +/** + * clutter_actor_add_action_with_name: + * @self: a #ClutterActor + * @name: the name to set on the action + * @action: a #ClutterAction + * + * A convenience function for setting the name of a #ClutterAction + * while adding it to the list of actions applied to @self + * + * This function is the logical equivalent of: + * + * |[ + * clutter_actor_meta_set_name (CLUTTER_ACTOR_META (action), name); + * clutter_actor_add_action (self, action); + * ]| + * + * Since: 1.4 + */ +void +clutter_actor_add_action_with_name (ClutterActor *self, + const gchar *name, + ClutterAction *action) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (name != NULL); + g_return_if_fail (CLUTTER_IS_ACTION (action)); + + clutter_actor_meta_set_name (CLUTTER_ACTOR_META (action), name); + clutter_actor_add_action (self, action); +} + +/** + * clutter_actor_remove_action: + * @self: a #ClutterActor + * @action: a #ClutterAction + * + * Removes @action from the list of actions applied to @self + * + * The reference held by @self on the #ClutterAction will be released + * + * Since: 1.4 + */ +void +clutter_actor_remove_action (ClutterActor *self, + ClutterAction *action) +{ + ClutterActorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (CLUTTER_IS_ACTION (action)); + + priv = self->priv; + + if (priv->actions == NULL) + return; + + _clutter_meta_group_remove_meta (priv->actions, CLUTTER_ACTOR_META (action)); + + if (_clutter_meta_group_peek_metas (priv->actions) == NULL) + g_clear_object (&priv->actions); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ACTIONS]); +} + +/** + * clutter_actor_remove_action_by_name: + * @self: a #ClutterActor + * @name: the name of the action to remove + * + * Removes the #ClutterAction with the given name from the list + * of actions applied to @self + * + * Since: 1.4 + */ +void +clutter_actor_remove_action_by_name (ClutterActor *self, + const gchar *name) +{ + ClutterActorPrivate *priv; + ClutterActorMeta *meta; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (name != NULL); + + priv = self->priv; + + if (priv->actions == NULL) + return; + + meta = _clutter_meta_group_get_meta (priv->actions, name); + if (meta == NULL) + return; + + _clutter_meta_group_remove_meta (priv->actions, meta); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ACTIONS]); +} + +/** + * clutter_actor_get_actions: + * @self: a #ClutterActor + * + * Retrieves the list of actions applied to @self + * + * Return value: (transfer container) (element-type Clutter.Action): a copy + * of the list of #ClutterActions. The contents of the list are + * owned by the #ClutterActor. Use g_list_free() to free the resources + * allocated by the returned #GList + * + * Since: 1.4 + */ +GList * +clutter_actor_get_actions (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + + if (self->priv->actions == NULL) + return NULL; + + return _clutter_meta_group_get_metas_no_internal (self->priv->actions); +} + +/** + * clutter_actor_get_action: + * @self: a #ClutterActor + * @name: the name of the action to retrieve + * + * Retrieves the #ClutterAction with the given name in the list + * of actions applied to @self + * + * Return value: (transfer none): a #ClutterAction for the given + * name, or %NULL. The returned #ClutterAction is owned by the + * actor and it should not be unreferenced directly + * + * Since: 1.4 + */ +ClutterAction * +clutter_actor_get_action (ClutterActor *self, + const gchar *name) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + g_return_val_if_fail (name != NULL, NULL); + + if (self->priv->actions == NULL) + return NULL; + + return CLUTTER_ACTION (_clutter_meta_group_get_meta (self->priv->actions, name)); +} + +/** + * clutter_actor_clear_actions: + * @self: a #ClutterActor + * + * Clears the list of actions applied to @self + * + * Since: 1.4 + */ +void +clutter_actor_clear_actions (ClutterActor *self) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + if (self->priv->actions == NULL) + return; + + _clutter_meta_group_clear_metas_no_internal (self->priv->actions); +} + +/** + * clutter_actor_add_constraint: + * @self: a #ClutterActor + * @constraint: a #ClutterConstraint + * + * Adds @constraint to the list of #ClutterConstraints applied + * to @self + * + * The #ClutterActor will hold a reference on the @constraint until + * either clutter_actor_remove_constraint() or + * clutter_actor_clear_constraints() is called. + * + * Since: 1.4 + */ +void +clutter_actor_add_constraint (ClutterActor *self, + ClutterConstraint *constraint) +{ + ClutterActorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (CLUTTER_IS_CONSTRAINT (constraint)); + + priv = self->priv; + + if (priv->constraints == NULL) + { + priv->constraints = g_object_new (CLUTTER_TYPE_META_GROUP, NULL); + priv->constraints->actor = self; + } + + _clutter_meta_group_add_meta (priv->constraints, + CLUTTER_ACTOR_META (constraint)); + clutter_actor_queue_relayout (self); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_CONSTRAINTS]); +} + +/** + * clutter_actor_add_constraint_with_name: + * @self: a #ClutterActor + * @name: the name to set on the constraint + * @constraint: a #ClutterConstraint + * + * A convenience function for setting the name of a #ClutterConstraint + * while adding it to the list of constraints applied to @self + * + * This function is the logical equivalent of: + * + * |[ + * clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), name); + * clutter_actor_add_constraint (self, constraint); + * ]| + * + * Since: 1.4 + */ +void +clutter_actor_add_constraint_with_name (ClutterActor *self, + const gchar *name, + ClutterConstraint *constraint) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (name != NULL); + g_return_if_fail (CLUTTER_IS_CONSTRAINT (constraint)); + + clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), name); + clutter_actor_add_constraint (self, constraint); +} + +/** + * clutter_actor_remove_constraint: + * @self: a #ClutterActor + * @constraint: a #ClutterConstraint + * + * Removes @constraint from the list of constraints applied to @self + * + * The reference held by @self on the #ClutterConstraint will be released + * + * Since: 1.4 + */ +void +clutter_actor_remove_constraint (ClutterActor *self, + ClutterConstraint *constraint) +{ + ClutterActorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (CLUTTER_IS_CONSTRAINT (constraint)); + + priv = self->priv; + + if (priv->constraints == NULL) + return; + + _clutter_meta_group_remove_meta (priv->constraints, + CLUTTER_ACTOR_META (constraint)); + + if (_clutter_meta_group_peek_metas (priv->constraints) == NULL) + g_clear_object (&priv->constraints); + + clutter_actor_queue_relayout (self); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_CONSTRAINTS]); +} + +/** + * clutter_actor_remove_constraint_by_name: + * @self: a #ClutterActor + * @name: the name of the constraint to remove + * + * Removes the #ClutterConstraint with the given name from the list + * of constraints applied to @self + * + * Since: 1.4 + */ +void +clutter_actor_remove_constraint_by_name (ClutterActor *self, + const gchar *name) +{ + ClutterActorPrivate *priv; + ClutterActorMeta *meta; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (name != NULL); + + priv = self->priv; + + if (priv->constraints == NULL) + return; + + meta = _clutter_meta_group_get_meta (priv->constraints, name); + if (meta == NULL) + return; + + _clutter_meta_group_remove_meta (priv->constraints, meta); + clutter_actor_queue_relayout (self); +} + +/** + * clutter_actor_get_constraints: + * @self: a #ClutterActor + * + * Retrieves the list of constraints applied to @self + * + * Return value: (transfer container) (element-type Clutter.Constraint): a copy + * of the list of #ClutterConstraints. The contents of the list are + * owned by the #ClutterActor. Use g_list_free() to free the resources + * allocated by the returned #GList + * + * Since: 1.4 + */ +GList * +clutter_actor_get_constraints (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + + if (self->priv->constraints == NULL) + return NULL; + + return _clutter_meta_group_get_metas_no_internal (self->priv->constraints); +} + +/** + * clutter_actor_get_constraint: + * @self: a #ClutterActor + * @name: the name of the constraint to retrieve + * + * Retrieves the #ClutterConstraint with the given name in the list + * of constraints applied to @self + * + * Return value: (transfer none): a #ClutterConstraint for the given + * name, or %NULL. The returned #ClutterConstraint is owned by the + * actor and it should not be unreferenced directly + * + * Since: 1.4 + */ +ClutterConstraint * +clutter_actor_get_constraint (ClutterActor *self, + const gchar *name) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + g_return_val_if_fail (name != NULL, NULL); + + if (self->priv->constraints == NULL) + return NULL; + + return CLUTTER_CONSTRAINT (_clutter_meta_group_get_meta (self->priv->constraints, name)); +} + +/** + * clutter_actor_clear_constraints: + * @self: a #ClutterActor + * + * Clears the list of constraints applied to @self + * + * Since: 1.4 + */ +void +clutter_actor_clear_constraints (ClutterActor *self) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + if (self->priv->constraints == NULL) + return; + + _clutter_meta_group_clear_metas_no_internal (self->priv->constraints); + + clutter_actor_queue_relayout (self); +} + +/** + * clutter_actor_set_clip_to_allocation: + * @self: a #ClutterActor + * @clip_set: %TRUE to apply a clip tracking the allocation + * + * Sets whether @self should be clipped to the same size as its + * allocation + * + * Since: 1.4 + */ +void +clutter_actor_set_clip_to_allocation (ClutterActor *self, + gboolean clip_set) +{ + ClutterActorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + clip_set = !!clip_set; + + priv = self->priv; + + if (priv->clip_to_allocation != clip_set) + { + priv->clip_to_allocation = clip_set; + + clutter_actor_queue_redraw (self); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_CLIP_TO_ALLOCATION]); + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_HAS_CLIP]); + } +} + +/** + * clutter_actor_get_clip_to_allocation: + * @self: a #ClutterActor + * + * Retrieves the value set using clutter_actor_set_clip_to_allocation() + * + * Return value: %TRUE if the #ClutterActor is clipped to its allocation + * + * Since: 1.4 + */ +gboolean +clutter_actor_get_clip_to_allocation (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); + + return self->priv->clip_to_allocation; +} + +/** + * clutter_actor_add_effect: + * @self: a #ClutterActor + * @effect: a #ClutterEffect + * + * Adds @effect to the list of #ClutterEffects applied to @self + * + * The #ClutterActor will hold a reference on the @effect until either + * clutter_actor_remove_effect() or clutter_actor_clear_effects() is + * called. + * + * Since: 1.4 + */ +void +clutter_actor_add_effect (ClutterActor *self, + ClutterEffect *effect) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (CLUTTER_IS_EFFECT (effect)); + + _clutter_actor_add_effect_internal (self, effect); + + clutter_actor_queue_redraw (self); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_EFFECT]); +} + +/** + * clutter_actor_add_effect_with_name: + * @self: a #ClutterActor + * @name: the name to set on the effect + * @effect: a #ClutterEffect + * + * A convenience function for setting the name of a #ClutterEffect + * while adding it to the list of effectss applied to @self + * + * This function is the logical equivalent of: + * + * |[ + * clutter_actor_meta_set_name (CLUTTER_ACTOR_META (effect), name); + * clutter_actor_add_effect (self, effect); + * ]| + * + * Since: 1.4 + */ +void +clutter_actor_add_effect_with_name (ClutterActor *self, + const gchar *name, + ClutterEffect *effect) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (name != NULL); + g_return_if_fail (CLUTTER_IS_EFFECT (effect)); + + clutter_actor_meta_set_name (CLUTTER_ACTOR_META (effect), name); + clutter_actor_add_effect (self, effect); +} + +/** + * clutter_actor_remove_effect: + * @self: a #ClutterActor + * @effect: a #ClutterEffect + * + * Removes @effect from the list of effects applied to @self + * + * The reference held by @self on the #ClutterEffect will be released + * + * Since: 1.4 + */ +void +clutter_actor_remove_effect (ClutterActor *self, + ClutterEffect *effect) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (CLUTTER_IS_EFFECT (effect)); + + _clutter_actor_remove_effect_internal (self, effect); + + clutter_actor_queue_redraw (self); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_EFFECT]); +} + +/** + * clutter_actor_remove_effect_by_name: + * @self: a #ClutterActor + * @name: the name of the effect to remove + * + * Removes the #ClutterEffect with the given name from the list + * of effects applied to @self + * + * Since: 1.4 + */ +void +clutter_actor_remove_effect_by_name (ClutterActor *self, + const gchar *name) +{ + ClutterActorPrivate *priv; + ClutterActorMeta *meta; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (name != NULL); + + priv = self->priv; + + if (priv->effects == NULL) + return; + + meta = _clutter_meta_group_get_meta (priv->effects, name); + if (meta == NULL) + return; + + clutter_actor_remove_effect (self, CLUTTER_EFFECT (meta)); +} + +/** + * clutter_actor_get_effects: + * @self: a #ClutterActor + * + * Retrieves the #ClutterEffects applied on @self, if any + * + * Return value: (transfer container) (element-type Clutter.Effect): a list + * of #ClutterEffects, or %NULL. The elements of the returned + * list are owned by Clutter and they should not be freed. You should + * free the returned list using g_list_free() when done + * + * Since: 1.4 + */ +GList * +clutter_actor_get_effects (ClutterActor *self) +{ + ClutterActorPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + + priv = self->priv; + + if (priv->effects == NULL) + return NULL; + + return _clutter_meta_group_get_metas_no_internal (priv->effects); +} + +/** + * clutter_actor_get_effect: + * @self: a #ClutterActor + * @name: the name of the effect to retrieve + * + * Retrieves the #ClutterEffect with the given name in the list + * of effects applied to @self + * + * Return value: (transfer none): a #ClutterEffect for the given + * name, or %NULL. The returned #ClutterEffect is owned by the + * actor and it should not be unreferenced directly + * + * Since: 1.4 + */ +ClutterEffect * +clutter_actor_get_effect (ClutterActor *self, + const gchar *name) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + g_return_val_if_fail (name != NULL, NULL); + + if (self->priv->effects == NULL) + return NULL; + + return CLUTTER_EFFECT (_clutter_meta_group_get_meta (self->priv->effects, name)); +} + +/** + * clutter_actor_clear_effects: + * @self: a #ClutterActor + * + * Clears the list of effects applied to @self + * + * Since: 1.4 + */ +void +clutter_actor_clear_effects (ClutterActor *self) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + if (self->priv->effects == NULL) + return; + + _clutter_meta_group_clear_metas_no_internal (self->priv->effects); + + clutter_actor_queue_redraw (self); +} + +/** + * clutter_actor_has_key_focus: + * @self: a #ClutterActor + * + * Checks whether @self is the #ClutterActor that has key focus + * + * Return value: %TRUE if the actor has key focus, and %FALSE otherwise + * + * Since: 1.4 + */ +gboolean +clutter_actor_has_key_focus (ClutterActor *self) +{ + ClutterActor *stage; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); + + stage = _clutter_actor_get_stage_internal (self); + if (stage == NULL) + return FALSE; + + return clutter_stage_get_key_focus (CLUTTER_STAGE (stage)) == self; +} + +static gboolean +_clutter_actor_get_paint_volume_real (ClutterActor *self, + ClutterPaintVolume *pv) +{ + ClutterActorPrivate *priv = self->priv; + + /* Actors are only expected to report a valid paint volume + * while they have a valid allocation. */ + if (G_UNLIKELY (priv->needs_allocation)) + { + CLUTTER_NOTE (CLIPPING, "Bail from get_paint_volume (%s): " + "Actor needs allocation", + _clutter_actor_get_debug_name (self)); + return FALSE; + } + + /* Check if there are any handlers connected to the paint + * signal. If there are then all bets are off for what the paint + * volume for this actor might possibly be! + * + * XXX: It's expected that this is going to end up being quite a + * costly check to have to do here, but we haven't come up with + * another solution that can reliably catch paint signal handlers at + * the right time to either avoid artefacts due to invalid stage + * clipping or due to incorrect culling. + * + * Previously we checked in clutter_actor_paint(), but at that time + * we may already be using a stage clip that could be derived from + * an invalid paint-volume. We used to try and handle that by + * queuing a follow up, unclipped, redraw but still the previous + * checking wasn't enough to catch invalid volumes involved in + * culling (considering that containers may derive their volume from + * children that haven't yet been painted) + * + * Longer term, improved solutions could be: + * - Disallow painting in the paint signal, only allow using it + * for tracking when paints happen. We can add another API that + * allows monkey patching the paint of arbitrary actors but in a + * more controlled way and that also supports modifying the + * paint-volume. + * - If we could be notified somehow when signal handlers are + * connected we wouldn't have to poll for handlers like this. + * + * XXX:2.0 - Remove when we remove the paint signal + */ + if (g_signal_has_handler_pending (self, + actor_signals[PAINT], + 0, + TRUE)) + { + CLUTTER_NOTE (CLIPPING, "Bail from get_paint_volume (%s): " + "Actor has \"paint\" signal handlers", + _clutter_actor_get_debug_name (self)); + return FALSE; + } + + _clutter_paint_volume_init_static (pv, self); + + if (!CLUTTER_ACTOR_GET_CLASS (self)->get_paint_volume (self, pv)) + { + clutter_paint_volume_free (pv); + CLUTTER_NOTE (CLIPPING, "Bail from get_paint_volume (%s): " + "Actor failed to report a volume", + _clutter_actor_get_debug_name (self)); + return FALSE; + } + + /* since effects can modify the paint volume, we allow them to actually + * do this by making get_paint_volume() "context sensitive" + */ + if (priv->effects != NULL) + { + if (priv->current_effect != NULL) + { + const GList *effects, *l; + + /* if we are being called from within the paint sequence of + * an actor, get the paint volume up to the current effect + */ + effects = _clutter_meta_group_peek_metas (priv->effects); + for (l = effects; + l != NULL || (l != NULL && l->data != priv->current_effect); + l = l->next) + { + if (!_clutter_effect_get_paint_volume (l->data, pv)) + { + clutter_paint_volume_free (pv); + CLUTTER_NOTE (CLIPPING, "Bail from get_paint_volume (%s): " + "Effect (%s) failed to report a volume", + _clutter_actor_get_debug_name (self), + _clutter_actor_meta_get_debug_name (l->data)); + return FALSE; + } + } + } + else + { + const GList *effects, *l; + + /* otherwise, get the cumulative volume */ + effects = _clutter_meta_group_peek_metas (priv->effects); + for (l = effects; l != NULL; l = l->next) + if (!_clutter_effect_get_paint_volume (l->data, pv)) + { + clutter_paint_volume_free (pv); + CLUTTER_NOTE (CLIPPING, "Bail from get_paint_volume (%s): " + "Effect (%s) failed to report a volume", + _clutter_actor_get_debug_name (self), + _clutter_actor_meta_get_debug_name (l->data)); + return FALSE; + } + } + } + + return TRUE; +} + +/* The public clutter_actor_get_paint_volume API returns a const + * pointer since we return a pointer directly to the cached + * PaintVolume associated with the actor and don't want the user to + * inadvertently modify it, but for internal uses we sometimes need + * access to the same PaintVolume but need to apply some book-keeping + * modifications to it so we don't want a const pointer. + */ +static ClutterPaintVolume * +_clutter_actor_get_paint_volume_mutable (ClutterActor *self) +{ + ClutterActorPrivate *priv; + + priv = self->priv; + + if (priv->paint_volume_valid) + clutter_paint_volume_free (&priv->paint_volume); + + if (_clutter_actor_get_paint_volume_real (self, &priv->paint_volume)) + { + priv->paint_volume_valid = TRUE; + return &priv->paint_volume; + } + else + { + priv->paint_volume_valid = FALSE; + return NULL; + } +} + +/** + * clutter_actor_get_paint_volume: + * @self: a #ClutterActor + * + * Retrieves the paint volume of the passed #ClutterActor, or %NULL + * when a paint volume can't be determined. + * + * The paint volume is defined as the 3D space occupied by an actor + * when being painted. + * + * This function will call the #ClutterActorClass.get_paint_volume() + * virtual function of the #ClutterActor class. Sub-classes of #ClutterActor + * should not usually care about overriding the default implementation, + * unless they are, for instance: painting outside their allocation, or + * actors with a depth factor (not in terms of #ClutterActor:depth but real + * 3D depth). + * + * Note: 2D actors overriding #ClutterActorClass.get_paint_volume() + * should ensure that their volume has a depth of 0. (This will be true + * as long as you don't call clutter_paint_volume_set_depth().) + * + * Return value: (transfer none): a pointer to a #ClutterPaintVolume, + * or %NULL if no volume could be determined. The returned pointer + * is not guaranteed to be valid across multiple frames; if you want + * to keep it, you will need to copy it using clutter_paint_volume_copy(). + * + * Since: 1.6 + */ +const ClutterPaintVolume * +clutter_actor_get_paint_volume (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + + return _clutter_actor_get_paint_volume_mutable (self); +} + +/** + * clutter_actor_get_transformed_paint_volume: + * @self: a #ClutterActor + * @relative_to_ancestor: A #ClutterActor that is an ancestor of @self + * (or %NULL for the stage) + * + * Retrieves the 3D paint volume of an actor like + * clutter_actor_get_paint_volume() does (Please refer to the + * documentation of clutter_actor_get_paint_volume() for more + * details.) and it additionally transforms the paint volume into the + * coordinate space of @relative_to_ancestor. (Or the stage if %NULL + * is passed for @relative_to_ancestor) + * + * This can be used by containers that base their paint volume on + * the volume of their children. Such containers can query the + * transformed paint volume of all of its children and union them + * together using clutter_paint_volume_union(). + * + * Return value: (transfer none): a pointer to a #ClutterPaintVolume, + * or %NULL if no volume could be determined. The returned pointer is + * not guaranteed to be valid across multiple frames; if you wish to + * keep it, you will have to copy it using clutter_paint_volume_copy(). + * + * Since: 1.6 + */ +const ClutterPaintVolume * +clutter_actor_get_transformed_paint_volume (ClutterActor *self, + ClutterActor *relative_to_ancestor) +{ + const ClutterPaintVolume *volume; + ClutterActor *stage; + ClutterPaintVolume *transformed_volume; + + stage = _clutter_actor_get_stage_internal (self); + if (G_UNLIKELY (stage == NULL)) + return NULL; + + if (relative_to_ancestor == NULL) + relative_to_ancestor = stage; + + volume = clutter_actor_get_paint_volume (self); + if (volume == NULL) + return NULL; + + transformed_volume = + _clutter_stage_paint_volume_stack_allocate (CLUTTER_STAGE (stage)); + + _clutter_paint_volume_copy_static (volume, transformed_volume); + + _clutter_paint_volume_transform_relative (transformed_volume, + relative_to_ancestor); + + return transformed_volume; +} + +/** + * clutter_actor_get_paint_box: + * @self: a #ClutterActor + * @box: (out): return location for a #ClutterActorBox + * + * Retrieves the paint volume of the passed #ClutterActor, and + * transforms it into a 2D bounding box in stage coordinates. + * + * This function is useful to determine the on screen area occupied by + * the actor. The box is only an approximation and may often be + * considerably larger due to the optimizations used to calculate the + * box. The box is never smaller though, so it can reliably be used + * for culling. + * + * There are times when a 2D paint box can't be determined, e.g. + * because the actor isn't yet parented under a stage or because + * the actor is unable to determine a paint volume. + * + * Return value: %TRUE if a 2D paint box could be determined, else + * %FALSE. + * + * Since: 1.6 + */ +gboolean +clutter_actor_get_paint_box (ClutterActor *self, + ClutterActorBox *box) +{ + ClutterActor *stage; + ClutterPaintVolume *pv; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); + g_return_val_if_fail (box != NULL, FALSE); + + stage = _clutter_actor_get_stage_internal (self); + if (G_UNLIKELY (!stage)) + return FALSE; + + pv = _clutter_actor_get_paint_volume_mutable (self); + if (G_UNLIKELY (!pv)) + return FALSE; + + _clutter_paint_volume_get_stage_paint_box (pv, CLUTTER_STAGE (stage), box); + + return TRUE; +} + +/** + * clutter_actor_has_overlaps: + * @self: A #ClutterActor + * + * Asks the actor's implementation whether it may contain overlapping + * primitives. + * + * For example; Clutter may use this to determine whether the painting + * should be redirected to an offscreen buffer to correctly implement + * the opacity property. + * + * Custom actors can override the default response by implementing the + * #ClutterActorClass.has_overlaps() virtual function. See + * clutter_actor_set_offscreen_redirect() for more information. + * + * Return value: %TRUE if the actor may have overlapping primitives, and + * %FALSE otherwise + * + * Since: 1.8 + */ +gboolean +clutter_actor_has_overlaps (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), TRUE); + + return CLUTTER_ACTOR_GET_CLASS (self)->has_overlaps (self); +} + +/** + * clutter_actor_has_effects: + * @self: A #ClutterActor + * + * Returns whether the actor has any effects applied. + * + * Return value: %TRUE if the actor has any effects, + * %FALSE otherwise + * + * Since: 1.10 + */ +gboolean +clutter_actor_has_effects (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); + + if (self->priv->effects == NULL) + return FALSE; + + return _clutter_meta_group_has_metas_no_internal (self->priv->effects); +} + +/** + * clutter_actor_has_constraints: + * @self: A #ClutterActor + * + * Returns whether the actor has any constraints applied. + * + * Return value: %TRUE if the actor has any constraints, + * %FALSE otherwise + * + * Since: 1.10 + */ +gboolean +clutter_actor_has_constraints (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); + + if (self->priv->constraints == NULL) + return FALSE; + + return _clutter_meta_group_has_metas_no_internal (self->priv->constraints); +} + +/** + * clutter_actor_has_actions: + * @self: A #ClutterActor + * + * Returns whether the actor has any actions applied. + * + * Return value: %TRUE if the actor has any actions, + * %FALSE otherwise + * + * Since: 1.10 + */ +gboolean +clutter_actor_has_actions (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); + + if (self->priv->actions == NULL) + return FALSE; + + return _clutter_meta_group_has_metas_no_internal (self->priv->actions); +} + +/** + * clutter_actor_get_n_children: + * @self: a #ClutterActor + * + * Retrieves the number of children of @self. + * + * Return value: the number of children of an actor + * + * Since: 1.10 + */ +gint +clutter_actor_get_n_children (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0); + + return self->priv->n_children; +} + +/** + * clutter_actor_get_child_at_index: + * @self: a #ClutterActor + * @index_: the position in the list of children + * + * Retrieves the actor at the given @index_ inside the list of + * children of @self. + * + * Return value: (transfer none): a pointer to a #ClutterActor, or %NULL + * + * Since: 1.10 + */ +ClutterActor * +clutter_actor_get_child_at_index (ClutterActor *self, + gint index_) +{ + ClutterActor *iter; + int i; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + g_return_val_if_fail (index_ <= self->priv->n_children, NULL); + + for (iter = self->priv->first_child, i = 0; + iter != NULL && i < index_; + iter = iter->priv->next_sibling, i += 1) + ; + + return iter; +} + +/*< private > + * _clutter_actor_foreach_child: + * @actor: The actor whos children you want to iterate + * @callback: The function to call for each child + * @user_data: Private data to pass to @callback + * + * Calls a given @callback once for each child of the specified @actor and + * passing the @user_data pointer each time. + * + * Return value: returns %TRUE if all children were iterated, else + * %FALSE if a callback broke out of iteration early. + */ +gboolean +_clutter_actor_foreach_child (ClutterActor *self, + ClutterForeachCallback callback, + gpointer user_data) +{ + ClutterActor *iter; + gboolean cont; + + if (self->priv->first_child == NULL) + return TRUE; + + cont = TRUE; + iter = self->priv->first_child; + + /* we use this form so that it's safe to change the children + * list while iterating it + */ + while (cont && iter != NULL) + { + ClutterActor *next = iter->priv->next_sibling; + + cont = callback (iter, user_data); + + iter = next; + } + + return cont; +} + +#if 0 +/* For debugging purposes this gives us a simple way to print out + * the scenegraph e.g in gdb using: + * [| + * _clutter_actor_traverse (stage, + * 0, + * clutter_debug_print_actor_cb, + * NULL, + * NULL); + * |] + */ +static ClutterActorTraverseVisitFlags +clutter_debug_print_actor_cb (ClutterActor *actor, + int depth, + void *user_data) +{ + g_print ("%*s%s:%p\n", + depth * 2, "", + _clutter_actor_get_debug_name (actor), + actor); + + return CLUTTER_ACTOR_TRAVERSE_VISIT_CONTINUE; +} +#endif + +static void +_clutter_actor_traverse_breadth (ClutterActor *actor, + ClutterTraverseCallback callback, + gpointer user_data) +{ + GQueue *queue = g_queue_new (); + ClutterActor dummy; + int current_depth = 0; + + g_queue_push_tail (queue, actor); + g_queue_push_tail (queue, &dummy); /* use to delimit depth changes */ + + while ((actor = g_queue_pop_head (queue))) + { + ClutterActorTraverseVisitFlags flags; + + if (actor == &dummy) + { + current_depth++; + g_queue_push_tail (queue, &dummy); + continue; + } + + flags = callback (actor, current_depth, user_data); + if (flags & CLUTTER_ACTOR_TRAVERSE_VISIT_BREAK) + break; + else if (!(flags & CLUTTER_ACTOR_TRAVERSE_VISIT_SKIP_CHILDREN)) + { + ClutterActor *iter; + + for (iter = actor->priv->first_child; + iter != NULL; + iter = iter->priv->next_sibling) + { + g_queue_push_tail (queue, iter); + } + } + } + + g_queue_free (queue); +} + +static ClutterActorTraverseVisitFlags +_clutter_actor_traverse_depth (ClutterActor *actor, + ClutterTraverseCallback before_children_callback, + ClutterTraverseCallback after_children_callback, + int current_depth, + gpointer user_data) +{ + ClutterActorTraverseVisitFlags flags; + + flags = before_children_callback (actor, current_depth, user_data); + if (flags & CLUTTER_ACTOR_TRAVERSE_VISIT_BREAK) + return CLUTTER_ACTOR_TRAVERSE_VISIT_BREAK; + + if (!(flags & CLUTTER_ACTOR_TRAVERSE_VISIT_SKIP_CHILDREN)) + { + ClutterActor *iter; + + for (iter = actor->priv->first_child; + iter != NULL; + iter = iter->priv->next_sibling) + { + flags = _clutter_actor_traverse_depth (iter, + before_children_callback, + after_children_callback, + current_depth + 1, + user_data); + + if (flags & CLUTTER_ACTOR_TRAVERSE_VISIT_BREAK) + return CLUTTER_ACTOR_TRAVERSE_VISIT_BREAK; + } + } + + if (after_children_callback) + return after_children_callback (actor, current_depth, user_data); + else + return CLUTTER_ACTOR_TRAVERSE_VISIT_CONTINUE; +} + +/* _clutter_actor_traverse: + * @actor: The actor to start traversing the graph from + * @flags: These flags may affect how the traversal is done + * @before_children_callback: A function to call before visiting the + * children of the current actor. + * @after_children_callback: A function to call after visiting the + * children of the current actor. (Ignored if + * %CLUTTER_ACTOR_TRAVERSE_BREADTH_FIRST is passed to @flags.) + * @user_data: The private data to pass to the callbacks + * + * Traverses the scenegraph starting at the specified @actor and + * descending through all its children and its children's children. + * For each actor traversed @before_children_callback and + * @after_children_callback are called with the specified + * @user_data, before and after visiting that actor's children. + * + * The callbacks can return flags that affect the ongoing traversal + * such as by skipping over an actors children or bailing out of + * any further traversing. + */ +void +_clutter_actor_traverse (ClutterActor *actor, + ClutterActorTraverseFlags flags, + ClutterTraverseCallback before_children_callback, + ClutterTraverseCallback after_children_callback, + gpointer user_data) +{ + if (flags & CLUTTER_ACTOR_TRAVERSE_BREADTH_FIRST) + _clutter_actor_traverse_breadth (actor, + before_children_callback, + user_data); + else /* DEPTH_FIRST */ + _clutter_actor_traverse_depth (actor, + before_children_callback, + after_children_callback, + 0, /* start depth */ + user_data); +} + +static void +on_layout_manager_changed (ClutterLayoutManager *manager, + ClutterActor *self) +{ + clutter_actor_queue_relayout (self); +} + +/** + * clutter_actor_set_layout_manager: + * @self: a #ClutterActor + * @manager: (allow-none): a #ClutterLayoutManager, or %NULL to unset it + * + * Sets the #ClutterLayoutManager delegate object that will be used to + * lay out the children of @self. + * + * The #ClutterActor will take a reference on the passed @manager which + * will be released either when the layout manager is removed, or when + * the actor is destroyed. + * + * Since: 1.10 + */ +void +clutter_actor_set_layout_manager (ClutterActor *self, + ClutterLayoutManager *manager) +{ + ClutterActorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (manager == NULL || CLUTTER_IS_LAYOUT_MANAGER (manager)); + + priv = self->priv; + + if (priv->layout_manager != NULL) + { + g_signal_handlers_disconnect_by_func (priv->layout_manager, + G_CALLBACK (on_layout_manager_changed), + self); + clutter_layout_manager_set_container (priv->layout_manager, NULL); + g_clear_object (&priv->layout_manager); + } + + priv->layout_manager = manager; + + if (priv->layout_manager != NULL) + { + g_object_ref_sink (priv->layout_manager); + clutter_layout_manager_set_container (priv->layout_manager, + CLUTTER_CONTAINER (self)); + g_signal_connect (priv->layout_manager, "layout-changed", + G_CALLBACK (on_layout_manager_changed), + self); + } + + clutter_actor_queue_relayout (self); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_LAYOUT_MANAGER]); +} + +/** + * clutter_actor_get_layout_manager: + * @self: a #ClutterActor + * + * Retrieves the #ClutterLayoutManager used by @self. + * + * Return value: (transfer none): a pointer to the #ClutterLayoutManager, + * or %NULL + * + * Since: 1.10 + */ +ClutterLayoutManager * +clutter_actor_get_layout_manager (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + + return self->priv->layout_manager; +} + +static const ClutterLayoutInfo default_layout_info = { + CLUTTER_POINT_INIT_ZERO, /* fixed-pos */ + { 0, 0, 0, 0 }, /* margin */ + CLUTTER_ACTOR_ALIGN_FILL, /* x-align */ + CLUTTER_ACTOR_ALIGN_FILL, /* y-align */ + FALSE, FALSE, /* expand */ + CLUTTER_SIZE_INIT_ZERO, /* minimum */ + CLUTTER_SIZE_INIT_ZERO, /* natural */ +}; + +static void +layout_info_free (gpointer data) +{ + if (G_LIKELY (data != NULL)) + g_slice_free (ClutterLayoutInfo, data); +} + +/*< private > + * _clutter_actor_peek_layout_info: + * @self: a #ClutterActor + * + * Retrieves a pointer to the ClutterLayoutInfo structure. + * + * If the actor does not have a ClutterLayoutInfo associated to it, %NULL is returned. + * + * Return value: (transfer none): a pointer to the ClutterLayoutInfo structure + */ +ClutterLayoutInfo * +_clutter_actor_peek_layout_info (ClutterActor *self) +{ + return g_object_get_qdata (G_OBJECT (self), quark_actor_layout_info); +} + +/*< private > + * _clutter_actor_get_layout_info: + * @self: a #ClutterActor + * + * Retrieves a pointer to the ClutterLayoutInfo structure. + * + * If the actor does not have a ClutterLayoutInfo associated to it, one + * will be created and initialized to the default values. + * + * This function should be used for setters. + * + * For getters, you should use _clutter_actor_get_layout_info_or_defaults() + * instead. + * + * Return value: (transfer none): a pointer to the ClutterLayoutInfo structure + */ +ClutterLayoutInfo * +_clutter_actor_get_layout_info (ClutterActor *self) +{ + ClutterLayoutInfo *retval; + + retval = _clutter_actor_peek_layout_info (self); + if (retval == NULL) + { + retval = g_slice_new (ClutterLayoutInfo); + + *retval = default_layout_info; + + g_object_set_qdata_full (G_OBJECT (self), quark_actor_layout_info, + retval, + layout_info_free); + } + + return retval; +} + +/*< private > + * _clutter_actor_get_layout_info_or_defaults: + * @self: a #ClutterActor + * + * Retrieves the ClutterLayoutInfo structure associated to an actor. + * + * If the actor does not have a ClutterLayoutInfo structure associated to it, + * then the default structure will be returned. + * + * This function should only be used for getters. + * + * Return value: a const pointer to the ClutterLayoutInfo structure + */ +const ClutterLayoutInfo * +_clutter_actor_get_layout_info_or_defaults (ClutterActor *self) +{ + const ClutterLayoutInfo *info; + + info = _clutter_actor_peek_layout_info (self); + if (info == NULL) + return &default_layout_info; + + return info; +} + +/** + * clutter_actor_set_x_align: + * @self: a #ClutterActor + * @x_align: the horizontal alignment policy + * + * Sets the horizontal alignment policy of a #ClutterActor, in case the + * actor received extra horizontal space. + * + * See also the #ClutterActor:x-align property. + * + * Since: 1.10 + */ +void +clutter_actor_set_x_align (ClutterActor *self, + ClutterActorAlign x_align) +{ + ClutterLayoutInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + info = _clutter_actor_get_layout_info (self); + + if (info->x_align != x_align) + { + info->x_align = x_align; + + clutter_actor_queue_relayout (self); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_X_ALIGN]); + } +} + +/** + * clutter_actor_get_x_align: + * @self: a #ClutterActor + * + * Retrieves the horizontal alignment policy set using + * clutter_actor_set_x_align(). + * + * Return value: the horizontal alignment policy. + * + * Since: 1.10 + */ +ClutterActorAlign +clutter_actor_get_x_align (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), CLUTTER_ACTOR_ALIGN_FILL); + + return _clutter_actor_get_layout_info_or_defaults (self)->x_align; +} + +/** + * clutter_actor_set_y_align: + * @self: a #ClutterActor + * @y_align: the vertical alignment policy + * + * Sets the vertical alignment policy of a #ClutterActor, in case the + * actor received extra vertical space. + * + * See also the #ClutterActor:y-align property. + * + * Since: 1.10 + */ +void +clutter_actor_set_y_align (ClutterActor *self, + ClutterActorAlign y_align) +{ + ClutterLayoutInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + info = _clutter_actor_get_layout_info (self); + + if (info->y_align != y_align) + { + info->y_align = y_align; + + clutter_actor_queue_relayout (self); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_Y_ALIGN]); + } +} + +/** + * clutter_actor_get_y_align: + * @self: a #ClutterActor + * + * Retrieves the vertical alignment policy set using + * clutter_actor_set_y_align(). + * + * Return value: the vertical alignment policy. + * + * Since: 1.10 + */ +ClutterActorAlign +clutter_actor_get_y_align (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), CLUTTER_ACTOR_ALIGN_FILL); + + return _clutter_actor_get_layout_info_or_defaults (self)->y_align; +} + +static inline void +clutter_actor_set_margin_internal (ClutterActor *self, + gfloat margin, + GParamSpec *pspec) +{ + ClutterLayoutInfo *info; + + info = _clutter_actor_get_layout_info (self); + + if (pspec == obj_props[PROP_MARGIN_TOP]) + info->margin.top = margin; + else if (pspec == obj_props[PROP_MARGIN_RIGHT]) + info->margin.right = margin; + else if (pspec == obj_props[PROP_MARGIN_BOTTOM]) + info->margin.bottom = margin; + else + info->margin.left = margin; + + clutter_actor_queue_relayout (self); + g_object_notify_by_pspec (G_OBJECT (self), pspec); +} + +/** + * clutter_actor_set_margin: + * @self: a #ClutterActor + * @margin: a #ClutterMargin + * + * Sets all the components of the margin of a #ClutterActor. + * + * Since: 1.10 + */ +void +clutter_actor_set_margin (ClutterActor *self, + const ClutterMargin *margin) +{ + ClutterLayoutInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (margin != NULL); + + info = _clutter_actor_get_layout_info (self); + + if (info->margin.top != margin->top) + clutter_actor_set_margin_top (self, margin->top); + + if (info->margin.right != margin->right) + clutter_actor_set_margin_right (self, margin->right); + + if (info->margin.bottom != margin->bottom) + clutter_actor_set_margin_bottom (self, margin->bottom); + + if (info->margin.left != margin->left) + clutter_actor_set_margin_left (self, margin->left); +} + +/** + * clutter_actor_get_margin: + * @self: a #ClutterActor + * @margin: (out caller-allocates): return location for a #ClutterMargin + * + * Retrieves all the components of the margin of a #ClutterActor. + * + * Since: 1.10 + */ +void +clutter_actor_get_margin (ClutterActor *self, + ClutterMargin *margin) +{ + const ClutterLayoutInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (margin != NULL); + + info = _clutter_actor_get_layout_info_or_defaults (self); + + *margin = info->margin; +} + +/** + * clutter_actor_set_margin_top: + * @self: a #ClutterActor + * @margin: the top margin + * + * Sets the margin from the top of a #ClutterActor. + * + * The #ClutterActor:margin-top property is animatable. + * + * Since: 1.10 + */ +void +clutter_actor_set_margin_top (ClutterActor *self, + gfloat margin) +{ + const ClutterLayoutInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (margin >= 0.f); + + info = _clutter_actor_get_layout_info_or_defaults (self); + _clutter_actor_create_transition (self, obj_props[PROP_MARGIN_TOP], + info->margin.top, + margin); +} + +/** + * clutter_actor_get_margin_top: + * @self: a #ClutterActor + * + * Retrieves the top margin of a #ClutterActor. + * + * Return value: the top margin + * + * Since: 1.10 + */ +gfloat +clutter_actor_get_margin_top (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0.f); + + return _clutter_actor_get_layout_info_or_defaults (self)->margin.top; +} + +/** + * clutter_actor_set_margin_bottom: + * @self: a #ClutterActor + * @margin: the bottom margin + * + * Sets the margin from the bottom of a #ClutterActor. + * + * The #ClutterActor:margin-bottom property is animatable. + * + * Since: 1.10 + */ +void +clutter_actor_set_margin_bottom (ClutterActor *self, + gfloat margin) +{ + const ClutterLayoutInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (margin >= 0.f); + + info = _clutter_actor_get_layout_info_or_defaults (self); + _clutter_actor_create_transition (self, obj_props[PROP_MARGIN_BOTTOM], + info->margin.bottom, + margin); +} + +/** + * clutter_actor_get_margin_bottom: + * @self: a #ClutterActor + * + * Retrieves the bottom margin of a #ClutterActor. + * + * Return value: the bottom margin + * + * Since: 1.10 + */ +gfloat +clutter_actor_get_margin_bottom (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0.f); + + return _clutter_actor_get_layout_info_or_defaults (self)->margin.bottom; +} + +/** + * clutter_actor_set_margin_left: + * @self: a #ClutterActor + * @margin: the left margin + * + * Sets the margin from the left of a #ClutterActor. + * + * The #ClutterActor:margin-left property is animatable. + * + * Since: 1.10 + */ +void +clutter_actor_set_margin_left (ClutterActor *self, + gfloat margin) +{ + const ClutterLayoutInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (margin >= 0.f); + + info = _clutter_actor_get_layout_info_or_defaults (self); + _clutter_actor_create_transition (self, obj_props[PROP_MARGIN_LEFT], + info->margin.left, + margin); +} + +/** + * clutter_actor_get_margin_left: + * @self: a #ClutterActor + * + * Retrieves the left margin of a #ClutterActor. + * + * Return value: the left margin + * + * Since: 1.10 + */ +gfloat +clutter_actor_get_margin_left (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0.f); + + return _clutter_actor_get_layout_info_or_defaults (self)->margin.left; +} + +/** + * clutter_actor_set_margin_right: + * @self: a #ClutterActor + * @margin: the right margin + * + * Sets the margin from the right of a #ClutterActor. + * + * The #ClutterActor:margin-right property is animatable. + * + * Since: 1.10 + */ +void +clutter_actor_set_margin_right (ClutterActor *self, + gfloat margin) +{ + const ClutterLayoutInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (margin >= 0.f); + + info = _clutter_actor_get_layout_info_or_defaults (self); + _clutter_actor_create_transition (self, obj_props[PROP_MARGIN_RIGHT], + info->margin.right, + margin); +} + +/** + * clutter_actor_get_margin_right: + * @self: a #ClutterActor + * + * Retrieves the right margin of a #ClutterActor. + * + * Return value: the right margin + * + * Since: 1.10 + */ +gfloat +clutter_actor_get_margin_right (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0.f); + + return _clutter_actor_get_layout_info_or_defaults (self)->margin.right; +} + +static inline void +clutter_actor_set_background_color_internal (ClutterActor *self, + const ClutterColor *color) +{ + ClutterActorPrivate *priv = self->priv; + GObject *obj; + + if (priv->bg_color_set && clutter_color_equal (color, &priv->bg_color)) + return; + + obj = G_OBJECT (self); + + priv->bg_color = *color; + priv->bg_color_set = TRUE; + + clutter_actor_queue_redraw (self); + + g_object_notify_by_pspec (obj, obj_props[PROP_BACKGROUND_COLOR_SET]); + g_object_notify_by_pspec (obj, obj_props[PROP_BACKGROUND_COLOR]); +} + +/** + * clutter_actor_set_background_color: + * @self: a #ClutterActor + * @color: (allow-none): a #ClutterColor, or %NULL to unset a previously + * set color + * + * Sets the background color of a #ClutterActor. + * + * The background color will be used to cover the whole allocation of the + * actor. The default background color of an actor is transparent. + * + * To check whether an actor has a background color, you can use the + * #ClutterActor:background-color-set actor property. + * + * The #ClutterActor:background-color property is animatable. + * + * Since: 1.10 + */ +void +clutter_actor_set_background_color (ClutterActor *self, + const ClutterColor *color) +{ + ClutterActorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + priv = self->priv; + + if (color == NULL) + { + GObject *obj = G_OBJECT (self); + + priv->bg_color_set = FALSE; + + clutter_actor_queue_redraw (self); + + g_object_notify_by_pspec (obj, obj_props[PROP_BACKGROUND_COLOR_SET]); + } + else + _clutter_actor_create_transition (self, + obj_props[PROP_BACKGROUND_COLOR], + &priv->bg_color, + color); +} + +/** + * clutter_actor_get_background_color: + * @self: a #ClutterActor + * @color: (out caller-allocates): return location for a #ClutterColor + * + * Retrieves the color set using clutter_actor_set_background_color(). + * + * Since: 1.10 + */ +void +clutter_actor_get_background_color (ClutterActor *self, + ClutterColor *color) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (color != NULL); + + *color = self->priv->bg_color; +} + +/** + * clutter_actor_get_previous_sibling: + * @self: a #ClutterActor + * + * Retrieves the sibling of @self that comes before it in the list + * of children of @self's parent. + * + * The returned pointer is only valid until the scene graph changes; it + * is not safe to modify the list of children of @self while iterating + * it. + * + * Return value: (transfer none): a pointer to a #ClutterActor, or %NULL + * + * Since: 1.10 + */ +ClutterActor * +clutter_actor_get_previous_sibling (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + + return self->priv->prev_sibling; +} + +/** + * clutter_actor_get_next_sibling: + * @self: a #ClutterActor + * + * Retrieves the sibling of @self that comes after it in the list + * of children of @self's parent. + * + * The returned pointer is only valid until the scene graph changes; it + * is not safe to modify the list of children of @self while iterating + * it. + * + * Return value: (transfer none): a pointer to a #ClutterActor, or %NULL + * + * Since: 1.10 + */ +ClutterActor * +clutter_actor_get_next_sibling (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + + return self->priv->next_sibling; +} + +/** + * clutter_actor_get_first_child: + * @self: a #ClutterActor + * + * Retrieves the first child of @self. + * + * The returned pointer is only valid until the scene graph changes; it + * is not safe to modify the list of children of @self while iterating + * it. + * + * Return value: (transfer none): a pointer to a #ClutterActor, or %NULL + * + * Since: 1.10 + */ +ClutterActor * +clutter_actor_get_first_child (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + + return self->priv->first_child; +} + +/** + * clutter_actor_get_last_child: + * @self: a #ClutterActor + * + * Retrieves the last child of @self. + * + * The returned pointer is only valid until the scene graph changes; it + * is not safe to modify the list of children of @self while iterating + * it. + * + * Return value: (transfer none): a pointer to a #ClutterActor, or %NULL + * + * Since: 1.10 + */ +ClutterActor * +clutter_actor_get_last_child (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + + return self->priv->last_child; +} + +/* easy way to have properly named fields instead of the dummy ones + * we use in the public structure + */ +typedef struct _RealActorIter +{ + ClutterActor *root; /* dummy1 */ + ClutterActor *current; /* dummy2 */ + gpointer padding_1; /* dummy3 */ + gint age; /* dummy4 */ + gpointer padding_2; /* dummy5 */ +} RealActorIter; + +/** + * clutter_actor_iter_init: + * @iter: a #ClutterActorIter + * @root: a #ClutterActor + * + * Initializes a #ClutterActorIter, which can then be used to iterate + * efficiently over a section of the scene graph, and associates it + * with @root. + * + * Modifying the scene graph section that contains @root will invalidate + * the iterator. + * + * |[ + * ClutterActorIter iter; + * ClutterActor *child; + * + * clutter_actor_iter_init (&iter, container); + * while (clutter_actor_iter_next (&iter, &child)) + * { + * // do something with child + * } + * ]| + * + * Since: 1.10 + */ +void +clutter_actor_iter_init (ClutterActorIter *iter, + ClutterActor *root) +{ + RealActorIter *ri = (RealActorIter *) iter; + + g_return_if_fail (iter != NULL); + g_return_if_fail (CLUTTER_IS_ACTOR (root)); + + ri->root = root; + ri->current = NULL; + ri->age = root->priv->age; +} + +/** + * clutter_actor_iter_is_valid: + * @iter: a #ClutterActorIter + * + * Checks whether a #ClutterActorIter is still valid. + * + * An iterator is considered valid if it has been initialized, and + * if the #ClutterActor that it refers to hasn't been modified after + * the initialization. + * + * Return value: %TRUE if the iterator is valid, and %FALSE otherwise + * + * Since: 1.12 + */ +gboolean +clutter_actor_iter_is_valid (const ClutterActorIter *iter) +{ + RealActorIter *ri = (RealActorIter *) iter; + + g_return_val_if_fail (iter != NULL, FALSE); + + if (ri->root == NULL) + return FALSE; + + return ri->root->priv->age == ri->age; +} + +/** + * clutter_actor_iter_next: + * @iter: a #ClutterActorIter + * @child: (out) (transfer none): return location for a #ClutterActor + * + * Advances the @iter and retrieves the next child of the root #ClutterActor + * that was used to initialize the #ClutterActorIterator. + * + * If the iterator can advance, this function returns %TRUE and sets the + * @child argument. + * + * If the iterator cannot advance, this function returns %FALSE, and + * the contents of @child are undefined. + * + * Return value: %TRUE if the iterator could advance, and %FALSE otherwise. + * + * Since: 1.10 + */ +gboolean +clutter_actor_iter_next (ClutterActorIter *iter, + ClutterActor **child) +{ + RealActorIter *ri = (RealActorIter *) iter; + + g_return_val_if_fail (iter != NULL, FALSE); + g_return_val_if_fail (ri->root != NULL, FALSE); +#ifndef G_DISABLE_ASSERT + g_return_val_if_fail (ri->age == ri->root->priv->age, FALSE); +#endif + + if (ri->current == NULL) + ri->current = ri->root->priv->first_child; + else + ri->current = ri->current->priv->next_sibling; + + if (child != NULL) + *child = ri->current; + + return ri->current != NULL; +} + +/** + * clutter_actor_iter_prev: + * @iter: a #ClutterActorIter + * @child: (out) (transfer none): return location for a #ClutterActor + * + * Advances the @iter and retrieves the previous child of the root + * #ClutterActor that was used to initialize the #ClutterActorIterator. + * + * If the iterator can advance, this function returns %TRUE and sets the + * @child argument. + * + * If the iterator cannot advance, this function returns %FALSE, and + * the contents of @child are undefined. + * + * Return value: %TRUE if the iterator could advance, and %FALSE otherwise. + * + * Since: 1.10 + */ +gboolean +clutter_actor_iter_prev (ClutterActorIter *iter, + ClutterActor **child) +{ + RealActorIter *ri = (RealActorIter *) iter; + + g_return_val_if_fail (iter != NULL, FALSE); + g_return_val_if_fail (ri->root != NULL, FALSE); +#ifndef G_DISABLE_ASSERT + g_return_val_if_fail (ri->age == ri->root->priv->age, FALSE); +#endif + + if (ri->current == NULL) + ri->current = ri->root->priv->last_child; + else + ri->current = ri->current->priv->prev_sibling; + + if (child != NULL) + *child = ri->current; + + return ri->current != NULL; +} + +/** + * clutter_actor_iter_remove: + * @iter: a #ClutterActorIter + * + * Safely removes the #ClutterActor currently pointer to by the iterator + * from its parent. + * + * This function can only be called after clutter_actor_iter_next() or + * clutter_actor_iter_prev() returned %TRUE, and cannot be called more + * than once for the same actor. + * + * This function will call clutter_actor_remove_child() internally. + * + * Since: 1.10 + */ +void +clutter_actor_iter_remove (ClutterActorIter *iter) +{ + RealActorIter *ri = (RealActorIter *) iter; + ClutterActor *cur; + + g_return_if_fail (iter != NULL); + g_return_if_fail (ri->root != NULL); +#ifndef G_DISABLE_ASSERT + g_return_if_fail (ri->age == ri->root->priv->age); +#endif + g_return_if_fail (ri->current != NULL); + + cur = ri->current; + + if (cur != NULL) + { + ri->current = cur->priv->prev_sibling; + + clutter_actor_remove_child_internal (ri->root, cur, + REMOVE_CHILD_DEFAULT_FLAGS); + + ri->age += 1; + } +} + +/** + * clutter_actor_iter_destroy: + * @iter: a #ClutterActorIter + * + * Safely destroys the #ClutterActor currently pointer to by the iterator + * from its parent. + * + * This function can only be called after clutter_actor_iter_next() or + * clutter_actor_iter_prev() returned %TRUE, and cannot be called more + * than once for the same actor. + * + * This function will call clutter_actor_destroy() internally. + * + * Since: 1.10 + */ +void +clutter_actor_iter_destroy (ClutterActorIter *iter) +{ + RealActorIter *ri = (RealActorIter *) iter; + ClutterActor *cur; + + g_return_if_fail (iter != NULL); + g_return_if_fail (ri->root != NULL); +#ifndef G_DISABLE_ASSERT + g_return_if_fail (ri->age == ri->root->priv->age); +#endif + g_return_if_fail (ri->current != NULL); + + cur = ri->current; + + if (cur != NULL) + { + ri->current = cur->priv->prev_sibling; + + clutter_actor_destroy (cur); + + ri->age += 1; + } +} + +static const ClutterAnimationInfo default_animation_info = { + NULL, /* transitions */ + NULL, /* states */ + NULL, /* cur_state */ +}; + +static void +clutter_animation_info_free (gpointer data) +{ + if (data != NULL) + { + ClutterAnimationInfo *info = data; + + if (info->transitions != NULL) + g_hash_table_unref (info->transitions); + + if (info->states != NULL) + g_array_unref (info->states); + + g_slice_free (ClutterAnimationInfo, info); + } +} + +const ClutterAnimationInfo * +_clutter_actor_get_animation_info_or_defaults (ClutterActor *self) +{ + const ClutterAnimationInfo *res; + GObject *obj = G_OBJECT (self); + + res = g_object_get_qdata (obj, quark_actor_animation_info); + if (res != NULL) + return res; + + return &default_animation_info; +} + +ClutterAnimationInfo * +_clutter_actor_get_animation_info (ClutterActor *self) +{ + GObject *obj = G_OBJECT (self); + ClutterAnimationInfo *res; + + res = g_object_get_qdata (obj, quark_actor_animation_info); + if (res == NULL) + { + res = g_slice_new (ClutterAnimationInfo); + + *res = default_animation_info; + + g_object_set_qdata_full (obj, quark_actor_animation_info, + res, + clutter_animation_info_free); + } + + return res; +} + +ClutterTransition * +_clutter_actor_get_transition (ClutterActor *actor, + GParamSpec *pspec) +{ + const ClutterAnimationInfo *info; + + info = _clutter_actor_get_animation_info_or_defaults (actor); + + if (info->transitions == NULL) + return NULL; + + return g_hash_table_lookup (info->transitions, pspec->name); +} + +static void +transition_closure_free (gpointer data) +{ + if (G_LIKELY (data != NULL)) + { + TransitionClosure *clos = data; + ClutterTimeline *timeline; + + timeline = CLUTTER_TIMELINE (clos->transition); + + /* we disconnect the signal handler before stopping the timeline, + * so that we don't end up inside on_transition_stopped() from + * a call to g_hash_table_remove(). + */ + g_signal_handler_disconnect (clos->transition, clos->completed_id); + + if (clutter_timeline_is_playing (timeline)) + clutter_timeline_stop (timeline); + + /* remove the reference added in add_transition_internal() */ + g_object_unref (clos->transition); + + g_free (clos->name); + + g_slice_free (TransitionClosure, clos); + } +} + +static void +on_transition_stopped (ClutterTransition *transition, + gboolean is_finished, + TransitionClosure *clos) +{ + ClutterActor *actor = clos->actor; + ClutterAnimationInfo *info; + GQuark t_quark; + gchar *t_name; + + if (clos->name == NULL) + return; + + /* reset the caches used by animations */ + clutter_actor_store_content_box (actor, NULL); + + info = _clutter_actor_get_animation_info (actor); + + /* we need copies because we emit the signal after the + * TransitionClosure data structure has been freed + */ + t_quark = g_quark_from_string (clos->name); + t_name = g_strdup (clos->name); + + if (clos->is_implicit || + clutter_transition_get_remove_on_complete (transition)) + { + /* we take a reference here because removing the closure + * will release the reference on the transition, and we + * want the transition to survive the signal emission + */ + g_object_ref (transition); + + /* this is safe, because the timeline has now stopped, + * so we won't recurse; the reference on the Animatable + * will be dropped by the ::stopped signal closure in + * ClutterTransition, which is RUN_LAST, and thus will + * be called after this handler + */ + g_hash_table_remove (info->transitions, clos->name); + } + + /* we emit the ::transition-stopped after removing the + * transition, so that we can chain up new transitions + * without interfering with the one that just finished + */ + g_signal_emit (actor, actor_signals[TRANSITION_STOPPED], t_quark, + t_name, + is_finished); + + g_free (t_name); + + /* if it's the last transition then we clean up */ + if (g_hash_table_size (info->transitions) == 0) + { + g_hash_table_unref (info->transitions); + info->transitions = NULL; + + CLUTTER_NOTE (ANIMATION, "Transitions for '%s' completed", + _clutter_actor_get_debug_name (actor)); + + g_signal_emit (actor, actor_signals[TRANSITIONS_COMPLETED], 0); + } +} + +static void +clutter_actor_add_transition_internal (ClutterActor *self, + const gchar *name, + ClutterTransition *transition, + gboolean is_implicit) +{ + ClutterTimeline *timeline; + TransitionClosure *clos; + ClutterAnimationInfo *info; + + info = _clutter_actor_get_animation_info (self); + + if (info->transitions == NULL) + info->transitions = g_hash_table_new_full (g_str_hash, g_str_equal, + NULL, + transition_closure_free); + + if (g_hash_table_lookup (info->transitions, name) != NULL) + { + g_warning ("A transition with name '%s' already exists for " + "the actor '%s'", + name, + _clutter_actor_get_debug_name (self)); + return; + } + + clutter_transition_set_animatable (transition, CLUTTER_ANIMATABLE (self)); + + timeline = CLUTTER_TIMELINE (transition); + + clos = g_slice_new (TransitionClosure); + clos->actor = self; + clos->transition = g_object_ref (transition); + clos->name = g_strdup (name); + clos->is_implicit = is_implicit; + clos->completed_id = g_signal_connect (timeline, "stopped", + G_CALLBACK (on_transition_stopped), + clos); + + CLUTTER_NOTE (ANIMATION, + "Adding transition '%s' [%p] to actor '%s'", + clos->name, + clos->transition, + _clutter_actor_get_debug_name (self)); + + g_hash_table_insert (info->transitions, clos->name, clos); + clutter_timeline_start (timeline); +} + +static gboolean +should_skip_implicit_transition (ClutterActor *self, + GParamSpec *pspec) +{ + ClutterActorPrivate *priv = self->priv; + const ClutterAnimationInfo *info; + + /* this function is called from _clutter_actor_create_transition() which + * calls _clutter_actor_get_animation_info() first, so we're guaranteed + * to have the correct ClutterAnimationInfo pointer + */ + info = _clutter_actor_get_animation_info_or_defaults (self); + + /* if the easing state has a non-zero duration we always want an + * implicit transition to occur + */ + if (info->cur_state->easing_duration == 0) + return TRUE; + + /* on the other hand, if the actor hasn't been allocated yet, we want to + * skip all transitions on the :allocation, to avoid actors "flying in" + * into their new position and size + */ + if (pspec == obj_props[PROP_ALLOCATION] && priv->needs_allocation) + return TRUE; + + /* if the actor is not mapped and is not part of a branch of the scene + * graph that is being cloned, then we always skip implicit transitions + * on the account of the fact that the actor is not going to be visible + * when those transitions happen + */ + if (!CLUTTER_ACTOR_IS_MAPPED (self) && + priv->in_cloned_branch == 0 && + !clutter_actor_has_mapped_clones (self)) + return TRUE; + + return FALSE; +} + +/*< private >* + * _clutter_actor_create_transition: + * @actor: a #ClutterActor + * @pspec: the property used for the transition + * @...: initial and final state + * + * Creates a #ClutterTransition for the property represented by @pspec. + * + * Return value: a #ClutterTransition + */ +ClutterTransition * +_clutter_actor_create_transition (ClutterActor *actor, + GParamSpec *pspec, + ...) +{ + ClutterTimeline *timeline; + ClutterInterval *interval; + ClutterAnimationInfo *info; + ClutterTransition *res = NULL; + gboolean call_restore = FALSE; + TransitionClosure *clos; + va_list var_args; + GValue initial = G_VALUE_INIT; + GValue final = G_VALUE_INIT; + GType ptype; + char *error; + + g_assert (pspec != NULL); + g_assert ((pspec->flags & CLUTTER_PARAM_ANIMATABLE) != 0); + + info = _clutter_actor_get_animation_info (actor); + + /* XXX - this will go away in 2.0 + * + * if no state has been pushed, we assume that the easing state is + * in "compatibility mode": all transitions have a duration of 0 + * msecs, which means that they happen immediately. in Clutter 2.0 + * this will turn into a g_assert(info->states != NULL), as every + * actor will start with a predefined easing state + */ + if (info->states == NULL) + { + clutter_actor_save_easing_state (actor); + clutter_actor_set_easing_duration (actor, 0); + call_restore = TRUE; + } + + if (info->transitions == NULL) + info->transitions = g_hash_table_new_full (g_str_hash, g_str_equal, + NULL, + transition_closure_free); + + va_start (var_args, pspec); + + ptype = G_PARAM_SPEC_VALUE_TYPE (pspec); + + G_VALUE_COLLECT_INIT (&initial, ptype, + var_args, 0, + &error); + if (error != NULL) + { + g_critical ("%s: %s", G_STRLOC, error); + g_free (error); + goto out; + } + + G_VALUE_COLLECT_INIT (&final, ptype, + var_args, 0, + &error); + if (error != NULL) + { + g_critical ("%s: %s", G_STRLOC, error); + g_value_unset (&initial); + g_free (error); + goto out; + } + + if (should_skip_implicit_transition (actor, pspec)) + { + CLUTTER_NOTE (ANIMATION, "Skipping implicit transition for '%s::%s'", + _clutter_actor_get_debug_name (actor), + pspec->name); + + /* remove a transition, if one exists */ + clutter_actor_remove_transition (actor, pspec->name); + + /* we don't go through the Animatable interface because we + * already know we got here through an animatable property. + */ + clutter_actor_set_animatable_property (actor, + pspec->param_id, + &final, + pspec); + + g_value_unset (&initial); + g_value_unset (&final); + + goto out; + } + + clos = g_hash_table_lookup (info->transitions, pspec->name); + if (clos == NULL) + { + res = clutter_property_transition_new (pspec->name); + + interval = clutter_interval_new_with_values (ptype, &initial, &final); + clutter_transition_set_interval (res, interval); + + timeline = CLUTTER_TIMELINE (res); + clutter_timeline_set_delay (timeline, info->cur_state->easing_delay); + clutter_timeline_set_duration (timeline, info->cur_state->easing_duration); + clutter_timeline_set_progress_mode (timeline, info->cur_state->easing_mode); + +#ifdef CLUTTER_ENABLE_DEBUG + if (CLUTTER_HAS_DEBUG (ANIMATION)) + { + gchar *initial_v, *final_v; + + initial_v = g_strdup_value_contents (&initial); + final_v = g_strdup_value_contents (&final); + + CLUTTER_NOTE (ANIMATION, + "Created transition for %s:%s " + "(len:%u, mode:%s, delay:%u) " + "initial:%s, final:%s", + _clutter_actor_get_debug_name (actor), + pspec->name, + info->cur_state->easing_duration, + clutter_get_easing_name_for_mode (info->cur_state->easing_mode), + info->cur_state->easing_delay, + initial_v, final_v); + + g_free (initial_v); + g_free (final_v); + } +#endif /* CLUTTER_ENABLE_DEBUG */ + + /* this will start the transition as well */ + clutter_actor_add_transition_internal (actor, pspec->name, res, TRUE); + + /* the actor now owns the transition */ + g_object_unref (res); + + g_value_unset (&initial); + g_value_unset (&final); + } + else + { + ClutterAnimationMode cur_mode; + guint cur_duration; + + CLUTTER_NOTE (ANIMATION, "Existing transition for %s:%s", + _clutter_actor_get_debug_name (actor), + pspec->name); + + timeline = CLUTTER_TIMELINE (clos->transition); + + cur_duration = clutter_timeline_get_duration (timeline); + if (cur_duration != info->cur_state->easing_duration) + clutter_timeline_set_duration (timeline, info->cur_state->easing_duration); + + cur_mode = clutter_timeline_get_progress_mode (timeline); + if (cur_mode != info->cur_state->easing_mode) + clutter_timeline_set_progress_mode (timeline, info->cur_state->easing_mode); + + clutter_timeline_rewind (timeline); + + interval = clutter_transition_get_interval (clos->transition); + clutter_interval_set_initial_value (interval, &initial); + clutter_interval_set_final_value (interval, &final); + + res = clos->transition; + } + +out: + if (call_restore) + clutter_actor_restore_easing_state (actor); + + va_end (var_args); + + return res; +} + +/** + * clutter_actor_add_transition: + * @self: a #ClutterActor + * @name: the name of the transition to add + * @transition: the #ClutterTransition to add + * + * Adds a @transition to the #ClutterActor's list of animations. + * + * The @name string is a per-actor unique identifier of the @transition: only + * one #ClutterTransition can be associated to the specified @name. + * + * The @transition will be started once added. + * + * This function will take a reference on the @transition. + * + * This function is usually called implicitly when modifying an animatable + * property. + * + * Since: 1.10 + */ +void +clutter_actor_add_transition (ClutterActor *self, + const char *name, + ClutterTransition *transition) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (name != NULL); + g_return_if_fail (CLUTTER_IS_TRANSITION (transition)); + + clutter_actor_add_transition_internal (self, name, transition, FALSE); +} + +/** + * clutter_actor_remove_transition: + * @self: a #ClutterActor + * @name: the name of the transition to remove + * + * Removes the transition stored inside a #ClutterActor using @name + * identifier. + * + * If the transition is currently in progress, it will be stopped. + * + * This function releases the reference acquired when the transition + * was added to the #ClutterActor. + * + * Since: 1.10 + */ +void +clutter_actor_remove_transition (ClutterActor *self, + const char *name) +{ + const ClutterAnimationInfo *info; + TransitionClosure *clos; + gboolean was_playing; + GQuark t_quark; + gchar *t_name; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (name != NULL); + + info = _clutter_actor_get_animation_info_or_defaults (self); + + if (info->transitions == NULL) + return; + + clos = g_hash_table_lookup (info->transitions, name); + if (clos == NULL) + return; + + was_playing = + clutter_timeline_is_playing (CLUTTER_TIMELINE (clos->transition)); + t_quark = g_quark_from_string (clos->name); + t_name = g_strdup (clos->name); + + g_hash_table_remove (info->transitions, name); + + /* we want to maintain the invariant that ::transition-stopped is + * emitted after the transition has been removed, to allow replacing + * or chaining; removing the transition from the hash table will + * stop it, but transition_closure_free() will disconnect the signal + * handler we install in add_transition_internal(), to avoid loops + * or segfaults. + * + * since we know already that a transition will stop once it's removed + * from an actor, we can simply emit the ::transition-stopped here + * ourselves, if the timeline was playing (if it wasn't, then the + * signal was already emitted at least once). + */ + if (was_playing) + { + g_signal_emit (self, actor_signals[TRANSITION_STOPPED], + t_quark, + t_name, + FALSE); + } + + g_free (t_name); +} + +/** + * clutter_actor_remove_all_transitions: + * @self: a #ClutterActor + * + * Removes all transitions associated to @self. + * + * Since: 1.10 + */ +void +clutter_actor_remove_all_transitions (ClutterActor *self) +{ + const ClutterAnimationInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + info = _clutter_actor_get_animation_info_or_defaults (self); + if (info->transitions == NULL) + return; + + g_hash_table_remove_all (info->transitions); +} + +/** + * clutter_actor_set_easing_duration: + * @self: a #ClutterActor + * @msecs: the duration of the easing, or %NULL + * + * Sets the duration of the tweening for animatable properties + * of @self for the current easing state. + * + * Since: 1.10 + */ +void +clutter_actor_set_easing_duration (ClutterActor *self, + guint msecs) +{ + ClutterAnimationInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + info = _clutter_actor_get_animation_info (self); + + if (info->cur_state == NULL) + { + g_warning ("You must call clutter_actor_save_easing_state() prior " + "to calling clutter_actor_set_easing_duration()."); + return; + } + + if (info->cur_state->easing_duration != msecs) + info->cur_state->easing_duration = msecs; +} + +/** + * clutter_actor_get_easing_duration: + * @self: a #ClutterActor + * + * Retrieves the duration of the tweening for animatable + * properties of @self for the current easing state. + * + * Return value: the duration of the tweening, in milliseconds + * + * Since: 1.10 + */ +guint +clutter_actor_get_easing_duration (ClutterActor *self) +{ + const ClutterAnimationInfo *info; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0); + + info = _clutter_actor_get_animation_info_or_defaults (self); + + if (info->cur_state != NULL) + return info->cur_state->easing_duration; + + return 0; +} + +/** + * clutter_actor_set_easing_mode: + * @self: a #ClutterActor + * @mode: an easing mode, excluding %CLUTTER_CUSTOM_MODE + * + * Sets the easing mode for the tweening of animatable properties + * of @self. + * + * Since: 1.10 + */ +void +clutter_actor_set_easing_mode (ClutterActor *self, + ClutterAnimationMode mode) +{ + ClutterAnimationInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (mode != CLUTTER_CUSTOM_MODE); + g_return_if_fail (mode < CLUTTER_ANIMATION_LAST); + + info = _clutter_actor_get_animation_info (self); + + if (info->cur_state == NULL) + { + g_warning ("You must call clutter_actor_save_easing_state() prior " + "to calling clutter_actor_set_easing_mode()."); + return; + } + + if (info->cur_state->easing_mode != mode) + info->cur_state->easing_mode = mode; +} + +/** + * clutter_actor_get_easing_mode: + * @self: a #ClutterActor + * + * Retrieves the easing mode for the tweening of animatable properties + * of @self for the current easing state. + * + * Return value: an easing mode + * + * Since: 1.10 + */ +ClutterAnimationMode +clutter_actor_get_easing_mode (ClutterActor *self) +{ + const ClutterAnimationInfo *info; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), CLUTTER_EASE_OUT_CUBIC); + + info = _clutter_actor_get_animation_info_or_defaults (self); + + if (info->cur_state != NULL) + return info->cur_state->easing_mode; + + return CLUTTER_EASE_OUT_CUBIC; +} + +/** + * clutter_actor_set_easing_delay: + * @self: a #ClutterActor + * @msecs: the delay before the start of the tweening, in milliseconds + * + * Sets the delay that should be applied before tweening animatable + * properties. + * + * Since: 1.10 + */ +void +clutter_actor_set_easing_delay (ClutterActor *self, + guint msecs) +{ + ClutterAnimationInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + info = _clutter_actor_get_animation_info (self); + + if (info->cur_state == NULL) + { + g_warning ("You must call clutter_actor_save_easing_state() prior " + "to calling clutter_actor_set_easing_delay()."); + return; + } + + if (info->cur_state->easing_delay != msecs) + info->cur_state->easing_delay = msecs; +} + +/** + * clutter_actor_get_easing_delay: + * @self: a #ClutterActor + * + * Retrieves the delay that should be applied when tweening animatable + * properties. + * + * Return value: a delay, in milliseconds + * + * Since: 1.10 + */ +guint +clutter_actor_get_easing_delay (ClutterActor *self) +{ + const ClutterAnimationInfo *info; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), 0); + + info = _clutter_actor_get_animation_info_or_defaults (self); + + if (info->cur_state != NULL) + return info->cur_state->easing_delay; + + return 0; +} + +/** + * clutter_actor_get_transition: + * @self: a #ClutterActor + * @name: the name of the transition + * + * Retrieves the #ClutterTransition of a #ClutterActor by using the + * transition @name. + * + * Transitions created for animatable properties use the name of the + * property itself, for instance the code below: + * + * |[ + * clutter_actor_set_easing_duration (actor, 1000); + * clutter_actor_set_rotation (actor, CLUTTER_Y_AXIS, 360.0, x, y, z); + * + * transition = clutter_actor_get_transition (actor, "rotation-angle-y"); + * g_signal_connect (transition, "stopped", + * G_CALLBACK (on_transition_stopped), + * actor); + * ]| + * + * will call the `on_transition_stopped` callback when the transition + * is finished. + * + * If you just want to get notifications of the completion of a transition, + * you should use the #ClutterActor::transition-stopped signal, using the + * transition name as the signal detail. + * + * Return value: (transfer none): a #ClutterTransition, or %NULL is none + * was found to match the passed name; the returned instance is owned + * by Clutter and it should not be freed + * + * Since: 1.10 + */ +ClutterTransition * +clutter_actor_get_transition (ClutterActor *self, + const char *name) +{ + TransitionClosure *clos; + const ClutterAnimationInfo *info; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + g_return_val_if_fail (name != NULL, NULL); + + info = _clutter_actor_get_animation_info_or_defaults (self); + if (info->transitions == NULL) + return NULL; + + clos = g_hash_table_lookup (info->transitions, name); + if (clos == NULL) + return NULL; + + return clos->transition; +} + +/** + * clutter_actor_save_easing_state: + * @self: a #ClutterActor + * + * Saves the current easing state for animatable properties, and creates + * a new state with the default values for easing mode and duration. + * + * New transitions created after calling this function will inherit the + * duration, easing mode, and delay of the new easing state; this also + * applies to transitions modified in flight. + * + * Since: 1.10 + */ +void +clutter_actor_save_easing_state (ClutterActor *self) +{ + ClutterAnimationInfo *info; + AState new_state; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + info = _clutter_actor_get_animation_info (self); + + if (info->states == NULL) + info->states = g_array_new (FALSE, FALSE, sizeof (AState)); + + new_state.easing_mode = CLUTTER_EASE_OUT_CUBIC; + new_state.easing_duration = 250; + new_state.easing_delay = 0; + + g_array_append_val (info->states, new_state); + + info->cur_state = &g_array_index (info->states, AState, info->states->len - 1); +} + +/** + * clutter_actor_restore_easing_state: + * @self: a #ClutterActor + * + * Restores the easing state as it was prior to a call to + * clutter_actor_save_easing_state(). + * + * Since: 1.10 + */ +void +clutter_actor_restore_easing_state (ClutterActor *self) +{ + ClutterAnimationInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + info = _clutter_actor_get_animation_info (self); + + if (info->states == NULL) + { + g_critical ("The function clutter_actor_restore_easing_state() has " + "been called without a previous call to " + "clutter_actor_save_easing_state()."); + return; + } + + g_array_remove_index (info->states, info->states->len - 1); + + if (info->states->len > 0) + info->cur_state = &g_array_index (info->states, AState, info->states->len - 1); + else + { + g_array_unref (info->states); + info->states = NULL; + info->cur_state = NULL; + } +} + +/** + * clutter_actor_set_content: + * @self: a #ClutterActor + * @content: (allow-none): a #ClutterContent, or %NULL + * + * Sets the contents of a #ClutterActor. + * + * Since: 1.10 + */ +void +clutter_actor_set_content (ClutterActor *self, + ClutterContent *content) +{ + ClutterActorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (content == NULL || CLUTTER_IS_CONTENT (content)); + + priv = self->priv; + + if (priv->content == content) + return; + + if (priv->content != NULL) + { + _clutter_content_detached (priv->content, self); + g_clear_object (&priv->content); + } + + priv->content = content; + + if (priv->content != NULL) + { + g_object_ref (priv->content); + _clutter_content_attached (priv->content, self); + } + + /* if the actor's preferred size is the content's preferred size, + * then we need to conditionally queue a relayout here... + */ + if (priv->request_mode == CLUTTER_REQUEST_CONTENT_SIZE) + _clutter_actor_queue_only_relayout (self); + + clutter_actor_queue_redraw (self); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_CONTENT]); + + /* if the content gravity is not resize-fill, and the new content has a + * different preferred size than the previous one, then the content box + * may have been changed. since we compute that lazily, we just notify + * here, and let whomever watches :content-box do whatever they need to + * do. + */ + if (priv->content_gravity != CLUTTER_CONTENT_GRAVITY_RESIZE_FILL) + { + if (priv->content_box_valid) + { + ClutterActorBox from_box, to_box; + + clutter_actor_get_content_box (self, &from_box); + + /* invalidate the cached content box */ + priv->content_box_valid = FALSE; + clutter_actor_get_content_box (self, &to_box); + + if (!clutter_actor_box_equal (&from_box, &to_box)) + _clutter_actor_create_transition (self, obj_props[PROP_CONTENT_BOX], + &from_box, + &to_box); + } + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_CONTENT_BOX]); + } +} + +/** + * clutter_actor_get_content: + * @self: a #ClutterActor + * + * Retrieves the contents of @self. + * + * Return value: (transfer none): a pointer to the #ClutterContent instance, + * or %NULL if none was set + * + * Since: 1.10 + */ +ClutterContent * +clutter_actor_get_content (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + + return self->priv->content; +} + +/** + * clutter_actor_set_content_gravity: + * @self: a #ClutterActor + * @gravity: the #ClutterContentGravity + * + * Sets the gravity of the #ClutterContent used by @self. + * + * See the description of the #ClutterActor:content-gravity property for + * more information. + * + * The #ClutterActor:content-gravity property is animatable. + * + * Since: 1.10 + */ +void +clutter_actor_set_content_gravity (ClutterActor *self, + ClutterContentGravity gravity) +{ + ClutterActorPrivate *priv; + ClutterActorBox from_box, to_box; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + priv = self->priv; + + if (priv->content_gravity == gravity) + return; + + priv->content_box_valid = FALSE; + + clutter_actor_get_content_box (self, &from_box); + + priv->content_gravity = gravity; + + clutter_actor_get_content_box (self, &to_box); + + _clutter_actor_create_transition (self, obj_props[PROP_CONTENT_BOX], + &from_box, + &to_box); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_CONTENT_GRAVITY]); +} + +/** + * clutter_actor_get_content_gravity: + * @self: a #ClutterActor + * + * Retrieves the content gravity as set using + * clutter_actor_set_content_gravity(). + * + * Return value: the content gravity + * + * Since: 1.10 + */ +ClutterContentGravity +clutter_actor_get_content_gravity (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), + CLUTTER_CONTENT_GRAVITY_RESIZE_FILL); + + return self->priv->content_gravity; +} + +/** + * clutter_actor_get_content_box: + * @self: a #ClutterActor + * @box: (out caller-allocates): the return location for the bounding + * box for the #ClutterContent + * + * Retrieves the bounding box for the #ClutterContent of @self. + * + * The bounding box is relative to the actor's allocation. + * + * If no #ClutterContent is set for @self, or if @self has not been + * allocated yet, then the result is undefined. + * + * The content box is guaranteed to be, at most, as big as the allocation + * of the #ClutterActor. + * + * If the #ClutterContent used by the actor has a preferred size, then + * it is possible to modify the content box by using the + * #ClutterActor:content-gravity property. + * + * Since: 1.10 + */ +void +clutter_actor_get_content_box (ClutterActor *self, + ClutterActorBox *box) +{ + ClutterActorPrivate *priv; + gfloat content_w, content_h; + gfloat alloc_w, alloc_h; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (box != NULL); + + priv = self->priv; + + box->x1 = 0.f; + box->y1 = 0.f; + box->x2 = priv->allocation.x2 - priv->allocation.x1; + box->y2 = priv->allocation.y2 - priv->allocation.y1; + + if (priv->content_box_valid) + { + *box = priv->content_box; + return; + } + + /* no need to do any more work */ + if (priv->content_gravity == CLUTTER_CONTENT_GRAVITY_RESIZE_FILL) + return; + + if (priv->content == NULL) + return; + + /* if the content does not have a preferred size then there is + * no point in computing the content box + */ + if (!clutter_content_get_preferred_size (priv->content, + &content_w, + &content_h)) + return; + + alloc_w = box->x2; + alloc_h = box->y2; + + switch (priv->content_gravity) + { + case CLUTTER_CONTENT_GRAVITY_TOP_LEFT: + box->x2 = box->x1 + MIN (content_w, alloc_w); + box->y2 = box->y1 + MIN (content_h, alloc_h); + break; + + case CLUTTER_CONTENT_GRAVITY_TOP: + if (alloc_w > content_w) + { + box->x1 += ceilf ((alloc_w - content_w) / 2.0); + box->x2 = box->x1 + content_w; + } + box->y2 = box->y1 + MIN (content_h, alloc_h); + break; + + case CLUTTER_CONTENT_GRAVITY_TOP_RIGHT: + if (alloc_w > content_w) + { + box->x1 += (alloc_w - content_w); + box->x2 = box->x1 + content_w; + } + box->y2 = box->y1 + MIN (content_h, alloc_h); + break; + + case CLUTTER_CONTENT_GRAVITY_LEFT: + box->x2 = box->x1 + MIN (content_w, alloc_w); + if (alloc_h > content_h) + { + box->y1 += ceilf ((alloc_h - content_h) / 2.0); + box->y2 = box->y1 + content_h; + } + break; + + case CLUTTER_CONTENT_GRAVITY_CENTER: + if (alloc_w > content_w) + { + box->x1 += ceilf ((alloc_w - content_w) / 2.0); + box->x2 = box->x1 + content_w; + } + if (alloc_h > content_h) + { + box->y1 += ceilf ((alloc_h - content_h) / 2.0); + box->y2 = box->y1 + content_h; + } + break; + + case CLUTTER_CONTENT_GRAVITY_RIGHT: + if (alloc_w > content_w) + { + box->x1 += (alloc_w - content_w); + box->x2 = box->x1 + content_w; + } + if (alloc_h > content_h) + { + box->y1 += ceilf ((alloc_h - content_h) / 2.0); + box->y2 = box->y1 + content_h; + } + break; + + case CLUTTER_CONTENT_GRAVITY_BOTTOM_LEFT: + box->x2 = box->x1 + MIN (content_w, alloc_w); + if (alloc_h > content_h) + { + box->y1 += (alloc_h - content_h); + box->y2 = box->y1 + content_h; + } + break; + + case CLUTTER_CONTENT_GRAVITY_BOTTOM: + if (alloc_w > content_w) + { + box->x1 += ceilf ((alloc_w - content_w) / 2.0); + box->x2 = box->x1 + content_w; + } + if (alloc_h > content_h) + { + box->y1 += (alloc_h - content_h); + box->y2 = box->y1 + content_h; + } + break; + + case CLUTTER_CONTENT_GRAVITY_BOTTOM_RIGHT: + if (alloc_w > content_w) + { + box->x1 += (alloc_w - content_w); + box->x2 = box->x1 + content_w; + } + if (alloc_h > content_h) + { + box->y1 += (alloc_h - content_h); + box->y2 = box->y1 + content_h; + } + break; + + case CLUTTER_CONTENT_GRAVITY_RESIZE_FILL: + g_assert_not_reached (); + break; + + case CLUTTER_CONTENT_GRAVITY_RESIZE_ASPECT: + { + double r_c = content_w / content_h; + + if ((alloc_w / r_c) > alloc_h) + { + box->y1 = 0.f; + box->y2 = alloc_h; + + box->x1 = (alloc_w - (alloc_h * r_c)) / 2.0f; + box->x2 = box->x1 + (alloc_h * r_c); + } + else + { + box->x1 = 0.f; + box->x2 = alloc_w; + + box->y1 = (alloc_h - (alloc_w / r_c)) / 2.0f; + box->y2 = box->y1 + (alloc_w / r_c); + } + + CLUTTER_NOTE (LAYOUT, + "r_c: %.3f, r_a: %.3f\t" + "a: [%.2fx%.2f], c: [%.2fx%.2f]\t" + "b: [%.2f, %.2f, %.2f, %.2f]", + r_c, alloc_w / alloc_h, + alloc_w, alloc_h, + content_w, content_h, + box->x1, box->y1, box->x2, box->y2); + } + break; + } +} + +/** + * clutter_actor_set_content_scaling_filters: + * @self: a #ClutterActor + * @min_filter: the minification filter for the content + * @mag_filter: the magnification filter for the content + * + * Sets the minification and magnification filter to be applied when + * scaling the #ClutterActor:content of a #ClutterActor. + * + * The #ClutterActor:minification-filter will be used when reducing + * the size of the content; the #ClutterActor:magnification-filter + * will be used when increasing the size of the content. + * + * Since: 1.10 + */ +void +clutter_actor_set_content_scaling_filters (ClutterActor *self, + ClutterScalingFilter min_filter, + ClutterScalingFilter mag_filter) +{ + ClutterActorPrivate *priv; + gboolean changed; + GObject *obj; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + priv = self->priv; + obj = G_OBJECT (self); + + g_object_freeze_notify (obj); + + changed = FALSE; + + if (priv->min_filter != min_filter) + { + priv->min_filter = min_filter; + changed = TRUE; + + g_object_notify_by_pspec (obj, obj_props[PROP_MINIFICATION_FILTER]); + } + + if (priv->mag_filter != mag_filter) + { + priv->mag_filter = mag_filter; + changed = TRUE; + + g_object_notify_by_pspec (obj, obj_props[PROP_MAGNIFICATION_FILTER]); + } + + if (changed) + clutter_actor_queue_redraw (self); + + g_object_thaw_notify (obj); +} + +/** + * clutter_actor_get_content_scaling_filters: + * @self: a #ClutterActor + * @min_filter: (out) (allow-none): return location for the minification + * filter, or %NULL + * @mag_filter: (out) (allow-none): return location for the magnification + * filter, or %NULL + * + * Retrieves the values set using clutter_actor_set_content_scaling_filters(). + * + * Since: 1.10 + */ +void +clutter_actor_get_content_scaling_filters (ClutterActor *self, + ClutterScalingFilter *min_filter, + ClutterScalingFilter *mag_filter) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + if (min_filter != NULL) + *min_filter = self->priv->min_filter; + + if (mag_filter != NULL) + *mag_filter = self->priv->mag_filter; +} + +/* + * clutter_actor_queue_compute_expand: + * @self: a #ClutterActor + * + * Invalidates the needs_x_expand and needs_y_expand flags on @self + * and its parents up to the top-level actor. + * + * This function also queues a relayout if anything changed. + */ +static inline void +clutter_actor_queue_compute_expand (ClutterActor *self) +{ + ClutterActor *parent; + gboolean changed; + + if (self->priv->needs_compute_expand) + return; + + changed = FALSE; + parent = self; + while (parent != NULL) + { + if (!parent->priv->needs_compute_expand) + { + parent->priv->needs_compute_expand = TRUE; + changed = TRUE; + } + + parent = parent->priv->parent; + } + + if (changed) + clutter_actor_queue_relayout (self); +} + +/** + * clutter_actor_set_x_expand: + * @self: a #ClutterActor + * @expand: whether the actor should expand horizontally + * + * Sets whether a #ClutterActor should expand horizontally; this means + * that layout manager should allocate extra space for the actor, if + * possible. + * + * Setting an actor to expand will also make all its parent expand, so + * that it's possible to build an actor tree and only set this flag on + * its leaves and not on every single actor. + * + * Since: 1.12 + */ +void +clutter_actor_set_x_expand (ClutterActor *self, + gboolean expand) +{ + ClutterLayoutInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + expand = !!expand; + + info = _clutter_actor_get_layout_info (self); + if (info->x_expand != expand) + { + info->x_expand = expand; + + self->priv->x_expand_set = TRUE; + + clutter_actor_queue_compute_expand (self); + + g_object_notify_by_pspec (G_OBJECT (self), + obj_props[PROP_X_EXPAND]); + } +} + +/** + * clutter_actor_get_x_expand: + * @self: a #ClutterActor + * + * Retrieves the value set with clutter_actor_set_x_expand(). + * + * See also: clutter_actor_needs_expand() + * + * Return value: %TRUE if the actor has been set to expand + * + * Since: 1.12 + */ +gboolean +clutter_actor_get_x_expand (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); + + return _clutter_actor_get_layout_info_or_defaults (self)->x_expand; +} + +/** + * clutter_actor_set_y_expand: + * @self: a #ClutterActor + * @expand: whether the actor should expand vertically + * + * Sets whether a #ClutterActor should expand horizontally; this means + * that layout manager should allocate extra space for the actor, if + * possible. + * + * Setting an actor to expand will also make all its parent expand, so + * that it's possible to build an actor tree and only set this flag on + * its leaves and not on every single actor. + * + * Since: 1.12 + */ +void +clutter_actor_set_y_expand (ClutterActor *self, + gboolean expand) +{ + ClutterLayoutInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + expand = !!expand; + + info = _clutter_actor_get_layout_info (self); + if (info->y_expand != expand) + { + info->y_expand = expand; + + self->priv->y_expand_set = TRUE; + + clutter_actor_queue_compute_expand (self); + + g_object_notify_by_pspec (G_OBJECT (self), + obj_props[PROP_Y_EXPAND]); + } +} + +/** + * clutter_actor_get_y_expand: + * @self: a #ClutterActor + * + * Retrieves the value set with clutter_actor_set_y_expand(). + * + * See also: clutter_actor_needs_expand() + * + * Return value: %TRUE if the actor has been set to expand + * + * Since: 1.12 + */ +gboolean +clutter_actor_get_y_expand (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); + + return _clutter_actor_get_layout_info_or_defaults (self)->y_expand; +} + +static void +clutter_actor_compute_expand_recursive (ClutterActor *self, + gboolean *x_expand_p, + gboolean *y_expand_p) +{ + ClutterActorIter iter; + ClutterActor *child; + gboolean x_expand, y_expand; + + x_expand = y_expand = FALSE; + + /* note that we don't recurse into children if we're already set to expand; + * this avoids traversing the whole actor tree, even if it may lead to some + * child left with the needs_compute_expand flag set. + */ + clutter_actor_iter_init (&iter, self); + while (clutter_actor_iter_next (&iter, &child)) + { + x_expand = x_expand || + clutter_actor_needs_expand (child, CLUTTER_ORIENTATION_HORIZONTAL); + + y_expand = y_expand || + clutter_actor_needs_expand (child, CLUTTER_ORIENTATION_VERTICAL); + } + + *x_expand_p = x_expand; + *y_expand_p = y_expand; +} + +static void +clutter_actor_compute_expand (ClutterActor *self) +{ + if (self->priv->needs_compute_expand) + { + const ClutterLayoutInfo *info; + gboolean x_expand, y_expand; + + info = _clutter_actor_get_layout_info_or_defaults (self); + + if (self->priv->x_expand_set) + x_expand = info->x_expand; + else + x_expand = FALSE; + + if (self->priv->y_expand_set) + y_expand = info->y_expand; + else + y_expand = FALSE; + + /* we don't need to recurse down to the children if the + * actor has been forcibly set to expand + */ + if (!(self->priv->x_expand_set && self->priv->y_expand_set)) + { + if (self->priv->n_children != 0) + { + gboolean *x_expand_p, *y_expand_p; + gboolean ignored = FALSE; + + x_expand_p = self->priv->x_expand_set ? &ignored : &x_expand; + y_expand_p = self->priv->y_expand_set ? &ignored : &y_expand; + + clutter_actor_compute_expand_recursive (self, + x_expand_p, + y_expand_p); + } + } + + self->priv->needs_compute_expand = FALSE; + self->priv->needs_x_expand = (x_expand != FALSE); + self->priv->needs_y_expand = (y_expand != FALSE); + } +} + +/** + * clutter_actor_needs_expand: + * @self: a #ClutterActor + * @orientation: the direction of expansion + * + * Checks whether an actor, or any of its children, is set to expand + * horizontally or vertically. + * + * This function should only be called by layout managers that can + * assign extra space to their children. + * + * If you want to know whether the actor was explicitly set to expand, + * use clutter_actor_get_x_expand() or clutter_actor_get_y_expand(). + * + * Return value: %TRUE if the actor should expand + * + * Since: 1.12 + */ +gboolean +clutter_actor_needs_expand (ClutterActor *self, + ClutterOrientation orientation) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); + + if (!CLUTTER_ACTOR_IS_VISIBLE (self)) + return FALSE; + + if (CLUTTER_ACTOR_IN_DESTRUCTION (self)) + return FALSE; + + clutter_actor_compute_expand (self); + + switch (orientation) + { + case CLUTTER_ORIENTATION_HORIZONTAL: + return self->priv->needs_x_expand; + + case CLUTTER_ORIENTATION_VERTICAL: + return self->priv->needs_y_expand; + } + + return FALSE; +} + +/** + * clutter_actor_set_content_repeat: + * @self: a #ClutterActor + * @repeat: the repeat policy + * + * Sets the policy for repeating the #ClutterActor:content of a + * #ClutterActor. The behaviour is deferred to the #ClutterContent + * implementation. + * + * Since: 1.12 + */ +void +clutter_actor_set_content_repeat (ClutterActor *self, + ClutterContentRepeat repeat) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + if (self->priv->content_repeat == repeat) + return; + + self->priv->content_repeat = repeat; + + clutter_actor_queue_redraw (self); +} + +/** + * clutter_actor_get_content_repeat: + * @self: a #ClutterActor + * + * Retrieves the repeat policy for a #ClutterActor set by + * clutter_actor_set_content_repeat(). + * + * Return value: the content repeat policy + * + * Since: 1.12 + */ +ClutterContentRepeat +clutter_actor_get_content_repeat (ClutterActor *self) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), CLUTTER_REPEAT_NONE); + + return self->priv->content_repeat; +} + +void +_clutter_actor_handle_event (ClutterActor *self, + const ClutterEvent *event) +{ + GPtrArray *event_tree; + ClutterActor *iter; + gboolean is_key_event; + gint i = 0; + + /* XXX - for historical reasons that are now lost in the mists of time, + * key events are delivered regardless of whether an actor is set as + * reactive; this should be changed for 2.0. + */ + is_key_event = event->type == CLUTTER_KEY_PRESS || + event->type == CLUTTER_KEY_RELEASE; + + event_tree = g_ptr_array_sized_new (64); + g_ptr_array_set_free_func (event_tree, (GDestroyNotify) g_object_unref); + + /* build the list of of emitters for the event */ + iter = self; + while (iter != NULL) + { + ClutterActor *parent = iter->priv->parent; + + if (CLUTTER_ACTOR_IS_REACTIVE (iter) || /* an actor must be reactive */ + parent == NULL || /* unless it's the stage */ + is_key_event) /* or this is a key event */ + { + /* keep a reference on the actor, so that it remains valid + * for the duration of the signal emission + */ + g_ptr_array_add (event_tree, g_object_ref (iter)); + } + + iter = parent; + } + + /* Capture: from top-level downwards */ + for (i = event_tree->len - 1; i >= 0; i--) + if (clutter_actor_event (g_ptr_array_index (event_tree, i), event, TRUE)) + goto done; + + /* Bubble: from source upwards */ + for (i = 0; i < event_tree->len; i++) + if (clutter_actor_event (g_ptr_array_index (event_tree, i), event, FALSE)) + goto done; + +done: + g_ptr_array_free (event_tree, TRUE); +} + +static void +clutter_actor_set_child_transform_internal (ClutterActor *self, + const ClutterMatrix *transform) +{ + ClutterTransformInfo *info = _clutter_actor_get_transform_info (self); + ClutterActorIter iter; + ClutterActor *child; + GObject *obj; + gboolean was_set = info->child_transform_set; + + clutter_matrix_init_from_matrix (&info->child_transform, transform); + + /* if it's the identity matrix, we need to toggle the boolean flag */ + info->child_transform_set = !cogl_matrix_is_identity (transform); + + /* we need to reset the transform_valid flag on each child */ + clutter_actor_iter_init (&iter, self); + while (clutter_actor_iter_next (&iter, &child)) + child->priv->transform_valid = FALSE; + + clutter_actor_queue_redraw (self); + + obj = G_OBJECT (self); + g_object_notify_by_pspec (obj, obj_props[PROP_CHILD_TRANSFORM]); + + if (was_set != info->child_transform_set) + g_object_notify_by_pspec (obj, obj_props[PROP_CHILD_TRANSFORM_SET]); +} + +/** + * clutter_actor_set_child_transform: + * @self: a #ClutterActor + * @transform: (allow-none): a #ClutterMatrix, or %NULL + * + * Sets the transformation matrix to be applied to all the children + * of @self prior to their own transformations. The default child + * transformation is the identity matrix. + * + * If @transform is %NULL, the child transform will be unset. + * + * The #ClutterActor:child-transform property is animatable. + * + * Since: 1.12 + */ +void +clutter_actor_set_child_transform (ClutterActor *self, + const ClutterMatrix *transform) +{ + const ClutterTransformInfo *info; + ClutterMatrix new_transform; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + info = _clutter_actor_get_transform_info_or_defaults (self); + + if (transform != NULL) + clutter_matrix_init_from_matrix (&new_transform, transform); + else + clutter_matrix_init_identity (&new_transform); + + _clutter_actor_create_transition (self, obj_props[PROP_CHILD_TRANSFORM], + &info->child_transform, + &new_transform); +} + +/** + * clutter_actor_get_child_transform: + * @self: a #ClutterActor + * @transform: (out caller-allocates): a #ClutterMatrix + * + * Retrieves the child transformation matrix set using + * clutter_actor_set_child_transform(); if none is currently set, + * the @transform matrix will be initialized to the identity matrix. + * + * Since: 1.12 + */ +void +clutter_actor_get_child_transform (ClutterActor *self, + ClutterMatrix *transform) +{ + const ClutterTransformInfo *info; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (transform != NULL); + + info = _clutter_actor_get_transform_info_or_defaults (self); + + if (info->child_transform_set) + clutter_matrix_init_from_matrix (transform, &info->child_transform); + else + clutter_matrix_init_identity (transform); +} + +static void +clutter_actor_push_in_cloned_branch (ClutterActor *self) +{ + ClutterActor *iter; + + for (iter = self->priv->first_child; + iter != NULL; + iter = iter->priv->next_sibling) + clutter_actor_push_in_cloned_branch (iter); + + self->priv->in_cloned_branch += 1; +} + +static void +clutter_actor_pop_in_cloned_branch (ClutterActor *self) +{ + ClutterActor *iter; + + self->priv->in_cloned_branch -= 1; + + for (iter = self->priv->first_child; + iter != NULL; + iter = iter->priv->next_sibling) + clutter_actor_pop_in_cloned_branch (iter); +} + +void +_clutter_actor_attach_clone (ClutterActor *actor, + ClutterActor *clone) +{ + ClutterActorPrivate *priv = actor->priv; + + g_assert (clone != NULL); + + if (priv->clones == NULL) + priv->clones = g_hash_table_new (NULL, NULL); + + g_hash_table_add (priv->clones, clone); + + clutter_actor_push_in_cloned_branch (actor); +} + +void +_clutter_actor_detach_clone (ClutterActor *actor, + ClutterActor *clone) +{ + ClutterActorPrivate *priv = actor->priv; + + g_assert (clone != NULL); + + if (priv->clones == NULL || + g_hash_table_lookup (priv->clones, clone) == NULL) + return; + + clutter_actor_pop_in_cloned_branch (actor); + + g_hash_table_remove (priv->clones, clone); + + if (g_hash_table_size (priv->clones) == 0) + { + g_hash_table_unref (priv->clones); + priv->clones = NULL; + } +} + +void +_clutter_actor_queue_redraw_on_clones (ClutterActor *self) +{ + ClutterActorPrivate *priv = self->priv; + GHashTableIter iter; + gpointer key; + + if (priv->clones == NULL) + return; + + g_hash_table_iter_init (&iter, priv->clones); + while (g_hash_table_iter_next (&iter, &key, NULL)) + clutter_actor_queue_redraw (key); +} + +void +_clutter_actor_queue_relayout_on_clones (ClutterActor *self) +{ + ClutterActorPrivate *priv = self->priv; + GHashTableIter iter; + gpointer key; + + if (priv->clones == NULL) + return; + + g_hash_table_iter_init (&iter, priv->clones); + while (g_hash_table_iter_next (&iter, &key, NULL)) + clutter_actor_queue_relayout (key); +} + +/** + * clutter_actor_has_mapped_clones: + * @self: a #ClutterActor + * + * Returns whether a #ClutterActor has any mapped clones. + * + * Return: %TRUE if the actor has mapped clones, and %FALSE otherwise + * + * Since: 1.16 + */ +gboolean +clutter_actor_has_mapped_clones (ClutterActor *self) +{ + ClutterActorPrivate *priv; + GHashTableIter iter; + gpointer key; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); + + priv = self->priv; + + if (priv->clones == NULL) + return FALSE; + + g_hash_table_iter_init (&iter, priv->clones); + while (g_hash_table_iter_next (&iter, &key, NULL)) + { + if (CLUTTER_ACTOR_IS_MAPPED (key)) + return TRUE; + } + + return FALSE; +} + +CoglFramebuffer * +_clutter_actor_get_active_framebuffer (ClutterActor *self) +{ + ClutterStage *stage; + + if (!CLUTTER_ACTOR_IN_PAINT (self)) + { + g_critical ("The active framebuffer of actor '%s' can only be " + "retrieved during the paint sequence. Please, check " + "your code.", + _clutter_actor_get_debug_name (self)); + return NULL; + } + + stage = (ClutterStage *) _clutter_actor_get_stage_internal (self); + if (stage == NULL) + { + g_critical ("The active framebuffer of actor '%s' is only available " + "if the actor is associated to a ClutterStage.", + _clutter_actor_get_debug_name (self)); + return NULL; + } + + return _clutter_stage_get_active_framebuffer (stage); +} + +static void +clutter_actor_child_model__items_changed (GListModel *model, + guint position, + guint removed, + guint added, + gpointer user_data) +{ + ClutterActor *parent = user_data; + ClutterActorPrivate *priv = parent->priv; + guint i; + + while (removed--) + { + ClutterActor *child = clutter_actor_get_child_at_index (parent, position); + clutter_actor_destroy (child); + } + + for (i = 0; i < added; i++) + { + GObject *item = g_list_model_get_item (model, position + i); + ClutterActor *child = priv->create_child_func (item, priv->create_child_data); + + /* The actor returned by the function can have a floating reference, + * if the implementation is in pure C, or have a full reference, usually + * the case for language bindings. To avoid leaking references, we + * try to assume ownership of the instance, and release the reference + * at the end unconditionally, leaving the only reference to the actor + * itself. + */ + if (g_object_is_floating (child)) + g_object_ref_sink (child); + + clutter_actor_insert_child_at_index (parent, child, position + i); + + g_object_unref (child); + g_object_unref (item); + } +} + +/** + * clutter_actor_bind_model: + * @self: a #ClutterActor + * @model: (nullable): a #GListModel + * @create_child_func: a function that creates #ClutterActor instances + * from the contents of the @model + * @user_data: user data passed to @create_child_func + * @notify: function called when unsetting the @model + * + * Binds a #GListModel to a #ClutterActor. + * + * If the #ClutterActor was already bound to a #GListModel, the previous + * binding is destroyed. + * + * The existing children of #ClutterActor are destroyed when setting a + * model, and new children are created and added, representing the contents + * of the @model. The #ClutterActor is updated whenever the @model changes. + * If @model is %NULL, the #ClutterActor is left empty. + * + * When a #ClutterActor is bound to a model, adding and removing children + * directly is undefined behaviour. + * + * Since: 1.24 + */ +void +clutter_actor_bind_model (ClutterActor *self, + GListModel *model, + ClutterActorCreateChildFunc create_child_func, + gpointer user_data, + GDestroyNotify notify) +{ + ClutterActorPrivate *priv = clutter_actor_get_instance_private (self); + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (model == NULL || G_IS_LIST_MODEL (model)); + g_return_if_fail (model == NULL || create_child_func != NULL); + + if (priv->child_model != NULL) + { + if (priv->create_child_notify != NULL) + priv->create_child_notify (priv->create_child_data); + + g_signal_handlers_disconnect_by_func (priv->child_model, + clutter_actor_child_model__items_changed, + self); + g_clear_object (&priv->child_model); + priv->create_child_func = NULL; + priv->create_child_data = NULL; + priv->create_child_notify = NULL; + } + + clutter_actor_destroy_all_children (self); + + if (model == NULL) + return; + + priv->child_model = g_object_ref (model); + priv->create_child_func = create_child_func; + priv->create_child_data = user_data; + priv->create_child_notify = notify; + + g_signal_connect (priv->child_model, "items-changed", + G_CALLBACK (clutter_actor_child_model__items_changed), + self); + + clutter_actor_child_model__items_changed (priv->child_model, + 0, + 0, + g_list_model_get_n_items (priv->child_model), + self); +} + +typedef struct { + GType child_type; + GArray *props; +} BindClosure; + +typedef struct { + const char *model_property; + const char *child_property; + GBindingFlags flags; +} BindProperty; + +static void +bind_closure_free (gpointer data_) +{ + BindClosure *data = data_; + + if (data == NULL) + return; + + g_array_unref (data->props); + g_slice_free (BindClosure, data); +} + +static ClutterActor * +bind_child_with_properties (gpointer item, + gpointer data_) +{ + BindClosure *data = data_; + ClutterActor *res; + guint i; + + res = g_object_new (data->child_type, NULL); + + for (i = 0; i < data->props->len; i++) + { + const BindProperty *prop = &g_array_index (data->props, BindProperty, i); + + g_object_bind_property (item, prop->model_property, + res, prop->child_property, + prop->flags); + } + + return res; +} + +/** + * clutter_actor_bind_model_with_properties: + * @self: a #ClutterActor + * @model: a #GListModel + * @child_type: the type of #ClutterActor to use when creating + * children mapping to items inside the @model + * @first_model_property: the first property of @model to bind + * @...: tuples of property names on the @model, on the child, and the + * #GBindingFlags used to bind them, terminated by %NULL + * + * Binds a #GListModel to a #ClutterActor. + * + * Unlike clutter_actor_bind_model(), this function automatically creates + * a child #ClutterActor of type @child_type, and binds properties on the + * items inside the @model to the corresponding properties on the child, + * for instance: + * + * |[ + * clutter_actor_bind_model_with_properties (actor, model, + * MY_TYPE_CHILD_VIEW, + * "label", "text", G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE, + * "icon", "image", G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE, + * "selected", "selected", G_BINDING_BIDIRECTIONAL, + * "active", "active", G_BINDING_BIDIRECTIONAL, + * NULL); + * ]| + * + * is the equivalent of calling clutter_actor_bind_model() with a + * #ClutterActorCreateChildFunc of: + * + * |[ + * ClutterActor *res = g_object_new (MY_TYPE_CHILD_VIEW, NULL); + * + * g_object_bind_property (item, "label", res, "text", G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE); + * g_object_bind_property (item, "icon", res, "image", G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE); + * g_object_bind_property (item, "selected", res, "selected", G_BINDING_BIDIRECTIONAL); + * g_object_bind_property (item, "active", res, "active", G_BINDING_BIDIRECTIONAL); + * + * return res; + * ]| + * + * If the #ClutterActor was already bound to a #GListModel, the previous + * binding is destroyed. + * + * When a #ClutterActor is bound to a model, adding and removing children + * directly is undefined behaviour. + * + * See also: clutter_actor_bind_model() + * + * Since: 1.24 + */ +void +clutter_actor_bind_model_with_properties (ClutterActor *self, + GListModel *model, + GType child_type, + const char *first_model_property, + ...) +{ + va_list args; + BindClosure *clos; + const char *model_property; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (G_IS_LIST_MODEL (model)); + g_return_if_fail (g_type_is_a (child_type, CLUTTER_TYPE_ACTOR)); + + clos = g_slice_new0 (BindClosure); + clos->child_type = child_type; + clos->props = g_array_new (FALSE, FALSE, sizeof (BindProperty)); + + va_start (args, first_model_property); + model_property = first_model_property; + while (model_property != NULL) + { + const char *child_property = va_arg (args, char *); + GBindingFlags binding_flags = va_arg (args, guint); + BindProperty bind; + + bind.model_property = g_intern_string (model_property); + bind.child_property = g_intern_string (child_property); + bind.flags = binding_flags; + + g_array_append_val (clos->props, bind); + + model_property = va_arg (args, char *); + } + + clutter_actor_bind_model (self, model, bind_child_with_properties, clos, bind_closure_free); +} + +/*< private > + * clutter_actor_create_texture_paint_node: + * @self: a #ClutterActor + * @texture: a #CoglTexture + * + * Creates a #ClutterPaintNode initialized using the state of the + * given #ClutterActor, ready to be used inside the implementation + * of the #ClutterActorClass.paint_node virtual function. + * + * The returned paint node has the geometry set to the size of the + * #ClutterActor:content-box property; it uses the filters specified + * in the #ClutterActor:minification-filter and #ClutterActor:magnification-filter + * properties; and respects the #ClutterActor:content-repeat property. + * + * Returns: (transfer full): The newly created #ClutterPaintNode + * + * Since: 1.24 + */ +ClutterPaintNode * +clutter_actor_create_texture_paint_node (ClutterActor *self, + CoglTexture *texture) +{ + ClutterActorPrivate *priv = clutter_actor_get_instance_private (self); + ClutterPaintNode *node; + ClutterActorBox box; + ClutterColor color; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + g_return_val_if_fail (texture != NULL, NULL); + + clutter_actor_get_content_box (self, &box); + + /* ClutterTextureNode will premultiply the blend color, so we + * want it to be white with the paint opacity + */ + color.red = 255; + color.green = 255; + color.blue = 255; + color.alpha = clutter_actor_get_paint_opacity_internal (self); + + node = clutter_texture_node_new (texture, &color, priv->min_filter, priv->mag_filter); + clutter_paint_node_set_name (node, "Texture"); + + if (priv->content_repeat == CLUTTER_REPEAT_NONE) + clutter_paint_node_add_rectangle (node, &box); + else + { + float t_w = 1.f, t_h = 1.f; + + if ((priv->content_repeat & CLUTTER_REPEAT_X_AXIS) != FALSE) + t_w = (box.x2 - box.x1) / cogl_texture_get_width (texture); + + if ((priv->content_repeat & CLUTTER_REPEAT_Y_AXIS) != FALSE) + t_h = (box.y2 - box.y1) / cogl_texture_get_height (texture); + + clutter_paint_node_add_texture_rectangle (node, &box, + 0.f, 0.f, + t_w, t_h); + } + + return node; +} diff --git a/clutter/clutter/clutter-actor.h b/clutter/clutter/clutter-actor.h new file mode 100644 index 0000000..0c5a08c --- /dev/null +++ b/clutter/clutter/clutter-actor.h @@ -0,0 +1,901 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006, 2007, 2008 OpenedHand Ltd + * Copyright (C) 2009, 2010 Intel Corp + * + * 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 . + */ + +#ifndef __CLUTTER_ACTOR_H__ +#define __CLUTTER_ACTOR_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +/* clutter-actor.h */ + +#include +#include +#include + +#include + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_ACTOR (clutter_actor_get_type ()) +#define CLUTTER_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ACTOR, ClutterActor)) +#define CLUTTER_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_ACTOR, ClutterActorClass)) +#define CLUTTER_IS_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ACTOR)) +#define CLUTTER_IS_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_ACTOR)) +#define CLUTTER_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_ACTOR, ClutterActorClass)) + +/** + * CLUTTER_ACTOR_SET_FLAGS: + * @a: a #ClutterActor + * @f: the #ClutterActorFlags to set + * + * Sets the given flags on a #ClutterActor + * + * Deprecated: 1.24: Changing flags directly is heavily discouraged in + * newly written code. #ClutterActor will take care of setting the + * internal state. + */ +#define CLUTTER_ACTOR_SET_FLAGS(a,f) \ + CLUTTER_MACRO_DEPRECATED_IN_1_24 \ + (((ClutterActor*)(a))->flags |= (f)) + +/** + * CLUTTER_ACTOR_UNSET_FLAGS: + * @a: a #ClutterActor + * @f: the #ClutterActorFlags to unset + * + * Unsets the given flags on a #ClutterActor + * + * Deprecated: 1.24: Changing flags directly is heavily discouraged in + * newly written code. #ClutterActor will take care of unsetting the + * internal state. + */ +#define CLUTTER_ACTOR_UNSET_FLAGS(a,f) \ + CLUTTER_MACRO_DEPRECATED_IN_1_24 \ + (((ClutterActor*)(a))->flags &= ~(f)) + +#define CLUTTER_ACTOR_IS_MAPPED(a) \ + CLUTTER_MACRO_DEPRECATED_IN_1_24_FOR ("Deprecated macro. Use clutter_actor_is_mapped instead") \ + ((((ClutterActor*)(a))->flags & CLUTTER_ACTOR_MAPPED) != FALSE) + +#define CLUTTER_ACTOR_IS_REALIZED(a) \ + CLUTTER_MACRO_DEPRECATED_IN_1_24_FOR ("Deprecated macro. Use clutter_actor_is_realized instead") \ + ((((ClutterActor*)(a))->flags & CLUTTER_ACTOR_REALIZED) != FALSE) + +#define CLUTTER_ACTOR_IS_VISIBLE(a) \ + CLUTTER_MACRO_DEPRECATED_IN_1_24_FOR ("Deprecated macro. Use clutter_actor_is_visible instead") \ + ((((ClutterActor*)(a))->flags & CLUTTER_ACTOR_VISIBLE) != FALSE) + +#define CLUTTER_ACTOR_IS_REACTIVE(a) \ + CLUTTER_MACRO_DEPRECATED_IN_1_24_FOR ("Deprecated macro. Use clutter_actor_get_reactive instead") \ + ((((ClutterActor*)(a))->flags & CLUTTER_ACTOR_REACTIVE) != FALSE) + +typedef struct _ClutterActorClass ClutterActorClass; +typedef struct _ClutterActorPrivate ClutterActorPrivate; + +/** + * ClutterCallback: + * @actor: a #ClutterActor + * @data: (closure): user data + * + * Generic callback + */ +typedef void (*ClutterCallback) (ClutterActor *actor, + gpointer data); + +/** + * CLUTTER_CALLBACK: + * @f: a function + * + * Convenience macro to cast a function to #ClutterCallback + */ +#define CLUTTER_CALLBACK(f) ((ClutterCallback) (f)) + +/** + * ClutterActor: + * @flags: #ClutterActorFlags + * + * Base class for actors. + */ +struct _ClutterActor +{ + /*< private >*/ + GInitiallyUnowned parent_instance; + + /*< public >*/ + guint32 flags; + + /*< private >*/ + guint32 private_flags; + + ClutterActorPrivate *priv; +}; + +/** + * ClutterActorClass: + * @show: signal class handler for #ClutterActor::show; it must chain + * up to the parent's implementation + * @show_all: virtual function for containers and composite actors, to + * determine which children should be shown when calling + * clutter_actor_show_all() on the actor. Defaults to calling + * clutter_actor_show(). This virtual function is deprecated and it + * should not be overridden. + * @hide: signal class handler for #ClutterActor::hide; it must chain + * up to the parent's implementation + * @hide_all: virtual function for containers and composite actors, to + * determine which children should be shown when calling + * clutter_actor_hide_all() on the actor. Defaults to calling + * clutter_actor_hide(). This virtual function is deprecated and it + * should not be overridden. + * @realize: virtual function, used to allocate resources for the actor; + * it should chain up to the parent's implementation. This virtual + * function is deprecated and should not be overridden in newly + * written code. + * @unrealize: virtual function, used to deallocate resources allocated + * in ::realize; it should chain up to the parent's implementation. This + * function is deprecated and should not be overridden in newly + * written code. + * @map: virtual function for containers and composite actors, to + * map their children; it must chain up to the parent's implementation. + * Overriding this function is optional. + * @unmap: virtual function for containers and composite actors, to + * unmap their children; it must chain up to the parent's implementation. + * Overriding this function is optional. + * @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 + * clutter_actor_get_preferred_width() + * @get_preferred_height: virtual function, used when querying the minimum + * and natural heights of an actor for a given width; it is used by + * clutter_actor_get_preferred_height() + * @allocate: virtual function, used when settings the coordinates of an + * actor; it is used by clutter_actor_allocate(); it must chain up to + * the parent's implementation, or call clutter_actor_set_allocation() + * @apply_transform: virtual function, used when applying the transformations + * to an actor before painting it or when transforming coordinates or + * the allocation; it must chain up to the parent's implementation + * @parent_set: signal class handler for the #ClutterActor::parent-set + * @destroy: signal class handler for #ClutterActor::destroy. It must + * chain up to the parent's implementation + * @pick: virtual function, used to draw an outline of the actor with + * the given color + * @queue_redraw: class handler for #ClutterActor::queue-redraw + * @event: class handler for #ClutterActor::event + * @button_press_event: class handler for #ClutterActor::button-press-event + * @button_release_event: class handler for + * #ClutterActor::button-release-event + * @scroll_event: signal class closure for #ClutterActor::scroll-event + * @key_press_event: signal class closure for #ClutterActor::key-press-event + * @key_release_event: signal class closure for + * #ClutterActor::key-release-event + * @motion_event: signal class closure for #ClutterActor::motion-event + * @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 + * @key_focus_in: signal class closure for #ClutterActor::key-focus-in + * @key_focus_out: signal class closure for #ClutterActor::key-focus-out + * @queue_relayout: class handler for #ClutterActor::queue-relayout + * @get_accessible: virtual function, returns the accessible object that + * describes the actor to an assistive technology. + * @get_paint_volume: virtual function, for sub-classes to define their + * #ClutterPaintVolume + * @has_overlaps: virtual function for + * sub-classes to advertise whether they need an offscreen redirect + * to get the correct opacity. See + * clutter_actor_set_offscreen_redirect() for details. + * @paint_node: virtual function for creating paint nodes and attaching + * them to the render tree + * @touch_event: signal class closure for #ClutterActor::touch-event + * + * Base class for actors. + */ +struct _ClutterActorClass +{ + /*< private >*/ + GInitiallyUnownedClass parent_class; + + /*< public >*/ + void (* show) (ClutterActor *self); + void (* show_all) (ClutterActor *self); + void (* hide) (ClutterActor *self); + void (* hide_all) (ClutterActor *self); + void (* realize) (ClutterActor *self); + void (* unrealize) (ClutterActor *self); + void (* map) (ClutterActor *self); + void (* unmap) (ClutterActor *self); + void (* paint) (ClutterActor *self); + void (* parent_set) (ClutterActor *actor, + ClutterActor *old_parent); + + void (* destroy) (ClutterActor *self); + void (* pick) (ClutterActor *actor, + const ClutterColor *color); + + void (* queue_redraw) (ClutterActor *actor, + ClutterActor *leaf_that_queued); + + /* size negotiation */ + void (* get_preferred_width) (ClutterActor *self, + gfloat for_height, + gfloat *min_width_p, + gfloat *natural_width_p); + void (* get_preferred_height) (ClutterActor *self, + gfloat for_width, + gfloat *min_height_p, + gfloat *natural_height_p); + void (* allocate) (ClutterActor *self, + const ClutterActorBox *box, + ClutterAllocationFlags flags); + + /* transformations */ + void (* apply_transform) (ClutterActor *actor, + ClutterMatrix *matrix); + + /* event signals */ + gboolean (* event) (ClutterActor *actor, + ClutterEvent *event); + gboolean (* button_press_event) (ClutterActor *actor, + ClutterButtonEvent *event); + gboolean (* button_release_event) (ClutterActor *actor, + ClutterButtonEvent *event); + gboolean (* scroll_event) (ClutterActor *actor, + ClutterScrollEvent *event); + gboolean (* key_press_event) (ClutterActor *actor, + ClutterKeyEvent *event); + gboolean (* key_release_event) (ClutterActor *actor, + ClutterKeyEvent *event); + gboolean (* motion_event) (ClutterActor *actor, + ClutterMotionEvent *event); + gboolean (* enter_event) (ClutterActor *actor, + ClutterCrossingEvent *event); + gboolean (* leave_event) (ClutterActor *actor, + ClutterCrossingEvent *event); + gboolean (* captured_event) (ClutterActor *actor, + ClutterEvent *event); + void (* key_focus_in) (ClutterActor *actor); + void (* key_focus_out) (ClutterActor *actor); + + void (* queue_relayout) (ClutterActor *self); + + /* accessibility support */ + AtkObject * (* get_accessible) (ClutterActor *self); + + gboolean (* get_paint_volume) (ClutterActor *actor, + ClutterPaintVolume *volume); + + gboolean (* has_overlaps) (ClutterActor *self); + + void (* paint_node) (ClutterActor *self, + ClutterPaintNode *root); + + gboolean (* touch_event) (ClutterActor *self, + ClutterTouchEvent *event); + + /*< private >*/ + /* padding for future expansion */ + gpointer _padding_dummy[26]; +}; + +/** + * ClutterActorIter: + * + * An iterator structure that allows to efficiently iterate over a + * section of the scene graph. + * + * The contents of the #ClutterActorIter structure + * are private and should only be accessed using the provided API. + * + * Since: 1.10 + */ +struct _ClutterActorIter +{ + /*< private >*/ + gpointer CLUTTER_PRIVATE_FIELD (dummy1); + gpointer CLUTTER_PRIVATE_FIELD (dummy2); + gpointer CLUTTER_PRIVATE_FIELD (dummy3); + gint CLUTTER_PRIVATE_FIELD (dummy4); + gpointer CLUTTER_PRIVATE_FIELD (dummy5); +}; + +CLUTTER_AVAILABLE_IN_ALL +GType clutter_actor_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_10 +ClutterActor * clutter_actor_new (void); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_set_flags (ClutterActor *self, + ClutterActorFlags flags); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_unset_flags (ClutterActor *self, + ClutterActorFlags flags); +CLUTTER_AVAILABLE_IN_ALL +ClutterActorFlags clutter_actor_get_flags (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_show (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_hide (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_realize (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_unrealize (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_map (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_unmap (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_paint (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_continue_paint (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_queue_redraw (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_queue_redraw_with_clip (ClutterActor *self, + const cairo_rectangle_int_t *clip); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_queue_relayout (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_destroy (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_set_name (ClutterActor *self, + const gchar *name); +CLUTTER_AVAILABLE_IN_ALL +const gchar * clutter_actor_get_name (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +AtkObject * clutter_actor_get_accessible (ClutterActor *self); + +CLUTTER_AVAILABLE_IN_1_24 +gboolean clutter_actor_is_visible (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_24 +gboolean clutter_actor_is_mapped (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_24 +gboolean clutter_actor_is_realized (ClutterActor *self); + +/* Size negotiation */ +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_set_request_mode (ClutterActor *self, + ClutterRequestMode mode); +CLUTTER_AVAILABLE_IN_ALL +ClutterRequestMode clutter_actor_get_request_mode (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_get_preferred_width (ClutterActor *self, + gfloat for_height, + gfloat *min_width_p, + gfloat *natural_width_p); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_get_preferred_height (ClutterActor *self, + gfloat for_width, + gfloat *min_height_p, + gfloat *natural_height_p); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_get_preferred_size (ClutterActor *self, + gfloat *min_width_p, + gfloat *min_height_p, + gfloat *natural_width_p, + gfloat *natural_height_p); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_allocate (ClutterActor *self, + const ClutterActorBox *box, + ClutterAllocationFlags flags); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_allocate_preferred_size (ClutterActor *self, + ClutterAllocationFlags flags); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_allocate_available_size (ClutterActor *self, + gfloat x, + gfloat y, + gfloat available_width, + gfloat available_height, + ClutterAllocationFlags flags); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_allocate_align_fill (ClutterActor *self, + const ClutterActorBox *box, + gdouble x_align, + gdouble y_align, + gboolean x_fill, + gboolean y_fill, + ClutterAllocationFlags flags); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_set_allocation (ClutterActor *self, + const ClutterActorBox *box, + ClutterAllocationFlags flags); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_get_allocation_box (ClutterActor *self, + ClutterActorBox *box); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_get_allocation_vertices (ClutterActor *self, + ClutterActor *ancestor, + ClutterVertex verts[]); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_actor_has_allocation (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_set_size (ClutterActor *self, + gfloat width, + gfloat height); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_get_size (ClutterActor *self, + gfloat *width, + gfloat *height); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_set_position (ClutterActor *self, + gfloat x, + gfloat y); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_get_position (ClutterActor *self, + gfloat *x, + gfloat *y); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_actor_get_fixed_position_set (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_set_fixed_position_set (ClutterActor *self, + gboolean is_set); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_move_by (ClutterActor *self, + gfloat dx, + gfloat dy); + +/* Actor geometry */ +CLUTTER_AVAILABLE_IN_ALL +gfloat clutter_actor_get_width (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +gfloat clutter_actor_get_height (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_set_width (ClutterActor *self, + gfloat width); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_set_height (ClutterActor *self, + gfloat height); +CLUTTER_AVAILABLE_IN_ALL +gfloat clutter_actor_get_x (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +gfloat clutter_actor_get_y (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_set_x (ClutterActor *self, + gfloat x); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_set_y (ClutterActor *self, + gfloat y); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_actor_set_z_position (ClutterActor *self, + gfloat z_position); +CLUTTER_AVAILABLE_IN_1_12 +gfloat clutter_actor_get_z_position (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_set_layout_manager (ClutterActor *self, + ClutterLayoutManager *manager); +CLUTTER_AVAILABLE_IN_1_10 +ClutterLayoutManager * clutter_actor_get_layout_manager (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_set_x_align (ClutterActor *self, + ClutterActorAlign x_align); +CLUTTER_AVAILABLE_IN_1_10 +ClutterActorAlign clutter_actor_get_x_align (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_set_y_align (ClutterActor *self, + ClutterActorAlign y_align); +CLUTTER_AVAILABLE_IN_1_10 +ClutterActorAlign clutter_actor_get_y_align (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_set_margin_top (ClutterActor *self, + gfloat margin); +CLUTTER_AVAILABLE_IN_1_10 +gfloat clutter_actor_get_margin_top (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_set_margin_bottom (ClutterActor *self, + gfloat margin); +CLUTTER_AVAILABLE_IN_1_10 +gfloat clutter_actor_get_margin_bottom (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_set_margin_left (ClutterActor *self, + gfloat margin); +CLUTTER_AVAILABLE_IN_1_10 +gfloat clutter_actor_get_margin_left (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_set_margin_right (ClutterActor *self, + gfloat margin); +CLUTTER_AVAILABLE_IN_1_10 +gfloat clutter_actor_get_margin_right (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_set_margin (ClutterActor *self, + const ClutterMargin *margin); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_get_margin (ClutterActor *self, + ClutterMargin *margin); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_actor_set_x_expand (ClutterActor *self, + gboolean expand); +CLUTTER_AVAILABLE_IN_1_12 +gboolean clutter_actor_get_x_expand (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_actor_set_y_expand (ClutterActor *self, + gboolean expand); +CLUTTER_AVAILABLE_IN_1_12 +gboolean clutter_actor_get_y_expand (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_12 +gboolean clutter_actor_needs_expand (ClutterActor *self, + ClutterOrientation orientation); + +/* Paint */ +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_set_clip (ClutterActor *self, + gfloat xoff, + gfloat yoff, + gfloat width, + gfloat height); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_remove_clip (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_actor_has_clip (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_get_clip (ClutterActor *self, + gfloat *xoff, + gfloat *yoff, + gfloat *width, + gfloat *height); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_set_clip_to_allocation (ClutterActor *self, + gboolean clip_set); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_actor_get_clip_to_allocation (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_set_opacity (ClutterActor *self, + guint8 opacity); +CLUTTER_AVAILABLE_IN_ALL +guint8 clutter_actor_get_opacity (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +guint8 clutter_actor_get_paint_opacity (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_actor_get_paint_visibility (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_8 +void clutter_actor_set_offscreen_redirect (ClutterActor *self, + ClutterOffscreenRedirect redirect); +CLUTTER_AVAILABLE_IN_1_8 +ClutterOffscreenRedirect clutter_actor_get_offscreen_redirect (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_actor_should_pick_paint (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_actor_is_in_clone_paint (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_actor_get_paint_box (ClutterActor *self, + ClutterActorBox *box); +CLUTTER_AVAILABLE_IN_1_8 +gboolean clutter_actor_has_overlaps (ClutterActor *self); + +/* Content */ +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_set_content (ClutterActor *self, + ClutterContent *content); +CLUTTER_AVAILABLE_IN_1_10 +ClutterContent * clutter_actor_get_content (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_set_content_gravity (ClutterActor *self, + ClutterContentGravity gravity); +CLUTTER_AVAILABLE_IN_1_10 +ClutterContentGravity clutter_actor_get_content_gravity (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_set_content_scaling_filters (ClutterActor *self, + ClutterScalingFilter min_filter, + ClutterScalingFilter mag_filter); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_get_content_scaling_filters (ClutterActor *self, + ClutterScalingFilter *min_filter, + ClutterScalingFilter *mag_filter); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_actor_set_content_repeat (ClutterActor *self, + ClutterContentRepeat repeat); +CLUTTER_AVAILABLE_IN_1_12 +ClutterContentRepeat clutter_actor_get_content_repeat (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_get_content_box (ClutterActor *self, + ClutterActorBox *box); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_set_background_color (ClutterActor *self, + const ClutterColor *color); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_get_background_color (ClutterActor *self, + ClutterColor *color); +CLUTTER_AVAILABLE_IN_1_6 +const ClutterPaintVolume * clutter_actor_get_paint_volume (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_6 +const ClutterPaintVolume * clutter_actor_get_transformed_paint_volume (ClutterActor *self, + ClutterActor *relative_to_ancestor); +CLUTTER_AVAILABLE_IN_1_10 +const ClutterPaintVolume * clutter_actor_get_default_paint_volume (ClutterActor *self); + +/* Events */ +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_set_reactive (ClutterActor *actor, + gboolean reactive); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_actor_get_reactive (ClutterActor *actor); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_actor_has_key_focus (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_grab_key_focus (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_actor_event (ClutterActor *actor, + const ClutterEvent *event, + gboolean capture); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_actor_has_pointer (ClutterActor *self); + +/* Text */ +CLUTTER_AVAILABLE_IN_ALL +PangoContext * clutter_actor_get_pango_context (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +PangoContext * clutter_actor_create_pango_context (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +PangoLayout * clutter_actor_create_pango_layout (ClutterActor *self, + const gchar *text); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_set_text_direction (ClutterActor *self, + ClutterTextDirection text_dir); +CLUTTER_AVAILABLE_IN_ALL +ClutterTextDirection clutter_actor_get_text_direction (ClutterActor *self); + +/* Actor hierarchy */ +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_add_child (ClutterActor *self, + ClutterActor *child); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_insert_child_at_index (ClutterActor *self, + ClutterActor *child, + gint index_); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_insert_child_above (ClutterActor *self, + ClutterActor *child, + ClutterActor *sibling); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_insert_child_below (ClutterActor *self, + ClutterActor *child, + ClutterActor *sibling); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_replace_child (ClutterActor *self, + ClutterActor *old_child, + ClutterActor *new_child); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_remove_child (ClutterActor *self, + ClutterActor *child); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_remove_all_children (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_destroy_all_children (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_10 +GList * clutter_actor_get_children (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_10 +gint clutter_actor_get_n_children (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_10 +ClutterActor * clutter_actor_get_child_at_index (ClutterActor *self, + gint index_); +CLUTTER_AVAILABLE_IN_1_10 +ClutterActor * clutter_actor_get_previous_sibling (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_10 +ClutterActor * clutter_actor_get_next_sibling (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_10 +ClutterActor * clutter_actor_get_first_child (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_10 +ClutterActor * clutter_actor_get_last_child (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +ClutterActor * clutter_actor_get_parent (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_4 +gboolean clutter_actor_contains (ClutterActor *self, + ClutterActor *descendant); +CLUTTER_AVAILABLE_IN_ALL +ClutterActor* clutter_actor_get_stage (ClutterActor *actor); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_set_child_below_sibling (ClutterActor *self, + ClutterActor *child, + ClutterActor *sibling); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_set_child_above_sibling (ClutterActor *self, + ClutterActor *child, + ClutterActor *sibling); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_set_child_at_index (ClutterActor *self, + ClutterActor *child, + gint index_); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_iter_init (ClutterActorIter *iter, + ClutterActor *root); +CLUTTER_AVAILABLE_IN_1_10 +gboolean clutter_actor_iter_next (ClutterActorIter *iter, + ClutterActor **child); +CLUTTER_AVAILABLE_IN_1_10 +gboolean clutter_actor_iter_prev (ClutterActorIter *iter, + ClutterActor **child); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_iter_remove (ClutterActorIter *iter); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_iter_destroy (ClutterActorIter *iter); +CLUTTER_AVAILABLE_IN_1_12 +gboolean clutter_actor_iter_is_valid (const ClutterActorIter *iter); + +/* Transformations */ +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_actor_is_rotated (ClutterActor *self); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_actor_is_scaled (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_actor_set_pivot_point (ClutterActor *self, + gfloat pivot_x, + gfloat pivot_y); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_actor_get_pivot_point (ClutterActor *self, + gfloat *pivot_x, + gfloat *pivot_y); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_actor_set_pivot_point_z (ClutterActor *self, + gfloat pivot_z); +CLUTTER_AVAILABLE_IN_1_12 +gfloat clutter_actor_get_pivot_point_z (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_actor_set_rotation_angle (ClutterActor *self, + ClutterRotateAxis axis, + gdouble angle); +CLUTTER_AVAILABLE_IN_1_12 +gdouble clutter_actor_get_rotation_angle (ClutterActor *self, + ClutterRotateAxis axis); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_set_scale (ClutterActor *self, + gdouble scale_x, + gdouble scale_y); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_get_scale (ClutterActor *self, + gdouble *scale_x, + gdouble *scale_y); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_actor_set_scale_z (ClutterActor *self, + gdouble scale_z); +CLUTTER_AVAILABLE_IN_1_12 +gdouble clutter_actor_get_scale_z (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_actor_set_translation (ClutterActor *self, + gfloat translate_x, + gfloat translate_y, + gfloat translate_z); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_actor_get_translation (ClutterActor *self, + gfloat *translate_x, + gfloat *translate_y, + gfloat *translate_z); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_actor_set_transform (ClutterActor *self, + const ClutterMatrix *transform); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_actor_get_transform (ClutterActor *self, + ClutterMatrix *transform); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_actor_set_child_transform (ClutterActor *self, + const ClutterMatrix *transform); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_actor_get_child_transform (ClutterActor *self, + ClutterMatrix *transform); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_get_transformed_position (ClutterActor *self, + gfloat *x, + gfloat *y); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_get_transformed_size (ClutterActor *self, + gfloat *width, + gfloat *height); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_actor_transform_stage_point (ClutterActor *self, + gfloat x, + gfloat y, + gfloat *x_out, + gfloat *y_out); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_get_abs_allocation_vertices (ClutterActor *self, + ClutterVertex verts[]); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_apply_transform_to_point (ClutterActor *self, + const ClutterVertex *point, + ClutterVertex *vertex); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_apply_relative_transform_to_point (ClutterActor *self, + ClutterActor *ancestor, + const ClutterVertex *point, + ClutterVertex *vertex); + +/* Implicit animations */ +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_save_easing_state (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_restore_easing_state (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_set_easing_mode (ClutterActor *self, + ClutterAnimationMode mode); +CLUTTER_AVAILABLE_IN_1_10 +ClutterAnimationMode clutter_actor_get_easing_mode (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_set_easing_duration (ClutterActor *self, + guint msecs); +CLUTTER_AVAILABLE_IN_1_10 +guint clutter_actor_get_easing_duration (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_set_easing_delay (ClutterActor *self, + guint msecs); +CLUTTER_AVAILABLE_IN_1_10 +guint clutter_actor_get_easing_delay (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_10 +ClutterTransition * clutter_actor_get_transition (ClutterActor *self, + const char *name); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_add_transition (ClutterActor *self, + const char *name, + ClutterTransition *transition); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_remove_transition (ClutterActor *self, + const char *name); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_actor_remove_all_transitions (ClutterActor *self); + + +CLUTTER_AVAILABLE_IN_1_16 +gboolean clutter_actor_has_mapped_clones (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_22 +void clutter_actor_set_opacity_override (ClutterActor *self, + gint opacity); +CLUTTER_AVAILABLE_IN_1_22 +gint clutter_actor_get_opacity_override (ClutterActor *self); + +/** + * ClutterActorCreateChildFunc: + * @item: (type GObject): the item in the model + * @user_data: Data passed to clutter_actor_bind_model() + * + * Creates a #ClutterActor using the @item in the model. + * + * The usual way to implement this function is to create a #ClutterActor + * instance and then bind the #GObject properties to the actor properties + * of interest, using g_object_bind_property(). This way, when the @item + * in the #GListModel changes, the #ClutterActor changes as well. + * + * Returns: (transfer full): The newly created child #ClutterActor + * + * Since: 1.24 + */ +typedef ClutterActor * (* ClutterActorCreateChildFunc) (gpointer item, + gpointer user_data); + +CLUTTER_AVAILABLE_IN_1_24 +void clutter_actor_bind_model (ClutterActor *self, + GListModel *model, + ClutterActorCreateChildFunc create_child_func, + gpointer user_data, + GDestroyNotify notify); +CLUTTER_AVAILABLE_IN_1_24 +void clutter_actor_bind_model_with_properties (ClutterActor *self, + GListModel *model, + GType child_type, + const char *first_model_property, + ...); + +G_END_DECLS + +#endif /* __CLUTTER_ACTOR_H__ */ diff --git a/clutter/clutter/clutter-align-constraint.c b/clutter/clutter/clutter-align-constraint.c new file mode 100644 index 0000000..345228a --- /dev/null +++ b/clutter/clutter/clutter-align-constraint.c @@ -0,0 +1,542 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-align-constraint + * @Title: ClutterAlignConstraint + * @Short_Description: A constraint aligning the position of an actor + * + * #ClutterAlignConstraint is a #ClutterConstraint that aligns the position + * of the #ClutterActor to which it is applied to the size of another + * #ClutterActor using an alignment factor + * + * #ClutterAlignConstraint is available since Clutter 1.4 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-align-constraint.h" + +#include "clutter-actor-meta-private.h" +#include "clutter-actor-private.h" +#include "clutter-constraint.h" +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-private.h" + +#include + +#define CLUTTER_ALIGN_CONSTRAINT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_ALIGN_CONSTRAINT, ClutterAlignConstraintClass)) +#define CLUTTER_IS_ALIGN_CONSTRAINT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_ALIGN_CONSTRAINT)) +#define CLUTTER_ALIGN_CONSTRAINT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_ALIGN_CONSTRAINT, ClutterAlignConstraintClass)) + +struct _ClutterAlignConstraint +{ + ClutterConstraint parent_instance; + + ClutterActor *actor; + ClutterActor *source; + ClutterAlignAxis align_axis; + gfloat factor; +}; + +struct _ClutterAlignConstraintClass +{ + ClutterConstraintClass parent_class; +}; + +enum +{ + PROP_0, + + PROP_SOURCE, + PROP_ALIGN_AXIS, + PROP_FACTOR, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +G_DEFINE_TYPE (ClutterAlignConstraint, + clutter_align_constraint, + CLUTTER_TYPE_CONSTRAINT); + +static void +source_position_changed (ClutterActor *actor, + const ClutterActorBox *allocation, + ClutterAllocationFlags flags, + ClutterAlignConstraint *align) +{ + if (align->actor != NULL) + clutter_actor_queue_relayout (align->actor); +} + +static void +source_destroyed (ClutterActor *actor, + ClutterAlignConstraint *align) +{ + align->source = NULL; +} + +static void +clutter_align_constraint_set_actor (ClutterActorMeta *meta, + ClutterActor *new_actor) +{ + ClutterAlignConstraint *align = CLUTTER_ALIGN_CONSTRAINT (meta); + ClutterActorMetaClass *parent; + + if (new_actor != NULL && + align->source != NULL && + clutter_actor_contains (new_actor, align->source)) + { + g_warning (G_STRLOC ": The source actor '%s' is contained " + "by the actor '%s' associated to the constraint " + "'%s'", + _clutter_actor_get_debug_name (align->source), + _clutter_actor_get_debug_name (new_actor), + _clutter_actor_meta_get_debug_name (meta)); + return; + } + + /* store the pointer to the actor, for later use */ + align->actor = new_actor; + + parent = CLUTTER_ACTOR_META_CLASS (clutter_align_constraint_parent_class); + parent->set_actor (meta, new_actor); +} + +static void +clutter_align_constraint_update_allocation (ClutterConstraint *constraint, + ClutterActor *actor, + ClutterActorBox *allocation) +{ + ClutterAlignConstraint *align = CLUTTER_ALIGN_CONSTRAINT (constraint); + gfloat source_width, source_height; + gfloat actor_width, actor_height; + gfloat source_x, source_y; + + if (align->source == NULL) + return; + + clutter_actor_box_get_size (allocation, &actor_width, &actor_height); + + clutter_actor_get_position (align->source, &source_x, &source_y); + clutter_actor_get_size (align->source, &source_width, &source_height); + + switch (align->align_axis) + { + case CLUTTER_ALIGN_X_AXIS: + allocation->x1 = ((source_width - actor_width) * align->factor) + + source_x; + allocation->x2 = allocation->x1 + actor_width; + break; + + case CLUTTER_ALIGN_Y_AXIS: + allocation->y1 = ((source_height - actor_height) * align->factor) + + source_y; + allocation->y2 = allocation->y1 + actor_height; + break; + + case CLUTTER_ALIGN_BOTH: + allocation->x1 = ((source_width - actor_width) * align->factor) + + source_x; + allocation->y1 = ((source_height - actor_height) * align->factor) + + source_y; + allocation->x2 = allocation->x1 + actor_width; + allocation->y2 = allocation->y1 + actor_height; + break; + + default: + g_assert_not_reached (); + break; + } + + clutter_actor_box_clamp_to_pixel (allocation); +} + +static void +clutter_align_constraint_dispose (GObject *gobject) +{ + ClutterAlignConstraint *align = CLUTTER_ALIGN_CONSTRAINT (gobject); + + if (align->source != NULL) + { + g_signal_handlers_disconnect_by_func (align->source, + G_CALLBACK (source_destroyed), + align); + g_signal_handlers_disconnect_by_func (align->source, + G_CALLBACK (source_position_changed), + align); + align->source = NULL; + } + + G_OBJECT_CLASS (clutter_align_constraint_parent_class)->dispose (gobject); +} + +static void +clutter_align_constraint_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterAlignConstraint *align = CLUTTER_ALIGN_CONSTRAINT (gobject); + + switch (prop_id) + { + case PROP_SOURCE: + clutter_align_constraint_set_source (align, g_value_get_object (value)); + break; + + case PROP_ALIGN_AXIS: + clutter_align_constraint_set_align_axis (align, g_value_get_enum (value)); + break; + + case PROP_FACTOR: + clutter_align_constraint_set_factor (align, g_value_get_float (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_align_constraint_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterAlignConstraint *align = CLUTTER_ALIGN_CONSTRAINT (gobject); + + switch (prop_id) + { + case PROP_SOURCE: + g_value_set_object (value, align->source); + break; + + case PROP_ALIGN_AXIS: + g_value_set_enum (value, align->align_axis); + break; + + case PROP_FACTOR: + g_value_set_float (value, align->factor); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_align_constraint_class_init (ClutterAlignConstraintClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass); + ClutterConstraintClass *constraint_class = CLUTTER_CONSTRAINT_CLASS (klass); + + meta_class->set_actor = clutter_align_constraint_set_actor; + + constraint_class->update_allocation = clutter_align_constraint_update_allocation; + + /** + * ClutterAlignConstraint:source: + * + * The #ClutterActor used as the source for the alignment. + * + * The #ClutterActor must not be a child or a grandchild of the actor + * using the constraint. + * + * Since: 1.4 + */ + obj_props[PROP_SOURCE] = + g_param_spec_object ("source", + P_("Source"), + P_("The source of the alignment"), + CLUTTER_TYPE_ACTOR, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT); + + /** + * ClutterAlignConstraint:align-axis: + * + * The axis to be used to compute the alignment + * + * Since: 1.4 + */ + obj_props[PROP_ALIGN_AXIS] = + g_param_spec_enum ("align-axis", + P_("Align Axis"), + P_("The axis to align the position to"), + CLUTTER_TYPE_ALIGN_AXIS, + CLUTTER_ALIGN_X_AXIS, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT); + + /** + * ClutterAlignConstraint:factor: + * + * The alignment factor, as a normalized value between 0.0 and 1.0 + * + * The factor depends on the #ClutterAlignConstraint:align-axis property: + * with an align-axis value of %CLUTTER_ALIGN_X_AXIS, 0.0 means left and + * 1.0 means right; with a value of %CLUTTER_ALIGN_Y_AXIS, 0.0 means top + * and 1.0 means bottom. + * + * Since: 1.4 + */ + obj_props[PROP_FACTOR] = + g_param_spec_float ("factor", + P_("Factor"), + P_("The alignment factor, between 0.0 and 1.0"), + 0.0, 1.0, + 0.0, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT); + + gobject_class->dispose = clutter_align_constraint_dispose; + gobject_class->set_property = clutter_align_constraint_set_property; + gobject_class->get_property = clutter_align_constraint_get_property; + g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); +} + +static void +clutter_align_constraint_init (ClutterAlignConstraint *self) +{ + self->actor = NULL; + self->source = NULL; + self->align_axis = CLUTTER_ALIGN_X_AXIS; + self->factor = 0.0f; +} + +/** + * clutter_align_constraint_new: + * @source: (allow-none): the #ClutterActor to use as the source of the + * alignment, or %NULL + * @axis: the axis to be used to compute the alignment + * @factor: the alignment factor, between 0.0 and 1.0 + * + * Creates a new constraint, aligning a #ClutterActor's position with + * regards of the size of the actor to @source, with the given + * alignment @factor + * + * Return value: the newly created #ClutterAlignConstraint + * + * Since: 1.4 + */ +ClutterConstraint * +clutter_align_constraint_new (ClutterActor *source, + ClutterAlignAxis axis, + gfloat factor) +{ + g_return_val_if_fail (source == NULL || CLUTTER_IS_ACTOR (source), NULL); + + return g_object_new (CLUTTER_TYPE_ALIGN_CONSTRAINT, + "source", source, + "align-axis", axis, + "factor", factor, + NULL); +} + +/** + * clutter_align_constraint_set_source: + * @align: a #ClutterAlignConstraint + * @source: (allow-none): a #ClutterActor, or %NULL to unset the source + * + * Sets the source of the alignment constraint + * + * Since: 1.4 + */ +void +clutter_align_constraint_set_source (ClutterAlignConstraint *align, + ClutterActor *source) +{ + ClutterActor *old_source, *actor; + ClutterActorMeta *meta; + + g_return_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align)); + g_return_if_fail (source == NULL || CLUTTER_IS_ACTOR (source)); + + if (align->source == source) + return; + + meta = CLUTTER_ACTOR_META (align); + actor = clutter_actor_meta_get_actor (meta); + if (actor != NULL && source != NULL) + { + if (clutter_actor_contains (actor, source)) + { + g_warning (G_STRLOC ": The source actor '%s' is contained " + "by the actor '%s' associated to the constraint " + "'%s'", + _clutter_actor_get_debug_name (source), + _clutter_actor_get_debug_name (actor), + _clutter_actor_meta_get_debug_name (meta)); + return; + } + } + + old_source = align->source; + if (old_source != NULL) + { + g_signal_handlers_disconnect_by_func (old_source, + G_CALLBACK (source_destroyed), + align); + g_signal_handlers_disconnect_by_func (old_source, + G_CALLBACK (source_position_changed), + align); + } + + align->source = source; + if (align->source != NULL) + { + g_signal_connect (align->source, "allocation-changed", + G_CALLBACK (source_position_changed), + align); + g_signal_connect (align->source, "destroy", + G_CALLBACK (source_destroyed), + align); + + if (align->actor != NULL) + clutter_actor_queue_relayout (align->actor); + } + + g_object_notify_by_pspec (G_OBJECT (align), obj_props[PROP_SOURCE]); +} + +/** + * clutter_align_constraint_get_source: + * @align: a #ClutterAlignConstraint + * + * Retrieves the source of the alignment + * + * Return value: (transfer none): the #ClutterActor used as the source + * of the alignment + * + * Since: 1.4 + */ +ClutterActor * +clutter_align_constraint_get_source (ClutterAlignConstraint *align) +{ + g_return_val_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align), NULL); + + return align->source; +} + +/** + * clutter_align_constraint_set_align_axis: + * @align: a #ClutterAlignConstraint + * @axis: the axis to which the alignment refers to + * + * Sets the axis to which the alignment refers to + * + * Since: 1.4 + */ +void +clutter_align_constraint_set_align_axis (ClutterAlignConstraint *align, + ClutterAlignAxis axis) +{ + g_return_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align)); + + if (align->align_axis == axis) + return; + + align->align_axis = axis; + + if (align->actor != NULL) + clutter_actor_queue_relayout (align->actor); + + g_object_notify_by_pspec (G_OBJECT (align), obj_props[PROP_ALIGN_AXIS]); +} + +/** + * clutter_align_constraint_get_align_axis: + * @align: a #ClutterAlignConstraint + * + * Retrieves the value set using clutter_align_constraint_set_align_axis() + * + * Return value: the alignment axis + * + * Since: 1.4 + */ +ClutterAlignAxis +clutter_align_constraint_get_align_axis (ClutterAlignConstraint *align) +{ + g_return_val_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align), + CLUTTER_ALIGN_X_AXIS); + + return align->align_axis; +} + +/** + * clutter_align_constraint_set_factor: + * @align: a #ClutterAlignConstraint + * @factor: the alignment factor, between 0.0 and 1.0 + * + * Sets the alignment factor of the constraint + * + * The factor depends on the #ClutterAlignConstraint:align-axis property + * and it is a value between 0.0 (meaning left, when + * #ClutterAlignConstraint:align-axis is set to %CLUTTER_ALIGN_X_AXIS; or + * meaning top, when #ClutterAlignConstraint:align-axis is set to + * %CLUTTER_ALIGN_Y_AXIS) and 1.0 (meaning right, when + * #ClutterAlignConstraint:align-axis is set to %CLUTTER_ALIGN_X_AXIS; or + * meaning bottom, when #ClutterAlignConstraint:align-axis is set to + * %CLUTTER_ALIGN_Y_AXIS). A value of 0.5 aligns in the middle in either + * cases + * + * Since: 1.4 + */ +void +clutter_align_constraint_set_factor (ClutterAlignConstraint *align, + gfloat factor) +{ + g_return_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align)); + + align->factor = CLAMP (factor, 0.0, 1.0); + + if (align->actor != NULL) + clutter_actor_queue_relayout (align->actor); + + g_object_notify_by_pspec (G_OBJECT (align), obj_props[PROP_FACTOR]); +} + +/** + * clutter_align_constraint_get_factor: + * @align: a #ClutterAlignConstraint + * + * Retrieves the factor set using clutter_align_constraint_set_factor() + * + * Return value: the alignment factor + * + * Since: 1.4 + */ +gfloat +clutter_align_constraint_get_factor (ClutterAlignConstraint *align) +{ + g_return_val_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align), 0.0); + + return align->factor; +} diff --git a/clutter/clutter/clutter-align-constraint.h b/clutter/clutter/clutter-align-constraint.h new file mode 100644 index 0000000..212be8b --- /dev/null +++ b/clutter/clutter/clutter-align-constraint.h @@ -0,0 +1,77 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_ALIGN_CONSTRAINT_H__ +#define __CLUTTER_ALIGN_CONSTRAINT_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_ALIGN_CONSTRAINT (clutter_align_constraint_get_type ()) +#define CLUTTER_ALIGN_CONSTRAINT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ALIGN_CONSTRAINT, ClutterAlignConstraint)) +#define CLUTTER_IS_ALIGN_CONSTRAINT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ALIGN_CONSTRAINT)) + +/** + * ClutterAlignConstraint: + * + * #ClutterAlignConstraint is an opaque structure + * whose members cannot be directly accesses + * + * Since: 1.4 + */ +typedef struct _ClutterAlignConstraint ClutterAlignConstraint; +typedef struct _ClutterAlignConstraintClass ClutterAlignConstraintClass; + +CLUTTER_AVAILABLE_IN_1_4 +GType clutter_align_constraint_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_4 +ClutterConstraint *clutter_align_constraint_new (ClutterActor *source, + ClutterAlignAxis axis, + gfloat factor); + +CLUTTER_AVAILABLE_IN_1_4 +void clutter_align_constraint_set_source (ClutterAlignConstraint *align, + ClutterActor *source); +CLUTTER_AVAILABLE_IN_1_4 +ClutterActor * clutter_align_constraint_get_source (ClutterAlignConstraint *align); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_align_constraint_set_align_axis (ClutterAlignConstraint *align, + ClutterAlignAxis axis); +CLUTTER_AVAILABLE_IN_1_4 +ClutterAlignAxis clutter_align_constraint_get_align_axis (ClutterAlignConstraint *align); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_align_constraint_set_factor (ClutterAlignConstraint *align, + gfloat factor); +CLUTTER_AVAILABLE_IN_1_4 +gfloat clutter_align_constraint_get_factor (ClutterAlignConstraint *align); + +G_END_DECLS + +#endif /* __CLUTTER_ALIGN_CONSTRAINT_H__ */ diff --git a/clutter/clutter/clutter-animatable.c b/clutter/clutter/clutter-animatable.c new file mode 100644 index 0000000..ea285b8 --- /dev/null +++ b/clutter/clutter/clutter-animatable.c @@ -0,0 +1,286 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * 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 . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-animatable + * @short_description: Interface for animatable classes + * + * #ClutterAnimatable is an interface that allows a #GObject class + * to control how a #ClutterAnimation will animate a property. + * + * Each #ClutterAnimatable should implement the + * #ClutterAnimatableIface.interpolate_property() virtual function of the + * interface to compute the animation state between two values of an interval + * depending on a progress factor, expressed as a floating point value. + * + * If a #ClutterAnimatable is animated by a #ClutterAnimation + * instance, the #ClutterAnimation will call + * clutter_animatable_interpolate_property() passing the name of the + * currently animated property; the values interval; and the progress factor. + * The #ClutterAnimatable implementation should return the computed value for + * the animated + * property. + * + * #ClutterAnimatable is available since Clutter 1.0 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS + +#include "clutter-animatable.h" +#include "clutter-interval.h" +#include "clutter-debug.h" +#include "clutter-private.h" + +#include "deprecated/clutter-animatable.h" +#include "deprecated/clutter-animation.h" + +typedef ClutterAnimatableIface ClutterAnimatableInterface; +G_DEFINE_INTERFACE (ClutterAnimatable, clutter_animatable, G_TYPE_OBJECT); + +static void +clutter_animatable_default_init (ClutterAnimatableInterface *iface) +{ +} + +/** + * clutter_animatable_animate_property: + * @animatable: a #ClutterAnimatable + * @animation: a #ClutterAnimation + * @property_name: the name of the animated property + * @initial_value: the initial value of the animation interval + * @final_value: the final value of the animation interval + * @progress: the progress factor + * @value: return location for the animation value + * + * Calls the animate_property() virtual function for @animatable. + * + * The @initial_value and @final_value #GValues must contain + * the same type; @value must have been initialized to the same + * type of @initial_value and @final_value. + * + * 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 + * + * Deprecated: 1.8: Use clutter_animatable_interpolate_value() + * instead + */ +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) +{ + ClutterAnimatableIface *iface; + gboolean res; + + 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); + + iface = CLUTTER_ANIMATABLE_GET_IFACE (animatable); + if (iface->animate_property == NULL) + { + ClutterInterval *interval; + + interval = clutter_animation_get_interval (animation, property_name); + if (interval == NULL) + return FALSE; + + res = clutter_animatable_interpolate_value (animatable, property_name, + interval, + progress, + value); + } + else + res = iface->animate_property (animatable, animation, + property_name, + initial_value, final_value, + progress, + value); + + return res; +} + +/** + * clutter_animatable_find_property: + * @animatable: a #ClutterAnimatable + * @property_name: the name of the animatable property to find + * + * Finds the #GParamSpec for @property_name + * + * Return value: (transfer none): The #GParamSpec for the given property + * or %NULL + * + * Since: 1.4 + */ +GParamSpec * +clutter_animatable_find_property (ClutterAnimatable *animatable, + const gchar *property_name) +{ + ClutterAnimatableIface *iface; + + g_return_val_if_fail (CLUTTER_IS_ANIMATABLE (animatable), NULL); + g_return_val_if_fail (property_name != NULL, NULL); + + CLUTTER_NOTE (ANIMATION, "Looking for property '%s'", property_name); + + iface = CLUTTER_ANIMATABLE_GET_IFACE (animatable); + if (iface->find_property != NULL) + return iface->find_property (animatable, property_name); + + return g_object_class_find_property (G_OBJECT_GET_CLASS (animatable), + property_name); +} + +/** + * clutter_animatable_get_initial_state: + * @animatable: a #ClutterAnimatable + * @property_name: the name of the animatable property to retrieve + * @value: a #GValue initialized to the type of the property to retrieve + * + * Retrieves the current state of @property_name and sets @value with it + * + * Since: 1.4 + */ +void +clutter_animatable_get_initial_state (ClutterAnimatable *animatable, + const gchar *property_name, + GValue *value) +{ + ClutterAnimatableIface *iface; + + g_return_if_fail (CLUTTER_IS_ANIMATABLE (animatable)); + g_return_if_fail (property_name != NULL); + + CLUTTER_NOTE (ANIMATION, "Getting initial state of '%s'", property_name); + + iface = CLUTTER_ANIMATABLE_GET_IFACE (animatable); + if (iface->get_initial_state != NULL) + iface->get_initial_state (animatable, property_name, value); + else + g_object_get_property (G_OBJECT (animatable), property_name, value); +} + +/** + * clutter_animatable_set_final_state: + * @animatable: a #ClutterAnimatable + * @property_name: the name of the animatable property to set + * @value: the value of the animatable property to set + * + * Sets the current state of @property_name to @value + * + * Since: 1.4 + */ +void +clutter_animatable_set_final_state (ClutterAnimatable *animatable, + const gchar *property_name, + const GValue *value) +{ + ClutterAnimatableIface *iface; + + g_return_if_fail (CLUTTER_IS_ANIMATABLE (animatable)); + g_return_if_fail (property_name != NULL); + + CLUTTER_NOTE (ANIMATION, "Setting state of property '%s'", property_name); + + iface = CLUTTER_ANIMATABLE_GET_IFACE (animatable); + if (iface->set_final_state != NULL) + iface->set_final_state (animatable, property_name, value); + else + g_object_set_property (G_OBJECT (animatable), property_name, value); +} + +/** + * clutter_animatable_interpolate_value: + * @animatable: a #ClutterAnimatable + * @property_name: the name of the property to interpolate + * @interval: a #ClutterInterval with the animation range + * @progress: the progress to use to interpolate between the + * initial and final values of the @interval + * @value: (out): return location for an initialized #GValue + * using the same type of the @interval + * + * Asks a #ClutterAnimatable implementation to interpolate a + * a named property between the initial and final values of + * a #ClutterInterval, using @progress as the interpolation + * value, and store the result inside @value. + * + * This function should be used for every property animation + * involving #ClutterAnimatables. + * + * This function replaces clutter_animatable_animate_property(). + * + * Return value: %TRUE if the interpolation was successful, + * and %FALSE otherwise + * + * Since: 1.8 + */ +gboolean +clutter_animatable_interpolate_value (ClutterAnimatable *animatable, + const gchar *property_name, + ClutterInterval *interval, + gdouble progress, + GValue *value) +{ + ClutterAnimatableIface *iface; + + g_return_val_if_fail (CLUTTER_IS_ANIMATABLE (animatable), FALSE); + g_return_val_if_fail (property_name != NULL, FALSE); + g_return_val_if_fail (CLUTTER_IS_INTERVAL (interval), FALSE); + g_return_val_if_fail (value != NULL, FALSE); + + CLUTTER_NOTE (ANIMATION, "Interpolating '%s' (progress: %.3f)", + property_name, + progress); + + iface = CLUTTER_ANIMATABLE_GET_IFACE (animatable); + if (iface->interpolate_value != NULL) + { + return iface->interpolate_value (animatable, property_name, + interval, + progress, + value); + } + else + return clutter_interval_compute_value (interval, progress, value); +} diff --git a/clutter/clutter/clutter-animatable.h b/clutter/clutter/clutter-animatable.h new file mode 100644 index 0000000..7d20c5a --- /dev/null +++ b/clutter/clutter/clutter-animatable.h @@ -0,0 +1,121 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * 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 . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_ANIMATABLE_H__ +#define __CLUTTER_ANIMATABLE_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_ANIMATABLE (clutter_animatable_get_type ()) +#define CLUTTER_ANIMATABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ANIMATABLE, ClutterAnimatable)) +#define CLUTTER_IS_ANIMATABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ANIMATABLE)) +#define CLUTTER_ANIMATABLE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), CLUTTER_TYPE_ANIMATABLE, ClutterAnimatableIface)) + +typedef struct _ClutterAnimatableIface ClutterAnimatableIface; + +/** + * ClutterAnimatable: + * + * #ClutterAnimatable is an opaque structure whose members cannot be directly + * accessed + * + * Since: 1.0 + */ + +/** + * ClutterAnimatableIface: + * @animate_property: virtual function for custom interpolation of a + * property. This virtual function is deprecated + * @find_property: virtual function for retrieving the #GParamSpec of + * an animatable property + * @get_initial_state: virtual function for retrieving the initial + * state of an animatable property + * @set_final_state: virtual function for setting the state of an + * animatable property + * @interpolate_value: virtual function for interpolating the progress + * of a property + * + * Base interface for #GObjects that can be animated by a + * a #ClutterAnimation. + * + * Since: 1.0 + */ +struct _ClutterAnimatableIface +{ + /*< private >*/ + GTypeInterface parent_iface; + + /*< public >*/ + gboolean (* animate_property) (ClutterAnimatable *animatable, + ClutterAnimation *animation, + const gchar *property_name, + const GValue *initial_value, + const GValue *final_value, + gdouble progress, + GValue *value); + GParamSpec *(* find_property) (ClutterAnimatable *animatable, + const gchar *property_name); + void (* get_initial_state) (ClutterAnimatable *animatable, + const gchar *property_name, + GValue *value); + void (* set_final_state) (ClutterAnimatable *animatable, + const gchar *property_name, + const GValue *value); + gboolean (* interpolate_value) (ClutterAnimatable *animatable, + const gchar *property_name, + ClutterInterval *interval, + gdouble progress, + GValue *value); +}; + +CLUTTER_AVAILABLE_IN_1_0 +GType clutter_animatable_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_0 +GParamSpec *clutter_animatable_find_property (ClutterAnimatable *animatable, + const gchar *property_name); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_animatable_get_initial_state (ClutterAnimatable *animatable, + const gchar *property_name, + GValue *value); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_animatable_set_final_state (ClutterAnimatable *animatable, + const gchar *property_name, + const GValue *value); +CLUTTER_AVAILABLE_IN_1_8 +gboolean clutter_animatable_interpolate_value (ClutterAnimatable *animatable, + const gchar *property_name, + ClutterInterval *interval, + gdouble progress, + GValue *value); + +G_END_DECLS + +#endif /* __CLUTTER_ANIMATABLE_H__ */ diff --git a/clutter/clutter/clutter-autocleanups.h b/clutter/clutter/clutter-autocleanups.h new file mode 100644 index 0000000..10c73fd --- /dev/null +++ b/clutter/clutter/clutter-autocleanups.h @@ -0,0 +1,106 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright 2015 Emmanuele Bassi + * + * 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 . + * + * + */ + +#ifndef __CLUTTER_AUTO_CLEANUPS_H__ +#define __CLUTTER_AUTO_CLEANUPS_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __GI_SCANNER__ + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterAction, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterActor, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterActorMeta, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterAlignConstraint, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterAnimatable, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBackend, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBindConstraint, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBindingPool, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBinLayout, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBlurEffect, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBoxLayout, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBrightnessContrastEffect, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterCanvas, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterChildMeta, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterClickAction, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterClone, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterColorizeEffect, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterConstraint, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterContainer, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterContent, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterDeformEffect, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterDesaturateEffect, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterDeviceManager, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterDragAction, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterDropAction, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterEffect, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterFixedLayout, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterFlowLayout, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterGestureAction, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterGridLayout, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterImage, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterInputDevice, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterInterval, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterKeyframeTransition, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterLayoutManager, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterLayoutMeta, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterOffscreenEffect, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPageTurnEffect, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPanAction, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPathConstraint, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPath, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPropertyTransition, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterRotateAction, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterScriptable, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterScript, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterScrollActor, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterSettings, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterShaderEffect, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterSnapConstraint, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterStage, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterSwipeAction, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterTapAction, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterTextBuffer, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterText, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterTimeline, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterTransitionGroup, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterTransition, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterZoomAction, g_object_unref) + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterActorBox, clutter_actor_box_free) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterColor, clutter_color_free) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterMargin, clutter_margin_free) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterMatrix, clutter_matrix_free) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPaintNode, clutter_paint_node_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPaintVolume, clutter_paint_volume_free) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPathNode, clutter_path_node_free) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPoint, clutter_point_free) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterRect, clutter_rect_free) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterSize, clutter_size_free) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterVertex, clutter_vertex_free) + +#endif /* __GI_SCANNER__ */ + +#endif /* __CLUTTER_AUTO_CLEANUPS_H__ */ diff --git a/clutter/clutter/clutter-backend-private.h b/clutter/clutter/clutter-backend-private.h new file mode 100644 index 0000000..b808d25 --- /dev/null +++ b/clutter/clutter/clutter-backend-private.h @@ -0,0 +1,158 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __CLUTTER_BACKEND_PRIVATE_H__ +#define __CLUTTER_BACKEND_PRIVATE_H__ + +#include +#include +#include + +#include "clutter-event-translator.h" + +#define CLUTTER_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BACKEND, ClutterBackendClass)) +#define CLUTTER_IS_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BACKEND)) +#define CLUTTER_BACKEND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BACKEND, ClutterBackendClass)) + +G_BEGIN_DECLS + +typedef struct _ClutterBackendPrivate ClutterBackendPrivate; + +struct _ClutterBackend +{ + /*< private >*/ + GObject parent_instance; + + CoglRenderer *cogl_renderer; + CoglDisplay *cogl_display; + CoglContext *cogl_context; + GSource *cogl_source; + + CoglOnscreen *dummy_onscreen; + + ClutterDeviceManager *device_manager; + + cairo_font_options_t *font_options; + + gchar *font_name; + + gfloat units_per_em; + gint32 units_serial; + + GList *event_translators; +}; + +struct _ClutterBackendClass +{ + /*< private >*/ + GObjectClass parent_class; + + /* vfuncs */ + gboolean (* pre_parse) (ClutterBackend *backend, + GError **error); + gboolean (* post_parse) (ClutterBackend *backend, + GError **error); + ClutterStageWindow * (* create_stage) (ClutterBackend *backend, + ClutterStage *wrapper, + GError **error); + void (* init_events) (ClutterBackend *backend); + void (* init_features) (ClutterBackend *backend); + void (* add_options) (ClutterBackend *backend, + GOptionGroup *group); + ClutterFeatureFlags (* get_features) (ClutterBackend *backend); + CoglRenderer * (* get_renderer) (ClutterBackend *backend, + GError **error); + CoglDisplay * (* get_display) (ClutterBackend *backend, + CoglRenderer *renderer, + CoglSwapChain *swap_chain, + GError **error); + gboolean (* create_context) (ClutterBackend *backend, + GError **error); + ClutterDeviceManager *(* get_device_manager) (ClutterBackend *backend); + + void (* copy_event_data) (ClutterBackend *backend, + const ClutterEvent *src, + ClutterEvent *dest); + void (* free_event_data) (ClutterBackend *backend, + ClutterEvent *event); + + gboolean (* translate_event) (ClutterBackend *backend, + gpointer native, + ClutterEvent *event); + + PangoDirection (* get_keymap_direction) (ClutterBackend *backend); + + /* signals */ + void (* resolution_changed) (ClutterBackend *backend); + void (* font_changed) (ClutterBackend *backend); + void (* settings_changed) (ClutterBackend *backend); +}; + +ClutterBackend * _clutter_create_backend (void); + +ClutterStageWindow * _clutter_backend_create_stage (ClutterBackend *backend, + ClutterStage *wrapper, + GError **error); +gboolean _clutter_backend_create_context (ClutterBackend *backend, + GError **error); + +void _clutter_backend_add_options (ClutterBackend *backend, + GOptionGroup *group); +gboolean _clutter_backend_pre_parse (ClutterBackend *backend, + GError **error); +gboolean _clutter_backend_post_parse (ClutterBackend *backend, + GError **error); + +void _clutter_backend_init_events (ClutterBackend *backend); +void _clutter_backend_copy_event_data (ClutterBackend *backend, + const ClutterEvent *src, + ClutterEvent *dest); +void _clutter_backend_free_event_data (ClutterBackend *backend, + ClutterEvent *event); +gboolean _clutter_backend_translate_event (ClutterBackend *backend, + gpointer native, + ClutterEvent *event); + +CLUTTER_AVAILABLE_IN_MUTTER +void _clutter_backend_add_event_translator (ClutterBackend *backend, + ClutterEventTranslator *translator); + +void _clutter_backend_remove_event_translator (ClutterBackend *backend, + ClutterEventTranslator *translator); + +ClutterFeatureFlags _clutter_backend_get_features (ClutterBackend *backend); + +gfloat _clutter_backend_get_units_per_em (ClutterBackend *backend, + PangoFontDescription *font_desc); +gint32 _clutter_backend_get_units_serial (ClutterBackend *backend); + +PangoDirection _clutter_backend_get_keymap_direction (ClutterBackend *backend); + +CLUTTER_AVAILABLE_IN_MUTTER +void _clutter_backend_reset_cogl_framebuffer (ClutterBackend *backend); + +void clutter_set_allowed_drivers (const char *drivers); + +void clutter_try_set_windowing_backend (const char *drivers); + +G_END_DECLS + +#endif /* __CLUTTER_BACKEND_PRIVATE_H__ */ diff --git a/clutter/clutter/clutter-backend.c b/clutter/clutter/clutter-backend.c new file mode 100644 index 0000000..5a457a2 --- /dev/null +++ b/clutter/clutter/clutter-backend.c @@ -0,0 +1,1365 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By: + * Matthew Allum + * Emmanuele Bassi + * + * Copyright (C) 2006, 2007, 2008 OpenedHand Ltd + * Copyright (C) 2009, 2010 Intel Corp + * + * 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 . + */ + +/** + * SECTION:clutter-backend + * @short_description: Backend abstraction + * + * Clutter can be compiled against different backends. Each backend + * has to implement a set of functions, in order to be used by Clutter. + * + * #ClutterBackend is the base class abstracting the various implementation; + * it provides a basic API to query the backend for generic information + * and settings. + * + * #ClutterBackend is available since Clutter 0.4 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#define CLUTTER_ENABLE_EXPERIMENTAL_API + +#include "clutter-backend-private.h" +#include "clutter-debug.h" +#include "clutter-event-private.h" +#include "clutter-marshal.h" +#include "clutter-mutter.h" +#include "clutter-private.h" +#include "clutter-stage-manager-private.h" +#include "clutter-stage-private.h" +#include "clutter-stage-window.h" +#include "clutter-version.h" +#include "clutter-device-manager-private.h" + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include "deprecated/clutter-backend.h" + +#ifdef CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT +#include "wayland/clutter-wayland-compositor.h" +#endif + +#include + +#ifdef CLUTTER_INPUT_X11 +#include "x11/clutter-backend-x11.h" +#endif +#ifdef CLUTTER_INPUT_EVDEV +#include "evdev/clutter-device-manager-evdev.h" +#endif +#ifdef CLUTTER_WINDOWING_EGL +#include "egl/clutter-backend-eglnative.h" +#endif + +#ifdef CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT +#include +#include +#include "wayland/clutter-wayland-compositor.h" +#endif + +#define DEFAULT_FONT_NAME "Sans 10" + +enum +{ + RESOLUTION_CHANGED, + FONT_CHANGED, + SETTINGS_CHANGED, + + LAST_SIGNAL +}; + +G_DEFINE_ABSTRACT_TYPE (ClutterBackend, clutter_backend, G_TYPE_OBJECT) + +static guint backend_signals[LAST_SIGNAL] = { 0, }; + +/* Global for being able to specify a compositor side wayland display + * pointer before clutter initialization */ +#ifdef CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT +static struct wl_display *_wayland_compositor_display; +#endif + +static void +clutter_backend_dispose (GObject *gobject) +{ + ClutterBackend *backend = CLUTTER_BACKEND (gobject); + + /* clear the events still in the queue of the main context */ + _clutter_clear_events_queue (); + + /* remove all event translators */ + g_clear_pointer (&backend->event_translators, g_list_free); + + g_clear_pointer (&backend->dummy_onscreen, cogl_object_unref); + + G_OBJECT_CLASS (clutter_backend_parent_class)->dispose (gobject); +} + +static void +clutter_backend_finalize (GObject *gobject) +{ + ClutterBackend *backend = CLUTTER_BACKEND (gobject); + + g_source_destroy (backend->cogl_source); + + g_free (backend->font_name); + clutter_backend_set_font_options (backend, NULL); + + G_OBJECT_CLASS (clutter_backend_parent_class)->finalize (gobject); +} + +static gfloat +get_units_per_em (ClutterBackend *backend, + PangoFontDescription *font_desc) +{ + gfloat units_per_em = -1.0; + gboolean free_font_desc = FALSE; + gdouble dpi; + + dpi = clutter_backend_get_resolution (backend); + + if (font_desc == NULL) + { + ClutterSettings *settings; + gchar *font_name = NULL; + + settings = clutter_settings_get_default (); + g_object_get (settings, "font-name", &font_name, NULL); + + if (G_LIKELY (font_name != NULL && *font_name != '\0')) + { + font_desc = pango_font_description_from_string (font_name); + free_font_desc = TRUE; + + g_free (font_name); + } + } + + 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 = dpi * ((gdouble) pango_size / PANGO_SCALE) / 72.0f; + + /* 10 points at 96 DPI is 13.3 pixels */ + units_per_em = (1.2f * font_size) * dpi / 96.0f; + } + else + 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) +{ + ClutterMainContext *context; + ClutterSettings *settings; + gdouble resolution; + gint dpi; + + settings = clutter_settings_get_default (); + g_object_get (settings, "font-dpi", &dpi, NULL); + + if (dpi < 0) + resolution = 96.0; + else + resolution = dpi / 1024.0; + + context = _clutter_context_get_default (); + if (context->font_map != NULL) + cogl_pango_font_map_set_resolution (context->font_map, resolution); + + backend->units_per_em = get_units_per_em (backend, NULL); + backend->units_serial += 1; + + CLUTTER_NOTE (BACKEND, "Units per em: %.2f", backend->units_per_em); +} + +static void +clutter_backend_real_font_changed (ClutterBackend *backend) +{ + backend->units_per_em = get_units_per_em (backend, NULL); + backend->units_serial += 1; + + CLUTTER_NOTE (BACKEND, "Units per em: %.2f", backend->units_per_em); +} + +static gboolean +clutter_backend_do_real_create_context (ClutterBackend *backend, + CoglDriver driver_id, + GError **error) +{ + ClutterBackendClass *klass; + CoglSwapChain *swap_chain; + GError *internal_error; + + klass = CLUTTER_BACKEND_GET_CLASS (backend); + + swap_chain = NULL; + internal_error = NULL; + + CLUTTER_NOTE (BACKEND, "Creating Cogl renderer"); + backend->cogl_renderer = klass->get_renderer (backend, &internal_error); + + if (backend->cogl_renderer == NULL) + goto error; + + CLUTTER_NOTE (BACKEND, "Connecting the renderer"); + cogl_renderer_set_driver (backend->cogl_renderer, driver_id); + if (!cogl_renderer_connect (backend->cogl_renderer, &internal_error)) + goto error; + + CLUTTER_NOTE (BACKEND, "Creating Cogl swap chain"); + swap_chain = cogl_swap_chain_new (); + + CLUTTER_NOTE (BACKEND, "Creating Cogl display"); + if (klass->get_display != NULL) + { + backend->cogl_display = klass->get_display (backend, + backend->cogl_renderer, + swap_chain, + &internal_error); + } + else + { + CoglOnscreenTemplate *tmpl; + gboolean res; + + tmpl = cogl_onscreen_template_new (swap_chain); + + /* XXX: I have some doubts that this is a good design. + * + * Conceptually should we be able to check an onscreen_template + * without more details about the CoglDisplay configuration? + */ + res = cogl_renderer_check_onscreen_template (backend->cogl_renderer, + tmpl, + &internal_error); + + if (!res) + goto error; + + backend->cogl_display = cogl_display_new (backend->cogl_renderer, tmpl); + + /* the display owns the template */ + cogl_object_unref (tmpl); + } + + if (backend->cogl_display == NULL) + goto error; + +#ifdef CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT + cogl_wayland_display_set_compositor_display (backend->cogl_display, + _wayland_compositor_display); +#endif + + CLUTTER_NOTE (BACKEND, "Setting up the display"); + if (!cogl_display_setup (backend->cogl_display, &internal_error)) + goto error; + + CLUTTER_NOTE (BACKEND, "Creating the Cogl context"); + backend->cogl_context = cogl_context_new (backend->cogl_display, &internal_error); + if (backend->cogl_context == NULL) + goto error; + + /* the display owns the renderer and the swap chain */ + cogl_object_unref (backend->cogl_renderer); + cogl_object_unref (swap_chain); + + return TRUE; + +error: + if (backend->cogl_display != NULL) + { + cogl_object_unref (backend->cogl_display); + backend->cogl_display = NULL; + } + + if (backend->cogl_renderer != NULL) + { + cogl_object_unref (backend->cogl_renderer); + backend->cogl_renderer = NULL; + } + + if (swap_chain != NULL) + cogl_object_unref (swap_chain); + + return FALSE; +} + +static const struct { + const char *driver_name; + const char *driver_desc; + CoglDriver driver_id; +} all_known_drivers[] = { + { "gl3", "OpenGL 3.2 core profile", COGL_DRIVER_GL3 }, + { "gl", "OpenGL legacy profile", COGL_DRIVER_GL }, + { "gles2", "OpenGL ES 2.0", COGL_DRIVER_GLES2 }, + { "any", "Default Cogl driver", COGL_DRIVER_ANY }, +}; + +static const char *allowed_drivers; + +static gboolean +clutter_backend_real_create_context (ClutterBackend *backend, + GError **error) +{ + GError *internal_error = NULL; + const char *drivers_list; + char **known_drivers; + gboolean allow_any; + int i; + + if (backend->cogl_context != NULL) + return TRUE; + + if (allowed_drivers == NULL) + allowed_drivers = CLUTTER_DRIVERS; + + allow_any = strstr (allowed_drivers, "*") != NULL; + + drivers_list = g_getenv ("CLUTTER_DRIVER"); + if (drivers_list == NULL) + drivers_list = allowed_drivers; + + known_drivers = g_strsplit (drivers_list, ",", 0); + + for (i = 0; backend->cogl_context == NULL && known_drivers[i] != NULL; i++) + { + const char *driver_name = known_drivers[i]; + gboolean is_any = g_str_equal (driver_name, "*"); + int j; + + for (j = 0; j < G_N_ELEMENTS (all_known_drivers); j++) + { + if (!allow_any && !is_any && !strstr (driver_name, all_known_drivers[j].driver_name)) + continue; + + if ((allow_any && is_any) || + (is_any && strstr (allowed_drivers, all_known_drivers[j].driver_name)) || + g_str_equal (all_known_drivers[j].driver_name, driver_name)) + { + CLUTTER_NOTE (BACKEND, "Checking for the %s driver", all_known_drivers[j].driver_desc); + + if (clutter_backend_do_real_create_context (backend, all_known_drivers[j].driver_id, &internal_error)) + break; + + if (internal_error) + { + CLUTTER_NOTE (BACKEND, "Unable to use the %s driver: %s", + all_known_drivers[j].driver_desc, + internal_error->message); + g_clear_error (&internal_error); + } + } + } + } + + g_strfreev (known_drivers); + + if (backend->cogl_context == NULL) + { + if (internal_error != NULL) + g_propagate_error (error, internal_error); + else + g_set_error_literal (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_BACKEND, + _("Unable to initialize the Clutter backend: no available drivers found.")); + + return FALSE; + } + + backend->cogl_source = cogl_glib_source_new (backend->cogl_context, G_PRIORITY_DEFAULT); + g_source_attach (backend->cogl_source, NULL); + + return TRUE; +} + +static ClutterFeatureFlags +clutter_backend_real_get_features (ClutterBackend *backend) +{ + ClutterFeatureFlags flags = 0; + + if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN)) + { + CLUTTER_NOTE (BACKEND, "Cogl supports multiple onscreen framebuffers"); + flags |= CLUTTER_FEATURE_STAGE_MULTIPLE; + } + else + { + CLUTTER_NOTE (BACKEND, "Cogl only supports one onscreen framebuffer"); + flags |= CLUTTER_FEATURE_STAGE_STATIC; + } + + if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_THROTTLE)) + { + CLUTTER_NOTE (BACKEND, "Cogl supports swap buffers throttling"); + flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK; + } + else + CLUTTER_NOTE (BACKEND, "Cogl doesn't support swap buffers throttling"); + + if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT)) + { + CLUTTER_NOTE (BACKEND, "Cogl supports swap buffers complete events"); + flags |= CLUTTER_FEATURE_SWAP_EVENTS; + } + + return flags; +} + +static const char *allowed_backends; + +static ClutterBackend * (* custom_backend_func) (void); + +static const struct { + const char *name; + ClutterBackend * (* create_backend) (void); +} available_backends[] = { +#ifdef CLUTTER_WINDOWING_X11 + { CLUTTER_WINDOWING_X11, clutter_backend_x11_new }, +#endif +#ifdef CLUTTER_WINDOWING_EGL + { CLUTTER_WINDOWING_EGL, clutter_backend_egl_native_new }, +#endif + { NULL, NULL }, +}; + +void +clutter_set_custom_backend_func (ClutterBackend *(* func) (void)) +{ + custom_backend_func = func; +} + +ClutterBackend * +_clutter_create_backend (void) +{ + const char *backends_list; + ClutterBackend *retval; + gboolean allow_any; + char **backends; + int i; + + if (custom_backend_func) + { + retval = custom_backend_func (); + + if (!retval) + g_error ("Failed to create custom backend."); + + return retval; + } + + if (allowed_backends == NULL) + allowed_backends = "*"; + + allow_any = strstr (allowed_backends, "*") != NULL; + + backends_list = g_getenv ("CLUTTER_BACKEND"); + if (backends_list == NULL) + backends_list = allowed_backends; + + backends = g_strsplit (backends_list, ",", 0); + + retval = NULL; + + for (i = 0; retval == NULL && backends[i] != NULL; i++) + { + const char *backend = backends[i]; + gboolean is_any = g_str_equal (backend, "*"); + int j; + + for (j = 0; available_backends[j].name != NULL; j++) + { + if ((is_any && allow_any) || + (is_any && strstr (allowed_backends, available_backends[j].name)) || + g_str_equal (backend, available_backends[j].name)) + { + retval = available_backends[j].create_backend (); + if (retval != NULL) + break; + } + } + } + + g_strfreev (backends); + + if (retval == NULL) + g_error ("No default Clutter backend found."); + + return retval; +} + +static void +clutter_backend_real_init_events (ClutterBackend *backend) +{ + const char *input_backend = NULL; + + input_backend = g_getenv ("CLUTTER_INPUT_BACKEND"); + if (input_backend != NULL) + input_backend = g_intern_string (input_backend); + +#ifdef CLUTTER_INPUT_X11 + if (clutter_check_windowing_backend (CLUTTER_WINDOWING_X11) && + (input_backend == NULL || input_backend == I_(CLUTTER_INPUT_X11))) + { + _clutter_backend_x11_events_init (backend); + } + else +#endif +#ifdef CLUTTER_INPUT_EVDEV + /* Evdev can be used regardless of the windowing system */ + if ((input_backend != NULL && strcmp (input_backend, CLUTTER_INPUT_EVDEV) == 0) +#ifdef CLUTTER_WINDOWING_EGL + /* but we do want to always use it for EGL native */ + || clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL) +#endif + ) + { + _clutter_events_evdev_init (backend); + } + else +#endif + if (input_backend != NULL) + { + if (input_backend != I_(CLUTTER_INPUT_NULL)) + g_error ("Unrecognized input backend '%s'", input_backend); + } + else + g_error ("Unknown input backend"); +} + +static ClutterDeviceManager * +clutter_backend_real_get_device_manager (ClutterBackend *backend) +{ + if (G_UNLIKELY (backend->device_manager == NULL)) + { + g_critical ("No device manager available, expect broken input"); + return NULL; + } + + return backend->device_manager; +} + +static gboolean +clutter_backend_real_translate_event (ClutterBackend *backend, + gpointer native, + ClutterEvent *event) +{ + GList *l; + + for (l = backend->event_translators; + l != NULL; + l = l->next) + { + ClutterEventTranslator *translator = l->data; + ClutterTranslateReturn retval; + + retval = _clutter_event_translator_translate_event (translator, + native, + event); + + if (retval == CLUTTER_TRANSLATE_QUEUE) + return TRUE; + + if (retval == CLUTTER_TRANSLATE_REMOVE) + return FALSE; + } + + return FALSE; +} + +static void +clutter_backend_class_init (ClutterBackendClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->dispose = clutter_backend_dispose; + gobject_class->finalize = clutter_backend_finalize; + + /** + * ClutterBackend::resolution-changed: + * @backend: the #ClutterBackend that emitted the signal + * + * The ::resolution-changed signal is emitted each time the font + * resolutions has been changed through #ClutterSettings. + * + * Since: 1.0 + */ + backend_signals[RESOLUTION_CHANGED] = + g_signal_new (I_("resolution-changed"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ClutterBackendClass, resolution_changed), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * ClutterBackend::font-changed: + * @backend: the #ClutterBackend that emitted the signal + * + * The ::font-changed signal is emitted each time the font options + * have been changed through #ClutterSettings. + * + * Since: 1.0 + */ + backend_signals[FONT_CHANGED] = + g_signal_new (I_("font-changed"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ClutterBackendClass, font_changed), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * ClutterBackend::settings-changed: + * @backend: the #ClutterBackend that emitted the signal + * + * The ::settings-changed signal is emitted each time the #ClutterSettings + * properties have been changed. + * + * Since: 1.4 + */ + backend_signals[SETTINGS_CHANGED] = + g_signal_new (I_("settings-changed"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ClutterBackendClass, settings_changed), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + klass->resolution_changed = clutter_backend_real_resolution_changed; + klass->font_changed = clutter_backend_real_font_changed; + + klass->init_events = clutter_backend_real_init_events; + klass->get_device_manager = clutter_backend_real_get_device_manager; + klass->translate_event = clutter_backend_real_translate_event; + klass->create_context = clutter_backend_real_create_context; + klass->get_features = clutter_backend_real_get_features; +} + +static void +clutter_backend_init (ClutterBackend *self) +{ + self->units_per_em = -1.0; + self->units_serial = 1; + + self->dummy_onscreen = COGL_INVALID_HANDLE; +} + +void +_clutter_backend_add_options (ClutterBackend *backend, + GOptionGroup *group) +{ + ClutterBackendClass *klass; + + g_assert (CLUTTER_IS_BACKEND (backend)); + + klass = CLUTTER_BACKEND_GET_CLASS (backend); + if (klass->add_options) + klass->add_options (backend, group); +} + +gboolean +_clutter_backend_pre_parse (ClutterBackend *backend, + GError **error) +{ + ClutterBackendClass *klass; + + g_assert (CLUTTER_IS_BACKEND (backend)); + + klass = CLUTTER_BACKEND_GET_CLASS (backend); + if (klass->pre_parse) + return klass->pre_parse (backend, error); + + return TRUE; +} + +gboolean +_clutter_backend_post_parse (ClutterBackend *backend, + GError **error) +{ + ClutterBackendClass *klass; + + g_assert (CLUTTER_IS_BACKEND (backend)); + + klass = CLUTTER_BACKEND_GET_CLASS (backend); + if (klass->post_parse) + return klass->post_parse (backend, error); + + return TRUE; +} + +ClutterStageWindow * +_clutter_backend_create_stage (ClutterBackend *backend, + ClutterStage *wrapper, + GError **error) +{ + ClutterBackendClass *klass; + ClutterStageWindow *stage_window; + + g_assert (CLUTTER_IS_BACKEND (backend)); + g_assert (CLUTTER_IS_STAGE (wrapper)); + + klass = CLUTTER_BACKEND_GET_CLASS (backend); + if (klass->create_stage != NULL) + stage_window = klass->create_stage (backend, wrapper, error); + else + stage_window = NULL; + + if (stage_window == NULL) + return NULL; + + g_assert (CLUTTER_IS_STAGE_WINDOW (stage_window)); + + return stage_window; +} + +gboolean +_clutter_backend_create_context (ClutterBackend *backend, + GError **error) +{ + ClutterBackendClass *klass; + + klass = CLUTTER_BACKEND_GET_CLASS (backend); + + return klass->create_context (backend, error); +} + +ClutterFeatureFlags +_clutter_backend_get_features (ClutterBackend *backend) +{ + ClutterBackendClass *klass; + GError *error; + + g_assert (CLUTTER_IS_BACKEND (backend)); + + klass = CLUTTER_BACKEND_GET_CLASS (backend); + + /* we need to have a context here; so we create the + * GL context first and the ask for features. if the + * context already exists this should be a no-op + */ + error = NULL; + if (klass->create_context != NULL) + { + gboolean res; + + res = klass->create_context (backend, &error); + if (!res) + { + if (error) + { + g_critical ("Unable to create a context: %s", error->message); + g_error_free (error); + } + else + g_critical ("Unable to create a context: unknown error"); + + return 0; + } + } + + if (klass->get_features) + return klass->get_features (backend); + + return 0; +} + +void +_clutter_backend_init_events (ClutterBackend *backend) +{ + ClutterBackendClass *klass; + + g_assert (CLUTTER_IS_BACKEND (backend)); + + klass = CLUTTER_BACKEND_GET_CLASS (backend); + klass->init_events (backend); +} + +gfloat +_clutter_backend_get_units_per_em (ClutterBackend *backend, + PangoFontDescription *font_desc) +{ + /* recompute for the font description, but do not cache the result */ + if (font_desc != NULL) + return get_units_per_em (backend, font_desc); + + if (backend->units_per_em < 0) + backend->units_per_em = get_units_per_em (backend, NULL); + + return backend->units_per_em; +} + +void +_clutter_backend_copy_event_data (ClutterBackend *backend, + const ClutterEvent *src, + ClutterEvent *dest) +{ + ClutterEventExtenderInterface *iface; + ClutterBackendClass *klass; + + klass = CLUTTER_BACKEND_GET_CLASS (backend); + if (CLUTTER_IS_EVENT_EXTENDER (backend->device_manager)) + { + iface = CLUTTER_EVENT_EXTENDER_GET_IFACE (backend->device_manager); + iface->copy_event_data (CLUTTER_EVENT_EXTENDER (backend->device_manager), + src, dest); + } + else if (klass->copy_event_data != NULL) + klass->copy_event_data (backend, src, dest); +} + +void +_clutter_backend_free_event_data (ClutterBackend *backend, + ClutterEvent *event) +{ + ClutterEventExtenderInterface *iface; + ClutterBackendClass *klass; + + klass = CLUTTER_BACKEND_GET_CLASS (backend); + + if (CLUTTER_IS_EVENT_EXTENDER (backend->device_manager)) + { + iface = CLUTTER_EVENT_EXTENDER_GET_IFACE (backend->device_manager); + iface->free_event_data (CLUTTER_EVENT_EXTENDER (backend->device_manager), + event); + } + else if (klass->free_event_data != NULL) + klass->free_event_data (backend, event); +} + +/** + * clutter_get_default_backend: + * + * Retrieves the default #ClutterBackend used by Clutter. The + * #ClutterBackend holds backend-specific configuration options. + * + * Return value: (transfer none): the default backend. You should + * not ref or unref the returned object. Applications should rarely + * need to use this. + * + * Since: 0.4 + */ +ClutterBackend * +clutter_get_default_backend (void) +{ + ClutterMainContext *clutter_context; + + clutter_context = _clutter_context_get_default (); + + return clutter_context->backend; +} + +/** + * clutter_backend_set_double_click_time: + * @backend: a #ClutterBackend + * @msec: milliseconds between two button press events + * + * Sets the maximum time between two button press events, used to + * verify whether it's a double click event or not. + * + * Since: 0.4 + * + * Deprecated: 1.4: Use #ClutterSettings:double-click-time instead + */ +void +clutter_backend_set_double_click_time (ClutterBackend *backend, + guint msec) +{ + ClutterSettings *settings = clutter_settings_get_default (); + + g_object_set (settings, "double-click-time", msec, NULL); +} + +/** + * clutter_backend_get_double_click_time: + * @backend: a #ClutterBackend + * + * Gets the maximum time between two button press events, as set + * by clutter_backend_set_double_click_time(). + * + * Return value: a time in milliseconds + * + * Since: 0.4 + * + * Deprecated: 1.4: Use #ClutterSettings:double-click-time instead + */ +guint +clutter_backend_get_double_click_time (ClutterBackend *backend) +{ + ClutterSettings *settings = clutter_settings_get_default (); + gint retval; + + g_object_get (settings, "double-click-time", &retval, NULL); + + return retval; +} + +/** + * clutter_backend_set_double_click_distance: + * @backend: a #ClutterBackend + * @distance: a distance, in pixels + * + * Sets the maximum distance used to verify a double click event. + * + * Since: 0.4 + * + * Deprecated: 1.4: Use #ClutterSettings:double-click-distance instead + */ +void +clutter_backend_set_double_click_distance (ClutterBackend *backend, + guint distance) +{ + ClutterSettings *settings = clutter_settings_get_default (); + + g_object_set (settings, "double-click-distance", distance, NULL); +} + +/** + * clutter_backend_get_double_click_distance: + * @backend: a #ClutterBackend + * + * Retrieves the distance used to verify a double click event + * + * Return value: a distance, in pixels. + * + * Since: 0.4 + * + * Deprecated: 1.4: Use #ClutterSettings:double-click-distance instead + */ +guint +clutter_backend_get_double_click_distance (ClutterBackend *backend) +{ + ClutterSettings *settings = clutter_settings_get_default (); + gint retval; + + g_object_get (settings, "double-click-distance", &retval, NULL); + + return retval; +} + +/** + * clutter_backend_set_resolution: + * @backend: a #ClutterBackend + * @dpi: the resolution in "dots per inch" (Physical inches aren't + * actually involved; the terminology is conventional). + * + * Sets the resolution for font handling on the screen. This is a + * scale factor between points specified in a #PangoFontDescription + * and cairo units. The default value is 96, meaning that a 10 point + * font will be 13 units high. (10 * 96. / 72. = 13.3). + * + * Applications should never need to call this function. + * + * Since: 0.4 + * + * Deprecated: 1.4: Use #ClutterSettings:font-dpi instead + */ +void +clutter_backend_set_resolution (ClutterBackend *backend, + gdouble dpi) +{ + ClutterSettings *settings; + gint resolution; + + g_return_if_fail (CLUTTER_IS_BACKEND (backend)); + + if (dpi < 0) + resolution = -1; + else + resolution = dpi * 1024; + + settings = clutter_settings_get_default (); + g_object_set (settings, "font-dpi", resolution, NULL); +} + +/** + * clutter_backend_get_resolution: + * @backend: a #ClutterBackend + * + * Gets the resolution for font handling on the screen. + * + * The resolution is a scale factor between points specified in a + * #PangoFontDescription and cairo units. The default value is 96.0, + * meaning that a 10 point font will be 13 units + * high (10 * 96. / 72. = 13.3). + * + * Clutter will set the resolution using the current backend when + * initializing; the resolution is also stored in the + * #ClutterSettings:font-dpi property. + * + * Return value: the current resolution, or -1 if no resolution + * has been set. + * + * Since: 0.4 + */ +gdouble +clutter_backend_get_resolution (ClutterBackend *backend) +{ + ClutterSettings *settings; + gint resolution; + + g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), -1.0); + + settings = clutter_settings_get_default (); + g_object_get (settings, "font-dpi", &resolution, NULL); + + if (resolution < 0) + return 96.0; + + return resolution / 1024.0; +} + +/** + * clutter_backend_set_font_options: + * @backend: a #ClutterBackend + * @options: Cairo font options for the backend, or %NULL + * + * Sets the new font options for @backend. The #ClutterBackend will + * copy the #cairo_font_options_t. + * + * If @options is %NULL, the first following call to + * clutter_backend_get_font_options() will return the default font + * options for @backend. + * + * This function is intended for actors creating a Pango layout + * using the PangoCairo API. + * + * Since: 0.8 + */ +void +clutter_backend_set_font_options (ClutterBackend *backend, + const cairo_font_options_t *options) +{ + g_return_if_fail (CLUTTER_IS_BACKEND (backend)); + + if (backend->font_options != options) + { + if (backend->font_options) + cairo_font_options_destroy (backend->font_options); + + if (options) + backend->font_options = cairo_font_options_copy (options); + else + backend->font_options = NULL; + + g_signal_emit (backend, backend_signals[FONT_CHANGED], 0); + } +} + +/** + * clutter_backend_get_font_options: + * @backend: a #ClutterBackend + * + * Retrieves the font options for @backend. + * + * Return value: (transfer none): the font options of the #ClutterBackend. + * The returned #cairo_font_options_t is owned by the backend and should + * not be modified or freed + * + * Since: 0.8 + */ +const cairo_font_options_t * +clutter_backend_get_font_options (ClutterBackend *backend) +{ + g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), NULL); + + if (G_LIKELY (backend->font_options)) + return backend->font_options; + + backend->font_options = cairo_font_options_create (); + + cairo_font_options_set_hint_style (backend->font_options, CAIRO_HINT_STYLE_NONE); + cairo_font_options_set_subpixel_order (backend->font_options, CAIRO_SUBPIXEL_ORDER_DEFAULT); + cairo_font_options_set_antialias (backend->font_options, CAIRO_ANTIALIAS_DEFAULT); + + g_signal_emit (backend, backend_signals[FONT_CHANGED], 0); + + return backend->font_options; +} + +/** + * clutter_backend_set_font_name: + * @backend: a #ClutterBackend + * @font_name: the name of the font + * + * Sets the default font to be used by Clutter. The @font_name string + * must either be %NULL, which means that the font name from the + * default #ClutterBackend will be used; or be something that can + * be parsed by the pango_font_description_from_string() function. + * + * Since: 1.0 + * + * Deprecated: 1.4: Use #ClutterSettings:font-name instead + */ +void +clutter_backend_set_font_name (ClutterBackend *backend, + const gchar *font_name) +{ + ClutterSettings *settings = clutter_settings_get_default (); + + g_object_set (settings, "font-name", font_name, NULL); +} + +/** + * clutter_backend_get_font_name: + * @backend: a #ClutterBackend + * + * Retrieves the default font name as set by + * clutter_backend_set_font_name(). + * + * Return value: the font name for the backend. The returned string is + * owned by the #ClutterBackend and should never be modified or freed + * + * Since: 1.0 + * + * Deprecated: 1.4: Use #ClutterSettings:font-name instead + */ +const gchar * +clutter_backend_get_font_name (ClutterBackend *backend) +{ + ClutterSettings *settings; + + g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), NULL); + + settings = clutter_settings_get_default (); + + /* XXX yuck. but we return a const pointer, so we need to + * store it in the backend + */ + g_free (backend->font_name); + g_object_get (settings, "font-name", &backend->font_name, NULL); + + return backend->font_name; +} + +gint32 +_clutter_backend_get_units_serial (ClutterBackend *backend) +{ + return backend->units_serial; +} + +gboolean +_clutter_backend_translate_event (ClutterBackend *backend, + gpointer native, + ClutterEvent *event) +{ + return CLUTTER_BACKEND_GET_CLASS (backend)->translate_event (backend, + native, + event); +} + +void +_clutter_backend_add_event_translator (ClutterBackend *backend, + ClutterEventTranslator *translator) +{ + if (g_list_find (backend->event_translators, translator) != NULL) + return; + + backend->event_translators = + g_list_prepend (backend->event_translators, translator); +} + +void +_clutter_backend_remove_event_translator (ClutterBackend *backend, + ClutterEventTranslator *translator) +{ + if (g_list_find (backend->event_translators, translator) == NULL) + return; + + backend->event_translators = + g_list_remove (backend->event_translators, translator); +} + +/** + * clutter_backend_get_cogl_context: (skip) + * @backend: a #ClutterBackend + * + * Retrieves the #CoglContext associated with the given clutter + * @backend. A #CoglContext is required when using some of the + * experimental 2.0 Cogl API. + * + * Since CoglContext is itself experimental API this API should + * be considered experimental too. + * + * This API is not yet supported on OSX because OSX still + * uses the stub Cogl winsys and the Clutter backend doesn't + * explicitly create a CoglContext. + * + * Return value: (transfer none): The #CoglContext associated with @backend. + * + * Since: 1.8 + * Stability: unstable + */ +CoglContext * +clutter_backend_get_cogl_context (ClutterBackend *backend) +{ + return backend->cogl_context; +} + +#ifdef CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT +/** + * clutter_wayland_set_compositor_display: + * @display: A compositor side struct wl_display pointer + * + * This informs Clutter of your compositor side Wayland display + * object. This must be called before calling clutter_init(). + * + * Since: 1.8 + * Stability: unstable + */ +void +clutter_wayland_set_compositor_display (void *display) +{ + if (_clutter_context_is_initialized ()) + { + g_warning ("%s() can only be used before calling clutter_init()", + G_STRFUNC); + return; + } + + _wayland_compositor_display = display; +} +#endif + +/** + * clutter_set_windowing_backend: + * @backend_type: a comma separated list of windowing backends + * + * Restricts Clutter to only use the specified backend or list of backends. + * + * You can use one of the `CLUTTER_WINDOWING_*` symbols, e.g. + * + * |[ + * clutter_set_windowing_backend (CLUTTER_WINDOWING_X11); + * ]| + * + * Will force Clutter to use the X11 windowing and input backend, and terminate + * if the X11 backend could not be initialized successfully. + * + * Since Clutter 1.26, you can also use a comma-separated list of windowing + * system backends to provide a fallback in case backends are not available or + * enabled, e.g.: + * + * |[ + * clutter_set_windowing_backend ("gdk,wayland,x11"); + * ]| + * + * Will make Clutter test for the GDK, Wayland, and X11 backends in that order. + * + * You can use the `*` special value to ask Clutter to use the internally + * defined list of backends. For instance: + * + * |[ + * clutter_set_windowing_backend ("x11,wayland,*"); + * ]| + * + * Will make Clutter test the X11 and Wayland backends, and then fall back + * to the internal list of available backends. + * + * This function must be called before the first API call to Clutter, including + * clutter_get_option_context() + * + * Since: 1.16 + */ +void +clutter_set_windowing_backend (const char *backend_type) +{ + g_return_if_fail (backend_type != NULL); + + allowed_backends = g_strdup (backend_type); +} + +void +clutter_try_set_windowing_backend (const char *backend_type) +{ + if (allowed_backends == NULL) + clutter_set_windowing_backend (backend_type); +} + +PangoDirection +_clutter_backend_get_keymap_direction (ClutterBackend *backend) +{ + ClutterBackendClass *klass; + + klass = CLUTTER_BACKEND_GET_CLASS (backend); + if (klass->get_keymap_direction != NULL) + return klass->get_keymap_direction (backend); + + return PANGO_DIRECTION_NEUTRAL; +} + +void +_clutter_backend_reset_cogl_framebuffer (ClutterBackend *backend) +{ + if (backend->dummy_onscreen == COGL_INVALID_HANDLE) + { + CoglError *internal_error = NULL; + + backend->dummy_onscreen = cogl_onscreen_new (backend->cogl_context, 1, 1); + + if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (backend->dummy_onscreen), + &internal_error)) + { + g_critical ("Unable to create dummy onscreen: %s", internal_error->message); + cogl_error_free (internal_error); + return; + } + } + + cogl_set_framebuffer (COGL_FRAMEBUFFER (backend->dummy_onscreen)); +} + +void +clutter_set_allowed_drivers (const char *drivers) +{ + if (_clutter_context_is_initialized ()) + { + g_warning ("Clutter has already been initialized.\n"); + return; + } + + allowed_drivers = g_strdup (drivers); +} diff --git a/clutter/clutter/clutter-backend.h b/clutter/clutter/clutter-backend.h new file mode 100644 index 0000000..e50f044 --- /dev/null +++ b/clutter/clutter/clutter-backend.h @@ -0,0 +1,79 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __CLUTTER_BACKEND_H__ +#define __CLUTTER_BACKEND_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +#include + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BACKEND (clutter_backend_get_type ()) +#define CLUTTER_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BACKEND, ClutterBackend)) +#define CLUTTER_IS_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BACKEND)) + +/** + * ClutterBackend: + * + * #ClutterBackend is an opaque structure whose + * members cannot be directly accessed. + * + * Since: 0.4 + */ +typedef struct _ClutterBackend ClutterBackend; +typedef struct _ClutterBackendClass ClutterBackendClass; + +CLUTTER_AVAILABLE_IN_ALL +GType clutter_backend_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_ALL +ClutterBackend * clutter_get_default_backend (void); + +CLUTTER_AVAILABLE_IN_1_16 +void clutter_set_windowing_backend (const char *backend_type); + +CLUTTER_AVAILABLE_IN_ALL +gdouble clutter_backend_get_resolution (ClutterBackend *backend); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_backend_set_font_options (ClutterBackend *backend, + const cairo_font_options_t *options); +CLUTTER_AVAILABLE_IN_ALL +const cairo_font_options_t * clutter_backend_get_font_options (ClutterBackend *backend); + +CLUTTER_AVAILABLE_IN_1_8 +CoglContext * clutter_backend_get_cogl_context (ClutterBackend *backend); + +G_END_DECLS + +#endif /* __CLUTTER_BACKEND_H__ */ diff --git a/clutter/clutter/clutter-base-types.c b/clutter/clutter/clutter-base-types.c new file mode 100644 index 0000000..1705ff9 --- /dev/null +++ b/clutter/clutter/clutter-base-types.c @@ -0,0 +1,1468 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +/** + * SECTION:clutter-geometric-types + * @Title: Base geometric types + * @Short_Description: Common geometric data types used by Clutter + * + * Clutter defines a set of geometric data structures that are commonly used + * across the whole API. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-types.h" +#include "clutter-private.h" + +#include + +#define FLOAT_EPSILON (1e-15) + + + +/* + * ClutterGeometry + */ + +static ClutterGeometry* +clutter_geometry_copy (const ClutterGeometry *geometry) +{ + return g_slice_dup (ClutterGeometry, geometry); +} + +static void +clutter_geometry_free (ClutterGeometry *geometry) +{ + if (G_LIKELY (geometry != NULL)) + g_slice_free (ClutterGeometry, geometry); +} + +/** + * clutter_geometry_union: + * @geometry_a: a #ClutterGeometry + * @geometry_b: another #ClutterGeometry + * @result: (out): location to store the result + * + * Find the union of two rectangles represented as #ClutterGeometry. + * + * Since: 1.4 + * + * Deprecated: 1.16: Use #ClutterRect and clutter_rect_union() + */ +void +clutter_geometry_union (const ClutterGeometry *geometry_a, + const ClutterGeometry *geometry_b, + ClutterGeometry *result) +{ + /* We don't try to handle rectangles that can't be represented + * as a signed integer box */ + gint x_1 = MIN (geometry_a->x, geometry_b->x); + gint y_1 = MIN (geometry_a->y, geometry_b->y); + gint x_2 = MAX (geometry_a->x + (gint)geometry_a->width, + geometry_b->x + (gint)geometry_b->width); + gint y_2 = MAX (geometry_a->y + (gint)geometry_a->height, + geometry_b->y + (gint)geometry_b->height); + result->x = x_1; + result->y = y_1; + result->width = x_2 - x_1; + result->height = y_2 - y_1; +} + +/** + * clutter_geometry_intersects: + * @geometry0: The first geometry to test + * @geometry1: The second geometry to test + * + * Determines if @geometry0 and geometry1 intersect returning %TRUE if + * they do else %FALSE. + * + * Return value: %TRUE of @geometry0 and geometry1 intersect else + * %FALSE. + * + * Since: 1.4 + * + * Deprecated: 1.16: Use #ClutterRect and clutter_rect_intersection() + */ +gboolean +clutter_geometry_intersects (const ClutterGeometry *geometry0, + const ClutterGeometry *geometry1) +{ + if (geometry1->x >= (geometry0->x + (gint)geometry0->width) || + geometry1->y >= (geometry0->y + (gint)geometry0->height) || + (geometry1->x + (gint)geometry1->width) <= geometry0->x || + (geometry1->y + (gint)geometry1->height) <= geometry0->y) + return FALSE; + else + return TRUE; +} + +static gboolean +clutter_geometry_progress (const GValue *a, + const GValue *b, + gdouble progress, + GValue *retval) +{ + const ClutterGeometry *a_geom = g_value_get_boxed (a); + const ClutterGeometry *b_geom = g_value_get_boxed (b); + ClutterGeometry res = { 0, }; + gint a_width = a_geom->width; + gint b_width = b_geom->width; + gint a_height = a_geom->height; + gint b_height = b_geom->height; + + res.x = a_geom->x + (b_geom->x - a_geom->x) * progress; + res.y = a_geom->y + (b_geom->y - a_geom->y) * progress; + + res.width = a_width + (b_width - a_width) * progress; + res.height = a_height + (b_height - a_height) * progress; + + g_value_set_boxed (retval, &res); + + return TRUE; +} + +G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterGeometry, clutter_geometry, + clutter_geometry_copy, + clutter_geometry_free, + CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_geometry_progress)); + + + +/* + * ClutterVertices + */ + +/** + * clutter_vertex_new: + * @x: X coordinate + * @y: Y coordinate + * @z: Z coordinate + * + * Creates a new #ClutterVertex for the point in 3D space + * identified by the 3 coordinates @x, @y, @z. + * + * This function is the logical equivalent of: + * + * |[ + * clutter_vertex_init (clutter_vertex_alloc (), x, y, z); + * ]| + * + * Return value: (transfer full): the newly allocated #ClutterVertex. + * Use clutter_vertex_free() to free the resources + * + * Since: 1.0 + */ +ClutterVertex * +clutter_vertex_new (gfloat x, + gfloat y, + gfloat z) +{ + return clutter_vertex_init (clutter_vertex_alloc (), x, y, z); +} + +/** + * clutter_vertex_alloc: (constructor) + * + * Allocates a new, empty #ClutterVertex. + * + * Return value: (transfer full): the newly allocated #ClutterVertex. + * Use clutter_vertex_free() to free its resources + * + * Since: 1.12 + */ +ClutterVertex * +clutter_vertex_alloc (void) +{ + return g_slice_new0 (ClutterVertex); +} + +/** + * clutter_vertex_init: + * @vertex: a #ClutterVertex + * @x: X coordinate + * @y: Y coordinate + * @z: Z coordinate + * + * Initializes @vertex with the given coordinates. + * + * Return value: (transfer none): the initialized #ClutterVertex + * + * Since: 1.10 + */ +ClutterVertex * +clutter_vertex_init (ClutterVertex *vertex, + gfloat x, + gfloat y, + gfloat z) +{ + g_return_val_if_fail (vertex != NULL, NULL); + + vertex->x = x; + vertex->y = y; + vertex->z = z; + + return vertex; +} + +/** + * clutter_vertex_copy: + * @vertex: a #ClutterVertex + * + * Copies @vertex + * + * Return value: (transfer full): a newly allocated copy of #ClutterVertex. + * Use clutter_vertex_free() to free the allocated resources + * + * Since: 1.0 + */ +ClutterVertex * +clutter_vertex_copy (const ClutterVertex *vertex) +{ + if (G_LIKELY (vertex != NULL)) + return g_slice_dup (ClutterVertex, vertex); + + return NULL; +} + +/** + * clutter_vertex_free: + * @vertex: a #ClutterVertex + * + * Frees a #ClutterVertex allocated using clutter_vertex_alloc() or + * clutter_vertex_copy(). + * + * Since: 1.0 + */ +void +clutter_vertex_free (ClutterVertex *vertex) +{ + if (G_UNLIKELY (vertex != NULL)) + g_slice_free (ClutterVertex, vertex); +} + +/** + * clutter_vertex_equal: + * @vertex_a: a #ClutterVertex + * @vertex_b: a #ClutterVertex + * + * Compares @vertex_a and @vertex_b for equality + * + * Return value: %TRUE if the passed #ClutterVertex are equal + * + * Since: 1.0 + */ +gboolean +clutter_vertex_equal (const ClutterVertex *vertex_a, + const ClutterVertex *vertex_b) +{ + g_return_val_if_fail (vertex_a != NULL && vertex_b != NULL, FALSE); + + if (vertex_a == vertex_b) + return TRUE; + + return fabsf (vertex_a->x - vertex_b->x) < FLOAT_EPSILON && + fabsf (vertex_a->y - vertex_b->y) < FLOAT_EPSILON && + fabsf (vertex_a->z - vertex_b->z) < FLOAT_EPSILON; +} + +static void +clutter_vertex_interpolate (const ClutterVertex *a, + const ClutterVertex *b, + double progress, + ClutterVertex *res) +{ + res->x = a->x + (b->x - a->x) * progress; + res->y = a->y + (b->y - a->y) * progress; + res->z = a->z + (b->z - a->z) * progress; +} + +static gboolean +clutter_vertex_progress (const GValue *a, + const GValue *b, + gdouble progress, + GValue *retval) +{ + const ClutterVertex *av = g_value_get_boxed (a); + const ClutterVertex *bv = g_value_get_boxed (b); + ClutterVertex res; + + clutter_vertex_interpolate (av, bv, progress, &res); + + g_value_set_boxed (retval, &res); + + return TRUE; +} + +G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterVertex, clutter_vertex, + clutter_vertex_copy, + clutter_vertex_free, + CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_vertex_progress)); + + + +/* + * ClutterMargin + */ + +/** + * clutter_margin_new: + * + * Creates a new #ClutterMargin. + * + * Return value: (transfer full): a newly allocated #ClutterMargin. Use + * clutter_margin_free() to free the resources associated with it when + * done. + * + * Since: 1.10 + */ +ClutterMargin * +clutter_margin_new (void) +{ + return g_slice_new0 (ClutterMargin); +} + +/** + * clutter_margin_copy: + * @margin_: a #ClutterMargin + * + * Creates a new #ClutterMargin and copies the contents of @margin_ into + * the newly created structure. + * + * Return value: (transfer full): a copy of the #ClutterMargin. + * + * Since: 1.10 + */ +ClutterMargin * +clutter_margin_copy (const ClutterMargin *margin_) +{ + if (G_LIKELY (margin_ != NULL)) + return g_slice_dup (ClutterMargin, margin_); + + return NULL; +} + +/** + * clutter_margin_free: + * @margin_: a #ClutterMargin + * + * Frees the resources allocated by clutter_margin_new() and + * clutter_margin_copy(). + * + * Since: 1.10 + */ +void +clutter_margin_free (ClutterMargin *margin_) +{ + if (G_LIKELY (margin_ != NULL)) + g_slice_free (ClutterMargin, margin_); +} + +G_DEFINE_BOXED_TYPE (ClutterMargin, clutter_margin, + clutter_margin_copy, + clutter_margin_free) + + + +/* + * ClutterPoint + */ + +static const ClutterPoint _clutter_point_zero = CLUTTER_POINT_INIT_ZERO; + +/** + * clutter_point_zero: + * + * A point centered at (0, 0). + * + * The returned value can be used as a guard. + * + * Return value: a point centered in (0, 0); the returned #ClutterPoint + * is owned by Clutter and it should not be modified or freed. + * + * Since: 1.12 + */ +const ClutterPoint * +clutter_point_zero (void) +{ + return &_clutter_point_zero; +} + +/** + * clutter_point_alloc: (constructor) + * + * Allocates a new #ClutterPoint. + * + * Return value: (transfer full): the newly allocated #ClutterPoint. + * Use clutter_point_free() to free its resources. + * + * Since: 1.12 + */ +ClutterPoint * +clutter_point_alloc (void) +{ + return g_slice_new0 (ClutterPoint); +} + +/** + * clutter_point_init: + * @point: a #ClutterPoint + * @x: the X coordinate of the point + * @y: the Y coordinate of the point + * + * Initializes @point with the given coordinates. + * + * Return value: (transfer none): the initialized #ClutterPoint + * + * Since: 1.12 + */ +ClutterPoint * +clutter_point_init (ClutterPoint *point, + float x, + float y) +{ + g_return_val_if_fail (point != NULL, NULL); + + point->x = x; + point->y = y; + + return point; +} + +/** + * clutter_point_copy: + * @point: a #ClutterPoint + * + * Creates a new #ClutterPoint with the same coordinates of @point. + * + * Return value: (transfer full): a newly allocated #ClutterPoint. + * Use clutter_point_free() to free its resources. + * + * Since: 1.12 + */ +ClutterPoint * +clutter_point_copy (const ClutterPoint *point) +{ + return g_slice_dup (ClutterPoint, point); +} + +/** + * clutter_point_free: + * @point: a #ClutterPoint + * + * Frees the resources allocated for @point. + * + * Since: 1.12 + */ +void +clutter_point_free (ClutterPoint *point) +{ + if (point != NULL && point != &_clutter_point_zero) + g_slice_free (ClutterPoint, point); +} + +/** + * clutter_point_equals: + * @a: the first #ClutterPoint to compare + * @b: the second #ClutterPoint to compare + * + * Compares two #ClutterPoint for equality. + * + * Return value: %TRUE if the #ClutterPoints are equal + * + * Since: 1.12 + */ +gboolean +clutter_point_equals (const ClutterPoint *a, + const ClutterPoint *b) +{ + if (a == b) + return TRUE; + + if (a == NULL || b == NULL) + return FALSE; + + return fabsf (a->x - b->x) < FLOAT_EPSILON && + fabsf (a->y - b->y) < FLOAT_EPSILON; +} + +/** + * clutter_point_distance: + * @a: a #ClutterPoint + * @b: a #ClutterPoint + * @x_distance: (out) (allow-none): return location for the horizontal + * distance between the points + * @y_distance: (out) (allow-none): return location for the vertical + * distance between the points + * + * Computes the distance between two #ClutterPoint. + * + * Return value: the distance between the points. + * + * Since: 1.12 + */ +float +clutter_point_distance (const ClutterPoint *a, + const ClutterPoint *b, + float *x_distance, + float *y_distance) +{ + float x_d, y_d; + + g_return_val_if_fail (a != NULL, 0.f); + g_return_val_if_fail (b != NULL, 0.f); + + if (clutter_point_equals (a, b)) + return 0.f; + + x_d = (a->x - b->x); + y_d = (a->y - b->y); + + if (x_distance != NULL) + *x_distance = fabsf (x_d); + + if (y_distance != NULL) + *y_distance = fabsf (y_d); + + return sqrt ((x_d * x_d) + (y_d * y_d)); +} + +static gboolean +clutter_point_progress (const GValue *a, + const GValue *b, + gdouble progress, + GValue *retval) +{ + const ClutterPoint *ap = g_value_get_boxed (a); + const ClutterPoint *bp = g_value_get_boxed (b); + ClutterPoint res = CLUTTER_POINT_INIT (0, 0); + + res.x = ap->x + (bp->x - ap->x) * progress; + res.y = ap->y + (bp->y - ap->y) * progress; + + g_value_set_boxed (retval, &res); + + return TRUE; +} + +G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterPoint, clutter_point, + clutter_point_copy, + clutter_point_free, + CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_point_progress)) + + + +/* + * ClutterSize + */ + +/** + * clutter_size_alloc: (constructor) + * + * Allocates a new #ClutterSize. + * + * Return value: (transfer full): the newly allocated #ClutterSize. + * Use clutter_size_free() to free its resources. + * + * Since: 1.12 + */ +ClutterSize * +clutter_size_alloc (void) +{ + return g_slice_new0 (ClutterSize); +} + +/** + * clutter_size_init: + * @size: a #ClutterSize + * @width: the width + * @height: the height + * + * Initializes a #ClutterSize with the given dimensions. + * + * Return value: (transfer none): the initialized #ClutterSize + * + * Since: 1.12 + */ +ClutterSize * +clutter_size_init (ClutterSize *size, + float width, + float height) +{ + g_return_val_if_fail (size != NULL, NULL); + + size->width = width; + size->height = height; + + return size; +} + +/** + * clutter_size_copy: + * @size: a #ClutterSize + * + * Creates a new #ClutterSize and duplicates @size. + * + * Return value: (transfer full): the newly allocated #ClutterSize. + * Use clutter_size_free() to free its resources. + * + * Since: 1.12 + */ +ClutterSize * +clutter_size_copy (const ClutterSize *size) +{ + return g_slice_dup (ClutterSize, size); +} + +/** + * clutter_size_free: + * @size: a #ClutterSize + * + * Frees the resources allocated for @size. + * + * Since: 1.12 + */ +void +clutter_size_free (ClutterSize *size) +{ + if (size != NULL) + g_slice_free (ClutterSize, size); +} + +/** + * clutter_size_equals: + * @a: a #ClutterSize to compare + * @b: a #ClutterSize to compare + * + * Compares two #ClutterSize for equality. + * + * Return value: %TRUE if the two #ClutterSize are equal + * + * Since: 1.12 + */ +gboolean +clutter_size_equals (const ClutterSize *a, + const ClutterSize *b) +{ + if (a == b) + return TRUE; + + if (a == NULL || b == NULL) + return FALSE; + + return fabsf (a->width - b->width) < FLOAT_EPSILON && + fabsf (a->height - b->height) < FLOAT_EPSILON; +} + +static gboolean +clutter_size_progress (const GValue *a, + const GValue *b, + gdouble progress, + GValue *retval) +{ + const ClutterSize *as = g_value_get_boxed (a); + const ClutterSize *bs = g_value_get_boxed (b); + ClutterSize res = CLUTTER_SIZE_INIT (0, 0); + + res.width = as->width + (bs->width - as->width) * progress; + res.height = as->height + (bs->height - as->height) * progress; + + g_value_set_boxed (retval, &res); + + return TRUE; +} + +G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterSize, clutter_size, + clutter_size_copy, + clutter_size_free, + CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_size_progress)) + + + +/* + * ClutterRect + */ + +static const ClutterRect _clutter_rect_zero = CLUTTER_RECT_INIT_ZERO; + +static gboolean clutter_rect_progress (const GValue *a, + const GValue *b, + gdouble progress, + GValue *res); + +G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterRect, clutter_rect, + clutter_rect_copy, + clutter_rect_free, + CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_rect_progress)) + +static inline void +clutter_rect_normalize_internal (ClutterRect *rect) +{ + if (rect->size.width >= 0.f && rect->size.height >= 0.f) + return; + + if (rect->size.width < 0.f) + { + float size = fabsf (rect->size.width); + + rect->origin.x -= size; + rect->size.width = size; + } + + if (rect->size.height < 0.f) + { + float size = fabsf (rect->size.height); + + rect->origin.y -= size; + rect->size.height = size; + } +} + +/** + * clutter_rect_zero: + * + * A #ClutterRect with #ClutterRect.origin set at (0, 0) and a size + * of 0. + * + * The returned value can be used as a guard. + * + * Return value: a rectangle with origin in (0, 0) and a size of 0. + * The returned #ClutterRect is owned by Clutter and it should not + * be modified or freed. + * + * Since: 1.12 + */ +const ClutterRect * +clutter_rect_zero (void) +{ + return &_clutter_rect_zero; +} + +/** + * clutter_rect_alloc: (constructor) + * + * Creates a new, empty #ClutterRect. + * + * You can use clutter_rect_init() to initialize the returned rectangle, + * for instance: + * + * |[ + * rect = clutter_rect_init (clutter_rect_alloc (), x, y, width, height); + * ]| + * + * Return value: (transfer full): the newly allocated #ClutterRect. + * Use clutter_rect_free() to free its resources + * + * Since: 1.12 + */ +ClutterRect * +clutter_rect_alloc (void) +{ + return g_slice_new0 (ClutterRect); +} + +/** + * clutter_rect_init: + * @rect: a #ClutterRect + * @x: X coordinate of the origin + * @y: Y coordinate of the origin + * @width: width of the rectangle + * @height: height of the rectangle + * + * Initializes a #ClutterRect with the given origin and size. + * + * Return value: (transfer none): the updated rectangle + * + * Since: 1.12 + */ +ClutterRect * +clutter_rect_init (ClutterRect *rect, + float x, + float y, + float width, + float height) +{ + g_return_val_if_fail (rect != NULL, NULL); + + rect->origin.x = x; + rect->origin.y = y; + + rect->size.width = width; + rect->size.height = height; + + return rect; +} + +/** + * clutter_rect_copy: + * @rect: a #ClutterRect + * + * Copies @rect into a new #ClutterRect instance. + * + * Return value: (transfer full): the newly allocate copy of @rect. + * Use clutter_rect_free() to free the associated resources + * + * Since: 1.12 + */ +ClutterRect * +clutter_rect_copy (const ClutterRect *rect) +{ + if (rect != NULL) + { + ClutterRect *res; + + res = g_slice_dup (ClutterRect, rect); + clutter_rect_normalize_internal (res); + + return res; + } + + return NULL; +} + +/** + * clutter_rect_free: + * @rect: a #ClutterRect + * + * Frees the resources allocated by @rect. + * + * Since: 1.12 + */ +void +clutter_rect_free (ClutterRect *rect) +{ + if (rect != NULL && rect != &_clutter_rect_zero) + g_slice_free (ClutterRect, rect); +} + +/** + * clutter_rect_equals: + * @a: a #ClutterRect + * @b: a #ClutterRect + * + * Checks whether @a and @b are equals. + * + * This function will normalize both @a and @b before comparing + * their origin and size. + * + * Return value: %TRUE if the rectangles match in origin and size. + * + * Since: 1.12 + */ +gboolean +clutter_rect_equals (ClutterRect *a, + ClutterRect *b) +{ + if (a == b) + return TRUE; + + if (a == NULL || b == NULL) + return FALSE; + + clutter_rect_normalize_internal (a); + clutter_rect_normalize_internal (b); + + return clutter_point_equals (&a->origin, &b->origin) && + clutter_size_equals (&a->size, &b->size); +} + +/** + * clutter_rect_normalize: + * @rect: a #ClutterRect + * + * Normalizes a #ClutterRect. + * + * A #ClutterRect is defined by the area covered by its size; this means + * that a #ClutterRect with #ClutterRect.origin in [ 0, 0 ] and a + * #ClutterRect.size of [ 10, 10 ] is equivalent to a #ClutterRect with + * #ClutterRect.origin in [ 10, 10 ] and a #ClutterRect.size of [ -10, -10 ]. + * + * This function is useful to ensure that a rectangle has positive width + * and height; it will modify the passed @rect and normalize its size. + * + * Since: 1.12 + */ +ClutterRect * +clutter_rect_normalize (ClutterRect *rect) +{ + g_return_val_if_fail (rect != NULL, NULL); + + clutter_rect_normalize_internal (rect); + + return rect; +} + +/** + * clutter_rect_get_center: + * @rect: a #ClutterRect + * @center: (out caller-allocates): a #ClutterPoint + * + * Retrieves the center of @rect, after normalizing the rectangle, + * and updates @center with the correct coordinates. + * + * Since: 1.12 + */ +void +clutter_rect_get_center (ClutterRect *rect, + ClutterPoint *center) +{ + g_return_if_fail (rect != NULL); + g_return_if_fail (center != NULL); + + clutter_rect_normalize_internal (rect); + + center->x = rect->origin.x + (rect->size.width / 2.0f); + center->y = rect->origin.y + (rect->size.height / 2.0f); +} + +/** + * clutter_rect_contains_point: + * @rect: a #ClutterRect + * @point: the point to check + * + * Checks whether @point is contained by @rect, after normalizing the + * rectangle. + * + * Return value: %TRUE if the @point is contained by @rect. + * + * Since: 1.12 + */ +gboolean +clutter_rect_contains_point (ClutterRect *rect, + ClutterPoint *point) +{ + g_return_val_if_fail (rect != NULL, FALSE); + g_return_val_if_fail (point != NULL, FALSE); + + clutter_rect_normalize_internal (rect); + + return (point->x >= rect->origin.x) && + (point->y >= rect->origin.y) && + (point->x <= (rect->origin.x + rect->size.width)) && + (point->y <= (rect->origin.y + rect->size.height)); +} + +/** + * clutter_rect_contains_rect: + * @a: a #ClutterRect + * @b: a #ClutterRect + * + * Checks whether @a contains @b. + * + * The first rectangle contains the second if the union of the + * two #ClutterRect is equal to the first rectangle. + * + * Return value: %TRUE if the first rectangle contains the second. + * + * Since: 1.12 + */ +gboolean +clutter_rect_contains_rect (ClutterRect *a, + ClutterRect *b) +{ + ClutterRect res; + + g_return_val_if_fail (a != NULL, FALSE); + g_return_val_if_fail (b != NULL, FALSE); + + clutter_rect_union (a, b, &res); + + return clutter_rect_equals (a, &res); +} + +/** + * clutter_rect_union: + * @a: a #ClutterRect + * @b: a #ClutterRect + * @res: (out caller-allocates): a #ClutterRect + * + * Computes the smallest possible rectangle capable of fully containing + * both @a and @b, and places it into @res. + * + * This function will normalize both @a and @b prior to computing their + * union. + * + * Since: 1.12 + */ +void +clutter_rect_union (ClutterRect *a, + ClutterRect *b, + ClutterRect *res) +{ + g_return_if_fail (a != NULL); + g_return_if_fail (b != NULL); + g_return_if_fail (res != NULL); + + clutter_rect_normalize_internal (a); + clutter_rect_normalize_internal (b); + + res->origin.x = MIN (a->origin.x, b->origin.x); + res->origin.y = MIN (a->origin.y, b->origin.y); + + res->size.width = MAX (a->size.width, b->size.width); + res->size.height = MAX (a->size.height, b->size.height); +} + +/** + * clutter_rect_intersection: + * @a: a #ClutterRect + * @b: a #ClutterRect + * @res: (out caller-allocates) (allow-none): a #ClutterRect, or %NULL + * + * Computes the intersection of @a and @b, and places it in @res, if @res + * is not %NULL. + * + * This function will normalize both @a and @b prior to computing their + * intersection. + * + * This function can be used to simply check if the intersection of @a and @b + * is not empty, by using %NULL for @res. + * + * Return value: %TRUE if the intersection of @a and @b is not empty + * + * Since: 1.12 + */ +gboolean +clutter_rect_intersection (ClutterRect *a, + ClutterRect *b, + ClutterRect *res) +{ + float x_1, y_1, x_2, y_2; + + g_return_val_if_fail (a != NULL, FALSE); + g_return_val_if_fail (b != NULL, FALSE); + + clutter_rect_normalize_internal (a); + clutter_rect_normalize_internal (b); + + x_1 = MAX (a->origin.x, b->origin.x); + y_1 = MAX (a->origin.y, b->origin.y); + x_2 = MIN (a->origin.x + a->size.width, b->origin.x + b->size.width); + y_2 = MIN (a->origin.y + a->size.height, b->origin.y + b->size.height); + + if (x_1 >= x_2 || y_1 >= y_2) + { + if (res != NULL) + clutter_rect_init (res, 0.f, 0.f, 0.f, 0.f); + + return FALSE; + } + + if (res != NULL) + clutter_rect_init (res, x_1, y_1, x_2 - x_1, y_2 - y_1); + + return TRUE; +} + +/** + * clutter_rect_offset: + * @rect: a #ClutterRect + * @d_x: the horizontal offset value + * @d_y: the vertical offset value + * + * Offsets the origin of @rect by the given values, after normalizing + * the rectangle. + * + * Since: 1.12 + */ +void +clutter_rect_offset (ClutterRect *rect, + float d_x, + float d_y) +{ + g_return_if_fail (rect != NULL); + + clutter_rect_normalize_internal (rect); + + rect->origin.x += d_x; + rect->origin.y += d_y; +} + +/** + * clutter_rect_inset: + * @rect: a #ClutterRect + * @d_x: an horizontal value; a positive @d_x will create an inset rectangle, + * and a negative value will create a larger rectangle + * @d_y: a vertical value; a positive @d_x will create an inset rectangle, + * and a negative value will create a larger rectangle + * + * Normalizes the @rect and offsets its origin by the @d_x and @d_y values; + * the size is adjusted by (2 * @d_x, 2 * @d_y). + * + * If @d_x and @d_y are positive the size of the rectangle is decreased; if + * the values are negative, the size of the rectangle is increased. + * + * If the resulting rectangle has a negative width or height, the size is + * set to 0. + * + * Since: 1.12 + */ +void +clutter_rect_inset (ClutterRect *rect, + float d_x, + float d_y) +{ + g_return_if_fail (rect != NULL); + + clutter_rect_normalize_internal (rect); + + rect->origin.x += d_x; + rect->origin.y += d_y; + + if (d_x >= 0.f) + rect->size.width -= (d_x * 2.f); + else + rect->size.width += (d_x * -2.f); + + if (d_y >= 0.f) + rect->size.height -= (d_y * 2.f); + else + rect->size.height += (d_y * -2.f); + + if (rect->size.width < 0.f) + rect->size.width = 0.f; + + if (rect->size.height < 0.f) + rect->size.height = 0.f; +} + +/** + * clutter_rect_clamp_to_pixel: + * @rect: a #ClutterRect + * + * Rounds the origin of @rect downwards to the nearest integer, and rounds + * the size of @rect upwards to the nearest integer, so that @rect is + * updated to the smallest rectangle capable of fully containing the + * original, fractional rectangle. + * + * Since: 1.12 + */ +void +clutter_rect_clamp_to_pixel (ClutterRect *rect) +{ + g_return_if_fail (rect != NULL); + + clutter_rect_normalize_internal (rect); + + rect->origin.x = floorf (rect->origin.x); + rect->origin.y = floorf (rect->origin.y); + + rect->size.width = ceilf (rect->size.width); + rect->size.height = ceilf (rect->size.height); +} + +/** + * clutter_rect_get_x: + * @rect: a #ClutterRect + * + * Retrieves the X coordinate of the origin of @rect. + * + * Return value: the X coordinate of the origin of the rectangle + * + * Since: 1.12 + */ +float +clutter_rect_get_x (ClutterRect *rect) +{ + g_return_val_if_fail (rect != NULL, 0.f); + + clutter_rect_normalize_internal (rect); + + return rect->origin.x; +} + +/** + * clutter_rect_get_y: + * @rect: a #ClutterRect + * + * Retrieves the Y coordinate of the origin of @rect. + * + * Return value: the Y coordinate of the origin of the rectangle + * + * Since: 1.12 + */ +float +clutter_rect_get_y (ClutterRect *rect) +{ + g_return_val_if_fail (rect != NULL, 0.f); + + clutter_rect_normalize_internal (rect); + + return rect->origin.y; +} + +/** + * clutter_rect_get_width: + * @rect: a #ClutterRect + * + * Retrieves the width of @rect. + * + * Return value: the width of the rectangle + * + * Since: 1.12 + */ +float +clutter_rect_get_width (ClutterRect *rect) +{ + g_return_val_if_fail (rect != NULL, 0.f); + + clutter_rect_normalize_internal (rect); + + return rect->size.width; +} + +/** + * clutter_rect_get_height: + * @rect: a #ClutterRect + * + * Retrieves the height of @rect. + * + * Return value: the height of the rectangle + * + * Since: 1.12 + */ +float +clutter_rect_get_height (ClutterRect *rect) +{ + g_return_val_if_fail (rect != NULL, 0.f); + + clutter_rect_normalize_internal (rect); + + return rect->size.height; +} + +static gboolean +clutter_rect_progress (const GValue *a, + const GValue *b, + gdouble progress, + GValue *retval) +{ + const ClutterRect *rect_a = g_value_get_boxed (a); + const ClutterRect *rect_b = g_value_get_boxed (b); + ClutterRect res = CLUTTER_RECT_INIT_ZERO; + +#define INTERPOLATE(r_a,r_b,member,field,factor) ((r_a)->member.field + (((r_b)->member.field - ((r_a)->member.field)) * (factor))) + + res.origin.x = INTERPOLATE (rect_a, rect_b, origin, x, progress); + res.origin.y = INTERPOLATE (rect_a, rect_b, origin, y, progress); + + res.size.width = INTERPOLATE (rect_a, rect_b, size, width, progress); + res.size.height = INTERPOLATE (rect_a, rect_b, size, height, progress); + +#undef INTERPOLATE + + g_value_set_boxed (retval, &res); + + return TRUE; +} + +/** + * ClutterMatrix: + * + * A type representing a 4x4 matrix. + * + * It is identicaly to #CoglMatrix. + * + * Since: 1.12 + */ + +static gpointer +clutter_matrix_copy (gpointer data) +{ + return cogl_matrix_copy (data); +} + +static gboolean +clutter_matrix_progress (const GValue *a, + const GValue *b, + gdouble progress, + GValue *retval) +{ + const ClutterMatrix *matrix1 = g_value_get_boxed (a); + const ClutterMatrix *matrix2 = g_value_get_boxed (b); + ClutterVertex scale1 = CLUTTER_VERTEX_INIT (1.f, 1.f, 1.f); + float shear1[3] = { 0.f, 0.f, 0.f }; + ClutterVertex rotate1 = CLUTTER_VERTEX_INIT_ZERO; + ClutterVertex translate1 = CLUTTER_VERTEX_INIT_ZERO; + ClutterVertex4 perspective1 = { 0.f, 0.f, 0.f, 0.f }; + ClutterVertex scale2 = CLUTTER_VERTEX_INIT (1.f, 1.f, 1.f); + float shear2[3] = { 0.f, 0.f, 0.f }; + ClutterVertex rotate2 = CLUTTER_VERTEX_INIT_ZERO; + ClutterVertex translate2 = CLUTTER_VERTEX_INIT_ZERO; + ClutterVertex4 perspective2 = { 0.f, 0.f, 0.f, 0.f }; + ClutterVertex scale_res = CLUTTER_VERTEX_INIT (1.f, 1.f, 1.f); + float shear_res = 0.f; + ClutterVertex rotate_res = CLUTTER_VERTEX_INIT_ZERO; + ClutterVertex translate_res = CLUTTER_VERTEX_INIT_ZERO; + ClutterVertex4 perspective_res = { 0.f, 0.f, 0.f, 0.f }; + ClutterMatrix res; + + clutter_matrix_init_identity (&res); + + _clutter_util_matrix_decompose (matrix1, + &scale1, shear1, &rotate1, &translate1, + &perspective1); + _clutter_util_matrix_decompose (matrix2, + &scale2, shear2, &rotate2, &translate2, + &perspective2); + + /* perspective */ + _clutter_util_vertex4_interpolate (&perspective1, &perspective2, progress, &perspective_res); + res.wx = perspective_res.x; + res.wy = perspective_res.y; + res.wz = perspective_res.z; + res.ww = perspective_res.w; + + /* translation */ + clutter_vertex_interpolate (&translate1, &translate2, progress, &translate_res); + cogl_matrix_translate (&res, translate_res.x, translate_res.y, translate_res.z); + + /* rotation */ + clutter_vertex_interpolate (&rotate1, &rotate2, progress, &rotate_res); + cogl_matrix_rotate (&res, rotate_res.x, 1.0f, 0.0f, 0.0f); + cogl_matrix_rotate (&res, rotate_res.y, 0.0f, 1.0f, 0.0f); + cogl_matrix_rotate (&res, rotate_res.z, 0.0f, 0.0f, 1.0f); + + /* skew */ + shear_res = shear1[2] + (shear2[2] - shear1[2]) * progress; /* YZ */ + if (shear_res != 0.f) + _clutter_util_matrix_skew_yz (&res, shear_res); + + shear_res = shear1[1] + (shear2[1] - shear1[1]) * progress; /* XZ */ + if (shear_res != 0.f) + _clutter_util_matrix_skew_xz (&res, shear_res); + + shear_res = shear1[0] + (shear2[0] - shear1[0]) * progress; /* XY */ + if (shear_res != 0.f) + _clutter_util_matrix_skew_xy (&res, shear_res); + + /* scale */ + clutter_vertex_interpolate (&scale1, &scale2, progress, &scale_res); + cogl_matrix_scale (&res, scale_res.x, scale_res.y, scale_res.z); + + g_value_set_boxed (retval, &res); + + return TRUE; +} + +G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterMatrix, clutter_matrix, + clutter_matrix_copy, + clutter_matrix_free, + CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_matrix_progress)) + +/** + * clutter_matrix_alloc: + * + * Allocates enough memory to hold a #ClutterMatrix. + * + * Return value: (transfer full): the newly allocated #ClutterMatrix + * + * Since: 1.12 + */ +ClutterMatrix * +clutter_matrix_alloc (void) +{ + return g_new0 (ClutterMatrix, 1); +} + +/** + * clutter_matrix_free: + * @matrix: (allow-none): a #ClutterMatrix + * + * Frees the memory allocated by clutter_matrix_alloc(). + * + * Since: 1.12 + */ +void +clutter_matrix_free (ClutterMatrix *matrix) +{ + cogl_matrix_free (matrix); +} + +/** + * clutter_matrix_init_identity: + * @matrix: a #ClutterMatrix + * + * Initializes @matrix with the identity matrix, i.e.: + * + * |[ + * .xx = 1.0, .xy = 0.0, .xz = 0.0, .xw = 0.0 + * .yx = 0.0, .yy = 1.0, .yz = 0.0, .yw = 0.0 + * .zx = 0.0, .zy = 0.0, .zz = 1.0, .zw = 0.0 + * .wx = 0.0, .wy = 0.0, .wz = 0.0, .ww = 1.0 + * ]| + * + * Return value: (transfer none): the initialized #ClutterMatrix + * + * Since: 1.12 + */ +ClutterMatrix * +clutter_matrix_init_identity (ClutterMatrix *matrix) +{ + cogl_matrix_init_identity (matrix); + + return matrix; +} + +/** + * clutter_matrix_init_from_array: + * @matrix: a #ClutterMatrix + * @values: (array fixed-size=16): a C array of 16 floating point values, + * representing a 4x4 matrix, with column-major order + * + * Initializes @matrix with the contents of a C array of floating point + * values. + * + * Return value: (transfer none): the initialzed #ClutterMatrix + * + * Since: 1.12 + */ +ClutterMatrix * +clutter_matrix_init_from_array (ClutterMatrix *matrix, + const float values[16]) +{ + cogl_matrix_init_from_array (matrix, values); + + return matrix; +} + +/** + * clutter_matrix_init_from_matrix: + * @a: the #ClutterMatrix to initialize + * @b: the #ClutterMatrix to copy + * + * Initializes the #ClutterMatrix @a with the contents of the + * #ClutterMatrix @b. + * + * Return value: (transfer none): the initialized #ClutterMatrix + * + * Since: 1.12 + */ +ClutterMatrix * +clutter_matrix_init_from_matrix (ClutterMatrix *a, + const ClutterMatrix *b) +{ + return memcpy (a, b, sizeof (ClutterMatrix)); +} diff --git a/clutter/clutter/clutter-bezier.c b/clutter/clutter/clutter-bezier.c new file mode 100644 index 0000000..a1d4694 --- /dev/null +++ b/clutter/clutter/clutter-bezier.c @@ -0,0 +1,514 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Tomas Frydrych + * + * Copyright (C) 2007 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "clutter-build-config.h" + +#include +#include +#include "clutter-bezier.h" +#include "clutter-debug.h" + +/* + * We have some experimental code here to allow for constant velocity + * movement of actors along the bezier path, this macro enables it. + */ +#undef CBZ_L2T_INTERPOLATION + +/**************************************************************************** + * ClutterBezier -- represenation of a cubic bezier curve * + * (private; a building block for the public bspline object) * + ****************************************************************************/ + +/* + * The t parameter of the bezier is from interval <0,1>, so we can use + * 14.18 format and special multiplication functions that preserve + * more of the least significant bits but would overflow if the value + * is > 1 + */ +#define CBZ_T_Q 18 +#define CBZ_T_ONE (1 << CBZ_T_Q) +#define CBZ_T_MUL(x,y) ((((x) >> 3) * ((y) >> 3)) >> 12) +#define CBZ_T_POW2(x) CBZ_T_MUL (x, x) +#define CBZ_T_POW3(x) CBZ_T_MUL (CBZ_T_POW2 (x), x) +#define CBZ_T_DIV(x,y) ((((x) << 9)/(y)) << 9) + +/* + * Constants for sampling of the bezier + */ +#define CBZ_T_SAMPLES 128 +#define CBZ_T_STEP (CBZ_T_ONE / CBZ_T_SAMPLES) +#define CBZ_L_STEP (CBZ_T_ONE / CBZ_T_SAMPLES) + +#define FIXED_BITS (32) +#define FIXED_Q (FIXED_BITS - 16) +#define FIXED_FROM_INT(x) ((x) << FIXED_Q) + +typedef gint32 _FixedT; + +/* + * This is a private type representing a single cubic bezier + */ +struct _ClutterBezier +{ + /* + * bezier coefficients -- these are calculated using multiplication and + * addition from integer input, so these are also integers + */ + gint ax; + gint bx; + gint cx; + gint dx; + + gint ay; + gint by; + gint cy; + gint dy; + + /* length of the bezier */ + guint length; + +#ifdef CBZ_L2T_INTERPOLATION + /* + * coefficients for the L -> t bezier; these are calculated from fixed + * point input, and more specifically numbers that have been normalised + * to fit <0,1>, so these are also fixed point, and we can used the + * _FixedT type here. + */ + _FixedT La; + _FixedT Lb; + _FixedT Lc; + /* _FixedT Ld; == 0 */ +#endif +}; + +ClutterBezier * +_clutter_bezier_new (void) +{ + return g_slice_new0 (ClutterBezier); +} + +void +_clutter_bezier_free (ClutterBezier * b) +{ + if (G_LIKELY (b)) + { + g_slice_free (ClutterBezier, b); + } +} + +ClutterBezier * +_clutter_bezier_clone_and_move (const ClutterBezier *b, gint x, gint y) +{ + ClutterBezier * b2 = _clutter_bezier_new (); + memcpy (b2, b, sizeof (ClutterBezier)); + + b2->dx += x; + b2->dy += y; + + return b2; +} + +#ifdef CBZ_L2T_INTERPOLATION +/* + * L is relative advance along the bezier curve from interval <0,1> + */ +static _FixedT +_clutter_bezier_L2t (const ClutterBezier *b, _FixedT L) +{ + _FixedT t = CBZ_T_MUL (b->La, CBZ_T_POW3(L)) + + CBZ_T_MUL (b->Lb, CBZ_T_POW2(L)) + + CBZ_T_MUL (b->Lc, L); + + if (t > CBZ_T_ONE) + t = CBZ_T_ONE; + else if (t < 0) + t = 0; + + return t; +} +#endif + +static gint +_clutter_bezier_t2x (const ClutterBezier * b, _FixedT t) +{ + /* + * NB -- the int coefficients can be at most 8192 for the multiplication + * to work in this fashion due to the limits of the 14.18 fixed. + */ + return ((b->ax*CBZ_T_POW3(t) + b->bx*CBZ_T_POW2(t) + b->cx*t) >> CBZ_T_Q) + + b->dx; +} + +static gint +_clutter_bezier_t2y (const ClutterBezier * b, _FixedT t) +{ + /* + * NB -- the int coefficients can be at most 8192 for the multiplication + * to work in this fashion due to the limits of the 14.18 fixed. + */ + return ((b->ay*CBZ_T_POW3(t) + b->by*CBZ_T_POW2(t) + b->cy*t) >> CBZ_T_Q) + + b->dy; +} + +/* + * Advances along the bezier to relative length L and returns the coordinances + * in knot + */ +void +_clutter_bezier_advance (const ClutterBezier *b, gint L, ClutterKnot * knot) +{ +#ifdef CBZ_L2T_INTERPOLATION + _FixedT t = clutter_bezier_L2t (b, L); +#else + _FixedT t = L; +#endif + + knot->x = _clutter_bezier_t2x (b, t); + knot->y = _clutter_bezier_t2y (b, t); + + CLUTTER_NOTE (MISC, "advancing to relative pt %f: t %f, {%d,%d}", + (double) L / (double) CBZ_T_ONE, + (double) t / (double) CBZ_T_ONE, + knot->x, knot->y); +} + +static int +sqrti (int number) +{ +#if defined __SSE2__ + /* The GCC built-in with SSE2 (sqrtsd) is up to twice as fast as + * the pure integer code below. It is also more accurate. + */ + return __builtin_sqrt (number); +#else + /* This is a fixed point implementation of the Quake III sqrt algorithm, + * described, for example, at + * http://www.codemaestro.com/reviews/review00000105.html + * + * While the original QIII is extremely fast, the use of floating division + * and multiplication makes it perform very on arm processors without FPU. + * + * The key to successfully replacing the floating point operations with + * fixed point is in the choice of the fixed point format. The QIII + * algorithm does not calculate the square root, but its reciprocal ('y' + * below), which is only at the end turned to the inverse value. In order + * for the algorithm to produce satisfactory results, the reciprocal value + * must be represented with sufficient precission; the 16.16 we use + * elsewhere in clutter is not good enough, and 10.22 is used instead. + */ + _FixedT x; + uint32_t y_1; /* 10.22 fixed point */ + uint32_t f = 0x600000; /* '1.5' as 10.22 fixed */ + + union + { + float f; + uint32_t i; + } flt, flt2; + + flt.f = number; + + x = FIXED_FROM_INT (number) / 2; + + /* The QIII initial estimate */ + flt.i = 0x5f3759df - ( flt.i >> 1 ); + + /* Now, we convert the float to 10.22 fixed. We exploit the mechanism + * described at http://www.d6.com/users/checker/pdfs/gdmfp.pdf. + * + * We want 22 bit fraction; a single precission float uses 23 bit + * mantisa, so we only need to add 2^(23-22) (no need for the 1.5 + * multiplier as we are only dealing with positive numbers). + * + * Note: we have to use two separate variables here -- for some reason, + * if we try to use just the flt variable, gcc on ARM optimises the whole + * addition out, and it all goes pear shape, since without it, the bits + * in the float will not be correctly aligned. + */ + flt2.f = flt.f + 2.0; + flt2.i &= 0x7FFFFF; + + /* Now we correct the estimate */ + y_1 = (flt2.i >> 11) * (flt2.i >> 11); + y_1 = (y_1 >> 8) * (x >> 8); + + y_1 = f - y_1; + flt2.i = (flt2.i >> 11) * (y_1 >> 11); + + /* If the original argument is less than 342, we do another + * iteration to improve precission (for arguments >= 342, the single + * iteration produces generally better results). + */ + if (x < 171) + { + y_1 = (flt2.i >> 11) * (flt2.i >> 11); + y_1 = (y_1 >> 8) * (x >> 8); + + y_1 = f - y_1; + flt2.i = (flt2.i >> 11) * (y_1 >> 11); + } + + /* Invert, round and convert from 10.22 to an integer + * 0x1e3c68 is a magical rounding constant that produces slightly + * better results than 0x200000. + */ + return (number * flt2.i + 0x1e3c68) >> 22; +#endif +} + +void +_clutter_bezier_init (ClutterBezier *b, + gint x_0, gint y_0, + gint x_1, gint y_1, + gint x_2, gint y_2, + gint x_3, gint y_3) +{ + _FixedT t; + int i; + int xp = x_0; + int yp = y_0; + _FixedT length [CBZ_T_SAMPLES + 1]; + +#ifdef CBZ_L2T_INTERPOLATION + int j, k; + _FixedT L; + _FixedT t_equalized [CBZ_T_SAMPLES + 1]; +#endif + +#if 0 + g_debug ("Initializing bezier at {{%d,%d},{%d,%d},{%d,%d},{%d,%d}}", + x0, y0, x1, y1, x2, y2, x3, y3); +#endif + + b->dx = x_0; + b->dy = y_0; + + b->cx = 3 * (x_1 - x_0); + b->cy = 3 * (y_1 - y_0); + + b->bx = 3 * (x_2 - x_1) - b->cx; + b->by = 3 * (y_2 - y_1) - b->cy; + + b->ax = x_3 - 3 * x_2 + 3 * x_1 - x_0; + b->ay = y_3 - 3 * y_2 + 3 * y_1 - y_0; + +#if 0 + g_debug ("Cooeficients {{%d,%d},{%d,%d},{%d,%d},{%d,%d}}", + b->ax, b->ay, b->bx, b->by, b->cx, b->cy, b->dx, b->dy); +#endif + + /* + * Because of the way we do the multiplication in bezeir_t2x,y + * these coefficients need to be at most 0x1fff; this should be the case, + * I think, but have added this warning to catch any problems -- if it + * triggers, we need to change those two functions a bit. + */ + if (b->ax > 0x1fff || b->bx > 0x1fff || b->cx > 0x1fff) + g_warning ("Calculated coefficents will result in multiplication " + "overflow in clutter_bezier_t2x and clutter_bezier_t2y."); + + /* + * Sample the bezier with CBZ_T_SAMPLES and calculate length at + * each point. + * + * We are working with integers here, so we use the fast sqrti function. + */ + length[0] = 0; + + for (t = CBZ_T_STEP, i = 1; i <= CBZ_T_SAMPLES; ++i, t += CBZ_T_STEP) + { + int x = _clutter_bezier_t2x (b, t); + int y = _clutter_bezier_t2y (b, t); + + guint l = sqrti ((y - yp)*(y - yp) + (x - xp)*(x - xp)); + + l += length[i-1]; + + length[i] = l; + + xp = x; + yp = y; + } + + b->length = length[CBZ_T_SAMPLES]; + +#if 0 + g_debug ("length %d", b->length); +#endif + +#ifdef CBZ_L2T_INTERPOLATION + /* + * Now normalize the length values, converting them into _FixedT + */ + for (i = 0; i <= CBZ_T_SAMPLES; ++i) + { + length[i] = (length[i] << CBZ_T_Q) / b->length; + } + + /* + * Now generate a L -> t table such that the L will equidistant + * over <0,1> + */ + t_equalized[0] = 0; + + for (i = 1, j = 1, L = CBZ_L_STEP; i < CBZ_T_SAMPLES; ++i, L += CBZ_L_STEP) + { + _FixedT l1, l2; + _FixedT d1, d2, d; + _FixedT t1, t2; + + /* find the band for our L */ + for (k = j; k < CBZ_T_SAMPLES; ++k) + { + if (L < length[k]) + break; + } + + /* + * Now we know that L is from (length[k-1],length[k]> + * We remember k-1 in order not to have to iterate over the + * whole length array in the next iteration of the main loop + */ + j = k - 1; + + /* + * Now interpolate equlised t as a weighted average + */ + l1 = length[k-1]; + l2 = length[k]; + d1 = l2 - L; + d2 = L - l1; + d = l2 - l1; + t1 = (k - 1) * CBZ_T_STEP; + t2 = k * CBZ_T_STEP; + + t_equalized[i] = (t1*d1 + t2*d2)/d; + + if (t_equalized[i] < t_equalized[i-1]) + g_debug ("wrong t: L %f, l1 %f, l2 %f, t1 %f, t2 %f", + (double) (L)/(double)CBZ_T_ONE, + (double) (l1)/(double)CBZ_T_ONE, + (double) (l2)/(double)CBZ_T_ONE, + (double) (t1)/(double)CBZ_T_ONE, + (double) (t2)/(double)CBZ_T_ONE); + + } + + t_equalized[CBZ_T_SAMPLES] = CBZ_T_ONE; + + /* We now fit a bezier -- at this stage, do a single fit through our values + * at 0, 1/3, 2/3 and 1 + * + * FIXME -- do we need to use a better fitting approach to choose the best + * beziere. The actual curve we acquire this way is not too bad shapwise, + * but (probably due to rounding errors) the resulting curve no longer + * satisfies the necessary condition that for L2 > L1, t2 > t1, which + * causes oscilation. + */ + +#if 0 + /* + * These are the control points we use to calculate the curve coefficients + * for bezier t(L); these are not needed directly, but are implied in the + * calculations below. + * + * (p0 is 0,0, and p3 is 1,1) + */ + p1 = (18 * t_equalized[CBZ_T_SAMPLES/3] - + 9 * t_equalized[2*CBZ_T_SAMPLES/3] + + 2 << CBZ_T_Q) / 6; + + p2 = (18 * t_equalized[2*CBZ_T_SAMPLES/3] - + 9 * t_equalized[CBZ_T_SAMPLES/3] - + (5 << CBZ_T_Q)) / 6; +#endif + + b->Lc = (18 * t_equalized[CBZ_T_SAMPLES/3] - + 9 * t_equalized[2*CBZ_T_SAMPLES/3] + + (2 << CBZ_T_Q)) >> 1; + + b->Lb = (36 * t_equalized[2*CBZ_T_SAMPLES/3] - + 45 * t_equalized[CBZ_T_SAMPLES/3] - + (9 << CBZ_T_Q)) >> 1; + + b->La = ((27 * (t_equalized[CBZ_T_SAMPLES/3] - + t_equalized[2*CBZ_T_SAMPLES/3]) + + (7 << CBZ_T_Q)) >> 1) + CBZ_T_ONE; + + g_debug ("t(1/3) %f, t(2/3) %f", + (double)t_equalized[CBZ_T_SAMPLES/3]/(double)CBZ_T_ONE, + (double)t_equalized[2*CBZ_T_SAMPLES/3]/(double)CBZ_T_ONE); + + g_debug ("L -> t coefficients: %f, %f, %f", + (double)b->La/(double)CBZ_T_ONE, + (double)b->Lb/(double)CBZ_T_ONE, + (double)b->Lc/(double)CBZ_T_ONE); + + + /* + * For debugging, you can load these values into a spreadsheet and graph + * them to see how well the approximation matches the data + */ + for (i = 0; i < CBZ_T_SAMPLES; ++i) + { + g_print ("%f, %f, %f\n", + (double)(i*CBZ_T_STEP)/(double)CBZ_T_ONE, + (double)(t_equalized[i])/(double)CBZ_T_ONE, + (double)(clutter_bezier_L2t(b,i*CBZ_T_STEP))/(double)CBZ_T_ONE); + } +#endif +} + +/* + * Moves a control point at indx to location represented by knot + */ +void +_clutter_bezier_adjust (ClutterBezier * b, ClutterKnot * knot, guint indx) +{ + guint x[4], y[4]; + + g_assert (indx < 4); + + x[0] = b->dx; + y[0] = b->dy; + + x[1] = b->cx / 3 + x[0]; + y[1] = b->cy / 3 + y[0]; + + x[2] = b->bx / 3 + b->cx + x[1]; + y[2] = b->by / 3 + b->cy + y[1]; + + x[3] = b->ax + x[0] + b->cx + b->bx; + y[3] = b->ay + y[0] + b->cy + b->by; + + x[indx] = knot->x; + y[indx] = knot->y; + + _clutter_bezier_init (b, x[0], y[0], x[1], y[1], x[2], y[2], x[3], y[3]); +} + +guint +_clutter_bezier_get_length (const ClutterBezier *b) +{ + return b->length; +} diff --git a/clutter/clutter/clutter-bezier.h b/clutter/clutter/clutter-bezier.h new file mode 100644 index 0000000..df9f617 --- /dev/null +++ b/clutter/clutter/clutter-bezier.h @@ -0,0 +1,65 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Tomas Frydrych + * + * Copyright (C) 2006, 2007 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __CLUTTER_BEZIER_H__ +#define __CLUTTER_BEZIER_H__ + +#include +#include "clutter-types.h" + +G_BEGIN_DECLS + +/* This is used in _clutter_bezier_advance to represent the full + length of the bezier curve. Anything less than that represents a + fraction of the length */ +#define CLUTTER_BEZIER_MAX_LENGTH (1 << 18) + +typedef struct _ClutterBezier ClutterBezier; + +ClutterBezier *_clutter_bezier_new (); + +void _clutter_bezier_free (ClutterBezier * b); + +ClutterBezier *_clutter_bezier_clone_and_move (const ClutterBezier *b, + gint x, + gint y); + +void _clutter_bezier_advance (const ClutterBezier *b, + gint L, + ClutterKnot *knot); + +void _clutter_bezier_init (ClutterBezier *b, + gint x_0, gint y_0, + gint x_1, gint y_1, + gint x_2, gint y_2, + gint x_3, gint y_3); + +void _clutter_bezier_adjust (ClutterBezier *b, + ClutterKnot *knot, + guint indx); + +guint _clutter_bezier_get_length (const ClutterBezier *b); + +G_END_DECLS + +#endif /* __CLUTTER_BEZIER_H__ */ diff --git a/clutter/clutter/clutter-bin-layout.c b/clutter/clutter/clutter-bin-layout.c new file mode 100644 index 0000000..764f5bc --- /dev/null +++ b/clutter/clutter/clutter-bin-layout.c @@ -0,0 +1,886 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * 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 . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-bin-layout + * @short_description: A simple layout manager + * + * #ClutterBinLayout is a layout manager which implements the following + * policy: + * + * - the preferred size is the maximum preferred size + * between all the children of the container using the + * layout; + * - each child is allocated in "layers", on on top + * of the other; + * - for each layer there are horizontal and vertical + * alignment policies. + * + * The [bin-layout example](https://git.gnome.org/browse/clutter/tree/examples/bin-layout.c?h=clutter-1.18) + * shows how to pack actors inside a #ClutterBinLayout. + * + * #ClutterBinLayout is available since Clutter 1.2 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include "deprecated/clutter-container.h" +#include "deprecated/clutter-bin-layout.h" + +#include "clutter-actor-private.h" +#include "clutter-animatable.h" +#include "clutter-child-meta.h" +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-layout-meta.h" +#include "clutter-private.h" + +#define CLUTTER_TYPE_BIN_LAYER (clutter_bin_layer_get_type ()) +#define CLUTTER_BIN_LAYER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BIN_LAYER, ClutterBinLayer)) +#define CLUTTER_IS_BIN_LAYER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BIN_LAYER)) + +typedef struct _ClutterBinLayer ClutterBinLayer; +typedef struct _ClutterLayoutMetaClass ClutterBinLayerClass; + +struct _ClutterBinLayoutPrivate +{ + ClutterBinAlignment x_align; + ClutterBinAlignment y_align; + + ClutterContainer *container; +}; + +struct _ClutterBinLayer +{ + ClutterLayoutMeta parent_instance; + + ClutterBinAlignment x_align; + ClutterBinAlignment y_align; +}; + +enum +{ + PROP_LAYER_0, + + PROP_LAYER_X_ALIGN, + PROP_LAYER_Y_ALIGN, + + PROP_LAYER_LAST +}; + +enum +{ + PROP_0, + + PROP_X_ALIGN, + PROP_Y_ALIGN, + + PROP_LAST +}; + +static GParamSpec *layer_props[PROP_LAYER_LAST] = { NULL, }; +static GParamSpec *bin_props[PROP_LAST] = { NULL, }; + +GType clutter_bin_layer_get_type (void); + +G_DEFINE_TYPE (ClutterBinLayer, + clutter_bin_layer, + CLUTTER_TYPE_LAYOUT_META) + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterBinLayout, + clutter_bin_layout, + CLUTTER_TYPE_LAYOUT_MANAGER) + +/* + * ClutterBinLayer + */ + +static void +set_layer_x_align (ClutterBinLayer *self, + ClutterBinAlignment alignment) +{ + ClutterLayoutManager *manager; + ClutterLayoutMeta *meta; + + if (self->x_align == alignment) + return; + + self->x_align = alignment; + + meta = CLUTTER_LAYOUT_META (self); + manager = clutter_layout_meta_get_manager (meta); + clutter_layout_manager_layout_changed (manager); + + g_object_notify_by_pspec (G_OBJECT (self), layer_props[PROP_LAYER_X_ALIGN]); +} + +static void +set_layer_y_align (ClutterBinLayer *self, + ClutterBinAlignment alignment) +{ + ClutterLayoutManager *manager; + ClutterLayoutMeta *meta; + + if (self->y_align == alignment) + return; + + self->y_align = alignment; + + meta = CLUTTER_LAYOUT_META (self); + manager = clutter_layout_meta_get_manager (meta); + clutter_layout_manager_layout_changed (manager); + + g_object_notify_by_pspec (G_OBJECT (self), layer_props[PROP_LAYER_Y_ALIGN]); +} + +static void +clutter_bin_layer_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterBinLayer *layer = CLUTTER_BIN_LAYER (gobject); + + switch (prop_id) + { + case PROP_LAYER_X_ALIGN: + set_layer_x_align (layer, g_value_get_enum (value)); + break; + + case PROP_LAYER_Y_ALIGN: + set_layer_y_align (layer, g_value_get_enum (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_bin_layer_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterBinLayer *layer = CLUTTER_BIN_LAYER (gobject); + + switch (prop_id) + { + case PROP_LAYER_X_ALIGN: + g_value_set_enum (value, layer->x_align); + break; + + case PROP_LAYER_Y_ALIGN: + g_value_set_enum (value, layer->y_align); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_bin_layer_class_init (ClutterBinLayerClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = clutter_bin_layer_set_property; + gobject_class->get_property = clutter_bin_layer_get_property; + + layer_props[PROP_LAYER_X_ALIGN] = + g_param_spec_enum ("x-align", + P_("Horizontal Alignment"), + P_("Horizontal alignment for the actor " + "inside the layout manager"), + CLUTTER_TYPE_BIN_ALIGNMENT, + CLUTTER_BIN_ALIGNMENT_CENTER, + CLUTTER_PARAM_READWRITE); + + layer_props[PROP_LAYER_Y_ALIGN] = + g_param_spec_enum ("y-align", + P_("Vertical Alignment"), + P_("Vertical alignment for the actor " + "inside the layout manager"), + CLUTTER_TYPE_BIN_ALIGNMENT, + CLUTTER_BIN_ALIGNMENT_CENTER, + CLUTTER_PARAM_READWRITE); + + g_object_class_install_properties (gobject_class, + PROP_LAYER_LAST, + layer_props); +} + +static void +clutter_bin_layer_init (ClutterBinLayer *layer) +{ + layer->x_align = CLUTTER_BIN_ALIGNMENT_CENTER; + layer->y_align = CLUTTER_BIN_ALIGNMENT_CENTER; +} + +/* + * ClutterBinLayout + */ + +static void +set_x_align (ClutterBinLayout *self, + ClutterBinAlignment alignment) +{ + ClutterBinLayoutPrivate *priv = self->priv; + + if (priv->x_align != alignment) + { + ClutterLayoutManager *manager; + + priv->x_align = alignment; + + manager = CLUTTER_LAYOUT_MANAGER (self); + clutter_layout_manager_layout_changed (manager); + + g_object_notify_by_pspec (G_OBJECT (self), bin_props[PROP_X_ALIGN]); + } +} + +static void +set_y_align (ClutterBinLayout *self, + ClutterBinAlignment alignment) +{ + ClutterBinLayoutPrivate *priv = self->priv; + + if (priv->y_align != alignment) + { + ClutterLayoutManager *manager; + + priv->y_align = alignment; + + manager = CLUTTER_LAYOUT_MANAGER (self); + clutter_layout_manager_layout_changed (manager); + + g_object_notify_by_pspec (G_OBJECT (self), bin_props[PROP_Y_ALIGN]); + } +} + +static void +clutter_bin_layout_get_preferred_width (ClutterLayoutManager *manager, + ClutterContainer *container, + gfloat for_height, + gfloat *min_width_p, + gfloat *nat_width_p) +{ + ClutterActor *actor = CLUTTER_ACTOR (container); + ClutterActorIter iter; + ClutterActor *child; + gfloat min_width, nat_width; + + min_width = nat_width = 0.0; + + clutter_actor_iter_init (&iter, actor); + while (clutter_actor_iter_next (&iter, &child)) + { + gfloat minimum, natural; + + if (!clutter_actor_is_visible (child)) + continue; + + clutter_actor_get_preferred_width (child, for_height, + &minimum, + &natural); + + min_width = MAX (min_width, minimum); + nat_width = MAX (nat_width, natural); + } + + if (min_width_p) + *min_width_p = min_width; + + if (nat_width_p) + *nat_width_p = nat_width; +} + +static void +clutter_bin_layout_get_preferred_height (ClutterLayoutManager *manager, + ClutterContainer *container, + gfloat for_width, + gfloat *min_height_p, + gfloat *nat_height_p) +{ + ClutterActor *actor = CLUTTER_ACTOR (container); + ClutterActorIter iter; + ClutterActor *child; + gfloat min_height, nat_height; + + min_height = nat_height = 0.0; + + clutter_actor_iter_init (&iter, actor); + while (clutter_actor_iter_next (&iter, &child)) + { + gfloat minimum, natural; + + if (!clutter_actor_is_visible (child)) + continue; + + clutter_actor_get_preferred_height (child, for_width, + &minimum, + &natural); + + min_height = MAX (min_height, minimum); + nat_height = MAX (nat_height, natural); + } + + if (min_height_p) + *min_height_p = min_height; + + if (nat_height_p) + *nat_height_p = nat_height; +} + +static gdouble +get_bin_alignment_factor (ClutterBinAlignment alignment, + ClutterTextDirection text_dir) +{ + switch (alignment) + { + case CLUTTER_BIN_ALIGNMENT_CENTER: + return 0.5; + + case CLUTTER_BIN_ALIGNMENT_START: + return text_dir == CLUTTER_TEXT_DIRECTION_LTR ? 0.0 : 1.0; + + case CLUTTER_BIN_ALIGNMENT_END: + return text_dir == CLUTTER_TEXT_DIRECTION_LTR ? 1.0 : 0.0; + + case CLUTTER_BIN_ALIGNMENT_FIXED: + case CLUTTER_BIN_ALIGNMENT_FILL: + return 0.0; + } + + return 0.0; +} + +static gdouble +get_actor_align_factor (ClutterActorAlign alignment) +{ + switch (alignment) + { + case CLUTTER_ACTOR_ALIGN_CENTER: + return 0.5; + + case CLUTTER_ACTOR_ALIGN_START: + return 0.0; + + case CLUTTER_ACTOR_ALIGN_END: + return 1.0; + + case CLUTTER_ACTOR_ALIGN_FILL: + return 0.0; + } + + return 0.0; +} + +static void +clutter_bin_layout_allocate (ClutterLayoutManager *manager, + ClutterContainer *container, + const ClutterActorBox *allocation, + ClutterAllocationFlags flags) +{ + gfloat allocation_x, allocation_y; + gfloat available_w, available_h; + ClutterActor *actor, *child; + ClutterActorIter iter; + + clutter_actor_box_get_origin (allocation, &allocation_x, &allocation_y); + clutter_actor_box_get_size (allocation, &available_w, &available_h); + + actor = CLUTTER_ACTOR (container); + + clutter_actor_iter_init (&iter, actor); + while (clutter_actor_iter_next (&iter, &child)) + { + ClutterLayoutMeta *meta; + ClutterBinLayer *layer; + ClutterActorBox child_alloc = { 0, }; + gdouble x_align, y_align; + gboolean x_fill, y_fill, is_fixed_position_set; + float fixed_x, fixed_y; + + if (!clutter_actor_is_visible (child)) + continue; + + meta = clutter_layout_manager_get_child_meta (manager, + container, + child); + layer = CLUTTER_BIN_LAYER (meta); + + fixed_x = fixed_y = 0.f; + g_object_get (child, + "fixed-position-set", &is_fixed_position_set, + "fixed-x", &fixed_x, + "fixed-y", &fixed_y, + NULL); + + /* XXX:2.0 - remove the FIXED alignment, and just use the fixed position + * of the actor if one is set + */ + if (is_fixed_position_set || + layer->x_align == CLUTTER_BIN_ALIGNMENT_FIXED) + { + if (is_fixed_position_set) + child_alloc.x1 = fixed_x; + else + child_alloc.x1 = clutter_actor_get_x (child); + } + else + child_alloc.x1 = allocation_x; + + if (is_fixed_position_set || + layer->y_align == CLUTTER_BIN_ALIGNMENT_FIXED) + { + if (is_fixed_position_set) + child_alloc.y1 = fixed_y; + else + child_alloc.y1 = clutter_actor_get_y (child); + } + else + child_alloc.y1 = allocation_y; + + child_alloc.x2 = allocation_x + available_w; + child_alloc.y2 = allocation_y + available_h; + + if (clutter_actor_needs_expand (child, CLUTTER_ORIENTATION_HORIZONTAL)) + { + ClutterActorAlign align; + + align = clutter_actor_get_x_align (child); + x_fill = align == CLUTTER_ACTOR_ALIGN_FILL; + x_align = get_actor_align_factor (align); + } + else + { + ClutterTextDirection text_dir; + + x_fill = (layer->x_align == CLUTTER_BIN_ALIGNMENT_FILL); + + text_dir = clutter_actor_get_text_direction (child); + + if (!is_fixed_position_set) + x_align = get_bin_alignment_factor (layer->x_align, text_dir); + else + x_align = 0.0; + } + + if (clutter_actor_needs_expand (child, CLUTTER_ORIENTATION_VERTICAL)) + { + ClutterActorAlign align; + + align = clutter_actor_get_y_align (child); + y_fill = align == CLUTTER_ACTOR_ALIGN_FILL; + y_align = get_actor_align_factor (align); + } + else + { + y_fill = (layer->y_align == CLUTTER_BIN_ALIGNMENT_FILL); + + if (!is_fixed_position_set) + y_align = get_bin_alignment_factor (layer->y_align, + CLUTTER_TEXT_DIRECTION_LTR); + else + y_align = 0.0; + } + + clutter_actor_allocate_align_fill (child, &child_alloc, + x_align, y_align, + x_fill, y_fill, + flags); + } +} + +static GType +clutter_bin_layout_get_child_meta_type (ClutterLayoutManager *manager) +{ + return CLUTTER_TYPE_BIN_LAYER; +} + +static ClutterLayoutMeta * +clutter_bin_layout_create_child_meta (ClutterLayoutManager *manager, + ClutterContainer *container, + ClutterActor *actor) +{ + ClutterBinLayoutPrivate *priv; + + priv = CLUTTER_BIN_LAYOUT (manager)->priv; + + return g_object_new (CLUTTER_TYPE_BIN_LAYER, + "container", container, + "actor", actor, + "manager", manager, + "x-align", priv->x_align, + "y_align", priv->y_align, + NULL); +} + +static void +clutter_bin_layout_set_container (ClutterLayoutManager *manager, + ClutterContainer *container) +{ + ClutterBinLayoutPrivate *priv; + ClutterLayoutManagerClass *parent_class; + + priv = CLUTTER_BIN_LAYOUT (manager)->priv; + priv->container = container; + + parent_class = CLUTTER_LAYOUT_MANAGER_CLASS (clutter_bin_layout_parent_class); + parent_class->set_container (manager, container); +} + +static void +clutter_bin_layout_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterBinLayout *layout = CLUTTER_BIN_LAYOUT (gobject); + + switch (prop_id) + { + case PROP_X_ALIGN: + set_x_align (layout, g_value_get_enum (value)); + break; + + case PROP_Y_ALIGN: + set_y_align (layout, g_value_get_enum (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_bin_layout_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterBinLayoutPrivate *priv; + + priv = CLUTTER_BIN_LAYOUT (gobject)->priv; + + switch (prop_id) + { + case PROP_X_ALIGN: + g_value_set_enum (value, priv->x_align); + break; + + case PROP_Y_ALIGN: + g_value_set_enum (value, priv->y_align); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_bin_layout_class_init (ClutterBinLayoutClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterLayoutManagerClass *layout_class = + CLUTTER_LAYOUT_MANAGER_CLASS (klass); + + /** + * ClutterBinLayout:x-align: + * + * The default horizontal alignment policy for actors managed + * by the #ClutterBinLayout + * + * Since: 1.2 + * + * Deprecated: 1.12: Use the #ClutterActor:x-expand and the + * #ClutterActor:x-align properties on #ClutterActor instead. + */ + bin_props[PROP_X_ALIGN] = + g_param_spec_enum ("x-align", + P_("Horizontal Alignment"), + P_("Default horizontal alignment for the actors " + "inside the layout manager"), + CLUTTER_TYPE_BIN_ALIGNMENT, + CLUTTER_BIN_ALIGNMENT_CENTER, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterBinLayout:y-align: + * + * The default vertical alignment policy for actors managed + * by the #ClutterBinLayout + * + * Since: 1.2 + * + * Deprecated: 1.12: Use the #ClutterActor:y-expand and the + * #ClutterActor:y-align properties on #ClutterActor instead. + */ + bin_props[PROP_Y_ALIGN] = + g_param_spec_enum ("y-align", + P_("Vertical Alignment"), + P_("Default vertical alignment for the actors " + "inside the layout manager"), + CLUTTER_TYPE_BIN_ALIGNMENT, + CLUTTER_BIN_ALIGNMENT_CENTER, + CLUTTER_PARAM_READWRITE); + + gobject_class->set_property = clutter_bin_layout_set_property; + gobject_class->get_property = clutter_bin_layout_get_property; + g_object_class_install_properties (gobject_class, PROP_LAST, bin_props); + + layout_class->get_preferred_width = clutter_bin_layout_get_preferred_width; + layout_class->get_preferred_height = clutter_bin_layout_get_preferred_height; + layout_class->allocate = clutter_bin_layout_allocate; + layout_class->create_child_meta = clutter_bin_layout_create_child_meta; + layout_class->get_child_meta_type = clutter_bin_layout_get_child_meta_type; + layout_class->set_container = clutter_bin_layout_set_container; +} + +static void +clutter_bin_layout_init (ClutterBinLayout *self) +{ + self->priv = clutter_bin_layout_get_instance_private (self); + + self->priv->x_align = CLUTTER_BIN_ALIGNMENT_CENTER; + self->priv->y_align = CLUTTER_BIN_ALIGNMENT_CENTER; +} + +/** + * clutter_bin_layout_new: + * @x_align: the default alignment policy to be used on the + * horizontal axis + * @y_align: the default alignment policy to be used on the + * vertical axis + * + * Creates a new #ClutterBinLayout layout manager + * + * Return value: the newly created layout manager + * + * Since: 1.2 + */ +ClutterLayoutManager * +clutter_bin_layout_new (ClutterBinAlignment x_align, + ClutterBinAlignment y_align) +{ + return g_object_new (CLUTTER_TYPE_BIN_LAYOUT, + "x-align", x_align, + "y-align", y_align, + NULL); +} + +/** + * clutter_bin_layout_set_alignment: + * @self: a #ClutterBinLayout + * @child: (allow-none): a child of @container + * @x_align: the horizontal alignment policy to be used for the @child + * inside @container + * @y_align: the vertical aligment policy to be used on the @child + * inside @container + * + * Sets the horizontal and vertical alignment policies to be applied + * to a @child of @self + * + * If @child is %NULL then the @x_align and @y_align values will + * be set as the default alignment policies + * + * Since: 1.2 + * + * Deprecated: 1.12: Use the #ClutterActor:x-align and + * #ClutterActor:y-align properties of #ClutterActor instead. + */ +void +clutter_bin_layout_set_alignment (ClutterBinLayout *self, + ClutterActor *child, + ClutterBinAlignment x_align, + ClutterBinAlignment y_align) +{ + ClutterBinLayoutPrivate *priv; + ClutterLayoutManager *manager; + ClutterLayoutMeta *meta; + + g_return_if_fail (CLUTTER_IS_BIN_LAYOUT (self)); + g_return_if_fail (child == NULL || CLUTTER_IS_ACTOR (child)); + + priv = self->priv; + + if (priv->container == NULL) + { + if (child == NULL) + { + set_x_align (self, x_align); + set_y_align (self, y_align); + } + else + g_warning ("The layout of type '%s' must be associated to " + "a ClutterContainer before setting the alignment " + "on its children", + G_OBJECT_TYPE_NAME (self)); + + return; + } + + manager = CLUTTER_LAYOUT_MANAGER (self); + meta = clutter_layout_manager_get_child_meta (manager, + priv->container, + child); + g_assert (CLUTTER_IS_BIN_LAYER (meta)); + + set_layer_x_align (CLUTTER_BIN_LAYER (meta), x_align); + set_layer_y_align (CLUTTER_BIN_LAYER (meta), y_align); +} + +/** + * clutter_bin_layout_get_alignment: + * @self: a #ClutterBinLayout + * @child: (allow-none): a child of @container + * @x_align: (out) (allow-none): return location for the horizontal + * alignment policy + * @y_align: (out) (allow-none): return location for the vertical + * alignment policy + * + * Retrieves the horizontal and vertical alignment policies for + * a child of @self + * + * If @child is %NULL the default alignment policies will be returned + * instead + * + * Since: 1.2 + * + * Deprecated: 1.12: Use the #ClutterActor:x-align and the + * #ClutterActor:y-align properties of #ClutterActor instead. + */ +void +clutter_bin_layout_get_alignment (ClutterBinLayout *self, + ClutterActor *child, + ClutterBinAlignment *x_align, + ClutterBinAlignment *y_align) +{ + ClutterBinLayoutPrivate *priv; + ClutterLayoutManager *manager; + ClutterLayoutMeta *meta; + ClutterBinLayer *layer; + + g_return_if_fail (CLUTTER_IS_BIN_LAYOUT (self)); + + priv = self->priv; + + if (priv->container == NULL) + { + if (child == NULL) + { + if (x_align) + *x_align = priv->x_align; + + if (y_align) + *y_align = priv->y_align; + } + else + g_warning ("The layout of type '%s' must be associated to " + "a ClutterContainer before getting the alignment " + "of its children", + G_OBJECT_TYPE_NAME (self)); + + return; + } + + manager = CLUTTER_LAYOUT_MANAGER (self); + meta = clutter_layout_manager_get_child_meta (manager, + priv->container, + child); + g_assert (CLUTTER_IS_BIN_LAYER (meta)); + + layer = CLUTTER_BIN_LAYER (meta); + + if (x_align) + *x_align = layer->x_align; + + if (y_align) + *y_align = layer->y_align; +} + +/** + * clutter_bin_layout_add: + * @self: a #ClutterBinLayout + * @child: a #ClutterActor + * @x_align: horizontal alignment policy for @child + * @y_align: vertical alignment policy for @child + * + * Adds a #ClutterActor to the container using @self and + * sets the alignment policies for it + * + * This function is equivalent to clutter_container_add_actor() + * and clutter_layout_manager_child_set_property() but it does not + * require a pointer to the #ClutterContainer associated to the + * #ClutterBinLayout + * + * Since: 1.2 + * + * Deprecated: 1.12: Use clutter_actor_add_child() instead. + */ +void +clutter_bin_layout_add (ClutterBinLayout *self, + ClutterActor *child, + ClutterBinAlignment x_align, + ClutterBinAlignment y_align) +{ + ClutterBinLayoutPrivate *priv; + ClutterLayoutManager *manager; + ClutterLayoutMeta *meta; + + g_return_if_fail (CLUTTER_IS_BIN_LAYOUT (self)); + g_return_if_fail (CLUTTER_IS_ACTOR (child)); + + priv = self->priv; + + if (priv->container == NULL) + { + g_warning ("The layout of type '%s' must be associated to " + "a ClutterContainer before adding children", + G_OBJECT_TYPE_NAME (self)); + return; + } + + clutter_container_add_actor (priv->container, child); + + manager = CLUTTER_LAYOUT_MANAGER (self); + meta = clutter_layout_manager_get_child_meta (manager, + priv->container, + child); + g_assert (CLUTTER_IS_BIN_LAYER (meta)); + + set_layer_x_align (CLUTTER_BIN_LAYER (meta), x_align); + set_layer_y_align (CLUTTER_BIN_LAYER (meta), y_align); +} diff --git a/clutter/clutter/clutter-bin-layout.h b/clutter/clutter/clutter-bin-layout.h new file mode 100644 index 0000000..f823b70 --- /dev/null +++ b/clutter/clutter/clutter-bin-layout.h @@ -0,0 +1,86 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * 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 . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_BIN_LAYOUT_H__ +#define __CLUTTER_BIN_LAYOUT_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BIN_LAYOUT (clutter_bin_layout_get_type ()) +#define CLUTTER_BIN_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BIN_LAYOUT, ClutterBinLayout)) +#define CLUTTER_IS_BIN_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BIN_LAYOUT)) +#define CLUTTER_BIN_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BIN_LAYOUT, ClutterBinLayoutClass)) +#define CLUTTER_IS_BIN_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BIN_LAYOUT)) +#define CLUTTER_BIN_LAYOUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BIN_LAYOUT, ClutterBinLayoutClass)) + +typedef struct _ClutterBinLayout ClutterBinLayout; +typedef struct _ClutterBinLayoutPrivate ClutterBinLayoutPrivate; +typedef struct _ClutterBinLayoutClass ClutterBinLayoutClass; + +/** + * ClutterBinLayout: + * + * The #ClutterBinLayout structure contains only private data + * and should be accessed using the provided API + * + * Since: 1.2 + */ +struct _ClutterBinLayout +{ + /*< private >*/ + ClutterLayoutManager parent_instance; + + ClutterBinLayoutPrivate *priv; +}; + +/** + * ClutterBinLayoutClass: + * + * The #ClutterBinLayoutClass structure contains only private + * data and should be accessed using the provided API + * + * Since: 1.2 + */ +struct _ClutterBinLayoutClass +{ + /*< private >*/ + ClutterLayoutManagerClass parent_class; +}; + +CLUTTER_AVAILABLE_IN_1_2 +GType clutter_bin_layout_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_2 +ClutterLayoutManager * clutter_bin_layout_new (ClutterBinAlignment x_align, + ClutterBinAlignment y_align); + +G_END_DECLS + +#endif /* __CLUTTER_BIN_LAYOUT_H__ */ diff --git a/clutter/clutter/clutter-bind-constraint.c b/clutter/clutter/clutter-bind-constraint.c new file mode 100644 index 0000000..93831f5 --- /dev/null +++ b/clutter/clutter/clutter-bind-constraint.c @@ -0,0 +1,591 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-bind-constraint + * @Title: ClutterBindConstraint + * @Short_Description: A constraint binding the position or size of an actor + * + * #ClutterBindConstraint is a #ClutterConstraint that binds the + * position or the size of the #ClutterActor to which it is applied + * to the the position or the size of another #ClutterActor, or + * "source". + * + * An offset can be applied to the constraint, to avoid overlapping. The offset + * can also be animated. For instance, the following code will set up three + * actors to be bound to the same origin: + * + * |[ + * // source + * rect[0] = clutter_rectangle_new_with_color (&red_color); + * clutter_actor_set_position (rect[0], x_pos, y_pos); + * clutter_actor_set_size (rect[0], 100, 100); + * + * // second rectangle + * rect[1] = clutter_rectangle_new_with_color (&green_color); + * clutter_actor_set_size (rect[1], 100, 100); + * clutter_actor_set_opacity (rect[1], 0); + * + * constraint = clutter_bind_constraint_new (rect[0], CLUTTER_BIND_X, 0.0); + * clutter_actor_add_constraint_with_name (rect[1], "green-x", constraint); + * constraint = clutter_bind_constraint_new (rect[0], CLUTTER_BIND_Y, 0.0); + * clutter_actor_add_constraint_with_name (rect[1], "green-y", constraint); + * + * // third rectangle + * rect[2] = clutter_rectangle_new_with_color (&blue_color); + * clutter_actor_set_size (rect[2], 100, 100); + * clutter_actor_set_opacity (rect[2], 0); + * + * constraint = clutter_bind_constraint_new (rect[0], CLUTTER_BIND_X, 0.0); + * clutter_actor_add_constraint_with_name (rect[2], "blue-x", constraint); + * constraint = clutter_bind_constraint_new (rect[0], CLUTTER_BIND_Y, 0.0); + * clutter_actor_add_constraint_with_name (rect[2], "blue-y", constraint); + * ]| + * + * The following code animates the second and third rectangles to "expand" + * them horizontally from underneath the first rectangle: + * + * |[ + * clutter_actor_animate (rect[1], CLUTTER_EASE_OUT_CUBIC, 250, + * "@constraints.green-x.offset", 100.0, + * "opacity", 255, + * NULL); + * clutter_actor_animate (rect[2], CLUTTER_EASE_OUT_CUBIC, 250, + * "@constraints.blue-x.offset", 200.0, + * "opacity", 255, + * NULL); + * ]| + * + * #ClutterBindConstraint is available since Clutter 1.4 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#include "clutter-bind-constraint.h" + +#include "clutter-actor-meta-private.h" +#include "clutter-actor-private.h" +#include "clutter-constraint.h" +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-private.h" + +#define CLUTTER_BIND_CONSTRAINT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BIND_CONSTRAINT, ClutterBindConstraintClass)) +#define CLUTTER_IS_BIND_CONSTRAINT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BIND_CONSTRAINT)) +#define CLUTTER_BIND_CONSTRAINT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BIND_CONSTRAINT, ClutterBindConstraintClass)) + +struct _ClutterBindConstraint +{ + ClutterConstraint parent_instance; + + ClutterActor *actor; + ClutterActor *source; + ClutterBindCoordinate coordinate; + gfloat offset; +}; + +struct _ClutterBindConstraintClass +{ + ClutterConstraintClass parent_class; +}; + +enum +{ + PROP_0, + + PROP_SOURCE, + PROP_COORDINATE, + PROP_OFFSET, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +G_DEFINE_TYPE (ClutterBindConstraint, + clutter_bind_constraint, + CLUTTER_TYPE_CONSTRAINT); + +static void +source_queue_relayout (ClutterActor *source, + ClutterBindConstraint *bind) +{ + if (bind->actor != NULL) + _clutter_actor_queue_only_relayout (bind->actor); +} + +static void +source_destroyed (ClutterActor *actor, + ClutterBindConstraint *bind) +{ + bind->source = NULL; +} + +static void +clutter_bind_constraint_update_allocation (ClutterConstraint *constraint, + ClutterActor *actor, + ClutterActorBox *allocation) +{ + ClutterBindConstraint *bind = CLUTTER_BIND_CONSTRAINT (constraint); + gfloat source_width, source_height; + gfloat actor_width, actor_height; + ClutterVertex source_position = { 0., }; + + if (bind->source == NULL) + return; + + source_position.x = clutter_actor_get_x (bind->source); + source_position.y = clutter_actor_get_y (bind->source); + clutter_actor_get_size (bind->source, &source_width, &source_height); + + clutter_actor_box_get_size (allocation, &actor_width, &actor_height); + + switch (bind->coordinate) + { + case CLUTTER_BIND_X: + allocation->x1 = source_position.x + bind->offset; + allocation->x2 = allocation->x1 + actor_width; + break; + + case CLUTTER_BIND_Y: + allocation->y1 = source_position.y + bind->offset; + allocation->y2 = allocation->y1 + actor_height; + break; + + case CLUTTER_BIND_POSITION: + allocation->x1 = source_position.x + bind->offset; + allocation->y1 = source_position.y + bind->offset; + allocation->x2 = allocation->x1 + actor_width; + allocation->y2 = allocation->y1 + actor_height; + break; + + case CLUTTER_BIND_WIDTH: + allocation->x2 = allocation->x1 + source_width + bind->offset; + break; + + case CLUTTER_BIND_HEIGHT: + allocation->y2 = allocation->y1 + source_height + bind->offset; + break; + + case CLUTTER_BIND_SIZE: + allocation->x2 = allocation->x1 + source_width + bind->offset; + allocation->y2 = allocation->y1 + source_height + bind->offset; + break; + + case CLUTTER_BIND_ALL: + allocation->x1 = source_position.x + bind->offset; + allocation->y1 = source_position.y + bind->offset; + allocation->x2 = allocation->x1 + source_width + bind->offset; + allocation->y2 = allocation->y1 + source_height + bind->offset; + break; + + default: + g_assert_not_reached (); + break; + } + + clutter_actor_box_clamp_to_pixel (allocation); +} + +static void +clutter_bind_constraint_set_actor (ClutterActorMeta *meta, + ClutterActor *new_actor) +{ + ClutterBindConstraint *bind = CLUTTER_BIND_CONSTRAINT (meta); + ClutterActorMetaClass *parent; + + if (new_actor != NULL && + bind->source != NULL && + clutter_actor_contains (new_actor, bind->source)) + { + g_warning (G_STRLOC ": The source actor '%s' is contained " + "by the actor '%s' associated to the constraint " + "'%s'", + _clutter_actor_get_debug_name (bind->source), + _clutter_actor_get_debug_name (new_actor), + _clutter_actor_meta_get_debug_name (meta)); + return; + } + + /* store the pointer to the actor, for later use */ + bind->actor = new_actor; + + parent = CLUTTER_ACTOR_META_CLASS (clutter_bind_constraint_parent_class); + parent->set_actor (meta, new_actor); +} + +static void +clutter_bind_constraint_dispose (GObject *gobject) +{ + ClutterBindConstraint *bind = CLUTTER_BIND_CONSTRAINT (gobject); + + if (bind->source != NULL) + { + g_signal_handlers_disconnect_by_func (bind->source, + G_CALLBACK (source_destroyed), + bind); + g_signal_handlers_disconnect_by_func (bind->source, + G_CALLBACK (source_queue_relayout), + bind); + bind->source = NULL; + } + + G_OBJECT_CLASS (clutter_bind_constraint_parent_class)->dispose (gobject); +} + +static void +clutter_bind_constraint_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterBindConstraint *bind = CLUTTER_BIND_CONSTRAINT (gobject); + + switch (prop_id) + { + case PROP_SOURCE: + clutter_bind_constraint_set_source (bind, g_value_get_object (value)); + break; + + case PROP_COORDINATE: + clutter_bind_constraint_set_coordinate (bind, g_value_get_enum (value)); + break; + + case PROP_OFFSET: + clutter_bind_constraint_set_offset (bind, g_value_get_float (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_bind_constraint_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterBindConstraint *bind = CLUTTER_BIND_CONSTRAINT (gobject); + + switch (prop_id) + { + case PROP_SOURCE: + g_value_set_object (value, bind->source); + break; + + case PROP_COORDINATE: + g_value_set_enum (value, bind->coordinate); + break; + + case PROP_OFFSET: + g_value_set_float (value, bind->offset); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_bind_constraint_class_init (ClutterBindConstraintClass *klass) +{ + ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass); + ClutterConstraintClass *constraint_class = CLUTTER_CONSTRAINT_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = clutter_bind_constraint_set_property; + gobject_class->get_property = clutter_bind_constraint_get_property; + gobject_class->dispose = clutter_bind_constraint_dispose; + + meta_class->set_actor = clutter_bind_constraint_set_actor; + + constraint_class->update_allocation = clutter_bind_constraint_update_allocation; + /** + * ClutterBindConstraint:source: + * + * The #ClutterActor used as the source for the binding. + * + * The #ClutterActor must not be contained inside the actor associated + * to the constraint. + * + * Since: 1.4 + */ + obj_props[PROP_SOURCE] = + g_param_spec_object ("source", + P_("Source"), + P_("The source of the binding"), + CLUTTER_TYPE_ACTOR, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT); + + /** + * ClutterBindConstraint:coordinate: + * + * The coordinate to be bound + * + * Since: 1.4 + */ + obj_props[PROP_COORDINATE] = + g_param_spec_enum ("coordinate", + P_("Coordinate"), + P_("The coordinate to bind"), + CLUTTER_TYPE_BIND_COORDINATE, + CLUTTER_BIND_X, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT); + + /** + * ClutterBindConstraint:offset: + * + * The offset, in pixels, to be applied to the binding + * + * Since: 1.4 + */ + obj_props[PROP_OFFSET] = + g_param_spec_float ("offset", + P_("Offset"), + P_("The offset in pixels to apply to the binding"), + -G_MAXFLOAT, G_MAXFLOAT, + 0.0f, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT); + + g_object_class_install_properties (gobject_class, + PROP_LAST, + obj_props); +} + +static void +clutter_bind_constraint_init (ClutterBindConstraint *self) +{ + self->actor = NULL; + self->source = NULL; + self->coordinate = CLUTTER_BIND_X; + self->offset = 0.0f; +} + +/** + * clutter_bind_constraint_new: + * @source: (allow-none): the #ClutterActor to use as the source of + * the binding, or %NULL + * @coordinate: the coordinate to bind + * @offset: the offset to apply to the binding, in pixels + * + * Creates a new constraint, binding a #ClutterActor's position to + * the given @coordinate of the position of @source + * + * Return value: the newly created #ClutterBindConstraint + * + * Since: 1.4 + */ +ClutterConstraint * +clutter_bind_constraint_new (ClutterActor *source, + ClutterBindCoordinate coordinate, + gfloat offset) +{ + g_return_val_if_fail (source == NULL || CLUTTER_IS_ACTOR (source), NULL); + + return g_object_new (CLUTTER_TYPE_BIND_CONSTRAINT, + "source", source, + "coordinate", coordinate, + "offset", offset, + NULL); +} + +/** + * clutter_bind_constraint_set_source: + * @constraint: a #ClutterBindConstraint + * @source: (allow-none): a #ClutterActor, or %NULL to unset the source + * + * Sets the source #ClutterActor for the constraint + * + * Since: 1.4 + */ +void +clutter_bind_constraint_set_source (ClutterBindConstraint *constraint, + ClutterActor *source) +{ + ClutterActor *old_source, *actor; + ClutterActorMeta *meta; + + g_return_if_fail (CLUTTER_IS_BIND_CONSTRAINT (constraint)); + g_return_if_fail (source == NULL || CLUTTER_IS_ACTOR (source)); + + if (constraint->source == source) + return; + + meta = CLUTTER_ACTOR_META (constraint); + actor = clutter_actor_meta_get_actor (meta); + if (source != NULL && actor != NULL) + { + if (clutter_actor_contains (actor, source)) + { + g_warning (G_STRLOC ": The source actor '%s' is contained " + "by the actor '%s' associated to the constraint " + "'%s'", + _clutter_actor_get_debug_name (source), + _clutter_actor_get_debug_name (actor), + _clutter_actor_meta_get_debug_name (meta)); + return; + } + } + + old_source = constraint->source; + if (old_source != NULL) + { + g_signal_handlers_disconnect_by_func (old_source, + G_CALLBACK (source_destroyed), + constraint); + g_signal_handlers_disconnect_by_func (old_source, + G_CALLBACK (source_queue_relayout), + constraint); + } + + constraint->source = source; + if (constraint->source != NULL) + { + g_signal_connect (constraint->source, "queue-relayout", + G_CALLBACK (source_queue_relayout), + constraint); + g_signal_connect (constraint->source, "destroy", + G_CALLBACK (source_destroyed), + constraint); + + if (constraint->actor != NULL) + clutter_actor_queue_relayout (constraint->actor); + } + + g_object_notify_by_pspec (G_OBJECT (constraint), obj_props[PROP_SOURCE]); +} + +/** + * clutter_bind_constraint_get_source: + * @constraint: a #ClutterBindConstraint + * + * Retrieves the #ClutterActor set using clutter_bind_constraint_set_source() + * + * Return value: (transfer none): a pointer to the source actor + * + * Since: 1.4 + */ +ClutterActor * +clutter_bind_constraint_get_source (ClutterBindConstraint *constraint) +{ + g_return_val_if_fail (CLUTTER_IS_BIND_CONSTRAINT (constraint), NULL); + + return constraint->source; +} + +/** + * clutter_bind_constraint_set_coordinate: + * @constraint: a #ClutterBindConstraint + * @coordinate: the coordinate to bind + * + * Sets the coordinate to bind in the constraint + * + * Since: 1.4 + */ +void +clutter_bind_constraint_set_coordinate (ClutterBindConstraint *constraint, + ClutterBindCoordinate coordinate) +{ + g_return_if_fail (CLUTTER_IS_BIND_CONSTRAINT (constraint)); + + if (constraint->coordinate == coordinate) + return; + + constraint->coordinate = coordinate; + + if (constraint->actor != NULL) + clutter_actor_queue_relayout (constraint->actor); + + g_object_notify_by_pspec (G_OBJECT (constraint), obj_props[PROP_COORDINATE]); +} + +/** + * clutter_bind_constraint_get_coordinate: + * @constraint: a #ClutterBindConstraint + * + * Retrieves the bound coordinate of the constraint + * + * Return value: the bound coordinate + * + * Since: 1.4 + */ +ClutterBindCoordinate +clutter_bind_constraint_get_coordinate (ClutterBindConstraint *constraint) +{ + g_return_val_if_fail (CLUTTER_IS_BIND_CONSTRAINT (constraint), + CLUTTER_BIND_X); + + return constraint->coordinate; +} + +/** + * clutter_bind_constraint_set_offset: + * @constraint: a #ClutterBindConstraint + * @offset: the offset to apply, in pixels + * + * Sets the offset to be applied to the constraint + * + * Since: 1.4 + */ +void +clutter_bind_constraint_set_offset (ClutterBindConstraint *constraint, + gfloat offset) +{ + g_return_if_fail (CLUTTER_IS_BIND_CONSTRAINT (constraint)); + + if (fabs (constraint->offset - offset) < 0.00001f) + return; + + constraint->offset = offset; + + if (constraint->actor != NULL) + clutter_actor_queue_relayout (constraint->actor); + + g_object_notify_by_pspec (G_OBJECT (constraint), obj_props[PROP_OFFSET]); +} + +/** + * clutter_bind_constraint_get_offset: + * @constraint: a #ClutterBindConstraint + * + * Retrieves the offset set using clutter_bind_constraint_set_offset() + * + * Return value: the offset, in pixels + * + * Since: 1.4 + */ +gfloat +clutter_bind_constraint_get_offset (ClutterBindConstraint *bind) +{ + g_return_val_if_fail (CLUTTER_IS_BIND_CONSTRAINT (bind), 0.0); + + return bind->offset; +} diff --git a/clutter/clutter/clutter-bind-constraint.h b/clutter/clutter/clutter-bind-constraint.h new file mode 100644 index 0000000..523fb18 --- /dev/null +++ b/clutter/clutter/clutter-bind-constraint.h @@ -0,0 +1,77 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_BIND_CONSTRAINT_H__ +#define __CLUTTER_BIND_CONSTRAINT_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BIND_CONSTRAINT (clutter_bind_constraint_get_type ()) +#define CLUTTER_BIND_CONSTRAINT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BIND_CONSTRAINT, ClutterBindConstraint)) +#define CLUTTER_IS_BIND_CONSTRAINT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BIND_CONSTRAINT)) + +/** + * ClutterBindConstraint: + * + * #ClutterBindConstraint is an opaque structure + * whose members cannot be directly accessed + * + * Since: 1.4 + */ +typedef struct _ClutterBindConstraint ClutterBindConstraint; +typedef struct _ClutterBindConstraintClass ClutterBindConstraintClass; + +CLUTTER_AVAILABLE_IN_1_4 +GType clutter_bind_constraint_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_4 +ClutterConstraint * clutter_bind_constraint_new (ClutterActor *source, + ClutterBindCoordinate coordinate, + gfloat offset); + +CLUTTER_AVAILABLE_IN_1_4 +void clutter_bind_constraint_set_source (ClutterBindConstraint *constraint, + ClutterActor *source); +CLUTTER_AVAILABLE_IN_1_4 +ClutterActor * clutter_bind_constraint_get_source (ClutterBindConstraint *constraint); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_bind_constraint_set_coordinate (ClutterBindConstraint *constraint, + ClutterBindCoordinate coordinate); +CLUTTER_AVAILABLE_IN_1_4 +ClutterBindCoordinate clutter_bind_constraint_get_coordinate (ClutterBindConstraint *constraint); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_bind_constraint_set_offset (ClutterBindConstraint *constraint, + gfloat offset); +CLUTTER_AVAILABLE_IN_1_4 +gfloat clutter_bind_constraint_get_offset (ClutterBindConstraint *constraint); + +G_END_DECLS + +#endif /* __CLUTTER_BIND_CONSTRAINT_H__ */ diff --git a/clutter/clutter/clutter-binding-pool.c b/clutter/clutter/clutter-binding-pool.c new file mode 100644 index 0000000..9c24b63 --- /dev/null +++ b/clutter/clutter/clutter-binding-pool.c @@ -0,0 +1,938 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2008 Intel Corporation. + * + * Authored By: Emmanuele Bassi + * + * 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 . + */ + +/** + * SECTION:clutter-binding-pool + * @short_description: Pool for key bindings + * + * #ClutterBindingPool is a data structure holding a set of key bindings. + * Each key binding associates a key symbol (eventually with modifiers) + * to an action. A callback function is associated to each action. + * + * For a given key symbol and modifier mask combination there can be only one + * action; for each action there can be only one callback. There can be + * multiple actions with the same name, and the same callback can be used + * to handle multiple key bindings. + * + * Actors requiring key bindings should create a new #ClutterBindingPool + * inside their class initialization function and then install actions + * like this: + * + * |[ + * static void + * foo_class_init (FooClass *klass) + * { + * ClutterBindingPool *binding_pool; + * + * binding_pool = clutter_binding_pool_get_for_class (klass); + * + * clutter_binding_pool_install_action (binding_pool, "move-up", + * CLUTTER_Up, 0, + * G_CALLBACK (foo_action_move_up), + * NULL, NULL); + * clutter_binding_pool_install_action (binding_pool, "move-up", + * CLUTTER_KP_Up, 0, + * G_CALLBACK (foo_action_move_up), + * NULL, NULL); + * } + * ]| + * + * The callback has a signature of: + * + * |[ + * gboolean (* callback) (GObject *instance, + * const gchar *action_name, + * guint key_val, + * ClutterModifierType modifiers, + * gpointer user_data); + * ]| + * + * The actor should then override the #ClutterActor::key-press-event and + * use clutter_binding_pool_activate() to match a #ClutterKeyEvent structure + * to one of the actions: + * + * |[ + * ClutterBindingPool *pool; + * + * // retrieve the binding pool for the type of the actor + * pool = clutter_binding_pool_find (G_OBJECT_TYPE_NAME (actor)); + * + * // activate any callback matching the key symbol and modifiers + * // mask of the key event. the returned value can be directly + * // used to signal that the actor has handled the event. + * return clutter_binding_pool_activate (pool, + * key_event->keyval, + * key_event->modifier_state, + * G_OBJECT (actor)); + * ]| + * + * The clutter_binding_pool_activate() function will return %FALSE if + * no action for the given key binding was found, if the action was + * blocked (using clutter_binding_pool_block_action()) or if the + * key binding handler returned %FALSE. + * + * #ClutterBindingPool is available since Clutter 1.0 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-binding-pool.h" +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-marshal.h" +#include "clutter-private.h" + +#define CLUTTER_BINDING_POOL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), CLUTTER_TYPE_BINDING_POOL, ClutterBindingPoolClass)) +#define CLUTTER_IS_BINDING_POOL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CLUTTER_TYPE_BINDING_POOL)) +#define CLUTTER_BINDING_POOL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CLUTTER_TYPE_BINDING_POOL, ClutterBindingPoolClass)) + +#define BINDING_MOD_MASK ((CLUTTER_SHIFT_MASK | \ + CLUTTER_CONTROL_MASK | \ + CLUTTER_MOD1_MASK | \ + CLUTTER_SUPER_MASK | \ + CLUTTER_HYPER_MASK | \ + CLUTTER_META_MASK) | CLUTTER_RELEASE_MASK) + +typedef struct _ClutterBindingEntry ClutterBindingEntry; + +static GSList *clutter_binding_pools = NULL; +static GQuark key_class_bindings = 0; + +struct _ClutterBindingPool +{ + GObject parent_instance; + + gchar *name; /* interned string, do not free */ + + GSList *entries; + GHashTable *entries_hash; +}; + +struct _ClutterBindingPoolClass +{ + GObjectClass parent_class; +}; + +struct _ClutterBindingEntry +{ + gchar *name; /* interned string, do not free */ + + guint key_val; + ClutterModifierType modifiers; + + GClosure *closure; + + guint is_blocked : 1; +}; + +enum +{ + PROP_0, + + PROP_NAME, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +G_DEFINE_TYPE (ClutterBindingPool, clutter_binding_pool, G_TYPE_OBJECT); + +static guint +binding_entry_hash (gconstpointer v) +{ + const ClutterBindingEntry *e = v; + guint h; + + h = e->key_val; + h ^= e->modifiers; + + return h; +} + +static gint +binding_entry_compare (gconstpointer v1, + gconstpointer v2) +{ + const ClutterBindingEntry *e1 = v1; + const ClutterBindingEntry *e2 = v2; + + return (e1->key_val == e2->key_val && e1->modifiers == e2->modifiers); +} + +static ClutterBindingEntry * +binding_entry_new (const gchar *name, + guint key_val, + ClutterModifierType modifiers) +{ + ClutterBindingEntry *entry; + + modifiers = modifiers & BINDING_MOD_MASK; + + entry = g_slice_new (ClutterBindingEntry); + entry->key_val = key_val; + entry->modifiers = modifiers; + entry->name = (gchar *) g_intern_string (name); + entry->closure = NULL; + entry->is_blocked = FALSE; + + return entry; +} + +static ClutterBindingEntry * +binding_pool_lookup_entry (ClutterBindingPool *pool, + guint key_val, + ClutterModifierType modifiers) +{ + ClutterBindingEntry lookup_entry = { 0, }; + + lookup_entry.key_val = key_val; + lookup_entry.modifiers = modifiers; + + return g_hash_table_lookup (pool->entries_hash, &lookup_entry); +} + +static void +binding_entry_free (gpointer data) +{ + if (G_LIKELY (data)) + { + ClutterBindingEntry *entry = data; + + g_closure_unref (entry->closure); + + g_slice_free (ClutterBindingEntry, entry); + } +} + +static void +clutter_binding_pool_finalize (GObject *gobject) +{ + ClutterBindingPool *pool = CLUTTER_BINDING_POOL (gobject); + + /* remove from the pools */ + clutter_binding_pools = g_slist_remove (clutter_binding_pools, pool); + + g_hash_table_destroy (pool->entries_hash); + + g_slist_foreach (pool->entries, (GFunc) binding_entry_free, NULL); + g_slist_free (pool->entries); + + G_OBJECT_CLASS (clutter_binding_pool_parent_class)->finalize (gobject); +} + +static void +clutter_binding_pool_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterBindingPool *pool = CLUTTER_BINDING_POOL (gobject); + + switch (prop_id) + { + case PROP_NAME: + pool->name = (gchar *) g_intern_string (g_value_get_string (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_binding_pool_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterBindingPool *pool = CLUTTER_BINDING_POOL (gobject); + + switch (prop_id) + { + case PROP_NAME: + g_value_set_string (value, pool->name); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_binding_pool_constructed (GObject *gobject) +{ + ClutterBindingPool *pool = CLUTTER_BINDING_POOL (gobject); + + /* bad monkey! bad, bad monkey! */ + if (G_UNLIKELY (pool->name == NULL)) + g_critical ("No name set for ClutterBindingPool %p", pool); + + if (G_OBJECT_CLASS (clutter_binding_pool_parent_class)->constructed) + G_OBJECT_CLASS (clutter_binding_pool_parent_class)->constructed (gobject); +} + +static void +clutter_binding_pool_class_init (ClutterBindingPoolClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->constructed = clutter_binding_pool_constructed; + gobject_class->set_property = clutter_binding_pool_set_property; + gobject_class->get_property = clutter_binding_pool_get_property; + gobject_class->finalize = clutter_binding_pool_finalize; + + /** + * ClutterBindingPool:name: + * + * The unique name of the #ClutterBindingPool. + * + * Since: 1.0 + */ + obj_props[PROP_NAME] = + g_param_spec_string ("name", + P_("Name"), + P_("The unique name of the binding pool"), + NULL, + CLUTTER_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY); + + g_object_class_install_properties (gobject_class, + PROP_LAST, + obj_props); +} + +static void +clutter_binding_pool_init (ClutterBindingPool *pool) +{ + pool->name = NULL; + pool->entries = NULL; + pool->entries_hash = g_hash_table_new (binding_entry_hash, + binding_entry_compare); + + clutter_binding_pools = g_slist_prepend (clutter_binding_pools, pool); +} + +/** + * clutter_binding_pool_new: + * @name: the name of the binding pool + * + * Creates a new #ClutterBindingPool that can be used to store + * key bindings for an actor. The @name must be a unique identifier + * for the binding pool, so that clutter_binding_pool_find() will + * be able to return the correct binding pool. + * + * Return value: the newly created binding pool with the given + * name. Use g_object_unref() when done. + * + * Since: 1.0 + */ +ClutterBindingPool * +clutter_binding_pool_new (const gchar *name) +{ + ClutterBindingPool *pool; + + g_return_val_if_fail (name != NULL, NULL); + + pool = clutter_binding_pool_find (name); + if (G_UNLIKELY (pool)) + { + g_warning ("A binding pool named '%s' is already present " + "in the binding pools list", + pool->name); + return NULL; + } + + return g_object_new (CLUTTER_TYPE_BINDING_POOL, "name", name, NULL); +} + +/** + * clutter_binding_pool_get_for_class: + * @klass: a #GObjectClass pointer + * + * Retrieves the #ClutterBindingPool for the given #GObject class + * and, eventually, creates it. This function is a wrapper around + * clutter_binding_pool_new() and uses the class type name as the + * unique name for the binding pool. + * + * Calling this function multiple times will return the same + * #ClutterBindingPool. + * + * A binding pool for a class can also be retrieved using + * clutter_binding_pool_find() with the class type name: + * + * |[ + * pool = clutter_binding_pool_find (G_OBJECT_TYPE_NAME (instance)); + * ]| + * + * Return value: (transfer none): the binding pool for the given class. + * The returned #ClutterBindingPool is owned by Clutter and should not + * be freed directly + * + * Since: 1.0 + */ +ClutterBindingPool * +clutter_binding_pool_get_for_class (gpointer klass) +{ + ClutterBindingPool *pool; + + g_return_val_if_fail (G_IS_OBJECT_CLASS (klass), NULL); + + if (G_UNLIKELY (key_class_bindings == 0)) + key_class_bindings = g_quark_from_static_string ("clutter-bindings-set"); + + pool = g_dataset_id_get_data (klass, key_class_bindings); + if (pool) + return pool; + + pool = clutter_binding_pool_new (G_OBJECT_CLASS_NAME (klass)); + g_dataset_id_set_data_full (klass, key_class_bindings, + pool, + g_object_unref); + + return pool; +} + +/** + * clutter_binding_pool_find: + * @name: the name of the binding pool to find + * + * Finds the #ClutterBindingPool with @name. + * + * Return value: (transfer none): a pointer to the #ClutterBindingPool, or %NULL + * + * Since: 1.0 + */ +ClutterBindingPool * +clutter_binding_pool_find (const gchar *name) +{ + GSList *l; + + g_return_val_if_fail (name != NULL, NULL); + + for (l = clutter_binding_pools; l != NULL; l = l->next) + { + ClutterBindingPool *pool = l->data; + + if (g_str_equal (pool->name, (gpointer) name)) + return pool; + } + + return NULL; +} + +/** + * clutter_binding_pool_install_action: + * @pool: a #ClutterBindingPool + * @action_name: the name of the action + * @key_val: key symbol + * @modifiers: bitmask of modifiers + * @callback: (type Clutter.BindingActionFunc): function to be called + * when the action is activated + * @data: data to be passed to @callback + * @notify: function to be called when the action is removed + * from the pool + * + * Installs a new action inside a #ClutterBindingPool. The action + * is bound to @key_val and @modifiers. + * + * The same action name can be used for multiple @key_val, @modifiers + * pairs. + * + * When an action has been activated using clutter_binding_pool_activate() + * the passed @callback will be invoked (with @data). + * + * Actions can be blocked with clutter_binding_pool_block_action() + * and then unblocked using clutter_binding_pool_unblock_action(). + * + * Since: 1.0 + */ +void +clutter_binding_pool_install_action (ClutterBindingPool *pool, + const gchar *action_name, + guint key_val, + ClutterModifierType modifiers, + GCallback callback, + gpointer data, + GDestroyNotify notify) +{ + ClutterBindingEntry *entry; + GClosure *closure; + + g_return_if_fail (pool != NULL); + g_return_if_fail (action_name != NULL); + g_return_if_fail (key_val != 0); + g_return_if_fail (callback != NULL); + + entry = binding_pool_lookup_entry (pool, key_val, modifiers); + if (G_UNLIKELY (entry)) + { + g_warning ("There already is an action '%s' for the given " + "key symbol of %d (modifiers: %d) installed inside " + "the binding pool.", + entry->name, + entry->key_val, entry->modifiers); + return; + } + else + entry = binding_entry_new (action_name, key_val, modifiers); + + closure = g_cclosure_new (callback, data, (GClosureNotify) notify); + entry->closure = g_closure_ref (closure); + g_closure_sink (closure); + + if (G_CLOSURE_NEEDS_MARSHAL (closure)) + { + GClosureMarshal marshal; + + marshal = _clutter_marshal_BOOLEAN__STRING_UINT_FLAGS; + g_closure_set_marshal (closure, marshal); + } + + pool->entries = g_slist_prepend (pool->entries, entry); + g_hash_table_insert (pool->entries_hash, entry, entry); +} + +/** + * clutter_binding_pool_install_closure: + * @pool: a #ClutterBindingPool + * @action_name: the name of the action + * @key_val: key symbol + * @modifiers: bitmask of modifiers + * @closure: a #GClosure + * + * A #GClosure variant of clutter_binding_pool_install_action(). + * + * Installs a new action inside a #ClutterBindingPool. The action + * is bound to @key_val and @modifiers. + * + * The same action name can be used for multiple @key_val, @modifiers + * pairs. + * + * When an action has been activated using clutter_binding_pool_activate() + * the passed @closure will be invoked. + * + * Actions can be blocked with clutter_binding_pool_block_action() + * and then unblocked using clutter_binding_pool_unblock_action(). + * + * Since: 1.0 + */ +void +clutter_binding_pool_install_closure (ClutterBindingPool *pool, + const gchar *action_name, + guint key_val, + ClutterModifierType modifiers, + GClosure *closure) +{ + ClutterBindingEntry *entry; + + g_return_if_fail (pool != NULL); + g_return_if_fail (action_name != NULL); + g_return_if_fail (key_val != 0); + g_return_if_fail (closure != NULL); + + entry = binding_pool_lookup_entry (pool, key_val, modifiers); + if (G_UNLIKELY (entry)) + { + g_warning ("There already is an action '%s' for the given " + "key symbol of %d (modifiers: %d) installed inside " + "the binding pool.", + entry->name, + entry->key_val, entry->modifiers); + return; + } + else + entry = binding_entry_new (action_name, key_val, modifiers); + + entry->closure = g_closure_ref (closure); + g_closure_sink (closure); + + if (G_CLOSURE_NEEDS_MARSHAL (closure)) + { + GClosureMarshal marshal; + + marshal = _clutter_marshal_BOOLEAN__STRING_UINT_FLAGS; + g_closure_set_marshal (closure, marshal); + } + + pool->entries = g_slist_prepend (pool->entries, entry); + g_hash_table_insert (pool->entries_hash, entry, entry); +} + +/** + * clutter_binding_pool_override_action: + * @pool: a #ClutterBindingPool + * @key_val: key symbol + * @modifiers: bitmask of modifiers + * @callback: function to be called when the action is activated + * @data: data to be passed to @callback + * @notify: function to be called when the action is removed + * from the pool + * + * Allows overriding the action for @key_val and @modifiers inside a + * #ClutterBindingPool. See clutter_binding_pool_install_action(). + * + * When an action has been activated using clutter_binding_pool_activate() + * the passed @callback will be invoked (with @data). + * + * Actions can be blocked with clutter_binding_pool_block_action() + * and then unblocked using clutter_binding_pool_unblock_action(). + * + * Since: 1.0 + */ +void +clutter_binding_pool_override_action (ClutterBindingPool *pool, + guint key_val, + ClutterModifierType modifiers, + GCallback callback, + gpointer data, + GDestroyNotify notify) +{ + ClutterBindingEntry *entry; + GClosure *closure; + + g_return_if_fail (pool != NULL); + g_return_if_fail (key_val != 0); + g_return_if_fail (callback != NULL); + + entry = binding_pool_lookup_entry (pool, key_val, modifiers); + if (G_UNLIKELY (entry == NULL)) + { + g_warning ("There is no action for the given key symbol " + "of %d (modifiers: %d) installed inside the " + "binding pool.", + key_val, modifiers); + return; + } + + if (entry->closure) + { + g_closure_unref (entry->closure); + entry->closure = NULL; + } + + closure = g_cclosure_new (callback, data, (GClosureNotify) notify); + entry->closure = g_closure_ref (closure); + g_closure_sink (closure); + + if (G_CLOSURE_NEEDS_MARSHAL (closure)) + { + GClosureMarshal marshal; + + marshal = _clutter_marshal_BOOLEAN__STRING_UINT_FLAGS; + g_closure_set_marshal (closure, marshal); + } +} + +/** + * clutter_binding_pool_override_closure: + * @pool: a #ClutterBindingPool + * @key_val: key symbol + * @modifiers: bitmask of modifiers + * @closure: a #GClosure + * + * A #GClosure variant of clutter_binding_pool_override_action(). + * + * Allows overriding the action for @key_val and @modifiers inside a + * #ClutterBindingPool. See clutter_binding_pool_install_closure(). + * + * When an action has been activated using clutter_binding_pool_activate() + * the passed @callback will be invoked (with @data). + * + * Actions can be blocked with clutter_binding_pool_block_action() + * and then unblocked using clutter_binding_pool_unblock_action(). + * + * Since: 1.0 + */ +void +clutter_binding_pool_override_closure (ClutterBindingPool *pool, + guint key_val, + ClutterModifierType modifiers, + GClosure *closure) +{ + ClutterBindingEntry *entry; + + g_return_if_fail (pool != NULL); + g_return_if_fail (key_val != 0); + g_return_if_fail (closure != NULL); + + entry = binding_pool_lookup_entry (pool, key_val, modifiers); + if (G_UNLIKELY (entry == NULL)) + { + g_warning ("There is no action for the given key symbol " + "of %d (modifiers: %d) installed inside the " + "binding pool.", + key_val, modifiers); + return; + } + + if (entry->closure) + { + g_closure_unref (entry->closure); + entry->closure = NULL; + } + + entry->closure = g_closure_ref (closure); + g_closure_sink (closure); + + if (G_CLOSURE_NEEDS_MARSHAL (closure)) + { + GClosureMarshal marshal; + + marshal = _clutter_marshal_BOOLEAN__STRING_UINT_FLAGS; + g_closure_set_marshal (closure, marshal); + } +} + +/** + * clutter_binding_pool_find_action: + * @pool: a #ClutterBindingPool + * @key_val: a key symbol + * @modifiers: a bitmask for the modifiers + * + * Retrieves the name of the action matching the given key symbol + * and modifiers bitmask. + * + * Return value: the name of the action, if found, or %NULL. The + * returned string is owned by the binding pool and should never + * be modified or freed + * + * Since: 1.0 + */ +const gchar * +clutter_binding_pool_find_action (ClutterBindingPool *pool, + guint key_val, + ClutterModifierType modifiers) +{ + ClutterBindingEntry *entry; + + g_return_val_if_fail (pool != NULL, NULL); + g_return_val_if_fail (key_val != 0, NULL); + + entry = binding_pool_lookup_entry (pool, key_val, modifiers); + if (!entry) + return NULL; + + return entry->name; +} + +/** + * clutter_binding_pool_remove_action: + * @pool: a #ClutterBindingPool + * @key_val: a key symbol + * @modifiers: a bitmask for the modifiers + * + * Removes the action matching the given @key_val, @modifiers pair, + * if any exists. + * + * Since: 1.0 + */ +void +clutter_binding_pool_remove_action (ClutterBindingPool *pool, + guint key_val, + ClutterModifierType modifiers) +{ + ClutterBindingEntry remove_entry = { 0, }; + GSList *l; + + g_return_if_fail (pool != NULL); + g_return_if_fail (key_val != 0); + + modifiers = modifiers & BINDING_MOD_MASK; + + remove_entry.key_val = key_val; + remove_entry.modifiers = modifiers; + + for (l = pool->entries; l != NULL; l = l->data) + { + ClutterBindingEntry *e = l->data; + + if (e->key_val == remove_entry.key_val && + e->modifiers == remove_entry.modifiers) + { + pool->entries = g_slist_remove_link (pool->entries, l); + break; + } + } + + g_hash_table_remove (pool->entries_hash, &remove_entry); +} + +static gboolean +clutter_binding_entry_invoke (ClutterBindingEntry *entry, + GObject *gobject) +{ + GValue params[4] = { + G_VALUE_INIT, + G_VALUE_INIT, + G_VALUE_INIT, + G_VALUE_INIT + }; + GValue result = G_VALUE_INIT; + gboolean retval = TRUE; + + g_value_init (¶ms[0], G_TYPE_OBJECT); + g_value_set_object (¶ms[0], gobject); + + g_value_init (¶ms[1], G_TYPE_STRING); + g_value_set_static_string (¶ms[1], entry->name); + + g_value_init (¶ms[2], G_TYPE_UINT); + g_value_set_uint (¶ms[2], entry->key_val); + + g_value_init (¶ms[3], CLUTTER_TYPE_MODIFIER_TYPE); + g_value_set_flags (¶ms[3], entry->modifiers); + + g_value_init (&result, G_TYPE_BOOLEAN); + + g_closure_invoke (entry->closure, &result, 4, params, NULL); + + retval = g_value_get_boolean (&result); + + g_value_unset (&result); + + g_value_unset (¶ms[0]); + g_value_unset (¶ms[1]); + g_value_unset (¶ms[2]); + g_value_unset (¶ms[3]); + + return retval; +} + +/** + * clutter_binding_pool_activate: + * @pool: a #ClutterBindingPool + * @key_val: the key symbol + * @modifiers: bitmask for the modifiers + * @gobject: a #GObject + * + * Activates the callback associated to the action that is + * bound to the @key_val and @modifiers pair. + * + * The callback has the following signature: + * + * |[ + * void (* callback) (GObject *gobject, + * const gchar *action_name, + * guint key_val, + * ClutterModifierType modifiers, + * gpointer user_data); + * ]| + * + * Where the #GObject instance is @gobject and the user data + * is the one passed when installing the action with + * clutter_binding_pool_install_action(). + * + * If the action bound to the @key_val, @modifiers pair has been + * blocked using clutter_binding_pool_block_action(), the callback + * will not be invoked, and this function will return %FALSE. + * + * Return value: %TRUE if an action was found and was activated + * + * Since: 1.0 + */ +gboolean +clutter_binding_pool_activate (ClutterBindingPool *pool, + guint key_val, + ClutterModifierType modifiers, + GObject *gobject) +{ + ClutterBindingEntry *entry = NULL; + + g_return_val_if_fail (pool != NULL, FALSE); + g_return_val_if_fail (key_val != 0, FALSE); + g_return_val_if_fail (G_IS_OBJECT (gobject), FALSE); + + modifiers = (modifiers & BINDING_MOD_MASK); + + entry = binding_pool_lookup_entry (pool, key_val, modifiers); + if (!entry) + return FALSE; + + if (!entry->is_blocked) + return clutter_binding_entry_invoke (entry, gobject); + + return FALSE; +} + +/** + * clutter_binding_pool_block_action: + * @pool: a #ClutterBindingPool + * @action_name: an action name + * + * Blocks all the actions with name @action_name inside @pool. + * + * Since: 1.0 + */ +void +clutter_binding_pool_block_action (ClutterBindingPool *pool, + const gchar *action_name) +{ + GSList *l; + + g_return_if_fail (pool != NULL); + g_return_if_fail (action_name != NULL); + + for (l = pool->entries; l != NULL; l = l->next) + { + ClutterBindingEntry *entry = l->data; + + if (g_str_equal (entry->name, (gpointer) action_name)) + entry->is_blocked = TRUE; + } +} + +/** + * clutter_binding_pool_unblock_action: + * @pool: a #ClutterBindingPool + * @action_name: an action name + * + * Unblockes all the actions with name @action_name inside @pool. + * + * Unblocking an action does not cause the callback bound to it to + * be invoked in case clutter_binding_pool_activate() was called on + * an action previously blocked with clutter_binding_pool_block_action(). + * + * Since: 1.0 + */ +void +clutter_binding_pool_unblock_action (ClutterBindingPool *pool, + const gchar *action_name) +{ + GSList *l; + + g_return_if_fail (pool != NULL); + g_return_if_fail (action_name != NULL); + + for (l = pool->entries; l != NULL; l = l->next) + { + ClutterBindingEntry *entry = l->data; + + if (g_str_equal (entry->name, (gpointer) action_name)) + entry->is_blocked = FALSE; + } +} diff --git a/clutter/clutter/clutter-binding-pool.h b/clutter/clutter/clutter-binding-pool.h new file mode 100644 index 0000000..2830d27 --- /dev/null +++ b/clutter/clutter/clutter-binding-pool.h @@ -0,0 +1,135 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2008 Intel Corporation. + * + * Authored By: Emmanuele Bassi + * + * 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 . + */ + +#ifndef __CLUTTER_BINDING_POOL_H__ +#define __CLUTTER_BINDING_POOL_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BINDING_POOL (clutter_binding_pool_get_type ()) +#define CLUTTER_BINDING_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BINDING_POOL, ClutterBindingPool)) +#define CLUTTER_IS_BINDING_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BINDING_POOL)) + +/** + * ClutterBindingPool: + * + * Container of key bindings. The #ClutterBindingPool struct is + * private. + * + * Since: 1.0 + */ +typedef struct _ClutterBindingPool ClutterBindingPool; +typedef struct _ClutterBindingPoolClass ClutterBindingPoolClass; + +/** + * ClutterBindingActionFunc: + * @gobject: a #GObject + * @action_name: the name of the action + * @key_val: the key symbol + * @modifiers: bitmask of the modifier flags + * @user_data: data passed to the function + * + * The prototype for the callback function registered with + * clutter_binding_pool_install_action() and invoked by + * clutter_binding_pool_activate(). + * + * Return value: the function should return %TRUE if the key + * binding has been handled, and return %FALSE otherwise + * + * Since: 1.0 + */ +typedef gboolean (* ClutterBindingActionFunc) (GObject *gobject, + const gchar *action_name, + guint key_val, + ClutterModifierType modifiers, + gpointer user_data); + +CLUTTER_AVAILABLE_IN_1_0 +GType clutter_binding_pool_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_0 +ClutterBindingPool * clutter_binding_pool_new (const gchar *name); +CLUTTER_AVAILABLE_IN_1_0 +ClutterBindingPool * clutter_binding_pool_get_for_class (gpointer klass); +CLUTTER_AVAILABLE_IN_1_0 +ClutterBindingPool * clutter_binding_pool_find (const gchar *name); + +CLUTTER_AVAILABLE_IN_1_0 +void clutter_binding_pool_install_action (ClutterBindingPool *pool, + const gchar *action_name, + guint key_val, + ClutterModifierType modifiers, + GCallback callback, + gpointer data, + GDestroyNotify notify); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_binding_pool_install_closure (ClutterBindingPool *pool, + const gchar *action_name, + guint key_val, + ClutterModifierType modifiers, + GClosure *closure); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_binding_pool_override_action (ClutterBindingPool *pool, + guint key_val, + ClutterModifierType modifiers, + GCallback callback, + gpointer data, + GDestroyNotify notify); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_binding_pool_override_closure (ClutterBindingPool *pool, + guint key_val, + ClutterModifierType modifiers, + GClosure *closure); + +CLUTTER_AVAILABLE_IN_1_0 +const gchar * clutter_binding_pool_find_action (ClutterBindingPool *pool, + guint key_val, + ClutterModifierType modifiers); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_binding_pool_remove_action (ClutterBindingPool *pool, + guint key_val, + ClutterModifierType modifiers); + +CLUTTER_AVAILABLE_IN_1_0 +gboolean clutter_binding_pool_activate (ClutterBindingPool *pool, + guint key_val, + ClutterModifierType modifiers, + GObject *gobject); + +CLUTTER_AVAILABLE_IN_1_0 +void clutter_binding_pool_block_action (ClutterBindingPool *pool, + const gchar *action_name); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_binding_pool_unblock_action (ClutterBindingPool *pool, + const gchar *action_name); + +G_END_DECLS + +#endif /* __CLUTTER_BINDING_POOL_H__ */ diff --git a/clutter/clutter/clutter-blur-effect.c b/clutter/clutter/clutter-blur-effect.c new file mode 100644 index 0000000..21cb3b4 --- /dev/null +++ b/clutter/clutter/clutter-blur-effect.c @@ -0,0 +1,278 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-blur-effect + * @short_description: A blur effect + * @see_also: #ClutterEffect, #ClutterOffscreenEffect + * + * #ClutterBlurEffect is a sub-class of #ClutterEffect that allows blurring a + * actor and its contents. + * + * #ClutterBlurEffect is available since Clutter 1.4 + */ + +#define CLUTTER_BLUR_EFFECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BLUR_EFFECT, ClutterBlurEffectClass)) +#define CLUTTER_IS_BLUR_EFFECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BLUR_EFFECT)) +#define CLUTTER_BLUR_EFFECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BLUR_EFFECT, ClutterBlurEffectClass)) + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#define CLUTTER_ENABLE_EXPERIMENTAL_API + +#include "clutter-blur-effect.h" + +#include "cogl/cogl.h" + +#include "clutter-debug.h" +#include "clutter-offscreen-effect.h" +#include "clutter-private.h" + +#define BLUR_PADDING 2 + +/* FIXME - lame shader; we should really have a decoupled + * horizontal/vertical two pass shader for the gaussian blur + */ +static const gchar *box_blur_glsl_declarations = +"uniform vec2 pixel_step;\n"; +#define SAMPLE(offx, offy) \ + "cogl_texel += texture2D (cogl_sampler, cogl_tex_coord.st + pixel_step * " \ + "vec2 (" G_STRINGIFY (offx) ", " G_STRINGIFY (offy) "));\n" +static const gchar *box_blur_glsl_shader = +" cogl_texel = texture2D (cogl_sampler, cogl_tex_coord.st);\n" + SAMPLE (-1.0, -1.0) + SAMPLE ( 0.0, -1.0) + SAMPLE (+1.0, -1.0) + SAMPLE (-1.0, 0.0) + SAMPLE (+1.0, 0.0) + SAMPLE (-1.0, +1.0) + SAMPLE ( 0.0, +1.0) + SAMPLE (+1.0, +1.0) +" cogl_texel /= 9.0;\n"; +#undef SAMPLE + +struct _ClutterBlurEffect +{ + ClutterOffscreenEffect parent_instance; + + /* a back pointer to our actor, so that we can query it */ + ClutterActor *actor; + + gint pixel_step_uniform; + + gint tex_width; + gint tex_height; + + CoglPipeline *pipeline; +}; + +struct _ClutterBlurEffectClass +{ + ClutterOffscreenEffectClass parent_class; + + CoglPipeline *base_pipeline; +}; + +G_DEFINE_TYPE (ClutterBlurEffect, + clutter_blur_effect, + CLUTTER_TYPE_OFFSCREEN_EFFECT); + +static gboolean +clutter_blur_effect_pre_paint (ClutterEffect *effect) +{ + ClutterBlurEffect *self = CLUTTER_BLUR_EFFECT (effect); + ClutterEffectClass *parent_class; + + if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect))) + return FALSE; + + self->actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); + if (self->actor == NULL) + return FALSE; + + if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) + { + /* if we don't have support for GLSL shaders then we + * forcibly disable the ActorMeta + */ + g_warning ("Unable to use the ShaderEffect: the graphics hardware " + "or the current GL driver does not implement support " + "for the GLSL shading language."); + clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (effect), FALSE); + return FALSE; + } + + parent_class = CLUTTER_EFFECT_CLASS (clutter_blur_effect_parent_class); + if (parent_class->pre_paint (effect)) + { + ClutterOffscreenEffect *offscreen_effect = + CLUTTER_OFFSCREEN_EFFECT (effect); + CoglHandle texture; + + texture = clutter_offscreen_effect_get_texture (offscreen_effect); + self->tex_width = cogl_texture_get_width (texture); + self->tex_height = cogl_texture_get_height (texture); + + if (self->pixel_step_uniform > -1) + { + gfloat pixel_step[2]; + + pixel_step[0] = 1.0f / self->tex_width; + pixel_step[1] = 1.0f / self->tex_height; + + cogl_pipeline_set_uniform_float (self->pipeline, + self->pixel_step_uniform, + 2, /* n_components */ + 1, /* count */ + pixel_step); + } + + cogl_pipeline_set_layer_texture (self->pipeline, 0, texture); + + return TRUE; + } + else + return FALSE; +} + +static void +clutter_blur_effect_paint_target (ClutterOffscreenEffect *effect) +{ + ClutterBlurEffect *self = CLUTTER_BLUR_EFFECT (effect); + guint8 paint_opacity; + + paint_opacity = clutter_actor_get_paint_opacity (self->actor); + + cogl_pipeline_set_color4ub (self->pipeline, + paint_opacity, + paint_opacity, + paint_opacity, + paint_opacity); + cogl_push_source (self->pipeline); + + cogl_rectangle (0, 0, self->tex_width, self->tex_height); + + cogl_pop_source (); +} + +static gboolean +clutter_blur_effect_get_paint_volume (ClutterEffect *effect, + ClutterPaintVolume *volume) +{ + gfloat cur_width, cur_height; + ClutterVertex origin; + + clutter_paint_volume_get_origin (volume, &origin); + cur_width = clutter_paint_volume_get_width (volume); + cur_height = clutter_paint_volume_get_height (volume); + + origin.x -= BLUR_PADDING; + origin.y -= BLUR_PADDING; + cur_width += 2 * BLUR_PADDING; + cur_height += 2 * BLUR_PADDING; + clutter_paint_volume_set_origin (volume, &origin); + clutter_paint_volume_set_width (volume, cur_width); + clutter_paint_volume_set_height (volume, cur_height); + + return TRUE; +} + +static void +clutter_blur_effect_dispose (GObject *gobject) +{ + ClutterBlurEffect *self = CLUTTER_BLUR_EFFECT (gobject); + + if (self->pipeline != NULL) + { + cogl_object_unref (self->pipeline); + self->pipeline = NULL; + } + + G_OBJECT_CLASS (clutter_blur_effect_parent_class)->dispose (gobject); +} + +static void +clutter_blur_effect_class_init (ClutterBlurEffectClass *klass) +{ + ClutterEffectClass *effect_class = CLUTTER_EFFECT_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterOffscreenEffectClass *offscreen_class; + + gobject_class->dispose = clutter_blur_effect_dispose; + + effect_class->pre_paint = clutter_blur_effect_pre_paint; + effect_class->get_paint_volume = clutter_blur_effect_get_paint_volume; + + offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass); + offscreen_class->paint_target = clutter_blur_effect_paint_target; +} + +static void +clutter_blur_effect_init (ClutterBlurEffect *self) +{ + ClutterBlurEffectClass *klass = CLUTTER_BLUR_EFFECT_GET_CLASS (self); + + if (G_UNLIKELY (klass->base_pipeline == NULL)) + { + CoglSnippet *snippet; + CoglContext *ctx = + clutter_backend_get_cogl_context (clutter_get_default_backend ()); + + klass->base_pipeline = cogl_pipeline_new (ctx); + + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_LOOKUP, + box_blur_glsl_declarations, + NULL); + cogl_snippet_set_replace (snippet, box_blur_glsl_shader); + cogl_pipeline_add_layer_snippet (klass->base_pipeline, 0, snippet); + cogl_object_unref (snippet); + + cogl_pipeline_set_layer_null_texture (klass->base_pipeline, + 0, /* layer number */ + COGL_TEXTURE_TYPE_2D); + } + + self->pipeline = cogl_pipeline_copy (klass->base_pipeline); + + self->pixel_step_uniform = + cogl_pipeline_get_uniform_location (self->pipeline, "pixel_step"); +} + +/** + * clutter_blur_effect_new: + * + * Creates a new #ClutterBlurEffect to be used with + * clutter_actor_add_effect() + * + * Return value: the newly created #ClutterBlurEffect or %NULL + * + * Since: 1.4 + */ +ClutterEffect * +clutter_blur_effect_new (void) +{ + return g_object_new (CLUTTER_TYPE_BLUR_EFFECT, NULL); +} diff --git a/clutter/clutter/clutter-blur-effect.h b/clutter/clutter/clutter-blur-effect.h new file mode 100644 index 0000000..4e1b83e --- /dev/null +++ b/clutter/clutter/clutter-blur-effect.h @@ -0,0 +1,59 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_BLUR_EFFECT_H__ +#define __CLUTTER_BLUR_EFFECT_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BLUR_EFFECT (clutter_blur_effect_get_type ()) +#define CLUTTER_BLUR_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BLUR_EFFECT, ClutterBlurEffect)) +#define CLUTTER_IS_BLUR_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BLUR_EFFECT)) + +/** + * ClutterBlurEffect: + * + * #ClutterBlurEffect is an opaque structure + * whose members cannot be accessed directly + * + * Since: 1.4 + */ +typedef struct _ClutterBlurEffect ClutterBlurEffect; +typedef struct _ClutterBlurEffectClass ClutterBlurEffectClass; + +CLUTTER_AVAILABLE_IN_1_4 +GType clutter_blur_effect_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_4 +ClutterEffect *clutter_blur_effect_new (void); + +G_END_DECLS + +#endif /* __CLUTTER_BLUR_EFFECT_H__ */ diff --git a/clutter/clutter/clutter-box-layout.c b/clutter/clutter/clutter-box-layout.c new file mode 100644 index 0000000..49c8d45 --- /dev/null +++ b/clutter/clutter/clutter-box-layout.c @@ -0,0 +1,2333 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * 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 . + * + * Author: + * Emmanuele Bassi + * + * Based on the NBTK NbtkBoxLayout actor by: + * Thomas Wood + */ + +/** + * SECTION:clutter-box-layout + * @short_description: A layout manager arranging children on a single line + * + * The #ClutterBoxLayout is a #ClutterLayoutManager implementing the + * following layout policy: + * + * - all children are arranged on a single line + * - the axis used is controlled by the #ClutterBoxLayout:orientation property + * - the order of the packing is determined by the #ClutterBoxLayout:pack-start boolean property + * - each child will be allocated to its natural size or, if #ClutterActor:x-expand or + * #ClutterActor:y-expand are set, the available size + * - honours the #ClutterActor's #ClutterActor:x-align and #ClutterActor:y-align properties + * to fill the available size + * - if the #ClutterBoxLayout:homogeneous boolean propert is set, then all widgets will + * get the same size, ignoring expand settings and the preferred sizes + * + * It is possible to control the spacing between children of a + * #ClutterBoxLayout by using clutter_box_layout_set_spacing(). + * + * #ClutterBoxLayout is available since Clutter 1.2 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include "deprecated/clutter-container.h" +#include "deprecated/clutter-alpha.h" + +#include "clutter-box-layout.h" + +#include "clutter-actor-private.h" +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-layout-meta.h" +#include "clutter-private.h" +#include "clutter-types.h" + +#define CLUTTER_TYPE_BOX_CHILD (clutter_box_child_get_type ()) +#define CLUTTER_BOX_CHILD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BOX_CHILD, ClutterBoxChild)) +#define CLUTTER_IS_BOX_CHILD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BOX_CHILD)) + +typedef struct _ClutterBoxChild ClutterBoxChild; +typedef struct _ClutterLayoutMetaClass ClutterBoxChildClass; + +struct _ClutterBoxLayoutPrivate +{ + ClutterContainer *container; + + guint spacing; + + gulong easing_mode; + guint easing_duration; + + ClutterOrientation orientation; + + guint is_pack_start : 1; + guint use_animations : 1; + guint is_homogeneous : 1; +}; + +struct _ClutterBoxChild +{ + ClutterLayoutMeta parent_instance; + + ClutterBoxAlignment x_align; + ClutterBoxAlignment y_align; + + guint x_fill : 1; + guint y_fill : 1; + guint expand : 1; +}; + +enum +{ + PROP_CHILD_0, + + PROP_CHILD_X_ALIGN, + PROP_CHILD_Y_ALIGN, + PROP_CHILD_X_FILL, + PROP_CHILD_Y_FILL, + PROP_CHILD_EXPAND, + + PROP_CHILD_LAST +}; + +enum +{ + PROP_0, + + PROP_SPACING, + PROP_VERTICAL, + PROP_HOMOGENEOUS, + PROP_PACK_START, + PROP_USE_ANIMATIONS, + PROP_EASING_MODE, + PROP_EASING_DURATION, + PROP_ORIENTATION, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST] = { NULL, }; + +GType clutter_box_child_get_type (void); + +G_DEFINE_TYPE (ClutterBoxChild, + clutter_box_child, + CLUTTER_TYPE_LAYOUT_META) + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterBoxLayout, + clutter_box_layout, + CLUTTER_TYPE_LAYOUT_MANAGER) + + +typedef struct _RequestedSize +{ + ClutterActor *actor; + + gfloat minimum_size; + gfloat natural_size; +} RequestedSize; + +static gint distribute_natural_allocation (gint extra_space, + guint n_requested_sizes, + RequestedSize *sizes); +static void count_expand_children (ClutterLayoutManager *layout, + ClutterContainer *container, + gint *visible_children, + gint *expand_children); + +/* + * ClutterBoxChild + */ + +static void +box_child_set_align (ClutterBoxChild *self, + ClutterBoxAlignment x_align, + ClutterBoxAlignment y_align) +{ + gboolean x_changed = FALSE, y_changed = FALSE; + + if (self->x_align != x_align) + { + self->x_align = x_align; + + x_changed = TRUE; + } + + if (self->y_align != y_align) + { + self->y_align = y_align; + + y_changed = TRUE; + } + + if (x_changed || y_changed) + { + ClutterLayoutManager *layout; + + layout = clutter_layout_meta_get_manager (CLUTTER_LAYOUT_META (self)); + + clutter_layout_manager_layout_changed (layout); + + if (x_changed) + g_object_notify (G_OBJECT (self), "x-align"); + + if (y_changed) + g_object_notify (G_OBJECT (self), "y-align"); + } +} + +static void +box_child_set_fill (ClutterBoxChild *self, + gboolean x_fill, + gboolean y_fill) +{ + gboolean x_changed = FALSE, y_changed = FALSE; + + if (self->x_fill != x_fill) + { + self->x_fill = x_fill; + + x_changed = TRUE; + } + + if (self->y_fill != y_fill) + { + self->y_fill = y_fill; + + y_changed = TRUE; + } + + if (x_changed || y_changed) + { + ClutterLayoutManager *layout; + + layout = clutter_layout_meta_get_manager (CLUTTER_LAYOUT_META (self)); + + clutter_layout_manager_layout_changed (layout); + + if (x_changed) + g_object_notify (G_OBJECT (self), "x-fill"); + + if (y_changed) + g_object_notify (G_OBJECT (self), "y-fill"); + } +} + +static void +box_child_set_expand (ClutterBoxChild *self, + gboolean expand) +{ + if (self->expand != expand) + { + ClutterLayoutManager *layout; + + self->expand = expand; + + layout = clutter_layout_meta_get_manager (CLUTTER_LAYOUT_META (self)); + + clutter_layout_manager_layout_changed (layout); + + g_object_notify (G_OBJECT (self), "expand"); + } +} + +static void +clutter_box_child_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterBoxChild *self = CLUTTER_BOX_CHILD (gobject); + + switch (prop_id) + { + case PROP_CHILD_X_ALIGN: + box_child_set_align (self, + g_value_get_enum (value), + self->y_align); + break; + + case PROP_CHILD_Y_ALIGN: + box_child_set_align (self, + self->x_align, + g_value_get_enum (value)); + break; + + case PROP_CHILD_X_FILL: + box_child_set_fill (self, + g_value_get_boolean (value), + self->y_fill); + break; + + case PROP_CHILD_Y_FILL: + box_child_set_fill (self, + self->x_fill, + g_value_get_boolean (value)); + break; + + case PROP_CHILD_EXPAND: + box_child_set_expand (self, g_value_get_boolean (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_box_child_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterBoxChild *self = CLUTTER_BOX_CHILD (gobject); + + switch (prop_id) + { + case PROP_CHILD_X_ALIGN: + g_value_set_enum (value, self->x_align); + break; + + case PROP_CHILD_Y_ALIGN: + g_value_set_enum (value, self->y_align); + break; + + case PROP_CHILD_X_FILL: + g_value_set_boolean (value, self->x_fill); + break; + + case PROP_CHILD_Y_FILL: + g_value_set_boolean (value, self->y_fill); + break; + + case PROP_CHILD_EXPAND: + g_value_set_boolean (value, self->expand); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_box_child_class_init (ClutterBoxChildClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GParamSpec *pspec; + + gobject_class->set_property = clutter_box_child_set_property; + gobject_class->get_property = clutter_box_child_get_property; + + pspec = g_param_spec_boolean ("expand", + P_("Expand"), + P_("Allocate extra space for the child"), + FALSE, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_CHILD_EXPAND, pspec); + + pspec = g_param_spec_boolean ("x-fill", + P_("Horizontal Fill"), + P_("Whether the child should receive priority " + "when the container is allocating spare space " + "on the horizontal axis"), + FALSE, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_CHILD_X_FILL, pspec); + + pspec = g_param_spec_boolean ("y-fill", + P_("Vertical Fill"), + P_("Whether the child should receive priority " + "when the container is allocating spare space " + "on the vertical axis"), + FALSE, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_CHILD_Y_FILL, pspec); + + pspec = g_param_spec_enum ("x-align", + P_("Horizontal Alignment"), + P_("Horizontal alignment of the actor within " + "the cell"), + CLUTTER_TYPE_BOX_ALIGNMENT, + CLUTTER_BOX_ALIGNMENT_CENTER, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_CHILD_X_ALIGN, pspec); + + pspec = g_param_spec_enum ("y-align", + P_("Vertical Alignment"), + P_("Vertical alignment of the actor within " + "the cell"), + CLUTTER_TYPE_BOX_ALIGNMENT, + CLUTTER_BOX_ALIGNMENT_CENTER, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_CHILD_Y_ALIGN, pspec); +} + +static void +clutter_box_child_init (ClutterBoxChild *self) +{ + self->x_align = CLUTTER_BOX_ALIGNMENT_CENTER; + self->y_align = CLUTTER_BOX_ALIGNMENT_CENTER; + + self->x_fill = self->y_fill = FALSE; + + self->expand = FALSE; +} + +static gdouble +get_box_alignment_factor (ClutterBoxAlignment alignment) +{ + switch (alignment) + { + case CLUTTER_BOX_ALIGNMENT_CENTER: + return 0.5; + + case CLUTTER_BOX_ALIGNMENT_START: + return 0.0; + + case CLUTTER_BOX_ALIGNMENT_END: + return 1.0; + } + + return 0.0; +} + +static GType +clutter_box_layout_get_child_meta_type (ClutterLayoutManager *manager) +{ + return CLUTTER_TYPE_BOX_CHILD; +} + +static void +clutter_box_layout_set_container (ClutterLayoutManager *layout, + ClutterContainer *container) +{ + ClutterBoxLayoutPrivate *priv = CLUTTER_BOX_LAYOUT (layout)->priv; + ClutterLayoutManagerClass *parent_class; + + priv->container = container; + + if (priv->container != NULL) + { + ClutterRequestMode request_mode; + + /* we need to change the :request-mode of the container + * to match the orientation + */ + request_mode = priv->orientation == CLUTTER_ORIENTATION_VERTICAL + ? CLUTTER_REQUEST_HEIGHT_FOR_WIDTH + : CLUTTER_REQUEST_WIDTH_FOR_HEIGHT; + clutter_actor_set_request_mode (CLUTTER_ACTOR (priv->container), + request_mode); + } + + parent_class = CLUTTER_LAYOUT_MANAGER_CLASS (clutter_box_layout_parent_class); + parent_class->set_container (layout, container); +} + +static void +get_child_size (ClutterActor *actor, + ClutterOrientation orientation, + gfloat for_size, + gfloat *min_size_p, + gfloat *natural_size_p) +{ + if (orientation == CLUTTER_ORIENTATION_HORIZONTAL) + clutter_actor_get_preferred_width (actor, for_size, min_size_p, natural_size_p); + else + clutter_actor_get_preferred_height (actor, for_size, min_size_p, natural_size_p); +} + +/* Handle the request in the orientation of the box (i.e. width request of horizontal box) */ +static void +get_preferred_size_for_orientation (ClutterBoxLayout *self, + ClutterActor *container, + gfloat for_size, + gfloat *min_size_p, + gfloat *natural_size_p) +{ + ClutterBoxLayoutPrivate *priv = self->priv; + ClutterActorIter iter; + ClutterActor *child; + gint n_children = 0; + gfloat minimum, natural; + + minimum = natural = 0; + + clutter_actor_iter_init (&iter, container); + while (clutter_actor_iter_next (&iter, &child)) + { + gfloat child_min = 0, child_nat = 0; + + if (!clutter_actor_is_visible (child)) + continue; + + n_children++; + + get_child_size (child, priv->orientation, + for_size, &child_min, &child_nat); + + minimum += child_min; + natural += child_nat; + } + + if (n_children > 1) + { + minimum += priv->spacing * (n_children - 1); + natural += priv->spacing * (n_children - 1); + } + + if (min_size_p) + *min_size_p = minimum; + + if (natural_size_p) + *natural_size_p = natural; +} + +static void +get_base_size_for_opposite_orientation (ClutterBoxLayout *self, + ClutterActor *container, + gfloat *min_size_p, + gfloat *natural_size_p) +{ + ClutterBoxLayoutPrivate *priv = self->priv; + ClutterActorIter iter; + ClutterActor *child; + gint n_children = 0; + gfloat minimum, natural; + ClutterOrientation opposite_orientation = + priv->orientation == CLUTTER_ORIENTATION_HORIZONTAL + ? CLUTTER_ORIENTATION_VERTICAL + : CLUTTER_ORIENTATION_HORIZONTAL; + + minimum = natural = 0; + + clutter_actor_iter_init (&iter, container); + while (clutter_actor_iter_next (&iter, &child)) + { + gfloat child_min = 0, child_nat = 0; + + if (!clutter_actor_is_visible (child)) + continue; + + n_children++; + + get_child_size (child, opposite_orientation, -1, &child_min, &child_nat); + + minimum = MAX (minimum, child_min); + natural = MAX (natural, child_nat); + } + + if (min_size_p) + *min_size_p = minimum; + + if (natural_size_p) + *natural_size_p = natural; +} + + +/* Handle the request in the opposite orientation of the box + * (i.e. height request of horizontal box) + * + * This operation requires a virtual allocation in the natural + * orientation of the box, after that each element must be asked + * for the size-for-virtually-allocated-size and the maximums of + * each child sample will be reported as the overall + * "size-for-size-in-opposite-orientation" + */ +static void +get_preferred_size_for_opposite_orientation (ClutterBoxLayout *self, + ClutterActor *container, + gfloat for_size, + gfloat *min_size_p, + gfloat *natural_size_p) +{ + ClutterLayoutManager *layout = CLUTTER_LAYOUT_MANAGER (self); + ClutterBoxLayoutPrivate *priv = self->priv; + ClutterContainer *real_container = CLUTTER_CONTAINER (container); + ClutterActor *child; + ClutterActorIter iter; + gint nvis_children = 0, n_extra_widgets = 0; + gint nexpand_children = 0, i; + RequestedSize *sizes; + gfloat minimum, natural, size, extra = 0; + ClutterOrientation opposite_orientation = + priv->orientation == CLUTTER_ORIENTATION_HORIZONTAL + ? CLUTTER_ORIENTATION_VERTICAL + : CLUTTER_ORIENTATION_HORIZONTAL; + + minimum = natural = 0; + + count_expand_children (layout, real_container, + &nvis_children, &nexpand_children); + + if (nvis_children < 1) + { + if (min_size_p) + *min_size_p = 0; + + if (natural_size_p) + *natural_size_p = 0; + + return; + } + + /* First collect the requested sizes in the natural orientation of the box */ + sizes = g_newa (RequestedSize, nvis_children); + size = for_size; + + i = 0; + clutter_actor_iter_init (&iter, container); + while (clutter_actor_iter_next (&iter, &child)) + { + if (!clutter_actor_is_visible (child)) + continue; + + get_child_size (child, priv->orientation, -1, + &sizes[i].minimum_size, + &sizes[i].natural_size); + + size -= sizes[i].minimum_size; + i++; + } + + if (priv->is_homogeneous) + { + size = for_size - (nvis_children - 1) * priv->spacing; + extra = size / nvis_children; + n_extra_widgets = ((gint)size) % nvis_children; + } + else + { + /* Bring children up to size first */ + size = distribute_natural_allocation (MAX (0, size), nvis_children, sizes); + + /* Calculate space which hasn't distributed yet, + * and is available for expanding children. + */ + if (nexpand_children > 0) + { + extra = size / nexpand_children; + n_extra_widgets = ((gint)size) % nexpand_children; + } + } + + /* Distribute expand space to children */ + i = 0; + clutter_actor_iter_init (&iter, container); + while (clutter_actor_iter_next (&iter, &child)) + { + ClutterLayoutMeta *meta; + ClutterBoxChild *box_child; + + /* If widget is not visible, skip it. */ + if (!clutter_actor_is_visible (child)) + continue; + + meta = clutter_layout_manager_get_child_meta (layout, real_container, child); + box_child = CLUTTER_BOX_CHILD (meta); + + if (priv->is_homogeneous) + { + sizes[i].minimum_size = extra; + + if (n_extra_widgets > 0) + { + sizes[i].minimum_size++; + n_extra_widgets--; + } + } + else + { + if (clutter_actor_needs_expand (child, priv->orientation) || box_child->expand) + { + sizes[i].minimum_size += extra; + + if (n_extra_widgets > 0) + { + sizes[i].minimum_size++; + n_extra_widgets--; + } + } + } + i++; + } + + /* Virtual allocation finished, now we can finally ask for the right size-for-size */ + i = 0; + clutter_actor_iter_init (&iter, container); + while (clutter_actor_iter_next (&iter, &child)) + { + gfloat child_min = 0, child_nat = 0; + + if (!clutter_actor_is_visible (child)) + continue; + + get_child_size (child, opposite_orientation, + sizes[i].minimum_size, + &child_min, &child_nat); + + minimum = MAX (minimum, child_min); + natural = MAX (natural, child_nat); + + i++; + } + + if (min_size_p) + *min_size_p = minimum; + + if (natural_size_p) + *natural_size_p = natural; +} + + +static void +allocate_box_child (ClutterBoxLayout *self, + ClutterContainer *container, + ClutterActor *child, + ClutterActorBox *child_box, + ClutterAllocationFlags flags) +{ + ClutterBoxLayoutPrivate *priv = self->priv; + ClutterBoxChild *box_child; + ClutterLayoutMeta *meta; + + meta = clutter_layout_manager_get_child_meta (CLUTTER_LAYOUT_MANAGER (self), + container, + child); + box_child = CLUTTER_BOX_CHILD (meta); + + CLUTTER_NOTE (LAYOUT, "Allocation for %s { %.2f, %.2f, %.2f, %.2f }", + _clutter_actor_get_debug_name (child), + child_box->x1, child_box->y1, + child_box->x2 - child_box->x1, + child_box->y2 - child_box->y1); + + if (priv->use_animations) + { + clutter_actor_save_easing_state (child); + clutter_actor_set_easing_mode (child, priv->easing_mode); + clutter_actor_set_easing_duration (child, priv->easing_duration); + } + + /* call allocate() instead of allocate_align_fill() if the actor needs + * expand in either direction. this will honour the actors alignment settings + */ + if (clutter_actor_needs_expand (child, CLUTTER_ORIENTATION_HORIZONTAL) || + clutter_actor_needs_expand (child, CLUTTER_ORIENTATION_VERTICAL)) + clutter_actor_allocate (child, child_box, flags); + else + clutter_actor_allocate_align_fill (child, child_box, + get_box_alignment_factor (box_child->x_align), + get_box_alignment_factor (box_child->y_align), + box_child->x_fill, + box_child->y_fill, + flags); + + if (priv->use_animations) + clutter_actor_restore_easing_state (child); +} + +static void +clutter_box_layout_get_preferred_width (ClutterLayoutManager *layout, + ClutterContainer *container, + gfloat for_height, + gfloat *min_width_p, + gfloat *natural_width_p) +{ + ClutterBoxLayout *self = CLUTTER_BOX_LAYOUT (layout); + ClutterBoxLayoutPrivate *priv = self->priv; + + if (priv->orientation == CLUTTER_ORIENTATION_VERTICAL) + { + if (for_height < 0) + get_base_size_for_opposite_orientation (self, CLUTTER_ACTOR (container), + min_width_p, natural_width_p); + else + get_preferred_size_for_opposite_orientation (self, CLUTTER_ACTOR (container), for_height, + min_width_p, natural_width_p); + } + else + get_preferred_size_for_orientation (self, CLUTTER_ACTOR (container), for_height, + min_width_p, natural_width_p); +} + +static void +clutter_box_layout_get_preferred_height (ClutterLayoutManager *layout, + ClutterContainer *container, + gfloat for_width, + gfloat *min_height_p, + gfloat *natural_height_p) +{ + ClutterBoxLayout *self = CLUTTER_BOX_LAYOUT (layout); + ClutterBoxLayoutPrivate *priv = self->priv; + + if (priv->orientation == CLUTTER_ORIENTATION_HORIZONTAL) + { + if (for_width < 0) + get_base_size_for_opposite_orientation (self, CLUTTER_ACTOR (container), + min_height_p, natural_height_p); + else + get_preferred_size_for_opposite_orientation (self, CLUTTER_ACTOR (container), for_width, + min_height_p, natural_height_p); + } + else + get_preferred_size_for_orientation (self, CLUTTER_ACTOR (container), for_width, + min_height_p, natural_height_p); +} + +static void +count_expand_children (ClutterLayoutManager *layout, + ClutterContainer *container, + gint *visible_children, + gint *expand_children) +{ + ClutterBoxLayoutPrivate *priv = CLUTTER_BOX_LAYOUT (layout)->priv; + ClutterActor *actor, *child; + ClutterActorIter iter; + + actor = CLUTTER_ACTOR (container); + + *visible_children = *expand_children = 0; + + clutter_actor_iter_init (&iter, actor); + while (clutter_actor_iter_next (&iter, &child)) + { + if (clutter_actor_is_visible (child)) + { + ClutterLayoutMeta *meta; + + *visible_children += 1; + + meta = clutter_layout_manager_get_child_meta (layout, + container, + child); + + if (clutter_actor_needs_expand (child, priv->orientation) || + CLUTTER_BOX_CHILD (meta)->expand) + *expand_children += 1; + } + } +} + +/* Pulled from gtksizerequest.c from Gtk+ */ +static gint +compare_gap (gconstpointer p1, + gconstpointer p2, + gpointer data) +{ + RequestedSize *sizes = data; + const guint *c1 = p1; + const guint *c2 = p2; + + const gint d1 = MAX (sizes[*c1].natural_size - + sizes[*c1].minimum_size, + 0); + const gint d2 = MAX (sizes[*c2].natural_size - + sizes[*c2].minimum_size, + 0); + + gint delta = (d2 - d1); + + if (0 == delta) + delta = (*c2 - *c1); + + return delta; +} + +/* + * distribute_natural_allocation: + * @extra_space: Extra space to redistribute among children after subtracting + * minimum sizes and any child padding from the overall allocation + * @n_requested_sizes: Number of requests to fit into the allocation + * @sizes: An array of structs with a client pointer and a minimum/natural size + * in the orientation of the allocation. + * + * Distributes @extra_space to child @sizes by bringing smaller + * children up to natural size first. + * + * The remaining space will be added to the @minimum_size member of the + * RequestedSize struct. If all sizes reach their natural size then + * the remaining space is returned. + * + * Returns: The remainder of @extra_space after redistributing space + * to @sizes. + * + * Pulled from gtksizerequest.c from Gtk+ + */ +static gint +distribute_natural_allocation (gint extra_space, + guint n_requested_sizes, + RequestedSize *sizes) +{ + guint *spreading; + gint i; + + g_return_val_if_fail (extra_space >= 0, 0); + + spreading = g_newa (guint, n_requested_sizes); + + for (i = 0; i < n_requested_sizes; i++) + spreading[i] = i; + + /* Distribute the container's extra space c_gap. We want to assign + * this space such that the sum of extra space assigned to children + * (c^i_gap) is equal to c_cap. The case that there's not enough + * space for all children to take their natural size needs some + * attention. The goals we want to achieve are: + * + * a) Maximize number of children taking their natural size. + * b) The allocated size of children should be a continuous + * function of c_gap. That is, increasing the container size by + * one pixel should never make drastic changes in the distribution. + * c) If child i takes its natural size and child j doesn't, + * child j should have received at least as much gap as child i. + * + * The following code distributes the additional space by following + * these rules. + */ + + /* Sort descending by gap and position. */ + g_qsort_with_data (spreading, + n_requested_sizes, sizeof (guint), + compare_gap, sizes); + + /* Distribute available space. + * This master piece of a loop was conceived by Behdad Esfahbod. + */ + for (i = n_requested_sizes - 1; extra_space > 0 && i >= 0; --i) + { + /* Divide remaining space by number of remaining children. + * Sort order and reducing remaining space by assigned space + * ensures that space is distributed equally. + */ + gint glue = (extra_space + i) / (i + 1); + gint gap = sizes[(spreading[i])].natural_size + - sizes[(spreading[i])].minimum_size; + + gint extra = MIN (glue, gap); + + sizes[spreading[i]].minimum_size += extra; + + extra_space -= extra; + } + + return extra_space; +} + +/* Pulled from gtkbox.c from Gtk+ */ + +static void +clutter_box_layout_allocate (ClutterLayoutManager *layout, + ClutterContainer *container, + const ClutterActorBox *box, + ClutterAllocationFlags flags) +{ + ClutterBoxLayoutPrivate *priv = CLUTTER_BOX_LAYOUT (layout)->priv; + ClutterActor *actor, *child; + gint nvis_children; + gint nexpand_children; + gboolean is_rtl; + ClutterActorIter iter; + + ClutterActorBox child_allocation; + RequestedSize *sizes; + + gint size; + gint extra; + gint n_extra_widgets = 0; /* Number of widgets that receive 1 extra px */ + gint x = 0, y = 0, i; + gfloat child_size; + + count_expand_children (layout, container, &nvis_children, &nexpand_children); + + CLUTTER_NOTE (LAYOUT, "BoxLayout for %s: visible=%d, expand=%d", + _clutter_actor_get_debug_name (CLUTTER_ACTOR (container)), + nvis_children, + nexpand_children); + + /* If there is no visible child, simply return. */ + if (nvis_children <= 0) + return; + + sizes = g_newa (RequestedSize, nvis_children); + + if (priv->orientation == CLUTTER_ORIENTATION_VERTICAL) + size = box->y2 - box->y1 - (nvis_children - 1) * priv->spacing; + else + size = box->x2 - box->x1 - (nvis_children - 1) * priv->spacing; + + actor = CLUTTER_ACTOR (container); + + /* Retrieve desired size for visible children. */ + i = 0; + clutter_actor_iter_init (&iter, actor); + while (clutter_actor_iter_next (&iter, &child)) + { + if (!clutter_actor_is_visible (child)) + continue; + + if (priv->orientation == CLUTTER_ORIENTATION_VERTICAL) + clutter_actor_get_preferred_height (child, + box->x2 - box->x1, + &sizes[i].minimum_size, + &sizes[i].natural_size); + else + clutter_actor_get_preferred_width (child, + box->y2 - box->y1, + &sizes[i].minimum_size, + &sizes[i].natural_size); + + + /* Assert the api is working properly */ + if (sizes[i].minimum_size < 0) + g_error ("ClutterBoxLayout child %s minimum %s: %f < 0 for %s %f", + _clutter_actor_get_debug_name (child), + priv->orientation == CLUTTER_ORIENTATION_VERTICAL + ? "height" + : "width", + sizes[i].minimum_size, + priv->orientation == CLUTTER_ORIENTATION_VERTICAL + ? "width" + : "height", + priv->orientation == CLUTTER_ORIENTATION_VERTICAL + ? box->x2 - box->x1 + : box->y2 - box->y1); + + if (sizes[i].natural_size < sizes[i].minimum_size) + g_error ("ClutterBoxLayout child %s natural %s: %f < minimum %f for %s %f", + _clutter_actor_get_debug_name (child), + priv->orientation == CLUTTER_ORIENTATION_VERTICAL + ? "height" + : "width", + sizes[i].natural_size, + sizes[i].minimum_size, + priv->orientation == CLUTTER_ORIENTATION_VERTICAL + ? "width" + : "height", + priv->orientation == CLUTTER_ORIENTATION_VERTICAL + ? box->x2 - box->x1 + : box->y2 - box->y1); + + size -= sizes[i].minimum_size; + + sizes[i].actor = child; + + i += 1; + } + + if (priv->is_homogeneous) + { + /* If were homogenous we still need to run the above loop to get the + * minimum sizes for children that are not going to fill + */ + if (priv->orientation == CLUTTER_ORIENTATION_VERTICAL) + size = box->y2 - box->y1 - (nvis_children - 1) * priv->spacing; + else + size = box->x2 - box->x1 - (nvis_children - 1) * priv->spacing; + + extra = size / nvis_children; + n_extra_widgets = size % nvis_children; + } + else + { + /* Bring children up to size first */ + size = distribute_natural_allocation (MAX (0, size), nvis_children, sizes); + + /* Calculate space which hasn't distributed yet, + * and is available for expanding children. + */ + if (nexpand_children > 0) + { + extra = size / nexpand_children; + n_extra_widgets = size % nexpand_children; + } + else + extra = 0; + } + + if (priv->orientation == CLUTTER_ORIENTATION_HORIZONTAL) + { + ClutterTextDirection text_dir; + + text_dir = clutter_actor_get_text_direction (CLUTTER_ACTOR (container)); + is_rtl = (text_dir == CLUTTER_TEXT_DIRECTION_RTL) ? TRUE : FALSE; + } + else + is_rtl = FALSE; + + /* Allocate child positions. */ + if (priv->orientation == CLUTTER_ORIENTATION_VERTICAL) + { + child_allocation.x1 = box->x1; + child_allocation.x2 = MAX (1.0, box->x2); + if (priv->is_pack_start) + y = box->y2 - box->y1; + else + y = box->y1; + } + else + { + child_allocation.y1 = box->y1; + child_allocation.y2 = MAX (1.0, box->y2); + if (priv->is_pack_start) + x = box->x2 - box->x1; + else + x = box->x1; + } + + i = 0; + clutter_actor_iter_init (&iter, actor); + while (clutter_actor_iter_next (&iter, &child)) + { + ClutterLayoutMeta *meta; + ClutterBoxChild *box_child; + + /* If widget is not visible, skip it. */ + if (!clutter_actor_is_visible (child)) + continue; + + meta = clutter_layout_manager_get_child_meta (layout, + container, + child); + box_child = CLUTTER_BOX_CHILD (meta); + + /* Assign the child's size. */ + if (priv->is_homogeneous) + { + child_size = extra; + + if (n_extra_widgets > 0) + { + child_size++; + n_extra_widgets--; + } + } + else + { + child_size = sizes[i].minimum_size; + + if (clutter_actor_needs_expand (child, priv->orientation) || + box_child->expand) + { + child_size += extra; + + if (n_extra_widgets > 0) + { + child_size++; + n_extra_widgets--; + } + } + } + + /* Assign the child's position. */ + if (priv->orientation == CLUTTER_ORIENTATION_VERTICAL) + { + if (clutter_actor_needs_expand (child, priv->orientation) || + box_child->expand) + { + child_allocation.y1 = y; + child_allocation.y2 = child_allocation.y1 + MAX (1.0, child_size); + } + else + { + child_allocation.y1 = y + (child_size - sizes[i].minimum_size) / 2; + child_allocation.y2 = child_allocation.y1 + sizes[i].minimum_size; + } + + if (priv->is_pack_start) + { + y -= child_size + priv->spacing; + + child_allocation.y1 -= child_size; + child_allocation.y2 -= child_size; + } + else + { + y += child_size + priv->spacing; + } + } + else /* CLUTTER_ORIENTATION_HORIZONTAL */ + { + if (clutter_actor_needs_expand (child, priv->orientation) || + box_child->expand) + { + child_allocation.x1 = x; + child_allocation.x2 = child_allocation.x1 + MAX (1.0, child_size); + } + else + { + child_allocation.x1 = x + (child_size - sizes[i].minimum_size) / 2; + child_allocation.x2 = child_allocation.x1 + sizes[i].minimum_size; + } + + if (priv->is_pack_start) + { + x -= child_size + priv->spacing; + + child_allocation.x1 -= child_size; + child_allocation.x2 -= child_size; + } + else + { + x += child_size + priv->spacing; + } + + if (is_rtl) + { + gfloat width = child_allocation.x2 - child_allocation.x1; + + child_allocation.x2 = box->x1 + (box->x2 - child_allocation.x1); + child_allocation.x1 = child_allocation.x2 - width; + } + + } + + allocate_box_child (CLUTTER_BOX_LAYOUT (layout), + container, + child, + &child_allocation, + flags); + + i += 1; + } +} + +static void +clutter_box_layout_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterBoxLayout *self = CLUTTER_BOX_LAYOUT (gobject); + + switch (prop_id) + { + case PROP_VERTICAL: + clutter_box_layout_set_vertical (self, g_value_get_boolean (value)); + break; + + case PROP_ORIENTATION: + clutter_box_layout_set_orientation (self, g_value_get_enum (value)); + break; + + case PROP_HOMOGENEOUS: + clutter_box_layout_set_homogeneous (self, g_value_get_boolean (value)); + break; + + case PROP_SPACING: + clutter_box_layout_set_spacing (self, g_value_get_uint (value)); + break; + + case PROP_PACK_START: + clutter_box_layout_set_pack_start (self, g_value_get_boolean (value)); + break; + + case PROP_USE_ANIMATIONS: + clutter_box_layout_set_use_animations (self, g_value_get_boolean (value)); + break; + + case PROP_EASING_MODE: + clutter_box_layout_set_easing_mode (self, g_value_get_ulong (value)); + break; + + case PROP_EASING_DURATION: + clutter_box_layout_set_easing_duration (self, g_value_get_uint (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_box_layout_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterBoxLayoutPrivate *priv = CLUTTER_BOX_LAYOUT (gobject)->priv; + + switch (prop_id) + { + case PROP_VERTICAL: + g_value_set_boolean (value, + priv->orientation == CLUTTER_ORIENTATION_VERTICAL); + break; + + case PROP_ORIENTATION: + g_value_set_enum (value, priv->orientation); + break; + + case PROP_HOMOGENEOUS: + g_value_set_boolean (value, priv->is_homogeneous); + break; + + case PROP_SPACING: + g_value_set_uint (value, priv->spacing); + break; + + case PROP_PACK_START: + g_value_set_boolean (value, priv->is_pack_start); + break; + + case PROP_USE_ANIMATIONS: + g_value_set_boolean (value, priv->use_animations); + break; + + case PROP_EASING_MODE: + g_value_set_ulong (value, priv->easing_mode); + break; + + case PROP_EASING_DURATION: + g_value_set_uint (value, priv->easing_duration); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_box_layout_class_init (ClutterBoxLayoutClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterLayoutManagerClass *layout_class; + + layout_class = CLUTTER_LAYOUT_MANAGER_CLASS (klass); + + layout_class->get_preferred_width = clutter_box_layout_get_preferred_width; + layout_class->get_preferred_height = clutter_box_layout_get_preferred_height; + layout_class->allocate = clutter_box_layout_allocate; + layout_class->set_container = clutter_box_layout_set_container; + layout_class->get_child_meta_type = clutter_box_layout_get_child_meta_type; + + /** + * ClutterBoxLayout:vertical: + * + * Whether the #ClutterBoxLayout should arrange its children + * alongside the Y axis, instead of alongside the X axis + * + * Since: 1.2 + * + * Deprecated: 1.12: Use #ClutterBoxLayout:orientation instead. + */ + obj_props[PROP_VERTICAL] = + g_param_spec_boolean ("vertical", + P_("Vertical"), + P_("Whether the layout should be vertical, " + "rather than horizontal"), + FALSE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + G_PARAM_DEPRECATED); + + /** + * ClutterBoxLayout:orientation: + * + * The orientation of the #ClutterBoxLayout, either horizontal + * or vertical + * + * Since: 1.12 + */ + obj_props[PROP_ORIENTATION] = + g_param_spec_enum ("orientation", + P_("Orientation"), + P_("The orientation of the layout"), + CLUTTER_TYPE_ORIENTATION, + CLUTTER_ORIENTATION_HORIZONTAL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + /** + * ClutterBoxLayout:homogeneous: + * + * Whether the #ClutterBoxLayout should arrange its children + * homogeneously, i.e. all children get the same size + * + * Since: 1.4 + */ + obj_props[PROP_HOMOGENEOUS] = + g_param_spec_boolean ("homogeneous", + P_("Homogeneous"), + P_("Whether the layout should be homogeneous, " + "i.e. all children get the same size"), + FALSE, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterBoxLayout:pack-start: + * + * Whether the #ClutterBoxLayout should pack items at the start + * or append them at the end + * + * Since: 1.2 + */ + obj_props[PROP_PACK_START] = + g_param_spec_boolean ("pack-start", + P_("Pack Start"), + P_("Whether to pack items at the start of the box"), + FALSE, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterBoxLayout:spacing: + * + * The spacing between children of the #ClutterBoxLayout, in pixels + * + * Since: 1.2 + */ + obj_props[PROP_SPACING] = + g_param_spec_uint ("spacing", + P_("Spacing"), + P_("Spacing between children"), + 0, G_MAXUINT, 0, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterBoxLayout:use-animations: + * + * Whether the #ClutterBoxLayout should animate changes in the + * layout, overriding the easing state of the children. + * + * Since: 1.2 + * + * Deprecated: 1.12: #ClutterBoxLayout will honour the easing state + * of the children when allocating them. + */ + obj_props[PROP_USE_ANIMATIONS] = + g_param_spec_boolean ("use-animations", + P_("Use Animations"), + P_("Whether layout changes should be animated"), + FALSE, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterBoxLayout:easing-mode: + * + * The easing mode for the animations, in case + * #ClutterBoxLayout:use-animations is set to %TRUE. + * + * The easing mode has the same semantics of #ClutterAnimation:mode: it can + * either be a value from the #ClutterAnimationMode enumeration, like + * %CLUTTER_EASE_OUT_CUBIC, or a logical id as returned by + * clutter_alpha_register_func(). + * + * The default value is %CLUTTER_EASE_OUT_CUBIC. + * + * Since: 1.2 + * + * Deprecated: 1.12: The #ClutterBoxLayout will honour the easing state of + * the children when allocating them. + */ + obj_props[PROP_EASING_MODE] = + g_param_spec_ulong ("easing-mode", + P_("Easing Mode"), + P_("The easing mode of the animations"), + 0, G_MAXULONG, + CLUTTER_EASE_OUT_CUBIC, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterBoxLayout:easing-duration: + * + * The duration of the animations, in case #ClutterBoxLayout:use-animations + * is set to %TRUE. + * + * The duration is expressed in milliseconds. + * + * Since: 1.2 + * + * Deprecated: 1.12: The #ClutterBoxLayout will honour the easing state of + * the children when allocating them. + */ + obj_props[PROP_EASING_DURATION] = + g_param_spec_uint ("easing-duration", + P_("Easing Duration"), + P_("The duration of the animations"), + 0, G_MAXUINT, + 500, + CLUTTER_PARAM_READWRITE); + + gobject_class->set_property = clutter_box_layout_set_property; + gobject_class->get_property = clutter_box_layout_get_property; + g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); +} + +static void +clutter_box_layout_init (ClutterBoxLayout *self) +{ + self->priv = clutter_box_layout_get_instance_private (self); + + self->priv->orientation = CLUTTER_ORIENTATION_HORIZONTAL; + self->priv->is_homogeneous = FALSE; + self->priv->is_pack_start = FALSE; + self->priv->spacing = 0; + + self->priv->use_animations = FALSE; + self->priv->easing_mode = CLUTTER_EASE_OUT_CUBIC; + self->priv->easing_duration = 500; +} + +/** + * clutter_box_layout_new: + * + * Creates a new #ClutterBoxLayout layout manager + * + * Return value: the newly created #ClutterBoxLayout + * + * Since: 1.2 + */ +ClutterLayoutManager * +clutter_box_layout_new (void) +{ + return g_object_new (CLUTTER_TYPE_BOX_LAYOUT, NULL); +} + +/** + * clutter_box_layout_set_spacing: + * @layout: a #ClutterBoxLayout + * @spacing: the spacing between children of the layout, in pixels + * + * Sets the spacing between children of @layout + * + * Since: 1.2 + */ +void +clutter_box_layout_set_spacing (ClutterBoxLayout *layout, + guint spacing) +{ + ClutterBoxLayoutPrivate *priv; + + g_return_if_fail (CLUTTER_IS_BOX_LAYOUT (layout)); + + priv = layout->priv; + + if (priv->spacing != spacing) + { + ClutterLayoutManager *manager; + + priv->spacing = spacing; + + manager = CLUTTER_LAYOUT_MANAGER (layout); + + clutter_layout_manager_layout_changed (manager); + + g_object_notify (G_OBJECT (layout), "spacing"); + } +} + +/** + * clutter_box_layout_get_spacing: + * @layout: a #ClutterBoxLayout + * + * Retrieves the spacing set using clutter_box_layout_set_spacing() + * + * Return value: the spacing between children of the #ClutterBoxLayout + * + * Since: 1.2 + */ +guint +clutter_box_layout_get_spacing (ClutterBoxLayout *layout) +{ + g_return_val_if_fail (CLUTTER_IS_BOX_LAYOUT (layout), 0); + + return layout->priv->spacing; +} + +/** + * clutter_box_layout_set_vertical: + * @layout: a #ClutterBoxLayout + * @vertical: %TRUE if the layout should be vertical + * + * Sets whether @layout should arrange its children vertically alongside + * the Y axis, instead of horizontally alongside the X axis + * + * Since: 1.2 + * + * Deprecated: 1.12: Use clutter_box_layout_set_orientation() instead. + */ +void +clutter_box_layout_set_vertical (ClutterBoxLayout *layout, + gboolean vertical) +{ + ClutterOrientation new_orientation, old_orientation; + + g_return_if_fail (CLUTTER_IS_BOX_LAYOUT (layout)); + + old_orientation = layout->priv->orientation; + new_orientation = vertical + ? CLUTTER_ORIENTATION_VERTICAL + : CLUTTER_ORIENTATION_HORIZONTAL; + clutter_box_layout_set_orientation (layout, new_orientation); + + if (old_orientation != new_orientation) + g_object_notify_by_pspec (G_OBJECT (layout), obj_props[PROP_VERTICAL]); +} + +/** + * clutter_box_layout_set_orientation: + * @layout: a #ClutterBoxLayout + * @orientation: the orientation of the #ClutterBoxLayout + * + * Sets the orientation of the #ClutterBoxLayout layout manager. + * + * Since: 1.12 + */ +void +clutter_box_layout_set_orientation (ClutterBoxLayout *layout, + ClutterOrientation orientation) +{ + ClutterBoxLayoutPrivate *priv; + ClutterLayoutManager *manager; + + g_return_if_fail (CLUTTER_IS_BOX_LAYOUT (layout)); + + priv = layout->priv; + + if (priv->orientation == orientation) + return; + + priv->orientation = orientation; + + manager = CLUTTER_LAYOUT_MANAGER (layout); + + clutter_layout_manager_layout_changed (manager); + + g_object_notify_by_pspec (G_OBJECT (layout), obj_props[PROP_ORIENTATION]); +} + +/** + * clutter_box_layout_get_vertical: + * @layout: a #ClutterBoxLayout + * + * Retrieves the orientation of the @layout as set using the + * clutter_box_layout_set_vertical() function + * + * Return value: %TRUE if the #ClutterBoxLayout is arranging its children + * vertically, and %FALSE otherwise + * + * Since: 1.2 + * + * Deprecated: 1.12: Use clutter_box_layout_get_orientation() instead + */ +gboolean +clutter_box_layout_get_vertical (ClutterBoxLayout *layout) +{ + g_return_val_if_fail (CLUTTER_IS_BOX_LAYOUT (layout), FALSE); + + return layout->priv->orientation == CLUTTER_ORIENTATION_VERTICAL; +} + +/** + * clutter_box_layout_get_orientation: + * @layout: a #ClutterBoxLayout + * + * Retrieves the orientation of the @layout. + * + * Return value: the orientation of the layout + * + * Since: 1.12 + */ +ClutterOrientation +clutter_box_layout_get_orientation (ClutterBoxLayout *layout) +{ + g_return_val_if_fail (CLUTTER_IS_BOX_LAYOUT (layout), + CLUTTER_ORIENTATION_HORIZONTAL); + + return layout->priv->orientation; +} + +/** + * clutter_box_layout_set_homogeneous: + * @layout: a #ClutterBoxLayout + * @homogeneous: %TRUE if the layout should be homogeneous + * + * Sets whether the size of @layout children should be + * homogeneous + * + * Since: 1.4 + */ +void +clutter_box_layout_set_homogeneous (ClutterBoxLayout *layout, + gboolean homogeneous) +{ + ClutterBoxLayoutPrivate *priv; + + g_return_if_fail (CLUTTER_IS_BOX_LAYOUT (layout)); + + priv = layout->priv; + + if (priv->is_homogeneous != homogeneous) + { + ClutterLayoutManager *manager; + + priv->is_homogeneous = !!homogeneous; + + manager = CLUTTER_LAYOUT_MANAGER (layout); + + clutter_layout_manager_layout_changed (manager); + + g_object_notify (G_OBJECT (layout), "homogeneous"); + } +} + +/** + * clutter_box_layout_get_homogeneous: + * @layout: a #ClutterBoxLayout + * + * Retrieves if the children sizes are allocated homogeneously. + * + * Return value: %TRUE if the #ClutterBoxLayout is arranging its children + * homogeneously, and %FALSE otherwise + * + * Since: 1.4 + */ +gboolean +clutter_box_layout_get_homogeneous (ClutterBoxLayout *layout) +{ + g_return_val_if_fail (CLUTTER_IS_BOX_LAYOUT (layout), FALSE); + + return layout->priv->is_homogeneous; +} + +/** + * clutter_box_layout_set_pack_start: + * @layout: a #ClutterBoxLayout + * @pack_start: %TRUE if the @layout should pack children at the + * beginning of the layout + * + * Sets whether children of @layout should be layed out by appending + * them or by prepending them + * + * Since: 1.2 + */ +void +clutter_box_layout_set_pack_start (ClutterBoxLayout *layout, + gboolean pack_start) +{ + ClutterBoxLayoutPrivate *priv; + + g_return_if_fail (CLUTTER_IS_BOX_LAYOUT (layout)); + + priv = layout->priv; + + if (priv->is_pack_start != pack_start) + { + ClutterLayoutManager *manager; + + priv->is_pack_start = pack_start ? TRUE : FALSE; + + manager = CLUTTER_LAYOUT_MANAGER (layout); + + clutter_layout_manager_layout_changed (manager); + + g_object_notify (G_OBJECT (layout), "pack-start"); + } +} + +/** + * clutter_box_layout_get_pack_start: + * @layout: a #ClutterBoxLayout + * + * Retrieves the value set using clutter_box_layout_set_pack_start() + * + * Return value: %TRUE if the #ClutterBoxLayout should pack children + * at the beginning of the layout, and %FALSE otherwise + * + * Since: 1.2 + */ +gboolean +clutter_box_layout_get_pack_start (ClutterBoxLayout *layout) +{ + g_return_val_if_fail (CLUTTER_IS_BOX_LAYOUT (layout), FALSE); + + return layout->priv->is_pack_start; +} + +/** + * clutter_box_layout_pack: + * @layout: a #ClutterBoxLayout + * @actor: a #ClutterActor + * @expand: whether the @actor should expand + * @x_fill: whether the @actor should fill horizontally + * @y_fill: whether the @actor should fill vertically + * @x_align: the horizontal alignment policy for @actor + * @y_align: the vertical alignment policy for @actor + * + * Packs @actor inside the #ClutterContainer associated to @layout + * and sets the layout properties + * + * Since: 1.2 + * Deprecated: 1.12: #ClutterBoxLayout honours #ClutterActor's + * align and expand properties. The preferred way is adding + * the @actor with clutter_actor_add_child() and setting + * #ClutterActor:x-align, #ClutterActor:y-align, + * #ClutterActor:x-expand and #ClutterActor:y-expand + */ +void +clutter_box_layout_pack (ClutterBoxLayout *layout, + ClutterActor *actor, + gboolean expand, + gboolean x_fill, + gboolean y_fill, + ClutterBoxAlignment x_align, + ClutterBoxAlignment y_align) +{ + ClutterBoxLayoutPrivate *priv; + ClutterLayoutManager *manager; + ClutterLayoutMeta *meta; + + g_return_if_fail (CLUTTER_IS_BOX_LAYOUT (layout)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + priv = layout->priv; + + if (priv->container == NULL) + { + g_warning ("The layout of type '%s' must be associated to " + "a ClutterContainer before adding children", + G_OBJECT_TYPE_NAME (layout)); + return; + } + + clutter_container_add_actor (priv->container, actor); + + manager = CLUTTER_LAYOUT_MANAGER (layout); + meta = clutter_layout_manager_get_child_meta (manager, + priv->container, + actor); + g_assert (CLUTTER_IS_BOX_CHILD (meta)); + + box_child_set_align (CLUTTER_BOX_CHILD (meta), x_align, y_align); + box_child_set_fill (CLUTTER_BOX_CHILD (meta), x_fill, y_fill); + box_child_set_expand (CLUTTER_BOX_CHILD (meta), expand); +} + +/** + * clutter_box_layout_set_alignment: + * @layout: a #ClutterBoxLayout + * @actor: a #ClutterActor child of @layout + * @x_align: Horizontal alignment policy for @actor + * @y_align: Vertical alignment policy for @actor + * + * Sets the horizontal and vertical alignment policies for @actor + * inside @layout + * + * Since: 1.2 + * Deprecated: 1.12: #ClutterBoxLayout will honour #ClutterActor's + * #ClutterActor:x-align and #ClutterActor:y-align properies + */ +void +clutter_box_layout_set_alignment (ClutterBoxLayout *layout, + ClutterActor *actor, + ClutterBoxAlignment x_align, + ClutterBoxAlignment y_align) +{ + ClutterBoxLayoutPrivate *priv; + ClutterLayoutManager *manager; + ClutterLayoutMeta *meta; + + g_return_if_fail (CLUTTER_IS_BOX_LAYOUT (layout)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + priv = layout->priv; + + if (priv->container == NULL) + { + g_warning ("The layout of type '%s' must be associated to " + "a ClutterContainer before querying layout " + "properties", + G_OBJECT_TYPE_NAME (layout)); + return; + } + + manager = CLUTTER_LAYOUT_MANAGER (layout); + meta = clutter_layout_manager_get_child_meta (manager, + priv->container, + actor); + if (meta == NULL) + { + g_warning ("No layout meta found for the child of type '%s' " + "inside the layout manager of type '%s'", + G_OBJECT_TYPE_NAME (actor), + G_OBJECT_TYPE_NAME (manager)); + return; + } + + g_assert (CLUTTER_IS_BOX_CHILD (meta)); + + box_child_set_align (CLUTTER_BOX_CHILD (meta), x_align, y_align); +} + +/** + * clutter_box_layout_get_alignment: + * @layout: a #ClutterBoxLayout + * @actor: a #ClutterActor child of @layout + * @x_align: (out): return location for the horizontal alignment policy + * @y_align: (out): return location for the vertical alignment policy + * + * Retrieves the horizontal and vertical alignment policies for @actor + * as set using clutter_box_layout_pack() or clutter_box_layout_set_alignment() + * + * Since: 1.2 + * Deprecated: 1.12: #ClutterBoxLayout will honour #ClutterActor's + * #ClutterActor:x-align and #ClutterActor:y-align properies + */ +void +clutter_box_layout_get_alignment (ClutterBoxLayout *layout, + ClutterActor *actor, + ClutterBoxAlignment *x_align, + ClutterBoxAlignment *y_align) +{ + ClutterBoxLayoutPrivate *priv; + ClutterLayoutManager *manager; + ClutterLayoutMeta *meta; + + g_return_if_fail (CLUTTER_IS_BOX_LAYOUT (layout)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + priv = layout->priv; + + if (priv->container == NULL) + { + g_warning ("The layout of type '%s' must be associated to " + "a ClutterContainer before querying layout " + "properties", + G_OBJECT_TYPE_NAME (layout)); + return; + } + + manager = CLUTTER_LAYOUT_MANAGER (layout); + meta = clutter_layout_manager_get_child_meta (manager, + priv->container, + actor); + if (meta == NULL) + { + g_warning ("No layout meta found for the child of type '%s' " + "inside the layout manager of type '%s'", + G_OBJECT_TYPE_NAME (actor), + G_OBJECT_TYPE_NAME (manager)); + return; + } + + g_assert (CLUTTER_IS_BOX_CHILD (meta)); + + if (x_align) + *x_align = CLUTTER_BOX_CHILD (meta)->x_align; + + if (y_align) + *y_align = CLUTTER_BOX_CHILD (meta)->y_align; +} + +/** + * clutter_box_layout_set_fill: + * @layout: a #ClutterBoxLayout + * @actor: a #ClutterActor child of @layout + * @x_fill: whether @actor should fill horizontally the allocated space + * @y_fill: whether @actor should fill vertically the allocated space + * + * Sets the horizontal and vertical fill policies for @actor + * inside @layout + * + * Since: 1.2 + * Deprecated: 1.12: #ClutterBoxLayout will honour #ClutterActor's + * #ClutterActor:x-align and #ClutterActor:y-align properies + */ +void +clutter_box_layout_set_fill (ClutterBoxLayout *layout, + ClutterActor *actor, + gboolean x_fill, + gboolean y_fill) +{ + ClutterBoxLayoutPrivate *priv; + ClutterLayoutManager *manager; + ClutterLayoutMeta *meta; + + g_return_if_fail (CLUTTER_IS_BOX_LAYOUT (layout)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + priv = layout->priv; + + if (priv->container == NULL) + { + g_warning ("The layout of type '%s' must be associated to " + "a ClutterContainer before querying layout " + "properties", + G_OBJECT_TYPE_NAME (layout)); + return; + } + + manager = CLUTTER_LAYOUT_MANAGER (layout); + meta = clutter_layout_manager_get_child_meta (manager, + priv->container, + actor); + if (meta == NULL) + { + g_warning ("No layout meta found for the child of type '%s' " + "inside the layout manager of type '%s'", + G_OBJECT_TYPE_NAME (actor), + G_OBJECT_TYPE_NAME (manager)); + return; + } + + g_assert (CLUTTER_IS_BOX_CHILD (meta)); + + box_child_set_fill (CLUTTER_BOX_CHILD (meta), x_fill, y_fill); +} + +/** + * clutter_box_layout_get_fill: + * @layout: a #ClutterBoxLayout + * @actor: a #ClutterActor child of @layout + * @x_fill: (out): return location for the horizontal fill policy + * @y_fill: (out): return location for the vertical fill policy + * + * Retrieves the horizontal and vertical fill policies for @actor + * as set using clutter_box_layout_pack() or clutter_box_layout_set_fill() + * + * Since: 1.2 + * Deprecated: 1.12: #ClutterBoxLayout will honour #ClutterActor's + * #ClutterActor:x-align and #ClutterActor:y-align properies + */ +void +clutter_box_layout_get_fill (ClutterBoxLayout *layout, + ClutterActor *actor, + gboolean *x_fill, + gboolean *y_fill) +{ + ClutterBoxLayoutPrivate *priv; + ClutterLayoutManager *manager; + ClutterLayoutMeta *meta; + + g_return_if_fail (CLUTTER_IS_BOX_LAYOUT (layout)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + priv = layout->priv; + + if (priv->container == NULL) + { + g_warning ("The layout of type '%s' must be associated to " + "a ClutterContainer before querying layout " + "properties", + G_OBJECT_TYPE_NAME (layout)); + return; + } + + manager = CLUTTER_LAYOUT_MANAGER (layout); + meta = clutter_layout_manager_get_child_meta (manager, + priv->container, + actor); + if (meta == NULL) + { + g_warning ("No layout meta found for the child of type '%s' " + "inside the layout manager of type '%s'", + G_OBJECT_TYPE_NAME (actor), + G_OBJECT_TYPE_NAME (manager)); + return; + } + + g_assert (CLUTTER_IS_BOX_CHILD (meta)); + + if (x_fill) + *x_fill = CLUTTER_BOX_CHILD (meta)->x_fill; + + if (y_fill) + *y_fill = CLUTTER_BOX_CHILD (meta)->y_fill; +} + +/** + * clutter_box_layout_set_expand: + * @layout: a #ClutterBoxLayout + * @actor: a #ClutterActor child of @layout + * @expand: whether @actor should expand + * + * Sets whether @actor should expand inside @layout + * + * Since: 1.2 + * Deprecated: 1.12: #ClutterBoxLayout will honour #ClutterActor's + * #ClutterActor:x-expand and #ClutterActor:y-expand properies + */ +void +clutter_box_layout_set_expand (ClutterBoxLayout *layout, + ClutterActor *actor, + gboolean expand) +{ + ClutterBoxLayoutPrivate *priv; + ClutterLayoutManager *manager; + ClutterLayoutMeta *meta; + + g_return_if_fail (CLUTTER_IS_BOX_LAYOUT (layout)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + priv = layout->priv; + + if (priv->container == NULL) + { + g_warning ("The layout of type '%s' must be associated to " + "a ClutterContainer before querying layout " + "properties", + G_OBJECT_TYPE_NAME (layout)); + return; + } + + manager = CLUTTER_LAYOUT_MANAGER (layout); + meta = clutter_layout_manager_get_child_meta (manager, + priv->container, + actor); + if (meta == NULL) + { + g_warning ("No layout meta found for the child of type '%s' " + "inside the layout manager of type '%s'", + G_OBJECT_TYPE_NAME (actor), + G_OBJECT_TYPE_NAME (manager)); + return; + } + + g_assert (CLUTTER_IS_BOX_CHILD (meta)); + + box_child_set_expand (CLUTTER_BOX_CHILD (meta), expand); +} + +/** + * clutter_box_layout_get_expand: + * @layout: a #ClutterBoxLayout + * @actor: a #ClutterActor child of @layout + * + * Retrieves whether @actor should expand inside @layout + * + * Return value: %TRUE if the #ClutterActor should expand, %FALSE otherwise + * + * Since: 1.2 + * Deprecated: 1.12: #ClutterBoxLayout will honour #ClutterActor's + * #ClutterActor:x-expand and #ClutterActor:y-expand properies + */ +gboolean +clutter_box_layout_get_expand (ClutterBoxLayout *layout, + ClutterActor *actor) +{ + ClutterBoxLayoutPrivate *priv; + ClutterLayoutManager *manager; + ClutterLayoutMeta *meta; + + g_return_val_if_fail (CLUTTER_IS_BOX_LAYOUT (layout), FALSE); + g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), FALSE); + + priv = layout->priv; + + if (priv->container == NULL) + { + g_warning ("The layout of type '%s' must be associated to " + "a ClutterContainer before querying layout " + "properties", + G_OBJECT_TYPE_NAME (layout)); + return FALSE; + } + + manager = CLUTTER_LAYOUT_MANAGER (layout); + meta = clutter_layout_manager_get_child_meta (manager, + priv->container, + actor); + if (meta == NULL) + { + g_warning ("No layout meta found for the child of type '%s' " + "inside the layout manager of type '%s'", + G_OBJECT_TYPE_NAME (actor), + G_OBJECT_TYPE_NAME (manager)); + return FALSE; + } + + g_assert (CLUTTER_IS_BOX_CHILD (meta)); + + return CLUTTER_BOX_CHILD (meta)->expand; +} + +/** + * clutter_box_layout_set_use_animations: + * @layout: a #ClutterBoxLayout + * @animate: %TRUE if the @layout should use animations + * + * Sets whether @layout should animate changes in the layout properties + * + * The duration of the animations is controlled by + * clutter_box_layout_set_easing_duration(); the easing mode to be used + * by the animations is controlled by clutter_box_layout_set_easing_mode(). + * + * Enabling animations will override the easing state of each child + * of the actor using @layout, and will use the #ClutterBoxLayout:easing-mode + * and #ClutterBoxLayout:easing-duration properties instead. + * + * Since: 1.2 + * + * Deprecated: 1.12: The layout manager will honour the easing state + * of the children when allocating them. + */ +void +clutter_box_layout_set_use_animations (ClutterBoxLayout *layout, + gboolean animate) +{ + ClutterBoxLayoutPrivate *priv; + + g_return_if_fail (CLUTTER_IS_BOX_LAYOUT (layout)); + + priv = layout->priv; + + if (priv->use_animations != animate) + { + priv->use_animations = animate; + + g_object_notify (G_OBJECT (layout), "use-animations"); + } +} + +/** + * clutter_box_layout_get_use_animations: + * @layout: a #ClutterBoxLayout + * + * Retrieves whether @layout should animate changes in the layout properties. + * + * Return value: %TRUE if the animations should be used, %FALSE otherwise + * + * Since: 1.2 + * + * Deprecated: 1.12 + */ +gboolean +clutter_box_layout_get_use_animations (ClutterBoxLayout *layout) +{ + g_return_val_if_fail (CLUTTER_IS_BOX_LAYOUT (layout), FALSE); + + return layout->priv->use_animations; +} + +/** + * clutter_box_layout_set_easing_mode: + * @layout: a #ClutterBoxLayout + * @mode: an easing mode, either from #ClutterAnimationMode or a logical id + * from clutter_alpha_register_func() + * + * Sets the easing mode to be used by @layout when animating changes in layout + * properties. + * + * Since: 1.2 + * + * Deprecated: 1.12: The layout manager will honour the easing state + * of the children when allocating them. + */ +void +clutter_box_layout_set_easing_mode (ClutterBoxLayout *layout, + gulong mode) +{ + ClutterBoxLayoutPrivate *priv; + + g_return_if_fail (CLUTTER_IS_BOX_LAYOUT (layout)); + + priv = layout->priv; + + if (priv->easing_mode != mode) + { + priv->easing_mode = mode; + + g_object_notify (G_OBJECT (layout), "easing-mode"); + } +} + +/** + * clutter_box_layout_get_easing_mode: + * @layout: a #ClutterBoxLayout + * + * Retrieves the easing mode set using clutter_box_layout_set_easing_mode() + * + * Return value: an easing mode + * + * Since: 1.2 + * + * Deprecated: 1.12 + */ +gulong +clutter_box_layout_get_easing_mode (ClutterBoxLayout *layout) +{ + g_return_val_if_fail (CLUTTER_IS_BOX_LAYOUT (layout), + CLUTTER_EASE_OUT_CUBIC); + + return layout->priv->easing_mode; +} + +/** + * clutter_box_layout_set_easing_duration: + * @layout: a #ClutterBoxLayout + * @msecs: the duration of the animations, in milliseconds + * + * Sets the duration of the animations used by @layout when animating changes + * in the layout properties. + * + * Since: 1.2 + * + * Deprecated: 1.12: The layout manager will honour the easing state + * of the children when allocating them. + */ +void +clutter_box_layout_set_easing_duration (ClutterBoxLayout *layout, + guint msecs) +{ + ClutterBoxLayoutPrivate *priv; + + g_return_if_fail (CLUTTER_IS_BOX_LAYOUT (layout)); + + priv = layout->priv; + + if (priv->easing_duration != msecs) + { + priv->easing_duration = msecs; + + g_object_notify (G_OBJECT (layout), "easing-duration"); + } +} + +/** + * clutter_box_layout_get_easing_duration: + * @layout: a #ClutterBoxLayout + * + * Retrieves the duration set using clutter_box_layout_set_easing_duration() + * + * Return value: the duration of the animations, in milliseconds + * + * Since: 1.2 + * + * Deprecated: 1.12 + */ +guint +clutter_box_layout_get_easing_duration (ClutterBoxLayout *layout) +{ + g_return_val_if_fail (CLUTTER_IS_BOX_LAYOUT (layout), 500); + + return layout->priv->easing_duration; +} diff --git a/clutter/clutter/clutter-box-layout.h b/clutter/clutter/clutter-box-layout.h new file mode 100644 index 0000000..a5c085c --- /dev/null +++ b/clutter/clutter/clutter-box-layout.h @@ -0,0 +1,168 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * 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 . + * + * Author: + * Emmanuele Bassi + * + * Based on the NBTK NbtkBoxLayout actor by: + * Thomas Wood + */ + +#ifndef __CLUTTER_BOX_LAYOUT_H__ +#define __CLUTTER_BOX_LAYOUT_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BOX_LAYOUT (clutter_box_layout_get_type ()) +#define CLUTTER_BOX_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BOX_LAYOUT, ClutterBoxLayout)) +#define CLUTTER_IS_BOX_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BOX_LAYOUT)) +#define CLUTTER_BOX_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BOX_LAYOUT, ClutterBoxLayoutClass)) +#define CLUTTER_IS_BOX_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BOX_LAYOUT)) +#define CLUTTER_BOX_LAYOUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BOX_LAYOUT, ClutterBoxLayoutClass)) + +typedef struct _ClutterBoxLayout ClutterBoxLayout; +typedef struct _ClutterBoxLayoutPrivate ClutterBoxLayoutPrivate; +typedef struct _ClutterBoxLayoutClass ClutterBoxLayoutClass; + +/** + * ClutterBoxLayout: + * + * The #ClutterBoxLayout structure contains only private data + * and should be accessed using the provided API + * + * Since: 1.2 + */ +struct _ClutterBoxLayout +{ + /*< private >*/ + ClutterLayoutManager parent_instance; + + ClutterBoxLayoutPrivate *priv; +}; + +/** + * ClutterBoxLayoutClass: + * + * The #ClutterBoxLayoutClass structure contains only private + * data and should be accessed using the provided API + * + * Since: 1.2 + */ +struct _ClutterBoxLayoutClass +{ + /*< private >*/ + ClutterLayoutManagerClass parent_class; +}; + +CLUTTER_AVAILABLE_IN_1_2 +GType clutter_box_layout_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_2 +ClutterLayoutManager * clutter_box_layout_new (void); + +CLUTTER_AVAILABLE_IN_1_12 +void clutter_box_layout_set_orientation (ClutterBoxLayout *layout, + ClutterOrientation orientation); +CLUTTER_AVAILABLE_IN_1_12 +ClutterOrientation clutter_box_layout_get_orientation (ClutterBoxLayout *layout); + +CLUTTER_AVAILABLE_IN_1_2 +void clutter_box_layout_set_spacing (ClutterBoxLayout *layout, + guint spacing); +CLUTTER_AVAILABLE_IN_1_2 +guint clutter_box_layout_get_spacing (ClutterBoxLayout *layout); +CLUTTER_AVAILABLE_IN_1_2 +void clutter_box_layout_set_homogeneous (ClutterBoxLayout *layout, + gboolean homogeneous); +CLUTTER_AVAILABLE_IN_1_2 +gboolean clutter_box_layout_get_homogeneous (ClutterBoxLayout *layout); +CLUTTER_AVAILABLE_IN_1_2 +void clutter_box_layout_set_pack_start (ClutterBoxLayout *layout, + gboolean pack_start); +CLUTTER_AVAILABLE_IN_1_2 +gboolean clutter_box_layout_get_pack_start (ClutterBoxLayout *layout); + +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_box_layout_set_orientation) +void clutter_box_layout_set_vertical (ClutterBoxLayout *layout, + gboolean vertical); +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_box_layout_get_orientation) +gboolean clutter_box_layout_get_vertical (ClutterBoxLayout *layout); + +CLUTTER_AVAILABLE_IN_1_2 +void clutter_box_layout_pack (ClutterBoxLayout *layout, + ClutterActor *actor, + gboolean expand, + gboolean x_fill, + gboolean y_fill, + ClutterBoxAlignment x_align, + ClutterBoxAlignment y_align); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_box_layout_set_alignment (ClutterBoxLayout *layout, + ClutterActor *actor, + ClutterBoxAlignment x_align, + ClutterBoxAlignment y_align); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_box_layout_get_alignment (ClutterBoxLayout *layout, + ClutterActor *actor, + ClutterBoxAlignment *x_align, + ClutterBoxAlignment *y_align); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_box_layout_set_fill (ClutterBoxLayout *layout, + ClutterActor *actor, + gboolean x_fill, + gboolean y_fill); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_box_layout_get_fill (ClutterBoxLayout *layout, + ClutterActor *actor, + gboolean *x_fill, + gboolean *y_fill); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_box_layout_set_expand (ClutterBoxLayout *layout, + ClutterActor *actor, + gboolean expand); +CLUTTER_DEPRECATED_IN_1_12 +gboolean clutter_box_layout_get_expand (ClutterBoxLayout *layout, + ClutterActor *actor); + +CLUTTER_DEPRECATED_IN_1_12 +void clutter_box_layout_set_use_animations (ClutterBoxLayout *layout, + gboolean animate); +CLUTTER_DEPRECATED_IN_1_12 +gboolean clutter_box_layout_get_use_animations (ClutterBoxLayout *layout); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_box_layout_set_easing_mode (ClutterBoxLayout *layout, + gulong mode); +CLUTTER_DEPRECATED_IN_1_12 +gulong clutter_box_layout_get_easing_mode (ClutterBoxLayout *layout); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_box_layout_set_easing_duration (ClutterBoxLayout *layout, + guint msecs); +CLUTTER_DEPRECATED_IN_1_12 +guint clutter_box_layout_get_easing_duration (ClutterBoxLayout *layout); + +G_END_DECLS + +#endif /* __CLUTTER_BOX_LAYOUT_H__ */ diff --git a/clutter/clutter/clutter-brightness-contrast-effect.c b/clutter/clutter/clutter-brightness-contrast-effect.c new file mode 100644 index 0000000..7b38391 --- /dev/null +++ b/clutter/clutter/clutter-brightness-contrast-effect.c @@ -0,0 +1,657 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010-2012 Inclusive Design Research Centre, OCAD University. + * + * 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 . + * + * Author: + * Joseph Scheuhammer + */ + +/** + * SECTION:clutter-brightness-contrast-effect + * @short_description: Increase/decrease brightness and/or contrast of actor. + * @see_also: #ClutterEffect, #ClutterOffscreenEffect + * + * #ClutterBrightnessContrastEffect is a sub-class of #ClutterEffect that + * changes the overall brightness of a #ClutterActor. + * + * #ClutterBrightnessContrastEffect is available since Clutter 1.10 + */ + +#define CLUTTER_BRIGHTNESS_CONTRAST_EFFECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BRIGHTNESS_CONTRAST_EFFECT, ClutterBrightnessContrastEffectClass)) +#define CLUTTER_IS_BRIGHTNESS_CONTRAST_EFFECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BRIGHTNESS_CONTRAST_EFFECT)) +#define CLUTTER_BRIGHTNESS_CONTRAST_EFFECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BRIGHTNESS_CONTRAST_EFFECT, ClutterBrightnessContrastEffectClass)) + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#define CLUTTER_ENABLE_EXPERIMENTAL_API + +#include "clutter-brightness-contrast-effect.h" + +#include + +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-offscreen-effect.h" +#include "clutter-private.h" + +struct _ClutterBrightnessContrastEffect +{ + ClutterOffscreenEffect parent_instance; + + /* Brightness and contrast changes. */ + gfloat brightness_red; + gfloat brightness_green; + gfloat brightness_blue; + + gfloat contrast_red; + gfloat contrast_green; + gfloat contrast_blue; + + gint brightness_multiplier_uniform; + gint brightness_offset_uniform; + gint contrast_uniform; + + gint tex_width; + gint tex_height; + + CoglPipeline *pipeline; +}; + +struct _ClutterBrightnessContrastEffectClass +{ + ClutterOffscreenEffectClass parent_class; + + CoglPipeline *base_pipeline; +}; + +/* Brightness effects in GLSL. + */ +static const gchar *brightness_contrast_decls = + "uniform vec3 brightness_multiplier;\n" + "uniform vec3 brightness_offset;\n" + "uniform vec3 contrast;\n"; + +static const gchar *brightness_contrast_source = + /* Apply the brightness. The brightness_offset is multiplied by the + alpha to keep the color pre-multiplied */ + "cogl_color_out.rgb = (cogl_color_out.rgb * brightness_multiplier +\n" + " brightness_offset * cogl_color_out.a);\n" + /* Apply the contrast */ + "cogl_color_out.rgb = ((cogl_color_out.rgb - 0.5 * cogl_color_out.a) *\n" + " contrast + 0.5 * cogl_color_out.a);\n"; + +static const ClutterColor no_brightness_change = { 0x7f, 0x7f, 0x7f, 0xff }; +static const ClutterColor no_contrast_change = { 0x7f, 0x7f, 0x7f, 0xff }; +static const gfloat no_change = 0.0f; + +enum +{ + PROP_0, + + PROP_BRIGHTNESS, + PROP_CONTRAST, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +G_DEFINE_TYPE (ClutterBrightnessContrastEffect, + clutter_brightness_contrast_effect, + CLUTTER_TYPE_OFFSCREEN_EFFECT); + +static gboolean +will_have_no_effect (ClutterBrightnessContrastEffect *self) +{ + return (self->brightness_red == no_change && + self->brightness_green == no_change && + self->brightness_blue == no_change && + self->contrast_red == no_change && + self->contrast_green == no_change && + self->contrast_blue == no_change); +} + +static gboolean +clutter_brightness_contrast_effect_pre_paint (ClutterEffect *effect) +{ + ClutterBrightnessContrastEffect *self = CLUTTER_BRIGHTNESS_CONTRAST_EFFECT (effect); + ClutterEffectClass *parent_class; + + if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect))) + return FALSE; + + if (will_have_no_effect (self)) + return FALSE; + + if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) + { + /* if we don't have support for GLSL shaders then we + * forcibly disable the ActorMeta + */ + g_warning ("Unable to use the ClutterBrightnessContrastEffect: the " + "graphics hardware or the current GL driver does not " + "implement support for the GLSL shading language. The " + "effect will be disabled."); + clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (effect), FALSE); + return FALSE; + } + + parent_class = + CLUTTER_EFFECT_CLASS (clutter_brightness_contrast_effect_parent_class); + if (parent_class->pre_paint (effect)) + { + ClutterOffscreenEffect *offscreen_effect = + CLUTTER_OFFSCREEN_EFFECT (effect); + CoglHandle texture; + + texture = clutter_offscreen_effect_get_texture (offscreen_effect); + self->tex_width = cogl_texture_get_width (texture); + self->tex_height = cogl_texture_get_height (texture); + + cogl_pipeline_set_layer_texture (self->pipeline, 0, texture); + + return TRUE; + } + else + return FALSE; +} + +static void +clutter_brightness_contrast_effect_paint_target (ClutterOffscreenEffect *effect) +{ + ClutterBrightnessContrastEffect *self = CLUTTER_BRIGHTNESS_CONTRAST_EFFECT (effect); + ClutterActor *actor; + guint8 paint_opacity; + + actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); + paint_opacity = clutter_actor_get_paint_opacity (actor); + + cogl_pipeline_set_color4ub (self->pipeline, + paint_opacity, + paint_opacity, + paint_opacity, + paint_opacity); + cogl_push_source (self->pipeline); + + cogl_rectangle (0, 0, self->tex_width, self->tex_height); + + cogl_pop_source (); +} + +static void +clutter_brightness_contrast_effect_dispose (GObject *gobject) +{ + ClutterBrightnessContrastEffect *self = CLUTTER_BRIGHTNESS_CONTRAST_EFFECT (gobject); + + if (self->pipeline != NULL) + { + cogl_object_unref (self->pipeline); + self->pipeline = NULL; + } + + G_OBJECT_CLASS (clutter_brightness_contrast_effect_parent_class)->dispose (gobject); +} + +static void +clutter_brightness_contrast_effect_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterBrightnessContrastEffect *effect = CLUTTER_BRIGHTNESS_CONTRAST_EFFECT (gobject); + + switch (prop_id) + { + case PROP_BRIGHTNESS: + { + const ClutterColor *color = clutter_value_get_color (value); + clutter_brightness_contrast_effect_set_brightness_full (effect, + color->red / 127.0f - 1.0f, + color->green / 127.0f - 1.0f, + color->blue / 127.0f - 1.0f); + } + break; + + case PROP_CONTRAST: + { + const ClutterColor *color = clutter_value_get_color (value); + clutter_brightness_contrast_effect_set_contrast_full (effect, + color->red / 127.0f - 1.0f, + color->green / 127.0f - 1.0f, + color->blue / 127.0f - 1.0f); + } + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_brightness_contrast_effect_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterBrightnessContrastEffect *effect = CLUTTER_BRIGHTNESS_CONTRAST_EFFECT (gobject); + ClutterColor color; + + switch (prop_id) + { + case PROP_BRIGHTNESS: + { + color.red = (effect->brightness_red + 1.0f) * 127.0f; + color.green = (effect->brightness_green + 1.0f) * 127.0f; + color.blue = (effect->brightness_blue + 1.0f) * 127.0f; + color.alpha = 0xff; + + clutter_value_set_color (value, &color); + } + break; + + case PROP_CONTRAST: + { + color.red = (effect->contrast_red + 1.0f) * 127.0f; + color.green = (effect->contrast_green + 1.0f) * 127.0f; + color.blue = (effect->contrast_blue + 1.0f) * 127.0f; + color.alpha = 0xff; + + clutter_value_set_color (value, &color); + } + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_brightness_contrast_effect_class_init (ClutterBrightnessContrastEffectClass *klass) +{ + ClutterEffectClass *effect_class = CLUTTER_EFFECT_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterOffscreenEffectClass *offscreen_class; + + offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass); + offscreen_class->paint_target = clutter_brightness_contrast_effect_paint_target; + + effect_class->pre_paint = clutter_brightness_contrast_effect_pre_paint; + + gobject_class->set_property = clutter_brightness_contrast_effect_set_property; + gobject_class->get_property = clutter_brightness_contrast_effect_get_property; + gobject_class->dispose = clutter_brightness_contrast_effect_dispose; + + /** + * ClutterBrightnessContrastEffect:brightness: + * + * The brightness change to apply to the effect. + * + * This property uses a #ClutterColor to represent the changes to each + * color channel. The range is [ 0, 255 ], with 127 as the value used + * to indicate no change; values smaller than 127 indicate a decrease + * in brightness, and values larger than 127 indicate an increase in + * brightness. + * + * Since: 1.10 + */ + obj_props[PROP_BRIGHTNESS] = + clutter_param_spec_color ("brightness", + P_("Brightness"), + P_("The brightness change to apply"), + &no_brightness_change, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterBrightnessContrastEffect:contrast: + * + * The contrast change to apply to the effect. + * + * This property uses a #ClutterColor to represent the changes to each + * color channel. The range is [ 0, 255 ], with 127 as the value used + * to indicate no change; values smaller than 127 indicate a decrease + * in contrast, and values larger than 127 indicate an increase in + * contrast. + * + * Since: 1.10 + */ + obj_props[PROP_CONTRAST] = + clutter_param_spec_color ("contrast", + P_("Contrast"), + P_("The contrast change to apply"), + &no_contrast_change, + CLUTTER_PARAM_READWRITE); + + g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); +} + +static void +get_brightness_values (gfloat value, + gfloat *multiplier, + gfloat *offset) +{ + if (value < 0.0f) + { + *multiplier = 1.0f + value; + *offset = 0.0f; + } + else + { + *multiplier = 1.0f - value; + *offset = value; + } +} + +static inline void +update_uniforms (ClutterBrightnessContrastEffect *self) +{ + if (self->brightness_multiplier_uniform > -1 && + self->brightness_offset_uniform > -1) + { + float brightness_multiplier[3]; + float brightness_offset[3]; + + get_brightness_values (self->brightness_red, + brightness_multiplier + 0, + brightness_offset + 0); + get_brightness_values (self->brightness_green, + brightness_multiplier + 1, + brightness_offset + 1); + get_brightness_values (self->brightness_blue, + brightness_multiplier + 2, + brightness_offset + 2); + + cogl_pipeline_set_uniform_float (self->pipeline, + self->brightness_multiplier_uniform, + 3, /* n_components */ + 1, /* count */ + brightness_multiplier); + cogl_pipeline_set_uniform_float (self->pipeline, + self->brightness_offset_uniform, + 3, /* n_components */ + 1, /* count */ + brightness_offset); + } + + if (self->contrast_uniform > -1) + { + float contrast[3] = { + tan ((self->contrast_red + 1) * G_PI_4), + tan ((self->contrast_green + 1) * G_PI_4), + tan ((self->contrast_blue + 1) * G_PI_4) + }; + + cogl_pipeline_set_uniform_float (self->pipeline, + self->contrast_uniform, + 3, /* n_components */ + 1, /* count */ + contrast); + } +} + +static void +clutter_brightness_contrast_effect_init (ClutterBrightnessContrastEffect *self) +{ + ClutterBrightnessContrastEffectClass *klass; + + self->brightness_red = no_change; + self->brightness_green = no_change; + self->brightness_blue = no_change; + + self->contrast_red = no_change; + self->contrast_green = no_change; + self->contrast_blue = no_change; + + klass = CLUTTER_BRIGHTNESS_CONTRAST_EFFECT_GET_CLASS (self); + + if (G_UNLIKELY (klass->base_pipeline == NULL)) + { + CoglSnippet *snippet; + CoglContext *ctx = + clutter_backend_get_cogl_context (clutter_get_default_backend ()); + + klass->base_pipeline = cogl_pipeline_new (ctx); + + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, + brightness_contrast_decls, + brightness_contrast_source); + cogl_pipeline_add_snippet (klass->base_pipeline, snippet); + cogl_object_unref (snippet); + + cogl_pipeline_set_layer_null_texture (klass->base_pipeline, + 0, /* layer number */ + COGL_TEXTURE_TYPE_2D); + } + + self->pipeline = cogl_pipeline_copy (klass->base_pipeline); + + self->brightness_multiplier_uniform = + cogl_pipeline_get_uniform_location (self->pipeline, + "brightness_multiplier"); + self->brightness_offset_uniform = + cogl_pipeline_get_uniform_location (self->pipeline, + "brightness_offset"); + self->contrast_uniform = + cogl_pipeline_get_uniform_location (self->pipeline, "contrast"); + + update_uniforms (self); +} + +/** + * clutter_brightness_contrast_effect_new: + * + * Creates a new #ClutterBrightnessContrastEffect to be used with + * clutter_actor_add_effect() + * + * Return value: (transfer full): the newly created + * #ClutterBrightnessContrastEffect or %NULL. Use g_object_unref() when + * done. + * + * Since: 1.10 + */ +ClutterEffect * +clutter_brightness_contrast_effect_new (void) +{ + return g_object_new (CLUTTER_TYPE_BRIGHTNESS_CONTRAST_EFFECT, NULL); +} + +/** + * clutter_brightness_contrast_effect_set_brightness_full: + * @effect: a #ClutterBrightnessContrastEffect + * @red: red component of the change in brightness + * @green: green component of the change in brightness + * @blue: blue component of the change in brightness + * + * The range for each component is [-1.0, 1.0] where 0.0 designates no change, + * values below 0.0 mean a decrease in brightness, and values above indicate + * an increase. + * + * Since: 1.10 + */ +void +clutter_brightness_contrast_effect_set_brightness_full (ClutterBrightnessContrastEffect *effect, + gfloat red, + gfloat green, + gfloat blue) +{ + g_return_if_fail (CLUTTER_IS_BRIGHTNESS_CONTRAST_EFFECT (effect)); + + if (red == effect->brightness_red && + green == effect->brightness_green && + blue == effect->brightness_blue) + return; + + effect->brightness_red = red; + effect->brightness_green = green; + effect->brightness_blue = blue; + + update_uniforms (effect); + + clutter_effect_queue_repaint (CLUTTER_EFFECT (effect)); + + g_object_notify_by_pspec (G_OBJECT (effect), obj_props[PROP_BRIGHTNESS]); +} + +/** + * clutter_brightness_contrast_effect_get_brightness: + * @effect: a #ClutterBrightnessContrastEffect + * @red: (out) (allow-none): return location for red component of the + * change in brightness + * @green: (out) (allow-none): return location for green component of the + * change in brightness + * @blue: (out) (allow-none): return location for blue component of the + * change in brightness + * + * Retrieves the change in brightness used by @effect. + * + * Since: 1.10 + */ +void +clutter_brightness_contrast_effect_get_brightness (ClutterBrightnessContrastEffect *effect, + gfloat *red, + gfloat *green, + gfloat *blue) +{ + g_return_if_fail (CLUTTER_IS_BRIGHTNESS_CONTRAST_EFFECT (effect)); + + if (red != NULL) + *red = effect->brightness_red; + + if (green != NULL) + *green = effect->brightness_green; + + if (blue != NULL) + *blue = effect->brightness_blue; +} + +/** + * clutter_brightness_contrast_effect_set_brightness: + * @effect: a #ClutterBrightnessContrastEffect + * @brightness: the brightness change for all three components (r, g, b) + * + * The range of @brightness is [-1.0, 1.0], where 0.0 designates no change; + * a value below 0.0 indicates a decrease in brightness; and a value + * above 0.0 indicates an increase of brightness. + * + * Since: 1.10 + */ +void +clutter_brightness_contrast_effect_set_brightness (ClutterBrightnessContrastEffect *effect, + gfloat brightness) +{ + clutter_brightness_contrast_effect_set_brightness_full (effect, + brightness, + brightness, + brightness); +} + +/** + * clutter_brightness_contrast_effect_set_contrast_full: + * @effect: a #ClutterBrightnessContrastEffect + * @red: red component of the change in contrast + * @green: green component of the change in contrast + * @blue: blue component of the change in contrast + * + * The range for each component is [-1.0, 1.0] where 0.0 designates no change, + * values below 0.0 mean a decrease in contrast, and values above indicate + * an increase. + * + * Since: 1.10 + */ +void +clutter_brightness_contrast_effect_set_contrast_full (ClutterBrightnessContrastEffect *effect, + gfloat red, + gfloat green, + gfloat blue) +{ + g_return_if_fail (CLUTTER_IS_BRIGHTNESS_CONTRAST_EFFECT (effect)); + + if (red == effect->contrast_red && + green == effect->contrast_green && + blue == effect->contrast_blue) + return; + + effect->contrast_red = red; + effect->contrast_green = green; + effect->contrast_blue = blue; + + update_uniforms (effect); + + clutter_effect_queue_repaint (CLUTTER_EFFECT (effect)); + + g_object_notify_by_pspec (G_OBJECT (effect), obj_props[PROP_CONTRAST]); +} + +/** + * clutter_brightness_contrast_effect_get_contrast: + * @effect: a #ClutterBrightnessContrastEffect + * @red: (out) (allow-none): return location for red component of the + * change in contrast + * @green: (out) (allow-none): return location for green component of the + * change in contrast + * @blue: (out) (allow-none): return location for blue component of the + * change in contrast + * + * Retrieves the contrast value used by @effect. + * + * Since: 1.10 + */ +void +clutter_brightness_contrast_effect_get_contrast (ClutterBrightnessContrastEffect *effect, + gfloat *red, + gfloat *green, + gfloat *blue) +{ + g_return_if_fail (CLUTTER_IS_BRIGHTNESS_CONTRAST_EFFECT (effect)); + + if (red != NULL) + *red = effect->contrast_red; + + if (green != NULL) + *green = effect->contrast_green; + + if (blue != NULL) + *blue = effect->contrast_blue; +} + +/** + * clutter_brightness_contrast_effect_set_contrast: + * @effect: a #ClutterBrightnessContrastEffect + * @contrast: contrast change for all three channels + * + * The range for @contrast is [-1.0, 1.0], where 0.0 designates no change; + * a value below 0.0 indicates a decrease in contrast; and a value above + * 0.0 indicates an increase. + * + * Since: 1.10 + */ +void +clutter_brightness_contrast_effect_set_contrast (ClutterBrightnessContrastEffect *effect, + gfloat contrast) +{ + clutter_brightness_contrast_effect_set_contrast_full (effect, + contrast, + contrast, + contrast); +} diff --git a/clutter/clutter/clutter-brightness-contrast-effect.h b/clutter/clutter/clutter-brightness-contrast-effect.h new file mode 100644 index 0000000..0d9094a --- /dev/null +++ b/clutter/clutter/clutter-brightness-contrast-effect.h @@ -0,0 +1,88 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010-2012 Inclusive Design Research Centre, OCAD University. + * + * 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 . + * + * Author: + * Joseph Scheuhammer + */ + +#ifndef __CLUTTER_BRIGHTNESS_CONTRAST_EFFECT_H__ +#define __CLUTTER_BRIGHTNESS_CONTRAST_EFFECT_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BRIGHTNESS_CONTRAST_EFFECT (clutter_brightness_contrast_effect_get_type ()) +#define CLUTTER_BRIGHTNESS_CONTRAST_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BRIGHTNESS_CONTRAST_EFFECT, ClutterBrightnessContrastEffect)) +#define CLUTTER_IS_BRIGHTNESS_CONTRAST_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BRIGHTNESS_CONTRAST_EFFECT)) + +/** + * ClutterBrightnessContrastEffect: + * + * #ClutterBrightnessContrastEffect is an opaque structure + * whose members cannot be directly accessed + * + * Since: 1.10 + */ +typedef struct _ClutterBrightnessContrastEffect ClutterBrightnessContrastEffect; +typedef struct _ClutterBrightnessContrastEffectClass ClutterBrightnessContrastEffectClass; + +CLUTTER_AVAILABLE_IN_1_10 +GType clutter_brightness_contrast_effect_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_10 +ClutterEffect * clutter_brightness_contrast_effect_new (void); + +CLUTTER_AVAILABLE_IN_1_10 +void clutter_brightness_contrast_effect_set_brightness_full (ClutterBrightnessContrastEffect *effect, + float red, + float green, + float blue); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_brightness_contrast_effect_set_brightness (ClutterBrightnessContrastEffect *effect, + float brightness); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_brightness_contrast_effect_get_brightness (ClutterBrightnessContrastEffect *effect, + float *red, + float *green, + float *blue); + +CLUTTER_AVAILABLE_IN_1_10 +void clutter_brightness_contrast_effect_set_contrast_full (ClutterBrightnessContrastEffect *effect, + float red, + float green, + float blue); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_brightness_contrast_effect_set_contrast (ClutterBrightnessContrastEffect *effect, + float contrast); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_brightness_contrast_effect_get_contrast (ClutterBrightnessContrastEffect *effect, + float *red, + float *green, + float *blue); + +G_END_DECLS + +#endif /* __CLUTTER_BRIGHTNESS_CONTRAST_EFFECT_H__ */ diff --git a/clutter/clutter/clutter-build-config.h.in b/clutter/clutter/clutter-build-config.h.in new file mode 100644 index 0000000..3fe04c1 --- /dev/null +++ b/clutter/clutter/clutter-build-config.h.in @@ -0,0 +1,100 @@ +/* clutter/clutter-build-config.h.in. Generated from configure.ac by autoheader. */ + +/* List of Cogl drivers */ +#undef CLUTTER_DRIVERS + +/* Use Generic EGL backend */ +#undef CLUTTER_EGL_BACKEND_GENERIC + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Have evdev support for input handling */ +#undef HAVE_EVDEV + +/* Whether you have gcov */ +#undef HAVE_GCOV + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Supports PangoFt2 */ +#undef HAVE_PANGO_FT2 + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_X11_EXTENSIONS_XINPUT2_H + +/* Define to 1 if we have the XCOMPOSITE X extension */ +#undef HAVE_XCOMPOSITE + +/* Define to 1 if we have the XDAMAGE X extension */ +#undef HAVE_XDAMAGE + +/* Define to 1 if we have the XEXT X extension */ +#undef HAVE_XEXT + +/* Define to 1 if X Generic Extensions is available */ +#undef HAVE_XGE + +/* Define to 1 if XI2 is available */ +#undef HAVE_XINPUT_2 + +/* Define to 1 if XInput 2.2 is available */ +#undef HAVE_XINPUT_2_2 + +/* Define to use XKB extension */ +#undef HAVE_XKB + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#undef LT_OBJDIR + +/* Define to 1 if building for Linux */ +#undef OS_LINUX + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* defines how to decorate public symbols while building */ +#undef _CLUTTER_EXTERN diff --git a/clutter/clutter/clutter-cairo.c b/clutter/clutter/clutter-cairo.c new file mode 100644 index 0000000..b5c24b2 --- /dev/null +++ b/clutter/clutter/clutter-cairo.c @@ -0,0 +1,92 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2012 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 . + */ + +/** + * SECTION:clutter-cairo + * @Title: Cairo integration + * @Short_Description: Functions for interoperating with Cairo + * + * Clutter provides some utility functions for using Cairo. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-cairo.h" +#include "clutter-color.h" + +/** + * clutter_cairo_set_source_color: + * @cr: a Cairo context + * @color: a #ClutterColor + * + * Utility function for setting the source color of @cr using + * a #ClutterColor. This function is the equivalent of: + * + * |[ + * cairo_set_source_rgba (cr, + * color->red / 255.0, + * color->green / 255.0, + * color->blue / 255.0, + * color->alpha / 255.0); + * ]| + * + * Since: 1.0 + */ +void +clutter_cairo_set_source_color (cairo_t *cr, + const ClutterColor *color) +{ + g_return_if_fail (cr != NULL); + g_return_if_fail (color != NULL); + + if (color->alpha == 0xff) + cairo_set_source_rgb (cr, + color->red / 255.0, + color->green / 255.0, + color->blue / 255.0); + else + cairo_set_source_rgba (cr, + color->red / 255.0, + color->green / 255.0, + color->blue / 255.0, + color->alpha / 255.0); +} + +/** + * clutter_cairo_clear: + * @cr: a Cairo context + * + * Utility function to clear a Cairo context. + * + * Since: 1.12 + */ +void +clutter_cairo_clear (cairo_t *cr) +{ + cairo_save (cr); + + cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); + cairo_paint (cr); + + cairo_restore (cr); +} diff --git a/clutter/clutter/clutter-cairo.h b/clutter/clutter/clutter-cairo.h new file mode 100644 index 0000000..9b2ad05 --- /dev/null +++ b/clutter/clutter/clutter-cairo.h @@ -0,0 +1,61 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2012 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 . + */ + +#ifndef __CLUTTER_CAIRO_H__ +#define __CLUTTER_CAIRO_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +/** + * CLUTTER_CAIRO_FORMAT_ARGB32: + * + * The #CoglPixelFormat to be used when uploading image data from + * and to a Cairo image surface using %CAIRO_FORMAT_ARGB32 and + * %CAIRO_FORMAT_RGB24 as #cairo_format_t. + * + * Since: 1.8 + */ + +/* Cairo stores the data in native byte order as ARGB but Cogl's pixel + * formats specify the actual byte order. Therefore we need to use a + * different format depending on the architecture + */ +#if G_BYTE_ORDER == G_LITTLE_ENDIAN +#define CLUTTER_CAIRO_FORMAT_ARGB32 (COGL_PIXEL_FORMAT_BGRA_8888_PRE) +#else +#define CLUTTER_CAIRO_FORMAT_ARGB32 (COGL_PIXEL_FORMAT_ARGB_8888_PRE) +#endif + +CLUTTER_AVAILABLE_IN_1_12 +void clutter_cairo_clear (cairo_t *cr); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_cairo_set_source_color (cairo_t *cr, + const ClutterColor *color); + +G_END_DECLS + +#endif /* __CLUTTER_CAIRO_H__ */ diff --git a/clutter/clutter/clutter-canvas.c b/clutter/clutter/clutter-canvas.c new file mode 100644 index 0000000..98f8c07 --- /dev/null +++ b/clutter/clutter/clutter-canvas.c @@ -0,0 +1,716 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2012 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 . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-canvas + * @Title: ClutterCanvas + * @Short_Description: Content for 2D painting + * @See_Also: #ClutterContent + * + * The #ClutterCanvas class is a #ClutterContent implementation that allows + * drawing using the Cairo API on a 2D surface. + * + * In order to draw on a #ClutterCanvas, you should connect a handler to the + * #ClutterCanvas::draw signal; the signal will receive a #cairo_t context + * that can be used to draw. #ClutterCanvas will emit the #ClutterCanvas::draw + * signal when invalidated using clutter_content_invalidate(). + * + * See [canvas.c](https://git.gnome.org/browse/clutter/tree/examples/canvas.c?h=clutter-1.18) + * for an example of how to use #ClutterCanvas. + * + * #ClutterCanvas is available since Clutter 1.10. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include +#include + +#include "clutter-canvas.h" + +#define CLUTTER_ENABLE_EXPERIMENTAL_API + +#include "clutter-actor-private.h" +#include "clutter-backend.h" +#include "clutter-cairo.h" +#include "clutter-color.h" +#include "clutter-content-private.h" +#include "clutter-debug.h" +#include "clutter-marshal.h" +#include "clutter-paint-node.h" +#include "clutter-paint-nodes.h" +#include "clutter-private.h" +#include "clutter-settings.h" + +struct _ClutterCanvasPrivate +{ + cairo_t *cr; + + int width; + int height; + + CoglTexture *texture; + gboolean dirty; + + CoglBitmap *buffer; + + int scale_factor; + guint scale_factor_set : 1; +}; + +enum +{ + PROP_0, + + PROP_WIDTH, + PROP_HEIGHT, + PROP_SCALE_FACTOR, + PROP_SCALE_FACTOR_SET, + + LAST_PROP +}; + +static GParamSpec *obj_props[LAST_PROP] = { NULL, }; + +enum +{ + DRAW, + + LAST_SIGNAL +}; + +static guint canvas_signals[LAST_SIGNAL] = { 0, }; + +static void clutter_content_iface_init (ClutterContentIface *iface); + +G_DEFINE_TYPE_WITH_CODE (ClutterCanvas, clutter_canvas, G_TYPE_OBJECT, + G_ADD_PRIVATE (ClutterCanvas) + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTENT, + clutter_content_iface_init)) + +static void +clutter_cairo_context_draw_marshaller (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + cairo_t *cr = g_value_get_boxed (¶m_values[1]); + + cairo_save (cr); + + _clutter_marshal_BOOLEAN__BOXED_INT_INT (closure, + return_value, + n_param_values, + param_values, + invocation_hint, + marshal_data); + + cairo_restore (cr); +} + +static void +clutter_canvas_finalize (GObject *gobject) +{ + ClutterCanvasPrivate *priv = CLUTTER_CANVAS (gobject)->priv; + + if (priv->buffer != NULL) + { + cogl_object_unref (priv->buffer); + priv->buffer = NULL; + } + + g_clear_pointer (&priv->texture, cogl_object_unref); + + G_OBJECT_CLASS (clutter_canvas_parent_class)->finalize (gobject); +} + +static void +clutter_canvas_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterCanvasPrivate *priv = CLUTTER_CANVAS (gobject)->priv; + + switch (prop_id) + { + case PROP_WIDTH: + { + gint new_size = g_value_get_int (value); + + if (priv->width != new_size) + { + priv->width = new_size; + + clutter_content_invalidate (CLUTTER_CONTENT (gobject)); + } + } + break; + + case PROP_HEIGHT: + { + gint new_size = g_value_get_int (value); + + if (priv->height != new_size) + { + priv->height = new_size; + + clutter_content_invalidate (CLUTTER_CONTENT (gobject)); + } + } + break; + + case PROP_SCALE_FACTOR: + clutter_canvas_set_scale_factor (CLUTTER_CANVAS (gobject), + g_value_get_int (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_canvas_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterCanvasPrivate *priv = CLUTTER_CANVAS (gobject)->priv; + + switch (prop_id) + { + case PROP_WIDTH: + g_value_set_int (value, priv->width); + break; + + case PROP_HEIGHT: + g_value_set_int (value, priv->height); + break; + + case PROP_SCALE_FACTOR: + if (priv->scale_factor_set) + g_value_set_int (value, priv->scale_factor); + else + g_value_set_int (value, -1); + break; + + case PROP_SCALE_FACTOR_SET: + g_value_set_boolean (value, priv->scale_factor_set); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_canvas_class_init (ClutterCanvasClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + /** + * ClutterCanvas:width: + * + * The width of the canvas. + * + * Since: 1.10 + */ + obj_props[PROP_WIDTH] = + g_param_spec_int ("width", + P_("Width"), + P_("The width of the canvas"), + -1, G_MAXINT, + -1, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + /** + * ClutterCanvas:height: + * + * The height of the canvas. + * + * Since: 1.10 + */ + obj_props[PROP_HEIGHT] = + g_param_spec_int ("height", + P_("Height"), + P_("The height of the canvas"), + -1, G_MAXINT, + -1, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + /** + * ClutterCanvas:scale-factor-set: + * + * Whether the #ClutterCanvas:scale-factor property is set. + * + * If the #ClutterCanvas:scale-factor-set property is %FALSE + * then #ClutterCanvas will use the #ClutterSettings:window-scaling-factor + * property. + * + * Since: 1.18 + */ + obj_props[PROP_SCALE_FACTOR_SET] = + g_param_spec_boolean ("scale-factor-set", + P_("Scale Factor Set"), + P_("Whether the scale-factor property is set"), + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + /** + * ClutterCanvas:scale-factor: + * + * The scaling factor to be applied to the Cairo surface used for + * drawing. + * + * If #ClutterCanvas:scale-factor is set to a negative value, the + * value of the #ClutterSettings:window-scaling-factor property is + * used instead. + * + * Use #ClutterCanvas:scale-factor-set to check if the scale factor + * is set. + * + * Since: 1.18 + */ + obj_props[PROP_SCALE_FACTOR] = + g_param_spec_int ("scale-factor", + P_("Scale Factor"), + P_("The scaling factor for the surface"), + -1, 1000, + -1, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * ClutterCanvas::draw: + * @canvas: the #ClutterCanvas that emitted the signal + * @cr: the Cairo context used to draw + * @width: the width of the @canvas + * @height: the height of the @canvas + * + * The #ClutterCanvas::draw signal is emitted each time a canvas is + * invalidated. + * + * It is safe to connect multiple handlers to this signal: each + * handler invocation will be automatically protected by cairo_save() + * and cairo_restore() pairs. + * + * Return value: %TRUE if the signal emission should stop, and + * %FALSE otherwise + * + * Since: 1.10 + */ + canvas_signals[DRAW] = + g_signal_new (I_("draw"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (ClutterCanvasClass, draw), + _clutter_boolean_handled_accumulator, NULL, + clutter_cairo_context_draw_marshaller, + G_TYPE_BOOLEAN, 3, + CAIRO_GOBJECT_TYPE_CONTEXT, + G_TYPE_INT, + G_TYPE_INT); + + gobject_class->set_property = clutter_canvas_set_property; + gobject_class->get_property = clutter_canvas_get_property; + gobject_class->finalize = clutter_canvas_finalize; + + g_object_class_install_properties (gobject_class, LAST_PROP, obj_props); +} + +static void +clutter_canvas_init (ClutterCanvas *self) +{ + self->priv = clutter_canvas_get_instance_private (self); + + self->priv->width = -1; + self->priv->height = -1; + self->priv->scale_factor = -1; +} + +static void +clutter_canvas_paint_content (ClutterContent *content, + ClutterActor *actor, + ClutterPaintNode *root) +{ + ClutterCanvas *self = CLUTTER_CANVAS (content); + ClutterCanvasPrivate *priv = self->priv; + ClutterPaintNode *node; + + if (priv->buffer == NULL) + return; + + if (priv->dirty) + g_clear_pointer (&priv->texture, cogl_object_unref); + + if (priv->texture == NULL) + priv->texture = cogl_texture_new_from_bitmap (priv->buffer, + COGL_TEXTURE_NO_SLICING, + CLUTTER_CAIRO_FORMAT_ARGB32); + + if (priv->texture == NULL) + return; + + node = clutter_actor_create_texture_paint_node (actor, priv->texture); + clutter_paint_node_set_name (node, "Canvas Content"); + clutter_paint_node_add_child (root, node); + clutter_paint_node_unref (node); + + priv->dirty = FALSE; +} + +static void +clutter_canvas_emit_draw (ClutterCanvas *self) +{ + ClutterCanvasPrivate *priv = self->priv; + int real_width, real_height; + cairo_surface_t *surface; + gboolean mapped_buffer; + unsigned char *data; + CoglBuffer *buffer; + int window_scale = 1; + gboolean res; + cairo_t *cr; + + g_assert (priv->height > 0 && priv->width > 0); + + priv->dirty = TRUE; + + if (priv->scale_factor_set) + window_scale = priv->scale_factor; + else + g_object_get (clutter_settings_get_default (), + "window-scaling-factor", &window_scale, + NULL); + + real_width = priv->width * window_scale; + real_height = priv->height * window_scale; + + CLUTTER_NOTE (MISC, "Creating Cairo surface with size %d x %d (real: %d x %d, scale: %d)", + priv->width, priv->height, + real_width, real_height, + window_scale); + + if (priv->buffer == NULL) + { + CoglContext *ctx; + + ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); + priv->buffer = cogl_bitmap_new_with_size (ctx, + real_width, + real_height, + CLUTTER_CAIRO_FORMAT_ARGB32); + } + + buffer = COGL_BUFFER (cogl_bitmap_get_buffer (priv->buffer)); + if (buffer == NULL) + return; + + cogl_buffer_set_update_hint (buffer, COGL_BUFFER_UPDATE_HINT_DYNAMIC); + + data = cogl_buffer_map (buffer, + COGL_BUFFER_ACCESS_READ_WRITE, + COGL_BUFFER_MAP_HINT_DISCARD); + + if (data != NULL) + { + int bitmap_stride = cogl_bitmap_get_rowstride (priv->buffer); + + surface = cairo_image_surface_create_for_data (data, + CAIRO_FORMAT_ARGB32, + real_width, + real_height, + bitmap_stride); + mapped_buffer = TRUE; + } + else + { + surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, + real_width, + real_height); + + mapped_buffer = FALSE; + } + + cairo_surface_set_device_scale (surface, window_scale, window_scale); + + self->priv->cr = cr = cairo_create (surface); + + g_signal_emit (self, canvas_signals[DRAW], 0, + cr, priv->width, priv->height, + &res); + +#ifdef CLUTTER_ENABLE_DEBUG + if (_clutter_diagnostic_enabled () && cairo_status (cr)) + { + g_warning ("Drawing failed for [%p]: %s", + self, + cairo_status_to_string (cairo_status (cr))); + } +#endif + + self->priv->cr = NULL; + cairo_destroy (cr); + + if (mapped_buffer) + cogl_buffer_unmap (buffer); + else + { + int size = cairo_image_surface_get_stride (surface) * priv->height; + cogl_buffer_set_data (buffer, + 0, + cairo_image_surface_get_data (surface), + size); + } + + cairo_surface_destroy (surface); +} + +static void +clutter_canvas_invalidate (ClutterContent *content) +{ + ClutterCanvas *self = CLUTTER_CANVAS (content); + ClutterCanvasPrivate *priv = self->priv; + + if (priv->buffer != NULL) + { + cogl_object_unref (priv->buffer); + priv->buffer = NULL; + } + + if (priv->width <= 0 || priv->height <= 0) + return; + + clutter_canvas_emit_draw (self); +} + +static gboolean +clutter_canvas_get_preferred_size (ClutterContent *content, + gfloat *width, + gfloat *height) +{ + ClutterCanvasPrivate *priv = CLUTTER_CANVAS (content)->priv; + + if (priv->width < 0 || priv->height < 0) + return FALSE; + + if (width != NULL) + *width = priv->width; + + if (height != NULL) + *height = priv->height; + + return TRUE; +} + +static void +clutter_content_iface_init (ClutterContentIface *iface) +{ + iface->invalidate = clutter_canvas_invalidate; + iface->paint_content = clutter_canvas_paint_content; + iface->get_preferred_size = clutter_canvas_get_preferred_size; +} + +/** + * clutter_canvas_new: + * + * Creates a new instance of #ClutterCanvas. + * + * You should call clutter_canvas_set_size() to set the size of the canvas. + * + * You should call clutter_content_invalidate() every time you wish to + * draw the contents of the canvas. + * + * Return value: (transfer full): The newly allocated instance of + * #ClutterCanvas. Use g_object_unref() when done. + * + * Since: 1.10 + */ +ClutterContent * +clutter_canvas_new (void) +{ + return g_object_new (CLUTTER_TYPE_CANVAS, NULL); +} + +static gboolean +clutter_canvas_invalidate_internal (ClutterCanvas *canvas, + int width, + int height) +{ + gboolean width_changed = FALSE, height_changed = FALSE; + gboolean res = FALSE; + GObject *obj; + + obj = G_OBJECT (canvas); + + g_object_freeze_notify (obj); + + if (canvas->priv->width != width) + { + canvas->priv->width = width; + width_changed = TRUE; + + g_object_notify_by_pspec (obj, obj_props[PROP_WIDTH]); + } + + if (canvas->priv->height != height) + { + canvas->priv->height = height; + height_changed = TRUE; + + g_object_notify_by_pspec (obj, obj_props[PROP_HEIGHT]); + } + + if (width_changed || height_changed) + { + clutter_content_invalidate (CLUTTER_CONTENT (canvas)); + res = TRUE; + } + + g_object_thaw_notify (obj); + + return res; +} + +/** + * clutter_canvas_set_size: + * @canvas: a #ClutterCanvas + * @width: the width of the canvas, in pixels + * @height: the height of the canvas, in pixels + * + * Sets the size of the @canvas, and invalidates the content. + * + * This function will cause the @canvas to be invalidated only + * if the size of the canvas surface has changed. + * + * If you want to invalidate the contents of the @canvas when setting + * the size, you can use the return value of the function to conditionally + * call clutter_content_invalidate(): + * + * |[ + * if (!clutter_canvas_set_size (canvas, width, height)) + * clutter_content_invalidate (CLUTTER_CONTENT (canvas)); + * ]| + * + * Return value: this function returns %TRUE if the size change + * caused a content invalidation, and %FALSE otherwise + * + * Since: 1.10 + */ +gboolean +clutter_canvas_set_size (ClutterCanvas *canvas, + int width, + int height) +{ + g_return_val_if_fail (CLUTTER_IS_CANVAS (canvas), FALSE); + g_return_val_if_fail (width >= -1 && height >= -1, FALSE); + + return clutter_canvas_invalidate_internal (canvas, width, height); +} + +/** + * clutter_canvas_set_scale_factor: + * @canvas: a #ClutterCanvas + * @scale: the scale factor, or -1 for the default + * + * Sets the scaling factor for the Cairo surface used by @canvas. + * + * This function should rarely be used. + * + * The default scaling factor of a #ClutterCanvas content uses the + * #ClutterSettings:window-scaling-factor property, which is set by + * the windowing system. By using this function it is possible to + * override that setting. + * + * Changing the scale factor will invalidate the @canvas. + * + * Since: 1.18 + */ +void +clutter_canvas_set_scale_factor (ClutterCanvas *canvas, + int scale) +{ + ClutterCanvasPrivate *priv; + GObject *obj; + + g_return_if_fail (CLUTTER_IS_CANVAS (canvas)); + g_return_if_fail (scale != 0); + + priv = canvas->priv; + + if (scale < 0) + { + if (!priv->scale_factor_set) + return; + + priv->scale_factor_set = FALSE; + priv->scale_factor = -1; + } + else + { + if (priv->scale_factor_set && priv->scale_factor == scale) + return; + + priv->scale_factor_set = TRUE; + priv->scale_factor = scale; + } + + clutter_content_invalidate (CLUTTER_CONTENT (canvas)); + + obj = G_OBJECT (canvas); + + g_object_notify_by_pspec (obj, obj_props[PROP_SCALE_FACTOR]); + g_object_notify_by_pspec (obj, obj_props[PROP_SCALE_FACTOR_SET]); +} + +/** + * clutter_canvas_get_scale_factor: + * @canvas: a #ClutterCanvas + * + * Retrieves the scaling factor of @canvas, as set using + * clutter_canvas_set_scale_factor(). + * + * Return value: the scaling factor, or -1 if the @canvas + * uses the default from #ClutterSettings + * + * Since: 1.18 + */ +int +clutter_canvas_get_scale_factor (ClutterCanvas *canvas) +{ + g_return_val_if_fail (CLUTTER_IS_CANVAS (canvas), -1); + + if (!canvas->priv->scale_factor_set) + return -1; + + return canvas->priv->scale_factor; +} diff --git a/clutter/clutter/clutter-canvas.h b/clutter/clutter/clutter-canvas.h new file mode 100644 index 0000000..ed62dd4 --- /dev/null +++ b/clutter/clutter/clutter-canvas.h @@ -0,0 +1,106 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2012 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 . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_CANVAS_H__ +#define __CLUTTER_CANVAS_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_CANVAS (clutter_canvas_get_type ()) +#define CLUTTER_CANVAS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_CANVAS, ClutterCanvas)) +#define CLUTTER_IS_CANVAS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_CANVAS)) +#define CLUTTER_CANVAS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_CANVAS, ClutterCanvasClass)) +#define CLUTTER_IS_CANVAS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_CANVAS)) +#define CLUTTER_CANVAS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_CANVAS, ClutterCanvasClass)) + +typedef struct _ClutterCanvas ClutterCanvas; +typedef struct _ClutterCanvasPrivate ClutterCanvasPrivate; +typedef struct _ClutterCanvasClass ClutterCanvasClass; + +/** + * ClutterCanvas: + * + * The #ClutterCanvas structure contains + * private data and should only be accessed using the provided + * API. + * + * Since: 1.10 + */ +struct _ClutterCanvas +{ + /*< private >*/ + GObject parent_instance; + + ClutterCanvasPrivate *priv; +}; + +/** + * ClutterCanvasClass: + * @draw: class handler for the #ClutterCanvas::draw signal + * + * The #ClutterCanvasClass structure contains + * private data. + * + * Since: 1.10 + */ +struct _ClutterCanvasClass +{ + /*< private >*/ + GObjectClass parent_class; + + /*< public >*/ + gboolean (* draw) (ClutterCanvas *canvas, + cairo_t *cr, + int width, + int height); + + /*< private >*/ + gpointer _padding[16]; +}; + +CLUTTER_AVAILABLE_IN_1_10 +GType clutter_canvas_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_10 +ClutterContent * clutter_canvas_new (void); +CLUTTER_AVAILABLE_IN_1_10 +gboolean clutter_canvas_set_size (ClutterCanvas *canvas, + int width, + int height); + +CLUTTER_AVAILABLE_IN_1_18 +void clutter_canvas_set_scale_factor (ClutterCanvas *canvas, + int scale); +CLUTTER_AVAILABLE_IN_1_18 +int clutter_canvas_get_scale_factor (ClutterCanvas *canvas); + +G_END_DECLS + +#endif /* __CLUTTER_CANVAS_H__ */ diff --git a/clutter/clutter/clutter-child-meta.c b/clutter/clutter/clutter-child-meta.c new file mode 100644 index 0000000..4267090 --- /dev/null +++ b/clutter/clutter/clutter-child-meta.c @@ -0,0 +1,192 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * Jorn Baayen + * Emmanuele Bassi + * Tomas Frydrych + * Øyvind KolÃ¥s + * + * Copyright (C) 2008 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +/** + * SECTION:clutter-child-meta + * @short_description: Wrapper for actors inside a container + * + * #ClutterChildMeta is a wrapper object created by #ClutterContainer + * implementations in order to store child-specific data and properties. + * + * A #ClutterChildMeta wraps a #ClutterActor inside a #ClutterContainer. + * + * #ClutterChildMeta is available since Clutter 0.8 + */ +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-child-meta.h" +#include "clutter-container.h" +#include "clutter-debug.h" +#include "clutter-private.h" + +G_DEFINE_ABSTRACT_TYPE (ClutterChildMeta, clutter_child_meta, G_TYPE_OBJECT); + +enum +{ + PROP_0, + + PROP_CONTAINER, + PROP_ACTOR, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +static void +clutter_child_meta_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterChildMeta *child_meta = CLUTTER_CHILD_META (object); + + switch (prop_id) + { + case PROP_CONTAINER: + child_meta->container = g_value_get_object (value); + break; + + case PROP_ACTOR: + child_meta->actor = g_value_get_object (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_child_meta_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterChildMeta *child_meta = CLUTTER_CHILD_META (object); + + switch (prop_id) + { + case PROP_CONTAINER: + g_value_set_object (value, child_meta->container); + break; + + case PROP_ACTOR: + g_value_set_object (value, child_meta->actor); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_child_meta_class_init (ClutterChildMetaClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = clutter_child_meta_set_property; + gobject_class->get_property = clutter_child_meta_get_property; + + /** + * ClutterChildMeta:container: + * + * The #ClutterContainer that created this #ClutterChildMeta. + * + * Since: 0.8 + */ + obj_props[PROP_CONTAINER] = + g_param_spec_object ("container", + P_("Container"), + P_("The container that created this data"), + CLUTTER_TYPE_CONTAINER, + G_PARAM_CONSTRUCT_ONLY | + CLUTTER_PARAM_READWRITE); + + /** + * ClutterChildMeta:actor: + * + * The #ClutterActor being wrapped by this #ClutterChildMeta + * + * Since: 0.8 + */ + obj_props[PROP_ACTOR] = + g_param_spec_object ("actor", + P_("Actor"), + P_("The actor wrapped by this data"), + CLUTTER_TYPE_ACTOR, + G_PARAM_CONSTRUCT_ONLY | + CLUTTER_PARAM_READWRITE); + + g_object_class_install_properties (gobject_class, + PROP_LAST, + obj_props); +} + +static void +clutter_child_meta_init (ClutterChildMeta *self) +{ +} + +/** + * clutter_child_meta_get_container: + * @data: a #ClutterChildMeta + * + * Retrieves the container using @data + * + * Return value: (transfer none): a #ClutterContainer + * + * Since: 0.8 + */ +ClutterContainer * +clutter_child_meta_get_container (ClutterChildMeta *data) +{ + g_return_val_if_fail (CLUTTER_IS_CHILD_META (data), NULL); + + return data->container; +} + +/** + * clutter_child_meta_get_actor: + * @data: a #ClutterChildMeta + * + * Retrieves the actor wrapped by @data + * + * Return value: (transfer none): a #ClutterActor + * + * Since: 0.8 + */ +ClutterActor * +clutter_child_meta_get_actor (ClutterChildMeta *data) +{ + g_return_val_if_fail (CLUTTER_IS_CHILD_META (data), NULL); + + return data->actor; +} diff --git a/clutter/clutter/clutter-child-meta.h b/clutter/clutter/clutter-child-meta.h new file mode 100644 index 0000000..02d9e9a --- /dev/null +++ b/clutter/clutter/clutter-child-meta.h @@ -0,0 +1,122 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * Jorn Baayen + * Emmanuele Bassi + * Tomas Frydrych + * Øyvind KolÃ¥s + * + * Copyright (C) 2008 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __CLUTTER_CHILD_META_H__ +#define __CLUTTER_CHILD_META_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_CHILD_META (clutter_child_meta_get_type ()) +#define CLUTTER_CHILD_META(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_CHILD_META, ClutterChildMeta)) +#define CLUTTER_CHILD_META_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_CHILD_META, ClutterChildMetaClass)) +#define CLUTTER_IS_CHILD_META(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_CHILD_META)) +#define CLUTTER_IS_CHILD_META_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_CHILD_META)) +#define CLUTTER_CHILD_META_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_CHILD_META, ClutterChildMetaClass)) + +typedef struct _ClutterChildMetaClass ClutterChildMetaClass; + +/** + * ClutterChildMeta: + * @container: the container handling this data + * @actor: the actor wrapped by this data + * + * Base interface for container specific state for child actors. A child + * data is meant to be used when you need to keep track of information + * about each individual child added to a container. + * + * In order to use it you should create your own subclass of + * #ClutterChildMeta and set the #ClutterContainerIface child_meta_type + * interface member to your subclass type, like: + * + * |[ + * static void + * my_container_iface_init (ClutterContainerIface *iface) + * { + * // set the rest of the #ClutterContainer vtable + * + * container_iface->child_meta_type = MY_TYPE_CHILD_META; + * } + * ]| + * + * This will automatically create a #ClutterChildMeta of type + * `MY_TYPE_CHILD_META` for every actor that is added to the container. + * + * The child data for an actor can be retrieved using the + * clutter_container_get_child_meta() function. + * + * The properties of the data and your subclass can be manipulated with + * clutter_container_child_set() and clutter_container_child_get() which + * act like g_object_set() and g_object_get(). + * + * You can provide hooks for your own storage as well as control the + * instantiation by overriding the #ClutterContainerIface virtual functions + * #ClutterContainerIface.create_child_meta(), #ClutterContainerIface.destroy_child_meta(), + * and #ClutterContainerIface.get_child_meta(). + * + * Since: 0.8 + */ +struct _ClutterChildMeta +{ + /*< private >*/ + GObject parent_instance; + + /*< public >*/ + ClutterContainer *container; + ClutterActor *actor; +}; + +/** + * ClutterChildMetaClass: + * + * The #ClutterChildMetaClass contains only private data + * + * Since: 0.8 + */ +struct _ClutterChildMetaClass +{ + /*< private >*/ + GObjectClass parent_class; +}; + +CLUTTER_AVAILABLE_IN_ALL +GType clutter_child_meta_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_ALL +ClutterContainer * clutter_child_meta_get_container (ClutterChildMeta *data); +CLUTTER_AVAILABLE_IN_ALL +ClutterActor * clutter_child_meta_get_actor (ClutterChildMeta *data); + +G_END_DECLS + +#endif /* __CLUTTER_CHILD_META_H__ */ diff --git a/clutter/clutter/clutter-click-action.c b/clutter/clutter/clutter-click-action.c new file mode 100644 index 0000000..c10eec2 --- /dev/null +++ b/clutter/clutter/clutter-click-action.c @@ -0,0 +1,831 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-click-action + * @Title: ClutterClickAction + * @Short_Description: Action for clickable actors + * + * #ClutterClickAction is a sub-class of #ClutterAction that implements + * the logic for clickable actors, by using the low level events of + * #ClutterActor, such as #ClutterActor::button-press-event and + * #ClutterActor::button-release-event, to synthesize the high level + * #ClutterClickAction::clicked signal. + * + * To use #ClutterClickAction you just need to apply it to a #ClutterActor + * using clutter_actor_add_action() and connect to the + * #ClutterClickAction::clicked signal: + * + * |[ + * ClutterAction *action = clutter_click_action_new (); + * + * clutter_actor_add_action (actor, action); + * + * g_signal_connect (action, "clicked", G_CALLBACK (on_clicked), NULL); + * ]| + * + * #ClutterClickAction also supports long press gestures: a long press is + * activated if the pointer remains pressed within a certain threshold (as + * defined by the #ClutterClickAction:long-press-threshold property) for a + * minimum amount of time (as the defined by the + * #ClutterClickAction:long-press-duration property). + * The #ClutterClickAction::long-press signal is emitted multiple times, + * using different #ClutterLongPressState values; to handle long presses + * you should connect to the #ClutterClickAction::long-press signal and + * handle the different states: + * + * |[ + * static gboolean + * on_long_press (ClutterClickAction *action, + * ClutterActor *actor, + * ClutterLongPressState state) + * { + * switch (state) + * { + * case CLUTTER_LONG_PRESS_QUERY: + * /* return TRUE if the actor should support long press + * * gestures, and FALSE otherwise; this state will be + * * emitted on button presses + * */ + * return TRUE; + * + * case CLUTTER_LONG_PRESS_ACTIVATE: + * /* this state is emitted if the minimum duration has + * * been reached without the gesture being cancelled. + * * the return value is not used + * */ + * return TRUE; + * + * case CLUTTER_LONG_PRESS_CANCEL: + * /* this state is emitted if the long press was cancelled; + * * for instance, the pointer went outside the actor or the + * * allowed threshold, or the button was released before + * * the minimum duration was reached. the return value is + * * not used + * */ + * return FALSE; + * } + * } + * ]| + * + * #ClutterClickAction is available since Clutter 1.4 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-click-action.h" + +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-marshal.h" +#include "clutter-private.h" + +struct _ClutterClickActionPrivate +{ + ClutterActor *stage; + + guint event_id; + guint capture_id; + guint long_press_id; + + gint long_press_threshold; + gint long_press_duration; + gint drag_threshold; + + guint press_button; + gint press_device_id; + ClutterEventSequence *press_sequence; + ClutterModifierType modifier_state; + gfloat press_x; + gfloat press_y; + + guint is_held : 1; + guint is_pressed : 1; +}; + +enum +{ + PROP_0, + + PROP_HELD, + PROP_PRESSED, + PROP_LONG_PRESS_THRESHOLD, + PROP_LONG_PRESS_DURATION, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST] = { NULL, }; + +enum +{ + CLICKED, + LONG_PRESS, + + LAST_SIGNAL +}; + +static guint click_signals[LAST_SIGNAL] = { 0, }; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterClickAction, clutter_click_action, CLUTTER_TYPE_ACTION) + +/* forward declaration */ +static gboolean on_captured_event (ClutterActor *stage, + ClutterEvent *event, + ClutterClickAction *action); + +static inline void +click_action_set_pressed (ClutterClickAction *action, + gboolean is_pressed) +{ + ClutterClickActionPrivate *priv = action->priv; + + is_pressed = !!is_pressed; + + if (priv->is_pressed == is_pressed) + return; + + priv->is_pressed = is_pressed; + g_object_notify_by_pspec (G_OBJECT (action), obj_props[PROP_PRESSED]); +} + +static inline void +click_action_set_held (ClutterClickAction *action, + gboolean is_held) +{ + ClutterClickActionPrivate *priv = action->priv; + + is_held = !!is_held; + + if (priv->is_held == is_held) + return; + + priv->is_held = is_held; + g_object_notify_by_pspec (G_OBJECT (action), obj_props[PROP_HELD]); +} + +static gboolean +click_action_emit_long_press (gpointer data) +{ + ClutterClickAction *action = data; + ClutterClickActionPrivate *priv = action->priv; + ClutterActor *actor; + gboolean result; + + priv->long_press_id = 0; + + actor = clutter_actor_meta_get_actor (data); + + g_signal_emit (action, click_signals[LONG_PRESS], 0, + actor, + CLUTTER_LONG_PRESS_ACTIVATE, + &result); + + if (priv->capture_id != 0) + { + g_signal_handler_disconnect (priv->stage, priv->capture_id); + priv->capture_id = 0; + } + + click_action_set_pressed (action, FALSE); + click_action_set_held (action, FALSE); + + return FALSE; +} + +static inline void +click_action_query_long_press (ClutterClickAction *action) +{ + ClutterClickActionPrivate *priv = action->priv; + ClutterActor *actor; + gboolean result = FALSE; + gint timeout; + + if (priv->long_press_duration < 0) + { + ClutterSettings *settings = clutter_settings_get_default (); + + g_object_get (settings, + "long-press-duration", &timeout, + NULL); + } + else + timeout = priv->long_press_duration; + + actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action)); + + g_signal_emit (action, click_signals[LONG_PRESS], 0, + actor, + CLUTTER_LONG_PRESS_QUERY, + &result); + + if (result) + { + priv->long_press_id = + clutter_threads_add_timeout (timeout, + click_action_emit_long_press, + action); + } +} + +static inline void +click_action_cancel_long_press (ClutterClickAction *action) +{ + ClutterClickActionPrivate *priv = action->priv; + + if (priv->long_press_id != 0) + { + ClutterActor *actor; + gboolean result; + + actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action)); + + g_source_remove (priv->long_press_id); + priv->long_press_id = 0; + + g_signal_emit (action, click_signals[LONG_PRESS], 0, + actor, + CLUTTER_LONG_PRESS_CANCEL, + &result); + } +} + +static gboolean +on_event (ClutterActor *actor, + ClutterEvent *event, + ClutterClickAction *action) +{ + ClutterClickActionPrivate *priv = action->priv; + gboolean has_button = TRUE; + + if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (action))) + return CLUTTER_EVENT_PROPAGATE; + + switch (clutter_event_type (event)) + { + case CLUTTER_TOUCH_BEGIN: + has_button = FALSE; + case CLUTTER_BUTTON_PRESS: + if (has_button && clutter_event_get_click_count (event) != 1) + return CLUTTER_EVENT_PROPAGATE; + + if (priv->is_held) + return CLUTTER_EVENT_STOP; + + if (!clutter_actor_contains (actor, clutter_event_get_source (event))) + return CLUTTER_EVENT_PROPAGATE; + + priv->press_button = has_button ? clutter_event_get_button (event) : 0; + priv->press_device_id = clutter_event_get_device_id (event); + priv->press_sequence = clutter_event_get_event_sequence (event); + priv->modifier_state = clutter_event_get_state (event); + clutter_event_get_coords (event, &priv->press_x, &priv->press_y); + + if (priv->long_press_threshold < 0) + { + ClutterSettings *settings = clutter_settings_get_default (); + + g_object_get (settings, + "dnd-drag-threshold", &priv->drag_threshold, + NULL); + } + else + priv->drag_threshold = priv->long_press_threshold; + + if (priv->stage == NULL) + priv->stage = clutter_actor_get_stage (actor); + + priv->capture_id = g_signal_connect_after (priv->stage, "captured-event", + G_CALLBACK (on_captured_event), + action); + + click_action_set_pressed (action, TRUE); + click_action_set_held (action, TRUE); + click_action_query_long_press (action); + break; + + case CLUTTER_ENTER: + click_action_set_pressed (action, priv->is_held); + break; + + case CLUTTER_LEAVE: + click_action_set_pressed (action, priv->is_held); + click_action_cancel_long_press (action); + break; + + default: + break; + } + + return CLUTTER_EVENT_PROPAGATE; +} + +static gboolean +on_captured_event (ClutterActor *stage, + ClutterEvent *event, + ClutterClickAction *action) +{ + ClutterClickActionPrivate *priv = action->priv; + ClutterActor *actor; + ClutterModifierType modifier_state; + gboolean has_button = TRUE; + + actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action)); + + switch (clutter_event_type (event)) + { + case CLUTTER_TOUCH_END: + has_button = FALSE; + case CLUTTER_BUTTON_RELEASE: + if (!priv->is_held) + return CLUTTER_EVENT_STOP; + + if ((has_button && clutter_event_get_button (event) != priv->press_button) || + (has_button && clutter_event_get_click_count (event) != 1) || + clutter_event_get_device_id (event) != priv->press_device_id || + clutter_event_get_event_sequence (event) != priv->press_sequence) + return CLUTTER_EVENT_PROPAGATE; + + click_action_set_held (action, FALSE); + click_action_cancel_long_press (action); + + /* disconnect the capture */ + if (priv->capture_id != 0) + { + g_signal_handler_disconnect (priv->stage, priv->capture_id); + priv->capture_id = 0; + } + + if (priv->long_press_id != 0) + { + g_source_remove (priv->long_press_id); + priv->long_press_id = 0; + } + + if (!clutter_actor_contains (actor, clutter_event_get_source (event))) + return CLUTTER_EVENT_PROPAGATE; + + /* exclude any button-mask so that we can compare + * the press and release states properly */ + modifier_state = clutter_event_get_state (event) & + ~(CLUTTER_BUTTON1_MASK | + CLUTTER_BUTTON2_MASK | + CLUTTER_BUTTON3_MASK | + CLUTTER_BUTTON4_MASK | + CLUTTER_BUTTON5_MASK); + + /* if press and release states don't match we + * simply ignore modifier keys. i.e. modifier keys + * are expected to be pressed throughout the whole + * click */ + if (modifier_state != priv->modifier_state) + priv->modifier_state = 0; + + click_action_set_pressed (action, FALSE); + g_signal_emit (action, click_signals[CLICKED], 0, actor); + break; + + case CLUTTER_MOTION: + case CLUTTER_TOUCH_UPDATE: + { + gfloat motion_x, motion_y; + gfloat delta_x, delta_y; + + if (clutter_event_get_device_id (event) != priv->press_device_id || + clutter_event_get_event_sequence (event) != priv->press_sequence) + return CLUTTER_EVENT_PROPAGATE; + + if (!priv->is_held) + return CLUTTER_EVENT_PROPAGATE; + + clutter_event_get_coords (event, &motion_x, &motion_y); + + delta_x = ABS (motion_x - priv->press_x); + delta_y = ABS (motion_y - priv->press_y); + + if (delta_x > priv->drag_threshold || + delta_y > priv->drag_threshold) + click_action_cancel_long_press (action); + } + break; + + default: + break; + } + + return CLUTTER_EVENT_STOP; +} + +static void +clutter_click_action_set_actor (ClutterActorMeta *meta, + ClutterActor *actor) +{ + ClutterClickAction *action = CLUTTER_CLICK_ACTION (meta); + ClutterClickActionPrivate *priv = action->priv; + + if (priv->event_id != 0) + { + ClutterActor *old_actor = clutter_actor_meta_get_actor (meta); + + if (old_actor != NULL) + g_signal_handler_disconnect (old_actor, priv->event_id); + + priv->event_id = 0; + } + + if (priv->capture_id != 0) + { + if (priv->stage != NULL) + g_signal_handler_disconnect (priv->stage, priv->capture_id); + + priv->capture_id = 0; + priv->stage = NULL; + } + + if (priv->long_press_id != 0) + { + g_source_remove (priv->long_press_id); + priv->long_press_id = 0; + } + + click_action_set_pressed (action, FALSE); + click_action_set_held (action, FALSE); + + if (actor != NULL) + priv->event_id = g_signal_connect (actor, "event", + G_CALLBACK (on_event), + action); + + CLUTTER_ACTOR_META_CLASS (clutter_click_action_parent_class)->set_actor (meta, actor); +} + +static void +clutter_click_action_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterClickActionPrivate *priv = CLUTTER_CLICK_ACTION (gobject)->priv; + + switch (prop_id) + { + case PROP_LONG_PRESS_DURATION: + priv->long_press_duration = g_value_get_int (value); + break; + + case PROP_LONG_PRESS_THRESHOLD: + priv->long_press_threshold = g_value_get_int (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_click_action_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterClickActionPrivate *priv = CLUTTER_CLICK_ACTION (gobject)->priv; + + switch (prop_id) + { + case PROP_HELD: + g_value_set_boolean (value, priv->is_held); + break; + + case PROP_PRESSED: + g_value_set_boolean (value, priv->is_pressed); + break; + + case PROP_LONG_PRESS_DURATION: + g_value_set_int (value, priv->long_press_duration); + break; + + case PROP_LONG_PRESS_THRESHOLD: + g_value_set_int (value, priv->long_press_threshold); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_click_action_dispose (GObject *gobject) +{ + ClutterClickActionPrivate *priv = CLUTTER_CLICK_ACTION (gobject)->priv; + + if (priv->event_id) + { + g_signal_handler_disconnect (clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (gobject)), + priv->event_id); + priv->event_id = 0; + } + + if (priv->capture_id) + { + g_signal_handler_disconnect (priv->stage, priv->capture_id); + priv->capture_id = 0; + } + + if (priv->long_press_id) + { + g_source_remove (priv->long_press_id); + priv->long_press_id = 0; + } + + G_OBJECT_CLASS (clutter_click_action_parent_class)->dispose (gobject); +} + + +static void +clutter_click_action_class_init (ClutterClickActionClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass); + + meta_class->set_actor = clutter_click_action_set_actor; + + gobject_class->dispose = clutter_click_action_dispose; + gobject_class->set_property = clutter_click_action_set_property; + gobject_class->get_property = clutter_click_action_get_property; + + /** + * ClutterClickAction:pressed: + * + * Whether the clickable actor should be in "pressed" state + * + * Since: 1.4 + */ + obj_props[PROP_PRESSED] = + g_param_spec_boolean ("pressed", + P_("Pressed"), + P_("Whether the clickable should be in pressed state"), + FALSE, + CLUTTER_PARAM_READABLE); + + /** + * ClutterClickAction:held: + * + * Whether the clickable actor has the pointer grabbed + * + * Since: 1.4 + */ + obj_props[PROP_HELD] = + g_param_spec_boolean ("held", + P_("Held"), + P_("Whether the clickable has a grab"), + FALSE, + CLUTTER_PARAM_READABLE); + + /** + * ClutterClickAction:long-press-duration: + * + * The minimum duration of a press for it to be recognized as a long + * press gesture, in milliseconds. + * + * A value of -1 will make the #ClutterClickAction use the value of + * the #ClutterSettings:long-press-duration property. + * + * Since: 1.8 + */ + obj_props[PROP_LONG_PRESS_DURATION] = + g_param_spec_int ("long-press-duration", + P_("Long Press Duration"), + P_("The minimum duration of a long press to recognize the gesture"), + -1, G_MAXINT, + -1, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterClickAction:long-press-threshold: + * + * The maximum allowed distance that can be covered (on both axes) before + * a long press gesture is cancelled, in pixels. + * + * A value of -1 will make the #ClutterClickAction use the value of + * the #ClutterSettings:dnd-drag-threshold property. + * + * Since: 1.8 + */ + obj_props[PROP_LONG_PRESS_THRESHOLD] = + g_param_spec_int ("long-press-threshold", + P_("Long Press Threshold"), + P_("The maximum threshold before a long press is cancelled"), + -1, G_MAXINT, + -1, + CLUTTER_PARAM_READWRITE); + + g_object_class_install_properties (gobject_class, + PROP_LAST, + obj_props); + + /** + * ClutterClickAction::clicked: + * @action: the #ClutterClickAction that emitted the signal + * @actor: the #ClutterActor attached to the @action + * + * The ::clicked signal is emitted when the #ClutterActor to which + * a #ClutterClickAction has been applied should respond to a + * pointer button press and release events + * + * Since: 1.4 + */ + click_signals[CLICKED] = + g_signal_new (I_("clicked"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterClickActionClass, clicked), + NULL, NULL, + _clutter_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CLUTTER_TYPE_ACTOR); + + /** + * ClutterClickAction::long-press: + * @action: the #ClutterClickAction that emitted the signal + * @actor: the #ClutterActor attached to the @action + * @state: the long press state + * + * The ::long-press signal is emitted during the long press gesture + * handling. + * + * This signal can be emitted multiple times with different states. + * + * The %CLUTTER_LONG_PRESS_QUERY state will be emitted on button presses, + * and its return value will determine whether the long press handling + * should be initiated. If the signal handlers will return %TRUE, the + * %CLUTTER_LONG_PRESS_QUERY state will be followed either by a signal + * emission with the %CLUTTER_LONG_PRESS_ACTIVATE state if the long press + * constraints were respected, or by a signal emission with the + * %CLUTTER_LONG_PRESS_CANCEL state if the long press was cancelled. + * + * It is possible to forcibly cancel a long press detection using + * clutter_click_action_release(). + * + * Return value: Only the %CLUTTER_LONG_PRESS_QUERY state uses the + * returned value of the handler; other states will ignore it + * + * Since: 1.8 + */ + click_signals[LONG_PRESS] = + g_signal_new (I_("long-press"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterClickActionClass, long_press), + NULL, NULL, + _clutter_marshal_BOOLEAN__OBJECT_ENUM, + G_TYPE_BOOLEAN, 2, + CLUTTER_TYPE_ACTOR, + CLUTTER_TYPE_LONG_PRESS_STATE); +} + +static void +clutter_click_action_init (ClutterClickAction *self) +{ + self->priv = clutter_click_action_get_instance_private (self); + self->priv->long_press_threshold = -1; + self->priv->long_press_duration = -1; +} + +/** + * clutter_click_action_new: + * + * Creates a new #ClutterClickAction instance + * + * Return value: the newly created #ClutterClickAction + * + * Since: 1.4 + */ +ClutterAction * +clutter_click_action_new (void) +{ + return g_object_new (CLUTTER_TYPE_CLICK_ACTION, NULL); +} + +/** + * clutter_click_action_release: + * @action: a #ClutterClickAction + * + * Emulates a release of the pointer button, which ungrabs the pointer + * and unsets the #ClutterClickAction:pressed state. + * + * This function will also cancel the long press gesture if one was + * initiated. + * + * This function is useful to break a grab, for instance after a certain + * amount of time has passed. + * + * Since: 1.4 + */ +void +clutter_click_action_release (ClutterClickAction *action) +{ + ClutterClickActionPrivate *priv; + + g_return_if_fail (CLUTTER_IS_CLICK_ACTION (action)); + + priv = action->priv; + + if (!priv->is_held) + return; + + /* disconnect the capture */ + if (priv->capture_id != 0) + { + g_signal_handler_disconnect (priv->stage, priv->capture_id); + priv->capture_id = 0; + } + + click_action_cancel_long_press (action); + click_action_set_held (action, FALSE); + click_action_set_pressed (action, FALSE); +} + +/** + * clutter_click_action_get_button: + * @action: a #ClutterClickAction + * + * Retrieves the button that was pressed. + * + * Return value: the button value + * + * Since: 1.4 + */ +guint +clutter_click_action_get_button (ClutterClickAction *action) +{ + g_return_val_if_fail (CLUTTER_IS_CLICK_ACTION (action), 0); + + return action->priv->press_button; +} + +/** + * clutter_click_action_get_state: + * @action: a #ClutterClickAction + * + * Retrieves the modifier state of the click action. + * + * Return value: the modifier state parameter, or 0 + * + * Since: 1.6 + */ +ClutterModifierType +clutter_click_action_get_state (ClutterClickAction *action) +{ + g_return_val_if_fail (CLUTTER_IS_CLICK_ACTION (action), 0); + + return action->priv->modifier_state; +} + +/** + * clutter_click_action_get_coords: + * @action: a #ClutterClickAction + * @press_x: (out): return location for the X coordinate, or %NULL + * @press_y: (out): return location for the Y coordinate, or %NULL + * + * Retrieves the screen coordinates of the button press. + * + * Since: 1.8 + */ +void +clutter_click_action_get_coords (ClutterClickAction *action, + gfloat *press_x, + gfloat *press_y) +{ + g_return_if_fail (CLUTTER_IS_ACTION (action)); + + if (press_x != NULL) + *press_x = action->priv->press_x; + + if (press_y != NULL) + *press_y = action->priv->press_y; +} diff --git a/clutter/clutter/clutter-click-action.h b/clutter/clutter/clutter-click-action.h new file mode 100644 index 0000000..942efd0 --- /dev/null +++ b/clutter/clutter/clutter-click-action.h @@ -0,0 +1,120 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + * + * Inspired by the StClickable class in GNOME Shell, written by: + * Colin Walters + */ + +#ifndef __CLUTTER_CLICK_ACTION_H__ +#define __CLUTTER_CLICK_ACTION_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_CLICK_ACTION (clutter_click_action_get_type ()) +#define CLUTTER_CLICK_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_CLICK_ACTION, ClutterClickAction)) +#define CLUTTER_IS_CLICK_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_CLICK_ACTION)) +#define CLUTTER_CLICK_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_CLICK_ACTION, ClutterClickActionClass)) +#define CLUTTER_IS_CLICK_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_CLICK_ACTION)) +#define CLUTTER_CLICK_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_CLICK_ACTION, ClutterClickActionClass)) + +typedef struct _ClutterClickAction ClutterClickAction; +typedef struct _ClutterClickActionPrivate ClutterClickActionPrivate; +typedef struct _ClutterClickActionClass ClutterClickActionClass; + +/** + * ClutterClickAction: + * + * The #ClutterClickAction structure contains + * only private data and should be accessed using the provided API + * + * Since: 1.4 + */ +struct _ClutterClickAction +{ + /*< private >*/ + ClutterAction parent_instance; + + ClutterClickActionPrivate *priv; +}; + +/** + * ClutterClickActionClass: + * @clicked: class handler for the #ClutterClickAction::clicked signal + * @long_press: class handler for the #ClutterClickAction::long-press signal + * + * The #ClutterClickActionClass structure + * contains only private data + * + * Since: 1.4 + */ +struct _ClutterClickActionClass +{ + /*< private >*/ + ClutterActionClass parent_class; + + /*< public >*/ + void (* clicked) (ClutterClickAction *action, + ClutterActor *actor); + + gboolean (* long_press) (ClutterClickAction *action, + ClutterActor *actor, + ClutterLongPressState state); + + /*< private >*/ + void (* _clutter_click_action1) (void); + void (* _clutter_click_action2) (void); + void (* _clutter_click_action3) (void); + void (* _clutter_click_action4) (void); + void (* _clutter_click_action5) (void); + void (* _clutter_click_action6) (void); + void (* _clutter_click_action7) (void); +}; + +CLUTTER_AVAILABLE_IN_1_4 +GType clutter_click_action_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_4 +ClutterAction * clutter_click_action_new (void); + +CLUTTER_AVAILABLE_IN_1_4 +guint clutter_click_action_get_button (ClutterClickAction *action); +CLUTTER_AVAILABLE_IN_1_4 +ClutterModifierType clutter_click_action_get_state (ClutterClickAction *action); +CLUTTER_AVAILABLE_IN_1_8 +void clutter_click_action_get_coords (ClutterClickAction *action, + gfloat *press_x, + gfloat *press_y); + +CLUTTER_AVAILABLE_IN_1_4 +void clutter_click_action_release (ClutterClickAction *action); + +G_END_DECLS + +#endif /* __CLUTTER_CLICK_ACTION_H__ */ diff --git a/clutter/clutter/clutter-clone.c b/clutter/clutter/clutter-clone.c new file mode 100644 index 0000000..af03a4e --- /dev/null +++ b/clutter/clutter/clutter-clone.c @@ -0,0 +1,442 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2008 Intel Corporation. + * + * Authored By: Robert Bragg + * + * 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 . + */ + +/** + * SECTION:clutter-clone + * @short_description: An actor that displays a clone of a source actor + * + * #ClutterClone is a #ClutterActor which draws with the paint + * function of another actor, scaled to fit its own allocation. + * + * #ClutterClone can be used to efficiently clone any other actor. + * + * Unlike clutter_texture_new_from_actor(), #ClutterClone does not require + * the presence of support for FBOs in the underlying GL or GLES + * implementation. + * + * #ClutterClone is available since Clutter 1.0 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#define CLUTTER_ENABLE_EXPERIMENTAL_API +#include "clutter-actor-private.h" +#include "clutter-clone.h" +#include "clutter-debug.h" +#include "clutter-main.h" +#include "clutter-paint-volume-private.h" +#include "clutter-private.h" + +#include "cogl/cogl.h" + +struct _ClutterClonePrivate +{ + ClutterActor *clone_source; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterClone, clutter_clone, CLUTTER_TYPE_ACTOR) + +enum +{ + PROP_0, + + PROP_SOURCE, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +static void clutter_clone_set_source_internal (ClutterClone *clone, + ClutterActor *source); +static void +clutter_clone_get_preferred_width (ClutterActor *self, + gfloat for_height, + gfloat *min_width_p, + gfloat *natural_width_p) +{ + ClutterClonePrivate *priv = CLUTTER_CLONE (self)->priv; + ClutterActor *clone_source = priv->clone_source; + + if (clone_source == NULL) + { + if (min_width_p) + *min_width_p = 0; + + if (natural_width_p) + *natural_width_p = 0; + } + else + clutter_actor_get_preferred_width (clone_source, + for_height, + min_width_p, + natural_width_p); +} + +static void +clutter_clone_get_preferred_height (ClutterActor *self, + gfloat for_width, + gfloat *min_height_p, + gfloat *natural_height_p) +{ + ClutterClonePrivate *priv = CLUTTER_CLONE (self)->priv; + ClutterActor *clone_source = priv->clone_source; + + if (clone_source == NULL) + { + if (min_height_p) + *min_height_p = 0; + + if (natural_height_p) + *natural_height_p = 0; + } + else + clutter_actor_get_preferred_height (clone_source, + for_width, + min_height_p, + natural_height_p); +} + +static void +clutter_clone_apply_transform (ClutterActor *self, CoglMatrix *matrix) +{ + ClutterClonePrivate *priv = CLUTTER_CLONE (self)->priv; + ClutterActorBox box, source_box; + gfloat x_scale, y_scale; + + /* First chain up and apply all the standard ClutterActor + * transformations... */ + CLUTTER_ACTOR_CLASS (clutter_clone_parent_class)->apply_transform (self, + matrix); + + /* if we don't have a source, nothing else to do */ + if (priv->clone_source == NULL) + return; + + /* get our allocated size */ + clutter_actor_get_allocation_box (self, &box); + + /* and get the allocated size of the source */ + clutter_actor_get_allocation_box (priv->clone_source, &source_box); + + /* We need to scale what the clone-source actor paints to fill our own + * allocation... + */ + x_scale = clutter_actor_box_get_width (&box) + / clutter_actor_box_get_width (&source_box); + y_scale = clutter_actor_box_get_height (&box) + / clutter_actor_box_get_height (&source_box); + + cogl_matrix_scale (matrix, x_scale, y_scale, x_scale); +} + +static void +clutter_clone_paint (ClutterActor *actor) +{ + ClutterClone *self = CLUTTER_CLONE (actor); + ClutterClonePrivate *priv = self->priv; + gboolean was_unmapped = FALSE; + + if (priv->clone_source == NULL) + return; + + CLUTTER_NOTE (PAINT, "painting clone actor '%s'", + _clutter_actor_get_debug_name (actor)); + + /* The final bits of magic: + * - We need to override the paint opacity of the actor with our own + * opacity. + * - We need to inform the actor that it's in a clone paint (for the function + * clutter_actor_is_in_clone_paint()) + * - We need to stop clutter_actor_paint applying the model view matrix of + * the clone source actor. + */ + _clutter_actor_set_in_clone_paint (priv->clone_source, TRUE); + clutter_actor_set_opacity_override (priv->clone_source, + clutter_actor_get_paint_opacity (actor)); + _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; + } + + /* If the source isn't ultimately parented to a toplevel, it can't be + * realized or painted. + */ + if (clutter_actor_is_realized (priv->clone_source)) + { + _clutter_actor_push_clone_paint (); + clutter_actor_paint (priv->clone_source); + _clutter_actor_pop_clone_paint (); + } + + 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_override (priv->clone_source, -1); + _clutter_actor_set_in_clone_paint (priv->clone_source, FALSE); +} + +static gboolean +clutter_clone_get_paint_volume (ClutterActor *actor, + ClutterPaintVolume *volume) +{ + ClutterClonePrivate *priv = CLUTTER_CLONE (actor)->priv; + const ClutterPaintVolume *source_volume; + + /* if the source is not set the paint volume is defined to be empty */ + if (priv->clone_source == NULL) + return TRUE; + + /* query the volume of the source actor and simply masquarade it as + * the clones volume... */ + source_volume = clutter_actor_get_paint_volume (priv->clone_source); + if (source_volume == NULL) + return FALSE; + + _clutter_paint_volume_set_from_volume (volume, source_volume); + _clutter_paint_volume_set_reference_actor (volume, actor); + + return TRUE; +} + +static gboolean +clutter_clone_has_overlaps (ClutterActor *actor) +{ + ClutterClonePrivate *priv = CLUTTER_CLONE (actor)->priv; + + /* The clone has overlaps iff the source has overlaps */ + + if (priv->clone_source == NULL) + return FALSE; + + return clutter_actor_has_overlaps (priv->clone_source); +} + +static void +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, flags); + + if (priv->clone_source == NULL) + return; + +#if 0 + /* XXX - this is wrong: ClutterClone cannot clone unparented + * actors, as it will break all invariants + */ + + /* we act like a "foster parent" for the source we are cloning; + * if the source has not been parented we have to force an + * allocation on it, so that we can paint it correctly from + * within our paint() implementation. since the actor does not + * have a parent, and thus it won't be painted by the usual + * 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, flags); +#endif +} + +static void +clutter_clone_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterClone *self = CLUTTER_CLONE (gobject); + + switch (prop_id) + { + case PROP_SOURCE: + clutter_clone_set_source (self, g_value_get_object (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_clone_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterClonePrivate *priv = CLUTTER_CLONE (gobject)->priv; + + switch (prop_id) + { + case PROP_SOURCE: + g_value_set_object (value, priv->clone_source); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_clone_dispose (GObject *gobject) +{ + clutter_clone_set_source_internal (CLUTTER_CLONE (gobject), NULL); + + G_OBJECT_CLASS (clutter_clone_parent_class)->dispose (gobject); +} + +static void +clutter_clone_class_init (ClutterCloneClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + + actor_class->apply_transform = clutter_clone_apply_transform; + actor_class->paint = clutter_clone_paint; + actor_class->get_paint_volume = clutter_clone_get_paint_volume; + actor_class->get_preferred_width = clutter_clone_get_preferred_width; + actor_class->get_preferred_height = clutter_clone_get_preferred_height; + actor_class->allocate = clutter_clone_allocate; + actor_class->has_overlaps = clutter_clone_has_overlaps; + + gobject_class->dispose = clutter_clone_dispose; + gobject_class->set_property = clutter_clone_set_property; + gobject_class->get_property = clutter_clone_get_property; + + /** + * ClutterClone:source: + * + * This property specifies the source actor being cloned. + * + * Since: 1.0 + */ + obj_props[PROP_SOURCE] = + g_param_spec_object ("source", + P_("Source"), + P_("Specifies the actor to be cloned"), + CLUTTER_TYPE_ACTOR, + G_PARAM_CONSTRUCT | + CLUTTER_PARAM_READWRITE); + + g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); +} + +static void +clutter_clone_init (ClutterClone *self) +{ + self->priv = clutter_clone_get_instance_private (self); +} + +/** + * clutter_clone_new: + * @source: a #ClutterActor, or %NULL + * + * Creates a new #ClutterActor which clones @source/ + * + * Return value: the newly created #ClutterClone + * + * Since: 1.0 + */ +ClutterActor * +clutter_clone_new (ClutterActor *source) +{ + return g_object_new (CLUTTER_TYPE_CLONE, "source", source, NULL); +} + +static void +clutter_clone_set_source_internal (ClutterClone *self, + ClutterActor *source) +{ + ClutterClonePrivate *priv = self->priv; + + if (priv->clone_source == source) + return; + + if (priv->clone_source != NULL) + { + _clutter_actor_detach_clone (priv->clone_source, CLUTTER_ACTOR (self)); + g_object_unref (priv->clone_source); + priv->clone_source = NULL; + } + + if (source != NULL) + { + priv->clone_source = g_object_ref (source); + _clutter_actor_attach_clone (priv->clone_source, CLUTTER_ACTOR (self)); + } + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SOURCE]); + + clutter_actor_queue_relayout (CLUTTER_ACTOR (self)); +} + +/** + * clutter_clone_set_source: + * @self: a #ClutterClone + * @source: (allow-none): a #ClutterActor, or %NULL + * + * Sets @source as the source actor to be cloned by @self. + * + * Since: 1.0 + */ +void +clutter_clone_set_source (ClutterClone *self, + ClutterActor *source) +{ + g_return_if_fail (CLUTTER_IS_CLONE (self)); + g_return_if_fail (source == NULL || CLUTTER_IS_ACTOR (source)); + + clutter_clone_set_source_internal (self, source); + clutter_actor_queue_relayout (CLUTTER_ACTOR (self)); +} + +/** + * clutter_clone_get_source: + * @self: a #ClutterClone + * + * Retrieves the source #ClutterActor being cloned by @self. + * + * Return value: (transfer none): the actor source for the clone + * + * Since: 1.0 + */ +ClutterActor * +clutter_clone_get_source (ClutterClone *self) +{ + g_return_val_if_fail (CLUTTER_IS_CLONE (self), NULL); + + return self->priv->clone_source; +} diff --git a/clutter/clutter/clutter-clone.h b/clutter/clutter/clutter-clone.h new file mode 100644 index 0000000..6cc503c --- /dev/null +++ b/clutter/clutter/clutter-clone.h @@ -0,0 +1,94 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2008 Intel Corporation. + * + * Authored By: Robert Bragg + * + * 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 . + */ + +#ifndef __CLUTTER_CLONE_H__ +#define __CLUTTER_CLONE_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_CLONE (clutter_clone_get_type()) +#define CLUTTER_CLONE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_CLONE, ClutterClone)) +#define CLUTTER_CLONE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_CLONE, ClutterCloneClass)) +#define CLUTTER_IS_CLONE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_CLONE)) +#define CLUTTER_IS_CLONE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_CLONE)) +#define CLUTTER_CLONE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_CLONE, ClutterCloneClass)) + +typedef struct _ClutterClone ClutterClone; +typedef struct _ClutterCloneClass ClutterCloneClass; +typedef struct _ClutterClonePrivate ClutterClonePrivate; + +/** + * ClutterClone: + * + * The #ClutterClone structure contains only private data + * and should be accessed using the provided API + * + * Since: 1.0 + */ +struct _ClutterClone +{ + /*< private >*/ + ClutterActor parent_instance; + + ClutterClonePrivate *priv; +}; + +/** + * ClutterCloneClass: + * + * The #ClutterCloneClass structure contains only private data + * + * Since: 1.0 + */ +struct _ClutterCloneClass +{ + /*< private >*/ + ClutterActorClass parent_class; + + /* padding for future expansion */ + void (*_clutter_actor_clone1) (void); + void (*_clutter_actor_clone2) (void); + void (*_clutter_actor_clone3) (void); + void (*_clutter_actor_clone4) (void); +}; + +CLUTTER_AVAILABLE_IN_1_0 +GType clutter_clone_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_0 +ClutterActor * clutter_clone_new (ClutterActor *source); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_clone_set_source (ClutterClone *self, + ClutterActor *source); +CLUTTER_AVAILABLE_IN_1_0 +ClutterActor * clutter_clone_get_source (ClutterClone *self); + +G_END_DECLS + +#endif /* __CLUTTER_CLONE_H__ */ diff --git a/clutter/clutter/clutter-color-static.h b/clutter/clutter/clutter-color-static.h new file mode 100644 index 0000000..766864c --- /dev/null +++ b/clutter/clutter/clutter-color-static.h @@ -0,0 +1,79 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __CLUTTER_COLOR_STATIC_H__ +#define __CLUTTER_COLOR_STATIC_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#define __CLUTTER_COLOR_SYM(x) (clutter_color_get_static (CLUTTER_COLOR_##x)) + +#define CLUTTER_COLOR_White (__CLUTTER_COLOR_SYM (WHITE)) +#define CLUTTER_COLOR_Black (__CLUTTER_COLOR_SYM (BLACK)) +#define CLUTTER_COLOR_Red (__CLUTTER_COLOR_SYM (RED)) +#define CLUTTER_COLOR_DarkRed (__CLUTTER_COLOR_SYM (DARK_RED)) +#define CLUTTER_COLOR_Green (__CLUTTER_COLOR_SYM (GREEN)) +#define CLUTTER_COLOR_DarkGreen (__CLUTTER_COLOR_SYM (DARK_GREEN)) +#define CLUTTER_COLOR_Blue (__CLUTTER_COLOR_SYM (BLUE)) +#define CLUTTER_COLOR_DarkBlue (__CLUTTER_COLOR_SYM (DARK_BLUE)) +#define CLUTTER_COLOR_Cyan (__CLUTTER_COLOR_SYM (CYAN)) +#define CLUTTER_COLOR_DarkCyan (__CLUTTER_COLOR_SYM (DARK_CYAN)) +#define CLUTTER_COLOR_Magenta (__CLUTTER_COLOR_SYM (MAGENTA)) +#define CLUTTER_COLOR_DarkMagenta (__CLUTTER_COLOR_SYM (DARK_MAGENTA)) +#define CLUTTER_COLOR_Yellow (__CLUTTER_COLOR_SYM (YELLOW)) +#define CLUTTER_COLOR_DarkYellow (__CLUTTER_COLOR_SYM (DARK_YELLOW)) +#define CLUTTER_COLOR_Gray (__CLUTTER_COLOR_SYM (GRAY)) +#define CLUTTER_COLOR_DarkGray (__CLUTTER_COLOR_SYM (DARK_GRAY)) +#define CLUTTER_COLOR_LightGray (__CLUTTER_COLOR_SYM (LIGHT_GRAY)) + +#define CLUTTER_COLOR_Butter (__CLUTTER_COLOR_SYM (BUTTER)) +#define CLUTTER_COLOR_LightButter (__CLUTTER_COLOR_SYM (BUTTER_LIGHT)) +#define CLUTTER_COLOR_DarkButter (__CLUTTER_COLOR_SYM (BUTTER_DARK)) +#define CLUTTER_COLOR_Orange (__CLUTTER_COLOR_SYM (ORANGE)) +#define CLUTTER_COLOR_LightOrange (__CLUTTER_COLOR_SYM (ORANGE_LIGHT)) +#define CLUTTER_COLOR_DarkOrange (__CLUTTER_COLOR_SYM (ORANGE_DARK)) +#define CLUTTER_COLOR_Chocolate (__CLUTTER_COLOR_SYM (CHOCOLATE)) +#define CLUTTER_COLOR_LightChocolate (__CLUTTER_COLOR_SYM (CHOCOLATE_LIGHT)) +#define CLUTTER_COLOR_DarkChocolate (__CLUTTER_COLOR_SYM (CHOCOLATE_DARK)) +#define CLUTTER_COLOR_Chameleon (__CLUTTER_COLOR_SYM (CHAMELEON)) +#define CLUTTER_COLOR_LightChameleon (__CLUTTER_COLOR_SYM (CHAMELEON_LIGHT)) +#define CLUTTER_COLOR_DarkChameleon (__CLUTTER_COLOR_SYM (CHAMELEON_DARK)) +#define CLUTTER_COLOR_SkyBlue (__CLUTTER_COLOR_SYM (SKY_BLUE)) +#define CLUTTER_COLOR_LightSkyBlue (__CLUTTER_COLOR_SYM (SKY_BLUE_LIGHT)) +#define CLUTTER_COLOR_DarkSkyBlue (__CLUTTER_COLOR_SYM (SKY_BLUE_DARK)) +#define CLUTTER_COLOR_Plum (__CLUTTER_COLOR_SYM (PLUM)) +#define CLUTTER_COLOR_LightPlum (__CLUTTER_COLOR_SYM (PLUM_LIGHT)) +#define CLUTTER_COLOR_DarkPlum (__CLUTTER_COLOR_SYM (PLUM_DARK)) +#define CLUTTER_COLOR_ScarletRed (__CLUTTER_COLOR_SYM (SCARLET_RED)) +#define CLUTTER_COLOR_LightScarletRed (__CLUTTER_COLOR_SYM (SCARLET_RED_LIGHT)) +#define CLUTTER_COLOR_DarkScarletRed (__CLUTTER_COLOR_SYM (SCARLET_RED_DARK)) +#define CLUTTER_COLOR_Aluminium1 (__CLUTTER_COLOR_SYM (ALUMINIUM_1)) +#define CLUTTER_COLOR_Aluminium2 (__CLUTTER_COLOR_SYM (ALUMINIUM_2)) +#define CLUTTER_COLOR_Aluminium3 (__CLUTTER_COLOR_SYM (ALUMINIUM_3)) +#define CLUTTER_COLOR_Aluminium4 (__CLUTTER_COLOR_SYM (ALUMINIUM_4)) +#define CLUTTER_COLOR_Aluminium5 (__CLUTTER_COLOR_SYM (ALUMINIUM_5)) +#define CLUTTER_COLOR_Aluminium6 (__CLUTTER_COLOR_SYM (ALUMINIUM_6)) + +#define CLUTTER_COLOR_Transparent (__CLUTTER_COLOR_SYM (TRANSPARENT)) + +#endif /* __CLUTTER_COLOR_STATIC_H__ */ diff --git a/clutter/clutter/clutter-color.c b/clutter/clutter/clutter-color.c new file mode 100644 index 0000000..83ae406 --- /dev/null +++ b/clutter/clutter/clutter-color.c @@ -0,0 +1,1195 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +/** + * SECTION:clutter-color + * @short_description: Color management and manipulation. + * + * #ClutterColor is a simple type for representing colors in Clutter. + * + * A #ClutterColor is expressed as a 4-tuple of values ranging from + * zero to 255, one for each color channel plus one for the alpha. + * + * The alpha channel is fully opaque at 255 and fully transparent at 0. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#include + +#include "clutter-interval.h" +#include "clutter-main.h" +#include "clutter-color.h" +#include "clutter-private.h" +#include "clutter-debug.h" + +/* XXX - keep in sync with the ClutterStaticColor enumeration order */ +static const ClutterColor const static_colors[] = { + /* CGA/EGA color palette */ + { 0xff, 0xff, 0xff, 0xff }, /* white */ + { 0x00, 0x00, 0x00, 0xff }, /* black */ + { 0xff, 0x00, 0x00, 0xff }, /* red */ + { 0x80, 0x00, 0x00, 0xff }, /* dark red */ + { 0x00, 0xff, 0x00, 0xff }, /* green */ + { 0x00, 0x80, 0x00, 0xff }, /* dark green */ + { 0x00, 0x00, 0xff, 0xff }, /* blue */ + { 0x00, 0x00, 0x80, 0xff }, /* dark blue */ + { 0x00, 0xff, 0xff, 0xff }, /* cyan */ + { 0x00, 0x80, 0x80, 0xff }, /* dark cyan */ + { 0xff, 0x00, 0xff, 0xff }, /* magenta */ + { 0x80, 0x00, 0x80, 0xff }, /* dark magenta */ + { 0xff, 0xff, 0x00, 0xff }, /* yellow */ + { 0x80, 0x80, 0x00, 0xff }, /* dark yellow */ + { 0xa0, 0xa0, 0xa4, 0xff }, /* gray */ + { 0x80, 0x80, 0x80, 0xff }, /* dark gray */ + { 0xc0, 0xc0, 0xc0, 0xff }, /* light gray */ + + /* Tango Icon color palette */ + { 0xed, 0xd4, 0x00, 0xff }, /* butter */ + { 0xfc, 0xe9, 0x4f, 0xff }, /* butter light */ + { 0xc4, 0xa0, 0x00, 0xff }, /* butter dark */ + { 0xf5, 0x79, 0x00, 0xff }, /* orange */ + { 0xfc, 0xaf, 0x3e, 0xff }, /* orange light */ + { 0xce, 0x5c, 0x00, 0xff }, /* orange dark */ + { 0xc1, 0x7d, 0x11, 0xff }, /* chocolate */ + { 0xe9, 0xb9, 0x6e, 0xff }, /* chocolate light */ + { 0x8f, 0x59, 0x02, 0xff }, /* chocolate dark */ + { 0x73, 0xd2, 0x16, 0xff }, /* chameleon */ + { 0x8a, 0xe2, 0x34, 0xff }, /* chameleon light */ + { 0x4e, 0x9a, 0x06, 0xff }, /* chameleon dark */ + { 0x34, 0x65, 0xa4, 0xff }, /* sky blue */ + { 0x72, 0x9f, 0xcf, 0xff }, /* sky blue light */ + { 0x20, 0x4a, 0x87, 0xff }, /* sky blue dark */ + { 0x75, 0x50, 0x7b, 0xff }, /* plum */ + { 0xad, 0x7f, 0xa8, 0xff }, /* plum light */ + { 0x5c, 0x35, 0x66, 0xff }, /* plum dark */ + { 0xcc, 0x00, 0x00, 0xff }, /* scarlet red */ + { 0xef, 0x29, 0x29, 0xff }, /* scarlet red light */ + { 0xa4, 0x00, 0x00, 0xff }, /* scarlet red dark */ + { 0xee, 0xee, 0xec, 0xff }, /* aluminium 1 */ + { 0xd3, 0xd7, 0xcf, 0xff }, /* aluminium 2 */ + { 0xba, 0xbd, 0xb6, 0xff }, /* aluminium 3 */ + { 0x88, 0x8a, 0x85, 0xff }, /* aluminium 4 */ + { 0x55, 0x57, 0x53, 0xff }, /* aluminium 5 */ + { 0x2e, 0x34, 0x36, 0xff }, /* aluminium 6 */ + + /* last color */ + { 0x00, 0x00, 0x00, 0x00 } /* transparent */ +}; + +/** + * clutter_color_get_static: + * @color: the named global color + * + * Retrieves a static color for the given @color name + * + * Static colors are created by Clutter and are guaranteed to always be + * available and valid + * + * Return value: a pointer to a static color; the returned pointer + * is owned by Clutter and it should never be modified or freed + * + * Since: 1.6 + */ +const ClutterColor * +clutter_color_get_static (ClutterStaticColor color) +{ + g_return_val_if_fail (color >= CLUTTER_COLOR_WHITE && + color <= CLUTTER_COLOR_TRANSPARENT, NULL); + + return &static_colors[color]; +} + +/** + * clutter_color_add: + * @a: a #ClutterColor + * @b: a #ClutterColor + * @result: (out caller-allocates): return location for the result + * + * Adds @a to @b and saves the resulting color inside @result. + * + * The alpha channel of @result is set as as the maximum value + * between the alpha channels of @a and @b. + */ +void +clutter_color_add (const ClutterColor *a, + const ClutterColor *b, + ClutterColor *result) +{ + g_return_if_fail (a != NULL); + g_return_if_fail (b != NULL); + g_return_if_fail (result != NULL); + + result->red = CLAMP (a->red + b->red, 0, 255); + result->green = CLAMP (a->green + b->green, 0, 255); + result->blue = CLAMP (a->blue + b->blue, 0, 255); + + result->alpha = MAX (a->alpha, b->alpha); +} + +/** + * clutter_color_subtract: + * @a: a #ClutterColor + * @b: a #ClutterColor + * @result: (out caller-allocates): return location for the result + * + * Subtracts @b from @a and saves the resulting color inside @result. + * + * This function assumes that the components of @a are greater than the + * components of @b; the result is, otherwise, undefined. + * + * The alpha channel of @result is set as the minimum value + * between the alpha channels of @a and @b. + */ +void +clutter_color_subtract (const ClutterColor *a, + const ClutterColor *b, + ClutterColor *result) +{ + g_return_if_fail (a != NULL); + g_return_if_fail (b != NULL); + g_return_if_fail (result != NULL); + + result->red = CLAMP (a->red - b->red, 0, 255); + result->green = CLAMP (a->green - b->green, 0, 255); + result->blue = CLAMP (a->blue - b->blue, 0, 255); + + result->alpha = MIN (a->alpha, b->alpha); +} + +/** + * clutter_color_lighten: + * @color: a #ClutterColor + * @result: (out caller-allocates): return location for the lighter color + * + * Lightens @color by a fixed amount, and saves the changed color + * in @result. + */ +void +clutter_color_lighten (const ClutterColor *color, + ClutterColor *result) +{ + clutter_color_shade (color, 1.3, result); +} + +/** + * clutter_color_darken: + * @color: a #ClutterColor + * @result: (out caller-allocates): return location for the darker color + * + * Darkens @color by a fixed amount, and saves the changed color + * in @result. + */ +void +clutter_color_darken (const ClutterColor *color, + ClutterColor *result) +{ + clutter_color_shade (color, 0.7, result); +} + +/** + * clutter_color_to_hls: + * @color: a #ClutterColor + * @hue: (out): return location for the hue value or %NULL + * @luminance: (out): return location for the luminance value or %NULL + * @saturation: (out): return location for the saturation value or %NULL + * + * Converts @color to the HLS format. + * + * The @hue value is in the 0 .. 360 range. The @luminance and + * @saturation values are in the 0 .. 1 range. + */ +void +clutter_color_to_hls (const ClutterColor *color, + float *hue, + float *luminance, + float *saturation) +{ + float red, green, blue; + float min, max, delta; + float h, l, s; + + g_return_if_fail (color != NULL); + + red = color->red / 255.0; + green = color->green / 255.0; + blue = color->blue / 255.0; + + if (red > green) + { + if (red > blue) + max = red; + else + max = blue; + + if (green < blue) + min = green; + else + min = blue; + } + else + { + if (green > blue) + max = green; + else + max = blue; + + if (red < blue) + min = red; + else + min = blue; + } + + l = (max + min) / 2; + s = 0; + h = 0; + + if (max != min) + { + if (l <= 0.5) + s = (max - min) / (max + min); + else + s = (max - min) / (2.0 - max - min); + + delta = max - min; + + if (red == max) + h = (green - blue) / delta; + else if (green == max) + h = 2.0 + (blue - red) / delta; + else if (blue == max) + h = 4.0 + (red - green) / delta; + + h *= 60; + + if (h < 0) + h += 360.0; + } + + if (hue) + *hue = h; + + if (luminance) + *luminance = l; + + if (saturation) + *saturation = s; +} + +/** + * clutter_color_from_hls: + * @color: (out): return location for a #ClutterColor + * @hue: hue value, in the 0 .. 360 range + * @luminance: luminance value, in the 0 .. 1 range + * @saturation: saturation value, in the 0 .. 1 range + * + * Converts a color expressed in HLS (hue, luminance and saturation) + * values into a #ClutterColor. + */ +void +clutter_color_from_hls (ClutterColor *color, + float hue, + float luminance, + float saturation) +{ + float tmp1, tmp2; + float tmp3[3]; + float clr[3]; + int i; + + hue /= 360.0; + + if (saturation == 0) + { + color->red = color->green = color->blue = (luminance * 255); + + return; + } + + if (luminance <= 0.5) + tmp2 = luminance * (1.0 + saturation); + else + tmp2 = luminance + saturation - (luminance * saturation); + + tmp1 = 2.0 * luminance - tmp2; + + tmp3[0] = hue + 1.0 / 3.0; + tmp3[1] = hue; + tmp3[2] = hue - 1.0 / 3.0; + + for (i = 0; i < 3; i++) + { + if (tmp3[i] < 0) + tmp3[i] += 1.0; + + if (tmp3[i] > 1) + tmp3[i] -= 1.0; + + if (6.0 * tmp3[i] < 1.0) + clr[i] = tmp1 + (tmp2 - tmp1) * tmp3[i] * 6.0; + else if (2.0 * tmp3[i] < 1.0) + clr[i] = tmp2; + else if (3.0 * tmp3[i] < 2.0) + clr[i] = (tmp1 + (tmp2 - tmp1) * ((2.0 / 3.0) - tmp3[i]) * 6.0); + else + clr[i] = tmp1; + } + + color->red = floorf (clr[0] * 255.0 + 0.5); + color->green = floorf (clr[1] * 255.0 + 0.5); + color->blue = floorf (clr[2] * 255.0 + 0.5); +} + +/** + * clutter_color_shade: + * @color: a #ClutterColor + * @factor: the shade factor to apply + * @result: (out caller-allocates): return location for the shaded color + * + * Shades @color by @factor and saves the modified color into @result. + */ +void +clutter_color_shade (const ClutterColor *color, + gdouble factor, + ClutterColor *result) +{ + float h, l, s; + + g_return_if_fail (color != NULL); + g_return_if_fail (result != NULL); + + clutter_color_to_hls (color, &h, &l, &s); + + l = CLAMP (l * factor, 0.0, 1.0); + s = CLAMP (s * factor, 0.0, 1.0); + + clutter_color_from_hls (result, h, l, s); + + result->alpha = color->alpha; +} + +/** + * clutter_color_to_pixel: + * @color: a #ClutterColor + * + * Converts @color into a packed 32 bit integer, containing + * all the four 8 bit channels used by #ClutterColor. + * + * Return value: a packed color + */ +guint32 +clutter_color_to_pixel (const ClutterColor *color) +{ + g_return_val_if_fail (color != NULL, 0); + + return (color->alpha | + color->blue << 8 | + color->green << 16 | + color->red << 24); +} + +/** + * clutter_color_from_pixel: + * @color: (out caller-allocates): return location for a #ClutterColor + * @pixel: a 32 bit packed integer containing a color + * + * Converts @pixel from the packed representation of a four 8 bit channel + * color to a #ClutterColor. + */ +void +clutter_color_from_pixel (ClutterColor *color, + guint32 pixel) +{ + g_return_if_fail (color != NULL); + + color->red = pixel >> 24; + color->green = (pixel >> 16) & 0xff; + color->blue = (pixel >> 8) & 0xff; + color->alpha = pixel & 0xff; +} + +static inline void +skip_whitespace (gchar **str) +{ + while (g_ascii_isspace (**str)) + *str += 1; +} + +static inline void +parse_rgb_value (gchar *str, + guint8 *color, + gchar **endp) +{ + gdouble number; + gchar *p; + + skip_whitespace (&str); + + number = g_ascii_strtod (str, endp); + + p = *endp; + + skip_whitespace (&p); + + if (*p == '%') + { + *endp = (gchar *) (p + 1); + + *color = CLAMP (number / 100.0, 0.0, 1.0) * 255; + } + else + *color = CLAMP (number, 0, 255); +} + +static gboolean +parse_rgba (ClutterColor *color, + gchar *str, + gboolean has_alpha) +{ + skip_whitespace (&str); + + if (*str != '(') + return FALSE; + + str += 1; + + /* red */ + parse_rgb_value (str, &color->red, &str); + skip_whitespace (&str); + if (*str != ',') + return FALSE; + + str += 1; + + /* green */ + parse_rgb_value (str, &color->green, &str); + skip_whitespace (&str); + if (*str != ',') + return FALSE; + + str += 1; + + /* blue */ + parse_rgb_value (str, &color->blue, &str); + skip_whitespace (&str); + + /* alpha (optional); since the alpha channel value can only + * be between 0 and 1 we don't use the parse_rgb_value() + * function + */ + if (has_alpha) + { + gdouble number; + + if (*str != ',') + return FALSE; + + str += 1; + + skip_whitespace (&str); + number = g_ascii_strtod (str, &str); + + color->alpha = CLAMP (number * 255.0, 0, 255); + } + else + color->alpha = 255; + + skip_whitespace (&str); + if (*str != ')') + return FALSE; + + return TRUE; +} + +static gboolean +parse_hsla (ClutterColor *color, + gchar *str, + gboolean has_alpha) +{ + gdouble number; + gdouble h, l, s; + + skip_whitespace (&str); + + if (*str != '(') + return FALSE; + + str += 1; + + /* hue */ + skip_whitespace (&str); + /* we don't do any angle normalization here because + * clutter_color_from_hls() will do it for us + */ + number = g_ascii_strtod (str, &str); + skip_whitespace (&str); + if (*str != ',') + return FALSE; + + h = number; + + str += 1; + + /* saturation */ + skip_whitespace (&str); + number = g_ascii_strtod (str, &str); + skip_whitespace (&str); + if (*str != '%') + return FALSE; + + str += 1; + + s = CLAMP (number / 100.0, 0.0, 1.0); + skip_whitespace (&str); + if (*str != ',') + return FALSE; + + str += 1; + + /* luminance */ + skip_whitespace (&str); + number = g_ascii_strtod (str, &str); + skip_whitespace (&str); + if (*str != '%') + return FALSE; + + str += 1; + + l = CLAMP (number / 100.0, 0.0, 1.0); + skip_whitespace (&str); + + /* alpha (optional); since the alpha channel value can only + * be between 0 and 1 we don't use the parse_rgb_value() + * function + */ + if (has_alpha) + { + if (*str != ',') + return FALSE; + + str += 1; + + skip_whitespace (&str); + number = g_ascii_strtod (str, &str); + + color->alpha = CLAMP (number * 255.0, 0, 255); + } + else + color->alpha = 255; + + skip_whitespace (&str); + if (*str != ')') + return FALSE; + + clutter_color_from_hls (color, h, l, s); + + return TRUE; +} + +/** + * clutter_color_from_string: + * @color: (out caller-allocates): return location for a #ClutterColor + * @str: a string specifiying a color + * + * Parses a string definition of a color, filling the #ClutterColor.red, + * #ClutterColor.green, #ClutterColor.blue and #ClutterColor.alpha fields + * of @color. + * + * The @color is not allocated. + * + * The format of @str can be either one of: + * + * - a standard name (as taken from the X11 rgb.txt file) + * - an hexadecimal value in the form: `#rgb`, `#rrggbb`, `#rgba`, or `#rrggbbaa` + * - a RGB color in the form: `rgb(r, g, b)` + * - a RGB color in the form: `rgba(r, g, b, a)` + * - a HSL color in the form: `hsl(h, s, l)` + * -a HSL color in the form: `hsla(h, s, l, a)` + * + * where 'r', 'g', 'b' and 'a' are (respectively) the red, green, blue color + * intensities and the opacity. The 'h', 's' and 'l' are (respectively) the + * hue, saturation and luminance values. + * + * In the rgb() and rgba() formats, the 'r', 'g', and 'b' values are either + * integers between 0 and 255, or percentage values in the range between 0% + * and 100%; the percentages require the '%' character. The 'a' value, if + * specified, can only be a floating point value between 0.0 and 1.0. + * + * In the hls() and hlsa() formats, the 'h' value (hue) is an angle between + * 0 and 360.0 degrees; the 'l' and 's' values (luminance and saturation) are + * percentage values in the range between 0% and 100%. The 'a' value, if specified, + * can only be a floating point value between 0.0 and 1.0. + * + * Whitespace inside the definitions is ignored; no leading whitespace + * is allowed. + * + * If the alpha component is not specified then it is assumed to be set to + * be fully opaque. + * + * Return value: %TRUE if parsing succeeded, and %FALSE otherwise + * + * Since: 1.0 + */ +gboolean +clutter_color_from_string (ClutterColor *color, + const gchar *str) +{ + PangoColor pango_color = { 0, }; + + g_return_val_if_fail (color != NULL, FALSE); + g_return_val_if_fail (str != NULL, FALSE); + + if (strncmp (str, "rgb", 3) == 0) + { + gchar *s = (gchar *) str; + gboolean res; + + if (strncmp (str, "rgba", 4) == 0) + res = parse_rgba (color, s + 4, TRUE); + else + res = parse_rgba (color, s + 3, FALSE); + + return res; + } + + if (strncmp (str, "hsl", 3) == 0) + { + gchar *s = (gchar *) str; + gboolean res; + + if (strncmp (str, "hsla", 4) == 0) + res = parse_hsla (color, s + 4, TRUE); + else + res = parse_hsla (color, s + 3, FALSE); + + return res; + } + + /* if the string contains a color encoded using the hexadecimal + * 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. + */ + if (str[0] == '#' && str[1] != '\0') + { + gsize length = strlen (str + 1); + gint32 result; + + if (sscanf (str + 1, "%x", &result) == 1) + { + switch (length) + { + case 8: /* rrggbbaa */ + color->red = (result >> 24) & 0xff; + color->green = (result >> 16) & 0xff; + color->blue = (result >> 8) & 0xff; + + color->alpha = result & 0xff; + + return TRUE; + + case 6: /* #rrggbb */ + color->red = (result >> 16) & 0xff; + color->green = (result >> 8) & 0xff; + color->blue = result & 0xff; + + color->alpha = 0xff; + + return TRUE; + + case 4: /* #rgba */ + color->red = ((result >> 12) & 0xf); + color->green = ((result >> 8) & 0xf); + color->blue = ((result >> 4) & 0xf); + color->alpha = result & 0xf; + + 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; + + case 3: /* #rgb */ + color->red = ((result >> 8) & 0xf); + color->green = ((result >> 4) & 0xf); + color->blue = result & 0xf; + + color->red = (color->red << 4) | color->red; + color->green = (color->green << 4) | color->green; + color->blue = (color->blue << 4) | color->blue; + + color->alpha = 0xff; + + return TRUE; + + default: + return FALSE; + } + } + } + + /* fall back to pango for X11-style named colors; see: + * + * http://en.wikipedia.org/wiki/X11_color_names + * + * for a list. at some point we might even ship with our own list generated + * from X11/rgb.txt, like we generate the key symbols. + */ + if (pango_color_parse (&pango_color, str)) + { + color->red = pango_color.red; + color->green = pango_color.green; + color->blue = pango_color.blue; + + color->alpha = 0xff; + + return TRUE; + } + + return FALSE; +} + +/** + * clutter_color_to_string: + * @color: a #ClutterColor + * + * Returns a textual specification of @color in the hexadecimal form + * #rrggbbaa, where r, + * g, b and a are + * hexadecimal digits representing the red, green, blue and alpha components + * respectively. + * + * Return value: (transfer full): a newly-allocated text string + * + * Since: 0.2 + */ +gchar * +clutter_color_to_string (const ClutterColor *color) +{ + g_return_val_if_fail (color != NULL, NULL); + + return g_strdup_printf ("#%02x%02x%02x%02x", + color->red, + color->green, + color->blue, + color->alpha); +} + +/** + * clutter_color_equal: + * @v1: (type Clutter.Color): a #ClutterColor + * @v2: (type Clutter.Color): a #ClutterColor + * + * Compares two #ClutterColors and checks if they are the same. + * + * This function can be passed to g_hash_table_new() as the @key_equal_func + * parameter, when using #ClutterColors as keys in a #GHashTable. + * + * Return value: %TRUE if the two colors are the same. + * + * Since: 0.2 + */ +gboolean +clutter_color_equal (gconstpointer v1, + gconstpointer v2) +{ + const ClutterColor *a, *b; + + g_return_val_if_fail (v1 != NULL, FALSE); + g_return_val_if_fail (v2 != NULL, FALSE); + + if (v1 == v2) + return TRUE; + + a = v1; + b = v2; + + return (a->red == b->red && + a->green == b->green && + a->blue == b->blue && + a->alpha == b->alpha); +} + +/** + * clutter_color_hash: + * @v: (type Clutter.Color): a #ClutterColor + * + * Converts a #ClutterColor to a hash value. + * + * This function can be passed to g_hash_table_new() as the @hash_func + * parameter, when using #ClutterColors as keys in a #GHashTable. + * + * Return value: a hash value corresponding to the color + * + * Since: 1.0 + */ +guint +clutter_color_hash (gconstpointer v) +{ + return clutter_color_to_pixel ((const ClutterColor *) v); +} + +/** + * clutter_color_interpolate: + * @initial: the initial #ClutterColor + * @final: the final #ClutterColor + * @progress: the interpolation progress + * @result: (out): return location for the interpolation + * + * Interpolates between @initial and @final #ClutterColors + * using @progress + * + * Since: 1.6 + */ +void +clutter_color_interpolate (const ClutterColor *initial, + const ClutterColor *final, + gdouble progress, + ClutterColor *result) +{ + g_return_if_fail (initial != NULL); + g_return_if_fail (final != NULL); + g_return_if_fail (result != NULL); + + result->red = initial->red + (final->red - initial->red) * progress; + result->green = initial->green + (final->green - initial->green) * progress; + result->blue = initial->blue + (final->blue - initial->blue) * progress; + result->alpha = initial->alpha + (final->alpha - initial->alpha) * progress; +} + +static gboolean +clutter_color_progress (const GValue *a, + const GValue *b, + gdouble progress, + GValue *retval) +{ + const ClutterColor *a_color = clutter_value_get_color (a); + const ClutterColor *b_color = clutter_value_get_color (b); + ClutterColor res = { 0, }; + + clutter_color_interpolate (a_color, b_color, progress, &res); + clutter_value_set_color (retval, &res); + + return TRUE; +} + +/** + * clutter_color_copy: + * @color: a #ClutterColor + * + * Makes a copy of the color structure. The result must be + * freed using clutter_color_free(). + * + * Return value: (transfer full): an allocated copy of @color. + * + * Since: 0.2 + */ +ClutterColor * +clutter_color_copy (const ClutterColor *color) +{ + if (G_LIKELY (color != NULL)) + return g_slice_dup (ClutterColor, color); + + return NULL; +} + +/** + * clutter_color_free: + * @color: a #ClutterColor + * + * Frees a color structure created with clutter_color_copy(). + * + * Since: 0.2 + */ +void +clutter_color_free (ClutterColor *color) +{ + if (G_LIKELY (color != NULL)) + g_slice_free (ClutterColor, color); +} + +/** + * clutter_color_new: + * @red: red component of the color, between 0 and 255 + * @green: green component of the color, between 0 and 255 + * @blue: blue component of the color, between 0 and 255 + * @alpha: alpha component of the color, between 0 and 255 + * + * Creates a new #ClutterColor with the given values. + * + * This function is the equivalent of: + * + * |[ + * clutter_color_init (clutter_color_alloc (), red, green, blue, alpha); + * ]| + * + * Return value: (transfer full): the newly allocated color. + * Use clutter_color_free() when done + * + * Since: 0.8 + */ +ClutterColor * +clutter_color_new (guint8 red, + guint8 green, + guint8 blue, + guint8 alpha) +{ + return clutter_color_init (clutter_color_alloc (), + red, + green, + blue, + alpha); +} + +/** + * clutter_color_alloc: (constructor) + * + * Allocates a new, transparent black #ClutterColor. + * + * Return value: (transfer full): the newly allocated #ClutterColor; use + * clutter_color_free() to free its resources + * + * Since: 1.12 + */ +ClutterColor * +clutter_color_alloc (void) +{ + return g_slice_new0 (ClutterColor); +} + +/** + * clutter_color_init: + * @color: a #ClutterColor + * @red: red component of the color, between 0 and 255 + * @green: green component of the color, between 0 and 255 + * @blue: blue component of the color, between 0 and 255 + * @alpha: alpha component of the color, between 0 and 255 + * + * Initializes @color with the given values. + * + * Return value: (transfer none): the initialized #ClutterColor + * + * Since: 1.12 + */ +ClutterColor * +clutter_color_init (ClutterColor *color, + guint8 red, + guint8 green, + guint8 blue, + guint8 alpha) +{ + g_return_val_if_fail (color != NULL, NULL); + + color->red = red; + color->green = green; + color->blue = blue; + color->alpha = alpha; + + return color; +} + +static void +clutter_value_transform_color_string (const GValue *src, + GValue *dest) +{ + const ClutterColor *color = g_value_get_boxed (src); + + if (color) + { + gchar *string = clutter_color_to_string (color); + + g_value_take_string (dest, string); + } + else + g_value_set_string (dest, NULL); +} + +static void +clutter_value_transform_string_color (const GValue *src, + GValue *dest) +{ + const char *str = g_value_get_string (src); + + if (str) + { + ClutterColor color = { 0, }; + + clutter_color_from_string (&color, str); + + clutter_value_set_color (dest, &color); + } + else + clutter_value_set_color (dest, NULL); +} + +G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterColor, clutter_color, + clutter_color_copy, + clutter_color_free, + CLUTTER_REGISTER_VALUE_TRANSFORM_TO (G_TYPE_STRING, clutter_value_transform_color_string) + CLUTTER_REGISTER_VALUE_TRANSFORM_FROM (G_TYPE_STRING, clutter_value_transform_string_color) + CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_color_progress)); + +/** + * clutter_value_set_color: + * @value: a #GValue initialized to #CLUTTER_TYPE_COLOR + * @color: the color to set + * + * Sets @value to @color. + * + * Since: 0.8 + */ +void +clutter_value_set_color (GValue *value, + const ClutterColor *color) +{ + g_return_if_fail (CLUTTER_VALUE_HOLDS_COLOR (value)); + + g_value_set_boxed (value, color); +} + +/** + * clutter_value_get_color: + * @value: a #GValue initialized to #CLUTTER_TYPE_COLOR + * + * Gets the #ClutterColor contained in @value. + * + * Return value: (transfer none): the color inside the passed #GValue + * + * Since: 0.8 + */ +const ClutterColor * +clutter_value_get_color (const GValue *value) +{ + g_return_val_if_fail (CLUTTER_VALUE_HOLDS_COLOR (value), NULL); + + return g_value_get_boxed (value); +} + +static void +param_color_init (GParamSpec *pspec) +{ + ClutterParamSpecColor *cspec = CLUTTER_PARAM_SPEC_COLOR (pspec); + + cspec->default_value = NULL; +} + +static void +param_color_finalize (GParamSpec *pspec) +{ + ClutterParamSpecColor *cspec = CLUTTER_PARAM_SPEC_COLOR (pspec); + + clutter_color_free (cspec->default_value); +} + +static void +param_color_set_default (GParamSpec *pspec, + GValue *value) +{ + const ClutterColor *default_value = + CLUTTER_PARAM_SPEC_COLOR (pspec)->default_value; + clutter_value_set_color (value, default_value); +} + +static gint +param_color_values_cmp (GParamSpec *pspec, + const GValue *value1, + const GValue *value2) +{ + const ClutterColor *color1 = g_value_get_boxed (value1); + const ClutterColor *color2 = g_value_get_boxed (value2); + int pixel1, pixel2; + + if (color1 == NULL) + return color2 == NULL ? 0 : -1; + + pixel1 = clutter_color_to_pixel (color1); + pixel2 = clutter_color_to_pixel (color2); + + if (pixel1 < pixel2) + return -1; + else if (pixel1 == pixel2) + return 0; + else + return 1; +} + +GType +clutter_param_color_get_type (void) +{ + static GType pspec_type = 0; + + if (G_UNLIKELY (pspec_type == 0)) + { + const GParamSpecTypeInfo pspec_info = { + sizeof (ClutterParamSpecColor), + 16, + param_color_init, + CLUTTER_TYPE_COLOR, + param_color_finalize, + param_color_set_default, + NULL, + param_color_values_cmp, + }; + + pspec_type = g_param_type_register_static (I_("ClutterParamSpecColor"), + &pspec_info); + } + + return pspec_type; +} + +/** + * clutter_param_spec_color: (skip) + * @name: name of the property + * @nick: short name + * @blurb: description (can be translatable) + * @default_value: default value + * @flags: flags for the param spec + * + * Creates a #GParamSpec for properties using #ClutterColor. + * + * Return value: the newly created #GParamSpec + * + * Since: 0.8 + */ +GParamSpec * +clutter_param_spec_color (const gchar *name, + const gchar *nick, + const gchar *blurb, + const ClutterColor *default_value, + GParamFlags flags) +{ + ClutterParamSpecColor *cspec; + + cspec = g_param_spec_internal (CLUTTER_TYPE_PARAM_COLOR, + name, nick, blurb, flags); + + cspec->default_value = clutter_color_copy (default_value); + + return G_PARAM_SPEC (cspec); +} diff --git a/clutter/clutter/clutter-color.h b/clutter/clutter/clutter-color.h new file mode 100644 index 0000000..913ed69 --- /dev/null +++ b/clutter/clutter/clutter-color.h @@ -0,0 +1,200 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By: Matthew Allum + * Emmanuele Bassi + * + * Copyright (C) 2006, 2007, 2008 OpenedHand + * Copyright (C) 2009 Intel Corp. + * + * 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 . + */ + +#ifndef __CLUTTER_COLOR_H__ +#define __CLUTTER_COLOR_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_COLOR (clutter_color_get_type ()) + +/** + * ClutterColor: + * @red: red component, between 0 and 255 + * @green: green component, between 0 and 255 + * @blue: blue component, between 0 and 255 + * @alpha: alpha component, between 0 and 255 + * + * Color representation. + */ +struct _ClutterColor +{ + /*< public >*/ + guint8 red; + guint8 green; + guint8 blue; + + guint8 alpha; +}; + +/** + * CLUTTER_COLOR_INIT: + * @r: value for the red channel, between 0 and 255 + * @g: value for the green channel, between 0 and 255 + * @b: value for the blue channel, between 0 and 255 + * @a: value for the alpha channel, between 0 and 255 + * + * A macro that initializes a #ClutterColor, to be used when declaring it. + * + * Since: 1.12 + */ +#define CLUTTER_COLOR_INIT(r,g,b,a) { (r), (g), (b), (a) } + +CLUTTER_AVAILABLE_IN_ALL +GType clutter_color_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_ALL +ClutterColor *clutter_color_new (guint8 red, + guint8 green, + guint8 blue, + guint8 alpha); +CLUTTER_AVAILABLE_IN_1_12 +ClutterColor *clutter_color_alloc (void); +CLUTTER_AVAILABLE_IN_1_12 +ClutterColor *clutter_color_init (ClutterColor *color, + guint8 red, + guint8 green, + guint8 blue, + guint8 alpha); +CLUTTER_AVAILABLE_IN_ALL +ClutterColor *clutter_color_copy (const ClutterColor *color); +CLUTTER_AVAILABLE_IN_ALL +void clutter_color_free (ClutterColor *color); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_color_add (const ClutterColor *a, + const ClutterColor *b, + ClutterColor *result); +CLUTTER_AVAILABLE_IN_ALL +void clutter_color_subtract (const ClutterColor *a, + const ClutterColor *b, + ClutterColor *result); +CLUTTER_AVAILABLE_IN_ALL +void clutter_color_lighten (const ClutterColor *color, + ClutterColor *result); +CLUTTER_AVAILABLE_IN_ALL +void clutter_color_darken (const ClutterColor *color, + ClutterColor *result); +CLUTTER_AVAILABLE_IN_ALL +void clutter_color_shade (const ClutterColor *color, + gdouble factor, + ClutterColor *result); + +CLUTTER_AVAILABLE_IN_ALL +gchar * clutter_color_to_string (const ClutterColor *color); +CLUTTER_AVAILABLE_IN_1_0 +gboolean clutter_color_from_string (ClutterColor *color, + const gchar *str); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_color_to_hls (const ClutterColor *color, + gfloat *hue, + gfloat *luminance, + gfloat *saturation); +CLUTTER_AVAILABLE_IN_ALL +void clutter_color_from_hls (ClutterColor *color, + gfloat hue, + gfloat luminance, + gfloat saturation); + +CLUTTER_AVAILABLE_IN_ALL +guint32 clutter_color_to_pixel (const ClutterColor *color); +CLUTTER_AVAILABLE_IN_ALL +void clutter_color_from_pixel (ClutterColor *color, + guint32 pixel); + +CLUTTER_AVAILABLE_IN_1_0 +guint clutter_color_hash (gconstpointer v); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_color_equal (gconstpointer v1, + gconstpointer v2); + +CLUTTER_AVAILABLE_IN_1_6 +void clutter_color_interpolate (const ClutterColor *initial, + const ClutterColor *final, + gdouble progress, + ClutterColor *result); + +#define CLUTTER_TYPE_PARAM_COLOR (clutter_param_color_get_type ()) +#define CLUTTER_PARAM_SPEC_COLOR(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), CLUTTER_TYPE_PARAM_COLOR, ClutterParamSpecColor)) +#define CLUTTER_IS_PARAM_SPEC_COLOR(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), CLUTTER_TYPE_PARAM_COLOR)) + +/** + * CLUTTER_VALUE_HOLDS_COLOR: + * @x: a #GValue + * + * Evaluates to %TRUE if @x holds a #ClutterColor. + * + * Since: 1.0 + */ +#define CLUTTER_VALUE_HOLDS_COLOR(x) (G_VALUE_HOLDS ((x), CLUTTER_TYPE_COLOR)) + +typedef struct _ClutterParamSpecColor ClutterParamSpecColor; + +/** + * ClutterParamSpecColor: (skip) + * @default_value: default color value + * + * A #GParamSpec subclass for defining properties holding + * a #ClutterColor. + * + * Since: 1.0 + */ +struct _ClutterParamSpecColor +{ + /*< private >*/ + GParamSpec parent_instance; + + /*< public >*/ + ClutterColor *default_value; +}; + +CLUTTER_AVAILABLE_IN_1_0 +void clutter_value_set_color (GValue *value, + const ClutterColor *color); +CLUTTER_AVAILABLE_IN_1_0 +const ClutterColor * clutter_value_get_color (const GValue *value); + +CLUTTER_AVAILABLE_IN_1_0 +GType clutter_param_color_get_type (void) G_GNUC_CONST; +CLUTTER_AVAILABLE_IN_1_0 +GParamSpec * clutter_param_spec_color (const gchar *name, + const gchar *nick, + const gchar *blurb, + const ClutterColor *default_value, + GParamFlags flags); + +CLUTTER_AVAILABLE_IN_1_6 +const ClutterColor *clutter_color_get_static (ClutterStaticColor color); + +G_END_DECLS + +#endif /* __CLUTTER_COLOR_H__ */ diff --git a/clutter/clutter/clutter-colorize-effect.c b/clutter/clutter/clutter-colorize-effect.c new file mode 100644 index 0000000..960708e --- /dev/null +++ b/clutter/clutter/clutter-colorize-effect.c @@ -0,0 +1,372 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-colorize-effect + * @short_description: A colorization effect + * @see_also: #ClutterEffect, #ClutterOffscreenEffect + * + * #ClutterColorizeEffect is a sub-class of #ClutterEffect that + * colorizes an actor with the given tint. + * + * #ClutterColorizeEffect is available since Clutter 1.4 + */ + +#define CLUTTER_COLORIZE_EFFECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_COLORIZE_EFFECT, ClutterColorizeEffectClass)) +#define CLUTTER_IS_COLORIZE_EFFECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_COLORIZE_EFFECT)) +#define CLUTTER_COLORIZE_EFFECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_COLORIZE_EFFECT, ClutterColorizeEffectClass)) + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#define CLUTTER_ENABLE_EXPERIMENTAL_API + +#include "clutter-colorize-effect.h" + +#include "cogl/cogl.h" + +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-offscreen-effect.h" +#include "clutter-private.h" + +struct _ClutterColorizeEffect +{ + ClutterOffscreenEffect parent_instance; + + /* the tint of the colorization */ + ClutterColor tint; + + gint tint_uniform; + + gint tex_width; + gint tex_height; + + CoglPipeline *pipeline; +}; + +struct _ClutterColorizeEffectClass +{ + ClutterOffscreenEffectClass parent_class; + + CoglPipeline *base_pipeline; +}; + +/* the magic gray vec3 has been taken from the NTSC conversion weights + * as defined by: + * + * "OpenGL Superbible, 4th Edition" + * -- Richard S. Wright Jr, Benjamin Lipchak, Nicholas Haemel + * Addison-Wesley + */ +static const gchar *colorize_glsl_declarations = +"uniform vec3 tint;\n"; + +static const gchar *colorize_glsl_source = +"float gray = dot (cogl_color_out.rgb, vec3 (0.299, 0.587, 0.114));\n" +"cogl_color_out.rgb = gray * tint;\n"; + +/* a lame sepia */ +static const ClutterColor default_tint = { 255, 204, 153, 255 }; + +enum +{ + PROP_0, + + PROP_TINT, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +G_DEFINE_TYPE (ClutterColorizeEffect, + clutter_colorize_effect, + CLUTTER_TYPE_OFFSCREEN_EFFECT); + +static gboolean +clutter_colorize_effect_pre_paint (ClutterEffect *effect) +{ + ClutterColorizeEffect *self = CLUTTER_COLORIZE_EFFECT (effect); + ClutterEffectClass *parent_class; + + if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect))) + return FALSE; + + if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) + { + /* if we don't have support for GLSL shaders then we + * forcibly disable the ActorMeta + */ + g_warning ("Unable to use the ShaderEffect: the graphics hardware " + "or the current GL driver does not implement support " + "for the GLSL shading language."); + clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (effect), FALSE); + return FALSE; + } + + parent_class = CLUTTER_EFFECT_CLASS (clutter_colorize_effect_parent_class); + if (parent_class->pre_paint (effect)) + { + ClutterOffscreenEffect *offscreen_effect = + CLUTTER_OFFSCREEN_EFFECT (effect); + CoglHandle texture; + + texture = clutter_offscreen_effect_get_texture (offscreen_effect); + self->tex_width = cogl_texture_get_width (texture); + self->tex_height = cogl_texture_get_height (texture); + + cogl_pipeline_set_layer_texture (self->pipeline, 0, texture); + + return TRUE; + } + else + return FALSE; +} + +static void +clutter_colorize_effect_paint_target (ClutterOffscreenEffect *effect) +{ + ClutterColorizeEffect *self = CLUTTER_COLORIZE_EFFECT (effect); + ClutterActor *actor; + guint8 paint_opacity; + + actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); + paint_opacity = clutter_actor_get_paint_opacity (actor); + + cogl_pipeline_set_color4ub (self->pipeline, + paint_opacity, + paint_opacity, + paint_opacity, + paint_opacity); + cogl_push_source (self->pipeline); + + cogl_rectangle (0, 0, self->tex_width, self->tex_height); + + cogl_pop_source (); +} + +static void +clutter_colorize_effect_dispose (GObject *gobject) +{ + ClutterColorizeEffect *self = CLUTTER_COLORIZE_EFFECT (gobject); + + if (self->pipeline != NULL) + { + cogl_object_unref (self->pipeline); + self->pipeline = NULL; + } + + G_OBJECT_CLASS (clutter_colorize_effect_parent_class)->dispose (gobject); +} + +static void +clutter_colorize_effect_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterColorizeEffect *effect = CLUTTER_COLORIZE_EFFECT (gobject); + + switch (prop_id) + { + case PROP_TINT: + clutter_colorize_effect_set_tint (effect, + clutter_value_get_color (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_colorize_effect_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterColorizeEffect *effect = CLUTTER_COLORIZE_EFFECT (gobject); + + switch (prop_id) + { + case PROP_TINT: + clutter_value_set_color (value, &effect->tint); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_colorize_effect_class_init (ClutterColorizeEffectClass *klass) +{ + ClutterEffectClass *effect_class = CLUTTER_EFFECT_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterOffscreenEffectClass *offscreen_class; + + offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass); + offscreen_class->paint_target = clutter_colorize_effect_paint_target; + + effect_class->pre_paint = clutter_colorize_effect_pre_paint; + + gobject_class->set_property = clutter_colorize_effect_set_property; + gobject_class->get_property = clutter_colorize_effect_get_property; + gobject_class->dispose = clutter_colorize_effect_dispose; + + /** + * ClutterColorizeEffect:tint: + * + * The tint to apply to the actor + * + * Since: 1.4 + */ + obj_props[PROP_TINT] = + clutter_param_spec_color ("tint", + P_("Tint"), + P_("The tint to apply"), + &default_tint, + CLUTTER_PARAM_READWRITE); + + g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); +} + +static void +update_tint_uniform (ClutterColorizeEffect *self) +{ + if (self->tint_uniform > -1) + { + float tint[3] = { + self->tint.red / 255.0, + self->tint.green / 255.0, + self->tint.blue / 255.0 + }; + + cogl_pipeline_set_uniform_float (self->pipeline, + self->tint_uniform, + 3, /* n_components */ + 1, /* count */ + tint); + } +} + +static void +clutter_colorize_effect_init (ClutterColorizeEffect *self) +{ + ClutterColorizeEffectClass *klass = CLUTTER_COLORIZE_EFFECT_GET_CLASS (self); + + if (G_UNLIKELY (klass->base_pipeline == NULL)) + { + CoglSnippet *snippet; + CoglContext *ctx = + clutter_backend_get_cogl_context (clutter_get_default_backend ()); + + klass->base_pipeline = cogl_pipeline_new (ctx); + + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, + colorize_glsl_declarations, + colorize_glsl_source); + cogl_pipeline_add_snippet (klass->base_pipeline, snippet); + cogl_object_unref (snippet); + + cogl_pipeline_set_layer_null_texture (klass->base_pipeline, + 0, /* layer number */ + COGL_TEXTURE_TYPE_2D); + } + + self->pipeline = cogl_pipeline_copy (klass->base_pipeline); + + self->tint_uniform = + cogl_pipeline_get_uniform_location (self->pipeline, "tint"); + + self->tint = default_tint; + + update_tint_uniform (self); +} + +/** + * clutter_colorize_effect_new: + * @tint: the color to be used + * + * Creates a new #ClutterColorizeEffect to be used with + * clutter_actor_add_effect() + * + * Return value: the newly created #ClutterColorizeEffect or %NULL + * + * Since: 1.4 + */ +ClutterEffect * +clutter_colorize_effect_new (const ClutterColor *tint) +{ + return g_object_new (CLUTTER_TYPE_COLORIZE_EFFECT, + "tint", tint, + NULL); +} + +/** + * clutter_colorize_effect_set_tint: + * @effect: a #ClutterColorizeEffect + * @tint: the color to be used + * + * Sets the tint to be used when colorizing + * + * Since: 1.4 + */ +void +clutter_colorize_effect_set_tint (ClutterColorizeEffect *effect, + const ClutterColor *tint) +{ + g_return_if_fail (CLUTTER_IS_COLORIZE_EFFECT (effect)); + + effect->tint = *tint; + + update_tint_uniform (effect); + + clutter_effect_queue_repaint (CLUTTER_EFFECT (effect)); + + g_object_notify_by_pspec (G_OBJECT (effect), obj_props[PROP_TINT]); +} + +/** + * clutter_colorize_effect_get_tint: + * @effect: a #ClutterColorizeEffect + * @tint: (out caller-allocates): return location for the color used + * + * Retrieves the tint used by @effect + * + * Since: 1.4 + */ +void +clutter_colorize_effect_get_tint (ClutterColorizeEffect *effect, + ClutterColor *tint) +{ + g_return_if_fail (CLUTTER_IS_COLORIZE_EFFECT (effect)); + g_return_if_fail (tint != NULL); + + *tint = effect->tint; +} diff --git a/clutter/clutter/clutter-colorize-effect.h b/clutter/clutter/clutter-colorize-effect.h new file mode 100644 index 0000000..f8f8436 --- /dev/null +++ b/clutter/clutter/clutter-colorize-effect.h @@ -0,0 +1,67 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_COLORIZE_EFFECT_H__ +#define __CLUTTER_COLORIZE_EFFECT_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_COLORIZE_EFFECT (clutter_colorize_effect_get_type ()) +#define CLUTTER_COLORIZE_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_COLORIZE_EFFECT, ClutterColorizeEffect)) +#define CLUTTER_IS_COLORIZE_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_COLORIZE_EFFECT)) + +/** + * ClutterColorizeEffect: + * + * #ClutterColorizeEffect is an opaque structure + * whose members cannot be directly accessed + * + * Since: 1.4 + */ +typedef struct _ClutterColorizeEffect ClutterColorizeEffect; +typedef struct _ClutterColorizeEffectClass ClutterColorizeEffectClass; + +CLUTTER_AVAILABLE_IN_1_4 +GType clutter_colorize_effect_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_4 +ClutterEffect *clutter_colorize_effect_new (const ClutterColor *tint); + +CLUTTER_AVAILABLE_IN_1_4 +void clutter_colorize_effect_set_tint (ClutterColorizeEffect *effect, + const ClutterColor *tint); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_colorize_effect_get_tint (ClutterColorizeEffect *effect, + ClutterColor *tint); + +G_END_DECLS + +#endif /* __CLUTTER_COLORIZE_EFFECT_H__ */ diff --git a/clutter/clutter/clutter-config.h.in b/clutter/clutter/clutter-config.h.in new file mode 100644 index 0000000..0aeadd2 --- /dev/null +++ b/clutter/clutter/clutter-config.h.in @@ -0,0 +1,16 @@ +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_CONFIG_H__ +#define __CLUTTER_CONFIG_H__ + +#include + +G_BEGIN_DECLS + +@CLUTTER_CONFIG_DEFINES@ + +G_END_DECLS + +#endif /* __CLUTTER_CONFIG_H__ */ diff --git a/clutter/clutter/clutter-constraint-private.h b/clutter/clutter/clutter-constraint-private.h new file mode 100644 index 0000000..2bed47b --- /dev/null +++ b/clutter/clutter/clutter-constraint-private.h @@ -0,0 +1,42 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __CLUTTER_CONSTRAINT_PRIVATE_H__ +#define __CLUTTER_CONSTRAINT_PRIVATE_H__ + +#include "clutter-constraint.h" + +G_BEGIN_DECLS + +gboolean clutter_constraint_update_allocation (ClutterConstraint *constraint, + ClutterActor *actor, + ClutterActorBox *allocation); + +void clutter_constraint_update_preferred_size (ClutterConstraint *constraint, + ClutterActor *actor, + ClutterOrientation direction, + float for_size, + float *minimum_size, + float *natural_size); + +G_END_DECLS + +#endif /* __CLUTTER_CONSTRAINT_PRIVATE_H__ */ diff --git a/clutter/clutter/clutter-constraint.c b/clutter/clutter/clutter-constraint.c new file mode 100644 index 0000000..c3d3f7d --- /dev/null +++ b/clutter/clutter/clutter-constraint.c @@ -0,0 +1,243 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-constraint + * @Title: ClutterConstraint + * @Short_Description: Abstract class for constraints on position or size + * @See_Also: #ClutterAction + * + * #ClutterConstraint is a base abstract class for modifiers of a #ClutterActor + * position or size. + * + * A #ClutterConstraint sub-class should contain the logic for modifying + * the position or size of the #ClutterActor to which it is applied, by + * updating the actor's allocation. Each #ClutterConstraint can change the + * allocation of the actor to which they are applied by overriding the + * #ClutterConstraintClass.update_allocation() virtual function. + * + * #ClutterConstraint is available since Clutter 1.4 + * + * ## Using Constraints + * + * Constraints can be used with fixed layout managers, like + * #ClutterFixedLayout, or with actors implicitly using a fixed layout + * manager, like #ClutterGroup and #ClutterStage. + * + * Constraints provide a way to build user interfaces by using + * relations between #ClutterActors, without explicit fixed + * positioning and sizing, similarly to how fluid layout managers like + * #ClutterBoxLayout and #ClutterTableLayout lay out their children. + * + * Constraints are attached to a #ClutterActor, and are available + * for inspection using clutter_actor_get_constraints(). + * + * Clutter provides different implementation of the #ClutterConstraint + * abstract class, for instance: + * + * - #ClutterAlignConstraint, a constraint that can be used to align + * an actor to another one on either the horizontal or the vertical + * axis, using a normalized value between 0 and 1. + * - #ClutterBindConstraint, a constraint binds the X, Y, width or height + * of an actor to the corresponding position or size of a source actor, + * with or without an offset. + * - #ClutterSnapConstraint, a constraint that "snaps" together the edges + * of two #ClutterActors; if an actor uses two constraints on both its + * horizontal or vertical edges then it can also expand to fit the empty + * space. + * + * The [constraints example](https://git.gnome.org/browse/clutter/tree/examples/constraints.c?h=clutter-1.18) + * uses various types of #ClutterConstraints to lay out three actors on a + * resizable stage. Only the central actor has an explicit size, and no + * actor has an explicit position. + * + * - The #ClutterActor with #ClutterActor:name `layerA` is explicitly + * sized to 100 pixels by 25 pixels, and it's added to the #ClutterStage + * - two #ClutterAlignConstraints are used to anchor `layerA` to the + * center of the stage, by using 0.5 as the alignment #ClutterAlignConstraint:factor on + * both the X and Y axis + * - the #ClutterActor with #ClutterActor:name `layerB` is added to the + * #ClutterStage with no explicit size + * - the #ClutterActor:x and #ClutterActor:width of `layerB` are bound + * to the same properties of `layerA` using two #ClutterBindConstraint + * objects, thus keeping `layerB` aligned to `layerA` + * - the top edge of `layerB` is snapped together with the bottom edge + * of `layerA`; the bottom edge of `layerB` is also snapped together with + * the bottom edge of the #ClutterStage; an offset is given to the two + * #ClutterSnapConstraintss to allow for some padding; since `layerB` is + * snapped between two different #ClutterActors, its height is stretched + * to match the gap + * - the #ClutterActor with #ClutterActor:name `layerC` mirrors `layerB`, + * snapping the top edge of the #ClutterStage to the top edge of `layerC` + * and the top edge of `layerA` to the bottom edge of `layerC` + * + * You can try resizing interactively the #ClutterStage and verify + * that the three #ClutterActors maintain the same position and + * size relative to each other, and to the #ClutterStage. + * + * It is important to note that Clutter does not avoid loops or + * competing constraints; if two or more #ClutterConstraints + * are operating on the same positional or dimensional attributes of an + * actor, or if the constraints on two different actors depend on each + * other, then the behavior is undefined. + * + * ## Implementing a ClutterConstraint + * + * Creating a sub-class of #ClutterConstraint requires the + * implementation of the #ClutterConstraintClass.update_allocation() + * virtual function. + * + * The `update_allocation()` virtual function is called during the + * allocation sequence of a #ClutterActor, and allows any #ClutterConstraint + * attached to that actor to modify the allocation before it is passed to + * the actor's #ClutterActorClass.allocate() implementation. + * + * The #ClutterActorBox passed to the `update_allocation()` implementation + * contains the original allocation of the #ClutterActor, plus the eventual + * modifications applied by the other #ClutterConstraints, in the same order + * the constraints have been applied to the actor. + * + * It is not necessary for a #ClutterConstraint sub-class to chain + * up to the parent's implementation. + * + * If a #ClutterConstraint is parametrized - i.e. if it contains + * properties that affect the way the constraint is implemented - it should + * call clutter_actor_queue_relayout() on the actor to which it is attached + * to whenever any parameter is changed. The actor to which it is attached + * can be recovered at any point using clutter_actor_meta_get_actor(). + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#include "clutter-constraint-private.h" + +#include "clutter-actor.h" +#include "clutter-actor-meta-private.h" +#include "clutter-private.h" + +G_DEFINE_ABSTRACT_TYPE (ClutterConstraint, + clutter_constraint, + CLUTTER_TYPE_ACTOR_META); + +static void +constraint_update_allocation (ClutterConstraint *constraint, + ClutterActor *actor, + ClutterActorBox *allocation) +{ +} + +static void +constraint_update_preferred_size (ClutterConstraint *constraint, + ClutterActor *actor, + ClutterOrientation direction, + float for_size, + float *minimum_size, + float *natural_size) +{ +} + +static void +clutter_constraint_notify (GObject *gobject, + GParamSpec *pspec) +{ + if (strcmp (pspec->name, "enabled") == 0) + { + ClutterActorMeta *meta = CLUTTER_ACTOR_META (gobject); + ClutterActor *actor = clutter_actor_meta_get_actor (meta); + + if (actor != NULL) + clutter_actor_queue_relayout (actor); + } + + if (G_OBJECT_CLASS (clutter_constraint_parent_class)->notify != NULL) + G_OBJECT_CLASS (clutter_constraint_parent_class)->notify (gobject, pspec); +} + +static void +clutter_constraint_class_init (ClutterConstraintClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->notify = clutter_constraint_notify; + + klass->update_allocation = constraint_update_allocation; + klass->update_preferred_size = constraint_update_preferred_size; +} + +static void +clutter_constraint_init (ClutterConstraint *self) +{ +} + +/*< private > + * clutter_constraint_update_allocation: + * @constraint: a #ClutterConstraint + * @actor: a #ClutterActor + * @allocation: (inout): the allocation to modify + * + * Asks the @constraint to update the @allocation of a #ClutterActor. + * + * Returns: %TRUE if the allocation was updated + */ +gboolean +clutter_constraint_update_allocation (ClutterConstraint *constraint, + ClutterActor *actor, + ClutterActorBox *allocation) +{ + ClutterActorBox old_alloc; + + g_return_val_if_fail (CLUTTER_IS_CONSTRAINT (constraint), FALSE); + g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), FALSE); + g_return_val_if_fail (allocation != NULL, FALSE); + + old_alloc = *allocation; + + CLUTTER_CONSTRAINT_GET_CLASS (constraint)->update_allocation (constraint, + actor, + allocation); + + return !clutter_actor_box_equal (allocation, &old_alloc); +} + +void +clutter_constraint_update_preferred_size (ClutterConstraint *constraint, + ClutterActor *actor, + ClutterOrientation direction, + float for_size, + float *minimum_size, + float *natural_size) +{ + g_return_if_fail (CLUTTER_IS_CONSTRAINT (constraint)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + CLUTTER_CONSTRAINT_GET_CLASS (constraint)->update_preferred_size (constraint, actor, + direction, + for_size, + minimum_size, + natural_size); +} diff --git a/clutter/clutter/clutter-constraint.h b/clutter/clutter/clutter-constraint.h new file mode 100644 index 0000000..aba07f6 --- /dev/null +++ b/clutter/clutter/clutter-constraint.h @@ -0,0 +1,129 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_CONSTRAINT_H__ +#define __CLUTTER_CONSTRAINT_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_CONSTRAINT (clutter_constraint_get_type ()) +#define CLUTTER_CONSTRAINT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_CONSTRAINT, ClutterConstraint)) +#define CLUTTER_IS_CONSTRAINT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_CONSTRAINT)) +#define CLUTTER_CONSTRAINT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_CONSTRAINT, ClutterConstraintClass)) +#define CLUTTER_IS_CONSTRAINT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_CONSTRAINT)) +#define CLUTTER_CONSTRAINT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_CONSTRAINT, ClutterConstraintClass)) + +typedef struct _ClutterConstraintClass ClutterConstraintClass; + +/** + * ClutterConstraint: + * + * The #ClutterConstraint structure contains only + * private data and should be accessed using the provided API + * + * Since: 1.4 + */ +struct _ClutterConstraint +{ + /*< private >*/ + ClutterActorMeta parent_instance; +}; + +/** + * ClutterConstraintClass: + * @update_allocation: virtual function used to update the allocation + * of the #ClutterActor using the #ClutterConstraint + * @update_preferred_size: virtual function used to update the preferred + * size of the #ClutterActor using the #ClutterConstraint; optional, + * since 1.22 + * + * The #ClutterConstraintClass structure contains + * only private data + * + * Since: 1.4 + */ +struct _ClutterConstraintClass +{ + /*< private >*/ + ClutterActorMetaClass parent_class; + + /*< public >*/ + void (* update_allocation) (ClutterConstraint *constraint, + ClutterActor *actor, + ClutterActorBox *allocation); + + void (* update_preferred_size) (ClutterConstraint *constraint, + ClutterActor *actor, + ClutterOrientation direction, + float for_size, + float *minimum_size, + float *natural_size); + + /*< private >*/ + void (* _clutter_constraint1) (void); + void (* _clutter_constraint2) (void); + void (* _clutter_constraint3) (void); + void (* _clutter_constraint4) (void); + void (* _clutter_constraint5) (void); + void (* _clutter_constraint6) (void); + void (* _clutter_constraint7) (void); +}; + +CLUTTER_AVAILABLE_IN_1_4 +GType clutter_constraint_get_type (void) G_GNUC_CONST; + +/* ClutterActor API */ +CLUTTER_AVAILABLE_IN_1_4 +void clutter_actor_add_constraint (ClutterActor *self, + ClutterConstraint *constraint); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_actor_add_constraint_with_name (ClutterActor *self, + const gchar *name, + ClutterConstraint *constraint); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_actor_remove_constraint (ClutterActor *self, + ClutterConstraint *constraint); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_actor_remove_constraint_by_name (ClutterActor *self, + const gchar *name); +CLUTTER_AVAILABLE_IN_1_4 +GList * clutter_actor_get_constraints (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_4 +ClutterConstraint *clutter_actor_get_constraint (ClutterActor *self, + const gchar *name); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_actor_clear_constraints (ClutterActor *self); + +CLUTTER_AVAILABLE_IN_1_10 +gboolean clutter_actor_has_constraints (ClutterActor *self); + +G_END_DECLS + +#endif /* __CLUTTER_CONSTRAINT_H__ */ diff --git a/clutter/clutter/clutter-container.c b/clutter/clutter/clutter-container.c new file mode 100644 index 0000000..81fe4dc --- /dev/null +++ b/clutter/clutter/clutter-container.c @@ -0,0 +1,1450 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + * + * ClutterContainer: Generic actor container interface. + * Author: Emmanuele Bassi + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include +#include +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include "deprecated/clutter-container.h" + +#include "clutter-actor-private.h" +#include "clutter-child-meta.h" +#include "clutter-debug.h" +#include "clutter-main.h" +#include "clutter-marshal.h" +#include "clutter-private.h" +#include "clutter-enum-types.h" + +#define CLUTTER_CONTAINER_WARN_NOT_IMPLEMENTED(container,vfunc) \ + G_STMT_START { \ + g_warning ("Container of type '%s' does not implement " \ + "the required ClutterContainer::%s virtual " \ + "function.", \ + G_OBJECT_TYPE_NAME ((container)), \ + (vfunc)); \ + } G_STMT_END + +#define CLUTTER_CONTAINER_NOTE_NOT_IMPLEMENTED(container,vfunc) \ + G_STMT_START { \ + CLUTTER_NOTE (ACTOR, "Container of type '%s' does not " \ + "implement the ClutterContainer::%s " \ + "virtual function.", \ + G_OBJECT_TYPE_NAME ((container)), \ + (vfunc)); \ + } G_STMT_END + +/** + * SECTION:clutter-container + * @short_description: An interface for container actors + * + * #ClutterContainer is an interface implemented by #ClutterActor, and + * it provides some common API for notifying when a child actor is added + * or removed, as well as the infrastructure for accessing child properties + * through #ClutterChildMeta. + * + * Until Clutter 1.10, the #ClutterContainer interface was also the public + * API for implementing container actors; this part of the interface has + * been deprecated: #ClutterContainer has a default implementation which + * defers to #ClutterActor the child addition and removal, as well as the + * iteration. See the documentation of #ClutterContainerIface for the list + * of virtual functions that should be overridden. + */ + +enum +{ + ACTOR_ADDED, + ACTOR_REMOVED, + CHILD_NOTIFY, + + LAST_SIGNAL +}; + +static guint container_signals[LAST_SIGNAL] = { 0, }; +static GQuark quark_child_meta = 0; + +static ClutterChildMeta *get_child_meta (ClutterContainer *container, + ClutterActor *actor); +static void create_child_meta (ClutterContainer *container, + ClutterActor *actor); +static void destroy_child_meta (ClutterContainer *container, + ClutterActor *actor); +static void child_notify (ClutterContainer *container, + ClutterActor *child, + GParamSpec *pspec); + +typedef ClutterContainerIface ClutterContainerInterface; + +G_DEFINE_INTERFACE (ClutterContainer, clutter_container, G_TYPE_OBJECT); + +static void +container_real_add (ClutterContainer *container, + ClutterActor *actor) +{ + clutter_actor_add_child (CLUTTER_ACTOR (container), actor); +} + +static void +container_real_remove (ClutterContainer *container, + ClutterActor *actor) +{ + clutter_actor_remove_child (CLUTTER_ACTOR (container), actor); +} + +typedef struct { + ClutterCallback callback; + gpointer data; +} ForeachClosure; + +static gboolean +foreach_cb (ClutterActor *actor, + gpointer data) +{ + ForeachClosure *clos = data; + + clos->callback (actor, clos->data); + + return TRUE; +} + +static void +container_real_foreach (ClutterContainer *container, + ClutterCallback callback, + gpointer user_data) +{ + ForeachClosure clos; + + clos.callback = callback; + clos.data = user_data; + + _clutter_actor_foreach_child (CLUTTER_ACTOR (container), + foreach_cb, + &clos); +} + +static void +container_real_raise (ClutterContainer *container, + ClutterActor *child, + ClutterActor *sibling) +{ + ClutterActor *self = CLUTTER_ACTOR (container); + + clutter_actor_set_child_above_sibling (self, child, sibling); +} + +static void +container_real_lower (ClutterContainer *container, + ClutterActor *child, + ClutterActor *sibling) +{ + ClutterActor *self = CLUTTER_ACTOR (container); + + clutter_actor_set_child_below_sibling (self, child, sibling); +} + +static void +container_real_sort_depth_order (ClutterContainer *container) +{ +} + +static void +clutter_container_default_init (ClutterContainerInterface *iface) +{ + GType iface_type = G_TYPE_FROM_INTERFACE (iface); + + quark_child_meta = + g_quark_from_static_string ("clutter-container-child-data"); + + /** + * ClutterContainer::actor-added: + * @container: the actor which received the signal + * @actor: the new child that has been added to @container + * + * The ::actor-added signal is emitted each time an actor + * has been added to @container. + * + * Since: 0.4 + */ + container_signals[ACTOR_ADDED] = + g_signal_new (I_("actor-added"), + iface_type, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ClutterContainerIface, actor_added), + NULL, NULL, + _clutter_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CLUTTER_TYPE_ACTOR); + /** + * ClutterContainer::actor-removed: + * @container: the actor which received the signal + * @actor: the child that has been removed from @container + * + * The ::actor-removed signal is emitted each time an actor + * is removed from @container. + * + * Since: 0.4 + */ + container_signals[ACTOR_REMOVED] = + g_signal_new (I_("actor-removed"), + iface_type, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ClutterContainerIface, actor_removed), + NULL, NULL, + _clutter_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CLUTTER_TYPE_ACTOR); + + /** + * ClutterContainer::child-notify: + * @container: the container which received the signal + * @actor: the child that has had a property set + * @pspec: (type GParamSpec): the #GParamSpec of the property set + * + * The ::child-notify signal is emitted each time a property is + * being set through the clutter_container_child_set() and + * clutter_container_child_set_property() calls. + * + * Since: 0.8 + */ + container_signals[CHILD_NOTIFY] = + g_signal_new (I_("child-notify"), + iface_type, + G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED, + G_STRUCT_OFFSET (ClutterContainerIface, child_notify), + NULL, NULL, + _clutter_marshal_VOID__OBJECT_PARAM, + G_TYPE_NONE, 2, + CLUTTER_TYPE_ACTOR, G_TYPE_PARAM); + + iface->add = container_real_add; + iface->remove = container_real_remove; + iface->foreach = container_real_foreach; + iface->raise = container_real_raise; + iface->lower = container_real_lower; + iface->sort_depth_order = container_real_sort_depth_order; + + iface->child_meta_type = G_TYPE_INVALID; + iface->create_child_meta = create_child_meta; + iface->destroy_child_meta = destroy_child_meta; + iface->get_child_meta = get_child_meta; + iface->child_notify = child_notify; +} + +static inline void +container_add_actor (ClutterContainer *container, + ClutterActor *actor) +{ + ClutterActor *parent; + + parent = clutter_actor_get_parent (actor); + if (G_UNLIKELY (parent != NULL)) + { + g_warning ("Attempting to add actor of type '%s' to a " + "container of type '%s', but the actor has " + "already a parent of type '%s'.", + g_type_name (G_OBJECT_TYPE (actor)), + g_type_name (G_OBJECT_TYPE (container)), + g_type_name (G_OBJECT_TYPE (parent))); + return; + } + + clutter_container_create_child_meta (container, actor); + +#ifdef CLUTTER_ENABLE_DEBUG + if (G_UNLIKELY (_clutter_diagnostic_enabled ())) + { + ClutterContainerIface *iface = CLUTTER_CONTAINER_GET_IFACE (container); + + if (iface->add != container_real_add) + _clutter_diagnostic_message ("The ClutterContainer::add() virtual " + "function has been deprecated and it " + "should not be overridden by newly " + "written code"); + } +#endif /* CLUTTER_ENABLE_DEBUG */ + + CLUTTER_CONTAINER_GET_IFACE (container)->add (container, actor); +} + +static inline void +container_remove_actor (ClutterContainer *container, + ClutterActor *actor) +{ + ClutterActor *parent; + + parent = clutter_actor_get_parent (actor); + if (parent != CLUTTER_ACTOR (container)) + { + g_warning ("Attempting to remove actor of type '%s' from " + "group of class '%s', but the container is not " + "the actor's parent.", + g_type_name (G_OBJECT_TYPE (actor)), + g_type_name (G_OBJECT_TYPE (container))); + return; + } + + clutter_container_destroy_child_meta (container, actor); + +#ifdef CLUTTER_ENABLE_DEBUG + if (G_UNLIKELY (_clutter_diagnostic_enabled ())) + { + ClutterContainerIface *iface = CLUTTER_CONTAINER_GET_IFACE (container); + + if (iface->remove != container_real_remove) + _clutter_diagnostic_message ("The ClutterContainer::remove() virtual " + "function has been deprecated and it " + "should not be overridden by newly " + "written code"); + } +#endif /* CLUTTER_ENABLE_DEBUG */ + + CLUTTER_CONTAINER_GET_IFACE (container)->remove (container, actor); +} + +static inline void +container_add_valist (ClutterContainer *container, + ClutterActor *first_actor, + va_list args) +{ + ClutterActor *actor = first_actor; + + while (actor != NULL) + { + container_add_actor (container, actor); + actor = va_arg (args, ClutterActor *); + } +} + +static inline void +container_remove_valist (ClutterContainer *container, + ClutterActor *first_actor, + va_list args) +{ + ClutterActor *actor = first_actor; + + while (actor != NULL) + { + container_remove_actor (container, actor); + actor = va_arg (args, ClutterActor *); + } +} + +/** + * clutter_container_add: (skip) + * @container: a #ClutterContainer + * @first_actor: the first #ClutterActor to add + * @...: %NULL terminated list of actors to add + * + * Adds a list of #ClutterActors to @container. Each time and + * actor is added, the "actor-added" signal is emitted. Each actor should + * be parented to @container, which takes a reference on the actor. You + * cannot add a #ClutterActor to more than one #ClutterContainer. + * + * This function will call #ClutterContainerIface.add(), which is a + * deprecated virtual function. The default implementation will + * call clutter_actor_add_child(). + * + * Since: 0.4 + * + * Deprecated: 1.10: Use clutter_actor_add_child() instead. + */ +void +clutter_container_add (ClutterContainer *container, + ClutterActor *first_actor, + ...) +{ + va_list args; + + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + g_return_if_fail (CLUTTER_IS_ACTOR (first_actor)); + + va_start (args, first_actor); + container_add_valist (container, first_actor, args); + va_end (args); +} + +/** + * clutter_container_add_actor: (virtual add) + * @container: a #ClutterContainer + * @actor: the first #ClutterActor to add + * + * Adds a #ClutterActor to @container. This function will emit the + * "actor-added" signal. The actor should be parented to + * @container. You cannot add a #ClutterActor to more than one + * #ClutterContainer. + * + * This function will call #ClutterContainerIface.add(), which is a + * deprecated virtual function. The default implementation will + * call clutter_actor_add_child(). + * + * Since: 0.4 + * + * Deprecated: 1.10: Use clutter_actor_add_child() instead. + */ +void +clutter_container_add_actor (ClutterContainer *container, + ClutterActor *actor) +{ + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + container_add_actor (container, actor); +} + +/** + * clutter_container_add_valist: (skip) + * @container: a #ClutterContainer + * @first_actor: the first #ClutterActor to add + * @var_args: list of actors to add, followed by %NULL + * + * Alternative va_list version of clutter_container_add(). + * + * This function will call #ClutterContainerIface.add(), which is a + * deprecated virtual function. The default implementation will + * call clutter_actor_add_child(). + * + * Since: 0.4 + * + * Deprecated: 1.10: Use clutter_actor_add_child() instead. + */ +void +clutter_container_add_valist (ClutterContainer *container, + ClutterActor *first_actor, + va_list var_args) +{ + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + g_return_if_fail (CLUTTER_IS_ACTOR (first_actor)); + + container_add_valist (container, first_actor, var_args); +} + +/** + * clutter_container_remove: (skip) + * @container: a #ClutterContainer + * @first_actor: first #ClutterActor to remove + * @...: a %NULL-terminated list of actors to remove + * + * Removes a %NULL terminated list of #ClutterActors from + * @container. Each actor should be unparented, so if you want to keep it + * around you must hold a reference to it yourself, using g_object_ref(). + * Each time an actor is removed, the "actor-removed" signal is + * emitted by @container. + * + * This function will call #ClutterContainerIface.remove(), which is a + * deprecated virtual function. The default implementation will call + * clutter_actor_remove_child(). + * + * Since: 0.4 + * + * Deprecated: 1.10: Use clutter_actor_remove_child() instead. + */ +void +clutter_container_remove (ClutterContainer *container, + ClutterActor *first_actor, + ...) +{ + va_list var_args; + + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + g_return_if_fail (CLUTTER_IS_ACTOR (first_actor)); + + va_start (var_args, first_actor); + container_remove_valist (container, first_actor, var_args); + va_end (var_args); +} + +/** + * clutter_container_remove_actor: (virtual remove) + * @container: a #ClutterContainer + * @actor: a #ClutterActor + * + * Removes @actor from @container. The actor should be unparented, so + * if you want to keep it around you must hold a reference to it + * yourself, using g_object_ref(). When the actor has been removed, + * the "actor-removed" signal is emitted by @container. + * + * This function will call #ClutterContainerIface.remove(), which is a + * deprecated virtual function. The default implementation will call + * clutter_actor_remove_child(). + * + * Since: 0.4 + * + * Deprecated: 1.10: Use clutter_actor_remove_child() instead. + */ +void +clutter_container_remove_actor (ClutterContainer *container, + ClutterActor *actor) +{ + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + container_remove_actor (container, actor); +} + +/** + * clutter_container_remove_valist: (skip) + * @container: a #ClutterContainer + * @first_actor: the first #ClutterActor to add + * @var_args: list of actors to remove, followed by %NULL + * + * Alternative va_list version of clutter_container_remove(). + * + * This function will call #ClutterContainerIface.remove(), which is a + * deprecated virtual function. The default implementation will call + * clutter_actor_remove_child(). + * + * Since: 0.4 + * + * Deprecated: 1.10: Use clutter_actor_remove_child() instead. + */ +void +clutter_container_remove_valist (ClutterContainer *container, + ClutterActor *first_actor, + va_list var_args) +{ + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + g_return_if_fail (CLUTTER_IS_ACTOR (first_actor)); + + container_remove_valist (container, first_actor, var_args); +} + +static void +get_children_cb (ClutterActor *child, + gpointer data) +{ + GList **children = data; + + *children = g_list_prepend (*children, child); +} + +/** + * clutter_container_get_children: + * @container: a #ClutterContainer + * + * Retrieves all the children of @container. + * + * Return value: (element-type Clutter.Actor) (transfer container): a list + * of #ClutterActors. Use g_list_free() on the returned + * list when done. + * + * Since: 0.4 + * + * Deprecated: 1.10: Use clutter_actor_get_children() instead. + */ +GList * +clutter_container_get_children (ClutterContainer *container) +{ + GList *retval; + + g_return_val_if_fail (CLUTTER_IS_CONTAINER (container), NULL); + + retval = NULL; + clutter_container_foreach (container, get_children_cb, &retval); + + return g_list_reverse (retval); +} + +/** + * clutter_container_foreach: + * @container: a #ClutterContainer + * @callback: (scope call): 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 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. + * + * This function calls the #ClutterContainerIface.foreach() + * virtual function, which has been deprecated. + * + * Since: 0.4 + * + * Deprecated: 1.10: Use clutter_actor_get_first_child() or + * clutter_actor_get_last_child() to retrieve the beginning of + * the list of children, and clutter_actor_get_next_sibling() + * and clutter_actor_get_previous_sibling() to iterate over it; + * alternatively, use the #ClutterActorIter API. + */ +void +clutter_container_foreach (ClutterContainer *container, + ClutterCallback callback, + gpointer user_data) +{ + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + g_return_if_fail (callback != NULL); + +#ifdef CLUTTER_ENABLE_DEBUG + if (G_UNLIKELY (_clutter_diagnostic_enabled ())) + { + ClutterContainerIface *iface = CLUTTER_CONTAINER_GET_IFACE (container); + + if (iface->foreach != container_real_foreach) + _clutter_diagnostic_message ("The ClutterContainer::foreach() " + "virtual function has been deprecated " + "and it should not be overridden by " + "newly written code"); + } +#endif /* CLUTTER_ENABLE_DEBUG */ + + CLUTTER_CONTAINER_GET_IFACE (container)->foreach (container, + callback, + user_data); +} + +/** + * clutter_container_foreach_with_internals: + * @container: a #ClutterContainer + * @callback: (scope call): 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. + * + * This function calls the #ClutterContainerIface.foreach_with_internals() + * virtual function, which has been deprecated. + * + * Since: 1.0 + * + * Deprecated: 1.10: See clutter_container_foreach(). + */ +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); + +#ifdef CLUTTER_ENABLE_DEBUG + if (G_UNLIKELY (_clutter_diagnostic_enabled ())) + { + if (iface->foreach_with_internals != NULL) + _clutter_diagnostic_message ("The ClutterContainer::foreach_with_internals() " + "virtual function has been deprecated " + "and it should not be overridden by " + "newly written code"); + } +#endif /* CLUTTER_ENABLE_DEBUG */ + + 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: (virtual raise) + * @container: a #ClutterContainer + * @actor: the actor to raise + * @sibling: (allow-none): the sibling to raise to, or %NULL to raise + * to the top + * + * Raises @actor to @sibling level, in the depth ordering. + * + * This function calls the #ClutterContainerIface.raise() virtual function, + * which has been deprecated. The default implementation will call + * clutter_actor_set_child_above_sibling(). + * + * Since: 0.6 + * + * Deprecated: 1.10: Use clutter_actor_set_child_above_sibling() instead. + */ +void +clutter_container_raise_child (ClutterContainer *container, + ClutterActor *actor, + ClutterActor *sibling) +{ + ClutterContainerIface *iface; + ClutterActor *self; + + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + g_return_if_fail (sibling == NULL || CLUTTER_IS_ACTOR (sibling)); + + if (actor == sibling) + return; + + self = CLUTTER_ACTOR (container); + + if (clutter_actor_get_parent (actor) != self) + { + g_warning ("Actor of type '%s' is not a child of the container " + "of type '%s'", + g_type_name (G_OBJECT_TYPE (actor)), + g_type_name (G_OBJECT_TYPE (container))); + return; + } + + if (sibling != NULL && + clutter_actor_get_parent (sibling) != self) + { + g_warning ("Actor of type '%s' is not a child of the container " + "of type '%s'", + g_type_name (G_OBJECT_TYPE (sibling)), + g_type_name (G_OBJECT_TYPE (container))); + return; + } + + iface = CLUTTER_CONTAINER_GET_IFACE (container); + +#ifdef CLUTTER_ENABLE_DEBUG + if (G_UNLIKELY (_clutter_diagnostic_enabled ())) + { + if (iface->raise != container_real_raise) + _clutter_diagnostic_message ("The ClutterContainer::raise() " + "virtual function has been deprecated " + "and it should not be overridden by " + "newly written code"); + } +#endif /* CLUTTER_ENABLE_DEBUG */ + + iface->raise (container, actor, sibling); +} + +/** + * clutter_container_lower_child: (virtual lower) + * @container: a #ClutterContainer + * @actor: the actor to raise + * @sibling: (allow-none): the sibling to lower to, or %NULL to lower + * to the bottom + * + * Lowers @actor to @sibling level, in the depth ordering. + * + * This function calls the #ClutterContainerIface.lower() virtual function, + * which has been deprecated. The default implementation will call + * clutter_actor_set_child_below_sibling(). + * + * Since: 0.6 + * + * Deprecated: 1.10: Use clutter_actor_set_child_below_sibling() instead. + */ +void +clutter_container_lower_child (ClutterContainer *container, + ClutterActor *actor, + ClutterActor *sibling) +{ + ClutterContainerIface *iface; + ClutterActor *self; + + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + g_return_if_fail (sibling == NULL || CLUTTER_IS_ACTOR (sibling)); + + if (actor == sibling) + return; + + self = CLUTTER_ACTOR (container); + + if (clutter_actor_get_parent (actor) != self) + { + g_warning ("Actor of type '%s' is not a child of the container " + "of type '%s'", + g_type_name (G_OBJECT_TYPE (actor)), + g_type_name (G_OBJECT_TYPE (container))); + return; + } + + if (sibling != NULL&& + clutter_actor_get_parent (sibling) != self) + { + g_warning ("Actor of type '%s' is not a child of the container " + "of type '%s'", + g_type_name (G_OBJECT_TYPE (sibling)), + g_type_name (G_OBJECT_TYPE (container))); + return; + } + + iface = CLUTTER_CONTAINER_GET_IFACE (container); + +#ifdef CLUTTER_ENABLE_DEBUG + if (G_UNLIKELY (_clutter_diagnostic_enabled ())) + { + if (iface->lower != container_real_lower) + _clutter_diagnostic_message ("The ClutterContainer::lower() " + "virtual function has been deprecated " + "and it should not be overridden by " + "newly written code"); + } +#endif /* CLUTTER_ENABLE_DEBUG */ + + iface->lower (container, actor, sibling); +} + +/** + * clutter_container_sort_depth_order: + * @container: a #ClutterContainer + * + * Sorts a container's children using their depth. This function should not + * be normally used by applications. + * + * Since: 0.6 + * + * Deprecated: 1.10: The #ClutterContainerIface.sort_depth_order() virtual + * function should not be used any more; the default implementation in + * #ClutterContainer does not do anything. + */ +void +clutter_container_sort_depth_order (ClutterContainer *container) +{ + ClutterContainerIface *iface; + + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + + iface = CLUTTER_CONTAINER_GET_IFACE (container); + +#ifdef CLUTTER_ENABLE_DEBUG + if (G_UNLIKELY (_clutter_diagnostic_enabled ())) + { + if (iface->sort_depth_order != container_real_sort_depth_order) + _clutter_diagnostic_message ("The ClutterContainer::sort_depth_order() " + "virtual function has been deprecated " + "and it should not be overridden by " + "newly written code"); + } +#endif /* CLUTTER_ENABLE_DEBUG */ + + iface->sort_depth_order (container); +} + +/** + * clutter_container_find_child_by_name: + * @container: a #ClutterContainer + * @child_name: the name of the requested child. + * + * Finds a child actor of a container by its name. Search recurses + * into any child container. + * + * Return value: (transfer none): The child actor with the requested name, + * or %NULL if no actor with that name was found. + * + * Since: 0.6 + */ +ClutterActor * +clutter_container_find_child_by_name (ClutterContainer *container, + const gchar *child_name) +{ + GList *children; + GList *iter; + ClutterActor *actor = NULL; + + g_return_val_if_fail (CLUTTER_IS_CONTAINER (container), NULL); + g_return_val_if_fail (child_name != NULL, NULL); + + children = clutter_container_get_children (container); + + for (iter = children; iter; iter = g_list_next (iter)) + { + ClutterActor *a; + const gchar *iter_name; + + a = CLUTTER_ACTOR (iter->data); + iter_name = clutter_actor_get_name (a); + + if (iter_name && !strcmp (iter_name, child_name)) + { + actor = a; + break; + } + + if (CLUTTER_IS_CONTAINER (a)) + { + ClutterContainer *c = CLUTTER_CONTAINER (a); + + actor = clutter_container_find_child_by_name (c, child_name); + if (actor) + break; + } + } + + g_list_free (children); + + return actor; +} + +static ClutterChildMeta * +get_child_meta (ClutterContainer *container, + ClutterActor *actor) +{ + ClutterContainerIface *iface = CLUTTER_CONTAINER_GET_IFACE (container); + ClutterChildMeta *meta; + + if (iface->child_meta_type == G_TYPE_INVALID) + return NULL; + + meta = g_object_get_qdata (G_OBJECT (actor), quark_child_meta); + if (meta != NULL && meta->actor == actor) + return meta; + + return NULL; +} + +static void +create_child_meta (ClutterContainer *container, + ClutterActor *actor) +{ + ClutterContainerIface *iface = CLUTTER_CONTAINER_GET_IFACE (container); + ClutterChildMeta *child_meta = NULL; + + if (iface->child_meta_type == G_TYPE_INVALID) + return; + + if (!g_type_is_a (iface->child_meta_type, CLUTTER_TYPE_CHILD_META)) + { + g_warning ("%s: Child data of type '%s' is not a ClutterChildMeta", + G_STRLOC, g_type_name (iface->child_meta_type)); + return; + } + + child_meta = g_object_new (iface->child_meta_type, + "container", container, + "actor", actor, + NULL); + + g_object_set_qdata_full (G_OBJECT (actor), quark_child_meta, + child_meta, + (GDestroyNotify) g_object_unref); +} + +static void +destroy_child_meta (ClutterContainer *container, + ClutterActor *actor) +{ + ClutterContainerIface *iface = CLUTTER_CONTAINER_GET_IFACE (container); + + if (iface->child_meta_type == G_TYPE_INVALID) + return; + + g_object_set_qdata (G_OBJECT (actor), quark_child_meta, NULL); +} + +/** + * clutter_container_get_child_meta: + * @container: a #ClutterContainer + * @actor: a #ClutterActor that is a child of @container. + * + * Retrieves the #ClutterChildMeta which contains the data about the + * @container specific state for @actor. + * + * Return value: (transfer none): the #ClutterChildMeta for the @actor child + * of @container or %NULL if the specifiec actor does not exist or the + * container is not configured to provide #ClutterChildMetas + * + * Since: 0.8 + */ +ClutterChildMeta * +clutter_container_get_child_meta (ClutterContainer *container, + ClutterActor *actor) +{ + ClutterContainerIface *iface = CLUTTER_CONTAINER_GET_IFACE (container); + + if (iface->child_meta_type == G_TYPE_INVALID) + return NULL; + + if (G_LIKELY (iface->get_child_meta)) + return iface->get_child_meta (container, actor); + + return NULL; +} + +/** + * clutter_container_create_child_meta: + * @container: a #ClutterContainer + * @actor: a #ClutterActor + * + * Creates the #ClutterChildMeta wrapping @actor inside the + * @container, if the #ClutterContainerIface::child_meta_type + * class member is not set to %G_TYPE_INVALID. + * + * This function is only useful when adding a #ClutterActor to + * a #ClutterContainer implementation outside of the + * #ClutterContainer::add() virtual function implementation. + * + * Applications should not call this function. + * + * Since: 1.2 + */ +void +clutter_container_create_child_meta (ClutterContainer *container, + ClutterActor *actor) +{ + ClutterContainerIface *iface; + + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + iface = CLUTTER_CONTAINER_GET_IFACE (container); + + if (iface->child_meta_type == G_TYPE_INVALID) + return; + + g_assert (g_type_is_a (iface->child_meta_type, CLUTTER_TYPE_CHILD_META)); + + if (G_LIKELY (iface->create_child_meta)) + iface->create_child_meta (container, actor); +} + +/** + * clutter_container_destroy_child_meta: + * @container: a #ClutterContainer + * @actor: a #ClutterActor + * + * Destroys the #ClutterChildMeta wrapping @actor inside the + * @container, if any. + * + * This function is only useful when removing a #ClutterActor to + * a #ClutterContainer implementation outside of the + * #ClutterContainer::add() virtual function implementation. + * + * Applications should not call this function. + * + * Since: 1.2 + */ +void +clutter_container_destroy_child_meta (ClutterContainer *container, + ClutterActor *actor) +{ + ClutterContainerIface *iface; + + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + iface = CLUTTER_CONTAINER_GET_IFACE (container); + + if (iface->child_meta_type == G_TYPE_INVALID) + return; + + if (G_LIKELY (iface->destroy_child_meta)) + iface->destroy_child_meta (container, actor); +} + +/** + * clutter_container_class_find_child_property: + * @klass: a #GObjectClass implementing the #ClutterContainer interface. + * @property_name: a property name. + * + * Looks up the #GParamSpec for a child property of @klass. + * + * Return value: (transfer none): The #GParamSpec for the property or %NULL + * if no such property exist. + * + * Since: 0.8 + */ +GParamSpec * +clutter_container_class_find_child_property (GObjectClass *klass, + const gchar *property_name) +{ + ClutterContainerIface *iface; + GObjectClass *child_class; + GParamSpec *pspec; + + g_return_val_if_fail (G_IS_OBJECT_CLASS (klass), NULL); + g_return_val_if_fail (property_name != NULL, NULL); + g_return_val_if_fail (g_type_is_a (G_TYPE_FROM_CLASS (klass), + CLUTTER_TYPE_CONTAINER), + NULL); + + iface = g_type_interface_peek (klass, CLUTTER_TYPE_CONTAINER); + g_return_val_if_fail (iface != NULL, NULL); + + if (iface->child_meta_type == G_TYPE_INVALID) + return NULL; + + child_class = g_type_class_ref (iface->child_meta_type); + pspec = g_object_class_find_property (child_class, property_name); + g_type_class_unref (child_class); + + return pspec; +} + +/** + * clutter_container_class_list_child_properties: + * @klass: a #GObjectClass implementing the #ClutterContainer interface. + * @n_properties: return location for length of returned array. + * + * Returns an array of #GParamSpec for all child properties. + * + * Return value: (array length=n_properties) (transfer full): an array + * of #GParamSpecs which should be freed after use. + * + * Since: 0.8 + */ +GParamSpec ** +clutter_container_class_list_child_properties (GObjectClass *klass, + guint *n_properties) +{ + ClutterContainerIface *iface; + GObjectClass *child_class; + GParamSpec **retval; + + g_return_val_if_fail (G_IS_OBJECT_CLASS (klass), NULL); + g_return_val_if_fail (g_type_is_a (G_TYPE_FROM_CLASS (klass), + CLUTTER_TYPE_CONTAINER), + NULL); + + iface = g_type_interface_peek (klass, CLUTTER_TYPE_CONTAINER); + g_return_val_if_fail (iface != NULL, NULL); + + if (iface->child_meta_type == G_TYPE_INVALID) + return NULL; + + child_class = g_type_class_ref (iface->child_meta_type); + retval = g_object_class_list_properties (child_class, n_properties); + g_type_class_unref (child_class); + + return retval; +} + +static void +child_notify (ClutterContainer *container, + ClutterActor *actor, + GParamSpec *pspec) +{ +} + +static inline void +container_set_child_property (ClutterContainer *container, + ClutterActor *actor, + const GValue *value, + GParamSpec *pspec) +{ + ClutterChildMeta *data; + + data = clutter_container_get_child_meta (container, actor); + g_object_set_property (G_OBJECT (data), pspec->name, value); + + g_signal_emit (container, container_signals[CHILD_NOTIFY], + (pspec->flags & G_PARAM_STATIC_NAME) + ? g_quark_from_static_string (pspec->name) + : g_quark_from_string (pspec->name), + actor, pspec); +} + +/** + * clutter_container_child_set_property: + * @container: a #ClutterContainer + * @child: a #ClutterActor that is a child of @container. + * @property: the name of the property to set. + * @value: the value. + * + * Sets a container-specific property on a child of @container. + * + * Since: 0.8 + */ +void +clutter_container_child_set_property (ClutterContainer *container, + ClutterActor *child, + const gchar *property, + const GValue *value) +{ + GObjectClass *klass; + GParamSpec *pspec; + + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + g_return_if_fail (CLUTTER_IS_ACTOR (child)); + g_return_if_fail (property != NULL); + g_return_if_fail (value != NULL); + + klass = G_OBJECT_GET_CLASS (container); + + pspec = clutter_container_class_find_child_property (klass, property); + if (!pspec) + { + g_warning ("%s: Containers of type '%s' have no child " + "property named '%s'", + G_STRLOC, G_OBJECT_TYPE_NAME (container), property); + return; + } + + if (!(pspec->flags & G_PARAM_WRITABLE)) + { + g_warning ("%s: Child property '%s' of the container '%s' " + "is not writable", + G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (container)); + return; + } + + container_set_child_property (container, child, value, pspec); +} + +/** + * clutter_container_child_set: + * @container: a #ClutterContainer + * @actor: a #ClutterActor that is a child of @container. + * @first_prop: name of the first property to be set. + * @...: value for the first property, followed optionally by more name/value + * pairs terminated with NULL. + * + * Sets container specific properties on the child of a container. + * + * Since: 0.8 + */ +void +clutter_container_child_set (ClutterContainer *container, + ClutterActor *actor, + const gchar *first_prop, + ...) +{ + GObjectClass *klass; + const gchar *name; + va_list var_args; + + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + klass = G_OBJECT_GET_CLASS (container); + + va_start (var_args, first_prop); + + name = first_prop; + while (name) + { + GValue value = G_VALUE_INIT; + gchar *error = NULL; + GParamSpec *pspec; + + pspec = clutter_container_class_find_child_property (klass, name); + if (!pspec) + { + g_warning ("%s: Containers of type '%s' have no child " + "property named '%s'", + G_STRLOC, G_OBJECT_TYPE_NAME (container), name); + break; + } + + if (!(pspec->flags & G_PARAM_WRITABLE)) + { + g_warning ("%s: Child property '%s' of the container '%s' " + "is not writable", + G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (container)); + break; + } + + G_VALUE_COLLECT_INIT (&value, G_PARAM_SPEC_VALUE_TYPE (pspec), + var_args, 0, + &error); + + if (error) + { + /* we intentionally leak the GValue because it might + * be in an undefined state and calling g_value_unset() + * on it might crash + */ + g_warning ("%s: %s", G_STRLOC, error); + g_free (error); + break; + } + + container_set_child_property (container, actor, &value, pspec); + + g_value_unset (&value); + + name = va_arg (var_args, gchar*); + } + + va_end (var_args); +} + +static inline void +container_get_child_property (ClutterContainer *container, + ClutterActor *actor, + GValue *value, + GParamSpec *pspec) +{ + ClutterChildMeta *data; + + data = clutter_container_get_child_meta (container, actor); + g_object_get_property (G_OBJECT (data), pspec->name, value); +} + +/** + * clutter_container_child_get_property: + * @container: a #ClutterContainer + * @child: a #ClutterActor that is a child of @container. + * @property: the name of the property to set. + * @value: the value. + * + * Gets a container specific property of a child of @container, In general, + * a copy is made of the property contents and the caller is responsible for + * freeing the memory by calling g_value_unset(). + * + * Note that clutter_container_child_set_property() is really intended for + * language bindings, clutter_container_child_set() is much more convenient + * for C programming. + * + * Since: 0.8 + */ +void +clutter_container_child_get_property (ClutterContainer *container, + ClutterActor *child, + const gchar *property, + GValue *value) +{ + GObjectClass *klass; + GParamSpec *pspec; + + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + g_return_if_fail (CLUTTER_IS_ACTOR (child)); + g_return_if_fail (property != NULL); + g_return_if_fail (value != NULL); + + klass = G_OBJECT_GET_CLASS (container); + + pspec = clutter_container_class_find_child_property (klass, property); + if (!pspec) + { + g_warning ("%s: Containers of type '%s' have no child " + "property named '%s'", + G_STRLOC, G_OBJECT_TYPE_NAME (container), property); + return; + } + + if (!(pspec->flags & G_PARAM_READABLE)) + { + g_warning ("%s: Child property '%s' of the container '%s' " + "is not writable", + G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (container)); + return; + } + + container_get_child_property (container, child, value, pspec); +} + + +/** + * clutter_container_child_get: + * @container: a #ClutterContainer + * @actor: a #ClutterActor that is a child of @container. + * @first_prop: name of the first property to be set. + * @...: value for the first property, followed optionally by more name/value + * pairs terminated with NULL. + * + * Gets @container specific properties of an actor. + * + * In general, a copy is made of the property contents and the caller is + * responsible for freeing the memory in the appropriate manner for the type, for + * instance by calling g_free() or g_object_unref(). + * + * Since: 0.8 + */ +void +clutter_container_child_get (ClutterContainer *container, + ClutterActor *actor, + const gchar *first_prop, + ...) +{ + GObjectClass *klass; + const gchar *name; + va_list var_args; + + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + klass = G_OBJECT_GET_CLASS (container); + + va_start (var_args, first_prop); + + name = first_prop; + while (name) + { + GValue value = G_VALUE_INIT; + gchar *error = NULL; + GParamSpec *pspec; + + pspec = clutter_container_class_find_child_property (klass, name); + if (!pspec) + { + g_warning ("%s: container '%s' has no child property named '%s'", + G_STRLOC, G_OBJECT_TYPE_NAME (container), name); + break; + } + + if (!(pspec->flags & G_PARAM_READABLE)) + { + g_warning ("%s: child property '%s' of container '%s' is not readable", + G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (container)); + break; + } + + g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec)); + + container_get_child_property (container, actor, &value, pspec); + + G_VALUE_LCOPY (&value, var_args, 0, &error); + if (error) + { + g_warning ("%s: %s", G_STRLOC, error); + g_free (error); + g_value_unset (&value); + break; + } + + g_value_unset (&value); + + name = va_arg (var_args, gchar*); + } + + va_end (var_args); +} + +/** + * clutter_container_child_notify: + * @container: a #ClutterContainer + * @child: a #ClutterActor + * @pspec: a #GParamSpec + * + * Calls the #ClutterContainerIface.child_notify() virtual function + * of #ClutterContainer. The default implementation will emit the + * #ClutterContainer::child-notify signal. + * + * Since: 1.6 + */ +void +clutter_container_child_notify (ClutterContainer *container, + ClutterActor *child, + GParamSpec *pspec) +{ + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + g_return_if_fail (CLUTTER_IS_ACTOR (child)); + g_return_if_fail (pspec != NULL); + + g_return_if_fail (clutter_actor_get_parent (child) == CLUTTER_ACTOR (container)); + + CLUTTER_CONTAINER_GET_IFACE (container)->child_notify (container, + child, + pspec); +} diff --git a/clutter/clutter/clutter-container.h b/clutter/clutter/clutter-container.h new file mode 100644 index 0000000..0fc3cef --- /dev/null +++ b/clutter/clutter/clutter-container.h @@ -0,0 +1,196 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * ClutterContainer: Generic actor container interface. + * Author: Emmanuele Bassi + */ + +#ifndef __CLUTTER_CONTAINER_H__ +#define __CLUTTER_CONTAINER_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_CONTAINER (clutter_container_get_type ()) +#define CLUTTER_CONTAINER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_CONTAINER, ClutterContainer)) +#define CLUTTER_IS_CONTAINER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_CONTAINER)) +#define CLUTTER_CONTAINER_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), CLUTTER_TYPE_CONTAINER, ClutterContainerIface)) + +typedef struct _ClutterContainerIface ClutterContainerIface; + +/** + * ClutterContainer: + * + * #ClutterContainer is an opaque structure whose members cannot be directly + * accessed + * + * Since: 0.4 + */ + +/** + * ClutterContainerIface: + * @add: virtual function for adding an actor to the container. This virtual + * function is deprecated, and it should not be overridden. + * @remove: virtual function for removing an actor from the container. This + * virtual function is deprecated, and it should not be overridden. + * @foreach: virtual function for iterating over the container's children. + * This virtual function is deprecated, and it should not be overridden. + * @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. This virtual function is deprecated, and it should + * not be overridden. + * @raise: virtual function for raising a child. This virtual function is + * deprecated and it should not be overridden. + * @lower: virtual function for lowering a child. This virtual function is + * deprecated and it should not be overridden. + * @sort_depth_order: virtual function for sorting the children of a + * container depending on their depth. This virtual function is deprecated + * and it should not be overridden. + * @child_meta_type: The GType used for storing auxiliary information about + * each of the containers children. + * @create_child_meta: virtual function that gets called for each added + * child, the function should instantiate an object of type + * #ClutterContainerIface::child_meta_type, set the container and actor + * fields in the instance and add the record to a data structure for + * subsequent access for #ClutterContainerIface::get_child_meta + * @destroy_child_meta: virtual function that gets called when a child is + * removed; it shuld release all resources held by the record + * @get_child_meta: return the record for a container child + * @actor_added: class handler for #ClutterContainer::actor-added + * @actor_removed: class handler for #ClutterContainer::actor-removed + * @child_notify: class handler for #ClutterContainer::child-notify + * + * Base interface for container actors. The @add, @remove and @foreach + * virtual functions must be provided by any implementation; the other + * virtual functions are optional. + * + * Since: 0.4 + */ +struct _ClutterContainerIface +{ + /*< private >*/ + GTypeInterface g_iface; + + /*< public >*/ + void (* add) (ClutterContainer *container, + ClutterActor *actor); + void (* remove) (ClutterContainer *container, + ClutterActor *actor); + void (* foreach) (ClutterContainer *container, + ClutterCallback callback, + gpointer user_data); + + void (* foreach_with_internals) (ClutterContainer *container, + ClutterCallback callback, + gpointer user_data); + + /* child stacking */ + void (* raise) (ClutterContainer *container, + ClutterActor *actor, + ClutterActor *sibling); + void (* lower) (ClutterContainer *container, + ClutterActor *actor, + ClutterActor *sibling); + void (* sort_depth_order) (ClutterContainer *container); + + /* ClutterChildMeta management */ + GType child_meta_type; + void (* create_child_meta) (ClutterContainer *container, + ClutterActor *actor); + void (* destroy_child_meta) (ClutterContainer *container, + ClutterActor *actor); + ClutterChildMeta *(* get_child_meta) (ClutterContainer *container, + ClutterActor *actor); + + /* signals */ + void (* actor_added) (ClutterContainer *container, + ClutterActor *actor); + void (* actor_removed) (ClutterContainer *container, + ClutterActor *actor); + + void (* child_notify) (ClutterContainer *container, + ClutterActor *child, + GParamSpec *pspec); +}; + +CLUTTER_AVAILABLE_IN_ALL +GType clutter_container_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_ALL +ClutterActor * clutter_container_find_child_by_name (ClutterContainer *container, + const gchar *child_name); + +CLUTTER_AVAILABLE_IN_ALL +GParamSpec * clutter_container_class_find_child_property (GObjectClass *klass, + const gchar *property_name); +CLUTTER_AVAILABLE_IN_ALL +GParamSpec ** clutter_container_class_list_child_properties (GObjectClass *klass, + guint *n_properties); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_container_create_child_meta (ClutterContainer *container, + ClutterActor *actor); +CLUTTER_AVAILABLE_IN_ALL +void clutter_container_destroy_child_meta (ClutterContainer *container, + ClutterActor *actor); +CLUTTER_AVAILABLE_IN_ALL +ClutterChildMeta * clutter_container_get_child_meta (ClutterContainer *container, + ClutterActor *actor); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_container_child_set_property (ClutterContainer *container, + ClutterActor *child, + const gchar * property, + const GValue *value); +CLUTTER_AVAILABLE_IN_ALL +void clutter_container_child_get_property (ClutterContainer *container, + ClutterActor *child, + const gchar *property, + GValue *value); +CLUTTER_AVAILABLE_IN_ALL +void clutter_container_child_set (ClutterContainer *container, + ClutterActor *actor, + const gchar *first_prop, + ...) G_GNUC_NULL_TERMINATED; +CLUTTER_AVAILABLE_IN_ALL +void clutter_container_child_get (ClutterContainer *container, + ClutterActor *actor, + const gchar *first_prop, + ...) G_GNUC_NULL_TERMINATED; + +CLUTTER_AVAILABLE_IN_ALL +void clutter_container_child_notify (ClutterContainer *container, + ClutterActor *child, + GParamSpec *pspec); + +G_END_DECLS + +#endif /* __CLUTTER_CONTAINER_H__ */ diff --git a/clutter/clutter/clutter-content-private.h b/clutter/clutter/clutter-content-private.h new file mode 100644 index 0000000..009ae41 --- /dev/null +++ b/clutter/clutter/clutter-content-private.h @@ -0,0 +1,43 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2011 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_CONTENT_PRIVATE_H__ +#define __CLUTTER_CONTENT_PRIVATE_H__ + +#include + +G_BEGIN_DECLS + +void _clutter_content_attached (ClutterContent *content, + ClutterActor *actor); +void _clutter_content_detached (ClutterContent *content, + ClutterActor *actor); + +void _clutter_content_paint_content (ClutterContent *content, + ClutterActor *actor, + ClutterPaintNode *node); + +G_END_DECLS + +#endif /* __CLUTTER_CONTENT_PRIVATE_H__ */ diff --git a/clutter/clutter/clutter-content.c b/clutter/clutter/clutter-content.c new file mode 100644 index 0000000..76ca65d --- /dev/null +++ b/clutter/clutter/clutter-content.c @@ -0,0 +1,305 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2011 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-content + * @Title: ClutterContent + * @Short_Description: Delegate for painting the content of an actor + * + * #ClutterContent is an interface to implement types responsible for + * painting the content of a #ClutterActor. + * + * Multiple actors can use the same #ClutterContent instance, in order + * to share the resources associated with painting the same content. + * + * #ClutterContent is available since Clutter 1.10. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-content-private.h" + +#include "clutter-debug.h" +#include "clutter-marshal.h" +#include "clutter-private.h" + +typedef struct _ClutterContentIface ClutterContentInterface; + +enum +{ + ATTACHED, + DETACHED, + + LAST_SIGNAL +}; + +static GQuark quark_content_actors = 0; + +static guint content_signals[LAST_SIGNAL] = { 0, }; + +G_DEFINE_INTERFACE (ClutterContent, clutter_content, G_TYPE_OBJECT) + +static gboolean +clutter_content_real_get_preferred_size (ClutterContent *content, + gfloat *width, + gfloat *height) +{ + if (width != NULL) + *width = 0.f; + + if (height != NULL) + *height = 0.f; + + return FALSE; +} + +static void +clutter_content_real_attached (ClutterContent *content, + ClutterActor *actor) +{ +} + +static void +clutter_content_real_detached (ClutterContent *content, + ClutterActor *actor) +{ +} + +static void +clutter_content_real_invalidate (ClutterContent *content) +{ +} + +static void +clutter_content_real_paint_content (ClutterContent *content, + ClutterActor *actor, + ClutterPaintNode *context) +{ +} + +static void +clutter_content_default_init (ClutterContentInterface *iface) +{ + quark_content_actors = g_quark_from_static_string ("-clutter-content-actors"); + + iface->get_preferred_size = clutter_content_real_get_preferred_size; + iface->paint_content = clutter_content_real_paint_content; + iface->attached = clutter_content_real_attached; + iface->detached = clutter_content_real_detached; + iface->invalidate = clutter_content_real_invalidate; + + /** + * ClutterContent::attached: + * @content: the object that emitted the signal + * @actor: a #ClutterActor + * + * This signal is emitted each time a #ClutterContent implementation is + * assigned to a #ClutterActor. + * + * Since: 1.10 + */ + content_signals[ATTACHED] = + g_signal_new (I_("attached"), + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ClutterContentIface, attached), + NULL, NULL, + _clutter_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CLUTTER_TYPE_ACTOR); + + /** + * ClutterContent::detached: + * @content: the object that emitted the signal + * @actor: a #ClutterActor + * + * This signal is emitted each time a #ClutterContent implementation is + * removed from a #ClutterActor. + * + * Since: 1.10 + */ + content_signals[DETACHED] = + g_signal_new (I_("detached"), + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ClutterContentIface, detached), + NULL, NULL, + _clutter_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CLUTTER_TYPE_ACTOR); +} + +/** + * clutter_content_invalidate: + * @content: a #ClutterContent + * + * Invalidates a #ClutterContent. + * + * This function should be called by #ClutterContent implementations when + * they change the way a the content should be painted regardless of the + * actor state. + * + * Since: 1.10 + */ +void +clutter_content_invalidate (ClutterContent *content) +{ + GHashTable *actors; + GHashTableIter iter; + gpointer key_p, value_p; + + g_return_if_fail (CLUTTER_IS_CONTENT (content)); + + CLUTTER_CONTENT_GET_IFACE (content)->invalidate (content); + + actors = g_object_get_qdata (G_OBJECT (content), quark_content_actors); + if (actors == NULL) + return; + + g_hash_table_iter_init (&iter, actors); + while (g_hash_table_iter_next (&iter, &key_p, &value_p)) + { + ClutterActor *actor = key_p; + + g_assert (actor != NULL); + + clutter_actor_queue_redraw (actor); + } +} + +/*< private > + * _clutter_content_attached: + * @content: a #ClutterContent + * @actor: a #ClutterActor + * + * Attaches @actor to the @content. + * + * This function should be used internally every time a #ClutterActor + * is associated to a #ClutterContent, to set up a backpointer from + * the @content to the @actor. + * + * This function will invoke the #ClutterContentIface.attached() virtual + * function. + */ +void +_clutter_content_attached (ClutterContent *content, + ClutterActor *actor) +{ + GObject *obj = G_OBJECT (content); + GHashTable *actors; + + actors = g_object_get_qdata (obj, quark_content_actors); + if (actors == NULL) + { + actors = g_hash_table_new (NULL, NULL); + g_object_set_qdata_full (obj, quark_content_actors, + actors, + (GDestroyNotify) g_hash_table_unref); + } + + g_hash_table_insert (actors, actor, actor); + + g_signal_emit (content, content_signals[ATTACHED], 0, actor); +} + +/*< private > + * _clutter_content_detached: + * @content: a #ClutterContent + * @actor: a #ClutterActor + * + * Detaches @actor from @content. + * + * This function should be used internally every time a #ClutterActor + * removes the association with a #ClutterContent. + * + * This function will invoke the #ClutterContentIface.detached() virtual + * function. + */ +void +_clutter_content_detached (ClutterContent *content, + ClutterActor *actor) +{ + GObject *obj = G_OBJECT (content); + GHashTable *actors; + + actors = g_object_get_qdata (obj, quark_content_actors); + g_assert (actors != NULL); + + g_hash_table_remove (actors, actor); + + if (g_hash_table_size (actors) == 0) + g_object_set_qdata (obj, quark_content_actors, NULL); + + g_signal_emit (content, content_signals[DETACHED], 0, actor); +} + +/*< private > + * _clutter_content_paint_content: + * @content: a #ClutterContent + * @actor: a #ClutterActor + * @context: a #ClutterPaintNode + * + * Creates the render tree for the @content and @actor. + * + * This function will invoke the #ClutterContentIface.paint_content() + * virtual function. + */ +void +_clutter_content_paint_content (ClutterContent *content, + ClutterActor *actor, + ClutterPaintNode *node) +{ + CLUTTER_CONTENT_GET_IFACE (content)->paint_content (content, actor, node); +} + +/** + * clutter_content_get_preferred_size: + * @content: a #ClutterContent + * @width: (out): return location for the natural width of the content + * @height: (out): return location for the natural height of the content + * + * Retrieves the natural size of the @content, if any. + * + * The natural size of a #ClutterContent is defined as the size the content + * would have regardless of the allocation of the actor that is painting it, + * for instance the size of an image data. + * + * Return value: %TRUE if the content has a preferred size, and %FALSE + * otherwise + * + * Since: 1.10 + */ +gboolean +clutter_content_get_preferred_size (ClutterContent *content, + gfloat *width, + gfloat *height) +{ + g_return_val_if_fail (CLUTTER_IS_CONTENT (content), FALSE); + + return CLUTTER_CONTENT_GET_IFACE (content)->get_preferred_size (content, + width, + height); +} diff --git a/clutter/clutter/clutter-content.h b/clutter/clutter/clutter-content.h new file mode 100644 index 0000000..84bfa0e --- /dev/null +++ b/clutter/clutter/clutter-content.h @@ -0,0 +1,103 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2012 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 . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_CONTENT_H__ +#define __CLUTTER_CONTENT_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_CONTENT (clutter_content_get_type ()) +#define CLUTTER_CONTENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_CONTENT, ClutterContent)) +#define CLUTTER_IS_CONTENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_CONTENT)) +#define CLUTTER_CONTENT_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), CLUTTER_TYPE_CONTENT, ClutterContentIface)) + +typedef struct _ClutterContentIface ClutterContentIface; + +/** + * ClutterContent: + * + * The #ClutterContent structure is an opaque type + * whose members cannot be acccessed directly. + * + * Since: 1.10 + */ + +/** + * ClutterContentIface: + * @get_preferred_size: virtual function; should be overridden by subclasses + * of #ClutterContent that have a natural size + * @paint_content: virtual function; called each time the content needs to + * paint itself + * @attached: virtual function; called each time a #ClutterContent is attached + * to a #ClutterActor. + * @detached: virtual function; called each time a #ClutterContent is detached + * from a #ClutterActor. + * @invalidate: virtual function; called each time a #ClutterContent state + * is changed. + * + * The #ClutterContentIface structure contains only + * private data. + * + * Since: 1.10 + */ +struct _ClutterContentIface +{ + /*< private >*/ + GTypeInterface g_iface; + + /*< public >*/ + gboolean (* get_preferred_size) (ClutterContent *content, + gfloat *width, + gfloat *height); + void (* paint_content) (ClutterContent *content, + ClutterActor *actor, + ClutterPaintNode *node); + + void (* attached) (ClutterContent *content, + ClutterActor *actor); + void (* detached) (ClutterContent *content, + ClutterActor *actor); + + void (* invalidate) (ClutterContent *content); +}; + +CLUTTER_AVAILABLE_IN_1_10 +GType clutter_content_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_10 +gboolean clutter_content_get_preferred_size (ClutterContent *content, + gfloat *width, + gfloat *height); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_content_invalidate (ClutterContent *content); + +G_END_DECLS + +#endif /* __CLUTTER_CONTENT_H__ */ diff --git a/clutter/clutter/clutter-debug.h b/clutter/clutter/clutter-debug.h new file mode 100644 index 0000000..00302bf --- /dev/null +++ b/clutter/clutter/clutter-debug.h @@ -0,0 +1,88 @@ +#ifndef __CLUTTER_DEBUG_H__ +#define __CLUTTER_DEBUG_H__ + +#include +#include "clutter-main.h" + +G_BEGIN_DECLS + +typedef enum { + CLUTTER_DEBUG_MISC = 1 << 0, + CLUTTER_DEBUG_ACTOR = 1 << 1, + CLUTTER_DEBUG_TEXTURE = 1 << 2, + CLUTTER_DEBUG_EVENT = 1 << 3, + CLUTTER_DEBUG_PAINT = 1 << 4, + CLUTTER_DEBUG_PANGO = 1 << 5, + CLUTTER_DEBUG_BACKEND = 1 << 6, + CLUTTER_DEBUG_SCHEDULER = 1 << 7, + CLUTTER_DEBUG_SCRIPT = 1 << 8, + CLUTTER_DEBUG_SHADER = 1 << 9, + CLUTTER_DEBUG_MULTISTAGE = 1 << 10, + CLUTTER_DEBUG_ANIMATION = 1 << 11, + CLUTTER_DEBUG_LAYOUT = 1 << 12, + CLUTTER_DEBUG_PICK = 1 << 13, + CLUTTER_DEBUG_EVENTLOOP = 1 << 14, + CLUTTER_DEBUG_CLIPPING = 1 << 15, + CLUTTER_DEBUG_OOB_TRANSFORMS = 1 << 16 +} ClutterDebugFlag; + +typedef enum { + CLUTTER_DEBUG_NOP_PICKING = 1 << 0, + CLUTTER_DEBUG_DUMP_PICK_BUFFERS = 1 << 1 +} ClutterPickDebugFlag; + +typedef enum { + CLUTTER_DEBUG_DISABLE_SWAP_EVENTS = 1 << 0, + CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS = 1 << 1, + CLUTTER_DEBUG_REDRAWS = 1 << 2, + CLUTTER_DEBUG_PAINT_VOLUMES = 1 << 3, + CLUTTER_DEBUG_DISABLE_CULLING = 1 << 4, + CLUTTER_DEBUG_DISABLE_OFFSCREEN_REDIRECT = 1 << 5, + CLUTTER_DEBUG_CONTINUOUS_REDRAW = 1 << 6, + CLUTTER_DEBUG_PAINT_DEFORM_TILES = 1 << 7 +} ClutterDrawDebugFlag; + +#ifdef CLUTTER_ENABLE_DEBUG + +#define CLUTTER_HAS_DEBUG(type) ((clutter_debug_flags & CLUTTER_DEBUG_##type) != FALSE) + +#ifdef __GNUC__ + +/* Try the GCC extension for valists in macros */ +#define CLUTTER_NOTE(type,x,a...) G_STMT_START { \ + if (G_UNLIKELY (CLUTTER_HAS_DEBUG (type))) { \ + _clutter_debug_message ("[" #type "]:" G_STRLOC ": " x, ##a); \ + } } G_STMT_END + +#else /* !__GNUC__ */ +/* Try the C99 version; unfortunately, this does not allow us to pass + * empty arguments to the macro, which means we have to + * do an intemediate printf. + */ +#define CLUTTER_NOTE(type,...) G_STMT_START { \ + if (G_UNLIKELY (CLUTTER_HAS_DEBUG (type))) { \ + gchar *_fmt = g_strdup_printf (__VA_ARGS__); \ + _clutter_debug_message ("[" #type "]:" G_STRLOC ": %s", _fmt); \ + g_free (_fmt); \ + } } G_STMT_END +#endif + +#else /* !CLUTTER_ENABLE_DEBUG */ + +#define CLUTTER_NOTE(type,...) G_STMT_START { } G_STMT_END +#define CLUTTER_HAS_DEBUG(type) FALSE + +#endif /* CLUTTER_ENABLE_DEBUG */ + +extern guint clutter_debug_flags; +extern guint clutter_pick_debug_flags; +extern guint clutter_paint_debug_flags; + +void _clutter_debug_messagev (const char *format, + va_list var_args); +void _clutter_debug_message (const char *format, + ...); + +G_END_DECLS + +#endif /* __CLUTTER_DEBUG_H__ */ diff --git a/clutter/clutter/clutter-deform-effect.c b/clutter/clutter/clutter-deform-effect.c new file mode 100644 index 0000000..be90aad --- /dev/null +++ b/clutter/clutter/clutter-deform-effect.c @@ -0,0 +1,813 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + * + * Based on the MxDeformTexture class, written by: + * Chris Lord + */ + +/** + * SECTION:clutter-deform-effect + * @Title: ClutterDeformEffect + * @Short_Description: A base class for effects deforming the geometry + * of an actor + * + * #ClutterDeformEffect is an abstract class providing all the plumbing + * for creating effects that result in the deformation of an actor's + * geometry. + * + * #ClutterDeformEffect uses offscreen buffers to render the contents of + * a #ClutterActor and then the Cogl vertex buffers API to submit the + * geometry to the GPU. + * + * #ClutterDeformEffect is available since Clutter 1.4 + * + * ## Implementing ClutterDeformEffect + * + * Sub-classes of #ClutterDeformEffect should override the + * #ClutterDeformEffectClass.deform_vertex() virtual function; this function + * is called on every vertex that needs to be deformed by the effect. + * Each passed vertex is an in-out parameter that initially contains the + * position of the vertex and should be modified according to a specific + * deformation algorithm. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#define CLUTTER_ENABLE_EXPERIMENTAL_API +#include "clutter-deform-effect.h" + +#include + +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-offscreen-effect-private.h" +#include "clutter-private.h" + +#define DEFAULT_N_TILES 32 + +struct _ClutterDeformEffectPrivate +{ + CoglPipeline *back_pipeline; + + gint x_tiles; + gint y_tiles; + + CoglAttributeBuffer *buffer; + + CoglPrimitive *primitive; + + CoglPrimitive *lines_primitive; + + gint n_vertices; + + gulong allocation_id; + + guint is_dirty : 1; +}; + +enum +{ + PROP_0, + + PROP_X_TILES, + PROP_Y_TILES, + + PROP_BACK_MATERIAL, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterDeformEffect, + clutter_deform_effect, + CLUTTER_TYPE_OFFSCREEN_EFFECT) + +static void +clutter_deform_effect_real_deform_vertex (ClutterDeformEffect *effect, + gfloat width, + gfloat height, + CoglTextureVertex *vertex) +{ + g_warning ("%s: Deformation effect of type '%s' does not implement " + "the required ClutterDeformEffect::deform_vertex virtual " + "function.", + G_STRLOC, + G_OBJECT_TYPE_NAME (effect)); +} + +static void +clutter_deform_effect_deform_vertex (ClutterDeformEffect *effect, + gfloat width, + gfloat height, + CoglTextureVertex *vertex) +{ + CLUTTER_DEFORM_EFFECT_GET_CLASS (effect)->deform_vertex (effect, + width, height, + vertex); +} + +static void +vbo_invalidate (ClutterActor *actor, + const ClutterActorBox *allocation, + ClutterAllocationFlags flags, + ClutterDeformEffect *effect) +{ + effect->priv->is_dirty = TRUE; +} + +static void +clutter_deform_effect_set_actor (ClutterActorMeta *meta, + ClutterActor *actor) +{ + ClutterDeformEffectPrivate *priv = CLUTTER_DEFORM_EFFECT (meta)->priv; + + if (priv->allocation_id != 0) + { + ClutterActor *old_actor = clutter_actor_meta_get_actor (meta); + + if (old_actor != NULL) + g_signal_handler_disconnect (old_actor, priv->allocation_id); + + priv->allocation_id = 0; + } + + /* we need to invalidate the VBO whenever the allocation of the actor + * changes + */ + if (actor != NULL) + priv->allocation_id = g_signal_connect (actor, "allocation-changed", + G_CALLBACK (vbo_invalidate), + meta); + + priv->is_dirty = TRUE; + + CLUTTER_ACTOR_META_CLASS (clutter_deform_effect_parent_class)->set_actor (meta, actor); +} + +static void +clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect) +{ + ClutterDeformEffect *self= CLUTTER_DEFORM_EFFECT (effect); + ClutterDeformEffectPrivate *priv = self->priv; + CoglHandle material; + CoglPipeline *pipeline; + CoglDepthState depth_state; + CoglFramebuffer *fb = cogl_get_draw_framebuffer (); + + if (priv->is_dirty) + { + ClutterRect rect; + gboolean mapped_buffer; + CoglVertexP3T2C4 *verts; + ClutterActor *actor; + gfloat width, height; + guint opacity; + gint i, j; + + actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); + opacity = clutter_actor_get_paint_opacity (actor); + + /* if we don't have a target size, fall back to the actor's + * allocation, though wrong it might be + */ + if (clutter_offscreen_effect_get_target_rect (effect, &rect)) + { + width = clutter_rect_get_width (&rect); + height = clutter_rect_get_height (&rect); + } + else + clutter_actor_get_size (actor, &width, &height); + + /* XXX ideally, the sub-classes should tell us what they + * changed in the texture vertices; we then would be able to + * avoid resubmitting the same data, if it did not change. for + * the time being, we resubmit everything + */ + verts = cogl_buffer_map (COGL_BUFFER (priv->buffer), + COGL_BUFFER_ACCESS_WRITE, + COGL_BUFFER_MAP_HINT_DISCARD); + + /* If the map failed then we'll resort to allocating a temporary + buffer */ + if (verts == NULL) + { + mapped_buffer = FALSE; + verts = g_malloc (sizeof (*verts) * priv->n_vertices); + } + else + mapped_buffer = TRUE; + + for (i = 0; i < priv->y_tiles + 1; i++) + { + for (j = 0; j < priv->x_tiles + 1; j++) + { + CoglVertexP3T2C4 *vertex_out; + CoglTextureVertex vertex; + + /* CoglTextureVertex isn't an ideal structure to use for + this because it contains a CoglColor. The internal + layout of CoglColor is mean to be private so Clutter + can not pass a pointer to it as a vertex + attribute. Also it contains padding so we end up + storing more data in the vertex buffer than we need + to. Instead we let the application modify a dummy + vertex and then copy the details back out to a more + well-defined struct */ + + vertex.tx = (float) j / priv->x_tiles; + vertex.ty = (float) i / priv->y_tiles; + + vertex.x = width * vertex.tx; + vertex.y = height * vertex.ty; + vertex.z = 0.0f; + + cogl_color_init_from_4ub (&vertex.color, 255, 255, 255, opacity); + + clutter_deform_effect_deform_vertex (self, + width, height, + &vertex); + + vertex_out = verts + i * (priv->x_tiles + 1) + j; + + vertex_out->x = vertex.x; + vertex_out->y = vertex.y; + vertex_out->z = vertex.z; + vertex_out->s = vertex.tx; + vertex_out->t = vertex.ty; + vertex_out->r = cogl_color_get_red_byte (&vertex.color); + vertex_out->g = cogl_color_get_green_byte (&vertex.color); + vertex_out->b = cogl_color_get_blue_byte (&vertex.color); + vertex_out->a = cogl_color_get_alpha_byte (&vertex.color); + } + } + + if (mapped_buffer) + cogl_buffer_unmap (COGL_BUFFER (priv->buffer)); + else + { + cogl_buffer_set_data (COGL_BUFFER (priv->buffer), + 0, /* offset */ + verts, + sizeof (*verts) * priv->n_vertices); + g_free (verts); + } + + priv->is_dirty = FALSE; + } + + material = clutter_offscreen_effect_get_target (effect); + pipeline = COGL_PIPELINE (material); + + /* enable depth testing */ + cogl_depth_state_init (&depth_state); + cogl_depth_state_set_test_enabled (&depth_state, TRUE); + cogl_pipeline_set_depth_state (pipeline, &depth_state, NULL); + + /* enable backface culling if we have a back material */ + if (priv->back_pipeline != NULL) + cogl_pipeline_set_cull_face_mode (pipeline, + COGL_PIPELINE_CULL_FACE_MODE_BACK); + + /* draw the front */ + if (material != NULL) + cogl_framebuffer_draw_primitive (fb, pipeline, priv->primitive); + + /* draw the back */ + if (priv->back_pipeline != NULL) + { + CoglPipeline *back_pipeline; + + /* We probably shouldn't be modifying the user's material so + instead we make a temporary copy */ + back_pipeline = cogl_pipeline_copy (priv->back_pipeline); + cogl_pipeline_set_depth_state (back_pipeline, &depth_state, NULL); + cogl_pipeline_set_cull_face_mode (back_pipeline, + COGL_PIPELINE_CULL_FACE_MODE_FRONT); + + cogl_framebuffer_draw_primitive (fb, back_pipeline, priv->primitive); + + cogl_object_unref (back_pipeline); + } + + if (G_UNLIKELY (priv->lines_primitive != NULL)) + { + CoglContext *ctx = + clutter_backend_get_cogl_context (clutter_get_default_backend ()); + CoglPipeline *lines_pipeline = cogl_pipeline_new (ctx); + cogl_pipeline_set_color4f (lines_pipeline, 1.0, 0, 0, 1.0); + cogl_framebuffer_draw_primitive (fb, lines_pipeline, + priv->lines_primitive); + cogl_object_unref (lines_pipeline); + } +} + +static inline void +clutter_deform_effect_free_arrays (ClutterDeformEffect *self) +{ + ClutterDeformEffectPrivate *priv = self->priv; + + if (priv->buffer) + { + cogl_object_unref (priv->buffer); + priv->buffer = NULL; + } + + if (priv->primitive) + { + cogl_object_unref (priv->primitive); + priv->primitive = NULL; + } + + if (priv->lines_primitive) + { + cogl_object_unref (priv->lines_primitive); + priv->lines_primitive = NULL; + } +} + +static void +clutter_deform_effect_init_arrays (ClutterDeformEffect *self) +{ + ClutterDeformEffectPrivate *priv = self->priv; + gint x, y, direction, n_indices; + CoglAttribute *attributes[3]; + guint16 *static_indices; + CoglContext *ctx = + clutter_backend_get_cogl_context (clutter_get_default_backend ()); + CoglIndices *indices; + guint16 *idx; + int i; + + clutter_deform_effect_free_arrays (self); + + n_indices = ((2 + 2 * priv->x_tiles) + * priv->y_tiles + + (priv->y_tiles - 1)); + + static_indices = g_new (guint16, n_indices); + +#define MESH_INDEX(x,y) ((y) * (priv->x_tiles + 1) + (x)) + + /* compute all the triangles from the various tiles */ + direction = 1; + + idx = static_indices; + idx[0] = MESH_INDEX (0, 0); + idx[1] = MESH_INDEX (0, 1); + idx += 2; + + for (y = 0; y < priv->y_tiles; y++) + { + for (x = 0; x < priv->x_tiles; x++) + { + if (direction) + { + idx[0] = MESH_INDEX (x + 1, y); + idx[1] = MESH_INDEX (x + 1, y + 1); + } + else + { + idx[0] = MESH_INDEX (priv->x_tiles - x - 1, y); + idx[1] = MESH_INDEX (priv->x_tiles - x - 1, y + 1); + } + + idx += 2; + } + + if (y == (priv->y_tiles - 1)) + break; + + if (direction) + { + idx[0] = MESH_INDEX (priv->x_tiles, y + 1); + idx[1] = MESH_INDEX (priv->x_tiles, y + 1); + idx[2] = MESH_INDEX (priv->x_tiles, y + 2); + } + else + { + idx[0] = MESH_INDEX (0, y + 1); + idx[1] = MESH_INDEX (0, y + 1); + idx[2] = MESH_INDEX (0, y + 2); + } + + idx += 3; + + direction = !direction; + } + +#undef MESH_INDEX + + indices = cogl_indices_new (ctx, + COGL_INDICES_TYPE_UNSIGNED_SHORT, + static_indices, + n_indices); + + g_free (static_indices); + + priv->n_vertices = (priv->x_tiles + 1) * (priv->y_tiles + 1); + + priv->buffer = + cogl_attribute_buffer_new (ctx, + sizeof (CoglVertexP3T2C4) * + priv->n_vertices, + NULL); + + /* The application is expected to continuously modify the vertices + so we should give a hint to Cogl about that */ + cogl_buffer_set_update_hint (COGL_BUFFER (priv->buffer), + COGL_BUFFER_UPDATE_HINT_DYNAMIC); + + attributes[0] = cogl_attribute_new (priv->buffer, + "cogl_position_in", + sizeof (CoglVertexP3T2C4), + G_STRUCT_OFFSET (CoglVertexP3T2C4, x), + 3, /* n_components */ + COGL_ATTRIBUTE_TYPE_FLOAT); + attributes[1] = cogl_attribute_new (priv->buffer, + "cogl_tex_coord0_in", + sizeof (CoglVertexP3T2C4), + G_STRUCT_OFFSET (CoglVertexP3T2C4, s), + 2, /* n_components */ + COGL_ATTRIBUTE_TYPE_FLOAT); + attributes[2] = cogl_attribute_new (priv->buffer, + "cogl_color_in", + sizeof (CoglVertexP3T2C4), + G_STRUCT_OFFSET (CoglVertexP3T2C4, r), + 4, /* n_components */ + COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE); + + priv->primitive = + cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLE_STRIP, + priv->n_vertices, + attributes, + 3 /* n_attributes */); + cogl_primitive_set_indices (priv->primitive, + indices, + n_indices); + + if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DEFORM_TILES)) + { + priv->lines_primitive = + cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_LINE_STRIP, + priv->n_vertices, + attributes, + 2 /* n_attributes */); + cogl_primitive_set_indices (priv->lines_primitive, + indices, + n_indices); + } + + cogl_object_unref (indices); + + for (i = 0; i < 3; i++) + cogl_object_unref (attributes[i]); + + priv->is_dirty = TRUE; +} + +static inline void +clutter_deform_effect_free_back_pipeline (ClutterDeformEffect *self) +{ + ClutterDeformEffectPrivate *priv = self->priv; + + if (priv->back_pipeline != NULL) + { + cogl_object_unref (priv->back_pipeline); + priv->back_pipeline = NULL; + } +} + +static void +clutter_deform_effect_finalize (GObject *gobject) +{ + ClutterDeformEffect *self = CLUTTER_DEFORM_EFFECT (gobject); + + clutter_deform_effect_free_arrays (self); + clutter_deform_effect_free_back_pipeline (self); + + G_OBJECT_CLASS (clutter_deform_effect_parent_class)->finalize (gobject); +} + +static void +clutter_deform_effect_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterDeformEffect *self = CLUTTER_DEFORM_EFFECT (gobject); + + switch (prop_id) + { + case PROP_X_TILES: + clutter_deform_effect_set_n_tiles (self, g_value_get_uint (value), + self->priv->y_tiles); + break; + + case PROP_Y_TILES: + clutter_deform_effect_set_n_tiles (self, self->priv->x_tiles, + g_value_get_uint (value)); + break; + + case PROP_BACK_MATERIAL: + clutter_deform_effect_set_back_material (self, g_value_get_boxed (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_deform_effect_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterDeformEffectPrivate *priv = CLUTTER_DEFORM_EFFECT (gobject)->priv; + + switch (prop_id) + { + case PROP_X_TILES: + g_value_set_uint (value, priv->x_tiles); + break; + + case PROP_Y_TILES: + g_value_set_uint (value, priv->y_tiles); + break; + + case PROP_BACK_MATERIAL: + g_value_set_boxed (value, priv->back_pipeline); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_deform_effect_class_init (ClutterDeformEffectClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass); + ClutterOffscreenEffectClass *offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass); + + klass->deform_vertex = clutter_deform_effect_real_deform_vertex; + + /** + * ClutterDeformEffect:x-tiles: + * + * The number of horizontal tiles. The bigger the number, the + * smaller the tiles + * + * Since: 1.4 + */ + obj_props[PROP_X_TILES] = + g_param_spec_uint ("x-tiles", + P_("Horizontal Tiles"), + P_("The number of horizontal tiles"), + 1, G_MAXUINT, + DEFAULT_N_TILES, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterDeformEffect:y-tiles: + * + * The number of vertical tiles. The bigger the number, the + * smaller the tiles + * + * Since: 1.4 + */ + obj_props[PROP_Y_TILES] = + g_param_spec_uint ("y-tiles", + P_("Vertical Tiles"), + P_("The number of vertical tiles"), + 1, G_MAXUINT, + DEFAULT_N_TILES, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterDeformEffect:back-material: + * + * A material to be used when painting the back of the actor + * to which this effect has been applied + * + * By default, no material will be used + * + * Since: 1.4 + */ + obj_props[PROP_BACK_MATERIAL] = + g_param_spec_boxed ("back-material", + P_("Back Material"), + P_("The material to be used when painting the back of the actor"), + COGL_TYPE_HANDLE, + CLUTTER_PARAM_READWRITE); + + gobject_class->finalize = clutter_deform_effect_finalize; + gobject_class->set_property = clutter_deform_effect_set_property; + gobject_class->get_property = clutter_deform_effect_get_property; + g_object_class_install_properties (gobject_class, + PROP_LAST, + obj_props); + + meta_class->set_actor = clutter_deform_effect_set_actor; + + offscreen_class->paint_target = clutter_deform_effect_paint_target; +} + +static void +clutter_deform_effect_init (ClutterDeformEffect *self) +{ + self->priv = clutter_deform_effect_get_instance_private (self); + self->priv->x_tiles = self->priv->y_tiles = DEFAULT_N_TILES; + self->priv->back_pipeline = NULL; + + clutter_deform_effect_init_arrays (self); +} + +/** + * clutter_deform_effect_set_back_material: + * @effect: a #ClutterDeformEffect + * @material: (allow-none): a handle to a Cogl material + * + * Sets the material that should be used when drawing the back face + * of the actor during a deformation + * + * The #ClutterDeformEffect will take a reference on the material's + * handle + * + * Since: 1.4 + */ +void +clutter_deform_effect_set_back_material (ClutterDeformEffect *effect, + CoglHandle material) +{ + ClutterDeformEffectPrivate *priv; + CoglPipeline *pipeline = COGL_PIPELINE (material); + + g_return_if_fail (CLUTTER_IS_DEFORM_EFFECT (effect)); + g_return_if_fail (pipeline == NULL || cogl_is_pipeline (pipeline)); + + priv = effect->priv; + + clutter_deform_effect_free_back_pipeline (effect); + + priv->back_pipeline = material; + if (priv->back_pipeline != NULL) + cogl_object_ref (priv->back_pipeline); + + clutter_deform_effect_invalidate (effect); +} + +/** + * clutter_deform_effect_get_back_material: + * @effect: a #ClutterDeformEffect + * + * Retrieves the handle to the back face material used by @effect + * + * Return value: (transfer none): a handle for the material, or %NULL. + * The returned material is owned by the #ClutterDeformEffect and it + * should not be freed directly + * + * Since: 1.4 + */ +CoglHandle +clutter_deform_effect_get_back_material (ClutterDeformEffect *effect) +{ + g_return_val_if_fail (CLUTTER_IS_DEFORM_EFFECT (effect), NULL); + + return effect->priv->back_pipeline; +} + +/** + * clutter_deform_effect_set_n_tiles: + * @effect: a #ClutterDeformEffect + * @x_tiles: number of horizontal tiles + * @y_tiles: number of vertical tiles + * + * Sets the number of horizontal and vertical tiles to be used + * when applying the effect + * + * More tiles allow a finer grained deformation at the expenses + * of computation + * + * Since: 1.4 + */ +void +clutter_deform_effect_set_n_tiles (ClutterDeformEffect *effect, + guint x_tiles, + guint y_tiles) +{ + ClutterDeformEffectPrivate *priv; + gboolean tiles_changed = FALSE; + + g_return_if_fail (CLUTTER_IS_DEFORM_EFFECT (effect)); + g_return_if_fail (x_tiles > 0 && y_tiles > 0); + + priv = effect->priv; + + g_object_freeze_notify (G_OBJECT (effect)); + + if (priv->x_tiles != x_tiles) + { + priv->x_tiles = x_tiles; + + g_object_notify_by_pspec (G_OBJECT (effect), obj_props[PROP_X_TILES]); + + tiles_changed = TRUE; + } + + if (priv->y_tiles != y_tiles) + { + priv->y_tiles = y_tiles; + + g_object_notify_by_pspec (G_OBJECT (effect), obj_props[PROP_Y_TILES]); + + tiles_changed = TRUE; + } + + if (tiles_changed) + { + clutter_deform_effect_init_arrays (effect); + clutter_deform_effect_invalidate (effect); + } + + g_object_thaw_notify (G_OBJECT (effect)); +} + +/** + * clutter_deform_effect_get_n_tiles: + * @effect: a #ClutterDeformEffect + * @x_tiles: (out): return location for the number of horizontal tiles, + * or %NULL + * @y_tiles: (out): return location for the number of vertical tiles, + * or %NULL + * + * Retrieves the number of horizontal and vertical tiles used to sub-divide + * the actor's geometry during the effect + * + * Since: 1.4 + */ +void +clutter_deform_effect_get_n_tiles (ClutterDeformEffect *effect, + guint *x_tiles, + guint *y_tiles) +{ + g_return_if_fail (CLUTTER_IS_DEFORM_EFFECT (effect)); + + if (x_tiles != NULL) + *x_tiles = effect->priv->x_tiles; + + if (y_tiles != NULL) + *y_tiles = effect->priv->y_tiles; +} + +/** + * clutter_deform_effect_invalidate: + * @effect: a #ClutterDeformEffect + * + * Invalidates the @effect's vertices and, if it is associated + * to an actor, it will queue a redraw + * + * Since: 1.4 + */ +void +clutter_deform_effect_invalidate (ClutterDeformEffect *effect) +{ + ClutterActor *actor; + + g_return_if_fail (CLUTTER_IS_DEFORM_EFFECT (effect)); + + if (effect->priv->is_dirty) + return; + + effect->priv->is_dirty = TRUE; + + actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); + if (actor != NULL) + clutter_effect_queue_repaint (CLUTTER_EFFECT (effect)); +} diff --git a/clutter/clutter/clutter-deform-effect.h b/clutter/clutter/clutter-deform-effect.h new file mode 100644 index 0000000..08d0ca9 --- /dev/null +++ b/clutter/clutter/clutter-deform-effect.h @@ -0,0 +1,117 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_DEFORM_EFFECT_H__ +#define __CLUTTER_DEFORM_EFFECT_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_DEFORM_EFFECT (clutter_deform_effect_get_type ()) +#define CLUTTER_DEFORM_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_DEFORM_EFFECT, ClutterDeformEffect)) +#define CLUTTER_IS_DEFORM_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_DEFORM_EFFECT)) +#define CLUTTER_DEFORM_EFFECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_DEFORM_EFFECT, ClutterDeformEffectClass)) +#define CLUTTER_IS_DEFORM_EFFECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_DEFORM_EFFECT)) +#define CLUTTER_DEFORM_EFFECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_DEFORM_EFFECT, ClutterDeformEffectClass)) + +typedef struct _ClutterDeformEffect ClutterDeformEffect; +typedef struct _ClutterDeformEffectPrivate ClutterDeformEffectPrivate; +typedef struct _ClutterDeformEffectClass ClutterDeformEffectClass; + +/** + * ClutterDeformEffect: + * + * The #ClutterDeformEffect structure contains + * only private data and should be accessed using the provided API + * + * Since: 1.4 + */ +struct _ClutterDeformEffect +{ + /*< private >*/ + ClutterOffscreenEffect parent_instance; + + ClutterDeformEffectPrivate *priv; +}; + +/** + * ClutterDeformEffectClass: + * @deform_vertex: virtual function; sub-classes should override this + * function to compute the deformation of each vertex + * + * The #ClutterDeformEffectClass structure contains + * only private data + * + * Since: 1.4 + */ +struct _ClutterDeformEffectClass +{ + /*< private >*/ + ClutterOffscreenEffectClass parent_class; + + /*< public >*/ + void (* deform_vertex) (ClutterDeformEffect *effect, + gfloat width, + gfloat height, + CoglTextureVertex *vertex); + + /*< private >*/ + void (*_clutter_deform1) (void); + void (*_clutter_deform2) (void); + void (*_clutter_deform3) (void); + void (*_clutter_deform4) (void); + void (*_clutter_deform5) (void); + void (*_clutter_deform6) (void); + void (*_clutter_deform7) (void); +}; + +CLUTTER_AVAILABLE_IN_1_4 +GType clutter_deform_effect_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_4 +void clutter_deform_effect_set_back_material (ClutterDeformEffect *effect, + CoglHandle material); +CLUTTER_AVAILABLE_IN_1_4 +CoglHandle clutter_deform_effect_get_back_material (ClutterDeformEffect *effect); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_deform_effect_set_n_tiles (ClutterDeformEffect *effect, + guint x_tiles, + guint y_tiles); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_deform_effect_get_n_tiles (ClutterDeformEffect *effect, + guint *x_tiles, + guint *y_tiles); + +CLUTTER_AVAILABLE_IN_1_4 +void clutter_deform_effect_invalidate (ClutterDeformEffect *effect); + +G_END_DECLS + +#endif /* __CLUTTER_DEFORM_EFFECT_H__ */ diff --git a/clutter/clutter/clutter-deprecated.h b/clutter/clutter/clutter-deprecated.h new file mode 100644 index 0000000..c54440d --- /dev/null +++ b/clutter/clutter/clutter-deprecated.h @@ -0,0 +1,45 @@ +#ifndef __CLUTTER_DEPRECATED_H__ +#define __CLUTTER_DEPRECATED_H__ + +#define __CLUTTER_DEPRECATED_H_INSIDE__ + +#include "deprecated/clutter-actor.h" +#include "deprecated/clutter-alpha.h" +#include "deprecated/clutter-animatable.h" +#include "deprecated/clutter-animation.h" +#include "deprecated/clutter-animator.h" +#include "deprecated/clutter-backend.h" +#include "deprecated/clutter-behaviour.h" +#include "deprecated/clutter-behaviour-depth.h" +#include "deprecated/clutter-behaviour-ellipse.h" +#include "deprecated/clutter-behaviour-opacity.h" +#include "deprecated/clutter-behaviour-path.h" +#include "deprecated/clutter-behaviour-rotate.h" +#include "deprecated/clutter-behaviour-scale.h" +#include "deprecated/clutter-bin-layout.h" +#include "deprecated/clutter-box.h" +#include "deprecated/clutter-cairo-texture.h" +#include "deprecated/clutter-container.h" +#include "deprecated/clutter-frame-source.h" +#include "deprecated/clutter-group.h" +#include "deprecated/clutter-input-device.h" +#include "deprecated/clutter-keysyms.h" +#include "deprecated/clutter-list-model.h" +#include "deprecated/clutter-main.h" +#include "deprecated/clutter-media.h" +#include "deprecated/clutter-model.h" +#include "deprecated/clutter-rectangle.h" +#include "deprecated/clutter-score.h" +#include "deprecated/clutter-shader.h" +#include "deprecated/clutter-stage-manager.h" +#include "deprecated/clutter-stage.h" +#include "deprecated/clutter-state.h" +#include "deprecated/clutter-table-layout.h" +#include "deprecated/clutter-texture.h" +#include "deprecated/clutter-timeline.h" +#include "deprecated/clutter-timeout-pool.h" +#include "deprecated/clutter-util.h" + +#undef __CLUTTER_DEPRECATED_H_INSIDE__ + +#endif /* __CLUTTER_DEPRECATED_H__ */ diff --git a/clutter/clutter/clutter-desaturate-effect.c b/clutter/clutter/clutter-desaturate-effect.c new file mode 100644 index 0000000..7e1804b --- /dev/null +++ b/clutter/clutter/clutter-desaturate-effect.c @@ -0,0 +1,382 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-desaturate-effect + * @short_description: A desaturation effect + * @see_also: #ClutterEffect, #ClutterOffscreenEffect + * + * #ClutterDesaturateEffect is a sub-class of #ClutterEffect that + * desaturates the color of an actor and its contents. The strenght + * of the desaturation effect is controllable and animatable through + * the #ClutterDesaturateEffect:factor property. + * + * #ClutterDesaturateEffect is available since Clutter 1.4 + */ + +#define CLUTTER_DESATURATE_EFFECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_DESATURATE_EFFECT, ClutterDesaturateEffectClass)) +#define CLUTTER_IS_DESATURATE_EFFECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_DESATURATE_EFFECT)) +#define CLUTTER_DESATURATE_EFFECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_DESATURATE_EFFECT, ClutterDesaturateEffectClass)) + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#define CLUTTER_ENABLE_EXPERIMENTAL_API + +#include + +#include "clutter-desaturate-effect.h" + +#include "cogl/cogl.h" + +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-offscreen-effect.h" +#include "clutter-private.h" + +struct _ClutterDesaturateEffect +{ + ClutterOffscreenEffect parent_instance; + + /* the desaturation factor, also known as "strength" */ + gdouble factor; + + gint factor_uniform; + + gint tex_width; + gint tex_height; + + CoglPipeline *pipeline; +}; + +struct _ClutterDesaturateEffectClass +{ + ClutterOffscreenEffectClass parent_class; + + CoglPipeline *base_pipeline; +}; + +/* the magic gray vec3 has been taken from the NTSC conversion weights + * as defined by: + * + * "OpenGL Superbible, 4th edition" + * -- Richard S. Wright Jr, Benjamin Lipchak, Nicholas Haemel + * Addison-Wesley + */ +static const gchar *desaturate_glsl_declarations = + "uniform float factor;\n" + "\n" + "vec3 desaturate (const vec3 color, const float desaturation)\n" + "{\n" + " const vec3 gray_conv = vec3 (0.299, 0.587, 0.114);\n" + " vec3 gray = vec3 (dot (gray_conv, color));\n" + " return vec3 (mix (color.rgb, gray, desaturation));\n" + "}\n"; + +static const gchar *desaturate_glsl_source = + " cogl_color_out.rgb = desaturate (cogl_color_out.rgb, factor);\n"; + +enum +{ + PROP_0, + + PROP_FACTOR, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +G_DEFINE_TYPE (ClutterDesaturateEffect, + clutter_desaturate_effect, + CLUTTER_TYPE_OFFSCREEN_EFFECT); + +static gboolean +clutter_desaturate_effect_pre_paint (ClutterEffect *effect) +{ + ClutterDesaturateEffect *self = CLUTTER_DESATURATE_EFFECT (effect); + ClutterEffectClass *parent_class; + + if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect))) + return FALSE; + + if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) + { + /* if we don't have support for GLSL shaders then we + * forcibly disable the ActorMeta + */ + g_warning ("Unable to use the ShaderEffect: the graphics hardware " + "or the current GL driver does not implement support " + "for the GLSL shading language."); + clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (effect), FALSE); + return FALSE; + } + + parent_class = CLUTTER_EFFECT_CLASS (clutter_desaturate_effect_parent_class); + if (parent_class->pre_paint (effect)) + { + ClutterOffscreenEffect *offscreen_effect = + CLUTTER_OFFSCREEN_EFFECT (effect); + CoglHandle texture; + + texture = clutter_offscreen_effect_get_texture (offscreen_effect); + self->tex_width = cogl_texture_get_width (texture); + self->tex_height = cogl_texture_get_height (texture); + + cogl_pipeline_set_layer_texture (self->pipeline, 0, texture); + + return TRUE; + } + else + return FALSE; +} + +static void +clutter_desaturate_effect_paint_target (ClutterOffscreenEffect *effect) +{ + ClutterDesaturateEffect *self = CLUTTER_DESATURATE_EFFECT (effect); + ClutterActor *actor; + CoglHandle texture; + guint8 paint_opacity; + + texture = clutter_offscreen_effect_get_texture (effect); + cogl_pipeline_set_layer_texture (self->pipeline, 0, texture); + + actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); + paint_opacity = clutter_actor_get_paint_opacity (actor); + + cogl_pipeline_set_color4ub (self->pipeline, + paint_opacity, + paint_opacity, + paint_opacity, + paint_opacity); + cogl_push_source (self->pipeline); + + cogl_rectangle (0, 0, + cogl_texture_get_width (texture), + cogl_texture_get_height (texture)); + + cogl_pop_source (); +} + +static void +clutter_desaturate_effect_dispose (GObject *gobject) +{ + ClutterDesaturateEffect *self = CLUTTER_DESATURATE_EFFECT (gobject); + + if (self->pipeline != NULL) + { + cogl_object_unref (self->pipeline); + self->pipeline = NULL; + } + + G_OBJECT_CLASS (clutter_desaturate_effect_parent_class)->dispose (gobject); +} + +static void +clutter_desaturate_effect_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterDesaturateEffect *effect = CLUTTER_DESATURATE_EFFECT (gobject); + + switch (prop_id) + { + case PROP_FACTOR: + clutter_desaturate_effect_set_factor (effect, + g_value_get_double (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_desaturate_effect_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterDesaturateEffect *effect = CLUTTER_DESATURATE_EFFECT (gobject); + + switch (prop_id) + { + case PROP_FACTOR: + g_value_set_double (value, effect->factor); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +update_factor_uniform (ClutterDesaturateEffect *self) +{ + if (self->factor_uniform > -1) + cogl_pipeline_set_uniform_1f (self->pipeline, + self->factor_uniform, + self->factor); +} + +static void +clutter_desaturate_effect_class_init (ClutterDesaturateEffectClass *klass) +{ + ClutterEffectClass *effect_class = CLUTTER_EFFECT_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterOffscreenEffectClass *offscreen_class; + + offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass); + offscreen_class->paint_target = clutter_desaturate_effect_paint_target; + + effect_class->pre_paint = clutter_desaturate_effect_pre_paint; + + /** + * ClutterDesaturateEffect:factor: + * + * The desaturation factor, between 0.0 (no desaturation) and 1.0 (full + * desaturation). + * + * Since: 1.4 + */ + obj_props[PROP_FACTOR] = + g_param_spec_double ("factor", + P_("Factor"), + P_("The desaturation factor"), + 0.0, 1.0, + 1.0, + CLUTTER_PARAM_READWRITE); + + gobject_class->dispose = clutter_desaturate_effect_dispose; + gobject_class->set_property = clutter_desaturate_effect_set_property; + gobject_class->get_property = clutter_desaturate_effect_get_property; + + g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); +} + +static void +clutter_desaturate_effect_init (ClutterDesaturateEffect *self) +{ + ClutterDesaturateEffectClass *klass = CLUTTER_DESATURATE_EFFECT_GET_CLASS (self); + + if (G_UNLIKELY (klass->base_pipeline == NULL)) + { + CoglContext *ctx = + clutter_backend_get_cogl_context (clutter_get_default_backend ()); + CoglSnippet *snippet; + + klass->base_pipeline = cogl_pipeline_new (ctx); + + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, + desaturate_glsl_declarations, + desaturate_glsl_source); + cogl_pipeline_add_snippet (klass->base_pipeline, snippet); + cogl_object_unref (snippet); + + cogl_pipeline_set_layer_null_texture (klass->base_pipeline, + 0, /* layer number */ + COGL_TEXTURE_TYPE_2D); + } + + self->pipeline = cogl_pipeline_copy (klass->base_pipeline); + + self->factor_uniform = + cogl_pipeline_get_uniform_location (self->pipeline, "factor"); + + self->factor = 1.0; + + update_factor_uniform (self); +} + +/** + * clutter_desaturate_effect_new: + * @factor: the desaturation factor, between 0.0 and 1.0 + * + * Creates a new #ClutterDesaturateEffect to be used with + * clutter_actor_add_effect() + * + * Return value: the newly created #ClutterDesaturateEffect or %NULL + * + * Since: 1.4 + */ +ClutterEffect * +clutter_desaturate_effect_new (gdouble factor) +{ + g_return_val_if_fail (factor >= 0.0 && factor <= 1.0, NULL); + + return g_object_new (CLUTTER_TYPE_DESATURATE_EFFECT, + "factor", factor, + NULL); +} + +/** + * clutter_desaturate_effect_set_factor: + * @effect: a #ClutterDesaturateEffect + * @factor: the desaturation factor, between 0.0 and 1.0 + * + * Sets the desaturation factor for @effect, with 0.0 being "do not desaturate" + * and 1.0 being "fully desaturate" + * + * Since: 1.4 + */ +void +clutter_desaturate_effect_set_factor (ClutterDesaturateEffect *effect, + gdouble factor) +{ + g_return_if_fail (CLUTTER_IS_DESATURATE_EFFECT (effect)); + g_return_if_fail (factor >= 0.0 && factor <= 1.0); + + if (fabsf (effect->factor - factor) >= 0.00001) + { + effect->factor = factor; + update_factor_uniform (effect); + + clutter_effect_queue_repaint (CLUTTER_EFFECT (effect)); + + g_object_notify_by_pspec (G_OBJECT (effect), obj_props[PROP_FACTOR]); + } +} + +/** + * clutter_desaturate_effect_get_factor: + * @effect: a #ClutterDesaturateEffect + * + * Retrieves the desaturation factor of @effect + * + * Return value: the desaturation factor + * + * Since: 1.4 + */ +gdouble +clutter_desaturate_effect_get_factor (ClutterDesaturateEffect *effect) +{ + g_return_val_if_fail (CLUTTER_IS_DESATURATE_EFFECT (effect), 0.0); + + return effect->factor; +} diff --git a/clutter/clutter/clutter-desaturate-effect.h b/clutter/clutter/clutter-desaturate-effect.h new file mode 100644 index 0000000..58f10a4 --- /dev/null +++ b/clutter/clutter/clutter-desaturate-effect.h @@ -0,0 +1,65 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_DESATURATE_EFFECT_H__ +#define __CLUTTER_DESATURATE_EFFECT_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_DESATURATE_EFFECT (clutter_desaturate_effect_get_type ()) +#define CLUTTER_DESATURATE_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_DESATURATE_EFFECT, ClutterDesaturateEffect)) +#define CLUTTER_IS_DESATURATE_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_DESATURATE_EFFECT)) + +/** + * ClutterDesaturateEffect: + * + * #ClutterDesaturateEffect is an opaque structure + * whose members cannot be directly accessed + * + * Since: 1.4 + */ +typedef struct _ClutterDesaturateEffect ClutterDesaturateEffect; +typedef struct _ClutterDesaturateEffectClass ClutterDesaturateEffectClass; + +CLUTTER_AVAILABLE_IN_1_4 +GType clutter_desaturate_effect_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_4 +ClutterEffect *clutter_desaturate_effect_new (gdouble factor); + +CLUTTER_AVAILABLE_IN_1_4 +void clutter_desaturate_effect_set_factor (ClutterDesaturateEffect *effect, + gdouble factor); +CLUTTER_AVAILABLE_IN_1_4 +gdouble clutter_desaturate_effect_get_factor (ClutterDesaturateEffect *effect); + +G_END_DECLS + +#endif /* __CLUTTER_DESATURATE_EFFECT_H__ */ diff --git a/clutter/clutter/clutter-device-manager-private.h b/clutter/clutter/clutter-device-manager-private.h new file mode 100644 index 0000000..108e8c5 --- /dev/null +++ b/clutter/clutter/clutter-device-manager-private.h @@ -0,0 +1,264 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_DEVICE_MANAGER_PRIVATE_H__ +#define __CLUTTER_DEVICE_MANAGER_PRIVATE_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +typedef struct _ClutterAxisInfo +{ + ClutterInputAxis axis; + + gdouble min_axis; + gdouble max_axis; + + gdouble min_value; + gdouble max_value; + + gdouble resolution; +} ClutterAxisInfo; + +typedef struct _ClutterKeyInfo +{ + guint keyval; + ClutterModifierType modifiers; +} ClutterKeyInfo; + +typedef struct _ClutterScrollInfo +{ + guint axis_id; + ClutterScrollDirection direction; + gdouble increment; + + gdouble last_value; + guint last_value_valid : 1; +} ClutterScrollInfo; + +typedef struct _ClutterTouchInfo +{ + ClutterEventSequence *sequence; + ClutterActor *actor; + + gfloat current_x; + gfloat current_y; +} ClutterTouchInfo; + +struct _ClutterInputDevice +{ + GObject parent_instance; + + gint id; + + ClutterInputDeviceType device_type; + ClutterInputMode device_mode; + + gchar *device_name; + + ClutterDeviceManager *device_manager; + + ClutterBackend *backend; + + /* the associated device */ + ClutterInputDevice *associated; + + GList *slaves; + + /* the actor underneath the pointer */ + ClutterActor *cursor_actor; + GHashTable *inv_touch_sequence_actors; + + /* the actor that has a grab in place for the device */ + ClutterActor *pointer_grab_actor; + ClutterActor *keyboard_grab_actor; + GHashTable *sequence_grab_actors; + GHashTable *inv_sequence_grab_actors; + + /* the current click count */ + gint click_count; + + /* the stage the device is on */ + ClutterStage *stage; + + /* the current state */ + gfloat current_x; + gfloat current_y; + guint32 current_time; + gint current_button_number; + ClutterModifierType current_state; + + /* the current touch points states */ + GHashTable *touch_sequences_info; + + /* the previous state, used for click count generation */ + gint previous_x; + gint previous_y; + guint32 previous_time; + gint previous_button_number; + ClutterModifierType previous_state; + + GArray *axes; + + guint n_keys; + GArray *keys; + + GArray *scroll_info; + + gchar *vendor_id; + gchar *product_id; + gchar *node_path; + + GPtrArray *tools; + + gint n_rings; + gint n_strips; + gint n_mode_groups; + + ClutterInputDeviceMapping mapping_mode; + + guint has_cursor : 1; + guint is_enabled : 1; +}; + +struct _ClutterInputDeviceClass +{ + GObjectClass parent_class; + + gboolean (* keycode_to_evdev) (ClutterInputDevice *device, + guint hardware_keycode, + guint *evdev_keycode); + void (* update_from_tool) (ClutterInputDevice *device, + ClutterInputDeviceTool *tool); +}; + +/* Platform-dependent interface */ +typedef struct _ClutterEventExtender ClutterEventExtender; +typedef struct _ClutterEventExtenderInterface ClutterEventExtenderInterface; + +#define CLUTTER_TYPE_EVENT_EXTENDER (clutter_event_extender_get_type ()) +#define CLUTTER_EVENT_EXTENDER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CLUTTER_TYPE_EVENT_EXTENDER, ClutterEventExtender)) +#define CLUTTER_IS_EVENT_EXTENDER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CLUTTER_TYPE_EVENT_EXTENDER)) +#define CLUTTER_EVENT_EXTENDER_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), CLUTTER_TYPE_EVENT_EXTENDER, ClutterEventExtenderInterface)) + +struct _ClutterEventExtenderInterface +{ + GTypeInterface g_iface; + + void (* copy_event_data) (ClutterEventExtender *event_extender, + const ClutterEvent *src, + ClutterEvent *dest); + void (* free_event_data) (ClutterEventExtender *event_extender, + ClutterEvent *event); +}; + +GType clutter_event_extender_get_type (void) G_GNUC_CONST; + +/* device manager */ +void _clutter_device_manager_add_device (ClutterDeviceManager *device_manager, + ClutterInputDevice *device); +void _clutter_device_manager_remove_device (ClutterDeviceManager *device_manager, + ClutterInputDevice *device); +void _clutter_device_manager_update_devices (ClutterDeviceManager *device_manager); +void _clutter_device_manager_select_stage_events (ClutterDeviceManager *device_manager, + ClutterStage *stage); +ClutterBackend *_clutter_device_manager_get_backend (ClutterDeviceManager *device_manager); + +void _clutter_device_manager_compress_motion (ClutterDeviceManager *device_manger, + ClutterEvent *event, + const ClutterEvent *to_discard); + +/* input device */ +gboolean _clutter_input_device_has_sequence (ClutterInputDevice *device, + ClutterEventSequence *sequence); +void _clutter_input_device_add_event_sequence (ClutterInputDevice *device, + ClutterEvent *event); +void _clutter_input_device_remove_event_sequence (ClutterInputDevice *device, + ClutterEvent *event); +void _clutter_input_device_set_coords (ClutterInputDevice *device, + ClutterEventSequence *sequence, + gfloat x, + gfloat y, + ClutterStage *stage); +void _clutter_input_device_set_state (ClutterInputDevice *device, + ClutterModifierType state); +void _clutter_input_device_set_time (ClutterInputDevice *device, + guint32 time_); +void _clutter_input_device_set_stage (ClutterInputDevice *device, + ClutterStage *stage); +ClutterStage * _clutter_input_device_get_stage (ClutterInputDevice *device); +void _clutter_input_device_set_actor (ClutterInputDevice *device, + ClutterEventSequence *sequence, + ClutterActor *actor, + gboolean emit_crossing); +ClutterActor * _clutter_input_device_update (ClutterInputDevice *device, + ClutterEventSequence *sequence, + gboolean emit_crossing); +void _clutter_input_device_set_n_keys (ClutterInputDevice *device, + guint n_keys); +guint _clutter_input_device_add_axis (ClutterInputDevice *device, + ClutterInputAxis axis, + gdouble min_value, + gdouble max_value, + gdouble resolution); +void _clutter_input_device_reset_axes (ClutterInputDevice *device); + +void _clutter_input_device_set_associated_device (ClutterInputDevice *device, + ClutterInputDevice *associated); +void _clutter_input_device_add_slave (ClutterInputDevice *master, + ClutterInputDevice *slave); +void _clutter_input_device_remove_slave (ClutterInputDevice *master, + ClutterInputDevice *slave); + +gboolean _clutter_input_device_translate_axis (ClutterInputDevice *device, + guint index_, + gdouble value, + gdouble *axis_value); + +void _clutter_input_device_add_scroll_info (ClutterInputDevice *device, + guint index_, + ClutterScrollDirection direction, + gdouble increment); +void _clutter_input_device_reset_scroll_info (ClutterInputDevice *device); +gboolean _clutter_input_device_get_scroll_delta (ClutterInputDevice *device, + guint index_, + gdouble value, + ClutterScrollDirection *direction_p, + gdouble *delta_p); + +ClutterInputDeviceTool * clutter_input_device_lookup_tool (ClutterInputDevice *device, + guint64 serial, + ClutterInputDeviceToolType type); +void clutter_input_device_add_tool (ClutterInputDevice *device, + ClutterInputDeviceTool *tool); + +void clutter_input_device_update_from_tool (ClutterInputDevice *device, + ClutterInputDeviceTool *tool); + +G_END_DECLS + +#endif /* __CLUTTER_DEVICE_MANAGER_PRIVATE_H__ */ diff --git a/clutter/clutter/clutter-device-manager.c b/clutter/clutter/clutter-device-manager.c new file mode 100644 index 0000000..f9222e7 --- /dev/null +++ b/clutter/clutter/clutter-device-manager.c @@ -0,0 +1,477 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2009 Intel Corp. + * + * 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 . + * + * Author: Emmanuele Bassi + */ + +/** + * SECTION:clutter-device-manager + * @short_description: Maintains the list of input devices + * + * #ClutterDeviceManager is a singleton object, owned by Clutter, which + * maintains the list of #ClutterInputDevices. + * + * Depending on the backend used by Clutter it is possible to use the + * #ClutterDeviceManager::device-added and + * #ClutterDeviceManager::device-removed to monitor addition and removal + * of devices. + * + * #ClutterDeviceManager is available since Clutter 1.2 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-backend-private.h" +#include "clutter-debug.h" +#include "clutter-device-manager-private.h" +#include "clutter-enum-types.h" +#include "clutter-marshal.h" +#include "clutter-private.h" +#include "clutter-stage-private.h" +#include "clutter-virtual-input-device.h" + +struct _ClutterDeviceManagerPrivate +{ + /* back-pointer to the backend */ + ClutterBackend *backend; +}; + +enum +{ + PROP_0, + + PROP_BACKEND, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +enum +{ + DEVICE_ADDED, + DEVICE_REMOVED, + + LAST_SIGNAL +}; + +static guint manager_signals[LAST_SIGNAL] = { 0, }; + +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterDeviceManager, + clutter_device_manager, + G_TYPE_OBJECT) + +G_DEFINE_INTERFACE (ClutterEventExtender, + clutter_event_extender, + CLUTTER_TYPE_DEVICE_MANAGER) + +static void +clutter_event_extender_default_init (ClutterEventExtenderInterface *iface) +{ +} + +static void +clutter_device_manager_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterDeviceManagerPrivate *priv = CLUTTER_DEVICE_MANAGER (gobject)->priv; + + switch (prop_id) + { + case PROP_BACKEND: + priv->backend = g_value_get_object (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + } +} + +static void +clutter_device_manager_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterDeviceManagerPrivate *priv = CLUTTER_DEVICE_MANAGER (gobject)->priv; + + switch (prop_id) + { + case PROP_BACKEND: + g_value_set_object (value, priv->backend); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + } +} + +static void +clutter_device_manager_class_init (ClutterDeviceManagerClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + obj_props[PROP_BACKEND] = + g_param_spec_object ("backend", + P_("Backend"), + P_("The ClutterBackend of the device manager"), + CLUTTER_TYPE_BACKEND, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + + gobject_class->set_property = clutter_device_manager_set_property; + gobject_class->get_property = clutter_device_manager_get_property; + g_object_class_install_properties (gobject_class, + PROP_LAST, + obj_props); + + /** + * ClutterDeviceManager::device-added: + * @manager: the #ClutterDeviceManager that emitted the signal + * @device: the newly added #ClutterInputDevice + * + * The ::device-added signal is emitted each time a device has been + * added to the #ClutterDeviceManager + * + * Since: 1.2 + */ + manager_signals[DEVICE_ADDED] = + g_signal_new (I_("device-added"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + _clutter_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CLUTTER_TYPE_INPUT_DEVICE); + + /** + * ClutterDeviceManager::device-removed: + * @manager: the #ClutterDeviceManager that emitted the signal + * @device: the removed #ClutterInputDevice + * + * The ::device-removed signal is emitted each time a device has been + * removed from the #ClutterDeviceManager + * + * Since: 1.2 + */ + manager_signals[DEVICE_REMOVED] = + g_signal_new (I_("device-removed"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + _clutter_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CLUTTER_TYPE_INPUT_DEVICE); +} + +static void +clutter_device_manager_init (ClutterDeviceManager *self) +{ + self->priv = clutter_device_manager_get_instance_private (self); +} + +/** + * clutter_device_manager_get_default: + * + * Retrieves the device manager singleton + * + * Return value: (transfer none): the #ClutterDeviceManager singleton. + * The returned instance is owned by Clutter and it should not be + * modified or freed + * + * Since: 1.2 + */ +ClutterDeviceManager * +clutter_device_manager_get_default (void) +{ + ClutterBackend *backend = clutter_get_default_backend (); + + return backend->device_manager; +} + +/** + * clutter_device_manager_list_devices: + * @device_manager: a #ClutterDeviceManager + * + * Lists all currently registered input devices + * + * Return value: (transfer container) (element-type Clutter.InputDevice): + * a newly allocated list of #ClutterInputDevice objects. Use + * g_slist_free() to deallocate it when done + * + * Since: 1.2 + */ +GSList * +clutter_device_manager_list_devices (ClutterDeviceManager *device_manager) +{ + const GSList *devices; + + g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager), NULL); + + devices = clutter_device_manager_peek_devices (device_manager); + + return g_slist_copy ((GSList *) devices); +} + +/** + * clutter_device_manager_peek_devices: + * @device_manager: a #ClutterDeviceManager + * + * Lists all currently registered input devices + * + * Return value: (transfer none) (element-type Clutter.InputDevice): + * a pointer to the internal list of #ClutterInputDevice objects. The + * returned list is owned by the #ClutterDeviceManager and should never + * be modified or freed + * + * Since: 1.2 + */ +const GSList * +clutter_device_manager_peek_devices (ClutterDeviceManager *device_manager) +{ + ClutterDeviceManagerClass *manager_class; + + g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager), NULL); + + manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager); + return manager_class->get_devices (device_manager); +} + +/** + * clutter_device_manager_get_device: + * @device_manager: a #ClutterDeviceManager + * @device_id: the integer id of a device + * + * Retrieves the #ClutterInputDevice with the given @device_id + * + * Return value: (transfer none): a #ClutterInputDevice or %NULL. The + * returned device is owned by the #ClutterDeviceManager and should + * never be modified or freed + * + * Since: 1.2 + */ +ClutterInputDevice * +clutter_device_manager_get_device (ClutterDeviceManager *device_manager, + gint device_id) +{ + ClutterDeviceManagerClass *manager_class; + + g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager), NULL); + + manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager); + return manager_class->get_device (device_manager, device_id); +} + +/** + * clutter_device_manager_get_core_device: + * @device_manager: a #ClutterDeviceManager + * @device_type: the type of the core device + * + * Retrieves the core #ClutterInputDevice of type @device_type + * + * Core devices are devices created automatically by the default + * Clutter backend + * + * Return value: (transfer none): a #ClutterInputDevice or %NULL. The + * returned device is owned by the #ClutterDeviceManager and should + * not be modified or freed + * + * Since: 1.2 + */ +ClutterInputDevice * +clutter_device_manager_get_core_device (ClutterDeviceManager *device_manager, + ClutterInputDeviceType device_type) +{ + ClutterDeviceManagerClass *manager_class; + + g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager), NULL); + + manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager); + return manager_class->get_core_device (device_manager, device_type); +} + +void +_clutter_device_manager_select_stage_events (ClutterDeviceManager *device_manager, + ClutterStage *stage) +{ + ClutterDeviceManagerClass *manager_class; + + g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager)); + + manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager); + if (manager_class->select_stage_events) + manager_class->select_stage_events (device_manager, stage); +} + +/* + * _clutter_device_manager_add_device: + * @device_manager: a #ClutterDeviceManager + * @device: a #ClutterInputDevice + * + * Adds @device to the list of #ClutterInputDevices maintained + * by @device_manager + * + * The reference count of @device is not increased + * + * The #ClutterDeviceManager::device-added signal is emitted after + * adding @device to the list + */ +void +_clutter_device_manager_add_device (ClutterDeviceManager *device_manager, + ClutterInputDevice *device) +{ + ClutterDeviceManagerClass *manager_class; + + g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager)); + + manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager); + g_assert (manager_class->add_device != NULL); + + manager_class->add_device (device_manager, device); + + g_signal_emit (device_manager, manager_signals[DEVICE_ADDED], 0, device); +} + +/* + * _clutter_device_manager_remove_device: + * @device_manager: a #ClutterDeviceManager + * @device: a #ClutterInputDevice + * + * Removes @device from the list of #ClutterInputDevices + * maintained by @device_manager + * + * The reference count of @device is not decreased + * + * The #ClutterDeviceManager::device-removed signal is emitted after + * removing @device from the list + */ +void +_clutter_device_manager_remove_device (ClutterDeviceManager *device_manager, + ClutterInputDevice *device) +{ + ClutterDeviceManagerClass *manager_class; + + g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager)); + + manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager); + g_assert (manager_class->remove_device != NULL); + + /* The subclass remove_device() method will likely unref it but we + have to keep it alive during the signal emission. */ + g_object_ref (device); + + manager_class->remove_device (device_manager, device); + g_signal_emit (device_manager, manager_signals[DEVICE_REMOVED], 0, device); + + g_object_unref (device); +} + +/* + * _clutter_device_manager_update_devices: + * @device_manager: a #ClutterDeviceManager + * + * Updates every #ClutterInputDevice handled by @device_manager + * by performing a pick paint at the coordinates of each pointer + * device + */ +void +_clutter_device_manager_update_devices (ClutterDeviceManager *device_manager) +{ + const GSList *d; + + for (d = clutter_device_manager_peek_devices (device_manager); + d != NULL; + d = d->next) + { + ClutterInputDevice *device = d->data; + ClutterInputDeviceType device_type; + + /* we only care about pointer devices */ + device_type = clutter_input_device_get_device_type (device); + if (device_type != CLUTTER_POINTER_DEVICE) + continue; + + /* out of stage */ + if (device->stage == NULL) + continue; + + /* the user disabled motion events delivery on actors for + * the stage the device is on; we don't perform any picking + * since the source of the events will always be set to be + * the stage + */ + if (!clutter_stage_get_motion_events_enabled (device->stage)) + continue; + + _clutter_input_device_update (device, NULL, TRUE); + } +} + +ClutterBackend * +_clutter_device_manager_get_backend (ClutterDeviceManager *manager) +{ + g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER (manager), NULL); + + return manager->priv->backend; +} + +/** + * clutter_device_manager_create_virtual_device: + * @device_manager: a #ClutterDeviceManager + * @device_type: the type of the virtual device + * + * Creates a virtual input device. + * + * Returns: (transfer full): a newly created virtual device + **/ +ClutterVirtualInputDevice * +clutter_device_manager_create_virtual_device (ClutterDeviceManager *device_manager, + ClutterInputDeviceType device_type) +{ + ClutterDeviceManagerClass *manager_class; + + g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager), NULL); + + manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager); + return manager_class->create_virtual_device (device_manager, + device_type); +} + +void +_clutter_device_manager_compress_motion (ClutterDeviceManager *device_manager, + ClutterEvent *event, + const ClutterEvent *to_discard) +{ + ClutterDeviceManagerClass *manager_class; + + g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager)); + + + manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager); + if (!manager_class->compress_motion) + return; + + manager_class->compress_motion (device_manager, event, to_discard); +} diff --git a/clutter/clutter/clutter-device-manager.h b/clutter/clutter/clutter-device-manager.h new file mode 100644 index 0000000..926d3b5 --- /dev/null +++ b/clutter/clutter/clutter-device-manager.h @@ -0,0 +1,119 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2009 Intel Corp. + * + * 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 . + * + * Author: Emmanuele Bassi + */ + +#ifndef __CLUTTER_DEVICE_MANAGER_H__ +#define __CLUTTER_DEVICE_MANAGER_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_DEVICE_MANAGER (clutter_device_manager_get_type ()) +#define CLUTTER_DEVICE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_DEVICE_MANAGER, ClutterDeviceManager)) +#define CLUTTER_IS_DEVICE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_DEVICE_MANAGER)) +#define CLUTTER_DEVICE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_DEVICE_MANAGER, ClutterDeviceManagerClass)) +#define CLUTTER_IS_DEVICE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_DEVICE_MANAGER)) +#define CLUTTER_DEVICE_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_DEVICE_MANAGER, ClutterDeviceManagerClass)) + +typedef struct _ClutterDeviceManager ClutterDeviceManager; +typedef struct _ClutterDeviceManagerPrivate ClutterDeviceManagerPrivate; +typedef struct _ClutterDeviceManagerClass ClutterDeviceManagerClass; + +/** + * ClutterDeviceManager: + * + * The #ClutterDeviceManager structure contains only private data + * + * Since: 1.2 + */ +struct _ClutterDeviceManager +{ + /*< private >*/ + GObject parent_instance; + + ClutterDeviceManagerPrivate *priv; +}; + +/** + * ClutterDeviceManagerClass: + * + * The #ClutterDeviceManagerClass structure contains only private data + * + * Since: 1.2 + */ +struct _ClutterDeviceManagerClass +{ + /*< private >*/ + GObjectClass parent_class; + + const GSList * (* get_devices) (ClutterDeviceManager *device_manager); + ClutterInputDevice *(* get_core_device) (ClutterDeviceManager *device_manager, + ClutterInputDeviceType device_type); + ClutterInputDevice *(* get_device) (ClutterDeviceManager *device_manager, + gint device_id); + + void (* add_device) (ClutterDeviceManager *manager, + ClutterInputDevice *device); + void (* remove_device) (ClutterDeviceManager *manager, + ClutterInputDevice *device); + void (* select_stage_events) (ClutterDeviceManager *manager, + ClutterStage *stage); + ClutterVirtualInputDevice *(* create_virtual_device) (ClutterDeviceManager *manager, + ClutterInputDeviceType device_type); + void (* compress_motion) (ClutterDeviceManager *device_manger, + ClutterEvent *event, + const ClutterEvent *to_discard); + + /* padding */ + gpointer _padding[6]; +}; + +CLUTTER_AVAILABLE_IN_1_2 +GType clutter_device_manager_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_2 +ClutterDeviceManager *clutter_device_manager_get_default (void); +CLUTTER_AVAILABLE_IN_1_2 +GSList * clutter_device_manager_list_devices (ClutterDeviceManager *device_manager); +CLUTTER_AVAILABLE_IN_1_2 +const GSList * clutter_device_manager_peek_devices (ClutterDeviceManager *device_manager); + +CLUTTER_AVAILABLE_IN_1_2 +ClutterInputDevice * clutter_device_manager_get_device (ClutterDeviceManager *device_manager, + gint device_id); +CLUTTER_AVAILABLE_IN_1_2 +ClutterInputDevice * clutter_device_manager_get_core_device (ClutterDeviceManager *device_manager, + ClutterInputDeviceType device_type); + +CLUTTER_AVAILABLE_IN_ALL +ClutterVirtualInputDevice *clutter_device_manager_create_virtual_device (ClutterDeviceManager *device_manager, + ClutterInputDeviceType device_type); + +G_END_DECLS + +#endif /* __CLUTTER_DEVICE_MANAGER_H__ */ diff --git a/clutter/clutter/clutter-drag-action.c b/clutter/clutter/clutter-drag-action.c new file mode 100644 index 0000000..57dae72 --- /dev/null +++ b/clutter/clutter/clutter-drag-action.c @@ -0,0 +1,1322 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-drag-action + * @Title: ClutterDragAction + * @Short_Description: Action enabling dragging on actors + * + * #ClutterDragAction is a sub-class of #ClutterAction that implements + * all the necessary logic for dragging actors. + * + * The simplest usage of #ClutterDragAction consists in adding it to + * a #ClutterActor and setting it as reactive; for instance, the following + * code: + * + * |[ + * clutter_actor_add_action (actor, clutter_drag_action_new ()); + * clutter_actor_set_reactive (actor, TRUE); + * ]| + * + * will automatically result in the actor moving to follow the pointer + * whenever the pointer's button is pressed over the actor and moved + * across the stage. + * + * The #ClutterDragAction will signal the begin and the end of a dragging + * through the #ClutterDragAction::drag-begin and #ClutterDragAction::drag-end + * signals, respectively. Each pointer motion during a drag will also result + * in the #ClutterDragAction::drag-motion signal to be emitted. + * + * It is also possible to set another #ClutterActor as the dragged actor + * by calling clutter_drag_action_set_drag_handle() from within a handle + * of the #ClutterDragAction::drag-begin signal. The drag handle must be + * parented and exist between the emission of #ClutterDragAction::drag-begin + * and #ClutterDragAction::drag-end. + * + * The [drag-action example](https://git.gnome.org/browse/clutter/tree/examples/drag-action.c?h=clutter-1.18) + * allows dragging the rectangle around the stage using a #ClutterDragAction. + * When pressing the `Shift` key the actor that is being dragged will be a + * separate rectangle, and when the drag ends, the original rectangle will be + * animated to the final drop coordinates. + * + * #ClutterDragAction is available since Clutter 1.4 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-drag-action.h" + +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-marshal.h" +#include "clutter-private.h" +#include "clutter-stage-private.h" + +struct _ClutterDragActionPrivate +{ + ClutterStage *stage; + + gint x_drag_threshold; + gint y_drag_threshold; + ClutterActor *drag_handle; + ClutterDragAxis drag_axis; + ClutterRect drag_area; + + ClutterInputDevice *device; + ClutterEventSequence *sequence; + gulong button_press_id; + gulong touch_begin_id; + gulong capture_id; + + gfloat press_x; + gfloat press_y; + ClutterModifierType press_state; + + gfloat last_motion_x; + gfloat last_motion_y; + ClutterModifierType last_motion_state; + ClutterInputDevice *last_motion_device; + + gfloat transformed_press_x; + gfloat transformed_press_y; + + guint emit_delayed_press : 1; + guint in_drag : 1; + guint motion_events_enabled : 1; + guint drag_area_set : 1; +}; + +enum +{ + PROP_0, + + PROP_X_DRAG_THRESHOLD, + PROP_Y_DRAG_THRESHOLD, + PROP_DRAG_HANDLE, + PROP_DRAG_AXIS, + PROP_DRAG_AREA, + PROP_DRAG_AREA_SET, + + PROP_LAST +}; + +static GParamSpec *drag_props[PROP_LAST] = { NULL, }; + +enum +{ + DRAG_BEGIN, + DRAG_PROGRESS, + DRAG_MOTION, + DRAG_END, + + LAST_SIGNAL +}; + +static guint drag_signals[LAST_SIGNAL] = { 0, }; + +/* forward declaration */ +static gboolean on_captured_event (ClutterActor *stage, + ClutterEvent *event, + ClutterDragAction *action); + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterDragAction, clutter_drag_action, CLUTTER_TYPE_ACTION) + +static void +get_drag_threshold (ClutterDragAction *action, + gint *x_threshold, + gint *y_threshold) +{ + ClutterDragActionPrivate *priv = action->priv; + ClutterSettings *settings = clutter_settings_get_default (); + gint x_res, y_res, default_threshold; + + g_object_get (settings, "dnd-drag-threshold", &default_threshold, NULL); + + if (priv->x_drag_threshold < 0) + x_res = default_threshold; + else + x_res = priv->x_drag_threshold; + + if (priv->y_drag_threshold < 0) + y_res = default_threshold; + else + y_res = priv->y_drag_threshold; + + if (x_threshold != NULL) + *x_threshold = x_res; + + if (y_threshold != NULL) + *y_threshold = y_res; +} + +static void +emit_drag_begin (ClutterDragAction *action, + ClutterActor *actor, + ClutterEvent *event) +{ + ClutterDragActionPrivate *priv = action->priv; + + if (priv->stage != NULL) + { + clutter_stage_set_motion_events_enabled (priv->stage, FALSE); + if (clutter_event_type (event) == CLUTTER_TOUCH_BEGIN) + _clutter_stage_add_touch_drag_actor (priv->stage, + clutter_event_get_event_sequence (event), + priv->drag_handle != NULL + ? priv->drag_handle + : actor); + else + _clutter_stage_add_pointer_drag_actor (priv->stage, + clutter_event_get_device (event), + priv->drag_handle != NULL + ? priv->drag_handle + : actor); + } + + g_signal_emit (action, drag_signals[DRAG_BEGIN], 0, + actor, + priv->press_x, priv->press_y, + priv->press_state); +} + +static void +emit_drag_motion (ClutterDragAction *action, + ClutterActor *actor, + ClutterEvent *event) +{ + ClutterDragActionPrivate *priv = action->priv; + ClutterActor *drag_handle = NULL; + gfloat delta_x, delta_y; + gfloat motion_x, motion_y; + gboolean can_emit_drag_motion = TRUE; + + clutter_event_get_coords (event, &priv->last_motion_x, &priv->last_motion_y); + priv->last_motion_state = clutter_event_get_state (event); + priv->last_motion_device = clutter_event_get_device (event); + + if (priv->drag_handle != NULL && !priv->emit_delayed_press) + drag_handle = priv->drag_handle; + else + drag_handle = actor; + + motion_x = motion_y = 0.0f; + clutter_actor_transform_stage_point (drag_handle, + priv->last_motion_x, + priv->last_motion_y, + &motion_x, &motion_y); + + delta_x = delta_y = 0.0f; + + switch (priv->drag_axis) + { + case CLUTTER_DRAG_AXIS_NONE: + delta_x = motion_x - priv->transformed_press_x; + delta_y = motion_y - priv->transformed_press_y; + break; + + case CLUTTER_DRAG_X_AXIS: + delta_x = motion_x - priv->transformed_press_x; + break; + + case CLUTTER_DRAG_Y_AXIS: + delta_y = motion_y - priv->transformed_press_y; + break; + + default: + g_assert_not_reached (); + return; + } + + if (priv->emit_delayed_press) + { + gint x_drag_threshold, y_drag_threshold; + + get_drag_threshold (action, &x_drag_threshold, &y_drag_threshold); + + if (ABS (delta_x) >= x_drag_threshold || + ABS (delta_y) >= y_drag_threshold) + { + priv->emit_delayed_press = FALSE; + + emit_drag_begin (action, actor, event); + } + else + return; + } + + g_signal_emit (action, drag_signals[DRAG_PROGRESS], 0, + actor, + delta_x, delta_y, + &can_emit_drag_motion); + + if (can_emit_drag_motion) + { + g_signal_emit (action, drag_signals[DRAG_MOTION], 0, + actor, + delta_x, delta_y); + } +} + +static void +emit_drag_end (ClutterDragAction *action, + ClutterActor *actor, + ClutterEvent *event) +{ + ClutterDragActionPrivate *priv = action->priv; + + /* ::drag-end may result in the destruction of the actor, which in turn + * will lead to the removal and finalization of the action, so we need + * to keep the action alive for the entire emission sequence + */ + g_object_ref (action); + + /* if we have an event, update our own state, otherwise we'll + * just use the currently stored state when emitting the ::drag-end + * signal + */ + if (event != NULL) + { + clutter_event_get_coords (event, &priv->last_motion_x, &priv->last_motion_y); + priv->last_motion_state = clutter_event_get_state (event); + priv->last_motion_device = clutter_event_get_device (event); + } + + priv->in_drag = FALSE; + + /* we might not have emitted ::drag-begin yet */ + if (!priv->emit_delayed_press) + g_signal_emit (action, drag_signals[DRAG_END], 0, + actor, + priv->last_motion_x, priv->last_motion_y, + priv->last_motion_state); + + if (priv->stage == NULL) + goto out; + + /* disconnect the capture */ + if (priv->capture_id != 0) + { + g_signal_handler_disconnect (priv->stage, priv->capture_id); + priv->capture_id = 0; + } + + clutter_stage_set_motion_events_enabled (priv->stage, + priv->motion_events_enabled); + + if (priv->last_motion_device != NULL && event != NULL) + { + if (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE) + _clutter_stage_remove_pointer_drag_actor (priv->stage, + priv->last_motion_device); + else + _clutter_stage_remove_touch_drag_actor (priv->stage, + priv->sequence); + } + +out: + priv->last_motion_device = NULL; + priv->sequence = NULL; + + g_object_unref (action); +} + +static gboolean +on_captured_event (ClutterActor *stage, + ClutterEvent *event, + ClutterDragAction *action) +{ + ClutterDragActionPrivate *priv = action->priv; + ClutterActor *actor; + + actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action)); + + if (!priv->in_drag) + return CLUTTER_EVENT_PROPAGATE; + + if (clutter_event_get_device (event) != priv->device || + clutter_event_get_event_sequence (event) != priv->sequence) + return CLUTTER_EVENT_PROPAGATE; + + switch (clutter_event_type (event)) + { + case CLUTTER_TOUCH_UPDATE: + emit_drag_motion (action, actor, event); + break; + + case CLUTTER_MOTION: + { + ClutterModifierType mods = clutter_event_get_state (event); + + /* we might miss a button-release event in case of grabs, + * so we need to check whether the button is still down + * during a motion event + */ + if (mods & CLUTTER_BUTTON1_MASK) + emit_drag_motion (action, actor, event); + else + emit_drag_end (action, actor, event); + } + break; + + case CLUTTER_TOUCH_END: + case CLUTTER_TOUCH_CANCEL: + emit_drag_end (action, actor, event); + break; + + case CLUTTER_BUTTON_RELEASE: + if (priv->in_drag) + emit_drag_end (action, actor, event); + break; + + case CLUTTER_ENTER: + case CLUTTER_LEAVE: + if (priv->in_drag) + return CLUTTER_EVENT_STOP; + break; + + default: + break; + } + + return CLUTTER_EVENT_PROPAGATE; +} + +static gboolean +on_drag_begin (ClutterActor *actor, + ClutterEvent *event, + ClutterDragAction *action) +{ + ClutterDragActionPrivate *priv = action->priv; + + if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (action))) + return CLUTTER_EVENT_PROPAGATE; + + /* dragging is only performed using the primary button */ + switch (clutter_event_type (event)) + { + case CLUTTER_BUTTON_PRESS: + if (priv->sequence != NULL) + return CLUTTER_EVENT_PROPAGATE; + if (clutter_event_get_button (event) != CLUTTER_BUTTON_PRIMARY) + return CLUTTER_EVENT_PROPAGATE; + break; + + case CLUTTER_TOUCH_BEGIN: + if (priv->sequence != NULL) + return CLUTTER_EVENT_PROPAGATE; + priv->sequence = clutter_event_get_event_sequence (event); + break; + + default: + return CLUTTER_EVENT_PROPAGATE; + } + + if (priv->stage == NULL) + priv->stage = CLUTTER_STAGE (clutter_actor_get_stage (actor)); + + clutter_event_get_coords (event, &priv->press_x, &priv->press_y); + priv->press_state = clutter_event_get_state (event); + + priv->device = clutter_event_get_device (event); + + priv->last_motion_x = priv->press_x; + priv->last_motion_y = priv->press_y; + + priv->transformed_press_x = priv->press_x; + priv->transformed_press_y = priv->press_y; + clutter_actor_transform_stage_point (actor, priv->press_x, priv->press_y, + &priv->transformed_press_x, + &priv->transformed_press_y); + + priv->motion_events_enabled = + clutter_stage_get_motion_events_enabled (priv->stage); + + if (priv->x_drag_threshold == 0 || priv->y_drag_threshold == 0) + emit_drag_begin (action, actor, event); + else + priv->emit_delayed_press = TRUE; + + priv->in_drag = TRUE; + priv->capture_id = g_signal_connect_after (priv->stage, "captured-event", + G_CALLBACK (on_captured_event), + action); + + return CLUTTER_EVENT_PROPAGATE; +} + +static void +clutter_drag_action_set_actor (ClutterActorMeta *meta, + ClutterActor *actor) +{ + ClutterDragActionPrivate *priv = CLUTTER_DRAG_ACTION (meta)->priv; + + if (priv->button_press_id != 0) + { + ClutterActor *old_actor; + + old_actor = clutter_actor_meta_get_actor (meta); + if (old_actor != NULL) + { + g_signal_handler_disconnect (old_actor, priv->button_press_id); + g_signal_handler_disconnect (old_actor, priv->touch_begin_id); + } + + priv->button_press_id = 0; + priv->touch_begin_id = 0; + } + + if (priv->capture_id != 0) + { + if (priv->stage != NULL) + g_signal_handler_disconnect (priv->stage, priv->capture_id); + + priv->capture_id = 0; + priv->stage = NULL; + } + + clutter_drag_action_set_drag_handle (CLUTTER_DRAG_ACTION (meta), NULL); + + priv->in_drag = FALSE; + + if (actor != NULL) + { + priv->button_press_id = g_signal_connect (actor, "button-press-event", + G_CALLBACK (on_drag_begin), + meta); + priv->touch_begin_id = g_signal_connect (actor, "touch-event", + G_CALLBACK (on_drag_begin), + meta); + } + + CLUTTER_ACTOR_META_CLASS (clutter_drag_action_parent_class)->set_actor (meta, actor); +} + +static gboolean +clutter_drag_action_real_drag_progress (ClutterDragAction *action, + ClutterActor *actor, + gfloat delta_x, + gfloat delta_y) +{ + return TRUE; +} + +static void +clutter_drag_action_real_drag_motion (ClutterDragAction *action, + ClutterActor *actor, + gfloat delta_x, + gfloat delta_y) +{ + ClutterActor *drag_handle; + gfloat x, y; + + if (action->priv->drag_handle != NULL) + drag_handle = action->priv->drag_handle; + else + drag_handle = actor; + + clutter_actor_get_position (drag_handle, &x, &y); + + x += delta_x; + y += delta_y; + + if (action->priv->drag_area_set) + { + ClutterRect *drag_area = &action->priv->drag_area; + + x = CLAMP (x, drag_area->origin.x, drag_area->origin.x + drag_area->size.width); + y = CLAMP (y, drag_area->origin.y, drag_area->origin.y + drag_area->size.height); + } + + clutter_actor_set_position (drag_handle, x, y); +} + +static void +clutter_drag_action_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterDragAction *action = CLUTTER_DRAG_ACTION (gobject); + ClutterDragActionPrivate *priv = action->priv; + + switch (prop_id) + { + case PROP_X_DRAG_THRESHOLD: + clutter_drag_action_set_drag_threshold (action, + g_value_get_int (value), + priv->y_drag_threshold); + break; + + case PROP_Y_DRAG_THRESHOLD: + clutter_drag_action_set_drag_threshold (action, + priv->x_drag_threshold, + g_value_get_int (value)); + break; + + case PROP_DRAG_HANDLE: + clutter_drag_action_set_drag_handle (action, g_value_get_object (value)); + break; + + case PROP_DRAG_AXIS: + clutter_drag_action_set_drag_axis (action, g_value_get_enum (value)); + break; + + case PROP_DRAG_AREA: + clutter_drag_action_set_drag_area (action, g_value_get_boxed (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + } +} + +static void +clutter_drag_action_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterDragActionPrivate *priv = CLUTTER_DRAG_ACTION (gobject)->priv; + + switch (prop_id) + { + case PROP_X_DRAG_THRESHOLD: + { + gint threshold; + + get_drag_threshold (CLUTTER_DRAG_ACTION (gobject), &threshold, NULL); + g_value_set_int (value, threshold); + } + break; + + case PROP_Y_DRAG_THRESHOLD: + { + gint threshold; + + get_drag_threshold (CLUTTER_DRAG_ACTION (gobject), NULL, &threshold); + g_value_set_int (value, threshold); + } + break; + + case PROP_DRAG_HANDLE: + g_value_set_object (value, priv->drag_handle); + break; + + case PROP_DRAG_AXIS: + g_value_set_enum (value, priv->drag_axis); + break; + + case PROP_DRAG_AREA: + g_value_set_boxed (value, &priv->drag_area); + break; + + case PROP_DRAG_AREA_SET: + g_value_set_boolean (value, priv->drag_area_set); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + } +} + +static void +clutter_drag_action_dispose (GObject *gobject) +{ + ClutterDragActionPrivate *priv = CLUTTER_DRAG_ACTION (gobject)->priv; + + /* if we're being disposed while a capture is still present, we + * need to reset the state we are currently holding + */ + if (priv->last_motion_device != NULL) + { + _clutter_stage_remove_pointer_drag_actor (priv->stage, + priv->last_motion_device); + priv->last_motion_device = NULL; + } + + if (priv->sequence != NULL) + { + _clutter_stage_remove_touch_drag_actor (priv->stage, + priv->sequence); + priv->sequence = NULL; + } + + if (priv->capture_id != 0) + { + clutter_stage_set_motion_events_enabled (priv->stage, + priv->motion_events_enabled); + + if (priv->stage != NULL) + g_signal_handler_disconnect (priv->stage, priv->capture_id); + + priv->capture_id = 0; + priv->stage = NULL; + } + + if (priv->button_press_id != 0) + { + ClutterActor *actor; + + actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (gobject)); + if (actor != NULL) + { + g_signal_handler_disconnect (actor, priv->button_press_id); + g_signal_handler_disconnect (actor, priv->touch_begin_id); + } + + priv->button_press_id = 0; + priv->touch_begin_id = 0; + } + + clutter_drag_action_set_drag_handle (CLUTTER_DRAG_ACTION (gobject), NULL); + clutter_drag_action_set_drag_area (CLUTTER_DRAG_ACTION (gobject), NULL); + + G_OBJECT_CLASS (clutter_drag_action_parent_class)->dispose (gobject); +} + +static void +clutter_drag_action_class_init (ClutterDragActionClass *klass) +{ + ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + meta_class->set_actor = clutter_drag_action_set_actor; + + klass->drag_progress = clutter_drag_action_real_drag_progress; + klass->drag_motion = clutter_drag_action_real_drag_motion; + + /** + * ClutterDragAction:x-drag-threshold: + * + * The horizontal threshold, in pixels, that the cursor must travel + * in order to begin a drag action. + * + * When set to a positive value, #ClutterDragAction will only emit + * #ClutterDragAction::drag-begin if the pointer has moved + * horizontally at least of the given amount of pixels since + * the button press event. + * + * When set to -1, #ClutterDragAction will use the default threshold + * stored in the #ClutterSettings:dnd-drag-threshold property of + * #ClutterSettings. + * + * When read, this property will always return a valid drag + * threshold, either as set or the default one. + * + * Since: 1.4 + */ + drag_props[PROP_X_DRAG_THRESHOLD] = + g_param_spec_int ("x-drag-threshold", + P_("Horizontal Drag Threshold"), + P_("The horizontal amount of pixels required to start dragging"), + -1, G_MAXINT, + 0, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterDragAction:y-drag-threshold: + * + * The vertical threshold, in pixels, that the cursor must travel + * in order to begin a drag action. + * + * When set to a positive value, #ClutterDragAction will only emit + * #ClutterDragAction::drag-begin if the pointer has moved + * vertically at least of the given amount of pixels since + * the button press event. + * + * When set to -1, #ClutterDragAction will use the value stored + * in the #ClutterSettings:dnd-drag-threshold property of + * #ClutterSettings. + * + * When read, this property will always return a valid drag + * threshold, either as set or the default one. + * + * Since: 1.4 + */ + drag_props[PROP_Y_DRAG_THRESHOLD] = + g_param_spec_int ("y-drag-threshold", + P_("Vertical Drag Threshold"), + P_("The vertical amount of pixels required to start dragging"), + -1, G_MAXINT, + 0, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterDragAction:drag-handle: + * + * The #ClutterActor that is effectively being dragged + * + * A #ClutterDragAction will, be default, use the #ClutterActor that + * has been attached to the action; it is possible to create a + * separate #ClutterActor and use it instead. + * + * Setting this property has no effect on the #ClutterActor argument + * passed to the #ClutterDragAction signals + * + * Since: 1.4 + */ + drag_props[PROP_DRAG_HANDLE] = + g_param_spec_object ("drag-handle", + P_("Drag Handle"), + P_("The actor that is being dragged"), + CLUTTER_TYPE_ACTOR, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterDragAction:drag-axis: + * + * Constraints the dragging action to the specified axis + * + * Since: 1.4 + */ + drag_props[PROP_DRAG_AXIS] = + g_param_spec_enum ("drag-axis", + P_("Drag Axis"), + P_("Constraints the dragging to an axis"), + CLUTTER_TYPE_DRAG_AXIS, + CLUTTER_DRAG_AXIS_NONE, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterDragAction:drag-area: + * + * Constains the dragging action (or in particular, the resulting + * actor position) to the specified #ClutterRect, in parent's + * coordinates. + * + * Since: 1.12 + */ + drag_props[PROP_DRAG_AREA] = + g_param_spec_boxed ("drag-area", + P_("Drag Area"), + P_("Constrains the dragging to a rectangle"), + CLUTTER_TYPE_RECT, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterDragAction:drag-area-set: + * + * Whether the #ClutterDragAction:drag-area property has been set. + * + * Since: 1.12 + */ + drag_props[PROP_DRAG_AREA_SET] = + g_param_spec_boolean ("drag-area-set", + P_("Drag Area Set"), + P_("Whether the drag area is set"), + FALSE, + CLUTTER_PARAM_READABLE); + + + gobject_class->set_property = clutter_drag_action_set_property; + gobject_class->get_property = clutter_drag_action_get_property; + gobject_class->dispose = clutter_drag_action_dispose; + g_object_class_install_properties (gobject_class, + PROP_LAST, + drag_props); + + /** + * ClutterDragAction::drag-begin: + * @action: the #ClutterDragAction that emitted the signal + * @actor: the #ClutterActor attached to the action + * @event_x: the X coordinate (in stage space) of the press event + * @event_y: the Y coordinate (in stage space) of the press event + * @modifiers: the modifiers of the press event + * + * The ::drag-begin signal is emitted when the #ClutterDragAction + * starts the dragging + * + * The emission of this signal can be delayed by using the + * #ClutterDragAction:x-drag-threshold and + * #ClutterDragAction:y-drag-threshold properties + * + * Since: 1.4 + */ + drag_signals[DRAG_BEGIN] = + g_signal_new (I_("drag-begin"), + CLUTTER_TYPE_DRAG_ACTION, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterDragActionClass, drag_begin), + NULL, NULL, + _clutter_marshal_VOID__OBJECT_FLOAT_FLOAT_FLAGS, + G_TYPE_NONE, 4, + CLUTTER_TYPE_ACTOR, + G_TYPE_FLOAT, + G_TYPE_FLOAT, + CLUTTER_TYPE_MODIFIER_TYPE); + + /** + * ClutterDragAction::drag-progress: + * @action: the #ClutterDragAction that emitted the signal + * @actor: the #ClutterActor attached to the action + * @delta_x: the X component of the distance between the press event + * that began the dragging and the current position of the pointer, + * as of the latest motion event + * @delta_y: the Y component of the distance between the press event + * that began the dragging and the current position of the pointer, + * as of the latest motion event + * + * The ::drag-progress signal is emitted for each motion event after + * the #ClutterDragAction::drag-begin signal has been emitted. + * + * The components of the distance between the press event and the + * latest motion event are computed in the actor's coordinate space, + * to take into account eventual transformations. If you want the + * stage coordinates of the latest motion event you can use + * clutter_drag_action_get_motion_coords(). + * + * The default handler will emit #ClutterDragAction::drag-motion, + * if #ClutterDragAction::drag-progress emission returns %TRUE. + * + * Return value: %TRUE if the drag should continue, and %FALSE + * if it should be stopped. + * + * Since: 1.12 + */ + drag_signals[DRAG_PROGRESS] = + g_signal_new (I_("drag-progress"), + CLUTTER_TYPE_DRAG_ACTION, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterDragActionClass, drag_progress), + _clutter_boolean_continue_accumulator, NULL, + _clutter_marshal_BOOLEAN__OBJECT_FLOAT_FLOAT, + G_TYPE_BOOLEAN, 3, + CLUTTER_TYPE_ACTOR, + G_TYPE_FLOAT, + G_TYPE_FLOAT); + + /** + * ClutterDragAction::drag-motion: + * @action: the #ClutterDragAction that emitted the signal + * @actor: the #ClutterActor attached to the action + * @delta_x: the X component of the distance between the press event + * that began the dragging and the current position of the pointer, + * as of the latest motion event + * @delta_y: the Y component of the distance between the press event + * that began the dragging and the current position of the pointer, + * as of the latest motion event + * + * The ::drag-motion signal is emitted for each motion event after + * the #ClutterDragAction::drag-begin signal has been emitted. + * + * The components of the distance between the press event and the + * latest motion event are computed in the actor's coordinate space, + * to take into account eventual transformations. If you want the + * stage coordinates of the latest motion event you can use + * clutter_drag_action_get_motion_coords(). + * + * The default handler of the signal will call clutter_actor_move_by() + * either on @actor or, if set, of #ClutterDragAction:drag-handle using + * the @delta_x and @delta_y components of the dragging motion. If you + * want to override the default behaviour, you can connect to the + * #ClutterDragAction::drag-progress signal and return %FALSE from the + * handler. + * + * Since: 1.4 + */ + drag_signals[DRAG_MOTION] = + g_signal_new (I_("drag-motion"), + CLUTTER_TYPE_DRAG_ACTION, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterDragActionClass, drag_motion), + NULL, NULL, + _clutter_marshal_VOID__OBJECT_FLOAT_FLOAT, + G_TYPE_NONE, 3, + CLUTTER_TYPE_ACTOR, + G_TYPE_FLOAT, + G_TYPE_FLOAT); + + /** + * ClutterDragAction::drag-end: + * @action: the #ClutterDragAction that emitted the signal + * @actor: the #ClutterActor attached to the action + * @event_x: the X coordinate (in stage space) of the release event + * @event_y: the Y coordinate (in stage space) of the release event + * @modifiers: the modifiers of the release event + * + * The ::drag-end signal is emitted at the end of the dragging, + * when the pointer button's is released + * + * This signal is emitted if and only if the #ClutterDragAction::drag-begin + * signal has been emitted first + * + * Since: 1.4 + */ + drag_signals[DRAG_END] = + g_signal_new (I_("drag-end"), + CLUTTER_TYPE_DRAG_ACTION, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterDragActionClass, drag_end), + NULL, NULL, + _clutter_marshal_VOID__OBJECT_FLOAT_FLOAT_FLAGS, + G_TYPE_NONE, 4, + CLUTTER_TYPE_ACTOR, + G_TYPE_FLOAT, + G_TYPE_FLOAT, + CLUTTER_TYPE_MODIFIER_TYPE); +} + +static void +clutter_drag_action_init (ClutterDragAction *self) +{ + self->priv = clutter_drag_action_get_instance_private (self); +} + +/** + * clutter_drag_action_new: + * + * Creates a new #ClutterDragAction instance + * + * Return value: the newly created #ClutterDragAction + * + * Since: 1.4 + */ +ClutterAction * +clutter_drag_action_new (void) +{ + return g_object_new (CLUTTER_TYPE_DRAG_ACTION, NULL); +} + +/** + * clutter_drag_action_set_drag_threshold: + * @action: a #ClutterDragAction + * @x_threshold: a distance on the horizontal axis, in pixels, or + * -1 to use the default drag threshold from #ClutterSettings + * @y_threshold: a distance on the vertical axis, in pixels, or + * -1 to use the default drag threshold from #ClutterSettings + * + * Sets the horizontal and vertical drag thresholds that must be + * cleared by the pointer before @action can begin the dragging. + * + * If @x_threshold or @y_threshold are set to -1 then the default + * drag threshold stored in the #ClutterSettings:dnd-drag-threshold + * property of #ClutterSettings will be used. + * + * Since: 1.4 + */ +void +clutter_drag_action_set_drag_threshold (ClutterDragAction *action, + gint x_threshold, + gint y_threshold) +{ + ClutterDragActionPrivate *priv; + GObject *self; + + g_return_if_fail (CLUTTER_IS_DRAG_ACTION (action)); + + self = G_OBJECT (action); + priv = action->priv; + + g_object_freeze_notify (self); + + if (priv->x_drag_threshold != x_threshold) + { + priv->x_drag_threshold = x_threshold; + + g_object_notify_by_pspec (self, drag_props[PROP_X_DRAG_THRESHOLD]); + } + + if (priv->y_drag_threshold != y_threshold) + { + priv->y_drag_threshold = y_threshold; + + g_object_notify_by_pspec (self, drag_props[PROP_Y_DRAG_THRESHOLD]); + } + + g_object_thaw_notify (self); +} + +/** + * clutter_drag_action_get_drag_threshold: + * @action: a #ClutterDragAction + * @x_threshold: (out): return location for the horizontal drag + * threshold value, in pixels + * @y_threshold: (out): return location for the vertical drag + * threshold value, in pixels + * + * Retrieves the values set by clutter_drag_action_set_drag_threshold(). + * + * If the #ClutterDragAction:x-drag-threshold property or the + * #ClutterDragAction:y-drag-threshold property have been set to -1 then + * this function will return the default drag threshold value as stored + * by the #ClutterSettings:dnd-drag-threshold property of #ClutterSettings. + * + * Since: 1.4 + */ +void +clutter_drag_action_get_drag_threshold (ClutterDragAction *action, + guint *x_threshold, + guint *y_threshold) +{ + gint x_res, y_res; + + g_return_if_fail (CLUTTER_IS_DRAG_ACTION (action)); + + get_drag_threshold (action, &x_res, &y_res); + + if (x_threshold != NULL) + *x_threshold = x_res; + + if (y_threshold != NULL) + *y_threshold = y_res; +} + +static void +on_drag_handle_destroy (ClutterActor *handle, + ClutterDragAction *action) +{ + ClutterDragActionPrivate *priv = action->priv; + ClutterActor *actor; + + /* make sure we reset the state */ + actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action)); + if (priv->in_drag) + emit_drag_end (action, actor, NULL); + + priv->drag_handle = NULL; +} + +/** + * clutter_drag_action_set_drag_handle: + * @action: a #ClutterDragAction + * @handle: (allow-none): a #ClutterActor, or %NULL to unset + * + * Sets the actor to be used as the drag handle. + * + * Since: 1.4 + */ +void +clutter_drag_action_set_drag_handle (ClutterDragAction *action, + ClutterActor *handle) +{ + ClutterDragActionPrivate *priv; + + g_return_if_fail (CLUTTER_IS_DRAG_ACTION (action)); + g_return_if_fail (handle == NULL || CLUTTER_IS_ACTOR (handle)); + + priv = action->priv; + + if (priv->drag_handle == handle) + return; + + if (priv->drag_handle != NULL) + g_signal_handlers_disconnect_by_func (priv->drag_handle, + G_CALLBACK (on_drag_handle_destroy), + action); + + priv->drag_handle = handle; + + priv->transformed_press_x = priv->press_x; + priv->transformed_press_y = priv->press_y; + + if (priv->drag_handle != NULL) + { + clutter_actor_transform_stage_point (priv->drag_handle, + priv->press_x, + priv->press_y, + &priv->transformed_press_x, + &priv->transformed_press_y); + g_signal_connect (priv->drag_handle, "destroy", + G_CALLBACK (on_drag_handle_destroy), + action); + } + + g_object_notify_by_pspec (G_OBJECT (action), drag_props[PROP_DRAG_HANDLE]); +} + +/** + * clutter_drag_action_get_drag_handle: + * @action: a #ClutterDragAction + * + * Retrieves the drag handle set by clutter_drag_action_set_drag_handle() + * + * Return value: (transfer none): a #ClutterActor, used as the drag + * handle, or %NULL if none was set + * + * Since: 1.4 + */ +ClutterActor * +clutter_drag_action_get_drag_handle (ClutterDragAction *action) +{ + g_return_val_if_fail (CLUTTER_IS_DRAG_ACTION (action), NULL); + + return action->priv->drag_handle; +} + +/** + * clutter_drag_action_set_drag_axis: + * @action: a #ClutterDragAction + * @axis: the axis to constraint the dragging to + * + * Restricts the dragging action to a specific axis + * + * Since: 1.4 + */ +void +clutter_drag_action_set_drag_axis (ClutterDragAction *action, + ClutterDragAxis axis) +{ + ClutterDragActionPrivate *priv; + + g_return_if_fail (CLUTTER_IS_DRAG_ACTION (action)); + g_return_if_fail (axis >= CLUTTER_DRAG_AXIS_NONE && + axis <= CLUTTER_DRAG_Y_AXIS); + + priv = action->priv; + + if (priv->drag_axis == axis) + return; + + priv->drag_axis = axis; + + g_object_notify_by_pspec (G_OBJECT (action), drag_props[PROP_DRAG_AXIS]); +} + +/** + * clutter_drag_action_get_drag_axis: + * @action: a #ClutterDragAction + * + * Retrieves the axis constraint set by clutter_drag_action_set_drag_axis() + * + * Return value: the axis constraint + * + * Since: 1.4 + */ +ClutterDragAxis +clutter_drag_action_get_drag_axis (ClutterDragAction *action) +{ + g_return_val_if_fail (CLUTTER_IS_DRAG_ACTION (action), + CLUTTER_DRAG_AXIS_NONE); + + return action->priv->drag_axis; +} + +/** + * clutter_drag_action_get_press_coords: + * @action: a #ClutterDragAction + * @press_x: (out): return location for the press event's X coordinate + * @press_y: (out): return location for the press event's Y coordinate + * + * Retrieves the coordinates, in stage space, of the press event + * that started the dragging + * + * Since: 1.4 + */ +void +clutter_drag_action_get_press_coords (ClutterDragAction *action, + gfloat *press_x, + gfloat *press_y) +{ + g_return_if_fail (CLUTTER_IS_DRAG_ACTION (action)); + + if (press_x) + *press_x = action->priv->press_x; + + if (press_y) + *press_y = action->priv->press_y; +} + +/** + * clutter_drag_action_get_motion_coords: + * @action: a #ClutterDragAction + * @motion_x: (out): return location for the latest motion + * event's X coordinate + * @motion_y: (out): return location for the latest motion + * event's Y coordinate + * + * Retrieves the coordinates, in stage space, of the latest motion + * event during the dragging + * + * Since: 1.4 + */ +void +clutter_drag_action_get_motion_coords (ClutterDragAction *action, + gfloat *motion_x, + gfloat *motion_y) +{ + g_return_if_fail (CLUTTER_IS_DRAG_ACTION (action)); + + if (motion_x) + *motion_x = action->priv->last_motion_x; + + if (motion_y) + *motion_y = action->priv->last_motion_y; +} + +/** + * clutter_drag_action_get_drag_area: + * @action: a #ClutterDragAction + * @drag_area: (out caller-allocates): a #ClutterRect to be filled + * + * Retrieves the "drag area" associated with @action, that + * is a #ClutterRect that constrains the actor movements, + * in parents coordinates. + * + * Returns: %TRUE if the actor is actually constrained (and thus + * @drag_area is valid), %FALSE otherwise + */ +gboolean +clutter_drag_action_get_drag_area (ClutterDragAction *action, + ClutterRect *drag_area) +{ + g_return_val_if_fail (CLUTTER_IS_DRAG_ACTION (action), FALSE); + + if (drag_area != NULL) + *drag_area = action->priv->drag_area; + return action->priv->drag_area_set; +} + +/** + * clutter_drag_action_set_drag_area: + * @action: a #ClutterDragAction + * @drag_area: (allow-none): a #ClutterRect + * + * Sets @drag_area to constrain the dragging of the actor associated + * with @action, so that it position is always within @drag_area, expressed + * in parent's coordinates. + * If @drag_area is %NULL, the actor is not constrained. + */ +void +clutter_drag_action_set_drag_area (ClutterDragAction *action, + const ClutterRect *drag_area) +{ + ClutterDragActionPrivate *priv; + + g_return_if_fail (CLUTTER_IS_DRAG_ACTION (action)); + + priv = action->priv; + + if (drag_area != NULL) + { + priv->drag_area = *drag_area; + priv->drag_area_set = TRUE; + } + else + priv->drag_area_set = FALSE; + + g_object_notify_by_pspec (G_OBJECT (action), drag_props[PROP_DRAG_AREA_SET]); + g_object_notify_by_pspec (G_OBJECT (action), drag_props[PROP_DRAG_AREA]); +} diff --git a/clutter/clutter/clutter-drag-action.h b/clutter/clutter/clutter-drag-action.h new file mode 100644 index 0000000..a11d738 --- /dev/null +++ b/clutter/clutter/clutter-drag-action.h @@ -0,0 +1,152 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_DRAG_ACTION_H__ +#define __CLUTTER_DRAG_ACTION_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_DRAG_ACTION (clutter_drag_action_get_type ()) +#define CLUTTER_DRAG_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_DRAG_ACTION, ClutterDragAction)) +#define CLUTTER_IS_DRAG_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_DRAG_ACTION)) +#define CLUTTER_DRAG_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_DRAG_ACTION, ClutterDragActionClass)) +#define CLUTTER_IS_DRAG_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_DRAG_ACTION)) +#define CLUTTER_DRAG_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_DRAG_ACTION, ClutterDragActionClass)) + +typedef struct _ClutterDragAction ClutterDragAction; +typedef struct _ClutterDragActionPrivate ClutterDragActionPrivate; +typedef struct _ClutterDragActionClass ClutterDragActionClass; + +/** + * ClutterDragAction: + * + * The #ClutterDragAction structure contains only + * private data and should be accessed using the provided API + * + * Since: 1.4 + */ +struct _ClutterDragAction +{ + /*< private >*/ + ClutterAction parent_instance; + + ClutterDragActionPrivate *priv; +}; + +/** + * ClutterDragActionClass: + * @drag_begin: class handler of the #ClutterDragAction::drag-begin signal + * @drag_motion: class handler of the #ClutterDragAction::drag-motion signal + * @drag_end: class handler of the #ClutterDragAction::drag-end signal + * @drag_progress: class handler of the #ClutterDragAction::drag-progress signal + * + * The #ClutterDragActionClass structure contains + * only private data + * + * Since: 1.4 + */ +struct _ClutterDragActionClass +{ + /*< private >*/ + ClutterActionClass parent_class; + + /*< public >*/ + void (* drag_begin) (ClutterDragAction *action, + ClutterActor *actor, + gfloat event_x, + gfloat event_y, + ClutterModifierType modifiers); + void (* drag_motion) (ClutterDragAction *action, + ClutterActor *actor, + gfloat delta_x, + gfloat delta_y); + void (* drag_end) (ClutterDragAction *action, + ClutterActor *actor, + gfloat event_x, + gfloat event_y, + ClutterModifierType modifiers); + gboolean (* drag_progress) (ClutterDragAction *action, + ClutterActor *actor, + gfloat delta_x, + gfloat delta_y); + + /*< private >*/ + void (* _clutter_drag_action1) (void); + void (* _clutter_drag_action2) (void); + void (* _clutter_drag_action3) (void); + void (* _clutter_drag_action4) (void); +}; + +CLUTTER_AVAILABLE_IN_1_4 +GType clutter_drag_action_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_4 +ClutterAction * clutter_drag_action_new (void); + +CLUTTER_AVAILABLE_IN_1_4 +void clutter_drag_action_set_drag_threshold (ClutterDragAction *action, + gint x_threshold, + gint y_threshold); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_drag_action_get_drag_threshold (ClutterDragAction *action, + guint *x_threshold, + guint *y_threshold); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_drag_action_set_drag_handle (ClutterDragAction *action, + ClutterActor *handle); +CLUTTER_AVAILABLE_IN_1_4 +ClutterActor * clutter_drag_action_get_drag_handle (ClutterDragAction *action); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_drag_action_set_drag_axis (ClutterDragAction *action, + ClutterDragAxis axis); +CLUTTER_AVAILABLE_IN_1_4 +ClutterDragAxis clutter_drag_action_get_drag_axis (ClutterDragAction *action); + +CLUTTER_AVAILABLE_IN_1_4 +void clutter_drag_action_get_press_coords (ClutterDragAction *action, + gfloat *press_x, + gfloat *press_y); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_drag_action_get_motion_coords (ClutterDragAction *action, + gfloat *motion_x, + gfloat *motion_y); + +CLUTTER_AVAILABLE_IN_1_12 +gboolean clutter_drag_action_get_drag_area (ClutterDragAction *action, + ClutterRect *drag_area); + +CLUTTER_AVAILABLE_IN_1_12 +void clutter_drag_action_set_drag_area (ClutterDragAction *action, + const ClutterRect *drag_area); + +G_END_DECLS + +#endif /* __CLUTTER_DRAG_ACTION_H__ */ diff --git a/clutter/clutter/clutter-drop-action.c b/clutter/clutter/clutter-drop-action.c new file mode 100644 index 0000000..e778411 --- /dev/null +++ b/clutter/clutter/clutter-drop-action.c @@ -0,0 +1,533 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright © 2011 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-drop-action + * @Title: ClutterDropAction + * @short_description: An action for drop targets + * + * #ClutterDropAction is a #ClutterAction that allows a #ClutterActor + * implementation to control what happens when an actor dragged using + * a #ClutterDragAction crosses the target area or when a dragged actor + * is released (or "dropped") on the target area. + * + * A trivial use of #ClutterDropAction consists in connecting to the + * #ClutterDropAction::drop signal and handling the drop from there, + * for instance: + * + * |[ + * ClutterAction *action = clutter_drop_action (); + * + * g_signal_connect (action, "drop", G_CALLBACK (on_drop), NULL); + * clutter_actor_add_action (an_actor, action); + * ]| + * + * The #ClutterDropAction::can-drop can be used to control whether the + * #ClutterDropAction::drop signal is going to be emitted; returning %FALSE + * from a handler connected to the #ClutterDropAction::can-drop signal will + * cause the #ClutterDropAction::drop signal to be skipped when the input + * device button is released. + * + * It's important to note that #ClutterDropAction will only work with + * actors dragged using #ClutterDragAction. + * + * See [drop-action.c](https://git.gnome.org/browse/clutter/tree/examples/drop-action.c?h=clutter-1.18) + * for an example of how to use #ClutterDropAction. + * + * #ClutterDropAction is available since Clutter 1.8 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-drop-action.h" + +#include "clutter-actor-meta-private.h" +#include "clutter-actor-private.h" +#include "clutter-drag-action.h" +#include "clutter-main.h" +#include "clutter-marshal.h" +#include "clutter-stage-private.h" + +struct _ClutterDropActionPrivate +{ + ClutterActor *actor; + ClutterActor *stage; + + gulong mapped_id; +}; + +typedef struct _DropTarget { + ClutterActor *stage; + + gulong capture_id; + + GHashTable *actions; + + ClutterDropAction *last_action; +} DropTarget; + +enum +{ + CAN_DROP, + OVER_IN, + OVER_OUT, + DROP, + DROP_CANCEL, + + LAST_SIGNAL +}; + +static guint drop_signals[LAST_SIGNAL] = { 0, }; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterDropAction, clutter_drop_action, CLUTTER_TYPE_ACTION) + +static void +drop_target_free (gpointer _data) +{ + DropTarget *data = _data; + + g_signal_handler_disconnect (data->stage, data->capture_id); + g_hash_table_destroy (data->actions); + g_free (data); +} + +static gboolean +on_stage_capture (ClutterStage *stage, + ClutterEvent *event, + gpointer user_data) +{ + DropTarget *data = user_data; + gfloat event_x, event_y; + ClutterActor *actor, *drag_actor; + ClutterDropAction *drop_action; + ClutterInputDevice *device; + gboolean was_reactive; + + switch (clutter_event_type (event)) + { + case CLUTTER_MOTION: + case CLUTTER_BUTTON_RELEASE: + if (clutter_event_type (event) == CLUTTER_MOTION && + !(clutter_event_get_state (event) & CLUTTER_BUTTON1_MASK)) + return CLUTTER_EVENT_PROPAGATE; + + if (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE && + clutter_event_get_button (event) != CLUTTER_BUTTON_PRIMARY) + return CLUTTER_EVENT_PROPAGATE; + + device = clutter_event_get_device (event); + drag_actor = _clutter_stage_get_pointer_drag_actor (stage, device); + if (drag_actor == NULL) + return CLUTTER_EVENT_PROPAGATE; + break; + + case CLUTTER_TOUCH_UPDATE: + case CLUTTER_TOUCH_END: + drag_actor = _clutter_stage_get_touch_drag_actor (stage, + clutter_event_get_event_sequence (event)); + if (drag_actor == NULL) + return CLUTTER_EVENT_PROPAGATE; + break; + + default: + return CLUTTER_EVENT_PROPAGATE; + } + + clutter_event_get_coords (event, &event_x, &event_y); + + /* get the actor under the cursor, excluding the dragged actor; we + * use reactivity because it won't cause any scene invalidation + */ + was_reactive = clutter_actor_get_reactive (drag_actor); + clutter_actor_set_reactive (drag_actor, FALSE); + + actor = clutter_stage_get_actor_at_pos (stage, CLUTTER_PICK_REACTIVE, + event_x, + event_y); + if (actor == NULL || actor == CLUTTER_ACTOR (stage)) + { + if (data->last_action != NULL) + { + ClutterActorMeta *meta = CLUTTER_ACTOR_META (data->last_action); + + g_signal_emit (data->last_action, drop_signals[OVER_OUT], 0, + clutter_actor_meta_get_actor (meta)); + + data->last_action = NULL; + } + + goto out; + } + + drop_action = g_hash_table_lookup (data->actions, actor); + + if (drop_action == NULL) + { + if (data->last_action != NULL) + { + ClutterActorMeta *meta = CLUTTER_ACTOR_META (data->last_action); + + g_signal_emit (data->last_action, drop_signals[OVER_OUT], 0, + clutter_actor_meta_get_actor (meta)); + + data->last_action = NULL; + } + + goto out; + } + else + { + if (data->last_action != drop_action) + { + ClutterActorMeta *meta; + + if (data->last_action != NULL) + { + meta = CLUTTER_ACTOR_META (data->last_action); + + g_signal_emit (data->last_action, drop_signals[OVER_OUT], 0, + clutter_actor_meta_get_actor (meta)); + } + + meta = CLUTTER_ACTOR_META (drop_action); + + g_signal_emit (drop_action, drop_signals[OVER_IN], 0, + clutter_actor_meta_get_actor (meta)); + } + + data->last_action = drop_action; + } + +out: + if (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE || + clutter_event_type (event) == CLUTTER_TOUCH_END) + { + if (data->last_action != NULL) + { + ClutterActorMeta *meta = CLUTTER_ACTOR_META (data->last_action); + gboolean can_drop = FALSE; + + g_signal_emit (data->last_action, drop_signals[CAN_DROP], 0, + clutter_actor_meta_get_actor (meta), + event_x, event_y, + &can_drop); + + if (can_drop) + { + g_signal_emit (data->last_action, drop_signals[DROP], 0, + clutter_actor_meta_get_actor (meta), + event_x, event_y); + } + else + { + g_signal_emit (data->last_action, drop_signals[DROP_CANCEL], 0, + clutter_actor_meta_get_actor (meta), + event_x, event_y); + } + + } + + data->last_action = NULL; + } + + if (drag_actor != NULL) + clutter_actor_set_reactive (drag_actor, was_reactive); + + return CLUTTER_EVENT_PROPAGATE; +} + +static void +drop_action_register (ClutterDropAction *self) +{ + ClutterDropActionPrivate *priv = self->priv; + DropTarget *data; + + g_assert (priv->stage != NULL); + + data = g_object_get_data (G_OBJECT (priv->stage), "__clutter_drop_targets"); + if (data == NULL) + { + data = g_new0 (DropTarget, 1); + + data->stage = priv->stage; + data->actions = g_hash_table_new (NULL, NULL); + data->capture_id = g_signal_connect (priv->stage, "captured-event", + G_CALLBACK (on_stage_capture), + data); + g_object_set_data_full (G_OBJECT (priv->stage), "__clutter_drop_targets", + data, + drop_target_free); + } + + g_hash_table_replace (data->actions, priv->actor, self); +} + +static void +drop_action_unregister (ClutterDropAction *self) +{ + ClutterDropActionPrivate *priv = self->priv; + DropTarget *data = NULL; + + if (priv->stage != NULL) + data = g_object_get_data (G_OBJECT (priv->stage), "__clutter_drop_targets"); + + if (data == NULL) + return; + + g_hash_table_remove (data->actions, priv->actor); + if (g_hash_table_size (data->actions) == 0) + g_object_set_data (G_OBJECT (data->stage), "__clutter_drop_targets", NULL); +} + +static void +on_actor_mapped (ClutterActor *actor, + GParamSpec *pspec, + ClutterDropAction *self) +{ + if (clutter_actor_is_mapped (actor)) + { + if (self->priv->stage == NULL) + self->priv->stage = clutter_actor_get_stage (actor); + + drop_action_register (self); + } + else + drop_action_unregister (self); +} + +static void +clutter_drop_action_set_actor (ClutterActorMeta *meta, + ClutterActor *actor) +{ + ClutterDropActionPrivate *priv = CLUTTER_DROP_ACTION (meta)->priv; + + if (priv->actor != NULL) + { + drop_action_unregister (CLUTTER_DROP_ACTION (meta)); + + if (priv->mapped_id != 0) + g_signal_handler_disconnect (priv->actor, priv->mapped_id); + + priv->stage = NULL; + priv->actor = NULL; + priv->mapped_id = 0; + } + + priv->actor = actor; + + if (priv->actor != NULL) + { + priv->stage = clutter_actor_get_stage (actor); + priv->mapped_id = g_signal_connect (actor, "notify::mapped", + G_CALLBACK (on_actor_mapped), + meta); + + if (priv->stage != NULL) + drop_action_register (CLUTTER_DROP_ACTION (meta)); + } + + CLUTTER_ACTOR_META_CLASS (clutter_drop_action_parent_class)->set_actor (meta, actor); +} + +static gboolean +signal_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer user_data) +{ + gboolean continue_emission; + + continue_emission = g_value_get_boolean (handler_return); + g_value_set_boolean (return_accu, continue_emission); + + return continue_emission; +} + +static gboolean +clutter_drop_action_real_can_drop (ClutterDropAction *action, + ClutterActor *actor, + gfloat event_x, + gfloat event_y) +{ + return TRUE; +} + +static void +clutter_drop_action_class_init (ClutterDropActionClass *klass) +{ + ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass); + + meta_class->set_actor = clutter_drop_action_set_actor; + + klass->can_drop = clutter_drop_action_real_can_drop; + + /** + * ClutterDropAction::can-drop: + * @action: the #ClutterDropAction that emitted the signal + * @actor: the #ClutterActor attached to the @action + * @event_x: the X coordinate (in stage space) of the drop event + * @event_y: the Y coordinate (in stage space) of the drop event + * + * The ::can-drop signal is emitted when the dragged actor is dropped + * on @actor. The return value of the ::can-drop signal will determine + * whether or not the #ClutterDropAction::drop signal is going to be + * emitted on @action. + * + * The default implementation of #ClutterDropAction returns %TRUE for + * this signal. + * + * Return value: %TRUE if the drop is accepted, and %FALSE otherwise + * + * Since: 1.8 + */ + drop_signals[CAN_DROP] = + g_signal_new (I_("can-drop"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterDropActionClass, can_drop), + signal_accumulator, NULL, + _clutter_marshal_BOOLEAN__OBJECT_FLOAT_FLOAT, + G_TYPE_BOOLEAN, 3, + CLUTTER_TYPE_ACTOR, + G_TYPE_FLOAT, + G_TYPE_FLOAT); + + /** + * ClutterDropAction::over-in: + * @action: the #ClutterDropAction that emitted the signal + * @actor: the #ClutterActor attached to the @action + * + * The ::over-in signal is emitted when the dragged actor crosses + * into @actor. + * + * Since: 1.8 + */ + drop_signals[OVER_IN] = + g_signal_new (I_("over-in"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterDropActionClass, over_in), + NULL, NULL, + _clutter_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CLUTTER_TYPE_ACTOR); + + /** + * ClutterDropAction::over-out: + * @action: the #ClutterDropAction that emitted the signal + * @actor: the #ClutterActor attached to the @action + * + * The ::over-out signal is emitted when the dragged actor crosses + * outside @actor. + * + * Since: 1.8 + */ + drop_signals[OVER_OUT] = + g_signal_new (I_("over-out"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterDropActionClass, over_out), + NULL, NULL, + _clutter_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CLUTTER_TYPE_ACTOR); + + /** + * ClutterDropAction::drop: + * @action: the #ClutterDropAction that emitted the signal + * @actor: the #ClutterActor attached to the @action + * @event_x: the X coordinate (in stage space) of the drop event + * @event_y: the Y coordinate (in stage space) of the drop event + * + * The ::drop signal is emitted when the dragged actor is dropped + * on @actor. This signal is only emitted if at least an handler of + * #ClutterDropAction::can-drop returns %TRUE. + * + * Since: 1.8 + */ + drop_signals[DROP] = + g_signal_new (I_("drop"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterDropActionClass, drop), + NULL, NULL, + _clutter_marshal_VOID__OBJECT_FLOAT_FLOAT, + G_TYPE_NONE, 3, + CLUTTER_TYPE_ACTOR, + G_TYPE_FLOAT, + G_TYPE_FLOAT); + + + /** + * ClutterDropAction::drop-cancel: + * @action: the #ClutterDropAction that emitted the signal + * @actor: the #ClutterActor attached to the @action + * @event_x: the X coordinate (in stage space) of the drop event + * @event_y: the Y coordinate (in stage space) of the drop event + * + * The ::drop-cancel signal is emitted when the drop is refused + * by an emission of the #ClutterDropAction::can-drop signal. + * + * After the ::drop-cancel signal is fired the active drag is + * terminated. + * + * Since: 1.12 + */ + drop_signals[DROP_CANCEL] = + g_signal_new (I_("drop-cancel"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterDropActionClass, drop), + NULL, NULL, + _clutter_marshal_VOID__OBJECT_FLOAT_FLOAT, + G_TYPE_NONE, 3, + CLUTTER_TYPE_ACTOR, + G_TYPE_FLOAT, + G_TYPE_FLOAT); +} + +static void +clutter_drop_action_init (ClutterDropAction *self) +{ + self->priv = clutter_drop_action_get_instance_private (self); +} + +/** + * clutter_drop_action_new: + * + * Creates a new #ClutterDropAction. + * + * Use clutter_actor_add_action() to add the action to a #ClutterActor. + * + * Return value: the newly created #ClutterDropAction + * + * Since: 1.8 + */ +ClutterAction * +clutter_drop_action_new (void) +{ + return g_object_new (CLUTTER_TYPE_DROP_ACTION, NULL); +} diff --git a/clutter/clutter/clutter-drop-action.h b/clutter/clutter/clutter-drop-action.h new file mode 100644 index 0000000..2d2b40d --- /dev/null +++ b/clutter/clutter/clutter-drop-action.h @@ -0,0 +1,115 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright © 2011 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_DROP_ACTION_H__ +#define __CLUTTER_DROP_ACTION_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be directly included." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_DROP_ACTION (clutter_drop_action_get_type ()) +#define CLUTTER_DROP_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_DROP_ACTION, ClutterDropAction)) +#define CLUTTER_IS_DROP_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_DROP_ACTION)) +#define CLUTTER_DROP_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_DROP_ACTION, ClutterDropActionClass)) +#define CLUTTER_IS_DROP_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_DROP_ACTION)) +#define CLUTTER_DROP_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_DROP_ACTION, ClutterDropActionClass)) + +typedef struct _ClutterDropAction ClutterDropAction; +typedef struct _ClutterDropActionPrivate ClutterDropActionPrivate; +typedef struct _ClutterDropActionClass ClutterDropActionClass; + +/** + * ClutterDropAction: + * + * The #ClutterDropAction structure contains only + * private data and should be accessed using the provided API. + * + * Since: 1.8 + */ +struct _ClutterDropAction +{ + /*< private >*/ + ClutterAction parent_instance; + + ClutterDropActionPrivate *priv; +}; + +/** + * ClutterDropActionClass: + * @can_drop: class handler for the #ClutterDropAction::can-drop signal + * @over_in: class handler for the #ClutterDropAction::over-in signal + * @over_out: class handler for the #ClutterDropAction::over-out signal + * @drop: class handler for the #ClutterDropAction::drop signal + * + * The #ClutterDropActionClass structure contains + * only private data. + * + * Since: 1.8 + */ +struct _ClutterDropActionClass +{ + /*< private >*/ + ClutterActionClass parent_class; + + /*< public >*/ + gboolean (* can_drop) (ClutterDropAction *action, + ClutterActor *actor, + gfloat event_x, + gfloat event_y); + + void (* over_in) (ClutterDropAction *action, + ClutterActor *actor); + void (* over_out) (ClutterDropAction *action, + ClutterActor *actor); + + void (* drop) (ClutterDropAction *action, + ClutterActor *actor, + gfloat event_x, + gfloat event_y); + + /*< private >*/ + void (*_clutter_drop_action1) (void); + void (*_clutter_drop_action2) (void); + void (*_clutter_drop_action3) (void); + void (*_clutter_drop_action4) (void); + void (*_clutter_drop_action5) (void); + void (*_clutter_drop_action6) (void); + void (*_clutter_drop_action7) (void); + void (*_clutter_drop_action8) (void); +}; + +CLUTTER_AVAILABLE_IN_1_8 +GType clutter_drop_action_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_8 +ClutterAction * clutter_drop_action_new (void); + +G_END_DECLS + +#endif /* __CLUTTER_DROP_ACTION_H__ */ diff --git a/clutter/clutter/clutter-easing.c b/clutter/clutter/clutter-easing.c new file mode 100644 index 0000000..544994d --- /dev/null +++ b/clutter/clutter/clutter-easing.c @@ -0,0 +1,555 @@ +#include "clutter-build-config.h" + +#include "clutter-easing.h" + +#include + +double +clutter_linear (double t, + double d) +{ + return t / d; +} + +double +clutter_ease_in_quad (double t, + double d) +{ + double p = t / d; + + return p * p; +} + +double +clutter_ease_out_quad (double t, + double d) +{ + double p = t / d; + + return -1.0 * p * (p - 2); +} + +double +clutter_ease_in_out_quad (double t, + double d) +{ + double p = t / (d / 2); + + if (p < 1) + return 0.5 * p * p; + + p -= 1; + + return -0.5 * (p * (p - 2) - 1); +} + +double +clutter_ease_in_cubic (double t, + double d) +{ + double p = t / d; + + return p * p * p; +} + +double +clutter_ease_out_cubic (double t, + double d) +{ + double p = t / d - 1; + + return p * p * p + 1; +} + +double +clutter_ease_in_out_cubic (double t, + double d) +{ + double p = t / (d / 2); + + if (p < 1) + return 0.5 * p * p * p; + + p -= 2; + + return 0.5 * (p * p * p + 2); +} + +double +clutter_ease_in_quart (double t, + double d) +{ + double p = t / d; + + return p * p * p * p; +} + +double +clutter_ease_out_quart (double t, + double d) +{ + double p = t / d - 1; + + return -1.0 * (p * p * p * p - 1); +} + +double +clutter_ease_in_out_quart (double t, + double d) +{ + double p = t / (d / 2); + + if (p < 1) + return 0.5 * p * p * p * p; + + p -= 2; + + return -0.5 * (p * p * p * p - 2); +} + +double +clutter_ease_in_quint (double t, + double d) + { + double p = t / d; + + return p * p * p * p * p; +} + +double +clutter_ease_out_quint (double t, + double d) +{ + double p = t / d - 1; + + return p * p * p * p * p + 1; +} + +double +clutter_ease_in_out_quint (double t, + double d) +{ + double p = t / (d / 2); + + if (p < 1) + return 0.5 * p * p * p * p * p; + + p -= 2; + + return 0.5 * (p * p * p * p * p + 2); +} + +double +clutter_ease_in_sine (double t, + double d) +{ + return -1.0 * cos (t / d * G_PI_2) + 1.0; +} + +double +clutter_ease_out_sine (double t, + double d) +{ + return sin (t / d * G_PI_2); +} + +double +clutter_ease_in_out_sine (double t, + double d) +{ + return -0.5 * (cos (G_PI * t / d) - 1); +} + +double +clutter_ease_in_expo (double t, + double d) +{ + return (t == 0) ? 0.0 : pow (2, 10 * (t / d - 1)); +} + +double +clutter_ease_out_expo (double t, + double d) +{ + return (t == d) ? 1.0 : -pow (2, -10 * t / d) + 1; +} + +double +clutter_ease_in_out_expo (double t, + double d) +{ + double p; + + if (t == 0) + return 0.0; + + if (t == d) + return 1.0; + + p = t / (d / 2); + + if (p < 1) + return 0.5 * pow (2, 10 * (p - 1)); + + p -= 1; + + return 0.5 * (-pow (2, -10 * p) + 2); +} + +double +clutter_ease_in_circ (double t, + double d) +{ + double p = t / d; + + return -1.0 * (sqrt (1 - p * p) - 1); +} + +double +clutter_ease_out_circ (double t, + double d) +{ + double p = t / d - 1; + + return sqrt (1 - p * p); +} + +double +clutter_ease_in_out_circ (double t, + double d) +{ + double p = t / (d / 2); + + if (p < 1) + return -0.5 * (sqrt (1 - p * p) - 1); + + p -= 2; + + return 0.5 * (sqrt (1 - p * p) + 1); +} + +double +clutter_ease_in_elastic (double t, + double d) +{ + double p = d * .3; + double s = p / 4; + double q = t / d; + + if (q == 1) + return 1.0; + + q -= 1; + + return -(pow (2, 10 * q) * sin ((q * d - s) * (2 * G_PI) / p)); +} + +double +clutter_ease_out_elastic (double t, + double d) +{ + double p = d * .3; + double s = p / 4; + double q = t / d; + + if (q == 1) + return 1.0; + + return pow (2, -10 * q) * sin ((q * d - s) * (2 * G_PI) / p) + 1.0; +} + +double +clutter_ease_in_out_elastic (double t, + double d) +{ + double p = d * (.3 * 1.5); + double s = p / 4; + double q = t / (d / 2); + + if (q == 2) + return 1.0; + + if (q < 1) + { + q -= 1; + + return -.5 * (pow (2, 10 * q) * sin ((q * d - s) * (2 * G_PI) / p)); + } + else + { + q -= 1; + + return pow (2, -10 * q) + * sin ((q * d - s) * (2 * G_PI) / p) + * .5 + 1.0; + } +} + +double +clutter_ease_in_back (double t, + double d) +{ + double p = t / d; + + return p * p * ((1.70158 + 1) * p - 1.70158); +} + +double +clutter_ease_out_back (double t, + double d) +{ + double p = t / d - 1; + + return p * p * ((1.70158 + 1) * p + 1.70158) + 1; +} + +double +clutter_ease_in_out_back (double t, + double d) +{ + double p = t / (d / 2); + double s = 1.70158 * 1.525; + + if (p < 1) + return 0.5 * (p * p * ((s + 1) * p - s)); + + p -= 2; + + return 0.5 * (p * p * ((s + 1) * p + s) + 2); +} + +static inline double +ease_out_bounce_internal (double t, + double d) +{ + double p = t / d; + + if (p < (1 / 2.75)) + { + return 7.5625 * p * p; + } + else if (p < (2 / 2.75)) + { + p -= (1.5 / 2.75); + + return 7.5625 * p * p + .75; + } + else if (p < (2.5 / 2.75)) + { + p -= (2.25 / 2.75); + + return 7.5625 * p * p + .9375; + } + else + { + p -= (2.625 / 2.75); + + return 7.5625 * p * p + .984375; + } +} + +static inline double +ease_in_bounce_internal (double t, + double d) +{ + return 1.0 - ease_out_bounce_internal (d - t, d); +} + +double +clutter_ease_in_bounce (double t, + double d) +{ + return ease_in_bounce_internal (t, d); +} + +double +clutter_ease_out_bounce (double t, + double d) +{ + return ease_out_bounce_internal (t, d); +} + +double +clutter_ease_in_out_bounce (double t, + double d) +{ + if (t < d / 2) + return ease_in_bounce_internal (t * 2, d) * 0.5; + else + return ease_out_bounce_internal (t * 2 - d, d) * 0.5 + 1.0 * 0.5; +} + +static inline double +ease_steps_end (double p, + int n_steps) +{ + return floor (p * (double) n_steps) / (double) n_steps; +} + +double +clutter_ease_steps_start (double t, + double d, + int n_steps) +{ + return 1.0 - ease_steps_end (1.0 - (t / d), n_steps); +} + +double +clutter_ease_steps_end (double t, + double d, + int n_steps) +{ + return ease_steps_end ((t / d), n_steps); +} + +static inline double +x_for_t (double t, + double x_1, + double x_2) +{ + double omt = 1.0 - t; + + return 3.0 * omt * omt * t * x_1 + + 3.0 * omt * t * t * x_2 + + t * t * t; +} + +static inline double +y_for_t (double t, + double y_1, + double y_2) +{ + double omt = 1.0 - t; + + return 3.0 * omt * omt * t * y_1 + + 3.0 * omt * t * t * y_2 + + t * t * t; +} + +static inline double +t_for_x (double x, + double x_1, + double x_2) +{ + double min_t = 0, max_t = 1; + int i; + + for (i = 0; i < 30; ++i) + { + double guess_t = (min_t + max_t) / 2.0; + double guess_x = x_for_t (guess_t, x_1, x_2); + + if (x < guess_x) + max_t = guess_t; + else + min_t = guess_t; + } + + return (min_t + max_t) / 2.0; +} + +double +clutter_ease_cubic_bezier (double t, + double d, + double x_1, + double y_1, + double x_2, + double y_2) +{ + double p = t / d; + + if (p == 0.0) + return 0.0; + + if (p == 1.0) + return 1.0; + + return y_for_t (t_for_x (p, x_1, x_2), y_1, y_2); +} + +/*< private > + * _clutter_animation_modes: + * + * A mapping of animation modes and easing functions. + */ +static const struct { + ClutterAnimationMode mode; + ClutterEasingFunc func; + const char *name; +} _clutter_animation_modes[] = { + { CLUTTER_CUSTOM_MODE, NULL, "custom" }, + + { CLUTTER_LINEAR, clutter_linear, "linear" }, + { CLUTTER_EASE_IN_QUAD, clutter_ease_in_quad, "easeInQuad" }, + { CLUTTER_EASE_OUT_QUAD, clutter_ease_out_quad, "easeOutQuad" }, + { CLUTTER_EASE_IN_OUT_QUAD, clutter_ease_in_out_quad, "easeInOutQuad" }, + { CLUTTER_EASE_IN_CUBIC, clutter_ease_in_cubic, "easeInCubic" }, + { CLUTTER_EASE_OUT_CUBIC, clutter_ease_out_cubic, "easeOutCubic" }, + { CLUTTER_EASE_IN_OUT_CUBIC, clutter_ease_in_out_cubic, "easeInOutCubic" }, + { CLUTTER_EASE_IN_QUART, clutter_ease_in_quart, "easeInQuart" }, + { CLUTTER_EASE_OUT_QUART, clutter_ease_out_quart, "easeOutQuart" }, + { CLUTTER_EASE_IN_OUT_QUART, clutter_ease_in_out_quart, "easeInOutQuart" }, + { CLUTTER_EASE_IN_QUINT, clutter_ease_in_quint, "easeInQuint" }, + { CLUTTER_EASE_OUT_QUINT, clutter_ease_out_quint, "easeOutQuint" }, + { CLUTTER_EASE_IN_OUT_QUINT, clutter_ease_in_out_quint, "easeInOutQuint" }, + { CLUTTER_EASE_IN_SINE, clutter_ease_in_sine, "easeInSine" }, + { CLUTTER_EASE_OUT_SINE, clutter_ease_out_sine, "easeOutSine" }, + { CLUTTER_EASE_IN_OUT_SINE, clutter_ease_in_out_sine, "easeInOutSine" }, + { CLUTTER_EASE_IN_EXPO, clutter_ease_in_expo, "easeInExpo" }, + { CLUTTER_EASE_OUT_EXPO, clutter_ease_out_expo, "easeOutExpo" }, + { CLUTTER_EASE_IN_OUT_EXPO, clutter_ease_in_out_expo, "easeInOutExpo" }, + { CLUTTER_EASE_IN_CIRC, clutter_ease_in_circ, "easeInCirc" }, + { CLUTTER_EASE_OUT_CIRC, clutter_ease_out_circ, "easeOutCirc" }, + { CLUTTER_EASE_IN_OUT_CIRC, clutter_ease_in_out_circ, "easeInOutCirc" }, + { CLUTTER_EASE_IN_ELASTIC, clutter_ease_in_elastic, "easeInElastic" }, + { CLUTTER_EASE_OUT_ELASTIC, clutter_ease_out_elastic, "easeOutElastic" }, + { CLUTTER_EASE_IN_OUT_ELASTIC, clutter_ease_in_out_elastic, "easeInOutElastic" }, + { CLUTTER_EASE_IN_BACK, clutter_ease_in_back, "easeInBack" }, + { CLUTTER_EASE_OUT_BACK, clutter_ease_out_back, "easeOutBack" }, + { CLUTTER_EASE_IN_OUT_BACK, clutter_ease_in_out_back, "easeInOutBack" }, + { CLUTTER_EASE_IN_BOUNCE, clutter_ease_in_bounce, "easeInBounce" }, + { CLUTTER_EASE_OUT_BOUNCE, clutter_ease_out_bounce, "easeOutBounce" }, + { CLUTTER_EASE_IN_OUT_BOUNCE, clutter_ease_in_out_bounce, "easeInOutBounce" }, + + /* the parametrized functions need a cast */ + { CLUTTER_STEPS, (ClutterEasingFunc) clutter_ease_steps_end, "steps" }, + { CLUTTER_STEP_START, (ClutterEasingFunc) clutter_ease_steps_start, "stepStart" }, + { CLUTTER_STEP_END, (ClutterEasingFunc) clutter_ease_steps_end, "stepEnd" }, + + { CLUTTER_CUBIC_BEZIER, (ClutterEasingFunc) clutter_ease_cubic_bezier, "cubicBezier" }, + { CLUTTER_EASE, (ClutterEasingFunc) clutter_ease_cubic_bezier, "ease" }, + { CLUTTER_EASE_IN, (ClutterEasingFunc) clutter_ease_cubic_bezier, "easeIn" }, + { CLUTTER_EASE_OUT, (ClutterEasingFunc) clutter_ease_cubic_bezier, "easeOut" }, + { CLUTTER_EASE_IN_OUT, (ClutterEasingFunc) clutter_ease_cubic_bezier, "easeInOut" }, + + { CLUTTER_ANIMATION_LAST, NULL, "sentinel" }, +}; + +ClutterEasingFunc +clutter_get_easing_func_for_mode (ClutterAnimationMode mode) +{ + g_assert (_clutter_animation_modes[mode].mode == mode); + g_assert (_clutter_animation_modes[mode].func != NULL); + + return _clutter_animation_modes[mode].func; +} + +const char * +clutter_get_easing_name_for_mode (ClutterAnimationMode mode) +{ + g_assert (_clutter_animation_modes[mode].mode == mode); + g_assert (_clutter_animation_modes[mode].func != NULL); + + return _clutter_animation_modes[mode].name; +} + +double +clutter_easing_for_mode (ClutterAnimationMode mode, + double t, + double d) +{ + g_assert (_clutter_animation_modes[mode].mode == mode); + g_assert (_clutter_animation_modes[mode].func != NULL); + + return _clutter_animation_modes[mode].func (t, d); +} diff --git a/clutter/clutter/clutter-easing.h b/clutter/clutter/clutter-easing.h new file mode 100644 index 0000000..f7e6dcc --- /dev/null +++ b/clutter/clutter/clutter-easing.h @@ -0,0 +1,142 @@ +#ifndef __CLUTTER_EASING_H__ +#define __CLUTTER_EASING_H__ + +#include + +G_BEGIN_DECLS + +/*< private > + * ClutterEasingFunc: + * @t: elapsed time + * @d: total duration + * + * Internal type for the easing functions used by Clutter. + * + * Return value: the interpolated value, between -1.0 and 2.0 + */ +typedef double (* ClutterEasingFunc) (double t, double d); + +G_GNUC_INTERNAL +ClutterEasingFunc clutter_get_easing_func_for_mode (ClutterAnimationMode mode); + +G_GNUC_INTERNAL +const char * clutter_get_easing_name_for_mode (ClutterAnimationMode mode); + +G_GNUC_INTERNAL +double clutter_easing_for_mode (ClutterAnimationMode mode, + double t, + double d); + +G_GNUC_INTERNAL +double clutter_linear (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_in_quad (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_out_quad (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_in_out_quad (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_in_cubic (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_out_cubic (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_in_out_cubic (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_in_quart (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_out_quart (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_in_out_quart (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_in_quint (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_out_quint (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_in_out_quint (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_in_sine (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_out_sine (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_in_out_sine (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_in_expo (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_out_expo (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_in_out_expo (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_in_circ (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_out_circ (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_in_out_circ (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_in_elastic (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_out_elastic (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_in_out_elastic (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_in_back (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_out_back (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_in_out_back (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_in_bounce (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_out_bounce (double t, + double d); +G_GNUC_INTERNAL +double clutter_ease_in_out_bounce (double t, + double d); + +G_GNUC_INTERNAL +double clutter_ease_steps_start (double t, + double d, + int steps); +G_GNUC_INTERNAL +double clutter_ease_steps_end (double t, + double d, + int steps); +G_GNUC_INTERNAL +double clutter_ease_cubic_bezier (double t, + double d, + double x_1, + double y_1, + double x_2, + double y_2); + +G_END_DECLS + +#endif /* __CLUTTER_EASING_H__ */ diff --git a/clutter/clutter/clutter-effect-private.h b/clutter/clutter/clutter-effect-private.h new file mode 100644 index 0000000..578b6a1 --- /dev/null +++ b/clutter/clutter/clutter-effect-private.h @@ -0,0 +1,19 @@ +#ifndef __CLUTTER_EFFECT_PRIVATE_H__ +#define __CLUTTER_EFFECT_PRIVATE_H__ + +#include + +G_BEGIN_DECLS + +gboolean _clutter_effect_pre_paint (ClutterEffect *effect); +void _clutter_effect_post_paint (ClutterEffect *effect); +gboolean _clutter_effect_get_paint_volume (ClutterEffect *effect, + ClutterPaintVolume *volume); +void _clutter_effect_paint (ClutterEffect *effect, + ClutterEffectPaintFlags flags); +void _clutter_effect_pick (ClutterEffect *effect, + ClutterEffectPaintFlags flags); + +G_END_DECLS + +#endif /* __CLUTTER_EFFECT_PRIVATE_H__ */ diff --git a/clutter/clutter/clutter-effect.c b/clutter/clutter/clutter-effect.c new file mode 100644 index 0000000..06df7ff --- /dev/null +++ b/clutter/clutter/clutter-effect.c @@ -0,0 +1,368 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-effect + * @short_description: Base class for actor effects + * + * The #ClutterEffect class provides a default type and API for creating + * effects for generic actors. + * + * Effects are a #ClutterActorMeta sub-class that modify the way an actor + * is painted in a way that is not part of the actor's implementation. + * + * Effects should be the preferred way to affect the paint sequence of an + * actor without sub-classing the actor itself and overriding the + * #ClutterActorClass.paint()_ virtual function. + * + * ## Implementing a ClutterEffect + * + * Creating a sub-class of #ClutterEffect requires overriding the + * #ClutterEffectClass.paint() method. The implementation of the function should look + * something like this: + * + * |[ + * void effect_paint (ClutterEffect *effect, ClutterEffectPaintFlags flags) + * { + * // Set up initialisation of the paint such as binding a + * // CoglOffscreen or other operations + * + * // Chain to the next item in the paint sequence. This will either call + * // ‘paint’ on the next effect or just paint the actor if this is + * // the last effect. + * ClutterActor *actor = + * clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); + * + * clutter_actor_continue_paint (actor); + * + * // perform any cleanup of state, such as popping the CoglOffscreen + * } + * ]| + * + * The effect can optionally avoid calling clutter_actor_continue_paint() to skip any + * further stages of the paint sequence. This is useful for example if the effect + * contains a cached image of the actor. In that case it can optimise painting by + * avoiding the actor paint and instead painting the cached image. + * + * The %CLUTTER_EFFECT_PAINT_ACTOR_DIRTY flag is useful in this case. Clutter will set + * this flag when a redraw has been queued on the actor since it was last painted. The + * effect can use this information to decide if the cached image is still valid. + * + * ## A simple ClutterEffect implementation + * + * The example below creates two rectangles: one will be painted "behind" the actor, + * while another will be painted "on top" of the actor. + * + * The #ClutterActorMetaClass.set_actor() implementation will create the two materials + * used for the two different rectangles; the #ClutterEffectClass.paint() implementation + * will paint the first material using cogl_rectangle(), before continuing and then it + * will paint paint the second material after. + * + * |[ + * typedef struct { + * ClutterEffect parent_instance; + * + * CoglHandle rect_1; + * CoglHandle rect_2; + * } MyEffect; + * + * typedef struct _ClutterEffectClass MyEffectClass; + * + * G_DEFINE_TYPE (MyEffect, my_effect, CLUTTER_TYPE_EFFECT); + * + * static void + * my_effect_set_actor (ClutterActorMeta *meta, + * ClutterActor *actor) + * { + * MyEffect *self = MY_EFFECT (meta); + * + * // Clear the previous state // + * if (self->rect_1) + * { + * cogl_handle_unref (self->rect_1); + * self->rect_1 = NULL; + * } + * + * if (self->rect_2) + * { + * cogl_handle_unref (self->rect_2); + * self->rect_2 = NULL; + * } + * + * // Maintain a pointer to the actor + * self->actor = actor; + * + * // If we've been detached by the actor then we should just bail out here + * if (self->actor == NULL) + * return; + * + * // Create a red material + * self->rect_1 = cogl_material_new (); + * cogl_material_set_color4f (self->rect_1, 1.0, 0.0, 0.0, 1.0); + * + * // Create a green material + * self->rect_2 = cogl_material_new (); + * cogl_material_set_color4f (self->rect_2, 0.0, 1.0, 0.0, 1.0); + * } + * + * static gboolean + * my_effect_paint (ClutterEffect *effect) + * { + * MyEffect *self = MY_EFFECT (effect); + * gfloat width, height; + * + * clutter_actor_get_size (self->actor, &width, &height); + * + * // Paint the first rectangle in the upper left quadrant + * cogl_set_source (self->rect_1); + * cogl_rectangle (0, 0, width / 2, height / 2); + * + * // Continue to the rest of the paint sequence + * clutter_actor_continue_paint (self->actor); + * + * // Paint the second rectangle in the lower right quadrant + * cogl_set_source (self->rect_2); + * cogl_rectangle (width / 2, height / 2, width, height); + * } + * + * static void + * my_effect_class_init (MyEffectClass *klass) + * { + * ClutterActorMetaClas *meta_class = CLUTTER_ACTOR_META_CLASS (klass); + * + * meta_class->set_actor = my_effect_set_actor; + * + * klass->paint = my_effect_paint; + * } + * ]| + * + * #ClutterEffect is available since Clutter 1.4 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-effect.h" + +#include "clutter-actor-meta-private.h" +#include "clutter-debug.h" +#include "clutter-effect-private.h" +#include "clutter-enum-types.h" +#include "clutter-marshal.h" +#include "clutter-private.h" +#include "clutter-actor-private.h" + +G_DEFINE_ABSTRACT_TYPE (ClutterEffect, + clutter_effect, + CLUTTER_TYPE_ACTOR_META); + +static gboolean +clutter_effect_real_pre_paint (ClutterEffect *effect) +{ + return TRUE; +} + +static void +clutter_effect_real_post_paint (ClutterEffect *effect) +{ +} + +static gboolean +clutter_effect_real_get_paint_volume (ClutterEffect *effect, + ClutterPaintVolume *volume) +{ + return TRUE; +} + +static void +clutter_effect_real_paint (ClutterEffect *effect, + ClutterEffectPaintFlags flags) +{ + ClutterActorMeta *actor_meta = CLUTTER_ACTOR_META (effect); + ClutterActor *actor; + gboolean pre_paint_succeeded; + + /* The default implementation provides a compatibility wrapper for + effects that haven't migrated to use the 'paint' virtual yet. This + just calls the old pre and post virtuals before chaining on */ + + pre_paint_succeeded = _clutter_effect_pre_paint (effect); + + actor = clutter_actor_meta_get_actor (actor_meta); + clutter_actor_continue_paint (actor); + + if (pre_paint_succeeded) + _clutter_effect_post_paint (effect); +} + +static void +clutter_effect_real_pick (ClutterEffect *effect, + ClutterEffectPaintFlags flags) +{ + ClutterActorMeta *actor_meta = CLUTTER_ACTOR_META (effect); + ClutterActor *actor; + + actor = clutter_actor_meta_get_actor (actor_meta); + clutter_actor_continue_paint (actor); +} + +static void +clutter_effect_notify (GObject *gobject, + GParamSpec *pspec) +{ + if (strcmp (pspec->name, "enabled") == 0) + { + ClutterActorMeta *meta = CLUTTER_ACTOR_META (gobject); + ClutterActor *actor = clutter_actor_meta_get_actor (meta); + + if (actor != NULL) + clutter_actor_queue_redraw (actor); + } + + if (G_OBJECT_CLASS (clutter_effect_parent_class)->notify != NULL) + G_OBJECT_CLASS (clutter_effect_parent_class)->notify (gobject, pspec); +} + +static void +clutter_effect_class_init (ClutterEffectClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->notify = clutter_effect_notify; + + klass->pre_paint = clutter_effect_real_pre_paint; + klass->post_paint = clutter_effect_real_post_paint; + klass->get_paint_volume = clutter_effect_real_get_paint_volume; + klass->paint = clutter_effect_real_paint; + klass->pick = clutter_effect_real_pick; +} + +static void +clutter_effect_init (ClutterEffect *self) +{ +} + +gboolean +_clutter_effect_pre_paint (ClutterEffect *effect) +{ + g_return_val_if_fail (CLUTTER_IS_EFFECT (effect), FALSE); + + return CLUTTER_EFFECT_GET_CLASS (effect)->pre_paint (effect); +} + +void +_clutter_effect_post_paint (ClutterEffect *effect) +{ + g_return_if_fail (CLUTTER_IS_EFFECT (effect)); + + CLUTTER_EFFECT_GET_CLASS (effect)->post_paint (effect); +} + +void +_clutter_effect_paint (ClutterEffect *effect, + ClutterEffectPaintFlags flags) +{ + g_return_if_fail (CLUTTER_IS_EFFECT (effect)); + + CLUTTER_EFFECT_GET_CLASS (effect)->paint (effect, flags); +} + +void +_clutter_effect_pick (ClutterEffect *effect, + ClutterEffectPaintFlags flags) +{ + g_return_if_fail (CLUTTER_IS_EFFECT (effect)); + + CLUTTER_EFFECT_GET_CLASS (effect)->pick (effect, flags); +} + +gboolean +_clutter_effect_get_paint_volume (ClutterEffect *effect, + ClutterPaintVolume *volume) +{ + g_return_val_if_fail (CLUTTER_IS_EFFECT (effect), FALSE); + g_return_val_if_fail (volume != NULL, FALSE); + + return CLUTTER_EFFECT_GET_CLASS (effect)->get_paint_volume (effect, volume); +} + +/** + * clutter_effect_queue_repaint: + * @effect: A #ClutterEffect which needs redrawing + * + * Queues a repaint of the effect. The effect can detect when the ‘paint’ + * method is called as a result of this function because it will not + * have the %CLUTTER_EFFECT_PAINT_ACTOR_DIRTY flag set. In that case the + * effect is free to assume that the actor has not changed its + * appearance since the last time it was painted so it doesn't need to + * call clutter_actor_continue_paint() if it can draw a cached + * image. This is mostly intended for effects that are using a + * %CoglOffscreen to redirect the actor (such as + * %ClutterOffscreenEffect). In that case the effect can save a bit of + * rendering time by painting the cached texture without causing the + * entire actor to be painted. + * + * This function can be used by effects that have their own animatable + * parameters. For example, an effect which adds a varying degree of a + * red tint to an actor by redirecting it through a CoglOffscreen + * might have a property to specify the level of tint. When this value + * changes, the underlying actor doesn't need to be redrawn so the + * effect can call clutter_effect_queue_repaint() to make sure the + * effect is repainted. + * + * Note however that modifying the position of the parent of an actor + * may change the appearance of the actor because its transformation + * matrix would change. In this case a redraw wouldn't be queued on + * the actor itself so the %CLUTTER_EFFECT_PAINT_ACTOR_DIRTY would still + * not be set. The effect can detect this case by keeping track of the + * last modelview matrix that was used to render the actor and + * veryifying that it remains the same in the next paint. + * + * Any other effects that are layered on top of the passed in effect + * will still be passed the %CLUTTER_EFFECT_PAINT_ACTOR_DIRTY flag. If + * anything queues a redraw on the actor without specifying an effect + * or with an effect that is lower in the chain of effects than this + * one then that will override this call. In that case this effect + * will instead be called with the %CLUTTER_EFFECT_PAINT_ACTOR_DIRTY + * flag set. + * + * Since: 1.8 + */ +void +clutter_effect_queue_repaint (ClutterEffect *effect) +{ + ClutterActor *actor; + + g_return_if_fail (CLUTTER_IS_EFFECT (effect)); + + actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); + + /* If the effect has no actor then nothing needs to be done */ + if (actor != NULL) + _clutter_actor_queue_redraw_full (actor, + 0, /* flags */ + NULL, /* clip volume */ + effect /* effect */); +} diff --git a/clutter/clutter/clutter-effect.h b/clutter/clutter/clutter-effect.h new file mode 100644 index 0000000..6cfc2f2 --- /dev/null +++ b/clutter/clutter/clutter-effect.h @@ -0,0 +1,130 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_EFFECT_H__ +#define __CLUTTER_EFFECT_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_EFFECT (clutter_effect_get_type ()) +#define CLUTTER_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_EFFECT, ClutterEffect)) +#define CLUTTER_IS_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_EFFECT)) +#define CLUTTER_EFFECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_EFFECT, ClutterEffectClass)) +#define CLUTTER_IS_EFFECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_EFFECT)) +#define CLUTTER_EFFECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_EFFECT, ClutterEffectClass)) + +typedef struct _ClutterEffectClass ClutterEffectClass; + +/** + * ClutterEffect: + * + * The #ClutterEffect structure contains only private data and should + * be accessed using the provided API + * + * Since: 1.4 + */ +struct _ClutterEffect +{ + /*< private >*/ + ClutterActorMeta parent_instance; +}; + +/** + * ClutterEffectClass: + * @pre_paint: virtual function + * @post_paint: virtual function + * @get_paint_volume: virtual function + * @paint: virtual function + * @pick: virtual function + * + * The #ClutterEffectClass structure contains only private data + * + * Since: 1.4 + */ +struct _ClutterEffectClass +{ + /*< private >*/ + ClutterActorMetaClass parent_class; + + /*< public >*/ + gboolean (* pre_paint) (ClutterEffect *effect); + void (* post_paint) (ClutterEffect *effect); + + gboolean (* get_paint_volume) (ClutterEffect *effect, + ClutterPaintVolume *volume); + + void (* paint) (ClutterEffect *effect, + ClutterEffectPaintFlags flags); + void (* pick) (ClutterEffect *effect, + ClutterEffectPaintFlags flags); + + /*< private >*/ + void (* _clutter_effect4) (void); + void (* _clutter_effect5) (void); + void (* _clutter_effect6) (void); +}; + +CLUTTER_AVAILABLE_IN_1_4 +GType clutter_effect_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_8 +void clutter_effect_queue_repaint (ClutterEffect *effect); + +/* + * ClutterActor API + */ + +CLUTTER_AVAILABLE_IN_1_4 +void clutter_actor_add_effect (ClutterActor *self, + ClutterEffect *effect); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_actor_add_effect_with_name (ClutterActor *self, + const gchar *name, + ClutterEffect *effect); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_actor_remove_effect (ClutterActor *self, + ClutterEffect *effect); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_actor_remove_effect_by_name (ClutterActor *self, + const gchar *name); +CLUTTER_AVAILABLE_IN_1_4 +GList * clutter_actor_get_effects (ClutterActor *self); +CLUTTER_AVAILABLE_IN_1_4 +ClutterEffect *clutter_actor_get_effect (ClutterActor *self, + const gchar *name); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_actor_clear_effects (ClutterActor *self); + +CLUTTER_AVAILABLE_IN_1_10 +gboolean clutter_actor_has_effects (ClutterActor *self); + +G_END_DECLS + +#endif /* __CLUTTER_EFFECT_H__ */ diff --git a/clutter/clutter/clutter-enum-types.c.in b/clutter/clutter/clutter-enum-types.c.in new file mode 100644 index 0000000..de2cb26 --- /dev/null +++ b/clutter/clutter/clutter-enum-types.c.in @@ -0,0 +1,41 @@ +/*** BEGIN file-header ***/ +#include "clutter-build-config.h" +#include "clutter-enum-types.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 ***/ diff --git a/clutter/clutter/clutter-enum-types.h.in b/clutter/clutter/clutter-enum-types.h.in new file mode 100644 index 0000000..aea757e --- /dev/null +++ b/clutter/clutter/clutter-enum-types.h.in @@ -0,0 +1,29 @@ +/*** BEGIN file-header ***/ +#ifndef __CLUTTER_ENUM_TYPES_H__ +#define __CLUTTER_ENUM_TYPES_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +/*** END file-header ***/ + +/*** BEGIN file-production ***/ +/* enumerations from "@filename@" */ +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +CLUTTER_AVAILABLE_IN_ALL GType @enum_name@_get_type (void) G_GNUC_CONST; +#define CLUTTER_TYPE_@ENUMSHORT@ (@enum_name@_get_type()) + +/*** END value-header ***/ + +/*** BEGIN file-tail ***/ +G_END_DECLS + +#endif /* !__CLUTTER_ENUM_TYPES_H__ */ +/*** END file-tail ***/ diff --git a/clutter/clutter/clutter-enums.h b/clutter/clutter/clutter-enums.h new file mode 100644 index 0000000..03c0395 --- /dev/null +++ b/clutter/clutter/clutter-enums.h @@ -0,0 +1,1541 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2011 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __CLUTTER_ENUMS_H__ +#define __CLUTTER_ENUMS_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +/** + * ClutterGravity: + * @CLUTTER_GRAVITY_NONE: Do not apply any gravity + * @CLUTTER_GRAVITY_NORTH: Scale from topmost downwards + * @CLUTTER_GRAVITY_NORTH_EAST: Scale from the top right corner + * @CLUTTER_GRAVITY_EAST: Scale from the right side + * @CLUTTER_GRAVITY_SOUTH_EAST: Scale from the bottom right corner + * @CLUTTER_GRAVITY_SOUTH: Scale from the bottom upwards + * @CLUTTER_GRAVITY_SOUTH_WEST: Scale from the bottom left corner + * @CLUTTER_GRAVITY_WEST: Scale from the left side + * @CLUTTER_GRAVITY_NORTH_WEST: Scale from the top left corner + * @CLUTTER_GRAVITY_CENTER: Scale from the center. + * + * Gravity of the scaling operations. When a gravity different than + * %CLUTTER_GRAVITY_NONE is used, an actor is scaled keeping the position + * of the specified portion at the same coordinates. + * + * Since: 0.2 + * + * Deprecated: 1.22: Use the normalized #ClutterActor pivot point instead + */ +typedef enum { /*< prefix=CLUTTER_GRAVITY >*/ + CLUTTER_GRAVITY_NONE = 0, + CLUTTER_GRAVITY_NORTH, + CLUTTER_GRAVITY_NORTH_EAST, + CLUTTER_GRAVITY_EAST, + CLUTTER_GRAVITY_SOUTH_EAST, + CLUTTER_GRAVITY_SOUTH, + CLUTTER_GRAVITY_SOUTH_WEST, + CLUTTER_GRAVITY_WEST, + CLUTTER_GRAVITY_NORTH_WEST, + CLUTTER_GRAVITY_CENTER +} ClutterGravity; + +/** + * ClutterRotateAxis: + * @CLUTTER_X_AXIS: Rotate around the X axis + * @CLUTTER_Y_AXIS: Rotate around the Y axis + * @CLUTTER_Z_AXIS: Rotate around the Z axis + * + * Axis of a rotation. + * + * Since: 0.4 + */ +typedef enum { /*< prefix=CLUTTER >*/ + CLUTTER_X_AXIS, + CLUTTER_Y_AXIS, + CLUTTER_Z_AXIS +} ClutterRotateAxis; + +/** + * ClutterRotateDirection: + * @CLUTTER_ROTATE_CW: Clockwise rotation + * @CLUTTER_ROTATE_CCW: Counter-clockwise rotation + * + * Direction of a rotation. + * + * Since: 0.4 + * + * Deprecated: 1.22 + */ +typedef enum { /*< prefix=CLUTTER_ROTATE >*/ + CLUTTER_ROTATE_CW, + CLUTTER_ROTATE_CCW +} ClutterRotateDirection; + +/** + * ClutterRequestMode: + * @CLUTTER_REQUEST_HEIGHT_FOR_WIDTH: Height for width requests + * @CLUTTER_REQUEST_WIDTH_FOR_HEIGHT: Width for height requests + * @CLUTTER_REQUEST_CONTENT_SIZE: Use the preferred size of the + * #ClutterContent, if it has any (available since 1.22) + * + * Specifies the type of requests for a #ClutterActor. + * + * Since: 0.8 + */ +typedef enum { /*< prefix=CLUTTER_REQUEST >*/ + CLUTTER_REQUEST_HEIGHT_FOR_WIDTH, + CLUTTER_REQUEST_WIDTH_FOR_HEIGHT, + CLUTTER_REQUEST_CONTENT_SIZE +} ClutterRequestMode; + +/** + * ClutterAnimationMode: + * @CLUTTER_CUSTOM_MODE: custom progress function + * @CLUTTER_LINEAR: linear tweening + * @CLUTTER_EASE_IN_QUAD: quadratic tweening + * @CLUTTER_EASE_OUT_QUAD: quadratic tweening, inverse of + * %CLUTTER_EASE_IN_QUAD + * @CLUTTER_EASE_IN_OUT_QUAD: quadratic tweening, combininig + * %CLUTTER_EASE_IN_QUAD and %CLUTTER_EASE_OUT_QUAD + * @CLUTTER_EASE_IN_CUBIC: cubic tweening + * @CLUTTER_EASE_OUT_CUBIC: cubic tweening, invers of + * %CLUTTER_EASE_IN_CUBIC + * @CLUTTER_EASE_IN_OUT_CUBIC: cubic tweening, combining + * %CLUTTER_EASE_IN_CUBIC and %CLUTTER_EASE_OUT_CUBIC + * @CLUTTER_EASE_IN_QUART: quartic tweening + * @CLUTTER_EASE_OUT_QUART: quartic tweening, inverse of + * %CLUTTER_EASE_IN_QUART + * @CLUTTER_EASE_IN_OUT_QUART: quartic tweening, combining + * %CLUTTER_EASE_IN_QUART and %CLUTTER_EASE_OUT_QUART + * @CLUTTER_EASE_IN_QUINT: quintic tweening + * @CLUTTER_EASE_OUT_QUINT: quintic tweening, inverse of + * %CLUTTER_EASE_IN_QUINT + * @CLUTTER_EASE_IN_OUT_QUINT: fifth power tweening, combining + * %CLUTTER_EASE_IN_QUINT and %CLUTTER_EASE_OUT_QUINT + * @CLUTTER_EASE_IN_SINE: sinusoidal tweening + * @CLUTTER_EASE_OUT_SINE: sinusoidal tweening, inverse of + * %CLUTTER_EASE_IN_SINE + * @CLUTTER_EASE_IN_OUT_SINE: sine wave tweening, combining + * %CLUTTER_EASE_IN_SINE and %CLUTTER_EASE_OUT_SINE + * @CLUTTER_EASE_IN_EXPO: exponential tweening + * @CLUTTER_EASE_OUT_EXPO: exponential tweening, inverse of + * %CLUTTER_EASE_IN_EXPO + * @CLUTTER_EASE_IN_OUT_EXPO: exponential tweening, combining + * %CLUTTER_EASE_IN_EXPO and %CLUTTER_EASE_OUT_EXPO + * @CLUTTER_EASE_IN_CIRC: circular tweening + * @CLUTTER_EASE_OUT_CIRC: circular tweening, inverse of + * %CLUTTER_EASE_IN_CIRC + * @CLUTTER_EASE_IN_OUT_CIRC: circular tweening, combining + * %CLUTTER_EASE_IN_CIRC and %CLUTTER_EASE_OUT_CIRC + * @CLUTTER_EASE_IN_ELASTIC: elastic tweening, with offshoot on start + * @CLUTTER_EASE_OUT_ELASTIC: elastic tweening, with offshoot on end + * @CLUTTER_EASE_IN_OUT_ELASTIC: elastic tweening with offshoot on both ends + * @CLUTTER_EASE_IN_BACK: overshooting cubic tweening, with + * backtracking on start + * @CLUTTER_EASE_OUT_BACK: overshooting cubic tweening, with + * backtracking on end + * @CLUTTER_EASE_IN_OUT_BACK: overshooting cubic tweening, with + * backtracking on both ends + * @CLUTTER_EASE_IN_BOUNCE: exponentially decaying parabolic (bounce) + * tweening, with bounce on start + * @CLUTTER_EASE_OUT_BOUNCE: exponentially decaying parabolic (bounce) + * tweening, with bounce on end + * @CLUTTER_EASE_IN_OUT_BOUNCE: exponentially decaying parabolic (bounce) + * tweening, with bounce on both ends + * @CLUTTER_STEPS: parametrized step function; see clutter_timeline_set_step_progress() + * for further details. (Since 1.12) + * @CLUTTER_STEP_START: equivalent to %CLUTTER_STEPS with a number of steps + * equal to 1, and a step mode of %CLUTTER_STEP_MODE_START. (Since 1.12) + * @CLUTTER_STEP_END: equivalent to %CLUTTER_STEPS with a number of steps + * equal to 1, and a step mode of %CLUTTER_STEP_MODE_END. (Since 1.12) + * @CLUTTER_CUBIC_BEZIER: cubic bezier between (0, 0) and (1, 1) with two + * control points; see clutter_timeline_set_cubic_bezier_progress(). (Since 1.12) + * @CLUTTER_EASE: equivalent to %CLUTTER_CUBIC_BEZIER with control points + * in (0.25, 0.1) and (0.25, 1.0). (Since 1.12) + * @CLUTTER_EASE_IN: equivalent to %CLUTTER_CUBIC_BEZIER with control points + * in (0.42, 0) and (1.0, 1.0). (Since 1.12) + * @CLUTTER_EASE_OUT: equivalent to %CLUTTER_CUBIC_BEZIER with control points + * in (0, 0) and (0.58, 1.0). (Since 1.12) + * @CLUTTER_EASE_IN_OUT: equivalent to %CLUTTER_CUBIC_BEZIER with control points + * in (0.42, 0) and (0.58, 1.0). (Since 1.12) + * @CLUTTER_ANIMATION_LAST: last animation mode, used as a guard for + * registered global alpha functions + * + * The animation modes used by #ClutterAlpha and #ClutterAnimation. This + * enumeration can be expanded in later versions of Clutter. + * + *
+ * Easing modes provided by Clutter + * + *
+ * + * Every global alpha function registered using clutter_alpha_register_func() + * or clutter_alpha_register_closure() will have a logical id greater than + * %CLUTTER_ANIMATION_LAST. + * + * Since: 1.0 + */ +typedef enum { + CLUTTER_CUSTOM_MODE = 0, + + /* linear */ + CLUTTER_LINEAR, + + /* quadratic */ + CLUTTER_EASE_IN_QUAD, + CLUTTER_EASE_OUT_QUAD, + CLUTTER_EASE_IN_OUT_QUAD, + + /* cubic */ + CLUTTER_EASE_IN_CUBIC, + CLUTTER_EASE_OUT_CUBIC, + CLUTTER_EASE_IN_OUT_CUBIC, + + /* quartic */ + CLUTTER_EASE_IN_QUART, + CLUTTER_EASE_OUT_QUART, + CLUTTER_EASE_IN_OUT_QUART, + + /* quintic */ + CLUTTER_EASE_IN_QUINT, + CLUTTER_EASE_OUT_QUINT, + CLUTTER_EASE_IN_OUT_QUINT, + + /* sinusoidal */ + CLUTTER_EASE_IN_SINE, + CLUTTER_EASE_OUT_SINE, + CLUTTER_EASE_IN_OUT_SINE, + + /* exponential */ + CLUTTER_EASE_IN_EXPO, + CLUTTER_EASE_OUT_EXPO, + CLUTTER_EASE_IN_OUT_EXPO, + + /* circular */ + CLUTTER_EASE_IN_CIRC, + CLUTTER_EASE_OUT_CIRC, + CLUTTER_EASE_IN_OUT_CIRC, + + /* elastic */ + CLUTTER_EASE_IN_ELASTIC, + CLUTTER_EASE_OUT_ELASTIC, + CLUTTER_EASE_IN_OUT_ELASTIC, + + /* overshooting cubic */ + CLUTTER_EASE_IN_BACK, + CLUTTER_EASE_OUT_BACK, + CLUTTER_EASE_IN_OUT_BACK, + + /* exponentially decaying parabolic */ + CLUTTER_EASE_IN_BOUNCE, + CLUTTER_EASE_OUT_BOUNCE, + CLUTTER_EASE_IN_OUT_BOUNCE, + + /* step functions (see css3-transitions) */ + CLUTTER_STEPS, + CLUTTER_STEP_START, /* steps(1, start) */ + CLUTTER_STEP_END, /* steps(1, end) */ + + /* cubic bezier (see css3-transitions) */ + CLUTTER_CUBIC_BEZIER, + CLUTTER_EASE, + CLUTTER_EASE_IN, + CLUTTER_EASE_OUT, + CLUTTER_EASE_IN_OUT, + + /* guard, before registered alpha functions */ + CLUTTER_ANIMATION_LAST +} ClutterAnimationMode; + +/** + * ClutterFontFlags: + * @CLUTTER_FONT_MIPMAPPING: Set to use mipmaps for the glyph cache textures. + * @CLUTTER_FONT_HINTING: Set to enable hinting on the glyphs. + * + * Runtime flags to change the font quality. To be used with + * clutter_set_font_flags(). + * + * Since: 1.0 + * + * Deprecated: 1.22: Use #cairo_font_options_t instead + */ +typedef enum { /*< prefix=CLUTTER_FONT >*/ + CLUTTER_FONT_MIPMAPPING = (1 << 0), + CLUTTER_FONT_HINTING = (1 << 1) +} ClutterFontFlags; + +/** + * ClutterTextDirection: + * @CLUTTER_TEXT_DIRECTION_DEFAULT: Use the default setting, as returned + * by clutter_get_default_text_direction() + * @CLUTTER_TEXT_DIRECTION_LTR: Use left-to-right text direction + * @CLUTTER_TEXT_DIRECTION_RTL: Use right-to-left text direction + * + * The text direction to be used by #ClutterActors + * + * Since: 1.2 + */ +typedef enum { + CLUTTER_TEXT_DIRECTION_DEFAULT, + CLUTTER_TEXT_DIRECTION_LTR, + CLUTTER_TEXT_DIRECTION_RTL +} ClutterTextDirection; + +/** + * ClutterShaderType: + * @CLUTTER_VERTEX_SHADER: a vertex shader + * @CLUTTER_FRAGMENT_SHADER: a fragment shader + * + * The type of GLSL shader program + * + * Since: 1.4 + */ +typedef enum { + CLUTTER_VERTEX_SHADER, + CLUTTER_FRAGMENT_SHADER +} ClutterShaderType; + +/** + * ClutterModifierType: + * @CLUTTER_SHIFT_MASK: Mask applied by the Shift key + * @CLUTTER_LOCK_MASK: Mask applied by the Caps Lock key + * @CLUTTER_CONTROL_MASK: Mask applied by the Control key + * @CLUTTER_MOD1_MASK: Mask applied by the first Mod key + * @CLUTTER_MOD2_MASK: Mask applied by the second Mod key + * @CLUTTER_MOD3_MASK: Mask applied by the third Mod key + * @CLUTTER_MOD4_MASK: Mask applied by the fourth Mod key + * @CLUTTER_MOD5_MASK: Mask applied by the fifth Mod key + * @CLUTTER_BUTTON1_MASK: Mask applied by the first pointer button + * @CLUTTER_BUTTON2_MASK: Mask applied by the second pointer button + * @CLUTTER_BUTTON3_MASK: Mask applied by the third pointer button + * @CLUTTER_BUTTON4_MASK: Mask applied by the fourth pointer button + * @CLUTTER_BUTTON5_MASK: Mask applied by the fifth pointer button + * @CLUTTER_SUPER_MASK: Mask applied by the Super key + * @CLUTTER_HYPER_MASK: Mask applied by the Hyper key + * @CLUTTER_META_MASK: Mask applied by the Meta key + * @CLUTTER_RELEASE_MASK: Mask applied during release + * @CLUTTER_MODIFIER_MASK: A mask covering all modifier types + * + * Masks applied to a #ClutterEvent by modifiers. + * + * Note that Clutter may add internal values to events which include + * reserved values such as %CLUTTER_MODIFIER_RESERVED_13_MASK. Your code + * should preserve and ignore them. You can use %CLUTTER_MODIFIER_MASK to + * remove all reserved values. + * + * Since: 0.4 + */ +typedef enum { + CLUTTER_SHIFT_MASK = 1 << 0, + CLUTTER_LOCK_MASK = 1 << 1, + CLUTTER_CONTROL_MASK = 1 << 2, + CLUTTER_MOD1_MASK = 1 << 3, + CLUTTER_MOD2_MASK = 1 << 4, + CLUTTER_MOD3_MASK = 1 << 5, + CLUTTER_MOD4_MASK = 1 << 6, + CLUTTER_MOD5_MASK = 1 << 7, + CLUTTER_BUTTON1_MASK = 1 << 8, + CLUTTER_BUTTON2_MASK = 1 << 9, + CLUTTER_BUTTON3_MASK = 1 << 10, + CLUTTER_BUTTON4_MASK = 1 << 11, + CLUTTER_BUTTON5_MASK = 1 << 12, + +#ifndef __GTK_DOC_IGNORE__ + CLUTTER_MODIFIER_RESERVED_13_MASK = 1 << 13, + CLUTTER_MODIFIER_RESERVED_14_MASK = 1 << 14, + CLUTTER_MODIFIER_RESERVED_15_MASK = 1 << 15, + CLUTTER_MODIFIER_RESERVED_16_MASK = 1 << 16, + CLUTTER_MODIFIER_RESERVED_17_MASK = 1 << 17, + CLUTTER_MODIFIER_RESERVED_18_MASK = 1 << 18, + CLUTTER_MODIFIER_RESERVED_19_MASK = 1 << 19, + CLUTTER_MODIFIER_RESERVED_20_MASK = 1 << 20, + CLUTTER_MODIFIER_RESERVED_21_MASK = 1 << 21, + CLUTTER_MODIFIER_RESERVED_22_MASK = 1 << 22, + CLUTTER_MODIFIER_RESERVED_23_MASK = 1 << 23, + CLUTTER_MODIFIER_RESERVED_24_MASK = 1 << 24, + CLUTTER_MODIFIER_RESERVED_25_MASK = 1 << 25, +#endif + + CLUTTER_SUPER_MASK = 1 << 26, + CLUTTER_HYPER_MASK = 1 << 27, + CLUTTER_META_MASK = 1 << 28, + +#ifndef __GTK_DOC_IGNORE__ + CLUTTER_MODIFIER_RESERVED_29_MASK = 1 << 29, +#endif + + CLUTTER_RELEASE_MASK = 1 << 30, + + /* Combination of CLUTTER_SHIFT_MASK..CLUTTER_BUTTON5_MASK + CLUTTER_SUPER_MASK + + CLUTTER_HYPER_MASK + CLUTTER_META_MASK + CLUTTER_RELEASE_MASK */ + CLUTTER_MODIFIER_MASK = 0x5c001fff +} ClutterModifierType; + +/** + * ClutterActorFlags: + * @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 + * @CLUTTER_ACTOR_NO_LAYOUT: the actor provides an explicit layout management + * policy for its children; this flag will prevent Clutter from automatic + * queueing of relayout and will defer all layouting to the actor itself + * + * Flags used to signal the state of an actor. + */ +typedef enum { /*< prefix=CLUTTER_ACTOR >*/ + CLUTTER_ACTOR_MAPPED = 1 << 1, + CLUTTER_ACTOR_REALIZED = 1 << 2, + CLUTTER_ACTOR_REACTIVE = 1 << 3, + CLUTTER_ACTOR_VISIBLE = 1 << 4, + CLUTTER_ACTOR_NO_LAYOUT = 1 << 5 +} ClutterActorFlags; + +/** + * ClutterOffscreenRedirect: + * @CLUTTER_OFFSCREEN_REDIRECT_AUTOMATIC_FOR_OPACITY: Only redirect + * the actor if it is semi-transparent and its has_overlaps() + * virtual returns %TRUE. This is the default. + * @CLUTTER_OFFSCREEN_REDIRECT_ALWAYS: Always redirect the actor to an + * offscreen buffer even if it is fully opaque. + * + * Possible flags to pass to clutter_actor_set_offscreen_redirect(). + * + * Since: 1.8 + */ +typedef enum { /*< prefix=CLUTTER_OFFSCREEN_REDIRECT >*/ + CLUTTER_OFFSCREEN_REDIRECT_AUTOMATIC_FOR_OPACITY = 1<<0, + CLUTTER_OFFSCREEN_REDIRECT_ALWAYS = 1<<1 +} ClutterOffscreenRedirect; + +/** + * 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. + * @CLUTTER_DELEGATE_LAYOUT: Whether the allocation should be delegated + * to the #ClutterLayoutManager instance stored inside the + * #ClutterActor:layout-manager property of #ClutterActor. This flag + * should only be used if you are subclassing #ClutterActor and + * overriding the #ClutterActorClass.allocate() virtual function, but + * you wish to use the default implementation of the virtual function + * inside #ClutterActor. Added in Clutter 1.10. + * + * Flags passed to the #ClutterActorClass.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, + CLUTTER_DELEGATE_LAYOUT = 1 << 2 +} ClutterAllocationFlags; + +/** + * ClutterAlignAxis: + * @CLUTTER_ALIGN_X_AXIS: Maintain the alignment on the X axis + * @CLUTTER_ALIGN_Y_AXIS: Maintain the alignment on the Y axis + * @CLUTTER_ALIGN_BOTH: Maintain the alignment on both the X and Y axis + * + * Specifies the axis on which #ClutterAlignConstraint should maintain + * the alignment. + * + * Since: 1.4 + */ +typedef enum { /*< prefix=CLUTTER_ALIGN >*/ + CLUTTER_ALIGN_X_AXIS, + CLUTTER_ALIGN_Y_AXIS, + CLUTTER_ALIGN_BOTH +} ClutterAlignAxis; + +/** + * ClutterInterpolation: + * @CLUTTER_INTERPOLATION_LINEAR: linear interpolation + * @CLUTTER_INTERPOLATION_CUBIC: cubic interpolation + * + * The mode of interpolation between key frames + * + * Since: 1.2 + * + * Deprecated: 1.22 + */ +typedef enum { + CLUTTER_INTERPOLATION_LINEAR, + CLUTTER_INTERPOLATION_CUBIC +} ClutterInterpolation; + +/** + * ClutterBinAlignment: + * @CLUTTER_BIN_ALIGNMENT_FIXED: Fixed position alignment; the + * #ClutterBinLayout will honour the fixed position provided + * by the actors themselves when allocating them + * @CLUTTER_BIN_ALIGNMENT_FILL: Fill the allocation size + * @CLUTTER_BIN_ALIGNMENT_START: Position the actors at the top + * or left side of the container, depending on the axis + * @CLUTTER_BIN_ALIGNMENT_END: Position the actors at the bottom + * or right side of the container, depending on the axis + * @CLUTTER_BIN_ALIGNMENT_CENTER: Position the actors at the + * center of the container, depending on the axis + * + * The alignment policies available on each axis for #ClutterBinLayout + * + * Since: 1.2 + * + * Deprecated: 1.12: Use #ClutterActorAlign and the #ClutterActor + * API instead + */ +typedef enum { + CLUTTER_BIN_ALIGNMENT_FIXED, + CLUTTER_BIN_ALIGNMENT_FILL, + CLUTTER_BIN_ALIGNMENT_START, + CLUTTER_BIN_ALIGNMENT_END, + CLUTTER_BIN_ALIGNMENT_CENTER +} ClutterBinAlignment; + +/** + * ClutterBindCoordinate: + * @CLUTTER_BIND_X: Bind the X coordinate + * @CLUTTER_BIND_Y: Bind the Y coordinate + * @CLUTTER_BIND_WIDTH: Bind the width + * @CLUTTER_BIND_HEIGHT: Bind the height + * @CLUTTER_BIND_POSITION: Equivalent to to %CLUTTER_BIND_X and + * %CLUTTER_BIND_Y (added in Clutter 1.6) + * @CLUTTER_BIND_SIZE: Equivalent to %CLUTTER_BIND_WIDTH and + * %CLUTTER_BIND_HEIGHT (added in Clutter 1.6) + * @CLUTTER_BIND_ALL: Equivalent to %CLUTTER_BIND_POSITION and + * %CLUTTER_BIND_SIZE (added in Clutter 1.10) + * + * Specifies which property should be used in a binding + * + * Since: 1.4 + */ +typedef enum { /*< prefix=CLUTTER_BIND >*/ + CLUTTER_BIND_X, + CLUTTER_BIND_Y, + CLUTTER_BIND_WIDTH, + CLUTTER_BIND_HEIGHT, + CLUTTER_BIND_POSITION, + CLUTTER_BIND_SIZE, + CLUTTER_BIND_ALL +} ClutterBindCoordinate; + +/** + * ClutterEffectPaintFlags: + * @CLUTTER_EFFECT_PAINT_ACTOR_DIRTY: The actor or one of its children + * has queued a redraw before this paint. This implies that the effect + * should call clutter_actor_continue_paint() to chain to the next + * effect and can not cache any results from a previous paint. + * + * Flags passed to the ‘paint’ or ‘pick’ method of #ClutterEffect. + */ +typedef enum { /*< prefix=CLUTTER_EFFECT_PAINT >*/ + CLUTTER_EFFECT_PAINT_ACTOR_DIRTY = (1 << 0) +} ClutterEffectPaintFlags; + +/** + * ClutterBoxAlignment: + * @CLUTTER_BOX_ALIGNMENT_START: Align the child to the top or to + * to the left, depending on the used axis + * @CLUTTER_BOX_ALIGNMENT_CENTER: Align the child to the center + * @CLUTTER_BOX_ALIGNMENT_END: Align the child to the bottom or to + * the right, depending on the used axis + * + * The alignment policies available on each axis of the #ClutterBoxLayout + * + * Since: 1.2 + */ +typedef enum { + CLUTTER_BOX_ALIGNMENT_START, + CLUTTER_BOX_ALIGNMENT_END, + CLUTTER_BOX_ALIGNMENT_CENTER +} ClutterBoxAlignment; + +/** + * ClutterLongPressState: + * @CLUTTER_LONG_PRESS_QUERY: Queries the action whether it supports + * long presses + * @CLUTTER_LONG_PRESS_ACTIVATE: Activates the action on a long press + * @CLUTTER_LONG_PRESS_CANCEL: The long press was cancelled + * + * The states for the #ClutterClickAction::long-press signal. + * + * Since: 1.8 + */ +typedef enum { /*< prefix=CLUTTER_LONG_PRESS >*/ + CLUTTER_LONG_PRESS_QUERY, + CLUTTER_LONG_PRESS_ACTIVATE, + CLUTTER_LONG_PRESS_CANCEL +} ClutterLongPressState; + +/** + * ClutterStaticColor: + * @CLUTTER_COLOR_WHITE: White color (ffffffff) + * @CLUTTER_COLOR_BLACK: Black color (000000ff) + * @CLUTTER_COLOR_RED: Red color (ff0000ff) + * @CLUTTER_COLOR_DARK_RED: Dark red color (800000ff) + * @CLUTTER_COLOR_GREEN: Green color (00ff00ff) + * @CLUTTER_COLOR_DARK_GREEN: Dark green color (008000ff) + * @CLUTTER_COLOR_BLUE: Blue color (0000ffff) + * @CLUTTER_COLOR_DARK_BLUE: Dark blue color (000080ff) + * @CLUTTER_COLOR_CYAN: Cyan color (00ffffff) + * @CLUTTER_COLOR_DARK_CYAN: Dark cyan color (008080ff) + * @CLUTTER_COLOR_MAGENTA: Magenta color (ff00ffff) + * @CLUTTER_COLOR_DARK_MAGENTA: Dark magenta color (800080ff) + * @CLUTTER_COLOR_YELLOW: Yellow color (ffff00ff) + * @CLUTTER_COLOR_DARK_YELLOW: Dark yellow color (808000ff) + * @CLUTTER_COLOR_GRAY: Gray color (a0a0a4ff) + * @CLUTTER_COLOR_DARK_GRAY: Dark Gray color (808080ff) + * @CLUTTER_COLOR_LIGHT_GRAY: Light gray color (c0c0c0ff) + * @CLUTTER_COLOR_BUTTER: Butter color (edd400ff) + * @CLUTTER_COLOR_BUTTER_LIGHT: Light butter color (fce94fff) + * @CLUTTER_COLOR_BUTTER_DARK: Dark butter color (c4a000ff) + * @CLUTTER_COLOR_ORANGE: Orange color (f57900ff) + * @CLUTTER_COLOR_ORANGE_LIGHT: Light orange color (fcaf3fff) + * @CLUTTER_COLOR_ORANGE_DARK: Dark orange color (ce5c00ff) + * @CLUTTER_COLOR_CHOCOLATE: Chocolate color (c17d11ff) + * @CLUTTER_COLOR_CHOCOLATE_LIGHT: Light chocolate color (e9b96eff) + * @CLUTTER_COLOR_CHOCOLATE_DARK: Dark chocolate color (8f5902ff) + * @CLUTTER_COLOR_CHAMELEON: Chameleon color (73d216ff) + * @CLUTTER_COLOR_CHAMELEON_LIGHT: Light chameleon color (8ae234ff) + * @CLUTTER_COLOR_CHAMELEON_DARK: Dark chameleon color (4e9a06ff) + * @CLUTTER_COLOR_SKY_BLUE: Sky color (3465a4ff) + * @CLUTTER_COLOR_SKY_BLUE_LIGHT: Light sky color (729fcfff) + * @CLUTTER_COLOR_SKY_BLUE_DARK: Dark sky color (204a87ff) + * @CLUTTER_COLOR_PLUM: Plum color (75507bff) + * @CLUTTER_COLOR_PLUM_LIGHT: Light plum color (ad7fa8ff) + * @CLUTTER_COLOR_PLUM_DARK: Dark plum color (5c3566ff) + * @CLUTTER_COLOR_SCARLET_RED: Scarlet red color (cc0000ff) + * @CLUTTER_COLOR_SCARLET_RED_LIGHT: Light scarlet red color (ef2929ff) + * @CLUTTER_COLOR_SCARLET_RED_DARK: Dark scarlet red color (a40000ff) + * @CLUTTER_COLOR_ALUMINIUM_1: Aluminium, first variant (eeeeecff) + * @CLUTTER_COLOR_ALUMINIUM_2: Aluminium, second variant (d3d7cfff) + * @CLUTTER_COLOR_ALUMINIUM_3: Aluminium, third variant (babdb6ff) + * @CLUTTER_COLOR_ALUMINIUM_4: Aluminium, fourth variant (888a85ff) + * @CLUTTER_COLOR_ALUMINIUM_5: Aluminium, fifth variant (555753ff) + * @CLUTTER_COLOR_ALUMINIUM_6: Aluminium, sixth variant (2e3436ff) + * @CLUTTER_COLOR_TRANSPARENT: Transparent color (00000000) + * + * Named colors, for accessing global colors defined by Clutter + * + * Since: 1.6 + */ +typedef enum { /*< prefix=CLUTTER_COLOR >*/ + /* CGA/EGA-like palette */ + CLUTTER_COLOR_WHITE = 0, + CLUTTER_COLOR_BLACK, + CLUTTER_COLOR_RED, + CLUTTER_COLOR_DARK_RED, + CLUTTER_COLOR_GREEN, + CLUTTER_COLOR_DARK_GREEN, + CLUTTER_COLOR_BLUE, + CLUTTER_COLOR_DARK_BLUE, + CLUTTER_COLOR_CYAN, + CLUTTER_COLOR_DARK_CYAN, + CLUTTER_COLOR_MAGENTA, + CLUTTER_COLOR_DARK_MAGENTA, + CLUTTER_COLOR_YELLOW, + CLUTTER_COLOR_DARK_YELLOW, + CLUTTER_COLOR_GRAY, + CLUTTER_COLOR_DARK_GRAY, + CLUTTER_COLOR_LIGHT_GRAY, + + /* Tango icon palette */ + CLUTTER_COLOR_BUTTER, + CLUTTER_COLOR_BUTTER_LIGHT, + CLUTTER_COLOR_BUTTER_DARK, + CLUTTER_COLOR_ORANGE, + CLUTTER_COLOR_ORANGE_LIGHT, + CLUTTER_COLOR_ORANGE_DARK, + CLUTTER_COLOR_CHOCOLATE, + CLUTTER_COLOR_CHOCOLATE_LIGHT, + CLUTTER_COLOR_CHOCOLATE_DARK, + CLUTTER_COLOR_CHAMELEON, + CLUTTER_COLOR_CHAMELEON_LIGHT, + CLUTTER_COLOR_CHAMELEON_DARK, + CLUTTER_COLOR_SKY_BLUE, + CLUTTER_COLOR_SKY_BLUE_LIGHT, + CLUTTER_COLOR_SKY_BLUE_DARK, + CLUTTER_COLOR_PLUM, + CLUTTER_COLOR_PLUM_LIGHT, + CLUTTER_COLOR_PLUM_DARK, + CLUTTER_COLOR_SCARLET_RED, + CLUTTER_COLOR_SCARLET_RED_LIGHT, + CLUTTER_COLOR_SCARLET_RED_DARK, + CLUTTER_COLOR_ALUMINIUM_1, + CLUTTER_COLOR_ALUMINIUM_2, + CLUTTER_COLOR_ALUMINIUM_3, + CLUTTER_COLOR_ALUMINIUM_4, + CLUTTER_COLOR_ALUMINIUM_5, + CLUTTER_COLOR_ALUMINIUM_6, + + /* Fully transparent black */ + CLUTTER_COLOR_TRANSPARENT +} ClutterStaticColor; + +/** + * ClutterDragAxis: + * @CLUTTER_DRAG_AXIS_NONE: No constraint + * @CLUTTER_DRAG_X_AXIS: Set a constraint on the X axis + * @CLUTTER_DRAG_Y_AXIS: Set a constraint on the Y axis + * + * The axis of the constraint that should be applied on the + * dragging action + * + * Since: 1.4 + */ +typedef enum { /*< prefix=CLUTTER_DRAG >*/ + CLUTTER_DRAG_AXIS_NONE = 0, + + CLUTTER_DRAG_X_AXIS, + CLUTTER_DRAG_Y_AXIS +} ClutterDragAxis; + +/** + * ClutterEventFlags: + * @CLUTTER_EVENT_NONE: No flag set + * @CLUTTER_EVENT_FLAG_SYNTHETIC: Synthetic event + * + * Flags for the #ClutterEvent + * + * Since: 0.6 + */ +typedef enum { /*< flags prefix=CLUTTER_EVENT >*/ + CLUTTER_EVENT_NONE = 0, + CLUTTER_EVENT_FLAG_SYNTHETIC = 1 << 0 +} ClutterEventFlags; + +/** + * ClutterEventType: + * @CLUTTER_NOTHING: Empty event + * @CLUTTER_KEY_PRESS: Key press event + * @CLUTTER_KEY_RELEASE: Key release event + * @CLUTTER_MOTION: Pointer motion event + * @CLUTTER_ENTER: Actor enter event + * @CLUTTER_LEAVE: Actor leave event + * @CLUTTER_BUTTON_PRESS: Pointer button press event + * @CLUTTER_BUTTON_RELEASE: Pointer button release event + * @CLUTTER_SCROLL: Pointer scroll event + * @CLUTTER_STAGE_STATE: Stage state change event + * @CLUTTER_DESTROY_NOTIFY: Destroy notification event + * @CLUTTER_CLIENT_MESSAGE: Client message event + * @CLUTTER_DELETE: Stage delete event + * @CLUTTER_TOUCH_BEGIN: A new touch event sequence has started; + * event added in 1.10 + * @CLUTTER_TOUCH_UPDATE: A touch event sequence has been updated; + * event added in 1.10 + * @CLUTTER_TOUCH_END: A touch event sequence has finished; + * event added in 1.10 + * @CLUTTER_TOUCH_CANCEL: A touch event sequence has been canceled; + * event added in 1.10 + * @CLUTTER_TOUCHPAD_PINCH: A pinch gesture event, the current state is + * determined by its phase field; event added in 1.24 + * @CLUTTER_TOUCHPAD_SWIPE: A swipe gesture event, the current state is + * determined by its phase field; event added in 1.24 + * @CLUTTER_PROXIMITY_IN: A tool entered in proximity to a tablet; + * event added in 1.28 + * @CLUTTER_PROXIMITY_OUT: A tool left from the proximity area of a tablet; + * event added in 1.28 + * @CLUTTER_EVENT_LAST: Marks the end of the #ClutterEventType enumeration; + * added in 1.10 + * + * Types of events. + * + * Since: 0.4 + */ +typedef enum { /*< prefix=CLUTTER >*/ + CLUTTER_NOTHING = 0, + CLUTTER_KEY_PRESS, + CLUTTER_KEY_RELEASE, + CLUTTER_MOTION, + CLUTTER_ENTER, + CLUTTER_LEAVE, + CLUTTER_BUTTON_PRESS, + CLUTTER_BUTTON_RELEASE, + CLUTTER_SCROLL, + CLUTTER_STAGE_STATE, + CLUTTER_DESTROY_NOTIFY, + CLUTTER_CLIENT_MESSAGE, + CLUTTER_DELETE, + CLUTTER_TOUCH_BEGIN, + CLUTTER_TOUCH_UPDATE, + CLUTTER_TOUCH_END, + CLUTTER_TOUCH_CANCEL, + CLUTTER_TOUCHPAD_PINCH, + CLUTTER_TOUCHPAD_SWIPE, + CLUTTER_PROXIMITY_IN, + CLUTTER_PROXIMITY_OUT, + CLUTTER_PAD_BUTTON_PRESS, + CLUTTER_PAD_BUTTON_RELEASE, + CLUTTER_PAD_STRIP, + CLUTTER_PAD_RING, + + CLUTTER_EVENT_LAST /* helper */ +} ClutterEventType; + +/** + * ClutterScrollDirection: + * @CLUTTER_SCROLL_UP: Scroll up + * @CLUTTER_SCROLL_DOWN: Scroll down + * @CLUTTER_SCROLL_LEFT: Scroll left + * @CLUTTER_SCROLL_RIGHT: Scroll right + * @CLUTTER_SCROLL_SMOOTH: Precise scrolling delta (available in 1.10) + * + * Direction of a pointer scroll event. + * + * The %CLUTTER_SCROLL_SMOOTH value implies that the #ClutterScrollEvent + * has precise scrolling delta information. + * + * Since: 0.4 + */ +typedef enum { /*< prefix=CLUTTER_SCROLL >*/ + CLUTTER_SCROLL_UP, + CLUTTER_SCROLL_DOWN, + CLUTTER_SCROLL_LEFT, + CLUTTER_SCROLL_RIGHT, + CLUTTER_SCROLL_SMOOTH +} ClutterScrollDirection; + +/** + * ClutterStageState: + * @CLUTTER_STAGE_STATE_FULLSCREEN: Fullscreen mask + * @CLUTTER_STAGE_STATE_OFFSCREEN: Offscreen mask (deprecated) + * @CLUTTER_STAGE_STATE_ACTIVATED: Activated mask + * + * Stage state masks, used by the #ClutterEvent of type %CLUTTER_STAGE_STATE. + * + * Since: 0.4 + */ +typedef enum { + CLUTTER_STAGE_STATE_FULLSCREEN = (1 << 1), + CLUTTER_STAGE_STATE_OFFSCREEN = (1 << 2), + CLUTTER_STAGE_STATE_ACTIVATED = (1 << 3) +} ClutterStageState; + +/** + * ClutterFeatureFlags: + * @CLUTTER_FEATURE_TEXTURE_NPOT: Set if NPOTS textures supported. + * @CLUTTER_FEATURE_SYNC_TO_VBLANK: Set if vblank syncing supported. + * @CLUTTER_FEATURE_TEXTURE_YUV: Set if YUV based textures supported. + * @CLUTTER_FEATURE_TEXTURE_READ_PIXELS: Set if texture pixels can be read. + * @CLUTTER_FEATURE_STAGE_STATIC: Set if stage size if fixed (i.e framebuffer) + * @CLUTTER_FEATURE_STAGE_USER_RESIZE: Set if stage is able to be user resized. + * @CLUTTER_FEATURE_STAGE_CURSOR: Set if stage has a graphical cursor. + * @CLUTTER_FEATURE_SHADERS_GLSL: Set if the backend supports GLSL shaders. + * @CLUTTER_FEATURE_OFFSCREEN: Set if the backend supports offscreen rendering. + * @CLUTTER_FEATURE_STAGE_MULTIPLE: Set if multiple stages are supported. + * @CLUTTER_FEATURE_SWAP_EVENTS: Set if the GLX_INTEL_swap_event is supported. + * + * Runtime flags indicating specific features available via Clutter window + * system and graphics backend. + * + * Since: 0.4 + */ +typedef enum +{ + CLUTTER_FEATURE_TEXTURE_NPOT = (1 << 2), + CLUTTER_FEATURE_SYNC_TO_VBLANK = (1 << 3), + CLUTTER_FEATURE_TEXTURE_YUV = (1 << 4), + CLUTTER_FEATURE_TEXTURE_READ_PIXELS = (1 << 5), + CLUTTER_FEATURE_STAGE_STATIC = (1 << 6), + CLUTTER_FEATURE_STAGE_USER_RESIZE = (1 << 7), + CLUTTER_FEATURE_STAGE_CURSOR = (1 << 8), + CLUTTER_FEATURE_SHADERS_GLSL = (1 << 9), + CLUTTER_FEATURE_OFFSCREEN = (1 << 10), + CLUTTER_FEATURE_STAGE_MULTIPLE = (1 << 11), + CLUTTER_FEATURE_SWAP_EVENTS = (1 << 12) +} ClutterFeatureFlags; + +/** + * ClutterFlowOrientation: + * @CLUTTER_FLOW_HORIZONTAL: Arrange the children of the flow layout + * horizontally first + * @CLUTTER_FLOW_VERTICAL: Arrange the children of the flow layout + * vertically first + * + * The direction of the arrangement of the children inside + * a #ClutterFlowLayout + * + * Since: 1.2 + */ +typedef enum { /*< prefix=CLUTTER_FLOW >*/ + CLUTTER_FLOW_HORIZONTAL, + CLUTTER_FLOW_VERTICAL +} ClutterFlowOrientation; + +/** + * ClutterInputDeviceType: + * @CLUTTER_POINTER_DEVICE: A pointer device + * @CLUTTER_KEYBOARD_DEVICE: A keyboard device + * @CLUTTER_EXTENSION_DEVICE: A generic extension device + * @CLUTTER_JOYSTICK_DEVICE: A joystick device + * @CLUTTER_TABLET_DEVICE: A tablet device + * @CLUTTER_TOUCHPAD_DEVICE: A touchpad device + * @CLUTTER_TOUCHSCREEN_DEVICE: A touch screen device + * @CLUTTER_PEN_DEVICE: A pen device + * @CLUTTER_ERASER_DEVICE: An eraser device + * @CLUTTER_CURSOR_DEVICE: A cursor device + * @CLUTTER_PAD_DEVICE: A tablet pad + * @CLUTTER_N_DEVICE_TYPES: The number of device types + * + * The types of input devices available. + * + * The #ClutterInputDeviceType enumeration can be extended at later + * date; not every platform supports every input device type. + * + * Since: 1.0 + */ +typedef enum { + CLUTTER_POINTER_DEVICE, + CLUTTER_KEYBOARD_DEVICE, + CLUTTER_EXTENSION_DEVICE, + CLUTTER_JOYSTICK_DEVICE, + CLUTTER_TABLET_DEVICE, + CLUTTER_TOUCHPAD_DEVICE, + CLUTTER_TOUCHSCREEN_DEVICE, + CLUTTER_PEN_DEVICE, + CLUTTER_ERASER_DEVICE, + CLUTTER_CURSOR_DEVICE, + CLUTTER_PAD_DEVICE, + + CLUTTER_N_DEVICE_TYPES +} ClutterInputDeviceType; + +/** + * ClutterInputMode: + * @CLUTTER_INPUT_MODE_MASTER: A master, virtual device + * @CLUTTER_INPUT_MODE_SLAVE: A slave, physical device, attached to + * a master device + * @CLUTTER_INPUT_MODE_FLOATING: A slave, physical device, not attached + * to a master device + * + * The mode for input devices available. + * + * Since: 1.6 + */ +typedef enum { + CLUTTER_INPUT_MODE_MASTER, + CLUTTER_INPUT_MODE_SLAVE, + CLUTTER_INPUT_MODE_FLOATING +} ClutterInputMode; + +/** + * ClutterInputAxis: + * @CLUTTER_INPUT_AXIS_IGNORE: Unused axis + * @CLUTTER_INPUT_AXIS_X: The position on the X axis + * @CLUTTER_INPUT_AXIS_Y: The position of the Y axis + * @CLUTTER_INPUT_AXIS_PRESSURE: The pressure information + * @CLUTTER_INPUT_AXIS_XTILT: The tilt on the X axis + * @CLUTTER_INPUT_AXIS_YTILT: The tile on the Y axis + * @CLUTTER_INPUT_AXIS_WHEEL: A wheel + * @CLUTTER_INPUT_AXIS_DISTANCE: Distance (Since 1.12) + * @CLUTTER_INPUT_AXIS_ROTATION: Rotation along the z-axis (Since 1.28) + * @CLUTTER_INPUT_AXIS_SLIDER: A slider (Since 1.28) + * @CLUTTER_INPUT_AXIS_LAST: Last value of the enumeration; this value is + * useful when iterating over the enumeration values (Since 1.12) + * + * The type of axes Clutter recognizes on a #ClutterInputDevice + * + * Since: 1.6 + */ +typedef enum { + CLUTTER_INPUT_AXIS_IGNORE, + + CLUTTER_INPUT_AXIS_X, + CLUTTER_INPUT_AXIS_Y, + CLUTTER_INPUT_AXIS_PRESSURE, + CLUTTER_INPUT_AXIS_XTILT, + CLUTTER_INPUT_AXIS_YTILT, + CLUTTER_INPUT_AXIS_WHEEL, + CLUTTER_INPUT_AXIS_DISTANCE, + CLUTTER_INPUT_AXIS_ROTATION, + CLUTTER_INPUT_AXIS_SLIDER, + + CLUTTER_INPUT_AXIS_LAST +} ClutterInputAxis; + +/** + * ClutterSnapEdge: + * @CLUTTER_SNAP_EDGE_TOP: the top edge + * @CLUTTER_SNAP_EDGE_RIGHT: the right edge + * @CLUTTER_SNAP_EDGE_BOTTOM: the bottom edge + * @CLUTTER_SNAP_EDGE_LEFT: the left edge + * + * The edge to snap + * + * Since: 1.6 + */ +typedef enum { + CLUTTER_SNAP_EDGE_TOP, + CLUTTER_SNAP_EDGE_RIGHT, + CLUTTER_SNAP_EDGE_BOTTOM, + CLUTTER_SNAP_EDGE_LEFT +} ClutterSnapEdge; + +/** + * 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; + +/** + * ClutterSwipeDirection: + * @CLUTTER_SWIPE_DIRECTION_UP: Upwards swipe gesture + * @CLUTTER_SWIPE_DIRECTION_DOWN: Downwards swipe gesture + * @CLUTTER_SWIPE_DIRECTION_LEFT: Leftwards swipe gesture + * @CLUTTER_SWIPE_DIRECTION_RIGHT: Rightwards swipe gesture + * + * The main direction of the swipe gesture + * + * Since: 1.8 + */ +typedef enum { /*< prefix=CLUTTER_SWIPE_DIRECTION >*/ + CLUTTER_SWIPE_DIRECTION_UP = 1 << 0, + CLUTTER_SWIPE_DIRECTION_DOWN = 1 << 1, + CLUTTER_SWIPE_DIRECTION_LEFT = 1 << 2, + CLUTTER_SWIPE_DIRECTION_RIGHT = 1 << 3 +} ClutterSwipeDirection; + +/** + * ClutterPanAxis: + * @CLUTTER_PAN_AXIS_NONE: No constraint + * @CLUTTER_PAN_X_AXIS: Set a constraint on the X axis + * @CLUTTER_PAN_Y_AXIS: Set a constraint on the Y axis + * @CLUTTER_PAN_AXIS_AUTO: Constrain panning automatically based on initial + * movement (available since 1.24) + * + * The axis of the constraint that should be applied on the + * panning action + * + * Since: 1.12 + */ +typedef enum { /*< prefix=CLUTTER_PAN >*/ + CLUTTER_PAN_AXIS_NONE = 0, + + CLUTTER_PAN_X_AXIS, + CLUTTER_PAN_Y_AXIS, + + CLUTTER_PAN_AXIS_AUTO +} ClutterPanAxis; + + +/** + * ClutterTableAlignment: + * @CLUTTER_TABLE_ALIGNMENT_START: Align the child to the top or to the + * left of a cell in the table, depending on the axis + * @CLUTTER_TABLE_ALIGNMENT_CENTER: Align the child to the center of + * a cell in the table + * @CLUTTER_TABLE_ALIGNMENT_END: Align the child to the bottom or to the + * right of a cell in the table, depending on the axis + * + * The alignment policies available on each axis of the #ClutterTableLayout + * + * Since: 1.4 + * + * Deprecated: 1.22: Use the alignment properties of #ClutterActor + */ +typedef enum { + CLUTTER_TABLE_ALIGNMENT_START, + CLUTTER_TABLE_ALIGNMENT_CENTER, + CLUTTER_TABLE_ALIGNMENT_END +} ClutterTableAlignment; + +/** + * ClutterTextureFlags: + * @CLUTTER_TEXTURE_NONE: No flags + * @CLUTTER_TEXTURE_RGB_FLAG_BGR: Unused flag + * @CLUTTER_TEXTURE_RGB_FLAG_PREMULT: Unused flag + * @CLUTTER_TEXTURE_YUV_FLAG_YUV2: Unused flag + * + * Flags for clutter_texture_set_from_rgb_data() and + * clutter_texture_set_from_yuv_data(). + * + * Since: 0.4 + * + * Deprecated: 1.22: The #ClutterTexture class was the only user of + * this API + */ +typedef enum { /*< prefix=CLUTTER_TEXTURE >*/ + CLUTTER_TEXTURE_NONE = 0, + CLUTTER_TEXTURE_RGB_FLAG_BGR = 1 << 1, + CLUTTER_TEXTURE_RGB_FLAG_PREMULT = 1 << 2, /* FIXME: not handled */ + CLUTTER_TEXTURE_YUV_FLAG_YUV2 = 1 << 3 +} ClutterTextureFlags; + +/** + * ClutterTextureQuality: + * @CLUTTER_TEXTURE_QUALITY_LOW: fastest rendering will use nearest neighbour + * interpolation when rendering. good setting. + * @CLUTTER_TEXTURE_QUALITY_MEDIUM: higher quality rendering without using + * extra resources. + * @CLUTTER_TEXTURE_QUALITY_HIGH: render the texture with the best quality + * available using extra memory. + * + * Enumaration controlling the texture quality. + * + * Since: 0.8 + * + * Deprecated: 1.22: The #ClutterTexture class was the only used ot + * this API; use #ClutterImage and clutter_actor_set_content_scaling_filters() + * instead. + */ +typedef enum { /*< prefix=CLUTTER_TEXTURE_QUALITY >*/ + CLUTTER_TEXTURE_QUALITY_LOW, + CLUTTER_TEXTURE_QUALITY_MEDIUM, + CLUTTER_TEXTURE_QUALITY_HIGH +} ClutterTextureQuality; + +/** + * ClutterTimelineDirection: + * @CLUTTER_TIMELINE_FORWARD: forward direction for a timeline + * @CLUTTER_TIMELINE_BACKWARD: backward direction for a timeline + * + * The direction of a #ClutterTimeline + * + * Since: 0.6 + */ +typedef enum { + CLUTTER_TIMELINE_FORWARD, + CLUTTER_TIMELINE_BACKWARD +} ClutterTimelineDirection; + +/** + * 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 + * @CLUTTER_UNIT_CM: Unit expressed in centimeters + * + * The type of unit in which a value is expressed + * + * This enumeration might be expanded at later date + * + * Since: 1.0 + */ +typedef enum { /*< prefix=CLUTTER_UNIT >*/ + CLUTTER_UNIT_PIXEL, + CLUTTER_UNIT_EM, + CLUTTER_UNIT_MM, + CLUTTER_UNIT_POINT, + CLUTTER_UNIT_CM +} ClutterUnitType; + +#define CLUTTER_PATH_RELATIVE (32) + +/** + * ClutterPathNodeType: + * @CLUTTER_PATH_MOVE_TO: jump to the given position + * @CLUTTER_PATH_LINE_TO: create a line from the last node to the + * given position + * @CLUTTER_PATH_CURVE_TO: bezier curve using the last position and + * three control points. + * @CLUTTER_PATH_CLOSE: create a line from the last node to the last + * %CLUTTER_PATH_MOVE_TO node. + * @CLUTTER_PATH_REL_MOVE_TO: same as %CLUTTER_PATH_MOVE_TO but with + * coordinates relative to the last node. + * @CLUTTER_PATH_REL_LINE_TO: same as %CLUTTER_PATH_LINE_TO but with + * coordinates relative to the last node. + * @CLUTTER_PATH_REL_CURVE_TO: same as %CLUTTER_PATH_CURVE_TO but with + * coordinates relative to the last node. + * + * Types of nodes in a #ClutterPath. + * + * Since: 1.0 + */ +typedef enum { + CLUTTER_PATH_MOVE_TO = 0, + CLUTTER_PATH_LINE_TO = 1, + CLUTTER_PATH_CURVE_TO = 2, + CLUTTER_PATH_CLOSE = 3, + + CLUTTER_PATH_REL_MOVE_TO = CLUTTER_PATH_MOVE_TO | CLUTTER_PATH_RELATIVE, + CLUTTER_PATH_REL_LINE_TO = CLUTTER_PATH_LINE_TO | CLUTTER_PATH_RELATIVE, + CLUTTER_PATH_REL_CURVE_TO = CLUTTER_PATH_CURVE_TO | CLUTTER_PATH_RELATIVE +} ClutterPathNodeType; + +/** + * ClutterActorAlign: + * @CLUTTER_ACTOR_ALIGN_FILL: Stretch to cover the whole allocated space + * @CLUTTER_ACTOR_ALIGN_START: Snap to left or top side, leaving space + * to the right or bottom. For horizontal layouts, in right-to-left + * locales this should be reversed. + * @CLUTTER_ACTOR_ALIGN_CENTER: Center the actor inside the allocation + * @CLUTTER_ACTOR_ALIGN_END: Snap to right or bottom side, leaving space + * to the left or top. For horizontal layouts, in right-to-left locales + * this should be reversed. + * + * Controls how a #ClutterActor should align itself inside the extra space + * assigned to it during the allocation. + * + * Alignment only matters if the allocated space given to an actor is + * bigger than its natural size; for example, when the #ClutterActor:x-expand + * or the #ClutterActor:y-expand properties of #ClutterActor are set to %TRUE. + * + * Since: 1.10 + */ +typedef enum { + CLUTTER_ACTOR_ALIGN_FILL, + CLUTTER_ACTOR_ALIGN_START, + CLUTTER_ACTOR_ALIGN_CENTER, + CLUTTER_ACTOR_ALIGN_END +} ClutterActorAlign; + +/** + * ClutterRepaintFlags: + * @CLUTTER_REPAINT_FLAGS_PRE_PAINT: Run the repaint function prior to + * painting the stages + * @CLUTTER_REPAINT_FLAGS_POST_PAINT: Run the repaint function after + * painting the stages + * @CLUTTER_REPAINT_FLAGS_QUEUE_REDRAW_ON_ADD: Ensure that a new frame + * is queued after adding the repaint function + * + * Flags to pass to clutter_threads_add_repaint_func_full(). + * + * Since: 1.10 + */ +typedef enum { + CLUTTER_REPAINT_FLAGS_PRE_PAINT = 1 << 0, + CLUTTER_REPAINT_FLAGS_POST_PAINT = 1 << 1, + CLUTTER_REPAINT_FLAGS_QUEUE_REDRAW_ON_ADD = 1 << 2 +} ClutterRepaintFlags; + +/** + * ClutterContentGravity: + * @CLUTTER_CONTENT_GRAVITY_TOP_LEFT: Align the content to the top left corner + * @CLUTTER_CONTENT_GRAVITY_TOP: Align the content to the top edge + * @CLUTTER_CONTENT_GRAVITY_TOP_RIGHT: Align the content to the top right corner + * @CLUTTER_CONTENT_GRAVITY_LEFT: Align the content to the left edge + * @CLUTTER_CONTENT_GRAVITY_CENTER: Align the content to the center + * @CLUTTER_CONTENT_GRAVITY_RIGHT: Align the content to the right edge + * @CLUTTER_CONTENT_GRAVITY_BOTTOM_LEFT: Align the content to the bottom left corner + * @CLUTTER_CONTENT_GRAVITY_BOTTOM: Align the content to the bottom edge + * @CLUTTER_CONTENT_GRAVITY_BOTTOM_RIGHT: Align the content to the bottom right corner + * @CLUTTER_CONTENT_GRAVITY_RESIZE_FILL: Resize the content to fill the allocation + * @CLUTTER_CONTENT_GRAVITY_RESIZE_ASPECT: Resize the content to remain within the + * allocation, while maintaining the aspect ratio + * + * Controls the alignment of the #ClutterContent inside a #ClutterActor. + * + * Since: 1.10 + */ +typedef enum { + CLUTTER_CONTENT_GRAVITY_TOP_LEFT, + CLUTTER_CONTENT_GRAVITY_TOP, + CLUTTER_CONTENT_GRAVITY_TOP_RIGHT, + + CLUTTER_CONTENT_GRAVITY_LEFT, + CLUTTER_CONTENT_GRAVITY_CENTER, + CLUTTER_CONTENT_GRAVITY_RIGHT, + + CLUTTER_CONTENT_GRAVITY_BOTTOM_LEFT, + CLUTTER_CONTENT_GRAVITY_BOTTOM, + CLUTTER_CONTENT_GRAVITY_BOTTOM_RIGHT, + + CLUTTER_CONTENT_GRAVITY_RESIZE_FILL, + CLUTTER_CONTENT_GRAVITY_RESIZE_ASPECT +} ClutterContentGravity; + +/** + * ClutterScalingFilter: + * @CLUTTER_SCALING_FILTER_LINEAR: Linear interpolation filter + * @CLUTTER_SCALING_FILTER_NEAREST: Nearest neighbor interpolation filter + * @CLUTTER_SCALING_FILTER_TRILINEAR: Trilinear minification filter, with + * mipmap generation; this filter linearly interpolates on every axis, + * as well as between mipmap levels. + * + * The scaling filters to be used with the #ClutterActor:minification-filter + * and #ClutterActor:magnification-filter properties. + * + * Since: 1.10 + */ +typedef enum { + CLUTTER_SCALING_FILTER_LINEAR, + CLUTTER_SCALING_FILTER_NEAREST, + CLUTTER_SCALING_FILTER_TRILINEAR +} ClutterScalingFilter; + +/** + * ClutterOrientation: + * @CLUTTER_ORIENTATION_HORIZONTAL: An horizontal orientation + * @CLUTTER_ORIENTATION_VERTICAL: A vertical orientation + * + * Represents the orientation of actors or layout managers. + * + * Since: 1.12 + */ +typedef enum { + CLUTTER_ORIENTATION_HORIZONTAL, + CLUTTER_ORIENTATION_VERTICAL +} ClutterOrientation; + +/** + * ClutterScrollMode: + * @CLUTTER_SCROLL_NONE: Ignore scrolling + * @CLUTTER_SCROLL_HORIZONTALLY: Scroll only horizontally + * @CLUTTER_SCROLL_VERTICALLY: Scroll only vertically + * @CLUTTER_SCROLL_BOTH: Scroll in both directions + * + * Scroll modes. + * + * Since: 1.12 + */ +typedef enum { /*< prefix=CLUTTER_SCROLL >*/ + CLUTTER_SCROLL_NONE = 0, + + CLUTTER_SCROLL_HORIZONTALLY = 1 << 0, + CLUTTER_SCROLL_VERTICALLY = 1 << 1, + + CLUTTER_SCROLL_BOTH = CLUTTER_SCROLL_HORIZONTALLY | CLUTTER_SCROLL_VERTICALLY +} ClutterScrollMode; + +/** + * ClutterGridPosition: + * @CLUTTER_GRID_POSITION_LEFT: left position + * @CLUTTER_GRID_POSITION_RIGHT: right position + * @CLUTTER_GRID_POSITION_TOP: top position + * @CLUTTER_GRID_POSITION_BOTTOM: bottom position + * + * Grid position modes. + * + * Since: 1.12 + */ +typedef enum { + CLUTTER_GRID_POSITION_LEFT, + CLUTTER_GRID_POSITION_RIGHT, + CLUTTER_GRID_POSITION_TOP, + CLUTTER_GRID_POSITION_BOTTOM +} ClutterGridPosition; + +/** + * ClutterContentRepeat: + * @CLUTTER_REPEAT_NONE: No repeat + * @CLUTTER_REPEAT_X_AXIS: Repeat the content on the X axis + * @CLUTTER_REPEAT_Y_AXIS: Repeat the content on the Y axis + * @CLUTTER_REPEAT_BOTH: Repeat the content on both axis + * + * Content repeat modes. + * + * Since: 1.12 + */ +typedef enum { + CLUTTER_REPEAT_NONE = 0, + CLUTTER_REPEAT_X_AXIS = 1 << 0, + CLUTTER_REPEAT_Y_AXIS = 1 << 1, + CLUTTER_REPEAT_BOTH = CLUTTER_REPEAT_X_AXIS | CLUTTER_REPEAT_Y_AXIS +} ClutterContentRepeat; + +/** + * ClutterStepMode: + * @CLUTTER_STEP_MODE_START: The change in the value of a + * %CLUTTER_STEP progress mode should occur at the start of + * the transition + * @CLUTTER_STEP_MODE_END: The change in the value of a + * %CLUTTER_STEP progress mode should occur at the end of + * the transition + * + * Change the value transition of a step function. + * + * See clutter_timeline_set_step_progress(). + * + * Since: 1.12 + */ +typedef enum { + CLUTTER_STEP_MODE_START, + CLUTTER_STEP_MODE_END +} ClutterStepMode; + +/** + * ClutterZoomAxis: + * @CLUTTER_ZOOM_X_AXIS: Scale only on the X axis + * @CLUTTER_ZOOM_Y_AXIS: Scale only on the Y axis + * @CLUTTER_ZOOM_BOTH: Scale on both axis + * + * The axis of the constraint that should be applied by the + * zooming action. + * + * Since: 1.12 + */ +typedef enum { /*< prefix=CLUTTER_ZOOM >*/ + CLUTTER_ZOOM_X_AXIS, + CLUTTER_ZOOM_Y_AXIS, + CLUTTER_ZOOM_BOTH +} ClutterZoomAxis; + +/** + * ClutterGestureTriggerEdge: + * @CLUTTER_GESTURE_TRIGGER_EDGE_NONE: Tell #ClutterGestureAction that + * the gesture must begin immediately and there's no drag limit that + * will cause its cancellation; + * @CLUTTER_GESTURE_TRIGGER_EDGE_AFTER: Tell #ClutterGestureAction that + * it needs to wait until the drag threshold has been exceeded before + * considering that the gesture has begun; + * @CLUTTER_GESTURE_TRIGGER_EDGE_BEFORE: Tell #ClutterGestureAction that + * the gesture must begin immediately and that it must be cancelled + * once the drag exceed the configured threshold. + * + * Enum passed to the clutter_gesture_action_set_threshold_trigger_edge() + * function. + * + * Since: 1.18 + */ +typedef enum { + CLUTTER_GESTURE_TRIGGER_EDGE_NONE = 0, + CLUTTER_GESTURE_TRIGGER_EDGE_AFTER, + CLUTTER_GESTURE_TRIGGER_EDGE_BEFORE +} ClutterGestureTriggerEdge; + +/** + * ClutterTouchpadGesturePhase: + * @CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN: The gesture has begun. + * @CLUTTER_TOUCHPAD_GESTURE_PHASE_UPDATE: The gesture has been updated. + * @CLUTTER_TOUCHPAD_GESTURE_PHASE_END: The gesture was finished, changes + * should be permanently applied. + * @CLUTTER_TOUCHPAD_GESTURE_PHASE_CANCEL: The gesture was cancelled, all + * changes should be undone. + * + * The phase of a touchpad gesture event. All gestures are guaranteed to + * begin with an event of type %CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN, + * followed by a number of %CLUTTER_TOUCHPAD_GESTURE_PHASE_UPDATE (possibly 0). + * + * A finished gesture may have 2 possible outcomes, an event with phase + * %CLUTTER_TOUCHPAD_GESTURE_PHASE_END will be emitted when the gesture is + * considered successful, this should be used as the hint to perform any + * permanent changes. + + * Cancelled gestures may be so for a variety of reasons, due to hardware, + * or due to the gesture recognition layers hinting the gesture did not + * finish resolutely (eg. a 3rd finger being added during a pinch gesture). + * In these cases, the last event with report the phase + * %CLUTTER_TOUCHPAD_GESTURE_PHASE_CANCEL, this should be used as a hint + * to undo any visible/permanent changes that were done throughout the + * progress of the gesture. + * + * See also #ClutterTouchpadPinchEvent and #ClutterTouchpadPinchEvent. + * + * Since: 1.24 + */ +typedef enum { + CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN, + CLUTTER_TOUCHPAD_GESTURE_PHASE_UPDATE, + CLUTTER_TOUCHPAD_GESTURE_PHASE_END, + CLUTTER_TOUCHPAD_GESTURE_PHASE_CANCEL +} ClutterTouchpadGesturePhase; + +/** + * ClutterScrollSource: + * @CLUTTER_SCROLL_SOURCE_UNKNOWN: Source of scroll events is unknown. + * @CLUTTER_SCROLL_SOURCE_WHEEL: The scroll event is originated by a mouse wheel. + * @CLUTTER_SCROLL_SOURCE_FINGER: The scroll event is originated by one or more + * fingers on the device (eg. touchpads). + * @CLUTTER_SCROLL_SOURCE_CONTINUOUS: The scroll event is originated by the + * motion of some device (eg. a scroll button is set). + * + * The scroll source determines the source of the scroll event. Keep in mind + * that the source device #ClutterInputDeviceType is not enough to infer + * the scroll source. + * + * Since: 1.26 + */ +typedef enum { + CLUTTER_SCROLL_SOURCE_UNKNOWN, + CLUTTER_SCROLL_SOURCE_WHEEL, + CLUTTER_SCROLL_SOURCE_FINGER, + CLUTTER_SCROLL_SOURCE_CONTINUOUS +} ClutterScrollSource; + +/** + * ClutterScrollFinishFlags: + * @CLUTTER_SCROLL_FINISHED_NONE: no axis was stopped. + * @CLUTTER_SCROLL_FINISHED_HORIZONTAL: The horizontal axis stopped. + * @CLUTTER_SCROLL_FINISHED_VERTICAL: The vertical axis stopped. + * + * Flags used to notify the axes that were stopped in a #ClutterScrollEvent. + * These can be used to trigger post-scroll effects like kinetic scrolling. + * + * Since: 1.26 + */ +typedef enum { + CLUTTER_SCROLL_FINISHED_NONE = 0, + CLUTTER_SCROLL_FINISHED_HORIZONTAL = 1 << 0, + CLUTTER_SCROLL_FINISHED_VERTICAL = 1 << 1 +} ClutterScrollFinishFlags; + +/** + * ClutterInputDeviceToolType: + * @CLUTTER_INPUT_DEVICE_TOOL_NONE: No tool + * @CLUTTER_INPUT_DEVICE_TOOL_PEN: The tool is a pen + * @CLUTTER_INPUT_DEVICE_TOOL_ERASER: The tool is an eraser + * @CLUTTER_INPUT_DEVICE_TOOL_BRUSH: The tool is a brush + * @CLUTTER_INPUT_DEVICE_TOOL_PENCIL: The tool is a pencil + * @CLUTTER_INPUT_DEVICE_TOOL_AIRBRUSH: The tool is an airbrush + * @CLUTTER_INPUT_DEVICE_TOOL_MOUSE: The tool is a mouse + * @CLUTTER_INPUT_DEVICE_TOOL_LENS: The tool is a lens + * + * Defines the type of tool that a #ClutterInputDeviceTool represents. + * + * Since: 1.28 + */ +typedef enum { + CLUTTER_INPUT_DEVICE_TOOL_NONE, + CLUTTER_INPUT_DEVICE_TOOL_PEN, + CLUTTER_INPUT_DEVICE_TOOL_ERASER, + CLUTTER_INPUT_DEVICE_TOOL_BRUSH, + CLUTTER_INPUT_DEVICE_TOOL_PENCIL, + CLUTTER_INPUT_DEVICE_TOOL_AIRBRUSH, + CLUTTER_INPUT_DEVICE_TOOL_MOUSE, + CLUTTER_INPUT_DEVICE_TOOL_LENS +} ClutterInputDeviceToolType; + +typedef enum { + CLUTTER_INPUT_DEVICE_PAD_SOURCE_UNKNOWN, + CLUTTER_INPUT_DEVICE_PAD_SOURCE_FINGER, +} ClutterInputDevicePadSource; + +typedef enum { + CLUTTER_INPUT_DEVICE_MAPPING_ABSOLUTE, + CLUTTER_INPUT_DEVICE_MAPPING_RELATIVE, +} ClutterInputDeviceMapping; + +G_END_DECLS + +#endif /* __CLUTTER_ENUMS_H__ */ diff --git a/clutter/clutter/clutter-event-private.h b/clutter/clutter/clutter-event-private.h new file mode 100644 index 0000000..00d627d --- /dev/null +++ b/clutter/clutter/clutter-event-private.h @@ -0,0 +1,36 @@ +#ifndef __CLUTTER_EVENT_PRIVATE_H__ +#define __CLUTTER_EVENT_PRIVATE_H__ + +#include + +G_BEGIN_DECLS + +void _clutter_event_set_pointer_emulated (ClutterEvent *event, + gboolean is_emulated); + +/* Reinjecting queued events for processing */ +void _clutter_process_event (ClutterEvent *event); + +gboolean _clutter_event_process_filters (ClutterEvent *event); + +/* clears the event queue inside the main context */ +void _clutter_clear_events_queue (void); +void _clutter_clear_events_queue_for_stage (ClutterStage *stage); + +void _clutter_event_set_platform_data (ClutterEvent *event, + gpointer data); +gpointer _clutter_event_get_platform_data (const ClutterEvent *event); + +void _clutter_event_set_state_full (ClutterEvent *event, + ClutterModifierType button_state, + ClutterModifierType base_state, + ClutterModifierType latched_state, + ClutterModifierType locked_state, + ClutterModifierType effective_state); + +void _clutter_event_push (const ClutterEvent *event, + gboolean do_copy); + +G_END_DECLS + +#endif /* __CLUTTER_EVENT_PRIVATE_H__ */ diff --git a/clutter/clutter/clutter-event-translator.c b/clutter/clutter/clutter-event-translator.c new file mode 100644 index 0000000..b98957d --- /dev/null +++ b/clutter/clutter/clutter-event-translator.c @@ -0,0 +1,38 @@ +#include "clutter-build-config.h" + +#include "clutter-event-translator.h" + +#include "clutter-backend.h" +#include "clutter-private.h" + +#define clutter_event_translator_get_type _clutter_event_translator_get_type + +typedef ClutterEventTranslatorIface ClutterEventTranslatorInterface; + +G_DEFINE_INTERFACE (ClutterEventTranslator, clutter_event_translator, G_TYPE_OBJECT); + +static ClutterTranslateReturn +default_translate_event (ClutterEventTranslator *translator, + gpointer native, + ClutterEvent *event) +{ + return CLUTTER_TRANSLATE_CONTINUE; +} + +static void +clutter_event_translator_default_init (ClutterEventTranslatorIface *iface) +{ + iface->translate_event = default_translate_event; +} + +ClutterTranslateReturn +_clutter_event_translator_translate_event (ClutterEventTranslator *translator, + gpointer native, + ClutterEvent *translated) +{ + ClutterEventTranslatorIface *iface; + + iface = CLUTTER_EVENT_TRANSLATOR_GET_IFACE (translator); + + return iface->translate_event (translator, native, translated); +} diff --git a/clutter/clutter/clutter-event-translator.h b/clutter/clutter/clutter-event-translator.h new file mode 100644 index 0000000..e784fd9 --- /dev/null +++ b/clutter/clutter/clutter-event-translator.h @@ -0,0 +1,41 @@ +#ifndef __CLUTTER_EVENT_TRANSLATOR_H__ +#define __CLUTTER_EVENT_TRANSLATOR_H__ + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_EVENT_TRANSLATOR (_clutter_event_translator_get_type ()) +#define CLUTTER_EVENT_TRANSLATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_EVENT_TRANSLATOR, ClutterEventTranslator)) +#define CLUTTER_IS_EVENT_TRANSLATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_EVENT_TRANSLATOR)) +#define CLUTTER_EVENT_TRANSLATOR_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), CLUTTER_TYPE_EVENT_TRANSLATOR, ClutterEventTranslatorIface)) + +typedef struct _ClutterEventTranslator ClutterEventTranslator; +typedef struct _ClutterEventTranslatorIface ClutterEventTranslatorIface; + +typedef enum { + CLUTTER_TRANSLATE_CONTINUE, + CLUTTER_TRANSLATE_REMOVE, + CLUTTER_TRANSLATE_QUEUE +} ClutterTranslateReturn; + +struct _ClutterEventTranslatorIface +{ + GTypeInterface g_iface; + + ClutterTranslateReturn (* translate_event) (ClutterEventTranslator *translator, + gpointer native, + ClutterEvent *translated); +}; + +CLUTTER_AVAILABLE_IN_MUTTER +GType _clutter_event_translator_get_type (void) G_GNUC_CONST; + +ClutterTranslateReturn _clutter_event_translator_translate_event (ClutterEventTranslator *translator, + gpointer native, + ClutterEvent *translated); + +G_END_DECLS + +#endif /* __CLUTTER_EVENT_TRANSLATOR_H__ */ diff --git a/clutter/clutter/clutter-event.c b/clutter/clutter/clutter-event.c new file mode 100644 index 0000000..35a1a4d --- /dev/null +++ b/clutter/clutter/clutter-event.c @@ -0,0 +1,2175 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-backend-private.h" +#include "clutter-debug.h" +#include "clutter-event-private.h" +#include "clutter-keysyms.h" +#include "clutter-private.h" + +#include + +/** + * SECTION:clutter-event + * @short_description: User and window system events + * + * Windowing events handled by Clutter. + * + * The events usually come from the windowing backend, but can also + * be synthesized by Clutter itself or by the application code. + */ + +typedef struct _ClutterEventPrivate { + ClutterEvent base; + + ClutterInputDevice *device; + ClutterInputDevice *source_device; + + gdouble delta_x; + gdouble delta_y; + + ClutterInputDeviceTool *tool; + + gpointer platform_data; + + ClutterModifierType button_state; + ClutterModifierType base_state; + ClutterModifierType latched_state; + ClutterModifierType locked_state; + + guint is_pointer_emulated : 1; +} ClutterEventPrivate; + +typedef struct _ClutterEventFilter { + int id; + + ClutterStage *stage; + ClutterEventFilterFunc func; + GDestroyNotify notify; + gpointer user_data; +} ClutterEventFilter; + +static GHashTable *all_events = NULL; + +G_DEFINE_BOXED_TYPE (ClutterEvent, clutter_event, + clutter_event_copy, + clutter_event_free); + +static ClutterEventSequence * +clutter_event_sequence_copy (ClutterEventSequence *sequence) +{ + /* Nothing to copy here */ + return sequence; +} + +static void +clutter_event_sequence_free (ClutterEventSequence *sequence) +{ + /* Nothing to free here */ +} + +G_DEFINE_BOXED_TYPE (ClutterEventSequence, clutter_event_sequence, + clutter_event_sequence_copy, + clutter_event_sequence_free); + +static gboolean +is_event_allocated (const ClutterEvent *event) +{ + if (all_events == NULL) + return FALSE; + + return g_hash_table_lookup (all_events, event) != NULL; +} + +/* + * _clutter_event_get_platform_data: + * @event: a #ClutterEvent + * + * Retrieves the pointer to platform-specific data inside an event + * + * Return value: a pointer to platform-specific data + * + * Since: 1.4 + */ +gpointer +_clutter_event_get_platform_data (const ClutterEvent *event) +{ + if (!is_event_allocated (event)) + return NULL; + + return ((ClutterEventPrivate *) event)->platform_data; +} + +/*< private > + * _clutter_event_set_platform_data: + * @event: a #ClutterEvent + * @data: a pointer to platform-specific data + * + * Sets the pointer to platform-specific data inside an event + * + * Since: 1.4 + */ +void +_clutter_event_set_platform_data (ClutterEvent *event, + gpointer data) +{ + if (!is_event_allocated (event)) + return; + + ((ClutterEventPrivate *) event)->platform_data = data; +} + +void +_clutter_event_set_pointer_emulated (ClutterEvent *event, + gboolean is_emulated) +{ + if (!is_event_allocated (event)) + return; + + ((ClutterEventPrivate *) event)->is_pointer_emulated = !!is_emulated; +} + +/** + * clutter_event_type: + * @event: a #ClutterEvent + * + * Retrieves the type of the event. + * + * Return value: a #ClutterEventType + */ +ClutterEventType +clutter_event_type (const ClutterEvent *event) +{ + g_return_val_if_fail (event != NULL, CLUTTER_NOTHING); + + return event->type; +} + +/** + * clutter_event_get_time: + * @event: a #ClutterEvent + * + * Retrieves the time of the event. + * + * Return value: the time of the event, or %CLUTTER_CURRENT_TIME + * + * Since: 0.4 + */ +guint32 +clutter_event_get_time (const ClutterEvent *event) +{ + g_return_val_if_fail (event != NULL, CLUTTER_CURRENT_TIME); + + return event->any.time; +} + +/** + * clutter_event_set_time: + * @event: a #ClutterEvent + * @time_: the time of the event + * + * Sets the time of the event. + * + * Since: 1.8 + */ +void +clutter_event_set_time (ClutterEvent *event, + guint32 time_) +{ + g_return_if_fail (event != NULL); + + event->any.time = time_; +} + +/** + * clutter_event_get_state: + * @event: a #ClutterEvent + * + * Retrieves the modifier state of the event. In case the window system + * supports reporting latched and locked modifiers, this function returns + * the effective state. + * + * Return value: the modifier state parameter, or 0 + * + * Since: 0.4 + */ +ClutterModifierType +clutter_event_get_state (const ClutterEvent *event) +{ + g_return_val_if_fail (event != NULL, 0); + + switch (event->type) + { + case CLUTTER_KEY_PRESS: + case CLUTTER_KEY_RELEASE: + return event->key.modifier_state; + + case CLUTTER_BUTTON_PRESS: + case CLUTTER_BUTTON_RELEASE: + return event->button.modifier_state; + + case CLUTTER_TOUCH_BEGIN: + case CLUTTER_TOUCH_UPDATE: + case CLUTTER_TOUCH_END: + case CLUTTER_TOUCH_CANCEL: + return event->touch.modifier_state; + + case CLUTTER_MOTION: + return event->motion.modifier_state; + + case CLUTTER_SCROLL: + return event->scroll.modifier_state; + + default: + break; + } + + return 0; +} + +/** + * clutter_event_set_state: + * @event: a #ClutterEvent + * @state: the modifier state to set + * + * Sets the modifier state of the event. + * + * Since: 1.8 + */ +void +clutter_event_set_state (ClutterEvent *event, + ClutterModifierType state) +{ + g_return_if_fail (event != NULL); + + switch (event->type) + { + case CLUTTER_KEY_PRESS: + case CLUTTER_KEY_RELEASE: + event->key.modifier_state = state; + break; + + case CLUTTER_BUTTON_PRESS: + case CLUTTER_BUTTON_RELEASE: + event->button.modifier_state = state; + break; + + case CLUTTER_MOTION: + event->motion.modifier_state = state; + break; + + case CLUTTER_TOUCH_BEGIN: + case CLUTTER_TOUCH_UPDATE: + case CLUTTER_TOUCH_END: + case CLUTTER_TOUCH_CANCEL: + event->touch.modifier_state = state; + break; + + case CLUTTER_SCROLL: + event->scroll.modifier_state = state; + break; + + default: + break; + } +} + +void +_clutter_event_set_state_full (ClutterEvent *event, + ClutterModifierType button_state, + ClutterModifierType base_state, + ClutterModifierType latched_state, + ClutterModifierType locked_state, + ClutterModifierType effective_state) +{ + ClutterEventPrivate *private = (ClutterEventPrivate*) event; + + private->button_state = button_state; + private->base_state = base_state; + private->latched_state = latched_state; + private->locked_state = locked_state; + + clutter_event_set_state (event, effective_state); +} + +/** + * clutter_event_get_state_full: + * @event: a #ClutterEvent + * @button_state: (out) (allow-none): the pressed buttons as a mask + * @base_state: (out) (allow-none): the regular pressed modifier keys + * @latched_state: (out) (allow-none): the latched modifier keys (currently released but still valid for one key press/release) + * @locked_state: (out) (allow-none): the locked modifier keys (valid until the lock key is pressed and released again) + * @effective_state: (out) (allow-none): the logical OR of all the state bits above + * + * Retrieves the decomposition of the keyboard state into button, base, + * latched, locked and effective. This can be used to transmit to other + * applications, for example when implementing a wayland compositor. + * + * Since: 1.16 + */ +void +clutter_event_get_state_full (const ClutterEvent *event, + ClutterModifierType *button_state, + ClutterModifierType *base_state, + ClutterModifierType *latched_state, + ClutterModifierType *locked_state, + ClutterModifierType *effective_state) +{ + const ClutterEventPrivate *private = (const ClutterEventPrivate*) event; + + g_return_if_fail (event != NULL); + + if (button_state) + *button_state = private->button_state; + if (base_state) + *base_state = private->base_state; + if (latched_state) + *latched_state = private->latched_state; + if (locked_state) + *locked_state = private->locked_state; + if (effective_state) + *effective_state = clutter_event_get_state (event); +} + +/** + * clutter_event_get_coords: + * @event: a #ClutterEvent + * @x: (out): return location for the X coordinate, or %NULL + * @y: (out): return location for the Y coordinate, or %NULL + * + * Retrieves the coordinates of @event and puts them into @x and @y. + * + * Since: 0.4 + */ +void +clutter_event_get_coords (const ClutterEvent *event, + gfloat *x, + gfloat *y) +{ + ClutterPoint coords; + + g_return_if_fail (event != NULL); + + clutter_event_get_position (event, &coords); + + if (x != NULL) + *x = coords.x; + + if (y != NULL) + *y = coords.y; +} + +/** + * clutter_event_get_position: + * @event: a #ClutterEvent + * @position: a #ClutterPoint + * + * Retrieves the event coordinates as a #ClutterPoint. + * + * Since: 1.12 + */ +void +clutter_event_get_position (const ClutterEvent *event, + ClutterPoint *position) +{ + g_return_if_fail (event != NULL); + g_return_if_fail (position != NULL); + + switch (event->type) + { + case CLUTTER_NOTHING: + case CLUTTER_KEY_PRESS: + case CLUTTER_KEY_RELEASE: + case CLUTTER_STAGE_STATE: + case CLUTTER_DESTROY_NOTIFY: + case CLUTTER_CLIENT_MESSAGE: + case CLUTTER_DELETE: + case CLUTTER_EVENT_LAST: + case CLUTTER_PROXIMITY_IN: + case CLUTTER_PROXIMITY_OUT: + case CLUTTER_PAD_BUTTON_PRESS: + case CLUTTER_PAD_BUTTON_RELEASE: + case CLUTTER_PAD_STRIP: + case CLUTTER_PAD_RING: + clutter_point_init (position, 0.f, 0.f); + break; + + case CLUTTER_ENTER: + case CLUTTER_LEAVE: + clutter_point_init (position, event->crossing.x, event->crossing.y); + break; + + case CLUTTER_BUTTON_PRESS: + case CLUTTER_BUTTON_RELEASE: + clutter_point_init (position, event->button.x, event->button.y); + break; + + case CLUTTER_MOTION: + clutter_point_init (position, event->motion.x, event->motion.y); + break; + + case CLUTTER_TOUCH_BEGIN: + case CLUTTER_TOUCH_UPDATE: + case CLUTTER_TOUCH_END: + case CLUTTER_TOUCH_CANCEL: + clutter_point_init (position, event->touch.x, event->touch.y); + break; + + case CLUTTER_SCROLL: + clutter_point_init (position, event->scroll.x, event->scroll.y); + break; + + case CLUTTER_TOUCHPAD_PINCH: + clutter_point_init (position, event->touchpad_pinch.x, + event->touchpad_pinch.y); + break; + + case CLUTTER_TOUCHPAD_SWIPE: + clutter_point_init (position, event->touchpad_swipe.x, + event->touchpad_swipe.y); + break; + } + +} + +/** + * clutter_event_set_coords: + * @event: a #ClutterEvent + * @x: the X coordinate of the event + * @y: the Y coordinate of the event + * + * Sets the coordinates of the @event. + * + * Since: 1.8 + */ +void +clutter_event_set_coords (ClutterEvent *event, + gfloat x, + gfloat y) +{ + g_return_if_fail (event != NULL); + + switch (event->type) + { + case CLUTTER_NOTHING: + case CLUTTER_KEY_PRESS: + case CLUTTER_KEY_RELEASE: + case CLUTTER_STAGE_STATE: + case CLUTTER_DESTROY_NOTIFY: + case CLUTTER_CLIENT_MESSAGE: + case CLUTTER_DELETE: + case CLUTTER_EVENT_LAST: + case CLUTTER_PROXIMITY_IN: + case CLUTTER_PROXIMITY_OUT: + case CLUTTER_PAD_BUTTON_PRESS: + case CLUTTER_PAD_BUTTON_RELEASE: + case CLUTTER_PAD_STRIP: + case CLUTTER_PAD_RING: + break; + + case CLUTTER_ENTER: + case CLUTTER_LEAVE: + event->crossing.x = x; + event->crossing.y = y; + break; + + case CLUTTER_BUTTON_PRESS: + case CLUTTER_BUTTON_RELEASE: + event->button.x = x; + event->button.y = y; + break; + + case CLUTTER_MOTION: + event->motion.x = x; + event->motion.y = y; + break; + + case CLUTTER_TOUCH_BEGIN: + case CLUTTER_TOUCH_UPDATE: + case CLUTTER_TOUCH_END: + case CLUTTER_TOUCH_CANCEL: + event->touch.x = x; + event->touch.y = y; + break; + + case CLUTTER_SCROLL: + event->scroll.x = x; + event->scroll.y = y; + break; + + case CLUTTER_TOUCHPAD_PINCH: + event->touchpad_pinch.x = x; + event->touchpad_pinch.y = y; + break; + + case CLUTTER_TOUCHPAD_SWIPE: + event->touchpad_swipe.x = x; + event->touchpad_swipe.y = y; + break; + } +} + +/** + * clutter_event_get_source: + * @event: a #ClutterEvent + * + * Retrieves the source #ClutterActor the event originated from, or + * NULL if the event has no source. + * + * Return value: (transfer none): a #ClutterActor + * + * Since: 0.6 + */ +ClutterActor * +clutter_event_get_source (const ClutterEvent *event) +{ + g_return_val_if_fail (event != NULL, NULL); + + return event->any.source; +} + +/** + * clutter_event_set_source: + * @event: a #ClutterEvent + * @actor: (allow-none): a #ClutterActor, or %NULL + * + * Sets the source #ClutterActor of @event. + * + * Since: 1.8 + */ +void +clutter_event_set_source (ClutterEvent *event, + ClutterActor *actor) +{ + g_return_if_fail (event != NULL); + g_return_if_fail (actor == NULL || CLUTTER_IS_ACTOR (actor)); + + event->any.source = actor; +} + +/** + * clutter_event_get_stage: + * @event: a #ClutterEvent + * + * Retrieves the source #ClutterStage the event originated for, or + * %NULL if the event has no stage. + * + * Return value: (transfer none): a #ClutterStage + * + * Since: 0.8 + */ +ClutterStage * +clutter_event_get_stage (const ClutterEvent *event) +{ + g_return_val_if_fail (event != NULL, NULL); + + return event->any.stage; +} + +/** + * clutter_event_set_stage: + * @event: a #ClutterEvent + * @stage: (allow-none): a #ClutterStage, or %NULL + * + * Sets the source #ClutterStage of the event. + * + * Since: 1.8 + */ +void +clutter_event_set_stage (ClutterEvent *event, + ClutterStage *stage) +{ + g_return_if_fail (event != NULL); + g_return_if_fail (stage == NULL || CLUTTER_IS_STAGE (stage)); + + if (event->any.stage == stage) + return; + + event->any.stage = stage; +} + +/** + * clutter_event_get_flags: + * @event: a #ClutterEvent + * + * Retrieves the #ClutterEventFlags of @event + * + * Return value: the event flags + * + * Since: 1.0 + */ +ClutterEventFlags +clutter_event_get_flags (const ClutterEvent *event) +{ + g_return_val_if_fail (event != NULL, CLUTTER_EVENT_NONE); + + return event->any.flags; +} + +/** + * clutter_event_set_flags: + * @event: a #ClutterEvent + * @flags: a binary OR of #ClutterEventFlags values + * + * Sets the #ClutterEventFlags of @event + * + * Since: 1.8 + */ +void +clutter_event_set_flags (ClutterEvent *event, + ClutterEventFlags flags) +{ + g_return_if_fail (event != NULL); + + if (event->any.flags == flags) + return; + + event->any.flags = flags; + event->any.flags |= CLUTTER_EVENT_FLAG_SYNTHETIC; +} + +/** + * clutter_event_get_related: + * @event: a #ClutterEvent of type %CLUTTER_ENTER or of + * type %CLUTTER_LEAVE + * + * Retrieves the related actor of a crossing event. + * + * Return value: (transfer none): the related #ClutterActor, or %NULL + * + * Since: 1.0 + */ +ClutterActor * +clutter_event_get_related (const ClutterEvent *event) +{ + g_return_val_if_fail (event != NULL, NULL); + g_return_val_if_fail (event->type == CLUTTER_ENTER || + event->type == CLUTTER_LEAVE, NULL); + + return event->crossing.related; +} + +/** + * clutter_event_set_related: + * @event: a #ClutterEvent of type %CLUTTER_ENTER or %CLUTTER_LEAVE + * @actor: (allow-none): a #ClutterActor or %NULL + * + * Sets the related actor of a crossing event + * + * Since: 1.8 + */ +void +clutter_event_set_related (ClutterEvent *event, + ClutterActor *actor) +{ + g_return_if_fail (event != NULL); + g_return_if_fail (event->type == CLUTTER_ENTER || + event->type == CLUTTER_LEAVE); + g_return_if_fail (actor == NULL || CLUTTER_IS_ACTOR (actor)); + + if (event->crossing.related == actor) + return; + + event->crossing.related = actor; +} + +/** + * clutter_event_set_scroll_delta: + * @event: a #ClutterEvent of type %CLUTTER_SCROLL + * @dx: delta on the horizontal axis + * @dy: delta on the vertical axis + * + * Sets the precise scrolling information of @event. + * + * Since: 1.10 + */ +void +clutter_event_set_scroll_delta (ClutterEvent *event, + gdouble dx, + gdouble dy) +{ + g_return_if_fail (event != NULL); + g_return_if_fail (event->type == CLUTTER_SCROLL); + + if (!is_event_allocated (event)) + return; + + event->scroll.direction = CLUTTER_SCROLL_SMOOTH; + + ((ClutterEventPrivate *) event)->delta_x = dx; + ((ClutterEventPrivate *) event)->delta_y = dy; +} + +/** + * clutter_event_get_scroll_delta: + * @event: a #ClutterEvent of type %CLUTTER_SCROLL + * @dx: (out): return location for the delta on the horizontal axis + * @dy: (out): return location for the delta on the vertical axis + * + * Retrieves the precise scrolling information of @event. + * + * The @event has to have a #ClutterScrollEvent.direction value + * of %CLUTTER_SCROLL_SMOOTH. + * + * Since: 1.10 + */ +void +clutter_event_get_scroll_delta (const ClutterEvent *event, + gdouble *dx, + gdouble *dy) +{ + gdouble delta_x, delta_y; + + g_return_if_fail (event != NULL); + g_return_if_fail (event->type == CLUTTER_SCROLL); + g_return_if_fail (event->scroll.direction == CLUTTER_SCROLL_SMOOTH); + + delta_x = delta_y = 0; + + if (is_event_allocated (event)) + { + delta_x = ((ClutterEventPrivate *) event)->delta_x; + delta_y = ((ClutterEventPrivate *) event)->delta_y; + } + + if (dx != NULL) + *dx = delta_x; + + if (dy != NULL) + *dy = delta_y; +} + +/** + * clutter_event_get_scroll_direction: + * @event: a #ClutterEvent of type %CLUTTER_SCROLL + * + * Retrieves the direction of the scrolling of @event + * + * Return value: the scrolling direction + * + * Since: 1.0 + */ +ClutterScrollDirection +clutter_event_get_scroll_direction (const ClutterEvent *event) +{ + g_return_val_if_fail (event != NULL, CLUTTER_SCROLL_UP); + g_return_val_if_fail (event->type == CLUTTER_SCROLL, CLUTTER_SCROLL_UP); + + return event->scroll.direction; +} + +/** + * clutter_event_set_scroll_direction: + * @event: a #ClutterEvent + * @direction: the scrolling direction + * + * Sets the direction of the scrolling of @event + * + * Since: 1.8 + */ +void +clutter_event_set_scroll_direction (ClutterEvent *event, + ClutterScrollDirection direction) +{ + g_return_if_fail (event != NULL); + g_return_if_fail (event->type == CLUTTER_SCROLL); + + event->scroll.direction = direction; +} + +/** + * clutter_event_get_button: + * @event: a #ClutterEvent of type %CLUTTER_BUTTON_PRESS or + * of type %CLUTTER_BUTTON_RELEASE + * + * Retrieves the button number of @event + * + * Return value: the button number + * + * Since: 1.0 + */ +guint32 +clutter_event_get_button (const ClutterEvent *event) +{ + g_return_val_if_fail (event != NULL, 0); + g_return_val_if_fail (event->type == CLUTTER_BUTTON_PRESS || + event->type == CLUTTER_BUTTON_RELEASE || + event->type == CLUTTER_PAD_BUTTON_PRESS || + event->type == CLUTTER_PAD_BUTTON_RELEASE, 0); + + if (event->type == CLUTTER_BUTTON_PRESS || + event->type == CLUTTER_BUTTON_RELEASE) + return event->button.button; + else + return event->pad_button.button; +} + +/** + * clutter_event_set_button: + * @event: a #ClutterEvent or type %CLUTTER_BUTTON_PRESS or + * of type %CLUTTER_BUTTON_RELEASE + * @button: the button number + * + * Sets the button number of @event + * + * Since: 1.8 + */ +void +clutter_event_set_button (ClutterEvent *event, + guint32 button) +{ + g_return_if_fail (event != NULL); + g_return_if_fail (event->type == CLUTTER_BUTTON_PRESS || + event->type == CLUTTER_BUTTON_RELEASE); + + event->button.button = button; +} + +/** + * clutter_event_get_click_count: + * @event: a #ClutterEvent of type %CLUTTER_BUTTON_PRESS or + * of type %CLUTTER_BUTTON_RELEASE + * + * Retrieves the number of clicks of @event + * + * Return value: the click count + * + * Since: 1.0 + */ +guint32 +clutter_event_get_click_count (const ClutterEvent *event) +{ + g_return_val_if_fail (event != NULL, 0); + g_return_val_if_fail (event->type == CLUTTER_BUTTON_PRESS || + event->type == CLUTTER_BUTTON_RELEASE, 0); + + return event->button.click_count; +} + +/* keys */ + +/** + * clutter_event_get_key_symbol: + * @event: a #ClutterEvent of type %CLUTTER_KEY_PRESS or + * of type %CLUTTER_KEY_RELEASE + * + * Retrieves the key symbol of @event + * + * Return value: the key symbol representing the key + * + * Since: 1.0 + */ +guint +clutter_event_get_key_symbol (const ClutterEvent *event) +{ + g_return_val_if_fail (event != NULL, 0); + g_return_val_if_fail (event->type == CLUTTER_KEY_PRESS || + event->type == CLUTTER_KEY_RELEASE, 0); + + return event->key.keyval; +} + +/** + * clutter_event_set_key_symbol: + * @event: a #ClutterEvent of type %CLUTTER_KEY_PRESS + * or %CLUTTER_KEY_RELEASE + * @key_sym: the key symbol representing the key + * + * Sets the key symbol of @event. + * + * Since: 1.8 + */ +void +clutter_event_set_key_symbol (ClutterEvent *event, + guint key_sym) +{ + g_return_if_fail (event != NULL); + g_return_if_fail (event->type == CLUTTER_KEY_PRESS || + event->type == CLUTTER_KEY_RELEASE); + + event->key.keyval = key_sym; +} + +/** + * clutter_event_get_key_code: + * @event: a #ClutterEvent of type %CLUTTER_KEY_PRESS or + * of type %CLUTTER_KEY_RELEASE + * + * Retrieves the keycode of the key that caused @event + * + * Return value: The keycode representing the key + * + * Since: 1.0 + */ +guint16 +clutter_event_get_key_code (const ClutterEvent *event) +{ + g_return_val_if_fail (event != NULL, 0); + g_return_val_if_fail (event->type == CLUTTER_KEY_PRESS || + event->type == CLUTTER_KEY_RELEASE, 0); + + return event->key.hardware_keycode; +} + +/** + * clutter_event_set_key_code: + * @event: a #ClutterEvent of type %CLUTTER_KEY_PRESS + * or %CLUTTER_KEY_RELEASE + * @key_code: the keycode representing the key + * + * Sets the keycode of the @event. + * + * Since: 1.8 + */ +void +clutter_event_set_key_code (ClutterEvent *event, + guint16 key_code) +{ + g_return_if_fail (event != NULL); + g_return_if_fail (event->type == CLUTTER_KEY_PRESS || + event->type == CLUTTER_KEY_RELEASE); + + event->key.hardware_keycode = key_code; +} + +/** + * clutter_event_get_key_unicode: + * @event: a #ClutterEvent of type %CLUTTER_KEY_PRESS + * or %CLUTTER_KEY_RELEASE + * + * Retrieves the unicode value for the key that caused @keyev. + * + * Return value: The unicode value representing the key + */ +gunichar +clutter_event_get_key_unicode (const ClutterEvent *event) +{ + g_return_val_if_fail (event != NULL, 0); + g_return_val_if_fail (event->type == CLUTTER_KEY_PRESS || + event->type == CLUTTER_KEY_RELEASE, 0); + + if (event->key.unicode_value) + return event->key.unicode_value; + else + return clutter_keysym_to_unicode (event->key.keyval); +} + +/** + * clutter_event_set_key_unicode: + * @event: a #ClutterEvent of type %CLUTTER_KEY_PRESS + * or %CLUTTER_KEY_RELEASE + * @key_unicode: the Unicode value representing the key + * + * Sets the Unicode value of @event. + * + * Since: 1.8 + */ +void +clutter_event_set_key_unicode (ClutterEvent *event, + gunichar key_unicode) +{ + g_return_if_fail (event != NULL); + g_return_if_fail (event->type == CLUTTER_KEY_PRESS || + event->type == CLUTTER_KEY_RELEASE); + + event->key.unicode_value = key_unicode; +} + +/** + * clutter_event_get_event_sequence: + * @event: a #ClutterEvent of type %CLUTTER_TOUCH_BEGIN, + * %CLUTTER_TOUCH_UPDATE, %CLUTTER_TOUCH_END, or + * %CLUTTER_TOUCH_CANCEL + * + * Retrieves the #ClutterEventSequence of @event. + * + * Return value: (transfer none): the event sequence, or %NULL + * + * Since: 1.10 + */ +ClutterEventSequence * +clutter_event_get_event_sequence (const ClutterEvent *event) +{ + g_return_val_if_fail (event != NULL, NULL); + + if (event->type == CLUTTER_TOUCH_BEGIN || + event->type == CLUTTER_TOUCH_UPDATE || + event->type == CLUTTER_TOUCH_END || + event->type == CLUTTER_TOUCH_CANCEL) + return event->touch.sequence; + + return NULL; +} + +/** + * clutter_event_get_device_id: + * @event: a clutter event + * + * Retrieves the events device id if set. + * + * Return value: A unique identifier for the device or -1 if the event has + * no specific device set. + */ +gint +clutter_event_get_device_id (const ClutterEvent *event) +{ + ClutterInputDevice *device = NULL; + + g_return_val_if_fail (event != NULL, CLUTTER_POINTER_DEVICE); + + device = clutter_event_get_device (event); + if (device != NULL) + return clutter_input_device_get_device_id (device); + + return -1; +} + +/** + * clutter_event_get_device_type: + * @event: a #ClutterEvent + * + * Retrieves the type of the device for @event + * + * Return value: the #ClutterInputDeviceType for the device, if + * any is set + * + * Since: 1.0 + */ +ClutterInputDeviceType +clutter_event_get_device_type (const ClutterEvent *event) +{ + ClutterInputDevice *device = NULL; + + g_return_val_if_fail (event != NULL, CLUTTER_POINTER_DEVICE); + + device = clutter_event_get_device (event); + if (device != NULL) + return clutter_input_device_get_device_type (device); + + return CLUTTER_POINTER_DEVICE; +} + +/** + * clutter_event_set_device: + * @event: a #ClutterEvent + * @device: (allow-none): a #ClutterInputDevice, or %NULL + * + * Sets the device for @event. + * + * Since: 1.6 + */ +void +clutter_event_set_device (ClutterEvent *event, + ClutterInputDevice *device) +{ + g_return_if_fail (event != NULL); + g_return_if_fail (device == NULL || CLUTTER_IS_INPUT_DEVICE (device)); + + if (is_event_allocated (event)) + { + ClutterEventPrivate *real_event = (ClutterEventPrivate *) event; + + real_event->device = device; + } + + switch (event->type) + { + case CLUTTER_NOTHING: + case CLUTTER_STAGE_STATE: + case CLUTTER_DESTROY_NOTIFY: + case CLUTTER_CLIENT_MESSAGE: + case CLUTTER_DELETE: + case CLUTTER_EVENT_LAST: + break; + + case CLUTTER_ENTER: + case CLUTTER_LEAVE: + event->crossing.device = device; + break; + + case CLUTTER_BUTTON_PRESS: + case CLUTTER_BUTTON_RELEASE: + event->button.device = device; + break; + + case CLUTTER_MOTION: + event->motion.device = device; + break; + + case CLUTTER_SCROLL: + event->scroll.device = device; + break; + + case CLUTTER_TOUCH_BEGIN: + case CLUTTER_TOUCH_UPDATE: + case CLUTTER_TOUCH_END: + case CLUTTER_TOUCH_CANCEL: + event->touch.device = device; + break; + + case CLUTTER_KEY_PRESS: + case CLUTTER_KEY_RELEASE: + event->key.device = device; + break; + + case CLUTTER_TOUCHPAD_PINCH: + case CLUTTER_TOUCHPAD_SWIPE: + /* Rely on priv data for these */ + break; + + case CLUTTER_PROXIMITY_IN: + case CLUTTER_PROXIMITY_OUT: + event->proximity.device = device; + break; + + case CLUTTER_PAD_BUTTON_PRESS: + case CLUTTER_PAD_BUTTON_RELEASE: + event->pad_button.device = device; + break; + + case CLUTTER_PAD_STRIP: + event->pad_strip.device = device; + break; + + case CLUTTER_PAD_RING: + event->pad_ring.device = device; + break; + } +} + +/** + * clutter_event_get_device: + * @event: a #ClutterEvent + * + * Retrieves the #ClutterInputDevice for the event. + * If you want the physical device the event originated from, use + * clutter_event_get_source_device(). + * + * The #ClutterInputDevice structure is completely opaque and should + * be cast to the platform-specific implementation. + * + * Return value: (transfer none): the #ClutterInputDevice or %NULL. The + * returned device is owned by the #ClutterEvent and it should not + * be unreferenced + * + * Since: 1.0 + */ +ClutterInputDevice * +clutter_event_get_device (const ClutterEvent *event) +{ + ClutterInputDevice *device = NULL; + + g_return_val_if_fail (event != NULL, NULL); + + if (is_event_allocated (event)) + { + ClutterEventPrivate *real_event = (ClutterEventPrivate *) event; + + if (real_event->device != NULL) + return real_event->device; + } + + switch (event->type) + { + case CLUTTER_NOTHING: + case CLUTTER_STAGE_STATE: + case CLUTTER_DESTROY_NOTIFY: + case CLUTTER_CLIENT_MESSAGE: + case CLUTTER_DELETE: + case CLUTTER_EVENT_LAST: + break; + + case CLUTTER_ENTER: + case CLUTTER_LEAVE: + device = event->crossing.device; + break; + + case CLUTTER_BUTTON_PRESS: + case CLUTTER_BUTTON_RELEASE: + device = event->button.device; + break; + + case CLUTTER_MOTION: + device = event->motion.device; + break; + + case CLUTTER_SCROLL: + device = event->scroll.device; + break; + + case CLUTTER_TOUCH_BEGIN: + case CLUTTER_TOUCH_UPDATE: + case CLUTTER_TOUCH_END: + case CLUTTER_TOUCH_CANCEL: + device = event->touch.device; + break; + + case CLUTTER_KEY_PRESS: + case CLUTTER_KEY_RELEASE: + device = event->key.device; + break; + + case CLUTTER_TOUCHPAD_PINCH: + case CLUTTER_TOUCHPAD_SWIPE: + /* Rely on priv data for these */ + break; + + case CLUTTER_PROXIMITY_IN: + case CLUTTER_PROXIMITY_OUT: + device = event->proximity.device; + break; + + case CLUTTER_PAD_BUTTON_PRESS: + case CLUTTER_PAD_BUTTON_RELEASE: + device = event->pad_button.device; + break; + + case CLUTTER_PAD_STRIP: + device = event->pad_strip.device; + break; + + case CLUTTER_PAD_RING: + device = event->pad_ring.device; + break; + } + + return device; +} + +/** + * clutter_event_set_device_tool: + * @event: a #ClutterEvent + * @tool: (nullable): a #ClutterInputDeviceTool + * + * Sets the tool in use for this event + * + * Since: 1.28 + **/ +void +clutter_event_set_device_tool (ClutterEvent *event, + ClutterInputDeviceTool *tool) +{ + g_return_if_fail (event != NULL); + + if (is_event_allocated (event)) + { + ClutterEventPrivate *real_event = (ClutterEventPrivate *) event; + + real_event->tool = tool; + } +} + +/** + * clutter_event_get_device_tool: + * @event: a #ClutterEvent + * + * Returns the device tool that originated this event + * + * Returns: (transfer none): The tool of this event + * + * Since: 1.28 + **/ +ClutterInputDeviceTool * +clutter_event_get_device_tool (const ClutterEvent *event) +{ + g_return_val_if_fail (event != NULL, NULL); + + if (is_event_allocated (event)) + { + ClutterEventPrivate *real_event = (ClutterEventPrivate *) event; + + return real_event->tool; + } + + return NULL; +} + +/** + * clutter_event_new: + * @type: The type of event. + * + * Creates a new #ClutterEvent of the specified type. + * + * Return value: (transfer full): A newly allocated #ClutterEvent. + */ +ClutterEvent * +clutter_event_new (ClutterEventType type) +{ + ClutterEvent *new_event; + ClutterEventPrivate *priv; + + priv = g_slice_new0 (ClutterEventPrivate); + + new_event = (ClutterEvent *) priv; + new_event->type = new_event->any.type = type; + + if (G_UNLIKELY (all_events == NULL)) + all_events = g_hash_table_new (NULL, NULL); + + g_hash_table_replace (all_events, priv, GUINT_TO_POINTER (1)); + + return new_event; +} + +/** + * clutter_event_copy: + * @event: A #ClutterEvent. + * + * Copies @event. + * + * Return value: (transfer full): A newly allocated #ClutterEvent + */ +ClutterEvent * +clutter_event_copy (const ClutterEvent *event) +{ + ClutterEvent *new_event; + ClutterEventPrivate *new_real_event; + ClutterInputDevice *device; + gint n_axes = 0; + + g_return_val_if_fail (event != NULL, NULL); + + new_event = clutter_event_new (CLUTTER_NOTHING); + new_real_event = (ClutterEventPrivate *) new_event; + + *new_event = *event; + + if (is_event_allocated (event)) + { + ClutterEventPrivate *real_event = (ClutterEventPrivate *) event; + + new_real_event->device = real_event->device; + new_real_event->source_device = real_event->source_device; + new_real_event->delta_x = real_event->delta_x; + new_real_event->delta_y = real_event->delta_y; + new_real_event->is_pointer_emulated = real_event->is_pointer_emulated; + new_real_event->base_state = real_event->base_state; + new_real_event->button_state = real_event->button_state; + new_real_event->latched_state = real_event->latched_state; + new_real_event->locked_state = real_event->locked_state; + new_real_event->tool = real_event->tool; + } + + device = clutter_event_get_device (event); + if (device != NULL) + n_axes = clutter_input_device_get_n_axes (device); + + switch (event->type) + { + case CLUTTER_BUTTON_PRESS: + case CLUTTER_BUTTON_RELEASE: + if (event->button.axes != NULL) + new_event->button.axes = g_memdup (event->button.axes, + sizeof (gdouble) * n_axes); + break; + + case CLUTTER_SCROLL: + if (event->scroll.axes != NULL) + new_event->scroll.axes = g_memdup (event->scroll.axes, + sizeof (gdouble) * n_axes); + break; + + case CLUTTER_MOTION: + if (event->motion.axes != NULL) + new_event->motion.axes = g_memdup (event->motion.axes, + sizeof (gdouble) * n_axes); + break; + + case CLUTTER_TOUCH_BEGIN: + case CLUTTER_TOUCH_UPDATE: + case CLUTTER_TOUCH_END: + case CLUTTER_TOUCH_CANCEL: + if (event->touch.axes != NULL) + new_event->touch.axes = g_memdup (event->touch.axes, + sizeof (gdouble) * n_axes); + break; + + default: + break; + } + + if (is_event_allocated (event)) + _clutter_backend_copy_event_data (clutter_get_default_backend (), + event, + new_event); + + return new_event; +} + +/** + * clutter_event_free: + * @event: A #ClutterEvent. + * + * Frees all resources used by @event. + */ +void +clutter_event_free (ClutterEvent *event) +{ + if (G_LIKELY (event != NULL)) + { + _clutter_backend_free_event_data (clutter_get_default_backend (), event); + + switch (event->type) + { + case CLUTTER_BUTTON_PRESS: + case CLUTTER_BUTTON_RELEASE: + g_free (event->button.axes); + break; + + case CLUTTER_MOTION: + g_free (event->motion.axes); + break; + + case CLUTTER_SCROLL: + g_free (event->scroll.axes); + break; + + case CLUTTER_TOUCH_BEGIN: + case CLUTTER_TOUCH_UPDATE: + case CLUTTER_TOUCH_END: + case CLUTTER_TOUCH_CANCEL: + g_free (event->touch.axes); + break; + + default: + break; + } + + g_hash_table_remove (all_events, event); + g_slice_free (ClutterEventPrivate, (ClutterEventPrivate *) event); + } +} + +/** + * clutter_event_get: + * + * Pops an event off the event queue. Applications should not need to call + * this. + * + * Return value: A #ClutterEvent or NULL if queue empty + * + * Since: 0.4 + */ +ClutterEvent * +clutter_event_get (void) +{ + ClutterMainContext *context = _clutter_context_get_default (); + + if (context->events_queue == NULL) + return NULL; + + if (g_queue_is_empty (context->events_queue)) + return NULL; + + return g_queue_pop_tail (context->events_queue); +} + +/** + * clutter_event_peek: + * + * Returns a pointer to the first event from the event queue but + * does not remove it. + * + * Return value: (transfer none): A #ClutterEvent or NULL if queue empty. + * + * Since: 0.4 + */ +ClutterEvent * +clutter_event_peek (void) +{ + ClutterMainContext *context = _clutter_context_get_default (); + + g_return_val_if_fail (context != NULL, NULL); + + if (context->events_queue == NULL) + return NULL; + + if (g_queue_is_empty (context->events_queue)) + return NULL; + + return g_queue_peek_tail (context->events_queue); +} + +void +_clutter_event_push (const ClutterEvent *event, + gboolean do_copy) +{ + ClutterMainContext *context = _clutter_context_get_default (); + ClutterInputDevice *device; + + g_assert (context != NULL); + + if (context->events_queue == NULL) + context->events_queue = g_queue_new (); + + /* disabled devices don't propagate events */ + device = clutter_event_get_device (event); + if (device != NULL) + { + if (!clutter_input_device_get_enabled (device)) + return; + } + + if (do_copy) + { + ClutterEvent *copy; + + copy = clutter_event_copy (event); + event = copy; + } + + g_queue_push_head (context->events_queue, (gpointer) event); +} + +/** + * clutter_event_put: + * @event: a #ClutterEvent + * + * Puts a copy of the event on the back of the event queue. The event will + * have the %CLUTTER_EVENT_FLAG_SYNTHETIC flag set. If the source is set + * event signals will be emitted for this source and capture/bubbling for + * its ancestors. If the source is not set it will be generated by picking + * or use the actor that currently has keyboard focus + * + * Since: 0.6 + */ +void +clutter_event_put (const ClutterEvent *event) +{ + _clutter_event_push (event, TRUE); +} + +/** + * clutter_events_pending: + * + * Checks if events are pending in the event queue. + * + * Return value: TRUE if there are pending events, FALSE otherwise. + * + * Since: 0.4 + */ +gboolean +clutter_events_pending (void) +{ + ClutterMainContext *context = _clutter_context_get_default (); + + g_return_val_if_fail (context != NULL, FALSE); + + if (context->events_queue == NULL) + return FALSE; + + return g_queue_is_empty (context->events_queue) == FALSE; +} + +/** + * clutter_get_current_event_time: + * + * Retrieves the timestamp of the last event, if there is an + * event or if the event has a timestamp. + * + * Return value: the event timestamp, or %CLUTTER_CURRENT_TIME + * + * Since: 1.0 + */ +guint32 +clutter_get_current_event_time (void) +{ + const ClutterEvent* event; + + event = clutter_get_current_event (); + + if (event != NULL) + return clutter_event_get_time (event); + + return CLUTTER_CURRENT_TIME; +} + +/** + * clutter_get_current_event: + * + * If an event is currently being processed, return that event. + * This function is intended to be used to access event state + * that might not be exposed by higher-level widgets. For + * example, to get the key modifier state from a Button 'clicked' + * event. + * + * Return value: (transfer none): The current ClutterEvent, or %NULL if none + * + * Since: 1.2 + */ +const ClutterEvent * +clutter_get_current_event (void) +{ + ClutterMainContext *context = _clutter_context_get_default (); + + g_return_val_if_fail (context != NULL, NULL); + + return context->current_event != NULL ? context->current_event->data : NULL; +} + +/** + * clutter_event_get_source_device: + * @event: a #ClutterEvent + * + * Retrieves the hardware device that originated the event. + * + * If you need the virtual device, use clutter_event_get_device(). + * + * If no hardware device originated this event, this function will + * return the same device as clutter_event_get_device(). + * + * Return value: (transfer none): a pointer to a #ClutterInputDevice + * or %NULL + * + * Since: 1.6 + */ +ClutterInputDevice * +clutter_event_get_source_device (const ClutterEvent *event) +{ + ClutterEventPrivate *real_event; + + if (!is_event_allocated (event)) + return NULL; + + real_event = (ClutterEventPrivate *) event; + + if (real_event->source_device != NULL) + return real_event->source_device; + + return clutter_event_get_device (event); +} + +/** + * clutter_event_set_source_device: + * @event: a #ClutterEvent + * @device: (allow-none): a #ClutterInputDevice + * + * Sets the source #ClutterInputDevice for @event. + * + * The #ClutterEvent must have been created using clutter_event_new(). + * + * Since: 1.8 + */ +void +clutter_event_set_source_device (ClutterEvent *event, + ClutterInputDevice *device) +{ + ClutterEventPrivate *real_event; + + g_return_if_fail (event != NULL); + g_return_if_fail (device == NULL || CLUTTER_IS_INPUT_DEVICE (device)); + + if (!is_event_allocated (event)) + return; + + real_event = (ClutterEventPrivate *) event; + real_event->source_device = device; +} + +/** + * clutter_event_get_axes: + * @event: a #ClutterEvent + * @n_axes: (out): return location for the number of axes returned + * + * Retrieves the array of axes values attached to the event. + * + * Return value: (transfer none): an array of axis values + * + * Since: 1.6 + */ +gdouble * +clutter_event_get_axes (const ClutterEvent *event, + guint *n_axes) +{ + gdouble *retval = NULL; + guint len = 0; + + switch (event->type) + { + case CLUTTER_NOTHING: + case CLUTTER_STAGE_STATE: + case CLUTTER_DESTROY_NOTIFY: + case CLUTTER_CLIENT_MESSAGE: + case CLUTTER_DELETE: + case CLUTTER_ENTER: + case CLUTTER_LEAVE: + case CLUTTER_KEY_PRESS: + case CLUTTER_KEY_RELEASE: + case CLUTTER_EVENT_LAST: + case CLUTTER_PROXIMITY_IN: + case CLUTTER_PROXIMITY_OUT: + break; + + case CLUTTER_SCROLL: + retval = event->scroll.axes; + break; + + case CLUTTER_BUTTON_PRESS: + case CLUTTER_BUTTON_RELEASE: + retval = event->button.axes; + break; + + case CLUTTER_TOUCH_BEGIN: + case CLUTTER_TOUCH_UPDATE: + case CLUTTER_TOUCH_END: + case CLUTTER_TOUCH_CANCEL: + retval = event->touch.axes; + break; + + case CLUTTER_MOTION: + retval = event->motion.axes; + break; + + case CLUTTER_TOUCHPAD_PINCH: + case CLUTTER_TOUCHPAD_SWIPE: + case CLUTTER_PAD_BUTTON_PRESS: + case CLUTTER_PAD_BUTTON_RELEASE: + case CLUTTER_PAD_STRIP: + case CLUTTER_PAD_RING: + break; + } + + if (retval != NULL) + { + ClutterInputDevice *device; + + device = clutter_event_get_device (event); + if (device != NULL) + len = clutter_input_device_get_n_axes (device); + else + retval = NULL; + } + + if (n_axes) + *n_axes = len; + + return retval; +} + +/** + * clutter_event_get_distance: + * @source: a #ClutterEvent + * @target: a #ClutterEvent + * + * Retrieves the distance between two events, a @source and a @target. + * + * Return value: the distance between two #ClutterEvent + * + * Since: 1.12 + */ +float +clutter_event_get_distance (const ClutterEvent *source, + const ClutterEvent *target) +{ + ClutterPoint p0, p1; + + clutter_event_get_position (source, &p0); + clutter_event_get_position (source, &p1); + + return clutter_point_distance (&p0, &p1, NULL, NULL); +} + +/** + * clutter_event_get_angle: + * @source: a #ClutterEvent + * @target: a #ClutterEvent + * + * Retrieves the angle relative from @source to @target. + * + * The direction of the angle is from the position X axis towards + * the positive Y axis. + * + * Return value: the angle between two #ClutterEvent + * + * Since: 1.12 + */ +double +clutter_event_get_angle (const ClutterEvent *source, + const ClutterEvent *target) +{ + ClutterPoint p0, p1; + float x_distance, y_distance; + double angle; + + clutter_event_get_position (source, &p0); + clutter_event_get_position (target, &p1); + + if (clutter_point_equals (&p0, &p1)) + return 0; + + clutter_point_distance (&p0, &p1, &x_distance, &y_distance); + + angle = atan2 (x_distance, y_distance); + + /* invert the angle, and shift it by 90 degrees */ + angle = (2.0 * G_PI) - angle; + angle += G_PI / 2.0; + + /* keep the angle within the [ 0, 360 ] interval */ + angle = fmod (angle, 2.0 * G_PI); + + return angle; +} + +/** + * clutter_event_has_shift_modifier: + * @event: a #ClutterEvent + * + * Checks whether @event has the Shift modifier mask set. + * + * Return value: %TRUE if the event has the Shift modifier mask set + * + * Since: 1.12 + */ +gboolean +clutter_event_has_shift_modifier (const ClutterEvent *event) +{ + return (clutter_event_get_state (event) & CLUTTER_SHIFT_MASK) != FALSE; +} + +/** + * clutter_event_has_control_modifier: + * @event: a #ClutterEvent + * + * Checks whether @event has the Control modifier mask set. + * + * Return value: %TRUE if the event has the Control modifier mask set + * + * Since: 1.12 + */ +gboolean +clutter_event_has_control_modifier (const ClutterEvent *event) +{ + return (clutter_event_get_state (event) & CLUTTER_CONTROL_MASK) != FALSE; +} + +/** + * clutter_event_is_pointer_emulated: + * @event: a #ClutterEvent + * + * Checks whether a pointer @event has been generated by the windowing + * system. The returned value can be used to distinguish between events + * synthesized by the windowing system itself (as opposed by Clutter). + * + * Return value: %TRUE if the event is pointer emulated + * + * Since: 1.12 + */ +gboolean +clutter_event_is_pointer_emulated (const ClutterEvent *event) +{ + g_return_val_if_fail (event != NULL, FALSE); + + if (!is_event_allocated (event)) + return FALSE; + + return ((ClutterEventPrivate *) event)->is_pointer_emulated; +} + +gboolean +_clutter_event_process_filters (ClutterEvent *event) +{ + ClutterMainContext *context = _clutter_context_get_default (); + GList *l, *next; + + /* Event filters are handled in order from least recently added to + * most recently added */ + + for (l = context->event_filters; l; l = next) + { + ClutterEventFilter *event_filter = l->data; + + next = l->next; + + if (event_filter->stage && event_filter->stage != event->any.stage) + continue; + + if (event_filter->func (event, event_filter->user_data) == CLUTTER_EVENT_STOP) + return CLUTTER_EVENT_STOP; + } + + return CLUTTER_EVENT_PROPAGATE; +} + +/** + * clutter_event_add_filter: + * @stage: (allow-none): The #ClutterStage to capture events for + * @func: The callback function which will be passed all events. + * @notify: A #GDestroyNotify + * @user_data: A data pointer to pass to the function. + * + * Adds a function which will be called for all events that Clutter + * processes. The function will be called before any signals are + * emitted for the event and it will take precedence over any grabs. + * + * Return value: an identifier for the event filter, to be used + * with clutter_event_remove_filter(). + * + * Since: 1.18 + */ +guint +clutter_event_add_filter (ClutterStage *stage, + ClutterEventFilterFunc func, + GDestroyNotify notify, + gpointer user_data) +{ + ClutterMainContext *context = _clutter_context_get_default (); + ClutterEventFilter *event_filter = g_slice_new (ClutterEventFilter); + static guint event_filter_id = 0; + + event_filter->stage = stage; + event_filter->id = ++event_filter_id; + event_filter->func = func; + event_filter->notify = notify; + event_filter->user_data = user_data; + + /* The event filters are kept in order from least recently added to + * most recently added so we must add it to the end */ + context->event_filters = g_list_append (context->event_filters, event_filter); + + return event_filter->id; +} + +/** + * clutter_event_remove_filter: + * @id: The ID of the event filter, as returned from clutter_event_add_filter() + * + * Removes an event filter that was previously added with + * clutter_event_add_filter(). + * + * Since: 1.18 + */ +void +clutter_event_remove_filter (guint id) +{ + ClutterMainContext *context = _clutter_context_get_default (); + GList *l; + + for (l = context->event_filters; l; l = l->next) + { + ClutterEventFilter *event_filter = l->data; + + if (event_filter->id == id) + { + if (event_filter->notify) + event_filter->notify (event_filter->user_data); + + context->event_filters = g_list_delete_link (context->event_filters, l); + g_slice_free (ClutterEventFilter, event_filter); + return; + } + } + + g_warning ("No event filter found for id: %d\n", id); +} + +/** + * clutter_event_get_gesture_swipe_finger_count: + * @event: a touchpad swipe event + * + * Returns the number of fingers that is triggering the touchpad gesture. + * + * Returns: the number of fingers swiping. + * + * Since: 1.24 + **/ +guint +clutter_event_get_gesture_swipe_finger_count (const ClutterEvent *event) +{ + g_return_val_if_fail (event != NULL, 0); + g_return_val_if_fail (event->type == CLUTTER_TOUCHPAD_SWIPE, 0); + + return event->touchpad_swipe.n_fingers; +} + +/** + * clutter_event_get_gesture_pinch_angle_delta: + * @event: a touchpad pinch event + * + * Returns the angle delta reported by this specific event. + * + * Returns: The angle delta relative to the previous event. + * + * Since: 1.24 + **/ +gdouble +clutter_event_get_gesture_pinch_angle_delta (const ClutterEvent *event) +{ + g_return_val_if_fail (event != NULL, 0); + g_return_val_if_fail (event->type == CLUTTER_TOUCHPAD_PINCH, 0); + + return event->touchpad_pinch.angle_delta; +} + +/** + * clutter_event_get_gesture_pinch_scale: + * @event: a touchpad pinch event + * + * Returns the current scale as reported by @event, 1.0 being the original + * distance at the time the corresponding event with phase + * %CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN is received. + * is received. + * + * Returns: the current pinch gesture scale + * + * Since: 1.24 + **/ +gdouble +clutter_event_get_gesture_pinch_scale (const ClutterEvent *event) +{ + g_return_val_if_fail (event != NULL, 0); + g_return_val_if_fail (event->type == CLUTTER_TOUCHPAD_PINCH, 0); + + return event->touchpad_pinch.scale; +} + +/** + * clutter_event_get_gesture_phase: + * @event: a touchpad gesture event + * + * Returns the phase of the event, See #ClutterTouchpadGesturePhase. + * + * Returns: the phase of the gesture event. + **/ +ClutterTouchpadGesturePhase +clutter_event_get_gesture_phase (const ClutterEvent *event) +{ + g_return_val_if_fail (event != NULL, 0); + g_return_val_if_fail (event->type == CLUTTER_TOUCHPAD_PINCH || + event->type == CLUTTER_TOUCHPAD_SWIPE, 0); + + if (event->type == CLUTTER_TOUCHPAD_PINCH) + return event->touchpad_pinch.phase; + else if (event->type == CLUTTER_TOUCHPAD_SWIPE) + return event->touchpad_swipe.phase; + + /* Shouldn't ever happen */ + return CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN; +}; + +/** + * clutter_event_get_gesture_motion_delta: + * @event: A clutter touchpad gesture event + * @dx: (out) (allow-none): the displacement relative to the pointer + * position in the X axis, or %NULL + * @dy: (out) (allow-none): the displacement relative to the pointer + * position in the Y axis, or %NULL + * + * Returns the gesture motion deltas relative to the current pointer + * position. + * + * Since: 1.24 + **/ +void +clutter_event_get_gesture_motion_delta (const ClutterEvent *event, + gdouble *dx, + gdouble *dy) +{ + g_return_if_fail (event != NULL); + g_return_if_fail (event->type == CLUTTER_TOUCHPAD_PINCH || + event->type == CLUTTER_TOUCHPAD_SWIPE); + + if (event->type == CLUTTER_TOUCHPAD_PINCH) + { + if (dx) + *dx = event->touchpad_pinch.dx; + if (dy) + *dy = event->touchpad_pinch.dy; + } + else if (event->type == CLUTTER_TOUCHPAD_SWIPE) + { + if (dx) + *dx = event->touchpad_swipe.dx; + if (dy) + *dy = event->touchpad_swipe.dy; + } +} + +/** + * clutter_event_get_scroll_source: + * @event: an scroll event + * + * Returns the #ClutterScrollSource that applies to an scroll event. + * + * Returns: The source of scroll events + * + * Since: 1.26 + **/ +ClutterScrollSource +clutter_event_get_scroll_source (const ClutterEvent *event) +{ + g_return_val_if_fail (event != NULL, CLUTTER_SCROLL_SOURCE_UNKNOWN); + g_return_val_if_fail (event->type == CLUTTER_SCROLL, + CLUTTER_SCROLL_SOURCE_UNKNOWN); + + return event->scroll.scroll_source; +} + +/** + * clutter_event_get_scroll_finish_flags: + * @event: an scroll event + * + * Returns the #ClutterScrollFinishFlags of an scroll event. Those + * can be used to determine whether post-scroll effects like kinetic + * scrolling should be applied. + * + * Returns: The scroll finish flags + * + * Since: 1.26 + **/ +ClutterScrollFinishFlags +clutter_event_get_scroll_finish_flags (const ClutterEvent *event) +{ + g_return_val_if_fail (event != NULL, CLUTTER_SCROLL_SOURCE_UNKNOWN); + g_return_val_if_fail (event->type == CLUTTER_SCROLL, + CLUTTER_SCROLL_SOURCE_UNKNOWN); + + return event->scroll.finish_flags; +} + +guint +clutter_event_get_mode_group (const ClutterEvent *event) +{ + g_return_val_if_fail (event->type == CLUTTER_PAD_BUTTON_PRESS || + event->type == CLUTTER_PAD_BUTTON_RELEASE || + event->type == CLUTTER_PAD_RING || + event->type == CLUTTER_PAD_STRIP, 0); + switch (event->type) + { + case CLUTTER_PAD_BUTTON_PRESS: + case CLUTTER_PAD_BUTTON_RELEASE: + return event->pad_button.group; + case CLUTTER_PAD_RING: + return event->pad_ring.group; + case CLUTTER_PAD_STRIP: + return event->pad_strip.group; + default: + return 0; + } +} diff --git a/clutter/clutter/clutter-event.h b/clutter/clutter/clutter-event.h new file mode 100644 index 0000000..5478f1d --- /dev/null +++ b/clutter/clutter/clutter-event.h @@ -0,0 +1,780 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __CLUTTER_EVENT_H__ +#define __CLUTTER_EVENT_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_EVENT (clutter_event_get_type ()) +#define CLUTTER_TYPE_EVENT_SEQUENCE (clutter_event_sequence_get_type ()) + +/** + * CLUTTER_PRIORITY_EVENTS: + * + * Priority for event handling. + * + * Since: 0.4 + */ +#define CLUTTER_PRIORITY_EVENTS (G_PRIORITY_DEFAULT) + +/** + * CLUTTER_CURRENT_TIME: + * + * Default value for "now". + * + * Since: 0.4 + */ +#define CLUTTER_CURRENT_TIME (0L) + +/** + * CLUTTER_EVENT_PROPAGATE: + * + * Continues the propagation of an event; this macro should be + * used in event-related signals. + * + * Since: 1.10 + */ +#define CLUTTER_EVENT_PROPAGATE (FALSE) + +/** + * CLUTTER_EVENT_STOP: + * + * Stops the propagation of an event; this macro should be used + * in event-related signals. + * + * Since: 1.10 + */ +#define CLUTTER_EVENT_STOP (TRUE) + +/** + * CLUTTER_BUTTON_PRIMARY: + * + * The primary button of a pointer device. + * + * This is typically the left mouse button in a right-handed + * mouse configuration. + * + * Since: 1.10 + */ +#define CLUTTER_BUTTON_PRIMARY (1) + +/** + * CLUTTER_BUTTON_MIDDLE: + * + * The middle button of a pointer device. + * + * Since: 1.10 + */ +#define CLUTTER_BUTTON_MIDDLE (2) + +/** + * CLUTTER_BUTTON_SECONDARY: + * + * The secondary button of a pointer device. + * + * This is typically the right mouse button in a right-handed + * mouse configuration. + * + * Since: 1.10 + */ +#define CLUTTER_BUTTON_SECONDARY (3) + +typedef struct _ClutterAnyEvent ClutterAnyEvent; +typedef struct _ClutterButtonEvent ClutterButtonEvent; +typedef struct _ClutterKeyEvent ClutterKeyEvent; +typedef struct _ClutterMotionEvent ClutterMotionEvent; +typedef struct _ClutterScrollEvent ClutterScrollEvent; +typedef struct _ClutterStageStateEvent ClutterStageStateEvent; +typedef struct _ClutterCrossingEvent ClutterCrossingEvent; +typedef struct _ClutterTouchEvent ClutterTouchEvent; +typedef struct _ClutterTouchpadPinchEvent ClutterTouchpadPinchEvent; +typedef struct _ClutterTouchpadSwipeEvent ClutterTouchpadSwipeEvent; +typedef struct _ClutterProximityEvent ClutterProximityEvent; +typedef struct _ClutterPadButtonEvent ClutterPadButtonEvent; +typedef struct _ClutterPadStripEvent ClutterPadStripEvent; +typedef struct _ClutterPadRingEvent ClutterPadRingEvent; + +/** + * ClutterAnyEvent: + * @type: event type + * @time: event time + * @flags: event flags + * @source: event source actor + * + * Common members for a #ClutterEvent + * + * Since: 0.2 + */ +struct _ClutterAnyEvent +{ + ClutterEventType type; + guint32 time; + ClutterEventFlags flags; + ClutterStage *stage; + ClutterActor *source; +}; + +/** + * ClutterKeyEvent: + * @type: event type + * @time: event time + * @flags: event flags + * @stage: event source stage + * @source: event source actor + * @modifier_state: key modifiers + * @keyval: raw key value + * @hardware_keycode: raw hardware key value + * @unicode_value: Unicode representation + * @device: the device that originated the event. If you want the physical + * device the event originated from, use clutter_event_get_source_device() + * + * Key event + * + * Since: 0.2 + */ +struct _ClutterKeyEvent +{ + ClutterEventType type; + guint32 time; + ClutterEventFlags flags; + ClutterStage *stage; + ClutterActor *source; + + ClutterModifierType modifier_state; + guint keyval; + guint16 hardware_keycode; + gunichar unicode_value; + ClutterInputDevice *device; +}; + +/** + * ClutterButtonEvent: + * @type: event type + * @time: event time + * @flags: event flags + * @stage: event source stage + * @source: event source actor + * @x: event X coordinate, relative to the stage + * @y: event Y coordinate, relative to the stage + * @modifier_state: button modifiers + * @button: event button + * @click_count: number of button presses within the default time + * and radius + * @axes: reserved for future use + * @device: the device that originated the event. If you want the physical + * device the event originated from, use clutter_event_get_source_device() + * + * Button event. + * + * The event coordinates are relative to the stage that received the + * event, and can be transformed into actor-relative coordinates by + * using clutter_actor_transform_stage_point(). + * + * Since: 0.2 + */ +struct _ClutterButtonEvent +{ + ClutterEventType type; + guint32 time; + ClutterEventFlags flags; + ClutterStage *stage; + ClutterActor *source; + + gfloat x; + gfloat y; + ClutterModifierType modifier_state; + guint32 button; + guint click_count; + gdouble *axes; /* Future use */ + ClutterInputDevice *device; +}; + +/** + * ClutterProximityEvent: + * @type: event type + * @time: event time + * @flags: event flags + * @stage: event source stage + * @source: event source actor + * @device: the device that originated the event. If you want the physical + * device the event originated from, use clutter_event_get_source_device() + * + * Event for tool proximity in tablet devices + * + * Since: 1.28 + */ +struct _ClutterProximityEvent +{ + ClutterEventType type; + guint32 time; + ClutterEventFlags flags; + ClutterStage *stage; + ClutterActor *source; + ClutterInputDevice *device; +}; + +/** + * ClutterCrossingEvent: + * @type: event type + * @time: event time + * @flags: event flags + * @stage: event source stage + * @source: event source actor + * @x: event X coordinate + * @y: event Y coordinate + * @related: actor related to the crossing + * @device: the device that originated the event. If you want the physical + * device the event originated from, use clutter_event_get_source_device() + * + * Event for the movement of the pointer across different actors + * + * Since: 0.2 + */ +struct _ClutterCrossingEvent +{ + ClutterEventType type; + guint32 time; + ClutterEventFlags flags; + ClutterStage *stage; + ClutterActor *source; + + gfloat x; + gfloat y; + ClutterInputDevice *device; + ClutterActor *related; +}; + +/** + * ClutterMotionEvent: + * @type: event type + * @time: event time + * @flags: event flags + * @stage: event source stage + * @source: event source actor + * @x: event X coordinate + * @y: event Y coordinate + * @modifier_state: button modifiers + * @axes: reserved for future use + * @device: the device that originated the event. If you want the physical + * device the event originated from, use clutter_event_get_source_device() + * + * Event for the pointer motion + * + * Since: 0.2 + */ +struct _ClutterMotionEvent +{ + ClutterEventType type; + guint32 time; + ClutterEventFlags flags; + ClutterStage *stage; + ClutterActor *source; + + gfloat x; + gfloat y; + ClutterModifierType modifier_state; + gdouble *axes; /* Future use */ + ClutterInputDevice *device; +}; + +/** + * ClutterScrollEvent: + * @type: event type + * @time: event time + * @flags: event flags + * @stage: event source stage + * @source: event source actor + * @x: event X coordinate + * @y: event Y coordinate + * @direction: direction of the scrolling + * @modifier_state: button modifiers + * @axes: reserved for future use + * @device: the device that originated the event. If you want the physical + * device the event originated from, use clutter_event_get_source_device() + * @scroll_source: the source of scroll events. This field is available since 1.26 + * @finish_flags: the axes that were stopped in this event. This field is available since 1.26 + * + * Scroll wheel (or similar device) event + * + * Since: 0.2 + */ +struct _ClutterScrollEvent +{ + ClutterEventType type; + guint32 time; + ClutterEventFlags flags; + ClutterStage *stage; + ClutterActor *source; + + gfloat x; + gfloat y; + ClutterScrollDirection direction; + ClutterModifierType modifier_state; + gdouble *axes; /* future use */ + ClutterInputDevice *device; + ClutterScrollSource scroll_source; + ClutterScrollFinishFlags finish_flags; +}; + +/** + * ClutterStageStateEvent: + * @type: event type + * @time: event time + * @flags: event flags + * @stage: event source stage + * @source: event source actor (unused) + * @changed_mask: bitwise OR of the changed flags + * @new_state: bitwise OR of the current state flags + * + * Event signalling a change in the #ClutterStage state. + * + * Since: 0.2 + */ +struct _ClutterStageStateEvent +{ + ClutterEventType type; + guint32 time; + ClutterEventFlags flags; + ClutterStage *stage; + ClutterActor *source; /* XXX: should probably be the stage itself */ + + ClutterStageState changed_mask; + ClutterStageState new_state; +}; + +/** + * ClutterTouchEvent: + * @type: event type + * @time: event time + * @flags: event flags + * @stage: event source stage + * @source: event source actor (unused) + * @x: the X coordinate of the pointer, relative to the stage + * @y: the Y coordinate of the pointer, relative to the stage + * @sequence: the event sequence that this event belongs to + * @modifier_state: (type ClutterModifierType): a bit-mask representing the state + * of modifier keys (e.g. Control, Shift, and Alt) and the pointer + * buttons. See #ClutterModifierType + * @axes: reserved + * @device: the device that originated the event. If you want the physical + * device the event originated from, use clutter_event_get_source_device() + * + * Used for touch events. + * + * The @type field will be one of %CLUTTER_TOUCH_BEGIN, %CLUTTER_TOUCH_END, + * %CLUTTER_TOUCH_UPDATE, or %CLUTTER_TOUCH_CANCEL. + * + * Touch events are grouped into sequences; each touch sequence will begin + * with a %CLUTTER_TOUCH_BEGIN event, progress with %CLUTTER_TOUCH_UPDATE + * events, and end either with a %CLUTTER_TOUCH_END event or with a + * %CLUTTER_TOUCH_CANCEL event. + * + * With multi-touch capable devices there can be multiple event sequence + * running at the same time. + * + * Since: 1.10 + */ +struct _ClutterTouchEvent +{ + ClutterEventType type; + guint32 time; + ClutterEventFlags flags; + ClutterStage *stage; + ClutterActor *source; + + gfloat x; + gfloat y; + ClutterEventSequence *sequence; + ClutterModifierType modifier_state; + gdouble *axes; /* reserved */ + ClutterInputDevice *device; +}; + +/** + * ClutterTouchpadPinchEvent: + * @type: event type + * @time: event time + * @flags: event flags + * @stage: event source stage + * @source: event source actor (unused) + * @phase: the current phase of the gesture + * @x: the X coordinate of the pointer, relative to the stage + * @y: the Y coordinate of the pointer, relative to the stage + * @dx: movement delta of the pinch focal point in the X axis + * @dy: movement delta of the pinch focal point in the Y axis + * @angle_delta: angle delta in degrees, clockwise rotations are + * represented by positive deltas + * @scale: the current scale + * + * Used for touchpad pinch gesture events. The current state of the + * gesture will be determined by the @phase field. + * + * Each event with phase %CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN + * will report a @scale of 1.0, all later phases in the gesture + * report the current scale relative to the initial 1.0 value + * (eg. 0.5 being half the size, 2.0 twice as big). + * + * Since: 1.24 + */ +struct _ClutterTouchpadPinchEvent +{ + ClutterEventType type; + guint32 time; + ClutterEventFlags flags; + ClutterStage *stage; + ClutterActor *source; + + ClutterTouchpadGesturePhase phase; + gfloat x; + gfloat y; + gfloat dx; + gfloat dy; + gfloat angle_delta; + gfloat scale; +}; + +/** + * ClutterTouchpadSwipeEvent + * @type: event type + * @time: event time + * @flags: event flags + * @stage: event source stage + * @source: event source actor (unused) + * @phase: the current phase of the gesture + * @n_fingers: the number of fingers triggering the swipe + * @x: the X coordinate of the pointer, relative to the stage + * @y: the Y coordinate of the pointer, relative to the stage + * @dx: movement delta of the pinch focal point in the X axis + * @dy: movement delta of the pinch focal point in the Y axis + * + * Used for touchpad swipe gesture events. The current state of the + * gesture will be determined by the @phase field. + * + * Since: 1.24 + */ +struct _ClutterTouchpadSwipeEvent +{ + ClutterEventType type; + guint32 time; + ClutterEventFlags flags; + ClutterStage *stage; + ClutterActor *source; + + ClutterTouchpadGesturePhase phase; + guint n_fingers; + gfloat x; + gfloat y; + gfloat dx; + gfloat dy; +}; + +struct _ClutterPadButtonEvent +{ + ClutterEventType type; + guint32 time; + ClutterEventFlags flags; + ClutterStage *stage; + ClutterActor *source; + + guint32 button; + guint32 group; + ClutterInputDevice *device; +}; + +struct _ClutterPadStripEvent +{ + ClutterEventType type; + guint32 time; + ClutterEventFlags flags; + ClutterStage *stage; + ClutterActor *source; + + ClutterInputDevice *device; + ClutterInputDevicePadSource strip_source; + guint32 strip_number; + guint32 group; + gdouble value; +}; + +struct _ClutterPadRingEvent +{ + ClutterEventType type; + guint32 time; + ClutterEventFlags flags; + ClutterStage *stage; + ClutterActor *source; + + ClutterInputDevice *device; + ClutterInputDevicePadSource ring_source; + guint32 ring_number; + guint32 group; + gdouble angle; +}; + +/** + * ClutterEvent: + * + * Generic event wrapper. + * + * Since: 0.2 + */ +union _ClutterEvent +{ + /*< private >*/ + ClutterEventType type; + + ClutterAnyEvent any; + ClutterButtonEvent button; + ClutterKeyEvent key; + ClutterMotionEvent motion; + ClutterScrollEvent scroll; + ClutterStageStateEvent stage_state; + ClutterCrossingEvent crossing; + ClutterTouchEvent touch; + ClutterTouchpadPinchEvent touchpad_pinch; + ClutterTouchpadSwipeEvent touchpad_swipe; + ClutterProximityEvent proximity; + ClutterPadButtonEvent pad_button; + ClutterPadStripEvent pad_strip; + ClutterPadRingEvent pad_ring; +}; + +/** + * ClutterEventFilterFunc: + * @event: the event that is going to be emitted + * @user_data: the data pointer passed to clutter_event_add_filter() + * + * A function pointer type used by event filters that are added with + * clutter_event_add_filter(). + * + * Return value: %CLUTTER_EVENT_STOP to indicate that the event + * has been handled or %CLUTTER_EVENT_PROPAGATE otherwise. + * Returning %CLUTTER_EVENT_STOP skips any further filter + * functions and prevents the signal emission for the event. + * + * Since: 1.18 + */ +typedef gboolean (* ClutterEventFilterFunc) (const ClutterEvent *event, + gpointer user_data); + +CLUTTER_AVAILABLE_IN_ALL +GType clutter_event_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_20 +GType clutter_event_sequence_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_events_pending (void); +CLUTTER_AVAILABLE_IN_ALL +ClutterEvent * clutter_event_get (void); +CLUTTER_AVAILABLE_IN_ALL +ClutterEvent * clutter_event_peek (void); +CLUTTER_AVAILABLE_IN_ALL +void clutter_event_put (const ClutterEvent *event); + +CLUTTER_AVAILABLE_IN_1_18 +guint clutter_event_add_filter (ClutterStage *stage, + ClutterEventFilterFunc func, + GDestroyNotify notify, + gpointer user_data); +CLUTTER_AVAILABLE_IN_1_18 +void clutter_event_remove_filter (guint id); + +CLUTTER_AVAILABLE_IN_ALL +ClutterEvent * clutter_event_new (ClutterEventType type); +CLUTTER_AVAILABLE_IN_ALL +ClutterEvent * clutter_event_copy (const ClutterEvent *event); +CLUTTER_AVAILABLE_IN_ALL +void clutter_event_free (ClutterEvent *event); + +CLUTTER_AVAILABLE_IN_ALL +ClutterEventType clutter_event_type (const ClutterEvent *event); +CLUTTER_AVAILABLE_IN_1_8 +void clutter_event_set_flags (ClutterEvent *event, + ClutterEventFlags flags); +CLUTTER_AVAILABLE_IN_1_0 +ClutterEventFlags clutter_event_get_flags (const ClutterEvent *event); +CLUTTER_AVAILABLE_IN_1_8 +void clutter_event_set_time (ClutterEvent *event, + guint32 time_); +CLUTTER_AVAILABLE_IN_ALL +guint32 clutter_event_get_time (const ClutterEvent *event); +CLUTTER_AVAILABLE_IN_1_8 +void clutter_event_set_state (ClutterEvent *event, + ClutterModifierType state); +CLUTTER_AVAILABLE_IN_ALL +ClutterModifierType clutter_event_get_state (const ClutterEvent *event); +CLUTTER_AVAILABLE_IN_1_16 +void clutter_event_get_state_full (const ClutterEvent *event, + ClutterModifierType *button_state, + ClutterModifierType *base_state, + ClutterModifierType *latched_state, + ClutterModifierType *locked_state, + ClutterModifierType *effective_state); +CLUTTER_AVAILABLE_IN_1_6 +void clutter_event_set_device (ClutterEvent *event, + ClutterInputDevice *device); +CLUTTER_AVAILABLE_IN_1_6 +ClutterInputDevice * clutter_event_get_device (const ClutterEvent *event); +CLUTTER_AVAILABLE_IN_1_6 +void clutter_event_set_source_device (ClutterEvent *event, + ClutterInputDevice *device); + +CLUTTER_AVAILABLE_IN_1_6 +ClutterInputDevice * clutter_event_get_source_device (const ClutterEvent *event); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_event_set_device_tool (ClutterEvent *event, + ClutterInputDeviceTool *tool); +CLUTTER_AVAILABLE_IN_ALL +ClutterInputDeviceTool *clutter_event_get_device_tool (const ClutterEvent *event); + +CLUTTER_AVAILABLE_IN_1_8 +void clutter_event_set_source (ClutterEvent *event, + ClutterActor *actor); +CLUTTER_AVAILABLE_IN_ALL +ClutterActor * clutter_event_get_source (const ClutterEvent *event); +CLUTTER_AVAILABLE_IN_1_8 +void clutter_event_set_stage (ClutterEvent *event, + ClutterStage *stage); +CLUTTER_AVAILABLE_IN_ALL +ClutterStage * clutter_event_get_stage (const ClutterEvent *event); +CLUTTER_AVAILABLE_IN_ALL +gint clutter_event_get_device_id (const ClutterEvent *event); +CLUTTER_AVAILABLE_IN_1_0 +ClutterInputDeviceType clutter_event_get_device_type (const ClutterEvent *event); +CLUTTER_AVAILABLE_IN_1_8 +void clutter_event_set_coords (ClutterEvent *event, + gfloat x, + gfloat y); +CLUTTER_AVAILABLE_IN_ALL +void clutter_event_get_coords (const ClutterEvent *event, + gfloat *x, + gfloat *y); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_event_get_position (const ClutterEvent *event, + ClutterPoint *position); +CLUTTER_AVAILABLE_IN_1_12 +float clutter_event_get_distance (const ClutterEvent *source, + const ClutterEvent *target); +CLUTTER_AVAILABLE_IN_1_12 +double clutter_event_get_angle (const ClutterEvent *source, + const ClutterEvent *target); +CLUTTER_AVAILABLE_IN_1_6 +gdouble * clutter_event_get_axes (const ClutterEvent *event, + guint *n_axes); +CLUTTER_AVAILABLE_IN_1_12 +gboolean clutter_event_has_shift_modifier (const ClutterEvent *event); +CLUTTER_AVAILABLE_IN_1_12 +gboolean clutter_event_has_control_modifier (const ClutterEvent *event); +CLUTTER_AVAILABLE_IN_1_12 +gboolean clutter_event_is_pointer_emulated (const ClutterEvent *event); +CLUTTER_AVAILABLE_IN_1_8 +void clutter_event_set_key_symbol (ClutterEvent *event, + guint key_sym); +CLUTTER_AVAILABLE_IN_1_0 +guint clutter_event_get_key_symbol (const ClutterEvent *event); +CLUTTER_AVAILABLE_IN_1_8 +void clutter_event_set_key_code (ClutterEvent *event, + guint16 key_code); +CLUTTER_AVAILABLE_IN_1_0 +guint16 clutter_event_get_key_code (const ClutterEvent *event); +CLUTTER_AVAILABLE_IN_1_8 +void clutter_event_set_key_unicode (ClutterEvent *event, + gunichar key_unicode); +CLUTTER_AVAILABLE_IN_1_0 +gunichar clutter_event_get_key_unicode (const ClutterEvent *event); +CLUTTER_AVAILABLE_IN_1_8 +void clutter_event_set_button (ClutterEvent *event, + guint32 button); +CLUTTER_AVAILABLE_IN_1_0 +guint32 clutter_event_get_button (const ClutterEvent *event); +CLUTTER_AVAILABLE_IN_1_0 +guint clutter_event_get_click_count (const ClutterEvent *event); +CLUTTER_AVAILABLE_IN_1_8 +void clutter_event_set_related (ClutterEvent *event, + ClutterActor *actor); +CLUTTER_AVAILABLE_IN_1_0 +ClutterActor * clutter_event_get_related (const ClutterEvent *event); +CLUTTER_AVAILABLE_IN_1_8 +void clutter_event_set_scroll_direction (ClutterEvent *event, + ClutterScrollDirection direction); +CLUTTER_AVAILABLE_IN_1_0 +ClutterScrollDirection clutter_event_get_scroll_direction (const ClutterEvent *event); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_event_set_scroll_delta (ClutterEvent *event, + gdouble dx, + gdouble dy); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_event_get_scroll_delta (const ClutterEvent *event, + gdouble *dx, + gdouble *dy); + +CLUTTER_AVAILABLE_IN_1_10 +ClutterEventSequence * clutter_event_get_event_sequence (const ClutterEvent *event); + +CLUTTER_AVAILABLE_IN_ALL +guint32 clutter_keysym_to_unicode (guint keyval); +CLUTTER_AVAILABLE_IN_1_10 +guint clutter_unicode_to_keysym (guint32 wc); + +CLUTTER_AVAILABLE_IN_1_0 +guint32 clutter_get_current_event_time (void); +CLUTTER_AVAILABLE_IN_1_2 +const ClutterEvent * clutter_get_current_event (void); + +CLUTTER_AVAILABLE_IN_1_24 +guint clutter_event_get_gesture_swipe_finger_count (const ClutterEvent *event); + +CLUTTER_AVAILABLE_IN_1_24 +gdouble clutter_event_get_gesture_pinch_angle_delta (const ClutterEvent *event); + +CLUTTER_AVAILABLE_IN_1_24 +gdouble clutter_event_get_gesture_pinch_scale (const ClutterEvent *event); + +CLUTTER_AVAILABLE_IN_1_24 +ClutterTouchpadGesturePhase clutter_event_get_gesture_phase (const ClutterEvent *event); + +CLUTTER_AVAILABLE_IN_1_24 +void clutter_event_get_gesture_motion_delta (const ClutterEvent *event, + gdouble *dx, + gdouble *dy); + +ClutterScrollSource clutter_event_get_scroll_source (const ClutterEvent *event); +ClutterScrollFinishFlags clutter_event_get_scroll_finish_flags (const ClutterEvent *event); + +CLUTTER_AVAILABLE_IN_ALL +guint clutter_event_get_mode_group (const ClutterEvent *event); + + +G_END_DECLS + +#endif /* __CLUTTER_EVENT_H__ */ diff --git a/clutter/clutter/clutter-feature.c b/clutter/clutter/clutter-feature.c new file mode 100644 index 0000000..a228064 --- /dev/null +++ b/clutter/clutter/clutter-feature.c @@ -0,0 +1,163 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +/** + * SECTION:clutter-feature + * @short_description: Run-time detection of Clutter features + * + * Parts of Clutter depend on the underlying platform, including the + * capabilities of the backend used and the OpenGL features exposed through the + * Clutter and COGL API. + * + * It is possible to ask whether Clutter has support for specific features at + * run-time. + * + * See also cogl_get_features() and #CoglFeatureFlags + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include +#include +#include + +#include "clutter-backend-private.h" +#include "clutter-feature.h" +#include "clutter-main.h" +#include "clutter-private.h" +#include "clutter-debug.h" + +#include "cogl/cogl.h" + +typedef struct ClutterFeatures +{ + ClutterFeatureFlags flags; + guint features_set : 1; +} ClutterFeatures; + +static ClutterFeatures* __features = NULL; + +static ClutterFeatureFlags +clutter_features_from_cogl (guint cogl_flags) +{ + ClutterFeatureFlags clutter_flags = 0; + + if (cogl_flags & COGL_FEATURE_TEXTURE_NPOT) + clutter_flags |= CLUTTER_FEATURE_TEXTURE_NPOT; + + if (cogl_flags & COGL_FEATURE_TEXTURE_YUV) + clutter_flags |= CLUTTER_FEATURE_TEXTURE_YUV; + + if (cogl_flags & COGL_FEATURE_TEXTURE_READ_PIXELS) + clutter_flags |= CLUTTER_FEATURE_TEXTURE_READ_PIXELS; + + if (cogl_flags & COGL_FEATURE_SHADERS_GLSL) + clutter_flags |= CLUTTER_FEATURE_SHADERS_GLSL; + + if (cogl_flags & COGL_FEATURE_OFFSCREEN) + clutter_flags |= CLUTTER_FEATURE_OFFSCREEN; + + return clutter_flags; +} + +gboolean +_clutter_feature_init (GError **error) +{ + ClutterMainContext *context; + + CLUTTER_NOTE (MISC, "checking features"); + + if (!__features) + { + CLUTTER_NOTE (MISC, "allocating features data"); + __features = g_new0 (ClutterFeatures, 1); + __features->features_set = FALSE; /* don't rely on zero-ing */ + } + + if (__features->features_set) + return TRUE; + + context = _clutter_context_get_default (); + + /* makes sure we have a GL context; if we have, this is a no-op */ + if (!_clutter_backend_create_context (context->backend, error)) + return FALSE; + + __features->flags = (clutter_features_from_cogl (cogl_get_features ()) + | _clutter_backend_get_features (context->backend)); + + __features->features_set = TRUE; + + CLUTTER_NOTE (MISC, "features checked"); + + return TRUE; +} + +/** + * clutter_feature_available: + * @feature: a #ClutterFeatureFlags + * + * Checks whether @feature is available. @feature can be a logical + * OR of #ClutterFeatureFlags. + * + * Return value: %TRUE if a feature is available + * + * Since: 0.2 + */ +gboolean +clutter_feature_available (ClutterFeatureFlags feature) +{ + if (G_UNLIKELY (!__features)) + { + g_critical ("Unable to check features. Have you initialized Clutter?"); + return FALSE; + } + + return (__features->flags & feature); +} + +/** + * clutter_feature_get_all: + * + * Returns all the supported features. + * + * Return value: a logical OR of all the supported features. + * + * Since: 0.2 + */ +ClutterFeatureFlags +clutter_feature_get_all (void) +{ + if (G_UNLIKELY (!__features)) + { + g_critical ("Unable to check features. Have you initialized Clutter?"); + return FALSE; + } + + return __features->flags; +} + diff --git a/clutter/clutter/clutter-feature.h b/clutter/clutter/clutter-feature.h new file mode 100644 index 0000000..1427e22 --- /dev/null +++ b/clutter/clutter/clutter-feature.h @@ -0,0 +1,42 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __CLUTTER_FEATURE_H__ +#define __CLUTTER_FEATURE_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_feature_available (ClutterFeatureFlags feature); +CLUTTER_AVAILABLE_IN_ALL +ClutterFeatureFlags clutter_feature_get_all (void); + +G_END_DECLS + +#endif /* __CLUTTER_FEATURE_H__ */ diff --git a/clutter/clutter/clutter-fixed-layout.c b/clutter/clutter/clutter-fixed-layout.c new file mode 100644 index 0000000..7034af7 --- /dev/null +++ b/clutter/clutter/clutter-fixed-layout.c @@ -0,0 +1,180 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * 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 . + * + * Author: + * Emmanuele Bassi + * + * Based on the fixed layout code inside clutter-group.c + */ + +/** + * SECTION:clutter-fixed-layout + * @short_description: A fixed layout manager + * + * #ClutterFixedLayout is a layout manager implementing the same + * layout policies as #ClutterGroup. + * + * #ClutterFixedLayout is available since Clutter 1.2 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-debug.h" +#include "clutter-fixed-layout.h" +#include "clutter-private.h" + +G_DEFINE_TYPE (ClutterFixedLayout, + clutter_fixed_layout, + CLUTTER_TYPE_LAYOUT_MANAGER); + +static void +clutter_fixed_layout_get_preferred_width (ClutterLayoutManager *manager, + ClutterContainer *container, + gfloat for_height, + gfloat *min_width_p, + gfloat *nat_width_p) +{ + ClutterActor *actor, *child; + gdouble min_right; + gdouble natural_right; + + min_right = 0; + natural_right = 0; + + actor = CLUTTER_ACTOR (container); + + for (child = clutter_actor_get_first_child (actor); + child != NULL; + child = clutter_actor_get_next_sibling (child)) + { + gfloat child_x, child_min, child_natural; + + child_x = clutter_actor_get_x (child); + + clutter_actor_get_preferred_size (child, + &child_min, NULL, + &child_natural, NULL); + + if (child_x + child_min > min_right) + min_right = child_x + child_min; + + if (child_x + child_natural > natural_right) + natural_right = child_x + child_natural; + } + + if (min_width_p) + *min_width_p = min_right; + + if (nat_width_p) + *nat_width_p = natural_right; +} + +static void +clutter_fixed_layout_get_preferred_height (ClutterLayoutManager *manager, + ClutterContainer *container, + gfloat for_width, + gfloat *min_height_p, + gfloat *nat_height_p) +{ + ClutterActor *actor, *child; + gdouble min_bottom; + gdouble natural_bottom; + + min_bottom = 0; + natural_bottom = 0; + + actor = CLUTTER_ACTOR (container); + + for (child = clutter_actor_get_first_child (actor); + child != NULL; + child = clutter_actor_get_next_sibling (child)) + { + gfloat child_y, child_min, child_natural; + + child_y = clutter_actor_get_y (child); + + clutter_actor_get_preferred_size (child, + NULL, &child_min, + NULL, &child_natural); + + if (child_y + child_min > min_bottom) + min_bottom = child_y + child_min; + + if (child_y + child_natural > natural_bottom) + natural_bottom = child_y + child_natural; + } + + if (min_height_p) + *min_height_p = min_bottom; + + if (nat_height_p) + *nat_height_p = natural_bottom; +} + +static void +clutter_fixed_layout_allocate (ClutterLayoutManager *manager, + ClutterContainer *container, + const ClutterActorBox *allocation, + ClutterAllocationFlags flags) +{ + ClutterActor *child; + + for (child = clutter_actor_get_first_child (CLUTTER_ACTOR (container)); + child != NULL; + child = clutter_actor_get_next_sibling (child)) + { + clutter_actor_allocate_preferred_size (child, flags); + } +} + +static void +clutter_fixed_layout_class_init (ClutterFixedLayoutClass *klass) +{ + ClutterLayoutManagerClass *manager_class = + CLUTTER_LAYOUT_MANAGER_CLASS (klass); + + manager_class->get_preferred_width = + clutter_fixed_layout_get_preferred_width; + manager_class->get_preferred_height = + clutter_fixed_layout_get_preferred_height; + manager_class->allocate = clutter_fixed_layout_allocate; +} + +static void +clutter_fixed_layout_init (ClutterFixedLayout *self) +{ +} + +/** + * clutter_fixed_layout_new: + * + * Creates a new #ClutterFixedLayout + * + * Return value: the newly created #ClutterFixedLayout + * + * Since: 1.2 + */ +ClutterLayoutManager * +clutter_fixed_layout_new (void) +{ + return g_object_new (CLUTTER_TYPE_FIXED_LAYOUT, NULL); +} diff --git a/clutter/clutter/clutter-fixed-layout.h b/clutter/clutter/clutter-fixed-layout.h new file mode 100644 index 0000000..01a2fd6 --- /dev/null +++ b/clutter/clutter/clutter-fixed-layout.h @@ -0,0 +1,82 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * 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 . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_FIXED_LAYOUT_H__ +#define __CLUTTER_FIXED_LAYOUT_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_FIXED_LAYOUT (clutter_fixed_layout_get_type ()) +#define CLUTTER_FIXED_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_FIXED_LAYOUT, ClutterFixedLayout)) +#define CLUTTER_IS_FIXED_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_FIXED_LAYOUT)) +#define CLUTTER_FIXED_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_FIXED_LAYOUT, ClutterFixedLayoutClass)) +#define CLUTTER_IS_FIXED_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_FIXED_LAYOUT)) +#define CLUTTER_FIXED_LAYOUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_FIXED_LAYOUT, ClutterFixedLayoutClass)) + +typedef struct _ClutterFixedLayout ClutterFixedLayout; +typedef struct _ClutterFixedLayoutClass ClutterFixedLayoutClass; + +/** + * ClutterFixedLayout: + * + * The #ClutterFixedLayout structure contains only private data and + * it should be accessed using the provided API + * + * Since: 1.2 + */ +struct _ClutterFixedLayout +{ + /*< private >*/ + ClutterLayoutManager parent_instance; +}; + +/** + * ClutterFixedLayoutClass: + * + * The #ClutterFixedLayoutClass structure contains only private data + * and it should be accessed using the provided API + * + * Since: 1.2 + */ +struct _ClutterFixedLayoutClass +{ + /*< private >*/ + ClutterLayoutManagerClass parent_class; +}; + +CLUTTER_AVAILABLE_IN_1_2 +GType clutter_fixed_layout_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_2 +ClutterLayoutManager *clutter_fixed_layout_new (void); + +G_END_DECLS + +#endif /* __CLUTTER_FIXED_LAYOUT_H__ */ diff --git a/clutter/clutter/clutter-flatten-effect.c b/clutter/clutter/clutter-flatten-effect.c new file mode 100644 index 0000000..d61930a --- /dev/null +++ b/clutter/clutter/clutter-flatten-effect.c @@ -0,0 +1,56 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2011 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: + * Neil Roberts + */ + +/* This is an internal-only effect used to implement the + 'offscreen-redirect' property of ClutterActor. It doesn't actually + need to do anything on top of the ClutterOffscreenEffect class so + it only exists because that class is abstract */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-flatten-effect.h" +#include "clutter-private.h" +#include "clutter-actor-private.h" + +G_DEFINE_TYPE (ClutterFlattenEffect, + _clutter_flatten_effect, + CLUTTER_TYPE_OFFSCREEN_EFFECT); + +static void +_clutter_flatten_effect_class_init (ClutterFlattenEffectClass *klass) +{ +} + +static void +_clutter_flatten_effect_init (ClutterFlattenEffect *self) +{ +} + +ClutterEffect * +_clutter_flatten_effect_new (void) +{ + return g_object_new (CLUTTER_TYPE_FLATTEN_EFFECT, NULL); +} diff --git a/clutter/clutter/clutter-flatten-effect.h b/clutter/clutter/clutter-flatten-effect.h new file mode 100644 index 0000000..03b2df6 --- /dev/null +++ b/clutter/clutter/clutter-flatten-effect.h @@ -0,0 +1,73 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2011 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: + * Neil Roberts + */ + +#ifndef __CLUTTER_FLATTEN_EFFECT_H__ +#define __CLUTTER_FLATTEN_EFFECT_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_FLATTEN_EFFECT \ + (_clutter_flatten_effect_get_type()) +#define CLUTTER_FLATTEN_EFFECT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + CLUTTER_TYPE_FLATTEN_EFFECT, \ + ClutterFlattenEffect)) +#define CLUTTER_FLATTEN_EFFECT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + CLUTTER_TYPE_FLATTEN_EFFECT, \ + ClutterFlattenEffectClass)) +#define CLUTTER_IS_FLATTEN_EFFECT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + CLUTTER_TYPE_FLATTEN_EFFECT)) +#define CLUTTER_IS_FLATTEN_EFFECT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + CLUTTER_TYPE_FLATTEN_EFFECT)) +#define CLUTTER_FLATTEN_EFFECT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + CLUTTER_FLATTEN_EFFECT, \ + ClutterFlattenEffectClass)) + +typedef struct _ClutterFlattenEffect ClutterFlattenEffect; +typedef struct _ClutterFlattenEffectClass ClutterFlattenEffectClass; +typedef struct _ClutterFlattenEffectPrivate ClutterFlattenEffectPrivate; + +struct _ClutterFlattenEffectClass +{ + ClutterOffscreenEffectClass parent_class; +}; + +struct _ClutterFlattenEffect +{ + ClutterOffscreenEffect parent; +}; + +GType _clutter_flatten_effect_get_type (void) G_GNUC_CONST; + +ClutterEffect *_clutter_flatten_effect_new (void); + +G_END_DECLS + +#endif /* __CLUTTER_FLATTEN_EFFECT_H__ */ diff --git a/clutter/clutter/clutter-flow-layout.c b/clutter/clutter/clutter-flow-layout.c new file mode 100644 index 0000000..13df882 --- /dev/null +++ b/clutter/clutter/clutter-flow-layout.c @@ -0,0 +1,1537 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * 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 . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-flow-layout + * @short_description: A reflowing layout manager + * + * #ClutterFlowLayout is a layout manager which implements the following + * policy: + * + * - the preferred natural size depends on the value + * of the #ClutterFlowLayout:orientation property; the layout will try + * to maintain all its children on a single row or + * column; + * - if either the width or the height allocated are + * smaller than the preferred ones, the layout will wrap; in this case, + * the preferred height or width, respectively, will take into account + * the amount of columns and rows; + * - each line (either column or row) in reflowing will + * have the size of the biggest cell on that line; if the + * #ClutterFlowLayout:homogeneous property is set to %FALSE the actor + * will be allocated within that area, and if set to %TRUE instead the + * actor will be given exactly that area; + * - the size of the columns or rows can be controlled + * for both minimum and maximum; the spacing can also be controlled + * in both columns and rows. + * + * The [flow-layout example](https://git.gnome.org/browse/clutter/tree/examples/flow-layout.c?h=clutter-1.18) + * shows how to use the #ClutterFlowLayout. + * + * #ClutterFlowLayout is available since Clutter 1.2 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include "deprecated/clutter-container.h" + +#include "clutter-actor.h" +#include "clutter-animatable.h" +#include "clutter-child-meta.h" +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-flow-layout.h" +#include "clutter-layout-meta.h" +#include "clutter-private.h" + +struct _ClutterFlowLayoutPrivate +{ + ClutterContainer *container; + + ClutterFlowOrientation orientation; + + gfloat col_spacing; + gfloat row_spacing; + + gfloat min_col_width; + gfloat max_col_width; + gfloat col_width; + + gfloat min_row_height; + gfloat max_row_height; + gfloat row_height; + + /* per-line size */ + GArray *line_min; + GArray *line_natural; + gfloat req_width; + gfloat req_height; + + guint line_count; + + guint is_homogeneous : 1; + guint snap_to_grid : 1; +}; + +enum +{ + PROP_0, + + PROP_ORIENTATION, + + PROP_HOMOGENEOUS, + + PROP_COLUMN_SPACING, + PROP_ROW_SPACING, + + PROP_MIN_COLUMN_WIDTH, + PROP_MAX_COLUMN_WIDTH, + PROP_MIN_ROW_HEGHT, + PROP_MAX_ROW_HEIGHT, + + PROP_SNAP_TO_GRID, + + N_PROPERTIES +}; + +static GParamSpec *flow_properties[N_PROPERTIES] = { NULL, }; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterFlowLayout, + clutter_flow_layout, + CLUTTER_TYPE_LAYOUT_MANAGER) + +static gint +get_columns (ClutterFlowLayout *self, + gfloat for_width) +{ + ClutterFlowLayoutPrivate *priv = self->priv; + gint n_columns; + + if (for_width < 0) + return 1; + + if (priv->col_width == 0) + return 1; + + n_columns = (gint) (for_width + priv->col_spacing) + / (priv->col_width + priv->col_spacing); + + if (n_columns == 0) + return 1; + + return n_columns; +} + +static gint +get_rows (ClutterFlowLayout *self, + gfloat for_height) +{ + ClutterFlowLayoutPrivate *priv = self->priv; + gint n_rows; + + if (for_height < 0) + return 1; + + if (priv->row_height == 0) + return 1; + + n_rows = (gint) (for_height + priv->row_spacing) + / (priv->row_height + priv->row_spacing); + + if (n_rows == 0) + return 1; + + return n_rows; +} + +static gint +compute_lines (ClutterFlowLayout *self, + gfloat avail_width, + gfloat avail_height) +{ + ClutterFlowLayoutPrivate *priv = self->priv; + + if (priv->orientation == CLUTTER_FLOW_HORIZONTAL) + return get_columns (self, avail_width); + else + return get_rows (self, avail_height); +} + +static void +clutter_flow_layout_get_preferred_width (ClutterLayoutManager *manager, + ClutterContainer *container, + gfloat for_height, + gfloat *min_width_p, + gfloat *nat_width_p) +{ + ClutterFlowLayoutPrivate *priv = CLUTTER_FLOW_LAYOUT (manager)->priv; + gint n_rows, line_item_count, line_count; + gfloat total_min_width, total_natural_width; + gfloat line_min_width, line_natural_width; + gfloat max_min_width, max_natural_width; + ClutterActor *actor, *child; + ClutterActorIter iter; + gfloat item_y; + + n_rows = get_rows (CLUTTER_FLOW_LAYOUT (manager), for_height); + + total_min_width = 0; + total_natural_width = 0; + + line_min_width = 0; + line_natural_width = 0; + + line_item_count = 0; + line_count = 0; + + item_y = 0; + + actor = CLUTTER_ACTOR (container); + + /* clear the line width arrays */ + if (priv->line_min != NULL) + g_array_free (priv->line_min, TRUE); + + if (priv->line_natural != NULL) + g_array_free (priv->line_natural, TRUE); + + priv->line_min = g_array_sized_new (FALSE, FALSE, + sizeof (gfloat), + 16); + priv->line_natural = g_array_sized_new (FALSE, FALSE, + sizeof (gfloat), + 16); + + if (clutter_actor_get_n_children (actor) != 0) + line_count = 1; + + max_min_width = max_natural_width = 0; + + clutter_actor_iter_init (&iter, actor); + while (clutter_actor_iter_next (&iter, &child)) + { + gfloat child_min, child_natural; + gfloat new_y, item_height; + + if (!clutter_actor_is_visible (child)) + continue; + + if (priv->orientation == CLUTTER_FLOW_VERTICAL && for_height > 0) + { + clutter_actor_get_preferred_height (child, -1, + &child_min, + &child_natural); + + if ((priv->snap_to_grid && line_item_count == n_rows) || + (!priv->snap_to_grid && item_y + child_natural > for_height)) + { + total_min_width += line_min_width; + total_natural_width += line_natural_width; + + g_array_append_val (priv->line_min, + line_min_width); + g_array_append_val (priv->line_natural, + line_natural_width); + + line_min_width = line_natural_width = 0; + + line_item_count = 0; + line_count += 1; + item_y = 0; + } + + if (priv->snap_to_grid) + { + new_y = ((line_item_count + 1) * (for_height + priv->row_spacing)) + / n_rows; + item_height = new_y - item_y - priv->row_spacing; + } + else + { + new_y = item_y + child_natural + priv->row_spacing; + item_height = child_natural; + } + + clutter_actor_get_preferred_width (child, item_height, + &child_min, + &child_natural); + + line_min_width = MAX (line_min_width, child_min); + line_natural_width = MAX (line_natural_width, child_natural); + + item_y = new_y; + line_item_count += 1; + + max_min_width = MAX (max_min_width, line_min_width); + max_natural_width = MAX (max_natural_width, line_natural_width); + } + else + { + clutter_actor_get_preferred_width (child, for_height, + &child_min, + &child_natural); + + max_min_width = MAX (max_min_width, child_min); + max_natural_width = MAX (max_natural_width, child_natural); + + total_min_width += max_min_width; + total_natural_width += max_natural_width; + line_count += 1; + } + } + + priv->col_width = max_natural_width; + + if (priv->max_col_width > 0 && priv->col_width > priv->max_col_width) + priv->col_width = MAX (priv->max_col_width, max_min_width); + + if (priv->col_width < priv->min_col_width) + priv->col_width = priv->min_col_width; + + if (priv->orientation == CLUTTER_FLOW_VERTICAL && for_height > 0) + { + /* if we have a non-full row we need to add it */ + if (line_item_count > 0) + { + total_min_width += line_min_width; + total_natural_width += line_natural_width; + + g_array_append_val (priv->line_min, + line_min_width); + g_array_append_val (priv->line_natural, + line_natural_width); + } + + priv->line_count = line_count; + + if (priv->line_count > 0) + { + gfloat total_spacing; + + total_spacing = priv->col_spacing * (priv->line_count - 1); + + total_min_width += total_spacing; + total_natural_width += total_spacing; + } + } + else + { + g_array_append_val (priv->line_min, line_min_width); + g_array_append_val (priv->line_natural, line_natural_width); + + priv->line_count = line_count; + + if (priv->line_count > 0) + { + gfloat total_spacing; + + total_spacing = priv->col_spacing * (priv->line_count - 1); + + total_min_width += total_spacing; + total_natural_width += total_spacing; + } + } + + CLUTTER_NOTE (LAYOUT, + "Flow[w]: %d lines (%d per line): w [ %.2f, %.2f ] for h %.2f", + n_rows, priv->line_count, + total_min_width, + total_natural_width, + for_height); + + priv->req_height = for_height; + + if (min_width_p) + *min_width_p = max_min_width; + + if (nat_width_p) + *nat_width_p = total_natural_width; +} + +static void +clutter_flow_layout_get_preferred_height (ClutterLayoutManager *manager, + ClutterContainer *container, + gfloat for_width, + gfloat *min_height_p, + gfloat *nat_height_p) +{ + ClutterFlowLayoutPrivate *priv = CLUTTER_FLOW_LAYOUT (manager)->priv; + gint n_columns, line_item_count, line_count; + gfloat total_min_height, total_natural_height; + gfloat line_min_height, line_natural_height; + gfloat max_min_height, max_natural_height; + ClutterActor *actor, *child; + ClutterActorIter iter; + gfloat item_x; + + n_columns = get_columns (CLUTTER_FLOW_LAYOUT (manager), for_width); + + total_min_height = 0; + total_natural_height = 0; + + line_min_height = 0; + line_natural_height = 0; + + line_item_count = 0; + line_count = 0; + + item_x = 0; + + actor = CLUTTER_ACTOR (container); + + /* clear the line height arrays */ + if (priv->line_min != NULL) + g_array_free (priv->line_min, TRUE); + + if (priv->line_natural != NULL) + g_array_free (priv->line_natural, TRUE); + + priv->line_min = g_array_sized_new (FALSE, FALSE, + sizeof (gfloat), + 16); + priv->line_natural = g_array_sized_new (FALSE, FALSE, + sizeof (gfloat), + 16); + + if (clutter_actor_get_n_children (actor) != 0) + line_count = 1; + + max_min_height = max_natural_height = 0; + + clutter_actor_iter_init (&iter, actor); + while (clutter_actor_iter_next (&iter, &child)) + { + gfloat child_min, child_natural; + gfloat new_x, item_width; + + if (!clutter_actor_is_visible (child)) + continue; + + if (priv->orientation == CLUTTER_FLOW_HORIZONTAL && for_width > 0) + { + clutter_actor_get_preferred_width (child, -1, + &child_min, + &child_natural); + + if ((priv->snap_to_grid && line_item_count == n_columns) || + (!priv->snap_to_grid && item_x + child_natural > for_width)) + { + total_min_height += line_min_height; + total_natural_height += line_natural_height; + + g_array_append_val (priv->line_min, + line_min_height); + g_array_append_val (priv->line_natural, + line_natural_height); + + line_min_height = line_natural_height = 0; + + line_item_count = 0; + line_count += 1; + item_x = 0; + } + + if (priv->snap_to_grid) + { + new_x = ((line_item_count + 1) * (for_width + priv->col_spacing)) + / n_columns; + item_width = new_x - item_x - priv->col_spacing; + } + else + { + new_x = item_x + child_natural + priv->col_spacing; + item_width = child_natural; + } + + clutter_actor_get_preferred_height (child, item_width, + &child_min, + &child_natural); + + line_min_height = MAX (line_min_height, child_min); + line_natural_height = MAX (line_natural_height, child_natural); + + item_x = new_x; + line_item_count += 1; + + max_min_height = MAX (max_min_height, line_min_height); + max_natural_height = MAX (max_natural_height, line_natural_height); + } + else + { + clutter_actor_get_preferred_height (child, for_width, + &child_min, + &child_natural); + + max_min_height = MAX (max_min_height, child_min); + max_natural_height = MAX (max_natural_height, child_natural); + + total_min_height += max_min_height; + total_natural_height += max_natural_height; + + line_count += 1; + } + } + + priv->row_height = max_natural_height; + + if (priv->max_row_height > 0 && priv->row_height > priv->max_row_height) + priv->row_height = MAX (priv->max_row_height, max_min_height); + + if (priv->row_height < priv->min_row_height) + priv->row_height = priv->min_row_height; + + if (priv->orientation == CLUTTER_FLOW_HORIZONTAL && for_width > 0) + { + /* if we have a non-full row we need to add it */ + if (line_item_count > 0) + { + total_min_height += line_min_height; + total_natural_height += line_natural_height; + + g_array_append_val (priv->line_min, + line_min_height); + g_array_append_val (priv->line_natural, + line_natural_height); + } + + priv->line_count = line_count; + if (priv->line_count > 0) + { + gfloat total_spacing; + + total_spacing = priv->row_spacing * (priv->line_count - 1); + + total_min_height += total_spacing; + total_natural_height += total_spacing; + } + } + else + { + g_array_append_val (priv->line_min, line_min_height); + g_array_append_val (priv->line_natural, line_natural_height); + + priv->line_count = line_count; + + if (priv->line_count > 0) + { + gfloat total_spacing; + + total_spacing = priv->col_spacing * priv->line_count; + + total_min_height += total_spacing; + total_natural_height += total_spacing; + } + } + + CLUTTER_NOTE (LAYOUT, + "Flow[h]: %d lines (%d per line): w [ %.2f, %.2f ] for h %.2f", + n_columns, priv->line_count, + total_min_height, + total_natural_height, + for_width); + + priv->req_width = for_width; + + if (min_height_p) + *min_height_p = max_min_height; + + if (nat_height_p) + *nat_height_p = total_natural_height; +} + +static void +clutter_flow_layout_allocate (ClutterLayoutManager *manager, + ClutterContainer *container, + const ClutterActorBox *allocation, + ClutterAllocationFlags flags) +{ + ClutterFlowLayoutPrivate *priv = CLUTTER_FLOW_LAYOUT (manager)->priv; + ClutterActor *actor, *child; + ClutterActorIter iter; + gfloat x_off, y_off; + gfloat avail_width, avail_height; + gfloat item_x, item_y; + gint line_item_count; + gint items_per_line; + gint line_index; + + actor = CLUTTER_ACTOR (container); + if (clutter_actor_get_n_children (actor) == 0) + return; + + clutter_actor_box_get_origin (allocation, &x_off, &y_off); + clutter_actor_box_get_size (allocation, &avail_width, &avail_height); + + /* blow the cached preferred size and re-compute with the given + * available size in case the FlowLayout wasn't given the exact + * size it requested + */ + if ((priv->req_width >= 0 && avail_width != priv->req_width) || + (priv->req_height >= 0 && avail_height != priv->req_height)) + { + clutter_flow_layout_get_preferred_width (manager, container, + avail_height, + NULL, NULL); + clutter_flow_layout_get_preferred_height (manager, container, + avail_width, + NULL, NULL); + } + + items_per_line = compute_lines (CLUTTER_FLOW_LAYOUT (manager), + avail_width, avail_height); + + item_x = x_off; + item_y = y_off; + + line_item_count = 0; + line_index = 0; + + clutter_actor_iter_init (&iter, actor); + while (clutter_actor_iter_next (&iter, &child)) + { + ClutterActorBox child_alloc; + gfloat item_width, item_height; + gfloat new_x, new_y; + gfloat child_min, child_natural; + + if (!clutter_actor_is_visible (child)) + continue; + + new_x = new_y = 0; + + if (!priv->snap_to_grid) + clutter_actor_get_preferred_size (child, + NULL, NULL, + &item_width, + &item_height); + + if (priv->orientation == CLUTTER_FLOW_HORIZONTAL) + { + if ((priv->snap_to_grid && + line_item_count == items_per_line && line_item_count > 0) || + (!priv->snap_to_grid && item_x + item_width > avail_width)) + { + item_y += g_array_index (priv->line_natural, + gfloat, + line_index); + + if (line_index >= 0) + item_y += priv->row_spacing; + + line_item_count = 0; + line_index += 1; + + item_x = x_off; + } + + if (priv->snap_to_grid) + { + new_x = x_off + ((line_item_count + 1) * (avail_width + priv->col_spacing)) + / items_per_line; + item_width = new_x - item_x - priv->col_spacing; + } + else + { + new_x = item_x + item_width + priv->col_spacing; + } + + item_height = g_array_index (priv->line_natural, + gfloat, + line_index); + + } + else + { + if ((priv->snap_to_grid && + line_item_count == items_per_line && line_item_count > 0) || + (!priv->snap_to_grid && item_y + item_height > avail_height)) + { + item_x += g_array_index (priv->line_natural, + gfloat, + line_index); + + if (line_index >= 0) + item_x += priv->col_spacing; + + line_item_count = 0; + line_index += 1; + + item_y = y_off; + } + + if (priv->snap_to_grid) + { + new_y = y_off + ((line_item_count + 1) * (avail_height + priv->row_spacing)) + / items_per_line; + item_height = new_y - item_y - priv->row_spacing; + } + else + { + new_y = item_y + item_height + priv->row_spacing; + } + + item_width = g_array_index (priv->line_natural, + gfloat, + line_index); + } + + if (!priv->is_homogeneous && + !clutter_actor_needs_expand (child, + CLUTTER_ORIENTATION_HORIZONTAL)) + { + clutter_actor_get_preferred_width (child, item_height, + &child_min, + &child_natural); + item_width = MIN (item_width, child_natural); + } + + if (!priv->is_homogeneous && + !clutter_actor_needs_expand (child, + CLUTTER_ORIENTATION_VERTICAL)) + { + clutter_actor_get_preferred_height (child, item_width, + &child_min, + &child_natural); + item_height = MIN (item_height, child_natural); + } + + CLUTTER_NOTE (LAYOUT, + "flow[line:%d, item:%d/%d] =" + "{ %.2f, %.2f, %.2f, %.2f }", + line_index, line_item_count + 1, items_per_line, + item_x, item_y, item_width, item_height); + + child_alloc.x1 = ceil (item_x); + child_alloc.y1 = ceil (item_y); + child_alloc.x2 = ceil (child_alloc.x1 + item_width); + child_alloc.y2 = ceil (child_alloc.y1 + item_height); + clutter_actor_allocate (child, &child_alloc, flags); + + if (priv->orientation == CLUTTER_FLOW_HORIZONTAL) + item_x = new_x; + else + item_y = new_y; + + line_item_count += 1; + } +} + +static void +clutter_flow_layout_set_container (ClutterLayoutManager *manager, + ClutterContainer *container) +{ + ClutterFlowLayoutPrivate *priv = CLUTTER_FLOW_LAYOUT (manager)->priv; + ClutterLayoutManagerClass *parent_class; + + priv->container = container; + + if (priv->container != NULL) + { + ClutterRequestMode request_mode; + + /* we need to change the :request-mode of the container + * to match the orientation + */ + request_mode = (priv->orientation == CLUTTER_FLOW_HORIZONTAL) + ? CLUTTER_REQUEST_HEIGHT_FOR_WIDTH + : CLUTTER_REQUEST_WIDTH_FOR_HEIGHT; + clutter_actor_set_request_mode (CLUTTER_ACTOR (priv->container), + request_mode); + } + + parent_class = CLUTTER_LAYOUT_MANAGER_CLASS (clutter_flow_layout_parent_class); + parent_class->set_container (manager, container); +} + +static void +clutter_flow_layout_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterFlowLayout *self = CLUTTER_FLOW_LAYOUT (gobject); + + switch (prop_id) + { + case PROP_ORIENTATION: + clutter_flow_layout_set_orientation (self, g_value_get_enum (value)); + break; + + case PROP_HOMOGENEOUS: + clutter_flow_layout_set_homogeneous (self, g_value_get_boolean (value)); + break; + + case PROP_COLUMN_SPACING: + clutter_flow_layout_set_column_spacing (self, g_value_get_float (value)); + break; + + case PROP_ROW_SPACING: + clutter_flow_layout_set_row_spacing (self, g_value_get_float (value)); + break; + + case PROP_MIN_COLUMN_WIDTH: + clutter_flow_layout_set_column_width (self, + g_value_get_float (value), + self->priv->max_col_width); + break; + + case PROP_MAX_COLUMN_WIDTH: + clutter_flow_layout_set_column_width (self, + self->priv->min_col_width, + g_value_get_float (value)); + break; + + case PROP_MIN_ROW_HEGHT: + clutter_flow_layout_set_row_height (self, + g_value_get_float (value), + self->priv->max_row_height); + break; + + case PROP_MAX_ROW_HEIGHT: + clutter_flow_layout_set_row_height (self, + self->priv->min_row_height, + g_value_get_float (value)); + break; + + case PROP_SNAP_TO_GRID: + clutter_flow_layout_set_snap_to_grid (self, + g_value_get_boolean (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_flow_layout_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterFlowLayoutPrivate *priv = CLUTTER_FLOW_LAYOUT (gobject)->priv; + + switch (prop_id) + { + case PROP_ORIENTATION: + g_value_set_enum (value, priv->orientation); + break; + + case PROP_HOMOGENEOUS: + g_value_set_boolean (value, priv->is_homogeneous); + break; + + case PROP_COLUMN_SPACING: + g_value_set_float (value, priv->col_spacing); + break; + + case PROP_ROW_SPACING: + g_value_set_float (value, priv->row_spacing); + break; + + case PROP_MIN_COLUMN_WIDTH: + g_value_set_float (value, priv->min_col_width); + break; + + case PROP_MAX_COLUMN_WIDTH: + g_value_set_float (value, priv->max_col_width); + break; + + case PROP_MIN_ROW_HEGHT: + g_value_set_float (value, priv->min_row_height); + break; + + case PROP_MAX_ROW_HEIGHT: + g_value_set_float (value, priv->max_row_height); + break; + + case PROP_SNAP_TO_GRID: + g_value_set_boolean (value, priv->snap_to_grid); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_flow_layout_finalize (GObject *gobject) +{ + ClutterFlowLayoutPrivate *priv = CLUTTER_FLOW_LAYOUT (gobject)->priv; + + if (priv->line_min != NULL) + g_array_free (priv->line_min, TRUE); + + if (priv->line_natural != NULL) + g_array_free (priv->line_natural, TRUE); + + G_OBJECT_CLASS (clutter_flow_layout_parent_class)->finalize (gobject); +} + +static void +clutter_flow_layout_class_init (ClutterFlowLayoutClass *klass) +{ + GObjectClass *gobject_class; + ClutterLayoutManagerClass *layout_class; + + gobject_class = G_OBJECT_CLASS (klass); + layout_class = CLUTTER_LAYOUT_MANAGER_CLASS (klass); + + layout_class->get_preferred_width = + clutter_flow_layout_get_preferred_width; + layout_class->get_preferred_height = + clutter_flow_layout_get_preferred_height; + layout_class->allocate = clutter_flow_layout_allocate; + layout_class->set_container = clutter_flow_layout_set_container; + + /** + * ClutterFlowLayout:orientation: + * + * The orientation of the #ClutterFlowLayout. The children + * of the layout will be layed out following the orientation. + * + * This property also controls the overflowing directions + * + * Since: 1.2 + */ + flow_properties[PROP_ORIENTATION] = + g_param_spec_enum ("orientation", + P_("Orientation"), + P_("The orientation of the layout"), + CLUTTER_TYPE_FLOW_ORIENTATION, + CLUTTER_FLOW_HORIZONTAL, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT); + + /** + * ClutterFlowLayout:homogeneous: + * + * Whether each child inside the #ClutterFlowLayout should receive + * the same allocation + * + * Since: 1.2 + */ + flow_properties[PROP_HOMOGENEOUS] = + g_param_spec_boolean ("homogeneous", + P_("Homogeneous"), + P_("Whether each item should receive the same allocation"), + FALSE, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterFlowLayout:column-spacing: + * + * The spacing between columns, in pixels; the value of this + * property is honoured by horizontal non-overflowing layouts + * and by vertical overflowing layouts + * + * Since: 1.2 + */ + flow_properties[PROP_COLUMN_SPACING] = + g_param_spec_float ("column-spacing", + P_("Column Spacing"), + P_("The spacing between columns"), + 0.0, G_MAXFLOAT, + 0.0, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterFlowLayout:row-spacing: + * + * The spacing between rows, in pixels; the value of this + * property is honoured by vertical non-overflowing layouts and + * by horizontal overflowing layouts + * + * Since: 1.2 + */ + flow_properties[PROP_ROW_SPACING] = + g_param_spec_float ("row-spacing", + P_("Row Spacing"), + P_("The spacing between rows"), + 0.0, G_MAXFLOAT, + 0.0, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterFlowLayout:min-column-width: + * + * Minimum width for each column in the layout, in pixels + * + * Since: 1.2 + */ + flow_properties[PROP_MIN_COLUMN_WIDTH] = + g_param_spec_float ("min-column-width", + P_("Minimum Column Width"), + P_("Minimum width for each column"), + 0.0, G_MAXFLOAT, + 0.0, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterFlowLayout:max-column-width: + * + * Maximum width for each column in the layout, in pixels. If + * set to -1 the width will be the maximum child width + * + * Since: 1.2 + */ + flow_properties[PROP_MAX_COLUMN_WIDTH] = + g_param_spec_float ("max-column-width", + P_("Maximum Column Width"), + P_("Maximum width for each column"), + -1.0, G_MAXFLOAT, + -1.0, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterFlowLayout:min-row-height: + * + * Minimum height for each row in the layout, in pixels + * + * Since: 1.2 + */ + flow_properties[PROP_MIN_ROW_HEGHT] = + g_param_spec_float ("min-row-height", + P_("Minimum Row Height"), + P_("Minimum height for each row"), + 0.0, G_MAXFLOAT, + 0.0, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterFlowLayout:max-row-height: + * + * Maximum height for each row in the layout, in pixels. If + * set to -1 the width will be the maximum child height + * + * Since: 1.2 + */ + flow_properties[PROP_MAX_ROW_HEIGHT] = + g_param_spec_float ("max-row-height", + P_("Maximum Row Height"), + P_("Maximum height for each row"), + -1.0, G_MAXFLOAT, + -1.0, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterFlowLayout:snap-to-grid: + * + * Whether the #ClutterFlowLayout should arrange its children + * on a grid + * + * Since: 1.16 + */ + flow_properties[PROP_SNAP_TO_GRID] = + g_param_spec_boolean ("snap-to-grid", + P_("Snap to grid"), + P_("Snap to grid"), + TRUE, + CLUTTER_PARAM_READWRITE); + + gobject_class->finalize = clutter_flow_layout_finalize; + gobject_class->set_property = clutter_flow_layout_set_property; + gobject_class->get_property = clutter_flow_layout_get_property; + g_object_class_install_properties (gobject_class, + N_PROPERTIES, + flow_properties); +} + +static void +clutter_flow_layout_init (ClutterFlowLayout *self) +{ + ClutterFlowLayoutPrivate *priv; + + self->priv = priv = clutter_flow_layout_get_instance_private (self); + + priv->orientation = CLUTTER_FLOW_HORIZONTAL; + + priv->col_spacing = 0; + priv->row_spacing = 0; + + priv->min_col_width = priv->min_row_height = 0; + priv->max_col_width = priv->max_row_height = -1; + + priv->line_min = NULL; + priv->line_natural = NULL; + priv->snap_to_grid = TRUE; +} + +/** + * clutter_flow_layout_new: + * @orientation: the orientation of the flow layout + * + * Creates a new #ClutterFlowLayout with the given @orientation + * + * Return value: the newly created #ClutterFlowLayout + * + * Since: 1.2 + */ +ClutterLayoutManager * +clutter_flow_layout_new (ClutterFlowOrientation orientation) +{ + return g_object_new (CLUTTER_TYPE_FLOW_LAYOUT, + "orientation", orientation, + NULL); +} + +/** + * clutter_flow_layout_set_orientation: + * @layout: a #ClutterFlowLayout + * @orientation: the orientation of the layout + * + * Sets the orientation of the flow layout + * + * The orientation controls the direction used to allocate + * the children: either horizontally or vertically. The + * orientation also controls the direction of the overflowing + * + * Since: 1.2 + */ +void +clutter_flow_layout_set_orientation (ClutterFlowLayout *layout, + ClutterFlowOrientation orientation) +{ + ClutterFlowLayoutPrivate *priv; + + g_return_if_fail (CLUTTER_IS_FLOW_LAYOUT (layout)); + + priv = layout->priv; + + if (priv->orientation != orientation) + { + ClutterLayoutManager *manager; + + priv->orientation = orientation; + + if (priv->container != NULL) + { + ClutterRequestMode request_mode; + + /* we need to change the :request-mode of the container + * to match the orientation + */ + request_mode = (priv->orientation == CLUTTER_FLOW_HORIZONTAL) + ? CLUTTER_REQUEST_HEIGHT_FOR_WIDTH + : CLUTTER_REQUEST_WIDTH_FOR_HEIGHT; + clutter_actor_set_request_mode (CLUTTER_ACTOR (priv->container), + request_mode); + } + + manager = CLUTTER_LAYOUT_MANAGER (layout); + clutter_layout_manager_layout_changed (manager); + + g_object_notify_by_pspec (G_OBJECT (layout), + flow_properties[PROP_ORIENTATION]); + } +} + +/** + * clutter_flow_layout_get_orientation: + * @layout: a #ClutterFlowLayout + * + * Retrieves the orientation of the @layout + * + * Return value: the orientation of the #ClutterFlowLayout + * + * Since: 1.2 + */ +ClutterFlowOrientation +clutter_flow_layout_get_orientation (ClutterFlowLayout *layout) +{ + g_return_val_if_fail (CLUTTER_IS_FLOW_LAYOUT (layout), + CLUTTER_FLOW_HORIZONTAL); + + return layout->priv->orientation; +} + +/** + * clutter_flow_layout_set_homogeneous: + * @layout: a #ClutterFlowLayout + * @homogeneous: whether the layout should be homogeneous or not + * + * Sets whether the @layout should allocate the same space for + * each child + * + * Since: 1.2 + */ +void +clutter_flow_layout_set_homogeneous (ClutterFlowLayout *layout, + gboolean homogeneous) +{ + ClutterFlowLayoutPrivate *priv; + + g_return_if_fail (CLUTTER_IS_FLOW_LAYOUT (layout)); + + priv = layout->priv; + + if (priv->is_homogeneous != homogeneous) + { + ClutterLayoutManager *manager; + + priv->is_homogeneous = homogeneous; + + manager = CLUTTER_LAYOUT_MANAGER (layout); + clutter_layout_manager_layout_changed (manager); + + g_object_notify_by_pspec (G_OBJECT (layout), + flow_properties[PROP_HOMOGENEOUS]); + } +} + +/** + * clutter_flow_layout_get_homogeneous: + * @layout: a #ClutterFlowLayout + * + * Retrieves whether the @layout is homogeneous + * + * Return value: %TRUE if the #ClutterFlowLayout is homogeneous + * + * Since: 1.2 + */ +gboolean +clutter_flow_layout_get_homogeneous (ClutterFlowLayout *layout) +{ + g_return_val_if_fail (CLUTTER_IS_FLOW_LAYOUT (layout), FALSE); + + return layout->priv->is_homogeneous; +} + +/** + * clutter_flow_layout_set_column_spacing: + * @layout: a #ClutterFlowLayout + * @spacing: the space between columns + * + * Sets the space between columns, in pixels + * + * Since: 1.2 + */ +void +clutter_flow_layout_set_column_spacing (ClutterFlowLayout *layout, + gfloat spacing) +{ + ClutterFlowLayoutPrivate *priv; + + g_return_if_fail (CLUTTER_IS_FLOW_LAYOUT (layout)); + + priv = layout->priv; + + if (priv->col_spacing != spacing) + { + ClutterLayoutManager *manager; + + priv->col_spacing = spacing; + + manager = CLUTTER_LAYOUT_MANAGER (layout); + clutter_layout_manager_layout_changed (manager); + + g_object_notify_by_pspec (G_OBJECT (layout), + flow_properties[PROP_COLUMN_SPACING]); + } +} + +/** + * clutter_flow_layout_get_column_spacing: + * @layout: a #ClutterFlowLayout + * + * Retrieves the spacing between columns + * + * Return value: the spacing between columns of the #ClutterFlowLayout, + * in pixels + * + * Since: 1.2 + */ +gfloat +clutter_flow_layout_get_column_spacing (ClutterFlowLayout *layout) +{ + g_return_val_if_fail (CLUTTER_IS_FLOW_LAYOUT (layout), 0.0); + + return layout->priv->col_spacing; +} + +/** + * clutter_flow_layout_set_row_spacing: + * @layout: a #ClutterFlowLayout + * @spacing: the space between rows + * + * Sets the spacing between rows, in pixels + * + * Since: 1.2 + */ +void +clutter_flow_layout_set_row_spacing (ClutterFlowLayout *layout, + gfloat spacing) +{ + ClutterFlowLayoutPrivate *priv; + + g_return_if_fail (CLUTTER_IS_FLOW_LAYOUT (layout)); + + priv = layout->priv; + + if (priv->row_spacing != spacing) + { + ClutterLayoutManager *manager; + + priv->row_spacing = spacing; + + manager = CLUTTER_LAYOUT_MANAGER (layout); + clutter_layout_manager_layout_changed (manager); + + g_object_notify_by_pspec (G_OBJECT (layout), + flow_properties[PROP_ROW_SPACING]); + } +} + +/** + * clutter_flow_layout_get_row_spacing: + * @layout: a #ClutterFlowLayout + * + * Retrieves the spacing between rows + * + * Return value: the spacing between rows of the #ClutterFlowLayout, + * in pixels + * + * Since: 1.2 + */ +gfloat +clutter_flow_layout_get_row_spacing (ClutterFlowLayout *layout) +{ + g_return_val_if_fail (CLUTTER_IS_FLOW_LAYOUT (layout), 0.0); + + return layout->priv->row_spacing; +} + +/** + * clutter_flow_layout_set_column_width: + * @layout: a #ClutterFlowLayout + * @min_width: minimum width of a column + * @max_width: maximum width of a column + * + * Sets the minimum and maximum widths that a column can have + * + * Since: 1.2 + */ +void +clutter_flow_layout_set_column_width (ClutterFlowLayout *layout, + gfloat min_width, + gfloat max_width) +{ + ClutterFlowLayoutPrivate *priv; + gboolean notify_min = FALSE, notify_max = FALSE; + + g_return_if_fail (CLUTTER_IS_FLOW_LAYOUT (layout)); + + priv = layout->priv; + + if (priv->min_col_width != min_width) + { + priv->min_col_width = min_width; + + notify_min = TRUE; + } + + if (priv->max_col_width != max_width) + { + priv->max_col_width = max_width; + + notify_max = TRUE; + } + + g_object_freeze_notify (G_OBJECT (layout)); + + if (notify_min || notify_max) + { + ClutterLayoutManager *manager = CLUTTER_LAYOUT_MANAGER (layout); + + clutter_layout_manager_layout_changed (manager); + } + + if (notify_min) + g_object_notify_by_pspec (G_OBJECT (layout), + flow_properties[PROP_MIN_COLUMN_WIDTH]); + + if (notify_max) + g_object_notify_by_pspec (G_OBJECT (layout), + flow_properties[PROP_MAX_COLUMN_WIDTH]); + + g_object_thaw_notify (G_OBJECT (layout)); +} + +/** + * clutter_flow_layout_get_column_width: + * @layout: a #ClutterFlowLayout + * @min_width: (out): return location for the minimum column width, or %NULL + * @max_width: (out): return location for the maximum column width, or %NULL + * + * Retrieves the minimum and maximum column widths + * + * Since: 1.2 + */ +void +clutter_flow_layout_get_column_width (ClutterFlowLayout *layout, + gfloat *min_width, + gfloat *max_width) +{ + g_return_if_fail (CLUTTER_IS_FLOW_LAYOUT (layout)); + + if (min_width) + *min_width = layout->priv->min_col_width; + + if (max_width) + *max_width = layout->priv->max_col_width; +} + +/** + * clutter_flow_layout_set_row_height: + * @layout: a #ClutterFlowLayout + * @min_height: the minimum height of a row + * @max_height: the maximum height of a row + * + * Sets the minimum and maximum heights that a row can have + * + * Since: 1.2 + */ +void +clutter_flow_layout_set_row_height (ClutterFlowLayout *layout, + gfloat min_height, + gfloat max_height) +{ + ClutterFlowLayoutPrivate *priv; + gboolean notify_min = FALSE, notify_max = FALSE; + + g_return_if_fail (CLUTTER_IS_FLOW_LAYOUT (layout)); + + priv = layout->priv; + + if (priv->min_row_height != min_height) + { + priv->min_row_height = min_height; + + notify_min = TRUE; + } + + if (priv->max_row_height != max_height) + { + priv->max_row_height = max_height; + + notify_max = TRUE; + } + + g_object_freeze_notify (G_OBJECT (layout)); + + if (notify_min || notify_max) + { + ClutterLayoutManager *manager = CLUTTER_LAYOUT_MANAGER (layout); + + clutter_layout_manager_layout_changed (manager); + } + + if (notify_min) + g_object_notify_by_pspec (G_OBJECT (layout), + flow_properties[PROP_MIN_ROW_HEGHT]); + + if (notify_max) + g_object_notify_by_pspec (G_OBJECT (layout), + flow_properties[PROP_MAX_ROW_HEIGHT]); + + g_object_thaw_notify (G_OBJECT (layout)); +} + +/** + * clutter_flow_layout_get_row_height: + * @layout: a #ClutterFlowLayout + * @min_height: (out): return location for the minimum row height, or %NULL + * @max_height: (out): return location for the maximum row height, or %NULL + * + * Retrieves the minimum and maximum row heights + * + * Since: 1.2 + */ +void +clutter_flow_layout_get_row_height (ClutterFlowLayout *layout, + gfloat *min_height, + gfloat *max_height) +{ + g_return_if_fail (CLUTTER_IS_FLOW_LAYOUT (layout)); + + if (min_height) + *min_height = layout->priv->min_row_height; + + if (max_height) + *max_height = layout->priv->max_row_height; +} + +/** + * clutter_flow_layout_set_snap_to_grid: + * @layout: a #ClutterFlowLayout + * @snap_to_grid: %TRUE if @layout should place its children on a grid + * + * Whether the @layout should place its children on a grid. + * + * Since: 1.16 + */ +void +clutter_flow_layout_set_snap_to_grid (ClutterFlowLayout *layout, + gboolean snap_to_grid) +{ + ClutterFlowLayoutPrivate *priv; + + g_return_if_fail (CLUTTER_IS_FLOW_LAYOUT (layout)); + + priv = layout->priv; + + if (priv->snap_to_grid != snap_to_grid) + { + priv->snap_to_grid = snap_to_grid; + + clutter_layout_manager_layout_changed (CLUTTER_LAYOUT_MANAGER (layout)); + + g_object_notify_by_pspec (G_OBJECT (layout), + flow_properties[PROP_SNAP_TO_GRID]); + } +} + +/** + * clutter_flow_layout_get_snap_to_grid: + * @layout: a #ClutterFlowLayout + * + * Retrieves the value of #ClutterFlowLayout:snap-to-grid property + * + * Return value: %TRUE if the @layout is placing its children on a grid + * + * Since: 1.16 + */ +gboolean +clutter_flow_layout_get_snap_to_grid (ClutterFlowLayout *layout) +{ + g_return_val_if_fail (CLUTTER_IS_FLOW_LAYOUT (layout), FALSE); + + return layout->priv->snap_to_grid; +} diff --git a/clutter/clutter/clutter-flow-layout.h b/clutter/clutter/clutter-flow-layout.h new file mode 100644 index 0000000..d44857b --- /dev/null +++ b/clutter/clutter/clutter-flow-layout.h @@ -0,0 +1,129 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * 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 . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_FLOW_LAYOUT_H__ +#define __CLUTTER_FLOW_LAYOUT_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_FLOW_LAYOUT (clutter_flow_layout_get_type ()) +#define CLUTTER_FLOW_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_FLOW_LAYOUT, ClutterFlowLayout)) +#define CLUTTER_IS_FLOW_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_FLOW_LAYOUT)) +#define CLUTTER_FLOW_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_FLOW_LAYOUT, ClutterFlowLayoutClass)) +#define CLUTTER_IS_FLOW_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_FLOW_LAYOUT)) +#define CLUTTER_FLOW_LAYOUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_FLOW_LAYOUT, ClutterFlowLayoutClass)) + +typedef struct _ClutterFlowLayout ClutterFlowLayout; +typedef struct _ClutterFlowLayoutPrivate ClutterFlowLayoutPrivate; +typedef struct _ClutterFlowLayoutClass ClutterFlowLayoutClass; + +/** + * ClutterFlowLayout: + * + * The #ClutterFlowLayout structure contains only private data + * and should be accessed using the provided API + * + * Since: 1.2 + */ +struct _ClutterFlowLayout +{ + /*< private >*/ + ClutterLayoutManager parent_instance; + + ClutterFlowLayoutPrivate *priv; +}; + +/** + * ClutterFlowLayoutClass: + * + * The #ClutterFlowLayoutClass structure contains only private data + * and should be accessed using the provided API + * + * Since: 1.2 + */ +struct _ClutterFlowLayoutClass +{ + /*< private >*/ + ClutterLayoutManagerClass parent_class; +}; + +CLUTTER_AVAILABLE_IN_1_2 +GType clutter_flow_layout_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_2 +ClutterLayoutManager * clutter_flow_layout_new (ClutterFlowOrientation orientation); + +CLUTTER_AVAILABLE_IN_1_2 +void clutter_flow_layout_set_orientation (ClutterFlowLayout *layout, + ClutterFlowOrientation orientation); +CLUTTER_AVAILABLE_IN_1_2 +ClutterFlowOrientation clutter_flow_layout_get_orientation (ClutterFlowLayout *layout); +CLUTTER_AVAILABLE_IN_1_2 +void clutter_flow_layout_set_homogeneous (ClutterFlowLayout *layout, + gboolean homogeneous); +CLUTTER_AVAILABLE_IN_1_2 +gboolean clutter_flow_layout_get_homogeneous (ClutterFlowLayout *layout); + +CLUTTER_AVAILABLE_IN_1_2 +void clutter_flow_layout_set_column_spacing (ClutterFlowLayout *layout, + gfloat spacing); +CLUTTER_AVAILABLE_IN_1_2 +gfloat clutter_flow_layout_get_column_spacing (ClutterFlowLayout *layout); +CLUTTER_AVAILABLE_IN_1_2 +void clutter_flow_layout_set_row_spacing (ClutterFlowLayout *layout, + gfloat spacing); +CLUTTER_AVAILABLE_IN_1_2 +gfloat clutter_flow_layout_get_row_spacing (ClutterFlowLayout *layout); + +CLUTTER_AVAILABLE_IN_1_2 +void clutter_flow_layout_set_column_width (ClutterFlowLayout *layout, + gfloat min_width, + gfloat max_width); +CLUTTER_AVAILABLE_IN_1_2 +void clutter_flow_layout_get_column_width (ClutterFlowLayout *layout, + gfloat *min_width, + gfloat *max_width); +CLUTTER_AVAILABLE_IN_1_2 +void clutter_flow_layout_set_row_height (ClutterFlowLayout *layout, + gfloat min_height, + gfloat max_height); +CLUTTER_AVAILABLE_IN_1_2 +void clutter_flow_layout_get_row_height (ClutterFlowLayout *layout, + gfloat *min_height, + gfloat *max_height); +CLUTTER_AVAILABLE_IN_1_16 +void clutter_flow_layout_set_snap_to_grid (ClutterFlowLayout *layout, + gboolean snap_to_grid); +CLUTTER_AVAILABLE_IN_1_16 +gboolean clutter_flow_layout_get_snap_to_grid (ClutterFlowLayout *layout); + +G_END_DECLS + +#endif /* __CLUTTER_FLOW_LAYOUT_H__ */ diff --git a/clutter/clutter/clutter-gesture-action-private.h b/clutter/clutter/clutter-gesture-action-private.h new file mode 100644 index 0000000..cd804ab --- /dev/null +++ b/clutter/clutter/clutter-gesture-action-private.h @@ -0,0 +1,31 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2012 Collabora Ltd.. + * + * 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 . + */ + +#ifndef __CLUTTER_GESTURE_ACTION_PRIVATE_H__ +#define __CLUTTER_GESTURE_ACTION_PRIVATE_H__ + +#include + +G_BEGIN_DECLS + +G_END_DECLS + +#endif /* __CLUTTER_GESTURE_ACTION_PRIVATE_H__ */ diff --git a/clutter/clutter/clutter-gesture-action.c b/clutter/clutter/clutter-gesture-action.c new file mode 100644 index 0000000..668112f --- /dev/null +++ b/clutter/clutter/clutter-gesture-action.c @@ -0,0 +1,1368 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * Copyright (C) 2011 Robert Bosch Car Multimedia GmbH. + * Copyright (C) 2012 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 . + * + * Author: + * Tomeu Vizoso + */ + +/** + * SECTION:clutter-gesture-action + * @Title: ClutterGestureAction + * @Short_Description: Action for gesture gestures + * + * #ClutterGestureAction is a sub-class of #ClutterAction that implements + * the logic for recognizing gesture gestures. It listens for low level events + * such as #ClutterButtonEvent and #ClutterMotionEvent on the stage to raise + * the #ClutterGestureAction::gesture-begin, #ClutterGestureAction::gesture-progress, + * and #ClutterGestureAction::gesture-end signals. + * + * To use #ClutterGestureAction you just need to apply it to a #ClutterActor + * using clutter_actor_add_action() and connect to the signals: + * + * |[ + * ClutterAction *action = clutter_gesture_action_new (); + * + * clutter_actor_add_action (actor, action); + * + * g_signal_connect (action, "gesture-begin", G_CALLBACK (on_gesture_begin), NULL); + * g_signal_connect (action, "gesture-progress", G_CALLBACK (on_gesture_progress), NULL); + * g_signal_connect (action, "gesture-end", G_CALLBACK (on_gesture_end), NULL); + * ]| + * + * ## Creating Gesture actions + * + * A #ClutterGestureAction provides four separate states that can be + * used to recognize or ignore gestures when writing a new action class: + * + * - Prepare -> Cancel + * - Prepare -> Begin -> Cancel + * - Prepare -> Begin -> End + * - Prepare -> Begin -> Progress -> Cancel + * - Prepare -> Begin -> Progress -> End + * + * Each #ClutterGestureAction starts in the "prepare" state, and calls + * the #ClutterGestureActionClass.gesture_prepare() virtual function; this + * state can be used to reset the internal state of a #ClutterGestureAction + * subclass, but it can also immediately cancel a gesture without going + * through the rest of the states. + * + * The "begin" state follows the "prepare" state, and calls the + * #ClutterGestureActionClass.gesture_begin() virtual function. This state + * signals the start of a gesture recognizing process. From the "begin" state + * the gesture recognition process can successfully end, by going to the + * "end" state; it can continue in the "progress" state, in case of a + * continuous gesture; or it can be terminated, by moving to the "cancel" + * state. + * + * In case of continuous gestures, the #ClutterGestureAction will use + * the "progress" state, calling the #ClutterGestureActionClass.gesture_progress() + * virtual function; the "progress" state will continue until the end of the + * gesture, in which case the "end" state will be reached, or until the + * gesture is cancelled, in which case the "cancel" gesture will be used + * instead. + * + * Since: 1.8 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-gesture-action-private.h" + +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-marshal.h" +#include "clutter-private.h" + +#include + +#define MAX_GESTURE_POINTS (10) +#define FLOAT_EPSILON (1e-15) + +typedef struct +{ + ClutterInputDevice *device; + ClutterEventSequence *sequence; + ClutterEvent *last_event; + + gfloat press_x, press_y; + gint64 last_motion_time; + gfloat last_motion_x, last_motion_y; + gint64 last_delta_time; + gfloat last_delta_x, last_delta_y; + gfloat release_x, release_y; +} GesturePoint; + +struct _ClutterGestureActionPrivate +{ + ClutterActor *stage; + + gint requested_nb_points; + GArray *points; + + guint actor_capture_id; + gulong stage_capture_id; + + ClutterGestureTriggerEdge edge; + float distance_x, distance_y; + + guint in_gesture : 1; +}; + +enum +{ + PROP_0, + + PROP_N_TOUCH_POINTS, + PROP_THRESHOLD_TRIGGER_EDGE, + PROP_THRESHOLD_TRIGGER_DISTANCE_X, + PROP_THRESHOLD_TRIGGER_DISTANCE_Y, + + PROP_LAST +}; + +enum +{ + GESTURE_BEGIN, + GESTURE_PROGRESS, + GESTURE_END, + GESTURE_CANCEL, + + LAST_SIGNAL +}; + +static GParamSpec *gesture_props[PROP_LAST]; +static guint gesture_signals[LAST_SIGNAL] = { 0, }; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterGestureAction, clutter_gesture_action, CLUTTER_TYPE_ACTION) + +static GesturePoint * +gesture_register_point (ClutterGestureAction *action, ClutterEvent *event) +{ + ClutterGestureActionPrivate *priv = action->priv; + GesturePoint *point = NULL; + + if (priv->points->len >= MAX_GESTURE_POINTS) + return NULL; + + g_array_set_size (priv->points, priv->points->len + 1); + point = &g_array_index (priv->points, GesturePoint, priv->points->len - 1); + + point->last_event = clutter_event_copy (event); + point->device = clutter_event_get_device (event); + + clutter_event_get_coords (event, &point->press_x, &point->press_y); + point->last_motion_x = point->press_x; + point->last_motion_y = point->press_y; + point->last_motion_time = clutter_event_get_time (event); + + point->last_delta_x = point->last_delta_y = 0; + point->last_delta_time = 0; + + if (clutter_event_type (event) != CLUTTER_BUTTON_PRESS) + point->sequence = clutter_event_get_event_sequence (event); + else + point->sequence = NULL; + + return point; +} + +static GesturePoint * +gesture_find_point (ClutterGestureAction *action, + ClutterEvent *event, + gint *position) +{ + ClutterGestureActionPrivate *priv = action->priv; + GesturePoint *point = NULL; + ClutterEventType type = clutter_event_type (event); + ClutterInputDevice *device = clutter_event_get_device (event); + ClutterEventSequence *sequence = NULL; + gint i; + + if ((type != CLUTTER_BUTTON_PRESS) && + (type != CLUTTER_BUTTON_RELEASE) && + (type != CLUTTER_MOTION)) + sequence = clutter_event_get_event_sequence (event); + + for (i = 0; i < priv->points->len; i++) + { + if ((g_array_index (priv->points, GesturePoint, i).device == device) && + (g_array_index (priv->points, GesturePoint, i).sequence == sequence)) + { + if (position != NULL) + *position = i; + point = &g_array_index (priv->points, GesturePoint, i); + break; + } + } + + return point; +} + +static void +gesture_unregister_point (ClutterGestureAction *action, gint position) +{ + ClutterGestureActionPrivate *priv = action->priv; + + if (action->priv->points->len == 0) + return; + + g_array_remove_index (priv->points, position); +} + +static void +gesture_update_motion_point (GesturePoint *point, + ClutterEvent *event) +{ + gfloat motion_x, motion_y; + gint64 _time; + + clutter_event_get_coords (event, &motion_x, &motion_y); + + clutter_event_free (point->last_event); + point->last_event = clutter_event_copy (event); + + point->last_delta_x = motion_x - point->last_motion_x; + point->last_delta_y = motion_y - point->last_motion_y; + point->last_motion_x = motion_x; + point->last_motion_y = motion_y; + + _time = clutter_event_get_time (event); + point->last_delta_time = _time - point->last_motion_time; + point->last_motion_time = _time; +} + +static void +gesture_update_release_point (GesturePoint *point, + ClutterEvent *event) +{ + gint64 _time; + + clutter_event_get_coords (event, &point->release_x, &point->release_y); + + clutter_event_free (point->last_event); + point->last_event = clutter_event_copy (event); + + /* Treat the release event as the continuation of the last motion, + * in case the user keeps the pointer still for a while before + * releasing it. */ + _time = clutter_event_get_time (event); + point->last_delta_time += _time - point->last_motion_time; +} + +static gint +gesture_get_default_threshold (void) +{ + gint threshold; + ClutterSettings *settings = clutter_settings_get_default (); + g_object_get (settings, "dnd-drag-threshold", &threshold, NULL); + return threshold; +} + +static gboolean +gesture_point_pass_threshold (ClutterGestureAction *action, + GesturePoint *point, + ClutterEvent *event) +{ + float threshold_x, threshold_y; + gfloat motion_x, motion_y; + + clutter_event_get_coords (event, &motion_x, &motion_y); + clutter_gesture_action_get_threshold_trigger_distance (action, &threshold_x, &threshold_y); + + if ((fabsf (point->press_y - motion_y) < threshold_y) && + (fabsf (point->press_x - motion_x) < threshold_x)) + return TRUE; + return FALSE; +} + +static void +gesture_point_unset (GesturePoint *point) +{ + clutter_event_free (point->last_event); +} + +static void +cancel_gesture (ClutterGestureAction *action) +{ + ClutterGestureActionPrivate *priv = action->priv; + ClutterActor *actor; + + priv->in_gesture = FALSE; + + if (priv->stage_capture_id != 0) + { + g_signal_handler_disconnect (priv->stage, priv->stage_capture_id); + priv->stage_capture_id = 0; + } + + actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action)); + g_signal_emit (action, gesture_signals[GESTURE_CANCEL], 0, actor); + + g_array_set_size (action->priv->points, 0); +} + +static gboolean +begin_gesture (ClutterGestureAction *action, + ClutterActor *actor) +{ + ClutterGestureActionPrivate *priv = action->priv; + gboolean return_value; + + priv->in_gesture = TRUE; + + if (!CLUTTER_GESTURE_ACTION_GET_CLASS (action)->gesture_prepare (action, actor)) + { + cancel_gesture (action); + return FALSE; + } + + /* clutter_gesture_action_cancel() may have been called during + * gesture_prepare(), check that the gesture is still active. */ + if (!priv->in_gesture) + return FALSE; + + g_signal_emit (action, gesture_signals[GESTURE_BEGIN], 0, actor, + &return_value); + + if (!return_value) + { + cancel_gesture (action); + return FALSE; + } + + return TRUE; +} + +static gboolean +stage_captured_event_cb (ClutterActor *stage, + ClutterEvent *event, + ClutterGestureAction *action) +{ + ClutterGestureActionPrivate *priv = action->priv; + ClutterActor *actor; + gint position; + float threshold_x, threshold_y; + gboolean return_value; + GesturePoint *point; + ClutterEventType event_type; + + event_type = clutter_event_type (event); + if (event_type != CLUTTER_TOUCH_CANCEL && + event_type != CLUTTER_TOUCH_UPDATE && + event_type != CLUTTER_TOUCH_END && + event_type != CLUTTER_MOTION && + event_type != CLUTTER_BUTTON_RELEASE) + return CLUTTER_EVENT_PROPAGATE; + + if ((point = gesture_find_point (action, event, &position)) == NULL) + return CLUTTER_EVENT_PROPAGATE; + + actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action)); + + switch (clutter_event_type (event)) + { + case CLUTTER_MOTION: + { + ClutterModifierType mods = clutter_event_get_state (event); + + /* we might miss a button-release event in case of grabs, + * so we need to check whether the button is still down + * during a motion event + */ + if (!(mods & CLUTTER_BUTTON1_MASK)) + { + cancel_gesture (action); + return CLUTTER_EVENT_PROPAGATE; + } + } + /* Follow same code path as a touch event update */ + + case CLUTTER_TOUCH_UPDATE: + if (!priv->in_gesture) + { + if (priv->points->len < priv->requested_nb_points) + { + gesture_update_motion_point (point, event); + return CLUTTER_EVENT_PROPAGATE; + } + + /* Wait until the drag threshold has been exceeded + * before starting _TRIGGER_EDGE_AFTER gestures. */ + if (priv->edge == CLUTTER_GESTURE_TRIGGER_EDGE_AFTER && + gesture_point_pass_threshold (action, point, event)) + { + gesture_update_motion_point (point, event); + return CLUTTER_EVENT_PROPAGATE; + } + + if (!begin_gesture (action, actor)) + { + if ((point = gesture_find_point (action, event, &position)) != NULL) + gesture_update_motion_point (point, event); + return CLUTTER_EVENT_PROPAGATE; + } + + if ((point = gesture_find_point (action, event, &position)) == NULL) + return CLUTTER_EVENT_PROPAGATE; + } + + gesture_update_motion_point (point, event); + + g_signal_emit (action, gesture_signals[GESTURE_PROGRESS], 0, actor, + &return_value); + if (!return_value) + { + cancel_gesture (action); + return CLUTTER_EVENT_PROPAGATE; + } + + /* Check if a _TRIGGER_EDGE_BEFORE gesture needs to be cancelled because + * the drag threshold has been exceeded. */ + clutter_gesture_action_get_threshold_trigger_distance (action, &threshold_x, &threshold_y); + if (priv->edge == CLUTTER_GESTURE_TRIGGER_EDGE_BEFORE && + ((fabsf (point->press_y - point->last_motion_y) > threshold_y) || + (fabsf (point->press_x - point->last_motion_x) > threshold_x))) + { + cancel_gesture (action); + return CLUTTER_EVENT_PROPAGATE; + } + break; + + case CLUTTER_BUTTON_RELEASE: + case CLUTTER_TOUCH_END: + { + gesture_update_release_point (point, event); + + if (priv->in_gesture && + ((priv->points->len - 1) < priv->requested_nb_points)) + { + priv->in_gesture = FALSE; + g_signal_emit (action, gesture_signals[GESTURE_END], 0, actor); + } + + gesture_unregister_point (action, position); + } + break; + + case CLUTTER_TOUCH_CANCEL: + { + gesture_update_release_point (point, event); + + if (priv->in_gesture) + { + priv->in_gesture = FALSE; + cancel_gesture (action); + } + + gesture_unregister_point (action, position); + } + break; + + default: + break; + } + + if (priv->points->len == 0 && priv->stage_capture_id) + { + g_signal_handler_disconnect (priv->stage, priv->stage_capture_id); + priv->stage_capture_id = 0; + } + + return CLUTTER_EVENT_PROPAGATE; +} + +static gboolean +actor_captured_event_cb (ClutterActor *actor, + ClutterEvent *event, + ClutterGestureAction *action) +{ + ClutterGestureActionPrivate *priv = action->priv; + GesturePoint *point G_GNUC_UNUSED; + + if ((clutter_event_type (event) != CLUTTER_BUTTON_PRESS) && + (clutter_event_type (event) != CLUTTER_TOUCH_BEGIN)) + return CLUTTER_EVENT_PROPAGATE; + + if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (action))) + return CLUTTER_EVENT_PROPAGATE; + + point = gesture_register_point (action, event); + + if (priv->stage == NULL) + priv->stage = clutter_actor_get_stage (actor); + + if (priv->stage_capture_id == 0) + priv->stage_capture_id = + g_signal_connect_after (priv->stage, "captured-event", + G_CALLBACK (stage_captured_event_cb), + action); + + /* Start the gesture immediately if the gesture has no + * _TRIGGER_EDGE_AFTER drag threshold. */ + if ((priv->points->len >= priv->requested_nb_points) && + (priv->edge != CLUTTER_GESTURE_TRIGGER_EDGE_AFTER)) + begin_gesture (action, actor); + + return CLUTTER_EVENT_PROPAGATE; +} + +static void +clutter_gesture_action_set_actor (ClutterActorMeta *meta, + ClutterActor *actor) +{ + ClutterGestureActionPrivate *priv = CLUTTER_GESTURE_ACTION (meta)->priv; + ClutterActorMetaClass *meta_class = + CLUTTER_ACTOR_META_CLASS (clutter_gesture_action_parent_class); + + if (priv->actor_capture_id != 0) + { + ClutterActor *old_actor = clutter_actor_meta_get_actor (meta); + + if (old_actor != NULL) + g_signal_handler_disconnect (old_actor, priv->actor_capture_id); + + priv->actor_capture_id = 0; + } + + if (priv->stage_capture_id != 0) + { + if (priv->stage != NULL) + g_signal_handler_disconnect (priv->stage, priv->stage_capture_id); + + priv->stage_capture_id = 0; + priv->stage = NULL; + } + + if (actor != NULL) + { + priv->actor_capture_id = + g_signal_connect (actor, "captured-event", + G_CALLBACK (actor_captured_event_cb), + meta); + } + + meta_class->set_actor (meta, actor); +} + +static gboolean +default_event_handler (ClutterGestureAction *action, + ClutterActor *actor) +{ + return TRUE; +} + +static void +clutter_gesture_action_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterGestureAction *self = CLUTTER_GESTURE_ACTION (gobject); + + switch (prop_id) + { + case PROP_N_TOUCH_POINTS: + clutter_gesture_action_set_n_touch_points (self, g_value_get_int (value)); + break; + + case PROP_THRESHOLD_TRIGGER_EDGE: + clutter_gesture_action_set_threshold_trigger_edge (self, g_value_get_enum (value)); + break; + + case PROP_THRESHOLD_TRIGGER_DISTANCE_X: + clutter_gesture_action_set_threshold_trigger_distance (self, g_value_get_float (value), self->priv->distance_y); + break; + + case PROP_THRESHOLD_TRIGGER_DISTANCE_Y: + clutter_gesture_action_set_threshold_trigger_distance (self, self->priv->distance_x, g_value_get_float (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_gesture_action_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterGestureAction *self = CLUTTER_GESTURE_ACTION (gobject); + + switch (prop_id) + { + case PROP_N_TOUCH_POINTS: + g_value_set_int (value, self->priv->requested_nb_points); + break; + + case PROP_THRESHOLD_TRIGGER_EDGE: + g_value_set_enum (value, self->priv->edge); + break; + + case PROP_THRESHOLD_TRIGGER_DISTANCE_X: + if (self->priv->distance_x > 0.0) + g_value_set_float (value, self->priv->distance_x); + else + g_value_set_float (value, gesture_get_default_threshold ()); + break; + + case PROP_THRESHOLD_TRIGGER_DISTANCE_Y: + if (self->priv->distance_y > 0.0) + g_value_set_float (value, self->priv->distance_y); + else + g_value_set_float (value, gesture_get_default_threshold ()); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_gesture_action_finalize (GObject *gobject) +{ + ClutterGestureActionPrivate *priv = CLUTTER_GESTURE_ACTION (gobject)->priv; + + g_array_unref (priv->points); + + G_OBJECT_CLASS (clutter_gesture_action_parent_class)->finalize (gobject); +} + +static void +clutter_gesture_action_class_init (ClutterGestureActionClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass); + + gobject_class->finalize = clutter_gesture_action_finalize; + gobject_class->set_property = clutter_gesture_action_set_property; + gobject_class->get_property = clutter_gesture_action_get_property; + + meta_class->set_actor = clutter_gesture_action_set_actor; + + klass->gesture_begin = default_event_handler; + klass->gesture_progress = default_event_handler; + klass->gesture_prepare = default_event_handler; + + /** + * ClutterGestureAction:n-touch-points: + * + * Number of touch points to trigger a gesture action. + * + * Since: 1.16 + */ + gesture_props[PROP_N_TOUCH_POINTS] = + g_param_spec_int ("n-touch-points", + P_("Number touch points"), + P_("Number of touch points"), + 1, G_MAXINT, 1, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterGestureAction:threshold-trigger-edge: + * + * The trigger edge to be used by the action to either emit the + * #ClutterGestureAction::gesture-begin signal or to emit the + * #ClutterGestureAction::gesture-cancel signal. + * + * Since: 1.18 + */ + gesture_props[PROP_THRESHOLD_TRIGGER_EDGE] = + g_param_spec_enum ("threshold-trigger-edge", + P_("Threshold Trigger Edge"), + P_("The trigger edge used by the action"), + CLUTTER_TYPE_GESTURE_TRIGGER_EDGE, + CLUTTER_GESTURE_TRIGGER_EDGE_NONE, + CLUTTER_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY); + + /** + * ClutterGestureAction:threshold-trigger-distance-x: + * + * The horizontal trigger distance to be used by the action to either + * emit the #ClutterGestureAction::gesture-begin signal or to emit + * the #ClutterGestureAction::gesture-cancel signal. + * + * A negative value will be interpreted as the default drag threshold. + * + * Since: 1.18 + */ + gesture_props[PROP_THRESHOLD_TRIGGER_DISTANCE_X] = + g_param_spec_float ("threshold-trigger-distance-x", + P_("Threshold Trigger Horizontal Distance"), + P_("The horizontal trigger distance used by the action"), + -1.0, G_MAXFLOAT, -1.0, + CLUTTER_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY); + + /** + * ClutterGestureAction:threshold-trigger-distance-y: + * + * The vertical trigger distance to be used by the action to either + * emit the #ClutterGestureAction::gesture-begin signal or to emit + * the #ClutterGestureAction::gesture-cancel signal. + * + * A negative value will be interpreted as the default drag threshold. + * + * Since: 1.18 + */ + gesture_props[PROP_THRESHOLD_TRIGGER_DISTANCE_Y] = + g_param_spec_float ("threshold-trigger-distance-y", + P_("Threshold Trigger Vertical Distance"), + P_("The vertical trigger distance used by the action"), + -1.0, G_MAXFLOAT, -1.0, + CLUTTER_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY); + + g_object_class_install_properties (gobject_class, + PROP_LAST, + gesture_props); + + /** + * ClutterGestureAction::gesture-begin: + * @action: the #ClutterGestureAction that emitted the signal + * @actor: the #ClutterActor attached to the @action + * + * The ::gesture_begin signal is emitted when the #ClutterActor to which + * a #ClutterGestureAction has been applied starts receiving a gesture. + * + * Return value: %TRUE if the gesture should start, and %FALSE if + * the gesture should be ignored. + * + * Since: 1.8 + */ + gesture_signals[GESTURE_BEGIN] = + g_signal_new (I_("gesture-begin"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterGestureActionClass, gesture_begin), + _clutter_boolean_continue_accumulator, NULL, + _clutter_marshal_BOOLEAN__OBJECT, + G_TYPE_BOOLEAN, 1, + CLUTTER_TYPE_ACTOR); + + /** + * ClutterGestureAction::gesture-progress: + * @action: the #ClutterGestureAction that emitted the signal + * @actor: the #ClutterActor attached to the @action + * + * The ::gesture-progress signal is emitted for each motion event after + * the #ClutterGestureAction::gesture-begin signal has been emitted. + * + * Return value: %TRUE if the gesture should continue, and %FALSE if + * the gesture should be cancelled. + * + * Since: 1.8 + */ + gesture_signals[GESTURE_PROGRESS] = + g_signal_new (I_("gesture-progress"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterGestureActionClass, gesture_progress), + _clutter_boolean_continue_accumulator, NULL, + _clutter_marshal_BOOLEAN__OBJECT, + G_TYPE_BOOLEAN, 1, + CLUTTER_TYPE_ACTOR); + + /** + * ClutterGestureAction::gesture-end: + * @action: the #ClutterGestureAction that emitted the signal + * @actor: the #ClutterActor attached to the @action + * + * The ::gesture-end signal is emitted at the end of the gesture gesture, + * when the pointer's button is released + * + * This signal is emitted if and only if the #ClutterGestureAction::gesture-begin + * signal has been emitted first. + * + * Since: 1.8 + */ + gesture_signals[GESTURE_END] = + g_signal_new (I_("gesture-end"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterGestureActionClass, gesture_end), + NULL, NULL, + _clutter_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CLUTTER_TYPE_ACTOR); + + /** + * ClutterGestureAction::gesture-cancel: + * @action: the #ClutterGestureAction that emitted the signal + * @actor: the #ClutterActor attached to the @action + * + * The ::gesture-cancel signal is emitted when the ongoing gesture gets + * cancelled from the #ClutterGestureAction::gesture-progress signal handler. + * + * This signal is emitted if and only if the #ClutterGestureAction::gesture-begin + * signal has been emitted first. + * + * Since: 1.8 + */ + gesture_signals[GESTURE_CANCEL] = + g_signal_new (I_("gesture-cancel"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterGestureActionClass, gesture_cancel), + NULL, NULL, + _clutter_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CLUTTER_TYPE_ACTOR); +} + +static void +clutter_gesture_action_init (ClutterGestureAction *self) +{ + self->priv = clutter_gesture_action_get_instance_private (self); + + self->priv->points = g_array_sized_new (FALSE, TRUE, sizeof (GesturePoint), 3); + g_array_set_clear_func (self->priv->points, (GDestroyNotify) gesture_point_unset); + + self->priv->requested_nb_points = 1; + self->priv->edge = CLUTTER_GESTURE_TRIGGER_EDGE_NONE; +} + +/** + * clutter_gesture_action_new: + * + * Creates a new #ClutterGestureAction instance. + * + * Return value: the newly created #ClutterGestureAction + * + * Since: 1.8 + */ +ClutterAction * +clutter_gesture_action_new (void) +{ + return g_object_new (CLUTTER_TYPE_GESTURE_ACTION, NULL); +} + +/** + * clutter_gesture_action_get_press_coords: + * @action: a #ClutterGestureAction + * @point: the touch point index, with 0 being the first touch + * point received by the action + * @press_x: (out) (allow-none): return location for the press + * event's X coordinate + * @press_y: (out) (allow-none): return location for the press + * event's Y coordinate + * + * Retrieves the coordinates, in stage space, of the press event + * that started the dragging for a specific touch point. + * + * Since: 1.8 + */ +void +clutter_gesture_action_get_press_coords (ClutterGestureAction *action, + guint point, + gfloat *press_x, + gfloat *press_y) +{ + g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action)); + g_return_if_fail (action->priv->points->len > point); + + if (press_x) + *press_x = g_array_index (action->priv->points, + GesturePoint, + point).press_x; + + if (press_y) + *press_y = g_array_index (action->priv->points, + GesturePoint, + point).press_y; +} + +/** + * clutter_gesture_action_get_motion_coords: + * @action: a #ClutterGestureAction + * @point: the touch point index, with 0 being the first touch + * point received by the action + * @motion_x: (out) (allow-none): return location for the latest motion + * event's X coordinate + * @motion_y: (out) (allow-none): return location for the latest motion + * event's Y coordinate + * + * Retrieves the coordinates, in stage space, of the latest motion + * event during the dragging. + * + * Since: 1.8 + */ +void +clutter_gesture_action_get_motion_coords (ClutterGestureAction *action, + guint point, + gfloat *motion_x, + gfloat *motion_y) +{ + g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action)); + g_return_if_fail (action->priv->points->len > point); + + if (motion_x) + *motion_x = g_array_index (action->priv->points, + GesturePoint, + point).last_motion_x; + + if (motion_y) + *motion_y = g_array_index (action->priv->points, + GesturePoint, + point).last_motion_y; +} + +/** + * clutter_gesture_action_get_motion_delta: + * @action: a #ClutterGestureAction + * @point: the touch point index, with 0 being the first touch + * point received by the action + * @delta_x: (out) (allow-none): return location for the X axis + * component of the incremental motion delta + * @delta_y: (out) (allow-none): return location for the Y axis + * component of the incremental motion delta + * + * Retrieves the incremental delta since the last motion event + * during the dragging. + * + * Return value: the distance since last motion event + * + * Since: 1.12 + */ +gfloat +clutter_gesture_action_get_motion_delta (ClutterGestureAction *action, + guint point, + gfloat *delta_x, + gfloat *delta_y) +{ + gfloat d_x, d_y; + + g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), 0); + g_return_val_if_fail (action->priv->points->len > point, 0); + + d_x = g_array_index (action->priv->points, + GesturePoint, + point).last_delta_x; + d_y = g_array_index (action->priv->points, + GesturePoint, + point).last_delta_y; + + if (delta_x) + *delta_x = d_x; + + if (delta_y) + *delta_y = d_y; + + return sqrt ((d_x * d_x) + (d_y * d_y)); +} + +/** + * clutter_gesture_action_get_release_coords: + * @action: a #ClutterGestureAction + * @point: the touch point index, with 0 being the first touch + * point received by the action + * @release_x: (out) (allow-none): return location for the X coordinate of + * the last release + * @release_y: (out) (allow-none): return location for the Y coordinate of + * the last release + * + * Retrieves the coordinates, in stage space, where the touch point was + * last released. + * + * Since: 1.8 + */ +void +clutter_gesture_action_get_release_coords (ClutterGestureAction *action, + guint point, + gfloat *release_x, + gfloat *release_y) +{ + g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action)); + g_return_if_fail (action->priv->points->len > point); + + if (release_x) + *release_x = g_array_index (action->priv->points, + GesturePoint, + point).release_x; + + if (release_y) + *release_y = g_array_index (action->priv->points, + GesturePoint, + point).release_y; +} + +/** + * clutter_gesture_action_get_velocity: + * @action: a #ClutterGestureAction + * @point: the touch point index, with 0 being the first touch + * point received by the action + * @velocity_x: (out) (allow-none): return location for the latest motion + * event's X velocity + * @velocity_y: (out) (allow-none): return location for the latest motion + * event's Y velocity + * + * Retrieves the velocity, in stage pixels per millisecond, of the + * latest motion event during the dragging. + * + * Since: 1.12 + */ +gfloat +clutter_gesture_action_get_velocity (ClutterGestureAction *action, + guint point, + gfloat *velocity_x, + gfloat *velocity_y) +{ + gfloat d_x, d_y, distance, velocity; + gint64 d_t; + + g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), 0); + g_return_val_if_fail (action->priv->points->len > point, 0); + + distance = clutter_gesture_action_get_motion_delta (action, point, + &d_x, &d_y); + + d_t = g_array_index (action->priv->points, + GesturePoint, + point).last_delta_time; + + if (velocity_x) + *velocity_x = d_t > FLOAT_EPSILON ? d_x / d_t : 0; + + if (velocity_y) + *velocity_y = d_t > FLOAT_EPSILON ? d_y / d_t : 0; + + velocity = d_t > FLOAT_EPSILON ? distance / d_t : 0; + return velocity; +} + +/** + * clutter_gesture_action_get_n_touch_points: + * @action: a #ClutterGestureAction + * + * Retrieves the number of requested points to trigger the gesture. + * + * Return value: the number of points to trigger the gesture. + * + * Since: 1.12 + */ +gint +clutter_gesture_action_get_n_touch_points (ClutterGestureAction *action) +{ + g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), 0); + + return action->priv->requested_nb_points; +} + +/** + * clutter_gesture_action_set_n_touch_points: + * @action: a #ClutterGestureAction + * @nb_points: a number of points + * + * Sets the number of points needed to trigger the gesture. + * + * Since: 1.12 + */ +void +clutter_gesture_action_set_n_touch_points (ClutterGestureAction *action, + gint nb_points) +{ + ClutterGestureActionPrivate *priv; + + g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action)); + g_return_if_fail (nb_points >= 1); + + priv = action->priv; + + if (priv->requested_nb_points == nb_points) + return; + + priv->requested_nb_points = nb_points; + + if (priv->in_gesture) + { + if (priv->points->len < priv->requested_nb_points) + cancel_gesture (action); + } + else if (priv->edge == CLUTTER_GESTURE_TRIGGER_EDGE_AFTER) + { + if (priv->points->len >= priv->requested_nb_points) + { + ClutterActor *actor = + clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action)); + gint i; + float threshold_x, threshold_y; + + clutter_gesture_action_get_threshold_trigger_distance (action, &threshold_x, &threshold_y); + + for (i = 0; i < priv->points->len; i++) + { + GesturePoint *point = &g_array_index (priv->points, GesturePoint, i); + + if ((fabsf (point->press_y - point->last_motion_y) >= threshold_y) || + (fabsf (point->press_x - point->last_motion_x) >= threshold_x)) + { + begin_gesture (action, actor); + break; + } + } + } + } + + g_object_notify_by_pspec (G_OBJECT (action), + gesture_props[PROP_N_TOUCH_POINTS]); +} + +/** + * clutter_gesture_action_get_n_current_points: + * @action: a #ClutterGestureAction + * + * Retrieves the number of points currently active. + * + * Return value: the number of points currently active. + * + * Since: 1.12 + */ +guint +clutter_gesture_action_get_n_current_points (ClutterGestureAction *action) +{ + g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), 0); + + return action->priv->points->len; +} + +/** + * clutter_gesture_action_get_sequence: + * @action: a #ClutterGestureAction + * @point: index of a point currently active + * + * Retrieves the #ClutterEventSequence of a touch point. + * + * Return value: (transfer none): the #ClutterEventSequence of a touch point. + * + * Since: 1.12 + */ +ClutterEventSequence * +clutter_gesture_action_get_sequence (ClutterGestureAction *action, + guint point) +{ + g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), NULL); + g_return_val_if_fail (action->priv->points->len > point, NULL); + + return g_array_index (action->priv->points, GesturePoint, point).sequence; +} + +/** + * clutter_gesture_action_get_device: + * @action: a #ClutterGestureAction + * @point: the touch point index, with 0 being the first touch + * point received by the action + * + * Retrieves the #ClutterInputDevice of a touch point. + * + * Return value: (transfer none): the #ClutterInputDevice of a touch point. + * + * Since: 1.12 + */ +ClutterInputDevice * +clutter_gesture_action_get_device (ClutterGestureAction *action, + guint point) +{ + g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), NULL); + g_return_val_if_fail (action->priv->points->len > point, NULL); + + return g_array_index (action->priv->points, GesturePoint, point).device; +} + +/** + * clutter_gesture_action_get_last_event: + * @action: a #ClutterGestureAction + * @point: index of a point currently active + * + * Retrieves a reference to the last #ClutterEvent for a touch point. Call + * clutter_event_copy() if you need to store the reference somewhere. + * + * Return value: (transfer none): the last #ClutterEvent for a touch point. + * + * Since: 1.14 + */ +const ClutterEvent * +clutter_gesture_action_get_last_event (ClutterGestureAction *action, + guint point) +{ + GesturePoint *gesture_point; + + g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), NULL); + g_return_val_if_fail (action->priv->points->len > point, NULL); + + gesture_point = &g_array_index (action->priv->points, GesturePoint, point); + + return gesture_point->last_event; +} + +/** + * clutter_gesture_action_cancel: + * @action: a #ClutterGestureAction + * + * Cancel a #ClutterGestureAction before it begins + * + * Since: 1.12 + */ +void +clutter_gesture_action_cancel (ClutterGestureAction *action) +{ + g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action)); + + cancel_gesture (action); +} + +/** + * clutter_gesture_action_set_threshold_trigger_edge: + * @action: a #ClutterGestureAction + * @edge: the %ClutterGestureTriggerEdge + * + * Sets the edge trigger for the gesture drag threshold, if any. + * + * This function should only be called by sub-classes of + * #ClutterGestureAction during their construction phase. + * + * Since: 1.18 + */ +void +clutter_gesture_action_set_threshold_trigger_edge (ClutterGestureAction *action, + ClutterGestureTriggerEdge edge) +{ + g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action)); + + if (action->priv->edge == edge) + return; + + action->priv->edge = edge; + + g_object_notify_by_pspec (G_OBJECT (action), gesture_props[PROP_THRESHOLD_TRIGGER_EDGE]); +} + +/** + * clutter_gesture_action_get_threshold_trigger_edge: + * @action: a #ClutterGestureAction + * + * Retrieves the edge trigger of the gesture @action, as set using + * clutter_gesture_action_set_threshold_trigger_edge(). + * + * Return value: the edge trigger + * + * Since: 1.20 + */ +ClutterGestureTriggerEdge +clutter_gesture_action_get_threshold_trigger_edge (ClutterGestureAction *action) +{ + g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), + CLUTTER_GESTURE_TRIGGER_EDGE_NONE); + + return action->priv->edge; +} + +/** + * clutter_gesture_action_get_threshold_trigger_egde: + * @action: a #ClutterGestureAction + * + * Retrieves the edge trigger of the gesture @action, as set using + * clutter_gesture_action_set_threshold_trigger_edge(). + * + * Return value: the edge trigger + * + * Since: 1.18 + * + * Deprecated: 1.20: Use clutter_gesture_action_get_threshold_trigger_edge() instead. + */ +ClutterGestureTriggerEdge +clutter_gesture_action_get_threshold_trigger_egde (ClutterGestureAction *action) +{ + return clutter_gesture_action_get_threshold_trigger_edge (action); +} + +/** + * clutter_gesture_action_set_threshold_trigger_distance: + * @action: a #ClutterGestureAction + * @x: the distance on the horizontal axis + * @y: the distance on the vertical axis + * + * Sets the threshold trigger distance for the gesture drag threshold, if any. + * + * This function should only be called by sub-classes of + * #ClutterGestureAction during their construction phase. + * + * Since: 1.18 + */ +void +clutter_gesture_action_set_threshold_trigger_distance (ClutterGestureAction *action, + float x, + float y) +{ + g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action)); + + if (fabsf (x - action->priv->distance_x) > FLOAT_EPSILON) + { + action->priv->distance_x = x; + g_object_notify_by_pspec (G_OBJECT (action), gesture_props[PROP_THRESHOLD_TRIGGER_DISTANCE_X]); + } + + if (fabsf (y - action->priv->distance_y) > FLOAT_EPSILON) + { + action->priv->distance_y = y; + g_object_notify_by_pspec (G_OBJECT (action), gesture_props[PROP_THRESHOLD_TRIGGER_DISTANCE_Y]); + } +} + +/** + * clutter_gesture_action_get_threshold_trigger_distance: + * @action: a #ClutterGestureAction + * @x: (out) (allow-none): The return location for the horizontal distance, or %NULL + * @y: (out) (allow-none): The return location for the vertical distance, or %NULL + * + * Retrieves the threshold trigger distance of the gesture @action, + * as set using clutter_gesture_action_set_threshold_trigger_distance(). + * + * Since: 1.18 + */ +void +clutter_gesture_action_get_threshold_trigger_distance (ClutterGestureAction *action, + float *x, + float *y) +{ + g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action)); + + if (x != NULL) + { + if (action->priv->distance_x > 0.0) + *x = action->priv->distance_x; + else + *x = gesture_get_default_threshold (); + } + if (y != NULL) + { + if (action->priv->distance_y > 0.0) + *y = action->priv->distance_y; + else + *y = gesture_get_default_threshold (); + } +} diff --git a/clutter/clutter/clutter-gesture-action.h b/clutter/clutter/clutter-gesture-action.h new file mode 100644 index 0000000..46d3c45 --- /dev/null +++ b/clutter/clutter/clutter-gesture-action.h @@ -0,0 +1,179 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * Copyright (C) 2011 Robert Bosch Car Multimedia GmbH. + * + * 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 . + * + * Author: + * Tomeu Vizoso + */ + +#ifndef __CLUTTER_GESTURE_ACTION_H__ +#define __CLUTTER_GESTURE_ACTION_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_GESTURE_ACTION (clutter_gesture_action_get_type ()) +#define CLUTTER_GESTURE_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_GESTURE_ACTION, ClutterGestureAction)) +#define CLUTTER_IS_GESTURE_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_GESTURE_ACTION)) +#define CLUTTER_GESTURE_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_GESTURE_ACTION, ClutterGestureActionClass)) +#define CLUTTER_IS_GESTURE_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_GESTURE_ACTION)) +#define CLUTTER_GESTURE_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_GESTURE_ACTION, ClutterGestureActionClass)) + +typedef struct _ClutterGestureAction ClutterGestureAction; +typedef struct _ClutterGestureActionPrivate ClutterGestureActionPrivate; +typedef struct _ClutterGestureActionClass ClutterGestureActionClass; + +/** + * ClutterGestureAction: + * + * The #ClutterGestureAction structure contains + * only private data and should be accessed using the provided API + * + * Since: 1.8 + */ +struct _ClutterGestureAction +{ + /*< private >*/ + ClutterAction parent_instance; + + ClutterGestureActionPrivate *priv; +}; + +/** + * ClutterGestureActionClass: + * @gesture_begin: class handler for the #ClutterGestureAction::gesture-begin signal + * @gesture_progress: class handler for the #ClutterGestureAction::gesture-progress signal + * @gesture_end: class handler for the #ClutterGestureAction::gesture-end signal + * @gesture_cancel: class handler for the #ClutterGestureAction::gesture-cancel signal + * @gesture_prepare: virtual function called before emitting the + * #ClutterGestureAction::gesture-cancel signal + * + * The #ClutterGestureClass structure contains only + * private data. + * + * Since: 1.8 + */ +struct _ClutterGestureActionClass +{ + /*< private >*/ + ClutterActionClass parent_class; + + /*< public >*/ + gboolean (* gesture_begin) (ClutterGestureAction *action, + ClutterActor *actor); + gboolean (* gesture_progress) (ClutterGestureAction *action, + ClutterActor *actor); + void (* gesture_end) (ClutterGestureAction *action, + ClutterActor *actor); + void (* gesture_cancel) (ClutterGestureAction *action, + ClutterActor *actor); + gboolean (* gesture_prepare) (ClutterGestureAction *action, + ClutterActor *actor); + + /*< private >*/ + void (* _clutter_gesture_action1) (void); + void (* _clutter_gesture_action2) (void); + void (* _clutter_gesture_action3) (void); + void (* _clutter_gesture_action4) (void); + void (* _clutter_gesture_action5) (void); + void (* _clutter_gesture_action6) (void); +}; + +CLUTTER_AVAILABLE_IN_1_8 +GType clutter_gesture_action_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_8 +ClutterAction * clutter_gesture_action_new (void); + +CLUTTER_AVAILABLE_IN_1_8 +gint clutter_gesture_action_get_n_touch_points (ClutterGestureAction *action); +CLUTTER_AVAILABLE_IN_1_8 +void clutter_gesture_action_set_n_touch_points (ClutterGestureAction *action, + gint nb_points); +CLUTTER_AVAILABLE_IN_1_8 +void clutter_gesture_action_get_press_coords (ClutterGestureAction *action, + guint point, + gfloat *press_x, + gfloat *press_y); +CLUTTER_AVAILABLE_IN_1_8 +void clutter_gesture_action_get_motion_coords (ClutterGestureAction *action, + guint point, + gfloat *motion_x, + gfloat *motion_y); +CLUTTER_AVAILABLE_IN_1_12 +gfloat clutter_gesture_action_get_motion_delta (ClutterGestureAction *action, + guint point, + gfloat *delta_x, + gfloat *delta_y); +CLUTTER_AVAILABLE_IN_1_8 +void clutter_gesture_action_get_release_coords (ClutterGestureAction *action, + guint point, + gfloat *release_x, + gfloat *release_y); +CLUTTER_AVAILABLE_IN_1_12 +gfloat clutter_gesture_action_get_velocity (ClutterGestureAction *action, + guint point, + gfloat *velocity_x, + gfloat *velocity_y); + +CLUTTER_AVAILABLE_IN_1_12 +guint clutter_gesture_action_get_n_current_points (ClutterGestureAction *action); + +CLUTTER_AVAILABLE_IN_1_12 +ClutterEventSequence * clutter_gesture_action_get_sequence (ClutterGestureAction *action, + guint point); + +CLUTTER_AVAILABLE_IN_1_12 +ClutterInputDevice * clutter_gesture_action_get_device (ClutterGestureAction *action, + guint point); + +CLUTTER_AVAILABLE_IN_1_14 +const ClutterEvent * clutter_gesture_action_get_last_event (ClutterGestureAction *action, + guint point); + +CLUTTER_AVAILABLE_IN_1_12 +void clutter_gesture_action_cancel (ClutterGestureAction *action); + +CLUTTER_AVAILABLE_IN_1_18 +void clutter_gesture_action_set_threshold_trigger_edge (ClutterGestureAction *action, + ClutterGestureTriggerEdge edge); +CLUTTER_DEPRECATED_IN_1_20_FOR(clutter_gesture_action_get_threshold_trigger_edge) +ClutterGestureTriggerEdge clutter_gesture_action_get_threshold_trigger_egde (ClutterGestureAction *action); +CLUTTER_AVAILABLE_IN_1_20 +ClutterGestureTriggerEdge clutter_gesture_action_get_threshold_trigger_edge (ClutterGestureAction *action); + +CLUTTER_AVAILABLE_IN_1_18 +void clutter_gesture_action_set_threshold_trigger_distance (ClutterGestureAction *action, + float x, + float y); + +CLUTTER_AVAILABLE_IN_1_18 +void clutter_gesture_action_get_threshold_trigger_distance (ClutterGestureAction *action, + float *x, + float *y); + +G_END_DECLS + +#endif /* __CLUTTER_GESTURE_ACTION_H__ */ diff --git a/clutter/clutter/clutter-grid-layout.c b/clutter/clutter/clutter-grid-layout.c new file mode 100644 index 0000000..069ccb6 --- /dev/null +++ b/clutter/clutter/clutter-grid-layout.c @@ -0,0 +1,2206 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Red Hat, Inc. + * Copyright (C) 2012 Bastian Winkler + * + * 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 . + * + * Author: + * Bastian Winkler + * + * Based on GtkGrid widget by: + * Matthias Clasen + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include +#include + +#include "clutter-grid-layout.h" + +#include "clutter-actor-private.h" +#include "clutter-container.h" +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-layout-meta.h" +#include "clutter-private.h" + +/** + * SECTION:clutter-grid-layout + * @Short_description: A layout manager for a grid of actors + * @Title: ClutterGridLayout + * @See_also: #ClutterTableLayout, #ClutterBoxLayout + * + * #ClutterGridLayout is a layout manager which arranges its child widgets in + * rows and columns. It is a very similar to #ClutterTableLayout and + * #ClutterBoxLayout, but it consistently uses #ClutterActor's + * alignment and expansion flags instead of custom child properties. + * + * Children are added using clutter_grid_layout_attach(). They can span + * multiple rows or columns. It is also possible to add a child next to an + * existing child, using clutter_grid_layout_attach_next_to(). The behaviour of + * #ClutterGridLayout when several children occupy the same grid cell is undefined. + * + * #ClutterGridLayout can be used like a #ClutterBoxLayout by just using + * clutter_actor_add_child(), which will place children next to each other in + * the direction determined by the #ClutterGridLayout:orientation property. + */ + +#define CLUTTER_TYPE_GRID_CHILD (clutter_grid_child_get_type ()) +#define CLUTTER_GRID_CHILD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_GRID_CHILD, ClutterGridChild)) +#define CLUTTER_IS_GRID_CHILD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_GRID_CHILD)) + +typedef struct _ClutterGridChild ClutterGridChild; +typedef struct _ClutterLayoutMetaClass ClutterGridChildClass; + +typedef struct _ClutterGridAttach ClutterGridAttach; +typedef struct _ClutterGridLine ClutterGridLine; +typedef struct _ClutterGridLines ClutterGridLines; +typedef struct _ClutterGridLineData ClutterGridLineData; +typedef struct _ClutterGridRequest ClutterGridRequest; + + +struct _ClutterGridAttach +{ + gint pos; + gint span; +}; + +struct _ClutterGridChild +{ + ClutterLayoutMeta parent_instance; + + ClutterGridAttach attach[2]; +}; + +#define CHILD_LEFT(child) ((child)->attach[CLUTTER_ORIENTATION_HORIZONTAL].pos) +#define CHILD_WIDTH(child) ((child)->attach[CLUTTER_ORIENTATION_HORIZONTAL].span) +#define CHILD_TOP(child) ((child)->attach[CLUTTER_ORIENTATION_VERTICAL].pos) +#define CHILD_HEIGHT(child) ((child)->attach[CLUTTER_ORIENTATION_VERTICAL].span) + +/* A ClutterGridLineData struct contains row/column specific parts + * of the grid. + */ +struct _ClutterGridLineData +{ + gfloat spacing; + guint homogeneous : 1; +}; + +struct _ClutterGridLayoutPrivate +{ + ClutterContainer *container; + ClutterOrientation orientation; + + ClutterGridLineData linedata[2]; +}; + +#define ROWS(priv) (&(priv)->linedata[CLUTTER_ORIENTATION_HORIZONTAL]) +#define COLUMNS(priv) (&(priv)->linedata[CLUTTER_ORIENTATION_VERTICAL]) + +/* A ClutterGridLine struct represents a single row or column + * during size requests + */ +struct _ClutterGridLine +{ + gfloat minimum; + gfloat natural; + gfloat position; + gfloat allocation; + + guint need_expand : 1; + guint expand : 1; + guint empty : 1; +}; + +struct _ClutterGridLines +{ + ClutterGridLine *lines; + gint min, max; +}; + +struct _ClutterGridRequest +{ + ClutterGridLayout *grid; + ClutterGridLines lines[2]; +}; + +enum +{ + PROP_0, + + PROP_ORIENTATION, + PROP_ROW_SPACING, + PROP_COLUMN_SPACING, + PROP_ROW_HOMOGENEOUS, + PROP_COLUMN_HOMOGENEOUS, + + PROP_LAST +}; +static GParamSpec *obj_props[PROP_LAST]; + +enum +{ + PROP_CHILD_0, + + PROP_CHILD_LEFT_ATTACH, + PROP_CHILD_TOP_ATTACH, + PROP_CHILD_WIDTH, + PROP_CHILD_HEIGHT, + + PROP_CHILD_LAST +}; +static GParamSpec *child_props[PROP_CHILD_LAST]; + +GType clutter_grid_child_get_type (void); + +G_DEFINE_TYPE (ClutterGridChild, clutter_grid_child, + CLUTTER_TYPE_LAYOUT_META) + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterGridLayout, + clutter_grid_layout, + CLUTTER_TYPE_LAYOUT_MANAGER) + + +#define GET_GRID_CHILD(grid, child) \ + (CLUTTER_GRID_CHILD(clutter_layout_manager_get_child_meta \ + (CLUTTER_LAYOUT_MANAGER((grid)),\ + CLUTTER_GRID_LAYOUT((grid))->priv->container,(child)))) + +static void +grid_attach (ClutterGridLayout *self, + ClutterActor *actor, + gint left, + gint top, + gint width, + gint height) +{ + ClutterGridChild *grid_child; + + grid_child = GET_GRID_CHILD (self, actor); + + CHILD_LEFT (grid_child) = left; + CHILD_TOP (grid_child) = top; + CHILD_WIDTH (grid_child) = width; + CHILD_HEIGHT (grid_child) = height; +} + +/* Find the position 'touching' existing + * children. @orientation and @max determine + * from which direction to approach (horizontal + * + max = right, vertical + !max = top, etc). + * @op_pos, @op_span determine the rows/columns + * in which the touching has to happen. + */ +static gint +find_attach_position (ClutterGridLayout *self, + ClutterOrientation orientation, + gint op_pos, + gint op_span, + gboolean max) +{ + ClutterGridLayoutPrivate *priv = self->priv; + ClutterGridChild *grid_child; + ClutterGridAttach *attach; + ClutterGridAttach *opposite; + ClutterActorIter iter; + ClutterActor *child; + gint pos; + gboolean hit; + + if (max) + pos = -G_MAXINT; + else + pos = G_MAXINT; + + hit = FALSE; + + if (!priv->container) + return -1; + + clutter_actor_iter_init (&iter, CLUTTER_ACTOR (priv->container)); + while (clutter_actor_iter_next (&iter, &child)) + { + grid_child = GET_GRID_CHILD (self, child); + + attach = &grid_child->attach[orientation]; + opposite = &grid_child->attach[1 - orientation]; + + /* check if the ranges overlap */ + if (opposite->pos <= op_pos + op_span && op_pos <= opposite->pos + opposite->span) + { + hit = TRUE; + + if (max) + pos = MAX (pos, attach->pos + attach->span); + else + pos = MIN (pos, attach->pos); + } + } + + if (!hit) + pos = 0; + + return pos; +} +static void +grid_attach_next_to (ClutterGridLayout *layout, + ClutterActor *child, + ClutterActor *sibling, + ClutterGridPosition side, + gint width, + gint height) +{ + ClutterGridChild *grid_sibling; + gint left, top; + + if (sibling) + { + grid_sibling = GET_GRID_CHILD (layout, sibling); + + switch (side) + { + case CLUTTER_GRID_POSITION_LEFT: + left = CHILD_LEFT (grid_sibling) - width; + top = CHILD_TOP (grid_sibling); + break; + + case CLUTTER_GRID_POSITION_RIGHT: + left = CHILD_LEFT (grid_sibling) + CHILD_WIDTH (grid_sibling); + top = CHILD_TOP (grid_sibling); + break; + + case CLUTTER_GRID_POSITION_TOP: + left = CHILD_LEFT (grid_sibling); + top = CHILD_TOP (grid_sibling) - height; + break; + + case CLUTTER_GRID_POSITION_BOTTOM: + left = CHILD_LEFT (grid_sibling); + top = CHILD_TOP (grid_sibling) + CHILD_HEIGHT (grid_sibling); + break; + + default: + g_assert_not_reached (); + } + } + else + { + switch (side) + { + case CLUTTER_GRID_POSITION_LEFT: + left = find_attach_position (layout, CLUTTER_ORIENTATION_HORIZONTAL, + 0, height, FALSE); + left -= width; + top = 0; + break; + + case CLUTTER_GRID_POSITION_RIGHT: + left = find_attach_position (layout, CLUTTER_ORIENTATION_HORIZONTAL, + 0, height, TRUE); + top = 0; + break; + + case CLUTTER_GRID_POSITION_TOP: + left = 0; + top = find_attach_position (layout, CLUTTER_ORIENTATION_VERTICAL, + 0, width, FALSE); + top -= height; + break; + + case CLUTTER_GRID_POSITION_BOTTOM: + left = 0; + top = find_attach_position (layout, CLUTTER_ORIENTATION_VERTICAL, + 0, width, TRUE); + break; + + default: + g_assert_not_reached (); + } + } + + grid_attach (layout, child, left, top, width, height); +} + +static void +clutter_grid_request_update_child_attach (ClutterGridRequest *request, + ClutterActor *actor) +{ + ClutterGridLayoutPrivate *priv = request->grid->priv; + ClutterGridChild *grid_child; + + grid_child = GET_GRID_CHILD (request->grid, actor); + + if (CHILD_LEFT (grid_child) == -1 || CHILD_TOP (grid_child) == -1) + { + ClutterGridPosition side; + ClutterActor *sibling; + + if (priv->orientation == CLUTTER_ORIENTATION_HORIZONTAL) + { + ClutterTextDirection td; + gboolean rtl; + ClutterActor *container = CLUTTER_ACTOR (priv->container); + + td = clutter_actor_get_text_direction (container); + rtl = (td == CLUTTER_TEXT_DIRECTION_RTL) ? TRUE : FALSE; + side = rtl ? CLUTTER_GRID_POSITION_LEFT : CLUTTER_GRID_POSITION_RIGHT; + } + else + { + /* XXX: maybe we should also add a :pack-start property to modify + * this */ + side = CLUTTER_GRID_POSITION_BOTTOM; + } + + sibling = clutter_actor_get_previous_sibling (actor); + if (sibling) + clutter_grid_layout_insert_next_to (request->grid, sibling, side); + grid_attach_next_to (request->grid, actor, sibling, side, + CHILD_WIDTH (grid_child), + CHILD_HEIGHT (grid_child)); + } +} + +static void +clutter_grid_request_update_attach (ClutterGridRequest *request) +{ + ClutterGridLayoutPrivate *priv = request->grid->priv; + ClutterActorIter iter; + ClutterActor *child; + + clutter_actor_iter_init (&iter, CLUTTER_ACTOR (priv->container)); + while (clutter_actor_iter_next (&iter, &child)) + clutter_grid_request_update_child_attach (request, child); +} + +/* Calculates the min and max numbers for both orientations. + */ +static void +clutter_grid_request_count_lines (ClutterGridRequest *request) +{ + ClutterGridLayoutPrivate *priv = request->grid->priv; + ClutterGridChild *grid_child; + ClutterGridAttach *attach; + ClutterActorIter iter; + ClutterActor *child; + gint min[2]; + gint max[2]; + + min[0] = min[1] = G_MAXINT; + max[0] = max[1] = G_MININT; + + clutter_actor_iter_init (&iter, CLUTTER_ACTOR (priv->container)); + while (clutter_actor_iter_next (&iter, &child)) + { + grid_child = GET_GRID_CHILD (request->grid, child); + attach = grid_child->attach; + + min[0] = MIN (min[0], attach[0].pos); + max[0] = MAX (max[0], attach[0].pos + attach[0].span); + min[1] = MIN (min[1], attach[1].pos); + max[1] = MAX (max[1], attach[1].pos + attach[1].span); + } + + request->lines[0].min = min[0]; + request->lines[0].max = max[0]; + request->lines[1].min = min[1]; + request->lines[1].max = max[1]; +} + +/* Sets line sizes to 0 and marks lines as expand + * if they have a non-spanning expanding child. + */ +static void +clutter_grid_request_init (ClutterGridRequest *request, + ClutterOrientation orientation) +{ + ClutterGridLayoutPrivate *priv = request->grid->priv; + ClutterGridChild *grid_child; + ClutterGridAttach *attach; + ClutterGridLines *lines; + ClutterActorIter iter; + ClutterActor *child; + gint i; + + lines = &request->lines[orientation]; + + for (i = 0; i < lines->max - lines->min; i++) + { + lines->lines[i].minimum = 0; + lines->lines[i].natural = 0; + lines->lines[i].expand = FALSE; + } + + clutter_actor_iter_init (&iter, CLUTTER_ACTOR (priv->container)); + while (clutter_actor_iter_next (&iter, &child)) + { + grid_child = GET_GRID_CHILD (request->grid, child); + attach = &grid_child->attach[orientation]; + if (attach->span == 1 && clutter_actor_needs_expand (child, orientation)) + lines->lines[attach->pos - lines->min].expand = TRUE; + } +} + +/* Sums allocations for lines spanned by child and their spacing. + */ +static gfloat +compute_allocation_for_child (ClutterGridRequest *request, + ClutterActor *child, + ClutterOrientation orientation) +{ + ClutterGridLayoutPrivate *priv = request->grid->priv; + ClutterGridChild *grid_child; + ClutterGridLineData *linedata; + ClutterGridLines *lines; + ClutterGridLine *line; + ClutterGridAttach *attach; + gfloat size; + gint i; + + grid_child = GET_GRID_CHILD (request->grid, child); + linedata = &priv->linedata[orientation]; + lines = &request->lines[orientation]; + attach = &grid_child->attach[orientation]; + + size = (attach->span - 1) * linedata->spacing; + for (i = 0; i < attach->span; i++) + { + line = &lines->lines[attach->pos - lines->min + i]; + size += line->allocation; + } + + return size; +} + +static void +compute_request_for_child (ClutterGridRequest *request, + ClutterActor *child, + ClutterOrientation orientation, + gboolean contextual, + gfloat *minimum, + gfloat *natural) +{ + if (contextual) + { + gfloat size; + + size = compute_allocation_for_child (request, child, 1 - orientation); + if (orientation == CLUTTER_ORIENTATION_HORIZONTAL) + clutter_actor_get_preferred_width (child, size, minimum, natural); + else + clutter_actor_get_preferred_height (child, size, minimum, natural); + } + else + { + if (orientation == CLUTTER_ORIENTATION_HORIZONTAL) + clutter_actor_get_preferred_width (child, -1, minimum, natural); + else + clutter_actor_get_preferred_height (child, -1, minimum, natural); + } +} + +/* Sets requisition to max. of non-spanning children. + * If contextual is TRUE, requires allocations of + * lines in the opposite orientation to be set. + */ +static void +clutter_grid_request_non_spanning (ClutterGridRequest *request, + ClutterOrientation orientation, + gboolean contextual) +{ + ClutterGridLayoutPrivate *priv = request->grid->priv; + ClutterGridChild *grid_child; + ClutterGridAttach *attach; + ClutterGridLines *lines; + ClutterGridLine *line; + ClutterActorIter iter; + ClutterActor *child; + gfloat minimum; + gfloat natural; + + lines = &request->lines[orientation]; + + clutter_actor_iter_init (&iter, CLUTTER_ACTOR (priv->container)); + while (clutter_actor_iter_next (&iter, &child)) + { + if (!clutter_actor_is_visible (child)) + continue; + + grid_child = GET_GRID_CHILD (request->grid, child); + + attach = &grid_child->attach[orientation]; + if (attach->span != 1) + continue; + + compute_request_for_child (request, child, orientation, contextual, &minimum, &natural); + + line = &lines->lines[attach->pos - lines->min]; + line->minimum = MAX (line->minimum, minimum); + line->natural = MAX (line->natural, natural); + } +} + +/* Enforce homogeneous sizes. + */ +static void +clutter_grid_request_homogeneous (ClutterGridRequest *request, + ClutterOrientation orientation) +{ + ClutterGridLayoutPrivate *priv = request->grid->priv; + ClutterGridLineData *linedata; + ClutterGridLines *lines; + gfloat minimum, natural; + gint i; + + linedata = &priv->linedata[orientation]; + lines = &request->lines[orientation]; + + if (!linedata->homogeneous) + return; + + minimum = 0.0f; + natural = 0.0f; + + for (i = 0; i < lines->max - lines->min; i++) + { + minimum = MAX (minimum, lines->lines[i].minimum); + natural = MAX (natural, lines->lines[i].natural); + } + + for (i = 0; i < lines->max - lines->min; i++) + { + lines->lines[i].minimum = minimum; + lines->lines[i].natural = natural; + } +} + +/* Deals with spanning children. + * Requires expand fields of lines to be set for + * non-spanning children. + */ +static void +clutter_grid_request_spanning (ClutterGridRequest *request, + ClutterOrientation orientation, + gboolean contextual) +{ + ClutterGridLayoutPrivate *priv = request->grid->priv; + ClutterGridChild *grid_child; + ClutterActor *child; + ClutterActorIter iter; + ClutterGridAttach *attach; + ClutterGridLineData *linedata; + ClutterGridLines *lines; + ClutterGridLine *line; + gfloat minimum; + gfloat natural; + gint span_minimum; + gint span_natural; + gint span_expand; + gboolean force_expand; + gint extra; + gint expand; + gint line_extra; + gint i; + + linedata = &priv->linedata[orientation]; + lines = &request->lines[orientation]; + + clutter_actor_iter_init (&iter, CLUTTER_ACTOR (priv->container)); + while (clutter_actor_iter_next (&iter, &child)) + { + if (!clutter_actor_is_visible (child)) + continue; + + grid_child = GET_GRID_CHILD (request->grid, child); + + attach = &grid_child->attach[orientation]; + if (attach->span == 1) + continue; + + compute_request_for_child (request, child, orientation, contextual, + &minimum, &natural); + + span_minimum = (attach->span - 1) * linedata->spacing; + span_natural = (attach->span - 1) * linedata->spacing; + span_expand = 0; + force_expand = FALSE; + for (i = 0; i < attach->span; i++) + { + line = &lines->lines[attach->pos - lines->min + i]; + span_minimum += line->minimum; + span_natural += line->natural; + if (line->expand) + span_expand += 1; + } + if (span_expand == 0) + { + span_expand = attach->span; + force_expand = TRUE; + } + + /* If we need to request more space for this child to fill + * its requisition, then divide up the needed space amongst the + * lines it spans, favoring expandable lines if any. + * + * When doing homogeneous allocation though, try to keep the + * line allocations even, since we're going to force them to + * be the same anyway, and we don't want to introduce unnecessary + * extra space. + */ + if (span_minimum < minimum) + { + if (linedata->homogeneous) + { + gint total, m; + + total = minimum - (attach->span - 1) * linedata->spacing; + m = total / attach->span + (total % attach->span ? 1 : 0); + for (i = 0; i < attach->span; i++) + { + line = &lines->lines[attach->pos - lines->min + i]; + line->minimum = MAX(line->minimum, m); + } + } + else + { + extra = minimum - span_minimum; + expand = span_expand; + for (i = 0; i < attach->span; i++) + { + line = &lines->lines[attach->pos - lines->min + i]; + if (force_expand || line->expand) + { + line_extra = extra / expand; + line->minimum += line_extra; + extra -= line_extra; + expand -= 1; + } + } + } + } + + if (span_natural < natural) + { + if (linedata->homogeneous) + { + gint total, n; + + total = natural - (attach->span - 1) * linedata->spacing; + n = total / attach->span + (total % attach->span ? 1 : 0); + for (i = 0; i < attach->span; i++) + { + line = &lines->lines[attach->pos - lines->min + i]; + line->natural = MAX(line->natural, n); + } + } + else + { + extra = natural - span_natural; + expand = span_expand; + for (i = 0; i < attach->span; i++) + { + line = &lines->lines[attach->pos - lines->min + i]; + if (force_expand || line->expand) + { + line_extra = extra / expand; + line->natural += line_extra; + extra -= line_extra; + expand -= 1; + } + } + } + } + } +} + +/* Marks empty and expanding lines and counts them. + */ +static void +clutter_grid_request_compute_expand (ClutterGridRequest *request, + ClutterOrientation orientation, + gint *nonempty_lines, + gint *expand_lines) +{ + ClutterGridLayoutPrivate *priv = request->grid->priv; + ClutterGridChild *grid_child; + ClutterGridAttach *attach; + ClutterActorIter iter; + ClutterActor *child; + gint i; + ClutterGridLines *lines; + ClutterGridLine *line; + gboolean has_expand; + gint expand; + gint empty; + + lines = &request->lines[orientation]; + + for (i = 0; i < lines->max - lines->min; i++) + { + lines->lines[i].need_expand = FALSE; + lines->lines[i].expand = FALSE; + lines->lines[i].empty = TRUE; + } + + clutter_actor_iter_init (&iter, CLUTTER_ACTOR (priv->container)); + while (clutter_actor_iter_next (&iter, &child)) + { + if (!clutter_actor_is_visible (child)) + continue; + + grid_child = GET_GRID_CHILD (request->grid, child); + + attach = &grid_child->attach[orientation]; + if (attach->span != 1) + continue; + + line = &lines->lines[attach->pos - lines->min]; + line->empty = FALSE; + if (clutter_actor_needs_expand (child, orientation)) + line->expand = TRUE; + } + + + clutter_actor_iter_init (&iter, CLUTTER_ACTOR (priv->container)); + while (clutter_actor_iter_next (&iter, &child)) + { + if (!clutter_actor_is_visible (child)) + continue; + + grid_child = GET_GRID_CHILD (request->grid, child); + + attach = &grid_child->attach[orientation]; + if (attach->span == 1) + continue; + + has_expand = FALSE; + for (i = 0; i < attach->span; i++) + { + line = &lines->lines[attach->pos - lines->min + i]; + line->empty = FALSE; + if (line->expand) + has_expand = TRUE; + } + + if (!has_expand && clutter_actor_needs_expand (child, orientation)) + { + for (i = 0; i < attach->span; i++) + { + line = &lines->lines[attach->pos - lines->min + i]; + line->need_expand = TRUE; + } + } + } + + empty = 0; + expand = 0; + for (i = 0; i < lines->max - lines->min; i++) + { + line = &lines->lines[i]; + + if (line->need_expand) + line->expand = TRUE; + + if (line->empty) + empty += 1; + + if (line->expand) + expand += 1; + } + + if (nonempty_lines) + *nonempty_lines = lines->max - lines->min - empty; + + if (expand_lines) + *expand_lines = expand; +} + +/* Sums the minimum and natural fields of lines and their spacing. + */ +static void +clutter_grid_request_sum (ClutterGridRequest *request, + ClutterOrientation orientation, + gfloat *minimum, + gfloat *natural) +{ + ClutterGridLayoutPrivate *priv = request->grid->priv; + ClutterGridLineData *linedata; + ClutterGridLines *lines; + gint i; + gfloat min, nat; + gint nonempty; + + clutter_grid_request_compute_expand (request, orientation, &nonempty, NULL); + + linedata = &priv->linedata[orientation]; + lines = &request->lines[orientation]; + + min = 0; + nat = 0; + if (nonempty > 0) + { + min = (nonempty - 1) * linedata->spacing; + nat = (nonempty - 1) * linedata->spacing; + } + + for (i = 0; i < lines->max - lines->min; i++) + { + min += lines->lines[i].minimum; + nat += lines->lines[i].natural; + } + + if (minimum) + *minimum = min; + + if (natural) + *natural = nat; +} + +/* Computes minimum and natural fields of lines. + * When contextual is TRUE, requires allocation of + * lines in the opposite orientation to be set. + */ +static void +clutter_grid_request_run (ClutterGridRequest *request, + ClutterOrientation orientation, + gboolean contextual) +{ + clutter_grid_request_init (request, orientation); + clutter_grid_request_non_spanning (request, orientation, contextual); + clutter_grid_request_homogeneous (request, orientation); + clutter_grid_request_spanning (request, orientation, contextual); + clutter_grid_request_homogeneous (request, orientation); +} + +typedef struct _RequestedSize +{ + gpointer data; + + gfloat minimum_size; + gfloat natural_size; +} RequestedSize; + + +/* Pulled from gtksizerequest.c from Gtk+ */ +static gint +compare_gap (gconstpointer p1, + gconstpointer p2, + gpointer data) +{ + RequestedSize *sizes = data; + const guint *c1 = p1; + const guint *c2 = p2; + + const gint d1 = MAX (sizes[*c1].natural_size - + sizes[*c1].minimum_size, + 0); + const gint d2 = MAX (sizes[*c2].natural_size - + sizes[*c2].minimum_size, + 0); + + gint delta = (d2 - d1); + + if (0 == delta) + delta = (*c2 - *c1); + + return delta; +} + +/* + * distribute_natural_allocation: + * @extra_space: Extra space to redistribute among children after subtracting + * minimum sizes and any child padding from the overall allocation + * @n_requested_sizes: Number of requests to fit into the allocation + * @sizes: An array of structs with a client pointer and a minimum/natural size + * in the orientation of the allocation. + * + * Distributes @extra_space to child @sizes by bringing smaller + * children up to natural size first. + * + * The remaining space will be added to the @minimum_size member of the + * RequestedSize struct. If all sizes reach their natural size then + * the remaining space is returned. + * + * Returns: The remainder of @extra_space after redistributing space + * to @sizes. + * + * Pulled from gtksizerequest.c from Gtk+ + */ +static gint +distribute_natural_allocation (gint extra_space, + guint n_requested_sizes, + RequestedSize *sizes) +{ + guint *spreading; + gint i; + + g_return_val_if_fail (extra_space >= 0, 0); + + spreading = g_newa (guint, n_requested_sizes); + + for (i = 0; i < n_requested_sizes; i++) + spreading[i] = i; + + /* Distribute the container's extra space c_gap. We want to assign + * this space such that the sum of extra space assigned to children + * (c^i_gap) is equal to c_cap. The case that there's not enough + * space for all children to take their natural size needs some + * attention. The goals we want to achieve are: + * + * a) Maximize number of children taking their natural size. + * b) The allocated size of children should be a continuous + * function of c_gap. That is, increasing the container size by + * one pixel should never make drastic changes in the distribution. + * c) If child i takes its natural size and child j doesn't, + * child j should have received at least as much gap as child i. + * + * The following code distributes the additional space by following + * these rules. + */ + + /* Sort descending by gap and position. */ + g_qsort_with_data (spreading, + n_requested_sizes, sizeof (guint), + compare_gap, sizes); + + /* Distribute available space. + * This master piece of a loop was conceived by Behdad Esfahbod. + */ + for (i = n_requested_sizes - 1; extra_space > 0 && i >= 0; --i) + { + /* Divide remaining space by number of remaining children. + * Sort order and reducing remaining space by assigned space + * ensures that space is distributed equally. + */ + gint glue = (extra_space + i) / (i + 1); + gint gap = sizes[(spreading[i])].natural_size + - sizes[(spreading[i])].minimum_size; + + gint extra = MIN (glue, gap); + + sizes[spreading[i]].minimum_size += extra; + + extra_space -= extra; + } + + return extra_space; +} + +/* Requires that the minimum and natural fields of lines + * have been set, computes the allocation field of lines + * by distributing total_size among lines. + */ +static void +clutter_grid_request_allocate (ClutterGridRequest *request, + ClutterOrientation orientation, + gfloat total_size) +{ + ClutterGridLayoutPrivate *priv = request->grid->priv; + ClutterGridLineData *linedata; + ClutterGridLines *lines; + ClutterGridLine *line; + gint nonempty; + gint expand; + gint i, j; + RequestedSize *sizes; + gint extra; + gint rest; + gint size; + + clutter_grid_request_compute_expand (request, orientation, &nonempty, &expand); + + if (nonempty == 0) + return; + + linedata = &priv->linedata[orientation]; + lines = &request->lines[orientation]; + + size = total_size - (nonempty - 1) * linedata->spacing; + + if (linedata->homogeneous) + { + extra = size / nonempty; + rest = size % nonempty; + + for (i = 0; i < lines->max - lines->min; i++) + { + line = &lines->lines[i]; + if (line->empty) + continue; + + line->allocation = extra; + if (rest > 0) + { + line->allocation += 1; + rest -= 1; + } + } + } + else + { + sizes = g_newa (RequestedSize, nonempty); + + j = 0; + for (i = 0; i < lines->max - lines->min; i++) + { + line = &lines->lines[i]; + if (line->empty) + continue; + + size -= line->minimum; + + sizes[j].minimum_size = line->minimum; + sizes[j].natural_size = line->natural; + sizes[j].data = line; + j++; + } + + size = distribute_natural_allocation (MAX (0, size), nonempty, sizes); + + if (expand > 0) + { + extra = size / expand; + rest = size % expand; + } + else + { + extra = 0; + rest = 0; + } + + j = 0; + for (i = 0; i < lines->max - lines->min; i++) + { + line = &lines->lines[i]; + if (line->empty) + continue; + + g_assert (line == sizes[j].data); + + line->allocation = sizes[j].minimum_size; + if (line->expand) + { + line->allocation += extra; + if (rest > 0) + { + line->allocation += 1; + rest -= 1; + } + } + + j++; + } + } +} + +/* Computes the position fields from allocation and spacing. + */ +static void +clutter_grid_request_position (ClutterGridRequest *request, + ClutterOrientation orientation) +{ + ClutterGridLayoutPrivate *priv = request->grid->priv; + ClutterGridLineData *linedata; + ClutterGridLines *lines; + ClutterGridLine *line; + gfloat position; + gint i; + + linedata = &priv->linedata[orientation]; + lines = &request->lines[orientation]; + + position = 0.f; + for (i = 0; i < lines->max - lines->min; i++) + { + line = &lines->lines[i]; + if (!line->empty) + { + line->position = position; + position += line->allocation + linedata->spacing; + } + } +} + +static void +clutter_grid_child_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterGridChild *grid_child = CLUTTER_GRID_CHILD (gobject); + ClutterLayoutManager *manager; + + manager = clutter_layout_meta_get_manager (CLUTTER_LAYOUT_META (gobject)); + + switch (prop_id) + { + case PROP_CHILD_LEFT_ATTACH: + CHILD_LEFT (grid_child) = g_value_get_int (value); + clutter_layout_manager_layout_changed (manager); + break; + + case PROP_CHILD_TOP_ATTACH: + CHILD_TOP (grid_child) = g_value_get_int (value); + clutter_layout_manager_layout_changed (manager); + break; + + case PROP_CHILD_WIDTH: + CHILD_WIDTH (grid_child) = g_value_get_int (value); + clutter_layout_manager_layout_changed (manager); + break; + + case PROP_CHILD_HEIGHT: + CHILD_HEIGHT (grid_child) = g_value_get_int (value); + clutter_layout_manager_layout_changed (manager); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_grid_child_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterGridChild *grid_child = CLUTTER_GRID_CHILD (gobject); + + switch (prop_id) + { + case PROP_CHILD_LEFT_ATTACH: + g_value_set_int (value, CHILD_LEFT (grid_child)); + break; + + case PROP_CHILD_TOP_ATTACH: + g_value_set_int (value, CHILD_TOP (grid_child)); + break; + + case PROP_CHILD_WIDTH: + g_value_set_int (value, CHILD_WIDTH (grid_child)); + break; + + case PROP_CHILD_HEIGHT: + g_value_set_int (value, CHILD_HEIGHT (grid_child)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_grid_child_class_init (ClutterGridChildClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = clutter_grid_child_set_property; + gobject_class->get_property = clutter_grid_child_get_property; + + child_props[PROP_CHILD_LEFT_ATTACH] = + g_param_spec_int ("left-attach", + P_("Left attachment"), + P_("The column number to attach the left side of the " + "child to"), + -G_MAXINT, G_MAXINT, 0, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); + + child_props[PROP_CHILD_TOP_ATTACH] = + g_param_spec_int ("top-attach", + P_("Top attachment"), + P_("The row number to attach the top side of a child " + "widget to"), + -G_MAXINT, G_MAXINT, 0, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); + + child_props[PROP_CHILD_WIDTH] = + g_param_spec_int ("width", + P_("Width"), + P_("The number of columns that a child spans"), + -G_MAXINT, G_MAXINT, 1, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); + + child_props[PROP_CHILD_HEIGHT] = + g_param_spec_int ("height", + P_("Height"), + P_("The number of rows that a child spans"), + -G_MAXINT, G_MAXINT, 1, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); + + g_object_class_install_properties (gobject_class, PROP_CHILD_LAST, + child_props); +} + +static void +clutter_grid_child_init (ClutterGridChild *self) +{ + CHILD_LEFT (self) = -1; + CHILD_TOP (self) = -1; + CHILD_WIDTH (self) = 1; + CHILD_HEIGHT (self) = 1; +} + +static void +clutter_grid_layout_set_container (ClutterLayoutManager *self, + ClutterContainer *container) +{ + ClutterGridLayoutPrivate *priv = CLUTTER_GRID_LAYOUT (self)->priv; + ClutterLayoutManagerClass *parent_class; + + priv->container = container; + + if (priv->container != NULL) + { + ClutterRequestMode request_mode; + + /* we need to change the :request-mode of the container + * to match the orientation + */ + request_mode = priv->orientation == CLUTTER_ORIENTATION_VERTICAL + ? CLUTTER_REQUEST_HEIGHT_FOR_WIDTH + : CLUTTER_REQUEST_WIDTH_FOR_HEIGHT; + clutter_actor_set_request_mode (CLUTTER_ACTOR (priv->container), + request_mode); + } + + parent_class = CLUTTER_LAYOUT_MANAGER_CLASS (clutter_grid_layout_parent_class); + parent_class->set_container (self, container); +} + +static void +clutter_grid_layout_get_size_for_size (ClutterGridLayout *self, + ClutterOrientation orientation, + float size, + float *minimum, + float *natural) +{ + ClutterGridRequest request; + ClutterGridLines *lines; + float min_size, nat_size; + + request.grid = self; + clutter_grid_request_update_attach (&request); + clutter_grid_request_count_lines (&request); + + lines = &request.lines[0]; + lines->lines = g_newa (ClutterGridLine, lines->max - lines->min); + memset (lines->lines, 0, (lines->max - lines->min) * sizeof (ClutterGridLine)); + + lines = &request.lines[1]; + lines->lines = g_newa (ClutterGridLine, lines->max - lines->min); + memset (lines->lines, 0, (lines->max - lines->min) * sizeof (ClutterGridLine)); + + clutter_grid_request_run (&request, 1 - orientation, FALSE); + clutter_grid_request_sum (&request, 1 - orientation, &min_size, &nat_size); + clutter_grid_request_allocate (&request, 1 - orientation, MAX (size, nat_size)); + + clutter_grid_request_run (&request, orientation, TRUE); + clutter_grid_request_sum (&request, orientation, minimum, natural); +} + +static void +clutter_grid_layout_get_preferred_width (ClutterLayoutManager *manager, + ClutterContainer *container, + gfloat for_height, + gfloat *min_width_p, + gfloat *nat_width_p) +{ + ClutterGridLayout *self = CLUTTER_GRID_LAYOUT (manager); + + if (min_width_p) + *min_width_p = 0.0f; + if (nat_width_p) + *nat_width_p = 0.0f; + + clutter_grid_layout_get_size_for_size (self, CLUTTER_ORIENTATION_HORIZONTAL, + for_height, + min_width_p, nat_width_p); +} + +static void +clutter_grid_layout_get_preferred_height (ClutterLayoutManager *manager, + ClutterContainer *container, + gfloat for_width, + gfloat *min_height_p, + gfloat *nat_height_p) +{ + ClutterGridLayout *self = CLUTTER_GRID_LAYOUT (manager); + + if (min_height_p) + *min_height_p = 0.0f; + if (nat_height_p) + *nat_height_p = 0.0f; + + clutter_grid_layout_get_size_for_size (self, CLUTTER_ORIENTATION_VERTICAL, + for_width, + min_height_p, nat_height_p); +} + +static void +allocate_child (ClutterGridRequest *request, + ClutterOrientation orientation, + ClutterGridChild *child, + gfloat *position, + gfloat *size) +{ + ClutterGridLayoutPrivate *priv = request->grid->priv; + ClutterGridLineData *linedata; + ClutterGridLines *lines; + ClutterGridLine *line; + ClutterGridAttach *attach; + gint i; + + linedata = &priv->linedata[orientation]; + lines = &request->lines[orientation]; + attach = &child->attach[orientation]; + + *position = lines->lines[attach->pos - lines->min].position; + + *size = (attach->span - 1) * linedata->spacing; + for (i = 0; i < attach->span; i++) + { + line = &lines->lines[attach->pos - lines->min + i]; + *size += line->allocation; + } +} + +#define GET_SIZE(allocation, orientation) \ + (orientation == CLUTTER_ORIENTATION_HORIZONTAL \ + ? clutter_actor_box_get_width ((allocation)) \ + : clutter_actor_box_get_height ((allocation))) + +static void +clutter_grid_layout_allocate (ClutterLayoutManager *layout, + ClutterContainer *container, + const ClutterActorBox *allocation, + ClutterAllocationFlags flags) +{ + ClutterGridLayout *self = CLUTTER_GRID_LAYOUT (layout); + ClutterOrientation orientation; + ClutterGridRequest request; + ClutterGridLines *lines; + ClutterActorIter iter; + ClutterActor *child; + + request.grid = self; + + clutter_grid_request_update_attach (&request); + clutter_grid_request_count_lines (&request); + lines = &request.lines[0]; + lines->lines = g_newa (ClutterGridLine, lines->max - lines->min); + memset (lines->lines, 0, (lines->max - lines->min) * sizeof (ClutterGridLine)); + lines = &request.lines[1]; + lines->lines = g_newa (ClutterGridLine, lines->max - lines->min); + memset (lines->lines, 0, (lines->max - lines->min) * sizeof (ClutterGridLine)); + + if (clutter_actor_get_request_mode (CLUTTER_ACTOR (container)) == CLUTTER_REQUEST_WIDTH_FOR_HEIGHT) + orientation = CLUTTER_ORIENTATION_HORIZONTAL; + else + orientation = CLUTTER_ORIENTATION_VERTICAL; + + clutter_grid_request_run (&request, 1 - orientation, FALSE); + clutter_grid_request_allocate (&request, 1 - orientation, GET_SIZE (allocation, 1 - orientation)); + clutter_grid_request_run (&request, orientation, TRUE); + + clutter_grid_request_allocate (&request, orientation, GET_SIZE (allocation, orientation)); + + clutter_grid_request_position (&request, 0); + clutter_grid_request_position (&request, 1); + + clutter_actor_iter_init (&iter, CLUTTER_ACTOR (container)); + while (clutter_actor_iter_next (&iter, &child)) + { + ClutterActorBox child_allocation; + gfloat x, y, width, height; + ClutterGridChild *grid_child; + + if (!clutter_actor_is_visible (child)) + continue; + + grid_child = GET_GRID_CHILD (self, child); + allocate_child (&request, CLUTTER_ORIENTATION_HORIZONTAL, grid_child, + &x, &width); + allocate_child (&request, CLUTTER_ORIENTATION_VERTICAL, grid_child, + &y, &height); + x += allocation->x1; + y += allocation->y1; + + CLUTTER_NOTE (LAYOUT, "Allocation for %s { %.2f, %.2f - %.2f x %.2f }", + _clutter_actor_get_debug_name (child), + x, y, width, height); + + child_allocation.x1 = x; + child_allocation.y1 = y; + child_allocation.x2 = child_allocation.x1 + width; + child_allocation.y2 = child_allocation.y1 + height; + + clutter_actor_allocate (child, &child_allocation, flags); + } +} + +static GType +clutter_grid_layout_get_child_meta_type (ClutterLayoutManager *self) +{ + return CLUTTER_TYPE_GRID_CHILD; +} + +static void +clutter_grid_layout_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterGridLayout *self = CLUTTER_GRID_LAYOUT (gobject); + + switch (prop_id) + { + case PROP_ORIENTATION: + clutter_grid_layout_set_orientation (self, g_value_get_enum (value)); + break; + + case PROP_ROW_SPACING: + clutter_grid_layout_set_row_spacing (self, g_value_get_uint (value)); + break; + + case PROP_COLUMN_SPACING: + clutter_grid_layout_set_column_spacing (self, g_value_get_uint (value)); + break; + + case PROP_ROW_HOMOGENEOUS: + clutter_grid_layout_set_row_homogeneous (self, + g_value_get_boolean (value)); + break; + + case PROP_COLUMN_HOMOGENEOUS: + clutter_grid_layout_set_column_homogeneous (self, + g_value_get_boolean (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_grid_layout_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterGridLayoutPrivate *priv = CLUTTER_GRID_LAYOUT (gobject)->priv; + + switch (prop_id) + { + case PROP_ORIENTATION: + g_value_set_enum (value, priv->orientation); + break; + + case PROP_ROW_SPACING: + g_value_set_uint (value, COLUMNS (priv)->spacing); + break; + + case PROP_COLUMN_SPACING: + g_value_set_uint (value, ROWS (priv)->spacing); + break; + + case PROP_ROW_HOMOGENEOUS: + g_value_set_boolean (value, COLUMNS (priv)->homogeneous); + break; + + case PROP_COLUMN_HOMOGENEOUS: + g_value_set_boolean (value, ROWS (priv)->homogeneous); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_grid_layout_class_init (ClutterGridLayoutClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + ClutterLayoutManagerClass *layout_class; + + layout_class = CLUTTER_LAYOUT_MANAGER_CLASS (klass); + + object_class->set_property = clutter_grid_layout_set_property; + object_class->get_property = clutter_grid_layout_get_property; + + layout_class->set_container = clutter_grid_layout_set_container; + layout_class->get_preferred_width = clutter_grid_layout_get_preferred_width; + layout_class->get_preferred_height = clutter_grid_layout_get_preferred_height; + layout_class->allocate = clutter_grid_layout_allocate; + layout_class->get_child_meta_type = clutter_grid_layout_get_child_meta_type; + + /** + * ClutterGridLayout:orientation: + * + * The orientation of the layout, either horizontal or vertical + * + * Since: 1.12 + */ + obj_props[PROP_ORIENTATION] = + g_param_spec_enum ("orientation", + P_("Orientation"), + P_("The orientation of the layout"), + CLUTTER_TYPE_ORIENTATION, + CLUTTER_ORIENTATION_HORIZONTAL, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); + + /** + * ClutterGridLayout:row-spacing: + * + * The amount of space in pixels between two consecutive rows + * + * Since: 1.12 + */ + obj_props[PROP_ROW_SPACING] = + g_param_spec_uint ("row-spacing", + P_("Row spacing"), + P_("The amount of space between two consecutive rows"), + 0, G_MAXUINT, 0, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); + + /** + * ClutterGridLayout:column-spacing: + * + * The amount of space in pixels between two consecutive columns + * + * Since: 1.12 + */ + obj_props[PROP_COLUMN_SPACING] = + g_param_spec_uint ("column-spacing", + P_("Column spacing"), + P_("The amount of space between two consecutive " + "columns"), + 0, G_MAXUINT, 0, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); + + /** + * ClutterGridLayout:row-homogeneous: + * + * Whether all rows of the layout should have the same height + * + * Since: 1.12 + */ + obj_props[PROP_ROW_HOMOGENEOUS] = + g_param_spec_boolean ("row-homogeneous", + P_("Row Homogeneous"), + P_("If TRUE, the rows are all the same height"), + FALSE, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); + + /** + * ClutterGridLayout:column-homogeneous: + * + * Whether all columns of the layout should have the same width + * + * Since: 1.12 + */ + obj_props[PROP_COLUMN_HOMOGENEOUS] = + g_param_spec_boolean ("column-homogeneous", + P_("Column Homogeneous"), + P_("If TRUE, the columns are all the same width"), + FALSE, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); + + g_object_class_install_properties (object_class, PROP_LAST, obj_props); +} + +static void +clutter_grid_layout_init (ClutterGridLayout *self) +{ + self->priv = clutter_grid_layout_get_instance_private (self); + + self->priv->orientation = CLUTTER_ORIENTATION_HORIZONTAL; + + self->priv->linedata[0].spacing = 0; + self->priv->linedata[1].spacing = 0; + + self->priv->linedata[0].homogeneous = FALSE; + self->priv->linedata[1].homogeneous = FALSE; +} + +/** + * clutter_grid_layout_new: + * + * Creates a new #ClutterGridLayout + * + * Return value: the new #ClutterGridLayout + */ +ClutterLayoutManager * +clutter_grid_layout_new (void) +{ + return g_object_new (CLUTTER_TYPE_GRID_LAYOUT, NULL); +} + +/** + * clutter_grid_layout_attach: + * @layout: a #ClutterGridLayout + * @child: the #ClutterActor to add + * @left: the column number to attach the left side of @child to + * @top: the row number to attach the top side of @child to + * @width: the number of columns that @child will span + * @height: the number of rows that @child will span + * + * Adds a widget to the grid. + * + * The position of @child is determined by @left and @top. The + * number of 'cells' that @child will occupy is determined by + * @width and @height. + * + * Since: 1.12 + */ +void +clutter_grid_layout_attach (ClutterGridLayout *layout, + ClutterActor *child, + gint left, + gint top, + gint width, + gint height) +{ + ClutterGridLayoutPrivate *priv; + + g_return_if_fail (CLUTTER_IS_GRID_LAYOUT (layout)); + + priv = layout->priv; + + if (!priv->container) + return; + + grid_attach (layout, child, left, top, width, height); + clutter_actor_add_child (CLUTTER_ACTOR (priv->container), child); +} + +/** + * clutter_grid_layout_attach_next_to: + * @layout: a #ClutterGridLayout + * @child: the actor to add + * @sibling: (allow-none): the child of @layout that @child will be placed + * next to, or %NULL to place @child at the beginning or end + * @side: the side of @sibling that @child is positioned next to + * @width: the number of columns that @child will span + * @height: the number of rows that @child will span + * + * Adds a actor to the grid. + * + * The actor is placed next to @sibling, on the side determined by + * @side. When @sibling is %NULL, the actor is placed in row (for + * left or right placement) or column 0 (for top or bottom placement), + * at the end indicated by @side. + * + * Attaching widgets labeled [1], [2], [3] with @sibling == %NULL and + * @side == %CLUTTER_GRID_POSITION_LEFT yields a layout of [3][2][1]. + * + * Since: 1.12 + */ +void +clutter_grid_layout_attach_next_to (ClutterGridLayout *layout, + ClutterActor *child, + ClutterActor *sibling, + ClutterGridPosition side, + gint width, + gint height) +{ + ClutterGridLayoutPrivate *priv; + + g_return_if_fail (CLUTTER_IS_GRID_LAYOUT (layout)); + g_return_if_fail (CLUTTER_IS_ACTOR (child)); + g_return_if_fail (clutter_actor_get_parent (child) == NULL); + g_return_if_fail (sibling == NULL || CLUTTER_IS_ACTOR (sibling)); + g_return_if_fail (width > 0); + g_return_if_fail (height > 0); + + priv = layout->priv; + + if (!priv->container) + return; + + grid_attach_next_to (layout, child, sibling, side, width, height); + clutter_actor_add_child (CLUTTER_ACTOR (priv->container), child); +} + +/** + * clutter_grid_layout_set_orientation: + * @layout: a #ClutterGridLayout + * @orientation: the orientation of the #ClutterGridLayout + * + * Sets the orientation of the @layout. + * + * #ClutterGridLayout uses the orientation as a hint when adding + * children to the #ClutterActor using it as a layout manager via + * clutter_actor_add_child(); changing this value will not have + * any effect on children that are already part of the layout. + * + * Since: 1.12 + */ +void +clutter_grid_layout_set_orientation (ClutterGridLayout *layout, + ClutterOrientation orientation) +{ + ClutterGridLayoutPrivate *priv; + + g_return_if_fail (CLUTTER_IS_GRID_LAYOUT (layout)); + + priv = layout->priv; + + if (priv->orientation != orientation) + { + priv->orientation = orientation; + + clutter_layout_manager_layout_changed (CLUTTER_LAYOUT_MANAGER (layout)); + g_object_notify_by_pspec (G_OBJECT (layout), obj_props[PROP_ORIENTATION]); + } +} + +/** + * clutter_grid_layout_get_child_at: + * @layout: a #ClutterGridLayout + * @left: the left edge of the cell + * @top: the top edge of the cell + * + * Gets the child of @layout whose area covers the grid + * cell whose upper left corner is at @left, @top. + * + * Returns: (transfer none): the child at the given position, or %NULL + * + * Since: 1.12 + */ +ClutterActor * +clutter_grid_layout_get_child_at (ClutterGridLayout *layout, + gint left, + gint top) +{ + ClutterGridLayoutPrivate *priv; + ClutterGridChild *grid_child; + ClutterActorIter iter; + ClutterActor *child; + + g_return_val_if_fail (CLUTTER_IS_GRID_LAYOUT (layout), NULL); + + priv = layout->priv; + + if (!priv->container) + return NULL; + + clutter_actor_iter_init (&iter, CLUTTER_ACTOR (priv->container)); + while (clutter_actor_iter_next (&iter, &child)) + { + grid_child = GET_GRID_CHILD (layout, child); + + if (CHILD_LEFT (grid_child) <= left && + CHILD_LEFT (grid_child) + CHILD_WIDTH (grid_child) > left && + CHILD_TOP (grid_child) <= top && + CHILD_TOP (grid_child) + CHILD_HEIGHT (grid_child) > top) + return child; + } + + return NULL; +} + +/** + * clutter_grid_layout_insert_row: + * @layout: a #ClutterGridLayout + * @position: the position to insert the row at + * + * Inserts a row at the specified position. + * + * Children which are attached at or below this position + * are moved one row down. Children which span across this + * position are grown to span the new row. + * + * Since: 1.12 + */ +void +clutter_grid_layout_insert_row (ClutterGridLayout *layout, + gint position) +{ + ClutterGridLayoutPrivate *priv; + ClutterGridChild *grid_child; + ClutterActorIter iter; + ClutterActor *child; + gint top, height; + + g_return_if_fail (CLUTTER_IS_GRID_LAYOUT (layout)); + + priv = layout->priv; + + if (!priv->container) + return; + + clutter_actor_iter_init (&iter, CLUTTER_ACTOR (priv->container)); + while (clutter_actor_iter_next (&iter, &child)) + { + grid_child = GET_GRID_CHILD (layout, child); + + top = CHILD_TOP (grid_child); + height = CHILD_HEIGHT (grid_child); + + if (top >= position) + { + CHILD_TOP (grid_child) = top + 1; + g_object_notify_by_pspec (G_OBJECT (grid_child), + child_props[PROP_CHILD_TOP_ATTACH]); + } + else if (top + height > position) + { + CHILD_HEIGHT (grid_child) = height + 1; + g_object_notify_by_pspec (G_OBJECT (grid_child), + child_props[PROP_CHILD_HEIGHT]); + } + } + clutter_layout_manager_layout_changed (CLUTTER_LAYOUT_MANAGER (layout)); +} + +/** + * clutter_grid_layout_insert_column: + * @layout: a #ClutterGridLayout + * @position: the position to insert the column at + * + * Inserts a column at the specified position. + * + * Children which are attached at or to the right of this position + * are moved one column to the right. Children which span across this + * position are grown to span the new column. + * + * Since: 1.12 + */ +void +clutter_grid_layout_insert_column (ClutterGridLayout *layout, + gint position) +{ + ClutterGridLayoutPrivate *priv; + ClutterGridChild *grid_child; + ClutterActorIter iter; + ClutterActor *child; + gint left, width; + + g_return_if_fail (CLUTTER_IS_GRID_LAYOUT (layout)); + + priv = layout->priv; + + if (!priv->container) + return; + + clutter_actor_iter_init (&iter, CLUTTER_ACTOR (priv->container)); + while (clutter_actor_iter_next (&iter, &child)) + { + grid_child = GET_GRID_CHILD (layout, child); + + left = CHILD_LEFT (grid_child); + width = CHILD_WIDTH (grid_child); + + if (left >= position) + { + CHILD_LEFT (grid_child) = left + 1; + g_object_notify_by_pspec (G_OBJECT (grid_child), + child_props[PROP_CHILD_LEFT_ATTACH]); + } + else if (left + width > position) + { + CHILD_WIDTH (grid_child) = width + 1; + g_object_notify_by_pspec (G_OBJECT (grid_child), + child_props[PROP_CHILD_WIDTH]); + } + } + clutter_layout_manager_layout_changed (CLUTTER_LAYOUT_MANAGER (layout)); +} + +/** + * clutter_grid_layout_insert_next_to: + * @layout: a #ClutterGridLayout + * @sibling: the child of @layout that the new row or column will be + * placed next to + * @side: the side of @sibling that @child is positioned next to + * + * Inserts a row or column at the specified position. + * + * The new row or column is placed next to @sibling, on the side + * determined by @side. If @side is %CLUTTER_GRID_POSITION_LEFT or + * %CLUTTER_GRID_POSITION_BOTTOM, a row is inserted. If @side is + * %CLUTTER_GRID_POSITION_LEFT of %CLUTTER_GRID_POSITION_RIGHT, + * a column is inserted. + * + * Since: 1.12 + */ +void +clutter_grid_layout_insert_next_to (ClutterGridLayout *layout, + ClutterActor *sibling, + ClutterGridPosition side) +{ + ClutterGridChild *grid_child; + + g_return_if_fail (CLUTTER_IS_GRID_LAYOUT (layout)); + g_return_if_fail (CLUTTER_IS_ACTOR (sibling)); + + grid_child = GET_GRID_CHILD (layout, sibling); + + switch (side) + { + case CLUTTER_GRID_POSITION_LEFT: + clutter_grid_layout_insert_column (layout, CHILD_LEFT (grid_child)); + break; + + case CLUTTER_GRID_POSITION_RIGHT: + clutter_grid_layout_insert_column (layout, CHILD_LEFT (grid_child) + + CHILD_WIDTH (grid_child)); + break; + + case CLUTTER_GRID_POSITION_TOP: + clutter_grid_layout_insert_row (layout, CHILD_TOP (grid_child)); + break; + + case CLUTTER_GRID_POSITION_BOTTOM: + clutter_grid_layout_insert_row (layout, CHILD_TOP (grid_child) + + CHILD_HEIGHT (grid_child)); + break; + + default: + g_assert_not_reached (); + } +} + +/** + * clutter_grid_layout_get_orientation: + * @layout: a #ClutterGridLayout + * + * Retrieves the orientation of the @layout. + * + * Return value: the orientation of the layout + * + * Since: 1.12 + */ +ClutterOrientation +clutter_grid_layout_get_orientation (ClutterGridLayout *layout) +{ + g_return_val_if_fail (CLUTTER_IS_GRID_LAYOUT (layout), + CLUTTER_ORIENTATION_HORIZONTAL); + + return layout->priv->orientation; +} + +/** + * clutter_grid_layout_set_row_spacing: + * @layout: a #ClutterGridLayout + * @spacing: the spacing between rows of the layout, in pixels + * + * Sets the spacing between rows of @layout + * + * Since: 1.12 + */ +void +clutter_grid_layout_set_row_spacing (ClutterGridLayout *layout, + guint spacing) +{ + ClutterGridLayoutPrivate *priv; + + g_return_if_fail (CLUTTER_IS_GRID_LAYOUT (layout)); + + priv = layout->priv; + + if (COLUMNS (priv)->spacing != spacing) + { + COLUMNS (priv)->spacing = spacing; + + clutter_layout_manager_layout_changed (CLUTTER_LAYOUT_MANAGER (layout)); + g_object_notify_by_pspec (G_OBJECT (layout), + obj_props[PROP_ROW_SPACING]); + } +} + +/** + * clutter_grid_layout_get_row_spacing: + * @layout: a #ClutterGridLayout + * + * Retrieves the spacing set using clutter_grid_layout_set_row_spacing() + * + * Return value: the spacing between rows of @layout + * + * Since: 1.12 + */ +guint +clutter_grid_layout_get_row_spacing (ClutterGridLayout *layout) +{ + ClutterGridLayoutPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_GRID_LAYOUT (layout), 0); + + priv = layout->priv; + + return COLUMNS (priv)->spacing; +} + +/** + * clutter_grid_layout_set_column_spacing: + * @layout: a #ClutterGridLayout + * @spacing: the spacing between columns of the layout, in pixels + * + * Sets the spacing between columns of @layout + * + * Since: 1.12 + */ +void +clutter_grid_layout_set_column_spacing (ClutterGridLayout *layout, + guint spacing) +{ + ClutterGridLayoutPrivate *priv; + + g_return_if_fail (CLUTTER_IS_GRID_LAYOUT (layout)); + + priv = layout->priv; + + if (ROWS (priv)->spacing != spacing) + { + ROWS (priv)->spacing = spacing; + + clutter_layout_manager_layout_changed (CLUTTER_LAYOUT_MANAGER (layout)); + g_object_notify_by_pspec (G_OBJECT (layout), + obj_props[PROP_COLUMN_SPACING]); + } +} + +/** + * clutter_grid_layout_get_column_spacing: + * @layout: a #ClutterGridLayout + * + * Retrieves the spacing set using clutter_grid_layout_set_column_spacing() + * + * Return value: the spacing between coluns of @layout + * + * Since: 1.12 + */ +guint +clutter_grid_layout_get_column_spacing (ClutterGridLayout *layout) +{ + ClutterGridLayoutPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_GRID_LAYOUT (layout), 0); + + priv = layout->priv; + + return ROWS (priv)->spacing; +} + +/** + * clutter_grid_layout_set_column_homogeneous: + * @layout: a #ClutterGridLayout + * @homogeneous: %TRUE to make columns homogeneous + * + * Sets whether all columns of @layout will have the same width. + * + * Since: 1.12 + */ +void +clutter_grid_layout_set_column_homogeneous (ClutterGridLayout *layout, + gboolean homogeneous) +{ + ClutterGridLayoutPrivate *priv; + + g_return_if_fail (CLUTTER_IS_GRID_LAYOUT (layout)); + + priv = layout->priv; + + if (ROWS (priv)->homogeneous != homogeneous) + { + ROWS (priv)->homogeneous = homogeneous; + + clutter_layout_manager_layout_changed (CLUTTER_LAYOUT_MANAGER (layout)); + g_object_notify_by_pspec (G_OBJECT (layout), + obj_props[PROP_COLUMN_HOMOGENEOUS]); + } +} + +/** + * clutter_grid_layout_get_column_homogeneous: + * @layout: a #ClutterGridLayout + * + * Returns whether all columns of @layout have the same width. + * + * Returns: whether all columns of @layout have the same width. + */ +gboolean +clutter_grid_layout_get_column_homogeneous (ClutterGridLayout *layout) +{ + ClutterGridLayoutPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_GRID_LAYOUT (layout), FALSE); + + priv = layout->priv; + + return ROWS (priv)->homogeneous; +} + +/** + * clutter_grid_layout_set_row_homogeneous: + * @layout: a #ClutterGridLayout + * @homogeneous: %TRUE to make rows homogeneous + * + * Sets whether all rows of @layout will have the same height. + * + * Since: 1.12 + */ +void +clutter_grid_layout_set_row_homogeneous (ClutterGridLayout *layout, + gboolean homogeneous) +{ + ClutterGridLayoutPrivate *priv; + + g_return_if_fail (CLUTTER_IS_GRID_LAYOUT (layout)); + + priv = layout->priv; + + if (COLUMNS (priv)->homogeneous != homogeneous) + { + COLUMNS (priv)->homogeneous = homogeneous; + + clutter_layout_manager_layout_changed (CLUTTER_LAYOUT_MANAGER (layout)); + g_object_notify_by_pspec (G_OBJECT (layout), + obj_props[PROP_ROW_HOMOGENEOUS]); + } +} + +/** + * clutter_grid_layout_get_row_homogeneous: + * @layout: a #ClutterGridLayout + * + * Returns whether all rows of @layout have the same height. + * + * Returns: whether all rows of @layout have the same height. + * + * Since: 1.12 + */ +gboolean +clutter_grid_layout_get_row_homogeneous (ClutterGridLayout *layout) +{ + ClutterGridLayoutPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_GRID_LAYOUT (layout), FALSE); + + priv = layout->priv; + + return COLUMNS (priv)->homogeneous; +} diff --git a/clutter/clutter/clutter-grid-layout.h b/clutter/clutter/clutter-grid-layout.h new file mode 100644 index 0000000..c04a5ba --- /dev/null +++ b/clutter/clutter/clutter-grid-layout.h @@ -0,0 +1,161 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Red Hat, Inc. + * Copyright (C) 2012 Bastian Winkler + * + * 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 . + * + * Author: + * Bastian Winkler + * + * Based on GtkGrid widget by: + * Matthias Clasen + */ + +#ifndef __CLUTTER_GRID_LAYOUT_H__ +#define __CLUTTER_GRID_LAYOUT_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_GRID_LAYOUT (clutter_grid_layout_get_type ()) +#define CLUTTER_GRID_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_GRID_LAYOUT, ClutterGridLayout)) +#define CLUTTER_IS_GRID_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_GRID_LAYOUT)) +#define CLUTTER_GRID_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_GRID_LAYOUT, ClutterGridLayoutClass)) +#define CLUTTER_IS_GRID_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_GRID_LAYOUT)) +#define CLUTTER_GRID_LAYOUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_GRID_LAYOUT, ClutterGridLayoutClass)) + +typedef struct _ClutterGridLayout ClutterGridLayout; +typedef struct _ClutterGridLayoutPrivate ClutterGridLayoutPrivate; +typedef struct _ClutterGridLayoutClass ClutterGridLayoutClass; + +/** + * ClutterGridLayout: + * + * The #ClutterGridLayout structure contains only private data + * and should be accessed using the provided API + * + * Since: 1.12 + */ +struct _ClutterGridLayout +{ + /*< private >*/ + ClutterLayoutManager parent_instance; + + ClutterGridLayoutPrivate *priv; +}; + +/** + * ClutterGridLayoutClass: + * + * The #ClutterGridLayoutClass structure contains only private + * data and should be accessed using the provided API + * + * Since: 1.12 + */ +struct _ClutterGridLayoutClass +{ + /*< private >*/ + ClutterLayoutManagerClass parent_class; + + gpointer _padding[8]; +}; + +CLUTTER_AVAILABLE_IN_1_12 +GType clutter_grid_layout_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_12 +ClutterLayoutManager * clutter_grid_layout_new (void); + +CLUTTER_AVAILABLE_IN_1_12 +void clutter_grid_layout_attach (ClutterGridLayout *layout, + ClutterActor *child, + gint left, + gint top, + gint width, + gint height); + +CLUTTER_AVAILABLE_IN_1_12 +void clutter_grid_layout_attach_next_to (ClutterGridLayout *layout, + ClutterActor *child, + ClutterActor *sibling, + ClutterGridPosition side, + gint width, + gint height); + +CLUTTER_AVAILABLE_IN_1_12 +ClutterActor * clutter_grid_layout_get_child_at (ClutterGridLayout *layout, + gint left, + gint top); + +CLUTTER_AVAILABLE_IN_1_12 +void clutter_grid_layout_insert_row (ClutterGridLayout *layout, + gint position); + +CLUTTER_AVAILABLE_IN_1_12 +void clutter_grid_layout_insert_column (ClutterGridLayout *layout, + gint position); + +CLUTTER_AVAILABLE_IN_1_12 +void clutter_grid_layout_insert_next_to (ClutterGridLayout *layout, + ClutterActor *sibling, + ClutterGridPosition side); + +CLUTTER_AVAILABLE_IN_1_12 +void clutter_grid_layout_set_orientation (ClutterGridLayout *layout, + ClutterOrientation orientation); + +CLUTTER_AVAILABLE_IN_1_12 +ClutterOrientation clutter_grid_layout_get_orientation (ClutterGridLayout *layout); + +CLUTTER_AVAILABLE_IN_1_12 +void clutter_grid_layout_set_column_spacing (ClutterGridLayout *layout, + guint spacing); + +CLUTTER_AVAILABLE_IN_1_12 +guint clutter_grid_layout_get_column_spacing (ClutterGridLayout *layout); + +CLUTTER_AVAILABLE_IN_1_12 +void clutter_grid_layout_set_row_spacing (ClutterGridLayout *layout, + guint spacing); + +CLUTTER_AVAILABLE_IN_1_12 +guint clutter_grid_layout_get_row_spacing (ClutterGridLayout *layout); + +CLUTTER_AVAILABLE_IN_1_12 +void clutter_grid_layout_set_column_homogeneous (ClutterGridLayout *layout, + gboolean homogeneous); + +CLUTTER_AVAILABLE_IN_1_12 +gboolean clutter_grid_layout_get_column_homogeneous (ClutterGridLayout *layout); + + +CLUTTER_AVAILABLE_IN_1_12 +void clutter_grid_layout_set_row_homogeneous (ClutterGridLayout *layout, + gboolean homogeneous); + +CLUTTER_AVAILABLE_IN_1_12 +gboolean clutter_grid_layout_get_row_homogeneous (ClutterGridLayout *layout); + +G_END_DECLS + +#endif /* __CLUTTER_GRID_LAYOUT_H__ */ diff --git a/clutter/clutter/clutter-group.h b/clutter/clutter/clutter-group.h new file mode 100644 index 0000000..40f71bc --- /dev/null +++ b/clutter/clutter/clutter-group.h @@ -0,0 +1,96 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __CLUTTER_GROUP_H__ +#define __CLUTTER_GROUP_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_GROUP (clutter_group_get_type ()) +#define CLUTTER_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_GROUP, ClutterGroup)) +#define CLUTTER_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_GROUP, ClutterGroupClass)) +#define CLUTTER_IS_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_GROUP)) +#define CLUTTER_IS_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_GROUP)) +#define CLUTTER_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_GROUP, ClutterGroupClass)) + +/* XXX - ClutterGroup is to be considered fully deprecated; the only + * reason we keep this header is because ClutterStage inherits from + * ClutterGroup, and thus we need to have a structure definition for + * the Stage object to expand. + */ + +typedef struct _ClutterGroup ClutterGroup; +typedef struct _ClutterGroupClass ClutterGroupClass; +typedef struct _ClutterGroupPrivate ClutterGroupPrivate; + +/** + * ClutterGroup: + * + * The #ClutterGroup structure contains only private data + * and should be accessed using the provided API + * + * Since: 0.2 + */ +struct _ClutterGroup +{ + /*< private >*/ + ClutterActor parent_instance; + + ClutterGroupPrivate *priv; +}; + +/** + * ClutterGroupClass: + * + * The #ClutterGroupClass structure contains only private data + * + * Since: 0.2 + */ +struct _ClutterGroupClass +{ + /*< private >*/ + ClutterActorClass parent_class; + + /* padding for future expansion */ + void (*_clutter_reserved1) (void); + void (*_clutter_reserved2) (void); + void (*_clutter_reserved3) (void); + void (*_clutter_reserved4) (void); + void (*_clutter_reserved5) (void); + void (*_clutter_reserved6) (void); +}; + +CLUTTER_AVAILABLE_IN_ALL +GType clutter_group_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* __CLUTTER_GROUP_H__ */ diff --git a/clutter/clutter/clutter-id-pool.c b/clutter/clutter/clutter-id-pool.c new file mode 100644 index 0000000..a565436 --- /dev/null +++ b/clutter/clutter/clutter-id-pool.c @@ -0,0 +1,131 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006-2008 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + * + * ClutterIDPool: pool of reusable integer ids associated with pointers. + * + * Author: Øyvind Kolås + * + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-debug.h" +#include "clutter-id-pool.h" + +struct _ClutterIDPool +{ + GArray *array; /* Array of pointers */ + GSList *free_ids; /* A stack of freed ids */ +}; + +ClutterIDPool * +_clutter_id_pool_new (guint initial_size) +{ + ClutterIDPool *self; + + self = g_slice_new (ClutterIDPool); + + self->array = g_array_sized_new (FALSE, FALSE, + sizeof (gpointer), initial_size); + self->free_ids = NULL; + return self; +} + +void +_clutter_id_pool_free (ClutterIDPool *id_pool) +{ + g_return_if_fail (id_pool != NULL); + + g_array_free (id_pool->array, TRUE); + g_slist_free (id_pool->free_ids); + g_slice_free (ClutterIDPool, id_pool); +} + +guint32 +_clutter_id_pool_add (ClutterIDPool *id_pool, + gpointer ptr) +{ + gpointer *array; + guint32 retval; + + g_return_val_if_fail (id_pool != NULL, 0); + + if (id_pool->free_ids) /* There are items on our freelist, reuse one */ + { + array = (void*) id_pool->array->data; + retval = GPOINTER_TO_UINT (id_pool->free_ids->data); + + id_pool->free_ids = g_slist_remove (id_pool->free_ids, + id_pool->free_ids->data); + array[retval] = ptr; + return retval; + } + + /* Allocate new id */ + retval = id_pool->array->len; + g_array_append_val (id_pool->array, ptr); + + return retval; +} + +void +_clutter_id_pool_remove (ClutterIDPool *id_pool, + guint32 id_) +{ + gpointer *array; + + g_return_if_fail (id_pool != NULL); + + array = (void*) id_pool->array->data; + + array[id_] = NULL; + + id_pool->free_ids = g_slist_prepend (id_pool->free_ids, + GUINT_TO_POINTER (id_)); +} + +gpointer +_clutter_id_pool_lookup (ClutterIDPool *id_pool, + guint32 id_) +{ + gpointer *array; + + g_return_val_if_fail (id_pool != NULL, NULL); + g_return_val_if_fail (id_pool->array != NULL, NULL); + + array = (void*) id_pool->array->data; + + if (id_ >= id_pool->array->len || array[id_] == NULL) + { + g_warning ("The required ID of %u does not refer to an existing actor; " + "this usually implies that the pick() of an actor is not " + "correctly implemented or that there is an error in the " + "glReadPixels() implementation of the GL driver.", id_); + return NULL; + } + + return array[id_]; +} diff --git a/clutter/clutter/clutter-id-pool.h b/clutter/clutter/clutter-id-pool.h new file mode 100644 index 0000000..2c41363 --- /dev/null +++ b/clutter/clutter/clutter-id-pool.h @@ -0,0 +1,50 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2008 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * ClutterIDPool: pool of reusable integer ids associated with pointers. + * + * Author: Øyvind Kolås + */ + +#ifndef __CLUTTER_ID_POOL_H__ +#define __CLUTTER_ID_POOL_H__ + +#include + +G_BEGIN_DECLS + +typedef struct _ClutterIDPool ClutterIDPool; + +ClutterIDPool * _clutter_id_pool_new (guint initial_size); +void _clutter_id_pool_free (ClutterIDPool *id_pool); + +guint32 _clutter_id_pool_add (ClutterIDPool *id_pool, + gpointer ptr); +void _clutter_id_pool_remove (ClutterIDPool *id_pool, + guint32 id_); +gpointer _clutter_id_pool_lookup (ClutterIDPool *id_pool, + guint32 id_); + + +G_END_DECLS + +#endif /* __CLUTTER_ID_POOL_H__ */ diff --git a/clutter/clutter/clutter-image.c b/clutter/clutter/clutter-image.c new file mode 100644 index 0000000..722b037 --- /dev/null +++ b/clutter/clutter/clutter-image.c @@ -0,0 +1,429 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive image' library. + * + * Copyright (C) 2012 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 . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-image + * @Title: ClutterImage + * @Short_Description: Image data content + * + * #ClutterImage is a #ClutterContent implementation that displays + * image data inside a #ClutterActor. + * + * See [image.c](https://git.gnome.org/browse/clutter/tree/examples/image-content.c?h=clutter-1.18) + * for an example of how to use #ClutterImage. + * + * #ClutterImage is available since Clutter 1.10. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#define CLUTTER_ENABLE_EXPERIMENTAL_API + +#include "clutter-image.h" + +#include "clutter-actor-private.h" +#include "clutter-color.h" +#include "clutter-content-private.h" +#include "clutter-debug.h" +#include "clutter-paint-node.h" +#include "clutter-paint-nodes.h" +#include "clutter-private.h" + +struct _ClutterImagePrivate +{ + CoglTexture *texture; +}; + +static void clutter_content_iface_init (ClutterContentIface *iface); + +G_DEFINE_TYPE_WITH_CODE (ClutterImage, clutter_image, G_TYPE_OBJECT, + G_ADD_PRIVATE (ClutterImage) + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTENT, + clutter_content_iface_init)) + +GQuark +clutter_image_error_quark (void) +{ + return g_quark_from_static_string ("clutter-image-error-quark"); +} + +static void +clutter_image_finalize (GObject *gobject) +{ + ClutterImagePrivate *priv = CLUTTER_IMAGE (gobject)->priv; + + if (priv->texture != NULL) + { + cogl_object_unref (priv->texture); + priv->texture = NULL; + } + + G_OBJECT_CLASS (clutter_image_parent_class)->finalize (gobject); +} + +static void +clutter_image_class_init (ClutterImageClass *klass) +{ + G_OBJECT_CLASS (klass)->finalize = clutter_image_finalize; +} + +static void +clutter_image_init (ClutterImage *self) +{ + self->priv = clutter_image_get_instance_private (self); +} + +static void +clutter_image_paint_content (ClutterContent *content, + ClutterActor *actor, + ClutterPaintNode *root) +{ + ClutterImagePrivate *priv = CLUTTER_IMAGE (content)->priv; + ClutterPaintNode *node; + + if (priv->texture == NULL) + return; + + node = clutter_actor_create_texture_paint_node (actor, priv->texture); + clutter_paint_node_set_name (node, "Image Content"); + clutter_paint_node_add_child (root, node); + clutter_paint_node_unref (node); +} + +static gboolean +clutter_image_get_preferred_size (ClutterContent *content, + gfloat *width, + gfloat *height) +{ + ClutterImagePrivate *priv = CLUTTER_IMAGE (content)->priv; + + if (priv->texture == NULL) + return FALSE; + + if (width != NULL) + *width = cogl_texture_get_width (priv->texture); + + if (height != NULL) + *height = cogl_texture_get_height (priv->texture); + + return TRUE; +} + +static void +clutter_content_iface_init (ClutterContentIface *iface) +{ + iface->get_preferred_size = clutter_image_get_preferred_size; + iface->paint_content = clutter_image_paint_content; +} + +/** + * clutter_image_new: + * + * Creates a new #ClutterImage instance. + * + * Return value: (transfer full): the newly created #ClutterImage instance. + * Use g_object_unref() when done. + * + * Since: 1.10 + */ +ClutterContent * +clutter_image_new (void) +{ + return g_object_new (CLUTTER_TYPE_IMAGE, NULL); +} + +/** + * clutter_image_set_data: + * @image: a #ClutterImage + * @data: (array): the image data, as an array of bytes + * @pixel_format: the Cogl pixel format of the image data + * @width: the width of the image data + * @height: the height of the image data + * @row_stride: the length of each row inside @data + * @error: return location for a #GError, or %NULL + * + * Sets the image data to be displayed by @image. + * + * If the image data was successfully loaded, the @image will be invalidated. + * + * In case of error, the @error value will be set, and this function will + * return %FALSE. + * + * The image data is copied in texture memory. + * + * The image data is expected to be a linear array of RGBA or RGB pixel data; + * how to retrieve that data is left to platform specific image loaders. For + * instance, if you use the GdkPixbuf library: + * + * |[ + * ClutterContent *image = clutter_image_new (); + * + * GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (filename, NULL); + * + * clutter_image_set_data (CLUTTER_IMAGE (image), + * gdk_pixbuf_get_pixels (pixbuf), + * gdk_pixbuf_get_has_alpha (pixbuf) + * ? COGL_PIXEL_FORMAT_RGBA_8888 + * : COGL_PIXEL_FORMAT_RGB_888, + * gdk_pixbuf_get_width (pixbuf), + * gdk_pixbuf_get_height (pixbuf), + * gdk_pixbuf_get_rowstride (pixbuf), + * &error); + * + * g_object_unref (pixbuf); + * ]| + * + * Return value: %TRUE if the image data was successfully loaded, + * and %FALSE otherwise. + * + * Since: 1.10 + */ +gboolean +clutter_image_set_data (ClutterImage *image, + const guint8 *data, + CoglPixelFormat pixel_format, + guint width, + guint height, + guint row_stride, + GError **error) +{ + ClutterImagePrivate *priv; + CoglTextureFlags flags; + + g_return_val_if_fail (CLUTTER_IS_IMAGE (image), FALSE); + g_return_val_if_fail (data != NULL, FALSE); + + priv = image->priv; + + if (priv->texture != NULL) + cogl_object_unref (priv->texture); + + flags = COGL_TEXTURE_NONE; + if (width >= 512 && height >= 512) + flags |= COGL_TEXTURE_NO_ATLAS; + + priv->texture = cogl_texture_new_from_data (width, height, + flags, + pixel_format, + COGL_PIXEL_FORMAT_ANY, + row_stride, + data); + if (priv->texture == NULL) + { + g_set_error_literal (error, CLUTTER_IMAGE_ERROR, + CLUTTER_IMAGE_ERROR_INVALID_DATA, + _("Unable to load image data")); + return FALSE; + } + + clutter_content_invalidate (CLUTTER_CONTENT (image)); + + return TRUE; +} + +/** + * clutter_image_set_bytes: + * @image: a #ClutterImage + * @data: the image data, as a #GBytes + * @pixel_format: the Cogl pixel format of the image data + * @width: the width of the image data + * @height: the height of the image data + * @row_stride: the length of each row inside @data + * @error: return location for a #GError, or %NULL + * + * Sets the image data stored inside a #GBytes to be displayed by @image. + * + * If the image data was successfully loaded, the @image will be invalidated. + * + * In case of error, the @error value will be set, and this function will + * return %FALSE. + * + * The image data contained inside the #GBytes is copied in texture memory, + * and no additional reference is acquired on the @data. + * + * Return value: %TRUE if the image data was successfully loaded, + * and %FALSE otherwise. + * + * Since: 1.12 + */ +gboolean +clutter_image_set_bytes (ClutterImage *image, + GBytes *data, + CoglPixelFormat pixel_format, + guint width, + guint height, + guint row_stride, + GError **error) +{ + ClutterImagePrivate *priv; + CoglTextureFlags flags; + + g_return_val_if_fail (CLUTTER_IS_IMAGE (image), FALSE); + g_return_val_if_fail (data != NULL, FALSE); + + priv = image->priv; + + if (priv->texture != NULL) + cogl_object_unref (priv->texture); + + flags = COGL_TEXTURE_NONE; + if (width >= 512 && height >= 512) + flags |= COGL_TEXTURE_NO_ATLAS; + + priv->texture = cogl_texture_new_from_data (width, height, + flags, + pixel_format, + COGL_PIXEL_FORMAT_ANY, + row_stride, + g_bytes_get_data (data, NULL)); + if (priv->texture == NULL) + { + g_set_error_literal (error, CLUTTER_IMAGE_ERROR, + CLUTTER_IMAGE_ERROR_INVALID_DATA, + _("Unable to load image data")); + return FALSE; + } + + clutter_content_invalidate (CLUTTER_CONTENT (image)); + + return TRUE; +} + +/** + * clutter_image_set_area: + * @image: a #ClutterImage + * @data: (array): the image data, as an array of bytes + * @pixel_format: the Cogl pixel format of the image data + * @rect: a rectangle indicating the area that should be set + * @row_stride: the length of each row inside @data + * @error: return location for a #GError, or %NULL + * + * Sets the image data to be display by @image, using @rect to indicate + * the position and size of the image data to be set. + * + * If the @image does not have any image data set when this function is + * called, a new texture will be created with the size of the width and + * height of the rectangle, i.e. calling this function on a newly created + * #ClutterImage will be the equivalent of calling clutter_image_set_data(). + * + * If the image data was successfully loaded, the @image will be invalidated. + * + * In case of error, the @error value will be set, and this function will + * return %FALSE. + * + * The image data is copied in texture memory. + * + * Return value: %TRUE if the image data was successfully loaded, + * and %FALSE otherwise. + * + * Since: 1.10 + */ +gboolean +clutter_image_set_area (ClutterImage *image, + const guint8 *data, + CoglPixelFormat pixel_format, + const cairo_rectangle_int_t *area, + guint row_stride, + GError **error) +{ + ClutterImagePrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_IMAGE (image), FALSE); + g_return_val_if_fail (data != NULL, FALSE); + g_return_val_if_fail (area != NULL, FALSE); + + priv = image->priv; + + if (priv->texture == NULL) + { + CoglTextureFlags flags = COGL_TEXTURE_NONE; + + if (area->width >= 512 && area->height >= 512) + flags |= COGL_TEXTURE_NO_ATLAS; + + priv->texture = cogl_texture_new_from_data (area->width, + area->height, + flags, + pixel_format, + COGL_PIXEL_FORMAT_ANY, + row_stride, + data); + } + else + { + gboolean res; + + res = cogl_texture_set_region (priv->texture, + 0, 0, + area->x, area->y, + area->width, area->height, + area->width, area->height, + pixel_format, + row_stride, + data); + + if (!res) + { + cogl_object_unref (priv->texture); + priv->texture = NULL; + } + } + + if (priv->texture == NULL) + { + g_set_error_literal (error, CLUTTER_IMAGE_ERROR, + CLUTTER_IMAGE_ERROR_INVALID_DATA, + _("Unable to load image data")); + return FALSE; + } + + clutter_content_invalidate (CLUTTER_CONTENT (image)); + + return TRUE; +} + +/** + * clutter_image_get_texture: + * @image: a #ClutterImage + * + * Retrieves a pointer to the Cogl texture used by @image. + * + * If you change the contents of the returned Cogl texture you will need + * to manually invalidate the @image with clutter_content_invalidate() + * in order to update the actors using @image as their content. + * + * Return value: (transfer none): a pointer to the Cogl texture, or %NULL + * + * Since: 1.10 + * Stability: unstable + */ +CoglTexture * +clutter_image_get_texture (ClutterImage *image) +{ + g_return_val_if_fail (CLUTTER_IS_IMAGE (image), NULL); + + return image->priv->texture; +} diff --git a/clutter/clutter/clutter-image.h b/clutter/clutter/clutter-image.h new file mode 100644 index 0000000..5a4d063 --- /dev/null +++ b/clutter/clutter/clutter-image.h @@ -0,0 +1,139 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive image' library. + * + * Copyright (C) 2012 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 . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_IMAGE_H__ +#define __CLUTTER_IMAGE_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_IMAGE (clutter_image_get_type ()) +#define CLUTTER_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_IMAGE, ClutterImage)) +#define CLUTTER_IS_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_IMAGE)) +#define CLUTTER_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_IMAGE, ClutterImageClass)) +#define CLUTTER_IS_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_IMAGE)) +#define CLUTTER_IMAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_IMAGE, ClutterImageClass)) + +/** + * CLUTTER_IMAGE_ERROR: + * + * Error domain for the #ClutterImageError enumeration. + * + * Since: 1.10 + */ +#define CLUTTER_IMAGE_ERROR (clutter_image_error_quark ()) + +typedef struct _ClutterImage ClutterImage; +typedef struct _ClutterImagePrivate ClutterImagePrivate; +typedef struct _ClutterImageClass ClutterImageClass; + +/** + * ClutterImageError: + * @CLUTTER_IMAGE_ERROR_INVALID_DATA: Invalid data passed to the + * clutter_image_set_data() function. + * + * Error enumeration for #ClutterImage. + * + * Since: 1.10 + */ +typedef enum { + CLUTTER_IMAGE_ERROR_INVALID_DATA +} ClutterImageError; + +/** + * ClutterImage: + * + * The #ClutterImage structure contains + * private data and should only be accessed using the provided + * API. + * + * Since: 1.10 + */ +struct _ClutterImage +{ + /*< private >*/ + GObject parent_instance; + + ClutterImagePrivate *priv; +}; + +/** + * ClutterImageClass: + * + * The #ClutterImageClass structure contains + * private data. + * + * Since: 1.10 + */ +struct _ClutterImageClass +{ + /*< private >*/ + GObjectClass parent_class; + + gpointer _padding[16]; +}; + +CLUTTER_AVAILABLE_IN_1_10 +GQuark clutter_image_error_quark (void); +CLUTTER_AVAILABLE_IN_1_10 +GType clutter_image_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_10 +ClutterContent * clutter_image_new (void); +CLUTTER_AVAILABLE_IN_1_10 +gboolean clutter_image_set_data (ClutterImage *image, + const guint8 *data, + CoglPixelFormat pixel_format, + guint width, + guint height, + guint row_stride, + GError **error); +CLUTTER_AVAILABLE_IN_1_10 +gboolean clutter_image_set_area (ClutterImage *image, + const guint8 *data, + CoglPixelFormat pixel_format, + const cairo_rectangle_int_t *rect, + guint row_stride, + GError **error); +CLUTTER_AVAILABLE_IN_1_12 +gboolean clutter_image_set_bytes (ClutterImage *image, + GBytes *data, + CoglPixelFormat pixel_format, + guint width, + guint height, + guint row_stride, + GError **error); + +CLUTTER_AVAILABLE_IN_1_10 +CoglTexture * clutter_image_get_texture (ClutterImage *image); + +G_END_DECLS + +#endif /* __CLUTTER_IMAGE_H__ */ diff --git a/clutter/clutter/clutter-input-device-tool.c b/clutter/clutter/clutter-input-device-tool.c new file mode 100644 index 0000000..0835ddf --- /dev/null +++ b/clutter/clutter/clutter-input-device-tool.c @@ -0,0 +1,207 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright © 2009, 2010, 2011 Intel Corp. + * + * 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 . + * + * Author: Carlos Garnacho + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-input-device-tool.h" +#include "clutter-private.h" + +typedef struct _ClutterInputDeviceToolPrivate ClutterInputDeviceToolPrivate; + +struct _ClutterInputDeviceToolPrivate +{ + ClutterInputDeviceToolType type; + guint64 serial; + guint64 id; +}; + +enum { + PROP_0, + PROP_TYPE, + PROP_SERIAL, + PROP_ID, + PROP_LAST +}; + +static GParamSpec *props[PROP_LAST] = { NULL, }; + +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterInputDeviceTool, clutter_input_device_tool, G_TYPE_OBJECT) + +static void +clutter_input_device_tool_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterInputDeviceTool *tool = CLUTTER_INPUT_DEVICE_TOOL (object); + ClutterInputDeviceToolPrivate *priv; + + priv = clutter_input_device_tool_get_instance_private (tool); + + switch (prop_id) + { + case PROP_TYPE: + priv->type = g_value_get_enum (value); + break; + case PROP_SERIAL: + priv->serial = g_value_get_uint64 (value); + break; + case PROP_ID: + priv->id = g_value_get_uint64 (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +clutter_input_device_tool_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterInputDeviceTool *tool = CLUTTER_INPUT_DEVICE_TOOL (object); + ClutterInputDeviceToolPrivate *priv; + + priv = clutter_input_device_tool_get_instance_private (tool); + + switch (prop_id) + { + case PROP_TYPE: + g_value_set_enum (value, priv->type); + break; + case PROP_SERIAL: + g_value_set_uint64 (value, priv->serial); + break; + case PROP_ID: + g_value_set_uint64 (value, priv->id); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +clutter_input_device_tool_class_init (ClutterInputDeviceToolClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = clutter_input_device_tool_set_property; + gobject_class->get_property = clutter_input_device_tool_get_property; + + props[PROP_TYPE] = + g_param_spec_enum ("type", + P_("Tool type"), + P_("Tool type"), + CLUTTER_TYPE_INPUT_DEVICE_TOOL_TYPE, + CLUTTER_INPUT_DEVICE_TOOL_NONE, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + props[PROP_SERIAL] = + g_param_spec_uint64 ("serial", + P_("Tool serial"), + P_("Tool serial"), + 0, G_MAXUINT64, 0, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + props[PROP_ID] = + g_param_spec_uint64 ("id", + P_("Tool ID"), + P_("Tool ID"), + 0, G_MAXUINT64, 0, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + + g_object_class_install_properties (gobject_class, PROP_LAST, props); +} + +static void +clutter_input_device_tool_init (ClutterInputDeviceTool *tool) +{ +} + +/** + * clutter_input_device_tool_get_serial: + * @tool: a #ClutterInputDeviceTool + * + * Gets the serial of this tool, this value can be used to identify a + * physical tool (eg. a tablet pen) across program executions. + * + * Returns: The serial ID for this tool + * + * Since: 1.28 + **/ +guint64 +clutter_input_device_tool_get_serial (ClutterInputDeviceTool *tool) +{ + ClutterInputDeviceToolPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE_TOOL (tool), 0); + + priv = clutter_input_device_tool_get_instance_private (tool); + + return priv->serial; +} + + +/** + * clutter_input_device_tool_get_tool_type: + * @tool: a #ClutterInputDeviceTool + * + * Gets the tool type of this tool. + * + * Returns: The tool type of this tool + * + * Since: 1.28 + **/ +ClutterInputDeviceToolType +clutter_input_device_tool_get_tool_type (ClutterInputDeviceTool *tool) +{ + ClutterInputDeviceToolPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE_TOOL (tool), 0); + + priv = clutter_input_device_tool_get_instance_private (tool); + + return priv->type; +} + +/** + * clutter_input_device_tool_get_id: + * @tool: a #ClutterInputDeviceTool + * + * Gets the ID of this tool, this value can be used to identify a + * physical tool (eg. a tablet pen) across program executions. + * + * Returns: The tool ID for this tool + **/ +guint64 +clutter_input_device_tool_get_id (ClutterInputDeviceTool *tool) +{ + ClutterInputDeviceToolPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE_TOOL (tool), 0); + + priv = clutter_input_device_tool_get_instance_private (tool); + + return priv->id; +} diff --git a/clutter/clutter/clutter-input-device-tool.h b/clutter/clutter/clutter-input-device-tool.h new file mode 100644 index 0000000..0b7beef --- /dev/null +++ b/clutter/clutter/clutter-input-device-tool.h @@ -0,0 +1,69 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright © 2009, 2010, 2011 Intel Corp. + * + * 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 . + * + * Author: Carlos Garnacho + */ + +#ifndef __CLUTTER_INPUT_DEVICE_TOOL_H__ +#define __CLUTTER_INPUT_DEVICE_TOOL_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include "clutter-enum-types.h" + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_INPUT_DEVICE_TOOL (clutter_input_device_tool_get_type ()) +#define CLUTTER_INPUT_DEVICE_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_INPUT_DEVICE_TOOL, ClutterInputDeviceTool)) +#define CLUTTER_IS_INPUT_DEVICE_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_INPUT_DEVICE_TOOL)) +#define CLUTTER_INPUT_DEVICE_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_INPUT_DEVICE_TOOL, ClutterInputDeviceToolClass)) +#define CLUTTER_IS_INPUT_DEVICE_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_INPUT_DEVICE_TOOL)) +#define CLUTTER_INPUT_DEVICE_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_INPUT_DEVICE_TOOL, ClutterInputDeviceToolClass)) + +typedef struct _ClutterInputDeviceToolClass ClutterInputDeviceToolClass; + +struct _ClutterInputDeviceTool +{ + GObject parent_instance; +}; + +struct _ClutterInputDeviceToolClass +{ + GObjectClass parent_class; +}; + +CLUTTER_AVAILABLE_IN_ALL +GType clutter_input_device_tool_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_ALL +guint64 clutter_input_device_tool_get_serial (ClutterInputDeviceTool *tool); + +CLUTTER_AVAILABLE_IN_ALL +ClutterInputDeviceToolType clutter_input_device_tool_get_tool_type (ClutterInputDeviceTool *tool); + +CLUTTER_AVAILABLE_IN_ALL +guint64 clutter_input_device_tool_get_id (ClutterInputDeviceTool *tool); + +G_END_DECLS + +#endif /* __CLUTTER_INPUT_DEVICE_TOOL_H__ */ diff --git a/clutter/clutter/clutter-input-device.c b/clutter/clutter/clutter-input-device.c new file mode 100644 index 0000000..2930e56 --- /dev/null +++ b/clutter/clutter/clutter-input-device.c @@ -0,0 +1,2211 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright © 2009, 2010, 2011 Intel Corp. + * + * 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 . + * + * Author: Emmanuele Bassi + */ + +/** + * SECTION:clutter-input-device + * @short_description: An input device managed by Clutter + * + * #ClutterInputDevice represents an input device known to Clutter. + * + * The #ClutterInputDevice class holds the state of the device, but + * its contents are usually defined by the Clutter backend in use. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-input-device.h" + +#include "clutter-actor-private.h" +#include "clutter-debug.h" +#include "clutter-device-manager-private.h" +#include "clutter-enum-types.h" +#include "clutter-event-private.h" +#include "clutter-marshal.h" +#include "clutter-private.h" +#include "clutter-stage-private.h" +#include "clutter-input-device-tool.h" + +#include + +enum +{ + PROP_0, + + PROP_BACKEND, + + PROP_ID, + PROP_NAME, + + PROP_DEVICE_TYPE, + PROP_DEVICE_MANAGER, + PROP_DEVICE_MODE, + + PROP_HAS_CURSOR, + PROP_ENABLED, + + PROP_N_AXES, + + PROP_VENDOR_ID, + PROP_PRODUCT_ID, + + PROP_N_STRIPS, + PROP_N_RINGS, + PROP_N_MODE_GROUPS, + PROP_DEVICE_NODE, + PROP_MAPPING_MODE, + + PROP_LAST +}; + +static void _clutter_input_device_free_touch_info (gpointer data); +static void on_cursor_actor_destroy (ClutterActor *actor, + ClutterInputDevice *device); +static void on_cursor_actor_reactive_changed (ClutterActor *actor, + GParamSpec *pspec, + ClutterInputDevice *device); + +static GParamSpec *obj_props[PROP_LAST] = { NULL, }; + +G_DEFINE_TYPE (ClutterInputDevice, clutter_input_device, G_TYPE_OBJECT); + +static void +clutter_input_device_dispose (GObject *gobject) +{ + ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (gobject); + + g_clear_pointer (&device->device_name, g_free); + g_clear_pointer (&device->vendor_id, g_free); + g_clear_pointer (&device->product_id, g_free); + + if (device->associated != NULL) + { + if (device->device_mode == CLUTTER_INPUT_MODE_SLAVE) + _clutter_input_device_remove_slave (device->associated, device); + + _clutter_input_device_set_associated_device (device->associated, NULL); + g_object_unref (device->associated); + device->associated = NULL; + } + + g_clear_pointer (&device->axes, g_array_unref); + g_clear_pointer (&device->keys, g_array_unref); + g_clear_pointer (&device->scroll_info, g_array_unref); + g_clear_pointer (&device->touch_sequences_info, g_hash_table_unref); + + if (device->cursor_actor) + { + g_signal_handlers_disconnect_by_func (device->cursor_actor, + G_CALLBACK (on_cursor_actor_destroy), + device); + g_signal_handlers_disconnect_by_func (device->cursor_actor, + G_CALLBACK (on_cursor_actor_reactive_changed), + device); + _clutter_actor_set_has_pointer (device->cursor_actor, FALSE); + device->cursor_actor = NULL; + } + + if (device->inv_touch_sequence_actors) + { + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init (&iter, device->inv_touch_sequence_actors); + while (g_hash_table_iter_next (&iter, &key, &value)) + { + g_signal_handlers_disconnect_by_func (key, + G_CALLBACK (on_cursor_actor_destroy), + device); + g_signal_handlers_disconnect_by_func (device->cursor_actor, + G_CALLBACK (on_cursor_actor_reactive_changed), + device); + _clutter_actor_set_has_pointer (key, FALSE); + g_list_free (value); + } + + g_hash_table_unref (device->inv_touch_sequence_actors); + device->inv_touch_sequence_actors = NULL; + } + + G_OBJECT_CLASS (clutter_input_device_parent_class)->dispose (gobject); +} + +static void +clutter_input_device_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterInputDevice *self = CLUTTER_INPUT_DEVICE (gobject); + + switch (prop_id) + { + case PROP_ID: + self->id = g_value_get_int (value); + break; + + case PROP_DEVICE_TYPE: + self->device_type = g_value_get_enum (value); + break; + + case PROP_DEVICE_MANAGER: + self->device_manager = g_value_get_object (value); + break; + + case PROP_DEVICE_MODE: + self->device_mode = g_value_get_enum (value); + break; + + case PROP_BACKEND: + self->backend = g_value_get_object (value); + break; + + case PROP_NAME: + self->device_name = g_value_dup_string (value); + break; + + case PROP_HAS_CURSOR: + self->has_cursor = g_value_get_boolean (value); + break; + + case PROP_ENABLED: + clutter_input_device_set_enabled (self, g_value_get_boolean (value)); + break; + + case PROP_VENDOR_ID: + self->vendor_id = g_value_dup_string (value); + break; + + case PROP_PRODUCT_ID: + self->product_id = g_value_dup_string (value); + break; + + case PROP_N_RINGS: + self->n_rings = g_value_get_int (value); + break; + + case PROP_N_STRIPS: + self->n_strips = g_value_get_int (value); + break; + + case PROP_N_MODE_GROUPS: + self->n_mode_groups = g_value_get_int (value); + break; + + case PROP_DEVICE_NODE: + self->node_path = g_value_dup_string (value); + break; + + case PROP_MAPPING_MODE: + self->mapping_mode = g_value_get_enum (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_input_device_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterInputDevice *self = CLUTTER_INPUT_DEVICE (gobject); + + switch (prop_id) + { + case PROP_ID: + g_value_set_int (value, self->id); + break; + + case PROP_DEVICE_TYPE: + g_value_set_enum (value, self->device_type); + break; + + case PROP_DEVICE_MANAGER: + g_value_set_object (value, self->device_manager); + break; + + case PROP_DEVICE_MODE: + g_value_set_enum (value, self->device_mode); + break; + + case PROP_BACKEND: + g_value_set_object (value, self->backend); + break; + + case PROP_NAME: + g_value_set_string (value, self->device_name); + break; + + case PROP_HAS_CURSOR: + g_value_set_boolean (value, self->has_cursor); + break; + + case PROP_N_AXES: + g_value_set_uint (value, clutter_input_device_get_n_axes (self)); + break; + + case PROP_ENABLED: + g_value_set_boolean (value, self->is_enabled); + break; + + case PROP_VENDOR_ID: + g_value_set_string (value, self->vendor_id); + break; + + case PROP_PRODUCT_ID: + g_value_set_string (value, self->product_id); + break; + + case PROP_N_RINGS: + g_value_set_int (value, self->n_rings); + break; + + case PROP_N_STRIPS: + g_value_set_int (value, self->n_strips); + break; + + case PROP_N_MODE_GROUPS: + g_value_set_int (value, self->n_mode_groups); + break; + + case PROP_DEVICE_NODE: + g_value_set_string (value, self->node_path); + break; + + case PROP_MAPPING_MODE: + g_value_set_enum (value, self->mapping_mode); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_input_device_class_init (ClutterInputDeviceClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + /** + * ClutterInputDevice:id: + * + * The unique identifier of the device + * + * Since: 1.2 + */ + obj_props[PROP_ID] = + g_param_spec_int ("id", + P_("Id"), + P_("Unique identifier of the device"), + -1, G_MAXINT, + 0, + CLUTTER_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY); + + /** + * ClutterInputDevice:name: + * + * The name of the device + * + * Since: 1.2 + */ + obj_props[PROP_NAME] = + g_param_spec_string ("name", + P_("Name"), + P_("The name of the device"), + NULL, + CLUTTER_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY); + + /** + * ClutterInputDevice:device-type: + * + * The type of the device + * + * Since: 1.2 + */ + obj_props[PROP_DEVICE_TYPE] = + g_param_spec_enum ("device-type", + P_("Device Type"), + P_("The type of the device"), + CLUTTER_TYPE_INPUT_DEVICE_TYPE, + CLUTTER_POINTER_DEVICE, + CLUTTER_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY); + + /** + * ClutterInputDevice:device-manager: + * + * The #ClutterDeviceManager instance which owns the device + * + * Since: 1.6 + */ + obj_props[PROP_DEVICE_MANAGER] = + g_param_spec_object ("device-manager", + P_("Device Manager"), + P_("The device manager instance"), + CLUTTER_TYPE_DEVICE_MANAGER, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + + /** + * ClutterInputDevice:mode: + * + * The mode of the device. + * + * Since: 1.6 + */ + obj_props[PROP_DEVICE_MODE] = + g_param_spec_enum ("device-mode", + P_("Device Mode"), + P_("The mode of the device"), + CLUTTER_TYPE_INPUT_MODE, + CLUTTER_INPUT_MODE_FLOATING, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + + /** + * ClutterInputDevice:has-cursor: + * + * Whether the device has an on screen cursor following its movement. + * + * Since: 1.6 + */ + obj_props[PROP_HAS_CURSOR] = + g_param_spec_boolean ("has-cursor", + P_("Has Cursor"), + P_("Whether the device has a cursor"), + FALSE, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + + /** + * ClutterInputDevice:enabled: + * + * Whether the device is enabled. + * + * A device with the #ClutterInputDevice:device-mode property set + * to %CLUTTER_INPUT_MODE_MASTER cannot be disabled. + * + * A device must be enabled in order to receive events from it. + * + * Since: 1.6 + */ + obj_props[PROP_ENABLED] = + g_param_spec_boolean ("enabled", + P_("Enabled"), + P_("Whether the device is enabled"), + FALSE, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterInputDevice:n-axes: + * + * The number of axes of the device. + * + * Since: 1.6 + */ + obj_props[PROP_N_AXES] = + g_param_spec_uint ("n-axes", + P_("Number of Axes"), + P_("The number of axes on the device"), + 0, G_MAXUINT, + 0, + CLUTTER_PARAM_READABLE); + + /** + * ClutterInputDevice:backend: + * + * The #ClutterBackend that created the device. + * + * Since: 1.6 + */ + obj_props[PROP_BACKEND] = + g_param_spec_object ("backend", + P_("Backend"), + P_("The backend instance"), + CLUTTER_TYPE_BACKEND, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + + /** + * ClutterInputDevice:vendor-id: + * + * Vendor ID of this device. + * + * Since: 1.22 + */ + obj_props[PROP_VENDOR_ID] = + g_param_spec_string ("vendor-id", + P_("Vendor ID"), + P_("Vendor ID"), + NULL, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + + /** + * ClutterInputDevice:product-id: + * + * Product ID of this device. + * + * Since: 1.22 + */ + obj_props[PROP_PRODUCT_ID] = + g_param_spec_string ("product-id", + P_("Product ID"), + P_("Product ID"), + NULL, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + + obj_props[PROP_N_RINGS] = + g_param_spec_int ("n-rings", + P_("Number of rings"), + P_("Number of rings (circular sliders) in this device"), + 0, G_MAXINT, 0, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + + obj_props[PROP_N_STRIPS] = + g_param_spec_int ("n-strips", + P_("Number of strips"), + P_("Number of strips (linear sliders) in this device"), + 0, G_MAXINT, 0, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + + obj_props[PROP_N_MODE_GROUPS] = + g_param_spec_int ("n-mode-groups", + P_("Number of mode groups"), + P_("Number of mode groups"), + 0, G_MAXINT, 0, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + + obj_props[PROP_DEVICE_NODE] = + g_param_spec_string ("device-node", + P_("Device node path"), + P_("Device node path"), + NULL, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + + obj_props[PROP_MAPPING_MODE] = + g_param_spec_enum ("mapping-mode", + P_("Device mapping mode"), + P_("Device mapping mode"), + CLUTTER_TYPE_INPUT_DEVICE_MAPPING, + CLUTTER_INPUT_DEVICE_MAPPING_ABSOLUTE, + CLUTTER_PARAM_READWRITE); + + gobject_class->dispose = clutter_input_device_dispose; + gobject_class->set_property = clutter_input_device_set_property; + gobject_class->get_property = clutter_input_device_get_property; + g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); +} + +static void +clutter_input_device_init (ClutterInputDevice *self) +{ + self->id = -1; + self->device_type = CLUTTER_POINTER_DEVICE; + + self->click_count = 0; + + self->current_time = self->previous_time = CLUTTER_CURRENT_TIME; + self->current_x = self->previous_x = -1; + self->current_y = self->previous_y = -1; + self->current_button_number = self->previous_button_number = -1; + self->current_state = self->previous_state = 0; + + self->touch_sequences_info = + g_hash_table_new_full (NULL, NULL, + NULL, _clutter_input_device_free_touch_info); + self->inv_touch_sequence_actors = g_hash_table_new (NULL, NULL); +} + +static ClutterTouchInfo * +_clutter_input_device_ensure_touch_info (ClutterInputDevice *device, + ClutterEventSequence *sequence, + ClutterStage *stage) +{ + ClutterTouchInfo *info; + + info = g_hash_table_lookup (device->touch_sequences_info, sequence); + + if (info == NULL) + { + info = g_slice_new0 (ClutterTouchInfo); + info->sequence = sequence; + g_hash_table_insert (device->touch_sequences_info, sequence, info); + + if (g_hash_table_size (device->touch_sequences_info) == 1) + _clutter_input_device_set_stage (device, stage); + } + + return info; +} + +/*< private > + * clutter_input_device_set_coords: + * @device: a #ClutterInputDevice + * @sequence: a #ClutterEventSequence or NULL + * @x: X coordinate of the device + * @y: Y coordinate of the device + * + * Stores the last known coordinates of the device + */ +void +_clutter_input_device_set_coords (ClutterInputDevice *device, + ClutterEventSequence *sequence, + gfloat x, + gfloat y, + ClutterStage *stage) +{ + g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); + + if (sequence == NULL) + { + if (device->current_x != x) + device->current_x = x; + + if (device->current_y != y) + device->current_y = y; + } + else + { + ClutterTouchInfo *info; + info = _clutter_input_device_ensure_touch_info (device, sequence, stage); + info->current_x = x; + info->current_y = y; + } +} + +/*< private > + * clutter_input_device_set_state: + * @device: a #ClutterInputDevice + * @state: a bitmask of modifiers + * + * Stores the last known modifiers state of the device + */ +void +_clutter_input_device_set_state (ClutterInputDevice *device, + ClutterModifierType state) +{ + g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); + + device->current_state = state; +} + +/** + * clutter_input_device_get_modifier_state: + * @device: a #ClutterInputDevice + * + * Retrieves the current modifiers state of the device, as seen + * by the last event Clutter processed. + * + * Return value: the last known modifier state + * + * Since: 1.16 + */ +ClutterModifierType +clutter_input_device_get_modifier_state (ClutterInputDevice *device) +{ + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), 0); + + return device->current_state; +} + +/*< private > + * clutter_input_device_set_time: + * @device: a #ClutterInputDevice + * @time_: the time + * + * Stores the last known event time of the device + */ +void +_clutter_input_device_set_time (ClutterInputDevice *device, + guint32 time_) +{ + g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); + + if (device->current_time != time_) + device->current_time = time_; +} + +/*< private > + * clutter_input_device_set_stage: + * @device: a #ClutterInputDevice + * @stage: a #ClutterStage or %NULL + * + * Stores the stage under the device + */ +void +_clutter_input_device_set_stage (ClutterInputDevice *device, + ClutterStage *stage) +{ + if (device->stage == stage) + return; + + device->stage = stage; + + /* we leave the ->cursor_actor in place in order to check + * if we left the stage without crossing it again; this way + * we can emit a leave event on the cursor actor right before + * we emit the leave event on the stage. + */ +} + +/*< private > + * clutter_input_device_get_stage: + * @device: a #ClutterInputDevice + * + * Retrieves the stage currently associated with @device. + * + * Return value: The stage currently associated with @device. + */ +ClutterStage * +_clutter_input_device_get_stage (ClutterInputDevice *device) +{ + return device->stage; +} + +static void +_clutter_input_device_free_touch_info (gpointer data) +{ + g_slice_free (ClutterTouchInfo, data); +} + +static ClutterActor * +_clutter_input_device_get_actor (ClutterInputDevice *device, + ClutterEventSequence *sequence) +{ + ClutterTouchInfo *info; + + if (sequence == NULL) + return device->cursor_actor; + + info = g_hash_table_lookup (device->touch_sequences_info, sequence); + + return info->actor; +} + +static void +_clutter_input_device_associate_actor (ClutterInputDevice *device, + ClutterEventSequence *sequence, + ClutterActor *actor) +{ + if (sequence == NULL) + device->cursor_actor = actor; + else + { + GList *sequences = + g_hash_table_lookup (device->inv_touch_sequence_actors, actor); + ClutterTouchInfo *info; + ClutterStage *stage = CLUTTER_STAGE (clutter_actor_get_stage (actor)); + + info = _clutter_input_device_ensure_touch_info (device, sequence, stage); + info->actor = actor; + + g_hash_table_insert (device->inv_touch_sequence_actors, + actor, g_list_prepend (sequences, sequence)); + } + + g_signal_connect (actor, + "destroy", G_CALLBACK (on_cursor_actor_destroy), + device); + g_signal_connect (actor, + "notify::reactive", G_CALLBACK (on_cursor_actor_reactive_changed), + device); + _clutter_actor_set_has_pointer (actor, TRUE); +} + +static void +_clutter_input_device_unassociate_actor (ClutterInputDevice *device, + ClutterActor *actor, + gboolean destroyed) +{ + if (device->cursor_actor == actor) + device->cursor_actor = NULL; + else + { + GList *l, *sequences = + g_hash_table_lookup (device->inv_touch_sequence_actors, + actor); + + for (l = sequences; l != NULL; l = l->next) + { + ClutterTouchInfo *info = + g_hash_table_lookup (device->touch_sequences_info, l->data); + + if (info) + info->actor = NULL; + } + + g_list_free (sequences); + g_hash_table_remove (device->inv_touch_sequence_actors, actor); + } + + if (destroyed == FALSE) + { + g_signal_handlers_disconnect_by_func (actor, + G_CALLBACK (on_cursor_actor_destroy), + device); + g_signal_handlers_disconnect_by_func (actor, + G_CALLBACK (on_cursor_actor_reactive_changed), + device); + _clutter_actor_set_has_pointer (actor, FALSE); + } +} + +static void +on_cursor_actor_destroy (ClutterActor *actor, + ClutterInputDevice *device) +{ + _clutter_input_device_unassociate_actor (device, actor, TRUE); +} + +static void +on_cursor_actor_reactive_changed (ClutterActor *actor, + GParamSpec *pspec, + ClutterInputDevice *device) +{ + if (!clutter_actor_get_reactive (actor)) + _clutter_input_device_unassociate_actor (device, actor, FALSE); +} + +/*< private > + * clutter_input_device_set_actor: + * @device: a #ClutterInputDevice + * @actor: a #ClutterActor + * @emit_crossing: %TRUE to emit crossing events + * + * Sets the actor under the pointer coordinates of @device + * + * This function is called by _clutter_input_device_update() + * and it will: + * + * - queue a %CLUTTER_LEAVE event on the previous pointer actor + * of @device, if any + * - set to %FALSE the :has-pointer property of the previous + * pointer actor of @device, if any + * - queue a %CLUTTER_ENTER event on the new pointer actor + * - set to %TRUE the :has-pointer property of the new pointer + * actor + */ +void +_clutter_input_device_set_actor (ClutterInputDevice *device, + ClutterEventSequence *sequence, + ClutterActor *actor, + gboolean emit_crossing) +{ + ClutterActor *old_actor = _clutter_input_device_get_actor (device, sequence); + + if (old_actor == actor) + return; + + if (old_actor != NULL) + { + ClutterActor *tmp_old_actor; + + if (emit_crossing) + { + ClutterEvent *event; + + event = clutter_event_new (CLUTTER_LEAVE); + event->crossing.time = device->current_time; + event->crossing.flags = 0; + event->crossing.stage = device->stage; + event->crossing.source = old_actor; + event->crossing.x = device->current_x; + event->crossing.y = device->current_y; + event->crossing.related = actor; + clutter_event_set_device (event, device); + + /* we need to make sure that this event is processed + * before any other event we might have queued up until + * now, so we go on, and synthesize the event emission + * ourselves + */ + _clutter_process_event (event); + + clutter_event_free (event); + } + + /* processing the event might have destroyed the actor */ + tmp_old_actor = _clutter_input_device_get_actor (device, sequence); + _clutter_input_device_unassociate_actor (device, + old_actor, + tmp_old_actor == NULL); + old_actor = tmp_old_actor; + } + + if (actor != NULL) + { + _clutter_input_device_associate_actor (device, sequence, actor); + + if (emit_crossing) + { + ClutterEvent *event; + + event = clutter_event_new (CLUTTER_ENTER); + event->crossing.time = device->current_time; + event->crossing.flags = 0; + event->crossing.stage = device->stage; + event->crossing.x = device->current_x; + event->crossing.y = device->current_y; + event->crossing.source = actor; + event->crossing.related = old_actor; + clutter_event_set_device (event, device); + + /* see above */ + _clutter_process_event (event); + + clutter_event_free (event); + } + } +} + +/** + * clutter_input_device_get_device_type: + * @device: a #ClutterInputDevice + * + * Retrieves the type of @device + * + * Return value: the type of the device + * + * Since: 1.0 + */ +ClutterInputDeviceType +clutter_input_device_get_device_type (ClutterInputDevice *device) +{ + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), + CLUTTER_POINTER_DEVICE); + + return device->device_type; +} + +/** + * clutter_input_device_get_device_id: + * @device: a #ClutterInputDevice + * + * Retrieves the unique identifier of @device + * + * Return value: the identifier of the device + * + * Since: 1.0 + */ +gint +clutter_input_device_get_device_id (ClutterInputDevice *device) +{ + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), -1); + + return device->id; +} + +/** + * clutter_input_device_set_enabled: + * @device: a #ClutterInputDevice + * @enabled: %TRUE to enable the @device + * + * Enables or disables a #ClutterInputDevice. + * + * Only devices with a #ClutterInputDevice:device-mode property set + * to %CLUTTER_INPUT_MODE_SLAVE or %CLUTTER_INPUT_MODE_FLOATING can + * be disabled. + * + * Since: 1.6 + */ +void +clutter_input_device_set_enabled (ClutterInputDevice *device, + gboolean enabled) +{ + g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); + + enabled = !!enabled; + + if (!enabled && device->device_mode == CLUTTER_INPUT_MODE_MASTER) + return; + + if (device->is_enabled == enabled) + return; + + device->is_enabled = enabled; + + g_object_notify_by_pspec (G_OBJECT (device), obj_props[PROP_ENABLED]); +} + +/** + * clutter_input_device_get_enabled: + * @device: a #ClutterInputDevice + * + * Retrieves whether @device is enabled. + * + * Return value: %TRUE if the device is enabled + * + * Since: 1.6 + */ +gboolean +clutter_input_device_get_enabled (ClutterInputDevice *device) +{ + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE); + + return device->is_enabled; +} + +/** + * clutter_input_device_get_coords: + * @device: a #ClutterInputDevice + * @sequence: (allow-none): a #ClutterEventSequence, or %NULL if + * the device is not touch-based + * @point: (out caller-allocates): return location for the pointer + * or touch point + * + * Retrieves the latest coordinates of a pointer or touch point of + * @device. + * + * Return value: %FALSE if the device's sequence hasn't been found, + * and %TRUE otherwise. + * + * Since: 1.12 + */ +gboolean +clutter_input_device_get_coords (ClutterInputDevice *device, + ClutterEventSequence *sequence, + ClutterPoint *point) +{ + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE); + g_return_val_if_fail (point != NULL, FALSE); + + if (sequence == NULL) + { + point->x = device->current_x; + point->y = device->current_y; + } + else + { + ClutterTouchInfo *info = + g_hash_table_lookup (device->touch_sequences_info, sequence); + + if (info == NULL) + return FALSE; + + point->x = info->current_x; + point->y = info->current_y; + } + + return TRUE; +} + +/* + * _clutter_input_device_update: + * @device: a #ClutterInputDevice + * + * Updates the input @device by determining the #ClutterActor underneath the + * pointer's cursor + * + * This function calls _clutter_input_device_set_actor() if needed. + * + * This function only works for #ClutterInputDevice of type + * %CLUTTER_POINTER_DEVICE. + * + * Since: 1.2 + */ +ClutterActor * +_clutter_input_device_update (ClutterInputDevice *device, + ClutterEventSequence *sequence, + gboolean emit_crossing) +{ + ClutterStage *stage; + ClutterActor *new_cursor_actor; + ClutterActor *old_cursor_actor; + ClutterPoint point = { -1, -1 }; + + if (device->device_type == CLUTTER_KEYBOARD_DEVICE) + return NULL; + + stage = device->stage; + if (G_UNLIKELY (stage == NULL)) + { + CLUTTER_NOTE (EVENT, "No stage defined for device %d '%s'", + clutter_input_device_get_device_id (device), + clutter_input_device_get_device_name (device)); + return NULL; + } + + clutter_input_device_get_coords (device, sequence, &point); + + old_cursor_actor = _clutter_input_device_get_actor (device, sequence); + new_cursor_actor = + _clutter_stage_do_pick (stage, point.x, point.y, CLUTTER_PICK_REACTIVE); + + /* if the pick could not find an actor then we do not update the + * input device, to avoid ghost enter/leave events; the pick should + * never fail, except for bugs in the glReadPixels() implementation + * in which case this is the safest course of action anyway + */ + if (new_cursor_actor == NULL) + return NULL; + + CLUTTER_NOTE (EVENT, + "Actor under cursor (device %d, at %.2f, %.2f): %s", + clutter_input_device_get_device_id (device), + point.x, + point.y, + _clutter_actor_get_debug_name (new_cursor_actor)); + + /* short-circuit here */ + if (new_cursor_actor == old_cursor_actor) + return old_cursor_actor; + + _clutter_input_device_set_actor (device, sequence, + new_cursor_actor, + emit_crossing); + + return new_cursor_actor; +} + +/** + * clutter_input_device_get_pointer_actor: + * @device: a #ClutterInputDevice of type %CLUTTER_POINTER_DEVICE + * + * Retrieves the #ClutterActor underneath the pointer of @device + * + * Return value: (transfer none): a pointer to the #ClutterActor or %NULL + * + * Since: 1.2 + */ +ClutterActor * +clutter_input_device_get_pointer_actor (ClutterInputDevice *device) +{ + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL); + g_return_val_if_fail (device->device_type == CLUTTER_POINTER_DEVICE, NULL); + + return device->cursor_actor; +} + +/** + * clutter_input_device_get_pointer_stage: + * @device: a #ClutterInputDevice of type %CLUTTER_POINTER_DEVICE + * + * Retrieves the #ClutterStage underneath the pointer of @device + * + * Return value: (transfer none): a pointer to the #ClutterStage or %NULL + * + * Since: 1.2 + */ +ClutterStage * +clutter_input_device_get_pointer_stage (ClutterInputDevice *device) +{ + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL); + g_return_val_if_fail (device->device_type == CLUTTER_POINTER_DEVICE, NULL); + + return device->stage; +} + +/** + * clutter_input_device_get_device_name: + * @device: a #ClutterInputDevice + * + * Retrieves the name of the @device + * + * Return value: the name of the device, or %NULL. The returned string + * is owned by the #ClutterInputDevice and should never be modified + * or freed + * + * Since: 1.2 + */ +const gchar * +clutter_input_device_get_device_name (ClutterInputDevice *device) +{ + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL); + + return device->device_name; +} + +/** + * clutter_input_device_get_has_cursor: + * @device: a #ClutterInputDevice + * + * Retrieves whether @device has a pointer that follows the + * device motion. + * + * Return value: %TRUE if the device has a cursor + * + * Since: 1.6 + */ +gboolean +clutter_input_device_get_has_cursor (ClutterInputDevice *device) +{ + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE); + + return device->has_cursor; +} + +/** + * clutter_input_device_get_device_mode: + * @device: a #ClutterInputDevice + * + * Retrieves the #ClutterInputMode of @device. + * + * Return value: the device mode + * + * Since: 1.6 + */ +ClutterInputMode +clutter_input_device_get_device_mode (ClutterInputDevice *device) +{ + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), + CLUTTER_INPUT_MODE_FLOATING); + + return device->device_mode; +} + +/** + * clutter_input_device_update_from_event: + * @device: a #ClutterInputDevice + * @event: a #ClutterEvent + * @update_stage: whether to update the #ClutterStage of the @device + * using the stage of the event + * + * Forcibly updates the state of the @device using a #ClutterEvent + * + * This function should never be used by applications: it is meant + * for integration with embedding toolkits, like clutter-gtk + * + * Embedding toolkits that disable the event collection inside Clutter + * need to use this function to update the state of input devices depending + * on a #ClutterEvent that they are going to submit to the event handling code + * in Clutter though clutter_do_event(). Since the input devices hold the state + * that is going to be used to fill in fields like the #ClutterButtonEvent + * click count, or to emit synthesized events like %CLUTTER_ENTER and + * %CLUTTER_LEAVE, it is necessary for embedding toolkits to also be + * responsible of updating the input device state. + * + * For instance, this might be the code to translate an embedding toolkit + * native motion notification into a Clutter #ClutterMotionEvent and ask + * Clutter to process it: + * + * |[ + * ClutterEvent c_event; + * + * translate_native_event_to_clutter (native_event, &c_event); + * + * clutter_do_event (&c_event); + * ]| + * + * Before letting clutter_do_event() process the event, it is necessary to call + * clutter_input_device_update_from_event(): + * + * |[ + * ClutterEvent c_event; + * ClutterDeviceManager *manager; + * ClutterInputDevice *device; + * + * translate_native_event_to_clutter (native_event, &c_event); + * + * // get the device manager + * manager = clutter_device_manager_get_default (); + * + * // use the default Core Pointer that Clutter backends register by default + * device = clutter_device_manager_get_core_device (manager, %CLUTTER_POINTER_DEVICE); + * + * // update the state of the input device + * clutter_input_device_update_from_event (device, &c_event, FALSE); + * + * clutter_do_event (&c_event); + * ]| + * + * The @update_stage boolean argument should be used when the input device + * enters and leaves a #ClutterStage; it will use the #ClutterStage field + * of the passed @event to update the stage associated to the input device. + * + * Since: 1.2 + */ +void +clutter_input_device_update_from_event (ClutterInputDevice *device, + ClutterEvent *event, + gboolean update_stage) +{ + ClutterModifierType event_state; + ClutterEventSequence *sequence; + ClutterStage *event_stage; + gfloat event_x, event_y; + guint32 event_time; + + g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); + g_return_if_fail (event != NULL); + + event_state = clutter_event_get_state (event); + event_time = clutter_event_get_time (event); + event_stage = clutter_event_get_stage (event); + sequence = clutter_event_get_event_sequence (event); + clutter_event_get_coords (event, &event_x, &event_y); + + _clutter_input_device_set_coords (device, sequence, event_x, event_y, event_stage); + _clutter_input_device_set_state (device, event_state); + _clutter_input_device_set_time (device, event_time); + + if (update_stage) + _clutter_input_device_set_stage (device, event_stage); +} + +/*< private > + * clutter_input_device_reset_axes: + * @device: a #ClutterInputDevice + * + * Resets the axes on @device + */ +void +_clutter_input_device_reset_axes (ClutterInputDevice *device) +{ + if (device->axes != NULL) + { + g_array_free (device->axes, TRUE); + device->axes = NULL; + + g_object_notify_by_pspec (G_OBJECT (device), obj_props[PROP_N_AXES]); + } +} + +/*< private > + * clutter_input_device_add_axis: + * @device: a #ClutterInputDevice + * @axis: the axis type + * @minimum: the minimum axis value + * @maximum: the maximum axis value + * @resolution: the axis resolution + * + * Adds an axis of type @axis on @device. + */ +guint +_clutter_input_device_add_axis (ClutterInputDevice *device, + ClutterInputAxis axis, + gdouble minimum, + gdouble maximum, + gdouble resolution) +{ + ClutterAxisInfo info; + guint pos; + + if (device->axes == NULL) + device->axes = g_array_new (FALSE, TRUE, sizeof (ClutterAxisInfo)); + + info.axis = axis; + info.min_value = minimum; + info.max_value = maximum; + info.resolution = resolution; + + switch (axis) + { + case CLUTTER_INPUT_AXIS_X: + case CLUTTER_INPUT_AXIS_Y: + info.min_axis = 0; + info.max_axis = 0; + break; + + case CLUTTER_INPUT_AXIS_XTILT: + case CLUTTER_INPUT_AXIS_YTILT: + info.min_axis = -1; + info.max_axis = 1; + break; + + default: + info.min_axis = 0; + info.max_axis = 1; + break; + } + + device->axes = g_array_append_val (device->axes, info); + pos = device->axes->len - 1; + + g_object_notify_by_pspec (G_OBJECT (device), obj_props[PROP_N_AXES]); + + return pos; +} + +/*< private > + * clutter_input_translate_axis: + * @device: a #ClutterInputDevice + * @index_: the index of the axis + * @gint: the absolute value of the axis + * @axis_value: (out): the translated value of the axis + * + * Performs a conversion from the absolute value of the axis + * to a relative value. + * + * The axis at @index_ must not be %CLUTTER_INPUT_AXIS_X or + * %CLUTTER_INPUT_AXIS_Y. + * + * Return value: %TRUE if the conversion was successful + */ +gboolean +_clutter_input_device_translate_axis (ClutterInputDevice *device, + guint index_, + gdouble value, + gdouble *axis_value) +{ + ClutterAxisInfo *info; + gdouble width; + gdouble real_value; + + if (device->axes == NULL || index_ >= device->axes->len) + return FALSE; + + info = &g_array_index (device->axes, ClutterAxisInfo, index_); + + if (info->axis == CLUTTER_INPUT_AXIS_X || + info->axis == CLUTTER_INPUT_AXIS_Y) + return FALSE; + + if (fabs (info->max_value - info->min_value) < 0.0000001) + return FALSE; + + width = info->max_value - info->min_value; + real_value = (info->max_axis * (value - info->min_value) + + info->min_axis * (info->max_value - value)) + / width; + + if (axis_value) + *axis_value = real_value; + + return TRUE; +} + +/** + * clutter_input_device_get_axis: + * @device: a #ClutterInputDevice + * @index_: the index of the axis + * + * Retrieves the type of axis on @device at the given index. + * + * Return value: the axis type + * + * Since: 1.6 + */ +ClutterInputAxis +clutter_input_device_get_axis (ClutterInputDevice *device, + guint index_) +{ + ClutterAxisInfo *info; + + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), + CLUTTER_INPUT_AXIS_IGNORE); + + if (device->axes == NULL) + return CLUTTER_INPUT_AXIS_IGNORE; + + if (index_ >= device->axes->len) + return CLUTTER_INPUT_AXIS_IGNORE; + + info = &g_array_index (device->axes, ClutterAxisInfo, index_); + + return info->axis; +} + +/** + * clutter_input_device_get_axis_value: + * @device: a #ClutterInputDevice + * @axes: (array): an array of axes values, typically + * coming from clutter_event_get_axes() + * @axis: the axis to extract + * @value: (out): return location for the axis value + * + * Extracts the value of the given @axis of a #ClutterInputDevice from + * an array of axis values. + * + * An example of typical usage for this function is: + * + * |[ + * ClutterInputDevice *device = clutter_event_get_device (event); + * gdouble *axes = clutter_event_get_axes (event, NULL); + * gdouble pressure_value = 0; + * + * clutter_input_device_get_axis_value (device, axes, + * CLUTTER_INPUT_AXIS_PRESSURE, + * &pressure_value); + * ]| + * + * Return value: %TRUE if the value was set, and %FALSE otherwise + * + * Since: 1.6 + */ +gboolean +clutter_input_device_get_axis_value (ClutterInputDevice *device, + gdouble *axes, + ClutterInputAxis axis, + gdouble *value) +{ + gint i; + + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE); + g_return_val_if_fail (device->axes != NULL, FALSE); + + for (i = 0; i < device->axes->len; i++) + { + ClutterAxisInfo *info; + + info = &g_array_index (device->axes, ClutterAxisInfo, i); + + if (info->axis == axis) + { + if (value) + *value = axes[i]; + + return TRUE; + } + } + + return FALSE; +} + +/** + * clutter_input_device_get_n_axes: + * @device: a #ClutterInputDevice + * + * Retrieves the number of axes available on @device. + * + * Return value: the number of axes on the device + * + * Since: 1.6 + */ +guint +clutter_input_device_get_n_axes (ClutterInputDevice *device) +{ + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), 0); + + if (device->axes != NULL) + return device->axes->len; + + return 0; +} + +/*< private > + * clutter_input_device_set_n_keys: + * @device: a #ClutterInputDevice + * @n_keys: the number of keys of the device + * + * Initializes the keys of @device. + * + * Call clutter_input_device_set_key() on each key to set the keyval + * and modifiers. + */ +void +_clutter_input_device_set_n_keys (ClutterInputDevice *device, + guint n_keys) +{ + if (device->keys != NULL) + g_array_free (device->keys, TRUE); + + device->n_keys = n_keys; + device->keys = g_array_sized_new (FALSE, TRUE, + sizeof (ClutterKeyInfo), + n_keys); +} + +/** + * clutter_input_device_get_n_keys: + * @device: a #ClutterInputDevice + * + * Retrieves the number of keys registered for @device. + * + * Return value: the number of registered keys + * + * Since: 1.6 + */ +guint +clutter_input_device_get_n_keys (ClutterInputDevice *device) +{ + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), 0); + + return device->n_keys; +} + +/** + * clutter_input_device_set_key: + * @device: a #ClutterInputDevice + * @index_: the index of the key + * @keyval: the keyval + * @modifiers: a bitmask of modifiers + * + * Sets the keyval and modifiers at the given @index_ for @device. + * + * Clutter will use the keyval and modifiers set when filling out + * an event coming from the same input device. + * + * Since: 1.6 + */ +void +clutter_input_device_set_key (ClutterInputDevice *device, + guint index_, + guint keyval, + ClutterModifierType modifiers) +{ + ClutterKeyInfo *key_info; + + g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); + g_return_if_fail (index_ < device->n_keys); + + key_info = &g_array_index (device->keys, ClutterKeyInfo, index_); + key_info->keyval = keyval; + key_info->modifiers = modifiers; +} + +/** + * clutter_input_device_get_key: + * @device: a #ClutterInputDevice + * @index_: the index of the key + * @keyval: (out): return location for the keyval at @index_ + * @modifiers: (out): return location for the modifiers at @index_ + * + * Retrieves the key set using clutter_input_device_set_key() + * + * Return value: %TRUE if a key was set at the given index + * + * Since: 1.6 + */ +gboolean +clutter_input_device_get_key (ClutterInputDevice *device, + guint index_, + guint *keyval, + ClutterModifierType *modifiers) +{ + ClutterKeyInfo *key_info; + + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE); + + if (device->keys == NULL) + return FALSE; + + if (index_ > device->keys->len) + return FALSE; + + key_info = &g_array_index (device->keys, ClutterKeyInfo, index_); + + if (!key_info->keyval && !key_info->modifiers) + return FALSE; + + if (keyval) + *keyval = key_info->keyval; + + if (modifiers) + *modifiers = key_info->modifiers; + + return TRUE; +} + +/*< private > + * clutter_input_device_add_slave: + * @master: a #ClutterInputDevice + * @slave: a #ClutterInputDevice + * + * Adds @slave to the list of slave devices of @master + * + * This function does not increase the reference count of either @master + * or @slave. + */ +void +_clutter_input_device_add_slave (ClutterInputDevice *master, + ClutterInputDevice *slave) +{ + if (g_list_find (master->slaves, slave) == NULL) + master->slaves = g_list_prepend (master->slaves, slave); +} + +/*< private > + * clutter_input_device_remove_slave: + * @master: a #ClutterInputDevice + * @slave: a #ClutterInputDevice + * + * Removes @slave from the list of slave devices of @master. + * + * This function does not decrease the reference count of either @master + * or @slave. + */ +void +_clutter_input_device_remove_slave (ClutterInputDevice *master, + ClutterInputDevice *slave) +{ + if (g_list_find (master->slaves, slave) != NULL) + master->slaves = g_list_remove (master->slaves, slave); +} + +/*< private > + * clutter_input_device_add_sequence: + * @device: a #ClutterInputDevice + * @sequence: a #ClutterEventSequence + * + * Start tracking informations related to a touch point (position, + * actor underneath the touch point). + */ +void +_clutter_input_device_add_event_sequence (ClutterInputDevice *device, + ClutterEvent *event) +{ + ClutterEventSequence *sequence = clutter_event_get_event_sequence (event); + ClutterStage *stage; + + if (sequence == NULL) + return; + + stage = clutter_event_get_stage (event); + if (stage == NULL) + return; + + _clutter_input_device_ensure_touch_info (device, sequence, stage); +} + +/*< private > + * clutter_input_device_remove_sequence: + * @device: a #ClutterInputDevice + * @sequence: a #ClutterEventSequence + * + * Stop tracking informations related to a touch point. + */ +void +_clutter_input_device_remove_event_sequence (ClutterInputDevice *device, + ClutterEvent *event) +{ + ClutterEventSequence *sequence = clutter_event_get_event_sequence (event); + ClutterTouchInfo *info = + g_hash_table_lookup (device->touch_sequences_info, sequence); + + if (info == NULL) + return; + + if (info->actor != NULL) + { + GList *sequences = + g_hash_table_lookup (device->inv_touch_sequence_actors, info->actor); + + sequences = g_list_remove (sequences, sequence); + + g_hash_table_replace (device->inv_touch_sequence_actors, + info->actor, sequences); + _clutter_input_device_set_actor (device, sequence, NULL, TRUE); + } + + g_hash_table_remove (device->touch_sequences_info, sequence); +} + +/** + * clutter_input_device_get_slave_devices: + * @device: a #ClutterInputDevice + * + * Retrieves the slave devices attached to @device. + * + * Return value: (transfer container) (element-type Clutter.InputDevice): a + * list of #ClutterInputDevice, or %NULL. The contents of the list are + * owned by the device. Use g_list_free() when done + * + * Since: 1.6 + */ +GList * +clutter_input_device_get_slave_devices (ClutterInputDevice *device) +{ + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL); + + return g_list_copy (device->slaves); +} + +/*< internal > + * clutter_input_device_set_associated_device: + * @device: a #ClutterInputDevice + * @associated: (allow-none): a #ClutterInputDevice, or %NULL + * + * Sets the associated device for @device. + * + * This function keeps a reference on the associated device. + */ +void +_clutter_input_device_set_associated_device (ClutterInputDevice *device, + ClutterInputDevice *associated) +{ + if (device->associated == associated) + return; + + if (device->associated != NULL) + g_object_unref (device->associated); + + device->associated = associated; + if (device->associated != NULL) + g_object_ref (device->associated); + + CLUTTER_NOTE (MISC, "Associating device %d '%s' to device %d '%s'", + clutter_input_device_get_device_id (device), + clutter_input_device_get_device_name (device), + device->associated != NULL + ? clutter_input_device_get_device_id (device->associated) + : -1, + device->associated != NULL + ? clutter_input_device_get_device_name (device->associated) + : "(none)"); + + if (device->device_mode != CLUTTER_INPUT_MODE_MASTER) + { + if (device->associated != NULL) + device->device_mode = CLUTTER_INPUT_MODE_SLAVE; + else + device->device_mode = CLUTTER_INPUT_MODE_FLOATING; + + g_object_notify_by_pspec (G_OBJECT (device), obj_props[PROP_DEVICE_MODE]); + } +} + +/** + * clutter_input_device_get_associated_device: + * @device: a #ClutterInputDevice + * + * Retrieves a pointer to the #ClutterInputDevice that has been + * associated to @device. + * + * If the #ClutterInputDevice:device-mode property of @device is + * set to %CLUTTER_INPUT_MODE_MASTER, this function will return + * %NULL. + * + * Return value: (transfer none): a #ClutterInputDevice, or %NULL + * + * Since: 1.6 + */ +ClutterInputDevice * +clutter_input_device_get_associated_device (ClutterInputDevice *device) +{ + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL); + + return device->associated; +} + +/** + * clutter_input_device_keycode_to_evdev: + * @device: A #ClutterInputDevice + * @hardware_keycode: The hardware keycode from a #ClutterKeyEvent + * @evdev_keycode: The return location for the evdev keycode + * + * Translates a hardware keycode from a #ClutterKeyEvent to the + * equivalent evdev keycode. Note that depending on the input backend + * used by Clutter this function can fail if there is no obvious + * mapping between the key codes. The hardware keycode can be taken + * from the #ClutterKeyEvent.hardware_keycode member of #ClutterKeyEvent. + * + * Return value: %TRUE if the conversion succeeded, %FALSE otherwise. + * + * Since: 1.10 + */ +gboolean +clutter_input_device_keycode_to_evdev (ClutterInputDevice *device, + guint hardware_keycode, + guint *evdev_keycode) +{ + ClutterInputDeviceClass *device_class; + + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE); + + device_class = CLUTTER_INPUT_DEVICE_GET_CLASS (device); + if (device_class->keycode_to_evdev == NULL) + return FALSE; + else + return device_class->keycode_to_evdev (device, + hardware_keycode, + evdev_keycode); +} + +void +_clutter_input_device_add_scroll_info (ClutterInputDevice *device, + guint index_, + ClutterScrollDirection direction, + gdouble increment) +{ + ClutterScrollInfo info; + + g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); + g_return_if_fail (index_ < clutter_input_device_get_n_axes (device)); + + info.axis_id = index_; + info.direction = direction; + info.increment = increment; + info.last_value_valid = FALSE; + + if (device->scroll_info == NULL) + { + device->scroll_info = g_array_new (FALSE, + FALSE, + sizeof (ClutterScrollInfo)); + } + + g_array_append_val (device->scroll_info, info); +} + +gboolean +_clutter_input_device_get_scroll_delta (ClutterInputDevice *device, + guint index_, + gdouble value, + ClutterScrollDirection *direction_p, + gdouble *delta_p) +{ + guint i; + + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE); + g_return_val_if_fail (index_ < clutter_input_device_get_n_axes (device), FALSE); + + if (device->scroll_info == NULL) + return FALSE; + + for (i = 0; i < device->scroll_info->len; i++) + { + ClutterScrollInfo *info = &g_array_index (device->scroll_info, + ClutterScrollInfo, + i); + + if (info->axis_id == index_) + { + if (direction_p != NULL) + *direction_p = info->direction; + + if (delta_p != NULL) + *delta_p = 0.0; + + if (info->last_value_valid) + { + if (delta_p != NULL) + { + *delta_p = (value - info->last_value) + / info->increment; + } + + info->last_value = value; + } + else + { + info->last_value = value; + info->last_value_valid = TRUE; + } + + return TRUE; + } + } + + return FALSE; +} + +void +_clutter_input_device_reset_scroll_info (ClutterInputDevice *device) +{ + guint i; + + if (device->scroll_info == NULL) + return; + + for (i = 0; i < device->scroll_info->len; i++) + { + ClutterScrollInfo *info = &g_array_index (device->scroll_info, + ClutterScrollInfo, + i); + + info->last_value_valid = FALSE; + } +} + +static void +on_grab_sequence_actor_destroy (ClutterActor *actor, + ClutterInputDevice *device) +{ + ClutterEventSequence *sequence = + g_hash_table_lookup (device->inv_sequence_grab_actors, actor); + + if (sequence != NULL) + { + g_hash_table_remove (device->sequence_grab_actors, sequence); + g_hash_table_remove (device->inv_sequence_grab_actors, actor); + } +} + +/** + * clutter_input_device_sequence_grab: + * @device: a #ClutterInputDevice + * @sequence: a #ClutterEventSequence + * @actor: a #ClutterActor + * + * Acquires a grab on @actor for the given @device and the given touch + * @sequence. + * + * Any touch event coming from @device and from @sequence will be + * delivered to @actor, bypassing the usual event delivery mechanism, + * until the grab is released by calling + * clutter_input_device_sequence_ungrab(). + * + * The grab is client-side: even if the windowing system used by the Clutter + * backend has the concept of "device grabs", Clutter will not use them. + * + * Since: 1.12 + */ +void +clutter_input_device_sequence_grab (ClutterInputDevice *device, + ClutterEventSequence *sequence, + ClutterActor *actor) +{ + ClutterActor *grab_actor; + + g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + if (device->sequence_grab_actors == NULL) + { + grab_actor = NULL; + device->sequence_grab_actors = g_hash_table_new (NULL, NULL); + device->inv_sequence_grab_actors = g_hash_table_new (NULL, NULL); + } + else + { + grab_actor = g_hash_table_lookup (device->sequence_grab_actors, sequence); + } + + if (grab_actor != NULL) + { + g_signal_handlers_disconnect_by_func (grab_actor, + G_CALLBACK (on_grab_sequence_actor_destroy), + device); + g_hash_table_remove (device->sequence_grab_actors, sequence); + g_hash_table_remove (device->inv_sequence_grab_actors, grab_actor); + } + + g_hash_table_insert (device->sequence_grab_actors, sequence, actor); + g_hash_table_insert (device->inv_sequence_grab_actors, actor, sequence); + g_signal_connect (actor, + "destroy", + G_CALLBACK (on_grab_sequence_actor_destroy), + device); +} + +/** + * clutter_input_device_sequence_ungrab: + * @device: a #ClutterInputDevice + * @sequence: a #ClutterEventSequence + * + * Releases the grab on the @device for the given @sequence, if one is + * in place. + * + * Since: 1.12 + */ +void +clutter_input_device_sequence_ungrab (ClutterInputDevice *device, + ClutterEventSequence *sequence) +{ + ClutterActor *grab_actor; + + g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); + + if (device->sequence_grab_actors == NULL) + return; + + grab_actor = g_hash_table_lookup (device->sequence_grab_actors, sequence); + + if (grab_actor == NULL) + return; + + g_signal_handlers_disconnect_by_func (grab_actor, + G_CALLBACK (on_grab_sequence_actor_destroy), + device); + g_hash_table_remove (device->sequence_grab_actors, sequence); + g_hash_table_remove (device->inv_sequence_grab_actors, grab_actor); + + if (g_hash_table_size (device->sequence_grab_actors) == 0) + { + g_hash_table_destroy (device->sequence_grab_actors); + device->sequence_grab_actors = NULL; + g_hash_table_destroy (device->inv_sequence_grab_actors); + device->inv_sequence_grab_actors = NULL; + } +} + +/** + * clutter_input_device_sequence_get_grabbed_actor: + * @device: a #ClutterInputDevice + * @sequence: a #ClutterEventSequence + * + * Retrieves a pointer to the #ClutterActor currently grabbing the + * touch events coming from @device given the @sequence. + * + * Return value: (transfer none): a #ClutterActor, or %NULL + * + * Since: 1.12 + */ +ClutterActor * +clutter_input_device_sequence_get_grabbed_actor (ClutterInputDevice *device, + ClutterEventSequence *sequence) +{ + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL); + + if (device->sequence_grab_actors == NULL) + return NULL; + + return g_hash_table_lookup (device->sequence_grab_actors, sequence); +} + +/** + * clutter_input_device_get_vendor_id: + * @device: a slave #ClutterInputDevice + * + * Gets the vendor ID of this device. + * + * Returns: the vendor ID + * + * Since: 1.22 + */ +const gchar * +clutter_input_device_get_vendor_id (ClutterInputDevice *device) +{ + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL); + g_return_val_if_fail (clutter_input_device_get_device_mode (device) != CLUTTER_INPUT_MODE_MASTER, NULL); + + return device->vendor_id; +} + +/** + * clutter_input_device_get_product_id: + * @device: a slave #ClutterInputDevice + * + * Gets the product ID of this device. + * + * Returns: the product ID + * + * Since: 1.22 + */ +const gchar * +clutter_input_device_get_product_id (ClutterInputDevice *device) +{ + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL); + g_return_val_if_fail (clutter_input_device_get_device_mode (device) != CLUTTER_INPUT_MODE_MASTER, NULL); + + return device->product_id; +} + +void +clutter_input_device_add_tool (ClutterInputDevice *device, + ClutterInputDeviceTool *tool) +{ + g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); + g_return_if_fail (clutter_input_device_get_device_mode (device) != CLUTTER_INPUT_MODE_MASTER); + g_return_if_fail (CLUTTER_IS_INPUT_DEVICE_TOOL (tool)); + + if (!device->tools) + device->tools = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); + + g_ptr_array_add (device->tools, tool); +} + +ClutterInputDeviceTool * +clutter_input_device_lookup_tool (ClutterInputDevice *device, + guint64 serial, + ClutterInputDeviceToolType type) +{ + ClutterInputDeviceTool *tool; + guint i; + + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL); + g_return_val_if_fail (clutter_input_device_get_device_mode (device) != CLUTTER_INPUT_MODE_MASTER, NULL); + + if (!device->tools) + return NULL; + + for (i = 0; i < device->tools->len; i++) + { + tool = g_ptr_array_index (device->tools, i); + + if (serial == clutter_input_device_tool_get_serial (tool) && + type == clutter_input_device_tool_get_tool_type (tool)) + return tool; + } + + return NULL; +} + +void +clutter_input_device_update_from_tool (ClutterInputDevice *device, + ClutterInputDeviceTool *tool) +{ + ClutterInputDeviceClass *device_class; + + g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); + + device_class = CLUTTER_INPUT_DEVICE_GET_CLASS (device); + + if (device_class->update_from_tool) + device_class->update_from_tool (device, tool); +} + +gint +clutter_input_device_get_n_rings (ClutterInputDevice *device) +{ + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), 0); + + return device->n_rings; +} + +gint +clutter_input_device_get_n_strips (ClutterInputDevice *device) +{ + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), 0); + + return device->n_strips; +} + +gint +clutter_input_device_get_n_mode_groups (ClutterInputDevice *device) +{ + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), 0); + g_return_val_if_fail (clutter_input_device_get_device_type (device) == + CLUTTER_PAD_DEVICE, 0); + + return device->n_mode_groups; +} + +const gchar * +clutter_input_device_get_device_node (ClutterInputDevice *device) +{ + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL); + + return device->node_path; +} + +ClutterInputDeviceMapping +clutter_input_device_get_mapping_mode (ClutterInputDevice *device) +{ + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), + CLUTTER_INPUT_DEVICE_MAPPING_ABSOLUTE); + g_return_val_if_fail (clutter_input_device_get_device_type (device) == + CLUTTER_TABLET_DEVICE, + CLUTTER_INPUT_DEVICE_MAPPING_ABSOLUTE); + + return device->mapping_mode; +} + +void +clutter_input_device_set_mapping_mode (ClutterInputDevice *device, + ClutterInputDeviceMapping mapping) +{ + g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); + g_return_if_fail (clutter_input_device_get_device_type (device) == + CLUTTER_TABLET_DEVICE); + + if (device->mapping_mode == mapping) + return; + + device->mapping_mode = mapping; + g_object_notify (G_OBJECT (device), "mapping-mode"); +} diff --git a/clutter/clutter/clutter-input-device.h b/clutter/clutter/clutter-input-device.h new file mode 100644 index 0000000..66b2a58 --- /dev/null +++ b/clutter/clutter/clutter-input-device.h @@ -0,0 +1,162 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright © 2009, 2010, 2011 Intel Corp. + * + * 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 . + * + * Author: Emmanuele Bassi + */ + +#ifndef __CLUTTER_INPUT_DEVICE_H__ +#define __CLUTTER_INPUT_DEVICE_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_INPUT_DEVICE (clutter_input_device_get_type ()) +#define CLUTTER_INPUT_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_INPUT_DEVICE, ClutterInputDevice)) +#define CLUTTER_IS_INPUT_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_INPUT_DEVICE)) +#define CLUTTER_INPUT_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_INPUT_DEVICE, ClutterInputDeviceClass)) +#define CLUTTER_IS_INPUT_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_INPUT_DEVICE)) +#define CLUTTER_INPUT_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_INPUT_DEVICE, ClutterInputDeviceClass)) + +/** + * ClutterInputDevice: + * + * Generic representation of an input device. The actual contents of this + * structure depend on the backend used. + */ +typedef struct _ClutterInputDeviceClass ClutterInputDeviceClass; + +CLUTTER_AVAILABLE_IN_1_0 +GType clutter_input_device_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_0 +ClutterInputDeviceType clutter_input_device_get_device_type (ClutterInputDevice *device); +CLUTTER_AVAILABLE_IN_1_0 +gint clutter_input_device_get_device_id (ClutterInputDevice *device); + +CLUTTER_AVAILABLE_IN_1_12 +gboolean clutter_input_device_get_coords (ClutterInputDevice *device, + ClutterEventSequence *sequence, + ClutterPoint *point); +CLUTTER_AVAILABLE_IN_1_16 +ClutterModifierType clutter_input_device_get_modifier_state (ClutterInputDevice *device); +CLUTTER_AVAILABLE_IN_1_2 +ClutterActor * clutter_input_device_get_pointer_actor (ClutterInputDevice *device); +CLUTTER_AVAILABLE_IN_1_2 +ClutterStage * clutter_input_device_get_pointer_stage (ClutterInputDevice *device); +CLUTTER_AVAILABLE_IN_1_2 +const gchar * clutter_input_device_get_device_name (ClutterInputDevice *device); +CLUTTER_AVAILABLE_IN_1_2 +ClutterInputMode clutter_input_device_get_device_mode (ClutterInputDevice *device); +CLUTTER_AVAILABLE_IN_1_2 +gboolean clutter_input_device_get_has_cursor (ClutterInputDevice *device); +CLUTTER_AVAILABLE_IN_1_2 +void clutter_input_device_set_enabled (ClutterInputDevice *device, + gboolean enabled); +CLUTTER_AVAILABLE_IN_1_2 +gboolean clutter_input_device_get_enabled (ClutterInputDevice *device); + +CLUTTER_AVAILABLE_IN_1_2 +guint clutter_input_device_get_n_axes (ClutterInputDevice *device); +CLUTTER_AVAILABLE_IN_1_2 +ClutterInputAxis clutter_input_device_get_axis (ClutterInputDevice *device, + guint index_); +CLUTTER_AVAILABLE_IN_1_2 +gboolean clutter_input_device_get_axis_value (ClutterInputDevice *device, + gdouble *axes, + ClutterInputAxis axis, + gdouble *value); + +CLUTTER_AVAILABLE_IN_1_2 +guint clutter_input_device_get_n_keys (ClutterInputDevice *device); +CLUTTER_AVAILABLE_IN_1_2 +void clutter_input_device_set_key (ClutterInputDevice *device, + guint index_, + guint keyval, + ClutterModifierType modifiers); +CLUTTER_AVAILABLE_IN_1_2 +gboolean clutter_input_device_get_key (ClutterInputDevice *device, + guint index_, + guint *keyval, + ClutterModifierType *modifiers); + +CLUTTER_AVAILABLE_IN_1_2 +ClutterInputDevice * clutter_input_device_get_associated_device (ClutterInputDevice *device); +CLUTTER_AVAILABLE_IN_1_2 +GList * clutter_input_device_get_slave_devices (ClutterInputDevice *device); + +CLUTTER_AVAILABLE_IN_1_2 +void clutter_input_device_update_from_event (ClutterInputDevice *device, + ClutterEvent *event, + gboolean update_stage); + +CLUTTER_AVAILABLE_IN_1_10 +void clutter_input_device_grab (ClutterInputDevice *device, + ClutterActor *actor); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_input_device_ungrab (ClutterInputDevice *device); +CLUTTER_AVAILABLE_IN_1_10 +ClutterActor * clutter_input_device_get_grabbed_actor (ClutterInputDevice *device); + +CLUTTER_AVAILABLE_IN_1_12 +void clutter_input_device_sequence_grab (ClutterInputDevice *device, + ClutterEventSequence *sequence, + ClutterActor *actor); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_input_device_sequence_ungrab (ClutterInputDevice *device, + ClutterEventSequence *sequence); +CLUTTER_AVAILABLE_IN_1_12 +ClutterActor * clutter_input_device_sequence_get_grabbed_actor (ClutterInputDevice *device, + ClutterEventSequence *sequence); + +CLUTTER_AVAILABLE_IN_1_10 +gboolean clutter_input_device_keycode_to_evdev (ClutterInputDevice *device, + guint hardware_keycode, + guint *evdev_keycode); + +CLUTTER_AVAILABLE_IN_1_22 +const gchar * clutter_input_device_get_vendor_id (ClutterInputDevice *device); +CLUTTER_AVAILABLE_IN_1_22 +const gchar * clutter_input_device_get_product_id (ClutterInputDevice *device); + +CLUTTER_AVAILABLE_IN_ALL +gint clutter_input_device_get_n_rings (ClutterInputDevice *device); +CLUTTER_AVAILABLE_IN_ALL +gint clutter_input_device_get_n_strips (ClutterInputDevice *device); +CLUTTER_AVAILABLE_IN_ALL +gint clutter_input_device_get_n_mode_groups (ClutterInputDevice *device); + +CLUTTER_AVAILABLE_IN_ALL +const gchar * clutter_input_device_get_device_node (ClutterInputDevice *device); + +CLUTTER_AVAILABLE_IN_ALL +ClutterInputDeviceMapping clutter_input_device_get_mapping_mode (ClutterInputDevice *device); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_input_device_set_mapping_mode (ClutterInputDevice *device, + ClutterInputDeviceMapping mapping); + +G_END_DECLS + +#endif /* __CLUTTER_INPUT_DEVICE_H__ */ diff --git a/clutter/clutter/clutter-interval.c b/clutter/clutter/clutter-interval.c new file mode 100644 index 0000000..6f14287 --- /dev/null +++ b/clutter/clutter/clutter-interval.c @@ -0,0 +1,1232 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2008 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 . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-interval + * @short_description: An object holding an interval of two values + * + * #ClutterInterval is a simple object that can hold two values + * defining an interval. #ClutterInterval can hold any value that + * can be enclosed inside a #GValue. + * + * Once a #ClutterInterval for a specific #GType has been instantiated + * the #ClutterInterval:value-type property cannot be changed anymore. + * + * #ClutterInterval starts with a floating reference; this means that + * any object taking a reference on a #ClutterInterval instance should + * also take ownership of the interval by using g_object_ref_sink(). + * + * #ClutterInterval is used by #ClutterAnimation to define the + * interval of values that an implicit animation should tween over. + * + * #ClutterInterval can be subclassed to override the validation + * and value computation. + * + * #ClutterInterval is available since Clutter 1.0 + */ + +#include "clutter-build-config.h" + +#include +#include + +#include +#include +#include + +#include "clutter-color.h" +#include "clutter-interval.h" +#include "clutter-private.h" +#include "clutter-units.h" +#include "clutter-scriptable.h" +#include "clutter-script-private.h" + +enum +{ + PROP_0, + + PROP_VALUE_TYPE, + PROP_INITIAL, + PROP_FINAL, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +enum +{ + INITIAL = 0, + FINAL, + RESULT, + + N_VALUES +}; + +struct _ClutterIntervalPrivate +{ + GType value_type; + + GValue *values; +}; + +static void clutter_scriptable_iface_init (ClutterScriptableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (ClutterInterval, + clutter_interval, + G_TYPE_INITIALLY_UNOWNED, + G_ADD_PRIVATE (ClutterInterval) + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_SCRIPTABLE, + clutter_scriptable_iface_init)); + + +static gboolean +clutter_interval_real_validate (ClutterInterval *interval, + GParamSpec *pspec) +{ + GType pspec_gtype = G_PARAM_SPEC_VALUE_TYPE (pspec); + + /* then check the fundamental types */ + switch (G_TYPE_FUNDAMENTAL (pspec_gtype)) + { + case G_TYPE_INT: + { + GParamSpecInt *pspec_int = G_PARAM_SPEC_INT (pspec); + gint a, b; + + a = b = 0; + clutter_interval_get_interval (interval, &a, &b); + if ((a >= pspec_int->minimum && a <= pspec_int->maximum) && + (b >= pspec_int->minimum && b <= pspec_int->maximum)) + return TRUE; + else + return FALSE; + } + break; + + case G_TYPE_INT64: + { + GParamSpecInt64 *pspec_int = G_PARAM_SPEC_INT64 (pspec); + gint64 a, b; + + a = b = 0; + clutter_interval_get_interval (interval, &a, &b); + if ((a >= pspec_int->minimum && a <= pspec_int->maximum) && + (b >= pspec_int->minimum && b <= pspec_int->maximum)) + return TRUE; + else + return FALSE; + } + break; + + case G_TYPE_UINT: + { + GParamSpecUInt *pspec_uint = G_PARAM_SPEC_UINT (pspec); + guint a, b; + + a = b = 0; + clutter_interval_get_interval (interval, &a, &b); + if ((a >= pspec_uint->minimum && a <= pspec_uint->maximum) && + (b >= pspec_uint->minimum && b <= pspec_uint->maximum)) + return TRUE; + else + return FALSE; + } + break; + + case G_TYPE_UINT64: + { + GParamSpecUInt64 *pspec_int = G_PARAM_SPEC_UINT64 (pspec); + guint64 a, b; + + a = b = 0; + clutter_interval_get_interval (interval, &a, &b); + if ((a >= pspec_int->minimum && a <= pspec_int->maximum) && + (b >= pspec_int->minimum && b <= pspec_int->maximum)) + return TRUE; + else + return FALSE; + } + break; + + case G_TYPE_CHAR: + { + GParamSpecChar *pspec_char = G_PARAM_SPEC_CHAR (pspec); + guchar a, b; + + a = b = 0; + clutter_interval_get_interval (interval, &a, &b); + if ((a >= pspec_char->minimum && a <= pspec_char->maximum) && + (b >= pspec_char->minimum && b <= pspec_char->maximum)) + return TRUE; + else + return FALSE; + } + break; + + case G_TYPE_UCHAR: + { + GParamSpecUChar *pspec_uchar = G_PARAM_SPEC_UCHAR (pspec); + guchar a, b; + + a = b = 0; + clutter_interval_get_interval (interval, &a, &b); + if ((a >= pspec_uchar->minimum && a <= pspec_uchar->maximum) && + (b >= pspec_uchar->minimum && b <= pspec_uchar->maximum)) + return TRUE; + else + return FALSE; + } + break; + + case G_TYPE_FLOAT: + { + GParamSpecFloat *pspec_flt = G_PARAM_SPEC_FLOAT (pspec); + float a, b; + + a = b = 0.f; + clutter_interval_get_interval (interval, &a, &b); + if ((a >= pspec_flt->minimum && a <= pspec_flt->maximum) && + (b >= pspec_flt->minimum && b <= pspec_flt->maximum)) + return TRUE; + else + return FALSE; + } + break; + + case G_TYPE_DOUBLE: + { + GParamSpecDouble *pspec_flt = G_PARAM_SPEC_DOUBLE (pspec); + double a, b; + + a = b = 0; + clutter_interval_get_interval (interval, &a, &b); + if ((a >= pspec_flt->minimum && a <= pspec_flt->maximum) && + (b >= pspec_flt->minimum && b <= pspec_flt->maximum)) + return TRUE; + else + return FALSE; + } + break; + + case G_TYPE_BOOLEAN: + return TRUE; + + default: + break; + } + + return TRUE; +} + +static gboolean +clutter_interval_real_compute_value (ClutterInterval *interval, + gdouble factor, + GValue *value) +{ + GValue *initial, *final; + GType value_type; + gboolean retval = FALSE; + + initial = clutter_interval_peek_initial_value (interval); + final = clutter_interval_peek_final_value (interval); + + value_type = clutter_interval_get_value_type (interval); + + if (_clutter_has_progress_function (value_type)) + { + retval = _clutter_run_progress_function (value_type, + initial, + final, + factor, + value); + if (retval) + return TRUE; + } + + switch (G_TYPE_FUNDAMENTAL (value_type)) + { + case G_TYPE_INT: + { + gint ia, ib, res; + + ia = g_value_get_int (initial); + ib = g_value_get_int (final); + + res = (factor * (ib - ia)) + ia; + + g_value_set_int (value, res); + + retval = TRUE; + } + break; + + case G_TYPE_CHAR: + { + gchar ia, ib, res; + + ia = g_value_get_schar (initial); + ib = g_value_get_schar (final); + + res = (factor * (ib - (gdouble) ia)) + ia; + + g_value_set_schar (value, res); + + retval = TRUE; + } + break; + + case G_TYPE_UINT: + { + guint ia, ib, res; + + ia = g_value_get_uint (initial); + ib = g_value_get_uint (final); + + res = (factor * (ib - (gdouble) ia)) + ia; + + g_value_set_uint (value, res); + + retval = TRUE; + } + break; + + case G_TYPE_UCHAR: + { + guchar ia, ib, res; + + ia = g_value_get_uchar (initial); + ib = g_value_get_uchar (final); + + res = (factor * (ib - (gdouble) ia)) + ia; + + g_value_set_uchar (value, res); + + retval = TRUE; + } + break; + + case G_TYPE_FLOAT: + case G_TYPE_DOUBLE: + { + gdouble ia, ib, res; + + 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; + + if (value_type == G_TYPE_DOUBLE) + g_value_set_double (value, res); + else + g_value_set_float (value, res); + + retval = TRUE; + } + break; + + case G_TYPE_BOOLEAN: + if (factor > 0.5) + g_value_set_boolean (value, TRUE); + else + g_value_set_boolean (value, FALSE); + + retval = TRUE; + break; + + case G_TYPE_BOXED: + break; + + default: + break; + } + + /* We're trying to animate a property without knowing how to do that. Issue + * a warning with a hint to what could be done to fix that */ + if (G_UNLIKELY (retval == FALSE)) + { + g_warning ("%s: Could not compute progress between two %s. You can " + "register a progress function to instruct ClutterInterval " + "how to deal with this GType", + G_STRLOC, + g_type_name (value_type)); + } + + return retval; +} + +static void +clutter_interval_finalize (GObject *gobject) +{ + ClutterIntervalPrivate *priv = CLUTTER_INTERVAL (gobject)->priv; + + if (G_IS_VALUE (&priv->values[INITIAL])) + g_value_unset (&priv->values[INITIAL]); + + if (G_IS_VALUE (&priv->values[FINAL])) + g_value_unset (&priv->values[FINAL]); + + if (G_IS_VALUE (&priv->values[RESULT])) + g_value_unset (&priv->values[RESULT]); + + g_free (priv->values); + + G_OBJECT_CLASS (clutter_interval_parent_class)->finalize (gobject); +} + +static void +clutter_interval_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterInterval *self = CLUTTER_INTERVAL (gobject); + ClutterIntervalPrivate *priv = clutter_interval_get_instance_private (self); + + switch (prop_id) + { + case PROP_VALUE_TYPE: + priv->value_type = g_value_get_gtype (value); + break; + + case PROP_INITIAL: + if (g_value_get_boxed (value) != NULL) + clutter_interval_set_initial_value (self, g_value_get_boxed (value)); + else if (G_IS_VALUE (&priv->values[INITIAL])) + g_value_unset (&priv->values[INITIAL]); + break; + + case PROP_FINAL: + if (g_value_get_boxed (value) != NULL) + clutter_interval_set_final_value (self, g_value_get_boxed (value)); + else if (G_IS_VALUE (&priv->values[FINAL])) + g_value_unset (&priv->values[FINAL]); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_interval_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterIntervalPrivate *priv; + + priv = clutter_interval_get_instance_private (CLUTTER_INTERVAL (gobject)); + + switch (prop_id) + { + case PROP_VALUE_TYPE: + g_value_set_gtype (value, priv->value_type); + break; + + case PROP_INITIAL: + if (G_IS_VALUE (&priv->values[INITIAL])) + g_value_set_boxed (value, &priv->values[INITIAL]); + break; + + case PROP_FINAL: + if (G_IS_VALUE (&priv->values[FINAL])) + g_value_set_boxed (value, &priv->values[FINAL]); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static gboolean +clutter_interval_parse_custom_node (ClutterScriptable *scriptable, + ClutterScript *script, + GValue *value, + const gchar *name, + JsonNode *node) +{ + ClutterIntervalPrivate *priv = CLUTTER_INTERVAL (scriptable)->priv; + + if ((strcmp (name, "initial") == 0) || (strcmp (name, "final") == 0)) + { + g_value_init (value, priv->value_type); + return _clutter_script_parse_node (script, value, name, node, NULL); + } + + return FALSE; +} + +static void +clutter_interval_set_custom_property (ClutterScriptable *scriptable, + ClutterScript *script, + const gchar *name, + const GValue *value) +{ + ClutterInterval *self = CLUTTER_INTERVAL (scriptable); + + if (strcmp (name, "initial") == 0) + clutter_interval_set_initial_value (self, value); + else if (strcmp (name, "final") == 0) + clutter_interval_set_final_value (self, value); + else + g_object_set_property (G_OBJECT (scriptable), name, value); +} + +static void +clutter_scriptable_iface_init (ClutterScriptableIface *iface) +{ + iface->parse_custom_node = clutter_interval_parse_custom_node; + iface->set_custom_property = clutter_interval_set_custom_property; +} + +static void +clutter_interval_class_init (ClutterIntervalClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + klass->validate = clutter_interval_real_validate; + klass->compute_value = clutter_interval_real_compute_value; + + gobject_class->set_property = clutter_interval_set_property, + gobject_class->get_property = clutter_interval_get_property; + gobject_class->finalize = clutter_interval_finalize; + + /** + * ClutterInterval:value-type: + * + * The type of the values in the interval. + * + * Since: 1.0 + */ + obj_props[PROP_VALUE_TYPE] = + g_param_spec_gtype ("value-type", + P_("Value Type"), + P_("The type of the values in the interval"), + G_TYPE_NONE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + /** + * ClutterInterval:initial: + * + * The initial value of the interval. + * + * Since: 1.12 + */ + obj_props[PROP_INITIAL] = + g_param_spec_boxed ("initial", + P_("Initial Value"), + P_("Initial value of the interval"), + G_TYPE_VALUE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + /** + * ClutterInterval:final: + * + * The final value of the interval. + * + * Since: 1.12 + */ + obj_props[PROP_FINAL] = + g_param_spec_boxed ("final", + P_("Final Value"), + P_("Final value of the interval"), + G_TYPE_VALUE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); +} + +static void +clutter_interval_init (ClutterInterval *self) +{ + self->priv = clutter_interval_get_instance_private (self); + + self->priv->value_type = G_TYPE_INVALID; + self->priv->values = g_malloc0 (sizeof (GValue) * N_VALUES); +} + +static inline void +clutter_interval_set_value_internal (ClutterInterval *interval, + gint index_, + const GValue *value) +{ + ClutterIntervalPrivate *priv = interval->priv; + GType value_type; + + g_assert (index_ >= INITIAL && index_ <= RESULT); + + if (G_IS_VALUE (&priv->values[index_])) + g_value_unset (&priv->values[index_]); + + g_value_init (&priv->values[index_], priv->value_type); + + value_type = G_VALUE_TYPE (value); + if (value_type != priv->value_type || + !g_type_is_a (value_type, priv->value_type)) + { + if (g_value_type_compatible (value_type, priv->value_type)) + { + g_value_copy (value, &priv->values[index_]); + return; + } + + if (g_value_type_transformable (value_type, priv->value_type)) + { + GValue transform = G_VALUE_INIT; + + g_value_init (&transform, priv->value_type); + + if (g_value_transform (value, &transform)) + g_value_copy (&transform, &priv->values[index_]); + else + { + g_warning ("%s: Unable to convert a value of type '%s' into " + "the value type '%s' of the interval.", + G_STRLOC, + g_type_name (value_type), + g_type_name (priv->value_type)); + } + + g_value_unset (&transform); + } + } + else + g_value_copy (value, &priv->values[index_]); +} + +static inline void +clutter_interval_get_value_internal (ClutterInterval *interval, + gint index_, + GValue *value) +{ + ClutterIntervalPrivate *priv = interval->priv; + + g_assert (index_ >= INITIAL && index_ <= RESULT); + + g_value_copy (&priv->values[index_], value); +} + +static gboolean +clutter_interval_set_initial_internal (ClutterInterval *interval, + va_list *args) +{ + GType gtype = interval->priv->value_type; + GValue value = G_VALUE_INIT; + gchar *error; + + /* initial value */ + G_VALUE_COLLECT_INIT (&value, gtype, *args, 0, &error); + + if (error) + { + g_warning ("%s: %s", G_STRLOC, error); + + /* we leak the value here as it might not be in a valid state + * given the error and calling g_value_unset() might lead to + * undefined behaviour + */ + g_free (error); + return FALSE; + } + + clutter_interval_set_value_internal (interval, INITIAL, &value); + g_value_unset (&value); + + return TRUE; +} + +static gboolean +clutter_interval_set_final_internal (ClutterInterval *interval, + va_list *args) +{ + GType gtype = interval->priv->value_type; + GValue value = G_VALUE_INIT; + gchar *error; + + /* initial value */ + G_VALUE_COLLECT_INIT (&value, gtype, *args, 0, &error); + + if (error) + { + g_warning ("%s: %s", G_STRLOC, error); + + /* we leak the value here as it might not be in a valid state + * given the error and calling g_value_unset() might lead to + * undefined behaviour + */ + g_free (error); + return FALSE; + } + + clutter_interval_set_value_internal (interval, FINAL, &value); + g_value_unset (&value); + + return TRUE; +} + +static void +clutter_interval_get_interval_valist (ClutterInterval *interval, + va_list var_args) +{ + GType gtype = interval->priv->value_type; + GValue value = G_VALUE_INIT; + gchar *error; + + /* initial value */ + g_value_init (&value, gtype); + clutter_interval_get_initial_value (interval, &value); + G_VALUE_LCOPY (&value, var_args, 0, &error); + if (error) + { + g_warning ("%s: %s", G_STRLOC, error); + g_free (error); + g_value_unset (&value); + return; + } + + g_value_unset (&value); + + /* final value */ + g_value_init (&value, gtype); + clutter_interval_get_final_value (interval, &value); + G_VALUE_LCOPY (&value, var_args, 0, &error); + if (error) + { + g_warning ("%s: %s", G_STRLOC, error); + g_free (error); + g_value_unset (&value); + return; + } + + g_value_unset (&value); +} + +/** + * clutter_interval_new: + * @gtype: the type of the values in the interval + * @...: the initial value and the final value of the interval + * + * Creates a new #ClutterInterval holding values of type @gtype. + * + * This function avoids using a #GValue for the initial and final values + * of the interval: + * + * |[ + * interval = clutter_interval_new (G_TYPE_FLOAT, 0.0, 1.0); + * interval = clutter_interval_new (G_TYPE_BOOLEAN, FALSE, TRUE); + * interval = clutter_interval_new (G_TYPE_INT, 0, 360); + * ]| + * + * Return value: the newly created #ClutterInterval + * + * Since: 1.0 + */ +ClutterInterval * +clutter_interval_new (GType gtype, + ...) +{ + ClutterInterval *retval; + va_list args; + + g_return_val_if_fail (gtype != G_TYPE_INVALID, NULL); + + retval = g_object_new (CLUTTER_TYPE_INTERVAL, "value-type", gtype, NULL); + + va_start (args, gtype); + + if (!clutter_interval_set_initial_internal (retval, &args)) + goto out; + + clutter_interval_set_final_internal (retval, &args); + +out: + va_end (args); + + return retval; +} + +/** + * clutter_interval_new_with_values: + * @gtype: the type of the values in the interval + * @initial: (allow-none): a #GValue holding the initial value of the interval + * @final: (allow-none): a #GValue holding the final value of the interval + * + * Creates a new #ClutterInterval of type @gtype, between @initial + * and @final. + * + * This function is useful for language bindings. + * + * Return value: the newly created #ClutterInterval + * + * Since: 1.0 + */ +ClutterInterval * +clutter_interval_new_with_values (GType gtype, + const GValue *initial, + const GValue *final) +{ + g_return_val_if_fail (gtype != G_TYPE_INVALID, NULL); + g_return_val_if_fail (initial == NULL || G_VALUE_TYPE (initial) == gtype, NULL); + g_return_val_if_fail (final == NULL || G_VALUE_TYPE (final) == gtype, NULL); + + return g_object_new (CLUTTER_TYPE_INTERVAL, + "value-type", gtype, + "initial", initial, + "final", final, + NULL); +} + +/** + * clutter_interval_clone: + * @interval: a #ClutterInterval + * + * Creates a copy of @interval. + * + * Return value: (transfer full): the newly created #ClutterInterval + * + * Since: 1.0 + */ +ClutterInterval * +clutter_interval_clone (ClutterInterval *interval) +{ + ClutterInterval *retval; + GType gtype; + GValue *tmp; + + g_return_val_if_fail (CLUTTER_IS_INTERVAL (interval), NULL); + g_return_val_if_fail (interval->priv->value_type != G_TYPE_INVALID, NULL); + + gtype = interval->priv->value_type; + retval = g_object_new (CLUTTER_TYPE_INTERVAL, "value-type", gtype, NULL); + + tmp = clutter_interval_peek_initial_value (interval); + clutter_interval_set_initial_value (retval, tmp); + + tmp = clutter_interval_peek_final_value (interval); + clutter_interval_set_final_value (retval, tmp); + + return retval; +} + +/** + * clutter_interval_get_value_type: + * @interval: a #ClutterInterval + * + * Retrieves the #GType of the values inside @interval. + * + * Return value: the type of the value, or G_TYPE_INVALID + * + * Since: 1.0 + */ +GType +clutter_interval_get_value_type (ClutterInterval *interval) +{ + g_return_val_if_fail (CLUTTER_IS_INTERVAL (interval), G_TYPE_INVALID); + + return interval->priv->value_type; +} + +/** + * clutter_interval_set_initial_value: (rename-to clutter_interval_set_initial) + * @interval: a #ClutterInterval + * @value: a #GValue + * + * Sets the initial value of @interval to @value. The value is copied + * inside the #ClutterInterval. + * + * Since: 1.0 + */ +void +clutter_interval_set_initial_value (ClutterInterval *interval, + const GValue *value) +{ + g_return_if_fail (CLUTTER_IS_INTERVAL (interval)); + g_return_if_fail (value != NULL); + + clutter_interval_set_value_internal (interval, INITIAL, value); +} + +/** + * clutter_interval_set_initial: (skip) + * @interval: a #ClutterInterval + * @...: the initial value of the interval. + * + * Variadic arguments version of clutter_interval_set_initial_value(). + * + * This function is meant as a convenience for the C API. + * + * Language bindings should use clutter_interval_set_initial_value() + * instead. + * + * Since: 1.10 + */ +void +clutter_interval_set_initial (ClutterInterval *interval, + ...) +{ + va_list args; + + g_return_if_fail (CLUTTER_IS_INTERVAL (interval)); + + va_start (args, interval); + clutter_interval_set_initial_internal (interval, &args); + va_end (args); +} + +/** + * clutter_interval_get_initial_value: + * @interval: a #ClutterInterval + * @value: (out caller-allocates): a #GValue + * + * Retrieves the initial value of @interval and copies + * it into @value. + * + * The passed #GValue must be initialized to the value held by + * the #ClutterInterval. + * + * Since: 1.0 + */ +void +clutter_interval_get_initial_value (ClutterInterval *interval, + GValue *value) +{ + g_return_if_fail (CLUTTER_IS_INTERVAL (interval)); + g_return_if_fail (value != NULL); + + clutter_interval_get_value_internal (interval, INITIAL, value); +} + +/** + * clutter_interval_peek_initial_value: + * @interval: a #ClutterInterval + * + * Gets the pointer to the initial value of @interval + * + * Return value: (transfer none): the initial value of the interval. + * The value is owned by the #ClutterInterval and it should not be + * modified or freed + * + * Since: 1.0 + */ +GValue * +clutter_interval_peek_initial_value (ClutterInterval *interval) +{ + g_return_val_if_fail (CLUTTER_IS_INTERVAL (interval), NULL); + + return interval->priv->values + INITIAL; +} + +/** + * clutter_interval_set_final_value: (rename-to clutter_interval_set_final) + * @interval: a #ClutterInterval + * @value: a #GValue + * + * Sets the final value of @interval to @value. The value is + * copied inside the #ClutterInterval. + * + * Since: 1.0 + */ +void +clutter_interval_set_final_value (ClutterInterval *interval, + const GValue *value) +{ + g_return_if_fail (CLUTTER_IS_INTERVAL (interval)); + g_return_if_fail (value != NULL); + + clutter_interval_set_value_internal (interval, FINAL, value); +} + +/** + * clutter_interval_get_final_value: + * @interval: a #ClutterInterval + * @value: (out caller-allocates): a #GValue + * + * Retrieves the final value of @interval and copies + * it into @value. + * + * The passed #GValue must be initialized to the value held by + * the #ClutterInterval. + * + * Since: 1.0 + */ +void +clutter_interval_get_final_value (ClutterInterval *interval, + GValue *value) +{ + g_return_if_fail (CLUTTER_IS_INTERVAL (interval)); + g_return_if_fail (value != NULL); + + clutter_interval_get_value_internal (interval, FINAL, value); +} + +/** + * clutter_interval_set_final: (skip) + * @interval: a #ClutterInterval + * @...: the final value of the interval + * + * Variadic arguments version of clutter_interval_set_final_value(). + * + * This function is meant as a convenience for the C API. + * + * Language bindings should use clutter_interval_set_final_value() instead. + * + * Since: 1.10 + */ +void +clutter_interval_set_final (ClutterInterval *interval, + ...) +{ + va_list args; + + g_return_if_fail (CLUTTER_IS_INTERVAL (interval)); + + va_start (args, interval); + clutter_interval_set_final_internal (interval, &args); + va_end (args); +} + +/** + * clutter_interval_peek_final_value: + * @interval: a #ClutterInterval + * + * Gets the pointer to the final value of @interval + * + * Return value: (transfer none): the final value of the interval. + * The value is owned by the #ClutterInterval and it should not be + * modified or freed + * + * Since: 1.0 + */ +GValue * +clutter_interval_peek_final_value (ClutterInterval *interval) +{ + g_return_val_if_fail (CLUTTER_IS_INTERVAL (interval), NULL); + + return interval->priv->values + FINAL; +} + +/** + * clutter_interval_set_interval: + * @interval: a #ClutterInterval + * @...: the initial and final values of the interval + * + * Variable arguments wrapper for clutter_interval_set_initial_value() + * and clutter_interval_set_final_value() that avoids using the + * #GValue arguments: + * + * |[ + * clutter_interval_set_interval (interval, 0, 50); + * clutter_interval_set_interval (interval, 1.0, 0.0); + * clutter_interval_set_interval (interval, FALSE, TRUE); + * ]| + * + * This function is meant for the convenience of the C API; bindings + * should reimplement this function using the #GValue-based API. + * + * Since: 1.0 + */ +void +clutter_interval_set_interval (ClutterInterval *interval, + ...) +{ + va_list args; + + g_return_if_fail (CLUTTER_IS_INTERVAL (interval)); + g_return_if_fail (interval->priv->value_type != G_TYPE_INVALID); + + va_start (args, interval); + + if (!clutter_interval_set_initial_internal (interval, &args)) + goto out; + + clutter_interval_set_final_internal (interval, &args); + +out: + va_end (args); +} + +/** + * clutter_interval_get_interval: + * @interval: a #ClutterInterval + * @...: return locations for the initial and final values of + * the interval + * + * Variable arguments wrapper for clutter_interval_get_initial_value() + * and clutter_interval_get_final_value() that avoids using the + * #GValue arguments: + * + * |[ + * gint a = 0, b = 0; + * clutter_interval_get_interval (interval, &a, &b); + * ]| + * + * This function is meant for the convenience of the C API; bindings + * should reimplement this function using the #GValue-based API. + * + * Since: 1.0 + */ +void +clutter_interval_get_interval (ClutterInterval *interval, + ...) +{ + va_list args; + + g_return_if_fail (CLUTTER_IS_INTERVAL (interval)); + g_return_if_fail (interval->priv->value_type != G_TYPE_INVALID); + + va_start (args, interval); + clutter_interval_get_interval_valist (interval, args); + va_end (args); +} + +/** + * clutter_interval_validate: + * @interval: a #ClutterInterval + * @pspec: a #GParamSpec + * + * Validates the initial and final values of @interval against + * a #GParamSpec. + * + * Return value: %TRUE if the #ClutterInterval is valid, %FALSE otherwise + * + * Since: 1.0 + */ +gboolean +clutter_interval_validate (ClutterInterval *interval, + GParamSpec *pspec) +{ + g_return_val_if_fail (CLUTTER_IS_INTERVAL (interval), FALSE); + g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE); + + return CLUTTER_INTERVAL_GET_CLASS (interval)->validate (interval, pspec); +} + +/** + * clutter_interval_compute_value: + * @interval: a #ClutterInterval + * @factor: the progress factor, between 0 and 1 + * @value: (out caller-allocates): return location for an initialized #GValue + * + * Computes the value between the @interval boundaries given the + * progress @factor and copies it into @value. + * + * Return value: %TRUE if the operation was successful + * + * Since: 1.0 + */ +gboolean +clutter_interval_compute_value (ClutterInterval *interval, + gdouble factor, + GValue *value) +{ + g_return_val_if_fail (CLUTTER_IS_INTERVAL (interval), FALSE); + g_return_val_if_fail (value != NULL, FALSE); + + return CLUTTER_INTERVAL_GET_CLASS (interval)->compute_value (interval, + factor, + value); +} + +/** + * clutter_interval_compute: + * @interval: a #ClutterInterval + * @factor: the progress factor, between 0 and 1 + * + * Computes the value between the @interval boundaries given the + * progress @factor + * + * Unlike clutter_interval_compute_value(), this function will + * return a const pointer to the computed value + * + * You should use this function if you immediately pass the computed + * value to another function that makes a copy of it, like + * g_object_set_property() + * + * Return value: (transfer none): a pointer to the computed value, + * or %NULL if the computation was not successfull + * + * Since: 1.4 + */ +const GValue * +clutter_interval_compute (ClutterInterval *interval, + gdouble factor) +{ + GValue *value; + gboolean res; + + g_return_val_if_fail (CLUTTER_IS_INTERVAL (interval), NULL); + + value = &(interval->priv->values[RESULT]); + + if (G_VALUE_TYPE (value) == G_TYPE_INVALID) + g_value_init (value, interval->priv->value_type); + + res = CLUTTER_INTERVAL_GET_CLASS (interval)->compute_value (interval, + factor, + value); + + if (res) + return interval->priv->values + RESULT; + + return NULL; +} + +/** + * clutter_interval_is_valid: + * @interval: a #ClutterInterval + * + * Checks if the @interval has a valid initial and final values. + * + * Return value: %TRUE if the #ClutterInterval has an initial and + * final values, and %FALSE otherwise + * + * Since: 1.12 + */ +gboolean +clutter_interval_is_valid (ClutterInterval *interval) +{ + ClutterIntervalPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_INTERVAL (interval), FALSE); + + priv = interval->priv; + + return G_IS_VALUE (&priv->values[INITIAL]) && + G_IS_VALUE (&priv->values[FINAL]); +} diff --git a/clutter/clutter/clutter-interval.h b/clutter/clutter/clutter-interval.h new file mode 100644 index 0000000..f3d62cb --- /dev/null +++ b/clutter/clutter/clutter-interval.h @@ -0,0 +1,159 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2008 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 . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_INTERVAL_H__ +#define __CLUTTER_INTERVAL_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_INTERVAL (clutter_interval_get_type ()) +#define CLUTTER_INTERVAL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_INTERVAL, ClutterInterval)) +#define CLUTTER_IS_INTERVAL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_INTERVAL)) +#define CLUTTER_INTERVAL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_INTERVAL, ClutterIntervalClass)) +#define CLUTTER_IS_INTERVAL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_INTERVAL)) +#define CLUTTER_INTERVAL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_INTERVAL, ClutterIntervalClass)) + +typedef struct _ClutterIntervalPrivate ClutterIntervalPrivate; +typedef struct _ClutterIntervalClass ClutterIntervalClass; + +/** + * ClutterInterval: + * + * The #ClutterInterval structure contains only private data and should + * be accessed using the provided functions. + * + * Since: 1.0 + */ +struct _ClutterInterval +{ + /*< private >*/ + GInitiallyUnowned parent_instance; + + ClutterIntervalPrivate *priv; +}; + +/** + * ClutterIntervalClass: + * @validate: virtual function for validating an interval + * using a #GParamSpec + * @compute_value: virtual function for computing the value + * inside an interval using an adimensional factor between 0 and 1 + * + * The #ClutterIntervalClass contains only private data. + * + * Since: 1.0 + */ +struct _ClutterIntervalClass +{ + /*< private >*/ + GInitiallyUnownedClass parent_class; + + /*< public >*/ + gboolean (* validate) (ClutterInterval *interval, + GParamSpec *pspec); + gboolean (* compute_value) (ClutterInterval *interval, + gdouble factor, + GValue *value); + + /*< private >*/ + /* padding for future expansion */ + void (*_clutter_reserved1) (void); + void (*_clutter_reserved2) (void); + void (*_clutter_reserved3) (void); + void (*_clutter_reserved4) (void); + void (*_clutter_reserved5) (void); + void (*_clutter_reserved6) (void); +}; + +CLUTTER_AVAILABLE_IN_1_0 +GType clutter_interval_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_0 +ClutterInterval *clutter_interval_new (GType gtype, + ...); +CLUTTER_AVAILABLE_IN_1_0 +ClutterInterval *clutter_interval_new_with_values (GType gtype, + const GValue *initial, + const GValue *final); + +CLUTTER_AVAILABLE_IN_1_0 +ClutterInterval *clutter_interval_clone (ClutterInterval *interval); + +CLUTTER_AVAILABLE_IN_1_0 +GType clutter_interval_get_value_type (ClutterInterval *interval); + +CLUTTER_AVAILABLE_IN_1_10 +void clutter_interval_set_initial (ClutterInterval *interval, + ...); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_interval_set_initial_value (ClutterInterval *interval, + const GValue *value); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_interval_get_initial_value (ClutterInterval *interval, + GValue *value); +CLUTTER_AVAILABLE_IN_1_0 +GValue * clutter_interval_peek_initial_value (ClutterInterval *interval); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_interval_set_final (ClutterInterval *interval, + ...); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_interval_set_final_value (ClutterInterval *interval, + const GValue *value); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_interval_get_final_value (ClutterInterval *interval, + GValue *value); +CLUTTER_AVAILABLE_IN_1_0 +GValue * clutter_interval_peek_final_value (ClutterInterval *interval); + +CLUTTER_AVAILABLE_IN_1_0 +void clutter_interval_set_interval (ClutterInterval *interval, + ...); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_interval_get_interval (ClutterInterval *interval, + ...); + +CLUTTER_AVAILABLE_IN_1_0 +gboolean clutter_interval_validate (ClutterInterval *interval, + GParamSpec *pspec); +CLUTTER_AVAILABLE_IN_1_0 +gboolean clutter_interval_compute_value (ClutterInterval *interval, + gdouble factor, + GValue *value); + +CLUTTER_AVAILABLE_IN_1_4 +const GValue * clutter_interval_compute (ClutterInterval *interval, + gdouble factor); + +CLUTTER_AVAILABLE_IN_1_12 +gboolean clutter_interval_is_valid (ClutterInterval *interval); + +G_END_DECLS + +#endif /* __CLUTTER_INTERVAL_H__ */ diff --git a/clutter/clutter/clutter-keyframe-transition.c b/clutter/clutter/clutter-keyframe-transition.c new file mode 100644 index 0000000..0142414 --- /dev/null +++ b/clutter/clutter/clutter-keyframe-transition.c @@ -0,0 +1,731 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2012 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 . + * + * Author: Emmanuele Bassi + */ + +/** + * SECTION:clutter-keyframe-transition + * @Title: ClutterKeyframeTransition + * @Short_Description: Keyframe property transition + * + * #ClutterKeyframeTransition allows animating a property by defining + * "key frames": values at a normalized position on the transition + * duration. + * + * The #ClutterKeyframeTransition interpolates the value of the property + * to which it's bound across these key values. + * + * Setting up a #ClutterKeyframeTransition means providing the times, + * values, and easing modes between these key frames, for instance: + * + * |[ + * ClutterTransition *keyframe; + * + * keyframe = clutter_keyframe_transition_new ("opacity"); + * clutter_transition_set_from (keyframe, G_TYPE_UINT, 255); + * clutter_transition_set_to (keyframe, G_TYPE_UINT, 0); + * clutter_keyframe_transition_set (CLUTTER_KEYFRAME_TRANSITION (keyframe), + * G_TYPE_UINT, + * 1, /* number of key frames */ + * 0.5, 128, CLUTTER_EASE_IN_OUT_CUBIC); + * ]| + * + * The example above sets up a keyframe transition for the #ClutterActor:opacity + * property of a #ClutterActor; the transition starts and sets the value of the + * property to fully transparent; between the start of the transition and its mid + * point, it will animate the property to half opacity, using an easy in/easy out + * progress. Once the transition reaches the mid point, it will linearly fade the + * actor out until it reaches the end of the transition. + * + * The #ClutterKeyframeTransition will add an implicit key frame between the last + * and the 1.0 value, to interpolate to the final value of the transition's + * interval. + * + * #ClutterKeyframeTransition is available since Clutter 1.12. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-keyframe-transition.h" + +#include "clutter-debug.h" +#include "clutter-easing.h" +#include "clutter-interval.h" +#include "clutter-private.h" +#include "clutter-timeline.h" + +#include +#include + +typedef struct _KeyFrame +{ + double key; + + double start; + double end; + + ClutterAnimationMode mode; + + ClutterInterval *interval; +} KeyFrame; + +struct _ClutterKeyframeTransitionPrivate +{ + GArray *frames; + + gint current_frame; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterKeyframeTransition, + clutter_keyframe_transition, + CLUTTER_TYPE_PROPERTY_TRANSITION) + +static void +key_frame_free (gpointer data) +{ + if (data != NULL) + { + KeyFrame *key = data; + + g_object_unref (key->interval); + } +} + +static int +sort_by_key (gconstpointer a, + gconstpointer b) +{ + const KeyFrame *k_a = a; + const KeyFrame *k_b = b; + + if (fabs (k_a->key - k_b->key) < 0.0001) + return 0; + + if (k_a->key > k_a->key) + return 1; + + return -1; +} + +static inline void +clutter_keyframe_transition_sort_frames (ClutterKeyframeTransition *transition) +{ + if (transition->priv->frames != NULL) + g_array_sort (transition->priv->frames, sort_by_key); +} + +static inline void +clutter_keyframe_transition_init_frames (ClutterKeyframeTransition *transition, + gssize n_key_frames) +{ + ClutterKeyframeTransitionPrivate *priv = transition->priv; + guint i; + + priv->frames = g_array_sized_new (FALSE, FALSE, + sizeof (KeyFrame), + n_key_frames); + g_array_set_clear_func (priv->frames, key_frame_free); + + /* we add an implicit key frame that goes to 1.0, so that the + * user doesn't have to do that an can simply add key frames + * in between 0.0 and 1.0 + */ + for (i = 0; i < n_key_frames + 1; i++) + { + KeyFrame frame; + + if (i == n_key_frames) + frame.key = 1.0; + else + frame.key = 0.0; + + frame.mode = CLUTTER_LINEAR; + frame.interval = NULL; + + g_array_insert_val (priv->frames, i, frame); + } +} + +static inline void +clutter_keyframe_transition_update_frames (ClutterKeyframeTransition *transition) +{ + ClutterKeyframeTransitionPrivate *priv = transition->priv; + guint i; + + if (priv->frames == NULL) + return; + + for (i = 0; i < priv->frames->len; i++) + { + KeyFrame *cur_frame = &g_array_index (priv->frames, KeyFrame, i); + KeyFrame *prev_frame; + + if (i > 0) + prev_frame = &g_array_index (priv->frames, KeyFrame, i - 1); + else + prev_frame = NULL; + + if (prev_frame != NULL) + { + cur_frame->start = prev_frame->key; + + if (prev_frame->interval != NULL) + { + const GValue *value; + + value = clutter_interval_peek_final_value (prev_frame->interval); + + if (cur_frame->interval != NULL) + clutter_interval_set_initial_value (cur_frame->interval, value); + else + { + cur_frame->interval = + clutter_interval_new_with_values (G_VALUE_TYPE (value), value, NULL); + } + } + } + else + cur_frame->start = 0.0; + + cur_frame->end = cur_frame->key; + } +} + +static void +clutter_keyframe_transition_compute_value (ClutterTransition *transition, + ClutterAnimatable *animatable, + ClutterInterval *interval, + gdouble progress) +{ + ClutterKeyframeTransition *self = CLUTTER_KEYFRAME_TRANSITION (transition); + ClutterTimeline *timeline = CLUTTER_TIMELINE (transition); + ClutterKeyframeTransitionPrivate *priv = self->priv; + ClutterTransitionClass *parent_class; + ClutterTimelineDirection direction; + ClutterInterval *real_interval; + gdouble real_progress; + double t, d, p; + KeyFrame *cur_frame = NULL; + + real_interval = interval; + real_progress = progress; + + /* if we don't have any keyframe, we behave like our parent class */ + if (priv->frames == NULL) + goto out; + + direction = clutter_timeline_get_direction (timeline); + + /* we need a normalized linear value */ + t = clutter_timeline_get_elapsed_time (timeline); + d = clutter_timeline_get_duration (timeline); + p = t / d; + + if (priv->current_frame < 0) + { + if (direction == CLUTTER_TIMELINE_FORWARD) + priv->current_frame = 0; + else + priv->current_frame = priv->frames->len - 1; + } + + cur_frame = &g_array_index (priv->frames, KeyFrame, priv->current_frame); + + /* skip to the next key frame, depending on the direction of the timeline */ + if (direction == CLUTTER_TIMELINE_FORWARD) + { + if (p > cur_frame->end) + { + priv->current_frame = MIN (priv->current_frame + 1, + priv->frames->len - 1); + + cur_frame = &g_array_index (priv->frames, KeyFrame, priv->current_frame); + } + } + else + { + if (p < cur_frame->start) + { + priv->current_frame = MAX (priv->current_frame - 1, 0); + + cur_frame = &g_array_index (priv->frames, KeyFrame, priv->current_frame); + } + } + + /* if we are at the boundaries of the transition, use the from and to + * value from the transition + */ + if (priv->current_frame == 0) + { + const GValue *value; + + value = clutter_interval_peek_initial_value (interval); + clutter_interval_set_initial_value (cur_frame->interval, value); + } + else if (priv->current_frame == priv->frames->len - 1) + { + const GValue *value; + + cur_frame->mode = clutter_timeline_get_progress_mode (timeline); + + value = clutter_interval_peek_final_value (interval); + clutter_interval_set_final_value (cur_frame->interval, value); + } + + /* update the interval to be used to interpolate the property */ + real_interval = cur_frame->interval; + + /* normalize the progress and apply the easing mode */ + real_progress = clutter_easing_for_mode ( cur_frame->mode, (p - cur_frame->start), (cur_frame->end - cur_frame->start)); + +#ifdef CLUTTER_ENABLE_DEBUG + if (CLUTTER_HAS_DEBUG (ANIMATION)) + { + char *from, *to; + const GValue *value; + + value = clutter_interval_peek_initial_value (cur_frame->interval); + from = g_strdup_value_contents (value); + + value = clutter_interval_peek_final_value (cur_frame->interval); + to = g_strdup_value_contents (value); + + CLUTTER_NOTE (ANIMATION, + "cur_frame [%d] => { %g, %s, %s %s %s } - " + "progress: %g, sub-progress: %g\n", + priv->current_frame, + cur_frame->key, + clutter_get_easing_name_for_mode (cur_frame->mode), + from, + direction == CLUTTER_TIMELINE_FORWARD ? "->" : "<-", + to, + p, real_progress); + + g_free (from); + g_free (to); + } +#endif /* CLUTTER_ENABLE_DEBUG */ + +out: + parent_class = + CLUTTER_TRANSITION_CLASS (clutter_keyframe_transition_parent_class); + parent_class->compute_value (transition, animatable, real_interval, real_progress); +} + +static void +clutter_keyframe_transition_started (ClutterTimeline *timeline) +{ + ClutterKeyframeTransition *transition; + + transition = CLUTTER_KEYFRAME_TRANSITION (timeline); + + transition->priv->current_frame = -1; + + clutter_keyframe_transition_sort_frames (transition); + clutter_keyframe_transition_update_frames (transition); +} + +static void +clutter_keyframe_transition_completed (ClutterTimeline *timeline) +{ + ClutterKeyframeTransitionPrivate *priv; + + priv = CLUTTER_KEYFRAME_TRANSITION (timeline)->priv; + + priv->current_frame = -1; +} + +static void +clutter_keyframe_transition_finalize (GObject *gobject) +{ + ClutterKeyframeTransitionPrivate *priv; + + priv = CLUTTER_KEYFRAME_TRANSITION (gobject)->priv; + + if (priv->frames != NULL) + g_array_unref (priv->frames); + + G_OBJECT_CLASS (clutter_keyframe_transition_parent_class)->finalize (gobject); +} + +static void +clutter_keyframe_transition_class_init (ClutterKeyframeTransitionClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterTimelineClass *timeline_class = CLUTTER_TIMELINE_CLASS (klass); + ClutterTransitionClass *transition_class = CLUTTER_TRANSITION_CLASS (klass); + + gobject_class->finalize = clutter_keyframe_transition_finalize; + + timeline_class->started = clutter_keyframe_transition_started; + timeline_class->completed = clutter_keyframe_transition_completed; + + transition_class->compute_value = clutter_keyframe_transition_compute_value; +} + +static void +clutter_keyframe_transition_init (ClutterKeyframeTransition *self) +{ + self->priv = clutter_keyframe_transition_get_instance_private (self); +} + +/** + * clutter_keyframe_transition_new: + * @property_name: the property to animate + * + * Creates a new #ClutterKeyframeTransition for @property_name. + * + * Return value: (transfer full): the newly allocated + * #ClutterKeyframeTransition instance. Use g_object_unref() when + * done to free its resources. + * + * Since: 1.12 + */ +ClutterTransition * +clutter_keyframe_transition_new (const char *property_name) +{ + return g_object_new (CLUTTER_TYPE_KEYFRAME_TRANSITION, + "property-name", property_name, + NULL); +} + +/** + * clutter_keyframe_transition_set_key_frames: + * @transition: a #ClutterKeyframeTransition + * @n_key_frames: the number of values + * @key_frames: (array length=n_key_frames): an array of keys between 0.0 + * and 1.0, one for each key frame + * + * Sets the keys for each key frame inside @transition. + * + * If @transition does not hold any key frame, @n_key_frames key frames + * will be created; if @transition already has key frames, @key_frames must + * have at least as many elements as the number of key frames. + * + * Since: 1.12 + */ +void +clutter_keyframe_transition_set_key_frames (ClutterKeyframeTransition *transition, + guint n_key_frames, + const double *key_frames) +{ + ClutterKeyframeTransitionPrivate *priv; + guint i; + + g_return_if_fail (CLUTTER_IS_KEYFRAME_TRANSITION (transition)); + g_return_if_fail (n_key_frames > 0); + g_return_if_fail (key_frames != NULL); + + priv = transition->priv; + + if (priv->frames == NULL) + clutter_keyframe_transition_init_frames (transition, n_key_frames); + else + g_return_if_fail (n_key_frames == priv->frames->len - 1); + + for (i = 0; i < n_key_frames; i++) + { + KeyFrame *frame = &g_array_index (priv->frames, KeyFrame, i); + + frame->key = key_frames[i]; + } +} + +/** + * clutter_keyframe_transition_set_values: + * @transition: a #ClutterKeyframeTransition + * @n_values: the number of values + * @values: (array length=n_values): an array of values, one for each + * key frame + * + * Sets the values for each key frame inside @transition. + * + * If @transition does not hold any key frame, @n_values key frames will + * be created; if @transition already has key frames, @values must have + * at least as many elements as the number of key frames. + * + * Since: 1.12 + */ +void +clutter_keyframe_transition_set_values (ClutterKeyframeTransition *transition, + guint n_values, + const GValue *values) +{ + ClutterKeyframeTransitionPrivate *priv; + guint i; + + g_return_if_fail (CLUTTER_IS_KEYFRAME_TRANSITION (transition)); + g_return_if_fail (n_values > 0); + g_return_if_fail (values != NULL); + + priv = transition->priv; + + if (priv->frames == NULL) + clutter_keyframe_transition_init_frames (transition, n_values); + else + g_return_if_fail (n_values == priv->frames->len - 1); + + for (i = 0; i < n_values; i++) + { + KeyFrame *frame = &g_array_index (priv->frames, KeyFrame, i); + + if (frame->interval) + clutter_interval_set_final_value (frame->interval, &values[i]); + else + frame->interval = + clutter_interval_new_with_values (G_VALUE_TYPE (&values[i]), NULL, + &values[i]); + } +} + +/** + * clutter_keyframe_transition_set_modes: + * @transition: a #ClutterKeyframeTransition + * @n_modes: the number of easing modes + * @modes: (array length=n_modes): an array of easing modes, one for + * each key frame + * + * Sets the easing modes for each key frame inside @transition. + * + * If @transition does not hold any key frame, @n_modes key frames will + * be created; if @transition already has key frames, @modes must have + * at least as many elements as the number of key frames. + * + * Since: 1.12 + */ +void +clutter_keyframe_transition_set_modes (ClutterKeyframeTransition *transition, + guint n_modes, + const ClutterAnimationMode *modes) +{ + ClutterKeyframeTransitionPrivate *priv; + guint i; + + g_return_if_fail (CLUTTER_IS_KEYFRAME_TRANSITION (transition)); + g_return_if_fail (n_modes > 0); + g_return_if_fail (modes != NULL); + + priv = transition->priv; + + if (priv->frames == NULL) + clutter_keyframe_transition_init_frames (transition, n_modes); + else + g_return_if_fail (n_modes == priv->frames->len - 1); + + for (i = 0; i < n_modes; i++) + { + KeyFrame *frame = &g_array_index (priv->frames, KeyFrame, i); + + frame->mode = modes[i]; + } +} + +/** + * clutter_keyframe_transition_set: (skip) + * @transition: a #ClutterKeyframeTransition + * @gtype: the type of the values to use for the key frames + * @n_key_frames: the number of key frames between the initial + * and final values + * @...: a list of tuples, containing the key frame index, the value + * at the key frame, and the animation mode + * + * Sets the key frames of the @transition. + * + * This variadic arguments function is a convenience for C developers; + * language bindings should use clutter_keyframe_transition_set_key_frames(), + * clutter_keyframe_transition_set_modes(), and + * clutter_keyframe_transition_set_values() instead. + * + * Since: 1.12 + */ +void +clutter_keyframe_transition_set (ClutterKeyframeTransition *transition, + GType gtype, + guint n_key_frames, + ...) +{ + ClutterKeyframeTransitionPrivate *priv; + va_list args; + guint i; + + g_return_if_fail (CLUTTER_IS_KEYFRAME_TRANSITION (transition)); + g_return_if_fail (gtype != G_TYPE_INVALID); + g_return_if_fail (n_key_frames > 0); + + priv = transition->priv; + + if (priv->frames == NULL) + clutter_keyframe_transition_init_frames (transition, n_key_frames); + else + g_return_if_fail (n_key_frames == priv->frames->len - 1); + + va_start (args, n_key_frames); + + for (i = 0; i < n_key_frames; i++) + { + KeyFrame *frame = &g_array_index (priv->frames, KeyFrame, i); + GValue value = G_VALUE_INIT; + char *error = NULL; + + frame->key = va_arg (args, double); + + G_VALUE_COLLECT_INIT (&value, gtype, args, 0, &error); + if (error != NULL) + { + g_warning ("%s: %s", G_STRLOC, error); + g_free (error); + break; + } + + frame->mode = va_arg (args, ClutterAnimationMode); + + g_clear_object (&frame->interval); + frame->interval = clutter_interval_new_with_values (gtype, NULL, &value); + + g_value_unset (&value); + } + + va_end (args); +} + +/** + * clutter_keyframe_transition_clear: + * @transition: a #ClutterKeyframeTransition + * + * Removes all key frames from @transition. + * + * Since: 1.12 + */ +void +clutter_keyframe_transition_clear (ClutterKeyframeTransition *transition) +{ + g_return_if_fail (CLUTTER_IS_KEYFRAME_TRANSITION (transition)); + + if (transition->priv->frames != NULL) + { + g_array_unref (transition->priv->frames); + transition->priv->frames = NULL; + } +} + +/** + * clutter_keyframe_transition_get_n_key_frames: + * @transition: a #ClutterKeyframeTransition + * + * Retrieves the number of key frames inside @transition. + * + * Return value: the number of key frames + * + * Since: 1.12 + */ +guint +clutter_keyframe_transition_get_n_key_frames (ClutterKeyframeTransition *transition) +{ + g_return_val_if_fail (CLUTTER_IS_KEYFRAME_TRANSITION (transition), 0); + + if (transition->priv->frames == NULL) + return 0; + + return transition->priv->frames->len - 1; +} + +/** + * clutter_keyframe_transition_set_key_frame: + * @transition: a #ClutterKeyframeTransition + * @index_: the index of the key frame + * @key: the key of the key frame + * @mode: the easing mode of the key frame + * @value: a #GValue containing the value of the key frame + * + * Sets the details of the key frame at @index_ inside @transition. + * + * The @transition must already have a key frame at @index_, and @index_ + * must be smaller than the number of key frames inside @transition. + * + * Since: 1.12 + */ +void +clutter_keyframe_transition_set_key_frame (ClutterKeyframeTransition *transition, + guint index_, + double key, + ClutterAnimationMode mode, + const GValue *value) +{ + ClutterKeyframeTransitionPrivate *priv; + KeyFrame *frame; + + g_return_if_fail (CLUTTER_IS_KEYFRAME_TRANSITION (transition)); + + priv = transition->priv; + g_return_if_fail (priv->frames != NULL); + g_return_if_fail (index_ < priv->frames->len - 1); + + frame = &g_array_index (priv->frames, KeyFrame, index_); + frame->key = key; + frame->mode = mode; + clutter_interval_set_final_value (frame->interval, value); +} + +/** + * clutter_keyframe_transition_get_key_frame: + * @transition: a #ClutterKeyframeTransition + * @index_: the index of the key frame + * @key: (out) (allow-none): return location for the key, or %NULL + * @mode: (out) (allow-none): return location for the easing mode, or %NULL + * @value: (out caller-allocates): a #GValue initialized with the type of + * the values + * + * Retrieves the details of the key frame at @index_ inside @transition. + * + * The @transition must already have key frames set, and @index_ must be + * smaller than the number of key frames. + * + * Since: 1.12 + */ +void +clutter_keyframe_transition_get_key_frame (ClutterKeyframeTransition *transition, + guint index_, + double *key, + ClutterAnimationMode *mode, + GValue *value) +{ + ClutterKeyframeTransitionPrivate *priv; + const KeyFrame *frame; + + g_return_if_fail (CLUTTER_IS_KEYFRAME_TRANSITION (transition)); + + priv = transition->priv; + g_return_if_fail (priv->frames != NULL); + g_return_if_fail (index_ < priv->frames->len - 1); + + frame = &g_array_index (priv->frames, KeyFrame, index_); + + if (key != NULL) + *key = frame->key; + + if (mode != NULL) + *mode = frame->mode; + + if (value != NULL) + clutter_interval_get_final_value (frame->interval, value); +} diff --git a/clutter/clutter/clutter-keyframe-transition.h b/clutter/clutter/clutter-keyframe-transition.h new file mode 100644 index 0000000..d0fe84e --- /dev/null +++ b/clutter/clutter/clutter-keyframe-transition.h @@ -0,0 +1,122 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2012 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 . + * + * Author: Emmanuele Bassi + */ + +#ifndef __CLUTTER_KEYFRAME_TRANSITION_H__ +#define __CLUTTER_KEYFRAME_TRANSITION_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_KEYFRAME_TRANSITION (clutter_keyframe_transition_get_type ()) +#define CLUTTER_KEYFRAME_TRANSITION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_KEYFRAME_TRANSITION, ClutterKeyframeTransition)) +#define CLUTTER_IS_KEYFRAME_TRANSITION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_KEYFRAME_TRANSITION)) +#define CLUTTER_KEYFRAME_TRANSITION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_KEYFRAME_TRANSITION, ClutterKeyframeTransitionClass)) +#define CLUTTER_IS_KEYFRAME_TRANSITION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_KEYFRAME_TRANSITION)) +#define CLUTTER_KEYFRAME_TRANSITION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_KEYFRAME_TRANSITION, ClutterKeyframeTransitionClass)) + +typedef struct _ClutterKeyframeTransitionPrivate ClutterKeyframeTransitionPrivate; +typedef struct _ClutterKeyframeTransitionClass ClutterKeyframeTransitionClass; + +/** + * ClutterKeyframeTransition: + * + * The `ClutterKeyframeTransition` structure contains only private + * data and should be accessed using the provided API. + * + * Since: 1.12 + */ +struct _ClutterKeyframeTransition +{ + /*< private >*/ + ClutterPropertyTransition parent_instance; + + ClutterKeyframeTransitionPrivate *priv; +}; + +/** + * ClutterKeyframeTransitionClass: + * + * The `ClutterKeyframeTransitionClass` structure contains only + * private data. + * + * Since: 1.12 + */ +struct _ClutterKeyframeTransitionClass +{ + /*< private >*/ + ClutterPropertyTransitionClass parent_class; + + gpointer _padding[8]; +}; + +CLUTTER_AVAILABLE_IN_1_12 +GType clutter_keyframe_transition_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_12 +ClutterTransition * clutter_keyframe_transition_new (const char *property_name); + +CLUTTER_AVAILABLE_IN_1_12 +void clutter_keyframe_transition_set_key_frames (ClutterKeyframeTransition *transition, + guint n_key_frames, + const double *key_frames); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_keyframe_transition_set_values (ClutterKeyframeTransition *transition, + guint n_values, + const GValue *values); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_keyframe_transition_set_modes (ClutterKeyframeTransition *transition, + guint n_modes, + const ClutterAnimationMode *modes); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_keyframe_transition_set (ClutterKeyframeTransition *transition, + GType gtype, + guint n_key_frames, + ...); + +CLUTTER_AVAILABLE_IN_1_12 +void clutter_keyframe_transition_set_key_frame (ClutterKeyframeTransition *transition, + guint index_, + double key, + ClutterAnimationMode mode, + const GValue *value); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_keyframe_transition_get_key_frame (ClutterKeyframeTransition *transition, + guint index_, + double *key, + ClutterAnimationMode *mode, + GValue *value); +CLUTTER_AVAILABLE_IN_1_12 +guint clutter_keyframe_transition_get_n_key_frames (ClutterKeyframeTransition *transition); + +CLUTTER_AVAILABLE_IN_1_12 +void clutter_keyframe_transition_clear (ClutterKeyframeTransition *transition); + +G_END_DECLS + +#endif /* __CLUTTER_KEYFRAME_TRANSITION_H__ */ diff --git a/clutter/clutter/clutter-keysyms-table.c b/clutter/clutter/clutter-keysyms-table.c new file mode 100644 index 0000000..47931f0 --- /dev/null +++ b/clutter/clutter/clutter-keysyms-table.c @@ -0,0 +1,1681 @@ +#include "clutter-build-config.h" + +#include + +#include "clutter-event.h" + +/* Code below from GDK, which contains following comment: + * + * Thanks to Markus G. Kuhn for the ksysym<->Unicode + * mapping functions, from the xterm sources. + */ +static const struct { + unsigned short keysym; + unsigned short ucs; +} clutter_keysym_to_unicode_tab[] = { + { 0x01a1, 0x0104 }, /* Aogonek Ą LATIN CAPITAL LETTER A WITH OGONEK */ + { 0x01a2, 0x02d8 }, /* breve ˘ BREVE */ + { 0x01a3, 0x0141 }, /* Lstroke Ł LATIN CAPITAL LETTER L WITH STROKE */ + { 0x01a5, 0x013d }, /* Lcaron Ľ LATIN CAPITAL LETTER L WITH CARON */ + { 0x01a6, 0x015a }, /* Sacute Ś LATIN CAPITAL LETTER S WITH ACUTE */ + { 0x01a9, 0x0160 }, /* Scaron Š LATIN CAPITAL LETTER S WITH CARON */ + { 0x01aa, 0x015e }, /* Scedilla Ş LATIN CAPITAL LETTER S WITH CEDILLA */ + { 0x01ab, 0x0164 }, /* Tcaron Ť LATIN CAPITAL LETTER T WITH CARON */ + { 0x01ac, 0x0179 }, /* Zacute Ź LATIN CAPITAL LETTER Z WITH ACUTE */ + { 0x01ae, 0x017d }, /* Zcaron Ž LATIN CAPITAL LETTER Z WITH CARON */ + { 0x01af, 0x017b }, /* Zabovedot Ż LATIN CAPITAL LETTER Z WITH DOT ABOVE */ + { 0x01b1, 0x0105 }, /* aogonek ą LATIN SMALL LETTER A WITH OGONEK */ + { 0x01b2, 0x02db }, /* ogonek ˛ OGONEK */ + { 0x01b3, 0x0142 }, /* lstroke ł LATIN SMALL LETTER L WITH STROKE */ + { 0x01b5, 0x013e }, /* lcaron ľ LATIN SMALL LETTER L WITH CARON */ + { 0x01b6, 0x015b }, /* sacute ś LATIN SMALL LETTER S WITH ACUTE */ + { 0x01b7, 0x02c7 }, /* caron ˇ CARON */ + { 0x01b9, 0x0161 }, /* scaron š LATIN SMALL LETTER S WITH CARON */ + { 0x01ba, 0x015f }, /* scedilla ş LATIN SMALL LETTER S WITH CEDILLA */ + { 0x01bb, 0x0165 }, /* tcaron ť LATIN SMALL LETTER T WITH CARON */ + { 0x01bc, 0x017a }, /* zacute ź LATIN SMALL LETTER Z WITH ACUTE */ + { 0x01bd, 0x02dd }, /* doubleacute ˝ DOUBLE ACUTE ACCENT */ + { 0x01be, 0x017e }, /* zcaron ž LATIN SMALL LETTER Z WITH CARON */ + { 0x01bf, 0x017c }, /* zabovedot ż LATIN SMALL LETTER Z WITH DOT ABOVE */ + { 0x01c0, 0x0154 }, /* Racute Ŕ LATIN CAPITAL LETTER R WITH ACUTE */ + { 0x01c3, 0x0102 }, /* Abreve Ă LATIN CAPITAL LETTER A WITH BREVE */ + { 0x01c5, 0x0139 }, /* Lacute Ĺ LATIN CAPITAL LETTER L WITH ACUTE */ + { 0x01c6, 0x0106 }, /* Cacute Ć LATIN CAPITAL LETTER C WITH ACUTE */ + { 0x01c8, 0x010c }, /* Ccaron Č LATIN CAPITAL LETTER C WITH CARON */ + { 0x01ca, 0x0118 }, /* Eogonek Ę LATIN CAPITAL LETTER E WITH OGONEK */ + { 0x01cc, 0x011a }, /* Ecaron Ě LATIN CAPITAL LETTER E WITH CARON */ + { 0x01cf, 0x010e }, /* Dcaron Ď LATIN CAPITAL LETTER D WITH CARON */ + { 0x01d0, 0x0110 }, /* Dstroke Đ LATIN CAPITAL LETTER D WITH STROKE */ + { 0x01d1, 0x0143 }, /* Nacute Ń LATIN CAPITAL LETTER N WITH ACUTE */ + { 0x01d2, 0x0147 }, /* Ncaron Ň LATIN CAPITAL LETTER N WITH CARON */ + { 0x01d5, 0x0150 }, /* Odoubleacute Ő LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */ + { 0x01d8, 0x0158 }, /* Rcaron Ř LATIN CAPITAL LETTER R WITH CARON */ + { 0x01d9, 0x016e }, /* Uring Ů LATIN CAPITAL LETTER U WITH RING ABOVE */ + { 0x01db, 0x0170 }, /* Udoubleacute Ű LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */ + { 0x01de, 0x0162 }, /* Tcedilla Ţ LATIN CAPITAL LETTER T WITH CEDILLA */ + { 0x01e0, 0x0155 }, /* racute ŕ LATIN SMALL LETTER R WITH ACUTE */ + { 0x01e3, 0x0103 }, /* abreve ă LATIN SMALL LETTER A WITH BREVE */ + { 0x01e5, 0x013a }, /* lacute ĺ LATIN SMALL LETTER L WITH ACUTE */ + { 0x01e6, 0x0107 }, /* cacute ć LATIN SMALL LETTER C WITH ACUTE */ + { 0x01e8, 0x010d }, /* ccaron č LATIN SMALL LETTER C WITH CARON */ + { 0x01ea, 0x0119 }, /* eogonek ę LATIN SMALL LETTER E WITH OGONEK */ + { 0x01ec, 0x011b }, /* ecaron ě LATIN SMALL LETTER E WITH CARON */ + { 0x01ef, 0x010f }, /* dcaron ď LATIN SMALL LETTER D WITH CARON */ + { 0x01f0, 0x0111 }, /* dstroke đ LATIN SMALL LETTER D WITH STROKE */ + { 0x01f1, 0x0144 }, /* nacute ń LATIN SMALL LETTER N WITH ACUTE */ + { 0x01f2, 0x0148 }, /* ncaron ň LATIN SMALL LETTER N WITH CARON */ + { 0x01f5, 0x0151 }, /* odoubleacute ő LATIN SMALL LETTER O WITH DOUBLE ACUTE */ + { 0x01f8, 0x0159 }, /* rcaron ř LATIN SMALL LETTER R WITH CARON */ + { 0x01f9, 0x016f }, /* uring ů LATIN SMALL LETTER U WITH RING ABOVE */ + { 0x01fb, 0x0171 }, /* udoubleacute ű LATIN SMALL LETTER U WITH DOUBLE ACUTE */ + { 0x01fe, 0x0163 }, /* tcedilla ţ LATIN SMALL LETTER T WITH CEDILLA */ + { 0x01ff, 0x02d9 }, /* abovedot ˙ DOT ABOVE */ + { 0x02a1, 0x0126 }, /* Hstroke Ħ LATIN CAPITAL LETTER H WITH STROKE */ + { 0x02a6, 0x0124 }, /* Hcircumflex Ĥ LATIN CAPITAL LETTER H WITH CIRCUMFLEX */ + { 0x02a9, 0x0130 }, /* Iabovedot İ LATIN CAPITAL LETTER I WITH DOT ABOVE */ + { 0x02ab, 0x011e }, /* Gbreve Ğ LATIN CAPITAL LETTER G WITH BREVE */ + { 0x02ac, 0x0134 }, /* Jcircumflex Ĵ LATIN CAPITAL LETTER J WITH CIRCUMFLEX */ + { 0x02b1, 0x0127 }, /* hstroke ħ LATIN SMALL LETTER H WITH STROKE */ + { 0x02b6, 0x0125 }, /* hcircumflex ĥ LATIN SMALL LETTER H WITH CIRCUMFLEX */ + { 0x02b9, 0x0131 }, /* idotless ı LATIN SMALL LETTER DOTLESS I */ + { 0x02bb, 0x011f }, /* gbreve ğ LATIN SMALL LETTER G WITH BREVE */ + { 0x02bc, 0x0135 }, /* jcircumflex ĵ LATIN SMALL LETTER J WITH CIRCUMFLEX */ + { 0x02c5, 0x010a }, /* Cabovedot Ċ LATIN CAPITAL LETTER C WITH DOT ABOVE */ + { 0x02c6, 0x0108 }, /* Ccircumflex Ĉ LATIN CAPITAL LETTER C WITH CIRCUMFLEX */ + { 0x02d5, 0x0120 }, /* Gabovedot Ġ LATIN CAPITAL LETTER G WITH DOT ABOVE */ + { 0x02d8, 0x011c }, /* Gcircumflex Ĝ LATIN CAPITAL LETTER G WITH CIRCUMFLEX */ + { 0x02dd, 0x016c }, /* Ubreve Ŭ LATIN CAPITAL LETTER U WITH BREVE */ + { 0x02de, 0x015c }, /* Scircumflex Ŝ LATIN CAPITAL LETTER S WITH CIRCUMFLEX */ + { 0x02e5, 0x010b }, /* cabovedot ċ LATIN SMALL LETTER C WITH DOT ABOVE */ + { 0x02e6, 0x0109 }, /* ccircumflex ĉ LATIN SMALL LETTER C WITH CIRCUMFLEX */ + { 0x02f5, 0x0121 }, /* gabovedot ġ LATIN SMALL LETTER G WITH DOT ABOVE */ + { 0x02f8, 0x011d }, /* gcircumflex ĝ LATIN SMALL LETTER G WITH CIRCUMFLEX */ + { 0x02fd, 0x016d }, /* ubreve ŭ LATIN SMALL LETTER U WITH BREVE */ + { 0x02fe, 0x015d }, /* scircumflex ŝ LATIN SMALL LETTER S WITH CIRCUMFLEX */ + { 0x03a2, 0x0138 }, /* kra ĸ LATIN SMALL LETTER KRA */ + { 0x03a3, 0x0156 }, /* Rcedilla Ŗ LATIN CAPITAL LETTER R WITH CEDILLA */ + { 0x03a5, 0x0128 }, /* Itilde Ĩ LATIN CAPITAL LETTER I WITH TILDE */ + { 0x03a6, 0x013b }, /* Lcedilla Ļ LATIN CAPITAL LETTER L WITH CEDILLA */ + { 0x03aa, 0x0112 }, /* Emacron Ē LATIN CAPITAL LETTER E WITH MACRON */ + { 0x03ab, 0x0122 }, /* Gcedilla Ģ LATIN CAPITAL LETTER G WITH CEDILLA */ + { 0x03ac, 0x0166 }, /* Tslash Ŧ LATIN CAPITAL LETTER T WITH STROKE */ + { 0x03b3, 0x0157 }, /* rcedilla ŗ LATIN SMALL LETTER R WITH CEDILLA */ + { 0x03b5, 0x0129 }, /* itilde ĩ LATIN SMALL LETTER I WITH TILDE */ + { 0x03b6, 0x013c }, /* lcedilla ļ LATIN SMALL LETTER L WITH CEDILLA */ + { 0x03ba, 0x0113 }, /* emacron ē LATIN SMALL LETTER E WITH MACRON */ + { 0x03bb, 0x0123 }, /* gcedilla ģ LATIN SMALL LETTER G WITH CEDILLA */ + { 0x03bc, 0x0167 }, /* tslash ŧ LATIN SMALL LETTER T WITH STROKE */ + { 0x03bd, 0x014a }, /* ENG Ŋ LATIN CAPITAL LETTER ENG */ + { 0x03bf, 0x014b }, /* eng ŋ LATIN SMALL LETTER ENG */ + { 0x03c0, 0x0100 }, /* Amacron Ā LATIN CAPITAL LETTER A WITH MACRON */ + { 0x03c7, 0x012e }, /* Iogonek Į LATIN CAPITAL LETTER I WITH OGONEK */ + { 0x03cc, 0x0116 }, /* Eabovedot Ė LATIN CAPITAL LETTER E WITH DOT ABOVE */ + { 0x03cf, 0x012a }, /* Imacron Ī LATIN CAPITAL LETTER I WITH MACRON */ + { 0x03d1, 0x0145 }, /* Ncedilla Ņ LATIN CAPITAL LETTER N WITH CEDILLA */ + { 0x03d2, 0x014c }, /* Omacron Ō LATIN CAPITAL LETTER O WITH MACRON */ + { 0x03d3, 0x0136 }, /* Kcedilla Ķ LATIN CAPITAL LETTER K WITH CEDILLA */ + { 0x03d9, 0x0172 }, /* Uogonek Ų LATIN CAPITAL LETTER U WITH OGONEK */ + { 0x03dd, 0x0168 }, /* Utilde Ũ LATIN CAPITAL LETTER U WITH TILDE */ + { 0x03de, 0x016a }, /* Umacron Ū LATIN CAPITAL LETTER U WITH MACRON */ + { 0x03e0, 0x0101 }, /* amacron ā LATIN SMALL LETTER A WITH MACRON */ + { 0x03e7, 0x012f }, /* iogonek į LATIN SMALL LETTER I WITH OGONEK */ + { 0x03ec, 0x0117 }, /* eabovedot ė LATIN SMALL LETTER E WITH DOT ABOVE */ + { 0x03ef, 0x012b }, /* imacron ī LATIN SMALL LETTER I WITH MACRON */ + { 0x03f1, 0x0146 }, /* ncedilla ņ LATIN SMALL LETTER N WITH CEDILLA */ + { 0x03f2, 0x014d }, /* omacron ō LATIN SMALL LETTER O WITH MACRON */ + { 0x03f3, 0x0137 }, /* kcedilla ķ LATIN SMALL LETTER K WITH CEDILLA */ + { 0x03f9, 0x0173 }, /* uogonek ų LATIN SMALL LETTER U WITH OGONEK */ + { 0x03fd, 0x0169 }, /* utilde ũ LATIN SMALL LETTER U WITH TILDE */ + { 0x03fe, 0x016b }, /* umacron ū LATIN SMALL LETTER U WITH MACRON */ + { 0x047e, 0x203e }, /* overline ‾ OVERLINE */ + { 0x04a1, 0x3002 }, /* kana_fullstop 。 IDEOGRAPHIC FULL STOP */ + { 0x04a2, 0x300c }, /* kana_openingbracket 「 LEFT CORNER BRACKET */ + { 0x04a3, 0x300d }, /* kana_closingbracket 」 RIGHT CORNER BRACKET */ + { 0x04a4, 0x3001 }, /* kana_comma 、 IDEOGRAPHIC COMMA */ + { 0x04a5, 0x30fb }, /* kana_conjunctive ・ KATAKANA MIDDLE DOT */ + { 0x04a6, 0x30f2 }, /* kana_WO ヲ KATAKANA LETTER WO */ + { 0x04a7, 0x30a1 }, /* kana_a ァ KATAKANA LETTER SMALL A */ + { 0x04a8, 0x30a3 }, /* kana_i ィ KATAKANA LETTER SMALL I */ + { 0x04a9, 0x30a5 }, /* kana_u ゥ KATAKANA LETTER SMALL U */ + { 0x04aa, 0x30a7 }, /* kana_e ェ KATAKANA LETTER SMALL E */ + { 0x04ab, 0x30a9 }, /* kana_o ォ KATAKANA LETTER SMALL O */ + { 0x04ac, 0x30e3 }, /* kana_ya ャ KATAKANA LETTER SMALL YA */ + { 0x04ad, 0x30e5 }, /* kana_yu ュ KATAKANA LETTER SMALL YU */ + { 0x04ae, 0x30e7 }, /* kana_yo ョ KATAKANA LETTER SMALL YO */ + { 0x04af, 0x30c3 }, /* kana_tsu ッ KATAKANA LETTER SMALL TU */ + { 0x04b0, 0x30fc }, /* prolongedsound ー KATAKANA-HIRAGANA PROLONGED SOUND MARK */ + { 0x04b1, 0x30a2 }, /* kana_A ア KATAKANA LETTER A */ + { 0x04b2, 0x30a4 }, /* kana_I イ KATAKANA LETTER I */ + { 0x04b3, 0x30a6 }, /* kana_U ウ KATAKANA LETTER U */ + { 0x04b4, 0x30a8 }, /* kana_E エ KATAKANA LETTER E */ + { 0x04b5, 0x30aa }, /* kana_O オ KATAKANA LETTER O */ + { 0x04b6, 0x30ab }, /* kana_KA カ KATAKANA LETTER KA */ + { 0x04b7, 0x30ad }, /* kana_KI キ KATAKANA LETTER KI */ + { 0x04b8, 0x30af }, /* kana_KU ク KATAKANA LETTER KU */ + { 0x04b9, 0x30b1 }, /* kana_KE ケ KATAKANA LETTER KE */ + { 0x04ba, 0x30b3 }, /* kana_KO コ KATAKANA LETTER KO */ + { 0x04bb, 0x30b5 }, /* kana_SA サ KATAKANA LETTER SA */ + { 0x04bc, 0x30b7 }, /* kana_SHI シ KATAKANA LETTER SI */ + { 0x04bd, 0x30b9 }, /* kana_SU ス KATAKANA LETTER SU */ + { 0x04be, 0x30bb }, /* kana_SE セ KATAKANA LETTER SE */ + { 0x04bf, 0x30bd }, /* kana_SO ソ KATAKANA LETTER SO */ + { 0x04c0, 0x30bf }, /* kana_TA タ KATAKANA LETTER TA */ + { 0x04c1, 0x30c1 }, /* kana_CHI チ KATAKANA LETTER TI */ + { 0x04c2, 0x30c4 }, /* kana_TSU ツ KATAKANA LETTER TU */ + { 0x04c3, 0x30c6 }, /* kana_TE テ KATAKANA LETTER TE */ + { 0x04c4, 0x30c8 }, /* kana_TO ト KATAKANA LETTER TO */ + { 0x04c5, 0x30ca }, /* kana_NA ナ KATAKANA LETTER NA */ + { 0x04c6, 0x30cb }, /* kana_NI ニ KATAKANA LETTER NI */ + { 0x04c7, 0x30cc }, /* kana_NU ヌ KATAKANA LETTER NU */ + { 0x04c8, 0x30cd }, /* kana_NE ネ KATAKANA LETTER NE */ + { 0x04c9, 0x30ce }, /* kana_NO ノ KATAKANA LETTER NO */ + { 0x04ca, 0x30cf }, /* kana_HA ハ KATAKANA LETTER HA */ + { 0x04cb, 0x30d2 }, /* kana_HI ヒ KATAKANA LETTER HI */ + { 0x04cc, 0x30d5 }, /* kana_FU フ KATAKANA LETTER HU */ + { 0x04cd, 0x30d8 }, /* kana_HE ヘ KATAKANA LETTER HE */ + { 0x04ce, 0x30db }, /* kana_HO ホ KATAKANA LETTER HO */ + { 0x04cf, 0x30de }, /* kana_MA マ KATAKANA LETTER MA */ + { 0x04d0, 0x30df }, /* kana_MI ミ KATAKANA LETTER MI */ + { 0x04d1, 0x30e0 }, /* kana_MU ム KATAKANA LETTER MU */ + { 0x04d2, 0x30e1 }, /* kana_ME メ KATAKANA LETTER ME */ + { 0x04d3, 0x30e2 }, /* kana_MO モ KATAKANA LETTER MO */ + { 0x04d4, 0x30e4 }, /* kana_YA ヤ KATAKANA LETTER YA */ + { 0x04d5, 0x30e6 }, /* kana_YU ユ KATAKANA LETTER YU */ + { 0x04d6, 0x30e8 }, /* kana_YO ヨ KATAKANA LETTER YO */ + { 0x04d7, 0x30e9 }, /* kana_RA ラ KATAKANA LETTER RA */ + { 0x04d8, 0x30ea }, /* kana_RI リ KATAKANA LETTER RI */ + { 0x04d9, 0x30eb }, /* kana_RU ル KATAKANA LETTER RU */ + { 0x04da, 0x30ec }, /* kana_RE レ KATAKANA LETTER RE */ + { 0x04db, 0x30ed }, /* kana_RO ロ KATAKANA LETTER RO */ + { 0x04dc, 0x30ef }, /* kana_WA ワ KATAKANA LETTER WA */ + { 0x04dd, 0x30f3 }, /* kana_N ン KATAKANA LETTER N */ + { 0x04de, 0x309b }, /* voicedsound ゛ KATAKANA-HIRAGANA VOICED SOUND MARK */ + { 0x04df, 0x309c }, /* semivoicedsound ゜ KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */ + { 0x05ac, 0x060c }, /* Arabic_comma ، ARABIC COMMA */ + { 0x05bb, 0x061b }, /* Arabic_semicolon ؛ ARABIC SEMICOLON */ + { 0x05bf, 0x061f }, /* Arabic_question_mark ؟ ARABIC QUESTION MARK */ + { 0x05c1, 0x0621 }, /* Arabic_hamza ء ARABIC LETTER HAMZA */ + { 0x05c2, 0x0622 }, /* Arabic_maddaonalef آ ARABIC LETTER ALEF WITH MADDA ABOVE */ + { 0x05c3, 0x0623 }, /* Arabic_hamzaonalef أ ARABIC LETTER ALEF WITH HAMZA ABOVE */ + { 0x05c4, 0x0624 }, /* Arabic_hamzaonwaw ؤ ARABIC LETTER WAW WITH HAMZA ABOVE */ + { 0x05c5, 0x0625 }, /* Arabic_hamzaunderalef إ ARABIC LETTER ALEF WITH HAMZA BELOW */ + { 0x05c6, 0x0626 }, /* Arabic_hamzaonyeh ئ ARABIC LETTER YEH WITH HAMZA ABOVE */ + { 0x05c7, 0x0627 }, /* Arabic_alef ا ARABIC LETTER ALEF */ + { 0x05c8, 0x0628 }, /* Arabic_beh ب ARABIC LETTER BEH */ + { 0x05c9, 0x0629 }, /* Arabic_tehmarbuta ة ARABIC LETTER TEH MARBUTA */ + { 0x05ca, 0x062a }, /* Arabic_teh ت ARABIC LETTER TEH */ + { 0x05cb, 0x062b }, /* Arabic_theh ث ARABIC LETTER THEH */ + { 0x05cc, 0x062c }, /* Arabic_jeem ج ARABIC LETTER JEEM */ + { 0x05cd, 0x062d }, /* Arabic_hah ح ARABIC LETTER HAH */ + { 0x05ce, 0x062e }, /* Arabic_khah خ ARABIC LETTER KHAH */ + { 0x05cf, 0x062f }, /* Arabic_dal د ARABIC LETTER DAL */ + { 0x05d0, 0x0630 }, /* Arabic_thal ذ ARABIC LETTER THAL */ + { 0x05d1, 0x0631 }, /* Arabic_ra ر ARABIC LETTER REH */ + { 0x05d2, 0x0632 }, /* Arabic_zain ز ARABIC LETTER ZAIN */ + { 0x05d3, 0x0633 }, /* Arabic_seen س ARABIC LETTER SEEN */ + { 0x05d4, 0x0634 }, /* Arabic_sheen ش ARABIC LETTER SHEEN */ + { 0x05d5, 0x0635 }, /* Arabic_sad ص ARABIC LETTER SAD */ + { 0x05d6, 0x0636 }, /* Arabic_dad ض ARABIC LETTER DAD */ + { 0x05d7, 0x0637 }, /* Arabic_tah ط ARABIC LETTER TAH */ + { 0x05d8, 0x0638 }, /* Arabic_zah ظ ARABIC LETTER ZAH */ + { 0x05d9, 0x0639 }, /* Arabic_ain ع ARABIC LETTER AIN */ + { 0x05da, 0x063a }, /* Arabic_ghain غ ARABIC LETTER GHAIN */ + { 0x05e0, 0x0640 }, /* Arabic_tatweel ـ ARABIC TATWEEL */ + { 0x05e1, 0x0641 }, /* Arabic_feh ف ARABIC LETTER FEH */ + { 0x05e2, 0x0642 }, /* Arabic_qaf ق ARABIC LETTER QAF */ + { 0x05e3, 0x0643 }, /* Arabic_kaf ك ARABIC LETTER KAF */ + { 0x05e4, 0x0644 }, /* Arabic_lam ل ARABIC LETTER LAM */ + { 0x05e5, 0x0645 }, /* Arabic_meem م ARABIC LETTER MEEM */ + { 0x05e6, 0x0646 }, /* Arabic_noon ن ARABIC LETTER NOON */ + { 0x05e7, 0x0647 }, /* Arabic_ha ه ARABIC LETTER HEH */ + { 0x05e8, 0x0648 }, /* Arabic_waw و ARABIC LETTER WAW */ + { 0x05e9, 0x0649 }, /* Arabic_alefmaksura ى ARABIC LETTER ALEF MAKSURA */ + { 0x05ea, 0x064a }, /* Arabic_yeh ي ARABIC LETTER YEH */ + { 0x05eb, 0x064b }, /* Arabic_fathatan ً ARABIC FATHATAN */ + { 0x05ec, 0x064c }, /* Arabic_dammatan ٌ ARABIC DAMMATAN */ + { 0x05ed, 0x064d }, /* Arabic_kasratan ٍ ARABIC KASRATAN */ + { 0x05ee, 0x064e }, /* Arabic_fatha َ ARABIC FATHA */ + { 0x05ef, 0x064f }, /* Arabic_damma ُ ARABIC DAMMA */ + { 0x05f0, 0x0650 }, /* Arabic_kasra ِ ARABIC KASRA */ + { 0x05f1, 0x0651 }, /* Arabic_shadda ّ ARABIC SHADDA */ + { 0x05f2, 0x0652 }, /* Arabic_sukun ْ ARABIC SUKUN */ + { 0x06a1, 0x0452 }, /* Serbian_dje ђ CYRILLIC SMALL LETTER DJE */ + { 0x06a2, 0x0453 }, /* Macedonia_gje ѓ CYRILLIC SMALL LETTER GJE */ + { 0x06a3, 0x0451 }, /* Cyrillic_io ё CYRILLIC SMALL LETTER IO */ + { 0x06a4, 0x0454 }, /* Ukrainian_ie є CYRILLIC SMALL LETTER UKRAINIAN IE */ + { 0x06a5, 0x0455 }, /* Macedonia_dse ѕ CYRILLIC SMALL LETTER DZE */ + { 0x06a6, 0x0456 }, /* Ukrainian_i і CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */ + { 0x06a7, 0x0457 }, /* Ukrainian_yi ї CYRILLIC SMALL LETTER YI */ + { 0x06a8, 0x0458 }, /* Cyrillic_je ј CYRILLIC SMALL LETTER JE */ + { 0x06a9, 0x0459 }, /* Cyrillic_lje љ CYRILLIC SMALL LETTER LJE */ + { 0x06aa, 0x045a }, /* Cyrillic_nje њ CYRILLIC SMALL LETTER NJE */ + { 0x06ab, 0x045b }, /* Serbian_tshe ћ CYRILLIC SMALL LETTER TSHE */ + { 0x06ac, 0x045c }, /* Macedonia_kje ќ CYRILLIC SMALL LETTER KJE */ + { 0x06ad, 0x0491 }, /* Ukrainian_ghe_with_upturn ґ CYRILLIC SMALL LETTER GHE WITH UPTURN */ + { 0x06ae, 0x045e }, /* Byelorussian_shortu ў CYRILLIC SMALL LETTER SHORT U */ + { 0x06af, 0x045f }, /* Cyrillic_dzhe џ CYRILLIC SMALL LETTER DZHE */ + { 0x06b0, 0x2116 }, /* numerosign № NUMERO SIGN */ + { 0x06b1, 0x0402 }, /* Serbian_DJE Ђ CYRILLIC CAPITAL LETTER DJE */ + { 0x06b2, 0x0403 }, /* Macedonia_GJE Ѓ CYRILLIC CAPITAL LETTER GJE */ + { 0x06b3, 0x0401 }, /* Cyrillic_IO Ё CYRILLIC CAPITAL LETTER IO */ + { 0x06b4, 0x0404 }, /* Ukrainian_IE Є CYRILLIC CAPITAL LETTER UKRAINIAN IE */ + { 0x06b5, 0x0405 }, /* Macedonia_DSE Ѕ CYRILLIC CAPITAL LETTER DZE */ + { 0x06b6, 0x0406 }, /* Ukrainian_I І CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */ + { 0x06b7, 0x0407 }, /* Ukrainian_YI Ї CYRILLIC CAPITAL LETTER YI */ + { 0x06b8, 0x0408 }, /* Cyrillic_JE Ј CYRILLIC CAPITAL LETTER JE */ + { 0x06b9, 0x0409 }, /* Cyrillic_LJE Љ CYRILLIC CAPITAL LETTER LJE */ + { 0x06ba, 0x040a }, /* Cyrillic_NJE Њ CYRILLIC CAPITAL LETTER NJE */ + { 0x06bb, 0x040b }, /* Serbian_TSHE Ћ CYRILLIC CAPITAL LETTER TSHE */ + { 0x06bc, 0x040c }, /* Macedonia_KJE Ќ CYRILLIC CAPITAL LETTER KJE */ + { 0x06bd, 0x0490 }, /* Ukrainian_GHE_WITH_UPTURN Ґ CYRILLIC CAPITAL LETTER GHE WITH UPTURN */ + { 0x06be, 0x040e }, /* Byelorussian_SHORTU Ў CYRILLIC CAPITAL LETTER SHORT U */ + { 0x06bf, 0x040f }, /* Cyrillic_DZHE Џ CYRILLIC CAPITAL LETTER DZHE */ + { 0x06c0, 0x044e }, /* Cyrillic_yu ю CYRILLIC SMALL LETTER YU */ + { 0x06c1, 0x0430 }, /* Cyrillic_a а CYRILLIC SMALL LETTER A */ + { 0x06c2, 0x0431 }, /* Cyrillic_be б CYRILLIC SMALL LETTER BE */ + { 0x06c3, 0x0446 }, /* Cyrillic_tse ц CYRILLIC SMALL LETTER TSE */ + { 0x06c4, 0x0434 }, /* Cyrillic_de д CYRILLIC SMALL LETTER DE */ + { 0x06c5, 0x0435 }, /* Cyrillic_ie е CYRILLIC SMALL LETTER IE */ + { 0x06c6, 0x0444 }, /* Cyrillic_ef ф CYRILLIC SMALL LETTER EF */ + { 0x06c7, 0x0433 }, /* Cyrillic_ghe г CYRILLIC SMALL LETTER GHE */ + { 0x06c8, 0x0445 }, /* Cyrillic_ha х CYRILLIC SMALL LETTER HA */ + { 0x06c9, 0x0438 }, /* Cyrillic_i и CYRILLIC SMALL LETTER I */ + { 0x06ca, 0x0439 }, /* Cyrillic_shorti й CYRILLIC SMALL LETTER SHORT I */ + { 0x06cb, 0x043a }, /* Cyrillic_ka к CYRILLIC SMALL LETTER KA */ + { 0x06cc, 0x043b }, /* Cyrillic_el л CYRILLIC SMALL LETTER EL */ + { 0x06cd, 0x043c }, /* Cyrillic_em м CYRILLIC SMALL LETTER EM */ + { 0x06ce, 0x043d }, /* Cyrillic_en н CYRILLIC SMALL LETTER EN */ + { 0x06cf, 0x043e }, /* Cyrillic_o о CYRILLIC SMALL LETTER O */ + { 0x06d0, 0x043f }, /* Cyrillic_pe п CYRILLIC SMALL LETTER PE */ + { 0x06d1, 0x044f }, /* Cyrillic_ya я CYRILLIC SMALL LETTER YA */ + { 0x06d2, 0x0440 }, /* Cyrillic_er р CYRILLIC SMALL LETTER ER */ + { 0x06d3, 0x0441 }, /* Cyrillic_es с CYRILLIC SMALL LETTER ES */ + { 0x06d4, 0x0442 }, /* Cyrillic_te т CYRILLIC SMALL LETTER TE */ + { 0x06d5, 0x0443 }, /* Cyrillic_u у CYRILLIC SMALL LETTER U */ + { 0x06d6, 0x0436 }, /* Cyrillic_zhe ж CYRILLIC SMALL LETTER ZHE */ + { 0x06d7, 0x0432 }, /* Cyrillic_ve в CYRILLIC SMALL LETTER VE */ + { 0x06d8, 0x044c }, /* Cyrillic_softsign ь CYRILLIC SMALL LETTER SOFT SIGN */ + { 0x06d9, 0x044b }, /* Cyrillic_yeru ы CYRILLIC SMALL LETTER YERU */ + { 0x06da, 0x0437 }, /* Cyrillic_ze з CYRILLIC SMALL LETTER ZE */ + { 0x06db, 0x0448 }, /* Cyrillic_sha ш CYRILLIC SMALL LETTER SHA */ + { 0x06dc, 0x044d }, /* Cyrillic_e э CYRILLIC SMALL LETTER E */ + { 0x06dd, 0x0449 }, /* Cyrillic_shcha щ CYRILLIC SMALL LETTER SHCHA */ + { 0x06de, 0x0447 }, /* Cyrillic_che ч CYRILLIC SMALL LETTER CHE */ + { 0x06df, 0x044a }, /* Cyrillic_hardsign ъ CYRILLIC SMALL LETTER HARD SIGN */ + { 0x06e0, 0x042e }, /* Cyrillic_YU Ю CYRILLIC CAPITAL LETTER YU */ + { 0x06e1, 0x0410 }, /* Cyrillic_A А CYRILLIC CAPITAL LETTER A */ + { 0x06e2, 0x0411 }, /* Cyrillic_BE Б CYRILLIC CAPITAL LETTER BE */ + { 0x06e3, 0x0426 }, /* Cyrillic_TSE Ц CYRILLIC CAPITAL LETTER TSE */ + { 0x06e4, 0x0414 }, /* Cyrillic_DE Д CYRILLIC CAPITAL LETTER DE */ + { 0x06e5, 0x0415 }, /* Cyrillic_IE Е CYRILLIC CAPITAL LETTER IE */ + { 0x06e6, 0x0424 }, /* Cyrillic_EF Ф CYRILLIC CAPITAL LETTER EF */ + { 0x06e7, 0x0413 }, /* Cyrillic_GHE Г CYRILLIC CAPITAL LETTER GHE */ + { 0x06e8, 0x0425 }, /* Cyrillic_HA Х CYRILLIC CAPITAL LETTER HA */ + { 0x06e9, 0x0418 }, /* Cyrillic_I И CYRILLIC CAPITAL LETTER I */ + { 0x06ea, 0x0419 }, /* Cyrillic_SHORTI Й CYRILLIC CAPITAL LETTER SHORT I */ + { 0x06eb, 0x041a }, /* Cyrillic_KA К CYRILLIC CAPITAL LETTER KA */ + { 0x06ec, 0x041b }, /* Cyrillic_EL Л CYRILLIC CAPITAL LETTER EL */ + { 0x06ed, 0x041c }, /* Cyrillic_EM М CYRILLIC CAPITAL LETTER EM */ + { 0x06ee, 0x041d }, /* Cyrillic_EN Н CYRILLIC CAPITAL LETTER EN */ + { 0x06ef, 0x041e }, /* Cyrillic_O О CYRILLIC CAPITAL LETTER O */ + { 0x06f0, 0x041f }, /* Cyrillic_PE П CYRILLIC CAPITAL LETTER PE */ + { 0x06f1, 0x042f }, /* Cyrillic_YA Я CYRILLIC CAPITAL LETTER YA */ + { 0x06f2, 0x0420 }, /* Cyrillic_ER Р CYRILLIC CAPITAL LETTER ER */ + { 0x06f3, 0x0421 }, /* Cyrillic_ES С CYRILLIC CAPITAL LETTER ES */ + { 0x06f4, 0x0422 }, /* Cyrillic_TE Т CYRILLIC CAPITAL LETTER TE */ + { 0x06f5, 0x0423 }, /* Cyrillic_U У CYRILLIC CAPITAL LETTER U */ + { 0x06f6, 0x0416 }, /* Cyrillic_ZHE Ж CYRILLIC CAPITAL LETTER ZHE */ + { 0x06f7, 0x0412 }, /* Cyrillic_VE В CYRILLIC CAPITAL LETTER VE */ + { 0x06f8, 0x042c }, /* Cyrillic_SOFTSIGN Ь CYRILLIC CAPITAL LETTER SOFT SIGN */ + { 0x06f9, 0x042b }, /* Cyrillic_YERU Ы CYRILLIC CAPITAL LETTER YERU */ + { 0x06fa, 0x0417 }, /* Cyrillic_ZE З CYRILLIC CAPITAL LETTER ZE */ + { 0x06fb, 0x0428 }, /* Cyrillic_SHA Ш CYRILLIC CAPITAL LETTER SHA */ + { 0x06fc, 0x042d }, /* Cyrillic_E Э CYRILLIC CAPITAL LETTER E */ + { 0x06fd, 0x0429 }, /* Cyrillic_SHCHA Щ CYRILLIC CAPITAL LETTER SHCHA */ + { 0x06fe, 0x0427 }, /* Cyrillic_CHE Ч CYRILLIC CAPITAL LETTER CHE */ + { 0x06ff, 0x042a }, /* Cyrillic_HARDSIGN Ъ CYRILLIC CAPITAL LETTER HARD SIGN */ + { 0x07a1, 0x0386 }, /* Greek_ALPHAaccent Ά GREEK CAPITAL LETTER ALPHA WITH TONOS */ + { 0x07a2, 0x0388 }, /* Greek_EPSILONaccent Έ GREEK CAPITAL LETTER EPSILON WITH TONOS */ + { 0x07a3, 0x0389 }, /* Greek_ETAaccent Ή GREEK CAPITAL LETTER ETA WITH TONOS */ + { 0x07a4, 0x038a }, /* Greek_IOTAaccent Ί GREEK CAPITAL LETTER IOTA WITH TONOS */ + { 0x07a5, 0x03aa }, /* Greek_IOTAdieresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */ + { 0x07a7, 0x038c }, /* Greek_OMICRONaccent Ό GREEK CAPITAL LETTER OMICRON WITH TONOS */ + { 0x07a8, 0x038e }, /* Greek_UPSILONaccent Ύ GREEK CAPITAL LETTER UPSILON WITH TONOS */ + { 0x07a9, 0x03ab }, /* Greek_UPSILONdieresis Ϋ GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */ + { 0x07ab, 0x038f }, /* Greek_OMEGAaccent Ώ GREEK CAPITAL LETTER OMEGA WITH TONOS */ + { 0x07ae, 0x0385 }, /* Greek_accentdieresis ΅ GREEK DIALYTIKA TONOS */ + { 0x07af, 0x2015 }, /* Greek_horizbar ― HORIZONTAL BAR */ + { 0x07b1, 0x03ac }, /* Greek_alphaaccent ά GREEK SMALL LETTER ALPHA WITH TONOS */ + { 0x07b2, 0x03ad }, /* Greek_epsilonaccent έ GREEK SMALL LETTER EPSILON WITH TONOS */ + { 0x07b3, 0x03ae }, /* Greek_etaaccent ή GREEK SMALL LETTER ETA WITH TONOS */ + { 0x07b4, 0x03af }, /* Greek_iotaaccent ί GREEK SMALL LETTER IOTA WITH TONOS */ + { 0x07b5, 0x03ca }, /* Greek_iotadieresis ϊ GREEK SMALL LETTER IOTA WITH DIALYTIKA */ + { 0x07b6, 0x0390 }, /* Greek_iotaaccentdieresis ΐ GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */ + { 0x07b7, 0x03cc }, /* Greek_omicronaccent ό GREEK SMALL LETTER OMICRON WITH TONOS */ + { 0x07b8, 0x03cd }, /* Greek_upsilonaccent ύ GREEK SMALL LETTER UPSILON WITH TONOS */ + { 0x07b9, 0x03cb }, /* Greek_upsilondieresis ϋ GREEK SMALL LETTER UPSILON WITH DIALYTIKA */ + { 0x07ba, 0x03b0 }, /* Greek_upsilonaccentdieresis ΰ GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */ + { 0x07bb, 0x03ce }, /* Greek_omegaaccent ώ GREEK SMALL LETTER OMEGA WITH TONOS */ + { 0x07c1, 0x0391 }, /* Greek_ALPHA Α GREEK CAPITAL LETTER ALPHA */ + { 0x07c2, 0x0392 }, /* Greek_BETA Β GREEK CAPITAL LETTER BETA */ + { 0x07c3, 0x0393 }, /* Greek_GAMMA Γ GREEK CAPITAL LETTER GAMMA */ + { 0x07c4, 0x0394 }, /* Greek_DELTA Δ GREEK CAPITAL LETTER DELTA */ + { 0x07c5, 0x0395 }, /* Greek_EPSILON Ε GREEK CAPITAL LETTER EPSILON */ + { 0x07c6, 0x0396 }, /* Greek_ZETA Ζ GREEK CAPITAL LETTER ZETA */ + { 0x07c7, 0x0397 }, /* Greek_ETA Η GREEK CAPITAL LETTER ETA */ + { 0x07c8, 0x0398 }, /* Greek_THETA Θ GREEK CAPITAL LETTER THETA */ + { 0x07c9, 0x0399 }, /* Greek_IOTA Ι GREEK CAPITAL LETTER IOTA */ + { 0x07ca, 0x039a }, /* Greek_KAPPA Κ GREEK CAPITAL LETTER KAPPA */ + { 0x07cb, 0x039b }, /* Greek_LAMBDA Λ GREEK CAPITAL LETTER LAMDA */ + { 0x07cc, 0x039c }, /* Greek_MU Μ GREEK CAPITAL LETTER MU */ + { 0x07cd, 0x039d }, /* Greek_NU Ν GREEK CAPITAL LETTER NU */ + { 0x07ce, 0x039e }, /* Greek_XI Ξ GREEK CAPITAL LETTER XI */ + { 0x07cf, 0x039f }, /* Greek_OMICRON Ο GREEK CAPITAL LETTER OMICRON */ + { 0x07d0, 0x03a0 }, /* Greek_PI Π GREEK CAPITAL LETTER PI */ + { 0x07d1, 0x03a1 }, /* Greek_RHO Ρ GREEK CAPITAL LETTER RHO */ + { 0x07d2, 0x03a3 }, /* Greek_SIGMA Σ GREEK CAPITAL LETTER SIGMA */ + { 0x07d4, 0x03a4 }, /* Greek_TAU Τ GREEK CAPITAL LETTER TAU */ + { 0x07d5, 0x03a5 }, /* Greek_UPSILON Υ GREEK CAPITAL LETTER UPSILON */ + { 0x07d6, 0x03a6 }, /* Greek_PHI Φ GREEK CAPITAL LETTER PHI */ + { 0x07d7, 0x03a7 }, /* Greek_CHI Χ GREEK CAPITAL LETTER CHI */ + { 0x07d8, 0x03a8 }, /* Greek_PSI Ψ GREEK CAPITAL LETTER PSI */ + { 0x07d9, 0x03a9 }, /* Greek_OMEGA Ω GREEK CAPITAL LETTER OMEGA */ + { 0x07e1, 0x03b1 }, /* Greek_alpha α GREEK SMALL LETTER ALPHA */ + { 0x07e2, 0x03b2 }, /* Greek_beta β GREEK SMALL LETTER BETA */ + { 0x07e3, 0x03b3 }, /* Greek_gamma γ GREEK SMALL LETTER GAMMA */ + { 0x07e4, 0x03b4 }, /* Greek_delta δ GREEK SMALL LETTER DELTA */ + { 0x07e5, 0x03b5 }, /* Greek_epsilon ε GREEK SMALL LETTER EPSILON */ + { 0x07e6, 0x03b6 }, /* Greek_zeta ζ GREEK SMALL LETTER ZETA */ + { 0x07e7, 0x03b7 }, /* Greek_eta η GREEK SMALL LETTER ETA */ + { 0x07e8, 0x03b8 }, /* Greek_theta θ GREEK SMALL LETTER THETA */ + { 0x07e9, 0x03b9 }, /* Greek_iota ι GREEK SMALL LETTER IOTA */ + { 0x07ea, 0x03ba }, /* Greek_kappa κ GREEK SMALL LETTER KAPPA */ + { 0x07eb, 0x03bb }, /* Greek_lambda λ GREEK SMALL LETTER LAMDA */ + { 0x07ec, 0x03bc }, /* Greek_mu μ GREEK SMALL LETTER MU */ + { 0x07ed, 0x03bd }, /* Greek_nu ν GREEK SMALL LETTER NU */ + { 0x07ee, 0x03be }, /* Greek_xi ξ GREEK SMALL LETTER XI */ + { 0x07ef, 0x03bf }, /* Greek_omicron ο GREEK SMALL LETTER OMICRON */ + { 0x07f0, 0x03c0 }, /* Greek_pi π GREEK SMALL LETTER PI */ + { 0x07f1, 0x03c1 }, /* Greek_rho ρ GREEK SMALL LETTER RHO */ + { 0x07f2, 0x03c3 }, /* Greek_sigma σ GREEK SMALL LETTER SIGMA */ + { 0x07f3, 0x03c2 }, /* Greek_finalsmallsigma ς GREEK SMALL LETTER FINAL SIGMA */ + { 0x07f4, 0x03c4 }, /* Greek_tau τ GREEK SMALL LETTER TAU */ + { 0x07f5, 0x03c5 }, /* Greek_upsilon υ GREEK SMALL LETTER UPSILON */ + { 0x07f6, 0x03c6 }, /* Greek_phi φ GREEK SMALL LETTER PHI */ + { 0x07f7, 0x03c7 }, /* Greek_chi χ GREEK SMALL LETTER CHI */ + { 0x07f8, 0x03c8 }, /* Greek_psi ψ GREEK SMALL LETTER PSI */ + { 0x07f9, 0x03c9 }, /* Greek_omega ω GREEK SMALL LETTER OMEGA */ +/* 0x08a1 leftradical ? ??? */ +/* 0x08a2 topleftradical ? ??? */ +/* 0x08a3 horizconnector ? ??? */ + { 0x08a4, 0x2320 }, /* topintegral ⌠ TOP HALF INTEGRAL */ + { 0x08a5, 0x2321 }, /* botintegral ⌡ BOTTOM HALF INTEGRAL */ + { 0x08a6, 0x2502 }, /* vertconnector │ BOX DRAWINGS LIGHT VERTICAL */ +/* 0x08a7 topleftsqbracket ? ??? */ +/* 0x08a8 botleftsqbracket ? ??? */ +/* 0x08a9 toprightsqbracket ? ??? */ +/* 0x08aa botrightsqbracket ? ??? */ +/* 0x08ab topleftparens ? ??? */ +/* 0x08ac botleftparens ? ??? */ +/* 0x08ad toprightparens ? ??? */ +/* 0x08ae botrightparens ? ??? */ +/* 0x08af leftmiddlecurlybrace ? ??? */ +/* 0x08b0 rightmiddlecurlybrace ? ??? */ +/* 0x08b1 topleftsummation ? ??? */ +/* 0x08b2 botleftsummation ? ??? */ +/* 0x08b3 topvertsummationconnector ? ??? */ +/* 0x08b4 botvertsummationconnector ? ??? */ +/* 0x08b5 toprightsummation ? ??? */ +/* 0x08b6 botrightsummation ? ??? */ +/* 0x08b7 rightmiddlesummation ? ??? */ + { 0x08bc, 0x2264 }, /* lessthanequal ≤ LESS-THAN OR EQUAL TO */ + { 0x08bd, 0x2260 }, /* notequal ≠ NOT EQUAL TO */ + { 0x08be, 0x2265 }, /* greaterthanequal ≥ GREATER-THAN OR EQUAL TO */ + { 0x08bf, 0x222b }, /* integral ∫ INTEGRAL */ + { 0x08c0, 0x2234 }, /* therefore ∴ THEREFORE */ + { 0x08c1, 0x221d }, /* variation ∝ PROPORTIONAL TO */ + { 0x08c2, 0x221e }, /* infinity ∞ INFINITY */ + { 0x08c5, 0x2207 }, /* nabla ∇ NABLA */ + { 0x08c8, 0x2245 }, /* approximate ≅ APPROXIMATELY EQUAL TO */ +/* 0x08c9 similarequal ? ??? */ + { 0x08cd, 0x21d4 }, /* ifonlyif ⇔ LEFT RIGHT DOUBLE ARROW */ + { 0x08ce, 0x21d2 }, /* implies ⇒ RIGHTWARDS DOUBLE ARROW */ + { 0x08cf, 0x2261 }, /* identical ≡ IDENTICAL TO */ + { 0x08d6, 0x221a }, /* radical √ SQUARE ROOT */ + { 0x08da, 0x2282 }, /* includedin ⊂ SUBSET OF */ + { 0x08db, 0x2283 }, /* includes ⊃ SUPERSET OF */ + { 0x08dc, 0x2229 }, /* intersection ∩ INTERSECTION */ + { 0x08dd, 0x222a }, /* union ∪ UNION */ + { 0x08de, 0x2227 }, /* logicaland ∧ LOGICAL AND */ + { 0x08df, 0x2228 }, /* logicalor ∨ LOGICAL OR */ + { 0x08ef, 0x2202 }, /* partialderivative ∂ PARTIAL DIFFERENTIAL */ + { 0x08f6, 0x0192 }, /* function ƒ LATIN SMALL LETTER F WITH HOOK */ + { 0x08fb, 0x2190 }, /* leftarrow ← LEFTWARDS ARROW */ + { 0x08fc, 0x2191 }, /* uparrow ↑ UPWARDS ARROW */ + { 0x08fd, 0x2192 }, /* rightarrow → RIGHTWARDS ARROW */ + { 0x08fe, 0x2193 }, /* downarrow ↓ DOWNWARDS ARROW */ + { 0x09df, 0x2422 }, /* blank ␢ BLANK SYMBOL */ + { 0x09e0, 0x25c6 }, /* soliddiamond ◆ BLACK DIAMOND */ + { 0x09e1, 0x2592 }, /* checkerboard ▒ MEDIUM SHADE */ + { 0x09e2, 0x2409 }, /* ht ␉ SYMBOL FOR HORIZONTAL TABULATION */ + { 0x09e3, 0x240c }, /* ff ␌ SYMBOL FOR FORM FEED */ + { 0x09e4, 0x240d }, /* cr ␍ SYMBOL FOR CARRIAGE RETURN */ + { 0x09e5, 0x240a }, /* lf ␊ SYMBOL FOR LINE FEED */ + { 0x09e8, 0x2424 }, /* nl ␤ SYMBOL FOR NEWLINE */ + { 0x09e9, 0x240b }, /* vt ␋ SYMBOL FOR VERTICAL TABULATION */ + { 0x09ea, 0x2518 }, /* lowrightcorner ┘ BOX DRAWINGS LIGHT UP AND LEFT */ + { 0x09eb, 0x2510 }, /* uprightcorner ┐ BOX DRAWINGS LIGHT DOWN AND LEFT */ + { 0x09ec, 0x250c }, /* upleftcorner ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */ + { 0x09ed, 0x2514 }, /* lowleftcorner └ BOX DRAWINGS LIGHT UP AND RIGHT */ + { 0x09ee, 0x253c }, /* crossinglines ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */ +/* 0x09ef horizlinescan1 ? ??? */ +/* 0x09f0 horizlinescan3 ? ??? */ + { 0x09f1, 0x2500 }, /* horizlinescan5 ─ BOX DRAWINGS LIGHT HORIZONTAL */ +/* 0x09f2 horizlinescan7 ? ??? */ +/* 0x09f3 horizlinescan9 ? ??? */ + { 0x09f4, 0x251c }, /* leftt ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT */ + { 0x09f5, 0x2524 }, /* rightt ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT */ + { 0x09f6, 0x2534 }, /* bott ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL */ + { 0x09f7, 0x252c }, /* topt ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */ + { 0x09f8, 0x2502 }, /* vertbar │ BOX DRAWINGS LIGHT VERTICAL */ + { 0x0aa1, 0x2003 }, /* emspace   EM SPACE */ + { 0x0aa2, 0x2002 }, /* enspace   EN SPACE */ + { 0x0aa3, 0x2004 }, /* em3space   THREE-PER-EM SPACE */ + { 0x0aa4, 0x2005 }, /* em4space   FOUR-PER-EM SPACE */ + { 0x0aa5, 0x2007 }, /* digitspace   FIGURE SPACE */ + { 0x0aa6, 0x2008 }, /* punctspace   PUNCTUATION SPACE */ + { 0x0aa7, 0x2009 }, /* thinspace   THIN SPACE */ + { 0x0aa8, 0x200a }, /* hairspace   HAIR SPACE */ + { 0x0aa9, 0x2014 }, /* emdash — EM DASH */ + { 0x0aaa, 0x2013 }, /* endash – EN DASH */ +/* 0x0aac signifblank ? ??? */ + { 0x0aae, 0x2026 }, /* ellipsis … HORIZONTAL ELLIPSIS */ +/* 0x0aaf doubbaselinedot ? ??? */ + { 0x0ab0, 0x2153 }, /* onethird ⅓ VULGAR FRACTION ONE THIRD */ + { 0x0ab1, 0x2154 }, /* twothirds ⅔ VULGAR FRACTION TWO THIRDS */ + { 0x0ab2, 0x2155 }, /* onefifth ⅕ VULGAR FRACTION ONE FIFTH */ + { 0x0ab3, 0x2156 }, /* twofifths ⅖ VULGAR FRACTION TWO FIFTHS */ + { 0x0ab4, 0x2157 }, /* threefifths ⅗ VULGAR FRACTION THREE FIFTHS */ + { 0x0ab5, 0x2158 }, /* fourfifths ⅘ VULGAR FRACTION FOUR FIFTHS */ + { 0x0ab6, 0x2159 }, /* onesixth ⅙ VULGAR FRACTION ONE SIXTH */ + { 0x0ab7, 0x215a }, /* fivesixths ⅚ VULGAR FRACTION FIVE SIXTHS */ + { 0x0ab8, 0x2105 }, /* careof ℅ CARE OF */ + { 0x0abb, 0x2012 }, /* figdash ‒ FIGURE DASH */ + { 0x0abc, 0x2329 }, /* leftanglebracket 〈 LEFT-POINTING ANGLE BRACKET */ + { 0x0abd, 0x002e }, /* decimalpoint . FULL STOP */ + { 0x0abe, 0x232a }, /* rightanglebracket 〉 RIGHT-POINTING ANGLE BRACKET */ +/* 0x0abf marker ? ??? */ + { 0x0ac3, 0x215b }, /* oneeighth ⅛ VULGAR FRACTION ONE EIGHTH */ + { 0x0ac4, 0x215c }, /* threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS */ + { 0x0ac5, 0x215d }, /* fiveeighths ⅝ VULGAR FRACTION FIVE EIGHTHS */ + { 0x0ac6, 0x215e }, /* seveneighths ⅞ VULGAR FRACTION SEVEN EIGHTHS */ + { 0x0ac9, 0x2122 }, /* trademark ™ TRADE MARK SIGN */ + { 0x0aca, 0x2613 }, /* signaturemark ☓ SALTIRE */ +/* 0x0acb trademarkincircle ? ??? */ + { 0x0acc, 0x25c1 }, /* leftopentriangle ◁ WHITE LEFT-POINTING TRIANGLE */ + { 0x0acd, 0x25b7 }, /* rightopentriangle ▷ WHITE RIGHT-POINTING TRIANGLE */ + { 0x0ace, 0x25cb }, /* emopencircle ○ WHITE CIRCLE */ + { 0x0acf, 0x25a1 }, /* emopenrectangle □ WHITE SQUARE */ + { 0x0ad0, 0x2018 }, /* leftsinglequotemark ‘ LEFT SINGLE QUOTATION MARK */ + { 0x0ad1, 0x2019 }, /* rightsinglequotemark ’ RIGHT SINGLE QUOTATION MARK */ + { 0x0ad2, 0x201c }, /* leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK */ + { 0x0ad3, 0x201d }, /* rightdoublequotemark ” RIGHT DOUBLE QUOTATION MARK */ + { 0x0ad4, 0x211e }, /* prescription ℞ PRESCRIPTION TAKE */ + { 0x0ad6, 0x2032 }, /* minutes ′ PRIME */ + { 0x0ad7, 0x2033 }, /* seconds ″ DOUBLE PRIME */ + { 0x0ad9, 0x271d }, /* latincross ✝ LATIN CROSS */ +/* 0x0ada hexagram ? ??? */ + { 0x0adb, 0x25ac }, /* filledrectbullet ▬ BLACK RECTANGLE */ + { 0x0adc, 0x25c0 }, /* filledlefttribullet ◀ BLACK LEFT-POINTING TRIANGLE */ + { 0x0add, 0x25b6 }, /* filledrighttribullet ▶ BLACK RIGHT-POINTING TRIANGLE */ + { 0x0ade, 0x25cf }, /* emfilledcircle ● BLACK CIRCLE */ + { 0x0adf, 0x25a0 }, /* emfilledrect ■ BLACK SQUARE */ + { 0x0ae0, 0x25e6 }, /* enopencircbullet ◦ WHITE BULLET */ + { 0x0ae1, 0x25ab }, /* enopensquarebullet ▫ WHITE SMALL SQUARE */ + { 0x0ae2, 0x25ad }, /* openrectbullet ▭ WHITE RECTANGLE */ + { 0x0ae3, 0x25b3 }, /* opentribulletup △ WHITE UP-POINTING TRIANGLE */ + { 0x0ae4, 0x25bd }, /* opentribulletdown ▽ WHITE DOWN-POINTING TRIANGLE */ + { 0x0ae5, 0x2606 }, /* openstar ☆ WHITE STAR */ + { 0x0ae6, 0x2022 }, /* enfilledcircbullet • BULLET */ + { 0x0ae7, 0x25aa }, /* enfilledsqbullet ▪ BLACK SMALL SQUARE */ + { 0x0ae8, 0x25b2 }, /* filledtribulletup ▲ BLACK UP-POINTING TRIANGLE */ + { 0x0ae9, 0x25bc }, /* filledtribulletdown ▼ BLACK DOWN-POINTING TRIANGLE */ + { 0x0aea, 0x261c }, /* leftpointer ☜ WHITE LEFT POINTING INDEX */ + { 0x0aeb, 0x261e }, /* rightpointer ☞ WHITE RIGHT POINTING INDEX */ + { 0x0aec, 0x2663 }, /* club ♣ BLACK CLUB SUIT */ + { 0x0aed, 0x2666 }, /* diamond ♦ BLACK DIAMOND SUIT */ + { 0x0aee, 0x2665 }, /* heart ♥ BLACK HEART SUIT */ + { 0x0af0, 0x2720 }, /* maltesecross ✠ MALTESE CROSS */ + { 0x0af1, 0x2020 }, /* dagger † DAGGER */ + { 0x0af2, 0x2021 }, /* doubledagger ‡ DOUBLE DAGGER */ + { 0x0af3, 0x2713 }, /* checkmark ✓ CHECK MARK */ + { 0x0af4, 0x2717 }, /* ballotcross ✗ BALLOT X */ + { 0x0af5, 0x266f }, /* musicalsharp ♯ MUSIC SHARP SIGN */ + { 0x0af6, 0x266d }, /* musicalflat ♭ MUSIC FLAT SIGN */ + { 0x0af7, 0x2642 }, /* malesymbol ♂ MALE SIGN */ + { 0x0af8, 0x2640 }, /* femalesymbol ♀ FEMALE SIGN */ + { 0x0af9, 0x260e }, /* telephone ☎ BLACK TELEPHONE */ + { 0x0afa, 0x2315 }, /* telephonerecorder ⌕ TELEPHONE RECORDER */ + { 0x0afb, 0x2117 }, /* phonographcopyright ℗ SOUND RECORDING COPYRIGHT */ + { 0x0afc, 0x2038 }, /* caret ‸ CARET */ + { 0x0afd, 0x201a }, /* singlelowquotemark ‚ SINGLE LOW-9 QUOTATION MARK */ + { 0x0afe, 0x201e }, /* doublelowquotemark „ DOUBLE LOW-9 QUOTATION MARK */ +/* 0x0aff cursor ? ??? */ + { 0x0ba3, 0x003c }, /* leftcaret < LESS-THAN SIGN */ + { 0x0ba6, 0x003e }, /* rightcaret > GREATER-THAN SIGN */ + { 0x0ba8, 0x2228 }, /* downcaret ∨ LOGICAL OR */ + { 0x0ba9, 0x2227 }, /* upcaret ∧ LOGICAL AND */ + { 0x0bc0, 0x00af }, /* overbar ¯ MACRON */ + { 0x0bc2, 0x22a4 }, /* downtack ⊤ DOWN TACK */ + { 0x0bc3, 0x2229 }, /* upshoe ∩ INTERSECTION */ + { 0x0bc4, 0x230a }, /* downstile ⌊ LEFT FLOOR */ + { 0x0bc6, 0x005f }, /* underbar _ LOW LINE */ + { 0x0bca, 0x2218 }, /* jot ∘ RING OPERATOR */ + { 0x0bcc, 0x2395 }, /* quad ⎕ APL FUNCTIONAL SYMBOL QUAD (Unicode 3.0) */ + { 0x0bce, 0x22a5 }, /* uptack ⊥ UP TACK */ + { 0x0bcf, 0x25cb }, /* circle ○ WHITE CIRCLE */ + { 0x0bd3, 0x2308 }, /* upstile ⌈ LEFT CEILING */ + { 0x0bd6, 0x222a }, /* downshoe ∪ UNION */ + { 0x0bd8, 0x2283 }, /* rightshoe ⊃ SUPERSET OF */ + { 0x0bda, 0x2282 }, /* leftshoe ⊂ SUBSET OF */ + { 0x0bdc, 0x22a3 }, /* lefttack ⊣ LEFT TACK */ + { 0x0bfc, 0x22a2 }, /* righttack ⊢ RIGHT TACK */ + { 0x0cdf, 0x2017 }, /* hebrew_doublelowline ‗ DOUBLE LOW LINE */ + { 0x0ce0, 0x05d0 }, /* hebrew_aleph א HEBREW LETTER ALEF */ + { 0x0ce1, 0x05d1 }, /* hebrew_bet ב HEBREW LETTER BET */ + { 0x0ce2, 0x05d2 }, /* hebrew_gimel ג HEBREW LETTER GIMEL */ + { 0x0ce3, 0x05d3 }, /* hebrew_dalet ד HEBREW LETTER DALET */ + { 0x0ce4, 0x05d4 }, /* hebrew_he ה HEBREW LETTER HE */ + { 0x0ce5, 0x05d5 }, /* hebrew_waw ו HEBREW LETTER VAV */ + { 0x0ce6, 0x05d6 }, /* hebrew_zain ז HEBREW LETTER ZAYIN */ + { 0x0ce7, 0x05d7 }, /* hebrew_chet ח HEBREW LETTER HET */ + { 0x0ce8, 0x05d8 }, /* hebrew_tet ט HEBREW LETTER TET */ + { 0x0ce9, 0x05d9 }, /* hebrew_yod י HEBREW LETTER YOD */ + { 0x0cea, 0x05da }, /* hebrew_finalkaph ך HEBREW LETTER FINAL KAF */ + { 0x0ceb, 0x05db }, /* hebrew_kaph כ HEBREW LETTER KAF */ + { 0x0cec, 0x05dc }, /* hebrew_lamed ל HEBREW LETTER LAMED */ + { 0x0ced, 0x05dd }, /* hebrew_finalmem ם HEBREW LETTER FINAL MEM */ + { 0x0cee, 0x05de }, /* hebrew_mem מ HEBREW LETTER MEM */ + { 0x0cef, 0x05df }, /* hebrew_finalnun ן HEBREW LETTER FINAL NUN */ + { 0x0cf0, 0x05e0 }, /* hebrew_nun נ HEBREW LETTER NUN */ + { 0x0cf1, 0x05e1 }, /* hebrew_samech ס HEBREW LETTER SAMEKH */ + { 0x0cf2, 0x05e2 }, /* hebrew_ayin ע HEBREW LETTER AYIN */ + { 0x0cf3, 0x05e3 }, /* hebrew_finalpe ף HEBREW LETTER FINAL PE */ + { 0x0cf4, 0x05e4 }, /* hebrew_pe פ HEBREW LETTER PE */ + { 0x0cf5, 0x05e5 }, /* hebrew_finalzade ץ HEBREW LETTER FINAL TSADI */ + { 0x0cf6, 0x05e6 }, /* hebrew_zade צ HEBREW LETTER TSADI */ + { 0x0cf7, 0x05e7 }, /* hebrew_qoph ק HEBREW LETTER QOF */ + { 0x0cf8, 0x05e8 }, /* hebrew_resh ר HEBREW LETTER RESH */ + { 0x0cf9, 0x05e9 }, /* hebrew_shin ש HEBREW LETTER SHIN */ + { 0x0cfa, 0x05ea }, /* hebrew_taw ת HEBREW LETTER TAV */ + { 0x0da1, 0x0e01 }, /* Thai_kokai ก THAI CHARACTER KO KAI */ + { 0x0da2, 0x0e02 }, /* Thai_khokhai ข THAI CHARACTER KHO KHAI */ + { 0x0da3, 0x0e03 }, /* Thai_khokhuat ฃ THAI CHARACTER KHO KHUAT */ + { 0x0da4, 0x0e04 }, /* Thai_khokhwai ค THAI CHARACTER KHO KHWAI */ + { 0x0da5, 0x0e05 }, /* Thai_khokhon ฅ THAI CHARACTER KHO KHON */ + { 0x0da6, 0x0e06 }, /* Thai_khorakhang ฆ THAI CHARACTER KHO RAKHANG */ + { 0x0da7, 0x0e07 }, /* Thai_ngongu ง THAI CHARACTER NGO NGU */ + { 0x0da8, 0x0e08 }, /* Thai_chochan จ THAI CHARACTER CHO CHAN */ + { 0x0da9, 0x0e09 }, /* Thai_choching ฉ THAI CHARACTER CHO CHING */ + { 0x0daa, 0x0e0a }, /* Thai_chochang ช THAI CHARACTER CHO CHANG */ + { 0x0dab, 0x0e0b }, /* Thai_soso ซ THAI CHARACTER SO SO */ + { 0x0dac, 0x0e0c }, /* Thai_chochoe ฌ THAI CHARACTER CHO CHOE */ + { 0x0dad, 0x0e0d }, /* Thai_yoying ญ THAI CHARACTER YO YING */ + { 0x0dae, 0x0e0e }, /* Thai_dochada ฎ THAI CHARACTER DO CHADA */ + { 0x0daf, 0x0e0f }, /* Thai_topatak ฏ THAI CHARACTER TO PATAK */ + { 0x0db0, 0x0e10 }, /* Thai_thothan ฐ THAI CHARACTER THO THAN */ + { 0x0db1, 0x0e11 }, /* Thai_thonangmontho ฑ THAI CHARACTER THO NANGMONTHO */ + { 0x0db2, 0x0e12 }, /* Thai_thophuthao ฒ THAI CHARACTER THO PHUTHAO */ + { 0x0db3, 0x0e13 }, /* Thai_nonen ณ THAI CHARACTER NO NEN */ + { 0x0db4, 0x0e14 }, /* Thai_dodek ด THAI CHARACTER DO DEK */ + { 0x0db5, 0x0e15 }, /* Thai_totao ต THAI CHARACTER TO TAO */ + { 0x0db6, 0x0e16 }, /* Thai_thothung ถ THAI CHARACTER THO THUNG */ + { 0x0db7, 0x0e17 }, /* Thai_thothahan ท THAI CHARACTER THO THAHAN */ + { 0x0db8, 0x0e18 }, /* Thai_thothong ธ THAI CHARACTER THO THONG */ + { 0x0db9, 0x0e19 }, /* Thai_nonu น THAI CHARACTER NO NU */ + { 0x0dba, 0x0e1a }, /* Thai_bobaimai บ THAI CHARACTER BO BAIMAI */ + { 0x0dbb, 0x0e1b }, /* Thai_popla ป THAI CHARACTER PO PLA */ + { 0x0dbc, 0x0e1c }, /* Thai_phophung ผ THAI CHARACTER PHO PHUNG */ + { 0x0dbd, 0x0e1d }, /* Thai_fofa ฝ THAI CHARACTER FO FA */ + { 0x0dbe, 0x0e1e }, /* Thai_phophan พ THAI CHARACTER PHO PHAN */ + { 0x0dbf, 0x0e1f }, /* Thai_fofan ฟ THAI CHARACTER FO FAN */ + { 0x0dc0, 0x0e20 }, /* Thai_phosamphao ภ THAI CHARACTER PHO SAMPHAO */ + { 0x0dc1, 0x0e21 }, /* Thai_moma ม THAI CHARACTER MO MA */ + { 0x0dc2, 0x0e22 }, /* Thai_yoyak ย THAI CHARACTER YO YAK */ + { 0x0dc3, 0x0e23 }, /* Thai_rorua ร THAI CHARACTER RO RUA */ + { 0x0dc4, 0x0e24 }, /* Thai_ru ฤ THAI CHARACTER RU */ + { 0x0dc5, 0x0e25 }, /* Thai_loling ล THAI CHARACTER LO LING */ + { 0x0dc6, 0x0e26 }, /* Thai_lu ฦ THAI CHARACTER LU */ + { 0x0dc7, 0x0e27 }, /* Thai_wowaen ว THAI CHARACTER WO WAEN */ + { 0x0dc8, 0x0e28 }, /* Thai_sosala ศ THAI CHARACTER SO SALA */ + { 0x0dc9, 0x0e29 }, /* Thai_sorusi ษ THAI CHARACTER SO RUSI */ + { 0x0dca, 0x0e2a }, /* Thai_sosua ส THAI CHARACTER SO SUA */ + { 0x0dcb, 0x0e2b }, /* Thai_hohip ห THAI CHARACTER HO HIP */ + { 0x0dcc, 0x0e2c }, /* Thai_lochula ฬ THAI CHARACTER LO CHULA */ + { 0x0dcd, 0x0e2d }, /* Thai_oang อ THAI CHARACTER O ANG */ + { 0x0dce, 0x0e2e }, /* Thai_honokhuk ฮ THAI CHARACTER HO NOKHUK */ + { 0x0dcf, 0x0e2f }, /* Thai_paiyannoi ฯ THAI CHARACTER PAIYANNOI */ + { 0x0dd0, 0x0e30 }, /* Thai_saraa ะ THAI CHARACTER SARA A */ + { 0x0dd1, 0x0e31 }, /* Thai_maihanakat ั THAI CHARACTER MAI HAN-AKAT */ + { 0x0dd2, 0x0e32 }, /* Thai_saraaa า THAI CHARACTER SARA AA */ + { 0x0dd3, 0x0e33 }, /* Thai_saraam ำ THAI CHARACTER SARA AM */ + { 0x0dd4, 0x0e34 }, /* Thai_sarai ิ THAI CHARACTER SARA I */ + { 0x0dd5, 0x0e35 }, /* Thai_saraii ี THAI CHARACTER SARA II */ + { 0x0dd6, 0x0e36 }, /* Thai_saraue ึ THAI CHARACTER SARA UE */ + { 0x0dd7, 0x0e37 }, /* Thai_sarauee ื THAI CHARACTER SARA UEE */ + { 0x0dd8, 0x0e38 }, /* Thai_sarau ุ THAI CHARACTER SARA U */ + { 0x0dd9, 0x0e39 }, /* Thai_sarauu ู THAI CHARACTER SARA UU */ + { 0x0dda, 0x0e3a }, /* Thai_phinthu ฺ THAI CHARACTER PHINTHU */ + { 0x0dde, 0x0e3e }, /* Thai_maihanakat_maitho ฾ ??? */ + { 0x0ddf, 0x0e3f }, /* Thai_baht ฿ THAI CURRENCY SYMBOL BAHT */ + { 0x0de0, 0x0e40 }, /* Thai_sarae เ THAI CHARACTER SARA E */ + { 0x0de1, 0x0e41 }, /* Thai_saraae แ THAI CHARACTER SARA AE */ + { 0x0de2, 0x0e42 }, /* Thai_sarao โ THAI CHARACTER SARA O */ + { 0x0de3, 0x0e43 }, /* Thai_saraaimaimuan ใ THAI CHARACTER SARA AI MAIMUAN */ + { 0x0de4, 0x0e44 }, /* Thai_saraaimaimalai ไ THAI CHARACTER SARA AI MAIMALAI */ + { 0x0de5, 0x0e45 }, /* Thai_lakkhangyao ๅ THAI CHARACTER LAKKHANGYAO */ + { 0x0de6, 0x0e46 }, /* Thai_maiyamok ๆ THAI CHARACTER MAIYAMOK */ + { 0x0de7, 0x0e47 }, /* Thai_maitaikhu ็ THAI CHARACTER MAITAIKHU */ + { 0x0de8, 0x0e48 }, /* Thai_maiek ่ THAI CHARACTER MAI EK */ + { 0x0de9, 0x0e49 }, /* Thai_maitho ้ THAI CHARACTER MAI THO */ + { 0x0dea, 0x0e4a }, /* Thai_maitri ๊ THAI CHARACTER MAI TRI */ + { 0x0deb, 0x0e4b }, /* Thai_maichattawa ๋ THAI CHARACTER MAI CHATTAWA */ + { 0x0dec, 0x0e4c }, /* Thai_thanthakhat ์ THAI CHARACTER THANTHAKHAT */ + { 0x0ded, 0x0e4d }, /* Thai_nikhahit ํ THAI CHARACTER NIKHAHIT */ + { 0x0df0, 0x0e50 }, /* Thai_leksun ๐ THAI DIGIT ZERO */ + { 0x0df1, 0x0e51 }, /* Thai_leknung ๑ THAI DIGIT ONE */ + { 0x0df2, 0x0e52 }, /* Thai_leksong ๒ THAI DIGIT TWO */ + { 0x0df3, 0x0e53 }, /* Thai_leksam ๓ THAI DIGIT THREE */ + { 0x0df4, 0x0e54 }, /* Thai_leksi ๔ THAI DIGIT FOUR */ + { 0x0df5, 0x0e55 }, /* Thai_lekha ๕ THAI DIGIT FIVE */ + { 0x0df6, 0x0e56 }, /* Thai_lekhok ๖ THAI DIGIT SIX */ + { 0x0df7, 0x0e57 }, /* Thai_lekchet ๗ THAI DIGIT SEVEN */ + { 0x0df8, 0x0e58 }, /* Thai_lekpaet ๘ THAI DIGIT EIGHT */ + { 0x0df9, 0x0e59 }, /* Thai_lekkao ๙ THAI DIGIT NINE */ + { 0x0ea1, 0x3131 }, /* Hangul_Kiyeog ㄱ HANGUL LETTER KIYEOK */ + { 0x0ea2, 0x3132 }, /* Hangul_SsangKiyeog ㄲ HANGUL LETTER SSANGKIYEOK */ + { 0x0ea3, 0x3133 }, /* Hangul_KiyeogSios ㄳ HANGUL LETTER KIYEOK-SIOS */ + { 0x0ea4, 0x3134 }, /* Hangul_Nieun ㄴ HANGUL LETTER NIEUN */ + { 0x0ea5, 0x3135 }, /* Hangul_NieunJieuj ㄵ HANGUL LETTER NIEUN-CIEUC */ + { 0x0ea6, 0x3136 }, /* Hangul_NieunHieuh ㄶ HANGUL LETTER NIEUN-HIEUH */ + { 0x0ea7, 0x3137 }, /* Hangul_Dikeud ㄷ HANGUL LETTER TIKEUT */ + { 0x0ea8, 0x3138 }, /* Hangul_SsangDikeud ㄸ HANGUL LETTER SSANGTIKEUT */ + { 0x0ea9, 0x3139 }, /* Hangul_Rieul ㄹ HANGUL LETTER RIEUL */ + { 0x0eaa, 0x313a }, /* Hangul_RieulKiyeog ㄺ HANGUL LETTER RIEUL-KIYEOK */ + { 0x0eab, 0x313b }, /* Hangul_RieulMieum ㄻ HANGUL LETTER RIEUL-MIEUM */ + { 0x0eac, 0x313c }, /* Hangul_RieulPieub ㄼ HANGUL LETTER RIEUL-PIEUP */ + { 0x0ead, 0x313d }, /* Hangul_RieulSios ㄽ HANGUL LETTER RIEUL-SIOS */ + { 0x0eae, 0x313e }, /* Hangul_RieulTieut ㄾ HANGUL LETTER RIEUL-THIEUTH */ + { 0x0eaf, 0x313f }, /* Hangul_RieulPhieuf ㄿ HANGUL LETTER RIEUL-PHIEUPH */ + { 0x0eb0, 0x3140 }, /* Hangul_RieulHieuh ㅀ HANGUL LETTER RIEUL-HIEUH */ + { 0x0eb1, 0x3141 }, /* Hangul_Mieum ㅁ HANGUL LETTER MIEUM */ + { 0x0eb2, 0x3142 }, /* Hangul_Pieub ㅂ HANGUL LETTER PIEUP */ + { 0x0eb3, 0x3143 }, /* Hangul_SsangPieub ㅃ HANGUL LETTER SSANGPIEUP */ + { 0x0eb4, 0x3144 }, /* Hangul_PieubSios ㅄ HANGUL LETTER PIEUP-SIOS */ + { 0x0eb5, 0x3145 }, /* Hangul_Sios ㅅ HANGUL LETTER SIOS */ + { 0x0eb6, 0x3146 }, /* Hangul_SsangSios ㅆ HANGUL LETTER SSANGSIOS */ + { 0x0eb7, 0x3147 }, /* Hangul_Ieung ㅇ HANGUL LETTER IEUNG */ + { 0x0eb8, 0x3148 }, /* Hangul_Jieuj ㅈ HANGUL LETTER CIEUC */ + { 0x0eb9, 0x3149 }, /* Hangul_SsangJieuj ㅉ HANGUL LETTER SSANGCIEUC */ + { 0x0eba, 0x314a }, /* Hangul_Cieuc ㅊ HANGUL LETTER CHIEUCH */ + { 0x0ebb, 0x314b }, /* Hangul_Khieuq ㅋ HANGUL LETTER KHIEUKH */ + { 0x0ebc, 0x314c }, /* Hangul_Tieut ㅌ HANGUL LETTER THIEUTH */ + { 0x0ebd, 0x314d }, /* Hangul_Phieuf ㅍ HANGUL LETTER PHIEUPH */ + { 0x0ebe, 0x314e }, /* Hangul_Hieuh ㅎ HANGUL LETTER HIEUH */ + { 0x0ebf, 0x314f }, /* Hangul_A ㅏ HANGUL LETTER A */ + { 0x0ec0, 0x3150 }, /* Hangul_AE ㅐ HANGUL LETTER AE */ + { 0x0ec1, 0x3151 }, /* Hangul_YA ㅑ HANGUL LETTER YA */ + { 0x0ec2, 0x3152 }, /* Hangul_YAE ㅒ HANGUL LETTER YAE */ + { 0x0ec3, 0x3153 }, /* Hangul_EO ㅓ HANGUL LETTER EO */ + { 0x0ec4, 0x3154 }, /* Hangul_E ㅔ HANGUL LETTER E */ + { 0x0ec5, 0x3155 }, /* Hangul_YEO ㅕ HANGUL LETTER YEO */ + { 0x0ec6, 0x3156 }, /* Hangul_YE ㅖ HANGUL LETTER YE */ + { 0x0ec7, 0x3157 }, /* Hangul_O ㅗ HANGUL LETTER O */ + { 0x0ec8, 0x3158 }, /* Hangul_WA ㅘ HANGUL LETTER WA */ + { 0x0ec9, 0x3159 }, /* Hangul_WAE ㅙ HANGUL LETTER WAE */ + { 0x0eca, 0x315a }, /* Hangul_OE ㅚ HANGUL LETTER OE */ + { 0x0ecb, 0x315b }, /* Hangul_YO ㅛ HANGUL LETTER YO */ + { 0x0ecc, 0x315c }, /* Hangul_U ㅜ HANGUL LETTER U */ + { 0x0ecd, 0x315d }, /* Hangul_WEO ㅝ HANGUL LETTER WEO */ + { 0x0ece, 0x315e }, /* Hangul_WE ㅞ HANGUL LETTER WE */ + { 0x0ecf, 0x315f }, /* Hangul_WI ㅟ HANGUL LETTER WI */ + { 0x0ed0, 0x3160 }, /* Hangul_YU ㅠ HANGUL LETTER YU */ + { 0x0ed1, 0x3161 }, /* Hangul_EU ㅡ HANGUL LETTER EU */ + { 0x0ed2, 0x3162 }, /* Hangul_YI ㅢ HANGUL LETTER YI */ + { 0x0ed3, 0x3163 }, /* Hangul_I ㅣ HANGUL LETTER I */ + { 0x0ed4, 0x11a8 }, /* Hangul_J_Kiyeog ᆨ HANGUL JONGSEONG KIYEOK */ + { 0x0ed5, 0x11a9 }, /* Hangul_J_SsangKiyeog ᆩ HANGUL JONGSEONG SSANGKIYEOK */ + { 0x0ed6, 0x11aa }, /* Hangul_J_KiyeogSios ᆪ HANGUL JONGSEONG KIYEOK-SIOS */ + { 0x0ed7, 0x11ab }, /* Hangul_J_Nieun ᆫ HANGUL JONGSEONG NIEUN */ + { 0x0ed8, 0x11ac }, /* Hangul_J_NieunJieuj ᆬ HANGUL JONGSEONG NIEUN-CIEUC */ + { 0x0ed9, 0x11ad }, /* Hangul_J_NieunHieuh ᆭ HANGUL JONGSEONG NIEUN-HIEUH */ + { 0x0eda, 0x11ae }, /* Hangul_J_Dikeud ᆮ HANGUL JONGSEONG TIKEUT */ + { 0x0edb, 0x11af }, /* Hangul_J_Rieul ᆯ HANGUL JONGSEONG RIEUL */ + { 0x0edc, 0x11b0 }, /* Hangul_J_RieulKiyeog ᆰ HANGUL JONGSEONG RIEUL-KIYEOK */ + { 0x0edd, 0x11b1 }, /* Hangul_J_RieulMieum ᆱ HANGUL JONGSEONG RIEUL-MIEUM */ + { 0x0ede, 0x11b2 }, /* Hangul_J_RieulPieub ᆲ HANGUL JONGSEONG RIEUL-PIEUP */ + { 0x0edf, 0x11b3 }, /* Hangul_J_RieulSios ᆳ HANGUL JONGSEONG RIEUL-SIOS */ + { 0x0ee0, 0x11b4 }, /* Hangul_J_RieulTieut ᆴ HANGUL JONGSEONG RIEUL-THIEUTH */ + { 0x0ee1, 0x11b5 }, /* Hangul_J_RieulPhieuf ᆵ HANGUL JONGSEONG RIEUL-PHIEUPH */ + { 0x0ee2, 0x11b6 }, /* Hangul_J_RieulHieuh ᆶ HANGUL JONGSEONG RIEUL-HIEUH */ + { 0x0ee3, 0x11b7 }, /* Hangul_J_Mieum ᆷ HANGUL JONGSEONG MIEUM */ + { 0x0ee4, 0x11b8 }, /* Hangul_J_Pieub ᆸ HANGUL JONGSEONG PIEUP */ + { 0x0ee5, 0x11b9 }, /* Hangul_J_PieubSios ᆹ HANGUL JONGSEONG PIEUP-SIOS */ + { 0x0ee6, 0x11ba }, /* Hangul_J_Sios ᆺ HANGUL JONGSEONG SIOS */ + { 0x0ee7, 0x11bb }, /* Hangul_J_SsangSios ᆻ HANGUL JONGSEONG SSANGSIOS */ + { 0x0ee8, 0x11bc }, /* Hangul_J_Ieung ᆼ HANGUL JONGSEONG IEUNG */ + { 0x0ee9, 0x11bd }, /* Hangul_J_Jieuj ᆽ HANGUL JONGSEONG CIEUC */ + { 0x0eea, 0x11be }, /* Hangul_J_Cieuc ᆾ HANGUL JONGSEONG CHIEUCH */ + { 0x0eeb, 0x11bf }, /* Hangul_J_Khieuq ᆿ HANGUL JONGSEONG KHIEUKH */ + { 0x0eec, 0x11c0 }, /* Hangul_J_Tieut ᇀ HANGUL JONGSEONG THIEUTH */ + { 0x0eed, 0x11c1 }, /* Hangul_J_Phieuf ᇁ HANGUL JONGSEONG PHIEUPH */ + { 0x0eee, 0x11c2 }, /* Hangul_J_Hieuh ᇂ HANGUL JONGSEONG HIEUH */ + { 0x0eef, 0x316d }, /* Hangul_RieulYeorinHieuh ㅭ HANGUL LETTER RIEUL-YEORINHIEUH */ + { 0x0ef0, 0x3171 }, /* Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM */ + { 0x0ef1, 0x3178 }, /* Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP */ + { 0x0ef2, 0x317f }, /* Hangul_PanSios ㅿ HANGUL LETTER PANSIOS */ +/* 0x0ef3 Hangul_KkogjiDalrinIeung ? ??? */ + { 0x0ef4, 0x3184 }, /* Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH */ + { 0x0ef5, 0x3186 }, /* Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH */ + { 0x0ef6, 0x318d }, /* Hangul_AraeA ㆍ HANGUL LETTER ARAEA */ + { 0x0ef7, 0x318e }, /* Hangul_AraeAE ㆎ HANGUL LETTER ARAEAE */ + { 0x0ef8, 0x11eb }, /* Hangul_J_PanSios ᇫ HANGUL JONGSEONG PANSIOS */ +/* 0x0ef9 Hangul_J_KkogjiDalrinIeung ? ??? */ + { 0x0efa, 0x11f9 }, /* Hangul_J_YeorinHieuh ᇹ HANGUL JONGSEONG YEORINHIEUH */ + { 0x0eff, 0x20a9 }, /* Korean_Won ₩ WON SIGN */ + { 0x13bc, 0x0152 }, /* OE Œ LATIN CAPITAL LIGATURE OE */ + { 0x13bd, 0x0153 }, /* oe œ LATIN SMALL LIGATURE OE */ + { 0x13be, 0x0178 }, /* Ydiaeresis Ÿ LATIN CAPITAL LETTER Y WITH DIAERESIS */ + { 0x20a0, 0x20a0 }, /* EcuSign ₠ EURO-CURRENCY SIGN */ + { 0x20a1, 0x20a1 }, /* ColonSign ₡ COLON SIGN */ + { 0x20a2, 0x20a2 }, /* CruzeiroSign ₢ CRUZEIRO SIGN */ + { 0x20a3, 0x20a3 }, /* FFrancSign ₣ FRENCH FRANC SIGN */ + { 0x20a4, 0x20a4 }, /* LiraSign ₤ LIRA SIGN */ + { 0x20a5, 0x20a5 }, /* MillSign ₥ MILL SIGN */ + { 0x20a6, 0x20a6 }, /* NairaSign ₦ NAIRA SIGN */ + { 0x20a7, 0x20a7 }, /* PesetaSign ₧ PESETA SIGN */ + { 0x20a8, 0x20a8 }, /* RupeeSign ₨ RUPEE SIGN */ + { 0x20a9, 0x20a9 }, /* WonSign ₩ WON SIGN */ + { 0x20aa, 0x20aa }, /* NewSheqelSign ₪ NEW SHEQEL SIGN */ + { 0x20ab, 0x20ab }, /* DongSign ₫ DONG SIGN */ + { 0x20ac, 0x20ac }, /* EuroSign € EURO SIGN */ + + + /* Following items added to GTK, not in the xterm table */ + + /* Numeric keypad */ + + { 0xFF80 /* Space */, ' ' }, + { 0xFFAA /* Multiply */, '*' }, + { 0xFFAB /* Add */, '+' }, + { 0xFFAC /* Separator */, ',' }, + { 0xFFAD /* Subtract */, '-' }, + { 0xFFAE /* Decimal */, '.' }, + { 0xFFAF /* Divide */, '/' }, + { 0xFFB0 /* 0 */, '0' }, + { 0xFFB1 /* 1 */, '1' }, + { 0xFFB2 /* 2 */, '2' }, + { 0xFFB3 /* 3 */, '3' }, + { 0xFFB4 /* 4 */, '4' }, + { 0xFFB5 /* 5 */, '5' }, + { 0xFFB6 /* 6 */, '6' }, + { 0xFFB7 /* 7 */, '7' }, + { 0xFFB8 /* 8 */, '8' }, + { 0xFFB9 /* 9 */, '9' }, + { 0xFFBD /* Equal */, '=' }, + + /* End numeric keypad */ +}; + +static const int clutter_keysym_to_unicode_tab_size = + G_N_ELEMENTS (clutter_keysym_to_unicode_tab); + +/** + * clutter_keysym_to_unicode: + * @keyval: a key symbol + * + * Converts @keyval from a Clutter key symbol to the corresponding + * ISO10646 (Unicode) character. + * + * Return value: a Unicode character, or 0 if there is no corresponding + * character. + */ +guint32 +clutter_keysym_to_unicode (guint keyval) +{ + int min = 0; + int max = clutter_keysym_to_unicode_tab_size - 1; + int mid; + + /* First check for Latin-1 characters (1:1 mapping) */ + if ((keyval >= 0x0020 && keyval <= 0x007e) || + (keyval >= 0x00a0 && keyval <= 0x00ff)) + return keyval; + + /* Also check for directly encoded 24-bit UCS characters: */ + if ((keyval & 0xff000000) == 0x01000000) + return keyval & 0x00ffffff; + + /* binary search in table */ + while (max >= min) + { + mid = (min + max) / 2; + + if (clutter_keysym_to_unicode_tab[mid].keysym < keyval) + min = mid + 1; + else if (clutter_keysym_to_unicode_tab[mid].keysym > keyval) + max = mid - 1; + else + { + /* found it */ + return clutter_keysym_to_unicode_tab[mid].ucs; + } + } + + /* No matching Unicode value found */ + return 0; +} + +static const struct { + unsigned short keysym; + unsigned short ucs; +} clutter_unicode_to_keysym_tab[] = { + { 0x0abd, 0x002e }, /* decimalpoint . FULL STOP */ + { 0x0ba3, 0x003c }, /* leftcaret < LESS-THAN SIGN */ + { 0x0ba6, 0x003e }, /* rightcaret > GREATER-THAN SIGN */ + { 0x0bc6, 0x005f }, /* underbar _ LOW LINE */ + { 0x0bc0, 0x00af }, /* overbar ¯ MACRON */ + { 0x03c0, 0x0100 }, /* Amacron Ā LATIN CAPITAL LETTER A WITH MACRON */ + { 0x03e0, 0x0101 }, /* amacron ā LATIN SMALL LETTER A WITH MACRON */ + { 0x01c3, 0x0102 }, /* Abreve Ă LATIN CAPITAL LETTER A WITH BREVE */ + { 0x01e3, 0x0103 }, /* abreve ă LATIN SMALL LETTER A WITH BREVE */ + { 0x01a1, 0x0104 }, /* Aogonek Ą LATIN CAPITAL LETTER A WITH OGONEK */ + { 0x01b1, 0x0105 }, /* aogonek ą LATIN SMALL LETTER A WITH OGONEK */ + { 0x01c6, 0x0106 }, /* Cacute Ć LATIN CAPITAL LETTER C WITH ACUTE */ + { 0x01e6, 0x0107 }, /* cacute ć LATIN SMALL LETTER C WITH ACUTE */ + { 0x02c6, 0x0108 }, /* Ccircumflex Ĉ LATIN CAPITAL LETTER C WITH CIRCUMFLEX */ + { 0x02e6, 0x0109 }, /* ccircumflex ĉ LATIN SMALL LETTER C WITH CIRCUMFLEX */ + { 0x02c5, 0x010a }, /* Cabovedot Ċ LATIN CAPITAL LETTER C WITH DOT ABOVE */ + { 0x02e5, 0x010b }, /* cabovedot ċ LATIN SMALL LETTER C WITH DOT ABOVE */ + { 0x01c8, 0x010c }, /* Ccaron Č LATIN CAPITAL LETTER C WITH CARON */ + { 0x01e8, 0x010d }, /* ccaron č LATIN SMALL LETTER C WITH CARON */ + { 0x01cf, 0x010e }, /* Dcaron Ď LATIN CAPITAL LETTER D WITH CARON */ + { 0x01ef, 0x010f }, /* dcaron ď LATIN SMALL LETTER D WITH CARON */ + { 0x01d0, 0x0110 }, /* Dstroke Đ LATIN CAPITAL LETTER D WITH STROKE */ + { 0x01f0, 0x0111 }, /* dstroke đ LATIN SMALL LETTER D WITH STROKE */ + { 0x03aa, 0x0112 }, /* Emacron Ē LATIN CAPITAL LETTER E WITH MACRON */ + { 0x03ba, 0x0113 }, /* emacron ē LATIN SMALL LETTER E WITH MACRON */ + { 0x03cc, 0x0116 }, /* Eabovedot Ė LATIN CAPITAL LETTER E WITH DOT ABOVE */ + { 0x03ec, 0x0117 }, /* eabovedot ė LATIN SMALL LETTER E WITH DOT ABOVE */ + { 0x01ca, 0x0118 }, /* Eogonek Ę LATIN CAPITAL LETTER E WITH OGONEK */ + { 0x01ea, 0x0119 }, /* eogonek ę LATIN SMALL LETTER E WITH OGONEK */ + { 0x01cc, 0x011a }, /* Ecaron Ě LATIN CAPITAL LETTER E WITH CARON */ + { 0x01ec, 0x011b }, /* ecaron ě LATIN SMALL LETTER E WITH CARON */ + { 0x02d8, 0x011c }, /* Gcircumflex Ĝ LATIN CAPITAL LETTER G WITH CIRCUMFLEX */ + { 0x02f8, 0x011d }, /* gcircumflex ĝ LATIN SMALL LETTER G WITH CIRCUMFLEX */ + { 0x02ab, 0x011e }, /* Gbreve Ğ LATIN CAPITAL LETTER G WITH BREVE */ + { 0x02bb, 0x011f }, /* gbreve ğ LATIN SMALL LETTER G WITH BREVE */ + { 0x02d5, 0x0120 }, /* Gabovedot Ġ LATIN CAPITAL LETTER G WITH DOT ABOVE */ + { 0x02f5, 0x0121 }, /* gabovedot ġ LATIN SMALL LETTER G WITH DOT ABOVE */ + { 0x03ab, 0x0122 }, /* Gcedilla Ģ LATIN CAPITAL LETTER G WITH CEDILLA */ + { 0x03bb, 0x0123 }, /* gcedilla ģ LATIN SMALL LETTER G WITH CEDILLA */ + { 0x02a6, 0x0124 }, /* Hcircumflex Ĥ LATIN CAPITAL LETTER H WITH CIRCUMFLEX */ + { 0x02b6, 0x0125 }, /* hcircumflex ĥ LATIN SMALL LETTER H WITH CIRCUMFLEX */ + { 0x02a1, 0x0126 }, /* Hstroke Ħ LATIN CAPITAL LETTER H WITH STROKE */ + { 0x02b1, 0x0127 }, /* hstroke ħ LATIN SMALL LETTER H WITH STROKE */ + { 0x03a5, 0x0128 }, /* Itilde Ĩ LATIN CAPITAL LETTER I WITH TILDE */ + { 0x03b5, 0x0129 }, /* itilde ĩ LATIN SMALL LETTER I WITH TILDE */ + { 0x03cf, 0x012a }, /* Imacron Ī LATIN CAPITAL LETTER I WITH MACRON */ + { 0x03ef, 0x012b }, /* imacron ī LATIN SMALL LETTER I WITH MACRON */ + { 0x03c7, 0x012e }, /* Iogonek Į LATIN CAPITAL LETTER I WITH OGONEK */ + { 0x03e7, 0x012f }, /* iogonek į LATIN SMALL LETTER I WITH OGONEK */ + { 0x02a9, 0x0130 }, /* Iabovedot İ LATIN CAPITAL LETTER I WITH DOT ABOVE */ + { 0x02b9, 0x0131 }, /* idotless ı LATIN SMALL LETTER DOTLESS I */ + { 0x02ac, 0x0134 }, /* Jcircumflex Ĵ LATIN CAPITAL LETTER J WITH CIRCUMFLEX */ + { 0x02bc, 0x0135 }, /* jcircumflex ĵ LATIN SMALL LETTER J WITH CIRCUMFLEX */ + { 0x03d3, 0x0136 }, /* Kcedilla Ķ LATIN CAPITAL LETTER K WITH CEDILLA */ + { 0x03f3, 0x0137 }, /* kcedilla ķ LATIN SMALL LETTER K WITH CEDILLA */ + { 0x03a2, 0x0138 }, /* kra ĸ LATIN SMALL LETTER KRA */ + { 0x01c5, 0x0139 }, /* Lacute Ĺ LATIN CAPITAL LETTER L WITH ACUTE */ + { 0x01e5, 0x013a }, /* lacute ĺ LATIN SMALL LETTER L WITH ACUTE */ + { 0x03a6, 0x013b }, /* Lcedilla Ļ LATIN CAPITAL LETTER L WITH CEDILLA */ + { 0x03b6, 0x013c }, /* lcedilla ļ LATIN SMALL LETTER L WITH CEDILLA */ + { 0x01a5, 0x013d }, /* Lcaron Ľ LATIN CAPITAL LETTER L WITH CARON */ + { 0x01b5, 0x013e }, /* lcaron ľ LATIN SMALL LETTER L WITH CARON */ + { 0x01a3, 0x0141 }, /* Lstroke Ł LATIN CAPITAL LETTER L WITH STROKE */ + { 0x01b3, 0x0142 }, /* lstroke ł LATIN SMALL LETTER L WITH STROKE */ + { 0x01d1, 0x0143 }, /* Nacute Ń LATIN CAPITAL LETTER N WITH ACUTE */ + { 0x01f1, 0x0144 }, /* nacute ń LATIN SMALL LETTER N WITH ACUTE */ + { 0x03d1, 0x0145 }, /* Ncedilla Ņ LATIN CAPITAL LETTER N WITH CEDILLA */ + { 0x03f1, 0x0146 }, /* ncedilla ņ LATIN SMALL LETTER N WITH CEDILLA */ + { 0x01d2, 0x0147 }, /* Ncaron Ň LATIN CAPITAL LETTER N WITH CARON */ + { 0x01f2, 0x0148 }, /* ncaron ň LATIN SMALL LETTER N WITH CARON */ + { 0x03bd, 0x014a }, /* ENG Ŋ LATIN CAPITAL LETTER ENG */ + { 0x03bf, 0x014b }, /* eng ŋ LATIN SMALL LETTER ENG */ + { 0x03d2, 0x014c }, /* Omacron Ō LATIN CAPITAL LETTER O WITH MACRON */ + { 0x03f2, 0x014d }, /* omacron ō LATIN SMALL LETTER O WITH MACRON */ + { 0x01d5, 0x0150 }, /* Odoubleacute Ő LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */ + { 0x01f5, 0x0151 }, /* odoubleacute ő LATIN SMALL LETTER O WITH DOUBLE ACUTE */ + { 0x13bc, 0x0152 }, /* OE Œ LATIN CAPITAL LIGATURE OE */ + { 0x13bd, 0x0153 }, /* oe œ LATIN SMALL LIGATURE OE */ + { 0x01c0, 0x0154 }, /* Racute Ŕ LATIN CAPITAL LETTER R WITH ACUTE */ + { 0x01e0, 0x0155 }, /* racute ŕ LATIN SMALL LETTER R WITH ACUTE */ + { 0x03a3, 0x0156 }, /* Rcedilla Ŗ LATIN CAPITAL LETTER R WITH CEDILLA */ + { 0x03b3, 0x0157 }, /* rcedilla ŗ LATIN SMALL LETTER R WITH CEDILLA */ + { 0x01d8, 0x0158 }, /* Rcaron Ř LATIN CAPITAL LETTER R WITH CARON */ + { 0x01f8, 0x0159 }, /* rcaron ř LATIN SMALL LETTER R WITH CARON */ + { 0x01a6, 0x015a }, /* Sacute Ś LATIN CAPITAL LETTER S WITH ACUTE */ + { 0x01b6, 0x015b }, /* sacute ś LATIN SMALL LETTER S WITH ACUTE */ + { 0x02de, 0x015c }, /* Scircumflex Ŝ LATIN CAPITAL LETTER S WITH CIRCUMFLEX */ + { 0x02fe, 0x015d }, /* scircumflex ŝ LATIN SMALL LETTER S WITH CIRCUMFLEX */ + { 0x01aa, 0x015e }, /* Scedilla Ş LATIN CAPITAL LETTER S WITH CEDILLA */ + { 0x01ba, 0x015f }, /* scedilla ş LATIN SMALL LETTER S WITH CEDILLA */ + { 0x01a9, 0x0160 }, /* Scaron Š LATIN CAPITAL LETTER S WITH CARON */ + { 0x01b9, 0x0161 }, /* scaron š LATIN SMALL LETTER S WITH CARON */ + { 0x01de, 0x0162 }, /* Tcedilla Ţ LATIN CAPITAL LETTER T WITH CEDILLA */ + { 0x01fe, 0x0163 }, /* tcedilla ţ LATIN SMALL LETTER T WITH CEDILLA */ + { 0x01ab, 0x0164 }, /* Tcaron Ť LATIN CAPITAL LETTER T WITH CARON */ + { 0x01bb, 0x0165 }, /* tcaron ť LATIN SMALL LETTER T WITH CARON */ + { 0x03ac, 0x0166 }, /* Tslash Ŧ LATIN CAPITAL LETTER T WITH STROKE */ + { 0x03bc, 0x0167 }, /* tslash ŧ LATIN SMALL LETTER T WITH STROKE */ + { 0x03dd, 0x0168 }, /* Utilde Ũ LATIN CAPITAL LETTER U WITH TILDE */ + { 0x03fd, 0x0169 }, /* utilde ũ LATIN SMALL LETTER U WITH TILDE */ + { 0x03de, 0x016a }, /* Umacron Ū LATIN CAPITAL LETTER U WITH MACRON */ + { 0x03fe, 0x016b }, /* umacron ū LATIN SMALL LETTER U WITH MACRON */ + { 0x02dd, 0x016c }, /* Ubreve Ŭ LATIN CAPITAL LETTER U WITH BREVE */ + { 0x02fd, 0x016d }, /* ubreve ŭ LATIN SMALL LETTER U WITH BREVE */ + { 0x01d9, 0x016e }, /* Uring Ů LATIN CAPITAL LETTER U WITH RING ABOVE */ + { 0x01f9, 0x016f }, /* uring ů LATIN SMALL LETTER U WITH RING ABOVE */ + { 0x01db, 0x0170 }, /* Udoubleacute Ű LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */ + { 0x01fb, 0x0171 }, /* udoubleacute ű LATIN SMALL LETTER U WITH DOUBLE ACUTE */ + { 0x03d9, 0x0172 }, /* Uogonek Ų LATIN CAPITAL LETTER U WITH OGONEK */ + { 0x03f9, 0x0173 }, /* uogonek ų LATIN SMALL LETTER U WITH OGONEK */ + { 0x13be, 0x0178 }, /* Ydiaeresis Ÿ LATIN CAPITAL LETTER Y WITH DIAERESIS */ + { 0x01ac, 0x0179 }, /* Zacute Ź LATIN CAPITAL LETTER Z WITH ACUTE */ + { 0x01bc, 0x017a }, /* zacute ź LATIN SMALL LETTER Z WITH ACUTE */ + { 0x01af, 0x017b }, /* Zabovedot Ż LATIN CAPITAL LETTER Z WITH DOT ABOVE */ + { 0x01bf, 0x017c }, /* zabovedot ż LATIN SMALL LETTER Z WITH DOT ABOVE */ + { 0x01ae, 0x017d }, /* Zcaron Ž LATIN CAPITAL LETTER Z WITH CARON */ + { 0x01be, 0x017e }, /* zcaron ž LATIN SMALL LETTER Z WITH CARON */ + { 0x08f6, 0x0192 }, /* function ƒ LATIN SMALL LETTER F WITH HOOK */ + { 0x01b7, 0x02c7 }, /* caron ˇ CARON */ + { 0x01a2, 0x02d8 }, /* breve ˘ BREVE */ + { 0x01ff, 0x02d9 }, /* abovedot ˙ DOT ABOVE */ + { 0x01b2, 0x02db }, /* ogonek ˛ OGONEK */ + { 0x01bd, 0x02dd }, /* doubleacute ˝ DOUBLE ACUTE ACCENT */ + { 0x07ae, 0x0385 }, /* Greek_accentdieresis ΅ GREEK DIALYTIKA TONOS */ + { 0x07a1, 0x0386 }, /* Greek_ALPHAaccent Ά GREEK CAPITAL LETTER ALPHA WITH TONOS */ + { 0x07a2, 0x0388 }, /* Greek_EPSILONaccent Έ GREEK CAPITAL LETTER EPSILON WITH TONOS */ + { 0x07a3, 0x0389 }, /* Greek_ETAaccent Ή GREEK CAPITAL LETTER ETA WITH TONOS */ + { 0x07a4, 0x038a }, /* Greek_IOTAaccent Ί GREEK CAPITAL LETTER IOTA WITH TONOS */ + { 0x07a7, 0x038c }, /* Greek_OMICRONaccent Ό GREEK CAPITAL LETTER OMICRON WITH TONOS */ + { 0x07a8, 0x038e }, /* Greek_UPSILONaccent Ύ GREEK CAPITAL LETTER UPSILON WITH TONOS */ + { 0x07ab, 0x038f }, /* Greek_OMEGAaccent Ώ GREEK CAPITAL LETTER OMEGA WITH TONOS */ + { 0x07b6, 0x0390 }, /* Greek_iotaaccentdieresis ΐ GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */ + { 0x07c1, 0x0391 }, /* Greek_ALPHA Α GREEK CAPITAL LETTER ALPHA */ + { 0x07c2, 0x0392 }, /* Greek_BETA Β GREEK CAPITAL LETTER BETA */ + { 0x07c3, 0x0393 }, /* Greek_GAMMA Γ GREEK CAPITAL LETTER GAMMA */ + { 0x07c4, 0x0394 }, /* Greek_DELTA Δ GREEK CAPITAL LETTER DELTA */ + { 0x07c5, 0x0395 }, /* Greek_EPSILON Ε GREEK CAPITAL LETTER EPSILON */ + { 0x07c6, 0x0396 }, /* Greek_ZETA Ζ GREEK CAPITAL LETTER ZETA */ + { 0x07c7, 0x0397 }, /* Greek_ETA Η GREEK CAPITAL LETTER ETA */ + { 0x07c8, 0x0398 }, /* Greek_THETA Θ GREEK CAPITAL LETTER THETA */ + { 0x07c9, 0x0399 }, /* Greek_IOTA Ι GREEK CAPITAL LETTER IOTA */ + { 0x07ca, 0x039a }, /* Greek_KAPPA Κ GREEK CAPITAL LETTER KAPPA */ + { 0x07cb, 0x039b }, /* Greek_LAMBDA Λ GREEK CAPITAL LETTER LAMDA */ + { 0x07cc, 0x039c }, /* Greek_MU Μ GREEK CAPITAL LETTER MU */ + { 0x07cd, 0x039d }, /* Greek_NU Ν GREEK CAPITAL LETTER NU */ + { 0x07ce, 0x039e }, /* Greek_XI Ξ GREEK CAPITAL LETTER XI */ + { 0x07cf, 0x039f }, /* Greek_OMICRON Ο GREEK CAPITAL LETTER OMICRON */ + { 0x07d0, 0x03a0 }, /* Greek_PI Π GREEK CAPITAL LETTER PI */ + { 0x07d1, 0x03a1 }, /* Greek_RHO Ρ GREEK CAPITAL LETTER RHO */ + { 0x07d2, 0x03a3 }, /* Greek_SIGMA Σ GREEK CAPITAL LETTER SIGMA */ + { 0x07d4, 0x03a4 }, /* Greek_TAU Τ GREEK CAPITAL LETTER TAU */ + { 0x07d5, 0x03a5 }, /* Greek_UPSILON Υ GREEK CAPITAL LETTER UPSILON */ + { 0x07d6, 0x03a6 }, /* Greek_PHI Φ GREEK CAPITAL LETTER PHI */ + { 0x07d7, 0x03a7 }, /* Greek_CHI Χ GREEK CAPITAL LETTER CHI */ + { 0x07d8, 0x03a8 }, /* Greek_PSI Ψ GREEK CAPITAL LETTER PSI */ + { 0x07d9, 0x03a9 }, /* Greek_OMEGA Ω GREEK CAPITAL LETTER OMEGA */ + { 0x07a5, 0x03aa }, /* Greek_IOTAdieresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */ + { 0x07a9, 0x03ab }, /* Greek_UPSILONdieresis Ϋ GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */ + { 0x07b1, 0x03ac }, /* Greek_alphaaccent ά GREEK SMALL LETTER ALPHA WITH TONOS */ + { 0x07b2, 0x03ad }, /* Greek_epsilonaccent έ GREEK SMALL LETTER EPSILON WITH TONOS */ + { 0x07b3, 0x03ae }, /* Greek_etaaccent ή GREEK SMALL LETTER ETA WITH TONOS */ + { 0x07b4, 0x03af }, /* Greek_iotaaccent ί GREEK SMALL LETTER IOTA WITH TONOS */ + { 0x07ba, 0x03b0 }, /* Greek_upsilonaccentdieresis ΰ GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */ + { 0x07e1, 0x03b1 }, /* Greek_alpha α GREEK SMALL LETTER ALPHA */ + { 0x07e2, 0x03b2 }, /* Greek_beta β GREEK SMALL LETTER BETA */ + { 0x07e3, 0x03b3 }, /* Greek_gamma γ GREEK SMALL LETTER GAMMA */ + { 0x07e4, 0x03b4 }, /* Greek_delta δ GREEK SMALL LETTER DELTA */ + { 0x07e5, 0x03b5 }, /* Greek_epsilon ε GREEK SMALL LETTER EPSILON */ + { 0x07e6, 0x03b6 }, /* Greek_zeta ζ GREEK SMALL LETTER ZETA */ + { 0x07e7, 0x03b7 }, /* Greek_eta η GREEK SMALL LETTER ETA */ + { 0x07e8, 0x03b8 }, /* Greek_theta θ GREEK SMALL LETTER THETA */ + { 0x07e9, 0x03b9 }, /* Greek_iota ι GREEK SMALL LETTER IOTA */ + { 0x07ea, 0x03ba }, /* Greek_kappa κ GREEK SMALL LETTER KAPPA */ + { 0x07eb, 0x03bb }, /* Greek_lambda λ GREEK SMALL LETTER LAMDA */ + { 0x07ec, 0x03bc }, /* Greek_mu μ GREEK SMALL LETTER MU */ + { 0x07ed, 0x03bd }, /* Greek_nu ν GREEK SMALL LETTER NU */ + { 0x07ee, 0x03be }, /* Greek_xi ξ GREEK SMALL LETTER XI */ + { 0x07ef, 0x03bf }, /* Greek_omicron ο GREEK SMALL LETTER OMICRON */ + { 0x07f0, 0x03c0 }, /* Greek_pi π GREEK SMALL LETTER PI */ + { 0x07f1, 0x03c1 }, /* Greek_rho ρ GREEK SMALL LETTER RHO */ + { 0x07f3, 0x03c2 }, /* Greek_finalsmallsigma ς GREEK SMALL LETTER FINAL SIGMA */ + { 0x07f2, 0x03c3 }, /* Greek_sigma σ GREEK SMALL LETTER SIGMA */ + { 0x07f4, 0x03c4 }, /* Greek_tau τ GREEK SMALL LETTER TAU */ + { 0x07f5, 0x03c5 }, /* Greek_upsilon υ GREEK SMALL LETTER UPSILON */ + { 0x07f6, 0x03c6 }, /* Greek_phi φ GREEK SMALL LETTER PHI */ + { 0x07f7, 0x03c7 }, /* Greek_chi χ GREEK SMALL LETTER CHI */ + { 0x07f8, 0x03c8 }, /* Greek_psi ψ GREEK SMALL LETTER PSI */ + { 0x07f9, 0x03c9 }, /* Greek_omega ω GREEK SMALL LETTER OMEGA */ + { 0x07b5, 0x03ca }, /* Greek_iotadieresis ϊ GREEK SMALL LETTER IOTA WITH DIALYTIKA */ + { 0x07b9, 0x03cb }, /* Greek_upsilondieresis ϋ GREEK SMALL LETTER UPSILON WITH DIALYTIKA */ + { 0x07b7, 0x03cc }, /* Greek_omicronaccent ό GREEK SMALL LETTER OMICRON WITH TONOS */ + { 0x07b8, 0x03cd }, /* Greek_upsilonaccent ύ GREEK SMALL LETTER UPSILON WITH TONOS */ + { 0x07bb, 0x03ce }, /* Greek_omegaaccent ώ GREEK SMALL LETTER OMEGA WITH TONOS */ + { 0x06b3, 0x0401 }, /* Cyrillic_IO Ё CYRILLIC CAPITAL LETTER IO */ + { 0x06b1, 0x0402 }, /* Serbian_DJE Ђ CYRILLIC CAPITAL LETTER DJE */ + { 0x06b2, 0x0403 }, /* Macedonia_GJE Ѓ CYRILLIC CAPITAL LETTER GJE */ + { 0x06b4, 0x0404 }, /* Ukrainian_IE Є CYRILLIC CAPITAL LETTER UKRAINIAN IE */ + { 0x06b5, 0x0405 }, /* Macedonia_DSE Ѕ CYRILLIC CAPITAL LETTER DZE */ + { 0x06b6, 0x0406 }, /* Ukrainian_I І CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */ + { 0x06b7, 0x0407 }, /* Ukrainian_YI Ї CYRILLIC CAPITAL LETTER YI */ + { 0x06b8, 0x0408 }, /* Cyrillic_JE Ј CYRILLIC CAPITAL LETTER JE */ + { 0x06b9, 0x0409 }, /* Cyrillic_LJE Љ CYRILLIC CAPITAL LETTER LJE */ + { 0x06ba, 0x040a }, /* Cyrillic_NJE Њ CYRILLIC CAPITAL LETTER NJE */ + { 0x06bb, 0x040b }, /* Serbian_TSHE Ћ CYRILLIC CAPITAL LETTER TSHE */ + { 0x06bc, 0x040c }, /* Macedonia_KJE Ќ CYRILLIC CAPITAL LETTER KJE */ + { 0x06be, 0x040e }, /* Byelorussian_SHORTU Ў CYRILLIC CAPITAL LETTER SHORT U */ + { 0x06bf, 0x040f }, /* Cyrillic_DZHE Џ CYRILLIC CAPITAL LETTER DZHE */ + { 0x06e1, 0x0410 }, /* Cyrillic_A А CYRILLIC CAPITAL LETTER A */ + { 0x06e2, 0x0411 }, /* Cyrillic_BE Б CYRILLIC CAPITAL LETTER BE */ + { 0x06f7, 0x0412 }, /* Cyrillic_VE В CYRILLIC CAPITAL LETTER VE */ + { 0x06e7, 0x0413 }, /* Cyrillic_GHE Г CYRILLIC CAPITAL LETTER GHE */ + { 0x06e4, 0x0414 }, /* Cyrillic_DE Д CYRILLIC CAPITAL LETTER DE */ + { 0x06e5, 0x0415 }, /* Cyrillic_IE Е CYRILLIC CAPITAL LETTER IE */ + { 0x06f6, 0x0416 }, /* Cyrillic_ZHE Ж CYRILLIC CAPITAL LETTER ZHE */ + { 0x06fa, 0x0417 }, /* Cyrillic_ZE З CYRILLIC CAPITAL LETTER ZE */ + { 0x06e9, 0x0418 }, /* Cyrillic_I И CYRILLIC CAPITAL LETTER I */ + { 0x06ea, 0x0419 }, /* Cyrillic_SHORTI Й CYRILLIC CAPITAL LETTER SHORT I */ + { 0x06eb, 0x041a }, /* Cyrillic_KA К CYRILLIC CAPITAL LETTER KA */ + { 0x06ec, 0x041b }, /* Cyrillic_EL Л CYRILLIC CAPITAL LETTER EL */ + { 0x06ed, 0x041c }, /* Cyrillic_EM М CYRILLIC CAPITAL LETTER EM */ + { 0x06ee, 0x041d }, /* Cyrillic_EN Н CYRILLIC CAPITAL LETTER EN */ + { 0x06ef, 0x041e }, /* Cyrillic_O О CYRILLIC CAPITAL LETTER O */ + { 0x06f0, 0x041f }, /* Cyrillic_PE П CYRILLIC CAPITAL LETTER PE */ + { 0x06f2, 0x0420 }, /* Cyrillic_ER Р CYRILLIC CAPITAL LETTER ER */ + { 0x06f3, 0x0421 }, /* Cyrillic_ES С CYRILLIC CAPITAL LETTER ES */ + { 0x06f4, 0x0422 }, /* Cyrillic_TE Т CYRILLIC CAPITAL LETTER TE */ + { 0x06f5, 0x0423 }, /* Cyrillic_U У CYRILLIC CAPITAL LETTER U */ + { 0x06e6, 0x0424 }, /* Cyrillic_EF Ф CYRILLIC CAPITAL LETTER EF */ + { 0x06e8, 0x0425 }, /* Cyrillic_HA Х CYRILLIC CAPITAL LETTER HA */ + { 0x06e3, 0x0426 }, /* Cyrillic_TSE Ц CYRILLIC CAPITAL LETTER TSE */ + { 0x06fe, 0x0427 }, /* Cyrillic_CHE Ч CYRILLIC CAPITAL LETTER CHE */ + { 0x06fb, 0x0428 }, /* Cyrillic_SHA Ш CYRILLIC CAPITAL LETTER SHA */ + { 0x06fd, 0x0429 }, /* Cyrillic_SHCHA Щ CYRILLIC CAPITAL LETTER SHCHA */ + { 0x06ff, 0x042a }, /* Cyrillic_HARDSIGN Ъ CYRILLIC CAPITAL LETTER HARD SIGN */ + { 0x06f9, 0x042b }, /* Cyrillic_YERU Ы CYRILLIC CAPITAL LETTER YERU */ + { 0x06f8, 0x042c }, /* Cyrillic_SOFTSIGN Ь CYRILLIC CAPITAL LETTER SOFT SIGN */ + { 0x06fc, 0x042d }, /* Cyrillic_E Э CYRILLIC CAPITAL LETTER E */ + { 0x06e0, 0x042e }, /* Cyrillic_YU Ю CYRILLIC CAPITAL LETTER YU */ + { 0x06f1, 0x042f }, /* Cyrillic_YA Я CYRILLIC CAPITAL LETTER YA */ + { 0x06c1, 0x0430 }, /* Cyrillic_a а CYRILLIC SMALL LETTER A */ + { 0x06c2, 0x0431 }, /* Cyrillic_be б CYRILLIC SMALL LETTER BE */ + { 0x06d7, 0x0432 }, /* Cyrillic_ve в CYRILLIC SMALL LETTER VE */ + { 0x06c7, 0x0433 }, /* Cyrillic_ghe г CYRILLIC SMALL LETTER GHE */ + { 0x06c4, 0x0434 }, /* Cyrillic_de д CYRILLIC SMALL LETTER DE */ + { 0x06c5, 0x0435 }, /* Cyrillic_ie е CYRILLIC SMALL LETTER IE */ + { 0x06d6, 0x0436 }, /* Cyrillic_zhe ж CYRILLIC SMALL LETTER ZHE */ + { 0x06da, 0x0437 }, /* Cyrillic_ze з CYRILLIC SMALL LETTER ZE */ + { 0x06c9, 0x0438 }, /* Cyrillic_i и CYRILLIC SMALL LETTER I */ + { 0x06ca, 0x0439 }, /* Cyrillic_shorti й CYRILLIC SMALL LETTER SHORT I */ + { 0x06cb, 0x043a }, /* Cyrillic_ka к CYRILLIC SMALL LETTER KA */ + { 0x06cc, 0x043b }, /* Cyrillic_el л CYRILLIC SMALL LETTER EL */ + { 0x06cd, 0x043c }, /* Cyrillic_em м CYRILLIC SMALL LETTER EM */ + { 0x06ce, 0x043d }, /* Cyrillic_en н CYRILLIC SMALL LETTER EN */ + { 0x06cf, 0x043e }, /* Cyrillic_o о CYRILLIC SMALL LETTER O */ + { 0x06d0, 0x043f }, /* Cyrillic_pe п CYRILLIC SMALL LETTER PE */ + { 0x06d2, 0x0440 }, /* Cyrillic_er р CYRILLIC SMALL LETTER ER */ + { 0x06d3, 0x0441 }, /* Cyrillic_es с CYRILLIC SMALL LETTER ES */ + { 0x06d4, 0x0442 }, /* Cyrillic_te т CYRILLIC SMALL LETTER TE */ + { 0x06d5, 0x0443 }, /* Cyrillic_u у CYRILLIC SMALL LETTER U */ + { 0x06c6, 0x0444 }, /* Cyrillic_ef ф CYRILLIC SMALL LETTER EF */ + { 0x06c8, 0x0445 }, /* Cyrillic_ha х CYRILLIC SMALL LETTER HA */ + { 0x06c3, 0x0446 }, /* Cyrillic_tse ц CYRILLIC SMALL LETTER TSE */ + { 0x06de, 0x0447 }, /* Cyrillic_che ч CYRILLIC SMALL LETTER CHE */ + { 0x06db, 0x0448 }, /* Cyrillic_sha ш CYRILLIC SMALL LETTER SHA */ + { 0x06dd, 0x0449 }, /* Cyrillic_shcha щ CYRILLIC SMALL LETTER SHCHA */ + { 0x06df, 0x044a }, /* Cyrillic_hardsign ъ CYRILLIC SMALL LETTER HARD SIGN */ + { 0x06d9, 0x044b }, /* Cyrillic_yeru ы CYRILLIC SMALL LETTER YERU */ + { 0x06d8, 0x044c }, /* Cyrillic_softsign ь CYRILLIC SMALL LETTER SOFT SIGN */ + { 0x06dc, 0x044d }, /* Cyrillic_e э CYRILLIC SMALL LETTER E */ + { 0x06c0, 0x044e }, /* Cyrillic_yu ю CYRILLIC SMALL LETTER YU */ + { 0x06d1, 0x044f }, /* Cyrillic_ya я CYRILLIC SMALL LETTER YA */ + { 0x06a3, 0x0451 }, /* Cyrillic_io ё CYRILLIC SMALL LETTER IO */ + { 0x06a1, 0x0452 }, /* Serbian_dje ђ CYRILLIC SMALL LETTER DJE */ + { 0x06a2, 0x0453 }, /* Macedonia_gje ѓ CYRILLIC SMALL LETTER GJE */ + { 0x06a4, 0x0454 }, /* Ukrainian_ie є CYRILLIC SMALL LETTER UKRAINIAN IE */ + { 0x06a5, 0x0455 }, /* Macedonia_dse ѕ CYRILLIC SMALL LETTER DZE */ + { 0x06a6, 0x0456 }, /* Ukrainian_i і CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */ + { 0x06a7, 0x0457 }, /* Ukrainian_yi ї CYRILLIC SMALL LETTER YI */ + { 0x06a8, 0x0458 }, /* Cyrillic_je ј CYRILLIC SMALL LETTER JE */ + { 0x06a9, 0x0459 }, /* Cyrillic_lje љ CYRILLIC SMALL LETTER LJE */ + { 0x06aa, 0x045a }, /* Cyrillic_nje њ CYRILLIC SMALL LETTER NJE */ + { 0x06ab, 0x045b }, /* Serbian_tshe ћ CYRILLIC SMALL LETTER TSHE */ + { 0x06ac, 0x045c }, /* Macedonia_kje ќ CYRILLIC SMALL LETTER KJE */ + { 0x06ae, 0x045e }, /* Byelorussian_shortu ў CYRILLIC SMALL LETTER SHORT U */ + { 0x06af, 0x045f }, /* Cyrillic_dzhe џ CYRILLIC SMALL LETTER DZHE */ + { 0x0ce0, 0x05d0 }, /* hebrew_aleph א HEBREW LETTER ALEF */ + { 0x0ce1, 0x05d1 }, /* hebrew_bet ב HEBREW LETTER BET */ + { 0x0ce2, 0x05d2 }, /* hebrew_gimel ג HEBREW LETTER GIMEL */ + { 0x0ce3, 0x05d3 }, /* hebrew_dalet ד HEBREW LETTER DALET */ + { 0x0ce4, 0x05d4 }, /* hebrew_he ה HEBREW LETTER HE */ + { 0x0ce5, 0x05d5 }, /* hebrew_waw ו HEBREW LETTER VAV */ + { 0x0ce6, 0x05d6 }, /* hebrew_zain ז HEBREW LETTER ZAYIN */ + { 0x0ce7, 0x05d7 }, /* hebrew_chet ח HEBREW LETTER HET */ + { 0x0ce8, 0x05d8 }, /* hebrew_tet ט HEBREW LETTER TET */ + { 0x0ce9, 0x05d9 }, /* hebrew_yod י HEBREW LETTER YOD */ + { 0x0cea, 0x05da }, /* hebrew_finalkaph ך HEBREW LETTER FINAL KAF */ + { 0x0ceb, 0x05db }, /* hebrew_kaph כ HEBREW LETTER KAF */ + { 0x0cec, 0x05dc }, /* hebrew_lamed ל HEBREW LETTER LAMED */ + { 0x0ced, 0x05dd }, /* hebrew_finalmem ם HEBREW LETTER FINAL MEM */ + { 0x0cee, 0x05de }, /* hebrew_mem מ HEBREW LETTER MEM */ + { 0x0cef, 0x05df }, /* hebrew_finalnun ן HEBREW LETTER FINAL NUN */ + { 0x0cf0, 0x05e0 }, /* hebrew_nun נ HEBREW LETTER NUN */ + { 0x0cf1, 0x05e1 }, /* hebrew_samech ס HEBREW LETTER SAMEKH */ + { 0x0cf2, 0x05e2 }, /* hebrew_ayin ע HEBREW LETTER AYIN */ + { 0x0cf3, 0x05e3 }, /* hebrew_finalpe ף HEBREW LETTER FINAL PE */ + { 0x0cf4, 0x05e4 }, /* hebrew_pe פ HEBREW LETTER PE */ + { 0x0cf5, 0x05e5 }, /* hebrew_finalzade ץ HEBREW LETTER FINAL TSADI */ + { 0x0cf6, 0x05e6 }, /* hebrew_zade צ HEBREW LETTER TSADI */ + { 0x0cf7, 0x05e7 }, /* hebrew_qoph ק HEBREW LETTER QOF */ + { 0x0cf8, 0x05e8 }, /* hebrew_resh ר HEBREW LETTER RESH */ + { 0x0cf9, 0x05e9 }, /* hebrew_shin ש HEBREW LETTER SHIN */ + { 0x0cfa, 0x05ea }, /* hebrew_taw ת HEBREW LETTER TAV */ + { 0x05ac, 0x060c }, /* Arabic_comma ، ARABIC COMMA */ + { 0x05bb, 0x061b }, /* Arabic_semicolon ؛ ARABIC SEMICOLON */ + { 0x05bf, 0x061f }, /* Arabic_question_mark ؟ ARABIC QUESTION MARK */ + { 0x05c1, 0x0621 }, /* Arabic_hamza ء ARABIC LETTER HAMZA */ + { 0x05c2, 0x0622 }, /* Arabic_maddaonalef آ ARABIC LETTER ALEF WITH MADDA ABOVE */ + { 0x05c3, 0x0623 }, /* Arabic_hamzaonalef أ ARABIC LETTER ALEF WITH HAMZA ABOVE */ + { 0x05c4, 0x0624 }, /* Arabic_hamzaonwaw ؤ ARABIC LETTER WAW WITH HAMZA ABOVE */ + { 0x05c5, 0x0625 }, /* Arabic_hamzaunderalef إ ARABIC LETTER ALEF WITH HAMZA BELOW */ + { 0x05c6, 0x0626 }, /* Arabic_hamzaonyeh ئ ARABIC LETTER YEH WITH HAMZA ABOVE */ + { 0x05c7, 0x0627 }, /* Arabic_alef ا ARABIC LETTER ALEF */ + { 0x05c8, 0x0628 }, /* Arabic_beh ب ARABIC LETTER BEH */ + { 0x05c9, 0x0629 }, /* Arabic_tehmarbuta ة ARABIC LETTER TEH MARBUTA */ + { 0x05ca, 0x062a }, /* Arabic_teh ت ARABIC LETTER TEH */ + { 0x05cb, 0x062b }, /* Arabic_theh ث ARABIC LETTER THEH */ + { 0x05cc, 0x062c }, /* Arabic_jeem ج ARABIC LETTER JEEM */ + { 0x05cd, 0x062d }, /* Arabic_hah ح ARABIC LETTER HAH */ + { 0x05ce, 0x062e }, /* Arabic_khah خ ARABIC LETTER KHAH */ + { 0x05cf, 0x062f }, /* Arabic_dal د ARABIC LETTER DAL */ + { 0x05d0, 0x0630 }, /* Arabic_thal ذ ARABIC LETTER THAL */ + { 0x05d1, 0x0631 }, /* Arabic_ra ر ARABIC LETTER REH */ + { 0x05d2, 0x0632 }, /* Arabic_zain ز ARABIC LETTER ZAIN */ + { 0x05d3, 0x0633 }, /* Arabic_seen س ARABIC LETTER SEEN */ + { 0x05d4, 0x0634 }, /* Arabic_sheen ش ARABIC LETTER SHEEN */ + { 0x05d5, 0x0635 }, /* Arabic_sad ص ARABIC LETTER SAD */ + { 0x05d6, 0x0636 }, /* Arabic_dad ض ARABIC LETTER DAD */ + { 0x05d7, 0x0637 }, /* Arabic_tah ط ARABIC LETTER TAH */ + { 0x05d8, 0x0638 }, /* Arabic_zah ظ ARABIC LETTER ZAH */ + { 0x05d9, 0x0639 }, /* Arabic_ain ع ARABIC LETTER AIN */ + { 0x05da, 0x063a }, /* Arabic_ghain غ ARABIC LETTER GHAIN */ + { 0x05e0, 0x0640 }, /* Arabic_tatweel ـ ARABIC TATWEEL */ + { 0x05e1, 0x0641 }, /* Arabic_feh ف ARABIC LETTER FEH */ + { 0x05e2, 0x0642 }, /* Arabic_qaf ق ARABIC LETTER QAF */ + { 0x05e3, 0x0643 }, /* Arabic_kaf ك ARABIC LETTER KAF */ + { 0x05e4, 0x0644 }, /* Arabic_lam ل ARABIC LETTER LAM */ + { 0x05e5, 0x0645 }, /* Arabic_meem م ARABIC LETTER MEEM */ + { 0x05e6, 0x0646 }, /* Arabic_noon ن ARABIC LETTER NOON */ + { 0x05e7, 0x0647 }, /* Arabic_ha ه ARABIC LETTER HEH */ + { 0x05e8, 0x0648 }, /* Arabic_waw و ARABIC LETTER WAW */ + { 0x05e9, 0x0649 }, /* Arabic_alefmaksura ى ARABIC LETTER ALEF MAKSURA */ + { 0x05ea, 0x064a }, /* Arabic_yeh ي ARABIC LETTER YEH */ + { 0x05eb, 0x064b }, /* Arabic_fathatan ً ARABIC FATHATAN */ + { 0x05ec, 0x064c }, /* Arabic_dammatan ٌ ARABIC DAMMATAN */ + { 0x05ed, 0x064d }, /* Arabic_kasratan ٍ ARABIC KASRATAN */ + { 0x05ee, 0x064e }, /* Arabic_fatha َ ARABIC FATHA */ + { 0x05ef, 0x064f }, /* Arabic_damma ُ ARABIC DAMMA */ + { 0x05f0, 0x0650 }, /* Arabic_kasra ِ ARABIC KASRA */ + { 0x05f1, 0x0651 }, /* Arabic_shadda ّ ARABIC SHADDA */ + { 0x05f2, 0x0652 }, /* Arabic_sukun ْ ARABIC SUKUN */ + { 0x0da1, 0x0e01 }, /* Thai_kokai ก THAI CHARACTER KO KAI */ + { 0x0da2, 0x0e02 }, /* Thai_khokhai ข THAI CHARACTER KHO KHAI */ + { 0x0da3, 0x0e03 }, /* Thai_khokhuat ฃ THAI CHARACTER KHO KHUAT */ + { 0x0da4, 0x0e04 }, /* Thai_khokhwai ค THAI CHARACTER KHO KHWAI */ + { 0x0da5, 0x0e05 }, /* Thai_khokhon ฅ THAI CHARACTER KHO KHON */ + { 0x0da6, 0x0e06 }, /* Thai_khorakhang ฆ THAI CHARACTER KHO RAKHANG */ + { 0x0da7, 0x0e07 }, /* Thai_ngongu ง THAI CHARACTER NGO NGU */ + { 0x0da8, 0x0e08 }, /* Thai_chochan จ THAI CHARACTER CHO CHAN */ + { 0x0da9, 0x0e09 }, /* Thai_choching ฉ THAI CHARACTER CHO CHING */ + { 0x0daa, 0x0e0a }, /* Thai_chochang ช THAI CHARACTER CHO CHANG */ + { 0x0dab, 0x0e0b }, /* Thai_soso ซ THAI CHARACTER SO SO */ + { 0x0dac, 0x0e0c }, /* Thai_chochoe ฌ THAI CHARACTER CHO CHOE */ + { 0x0dad, 0x0e0d }, /* Thai_yoying ญ THAI CHARACTER YO YING */ + { 0x0dae, 0x0e0e }, /* Thai_dochada ฎ THAI CHARACTER DO CHADA */ + { 0x0daf, 0x0e0f }, /* Thai_topatak ฏ THAI CHARACTER TO PATAK */ + { 0x0db0, 0x0e10 }, /* Thai_thothan ฐ THAI CHARACTER THO THAN */ + { 0x0db1, 0x0e11 }, /* Thai_thonangmontho ฑ THAI CHARACTER THO NANGMONTHO */ + { 0x0db2, 0x0e12 }, /* Thai_thophuthao ฒ THAI CHARACTER THO PHUTHAO */ + { 0x0db3, 0x0e13 }, /* Thai_nonen ณ THAI CHARACTER NO NEN */ + { 0x0db4, 0x0e14 }, /* Thai_dodek ด THAI CHARACTER DO DEK */ + { 0x0db5, 0x0e15 }, /* Thai_totao ต THAI CHARACTER TO TAO */ + { 0x0db6, 0x0e16 }, /* Thai_thothung ถ THAI CHARACTER THO THUNG */ + { 0x0db7, 0x0e17 }, /* Thai_thothahan ท THAI CHARACTER THO THAHAN */ + { 0x0db8, 0x0e18 }, /* Thai_thothong ธ THAI CHARACTER THO THONG */ + { 0x0db9, 0x0e19 }, /* Thai_nonu น THAI CHARACTER NO NU */ + { 0x0dba, 0x0e1a }, /* Thai_bobaimai บ THAI CHARACTER BO BAIMAI */ + { 0x0dbb, 0x0e1b }, /* Thai_popla ป THAI CHARACTER PO PLA */ + { 0x0dbc, 0x0e1c }, /* Thai_phophung ผ THAI CHARACTER PHO PHUNG */ + { 0x0dbd, 0x0e1d }, /* Thai_fofa ฝ THAI CHARACTER FO FA */ + { 0x0dbe, 0x0e1e }, /* Thai_phophan พ THAI CHARACTER PHO PHAN */ + { 0x0dbf, 0x0e1f }, /* Thai_fofan ฟ THAI CHARACTER FO FAN */ + { 0x0dc0, 0x0e20 }, /* Thai_phosamphao ภ THAI CHARACTER PHO SAMPHAO */ + { 0x0dc1, 0x0e21 }, /* Thai_moma ม THAI CHARACTER MO MA */ + { 0x0dc2, 0x0e22 }, /* Thai_yoyak ย THAI CHARACTER YO YAK */ + { 0x0dc3, 0x0e23 }, /* Thai_rorua ร THAI CHARACTER RO RUA */ + { 0x0dc4, 0x0e24 }, /* Thai_ru ฤ THAI CHARACTER RU */ + { 0x0dc5, 0x0e25 }, /* Thai_loling ล THAI CHARACTER LO LING */ + { 0x0dc6, 0x0e26 }, /* Thai_lu ฦ THAI CHARACTER LU */ + { 0x0dc7, 0x0e27 }, /* Thai_wowaen ว THAI CHARACTER WO WAEN */ + { 0x0dc8, 0x0e28 }, /* Thai_sosala ศ THAI CHARACTER SO SALA */ + { 0x0dc9, 0x0e29 }, /* Thai_sorusi ษ THAI CHARACTER SO RUSI */ + { 0x0dca, 0x0e2a }, /* Thai_sosua ส THAI CHARACTER SO SUA */ + { 0x0dcb, 0x0e2b }, /* Thai_hohip ห THAI CHARACTER HO HIP */ + { 0x0dcc, 0x0e2c }, /* Thai_lochula ฬ THAI CHARACTER LO CHULA */ + { 0x0dcd, 0x0e2d }, /* Thai_oang อ THAI CHARACTER O ANG */ + { 0x0dce, 0x0e2e }, /* Thai_honokhuk ฮ THAI CHARACTER HO NOKHUK */ + { 0x0dcf, 0x0e2f }, /* Thai_paiyannoi ฯ THAI CHARACTER PAIYANNOI */ + { 0x0dd0, 0x0e30 }, /* Thai_saraa ะ THAI CHARACTER SARA A */ + { 0x0dd1, 0x0e31 }, /* Thai_maihanakat ั THAI CHARACTER MAI HAN-AKAT */ + { 0x0dd2, 0x0e32 }, /* Thai_saraaa า THAI CHARACTER SARA AA */ + { 0x0dd3, 0x0e33 }, /* Thai_saraam ำ THAI CHARACTER SARA AM */ + { 0x0dd4, 0x0e34 }, /* Thai_sarai ิ THAI CHARACTER SARA I */ + { 0x0dd5, 0x0e35 }, /* Thai_saraii ี THAI CHARACTER SARA II */ + { 0x0dd6, 0x0e36 }, /* Thai_saraue ึ THAI CHARACTER SARA UE */ + { 0x0dd7, 0x0e37 }, /* Thai_sarauee ื THAI CHARACTER SARA UEE */ + { 0x0dd8, 0x0e38 }, /* Thai_sarau ุ THAI CHARACTER SARA U */ + { 0x0dd9, 0x0e39 }, /* Thai_sarauu ู THAI CHARACTER SARA UU */ + { 0x0dda, 0x0e3a }, /* Thai_phinthu ฺ THAI CHARACTER PHINTHU */ + { 0x0ddf, 0x0e3f }, /* Thai_baht ฿ THAI CURRENCY SYMBOL BAHT */ + { 0x0de0, 0x0e40 }, /* Thai_sarae เ THAI CHARACTER SARA E */ + { 0x0de1, 0x0e41 }, /* Thai_saraae แ THAI CHARACTER SARA AE */ + { 0x0de2, 0x0e42 }, /* Thai_sarao โ THAI CHARACTER SARA O */ + { 0x0de3, 0x0e43 }, /* Thai_saraaimaimuan ใ THAI CHARACTER SARA AI MAIMUAN */ + { 0x0de4, 0x0e44 }, /* Thai_saraaimaimalai ไ THAI CHARACTER SARA AI MAIMALAI */ + { 0x0de5, 0x0e45 }, /* Thai_lakkhangyao ๅ THAI CHARACTER LAKKHANGYAO */ + { 0x0de6, 0x0e46 }, /* Thai_maiyamok ๆ THAI CHARACTER MAIYAMOK */ + { 0x0de7, 0x0e47 }, /* Thai_maitaikhu ็ THAI CHARACTER MAITAIKHU */ + { 0x0de8, 0x0e48 }, /* Thai_maiek ่ THAI CHARACTER MAI EK */ + { 0x0de9, 0x0e49 }, /* Thai_maitho ้ THAI CHARACTER MAI THO */ + { 0x0dea, 0x0e4a }, /* Thai_maitri ๊ THAI CHARACTER MAI TRI */ + { 0x0deb, 0x0e4b }, /* Thai_maichattawa ๋ THAI CHARACTER MAI CHATTAWA */ + { 0x0dec, 0x0e4c }, /* Thai_thanthakhat ์ THAI CHARACTER THANTHAKHAT */ + { 0x0ded, 0x0e4d }, /* Thai_nikhahit ํ THAI CHARACTER NIKHAHIT */ + { 0x0df0, 0x0e50 }, /* Thai_leksun ๐ THAI DIGIT ZERO */ + { 0x0df1, 0x0e51 }, /* Thai_leknung ๑ THAI DIGIT ONE */ + { 0x0df2, 0x0e52 }, /* Thai_leksong ๒ THAI DIGIT TWO */ + { 0x0df3, 0x0e53 }, /* Thai_leksam ๓ THAI DIGIT THREE */ + { 0x0df4, 0x0e54 }, /* Thai_leksi ๔ THAI DIGIT FOUR */ + { 0x0df5, 0x0e55 }, /* Thai_lekha ๕ THAI DIGIT FIVE */ + { 0x0df6, 0x0e56 }, /* Thai_lekhok ๖ THAI DIGIT SIX */ + { 0x0df7, 0x0e57 }, /* Thai_lekchet ๗ THAI DIGIT SEVEN */ + { 0x0df8, 0x0e58 }, /* Thai_lekpaet ๘ THAI DIGIT EIGHT */ + { 0x0df9, 0x0e59 }, /* Thai_lekkao ๙ THAI DIGIT NINE */ + { 0x0ed4, 0x11a8 }, /* Hangul_J_Kiyeog ᆨ HANGUL JONGSEONG KIYEOK */ + { 0x0ed5, 0x11a9 }, /* Hangul_J_SsangKiyeog ᆩ HANGUL JONGSEONG SSANGKIYEOK */ + { 0x0ed6, 0x11aa }, /* Hangul_J_KiyeogSios ᆪ HANGUL JONGSEONG KIYEOK-SIOS */ + { 0x0ed7, 0x11ab }, /* Hangul_J_Nieun ᆫ HANGUL JONGSEONG NIEUN */ + { 0x0ed8, 0x11ac }, /* Hangul_J_NieunJieuj ᆬ HANGUL JONGSEONG NIEUN-CIEUC */ + { 0x0ed9, 0x11ad }, /* Hangul_J_NieunHieuh ᆭ HANGUL JONGSEONG NIEUN-HIEUH */ + { 0x0eda, 0x11ae }, /* Hangul_J_Dikeud ᆮ HANGUL JONGSEONG TIKEUT */ + { 0x0edb, 0x11af }, /* Hangul_J_Rieul ᆯ HANGUL JONGSEONG RIEUL */ + { 0x0edc, 0x11b0 }, /* Hangul_J_RieulKiyeog ᆰ HANGUL JONGSEONG RIEUL-KIYEOK */ + { 0x0edd, 0x11b1 }, /* Hangul_J_RieulMieum ᆱ HANGUL JONGSEONG RIEUL-MIEUM */ + { 0x0ede, 0x11b2 }, /* Hangul_J_RieulPieub ᆲ HANGUL JONGSEONG RIEUL-PIEUP */ + { 0x0edf, 0x11b3 }, /* Hangul_J_RieulSios ᆳ HANGUL JONGSEONG RIEUL-SIOS */ + { 0x0ee0, 0x11b4 }, /* Hangul_J_RieulTieut ᆴ HANGUL JONGSEONG RIEUL-THIEUTH */ + { 0x0ee1, 0x11b5 }, /* Hangul_J_RieulPhieuf ᆵ HANGUL JONGSEONG RIEUL-PHIEUPH */ + { 0x0ee2, 0x11b6 }, /* Hangul_J_RieulHieuh ᆶ HANGUL JONGSEONG RIEUL-HIEUH */ + { 0x0ee3, 0x11b7 }, /* Hangul_J_Mieum ᆷ HANGUL JONGSEONG MIEUM */ + { 0x0ee4, 0x11b8 }, /* Hangul_J_Pieub ᆸ HANGUL JONGSEONG PIEUP */ + { 0x0ee5, 0x11b9 }, /* Hangul_J_PieubSios ᆹ HANGUL JONGSEONG PIEUP-SIOS */ + { 0x0ee6, 0x11ba }, /* Hangul_J_Sios ᆺ HANGUL JONGSEONG SIOS */ + { 0x0ee7, 0x11bb }, /* Hangul_J_SsangSios ᆻ HANGUL JONGSEONG SSANGSIOS */ + { 0x0ee8, 0x11bc }, /* Hangul_J_Ieung ᆼ HANGUL JONGSEONG IEUNG */ + { 0x0ee9, 0x11bd }, /* Hangul_J_Jieuj ᆽ HANGUL JONGSEONG CIEUC */ + { 0x0eea, 0x11be }, /* Hangul_J_Cieuc ᆾ HANGUL JONGSEONG CHIEUCH */ + { 0x0eeb, 0x11bf }, /* Hangul_J_Khieuq ᆿ HANGUL JONGSEONG KHIEUKH */ + { 0x0eec, 0x11c0 }, /* Hangul_J_Tieut ᇀ HANGUL JONGSEONG THIEUTH */ + { 0x0eed, 0x11c1 }, /* Hangul_J_Phieuf ᇁ HANGUL JONGSEONG PHIEUPH */ + { 0x0eee, 0x11c2 }, /* Hangul_J_Hieuh ᇂ HANGUL JONGSEONG HIEUH */ + { 0x0ef8, 0x11eb }, /* Hangul_J_PanSios ᇫ HANGUL JONGSEONG PANSIOS */ + { 0x0efa, 0x11f9 }, /* Hangul_J_YeorinHieuh ᇹ HANGUL JONGSEONG YEORINHIEUH */ + { 0x0aa2, 0x2002 }, /* enspace   EN SPACE */ + { 0x0aa1, 0x2003 }, /* emspace   EM SPACE */ + { 0x0aa3, 0x2004 }, /* em3space   THREE-PER-EM SPACE */ + { 0x0aa4, 0x2005 }, /* em4space   FOUR-PER-EM SPACE */ + { 0x0aa5, 0x2007 }, /* digitspace   FIGURE SPACE */ + { 0x0aa6, 0x2008 }, /* punctspace   PUNCTUATION SPACE */ + { 0x0aa7, 0x2009 }, /* thinspace   THIN SPACE */ + { 0x0aa8, 0x200a }, /* hairspace   HAIR SPACE */ + { 0x0abb, 0x2012 }, /* figdash ‒ FIGURE DASH */ + { 0x0aaa, 0x2013 }, /* endash – EN DASH */ + { 0x0aa9, 0x2014 }, /* emdash — EM DASH */ + { 0x07af, 0x2015 }, /* Greek_horizbar ― HORIZONTAL BAR */ + { 0x0cdf, 0x2017 }, /* hebrew_doublelowline ‗ DOUBLE LOW LINE */ + { 0x0ad0, 0x2018 }, /* leftsinglequotemark ‘ LEFT SINGLE QUOTATION MARK */ + { 0x0ad1, 0x2019 }, /* rightsinglequotemark ’ RIGHT SINGLE QUOTATION MARK */ + { 0x0afd, 0x201a }, /* singlelowquotemark ‚ SINGLE LOW-9 QUOTATION MARK */ + { 0x0ad2, 0x201c }, /* leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK */ + { 0x0ad3, 0x201d }, /* rightdoublequotemark ” RIGHT DOUBLE QUOTATION MARK */ + { 0x0afe, 0x201e }, /* doublelowquotemark „ DOUBLE LOW-9 QUOTATION MARK */ + { 0x0af1, 0x2020 }, /* dagger † DAGGER */ + { 0x0af2, 0x2021 }, /* doubledagger ‡ DOUBLE DAGGER */ + { 0x0ae6, 0x2022 }, /* enfilledcircbullet • BULLET */ + { 0x0aae, 0x2026 }, /* ellipsis … HORIZONTAL ELLIPSIS */ + { 0x0ad6, 0x2032 }, /* minutes ′ PRIME */ + { 0x0ad7, 0x2033 }, /* seconds ″ DOUBLE PRIME */ + { 0x0afc, 0x2038 }, /* caret ‸ CARET */ + { 0x047e, 0x203e }, /* overline ‾ OVERLINE */ + { 0x20a0, 0x20a0 }, /* EcuSign ₠ EURO-CURRENCY SIGN */ + { 0x20a1, 0x20a1 }, /* ColonSign ₡ COLON SIGN */ + { 0x20a2, 0x20a2 }, /* CruzeiroSign ₢ CRUZEIRO SIGN */ + { 0x20a3, 0x20a3 }, /* FFrancSign ₣ FRENCH FRANC SIGN */ + { 0x20a4, 0x20a4 }, /* LiraSign ₤ LIRA SIGN */ + { 0x20a5, 0x20a5 }, /* MillSign ₥ MILL SIGN */ + { 0x20a6, 0x20a6 }, /* NairaSign ₦ NAIRA SIGN */ + { 0x20a7, 0x20a7 }, /* PesetaSign ₧ PESETA SIGN */ + { 0x20a8, 0x20a8 }, /* RupeeSign ₨ RUPEE SIGN */ + { 0x0eff, 0x20a9 }, /* Korean_Won ₩ WON SIGN */ + { 0x20a9, 0x20a9 }, /* WonSign ₩ WON SIGN */ + { 0x20aa, 0x20aa }, /* NewSheqelSign ₪ NEW SHEQEL SIGN */ + { 0x20ab, 0x20ab }, /* DongSign ₫ DONG SIGN */ + { 0x20ac, 0x20ac }, /* EuroSign € EURO SIGN */ + { 0x0ab8, 0x2105 }, /* careof ℅ CARE OF */ + { 0x06b0, 0x2116 }, /* numerosign № NUMERO SIGN */ + { 0x0afb, 0x2117 }, /* phonographcopyright ℗ SOUND RECORDING COPYRIGHT */ + { 0x0ad4, 0x211e }, /* prescription ℞ PRESCRIPTION TAKE */ + { 0x0ac9, 0x2122 }, /* trademark ™ TRADE MARK SIGN */ + { 0x0ab0, 0x2153 }, /* onethird ⅓ VULGAR FRACTION ONE THIRD */ + { 0x0ab1, 0x2154 }, /* twothirds ⅔ VULGAR FRACTION TWO THIRDS */ + { 0x0ab2, 0x2155 }, /* onefifth ⅕ VULGAR FRACTION ONE FIFTH */ + { 0x0ab3, 0x2156 }, /* twofifths ⅖ VULGAR FRACTION TWO FIFTHS */ + { 0x0ab4, 0x2157 }, /* threefifths ⅗ VULGAR FRACTION THREE FIFTHS */ + { 0x0ab5, 0x2158 }, /* fourfifths ⅘ VULGAR FRACTION FOUR FIFTHS */ + { 0x0ab6, 0x2159 }, /* onesixth ⅙ VULGAR FRACTION ONE SIXTH */ + { 0x0ab7, 0x215a }, /* fivesixths ⅚ VULGAR FRACTION FIVE SIXTHS */ + { 0x0ac3, 0x215b }, /* oneeighth ⅛ VULGAR FRACTION ONE EIGHTH */ + { 0x0ac4, 0x215c }, /* threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS */ + { 0x0ac5, 0x215d }, /* fiveeighths ⅝ VULGAR FRACTION FIVE EIGHTHS */ + { 0x0ac6, 0x215e }, /* seveneighths ⅞ VULGAR FRACTION SEVEN EIGHTHS */ + { 0x08fb, 0x2190 }, /* leftarrow ← LEFTWARDS ARROW */ + { 0x08fc, 0x2191 }, /* uparrow ↑ UPWARDS ARROW */ + { 0x08fd, 0x2192 }, /* rightarrow → RIGHTWARDS ARROW */ + { 0x08fe, 0x2193 }, /* downarrow ↓ DOWNWARDS ARROW */ + { 0x08ce, 0x21d2 }, /* implies ⇒ RIGHTWARDS DOUBLE ARROW */ + { 0x08cd, 0x21d4 }, /* ifonlyif ⇔ LEFT RIGHT DOUBLE ARROW */ + { 0x08ef, 0x2202 }, /* partialderivative ∂ PARTIAL DIFFERENTIAL */ + { 0x08c5, 0x2207 }, /* nabla ∇ NABLA */ + { 0x0bca, 0x2218 }, /* jot ∘ RING OPERATOR */ + { 0x08d6, 0x221a }, /* radical √ SQUARE ROOT */ + { 0x08c1, 0x221d }, /* variation ∝ PROPORTIONAL TO */ + { 0x08c2, 0x221e }, /* infinity ∞ INFINITY */ + { 0x08de, 0x2227 }, /* logicaland ∧ LOGICAL AND */ + { 0x0ba9, 0x2227 }, /* upcaret ∧ LOGICAL AND */ + { 0x08df, 0x2228 }, /* logicalor ∨ LOGICAL OR */ + { 0x0ba8, 0x2228 }, /* downcaret ∨ LOGICAL OR */ + { 0x08dc, 0x2229 }, /* intersection ∩ INTERSECTION */ + { 0x0bc3, 0x2229 }, /* upshoe ∩ INTERSECTION */ + { 0x08dd, 0x222a }, /* union ∪ UNION */ + { 0x0bd6, 0x222a }, /* downshoe ∪ UNION */ + { 0x08bf, 0x222b }, /* integral ∫ INTEGRAL */ + { 0x08c0, 0x2234 }, /* therefore ∴ THEREFORE */ + { 0x08c8, 0x2245 }, /* approximate ≅ APPROXIMATELY EQUAL TO */ + { 0x08bd, 0x2260 }, /* notequal ≠ NOT EQUAL TO */ + { 0x08cf, 0x2261 }, /* identical ≡ IDENTICAL TO */ + { 0x08bc, 0x2264 }, /* lessthanequal ≤ LESS-THAN OR EQUAL TO */ + { 0x08be, 0x2265 }, /* greaterthanequal ≥ GREATER-THAN OR EQUAL TO */ + { 0x08da, 0x2282 }, /* includedin ⊂ SUBSET OF */ + { 0x0bda, 0x2282 }, /* leftshoe ⊂ SUBSET OF */ + { 0x08db, 0x2283 }, /* includes ⊃ SUPERSET OF */ + { 0x0bd8, 0x2283 }, /* rightshoe ⊃ SUPERSET OF */ + { 0x0bfc, 0x22a2 }, /* righttack ⊢ RIGHT TACK */ + { 0x0bdc, 0x22a3 }, /* lefttack ⊣ LEFT TACK */ + { 0x0bc2, 0x22a4 }, /* downtack ⊤ DOWN TACK */ + { 0x0bce, 0x22a5 }, /* uptack ⊥ UP TACK */ + { 0x0bd3, 0x2308 }, /* upstile ⌈ LEFT CEILING */ + { 0x0bc4, 0x230a }, /* downstile ⌊ LEFT FLOOR */ + { 0x0afa, 0x2315 }, /* telephonerecorder ⌕ TELEPHONE RECORDER */ + { 0x08a4, 0x2320 }, /* topintegral ⌠ TOP HALF INTEGRAL */ + { 0x08a5, 0x2321 }, /* botintegral ⌡ BOTTOM HALF INTEGRAL */ + { 0x0abc, 0x2329 }, /* leftanglebracket 〈 LEFT-POINTING ANGLE BRACKET */ + { 0x0abe, 0x232a }, /* rightanglebracket 〉 RIGHT-POINTING ANGLE BRACKET */ + { 0x0bcc, 0x2395 }, /* quad ⎕ APL FUNCTIONAL SYMBOL QUAD (Unicode 3.0) */ + { 0x09e2, 0x2409 }, /* ht ␉ SYMBOL FOR HORIZONTAL TABULATION */ + { 0x09e5, 0x240a }, /* lf ␊ SYMBOL FOR LINE FEED */ + { 0x09e9, 0x240b }, /* vt ␋ SYMBOL FOR VERTICAL TABULATION */ + { 0x09e3, 0x240c }, /* ff ␌ SYMBOL FOR FORM FEED */ + { 0x09e4, 0x240d }, /* cr ␍ SYMBOL FOR CARRIAGE RETURN */ + { 0x09df, 0x2422 }, /* blank ␢ BLANK SYMBOL */ + { 0x09e8, 0x2424 }, /* nl ␤ SYMBOL FOR NEWLINE */ + { 0x09f1, 0x2500 }, /* horizlinescan5 ─ BOX DRAWINGS LIGHT HORIZONTAL */ + { 0x08a6, 0x2502 }, /* vertconnector │ BOX DRAWINGS LIGHT VERTICAL */ + { 0x09f8, 0x2502 }, /* vertbar │ BOX DRAWINGS LIGHT VERTICAL */ + { 0x09ec, 0x250c }, /* upleftcorner ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */ + { 0x09eb, 0x2510 }, /* uprightcorner ┐ BOX DRAWINGS LIGHT DOWN AND LEFT */ + { 0x09ed, 0x2514 }, /* lowleftcorner └ BOX DRAWINGS LIGHT UP AND RIGHT */ + { 0x09ea, 0x2518 }, /* lowrightcorner ┘ BOX DRAWINGS LIGHT UP AND LEFT */ + { 0x09f4, 0x251c }, /* leftt ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT */ + { 0x09f5, 0x2524 }, /* rightt ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT */ + { 0x09f7, 0x252c }, /* topt ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */ + { 0x09f6, 0x2534 }, /* bott ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL */ + { 0x09ee, 0x253c }, /* crossinglines ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */ + { 0x09e1, 0x2592 }, /* checkerboard ▒ MEDIUM SHADE */ + { 0x0adf, 0x25a0 }, /* emfilledrect ■ BLACK SQUARE */ + { 0x0acf, 0x25a1 }, /* emopenrectangle □ WHITE SQUARE */ + { 0x0ae7, 0x25aa }, /* enfilledsqbullet ▪ BLACK SMALL SQUARE */ + { 0x0ae1, 0x25ab }, /* enopensquarebullet ▫ WHITE SMALL SQUARE */ + { 0x0adb, 0x25ac }, /* filledrectbullet ▬ BLACK RECTANGLE */ + { 0x0ae2, 0x25ad }, /* openrectbullet ▭ WHITE RECTANGLE */ + { 0x0ae8, 0x25b2 }, /* filledtribulletup ▲ BLACK UP-POINTING TRIANGLE */ + { 0x0ae3, 0x25b3 }, /* opentribulletup △ WHITE UP-POINTING TRIANGLE */ + { 0x0add, 0x25b6 }, /* filledrighttribullet ▶ BLACK RIGHT-POINTING TRIANGLE */ + { 0x0acd, 0x25b7 }, /* rightopentriangle ▷ WHITE RIGHT-POINTING TRIANGLE */ + { 0x0ae9, 0x25bc }, /* filledtribulletdown ▼ BLACK DOWN-POINTING TRIANGLE */ + { 0x0ae4, 0x25bd }, /* opentribulletdown ▽ WHITE DOWN-POINTING TRIANGLE */ + { 0x0adc, 0x25c0 }, /* filledlefttribullet ◀ BLACK LEFT-POINTING TRIANGLE */ + { 0x0acc, 0x25c1 }, /* leftopentriangle ◁ WHITE LEFT-POINTING TRIANGLE */ + { 0x09e0, 0x25c6 }, /* soliddiamond ◆ BLACK DIAMOND */ + { 0x0ace, 0x25cb }, /* emopencircle ○ WHITE CIRCLE */ + { 0x0bcf, 0x25cb }, /* circle ○ WHITE CIRCLE */ + { 0x0ade, 0x25cf }, /* emfilledcircle ● BLACK CIRCLE */ + { 0x0ae0, 0x25e6 }, /* enopencircbullet ◦ WHITE BULLET */ + { 0x0ae5, 0x2606 }, /* openstar ☆ WHITE STAR */ + { 0x0af9, 0x260e }, /* telephone ☎ BLACK TELEPHONE */ + { 0x0aca, 0x2613 }, /* signaturemark ☓ SALTIRE */ + { 0x0aea, 0x261c }, /* leftpointer ☜ WHITE LEFT POINTING INDEX */ + { 0x0aeb, 0x261e }, /* rightpointer ☞ WHITE RIGHT POINTING INDEX */ + { 0x0af8, 0x2640 }, /* femalesymbol ♀ FEMALE SIGN */ + { 0x0af7, 0x2642 }, /* malesymbol ♂ MALE SIGN */ + { 0x0aec, 0x2663 }, /* club ♣ BLACK CLUB SUIT */ + { 0x0aee, 0x2665 }, /* heart ♥ BLACK HEART SUIT */ + { 0x0aed, 0x2666 }, /* diamond ♦ BLACK DIAMOND SUIT */ + { 0x0af6, 0x266d }, /* musicalflat ♭ MUSIC FLAT SIGN */ + { 0x0af5, 0x266f }, /* musicalsharp ♯ MUSIC SHARP SIGN */ + { 0x0af3, 0x2713 }, /* checkmark ✓ CHECK MARK */ + { 0x0af4, 0x2717 }, /* ballotcross ✗ BALLOT X */ + { 0x0ad9, 0x271d }, /* latincross ✝ LATIN CROSS */ + { 0x0af0, 0x2720 }, /* maltesecross ✠ MALTESE CROSS */ + { 0x04a4, 0x3001 }, /* kana_comma 、 IDEOGRAPHIC COMMA */ + { 0x04a1, 0x3002 }, /* kana_fullstop 。 IDEOGRAPHIC FULL STOP */ + { 0x04a2, 0x300c }, /* kana_openingbracket 「 LEFT CORNER BRACKET */ + { 0x04a3, 0x300d }, /* kana_closingbracket 」 RIGHT CORNER BRACKET */ + { 0x04de, 0x309b }, /* voicedsound ゛ KATAKANA-HIRAGANA VOICED SOUND MARK */ + { 0x04df, 0x309c }, /* semivoicedsound ゜ KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */ + { 0x04a7, 0x30a1 }, /* kana_a ァ KATAKANA LETTER SMALL A */ + { 0x04b1, 0x30a2 }, /* kana_A ア KATAKANA LETTER A */ + { 0x04a8, 0x30a3 }, /* kana_i ィ KATAKANA LETTER SMALL I */ + { 0x04b2, 0x30a4 }, /* kana_I イ KATAKANA LETTER I */ + { 0x04a9, 0x30a5 }, /* kana_u ゥ KATAKANA LETTER SMALL U */ + { 0x04b3, 0x30a6 }, /* kana_U ウ KATAKANA LETTER U */ + { 0x04aa, 0x30a7 }, /* kana_e ェ KATAKANA LETTER SMALL E */ + { 0x04b4, 0x30a8 }, /* kana_E エ KATAKANA LETTER E */ + { 0x04ab, 0x30a9 }, /* kana_o ォ KATAKANA LETTER SMALL O */ + { 0x04b5, 0x30aa }, /* kana_O オ KATAKANA LETTER O */ + { 0x04b6, 0x30ab }, /* kana_KA カ KATAKANA LETTER KA */ + { 0x04b7, 0x30ad }, /* kana_KI キ KATAKANA LETTER KI */ + { 0x04b8, 0x30af }, /* kana_KU ク KATAKANA LETTER KU */ + { 0x04b9, 0x30b1 }, /* kana_KE ケ KATAKANA LETTER KE */ + { 0x04ba, 0x30b3 }, /* kana_KO コ KATAKANA LETTER KO */ + { 0x04bb, 0x30b5 }, /* kana_SA サ KATAKANA LETTER SA */ + { 0x04bc, 0x30b7 }, /* kana_SHI シ KATAKANA LETTER SI */ + { 0x04bd, 0x30b9 }, /* kana_SU ス KATAKANA LETTER SU */ + { 0x04be, 0x30bb }, /* kana_SE セ KATAKANA LETTER SE */ + { 0x04bf, 0x30bd }, /* kana_SO ソ KATAKANA LETTER SO */ + { 0x04c0, 0x30bf }, /* kana_TA タ KATAKANA LETTER TA */ + { 0x04c1, 0x30c1 }, /* kana_CHI チ KATAKANA LETTER TI */ + { 0x04af, 0x30c3 }, /* kana_tsu ッ KATAKANA LETTER SMALL TU */ + { 0x04c2, 0x30c4 }, /* kana_TSU ツ KATAKANA LETTER TU */ + { 0x04c3, 0x30c6 }, /* kana_TE テ KATAKANA LETTER TE */ + { 0x04c4, 0x30c8 }, /* kana_TO ト KATAKANA LETTER TO */ + { 0x04c5, 0x30ca }, /* kana_NA ナ KATAKANA LETTER NA */ + { 0x04c6, 0x30cb }, /* kana_NI ニ KATAKANA LETTER NI */ + { 0x04c7, 0x30cc }, /* kana_NU ヌ KATAKANA LETTER NU */ + { 0x04c8, 0x30cd }, /* kana_NE ネ KATAKANA LETTER NE */ + { 0x04c9, 0x30ce }, /* kana_NO ノ KATAKANA LETTER NO */ + { 0x04ca, 0x30cf }, /* kana_HA ハ KATAKANA LETTER HA */ + { 0x04cb, 0x30d2 }, /* kana_HI ヒ KATAKANA LETTER HI */ + { 0x04cc, 0x30d5 }, /* kana_FU フ KATAKANA LETTER HU */ + { 0x04cd, 0x30d8 }, /* kana_HE ヘ KATAKANA LETTER HE */ + { 0x04ce, 0x30db }, /* kana_HO ホ KATAKANA LETTER HO */ + { 0x04cf, 0x30de }, /* kana_MA マ KATAKANA LETTER MA */ + { 0x04d0, 0x30df }, /* kana_MI ミ KATAKANA LETTER MI */ + { 0x04d1, 0x30e0 }, /* kana_MU ム KATAKANA LETTER MU */ + { 0x04d2, 0x30e1 }, /* kana_ME メ KATAKANA LETTER ME */ + { 0x04d3, 0x30e2 }, /* kana_MO モ KATAKANA LETTER MO */ + { 0x04ac, 0x30e3 }, /* kana_ya ャ KATAKANA LETTER SMALL YA */ + { 0x04d4, 0x30e4 }, /* kana_YA ヤ KATAKANA LETTER YA */ + { 0x04ad, 0x30e5 }, /* kana_yu ュ KATAKANA LETTER SMALL YU */ + { 0x04d5, 0x30e6 }, /* kana_YU ユ KATAKANA LETTER YU */ + { 0x04ae, 0x30e7 }, /* kana_yo ョ KATAKANA LETTER SMALL YO */ + { 0x04d6, 0x30e8 }, /* kana_YO ヨ KATAKANA LETTER YO */ + { 0x04d7, 0x30e9 }, /* kana_RA ラ KATAKANA LETTER RA */ + { 0x04d8, 0x30ea }, /* kana_RI リ KATAKANA LETTER RI */ + { 0x04d9, 0x30eb }, /* kana_RU ル KATAKANA LETTER RU */ + { 0x04da, 0x30ec }, /* kana_RE レ KATAKANA LETTER RE */ + { 0x04db, 0x30ed }, /* kana_RO ロ KATAKANA LETTER RO */ + { 0x04dc, 0x30ef }, /* kana_WA ワ KATAKANA LETTER WA */ + { 0x04a6, 0x30f2 }, /* kana_WO ヲ KATAKANA LETTER WO */ + { 0x04dd, 0x30f3 }, /* kana_N ン KATAKANA LETTER N */ + { 0x04a5, 0x30fb }, /* kana_conjunctive ・ KATAKANA MIDDLE DOT */ + { 0x04b0, 0x30fc }, /* prolongedsound ー KATAKANA-HIRAGANA PROLONGED SOUND MARK */ + { 0x0ea1, 0x3131 }, /* Hangul_Kiyeog ㄱ HANGUL LETTER KIYEOK */ + { 0x0ea2, 0x3132 }, /* Hangul_SsangKiyeog ㄲ HANGUL LETTER SSANGKIYEOK */ + { 0x0ea3, 0x3133 }, /* Hangul_KiyeogSios ㄳ HANGUL LETTER KIYEOK-SIOS */ + { 0x0ea4, 0x3134 }, /* Hangul_Nieun ㄴ HANGUL LETTER NIEUN */ + { 0x0ea5, 0x3135 }, /* Hangul_NieunJieuj ㄵ HANGUL LETTER NIEUN-CIEUC */ + { 0x0ea6, 0x3136 }, /* Hangul_NieunHieuh ㄶ HANGUL LETTER NIEUN-HIEUH */ + { 0x0ea7, 0x3137 }, /* Hangul_Dikeud ㄷ HANGUL LETTER TIKEUT */ + { 0x0ea8, 0x3138 }, /* Hangul_SsangDikeud ㄸ HANGUL LETTER SSANGTIKEUT */ + { 0x0ea9, 0x3139 }, /* Hangul_Rieul ㄹ HANGUL LETTER RIEUL */ + { 0x0eaa, 0x313a }, /* Hangul_RieulKiyeog ㄺ HANGUL LETTER RIEUL-KIYEOK */ + { 0x0eab, 0x313b }, /* Hangul_RieulMieum ㄻ HANGUL LETTER RIEUL-MIEUM */ + { 0x0eac, 0x313c }, /* Hangul_RieulPieub ㄼ HANGUL LETTER RIEUL-PIEUP */ + { 0x0ead, 0x313d }, /* Hangul_RieulSios ㄽ HANGUL LETTER RIEUL-SIOS */ + { 0x0eae, 0x313e }, /* Hangul_RieulTieut ㄾ HANGUL LETTER RIEUL-THIEUTH */ + { 0x0eaf, 0x313f }, /* Hangul_RieulPhieuf ㄿ HANGUL LETTER RIEUL-PHIEUPH */ + { 0x0eb0, 0x3140 }, /* Hangul_RieulHieuh ㅀ HANGUL LETTER RIEUL-HIEUH */ + { 0x0eb1, 0x3141 }, /* Hangul_Mieum ㅁ HANGUL LETTER MIEUM */ + { 0x0eb2, 0x3142 }, /* Hangul_Pieub ㅂ HANGUL LETTER PIEUP */ + { 0x0eb3, 0x3143 }, /* Hangul_SsangPieub ㅃ HANGUL LETTER SSANGPIEUP */ + { 0x0eb4, 0x3144 }, /* Hangul_PieubSios ㅄ HANGUL LETTER PIEUP-SIOS */ + { 0x0eb5, 0x3145 }, /* Hangul_Sios ㅅ HANGUL LETTER SIOS */ + { 0x0eb6, 0x3146 }, /* Hangul_SsangSios ㅆ HANGUL LETTER SSANGSIOS */ + { 0x0eb7, 0x3147 }, /* Hangul_Ieung ㅇ HANGUL LETTER IEUNG */ + { 0x0eb8, 0x3148 }, /* Hangul_Jieuj ㅈ HANGUL LETTER CIEUC */ + { 0x0eb9, 0x3149 }, /* Hangul_SsangJieuj ㅉ HANGUL LETTER SSANGCIEUC */ + { 0x0eba, 0x314a }, /* Hangul_Cieuc ㅊ HANGUL LETTER CHIEUCH */ + { 0x0ebb, 0x314b }, /* Hangul_Khieuq ㅋ HANGUL LETTER KHIEUKH */ + { 0x0ebc, 0x314c }, /* Hangul_Tieut ㅌ HANGUL LETTER THIEUTH */ + { 0x0ebd, 0x314d }, /* Hangul_Phieuf ㅍ HANGUL LETTER PHIEUPH */ + { 0x0ebe, 0x314e }, /* Hangul_Hieuh ㅎ HANGUL LETTER HIEUH */ + { 0x0ebf, 0x314f }, /* Hangul_A ㅏ HANGUL LETTER A */ + { 0x0ec0, 0x3150 }, /* Hangul_AE ㅐ HANGUL LETTER AE */ + { 0x0ec1, 0x3151 }, /* Hangul_YA ㅑ HANGUL LETTER YA */ + { 0x0ec2, 0x3152 }, /* Hangul_YAE ㅒ HANGUL LETTER YAE */ + { 0x0ec3, 0x3153 }, /* Hangul_EO ㅓ HANGUL LETTER EO */ + { 0x0ec4, 0x3154 }, /* Hangul_E ㅔ HANGUL LETTER E */ + { 0x0ec5, 0x3155 }, /* Hangul_YEO ㅕ HANGUL LETTER YEO */ + { 0x0ec6, 0x3156 }, /* Hangul_YE ㅖ HANGUL LETTER YE */ + { 0x0ec7, 0x3157 }, /* Hangul_O ㅗ HANGUL LETTER O */ + { 0x0ec8, 0x3158 }, /* Hangul_WA ㅘ HANGUL LETTER WA */ + { 0x0ec9, 0x3159 }, /* Hangul_WAE ㅙ HANGUL LETTER WAE */ + { 0x0eca, 0x315a }, /* Hangul_OE ㅚ HANGUL LETTER OE */ + { 0x0ecb, 0x315b }, /* Hangul_YO ㅛ HANGUL LETTER YO */ + { 0x0ecc, 0x315c }, /* Hangul_U ㅜ HANGUL LETTER U */ + { 0x0ecd, 0x315d }, /* Hangul_WEO ㅝ HANGUL LETTER WEO */ + { 0x0ece, 0x315e }, /* Hangul_WE ㅞ HANGUL LETTER WE */ + { 0x0ecf, 0x315f }, /* Hangul_WI ㅟ HANGUL LETTER WI */ + { 0x0ed0, 0x3160 }, /* Hangul_YU ㅠ HANGUL LETTER YU */ + { 0x0ed1, 0x3161 }, /* Hangul_EU ㅡ HANGUL LETTER EU */ + { 0x0ed2, 0x3162 }, /* Hangul_YI ㅢ HANGUL LETTER YI */ + { 0x0ed3, 0x3163 }, /* Hangul_I ㅣ HANGUL LETTER I */ + { 0x0eef, 0x316d }, /* Hangul_RieulYeorinHieuh ㅭ HANGUL LETTER RIEUL-YEORINHIEUH */ + { 0x0ef0, 0x3171 }, /* Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM */ + { 0x0ef1, 0x3178 }, /* Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP */ + { 0x0ef2, 0x317f }, /* Hangul_PanSios ㅿ HANGUL LETTER PANSIOS */ + { 0x0ef4, 0x3184 }, /* Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH */ + { 0x0ef5, 0x3186 }, /* Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH */ + { 0x0ef6, 0x318d }, /* Hangul_AraeA ㆍ HANGUL LETTER ARAEA */ + { 0x0ef7, 0x318e }, /* Hangul_AraeAE ㆎ HANGUL LETTER ARAEAE */ +}; + +static const int clutter_unicode_to_keysym_tab_size = + G_N_ELEMENTS (clutter_unicode_to_keysym_tab); + +/** + * clutter_unicode_to_keysym: + * @wc: a ISO10646 encoded character + * + * Convert from a ISO10646 character to a key symbol. + * + * Return value: the corresponding Clutter key symbol, if one exists. + * or, if there is no corresponding symbol, wc | 0x01000000 + * + * Since: 1.10 + */ +guint +clutter_unicode_to_keysym (guint32 wc) +{ + int min = 0; + int max = clutter_unicode_to_keysym_tab_size - 1; + int mid; + + /* First check for Latin-1 characters (1:1 mapping) */ + if ((wc >= 0x0020 && wc <= 0x007e) || + (wc >= 0x00a0 && wc <= 0x00ff)) + return wc; + + /* Binary search in table */ + while (max >= min) + { + mid = (min + max) / 2; + + if (clutter_unicode_to_keysym_tab[mid].ucs < wc) + min = mid + 1; + else if (clutter_unicode_to_keysym_tab[mid].ucs > wc) + max = mid - 1; + else + { + /* found it */ + return clutter_unicode_to_keysym_tab[mid].keysym; + } + } + + /* No matching keysym value found, return Unicode value plus 0x01000000 + * (a convention introduced in the UTF-8 work on xterm). + */ + return wc | 0x01000000; +} diff --git a/clutter/clutter/clutter-keysyms-update.pl b/clutter/clutter/clutter-keysyms-update.pl new file mode 100755 index 0000000..35440ee --- /dev/null +++ b/clutter/clutter/clutter-keysyms-update.pl @@ -0,0 +1,217 @@ +#!/usr/bin/env perl + +# Author : Simos Xenitellis . +# Authos : Bastien Nocera +# Version : 1.2 +# +# Notes : It downloads keysymdef.h from the Internet, if not found locally, +# Notes : and creates an updated clutter-keysyms.h + +use strict; + +my $update_url = 'http://git.clutter-project.org/clutter/plain/clutter/clutter-keysyms-update.pl'; + +# Used for reading the keysymdef symbols. +my @keysymelements; + +my $keysymdef_url = 'http://cgit.freedesktop.org/xorg/proto/x11proto/plain/keysymdef.h'; + +if ( ! -f "keysymdef.h" ) +{ + print "Trying to download keysymdef.h from\n", $keysymdef_url, "\n"; + die "Unable to download keysymdef.h: $!" + unless system("wget -c -O keysymdef.h \"$keysymdef_url\"") == 0; + print " done.\n\n"; +} +else +{ + print "We are using existing keysymdef.h found in this directory.\n"; + print "It is assumed that you took care and it is a recent version\n"; +} + +my $XF86keysym_url = 'http://cgit.freedesktop.org/xorg/proto/x11proto/plain/XF86keysym.h'; + +if ( ! -f "XF86keysym.h" ) +{ + print "Trying to download XF86keysym.h from\n", $XF86keysym_url, "\n"; + die "Unable to download keysymdef.h: $!\n" + unless system("wget -c -O XF86keysym.h \"$XF86keysym_url\"") == 0; + print " done.\n\n"; +} +else +{ + print "We are using existing XF86keysym.h found in this directory.\n"; + print "It is assumed that you took care and it is a recent version\n"; +} + +if ( -f "clutter-keysyms.h" ) +{ + print "There is already a clutter-keysyms.h file in this directory. We are not overwriting it.\n"; + print "Please move it somewhere else in order to run this script.\n"; + die "Exiting...\n\n"; +} + +die "Could not open file keysymdef.h: $!\n" + unless open(IN_KEYSYMDEF, "<:utf8", "keysymdef.h"); + +# Output: clutter/clutter/clutter-keysyms.h +die "Could not open file clutter-keysyms.h: $!\n" + unless open(OUT_KEYSYMS, ">:utf8", "clutter-keysyms.h"); + +# Output: clutter/clutter/deprecated/clutter-keysyms.h +die "Could not open file clutter-keysyms-compat.h: $!\n" + unless open(OUT_KEYSYMS_COMPAT, ">:utf8", "deprecated/clutter-keysyms.h"); + +my $LICENSE_HEADER= <. + */ + +EOF + +print OUT_KEYSYMS $LICENSE_HEADER; +print OUT_KEYSYMS_COMPAT $LICENSE_HEADER; + +print OUT_KEYSYMS<) +{ + next if ( ! /^#define / ); + + @keysymelements = split(/\s+/); + die "Internal error, no \@keysymelements: $_\n" unless @keysymelements; + + $_ = $keysymelements[1]; + die "Internal error, was expecting \"XC_*\", found: $_\n" if ( ! /^XK_/ ); + + $_ = $keysymelements[2]; + die "Internal error, was expecting \"0x*\", found: $_\n" if ( ! /^0x/ ); + + my $element = $keysymelements[1]; + my $binding = $element; + $binding =~ s/^XK_/CLUTTER_KEY_/g; + my $compat_binding = $element; + $compat_binding =~ s/^XK_/CLUTTER_/g; + + my $deprecation = "CLUTTER_DEPRECATED_MACRO_FOR(\"Deprecated key symbol. Use $binding instead.\")"; + + printf OUT_KEYSYMS "#define %s 0x%03x\n", $binding, hex($keysymelements[2]); + printf OUT_KEYSYMS_COMPAT "#define %s 0x%03x %s\n", $compat_binding, hex($keysymelements[2]), $deprecation; +} + +close IN_KEYSYMDEF; + +#$cluttersyms{"0"} = "0000"; + +# Source: http://gitweb.freedesktop.org/?p=xorg/proto/x11proto.git;a=blob;f=XF86keysym.h +die "Could not open file XF86keysym.h: $!\n" unless open(IN_XF86KEYSYM, "<:utf8", "XF86keysym.h"); + +while () +{ + next if ( ! /^#define / ); + + @keysymelements = split(/\s+/); + die "Internal error, no \@keysymelements: $_\n" unless @keysymelements; + + $_ = $keysymelements[1]; + die "Internal error, was expecting \"XF86XK_*\", found: $_\n" if ( ! /^XF86XK_/ ); + + # Work-around https://bugs.freedesktop.org/show_bug.cgi?id=11193 + if ($_ eq "XF86XK_XF86BackForward") { + $keysymelements[1] = "XF86XK_AudioForward"; + } + # XF86XK_Clear could end up a dupe of XK_Clear + # XF86XK_Select could end up a dupe of XK_Select + if ($_ eq "XF86XK_Clear") { + $keysymelements[1] = "XF86XK_WindowClear"; + } + if ($_ eq "XF86XK_Select") { + $keysymelements[1] = "XF86XK_SelectButton"; + } + + # Ignore XF86XK_Q + next if ( $_ eq "XF86XK_Q"); + # XF86XK_Calculater is misspelled, and a dupe + next if ( $_ eq "XF86XK_Calculater"); + + $_ = $keysymelements[2]; + die "Internal error, was expecting \"0x*\", found: $_\n" if ( ! /^0x/ ); + + my $element = $keysymelements[1]; + my $binding = $element; + $binding =~ s/^XF86XK_/CLUTTER_KEY_/g; + my $compat_binding = $element; + $compat_binding =~ s/^XF86XK_/CLUTTER_/g; + + printf OUT_KEYSYMS "#define %s 0x%03x\n", $binding, hex($keysymelements[2]); + printf OUT_KEYSYMS_COMPAT "#define %s 0x%03x\n", $compat_binding, hex($keysymelements[2]); +} + +close IN_XF86KEYSYM; + + +print OUT_KEYSYMS<. + */ + + +/* + * File auto-generated from script at: + * http://git.clutter-project.org/clutter/plain/clutter/clutter-keysyms-update.pl + * + * using the input files: + * http://cgit.freedesktop.org/xorg/proto/x11proto/plain/keysymdef.h + * and + * http://cgit.freedesktop.org/xorg/proto/x11proto/plain/XF86keysym.h + */ + +#ifndef __CLUTTER_KEYSYMS_H__ +#define __CLUTTER_KEYSYMS_H__ + +#define CLUTTER_KEY_VoidSymbol 0xffffff +#define CLUTTER_KEY_BackSpace 0xff08 +#define CLUTTER_KEY_Tab 0xff09 +#define CLUTTER_KEY_Linefeed 0xff0a +#define CLUTTER_KEY_Clear 0xff0b +#define CLUTTER_KEY_Return 0xff0d +#define CLUTTER_KEY_Pause 0xff13 +#define CLUTTER_KEY_Scroll_Lock 0xff14 +#define CLUTTER_KEY_Sys_Req 0xff15 +#define CLUTTER_KEY_Escape 0xff1b +#define CLUTTER_KEY_Delete 0xffff +#define CLUTTER_KEY_Multi_key 0xff20 +#define CLUTTER_KEY_Codeinput 0xff37 +#define CLUTTER_KEY_SingleCandidate 0xff3c +#define CLUTTER_KEY_MultipleCandidate 0xff3d +#define CLUTTER_KEY_PreviousCandidate 0xff3e +#define CLUTTER_KEY_Kanji 0xff21 +#define CLUTTER_KEY_Muhenkan 0xff22 +#define CLUTTER_KEY_Henkan_Mode 0xff23 +#define CLUTTER_KEY_Henkan 0xff23 +#define CLUTTER_KEY_Romaji 0xff24 +#define CLUTTER_KEY_Hiragana 0xff25 +#define CLUTTER_KEY_Katakana 0xff26 +#define CLUTTER_KEY_Hiragana_Katakana 0xff27 +#define CLUTTER_KEY_Zenkaku 0xff28 +#define CLUTTER_KEY_Hankaku 0xff29 +#define CLUTTER_KEY_Zenkaku_Hankaku 0xff2a +#define CLUTTER_KEY_Touroku 0xff2b +#define CLUTTER_KEY_Massyo 0xff2c +#define CLUTTER_KEY_Kana_Lock 0xff2d +#define CLUTTER_KEY_Kana_Shift 0xff2e +#define CLUTTER_KEY_Eisu_Shift 0xff2f +#define CLUTTER_KEY_Eisu_toggle 0xff30 +#define CLUTTER_KEY_Kanji_Bangou 0xff37 +#define CLUTTER_KEY_Zen_Koho 0xff3d +#define CLUTTER_KEY_Mae_Koho 0xff3e +#define CLUTTER_KEY_Home 0xff50 +#define CLUTTER_KEY_Left 0xff51 +#define CLUTTER_KEY_Up 0xff52 +#define CLUTTER_KEY_Right 0xff53 +#define CLUTTER_KEY_Down 0xff54 +#define CLUTTER_KEY_Prior 0xff55 +#define CLUTTER_KEY_Page_Up 0xff55 +#define CLUTTER_KEY_Next 0xff56 +#define CLUTTER_KEY_Page_Down 0xff56 +#define CLUTTER_KEY_End 0xff57 +#define CLUTTER_KEY_Begin 0xff58 +#define CLUTTER_KEY_Select 0xff60 +#define CLUTTER_KEY_Print 0xff61 +#define CLUTTER_KEY_Execute 0xff62 +#define CLUTTER_KEY_Insert 0xff63 +#define CLUTTER_KEY_Undo 0xff65 +#define CLUTTER_KEY_Redo 0xff66 +#define CLUTTER_KEY_Menu 0xff67 +#define CLUTTER_KEY_Find 0xff68 +#define CLUTTER_KEY_Cancel 0xff69 +#define CLUTTER_KEY_Help 0xff6a +#define CLUTTER_KEY_Break 0xff6b +#define CLUTTER_KEY_Mode_switch 0xff7e +#define CLUTTER_KEY_script_switch 0xff7e +#define CLUTTER_KEY_Num_Lock 0xff7f +#define CLUTTER_KEY_KP_Space 0xff80 +#define CLUTTER_KEY_KP_Tab 0xff89 +#define CLUTTER_KEY_KP_Enter 0xff8d +#define CLUTTER_KEY_KP_F1 0xff91 +#define CLUTTER_KEY_KP_F2 0xff92 +#define CLUTTER_KEY_KP_F3 0xff93 +#define CLUTTER_KEY_KP_F4 0xff94 +#define CLUTTER_KEY_KP_Home 0xff95 +#define CLUTTER_KEY_KP_Left 0xff96 +#define CLUTTER_KEY_KP_Up 0xff97 +#define CLUTTER_KEY_KP_Right 0xff98 +#define CLUTTER_KEY_KP_Down 0xff99 +#define CLUTTER_KEY_KP_Prior 0xff9a +#define CLUTTER_KEY_KP_Page_Up 0xff9a +#define CLUTTER_KEY_KP_Next 0xff9b +#define CLUTTER_KEY_KP_Page_Down 0xff9b +#define CLUTTER_KEY_KP_End 0xff9c +#define CLUTTER_KEY_KP_Begin 0xff9d +#define CLUTTER_KEY_KP_Insert 0xff9e +#define CLUTTER_KEY_KP_Delete 0xff9f +#define CLUTTER_KEY_KP_Equal 0xffbd +#define CLUTTER_KEY_KP_Multiply 0xffaa +#define CLUTTER_KEY_KP_Add 0xffab +#define CLUTTER_KEY_KP_Separator 0xffac +#define CLUTTER_KEY_KP_Subtract 0xffad +#define CLUTTER_KEY_KP_Decimal 0xffae +#define CLUTTER_KEY_KP_Divide 0xffaf +#define CLUTTER_KEY_KP_0 0xffb0 +#define CLUTTER_KEY_KP_1 0xffb1 +#define CLUTTER_KEY_KP_2 0xffb2 +#define CLUTTER_KEY_KP_3 0xffb3 +#define CLUTTER_KEY_KP_4 0xffb4 +#define CLUTTER_KEY_KP_5 0xffb5 +#define CLUTTER_KEY_KP_6 0xffb6 +#define CLUTTER_KEY_KP_7 0xffb7 +#define CLUTTER_KEY_KP_8 0xffb8 +#define CLUTTER_KEY_KP_9 0xffb9 +#define CLUTTER_KEY_F1 0xffbe +#define CLUTTER_KEY_F2 0xffbf +#define CLUTTER_KEY_F3 0xffc0 +#define CLUTTER_KEY_F4 0xffc1 +#define CLUTTER_KEY_F5 0xffc2 +#define CLUTTER_KEY_F6 0xffc3 +#define CLUTTER_KEY_F7 0xffc4 +#define CLUTTER_KEY_F8 0xffc5 +#define CLUTTER_KEY_F9 0xffc6 +#define CLUTTER_KEY_F10 0xffc7 +#define CLUTTER_KEY_F11 0xffc8 +#define CLUTTER_KEY_L1 0xffc8 +#define CLUTTER_KEY_F12 0xffc9 +#define CLUTTER_KEY_L2 0xffc9 +#define CLUTTER_KEY_F13 0xffca +#define CLUTTER_KEY_L3 0xffca +#define CLUTTER_KEY_F14 0xffcb +#define CLUTTER_KEY_L4 0xffcb +#define CLUTTER_KEY_F15 0xffcc +#define CLUTTER_KEY_L5 0xffcc +#define CLUTTER_KEY_F16 0xffcd +#define CLUTTER_KEY_L6 0xffcd +#define CLUTTER_KEY_F17 0xffce +#define CLUTTER_KEY_L7 0xffce +#define CLUTTER_KEY_F18 0xffcf +#define CLUTTER_KEY_L8 0xffcf +#define CLUTTER_KEY_F19 0xffd0 +#define CLUTTER_KEY_L9 0xffd0 +#define CLUTTER_KEY_F20 0xffd1 +#define CLUTTER_KEY_L10 0xffd1 +#define CLUTTER_KEY_F21 0xffd2 +#define CLUTTER_KEY_R1 0xffd2 +#define CLUTTER_KEY_F22 0xffd3 +#define CLUTTER_KEY_R2 0xffd3 +#define CLUTTER_KEY_F23 0xffd4 +#define CLUTTER_KEY_R3 0xffd4 +#define CLUTTER_KEY_F24 0xffd5 +#define CLUTTER_KEY_R4 0xffd5 +#define CLUTTER_KEY_F25 0xffd6 +#define CLUTTER_KEY_R5 0xffd6 +#define CLUTTER_KEY_F26 0xffd7 +#define CLUTTER_KEY_R6 0xffd7 +#define CLUTTER_KEY_F27 0xffd8 +#define CLUTTER_KEY_R7 0xffd8 +#define CLUTTER_KEY_F28 0xffd9 +#define CLUTTER_KEY_R8 0xffd9 +#define CLUTTER_KEY_F29 0xffda +#define CLUTTER_KEY_R9 0xffda +#define CLUTTER_KEY_F30 0xffdb +#define CLUTTER_KEY_R10 0xffdb +#define CLUTTER_KEY_F31 0xffdc +#define CLUTTER_KEY_R11 0xffdc +#define CLUTTER_KEY_F32 0xffdd +#define CLUTTER_KEY_R12 0xffdd +#define CLUTTER_KEY_F33 0xffde +#define CLUTTER_KEY_R13 0xffde +#define CLUTTER_KEY_F34 0xffdf +#define CLUTTER_KEY_R14 0xffdf +#define CLUTTER_KEY_F35 0xffe0 +#define CLUTTER_KEY_R15 0xffe0 +#define CLUTTER_KEY_Shift_L 0xffe1 +#define CLUTTER_KEY_Shift_R 0xffe2 +#define CLUTTER_KEY_Control_L 0xffe3 +#define CLUTTER_KEY_Control_R 0xffe4 +#define CLUTTER_KEY_Caps_Lock 0xffe5 +#define CLUTTER_KEY_Shift_Lock 0xffe6 +#define CLUTTER_KEY_Meta_L 0xffe7 +#define CLUTTER_KEY_Meta_R 0xffe8 +#define CLUTTER_KEY_Alt_L 0xffe9 +#define CLUTTER_KEY_Alt_R 0xffea +#define CLUTTER_KEY_Super_L 0xffeb +#define CLUTTER_KEY_Super_R 0xffec +#define CLUTTER_KEY_Hyper_L 0xffed +#define CLUTTER_KEY_Hyper_R 0xffee +#define CLUTTER_KEY_ISO_Lock 0xfe01 +#define CLUTTER_KEY_ISO_Level2_Latch 0xfe02 +#define CLUTTER_KEY_ISO_Level3_Shift 0xfe03 +#define CLUTTER_KEY_ISO_Level3_Latch 0xfe04 +#define CLUTTER_KEY_ISO_Level3_Lock 0xfe05 +#define CLUTTER_KEY_ISO_Level5_Shift 0xfe11 +#define CLUTTER_KEY_ISO_Level5_Latch 0xfe12 +#define CLUTTER_KEY_ISO_Level5_Lock 0xfe13 +#define CLUTTER_KEY_ISO_Group_Shift 0xff7e +#define CLUTTER_KEY_ISO_Group_Latch 0xfe06 +#define CLUTTER_KEY_ISO_Group_Lock 0xfe07 +#define CLUTTER_KEY_ISO_Next_Group 0xfe08 +#define CLUTTER_KEY_ISO_Next_Group_Lock 0xfe09 +#define CLUTTER_KEY_ISO_Prev_Group 0xfe0a +#define CLUTTER_KEY_ISO_Prev_Group_Lock 0xfe0b +#define CLUTTER_KEY_ISO_First_Group 0xfe0c +#define CLUTTER_KEY_ISO_First_Group_Lock 0xfe0d +#define CLUTTER_KEY_ISO_Last_Group 0xfe0e +#define CLUTTER_KEY_ISO_Last_Group_Lock 0xfe0f +#define CLUTTER_KEY_ISO_Left_Tab 0xfe20 +#define CLUTTER_KEY_ISO_Move_Line_Up 0xfe21 +#define CLUTTER_KEY_ISO_Move_Line_Down 0xfe22 +#define CLUTTER_KEY_ISO_Partial_Line_Up 0xfe23 +#define CLUTTER_KEY_ISO_Partial_Line_Down 0xfe24 +#define CLUTTER_KEY_ISO_Partial_Space_Left 0xfe25 +#define CLUTTER_KEY_ISO_Partial_Space_Right 0xfe26 +#define CLUTTER_KEY_ISO_Set_Margin_Left 0xfe27 +#define CLUTTER_KEY_ISO_Set_Margin_Right 0xfe28 +#define CLUTTER_KEY_ISO_Release_Margin_Left 0xfe29 +#define CLUTTER_KEY_ISO_Release_Margin_Right 0xfe2a +#define CLUTTER_KEY_ISO_Release_Both_Margins 0xfe2b +#define CLUTTER_KEY_ISO_Fast_Cursor_Left 0xfe2c +#define CLUTTER_KEY_ISO_Fast_Cursor_Right 0xfe2d +#define CLUTTER_KEY_ISO_Fast_Cursor_Up 0xfe2e +#define CLUTTER_KEY_ISO_Fast_Cursor_Down 0xfe2f +#define CLUTTER_KEY_ISO_Continuous_Underline 0xfe30 +#define CLUTTER_KEY_ISO_Discontinuous_Underline 0xfe31 +#define CLUTTER_KEY_ISO_Emphasize 0xfe32 +#define CLUTTER_KEY_ISO_Center_Object 0xfe33 +#define CLUTTER_KEY_ISO_Enter 0xfe34 +#define CLUTTER_KEY_dead_grave 0xfe50 +#define CLUTTER_KEY_dead_acute 0xfe51 +#define CLUTTER_KEY_dead_circumflex 0xfe52 +#define CLUTTER_KEY_dead_tilde 0xfe53 +#define CLUTTER_KEY_dead_perispomeni 0xfe53 +#define CLUTTER_KEY_dead_macron 0xfe54 +#define CLUTTER_KEY_dead_breve 0xfe55 +#define CLUTTER_KEY_dead_abovedot 0xfe56 +#define CLUTTER_KEY_dead_diaeresis 0xfe57 +#define CLUTTER_KEY_dead_abovering 0xfe58 +#define CLUTTER_KEY_dead_doubleacute 0xfe59 +#define CLUTTER_KEY_dead_caron 0xfe5a +#define CLUTTER_KEY_dead_cedilla 0xfe5b +#define CLUTTER_KEY_dead_ogonek 0xfe5c +#define CLUTTER_KEY_dead_iota 0xfe5d +#define CLUTTER_KEY_dead_voiced_sound 0xfe5e +#define CLUTTER_KEY_dead_semivoiced_sound 0xfe5f +#define CLUTTER_KEY_dead_belowdot 0xfe60 +#define CLUTTER_KEY_dead_hook 0xfe61 +#define CLUTTER_KEY_dead_horn 0xfe62 +#define CLUTTER_KEY_dead_stroke 0xfe63 +#define CLUTTER_KEY_dead_abovecomma 0xfe64 +#define CLUTTER_KEY_dead_psili 0xfe64 +#define CLUTTER_KEY_dead_abovereversedcomma 0xfe65 +#define CLUTTER_KEY_dead_dasia 0xfe65 +#define CLUTTER_KEY_dead_doublegrave 0xfe66 +#define CLUTTER_KEY_dead_belowring 0xfe67 +#define CLUTTER_KEY_dead_belowmacron 0xfe68 +#define CLUTTER_KEY_dead_belowcircumflex 0xfe69 +#define CLUTTER_KEY_dead_belowtilde 0xfe6a +#define CLUTTER_KEY_dead_belowbreve 0xfe6b +#define CLUTTER_KEY_dead_belowdiaeresis 0xfe6c +#define CLUTTER_KEY_dead_invertedbreve 0xfe6d +#define CLUTTER_KEY_dead_belowcomma 0xfe6e +#define CLUTTER_KEY_dead_currency 0xfe6f +#define CLUTTER_KEY_dead_lowline 0xfe90 +#define CLUTTER_KEY_dead_aboveverticalline 0xfe91 +#define CLUTTER_KEY_dead_belowverticalline 0xfe92 +#define CLUTTER_KEY_dead_longsolidusoverlay 0xfe93 +#define CLUTTER_KEY_dead_a 0xfe80 +#define CLUTTER_KEY_dead_A 0xfe81 +#define CLUTTER_KEY_dead_e 0xfe82 +#define CLUTTER_KEY_dead_E 0xfe83 +#define CLUTTER_KEY_dead_i 0xfe84 +#define CLUTTER_KEY_dead_I 0xfe85 +#define CLUTTER_KEY_dead_o 0xfe86 +#define CLUTTER_KEY_dead_O 0xfe87 +#define CLUTTER_KEY_dead_u 0xfe88 +#define CLUTTER_KEY_dead_U 0xfe89 +#define CLUTTER_KEY_dead_small_schwa 0xfe8a +#define CLUTTER_KEY_dead_capital_schwa 0xfe8b +#define CLUTTER_KEY_dead_greek 0xfe8c +#define CLUTTER_KEY_First_Virtual_Screen 0xfed0 +#define CLUTTER_KEY_Prev_Virtual_Screen 0xfed1 +#define CLUTTER_KEY_Next_Virtual_Screen 0xfed2 +#define CLUTTER_KEY_Last_Virtual_Screen 0xfed4 +#define CLUTTER_KEY_Terminate_Server 0xfed5 +#define CLUTTER_KEY_AccessX_Enable 0xfe70 +#define CLUTTER_KEY_AccessX_Feedback_Enable 0xfe71 +#define CLUTTER_KEY_RepeatKeys_Enable 0xfe72 +#define CLUTTER_KEY_SlowKeys_Enable 0xfe73 +#define CLUTTER_KEY_BounceKeys_Enable 0xfe74 +#define CLUTTER_KEY_StickyKeys_Enable 0xfe75 +#define CLUTTER_KEY_MouseKeys_Enable 0xfe76 +#define CLUTTER_KEY_MouseKeys_Accel_Enable 0xfe77 +#define CLUTTER_KEY_Overlay1_Enable 0xfe78 +#define CLUTTER_KEY_Overlay2_Enable 0xfe79 +#define CLUTTER_KEY_AudibleBell_Enable 0xfe7a +#define CLUTTER_KEY_Pointer_Left 0xfee0 +#define CLUTTER_KEY_Pointer_Right 0xfee1 +#define CLUTTER_KEY_Pointer_Up 0xfee2 +#define CLUTTER_KEY_Pointer_Down 0xfee3 +#define CLUTTER_KEY_Pointer_UpLeft 0xfee4 +#define CLUTTER_KEY_Pointer_UpRight 0xfee5 +#define CLUTTER_KEY_Pointer_DownLeft 0xfee6 +#define CLUTTER_KEY_Pointer_DownRight 0xfee7 +#define CLUTTER_KEY_Pointer_Button_Dflt 0xfee8 +#define CLUTTER_KEY_Pointer_Button1 0xfee9 +#define CLUTTER_KEY_Pointer_Button2 0xfeea +#define CLUTTER_KEY_Pointer_Button3 0xfeeb +#define CLUTTER_KEY_Pointer_Button4 0xfeec +#define CLUTTER_KEY_Pointer_Button5 0xfeed +#define CLUTTER_KEY_Pointer_DblClick_Dflt 0xfeee +#define CLUTTER_KEY_Pointer_DblClick1 0xfeef +#define CLUTTER_KEY_Pointer_DblClick2 0xfef0 +#define CLUTTER_KEY_Pointer_DblClick3 0xfef1 +#define CLUTTER_KEY_Pointer_DblClick4 0xfef2 +#define CLUTTER_KEY_Pointer_DblClick5 0xfef3 +#define CLUTTER_KEY_Pointer_Drag_Dflt 0xfef4 +#define CLUTTER_KEY_Pointer_Drag1 0xfef5 +#define CLUTTER_KEY_Pointer_Drag2 0xfef6 +#define CLUTTER_KEY_Pointer_Drag3 0xfef7 +#define CLUTTER_KEY_Pointer_Drag4 0xfef8 +#define CLUTTER_KEY_Pointer_Drag5 0xfefd +#define CLUTTER_KEY_Pointer_EnableKeys 0xfef9 +#define CLUTTER_KEY_Pointer_Accelerate 0xfefa +#define CLUTTER_KEY_Pointer_DfltBtnNext 0xfefb +#define CLUTTER_KEY_Pointer_DfltBtnPrev 0xfefc +#define CLUTTER_KEY_ch 0xfea0 +#define CLUTTER_KEY_Ch 0xfea1 +#define CLUTTER_KEY_CH 0xfea2 +#define CLUTTER_KEY_c_h 0xfea3 +#define CLUTTER_KEY_C_h 0xfea4 +#define CLUTTER_KEY_C_H 0xfea5 +#define CLUTTER_KEY_3270_Duplicate 0xfd01 +#define CLUTTER_KEY_3270_FieldMark 0xfd02 +#define CLUTTER_KEY_3270_Right2 0xfd03 +#define CLUTTER_KEY_3270_Left2 0xfd04 +#define CLUTTER_KEY_3270_BackTab 0xfd05 +#define CLUTTER_KEY_3270_EraseEOF 0xfd06 +#define CLUTTER_KEY_3270_EraseInput 0xfd07 +#define CLUTTER_KEY_3270_Reset 0xfd08 +#define CLUTTER_KEY_3270_Quit 0xfd09 +#define CLUTTER_KEY_3270_PA1 0xfd0a +#define CLUTTER_KEY_3270_PA2 0xfd0b +#define CLUTTER_KEY_3270_PA3 0xfd0c +#define CLUTTER_KEY_3270_Test 0xfd0d +#define CLUTTER_KEY_3270_Attn 0xfd0e +#define CLUTTER_KEY_3270_CursorBlink 0xfd0f +#define CLUTTER_KEY_3270_AltCursor 0xfd10 +#define CLUTTER_KEY_3270_KeyClick 0xfd11 +#define CLUTTER_KEY_3270_Jump 0xfd12 +#define CLUTTER_KEY_3270_Ident 0xfd13 +#define CLUTTER_KEY_3270_Rule 0xfd14 +#define CLUTTER_KEY_3270_Copy 0xfd15 +#define CLUTTER_KEY_3270_Play 0xfd16 +#define CLUTTER_KEY_3270_Setup 0xfd17 +#define CLUTTER_KEY_3270_Record 0xfd18 +#define CLUTTER_KEY_3270_ChangeScreen 0xfd19 +#define CLUTTER_KEY_3270_DeleteWord 0xfd1a +#define CLUTTER_KEY_3270_ExSelect 0xfd1b +#define CLUTTER_KEY_3270_CursorSelect 0xfd1c +#define CLUTTER_KEY_3270_PrintScreen 0xfd1d +#define CLUTTER_KEY_3270_Enter 0xfd1e +#define CLUTTER_KEY_space 0x020 +#define CLUTTER_KEY_exclam 0x021 +#define CLUTTER_KEY_quotedbl 0x022 +#define CLUTTER_KEY_numbersign 0x023 +#define CLUTTER_KEY_dollar 0x024 +#define CLUTTER_KEY_percent 0x025 +#define CLUTTER_KEY_ampersand 0x026 +#define CLUTTER_KEY_apostrophe 0x027 +#define CLUTTER_KEY_quoteright 0x027 +#define CLUTTER_KEY_parenleft 0x028 +#define CLUTTER_KEY_parenright 0x029 +#define CLUTTER_KEY_asterisk 0x02a +#define CLUTTER_KEY_plus 0x02b +#define CLUTTER_KEY_comma 0x02c +#define CLUTTER_KEY_minus 0x02d +#define CLUTTER_KEY_period 0x02e +#define CLUTTER_KEY_slash 0x02f +#define CLUTTER_KEY_0 0x030 +#define CLUTTER_KEY_1 0x031 +#define CLUTTER_KEY_2 0x032 +#define CLUTTER_KEY_3 0x033 +#define CLUTTER_KEY_4 0x034 +#define CLUTTER_KEY_5 0x035 +#define CLUTTER_KEY_6 0x036 +#define CLUTTER_KEY_7 0x037 +#define CLUTTER_KEY_8 0x038 +#define CLUTTER_KEY_9 0x039 +#define CLUTTER_KEY_colon 0x03a +#define CLUTTER_KEY_semicolon 0x03b +#define CLUTTER_KEY_less 0x03c +#define CLUTTER_KEY_equal 0x03d +#define CLUTTER_KEY_greater 0x03e +#define CLUTTER_KEY_question 0x03f +#define CLUTTER_KEY_at 0x040 +#define CLUTTER_KEY_A 0x041 +#define CLUTTER_KEY_B 0x042 +#define CLUTTER_KEY_C 0x043 +#define CLUTTER_KEY_D 0x044 +#define CLUTTER_KEY_E 0x045 +#define CLUTTER_KEY_F 0x046 +#define CLUTTER_KEY_G 0x047 +#define CLUTTER_KEY_H 0x048 +#define CLUTTER_KEY_I 0x049 +#define CLUTTER_KEY_J 0x04a +#define CLUTTER_KEY_K 0x04b +#define CLUTTER_KEY_L 0x04c +#define CLUTTER_KEY_M 0x04d +#define CLUTTER_KEY_N 0x04e +#define CLUTTER_KEY_O 0x04f +#define CLUTTER_KEY_P 0x050 +#define CLUTTER_KEY_Q 0x051 +#define CLUTTER_KEY_R 0x052 +#define CLUTTER_KEY_S 0x053 +#define CLUTTER_KEY_T 0x054 +#define CLUTTER_KEY_U 0x055 +#define CLUTTER_KEY_V 0x056 +#define CLUTTER_KEY_W 0x057 +#define CLUTTER_KEY_X 0x058 +#define CLUTTER_KEY_Y 0x059 +#define CLUTTER_KEY_Z 0x05a +#define CLUTTER_KEY_bracketleft 0x05b +#define CLUTTER_KEY_backslash 0x05c +#define CLUTTER_KEY_bracketright 0x05d +#define CLUTTER_KEY_asciicircum 0x05e +#define CLUTTER_KEY_underscore 0x05f +#define CLUTTER_KEY_grave 0x060 +#define CLUTTER_KEY_quoteleft 0x060 +#define CLUTTER_KEY_a 0x061 +#define CLUTTER_KEY_b 0x062 +#define CLUTTER_KEY_c 0x063 +#define CLUTTER_KEY_d 0x064 +#define CLUTTER_KEY_e 0x065 +#define CLUTTER_KEY_f 0x066 +#define CLUTTER_KEY_g 0x067 +#define CLUTTER_KEY_h 0x068 +#define CLUTTER_KEY_i 0x069 +#define CLUTTER_KEY_j 0x06a +#define CLUTTER_KEY_k 0x06b +#define CLUTTER_KEY_l 0x06c +#define CLUTTER_KEY_m 0x06d +#define CLUTTER_KEY_n 0x06e +#define CLUTTER_KEY_o 0x06f +#define CLUTTER_KEY_p 0x070 +#define CLUTTER_KEY_q 0x071 +#define CLUTTER_KEY_r 0x072 +#define CLUTTER_KEY_s 0x073 +#define CLUTTER_KEY_t 0x074 +#define CLUTTER_KEY_u 0x075 +#define CLUTTER_KEY_v 0x076 +#define CLUTTER_KEY_w 0x077 +#define CLUTTER_KEY_x 0x078 +#define CLUTTER_KEY_y 0x079 +#define CLUTTER_KEY_z 0x07a +#define CLUTTER_KEY_braceleft 0x07b +#define CLUTTER_KEY_bar 0x07c +#define CLUTTER_KEY_braceright 0x07d +#define CLUTTER_KEY_asciitilde 0x07e +#define CLUTTER_KEY_nobreakspace 0x0a0 +#define CLUTTER_KEY_exclamdown 0x0a1 +#define CLUTTER_KEY_cent 0x0a2 +#define CLUTTER_KEY_sterling 0x0a3 +#define CLUTTER_KEY_currency 0x0a4 +#define CLUTTER_KEY_yen 0x0a5 +#define CLUTTER_KEY_brokenbar 0x0a6 +#define CLUTTER_KEY_section 0x0a7 +#define CLUTTER_KEY_diaeresis 0x0a8 +#define CLUTTER_KEY_copyright 0x0a9 +#define CLUTTER_KEY_ordfeminine 0x0aa +#define CLUTTER_KEY_guillemotleft 0x0ab +#define CLUTTER_KEY_notsign 0x0ac +#define CLUTTER_KEY_hyphen 0x0ad +#define CLUTTER_KEY_registered 0x0ae +#define CLUTTER_KEY_macron 0x0af +#define CLUTTER_KEY_degree 0x0b0 +#define CLUTTER_KEY_plusminus 0x0b1 +#define CLUTTER_KEY_twosuperior 0x0b2 +#define CLUTTER_KEY_threesuperior 0x0b3 +#define CLUTTER_KEY_acute 0x0b4 +#define CLUTTER_KEY_mu 0x0b5 +#define CLUTTER_KEY_paragraph 0x0b6 +#define CLUTTER_KEY_periodcentered 0x0b7 +#define CLUTTER_KEY_cedilla 0x0b8 +#define CLUTTER_KEY_onesuperior 0x0b9 +#define CLUTTER_KEY_masculine 0x0ba +#define CLUTTER_KEY_guillemotright 0x0bb +#define CLUTTER_KEY_onequarter 0x0bc +#define CLUTTER_KEY_onehalf 0x0bd +#define CLUTTER_KEY_threequarters 0x0be +#define CLUTTER_KEY_questiondown 0x0bf +#define CLUTTER_KEY_Agrave 0x0c0 +#define CLUTTER_KEY_Aacute 0x0c1 +#define CLUTTER_KEY_Acircumflex 0x0c2 +#define CLUTTER_KEY_Atilde 0x0c3 +#define CLUTTER_KEY_Adiaeresis 0x0c4 +#define CLUTTER_KEY_Aring 0x0c5 +#define CLUTTER_KEY_AE 0x0c6 +#define CLUTTER_KEY_Ccedilla 0x0c7 +#define CLUTTER_KEY_Egrave 0x0c8 +#define CLUTTER_KEY_Eacute 0x0c9 +#define CLUTTER_KEY_Ecircumflex 0x0ca +#define CLUTTER_KEY_Ediaeresis 0x0cb +#define CLUTTER_KEY_Igrave 0x0cc +#define CLUTTER_KEY_Iacute 0x0cd +#define CLUTTER_KEY_Icircumflex 0x0ce +#define CLUTTER_KEY_Idiaeresis 0x0cf +#define CLUTTER_KEY_ETH 0x0d0 +#define CLUTTER_KEY_Eth 0x0d0 +#define CLUTTER_KEY_Ntilde 0x0d1 +#define CLUTTER_KEY_Ograve 0x0d2 +#define CLUTTER_KEY_Oacute 0x0d3 +#define CLUTTER_KEY_Ocircumflex 0x0d4 +#define CLUTTER_KEY_Otilde 0x0d5 +#define CLUTTER_KEY_Odiaeresis 0x0d6 +#define CLUTTER_KEY_multiply 0x0d7 +#define CLUTTER_KEY_Oslash 0x0d8 +#define CLUTTER_KEY_Ooblique 0x0d8 +#define CLUTTER_KEY_Ugrave 0x0d9 +#define CLUTTER_KEY_Uacute 0x0da +#define CLUTTER_KEY_Ucircumflex 0x0db +#define CLUTTER_KEY_Udiaeresis 0x0dc +#define CLUTTER_KEY_Yacute 0x0dd +#define CLUTTER_KEY_THORN 0x0de +#define CLUTTER_KEY_Thorn 0x0de +#define CLUTTER_KEY_ssharp 0x0df +#define CLUTTER_KEY_agrave 0x0e0 +#define CLUTTER_KEY_aacute 0x0e1 +#define CLUTTER_KEY_acircumflex 0x0e2 +#define CLUTTER_KEY_atilde 0x0e3 +#define CLUTTER_KEY_adiaeresis 0x0e4 +#define CLUTTER_KEY_aring 0x0e5 +#define CLUTTER_KEY_ae 0x0e6 +#define CLUTTER_KEY_ccedilla 0x0e7 +#define CLUTTER_KEY_egrave 0x0e8 +#define CLUTTER_KEY_eacute 0x0e9 +#define CLUTTER_KEY_ecircumflex 0x0ea +#define CLUTTER_KEY_ediaeresis 0x0eb +#define CLUTTER_KEY_igrave 0x0ec +#define CLUTTER_KEY_iacute 0x0ed +#define CLUTTER_KEY_icircumflex 0x0ee +#define CLUTTER_KEY_idiaeresis 0x0ef +#define CLUTTER_KEY_eth 0x0f0 +#define CLUTTER_KEY_ntilde 0x0f1 +#define CLUTTER_KEY_ograve 0x0f2 +#define CLUTTER_KEY_oacute 0x0f3 +#define CLUTTER_KEY_ocircumflex 0x0f4 +#define CLUTTER_KEY_otilde 0x0f5 +#define CLUTTER_KEY_odiaeresis 0x0f6 +#define CLUTTER_KEY_division 0x0f7 +#define CLUTTER_KEY_oslash 0x0f8 +#define CLUTTER_KEY_ooblique 0x0f8 +#define CLUTTER_KEY_ugrave 0x0f9 +#define CLUTTER_KEY_uacute 0x0fa +#define CLUTTER_KEY_ucircumflex 0x0fb +#define CLUTTER_KEY_udiaeresis 0x0fc +#define CLUTTER_KEY_yacute 0x0fd +#define CLUTTER_KEY_thorn 0x0fe +#define CLUTTER_KEY_ydiaeresis 0x0ff +#define CLUTTER_KEY_Aogonek 0x1a1 +#define CLUTTER_KEY_breve 0x1a2 +#define CLUTTER_KEY_Lstroke 0x1a3 +#define CLUTTER_KEY_Lcaron 0x1a5 +#define CLUTTER_KEY_Sacute 0x1a6 +#define CLUTTER_KEY_Scaron 0x1a9 +#define CLUTTER_KEY_Scedilla 0x1aa +#define CLUTTER_KEY_Tcaron 0x1ab +#define CLUTTER_KEY_Zacute 0x1ac +#define CLUTTER_KEY_Zcaron 0x1ae +#define CLUTTER_KEY_Zabovedot 0x1af +#define CLUTTER_KEY_aogonek 0x1b1 +#define CLUTTER_KEY_ogonek 0x1b2 +#define CLUTTER_KEY_lstroke 0x1b3 +#define CLUTTER_KEY_lcaron 0x1b5 +#define CLUTTER_KEY_sacute 0x1b6 +#define CLUTTER_KEY_caron 0x1b7 +#define CLUTTER_KEY_scaron 0x1b9 +#define CLUTTER_KEY_scedilla 0x1ba +#define CLUTTER_KEY_tcaron 0x1bb +#define CLUTTER_KEY_zacute 0x1bc +#define CLUTTER_KEY_doubleacute 0x1bd +#define CLUTTER_KEY_zcaron 0x1be +#define CLUTTER_KEY_zabovedot 0x1bf +#define CLUTTER_KEY_Racute 0x1c0 +#define CLUTTER_KEY_Abreve 0x1c3 +#define CLUTTER_KEY_Lacute 0x1c5 +#define CLUTTER_KEY_Cacute 0x1c6 +#define CLUTTER_KEY_Ccaron 0x1c8 +#define CLUTTER_KEY_Eogonek 0x1ca +#define CLUTTER_KEY_Ecaron 0x1cc +#define CLUTTER_KEY_Dcaron 0x1cf +#define CLUTTER_KEY_Dstroke 0x1d0 +#define CLUTTER_KEY_Nacute 0x1d1 +#define CLUTTER_KEY_Ncaron 0x1d2 +#define CLUTTER_KEY_Odoubleacute 0x1d5 +#define CLUTTER_KEY_Rcaron 0x1d8 +#define CLUTTER_KEY_Uring 0x1d9 +#define CLUTTER_KEY_Udoubleacute 0x1db +#define CLUTTER_KEY_Tcedilla 0x1de +#define CLUTTER_KEY_racute 0x1e0 +#define CLUTTER_KEY_abreve 0x1e3 +#define CLUTTER_KEY_lacute 0x1e5 +#define CLUTTER_KEY_cacute 0x1e6 +#define CLUTTER_KEY_ccaron 0x1e8 +#define CLUTTER_KEY_eogonek 0x1ea +#define CLUTTER_KEY_ecaron 0x1ec +#define CLUTTER_KEY_dcaron 0x1ef +#define CLUTTER_KEY_dstroke 0x1f0 +#define CLUTTER_KEY_nacute 0x1f1 +#define CLUTTER_KEY_ncaron 0x1f2 +#define CLUTTER_KEY_odoubleacute 0x1f5 +#define CLUTTER_KEY_rcaron 0x1f8 +#define CLUTTER_KEY_uring 0x1f9 +#define CLUTTER_KEY_udoubleacute 0x1fb +#define CLUTTER_KEY_tcedilla 0x1fe +#define CLUTTER_KEY_abovedot 0x1ff +#define CLUTTER_KEY_Hstroke 0x2a1 +#define CLUTTER_KEY_Hcircumflex 0x2a6 +#define CLUTTER_KEY_Iabovedot 0x2a9 +#define CLUTTER_KEY_Gbreve 0x2ab +#define CLUTTER_KEY_Jcircumflex 0x2ac +#define CLUTTER_KEY_hstroke 0x2b1 +#define CLUTTER_KEY_hcircumflex 0x2b6 +#define CLUTTER_KEY_idotless 0x2b9 +#define CLUTTER_KEY_gbreve 0x2bb +#define CLUTTER_KEY_jcircumflex 0x2bc +#define CLUTTER_KEY_Cabovedot 0x2c5 +#define CLUTTER_KEY_Ccircumflex 0x2c6 +#define CLUTTER_KEY_Gabovedot 0x2d5 +#define CLUTTER_KEY_Gcircumflex 0x2d8 +#define CLUTTER_KEY_Ubreve 0x2dd +#define CLUTTER_KEY_Scircumflex 0x2de +#define CLUTTER_KEY_cabovedot 0x2e5 +#define CLUTTER_KEY_ccircumflex 0x2e6 +#define CLUTTER_KEY_gabovedot 0x2f5 +#define CLUTTER_KEY_gcircumflex 0x2f8 +#define CLUTTER_KEY_ubreve 0x2fd +#define CLUTTER_KEY_scircumflex 0x2fe +#define CLUTTER_KEY_kra 0x3a2 +#define CLUTTER_KEY_kappa 0x3a2 +#define CLUTTER_KEY_Rcedilla 0x3a3 +#define CLUTTER_KEY_Itilde 0x3a5 +#define CLUTTER_KEY_Lcedilla 0x3a6 +#define CLUTTER_KEY_Emacron 0x3aa +#define CLUTTER_KEY_Gcedilla 0x3ab +#define CLUTTER_KEY_Tslash 0x3ac +#define CLUTTER_KEY_rcedilla 0x3b3 +#define CLUTTER_KEY_itilde 0x3b5 +#define CLUTTER_KEY_lcedilla 0x3b6 +#define CLUTTER_KEY_emacron 0x3ba +#define CLUTTER_KEY_gcedilla 0x3bb +#define CLUTTER_KEY_tslash 0x3bc +#define CLUTTER_KEY_ENG 0x3bd +#define CLUTTER_KEY_eng 0x3bf +#define CLUTTER_KEY_Amacron 0x3c0 +#define CLUTTER_KEY_Iogonek 0x3c7 +#define CLUTTER_KEY_Eabovedot 0x3cc +#define CLUTTER_KEY_Imacron 0x3cf +#define CLUTTER_KEY_Ncedilla 0x3d1 +#define CLUTTER_KEY_Omacron 0x3d2 +#define CLUTTER_KEY_Kcedilla 0x3d3 +#define CLUTTER_KEY_Uogonek 0x3d9 +#define CLUTTER_KEY_Utilde 0x3dd +#define CLUTTER_KEY_Umacron 0x3de +#define CLUTTER_KEY_amacron 0x3e0 +#define CLUTTER_KEY_iogonek 0x3e7 +#define CLUTTER_KEY_eabovedot 0x3ec +#define CLUTTER_KEY_imacron 0x3ef +#define CLUTTER_KEY_ncedilla 0x3f1 +#define CLUTTER_KEY_omacron 0x3f2 +#define CLUTTER_KEY_kcedilla 0x3f3 +#define CLUTTER_KEY_uogonek 0x3f9 +#define CLUTTER_KEY_utilde 0x3fd +#define CLUTTER_KEY_umacron 0x3fe +#define CLUTTER_KEY_Wcircumflex 0x1000174 +#define CLUTTER_KEY_wcircumflex 0x1000175 +#define CLUTTER_KEY_Ycircumflex 0x1000176 +#define CLUTTER_KEY_ycircumflex 0x1000177 +#define CLUTTER_KEY_Babovedot 0x1001e02 +#define CLUTTER_KEY_babovedot 0x1001e03 +#define CLUTTER_KEY_Dabovedot 0x1001e0a +#define CLUTTER_KEY_dabovedot 0x1001e0b +#define CLUTTER_KEY_Fabovedot 0x1001e1e +#define CLUTTER_KEY_fabovedot 0x1001e1f +#define CLUTTER_KEY_Mabovedot 0x1001e40 +#define CLUTTER_KEY_mabovedot 0x1001e41 +#define CLUTTER_KEY_Pabovedot 0x1001e56 +#define CLUTTER_KEY_pabovedot 0x1001e57 +#define CLUTTER_KEY_Sabovedot 0x1001e60 +#define CLUTTER_KEY_sabovedot 0x1001e61 +#define CLUTTER_KEY_Tabovedot 0x1001e6a +#define CLUTTER_KEY_tabovedot 0x1001e6b +#define CLUTTER_KEY_Wgrave 0x1001e80 +#define CLUTTER_KEY_wgrave 0x1001e81 +#define CLUTTER_KEY_Wacute 0x1001e82 +#define CLUTTER_KEY_wacute 0x1001e83 +#define CLUTTER_KEY_Wdiaeresis 0x1001e84 +#define CLUTTER_KEY_wdiaeresis 0x1001e85 +#define CLUTTER_KEY_Ygrave 0x1001ef2 +#define CLUTTER_KEY_ygrave 0x1001ef3 +#define CLUTTER_KEY_OE 0x13bc +#define CLUTTER_KEY_oe 0x13bd +#define CLUTTER_KEY_Ydiaeresis 0x13be +#define CLUTTER_KEY_overline 0x47e +#define CLUTTER_KEY_kana_fullstop 0x4a1 +#define CLUTTER_KEY_kana_openingbracket 0x4a2 +#define CLUTTER_KEY_kana_closingbracket 0x4a3 +#define CLUTTER_KEY_kana_comma 0x4a4 +#define CLUTTER_KEY_kana_conjunctive 0x4a5 +#define CLUTTER_KEY_kana_middledot 0x4a5 +#define CLUTTER_KEY_kana_WO 0x4a6 +#define CLUTTER_KEY_kana_a 0x4a7 +#define CLUTTER_KEY_kana_i 0x4a8 +#define CLUTTER_KEY_kana_u 0x4a9 +#define CLUTTER_KEY_kana_e 0x4aa +#define CLUTTER_KEY_kana_o 0x4ab +#define CLUTTER_KEY_kana_ya 0x4ac +#define CLUTTER_KEY_kana_yu 0x4ad +#define CLUTTER_KEY_kana_yo 0x4ae +#define CLUTTER_KEY_kana_tsu 0x4af +#define CLUTTER_KEY_kana_tu 0x4af +#define CLUTTER_KEY_prolongedsound 0x4b0 +#define CLUTTER_KEY_kana_A 0x4b1 +#define CLUTTER_KEY_kana_I 0x4b2 +#define CLUTTER_KEY_kana_U 0x4b3 +#define CLUTTER_KEY_kana_E 0x4b4 +#define CLUTTER_KEY_kana_O 0x4b5 +#define CLUTTER_KEY_kana_KA 0x4b6 +#define CLUTTER_KEY_kana_KI 0x4b7 +#define CLUTTER_KEY_kana_KU 0x4b8 +#define CLUTTER_KEY_kana_KE 0x4b9 +#define CLUTTER_KEY_kana_KO 0x4ba +#define CLUTTER_KEY_kana_SA 0x4bb +#define CLUTTER_KEY_kana_SHI 0x4bc +#define CLUTTER_KEY_kana_SU 0x4bd +#define CLUTTER_KEY_kana_SE 0x4be +#define CLUTTER_KEY_kana_SO 0x4bf +#define CLUTTER_KEY_kana_TA 0x4c0 +#define CLUTTER_KEY_kana_CHI 0x4c1 +#define CLUTTER_KEY_kana_TI 0x4c1 +#define CLUTTER_KEY_kana_TSU 0x4c2 +#define CLUTTER_KEY_kana_TU 0x4c2 +#define CLUTTER_KEY_kana_TE 0x4c3 +#define CLUTTER_KEY_kana_TO 0x4c4 +#define CLUTTER_KEY_kana_NA 0x4c5 +#define CLUTTER_KEY_kana_NI 0x4c6 +#define CLUTTER_KEY_kana_NU 0x4c7 +#define CLUTTER_KEY_kana_NE 0x4c8 +#define CLUTTER_KEY_kana_NO 0x4c9 +#define CLUTTER_KEY_kana_HA 0x4ca +#define CLUTTER_KEY_kana_HI 0x4cb +#define CLUTTER_KEY_kana_FU 0x4cc +#define CLUTTER_KEY_kana_HU 0x4cc +#define CLUTTER_KEY_kana_HE 0x4cd +#define CLUTTER_KEY_kana_HO 0x4ce +#define CLUTTER_KEY_kana_MA 0x4cf +#define CLUTTER_KEY_kana_MI 0x4d0 +#define CLUTTER_KEY_kana_MU 0x4d1 +#define CLUTTER_KEY_kana_ME 0x4d2 +#define CLUTTER_KEY_kana_MO 0x4d3 +#define CLUTTER_KEY_kana_YA 0x4d4 +#define CLUTTER_KEY_kana_YU 0x4d5 +#define CLUTTER_KEY_kana_YO 0x4d6 +#define CLUTTER_KEY_kana_RA 0x4d7 +#define CLUTTER_KEY_kana_RI 0x4d8 +#define CLUTTER_KEY_kana_RU 0x4d9 +#define CLUTTER_KEY_kana_RE 0x4da +#define CLUTTER_KEY_kana_RO 0x4db +#define CLUTTER_KEY_kana_WA 0x4dc +#define CLUTTER_KEY_kana_N 0x4dd +#define CLUTTER_KEY_voicedsound 0x4de +#define CLUTTER_KEY_semivoicedsound 0x4df +#define CLUTTER_KEY_kana_switch 0xff7e +#define CLUTTER_KEY_Farsi_0 0x10006f0 +#define CLUTTER_KEY_Farsi_1 0x10006f1 +#define CLUTTER_KEY_Farsi_2 0x10006f2 +#define CLUTTER_KEY_Farsi_3 0x10006f3 +#define CLUTTER_KEY_Farsi_4 0x10006f4 +#define CLUTTER_KEY_Farsi_5 0x10006f5 +#define CLUTTER_KEY_Farsi_6 0x10006f6 +#define CLUTTER_KEY_Farsi_7 0x10006f7 +#define CLUTTER_KEY_Farsi_8 0x10006f8 +#define CLUTTER_KEY_Farsi_9 0x10006f9 +#define CLUTTER_KEY_Arabic_percent 0x100066a +#define CLUTTER_KEY_Arabic_superscript_alef 0x1000670 +#define CLUTTER_KEY_Arabic_tteh 0x1000679 +#define CLUTTER_KEY_Arabic_peh 0x100067e +#define CLUTTER_KEY_Arabic_tcheh 0x1000686 +#define CLUTTER_KEY_Arabic_ddal 0x1000688 +#define CLUTTER_KEY_Arabic_rreh 0x1000691 +#define CLUTTER_KEY_Arabic_comma 0x5ac +#define CLUTTER_KEY_Arabic_fullstop 0x10006d4 +#define CLUTTER_KEY_Arabic_0 0x1000660 +#define CLUTTER_KEY_Arabic_1 0x1000661 +#define CLUTTER_KEY_Arabic_2 0x1000662 +#define CLUTTER_KEY_Arabic_3 0x1000663 +#define CLUTTER_KEY_Arabic_4 0x1000664 +#define CLUTTER_KEY_Arabic_5 0x1000665 +#define CLUTTER_KEY_Arabic_6 0x1000666 +#define CLUTTER_KEY_Arabic_7 0x1000667 +#define CLUTTER_KEY_Arabic_8 0x1000668 +#define CLUTTER_KEY_Arabic_9 0x1000669 +#define CLUTTER_KEY_Arabic_semicolon 0x5bb +#define CLUTTER_KEY_Arabic_question_mark 0x5bf +#define CLUTTER_KEY_Arabic_hamza 0x5c1 +#define CLUTTER_KEY_Arabic_maddaonalef 0x5c2 +#define CLUTTER_KEY_Arabic_hamzaonalef 0x5c3 +#define CLUTTER_KEY_Arabic_hamzaonwaw 0x5c4 +#define CLUTTER_KEY_Arabic_hamzaunderalef 0x5c5 +#define CLUTTER_KEY_Arabic_hamzaonyeh 0x5c6 +#define CLUTTER_KEY_Arabic_alef 0x5c7 +#define CLUTTER_KEY_Arabic_beh 0x5c8 +#define CLUTTER_KEY_Arabic_tehmarbuta 0x5c9 +#define CLUTTER_KEY_Arabic_teh 0x5ca +#define CLUTTER_KEY_Arabic_theh 0x5cb +#define CLUTTER_KEY_Arabic_jeem 0x5cc +#define CLUTTER_KEY_Arabic_hah 0x5cd +#define CLUTTER_KEY_Arabic_khah 0x5ce +#define CLUTTER_KEY_Arabic_dal 0x5cf +#define CLUTTER_KEY_Arabic_thal 0x5d0 +#define CLUTTER_KEY_Arabic_ra 0x5d1 +#define CLUTTER_KEY_Arabic_zain 0x5d2 +#define CLUTTER_KEY_Arabic_seen 0x5d3 +#define CLUTTER_KEY_Arabic_sheen 0x5d4 +#define CLUTTER_KEY_Arabic_sad 0x5d5 +#define CLUTTER_KEY_Arabic_dad 0x5d6 +#define CLUTTER_KEY_Arabic_tah 0x5d7 +#define CLUTTER_KEY_Arabic_zah 0x5d8 +#define CLUTTER_KEY_Arabic_ain 0x5d9 +#define CLUTTER_KEY_Arabic_ghain 0x5da +#define CLUTTER_KEY_Arabic_tatweel 0x5e0 +#define CLUTTER_KEY_Arabic_feh 0x5e1 +#define CLUTTER_KEY_Arabic_qaf 0x5e2 +#define CLUTTER_KEY_Arabic_kaf 0x5e3 +#define CLUTTER_KEY_Arabic_lam 0x5e4 +#define CLUTTER_KEY_Arabic_meem 0x5e5 +#define CLUTTER_KEY_Arabic_noon 0x5e6 +#define CLUTTER_KEY_Arabic_ha 0x5e7 +#define CLUTTER_KEY_Arabic_heh 0x5e7 +#define CLUTTER_KEY_Arabic_waw 0x5e8 +#define CLUTTER_KEY_Arabic_alefmaksura 0x5e9 +#define CLUTTER_KEY_Arabic_yeh 0x5ea +#define CLUTTER_KEY_Arabic_fathatan 0x5eb +#define CLUTTER_KEY_Arabic_dammatan 0x5ec +#define CLUTTER_KEY_Arabic_kasratan 0x5ed +#define CLUTTER_KEY_Arabic_fatha 0x5ee +#define CLUTTER_KEY_Arabic_damma 0x5ef +#define CLUTTER_KEY_Arabic_kasra 0x5f0 +#define CLUTTER_KEY_Arabic_shadda 0x5f1 +#define CLUTTER_KEY_Arabic_sukun 0x5f2 +#define CLUTTER_KEY_Arabic_madda_above 0x1000653 +#define CLUTTER_KEY_Arabic_hamza_above 0x1000654 +#define CLUTTER_KEY_Arabic_hamza_below 0x1000655 +#define CLUTTER_KEY_Arabic_jeh 0x1000698 +#define CLUTTER_KEY_Arabic_veh 0x10006a4 +#define CLUTTER_KEY_Arabic_keheh 0x10006a9 +#define CLUTTER_KEY_Arabic_gaf 0x10006af +#define CLUTTER_KEY_Arabic_noon_ghunna 0x10006ba +#define CLUTTER_KEY_Arabic_heh_doachashmee 0x10006be +#define CLUTTER_KEY_Farsi_yeh 0x10006cc +#define CLUTTER_KEY_Arabic_farsi_yeh 0x10006cc +#define CLUTTER_KEY_Arabic_yeh_baree 0x10006d2 +#define CLUTTER_KEY_Arabic_heh_goal 0x10006c1 +#define CLUTTER_KEY_Arabic_switch 0xff7e +#define CLUTTER_KEY_Cyrillic_GHE_bar 0x1000492 +#define CLUTTER_KEY_Cyrillic_ghe_bar 0x1000493 +#define CLUTTER_KEY_Cyrillic_ZHE_descender 0x1000496 +#define CLUTTER_KEY_Cyrillic_zhe_descender 0x1000497 +#define CLUTTER_KEY_Cyrillic_KA_descender 0x100049a +#define CLUTTER_KEY_Cyrillic_ka_descender 0x100049b +#define CLUTTER_KEY_Cyrillic_KA_vertstroke 0x100049c +#define CLUTTER_KEY_Cyrillic_ka_vertstroke 0x100049d +#define CLUTTER_KEY_Cyrillic_EN_descender 0x10004a2 +#define CLUTTER_KEY_Cyrillic_en_descender 0x10004a3 +#define CLUTTER_KEY_Cyrillic_U_straight 0x10004ae +#define CLUTTER_KEY_Cyrillic_u_straight 0x10004af +#define CLUTTER_KEY_Cyrillic_U_straight_bar 0x10004b0 +#define CLUTTER_KEY_Cyrillic_u_straight_bar 0x10004b1 +#define CLUTTER_KEY_Cyrillic_HA_descender 0x10004b2 +#define CLUTTER_KEY_Cyrillic_ha_descender 0x10004b3 +#define CLUTTER_KEY_Cyrillic_CHE_descender 0x10004b6 +#define CLUTTER_KEY_Cyrillic_che_descender 0x10004b7 +#define CLUTTER_KEY_Cyrillic_CHE_vertstroke 0x10004b8 +#define CLUTTER_KEY_Cyrillic_che_vertstroke 0x10004b9 +#define CLUTTER_KEY_Cyrillic_SHHA 0x10004ba +#define CLUTTER_KEY_Cyrillic_shha 0x10004bb +#define CLUTTER_KEY_Cyrillic_SCHWA 0x10004d8 +#define CLUTTER_KEY_Cyrillic_schwa 0x10004d9 +#define CLUTTER_KEY_Cyrillic_I_macron 0x10004e2 +#define CLUTTER_KEY_Cyrillic_i_macron 0x10004e3 +#define CLUTTER_KEY_Cyrillic_O_bar 0x10004e8 +#define CLUTTER_KEY_Cyrillic_o_bar 0x10004e9 +#define CLUTTER_KEY_Cyrillic_U_macron 0x10004ee +#define CLUTTER_KEY_Cyrillic_u_macron 0x10004ef +#define CLUTTER_KEY_Serbian_dje 0x6a1 +#define CLUTTER_KEY_Macedonia_gje 0x6a2 +#define CLUTTER_KEY_Cyrillic_io 0x6a3 +#define CLUTTER_KEY_Ukrainian_ie 0x6a4 +#define CLUTTER_KEY_Ukranian_je 0x6a4 +#define CLUTTER_KEY_Macedonia_dse 0x6a5 +#define CLUTTER_KEY_Ukrainian_i 0x6a6 +#define CLUTTER_KEY_Ukranian_i 0x6a6 +#define CLUTTER_KEY_Ukrainian_yi 0x6a7 +#define CLUTTER_KEY_Ukranian_yi 0x6a7 +#define CLUTTER_KEY_Cyrillic_je 0x6a8 +#define CLUTTER_KEY_Serbian_je 0x6a8 +#define CLUTTER_KEY_Cyrillic_lje 0x6a9 +#define CLUTTER_KEY_Serbian_lje 0x6a9 +#define CLUTTER_KEY_Cyrillic_nje 0x6aa +#define CLUTTER_KEY_Serbian_nje 0x6aa +#define CLUTTER_KEY_Serbian_tshe 0x6ab +#define CLUTTER_KEY_Macedonia_kje 0x6ac +#define CLUTTER_KEY_Ukrainian_ghe_with_upturn 0x6ad +#define CLUTTER_KEY_Byelorussian_shortu 0x6ae +#define CLUTTER_KEY_Cyrillic_dzhe 0x6af +#define CLUTTER_KEY_Serbian_dze 0x6af +#define CLUTTER_KEY_numerosign 0x6b0 +#define CLUTTER_KEY_Serbian_DJE 0x6b1 +#define CLUTTER_KEY_Macedonia_GJE 0x6b2 +#define CLUTTER_KEY_Cyrillic_IO 0x6b3 +#define CLUTTER_KEY_Ukrainian_IE 0x6b4 +#define CLUTTER_KEY_Ukranian_JE 0x6b4 +#define CLUTTER_KEY_Macedonia_DSE 0x6b5 +#define CLUTTER_KEY_Ukrainian_I 0x6b6 +#define CLUTTER_KEY_Ukranian_I 0x6b6 +#define CLUTTER_KEY_Ukrainian_YI 0x6b7 +#define CLUTTER_KEY_Ukranian_YI 0x6b7 +#define CLUTTER_KEY_Cyrillic_JE 0x6b8 +#define CLUTTER_KEY_Serbian_JE 0x6b8 +#define CLUTTER_KEY_Cyrillic_LJE 0x6b9 +#define CLUTTER_KEY_Serbian_LJE 0x6b9 +#define CLUTTER_KEY_Cyrillic_NJE 0x6ba +#define CLUTTER_KEY_Serbian_NJE 0x6ba +#define CLUTTER_KEY_Serbian_TSHE 0x6bb +#define CLUTTER_KEY_Macedonia_KJE 0x6bc +#define CLUTTER_KEY_Ukrainian_GHE_WITH_UPTURN 0x6bd +#define CLUTTER_KEY_Byelorussian_SHORTU 0x6be +#define CLUTTER_KEY_Cyrillic_DZHE 0x6bf +#define CLUTTER_KEY_Serbian_DZE 0x6bf +#define CLUTTER_KEY_Cyrillic_yu 0x6c0 +#define CLUTTER_KEY_Cyrillic_a 0x6c1 +#define CLUTTER_KEY_Cyrillic_be 0x6c2 +#define CLUTTER_KEY_Cyrillic_tse 0x6c3 +#define CLUTTER_KEY_Cyrillic_de 0x6c4 +#define CLUTTER_KEY_Cyrillic_ie 0x6c5 +#define CLUTTER_KEY_Cyrillic_ef 0x6c6 +#define CLUTTER_KEY_Cyrillic_ghe 0x6c7 +#define CLUTTER_KEY_Cyrillic_ha 0x6c8 +#define CLUTTER_KEY_Cyrillic_i 0x6c9 +#define CLUTTER_KEY_Cyrillic_shorti 0x6ca +#define CLUTTER_KEY_Cyrillic_ka 0x6cb +#define CLUTTER_KEY_Cyrillic_el 0x6cc +#define CLUTTER_KEY_Cyrillic_em 0x6cd +#define CLUTTER_KEY_Cyrillic_en 0x6ce +#define CLUTTER_KEY_Cyrillic_o 0x6cf +#define CLUTTER_KEY_Cyrillic_pe 0x6d0 +#define CLUTTER_KEY_Cyrillic_ya 0x6d1 +#define CLUTTER_KEY_Cyrillic_er 0x6d2 +#define CLUTTER_KEY_Cyrillic_es 0x6d3 +#define CLUTTER_KEY_Cyrillic_te 0x6d4 +#define CLUTTER_KEY_Cyrillic_u 0x6d5 +#define CLUTTER_KEY_Cyrillic_zhe 0x6d6 +#define CLUTTER_KEY_Cyrillic_ve 0x6d7 +#define CLUTTER_KEY_Cyrillic_softsign 0x6d8 +#define CLUTTER_KEY_Cyrillic_yeru 0x6d9 +#define CLUTTER_KEY_Cyrillic_ze 0x6da +#define CLUTTER_KEY_Cyrillic_sha 0x6db +#define CLUTTER_KEY_Cyrillic_e 0x6dc +#define CLUTTER_KEY_Cyrillic_shcha 0x6dd +#define CLUTTER_KEY_Cyrillic_che 0x6de +#define CLUTTER_KEY_Cyrillic_hardsign 0x6df +#define CLUTTER_KEY_Cyrillic_YU 0x6e0 +#define CLUTTER_KEY_Cyrillic_A 0x6e1 +#define CLUTTER_KEY_Cyrillic_BE 0x6e2 +#define CLUTTER_KEY_Cyrillic_TSE 0x6e3 +#define CLUTTER_KEY_Cyrillic_DE 0x6e4 +#define CLUTTER_KEY_Cyrillic_IE 0x6e5 +#define CLUTTER_KEY_Cyrillic_EF 0x6e6 +#define CLUTTER_KEY_Cyrillic_GHE 0x6e7 +#define CLUTTER_KEY_Cyrillic_HA 0x6e8 +#define CLUTTER_KEY_Cyrillic_I 0x6e9 +#define CLUTTER_KEY_Cyrillic_SHORTI 0x6ea +#define CLUTTER_KEY_Cyrillic_KA 0x6eb +#define CLUTTER_KEY_Cyrillic_EL 0x6ec +#define CLUTTER_KEY_Cyrillic_EM 0x6ed +#define CLUTTER_KEY_Cyrillic_EN 0x6ee +#define CLUTTER_KEY_Cyrillic_O 0x6ef +#define CLUTTER_KEY_Cyrillic_PE 0x6f0 +#define CLUTTER_KEY_Cyrillic_YA 0x6f1 +#define CLUTTER_KEY_Cyrillic_ER 0x6f2 +#define CLUTTER_KEY_Cyrillic_ES 0x6f3 +#define CLUTTER_KEY_Cyrillic_TE 0x6f4 +#define CLUTTER_KEY_Cyrillic_U 0x6f5 +#define CLUTTER_KEY_Cyrillic_ZHE 0x6f6 +#define CLUTTER_KEY_Cyrillic_VE 0x6f7 +#define CLUTTER_KEY_Cyrillic_SOFTSIGN 0x6f8 +#define CLUTTER_KEY_Cyrillic_YERU 0x6f9 +#define CLUTTER_KEY_Cyrillic_ZE 0x6fa +#define CLUTTER_KEY_Cyrillic_SHA 0x6fb +#define CLUTTER_KEY_Cyrillic_E 0x6fc +#define CLUTTER_KEY_Cyrillic_SHCHA 0x6fd +#define CLUTTER_KEY_Cyrillic_CHE 0x6fe +#define CLUTTER_KEY_Cyrillic_HARDSIGN 0x6ff +#define CLUTTER_KEY_Greek_ALPHAaccent 0x7a1 +#define CLUTTER_KEY_Greek_EPSILONaccent 0x7a2 +#define CLUTTER_KEY_Greek_ETAaccent 0x7a3 +#define CLUTTER_KEY_Greek_IOTAaccent 0x7a4 +#define CLUTTER_KEY_Greek_IOTAdieresis 0x7a5 +#define CLUTTER_KEY_Greek_IOTAdiaeresis 0x7a5 +#define CLUTTER_KEY_Greek_OMICRONaccent 0x7a7 +#define CLUTTER_KEY_Greek_UPSILONaccent 0x7a8 +#define CLUTTER_KEY_Greek_UPSILONdieresis 0x7a9 +#define CLUTTER_KEY_Greek_OMEGAaccent 0x7ab +#define CLUTTER_KEY_Greek_accentdieresis 0x7ae +#define CLUTTER_KEY_Greek_horizbar 0x7af +#define CLUTTER_KEY_Greek_alphaaccent 0x7b1 +#define CLUTTER_KEY_Greek_epsilonaccent 0x7b2 +#define CLUTTER_KEY_Greek_etaaccent 0x7b3 +#define CLUTTER_KEY_Greek_iotaaccent 0x7b4 +#define CLUTTER_KEY_Greek_iotadieresis 0x7b5 +#define CLUTTER_KEY_Greek_iotaaccentdieresis 0x7b6 +#define CLUTTER_KEY_Greek_omicronaccent 0x7b7 +#define CLUTTER_KEY_Greek_upsilonaccent 0x7b8 +#define CLUTTER_KEY_Greek_upsilondieresis 0x7b9 +#define CLUTTER_KEY_Greek_upsilonaccentdieresis 0x7ba +#define CLUTTER_KEY_Greek_omegaaccent 0x7bb +#define CLUTTER_KEY_Greek_ALPHA 0x7c1 +#define CLUTTER_KEY_Greek_BETA 0x7c2 +#define CLUTTER_KEY_Greek_GAMMA 0x7c3 +#define CLUTTER_KEY_Greek_DELTA 0x7c4 +#define CLUTTER_KEY_Greek_EPSILON 0x7c5 +#define CLUTTER_KEY_Greek_ZETA 0x7c6 +#define CLUTTER_KEY_Greek_ETA 0x7c7 +#define CLUTTER_KEY_Greek_THETA 0x7c8 +#define CLUTTER_KEY_Greek_IOTA 0x7c9 +#define CLUTTER_KEY_Greek_KAPPA 0x7ca +#define CLUTTER_KEY_Greek_LAMDA 0x7cb +#define CLUTTER_KEY_Greek_LAMBDA 0x7cb +#define CLUTTER_KEY_Greek_MU 0x7cc +#define CLUTTER_KEY_Greek_NU 0x7cd +#define CLUTTER_KEY_Greek_XI 0x7ce +#define CLUTTER_KEY_Greek_OMICRON 0x7cf +#define CLUTTER_KEY_Greek_PI 0x7d0 +#define CLUTTER_KEY_Greek_RHO 0x7d1 +#define CLUTTER_KEY_Greek_SIGMA 0x7d2 +#define CLUTTER_KEY_Greek_TAU 0x7d4 +#define CLUTTER_KEY_Greek_UPSILON 0x7d5 +#define CLUTTER_KEY_Greek_PHI 0x7d6 +#define CLUTTER_KEY_Greek_CHI 0x7d7 +#define CLUTTER_KEY_Greek_PSI 0x7d8 +#define CLUTTER_KEY_Greek_OMEGA 0x7d9 +#define CLUTTER_KEY_Greek_alpha 0x7e1 +#define CLUTTER_KEY_Greek_beta 0x7e2 +#define CLUTTER_KEY_Greek_gamma 0x7e3 +#define CLUTTER_KEY_Greek_delta 0x7e4 +#define CLUTTER_KEY_Greek_epsilon 0x7e5 +#define CLUTTER_KEY_Greek_zeta 0x7e6 +#define CLUTTER_KEY_Greek_eta 0x7e7 +#define CLUTTER_KEY_Greek_theta 0x7e8 +#define CLUTTER_KEY_Greek_iota 0x7e9 +#define CLUTTER_KEY_Greek_kappa 0x7ea +#define CLUTTER_KEY_Greek_lamda 0x7eb +#define CLUTTER_KEY_Greek_lambda 0x7eb +#define CLUTTER_KEY_Greek_mu 0x7ec +#define CLUTTER_KEY_Greek_nu 0x7ed +#define CLUTTER_KEY_Greek_xi 0x7ee +#define CLUTTER_KEY_Greek_omicron 0x7ef +#define CLUTTER_KEY_Greek_pi 0x7f0 +#define CLUTTER_KEY_Greek_rho 0x7f1 +#define CLUTTER_KEY_Greek_sigma 0x7f2 +#define CLUTTER_KEY_Greek_finalsmallsigma 0x7f3 +#define CLUTTER_KEY_Greek_tau 0x7f4 +#define CLUTTER_KEY_Greek_upsilon 0x7f5 +#define CLUTTER_KEY_Greek_phi 0x7f6 +#define CLUTTER_KEY_Greek_chi 0x7f7 +#define CLUTTER_KEY_Greek_psi 0x7f8 +#define CLUTTER_KEY_Greek_omega 0x7f9 +#define CLUTTER_KEY_Greek_switch 0xff7e +#define CLUTTER_KEY_leftradical 0x8a1 +#define CLUTTER_KEY_topleftradical 0x8a2 +#define CLUTTER_KEY_horizconnector 0x8a3 +#define CLUTTER_KEY_topintegral 0x8a4 +#define CLUTTER_KEY_botintegral 0x8a5 +#define CLUTTER_KEY_vertconnector 0x8a6 +#define CLUTTER_KEY_topleftsqbracket 0x8a7 +#define CLUTTER_KEY_botleftsqbracket 0x8a8 +#define CLUTTER_KEY_toprightsqbracket 0x8a9 +#define CLUTTER_KEY_botrightsqbracket 0x8aa +#define CLUTTER_KEY_topleftparens 0x8ab +#define CLUTTER_KEY_botleftparens 0x8ac +#define CLUTTER_KEY_toprightparens 0x8ad +#define CLUTTER_KEY_botrightparens 0x8ae +#define CLUTTER_KEY_leftmiddlecurlybrace 0x8af +#define CLUTTER_KEY_rightmiddlecurlybrace 0x8b0 +#define CLUTTER_KEY_topleftsummation 0x8b1 +#define CLUTTER_KEY_botleftsummation 0x8b2 +#define CLUTTER_KEY_topvertsummationconnector 0x8b3 +#define CLUTTER_KEY_botvertsummationconnector 0x8b4 +#define CLUTTER_KEY_toprightsummation 0x8b5 +#define CLUTTER_KEY_botrightsummation 0x8b6 +#define CLUTTER_KEY_rightmiddlesummation 0x8b7 +#define CLUTTER_KEY_lessthanequal 0x8bc +#define CLUTTER_KEY_notequal 0x8bd +#define CLUTTER_KEY_greaterthanequal 0x8be +#define CLUTTER_KEY_integral 0x8bf +#define CLUTTER_KEY_therefore 0x8c0 +#define CLUTTER_KEY_variation 0x8c1 +#define CLUTTER_KEY_infinity 0x8c2 +#define CLUTTER_KEY_nabla 0x8c5 +#define CLUTTER_KEY_approximate 0x8c8 +#define CLUTTER_KEY_similarequal 0x8c9 +#define CLUTTER_KEY_ifonlyif 0x8cd +#define CLUTTER_KEY_implies 0x8ce +#define CLUTTER_KEY_identical 0x8cf +#define CLUTTER_KEY_radical 0x8d6 +#define CLUTTER_KEY_includedin 0x8da +#define CLUTTER_KEY_includes 0x8db +#define CLUTTER_KEY_intersection 0x8dc +#define CLUTTER_KEY_union 0x8dd +#define CLUTTER_KEY_logicaland 0x8de +#define CLUTTER_KEY_logicalor 0x8df +#define CLUTTER_KEY_partialderivative 0x8ef +#define CLUTTER_KEY_function 0x8f6 +#define CLUTTER_KEY_leftarrow 0x8fb +#define CLUTTER_KEY_uparrow 0x8fc +#define CLUTTER_KEY_rightarrow 0x8fd +#define CLUTTER_KEY_downarrow 0x8fe +#define CLUTTER_KEY_blank 0x9df +#define CLUTTER_KEY_soliddiamond 0x9e0 +#define CLUTTER_KEY_checkerboard 0x9e1 +#define CLUTTER_KEY_ht 0x9e2 +#define CLUTTER_KEY_ff 0x9e3 +#define CLUTTER_KEY_cr 0x9e4 +#define CLUTTER_KEY_lf 0x9e5 +#define CLUTTER_KEY_nl 0x9e8 +#define CLUTTER_KEY_vt 0x9e9 +#define CLUTTER_KEY_lowrightcorner 0x9ea +#define CLUTTER_KEY_uprightcorner 0x9eb +#define CLUTTER_KEY_upleftcorner 0x9ec +#define CLUTTER_KEY_lowleftcorner 0x9ed +#define CLUTTER_KEY_crossinglines 0x9ee +#define CLUTTER_KEY_horizlinescan1 0x9ef +#define CLUTTER_KEY_horizlinescan3 0x9f0 +#define CLUTTER_KEY_horizlinescan5 0x9f1 +#define CLUTTER_KEY_horizlinescan7 0x9f2 +#define CLUTTER_KEY_horizlinescan9 0x9f3 +#define CLUTTER_KEY_leftt 0x9f4 +#define CLUTTER_KEY_rightt 0x9f5 +#define CLUTTER_KEY_bott 0x9f6 +#define CLUTTER_KEY_topt 0x9f7 +#define CLUTTER_KEY_vertbar 0x9f8 +#define CLUTTER_KEY_emspace 0xaa1 +#define CLUTTER_KEY_enspace 0xaa2 +#define CLUTTER_KEY_em3space 0xaa3 +#define CLUTTER_KEY_em4space 0xaa4 +#define CLUTTER_KEY_digitspace 0xaa5 +#define CLUTTER_KEY_punctspace 0xaa6 +#define CLUTTER_KEY_thinspace 0xaa7 +#define CLUTTER_KEY_hairspace 0xaa8 +#define CLUTTER_KEY_emdash 0xaa9 +#define CLUTTER_KEY_endash 0xaaa +#define CLUTTER_KEY_signifblank 0xaac +#define CLUTTER_KEY_ellipsis 0xaae +#define CLUTTER_KEY_doubbaselinedot 0xaaf +#define CLUTTER_KEY_onethird 0xab0 +#define CLUTTER_KEY_twothirds 0xab1 +#define CLUTTER_KEY_onefifth 0xab2 +#define CLUTTER_KEY_twofifths 0xab3 +#define CLUTTER_KEY_threefifths 0xab4 +#define CLUTTER_KEY_fourfifths 0xab5 +#define CLUTTER_KEY_onesixth 0xab6 +#define CLUTTER_KEY_fivesixths 0xab7 +#define CLUTTER_KEY_careof 0xab8 +#define CLUTTER_KEY_figdash 0xabb +#define CLUTTER_KEY_leftanglebracket 0xabc +#define CLUTTER_KEY_decimalpoint 0xabd +#define CLUTTER_KEY_rightanglebracket 0xabe +#define CLUTTER_KEY_marker 0xabf +#define CLUTTER_KEY_oneeighth 0xac3 +#define CLUTTER_KEY_threeeighths 0xac4 +#define CLUTTER_KEY_fiveeighths 0xac5 +#define CLUTTER_KEY_seveneighths 0xac6 +#define CLUTTER_KEY_trademark 0xac9 +#define CLUTTER_KEY_signaturemark 0xaca +#define CLUTTER_KEY_trademarkincircle 0xacb +#define CLUTTER_KEY_leftopentriangle 0xacc +#define CLUTTER_KEY_rightopentriangle 0xacd +#define CLUTTER_KEY_emopencircle 0xace +#define CLUTTER_KEY_emopenrectangle 0xacf +#define CLUTTER_KEY_leftsinglequotemark 0xad0 +#define CLUTTER_KEY_rightsinglequotemark 0xad1 +#define CLUTTER_KEY_leftdoublequotemark 0xad2 +#define CLUTTER_KEY_rightdoublequotemark 0xad3 +#define CLUTTER_KEY_prescription 0xad4 +#define CLUTTER_KEY_permille 0xad5 +#define CLUTTER_KEY_minutes 0xad6 +#define CLUTTER_KEY_seconds 0xad7 +#define CLUTTER_KEY_latincross 0xad9 +#define CLUTTER_KEY_hexagram 0xada +#define CLUTTER_KEY_filledrectbullet 0xadb +#define CLUTTER_KEY_filledlefttribullet 0xadc +#define CLUTTER_KEY_filledrighttribullet 0xadd +#define CLUTTER_KEY_emfilledcircle 0xade +#define CLUTTER_KEY_emfilledrect 0xadf +#define CLUTTER_KEY_enopencircbullet 0xae0 +#define CLUTTER_KEY_enopensquarebullet 0xae1 +#define CLUTTER_KEY_openrectbullet 0xae2 +#define CLUTTER_KEY_opentribulletup 0xae3 +#define CLUTTER_KEY_opentribulletdown 0xae4 +#define CLUTTER_KEY_openstar 0xae5 +#define CLUTTER_KEY_enfilledcircbullet 0xae6 +#define CLUTTER_KEY_enfilledsqbullet 0xae7 +#define CLUTTER_KEY_filledtribulletup 0xae8 +#define CLUTTER_KEY_filledtribulletdown 0xae9 +#define CLUTTER_KEY_leftpointer 0xaea +#define CLUTTER_KEY_rightpointer 0xaeb +#define CLUTTER_KEY_club 0xaec +#define CLUTTER_KEY_diamond 0xaed +#define CLUTTER_KEY_heart 0xaee +#define CLUTTER_KEY_maltesecross 0xaf0 +#define CLUTTER_KEY_dagger 0xaf1 +#define CLUTTER_KEY_doubledagger 0xaf2 +#define CLUTTER_KEY_checkmark 0xaf3 +#define CLUTTER_KEY_ballotcross 0xaf4 +#define CLUTTER_KEY_musicalsharp 0xaf5 +#define CLUTTER_KEY_musicalflat 0xaf6 +#define CLUTTER_KEY_malesymbol 0xaf7 +#define CLUTTER_KEY_femalesymbol 0xaf8 +#define CLUTTER_KEY_telephone 0xaf9 +#define CLUTTER_KEY_telephonerecorder 0xafa +#define CLUTTER_KEY_phonographcopyright 0xafb +#define CLUTTER_KEY_caret 0xafc +#define CLUTTER_KEY_singlelowquotemark 0xafd +#define CLUTTER_KEY_doublelowquotemark 0xafe +#define CLUTTER_KEY_cursor 0xaff +#define CLUTTER_KEY_leftcaret 0xba3 +#define CLUTTER_KEY_rightcaret 0xba6 +#define CLUTTER_KEY_downcaret 0xba8 +#define CLUTTER_KEY_upcaret 0xba9 +#define CLUTTER_KEY_overbar 0xbc0 +#define CLUTTER_KEY_downtack 0xbc2 +#define CLUTTER_KEY_upshoe 0xbc3 +#define CLUTTER_KEY_downstile 0xbc4 +#define CLUTTER_KEY_underbar 0xbc6 +#define CLUTTER_KEY_jot 0xbca +#define CLUTTER_KEY_quad 0xbcc +#define CLUTTER_KEY_uptack 0xbce +#define CLUTTER_KEY_circle 0xbcf +#define CLUTTER_KEY_upstile 0xbd3 +#define CLUTTER_KEY_downshoe 0xbd6 +#define CLUTTER_KEY_rightshoe 0xbd8 +#define CLUTTER_KEY_leftshoe 0xbda +#define CLUTTER_KEY_lefttack 0xbdc +#define CLUTTER_KEY_righttack 0xbfc +#define CLUTTER_KEY_hebrew_doublelowline 0xcdf +#define CLUTTER_KEY_hebrew_aleph 0xce0 +#define CLUTTER_KEY_hebrew_bet 0xce1 +#define CLUTTER_KEY_hebrew_beth 0xce1 +#define CLUTTER_KEY_hebrew_gimel 0xce2 +#define CLUTTER_KEY_hebrew_gimmel 0xce2 +#define CLUTTER_KEY_hebrew_dalet 0xce3 +#define CLUTTER_KEY_hebrew_daleth 0xce3 +#define CLUTTER_KEY_hebrew_he 0xce4 +#define CLUTTER_KEY_hebrew_waw 0xce5 +#define CLUTTER_KEY_hebrew_zain 0xce6 +#define CLUTTER_KEY_hebrew_zayin 0xce6 +#define CLUTTER_KEY_hebrew_chet 0xce7 +#define CLUTTER_KEY_hebrew_het 0xce7 +#define CLUTTER_KEY_hebrew_tet 0xce8 +#define CLUTTER_KEY_hebrew_teth 0xce8 +#define CLUTTER_KEY_hebrew_yod 0xce9 +#define CLUTTER_KEY_hebrew_finalkaph 0xcea +#define CLUTTER_KEY_hebrew_kaph 0xceb +#define CLUTTER_KEY_hebrew_lamed 0xcec +#define CLUTTER_KEY_hebrew_finalmem 0xced +#define CLUTTER_KEY_hebrew_mem 0xcee +#define CLUTTER_KEY_hebrew_finalnun 0xcef +#define CLUTTER_KEY_hebrew_nun 0xcf0 +#define CLUTTER_KEY_hebrew_samech 0xcf1 +#define CLUTTER_KEY_hebrew_samekh 0xcf1 +#define CLUTTER_KEY_hebrew_ayin 0xcf2 +#define CLUTTER_KEY_hebrew_finalpe 0xcf3 +#define CLUTTER_KEY_hebrew_pe 0xcf4 +#define CLUTTER_KEY_hebrew_finalzade 0xcf5 +#define CLUTTER_KEY_hebrew_finalzadi 0xcf5 +#define CLUTTER_KEY_hebrew_zade 0xcf6 +#define CLUTTER_KEY_hebrew_zadi 0xcf6 +#define CLUTTER_KEY_hebrew_qoph 0xcf7 +#define CLUTTER_KEY_hebrew_kuf 0xcf7 +#define CLUTTER_KEY_hebrew_resh 0xcf8 +#define CLUTTER_KEY_hebrew_shin 0xcf9 +#define CLUTTER_KEY_hebrew_taw 0xcfa +#define CLUTTER_KEY_hebrew_taf 0xcfa +#define CLUTTER_KEY_Hebrew_switch 0xff7e +#define CLUTTER_KEY_Thai_kokai 0xda1 +#define CLUTTER_KEY_Thai_khokhai 0xda2 +#define CLUTTER_KEY_Thai_khokhuat 0xda3 +#define CLUTTER_KEY_Thai_khokhwai 0xda4 +#define CLUTTER_KEY_Thai_khokhon 0xda5 +#define CLUTTER_KEY_Thai_khorakhang 0xda6 +#define CLUTTER_KEY_Thai_ngongu 0xda7 +#define CLUTTER_KEY_Thai_chochan 0xda8 +#define CLUTTER_KEY_Thai_choching 0xda9 +#define CLUTTER_KEY_Thai_chochang 0xdaa +#define CLUTTER_KEY_Thai_soso 0xdab +#define CLUTTER_KEY_Thai_chochoe 0xdac +#define CLUTTER_KEY_Thai_yoying 0xdad +#define CLUTTER_KEY_Thai_dochada 0xdae +#define CLUTTER_KEY_Thai_topatak 0xdaf +#define CLUTTER_KEY_Thai_thothan 0xdb0 +#define CLUTTER_KEY_Thai_thonangmontho 0xdb1 +#define CLUTTER_KEY_Thai_thophuthao 0xdb2 +#define CLUTTER_KEY_Thai_nonen 0xdb3 +#define CLUTTER_KEY_Thai_dodek 0xdb4 +#define CLUTTER_KEY_Thai_totao 0xdb5 +#define CLUTTER_KEY_Thai_thothung 0xdb6 +#define CLUTTER_KEY_Thai_thothahan 0xdb7 +#define CLUTTER_KEY_Thai_thothong 0xdb8 +#define CLUTTER_KEY_Thai_nonu 0xdb9 +#define CLUTTER_KEY_Thai_bobaimai 0xdba +#define CLUTTER_KEY_Thai_popla 0xdbb +#define CLUTTER_KEY_Thai_phophung 0xdbc +#define CLUTTER_KEY_Thai_fofa 0xdbd +#define CLUTTER_KEY_Thai_phophan 0xdbe +#define CLUTTER_KEY_Thai_fofan 0xdbf +#define CLUTTER_KEY_Thai_phosamphao 0xdc0 +#define CLUTTER_KEY_Thai_moma 0xdc1 +#define CLUTTER_KEY_Thai_yoyak 0xdc2 +#define CLUTTER_KEY_Thai_rorua 0xdc3 +#define CLUTTER_KEY_Thai_ru 0xdc4 +#define CLUTTER_KEY_Thai_loling 0xdc5 +#define CLUTTER_KEY_Thai_lu 0xdc6 +#define CLUTTER_KEY_Thai_wowaen 0xdc7 +#define CLUTTER_KEY_Thai_sosala 0xdc8 +#define CLUTTER_KEY_Thai_sorusi 0xdc9 +#define CLUTTER_KEY_Thai_sosua 0xdca +#define CLUTTER_KEY_Thai_hohip 0xdcb +#define CLUTTER_KEY_Thai_lochula 0xdcc +#define CLUTTER_KEY_Thai_oang 0xdcd +#define CLUTTER_KEY_Thai_honokhuk 0xdce +#define CLUTTER_KEY_Thai_paiyannoi 0xdcf +#define CLUTTER_KEY_Thai_saraa 0xdd0 +#define CLUTTER_KEY_Thai_maihanakat 0xdd1 +#define CLUTTER_KEY_Thai_saraaa 0xdd2 +#define CLUTTER_KEY_Thai_saraam 0xdd3 +#define CLUTTER_KEY_Thai_sarai 0xdd4 +#define CLUTTER_KEY_Thai_saraii 0xdd5 +#define CLUTTER_KEY_Thai_saraue 0xdd6 +#define CLUTTER_KEY_Thai_sarauee 0xdd7 +#define CLUTTER_KEY_Thai_sarau 0xdd8 +#define CLUTTER_KEY_Thai_sarauu 0xdd9 +#define CLUTTER_KEY_Thai_phinthu 0xdda +#define CLUTTER_KEY_Thai_maihanakat_maitho 0xdde +#define CLUTTER_KEY_Thai_baht 0xddf +#define CLUTTER_KEY_Thai_sarae 0xde0 +#define CLUTTER_KEY_Thai_saraae 0xde1 +#define CLUTTER_KEY_Thai_sarao 0xde2 +#define CLUTTER_KEY_Thai_saraaimaimuan 0xde3 +#define CLUTTER_KEY_Thai_saraaimaimalai 0xde4 +#define CLUTTER_KEY_Thai_lakkhangyao 0xde5 +#define CLUTTER_KEY_Thai_maiyamok 0xde6 +#define CLUTTER_KEY_Thai_maitaikhu 0xde7 +#define CLUTTER_KEY_Thai_maiek 0xde8 +#define CLUTTER_KEY_Thai_maitho 0xde9 +#define CLUTTER_KEY_Thai_maitri 0xdea +#define CLUTTER_KEY_Thai_maichattawa 0xdeb +#define CLUTTER_KEY_Thai_thanthakhat 0xdec +#define CLUTTER_KEY_Thai_nikhahit 0xded +#define CLUTTER_KEY_Thai_leksun 0xdf0 +#define CLUTTER_KEY_Thai_leknung 0xdf1 +#define CLUTTER_KEY_Thai_leksong 0xdf2 +#define CLUTTER_KEY_Thai_leksam 0xdf3 +#define CLUTTER_KEY_Thai_leksi 0xdf4 +#define CLUTTER_KEY_Thai_lekha 0xdf5 +#define CLUTTER_KEY_Thai_lekhok 0xdf6 +#define CLUTTER_KEY_Thai_lekchet 0xdf7 +#define CLUTTER_KEY_Thai_lekpaet 0xdf8 +#define CLUTTER_KEY_Thai_lekkao 0xdf9 +#define CLUTTER_KEY_Hangul 0xff31 +#define CLUTTER_KEY_Hangul_Start 0xff32 +#define CLUTTER_KEY_Hangul_End 0xff33 +#define CLUTTER_KEY_Hangul_Hanja 0xff34 +#define CLUTTER_KEY_Hangul_Jamo 0xff35 +#define CLUTTER_KEY_Hangul_Romaja 0xff36 +#define CLUTTER_KEY_Hangul_Codeinput 0xff37 +#define CLUTTER_KEY_Hangul_Jeonja 0xff38 +#define CLUTTER_KEY_Hangul_Banja 0xff39 +#define CLUTTER_KEY_Hangul_PreHanja 0xff3a +#define CLUTTER_KEY_Hangul_PostHanja 0xff3b +#define CLUTTER_KEY_Hangul_SingleCandidate 0xff3c +#define CLUTTER_KEY_Hangul_MultipleCandidate 0xff3d +#define CLUTTER_KEY_Hangul_PreviousCandidate 0xff3e +#define CLUTTER_KEY_Hangul_Special 0xff3f +#define CLUTTER_KEY_Hangul_switch 0xff7e +#define CLUTTER_KEY_Hangul_Kiyeog 0xea1 +#define CLUTTER_KEY_Hangul_SsangKiyeog 0xea2 +#define CLUTTER_KEY_Hangul_KiyeogSios 0xea3 +#define CLUTTER_KEY_Hangul_Nieun 0xea4 +#define CLUTTER_KEY_Hangul_NieunJieuj 0xea5 +#define CLUTTER_KEY_Hangul_NieunHieuh 0xea6 +#define CLUTTER_KEY_Hangul_Dikeud 0xea7 +#define CLUTTER_KEY_Hangul_SsangDikeud 0xea8 +#define CLUTTER_KEY_Hangul_Rieul 0xea9 +#define CLUTTER_KEY_Hangul_RieulKiyeog 0xeaa +#define CLUTTER_KEY_Hangul_RieulMieum 0xeab +#define CLUTTER_KEY_Hangul_RieulPieub 0xeac +#define CLUTTER_KEY_Hangul_RieulSios 0xead +#define CLUTTER_KEY_Hangul_RieulTieut 0xeae +#define CLUTTER_KEY_Hangul_RieulPhieuf 0xeaf +#define CLUTTER_KEY_Hangul_RieulHieuh 0xeb0 +#define CLUTTER_KEY_Hangul_Mieum 0xeb1 +#define CLUTTER_KEY_Hangul_Pieub 0xeb2 +#define CLUTTER_KEY_Hangul_SsangPieub 0xeb3 +#define CLUTTER_KEY_Hangul_PieubSios 0xeb4 +#define CLUTTER_KEY_Hangul_Sios 0xeb5 +#define CLUTTER_KEY_Hangul_SsangSios 0xeb6 +#define CLUTTER_KEY_Hangul_Ieung 0xeb7 +#define CLUTTER_KEY_Hangul_Jieuj 0xeb8 +#define CLUTTER_KEY_Hangul_SsangJieuj 0xeb9 +#define CLUTTER_KEY_Hangul_Cieuc 0xeba +#define CLUTTER_KEY_Hangul_Khieuq 0xebb +#define CLUTTER_KEY_Hangul_Tieut 0xebc +#define CLUTTER_KEY_Hangul_Phieuf 0xebd +#define CLUTTER_KEY_Hangul_Hieuh 0xebe +#define CLUTTER_KEY_Hangul_A 0xebf +#define CLUTTER_KEY_Hangul_AE 0xec0 +#define CLUTTER_KEY_Hangul_YA 0xec1 +#define CLUTTER_KEY_Hangul_YAE 0xec2 +#define CLUTTER_KEY_Hangul_EO 0xec3 +#define CLUTTER_KEY_Hangul_E 0xec4 +#define CLUTTER_KEY_Hangul_YEO 0xec5 +#define CLUTTER_KEY_Hangul_YE 0xec6 +#define CLUTTER_KEY_Hangul_O 0xec7 +#define CLUTTER_KEY_Hangul_WA 0xec8 +#define CLUTTER_KEY_Hangul_WAE 0xec9 +#define CLUTTER_KEY_Hangul_OE 0xeca +#define CLUTTER_KEY_Hangul_YO 0xecb +#define CLUTTER_KEY_Hangul_U 0xecc +#define CLUTTER_KEY_Hangul_WEO 0xecd +#define CLUTTER_KEY_Hangul_WE 0xece +#define CLUTTER_KEY_Hangul_WI 0xecf +#define CLUTTER_KEY_Hangul_YU 0xed0 +#define CLUTTER_KEY_Hangul_EU 0xed1 +#define CLUTTER_KEY_Hangul_YI 0xed2 +#define CLUTTER_KEY_Hangul_I 0xed3 +#define CLUTTER_KEY_Hangul_J_Kiyeog 0xed4 +#define CLUTTER_KEY_Hangul_J_SsangKiyeog 0xed5 +#define CLUTTER_KEY_Hangul_J_KiyeogSios 0xed6 +#define CLUTTER_KEY_Hangul_J_Nieun 0xed7 +#define CLUTTER_KEY_Hangul_J_NieunJieuj 0xed8 +#define CLUTTER_KEY_Hangul_J_NieunHieuh 0xed9 +#define CLUTTER_KEY_Hangul_J_Dikeud 0xeda +#define CLUTTER_KEY_Hangul_J_Rieul 0xedb +#define CLUTTER_KEY_Hangul_J_RieulKiyeog 0xedc +#define CLUTTER_KEY_Hangul_J_RieulMieum 0xedd +#define CLUTTER_KEY_Hangul_J_RieulPieub 0xede +#define CLUTTER_KEY_Hangul_J_RieulSios 0xedf +#define CLUTTER_KEY_Hangul_J_RieulTieut 0xee0 +#define CLUTTER_KEY_Hangul_J_RieulPhieuf 0xee1 +#define CLUTTER_KEY_Hangul_J_RieulHieuh 0xee2 +#define CLUTTER_KEY_Hangul_J_Mieum 0xee3 +#define CLUTTER_KEY_Hangul_J_Pieub 0xee4 +#define CLUTTER_KEY_Hangul_J_PieubSios 0xee5 +#define CLUTTER_KEY_Hangul_J_Sios 0xee6 +#define CLUTTER_KEY_Hangul_J_SsangSios 0xee7 +#define CLUTTER_KEY_Hangul_J_Ieung 0xee8 +#define CLUTTER_KEY_Hangul_J_Jieuj 0xee9 +#define CLUTTER_KEY_Hangul_J_Cieuc 0xeea +#define CLUTTER_KEY_Hangul_J_Khieuq 0xeeb +#define CLUTTER_KEY_Hangul_J_Tieut 0xeec +#define CLUTTER_KEY_Hangul_J_Phieuf 0xeed +#define CLUTTER_KEY_Hangul_J_Hieuh 0xeee +#define CLUTTER_KEY_Hangul_RieulYeorinHieuh 0xeef +#define CLUTTER_KEY_Hangul_SunkyeongeumMieum 0xef0 +#define CLUTTER_KEY_Hangul_SunkyeongeumPieub 0xef1 +#define CLUTTER_KEY_Hangul_PanSios 0xef2 +#define CLUTTER_KEY_Hangul_KkogjiDalrinIeung 0xef3 +#define CLUTTER_KEY_Hangul_SunkyeongeumPhieuf 0xef4 +#define CLUTTER_KEY_Hangul_YeorinHieuh 0xef5 +#define CLUTTER_KEY_Hangul_AraeA 0xef6 +#define CLUTTER_KEY_Hangul_AraeAE 0xef7 +#define CLUTTER_KEY_Hangul_J_PanSios 0xef8 +#define CLUTTER_KEY_Hangul_J_KkogjiDalrinIeung 0xef9 +#define CLUTTER_KEY_Hangul_J_YeorinHieuh 0xefa +#define CLUTTER_KEY_Korean_Won 0xeff +#define CLUTTER_KEY_Armenian_ligature_ew 0x1000587 +#define CLUTTER_KEY_Armenian_full_stop 0x1000589 +#define CLUTTER_KEY_Armenian_verjaket 0x1000589 +#define CLUTTER_KEY_Armenian_separation_mark 0x100055d +#define CLUTTER_KEY_Armenian_but 0x100055d +#define CLUTTER_KEY_Armenian_hyphen 0x100058a +#define CLUTTER_KEY_Armenian_yentamna 0x100058a +#define CLUTTER_KEY_Armenian_exclam 0x100055c +#define CLUTTER_KEY_Armenian_amanak 0x100055c +#define CLUTTER_KEY_Armenian_accent 0x100055b +#define CLUTTER_KEY_Armenian_shesht 0x100055b +#define CLUTTER_KEY_Armenian_question 0x100055e +#define CLUTTER_KEY_Armenian_paruyk 0x100055e +#define CLUTTER_KEY_Armenian_AYB 0x1000531 +#define CLUTTER_KEY_Armenian_ayb 0x1000561 +#define CLUTTER_KEY_Armenian_BEN 0x1000532 +#define CLUTTER_KEY_Armenian_ben 0x1000562 +#define CLUTTER_KEY_Armenian_GIM 0x1000533 +#define CLUTTER_KEY_Armenian_gim 0x1000563 +#define CLUTTER_KEY_Armenian_DA 0x1000534 +#define CLUTTER_KEY_Armenian_da 0x1000564 +#define CLUTTER_KEY_Armenian_YECH 0x1000535 +#define CLUTTER_KEY_Armenian_yech 0x1000565 +#define CLUTTER_KEY_Armenian_ZA 0x1000536 +#define CLUTTER_KEY_Armenian_za 0x1000566 +#define CLUTTER_KEY_Armenian_E 0x1000537 +#define CLUTTER_KEY_Armenian_e 0x1000567 +#define CLUTTER_KEY_Armenian_AT 0x1000538 +#define CLUTTER_KEY_Armenian_at 0x1000568 +#define CLUTTER_KEY_Armenian_TO 0x1000539 +#define CLUTTER_KEY_Armenian_to 0x1000569 +#define CLUTTER_KEY_Armenian_ZHE 0x100053a +#define CLUTTER_KEY_Armenian_zhe 0x100056a +#define CLUTTER_KEY_Armenian_INI 0x100053b +#define CLUTTER_KEY_Armenian_ini 0x100056b +#define CLUTTER_KEY_Armenian_LYUN 0x100053c +#define CLUTTER_KEY_Armenian_lyun 0x100056c +#define CLUTTER_KEY_Armenian_KHE 0x100053d +#define CLUTTER_KEY_Armenian_khe 0x100056d +#define CLUTTER_KEY_Armenian_TSA 0x100053e +#define CLUTTER_KEY_Armenian_tsa 0x100056e +#define CLUTTER_KEY_Armenian_KEN 0x100053f +#define CLUTTER_KEY_Armenian_ken 0x100056f +#define CLUTTER_KEY_Armenian_HO 0x1000540 +#define CLUTTER_KEY_Armenian_ho 0x1000570 +#define CLUTTER_KEY_Armenian_DZA 0x1000541 +#define CLUTTER_KEY_Armenian_dza 0x1000571 +#define CLUTTER_KEY_Armenian_GHAT 0x1000542 +#define CLUTTER_KEY_Armenian_ghat 0x1000572 +#define CLUTTER_KEY_Armenian_TCHE 0x1000543 +#define CLUTTER_KEY_Armenian_tche 0x1000573 +#define CLUTTER_KEY_Armenian_MEN 0x1000544 +#define CLUTTER_KEY_Armenian_men 0x1000574 +#define CLUTTER_KEY_Armenian_HI 0x1000545 +#define CLUTTER_KEY_Armenian_hi 0x1000575 +#define CLUTTER_KEY_Armenian_NU 0x1000546 +#define CLUTTER_KEY_Armenian_nu 0x1000576 +#define CLUTTER_KEY_Armenian_SHA 0x1000547 +#define CLUTTER_KEY_Armenian_sha 0x1000577 +#define CLUTTER_KEY_Armenian_VO 0x1000548 +#define CLUTTER_KEY_Armenian_vo 0x1000578 +#define CLUTTER_KEY_Armenian_CHA 0x1000549 +#define CLUTTER_KEY_Armenian_cha 0x1000579 +#define CLUTTER_KEY_Armenian_PE 0x100054a +#define CLUTTER_KEY_Armenian_pe 0x100057a +#define CLUTTER_KEY_Armenian_JE 0x100054b +#define CLUTTER_KEY_Armenian_je 0x100057b +#define CLUTTER_KEY_Armenian_RA 0x100054c +#define CLUTTER_KEY_Armenian_ra 0x100057c +#define CLUTTER_KEY_Armenian_SE 0x100054d +#define CLUTTER_KEY_Armenian_se 0x100057d +#define CLUTTER_KEY_Armenian_VEV 0x100054e +#define CLUTTER_KEY_Armenian_vev 0x100057e +#define CLUTTER_KEY_Armenian_TYUN 0x100054f +#define CLUTTER_KEY_Armenian_tyun 0x100057f +#define CLUTTER_KEY_Armenian_RE 0x1000550 +#define CLUTTER_KEY_Armenian_re 0x1000580 +#define CLUTTER_KEY_Armenian_TSO 0x1000551 +#define CLUTTER_KEY_Armenian_tso 0x1000581 +#define CLUTTER_KEY_Armenian_VYUN 0x1000552 +#define CLUTTER_KEY_Armenian_vyun 0x1000582 +#define CLUTTER_KEY_Armenian_PYUR 0x1000553 +#define CLUTTER_KEY_Armenian_pyur 0x1000583 +#define CLUTTER_KEY_Armenian_KE 0x1000554 +#define CLUTTER_KEY_Armenian_ke 0x1000584 +#define CLUTTER_KEY_Armenian_O 0x1000555 +#define CLUTTER_KEY_Armenian_o 0x1000585 +#define CLUTTER_KEY_Armenian_FE 0x1000556 +#define CLUTTER_KEY_Armenian_fe 0x1000586 +#define CLUTTER_KEY_Armenian_apostrophe 0x100055a +#define CLUTTER_KEY_Georgian_an 0x10010d0 +#define CLUTTER_KEY_Georgian_ban 0x10010d1 +#define CLUTTER_KEY_Georgian_gan 0x10010d2 +#define CLUTTER_KEY_Georgian_don 0x10010d3 +#define CLUTTER_KEY_Georgian_en 0x10010d4 +#define CLUTTER_KEY_Georgian_vin 0x10010d5 +#define CLUTTER_KEY_Georgian_zen 0x10010d6 +#define CLUTTER_KEY_Georgian_tan 0x10010d7 +#define CLUTTER_KEY_Georgian_in 0x10010d8 +#define CLUTTER_KEY_Georgian_kan 0x10010d9 +#define CLUTTER_KEY_Georgian_las 0x10010da +#define CLUTTER_KEY_Georgian_man 0x10010db +#define CLUTTER_KEY_Georgian_nar 0x10010dc +#define CLUTTER_KEY_Georgian_on 0x10010dd +#define CLUTTER_KEY_Georgian_par 0x10010de +#define CLUTTER_KEY_Georgian_zhar 0x10010df +#define CLUTTER_KEY_Georgian_rae 0x10010e0 +#define CLUTTER_KEY_Georgian_san 0x10010e1 +#define CLUTTER_KEY_Georgian_tar 0x10010e2 +#define CLUTTER_KEY_Georgian_un 0x10010e3 +#define CLUTTER_KEY_Georgian_phar 0x10010e4 +#define CLUTTER_KEY_Georgian_khar 0x10010e5 +#define CLUTTER_KEY_Georgian_ghan 0x10010e6 +#define CLUTTER_KEY_Georgian_qar 0x10010e7 +#define CLUTTER_KEY_Georgian_shin 0x10010e8 +#define CLUTTER_KEY_Georgian_chin 0x10010e9 +#define CLUTTER_KEY_Georgian_can 0x10010ea +#define CLUTTER_KEY_Georgian_jil 0x10010eb +#define CLUTTER_KEY_Georgian_cil 0x10010ec +#define CLUTTER_KEY_Georgian_char 0x10010ed +#define CLUTTER_KEY_Georgian_xan 0x10010ee +#define CLUTTER_KEY_Georgian_jhan 0x10010ef +#define CLUTTER_KEY_Georgian_hae 0x10010f0 +#define CLUTTER_KEY_Georgian_he 0x10010f1 +#define CLUTTER_KEY_Georgian_hie 0x10010f2 +#define CLUTTER_KEY_Georgian_we 0x10010f3 +#define CLUTTER_KEY_Georgian_har 0x10010f4 +#define CLUTTER_KEY_Georgian_hoe 0x10010f5 +#define CLUTTER_KEY_Georgian_fi 0x10010f6 +#define CLUTTER_KEY_Xabovedot 0x1001e8a +#define CLUTTER_KEY_Ibreve 0x100012c +#define CLUTTER_KEY_Zstroke 0x10001b5 +#define CLUTTER_KEY_Gcaron 0x10001e6 +#define CLUTTER_KEY_Ocaron 0x10001d1 +#define CLUTTER_KEY_Obarred 0x100019f +#define CLUTTER_KEY_xabovedot 0x1001e8b +#define CLUTTER_KEY_ibreve 0x100012d +#define CLUTTER_KEY_zstroke 0x10001b6 +#define CLUTTER_KEY_gcaron 0x10001e7 +#define CLUTTER_KEY_ocaron 0x10001d2 +#define CLUTTER_KEY_obarred 0x1000275 +#define CLUTTER_KEY_SCHWA 0x100018f +#define CLUTTER_KEY_schwa 0x1000259 +#define CLUTTER_KEY_EZH 0x10001b7 +#define CLUTTER_KEY_ezh 0x1000292 +#define CLUTTER_KEY_Lbelowdot 0x1001e36 +#define CLUTTER_KEY_lbelowdot 0x1001e37 +#define CLUTTER_KEY_Abelowdot 0x1001ea0 +#define CLUTTER_KEY_abelowdot 0x1001ea1 +#define CLUTTER_KEY_Ahook 0x1001ea2 +#define CLUTTER_KEY_ahook 0x1001ea3 +#define CLUTTER_KEY_Acircumflexacute 0x1001ea4 +#define CLUTTER_KEY_acircumflexacute 0x1001ea5 +#define CLUTTER_KEY_Acircumflexgrave 0x1001ea6 +#define CLUTTER_KEY_acircumflexgrave 0x1001ea7 +#define CLUTTER_KEY_Acircumflexhook 0x1001ea8 +#define CLUTTER_KEY_acircumflexhook 0x1001ea9 +#define CLUTTER_KEY_Acircumflextilde 0x1001eaa +#define CLUTTER_KEY_acircumflextilde 0x1001eab +#define CLUTTER_KEY_Acircumflexbelowdot 0x1001eac +#define CLUTTER_KEY_acircumflexbelowdot 0x1001ead +#define CLUTTER_KEY_Abreveacute 0x1001eae +#define CLUTTER_KEY_abreveacute 0x1001eaf +#define CLUTTER_KEY_Abrevegrave 0x1001eb0 +#define CLUTTER_KEY_abrevegrave 0x1001eb1 +#define CLUTTER_KEY_Abrevehook 0x1001eb2 +#define CLUTTER_KEY_abrevehook 0x1001eb3 +#define CLUTTER_KEY_Abrevetilde 0x1001eb4 +#define CLUTTER_KEY_abrevetilde 0x1001eb5 +#define CLUTTER_KEY_Abrevebelowdot 0x1001eb6 +#define CLUTTER_KEY_abrevebelowdot 0x1001eb7 +#define CLUTTER_KEY_Ebelowdot 0x1001eb8 +#define CLUTTER_KEY_ebelowdot 0x1001eb9 +#define CLUTTER_KEY_Ehook 0x1001eba +#define CLUTTER_KEY_ehook 0x1001ebb +#define CLUTTER_KEY_Etilde 0x1001ebc +#define CLUTTER_KEY_etilde 0x1001ebd +#define CLUTTER_KEY_Ecircumflexacute 0x1001ebe +#define CLUTTER_KEY_ecircumflexacute 0x1001ebf +#define CLUTTER_KEY_Ecircumflexgrave 0x1001ec0 +#define CLUTTER_KEY_ecircumflexgrave 0x1001ec1 +#define CLUTTER_KEY_Ecircumflexhook 0x1001ec2 +#define CLUTTER_KEY_ecircumflexhook 0x1001ec3 +#define CLUTTER_KEY_Ecircumflextilde 0x1001ec4 +#define CLUTTER_KEY_ecircumflextilde 0x1001ec5 +#define CLUTTER_KEY_Ecircumflexbelowdot 0x1001ec6 +#define CLUTTER_KEY_ecircumflexbelowdot 0x1001ec7 +#define CLUTTER_KEY_Ihook 0x1001ec8 +#define CLUTTER_KEY_ihook 0x1001ec9 +#define CLUTTER_KEY_Ibelowdot 0x1001eca +#define CLUTTER_KEY_ibelowdot 0x1001ecb +#define CLUTTER_KEY_Obelowdot 0x1001ecc +#define CLUTTER_KEY_obelowdot 0x1001ecd +#define CLUTTER_KEY_Ohook 0x1001ece +#define CLUTTER_KEY_ohook 0x1001ecf +#define CLUTTER_KEY_Ocircumflexacute 0x1001ed0 +#define CLUTTER_KEY_ocircumflexacute 0x1001ed1 +#define CLUTTER_KEY_Ocircumflexgrave 0x1001ed2 +#define CLUTTER_KEY_ocircumflexgrave 0x1001ed3 +#define CLUTTER_KEY_Ocircumflexhook 0x1001ed4 +#define CLUTTER_KEY_ocircumflexhook 0x1001ed5 +#define CLUTTER_KEY_Ocircumflextilde 0x1001ed6 +#define CLUTTER_KEY_ocircumflextilde 0x1001ed7 +#define CLUTTER_KEY_Ocircumflexbelowdot 0x1001ed8 +#define CLUTTER_KEY_ocircumflexbelowdot 0x1001ed9 +#define CLUTTER_KEY_Ohornacute 0x1001eda +#define CLUTTER_KEY_ohornacute 0x1001edb +#define CLUTTER_KEY_Ohorngrave 0x1001edc +#define CLUTTER_KEY_ohorngrave 0x1001edd +#define CLUTTER_KEY_Ohornhook 0x1001ede +#define CLUTTER_KEY_ohornhook 0x1001edf +#define CLUTTER_KEY_Ohorntilde 0x1001ee0 +#define CLUTTER_KEY_ohorntilde 0x1001ee1 +#define CLUTTER_KEY_Ohornbelowdot 0x1001ee2 +#define CLUTTER_KEY_ohornbelowdot 0x1001ee3 +#define CLUTTER_KEY_Ubelowdot 0x1001ee4 +#define CLUTTER_KEY_ubelowdot 0x1001ee5 +#define CLUTTER_KEY_Uhook 0x1001ee6 +#define CLUTTER_KEY_uhook 0x1001ee7 +#define CLUTTER_KEY_Uhornacute 0x1001ee8 +#define CLUTTER_KEY_uhornacute 0x1001ee9 +#define CLUTTER_KEY_Uhorngrave 0x1001eea +#define CLUTTER_KEY_uhorngrave 0x1001eeb +#define CLUTTER_KEY_Uhornhook 0x1001eec +#define CLUTTER_KEY_uhornhook 0x1001eed +#define CLUTTER_KEY_Uhorntilde 0x1001eee +#define CLUTTER_KEY_uhorntilde 0x1001eef +#define CLUTTER_KEY_Uhornbelowdot 0x1001ef0 +#define CLUTTER_KEY_uhornbelowdot 0x1001ef1 +#define CLUTTER_KEY_Ybelowdot 0x1001ef4 +#define CLUTTER_KEY_ybelowdot 0x1001ef5 +#define CLUTTER_KEY_Yhook 0x1001ef6 +#define CLUTTER_KEY_yhook 0x1001ef7 +#define CLUTTER_KEY_Ytilde 0x1001ef8 +#define CLUTTER_KEY_ytilde 0x1001ef9 +#define CLUTTER_KEY_Ohorn 0x10001a0 +#define CLUTTER_KEY_ohorn 0x10001a1 +#define CLUTTER_KEY_Uhorn 0x10001af +#define CLUTTER_KEY_uhorn 0x10001b0 +#define CLUTTER_KEY_EcuSign 0x10020a0 +#define CLUTTER_KEY_ColonSign 0x10020a1 +#define CLUTTER_KEY_CruzeiroSign 0x10020a2 +#define CLUTTER_KEY_FFrancSign 0x10020a3 +#define CLUTTER_KEY_LiraSign 0x10020a4 +#define CLUTTER_KEY_MillSign 0x10020a5 +#define CLUTTER_KEY_NairaSign 0x10020a6 +#define CLUTTER_KEY_PesetaSign 0x10020a7 +#define CLUTTER_KEY_RupeeSign 0x10020a8 +#define CLUTTER_KEY_WonSign 0x10020a9 +#define CLUTTER_KEY_NewSheqelSign 0x10020aa +#define CLUTTER_KEY_DongSign 0x10020ab +#define CLUTTER_KEY_EuroSign 0x20ac +#define CLUTTER_KEY_zerosuperior 0x1002070 +#define CLUTTER_KEY_foursuperior 0x1002074 +#define CLUTTER_KEY_fivesuperior 0x1002075 +#define CLUTTER_KEY_sixsuperior 0x1002076 +#define CLUTTER_KEY_sevensuperior 0x1002077 +#define CLUTTER_KEY_eightsuperior 0x1002078 +#define CLUTTER_KEY_ninesuperior 0x1002079 +#define CLUTTER_KEY_zerosubscript 0x1002080 +#define CLUTTER_KEY_onesubscript 0x1002081 +#define CLUTTER_KEY_twosubscript 0x1002082 +#define CLUTTER_KEY_threesubscript 0x1002083 +#define CLUTTER_KEY_foursubscript 0x1002084 +#define CLUTTER_KEY_fivesubscript 0x1002085 +#define CLUTTER_KEY_sixsubscript 0x1002086 +#define CLUTTER_KEY_sevensubscript 0x1002087 +#define CLUTTER_KEY_eightsubscript 0x1002088 +#define CLUTTER_KEY_ninesubscript 0x1002089 +#define CLUTTER_KEY_partdifferential 0x1002202 +#define CLUTTER_KEY_emptyset 0x1002205 +#define CLUTTER_KEY_elementof 0x1002208 +#define CLUTTER_KEY_notelementof 0x1002209 +#define CLUTTER_KEY_containsas 0x100220b +#define CLUTTER_KEY_squareroot 0x100221a +#define CLUTTER_KEY_cuberoot 0x100221b +#define CLUTTER_KEY_fourthroot 0x100221c +#define CLUTTER_KEY_dintegral 0x100222c +#define CLUTTER_KEY_tintegral 0x100222d +#define CLUTTER_KEY_because 0x1002235 +#define CLUTTER_KEY_approxeq 0x1002248 +#define CLUTTER_KEY_notapproxeq 0x1002247 +#define CLUTTER_KEY_notidentical 0x1002262 +#define CLUTTER_KEY_stricteq 0x1002263 +#define CLUTTER_KEY_braille_dot_1 0xfff1 +#define CLUTTER_KEY_braille_dot_2 0xfff2 +#define CLUTTER_KEY_braille_dot_3 0xfff3 +#define CLUTTER_KEY_braille_dot_4 0xfff4 +#define CLUTTER_KEY_braille_dot_5 0xfff5 +#define CLUTTER_KEY_braille_dot_6 0xfff6 +#define CLUTTER_KEY_braille_dot_7 0xfff7 +#define CLUTTER_KEY_braille_dot_8 0xfff8 +#define CLUTTER_KEY_braille_dot_9 0xfff9 +#define CLUTTER_KEY_braille_dot_10 0xfffa +#define CLUTTER_KEY_braille_blank 0x1002800 +#define CLUTTER_KEY_braille_dots_1 0x1002801 +#define CLUTTER_KEY_braille_dots_2 0x1002802 +#define CLUTTER_KEY_braille_dots_12 0x1002803 +#define CLUTTER_KEY_braille_dots_3 0x1002804 +#define CLUTTER_KEY_braille_dots_13 0x1002805 +#define CLUTTER_KEY_braille_dots_23 0x1002806 +#define CLUTTER_KEY_braille_dots_123 0x1002807 +#define CLUTTER_KEY_braille_dots_4 0x1002808 +#define CLUTTER_KEY_braille_dots_14 0x1002809 +#define CLUTTER_KEY_braille_dots_24 0x100280a +#define CLUTTER_KEY_braille_dots_124 0x100280b +#define CLUTTER_KEY_braille_dots_34 0x100280c +#define CLUTTER_KEY_braille_dots_134 0x100280d +#define CLUTTER_KEY_braille_dots_234 0x100280e +#define CLUTTER_KEY_braille_dots_1234 0x100280f +#define CLUTTER_KEY_braille_dots_5 0x1002810 +#define CLUTTER_KEY_braille_dots_15 0x1002811 +#define CLUTTER_KEY_braille_dots_25 0x1002812 +#define CLUTTER_KEY_braille_dots_125 0x1002813 +#define CLUTTER_KEY_braille_dots_35 0x1002814 +#define CLUTTER_KEY_braille_dots_135 0x1002815 +#define CLUTTER_KEY_braille_dots_235 0x1002816 +#define CLUTTER_KEY_braille_dots_1235 0x1002817 +#define CLUTTER_KEY_braille_dots_45 0x1002818 +#define CLUTTER_KEY_braille_dots_145 0x1002819 +#define CLUTTER_KEY_braille_dots_245 0x100281a +#define CLUTTER_KEY_braille_dots_1245 0x100281b +#define CLUTTER_KEY_braille_dots_345 0x100281c +#define CLUTTER_KEY_braille_dots_1345 0x100281d +#define CLUTTER_KEY_braille_dots_2345 0x100281e +#define CLUTTER_KEY_braille_dots_12345 0x100281f +#define CLUTTER_KEY_braille_dots_6 0x1002820 +#define CLUTTER_KEY_braille_dots_16 0x1002821 +#define CLUTTER_KEY_braille_dots_26 0x1002822 +#define CLUTTER_KEY_braille_dots_126 0x1002823 +#define CLUTTER_KEY_braille_dots_36 0x1002824 +#define CLUTTER_KEY_braille_dots_136 0x1002825 +#define CLUTTER_KEY_braille_dots_236 0x1002826 +#define CLUTTER_KEY_braille_dots_1236 0x1002827 +#define CLUTTER_KEY_braille_dots_46 0x1002828 +#define CLUTTER_KEY_braille_dots_146 0x1002829 +#define CLUTTER_KEY_braille_dots_246 0x100282a +#define CLUTTER_KEY_braille_dots_1246 0x100282b +#define CLUTTER_KEY_braille_dots_346 0x100282c +#define CLUTTER_KEY_braille_dots_1346 0x100282d +#define CLUTTER_KEY_braille_dots_2346 0x100282e +#define CLUTTER_KEY_braille_dots_12346 0x100282f +#define CLUTTER_KEY_braille_dots_56 0x1002830 +#define CLUTTER_KEY_braille_dots_156 0x1002831 +#define CLUTTER_KEY_braille_dots_256 0x1002832 +#define CLUTTER_KEY_braille_dots_1256 0x1002833 +#define CLUTTER_KEY_braille_dots_356 0x1002834 +#define CLUTTER_KEY_braille_dots_1356 0x1002835 +#define CLUTTER_KEY_braille_dots_2356 0x1002836 +#define CLUTTER_KEY_braille_dots_12356 0x1002837 +#define CLUTTER_KEY_braille_dots_456 0x1002838 +#define CLUTTER_KEY_braille_dots_1456 0x1002839 +#define CLUTTER_KEY_braille_dots_2456 0x100283a +#define CLUTTER_KEY_braille_dots_12456 0x100283b +#define CLUTTER_KEY_braille_dots_3456 0x100283c +#define CLUTTER_KEY_braille_dots_13456 0x100283d +#define CLUTTER_KEY_braille_dots_23456 0x100283e +#define CLUTTER_KEY_braille_dots_123456 0x100283f +#define CLUTTER_KEY_braille_dots_7 0x1002840 +#define CLUTTER_KEY_braille_dots_17 0x1002841 +#define CLUTTER_KEY_braille_dots_27 0x1002842 +#define CLUTTER_KEY_braille_dots_127 0x1002843 +#define CLUTTER_KEY_braille_dots_37 0x1002844 +#define CLUTTER_KEY_braille_dots_137 0x1002845 +#define CLUTTER_KEY_braille_dots_237 0x1002846 +#define CLUTTER_KEY_braille_dots_1237 0x1002847 +#define CLUTTER_KEY_braille_dots_47 0x1002848 +#define CLUTTER_KEY_braille_dots_147 0x1002849 +#define CLUTTER_KEY_braille_dots_247 0x100284a +#define CLUTTER_KEY_braille_dots_1247 0x100284b +#define CLUTTER_KEY_braille_dots_347 0x100284c +#define CLUTTER_KEY_braille_dots_1347 0x100284d +#define CLUTTER_KEY_braille_dots_2347 0x100284e +#define CLUTTER_KEY_braille_dots_12347 0x100284f +#define CLUTTER_KEY_braille_dots_57 0x1002850 +#define CLUTTER_KEY_braille_dots_157 0x1002851 +#define CLUTTER_KEY_braille_dots_257 0x1002852 +#define CLUTTER_KEY_braille_dots_1257 0x1002853 +#define CLUTTER_KEY_braille_dots_357 0x1002854 +#define CLUTTER_KEY_braille_dots_1357 0x1002855 +#define CLUTTER_KEY_braille_dots_2357 0x1002856 +#define CLUTTER_KEY_braille_dots_12357 0x1002857 +#define CLUTTER_KEY_braille_dots_457 0x1002858 +#define CLUTTER_KEY_braille_dots_1457 0x1002859 +#define CLUTTER_KEY_braille_dots_2457 0x100285a +#define CLUTTER_KEY_braille_dots_12457 0x100285b +#define CLUTTER_KEY_braille_dots_3457 0x100285c +#define CLUTTER_KEY_braille_dots_13457 0x100285d +#define CLUTTER_KEY_braille_dots_23457 0x100285e +#define CLUTTER_KEY_braille_dots_123457 0x100285f +#define CLUTTER_KEY_braille_dots_67 0x1002860 +#define CLUTTER_KEY_braille_dots_167 0x1002861 +#define CLUTTER_KEY_braille_dots_267 0x1002862 +#define CLUTTER_KEY_braille_dots_1267 0x1002863 +#define CLUTTER_KEY_braille_dots_367 0x1002864 +#define CLUTTER_KEY_braille_dots_1367 0x1002865 +#define CLUTTER_KEY_braille_dots_2367 0x1002866 +#define CLUTTER_KEY_braille_dots_12367 0x1002867 +#define CLUTTER_KEY_braille_dots_467 0x1002868 +#define CLUTTER_KEY_braille_dots_1467 0x1002869 +#define CLUTTER_KEY_braille_dots_2467 0x100286a +#define CLUTTER_KEY_braille_dots_12467 0x100286b +#define CLUTTER_KEY_braille_dots_3467 0x100286c +#define CLUTTER_KEY_braille_dots_13467 0x100286d +#define CLUTTER_KEY_braille_dots_23467 0x100286e +#define CLUTTER_KEY_braille_dots_123467 0x100286f +#define CLUTTER_KEY_braille_dots_567 0x1002870 +#define CLUTTER_KEY_braille_dots_1567 0x1002871 +#define CLUTTER_KEY_braille_dots_2567 0x1002872 +#define CLUTTER_KEY_braille_dots_12567 0x1002873 +#define CLUTTER_KEY_braille_dots_3567 0x1002874 +#define CLUTTER_KEY_braille_dots_13567 0x1002875 +#define CLUTTER_KEY_braille_dots_23567 0x1002876 +#define CLUTTER_KEY_braille_dots_123567 0x1002877 +#define CLUTTER_KEY_braille_dots_4567 0x1002878 +#define CLUTTER_KEY_braille_dots_14567 0x1002879 +#define CLUTTER_KEY_braille_dots_24567 0x100287a +#define CLUTTER_KEY_braille_dots_124567 0x100287b +#define CLUTTER_KEY_braille_dots_34567 0x100287c +#define CLUTTER_KEY_braille_dots_134567 0x100287d +#define CLUTTER_KEY_braille_dots_234567 0x100287e +#define CLUTTER_KEY_braille_dots_1234567 0x100287f +#define CLUTTER_KEY_braille_dots_8 0x1002880 +#define CLUTTER_KEY_braille_dots_18 0x1002881 +#define CLUTTER_KEY_braille_dots_28 0x1002882 +#define CLUTTER_KEY_braille_dots_128 0x1002883 +#define CLUTTER_KEY_braille_dots_38 0x1002884 +#define CLUTTER_KEY_braille_dots_138 0x1002885 +#define CLUTTER_KEY_braille_dots_238 0x1002886 +#define CLUTTER_KEY_braille_dots_1238 0x1002887 +#define CLUTTER_KEY_braille_dots_48 0x1002888 +#define CLUTTER_KEY_braille_dots_148 0x1002889 +#define CLUTTER_KEY_braille_dots_248 0x100288a +#define CLUTTER_KEY_braille_dots_1248 0x100288b +#define CLUTTER_KEY_braille_dots_348 0x100288c +#define CLUTTER_KEY_braille_dots_1348 0x100288d +#define CLUTTER_KEY_braille_dots_2348 0x100288e +#define CLUTTER_KEY_braille_dots_12348 0x100288f +#define CLUTTER_KEY_braille_dots_58 0x1002890 +#define CLUTTER_KEY_braille_dots_158 0x1002891 +#define CLUTTER_KEY_braille_dots_258 0x1002892 +#define CLUTTER_KEY_braille_dots_1258 0x1002893 +#define CLUTTER_KEY_braille_dots_358 0x1002894 +#define CLUTTER_KEY_braille_dots_1358 0x1002895 +#define CLUTTER_KEY_braille_dots_2358 0x1002896 +#define CLUTTER_KEY_braille_dots_12358 0x1002897 +#define CLUTTER_KEY_braille_dots_458 0x1002898 +#define CLUTTER_KEY_braille_dots_1458 0x1002899 +#define CLUTTER_KEY_braille_dots_2458 0x100289a +#define CLUTTER_KEY_braille_dots_12458 0x100289b +#define CLUTTER_KEY_braille_dots_3458 0x100289c +#define CLUTTER_KEY_braille_dots_13458 0x100289d +#define CLUTTER_KEY_braille_dots_23458 0x100289e +#define CLUTTER_KEY_braille_dots_123458 0x100289f +#define CLUTTER_KEY_braille_dots_68 0x10028a0 +#define CLUTTER_KEY_braille_dots_168 0x10028a1 +#define CLUTTER_KEY_braille_dots_268 0x10028a2 +#define CLUTTER_KEY_braille_dots_1268 0x10028a3 +#define CLUTTER_KEY_braille_dots_368 0x10028a4 +#define CLUTTER_KEY_braille_dots_1368 0x10028a5 +#define CLUTTER_KEY_braille_dots_2368 0x10028a6 +#define CLUTTER_KEY_braille_dots_12368 0x10028a7 +#define CLUTTER_KEY_braille_dots_468 0x10028a8 +#define CLUTTER_KEY_braille_dots_1468 0x10028a9 +#define CLUTTER_KEY_braille_dots_2468 0x10028aa +#define CLUTTER_KEY_braille_dots_12468 0x10028ab +#define CLUTTER_KEY_braille_dots_3468 0x10028ac +#define CLUTTER_KEY_braille_dots_13468 0x10028ad +#define CLUTTER_KEY_braille_dots_23468 0x10028ae +#define CLUTTER_KEY_braille_dots_123468 0x10028af +#define CLUTTER_KEY_braille_dots_568 0x10028b0 +#define CLUTTER_KEY_braille_dots_1568 0x10028b1 +#define CLUTTER_KEY_braille_dots_2568 0x10028b2 +#define CLUTTER_KEY_braille_dots_12568 0x10028b3 +#define CLUTTER_KEY_braille_dots_3568 0x10028b4 +#define CLUTTER_KEY_braille_dots_13568 0x10028b5 +#define CLUTTER_KEY_braille_dots_23568 0x10028b6 +#define CLUTTER_KEY_braille_dots_123568 0x10028b7 +#define CLUTTER_KEY_braille_dots_4568 0x10028b8 +#define CLUTTER_KEY_braille_dots_14568 0x10028b9 +#define CLUTTER_KEY_braille_dots_24568 0x10028ba +#define CLUTTER_KEY_braille_dots_124568 0x10028bb +#define CLUTTER_KEY_braille_dots_34568 0x10028bc +#define CLUTTER_KEY_braille_dots_134568 0x10028bd +#define CLUTTER_KEY_braille_dots_234568 0x10028be +#define CLUTTER_KEY_braille_dots_1234568 0x10028bf +#define CLUTTER_KEY_braille_dots_78 0x10028c0 +#define CLUTTER_KEY_braille_dots_178 0x10028c1 +#define CLUTTER_KEY_braille_dots_278 0x10028c2 +#define CLUTTER_KEY_braille_dots_1278 0x10028c3 +#define CLUTTER_KEY_braille_dots_378 0x10028c4 +#define CLUTTER_KEY_braille_dots_1378 0x10028c5 +#define CLUTTER_KEY_braille_dots_2378 0x10028c6 +#define CLUTTER_KEY_braille_dots_12378 0x10028c7 +#define CLUTTER_KEY_braille_dots_478 0x10028c8 +#define CLUTTER_KEY_braille_dots_1478 0x10028c9 +#define CLUTTER_KEY_braille_dots_2478 0x10028ca +#define CLUTTER_KEY_braille_dots_12478 0x10028cb +#define CLUTTER_KEY_braille_dots_3478 0x10028cc +#define CLUTTER_KEY_braille_dots_13478 0x10028cd +#define CLUTTER_KEY_braille_dots_23478 0x10028ce +#define CLUTTER_KEY_braille_dots_123478 0x10028cf +#define CLUTTER_KEY_braille_dots_578 0x10028d0 +#define CLUTTER_KEY_braille_dots_1578 0x10028d1 +#define CLUTTER_KEY_braille_dots_2578 0x10028d2 +#define CLUTTER_KEY_braille_dots_12578 0x10028d3 +#define CLUTTER_KEY_braille_dots_3578 0x10028d4 +#define CLUTTER_KEY_braille_dots_13578 0x10028d5 +#define CLUTTER_KEY_braille_dots_23578 0x10028d6 +#define CLUTTER_KEY_braille_dots_123578 0x10028d7 +#define CLUTTER_KEY_braille_dots_4578 0x10028d8 +#define CLUTTER_KEY_braille_dots_14578 0x10028d9 +#define CLUTTER_KEY_braille_dots_24578 0x10028da +#define CLUTTER_KEY_braille_dots_124578 0x10028db +#define CLUTTER_KEY_braille_dots_34578 0x10028dc +#define CLUTTER_KEY_braille_dots_134578 0x10028dd +#define CLUTTER_KEY_braille_dots_234578 0x10028de +#define CLUTTER_KEY_braille_dots_1234578 0x10028df +#define CLUTTER_KEY_braille_dots_678 0x10028e0 +#define CLUTTER_KEY_braille_dots_1678 0x10028e1 +#define CLUTTER_KEY_braille_dots_2678 0x10028e2 +#define CLUTTER_KEY_braille_dots_12678 0x10028e3 +#define CLUTTER_KEY_braille_dots_3678 0x10028e4 +#define CLUTTER_KEY_braille_dots_13678 0x10028e5 +#define CLUTTER_KEY_braille_dots_23678 0x10028e6 +#define CLUTTER_KEY_braille_dots_123678 0x10028e7 +#define CLUTTER_KEY_braille_dots_4678 0x10028e8 +#define CLUTTER_KEY_braille_dots_14678 0x10028e9 +#define CLUTTER_KEY_braille_dots_24678 0x10028ea +#define CLUTTER_KEY_braille_dots_124678 0x10028eb +#define CLUTTER_KEY_braille_dots_34678 0x10028ec +#define CLUTTER_KEY_braille_dots_134678 0x10028ed +#define CLUTTER_KEY_braille_dots_234678 0x10028ee +#define CLUTTER_KEY_braille_dots_1234678 0x10028ef +#define CLUTTER_KEY_braille_dots_5678 0x10028f0 +#define CLUTTER_KEY_braille_dots_15678 0x10028f1 +#define CLUTTER_KEY_braille_dots_25678 0x10028f2 +#define CLUTTER_KEY_braille_dots_125678 0x10028f3 +#define CLUTTER_KEY_braille_dots_35678 0x10028f4 +#define CLUTTER_KEY_braille_dots_135678 0x10028f5 +#define CLUTTER_KEY_braille_dots_235678 0x10028f6 +#define CLUTTER_KEY_braille_dots_1235678 0x10028f7 +#define CLUTTER_KEY_braille_dots_45678 0x10028f8 +#define CLUTTER_KEY_braille_dots_145678 0x10028f9 +#define CLUTTER_KEY_braille_dots_245678 0x10028fa +#define CLUTTER_KEY_braille_dots_1245678 0x10028fb +#define CLUTTER_KEY_braille_dots_345678 0x10028fc +#define CLUTTER_KEY_braille_dots_1345678 0x10028fd +#define CLUTTER_KEY_braille_dots_2345678 0x10028fe +#define CLUTTER_KEY_braille_dots_12345678 0x10028ff +#define CLUTTER_KEY_Sinh_ng 0x1000d82 +#define CLUTTER_KEY_Sinh_h2 0x1000d83 +#define CLUTTER_KEY_Sinh_a 0x1000d85 +#define CLUTTER_KEY_Sinh_aa 0x1000d86 +#define CLUTTER_KEY_Sinh_ae 0x1000d87 +#define CLUTTER_KEY_Sinh_aee 0x1000d88 +#define CLUTTER_KEY_Sinh_i 0x1000d89 +#define CLUTTER_KEY_Sinh_ii 0x1000d8a +#define CLUTTER_KEY_Sinh_u 0x1000d8b +#define CLUTTER_KEY_Sinh_uu 0x1000d8c +#define CLUTTER_KEY_Sinh_ri 0x1000d8d +#define CLUTTER_KEY_Sinh_rii 0x1000d8e +#define CLUTTER_KEY_Sinh_lu 0x1000d8f +#define CLUTTER_KEY_Sinh_luu 0x1000d90 +#define CLUTTER_KEY_Sinh_e 0x1000d91 +#define CLUTTER_KEY_Sinh_ee 0x1000d92 +#define CLUTTER_KEY_Sinh_ai 0x1000d93 +#define CLUTTER_KEY_Sinh_o 0x1000d94 +#define CLUTTER_KEY_Sinh_oo 0x1000d95 +#define CLUTTER_KEY_Sinh_au 0x1000d96 +#define CLUTTER_KEY_Sinh_ka 0x1000d9a +#define CLUTTER_KEY_Sinh_kha 0x1000d9b +#define CLUTTER_KEY_Sinh_ga 0x1000d9c +#define CLUTTER_KEY_Sinh_gha 0x1000d9d +#define CLUTTER_KEY_Sinh_ng2 0x1000d9e +#define CLUTTER_KEY_Sinh_nga 0x1000d9f +#define CLUTTER_KEY_Sinh_ca 0x1000da0 +#define CLUTTER_KEY_Sinh_cha 0x1000da1 +#define CLUTTER_KEY_Sinh_ja 0x1000da2 +#define CLUTTER_KEY_Sinh_jha 0x1000da3 +#define CLUTTER_KEY_Sinh_nya 0x1000da4 +#define CLUTTER_KEY_Sinh_jnya 0x1000da5 +#define CLUTTER_KEY_Sinh_nja 0x1000da6 +#define CLUTTER_KEY_Sinh_tta 0x1000da7 +#define CLUTTER_KEY_Sinh_ttha 0x1000da8 +#define CLUTTER_KEY_Sinh_dda 0x1000da9 +#define CLUTTER_KEY_Sinh_ddha 0x1000daa +#define CLUTTER_KEY_Sinh_nna 0x1000dab +#define CLUTTER_KEY_Sinh_ndda 0x1000dac +#define CLUTTER_KEY_Sinh_tha 0x1000dad +#define CLUTTER_KEY_Sinh_thha 0x1000dae +#define CLUTTER_KEY_Sinh_dha 0x1000daf +#define CLUTTER_KEY_Sinh_dhha 0x1000db0 +#define CLUTTER_KEY_Sinh_na 0x1000db1 +#define CLUTTER_KEY_Sinh_ndha 0x1000db3 +#define CLUTTER_KEY_Sinh_pa 0x1000db4 +#define CLUTTER_KEY_Sinh_pha 0x1000db5 +#define CLUTTER_KEY_Sinh_ba 0x1000db6 +#define CLUTTER_KEY_Sinh_bha 0x1000db7 +#define CLUTTER_KEY_Sinh_ma 0x1000db8 +#define CLUTTER_KEY_Sinh_mba 0x1000db9 +#define CLUTTER_KEY_Sinh_ya 0x1000dba +#define CLUTTER_KEY_Sinh_ra 0x1000dbb +#define CLUTTER_KEY_Sinh_la 0x1000dbd +#define CLUTTER_KEY_Sinh_va 0x1000dc0 +#define CLUTTER_KEY_Sinh_sha 0x1000dc1 +#define CLUTTER_KEY_Sinh_ssha 0x1000dc2 +#define CLUTTER_KEY_Sinh_sa 0x1000dc3 +#define CLUTTER_KEY_Sinh_ha 0x1000dc4 +#define CLUTTER_KEY_Sinh_lla 0x1000dc5 +#define CLUTTER_KEY_Sinh_fa 0x1000dc6 +#define CLUTTER_KEY_Sinh_al 0x1000dca +#define CLUTTER_KEY_Sinh_aa2 0x1000dcf +#define CLUTTER_KEY_Sinh_ae2 0x1000dd0 +#define CLUTTER_KEY_Sinh_aee2 0x1000dd1 +#define CLUTTER_KEY_Sinh_i2 0x1000dd2 +#define CLUTTER_KEY_Sinh_ii2 0x1000dd3 +#define CLUTTER_KEY_Sinh_u2 0x1000dd4 +#define CLUTTER_KEY_Sinh_uu2 0x1000dd6 +#define CLUTTER_KEY_Sinh_ru2 0x1000dd8 +#define CLUTTER_KEY_Sinh_e2 0x1000dd9 +#define CLUTTER_KEY_Sinh_ee2 0x1000dda +#define CLUTTER_KEY_Sinh_ai2 0x1000ddb +#define CLUTTER_KEY_Sinh_o2 0x1000ddc +#define CLUTTER_KEY_Sinh_oo2 0x1000ddd +#define CLUTTER_KEY_Sinh_au2 0x1000dde +#define CLUTTER_KEY_Sinh_lu2 0x1000ddf +#define CLUTTER_KEY_Sinh_ruu2 0x1000df2 +#define CLUTTER_KEY_Sinh_luu2 0x1000df3 +#define CLUTTER_KEY_Sinh_kunddaliya 0x1000df4 +#define CLUTTER_KEY_ModeLock 0x1008ff01 +#define CLUTTER_KEY_MonBrightnessUp 0x1008ff02 +#define CLUTTER_KEY_MonBrightnessDown 0x1008ff03 +#define CLUTTER_KEY_KbdLightOnOff 0x1008ff04 +#define CLUTTER_KEY_KbdBrightnessUp 0x1008ff05 +#define CLUTTER_KEY_KbdBrightnessDown 0x1008ff06 +#define CLUTTER_KEY_Standby 0x1008ff10 +#define CLUTTER_KEY_AudioLowerVolume 0x1008ff11 +#define CLUTTER_KEY_AudioMute 0x1008ff12 +#define CLUTTER_KEY_AudioRaiseVolume 0x1008ff13 +#define CLUTTER_KEY_AudioPlay 0x1008ff14 +#define CLUTTER_KEY_AudioStop 0x1008ff15 +#define CLUTTER_KEY_AudioPrev 0x1008ff16 +#define CLUTTER_KEY_AudioNext 0x1008ff17 +#define CLUTTER_KEY_HomePage 0x1008ff18 +#define CLUTTER_KEY_Mail 0x1008ff19 +#define CLUTTER_KEY_Start 0x1008ff1a +#define CLUTTER_KEY_Search 0x1008ff1b +#define CLUTTER_KEY_AudioRecord 0x1008ff1c +#define CLUTTER_KEY_Calculator 0x1008ff1d +#define CLUTTER_KEY_Memo 0x1008ff1e +#define CLUTTER_KEY_ToDoList 0x1008ff1f +#define CLUTTER_KEY_Calendar 0x1008ff20 +#define CLUTTER_KEY_PowerDown 0x1008ff21 +#define CLUTTER_KEY_ContrastAdjust 0x1008ff22 +#define CLUTTER_KEY_RockerUp 0x1008ff23 +#define CLUTTER_KEY_RockerDown 0x1008ff24 +#define CLUTTER_KEY_RockerEnter 0x1008ff25 +#define CLUTTER_KEY_Back 0x1008ff26 +#define CLUTTER_KEY_Forward 0x1008ff27 +#define CLUTTER_KEY_Stop 0x1008ff28 +#define CLUTTER_KEY_Refresh 0x1008ff29 +#define CLUTTER_KEY_PowerOff 0x1008ff2a +#define CLUTTER_KEY_WakeUp 0x1008ff2b +#define CLUTTER_KEY_Eject 0x1008ff2c +#define CLUTTER_KEY_ScreenSaver 0x1008ff2d +#define CLUTTER_KEY_WWW 0x1008ff2e +#define CLUTTER_KEY_Sleep 0x1008ff2f +#define CLUTTER_KEY_Favorites 0x1008ff30 +#define CLUTTER_KEY_AudioPause 0x1008ff31 +#define CLUTTER_KEY_AudioMedia 0x1008ff32 +#define CLUTTER_KEY_MyComputer 0x1008ff33 +#define CLUTTER_KEY_VendorHome 0x1008ff34 +#define CLUTTER_KEY_LightBulb 0x1008ff35 +#define CLUTTER_KEY_Shop 0x1008ff36 +#define CLUTTER_KEY_History 0x1008ff37 +#define CLUTTER_KEY_OpenURL 0x1008ff38 +#define CLUTTER_KEY_AddFavorite 0x1008ff39 +#define CLUTTER_KEY_HotLinks 0x1008ff3a +#define CLUTTER_KEY_BrightnessAdjust 0x1008ff3b +#define CLUTTER_KEY_Finance 0x1008ff3c +#define CLUTTER_KEY_Community 0x1008ff3d +#define CLUTTER_KEY_AudioRewind 0x1008ff3e +#define CLUTTER_KEY_BackForward 0x1008ff3f +#define CLUTTER_KEY_Launch0 0x1008ff40 +#define CLUTTER_KEY_Launch1 0x1008ff41 +#define CLUTTER_KEY_Launch2 0x1008ff42 +#define CLUTTER_KEY_Launch3 0x1008ff43 +#define CLUTTER_KEY_Launch4 0x1008ff44 +#define CLUTTER_KEY_Launch5 0x1008ff45 +#define CLUTTER_KEY_Launch6 0x1008ff46 +#define CLUTTER_KEY_Launch7 0x1008ff47 +#define CLUTTER_KEY_Launch8 0x1008ff48 +#define CLUTTER_KEY_Launch9 0x1008ff49 +#define CLUTTER_KEY_LaunchA 0x1008ff4a +#define CLUTTER_KEY_LaunchB 0x1008ff4b +#define CLUTTER_KEY_LaunchC 0x1008ff4c +#define CLUTTER_KEY_LaunchD 0x1008ff4d +#define CLUTTER_KEY_LaunchE 0x1008ff4e +#define CLUTTER_KEY_LaunchF 0x1008ff4f +#define CLUTTER_KEY_ApplicationLeft 0x1008ff50 +#define CLUTTER_KEY_ApplicationRight 0x1008ff51 +#define CLUTTER_KEY_Book 0x1008ff52 +#define CLUTTER_KEY_CD 0x1008ff53 +#define CLUTTER_KEY_WindowClear 0x1008ff55 +#define CLUTTER_KEY_Close 0x1008ff56 +#define CLUTTER_KEY_Copy 0x1008ff57 +#define CLUTTER_KEY_Cut 0x1008ff58 +#define CLUTTER_KEY_Display 0x1008ff59 +#define CLUTTER_KEY_DOS 0x1008ff5a +#define CLUTTER_KEY_Documents 0x1008ff5b +#define CLUTTER_KEY_Excel 0x1008ff5c +#define CLUTTER_KEY_Explorer 0x1008ff5d +#define CLUTTER_KEY_Game 0x1008ff5e +#define CLUTTER_KEY_Go 0x1008ff5f +#define CLUTTER_KEY_iTouch 0x1008ff60 +#define CLUTTER_KEY_LogOff 0x1008ff61 +#define CLUTTER_KEY_Market 0x1008ff62 +#define CLUTTER_KEY_Meeting 0x1008ff63 +#define CLUTTER_KEY_MenuKB 0x1008ff65 +#define CLUTTER_KEY_MenuPB 0x1008ff66 +#define CLUTTER_KEY_MySites 0x1008ff67 +#define CLUTTER_KEY_New 0x1008ff68 +#define CLUTTER_KEY_News 0x1008ff69 +#define CLUTTER_KEY_OfficeHome 0x1008ff6a +#define CLUTTER_KEY_Open 0x1008ff6b +#define CLUTTER_KEY_Option 0x1008ff6c +#define CLUTTER_KEY_Paste 0x1008ff6d +#define CLUTTER_KEY_Phone 0x1008ff6e +#define CLUTTER_KEY_Reply 0x1008ff72 +#define CLUTTER_KEY_Reload 0x1008ff73 +#define CLUTTER_KEY_RotateWindows 0x1008ff74 +#define CLUTTER_KEY_RotationPB 0x1008ff75 +#define CLUTTER_KEY_RotationKB 0x1008ff76 +#define CLUTTER_KEY_Save 0x1008ff77 +#define CLUTTER_KEY_ScrollUp 0x1008ff78 +#define CLUTTER_KEY_ScrollDown 0x1008ff79 +#define CLUTTER_KEY_ScrollClick 0x1008ff7a +#define CLUTTER_KEY_Send 0x1008ff7b +#define CLUTTER_KEY_Spell 0x1008ff7c +#define CLUTTER_KEY_SplitScreen 0x1008ff7d +#define CLUTTER_KEY_Support 0x1008ff7e +#define CLUTTER_KEY_TaskPane 0x1008ff7f +#define CLUTTER_KEY_Terminal 0x1008ff80 +#define CLUTTER_KEY_Tools 0x1008ff81 +#define CLUTTER_KEY_Travel 0x1008ff82 +#define CLUTTER_KEY_UserPB 0x1008ff84 +#define CLUTTER_KEY_User1KB 0x1008ff85 +#define CLUTTER_KEY_User2KB 0x1008ff86 +#define CLUTTER_KEY_Video 0x1008ff87 +#define CLUTTER_KEY_WheelButton 0x1008ff88 +#define CLUTTER_KEY_Word 0x1008ff89 +#define CLUTTER_KEY_Xfer 0x1008ff8a +#define CLUTTER_KEY_ZoomIn 0x1008ff8b +#define CLUTTER_KEY_ZoomOut 0x1008ff8c +#define CLUTTER_KEY_Away 0x1008ff8d +#define CLUTTER_KEY_Messenger 0x1008ff8e +#define CLUTTER_KEY_WebCam 0x1008ff8f +#define CLUTTER_KEY_MailForward 0x1008ff90 +#define CLUTTER_KEY_Pictures 0x1008ff91 +#define CLUTTER_KEY_Music 0x1008ff92 +#define CLUTTER_KEY_Battery 0x1008ff93 +#define CLUTTER_KEY_Bluetooth 0x1008ff94 +#define CLUTTER_KEY_WLAN 0x1008ff95 +#define CLUTTER_KEY_UWB 0x1008ff96 +#define CLUTTER_KEY_AudioForward 0x1008ff97 +#define CLUTTER_KEY_AudioRepeat 0x1008ff98 +#define CLUTTER_KEY_AudioRandomPlay 0x1008ff99 +#define CLUTTER_KEY_Subtitle 0x1008ff9a +#define CLUTTER_KEY_AudioCycleTrack 0x1008ff9b +#define CLUTTER_KEY_CycleAngle 0x1008ff9c +#define CLUTTER_KEY_FrameBack 0x1008ff9d +#define CLUTTER_KEY_FrameForward 0x1008ff9e +#define CLUTTER_KEY_Time 0x1008ff9f +#define CLUTTER_KEY_SelectButton 0x1008ffa0 +#define CLUTTER_KEY_View 0x1008ffa1 +#define CLUTTER_KEY_TopMenu 0x1008ffa2 +#define CLUTTER_KEY_Red 0x1008ffa3 +#define CLUTTER_KEY_Green 0x1008ffa4 +#define CLUTTER_KEY_Yellow 0x1008ffa5 +#define CLUTTER_KEY_Blue 0x1008ffa6 +#define CLUTTER_KEY_Suspend 0x1008ffa7 +#define CLUTTER_KEY_Hibernate 0x1008ffa8 +#define CLUTTER_KEY_TouchpadToggle 0x1008ffa9 +#define CLUTTER_KEY_TouchpadOn 0x1008ffb0 +#define CLUTTER_KEY_TouchpadOff 0x1008ffb1 +#define CLUTTER_KEY_AudioMicMute 0x1008ffb2 +#define CLUTTER_KEY_Switch_VT_1 0x1008fe01 +#define CLUTTER_KEY_Switch_VT_2 0x1008fe02 +#define CLUTTER_KEY_Switch_VT_3 0x1008fe03 +#define CLUTTER_KEY_Switch_VT_4 0x1008fe04 +#define CLUTTER_KEY_Switch_VT_5 0x1008fe05 +#define CLUTTER_KEY_Switch_VT_6 0x1008fe06 +#define CLUTTER_KEY_Switch_VT_7 0x1008fe07 +#define CLUTTER_KEY_Switch_VT_8 0x1008fe08 +#define CLUTTER_KEY_Switch_VT_9 0x1008fe09 +#define CLUTTER_KEY_Switch_VT_10 0x1008fe0a +#define CLUTTER_KEY_Switch_VT_11 0x1008fe0b +#define CLUTTER_KEY_Switch_VT_12 0x1008fe0c +#define CLUTTER_KEY_Ungrab 0x1008fe20 +#define CLUTTER_KEY_ClearGrab 0x1008fe21 +#define CLUTTER_KEY_Next_VMode 0x1008fe22 +#define CLUTTER_KEY_Prev_VMode 0x1008fe23 +#define CLUTTER_KEY_LogWindowTree 0x1008fe24 +#define CLUTTER_KEY_LogGrabInfo 0x1008fe25 + +#endif /* __CLUTTER_KEYSYMS_H__ */ diff --git a/clutter/clutter/clutter-layout-manager.c b/clutter/clutter/clutter-layout-manager.c new file mode 100644 index 0000000..069d9af --- /dev/null +++ b/clutter/clutter/clutter-layout-manager.c @@ -0,0 +1,1112 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * 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 . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-layout-manager + * @short_description: Layout managers base class + * + * #ClutterLayoutManager is a base abstract class for layout managers. A + * layout manager implements the layouting policy for a composite or a + * container actor: it controls the preferred size of the actor to which + * it has been paired, and it controls the allocation of its children. + * + * Any composite or container #ClutterActor subclass can delegate the + * layouting of its children to a #ClutterLayoutManager. Clutter provides + * a generic container using #ClutterLayoutManager called #ClutterBox. + * + * Clutter provides some simple #ClutterLayoutManager sub-classes, like + * #ClutterFlowLayout and #ClutterBinLayout. + * + * ## Implementing a ClutterLayoutManager + * The implementation of a layout manager does not differ from the + * implementation of the size requisition and allocation bits of + * #ClutterActor, so you should read the relative documentation + * forr subclassing #ClutterActor. + * + * The layout manager implementation can hold a back pointer to the + * #ClutterContainer by implementing the #ClutterLayoutManagerClass.set_container() + * virtual function. The layout manager should not hold a real reference (i.e. + * call g_object_ref()) on the container actor, to avoid reference cycles. + * + * If a layout manager has properties affecting the layout policies then it should + * emit the #ClutterLayoutManager::layout-changed signal on itself by using the + * clutter_layout_manager_layout_changed() function whenever one of these properties + * changes. + * + * ## Layout Properties + * + * If a layout manager has layout properties, that is properties that + * should exist only as the result of the presence of a specific (layout + * manager, container actor, child actor) combination, and it wishes to store + * those properties inside a #ClutterLayoutMeta, then it should override the + * #ClutterLayoutManagerClass.get_child_meta_type() virtual function to return + * the #GType of the #ClutterLayoutMeta sub-class used to store the layout + * properties; optionally, the #ClutterLayoutManager sub-class might also + * override the #ClutterLayoutManagerClass.create_child_meta() virtual function + * to control how the #ClutterLayoutMeta instance is created, otherwise the + * default implementation will be equivalent to: + * + * |[ + * ClutterLayoutManagerClass *klass; + * GType meta_type; + * + * klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager); + * meta_type = klass->get_child_meta_type (manager); + * + * return g_object_new (meta_type, + * "manager", manager, + * "container", container, + * "actor", actor, + * NULL); + * ]| + * + * Where `manager` is the #ClutterLayoutManager, `container` is the + * #ClutterContainer using the #ClutterLayoutManager, and `actor` is + * the #ClutterActor child of the #ClutterContainer. + * + * ## Using ClutterLayoutManager with ClutterScript + * + * #ClutterLayoutManager instances can be created in the same way + * as other objects in #ClutterScript; properties can be set using the + * common syntax. + * + * Layout properties can be set on children of a container with + * a #ClutterLayoutManager using the `layout::` modifier on the property + * name, for instance: + * + * |[ + * { + * "type" : "ClutterBox", + * "layout-manager" : { "type" : "ClutterTableLayout" }, + * "children" : [ + * { + * "type" : "ClutterTexture", + * "filename" : "image-00.png", + * + * "layout::row" : 0, + * "layout::column" : 0, + * "layout::x-align" : "left", + * "layout::y-align" : "center", + * "layout::x-expand" : true, + * "layout::y-expand" : true + * }, + * { + * "type" : "ClutterTexture", + * "filename" : "image-01.png", + * + * "layout::row" : 0, + * "layout::column" : 1, + * "layout::x-align" : "right", + * "layout::y-align" : "center", + * "layout::x-expand" : true, + * "layout::y-expand" : true + * } + * ] + * } + * ]| + * + * #ClutterLayoutManager is available since Clutter 1.2 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include "deprecated/clutter-container.h" +#include "deprecated/clutter-alpha.h" + +#include "clutter-debug.h" +#include "clutter-layout-manager.h" +#include "clutter-layout-meta.h" +#include "clutter-marshal.h" +#include "clutter-private.h" +#include "clutter-timeline.h" + +#define LAYOUT_MANAGER_WARN_NOT_IMPLEMENTED(m,method) G_STMT_START { \ + GObject *_obj = G_OBJECT (m); \ + g_warning ("Layout managers of type %s do not implement " \ + "the ClutterLayoutManager::%s method", \ + G_OBJECT_TYPE_NAME (_obj), \ + (method)); } G_STMT_END + +enum +{ + LAYOUT_CHANGED, + + LAST_SIGNAL +}; + +G_DEFINE_ABSTRACT_TYPE (ClutterLayoutManager, + clutter_layout_manager, + G_TYPE_INITIALLY_UNOWNED) + +static GQuark quark_layout_meta = 0; +static GQuark quark_layout_alpha = 0; + +static guint manager_signals[LAST_SIGNAL] = { 0, }; + +static void +layout_manager_freeze_layout_change (ClutterLayoutManager *manager) +{ + gpointer is_frozen; + + CLUTTER_NOTE (LAYOUT, "Freezing changes for manager '%s'[%p]", + G_OBJECT_TYPE_NAME (manager), + manager); + + is_frozen = g_object_get_data (G_OBJECT (manager), "freeze-change"); + if (is_frozen == NULL) + g_object_set_data (G_OBJECT (manager), "freeze-change", + GUINT_TO_POINTER (1)); + else + { + guint level = GPOINTER_TO_UINT (is_frozen) + 1; + + g_object_set_data (G_OBJECT (manager), "freeze-change", + GUINT_TO_POINTER (level)); + } +} + +static void +layout_manager_thaw_layout_change (ClutterLayoutManager *manager) +{ + gpointer is_frozen; + + is_frozen = g_object_get_data (G_OBJECT (manager), "freeze-change"); + if (is_frozen == NULL) + g_critical (G_STRLOC ": Mismatched thaw; you have to call " + "clutter_layout_manager_freeze_layout_change() prior to " + "calling clutter_layout_manager_thaw_layout_change()"); + else + { + guint level = GPOINTER_TO_UINT (is_frozen); + + g_assert (level > 0); + + CLUTTER_NOTE (LAYOUT, "Thawing changes for manager '%s'[%p]", + G_OBJECT_TYPE_NAME (manager), + manager); + + level -= 1; + if (level == 0) + g_object_set_data (G_OBJECT (manager), "freeze-change", NULL); + else + g_object_set_data (G_OBJECT (manager), "freeze-change", + GUINT_TO_POINTER (level)); + } + +} + +static void +layout_manager_real_get_preferred_width (ClutterLayoutManager *manager, + ClutterContainer *container, + gfloat for_height, + gfloat *min_width_p, + gfloat *nat_width_p) +{ + LAYOUT_MANAGER_WARN_NOT_IMPLEMENTED (manager, "get_preferred_width"); + + if (min_width_p) + *min_width_p = 0.0; + + if (nat_width_p) + *nat_width_p = 0.0; +} + +static void +layout_manager_real_get_preferred_height (ClutterLayoutManager *manager, + ClutterContainer *container, + gfloat for_width, + gfloat *min_height_p, + gfloat *nat_height_p) +{ + LAYOUT_MANAGER_WARN_NOT_IMPLEMENTED (manager, "get_preferred_height"); + + if (min_height_p) + *min_height_p = 0.0; + + if (nat_height_p) + *nat_height_p = 0.0; +} + +static void +layout_manager_real_allocate (ClutterLayoutManager *manager, + ClutterContainer *container, + const ClutterActorBox *allocation, + ClutterAllocationFlags flags) +{ + LAYOUT_MANAGER_WARN_NOT_IMPLEMENTED (manager, "allocate"); +} + +static void +layout_manager_real_set_container (ClutterLayoutManager *manager, + ClutterContainer *container) +{ + if (container != NULL) + g_object_set_data (G_OBJECT (container), "clutter-layout-manager", manager); +} + +static ClutterLayoutMeta * +layout_manager_real_create_child_meta (ClutterLayoutManager *manager, + ClutterContainer *container, + ClutterActor *actor) +{ + ClutterLayoutManagerClass *klass; + GType meta_type; + + klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager); + meta_type = klass->get_child_meta_type (manager); + + /* provide a default implementation to reduce common code */ + if (meta_type != G_TYPE_INVALID) + { + g_assert (g_type_is_a (meta_type, CLUTTER_TYPE_LAYOUT_META)); + + return g_object_new (meta_type, + "manager", manager, + "container", container, + "actor", actor, + NULL); + } + + return NULL; +} + +static GType +layout_manager_real_get_child_meta_type (ClutterLayoutManager *manager) +{ + return G_TYPE_INVALID; +} + +/* XXX:2.0 - Remove */ +static ClutterAlpha * +layout_manager_real_begin_animation (ClutterLayoutManager *manager, + guint duration, + gulong mode) +{ + ClutterTimeline *timeline; + ClutterAlpha *alpha; + + alpha = g_object_get_qdata (G_OBJECT (manager), quark_layout_alpha); + if (alpha != NULL) + { + clutter_alpha_set_mode (alpha, mode); + + timeline = clutter_alpha_get_timeline (alpha); + clutter_timeline_set_duration (timeline, duration); + clutter_timeline_rewind (timeline); + + return alpha; + }; + + timeline = clutter_timeline_new (duration); + + alpha = clutter_alpha_new_full (timeline, mode); + + /* let the alpha take ownership of the timeline */ + g_object_unref (timeline); + + g_signal_connect_swapped (timeline, "completed", + G_CALLBACK (clutter_layout_manager_end_animation), + manager); + g_signal_connect_swapped (timeline, "new-frame", + G_CALLBACK (clutter_layout_manager_layout_changed), + manager); + + g_object_set_qdata_full (G_OBJECT (manager), + quark_layout_alpha, alpha, + (GDestroyNotify) g_object_unref); + + clutter_timeline_start (timeline); + + return alpha; +} + +/* XXX:2.0 - Remove */ +static gdouble +layout_manager_real_get_animation_progress (ClutterLayoutManager *manager) +{ + ClutterAlpha *alpha; + + alpha = g_object_get_qdata (G_OBJECT (manager), quark_layout_alpha); + if (alpha == NULL) + return 1.0; + + return clutter_alpha_get_alpha (alpha); +} + +/* XXX:2.0 - Remove */ +static void +layout_manager_real_end_animation (ClutterLayoutManager *manager) +{ + ClutterTimeline *timeline; + ClutterAlpha *alpha; + + alpha = g_object_get_qdata (G_OBJECT (manager), quark_layout_alpha); + if (alpha == NULL) + return; + + timeline = clutter_alpha_get_timeline (alpha); + g_assert (timeline != NULL); + + if (clutter_timeline_is_playing (timeline)) + clutter_timeline_stop (timeline); + + g_signal_handlers_disconnect_by_func (timeline, + G_CALLBACK (clutter_layout_manager_end_animation), + manager); + g_signal_handlers_disconnect_by_func (timeline, + G_CALLBACK (clutter_layout_manager_layout_changed), + manager); + + g_object_set_qdata (G_OBJECT (manager), quark_layout_alpha, NULL); + + clutter_layout_manager_layout_changed (manager); +} + +static void +clutter_layout_manager_class_init (ClutterLayoutManagerClass *klass) +{ + quark_layout_meta = + g_quark_from_static_string ("clutter-layout-manager-child-meta"); + + /* XXX:2.0 - Remove */ + quark_layout_alpha = + g_quark_from_static_string ("clutter-layout-manager-alpha"); + + klass->get_preferred_width = layout_manager_real_get_preferred_width; + klass->get_preferred_height = layout_manager_real_get_preferred_height; + klass->allocate = layout_manager_real_allocate; + klass->create_child_meta = layout_manager_real_create_child_meta; + klass->get_child_meta_type = layout_manager_real_get_child_meta_type; + + /* XXX:2.0 - Remove */ + klass->begin_animation = layout_manager_real_begin_animation; + klass->get_animation_progress = layout_manager_real_get_animation_progress; + klass->end_animation = layout_manager_real_end_animation; + klass->set_container = layout_manager_real_set_container; + + /** + * ClutterLayoutManager::layout-changed: + * @manager: the #ClutterLayoutManager that emitted the signal + * + * The ::layout-changed signal is emitted each time a layout manager + * has been changed. Every #ClutterActor using the @manager instance + * as a layout manager should connect a handler to the ::layout-changed + * signal and queue a relayout on themselves: + * + * |[ + * static void layout_changed (ClutterLayoutManager *manager, + * ClutterActor *self) + * { + * clutter_actor_queue_relayout (self); + * } + * ... + * self->manager = g_object_ref_sink (manager); + * g_signal_connect (self->manager, "layout-changed", + * G_CALLBACK (layout_changed), + * self); + * ]| + * + * Sub-classes of #ClutterLayoutManager that implement a layout that + * can be controlled or changed using parameters should emit the + * ::layout-changed signal whenever one of the parameters changes, + * by using clutter_layout_manager_layout_changed(). + * + * Since: 1.2 + */ + manager_signals[LAYOUT_CHANGED] = + g_signal_new (I_("layout-changed"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterLayoutManagerClass, + layout_changed), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +clutter_layout_manager_init (ClutterLayoutManager *manager) +{ +} + +/** + * clutter_layout_manager_get_preferred_width: + * @manager: a #ClutterLayoutManager + * @container: the #ClutterContainer using @manager + * @for_height: the height for which the width should be computed, or -1 + * @min_width_p: (out) (allow-none): return location for the minimum width + * of the layout, or %NULL + * @nat_width_p: (out) (allow-none): return location for the natural width + * of the layout, or %NULL + * + * Computes the minimum and natural widths of the @container according + * to @manager. + * + * See also clutter_actor_get_preferred_width() + * + * Since: 1.2 + */ +void +clutter_layout_manager_get_preferred_width (ClutterLayoutManager *manager, + ClutterContainer *container, + gfloat for_height, + gfloat *min_width_p, + gfloat *nat_width_p) +{ + ClutterLayoutManagerClass *klass; + + g_return_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager)); + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + + klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager); + klass->get_preferred_width (manager, container, for_height, + min_width_p, + nat_width_p); +} + +/** + * clutter_layout_manager_get_preferred_height: + * @manager: a #ClutterLayoutManager + * @container: the #ClutterContainer using @manager + * @for_width: the width for which the height should be computed, or -1 + * @min_height_p: (out) (allow-none): return location for the minimum height + * of the layout, or %NULL + * @nat_height_p: (out) (allow-none): return location for the natural height + * of the layout, or %NULL + * + * Computes the minimum and natural heights of the @container according + * to @manager. + * + * See also clutter_actor_get_preferred_height() + * + * Since: 1.2 + */ +void +clutter_layout_manager_get_preferred_height (ClutterLayoutManager *manager, + ClutterContainer *container, + gfloat for_width, + gfloat *min_height_p, + gfloat *nat_height_p) +{ + ClutterLayoutManagerClass *klass; + + g_return_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager)); + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + + klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager); + klass->get_preferred_height (manager, container, for_width, + min_height_p, + nat_height_p); +} + +/** + * clutter_layout_manager_allocate: + * @manager: a #ClutterLayoutManager + * @container: the #ClutterContainer using @manager + * @allocation: the #ClutterActorBox containing the allocated area + * of @container + * @flags: the allocation flags + * + * Allocates the children of @container given an area + * + * See also clutter_actor_allocate() + * + * Since: 1.2 + */ +void +clutter_layout_manager_allocate (ClutterLayoutManager *manager, + ClutterContainer *container, + const ClutterActorBox *allocation, + ClutterAllocationFlags flags) +{ + ClutterLayoutManagerClass *klass; + + g_return_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager)); + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + g_return_if_fail (allocation != NULL); + + klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager); + klass->allocate (manager, container, allocation, flags); +} + +/** + * clutter_layout_manager_layout_changed: + * @manager: a #ClutterLayoutManager + * + * Emits the #ClutterLayoutManager::layout-changed signal on @manager + * + * This function should only be called by implementations of the + * #ClutterLayoutManager class + * + * Since: 1.2 + */ +void +clutter_layout_manager_layout_changed (ClutterLayoutManager *manager) +{ + gpointer is_frozen; + + g_return_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager)); + + is_frozen = g_object_get_data (G_OBJECT (manager), "freeze-change"); + if (is_frozen == NULL) + g_signal_emit (manager, manager_signals[LAYOUT_CHANGED], 0); + else + CLUTTER_NOTE (LAYOUT, "Layout manager '%s'[%p] has been frozen", + G_OBJECT_TYPE_NAME (manager), + manager); +} + +/** + * clutter_layout_manager_set_container: + * @manager: a #ClutterLayoutManager + * @container: (allow-none): a #ClutterContainer using @manager + * + * If the #ClutterLayoutManager sub-class allows it, allow + * adding a weak reference of the @container using @manager + * from within the layout manager + * + * The layout manager should not increase the reference + * count of the @container + * + * Since: 1.2 + */ +void +clutter_layout_manager_set_container (ClutterLayoutManager *manager, + ClutterContainer *container) +{ + ClutterLayoutManagerClass *klass; + + g_return_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager)); + g_return_if_fail (container == NULL || CLUTTER_IS_CONTAINER (container)); + + klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager); + if (klass->set_container) + klass->set_container (manager, container); +} + +GType +_clutter_layout_manager_get_child_meta_type (ClutterLayoutManager *manager) +{ + return CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager)->get_child_meta_type (manager); +} + +static inline ClutterLayoutMeta * +create_child_meta (ClutterLayoutManager *manager, + ClutterContainer *container, + ClutterActor *actor) +{ + ClutterLayoutManagerClass *klass; + ClutterLayoutMeta *meta = NULL; + + layout_manager_freeze_layout_change (manager); + + klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager); + if (klass->get_child_meta_type (manager) != G_TYPE_INVALID) + meta = klass->create_child_meta (manager, container, actor); + + layout_manager_thaw_layout_change (manager); + + return meta; +} + +static inline ClutterLayoutMeta * +get_child_meta (ClutterLayoutManager *manager, + ClutterContainer *container, + ClutterActor *actor) +{ + ClutterLayoutMeta *layout = NULL; + + layout = g_object_get_qdata (G_OBJECT (actor), quark_layout_meta); + if (layout != NULL) + { + ClutterChildMeta *child = CLUTTER_CHILD_META (layout); + + if (layout->manager == manager && + child->container == container && + child->actor == actor) + return layout; + + /* if the LayoutMeta referenced is not attached to the + * layout manager then we simply ask the layout manager + * to replace it with the right one + */ + } + + layout = create_child_meta (manager, container, actor); + if (layout != NULL) + { + g_assert (CLUTTER_IS_LAYOUT_META (layout)); + g_object_set_qdata_full (G_OBJECT (actor), quark_layout_meta, + layout, + (GDestroyNotify) g_object_unref); + return layout; + } + + return NULL; +} + +/** + * clutter_layout_manager_get_child_meta: + * @manager: a #ClutterLayoutManager + * @container: a #ClutterContainer using @manager + * @actor: a #ClutterActor child of @container + * + * Retrieves the #ClutterLayoutMeta that the layout @manager associated + * to the @actor child of @container, eventually by creating one if the + * #ClutterLayoutManager supports layout properties + * + * Return value: (transfer none): a #ClutterLayoutMeta, or %NULL if the + * #ClutterLayoutManager does not have layout properties. The returned + * layout meta instance is owned by the #ClutterLayoutManager and it + * should not be unreferenced + * + * Since: 1.0 + */ +ClutterLayoutMeta * +clutter_layout_manager_get_child_meta (ClutterLayoutManager *manager, + ClutterContainer *container, + ClutterActor *actor) +{ + g_return_val_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager), NULL); + g_return_val_if_fail (CLUTTER_IS_CONTAINER (container), NULL); + g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), NULL); + + return get_child_meta (manager, container, actor); +} + +static inline gboolean +layout_set_property_internal (ClutterLayoutManager *manager, + GObject *gobject, + GParamSpec *pspec, + const GValue *value) +{ + if (pspec->flags & G_PARAM_CONSTRUCT_ONLY) + { + g_warning ("%s: Child property '%s' of the layout manager of " + "type '%s' is constructor-only", + G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (manager)); + return FALSE; + } + + if (!(pspec->flags & G_PARAM_WRITABLE)) + { + g_warning ("%s: Child property '%s' of the layout manager of " + "type '%s' is not writable", + G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (manager)); + return FALSE; + } + + g_object_set_property (gobject, pspec->name, value); + + return TRUE; +} + +static inline gboolean +layout_get_property_internal (ClutterLayoutManager *manager, + GObject *gobject, + GParamSpec *pspec, + GValue *value) +{ + if (!(pspec->flags & G_PARAM_READABLE)) + { + g_warning ("%s: Child property '%s' of the layout manager of " + "type '%s' is not readable", + G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (manager)); + return FALSE; + } + + g_object_get_property (gobject, pspec->name, value); + + return TRUE; +} + +/** + * clutter_layout_manager_child_set: + * @manager: a #ClutterLayoutManager + * @container: a #ClutterContainer using @manager + * @actor: a #ClutterActor child of @container + * @first_property: the first property name + * @...: a list of property name and value pairs + * + * Sets a list of properties and their values on the #ClutterLayoutMeta + * associated by @manager to a child of @container + * + * Languages bindings should use clutter_layout_manager_child_set_property() + * instead + * + * Since: 1.2 + */ +void +clutter_layout_manager_child_set (ClutterLayoutManager *manager, + ClutterContainer *container, + ClutterActor *actor, + const gchar *first_property, + ...) +{ + ClutterLayoutMeta *meta; + GObjectClass *klass; + const gchar *pname; + va_list var_args; + + g_return_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager)); + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + g_return_if_fail (first_property != NULL); + + meta = get_child_meta (manager, container, actor); + if (meta == NULL) + { + g_warning ("Layout managers of type '%s' do not support " + "layout metadata", + g_type_name (G_OBJECT_TYPE (manager))); + return; + } + + klass = G_OBJECT_GET_CLASS (meta); + + va_start (var_args, first_property); + + pname = first_property; + while (pname) + { + GValue value = G_VALUE_INIT; + GParamSpec *pspec; + gchar *error; + gboolean res; + + pspec = g_object_class_find_property (klass, pname); + if (pspec == NULL) + { + g_warning ("%s: Layout managers of type '%s' have no layout " + "property named '%s'", + G_STRLOC, G_OBJECT_TYPE_NAME (manager), pname); + break; + } + + G_VALUE_COLLECT_INIT (&value, G_PARAM_SPEC_VALUE_TYPE (pspec), + var_args, 0, + &error); + + if (error) + { + g_warning ("%s: %s", G_STRLOC, error); + g_free (error); + break; + } + + res = layout_set_property_internal (manager, G_OBJECT (meta), + pspec, + &value); + + g_value_unset (&value); + + if (!res) + break; + + pname = va_arg (var_args, gchar*); + } + + va_end (var_args); +} + +/** + * clutter_layout_manager_child_set_property: + * @manager: a #ClutterLayoutManager + * @container: a #ClutterContainer using @manager + * @actor: a #ClutterActor child of @container + * @property_name: the name of the property to set + * @value: a #GValue with the value of the property to set + * + * Sets a property on the #ClutterLayoutMeta created by @manager and + * attached to a child of @container + * + * Since: 1.2 + */ +void +clutter_layout_manager_child_set_property (ClutterLayoutManager *manager, + ClutterContainer *container, + ClutterActor *actor, + const gchar *property_name, + const GValue *value) +{ + ClutterLayoutMeta *meta; + GObjectClass *klass; + GParamSpec *pspec; + + g_return_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager)); + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + g_return_if_fail (property_name != NULL); + g_return_if_fail (value != NULL); + + meta = get_child_meta (manager, container, actor); + if (meta == NULL) + { + g_warning ("Layout managers of type '%s' do not support " + "layout metadata", + g_type_name (G_OBJECT_TYPE (manager))); + return; + } + + klass = G_OBJECT_GET_CLASS (meta); + + pspec = g_object_class_find_property (klass, property_name); + if (pspec == NULL) + { + g_warning ("%s: Layout managers of type '%s' have no layout " + "property named '%s'", + G_STRLOC, G_OBJECT_TYPE_NAME (manager), property_name); + return; + } + + layout_set_property_internal (manager, G_OBJECT (meta), pspec, value); +} + +/** + * clutter_layout_manager_child_get: + * @manager: a #ClutterLayoutManager + * @container: a #ClutterContainer using @manager + * @actor: a #ClutterActor child of @container + * @first_property: the name of the first property + * @...: a list of property name and return location for the value pairs + * + * Retrieves the values for a list of properties out of the + * #ClutterLayoutMeta created by @manager and attached to the + * child of a @container + * + * Since: 1.2 + */ +void +clutter_layout_manager_child_get (ClutterLayoutManager *manager, + ClutterContainer *container, + ClutterActor *actor, + const gchar *first_property, + ...) +{ + ClutterLayoutMeta *meta; + GObjectClass *klass; + const gchar *pname; + va_list var_args; + + g_return_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager)); + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + g_return_if_fail (first_property != NULL); + + meta = get_child_meta (manager, container, actor); + if (meta == NULL) + { + g_warning ("Layout managers of type '%s' do not support " + "layout metadata", + g_type_name (G_OBJECT_TYPE (manager))); + return; + } + + klass = G_OBJECT_GET_CLASS (meta); + + va_start (var_args, first_property); + + pname = first_property; + while (pname) + { + GValue value = G_VALUE_INIT; + GParamSpec *pspec; + gchar *error; + gboolean res; + + pspec = g_object_class_find_property (klass, pname); + if (pspec == NULL) + { + g_warning ("%s: Layout managers of type '%s' have no layout " + "property named '%s'", + G_STRLOC, G_OBJECT_TYPE_NAME (manager), pname); + break; + } + + g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec)); + + res = layout_get_property_internal (manager, G_OBJECT (meta), + pspec, + &value); + if (!res) + { + g_value_unset (&value); + break; + } + + G_VALUE_LCOPY (&value, var_args, 0, &error); + if (error) + { + g_warning ("%s: %s", G_STRLOC, error); + g_free (error); + g_value_unset (&value); + break; + } + + g_value_unset (&value); + + pname = va_arg (var_args, gchar*); + } + + va_end (var_args); +} + +/** + * clutter_layout_manager_child_get_property: + * @manager: a #ClutterLayoutManager + * @container: a #ClutterContainer using @manager + * @actor: a #ClutterActor child of @container + * @property_name: the name of the property to get + * @value: a #GValue with the value of the property to get + * + * Gets a property on the #ClutterLayoutMeta created by @manager and + * attached to a child of @container + * + * The #GValue must already be initialized to the type of the property + * and has to be unset with g_value_unset() after extracting the real + * value out of it + * + * Since: 1.2 + */ +void +clutter_layout_manager_child_get_property (ClutterLayoutManager *manager, + ClutterContainer *container, + ClutterActor *actor, + const gchar *property_name, + GValue *value) +{ + ClutterLayoutMeta *meta; + GObjectClass *klass; + GParamSpec *pspec; + + g_return_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager)); + g_return_if_fail (CLUTTER_IS_CONTAINER (container)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + g_return_if_fail (property_name != NULL); + g_return_if_fail (value != NULL); + + meta = get_child_meta (manager, container, actor); + if (meta == NULL) + { + g_warning ("Layout managers of type %s do not support " + "layout metadata", + g_type_name (G_OBJECT_TYPE (manager))); + return; + } + + klass = G_OBJECT_GET_CLASS (meta); + + pspec = g_object_class_find_property (klass, property_name); + if (pspec == NULL) + { + g_warning ("%s: Layout managers of type '%s' have no layout " + "property named '%s'", + G_STRLOC, G_OBJECT_TYPE_NAME (manager), property_name); + return; + } + + layout_get_property_internal (manager, G_OBJECT (meta), pspec, value); +} + +/** + * clutter_layout_manager_find_child_property: + * @manager: a #ClutterLayoutManager + * @name: the name of the property + * + * Retrieves the #GParamSpec for the layout property @name inside + * the #ClutterLayoutMeta sub-class used by @manager + * + * Return value: (transfer none): a #GParamSpec describing the property, + * or %NULL if no property with that name exists. The returned + * #GParamSpec is owned by the layout manager and should not be + * modified or freed + * + * Since: 1.2 + */ +GParamSpec * +clutter_layout_manager_find_child_property (ClutterLayoutManager *manager, + const gchar *name) +{ + ClutterLayoutManagerClass *klass; + GObjectClass *meta_klass; + GParamSpec *pspec; + GType meta_type; + + klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager); + meta_type = klass->get_child_meta_type (manager); + if (meta_type == G_TYPE_INVALID) + return NULL; + + meta_klass = g_type_class_ref (meta_type); + + pspec = g_object_class_find_property (meta_klass, name); + + g_type_class_unref (meta_klass); + + return pspec; +} + +/** + * clutter_layout_manager_list_child_properties: + * @manager: a #ClutterLayoutManager + * @n_pspecs: (out): return location for the number of returned + * #GParamSpecs + * + * Retrieves all the #GParamSpecs for the layout properties + * stored inside the #ClutterLayoutMeta sub-class used by @manager + * + * Return value: (transfer full) (array length=n_pspecs): the newly-allocated, + * %NULL-terminated array of #GParamSpecs. Use g_free() to free the + * resources allocated for the array + * + * Since: 1.2 + */ +GParamSpec ** +clutter_layout_manager_list_child_properties (ClutterLayoutManager *manager, + guint *n_pspecs) +{ + ClutterLayoutManagerClass *klass; + GObjectClass *meta_klass; + GParamSpec **pspecs; + GType meta_type; + + klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager); + meta_type = klass->get_child_meta_type (manager); + if (meta_type == G_TYPE_INVALID) + return NULL; + + meta_klass = g_type_class_ref (meta_type); + + pspecs = g_object_class_list_properties (meta_klass, n_pspecs); + + g_type_class_unref (meta_klass); + + return pspecs; +} diff --git a/clutter/clutter/clutter-layout-manager.h b/clutter/clutter/clutter-layout-manager.h new file mode 100644 index 0000000..8bb9099 --- /dev/null +++ b/clutter/clutter/clutter-layout-manager.h @@ -0,0 +1,227 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * 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 . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_LAYOUT_MANAGER_H__ +#define __CLUTTER_LAYOUT_MANAGER_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_LAYOUT_MANAGER (clutter_layout_manager_get_type ()) +#define CLUTTER_LAYOUT_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_LAYOUT_MANAGER, ClutterLayoutManager)) +#define CLUTTER_IS_LAYOUT_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_LAYOUT_MANAGER)) +#define CLUTTER_LAYOUT_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_LAYOUT_MANAGER, ClutterLayoutManagerClass)) +#define CLUTTER_IS_LAYOUT_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_LAYOUT_MANAGER)) +#define CLUTTER_LAYOUT_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_LAYOUT_MANAGER, ClutterLayoutManagerClass)) + +typedef struct _ClutterLayoutManagerClass ClutterLayoutManagerClass; + +/** + * ClutterLayoutManager: + * + * The #ClutterLayoutManager structure contains only private data + * and should be accessed using the provided API + * + * Since: 1.2 + */ +struct _ClutterLayoutManager +{ + /*< private >*/ + GInitiallyUnowned parent_instance; + + gpointer CLUTTER_PRIVATE_FIELD (dummy); +}; + +/** + * ClutterLayoutManagerClass: + * @get_preferred_width: virtual function; override to provide a preferred + * width for the layout manager. See also the get_preferred_width() + * virtual function in #ClutterActor + * @get_preferred_height: virtual function; override to provide a preferred + * height for the layout manager. See also the get_preferred_height() + * virtual function in #ClutterActor + * @allocate: virtual function; override to allocate the children of the + * layout manager. See also the allocate() virtual function in + * #ClutterActor + * @set_container: virtual function; override to set a back pointer + * on the #ClutterContainer using the layout manager. The implementation + * should not take a reference on the container, but just take a weak + * reference, to avoid potential leaks due to reference cycles + * @get_child_meta_type: virtual function; override to return the #GType + * of the #ClutterLayoutMeta sub-class used by the #ClutterLayoutManager + * @create_child_meta: virtual function; override to create a + * #ClutterLayoutMeta instance associated to a #ClutterContainer and a + * child #ClutterActor, used to maintain layout manager specific properties + * @begin_animation: virtual function; override to control the animation + * of a #ClutterLayoutManager with the given duration and easing mode. + * This virtual function is deprecated, and it should not be overridden + * in newly written code. + * @end_animation: virtual function; override to end an animation started + * by clutter_layout_manager_begin_animation(). This virtual function is + * deprecated, and it should not be overriden in newly written code. + * @get_animation_progress: virtual function; override to control the + * progress of the animation of a #ClutterLayoutManager. This virtual + * function is deprecated, and it should not be overridden in newly written + * code. + * @layout_changed: class handler for the #ClutterLayoutManager::layout-changed + * signal + * + * The #ClutterLayoutManagerClass structure contains only private + * data and should be accessed using the provided API + * + * Since: 1.2 + */ +struct _ClutterLayoutManagerClass +{ + /*< private >*/ + GInitiallyUnownedClass parent_class; + + /*< public >*/ + void (* get_preferred_width) (ClutterLayoutManager *manager, + ClutterContainer *container, + gfloat for_height, + gfloat *min_width_p, + gfloat *nat_width_p); + void (* get_preferred_height) (ClutterLayoutManager *manager, + ClutterContainer *container, + gfloat for_width, + gfloat *min_height_p, + gfloat *nat_height_p); + void (* allocate) (ClutterLayoutManager *manager, + ClutterContainer *container, + const ClutterActorBox *allocation, + ClutterAllocationFlags flags); + + void (* set_container) (ClutterLayoutManager *manager, + ClutterContainer *container); + + GType (* get_child_meta_type) (ClutterLayoutManager *manager); + ClutterLayoutMeta *(* create_child_meta) (ClutterLayoutManager *manager, + ClutterContainer *container, + ClutterActor *actor); + + /* deprecated */ + ClutterAlpha * (* begin_animation) (ClutterLayoutManager *manager, + guint duration, + gulong mode); + /* deprecated */ + gdouble (* get_animation_progress) (ClutterLayoutManager *manager); + /* deprecated */ + void (* end_animation) (ClutterLayoutManager *manager); + + void (* layout_changed) (ClutterLayoutManager *manager); + + /*< private >*/ + /* padding for future expansion */ + void (* _clutter_padding_1) (void); + void (* _clutter_padding_2) (void); + void (* _clutter_padding_3) (void); + void (* _clutter_padding_4) (void); + void (* _clutter_padding_5) (void); + void (* _clutter_padding_6) (void); + void (* _clutter_padding_7) (void); + void (* _clutter_padding_8) (void); +}; + +CLUTTER_AVAILABLE_IN_1_2 +GType clutter_layout_manager_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_2 +void clutter_layout_manager_get_preferred_width (ClutterLayoutManager *manager, + ClutterContainer *container, + gfloat for_height, + gfloat *min_width_p, + gfloat *nat_width_p); +CLUTTER_AVAILABLE_IN_1_2 +void clutter_layout_manager_get_preferred_height (ClutterLayoutManager *manager, + ClutterContainer *container, + gfloat for_width, + gfloat *min_height_p, + gfloat *nat_height_p); +CLUTTER_AVAILABLE_IN_1_2 +void clutter_layout_manager_allocate (ClutterLayoutManager *manager, + ClutterContainer *container, + const ClutterActorBox *allocation, + ClutterAllocationFlags flags); + +CLUTTER_AVAILABLE_IN_1_2 +void clutter_layout_manager_set_container (ClutterLayoutManager *manager, + ClutterContainer *container); +CLUTTER_AVAILABLE_IN_1_2 +void clutter_layout_manager_layout_changed (ClutterLayoutManager *manager); + +CLUTTER_AVAILABLE_IN_1_2 +GParamSpec * clutter_layout_manager_find_child_property (ClutterLayoutManager *manager, + const gchar *name); +CLUTTER_AVAILABLE_IN_1_2 +GParamSpec ** clutter_layout_manager_list_child_properties (ClutterLayoutManager *manager, + guint *n_pspecs); + +CLUTTER_AVAILABLE_IN_1_2 +ClutterLayoutMeta *clutter_layout_manager_get_child_meta (ClutterLayoutManager *manager, + ClutterContainer *container, + ClutterActor *actor); + +CLUTTER_AVAILABLE_IN_1_2 +void clutter_layout_manager_child_set (ClutterLayoutManager *manager, + ClutterContainer *container, + ClutterActor *actor, + const gchar *first_property, + ...) G_GNUC_NULL_TERMINATED; +CLUTTER_AVAILABLE_IN_1_2 +void clutter_layout_manager_child_get (ClutterLayoutManager *manager, + ClutterContainer *container, + ClutterActor *actor, + const gchar *first_property, + ...) G_GNUC_NULL_TERMINATED; +CLUTTER_AVAILABLE_IN_1_2 +void clutter_layout_manager_child_set_property (ClutterLayoutManager *manager, + ClutterContainer *container, + ClutterActor *actor, + const gchar *property_name, + const GValue *value); +CLUTTER_AVAILABLE_IN_1_2 +void clutter_layout_manager_child_get_property (ClutterLayoutManager *manager, + ClutterContainer *container, + ClutterActor *actor, + const gchar *property_name, + GValue *value); + +CLUTTER_DEPRECATED_IN_1_12 +ClutterAlpha * clutter_layout_manager_begin_animation (ClutterLayoutManager *manager, + guint duration, + gulong mode); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_layout_manager_end_animation (ClutterLayoutManager *manager); +CLUTTER_DEPRECATED_IN_1_12 +gdouble clutter_layout_manager_get_animation_progress (ClutterLayoutManager *manager); + +G_END_DECLS + +#endif /* __CLUTTER_LAYOUT_MANAGER_H__ */ diff --git a/clutter/clutter/clutter-layout-meta.c b/clutter/clutter/clutter-layout-meta.c new file mode 100644 index 0000000..971079e --- /dev/null +++ b/clutter/clutter/clutter-layout-meta.c @@ -0,0 +1,147 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * 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 . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-layout-meta + * @short_description: Wrapper for actors inside a layout manager + * + * #ClutterLayoutMeta is a wrapper object created by #ClutterLayoutManager + * implementations in order to store child-specific data and properties. + * + * A #ClutterLayoutMeta wraps a #ClutterActor inside a #ClutterContainer + * using a #ClutterLayoutManager. + * + * #ClutterLayoutMeta is available since Clutter 1.2 + */ +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-layout-meta.h" +#include "clutter-debug.h" +#include "clutter-private.h" + +G_DEFINE_ABSTRACT_TYPE (ClutterLayoutMeta, + clutter_layout_meta, + CLUTTER_TYPE_CHILD_META); + +enum +{ + PROP_0, + + PROP_MANAGER, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +static void +clutter_layout_meta_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterLayoutMeta *layout_meta = CLUTTER_LAYOUT_META (object); + + switch (prop_id) + { + case PROP_MANAGER: + layout_meta->manager = g_value_get_object (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_layout_meta_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterLayoutMeta *layout_meta = CLUTTER_LAYOUT_META (object); + + switch (prop_id) + { + case PROP_MANAGER: + g_value_set_object (value, layout_meta->manager); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_layout_meta_class_init (ClutterLayoutMetaClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GParamSpec *pspec; + + gobject_class->set_property = clutter_layout_meta_set_property; + gobject_class->get_property = clutter_layout_meta_get_property; + + /** + * ClutterLayoutMeta:manager: + * + * The #ClutterLayoutManager that created this #ClutterLayoutMeta. + * + * Since: 1.2 + */ + pspec = g_param_spec_object ("manager", + P_("Manager"), + P_("The manager that created this data"), + CLUTTER_TYPE_LAYOUT_MANAGER, + G_PARAM_CONSTRUCT_ONLY | + CLUTTER_PARAM_READWRITE); + obj_props[PROP_MANAGER] = pspec; + g_object_class_install_property (gobject_class, PROP_MANAGER, pspec); +} + +static void +clutter_layout_meta_init (ClutterLayoutMeta *self) +{ +} + +/** + * clutter_layout_meta_get_manager: + * @data: a #ClutterLayoutMeta + * + * Retrieves the actor wrapped by @data + * + * Return value: (transfer none): a #ClutterLayoutManager + * + * Since: 1.2 + */ +ClutterLayoutManager * +clutter_layout_meta_get_manager (ClutterLayoutMeta *data) +{ + g_return_val_if_fail (CLUTTER_IS_LAYOUT_META (data), NULL); + + return data->manager; +} diff --git a/clutter/clutter/clutter-layout-meta.h b/clutter/clutter/clutter-layout-meta.h new file mode 100644 index 0000000..6de0b47 --- /dev/null +++ b/clutter/clutter/clutter-layout-meta.h @@ -0,0 +1,103 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * 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 . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_LAYOUT_META_H__ +#define __CLUTTER_LAYOUT_META_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_LAYOUT_META (clutter_layout_meta_get_type ()) +#define CLUTTER_LAYOUT_META(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_LAYOUT_META, ClutterLayoutMeta)) +#define CLUTTER_IS_LAYOUT_META(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_LAYOUT_META)) +#define CLUTTER_LAYOUT_META_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_LAYOUT_META, ClutterLayoutMetaClass)) +#define CLUTTER_IS_LAYOUT_META_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_LAYOUT_META)) +#define CLUTTER_LAYOUT_META_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_LAYOUT_META, ClutterLayoutMetaClass)) + +/* ClutterLayoutMeta is defined in clutter-types.h */ + +typedef struct _ClutterLayoutMetaClass ClutterLayoutMetaClass; + +/** + * ClutterLayoutMeta: + * @manager: the layout manager handling this data + * + * Sub-class of #ClutterChildMeta specific for layout managers + * + * A #ClutterLayoutManager sub-class should create a #ClutterLayoutMeta + * instance by overriding the #ClutterLayoutManager::create_child_meta() + * virtual function + * + * Since: 1.2 + */ +struct _ClutterLayoutMeta +{ + /*< private >*/ + ClutterChildMeta parent_instance; + + /*< public >*/ + ClutterLayoutManager *manager; + + /*< private >*/ + /* padding */ + gint32 dummy0; + gpointer dummy1; +}; + +/** + * ClutterLayoutMetaClass: + * + * The #ClutterLayoutMetaClass contains only private data and + * should never be accessed directly + * + * Since: 1.2 + */ +struct _ClutterLayoutMetaClass +{ + /*< private >*/ + ClutterChildMetaClass parent_class; + + /* padding, for expansion */ + void (*_clutter_padding1) (void); + void (*_clutter_padding2) (void); + void (*_clutter_padding3) (void); + void (*_clutter_padding4) (void); +}; + +CLUTTER_AVAILABLE_IN_1_2 +GType clutter_layout_meta_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_2 +ClutterLayoutManager *clutter_layout_meta_get_manager (ClutterLayoutMeta *data); + +G_END_DECLS + +#endif /* __CLUTTER_LAYOUT_META_H__ */ diff --git a/clutter/clutter/clutter-macros.h b/clutter/clutter/clutter-macros.h new file mode 100644 index 0000000..21cb304 --- /dev/null +++ b/clutter/clutter/clutter-macros.h @@ -0,0 +1,395 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2012 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 . + */ + +#ifndef __CLUTTER_MACROS_H__ +#define __CLUTTER_MACROS_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +/** + * CLUTTER_FLAVOUR: + * + * GL Windowing system used + * + * Since: 0.4 + * + * Deprecated: 1.10: The macro evaluates to "deprecated" as Clutter can be + * compiled with multiple windowing system backends. Use the various + * CLUTTER_WINDOWING_* macros to detect the windowing system that Clutter + * is being compiled against, and the type check macros for the + * #ClutterBackend for a run-time check. + */ +#define CLUTTER_FLAVOUR "deprecated" + +/** + * CLUTTER_COGL: + * + * Cogl (internal GL abstraction utility library) backend. Can be "gl" or + * "gles" currently + * + * Since: 0.4 + * + * Deprecated: 1.10: The macro evaluates to "deprecated" as Cogl can be + * compiled against multiple GL implementations. + */ +#define CLUTTER_COGL "deprecated" + +/** + * CLUTTER_STAGE_TYPE: + * + * The default GObject type for the Clutter stage. + * + * Since: 0.8 + * + * Deprecated: 1.10: The macro evaluates to "deprecated" as Clutter can + * be compiled against multiple windowing systems. You can use the + * CLUTTER_WINDOWING_* macros for compile-time checks, and the type + * check macros for run-time checks. + */ +#define CLUTTER_STAGE_TYPE "deprecated" + +/** + * CLUTTER_NO_FPU: + * + * Set to 1 if Clutter was built without FPU (i.e fixed math), 0 otherwise + * + * Deprecated: 0.6: This macro is no longer defined (identical code is used + * regardless the presence of FPU). + */ +#define CLUTTER_NO_FPU (0) + +/* some structures are meant to be opaque and still be allocated on the stack; + * in order to avoid people poking at their internals, we use this macro to + * ensure that users don't accidentally access a struct private members. + * + * we use the CLUTTER_COMPILATION define to allow us easier access, though. + */ +#ifdef CLUTTER_COMPILATION +#define CLUTTER_PRIVATE_FIELD(x) x +#else +#define CLUTTER_PRIVATE_FIELD(x) clutter_private_ ## x +#endif + +#ifndef _CLUTTER_EXTERN +#define _CLUTTER_EXTERN extern +#endif + +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || \ + __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 4) +#define _CLUTTER_GNUC_DO_PRAGMA(x) _Pragma(G_STRINGIFY (x)) +#define _CLUTTER_DEPRECATED_MACRO _CLUTTER_GNUC_DO_PRAGMA(GCC warning "Deprecated macro") +#define _CLUTTER_DEPRECATED_MACRO_FOR(f) _CLUTTER_GNUC_DO_PRAGMA(GCC warning #f) +#else +#define _CLUTTER_DEPRECATED_MACRO +#define _CLUTTER_DEPRECATED_MACRO_FOR(f) +#endif + +/* these macros are used to mark deprecated functions, and thus have to be + * exposed in a public header. + * + * do *not* use them in other libraries depending on Clutter: use G_DEPRECATED + * and G_DEPRECATED_FOR, or use your own wrappers around them. + */ +#ifdef CLUTTER_DISABLE_DEPRECATION_WARNINGS +#define CLUTTER_DEPRECATED _CLUTTER_EXTERN +#define CLUTTER_DEPRECATED_FOR(f) _CLUTTER_EXTERN +#define CLUTTER_UNAVAILABLE(maj,min) _CLUTTER_EXTERN +#define CLUTTER_DEPRECATED_MACRO +#define CLUTTER_DEPRECATED_MACRO_FOR(f) +#else +#define CLUTTER_DEPRECATED G_DEPRECATED _CLUTTER_EXTERN +#define CLUTTER_DEPRECATED_FOR(f) G_DEPRECATED_FOR(f) _CLUTTER_EXTERN +#define CLUTTER_UNAVAILABLE(maj,min) G_UNAVAILABLE(maj,min) _CLUTTER_EXTERN +#define CLUTTER_DEPRECATED_MACRO _CLUTTER_DEPRECATED_MACRO +#define CLUTTER_DEPRECATED_MACRO_FOR(f) _CLUTTER_DEPRECATED_MACRO_FOR(f) +#endif + +#define CLUTTER_AVAILABLE_IN_ALL _CLUTTER_EXTERN + +#define CLUTTER_AVAILABLE_IN_MUTTER _CLUTTER_EXTERN + +/** + * CLUTTER_VERSION_MIN_REQUIRED: + * + * A macro that should be defined by the user prior to including the + * clutter.h header. + * + * The definition should be one of the predefined Clutter version macros, + * such as: %CLUTTER_VERSION_1_0, %CLUTTER_VERSION_1_2, ... + * + * This macro defines the lower bound for the Clutter API to be used. + * + * If a function has been deprecated in a newer version of Clutter, it + * is possible to use this symbol to avoid the compiler warnings without + * disabling warnings for every deprecated function. + * + * Since: 1.10 + */ +#ifndef CLUTTER_VERSION_MIN_REQUIRED +# define CLUTTER_VERSION_MIN_REQUIRED (CLUTTER_VERSION_CUR_STABLE) +#endif + +/** + * CLUTTER_VERSION_MAX_ALLOWED: + * + * A macro that should be define by the user prior to including the + * clutter.h header. + * + * The definition should be one of the predefined Clutter version macros, + * such as: %CLUTTER_VERSION_1_0, %CLUTTER_VERSION_1_2, ... + * + * This macro defines the upper bound for the Clutter API to be used. + * + * If a function has been introduced in a newer version of Clutter, it + * is possible to use this symbol to get compiler warnings when trying + * to use that function. + * + * Since: 1.10 + */ +#ifndef CLUTTER_VERSION_MAX_ALLOWED +# if CLUTTER_VERSION_MIN_REQUIRED > CLUTTER_VERSION_PREV_STABLE +# define CLUTTER_VERSION_MAX_ALLOWED CLUTTER_VERSION_MIN_REQUIRED +# else +# define CLUTTER_VERSION_MAX_ALLOWED CLUTTER_VERSION_CUR_STABLE +# endif +#endif + +/* sanity checks */ +#if CLUTTER_VERSION_MAX_ALLOWED < CLUTTER_VERSION_MIN_REQUIRED +# error "CLUTTER_VERSION_MAX_ALLOWED must be >= CLUTTER_VERSION_MIN_REQUIRED" +#endif +#if CLUTTER_VERSION_MIN_REQUIRED < CLUTTER_VERSION_1_0 +# error "CLUTTER_VERSION_MIN_REQUIRED must be >= CLUTTER_VERSION_1_0" +#endif + +/* XXX: Every new stable minor release should add a set of macros here */ + +#if CLUTTER_VERSION_MIN_REQUIRED >= CLUTTER_VERSION_1_0 +# define CLUTTER_DEPRECATED_IN_1_0 CLUTTER_DEPRECATED +# define CLUTTER_DEPRECATED_IN_1_0_FOR(f) CLUTTER_DEPRECATED_FOR(f) +#else +# define CLUTTER_DEPRECATED_IN_1_0 _CLUTTER_EXTERN +# define CLUTTER_DEPRECATED_IN_1_0_FOR(f) _CLUTTER_EXTERN +#endif + +#if CLUTTER_VERSION_MAX_ALLOWED < CLUTTER_VERSION_1_0 +# define CLUTTER_AVAILABLE_IN_1_0 CLUTTER_UNAVAILABLE(1, 0) +#else +# define CLUTTER_AVAILABLE_IN_1_0 _CLUTTER_EXTERN +#endif + +#if CLUTTER_VERSION_MIN_REQUIRED >= CLUTTER_VERSION_1_2 +# define CLUTTER_DEPRECATED_IN_1_2 CLUTTER_DEPRECATED +# define CLUTTER_DEPRECATED_IN_1_2_FOR(f) CLUTTER_DEPRECATED_FOR(f) +#else +# define CLUTTER_DEPRECATED_IN_1_2 _CLUTTER_EXTERN +# define CLUTTER_DEPRECATED_IN_1_2_FOR(f) _CLUTTER_EXTERN +#endif + +#if CLUTTER_VERSION_MAX_ALLOWED < CLUTTER_VERSION_1_2 +# define CLUTTER_AVAILABLE_IN_1_2 CLUTTER_UNAVAILABLE(1, 2) +#else +# define CLUTTER_AVAILABLE_IN_1_2 _CLUTTER_EXTERN +#endif + +#if CLUTTER_VERSION_MIN_REQUIRED >= CLUTTER_VERSION_1_4 +# define CLUTTER_DEPRECATED_IN_1_4 CLUTTER_DEPRECATED +# define CLUTTER_DEPRECATED_IN_1_4_FOR(f) CLUTTER_DEPRECATED_FOR(f) +#else +# define CLUTTER_DEPRECATED_IN_1_4 _CLUTTER_EXTERN +# define CLUTTER_DEPRECATED_IN_1_4_FOR(f) _CLUTTER_EXTERN +#endif + +#if CLUTTER_VERSION_MAX_ALLOWED < CLUTTER_VERSION_1_4 +# define CLUTTER_AVAILABLE_IN_1_4 CLUTTER_UNAVAILABLE(1, 4) +#else +# define CLUTTER_AVAILABLE_IN_1_4 _CLUTTER_EXTERN +#endif + +#if CLUTTER_VERSION_MIN_REQUIRED >= CLUTTER_VERSION_1_6 +# define CLUTTER_DEPRECATED_IN_1_6 CLUTTER_DEPRECATED +# define CLUTTER_DEPRECATED_IN_1_6_FOR(f) CLUTTER_DEPRECATED_FOR(f) +#else +# define CLUTTER_DEPRECATED_IN_1_6 _CLUTTER_EXTERN +# define CLUTTER_DEPRECATED_IN_1_6_FOR(f) _CLUTTER_EXTERN +#endif + +#if CLUTTER_VERSION_MAX_ALLOWED < CLUTTER_VERSION_1_6 +# define CLUTTER_AVAILABLE_IN_1_6 CLUTTER_UNAVAILABLE(1, 6) +#else +# define CLUTTER_AVAILABLE_IN_1_6 _CLUTTER_EXTERN +#endif + +#if CLUTTER_VERSION_MIN_REQUIRED >= CLUTTER_VERSION_1_8 +# define CLUTTER_DEPRECATED_IN_1_8 CLUTTER_DEPRECATED +# define CLUTTER_DEPRECATED_IN_1_8_FOR(f) CLUTTER_DEPRECATED_FOR(f) +#else +# define CLUTTER_DEPRECATED_IN_1_8 _CLUTTER_EXTERN +# define CLUTTER_DEPRECATED_IN_1_8_FOR(f) _CLUTTER_EXTERN +#endif + +#if CLUTTER_VERSION_MAX_ALLOWED < CLUTTER_VERSION_1_8 +# define CLUTTER_AVAILABLE_IN_1_8 CLUTTER_UNAVAILABLE(1, 8) +#else +# define CLUTTER_AVAILABLE_IN_1_8 _CLUTTER_EXTERN +#endif + +#if CLUTTER_VERSION_MIN_REQUIRED >= CLUTTER_VERSION_1_10 +# define CLUTTER_DEPRECATED_IN_1_10 CLUTTER_DEPRECATED +# define CLUTTER_DEPRECATED_IN_1_10_FOR(f) CLUTTER_DEPRECATED_FOR(f) +#else +# define CLUTTER_DEPRECATED_IN_1_10 _CLUTTER_EXTERN +# define CLUTTER_DEPRECATED_IN_1_10_FOR(f) _CLUTTER_EXTERN +#endif + +#if CLUTTER_VERSION_MAX_ALLOWED < CLUTTER_VERSION_1_10 +# define CLUTTER_AVAILABLE_IN_1_10 CLUTTER_UNAVAILABLE(1, 10) +#else +# define CLUTTER_AVAILABLE_IN_1_10 _CLUTTER_EXTERN +#endif + +#if CLUTTER_VERSION_MIN_REQUIRED >= CLUTTER_VERSION_1_12 +# define CLUTTER_DEPRECATED_IN_1_12 CLUTTER_DEPRECATED +# define CLUTTER_DEPRECATED_IN_1_12_FOR(f) CLUTTER_DEPRECATED_FOR(f) +#else +# define CLUTTER_DEPRECATED_IN_1_12 _CLUTTER_EXTERN +# define CLUTTER_DEPRECATED_IN_1_12_FOR(f) _CLUTTER_EXTERN +#endif + +#define CLUTTER_DEPRECATED_IN_MUTTER CLUTTER_DEPRECATED + +#if CLUTTER_VERSION_MAX_ALLOWED < CLUTTER_VERSION_1_12 +# define CLUTTER_AVAILABLE_IN_1_12 CLUTTER_UNAVAILABLE(1, 12) +#else +# define CLUTTER_AVAILABLE_IN_1_12 _CLUTTER_EXTERN +#endif + +#if CLUTTER_VERSION_MIN_REQUIRED >= CLUTTER_VERSION_1_14 +# define CLUTTER_DEPRECATED_IN_1_14 CLUTTER_DEPRECATED +# define CLUTTER_DEPRECATED_IN_1_14_FOR(f) CLUTTER_DEPRECATED_FOR(f) +#else +# define CLUTTER_DEPRECATED_IN_1_14 _CLUTTER_EXTERN +# define CLUTTER_DEPRECATED_IN_1_14_FOR(f) _CLUTTER_EXTERN +#endif + +#if CLUTTER_VERSION_MAX_ALLOWED < CLUTTER_VERSION_1_14 +# define CLUTTER_AVAILABLE_IN_1_14 CLUTTER_UNAVAILABLE(1, 14) +#else +# define CLUTTER_AVAILABLE_IN_1_14 _CLUTTER_EXTERN +#endif + +#if CLUTTER_VERSION_MIN_REQUIRED >= CLUTTER_VERSION_1_16 +# define CLUTTER_DEPRECATED_IN_1_16 CLUTTER_DEPRECATED +# define CLUTTER_DEPRECATED_IN_1_16_FOR(f) CLUTTER_DEPRECATED_FOR(f) +#else +# define CLUTTER_DEPRECATED_IN_1_16 _CLUTTER_EXTERN +# define CLUTTER_DEPRECATED_IN_1_16_FOR(f) _CLUTTER_EXTERN +#endif + +#if CLUTTER_VERSION_MAX_ALLOWED < CLUTTER_VERSION_1_16 +# define CLUTTER_AVAILABLE_IN_1_16 CLUTTER_UNAVAILABLE(1, 16) +#else +# define CLUTTER_AVAILABLE_IN_1_16 _CLUTTER_EXTERN +#endif + +#if CLUTTER_VERSION_MIN_REQUIRED >= CLUTTER_VERSION_1_18 +# define CLUTTER_DEPRECATED_IN_1_18 CLUTTER_DEPRECATED +# define CLUTTER_DEPRECATED_IN_1_18_FOR(f) CLUTTER_DEPRECATED_FOR(f) +#else +# define CLUTTER_DEPRECATED_IN_1_18 _CLUTTER_EXTERN +# define CLUTTER_DEPRECATED_IN_1_18_FOR(f) _CLUTTER_EXTERN +#endif + +#if CLUTTER_VERSION_MAX_ALLOWED < CLUTTER_VERSION_1_18 +# define CLUTTER_AVAILABLE_IN_1_18 CLUTTER_UNAVAILABLE(1, 18) +#else +# define CLUTTER_AVAILABLE_IN_1_18 _CLUTTER_EXTERN +#endif + +#if CLUTTER_VERSION_MIN_REQUIRED >= CLUTTER_VERSION_1_20 +# define CLUTTER_DEPRECATED_IN_1_20 CLUTTER_DEPRECATED +# define CLUTTER_DEPRECATED_IN_1_20_FOR(f) CLUTTER_DEPRECATED_FOR(f) +#else +# define CLUTTER_DEPRECATED_IN_1_20 _CLUTTER_EXTERN +# define CLUTTER_DEPRECATED_IN_1_20_FOR(f) _CLUTTER_EXTERN +#endif + +#if CLUTTER_VERSION_MAX_ALLOWED < CLUTTER_VERSION_1_20 +# define CLUTTER_AVAILABLE_IN_1_20 CLUTTER_UNAVAILABLE(1, 20) +#else +# define CLUTTER_AVAILABLE_IN_1_20 _CLUTTER_EXTERN +#endif + +#if CLUTTER_VERSION_MIN_REQUIRED >= CLUTTER_VERSION_1_22 +# define CLUTTER_DEPRECATED_IN_1_22 CLUTTER_DEPRECATED +# define CLUTTER_DEPRECATED_IN_1_22_FOR(f) CLUTTER_DEPRECATED_FOR(f) +#else +# define CLUTTER_DEPRECATED_IN_1_22 _CLUTTER_EXTERN +# define CLUTTER_DEPRECATED_IN_1_22_FOR(f) _CLUTTER_EXTERN +#endif + +#if CLUTTER_VERSION_MAX_ALLOWED < CLUTTER_VERSION_1_22 +# define CLUTTER_AVAILABLE_IN_1_22 CLUTTER_UNAVAILABLE(1, 22) +#else +# define CLUTTER_AVAILABLE_IN_1_22 _CLUTTER_EXTERN +#endif + +#if CLUTTER_VERSION_MIN_REQUIRED >= CLUTTER_VERSION_1_24 +# define CLUTTER_DEPRECATED_IN_1_24 CLUTTER_DEPRECATED +# define CLUTTER_DEPRECATED_IN_1_24_FOR(f) CLUTTER_DEPRECATED_FOR(f) +# define CLUTTER_MACRO_DEPRECATED_IN_1_24 CLUTTER_DEPRECATED_MACRO +# define CLUTTER_MACRO_DEPRECATED_IN_1_24_FOR(f) CLUTTER_DEPRECATED_MACRO_FOR(f) +#else +# define CLUTTER_DEPRECATED_IN_1_24 _CLUTTER_EXTERN +# define CLUTTER_DEPRECATED_IN_1_24_FOR(f) _CLUTTER_EXTERN +# define CLUTTER_MACRO_DEPRECATED_IN_1_24 +# define CLUTTER_MACRO_DEPRECATED_IN_1_24_FOR(f) +#endif + +#if CLUTTER_VERSION_MAX_ALLOWED < CLUTTER_VERSION_1_24 +# define CLUTTER_AVAILABLE_IN_1_24 CLUTTER_UNAVAILABLE(1, 24) +#else +# define CLUTTER_AVAILABLE_IN_1_24 _CLUTTER_EXTERN +#endif + +#if CLUTTER_VERSION_MIN_REQUIRED >= CLUTTER_VERSION_1_26 +# define CLUTTER_DEPRECATED_IN_1_26 CLUTTER_DEPRECATED +# define CLUTTER_DEPRECATED_IN_1_26_FOR(f) CLUTTER_DEPRECATED_FOR(f) +# define CLUTTER_MACRO_DEPRECATED_IN_1_26 CLUTTER_DEPRECATED_MACRO +# define CLUTTER_MACRO_DEPRECATED_IN_1_26_FOR(f) CLUTTER_DEPRECATED_MACRO_FOR(f) +#else +# define CLUTTER_DEPRECATED_IN_1_26 _CLUTTER_EXTERN +# define CLUTTER_DEPRECATED_IN_1_26_FOR(f) _CLUTTER_EXTERN +# define CLUTTER_MACRO_DEPRECATED_IN_1_26 +# define CLUTTER_MACRO_DEPRECATED_IN_1_26_FOR(f) +#endif + +#if CLUTTER_VERSION_MAX_ALLOWED < CLUTTER_VERSION_1_26 +# define CLUTTER_AVAILABLE_IN_1_26 CLUTTER_UNAVAILABLE(1, 26) +#else +# define CLUTTER_AVAILABLE_IN_1_26 _CLUTTER_EXTERN +#endif + +#endif /* __CLUTTER_MACROS_H__ */ diff --git a/clutter/clutter/clutter-main.c b/clutter/clutter/clutter-main.c new file mode 100644 index 0000000..0f85db6 --- /dev/null +++ b/clutter/clutter/clutter-main.c @@ -0,0 +1,3735 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +/** + * SECTION:clutter-main + * @short_description: Various 'global' Clutter functions. + * + * Functions to retrieve various global Clutter resources and other utility + * functions for mainloops, events and threads + * + * ## The Clutter Threading Model + * + * Clutter is *thread-aware*: all operations performed by Clutter are assumed + * to be under the Big Clutter Lock, which is created when the threading is + * initialized through clutter_init(), and entered when calling user-related + * code during event handling and actor drawing. + * + * The only safe and portable way to use the Clutter API in a multi-threaded + * environment is to only access the Clutter API from a thread that did called + * clutter_init() and clutter_main(). + * + * The common pattern for using threads with Clutter is to use worker threads + * to perform blocking operations and then install idle or timeout sources with + * the result when the thread finishes, and update the UI from those callbacks. + * + * For a working example of how to use a worker thread to update the UI, see + * [threads.c](https://git.gnome.org/browse/clutter/tree/examples/threads.c?h=clutter-1.18) + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#include "clutter-actor-private.h" +#include "clutter-backend-private.h" +#include "clutter-config.h" +#include "clutter-debug.h" +#include "clutter-device-manager-private.h" +#include "clutter-event-private.h" +#include "clutter-feature.h" +#include "clutter-main.h" +#include "clutter-master-clock.h" +#include "clutter-mutter.h" +#include "clutter-private.h" +#include "clutter-settings-private.h" +#include "clutter-stage-manager.h" +#include "clutter-stage-private.h" +#include "clutter-version.h" /* For flavour define */ + +#ifdef CLUTTER_WINDOWING_X11 +#include "x11/clutter-backend-x11.h" +#endif +#ifdef CLUTTER_WINDOWING_EGL +#include "egl/clutter-backend-eglnative.h" +#endif + +#include +#include + +#include "cally.h" /* For accessibility support */ + +/* main context */ +static ClutterMainContext *ClutterCntx = NULL; +G_LOCK_DEFINE_STATIC (ClutterCntx); + +/* main lock and locking/unlocking functions */ +static GMutex clutter_threads_mutex; +static GCallback clutter_threads_lock = NULL; +static GCallback clutter_threads_unlock = NULL; + +/* command line options */ +static gboolean clutter_is_initialized = FALSE; +static gboolean clutter_show_fps = FALSE; +static gboolean clutter_fatal_warnings = FALSE; +static gboolean clutter_disable_mipmap_text = FALSE; +static gboolean clutter_use_fuzzy_picking = FALSE; +static gboolean clutter_enable_accessibility = TRUE; +static gboolean clutter_sync_to_vblank = TRUE; + +static guint clutter_default_fps = 60; + +static ClutterTextDirection clutter_text_direction = CLUTTER_TEXT_DIRECTION_LTR; + +static guint clutter_main_loop_level = 0; +static GSList *main_loops = NULL; + +/* debug flags */ +guint clutter_debug_flags = 0; +guint clutter_paint_debug_flags = 0; +guint clutter_pick_debug_flags = 0; + +const guint clutter_major_version = CLUTTER_MAJOR_VERSION; +const guint clutter_minor_version = CLUTTER_MINOR_VERSION; +const guint clutter_micro_version = CLUTTER_MICRO_VERSION; + +#ifdef CLUTTER_ENABLE_DEBUG +static const GDebugKey clutter_debug_keys[] = { + { "misc", CLUTTER_DEBUG_MISC }, + { "actor", CLUTTER_DEBUG_ACTOR }, + { "texture", CLUTTER_DEBUG_TEXTURE }, + { "event", CLUTTER_DEBUG_EVENT }, + { "paint", CLUTTER_DEBUG_PAINT }, + { "pick", CLUTTER_DEBUG_PICK }, + { "pango", CLUTTER_DEBUG_PANGO }, + { "backend", CLUTTER_DEBUG_BACKEND }, + { "scheduler", CLUTTER_DEBUG_SCHEDULER }, + { "script", CLUTTER_DEBUG_SCRIPT }, + { "shader", CLUTTER_DEBUG_SHADER }, + { "animation", CLUTTER_DEBUG_ANIMATION }, + { "layout", CLUTTER_DEBUG_LAYOUT }, + { "clipping", CLUTTER_DEBUG_CLIPPING }, + { "oob-transforms", CLUTTER_DEBUG_OOB_TRANSFORMS }, +}; +#endif /* CLUTTER_ENABLE_DEBUG */ + +static const GDebugKey clutter_pick_debug_keys[] = { + { "nop-picking", CLUTTER_DEBUG_NOP_PICKING }, + { "dump-pick-buffers", CLUTTER_DEBUG_DUMP_PICK_BUFFERS }, +}; + +static const GDebugKey clutter_paint_debug_keys[] = { + { "disable-swap-events", CLUTTER_DEBUG_DISABLE_SWAP_EVENTS }, + { "disable-clipped-redraws", CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS }, + { "redraws", CLUTTER_DEBUG_REDRAWS }, + { "paint-volumes", CLUTTER_DEBUG_PAINT_VOLUMES }, + { "disable-culling", CLUTTER_DEBUG_DISABLE_CULLING }, + { "disable-offscreen-redirect", CLUTTER_DEBUG_DISABLE_OFFSCREEN_REDIRECT }, + { "continuous-redraw", CLUTTER_DEBUG_CONTINUOUS_REDRAW }, + { "paint-deform-tiles", CLUTTER_DEBUG_PAINT_DEFORM_TILES }, +}; + +static void +clutter_threads_impl_lock (void) +{ + g_mutex_lock (&clutter_threads_mutex); +} + +static void +clutter_threads_impl_unlock (void) +{ + /* we need to trylock here, in case the lock hasn't been acquired; on + * various systems trying to release a mutex that hasn't been acquired + * will cause a run-time error. trylock() will either fail, in which + * case we can release the lock we own; or it will succeeds, in which + * case we need to release the lock we just acquired. so we ignore the + * returned value. + * + * see: https://bugs.gnome.org/679439 + */ + g_mutex_trylock (&clutter_threads_mutex); + g_mutex_unlock (&clutter_threads_mutex); +} + +static inline void +clutter_threads_init_default (void) +{ + g_mutex_init (&clutter_threads_mutex); + + if (clutter_threads_lock == NULL) + clutter_threads_lock = clutter_threads_impl_lock; + + if (clutter_threads_unlock == NULL) + clutter_threads_unlock = clutter_threads_impl_unlock; +} + +#define ENVIRONMENT_GROUP "Environment" +#define DEBUG_GROUP "Debug" + +static void +clutter_config_read_from_key_file (GKeyFile *keyfile) +{ + GError *key_error = NULL; + gboolean bool_value; + gint int_value; + gchar *str_value; + + if (!g_key_file_has_group (keyfile, ENVIRONMENT_GROUP)) + return; + + str_value = + g_key_file_get_string (keyfile, ENVIRONMENT_GROUP, + "Backends", + &key_error); + if (key_error != NULL) + g_clear_error (&key_error); + else + clutter_try_set_windowing_backend (str_value); + + g_free (str_value); + + str_value = + g_key_file_get_string (keyfile, ENVIRONMENT_GROUP, + "Drivers", + &key_error); + if (key_error != NULL) + g_clear_error (&key_error); + else + clutter_set_allowed_drivers (str_value); + + g_free (str_value); + + bool_value = + g_key_file_get_boolean (keyfile, ENVIRONMENT_GROUP, + "ShowFps", + &key_error); + + if (key_error != NULL) + g_clear_error (&key_error); + else + clutter_show_fps = bool_value; + + bool_value = + g_key_file_get_boolean (keyfile, ENVIRONMENT_GROUP, + "DisableMipmappedText", + &key_error); + + if (key_error != NULL) + g_clear_error (&key_error); + else + clutter_disable_mipmap_text = bool_value; + + bool_value = + g_key_file_get_boolean (keyfile, ENVIRONMENT_GROUP, + "UseFuzzyPicking", + &key_error); + + if (key_error != NULL) + g_clear_error (&key_error); + else + clutter_use_fuzzy_picking = bool_value; + + bool_value = + g_key_file_get_boolean (keyfile, ENVIRONMENT_GROUP, + "EnableAccessibility", + &key_error); + + if (key_error != NULL) + g_clear_error (&key_error); + else + clutter_enable_accessibility = bool_value; + + bool_value = + g_key_file_get_boolean (keyfile, ENVIRONMENT_GROUP, + "SyncToVblank", + &key_error); + + if (key_error != NULL) + g_clear_error (&key_error); + else + clutter_sync_to_vblank = bool_value; + + int_value = + g_key_file_get_integer (keyfile, ENVIRONMENT_GROUP, + "DefaultFps", + &key_error); + + if (key_error != NULL) + g_clear_error (&key_error); + else + clutter_default_fps = int_value; + + str_value = + g_key_file_get_string (keyfile, ENVIRONMENT_GROUP, + "TextDirection", + &key_error); + + if (key_error != NULL) + g_clear_error (&key_error); + else + { + if (g_strcmp0 (str_value, "rtl") == 0) + clutter_text_direction = CLUTTER_TEXT_DIRECTION_RTL; + else + clutter_text_direction = CLUTTER_TEXT_DIRECTION_LTR; + } + + g_free (str_value); +} + +#ifdef CLUTTER_ENABLE_DEBUG +static void +clutter_debug_read_from_key_file (GKeyFile *keyfile) +{ + GError *key_error = NULL; + gchar *value; + + if (!g_key_file_has_group (keyfile, DEBUG_GROUP)) + return; + + value = g_key_file_get_value (keyfile, DEBUG_GROUP, + "Debug", + &key_error); + if (key_error == NULL) + { + clutter_debug_flags |= + g_parse_debug_string (value, + clutter_debug_keys, + G_N_ELEMENTS (clutter_debug_keys)); + } + else + g_clear_error (&key_error); + + g_free (value); + + value = g_key_file_get_value (keyfile, DEBUG_GROUP, + "PaintDebug", + &key_error); + if (key_error == NULL) + { + clutter_paint_debug_flags |= + g_parse_debug_string (value, + clutter_paint_debug_keys, + G_N_ELEMENTS (clutter_paint_debug_keys)); + } + else + g_clear_error (&key_error); + + g_free (value); + + value = g_key_file_get_value (keyfile, DEBUG_GROUP, + "PickDebug", + &key_error); + if (key_error == NULL) + { + clutter_pick_debug_flags |= + g_parse_debug_string (value, + clutter_pick_debug_keys, + G_N_ELEMENTS (clutter_pick_debug_keys)); + } + else + g_clear_error (&key_error); + + g_free (value); +} +#endif + +static void +clutter_config_read_from_file (const gchar *config_path) +{ + ClutterSettings *settings = clutter_settings_get_default (); + GKeyFile *key_file = g_key_file_new (); + GError *error = NULL; + + g_key_file_load_from_file (key_file, config_path, G_KEY_FILE_NONE, &error); + if (error == NULL) + { + CLUTTER_NOTE (MISC, "Reading configuration from '%s'", config_path); + + clutter_config_read_from_key_file (key_file); +#ifdef CLUTTER_ENABLE_DEBUG + clutter_debug_read_from_key_file (key_file); +#endif + _clutter_settings_read_from_key_file (settings, key_file); + } + else + { + g_warning ("Unable to read configuration settings from '%s': %s", + config_path, + error->message); + g_error_free (error); + } + + g_key_file_free (key_file); +} + +static void +clutter_config_read (void) +{ + gchar *config_path; + + config_path = g_build_filename (CLUTTER_SYSCONFDIR, + "clutter-1.0", + "settings.ini", + NULL); + if (g_file_test (config_path, G_FILE_TEST_EXISTS)) + clutter_config_read_from_file (config_path); + + g_free (config_path); + + config_path = g_build_filename (g_get_user_config_dir (), + "clutter-1.0", + "settings.ini", + NULL); + if (g_file_test (config_path, G_FILE_TEST_EXISTS)) + clutter_config_read_from_file (config_path); + + g_free (config_path); +} + +/** + * clutter_get_show_fps: + * + * Returns whether Clutter should print out the frames per second on the + * console. You can enable this setting either using the + * CLUTTER_SHOW_FPS environment variable or passing + * the --clutter-show-fps command line argument. * + * + * Return value: %TRUE if Clutter should show the FPS. + * + * Since: 0.4 + * + * Deprecated: 1.10: This function does not do anything. Use the environment + * variable or the configuration file to determine whether Clutter should + * print out the FPS counter on the console. + */ +gboolean +clutter_get_show_fps (void) +{ + return FALSE; +} + +gboolean +_clutter_context_get_show_fps (void) +{ + ClutterMainContext *context = _clutter_context_get_default (); + + return context->show_fps; +} + +/** + * clutter_get_accessibility_enabled: + * + * Returns whether Clutter has accessibility support enabled. As + * least, a value of TRUE means that there are a proper AtkUtil + * implementation available + * + * Return value: %TRUE if Clutter has accessibility support enabled + * + * Since: 1.4 + */ +gboolean +clutter_get_accessibility_enabled (void) +{ + return cally_get_cally_initialized (); +} + +/** + * clutter_disable_accessibility: + * + * Disable loading the accessibility support. It has the same effect + * as setting the environment variable + * CLUTTER_DISABLE_ACCESSIBILITY. For the same reason, this method + * should be called before clutter_init(). + * + * Since: 1.14 + */ +void +clutter_disable_accessibility (void) +{ + if (clutter_is_initialized) + { + g_warning ("clutter_disable_accessibility() can only be called before " + "initializing Clutter."); + return; + } + + clutter_enable_accessibility = FALSE; +} + +/** + * clutter_redraw: + * + * Forces a redraw of the entire stage. Applications should never use this + * function, but queue a redraw using clutter_actor_queue_redraw(). + * + * This function should only be used by libraries integrating Clutter from + * within another toolkit. + * + * Deprecated: 1.10: Use clutter_stage_ensure_redraw() instead. + */ +void +clutter_redraw (ClutterStage *stage) +{ + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + clutter_stage_ensure_redraw (stage); +} + +/** + * clutter_set_motion_events_enabled: + * @enable: %TRUE to enable per-actor motion events + * + * Sets whether per-actor motion events should be enabled or not on + * all #ClutterStages managed by Clutter. + * + * If @enable is %FALSE the following events will not work: + * + * - ClutterActor::motion-event, except on the #ClutterStage + * - ClutterActor::enter-event + * - ClutterActor::leave-event + * + * Since: 0.6 + * + * Deprecated: 1.8: Use clutter_stage_set_motion_events_enabled() instead. + */ +void +clutter_set_motion_events_enabled (gboolean enable) +{ + ClutterStageManager *stage_manager; + ClutterMainContext *context; + const GSList *l; + + enable = !!enable; + + context = _clutter_context_get_default (); + if (context->motion_events_per_actor == enable) + return; + + /* store the flag for later query and for newly created stages */ + context->motion_events_per_actor = enable; + + /* propagate the change to all stages */ + stage_manager = clutter_stage_manager_get_default (); + + for (l = clutter_stage_manager_peek_stages (stage_manager); + l != NULL; + l = l->next) + { + clutter_stage_set_motion_events_enabled (l->data, enable); + } +} + +/** + * clutter_get_motion_events_enabled: + * + * Gets whether the per-actor motion events are enabled. + * + * Return value: %TRUE if the motion events are enabled + * + * Since: 0.6 + * + * Deprecated: 1.8: Use clutter_stage_get_motion_events_enabled() instead. + */ +gboolean +clutter_get_motion_events_enabled (void) +{ + return _clutter_context_get_motion_events_enabled (); +} + +void +_clutter_id_to_color (guint id_, + ClutterColor *col) +{ + ClutterMainContext *ctx; + gint red, green, blue; + + ctx = _clutter_context_get_default (); + + if (ctx->fb_g_mask == 0) + { + /* Figure out framebuffer masks used for pick */ + cogl_get_bitmasks (&ctx->fb_r_mask, + &ctx->fb_g_mask, + &ctx->fb_b_mask, NULL); + + ctx->fb_r_mask_used = ctx->fb_r_mask; + ctx->fb_g_mask_used = ctx->fb_g_mask; + ctx->fb_b_mask_used = ctx->fb_b_mask; + + /* XXX - describe what "fuzzy picking" is */ + if (clutter_use_fuzzy_picking) + { + ctx->fb_r_mask_used--; + ctx->fb_g_mask_used--; + ctx->fb_b_mask_used--; + } + } + + /* compute the numbers we'll store in the components */ + red = (id_ >> (ctx->fb_g_mask_used+ctx->fb_b_mask_used)) + & (0xff >> (8-ctx->fb_r_mask_used)); + green = (id_ >> ctx->fb_b_mask_used) + & (0xff >> (8-ctx->fb_g_mask_used)); + blue = (id_) + & (0xff >> (8-ctx->fb_b_mask_used)); + + /* shift left bits a bit and add one, this circumvents + * at least some potential rounding errors in GL/GLES + * driver / hw implementation. + */ + if (ctx->fb_r_mask_used != ctx->fb_r_mask) + red = red * 2; + if (ctx->fb_g_mask_used != ctx->fb_g_mask) + green = green * 2; + if (ctx->fb_b_mask_used != ctx->fb_b_mask) + blue = blue * 2; + + /* shift up to be full 8bit values */ + red = (red << (8 - ctx->fb_r_mask)) | (0x7f >> (ctx->fb_r_mask_used)); + green = (green << (8 - ctx->fb_g_mask)) | (0x7f >> (ctx->fb_g_mask_used)); + blue = (blue << (8 - ctx->fb_b_mask)) | (0x7f >> (ctx->fb_b_mask_used)); + + col->red = red; + col->green = green; + col->blue = blue; + col->alpha = 0xff; + + /* XXX: We rotate the nibbles of the colors here so that there is a + * visible variation between colors of sequential actor identifiers; + * otherwise pick buffers dumped to an image will pretty much just look + * black. + */ + if (G_UNLIKELY (clutter_pick_debug_flags & CLUTTER_DEBUG_DUMP_PICK_BUFFERS)) + { + col->red = (col->red << 4) | (col->red >> 4); + col->green = (col->green << 4) | (col->green >> 4); + col->blue = (col->blue << 4) | (col->blue >> 4); + } +} + +guint +_clutter_pixel_to_id (guchar pixel[4]) +{ + ClutterMainContext *ctx; + gint red, green, blue; + guint retval; + + ctx = _clutter_context_get_default (); + + /* reduce the pixel components to the number of bits actually used of the + * 8bits. + */ + if (G_UNLIKELY (clutter_pick_debug_flags & CLUTTER_DEBUG_DUMP_PICK_BUFFERS)) + { + guchar tmp; + + /* XXX: In _clutter_id_to_color we rotated the nibbles of the colors so + * that there is a visible variation between colors of sequential actor + * identifiers (otherwise pick buffers dumped to an image will pretty + * much just look black.) Here we reverse that rotation. + */ + tmp = ((pixel[0] << 4) | (pixel[0] >> 4)); + red = tmp >> (8 - ctx->fb_r_mask); + tmp = ((pixel[1] << 4) | (pixel[1] >> 4)); + green = tmp >> (8 - ctx->fb_g_mask); + tmp = ((pixel[2] << 4) | (pixel[2] >> 4)); + blue = tmp >> (8 - ctx->fb_b_mask); + } + else + { + red = pixel[0] >> (8 - ctx->fb_r_mask); + green = pixel[1] >> (8 - ctx->fb_g_mask); + blue = pixel[2] >> (8 - ctx->fb_b_mask); + } + + /* divide potentially by two if 'fuzzy' */ + red = red >> (ctx->fb_r_mask - ctx->fb_r_mask_used); + green = green >> (ctx->fb_g_mask - ctx->fb_g_mask_used); + blue = blue >> (ctx->fb_b_mask - ctx->fb_b_mask_used); + + /* combine the correct per component values into the final id */ + retval = blue + + (green << ctx->fb_b_mask_used) + + (red << (ctx->fb_b_mask_used + ctx->fb_g_mask_used)); + + return retval; +} + +static CoglPangoFontMap * +clutter_context_get_pango_fontmap (void) +{ + ClutterMainContext *self; + CoglPangoFontMap *font_map; + gdouble resolution; + gboolean use_mipmapping; + + self = _clutter_context_get_default (); + if (G_LIKELY (self->font_map != NULL)) + return self->font_map; + + font_map = COGL_PANGO_FONT_MAP (cogl_pango_font_map_new ()); + + resolution = clutter_backend_get_resolution (self->backend); + cogl_pango_font_map_set_resolution (font_map, resolution); + + use_mipmapping = !clutter_disable_mipmap_text; + cogl_pango_font_map_set_use_mipmapping (font_map, use_mipmapping); + + self->font_map = font_map; + + return self->font_map; +} + +static ClutterTextDirection +clutter_get_text_direction (void) +{ + ClutterTextDirection dir = CLUTTER_TEXT_DIRECTION_LTR; + const gchar *direction; + + direction = g_getenv ("CLUTTER_TEXT_DIRECTION"); + if (direction && *direction != '\0') + { + if (strcmp (direction, "rtl") == 0) + dir = CLUTTER_TEXT_DIRECTION_RTL; + else if (strcmp (direction, "ltr") == 0) + dir = CLUTTER_TEXT_DIRECTION_LTR; + } + else + { + /* Re-use GTK+'s LTR/RTL handling */ + const char *e = g_dgettext ("gtk30", "default:LTR"); + + if (strcmp (e, "default:RTL") == 0) + dir = CLUTTER_TEXT_DIRECTION_RTL; + else if (strcmp (e, "default:LTR") == 0) + dir = CLUTTER_TEXT_DIRECTION_LTR; + else + g_warning ("Whoever translated default:LTR did so wrongly."); + } + + CLUTTER_NOTE (MISC, "Text direction: %s", + dir == CLUTTER_TEXT_DIRECTION_RTL ? "rtl" : "ltr"); + + return dir; +} + +/** + * clutter_main_quit: + * + * Terminates the Clutter mainloop. + */ +void +clutter_main_quit (void) +{ + if (main_loops == NULL) + { + g_critical ("Calling clutter_main_quit() without calling clutter_main() " + "is not allowed. If you are using another main loop, use the " + "appropriate API to terminate it."); + return; + } + + CLUTTER_NOTE (MISC, "Terminating main loop level %d", clutter_main_loop_level); + + g_main_loop_quit (main_loops->data); +} + +/** + * clutter_main_level: + * + * Retrieves the depth of the Clutter mainloop. + * + * Return value: The level of the mainloop. + */ +gint +clutter_main_level (void) +{ + return clutter_main_loop_level; +} + +/** + * clutter_main: + * + * Starts the Clutter mainloop. + */ +void +clutter_main (void) +{ + GMainLoop *loop; + + if (!_clutter_context_is_initialized ()) + { + g_warning ("Called clutter_main() but Clutter wasn't initialised. " + "You must call clutter_init() first."); + return; + } + + clutter_main_loop_level++; + + CLUTTER_NOTE (MISC, "Entering main loop level %d", clutter_main_loop_level); + + loop = g_main_loop_new (NULL, TRUE); + main_loops = g_slist_prepend (main_loops, loop); + + if (g_main_loop_is_running (main_loops->data)) + { + _clutter_threads_release_lock (); + g_main_loop_run (loop); + _clutter_threads_acquire_lock (); + } + + main_loops = g_slist_remove (main_loops, loop); + + g_main_loop_unref (loop); + + CLUTTER_NOTE (MISC, "Leaving main loop level %d", clutter_main_loop_level); + + clutter_main_loop_level--; +} + +/** + * clutter_threads_init: + * + * Initialises the Clutter threading mechanism, so that Clutter API can be + * called by multiple threads, using clutter_threads_enter() and + * clutter_threads_leave() to mark the critical sections. + * + * You must call g_thread_init() before this function. + * + * This function must be called before clutter_init(). + * + * It is safe to call this function multiple times. + * + * Since: 0.4 + * + * Deprecated: 1.10: This function does not do anything. Threading support + * is initialized when Clutter is initialized. + */ +void +clutter_threads_init (void) +{ +} + +/** + * clutter_threads_set_lock_functions: (skip) + * @enter_fn: function called when aquiring the Clutter main lock + * @leave_fn: function called when releasing the Clutter main lock + * + * Allows the application to replace the standard method that + * Clutter uses to protect its data structures. Normally, Clutter + * creates a single #GMutex that is locked by clutter_threads_enter(), + * and released by clutter_threads_leave(); using this function an + * application provides, instead, a function @enter_fn that is + * called by clutter_threads_enter() and a function @leave_fn that is + * called by clutter_threads_leave(). + * + * The functions must provide at least same locking functionality + * as the default implementation, but can also do extra application + * specific processing. + * + * As an example, consider an application that has its own recursive + * lock that when held, holds the Clutter lock as well. When Clutter + * unlocks the Clutter lock when entering a recursive main loop, the + * application must temporarily release its lock as well. + * + * Most threaded Clutter apps won't need to use this method. + * + * This method must be called before clutter_init(), and cannot + * be called multiple times. + * + * Since: 0.4 + */ +void +clutter_threads_set_lock_functions (GCallback enter_fn, + GCallback leave_fn) +{ + g_return_if_fail (clutter_threads_lock == NULL && + clutter_threads_unlock == NULL); + + clutter_threads_lock = enter_fn; + clutter_threads_unlock = leave_fn; +} + +gboolean +_clutter_threads_dispatch (gpointer data) +{ + ClutterThreadsDispatch *dispatch = data; + gboolean ret = FALSE; + + _clutter_threads_acquire_lock (); + + if (!g_source_is_destroyed (g_main_current_source ())) + ret = dispatch->func (dispatch->data); + + _clutter_threads_release_lock (); + + return ret; +} + +void +_clutter_threads_dispatch_free (gpointer data) +{ + ClutterThreadsDispatch *dispatch = data; + + /* XXX - we cannot hold the thread lock here because the main loop + * might destroy a source while still in the dispatcher function; so + * knowing whether the lock is being held or not is not known a priori. + * + * see bug: http://bugzilla.gnome.org/show_bug.cgi?id=459555 + */ + if (dispatch->notify) + dispatch->notify (dispatch->data); + + g_slice_free (ClutterThreadsDispatch, dispatch); +} + +/** + * clutter_threads_add_idle_full: (rename-to clutter_threads_add_idle) + * @priority: the priority of the timeout source. Typically this will be in the + * range between #G_PRIORITY_DEFAULT_IDLE and #G_PRIORITY_HIGH_IDLE + * @func: function to call + * @data: data to pass to the function + * @notify: functio to call when the idle source is removed + * + * Adds a function to be called whenever there are no higher priority + * events pending. If the function returns %FALSE it is automatically + * removed from the list of event sources and will not be called again. + * + * This function can be considered a thread-safe variant of g_idle_add_full(): + * it will call @function while holding the Clutter lock. It is logically + * equivalent to the following implementation: + * + * |[ + * static gboolean + * idle_safe_callback (gpointer data) + * { + * SafeClosure *closure = data; + * gboolean res = FALSE; + * + * // mark the critical section // + * + * clutter_threads_enter(); + * + * // the callback does not need to acquire the Clutter + * / lock itself, as it is held by the this proxy handler + * // + * res = closure->callback (closure->data); + * + * clutter_threads_leave(); + * + * return res; + * } + * static gulong + * add_safe_idle (GSourceFunc callback, + * gpointer data) + * { + * SafeClosure *closure = g_new0 (SafeClosure, 1); + * + * closure->callback = callback; + * closure->data = data; + * + * return g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, + * idle_safe_callback, + * closure, + * g_free) + * } + *]| + * + * This function should be used by threaded applications to make sure + * that @func is emitted under the Clutter threads lock and invoked + * from the same thread that started the Clutter main loop. For instance, + * it can be used to update the UI using the results from a worker + * thread: + * + * |[ + * static gboolean + * update_ui (gpointer data) + * { + * SomeClosure *closure = data; + * + * // it is safe to call Clutter API from this function because + * / it is invoked from the same thread that started the main + * / loop and under the Clutter thread lock + * // + * clutter_label_set_text (CLUTTER_LABEL (closure->label), + * closure->text); + * + * g_object_unref (closure->label); + * g_free (closure); + * + * return FALSE; + * } + * + * // within another thread // + * closure = g_new0 (SomeClosure, 1); + * // always take a reference on GObject instances // + * closure->label = g_object_ref (my_application->label); + * closure->text = g_strdup (processed_text_to_update_the_label); + * + * clutter_threads_add_idle_full (G_PRIORITY_HIGH_IDLE, + * update_ui, + * closure, + * NULL); + * ]| + * + * Return value: the ID (greater than 0) of the event source. + * + * Since: 0.4 + */ +guint +clutter_threads_add_idle_full (gint priority, + GSourceFunc func, + gpointer data, + GDestroyNotify notify) +{ + ClutterThreadsDispatch *dispatch; + + g_return_val_if_fail (func != NULL, 0); + + dispatch = g_slice_new (ClutterThreadsDispatch); + dispatch->func = func; + dispatch->data = data; + dispatch->notify = notify; + + return g_idle_add_full (priority, + _clutter_threads_dispatch, dispatch, + _clutter_threads_dispatch_free); +} + +/** + * clutter_threads_add_idle: (skip) + * @func: function to call + * @data: data to pass to the function + * + * Simple wrapper around clutter_threads_add_idle_full() using the + * default priority. + * + * Return value: the ID (greater than 0) of the event source. + * + * Since: 0.4 + */ +guint +clutter_threads_add_idle (GSourceFunc func, + gpointer data) +{ + g_return_val_if_fail (func != NULL, 0); + + return clutter_threads_add_idle_full (G_PRIORITY_DEFAULT_IDLE, + func, data, + NULL); +} + +/** + * clutter_threads_add_timeout_full: (rename-to clutter_threads_add_timeout) + * @priority: the priority of the timeout source. Typically this will be in the + * range between #G_PRIORITY_DEFAULT and #G_PRIORITY_HIGH. + * @interval: the time between calls to the function, in milliseconds + * @func: function to call + * @data: data to pass to the function + * @notify: function to call when the timeout source is removed + * + * Sets a function to be called at regular intervals holding the Clutter + * threads lock, with the given priority. The function is called repeatedly + * until it returns %FALSE, at which point the timeout is automatically + * removed and the function will not be called again. The @notify function + * is called when the timeout is removed. + * + * The first call to the function will be at the end of the first @interval. + * + * It is important to note that, due to how the Clutter main loop is + * implemented, the timing will not be accurate and it will not try to + * "keep up" with the interval. + * + * See also clutter_threads_add_idle_full(). + * + * Return value: the ID (greater than 0) of the event source. + * + * Since: 0.4 + */ +guint +clutter_threads_add_timeout_full (gint priority, + guint interval, + GSourceFunc func, + gpointer data, + GDestroyNotify notify) +{ + ClutterThreadsDispatch *dispatch; + + g_return_val_if_fail (func != NULL, 0); + + dispatch = g_slice_new (ClutterThreadsDispatch); + dispatch->func = func; + dispatch->data = data; + dispatch->notify = notify; + + return g_timeout_add_full (priority, + interval, + _clutter_threads_dispatch, dispatch, + _clutter_threads_dispatch_free); +} + +/** + * clutter_threads_add_timeout: (skip) + * @interval: the time between calls to the function, in milliseconds + * @func: function to call + * @data: data to pass to the function + * + * Simple wrapper around clutter_threads_add_timeout_full(). + * + * Return value: the ID (greater than 0) of the event source. + * + * Since: 0.4 + */ +guint +clutter_threads_add_timeout (guint interval, + GSourceFunc func, + gpointer data) +{ + g_return_val_if_fail (func != NULL, 0); + + return clutter_threads_add_timeout_full (G_PRIORITY_DEFAULT, + interval, + func, data, + NULL); +} + +void +_clutter_threads_acquire_lock (void) +{ + if (clutter_threads_lock != NULL) + (* clutter_threads_lock) (); +} + +void +_clutter_threads_release_lock (void) +{ + if (clutter_threads_unlock != NULL) + (* clutter_threads_unlock) (); +} + +/** + * clutter_threads_enter: + * + * Locks the Clutter thread lock. + * + * Since: 0.4 + * + * Deprecated: 1.12: This function should not be used by application + * code; marking critical sections is not portable on various + * platforms. Instead of acquiring the Clutter lock, schedule UI + * updates from the main loop using clutter_threads_add_idle() or + * clutter_threads_add_timeout(). + */ +void +clutter_threads_enter (void) +{ + _clutter_threads_acquire_lock (); +} + +/** + * clutter_threads_leave: + * + * Unlocks the Clutter thread lock. + * + * Since: 0.4 + * + * Deprecated: 1.12: This function should not be used by application + * code; marking critical sections is not portable on various + * platforms. Instead of acquiring the Clutter lock, schedule UI + * updates from the main loop using clutter_threads_add_idle() or + * clutter_threads_add_timeout(). + */ +void +clutter_threads_leave (void) +{ + _clutter_threads_release_lock (); +} + + +/** + * clutter_get_debug_enabled: + * + * Check if Clutter has debugging enabled. + * + * Return value: %FALSE + * + * Deprecated: 1.10: This function does not do anything. + */ +gboolean +clutter_get_debug_enabled (void) +{ + return FALSE; +} + +void +_clutter_context_lock (void) +{ + G_LOCK (ClutterCntx); +} + +void +_clutter_context_unlock (void) +{ + G_UNLOCK (ClutterCntx); +} + +gboolean +_clutter_context_is_initialized (void) +{ + if (ClutterCntx == NULL) + return FALSE; + + return ClutterCntx->is_initialized; +} + +static ClutterMainContext * +clutter_context_get_default_unlocked (void) +{ + if (G_UNLIKELY (ClutterCntx == NULL)) + { + ClutterMainContext *ctx; + + /* Read the configuration file, if any, before we set up the + * whole thing, so that we can override things like the backend + * and the driver + */ + clutter_config_read (); + + ClutterCntx = ctx = g_new0 (ClutterMainContext, 1); + + ctx->is_initialized = FALSE; + + /* create the windowing system backend */ + ctx->backend = _clutter_create_backend (); + + /* create the default settings object, and store a back pointer to + * the backend singleton + */ + ctx->settings = clutter_settings_get_default (); + _clutter_settings_set_backend (ctx->settings, ctx->backend); + + ctx->motion_events_per_actor = TRUE; + ctx->last_repaint_id = 1; + } + + return ClutterCntx; +} + +ClutterMainContext * +_clutter_context_get_default (void) +{ + ClutterMainContext *retval; + + _clutter_context_lock (); + + retval = clutter_context_get_default_unlocked (); + + _clutter_context_unlock (); + + return retval; +} + +/** + * clutter_get_timestamp: + * + * Returns the approximate number of microseconds passed since Clutter was + * intialised. + * + * This function shdould not be used by application code. + * + * The output of this function depends on whether Clutter was configured to + * enable its debugging code paths, so it's less useful than intended. + * + * Since Clutter 1.10, this function is an alias to g_get_monotonic_time() + * if Clutter was configured to enable the debugging code paths. + * + * Return value: Number of microseconds since clutter_init() was called, or + * zero if Clutter was not configured with debugging code paths. + * + * Deprecated: 1.10: Use #GTimer or g_get_monotonic_time() for a proper + * timing source + */ +gulong +clutter_get_timestamp (void) +{ +#ifdef CLUTTER_ENABLE_DEBUG + return (gulong) g_get_monotonic_time (); +#else + return 0L; +#endif +} + +static gboolean +clutter_arg_direction_cb (const char *key, + const char *value, + gpointer user_data) +{ + clutter_text_direction = + (strcmp (value, "rtl") == 0) ? CLUTTER_TEXT_DIRECTION_RTL + : CLUTTER_TEXT_DIRECTION_LTR; + + return TRUE; +} + +#ifdef CLUTTER_ENABLE_DEBUG +static gboolean +clutter_arg_debug_cb (const char *key, + const char *value, + gpointer user_data) +{ + clutter_debug_flags |= + g_parse_debug_string (value, + clutter_debug_keys, + G_N_ELEMENTS (clutter_debug_keys)); + return TRUE; +} + +static gboolean +clutter_arg_no_debug_cb (const char *key, + const char *value, + gpointer user_data) +{ + clutter_debug_flags &= + ~g_parse_debug_string (value, + clutter_debug_keys, + G_N_ELEMENTS (clutter_debug_keys)); + return TRUE; +} +#endif /* CLUTTER_ENABLE_DEBUG */ + +GQuark +clutter_init_error_quark (void) +{ + return g_quark_from_static_string ("clutter-init-error-quark"); +} + +static ClutterInitError +clutter_init_real (GError **error) +{ + ClutterMainContext *ctx; + ClutterBackend *backend; + + /* Note, creates backend if not already existing, though parse args will + * have likely created it + */ + ctx = _clutter_context_get_default (); + backend = ctx->backend; + + if (!ctx->options_parsed) + { + if (error) + g_set_error (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_INTERNAL, + "When using clutter_get_option_group_without_init() " + "you must parse options before calling clutter_init()"); + else + g_critical ("When using clutter_get_option_group_without_init() " + "you must parse options before calling clutter_init()"); + + return CLUTTER_INIT_ERROR_INTERNAL; + } + + /* + * Call backend post parse hooks. + */ + if (!_clutter_backend_post_parse (backend, error)) + return CLUTTER_INIT_ERROR_BACKEND; + + /* If we are displaying the regions that would get redrawn with clipped + * redraws enabled we actually have to disable the clipped redrawing + * because otherwise we end up with nasty trails of rectangles everywhere. + */ + if (clutter_paint_debug_flags & CLUTTER_DEBUG_REDRAWS) + clutter_paint_debug_flags |= CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS; + + /* The same is true when drawing the outlines of paint volumes... */ + if (clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_VOLUMES) + { + clutter_paint_debug_flags |= + CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS | CLUTTER_DEBUG_DISABLE_CULLING; + } + + /* this will take care of initializing Cogl's state and + * query the GL machinery for features + */ + if (!_clutter_feature_init (error)) + return CLUTTER_INIT_ERROR_BACKEND; + + clutter_text_direction = clutter_get_text_direction (); + + /* Initiate event collection */ + _clutter_backend_init_events (ctx->backend); + + clutter_is_initialized = TRUE; + ctx->is_initialized = TRUE; + + /* Initialize a11y */ + if (clutter_enable_accessibility) + cally_accessibility_init (); + + return CLUTTER_INIT_SUCCESS; +} + +static GOptionEntry clutter_args[] = { + { "clutter-show-fps", 0, 0, G_OPTION_ARG_NONE, &clutter_show_fps, + N_("Show frames per second"), NULL }, + { "clutter-default-fps", 0, 0, G_OPTION_ARG_INT, &clutter_default_fps, + N_("Default frame rate"), "FPS" }, + { "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &clutter_fatal_warnings, + N_("Make all warnings fatal"), NULL }, + { "clutter-text-direction", 0, 0, G_OPTION_ARG_CALLBACK, + clutter_arg_direction_cb, + N_("Direction for the text"), "DIRECTION" }, + { "clutter-disable-mipmapped-text", 0, 0, G_OPTION_ARG_NONE, + &clutter_disable_mipmap_text, + N_("Disable mipmapping on text"), NULL }, + { "clutter-use-fuzzy-picking", 0, 0, G_OPTION_ARG_NONE, + &clutter_use_fuzzy_picking, + N_("Use 'fuzzy' picking"), NULL }, +#ifdef CLUTTER_ENABLE_DEBUG + { "clutter-debug", 0, 0, G_OPTION_ARG_CALLBACK, clutter_arg_debug_cb, + N_("Clutter debugging flags to set"), "FLAGS" }, + { "clutter-no-debug", 0, 0, G_OPTION_ARG_CALLBACK, clutter_arg_no_debug_cb, + N_("Clutter debugging flags to unset"), "FLAGS" }, +#endif /* CLUTTER_ENABLE_DEBUG */ + { "clutter-enable-accessibility", 0, 0, G_OPTION_ARG_NONE, &clutter_enable_accessibility, + N_("Enable accessibility"), NULL }, + { NULL, }, +}; + +/* pre_parse_hook: initialise variables depending on environment + * variables; these variables might be overridden by the command + * line arguments that are going to be parsed after. + */ +static gboolean +pre_parse_hook (GOptionContext *context, + GOptionGroup *group, + gpointer data, + GError **error) +{ + ClutterMainContext *clutter_context; + ClutterBackend *backend; + const char *env_string; + + if (clutter_is_initialized) + return TRUE; + + clutter_context = _clutter_context_get_default (); + + backend = clutter_context->backend; + g_assert (CLUTTER_IS_BACKEND (backend)); + +#ifdef CLUTTER_ENABLE_DEBUG + env_string = g_getenv ("CLUTTER_DEBUG"); + if (env_string != NULL) + { + clutter_debug_flags = + g_parse_debug_string (env_string, + clutter_debug_keys, + G_N_ELEMENTS (clutter_debug_keys)); + env_string = NULL; + } +#endif /* CLUTTER_ENABLE_DEBUG */ + + env_string = g_getenv ("CLUTTER_PICK"); + if (env_string != NULL) + { + clutter_pick_debug_flags = + g_parse_debug_string (env_string, + clutter_pick_debug_keys, + G_N_ELEMENTS (clutter_pick_debug_keys)); + env_string = NULL; + } + + env_string = g_getenv ("CLUTTER_PAINT"); + if (env_string != NULL) + { + clutter_paint_debug_flags = + g_parse_debug_string (env_string, + clutter_paint_debug_keys, + G_N_ELEMENTS (clutter_paint_debug_keys)); + env_string = NULL; + } + + env_string = g_getenv ("CLUTTER_SHOW_FPS"); + if (env_string) + clutter_show_fps = TRUE; + + env_string = g_getenv ("CLUTTER_DEFAULT_FPS"); + if (env_string) + { + gint default_fps = g_ascii_strtoll (env_string, NULL, 10); + + clutter_default_fps = CLAMP (default_fps, 1, 1000); + } + + env_string = g_getenv ("CLUTTER_DISABLE_MIPMAPPED_TEXT"); + if (env_string) + clutter_disable_mipmap_text = TRUE; + + env_string = g_getenv ("CLUTTER_FUZZY_PICK"); + if (env_string) + clutter_use_fuzzy_picking = TRUE; + + env_string = g_getenv ("CLUTTER_VBLANK"); + if (g_strcmp0 (env_string, "none") == 0) + clutter_sync_to_vblank = FALSE; + + return _clutter_backend_pre_parse (backend, error); +} + +/* post_parse_hook: initialise the context and data structures + * and opens the X display + */ +static gboolean +post_parse_hook (GOptionContext *context, + GOptionGroup *group, + gpointer data, + GError **error) +{ + ClutterMainContext *clutter_context; + ClutterBackend *backend; + + if (clutter_is_initialized) + return TRUE; + + clutter_context = _clutter_context_get_default (); + backend = clutter_context->backend; + g_assert (CLUTTER_IS_BACKEND (backend)); + + if (clutter_fatal_warnings) + { + GLogLevelFlags fatal_mask; + + fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK); + fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL; + g_log_set_always_fatal (fatal_mask); + } + + clutter_context->frame_rate = clutter_default_fps; + clutter_context->show_fps = clutter_show_fps; + clutter_context->options_parsed = TRUE; + + /* If not asked to defer display setup, call clutter_init_real(), + * which in turn calls the backend post parse hooks. + */ + if (!clutter_context->defer_display_setup) + return clutter_init_real (error) == CLUTTER_INIT_SUCCESS; + + return TRUE; +} + +/** + * clutter_get_option_group: (skip) + * + * Returns a #GOptionGroup for the command line arguments recognized + * by Clutter. You should add this group to your #GOptionContext with + * g_option_context_add_group(), if you are using g_option_context_parse() + * to parse your commandline arguments. + * + * Calling g_option_context_parse() with Clutter's #GOptionGroup will result + * in Clutter's initialization. That is, the following code: + * + * |[ + * g_option_context_set_main_group (context, clutter_get_option_group ()); + * res = g_option_context_parse (context, &argc, &argc, NULL); + * ]| + * + * is functionally equivalent to: + * + * |[ + * clutter_init (&argc, &argv); + * ]| + * + * After g_option_context_parse() on a #GOptionContext containing the + * Clutter #GOptionGroup has returned %TRUE, Clutter is guaranteed to be + * initialized. + * + * Return value: (transfer full): a #GOptionGroup for the commandline arguments + * recognized by Clutter + * + * Since: 0.2 + */ +GOptionGroup * +clutter_get_option_group (void) +{ + ClutterMainContext *context; + GOptionGroup *group; + + clutter_base_init (); + + context = _clutter_context_get_default (); + + group = g_option_group_new ("clutter", + _("Clutter Options"), + _("Show Clutter Options"), + NULL, + NULL); + + g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook); + g_option_group_add_entries (group, clutter_args); + + /* add backend-specific options */ + _clutter_backend_add_options (context->backend, group); + + return group; +} + +/** + * clutter_get_option_group_without_init: (skip) + * + * Returns a #GOptionGroup for the command line arguments recognized + * by Clutter. You should add this group to your #GOptionContext with + * g_option_context_add_group(), if you are using g_option_context_parse() + * to parse your commandline arguments. + * + * Unlike clutter_get_option_group(), calling g_option_context_parse() with + * the #GOptionGroup returned by this function requires a subsequent explicit + * call to clutter_init(); use this function when needing to set foreign + * display connection with clutter_x11_set_display(), or with + * `gtk_clutter_init()`. + * + * Return value: (transfer full): a #GOptionGroup for the commandline arguments + * recognized by Clutter + * + * Since: 0.8 + */ +GOptionGroup * +clutter_get_option_group_without_init (void) +{ + ClutterMainContext *context; + GOptionGroup *group; + + clutter_base_init (); + + context = _clutter_context_get_default (); + context->defer_display_setup = TRUE; + + group = clutter_get_option_group (); + + return group; +} + +/* Note that the gobject-introspection annotations for the argc/argv + * parameters do not produce the right result; however, they do + * allow the common case of argc=NULL, argv=NULL to work. + */ + +/** + * clutter_init_with_args: + * @argc: (inout): a pointer to the number of command line arguments + * @argv: (array length=argc) (inout) (allow-none): a pointer to the array + * of command line arguments + * @parameter_string: (allow-none): a string which is displayed in the + * first line of output, after + * programname [OPTION...] + * @entries: (array) (allow-none): a %NULL terminated array of + * #GOptionEntrys describing the options of your program + * @translation_domain: (allow-none): a translation domain to use for + * translating the output for the options in + * @entries with gettext(), or %NULL + * @error: (allow-none): a return location for a #GError + * + * This function does the same work as clutter_init(). Additionally, + * it allows you to add your own command line options, and it + * automatically generates nicely formatted + * output. Note that your program will be terminated after writing + * out the help output. Also note that, in case of error, the + * error message will be placed inside @error instead of being + * printed on the display. + * + * Just like clutter_init(), if this function returns an error code then + * any subsequent call to any other Clutter API will result in undefined + * behaviour - including segmentation faults. + * + * Return value: %CLUTTER_INIT_SUCCESS if Clutter has been successfully + * initialised, or other values or #ClutterInitError in case of + * error. + * + * Since: 0.2 + */ +ClutterInitError +clutter_init_with_args (int *argc, + char ***argv, + const char *parameter_string, + GOptionEntry *entries, + const char *translation_domain, + GError **error) +{ + GOptionContext *context; + GOptionGroup *group; + gboolean res; + ClutterMainContext *ctx; + + if (clutter_is_initialized) + return CLUTTER_INIT_SUCCESS; + + clutter_base_init (); + + ctx = _clutter_context_get_default (); + + if (!ctx->defer_display_setup) + { +#if 0 + if (argc && *argc > 0 && *argv) + g_set_prgname ((*argv)[0]); +#endif + + context = g_option_context_new (parameter_string); + + group = clutter_get_option_group (); + g_option_context_add_group (context, group); + + group = cogl_get_option_group (); + g_option_context_add_group (context, group); + + if (entries) + g_option_context_add_main_entries (context, entries, translation_domain); + + res = g_option_context_parse (context, argc, argv, error); + g_option_context_free (context); + + /* if res is FALSE, the error is filled for + * us by g_option_context_parse() + */ + if (!res) + { + /* if there has been an error in the initialization, the + * error id will be preserved inside the GError code + */ + if (error && *error) + return (*error)->code; + else + return CLUTTER_INIT_ERROR_INTERNAL; + } + + return CLUTTER_INIT_SUCCESS; + } + else + return clutter_init_real (error); +} + +static gboolean +clutter_parse_args (int *argc, + char ***argv, + GError **error) +{ + GOptionContext *option_context; + GOptionGroup *clutter_group, *cogl_group; + GError *internal_error = NULL; + gboolean ret = TRUE; + + if (clutter_is_initialized) + return TRUE; + + option_context = g_option_context_new (NULL); + g_option_context_set_ignore_unknown_options (option_context, TRUE); + g_option_context_set_help_enabled (option_context, FALSE); + + /* Initiate any command line options from the backend */ + clutter_group = clutter_get_option_group (); + g_option_context_set_main_group (option_context, clutter_group); + + cogl_group = cogl_get_option_group (); + g_option_context_add_group (option_context, cogl_group); + + if (!g_option_context_parse (option_context, argc, argv, &internal_error)) + { + g_propagate_error (error, internal_error); + ret = FALSE; + } + + g_option_context_free (option_context); + + return ret; +} + +/** + * clutter_init: + * @argc: (inout): The number of arguments in @argv + * @argv: (array length=argc) (inout) (allow-none): A pointer to an array + * of arguments. + * + * Initialises everything needed to operate with Clutter and parses some + * standard command line options; @argc and @argv are adjusted accordingly + * so your own code will never see those standard arguments. + * + * It is safe to call this function multiple times. + * + * This function will not abort in case of errors during + * initialization; clutter_init() will print out the error message on + * stderr, and will return an error code. It is up to the application + * code to handle this case. If you need to display the error message + * yourself, you can use clutter_init_with_args(), which takes a #GError + * pointer. + * + * If this function fails, and returns an error code, any subsequent + * Clutter API will have undefined behaviour - including segmentation + * faults and assertion failures. Make sure to handle the returned + * #ClutterInitError enumeration value. + * + * Return value: a #ClutterInitError value + */ +ClutterInitError +clutter_init (int *argc, + char ***argv) +{ + ClutterMainContext *ctx; + GError *error = NULL; + ClutterInitError res; + + if (clutter_is_initialized) + return CLUTTER_INIT_SUCCESS; + + clutter_base_init (); + + ctx = _clutter_context_get_default (); + + if (!ctx->defer_display_setup) + { +#if 0 + if (argc && *argc > 0 && *argv) + g_set_prgname ((*argv)[0]); +#endif + + /* parse_args will trigger backend creation and things like + * DISPLAY connection etc. + */ + if (!clutter_parse_args (argc, argv, &error)) + { + g_critical ("Unable to initialize Clutter: %s", error->message); + g_error_free (error); + + res = CLUTTER_INIT_ERROR_INTERNAL; + } + else + res = CLUTTER_INIT_SUCCESS; + } + else + { + res = clutter_init_real (&error); + if (error != NULL) + { + g_critical ("Unable to initialize Clutter: %s", error->message); + g_error_free (error); + } + } + + return res; +} + +gboolean +_clutter_boolean_handled_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer dummy) +{ + gboolean continue_emission; + gboolean signal_handled; + + signal_handled = g_value_get_boolean (handler_return); + g_value_set_boolean (return_accu, signal_handled); + continue_emission = !signal_handled; + + return continue_emission; +} + +gboolean +_clutter_boolean_continue_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer dummy) +{ + gboolean continue_emission; + + continue_emission = g_value_get_boolean (handler_return); + g_value_set_boolean (return_accu, continue_emission); + + return continue_emission; +} + +static void +event_click_count_generate (ClutterEvent *event) +{ + /* multiple button click detection */ + static gint click_count = 0; + static gint previous_x = -1; + static gint previous_y = -1; + static guint32 previous_time = 0; + static gint previous_button_number = -1; + + ClutterInputDevice *device = NULL; + ClutterSettings *settings; + guint double_click_time; + guint double_click_distance; + + settings = clutter_settings_get_default (); + + g_object_get (settings, + "double-click-distance", &double_click_distance, + "double-click-time", &double_click_time, + NULL); + + device = clutter_event_get_device (event); + if (device != NULL) + { + click_count = device->click_count; + previous_x = device->previous_x; + previous_y = device->previous_y; + previous_time = device->previous_time; + previous_button_number = device->previous_button_number; + + CLUTTER_NOTE (EVENT, + "Restoring previous click count:%d (device:%d, time:%u)", + click_count, + clutter_input_device_get_device_id (device), + previous_time); + } + else + { + CLUTTER_NOTE (EVENT, + "Restoring previous click count:%d (time:%u)", + click_count, + previous_time); + } + + switch (clutter_event_type (event)) + { + case CLUTTER_BUTTON_PRESS: + /* check if we are in time and within distance to increment an + * existing click count + */ + if (event->button.button == previous_button_number && + event->button.time < (previous_time + double_click_time) && + (ABS (event->button.x - previous_x) <= double_click_distance) && + (ABS (event->button.y - previous_y) <= double_click_distance)) + { + CLUTTER_NOTE (EVENT, "Increase click count (button: %d, time: %u)", + event->button.button, + event->button.time); + + click_count += 1; + } + else /* start a new click count*/ + { + CLUTTER_NOTE (EVENT, "Reset click count (button: %d, time: %u)", + event->button.button, + event->button.time); + + click_count = 1; + previous_button_number = event->button.button; + } + + previous_x = event->button.x; + previous_y = event->button.y; + previous_time = event->button.time; + + /* fallthrough */ + case CLUTTER_BUTTON_RELEASE: + event->button.click_count = click_count; + break; + + default: + g_assert_not_reached (); + break; + } + + if (event->type == CLUTTER_BUTTON_PRESS && device != NULL) + { + CLUTTER_NOTE (EVENT, "Storing click count: %d (device:%d, time:%u)", + click_count, + clutter_input_device_get_device_id (device), + previous_time); + + device->click_count = click_count; + device->previous_x = previous_x; + device->previous_y = previous_y; + device->previous_time = previous_time; + device->previous_button_number = previous_button_number; + } +} + +static inline void +emit_event_chain (ClutterEvent *event) +{ + static gboolean lock = FALSE; + + if (event->any.source == NULL) + { + CLUTTER_NOTE (EVENT, "No source set, discarding event"); + return; + } + + /* reentrancy check */ + if (lock != FALSE) + { + g_warning ("Tried emitting event during event delivery, bailing out."); + return; + } + + lock = TRUE; + + _clutter_actor_handle_event (event->any.source, event); + + lock = FALSE; +} + +/* + * Emits a pointer event after having prepared the event for delivery (setting + * source, computing click_count, generating enter/leave etc.). + */ + +static inline void +emit_pointer_event (ClutterEvent *event, + ClutterInputDevice *device) +{ + ClutterMainContext *context = _clutter_context_get_default (); + + if (_clutter_event_process_filters (event)) + return; + + if (context->pointer_grab_actor == NULL && + (device == NULL || device->pointer_grab_actor == NULL)) + { + /* no grab, time to capture and bubble */ + emit_event_chain (event); + } + else + { + if (context->pointer_grab_actor != NULL) + { + /* global grab */ + clutter_actor_event (context->pointer_grab_actor, event, FALSE); + } + else if (device != NULL && device->pointer_grab_actor != NULL) + { + /* per device grab */ + clutter_actor_event (device->pointer_grab_actor, event, FALSE); + } + } +} + +static inline void +emit_touch_event (ClutterEvent *event, + ClutterInputDevice *device) +{ + ClutterActor *grab_actor = NULL; + + if (_clutter_event_process_filters (event)) + return; + + if (device->sequence_grab_actors != NULL) + { + grab_actor = g_hash_table_lookup (device->sequence_grab_actors, + event->touch.sequence); + } + + if (grab_actor != NULL) + { + /* per-device sequence grab */ + clutter_actor_event (grab_actor, event, FALSE); + } + else + { + /* no grab, time to capture and bubble */ + emit_event_chain (event); + } +} + +static inline void +emit_keyboard_event (ClutterEvent *event, + ClutterInputDevice *device) +{ + ClutterMainContext *context = _clutter_context_get_default (); + + if (_clutter_event_process_filters (event)) + return; + + if (context->keyboard_grab_actor == NULL && + (device == NULL || device->keyboard_grab_actor == NULL)) + { + /* no grab, time to capture and bubble */ + emit_event_chain (event); + } + else + { + if (context->keyboard_grab_actor != NULL) + { + /* global key grab */ + clutter_actor_event (context->keyboard_grab_actor, event, FALSE); + } + else if (device != NULL && device->keyboard_grab_actor != NULL) + { + /* per-device key grab */ + clutter_actor_event (context->keyboard_grab_actor, event, FALSE); + } + } +} + +static gboolean +is_off_stage (ClutterActor *stage, + gfloat x, + gfloat y) +{ + gfloat width, height; + + clutter_actor_get_size (stage, &width, &height); + + return (x < 0 || + y < 0 || + x >= width || + y >= height); +} + +/** + * clutter_do_event: + * @event: a #ClutterEvent. + * + * Processes an event. + * + * The @event must be a valid #ClutterEvent and have a #ClutterStage + * associated to it. + * + * This function is only useful when embedding Clutter inside another + * toolkit, and it should never be called by applications. + * + * Since: 0.4 + */ +void +clutter_do_event (ClutterEvent *event) +{ + /* we need the stage for the event */ + if (event->any.stage == NULL) + { + g_warning ("%s: Event does not have a stage: discarding.", G_STRFUNC); + return; + } + + /* stages in destruction do not process events */ + if (CLUTTER_ACTOR_IN_DESTRUCTION (event->any.stage)) + return; + + /* Instead of processing events when received, we queue them up to + * handle per-frame before animations, layout, and drawing. + * + * This gives us the chance to reliably compress motion events + * because we've "looked ahead" and know all motion events that + * will occur before drawing the frame. + */ + _clutter_stage_queue_event (event->any.stage, event, TRUE); +} + +static void +_clutter_process_event_details (ClutterActor *stage, + ClutterMainContext *context, + ClutterEvent *event) +{ + ClutterInputDevice *device = clutter_event_get_device (event); + + switch (event->type) + { + case CLUTTER_NOTHING: + event->any.source = stage; + break; + + case CLUTTER_KEY_PRESS: + case CLUTTER_KEY_RELEASE: + case CLUTTER_PAD_BUTTON_PRESS: + case CLUTTER_PAD_BUTTON_RELEASE: + case CLUTTER_PAD_STRIP: + case CLUTTER_PAD_RING: + { + ClutterActor *actor = NULL; + + /* check that we're not a synthetic event with source set */ + if (event->any.source == NULL) + { + actor = clutter_stage_get_key_focus (CLUTTER_STAGE (stage)); + event->any.source = actor; + if (G_UNLIKELY (actor == NULL)) + { + g_warning ("No key focus set, discarding"); + return; + } + } + + emit_keyboard_event (event, device); + } + break; + + case CLUTTER_ENTER: + /* if we're entering from outside the stage we need + * to check whether the pointer is actually on another + * actor, and emit an additional pointer event + */ + if (event->any.source == stage && + event->crossing.related == NULL) + { + ClutterActor *actor = NULL; + + emit_pointer_event (event, device); + + actor = _clutter_input_device_update (device, NULL, FALSE); + if (actor != stage) + { + ClutterEvent *crossing; + + /* we emit the exact same event on the actor */ + crossing = clutter_event_copy (event); + crossing->crossing.related = stage; + crossing->crossing.source = actor; + + emit_pointer_event (crossing, device); + clutter_event_free (crossing); + } + } + else + emit_pointer_event (event, device); + break; + + case CLUTTER_LEAVE: + /* same as CLUTTER_ENTER above: when leaving the stage + * we need to also emit a CLUTTER_LEAVE event on the + * actor currently underneath the device, unless it's the + * stage + */ + if (event->any.source == stage && + event->crossing.related == NULL && + device->cursor_actor != stage) + { + ClutterEvent *crossing; + + crossing = clutter_event_copy (event); + crossing->crossing.related = stage; + crossing->crossing.source = device->cursor_actor; + + emit_pointer_event (crossing, device); + clutter_event_free (crossing); + } + emit_pointer_event (event, device); + break; + + case CLUTTER_DESTROY_NOTIFY: + case CLUTTER_DELETE: + event->any.source = stage; + + if (_clutter_event_process_filters (event)) + break; + + /* the stage did not handle the event, so we just quit */ + clutter_stage_event (CLUTTER_STAGE (stage), event); + break; + + case CLUTTER_MOTION: + /* only the stage gets motion events if they are enabled */ + if (!clutter_stage_get_motion_events_enabled (CLUTTER_STAGE (stage)) && + event->any.source == NULL) + { + /* Only stage gets motion events */ + event->any.source = stage; + + if (_clutter_event_process_filters (event)) + break; + + /* global grabs */ + if (context->pointer_grab_actor != NULL) + { + clutter_actor_event (context->pointer_grab_actor, + event, + FALSE); + break; + } + else if (device != NULL && device->pointer_grab_actor != NULL) + { + clutter_actor_event (device->pointer_grab_actor, + event, + FALSE); + break; + } + + /* Trigger handlers on stage in both capture .. */ + if (!clutter_actor_event (stage, event, TRUE)) + { + /* and bubbling phase */ + clutter_actor_event (stage, event, FALSE); + } + break; + } + + /* fallthrough from motion */ + case CLUTTER_BUTTON_PRESS: + case CLUTTER_BUTTON_RELEASE: + case CLUTTER_SCROLL: + case CLUTTER_TOUCHPAD_PINCH: + case CLUTTER_TOUCHPAD_SWIPE: + { + ClutterActor *actor; + gfloat x, y; + + clutter_event_get_coords (event, &x, &y); + + /* Only do a pick to find the source if source is not already set + * (as it could be in a synthetic event) + */ + if (event->any.source == NULL) + { + /* emulate X11 the implicit soft grab; the implicit soft grab + * keeps relaying motion events when the stage is left with a + * pointer button pressed. since this is what happens when we + * disable per-actor motion events we need to maintain the same + * behaviour when the per-actor motion events are enabled as + * well + */ + if (is_off_stage (stage, x, y)) + { + if (event->type == CLUTTER_BUTTON_RELEASE) + { + CLUTTER_NOTE (EVENT, + "Release off stage received at %.2f, %.2f", + x, y); + + event->button.source = stage; + event->button.click_count = 1; + + emit_pointer_event (event, device); + } + else if (event->type == CLUTTER_MOTION) + { + CLUTTER_NOTE (EVENT, + "Motion off stage received at %.2f, %2.f", + x, y); + + event->motion.source = stage; + + emit_pointer_event (event, device); + } + + break; + } + + /* if the backend provides a device then we should + * already have everything we need to update it and + * get the actor underneath + */ + if (device != NULL) + actor = _clutter_input_device_update (device, NULL, TRUE); + else + { + CLUTTER_NOTE (EVENT, "No device found: picking"); + + actor = _clutter_stage_do_pick (CLUTTER_STAGE (stage), + x, y, + CLUTTER_PICK_REACTIVE); + } + + if (actor == NULL) + break; + + event->any.source = actor; + } + else + { + /* use the source already set in the synthetic event */ + actor = event->any.source; + } + + CLUTTER_NOTE (EVENT, + "Reactive event received at %.2f, %.2f - actor: %p", + x, y, + actor); + + /* button presses and releases need a click count */ + if (event->type == CLUTTER_BUTTON_PRESS || + event->type == CLUTTER_BUTTON_RELEASE) + { + /* Generate click count */ + event_click_count_generate (event); + } + + emit_pointer_event (event, device); + break; + } + + case CLUTTER_TOUCH_UPDATE: + /* only the stage gets motion events if they are enabled */ + if (!clutter_stage_get_motion_events_enabled (CLUTTER_STAGE (stage)) && + event->any.source == NULL) + { + ClutterActor *grab_actor = NULL; + + /* Only stage gets motion events */ + event->any.source = stage; + + if (_clutter_event_process_filters (event)) + break; + + /* global grabs */ + if (device->sequence_grab_actors != NULL) + { + grab_actor = g_hash_table_lookup (device->sequence_grab_actors, + event->touch.sequence); + } + + if (grab_actor != NULL) + { + clutter_actor_event (grab_actor, event, FALSE); + break; + } + + /* Trigger handlers on stage in both capture .. */ + if (!clutter_actor_event (stage, event, TRUE)) + { + /* and bubbling phase */ + clutter_actor_event (stage, event, FALSE); + } + break; + } + + /* fallthrough from motion */ + case CLUTTER_TOUCH_BEGIN: + case CLUTTER_TOUCH_CANCEL: + case CLUTTER_TOUCH_END: + { + ClutterActor *actor; + ClutterEventSequence *sequence; + gfloat x, y; + + sequence = + clutter_event_get_event_sequence (event); + + if (event->type == CLUTTER_TOUCH_BEGIN) + _clutter_input_device_add_event_sequence (device, event); + + clutter_event_get_coords (event, &x, &y); + + /* Only do a pick to find the source if source is not already set + * (as it could be in a synthetic event) + */ + if (event->any.source == NULL) + { + /* same as the mouse events above, emulate the X11 implicit + * soft grab */ + if (is_off_stage (stage, x, y)) + { + CLUTTER_NOTE (EVENT, + "Touch %s off stage received at %.2f, %.2f", + event->type == CLUTTER_TOUCH_UPDATE ? "update" : + event->type == CLUTTER_TOUCH_END ? "end" : + event->type == CLUTTER_TOUCH_CANCEL ? "cancel" : + "?", x, y); + + event->touch.source = stage; + + emit_touch_event (event, device); + + if (event->type == CLUTTER_TOUCH_END) + _clutter_input_device_remove_event_sequence (device, event); + + break; + } + + if (device != NULL) + actor = _clutter_input_device_update (device, sequence, TRUE); + else + { + CLUTTER_NOTE (EVENT, "No device found: picking"); + + actor = _clutter_stage_do_pick (CLUTTER_STAGE (stage), + x, y, + CLUTTER_PICK_REACTIVE); + } + + if (actor == NULL) + break; + + event->any.source = actor; + } + else + { + /* use the source already set in the synthetic event */ + actor = event->any.source; + } + + CLUTTER_NOTE (EVENT, + "Reactive event received at %.2f, %.2f - actor: %p", + x, y, + actor); + + emit_touch_event (event, device); + + if (event->type == CLUTTER_TOUCH_END) + _clutter_input_device_remove_event_sequence (device, event); + + break; + } + + case CLUTTER_PROXIMITY_IN: + case CLUTTER_PROXIMITY_OUT: + clutter_input_device_update_from_tool (clutter_event_get_source_device (event), + clutter_event_get_device_tool (event)); + + if (_clutter_event_process_filters (event)) + break; + + if (!clutter_actor_event (stage, event, TRUE)) + { + /* and bubbling phase */ + clutter_actor_event (stage, event, FALSE); + } + + break; + + case CLUTTER_STAGE_STATE: + /* fullscreen / focus - forward to stage */ + event->any.source = stage; + if (!_clutter_event_process_filters (event)) + clutter_stage_event (CLUTTER_STAGE (stage), event); + break; + + case CLUTTER_CLIENT_MESSAGE: + break; + + case CLUTTER_EVENT_LAST: + break; + } +} + +/* + * _clutter_process_event + * @event: a #ClutterEvent. + * + * Does the actual work of processing an event that was queued earlier + * out of clutter_do_event(). + */ +void +_clutter_process_event (ClutterEvent *event) +{ + ClutterMainContext *context; + ClutterActor *stage; + + context = _clutter_context_get_default (); + + stage = CLUTTER_ACTOR (event->any.stage); + if (stage == NULL) + { + CLUTTER_NOTE (EVENT, "Discarding event without a stage set"); + return; + } + + /* push events on a stack, so that we don't need to + * add an event parameter to all signals that can be emitted within + * an event chain + */ + context->current_event = g_slist_prepend (context->current_event, event); + + _clutter_process_event_details (stage, context, event); + + context->current_event = g_slist_delete_link (context->current_event, context->current_event); +} + +/** + * clutter_get_actor_by_gid: + * @id_: a #ClutterActor unique id. + * + * Retrieves the #ClutterActor with @id_. + * + * Return value: (transfer none): the actor with the passed id or %NULL. + * The returned actor does not have its reference count increased. + * + * Since: 0.6 + * + * Deprecated: 1.8: The id is deprecated, and this function always returns + * %NULL. Use the proper scene graph API in #ClutterActor to find a child + * of the stage. + */ +ClutterActor * +clutter_get_actor_by_gid (guint32 id_) +{ + return NULL; +} + +void +clutter_base_init (void) +{ + static gboolean initialised = FALSE; + + if (!initialised) + { + initialised = TRUE; + +#if !GLIB_CHECK_VERSION (2, 35, 1) + /* initialise GLib type system */ + g_type_init (); +#endif + + /* initialise the Big Clutter Lock™ if necessary */ + clutter_threads_init_default (); + } +} + +/** + * clutter_get_default_frame_rate: + * + * Retrieves the default frame rate. See clutter_set_default_frame_rate(). + * + * Return value: the default frame rate + * + * Since: 0.6 + */ +guint +clutter_get_default_frame_rate (void) +{ + ClutterMainContext *context; + + context = _clutter_context_get_default (); + + return context->frame_rate; +} + +/** + * clutter_set_default_frame_rate: + * @frames_per_sec: the new default frame rate + * + * Sets the default frame rate. This frame rate will be used to limit + * the number of frames drawn if Clutter is not able to synchronize + * with the vertical refresh rate of the display. When synchronization + * is possible, this value is ignored. + * + * Since: 0.6 + * + * Deprecated: 1.10: This function does not do anything any more. + */ +void +clutter_set_default_frame_rate (guint frames_per_sec) +{ +} + +static void +on_grab_actor_destroy (ClutterActor *actor, + ClutterInputDevice *device) +{ + if (device == NULL) + { + ClutterMainContext *context = _clutter_context_get_default (); + + if (context->pointer_grab_actor == actor) + clutter_ungrab_pointer (); + + if (context->keyboard_grab_actor == actor) + clutter_ungrab_keyboard (); + + return; + } + + switch (device->device_type) + { + case CLUTTER_POINTER_DEVICE: + device->pointer_grab_actor = NULL; + break; + + case CLUTTER_KEYBOARD_DEVICE: + device->keyboard_grab_actor = NULL; + break; + + default: + g_assert_not_reached (); + } +} + +/** + * clutter_grab_pointer: + * @actor: a #ClutterActor + * + * Grabs pointer events, after the grab is done all pointer related events + * (press, motion, release, enter, leave and scroll) are delivered to this + * actor directly without passing through both capture and bubble phases of + * the event delivery chain. The source set in the event will be the actor + * that would have received the event if the pointer grab was not in effect. + * + * Grabs completely override the entire event delivery chain + * done by Clutter. Pointer grabs should only be used as a last resource; + * using the #ClutterActor::captured-event signal should always be the + * preferred way to intercept event delivery to reactive actors. + * + * This function should rarely be used. + * + * If a grab is required, you are strongly encouraged to use a specific + * input device by calling clutter_input_device_grab(). + * + * Since: 0.6 + */ +void +clutter_grab_pointer (ClutterActor *actor) +{ + ClutterMainContext *context; + + g_return_if_fail (actor == NULL || CLUTTER_IS_ACTOR (actor)); + + context = _clutter_context_get_default (); + + if (context->pointer_grab_actor == actor) + return; + + if (context->pointer_grab_actor != NULL) + { + g_signal_handlers_disconnect_by_func (context->pointer_grab_actor, + G_CALLBACK (on_grab_actor_destroy), + NULL); + context->pointer_grab_actor = NULL; + } + + if (actor != NULL) + { + context->pointer_grab_actor = actor; + + g_signal_connect (context->pointer_grab_actor, "destroy", + G_CALLBACK (on_grab_actor_destroy), + NULL); + } +} + +/** + * clutter_input_device_grab: + * @device: a #ClutterInputDevice + * @actor: a #ClutterActor + * + * Acquires a grab on @actor for the given @device. + * + * Any event coming from @device will be delivered to @actor, bypassing + * the usual event delivery mechanism, until the grab is released by + * calling clutter_input_device_ungrab(). + * + * The grab is client-side: even if the windowing system used by the Clutter + * backend has the concept of "device grabs", Clutter will not use them. + * + * Only #ClutterInputDevice of types %CLUTTER_POINTER_DEVICE and + * %CLUTTER_KEYBOARD_DEVICE can hold a grab. + * + * Since: 1.10 + */ +void +clutter_input_device_grab (ClutterInputDevice *device, + ClutterActor *actor) +{ + ClutterActor **grab_actor; + + g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + switch (device->device_type) + { + case CLUTTER_POINTER_DEVICE: + grab_actor = &(device->pointer_grab_actor); + break; + + case CLUTTER_KEYBOARD_DEVICE: + grab_actor = &(device->keyboard_grab_actor); + break; + + default: + g_critical ("Only pointer and keyboard devices can grab an actor"); + return; + } + + if (*grab_actor != NULL) + { + g_signal_handlers_disconnect_by_func (*grab_actor, + G_CALLBACK (on_grab_actor_destroy), + device); + } + + *grab_actor = actor; + + g_signal_connect (*grab_actor, + "destroy", + G_CALLBACK (on_grab_actor_destroy), + device); +} + +/** + * clutter_input_device_ungrab: + * @device: a #ClutterInputDevice + * + * Releases the grab on the @device, if one is in place. + * + * Since: 1.10 + */ +void +clutter_input_device_ungrab (ClutterInputDevice *device) +{ + ClutterActor **grab_actor; + + g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); + + switch (device->device_type) + { + case CLUTTER_POINTER_DEVICE: + grab_actor = &(device->pointer_grab_actor); + break; + + case CLUTTER_KEYBOARD_DEVICE: + grab_actor = &(device->keyboard_grab_actor); + break; + + default: + return; + } + + if (*grab_actor == NULL) + return; + + g_signal_handlers_disconnect_by_func (*grab_actor, + G_CALLBACK (on_grab_actor_destroy), + device); + + *grab_actor = NULL; +} + +/** + * clutter_input_device_get_grabbed_actor: + * @device: a #ClutterInputDevice + * + * Retrieves a pointer to the #ClutterActor currently grabbing all + * the events coming from @device. + * + * Return value: (transfer none): a #ClutterActor, or %NULL + * + * Since: 1.10 + */ +ClutterActor * +clutter_input_device_get_grabbed_actor (ClutterInputDevice *device) +{ + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL); + + switch (device->device_type) + { + case CLUTTER_POINTER_DEVICE: + return device->pointer_grab_actor; + + case CLUTTER_KEYBOARD_DEVICE: + return device->keyboard_grab_actor; + + default: + g_critical ("Only pointer and keyboard devices can grab an actor"); + } + + return NULL; +} + +/** + * clutter_grab_pointer_for_device: + * @actor: a #ClutterActor + * @id_: a device id, or -1 + * + * Grabs all the pointer events coming from the device @id for @actor. + * + * If @id is -1 then this function is equivalent to clutter_grab_pointer(). + * + * Since: 0.8 + * + * Deprecated: 1.10: Use clutter_input_device_grab() instead. + */ +void +clutter_grab_pointer_for_device (ClutterActor *actor, + gint id_) +{ + ClutterDeviceManager *manager; + ClutterInputDevice *dev; + + g_return_if_fail (actor == NULL || CLUTTER_IS_ACTOR (actor)); + + /* essentially a global grab */ + if (id_ == -1) + { + if (actor == NULL) + clutter_ungrab_pointer (); + else + clutter_grab_pointer (actor); + + return; + } + + manager = clutter_device_manager_get_default (); + if (manager == NULL) + return; + + dev = clutter_device_manager_get_device (manager, id_); + if (dev == NULL) + return; + + if (dev->device_type != CLUTTER_POINTER_DEVICE) + return; + + if (actor == NULL) + clutter_input_device_ungrab (dev); + else + clutter_input_device_grab (dev, actor); +} + + +/** + * clutter_ungrab_pointer: + * + * Removes an existing grab of the pointer. + * + * Since: 0.6 + */ +void +clutter_ungrab_pointer (void) +{ + clutter_grab_pointer (NULL); +} + +/** + * clutter_ungrab_pointer_for_device: + * @id_: a device id + * + * Removes an existing grab of the pointer events for device @id_. + * + * Since: 0.8 + * + * Deprecated: 1.10: Use clutter_input_device_ungrab() instead. + */ +void +clutter_ungrab_pointer_for_device (gint id_) +{ + ClutterDeviceManager *manager; + ClutterInputDevice *device; + + manager = clutter_device_manager_get_default (); + if (manager == NULL) + return; + + device = clutter_device_manager_get_device (manager, id_); + if (device != NULL) + clutter_input_device_ungrab (device); +} + + +/** + * clutter_get_pointer_grab: + * + * Queries the current pointer grab of clutter. + * + * Return value: (transfer none): the actor currently holding the pointer grab, or NULL if there is no grab. + * + * Since: 0.6 + */ +ClutterActor * +clutter_get_pointer_grab (void) +{ + ClutterMainContext *context; + context = _clutter_context_get_default (); + + return context->pointer_grab_actor; +} + + +/** + * clutter_grab_keyboard: + * @actor: a #ClutterActor + * + * Grabs keyboard events, after the grab is done keyboard + * events (#ClutterActor::key-press-event and #ClutterActor::key-release-event) + * are delivered to this actor directly. The source set in the event will be + * the actor that would have received the event if the keyboard grab was not + * in effect. + * + * Like pointer grabs, keyboard grabs should only be used as a last + * resource. + * + * See also clutter_stage_set_key_focus() and clutter_actor_grab_key_focus() + * to perform a "soft" key grab and assign key focus to a specific actor. + * + * Since: 0.6 + */ +void +clutter_grab_keyboard (ClutterActor *actor) +{ + ClutterMainContext *context; + + g_return_if_fail (actor == NULL || CLUTTER_IS_ACTOR (actor)); + + context = _clutter_context_get_default (); + + if (context->keyboard_grab_actor == actor) + return; + + if (context->keyboard_grab_actor != NULL) + { + g_signal_handlers_disconnect_by_func (context->keyboard_grab_actor, + G_CALLBACK (on_grab_actor_destroy), + NULL); + context->keyboard_grab_actor = NULL; + } + + if (actor != NULL) + { + context->keyboard_grab_actor = actor; + + g_signal_connect (context->keyboard_grab_actor, "destroy", + G_CALLBACK (on_grab_actor_destroy), + NULL); + } +} + +/** + * clutter_ungrab_keyboard: + * + * Removes an existing grab of the keyboard. + * + * Since: 0.6 + */ +void +clutter_ungrab_keyboard (void) +{ + clutter_grab_keyboard (NULL); +} + +/** + * clutter_get_keyboard_grab: + * + * Queries the current keyboard grab of clutter. + * + * Return value: (transfer none): the actor currently holding the keyboard grab, or NULL if there is no grab. + * + * Since: 0.6 + */ +ClutterActor * +clutter_get_keyboard_grab (void) +{ + ClutterMainContext *context; + + context = _clutter_context_get_default (); + + return context->keyboard_grab_actor; +} + +/** + * clutter_clear_glyph_cache: + * + * Clears the internal cache of glyphs used by the Pango + * renderer. This will free up some memory and GL texture + * resources. The cache will be automatically refilled as more text is + * drawn. + * + * Since: 0.8 + * + * Deprecated: 1.10: Use clutter_get_font_map() and + * cogl_pango_font_map_clear_glyph_cache() instead. + */ +void +clutter_clear_glyph_cache (void) +{ + CoglPangoFontMap *font_map; + + font_map = clutter_context_get_pango_fontmap (); + cogl_pango_font_map_clear_glyph_cache (font_map); +} + +/** + * clutter_set_font_flags: + * @flags: The new flags + * + * Sets the font quality options for subsequent text rendering + * operations. + * + * Using mipmapped textures will improve the quality for scaled down + * text but will use more texture memory. + * + * Enabling hinting improves text quality for static text but may + * introduce some artifacts if the text is animated. + * + * Since: 1.0 + * + * Deprecated: 1.10: Use clutter_backend_set_font_options() and the + * #cairo_font_option_t API. + */ +void +clutter_set_font_flags (ClutterFontFlags flags) +{ + CoglPangoFontMap *font_map; + ClutterFontFlags old_flags, changed_flags; + const cairo_font_options_t *font_options; + cairo_font_options_t *new_font_options; + cairo_hint_style_t hint_style; + gboolean use_mipmapping; + ClutterBackend *backend; + + backend = clutter_get_default_backend (); + font_map = clutter_context_get_pango_fontmap (); + font_options = clutter_backend_get_font_options (backend); + old_flags = 0; + + if (cogl_pango_font_map_get_use_mipmapping (font_map)) + old_flags |= CLUTTER_FONT_MIPMAPPING; + + hint_style = cairo_font_options_get_hint_style (font_options); + if (hint_style != CAIRO_HINT_STYLE_DEFAULT && + hint_style != CAIRO_HINT_STYLE_NONE) + old_flags |= CLUTTER_FONT_HINTING; + + if (old_flags == flags) + return; + + new_font_options = cairo_font_options_copy (font_options); + + /* Only set the font options that have actually changed so we don't + override a detailed setting from the backend */ + changed_flags = old_flags ^ flags; + + if ((changed_flags & CLUTTER_FONT_MIPMAPPING)) + { + use_mipmapping = (changed_flags & CLUTTER_FONT_MIPMAPPING) != 0; + + cogl_pango_font_map_set_use_mipmapping (font_map, use_mipmapping); + } + + if ((changed_flags & CLUTTER_FONT_HINTING)) + { + hint_style = (flags & CLUTTER_FONT_HINTING) + ? CAIRO_HINT_STYLE_FULL + : CAIRO_HINT_STYLE_NONE; + + cairo_font_options_set_hint_style (new_font_options, hint_style); + } + + clutter_backend_set_font_options (backend, new_font_options); + + cairo_font_options_destroy (new_font_options); +} + +/** + * clutter_get_font_flags: + * + * Gets the current font flags for rendering text. See + * clutter_set_font_flags(). + * + * Return value: The font flags + * + * Since: 1.0 + * + * Deprecated: 1.10: Use clutter_backend_get_font_options() and the + * #cairo_font_options_t API. + */ +ClutterFontFlags +clutter_get_font_flags (void) +{ + CoglPangoFontMap *font_map = NULL; + const cairo_font_options_t *font_options; + ClutterFontFlags flags = 0; + cairo_hint_style_t hint_style; + + font_map = clutter_context_get_pango_fontmap (); + if (cogl_pango_font_map_get_use_mipmapping (font_map)) + flags |= CLUTTER_FONT_MIPMAPPING; + + font_options = + clutter_backend_get_font_options (clutter_get_default_backend ()); + + hint_style = cairo_font_options_get_hint_style (font_options); + if (hint_style != CAIRO_HINT_STYLE_DEFAULT && + hint_style != CAIRO_HINT_STYLE_NONE) + flags |= CLUTTER_FONT_HINTING; + + return flags; +} + +/** + * clutter_get_input_device_for_id: + * @id_: the unique id for a device + * + * Retrieves the #ClutterInputDevice from its @id_. This is a convenience + * wrapper for clutter_device_manager_get_device() and it is functionally + * equivalent to: + * + * |[ + * ClutterDeviceManager *manager; + * ClutterInputDevice *device; + * + * manager = clutter_device_manager_get_default (); + * device = clutter_device_manager_get_device (manager, id); + * ]| + * + * Return value: (transfer none): a #ClutterInputDevice, or %NULL + * + * Since: 0.8 + * + * Deprecated: 1.10: Use clutter_device_manager_get_device() instead. + */ +ClutterInputDevice * +clutter_get_input_device_for_id (gint id_) +{ + ClutterDeviceManager *manager; + + manager = clutter_device_manager_get_default (); + if (manager == NULL) + return NULL; + + return clutter_device_manager_get_device (manager, id_); +} + +/** + * clutter_get_font_map: + * + * Retrieves the #PangoFontMap instance used by Clutter. + * You can use the global font map object with the COGL + * Pango API. + * + * Return value: (transfer none): the #PangoFontMap instance. The returned + * value is owned by Clutter and it should never be unreferenced. + * + * Since: 1.0 + */ +PangoFontMap * +clutter_get_font_map (void) +{ + return PANGO_FONT_MAP (clutter_context_get_pango_fontmap ()); +} + +typedef struct _ClutterRepaintFunction +{ + guint id; + ClutterRepaintFlags flags; + 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); + + _clutter_context_lock (); + + context = clutter_context_get_default_unlocked (); + 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); + + break; + } + + l = l->next; + } + + _clutter_context_unlock (); +} + +/** + * 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 processing a new + * frame. + * + * 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; + * the function will be called within the main loop, so it is imperative + * that it does not block, otherwise the frame time budget may be lost. + * + * 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. By default, a repaint + * function added using this function will be invoked prior to the frame + * being processed. + * + * Adding a repaint function does not automatically ensure that a new + * frame will be queued. + * + * 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. + * + * See also: clutter_threads_add_repaint_func_full() + * + * 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) +{ + return clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_PRE_PAINT, + func, + data, notify); +} + +/** + * clutter_threads_add_repaint_func_full: + * @flags: flags for the repaint function + * @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 processing a new + * frame. + * + * 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; + * the function will be called within the main loop, so it is imperative + * that it does not block, otherwise the frame time budget may be lost. + * + * 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. The @flags passed to this + * function will determine the section of the frame processing that will + * result in @func being called. + * + * Adding a repaint function does not automatically ensure that a new + * frame will be queued. + * + * 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.10 + */ +guint +clutter_threads_add_repaint_func_full (ClutterRepaintFlags flags, + GSourceFunc func, + gpointer data, + GDestroyNotify notify) +{ + ClutterMainContext *context; + ClutterRepaintFunction *repaint_func; + + g_return_val_if_fail (func != NULL, 0); + + _clutter_context_lock (); + + context = clutter_context_get_default_unlocked (); + + repaint_func = g_slice_new (ClutterRepaintFunction); + + repaint_func->id = context->last_repaint_id++; + + /* mask out QUEUE_REDRAW_ON_ADD, since we're going to consume it */ + repaint_func->flags = flags & ~CLUTTER_REPAINT_FLAGS_QUEUE_REDRAW_ON_ADD; + repaint_func->func = func; + repaint_func->data = data; + repaint_func->notify = notify; + + context->repaint_funcs = g_list_prepend (context->repaint_funcs, + repaint_func); + + _clutter_context_unlock (); + + if ((flags & CLUTTER_REPAINT_FLAGS_QUEUE_REDRAW_ON_ADD) != 0) + { + ClutterMasterClock *master_clock = _clutter_master_clock_get_default (); + + _clutter_master_clock_ensure_next_iteration (master_clock); + } + + return repaint_func->id; +} + +/* + * _clutter_run_repaint_functions: + * @flags: only run the repaint functions matching the passed flags + * + * Executes the repaint functions added using the + * clutter_threads_add_repaint_func() function. + * + * Must be called with the Clutter thread lock held. + */ +void +_clutter_run_repaint_functions (ClutterRepaintFlags flags) +{ + ClutterMainContext *context = _clutter_context_get_default (); + ClutterRepaintFunction *repaint_func; + GList *invoke_list, *reinvoke_list, *l; + + if (context->repaint_funcs == NULL) + return; + + /* steal the list */ + invoke_list = context->repaint_funcs; + context->repaint_funcs = NULL; + + reinvoke_list = NULL; + + /* consume the whole list while we execute the functions */ + while (invoke_list != NULL) + { + gboolean res = FALSE; + + repaint_func = invoke_list->data; + + l = invoke_list; + invoke_list = g_list_remove_link (invoke_list, invoke_list); + + g_list_free (l); + + if ((repaint_func->flags & flags) != 0) + res = repaint_func->func (repaint_func->data); + else + res = TRUE; + + if (res) + reinvoke_list = g_list_prepend (reinvoke_list, repaint_func); + else + { + if (repaint_func->notify != NULL) + repaint_func->notify (repaint_func->data); + + g_slice_free (ClutterRepaintFunction, repaint_func); + } + } + + if (context->repaint_funcs != NULL) + { + context->repaint_funcs = g_list_concat (context->repaint_funcs, + g_list_reverse (reinvoke_list)); + } + else + context->repaint_funcs = g_list_reverse (reinvoke_list); +} + +/** + * clutter_check_version: + * @major: major version, like 1 in 1.2.3 + * @minor: minor version, like 2 in 1.2.3 + * @micro: micro version, like 3 in 1.2.3 + * + * Run-time version check, to check the version the Clutter library + * that an application is currently linked against + * + * This is the run-time equivalent of the compile-time %CLUTTER_CHECK_VERSION + * pre-processor macro + * + * Return value: %TRUE if the version of the Clutter library is + * greater than (@major, @minor, @micro), and %FALSE otherwise + * + * Since: 1.2 + */ +gboolean +clutter_check_version (guint major, + guint minor, + guint micro) +{ + return (clutter_major_version > major || + (clutter_major_version == major && + clutter_minor_version > minor) || + (clutter_major_version == major && + clutter_minor_version == minor && + clutter_micro_version >= micro)); +} + +/** + * clutter_get_default_text_direction: + * + * Retrieves the default direction for the text. The text direction is + * determined by the locale and/or by the `CLUTTER_TEXT_DIRECTION` + * environment variable. + * + * The default text direction can be overridden on a per-actor basis by using + * clutter_actor_set_text_direction(). + * + * Return value: the default text direction + * + * Since: 1.2 + */ +ClutterTextDirection +clutter_get_default_text_direction (void) +{ + return clutter_text_direction; +} + +/*< private > + * clutter_clear_events_queue: + * + * Clears the events queue stored in the main context. + */ +void +_clutter_clear_events_queue (void) +{ + ClutterMainContext *context = _clutter_context_get_default (); + + if (context->events_queue != NULL) + { + g_queue_foreach (context->events_queue, + (GFunc) clutter_event_free, + NULL); + g_queue_free (context->events_queue); + context->events_queue = NULL; + } +} + +void +_clutter_clear_events_queue_for_stage (ClutterStage *stage) +{ + ClutterMainContext *context = _clutter_context_get_default (); + GList *l, *next; + + if (context->events_queue == NULL) + return; + + /* Remove any pending events for this stage from the event queue */ + for (l = context->events_queue->head; l; l = next) + { + ClutterEvent *event = l->data; + + next = l->next; + + if (event->any.stage == stage) + { + g_queue_delete_link (context->events_queue, l); + clutter_event_free (event); + } + } +} + +ClutterPickMode +_clutter_context_get_pick_mode (void) +{ + ClutterMainContext *context = _clutter_context_get_default (); + + return context->pick_mode; +} + +void +_clutter_context_push_shader_stack (ClutterActor *actor) +{ + ClutterMainContext *context = _clutter_context_get_default (); + + context->shaders = g_slist_prepend (context->shaders, actor); +} + +ClutterActor * +_clutter_context_peek_shader_stack (void) +{ + ClutterMainContext *context = _clutter_context_get_default (); + + if (context->shaders != NULL) + return context->shaders->data; + + return NULL; +} + +ClutterActor * +_clutter_context_pop_shader_stack (ClutterActor *actor) +{ + ClutterMainContext *context = _clutter_context_get_default (); + + context->shaders = g_slist_remove (context->shaders, actor); + + return _clutter_context_peek_shader_stack (); +} + +gboolean +_clutter_context_get_motion_events_enabled (void) +{ + ClutterMainContext *context = _clutter_context_get_default (); + + return context->motion_events_per_actor; +} + +/** + * clutter_check_windowing_backend: + * @backend_type: the name of the backend to check + * + * Checks the run-time name of the Clutter windowing system backend, using + * the symbolic macros like %CLUTTER_WINDOWING_X11. + * + * This function should be used in conjuction with the compile-time macros + * inside applications and libraries that are using the platform-specific + * windowing system API, to ensure that they are running on the correct + * windowing system; for instance: + * + * |[ + * #ifdef CLUTTER_WINDOWING_X11 + * if (clutter_check_windowing_backend (CLUTTER_WINDOWING_X11)) + * { + * // it is safe to use the clutter_x11_* API + * } + * else + * #endif + * g_error ("Unknown Clutter backend."); + * ]| + * + * Return value: %TRUE if the current Clutter windowing system backend is + * the one checked, and %FALSE otherwise + * + * Since: 1.10 + */ +gboolean +clutter_check_windowing_backend (const char *backend_type) +{ + ClutterMainContext *context = _clutter_context_get_default (); + + g_return_val_if_fail (backend_type != NULL, FALSE); + + backend_type = g_intern_string (backend_type); + +#ifdef CLUTTER_WINDOWING_EGL + if (backend_type == I_(CLUTTER_WINDOWING_EGL) && + CLUTTER_IS_BACKEND_EGL_NATIVE (context->backend)) + return TRUE; + else +#endif +#ifdef CLUTTER_WINDOWING_X11 + if (backend_type == I_(CLUTTER_WINDOWING_X11) && + CLUTTER_IS_BACKEND_X11 (context->backend)) + return TRUE; + else +#endif + return FALSE; +} + +void +_clutter_set_sync_to_vblank (gboolean sync_to_vblank) +{ + clutter_sync_to_vblank = !!sync_to_vblank; +} + +gboolean +_clutter_get_sync_to_vblank (void) +{ + return clutter_sync_to_vblank; +} + +void +_clutter_debug_messagev (const char *format, + va_list var_args) +{ + static gint64 last_debug_stamp; + gchar *stamp, *fmt; + gint64 cur_time, debug_stamp; + + cur_time = g_get_monotonic_time (); + + /* if the last debug message happened less than a second ago, just + * show the increments instead of the full timestamp + */ + if (last_debug_stamp == 0 || + cur_time - last_debug_stamp >= G_USEC_PER_SEC) + { + debug_stamp = cur_time; + last_debug_stamp = debug_stamp; + + stamp = g_strdup_printf ("[%16" G_GINT64_FORMAT "]", debug_stamp); + } + else + { + debug_stamp = cur_time - last_debug_stamp; + + stamp = g_strdup_printf ("[%+16" G_GINT64_FORMAT "]", debug_stamp); + } + + fmt = g_strconcat (stamp, ":", format, NULL); + g_free (stamp); + + g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, fmt, var_args); + + g_free (fmt); +} + +void +_clutter_debug_message (const char *format, ...) +{ + va_list args; + + va_start (args, format); + _clutter_debug_messagev (format, args); + va_end (args); +} + +gboolean +_clutter_diagnostic_enabled (void) +{ + static const char *clutter_enable_diagnostic = NULL; + + if (G_UNLIKELY (clutter_enable_diagnostic == NULL)) + { + clutter_enable_diagnostic = g_getenv ("CLUTTER_ENABLE_DIAGNOSTIC"); + + if (clutter_enable_diagnostic == NULL) + clutter_enable_diagnostic = "0"; + } + + return *clutter_enable_diagnostic != '0'; +} + +void +_clutter_diagnostic_message (const char *format, ...) +{ + va_list args; + char *fmt; + + fmt = g_strconcat ("[DIAGNOSTIC]: ", format, NULL); + + va_start (args, format); + g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, fmt, args); + va_end (args); + + g_free (fmt); +} diff --git a/clutter/clutter/clutter-main.h b/clutter/clutter/clutter-main.h new file mode 100644 index 0000000..21bdb06 --- /dev/null +++ b/clutter/clutter/clutter-main.h @@ -0,0 +1,184 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __CLUTTER_MAIN_H__ +#define __CLUTTER_MAIN_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include +#include + +G_BEGIN_DECLS + +/** + * CLUTTER_INIT_ERROR: + * + * #GError domain for #ClutterInitError + */ +#define CLUTTER_INIT_ERROR (clutter_init_error_quark ()) + +/** + * ClutterInitError: + * @CLUTTER_INIT_SUCCESS: Initialisation successful + * @CLUTTER_INIT_ERROR_UNKNOWN: Unknown error + * @CLUTTER_INIT_ERROR_THREADS: Thread initialisation failed + * @CLUTTER_INIT_ERROR_BACKEND: Backend initialisation failed + * @CLUTTER_INIT_ERROR_INTERNAL: Internal error + * + * Error conditions returned by clutter_init() and clutter_init_with_args(). + * + * Since: 0.2 + */ +typedef enum { + CLUTTER_INIT_SUCCESS = 1, + CLUTTER_INIT_ERROR_UNKNOWN = 0, + CLUTTER_INIT_ERROR_THREADS = -1, + CLUTTER_INIT_ERROR_BACKEND = -2, + CLUTTER_INIT_ERROR_INTERNAL = -3 +} ClutterInitError; + +CLUTTER_AVAILABLE_IN_ALL +GQuark clutter_init_error_quark (void); + +/** + * CLUTTER_PRIORITY_REDRAW: + * + * Priority of the redraws. This is chosen to be lower than the GTK+ + * redraw and resize priorities, because in application with both + * GTK+ and Clutter it's more likely that the Clutter part will be + * continually animating (and thus able to starve GTK+) than + * vice-versa. + * + * Since: 0.8 + */ +#define CLUTTER_PRIORITY_REDRAW (G_PRIORITY_HIGH_IDLE + 50) + +/* Initialisation */ +CLUTTER_AVAILABLE_IN_ALL +void clutter_base_init (void); +CLUTTER_AVAILABLE_IN_ALL +ClutterInitError clutter_init (int *argc, + char ***argv) G_GNUC_WARN_UNUSED_RESULT; +CLUTTER_AVAILABLE_IN_ALL +ClutterInitError clutter_init_with_args (int *argc, + char ***argv, + const char *parameter_string, + GOptionEntry *entries, + const char *translation_domain, + GError **error) G_GNUC_WARN_UNUSED_RESULT; + +CLUTTER_AVAILABLE_IN_ALL +GOptionGroup * clutter_get_option_group (void); +CLUTTER_AVAILABLE_IN_ALL +GOptionGroup * clutter_get_option_group_without_init (void); + +/* Mainloop */ +CLUTTER_AVAILABLE_IN_ALL +void clutter_main (void); +CLUTTER_AVAILABLE_IN_ALL +void clutter_main_quit (void); +CLUTTER_AVAILABLE_IN_ALL +gint clutter_main_level (void); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_do_event (ClutterEvent *event); + +/* Debug utility functions */ +CLUTTER_AVAILABLE_IN_1_4 +gboolean clutter_get_accessibility_enabled (void); + +CLUTTER_AVAILABLE_IN_1_14 +void clutter_disable_accessibility (void); + +/* Threading functions */ +CLUTTER_AVAILABLE_IN_ALL +void clutter_threads_set_lock_functions (GCallback enter_fn, + GCallback leave_fn); +CLUTTER_AVAILABLE_IN_ALL +guint clutter_threads_add_idle (GSourceFunc func, + gpointer data); +CLUTTER_AVAILABLE_IN_ALL +guint clutter_threads_add_idle_full (gint priority, + GSourceFunc func, + gpointer data, + GDestroyNotify notify); +CLUTTER_AVAILABLE_IN_ALL +guint clutter_threads_add_timeout (guint interval, + GSourceFunc func, + gpointer data); +CLUTTER_AVAILABLE_IN_ALL +guint clutter_threads_add_timeout_full (gint priority, + guint interval, + GSourceFunc func, + gpointer data, + GDestroyNotify notify); +CLUTTER_AVAILABLE_IN_1_0 +guint clutter_threads_add_repaint_func (GSourceFunc func, + gpointer data, + GDestroyNotify notify); +CLUTTER_AVAILABLE_IN_1_10 +guint clutter_threads_add_repaint_func_full (ClutterRepaintFlags flags, + GSourceFunc func, + gpointer data, + GDestroyNotify notify); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_threads_remove_repaint_func (guint handle_id); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_grab_pointer (ClutterActor *actor); +CLUTTER_AVAILABLE_IN_ALL +void clutter_ungrab_pointer (void); +CLUTTER_AVAILABLE_IN_ALL +ClutterActor * clutter_get_pointer_grab (void); +CLUTTER_AVAILABLE_IN_ALL +void clutter_grab_keyboard (ClutterActor *actor); +CLUTTER_AVAILABLE_IN_ALL +void clutter_ungrab_keyboard (void); +CLUTTER_AVAILABLE_IN_ALL +ClutterActor * clutter_get_keyboard_grab (void); + +CLUTTER_AVAILABLE_IN_ALL +PangoFontMap * clutter_get_font_map (void); + +CLUTTER_AVAILABLE_IN_ALL +ClutterTextDirection clutter_get_default_text_direction (void); + +CLUTTER_AVAILABLE_IN_ALL +guint clutter_get_default_frame_rate (void); + +CLUTTER_AVAILABLE_IN_1_2 +gboolean clutter_check_version (guint major, + guint minor, + guint micro); + +CLUTTER_AVAILABLE_IN_1_10 +gboolean clutter_check_windowing_backend (const char *backend_type); + + +G_END_DECLS + +#endif /* _CLUTTER_MAIN_H__ */ diff --git a/clutter/clutter/clutter-marshal.list b/clutter/clutter/clutter-marshal.list new file mode 100644 index 0000000..fc7680d --- /dev/null +++ b/clutter/clutter/clutter-marshal.list @@ -0,0 +1,37 @@ +BOOLEAN:BOXED +BOOLEAN:BOXED,INT,INT +BOOLEAN:OBJECT,BOOLEAN +BOOLEAN:OBJECT,BOXED,DOUBLE +BOOLEAN:OBJECT,DOUBLE +BOOLEAN:OBJECT,ENUM +BOOLEAN:OBJECT,FLAGS +BOOLEAN:STRING,UINT,FLAGS +BOOLEAN:OBJECT +BOOLEAN:OBJECT,FLOAT,FLOAT +BOXED:UINT,UINT +DOUBLE:VOID +UINT:VOID +VOID:BOOLEAN +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,FLAGS +VOID:OBJECT,FLOAT,FLOAT +VOID:OBJECT,FLOAT,FLOAT,FLAGS +VOID:OBJECT,PARAM +VOID:OBJECT,POINTER +VOID:OBJECT,UINT +VOID:POINTER +VOID:STRING,BOOLEAN +VOID:STRING,BOOLEAN,BOOLEAN +VOID:STRING,INT +VOID:UINT +VOID:UINT,STRING,UINT +VOID:UINT,UINT +VOID:VOID +VOID:STRING,INT,POINTER diff --git a/clutter/clutter/clutter-master-clock-default.c b/clutter/clutter/clutter-master-clock-default.c new file mode 100644 index 0000000..7b2df0d --- /dev/null +++ b/clutter/clutter/clutter-master-clock-default.c @@ -0,0 +1,691 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By: Emmanuele Bassi + * + * 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 . + */ + +/* + * SECTION:clutter-master-clock-default + * @short_description: The default master clock for all animations + * + * The #ClutterMasterClockDefault class is the default implementation + * of #ClutterMasterClock. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-master-clock.h" +#include "clutter-master-clock-default.h" +#include "clutter-debug.h" +#include "clutter-private.h" +#include "clutter-stage-manager-private.h" +#include "clutter-stage-private.h" + +#ifdef CLUTTER_ENABLE_DEBUG +#define clutter_warn_if_over_budget(master_clock,start_time,section) G_STMT_START { \ + gint64 __delta = g_get_monotonic_time () - start_time; \ + gint64 __budget = master_clock->remaining_budget; \ + if (__budget > 0 && __delta >= __budget) { \ + _clutter_diagnostic_message ("%s took %" G_GINT64_FORMAT " microseconds " \ + "more than the remaining budget of %" G_GINT64_FORMAT \ + " microseconds", \ + section, __delta - __budget, __budget); \ + } } G_STMT_END +#else +#define clutter_warn_if_over_budget(master_clock,start_time,section) +#endif + +typedef struct _ClutterClockSource ClutterClockSource; + +struct _ClutterMasterClockDefault +{ + GObject parent_instance; + + /* the list of timelines handled by the clock */ + GSList *timelines; + + /* the current state of the clock, in usecs */ + gint64 cur_tick; + + /* the previous state of the clock, in usecs, used to compute the delta */ + gint64 prev_tick; + +#ifdef CLUTTER_ENABLE_DEBUG + gint64 frame_budget; + gint64 remaining_budget; +#endif + + /* an idle source, used by the Master Clock to queue + * a redraw on the stage and drive the animations + */ + GSource *source; + + /* If the master clock is idle that means it has + * fallen back to idle polling for timeline + * progressions and it may have been some time since + * the last real stage update. + */ + guint idle : 1; + guint ensure_next_iteration : 1; + + guint paused : 1; +}; + +struct _ClutterClockSource +{ + GSource source; + + ClutterMasterClockDefault *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 GSourceFuncs clock_funcs = { + clutter_clock_prepare, + clutter_clock_check, + clutter_clock_dispatch, + NULL +}; + +static void clutter_master_clock_iface_init (ClutterMasterClockIface *iface); + +#define clutter_master_clock_default_get_type _clutter_master_clock_default_get_type + +G_DEFINE_TYPE_WITH_CODE (ClutterMasterClockDefault, + clutter_master_clock_default, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_MASTER_CLOCK, + clutter_master_clock_iface_init)); + +/* + * master_clock_is_running: + * @master_clock: a #ClutterMasterClock + * + * Checks if we should currently be advancing timelines or redrawing + * stages. + * + * Return value: %TRUE if the #ClutterMasterClock has at least + * one running timeline + */ +static gboolean +master_clock_is_running (ClutterMasterClockDefault *master_clock) +{ + ClutterStageManager *stage_manager = clutter_stage_manager_get_default (); + const GSList *stages, *l; + + stages = clutter_stage_manager_peek_stages (stage_manager); + + if (master_clock->paused) + return FALSE; + + if (master_clock->timelines) + return TRUE; + + for (l = stages; l; l = l->next) + { + if (clutter_actor_is_mapped (l->data) && + (_clutter_stage_has_queued_events (l->data) || + _clutter_stage_needs_update (l->data))) + return TRUE; + } + + if (master_clock->ensure_next_iteration) + { + master_clock->ensure_next_iteration = FALSE; + return TRUE; + } + + return FALSE; +} + +static gint +master_clock_get_swap_wait_time (ClutterMasterClockDefault *master_clock) +{ + ClutterStageManager *stage_manager = clutter_stage_manager_get_default (); + const GSList *stages, *l; + gint64 min_update_time = -1; + + stages = clutter_stage_manager_peek_stages (stage_manager); + + for (l = stages; l != NULL; l = l->next) + { + gint64 update_time = _clutter_stage_get_update_time (l->data); + if (min_update_time == -1 || + (update_time != -1 && update_time < min_update_time)) + min_update_time = update_time; + } + + if (min_update_time == -1) + { + return -1; + } + else + { + gint64 now = g_source_get_time (master_clock->source); + if (min_update_time < now) + { + return 0; + } + else + { + gint64 delay_us = min_update_time - now; + return (delay_us + 999) / 1000; + } + } +} + +static void +master_clock_schedule_stage_updates (ClutterMasterClockDefault *master_clock) +{ + ClutterStageManager *stage_manager = clutter_stage_manager_get_default (); + const GSList *stages, *l; + + stages = clutter_stage_manager_peek_stages (stage_manager); + + for (l = stages; l != NULL; l = l->next) + _clutter_stage_schedule_update (l->data); +} + +static GSList * +master_clock_list_ready_stages (ClutterMasterClockDefault *master_clock) +{ + ClutterStageManager *stage_manager = clutter_stage_manager_get_default (); + const GSList *stages, *l; + GSList *result; + + stages = clutter_stage_manager_peek_stages (stage_manager); + + result = NULL; + for (l = stages; l != NULL; l = l->next) + { + gint64 update_time = _clutter_stage_get_update_time (l->data); + /* We carefully avoid to update stages that aren't mapped, because + * they have nothing to render and this could cause a deadlock with + * some of the SwapBuffers implementations (in particular + * GLX_INTEL_swap_event is not emitted if nothing was rendered). + * + * Also, if a stage has a swap-buffers pending we don't want to draw + * to it in case the driver may block the CPU while it waits for the + * next backbuffer to become available. + * + * TODO: We should be able to identify if we are running triple or N + * buffered and in these cases we can still draw if there is 1 swap + * pending so we can hopefully always be ready to swap for the next + * vblank and really match the vsync frequency. + */ + if (clutter_actor_is_mapped (l->data) && + update_time != -1 && update_time <= master_clock->cur_tick) + result = g_slist_prepend (result, g_object_ref (l->data)); + } + + return g_slist_reverse (result); +} + +static void +master_clock_reschedule_stage_updates (ClutterMasterClockDefault *master_clock, + GSList *stages) +{ + const GSList *l; + + for (l = stages; l != NULL; l = l->next) + { + /* Clear the old update time */ + _clutter_stage_clear_update_time (l->data); + + /* And if there is still work to be done, schedule a new one */ + if (master_clock->timelines || + _clutter_stage_has_queued_events (l->data) || + _clutter_stage_needs_update (l->data)) + _clutter_stage_schedule_update (l->data); + } +} + +/* + * master_clock_next_frame_delay: + * @master_clock: a #ClutterMasterClock + * + * Computes the number of delay before we need to draw the next frame. + * + * Return value: -1 if there is no next frame pending, otherwise the + * number of millseconds before the we need to draw the next frame + */ +static gint +master_clock_next_frame_delay (ClutterMasterClockDefault *master_clock) +{ + gint64 now, next; + gint swap_delay; + + if (!master_clock_is_running (master_clock)) + return -1; + + /* If all of the stages are busy waiting for a swap-buffers to complete + * then we wait for one to be ready.. */ + swap_delay = master_clock_get_swap_wait_time (master_clock); + if (swap_delay != 0) + return swap_delay; + + /* When we have sync-to-vblank, we count on swap-buffer requests (or + * swap-buffer-complete events if supported in the backend) to throttle our + * frame rate so no additional delay is needed to start the next frame. + * + * If the master-clock has become idle due to no timeline progression causing + * redraws then we can no longer rely on vblank synchronization because the + * last real stage update/redraw may have happened a long time ago and so we + * fallback to polling for timeline progressions every 1/frame_rate seconds. + * + * (NB: if there aren't even any timelines running then the master clock will + * be completely stopped in master_clock_is_running()) + */ + if (clutter_feature_available (CLUTTER_FEATURE_SYNC_TO_VBLANK) && + !master_clock->idle) + { + CLUTTER_NOTE (SCHEDULER, "vblank available and updated stages"); + return 0; + } + + if (master_clock->prev_tick == 0) + { + /* If we weren't previously running, then draw the next frame + * immediately + */ + CLUTTER_NOTE (SCHEDULER, "draw the first frame immediately"); + return 0; + } + + /* Otherwise, wait at least 1/frame_rate seconds since we last + * started a frame + */ + now = g_source_get_time (master_clock->source); + + next = master_clock->prev_tick; + + /* If time has gone backwards then there's no way of knowing how + long we should wait so let's just dispatch immediately */ + if (now <= next) + { + CLUTTER_NOTE (SCHEDULER, "Time has gone backwards"); + + return 0; + } + + next += (1000000L / clutter_get_default_frame_rate ()); + + if (next <= now) + { + CLUTTER_NOTE (SCHEDULER, "Less than %lu microsecs", + 1000000L / (gulong) clutter_get_default_frame_rate ()); + + return 0; + } + else + { + CLUTTER_NOTE (SCHEDULER, "Waiting %" G_GINT64_FORMAT " msecs", + (next - now) / 1000); + + return (next - now) / 1000; + } +} + +static void +master_clock_process_events (ClutterMasterClockDefault *master_clock, + GSList *stages) +{ + GSList *l; +#ifdef CLUTTER_ENABLE_DEBUG + gint64 start = g_get_monotonic_time (); +#endif + + /* Process queued events */ + for (l = stages; l != NULL; l = l->next) + _clutter_stage_process_queued_events (l->data); + +#ifdef CLUTTER_ENABLE_DEBUG + if (_clutter_diagnostic_enabled ()) + clutter_warn_if_over_budget (master_clock, start, "Event processing"); + + master_clock->remaining_budget -= (g_get_monotonic_time () - start); +#endif +} + +/* + * master_clock_advance_timelines: + * @master_clock: a #ClutterMasterClock + * + * Advances all the timelines held by the master clock. This function + * should be called before calling _clutter_stage_do_update() to + * make sure that all the timelines are advanced and the scene is updated. + */ +static void +master_clock_advance_timelines (ClutterMasterClockDefault *master_clock) +{ + GSList *timelines, *l; +#ifdef CLUTTER_ENABLE_DEBUG + gint64 start = g_get_monotonic_time (); +#endif + + /* we protect ourselves from timelines being removed during + * the advancement by other timelines by copying the list of + * timelines, taking a reference on them, iterating over the + * copied list and then releasing the reference. + * + * we cannot simply take a reference on the timelines and still + * use the list held by the master clock because the do_tick() + * might result in the creation of a new timeline, which gets + * added at the end of the list with no reference increase and + * thus gets disposed at the end of the iteration. + * + * this implies that a newly added timeline will not be advanced + * by this clock iteration, which is perfectly fine since we're + * in its first cycle. + * + * we also cannot steal the master clock timelines list because + * a timeline might be removed as the direct result of do_tick() + * and remove_timeline() would not find the timeline, failing + * and leaving a dangling pointer behind. + */ + timelines = g_slist_copy (master_clock->timelines); + g_slist_foreach (timelines, (GFunc) g_object_ref, NULL); + + for (l = timelines; l != NULL; l = l->next) + _clutter_timeline_do_tick (l->data, master_clock->cur_tick / 1000); + + g_slist_foreach (timelines, (GFunc) g_object_unref, NULL); + g_slist_free (timelines); + +#ifdef CLUTTER_ENABLE_DEBUG + if (_clutter_diagnostic_enabled ()) + clutter_warn_if_over_budget (master_clock, start, "Animations"); + + master_clock->remaining_budget -= (g_get_monotonic_time () - start); +#endif +} + +static gboolean +master_clock_update_stages (ClutterMasterClockDefault *master_clock, + GSList *stages) +{ + gboolean stages_updated = FALSE; + GSList *l; +#ifdef CLUTTER_ENABLE_DEBUG + gint64 start = g_get_monotonic_time (); +#endif + + _clutter_run_repaint_functions (CLUTTER_REPAINT_FLAGS_PRE_PAINT); + + /* Update any stage that needs redraw/relayout after the clock + * is advanced. + */ + for (l = stages; l != NULL; l = l->next) + stages_updated |= _clutter_stage_do_update (l->data); + + _clutter_run_repaint_functions (CLUTTER_REPAINT_FLAGS_POST_PAINT); + +#ifdef CLUTTER_ENABLE_DEBUG + if (_clutter_diagnostic_enabled ()) + clutter_warn_if_over_budget (master_clock, start, "Updating the stage"); + + master_clock->remaining_budget -= (g_get_monotonic_time () - start); +#endif + + return stages_updated; +} + +/* + * 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 (ClutterMasterClockDefault *master_clock) +{ + GSource *source = g_source_new (&clock_funcs, sizeof (ClutterClockSource)); + ClutterClockSource *clock_source = (ClutterClockSource *) source; + + g_source_set_name (source, "Clutter master clock"); + clock_source->master_clock = master_clock; + + return source; +} + +static gboolean +clutter_clock_prepare (GSource *source, + gint *timeout) +{ + ClutterClockSource *clock_source = (ClutterClockSource *) source; + ClutterMasterClockDefault *master_clock = clock_source->master_clock; + int delay; + + _clutter_threads_acquire_lock (); + + if (G_UNLIKELY (clutter_paint_debug_flags & + CLUTTER_DEBUG_CONTINUOUS_REDRAW)) + { + ClutterStageManager *stage_manager = clutter_stage_manager_get_default (); + const GSList *stages, *l; + + stages = clutter_stage_manager_peek_stages (stage_manager); + + /* Queue a full redraw on all of the stages */ + for (l = stages; l != NULL; l = l->next) + clutter_actor_queue_redraw (l->data); + } + + delay = master_clock_next_frame_delay (master_clock); + + _clutter_threads_release_lock (); + + *timeout = delay; + + return delay == 0; +} + +static gboolean +clutter_clock_check (GSource *source) +{ + ClutterClockSource *clock_source = (ClutterClockSource *) source; + ClutterMasterClockDefault *master_clock = clock_source->master_clock; + int delay; + + _clutter_threads_acquire_lock (); + delay = master_clock_next_frame_delay (master_clock); + _clutter_threads_release_lock (); + + return delay == 0; +} + +static gboolean +clutter_clock_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + ClutterClockSource *clock_source = (ClutterClockSource *) source; + ClutterMasterClockDefault *master_clock = clock_source->master_clock; + gboolean stages_updated = FALSE; + GSList *stages; + + CLUTTER_NOTE (SCHEDULER, "Master clock [tick]"); + + _clutter_threads_acquire_lock (); + + /* Get the time to use for this frame */ + master_clock->cur_tick = g_source_get_time (source); + +#ifdef CLUTTER_ENABLE_DEBUG + master_clock->remaining_budget = master_clock->frame_budget; +#endif + + /* We need to protect ourselves against stages being destroyed during + * event handling - master_clock_list_ready_stages() returns a + * list of referenced that we'll unref afterwards. + */ + stages = master_clock_list_ready_stages (master_clock); + + master_clock->idle = FALSE; + + /* Each frame is split into three separate phases: */ + + /* 1. process all the events; each stage goes through its events queue + * and processes each event according to its type, then emits the + * various signals that are associated with the event + */ + master_clock_process_events (master_clock, stages); + + /* 2. advance the timelines */ + master_clock_advance_timelines (master_clock); + + /* 3. relayout and redraw the stages */ + stages_updated = master_clock_update_stages (master_clock, stages); + + /* The master clock goes idle if no stages were updated and falls back + * to polling for timeline progressions... */ + if (!stages_updated) + master_clock->idle = TRUE; + + master_clock_reschedule_stage_updates (master_clock, stages); + + g_slist_foreach (stages, (GFunc) g_object_unref, NULL); + g_slist_free (stages); + + master_clock->prev_tick = master_clock->cur_tick; + + _clutter_threads_release_lock (); + + return TRUE; +} + +static void +clutter_master_clock_default_finalize (GObject *gobject) +{ + ClutterMasterClockDefault *master_clock = CLUTTER_MASTER_CLOCK_DEFAULT (gobject); + + g_slist_free (master_clock->timelines); + + G_OBJECT_CLASS (clutter_master_clock_default_parent_class)->finalize (gobject); +} + +static void +clutter_master_clock_default_class_init (ClutterMasterClockDefaultClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = clutter_master_clock_default_finalize; +} + +static void +clutter_master_clock_default_init (ClutterMasterClockDefault *self) +{ + GSource *source; + + source = clutter_clock_source_new (self); + self->source = source; + + self->idle = FALSE; + self->ensure_next_iteration = FALSE; + self->paused = FALSE; + +#ifdef CLUTTER_ENABLE_DEBUG + self->frame_budget = G_USEC_PER_SEC / 60; +#endif + + g_source_set_priority (source, CLUTTER_PRIORITY_REDRAW); + g_source_set_can_recurse (source, FALSE); + g_source_attach (source, NULL); +} + +static void +clutter_master_clock_default_add_timeline (ClutterMasterClock *clock, + ClutterTimeline *timeline) +{ + ClutterMasterClockDefault *master_clock = (ClutterMasterClockDefault *) clock; + gboolean is_first; + + if (g_slist_find (master_clock->timelines, timeline)) + return; + + is_first = master_clock->timelines == NULL; + + master_clock->timelines = g_slist_prepend (master_clock->timelines, + timeline); + + if (is_first) + { + master_clock_schedule_stage_updates (master_clock); + _clutter_master_clock_start_running (clock); + } +} + +static void +clutter_master_clock_default_remove_timeline (ClutterMasterClock *clock, + ClutterTimeline *timeline) +{ + ClutterMasterClockDefault *master_clock = (ClutterMasterClockDefault *) clock; + + master_clock->timelines = g_slist_remove (master_clock->timelines, + timeline); +} + +static void +clutter_master_clock_default_start_running (ClutterMasterClock *master_clock) +{ + /* If called from a different thread, we need to wake up the + * main loop to start running the timelines + */ + g_main_context_wakeup (NULL); +} + +static void +clutter_master_clock_default_ensure_next_iteration (ClutterMasterClock *clock) +{ + ClutterMasterClockDefault *master_clock = (ClutterMasterClockDefault *) clock; + + master_clock->ensure_next_iteration = TRUE; +} + +static void +clutter_master_clock_default_set_paused (ClutterMasterClock *clock, + gboolean paused) +{ + ClutterMasterClockDefault *master_clock = (ClutterMasterClockDefault *) clock; + + master_clock->paused = !!paused; +} + +static void +clutter_master_clock_iface_init (ClutterMasterClockIface *iface) +{ + iface->add_timeline = clutter_master_clock_default_add_timeline; + iface->remove_timeline = clutter_master_clock_default_remove_timeline; + iface->start_running = clutter_master_clock_default_start_running; + iface->ensure_next_iteration = clutter_master_clock_default_ensure_next_iteration; + iface->set_paused = clutter_master_clock_default_set_paused; +} diff --git a/clutter/clutter/clutter-master-clock-default.h b/clutter/clutter/clutter-master-clock-default.h new file mode 100644 index 0000000..87dcf6c --- /dev/null +++ b/clutter/clutter/clutter-master-clock-default.h @@ -0,0 +1,48 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By: Lionel Landwerlin + * + * Copyright (C) 2015 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 . + */ + +#ifndef __CLUTTER_MASTER_CLOCK_DEFAULT_H__ +#define __CLUTTER_MASTER_CLOCK_DEFAULT_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_MASTER_CLOCK_DEFAULT (_clutter_master_clock_default_get_type ()) +#define CLUTTER_MASTER_CLOCK_DEFAULT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_MASTER_CLOCK_DEFAULT, ClutterMasterClockDefault)) +#define CLUTTER_IS_MASTER_CLOCK_DEFAULT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_MASTER_CLOCK_DEFAULT)) +#define CLUTTER_MASTER_CLOCK_DEFAULT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_MASTER_CLOCK_DEFAULT, ClutterMasterClockDefaultClass)) + +typedef struct _ClutterMasterClockDefault ClutterMasterClockDefault; +typedef struct _ClutterMasterClockDefaultClass ClutterMasterClockDefaultClass; + +struct _ClutterMasterClockDefaultClass +{ + GObjectClass parent_class; +}; + +GType _clutter_master_clock_default_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* __CLUTTER_MASTER_CLOCK_DEFAULT_H__ */ diff --git a/clutter/clutter/clutter-master-clock.c b/clutter/clutter/clutter-master-clock.c new file mode 100644 index 0000000..379df3a --- /dev/null +++ b/clutter/clutter/clutter-master-clock.c @@ -0,0 +1,138 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By: Emmanuele Bassi + * + * 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 . + */ + +/* + * 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 "clutter-build-config.h" +#endif + +#include "clutter-master-clock.h" +#include "clutter-master-clock-default.h" +#include "clutter-private.h" + +#define clutter_master_clock_get_type _clutter_master_clock_get_type + +typedef ClutterMasterClockIface ClutterMasterClockInterface; + +G_DEFINE_INTERFACE (ClutterMasterClock, clutter_master_clock, G_TYPE_OBJECT) + +static void +clutter_master_clock_default_init (ClutterMasterClockInterface *iface) +{ +} + +ClutterMasterClock * +_clutter_master_clock_get_default (void) +{ + ClutterMainContext *context = _clutter_context_get_default (); + + if (G_UNLIKELY (context->master_clock == NULL)) + context->master_clock = g_object_new (CLUTTER_TYPE_MASTER_CLOCK_DEFAULT, NULL); + + return context->master_clock; + +} + +/* + * _clutter_master_clock_add_timeline: + * @master_clock: a #ClutterMasterClock + * @timeline: a #ClutterTimeline + * + * Adds @timeline to the list of playing timelines held by the master + * clock. + */ +void +_clutter_master_clock_add_timeline (ClutterMasterClock *master_clock, + ClutterTimeline *timeline) +{ + g_return_if_fail (CLUTTER_IS_MASTER_CLOCK (master_clock)); + + CLUTTER_MASTER_CLOCK_GET_IFACE (master_clock)->add_timeline (master_clock, + timeline); +} + +/* + * _clutter_master_clock_remove_timeline: + * @master_clock: a #ClutterMasterClock + * @timeline: a #ClutterTimeline + * + * Removes @timeline from the list of playing timelines held by the + * master clock. + */ +void +_clutter_master_clock_remove_timeline (ClutterMasterClock *master_clock, + ClutterTimeline *timeline) +{ + g_return_if_fail (CLUTTER_IS_MASTER_CLOCK (master_clock)); + + CLUTTER_MASTER_CLOCK_GET_IFACE (master_clock)->remove_timeline (master_clock, + timeline); +} + +/* + * _clutter_master_clock_start_running: + * @master_clock: a #ClutterMasterClock + * + * Called when we have events or redraws to process; if the clock + * is stopped, does the processing necessary to wake it up again. + */ +void +_clutter_master_clock_start_running (ClutterMasterClock *master_clock) +{ + g_return_if_fail (CLUTTER_IS_MASTER_CLOCK (master_clock)); + + CLUTTER_MASTER_CLOCK_GET_IFACE (master_clock)->start_running (master_clock); +} + +/** + * _clutter_master_clock_ensure_next_iteration: + * @master_clock: a #ClutterMasterClock + * + * Ensures that the master clock will run at least one iteration + */ +void +_clutter_master_clock_ensure_next_iteration (ClutterMasterClock *master_clock) +{ + g_return_if_fail (CLUTTER_IS_MASTER_CLOCK (master_clock)); + + CLUTTER_MASTER_CLOCK_GET_IFACE (master_clock)->ensure_next_iteration (master_clock); +} + +void +_clutter_master_clock_set_paused (ClutterMasterClock *master_clock, + gboolean paused) +{ + g_return_if_fail (CLUTTER_IS_MASTER_CLOCK (master_clock)); + + CLUTTER_MASTER_CLOCK_GET_IFACE (master_clock)->set_paused (master_clock, + !!paused); +} diff --git a/clutter/clutter/clutter-master-clock.h b/clutter/clutter/clutter-master-clock.h new file mode 100644 index 0000000..542b917 --- /dev/null +++ b/clutter/clutter/clutter-master-clock.h @@ -0,0 +1,74 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By: Emmanuele Bassi + * + * 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 . + */ + +#ifndef __CLUTTER_MASTER_CLOCK_H__ +#define __CLUTTER_MASTER_CLOCK_H__ + +#include + +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)) +#define CLUTTER_MASTER_CLOCK_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), CLUTTER_TYPE_MASTER_CLOCK, ClutterMasterClockIface)) + +typedef struct _ClutterMasterClock ClutterMasterClock; /* dummy */ +typedef struct _ClutterMasterClockIface ClutterMasterClockIface; + +struct _ClutterMasterClockIface +{ + /*< private >*/ + GTypeInterface parent_iface; + + void (* add_timeline) (ClutterMasterClock *master_clock, + ClutterTimeline *timeline); + void (* remove_timeline) (ClutterMasterClock *master_clock, + ClutterTimeline *timeline); + void (* start_running) (ClutterMasterClock *master_clock); + void (* ensure_next_iteration) (ClutterMasterClock *master_clock); + void (* set_paused) (ClutterMasterClock *master_clock, + gboolean paused); +}; + +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_start_running (ClutterMasterClock *master_clock); +void _clutter_master_clock_ensure_next_iteration (ClutterMasterClock *master_clock); +void _clutter_master_clock_set_paused (ClutterMasterClock *master_clock, + gboolean paused); + +void _clutter_timeline_advance (ClutterTimeline *timeline, + gint64 tick_time); +gint64 _clutter_timeline_get_delta (ClutterTimeline *timeline); +void _clutter_timeline_do_tick (ClutterTimeline *timeline, + gint64 tick_time); + +G_END_DECLS + +#endif /* __CLUTTER_MASTER_CLOCK_H__ */ diff --git a/clutter/clutter/clutter-mutter.h b/clutter/clutter/clutter-mutter.h new file mode 100644 index 0000000..b820e6b --- /dev/null +++ b/clutter/clutter/clutter-mutter.h @@ -0,0 +1,45 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2016 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + */ + +#ifndef __CLUTTER_MUTTER_H__ +#define __CLUTTER_MUTTER_H__ + +#define __CLUTTER_H_INSIDE__ + +#include "clutter-backend.h" +#include "clutter-macros.h" +#include "clutter-stage-view.h" +#include "cogl/clutter-stage-cogl.h" +#include "x11/clutter-stage-x11.h" + +CLUTTER_AVAILABLE_IN_MUTTER +void clutter_set_custom_backend_func (ClutterBackend *(* func) (void)); + +CLUTTER_AVAILABLE_IN_MUTTER +gboolean _clutter_get_sync_to_vblank (void); + +CLUTTER_AVAILABLE_IN_MUTTER +int64_t clutter_stage_get_frame_counter (ClutterStage *stage); + +#undef __CLUTTER_H_INSIDE__ + +#endif /* __CLUTTER_MUTTER_H__ */ diff --git a/clutter/clutter/clutter-offscreen-effect-private.h b/clutter/clutter/clutter-offscreen-effect-private.h new file mode 100644 index 0000000..a5249da --- /dev/null +++ b/clutter/clutter/clutter-offscreen-effect-private.h @@ -0,0 +1,10 @@ +#ifndef __CLUTTER_OFFSCREEN_EFFECT_PRIVATE_H__ +#define __CLUTTER_OFFSCREEN_EFFECT_PRIVATE_H__ + +#include + +G_BEGIN_DECLS + +G_END_DECLS + +#endif /* __CLUTTER_OFFSCREEN_EFFECT_PRIVATE_H__ */ diff --git a/clutter/clutter/clutter-offscreen-effect.c b/clutter/clutter/clutter-offscreen-effect.c new file mode 100644 index 0000000..1dbf29f --- /dev/null +++ b/clutter/clutter/clutter-offscreen-effect.c @@ -0,0 +1,669 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: + * Emmanuele Bassi + * Robert Bragg + */ + +/** + * SECTION:clutter-offscreen-effect + * @short_description: Base class for effects using offscreen buffers + * @see_also: #ClutterBlurEffect, #ClutterEffect + * + * #ClutterOffscreenEffect is an abstract class that can be used by + * #ClutterEffect sub-classes requiring access to an offscreen buffer. + * + * Some effects, like the fragment shader based effects, can only use GL + * textures, and in order to apply those effects to any kind of actor they + * require that all drawing operations are applied to an offscreen framebuffer + * that gets redirected to a texture. + * + * #ClutterOffscreenEffect provides all the heavy-lifting for creating the + * offscreen framebuffer, the redirection and the final paint of the texture on + * the desired stage. + * + * #ClutterOffscreenEffect is available since Clutter 1.4 + * + * ## Implementing a ClutterOffscreenEffect + * + * Creating a sub-class of #ClutterOffscreenEffect requires, in case + * of overriding the #ClutterEffect virtual functions, to chain up to the + * #ClutterOffscreenEffect's implementation. + * + * On top of the #ClutterEffect's virtual functions, + * #ClutterOffscreenEffect also provides a #ClutterOffscreenEffectClass.paint_target() + * function, which encapsulates the effective painting of the texture that + * contains the result of the offscreen redirection. + * + * The size of the target material is defined to be as big as the + * transformed size of the #ClutterActor using the offscreen effect. + * Sub-classes of #ClutterOffscreenEffect can change the texture creation + * code to provide bigger textures by overriding the + * #ClutterOffscreenEffectClass.create_texture() virtual function; no chain up + * to the #ClutterOffscreenEffect implementation is required in this + * case. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-offscreen-effect.h" + +#include "cogl/cogl.h" + +#include "clutter-actor-private.h" +#include "clutter-debug.h" +#include "clutter-private.h" +#include "clutter-stage-private.h" + +struct _ClutterOffscreenEffectPrivate +{ + CoglHandle offscreen; + CoglPipeline *target; + CoglHandle texture; + + ClutterActor *actor; + ClutterActor *stage; + + gfloat x_offset; + gfloat y_offset; + + /* This is the calculated size of the fbo before being passed + through create_texture(). This needs to be tracked separately so + that we can detect when a different size is calculated and + regenerate the fbo */ + int fbo_width; + int fbo_height; + + gint old_opacity_override; + + /* The matrix that was current the last time the fbo was updated. We + need to keep track of this to detect when we can reuse the + contents of the fbo without redrawing the actor. We need the + actual matrix rather than just detecting queued redraws on the + actor because any change in the parent hierarchy (even just a + translation) could cause the actor to look completely different + and it won't cause a redraw to be queued on the parent's + children. */ + CoglMatrix last_matrix_drawn; +}; + +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterOffscreenEffect, + clutter_offscreen_effect, + CLUTTER_TYPE_EFFECT) + +static void +clutter_offscreen_effect_set_actor (ClutterActorMeta *meta, + ClutterActor *actor) +{ + ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (meta); + ClutterOffscreenEffectPrivate *priv = self->priv; + ClutterActorMetaClass *meta_class; + + meta_class = CLUTTER_ACTOR_META_CLASS (clutter_offscreen_effect_parent_class); + meta_class->set_actor (meta, actor); + + /* clear out the previous state */ + if (priv->offscreen != NULL) + { + cogl_handle_unref (priv->offscreen); + priv->offscreen = NULL; + } + + /* we keep a back pointer here, to avoid going through the ActorMeta */ + priv->actor = clutter_actor_meta_get_actor (meta); +} + +static CoglHandle +clutter_offscreen_effect_real_create_texture (ClutterOffscreenEffect *effect, + gfloat width, + gfloat height) +{ + return cogl_texture_new_with_size (MAX (width, 1), MAX (height, 1), + COGL_TEXTURE_NO_SLICING, + COGL_PIXEL_FORMAT_RGBA_8888_PRE); +} + +static gboolean +update_fbo (ClutterEffect *effect, int fbo_width, int fbo_height) +{ + ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect); + ClutterOffscreenEffectPrivate *priv = self->priv; + + priv->stage = clutter_actor_get_stage (priv->actor); + if (priv->stage == NULL) + { + CLUTTER_NOTE (MISC, "The actor '%s' is not part of a stage", + clutter_actor_get_name (priv->actor) == NULL + ? G_OBJECT_TYPE_NAME (priv->actor) + : clutter_actor_get_name (priv->actor)); + return FALSE; + } + + if (priv->fbo_width == fbo_width && + priv->fbo_height == fbo_height && + priv->offscreen != NULL) + return TRUE; + + if (priv->target == NULL) + { + CoglContext *ctx = + clutter_backend_get_cogl_context (clutter_get_default_backend ()); + + priv->target = cogl_pipeline_new (ctx); + + /* We're always going to render the texture at a 1:1 texel:pixel + ratio so we can use 'nearest' filtering to decrease the + effects of rounding errors in the geometry calculation */ + cogl_pipeline_set_layer_filters (priv->target, + 0, /* layer_index */ + COGL_PIPELINE_FILTER_NEAREST, + COGL_PIPELINE_FILTER_NEAREST); + } + + if (priv->texture != NULL) + { + cogl_handle_unref (priv->texture); + priv->texture = NULL; + } + + priv->texture = + clutter_offscreen_effect_create_texture (self, fbo_width, fbo_height); + if (priv->texture == NULL) + return FALSE; + + cogl_pipeline_set_layer_texture (priv->target, 0, priv->texture); + + priv->fbo_width = fbo_width; + priv->fbo_height = fbo_height; + + if (priv->offscreen != NULL) + cogl_handle_unref (priv->offscreen); + + priv->offscreen = cogl_offscreen_new_to_texture (priv->texture); + if (priv->offscreen == NULL) + { + g_warning ("%s: Unable to create an Offscreen buffer", G_STRLOC); + + cogl_handle_unref (priv->target); + priv->target = NULL; + + priv->fbo_width = 0; + priv->fbo_height = 0; + + return FALSE; + } + + return TRUE; +} + +static gboolean +clutter_offscreen_effect_pre_paint (ClutterEffect *effect) +{ + ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect); + ClutterOffscreenEffectPrivate *priv = self->priv; + ClutterActorBox box; + ClutterActor *stage; + CoglMatrix projection; + CoglColor transparent; + gfloat stage_width, stage_height; + gfloat fbo_width = -1, fbo_height = -1; + gfloat width, height; + gfloat xexpand, yexpand; + int texture_width, texture_height; + + if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect))) + return FALSE; + + if (priv->actor == NULL) + return FALSE; + + stage = _clutter_actor_get_stage_internal (priv->actor); + clutter_actor_get_size (stage, &stage_width, &stage_height); + + /* The paint box is the bounding box of the actor's paint volume in + * stage coordinates. This will give us the size for the framebuffer + * we need to redirect its rendering offscreen and its position will + * be used to setup an offset viewport */ + if (clutter_actor_get_paint_box (priv->actor, &box)) + { + clutter_actor_box_get_size (&box, &fbo_width, &fbo_height); + clutter_actor_box_get_origin (&box, &priv->x_offset, &priv->y_offset); + + fbo_width = MIN (fbo_width, stage_width); + fbo_height = MIN (fbo_height, stage_height); + } + else + { + fbo_width = stage_width; + fbo_height = stage_height; + } + + if (fbo_width == stage_width) + priv->x_offset = 0.0f; + if (fbo_height == stage_height) + priv->y_offset = 0.0f; + + /* First assert that the framebuffer is the right size... */ + if (!update_fbo (effect, fbo_width, fbo_height)) + return FALSE; + + texture_width = cogl_texture_get_width (priv->texture); + texture_height = cogl_texture_get_height (priv->texture); + + /* get the current modelview matrix so that we can copy it to the + * framebuffer. We also store the matrix that was last used when we + * updated the FBO so that we can detect when we don't need to + * update the FBO to paint a second time */ + cogl_get_modelview_matrix (&priv->last_matrix_drawn); + + /* let's draw offscreen */ + cogl_push_framebuffer (priv->offscreen); + + /* Copy the modelview that would have been used if rendering onscreen */ + cogl_set_modelview_matrix (&priv->last_matrix_drawn); + + /* Set up the viewport so that it has the same size as the stage, + * but offset it so that the actor of interest lands on our + * framebuffer. */ + clutter_actor_get_size (priv->stage, &width, &height); + + /* Expand the viewport if the actor is partially off-stage, + * otherwise the actor will end up clipped to the stage viewport + */ + xexpand = 0.f; + if (priv->x_offset < 0.f) + xexpand = -priv->x_offset; + if (priv->x_offset + texture_width > width) + xexpand = MAX (xexpand, (priv->x_offset + texture_width) - width); + + yexpand = 0.f; + if (priv->y_offset < 0.f) + yexpand = -priv->y_offset; + if (priv->y_offset + texture_height > height) + yexpand = MAX (yexpand, (priv->y_offset + texture_height) - height); + + /* Set the viewport */ + cogl_set_viewport (-(priv->x_offset + xexpand), -(priv->y_offset + yexpand), + width + (2 * xexpand), height + (2 * yexpand)); + + /* Copy the stage's projection matrix across to the framebuffer */ + _clutter_stage_get_projection_matrix (CLUTTER_STAGE (priv->stage), + &projection); + + /* If we've expanded the viewport, make sure to scale the projection + * matrix accordingly (as it's been initialised to work with the + * original viewport and not our expanded one). + */ + if (xexpand > 0.f || yexpand > 0.f) + { + gfloat new_width, new_height; + + new_width = width + (2 * xexpand); + new_height = height + (2 * yexpand); + + cogl_matrix_scale (&projection, + width / new_width, + height / new_height, + 1); + } + + cogl_set_projection_matrix (&projection); + + cogl_color_init_from_4ub (&transparent, 0, 0, 0, 0); + cogl_clear (&transparent, + COGL_BUFFER_BIT_COLOR | + COGL_BUFFER_BIT_DEPTH); + + cogl_push_matrix (); + + /* Override the actor's opacity to fully opaque - we paint the offscreen + * texture with the actor's paint opacity, so we need to do this to avoid + * multiplying the opacity twice. + */ + priv->old_opacity_override = + clutter_actor_get_opacity_override (priv->actor); + clutter_actor_set_opacity_override (priv->actor, 0xff); + + return TRUE; +} + +static void +clutter_offscreen_effect_real_paint_target (ClutterOffscreenEffect *effect) +{ + ClutterOffscreenEffectPrivate *priv = effect->priv; + guint8 paint_opacity; + + paint_opacity = clutter_actor_get_paint_opacity (priv->actor); + + cogl_pipeline_set_color4ub (priv->target, + paint_opacity, + paint_opacity, + paint_opacity, + paint_opacity); + cogl_set_source (priv->target); + + /* At this point we are in stage coordinates translated so if + * we draw our texture using a textured quad the size of the paint + * box then we will overlay where the actor would have drawn if it + * hadn't been redirected offscreen. + */ + cogl_rectangle_with_texture_coords (0, 0, + cogl_texture_get_width (priv->texture), + cogl_texture_get_height (priv->texture), + 0.0, 0.0, + 1.0, 1.0); +} + +static void +clutter_offscreen_effect_paint_texture (ClutterOffscreenEffect *effect) +{ + ClutterOffscreenEffectPrivate *priv = effect->priv; + CoglMatrix modelview; + + cogl_push_matrix (); + + /* Now reset the modelview to put us in stage coordinates so + * we can drawn the result of our offscreen render as a textured + * quad... */ + + cogl_matrix_init_identity (&modelview); + _clutter_actor_apply_modelview_transform (priv->stage, &modelview); + cogl_matrix_translate (&modelview, priv->x_offset, priv->y_offset, 0.0f); + cogl_set_modelview_matrix (&modelview); + + /* paint the target material; this is virtualized for + * sub-classes that require special hand-holding + */ + clutter_offscreen_effect_paint_target (effect); + + cogl_pop_matrix (); +} + +static void +clutter_offscreen_effect_post_paint (ClutterEffect *effect) +{ + ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect); + ClutterOffscreenEffectPrivate *priv = self->priv; + + if (priv->offscreen == NULL || + priv->target == NULL || + priv->actor == NULL) + return; + + /* Restore the previous opacity override */ + clutter_actor_set_opacity_override (priv->actor, priv->old_opacity_override); + + cogl_pop_matrix (); + cogl_pop_framebuffer (); + + clutter_offscreen_effect_paint_texture (self); +} + +static void +clutter_offscreen_effect_paint (ClutterEffect *effect, + ClutterEffectPaintFlags flags) +{ + ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect); + ClutterOffscreenEffectPrivate *priv = self->priv; + CoglMatrix matrix; + + cogl_get_modelview_matrix (&matrix); + + /* If we've already got a cached image for the same matrix and the + actor hasn't been redrawn then we can just use the cached image + in the fbo */ + if (priv->offscreen == NULL || + (flags & CLUTTER_EFFECT_PAINT_ACTOR_DIRTY) || + !cogl_matrix_equal (&matrix, &priv->last_matrix_drawn)) + { + /* Chain up to the parent paint method which will call the pre and + post paint functions to update the image */ + CLUTTER_EFFECT_CLASS (clutter_offscreen_effect_parent_class)-> + paint (effect, flags); + } + else + clutter_offscreen_effect_paint_texture (self); +} + +static void +clutter_offscreen_effect_finalize (GObject *gobject) +{ + ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (gobject); + ClutterOffscreenEffectPrivate *priv = self->priv; + + if (priv->offscreen) + cogl_handle_unref (priv->offscreen); + + if (priv->target) + cogl_handle_unref (priv->target); + + if (priv->texture) + cogl_handle_unref (priv->texture); + + G_OBJECT_CLASS (clutter_offscreen_effect_parent_class)->finalize (gobject); +} + +static void +clutter_offscreen_effect_class_init (ClutterOffscreenEffectClass *klass) +{ + ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass); + ClutterEffectClass *effect_class = CLUTTER_EFFECT_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + klass->create_texture = clutter_offscreen_effect_real_create_texture; + klass->paint_target = clutter_offscreen_effect_real_paint_target; + + meta_class->set_actor = clutter_offscreen_effect_set_actor; + + effect_class->pre_paint = clutter_offscreen_effect_pre_paint; + effect_class->post_paint = clutter_offscreen_effect_post_paint; + effect_class->paint = clutter_offscreen_effect_paint; + + gobject_class->finalize = clutter_offscreen_effect_finalize; +} + +static void +clutter_offscreen_effect_init (ClutterOffscreenEffect *self) +{ + self->priv = clutter_offscreen_effect_get_instance_private (self); +} + +/** + * clutter_offscreen_effect_get_texture: + * @effect: a #ClutterOffscreenEffect + * + * Retrieves the texture used as a render target for the offscreen + * buffer created by @effect + * + * You should only use the returned texture when painting. The texture + * may change after ClutterEffect::pre_paint is called so the effect + * implementation should update any references to the texture after + * chaining-up to the parent's pre_paint implementation. This can be + * used instead of clutter_offscreen_effect_get_target() when the + * effect subclass wants to paint using its own material. + * + * Return value: (transfer none): a #CoglHandle or %COGL_INVALID_HANDLE. The + * returned texture is owned by Clutter and it should not be + * modified or freed + * + * Since: 1.10 + */ +CoglHandle +clutter_offscreen_effect_get_texture (ClutterOffscreenEffect *effect) +{ + g_return_val_if_fail (CLUTTER_IS_OFFSCREEN_EFFECT (effect), + NULL); + + return effect->priv->texture; +} + +/** + * clutter_offscreen_effect_get_target: (skip) + * @effect: a #ClutterOffscreenEffect + * + * Retrieves the material used as a render target for the offscreen + * buffer created by @effect + * + * You should only use the returned #CoglMaterial when painting. The + * returned material might change between different frames. + * + * Return value: (transfer none): a #CoglMaterial or %NULL. The + * returned material is owned by Clutter and it should not be + * modified or freed + * + * Since: 1.4 + */ +CoglMaterial * +clutter_offscreen_effect_get_target (ClutterOffscreenEffect *effect) +{ + g_return_val_if_fail (CLUTTER_IS_OFFSCREEN_EFFECT (effect), + NULL); + + return (CoglMaterial *)effect->priv->target; +} + +/** + * clutter_offscreen_effect_paint_target: + * @effect: a #ClutterOffscreenEffect + * + * Calls the paint_target() virtual function of the @effect + * + * Since: 1.4 + */ +void +clutter_offscreen_effect_paint_target (ClutterOffscreenEffect *effect) +{ + g_return_if_fail (CLUTTER_IS_OFFSCREEN_EFFECT (effect)); + + CLUTTER_OFFSCREEN_EFFECT_GET_CLASS (effect)->paint_target (effect); +} + +/** + * clutter_offscreen_effect_create_texture: + * @effect: a #ClutterOffscreenEffect + * @width: the minimum width of the target texture + * @height: the minimum height of the target texture + * + * Calls the create_texture() virtual function of the @effect + * + * Return value: (transfer full): a handle to a Cogl texture, or + * %COGL_INVALID_HANDLE. The returned handle has its reference + * count increased. + * + * Since: 1.4 + */ +CoglHandle +clutter_offscreen_effect_create_texture (ClutterOffscreenEffect *effect, + gfloat width, + gfloat height) +{ + g_return_val_if_fail (CLUTTER_IS_OFFSCREEN_EFFECT (effect), + NULL); + + return CLUTTER_OFFSCREEN_EFFECT_GET_CLASS (effect)->create_texture (effect, + width, + height); +} + +/** + * clutter_offscreen_effect_get_target_size: + * @effect: a #ClutterOffscreenEffect + * @width: (out): return location for the target width, or %NULL + * @height: (out): return location for the target height, or %NULL + * + * Retrieves the size of the offscreen buffer used by @effect to + * paint the actor to which it has been applied. + * + * This function should only be called by #ClutterOffscreenEffect + * implementations, from within the #ClutterOffscreenEffectClass.paint_target() + * virtual function. + * + * Return value: %TRUE if the offscreen buffer has a valid size, + * and %FALSE otherwise + * + * Since: 1.8 + * + * Deprecated: 1.14: Use clutter_offscreen_effect_get_target_rect() instead + */ +gboolean +clutter_offscreen_effect_get_target_size (ClutterOffscreenEffect *effect, + gfloat *width, + gfloat *height) +{ + ClutterOffscreenEffectPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_OFFSCREEN_EFFECT (effect), FALSE); + + priv = effect->priv; + + if (priv->texture == NULL) + return FALSE; + + if (width) + *width = cogl_texture_get_width (priv->texture); + + if (height) + *height = cogl_texture_get_height (priv->texture); + + return TRUE; +} + +/** + * clutter_offscreen_effect_get_target_rect: + * @effect: a #ClutterOffscreenEffect + * @rect: (out caller-allocates): return location for the target area + * + * Retrieves the origin and size of the offscreen buffer used by @effect to + * paint the actor to which it has been applied. + * + * This function should only be called by #ClutterOffscreenEffect + * implementations, from within the #ClutterOffscreenEffectClass.paint_target() + * virtual function. + * + * Return value: %TRUE if the offscreen buffer has a valid rectangle, + * and %FALSE otherwise + * + * Since: 1.14 + */ +gboolean +clutter_offscreen_effect_get_target_rect (ClutterOffscreenEffect *effect, + ClutterRect *rect) +{ + ClutterOffscreenEffectPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_OFFSCREEN_EFFECT (effect), FALSE); + g_return_val_if_fail (rect != NULL, FALSE); + + priv = effect->priv; + + if (priv->texture == NULL) + return FALSE; + + clutter_rect_init (rect, + priv->x_offset, + priv->y_offset, + cogl_texture_get_width (priv->texture), + cogl_texture_get_height (priv->texture)); + + return TRUE; +} diff --git a/clutter/clutter/clutter-offscreen-effect.h b/clutter/clutter/clutter-offscreen-effect.h new file mode 100644 index 0000000..3c88f67 --- /dev/null +++ b/clutter/clutter/clutter-offscreen-effect.h @@ -0,0 +1,121 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_OFFSCREEN_EFFECT_H__ +#define __CLUTTER_OFFSCREEN_EFFECT_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_OFFSCREEN_EFFECT (clutter_offscreen_effect_get_type ()) +#define CLUTTER_OFFSCREEN_EFFECT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CLUTTER_TYPE_OFFSCREEN_EFFECT, ClutterOffscreenEffect)) +#define CLUTTER_IS_OFFSCREEN_EFFECT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CLUTTER_TYPE_OFFSCREEN_EFFECT)) +#define CLUTTER_OFFSCREEN_EFFECT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), CLUTTER_TYPE_OFFSCREEN_EFFECT, ClutterOffscreenEffectClass)) +#define CLUTTER_IS_OFFSCREEN_EFFECT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CLUTTER_TYPE_OFFSCREEN_EFFECT)) +#define CLUTTER_OFFSCREEN_EFFECT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CLUTTER_TYPE_OFFSCREEN_EFFECT, ClutterOffscreenEffectClass)) + +typedef struct _ClutterOffscreenEffect ClutterOffscreenEffect; +typedef struct _ClutterOffscreenEffectPrivate ClutterOffscreenEffectPrivate; +typedef struct _ClutterOffscreenEffectClass ClutterOffscreenEffectClass; + +/** + * ClutterOffscreenEffect: + * + * The #ClutterOffscreenEffect structure contains only private data + * and should be accessed using the provided API + * + * Since: 1.4 + */ +struct _ClutterOffscreenEffect +{ + /*< private >*/ + ClutterEffect parent_instance; + + ClutterOffscreenEffectPrivate *priv; +}; + +/** + * ClutterOffscreenEffectClass: + * @create_texture: virtual function + * @paint_target: virtual function + * + * The #ClutterOffscreenEffectClass structure contains only private data + * + * Since: 1.4 + */ +struct _ClutterOffscreenEffectClass +{ + /*< private >*/ + ClutterEffectClass parent_class; + + /*< public >*/ + CoglHandle (* create_texture) (ClutterOffscreenEffect *effect, + gfloat width, + gfloat height); + void (* paint_target) (ClutterOffscreenEffect *effect); + + /*< private >*/ + void (* _clutter_offscreen1) (void); + void (* _clutter_offscreen2) (void); + void (* _clutter_offscreen3) (void); + void (* _clutter_offscreen4) (void); + void (* _clutter_offscreen5) (void); + void (* _clutter_offscreen6) (void); + void (* _clutter_offscreen7) (void); +}; + +CLUTTER_AVAILABLE_IN_1_4 +GType clutter_offscreen_effect_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_4 +CoglMaterial * clutter_offscreen_effect_get_target (ClutterOffscreenEffect *effect); + +CLUTTER_AVAILABLE_IN_1_10 +CoglHandle clutter_offscreen_effect_get_texture (ClutterOffscreenEffect *effect); + +CLUTTER_AVAILABLE_IN_1_4 +void clutter_offscreen_effect_paint_target (ClutterOffscreenEffect *effect); +CLUTTER_AVAILABLE_IN_1_4 +CoglHandle clutter_offscreen_effect_create_texture (ClutterOffscreenEffect *effect, + gfloat width, + gfloat height); + +CLUTTER_DEPRECATED_IN_1_14_FOR (clutter_offscreen_effect_get_target_rect) +gboolean clutter_offscreen_effect_get_target_size (ClutterOffscreenEffect *effect, + gfloat *width, + gfloat *height); + +CLUTTER_AVAILABLE_IN_1_14 +gboolean clutter_offscreen_effect_get_target_rect (ClutterOffscreenEffect *effect, + ClutterRect *rect); + +G_END_DECLS + +#endif /* __CLUTTER_OFFSCREEN_EFFECT_H__ */ diff --git a/clutter/clutter/clutter-page-turn-effect.c b/clutter/clutter/clutter-page-turn-effect.c new file mode 100644 index 0000000..4146b13 --- /dev/null +++ b/clutter/clutter/clutter-page-turn-effect.c @@ -0,0 +1,424 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + * + * Based on MxDeformPageTurn, written by: + * Chris Lord + */ + +/** + * SECTION:clutter-page-turn-effect + * @Title: ClutterPageTurnEffect + * @Short_Description: A page turning effect + * + * A simple page turning effect + * + * #ClutterPageTurnEffect is available since Clutter 1.4 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#include "clutter-page-turn-effect.h" + +#include "clutter-debug.h" +#include "clutter-private.h" + +#define CLUTTER_PAGE_TURN_EFFECT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), CLUTTER_TYPE_PAGE_TURN_EFFECT, ClutterPageTurnEffectClass)) +#define CLUTTER_IS_PAGE_TURN_EFFECT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CLUTTER_TYPE_PAGE_TURN_EFFECT)) +#define CLUTTER_PAGE_TURN_EFFECT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CLUTTER_TYPE_PAGE_TURN_EFFECT, ClutterPageTurnEffectClass)) + +struct _ClutterPageTurnEffect +{ + ClutterDeformEffect parent_instance; + + gdouble period; + gdouble angle; + + gfloat radius; +}; + +struct _ClutterPageTurnEffectClass +{ + ClutterDeformEffectClass parent_class; +}; + +enum +{ + PROP_0, + + PROP_PERIOD, + PROP_ANGLE, + PROP_RADIUS, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +G_DEFINE_TYPE (ClutterPageTurnEffect, + clutter_page_turn_effect, + CLUTTER_TYPE_DEFORM_EFFECT); + +static void +clutter_page_turn_effect_deform_vertex (ClutterDeformEffect *effect, + gfloat width, + gfloat height, + CoglTextureVertex *vertex) +{ + ClutterPageTurnEffect *self = CLUTTER_PAGE_TURN_EFFECT (effect); + gfloat cx, cy, rx, ry, radians, turn_angle; + guint shade; + + if (self->period == 0.0) + return; + + radians = self->angle / (180.0f / G_PI); + + /* Rotate the point around the centre of the page-curl ray to align it with + * the y-axis. + */ + cx = (1.f - self->period) * width; + cy = (1.f - self->period) * height; + + rx = ((vertex->x - cx) * cos (- radians)) + - ((vertex->y - cy) * sin (- radians)) + - self->radius; + ry = ((vertex->x - cx) * sin (- radians)) + + ((vertex->y - cy) * cos (- radians)); + + turn_angle = 0.f; + if (rx > self->radius * -2.0f) + { + /* Calculate the curl angle as a function from the distance of the curl + * ray (i.e. the page crease) + */ + turn_angle = (rx / self->radius * G_PI_2) - G_PI_2; + shade = (sin (turn_angle) * 96.0f) + 159.0f; + + /* Add a gradient that makes it look like lighting and hides the switch + * between textures. + */ + cogl_color_init_from_4ub (&vertex->color, shade, shade, shade, 0xff); + } + + if (rx > 0) + { + /* Make the curl radius smaller as more circles are formed (stops + * z-fighting and looks cool). Note that 10 is a semi-arbitrary + * number here - divide it by two and it's the amount of space + * between curled layers of the texture, in pixels. + */ + gfloat small_radius; + + small_radius = self->radius + - MIN (self->radius, (turn_angle * 10) / G_PI); + + /* Calculate a point on a cylinder (maybe make this a cone at some + * point) and rotate it by the specified angle. + */ + rx = (small_radius * cos (turn_angle)) + self->radius; + + vertex->x = (rx * cos (radians)) - (ry * sin (radians)) + cx; + vertex->y = (rx * sin (radians)) + (ry * cos (radians)) + cy; + vertex->z = (small_radius * sin (turn_angle)) + self->radius; + } +} + +static void +clutter_page_turn_effect_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterPageTurnEffect *effect = CLUTTER_PAGE_TURN_EFFECT (gobject); + + switch (prop_id) + { + case PROP_PERIOD: + clutter_page_turn_effect_set_period (effect, g_value_get_double (value)); + break; + + case PROP_ANGLE: + clutter_page_turn_effect_set_angle (effect, g_value_get_double (value)); + break; + + case PROP_RADIUS: + clutter_page_turn_effect_set_radius (effect, g_value_get_float (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_page_turn_effect_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterPageTurnEffect *effect = CLUTTER_PAGE_TURN_EFFECT (gobject); + + switch (prop_id) + { + case PROP_PERIOD: + g_value_set_double (value, effect->period); + break; + + case PROP_ANGLE: + g_value_set_double (value, effect->angle); + break; + + case PROP_RADIUS: + g_value_set_float (value, effect->radius); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_page_turn_effect_class_init (ClutterPageTurnEffectClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterDeformEffectClass *deform_class = CLUTTER_DEFORM_EFFECT_CLASS (klass); + GParamSpec *pspec; + + gobject_class->set_property = clutter_page_turn_effect_set_property; + gobject_class->get_property = clutter_page_turn_effect_get_property; + + /** + * ClutterPageTurnEffect:period: + * + * The period of the page turn, between 0.0 (no curling) and + * 1.0 (fully curled) + * + * Since: 1.4 + */ + pspec = g_param_spec_double ("period", + "Period", + "The period of the page turn", + 0.0, 1.0, + 0.0, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_PERIOD] = pspec; + g_object_class_install_property (gobject_class, PROP_PERIOD, pspec); + + /** + * ClutterPageTurnEffect:angle: + * + * The angle of the page rotation, in degrees, between 0.0 and 360.0 + * + * Since: 1.4 + */ + pspec = g_param_spec_double ("angle", + "Angle", + "The angle of the page rotation, in degrees", + 0.0, 360.0, + 0.0, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_ANGLE] = pspec; + g_object_class_install_property (gobject_class, PROP_ANGLE, pspec); + + /** + * ClutterPageTurnEffect:radius: + * + * The radius of the page curl, in pixels + * + * Since: 1.4 + */ + pspec = g_param_spec_float ("radius", + "Radius", + "The radius of the page curl", + -G_MAXFLOAT, G_MAXFLOAT, + 24.0, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_RADIUS] = pspec; + g_object_class_install_property (gobject_class, PROP_RADIUS, pspec); + + deform_class->deform_vertex = clutter_page_turn_effect_deform_vertex; +} + +static void +clutter_page_turn_effect_init (ClutterPageTurnEffect *self) +{ + self->period = 0.0; + self->angle = 0.0; + self->radius = 24.0f; +} + +/** + * clutter_page_turn_effect_new: + * @period: the period of the page curl, between 0.0 and 1.0 + * @angle: the angle of the page curl, between 0.0 and 360.0 + * @radius: the radius of the page curl, in pixels + * + * Creates a new #ClutterPageTurnEffect instance with the given parameters + * + * Return value: the newly created #ClutterPageTurnEffect + * + * Since: 1.4 + */ +ClutterEffect * +clutter_page_turn_effect_new (gdouble period, + gdouble angle, + gfloat radius) +{ + g_return_val_if_fail (period >= 0.0 && period <= 1.0, NULL); + g_return_val_if_fail (angle >= 0.0 && angle <= 360.0, NULL); + + return g_object_new (CLUTTER_TYPE_PAGE_TURN_EFFECT, + "period", period, + "angle", angle, + "radius", radius, + NULL); +} + +/** + * clutter_page_turn_effect_set_period: + * @effect: a #ClutterPageTurnEffect + * @period: the period of the page curl, between 0.0 and 1.0 + * + * Sets the period of the page curling, between 0.0 (no curling) + * and 1.0 (fully curled) + * + * Since: 1.4 + */ +void +clutter_page_turn_effect_set_period (ClutterPageTurnEffect *effect, + gdouble period) +{ + g_return_if_fail (CLUTTER_IS_PAGE_TURN_EFFECT (effect)); + g_return_if_fail (period >= 0.0 && period <= 1.0); + + effect->period = period; + + clutter_deform_effect_invalidate (CLUTTER_DEFORM_EFFECT (effect)); + + g_object_notify_by_pspec (G_OBJECT (effect), obj_props[PROP_PERIOD]); +} + +/** + * clutter_page_turn_effect_get_period: + * @effect: a #ClutterPageTurnEffect + * + * Retrieves the value set using clutter_page_turn_effect_get_period() + * + * Return value: the period of the page curling + * + * Since: 1.4 + */ +gdouble +clutter_page_turn_effect_get_period (ClutterPageTurnEffect *effect) +{ + g_return_val_if_fail (CLUTTER_IS_PAGE_TURN_EFFECT (effect), 0.0); + + return effect->period; +} + +/** + * clutter_page_turn_effect_set_angle: + * @effect: #ClutterPageTurnEffect + * @angle: the angle of the page curl, in degrees + * + * Sets the angle of the page curling, in degrees + * + * Since: 1.4 + */ +void +clutter_page_turn_effect_set_angle (ClutterPageTurnEffect *effect, + gdouble angle) +{ + g_return_if_fail (CLUTTER_IS_PAGE_TURN_EFFECT (effect)); + g_return_if_fail (angle >= 0.0 && angle <= 360.0); + + effect->angle = angle; + + clutter_deform_effect_invalidate (CLUTTER_DEFORM_EFFECT (effect)); + + g_object_notify_by_pspec (G_OBJECT (effect), obj_props[PROP_ANGLE]); +} + +/** + * clutter_page_turn_effect_get_angle: + * @effect: a #ClutterPageTurnEffect: + * + * Retrieves the value set using clutter_page_turn_effect_get_angle() + * + * Return value: the angle of the page curling + * + * Since: 1.4 + */ +gdouble +clutter_page_turn_effect_get_angle (ClutterPageTurnEffect *effect) +{ + g_return_val_if_fail (CLUTTER_IS_PAGE_TURN_EFFECT (effect), 0.0); + + return effect->angle; +} + +/** + * clutter_page_turn_effect_set_radius: + * @effect: a #ClutterPageTurnEffect: + * @radius: the radius of the page curling, in pixels + * + * Sets the radius of the page curling + * + * Since: 1.4 + */ +void +clutter_page_turn_effect_set_radius (ClutterPageTurnEffect *effect, + gfloat radius) +{ + g_return_if_fail (CLUTTER_IS_PAGE_TURN_EFFECT (effect)); + + effect->radius = radius; + + clutter_deform_effect_invalidate (CLUTTER_DEFORM_EFFECT (effect)); + + g_object_notify_by_pspec (G_OBJECT (effect), obj_props[PROP_RADIUS]); +} + +/** + * clutter_page_turn_effect_get_radius: + * @effect: a #ClutterPageTurnEffect + * + * Retrieves the value set using clutter_page_turn_effect_set_radius() + * + * Return value: the radius of the page curling + * + * Since: 1.4 + */ +gfloat +clutter_page_turn_effect_get_radius (ClutterPageTurnEffect *effect) +{ + g_return_val_if_fail (CLUTTER_IS_PAGE_TURN_EFFECT (effect), 0.0); + + return effect->radius; +} diff --git a/clutter/clutter/clutter-page-turn-effect.h b/clutter/clutter/clutter-page-turn-effect.h new file mode 100644 index 0000000..b3fb804 --- /dev/null +++ b/clutter/clutter/clutter-page-turn-effect.h @@ -0,0 +1,80 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + * + * Based on MxDeformPageTurn, written by: + * Chris Lord + */ + +#ifndef __CLUTTER_PAGE_TURN_EFFECT_H__ +#define __CLUTTER_PAGE_TURN_EFFECT_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_PAGE_TURN_EFFECT (clutter_page_turn_effect_get_type ()) +#define CLUTTER_PAGE_TURN_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_PAGE_TURN_EFFECT, ClutterPageTurnEffect)) +#define CLUTTER_IS_PAGE_TURN_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_PAGE_TURN_EFFECT)) + +/** + * ClutterPageTurnEffect: + * + * #ClutterPageTurnEffect is an opaque structure + * whose members can only be accessed using the provided API + * + * Since: 1.4 + */ +typedef struct _ClutterPageTurnEffect ClutterPageTurnEffect; +typedef struct _ClutterPageTurnEffectClass ClutterPageTurnEffectClass; + +CLUTTER_AVAILABLE_IN_1_4 +GType clutter_page_turn_effect_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_4 +ClutterEffect *clutter_page_turn_effect_new (gdouble period, + gdouble angle, + gfloat radius); + +CLUTTER_AVAILABLE_IN_1_4 +void clutter_page_turn_effect_set_period (ClutterPageTurnEffect *effect, + gdouble period); +CLUTTER_AVAILABLE_IN_1_4 +gdouble clutter_page_turn_effect_get_period (ClutterPageTurnEffect *effect); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_page_turn_effect_set_angle (ClutterPageTurnEffect *effect, + gdouble angle); +CLUTTER_AVAILABLE_IN_1_4 +gdouble clutter_page_turn_effect_get_angle (ClutterPageTurnEffect *effect); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_page_turn_effect_set_radius (ClutterPageTurnEffect *effect, + gfloat radius); +CLUTTER_AVAILABLE_IN_1_4 +gfloat clutter_page_turn_effect_get_radius (ClutterPageTurnEffect *effect); + +G_END_DECLS + +#endif /* __CLUTTER_PAGE_TURN_EFFECT_H__ */ diff --git a/clutter/clutter/clutter-paint-node-private.h b/clutter/clutter/clutter-paint-node-private.h new file mode 100644 index 0000000..2945b78 --- /dev/null +++ b/clutter/clutter/clutter-paint-node-private.h @@ -0,0 +1,171 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2011 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_PAINT_NODE_PRIVATE_H__ +#define __CLUTTER_PAINT_NODE_PRIVATE_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_PAINT_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_PAINT_NODE, ClutterPaintNodeClass)) +#define CLUTTER_IS_PAINT_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_PAINT_NODE)) +#define CLUTTER_PAINT_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_PAINT_NODE, ClutterPaintNodeClass)) + +typedef struct _ClutterPaintOperation ClutterPaintOperation; + +struct _ClutterPaintNode +{ + GTypeInstance parent_instance; + + ClutterPaintNode *parent; + + ClutterPaintNode *first_child; + ClutterPaintNode *prev_sibling; + ClutterPaintNode *next_sibling; + ClutterPaintNode *last_child; + + guint n_children; + + GArray *operations; + + gchar *name; + + volatile int ref_count; +}; + +struct _ClutterPaintNodeClass +{ + GTypeClass base_class; + + void (* finalize) (ClutterPaintNode *node); + + gboolean (* pre_draw) (ClutterPaintNode *node); + void (* draw) (ClutterPaintNode *node); + void (* post_draw) (ClutterPaintNode *node); + + JsonNode*(* serialize) (ClutterPaintNode *node); + + CoglFramebuffer *(* get_framebuffer) (ClutterPaintNode *node); +}; + +#define PAINT_OP_INIT { PAINT_OP_INVALID } + +typedef enum { + PAINT_OP_INVALID = 0, + PAINT_OP_TEX_RECT, + PAINT_OP_PATH, + PAINT_OP_PRIMITIVE +} PaintOpCode; + +struct _ClutterPaintOperation +{ + PaintOpCode opcode; + + union { + float texrect[8]; + + CoglPath *path; + + CoglPrimitive *primitive; + } op; +}; + +GType _clutter_root_node_get_type (void) G_GNUC_CONST; +GType _clutter_transform_node_get_type (void) G_GNUC_CONST; +GType _clutter_dummy_node_get_type (void) G_GNUC_CONST; + +void _clutter_paint_operation_paint_rectangle (const ClutterPaintOperation *op); +void _clutter_paint_operation_clip_rectangle (const ClutterPaintOperation *op); +void _clutter_paint_operation_paint_path (const ClutterPaintOperation *op); +void _clutter_paint_operation_clip_path (const ClutterPaintOperation *op); +void _clutter_paint_operation_paint_primitive (const ClutterPaintOperation *op); + +void _clutter_paint_node_init_types (void); +gpointer _clutter_paint_node_create (GType gtype); + +ClutterPaintNode * _clutter_root_node_new (CoglFramebuffer *framebuffer, + const ClutterColor *clear_color, + CoglBufferBit clear_flags); +ClutterPaintNode * _clutter_transform_node_new (const CoglMatrix *matrix); +ClutterPaintNode * _clutter_dummy_node_new (ClutterActor *actor); + +void _clutter_paint_node_paint (ClutterPaintNode *root); +void _clutter_paint_node_dump_tree (ClutterPaintNode *root); + +G_GNUC_INTERNAL +void clutter_paint_node_remove_child (ClutterPaintNode *node, + ClutterPaintNode *child); +G_GNUC_INTERNAL +void clutter_paint_node_replace_child (ClutterPaintNode *node, + ClutterPaintNode *old_child, + ClutterPaintNode *new_child); +G_GNUC_INTERNAL +void clutter_paint_node_remove_all (ClutterPaintNode *node); + +G_GNUC_INTERNAL +guint clutter_paint_node_get_n_children (ClutterPaintNode *node); + +G_GNUC_INTERNAL +ClutterPaintNode * clutter_paint_node_get_first_child (ClutterPaintNode *node); +G_GNUC_INTERNAL +ClutterPaintNode * clutter_paint_node_get_previous_sibling (ClutterPaintNode *node); +G_GNUC_INTERNAL +ClutterPaintNode * clutter_paint_node_get_next_sibling (ClutterPaintNode *node); +G_GNUC_INTERNAL +ClutterPaintNode * clutter_paint_node_get_last_child (ClutterPaintNode *node); +G_GNUC_INTERNAL +ClutterPaintNode * clutter_paint_node_get_parent (ClutterPaintNode *node); +G_GNUC_INTERNAL +CoglFramebuffer * clutter_paint_node_get_framebuffer (ClutterPaintNode *node); + +#define CLUTTER_TYPE_LAYER_NODE (_clutter_layer_node_get_type ()) +#define CLUTTER_LAYER_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_LAYER_NODE, ClutterLayerNode)) +#define CLUTTER_IS_LAYER_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_LAYER_NODE)) + +/* + * ClutterLayerNode: + * + * The #ClutterLayerNode structure is an opaque + * type whose members cannot be directly accessed. + * + * Since: 1.10 + */ +typedef struct _ClutterLayerNode ClutterLayerNode; +typedef struct _ClutterLayerNodeClass ClutterLayerNodeClass; + +GType _clutter_layer_node_get_type (void) G_GNUC_CONST; + +ClutterPaintNode * _clutter_layer_node_new (const CoglMatrix *projection, + const cairo_rectangle_t *viewport, + float width, + float height, + guint8 opacity); + + +G_END_DECLS + +#endif /* __CLUTTER_PAINT_NODE_PRIVATE_H__ */ diff --git a/clutter/clutter/clutter-paint-node.c b/clutter/clutter/clutter-paint-node.c new file mode 100644 index 0000000..391f483 --- /dev/null +++ b/clutter/clutter/clutter-paint-node.c @@ -0,0 +1,1147 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2011 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-paint-node + * @Title: ClutterPaintNode + * @Short_Description: Paint objects + * + * #ClutterPaintNode is an element in the render graph. + * + * The render graph contains all the elements that need to be painted by + * Clutter when submitting a frame to the graphics system. + * + * The render graph is distinct from the scene graph: the scene graph is + * composed by actors, which can be visible or invisible; the scene graph + * elements also respond to events. The render graph, instead, is only + * composed by nodes that will be painted. + * + * Each #ClutterActor can submit multiple #ClutterPaintNodes to + * the render graph. + */ + +/** + * ClutterPaintNode: (ref-func clutter_paint_node_ref) (unref-func clutter_paint_node_unref) (set-value-func clutter_value_set_paint_node) (get-value-func clutter_value_get_paint_node) + * + * The `ClutterPaintNode` structure contains only private data + * and it should be accessed using the provided API. + * + * Since: 1.10 + */ + +/** + * ClutterPaintNodeClass: + * + * The `ClutterPaintNodeClass` structure contains only private data. + * + * Since: 1.10 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#define CLUTTER_ENABLE_EXPERIMENTAL_API + +#include +#include +#include + +#include "clutter-paint-node-private.h" + +#include "clutter-debug.h" +#include "clutter-private.h" + +#include + +static inline void clutter_paint_operation_clear (ClutterPaintOperation *op); + +static void +value_paint_node_init (GValue *value) +{ + value->data[0].v_pointer = NULL; +} + +static void +value_paint_node_free_value (GValue *value) +{ + if (value->data[0].v_pointer != NULL) + clutter_paint_node_unref (value->data[0].v_pointer); +} + +static void +value_paint_node_copy_value (const GValue *src, + GValue *dst) +{ + if (src->data[0].v_pointer != NULL) + dst->data[0].v_pointer = clutter_paint_node_ref (src->data[0].v_pointer); + else + dst->data[0].v_pointer = NULL; +} + +static gpointer +value_paint_node_peek_pointer (const GValue *value) +{ + return value->data[0].v_pointer; +} + +static gchar * +value_paint_node_collect_value (GValue *value, + guint n_collect_values, + GTypeCValue *collect_values, + guint collect_flags) +{ + ClutterPaintNode *node; + + node = collect_values[0].v_pointer; + + if (node == NULL) + { + value->data[0].v_pointer = NULL; + return NULL; + } + + if (node->parent_instance.g_class == NULL) + return g_strconcat ("invalid unclassed ClutterPaintNode pointer for " + "value type '", + G_VALUE_TYPE_NAME (value), + "'", + NULL); + + value->data[0].v_pointer = clutter_paint_node_ref (node); + + return NULL; +} + +static gchar * +value_paint_node_lcopy_value (const GValue *value, + guint n_collect_values, + GTypeCValue *collect_values, + guint collect_flags) +{ + ClutterPaintNode **node_p = collect_values[0].v_pointer; + + if (node_p == NULL) + return g_strconcat ("value location for '", + G_VALUE_TYPE_NAME (value), + "' passed as NULL", + NULL); + + if (value->data[0].v_pointer == NULL) + *node_p = NULL; + else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) + *node_p = value->data[0].v_pointer; + else + *node_p = clutter_paint_node_ref (value->data[0].v_pointer); + + return NULL; +} + +static void +clutter_paint_node_class_base_init (ClutterPaintNodeClass *klass) +{ +} + +static void +clutter_paint_node_class_base_finalize (ClutterPaintNodeClass *klass) +{ +} + +static void +clutter_paint_node_real_finalize (ClutterPaintNode *node) +{ + ClutterPaintNode *iter; + + g_free (node->name); + + if (node->operations != NULL) + { + guint i; + + for (i = 0; i < node->operations->len; i++) + { + ClutterPaintOperation *op; + + op = &g_array_index (node->operations, ClutterPaintOperation, i); + clutter_paint_operation_clear (op); + } + + g_array_unref (node->operations); + } + + iter = node->first_child; + while (iter != NULL) + { + ClutterPaintNode *next = iter->next_sibling; + + clutter_paint_node_remove_child (node, iter); + + iter = next; + } + + g_type_free_instance ((GTypeInstance *) node); +} + +static gboolean +clutter_paint_node_real_pre_draw (ClutterPaintNode *node) +{ + return FALSE; +} + +static void +clutter_paint_node_real_draw (ClutterPaintNode *node) +{ +} + +static void +clutter_paint_node_real_post_draw (ClutterPaintNode *node) +{ +} + +static void +clutter_paint_node_class_init (ClutterPaintNodeClass *klass) +{ + klass->pre_draw = clutter_paint_node_real_pre_draw; + klass->draw = clutter_paint_node_real_draw; + klass->post_draw = clutter_paint_node_real_post_draw; + klass->finalize = clutter_paint_node_real_finalize; +} + +static void +clutter_paint_node_init (ClutterPaintNode *self) +{ + self->ref_count = 1; +} + +GType +clutter_paint_node_get_type (void) +{ + static volatile gsize paint_node_type_id__volatile = 0; + + if (g_once_init_enter (&paint_node_type_id__volatile)) + { + static const GTypeFundamentalInfo finfo = { + (G_TYPE_FLAG_CLASSED | + G_TYPE_FLAG_INSTANTIATABLE | + G_TYPE_FLAG_DERIVABLE | + G_TYPE_FLAG_DEEP_DERIVABLE), + }; + + static const GTypeValueTable value_table = { + value_paint_node_init, + value_paint_node_free_value, + value_paint_node_copy_value, + value_paint_node_peek_pointer, + "p", + value_paint_node_collect_value, + "p", + value_paint_node_lcopy_value, + }; + + const GTypeInfo node_info = { + sizeof (ClutterPaintNodeClass), + + (GBaseInitFunc) clutter_paint_node_class_base_init, + (GBaseFinalizeFunc) clutter_paint_node_class_base_finalize, + (GClassInitFunc) clutter_paint_node_class_init, + (GClassFinalizeFunc) NULL, + NULL, + + sizeof (ClutterPaintNode), + 0, + (GInstanceInitFunc) clutter_paint_node_init, + + &value_table, + }; + + GType paint_node_type_id = + g_type_register_fundamental (g_type_fundamental_next (), + I_("ClutterPaintNode"), + &node_info, &finfo, + G_TYPE_FLAG_ABSTRACT); + + g_once_init_leave (&paint_node_type_id__volatile, paint_node_type_id); + } + + return paint_node_type_id__volatile; +} + +/** + * clutter_paint_node_set_name: + * @node: a #ClutterPaintNode + * @name: a string annotating the @node + * + * Sets a user-readable @name for @node. + * + * The @name will be used for debugging purposes. + * + * The @node will copy the passed string. + * + * Since: 1.10 + */ +void +clutter_paint_node_set_name (ClutterPaintNode *node, + const char *name) +{ + g_return_if_fail (CLUTTER_IS_PAINT_NODE (node)); + + g_free (node->name); + node->name = g_strdup (name); +} + +/** + * clutter_paint_node_ref: + * @node: a #ClutterPaintNode + * + * Acquires a reference on @node. + * + * Return value: (transfer full): the #ClutterPaintNode + * + * Since: 1.10 + */ +ClutterPaintNode * +clutter_paint_node_ref (ClutterPaintNode *node) +{ + g_return_val_if_fail (CLUTTER_IS_PAINT_NODE (node), NULL); + + g_atomic_int_inc (&node->ref_count); + + return node; +} + +/** + * clutter_paint_node_unref: + * @node: a #ClutterPaintNode + * + * Releases a reference on @node. + * + * Since: 1.10 + */ +void +clutter_paint_node_unref (ClutterPaintNode *node) +{ + g_return_if_fail (CLUTTER_IS_PAINT_NODE (node)); + + if (g_atomic_int_dec_and_test (&node->ref_count)) + { + ClutterPaintNodeClass *klass = CLUTTER_PAINT_NODE_GET_CLASS (node); + + klass->finalize (node); + } +} + +/** + * clutter_paint_node_add_child: + * @node: a #ClutterPaintNode + * @child: the child #ClutterPaintNode to add + * + * Adds @child to the list of children of @node. + * + * This function will acquire a reference on @child. + * + * Since: 1.10 + */ +void +clutter_paint_node_add_child (ClutterPaintNode *node, + ClutterPaintNode *child) +{ + g_return_if_fail (CLUTTER_IS_PAINT_NODE (node)); + g_return_if_fail (CLUTTER_IS_PAINT_NODE (child)); + g_return_if_fail (node != child); + g_return_if_fail (child->parent == NULL); + + child->parent = node; + clutter_paint_node_ref (child); + + node->n_children += 1; + + child->prev_sibling = node->last_child; + + if (node->last_child != NULL) + { + ClutterPaintNode *tmp = node->last_child; + + tmp->next_sibling = child; + } + + if (child->prev_sibling == NULL) + node->first_child = child; + + if (child->next_sibling == NULL) + node->last_child = child; +} + +/** + * clutter_paint_node_remove_child: + * @node: a #ClutterPaintNode + * @child: the #ClutterPaintNode to remove + * + * Removes @child from the list of children of @node. + * + * This function will release the reference on @child acquired by + * using clutter_paint_node_add_child(). + * + * Since: 1.10 + */ +void +clutter_paint_node_remove_child (ClutterPaintNode *node, + ClutterPaintNode *child) +{ + ClutterPaintNode *prev, *next; + + g_return_if_fail (CLUTTER_IS_PAINT_NODE (node)); + g_return_if_fail (CLUTTER_IS_PAINT_NODE (child)); + g_return_if_fail (node != child); + g_return_if_fail (child->parent == node); + + node->n_children -= 1; + + prev = child->prev_sibling; + next = child->next_sibling; + + if (prev != NULL) + prev->next_sibling = next; + + if (next != NULL) + next->prev_sibling = prev; + + if (node->first_child == child) + node->first_child = next; + + if (node->last_child == child) + node->last_child = prev; + + child->prev_sibling = NULL; + child->next_sibling = NULL; + child->parent = NULL; + + clutter_paint_node_unref (child); +} + +/** + * clutter_paint_node_replace_child: + * @node: a #ClutterPaintNode + * @old_child: the child replaced by @new_child + * @new_child: the child that replaces @old_child + * + * Atomically replaces @old_child with @new_child in the list of + * children of @node. + * + * This function will release the reference on @old_child acquired + * by @node, and will acquire a new reference on @new_child. + * + * Since: 1.10 + */ +void +clutter_paint_node_replace_child (ClutterPaintNode *node, + ClutterPaintNode *old_child, + ClutterPaintNode *new_child) +{ + ClutterPaintNode *prev, *next; + + g_return_if_fail (CLUTTER_IS_PAINT_NODE (node)); + g_return_if_fail (CLUTTER_IS_PAINT_NODE (old_child)); + g_return_if_fail (old_child->parent == node); + g_return_if_fail (CLUTTER_IS_PAINT_NODE (new_child)); + g_return_if_fail (new_child->parent == NULL); + + prev = old_child->prev_sibling; + next = old_child->next_sibling; + + new_child->parent = node; + new_child->prev_sibling = prev; + new_child->next_sibling = next; + clutter_paint_node_ref (new_child); + + if (prev != NULL) + prev->next_sibling = new_child; + + if (next != NULL) + next->prev_sibling = new_child; + + if (node->first_child == old_child) + node->first_child = new_child; + + if (node->last_child == old_child) + node->last_child = new_child; + + old_child->prev_sibling = NULL; + old_child->next_sibling = NULL; + old_child->parent = NULL; + clutter_paint_node_unref (old_child); +} + +/** + * clutter_paint_node_remove_all: + * @node: a #ClutterPaintNode + * + * Removes all children of @node. + * + * This function releases the reference acquired by @node on its + * children. + * + * Since: 1.10 + */ +void +clutter_paint_node_remove_all (ClutterPaintNode *node) +{ + ClutterPaintNode *iter; + + g_return_if_fail (CLUTTER_IS_PAINT_NODE (node)); + + iter = node->first_child; + while (iter != NULL) + { + ClutterPaintNode *next = iter->next_sibling; + + clutter_paint_node_remove_child (node, iter); + + iter = next; + } +} + +/** + * clutter_paint_node_get_first_child: + * @node: a #ClutterPaintNode + * + * Retrieves the first child of the @node. + * + * Return value: (transfer none): a pointer to the first child of + * the #ClutterPaintNode. + * + * Since: 1.10 + */ +ClutterPaintNode * +clutter_paint_node_get_first_child (ClutterPaintNode *node) +{ + g_return_val_if_fail (CLUTTER_IS_PAINT_NODE (node), NULL); + + return node->first_child; +} + +/** + * clutter_paint_node_get_previous_sibling: + * @node: a #ClutterPaintNode + * + * Retrieves the previous sibling of @node. + * + * Return value: (transfer none): a pointer to the previous sibling + * of the #ClutterPaintNode. + * + * Since: 1.10 + */ +ClutterPaintNode * +clutter_paint_node_get_previous_sibling (ClutterPaintNode *node) +{ + g_return_val_if_fail (CLUTTER_IS_PAINT_NODE (node), NULL); + + return node->prev_sibling; +} + +/** + * clutter_paint_node_get_next_sibling: + * @node: a #ClutterPaintNode + * + * Retrieves the next sibling of @node. + * + * Return value: (transfer none): a pointer to the next sibling + * of a #ClutterPaintNode + * + * Since: 1.10 + */ +ClutterPaintNode * +clutter_paint_node_get_next_sibling (ClutterPaintNode *node) +{ + g_return_val_if_fail (CLUTTER_IS_PAINT_NODE (node), NULL); + + return node->next_sibling; +} + +/** + * clutter_paint_node_get_last_child: + * @node: a #ClutterPaintNode + * + * Retrieves the last child of @node. + * + * Return value: (transfer none): a pointer to the last child + * of a #ClutterPaintNode + * + * Since: 1.10 + */ +ClutterPaintNode * +clutter_paint_node_get_last_child (ClutterPaintNode *node) +{ + g_return_val_if_fail (CLUTTER_IS_PAINT_NODE (node), NULL); + + return node->last_child; +} + +/** + * clutter_paint_node_get_parent: + * @node: a #ClutterPaintNode + * + * Retrieves the parent of @node. + * + * Return value: (transfer none): a pointer to the parent of + * a #ClutterPaintNode + * + * Since: 1.10 + */ +ClutterPaintNode * +clutter_paint_node_get_parent (ClutterPaintNode *node) +{ + g_return_val_if_fail (CLUTTER_IS_PAINT_NODE (node), NULL); + + return node->parent; +} + +/** + * clutter_paint_node_get_n_children: + * @node: a #ClutterPaintNode + * + * Retrieves the number of children of @node. + * + * Return value: the number of children of a #ClutterPaintNode + * + * Since: 1.10 + */ +guint +clutter_paint_node_get_n_children (ClutterPaintNode *node) +{ + g_return_val_if_fail (CLUTTER_IS_PAINT_NODE (node), 0); + + return node->n_children; +} + +/** + * clutter_value_set_paint_node: + * @value: a #GValue initialized with %CLUTTER_TYPE_PAINT_NODE + * @node: (type Clutter.PaintNode) (allow-none): a #ClutterPaintNode, or %NULL + * + * Sets the contents of a #GValue initialized with %CLUTTER_TYPE_PAINT_NODE. + * + * This function increased the reference count of @node; if you do not wish + * to increase the reference count, use clutter_value_take_paint_node() + * instead. The reference count will be released by g_value_unset(). + * + * Since: 1.10 + */ +void +clutter_value_set_paint_node (GValue *value, + gpointer node) +{ + ClutterPaintNode *old_node; + + g_return_if_fail (CLUTTER_VALUE_HOLDS_PAINT_NODE (value)); + + old_node = value->data[0].v_pointer; + + if (node != NULL) + { + g_return_if_fail (CLUTTER_IS_PAINT_NODE (node)); + + value->data[0].v_pointer = clutter_paint_node_ref (node); + } + else + value->data[0].v_pointer = NULL; + + if (old_node != NULL) + clutter_paint_node_unref (old_node); +} + +/** + * clutter_value_take_paint_node: + * @value: a #GValue, initialized with %CLUTTER_TYPE_PAINT_NODE + * @node: (type Clutter.PaintNode) (allow-none): a #ClutterPaintNode, or %NULL + * + * Sets the contents of a #GValue initialized with %CLUTTER_TYPE_PAINT_NODE. + * + * Unlike clutter_value_set_paint_node(), this function will not take a + * reference on the passed @node: instead, it will take ownership of the + * current reference count. + * + * Since: 1.10 + */ +void +clutter_value_take_paint_node (GValue *value, + gpointer node) +{ + ClutterPaintNode *old_node; + + g_return_if_fail (CLUTTER_VALUE_HOLDS_PAINT_NODE (value)); + + old_node = value->data[0].v_pointer; + + if (node != NULL) + { + g_return_if_fail (CLUTTER_IS_PAINT_NODE (node)); + + /* take over ownership */ + value->data[0].v_pointer = node; + } + else + value->data[0].v_pointer = NULL; + + if (old_node != NULL) + clutter_paint_node_unref (old_node); +} + +/** + * clutter_value_get_paint_node: + * @value: a #GValue initialized with %CLUTTER_TYPE_PAINT_NODE + * + * Retrieves a pointer to the #ClutterPaintNode contained inside + * the passed #GValue. + * + * Return value: (transfer none) (type Clutter.PaintNode): a pointer to + * a #ClutterPaintNode, or %NULL + * + * Since: 1.10 + */ +gpointer +clutter_value_get_paint_node (const GValue *value) +{ + g_return_val_if_fail (CLUTTER_VALUE_HOLDS_PAINT_NODE (value), NULL); + + return value->data[0].v_pointer; +} + +/** + * clutter_value_dup_paint_node: + * @value: a #GValue initialized with %CLUTTER_TYPE_PAINT_NODE + * + * Retrieves a pointer to the #ClutterPaintNode contained inside + * the passed #GValue, and if not %NULL it will increase the + * reference count. + * + * Return value: (transfer full) (type Clutter.PaintNode): a pointer + * to the #ClutterPaintNode, with its reference count increased, + * or %NULL + * + * Since: 1.10 + */ +gpointer +clutter_value_dup_paint_node (const GValue *value) +{ + g_return_val_if_fail (CLUTTER_VALUE_HOLDS_PAINT_NODE (value), NULL); + + if (value->data[0].v_pointer != NULL) + return clutter_paint_node_ref (value->data[0].v_pointer); + + return NULL; +} + +static inline void +clutter_paint_operation_clear (ClutterPaintOperation *op) +{ + switch (op->opcode) + { + case PAINT_OP_INVALID: + break; + + case PAINT_OP_TEX_RECT: + break; + + case PAINT_OP_PATH: + if (op->op.path != NULL) + cogl_object_unref (op->op.path); + break; + + case PAINT_OP_PRIMITIVE: + if (op->op.primitive != NULL) + cogl_object_unref (op->op.primitive); + break; + } +} + +static inline void +clutter_paint_op_init_tex_rect (ClutterPaintOperation *op, + const ClutterActorBox *rect, + float x_1, + float y_1, + float x_2, + float y_2) +{ + clutter_paint_operation_clear (op); + + op->opcode = PAINT_OP_TEX_RECT; + op->op.texrect[0] = rect->x1; + op->op.texrect[1] = rect->y1; + op->op.texrect[2] = rect->x2; + op->op.texrect[3] = rect->y2; + op->op.texrect[4] = x_1; + op->op.texrect[5] = y_1; + op->op.texrect[6] = x_2; + op->op.texrect[7] = y_2; +} + +static inline void +clutter_paint_op_init_path (ClutterPaintOperation *op, + CoglPath *path) +{ + clutter_paint_operation_clear (op); + + op->opcode = PAINT_OP_PATH; + op->op.path = cogl_object_ref (path); +} + +static inline void +clutter_paint_op_init_primitive (ClutterPaintOperation *op, + CoglPrimitive *primitive) +{ + clutter_paint_operation_clear (op); + + op->opcode = PAINT_OP_PRIMITIVE; + op->op.primitive = cogl_object_ref (primitive); +} + +static inline void +clutter_paint_node_maybe_init_operations (ClutterPaintNode *node) +{ + if (node->operations != NULL) + return; + + node->operations = + g_array_new (FALSE, FALSE, sizeof (ClutterPaintOperation)); +} + +/** + * clutter_paint_node_add_rectangle: + * @node: a #ClutterPaintNode + * @rect: a #ClutterActorBox + * + * Adds a rectangle region to the @node, as described by the + * passed @rect. + * + * Since: 1.10 + */ +void +clutter_paint_node_add_rectangle (ClutterPaintNode *node, + const ClutterActorBox *rect) +{ + ClutterPaintOperation operation = PAINT_OP_INIT; + + g_return_if_fail (CLUTTER_IS_PAINT_NODE (node)); + g_return_if_fail (rect != NULL); + + clutter_paint_node_maybe_init_operations (node); + + clutter_paint_op_init_tex_rect (&operation, rect, 0.0, 0.0, 1.0, 1.0); + g_array_append_val (node->operations, operation); +} + +/** + * clutter_paint_node_add_texture_rectangle: + * @node: a #ClutterPaintNode + * @rect: a #ClutterActorBox + * @x_1: the left X coordinate of the texture + * @y_1: the top Y coordinate of the texture + * @x_2: the right X coordinate of the texture + * @y_2: the bottom Y coordinate of the texture + * + * Adds a rectangle region to the @node, with texture coordinates. + * + * Since: 1.10 + */ +void +clutter_paint_node_add_texture_rectangle (ClutterPaintNode *node, + const ClutterActorBox *rect, + float x_1, + float y_1, + float x_2, + float y_2) +{ + ClutterPaintOperation operation = PAINT_OP_INIT; + + g_return_if_fail (CLUTTER_IS_PAINT_NODE (node)); + g_return_if_fail (rect != NULL); + + clutter_paint_node_maybe_init_operations (node); + + clutter_paint_op_init_tex_rect (&operation, rect, x_1, y_1, x_2, y_2); + g_array_append_val (node->operations, operation); +} + +/** + * clutter_paint_node_add_path: (skip) + * @node: a #ClutterPaintNode + * @path: a Cogl path + * + * Adds a region described as a path to the @node. + * + * This function acquires a reference on the passed @path, so it + * is safe to call cogl_object_unref() when it returns. + * + * Since: 1.10 + * Stability: unstable + */ +void +clutter_paint_node_add_path (ClutterPaintNode *node, + CoglPath *path) +{ + ClutterPaintOperation operation = PAINT_OP_INIT; + + g_return_if_fail (CLUTTER_IS_PAINT_NODE (node)); + g_return_if_fail (cogl_is_path (path)); + + clutter_paint_node_maybe_init_operations (node); + + clutter_paint_op_init_path (&operation, path); + g_array_append_val (node->operations, operation); +} + +/** + * clutter_paint_node_add_primitive: (skip) + * @node: a #ClutterPaintNode + * @primitive: a Cogl primitive + * + * Adds a region described by a Cogl primitive to the @node. + * + * This function acquires a reference on @primitive, so it is safe + * to call cogl_object_unref() when it returns. + * + * Since: 1.10 + */ +void +clutter_paint_node_add_primitive (ClutterPaintNode *node, + CoglPrimitive *primitive) +{ + ClutterPaintOperation operation = PAINT_OP_INIT; + + g_return_if_fail (CLUTTER_IS_PAINT_NODE (node)); + g_return_if_fail (cogl_is_primitive (primitive)); + + clutter_paint_node_maybe_init_operations (node); + + clutter_paint_op_init_primitive (&operation, primitive); + g_array_append_val (node->operations, operation); +} + +/*< private > + * _clutter_paint_node_paint: + * @node: a #ClutterPaintNode + * + * Paints the @node using the class implementation, traversing + * its children, if any. + */ +void +_clutter_paint_node_paint (ClutterPaintNode *node) +{ + ClutterPaintNodeClass *klass = CLUTTER_PAINT_NODE_GET_CLASS (node); + ClutterPaintNode *iter; + gboolean res; + + res = klass->pre_draw (node); + + if (res) + { + klass->draw (node); + } + + for (iter = node->first_child; + iter != NULL; + iter = iter->next_sibling) + { + _clutter_paint_node_paint (iter); + } + + if (res) + { + klass->post_draw (node); + } +} + +#ifdef CLUTTER_ENABLE_DEBUG +static JsonNode * +clutter_paint_node_serialize (ClutterPaintNode *node) +{ + ClutterPaintNodeClass *klass = CLUTTER_PAINT_NODE_GET_CLASS (node); + + if (klass->serialize != NULL) + return klass->serialize (node); + + return json_node_new (JSON_NODE_NULL); +} + +static JsonNode * +clutter_paint_node_to_json (ClutterPaintNode *node) +{ + JsonBuilder *builder; + JsonNode *res; + + builder = json_builder_new (); + + json_builder_begin_object (builder); + + json_builder_set_member_name (builder, "type"); + json_builder_add_string_value (builder, g_type_name (G_TYPE_FROM_INSTANCE (node))); + + json_builder_set_member_name (builder, "name"); + json_builder_add_string_value (builder, node->name); + + json_builder_set_member_name (builder, "node-data"); + json_builder_add_value (builder, clutter_paint_node_serialize (node)); + + json_builder_set_member_name (builder, "operations"); + json_builder_begin_array (builder); + + if (node->operations != NULL) + { + guint i; + + for (i = 0; i < node->operations->len; i++) + { + const ClutterPaintOperation *op; + + op = &g_array_index (node->operations, ClutterPaintOperation, i); + json_builder_begin_object (builder); + + switch (op->opcode) + { + case PAINT_OP_TEX_RECT: + json_builder_set_member_name (builder, "texrect"); + json_builder_begin_array (builder); + json_builder_add_double_value (builder, op->op.texrect[0]); + json_builder_add_double_value (builder, op->op.texrect[1]); + json_builder_add_double_value (builder, op->op.texrect[2]); + json_builder_add_double_value (builder, op->op.texrect[3]); + json_builder_add_double_value (builder, op->op.texrect[4]); + json_builder_add_double_value (builder, op->op.texrect[5]); + json_builder_add_double_value (builder, op->op.texrect[6]); + json_builder_add_double_value (builder, op->op.texrect[7]); + json_builder_end_array (builder); + break; + + case PAINT_OP_PATH: + json_builder_set_member_name (builder, "path"); + json_builder_add_int_value (builder, (gint64) op->op.path); + break; + + case PAINT_OP_PRIMITIVE: + json_builder_set_member_name (builder, "primitive"); + json_builder_add_int_value (builder, (gint64) op->op.primitive); + break; + + case PAINT_OP_INVALID: + break; + } + + json_builder_end_object (builder); + } + } + + json_builder_end_array (builder); + + json_builder_set_member_name (builder, "children"); + json_builder_begin_array (builder); + + if (node->first_child != NULL) + { + ClutterPaintNode *child; + + for (child = node->first_child; + child != NULL; + child = child->next_sibling) + { + JsonNode *n = clutter_paint_node_to_json (child); + + json_builder_add_value (builder, n); + } + } + + json_builder_end_array (builder); + + json_builder_end_object (builder); + + res = json_builder_get_root (builder); + + g_object_unref (builder); + + return res; +} +#endif /* CLUTTER_ENABLE_DEBUG */ + +void +_clutter_paint_node_dump_tree (ClutterPaintNode *node) +{ +#ifdef CLUTTER_ENABLE_DEBUG + JsonGenerator *gen = json_generator_new (); + char *str; + gsize len; + + json_generator_set_root (gen, clutter_paint_node_to_json (node)); + str = json_generator_to_data (gen, &len); + + g_print ("Render tree starting from %p:\n%s\n", node, str); + + g_free (str); +#endif /* CLUTTER_ENABLE_DEBUG */ +} + +/*< private > + * _clutter_paint_node_create: + * @gtype: a #ClutterPaintNode type + * + * Creates a new #ClutterPaintNode instance using @gtype + * + * Return value: (transfer full): the newly created #ClutterPaintNode + * sub-class instance; use clutter_paint_node_unref() when done + */ +gpointer +_clutter_paint_node_create (GType gtype) +{ + g_return_val_if_fail (g_type_is_a (gtype, CLUTTER_TYPE_PAINT_NODE), NULL); + + _clutter_paint_node_init_types (); + + return (gpointer) g_type_create_instance (gtype); +} + +static ClutterPaintNode * +clutter_paint_node_get_root (ClutterPaintNode *node) +{ + ClutterPaintNode *iter; + + iter = node; + while (iter != NULL && iter->parent != NULL) + iter = iter->parent; + + return iter; +} + +CoglFramebuffer * +clutter_paint_node_get_framebuffer (ClutterPaintNode *node) +{ + ClutterPaintNode *root = clutter_paint_node_get_root (node); + ClutterPaintNodeClass *klass; + + if (root == NULL) + return NULL; + + klass = CLUTTER_PAINT_NODE_GET_CLASS (root); + if (klass->get_framebuffer != NULL) + return klass->get_framebuffer (root); + + return cogl_get_draw_framebuffer (); +} diff --git a/clutter/clutter/clutter-paint-node.h b/clutter/clutter/clutter-paint-node.h new file mode 100644 index 0000000..5f3e962 --- /dev/null +++ b/clutter/clutter/clutter-paint-node.h @@ -0,0 +1,101 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2011 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_PAINT_NODE_H__ +#define __CLUTTER_PAINT_NODE_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_PAINT_NODE (clutter_paint_node_get_type ()) +#define CLUTTER_PAINT_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_PAINT_NODE, ClutterPaintNode)) +#define CLUTTER_IS_PAINT_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_PAINT_NODE)) + +typedef struct _ClutterPaintNodePrivate ClutterPaintNodePrivate; +typedef struct _ClutterPaintNodeClass ClutterPaintNodeClass; + +CLUTTER_AVAILABLE_IN_1_10 +GType clutter_paint_node_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_10 +ClutterPaintNode * clutter_paint_node_ref (ClutterPaintNode *node); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_paint_node_unref (ClutterPaintNode *node); + +CLUTTER_AVAILABLE_IN_1_10 +void clutter_paint_node_set_name (ClutterPaintNode *node, + const char *name); + +CLUTTER_AVAILABLE_IN_1_10 +void clutter_paint_node_add_child (ClutterPaintNode *node, + ClutterPaintNode *child); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_paint_node_add_rectangle (ClutterPaintNode *node, + const ClutterActorBox *rect); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_paint_node_add_texture_rectangle (ClutterPaintNode *node, + const ClutterActorBox *rect, + float x_1, + float y_1, + float x_2, + float y_2); + +CLUTTER_AVAILABLE_IN_1_10 +void clutter_paint_node_add_path (ClutterPaintNode *node, + CoglPath *path); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_paint_node_add_primitive (ClutterPaintNode *node, + CoglPrimitive *primitive); + +/** + * CLUTTER_VALUE_HOLDS_PAINT_NODE: + * @value: a #GValue + * + * Evaluates to %TRUE if the @value has been initialized to hold + * a #ClutterPaintNode. + * + * Since: 1.10 + */ +#define CLUTTER_VALUE_HOLDS_PAINT_NODE(value) (G_VALUE_HOLDS (value, CLUTTER_TYPE_PAINT_NODE)) + +CLUTTER_AVAILABLE_IN_1_10 +void clutter_value_set_paint_node (GValue *value, + gpointer node); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_value_take_paint_node (GValue *value, + gpointer node); +CLUTTER_AVAILABLE_IN_1_10 +gpointer clutter_value_get_paint_node (const GValue *value); +CLUTTER_AVAILABLE_IN_1_10 +gpointer clutter_value_dup_paint_node (const GValue *value); + +G_END_DECLS + +#endif /* __CLUTTER_PAINT_NODE_H__ */ diff --git a/clutter/clutter/clutter-paint-nodes.c b/clutter/clutter/clutter-paint-nodes.c new file mode 100644 index 0000000..3870ba6 --- /dev/null +++ b/clutter/clutter/clutter-paint-nodes.c @@ -0,0 +1,1299 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2011 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-paint-nodes + * @Title: Paint Nodes + * @Short_Description: ClutterPaintNode implementations + * + * Clutter provides a set of predefined #ClutterPaintNode implementations + * that cover all the state changes available. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#define CLUTTER_ENABLE_EXPERIMENTAL_API + +#include "clutter-paint-node-private.h" + +#include +#include + +#include "clutter-actor-private.h" +#include "clutter-color.h" +#include "clutter-debug.h" +#include "clutter-private.h" + +#include "clutter-paint-nodes.h" + +static CoglPipeline *default_color_pipeline = NULL; +static CoglPipeline *default_texture_pipeline = NULL; + +/*< private > + * _clutter_paint_node_init_types: + * + * Initializes the required types for ClutterPaintNode subclasses + */ +void +_clutter_paint_node_init_types (void) +{ + CoglContext *ctx; + CoglColor cogl_color; + GType node_type G_GNUC_UNUSED; + + if (G_LIKELY (default_color_pipeline != NULL)) + return; + + ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); + + node_type = clutter_paint_node_get_type (); + + cogl_color_init_from_4f (&cogl_color, 1.0, 1.0, 1.0, 1.0); + + default_color_pipeline = cogl_pipeline_new (ctx); + cogl_pipeline_set_color (default_color_pipeline, &cogl_color); + + default_texture_pipeline = cogl_pipeline_new (ctx); + cogl_pipeline_set_layer_null_texture (default_texture_pipeline, 0, + COGL_TEXTURE_TYPE_2D); + cogl_pipeline_set_color (default_texture_pipeline, &cogl_color); + cogl_pipeline_set_layer_wrap_mode (default_texture_pipeline, 0, + COGL_PIPELINE_WRAP_MODE_AUTOMATIC); +} + +/* + * Root node, private + * + * any frame can only have a since RootNode instance for each + * top-level actor. + */ + +#define clutter_root_node_get_type _clutter_root_node_get_type + +typedef struct _ClutterRootNode ClutterRootNode; +typedef struct _ClutterPaintNodeClass ClutterRootNodeClass; + +struct _ClutterRootNode +{ + ClutterPaintNode parent_instance; + + CoglFramebuffer *framebuffer; + + CoglBufferBit clear_flags; + CoglColor clear_color; +}; + +G_DEFINE_TYPE (ClutterRootNode, clutter_root_node, CLUTTER_TYPE_PAINT_NODE) + +static gboolean +clutter_root_node_pre_draw (ClutterPaintNode *node) +{ + ClutterRootNode *rnode = (ClutterRootNode *) node; + + cogl_framebuffer_clear (rnode->framebuffer, + rnode->clear_flags, + &rnode->clear_color); + + return TRUE; +} + +static void +clutter_root_node_post_draw (ClutterPaintNode *node) +{ +} + +static void +clutter_root_node_finalize (ClutterPaintNode *node) +{ + ClutterRootNode *rnode = (ClutterRootNode *) node; + + cogl_object_unref (rnode->framebuffer); + + CLUTTER_PAINT_NODE_CLASS (clutter_root_node_parent_class)->finalize (node); +} + +static CoglFramebuffer * +clutter_root_node_get_framebuffer (ClutterPaintNode *node) +{ + ClutterRootNode *rnode = (ClutterRootNode *) node; + + return rnode->framebuffer; +} + +static void +clutter_root_node_class_init (ClutterRootNodeClass *klass) +{ + ClutterPaintNodeClass *node_class = CLUTTER_PAINT_NODE_CLASS (klass); + + node_class->pre_draw = clutter_root_node_pre_draw; + node_class->post_draw = clutter_root_node_post_draw; + node_class->finalize = clutter_root_node_finalize; + node_class->get_framebuffer = clutter_root_node_get_framebuffer; +} + +static void +clutter_root_node_init (ClutterRootNode *self) +{ +} + +ClutterPaintNode * +_clutter_root_node_new (CoglFramebuffer *framebuffer, + const ClutterColor *clear_color, + CoglBufferBit clear_flags) +{ + ClutterRootNode *res; + + res = _clutter_paint_node_create (_clutter_root_node_get_type ()); + + cogl_color_init_from_4ub (&res->clear_color, + clear_color->red, + clear_color->green, + clear_color->blue, + clear_color->alpha); + cogl_color_premultiply (&res->clear_color); + + if (G_LIKELY (framebuffer != NULL)) + res->framebuffer = cogl_object_ref (framebuffer); + else + res->framebuffer = cogl_object_ref (cogl_get_draw_framebuffer ()); + + res->clear_flags = clear_flags; + + return (ClutterPaintNode *) res; +} + +/* + * Transform node + * + * A private PaintNode, that changes the modelview of its child + * nodes. + */ + +#define clutter_transform_node_get_type _clutter_transform_node_get_type + +typedef struct _ClutterTransformNode { + ClutterPaintNode parent_instance; + + CoglMatrix modelview; +} ClutterTransformNode; + +typedef struct _ClutterPaintNodeClass ClutterTransformNodeClass; + +G_DEFINE_TYPE (ClutterTransformNode, clutter_transform_node, CLUTTER_TYPE_PAINT_NODE) + +static gboolean +clutter_transform_node_pre_draw (ClutterPaintNode *node) +{ + ClutterTransformNode *tnode = (ClutterTransformNode *) node; + CoglMatrix matrix; + + cogl_push_matrix (); + + cogl_get_modelview_matrix (&matrix); + cogl_matrix_multiply (&matrix, &matrix, &tnode->modelview); + cogl_set_modelview_matrix (&matrix); + + return TRUE; +} + +static void +clutter_transform_node_post_draw (ClutterPaintNode *node) +{ + cogl_pop_matrix (); +} + +static void +clutter_transform_node_class_init (ClutterTransformNodeClass *klass) +{ + ClutterPaintNodeClass *node_class; + + node_class = CLUTTER_PAINT_NODE_CLASS (klass); + node_class->pre_draw = clutter_transform_node_pre_draw; + node_class->post_draw = clutter_transform_node_post_draw; +} + +static void +clutter_transform_node_init (ClutterTransformNode *self) +{ + cogl_matrix_init_identity (&self->modelview); +} + +ClutterPaintNode * +_clutter_transform_node_new (const CoglMatrix *modelview) +{ + ClutterTransformNode *res; + + res = _clutter_paint_node_create (_clutter_transform_node_get_type ()); + + if (modelview != NULL) + res->modelview = *modelview; + + return (ClutterPaintNode *) res; +} + +/* + * Dummy node, private + * + * an empty node, used temporarily until we can drop API compatibility, + * and we'll be able to build a full render tree for each frame. + */ + +#define clutter_dummy_node_get_type _clutter_dummy_node_get_type + +typedef struct _ClutterDummyNode ClutterDummyNode; +typedef struct _ClutterPaintNodeClass ClutterDummyNodeClass; + +struct _ClutterDummyNode +{ + ClutterPaintNode parent_instance; + + ClutterActor *actor; + CoglFramebuffer *framebuffer; +}; + +G_DEFINE_TYPE (ClutterDummyNode, clutter_dummy_node, CLUTTER_TYPE_PAINT_NODE) + +static gboolean +clutter_dummy_node_pre_draw (ClutterPaintNode *node) +{ + return TRUE; +} + +static JsonNode * +clutter_dummy_node_serialize (ClutterPaintNode *node) +{ + ClutterDummyNode *dnode = (ClutterDummyNode *) node; + JsonBuilder *builder; + JsonNode *res; + + if (dnode->actor == NULL) + return json_node_new (JSON_NODE_NULL); + + builder = json_builder_new (); + json_builder_begin_object (builder); + + json_builder_set_member_name (builder, "actor"); + json_builder_add_string_value (builder, _clutter_actor_get_debug_name (dnode->actor)); + + json_builder_end_object (builder); + + res = json_builder_get_root (builder); + g_object_unref (builder); + + return res; +} + +static CoglFramebuffer * +clutter_dummy_node_get_framebuffer (ClutterPaintNode *node) +{ + ClutterDummyNode *dnode = (ClutterDummyNode *) node; + + return dnode->framebuffer; +} + +static void +clutter_dummy_node_class_init (ClutterDummyNodeClass *klass) +{ + ClutterPaintNodeClass *node_class = CLUTTER_PAINT_NODE_CLASS (klass); + + node_class->pre_draw = clutter_dummy_node_pre_draw; + node_class->serialize = clutter_dummy_node_serialize; + node_class->get_framebuffer = clutter_dummy_node_get_framebuffer; +} + +static void +clutter_dummy_node_init (ClutterDummyNode *self) +{ +} + +ClutterPaintNode * +_clutter_dummy_node_new (ClutterActor *actor) +{ + ClutterPaintNode *res; + ClutterDummyNode *dnode; + + res = _clutter_paint_node_create (_clutter_dummy_node_get_type ()); + + dnode = (ClutterDummyNode *) res; + dnode->actor = actor; + dnode->framebuffer = _clutter_actor_get_active_framebuffer (actor); + + return res; +} + +/* + * Pipeline node + */ + +struct _ClutterPipelineNode +{ + ClutterPaintNode parent_instance; + + CoglPipeline *pipeline; +}; + +/** + * ClutterPipelineNodeClass: + * + * The `ClutterPipelineNodeClass` structure is an opaque + * type whose members cannot be directly accessed. + * + * Since: 1.10 + */ +struct _ClutterPipelineNodeClass +{ + ClutterPaintNodeClass parent_class; +}; + +G_DEFINE_TYPE (ClutterPipelineNode, clutter_pipeline_node, CLUTTER_TYPE_PAINT_NODE) + +static void +clutter_pipeline_node_finalize (ClutterPaintNode *node) +{ + ClutterPipelineNode *pnode = CLUTTER_PIPELINE_NODE (node); + + if (pnode->pipeline != NULL) + cogl_object_unref (pnode->pipeline); + + CLUTTER_PAINT_NODE_CLASS (clutter_pipeline_node_parent_class)->finalize (node); +} + +static gboolean +clutter_pipeline_node_pre_draw (ClutterPaintNode *node) +{ + ClutterPipelineNode *pnode = CLUTTER_PIPELINE_NODE (node); + + if (node->operations != NULL && + pnode->pipeline != NULL) + { + cogl_push_source (pnode->pipeline); + return TRUE; + } + + return FALSE; +} + +static void +clutter_pipeline_node_draw (ClutterPaintNode *node) +{ + ClutterPipelineNode *pnode = CLUTTER_PIPELINE_NODE (node); + CoglFramebuffer *fb; + guint i; + + if (pnode->pipeline == NULL) + return; + + if (node->operations == NULL) + return; + + fb = clutter_paint_node_get_framebuffer (node); + + for (i = 0; i < node->operations->len; i++) + { + const ClutterPaintOperation *op; + + op = &g_array_index (node->operations, ClutterPaintOperation, i); + + switch (op->opcode) + { + case PAINT_OP_INVALID: + break; + + case PAINT_OP_TEX_RECT: + cogl_rectangle_with_texture_coords (op->op.texrect[0], + op->op.texrect[1], + op->op.texrect[2], + op->op.texrect[3], + op->op.texrect[4], + op->op.texrect[5], + op->op.texrect[6], + op->op.texrect[7]); + break; + + case PAINT_OP_PATH: + cogl_path_fill (op->op.path); + break; + + case PAINT_OP_PRIMITIVE: + cogl_framebuffer_draw_primitive (fb, + pnode->pipeline, + op->op.primitive); + break; + } + } +} + +static void +clutter_pipeline_node_post_draw (ClutterPaintNode *node) +{ + cogl_pop_source (); +} + +static JsonNode * +clutter_pipeline_node_serialize (ClutterPaintNode *node) +{ + ClutterPipelineNode *pnode = CLUTTER_PIPELINE_NODE (node); + JsonBuilder *builder; + CoglColor color; + JsonNode *res; + + if (pnode->pipeline == NULL) + return json_node_new (JSON_NODE_NULL); + + builder = json_builder_new (); + json_builder_begin_object (builder); + + cogl_pipeline_get_color (pnode->pipeline, &color); + json_builder_set_member_name (builder, "color"); + json_builder_begin_array (builder); + json_builder_add_double_value (builder, cogl_color_get_red (&color)); + json_builder_add_double_value (builder, cogl_color_get_green (&color)); + json_builder_add_double_value (builder, cogl_color_get_blue (&color)); + json_builder_add_double_value (builder, cogl_color_get_alpha (&color)); + json_builder_end_array (builder); + +#if 0 + json_builder_set_member_name (builder, "layers"); + json_builder_begin_array (builder); + cogl_pipeline_foreach_layer (pnode->pipeline, + clutter_pipeline_node_serialize_layer, + builder); + json_builder_end_array (builder); +#endif + + json_builder_end_object (builder); + + res = json_builder_get_root (builder); + g_object_unref (builder); + + return res; +} + +static void +clutter_pipeline_node_class_init (ClutterPipelineNodeClass *klass) +{ + ClutterPaintNodeClass *node_class; + + node_class = CLUTTER_PAINT_NODE_CLASS (klass); + node_class->pre_draw = clutter_pipeline_node_pre_draw; + node_class->draw = clutter_pipeline_node_draw; + node_class->post_draw = clutter_pipeline_node_post_draw; + node_class->finalize = clutter_pipeline_node_finalize; + node_class->serialize = clutter_pipeline_node_serialize; +} + +static void +clutter_pipeline_node_init (ClutterPipelineNode *self) +{ +} + +/** + * clutter_pipeline_node_new: (skip) + * @pipeline: (allow-none): a Cogl pipeline state object, or %NULL + * + * Creates a new #ClutterPaintNode that will use the @pipeline to + * paint its contents. + * + * This function will acquire a reference on the passed @pipeline, + * so it is safe to call cogl_object_unref() when it returns. + * + * Return value: (transfer full): the newly created #ClutterPaintNode. + * Use clutter_paint_node_unref() when done. + * + * Since: 1.10 + */ +ClutterPaintNode * +clutter_pipeline_node_new (CoglPipeline *pipeline) +{ + ClutterPipelineNode *res; + + g_return_val_if_fail (pipeline == NULL || cogl_is_pipeline (pipeline), NULL); + + res = _clutter_paint_node_create (CLUTTER_TYPE_PIPELINE_NODE); + + if (pipeline != NULL) + res->pipeline = cogl_object_ref (pipeline); + + return (ClutterPaintNode *) res; +} + +/* + * Color node + */ + +struct _ClutterColorNode +{ + ClutterPipelineNode parent_instance; +}; + +/** + * ClutterColorNodeClass: + * + * The `ClutterColorNodeClass` structure is an + * opaque type whose members cannot be directly accessed. + * + * Since: 1.10 + */ +struct _ClutterColorNodeClass +{ + ClutterPipelineNodeClass parent_class; +}; + +G_DEFINE_TYPE (ClutterColorNode, clutter_color_node, CLUTTER_TYPE_PIPELINE_NODE) + +static void +clutter_color_node_class_init (ClutterColorNodeClass *klass) +{ + +} + +static void +clutter_color_node_init (ClutterColorNode *cnode) +{ + ClutterPipelineNode *pnode = CLUTTER_PIPELINE_NODE (cnode); + + g_assert (default_color_pipeline != NULL); + pnode->pipeline = cogl_pipeline_copy (default_color_pipeline); +} + +/** + * clutter_color_node_new: + * @color: (allow-none): the color to paint, or %NULL + * + * Creates a new #ClutterPaintNode that will paint a solid color + * fill using @color. + * + * Return value: (transfer full): the newly created #ClutterPaintNode. Use + * clutter_paint_node_unref() when done + * + * Since: 1.10 + */ +ClutterPaintNode * +clutter_color_node_new (const ClutterColor *color) +{ + ClutterPipelineNode *cnode; + + cnode = _clutter_paint_node_create (CLUTTER_TYPE_COLOR_NODE); + + if (color != NULL) + { + CoglColor cogl_color; + + cogl_color_init_from_4ub (&cogl_color, + color->red, + color->green, + color->blue, + color->alpha); + cogl_color_premultiply (&cogl_color); + + cogl_pipeline_set_color (cnode->pipeline, &cogl_color); + } + + return (ClutterPaintNode *) cnode; +} + +/* + * Texture node + */ + +struct _ClutterTextureNode +{ + ClutterPipelineNode parent_instance; +}; + +/** + * ClutterTextureNodeClass: + * + * The `ClutterTextureNodeClass` structure is an + * opaque type whose members cannot be directly accessed. + * + * Since: 1.10 + */ +struct _ClutterTextureNodeClass +{ + ClutterPipelineNodeClass parent_class; +}; + +G_DEFINE_TYPE (ClutterTextureNode, clutter_texture_node, CLUTTER_TYPE_PIPELINE_NODE) + +static void +clutter_texture_node_class_init (ClutterTextureNodeClass *klass) +{ +} + +static void +clutter_texture_node_init (ClutterTextureNode *self) +{ + ClutterPipelineNode *pnode = CLUTTER_PIPELINE_NODE (self); + + g_assert (default_texture_pipeline != NULL); + pnode->pipeline = cogl_pipeline_copy (default_texture_pipeline); +} + +static CoglPipelineFilter +clutter_scaling_filter_to_cogl_pipeline_filter (ClutterScalingFilter filter) +{ + switch (filter) + { + case CLUTTER_SCALING_FILTER_NEAREST: + return COGL_PIPELINE_FILTER_NEAREST; + + case CLUTTER_SCALING_FILTER_LINEAR: + return COGL_PIPELINE_FILTER_LINEAR; + + case CLUTTER_SCALING_FILTER_TRILINEAR: + return COGL_PIPELINE_FILTER_LINEAR_MIPMAP_LINEAR; + } + + return COGL_PIPELINE_FILTER_LINEAR; +} + +/** + * clutter_texture_node_new: + * @texture: a #CoglTexture + * @color: (allow-none): a #ClutterColor used for blending, or %NULL + * @min_filter: the minification filter for the texture + * @mag_filter: the magnification filter for the texture + * + * Creates a new #ClutterPaintNode that will paint the passed @texture. + * + * This function will take a reference on @texture, so it is safe to + * call cogl_object_unref() on @texture when it returns. + * + * The @color must not be pre-multiplied with its #ClutterColor.alpha + * channel value; if @color is %NULL, a fully opaque white color will + * be used for blending. + * + * Return value: (transfer full): the newly created #ClutterPaintNode. + * Use clutter_paint_node_unref() when done + * + * Since: 1.10 + */ +ClutterPaintNode * +clutter_texture_node_new (CoglTexture *texture, + const ClutterColor *color, + ClutterScalingFilter min_filter, + ClutterScalingFilter mag_filter) +{ + ClutterPipelineNode *tnode; + CoglColor cogl_color; + CoglPipelineFilter min_f, mag_f; + + g_return_val_if_fail (cogl_is_texture (texture), NULL); + + tnode = _clutter_paint_node_create (CLUTTER_TYPE_TEXTURE_NODE); + + cogl_pipeline_set_layer_texture (tnode->pipeline, 0, texture); + + min_f = clutter_scaling_filter_to_cogl_pipeline_filter (min_filter); + mag_f = clutter_scaling_filter_to_cogl_pipeline_filter (mag_filter); + cogl_pipeline_set_layer_filters (tnode->pipeline, 0, min_f, mag_f); + + if (color != NULL) + { + cogl_color_init_from_4ub (&cogl_color, + color->red, + color->green, + color->blue, + color->alpha); + cogl_color_premultiply (&cogl_color); + } + else + cogl_color_init_from_4ub (&cogl_color, 255, 255, 255, 255); + + cogl_pipeline_set_color (tnode->pipeline, &cogl_color); + + return (ClutterPaintNode *) tnode; +} + +/* + * Text node + */ + +struct _ClutterTextNode +{ + ClutterPaintNode parent_instance; + + PangoLayout *layout; + CoglColor color; +}; + +/** + * ClutterTextNodeClass: + * + * The `ClutterTextNodeClass` structure is an opaque + * type whose contents cannot be directly accessed. + * + * Since: 1.10 + */ +struct _ClutterTextNodeClass +{ + ClutterPaintNodeClass parent_class; +}; + +G_DEFINE_TYPE (ClutterTextNode, clutter_text_node, CLUTTER_TYPE_PAINT_NODE) + +static void +clutter_text_node_finalize (ClutterPaintNode *node) +{ + ClutterTextNode *tnode = CLUTTER_TEXT_NODE (node); + + if (tnode->layout != NULL) + g_object_unref (tnode->layout); + + CLUTTER_PAINT_NODE_CLASS (clutter_text_node_parent_class)->finalize (node); +} + +static gboolean +clutter_text_node_pre_draw (ClutterPaintNode *node) +{ + ClutterTextNode *tnode = CLUTTER_TEXT_NODE (node); + + return tnode->layout != NULL; +} + +static void +clutter_text_node_draw (ClutterPaintNode *node) +{ + ClutterTextNode *tnode = CLUTTER_TEXT_NODE (node); + PangoRectangle extents; + CoglFramebuffer *fb; + guint i; + + if (node->operations == NULL) + return; + + fb = clutter_paint_node_get_framebuffer (node); + + pango_layout_get_pixel_extents (tnode->layout, NULL, &extents); + + for (i = 0; i < node->operations->len; i++) + { + const ClutterPaintOperation *op; + float op_width, op_height; + gboolean clipped = FALSE; + + op = &g_array_index (node->operations, ClutterPaintOperation, i); + + switch (op->opcode) + { + case PAINT_OP_TEX_RECT: + op_width = op->op.texrect[2] - op->op.texrect[0]; + op_height = op->op.texrect[3] - op->op.texrect[1]; + + /* if the primitive size was smaller than the layout, + * we clip the layout when drawin, to avoid spilling + * it out + */ + if (extents.width > op_width || + extents.height > op_height) + { + cogl_framebuffer_push_rectangle_clip (fb, + op->op.texrect[0], + op->op.texrect[1], + op->op.texrect[2], + op->op.texrect[3]); + clipped = TRUE; + } + + cogl_pango_render_layout (tnode->layout, + op->op.texrect[0], + op->op.texrect[1], + &tnode->color, + 0); + + if (clipped) + cogl_framebuffer_pop_clip (fb); + break; + + case PAINT_OP_PATH: + case PAINT_OP_PRIMITIVE: + case PAINT_OP_INVALID: + break; + } + } +} + +static JsonNode * +clutter_text_node_serialize (ClutterPaintNode *node) +{ + ClutterTextNode *tnode = CLUTTER_TEXT_NODE (node); + JsonBuilder *builder; + JsonNode *res; + + builder = json_builder_new (); + + json_builder_begin_object (builder); + + json_builder_set_member_name (builder, "layout"); + + if (pango_layout_get_character_count (tnode->layout) > 12) + { + const char *text = pango_layout_get_text (tnode->layout); + char *str; + + str = g_strndup (text, 12); + json_builder_add_string_value (builder, str); + g_free (str); + } + else + json_builder_add_string_value (builder, pango_layout_get_text (tnode->layout)); + + json_builder_set_member_name (builder, "color"); + json_builder_begin_array (builder); + json_builder_add_double_value (builder, cogl_color_get_red (&tnode->color)); + json_builder_add_double_value (builder, cogl_color_get_green (&tnode->color)); + json_builder_add_double_value (builder, cogl_color_get_blue (&tnode->color)); + json_builder_add_double_value (builder, cogl_color_get_alpha (&tnode->color)); + json_builder_end_array (builder); + + json_builder_end_object (builder); + + res = json_builder_get_root (builder); + g_object_unref (builder); + + return res; +} + +static void +clutter_text_node_class_init (ClutterTextNodeClass *klass) +{ + ClutterPaintNodeClass *node_class = CLUTTER_PAINT_NODE_CLASS (klass); + + node_class->pre_draw = clutter_text_node_pre_draw; + node_class->draw = clutter_text_node_draw; + node_class->finalize = clutter_text_node_finalize; + node_class->serialize = clutter_text_node_serialize; +} + +static void +clutter_text_node_init (ClutterTextNode *self) +{ + cogl_color_init_from_4f (&self->color, 0.0, 0.0, 0.0, 1.0); +} + +/** + * clutter_text_node_new: + * @layout: (allow-none): a #PangoLayout, or %NULL + * @color: (allow-none): the color used to paint the layout, + * or %NULL + * + * Creates a new #ClutterPaintNode that will paint a #PangoLayout + * with the given color. + * + * This function takes a reference on the passed @layout, so it + * is safe to call g_object_unref() after it returns. + * + * Return value: (transfer full): the newly created #ClutterPaintNode. + * Use clutter_paint_node_unref() when done + * + * Since: 1.10 + */ +ClutterPaintNode * +clutter_text_node_new (PangoLayout *layout, + const ClutterColor *color) +{ + ClutterTextNode *res; + + g_return_val_if_fail (layout == NULL || PANGO_IS_LAYOUT (layout), NULL); + + res = _clutter_paint_node_create (CLUTTER_TYPE_TEXT_NODE); + + if (layout != NULL) + res->layout = g_object_ref (layout); + + if (color != NULL) + { + cogl_color_init_from_4ub (&res->color, + color->red, + color->green, + color->blue, + color->alpha); + } + + return (ClutterPaintNode *) res; +} + +/* + * Clip node + */ +struct _ClutterClipNode +{ + ClutterPaintNode parent_instance; +}; + +/** + * ClutterClipNodeClass: + * + * The `ClutterClipNodeClass` structure is an opaque + * type whose members cannot be directly accessed. + * + * Since: 1.10 + */ +struct _ClutterClipNodeClass +{ + ClutterPaintNodeClass parent_class; +}; + +G_DEFINE_TYPE (ClutterClipNode, clutter_clip_node, CLUTTER_TYPE_PAINT_NODE) + +static gboolean +clutter_clip_node_pre_draw (ClutterPaintNode *node) +{ + gboolean retval = FALSE; + CoglFramebuffer *fb; + guint i; + + if (node->operations == NULL) + return FALSE; + + fb = clutter_paint_node_get_framebuffer (node); + + for (i = 0; i < node->operations->len; i++) + { + const ClutterPaintOperation *op; + + op = &g_array_index (node->operations, ClutterPaintOperation, i); + + switch (op->opcode) + { + case PAINT_OP_TEX_RECT: + cogl_framebuffer_push_rectangle_clip (fb, + op->op.texrect[0], + op->op.texrect[1], + op->op.texrect[2], + op->op.texrect[3]); + retval = TRUE; + break; + + case PAINT_OP_PATH: + cogl_framebuffer_push_path_clip (fb, op->op.path); + retval = TRUE; + break; + + case PAINT_OP_PRIMITIVE: + case PAINT_OP_INVALID: + break; + } + } + + return retval; +} + +static void +clutter_clip_node_post_draw (ClutterPaintNode *node) +{ + CoglFramebuffer *fb; + guint i; + + if (node->operations == NULL) + return; + + fb = clutter_paint_node_get_framebuffer (node); + + for (i = 0; i < node->operations->len; i++) + { + const ClutterPaintOperation *op; + + op = &g_array_index (node->operations, ClutterPaintOperation, i); + + switch (op->opcode) + { + case PAINT_OP_PATH: + case PAINT_OP_TEX_RECT: + cogl_framebuffer_pop_clip (fb); + break; + + case PAINT_OP_PRIMITIVE: + case PAINT_OP_INVALID: + break; + } + } +} + +static void +clutter_clip_node_class_init (ClutterClipNodeClass *klass) +{ + ClutterPaintNodeClass *node_class; + + node_class = CLUTTER_PAINT_NODE_CLASS (klass); + node_class->pre_draw = clutter_clip_node_pre_draw; + node_class->post_draw = clutter_clip_node_post_draw; +} + +static void +clutter_clip_node_init (ClutterClipNode *self) +{ +} + +/** + * clutter_clip_node_new: + * + * Creates a new #ClutterPaintNode that will clip its child + * nodes to the 2D regions added to it. + * + * Return value: (transfer full): the newly created #ClutterPaintNode. + * Use clutter_paint_node_unref() when done. + * + * Since: 1.10 + */ +ClutterPaintNode * +clutter_clip_node_new (void) +{ + return _clutter_paint_node_create (CLUTTER_TYPE_CLIP_NODE); +} + +/* + * ClutterLayerNode (private) + */ + +#define clutter_layer_node_get_type _clutter_layer_node_get_type + +struct _ClutterLayerNode +{ + ClutterPaintNode parent_instance; + + cairo_rectangle_t viewport; + + CoglMatrix projection; + + float fbo_width; + float fbo_height; + + CoglPipeline *state; + CoglFramebuffer *offscreen; + CoglTexture *texture; + + guint8 opacity; +}; + +struct _ClutterLayerNodeClass +{ + ClutterPaintNodeClass parent_class; +}; + +G_DEFINE_TYPE (ClutterLayerNode, clutter_layer_node, CLUTTER_TYPE_PAINT_NODE) + +static gboolean +clutter_layer_node_pre_draw (ClutterPaintNode *node) +{ + ClutterLayerNode *lnode = (ClutterLayerNode *) node; + CoglMatrix matrix; + + /* if we were unable to create an offscreen buffer for this node, then + * we simply ignore it + */ + if (lnode->offscreen == NULL) + return FALSE; + + /* if no geometry was submitted for this node then we simply ignore it */ + if (node->operations == NULL) + return FALSE; + + /* copy the same modelview from the current framebuffer to the one we + * are going to use + */ + cogl_get_modelview_matrix (&matrix); + + cogl_push_framebuffer (lnode->offscreen); + + cogl_framebuffer_set_modelview_matrix (lnode->offscreen, &matrix); + + cogl_framebuffer_set_viewport (lnode->offscreen, + lnode->viewport.x, + lnode->viewport.y, + lnode->viewport.width, + lnode->viewport.height); + + cogl_framebuffer_set_projection_matrix (lnode->offscreen, + &lnode->projection); + + /* clear out the target framebuffer */ + cogl_framebuffer_clear4f (lnode->offscreen, + COGL_BUFFER_BIT_COLOR | COGL_BUFFER_BIT_DEPTH, + 0.f, 0.f, 0.f, 0.f); + + cogl_push_matrix (); + + /* every draw operation after this point will happen an offscreen + * framebuffer + */ + + return TRUE; +} + +static void +clutter_layer_node_post_draw (ClutterPaintNode *node) +{ + ClutterLayerNode *lnode = CLUTTER_LAYER_NODE (node); + CoglFramebuffer *fb; + guint i; + + /* switch to the previous framebuffer */ + cogl_pop_matrix (); + cogl_pop_framebuffer (); + + fb = cogl_get_draw_framebuffer (); + + for (i = 0; i < node->operations->len; i++) + { + const ClutterPaintOperation *op; + + op = &g_array_index (node->operations, ClutterPaintOperation, i); + switch (op->opcode) + { + case PAINT_OP_INVALID: + break; + + case PAINT_OP_TEX_RECT: + /* now we need to paint the texture */ + cogl_push_source (lnode->state); + cogl_rectangle_with_texture_coords (op->op.texrect[0], + op->op.texrect[1], + op->op.texrect[2], + op->op.texrect[3], + op->op.texrect[4], + op->op.texrect[5], + op->op.texrect[6], + op->op.texrect[7]); + cogl_pop_source (); + break; + + case PAINT_OP_PATH: + cogl_push_source (lnode->state); + cogl_path_fill (op->op.path); + cogl_pop_source (); + break; + + case PAINT_OP_PRIMITIVE: + cogl_framebuffer_draw_primitive (fb, lnode->state, op->op.primitive); + break; + } + } +} + +static void +clutter_layer_node_finalize (ClutterPaintNode *node) +{ + ClutterLayerNode *lnode = CLUTTER_LAYER_NODE (node); + + if (lnode->state != NULL) + cogl_object_unref (lnode->state); + + if (lnode->offscreen != NULL) + cogl_object_unref (lnode->offscreen); + + CLUTTER_PAINT_NODE_CLASS (clutter_layer_node_parent_class)->finalize (node); +} + +static void +clutter_layer_node_class_init (ClutterLayerNodeClass *klass) +{ + ClutterPaintNodeClass *node_class; + + node_class = CLUTTER_PAINT_NODE_CLASS (klass); + node_class->pre_draw = clutter_layer_node_pre_draw; + node_class->post_draw = clutter_layer_node_post_draw; + node_class->finalize = clutter_layer_node_finalize; +} + +static void +clutter_layer_node_init (ClutterLayerNode *self) +{ + cogl_matrix_init_identity (&self->projection); +} + +/* + * clutter_layer_node_new: + * @projection: the projection matrix to use to set up the layer + * @viewport: (type cairo.Rectangle): the viewport to use to set up the layer + * @width: the width of the layer + * @height: the height of the layer + * @opacity: the opacity to be used when drawing the layer + * + * Creates a new #ClutterLayerNode. + * + * All children of this node will be painted inside a separate + * framebuffer; the framebuffer will then be painted using the + * given @opacity. + * + * Return value: (transfer full): the newly created #ClutterLayerNode. + * Use clutter_paint_node_unref() when done. + * + * Since: 1.10 + */ +ClutterPaintNode * +_clutter_layer_node_new (const CoglMatrix *projection, + const cairo_rectangle_t *viewport, + float width, + float height, + guint8 opacity) +{ + ClutterLayerNode *res; + CoglColor color; + + res = _clutter_paint_node_create (CLUTTER_TYPE_LAYER_NODE); + + res->projection = *projection; + res->viewport = *viewport; + res->fbo_width = width; + res->fbo_height = height; + res->opacity = opacity; + + /* the texture backing the FBO */ + res->texture = cogl_texture_new_with_size (MAX (res->fbo_width, 1), + MAX (res->fbo_height, 1), + COGL_TEXTURE_NO_SLICING, + COGL_PIXEL_FORMAT_RGBA_8888_PRE); + + res->offscreen = COGL_FRAMEBUFFER (cogl_offscreen_new_to_texture (res->texture)); + if (res->offscreen == NULL) + { + g_critical ("%s: Unable to create an offscreen buffer", G_STRLOC); + + cogl_object_unref (res->texture); + res->texture = NULL; + + goto out; + } + + cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity); + + /* the pipeline used to paint the texture; we use nearest + * interpolation filters because the texture is always + * going to be painted at a 1:1 texel:pixel ratio + */ + res->state = cogl_pipeline_copy (default_texture_pipeline); + cogl_pipeline_set_layer_filters (res->state, 0, + COGL_PIPELINE_FILTER_NEAREST, + COGL_PIPELINE_FILTER_NEAREST); + cogl_pipeline_set_layer_texture (res->state, 0, res->texture); + cogl_pipeline_set_color (res->state, &color); + cogl_object_unref (res->texture); + +out: + return (ClutterPaintNode *) res; +} diff --git a/clutter/clutter/clutter-paint-nodes.h b/clutter/clutter/clutter-paint-nodes.h new file mode 100644 index 0000000..c86132c --- /dev/null +++ b/clutter/clutter/clutter-paint-nodes.h @@ -0,0 +1,148 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2011 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_PAINT_NODES_H__ +#define __CLUTTER_PAINT_NODES_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_COLOR_NODE (clutter_color_node_get_type ()) +#define CLUTTER_COLOR_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_COLOR_NODE, ClutterColorNode)) +#define CLUTTER_IS_COLOR_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_COLOR_NODE)) + +/** + * ClutterColorNode: + * + * The #ClutterTextNode structure is an opaque + * type whose members cannot be directly accessed. + * + * Since: 1.10 + */ +typedef struct _ClutterColorNode ClutterColorNode; +typedef struct _ClutterColorNodeClass ClutterColorNodeClass; + +CLUTTER_AVAILABLE_IN_1_10 +GType clutter_color_node_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_10 +ClutterPaintNode * clutter_color_node_new (const ClutterColor *color); + +#define CLUTTER_TYPE_TEXTURE_NODE (clutter_texture_node_get_type ()) +#define CLUTTER_TEXTURE_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_TEXTURE_NODE, ClutterTextureNode)) +#define CLUTTER_IS_TEXTURE_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_TEXTURE_NODE)) + +/** + * ClutterTextureNode: + * + * The #ClutterTextNode structure is an opaque + * type whose members cannot be directly accessed. + * + * Since: 1.10 + */ +typedef struct _ClutterTextureNode ClutterTextureNode; +typedef struct _ClutterTextureNodeClass ClutterTextureNodeClass; + +CLUTTER_AVAILABLE_IN_1_10 +GType clutter_texture_node_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_10 +ClutterPaintNode * clutter_texture_node_new (CoglTexture *texture, + const ClutterColor *color, + ClutterScalingFilter min_filter, + ClutterScalingFilter mag_filter); + +#define CLUTTER_TYPE_CLIP_NODE (clutter_clip_node_get_type ()) +#define CLUTTER_CLIP_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_CLIP_NODE, ClutterClipNode)) +#define CLUTTER_IS_CLIP_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_CLIP_NODE)) + +/** + * ClutterClipNode: + * + * The #ClutterTextNode structure is an opaque + * type whose members cannot be directly accessed. + * + * Since: 1.10 + */ +typedef struct _ClutterClipNode ClutterClipNode; +typedef struct _ClutterClipNodeClass ClutterClipNodeClass; + +CLUTTER_AVAILABLE_IN_1_10 +GType clutter_clip_node_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_10 +ClutterPaintNode * clutter_clip_node_new (void); + +#define CLUTTER_TYPE_PIPELINE_NODE (clutter_pipeline_node_get_type ()) +#define CLUTTER_PIPELINE_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_PIPELINE_NODE, ClutterPipelineNode)) +#define CLUTTER_IS_PIPELINE_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_PIPELINE_NODE)) + +/** + * ClutterPipelineNode: + * + * The #ClutterTextNode structure is an opaque + * type whose members cannot be directly accessed. + * + * Since: 1.10 + */ +typedef struct _ClutterPipelineNode ClutterPipelineNode; +typedef struct _ClutterPipelineNodeClass ClutterPipelineNodeClass; + +CLUTTER_AVAILABLE_IN_1_10 +GType clutter_pipeline_node_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_10 +ClutterPaintNode * clutter_pipeline_node_new (CoglPipeline *pipeline); + +#define CLUTTER_TYPE_TEXT_NODE (clutter_text_node_get_type ()) +#define CLUTTER_TEXT_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_TEXT_NODE, ClutterTextNode)) +#define CLUTTER_IS_TEXT_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_TEXT_NODE)) + +/** + * ClutterTextNode: + * + * The #ClutterTextNode structure is an opaque + * type whose members cannot be directly accessed. + * + * Since: 1.10 + */ +typedef struct _ClutterTextNode ClutterTextNode; +typedef struct _ClutterTextNodeClass ClutterTextNodeClass; + +CLUTTER_AVAILABLE_IN_1_10 +GType clutter_text_node_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_10 +ClutterPaintNode * clutter_text_node_new (PangoLayout *layout, + const ClutterColor *color); + +G_END_DECLS + +#endif /* __CLUTTER_PAINT_NODES_H__ */ diff --git a/clutter/clutter/clutter-paint-volume-private.h b/clutter/clutter/clutter-paint-volume-private.h new file mode 100644 index 0000000..72bc7ae --- /dev/null +++ b/clutter/clutter/clutter-paint-volume-private.h @@ -0,0 +1,138 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __CLUTTER_PAINT_VOLUME_PRIVATE_H__ +#define __CLUTTER_PAINT_VOLUME_PRIVATE_H__ + +#include +#include + +G_BEGIN_DECLS + +struct _ClutterPaintVolume +{ + /* A paint volume represents a volume in a given actors private + * coordinate system. */ + ClutterActor *actor; + + /* cuboid for the volume: + * + * 4━━━━━━━┓5 + * ┏━━━━━━━━┓╱┃ + * ┃0 ┊7 1┃ ┃ + * ┃ ┄┄┄┄┄┃┄┃6 + * ┃3 2┃╱ + * ┗━━━━━━━━┛ + * + * 0: top, left (origin) : always valid + * 1: top, right : always valid + * 2: bottom, right : updated lazily + * 3: bottom, left : always valid + * + * 4: top, left, back : always valid + * 5: top, right, back : updated lazily + * 6: bottom, right, back : updated lazily + * 7: bottom, left, back : updated lazily + * + * Elements 0, 1, 3 and 4 are filled in by the PaintVolume setters + * + * Note: the reason for this ordering is that we can simply ignore + * elements 4, 5, 6 and 7 most of the time for 2D actors when + * calculating the projected paint box. + */ + ClutterVertex vertices[8]; + + /* As an optimization for internally managed PaintVolumes we allow + * initializing ClutterPaintVolume variables allocated on the stack + * so we can avoid hammering the slice allocator. */ + guint is_static:1; + + /* A newly initialized PaintVolume is considered empty as it is + * degenerate on all three axis. + * + * We consider this carefully when we union an empty volume with + * another so that the union simply results in a copy of the other + * volume instead of also bounding the origin of the empty volume. + * + * For example this is a convenient property when calculating the + * volume of a container as the union of the volume of its children + * where the initial volume passed to the containers + * ->get_paint_volume method will be empty. */ + guint is_empty:1; + + /* TRUE when we've updated the values we calculate lazily */ + guint is_complete:1; + + /* TRUE if vertices 4-7 can be ignored. (Only valid if complete is + * TRUE) */ + guint is_2d:1; + + /* Set to TRUE initialy but cleared if the paint volume is + * transfomed by a matrix. */ + guint is_axis_aligned:1; + + + /* Note: There is a precedence to the above bitfields that should be + * considered whenever we implement code that manipulates + * PaintVolumes... + * + * Firstly if ->is_empty == TRUE then the values for ->is_complete + * and ->is_2d are undefined, so you should typically check + * ->is_empty as the first priority. + * + * XXX: document other invariables... + */ +}; + +void _clutter_paint_volume_init_static (ClutterPaintVolume *pv, + ClutterActor *actor); +ClutterPaintVolume *_clutter_paint_volume_new (ClutterActor *actor); +void _clutter_paint_volume_copy_static (const ClutterPaintVolume *src_pv, + ClutterPaintVolume *dst_pv); +void _clutter_paint_volume_set_from_volume (ClutterPaintVolume *pv, + const ClutterPaintVolume *src); + +void _clutter_paint_volume_complete (ClutterPaintVolume *pv); +void _clutter_paint_volume_transform (ClutterPaintVolume *pv, + const CoglMatrix *matrix); +void _clutter_paint_volume_project (ClutterPaintVolume *pv, + const CoglMatrix *modelview, + const CoglMatrix *projection, + const float *viewport); +void _clutter_paint_volume_get_bounding_box (ClutterPaintVolume *pv, + ClutterActorBox *box); +void _clutter_paint_volume_axis_align (ClutterPaintVolume *pv); +void _clutter_paint_volume_set_reference_actor (ClutterPaintVolume *pv, + ClutterActor *actor); + +ClutterCullResult _clutter_paint_volume_cull (ClutterPaintVolume *pv, + const ClutterPlane *planes); + +void _clutter_paint_volume_get_stage_paint_box (ClutterPaintVolume *pv, + ClutterStage *stage, + ClutterActorBox *box); + +void _clutter_paint_volume_transform_relative (ClutterPaintVolume *pv, + ClutterActor *relative_to_ancestor); + +G_END_DECLS + +#endif /* __CLUTTER_PAINT_VOLUME_PRIVATE_H__ */ diff --git a/clutter/clutter/clutter-paint-volume.c b/clutter/clutter/clutter-paint-volume.c new file mode 100644 index 0000000..b48f7f9 --- /dev/null +++ b/clutter/clutter/clutter-paint-volume.c @@ -0,0 +1,1236 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + * Authors: + * Robert Bragg + * Emmanuele Bassi + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#include +#include + +#include "clutter-actor-private.h" +#include "clutter-paint-volume-private.h" +#include "clutter-private.h" +#include "clutter-stage-private.h" + +G_DEFINE_BOXED_TYPE (ClutterPaintVolume, clutter_paint_volume, + clutter_paint_volume_copy, + clutter_paint_volume_free); + +/* + * _clutter_paint_volume_new: + * @actor: a #ClutterActor + * + * Creates a new #ClutterPaintVolume for the given @actor. + * + * Return value: the newly allocated #ClutterPaintVolume. Use + * clutter_paint_volume_free() to free the resources it uses + * + * Since: 1.6 + */ +ClutterPaintVolume * +_clutter_paint_volume_new (ClutterActor *actor) +{ + ClutterPaintVolume *pv; + + g_return_val_if_fail (actor != NULL, NULL); + + pv = g_slice_new (ClutterPaintVolume); + + pv->actor = actor; + + memset (pv->vertices, 0, 8 * sizeof (ClutterVertex)); + + pv->is_static = FALSE; + pv->is_empty = TRUE; + pv->is_axis_aligned = TRUE; + pv->is_complete = TRUE; + pv->is_2d = TRUE; + + return pv; +} + +/* Since paint volumes are used so heavily in a typical paint + * traversal of a Clutter scene graph and since paint volumes often + * have a very short life cycle that maps well to stack allocation we + * allow initializing a static ClutterPaintVolume variable to avoid + * hammering the slice allocator. + * + * We were seeing slice allocation take about 1% cumulative CPU time + * for some very simple clutter tests which although it isn't a *lot* + * this is an easy way to basically drop that to 0%. + * + * The PaintVolume will be internally marked as static and + * clutter_paint_volume_free should still be used to "free" static + * volumes. This allows us to potentially store dynamically allocated + * data inside paint volumes in the future since we would be able to + * free it during _paint_volume_free(). + */ +void +_clutter_paint_volume_init_static (ClutterPaintVolume *pv, + ClutterActor *actor) +{ + pv->actor = actor; + + memset (pv->vertices, 0, 8 * sizeof (ClutterVertex)); + + pv->is_static = TRUE; + pv->is_empty = TRUE; + pv->is_axis_aligned = TRUE; + pv->is_complete = TRUE; + pv->is_2d = TRUE; +} + +void +_clutter_paint_volume_copy_static (const ClutterPaintVolume *src_pv, + ClutterPaintVolume *dst_pv) +{ + + g_return_if_fail (src_pv != NULL && dst_pv != NULL); + + memcpy (dst_pv, src_pv, sizeof (ClutterPaintVolume)); + dst_pv->is_static = TRUE; +} + +/** + * clutter_paint_volume_copy: + * @pv: a #ClutterPaintVolume + * + * Copies @pv into a new #ClutterPaintVolume + * + * Return value: a newly allocated copy of a #ClutterPaintVolume + * + * Since: 1.6 + */ +ClutterPaintVolume * +clutter_paint_volume_copy (const ClutterPaintVolume *pv) +{ + ClutterPaintVolume *copy; + + g_return_val_if_fail (pv != NULL, NULL); + + copy = g_slice_dup (ClutterPaintVolume, pv); + copy->is_static = FALSE; + + return copy; +} + +void +_clutter_paint_volume_set_from_volume (ClutterPaintVolume *pv, + const ClutterPaintVolume *src) +{ + gboolean is_static = pv->is_static; + memcpy (pv, src, sizeof (ClutterPaintVolume)); + pv->is_static = is_static; +} + +/** + * clutter_paint_volume_free: + * @pv: a #ClutterPaintVolume + * + * Frees the resources allocated by @pv + * + * Since: 1.6 + */ +void +clutter_paint_volume_free (ClutterPaintVolume *pv) +{ + g_return_if_fail (pv != NULL); + + if (G_LIKELY (pv->is_static)) + return; + + g_slice_free (ClutterPaintVolume, pv); +} + +/** + * clutter_paint_volume_set_origin: + * @pv: a #ClutterPaintVolume + * @origin: a #ClutterVertex + * + * Sets the origin of the paint volume. + * + * The origin is defined as the X, Y and Z coordinates of the top-left + * corner of an actor's paint volume, in actor coordinates. + * + * The default is origin is assumed at: (0, 0, 0) + * + * Since: 1.6 + */ +void +clutter_paint_volume_set_origin (ClutterPaintVolume *pv, + const ClutterVertex *origin) +{ + static const int key_vertices[4] = { 0, 1, 3, 4 }; + float dx, dy, dz; + int i; + + g_return_if_fail (pv != NULL); + + dx = origin->x - pv->vertices[0].x; + dy = origin->y - pv->vertices[0].y; + dz = origin->z - pv->vertices[0].z; + + /* If we change the origin then all the key vertices of the paint + * volume need to be shifted too... */ + for (i = 0; i < 4; i++) + { + pv->vertices[key_vertices[i]].x += dx; + pv->vertices[key_vertices[i]].y += dy; + pv->vertices[key_vertices[i]].z += dz; + } + + pv->is_complete = FALSE; +} + +/** + * clutter_paint_volume_get_origin: + * @pv: a #ClutterPaintVolume + * @vertex: (out): the return location for a #ClutterVertex + * + * Retrieves the origin of the #ClutterPaintVolume. + * + * Since: 1.6 + */ +void +clutter_paint_volume_get_origin (const ClutterPaintVolume *pv, + ClutterVertex *vertex) +{ + g_return_if_fail (pv != NULL); + g_return_if_fail (vertex != NULL); + + *vertex = pv->vertices[0]; +} + +static void +_clutter_paint_volume_update_is_empty (ClutterPaintVolume *pv) +{ + if (pv->vertices[0].x == pv->vertices[1].x && + pv->vertices[0].y == pv->vertices[3].y && + pv->vertices[0].z == pv->vertices[4].z) + pv->is_empty = TRUE; + else + pv->is_empty = FALSE; +} + +/** + * clutter_paint_volume_set_width: + * @pv: a #ClutterPaintVolume + * @width: the width of the paint volume, in pixels + * + * Sets the width of the paint volume. The width is measured along + * the x axis in the actor coordinates that @pv is associated with. + * + * Since: 1.6 + */ +void +clutter_paint_volume_set_width (ClutterPaintVolume *pv, + gfloat width) +{ + gfloat right_xpos; + + g_return_if_fail (pv != NULL); + g_return_if_fail (width >= 0.0f); + + /* If the volume is currently empty then only the origin is + * currently valid */ + if (pv->is_empty) + pv->vertices[1] = pv->vertices[3] = pv->vertices[4] = pv->vertices[0]; + + if (!pv->is_axis_aligned) + _clutter_paint_volume_axis_align (pv); + + right_xpos = pv->vertices[0].x + width; + + /* Move the right vertices of the paint box relative to the + * origin... */ + pv->vertices[1].x = right_xpos; + /* pv->vertices[2].x = right_xpos; NB: updated lazily */ + /* pv->vertices[5].x = right_xpos; NB: updated lazily */ + /* pv->vertices[6].x = right_xpos; NB: updated lazily */ + + pv->is_complete = FALSE; + + _clutter_paint_volume_update_is_empty (pv); +} + +/** + * clutter_paint_volume_get_width: + * @pv: a #ClutterPaintVolume + * + * Retrieves the width of the volume's, axis aligned, bounding box. + * + * In other words; this takes into account what actor's coordinate + * space @pv belongs too and conceptually fits an axis aligned box + * around the volume. It returns the size of that bounding box as + * measured along the x-axis. + * + * If, for example, clutter_actor_get_transformed_paint_volume() + * is used to transform a 2D child actor that is 100px wide, 100px + * high and 0px deep into container coordinates then the width might + * not simply be 100px if the child actor has a 3D rotation applied to + * it. + * + * Remember: if clutter_actor_get_transformed_paint_volume() is + * used then a transformed child volume will be defined relative to the + * ancestor container actor and so a 2D child actor can have a 3D + * bounding volume. + * + * There are no accuracy guarantees for the reported width, + * except that it must always be greater than, or equal to, the + * actor's width. This is because actors may report simple, loose + * fitting paint volumes for efficiency. + + * Return value: the width, in units of @pv's local coordinate system. + * + * Since: 1.6 + */ +gfloat +clutter_paint_volume_get_width (const ClutterPaintVolume *pv) +{ + g_return_val_if_fail (pv != NULL, 0.0); + + if (pv->is_empty) + return 0; + else if (!pv->is_axis_aligned) + { + ClutterPaintVolume tmp; + float width; + _clutter_paint_volume_copy_static (pv, &tmp); + _clutter_paint_volume_axis_align (&tmp); + width = tmp.vertices[1].x - tmp.vertices[0].x; + clutter_paint_volume_free (&tmp); + return width; + } + else + return pv->vertices[1].x - pv->vertices[0].x; +} + +/** + * clutter_paint_volume_set_height: + * @pv: a #ClutterPaintVolume + * @height: the height of the paint volume, in pixels + * + * Sets the height of the paint volume. The height is measured along + * the y axis in the actor coordinates that @pv is associated with. + * + * Since: 1.6 + */ +void +clutter_paint_volume_set_height (ClutterPaintVolume *pv, + gfloat height) +{ + gfloat height_ypos; + + g_return_if_fail (pv != NULL); + g_return_if_fail (height >= 0.0f); + + /* If the volume is currently empty then only the origin is + * currently valid */ + if (pv->is_empty) + pv->vertices[1] = pv->vertices[3] = pv->vertices[4] = pv->vertices[0]; + + if (!pv->is_axis_aligned) + _clutter_paint_volume_axis_align (pv); + + height_ypos = pv->vertices[0].y + height; + + /* Move the bottom vertices of the paint box relative to the + * origin... */ + /* pv->vertices[2].y = height_ypos; NB: updated lazily */ + pv->vertices[3].y = height_ypos; + /* pv->vertices[6].y = height_ypos; NB: updated lazily */ + /* pv->vertices[7].y = height_ypos; NB: updated lazily */ + pv->is_complete = FALSE; + + _clutter_paint_volume_update_is_empty (pv); +} + +/** + * clutter_paint_volume_get_height: + * @pv: a #ClutterPaintVolume + * + * Retrieves the height of the volume's, axis aligned, bounding box. + * + * In other words; this takes into account what actor's coordinate + * space @pv belongs too and conceptually fits an axis aligned box + * around the volume. It returns the size of that bounding box as + * measured along the y-axis. + * + * If, for example, clutter_actor_get_transformed_paint_volume() + * is used to transform a 2D child actor that is 100px wide, 100px + * high and 0px deep into container coordinates then the height might + * not simply be 100px if the child actor has a 3D rotation applied to + * it. + * + * Remember: if clutter_actor_get_transformed_paint_volume() is + * used then a transformed child volume will be defined relative to the + * ancestor container actor and so a 2D child actor + * can have a 3D bounding volume. + * + * There are no accuracy guarantees for the reported height, + * except that it must always be greater than, or equal to, the actor's + * height. This is because actors may report simple, loose fitting paint + * volumes for efficiency. + * + * Return value: the height, in units of @pv's local coordinate system. + * + * Since: 1.6 + */ +gfloat +clutter_paint_volume_get_height (const ClutterPaintVolume *pv) +{ + g_return_val_if_fail (pv != NULL, 0.0); + + if (pv->is_empty) + return 0; + else if (!pv->is_axis_aligned) + { + ClutterPaintVolume tmp; + float height; + _clutter_paint_volume_copy_static (pv, &tmp); + _clutter_paint_volume_axis_align (&tmp); + height = tmp.vertices[3].y - tmp.vertices[0].y; + clutter_paint_volume_free (&tmp); + return height; + } + else + return pv->vertices[3].y - pv->vertices[0].y; +} + +/** + * clutter_paint_volume_set_depth: + * @pv: a #ClutterPaintVolume + * @depth: the depth of the paint volume, in pixels + * + * Sets the depth of the paint volume. The depth is measured along + * the z axis in the actor coordinates that @pv is associated with. + * + * Since: 1.6 + */ +void +clutter_paint_volume_set_depth (ClutterPaintVolume *pv, + gfloat depth) +{ + gfloat depth_zpos; + + g_return_if_fail (pv != NULL); + g_return_if_fail (depth >= 0.0f); + + /* If the volume is currently empty then only the origin is + * currently valid */ + if (pv->is_empty) + pv->vertices[1] = pv->vertices[3] = pv->vertices[4] = pv->vertices[0]; + + if (!pv->is_axis_aligned) + _clutter_paint_volume_axis_align (pv); + + depth_zpos = pv->vertices[0].z + depth; + + /* Move the back vertices of the paint box relative to the + * origin... */ + pv->vertices[4].z = depth_zpos; + /* pv->vertices[5].z = depth_zpos; NB: updated lazily */ + /* pv->vertices[6].z = depth_zpos; NB: updated lazily */ + /* pv->vertices[7].z = depth_zpos; NB: updated lazily */ + + pv->is_complete = FALSE; + pv->is_2d = depth ? FALSE : TRUE; + _clutter_paint_volume_update_is_empty (pv); +} + +/** + * clutter_paint_volume_get_depth: + * @pv: a #ClutterPaintVolume + * + * Retrieves the depth of the volume's, axis aligned, bounding box. + * + * In other words; this takes into account what actor's coordinate + * space @pv belongs too and conceptually fits an axis aligned box + * around the volume. It returns the size of that bounding box as + * measured along the z-axis. + * + * If, for example, clutter_actor_get_transformed_paint_volume() + * is used to transform a 2D child actor that is 100px wide, 100px + * high and 0px deep into container coordinates then the depth might + * not simply be 0px if the child actor has a 3D rotation applied to + * it. + * + * Remember: if clutter_actor_get_transformed_paint_volume() is + * used then the transformed volume will be defined relative to the + * container actor and in container coordinates a 2D child actor + * can have a 3D bounding volume. + * + * There are no accuracy guarantees for the reported depth, + * except that it must always be greater than, or equal to, the actor's + * depth. This is because actors may report simple, loose fitting paint + * volumes for efficiency. + * + * Return value: the depth, in units of @pv's local coordinate system. + * + * Since: 1.6 + */ +gfloat +clutter_paint_volume_get_depth (const ClutterPaintVolume *pv) +{ + g_return_val_if_fail (pv != NULL, 0.0); + + if (pv->is_empty) + return 0; + else if (!pv->is_axis_aligned) + { + ClutterPaintVolume tmp; + float depth; + _clutter_paint_volume_copy_static (pv, &tmp); + _clutter_paint_volume_axis_align (&tmp); + depth = tmp.vertices[4].z - tmp.vertices[0].z; + clutter_paint_volume_free (&tmp); + return depth; + } + else + return pv->vertices[4].z - pv->vertices[0].z; +} + +/** + * clutter_paint_volume_union: + * @pv: The first #ClutterPaintVolume and destination for resulting + * union + * @another_pv: A second #ClutterPaintVolume to union with @pv + * + * Updates the geometry of @pv to encompass @pv and @another_pv. + * + * There are no guarantees about how precisely the two volumes + * will be unioned. + * + * Since: 1.6 + */ +void +clutter_paint_volume_union (ClutterPaintVolume *pv, + const ClutterPaintVolume *another_pv) +{ + ClutterPaintVolume aligned_pv; + + g_return_if_fail (pv != NULL); + g_return_if_fail (another_pv != NULL); + + /* Both volumes have to belong to the same local coordinate space */ + g_return_if_fail (pv->actor == another_pv->actor); + + /* NB: we only have to update vertices 0, 1, 3 and 4 + * (See the ClutterPaintVolume typedef for more details) */ + + /* We special case empty volumes because otherwise we'd end up + * calculating a bounding box that would enclose the origin of + * the empty volume which isn't desired. + */ + if (another_pv->is_empty) + return; + + if (pv->is_empty) + { + _clutter_paint_volume_set_from_volume (pv, another_pv); + goto done; + } + + if (!pv->is_axis_aligned) + _clutter_paint_volume_axis_align (pv); + + if (!another_pv->is_axis_aligned) + { + _clutter_paint_volume_copy_static (another_pv, &aligned_pv); + _clutter_paint_volume_axis_align (&aligned_pv); + another_pv = &aligned_pv; + } + + /* grow left*/ + /* left vertices 0, 3, 4, 7 */ + if (another_pv->vertices[0].x < pv->vertices[0].x) + { + int min_x = another_pv->vertices[0].x; + pv->vertices[0].x = min_x; + pv->vertices[3].x = min_x; + pv->vertices[4].x = min_x; + /* pv->vertices[7].x = min_x; */ + } + + /* grow right */ + /* right vertices 1, 2, 5, 6 */ + if (another_pv->vertices[1].x > pv->vertices[1].x) + { + int max_x = another_pv->vertices[1].x; + pv->vertices[1].x = max_x; + /* pv->vertices[2].x = max_x; */ + /* pv->vertices[5].x = max_x; */ + /* pv->vertices[6].x = max_x; */ + } + + /* grow up */ + /* top vertices 0, 1, 4, 5 */ + if (another_pv->vertices[0].y < pv->vertices[0].y) + { + int min_y = another_pv->vertices[0].y; + pv->vertices[0].y = min_y; + pv->vertices[1].y = min_y; + pv->vertices[4].y = min_y; + /* pv->vertices[5].y = min_y; */ + } + + /* grow down */ + /* bottom vertices 2, 3, 6, 7 */ + if (another_pv->vertices[3].y > pv->vertices[3].y) + { + int may_y = another_pv->vertices[3].y; + /* pv->vertices[2].y = may_y; */ + pv->vertices[3].y = may_y; + /* pv->vertices[6].y = may_y; */ + /* pv->vertices[7].y = may_y; */ + } + + /* grow forward */ + /* front vertices 0, 1, 2, 3 */ + if (another_pv->vertices[0].z < pv->vertices[0].z) + { + int min_z = another_pv->vertices[0].z; + pv->vertices[0].z = min_z; + pv->vertices[1].z = min_z; + /* pv->vertices[2].z = min_z; */ + pv->vertices[3].z = min_z; + } + + /* grow backward */ + /* back vertices 4, 5, 6, 7 */ + if (another_pv->vertices[4].z > pv->vertices[4].z) + { + int maz_z = another_pv->vertices[4].z; + pv->vertices[4].z = maz_z; + /* pv->vertices[5].z = maz_z; */ + /* pv->vertices[6].z = maz_z; */ + /* pv->vertices[7].z = maz_z; */ + } + + if (pv->vertices[4].z == pv->vertices[0].z) + pv->is_2d = TRUE; + else + pv->is_2d = FALSE; + +done: + pv->is_empty = FALSE; + pv->is_complete = FALSE; +} + +/** + * clutter_paint_volume_union_box: + * @pv: a #ClutterPaintVolume + * @box: a #ClutterActorBox to union to @pv + * + * Unions the 2D region represented by @box to a #ClutterPaintVolume. + * + * This function is similar to clutter_paint_volume_union(), but it is + * specific for 2D regions. + * + * Since: 1.10 + */ +void +clutter_paint_volume_union_box (ClutterPaintVolume *pv, + const ClutterActorBox *box) +{ + ClutterPaintVolume volume; + ClutterVertex origin; + + g_return_if_fail (pv != NULL); + g_return_if_fail (box != NULL); + + _clutter_paint_volume_init_static (&volume, pv->actor); + + origin.x = box->x1; + origin.y = box->y1; + origin.z = 0.f; + clutter_paint_volume_set_origin (&volume, &origin); + clutter_paint_volume_set_width (&volume, box->x2 - box->x1); + clutter_paint_volume_set_height (&volume, box->y2 - box->y1); + + clutter_paint_volume_union (pv, &volume); + + clutter_paint_volume_free (&volume); +} + +/* The paint_volume setters only update vertices 0, 1, 3 and + * 4 since the others can be drived from them. + * + * This will set pv->completed = TRUE; + */ +void +_clutter_paint_volume_complete (ClutterPaintVolume *pv) +{ + float dx_l2r, dy_l2r, dz_l2r; + float dx_t2b, dy_t2b, dz_t2b; + + if (pv->is_empty) + return; + + if (pv->is_complete) + return; + + /* Find the vector that takes us from any vertex on the left face to + * the corresponding vertex on the right face. */ + dx_l2r = pv->vertices[1].x - pv->vertices[0].x; + dy_l2r = pv->vertices[1].y - pv->vertices[0].y; + dz_l2r = pv->vertices[1].z - pv->vertices[0].z; + + /* Find the vector that takes us from any vertex on the top face to + * the corresponding vertex on the bottom face. */ + dx_t2b = pv->vertices[3].x - pv->vertices[0].x; + dy_t2b = pv->vertices[3].y - pv->vertices[0].y; + dz_t2b = pv->vertices[3].z - pv->vertices[0].z; + + /* front-bottom-right */ + pv->vertices[2].x = pv->vertices[3].x + dx_l2r; + pv->vertices[2].y = pv->vertices[3].y + dy_l2r; + pv->vertices[2].z = pv->vertices[3].z + dz_l2r; + + if (G_UNLIKELY (!pv->is_2d)) + { + /* back-top-right */ + pv->vertices[5].x = pv->vertices[4].x + dx_l2r; + pv->vertices[5].y = pv->vertices[4].y + dy_l2r; + pv->vertices[5].z = pv->vertices[4].z + dz_l2r; + + /* back-bottom-right */ + pv->vertices[6].x = pv->vertices[5].x + dx_t2b; + pv->vertices[6].y = pv->vertices[5].y + dy_t2b; + pv->vertices[6].z = pv->vertices[5].z + dz_t2b; + + /* back-bottom-left */ + pv->vertices[7].x = pv->vertices[4].x + dx_t2b; + pv->vertices[7].y = pv->vertices[4].y + dy_t2b; + pv->vertices[7].z = pv->vertices[4].z + dz_t2b; + } + + pv->is_complete = TRUE; +} + +/* + * _clutter_paint_volume_get_box: + * @pv: a #ClutterPaintVolume + * @box: a pixel aligned #ClutterActorBox + * + * Transforms a 3D paint volume into a 2D bounding box in the + * same coordinate space as the 3D paint volume. + * + * To get an actors "paint box" you should first project + * the paint volume into window coordinates before getting + * the 2D bounding box. + * + * The coordinates of the returned box are not clamped to + * integer pixel values; if you need them to be rounded to the + * nearest integer pixel values, you can use the + * clutter_actor_box_clamp_to_pixel() function. + * + * Since: 1.6 + */ +void +_clutter_paint_volume_get_bounding_box (ClutterPaintVolume *pv, + ClutterActorBox *box) +{ + gfloat x_min, y_min, x_max, y_max; + ClutterVertex *vertices; + int count; + gint i; + + g_return_if_fail (pv != NULL); + g_return_if_fail (box != NULL); + + if (pv->is_empty) + { + box->x1 = box->x2 = pv->vertices[0].x; + box->y1 = box->y2 = pv->vertices[0].y; + return; + } + + /* Updates the vertices we calculate lazily + * (See ClutterPaintVolume typedef for more details) */ + _clutter_paint_volume_complete (pv); + + vertices = pv->vertices; + + x_min = x_max = vertices[0].x; + y_min = y_max = vertices[0].y; + + /* Most actors are 2D so we only have to look at the front 4 + * vertices of the paint volume... */ + if (G_LIKELY (pv->is_2d)) + count = 4; + else + count = 8; + + for (i = 1; i < count; i++) + { + if (vertices[i].x < x_min) + x_min = vertices[i].x; + else if (vertices[i].x > x_max) + x_max = vertices[i].x; + + if (vertices[i].y < y_min) + y_min = vertices[i].y; + else if (vertices[i].y > y_max) + y_max = vertices[i].y; + } + + box->x1 = x_min; + box->y1 = y_min; + box->x2 = x_max; + box->y2 = y_max; +} + +void +_clutter_paint_volume_project (ClutterPaintVolume *pv, + const CoglMatrix *modelview, + const CoglMatrix *projection, + const float *viewport) +{ + int transform_count; + + if (pv->is_empty) + { + /* Just transform the origin... */ + _clutter_util_fully_transform_vertices (modelview, + projection, + viewport, + pv->vertices, + pv->vertices, + 1); + return; + } + + /* All the vertices must be up to date, since after the projection + * it wont be trivial to derive the other vertices. */ + _clutter_paint_volume_complete (pv); + + /* Most actors are 2D so we only have to transform the front 4 + * vertices of the paint volume... */ + if (G_LIKELY (pv->is_2d)) + transform_count = 4; + else + transform_count = 8; + + _clutter_util_fully_transform_vertices (modelview, + projection, + viewport, + pv->vertices, + pv->vertices, + transform_count); + + pv->is_axis_aligned = FALSE; +} + +void +_clutter_paint_volume_transform (ClutterPaintVolume *pv, + const CoglMatrix *matrix) +{ + int transform_count; + + if (pv->is_empty) + { + gfloat w = 1; + /* Just transform the origin */ + cogl_matrix_transform_point (matrix, + &pv->vertices[0].x, + &pv->vertices[0].y, + &pv->vertices[0].z, + &w); + return; + } + + /* All the vertices must be up to date, since after the transform + * it wont be trivial to derive the other vertices. */ + _clutter_paint_volume_complete (pv); + + /* Most actors are 2D so we only have to transform the front 4 + * vertices of the paint volume... */ + if (G_LIKELY (pv->is_2d)) + transform_count = 4; + else + transform_count = 8; + + cogl_matrix_transform_points (matrix, + 3, + sizeof (ClutterVertex), + pv->vertices, + sizeof (ClutterVertex), + pv->vertices, + transform_count); + + pv->is_axis_aligned = FALSE; +} + + +/* Given a paint volume that has been transformed by an arbitrary + * modelview and is no longer axis aligned, this derives a replacement + * that is axis aligned. */ +void +_clutter_paint_volume_axis_align (ClutterPaintVolume *pv) +{ + int count; + int i; + ClutterVertex origin; + float max_x; + float max_y; + float max_z; + + g_return_if_fail (pv != NULL); + + if (pv->is_empty) + return; + + if (G_LIKELY (pv->is_axis_aligned)) + return; + + if (G_LIKELY (pv->vertices[0].x == pv->vertices[1].x && + pv->vertices[0].y == pv->vertices[3].y && + pv->vertices[0].z == pv->vertices[4].z)) + { + pv->is_axis_aligned = TRUE; + return; + } + + if (!pv->is_complete) + _clutter_paint_volume_complete (pv); + + origin = pv->vertices[0]; + max_x = pv->vertices[0].x; + max_y = pv->vertices[0].y; + max_z = pv->vertices[0].z; + + count = pv->is_2d ? 4 : 8; + for (i = 1; i < count; i++) + { + if (pv->vertices[i].x < origin.x) + origin.x = pv->vertices[i].x; + else if (pv->vertices[i].x > max_x) + max_x = pv->vertices[i].x; + + if (pv->vertices[i].y < origin.y) + origin.y = pv->vertices[i].y; + else if (pv->vertices[i].y > max_y) + max_y = pv->vertices[i].y; + + if (pv->vertices[i].z < origin.z) + origin.z = pv->vertices[i].z; + else if (pv->vertices[i].z > max_z) + max_z = pv->vertices[i].z; + } + + pv->vertices[0] = origin; + + pv->vertices[1].x = max_x; + pv->vertices[1].y = origin.y; + pv->vertices[1].z = origin.z; + + pv->vertices[3].x = origin.x; + pv->vertices[3].y = max_y; + pv->vertices[3].z = origin.z; + + pv->vertices[4].x = origin.x; + pv->vertices[4].y = origin.y; + pv->vertices[4].z = max_z; + + pv->is_complete = FALSE; + pv->is_axis_aligned = TRUE; + + if (pv->vertices[4].z == pv->vertices[0].z) + pv->is_2d = TRUE; + else + pv->is_2d = FALSE; +} + +/* + * _clutter_actor_set_default_paint_volume: + * @self: a #ClutterActor + * @check_gtype: if not %G_TYPE_INVALID, match the type of @self against + * this type + * @volume: the #ClutterPaintVolume to set + * + * Sets the default paint volume for @self. + * + * This function should be called by #ClutterActor sub-classes that follow + * the default assumption that their paint volume is defined by their + * allocation. + * + * If @check_gtype is not %G_TYPE_INVALID, this function will check the + * type of @self and only compute the paint volume if the type matches; + * this can be used to avoid computing the paint volume for sub-classes + * of an actor class + * + * Return value: %TRUE if the paint volume was set, and %FALSE otherwise + */ +gboolean +_clutter_actor_set_default_paint_volume (ClutterActor *self, + GType check_gtype, + ClutterPaintVolume *volume) +{ + ClutterActorBox box; + + if (check_gtype != G_TYPE_INVALID) + { + if (G_OBJECT_TYPE (self) != check_gtype) + return FALSE; + } + + /* calling clutter_actor_get_allocation_* can potentially be very + * expensive, as it can result in a synchronous full stage relayout + * and redraw + */ + if (!clutter_actor_has_allocation (self)) + return FALSE; + + clutter_actor_get_allocation_box (self, &box); + + /* we only set the width and height, as the paint volume is defined + * to be relative to the actor's modelview, which means that the + * allocation's origin has already been applied + */ + clutter_paint_volume_set_width (volume, box.x2 - box.x1); + clutter_paint_volume_set_height (volume, box.y2 - box.y1); + + return TRUE; +} + +/** + * clutter_paint_volume_set_from_allocation: + * @pv: a #ClutterPaintVolume + * @actor: a #ClutterActor + * + * Sets the #ClutterPaintVolume from the allocation of @actor. + * + * This function should be used when overriding the + * #ClutterActorClass.get_paint_volume() by #ClutterActor sub-classes + * that do not paint outside their allocation. + * + * A typical example is: + * + * |[ + * static gboolean + * my_actor_get_paint_volume (ClutterActor *self, + * ClutterPaintVolume *volume) + * { + * return clutter_paint_volume_set_from_allocation (volume, self); + * } + * ]| + * + * Return value: %TRUE if the paint volume was successfully set, and %FALSE + * otherwise + * + * Since: 1.6 + */ +gboolean +clutter_paint_volume_set_from_allocation (ClutterPaintVolume *pv, + ClutterActor *actor) +{ + g_return_val_if_fail (pv != NULL, FALSE); + g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), FALSE); + + return _clutter_actor_set_default_paint_volume (actor, G_TYPE_INVALID, pv); +} + +/* Currently paint volumes are defined relative to a given actor, but + * in some cases it is desireable to be able to change the actor that + * a volume relates too (For instance for ClutterClone actors where we + * need to masquarade the source actors volume as the volume for the + * clone). */ +void +_clutter_paint_volume_set_reference_actor (ClutterPaintVolume *pv, + ClutterActor *actor) +{ + g_return_if_fail (pv != NULL); + + pv->actor = actor; +} + +ClutterCullResult +_clutter_paint_volume_cull (ClutterPaintVolume *pv, + const ClutterPlane *planes) +{ + int vertex_count; + ClutterVertex *vertices = pv->vertices; + gboolean partial = FALSE; + int i; + int j; + + if (pv->is_empty) + return CLUTTER_CULL_RESULT_OUT; + + /* We expect the volume to already be transformed into eye coordinates + */ + g_return_val_if_fail (pv->is_complete == TRUE, CLUTTER_CULL_RESULT_IN); + g_return_val_if_fail (pv->actor == NULL, CLUTTER_CULL_RESULT_IN); + + /* Most actors are 2D so we only have to transform the front 4 + * vertices of the paint volume... */ + if (G_LIKELY (pv->is_2d)) + vertex_count = 4; + else + vertex_count = 8; + + for (i = 0; i < 4; i++) + { + int out = 0; + for (j = 0; j < vertex_count; j++) + { + ClutterVertex p; + float distance; + + /* XXX: for perspective projections this can be optimized + * out because all the planes should pass through the origin + * so (0,0,0) is a valid v0. */ + p.x = vertices[j].x - planes[i].v0[0]; + p.y = vertices[j].y - planes[i].v0[1]; + p.z = vertices[j].z - planes[i].v0[2]; + + distance = (planes[i].n[0] * p.x + + planes[i].n[1] * p.y + + planes[i].n[2] * p.z); + + if (distance < 0) + out++; + } + + if (out == vertex_count) + return CLUTTER_CULL_RESULT_OUT; + else if (out != 0) + partial = TRUE; + } + + if (partial) + return CLUTTER_CULL_RESULT_PARTIAL; + else + return CLUTTER_CULL_RESULT_IN; +} + +void +_clutter_paint_volume_get_stage_paint_box (ClutterPaintVolume *pv, + ClutterStage *stage, + ClutterActorBox *box) +{ + ClutterPaintVolume projected_pv; + CoglMatrix modelview; + CoglMatrix projection; + float viewport[4]; + float width; + float height; + + _clutter_paint_volume_copy_static (pv, &projected_pv); + + cogl_matrix_init_identity (&modelview); + + /* If the paint volume isn't already in eye coordinates... */ + if (pv->actor) + _clutter_actor_apply_relative_transformation_matrix (pv->actor, NULL, + &modelview); + + _clutter_stage_get_projection_matrix (stage, &projection); + _clutter_stage_get_viewport (stage, + &viewport[0], + &viewport[1], + &viewport[2], + &viewport[3]); + + _clutter_paint_volume_project (&projected_pv, + &modelview, + &projection, + viewport); + + _clutter_paint_volume_get_bounding_box (&projected_pv, box); + + /* The aim here is that for a given rectangle defined with floating point + * coordinates we want to determine a stable quantized size in pixels + * that doesn't vary due to the original box's sub-pixel position. + * + * The reason this is important is because effects will use this + * API to determine the size of offscreen framebuffers and so for + * a fixed-size object that may be animated accross the screen we + * want to make sure that the stage paint-box has an equally stable + * size so that effects aren't made to continuously re-allocate + * a corresponding fbo. + * + * The other thing we consider is that the calculation of this box is + * subject to floating point precision issues that might be slightly + * different to the precision issues involved with actually painting the + * actor, which might result in painting slightly leaking outside the + * user's calculated paint-volume. For this we simply aim to pad out the + * paint-volume by at least half a pixel all the way around. + */ + width = box->x2 - box->x1; + height = box->y2 - box->y1; + width = CLUTTER_NEARBYINT (width); + height = CLUTTER_NEARBYINT (height); + /* XXX: NB the width/height may now be up to 0.5px too small so we + * must also pad by 0.25px all around to account for this. In total we + * must padd by at least 0.75px around all sides. */ + + /* XXX: The furthest that we can overshoot the bottom right corner by + * here is 1.75px in total if you consider that the 0.75 padding could + * just cross an integer boundary and so ceil will effectively add 1. + */ + box->x2 = ceilf (box->x2 + 0.75); + box->y2 = ceilf (box->y2 + 0.75); + + /* Now we redefine the top-left relative to the bottom right based on the + * rounded width/height determined above + a constant so that the overall + * size of the box will be stable and not dependant on the box's + * position. + * + * Adding 3px to the width/height will ensure we cover the maximum of + * 1.75px padding on the bottom/right and still ensure we have > 0.75px + * padding on the top/left. + */ + box->x1 = box->x2 - width - 3; + box->y1 = box->y2 - height - 3; + + clutter_paint_volume_free (&projected_pv); +} + +void +_clutter_paint_volume_transform_relative (ClutterPaintVolume *pv, + ClutterActor *relative_to_ancestor) +{ + CoglMatrix matrix; + ClutterActor *actor; + + actor = pv->actor; + + g_return_if_fail (actor != NULL); + + _clutter_paint_volume_set_reference_actor (pv, relative_to_ancestor); + + cogl_matrix_init_identity (&matrix); + _clutter_actor_apply_relative_transformation_matrix (actor, + relative_to_ancestor, + &matrix); + + _clutter_paint_volume_transform (pv, &matrix); +} diff --git a/clutter/clutter/clutter-pan-action.c b/clutter/clutter/clutter-pan-action.c new file mode 100644 index 0000000..582a7d7 --- /dev/null +++ b/clutter/clutter/clutter-pan-action.c @@ -0,0 +1,1019 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * Copyright (C) 2011 Robert Bosch Car Multimedia GmbH. + * Copyright (C) 2012, 2014 Collabora Ltd. + * + * 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 . + * + * Author: + * Emanuele Aina + * + * Based on ClutterDragAction, ClutterSwipeAction, and MxKineticScrollView, + * written by: + * Emmanuele Bassi + * Tomeu Vizoso + * Chris Lord + */ + +/** + * SECTION:clutter-pan-action + * @Title: ClutterPanAction + * @Short_Description: Action for pan gestures + * + * #ClutterPanAction is a sub-class of #ClutterGestureAction that implements + * the logic for recognizing pan gestures. + * + * The simplest usage of #ClutterPanAction consists in adding it to + * a #ClutterActor with a child and setting it as reactive; for instance, + * the following code: + * + * |[ + * clutter_actor_add_action (actor, clutter_pan_action_new ()); + * clutter_actor_set_reactive (actor, TRUE); + * ]| + * + * will automatically result in the actor children to be moved + * when dragging. + * + * Since: 1.12 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-pan-action.h" + +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-gesture-action-private.h" +#include "clutter-marshal.h" +#include "clutter-private.h" +#include + +#define FLOAT_EPSILON (1e-15) + +static const gfloat min_velocity = 0.1f; // measured in px/ms +static const gfloat reference_fps = 60.0f; // the fps assumed for the deceleration rate +static const gfloat default_deceleration_rate = 0.95f; +static const gfloat default_acceleration_factor = 1.0f; + +typedef enum +{ + PAN_STATE_INACTIVE, + PAN_STATE_PANNING, + PAN_STATE_INTERPOLATING +} PanState; + +typedef enum +{ + SCROLL_PINNED_UNKNOWN, + SCROLL_PINNED_NONE, + SCROLL_PINNED_HORIZONTAL, + SCROLL_PINNED_VERTICAL +} PinState; + +struct _ClutterPanActionPrivate +{ + ClutterPanAxis pan_axis; + + PanState state; + + /* Variables for storing acceleration information */ + ClutterTimeline *deceleration_timeline; + gfloat target_x; + gfloat target_y; + gfloat dx; + gfloat dy; + gdouble deceleration_rate; + gdouble acceleration_factor; + + /* Inertial motion tracking */ + gfloat interpolated_x; + gfloat interpolated_y; + gfloat release_x; + gfloat release_y; + + guint should_interpolate : 1; + + PinState pin_state; +}; + +enum +{ + PROP_0, + + PROP_PAN_AXIS, + PROP_INTERPOLATE, + PROP_DECELERATION, + PROP_ACCELERATION_FACTOR, + + PROP_LAST +}; + +static GParamSpec *pan_props[PROP_LAST] = { NULL, }; + +enum +{ + PAN, + PAN_STOPPED, + + LAST_SIGNAL +}; + +static guint pan_signals[LAST_SIGNAL] = { 0, }; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterPanAction, clutter_pan_action, CLUTTER_TYPE_GESTURE_ACTION) + +static void +emit_pan (ClutterPanAction *self, + ClutterActor *actor, + gboolean is_interpolated) +{ + ClutterPanActionPrivate *priv = self->priv; + gboolean retval; + + if (priv->pin_state == SCROLL_PINNED_UNKNOWN) + { + priv->pin_state = SCROLL_PINNED_NONE; + if (priv->pan_axis == CLUTTER_PAN_AXIS_AUTO) + { + gfloat delta_x; + gfloat delta_y; + gfloat scroll_threshold = G_PI_4/2; + gfloat drag_angle; + + clutter_gesture_action_get_motion_delta (CLUTTER_GESTURE_ACTION (self), 0, &delta_x, &delta_y); + + if (delta_x != 0.0f) + drag_angle = atanf (delta_y / delta_x); + else + drag_angle = G_PI_2; + + if ((drag_angle > -scroll_threshold) && (drag_angle < scroll_threshold)) + priv->pin_state = SCROLL_PINNED_HORIZONTAL; + else if ((drag_angle > (G_PI_2 - scroll_threshold)) || + (drag_angle < -(G_PI_2 - scroll_threshold))) + priv->pin_state = SCROLL_PINNED_VERTICAL; + } + } + + g_signal_emit (self, pan_signals[PAN], 0, actor, is_interpolated, &retval); +} + +static void +emit_pan_stopped (ClutterPanAction *self, + ClutterActor *actor) +{ + ClutterPanActionPrivate *priv = self->priv; + + g_signal_emit (self, pan_signals[PAN_STOPPED], 0, actor); + priv->state = PAN_STATE_INACTIVE; +} + +static void +on_deceleration_stopped (ClutterTimeline *timeline, + gboolean is_finished, + ClutterPanAction *self) +{ + ClutterPanActionPrivate *priv = self->priv; + ClutterActor *actor; + + g_object_unref (timeline); + priv->deceleration_timeline = NULL; + + actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (self)); + emit_pan_stopped (self, actor); +} + +static void +on_deceleration_new_frame (ClutterTimeline *timeline, + gint elapsed_time, + ClutterPanAction *self) +{ + ClutterPanActionPrivate *priv = self->priv; + ClutterActor *actor; + gdouble progress; + gfloat interpolated_x, interpolated_y; + + progress = clutter_timeline_get_progress (timeline); + + interpolated_x = priv->target_x * progress; + interpolated_y = priv->target_y * progress; + priv->dx = interpolated_x - priv->interpolated_x; + priv->dy = interpolated_y - priv->interpolated_y; + priv->interpolated_x = interpolated_x; + priv->interpolated_y = interpolated_y; + + actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (self)); + emit_pan (self, actor, TRUE); +} + +static gboolean +gesture_prepare (ClutterGestureAction *gesture, + ClutterActor *actor) +{ + ClutterPanAction *self = CLUTTER_PAN_ACTION (gesture); + ClutterPanActionPrivate *priv = self->priv; + + if (priv->state == PAN_STATE_INTERPOLATING && priv->deceleration_timeline) + clutter_timeline_stop (priv->deceleration_timeline); + + return TRUE; +} + +static gboolean +gesture_begin (ClutterGestureAction *gesture, + ClutterActor *actor) +{ + ClutterPanAction *self = CLUTTER_PAN_ACTION (gesture); + ClutterPanActionPrivate *priv = self->priv; + + priv->pin_state = SCROLL_PINNED_UNKNOWN; + priv->state = PAN_STATE_PANNING; + priv->interpolated_x = priv->interpolated_y = 0.0f; + priv->dx = priv->dy = 0.0f; + + return TRUE; +} + +static gboolean +gesture_progress (ClutterGestureAction *gesture, + ClutterActor *actor) +{ + ClutterPanAction *self = CLUTTER_PAN_ACTION (gesture); + + emit_pan (self, actor, FALSE); + + return TRUE; +} + +static void +gesture_cancel (ClutterGestureAction *gesture, + ClutterActor *actor) +{ + ClutterPanAction *self = CLUTTER_PAN_ACTION (gesture); + ClutterPanActionPrivate *priv = self->priv; + + priv->state = PAN_STATE_INACTIVE; +} + +static void +gesture_end (ClutterGestureAction *gesture, + ClutterActor *actor) +{ + ClutterPanAction *self = CLUTTER_PAN_ACTION (gesture); + ClutterPanActionPrivate *priv = self->priv; + gfloat velocity, velocity_x, velocity_y; + gfloat delta_x, delta_y; + gfloat tau; + gint duration; + + clutter_gesture_action_get_release_coords (CLUTTER_GESTURE_ACTION (self), 0, &priv->release_x, &priv->release_y); + + if (!priv->should_interpolate) + { + priv->state = PAN_STATE_INACTIVE; + return; + } + + priv->state = PAN_STATE_INTERPOLATING; + + clutter_gesture_action_get_motion_delta (gesture, 0, &delta_x, &delta_y); + velocity = clutter_gesture_action_get_velocity (gesture, 0, &velocity_x, &velocity_y); + + /* Exponential timing constant v(t) = v(0) * exp(-t/tau) + * tau = 1000ms / (frame_per_second * - ln(decay_per_frame)) + * with frame_per_second = 60 and decay_per_frame = 0.95, tau ~= 325ms + * see http://ariya.ofilabs.com/2011/10/flick-list-with-its-momentum-scrolling-and-deceleration.html */ + tau = 1000.0f / (reference_fps * - logf (priv->deceleration_rate)); + + /* See where the decreasing velocity reaches $min_velocity px/ms + * v(t) = v(0) * exp(-t/tau) = min_velocity + * t = - tau * ln( min_velocity / |v(0)|) */ + duration = - tau * logf (min_velocity / (ABS (velocity) * priv->acceleration_factor)); + + /* Target point: x(t) = v(0) * tau * [1 - exp(-t/tau)] */ + priv->target_x = velocity_x * priv->acceleration_factor * tau * (1 - exp ((float)-duration / tau)); + priv->target_y = velocity_y * priv->acceleration_factor * tau * (1 - exp ((float)-duration / tau)); + + if (ABS (velocity) * priv->acceleration_factor > min_velocity && duration > FLOAT_EPSILON) + { + priv->interpolated_x = priv->interpolated_y = 0.0f; + priv->deceleration_timeline = clutter_timeline_new (duration); + clutter_timeline_set_progress_mode (priv->deceleration_timeline, CLUTTER_EASE_OUT_EXPO); + + g_signal_connect (priv->deceleration_timeline, "new_frame", + G_CALLBACK (on_deceleration_new_frame), self); + g_signal_connect (priv->deceleration_timeline, "stopped", + G_CALLBACK (on_deceleration_stopped), self); + clutter_timeline_start (priv->deceleration_timeline); + } + else + { + emit_pan_stopped (self, actor); + } +} + +static gboolean +clutter_pan_action_real_pan (ClutterPanAction *self, + ClutterActor *actor, + gboolean is_interpolated) +{ + gfloat dx, dy; + ClutterMatrix transform; + + clutter_pan_action_get_constrained_motion_delta (self, 0, &dx, &dy); + + clutter_actor_get_child_transform (actor, &transform); + cogl_matrix_translate (&transform, dx, dy, 0.0f); + clutter_actor_set_child_transform (actor, &transform); + return TRUE; +} + +static void +clutter_pan_action_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterPanAction *self = CLUTTER_PAN_ACTION (gobject); + + switch (prop_id) + { + case PROP_PAN_AXIS: + clutter_pan_action_set_pan_axis (self, g_value_get_enum (value)); + break; + + case PROP_INTERPOLATE : + clutter_pan_action_set_interpolate (self, g_value_get_boolean (value)); + break; + + case PROP_DECELERATION : + clutter_pan_action_set_deceleration (self, g_value_get_double (value)); + break; + + case PROP_ACCELERATION_FACTOR : + clutter_pan_action_set_acceleration_factor (self, g_value_get_double (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + } +} + +static void +clutter_pan_action_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterPanAction *self = CLUTTER_PAN_ACTION (gobject); + ClutterPanActionPrivate *priv = self->priv; + + switch (prop_id) + { + case PROP_PAN_AXIS: + g_value_set_enum (value, priv->pan_axis); + break; + + case PROP_INTERPOLATE : + g_value_set_boolean (value, priv->should_interpolate); + break; + + case PROP_DECELERATION : + g_value_set_double (value, priv->deceleration_rate); + break; + + case PROP_ACCELERATION_FACTOR : + g_value_set_double (value, priv->acceleration_factor); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + } +} + +static void +clutter_pan_action_constructed (GObject *gobject) +{ + ClutterGestureAction *gesture; + + gesture = CLUTTER_GESTURE_ACTION (gobject); + clutter_gesture_action_set_threshold_trigger_edge (gesture, CLUTTER_GESTURE_TRIGGER_EDGE_AFTER); +} + +static void +clutter_pan_action_dispose (GObject *gobject) +{ + ClutterPanActionPrivate *priv = CLUTTER_PAN_ACTION (gobject)->priv; + + g_clear_object (&priv->deceleration_timeline); + + G_OBJECT_CLASS (clutter_pan_action_parent_class)->dispose (gobject); +} + +static void +clutter_pan_action_set_actor (ClutterActorMeta *meta, + ClutterActor *actor) +{ + ClutterPanAction *self = CLUTTER_PAN_ACTION (meta); + ClutterPanActionPrivate *priv = self->priv; + ClutterActor *old_actor; + + old_actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (self)); + if (old_actor != actor) + { + /* make sure we reset the state */ + if (priv->state == PAN_STATE_INTERPOLATING) + g_clear_object (&priv->deceleration_timeline); + } + + CLUTTER_ACTOR_META_CLASS (clutter_pan_action_parent_class)->set_actor (meta, actor); +} + + +static void +clutter_pan_action_class_init (ClutterPanActionClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass); + ClutterGestureActionClass *gesture_class = + CLUTTER_GESTURE_ACTION_CLASS (klass); + + klass->pan = clutter_pan_action_real_pan; + + gesture_class->gesture_prepare = gesture_prepare; + gesture_class->gesture_begin = gesture_begin; + gesture_class->gesture_progress = gesture_progress; + gesture_class->gesture_cancel = gesture_cancel; + gesture_class->gesture_end = gesture_end; + + meta_class->set_actor = clutter_pan_action_set_actor; + + /** + * ClutterPanAction:pan-axis: + * + * Constraints the panning action to the specified axis + * + * Since: 1.12 + */ + pan_props[PROP_PAN_AXIS] = + g_param_spec_enum ("pan-axis", + P_("Pan Axis"), + P_("Constraints the panning to an axis"), + CLUTTER_TYPE_PAN_AXIS, + CLUTTER_PAN_AXIS_NONE, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterPanAction:interpolate: + * + * Whether interpolated events emission is enabled. + * + * Since: 1.12 + */ + pan_props[PROP_INTERPOLATE] = + g_param_spec_boolean ("interpolate", + P_("Interpolate"), + P_("Whether interpolated events emission is enabled."), + FALSE, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterPanAction:deceleration: + * + * The rate at which the interpolated panning will decelerate in + * + * #ClutterPanAction will emit interpolated ::pan events with decreasing + * scroll deltas, using the rate specified by this property. + * + * Since: 1.12 + */ + pan_props[PROP_DECELERATION] = + g_param_spec_double ("deceleration", + P_("Deceleration"), + P_("Rate at which the interpolated panning will decelerate in"), + FLOAT_EPSILON, 1.0, default_deceleration_rate, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterPanAction:acceleration-factor: + * + * The initial acceleration factor + * + * The kinetic momentum measured at the time of releasing the pointer will + * be multiplied by the factor specified by this property before being used + * to generate interpolated ::pan events. + * + * Since: 1.12 + */ + pan_props[PROP_ACCELERATION_FACTOR] = + g_param_spec_double ("acceleration-factor", + P_("Initial acceleration factor"), + P_("Factor applied to the momentum when starting the interpolated phase"), + 1.0, G_MAXDOUBLE, default_acceleration_factor, + CLUTTER_PARAM_READWRITE); + + gobject_class->constructed = clutter_pan_action_constructed; + gobject_class->set_property = clutter_pan_action_set_property; + gobject_class->get_property = clutter_pan_action_get_property; + gobject_class->dispose = clutter_pan_action_dispose; + g_object_class_install_properties (gobject_class, + PROP_LAST, + pan_props); + + /** + * ClutterPanAction::pan: + * @action: the #ClutterPanAction that emitted the signal + * @actor: the #ClutterActor attached to the @action + * @is_interpolated: if the event is the result of interpolating + * the motion velocity at the end of the drag + * + * The ::pan signal is emitted to keep track of the motion during + * a pan gesture. @is_interpolated is set to %TRUE during the + * interpolation phase of the pan, after the drag has ended and + * the :interpolate property was set to %TRUE. + * + * Return value: %TRUE if the pan should continue, and %FALSE if + * the pan should be cancelled. + * + * Since: 1.12 + */ + pan_signals[PAN] = + g_signal_new (I_("pan"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterPanActionClass, pan), + _clutter_boolean_continue_accumulator, NULL, + _clutter_marshal_BOOLEAN__OBJECT_BOOLEAN, + G_TYPE_BOOLEAN, 2, + CLUTTER_TYPE_ACTOR, + G_TYPE_BOOLEAN); + + /** + * ClutterPanAction::pan-stopped: + * @action: the #ClutterPanAction that emitted the signal + * @actor: the #ClutterActor attached to the @action + * + * The ::pan-stopped signal is emitted at the end of the interpolation + * phase of the pan action, only when :interpolate is set to %TRUE. + * + * Since: 1.12 + */ + pan_signals[PAN_STOPPED] = + g_signal_new (I_("pan-stopped"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterPanActionClass, pan_stopped), + NULL, NULL, + _clutter_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CLUTTER_TYPE_ACTOR); +} + +static void +clutter_pan_action_init (ClutterPanAction *self) +{ + self->priv = clutter_pan_action_get_instance_private (self); + self->priv->deceleration_rate = default_deceleration_rate; + self->priv->acceleration_factor = default_acceleration_factor; + self->priv->state = PAN_STATE_INACTIVE; +} + +/** + * clutter_pan_action_new: + * + * Creates a new #ClutterPanAction instance + * + * Return value: the newly created #ClutterPanAction + * + * Since: 1.12 + */ +ClutterAction * +clutter_pan_action_new (void) +{ + return g_object_new (CLUTTER_TYPE_PAN_ACTION, NULL); +} + +/** + * clutter_pan_action_set_pan_axis: + * @self: a #ClutterPanAction + * @axis: the axis to constraint the panning to + * + * Restricts the panning action to a specific axis + * + * Since: 1.12 + */ +void +clutter_pan_action_set_pan_axis (ClutterPanAction *self, + ClutterPanAxis axis) +{ + ClutterPanActionPrivate *priv; + + g_return_if_fail (CLUTTER_IS_PAN_ACTION (self)); + g_return_if_fail (axis >= CLUTTER_PAN_AXIS_NONE && + axis <= CLUTTER_PAN_AXIS_AUTO); + + priv = self->priv; + + if (priv->pan_axis == axis) + return; + + priv->pan_axis = axis; + + g_object_notify_by_pspec (G_OBJECT (self), pan_props[PROP_PAN_AXIS]); +} + +/** + * clutter_pan_action_get_pan_axis: + * @self: a #ClutterPanAction + * + * Retrieves the axis constraint set by clutter_pan_action_set_pan_axis() + * + * Return value: the axis constraint + * + * Since: 1.12 + */ +ClutterPanAxis +clutter_pan_action_get_pan_axis (ClutterPanAction *self) +{ + g_return_val_if_fail (CLUTTER_IS_PAN_ACTION (self), + CLUTTER_PAN_AXIS_NONE); + + return self->priv->pan_axis; +} + +/** + * clutter_pan_action_set_interpolate: + * @self: a #ClutterPanAction + * @should_interpolate: whether to enable interpolated pan events + * + * Sets whether the action should emit interpolated ::pan events + * after the drag has ended, to emulate the gesture kinetic inertia. + * + * Since: 1.12 + */ +void +clutter_pan_action_set_interpolate (ClutterPanAction *self, + gboolean should_interpolate) +{ + ClutterPanActionPrivate *priv; + + g_return_if_fail (CLUTTER_IS_PAN_ACTION (self)); + + priv = self->priv; + + should_interpolate = !!should_interpolate; + + if (priv->should_interpolate == should_interpolate) + return; + + priv->should_interpolate = should_interpolate; + + g_object_notify_by_pspec (G_OBJECT (self), pan_props[PROP_INTERPOLATE]); +} + +/** + * clutter_pan_action_get_interpolate: + * @self: a #ClutterPanAction + * + * Checks if the action should emit ::pan events even after releasing + * the pointer during a panning gesture, to emulate some kind of + * kinetic inertia. + * + * Return value: %TRUE if interpolated events emission is active. + * + * Since: 1.12 + */ +gboolean +clutter_pan_action_get_interpolate (ClutterPanAction *self) +{ + g_return_val_if_fail (CLUTTER_IS_PAN_ACTION (self), + FALSE); + + return self->priv->should_interpolate; +} + +/** + * clutter_pan_action_set_deceleration: + * @self: A #ClutterPanAction + * @rate: The deceleration rate + * + * Sets the deceleration rate of the interpolated ::pan events generated + * after a pan gesture. This is approximately the value that the momentum + * at the time of releasing the pointer is divided by every 60th of a second. + * + * Since: 1.12 + */ +void +clutter_pan_action_set_deceleration (ClutterPanAction *self, + gdouble rate) +{ + g_return_if_fail (CLUTTER_IS_PAN_ACTION (self)); + g_return_if_fail (rate <= 1.0); + g_return_if_fail (rate > 0.0); + + self->priv->deceleration_rate = rate; + g_object_notify_by_pspec (G_OBJECT (self), pan_props[PROP_DECELERATION]); +} + +/** + * clutter_pan_action_get_deceleration: + * @self: A #ClutterPanAction + * + * Retrieves the deceleration rate of interpolated ::pan events. + * + * Return value: The deceleration rate of the interpolated events. + * + * Since: 1.12 + */ +gdouble +clutter_pan_action_get_deceleration (ClutterPanAction *self) +{ + g_return_val_if_fail (CLUTTER_IS_PAN_ACTION (self), 0.95); + return self->priv->deceleration_rate; +} + +/** + * clutter_pan_action_set_acceleration_factor: + * @self: A #ClutterPanAction + * @factor: The acceleration factor + * + * Factor applied to the momentum velocity at the time of releasing the + * pointer when generating interpolated ::pan events. + * + * Since: 1.12 + */ +void +clutter_pan_action_set_acceleration_factor (ClutterPanAction *self, + gdouble factor) +{ + g_return_if_fail (CLUTTER_IS_PAN_ACTION (self)); + g_return_if_fail (factor >= 0.0); + + self->priv->acceleration_factor = factor; + g_object_notify_by_pspec (G_OBJECT (self), pan_props[PROP_ACCELERATION_FACTOR]); +} + +/** + * clutter_pan_action_get_acceleration_factor: + * @self: A #ClutterPanAction + * + * Retrieves the initial acceleration factor for interpolated ::pan events. + * + * Return value: The initial acceleration factor for interpolated events. + * + * Since: 1.12 + */ +gdouble +clutter_pan_action_get_acceleration_factor (ClutterPanAction *self) +{ + g_return_val_if_fail (CLUTTER_IS_PAN_ACTION (self), 1.0); + return self->priv->acceleration_factor; +} + +/** + * clutter_pan_action_get_interpolated_coords: + * @self: A #ClutterPanAction + * @interpolated_x: (out) (allow-none): return location for the latest + * interpolated event's X coordinate + * @interpolated_y: (out) (allow-none): return location for the latest + * interpolated event's Y coordinate + * + * Retrieves the coordinates, in stage space, of the latest interpolated + * event, analogous to clutter_gesture_action_get_motion_coords(). + * + * Since: 1.12 + */ +void +clutter_pan_action_get_interpolated_coords (ClutterPanAction *self, + gfloat *interpolated_x, + gfloat *interpolated_y) +{ + ClutterPanActionPrivate *priv; + + g_return_if_fail (CLUTTER_IS_PAN_ACTION (self)); + + priv = self->priv; + + if (interpolated_x) + *interpolated_x = priv->release_x + priv->interpolated_x; + + if (interpolated_y) + *interpolated_y = priv->release_y + priv->interpolated_y; +} + +/** + * clutter_pan_action_get_interpolated_delta: + * @self: A #ClutterPanAction + * @delta_x: (out) (allow-none): return location for the X delta since + * the latest interpolated event + * @delta_y: (out) (allow-none): return location for the Y delta since + * the latest interpolated event + * + * Retrieves the delta, in stage space, since the latest interpolated + * event, analogous to clutter_gesture_action_get_motion_delta(). + * + * Return value: the distance since the latest interpolated event + * + * Since: 1.12 + */ +gfloat +clutter_pan_action_get_interpolated_delta (ClutterPanAction *self, + gfloat *delta_x, + gfloat *delta_y) +{ + ClutterPanActionPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_PAN_ACTION (self), 0.0f); + + priv = self->priv; + + if (delta_x) + *delta_x = priv->dx; + + if (delta_y) + *delta_y = priv->dy; + + return sqrt ((priv->dx * priv->dx) + (priv->dy * priv->dy)); +} + +/** + * clutter_pan_action_get_constrained_motion_delta: + * @self: A #ClutterPanAction + * @point: the touch point index, with 0 being the first touch + * point received by the action + * @delta_x: (out) (optional): return location for the X delta + * @delta_y: (out) (optional): return location for the Y delta + * + * Retrieves the delta, in stage space, dependent on the current state + * of the #ClutterPanAction, and respecting the constraint specified by the + * #ClutterPanAction:pan-axis property. + * + * Return value: the distance since last motion event + * + * Since: 1.24 + */ +gfloat +clutter_pan_action_get_constrained_motion_delta (ClutterPanAction *self, + guint point, + gfloat *out_delta_x, + gfloat *out_delta_y) +{ + ClutterPanActionPrivate *priv; + gfloat delta_x = 0.f, delta_y = 0.f, distance; + + g_return_val_if_fail (CLUTTER_IS_PAN_ACTION (self), 0.0f); + + priv = self->priv; + + distance = clutter_pan_action_get_motion_delta (self, point, &delta_x, &delta_y); + + switch (priv->pan_axis) + { + case CLUTTER_PAN_AXIS_NONE: + break; + + case CLUTTER_PAN_AXIS_AUTO: + if (priv->pin_state == SCROLL_PINNED_VERTICAL) + delta_x = 0.0f; + else if (priv->pin_state == SCROLL_PINNED_HORIZONTAL) + delta_y = 0.0f; + break; + + case CLUTTER_PAN_X_AXIS: + delta_y = 0.0f; + break; + + case CLUTTER_PAN_Y_AXIS: + delta_x = 0.0f; + break; + } + + if (out_delta_x) + *out_delta_x = delta_x; + + if (out_delta_y) + *out_delta_y = delta_y; + + return distance; +} + +/** + * clutter_pan_action_get_motion_delta: + * @self: A #ClutterPanAction + * @point: the touch point index, with 0 being the first touch + * point received by the action + * @delta_x: (out) (allow-none): return location for the X delta + * @delta_y: (out) (allow-none): return location for the Y delta + * + * Retrieves the delta, in stage space, dependent on the current state + * of the #ClutterPanAction. If it is inactive, both fields will be + * set to 0. If it is panning by user action, the values will be equivalent + * to those returned by clutter_gesture_action_get_motion_delta(). + * If it is interpolating with some form of kinetic scrolling, the values + * will be equivalent to those returned by + * clutter_pan_action_get_interpolated_delta(). This is a convenience + * method designed to be used in replacement "pan" signal handlers. + * + * Since: 1.14 + */ +gfloat +clutter_pan_action_get_motion_delta (ClutterPanAction *self, + guint point, + gfloat *delta_x, + gfloat *delta_y) +{ + ClutterPanActionPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_PAN_ACTION (self), 0.0f); + + priv = self->priv; + + switch (priv->state) + { + case PAN_STATE_INACTIVE: + if (delta_x) + *delta_x = 0; + + if (delta_y) + *delta_y = 0; + + return 0; + case PAN_STATE_PANNING: + return clutter_gesture_action_get_motion_delta (CLUTTER_GESTURE_ACTION (self), + point, delta_x, delta_y); + case PAN_STATE_INTERPOLATING: + return clutter_pan_action_get_interpolated_delta (self, delta_x, delta_y); + default: + g_assert_not_reached (); + } +} + +/** + * clutter_pan_action_get_motion_coords: + * @self: A #ClutterPanAction + * @point: the touch point index, with 0 being the first touch + * point received by the action + * @motion_x: (out) (allow-none): return location for the X coordinate + * @motion_y: (out) (allow-none): return location for the Y coordinate + * + * Retrieves the coordinates, in stage space, dependent on the current state + * of the #ClutterPanAction. If it is inactive, both fields will be + * set to 0. If it is panning by user action, the values will be equivalent + * to those returned by clutter_gesture_action_get_motion_coords(). + * If it is interpolating with some form of kinetic scrolling, the values + * will be equivalent to those returned by + * clutter_pan_action_get_interpolated_coords(). This is a convenience + * method designed to be used in replacement "pan" signal handlers. + * + * Since: 1.14 + */ +void +clutter_pan_action_get_motion_coords (ClutterPanAction *self, + guint point, + gfloat *motion_x, + gfloat *motion_y) +{ + ClutterPanActionPrivate *priv; + + g_return_if_fail (CLUTTER_IS_PAN_ACTION (self)); + + priv = self->priv; + + switch (priv->state) + { + case PAN_STATE_INACTIVE: + if (motion_x) + *motion_x = 0; + + if (motion_y) + *motion_y = 0; + break; + case PAN_STATE_PANNING: + clutter_gesture_action_get_motion_coords (CLUTTER_GESTURE_ACTION (self), + point, motion_x, motion_y); + break; + case PAN_STATE_INTERPOLATING: + clutter_pan_action_get_interpolated_coords (self, motion_x, motion_y); + break; + default: + g_assert_not_reached (); + } +} diff --git a/clutter/clutter/clutter-pan-action.h b/clutter/clutter/clutter-pan-action.h new file mode 100644 index 0000000..866ec97 --- /dev/null +++ b/clutter/clutter/clutter-pan-action.h @@ -0,0 +1,152 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * Copyright (C) 2011 Robert Bosch Car Multimedia GmbH. + * Copyright (C) 2012 Collabora Ltd. + * + * 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 . + * + * Author: + * Emanuele Aina + * + * Based on ClutterDragAction, ClutterSwipeAction, and MxKineticScrollView, + * written by: + * Emmanuele Bassi + * Tomeu Vizoso + * Chris Lord + */ + +#ifndef __CLUTTER_PAN_ACTION_H__ +#define __CLUTTER_PAN_ACTION_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_PAN_ACTION (clutter_pan_action_get_type ()) +#define CLUTTER_PAN_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_PAN_ACTION, ClutterPanAction)) +#define CLUTTER_IS_PAN_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_PAN_ACTION)) +#define CLUTTER_PAN_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_PAN_ACTION, ClutterPanActionClass)) +#define CLUTTER_IS_PAN_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_PAN_ACTION)) +#define CLUTTER_PAN_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_PAN_ACTION, ClutterPanActionClass)) + +typedef struct _ClutterPanAction ClutterPanAction; +typedef struct _ClutterPanActionPrivate ClutterPanActionPrivate; +typedef struct _ClutterPanActionClass ClutterPanActionClass; + +/** + * ClutterPanAction: + * + * The #ClutterPanAction structure contains + * only private data and should be accessed using the provided API + * + * Since: 1.12 + */ +struct _ClutterPanAction +{ + /*< private >*/ + ClutterGestureAction parent_instance; + + ClutterPanActionPrivate *priv; +}; + +/** + * ClutterPanActionClass: + * @pan: class handler for the #ClutterPanAction::pan signal + * @pan_stopped: class handler for the #ClutterPanAction::pan-stopped signal + * + * The #ClutterPanActionClass structure contains + * only private data. + * + * Since: 1.12 + */ +struct _ClutterPanActionClass +{ + /*< private >*/ + ClutterGestureActionClass parent_class; + + /*< public >*/ + gboolean (* pan) (ClutterPanAction *action, + ClutterActor *actor, + gboolean is_interpolated); + void (* pan_stopped) (ClutterPanAction *action, + ClutterActor *actor); + + /*< private >*/ + void (* _clutter_pan_action1) (void); + void (* _clutter_pan_action2) (void); + void (* _clutter_pan_action3) (void); + void (* _clutter_pan_action4) (void); + void (* _clutter_pan_action5) (void); + void (* _clutter_pan_action6) (void); +}; + +CLUTTER_AVAILABLE_IN_1_12 +GType clutter_pan_action_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_12 +ClutterAction * clutter_pan_action_new (void); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_pan_action_set_pan_axis (ClutterPanAction *self, + ClutterPanAxis axis); +CLUTTER_AVAILABLE_IN_1_12 +ClutterPanAxis clutter_pan_action_get_pan_axis (ClutterPanAction *self); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_pan_action_set_interpolate (ClutterPanAction *self, + gboolean should_interpolate); +CLUTTER_AVAILABLE_IN_1_12 +gboolean clutter_pan_action_get_interpolate (ClutterPanAction *self); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_pan_action_set_deceleration (ClutterPanAction *self, + gdouble rate); +CLUTTER_AVAILABLE_IN_1_12 +gdouble clutter_pan_action_get_deceleration (ClutterPanAction *self); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_pan_action_set_acceleration_factor (ClutterPanAction *self, + gdouble factor); +CLUTTER_AVAILABLE_IN_1_12 +gdouble clutter_pan_action_get_acceleration_factor (ClutterPanAction *self); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_pan_action_get_interpolated_coords (ClutterPanAction *self, + gfloat *interpolated_x, + gfloat *interpolated_y); +CLUTTER_AVAILABLE_IN_1_12 +gfloat clutter_pan_action_get_interpolated_delta (ClutterPanAction *self, + gfloat *delta_x, + gfloat *delta_y); +CLUTTER_AVAILABLE_IN_1_14 +gfloat clutter_pan_action_get_motion_delta (ClutterPanAction *self, + guint point, + gfloat *delta_x, + gfloat *delta_y); +CLUTTER_AVAILABLE_IN_1_14 +void clutter_pan_action_get_motion_coords (ClutterPanAction *self, + guint point, + gfloat *motion_x, + gfloat *motion_y); +CLUTTER_AVAILABLE_IN_1_24 +gfloat clutter_pan_action_get_constrained_motion_delta (ClutterPanAction *self, + guint point, + gfloat *delta_x, + gfloat *delta_y); +G_END_DECLS + +#endif /* __CLUTTER_PAN_ACTION_H__ */ diff --git a/clutter/clutter/clutter-path-constraint.c b/clutter/clutter/clutter-path-constraint.c new file mode 100644 index 0000000..fc9720b --- /dev/null +++ b/clutter/clutter/clutter-path-constraint.c @@ -0,0 +1,396 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-path-constraint + * @Title: ClutterPathConstraint + * @Short_Description: A constraint that follows a path + * + * #ClutterPathConstraint is a simple constraint that modifies the allocation + * of the #ClutterActor to which it has been applied using a #ClutterPath. + * + * By setting the #ClutterPathConstraint:offset property it is possible to + * control how far along the path the #ClutterActor should be. + * + * ClutterPathConstraint is available since Clutter 1.6. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-path-constraint.h" + +#include "clutter-debug.h" +#include "clutter-marshal.h" +#include "clutter-private.h" + +#define CLUTTER_PATH_CONSTRAINT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_PATH_CONSTRAINT, ClutterPathConstraintClass)) +#define CLUTTER_IS_PATH_CONSTRAINT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_PATH_CONSTRAINT)) +#define CLUTTER_PATH_CONSTRAINT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_PATH_CONSTRAINT, ClutterPathConstraintClass)) + +struct _ClutterPathConstraint +{ + ClutterConstraint parent_instance; + + ClutterPath *path; + + gfloat offset; + + ClutterActor *actor; + + guint current_node; +}; + +struct _ClutterPathConstraintClass +{ + ClutterConstraintClass parent_class; +}; + +enum +{ + PROP_0, + + PROP_PATH, + PROP_OFFSET, + + LAST_PROPERTY +}; + +enum +{ + NODE_REACHED, + + LAST_SIGNAL +}; + +G_DEFINE_TYPE (ClutterPathConstraint, clutter_path_constraint, CLUTTER_TYPE_CONSTRAINT); + +static GParamSpec *path_properties[LAST_PROPERTY] = { NULL, }; +static guint path_signals[LAST_SIGNAL] = { 0, }; + +static void +clutter_path_constraint_update_allocation (ClutterConstraint *constraint, + ClutterActor *actor, + ClutterActorBox *allocation) +{ + ClutterPathConstraint *self = CLUTTER_PATH_CONSTRAINT (constraint); + gfloat width, height; + ClutterKnot position; + guint knot_id; + + if (self->path == NULL) + return; + + knot_id = clutter_path_get_position (self->path, self->offset, &position); + clutter_actor_box_get_size (allocation, &width, &height); + allocation->x1 = position.x; + allocation->y1 = position.y; + allocation->x2 = allocation->x1 + width; + allocation->y2 = allocation->y1 + height; + + if (knot_id != self->current_node) + { + self->current_node = knot_id; + g_signal_emit (self, path_signals[NODE_REACHED], 0, + self->actor, + self->current_node); + } +} + +static void +clutter_path_constraint_set_actor (ClutterActorMeta *meta, + ClutterActor *new_actor) +{ + ClutterPathConstraint *path = CLUTTER_PATH_CONSTRAINT (meta); + ClutterActorMetaClass *parent; + + /* store the pointer to the actor, for later use */ + path->actor = new_actor; + + parent = CLUTTER_ACTOR_META_CLASS (clutter_path_constraint_parent_class); + parent->set_actor (meta, new_actor); +} + +static void +clutter_path_constraint_dispose (GObject *gobject) +{ + ClutterPathConstraint *self = CLUTTER_PATH_CONSTRAINT (gobject); + + if (self->path != NULL) + { + g_object_unref (self->path); + self->path = NULL; + } + + G_OBJECT_CLASS (clutter_path_constraint_parent_class)->dispose (gobject); +} + +static void +clutter_path_constraint_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterPathConstraint *self = CLUTTER_PATH_CONSTRAINT (gobject); + + switch (prop_id) + { + case PROP_PATH: + clutter_path_constraint_set_path (self, g_value_get_object (value)); + break; + + case PROP_OFFSET: + clutter_path_constraint_set_offset (self, g_value_get_float (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + } +} + +static void +clutter_path_constraint_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterPathConstraint *self = CLUTTER_PATH_CONSTRAINT (gobject); + + switch (prop_id) + { + case PROP_PATH: + g_value_set_object (value, self->path); + break; + + case PROP_OFFSET: + g_value_set_float (value, self->offset); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + } +} + +static void +clutter_path_constraint_class_init (ClutterPathConstraintClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass); + ClutterConstraintClass *constraint_class = CLUTTER_CONSTRAINT_CLASS (klass); + + /** + * ClutterPathConstraint:path: + * + * The #ClutterPath used to constrain the position of an actor. + * + * Since: 1.6 + */ + path_properties[PROP_PATH] = + g_param_spec_object ("path", + P_("Path"), + P_("The path used to constrain an actor"), + CLUTTER_TYPE_PATH, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterPathConstraint:offset: + * + * The offset along the #ClutterPathConstraint:path, between -1.0 and 2.0. + * + * Since: 1.6 + */ + path_properties[PROP_OFFSET] = + g_param_spec_float ("offset", + P_("Offset"), + P_("The offset along the path, between -1.0 and 2.0"), + -1.0, 2.0, + 0.0, + CLUTTER_PARAM_READWRITE); + + gobject_class->set_property = clutter_path_constraint_set_property; + gobject_class->get_property = clutter_path_constraint_get_property; + gobject_class->dispose = clutter_path_constraint_dispose; + g_object_class_install_properties (gobject_class, + LAST_PROPERTY, + path_properties); + + meta_class->set_actor = clutter_path_constraint_set_actor; + + constraint_class->update_allocation = clutter_path_constraint_update_allocation; + + /** + * ClutterPathConstraint::node-reached: + * @constraint: the #ClutterPathConstraint that emitted the signal + * @actor: the #ClutterActor using the @constraint + * @index: the index of the node that has been reached + * + * The ::node-reached signal is emitted each time a + * #ClutterPathConstraint:offset value results in the actor + * passing a #ClutterPathNode + * + * Since: 1.6 + */ + path_signals[NODE_REACHED] = + g_signal_new (I_("node-reached"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + _clutter_marshal_VOID__OBJECT_UINT, + G_TYPE_NONE, 2, + CLUTTER_TYPE_ACTOR, + G_TYPE_UINT); +} + +static void +clutter_path_constraint_init (ClutterPathConstraint *self) +{ + self->offset = 0.0f; + self->current_node = G_MAXUINT; +} + +/** + * clutter_path_constraint_new: + * @path: (allow-none): a #ClutterPath, or %NULL + * @offset: the offset along the #ClutterPath + * + * Creates a new #ClutterPathConstraint with the given @path and @offset + * + * Return value: the newly created #ClutterPathConstraint + * + * Since: 1.6 + */ +ClutterConstraint * +clutter_path_constraint_new (ClutterPath *path, + gfloat offset) +{ + g_return_val_if_fail (path == NULL || CLUTTER_IS_PATH (path), NULL); + + return g_object_new (CLUTTER_TYPE_PATH_CONSTRAINT, + "path", path, + "offset", offset, + NULL); +} + +/** + * clutter_path_constraint_set_path: + * @constraint: a #ClutterPathConstraint + * @path: (allow-none): a #ClutterPath + * + * Sets the @path to be followed by the #ClutterPathConstraint. + * + * The @constraint will take ownership of the #ClutterPath passed to this + * function. + * + * Since: 1.6 + */ +void +clutter_path_constraint_set_path (ClutterPathConstraint *constraint, + ClutterPath *path) +{ + g_return_if_fail (CLUTTER_IS_PATH_CONSTRAINT (constraint)); + g_return_if_fail (path == NULL || CLUTTER_IS_PATH (path)); + + if (constraint->path == path) + return; + + if (constraint->path != NULL) + { + g_object_unref (constraint->path); + constraint->path = NULL; + } + + if (path != NULL) + constraint->path = g_object_ref_sink (path); + + if (constraint->actor != NULL) + clutter_actor_queue_relayout (constraint->actor); + + g_object_notify_by_pspec (G_OBJECT (constraint), path_properties[PROP_PATH]); +} + +/** + * clutter_path_constraint_get_path: + * @constraint: a #ClutterPathConstraint + * + * Retrieves a pointer to the #ClutterPath used by @constraint. + * + * Return value: (transfer none): the #ClutterPath used by the + * #ClutterPathConstraint, or %NULL. The returned #ClutterPath is owned + * by the constraint and it should not be unreferenced + * + * Since: 1.6 + */ +ClutterPath * +clutter_path_constraint_get_path (ClutterPathConstraint *constraint) +{ + g_return_val_if_fail (CLUTTER_IS_PATH_CONSTRAINT (constraint), NULL); + + return constraint->path; +} + +/** + * clutter_path_constraint_set_offset: + * @constraint: a #ClutterPathConstraint + * @offset: the offset along the path + * + * Sets the offset along the #ClutterPath used by @constraint. + * + * Since: 1.6 + */ +void +clutter_path_constraint_set_offset (ClutterPathConstraint *constraint, + gfloat offset) +{ + g_return_if_fail (CLUTTER_IS_PATH_CONSTRAINT (constraint)); + + if (constraint->offset == offset) + return; + + constraint->offset = offset; + + if (constraint->actor != NULL) + clutter_actor_queue_relayout (constraint->actor); + + g_object_notify_by_pspec (G_OBJECT (constraint), path_properties[PROP_OFFSET]); +} + +/** + * clutter_path_constraint_get_offset: + * @constraint: a #ClutterPathConstraint + * + * Retrieves the offset along the #ClutterPath used by @constraint. + * + * Return value: the offset + * + * Since: 1.6 + */ +gfloat +clutter_path_constraint_get_offset (ClutterPathConstraint *constraint) +{ + g_return_val_if_fail (CLUTTER_IS_PATH_CONSTRAINT (constraint), 0.0); + + return constraint->offset; +} diff --git a/clutter/clutter/clutter-path-constraint.h b/clutter/clutter/clutter-path-constraint.h new file mode 100644 index 0000000..f6d65ea --- /dev/null +++ b/clutter/clutter/clutter-path-constraint.h @@ -0,0 +1,72 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_PATH_CONSTRAINT_H__ +#define __CLUTTER_PATH_CONSTRAINT_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_PATH_CONSTRAINT (clutter_path_constraint_get_type ()) +#define CLUTTER_PATH_CONSTRAINT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_PATH_CONSTRAINT, ClutterPathConstraint)) +#define CLUTTER_IS_PATH_CONSTRAINT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_PATH_CONSTRAINT)) + +/** + * ClutterPathConstraint: + * + * #ClutterPathConstraint is an opaque structure + * whose members cannot be directly accessed + * + * Since: 1.6 + */ +typedef struct _ClutterPathConstraint ClutterPathConstraint; +typedef struct _ClutterPathConstraintClass ClutterPathConstraintClass; + +CLUTTER_AVAILABLE_IN_1_6 +GType clutter_path_constraint_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_6 +ClutterConstraint *clutter_path_constraint_new (ClutterPath *path, + gfloat offset); + +CLUTTER_AVAILABLE_IN_1_6 +void clutter_path_constraint_set_path (ClutterPathConstraint *constraint, + ClutterPath *path); +CLUTTER_AVAILABLE_IN_1_6 +ClutterPath * clutter_path_constraint_get_path (ClutterPathConstraint *constraint); +CLUTTER_AVAILABLE_IN_1_6 +void clutter_path_constraint_set_offset (ClutterPathConstraint *constraint, + gfloat offset); +CLUTTER_AVAILABLE_IN_1_6 +gfloat clutter_path_constraint_get_offset (ClutterPathConstraint *constraint); + +G_END_DECLS + +#endif /* __CLUTTER_PATH_CONSTRAINT_H__ */ diff --git a/clutter/clutter/clutter-path.c b/clutter/clutter/clutter-path.c new file mode 100644 index 0000000..5f8763a --- /dev/null +++ b/clutter/clutter/clutter-path.c @@ -0,0 +1,1604 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2008 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 . + */ + +/** + * SECTION:clutter-path + * @short_description: An object describing a path with straight lines + * and bezier curves. + * + * A #ClutterPath contains a description of a path consisting of + * straight lines and bezier curves. This can be used in a + * #ClutterBehaviourPath to animate an actor moving along the path. + * + * The path consists of a series of nodes. Each node is one of the + * following four types: + * + * - %CLUTTER_PATH_MOVE_TO, changes the position of the path to the + * given pair of coordinates. This is usually used as the first node + * of a path to mark the start position. If it is used in the middle + * of a path then the path will be disjoint and the actor will appear + * to jump to the new position when animated. + * - %CLUTTER_PATH_LINE_TO, creates a straight line from the previous + * point to the given point. + * - %CLUTTER_PATH_CURVE_TO, creates a bezier curve. The end of the + * last node is used as the first control point and the three + * subsequent coordinates given in the node as used as the other three. + * -%CLUTTER_PATH_CLOSE, creates a straight line from the last node to + * the last %CLUTTER_PATH_MOVE_TO node. This can be used to close a + * path so that it will appear as a loop when animated. + * + * The first three types have the corresponding relative versions + * %CLUTTER_PATH_REL_MOVE_TO, %CLUTTER_PATH_REL_LINE_TO and + * %CLUTTER_PATH_REL_CURVE_TO. These are exactly the same except the + * coordinates are given relative to the previous node instead of as + * direct screen positions. + * + * You can build a path using the node adding functions such as + * clutter_path_add_line_to(). Alternatively the path can be described + * in a string using a subset of the SVG path syntax. See + * clutter_path_add_string() for details. + * + * #ClutterPath is available since Clutter 1.0 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include +#include +#include +#include + +#include "clutter-path.h" +#include "clutter-types.h" +#include "clutter-bezier.h" +#include "clutter-private.h" + +#define CLUTTER_PATH_NODE_TYPE_IS_VALID(t) \ + ((((t) & ~CLUTTER_PATH_RELATIVE) >= CLUTTER_PATH_MOVE_TO \ + && ((t) & ~CLUTTER_PATH_RELATIVE) <= CLUTTER_PATH_CURVE_TO) \ + || (t) == CLUTTER_PATH_CLOSE) + +enum +{ + PROP_0, + + PROP_DESCRIPTION, + PROP_LENGTH, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +typedef struct _ClutterPathNodeFull ClutterPathNodeFull; + +struct _ClutterPathNodeFull +{ + ClutterPathNode k; + + ClutterBezier *bezier; + + guint length; +}; + +struct _ClutterPathPrivate +{ + GSList *nodes, *nodes_tail; + gboolean nodes_dirty; + + guint total_length; +}; + +/* Character tests that don't pay attention to the locale */ +#define clutter_path_isspace(ch) memchr (" \f\n\r\t\v", (ch), 6) +#define clutter_path_isdigit(ch) ((ch) >= '0' && (ch) <= '9') + +static ClutterPathNodeFull *clutter_path_node_full_new (void); +static void clutter_path_node_full_free (ClutterPathNodeFull *node); + +static void clutter_path_finalize (GObject *object); + +static void clutter_value_transform_path_string (const GValue *src, + GValue *dest); +static void clutter_value_transform_string_path (const GValue *src, + GValue *dest); + +G_DEFINE_BOXED_TYPE (ClutterPathNode, clutter_path_node, + clutter_path_node_copy, + clutter_path_node_free); + +G_DEFINE_TYPE_WITH_CODE (ClutterPath, + clutter_path, + G_TYPE_INITIALLY_UNOWNED, + G_ADD_PRIVATE (ClutterPath) + CLUTTER_REGISTER_VALUE_TRANSFORM_TO (G_TYPE_STRING, clutter_value_transform_path_string) + CLUTTER_REGISTER_VALUE_TRANSFORM_FROM (G_TYPE_STRING, clutter_value_transform_string_path)); + +static void +clutter_path_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterPath *path = CLUTTER_PATH (gobject); + + switch (prop_id) + { + case PROP_DESCRIPTION: + g_value_take_string (value, clutter_path_get_description (path)); + break; + case PROP_LENGTH: + g_value_set_uint (value, clutter_path_get_length (path)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_path_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterPath *path = CLUTTER_PATH (gobject); + + switch (prop_id) + { + case PROP_DESCRIPTION: + if (!clutter_path_set_description (path, g_value_get_string (value))) + g_warning ("Invalid path description"); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_path_class_init (ClutterPathClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GParamSpec *pspec; + + gobject_class->get_property = clutter_path_get_property; + gobject_class->set_property = clutter_path_set_property; + gobject_class->finalize = clutter_path_finalize; + + pspec = g_param_spec_string ("description", + "Description", + "SVG-style description of the path", + "", + CLUTTER_PARAM_READWRITE); + obj_props[PROP_DESCRIPTION] = pspec; + g_object_class_install_property (gobject_class, PROP_DESCRIPTION, pspec); + + pspec = g_param_spec_uint ("length", + "Length", + "An approximation of the total length " + "of the path.", + 0, G_MAXUINT, 0, + CLUTTER_PARAM_READABLE); + obj_props[PROP_LENGTH] = pspec; + g_object_class_install_property (gobject_class, PROP_LENGTH, pspec); +} + +static void +clutter_path_init (ClutterPath *self) +{ + self->priv = clutter_path_get_instance_private (self); +} + +static void +clutter_value_transform_path_string (const GValue *src, + GValue *dest) +{ + gchar *string = clutter_path_get_description (src->data[0].v_pointer); + + g_value_take_string (dest, string); +} + +static void +clutter_value_transform_string_path (const GValue *src, + GValue *dest) +{ + ClutterPath *new_path; + + new_path = clutter_path_new_with_description (g_value_get_string (src)); + g_value_take_object (dest, new_path); +} + +static void +clutter_path_finalize (GObject *object) +{ + ClutterPath *self = (ClutterPath *) object; + + clutter_path_clear (self); + + G_OBJECT_CLASS (clutter_path_parent_class)->finalize (object); +} + +/** + * clutter_path_new: + * + * Creates a new #ClutterPath instance with no nodes. + * + * The object has a floating reference so if you add it to a + * #ClutterBehaviourPath then you do not need to unref it. + * + * Return value: the newly created #ClutterPath + * + * Since: 1.0 + */ +ClutterPath * +clutter_path_new (void) +{ + ClutterPath *self = g_object_new (CLUTTER_TYPE_PATH, NULL); + + return self; +} + +/** + * clutter_path_new_with_description: + * @desc: a string describing the path + * + * Creates a new #ClutterPath instance with the nodes described in + * @desc. See clutter_path_add_string() for details of the format of + * the string. + * + * The object has a floating reference so if you add it to a + * #ClutterBehaviourPath then you do not need to unref it. + * + * Return value: the newly created #ClutterPath + * + * Since: 1.0 + */ +ClutterPath * +clutter_path_new_with_description (const gchar *desc) +{ + return g_object_new (CLUTTER_TYPE_PATH, + "description", desc, + NULL); +} + +/** + * clutter_path_clear: + * @path: a #ClutterPath + * + * Removes all nodes from the path. + * + * Since: 1.0 + */ +void +clutter_path_clear (ClutterPath *path) +{ + ClutterPathPrivate *priv = path->priv; + + g_slist_foreach (priv->nodes, (GFunc) clutter_path_node_full_free, NULL); + g_slist_free (priv->nodes); + + priv->nodes = priv->nodes_tail = NULL; + priv->nodes_dirty = TRUE; +} + +/* Takes ownership of the node */ +static void +clutter_path_add_node_full (ClutterPath *path, + ClutterPathNodeFull *node) +{ + ClutterPathPrivate *priv = path->priv; + GSList *new_node; + + new_node = g_slist_prepend (NULL, node); + + if (priv->nodes_tail == NULL) + priv->nodes = new_node; + else + priv->nodes_tail->next = new_node; + + priv->nodes_tail = new_node; + + priv->nodes_dirty = TRUE; +} + +/* Helper function to make the rest of teh add_* functions shorter */ +static void +clutter_path_add_node_helper (ClutterPath *path, + ClutterPathNodeType type, + int num_coords, + ...) +{ + ClutterPathNodeFull *node; + int i; + va_list ap; + + node = clutter_path_node_full_new (); + + node->k.type = type; + + va_start (ap, num_coords); + + for (i = 0; i < num_coords; i++) + { + node->k.points[i].x = va_arg (ap, gint); + node->k.points[i].y = va_arg (ap, gint); + } + + va_end (ap); + + clutter_path_add_node_full (path, node); +} + +/** + * clutter_path_add_move_to: + * @path: a #ClutterPath + * @x: the x coordinate + * @y: the y coordinate + * + * Adds a %CLUTTER_PATH_MOVE_TO type node to the path. This is usually + * used as the first node in a path. It can also be used in the middle + * of the path to cause the actor to jump to the new coordinate. + * + * Since: 1.0 + */ +void +clutter_path_add_move_to (ClutterPath *path, + gint x, + gint y) +{ + g_return_if_fail (CLUTTER_IS_PATH (path)); + + clutter_path_add_node_helper (path, CLUTTER_PATH_MOVE_TO, 1, x, y); +} + +/** + * clutter_path_add_rel_move_to: + * @path: a #ClutterPath + * @x: the x coordinate + * @y: the y coordinate + * + * Same as clutter_path_add_move_to() except the coordinates are + * relative to the previous node. + * + * Since: 1.0 + */ +void +clutter_path_add_rel_move_to (ClutterPath *path, + gint x, + gint y) +{ + g_return_if_fail (CLUTTER_IS_PATH (path)); + + clutter_path_add_node_helper (path, CLUTTER_PATH_REL_MOVE_TO, 1, x, y); +} + +/** + * clutter_path_add_line_to: + * @path: a #ClutterPath + * @x: the x coordinate + * @y: the y coordinate + * + * Adds a %CLUTTER_PATH_LINE_TO type node to the path. This causes the + * actor to move to the new coordinates in a straight line. + * + * Since: 1.0 + */ +void +clutter_path_add_line_to (ClutterPath *path, + gint x, + gint y) +{ + g_return_if_fail (CLUTTER_IS_PATH (path)); + + clutter_path_add_node_helper (path, CLUTTER_PATH_LINE_TO, 1, x, y); +} + +/** + * clutter_path_add_rel_line_to: + * @path: a #ClutterPath + * @x: the x coordinate + * @y: the y coordinate + * + * Same as clutter_path_add_line_to() except the coordinates are + * relative to the previous node. + * + * Since: 1.0 + */ +void +clutter_path_add_rel_line_to (ClutterPath *path, + gint x, + gint y) +{ + g_return_if_fail (CLUTTER_IS_PATH (path)); + + clutter_path_add_node_helper (path, CLUTTER_PATH_REL_LINE_TO, 1, x, y); +} + +/** + * clutter_path_add_curve_to: + * @path: a #ClutterPath + * @x_1: the x coordinate of the first control point + * @y_1: the y coordinate of the first control point + * @x_2: the x coordinate of the second control point + * @y_2: the y coordinate of the second control point + * @x_3: the x coordinate of the third control point + * @y_3: the y coordinate of the third control point + * + * Adds a %CLUTTER_PATH_CURVE_TO type node to the path. This causes + * the actor to follow a bezier from the last node to (@x_3, @y_3) using + * (@x_1, @y_1) and (@x_2,@y_2) as control points. + * + * Since: 1.0 + */ +void +clutter_path_add_curve_to (ClutterPath *path, + gint x_1, + gint y_1, + gint x_2, + gint y_2, + gint x_3, + gint y_3) +{ + g_return_if_fail (CLUTTER_IS_PATH (path)); + + clutter_path_add_node_helper (path, CLUTTER_PATH_CURVE_TO, 3, + x_1, y_1, + x_2, y_2, + x_3, y_3); +} + +/** + * clutter_path_add_rel_curve_to: + * @path: a #ClutterPath + * @x_1: the x coordinate of the first control point + * @y_1: the y coordinate of the first control point + * @x_2: the x coordinate of the second control point + * @y_2: the y coordinate of the second control point + * @x_3: the x coordinate of the third control point + * @y_3: the y coordinate of the third control point + * + * Same as clutter_path_add_curve_to() except the coordinates are + * relative to the previous node. + * + * Since: 1.0 + */ +void +clutter_path_add_rel_curve_to (ClutterPath *path, + gint x_1, + gint y_1, + gint x_2, + gint y_2, + gint x_3, + gint y_3) +{ + g_return_if_fail (CLUTTER_IS_PATH (path)); + + clutter_path_add_node_helper (path, CLUTTER_PATH_REL_CURVE_TO, 3, + x_1, y_1, + x_2, y_2, + x_3, y_3); +} + +/** + * clutter_path_add_close: + * @path: a #ClutterPath + * + * Adds a %CLUTTER_PATH_CLOSE type node to the path. This creates a + * straight line from the last node to the last %CLUTTER_PATH_MOVE_TO + * type node. + * + * Since: 1.0 + */ +void +clutter_path_add_close (ClutterPath *path) +{ + g_return_if_fail (CLUTTER_IS_PATH (path)); + + clutter_path_add_node_helper (path, CLUTTER_PATH_CLOSE, 0); +} + +static gboolean +clutter_path_parse_number (const gchar **pin, + gboolean allow_comma, + gint *ret) +{ + gint val = 0; + gboolean negative = FALSE; + gint digit_count = 0; + const gchar *p = *pin; + + /* Skip leading spaces */ + while (clutter_path_isspace (*p)) + p++; + + /* Optional comma */ + if (allow_comma && *p == ',') + { + p++; + while (clutter_path_isspace (*p)) + p++; + } + + /* Optional sign */ + if (*p == '+') + p++; + else if (*p == '-') + { + negative = TRUE; + p++; + } + + /* Some digits */ + while (clutter_path_isdigit (*p)) + { + val = val * 10 + *p - '0'; + digit_count++; + p++; + } + + /* We need at least one digit */ + if (digit_count < 1) + return FALSE; + + /* Optional fractional part which we ignore */ + if (*p == '.') + { + p++; + digit_count = 0; + while (clutter_path_isdigit (*p)) + { + digit_count++; + p++; + } + /* If there is a fractional part then it also needs at least one + digit */ + if (digit_count < 1) + return FALSE; + } + + *pin = p; + *ret = negative ? -val : val; + + return TRUE; +} + +static gboolean +clutter_path_parse_description (const gchar *p, + GSList **ret) +{ + ClutterPathNodeFull *node; + GSList *nodes = NULL; + + if (p == NULL || *p == '\0') + return FALSE; + + while (TRUE) + { + /* Skip leading whitespace */ + while (clutter_path_isspace (*p)) + p++; + + /* It is not an error to end now */ + if (*p == '\0') + break; + + switch (*p) + { + case 'M': + case 'm': + case 'L': + case 'l': + node = clutter_path_node_full_new (); + nodes = g_slist_prepend (nodes, node); + + node->k.type = (*p == 'M' ? CLUTTER_PATH_MOVE_TO : + *p == 'm' ? CLUTTER_PATH_REL_MOVE_TO : + *p == 'L' ? CLUTTER_PATH_LINE_TO : + CLUTTER_PATH_REL_LINE_TO); + p++; + + if (!clutter_path_parse_number (&p, FALSE, &node->k.points[0].x) || + !clutter_path_parse_number (&p, TRUE, &node->k.points[0].y)) + goto fail; + break; + + case 'C': + case 'c': + node = clutter_path_node_full_new (); + nodes = g_slist_prepend (nodes, node); + + node->k.type = (*p == 'C' ? CLUTTER_PATH_CURVE_TO : + CLUTTER_PATH_REL_CURVE_TO); + p++; + + if (!clutter_path_parse_number (&p, FALSE, &node->k.points[0].x) || + !clutter_path_parse_number (&p, TRUE, &node->k.points[0].y) || + !clutter_path_parse_number (&p, TRUE, &node->k.points[1].x) || + !clutter_path_parse_number (&p, TRUE, &node->k.points[1].y) || + !clutter_path_parse_number (&p, TRUE, &node->k.points[2].x) || + !clutter_path_parse_number (&p, TRUE, &node->k.points[2].y)) + goto fail; + break; + + case 'Z': + case 'z': + node = clutter_path_node_full_new (); + nodes = g_slist_prepend (nodes, node); + p++; + + node->k.type = CLUTTER_PATH_CLOSE; + break; + + default: + goto fail; + } + } + + *ret = g_slist_reverse (nodes); + return TRUE; + + fail: + g_slist_foreach (nodes, (GFunc) clutter_path_node_full_free, NULL); + g_slist_free (nodes); + return FALSE; +} + +/* Takes ownership of the node list */ +static void +clutter_path_add_nodes (ClutterPath *path, + GSList *nodes) +{ + ClutterPathPrivate *priv = path->priv; + + if (priv->nodes_tail == NULL) + priv->nodes = nodes; + else + priv->nodes_tail->next = nodes; + + while (nodes) + { + priv->nodes_tail = nodes; + nodes = nodes->next; + } + + priv->nodes_dirty = TRUE; +} + +/** + * clutter_path_add_string: + * @path: a #ClutterPath + * @str: a string describing the new nodes + * + * Adds new nodes to the end of the path as described in @str. The + * format is a subset of the SVG path format. Each node is represented + * by a letter and is followed by zero, one or three pairs of + * coordinates. The coordinates can be separated by spaces or a + * comma. The types are: + * + * - `M`: Adds a %CLUTTER_PATH_MOVE_TO node. Takes one pair of coordinates. + * - `L`: Adds a %CLUTTER_PATH_LINE_TO node. Takes one pair of coordinates. + * - `C`: Adds a %CLUTTER_PATH_CURVE_TO node. Takes three pairs of coordinates. + * - `z`: Adds a %CLUTTER_PATH_CLOSE node. No coordinates are needed. + * + * The M, L and C commands can also be specified in lower case which + * means the coordinates are relative to the previous node. + * + * For example, to move an actor in a 100 by 100 pixel square centered + * on the point 300,300 you could use the following path: + * + * |[ + * M 250,350 l 0 -100 L 350,250 l 0 100 z + * ]| + * + * If the path description isn't valid %FALSE will be returned and no + * nodes will be added. + * + * Return value: %TRUE is the path description was valid or %FALSE + * otherwise. + * + * Since: 1.0 + */ +gboolean +clutter_path_add_string (ClutterPath *path, + const gchar *str) +{ + GSList *nodes; + + g_return_val_if_fail (CLUTTER_IS_PATH (path), FALSE); + g_return_val_if_fail (str != NULL, FALSE); + + if (clutter_path_parse_description (str, &nodes)) + { + clutter_path_add_nodes (path, nodes); + + return TRUE; + } + else + return FALSE; +} + +/** + * clutter_path_add_node: + * @path: a #ClutterPath + * @node: a #ClutterPathNode + * + * Adds @node to the end of the path. + * + * Since: 1.0 + */ +void +clutter_path_add_node (ClutterPath *path, + const ClutterPathNode *node) +{ + ClutterPathNodeFull *node_full; + + g_return_if_fail (CLUTTER_IS_PATH (path)); + g_return_if_fail (node != NULL); + g_return_if_fail (CLUTTER_PATH_NODE_TYPE_IS_VALID (node->type)); + + node_full = clutter_path_node_full_new (); + node_full->k = *node; + + clutter_path_add_node_full (path, node_full); +} + +/** + * clutter_path_add_cairo_path: + * @path: a #ClutterPath + * @cpath: a Cairo path + * + * Add the nodes of the Cairo path to the end of @path. + * + * Since: 1.0 + */ +void +clutter_path_add_cairo_path (ClutterPath *path, + const cairo_path_t *cpath) +{ + int num_data; + const cairo_path_data_t *p; + + g_return_if_fail (CLUTTER_IS_PATH (path)); + g_return_if_fail (cpath != NULL); + + /* Iterate over each command in the cairo path */ + for (num_data = cpath->num_data, p = cpath->data; + num_data > 0; + num_data -= p->header.length, p += p->header.length) + { + switch (p->header.type) + { + case CAIRO_PATH_MOVE_TO: + g_assert (p->header.length >= 2); + + clutter_path_add_move_to (path, p[1].point.x, p[1].point.y); + break; + + case CAIRO_PATH_LINE_TO: + g_assert (p->header.length >= 2); + + clutter_path_add_line_to (path, p[1].point.x, p[1].point.y); + break; + + case CAIRO_PATH_CURVE_TO: + g_assert (p->header.length >= 4); + + clutter_path_add_curve_to (path, + p[1].point.x, p[1].point.y, + p[2].point.x, p[2].point.y, + p[3].point.x, p[3].point.y); + break; + + case CAIRO_PATH_CLOSE_PATH: + clutter_path_add_close (path); + } + } +} + +static void +clutter_path_add_node_to_cairo_path (const ClutterPathNode *node, + gpointer data) +{ + cairo_t *cr = data; + + switch (node->type) + { + case CLUTTER_PATH_MOVE_TO: + cairo_move_to (cr, node->points[0].x, node->points[0].y); + break; + + case CLUTTER_PATH_LINE_TO: + cairo_line_to (cr, node->points[0].x, node->points[0].y); + break; + + case CLUTTER_PATH_CURVE_TO: + cairo_curve_to (cr, + node->points[0].x, node->points[0].y, + node->points[1].x, node->points[1].y, + node->points[2].x, node->points[2].y); + break; + + case CLUTTER_PATH_REL_MOVE_TO: + cairo_rel_move_to (cr, node->points[0].x, node->points[0].y); + break; + + case CLUTTER_PATH_REL_LINE_TO: + cairo_rel_line_to (cr, node->points[0].x, node->points[0].y); + break; + + case CLUTTER_PATH_REL_CURVE_TO: + cairo_rel_curve_to (cr, + node->points[0].x, node->points[0].y, + node->points[1].x, node->points[1].y, + node->points[2].x, node->points[2].y); + break; + + case CLUTTER_PATH_CLOSE: + cairo_close_path (cr); + } +} + +/** + * clutter_path_to_cairo_path: + * @path: a #ClutterPath + * @cr: a Cairo context + * + * Add the nodes of the ClutterPath to the path in the Cairo context. + * + * Since: 1.0 + */ +void +clutter_path_to_cairo_path (ClutterPath *path, + cairo_t *cr) +{ + g_return_if_fail (CLUTTER_IS_PATH (path)); + g_return_if_fail (cr != NULL); + + clutter_path_foreach (path, clutter_path_add_node_to_cairo_path, cr); +} + +/** + * clutter_path_get_n_nodes: + * @path: a #ClutterPath + * + * Retrieves the number of nodes in the path. + * + * Return value: the number of nodes. + * + * Since: 1.0 + */ +guint +clutter_path_get_n_nodes (ClutterPath *path) +{ + ClutterPathPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_PATH (path), 0); + + priv = path->priv; + + return g_slist_length (priv->nodes); +} + +/** + * clutter_path_get_node: + * @path: a #ClutterPath + * @index_: the node number to retrieve + * @node: (out): a location to store a copy of the node + * + * Retrieves the node of the path indexed by @index. + * + * Since: 1.0 + */ +void +clutter_path_get_node (ClutterPath *path, + guint index_, + ClutterPathNode *node) +{ + ClutterPathNodeFull *node_full; + ClutterPathPrivate *priv; + + g_return_if_fail (CLUTTER_IS_PATH (path)); + + priv = path->priv; + + node_full = g_slist_nth_data (priv->nodes, index_); + + g_return_if_fail (node_full != NULL); + + *node = node_full->k; +} + +/** + * clutter_path_get_nodes: + * @path: a #ClutterPath + * + * Returns a #GSList of #ClutterPathNodes. The list should be + * freed with g_slist_free(). The nodes are owned by the path and + * should not be freed. Altering the path may cause the nodes in the + * list to become invalid so you should copy them if you want to keep + * the list. + * + * Return value: (transfer container) (element-type Clutter.PathNode): a + * list of nodes in the path. + * + * Since: 1.0 + */ +GSList * +clutter_path_get_nodes (ClutterPath *path) +{ + ClutterPathPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_PATH (path), NULL); + + priv = path->priv; + + return g_slist_copy (priv->nodes); +} + +/** + * clutter_path_foreach: + * @path: a #ClutterPath + * @callback: (scope call): the function to call with each node + * @user_data: user data to pass to the function + * + * Calls a function for each node of the path. + * + * Since: 1.0 + */ +void +clutter_path_foreach (ClutterPath *path, + ClutterPathCallback callback, + gpointer user_data) +{ + ClutterPathPrivate *priv; + + g_return_if_fail (CLUTTER_IS_PATH (path)); + + priv = path->priv; + + g_slist_foreach (priv->nodes, (GFunc) callback, user_data); +} + +/** + * clutter_path_insert_node: + * @path: a #ClutterPath + * @index_: offset of where to insert the node + * @node: the node to insert + * + * Inserts @node into the path before the node at the given offset. If + * @index_ is negative it will append the node to the end of the path. + * + * Since: 1.0 + */ +void +clutter_path_insert_node (ClutterPath *path, + gint index_, + const ClutterPathNode *node) +{ + ClutterPathPrivate *priv; + ClutterPathNodeFull *node_full; + + g_return_if_fail (CLUTTER_IS_PATH (path)); + g_return_if_fail (node != NULL); + g_return_if_fail (CLUTTER_PATH_NODE_TYPE_IS_VALID (node->type)); + + priv = path->priv; + + node_full = clutter_path_node_full_new (); + node_full->k = *node; + + priv->nodes = g_slist_insert (priv->nodes, node_full, index_); + + if (priv->nodes_tail == NULL) + priv->nodes_tail = priv->nodes; + else if (priv->nodes_tail->next) + priv->nodes_tail = priv->nodes_tail->next; + + priv->nodes_dirty = TRUE; +} + +/** + * clutter_path_remove_node: + * @path: a #ClutterPath + * @index_: index of the node to remove + * + * Removes the node at the given offset from the path. + * + * Since: 1.0 + */ +void +clutter_path_remove_node (ClutterPath *path, + guint index_) +{ + ClutterPathPrivate *priv; + GSList *node, *prev = NULL; + + g_return_if_fail (CLUTTER_IS_PATH (path)); + + priv = path->priv; + + for (node = priv->nodes; node && index_--; node = node->next) + prev = node; + + if (node) + { + clutter_path_node_full_free (node->data); + + if (prev) + prev->next = node->next; + else + priv->nodes = node->next; + + if (node == priv->nodes_tail) + priv->nodes_tail = prev; + + g_slist_free_1 (node); + + priv->nodes_dirty = TRUE; + } +} + +/** + * clutter_path_replace_node: + * @path: a #ClutterPath + * @index_: index to the existing node + * @node: the replacement node + * + * Replaces the node at offset @index_ with @node. + * + * Since: 1.0 + */ +void +clutter_path_replace_node (ClutterPath *path, + guint index_, + const ClutterPathNode *node) +{ + ClutterPathPrivate *priv; + ClutterPathNodeFull *node_full; + + g_return_if_fail (CLUTTER_IS_PATH (path)); + g_return_if_fail (node != NULL); + g_return_if_fail (CLUTTER_PATH_NODE_TYPE_IS_VALID (node->type)); + + priv = path->priv; + + if ((node_full = g_slist_nth_data (priv->nodes, index_))) + { + node_full->k = *node; + + priv->nodes_dirty = TRUE; + } +} + +/** + * clutter_path_set_description: + * @path: a #ClutterPath + * @str: a string describing the path + * + * Replaces all of the nodes in the path with nodes described by + * @str. See clutter_path_add_string() for details of the format. + * + * If the string is invalid then %FALSE is returned and the path is + * unaltered. + * + * Return value: %TRUE is the path was valid, %FALSE otherwise. + * + * Since: 1.0 + */ +gboolean +clutter_path_set_description (ClutterPath *path, + const gchar *str) +{ + GSList *nodes; + + g_return_val_if_fail (CLUTTER_IS_PATH (path), FALSE); + g_return_val_if_fail (str != NULL, FALSE); + + if (clutter_path_parse_description (str, &nodes)) + { + clutter_path_clear (path); + clutter_path_add_nodes (path, nodes); + + return TRUE; + } + else + return FALSE; +} + +/** + * clutter_path_get_description: + * @path: a #ClutterPath + * + * Returns a newly allocated string describing the path in the same + * format as used by clutter_path_add_string(). + * + * Return value: a string description of the path. Free with g_free(). + * + * Since: 1.0 + */ +gchar * +clutter_path_get_description (ClutterPath *path) +{ + ClutterPathPrivate *priv; + GString *str; + GSList *l; + + g_return_val_if_fail (CLUTTER_IS_PATH (path), NULL); + + priv = path->priv; + + str = g_string_new (""); + + for (l = priv->nodes; l; l = l->next) + { + ClutterPathNodeFull *node = l->data; + gchar letter = '?'; + gint params = 0; + gint i; + + switch (node->k.type) + { + case CLUTTER_PATH_MOVE_TO: + letter = 'M'; + params = 1; + break; + + case CLUTTER_PATH_REL_MOVE_TO: + letter = 'm'; + params = 1; + break; + + case CLUTTER_PATH_LINE_TO: + letter = 'L'; + params = 1; + break; + + case CLUTTER_PATH_REL_LINE_TO: + letter = 'l'; + params = 1; + break; + + case CLUTTER_PATH_CURVE_TO: + letter = 'C'; + params = 3; + break; + + case CLUTTER_PATH_REL_CURVE_TO: + letter = 'c'; + params = 3; + break; + + case CLUTTER_PATH_CLOSE: + letter = 'z'; + params = 0; + break; + } + + if (str->len > 0) + g_string_append_c (str, ' '); + g_string_append_c (str, letter); + + for (i = 0; i < params; i++) + g_string_append_printf (str, " %i %i", + node->k.points[i].x, + node->k.points[i].y); + } + + return g_string_free (str, FALSE); +} + +static guint +clutter_path_node_distance (const ClutterKnot *start, + const ClutterKnot *end) +{ + gint64 x_d, y_d; + float t; + + g_return_val_if_fail (start != NULL, 0); + g_return_val_if_fail (end != NULL, 0); + + if (clutter_knot_equal (start, end)) + return 0; + + x_d = end->x - start->x; + y_d = end->y - start->y; + + t = floorf (sqrtf ((x_d * x_d) + (y_d * y_d))); + + return (guint) t; +} + +static void +clutter_path_ensure_node_data (ClutterPath *path) +{ + ClutterPathPrivate *priv = path->priv; + + /* Recalculate the nodes data if has changed */ + if (priv->nodes_dirty) + { + GSList *l; + ClutterKnot last_position = { 0, 0 }; + ClutterKnot loop_start = { 0, 0 }; + ClutterKnot points[3]; + + priv->total_length = 0; + + for (l = priv->nodes; l; l = l->next) + { + ClutterPathNodeFull *node = l->data; + gboolean relative = (node->k.type & CLUTTER_PATH_RELATIVE) != 0; + + switch (node->k.type & ~CLUTTER_PATH_RELATIVE) + { + case CLUTTER_PATH_MOVE_TO: + node->length = 0; + + /* Store the actual position in point[1] */ + if (relative) + { + node->k.points[1].x = last_position.x + node->k.points[0].x; + node->k.points[1].y = last_position.y + node->k.points[0].y; + } + else + node->k.points[1] = node->k.points[0]; + + last_position = node->k.points[1]; + loop_start = node->k.points[1]; + break; + + case CLUTTER_PATH_LINE_TO: + /* Use point[1] as the start point and point[2] as the end + point */ + node->k.points[1] = last_position; + + if (relative) + { + node->k.points[2].x = (node->k.points[1].x + + node->k.points[0].x); + node->k.points[2].y = (node->k.points[1].y + + node->k.points[0].y); + } + else + node->k.points[2] = node->k.points[0]; + + last_position = node->k.points[2]; + + node->length = clutter_path_node_distance (node->k.points + 1, + node->k.points + 2); + break; + + case CLUTTER_PATH_CURVE_TO: + /* Convert to a bezier curve */ + if (node->bezier == NULL) + node->bezier = _clutter_bezier_new (); + + if (relative) + { + int i; + + for (i = 0; i < 3; i++) + { + points[i].x = last_position.x + node->k.points[i].x; + points[i].y = last_position.y + node->k.points[i].y; + } + } + else + memcpy (points, node->k.points, sizeof (ClutterKnot) * 3); + + _clutter_bezier_init (node->bezier, + last_position.x, last_position.y, + points[0].x, points[0].y, + points[1].x, points[1].y, + points[2].x, points[2].y); + + last_position = points[2]; + + node->length = _clutter_bezier_get_length (node->bezier); + + break; + + case CLUTTER_PATH_CLOSE: + /* Convert to a line to from last_point to loop_start */ + node->k.points[1] = last_position; + node->k.points[2] = loop_start; + last_position = node->k.points[2]; + + node->length = clutter_path_node_distance (node->k.points + 1, + node->k.points + 2); + break; + } + + priv->total_length += node->length; + } + + priv->nodes_dirty = FALSE; + } +} + +/** + * clutter_path_get_position: + * @path: a #ClutterPath + * @progress: a position along the path as a fraction of its length + * @position: (out): location to store the position + * + * The value in @progress represents a position along the path where + * 0.0 is the beginning and 1.0 is the end of the path. An + * interpolated position is then stored in @position. + * + * Return value: index of the node used to calculate the position. + * + * Since: 1.0 + */ +guint +clutter_path_get_position (ClutterPath *path, + gdouble progress, + ClutterKnot *position) +{ + ClutterPathPrivate *priv; + GSList *l; + guint point_distance, length = 0, node_num = 0; + ClutterPathNodeFull *node; + + g_return_val_if_fail (CLUTTER_IS_PATH (path), 0); + g_return_val_if_fail (progress >= 0.0 && progress <= 1.0, 0); + + priv = path->priv; + + clutter_path_ensure_node_data (path); + + /* Special case if the path is empty, just return 0,0 for want of + something better */ + if (priv->nodes == NULL) + { + memset (position, 0, sizeof (ClutterKnot)); + return 0; + } + + /* Convert the progress to a length along the path */ + point_distance = progress * priv->total_length; + + /* Find the node that covers this point */ + for (l = priv->nodes; + l->next && point_distance >= (((ClutterPathNodeFull *) l->data)->length + + length); + l = l->next) + { + length += ((ClutterPathNodeFull *) l->data)->length; + node_num++; + } + + node = l->data; + + /* Convert the point distance to a distance along the node */ + point_distance -= length; + if (point_distance > node->length) + point_distance = node->length; + + switch (node->k.type & ~CLUTTER_PATH_RELATIVE) + { + case CLUTTER_PATH_MOVE_TO: + *position = node->k.points[1]; + break; + + case CLUTTER_PATH_LINE_TO: + case CLUTTER_PATH_CLOSE: + if (node->length == 0) + *position = node->k.points[1]; + else + { + position->x = (node->k.points[1].x + + ((node->k.points[2].x - node->k.points[1].x) + * (gint) point_distance / (gint) node->length)); + position->y = (node->k.points[1].y + + ((node->k.points[2].y - node->k.points[1].y) + * (gint) point_distance / (gint) node->length)); + } + break; + + case CLUTTER_PATH_CURVE_TO: + if (node->length == 0) + *position = node->k.points[2]; + else + { + _clutter_bezier_advance (node->bezier, + point_distance * CLUTTER_BEZIER_MAX_LENGTH + / node->length, + position); + } + break; + } + + return node_num; +} + +/** + * clutter_path_get_length: + * @path: a #ClutterPath + * + * Retrieves an approximation of the total length of the path. + * + * Return value: the length of the path. + * + * Since: 1.0 + */ +guint +clutter_path_get_length (ClutterPath *path) +{ + g_return_val_if_fail (CLUTTER_IS_PATH (path), 0); + + clutter_path_ensure_node_data (path); + + return path->priv->total_length; +} + +static ClutterPathNodeFull * +clutter_path_node_full_new (void) +{ + return g_slice_new0 (ClutterPathNodeFull); +} + +static void +clutter_path_node_full_free (ClutterPathNodeFull *node) +{ + if (node->bezier) + _clutter_bezier_free (node->bezier); + + g_slice_free (ClutterPathNodeFull, node); +} + +/** + * clutter_path_node_copy: + * @node: a #ClutterPathNode + * + * Makes an allocated copy of a node. + * + * Return value: the copied node. + * + * Since: 1.0 + */ +ClutterPathNode * +clutter_path_node_copy (const ClutterPathNode *node) +{ + return g_slice_dup (ClutterPathNode, node); +} + +/** + * clutter_path_node_free: + * @node: a #ClutterPathNode + * + * Frees the memory of an allocated node. + * + * Since: 1.0 + */ +void +clutter_path_node_free (ClutterPathNode *node) +{ + if (G_LIKELY (node)) + g_slice_free (ClutterPathNode, node); +} + +/** + * clutter_path_node_equal: + * @node_a: First node + * @node_b: Second node + * + * Compares two nodes and checks if they are the same type with the + * same coordinates. + * + * Return value: %TRUE if the nodes are the same. + * + * Since: 1.0 + */ +gboolean +clutter_path_node_equal (const ClutterPathNode *node_a, + const ClutterPathNode *node_b) +{ + guint n_points, i; + + g_return_val_if_fail (node_a != NULL, FALSE); + g_return_val_if_fail (node_b != NULL, FALSE); + + if (node_a->type != node_b->type) + return FALSE; + + switch (node_a->type & ~CLUTTER_PATH_RELATIVE) + { + case CLUTTER_PATH_MOVE_TO: n_points = 1; break; + case CLUTTER_PATH_LINE_TO: n_points = 1; break; + case CLUTTER_PATH_CURVE_TO: n_points = 3; break; + case CLUTTER_PATH_CLOSE: n_points = 0; break; + default: return FALSE; + } + + for (i = 0; i < n_points; i++) + if (node_a->points[i].x != node_b->points[i].x + || node_a->points[i].y != node_b->points[i].y) + return FALSE; + + return TRUE; +} + +G_DEFINE_BOXED_TYPE (ClutterKnot, clutter_knot, + clutter_knot_copy, + clutter_knot_free); + +/** + * clutter_knot_copy: + * @knot: a #ClutterKnot + * + * Makes an allocated copy of a knot. + * + * Return value: the copied knot. + * + * Since: 0.2 + */ +ClutterKnot * +clutter_knot_copy (const ClutterKnot *knot) +{ + if (G_UNLIKELY (knot == NULL)) + return NULL; + + return g_slice_dup (ClutterKnot, knot); +} + +/** + * clutter_knot_free: + * @knot: a #ClutterKnot + * + * Frees the memory of an allocated knot. + * + * Since: 0.2 + */ +void +clutter_knot_free (ClutterKnot *knot) +{ + if (G_LIKELY (knot != NULL)) + g_slice_free (ClutterKnot, knot); +} + +/** + * clutter_knot_equal: + * @knot_a: First knot + * @knot_b: Second knot + * + * Compares to knot and checks if the point to the same location. + * + * Return value: %TRUE if the knots point to the same location. + * + * Since: 0.2 + */ +gboolean +clutter_knot_equal (const ClutterKnot *knot_a, + const ClutterKnot *knot_b) +{ + g_return_val_if_fail (knot_a != NULL, FALSE); + g_return_val_if_fail (knot_b != NULL, FALSE); + + if (knot_a == knot_b) + return TRUE; + + return knot_a->x == knot_b->x && knot_a->y == knot_b->y; +} diff --git a/clutter/clutter/clutter-path.h b/clutter/clutter/clutter-path.h new file mode 100644 index 0000000..38133a5 --- /dev/null +++ b/clutter/clutter/clutter-path.h @@ -0,0 +1,181 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2008 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 . + */ + +#ifndef __CLUTTER_PATH_H__ +#define __CLUTTER_PATH_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_PATH (clutter_path_get_type ()) +#define CLUTTER_TYPE_PATH_NODE (clutter_path_node_get_type ()) +#define CLUTTER_PATH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_PATH, ClutterPath)) +#define CLUTTER_PATH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_PATH, ClutterPathClass)) +#define CLUTTER_IS_PATH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_PATH)) +#define CLUTTER_IS_PATH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_PATH)) +#define CLUTTER_PATH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_PATH, ClutterPathClass)) + +typedef struct _ClutterPathClass ClutterPathClass; +typedef struct _ClutterPathPrivate ClutterPathPrivate; + +/** + * ClutterPathCallback: + * @node: the node + * @data: (closure): optional data passed to the function + * + * This function is passed to clutter_path_foreach() and will be + * called for each node contained in the path. + * + * Since: 1.0 + */ +typedef void (* ClutterPathCallback) (const ClutterPathNode *node, + gpointer data); + +/** + * ClutterPath: + * + * The #ClutterPath struct contains only private data and should + * be accessed with the functions below. + * + * Since: 1.0 + */ +struct _ClutterPath +{ + /*< private >*/ + GInitiallyUnowned parent; + + ClutterPathPrivate *priv; +}; + +/** + * ClutterPathClass: + * + * The #ClutterPathClass struct contains only private data. + * + * Since: 1.0 + */ +struct _ClutterPathClass +{ + /*< private >*/ + GInitiallyUnownedClass parent_class; +}; + +CLUTTER_AVAILABLE_IN_1_0 +GType clutter_path_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_0 +ClutterPath *clutter_path_new (void); +CLUTTER_AVAILABLE_IN_1_0 +ClutterPath *clutter_path_new_with_description (const gchar *desc); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_path_add_move_to (ClutterPath *path, + gint x, + gint y); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_path_add_rel_move_to (ClutterPath *path, + gint x, + gint y); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_path_add_line_to (ClutterPath *path, + gint x, + gint y); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_path_add_rel_line_to (ClutterPath *path, + gint x, + gint y); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_path_add_curve_to (ClutterPath *path, + gint x_1, + gint y_1, + gint x_2, + gint y_2, + gint x_3, + gint y_3); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_path_add_rel_curve_to (ClutterPath *path, + gint x_1, + gint y_1, + gint x_2, + gint y_2, + gint x_3, + gint y_3); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_path_add_close (ClutterPath *path); +CLUTTER_AVAILABLE_IN_1_0 +gboolean clutter_path_add_string (ClutterPath *path, + const gchar *str); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_path_add_node (ClutterPath *path, + const ClutterPathNode *node); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_path_add_cairo_path (ClutterPath *path, + const cairo_path_t *cpath); +CLUTTER_AVAILABLE_IN_1_0 +guint clutter_path_get_n_nodes (ClutterPath *path); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_path_get_node (ClutterPath *path, + guint index_, + ClutterPathNode *node); +CLUTTER_AVAILABLE_IN_1_0 +GSList * clutter_path_get_nodes (ClutterPath *path); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_path_foreach (ClutterPath *path, + ClutterPathCallback callback, + gpointer user_data); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_path_insert_node (ClutterPath *path, + gint index_, + const ClutterPathNode *node); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_path_remove_node (ClutterPath *path, + guint index_); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_path_replace_node (ClutterPath *path, + guint index_, + const ClutterPathNode *node); +CLUTTER_AVAILABLE_IN_1_0 +gchar * clutter_path_get_description (ClutterPath *path); +CLUTTER_AVAILABLE_IN_1_0 +gboolean clutter_path_set_description (ClutterPath *path, + const gchar *str); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_path_clear (ClutterPath *path); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_path_to_cairo_path (ClutterPath *path, + cairo_t *cr); +CLUTTER_AVAILABLE_IN_1_0 +guint clutter_path_get_position (ClutterPath *path, + gdouble progress, + ClutterKnot *position); +CLUTTER_AVAILABLE_IN_1_0 +guint clutter_path_get_length (ClutterPath *path); + +G_END_DECLS + +#endif /* __CLUTTER_PATH_H__ */ diff --git a/clutter/clutter/clutter-private.h b/clutter/clutter/clutter-private.h new file mode 100644 index 0000000..129880d --- /dev/null +++ b/clutter/clutter/clutter-private.h @@ -0,0 +1,312 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +#ifndef __CLUTTER_PRIVATE_H__ +#define __CLUTTER_PRIVATE_H__ + +#include +#include + +#include + +#include "clutter-backend.h" +#include "clutter-effect.h" +#include "clutter-event.h" +#include "clutter-feature.h" +#include "clutter-id-pool.h" +#include "clutter-layout-manager.h" +#include "clutter-master-clock.h" +#include "clutter-settings.h" +#include "clutter-stage-manager.h" +#include "clutter-stage.h" + +G_BEGIN_DECLS + +typedef struct _ClutterMainContext ClutterMainContext; +typedef struct _ClutterVertex4 ClutterVertex4; + +#define CLUTTER_REGISTER_VALUE_TRANSFORM_TO(TYPE_TO,func) { \ + g_value_register_transform_func (g_define_type_id, TYPE_TO, func); \ +} + +#define CLUTTER_REGISTER_VALUE_TRANSFORM_FROM(TYPE_FROM,func) { \ + g_value_register_transform_func (TYPE_FROM, g_define_type_id, func); \ +} + +#define CLUTTER_REGISTER_INTERVAL_PROGRESS(func) { \ + clutter_interval_register_progress_func (g_define_type_id, func); \ +} + +#define CLUTTER_PRIVATE_FLAGS(a) (((ClutterActor *) (a))->private_flags) +#define CLUTTER_SET_PRIVATE_FLAGS(a,f) (CLUTTER_PRIVATE_FLAGS (a) |= (f)) +#define CLUTTER_UNSET_PRIVATE_FLAGS(a,f) (CLUTTER_PRIVATE_FLAGS (a) &= ~(f)) + +#define CLUTTER_ACTOR_IS_TOPLEVEL(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IS_TOPLEVEL) != FALSE) +#define CLUTTER_ACTOR_IS_INTERNAL_CHILD(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_INTERNAL_CHILD) != FALSE) +#define CLUTTER_ACTOR_IN_DESTRUCTION(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_DESTRUCTION) != FALSE) +#define CLUTTER_ACTOR_IN_REPARENT(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_REPARENT) != FALSE) +#define CLUTTER_ACTOR_IN_PAINT(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_PAINT) != FALSE) +#define CLUTTER_ACTOR_IN_RELAYOUT(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_RELAYOUT) != FALSE) + +#define CLUTTER_PARAM_READABLE (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS) +#define CLUTTER_PARAM_WRITABLE (G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS) +#define CLUTTER_PARAM_READWRITE (G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS) + +#define CLUTTER_PARAM_ANIMATABLE (1 << G_PARAM_USER_SHIFT) + +/* automagic interning of a static string */ +#define I_(str) (g_intern_static_string ((str))) + +/* keep this for source compatibility with clutter */ +#define P_(String) (String) +#define N_(String) (String) +#define _(String) (String) + +/* This is a replacement for the nearbyint function which always rounds to the + * nearest integer. nearbyint is apparently a C99 function so it might not + * always be available but also it seems in glibc it is defined as a function + * call so this macro could end up faster anyway. We can't just add 0.5f + * because it will break for negative numbers. */ +#define CLUTTER_NEARBYINT(x) ((int) ((x) < 0.0f ? (x) - 0.5f : (x) + 0.5f)) + +typedef enum { + CLUTTER_ACTOR_UNUSED_FLAG = 0, + + CLUTTER_IN_DESTRUCTION = 1 << 0, + CLUTTER_IS_TOPLEVEL = 1 << 1, + CLUTTER_IN_REPARENT = 1 << 2, + + /* Used to avoid recursion */ + CLUTTER_IN_PAINT = 1 << 3, + + /* Used to avoid recursion */ + CLUTTER_IN_RELAYOUT = 1 << 4, + + /* a flag for internal children of Containers (DEPRECATED) */ + CLUTTER_INTERNAL_CHILD = 1 << 5 +} ClutterPrivateFlags; + +/* + * ClutterMainContext: + * + * The shared state of Clutter + */ +struct _ClutterMainContext +{ + /* the main windowing system backend */ + ClutterBackend *backend; + + /* the object holding all the stage instances */ + ClutterStageManager *stage_manager; + + /* the clock driving all the frame operations */ + ClutterMasterClock *master_clock; + + /* the main event queue */ + GQueue *events_queue; + + /* the event filters added via clutter_event_add_filter. these are + * ordered from least recently added to most recently added */ + GList *event_filters; + + ClutterPickMode pick_mode; + + /* default FPS; this is only used if we cannot sync to vblank */ + guint frame_rate; + + /* actors with a grab on all devices */ + ClutterActor *pointer_grab_actor; + ClutterActor *keyboard_grab_actor; + + /* stack of actors with shaders during paint */ + GSList *shaders; + + /* fb bit masks for col<->id mapping in picking */ + gint fb_r_mask; + gint fb_g_mask; + gint fb_b_mask; + gint fb_r_mask_used; + gint fb_g_mask_used; + gint fb_b_mask_used; + + CoglPangoFontMap *font_map; /* Global font map */ + + /* stack of #ClutterEvent */ + GSList *current_event; + + /* list of repaint functions installed through + * clutter_threads_add_repaint_func() + */ + GList *repaint_funcs; + guint last_repaint_id; + + /* main settings singleton */ + ClutterSettings *settings; + + /* boolean flags */ + guint is_initialized : 1; + guint motion_events_per_actor : 1; + guint defer_display_setup : 1; + guint options_parsed : 1; + guint show_fps : 1; +}; + +/* shared between clutter-main.c and clutter-frame-source.c */ +typedef struct +{ + GSourceFunc func; + gpointer data; + GDestroyNotify notify; +} ClutterThreadsDispatch; + +gboolean _clutter_threads_dispatch (gpointer data); +void _clutter_threads_dispatch_free (gpointer data); + +void _clutter_threads_acquire_lock (void); +void _clutter_threads_release_lock (void); + +ClutterMainContext * _clutter_context_get_default (void); +void _clutter_context_lock (void); +void _clutter_context_unlock (void); +gboolean _clutter_context_is_initialized (void); +ClutterPickMode _clutter_context_get_pick_mode (void); +void _clutter_context_push_shader_stack (ClutterActor *actor); +ClutterActor * _clutter_context_pop_shader_stack (ClutterActor *actor); +ClutterActor * _clutter_context_peek_shader_stack (void); +gboolean _clutter_context_get_motion_events_enabled (void); +gboolean _clutter_context_get_show_fps (void); + +gboolean _clutter_feature_init (GError **error); + +/* Diagnostic mode */ +gboolean _clutter_diagnostic_enabled (void); +void _clutter_diagnostic_message (const char *fmt, ...); + +/* Picking code */ +guint _clutter_pixel_to_id (guchar pixel[4]); +void _clutter_id_to_color (guint id, + ClutterColor *col); + +void _clutter_set_sync_to_vblank (gboolean sync_to_vblank); + +/* 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 + */ +gboolean _clutter_boolean_handled_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer dummy); + +/* 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 FALSE + */ +gboolean _clutter_boolean_continue_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer dummy); + +void _clutter_run_repaint_functions (ClutterRepaintFlags flags); + +GType _clutter_layout_manager_get_child_meta_type (ClutterLayoutManager *manager); + +void _clutter_util_fully_transform_vertices (const CoglMatrix *modelview, + const CoglMatrix *projection, + const float *viewport, + const ClutterVertex *vertices_in, + ClutterVertex *vertices_out, + int n_vertices); + +void _clutter_util_rectangle_union (const cairo_rectangle_int_t *src1, + const cairo_rectangle_int_t *src2, + cairo_rectangle_int_t *dest); + +gboolean _clutter_util_rectangle_intersection (const cairo_rectangle_int_t *src1, + const cairo_rectangle_int_t *src2, + cairo_rectangle_int_t *dest); + + +struct _ClutterVertex4 +{ + float x; + float y; + float z; + float w; +}; + +void +_clutter_util_vertex4_interpolate (const ClutterVertex4 *a, + const ClutterVertex4 *b, + double progress, + ClutterVertex4 *res); + +#define CLUTTER_MATRIX_INIT_IDENTITY { \ + 1.0f, 0.0f, 0.0f, 0.0f, \ + 0.0f, 1.0f, 0.0f, 0.0f, \ + 0.0f, 0.0f, 1.0f, 0.0f, \ + 0.0f, 0.0f, 0.0f, 1.0f, \ +} + +float _clutter_util_matrix_determinant (const ClutterMatrix *matrix); + +void _clutter_util_matrix_skew_xy (ClutterMatrix *matrix, + float factor); +void _clutter_util_matrix_skew_xz (ClutterMatrix *matrix, + float factor); +void _clutter_util_matrix_skew_yz (ClutterMatrix *matrix, + float factor); + +gboolean _clutter_util_matrix_decompose (const ClutterMatrix *src, + ClutterVertex *scale_p, + float shear_p[3], + ClutterVertex *rotate_p, + ClutterVertex *translate_p, + ClutterVertex4 *perspective_p); + +typedef struct _ClutterPlane +{ + float v0[3]; + float n[3]; +} ClutterPlane; + +typedef enum _ClutterCullResult +{ + CLUTTER_CULL_RESULT_UNKNOWN, + CLUTTER_CULL_RESULT_IN, + CLUTTER_CULL_RESULT_OUT, + CLUTTER_CULL_RESULT_PARTIAL +} ClutterCullResult; + +gboolean _clutter_has_progress_function (GType gtype); +gboolean _clutter_run_progress_function (GType gtype, + const GValue *initial, + const GValue *final, + gdouble progress, + GValue *retval); + +G_END_DECLS + +#endif /* __CLUTTER_PRIVATE_H__ */ diff --git a/clutter/clutter/clutter-property-transition.c b/clutter/clutter/clutter-property-transition.c new file mode 100644 index 0000000..2b98cb1 --- /dev/null +++ b/clutter/clutter/clutter-property-transition.c @@ -0,0 +1,360 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2012 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 . + */ + +/** + * SECTION:clutter-property-transition + * @Title: ClutterPropertyTransition + * @Short_Description: Property transitions + * + * #ClutterPropertyTransition is a specialized #ClutterTransition that + * can be used to tween a property of a #ClutterAnimatable instance. + * + * #ClutterPropertyTransition is available since Clutter 1.10 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-property-transition.h" + +#include "clutter-animatable.h" +#include "clutter-debug.h" +#include "clutter-interval.h" +#include "clutter-private.h" +#include "clutter-transition.h" + +struct _ClutterPropertyTransitionPrivate +{ + char *property_name; + + GParamSpec *pspec; +}; + +enum +{ + PROP_0, + + PROP_PROPERTY_NAME, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST] = { NULL, }; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterPropertyTransition, clutter_property_transition, CLUTTER_TYPE_TRANSITION) + +static inline void +clutter_property_transition_ensure_interval (ClutterPropertyTransition *transition, + ClutterAnimatable *animatable, + ClutterInterval *interval) +{ + ClutterPropertyTransitionPrivate *priv = transition->priv; + GValue *value_p; + + if (clutter_interval_is_valid (interval)) + return; + + /* if no initial value has been set, use the current value */ + value_p = clutter_interval_peek_initial_value (interval); + if (!G_IS_VALUE (value_p)) + { + g_value_init (value_p, clutter_interval_get_value_type (interval)); + clutter_animatable_get_initial_state (animatable, + priv->property_name, + value_p); + } + + /* if no final value has been set, use the current value */ + value_p = clutter_interval_peek_final_value (interval); + if (!G_IS_VALUE (value_p)) + { + g_value_init (value_p, clutter_interval_get_value_type (interval)); + clutter_animatable_get_initial_state (animatable, + priv->property_name, + value_p); + } +} + +static void +clutter_property_transition_attached (ClutterTransition *transition, + ClutterAnimatable *animatable) +{ + ClutterPropertyTransition *self = CLUTTER_PROPERTY_TRANSITION (transition); + ClutterPropertyTransitionPrivate *priv = self->priv; + ClutterInterval *interval; + + if (priv->property_name == NULL) + return; + + priv->pspec = + clutter_animatable_find_property (animatable, priv->property_name); + + if (priv->pspec == NULL) + return; + + interval = clutter_transition_get_interval (transition); + if (interval == NULL) + return; + + clutter_property_transition_ensure_interval (self, animatable, interval); +} + +static void +clutter_property_transition_detached (ClutterTransition *transition, + ClutterAnimatable *animatable) +{ + ClutterPropertyTransition *self = CLUTTER_PROPERTY_TRANSITION (transition); + ClutterPropertyTransitionPrivate *priv = self->priv; + + priv->pspec = NULL; +} + +static void +clutter_property_transition_compute_value (ClutterTransition *transition, + ClutterAnimatable *animatable, + ClutterInterval *interval, + gdouble progress) +{ + ClutterPropertyTransition *self = CLUTTER_PROPERTY_TRANSITION (transition); + ClutterPropertyTransitionPrivate *priv = self->priv; + GValue value = G_VALUE_INIT; + GType p_type, i_type; + gboolean res; + + /* if we have a GParamSpec we also have an animatable instance */ + if (priv->pspec == NULL) + return; + + clutter_property_transition_ensure_interval (self, animatable, interval); + + p_type = G_PARAM_SPEC_VALUE_TYPE (priv->pspec); + i_type = clutter_interval_get_value_type (interval); + + g_value_init (&value, i_type); + + res = clutter_animatable_interpolate_value (animatable, + priv->property_name, + interval, + progress, + &value); + + if (res) + { + if (i_type != p_type || g_type_is_a (i_type, p_type)) + { + if (g_value_type_transformable (i_type, p_type)) + { + GValue transform = G_VALUE_INIT; + + g_value_init (&transform, p_type); + + if (g_value_transform (&value, &transform)) + { + clutter_animatable_set_final_state (animatable, + priv->property_name, + &transform); + } + else + g_warning ("%s: Unable to convert a value of type '%s' from " + "the value type '%s' of the interval.", + G_STRLOC, + g_type_name (p_type), + g_type_name (i_type)); + + g_value_unset (&transform); + } + } + else + clutter_animatable_set_final_state (animatable, + priv->property_name, + &value); + } + + g_value_unset (&value); +} + +static void +clutter_property_transition_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterPropertyTransition *self = CLUTTER_PROPERTY_TRANSITION (gobject); + + switch (prop_id) + { + case PROP_PROPERTY_NAME: + clutter_property_transition_set_property_name (self, + g_value_get_string (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + } +} + +static void +clutter_property_transition_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterPropertyTransitionPrivate *priv = CLUTTER_PROPERTY_TRANSITION (gobject)->priv; + + switch (prop_id) + { + case PROP_PROPERTY_NAME: + g_value_set_string (value, priv->property_name); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + } +} + +static void +clutter_property_transition_finalize (GObject *gobject) +{ + ClutterPropertyTransitionPrivate *priv; + + priv = CLUTTER_PROPERTY_TRANSITION (gobject)->priv; + + g_free (priv->property_name); + + G_OBJECT_CLASS (clutter_property_transition_parent_class)->finalize (gobject); +} + +static void +clutter_property_transition_class_init (ClutterPropertyTransitionClass *klass) +{ + ClutterTransitionClass *transition_class = CLUTTER_TRANSITION_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + transition_class->attached = clutter_property_transition_attached; + transition_class->detached = clutter_property_transition_detached; + transition_class->compute_value = clutter_property_transition_compute_value; + + gobject_class->set_property = clutter_property_transition_set_property; + gobject_class->get_property = clutter_property_transition_get_property; + gobject_class->finalize = clutter_property_transition_finalize; + + /** + * ClutterPropertyTransition:property-name: + * + * The name of the property of a #ClutterAnimatable to animate. + * + * Since: 1.10 + */ + obj_props[PROP_PROPERTY_NAME] = + g_param_spec_string ("property-name", + P_("Property Name"), + P_("The name of the property to animate"), + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); +} + +static void +clutter_property_transition_init (ClutterPropertyTransition *self) +{ + self->priv = clutter_property_transition_get_instance_private (self); +} + +/** + * clutter_property_transition_new: + * @property_name: (allow-none): a property of @animatable, or %NULL + * + * Creates a new #ClutterPropertyTransition. + * + * Return value: (transfer full): the newly created #ClutterPropertyTransition. + * Use g_object_unref() when done + * + * Since: 1.10 + */ +ClutterTransition * +clutter_property_transition_new (const char *property_name) +{ + return g_object_new (CLUTTER_TYPE_PROPERTY_TRANSITION, + "property-name", property_name, + NULL); +} + +/** + * clutter_property_transition_set_property_name: + * @transition: a #ClutterPropertyTransition + * @property_name: (allow-none): a property name + * + * Sets the #ClutterPropertyTransition:property-name property of @transition. + * + * Since: 1.10 + */ +void +clutter_property_transition_set_property_name (ClutterPropertyTransition *transition, + const char *property_name) +{ + ClutterPropertyTransitionPrivate *priv; + ClutterAnimatable *animatable; + + g_return_if_fail (CLUTTER_IS_PROPERTY_TRANSITION (transition)); + + priv = transition->priv; + + if (g_strcmp0 (priv->property_name, property_name) == 0) + return; + + g_free (priv->property_name); + priv->property_name = g_strdup (property_name); + priv->pspec = NULL; + + animatable = + clutter_transition_get_animatable (CLUTTER_TRANSITION (transition)); + if (animatable != NULL) + { + priv->pspec = clutter_animatable_find_property (animatable, + priv->property_name); + } + + g_object_notify_by_pspec (G_OBJECT (transition), + obj_props[PROP_PROPERTY_NAME]); +} + +/** + * clutter_property_transition_get_property_name: + * @transition: a #ClutterPropertyTransition + * + * Retrieves the value of the #ClutterPropertyTransition:property-name + * property. + * + * Return value: the name of the property being animated, or %NULL if + * none is set. The returned string is owned by the @transition and + * it should not be freed. + * + * Since: 1.10 + */ +const char * +clutter_property_transition_get_property_name (ClutterPropertyTransition *transition) +{ + g_return_val_if_fail (CLUTTER_IS_PROPERTY_TRANSITION (transition), NULL); + + return transition->priv->property_name; +} diff --git a/clutter/clutter/clutter-property-transition.h b/clutter/clutter/clutter-property-transition.h new file mode 100644 index 0000000..a53f034 --- /dev/null +++ b/clutter/clutter/clutter-property-transition.h @@ -0,0 +1,91 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2012 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 . + * + * Author: Emmanuele Bassi + */ + +#ifndef __CLUTTER_PROPERTY_TRANSITION_H__ +#define __CLUTTER_PROPERTY_TRANSITION_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_PROPERTY_TRANSITION (clutter_property_transition_get_type ()) +#define CLUTTER_PROPERTY_TRANSITION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_PROPERTY_TRANSITION, ClutterPropertyTransition)) +#define CLUTTER_IS_PROPERTY_TRANSITION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_PROPERTY_TRANSITION)) +#define CLUTTER_PROPERTY_TRANSITION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_PROPERTY_TRANSITION, ClutterPropertyTransitionClass)) +#define CLUTTER_IS_PROPERTY_TRANSITION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_PROPERTY_TRANSITION)) +#define CLUTTER_PROPERTY_TRANSITION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_PROPERTY_TRANSITION, ClutterPropertyTransitionClass)) + +typedef struct _ClutterPropertyTransitionPrivate ClutterPropertyTransitionPrivate; +typedef struct _ClutterPropertyTransitionClass ClutterPropertyTransitionClass; + +/** + * ClutterPropertyTransition: + * + * The #ClutterPropertyTransition structure contains + * private data and should only be accessed using the provided API. + * + * Since: 1.10 + */ +struct _ClutterPropertyTransition +{ + /*< private >*/ + ClutterTransition parent_instance; + + ClutterPropertyTransitionPrivate *priv; +}; + +/** + * ClutterPropertyTransitionClass: + * + * The #ClutterPropertyTransitionClass structure + * contains private data. + * + * Since: 1.10 + */ +struct _ClutterPropertyTransitionClass +{ + /*< private >*/ + ClutterTransitionClass parent_class; + + gpointer _padding[8]; +}; + +CLUTTER_AVAILABLE_IN_1_10 +GType clutter_property_transition_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_10 +ClutterTransition * clutter_property_transition_new (const char *property_name); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_property_transition_set_property_name (ClutterPropertyTransition *transition, + const char *property_name); +CLUTTER_AVAILABLE_IN_1_10 +const char * clutter_property_transition_get_property_name (ClutterPropertyTransition *transition); + +G_END_DECLS + +#endif /* __CLUTTER_PROPERTY_TRANSITION_H__ */ diff --git a/clutter/clutter/clutter-rotate-action.c b/clutter/clutter/clutter-rotate-action.c new file mode 100644 index 0000000..b1c28db --- /dev/null +++ b/clutter/clutter/clutter-rotate-action.c @@ -0,0 +1,252 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2012 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 . + * + * Author: + * Lionel Landwerlin + */ + +/** + * SECTION:clutter-rotate-action + * @Title: ClutterRotateAction + * @Short_Description: Action to rotate an actor + * + * #ClutterRotateAction is a sub-class of #ClutterGestureAction that implements + * the logic for recognizing rotate gestures using two touch points. + * + * Since: 1.12 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#include "clutter-rotate-action.h" + +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-gesture-action-private.h" +#include "clutter-marshal.h" +#include "clutter-private.h" + +struct _ClutterRotateActionPrivate +{ + gfloat initial_vector[2]; + gdouble initial_vector_norm; + gdouble initial_rotation; +}; + +enum +{ + ROTATE, + + LAST_SIGNAL +}; + +static guint rotate_signals[LAST_SIGNAL] = { 0, }; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterRotateAction, clutter_rotate_action, CLUTTER_TYPE_GESTURE_ACTION) + +static gboolean +clutter_rotate_action_real_rotate (ClutterRotateAction *action, + ClutterActor *actor, + gdouble angle) +{ + clutter_actor_set_rotation_angle (actor, + CLUTTER_Z_AXIS, + action->priv->initial_rotation + angle); + + return TRUE; +} + +static gboolean +clutter_rotate_action_gesture_begin (ClutterGestureAction *action, + ClutterActor *actor) +{ + ClutterRotateActionPrivate *priv = CLUTTER_ROTATE_ACTION (action)->priv; + gfloat p1[2], p2[2]; + + /* capture initial vector */ + clutter_gesture_action_get_motion_coords (action, 0, &p1[0], &p1[1]); + clutter_gesture_action_get_motion_coords (action, 1, &p2[0], &p2[1]); + + priv->initial_vector[0] = p2[0] - p1[0]; + priv->initial_vector[1] = p2[1] - p1[1]; + + priv->initial_vector_norm = + sqrt (priv->initial_vector[0] * priv->initial_vector[0] + + priv->initial_vector[1] * priv->initial_vector[1]); + + priv->initial_rotation = clutter_actor_get_rotation_angle (actor, CLUTTER_Z_AXIS); + + return TRUE; +} + +static gboolean +clutter_rotate_action_gesture_progress (ClutterGestureAction *action, + ClutterActor *actor) +{ + ClutterRotateActionPrivate *priv = CLUTTER_ROTATE_ACTION (action)->priv; + gfloat p1[2], p2[2]; + gfloat vector[2]; + gboolean retval; + + /* capture current vector */ + clutter_gesture_action_get_motion_coords (action, 0, &p1[0], &p1[1]); + clutter_gesture_action_get_motion_coords (action, 1, &p2[0], &p2[1]); + + vector[0] = p2[0] - p1[0]; + vector[1] = p2[1] - p1[1]; + + if ((vector[0] == priv->initial_vector[0]) && + (vector[1] == priv->initial_vector[1])) + { + g_signal_emit (action, rotate_signals[ROTATE], 0, + actor, (gdouble) 0.0, + &retval); + } + else + { + gfloat mult[2]; + gfloat norm; + gdouble angle; + + /* Computes angle between the 2 initial touch points and the + current position of the 2 touch points. */ + norm = sqrt (vector[0] * vector[0] + vector[1] * vector[1]); + norm = (priv->initial_vector[0] * vector[0] + + priv->initial_vector[1] * vector[1]) / (priv->initial_vector_norm * norm); + + if ((norm >= -1.0) && (norm <= 1.0)) + angle = acos (norm); + else + angle = 0; + + /* The angle given is comprise between 0 and 180 degrees, we + need some logic on top to get a value between 0 and 360. */ + mult[0] = priv->initial_vector[0] * vector[1] - + priv->initial_vector[1] * vector[0]; + mult[1] = priv->initial_vector[1] * vector[0] - + priv->initial_vector[0] * vector[1]; + + if (mult[0] < 0) + angle = -angle; + + /* Convert radians to degrees */ + angle = angle * 180.0 / G_PI; + + g_signal_emit (action, rotate_signals[ROTATE], 0, + actor, angle, + &retval); + } + + return TRUE; +} + +static void +clutter_rotate_action_gesture_cancel (ClutterGestureAction *action, + ClutterActor *actor) +{ + gboolean retval; + + g_signal_emit (action, rotate_signals[ROTATE], 0, + actor, (gdouble) 0.0, + &retval); +} + +static void +clutter_rotate_action_constructed (GObject *gobject) +{ + ClutterGestureAction *gesture; + + gesture = CLUTTER_GESTURE_ACTION (gobject); + clutter_gesture_action_set_threshold_trigger_edge (gesture, CLUTTER_GESTURE_TRIGGER_EDGE_NONE); +} + +static void +clutter_rotate_action_class_init (ClutterRotateActionClass *klass) +{ + ClutterGestureActionClass *gesture_class = + CLUTTER_GESTURE_ACTION_CLASS (klass); + GObjectClass *object_class = + G_OBJECT_CLASS (klass); + + klass->rotate = clutter_rotate_action_real_rotate; + + object_class->constructed = clutter_rotate_action_constructed; + + gesture_class->gesture_begin = clutter_rotate_action_gesture_begin; + gesture_class->gesture_progress = clutter_rotate_action_gesture_progress; + gesture_class->gesture_cancel = clutter_rotate_action_gesture_cancel; + + /** + * ClutterRotateAction::rotate: + * @action: the #ClutterRotateAction that emitted the signal + * @actor: the #ClutterActor attached to the @action + * @angle: the difference of angle of rotation between the initial + * rotation and the current rotation + * + * The ::rotate signal is emitted when a rotate gesture is + * recognized on the attached actor and when the gesture is + * cancelled (in this case with an angle value of 0). + * + * Return value: %TRUE if the rotation should continue, and %FALSE if + * the rotation should be cancelled. + * + * Since: 1.12 + */ + rotate_signals[ROTATE] = + g_signal_new (I_("rotate"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterRotateActionClass, rotate), + _clutter_boolean_continue_accumulator, NULL, + _clutter_marshal_BOOLEAN__OBJECT_DOUBLE, + G_TYPE_BOOLEAN, 2, + CLUTTER_TYPE_ACTOR, + G_TYPE_DOUBLE); +} + +static void +clutter_rotate_action_init (ClutterRotateAction *self) +{ + ClutterGestureAction *gesture; + + self->priv = clutter_rotate_action_get_instance_private (self); + + gesture = CLUTTER_GESTURE_ACTION (self); + clutter_gesture_action_set_n_touch_points (gesture, 2); +} + +/** + * clutter_rotate_action_new: + * + * Creates a new #ClutterRotateAction instance + * + * Return value: the newly created #ClutterRotateAction + * + * Since: 1.12 + */ +ClutterAction * +clutter_rotate_action_new (void) +{ + return g_object_new (CLUTTER_TYPE_ROTATE_ACTION, NULL); +} diff --git a/clutter/clutter/clutter-rotate-action.h b/clutter/clutter/clutter-rotate-action.h new file mode 100644 index 0000000..c739054 --- /dev/null +++ b/clutter/clutter/clutter-rotate-action.h @@ -0,0 +1,100 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2012 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 . + * + * Author: + * Lionel Landwerlin + */ + +#ifndef __CLUTTER_ROTATE_ACTION_H__ +#define __CLUTTER_ROTATE_ACTION_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_ROTATE_ACTION (clutter_rotate_action_get_type ()) +#define CLUTTER_ROTATE_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ROTATE_ACTION, ClutterRotateAction)) +#define CLUTTER_IS_ROTATE_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ROTATE_ACTION)) +#define CLUTTER_ROTATE_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_ROTATE_ACTION, ClutterRotateActionClass)) +#define CLUTTER_IS_ROTATE_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_ROTATE_ACTION)) +#define CLUTTER_ROTATE_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_ROTATE_ACTION, ClutterRotateActionClass)) + +typedef struct _ClutterRotateAction ClutterRotateAction; +typedef struct _ClutterRotateActionPrivate ClutterRotateActionPrivate; +typedef struct _ClutterRotateActionClass ClutterRotateActionClass; + +/** + * ClutterRotateAction: + * + * The #ClutterRotateAction structure contains + * only private data and should be accessed using the provided API + * + * Since: 1.12 + */ +struct _ClutterRotateAction +{ + /*< private >*/ + ClutterGestureAction parent_instance; + + ClutterRotateActionPrivate *priv; +}; + +/** + * ClutterRotateActionClass: + * @rotate: class handler for the #ClutterRotateAction::rotate signal + * + * The #ClutterRotateActionClass structure contains + * only private data. + * + * Since: 1.12 + */ +struct _ClutterRotateActionClass +{ + /*< private >*/ + ClutterGestureActionClass parent_class; + + /*< public >*/ + gboolean (* rotate) (ClutterRotateAction *action, + ClutterActor *actor, + gdouble angle); + + /*< private >*/ + void (* _clutter_rotate_action1) (void); + void (* _clutter_rotate_action2) (void); + void (* _clutter_rotate_action3) (void); + void (* _clutter_rotate_action4) (void); + void (* _clutter_rotate_action5) (void); + void (* _clutter_rotate_action6) (void); + void (* _clutter_rotate_action7) (void); +}; + +CLUTTER_AVAILABLE_IN_1_12 +GType clutter_rotate_action_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_12 +ClutterAction *clutter_rotate_action_new (void); + +G_END_DECLS + +#endif /* __CLUTTER_ROTATE_ACTION_H__ */ diff --git a/clutter/clutter/clutter-script-parser.c b/clutter/clutter/clutter-script-parser.c new file mode 100644 index 0000000..5b7dcd8 --- /dev/null +++ b/clutter/clutter/clutter-script-parser.c @@ -0,0 +1,2256 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2006, 2007, 2008 OpenedHand Ltd + * Copyright (C) 2009 Intel Corportation + * + * 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 . + * + * Original author: + * + * Emmanuele Bassi + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include +#include + +#include +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include "deprecated/clutter-container.h" +#include "deprecated/clutter-alpha.h" + +#include "clutter-actor.h" +#include "clutter-debug.h" +#include "clutter-enum-types.h" + +#include "clutter-script.h" +#include "clutter-script-private.h" +#include "clutter-scriptable.h" + +#include "clutter-stage-manager.h" + +#include "clutter-private.h" + +static void clutter_script_parser_object_end (JsonParser *parser, + JsonObject *object); +static void clutter_script_parser_parse_end (JsonParser *parser); + +#define clutter_script_parser_get_type _clutter_script_parser_get_type + +G_DEFINE_TYPE (ClutterScriptParser, clutter_script_parser, JSON_TYPE_PARSER); + +static void +clutter_script_parser_class_init (ClutterScriptParserClass *klass) +{ + JsonParserClass *parser_class = JSON_PARSER_CLASS (klass); + + parser_class->object_end = clutter_script_parser_object_end; + parser_class->parse_end = clutter_script_parser_parse_end; +} + +static void +clutter_script_parser_init (ClutterScriptParser *parser) +{ +} + +GType +_clutter_script_get_type_from_symbol (const gchar *symbol) +{ + static GModule *module = NULL; + GTypeGetFunc func; + GType gtype = G_TYPE_INVALID; + + if (!module) + module = g_module_open (NULL, 0); + + if (g_module_symbol (module, symbol, (gpointer)&func)) + gtype = func (); + + return gtype; +} + +GType +_clutter_script_get_type_from_class (const gchar *name) +{ + static GModule *module = NULL; + GString *symbol_name = g_string_sized_new (64); + GType gtype = G_TYPE_INVALID; + GTypeGetFunc func; + gchar *symbol; + gint i; + + if (G_UNLIKELY (!module)) + module = g_module_open (NULL, 0); + + for (i = 0; name[i] != '\0'; i++) + { + gchar c = name[i]; + + /* the standard naming policy for GObject-based libraries + * is: + * + * NAME := INITIAL_WORD WORD+ + * INITIAL_WORD := [A-Z][a-z0-9]* + * WORD := [A-Z]{1,2}[a-z0-9]+ | [A-Z]{2,} + * + * for instance: + * + * GString -> g_string + * GtkCTree -> gtk_ctree + * ClutterX11TexturePixmap -> clutter_x11_texture_pixmap + * + * see: + * + * http://mail.gnome.org/archives/gtk-devel-list/2007-June/msg00022.html + * + * and: + * + * http://git.gnome.org/cgit/gtk+/plain/gtk/gtkbuilderparser.c + */ + + if ((c == g_ascii_toupper (c) && + i > 0 && name[i - 1] != g_ascii_toupper (name[i - 1])) || + (i > 2 && name[i] == g_ascii_toupper (name[i]) && + name[i - 1] == g_ascii_toupper (name[i - 1]) && + name[i - 2] == g_ascii_toupper (name[i - 2]))) + g_string_append_c (symbol_name, '_'); + + g_string_append_c (symbol_name, g_ascii_tolower (c)); + } + + g_string_append (symbol_name, "_get_type"); + + symbol = g_string_free (symbol_name, FALSE); + + if (g_module_symbol (module, symbol, (gpointer)&func)) + { + CLUTTER_NOTE (SCRIPT, "Type function: %s", symbol); + gtype = func (); + } + + g_free (symbol); + + return gtype; +} + +/* + * clutter_script_enum_from_string: + * @type: a #GType for an enumeration type + * @string: the enumeration value as a string + * @enum_value: (out): return location for the enumeration value as an integer + * + * Converts an enumeration value inside @string into a numeric + * value and places it into @enum_value. + * + * The enumeration value can be an integer, the enumeration nick + * or the enumeration name, as part of the #GEnumValue structure. + * + * Return value: %TRUE if the conversion was successfull. + */ +gboolean +_clutter_script_enum_from_string (GType type, + const gchar *string, + gint *enum_value) +{ + GEnumClass *eclass; + GEnumValue *ev; + gchar *endptr; + gint value; + gboolean retval = TRUE; + + g_return_val_if_fail (G_TYPE_IS_ENUM (type), 0); + g_return_val_if_fail (string != NULL, 0); + + value = strtoul (string, &endptr, 0); + if (endptr != string) /* parsed a number */ + *enum_value = value; + else + { + eclass = g_type_class_ref (type); + ev = g_enum_get_value_by_name (eclass, string); + if (!ev) + ev = g_enum_get_value_by_nick (eclass, string); + + if (ev) + *enum_value = ev->value; + else + retval = FALSE; + + g_type_class_unref (eclass); + } + + return retval; +} + +gboolean +_clutter_script_flags_from_string (GType type, + const gchar *string, + gint *flags_value) +{ + gchar *endptr, *prevptr; + guint i, j, ret, value; + gchar *flagstr; + GFlagsValue *fv; + const gchar *flag; + + g_return_val_if_fail (G_TYPE_IS_FLAGS (type), 0); + g_return_val_if_fail (string != NULL, 0); + + ret = TRUE; + + value = strtoul (string, &endptr, 0); + if (endptr != string) /* parsed a number */ + *flags_value = value; + else + { + GFlagsClass *fclass; + + fclass = g_type_class_ref (type); + + flagstr = g_strdup (string); + for (value = i = j = 0; ; i++) + { + gboolean eos = (flagstr[i] == '\0') ? TRUE : FALSE; + + if (!eos && flagstr[i] != '|') + continue; + + flag = &flagstr[j]; + endptr = &flagstr[i]; + + if (!eos) + { + flagstr[i++] = '\0'; + j = i; + } + + /* trim spaces */ + for (;;) + { + gunichar ch = g_utf8_get_char (flag); + if (!g_unichar_isspace (ch)) + break; + + flag = g_utf8_next_char (flag); + } + + while (endptr > flag) + { + gunichar ch; + + prevptr = g_utf8_prev_char (endptr); + + ch = g_utf8_get_char (prevptr); + if (!g_unichar_isspace (ch)) + break; + + endptr = prevptr; + } + + if (endptr > flag) + { + *endptr = '\0'; + + fv = g_flags_get_value_by_name (fclass, flag); + + if (!fv) + fv = g_flags_get_value_by_nick (fclass, flag); + + if (fv) + value |= fv->value; + else + { + ret = FALSE; + break; + } + } + + if (eos) + { + *flags_value = value; + break; + } + } + + g_free (flagstr); + + g_type_class_unref (fclass); + } + + return ret; +} + +static gboolean +parse_knot_from_array (JsonArray *array, + ClutterKnot *knot) +{ + if (json_array_get_length (array) != 2) + return FALSE; + + knot->x = json_array_get_int_element (array, 0); + knot->y = json_array_get_int_element (array, 1); + + return TRUE; +} + +static gboolean +parse_knot_from_object (JsonObject *object, + ClutterKnot *knot) +{ + if (json_object_has_member (object, "x")) + knot->x = json_object_get_int_member (object, "x"); + else + knot->x = 0; + + if (json_object_has_member (object, "y")) + knot->y = json_object_get_int_member (object, "y"); + else + knot->y = 0; + + return TRUE; +} + +gboolean +_clutter_script_parse_knot (ClutterScript *script, + JsonNode *node, + ClutterKnot *knot) +{ + g_return_val_if_fail (CLUTTER_IS_SCRIPT (script), FALSE); + g_return_val_if_fail (node != NULL, FALSE); + g_return_val_if_fail (knot != NULL, FALSE); + + switch (JSON_NODE_TYPE (node)) + { + case JSON_NODE_ARRAY: + return parse_knot_from_array (json_node_get_array (node), knot); + + case JSON_NODE_OBJECT: + return parse_knot_from_object (json_node_get_object (node), knot); + + default: + break; + } + + return FALSE; +} + +static gboolean +parse_geometry_from_array (JsonArray *array, + ClutterGeometry *geometry) +{ + if (json_array_get_length (array) != 4) + return FALSE; + + geometry->x = json_array_get_int_element (array, 0); + geometry->y = json_array_get_int_element (array, 1); + geometry->width = json_array_get_int_element (array, 2); + geometry->height = json_array_get_int_element (array, 3); + + return TRUE; +} + +static gboolean +parse_geometry_from_object (JsonObject *object, + ClutterGeometry *geometry) +{ + if (json_object_has_member (object, "x")) + geometry->x = json_object_get_int_member (object, "x"); + else + geometry->x = 0; + + if (json_object_has_member (object, "y")) + geometry->y = json_object_get_int_member (object, "y"); + else + geometry->y = 0; + + if (json_object_has_member (object, "width")) + geometry->width = json_object_get_int_member (object, "width"); + else + geometry->width = 0; + + if (json_object_has_member (object, "height")) + geometry->height = json_object_get_int_member (object, "height"); + else + geometry->height = 0; + + return TRUE; +} + +gboolean +_clutter_script_parse_geometry (ClutterScript *script, + JsonNode *node, + ClutterGeometry *geometry) +{ + g_return_val_if_fail (CLUTTER_IS_SCRIPT (script), FALSE); + g_return_val_if_fail (node != NULL, FALSE); + g_return_val_if_fail (geometry != NULL, FALSE); + + switch (JSON_NODE_TYPE (node)) + { + case JSON_NODE_ARRAY: + return parse_geometry_from_array (json_node_get_array (node), geometry); + + case JSON_NODE_OBJECT: + return parse_geometry_from_object (json_node_get_object (node), geometry); + + default: + break; + } + + return FALSE; +} + +static gboolean +parse_color_from_array (JsonArray *array, + ClutterColor *color) +{ + if (json_array_get_length (array) != 3 || + json_array_get_length (array) != 4) + return FALSE; + + color->red = CLAMP (json_array_get_int_element (array, 0), 0, 255); + color->green = CLAMP (json_array_get_int_element (array, 1), 0, 255); + color->blue = CLAMP (json_array_get_int_element (array, 2), 0, 255); + + if (json_array_get_length (array) == 4) + color->alpha = CLAMP (json_array_get_int_element (array, 3), 0, 255); + else + color->alpha = 255; + + return TRUE; +} + +static gboolean +parse_color_from_object (JsonObject *object, + ClutterColor *color) +{ + if (json_object_has_member (object, "red")) + color->red = CLAMP (json_object_get_int_member (object, "red"), 0, 255); + else + color->red = 0; + + if (json_object_has_member (object, "green")) + color->green = CLAMP (json_object_get_int_member (object, "green"), 0, 255); + else + color->green = 0; + + if (json_object_has_member (object, "blue")) + color->blue = CLAMP (json_object_get_int_member (object, "blue"), 0, 255); + else + color->blue = 0; + + if (json_object_has_member (object, "alpha")) + color->alpha = CLAMP (json_object_get_int_member (object, "alpha"), 0, 255); + else + color->alpha = 255; + + return TRUE; +} + +gboolean +_clutter_script_parse_color (ClutterScript *script, + JsonNode *node, + ClutterColor *color) +{ + g_return_val_if_fail (CLUTTER_IS_SCRIPT (script), FALSE); + g_return_val_if_fail (node != NULL, FALSE); + g_return_val_if_fail (color != NULL, FALSE); + + switch (JSON_NODE_TYPE (node)) + { + case JSON_NODE_ARRAY: + return parse_color_from_array (json_node_get_array (node), color); + + case JSON_NODE_OBJECT: + return parse_color_from_object (json_node_get_object (node), color); + + case JSON_NODE_VALUE: + return clutter_color_from_string (color, json_node_get_string (node)); + + default: + break; + } + + return FALSE; +} + +static gboolean +parse_point_from_array (JsonArray *array, + ClutterPoint *point) +{ + if (json_array_get_length (array) != 2) + return FALSE; + + point->x = json_array_get_double_element (array, 0); + point->y = json_array_get_double_element (array, 1); + + return TRUE; +} + +static gboolean +parse_point_from_object (JsonObject *object, + ClutterPoint *point) +{ + if (json_object_has_member (object, "x")) + point->x = json_object_get_double_member (object, "x"); + else + point->x = 0.f; + + if (json_object_has_member (object, "y")) + point->y = json_object_get_double_member (object, "y"); + else + point->y = 0.f; + + return TRUE; +} + +gboolean +_clutter_script_parse_point (ClutterScript *script, + JsonNode *node, + ClutterPoint *point) +{ + g_return_val_if_fail (CLUTTER_IS_SCRIPT (script), FALSE); + g_return_val_if_fail (node != NULL, FALSE); + g_return_val_if_fail (point != NULL, FALSE); + + switch (JSON_NODE_TYPE (node)) + { + case JSON_NODE_ARRAY: + return parse_point_from_array (json_node_get_array (node), point); + + case JSON_NODE_OBJECT: + return parse_point_from_object (json_node_get_object (node), point); + + default: + break; + } + + return FALSE; +} + +static gboolean +parse_size_from_array (JsonArray *array, + ClutterSize *size) +{ + if (json_array_get_length (array) != 2) + return FALSE; + + size->width = json_array_get_double_element (array, 0); + size->height = json_array_get_double_element (array, 1); + + return TRUE; +} + +static gboolean +parse_size_from_object (JsonObject *object, + ClutterSize *size) +{ + if (json_object_has_member (object, "width")) + size->width = json_object_get_double_member (object, "width"); + else + size->width = 0.f; + + if (json_object_has_member (object, "height")) + size->height = json_object_get_double_member (object, "height"); + else + size->height = 0.f; + + return TRUE; +} + +gboolean +_clutter_script_parse_size (ClutterScript *script, + JsonNode *node, + ClutterSize *size) +{ + g_return_val_if_fail (CLUTTER_IS_SCRIPT (script), FALSE); + g_return_val_if_fail (node != NULL, FALSE); + g_return_val_if_fail (size != NULL, FALSE); + + switch (JSON_NODE_TYPE (node)) + { + case JSON_NODE_ARRAY: + return parse_size_from_array (json_node_get_array (node), size); + + case JSON_NODE_OBJECT: + return parse_size_from_object (json_node_get_object (node), size); + + default: + break; + } + + return FALSE; +} + +const gchar * +_clutter_script_get_id_from_node (JsonNode *node) +{ + JsonObject *object; + + switch (JSON_NODE_TYPE (node)) + { + case JSON_NODE_OBJECT: + object = json_node_get_object (node); + if (json_object_has_member (object, "id")) + return json_object_get_string_member (object, "id"); + break; + + case JSON_NODE_VALUE: + return json_node_get_string (node); + + default: + break; + } + + return NULL; +} + +static GList * +parse_children (ObjectInfo *oinfo, + JsonNode *node) +{ + JsonArray *array; + GList *retval; + guint array_len, i; + + if (JSON_NODE_TYPE (node) != JSON_NODE_ARRAY) + return NULL; + + retval = oinfo->children; + + array = json_node_get_array (node); + array_len = json_array_get_length (array); + + for (i = 0; i < array_len; i++) + { + JsonNode *child = json_array_get_element (array, i); + const gchar *id_; + + id_ = _clutter_script_get_id_from_node (child); + if (id_ != NULL) + retval = g_list_prepend (retval, g_strdup (id_)); + } + + return g_list_reverse (retval); +} + +static GList * +parse_signals (ClutterScript *script, + ObjectInfo *oinfo, + JsonNode *node) +{ + JsonArray *array; + GList *retval; + guint array_len, i; + + if (JSON_NODE_TYPE (node) != JSON_NODE_ARRAY) + { + _clutter_script_warn_invalid_value (script, "signals", "Array", node); + return NULL; + } + + retval = oinfo->signals; + array = json_node_get_array (node); + array_len = json_array_get_length (array); + + for (i = 0; i < array_len; i++) + { + JsonNode *val = json_array_get_element (array, i); + SignalInfo *sinfo = NULL; + JsonObject *object; + const gchar *name; + + if (JSON_NODE_TYPE (val) != JSON_NODE_OBJECT) + { + _clutter_script_warn_invalid_value (script, + "signals array", "Object", + node); + continue; + } + + object = json_node_get_object (val); + + /* mandatory: "name" */ + if (!json_object_has_member (object, "name")) + { + _clutter_script_warn_missing_attribute (script, NULL, "name"); + continue; + } + else + { + name = json_object_get_string_member (object, "name"); + if (!name) + { + _clutter_script_warn_invalid_value (script, + "name", "string", + val); + continue; + } + } + + /* mandatory: "target-state" or "handler" */ + if (json_object_has_member (object, "target-state")) + { + const gchar *state = NULL; + const gchar *target = NULL; + gboolean warp_to = FALSE; + + target = json_object_get_string_member (object, "target-state"); + if (target == NULL) + { + _clutter_script_warn_invalid_value (script, + "target-state", "string", + val); + continue; + } + + if (json_object_has_member (object, "states")) + state = json_object_get_string_member (object, "states"); + + if (json_object_has_member (object, "warp")) + warp_to = json_object_get_boolean_member (object, "warp"); + + CLUTTER_NOTE (SCRIPT, + "Added signal '%s' (states:%s, target-state:%s, warp:%s)", + name, + state != NULL ? state : "", target, + warp_to ? "true" : "false"); + + sinfo = g_slice_new0 (SignalInfo); + sinfo->is_handler = FALSE; + sinfo->name = g_strdup (name); + sinfo->state = g_strdup (state); + sinfo->target = g_strdup (target); + sinfo->warp_to = warp_to; + } + else if (json_object_has_member (object, "handler")) + { + const gchar *handler; + const gchar *connect; + GConnectFlags flags = 0; + + handler = json_object_get_string_member (object, "handler"); + if (handler == NULL) + { + _clutter_script_warn_invalid_value (script, + "handler", "string", + val); + continue; + } + + /* optional: "object" */ + if (json_object_has_member (object, "object")) + connect = json_object_get_string_member (object, "object"); + else + connect = NULL; + + /* optional: "after" */ + if (json_object_has_member (object, "after")) + { + if (json_object_get_boolean_member (object, "after")) + flags |= G_CONNECT_AFTER; + } + + /* optional: "swapped" */ + if (json_object_has_member (object, "swapped")) + { + if (json_object_get_boolean_member (object, "swapped")) + flags |= G_CONNECT_SWAPPED; + } + + CLUTTER_NOTE (SCRIPT, + "Added signal '%s' (handler:%s, object:%s, flags:%d)", + name, + handler, connect, flags); + + sinfo = g_slice_new0 (SignalInfo); + sinfo->is_handler = TRUE; + sinfo->name = g_strdup (name); + sinfo->handler = g_strdup (handler); + sinfo->object = g_strdup (connect); + sinfo->flags = flags; + } + else + _clutter_script_warn_missing_attribute (script, + NULL, + "handler or state"); + if (sinfo != NULL) + retval = g_list_prepend (retval, sinfo); + } + + return retval; +} + +static ClutterTimeline * +construct_timeline (ClutterScript *script, + JsonObject *object) +{ + ClutterTimeline *retval = NULL; + ObjectInfo *oinfo; + GList *members, *l; + + /* we fake an ObjectInfo so we can reuse clutter_script_construct_object() + * here; we do not save it inside the hash table, because if this had + * been a named object then we wouldn't have ended up here in the first + * place + */ + oinfo = g_slice_new0 (ObjectInfo); + oinfo->gtype = CLUTTER_TYPE_TIMELINE; + oinfo->id = g_strdup ("dummy"); + + members = json_object_get_members (object); + for (l = members; l != NULL; l = l->next) + { + const gchar *name = l->data; + JsonNode *node = json_object_get_member (object, name); + PropertyInfo *pinfo = g_slice_new0 (PropertyInfo); + + pinfo->name = g_strdelimit (g_strdup (name), G_STR_DELIMITERS, '-'); + pinfo->node = json_node_copy (node); + + oinfo->properties = g_list_prepend (oinfo->properties, pinfo); + } + + g_list_free (members); + + _clutter_script_construct_object (script, oinfo); + _clutter_script_apply_properties (script, oinfo); + retval = CLUTTER_TIMELINE (oinfo->object); + + /* we transfer ownership to the alpha function, so we ref before + * destroying the ObjectInfo to avoid the timeline going away + */ + g_object_ref (retval); + object_info_free (oinfo); + + return retval; +} + +/* define the names of the animation modes to match the ones + * that developers might be more accustomed to + */ +static const struct +{ + const gchar *name; + ClutterAnimationMode mode; +} animation_modes[] = { + { "linear", CLUTTER_LINEAR }, + { "easeInQuad", CLUTTER_EASE_IN_QUAD }, + { "easeOutQuad", CLUTTER_EASE_OUT_QUAD }, + { "easeInOutQuad", CLUTTER_EASE_IN_OUT_QUAD }, + { "easeInCubic", CLUTTER_EASE_IN_CUBIC }, + { "easeOutCubic", CLUTTER_EASE_OUT_CUBIC }, + { "easeInOutCubic", CLUTTER_EASE_IN_OUT_CUBIC }, + { "easeInQuart", CLUTTER_EASE_IN_QUART }, + { "easeOutQuart", CLUTTER_EASE_OUT_QUART }, + { "easeInOutQuart", CLUTTER_EASE_IN_OUT_QUART }, + { "easeInQuint", CLUTTER_EASE_IN_QUINT }, + { "easeOutQuint", CLUTTER_EASE_OUT_QUINT }, + { "easeInOutQuint", CLUTTER_EASE_IN_OUT_QUINT }, + { "easeInSine", CLUTTER_EASE_IN_SINE }, + { "easeOutSine", CLUTTER_EASE_OUT_SINE }, + { "easeInOutSine", CLUTTER_EASE_IN_OUT_SINE }, + { "easeInExpo", CLUTTER_EASE_IN_EXPO }, + { "easeOutExpo", CLUTTER_EASE_OUT_EXPO }, + { "easeInOutExpo", CLUTTER_EASE_IN_OUT_EXPO }, + { "easeInCirc", CLUTTER_EASE_IN_CIRC }, + { "easeOutCirc", CLUTTER_EASE_OUT_CIRC }, + { "easeInOutCirc", CLUTTER_EASE_IN_OUT_CIRC }, + { "easeInElastic", CLUTTER_EASE_IN_ELASTIC }, + { "easeOutElastic", CLUTTER_EASE_OUT_ELASTIC }, + { "easeInOutElastic", CLUTTER_EASE_IN_OUT_ELASTIC }, + { "easeInBack", CLUTTER_EASE_IN_BACK }, + { "easeOutBack", CLUTTER_EASE_OUT_BACK }, + { "easeInOutBack", CLUTTER_EASE_IN_OUT_BACK }, + { "easeInBounce", CLUTTER_EASE_IN_BOUNCE }, + { "easeOutBounce", CLUTTER_EASE_OUT_BOUNCE }, + { "easeInOutBounce", CLUTTER_EASE_IN_OUT_BOUNCE }, +}; + +static const gint n_animation_modes = G_N_ELEMENTS (animation_modes); + +gulong +_clutter_script_resolve_animation_mode (JsonNode *node) +{ + gint i, res = CLUTTER_CUSTOM_MODE; + + if (JSON_NODE_TYPE (node) != JSON_NODE_VALUE) + return CLUTTER_CUSTOM_MODE; + + if (json_node_get_value_type (node) == G_TYPE_INT64) + return json_node_get_int (node); + + if (json_node_get_value_type (node) == G_TYPE_STRING) + { + const gchar *name = json_node_get_string (node); + + /* XXX - we might be able to optimize by changing the ordering + * of the animation_modes array, e.g. + * - special casing linear + * - tokenizing ('ease', 'In', 'Sine') and matching on token + * - binary searching? + */ + for (i = 0; i < n_animation_modes; i++) + { + if (strcmp (animation_modes[i].name, name) == 0) + return animation_modes[i].mode; + } + + if (_clutter_script_enum_from_string (CLUTTER_TYPE_ANIMATION_MODE, + name, + &res)) + return res; + + g_warning ("Unable to find the animation mode '%s'", name); + } + + return CLUTTER_CUSTOM_MODE; +} + +static ClutterAlphaFunc +resolve_alpha_func (const gchar *name) +{ + static GModule *module = NULL; + ClutterAlphaFunc func; + + CLUTTER_NOTE (SCRIPT, "Looking up '%s' alpha function", name); + + if (G_UNLIKELY (!module)) + module = g_module_open (NULL, 0); + + if (g_module_symbol (module, name, (gpointer) &func)) + { + CLUTTER_NOTE (SCRIPT, "Found '%s' alpha function in the symbols table", + name); + return func; + } + + return NULL; +} + +GObject * +_clutter_script_parse_alpha (ClutterScript *script, + JsonNode *node) +{ + GObject *retval = NULL; + JsonObject *object; + ClutterTimeline *timeline = NULL; + ClutterAlphaFunc alpha_func = NULL; + ClutterAnimationMode mode = CLUTTER_CUSTOM_MODE; + JsonNode *val; + gboolean unref_timeline = FALSE; + + if (JSON_NODE_TYPE (node) != JSON_NODE_OBJECT) + return NULL; + + object = json_node_get_object (node); + + val = json_object_get_member (object, "timeline"); + if (val) + { + if (JSON_NODE_TYPE (val) == JSON_NODE_VALUE && + json_node_get_string (val) != NULL) + { + const gchar *id_ = json_node_get_string (val); + + timeline = + CLUTTER_TIMELINE (clutter_script_get_object (script, id_)); + } + else if (JSON_NODE_TYPE (val) == JSON_NODE_OBJECT) + { + timeline = construct_timeline (script, json_node_get_object (val)); + unref_timeline = TRUE; + } + } + + val = json_object_get_member (object, "mode"); + if (val != NULL) + mode = _clutter_script_resolve_animation_mode (val); + + if (mode == CLUTTER_CUSTOM_MODE) + { + val = json_object_get_member (object, "function"); + if (val && json_node_get_string (val) != NULL) + { + alpha_func = resolve_alpha_func (json_node_get_string (val)); + if (!alpha_func) + { + g_warning ("Unable to find the function '%s' in the " + "Clutter alpha functions or the symbols table", + json_node_get_string (val)); + } + } + } + + CLUTTER_NOTE (SCRIPT, "Parsed alpha: %s timeline (%p) (mode:%d, func:%p)", + unref_timeline ? "implicit" : "explicit", + timeline ? timeline : 0x0, + mode != CLUTTER_CUSTOM_MODE ? mode : 0, + alpha_func ? alpha_func : 0x0); + + retval = g_object_new (CLUTTER_TYPE_ALPHA, NULL); + + if (mode != CLUTTER_CUSTOM_MODE) + clutter_alpha_set_mode (CLUTTER_ALPHA (retval), mode); + + if (alpha_func != NULL) + clutter_alpha_set_func (CLUTTER_ALPHA (retval), alpha_func, NULL, NULL); + + clutter_alpha_set_timeline (CLUTTER_ALPHA (retval), timeline); + + /* if we created an implicit timeline, the Alpha has full ownership + * of it now, since it won't be accessible from ClutterScript + */ + if (unref_timeline) + g_object_unref (timeline); + + return retval; +} + +static void +clutter_script_parser_object_end (JsonParser *json_parser, + JsonObject *object) +{ + ClutterScriptParser *parser = CLUTTER_SCRIPT_PARSER (json_parser); + ClutterScript *script = parser->script; + ObjectInfo *oinfo; + JsonNode *val; + const gchar *id_; + GList *members, *l; + + /* if the object definition does not have an 'id' field we'll + * fake one for it... + */ + if (!json_object_has_member (object, "id")) + { + gchar *fake; + + /* ... unless it doesn't even have a type - in which case + * it is an internal object definition and we're not + * supposed to touch it + */ + if (!json_object_has_member (object, "type")) + return; + + fake = _clutter_script_generate_fake_id (script); + json_object_set_string_member (object, "id", fake); + + CLUTTER_NOTE (SCRIPT, + "Adding fake id '%s' to object of type '%s'", + json_object_get_string_member (object, "id"), + json_object_get_string_member (object, "type")); + + g_free (fake); + } + + if (!json_object_has_member (object, "type")) + { + val = json_object_get_member (object, "id"); + + _clutter_script_warn_missing_attribute (script, + json_node_get_string (val), + "type"); + return; + } + + id_ = json_object_get_string_member (object, "id"); + CLUTTER_NOTE (SCRIPT, "Getting object info for object '%s'", id_); + + oinfo = _clutter_script_get_object_info (script, id_); + if (oinfo == NULL) + { + const gchar *class_name; + + oinfo = g_slice_new0 (ObjectInfo); + oinfo->merge_id = _clutter_script_get_last_merge_id (script); + oinfo->id = g_strdup (id_); + oinfo->has_unresolved = TRUE; + + class_name = json_object_get_string_member (object, "type"); + oinfo->class_name = g_strdup (class_name); + + if (json_object_has_member (object, "type_func")) + { + const gchar *type_func; + + type_func = json_object_get_string_member (object, "type_func"); + oinfo->type_func = g_strdup (type_func); + + /* remove the type_func member; we don't want it to + * pollute the object members + */ + json_object_remove_member (object, "type_func"); + } + } + + if (json_object_has_member (object, "children")) + { + val = json_object_get_member (object, "children"); + oinfo->children = parse_children (oinfo, val); + + json_object_remove_member (object, "children"); + + oinfo->has_unresolved = TRUE; + } + + if (json_object_has_member (object, "signals")) + { + val = json_object_get_member (object, "signals"); + oinfo->signals = parse_signals (script, oinfo, val); + + json_object_remove_member (object, "signals"); + + oinfo->has_unresolved = TRUE; + } + + if (strcmp (oinfo->class_name, "ClutterStage") == 0 && + json_object_has_member (object, "is-default")) + { + oinfo->is_actor = TRUE; + oinfo->is_stage = TRUE; + oinfo->is_stage_default = + json_object_get_boolean_member (object, "is-default"); + + json_object_remove_member (object, "is-default"); + } + else + oinfo->is_stage_default = FALSE; + + members = json_object_get_members (object); + for (l = members; l; l = l->next) + { + const gchar *name = l->data; + PropertyInfo *pinfo; + JsonNode *node; + + CLUTTER_NOTE (SCRIPT, "Object '%s' member '%s'", + oinfo->id, + name); + + /* we have already parsed these */ + if (strcmp (name, "id") == 0 || strcmp (name, "type") == 0) + continue; + + node = json_object_get_member (object, name); + + /* this should not really happen; we're getting a list of + * member names, and if one does not map a real member + * value then it's likely that something has gone wrong + */ + if (G_UNLIKELY (node == NULL)) + { + CLUTTER_NOTE (SCRIPT, + "Empty node for member '%s' of object '%s' (type: %s)", + name, + oinfo->id, + oinfo->class_name); + continue; + } + + pinfo = g_slice_new (PropertyInfo); + + pinfo->name = g_strdup (name); + pinfo->node = json_node_copy (node); + pinfo->pspec = NULL; + pinfo->is_child = g_str_has_prefix (name, "child::") ? TRUE : FALSE; + pinfo->is_layout = g_str_has_prefix (name, "layout::") ? TRUE : FALSE; + + oinfo->properties = g_list_prepend (oinfo->properties, pinfo); + oinfo->has_unresolved = TRUE; + } + + g_list_free (members); + + CLUTTER_NOTE (SCRIPT, + "Added object '%s' (type:%s, id:%d, props:%d, signals:%d)", + oinfo->id, + oinfo->class_name, + oinfo->merge_id, + g_list_length (oinfo->properties), + g_list_length (oinfo->signals)); + + _clutter_script_add_object_info (script, oinfo); + _clutter_script_construct_object (script, oinfo); +} + +static void +clutter_script_parser_parse_end (JsonParser *parser) +{ + clutter_script_ensure_objects (CLUTTER_SCRIPT_PARSER (parser)->script); +} + +gboolean +_clutter_script_parse_translatable_string (ClutterScript *script, + JsonNode *node, + char **str) +{ + JsonObject *obj; + const char *string, *domain, *context; + const char *res; + gboolean translatable; + + if (!JSON_NODE_HOLDS_OBJECT (node)) + return FALSE; + + obj = json_node_get_object (node); + if (!(json_object_has_member (obj, "translatable") && + json_object_has_member (obj, "string"))) + return FALSE; + + translatable = json_object_get_boolean_member (obj, "translatable"); + + string = json_object_get_string_member (obj, "string"); + if (string == NULL || *string == '\0') + return FALSE; + + if (json_object_has_member (obj, "context")) + context = json_object_get_string_member (obj, "context"); + else + context = NULL; + + if (json_object_has_member (obj, "domain")) + domain = json_object_get_string_member (obj, "domain"); + else + domain = NULL; + + if (domain == NULL || *domain == '\0') + domain = clutter_script_get_translation_domain (script); + + if (translatable) + { + if (context != NULL && *context != '\0') + res = g_dpgettext2 (domain, context, string); + else + res = g_dgettext (domain, string); + } + else + res = string; + + if (str != NULL) + *str = g_strdup (res); + + return TRUE; +} + +gboolean +_clutter_script_parse_node (ClutterScript *script, + GValue *value, + const gchar *name, + JsonNode *node, + GParamSpec *pspec) +{ + GValue node_value = G_VALUE_INIT; + gboolean retval = FALSE; + + g_return_val_if_fail (CLUTTER_IS_SCRIPT (script), FALSE); + g_return_val_if_fail (name != NULL, FALSE); + g_return_val_if_fail (node != NULL, FALSE); + + switch (JSON_NODE_TYPE (node)) + { + case JSON_NODE_OBJECT: + /* if we don't have a GParamSpec we can't infer the type + * of the property; this usually means that this property + * is a custom member that will be parsed by the Scriptable + * interface implementantion + */ + if (pspec == NULL && !G_IS_VALUE (value)) + return FALSE; + else + { + GType p_type; + ObjectInfo *oinfo; + const gchar *id_; + + if (G_IS_VALUE (value)) + p_type = G_VALUE_TYPE (value); + else + { + p_type = G_PARAM_SPEC_VALUE_TYPE (pspec); + g_value_init (value, p_type); + } + + if (g_type_is_a (p_type, G_TYPE_OBJECT)) + { + /* default GObject handling: we get the id and + * retrieve the ObjectInfo for it; since the object + * definitions are parsed leaf-first we are guaranteed + * to have a defined object at this point + */ + id_ = _clutter_script_get_id_from_node (node); + if (id_ == NULL || *id_ == '\0') + return FALSE; + + oinfo = _clutter_script_get_object_info (script, id_); + if (oinfo == NULL || oinfo->gtype == G_TYPE_INVALID ) + return FALSE; + + if (g_type_is_a (oinfo->gtype, p_type)) + { + /* force construction, even though it should + * not be necessary; we don't need the properties + * to be applied as well: they will when the + * ScriptParser finishes + */ + _clutter_script_construct_object (script, oinfo); + + g_value_set_object (value, oinfo->object); + + return TRUE; + } + } + else if (p_type == CLUTTER_TYPE_KNOT) + { + ClutterKnot knot = { 0, }; + + /* knot := { "x" : (int), "y" : (int) } */ + + if (_clutter_script_parse_knot (script, node, &knot)) + { + g_value_set_boxed (value, &knot); + return TRUE; + } + } + else if (p_type == CLUTTER_TYPE_GEOMETRY) + { + ClutterGeometry geom = { 0, }; + + /* geometry := { + * "x" : (int), + * "y" : (int), + * "width" : (int), + * "height" : (int) + * } + */ + + if (_clutter_script_parse_geometry (script, node, &geom)) + { + g_value_set_boxed (value, &geom); + return TRUE; + } + } + else if (p_type == CLUTTER_TYPE_COLOR) + { + ClutterColor color = { 0, }; + + /* color := { + * "red" : (int), + * "green" : (int), + * "blue" : (int), + * "alpha" : (int) + * } + */ + + if (_clutter_script_parse_color (script, node, &color)) + { + g_value_set_boxed (value, &color); + return TRUE; + } + } + else if (p_type == CLUTTER_TYPE_POINT) + { + ClutterPoint point = CLUTTER_POINT_INIT_ZERO; + + if (_clutter_script_parse_point (script, node, &point)) + { + g_value_set_boxed (value, &point); + return TRUE; + } + } + else if (p_type == CLUTTER_TYPE_SIZE) + { + ClutterSize size = CLUTTER_SIZE_INIT_ZERO; + + if (_clutter_script_parse_size (script, node, &size)) + { + g_value_set_boxed (value, &size); + return TRUE; + } + } + else if (p_type == G_TYPE_STRING) + { + char *str = NULL; + + if (_clutter_script_parse_translatable_string (script, node, &str)) + { + g_value_take_string (value, str); + return TRUE; + } + } + } + return FALSE; + + case JSON_NODE_ARRAY: + if (!pspec && !G_IS_VALUE (value)) + return FALSE; + else + { + if (!G_IS_VALUE (value)) + g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec)); + + if (G_VALUE_HOLDS (value, CLUTTER_TYPE_KNOT)) + { + ClutterKnot knot = { 0, }; + + /* knot := [ (int), (int) ] */ + + if (_clutter_script_parse_knot (script, node, &knot)) + { + g_value_set_boxed (value, &knot); + return TRUE; + } + } + else if (G_VALUE_HOLDS (value, CLUTTER_TYPE_GEOMETRY)) + { + ClutterGeometry geom = { 0, }; + + /* geometry := [ (int), (int), (int), (int) ] */ + + if (_clutter_script_parse_geometry (script, node, &geom)) + { + g_value_set_boxed (value, &geom); + return TRUE; + } + } + else if (CLUTTER_VALUE_HOLDS_COLOR (value)) + { + ClutterColor color = { 0, }; + + /* color := [ (int), (int), (int), (int) ] */ + + if (_clutter_script_parse_color (script, node, &color)) + { + g_value_set_boxed (value, &color); + return TRUE; + } + } + else if (G_VALUE_HOLDS (value, CLUTTER_TYPE_POINT)) + { + ClutterPoint point = CLUTTER_POINT_INIT_ZERO; + + if (_clutter_script_parse_point (script, node, &point)) + { + g_value_set_boxed (value, &point); + return TRUE; + } + } + else if (G_VALUE_HOLDS (value, CLUTTER_TYPE_SIZE)) + { + ClutterSize size = CLUTTER_SIZE_INIT_ZERO; + + if (_clutter_script_parse_size (script, node, &size)) + { + g_value_set_boxed (value, &size); + return TRUE; + } + } + else if (G_VALUE_HOLDS (value, G_TYPE_STRV)) + { + JsonArray *array = json_node_get_array (node); + guint i, array_len = json_array_get_length (array); + GPtrArray *str_array = g_ptr_array_sized_new (array_len); + + /* strv := [ (str), (str), ... ] */ + + for (i = 0; i < array_len; i++) + { + JsonNode *val = json_array_get_element (array, i); + + if (JSON_NODE_TYPE (val) != JSON_NODE_VALUE && + json_node_get_string (val) == NULL) + continue; + + g_ptr_array_add (str_array, + (gpointer) json_node_get_string (val)); + } + + g_value_set_boxed (value, str_array->pdata); + g_ptr_array_free (str_array, TRUE); + + return TRUE; + } + } + return FALSE; + + case JSON_NODE_NULL: + return FALSE; + + case JSON_NODE_VALUE: + json_node_get_value (node, &node_value); + + if (!pspec && !G_IS_VALUE (value)) + g_value_init (value, G_VALUE_TYPE (&node_value)); + else if (pspec) + g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec)); + + switch (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value))) + { + /* fundamental JSON types */ + case G_TYPE_INT64: + case G_TYPE_DOUBLE: + case G_TYPE_STRING: + case G_TYPE_BOOLEAN: + g_value_copy (&node_value, value); + retval = TRUE; + break; + + case G_TYPE_INT: + g_value_set_int (value, g_value_get_int64 (&node_value)); + retval = TRUE; + break; + + case G_TYPE_UINT: + g_value_set_uint (value, (guint) g_value_get_int64 (&node_value)); + retval = TRUE; + break; + + case G_TYPE_ULONG: + g_value_set_ulong (value, (gulong) g_value_get_int64 (&node_value)); + retval = TRUE; + break; + + case G_TYPE_UCHAR: + g_value_set_uchar (value, (guchar) g_value_get_int64 (&node_value)); + retval = TRUE; + break; + + case G_TYPE_FLOAT: + if (G_VALUE_HOLDS (&node_value, G_TYPE_DOUBLE)) + { + g_value_set_float (value, g_value_get_double (&node_value)); + retval = TRUE; + } + else if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64)) + { + g_value_set_float (value, g_value_get_int64 (&node_value)); + retval = TRUE; + } + break; + + case G_TYPE_ENUM: + if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64)) + { + g_value_set_enum (value, g_value_get_int64 (&node_value)); + retval = TRUE; + } + else if (G_VALUE_HOLDS (&node_value, G_TYPE_STRING)) + { + gint enum_value; + + retval = _clutter_script_enum_from_string (G_VALUE_TYPE (value), + g_value_get_string (&node_value), + &enum_value); + if (retval) + g_value_set_enum (value, enum_value); + } + break; + + case G_TYPE_FLAGS: + if (G_VALUE_HOLDS (&node_value, G_TYPE_INT64)) + { + g_value_set_flags (value, g_value_get_int64 (&node_value)); + retval = TRUE; + } + else if (G_VALUE_HOLDS (&node_value, G_TYPE_STRING)) + { + gint flags_value; + + retval = _clutter_script_flags_from_string (G_VALUE_TYPE (value), + g_value_get_string (&node_value), + &flags_value); + if (retval) + g_value_set_flags (value, flags_value); + } + break; + + case G_TYPE_BOXED: + if (G_VALUE_HOLDS (value, CLUTTER_TYPE_COLOR)) + { + ClutterColor color = { 0, }; + + retval = _clutter_script_parse_color (script, node, &color); + if (retval) + clutter_value_set_color (value, &color); + } + break; + + case G_TYPE_OBJECT: + if (G_VALUE_HOLDS (&node_value, G_TYPE_STRING)) + { + const gchar *str = g_value_get_string (&node_value); + GObject *object = clutter_script_get_object (script, str); + if (object) + { + CLUTTER_NOTE (SCRIPT, + "Assigning '%s' (%s) to property '%s'", + str, + G_OBJECT_TYPE_NAME (object), + name); + + g_value_set_object (value, object); + retval = TRUE; + } + } + break; + + default: + retval = FALSE; + break; + } + + if (G_VALUE_TYPE (value) == G_TYPE_GTYPE && + G_VALUE_HOLDS (&node_value, G_TYPE_STRING)) + { + const gchar *str = g_value_get_string (&node_value); + GType type = clutter_script_get_type_from_name (script, str); + g_value_set_gtype (value, type); + retval = TRUE; + } + + g_value_unset (&node_value); + break; + } + + return retval; +} + +static GList * +clutter_script_translate_parameters (ClutterScript *script, + GObject *object, + const gchar *name, + GList *properties, + GArray **params) +{ + ClutterScriptable *scriptable = NULL; + ClutterScriptableIface *iface = NULL; + GList *l, *unparsed; + gboolean parse_custom = FALSE; + + *params = g_array_new (FALSE, FALSE, sizeof (GParameter)); + + if (CLUTTER_IS_SCRIPTABLE (object)) + { + scriptable = CLUTTER_SCRIPTABLE (object); + iface = CLUTTER_SCRIPTABLE_GET_IFACE (scriptable); + + if (iface->parse_custom_node) + parse_custom = TRUE; + } + + unparsed = NULL; + + for (l = properties; l != NULL; l = l->next) + { + PropertyInfo *pinfo = l->data; + GParameter param = { NULL }; + gboolean res = FALSE; + + if (pinfo->is_child || pinfo->is_layout) + { + CLUTTER_NOTE (SCRIPT, "Skipping %s property '%s'", + pinfo->is_child ? "child" : "layout", + pinfo->name); + unparsed = g_list_prepend (unparsed, pinfo); + continue; + } + + CLUTTER_NOTE (SCRIPT, "Parsing %s property (id:%s)", + pinfo->pspec ? "regular" : "custom", + pinfo->name); + + if (parse_custom) + res = iface->parse_custom_node (scriptable, script, ¶m.value, + pinfo->name, + pinfo->node); + + if (!res) + res = _clutter_script_parse_node (script, ¶m.value, + pinfo->name, + pinfo->node, + pinfo->pspec); + + if (!res) + { + CLUTTER_NOTE (SCRIPT, "Property '%s' ignored", pinfo->name); + unparsed = g_list_prepend (unparsed, pinfo); + continue; + } + + param.name = g_strdup (pinfo->name); + + g_array_append_val (*params, param); + + property_info_free (pinfo); + } + + g_list_free (properties); + + return unparsed; +} + +static GList * +clutter_script_construct_parameters (ClutterScript *script, + GType gtype, + const gchar *name, + GList *properties, + GArray **construct_params) +{ + GObjectClass *klass; + GList *l, *unparsed; + + klass = g_type_class_ref (gtype); + g_assert (klass != NULL); + + *construct_params = g_array_new (FALSE, FALSE, sizeof (GParameter)); + + unparsed = NULL; + + for (l = properties; l != NULL; l = l->next) + { + PropertyInfo *pinfo = l->data; + GParameter param = { NULL }; + GParamSpec *pspec = NULL; + + /* we allow custom property names for classes, so if we + * don't find a corresponding GObject property for this + * class we just skip it and let the class itself deal + * with it later on + */ + pspec = g_object_class_find_property (klass, pinfo->name); + if (pspec) + pinfo->pspec = g_param_spec_ref (pspec); + else + { + pinfo->pspec = NULL; + unparsed = g_list_prepend (unparsed, pinfo); + continue; + } + + if (!(pspec->flags & G_PARAM_CONSTRUCT_ONLY)) + { + unparsed = g_list_prepend (unparsed, pinfo); + continue; + } + + param.name = g_strdup (pinfo->name); + + if (!_clutter_script_parse_node (script, ¶m.value, + pinfo->name, + pinfo->node, + pinfo->pspec)) + { + unparsed = g_list_prepend (unparsed, pinfo); + continue; + } + + g_array_append_val (*construct_params, param); + + property_info_free (pinfo); + } + + g_list_free (properties); + + g_type_class_unref (klass); + + return unparsed; +} + +static void +apply_layout_properties (ClutterScript *script, + ClutterContainer *container, + ClutterActor *actor, + ObjectInfo *oinfo) +{ + ClutterScriptable *scriptable = NULL; + ClutterScriptableIface *iface = NULL; + gboolean parse_custom_node = FALSE; + GList *l, *unresolved, *properties; + ClutterLayoutManager *manager; + GType meta_type; + + manager = g_object_get_data (G_OBJECT (container), "clutter-layout-manager"); + if (manager == NULL) + return; + + meta_type = _clutter_layout_manager_get_child_meta_type (manager); + if (meta_type == G_TYPE_INVALID) + return; + + CLUTTER_NOTE (SCRIPT, "Layout manager of type '%s' with meta type '%s'", + G_OBJECT_TYPE_NAME (manager), + g_type_name (meta_type)); + + /* shortcut, to avoid typechecking every time */ + if (CLUTTER_IS_SCRIPTABLE (manager)) + { + scriptable = CLUTTER_SCRIPTABLE (manager); + iface = CLUTTER_SCRIPTABLE_GET_IFACE (scriptable); + + parse_custom_node = iface->parse_custom_node != NULL ? TRUE : FALSE; + } + + properties = oinfo->properties; + oinfo->properties = NULL; + + unresolved = NULL; + for (l = properties; l != NULL; l = l->next) + { + PropertyInfo *pinfo = l->data; + GValue value = G_VALUE_INIT; + gboolean res = FALSE; + const gchar *name; + + if (!pinfo->is_layout) + { + unresolved = g_list_prepend (unresolved, pinfo); + continue; + } + + name = pinfo->name + strlen ("layout::"); + + pinfo->pspec = + clutter_layout_manager_find_child_property (manager, name); + + if (pinfo->pspec != NULL) + g_param_spec_ref (pinfo->pspec); + + CLUTTER_NOTE (SCRIPT, "Parsing %s layout property (id:%s)", + pinfo->pspec != NULL ? "regular" : "custom", + name); + + if (parse_custom_node) + res = iface->parse_custom_node (scriptable, script, &value, + name, + pinfo->node); + + if (!res) + res = _clutter_script_parse_node (script, &value, + name, + pinfo->node, + pinfo->pspec); + + if (!res) + { + CLUTTER_NOTE (SCRIPT, "Layout property '%s' ignored", name); + unresolved = g_list_prepend (unresolved, pinfo); + continue; + } + + CLUTTER_NOTE (SCRIPT, + "Setting %s layout property '%s' (type:%s) to " + "object '%s' (id:%s)", + iface->set_custom_property != NULL ? "custom" : "regular", + name, + g_type_name (G_VALUE_TYPE (&value)), + g_type_name (oinfo->gtype), + oinfo->id); + + clutter_layout_manager_child_set_property (manager, container, actor, + name, + &value); + + g_value_unset (&value); + + property_info_free (pinfo); + } + + g_list_free (properties); + + oinfo->properties = unresolved; +} + +static void +apply_child_properties (ClutterScript *script, + ClutterContainer *container, + ClutterActor *actor, + ObjectInfo *oinfo) +{ + ClutterScriptable *scriptable = NULL; + ClutterScriptableIface *iface = NULL; + gboolean parse_custom_node = FALSE; + GList *l, *unresolved, *properties; + GObjectClass *klass; + GType meta_type; + + meta_type = CLUTTER_CONTAINER_GET_IFACE (container)->child_meta_type; + if (meta_type == G_TYPE_INVALID) + return; + + klass = G_OBJECT_GET_CLASS (container); + + /* shortcut, to avoid typechecking every time */ + if (CLUTTER_IS_SCRIPTABLE (container)) + { + scriptable = CLUTTER_SCRIPTABLE (container); + iface = CLUTTER_SCRIPTABLE_GET_IFACE (scriptable); + + parse_custom_node = iface->parse_custom_node != NULL ? TRUE : FALSE; + } + + properties = oinfo->properties; + oinfo->properties = NULL; + + unresolved = NULL; + for (l = properties; l != NULL; l = l->next) + { + PropertyInfo *pinfo = l->data; + GValue value = G_VALUE_INIT; + gboolean res = FALSE; + const gchar *name; + + if (!pinfo->is_child) + { + unresolved = g_list_prepend (unresolved, pinfo); + continue; + } + + name = pinfo->name + strlen ("child::"); + + pinfo->pspec = + clutter_container_class_find_child_property (klass, name); + + if (pinfo->pspec != NULL) + g_param_spec_ref (pinfo->pspec); + + CLUTTER_NOTE (SCRIPT, "Parsing %s child property (id:%s)", + pinfo->pspec != NULL ? "regular" : "custom", + name); + + if (parse_custom_node) + res = iface->parse_custom_node (scriptable, script, &value, + name, + pinfo->node); + + if (!res) + res = _clutter_script_parse_node (script, &value, + name, + pinfo->node, + pinfo->pspec); + + if (!res) + { + CLUTTER_NOTE (SCRIPT, "Child property '%s' ignored", name); + unresolved = g_list_prepend (unresolved, pinfo); + continue; + } + + + CLUTTER_NOTE (SCRIPT, + "Setting %s child property '%s' (type:%s) to " + "object '%s' (id:%s)", + iface->set_custom_property != NULL ? "custom" : "regular", + name, + g_type_name (G_VALUE_TYPE (&value)), + g_type_name (oinfo->gtype), + oinfo->id); + + clutter_container_child_set_property (container, actor, + name, + &value); + + g_value_unset (&value); + + property_info_free (pinfo); + } + + g_list_free (properties); + + oinfo->properties = unresolved; +} + +static void +add_children (ClutterScript *script, + ObjectInfo *oinfo) +{ + ClutterContainer *container = CLUTTER_CONTAINER (oinfo->object); + GList *l, *unresolved; + + unresolved = NULL; + for (l = oinfo->children; l != NULL; l = l->next) + { + const gchar *name = l->data; + GObject *object = NULL; + ObjectInfo *child_info; + + child_info = _clutter_script_get_object_info (script, name); + if (child_info != NULL) + { + _clutter_script_construct_object (script, child_info); + object = child_info->object; + } + + if (object == NULL) + { + unresolved = g_list_prepend (unresolved, g_strdup (name)); + continue; + } + + if (!CLUTTER_IS_ACTOR (object)) + { + g_warning ("The object definition '%s' (type: %s) is not " + "an actor, but it is referenced in the 'children' " + "member of the container '%s' (type: %s); skipping.", + child_info->id, + g_type_name (child_info->gtype), + oinfo->id, + g_type_name (oinfo->gtype)); + continue; + } + + CLUTTER_NOTE (SCRIPT, "Adding children '%s' to actor of type '%s'", + name, + g_type_name (G_OBJECT_TYPE (container))); + + clutter_container_add_actor (container, CLUTTER_ACTOR (object)); + } + + g_list_foreach (oinfo->children, (GFunc) g_free, NULL); + g_list_free (oinfo->children); + + oinfo->children = unresolved; +} + +static inline void +_clutter_script_check_unresolved (ClutterScript *script, + ObjectInfo *oinfo) +{ + if (oinfo->children != NULL && CLUTTER_IS_CONTAINER (oinfo->object)) + add_children (script, oinfo); + + /* this is a bit *eugh*, but it allows us to effectively make sure + * that child and layout properties are parsed and applied to the + * right child + */ + if (oinfo->properties != NULL && CLUTTER_IS_ACTOR (oinfo->object)) + { + ClutterActor *parent; + + parent = clutter_actor_get_parent (CLUTTER_ACTOR (oinfo->object)); + if (parent != NULL) + { + ClutterContainer *container = CLUTTER_CONTAINER (parent); + ClutterActor *child; + + for (child = clutter_actor_get_first_child (parent); + child != NULL; + child = clutter_actor_get_next_sibling (child)) + { + ObjectInfo *child_info; + const gchar *id_; + + id_ = clutter_get_script_id (G_OBJECT (child)); + if (id_ == NULL || *id_ == '\0') + continue; + + child_info = _clutter_script_get_object_info (script, id_); + if (child_info == NULL) + continue; + + apply_child_properties (script, container, + child, + child_info); + apply_layout_properties (script, container, + child, + child_info); + } + } + } + + if (oinfo->properties || oinfo->children) + oinfo->has_unresolved = TRUE; + else + oinfo->has_unresolved = FALSE; +} + +void +_clutter_script_apply_properties (ClutterScript *script, + ObjectInfo *oinfo) +{ + ClutterScriptable *scriptable = NULL; + ClutterScriptableIface *iface = NULL; + gboolean set_custom_property = FALSE; + GObject *object = oinfo->object; + GList *properties; + GArray *params; + guint i; + + if (!oinfo->has_unresolved) + return; + + /* shortcut, to avoid typechecking every time */ + if (CLUTTER_IS_SCRIPTABLE (object)) + { + scriptable = CLUTTER_SCRIPTABLE (object); + iface = CLUTTER_SCRIPTABLE_GET_IFACE (scriptable); + + if (iface->set_custom_property) + set_custom_property = TRUE; + } + + /* then we get the rest of the parameters, asking the object itself + * to translate them for us, if we cannot do that + */ + properties = oinfo->properties; + oinfo->properties = clutter_script_translate_parameters (script, + object, + oinfo->id, + properties, + ¶ms); + + /* consume all the properties we could translate in this pass */ + for (i = 0; i < params->len; i++) + { + GParameter *param = &g_array_index (params, GParameter, i); + + CLUTTER_NOTE (SCRIPT, + "Setting %s property '%s' (type:%s) to object '%s' (id:%s)", + set_custom_property ? "custom" : "regular", + param->name, + g_type_name (G_VALUE_TYPE (¶m->value)), + g_type_name (oinfo->gtype), + oinfo->id); + + if (set_custom_property) + iface->set_custom_property (scriptable, script, + param->name, + ¶m->value); + else + g_object_set_property (object, param->name, ¶m->value); + + g_free ((gchar *) param->name); + g_value_unset (¶m->value); + } + + g_array_free (params, TRUE); + + _clutter_script_check_unresolved (script, oinfo); +} + +void +_clutter_script_construct_object (ClutterScript *script, + ObjectInfo *oinfo) +{ + GArray *params = NULL; + guint i; + + /* we have completely updated the object */ + if (oinfo->object != NULL) + { + if (oinfo->has_unresolved) + _clutter_script_check_unresolved (script, oinfo); + + return; + } + + if (oinfo->gtype == G_TYPE_INVALID) + { + if (G_UNLIKELY (oinfo->type_func)) + oinfo->gtype = _clutter_script_get_type_from_symbol (oinfo->type_func); + else + oinfo->gtype = clutter_script_get_type_from_name (script, oinfo->class_name); + + if (G_UNLIKELY (oinfo->gtype == G_TYPE_INVALID)) + return; + } + + oinfo->is_actor = g_type_is_a (oinfo->gtype, CLUTTER_TYPE_ACTOR); + if (oinfo->is_actor) + oinfo->is_stage = g_type_is_a (oinfo->gtype, CLUTTER_TYPE_STAGE); + + if (oinfo->is_stage && oinfo->is_stage_default) + { + ClutterStageManager *manager = clutter_stage_manager_get_default (); + GList *properties = oinfo->properties; + ClutterStage *default_stage; + + /* the default stage is a complex beast: we cannot create it using + * g_object_newv() but we need clutter_script_construct_parameters() + * to add the GParamSpec to the PropertyInfo pspec member, so + * that we don't have to implement every complex property (like + * the "color" one) directly inside the ClutterStage class. + */ + oinfo->properties = + clutter_script_construct_parameters (script, + oinfo->gtype, + oinfo->id, + properties, + ¶ms); + + default_stage = clutter_stage_manager_get_default_stage (manager); + oinfo->object = G_OBJECT (default_stage); + + for (i = 0; i < params->len; i++) + { + GParameter *param = &g_array_index (params, GParameter, i); + + g_free ((gchar *) param->name); + g_value_unset (¶m->value); + } + + g_array_free (params, TRUE); + } + else + { + GList *properties = oinfo->properties; + GParameter *parameters; + + /* every other object: first, we get the construction parameters */ + oinfo->properties = + clutter_script_construct_parameters (script, + oinfo->gtype, + oinfo->id, + properties, + ¶ms); + + parameters = (GParameter *) (void *) params->data; + oinfo->object = g_object_newv (oinfo->gtype, + params->len, + parameters); + + /* by sinking the floating reference, we make sure that the reference + * count is correct whether the object is referenced from somewhere + * else too or only by this ClutterScript object. + */ + g_object_ref_sink (oinfo->object); + + for (i = 0; i < params->len; i++) + { + GParameter *param = &g_array_index (params, GParameter, i); + + g_free ((gchar *) param->name); + g_value_unset (¶m->value); + } + + g_array_free (params, TRUE); + } + + g_assert (oinfo->object != NULL); + + if (CLUTTER_IS_SCRIPTABLE (oinfo->object)) + clutter_scriptable_set_id (CLUTTER_SCRIPTABLE (oinfo->object), oinfo->id); + else + g_object_set_data_full (oinfo->object, "clutter-script-id", + g_strdup (oinfo->id), + g_free); + + _clutter_script_check_unresolved (script, oinfo); +} diff --git a/clutter/clutter/clutter-script-private.h b/clutter/clutter/clutter-script-private.h new file mode 100644 index 0000000..52a67bc --- /dev/null +++ b/clutter/clutter/clutter-script-private.h @@ -0,0 +1,172 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +#ifndef __CLUTTER_SCRIPT_PRIVATE_H__ +#define __CLUTTER_SCRIPT_PRIVATE_H__ + +#include +#include + +#include "clutter-color.h" +#include "clutter-types.h" +#include "clutter-script.h" + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_SCRIPT_PARSER (_clutter_script_parser_get_type ()) +#define CLUTTER_SCRIPT_PARSER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_SCRIPT_PARSER, ClutterScriptParser)) +#define CLUTTER_IS_SCRIPT_PARSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_SCRIPT_PARSER)) + +typedef struct _ClutterScriptParser ClutterScriptParser; +typedef struct _JsonParserClass ClutterScriptParserClass; + +struct _ClutterScriptParser +{ + JsonParser parent_instance; + + /* back reference */ + ClutterScript *script; +}; + +typedef GType (* GTypeGetFunc) (void); + +typedef struct { + gchar *id; + gchar *class_name; + gchar *type_func; + + GList *properties; + GList *children; + GList *signals; + + GType gtype; + GObject *object; + + guint merge_id; + + guint is_actor : 1; + guint is_stage : 1; + guint is_stage_default : 1; + guint has_unresolved : 1; + guint is_unmerged : 1; +} ObjectInfo; + +void object_info_free (gpointer data); + +typedef struct { + gchar *name; + JsonNode *node; + GParamSpec *pspec; + + guint is_child : 1; + guint is_layout : 1; +} PropertyInfo; + +typedef struct { + gchar *name; + gchar *handler; + gchar *object; + gchar *state; + gchar *target; + + GConnectFlags flags; + + guint is_handler : 1; + guint warp_to : 1; +} SignalInfo; + +void property_info_free (gpointer data); + +GType _clutter_script_parser_get_type (void) G_GNUC_CONST; + +gboolean _clutter_script_parse_node (ClutterScript *script, + GValue *value, + const gchar *name, + JsonNode *node, + GParamSpec *pspec); + +GType _clutter_script_get_type_from_symbol (const gchar *symbol); +GType _clutter_script_get_type_from_class (const gchar *name); + +gulong _clutter_script_resolve_animation_mode (JsonNode *node); + +gboolean _clutter_script_enum_from_string (GType gtype, + const gchar *string, + gint *enum_value); +gboolean _clutter_script_flags_from_string (GType gtype, + const gchar *string, + gint *flags_value); + +gboolean _clutter_script_parse_knot (ClutterScript *script, + JsonNode *node, + ClutterKnot *knot); +gboolean _clutter_script_parse_geometry (ClutterScript *script, + JsonNode *node, + ClutterGeometry *geometry); +gboolean _clutter_script_parse_color (ClutterScript *script, + JsonNode *node, + ClutterColor *color); +GObject *_clutter_script_parse_alpha (ClutterScript *script, + JsonNode *node); +gboolean _clutter_script_parse_point (ClutterScript *script, + JsonNode *node, + ClutterPoint *point); +gboolean _clutter_script_parse_size (ClutterScript *script, + JsonNode *node, + ClutterSize *size); + +gboolean _clutter_script_parse_translatable_string (ClutterScript *script, + JsonNode *node, + char **str); + +void _clutter_script_construct_object (ClutterScript *script, + ObjectInfo *oinfo); +void _clutter_script_apply_properties (ClutterScript *script, + ObjectInfo *oinfo); + +gchar *_clutter_script_generate_fake_id (ClutterScript *script); + +void _clutter_script_warn_missing_attribute (ClutterScript *script, + const gchar *id, + const gchar *attribute); + +void _clutter_script_warn_invalid_value (ClutterScript *script, + const gchar *attribute, + const gchar *expected, + JsonNode *node); + +ObjectInfo *_clutter_script_get_object_info (ClutterScript *script, + const gchar *script_id); + +guint _clutter_script_get_last_merge_id (ClutterScript *script); + +void _clutter_script_add_object_info (ClutterScript *script, + ObjectInfo *oinfo); + +const gchar *_clutter_script_get_id_from_node (JsonNode *node); + +G_END_DECLS + +#endif /* __CLUTTER_SCRIPT_PRIVATE_H__ */ diff --git a/clutter/clutter/clutter-script.c b/clutter/clutter/clutter-script.c new file mode 100644 index 0000000..9ca5fbb --- /dev/null +++ b/clutter/clutter/clutter-script.c @@ -0,0 +1,1689 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +/** + * SECTION:clutter-script + * @short_description: Loads a scene from UI definition data + * + * #ClutterScript is an object used for loading and building parts or a + * complete scenegraph from external definition data in forms of string + * buffers or files. + * + * The UI definition format is JSON, the JavaScript Object Notation as + * described by RFC 4627. #ClutterScript can load a JSON data stream, + * parse it and build all the objects defined into it. Each object must + * have an "id" and a "type" properties defining the name to be used + * to retrieve it from #ClutterScript with clutter_script_get_object(), + * and the class type to be instanciated. Every other attribute will + * be mapped to the class properties. + * + * A #ClutterScript holds a reference on every object it creates from + * the definition data, except for the stage. Every non-actor object + * will be finalized when the #ClutterScript instance holding it will + * be finalized, so they need to be referenced using g_object_ref() in + * order for them to survive. + * + * A simple object might be defined as: + * + * + * + * This will produce a red #ClutterRectangle, 100x100 pixels wide, and + * with a ClutterScript id of "red-button"; it can be retrieved by calling: + * + * |[ + * ClutterActor *red_button; + * + * red_button = CLUTTER_ACTOR (clutter_script_get_object (script, "red-button")); + * ]| + * + * and then manipulated with the Clutter API. For every object created + * using ClutterScript it is possible to check the id by calling + * clutter_get_script_id(). + * + * Packing can be represented using the "children" member, and passing an + * array of objects or ids of objects already defined (but not packed: the + * packing rules of Clutter still apply, and an actor cannot be packed + * in multiple containers without unparenting it in between). + * + * Behaviours and timelines can also be defined inside a UI definition + * buffer: + * + * + * + * And then to apply a defined behaviour to an actor defined inside the + * definition of an actor, the "behaviour" member can be used: + * + * + * + * A #ClutterAlpha belonging to a #ClutterBehaviour can only be defined + * implicitly like in the example above, or explicitly by setting the + * "alpha" property to point to a previously defined #ClutterAlpha, e.g.: + * + * + * + * Implicitely defined #ClutterAlphas and #ClutterTimelines + * can omit the `id`, as well as the `type` members, but will not be available + * using clutter_script_get_object() (they can, however, be extracted using the + * #ClutterBehaviour and #ClutterAlpha API respectively). + * + * Signal handlers can be defined inside a Clutter UI definition file and + * then autoconnected to their respective signals using the + * clutter_script_connect_signals() function: + * + * + * + * Signal handler definitions must have a "name" and a "handler" members; + * they can also have the "after" and "swapped" boolean members (for the + * signal connection flags %G_CONNECT_AFTER and %G_CONNECT_SWAPPED + * respectively) and the "object" string member for calling + * g_signal_connect_object() instead of g_signal_connect(). + * + * Signals can also be directly attached to a specific state defined + * inside a #ClutterState instance, for instance: + * + * |[ + * ... + * "signals" : [ + * { + * "name" : "enter-event", + * "states" : "button-states", + * "target-state" : "hover" + * }, + * { + * "name" : "leave-event", + * "states" : "button-states", + * "target-state" : "base" + * }, + * { + * "name" : "button-press-event", + * "states" : "button-states", + * "target-state" : "active", + * }, + * { + * "name" : "key-press-event", + * "states" : "button-states", + * "target-state" : "key-focus", + * "warp" : true + * } + * ], + * ... + * ]| + * + * The "states" key defines the #ClutterState instance to be used to + * resolve the "target-state" key; it can be either a script id for a + * #ClutterState built by the same #ClutterScript instance, or to a + * #ClutterState built in code and associated to the #ClutterScript + * instance through the clutter_script_add_states() function. If no + * "states" key is present, then the default #ClutterState associated to + * the #ClutterScript instance will be used; the default #ClutterState + * can be set using clutter_script_add_states() using a %NULL name. The + * "warp" key can be used to warp to a specific state instead of + * animating to it. State changes on signal emission will not affect + * the signal emission chain. + * + * Clutter reserves the following names, so classes defining properties + * through the usual GObject registration process should avoid using these + * names to avoid collisions: + * + * + * + * #ClutterScript is available since Clutter 0.6 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include +#include +#include +#include + +#include +#include +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS + +#include "clutter-actor.h" +#include "clutter-stage.h" +#include "clutter-texture.h" + +#include "clutter-script.h" +#include "clutter-script-private.h" +#include "clutter-scriptable.h" + +#include "clutter-enum-types.h" +#include "clutter-private.h" +#include "clutter-debug.h" + +#include "deprecated/clutter-alpha.h" +#include "deprecated/clutter-behaviour.h" +#include "deprecated/clutter-container.h" +#include "deprecated/clutter-state.h" + +enum +{ + PROP_0, + + PROP_FILENAME_SET, + PROP_FILENAME, + PROP_TRANSLATION_DOMAIN, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +#define CLUTTER_SCRIPT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CLUTTER_TYPE_SCRIPT, ClutterScriptPrivate)) + +struct _ClutterScriptPrivate +{ + GHashTable *objects; + + guint last_merge_id; + guint last_unknown; + + ClutterScriptParser *parser; + + GHashTable *states; + + gchar **search_paths; + + gchar *translation_domain; + + gchar *filename; + guint is_filename : 1; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterScript, clutter_script, G_TYPE_OBJECT) + +static GType +clutter_script_real_get_type_from_name (ClutterScript *script, + const gchar *type_name) +{ + GType gtype; + + gtype = g_type_from_name (type_name); + if (gtype != G_TYPE_INVALID) + return gtype; + + return _clutter_script_get_type_from_class (type_name); +} + +void +property_info_free (gpointer data) +{ + if (G_LIKELY (data)) + { + PropertyInfo *pinfo = data; + + if (pinfo->node) + json_node_free (pinfo->node); + + if (pinfo->pspec) + g_param_spec_unref (pinfo->pspec); + + g_free (pinfo->name); + + g_slice_free (PropertyInfo, pinfo); + } +} + +static void +signal_info_free (gpointer data) +{ + if (G_LIKELY (data)) + { + SignalInfo *sinfo = data; + + g_free (sinfo->name); + g_free (sinfo->handler); + g_free (sinfo->object); + g_free (sinfo->state); + g_free (sinfo->target); + + g_slice_free (SignalInfo, sinfo); + } +} + +void +object_info_free (gpointer data) +{ + if (G_LIKELY (data)) + { + ObjectInfo *oinfo = data; + + g_free (oinfo->id); + g_free (oinfo->class_name); + g_free (oinfo->type_func); + + g_list_foreach (oinfo->properties, (GFunc) property_info_free, NULL); + g_list_free (oinfo->properties); + + g_list_foreach (oinfo->signals, (GFunc) signal_info_free, NULL); + g_list_free (oinfo->signals); + + /* these are ids */ + g_list_foreach (oinfo->children, (GFunc) g_free, NULL); + g_list_free (oinfo->children); + + /* we unref top-level objects and leave the actors alone, + * unless we are unmerging in which case we have to destroy + * the actor to unparent them + */ + if (oinfo->object != NULL) + { + if (oinfo->is_unmerged) + { + if (oinfo->is_actor && !oinfo->is_stage) + clutter_actor_destroy (CLUTTER_ACTOR (oinfo->object)); + } + + g_object_unref (oinfo->object); + + oinfo->object = NULL; + } + + g_slice_free (ObjectInfo, oinfo); + } +} + +static void +clutter_script_finalize (GObject *gobject) +{ + ClutterScriptPrivate *priv = CLUTTER_SCRIPT_GET_PRIVATE (gobject); + + g_object_unref (priv->parser); + g_hash_table_destroy (priv->objects); + g_strfreev (priv->search_paths); + g_free (priv->filename); + g_hash_table_destroy (priv->states); + g_free (priv->translation_domain); + + G_OBJECT_CLASS (clutter_script_parent_class)->finalize (gobject); +} + +static void +clutter_script_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterScript *script = CLUTTER_SCRIPT (gobject); + + switch (prop_id) + { + case PROP_TRANSLATION_DOMAIN: + clutter_script_set_translation_domain (script, g_value_get_string (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_script_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterScript *script = CLUTTER_SCRIPT (gobject); + + switch (prop_id) + { + case PROP_FILENAME_SET: + g_value_set_boolean (value, script->priv->is_filename); + break; + + case PROP_FILENAME: + g_value_set_string (value, script->priv->filename); + break; + + case PROP_TRANSLATION_DOMAIN: + g_value_set_string (value, script->priv->translation_domain); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_script_class_init (ClutterScriptClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + klass->get_type_from_name = clutter_script_real_get_type_from_name; + + /** + * ClutterScript:filename-set: + * + * Whether the #ClutterScript:filename property is set. If this property + * is %TRUE then the currently parsed data comes from a file, and the + * file name is stored inside the #ClutterScript:filename property. + * + * Since: 0.6 + */ + obj_props[PROP_FILENAME_SET] = + g_param_spec_boolean ("filename-set", + P_("Filename Set"), + P_("Whether the :filename property is set"), + FALSE, + CLUTTER_PARAM_READABLE); + + /** + * ClutterScript:filename: + * + * The path of the currently parsed file. If #ClutterScript:filename-set + * is %FALSE then the value of this property is undefined. + * + * Since: 0.6 + */ + obj_props[PROP_FILENAME] = + g_param_spec_string ("filename", + P_("Filename"), + P_("The path of the currently parsed file"), + NULL, + CLUTTER_PARAM_READABLE); + + /** + * ClutterScript:translation-domain: + * + * The translation domain, used to localize strings marked as translatable + * inside a UI definition. + * + * If #ClutterScript:translation-domain is set to %NULL, #ClutterScript + * will use gettext(), otherwise g_dgettext() will be used. + * + * Since: 1.10 + */ + obj_props[PROP_TRANSLATION_DOMAIN] = + g_param_spec_string ("translation-domain", + P_("Translation Domain"), + P_("The translation domain used to localize string"), + NULL, + CLUTTER_PARAM_READWRITE); + + gobject_class->set_property = clutter_script_set_property; + gobject_class->get_property = clutter_script_get_property; + gobject_class->finalize = clutter_script_finalize; + + g_object_class_install_properties (gobject_class, + PROP_LAST, + obj_props); +} + +static void +clutter_script_init (ClutterScript *script) +{ + ClutterScriptPrivate *priv; + + script->priv = priv = clutter_script_get_instance_private (script); + + priv->parser = g_object_new (CLUTTER_TYPE_SCRIPT_PARSER, NULL); + priv->parser->script = script; + + priv->is_filename = FALSE; + priv->last_merge_id = 0; + + priv->objects = g_hash_table_new_full (g_str_hash, g_str_equal, + NULL, + object_info_free); + priv->states = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, + (GDestroyNotify) g_object_unref); +} + +/** + * clutter_script_new: + * + * Creates a new #ClutterScript instance. #ClutterScript can be used + * to load objects definitions for scenegraph elements, like actors, + * or behavioural elements, like behaviours and timelines. The + * definitions must be encoded using the JavaScript Object Notation (JSON) + * language. + * + * Return value: the newly created #ClutterScript instance. Use + * g_object_unref() when done. + * + * Since: 0.6 + */ +ClutterScript * +clutter_script_new (void) +{ + return g_object_new (CLUTTER_TYPE_SCRIPT, NULL); +} + +/** + * clutter_script_load_from_file: + * @script: a #ClutterScript + * @filename: the full path to the definition file + * @error: return location for a #GError, or %NULL + * + * Loads the definitions from @filename into @script and merges with + * the currently loaded ones, if any. + * + * Return value: on error, zero is returned and @error is set + * accordingly. On success, the merge id for the UI definitions is + * returned. You can use the merge id with clutter_script_unmerge_objects(). + * + * Since: 0.6 + */ +guint +clutter_script_load_from_file (ClutterScript *script, + const gchar *filename, + GError **error) +{ + ClutterScriptPrivate *priv; + GError *internal_error; + + g_return_val_if_fail (CLUTTER_IS_SCRIPT (script), 0); + g_return_val_if_fail (filename != NULL, 0); + + priv = script->priv; + + g_free (priv->filename); + priv->filename = g_strdup (filename); + priv->is_filename = TRUE; + priv->last_merge_id += 1; + + internal_error = NULL; + json_parser_load_from_file (JSON_PARSER (priv->parser), + filename, + &internal_error); + if (internal_error) + { + g_propagate_error (error, internal_error); + priv->last_merge_id -= 1; + return 0; + } + + return priv->last_merge_id; +} + +/** + * clutter_script_load_from_data: + * @script: a #ClutterScript + * @data: a buffer containing the definitions + * @length: the length of the buffer, or -1 if @data is a NUL-terminated + * buffer + * @error: return location for a #GError, or %NULL + * + * Loads the definitions from @data into @script and merges with + * the currently loaded ones, if any. + * + * Return value: on error, zero is returned and @error is set + * accordingly. On success, the merge id for the UI definitions is + * returned. You can use the merge id with clutter_script_unmerge_objects(). + * + * Since: 0.6 + */ +guint +clutter_script_load_from_data (ClutterScript *script, + const gchar *data, + gssize length, + GError **error) +{ + ClutterScriptPrivate *priv; + GError *internal_error; + + g_return_val_if_fail (CLUTTER_IS_SCRIPT (script), 0); + g_return_val_if_fail (data != NULL, 0); + + if (length < 0) + length = strlen (data); + + priv = script->priv; + + g_free (priv->filename); + priv->filename = NULL; + priv->is_filename = FALSE; + priv->last_merge_id += 1; + + internal_error = NULL; + json_parser_load_from_data (JSON_PARSER (priv->parser), + data, length, + &internal_error); + if (internal_error) + { + g_propagate_error (error, internal_error); + priv->last_merge_id -= 1; + return 0; + } + + return priv->last_merge_id; +} + +/** + * clutter_script_load_from_resource: + * @script: a #ClutterScript + * @resource_path: the resource path of the file to parse + * @error: return location for a #GError, or %NULL + * + * Loads the definitions from a resource file into @script and merges with + * the currently loaded ones, if any. + * + * Return value: on error, zero is returned and @error is set + * accordingly. On success, the merge id for the UI definitions is + * returned. You can use the merge id with clutter_script_unmerge_objects(). + * + * Since: 1.10 + */ +guint +clutter_script_load_from_resource (ClutterScript *script, + const gchar *resource_path, + GError **error) +{ + GBytes *data; + guint res; + + g_return_val_if_fail (CLUTTER_IS_SCRIPT (script), 0); + + data = g_resources_lookup_data (resource_path, 0, error); + if (data == NULL) + return 0; + + res = clutter_script_load_from_data (script, + g_bytes_get_data (data, NULL), + g_bytes_get_size (data), + error); + + g_bytes_unref (data); + + return res; +} + +/** + * clutter_script_get_object: + * @script: a #ClutterScript + * @name: the name of the object to retrieve + * + * Retrieves the object bound to @name. This function does not increment + * the reference count of the returned object. + * + * Return value: (transfer none): the named object, or %NULL if no object + * with the given name was available + * + * Since: 0.6 + */ +GObject * +clutter_script_get_object (ClutterScript *script, + const gchar *name) +{ + ObjectInfo *oinfo; + + g_return_val_if_fail (CLUTTER_IS_SCRIPT (script), NULL); + g_return_val_if_fail (name != NULL, NULL); + + oinfo = g_hash_table_lookup (script->priv->objects, name); + if (!oinfo) + return NULL; + + _clutter_script_construct_object (script, oinfo); + _clutter_script_apply_properties (script, oinfo); + + return oinfo->object; +} + +static gint +clutter_script_get_objects_valist (ClutterScript *script, + const gchar *first_name, + va_list args) +{ + gint retval = 0; + const gchar *name; + + name = first_name; + while (name) + { + GObject **obj = NULL; + + obj = va_arg (args, GObject**); + + *obj = clutter_script_get_object (script, name); + if (*obj) + retval += 1; + + name = va_arg (args, gchar*); + } + + return retval; +} + +/** + * clutter_script_get_objects: + * @script: a #ClutterScript + * @first_name: the name of the first object to retrieve + * @...: return location for a #GObject, then additional names, ending + * with %NULL + * + * Retrieves a list of objects for the given names. After @script, object + * names/return location pairs should be listed, with a %NULL pointer + * ending the list, like: + * + * |[ + * GObject *my_label, *a_button, *main_timeline; + * + * clutter_script_get_objects (script, + * "my-label", &my_label, + * "a-button", &a_button, + * "main-timeline", &main_timeline, + * NULL); + * ]| + * + * Note: This function does not increment the reference count of the + * returned objects. + * + * Return value: the number of objects returned. + * + * Since: 0.6 + */ +gint +clutter_script_get_objects (ClutterScript *script, + const gchar *first_name, + ...) +{ + gint retval; + va_list var_args; + + g_return_val_if_fail (CLUTTER_IS_SCRIPT (script), 0); + g_return_val_if_fail (first_name != NULL, 0); + + va_start (var_args, first_name); + retval = clutter_script_get_objects_valist (script, first_name, var_args); + va_end (var_args); + + return retval; +} + +typedef struct { + ClutterScript *script; + guint merge_id; + GSList *ids; +} UnmergeData; + +static void +remove_by_merge_id (gpointer key, + gpointer value, + gpointer data) +{ + gchar *name = key; + ObjectInfo *oinfo = value; + UnmergeData *unmerge_data = data; + + if (oinfo->merge_id == unmerge_data->merge_id) + { + CLUTTER_NOTE (SCRIPT, + "Unmerging object (id:%s, type:%s, merge-id:%d)", + oinfo->id, + oinfo->class_name, + oinfo->merge_id); + + unmerge_data->ids = g_slist_prepend (unmerge_data->ids, g_strdup (name)); + oinfo->is_unmerged = TRUE; + } +} + +/** + * clutter_script_unmerge_objects: + * @script: a #ClutterScript + * @merge_id: merge id returned when loading a UI definition + * + * Unmerges the objects identified by @merge_id. + * + * Since: 0.6 + */ +void +clutter_script_unmerge_objects (ClutterScript *script, + guint merge_id) +{ + ClutterScriptPrivate *priv; + UnmergeData data; + GSList *l; + + g_return_if_fail (CLUTTER_IS_SCRIPT (script)); + g_return_if_fail (merge_id > 0); + + priv = script->priv; + + data.script = script; + data.merge_id = merge_id; + data.ids = NULL; + g_hash_table_foreach (priv->objects, remove_by_merge_id, &data); + + for (l = data.ids; l != NULL; l = l->next) + g_hash_table_remove (priv->objects, l->data); + + g_slist_foreach (data.ids, (GFunc) g_free, NULL); + g_slist_free (data.ids); + + clutter_script_ensure_objects (script); +} + +static void +construct_each_objects (gpointer key, + gpointer value, + gpointer user_data) +{ + ClutterScript *script = user_data; + ObjectInfo *oinfo = value; + + /* we have unfinished business */ + if (oinfo->has_unresolved) + { + /* this should not happen, but resilence is + * a good thing in a parser + */ + if (oinfo->object == NULL) + _clutter_script_construct_object (script, oinfo); + + /* this will take care of setting up properties, + * adding children and applying behaviours + */ + _clutter_script_apply_properties (script, oinfo); + } +} + +/** + * clutter_script_ensure_objects: + * @script: a #ClutterScript + * + * Ensure that every object defined inside @script is correctly + * constructed. You should rarely need to use this function. + * + * Since: 0.6 + */ +void +clutter_script_ensure_objects (ClutterScript *script) +{ + ClutterScriptPrivate *priv; + + g_return_if_fail (CLUTTER_IS_SCRIPT (script)); + + priv = script->priv; + g_hash_table_foreach (priv->objects, construct_each_objects, script); +} + +/** + * clutter_script_get_type_from_name: + * @script: a #ClutterScript + * @type_name: name of the type to look up + * + * Looks up a type by name, using the virtual function that + * #ClutterScript has for that purpose. This function should + * rarely be used. + * + * Return value: the type for the requested type name, or + * %G_TYPE_INVALID if not corresponding type was found. + * + * Since: 0.6 + */ +GType +clutter_script_get_type_from_name (ClutterScript *script, + const gchar *type_name) +{ + g_return_val_if_fail (CLUTTER_IS_SCRIPT (script), G_TYPE_INVALID); + g_return_val_if_fail (type_name != NULL, G_TYPE_INVALID); + + return CLUTTER_SCRIPT_GET_CLASS (script)->get_type_from_name (script, type_name); +} + +/** + * clutter_get_script_id: + * @gobject: a #GObject + * + * Retrieves the Clutter script id, if any. + * + * Return value: the script id, or %NULL if @object was not defined inside + * a UI definition file. The returned string is owned by the object and + * should never be modified or freed. + * + * Since: 0.6 + */ +const gchar * +clutter_get_script_id (GObject *gobject) +{ + g_return_val_if_fail (G_IS_OBJECT (gobject), NULL); + + if (CLUTTER_IS_SCRIPTABLE (gobject)) + return clutter_scriptable_get_id (CLUTTER_SCRIPTABLE (gobject)); + else + return g_object_get_data (gobject, "clutter-script-id"); +} + +typedef struct { + GModule *module; + gpointer data; +} ConnectData; + +/* default signal connection code */ +static void +clutter_script_default_connect (ClutterScript *script, + GObject *gobject, + const gchar *signal_name, + const gchar *signal_handler, + GObject *connect_gobject, + GConnectFlags flags, + gpointer user_data) +{ + ConnectData *data = user_data; + GCallback function; + + if (!data->module) + return; + + if (!g_module_symbol (data->module, signal_handler, (gpointer) &function)) + { + g_warning ("Could not find a signal handler '%s' for signal '%s::%s'", + signal_handler, + connect_gobject ? G_OBJECT_TYPE_NAME (connect_gobject) + : G_OBJECT_TYPE_NAME (gobject), + signal_name); + return; + } + + CLUTTER_NOTE (SCRIPT, + "connecting %s::%s to %s (afetr:%s, swapped:%s, object:%s)", + (connect_gobject ? G_OBJECT_TYPE_NAME (connect_gobject) + : G_OBJECT_TYPE_NAME (gobject)), + signal_name, + signal_handler, + (flags & G_CONNECT_AFTER) ? "true" : "false", + (flags & G_CONNECT_SWAPPED) ? "true" : "false", + (connect_gobject ? G_OBJECT_TYPE_NAME (connect_gobject) + : "")); + + if (connect_gobject != NULL) + g_signal_connect_object (gobject, + signal_name, function, + connect_gobject, + flags); + else + g_signal_connect_data (gobject, + signal_name, function, + data->data, + NULL, + flags); +} + +/** + * clutter_script_connect_signals: + * @script: a #ClutterScript + * @user_data: data to be passed to the signal handlers, or %NULL + * + * Connects all the signals defined into a UI definition file to their + * handlers. + * + * This method invokes clutter_script_connect_signals_full() internally + * and uses #GModule's introspective features (by opening the current + * module's scope) to look at the application's symbol table. + * + * Note that this function will not work if #GModule is not supported by + * the platform Clutter is running on. + * + * Since: 0.6 + */ +void +clutter_script_connect_signals (ClutterScript *script, + gpointer user_data) +{ + ConnectData *cd; + + g_return_if_fail (CLUTTER_IS_SCRIPT (script)); + + if (!g_module_supported ()) + { + g_critical ("clutter_script_connect_signals() requires a working " + "GModule support from GLib"); + return; + } + + cd = g_new (ConnectData, 1); + cd->module = g_module_open (NULL, 0); + cd->data = user_data; + + clutter_script_connect_signals_full (script, + clutter_script_default_connect, + cd); + + g_module_close (cd->module); + + g_free (cd); +} + +typedef struct { + ClutterState *state; + GObject *emitter; + gchar *target; + gulong signal_id; + gulong hook_id; + gboolean warp_to; +} HookData; + +typedef struct { + ClutterScript *script; + ClutterScriptConnectFunc func; + gpointer user_data; +} SignalConnectData; + +static void +hook_data_free (gpointer data) +{ + if (G_LIKELY (data != NULL)) + { + HookData *hook_data = data; + + g_free (hook_data->target); + g_slice_free (HookData, hook_data); + } +} + +static gboolean +clutter_script_state_change_hook (GSignalInvocationHint *ihint, + guint n_params, + const GValue *params, + gpointer user_data) +{ + HookData *hook_data = user_data; + GObject *emitter; + + emitter = g_value_get_object (¶ms[0]); + + if (emitter == hook_data->emitter) + { + if (hook_data->warp_to) + clutter_state_warp_to_state (hook_data->state, hook_data->target); + else + clutter_state_set_state (hook_data->state, hook_data->target); + } + + return TRUE; +} + +static void +clutter_script_remove_state_change_hook (gpointer user_data, + GObject *object_p) +{ + HookData *hook_data = user_data; + + g_signal_remove_emission_hook (hook_data->signal_id, + hook_data->hook_id); +} + +static void +connect_each_object (gpointer key, + gpointer value, + gpointer data) +{ + SignalConnectData *connect_data = data; + ClutterScript *script = connect_data->script; + ObjectInfo *oinfo = value; + GObject *object = oinfo->object; + GList *unresolved, *l; + + _clutter_script_construct_object (script, oinfo); + + unresolved = NULL; + for (l = oinfo->signals; l != NULL; l = l->next) + { + SignalInfo *sinfo = l->data; + + if (sinfo->is_handler) + { + GObject *connect_object = NULL; + + if (sinfo->object) + connect_object = clutter_script_get_object (script, sinfo->object); + + if (sinfo->object && !connect_object) + unresolved = g_list_prepend (unresolved, sinfo); + else + { + connect_data->func (script, object, + sinfo->name, + sinfo->handler, + connect_object, + sinfo->flags, + connect_data->user_data); + } + } + else + { + GObject *state_object = NULL; + const gchar *signal_name, *signal_detail; + gchar **components; + GQuark signal_quark; + guint signal_id; + HookData *hook_data; + + if (sinfo->state == NULL) + state_object = (GObject *) clutter_script_get_states (script, NULL); + else + { + state_object = clutter_script_get_object (script, sinfo->state); + if (state_object == NULL) + state_object = (GObject *) clutter_script_get_states (script, sinfo->state); + } + + if (state_object == NULL) + continue; + + components = g_strsplit (sinfo->name, "::", 2); + if (g_strv_length (components) == 2) + { + signal_name = components[0]; + signal_detail = components[1]; + } + else + { + signal_name = components[0]; + signal_detail = NULL; + } + + signal_id = g_signal_lookup (signal_name, G_OBJECT_TYPE (object)); + if (signal_id == 0) + { + g_strfreev (components); + continue; + } + + if (signal_detail != NULL) + signal_quark = g_quark_from_string (signal_detail); + else + signal_quark = 0; + + hook_data = g_slice_new (HookData); + hook_data->emitter = object; + hook_data->state = CLUTTER_STATE (state_object); + hook_data->target = g_strdup (sinfo->target); + hook_data->warp_to = sinfo->warp_to; + hook_data->signal_id = signal_id; + hook_data->hook_id = + g_signal_add_emission_hook (signal_id, signal_quark, + clutter_script_state_change_hook, + hook_data, + hook_data_free); + + g_object_weak_ref (hook_data->emitter, + clutter_script_remove_state_change_hook, + hook_data); + } + + signal_info_free (sinfo); + } + + /* keep the unresolved signal handlers around, in case + * clutter_script_connect_signals() is called multiple + * times (e.g. after a UI definition merge) + */ + g_list_free (oinfo->signals); + oinfo->signals = unresolved; +} + +/** + * clutter_script_connect_signals_full: + * @script: a #ClutterScript + * @func: (scope call): signal connection function + * @user_data: data to be passed to the signal handlers, or %NULL + * + * Connects all the signals defined into a UI definition file to their + * handlers. + * + * This function allows to control how the signal handlers are + * going to be connected to their respective signals. It is meant + * primarily for language bindings to allow resolving the function + * names using the native API, but it can also be used on platforms + * that do not support GModule. + * + * Applications should use clutter_script_connect_signals(). + * + * Since: 0.6 + */ +void +clutter_script_connect_signals_full (ClutterScript *script, + ClutterScriptConnectFunc func, + gpointer user_data) +{ + SignalConnectData data; + + g_return_if_fail (CLUTTER_IS_SCRIPT (script)); + g_return_if_fail (func != NULL); + + data.script = script; + data.func = func; + data.user_data = user_data; + + g_hash_table_foreach (script->priv->objects, connect_each_object, &data); +} + +GQuark +clutter_script_error_quark (void) +{ + return g_quark_from_static_string ("clutter-script-error"); +} + +/** + * clutter_script_add_search_paths: + * @script: a #ClutterScript + * @paths: (array length=n_paths): an array of strings containing + * different search paths + * @n_paths: the length of the passed array + * + * Adds @paths to the list of search paths held by @script. + * + * The search paths are used by clutter_script_lookup_filename(), which + * can be used to define search paths for the textures source file name + * or other custom, file-based properties. + * + * Since: 0.8 + */ +void +clutter_script_add_search_paths (ClutterScript *script, + const gchar * const paths[], + gsize n_paths) +{ + ClutterScriptPrivate *priv; + gchar **old_paths, **new_paths; + gsize old_paths_len, i; + gsize iter = 0; + + g_return_if_fail (CLUTTER_IS_SCRIPT (script)); + g_return_if_fail (paths != NULL); + g_return_if_fail (n_paths > 0); + + priv = script->priv; + + if (priv->search_paths) + { + old_paths = priv->search_paths; + old_paths_len = g_strv_length (old_paths); + } + else + { + old_paths = NULL; + old_paths_len = 0; + } + + new_paths = g_new0 (gchar*, old_paths_len + n_paths + 1); + + for (i = 0, iter = 0; i < old_paths_len; i++, iter++) + new_paths[iter] = g_strdup (old_paths[i]); + + for (i = 0; i < n_paths; i++, iter++) + new_paths[iter] = g_strdup (paths[i]); + + CLUTTER_NOTE (SCRIPT, + "Added %" G_GSIZE_FORMAT " new search paths (new size: %d)", + n_paths, + g_strv_length (new_paths)); + + priv->search_paths = new_paths; + + if (old_paths) + g_strfreev (old_paths); +} + +/** + * clutter_script_lookup_filename: + * @script: a #ClutterScript + * @filename: the name of the file to lookup + * + * Looks up @filename inside the search paths of @script. If @filename + * is found, its full path will be returned . + * + * Return value: the full path of @filename or %NULL if no path was + * found. + * + * Since: 0.8 + */ +gchar * +clutter_script_lookup_filename (ClutterScript *script, + const gchar *filename) +{ + ClutterScriptPrivate *priv; + gchar *dirname; + gchar *retval; + + g_return_val_if_fail (CLUTTER_IS_SCRIPT (script), NULL); + g_return_val_if_fail (filename != NULL, NULL); + + if (g_path_is_absolute (filename)) + return g_strdup (filename); + + priv = script->priv; + + if (priv->search_paths) + { + gsize paths_len, i; + + paths_len = g_strv_length (priv->search_paths); + for (i = 0; i < paths_len; i++) + { + retval = g_build_filename (priv->search_paths[i], filename, NULL); + if (g_file_test (retval, G_FILE_TEST_EXISTS)) + return retval; + else + { + g_free (retval); + retval = NULL; + } + } + } + + /* Fall back to assuming relative to our script */ + if (priv->is_filename) + dirname = g_path_get_dirname (script->priv->filename); + else + dirname = g_get_current_dir (); + + retval = g_build_filename (dirname, filename, NULL); + if (!g_file_test (retval, G_FILE_TEST_EXISTS)) + { + g_free (retval); + retval = NULL; + } + + g_free (dirname); + + return retval; +} + +/** + * clutter_script_list_objects: + * @script: a #ClutterScript + * + * Retrieves all the objects created by @script. + * + * Note: this function does not increment the reference count of the + * objects it returns. + * + * Return value: (transfer container) (element-type GObject.Object): a list + * of #GObjects, or %NULL. The objects are owned by the + * #ClutterScript instance. Use g_list_free() on the returned list when + * done. + * + * Since: 0.8 + */ +GList * +clutter_script_list_objects (ClutterScript *script) +{ + GList *objects, *l; + GList *retval; + + g_return_val_if_fail (CLUTTER_IS_SCRIPT (script), NULL); + + clutter_script_ensure_objects (script); + if (!script->priv->objects) + return NULL; + + retval = NULL; + objects = g_hash_table_get_values (script->priv->objects); + for (l = objects; l != NULL; l = l->next) + { + ObjectInfo *oinfo = l->data; + + if (oinfo->object) + retval = g_list_prepend (retval, oinfo->object); + } + + g_list_free (objects); + + return retval; +} + +/** + * clutter_script_add_states: + * @script: a #ClutterScript + * @name: (allow-none): a name for the @state, or %NULL to + * set the default #ClutterState + * @state: a #ClutterState + * + * Associates a #ClutterState to the #ClutterScript instance using the given + * name. + * + * The #ClutterScript instance will use @state to resolve target states when + * connecting signal handlers. + * + * The #ClutterScript instance will take a reference on the #ClutterState + * passed to this function. + * + * Since: 1.8 + * + * Deprecated: 1.12 + */ +void +clutter_script_add_states (ClutterScript *script, + const gchar *name, + ClutterState *state) +{ + g_return_if_fail (CLUTTER_IS_SCRIPT (script)); + g_return_if_fail (CLUTTER_IS_STATE (state)); + + if (name == NULL || *name == '\0') + name = "__clutter_script_default_state"; + + g_hash_table_replace (script->priv->states, + g_strdup (name), + g_object_ref (state)); +} + +/** + * clutter_script_get_states: + * @script: a #ClutterScript + * @name: (allow-none): the name of the #ClutterState, or %NULL + * + * Retrieves the #ClutterState for the given @state_name. + * + * If @name is %NULL, this function will return the default + * #ClutterState instance. + * + * Return value: (transfer none): a pointer to the #ClutterState for the + * given name. The #ClutterState is owned by the #ClutterScript instance + * and it should not be unreferenced + * + * Since: 1.8 + * + * Deprecated: 1.12 + */ +ClutterState * +clutter_script_get_states (ClutterScript *script, + const gchar *name) +{ + g_return_val_if_fail (CLUTTER_IS_SCRIPT (script), NULL); + + if (name == NULL || *name == '\0') + name = "__clutter_script_default_state"; + + return g_hash_table_lookup (script->priv->states, name); +} + +/** + * clutter_script_set_translation_domain: + * @script: a #ClutterScript + * @domain: (allow-none): the translation domain, or %NULL + * + * Sets the translation domain for @script. + * + * Since: 1.10 + */ +void +clutter_script_set_translation_domain (ClutterScript *script, + const gchar *domain) +{ + g_return_if_fail (CLUTTER_IS_SCRIPT (script)); + + if (g_strcmp0 (domain, script->priv->translation_domain) == 0) + return; + + g_free (script->priv->translation_domain); + script->priv->translation_domain = g_strdup (domain); + + g_object_notify_by_pspec (G_OBJECT (script), obj_props[PROP_TRANSLATION_DOMAIN]); +} + +/** + * clutter_script_get_translation_domain: + * @script: a #ClutterScript + * + * Retrieves the translation domain set using + * clutter_script_set_translation_domain(). + * + * Return value: (transfer none): the translation domain, if any is set, + * or %NULL + * + * Since: 1.10 + */ +const gchar * +clutter_script_get_translation_domain (ClutterScript *script) +{ + g_return_val_if_fail (CLUTTER_IS_SCRIPT (script), NULL); + + return script->priv->translation_domain; +} + +/* + * _clutter_script_generate_fake_id: + * @script: a #ClutterScript + * + * Generates a fake id string for object definitions without + * an "id" member + * + * Return value: a newly-allocated string containing the fake + * id. Use g_free() to free the resources allocated by the + * returned value + * + */ +gchar * +_clutter_script_generate_fake_id (ClutterScript *script) +{ + ClutterScriptPrivate *priv = script->priv; + + return g_strdup_printf ("script-%d-%d", + priv->last_merge_id, + priv->last_unknown++); +} + +/* + * _clutter_script_warn_missing_attribute: + * @script: a #ClutterScript + * @id_: the id of an object definition, or %NULL + * @attribute: the expected attribute + * + * Emits a warning, using GLib's log facilities, for a missing + * @attribute in an object definition, pointing to the current + * location of the #ClutterScriptParser + */ +void +_clutter_script_warn_missing_attribute (ClutterScript *script, + const gchar *id_, + const gchar *attribute) +{ + ClutterScriptPrivate *priv = script->priv; + JsonParser *parser = JSON_PARSER (priv->parser); + gint current_line = json_parser_get_current_line (parser); + + if (id_ != NULL && *id_ != '\0') + { + g_warning ("%s:%d: object '%s' has no '%s' attribute", + priv->is_filename ? priv->filename : "", + current_line, + id_, + attribute); + } + else + { + g_warning ("%s:%d: object has no '%s' attribute", + priv->is_filename ? priv->filename : "", + current_line, + attribute); + } +} + +/* + * _clutter_script_warn_invalid_value: + * @script: a #ClutterScript + * @attribute: the attribute with the invalid value + * @expected: a string with the expected value + * @node: a #JsonNode containing the value + * + * Emits a warning, using GLib's log facilities, for an invalid + * value found when parsing @attribute, pointing to the current + * location of the #ClutterScriptParser + */ +void +_clutter_script_warn_invalid_value (ClutterScript *script, + const gchar *attribute, + const gchar *expected, + JsonNode *node) +{ + ClutterScriptPrivate *priv = script->priv; + JsonParser *parser = JSON_PARSER (priv->parser); + gint current_line = json_parser_get_current_line (parser); + + if (node != NULL) + { + g_warning ("%s:%d: invalid value of type '%s' for attribute '%s':" + "a value of type '%s' is expected", + priv->is_filename ? priv->filename : "", + current_line, + json_node_type_name (node), + attribute, + expected); + } + else + { + g_warning ("%s:%d: invalid value for attribute '%s':" + "a value of type '%s' is expected", + priv->is_filename ? priv->filename : "", + current_line, + attribute, + expected); + } +} + +/* + * _clutter_script_get_object_info: + * @script: a #ClutterScript + * @script_id: the id of the object definition + * + * Retrieves the #ObjectInfo for the given @script_id + * + * Return value: a #ObjectInfo or %NULL + */ +ObjectInfo * +_clutter_script_get_object_info (ClutterScript *script, + const gchar *script_id) +{ + ClutterScriptPrivate *priv = script->priv; + + return g_hash_table_lookup (priv->objects, script_id); +} + +/* + * _clutter_script_get_last_merge_id: + * @script: a #ClutterScript + * + * Retrieves the last merge id of @script. The merge id + * should be stored inside an #ObjectInfo. If you need + * a unique fake id for object definitions with an "id" + * member, consider using _clutter_script_generate_fake_id() + * instead + * + * Return value: the last merge id + */ +guint +_clutter_script_get_last_merge_id (ClutterScript *script) +{ + return script->priv->last_merge_id; +} + +/* + * _clutter_script_add_object_info: + * @script: a #ClutterScript + * @oinfo: a #ObjectInfo + * + * Adds @oinfo inside the objects list held by @script + */ +void +_clutter_script_add_object_info (ClutterScript *script, + ObjectInfo *oinfo) +{ + ClutterScriptPrivate *priv = script->priv; + + g_hash_table_steal (priv->objects, oinfo->id); + g_hash_table_insert (priv->objects, oinfo->id, oinfo); +} diff --git a/clutter/clutter/clutter-script.h b/clutter/clutter/clutter-script.h new file mode 100644 index 0000000..37f4a05 --- /dev/null +++ b/clutter/clutter/clutter-script.h @@ -0,0 +1,220 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __CLUTTER_SCRIPT_H__ +#define __CLUTTER_SCRIPT_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_SCRIPT (clutter_script_get_type ()) +#define CLUTTER_SCRIPT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_SCRIPT, ClutterScript)) +#define CLUTTER_IS_SCRIPT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_SCRIPT)) +#define CLUTTER_SCRIPT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_SCRIPT, ClutterScriptClass)) +#define CLUTTER_IS_SCRIPT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_SCRIPT)) +#define CLUTTER_SCRIPT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_SCRIPT, ClutterScriptClass)) + +typedef struct _ClutterScript ClutterScript; +typedef struct _ClutterScriptPrivate ClutterScriptPrivate; +typedef struct _ClutterScriptClass ClutterScriptClass; + +/** + * ClutterScriptConnectFunc: + * @script: a #ClutterScript + * @object: the object to connect + * @signal_name: the name of the signal + * @handler_name: the name of the signal handler + * @connect_object: the object to connect the signal to, or %NULL + * @flags: signal connection flags + * @user_data: user data to pass to the signal handler + * + * This is the signature of a function used to connect signals. It is used + * by the clutter_script_connect_signals_full() function. It is mainly + * intended for interpreted language bindings, but could be useful where the + * programmer wants more control over the signal connection process. + * + * Since: 0.6 + */ +typedef void (* ClutterScriptConnectFunc) (ClutterScript *script, + GObject *object, + const gchar *signal_name, + const gchar *handler_name, + GObject *connect_object, + GConnectFlags flags, + gpointer user_data); + +/** + * ClutterScriptError: + * @CLUTTER_SCRIPT_ERROR_INVALID_TYPE_FUNCTION: Type function not found + * or invalid + * @CLUTTER_SCRIPT_ERROR_INVALID_PROPERTY: Property not found or invalid + * @CLUTTER_SCRIPT_ERROR_INVALID_VALUE: Invalid value + * + * #ClutterScript error enumeration. + * + * Since: 0.6 + */ +typedef enum { + CLUTTER_SCRIPT_ERROR_INVALID_TYPE_FUNCTION, + CLUTTER_SCRIPT_ERROR_INVALID_PROPERTY, + CLUTTER_SCRIPT_ERROR_INVALID_VALUE +} ClutterScriptError; + +/** + * CLUTTER_SCRIPT_ERROR: + * + * Error domain for the #ClutterScript errors + * + * Since: 0.6 + */ +#define CLUTTER_SCRIPT_ERROR (clutter_script_error_quark ()) +CLUTTER_AVAILABLE_IN_ALL +GQuark clutter_script_error_quark (void); + +/** + * ClutterScript: + * + * The #ClutterScript structure contains only private data + * and should be accessed using the provided API + * + * Since: 0.6 + */ +struct _ClutterScript +{ + /*< private >*/ + GObject parent_instance; + + ClutterScriptPrivate *priv; +}; + +/** + * ClutterScriptClass: + * @get_type_from_name: virtual function used to map a type name + * to a #GType. This function should only be overridden by + * language bindings in order to map native types to #GType. + * The default implementation is equivalent to g_type_from_name() + * + * The #ClutterScriptClass structure contains only private data + * + * Since: 0.6 + */ +struct _ClutterScriptClass +{ + /*< private >*/ + GObjectClass parent_class; + + /*< public >*/ + GType (* get_type_from_name) (ClutterScript *script, + const gchar *type_name); + + /*< private >*/ + /* padding, for future expansion */ + void (*_clutter_reserved1) (void); + void (*_clutter_reserved2) (void); + void (*_clutter_reserved3) (void); + void (*_clutter_reserved4) (void); + void (*_clutter_reserved5) (void); + void (*_clutter_reserved6) (void); + void (*_clutter_reserved7) (void); + void (*_clutter_reserved8) (void); +}; + +CLUTTER_AVAILABLE_IN_ALL +GType clutter_script_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_ALL +ClutterScript * clutter_script_new (void); +CLUTTER_AVAILABLE_IN_ALL +guint clutter_script_load_from_file (ClutterScript *script, + const gchar *filename, + GError **error); +CLUTTER_AVAILABLE_IN_ALL +guint clutter_script_load_from_data (ClutterScript *script, + const gchar *data, + gssize length, + GError **error); +CLUTTER_AVAILABLE_IN_1_10 +guint clutter_script_load_from_resource (ClutterScript *script, + const gchar *resource_path, + GError **error); + +CLUTTER_AVAILABLE_IN_ALL +GObject * clutter_script_get_object (ClutterScript *script, + const gchar *name); +CLUTTER_AVAILABLE_IN_ALL +gint clutter_script_get_objects (ClutterScript *script, + const gchar *first_name, + ...) G_GNUC_NULL_TERMINATED; +CLUTTER_AVAILABLE_IN_ALL +GList * clutter_script_list_objects (ClutterScript *script); +CLUTTER_AVAILABLE_IN_ALL +void clutter_script_unmerge_objects (ClutterScript *script, + guint merge_id); +CLUTTER_AVAILABLE_IN_ALL +void clutter_script_ensure_objects (ClutterScript *script); + +CLUTTER_DEPRECATED_IN_1_12 +void clutter_script_add_states (ClutterScript *script, + const gchar *name, + ClutterState *state); + +CLUTTER_DEPRECATED_IN_1_12 +ClutterState * clutter_script_get_states (ClutterScript *script, + const gchar *name); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_script_connect_signals (ClutterScript *script, + gpointer user_data); +CLUTTER_AVAILABLE_IN_ALL +void clutter_script_connect_signals_full (ClutterScript *script, + ClutterScriptConnectFunc func, + gpointer user_data); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_script_add_search_paths (ClutterScript *script, + const gchar * const paths[], + gsize n_paths); +CLUTTER_AVAILABLE_IN_ALL +gchar * clutter_script_lookup_filename (ClutterScript *script, + const gchar *filename) G_GNUC_MALLOC; +CLUTTER_AVAILABLE_IN_ALL +GType clutter_script_get_type_from_name (ClutterScript *script, + const gchar *type_name); + +CLUTTER_AVAILABLE_IN_1_10 +void clutter_script_set_translation_domain (ClutterScript *script, + const gchar *domain); +CLUTTER_AVAILABLE_IN_1_10 +const gchar * clutter_script_get_translation_domain (ClutterScript *script); + +CLUTTER_AVAILABLE_IN_ALL +const gchar * clutter_get_script_id (GObject *gobject); + +G_END_DECLS + +#endif /* __CLUTTER_SCRIPT_H__ */ diff --git a/clutter/clutter/clutter-scriptable.c b/clutter/clutter/clutter-scriptable.c new file mode 100644 index 0000000..5b5096e --- /dev/null +++ b/clutter/clutter/clutter-scriptable.c @@ -0,0 +1,185 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * Emmanuele Bassi + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +/** + * SECTION:clutter-scriptable + * @short_description: Override the UI definition parsing + * + * The #ClutterScriptableIface interface exposes the UI definition parsing + * process to external classes. By implementing this interface, a class can + * override the UI definition parsing and transform complex data types into + * GObject properties, or allow custom properties. + * + * #ClutterScriptable is available since Clutter 0.6 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include +#include + +#include + +#include "clutter-scriptable.h" +#include "clutter-script-private.h" + +#include "clutter-private.h" +#include "clutter-debug.h" + +typedef ClutterScriptableIface ClutterScriptableInterface; + +G_DEFINE_INTERFACE (ClutterScriptable, clutter_scriptable, G_TYPE_OBJECT); + +static void +clutter_scriptable_default_init (ClutterScriptableInterface *iface) +{ +} + +/** + * clutter_scriptable_set_id: + * @scriptable: a #ClutterScriptable + * @id_: the #ClutterScript id of the object + * + * Sets @id_ as the unique Clutter script it for this instance of + * #ClutterScriptableIface. + * + * This name can be used by user interface designer applications to + * define a unique name for an object constructable using the UI + * definition language parsed by #ClutterScript. + * + * Since: 0.6 + */ +void +clutter_scriptable_set_id (ClutterScriptable *scriptable, + const gchar *id_) +{ + ClutterScriptableIface *iface; + + g_return_if_fail (CLUTTER_IS_SCRIPTABLE (scriptable)); + g_return_if_fail (id_ != NULL); + + iface = CLUTTER_SCRIPTABLE_GET_IFACE (scriptable); + if (iface->set_id) + iface->set_id (scriptable, id_); + else + g_object_set_data_full (G_OBJECT (scriptable), + "clutter-script-id", + g_strdup (id_), + g_free); +} + +/** + * clutter_scriptable_get_id: + * @scriptable: a #ClutterScriptable + * + * Retrieves the id of @scriptable set using clutter_scriptable_set_id(). + * + * Return value: the id of the object. The returned string is owned by + * the scriptable object and should never be modified of freed + * + * Since: 0.6 + */ +const gchar * +clutter_scriptable_get_id (ClutterScriptable *scriptable) +{ + ClutterScriptableIface *iface; + + g_return_val_if_fail (CLUTTER_IS_SCRIPTABLE (scriptable), NULL); + + iface = CLUTTER_SCRIPTABLE_GET_IFACE (scriptable); + if (iface->get_id) + return iface->get_id (scriptable); + else + return g_object_get_data (G_OBJECT (scriptable), "clutter-script-id"); +} + +/** + * clutter_scriptable_parse_custom_node: + * @scriptable: a #ClutterScriptable + * @script: the #ClutterScript creating the scriptable instance + * @value: the generic value to be set + * @name: the name of the node + * @node: the JSON node to be parsed + * + * Parses the passed JSON node. The implementation must set the type + * of the passed #GValue pointer using g_value_init(). + * + * Return value: %TRUE if the node was successfully parsed, %FALSE otherwise. + * + * Since: 0.6 + */ +gboolean +clutter_scriptable_parse_custom_node (ClutterScriptable *scriptable, + ClutterScript *script, + GValue *value, + const gchar *name, + JsonNode *node) +{ + ClutterScriptableIface *iface; + + g_return_val_if_fail (CLUTTER_IS_SCRIPTABLE (scriptable), FALSE); + g_return_val_if_fail (CLUTTER_IS_SCRIPT (script), FALSE); + g_return_val_if_fail (name != NULL, FALSE); + g_return_val_if_fail (node != NULL, FALSE); + + iface = CLUTTER_SCRIPTABLE_GET_IFACE (scriptable); + if (iface->parse_custom_node) + return iface->parse_custom_node (scriptable, script, value, name, node); + + return FALSE; +} + +/** + * clutter_scriptable_set_custom_property: + * @scriptable: a #ClutterScriptable + * @script: the #ClutterScript creating the scriptable instance + * @name: the name of the property + * @value: the value of the property + * + * Overrides the common properties setting. The underlying virtual + * function should be used when implementing custom properties. + * + * Since: 0.6 + */ +void +clutter_scriptable_set_custom_property (ClutterScriptable *scriptable, + ClutterScript *script, + const gchar *name, + const GValue *value) +{ + ClutterScriptableIface *iface; + + g_return_if_fail (CLUTTER_IS_SCRIPTABLE (scriptable)); + g_return_if_fail (CLUTTER_IS_SCRIPT (script)); + g_return_if_fail (name != NULL); + g_return_if_fail (value != NULL); + + iface = CLUTTER_SCRIPTABLE_GET_IFACE (scriptable); + if (iface->set_custom_property) + iface->set_custom_property (scriptable, script, name, value); +} diff --git a/clutter/clutter/clutter-scriptable.h b/clutter/clutter/clutter-scriptable.h new file mode 100644 index 0000000..61beb29 --- /dev/null +++ b/clutter/clutter/clutter-scriptable.h @@ -0,0 +1,112 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * Emmanuele Bassi + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __CLUTTER_SCRIPTABLE_H__ +#define __CLUTTER_SCRIPTABLE_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_SCRIPTABLE (clutter_scriptable_get_type ()) +#define CLUTTER_SCRIPTABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_SCRIPTABLE, ClutterScriptable)) +#define CLUTTER_IS_SCRIPTABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_SCRIPTABLE)) +#define CLUTTER_SCRIPTABLE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), CLUTTER_TYPE_SCRIPTABLE, ClutterScriptableIface)) + +typedef struct _ClutterScriptable ClutterScriptable; +typedef struct _ClutterScriptableIface ClutterScriptableIface; + +/** + * ClutterScriptable: + * + * #ClutterScriptable is an opaque structure whose members cannot be directly + * accessed + * + * Since: 0.6 + */ + +/** + * ClutterScriptableIface: + * @set_id: virtual function for setting the id of a scriptable object + * @get_id: virtual function for getting the id of a scriptable object + * @parse_custom_node: virtual function for parsing complex data containers + * into GObject properties + * @set_custom_property: virtual function for setting a custom property + * + * Interface for implementing "scriptable" objects. An object implementing + * this interface can override the parsing and properties setting sequence + * when loading a UI definition data with #ClutterScript + * + * Since: 0.6 + */ +struct _ClutterScriptableIface +{ + /*< private >*/ + GTypeInterface g_iface; + + /*< public >*/ + void (* set_id) (ClutterScriptable *scriptable, + const gchar *id_); + const gchar *(* get_id) (ClutterScriptable *scriptable); + + gboolean (* parse_custom_node) (ClutterScriptable *scriptable, + ClutterScript *script, + GValue *value, + const gchar *name, + JsonNode *node); + void (* set_custom_property) (ClutterScriptable *scriptable, + ClutterScript *script, + const gchar *name, + const GValue *value); +}; + +CLUTTER_AVAILABLE_IN_ALL +GType clutter_scriptable_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_ALL +void clutter_scriptable_set_id (ClutterScriptable *scriptable, + const gchar *id_); +CLUTTER_AVAILABLE_IN_ALL +const gchar * clutter_scriptable_get_id (ClutterScriptable *scriptable); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_scriptable_parse_custom_node (ClutterScriptable *scriptable, + ClutterScript *script, + GValue *value, + const gchar *name, + JsonNode *node); +CLUTTER_AVAILABLE_IN_ALL +void clutter_scriptable_set_custom_property (ClutterScriptable *scriptable, + ClutterScript *script, + const gchar *name, + const GValue *value); + +G_END_DECLS + +#endif /* __CLUTTER_SCRIPTABLE_H__ */ diff --git a/clutter/clutter/clutter-scroll-actor.c b/clutter/clutter/clutter-scroll-actor.c new file mode 100644 index 0000000..941f643 --- /dev/null +++ b/clutter/clutter/clutter-scroll-actor.c @@ -0,0 +1,436 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2012 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 . + */ + +/** + * SECTION:clutter-scroll-actor + * @Title: ClutterScrollActor + * @Short_Description: An actor for displaying a portion of its children + * + * #ClutterScrollActor is an actor that can be used to display a portion + * of the contents of its children. + * + * The extent of the area of a #ClutterScrollActor is defined by the size + * of its children; the visible region of the children of a #ClutterScrollActor + * is set by using clutter_scroll_actor_scroll_to_point() or by using + * clutter_scroll_actor_scroll_to_rect() to define a point or a rectangle + * acting as the origin, respectively. + * + * #ClutterScrollActor does not provide pointer or keyboard event handling, + * nor does it provide visible scroll handles. + * + * See [scroll-actor.c](https://git.gnome.org/browse/clutter/tree/examples/scroll-actor.c?h=clutter-1.18) + * for an example of how to use #ClutterScrollActor. + * + * #ClutterScrollActor is available since Clutter 1.12. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-scroll-actor.h" + +#include "clutter-actor-private.h" +#include "clutter-animatable.h" +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-private.h" +#include "clutter-property-transition.h" +#include "clutter-transition.h" + +struct _ClutterScrollActorPrivate +{ + ClutterPoint scroll_to; + + ClutterScrollMode scroll_mode; + + ClutterTransition *transition; +}; + +enum +{ + PROP_0, + + PROP_SCROLL_MODE, + + PROP_LAST +}; + +enum +{ + ANIM_PROP_0, + + ANIM_PROP_SCROLL_TO, + + ANIM_PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST] = { NULL, }; +static GParamSpec *animatable_props[ANIM_PROP_LAST] = { NULL, }; + +static ClutterAnimatableIface *parent_animatable_iface = NULL; + +static void clutter_animatable_iface_init (ClutterAnimatableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (ClutterScrollActor, clutter_scroll_actor, CLUTTER_TYPE_ACTOR, + G_ADD_PRIVATE (ClutterScrollActor) + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_ANIMATABLE, + clutter_animatable_iface_init)) + +static void +clutter_scroll_actor_set_scroll_to_internal (ClutterScrollActor *self, + const ClutterPoint *point) +{ + ClutterScrollActorPrivate *priv = self->priv; + ClutterActor *actor = CLUTTER_ACTOR (self); + ClutterMatrix m = CLUTTER_MATRIX_INIT_IDENTITY; + float dx, dy; + + if (clutter_point_equals (&priv->scroll_to, point)) + return; + + if (point == NULL) + clutter_point_init (&priv->scroll_to, 0.f, 0.f); + else + priv->scroll_to = *point; + + if (priv->scroll_mode & CLUTTER_SCROLL_HORIZONTALLY) + dx = -priv->scroll_to.x; + else + dx = 0.f; + + if (priv->scroll_mode & CLUTTER_SCROLL_VERTICALLY) + dy = -priv->scroll_to.y; + else + dy = 0.f; + + cogl_matrix_translate (&m, dx, dy, 0.f); + clutter_actor_set_child_transform (actor, &m); +} + +static void +clutter_scroll_actor_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterScrollActor *actor = CLUTTER_SCROLL_ACTOR (gobject); + + switch (prop_id) + { + case PROP_SCROLL_MODE: + clutter_scroll_actor_set_scroll_mode (actor, g_value_get_flags (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + } +} + +static void +clutter_scroll_actor_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterScrollActor *actor = CLUTTER_SCROLL_ACTOR (gobject); + + switch (prop_id) + { + case PROP_SCROLL_MODE: + g_value_set_flags (value, actor->priv->scroll_mode); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + } +} + +static void +clutter_scroll_actor_class_init (ClutterScrollActorClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = clutter_scroll_actor_set_property; + gobject_class->get_property = clutter_scroll_actor_get_property; + + /** + * ClutterScrollActor:scroll-mode: + * + * The scrollin direction. + * + * Since: 1.12 + */ + obj_props[PROP_SCROLL_MODE] = + g_param_spec_flags ("scroll-mode", + P_("Scroll Mode"), + P_("The scrolling direction"), + CLUTTER_TYPE_SCROLL_MODE, + CLUTTER_SCROLL_BOTH, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); +} + +static void +clutter_scroll_actor_init (ClutterScrollActor *self) +{ + self->priv = clutter_scroll_actor_get_instance_private (self); + self->priv->scroll_mode = CLUTTER_SCROLL_BOTH; + + clutter_actor_set_clip_to_allocation (CLUTTER_ACTOR (self), TRUE); +} + +static GParamSpec * +clutter_scroll_actor_find_property (ClutterAnimatable *animatable, + const char *property_name) +{ + if (strcmp (property_name, "scroll-to") == 0) + return animatable_props[ANIM_PROP_SCROLL_TO]; + + return parent_animatable_iface->find_property (animatable, property_name); +} + +static void +clutter_scroll_actor_set_final_state (ClutterAnimatable *animatable, + const char *property_name, + const GValue *value) +{ + if (strcmp (property_name, "scroll-to") == 0) + { + ClutterScrollActor *self = CLUTTER_SCROLL_ACTOR (animatable); + const ClutterPoint *point = g_value_get_boxed (value); + + clutter_scroll_actor_set_scroll_to_internal (self, point); + } + else + parent_animatable_iface->set_final_state (animatable, property_name, value); +} + +static void +clutter_scroll_actor_get_initial_state (ClutterAnimatable *animatable, + const char *property_name, + GValue *value) +{ + if (strcmp (property_name, "scroll-to") == 0) + { + ClutterScrollActor *self = CLUTTER_SCROLL_ACTOR (animatable); + + g_value_set_boxed (value, &self->priv->scroll_to); + } + else + parent_animatable_iface->get_initial_state (animatable, property_name, value); +} + +static void +clutter_animatable_iface_init (ClutterAnimatableIface *iface) +{ + parent_animatable_iface = g_type_interface_peek_parent (iface); + + animatable_props[ANIM_PROP_SCROLL_TO] = + g_param_spec_boxed ("scroll-to", + "Scroll To", + "The point to scroll the actor to", + CLUTTER_TYPE_POINT, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + CLUTTER_PARAM_ANIMATABLE); + + iface->find_property = clutter_scroll_actor_find_property; + iface->get_initial_state = clutter_scroll_actor_get_initial_state; + iface->set_final_state = clutter_scroll_actor_set_final_state; +} + +/** + * clutter_scroll_actor_new: + * + * Creates a new #ClutterScrollActor. + * + * Return value: The newly created #ClutterScrollActor + * instance. + * + * Since: 1.12 + */ +ClutterActor * +clutter_scroll_actor_new (void) +{ + return g_object_new (CLUTTER_TYPE_SCROLL_ACTOR, NULL); +} + +/** + * clutter_scroll_actor_set_scroll_mode: + * @actor: a #ClutterScrollActor + * @mode: a #ClutterScrollMode + * + * Sets the #ClutterScrollActor:scroll-mode property. + * + * Since: 1.12 + */ +void +clutter_scroll_actor_set_scroll_mode (ClutterScrollActor *actor, + ClutterScrollMode mode) +{ + ClutterScrollActorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_SCROLL_ACTOR (actor)); + + priv = actor->priv; + + if (priv->scroll_mode == mode) + return; + + priv->scroll_mode = mode; + + g_object_notify_by_pspec (G_OBJECT (actor), obj_props[PROP_SCROLL_MODE]); +} + +/** + * clutter_scroll_actor_get_scroll_mode: + * @actor: a #ClutterScrollActor + * + * Retrieves the #ClutterScrollActor:scroll-mode property + * + * Return value: the scrolling mode + * + * Since: 1.12 + */ +ClutterScrollMode +clutter_scroll_actor_get_scroll_mode (ClutterScrollActor *actor) +{ + g_return_val_if_fail (CLUTTER_IS_SCROLL_ACTOR (actor), CLUTTER_SCROLL_NONE); + + return actor->priv->scroll_mode; +} + +/** + * clutter_scroll_actor_scroll_to_point: + * @actor: a #ClutterScrollActor + * @point: a #ClutterPoint + * + * Scrolls the contents of @actor so that @point is the new origin + * of the visible area. + * + * The coordinates of @point must be relative to the @actor. + * + * This function will use the currently set easing state of the @actor + * to transition from the current scroll origin to the new one. + * + * Since: 1.12 + */ +void +clutter_scroll_actor_scroll_to_point (ClutterScrollActor *actor, + const ClutterPoint *point) +{ + ClutterScrollActorPrivate *priv; + const ClutterAnimationInfo *info; + + g_return_if_fail (CLUTTER_IS_SCROLL_ACTOR (actor)); + g_return_if_fail (point != NULL); + + priv = actor->priv; + + info = _clutter_actor_get_animation_info (CLUTTER_ACTOR (actor)); + + /* jump to the end if there is no easing state, or if the easing + * state has a duration of 0 msecs + */ + if (info->cur_state == NULL || + info->cur_state->easing_duration == 0) + { + /* ensure that we remove any currently running transition */ + if (priv->transition != NULL) + { + clutter_actor_remove_transition (CLUTTER_ACTOR (actor), + "scroll-to"); + priv->transition = NULL; + } + + clutter_scroll_actor_set_scroll_to_internal (actor, point); + + return; + } + + if (priv->transition == NULL) + { + priv->transition = clutter_property_transition_new ("scroll-to"); + clutter_transition_set_animatable (priv->transition, + CLUTTER_ANIMATABLE (actor)); + clutter_transition_set_remove_on_complete (priv->transition, TRUE); + + /* delay only makes sense if the transition has just been created */ + clutter_timeline_set_delay (CLUTTER_TIMELINE (priv->transition), + info->cur_state->easing_delay); + /* we need this to clear the priv->transition pointer */ + g_object_add_weak_pointer (G_OBJECT (priv->transition), (gpointer *) &priv->transition); + + clutter_actor_add_transition (CLUTTER_ACTOR (actor), + "scroll-to", + priv->transition); + + /* the actor now owns the transition */ + g_object_unref (priv->transition); + } + + /* if a transition already exist, update its bounds */ + clutter_transition_set_from (priv->transition, + CLUTTER_TYPE_POINT, + &priv->scroll_to); + clutter_transition_set_to (priv->transition, + CLUTTER_TYPE_POINT, + point); + + /* always use the current easing state */ + clutter_timeline_set_duration (CLUTTER_TIMELINE (priv->transition), + info->cur_state->easing_duration); + clutter_timeline_set_progress_mode (CLUTTER_TIMELINE (priv->transition), + info->cur_state->easing_mode); + + /* ensure that we start from the beginning */ + clutter_timeline_rewind (CLUTTER_TIMELINE (priv->transition)); + clutter_timeline_start (CLUTTER_TIMELINE (priv->transition)); +} + +/** + * clutter_scroll_actor_scroll_to_rect: + * @actor: a #ClutterScrollActor + * @rect: a #ClutterRect + * + * Scrolls @actor so that @rect is in the visible portion. + * + * Since: 1.12 + */ +void +clutter_scroll_actor_scroll_to_rect (ClutterScrollActor *actor, + const ClutterRect *rect) +{ + ClutterRect n_rect; + + g_return_if_fail (CLUTTER_IS_SCROLL_ACTOR (actor)); + g_return_if_fail (rect != NULL); + + n_rect = *rect; + + /* normalize, so that we have a valid origin */ + clutter_rect_normalize (&n_rect); + + clutter_scroll_actor_scroll_to_point (actor, &n_rect.origin); +} diff --git a/clutter/clutter/clutter-scroll-actor.h b/clutter/clutter/clutter-scroll-actor.h new file mode 100644 index 0000000..be3cbc2 --- /dev/null +++ b/clutter/clutter/clutter-scroll-actor.h @@ -0,0 +1,97 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2012 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 . + */ + +#ifndef __CLUTTER_SCROLL_ACTOR_H__ +#define __CLUTTER_SCROLL_ACTOR_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_SCROLL_ACTOR (clutter_scroll_actor_get_type ()) +#define CLUTTER_SCROLL_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_SCROLL_ACTOR, ClutterScrollActor)) +#define CLUTTER_IS_SCROLL_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_SCROLL_ACTOR)) +#define CLUTTER_SCROLL_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_SCROLL_ACTOR, ClutterScrollActorClass)) +#define CLUTTER_IS_SCROLL_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_SCROLL_ACTOR)) +#define CLUTTER_SCROLL_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_SCROLL_ACTOR, ClutterScrollActorClass)) + +typedef struct _ClutterScrollActorPrivate ClutterScrollActorPrivate; +typedef struct _ClutterScrollActorClass ClutterScrollActorClass; + +/** + * ClutterScrollActor: + * + * The #ClutterScrollActor structure contains only + * private data, and should be accessed using the provided API. + * + * Since: 1.12 + */ +struct _ClutterScrollActor +{ + /*< private >*/ + ClutterActor parent_instance; + + ClutterScrollActorPrivate *priv; +}; + +/** + * ClutterScrollActorClass: + * + * The #ClutterScrollActor structure contains only + * private data. + * + * Since: 1.12 + */ +struct _ClutterScrollActorClass +{ + /*< private >*/ + ClutterActorClass parent_instance; + + gpointer _padding[8]; +}; + +CLUTTER_AVAILABLE_IN_1_12 +GType clutter_scroll_actor_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_12 +ClutterActor * clutter_scroll_actor_new (void); + +CLUTTER_AVAILABLE_IN_1_12 +void clutter_scroll_actor_set_scroll_mode (ClutterScrollActor *actor, + ClutterScrollMode mode); +CLUTTER_AVAILABLE_IN_1_12 +ClutterScrollMode clutter_scroll_actor_get_scroll_mode (ClutterScrollActor *actor); + +CLUTTER_AVAILABLE_IN_1_12 +void clutter_scroll_actor_scroll_to_point (ClutterScrollActor *actor, + const ClutterPoint *point); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_scroll_actor_scroll_to_rect (ClutterScrollActor *actor, + const ClutterRect *rect); + +G_END_DECLS + +#endif /* __CLUTTER_SCROLL_ACTOR_H__ */ diff --git a/clutter/clutter/clutter-settings-private.h b/clutter/clutter/clutter-settings-private.h new file mode 100644 index 0000000..244122c --- /dev/null +++ b/clutter/clutter/clutter-settings-private.h @@ -0,0 +1,20 @@ +#ifndef __CLUTTER_SETTINGS_PRIVATE_H__ +#define __CLUTTER_SETTINGS_PRIVATE_H__ + +#include +#include + +G_BEGIN_DECLS + +void _clutter_settings_set_backend (ClutterSettings *settings, + ClutterBackend *backend); +void _clutter_settings_read_from_key_file (ClutterSettings *settings, + GKeyFile *key_file); + +void clutter_settings_set_property_internal (ClutterSettings *settings, + const char *property, + GValue *value); + +G_END_DECLS + +#endif /* __CLUTTER_SETTINGS_PRIVATE_H__ */ diff --git a/clutter/clutter/clutter-settings.c b/clutter/clutter/clutter-settings.c new file mode 100644 index 0000000..bfe68a5 --- /dev/null +++ b/clutter/clutter/clutter-settings.c @@ -0,0 +1,892 @@ +/** + * SECTION:clutter-settings + * @Title: ClutterSettings + * @Short_Description: Settings configuration + * + * Clutter depends on some settings to perform operations like detecting + * multiple button press events, or font options to render text. + * + * Usually, Clutter will strive to use the platform's settings in order + * to be as much integrated as possible. It is, however, possible to + * change these settings on a per-application basis, by using the + * #ClutterSettings singleton object and setting its properties. It is + * also possible, for toolkit developers, to retrieve the settings from + * the #ClutterSettings properties when implementing new UI elements, + * for instance the default font name. + * + * #ClutterSettings is available since Clutter 1.4 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-settings.h" + +#ifdef HAVE_PANGO_FT2 +/* for pango_fc_font_map_cache_clear() */ +#define PANGO_ENABLE_BACKEND +#include +#endif /* HAVE_PANGO_FT2 */ + +#include "clutter-debug.h" +#include "clutter-settings-private.h" +#include "clutter-stage-private.h" +#include "clutter-private.h" + +#include + +#define DEFAULT_FONT_NAME "Sans 12" + +#define CLUTTER_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_SETTINGS, ClutterSettingsClass)) +#define CLUTTER_IS_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_SETTINGS)) +#define CLUTTER_SETTINGS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_SETTINGS, ClutterSettingsClass)) + +/** + * ClutterSettings: + * + * `ClutterSettings` is an opaque structure whose + * members cannot be directly accessed. + * + * Since: 1.4 + */ +struct _ClutterSettings +{ + GObject parent_instance; + + ClutterBackend *backend; + + gint double_click_time; + gint double_click_distance; + + gint dnd_drag_threshold; + + gdouble resolution; + + gchar *font_name; + gint font_dpi; + + gint xft_hinting; + gint xft_antialias; + gchar *xft_hint_style; + gchar *xft_rgba; + + gint long_press_duration; + + guint last_fontconfig_timestamp; + + guint password_hint_time; + + gint window_scaling_factor; + gint unscaled_font_dpi; + guint fixed_scaling_factor : 1; +}; + +struct _ClutterSettingsClass +{ + GObjectClass parent_class; +}; + +enum +{ + PROP_0, + + PROP_BACKEND, + + PROP_DOUBLE_CLICK_TIME, + PROP_DOUBLE_CLICK_DISTANCE, + + PROP_DND_DRAG_THRESHOLD, + + PROP_FONT_NAME, + + PROP_FONT_ANTIALIAS, + PROP_FONT_DPI, + PROP_FONT_HINTING, + PROP_FONT_HINT_STYLE, + PROP_FONT_RGBA, + + PROP_LONG_PRESS_DURATION, + + PROP_FONTCONFIG_TIMESTAMP, + + PROP_PASSWORD_HINT_TIME, + + PROP_WINDOW_SCALING_FACTOR, + PROP_UNSCALED_FONT_DPI, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +G_DEFINE_TYPE (ClutterSettings, clutter_settings, G_TYPE_OBJECT); + +static inline void +settings_update_font_options (ClutterSettings *self) +{ + cairo_hint_style_t hint_style = CAIRO_HINT_STYLE_NONE; + cairo_antialias_t antialias_mode = CAIRO_ANTIALIAS_GRAY; + cairo_subpixel_order_t subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT; + cairo_font_options_t *options; + + if (self->backend == NULL) + return; + + options = cairo_font_options_create (); + + cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON); + + if (self->xft_hinting >= 0 && + self->xft_hint_style == NULL) + { + hint_style = CAIRO_HINT_STYLE_NONE; + } + else if (self->xft_hint_style != NULL) + { + if (strcmp (self->xft_hint_style, "hintnone") == 0) + hint_style = CAIRO_HINT_STYLE_NONE; + else if (strcmp (self->xft_hint_style, "hintslight") == 0) + hint_style = CAIRO_HINT_STYLE_SLIGHT; + else if (strcmp (self->xft_hint_style, "hintmedium") == 0) + hint_style = CAIRO_HINT_STYLE_MEDIUM; + else if (strcmp (self->xft_hint_style, "hintfull") == 0) + hint_style = CAIRO_HINT_STYLE_FULL; + } + + cairo_font_options_set_hint_style (options, hint_style); + + if (self->xft_rgba) + { + if (strcmp (self->xft_rgba, "rgb") == 0) + subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB; + else if (strcmp (self->xft_rgba, "bgr") == 0) + subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR; + else if (strcmp (self->xft_rgba, "vrgb") == 0) + subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB; + else if (strcmp (self->xft_rgba, "vbgr") == 0) + subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR; + } + + cairo_font_options_set_subpixel_order (options, subpixel_order); + + if (self->xft_antialias >= 0 && !self->xft_antialias) + antialias_mode = CAIRO_ANTIALIAS_NONE; + else if (subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT) + antialias_mode = CAIRO_ANTIALIAS_SUBPIXEL; + else if (self->xft_antialias >= 0) + antialias_mode = CAIRO_ANTIALIAS_GRAY; + + cairo_font_options_set_antialias (options, antialias_mode); + + CLUTTER_NOTE (BACKEND, "New font options:\n" + " - font-name: %s\n" + " - antialias: %d\n" + " - hinting: %d\n" + " - hint-style: %s\n" + " - rgba: %s\n", + self->font_name != NULL ? self->font_name : DEFAULT_FONT_NAME, + self->xft_antialias, + self->xft_hinting, + self->xft_hint_style != NULL ? self->xft_hint_style : "", + self->xft_rgba != NULL ? self->xft_rgba : ""); + + clutter_backend_set_font_options (self->backend, options); + cairo_font_options_destroy (options); +} + +static void +settings_update_font_name (ClutterSettings *self) +{ + CLUTTER_NOTE (BACKEND, "New font-name: %s", self->font_name); + + if (self->backend != NULL) + g_signal_emit_by_name (self->backend, "font-changed"); +} + +static void +settings_update_resolution (ClutterSettings *self) +{ + const char *scale_env = NULL; + + if (self->font_dpi > 0) + self->resolution = (gdouble) self->font_dpi / 1024.0; + else + self->resolution = 96.0; + + scale_env = g_getenv ("GDK_DPI_SCALE"); + if (scale_env != NULL) + { + double scale = g_ascii_strtod (scale_env, NULL); + if (scale != 0 && self->resolution > 0) + self->resolution *= scale; + } + + CLUTTER_NOTE (BACKEND, "New resolution: %.2f (%s)", + self->resolution, + self->unscaled_font_dpi > 0 ? "unscaled" : "scaled"); + + if (self->backend != NULL) + g_signal_emit_by_name (self->backend, "resolution-changed"); +} + +static void +settings_update_fontmap (ClutterSettings *self, + guint stamp) +{ + if (self->backend == NULL) + return; + +#ifdef HAVE_PANGO_FT2 + CLUTTER_NOTE (BACKEND, "Update fontmaps (stamp: %d)", stamp); + + if (self->last_fontconfig_timestamp != stamp) + { + ClutterMainContext *context; + gboolean update_needed = FALSE; + + context = _clutter_context_get_default (); + + /* If there is no font map yet then we don't need to do anything + * because the config for fontconfig will be read when it is + * created */ + if (context->font_map) + { + PangoFontMap *fontmap = PANGO_FONT_MAP (context->font_map); + + if (PANGO_IS_FC_FONT_MAP (fontmap) && + !FcConfigUptoDate (NULL)) + { + pango_fc_font_map_cache_clear (PANGO_FC_FONT_MAP (fontmap)); + + if (FcInitReinitialize ()) + update_needed = TRUE; + } + } + + self->last_fontconfig_timestamp = stamp; + + if (update_needed) + g_signal_emit_by_name (self->backend, "font-changed"); + } +#endif /* HAVE_PANGO_FT2 */ +} + +static void +clutter_settings_finalize (GObject *gobject) +{ + ClutterSettings *self = CLUTTER_SETTINGS (gobject); + + g_free (self->font_name); + g_free (self->xft_hint_style); + g_free (self->xft_rgba); + + G_OBJECT_CLASS (clutter_settings_parent_class)->finalize (gobject); +} + +static void +clutter_settings_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterSettings *self = CLUTTER_SETTINGS (gobject); + + switch (prop_id) + { + case PROP_BACKEND: + self->backend = g_value_get_object (value); + break; + + case PROP_DOUBLE_CLICK_TIME: + self->double_click_time = g_value_get_int (value); + break; + + case PROP_DOUBLE_CLICK_DISTANCE: + self->double_click_distance = g_value_get_int (value); + break; + + case PROP_DND_DRAG_THRESHOLD: + self->dnd_drag_threshold = g_value_get_int (value); + break; + + case PROP_FONT_NAME: + g_free (self->font_name); + self->font_name = g_value_dup_string (value); + settings_update_font_name (self); + break; + + case PROP_FONT_ANTIALIAS: + self->xft_antialias = g_value_get_int (value); + settings_update_font_options (self); + break; + + case PROP_FONT_DPI: + self->font_dpi = g_value_get_int (value); + settings_update_resolution (self); + break; + + case PROP_FONT_HINTING: + self->xft_hinting = g_value_get_int (value); + settings_update_font_options (self); + break; + + case PROP_FONT_HINT_STYLE: + g_free (self->xft_hint_style); + self->xft_hint_style = g_value_dup_string (value); + settings_update_font_options (self); + break; + + case PROP_FONT_RGBA: + g_free (self->xft_rgba); + self->xft_rgba = g_value_dup_string (value); + settings_update_font_options (self); + break; + + case PROP_LONG_PRESS_DURATION: + self->long_press_duration = g_value_get_int (value); + break; + + case PROP_FONTCONFIG_TIMESTAMP: + settings_update_fontmap (self, g_value_get_uint (value)); + break; + + case PROP_PASSWORD_HINT_TIME: + self->password_hint_time = g_value_get_uint (value); + break; + + case PROP_WINDOW_SCALING_FACTOR: + if (!self->fixed_scaling_factor) + { + self->window_scaling_factor = g_value_get_int (value); + self->fixed_scaling_factor = TRUE; + } + break; + + case PROP_UNSCALED_FONT_DPI: + self->font_dpi = g_value_get_int (value); + settings_update_resolution (self); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +void +clutter_settings_set_property_internal (ClutterSettings *self, + const char *property, + GValue *value) +{ + + property = g_intern_string (property); + + if (property == I_("window-scaling-factor") && + self->fixed_scaling_factor) + return; + + g_object_set_property (G_OBJECT (self), property, value); + + if (property == I_("window-scaling-factor")) + self->fixed_scaling_factor = FALSE; +} + +static void +clutter_settings_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterSettings *self = CLUTTER_SETTINGS (gobject); + + switch (prop_id) + { + case PROP_DOUBLE_CLICK_TIME: + g_value_set_int (value, self->double_click_time); + break; + + case PROP_DOUBLE_CLICK_DISTANCE: + g_value_set_int (value, self->double_click_distance); + break; + + case PROP_DND_DRAG_THRESHOLD: + g_value_set_int (value, self->dnd_drag_threshold); + break; + + case PROP_FONT_NAME: + g_value_set_string (value, self->font_name); + break; + + case PROP_FONT_ANTIALIAS: + g_value_set_int (value, self->xft_antialias); + break; + + case PROP_FONT_DPI: + g_value_set_int (value, self->resolution * 1024); + break; + + case PROP_FONT_HINTING: + g_value_set_int (value, self->xft_hinting); + break; + + case PROP_FONT_HINT_STYLE: + g_value_set_string (value, self->xft_hint_style); + break; + + case PROP_FONT_RGBA: + g_value_set_string (value, self->xft_rgba); + break; + + case PROP_LONG_PRESS_DURATION: + g_value_set_int (value, self->long_press_duration); + break; + + case PROP_PASSWORD_HINT_TIME: + g_value_set_uint (value, self->password_hint_time); + break; + + case PROP_WINDOW_SCALING_FACTOR: + g_value_set_int (value, self->window_scaling_factor); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_settings_dispatch_properties_changed (GObject *gobject, + guint n_pspecs, + GParamSpec **pspecs) +{ + ClutterSettings *self = CLUTTER_SETTINGS (gobject); + GObjectClass *klass; + + /* chain up to emit ::notify */ + klass = G_OBJECT_CLASS (clutter_settings_parent_class); + klass->dispatch_properties_changed (gobject, n_pspecs, pspecs); + + /* emit settings-changed just once for multiple properties */ + if (self->backend != NULL) + g_signal_emit_by_name (self->backend, "settings-changed"); +} + +static void +clutter_settings_class_init (ClutterSettingsClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + /** + * ClutterSettings:backend: + * + * A back pointer to the #ClutterBackend + * + * Since: 1.4 + * + * Deprecated: 1.10 + */ + obj_props[PROP_BACKEND] = + g_param_spec_object ("backend", + "Backend", + "A pointer to the backend", + CLUTTER_TYPE_BACKEND, + CLUTTER_PARAM_WRITABLE | + G_PARAM_DEPRECATED | + G_PARAM_CONSTRUCT_ONLY); + + /** + * ClutterSettings:double-click-time: + * + * The time, in milliseconds, that should elapse between button-press + * events in order to increase the click count by 1. + * + * Since: 1.4 + */ + obj_props[PROP_DOUBLE_CLICK_TIME] = + g_param_spec_int ("double-click-time", + P_("Double Click Time"), + P_("The time between clicks necessary to detect a multiple click"), + 0, G_MAXINT, + 250, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterSettings:double-click-distance: + * + * The maximum distance, in pixels, between button-press events that + * determines whether or not to increase the click count by 1. + * + * Since: 1.4 + */ + obj_props[PROP_DOUBLE_CLICK_DISTANCE] = + g_param_spec_int ("double-click-distance", + P_("Double Click Distance"), + P_("The distance between clicks necessary to detect a multiple click"), + 0, G_MAXINT, + 5, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterSettings:dnd-drag-threshold: + * + * The default distance that the cursor of a pointer device + * should travel before a drag operation should start. + * + * Since: 1.8 + */ + obj_props[PROP_DND_DRAG_THRESHOLD] = + g_param_spec_int ("dnd-drag-threshold", + P_("Drag Threshold"), + P_("The distance the cursor should travel before starting to drag"), + 1, G_MAXINT, + 8, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterSettings:font-name: + * + * The default font name that should be used by text actors, as + * a string that can be passed to pango_font_description_from_string(). + * + * Since: 1.4 + */ + obj_props[PROP_FONT_NAME] = + g_param_spec_string ("font-name", + P_("Font Name"), + P_("The description of the default font, as one that could be parsed by Pango"), + NULL, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterSettings:font-antialias: + * + * Whether or not to use antialiasing when rendering text; a value + * of 1 enables it unconditionally; a value of 0 disables it + * unconditionally; and -1 will use the system's default. + * + * Since: 1.4 + */ + obj_props[PROP_FONT_ANTIALIAS] = + g_param_spec_int ("font-antialias", + P_("Font Antialias"), + P_("Whether to use antialiasing (1 to enable, 0 to disable, and -1 to use the default)"), + -1, 1, + -1, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterSettings:font-dpi: + * + * The DPI used when rendering text, as a value of 1024 * dots/inch. + * + * If set to -1, the system's default will be used instead + * + * Since: 1.4 + */ + obj_props[PROP_FONT_DPI] = + g_param_spec_int ("font-dpi", + P_("Font DPI"), + P_("The resolution of the font, in 1024 * dots/inch, or -1 to use the default"), + -1, 1024 * 1024, + -1, + CLUTTER_PARAM_READWRITE); + + obj_props[PROP_UNSCALED_FONT_DPI] = + g_param_spec_int ("unscaled-font-dpi", + P_("Font DPI"), + P_("The resolution of the font, in 1024 * dots/inch, or -1 to use the default"), + -1, 1024 * 1024, + -1, + CLUTTER_PARAM_WRITABLE); + + /** + * ClutterSettings:font-hinting: + * + * Whether or not to use hinting when rendering text; a value of 1 + * unconditionally enables it; a value of 0 unconditionally disables + * it; and a value of -1 will use the system's default. + * + * Since: 1.4 + */ + obj_props[PROP_FONT_HINTING] = + g_param_spec_int ("font-hinting", + P_("Font Hinting"), + P_("Whether to use hinting (1 to enable, 0 to disable and -1 to use the default)"), + -1, 1, + -1, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterSettings:font-hint-style: + * + * The style of the hinting used when rendering text. Valid values + * are: + * + * - hintnone + * - hintslight + * - hintmedium + * - hintfull + * + * Since: 1.4 + */ + obj_props[PROP_FONT_HINT_STYLE] = + g_param_spec_string ("font-hint-style", + P_("Font Hint Style"), + P_("The style of hinting (hintnone, hintslight, hintmedium, hintfull)"), + NULL, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterSettings:font-subpixel-order: + * + * The type of sub-pixel antialiasing used when rendering text. Valid + * values are: + * + * - none + * - rgb + * - bgr + * - vrgb + * - vbgr + * + * Since: 1.4 + */ + obj_props[PROP_FONT_RGBA] = + g_param_spec_string ("font-subpixel-order", + P_("Font Subpixel Order"), + P_("The type of subpixel antialiasing (none, rgb, bgr, vrgb, vbgr)"), + NULL, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterSettings:long-press-duration: + * + * Sets the minimum duration for a press to be recognized as a long press + * gesture. The duration is expressed in milliseconds. + * + * See also #ClutterClickAction:long-press-duration. + * + * Since: 1.8 + */ + obj_props[PROP_LONG_PRESS_DURATION] = + g_param_spec_int ("long-press-duration", + P_("Long Press Duration"), + P_("The minimum duration for a long press gesture to be recognized"), + 0, G_MAXINT, + 500, + CLUTTER_PARAM_READWRITE); + + obj_props[PROP_WINDOW_SCALING_FACTOR] = + g_param_spec_int ("window-scaling-factor", + P_("Window Scaling Factor"), + P_("The scaling factor to be applied to windows"), + 1, G_MAXINT, + 1, + CLUTTER_PARAM_READWRITE); + + obj_props[PROP_FONTCONFIG_TIMESTAMP] = + g_param_spec_uint ("fontconfig-timestamp", + P_("Fontconfig configuration timestamp"), + P_("Timestamp of the current fontconfig configuration"), + 0, G_MAXUINT, + 0, + CLUTTER_PARAM_WRITABLE); + + /** + * ClutterText:password-hint-time: + * + * How long should Clutter show the last input character in editable + * ClutterText actors. The value is in milliseconds. A value of 0 + * disables showing the password hint. 600 is a good value for + * enabling the hint. + * + * Since: 1.10 + */ + obj_props[PROP_PASSWORD_HINT_TIME] = + g_param_spec_uint ("password-hint-time", + P_("Password Hint Time"), + P_("How long to show the last input character in hidden entries"), + 0, G_MAXUINT, + 0, + CLUTTER_PARAM_READWRITE); + + gobject_class->set_property = clutter_settings_set_property; + gobject_class->get_property = clutter_settings_get_property; + gobject_class->dispatch_properties_changed = + clutter_settings_dispatch_properties_changed; + gobject_class->finalize = clutter_settings_finalize; + g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); +} + +static void +clutter_settings_init (ClutterSettings *self) +{ + const char *scale_str; + + self->resolution = -1.0; + + self->font_dpi = -1; + self->unscaled_font_dpi = -1; + + self->double_click_time = 250; + self->double_click_distance = 5; + + self->dnd_drag_threshold = 8; + + self->font_name = g_strdup (DEFAULT_FONT_NAME); + + self->xft_antialias = -1; + self->xft_hinting = -1; + self->xft_hint_style = NULL; + self->xft_rgba = NULL; + + self->long_press_duration = 500; + + /* if the scaling factor was set by the environment we ignore + * any explicit setting + */ + scale_str = g_getenv ("CLUTTER_SCALE"); + if (scale_str != NULL) + { + self->window_scaling_factor = atol (scale_str); + self->fixed_scaling_factor = TRUE; + } + else + self->window_scaling_factor = 1; +} + +/** + * clutter_settings_get_default: + * + * Retrieves the singleton instance of #ClutterSettings + * + * Return value: (transfer none): the instance of #ClutterSettings. The + * returned object is owned by Clutter and it should not be unreferenced + * directly + * + * Since: 1.4 + */ +ClutterSettings * +clutter_settings_get_default (void) +{ + static ClutterSettings *settings = NULL; + + if (G_UNLIKELY (settings == NULL)) + settings = g_object_new (CLUTTER_TYPE_SETTINGS, NULL); + + return settings; +} + +void +_clutter_settings_set_backend (ClutterSettings *settings, + ClutterBackend *backend) +{ + g_assert (CLUTTER_IS_SETTINGS (settings)); + g_assert (CLUTTER_IS_BACKEND (backend)); + + settings->backend = backend; +} + +#define SETTINGS_GROUP "Settings" + +void +_clutter_settings_read_from_key_file (ClutterSettings *settings, + GKeyFile *keyfile) +{ + GObjectClass *settings_class; + GObject *settings_obj; + GParamSpec **pspecs; + guint n_pspecs, i; + + if (!g_key_file_has_group (keyfile, SETTINGS_GROUP)) + return; + + settings_obj = G_OBJECT (settings); + settings_class = G_OBJECT_GET_CLASS (settings); + pspecs = g_object_class_list_properties (settings_class, &n_pspecs); + + for (i = 0; i < n_pspecs; i++) + { + GParamSpec *pspec = pspecs[i]; + const gchar *p_name = pspec->name; + GType p_type = G_TYPE_FUNDAMENTAL (pspec->value_type); + GValue value = G_VALUE_INIT; + GError *key_error = NULL; + + g_value_init (&value, p_type); + + switch (p_type) + { + case G_TYPE_INT: + case G_TYPE_UINT: + { + gint val; + + val = g_key_file_get_integer (keyfile, + SETTINGS_GROUP, p_name, + &key_error); + if (p_type == G_TYPE_INT) + g_value_set_int (&value, val); + else + g_value_set_uint (&value, val); + } + break; + + case G_TYPE_BOOLEAN: + { + gboolean val; + + val = g_key_file_get_boolean (keyfile, + SETTINGS_GROUP, p_name, + &key_error); + g_value_set_boolean (&value, val); + } + break; + + case G_TYPE_FLOAT: + case G_TYPE_DOUBLE: + { + gdouble val; + + val = g_key_file_get_double (keyfile, + SETTINGS_GROUP, p_name, + &key_error); + if (p_type == G_TYPE_FLOAT) + g_value_set_float (&value, val); + else + g_value_set_double (&value, val); + } + break; + + case G_TYPE_STRING: + { + gchar *val; + + val = g_key_file_get_string (keyfile, + SETTINGS_GROUP, p_name, + &key_error); + g_value_take_string (&value, val); + } + break; + } + + if (key_error != NULL && + key_error->domain != G_KEY_FILE_ERROR && + key_error->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND) + { + g_critical ("Unable to read the value for setting '%s': %s", + p_name, + key_error->message); + } + + if (key_error == NULL) + g_object_set_property (settings_obj, p_name, &value); + else + g_error_free (key_error); + + g_value_unset (&value); + } + + g_free (pspecs); +} diff --git a/clutter/clutter/clutter-settings.h b/clutter/clutter/clutter-settings.h new file mode 100644 index 0000000..7c9fe42 --- /dev/null +++ b/clutter/clutter/clutter-settings.h @@ -0,0 +1,27 @@ +#ifndef __CLUTTER_SETTINGS_H__ +#define __CLUTTER_SETTINGS_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_SETTINGS (clutter_settings_get_type ()) +#define CLUTTER_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_SETTINGS, ClutterSettings)) +#define CLUTTER_IS_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_SETTINGS)) + +typedef struct _ClutterSettings ClutterSettings; +typedef struct _ClutterSettingsClass ClutterSettingsClass; + +CLUTTER_AVAILABLE_IN_ALL +GType clutter_settings_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_ALL +ClutterSettings *clutter_settings_get_default (void); + +G_END_DECLS + +#endif /* __CLUTTER_SETTINGS_H__ */ diff --git a/clutter/clutter/clutter-shader-effect.c b/clutter/clutter/clutter-shader-effect.c new file mode 100644 index 0000000..ee54485 --- /dev/null +++ b/clutter/clutter/clutter-shader-effect.c @@ -0,0 +1,923 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-shader-effect + * @short_description: Base class for shader effects + * @See_Also: #ClutterEffect, #ClutterOffscreenEffect + * + * #ClutterShaderEffect is a class that implements all the plumbing for + * creating #ClutterEffects using GLSL shaders. + * + * #ClutterShaderEffect creates an offscreen buffer and then applies the + * GLSL shader (after checking whether the compilation and linking were + * successfull) to the buffer before painting it on screen. + * + * #ClutterShaderEffect is available since Clutter 1.4 + * + * ## Implementing a ClutterShaderEffect + * + * Creating a sub-class of #ClutterShaderEffect requires the + * overriding of the #ClutterOffscreenEffectClass.paint_target() virtual + * function from the #ClutterOffscreenEffect class. It is also convenient + * to implement the #ClutterShaderEffectClass.get_static_shader_source() + * virtual function in case you are planning to create more than one + * instance of the effect. + * + * The #ClutterShaderEffectClass.get_static_shader_source() + * function should return a copy of the shader source to use. This + * function is only called once per subclass of #ClutterShaderEffect + * regardless of how many instances of the effect are created. The + * source for the shader is typically stored in a static const + * string which is returned from this function via + * g_strdup(). + * + * The #ClutterOffscreenEffectClass.paint_target() should set the + * shader's uniforms if any. This is done by calling + * clutter_shader_effect_set_uniform_value() or + * clutter_shader_effect_set_uniform(). The sub-class should then + * chain up to the #ClutterShaderEffect implementation. + * + * ## Setting uniforms on a ClutterShaderEffect + * + * The example below shows a typical implementation of the + * #ClutterShaderEffectClass.get_static_shader_source() and + * #ClutterOffscreenEffectClass.paint_target() virtual functions + * for a #ClutterShaderEffect subclass. + * + * |[ + * static gchar * + * my_effect_get_static_shader_source (ClutterShaderEffect *effect) + * { + * // shader_source is set elsewhere + * return g_strdup (shader_source); + * } + * + * static gboolean + * my_effect_paint_target (ClutterOffscreenEffect *effect) + * { + * MyEffect *self = MY_EFFECT (effect); + * ClutterShaderEffect *shader = CLUTTER_SHADER_EFFECT (effect); + * ClutterEffectClass *parent_class; + * gfloat component_r, component_g, component_b; + * + * // the "tex" uniform is declared in the shader as: + * // + * // uniform int tex; + * // + * // and it is passed a constant value of 0 + * clutter_shader_effect_set_uniform (shader, "tex", G_TYPE_INT, 1, 0); + * + * // the "component" uniform is declared in the shader as: + * // + * // uniform vec3 component; + * // + * // and it's defined to contain the normalized components + * // of a #ClutterColor + * component_r = self->color.red / 255.0f; + * component_g = self->color.green / 255.0f; + * component_b = self->color.blue / 255.0f; + * clutter_shader_effect_set_uniform (shader, "component", + * G_TYPE_FLOAT, 3, + * component_r, + * component_g, + * component_b); + * + * // chain up to the parent's implementation + * parent_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (my_effect_parent_class); + * return parent_class->paint_target (effect); + * } + * ]| + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "cogl/cogl.h" + +#include "clutter-shader-effect.h" + +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-feature.h" +#include "clutter-private.h" +#include "clutter-shader-types.h" + +typedef struct _ShaderUniform +{ + gchar *name; + GType type; + GValue value; + int location; +} ShaderUniform; + +struct _ClutterShaderEffectPrivate +{ + ClutterActor *actor; + + ClutterShaderType shader_type; + + CoglHandle program; + CoglHandle shader; + + GHashTable *uniforms; +}; + +typedef struct _ClutterShaderEffectClassPrivate +{ + /* These are the per-class pre-compiled shader and program which is + used when the class implements get_static_shader_source without + calling set_shader_source. They will be shared by all instances + of this class */ + CoglHandle program; + CoglHandle shader; +} ClutterShaderEffectClassPrivate; + +enum +{ + PROP_0, + + PROP_SHADER_TYPE, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +G_DEFINE_TYPE_WITH_CODE (ClutterShaderEffect, + clutter_shader_effect, + CLUTTER_TYPE_OFFSCREEN_EFFECT, + G_ADD_PRIVATE (ClutterShaderEffect) + g_type_add_class_private (g_define_type_id, + sizeof (ClutterShaderEffectClassPrivate))) + +static inline void +clutter_shader_effect_clear (ClutterShaderEffect *self, + gboolean reset_uniforms) +{ + ClutterShaderEffectPrivate *priv = self->priv; + + if (priv->shader != COGL_INVALID_HANDLE) + { + cogl_handle_unref (priv->shader); + + priv->shader = COGL_INVALID_HANDLE; + } + + if (priv->program != COGL_INVALID_HANDLE) + { + cogl_handle_unref (priv->program); + + priv->program = COGL_INVALID_HANDLE; + } + + if (reset_uniforms && priv->uniforms != NULL) + { + g_hash_table_destroy (priv->uniforms); + priv->uniforms = NULL; + } + + priv->actor = NULL; +} + +static void +clutter_shader_effect_update_uniforms (ClutterShaderEffect *effect) +{ + ClutterShaderEffectPrivate *priv = effect->priv; + GHashTableIter iter; + gpointer key, value; + gsize size; + + if (priv->program == COGL_INVALID_HANDLE) + return; + + if (priv->uniforms == NULL) + return; + + key = value = NULL; + g_hash_table_iter_init (&iter, priv->uniforms); + while (g_hash_table_iter_next (&iter, &key, &value)) + { + ShaderUniform *uniform = value; + + if (uniform->location == -1) + uniform->location = cogl_program_get_uniform_location (priv->program, + uniform->name); + + if (CLUTTER_VALUE_HOLDS_SHADER_FLOAT (&uniform->value)) + { + const float *floats; + + floats = clutter_value_get_shader_float (&uniform->value, &size); + cogl_program_set_uniform_float (priv->program, uniform->location, + size, 1, + floats); + } + else if (CLUTTER_VALUE_HOLDS_SHADER_INT (&uniform->value)) + { + const int *ints; + + ints = clutter_value_get_shader_int (&uniform->value, &size); + cogl_program_set_uniform_int (priv->program, uniform->location, + size, 1, + ints); + } + else if (CLUTTER_VALUE_HOLDS_SHADER_MATRIX (&uniform->value)) + { + const float *matrix; + + matrix = clutter_value_get_shader_matrix (&uniform->value, &size); + cogl_program_set_uniform_matrix (priv->program, uniform->location, + size, 1, + FALSE, + matrix); + } + else if (G_VALUE_HOLDS_FLOAT (&uniform->value)) + { + const float float_val = g_value_get_float (&uniform->value); + + cogl_program_set_uniform_float (priv->program, uniform->location, + 1, 1, + &float_val); + } + else if (G_VALUE_HOLDS_DOUBLE (&uniform->value)) + { + const float float_val = + (float) g_value_get_double (&uniform->value); + + cogl_program_set_uniform_float (priv->program, uniform->location, + 1, 1, + &float_val); + } + else if (G_VALUE_HOLDS_INT (&uniform->value)) + { + const int int_val = g_value_get_int (&uniform->value); + + cogl_program_set_uniform_int (priv->program, uniform->location, + 1, 1, + &int_val); + } + else + g_warning ("Invalid uniform of type '%s' for name '%s'", + g_type_name (G_VALUE_TYPE (&uniform->value)), + uniform->name); + } +} + +static void +clutter_shader_effect_set_actor (ClutterActorMeta *meta, + ClutterActor *actor) +{ + ClutterShaderEffect *self = CLUTTER_SHADER_EFFECT (meta); + ClutterShaderEffectPrivate *priv = self->priv; + ClutterActorMetaClass *parent; + + if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) + { + /* if we don't have support for GLSL shaders then we + * forcibly disable the ActorMeta + */ + g_warning ("Unable to use the ShaderEffect: the graphics hardware " + "or the current GL driver does not implement support " + "for the GLSL shading language."); + clutter_actor_meta_set_enabled (meta, FALSE); + return; + } + + parent = CLUTTER_ACTOR_META_CLASS (clutter_shader_effect_parent_class); + parent->set_actor (meta, actor); + + /* we keep a back pointer here */ + priv->actor = clutter_actor_meta_get_actor (meta); + if (priv->actor == NULL) + return; + + CLUTTER_NOTE (SHADER, "Preparing shader effect of type '%s'", + G_OBJECT_TYPE_NAME (meta)); +} + +static CoglHandle +clutter_shader_effect_create_shader (ClutterShaderEffect *self) +{ + ClutterShaderEffectPrivate *priv = self->priv; + + switch (priv->shader_type) + { + case CLUTTER_FRAGMENT_SHADER: + return cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT); + break; + + case CLUTTER_VERTEX_SHADER: + return cogl_create_shader (COGL_SHADER_TYPE_VERTEX); + break; + + default: + g_assert_not_reached (); + } +} + +static void +clutter_shader_effect_try_static_source (ClutterShaderEffect *self) +{ + ClutterShaderEffectPrivate *priv = self->priv; + ClutterShaderEffectClass *shader_effect_class = + CLUTTER_SHADER_EFFECT_GET_CLASS (self); + + if (shader_effect_class->get_static_shader_source != NULL) + { + ClutterShaderEffectClassPrivate *class_priv; + + class_priv = + G_TYPE_CLASS_GET_PRIVATE (shader_effect_class, + CLUTTER_TYPE_SHADER_EFFECT, + ClutterShaderEffectClassPrivate); + + if (class_priv->shader == COGL_INVALID_HANDLE) + { + gchar *source; + + class_priv->shader = clutter_shader_effect_create_shader (self); + + source = shader_effect_class->get_static_shader_source (self); + + cogl_shader_source (class_priv->shader, source); + + g_free (source); + + CLUTTER_NOTE (SHADER, "Compiling shader effect"); + + cogl_shader_compile (class_priv->shader); + + if (cogl_shader_is_compiled (class_priv->shader)) + { + class_priv->program = cogl_create_program (); + + cogl_program_attach_shader (class_priv->program, + class_priv->shader); + + cogl_program_link (class_priv->program); + } + else + { + gchar *log_buf = cogl_shader_get_info_log (class_priv->shader); + + g_warning (G_STRLOC ": Unable to compile the GLSL shader: %s", log_buf); + g_free (log_buf); + } + } + + priv->shader = cogl_handle_ref (class_priv->shader); + + if (class_priv->program != COGL_INVALID_HANDLE) + priv->program = cogl_handle_ref (class_priv->program); + } +} + +static void +clutter_shader_effect_paint_target (ClutterOffscreenEffect *effect) +{ + ClutterShaderEffect *self = CLUTTER_SHADER_EFFECT (effect); + ClutterShaderEffectPrivate *priv = self->priv; + ClutterOffscreenEffectClass *parent; + CoglHandle material; + + /* If the source hasn't been set then we'll try to get it from the + static source instead */ + if (priv->shader == COGL_INVALID_HANDLE) + clutter_shader_effect_try_static_source (self); + + /* we haven't been prepared or we don't have support for + * GLSL shaders in Clutter + */ + if (priv->program == COGL_INVALID_HANDLE) + goto out; + + CLUTTER_NOTE (SHADER, "Applying the shader effect of type '%s'", + G_OBJECT_TYPE_NAME (effect)); + + clutter_shader_effect_update_uniforms (CLUTTER_SHADER_EFFECT (effect)); + + /* associate the program to the offscreen target material */ + material = clutter_offscreen_effect_get_target (effect); + cogl_pipeline_set_user_program (material, priv->program); + +out: + /* paint the offscreen buffer */ + parent = CLUTTER_OFFSCREEN_EFFECT_CLASS (clutter_shader_effect_parent_class); + parent->paint_target (effect); + +} + +static void +clutter_shader_effect_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterShaderEffectPrivate *priv = CLUTTER_SHADER_EFFECT (gobject)->priv; + + switch (prop_id) + { + case PROP_SHADER_TYPE: + priv->shader_type = g_value_get_enum (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_shader_effect_finalize (GObject *gobject) +{ + ClutterShaderEffect *effect = CLUTTER_SHADER_EFFECT (gobject); + + clutter_shader_effect_clear (effect, TRUE); + + G_OBJECT_CLASS (clutter_shader_effect_parent_class)->finalize (gobject); +} + +static void +clutter_shader_effect_class_init (ClutterShaderEffectClass *klass) +{ + ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterOffscreenEffectClass *offscreen_class; + + offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass); + + /** + * ClutterShaderEffect:shader-type: + * + * The type of shader that is used by the effect. This property + * should be set by the constructor of #ClutterShaderEffect + * sub-classes. + * + * Since: 1.4 + */ + obj_props[PROP_SHADER_TYPE] = + g_param_spec_enum ("shader-type", + P_("Shader Type"), + P_("The type of shader used"), + CLUTTER_TYPE_SHADER_TYPE, + CLUTTER_FRAGMENT_SHADER, + CLUTTER_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY); + + gobject_class->set_property = clutter_shader_effect_set_property; + gobject_class->finalize = clutter_shader_effect_finalize; + g_object_class_install_properties (gobject_class, + PROP_LAST, + obj_props); + + meta_class->set_actor = clutter_shader_effect_set_actor; + + offscreen_class->paint_target = clutter_shader_effect_paint_target; +} + +static void +clutter_shader_effect_init (ClutterShaderEffect *effect) +{ + effect->priv = clutter_shader_effect_get_instance_private (effect); +} + +/** + * clutter_shader_effect_new: + * @shader_type: the type of the shader, either %CLUTTER_FRAGMENT_SHADER, + * or %CLUTTER_VERTEX_SHADER + * + * Creates a new #ClutterShaderEffect, to be applied to an actor using + * clutter_actor_add_effect(). + * + * The effect will be empty until clutter_shader_effect_set_shader_source() + * is called. + * + * Return value: the newly created #ClutterShaderEffect. + * Use g_object_unref() when done. + * + * Since: 1.8 + */ +ClutterEffect * +clutter_shader_effect_new (ClutterShaderType shader_type) +{ + return g_object_new (CLUTTER_TYPE_SHADER_EFFECT, + "shader-type", shader_type, + NULL); +} + +/** + * clutter_shader_effect_get_shader: + * @effect: a #ClutterShaderEffect + * + * Retrieves a pointer to the shader's handle + * + * Return value: (transfer none): a pointer to the shader's handle, + * or %COGL_INVALID_HANDLE + * + * Since: 1.4 + */ +CoglHandle +clutter_shader_effect_get_shader (ClutterShaderEffect *effect) +{ + g_return_val_if_fail (CLUTTER_IS_SHADER_EFFECT (effect), + COGL_INVALID_HANDLE); + + return effect->priv->shader; +} + +/** + * clutter_shader_effect_get_program: + * @effect: a #ClutterShaderEffect + * + * Retrieves a pointer to the program's handle + * + * Return value: (transfer none): a pointer to the program's handle, + * or %COGL_INVALID_HANDLE + * + * Since: 1.4 + */ +CoglHandle +clutter_shader_effect_get_program (ClutterShaderEffect *effect) +{ + g_return_val_if_fail (CLUTTER_IS_SHADER_EFFECT (effect), + COGL_INVALID_HANDLE); + + return effect->priv->program; +} + +static void +shader_uniform_free (gpointer data) +{ + if (data != NULL) + { + ShaderUniform *uniform = data; + + g_value_unset (&uniform->value); + g_free (uniform->name); + + g_slice_free (ShaderUniform, uniform); + } +} + +static ShaderUniform * +shader_uniform_new (const gchar *name, + const GValue *value) +{ + ShaderUniform *retval; + + retval = g_slice_new0 (ShaderUniform); + retval->name = g_strdup (name); + retval->type = G_VALUE_TYPE (value); + retval->location = -1; + + g_value_init (&retval->value, retval->type); + g_value_copy (value, &retval->value); + + return retval; +} + +static void +shader_uniform_update (ShaderUniform *uniform, + const GValue *value) +{ + g_value_unset (&uniform->value); + + g_value_init (&uniform->value, G_VALUE_TYPE (value)); + g_value_copy (value, &uniform->value); +} + +static inline void +clutter_shader_effect_add_uniform (ClutterShaderEffect *effect, + const gchar *name, + const GValue *value) +{ + ClutterShaderEffectPrivate *priv = effect->priv; + ShaderUniform *uniform; + + if (priv->uniforms == NULL) + { + priv->uniforms = g_hash_table_new_full (g_str_hash, g_str_equal, + NULL, + shader_uniform_free); + } + + uniform = g_hash_table_lookup (priv->uniforms, name); + if (uniform == NULL) + { + uniform = shader_uniform_new (name, value); + g_hash_table_insert (priv->uniforms, uniform->name, uniform); + } + else + shader_uniform_update (uniform, value); + + if (priv->actor != NULL && !CLUTTER_ACTOR_IN_PAINT (priv->actor)) + clutter_effect_queue_repaint (CLUTTER_EFFECT (effect)); +} + +/** + * clutter_shader_effect_set_uniform_value: + * @effect: a #ClutterShaderEffect + * @name: the name of the uniform to set + * @value: a #GValue with the value of the uniform to set + * + * Sets @value as the payload for the uniform @name inside the shader + * effect + * + * The #GType of the @value must be one of: %G_TYPE_INT, for a single + * integer value; %G_TYPE_FLOAT, for a single floating point value; + * %CLUTTER_TYPE_SHADER_INT, for an array of integer values; + * %CLUTTER_TYPE_SHADER_FLOAT, for an array of floating point values; + * and %CLUTTER_TYPE_SHADER_MATRIX, for a matrix of floating point + * values. It also accepts %G_TYPE_DOUBLE for compatibility with other + * languages than C. + * + * Since: 1.4 + */ +void +clutter_shader_effect_set_uniform_value (ClutterShaderEffect *effect, + const gchar *name, + const GValue *value) +{ + g_return_if_fail (CLUTTER_IS_SHADER_EFFECT (effect)); + g_return_if_fail (name != NULL); + g_return_if_fail (value != NULL); + + clutter_shader_effect_add_uniform (effect, name, value); +} + +static void +clutter_shader_effect_set_uniform_valist (ClutterShaderEffect *effect, + const gchar *name, + GType value_type, + gsize n_values, + va_list *args) +{ + GValue value = G_VALUE_INIT; + + if (value_type == CLUTTER_TYPE_SHADER_INT) + { + gint *int_values = va_arg (*args, gint*); + + g_value_init (&value, CLUTTER_TYPE_SHADER_INT); + clutter_value_set_shader_int (&value, n_values, int_values); + + goto add_uniform; + } + + if (value_type == CLUTTER_TYPE_SHADER_FLOAT) + { + gfloat *float_values = va_arg (*args, gfloat*); + + g_value_init (&value, CLUTTER_TYPE_SHADER_FLOAT); + clutter_value_set_shader_float (&value, n_values, float_values); + + goto add_uniform; + } + + if (value_type == CLUTTER_TYPE_SHADER_MATRIX) + { + gfloat *float_values = va_arg (*args, gfloat*); + + g_value_init (&value, CLUTTER_TYPE_SHADER_MATRIX); + clutter_value_set_shader_matrix (&value, n_values, float_values); + + goto add_uniform; + } + + if (value_type == G_TYPE_INT) + { + g_return_if_fail (n_values <= 4); + + /* if we only have one value we can go through the fast path + * of using G_TYPE_INT, otherwise we create a vector of integers + * from the passed values + */ + if (n_values == 1) + { + gint int_val = va_arg (*args, gint); + + g_value_init (&value, G_TYPE_INT); + g_value_set_int (&value, int_val); + } + else + { + gint *int_values = g_new (gint, n_values); + gint i; + + for (i = 0; i < n_values; i++) + int_values[i] = va_arg (*args, gint); + + g_value_init (&value, CLUTTER_TYPE_SHADER_INT); + clutter_value_set_shader_int (&value, n_values, int_values); + + g_free (int_values); + } + + goto add_uniform; + } + + if (value_type == G_TYPE_FLOAT) + { + g_return_if_fail (n_values <= 4); + + /* if we only have one value we can go through the fast path + * of using G_TYPE_FLOAT, otherwise we create a vector of floats + * from the passed values + */ + if (n_values == 1) + { + gfloat float_val = (gfloat) va_arg (*args, gdouble); + + g_value_init (&value, G_TYPE_FLOAT); + g_value_set_float (&value, float_val); + } + else + { + gfloat *float_values = g_new (gfloat, n_values); + gint i; + + for (i = 0; i < n_values; i++) + float_values[i] = (gfloat) va_arg (*args, double); + + g_value_init (&value, CLUTTER_TYPE_SHADER_FLOAT); + clutter_value_set_shader_float (&value, n_values, float_values); + + g_free (float_values); + } + + goto add_uniform; + } + + g_warning ("Unrecognized type '%s' (values: %d) for uniform name '%s'", + g_type_name (value_type), + (int) n_values, + name); + return; + +add_uniform: + clutter_shader_effect_add_uniform (effect, name, &value); + g_value_unset (&value); +} + +/** + * clutter_shader_effect_set_uniform: + * @effect: a #ClutterShaderEffect + * @name: the name of the uniform to set + * @gtype: the type of the uniform to set + * @n_values: the number of values + * @...: a list of values + * + * Sets a list of values as the payload for the uniform @name inside + * the shader effect + * + * The @gtype must be one of: %G_TYPE_INT, for 1 or more integer values; + * %G_TYPE_FLOAT, for 1 or more floating point values; + * %CLUTTER_TYPE_SHADER_INT, for a pointer to an array of integer values; + * %CLUTTER_TYPE_SHADER_FLOAT, for a pointer to an array of floating point + * values; and %CLUTTER_TYPE_SHADER_MATRIX, for a pointer to an array of + * floating point values mapping a matrix + * + * The number of values interepreted is defined by the @n_value + * argument, and by the @gtype argument. For instance, a uniform named + * "sampler0" and containing a single integer value is set using: + * + * |[ + * clutter_shader_effect_set_uniform (effect, "sampler0", + * G_TYPE_INT, 1, + * 0); + * ]| + * + * While a uniform named "components" and containing a 3-elements vector + * of floating point values (a "vec3") can be set using: + * + * |[ + * gfloat component_r, component_g, component_b; + * + * clutter_shader_effect_set_uniform (effect, "components", + * G_TYPE_FLOAT, 3, + * component_r, + * component_g, + * component_b); + * ]| + * + * or can be set using: + * + * |[ + * gfloat component_vec[3]; + * + * clutter_shader_effect_set_uniform (effect, "components", + * CLUTTER_TYPE_SHADER_FLOAT, 3, + * component_vec); + * ]| + * + * Finally, a uniform named "map" and containing a matrix can be set using: + * + * |[ + * clutter_shader_effect_set_uniform (effect, "map", + * CLUTTER_TYPE_SHADER_MATRIX, 1, + * cogl_matrix_get_array (&matrix)); + * ]| + * + * Since: 1.4 + */ +void +clutter_shader_effect_set_uniform (ClutterShaderEffect *effect, + const gchar *name, + GType gtype, + gsize n_values, + ...) +{ + va_list args; + + g_return_if_fail (CLUTTER_IS_SHADER_EFFECT (effect)); + g_return_if_fail (name != NULL); + g_return_if_fail (gtype != G_TYPE_INVALID); + g_return_if_fail (n_values > 0); + + va_start (args, n_values); + clutter_shader_effect_set_uniform_valist (effect, name, + gtype, + n_values, + &args); + va_end (args); +} + +/** + * clutter_shader_effect_set_shader_source: + * @effect: a #ClutterShaderEffect + * @source: the source of a GLSL shader + * + * Sets the source of the GLSL shader used by @effect + * + * This function should only be called by implementations of + * the #ClutterShaderEffect class, and not by application code. + * + * This function can only be called once; subsequent calls will + * yield no result. + * + * Return value: %TRUE if the source was set + * + * Since: 1.4 + */ +gboolean +clutter_shader_effect_set_shader_source (ClutterShaderEffect *effect, + const gchar *source) +{ + ClutterShaderEffectPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_SHADER_EFFECT (effect), FALSE); + g_return_val_if_fail (source != NULL && *source != '\0', FALSE); + + priv = effect->priv; + + if (priv->shader != COGL_INVALID_HANDLE) + return TRUE; + + priv->shader = clutter_shader_effect_create_shader (effect); + + cogl_shader_source (priv->shader, source); + + CLUTTER_NOTE (SHADER, "Compiling shader effect"); + + cogl_shader_compile (priv->shader); + + if (cogl_shader_is_compiled (priv->shader)) + { + priv->program = cogl_create_program (); + + cogl_program_attach_shader (priv->program, priv->shader); + + cogl_program_link (priv->program); + } + else + { + gchar *log_buf = cogl_shader_get_info_log (priv->shader); + + g_warning (G_STRLOC ": Unable to compile the GLSL shader: %s", log_buf); + g_free (log_buf); + } + + return TRUE; +} diff --git a/clutter/clutter/clutter-shader-effect.h b/clutter/clutter/clutter-shader-effect.h new file mode 100644 index 0000000..fc9775e --- /dev/null +++ b/clutter/clutter/clutter-shader-effect.h @@ -0,0 +1,121 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_SHADER_EFFECT_H__ +#define __CLUTTER_SHADER_EFFECT_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_SHADER_EFFECT (clutter_shader_effect_get_type ()) +#define CLUTTER_SHADER_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_SHADER_EFFECT, ClutterShaderEffect)) +#define CLUTTER_IS_SHADER_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_SHADER_EFFECT)) +#define CLUTTER_SHADER_EFFECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_SHADER_EFFECT, ClutterShaderEffectClass)) +#define CLUTTER_IS_SHADER_EFFECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_SHADER_EFFECT)) +#define CLUTTER_SHADER_EFFECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_SHADER_EFFECT, ClutterShaderEffectClass)) + +typedef struct _ClutterShaderEffect ClutterShaderEffect; +typedef struct _ClutterShaderEffectPrivate ClutterShaderEffectPrivate; +typedef struct _ClutterShaderEffectClass ClutterShaderEffectClass; + +/** + * ClutterShaderEffect: + * + * The #ClutterShaderEffect structure contains + * only private data and should be accessed using the provided API + * + * Since: 1.4 + */ +struct _ClutterShaderEffect +{ + /*< private >*/ + ClutterOffscreenEffect parent_instance; + + ClutterShaderEffectPrivate *priv; +}; + +/** + * ClutterShaderEffectClass: + * @get_static_shader_source: Returns the GLSL source code to use for + * instances of this shader effect. Note that this function is only + * called once per subclass of #ClutterShaderEffect regardless of how + * many instances are used. It is expected that subclasses will return + * a copy of a static string from this function. + * + * The #ClutterShaderEffectClass structure contains + * only private data + * + * Since: 1.4 + */ +struct _ClutterShaderEffectClass +{ + /*< private >*/ + ClutterOffscreenEffectClass parent_class; + + /*< public >*/ + gchar * (* get_static_shader_source) (ClutterShaderEffect *effect); + + /*< private >*/ + /* padding */ + void (*_clutter_shader1) (void); + void (*_clutter_shader2) (void); + void (*_clutter_shader3) (void); + void (*_clutter_shader4) (void); + void (*_clutter_shader5) (void); +}; + +CLUTTER_AVAILABLE_IN_1_4 +GType clutter_shader_effect_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_4 +ClutterEffect * clutter_shader_effect_new (ClutterShaderType shader_type); + +CLUTTER_AVAILABLE_IN_1_4 +gboolean clutter_shader_effect_set_shader_source (ClutterShaderEffect *effect, + const gchar *source); + +CLUTTER_AVAILABLE_IN_1_4 +void clutter_shader_effect_set_uniform (ClutterShaderEffect *effect, + const gchar *name, + GType gtype, + gsize n_values, + ...); +CLUTTER_AVAILABLE_IN_1_4 +void clutter_shader_effect_set_uniform_value (ClutterShaderEffect *effect, + const gchar *name, + const GValue *value); + +CLUTTER_AVAILABLE_IN_1_4 +CoglHandle clutter_shader_effect_get_shader (ClutterShaderEffect *effect); +CLUTTER_AVAILABLE_IN_1_4 +CoglHandle clutter_shader_effect_get_program (ClutterShaderEffect *effect); + +G_END_DECLS + +#endif /* __CLUTTER_SHADER_EFFECT_H__ */ diff --git a/clutter/clutter/clutter-shader-types.c b/clutter/clutter/clutter-shader-types.c new file mode 100644 index 0000000..c956ef3 --- /dev/null +++ b/clutter/clutter/clutter-shader-types.c @@ -0,0 +1,566 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * Chris Lord + * + * Copyright (C) 2008 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include +#include + +#include "clutter-shader-types.h" +#include "clutter-private.h" + +static GTypeInfo shader_float_info = { + 0, + NULL, + NULL, + NULL, + NULL, + NULL, + 0, + 0, + NULL, + NULL, +}; + +static GTypeFundamentalInfo shader_float_finfo = { 0, }; + +static GTypeInfo shader_int_info = { + 0, + NULL, + NULL, + NULL, + NULL, + NULL, + 0, + 0, + NULL, + NULL, +}; + +static GTypeFundamentalInfo shader_int_finfo = { 0, }; + +static GTypeInfo shader_matrix_info = { + 0, + NULL, + NULL, + NULL, + NULL, + NULL, + 0, + 0, + NULL, + NULL, +}; + +static GTypeFundamentalInfo shader_matrix_finfo = { 0, }; + +struct _ClutterShaderFloat +{ + gint size; + float value[4]; +}; + +struct _ClutterShaderInt +{ + gint size; + int value[4]; +}; + +struct _ClutterShaderMatrix +{ + gint size; + float value[16]; +}; + +static gpointer +clutter_value_peek_pointer (const GValue *value) +{ + return value->data[0].v_pointer; +} + +/* Float */ + +static void +clutter_value_init_shader_float (GValue *value) +{ + value->data[0].v_pointer = g_slice_new0 (ClutterShaderFloat); +} + +static void +clutter_value_free_shader_float (GValue *value) +{ + g_slice_free (ClutterShaderFloat, value->data[0].v_pointer); +} + +static void +clutter_value_copy_shader_float (const GValue *src, + GValue *dest) +{ + dest->data[0].v_pointer = + g_slice_dup (ClutterShaderFloat, src->data[0].v_pointer); +} + +static gchar * +clutter_value_collect_shader_float (GValue *value, + guint n_collect_values, + GTypeCValue *collect_values, + guint collect_flags) +{ + gint float_count = collect_values[0].v_int; + const float *floats = collect_values[1].v_pointer; + + if (!floats) + return g_strdup_printf ("value location for '%s' passed as NULL", + G_VALUE_TYPE_NAME (value)); + + clutter_value_init_shader_float (value); + clutter_value_set_shader_float (value, float_count, floats); + + return NULL; +} + +static gchar * +clutter_value_lcopy_shader_float (const GValue *value, + guint n_collect_values, + GTypeCValue *collect_values, + guint collect_flags) +{ + gint *float_count = collect_values[0].v_pointer; + float **floats = collect_values[1].v_pointer; + ClutterShaderFloat *shader_float = value->data[0].v_pointer; + + if (!float_count || !floats) + return g_strdup_printf ("value location for '%s' passed as NULL", + G_VALUE_TYPE_NAME (value)); + + *float_count = shader_float->size; + *floats = g_memdup (shader_float->value, shader_float->size * sizeof (float)); + + return NULL; +} + +static const GTypeValueTable _clutter_shader_float_value_table = { + clutter_value_init_shader_float, + clutter_value_free_shader_float, + clutter_value_copy_shader_float, + clutter_value_peek_pointer, + "ip", + clutter_value_collect_shader_float, + "pp", + clutter_value_lcopy_shader_float +}; + +GType +clutter_shader_float_get_type (void) +{ + static GType _clutter_shader_float_type = 0; + + if (G_UNLIKELY (_clutter_shader_float_type == 0)) + { + shader_float_info.value_table = & _clutter_shader_float_value_table; + _clutter_shader_float_type = + g_type_register_fundamental (g_type_fundamental_next (), + I_("ClutterShaderFloat"), + &shader_float_info, + &shader_float_finfo, 0); + } + + return _clutter_shader_float_type; +} + + +/* Integer */ + +static void +clutter_value_init_shader_int (GValue *value) +{ + value->data[0].v_pointer = g_slice_new0 (ClutterShaderInt); +} + +static void +clutter_value_free_shader_int (GValue *value) +{ + g_slice_free (ClutterShaderInt, value->data[0].v_pointer); +} + +static void +clutter_value_copy_shader_int (const GValue *src, + GValue *dest) +{ + dest->data[0].v_pointer = + g_slice_dup (ClutterShaderInt, src->data[0].v_pointer); +} + +static gchar * +clutter_value_collect_shader_int (GValue *value, + guint n_collect_values, + GTypeCValue *collect_values, + guint collect_flags) +{ + gint int_count = collect_values[0].v_int; + const int *ints = collect_values[1].v_pointer; + + if (!ints) + return g_strdup_printf ("value location for '%s' passed as NULL", + G_VALUE_TYPE_NAME (value)); + + clutter_value_init_shader_int (value); + clutter_value_set_shader_int (value, int_count, ints); + + return NULL; +} + +static gchar * +clutter_value_lcopy_shader_int (const GValue *value, + guint n_collect_values, + GTypeCValue *collect_values, + guint collect_flags) +{ + gint *int_count = collect_values[0].v_pointer; + int **ints = collect_values[1].v_pointer; + ClutterShaderInt *shader_int = value->data[0].v_pointer; + + if (!int_count || !ints) + return g_strdup_printf ("value location for '%s' passed as NULL", + G_VALUE_TYPE_NAME (value)); + + *int_count = shader_int->size; + *ints = g_memdup (shader_int->value, shader_int->size * sizeof (int)); + + return NULL; +} + +static const GTypeValueTable _clutter_shader_int_value_table = { + clutter_value_init_shader_int, + clutter_value_free_shader_int, + clutter_value_copy_shader_int, + clutter_value_peek_pointer, + "ip", + clutter_value_collect_shader_int, + "pp", + clutter_value_lcopy_shader_int +}; + +GType +clutter_shader_int_get_type (void) +{ + static GType _clutter_shader_int_type = 0; + + if (G_UNLIKELY (_clutter_shader_int_type == 0)) + { + shader_int_info.value_table = & _clutter_shader_int_value_table; + _clutter_shader_int_type = + g_type_register_fundamental (g_type_fundamental_next (), + I_("ClutterShaderInt"), + &shader_int_info, + &shader_int_finfo, 0); + } + + return _clutter_shader_int_type; +} + + +/* Matrix */ + +static void +clutter_value_init_shader_matrix (GValue *value) +{ + value->data[0].v_pointer = g_slice_new0 (ClutterShaderMatrix); +} + +static void +clutter_value_free_shader_matrix (GValue *value) +{ + g_slice_free (ClutterShaderMatrix, value->data[0].v_pointer); +} + +static void +clutter_value_copy_shader_matrix (const GValue *src, + GValue *dest) +{ + dest->data[0].v_pointer = + g_slice_dup (ClutterShaderMatrix, src->data[0].v_pointer); +} + +static gchar * +clutter_value_collect_shader_matrix (GValue *value, + guint n_collect_values, + GTypeCValue *collect_values, + guint collect_flags) +{ + gint float_count = collect_values[0].v_int; + const float *floats = collect_values[1].v_pointer; + + if (!floats) + return g_strdup_printf ("value location for '%s' passed as NULL", + G_VALUE_TYPE_NAME (value)); + + clutter_value_init_shader_matrix (value); + clutter_value_set_shader_matrix (value, float_count, floats); + + return NULL; +} + +static gchar * +clutter_value_lcopy_shader_matrix (const GValue *value, + guint n_collect_values, + GTypeCValue *collect_values, + guint collect_flags) +{ + gint *float_count = collect_values[0].v_pointer; + float **floats = collect_values[1].v_pointer; + ClutterShaderFloat *shader_float = value->data[0].v_pointer; + + if (!float_count || !floats) + return g_strdup_printf ("value location for '%s' passed as NULL", + G_VALUE_TYPE_NAME (value)); + + *float_count = shader_float->size; + *floats = g_memdup (shader_float->value, + shader_float->size * shader_float->size * sizeof (float)); + + return NULL; +} + +static const GTypeValueTable _clutter_shader_matrix_value_table = { + clutter_value_init_shader_matrix, + clutter_value_free_shader_matrix, + clutter_value_copy_shader_matrix, + clutter_value_peek_pointer, + "ip", + clutter_value_collect_shader_matrix, + "pp", + clutter_value_lcopy_shader_matrix +}; + +GType +clutter_shader_matrix_get_type (void) +{ + static GType _clutter_shader_matrix_type = 0; + + if (G_UNLIKELY (_clutter_shader_matrix_type == 0)) + { + shader_matrix_info.value_table = & _clutter_shader_matrix_value_table; + _clutter_shader_matrix_type = + g_type_register_fundamental (g_type_fundamental_next (), + I_("ClutterShaderMatrix"), + &shader_matrix_info, + &shader_matrix_finfo, 0); + } + + return _clutter_shader_matrix_type; +} + + +/* Utility functions */ + +/** + * clutter_value_set_shader_float: + * @value: a #GValue + * @size: number of floating point values in @floats + * @floats: (array length=size): an array of floating point values + * + * Sets @floats as the contents of @value. The passed #GValue + * must have been initialized using %CLUTTER_TYPE_SHADER_FLOAT. + * + * Since: 0.8 + */ +void +clutter_value_set_shader_float (GValue *value, + gint size, + const gfloat *floats) +{ + ClutterShaderFloat *shader_float; + gint i; + + g_return_if_fail (CLUTTER_VALUE_HOLDS_SHADER_FLOAT (value)); + g_return_if_fail (size <= 4); + + shader_float = value->data[0].v_pointer; + + shader_float->size = size; + + for (i = 0; i < size; i++) + shader_float->value[i] = floats[i]; +} + +/** + * clutter_value_set_shader_int: + * @value: a #GValue + * @size: number of integer values in @ints + * @ints: (array length=size): an array of integer values + * + * Sets @ints as the contents of @value. The passed #GValue + * must have been initialized using %CLUTTER_TYPE_SHADER_INT. + * + * Since: 0.8 + */ +void +clutter_value_set_shader_int (GValue *value, + gint size, + const gint *ints) +{ + ClutterShaderInt *shader_int; + gint i; + + g_return_if_fail (CLUTTER_VALUE_HOLDS_SHADER_INT (value)); + g_return_if_fail (size <= 4); + + shader_int = value->data[0].v_pointer; + + shader_int->size = size; + + for (i = 0; i < size; i++) + shader_int->value[i] = ints[i]; +} + +/** + * clutter_value_set_shader_matrix: + * @value: a #GValue + * @size: number of floating point values in @floats + * @matrix: (array length=size): a matrix of floating point values + * + * Sets @matrix as the contents of @value. The passed #GValue + * must have been initialized using %CLUTTER_TYPE_SHADER_MATRIX. + * + * Since: 0.8 + */ +void +clutter_value_set_shader_matrix (GValue *value, + gint size, + const gfloat *matrix) +{ + ClutterShaderMatrix *shader_matrix; + gint i; + + g_return_if_fail (CLUTTER_VALUE_HOLDS_SHADER_MATRIX (value)); + g_return_if_fail (size <= 4); + + shader_matrix = value->data[0].v_pointer; + + shader_matrix->size = size; + + for (i = 0; i < size * size; i++) + shader_matrix->value[i] = matrix[i]; +} + +/** + * clutter_value_get_shader_float: + * @value: a #GValue + * @length: (out): return location for the number of returned floating + * point values, or %NULL + * + * Retrieves the list of floating point values stored inside + * the passed #GValue. @value must have been initialized with + * %CLUTTER_TYPE_SHADER_FLOAT. + * + * Return value: (array length=length): the pointer to a list of + * floating point values. The returned value is owned by the + * #GValue and should never be modified or freed. + * + * Since: 0.8 + */ +const gfloat * +clutter_value_get_shader_float (const GValue *value, + gsize *length) +{ + ClutterShaderFloat *shader_float; + + g_return_val_if_fail (CLUTTER_VALUE_HOLDS_SHADER_FLOAT (value), NULL); + + shader_float = value->data[0].v_pointer; + + if (length) + *length = shader_float->size; + + return shader_float->value; +} + +/** + * clutter_value_get_shader_int: + * @value: a #GValue + * @length: (out): return location for the number of returned integer + * values, or %NULL + * + * Retrieves the list of integer values stored inside the passed + * #GValue. @value must have been initialized with + * %CLUTTER_TYPE_SHADER_INT. + * + * Return value: (array length=length): the pointer to a list of + * integer values. The returned value is owned by the #GValue and + * should never be modified or freed. + * + * Since: 0.8 + */ +const gint * +clutter_value_get_shader_int (const GValue *value, + gsize *length) +{ + ClutterShaderInt *shader_int; + + g_return_val_if_fail (CLUTTER_VALUE_HOLDS_SHADER_INT (value), NULL); + + shader_int = value->data[0].v_pointer; + + if (length) + *length = shader_int->size; + + return shader_int->value; +} + +/** + * clutter_value_get_shader_matrix: + * @value: a #GValue + * @length: (out): return location for the number of returned floating + * point values, or %NULL + * + * Retrieves a matrix of floating point values stored inside + * the passed #GValue. @value must have been initialized with + * %CLUTTER_TYPE_SHADER_MATRIX. + * + * Return value: (array length=length) (transfer none): the pointer to a matrix + * of floating point values. The returned value is owned by the #GValue and + * should never be modified or freed. + * + * Since: 0.8 + */ +const gfloat * +clutter_value_get_shader_matrix (const GValue *value, + gsize *length) +{ + ClutterShaderMatrix *shader_matrix; + + g_return_val_if_fail (CLUTTER_VALUE_HOLDS_SHADER_MATRIX (value), NULL); + + shader_matrix = value->data[0].v_pointer; + + if (length) + *length = shader_matrix->size; + + return shader_matrix->value; +} diff --git a/clutter/clutter/clutter-shader-types.h b/clutter/clutter/clutter-shader-types.h new file mode 100644 index 0000000..f144b6c --- /dev/null +++ b/clutter/clutter/clutter-shader-types.h @@ -0,0 +1,104 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2008 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 . + */ + +#ifndef __CLUTTER_SHADER_TYPES_H__ +#define __CLUTTER_SHADER_TYPES_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_SHADER_FLOAT (clutter_shader_float_get_type ()) +#define CLUTTER_TYPE_SHADER_INT (clutter_shader_int_get_type ()) +#define CLUTTER_TYPE_SHADER_MATRIX (clutter_shader_matrix_get_type ()) + +typedef struct _ClutterShaderFloat ClutterShaderFloat; +typedef struct _ClutterShaderInt ClutterShaderInt; +typedef struct _ClutterShaderMatrix ClutterShaderMatrix; + +/** + * CLUTTER_VALUE_HOLDS_SHADER_FLOAT: + * @x: a #GValue + * + * Evaluates to %TRUE if @x holds a #ClutterShaderFloat. + * + * Since: 1.0 + */ +#define CLUTTER_VALUE_HOLDS_SHADER_FLOAT(x) (G_VALUE_HOLDS ((x), CLUTTER_TYPE_SHADER_FLOAT)) + +/** + * CLUTTER_VALUE_HOLDS_SHADER_INT: + * @x: a #GValue + * + * Evaluates to %TRUE if @x holds a #ClutterShaderInt. + * + * Since: 1.0 + */ +#define CLUTTER_VALUE_HOLDS_SHADER_INT(x) (G_VALUE_HOLDS ((x), CLUTTER_TYPE_SHADER_INT)) + +/** + * CLUTTER_VALUE_HOLDS_SHADER_MATRIX: + * @x: a #GValue + * + * Evaluates to %TRUE if @x holds a #ClutterShaderMatrix. + * + * Since: 1.0 + */ +#define CLUTTER_VALUE_HOLDS_SHADER_MATRIX(x) (G_VALUE_HOLDS ((x), CLUTTER_TYPE_SHADER_MATRIX)) + +CLUTTER_AVAILABLE_IN_1_0 +GType clutter_shader_float_get_type (void) G_GNUC_CONST; +CLUTTER_AVAILABLE_IN_1_0 +GType clutter_shader_int_get_type (void) G_GNUC_CONST; +CLUTTER_AVAILABLE_IN_1_0 +GType clutter_shader_matrix_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_0 +void clutter_value_set_shader_float (GValue *value, + gint size, + const gfloat *floats); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_value_set_shader_int (GValue *value, + gint size, + const gint *ints); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_value_set_shader_matrix (GValue *value, + gint size, + const gfloat *matrix); +CLUTTER_AVAILABLE_IN_1_0 +const gfloat * clutter_value_get_shader_float (const GValue *value, + gsize *length); +CLUTTER_AVAILABLE_IN_1_0 +const gint * clutter_value_get_shader_int (const GValue *value, + gsize *length); +CLUTTER_AVAILABLE_IN_1_0 +const gfloat * clutter_value_get_shader_matrix (const GValue *value, + gsize *length); + +G_END_DECLS + +#endif /* __CLUTTER_SHADER_TYPES_H__ */ diff --git a/clutter/clutter/clutter-snap-constraint.c b/clutter/clutter/clutter-snap-constraint.c new file mode 100644 index 0000000..5b6db9b --- /dev/null +++ b/clutter/clutter/clutter-snap-constraint.c @@ -0,0 +1,604 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-snap-constraint + * @Title: ClutterSnapConstraint + * @Short_Description: A constraint snapping two actors together + * + * #ClutterSnapConstraint is a constraint the snaps the edges of two + * actors together, expanding the actor's allocation if necessary. + * + * An offset can be applied to the constraint, to provide spacing. + * + * #ClutterSnapConstraint is available since Clutter 1.6 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#include "clutter-snap-constraint.h" + +#include "clutter-actor-private.h" +#include "clutter-constraint.h" +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-private.h" + +#define CLUTTER_SNAP_CONSTRAINT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_SNAP_CONSTRAINT, ClutterSnapConstraintClass)) +#define CLUTTER_IS_SNAP_CONSTRAINT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_SNAP_CONSTRAINT)) +#define CLUTTER_SNAP_CONSTRAINT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_SNAP_CONSTRAINT, ClutterSnapConstraintClass)) + +struct _ClutterSnapConstraint +{ + ClutterConstraint parent_instance; + + ClutterActor *actor; + ClutterActor *source; + + ClutterSnapEdge from_edge; + ClutterSnapEdge to_edge; + + gfloat offset; +}; + +struct _ClutterSnapConstraintClass +{ + ClutterConstraintClass parent_class; +}; + +enum +{ + PROP_0, + + PROP_SOURCE, + PROP_FROM_EDGE, + PROP_TO_EDGE, + PROP_OFFSET, + + PROP_LAST +}; + +G_DEFINE_TYPE (ClutterSnapConstraint, + clutter_snap_constraint, + CLUTTER_TYPE_CONSTRAINT); + +static GParamSpec *obj_props[PROP_LAST] = { NULL, }; + +static void +source_queue_relayout (ClutterActor *source, + ClutterSnapConstraint *constraint) +{ + if (constraint->actor != NULL) + _clutter_actor_queue_only_relayout (constraint->actor); +} + +static void +source_destroyed (ClutterActor *actor, + ClutterSnapConstraint *constraint) +{ + constraint->source = NULL; +} + +static inline void +warn_horizontal_edge (const gchar *edge, + ClutterActor *actor, + ClutterActor *source) +{ + g_warning (G_STRLOC ": the %s edge of actor '%s' can only be snapped " + "to either the right or the left edge of actor '%s'", + edge, + _clutter_actor_get_debug_name (actor), + _clutter_actor_get_debug_name (source)); +} + +static inline void +warn_vertical_edge (const gchar *edge, + ClutterActor *actor, + ClutterActor *source) +{ + g_warning (G_STRLOC ": the %s edge of actor '%s' can only " + "be snapped to the top or bottom edge of actor '%s'", + edge, + _clutter_actor_get_debug_name (actor), + _clutter_actor_get_debug_name (source)); +} + +static void +clutter_snap_constraint_update_allocation (ClutterConstraint *constraint, + ClutterActor *actor, + ClutterActorBox *allocation) +{ + ClutterSnapConstraint *self = CLUTTER_SNAP_CONSTRAINT (constraint); + gfloat source_width, source_height; + gfloat source_x, source_y; + gfloat actor_width, actor_height; + + if (self->source == NULL) + return; + + clutter_actor_get_position (self->source, &source_x, &source_y); + clutter_actor_get_size (self->source, &source_width, &source_height); + + clutter_actor_box_get_size (allocation, &actor_width, &actor_height); + + switch (self->to_edge) + { + case CLUTTER_SNAP_EDGE_LEFT: + if (self->from_edge == CLUTTER_SNAP_EDGE_LEFT) + allocation->x1 = source_x + self->offset; + else if (self->from_edge == CLUTTER_SNAP_EDGE_RIGHT) + allocation->x2 = source_x + self->offset; + else + warn_horizontal_edge ("left", self->actor, self->source); + break; + + case CLUTTER_SNAP_EDGE_RIGHT: + if (self->from_edge == CLUTTER_SNAP_EDGE_RIGHT) + allocation->x2 = source_x + source_width + self->offset; + else if (self->from_edge == CLUTTER_SNAP_EDGE_LEFT) + allocation->x1 = source_x + source_width + self->offset; + else + warn_horizontal_edge ("right", self->actor, self->source); + break; + + break; + + case CLUTTER_SNAP_EDGE_TOP: + if (self->from_edge == CLUTTER_SNAP_EDGE_TOP) + allocation->y1 = source_y + self->offset; + else if (self->from_edge == CLUTTER_SNAP_EDGE_BOTTOM) + allocation->y2 = source_y + self->offset; + else + warn_vertical_edge ("top", self->actor, self->source); + break; + + case CLUTTER_SNAP_EDGE_BOTTOM: + if (self->from_edge == CLUTTER_SNAP_EDGE_BOTTOM) + allocation->y2 = source_y + source_height + self->offset; + else if (self->from_edge == CLUTTER_SNAP_EDGE_TOP) + allocation->y1 = source_y + source_height + self->offset; + else + warn_vertical_edge ("bottom", self->actor, self->source); + break; + + default: + g_assert_not_reached (); + break; + } + + if (allocation->x2 - allocation->x1 < 0) + allocation->x2 = allocation->x1; + + if (allocation->y2 - allocation->y1 < 0) + allocation->y2 = allocation->y1; +} + +static void +clutter_snap_constraint_set_actor (ClutterActorMeta *meta, + ClutterActor *new_actor) +{ + ClutterSnapConstraint *self = CLUTTER_SNAP_CONSTRAINT (meta); + ClutterActorMetaClass *parent; + + /* store the pointer to the actor, for later use */ + self->actor = new_actor; + + parent = CLUTTER_ACTOR_META_CLASS (clutter_snap_constraint_parent_class); + parent->set_actor (meta, new_actor); +} + +static void +clutter_snap_constraint_dispose (GObject *gobject) +{ + ClutterSnapConstraint *snap = CLUTTER_SNAP_CONSTRAINT (gobject); + + if (snap->source != NULL) + { + g_signal_handlers_disconnect_by_func (snap->source, + G_CALLBACK (source_destroyed), + snap); + g_signal_handlers_disconnect_by_func (snap->source, + G_CALLBACK (source_queue_relayout), + snap); + snap->source = NULL; + } + + G_OBJECT_CLASS (clutter_snap_constraint_parent_class)->dispose (gobject); +} + +static void +clutter_snap_constraint_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterSnapConstraint *self = CLUTTER_SNAP_CONSTRAINT (gobject); + + switch (prop_id) + { + case PROP_SOURCE: + clutter_snap_constraint_set_source (self, g_value_get_object (value)); + break; + + case PROP_FROM_EDGE: + clutter_snap_constraint_set_edges (self, + g_value_get_enum (value), + self->to_edge); + break; + + case PROP_TO_EDGE: + clutter_snap_constraint_set_edges (self, + self->from_edge, + g_value_get_enum (value)); + break; + + case PROP_OFFSET: + clutter_snap_constraint_set_offset (self, g_value_get_float (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_snap_constraint_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterSnapConstraint *self = CLUTTER_SNAP_CONSTRAINT (gobject); + + switch (prop_id) + { + case PROP_SOURCE: + g_value_set_object (value, self->source); + break; + + case PROP_FROM_EDGE: + g_value_set_enum (value, self->from_edge); + break; + + case PROP_TO_EDGE: + g_value_set_enum (value, self->to_edge); + break; + + case PROP_OFFSET: + g_value_set_float (value, self->offset); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_snap_constraint_class_init (ClutterSnapConstraintClass *klass) +{ + ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass); + ClutterConstraintClass *constraint_class = CLUTTER_CONSTRAINT_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + meta_class->set_actor = clutter_snap_constraint_set_actor; + + constraint_class->update_allocation = clutter_snap_constraint_update_allocation; + /** + * ClutterSnapConstraint:source: + * + * The #ClutterActor used as the source for the constraint + * + * Since: 1.6 + */ + obj_props[PROP_SOURCE] = + g_param_spec_object ("source", + P_("Source"), + P_("The source of the constraint"), + CLUTTER_TYPE_ACTOR, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT); + + /** + * ClutterSnapConstraint:from-edge: + * + * The edge of the #ClutterActor that should be snapped + * + * Since: 1.6 + */ + obj_props[PROP_FROM_EDGE] = + g_param_spec_enum ("from-edge", + P_("From Edge"), + P_("The edge of the actor that should be snapped"), + CLUTTER_TYPE_SNAP_EDGE, + CLUTTER_SNAP_EDGE_RIGHT, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT); + + /** + * ClutterSnapConstraint:to-edge: + * + * The edge of the #ClutterSnapConstraint:source that should be snapped + * + * Since: 1.6 + */ + obj_props[PROP_TO_EDGE] = + g_param_spec_enum ("to-edge", + P_("To Edge"), + P_("The edge of the source that should be snapped"), + CLUTTER_TYPE_SNAP_EDGE, + CLUTTER_SNAP_EDGE_RIGHT, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT); + + /** + * ClutterSnapConstraint:offset: + * + * The offset, in pixels, between #ClutterSnapConstraint:from-edge + * and #ClutterSnapConstraint:to-edge + * + * Since: 1.6 + */ + obj_props[PROP_OFFSET] = + g_param_spec_float ("offset", + P_("Offset"), + P_("The offset in pixels to apply to the constraint"), + -G_MAXFLOAT, G_MAXFLOAT, + 0.0f, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT); + + gobject_class->dispose = clutter_snap_constraint_dispose; + gobject_class->set_property = clutter_snap_constraint_set_property; + gobject_class->get_property = clutter_snap_constraint_get_property; + g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); +} + +static void +clutter_snap_constraint_init (ClutterSnapConstraint *self) +{ + self->actor = NULL; + self->source = NULL; + + self->from_edge = CLUTTER_SNAP_EDGE_RIGHT; + self->to_edge = CLUTTER_SNAP_EDGE_RIGHT; + + self->offset = 0.0f; +} + +/** + * clutter_snap_constraint_new: + * @source: (allow-none): the #ClutterActor to use as the source of + * the constraint, or %NULL + * @from_edge: the edge of the actor to use in the constraint + * @to_edge: the edge of @source to use in the constraint + * @offset: the offset to apply to the constraint, in pixels + * + * Creates a new #ClutterSnapConstraint that will snap a #ClutterActor + * to the @edge of @source, with the given @offset. + * + * Return value: the newly created #ClutterSnapConstraint + * + * Since: 1.6 + */ +ClutterConstraint * +clutter_snap_constraint_new (ClutterActor *source, + ClutterSnapEdge from_edge, + ClutterSnapEdge to_edge, + gfloat offset) +{ + g_return_val_if_fail (source == NULL || CLUTTER_IS_ACTOR (source), NULL); + + return g_object_new (CLUTTER_TYPE_SNAP_CONSTRAINT, + "source", source, + "from-edge", from_edge, + "to-edge", to_edge, + "offset", offset, + NULL); +} + +/** + * clutter_snap_constraint_set_source: + * @constraint: a #ClutterSnapConstraint + * @source: (allow-none): a #ClutterActor, or %NULL to unset the source + * + * Sets the source #ClutterActor for the constraint + * + * Since: 1.6 + */ +void +clutter_snap_constraint_set_source (ClutterSnapConstraint *constraint, + ClutterActor *source) +{ + ClutterActor *old_source; + + g_return_if_fail (CLUTTER_IS_SNAP_CONSTRAINT (constraint)); + g_return_if_fail (source == NULL || CLUTTER_IS_ACTOR (source)); + + if (constraint->source == source) + return; + + old_source = constraint->source; + if (old_source != NULL) + { + g_signal_handlers_disconnect_by_func (old_source, + G_CALLBACK (source_destroyed), + constraint); + g_signal_handlers_disconnect_by_func (old_source, + G_CALLBACK (source_queue_relayout), + constraint); + } + + constraint->source = source; + if (constraint->source != NULL) + { + g_signal_connect (constraint->source, "queue-relayout", + G_CALLBACK (source_queue_relayout), + constraint); + g_signal_connect (constraint->source, "destroy", + G_CALLBACK (source_destroyed), + constraint); + + if (constraint->actor != NULL) + clutter_actor_queue_relayout (constraint->actor); + } + + g_object_notify_by_pspec (G_OBJECT (constraint), obj_props[PROP_SOURCE]); +} + +/** + * clutter_snap_constraint_get_source: + * @constraint: a #ClutterSnapConstraint + * + * Retrieves the #ClutterActor set using clutter_snap_constraint_set_source() + * + * Return value: (transfer none): a pointer to the source actor + * + * Since: 1.6 + */ +ClutterActor * +clutter_snap_constraint_get_source (ClutterSnapConstraint *constraint) +{ + g_return_val_if_fail (CLUTTER_IS_SNAP_CONSTRAINT (constraint), NULL); + + return constraint->source; +} + +/** + * clutter_snap_constraint_set_edges: + * @constraint: a #ClutterSnapConstraint + * @from_edge: the edge on the actor + * @to_edge: the edge on the source + * + * Sets the edges to be used by the @constraint + * + * The @from_edge is the edge on the #ClutterActor to which @constraint + * has been added. The @to_edge is the edge of the #ClutterActor inside + * the #ClutterSnapConstraint:source property. + * + * Since: 1.6 + */ +void +clutter_snap_constraint_set_edges (ClutterSnapConstraint *constraint, + ClutterSnapEdge from_edge, + ClutterSnapEdge to_edge) +{ + gboolean from_changed = FALSE, to_changed = FALSE; + + g_return_if_fail (CLUTTER_IS_SNAP_CONSTRAINT (constraint)); + + g_object_freeze_notify (G_OBJECT (constraint)); + + if (constraint->from_edge != from_edge) + { + constraint->from_edge = from_edge; + g_object_notify_by_pspec (G_OBJECT (constraint), + obj_props[PROP_FROM_EDGE]); + from_changed = TRUE; + } + + if (constraint->to_edge != to_edge) + { + constraint->to_edge = to_edge; + g_object_notify_by_pspec (G_OBJECT (constraint), + obj_props[PROP_TO_EDGE]); + to_changed = TRUE; + } + + if ((from_changed || to_changed) && + constraint->actor != NULL) + { + clutter_actor_queue_relayout (constraint->actor); + } + + g_object_thaw_notify (G_OBJECT (constraint)); +} + +/** + * clutter_snap_constraint_get_edges: + * @constraint: a #ClutterSnapConstraint + * @from_edge: (out): return location for the actor's edge, or %NULL + * @to_edge: (out): return location for the source's edge, or %NULL + * + * Retrieves the edges used by the @constraint + * + * Since: 1.6 + */ +void +clutter_snap_constraint_get_edges (ClutterSnapConstraint *constraint, + ClutterSnapEdge *from_edge, + ClutterSnapEdge *to_edge) +{ + g_return_if_fail (CLUTTER_IS_SNAP_CONSTRAINT (constraint)); + + if (from_edge) + *from_edge = constraint->from_edge; + + if (to_edge) + *to_edge = constraint->to_edge; +} + +/** + * clutter_snap_constraint_set_offset: + * @constraint: a #ClutterSnapConstraint + * @offset: the offset to apply, in pixels + * + * Sets the offset to be applied to the constraint + * + * Since: 1.6 + */ +void +clutter_snap_constraint_set_offset (ClutterSnapConstraint *constraint, + gfloat offset) +{ + g_return_if_fail (CLUTTER_IS_SNAP_CONSTRAINT (constraint)); + + if (fabs (constraint->offset - offset) < 0.00001f) + return; + + constraint->offset = offset; + + if (constraint->actor != NULL) + clutter_actor_queue_relayout (constraint->actor); + + g_object_notify_by_pspec (G_OBJECT (constraint), obj_props[PROP_OFFSET]); +} + +/** + * clutter_snap_constraint_get_offset: + * @constraint: a #ClutterSnapConstraint + * + * Retrieves the offset set using clutter_snap_constraint_set_offset() + * + * Return value: the offset, in pixels + * + * Since: 1.6 + */ +gfloat +clutter_snap_constraint_get_offset (ClutterSnapConstraint *constraint) +{ + g_return_val_if_fail (CLUTTER_IS_SNAP_CONSTRAINT (constraint), 0.0); + + return constraint->offset; +} diff --git a/clutter/clutter/clutter-snap-constraint.h b/clutter/clutter/clutter-snap-constraint.h new file mode 100644 index 0000000..5a788dc --- /dev/null +++ b/clutter/clutter/clutter-snap-constraint.h @@ -0,0 +1,81 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_SNAP_CONSTRAINT_H__ +#define __CLUTTER_SNAP_CONSTRAINT_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_SNAP_CONSTRAINT (clutter_snap_constraint_get_type ()) +#define CLUTTER_SNAP_CONSTRAINT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_SNAP_CONSTRAINT, ClutterSnapConstraint)) +#define CLUTTER_IS_SNAP_CONSTRAINT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_SNAP_CONSTRAINT)) + +/** + * ClutterSnapConstraint: + * + * #ClutterSnapConstraint is an opaque structure + * whose members cannot be directly accesses + * + * Since: 1.6 + */ +typedef struct _ClutterSnapConstraint ClutterSnapConstraint; +typedef struct _ClutterSnapConstraintClass ClutterSnapConstraintClass; + +CLUTTER_AVAILABLE_IN_1_6 +GType clutter_snap_constraint_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_6 +ClutterConstraint * clutter_snap_constraint_new (ClutterActor *source, + ClutterSnapEdge from_edge, + ClutterSnapEdge to_edge, + gfloat offset); + +CLUTTER_AVAILABLE_IN_1_6 +void clutter_snap_constraint_set_source (ClutterSnapConstraint *constraint, + ClutterActor *source); +CLUTTER_AVAILABLE_IN_1_6 +ClutterActor * clutter_snap_constraint_get_source (ClutterSnapConstraint *constraint); +CLUTTER_AVAILABLE_IN_1_6 +void clutter_snap_constraint_set_edges (ClutterSnapConstraint *constraint, + ClutterSnapEdge from_edge, + ClutterSnapEdge to_edge); +CLUTTER_AVAILABLE_IN_1_6 +void clutter_snap_constraint_get_edges (ClutterSnapConstraint *constraint, + ClutterSnapEdge *from_edge, + ClutterSnapEdge *to_edge); +CLUTTER_AVAILABLE_IN_1_6 +void clutter_snap_constraint_set_offset (ClutterSnapConstraint *constraint, + gfloat offset); +CLUTTER_AVAILABLE_IN_1_6 +gfloat clutter_snap_constraint_get_offset (ClutterSnapConstraint *constraint); + +G_END_DECLS + +#endif /* __CLUTTER_SNAP_CONSTRAINT_H__ */ diff --git a/clutter/clutter/clutter-stage-manager-private.h b/clutter/clutter/clutter-stage-manager-private.h new file mode 100644 index 0000000..81ebbb6 --- /dev/null +++ b/clutter/clutter/clutter-stage-manager-private.h @@ -0,0 +1,49 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_STAGE_MANAGER_PRIVATE_H__ +#define __CLUTTER_STAGE_MANAGER_PRIVATE_H__ + +#include + +G_BEGIN_DECLS + +struct _ClutterStageManager +{ + GObject parent_instance; + + GSList *stages; +}; + +/* stage manager */ +void _clutter_stage_manager_add_stage (ClutterStageManager *stage_manager, + ClutterStage *stage); +void _clutter_stage_manager_remove_stage (ClutterStageManager *stage_manager, + ClutterStage *stage); +void _clutter_stage_manager_set_default_stage (ClutterStageManager *stage_manager, + ClutterStage *stage); + +G_END_DECLS + +#endif /* __CLUTTER_STAGE_MANAGER_PRIVATE_H__ */ diff --git a/clutter/clutter/clutter-stage-manager.c b/clutter/clutter/clutter-stage-manager.c new file mode 100644 index 0000000..3a44c82 --- /dev/null +++ b/clutter/clutter/clutter-stage-manager.c @@ -0,0 +1,323 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2008 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: Emmanuele Bassi + */ + +/** + * SECTION:clutter-stage-manager + * @short_description: Maintains the list of stages + * + * #ClutterStageManager is a singleton object, owned by Clutter, which + * maintains the list of currently active stages + * + * Every newly-created #ClutterStage will cause the emission of the + * #ClutterStageManager::stage-added signal; once a #ClutterStage has + * been destroyed, the #ClutterStageManager::stage-removed signal will + * be emitted + * + * #ClutterStageManager is available since Clutter 0.8 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-stage-manager-private.h" + +#include "clutter-marshal.h" +#include "clutter-debug.h" +#include "clutter-private.h" +#include "clutter-version.h" + +#include "deprecated/clutter-stage-manager.h" + +enum +{ + PROP_0, + PROP_DEFAULT_STAGE +}; + +enum +{ + STAGE_ADDED, + STAGE_REMOVED, + + LAST_SIGNAL +}; + +static guint manager_signals[LAST_SIGNAL] = { 0, }; +static ClutterStage *default_stage = NULL; + +G_DEFINE_TYPE (ClutterStageManager, clutter_stage_manager, G_TYPE_OBJECT); + +static void +clutter_stage_manager_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) + { + case PROP_DEFAULT_STAGE: + g_value_set_object (value, default_stage); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_stage_manager_dispose (GObject *gobject) +{ + ClutterStageManager *stage_manager; + + stage_manager = CLUTTER_STAGE_MANAGER (gobject); + + g_slist_foreach (stage_manager->stages, (GFunc) clutter_actor_destroy, NULL); + g_slist_free (stage_manager->stages); + stage_manager->stages = NULL; + + G_OBJECT_CLASS (clutter_stage_manager_parent_class)->dispose (gobject); +} + +static void +clutter_stage_manager_class_init (ClutterStageManagerClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->dispose = clutter_stage_manager_dispose; + gobject_class->get_property = clutter_stage_manager_get_property; + + /** + * ClutterStageManager:default-stage: + * + * The default stage used by Clutter. + * + * Since: 0.8 + */ + g_object_class_install_property (gobject_class, + PROP_DEFAULT_STAGE, + g_param_spec_object ("default-stage", + "Default Stage", + "The default stage", + CLUTTER_TYPE_STAGE, + CLUTTER_PARAM_READABLE)); + + /** + * ClutterStageManager::stage-added: + * @stage_manager: the object which received the signal + * @stage: the added stage + * + * The ::stage-added signal is emitted each time a new #ClutterStage + * has been added to the stage manager. + * + * Since: 0.8 + */ + manager_signals[STAGE_ADDED] = + g_signal_new ("stage-added", + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterStageManagerClass, stage_added), + NULL, NULL, + _clutter_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CLUTTER_TYPE_STAGE); + /** + * ClutterStageManager::stage-removed: + * @stage_manager: the object which received the signal + * @stage: the removed stage + * + * The ::stage-removed signal is emitted each time a #ClutterStage + * has been removed from the stage manager. + * + * Since: 0.8 + */ + manager_signals[STAGE_REMOVED] = + g_signal_new ("stage-removed", + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterStageManagerClass, stage_removed), + NULL, NULL, + _clutter_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CLUTTER_TYPE_STAGE); +} + +static void +clutter_stage_manager_init (ClutterStageManager *stage_manager) +{ +} + +/** + * clutter_stage_manager_get_default: + * + * Returns the default #ClutterStageManager. + * + * Return value: (transfer none): the default stage manager instance. The returned + * object is owned by Clutter and you should not reference or unreference it. + * + * Since: 0.8 + */ +ClutterStageManager * +clutter_stage_manager_get_default (void) +{ + ClutterMainContext *context = _clutter_context_get_default (); + + if (G_UNLIKELY (context->stage_manager == NULL)) + context->stage_manager = g_object_new (CLUTTER_TYPE_STAGE_MANAGER, NULL); + + return context->stage_manager; +} + +/** + * clutter_stage_manager_set_default_stage: + * @stage_manager: a #ClutterStageManager + * @stage: a #ClutterStage + * + * Sets @stage as the default stage. + * + * Since: 0.8 + * + * Deprecated: 1.2: Calling this function has no effect + */ +void +clutter_stage_manager_set_default_stage (ClutterStageManager *stage_manager, + ClutterStage *stage) +{ +} + +/*< private > + * _clutter_stage_manager_set_default_stage: + * @stage_manager: a #ClutterStageManager + * @stage: a #ClutterStage + * + * Sets @stage as the default stage + * + * A no-op if there already is a default stage + */ +void +_clutter_stage_manager_set_default_stage (ClutterStageManager *stage_manager, + ClutterStage *stage) +{ + if (G_UNLIKELY (default_stage == NULL)) + { + default_stage = stage; + + /* the default stage is immediately realized */ + clutter_actor_realize (CLUTTER_ACTOR (stage)); + + g_object_notify (G_OBJECT (stage_manager), "default-stage"); + } +} + +/** + * clutter_stage_manager_get_default_stage: + * @stage_manager: a #ClutterStageManager + * + * Returns the default #ClutterStage. + * + * Return value: (transfer none): the default stage. The returned object + * is owned by Clutter and you should never reference or unreference it + * + * Since: 0.8 + */ +ClutterStage * +clutter_stage_manager_get_default_stage (ClutterStageManager *stage_manager) +{ + return default_stage; +} + +/** + * clutter_stage_manager_list_stages: + * @stage_manager: a #ClutterStageManager + * + * Lists all currently used stages. + * + * Return value: (transfer container) (element-type Clutter.Stage): a newly + * allocated list of #ClutterStage objects. Use g_slist_free() to + * deallocate it when done. + * + * Since: 0.8 + */ +GSList * +clutter_stage_manager_list_stages (ClutterStageManager *stage_manager) +{ + return g_slist_copy (stage_manager->stages); +} + +/** + * clutter_stage_manager_peek_stages: + * @stage_manager: a #ClutterStageManager + * + * Lists all currently used stages. + * + * Return value: (transfer none) (element-type Clutter.Stage): 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) +{ + if (g_slist_find (stage_manager->stages, stage)) + { + g_warning ("Trying to add a stage to the list of managed stages, " + "but it is already in it, aborting."); + return; + } + + g_object_ref_sink (stage); + + stage_manager->stages = g_slist_append (stage_manager->stages, stage); + + g_signal_emit (stage_manager, manager_signals[STAGE_ADDED], 0, stage); +} + +void +_clutter_stage_manager_remove_stage (ClutterStageManager *stage_manager, + ClutterStage *stage) +{ + /* this might be called multiple times from a ::dispose, so it + * needs to just return without warning + */ + if (!g_slist_find (stage_manager->stages, stage)) + return; + + stage_manager->stages = g_slist_remove (stage_manager->stages, stage); + + /* if the default stage is being destroyed then we unset the pointer */ + if (default_stage == stage) + default_stage = NULL; + + g_signal_emit (stage_manager, manager_signals[STAGE_REMOVED], 0, stage); + + g_object_unref (stage); +} diff --git a/clutter/clutter/clutter-stage-manager.h b/clutter/clutter/clutter-stage-manager.h new file mode 100644 index 0000000..fa3badd --- /dev/null +++ b/clutter/clutter/clutter-stage-manager.h @@ -0,0 +1,86 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2008 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: Emmanuele Bassi + */ + +#ifndef __CLUTTER_STAGE_MANAGER_H__ +#define __CLUTTER_STAGE_MANAGER_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_STAGE_MANAGER (clutter_stage_manager_get_type ()) +#define CLUTTER_STAGE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STAGE_MANAGER, ClutterStageManager)) +#define CLUTTER_IS_STAGE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_STAGE_MANAGER)) +#define CLUTTER_STAGE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_STAGE_MANAGER, ClutterStageManagerClass)) +#define CLUTTER_IS_STAGE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_STAGE_MANAGER)) +#define CLUTTER_STAGE_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_STAGE_MANAGER, ClutterStageManagerClass)) + +typedef struct _ClutterStageManager ClutterStageManager; +typedef struct _ClutterStageManagerClass ClutterStageManagerClass; + +/** + * ClutterStageManager: + * + * The #ClutterStageManager structure is private. + * + * Since: 1.0 + */ + +/** + * ClutterStageManagerClass: + * + * The #ClutterStageManagerClass structure contains only private data + * and should be accessed using the provided API + * + * Since: 1.0 + */ +struct _ClutterStageManagerClass +{ + /*< private >*/ + GObjectClass parent_class; + + void (* stage_added) (ClutterStageManager *stage_manager, + ClutterStage *stage); + void (* stage_removed) (ClutterStageManager *stage_manager, + ClutterStage *stage); +}; + +CLUTTER_AVAILABLE_IN_1_0 +GType clutter_stage_manager_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_0 +ClutterStageManager *clutter_stage_manager_get_default (void); +CLUTTER_AVAILABLE_IN_1_0 +ClutterStage * clutter_stage_manager_get_default_stage (ClutterStageManager *stage_manager); +CLUTTER_AVAILABLE_IN_1_0 +GSList * clutter_stage_manager_list_stages (ClutterStageManager *stage_manager); +CLUTTER_AVAILABLE_IN_1_0 +const GSList * clutter_stage_manager_peek_stages (ClutterStageManager *stage_manager); + +G_END_DECLS + +#endif /* __CLUTTER_STAGE_MANAGER_H__ */ diff --git a/clutter/clutter/clutter-stage-private.h b/clutter/clutter/clutter-stage-private.h new file mode 100644 index 0000000..517c9ad --- /dev/null +++ b/clutter/clutter/clutter-stage-private.h @@ -0,0 +1,134 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __CLUTTER_STAGE_PRIVATE_H__ +#define __CLUTTER_STAGE_PRIVATE_H__ + +#include +#include +#include +#include + +#include + +G_BEGIN_DECLS + +typedef struct _ClutterStageQueueRedrawEntry ClutterStageQueueRedrawEntry; + +/* stage */ +ClutterStageWindow *_clutter_stage_get_default_window (void); + +void _clutter_stage_paint_view (ClutterStage *stage, + ClutterStageView *view, + const cairo_rectangle_int_t *clip); + +void _clutter_stage_set_window (ClutterStage *stage, + ClutterStageWindow *stage_window); +ClutterStageWindow *_clutter_stage_get_window (ClutterStage *stage); +void _clutter_stage_get_projection_matrix (ClutterStage *stage, + CoglMatrix *projection); +void _clutter_stage_dirty_projection (ClutterStage *stage); +void _clutter_stage_set_viewport (ClutterStage *stage, + float x, + float y, + float width, + float height); +void _clutter_stage_get_viewport (ClutterStage *stage, + float *x, + float *y, + float *width, + float *height); +void _clutter_stage_dirty_viewport (ClutterStage *stage); +void _clutter_stage_maybe_setup_viewport (ClutterStage *stage, + ClutterStageView *view); +void _clutter_stage_maybe_relayout (ClutterActor *stage); +gboolean _clutter_stage_needs_update (ClutterStage *stage); +gboolean _clutter_stage_do_update (ClutterStage *stage); + +void _clutter_stage_queue_event (ClutterStage *stage, + ClutterEvent *event, + gboolean copy_event); +gboolean _clutter_stage_has_queued_events (ClutterStage *stage); +void _clutter_stage_process_queued_events (ClutterStage *stage); +void _clutter_stage_update_input_devices (ClutterStage *stage); +void _clutter_stage_schedule_update (ClutterStage *stage); +gint64 _clutter_stage_get_update_time (ClutterStage *stage); +void _clutter_stage_clear_update_time (ClutterStage *stage); +gboolean _clutter_stage_has_full_redraw_queued (ClutterStage *stage); + +ClutterActor *_clutter_stage_do_pick (ClutterStage *stage, + gint x, + gint y, + ClutterPickMode mode); + +ClutterPaintVolume *_clutter_stage_paint_volume_stack_allocate (ClutterStage *stage); +void _clutter_stage_paint_volume_stack_free_all (ClutterStage *stage); + +const ClutterPlane *_clutter_stage_get_clip (ClutterStage *stage); + +ClutterStageQueueRedrawEntry *_clutter_stage_queue_actor_redraw (ClutterStage *stage, + ClutterStageQueueRedrawEntry *entry, + ClutterActor *actor, + ClutterPaintVolume *clip); +void _clutter_stage_queue_redraw_entry_invalidate (ClutterStageQueueRedrawEntry *entry); + +CoglFramebuffer *_clutter_stage_get_active_framebuffer (ClutterStage *stage); + +gint32 _clutter_stage_acquire_pick_id (ClutterStage *stage, + ClutterActor *actor); +void _clutter_stage_release_pick_id (ClutterStage *stage, + gint32 pick_id); +ClutterActor * _clutter_stage_get_actor_by_pick_id (ClutterStage *stage, + gint32 pick_id); + +void _clutter_stage_add_pointer_drag_actor (ClutterStage *stage, + ClutterInputDevice *device, + ClutterActor *actor); +ClutterActor * _clutter_stage_get_pointer_drag_actor (ClutterStage *stage, + ClutterInputDevice *device); +void _clutter_stage_remove_pointer_drag_actor (ClutterStage *stage, + ClutterInputDevice *device); + +void _clutter_stage_add_touch_drag_actor (ClutterStage *stage, + ClutterEventSequence *sequence, + ClutterActor *actor); +ClutterActor * _clutter_stage_get_touch_drag_actor (ClutterStage *stage, + ClutterEventSequence *sequence); +void _clutter_stage_remove_touch_drag_actor (ClutterStage *stage, + ClutterEventSequence *sequence); + +ClutterStageState _clutter_stage_get_state (ClutterStage *stage); +gboolean _clutter_stage_is_activated (ClutterStage *stage); +gboolean _clutter_stage_is_fullscreen (ClutterStage *stage); +gboolean _clutter_stage_update_state (ClutterStage *stage, + ClutterStageState unset_state, + ClutterStageState set_state); + +void _clutter_stage_set_scale_factor (ClutterStage *stage, + int factor); + +void _clutter_stage_presented (ClutterStage *stage, + CoglFrameEvent frame_event, + ClutterFrameInfo *frame_info); + +G_END_DECLS + +#endif /* __CLUTTER_STAGE_PRIVATE_H__ */ diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c new file mode 100644 index 0000000..2b89bb2 --- /dev/null +++ b/clutter/clutter/clutter-stage-view.c @@ -0,0 +1,319 @@ +/* + * Copyright (C) 2016 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "clutter-build-config.h" + +#include "clutter/clutter-stage-view.h" + +#include + +enum +{ + PROP_0, + + PROP_LAYOUT, + PROP_FRAMEBUFFER, + PROP_OFFSCREEN, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +typedef struct _ClutterStageViewPrivate +{ + cairo_rectangle_int_t layout; + CoglFramebuffer *framebuffer; + + CoglOffscreen *offscreen; + CoglPipeline *pipeline; + + guint dirty_viewport : 1; + guint dirty_projection : 1; +} ClutterStageViewPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterStageView, clutter_stage_view, G_TYPE_OBJECT) + +void +clutter_stage_view_get_layout (ClutterStageView *view, + cairo_rectangle_int_t *rect) +{ + ClutterStageViewPrivate *priv = + clutter_stage_view_get_instance_private (view); + + *rect = priv->layout; +} + +CoglFramebuffer * +clutter_stage_view_get_framebuffer (ClutterStageView *view) +{ + ClutterStageViewPrivate *priv = + clutter_stage_view_get_instance_private (view); + + if (priv->offscreen) + return priv->offscreen; + else + return priv->framebuffer; +} + +CoglFramebuffer * +clutter_stage_view_get_onscreen (ClutterStageView *view) +{ + ClutterStageViewPrivate *priv = + clutter_stage_view_get_instance_private (view); + + return priv->framebuffer; +} + +static void +clutter_stage_view_ensure_offscreen_blit_pipeline (ClutterStageView *view) +{ + ClutterStageViewPrivate *priv = + clutter_stage_view_get_instance_private (view); + ClutterStageViewClass *view_class = + CLUTTER_STAGE_VIEW_GET_CLASS (view); + + g_assert (priv->offscreen != NULL); + + if (priv->pipeline) + return; + + priv->pipeline = + cogl_pipeline_new (cogl_framebuffer_get_context (priv->offscreen)); + cogl_pipeline_set_layer_filters (priv->pipeline, 0, + COGL_PIPELINE_FILTER_NEAREST, + COGL_PIPELINE_FILTER_NEAREST); + cogl_pipeline_set_layer_texture (priv->pipeline, 0, + cogl_offscreen_get_texture (priv->offscreen)); + cogl_pipeline_set_layer_wrap_mode (priv->pipeline, 0, + COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); + + if (view_class->setup_offscreen_blit_pipeline) + view_class->setup_offscreen_blit_pipeline (view, priv->pipeline); +} + +void +clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view) +{ + ClutterStageViewPrivate *priv = + clutter_stage_view_get_instance_private (view); + + g_clear_pointer (&priv->pipeline, cogl_object_unref); +} + +void +clutter_stage_view_blit_offscreen (ClutterStageView *view, + const cairo_rectangle_int_t *rect) +{ + ClutterStageViewPrivate *priv = + clutter_stage_view_get_instance_private (view); + CoglMatrix matrix; + + clutter_stage_view_ensure_offscreen_blit_pipeline (view); + cogl_framebuffer_push_matrix (priv->framebuffer); + + /* Set transform so 0,0 is on the top left corner and 1,1 on + * the bottom right corner. + */ + cogl_matrix_init_identity (&matrix); + cogl_matrix_translate (&matrix, -1, 1, 0); + cogl_matrix_scale (&matrix, 2, -2, 0); + cogl_framebuffer_set_projection_matrix (priv->framebuffer, &matrix); + + cogl_framebuffer_draw_rectangle (priv->framebuffer, + priv->pipeline, + 0, 0, 1, 1); + + cogl_framebuffer_pop_matrix (priv->framebuffer); +} + +gboolean +clutter_stage_view_is_dirty_viewport (ClutterStageView *view) +{ + ClutterStageViewPrivate *priv = + clutter_stage_view_get_instance_private (view); + + return priv->dirty_viewport; +} + +void +clutter_stage_view_set_dirty_viewport (ClutterStageView *view, + gboolean dirty) +{ + ClutterStageViewPrivate *priv = + clutter_stage_view_get_instance_private (view); + + priv->dirty_viewport = dirty; +} + +gboolean +clutter_stage_view_is_dirty_projection (ClutterStageView *view) +{ + ClutterStageViewPrivate *priv = + clutter_stage_view_get_instance_private (view); + + return priv->dirty_projection; +} + +void +clutter_stage_view_set_dirty_projection (ClutterStageView *view, + gboolean dirty) +{ + ClutterStageViewPrivate *priv = + clutter_stage_view_get_instance_private (view); + + priv->dirty_projection = dirty; +} + +void +clutter_stage_view_transform_to_onscreen (ClutterStageView *view, + gfloat *x, + gfloat *y) +{ + ClutterStageViewClass *view_class = CLUTTER_STAGE_VIEW_GET_CLASS (view); + gfloat z = 0, w = 1; + CoglMatrix matrix; + + view_class->get_offscreen_transformation_matrix (view, &matrix); + cogl_matrix_get_inverse (&matrix, &matrix); + cogl_matrix_transform_point (&matrix, x, y, &z, &w); +} + +static void +clutter_stage_default_get_offscreen_transformation_matrix (ClutterStageView *view, + CoglMatrix *matrix) +{ + cogl_matrix_init_identity (matrix); +} + +static void +clutter_stage_view_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterStageView *view = CLUTTER_STAGE_VIEW (object); + ClutterStageViewPrivate *priv = + clutter_stage_view_get_instance_private (view); + + switch (prop_id) + { + case PROP_LAYOUT: + g_value_set_boxed (value, &priv->layout); + break; + case PROP_FRAMEBUFFER: + g_value_set_boxed (value, priv->framebuffer); + break; + case PROP_OFFSCREEN: + g_value_set_boxed (value, priv->offscreen); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +clutter_stage_view_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterStageView *view = CLUTTER_STAGE_VIEW (object); + ClutterStageViewPrivate *priv = + clutter_stage_view_get_instance_private (view); + cairo_rectangle_int_t *layout; + + switch (prop_id) + { + case PROP_LAYOUT: + layout = g_value_get_boxed (value); + priv->layout = *layout; + break; + case PROP_FRAMEBUFFER: + priv->framebuffer = g_value_dup_boxed (value); + break; + case PROP_OFFSCREEN: + priv->offscreen = g_value_dup_boxed (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +clutter_stage_view_dispose (GObject *object) +{ + ClutterStageView *view = CLUTTER_STAGE_VIEW (object); + ClutterStageViewPrivate *priv = + clutter_stage_view_get_instance_private (view); + + g_clear_pointer (&priv->framebuffer, cogl_object_unref); + g_clear_pointer (&priv->offscreen, cogl_object_unref); + g_clear_pointer (&priv->pipeline, cogl_object_unref); + + G_OBJECT_CLASS (clutter_stage_view_parent_class)->dispose (object); +} + +static void +clutter_stage_view_init (ClutterStageView *view) +{ + ClutterStageViewPrivate *priv = + clutter_stage_view_get_instance_private (view); + + priv->dirty_viewport = TRUE; + priv->dirty_projection = TRUE; +} + +static void +clutter_stage_view_class_init (ClutterStageViewClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + klass->get_offscreen_transformation_matrix = + clutter_stage_default_get_offscreen_transformation_matrix; + + object_class->get_property = clutter_stage_view_get_property; + object_class->set_property = clutter_stage_view_set_property; + object_class->dispose = clutter_stage_view_dispose; + + obj_props[PROP_LAYOUT] = + g_param_spec_boxed ("layout", + "View layout", + "The view layout on the screen", + CAIRO_GOBJECT_TYPE_RECTANGLE_INT, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + obj_props[PROP_FRAMEBUFFER] = + g_param_spec_boxed ("framebuffer", + "View framebuffer", + "The front buffer of the view", + COGL_TYPE_HANDLE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + obj_props[PROP_OFFSCREEN] = + g_param_spec_boxed ("offscreen", + "Offscreen buffer", + "Framebuffer used as intermediate buffer", + COGL_TYPE_HANDLE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, PROP_LAST, obj_props); +} diff --git a/clutter/clutter/clutter-stage-view.h b/clutter/clutter/clutter-stage-view.h new file mode 100644 index 0000000..e820e96 --- /dev/null +++ b/clutter/clutter/clutter-stage-view.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2016 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __CLUTTER_STAGE_VIEW_H__ +#define __CLUTTER_STAGE_VIEW_H__ + +#include +#include +#include + +#include "clutter-macros.h" + +#define CLUTTER_TYPE_STAGE_VIEW (clutter_stage_view_get_type ()) +CLUTTER_AVAILABLE_IN_MUTTER +G_DECLARE_DERIVABLE_TYPE (ClutterStageView, clutter_stage_view, + CLUTTER, STAGE_VIEW, + GObject) + +struct _ClutterStageViewClass +{ + GObjectClass parent_class; + + void (* setup_offscreen_blit_pipeline) (ClutterStageView *view, + CoglPipeline *pipeline); + + void (* get_offscreen_transformation_matrix) (ClutterStageView *view, + CoglMatrix *matrix); +}; + +CLUTTER_AVAILABLE_IN_MUTTER +void clutter_stage_view_get_layout (ClutterStageView *view, + cairo_rectangle_int_t *rect); + +CLUTTER_AVAILABLE_IN_MUTTER +CoglFramebuffer *clutter_stage_view_get_framebuffer (ClutterStageView *view); +CLUTTER_AVAILABLE_IN_MUTTER +CoglFramebuffer *clutter_stage_view_get_onscreen (ClutterStageView *view); +CLUTTER_AVAILABLE_IN_MUTTER +void clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view); + +CLUTTER_AVAILABLE_IN_MUTTER +void clutter_stage_view_transform_to_onscreen (ClutterStageView *view, + gfloat *x, + gfloat *y); + +void clutter_stage_view_blit_offscreen (ClutterStageView *view, + const cairo_rectangle_int_t *clip); + +gboolean clutter_stage_view_is_dirty_viewport (ClutterStageView *view); + +void clutter_stage_view_set_dirty_viewport (ClutterStageView *view, + gboolean dirty); + +gboolean clutter_stage_view_is_dirty_projection (ClutterStageView *view); + +void clutter_stage_view_set_dirty_projection (ClutterStageView *view, + gboolean dirty); + +#endif /* __CLUTTER_STAGE_VIEW_H__ */ diff --git a/clutter/clutter/clutter-stage-window.c b/clutter/clutter/clutter-stage-window.c new file mode 100644 index 0000000..97eb5e4 --- /dev/null +++ b/clutter/clutter/clutter-stage-window.c @@ -0,0 +1,359 @@ +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#include "clutter-actor.h" +#include "clutter-stage-window.h" +#include "clutter-private.h" + +#define clutter_stage_window_get_type _clutter_stage_window_get_type + +typedef ClutterStageWindowIface ClutterStageWindowInterface; + +G_DEFINE_INTERFACE (ClutterStageWindow, clutter_stage_window, G_TYPE_OBJECT); + +static void +clutter_stage_window_default_init (ClutterStageWindowInterface *iface) +{ + GParamSpec *pspec; + + pspec = g_param_spec_object ("backend", + "Backend", + "Back pointer to the Backend instance", + CLUTTER_TYPE_BACKEND, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + g_object_interface_install_property (iface, pspec); + + pspec = g_param_spec_object ("wrapper", + "Wrapper", + "Back pointer to the Stage actor", + CLUTTER_TYPE_STAGE, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + g_object_interface_install_property (iface, pspec); +} + +ClutterActor * +_clutter_stage_window_get_wrapper (ClutterStageWindow *window) +{ + return CLUTTER_STAGE_WINDOW_GET_IFACE (window)->get_wrapper (window); +} + +void +_clutter_stage_window_set_title (ClutterStageWindow *window, + const gchar *title) +{ + ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); + + if (iface->set_title) + iface->set_title (window, title); +} + +void +_clutter_stage_window_set_fullscreen (ClutterStageWindow *window, + gboolean is_fullscreen) +{ + ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); + + if (iface->set_fullscreen) + iface->set_fullscreen (window, is_fullscreen); +} + +void +_clutter_stage_window_set_cursor_visible (ClutterStageWindow *window, + gboolean is_visible) +{ + ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); + + if (iface->set_cursor_visible) + iface->set_cursor_visible (window, is_visible); +} + +void +_clutter_stage_window_set_user_resizable (ClutterStageWindow *window, + gboolean is_resizable) +{ + CLUTTER_STAGE_WINDOW_GET_IFACE (window)->set_user_resizable (window, + is_resizable); +} + +gboolean +_clutter_stage_window_realize (ClutterStageWindow *window) +{ + return CLUTTER_STAGE_WINDOW_GET_IFACE (window)->realize (window); +} + +void +_clutter_stage_window_unrealize (ClutterStageWindow *window) +{ + CLUTTER_STAGE_WINDOW_GET_IFACE (window)->unrealize (window); +} + +void +_clutter_stage_window_show (ClutterStageWindow *window, + gboolean do_raise) +{ + CLUTTER_STAGE_WINDOW_GET_IFACE (window)->show (window, do_raise); +} + +void +_clutter_stage_window_hide (ClutterStageWindow *window) +{ + CLUTTER_STAGE_WINDOW_GET_IFACE (window)->hide (window); +} + +void +_clutter_stage_window_resize (ClutterStageWindow *window, + gint width, + gint height) +{ + CLUTTER_STAGE_WINDOW_GET_IFACE (window)->resize (window, width, height); +} + +void +_clutter_stage_window_get_geometry (ClutterStageWindow *window, + cairo_rectangle_int_t *geometry) +{ + CLUTTER_STAGE_WINDOW_GET_IFACE (window)->get_geometry (window, geometry); +} + +void +_clutter_stage_window_schedule_update (ClutterStageWindow *window, + int sync_delay) +{ + ClutterStageWindowIface *iface; + + g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window)); + + iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); + if (iface->schedule_update == NULL) + { + g_assert (!clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS)); + return; + } + + iface->schedule_update (window, sync_delay); +} + +gint64 +_clutter_stage_window_get_update_time (ClutterStageWindow *window) +{ + ClutterStageWindowIface *iface; + + g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), 0); + + iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); + if (iface->get_update_time == NULL) + { + g_assert (!clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS)); + return 0; + } + + return iface->get_update_time (window); +} + +void +_clutter_stage_window_clear_update_time (ClutterStageWindow *window) +{ + ClutterStageWindowIface *iface; + + g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window)); + + iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); + if (iface->clear_update_time == NULL) + { + g_assert (!clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS)); + return; + } + + iface->clear_update_time (window); +} + +void +_clutter_stage_window_add_redraw_clip (ClutterStageWindow *window, + cairo_rectangle_int_t *stage_clip) +{ + ClutterStageWindowIface *iface; + + g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window)); + + iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); + if (iface->add_redraw_clip != NULL) + iface->add_redraw_clip (window, stage_clip); +} + +/* Determines if the backend will clip the rendering of the next + * frame. + * + * Note: at the start of each new frame there is an implied clip that + * clips everything (i.e. nothing would be drawn) so this function + * will return True at the start of a new frame if the backend + * supports clipped redraws. + */ +gboolean +_clutter_stage_window_has_redraw_clips (ClutterStageWindow *window) +{ + ClutterStageWindowIface *iface; + + g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), FALSE); + + iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); + if (iface->has_redraw_clips != NULL) + return iface->has_redraw_clips (window); + + return FALSE; +} + +/* Determines if the backend will discard any additional redraw clips + * and instead promote them to a full stage redraw. + * + * The ideas is that backend may have some heuristics that cause it to + * give up tracking redraw clips so this can be used to avoid the cost + * of calculating a redraw clip when we know it's going to be ignored + * anyway. + */ +gboolean +_clutter_stage_window_ignoring_redraw_clips (ClutterStageWindow *window) +{ + ClutterStageWindowIface *iface; + + g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), FALSE); + + iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); + if (iface->ignoring_redraw_clips != NULL) + return iface->ignoring_redraw_clips (window); + + return TRUE; +} + +gboolean +_clutter_stage_window_get_redraw_clip_bounds (ClutterStageWindow *window, + cairo_rectangle_int_t *stage_clip) +{ + ClutterStageWindowIface *iface; + + g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), FALSE); + + iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); + if (iface->get_redraw_clip_bounds != NULL) + return iface->get_redraw_clip_bounds (window, stage_clip); + + return FALSE; +} + +void +_clutter_stage_window_set_accept_focus (ClutterStageWindow *window, + gboolean accept_focus) +{ + ClutterStageWindowIface *iface; + + g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window)); + + iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); + if (iface->set_accept_focus) + iface->set_accept_focus (window, accept_focus); +} + +void +_clutter_stage_window_redraw (ClutterStageWindow *window) +{ + ClutterStageWindowIface *iface; + + g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window)); + + iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); + if (iface->redraw) + iface->redraw (window); +} + + +void +_clutter_stage_window_get_dirty_pixel (ClutterStageWindow *window, + ClutterStageView *view, + int *x, int *y) +{ + ClutterStageWindowIface *iface; + + *x = 0; + *y = 0; + + g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window)); + + iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); + if (iface->get_dirty_pixel) + iface->get_dirty_pixel (window, view, x, y); +} + +gboolean +_clutter_stage_window_can_clip_redraws (ClutterStageWindow *window) +{ + ClutterStageWindowIface *iface; + + g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), FALSE); + + iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); + if (iface->can_clip_redraws != NULL) + return iface->can_clip_redraws (window); + + return FALSE; +} + +void +_clutter_stage_window_set_scale_factor (ClutterStageWindow *window, + int factor) +{ + ClutterStageWindowIface *iface; + + g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window)); + + iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); + if (iface->set_scale_factor != NULL) + iface->set_scale_factor (window, factor); +} + +int +_clutter_stage_window_get_scale_factor (ClutterStageWindow *window) +{ + ClutterStageWindowIface *iface; + + g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), 1); + + iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); + if (iface->get_scale_factor != NULL) + return iface->get_scale_factor (window); + + return 1; +} + +GList * +_clutter_stage_window_get_views (ClutterStageWindow *window) +{ + ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); + + return iface->get_views (window); +} + +void +_clutter_stage_window_finish_frame (ClutterStageWindow *window) +{ + ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); + + if (iface->finish_frame) + iface->finish_frame (window); +} + +int64_t +_clutter_stage_window_get_frame_counter (ClutterStageWindow *window) +{ + ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); + + if (iface->get_frame_counter) + return iface->get_frame_counter (window); + else + return 0; +} diff --git a/clutter/clutter/clutter-stage-window.h b/clutter/clutter/clutter-stage-window.h new file mode 100644 index 0000000..452f9de --- /dev/null +++ b/clutter/clutter/clutter-stage-window.h @@ -0,0 +1,155 @@ +#ifndef __CLUTTER_STAGE_WINDOW_H__ +#define __CLUTTER_STAGE_WINDOW_H__ + +#include +#include +#include "clutter/clutter-stage-view.h" + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_STAGE_WINDOW (_clutter_stage_window_get_type ()) +#define CLUTTER_STAGE_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STAGE_WINDOW, ClutterStageWindow)) +#define CLUTTER_IS_STAGE_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_STAGE_WINDOW)) +#define CLUTTER_STAGE_WINDOW_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), CLUTTER_TYPE_STAGE_WINDOW, ClutterStageWindowIface)) + +/* + * ClutterStageWindow: (skip) + * + * #ClutterStageWindow is an opaque structure + * whose members should not be accessed directly + * + * Since: 0.8 + */ +typedef struct _ClutterStageWindow ClutterStageWindow; /* dummy */ +typedef struct _ClutterStageWindowIface ClutterStageWindowIface; + +/* + * ClutterStageWindowIface: (skip) + * + * The interface implemented by backends for stage windows + * + * Since: 0.8 + */ +struct _ClutterStageWindowIface +{ + /*< private >*/ + GTypeInterface parent_iface; + + ClutterActor *(* get_wrapper) (ClutterStageWindow *stage_window); + + void (* set_title) (ClutterStageWindow *stage_window, + const gchar *title); + void (* set_fullscreen) (ClutterStageWindow *stage_window, + gboolean is_fullscreen); + void (* set_cursor_visible) (ClutterStageWindow *stage_window, + gboolean cursor_visible); + void (* set_user_resizable) (ClutterStageWindow *stage_window, + gboolean is_resizable); + + gboolean (* realize) (ClutterStageWindow *stage_window); + void (* unrealize) (ClutterStageWindow *stage_window); + + void (* show) (ClutterStageWindow *stage_window, + gboolean do_raise); + void (* hide) (ClutterStageWindow *stage_window); + + void (* resize) (ClutterStageWindow *stage_window, + gint width, + gint height); + void (* get_geometry) (ClutterStageWindow *stage_window, + cairo_rectangle_int_t *geometry); + + void (* schedule_update) (ClutterStageWindow *stage_window, + int sync_delay); + gint64 (* get_update_time) (ClutterStageWindow *stage_window); + void (* clear_update_time) (ClutterStageWindow *stage_window); + + void (* add_redraw_clip) (ClutterStageWindow *stage_window, + cairo_rectangle_int_t *stage_rectangle); + gboolean (* has_redraw_clips) (ClutterStageWindow *stage_window); + gboolean (* ignoring_redraw_clips) (ClutterStageWindow *stage_window); + gboolean (* get_redraw_clip_bounds) (ClutterStageWindow *stage_window, + cairo_rectangle_int_t *clip); + + + void (* set_accept_focus) (ClutterStageWindow *stage_window, + gboolean accept_focus); + + void (* redraw) (ClutterStageWindow *stage_window); + + void (* get_dirty_pixel) (ClutterStageWindow *stage_window, + ClutterStageView *view, + int *x, int *y); + + gboolean (* can_clip_redraws) (ClutterStageWindow *stage_window); + + void (* set_scale_factor) (ClutterStageWindow *stage_window, + int factor); + int (* get_scale_factor) (ClutterStageWindow *stage_window); + GList *(* get_views) (ClutterStageWindow *stage_window); + int64_t (* get_frame_counter) (ClutterStageWindow *stage_window); + void (* finish_frame) (ClutterStageWindow *stage_window); +}; + +CLUTTER_AVAILABLE_IN_MUTTER +GType _clutter_stage_window_get_type (void) G_GNUC_CONST; + +ClutterActor * _clutter_stage_window_get_wrapper (ClutterStageWindow *window); + +void _clutter_stage_window_set_title (ClutterStageWindow *window, + const gchar *title); +void _clutter_stage_window_set_fullscreen (ClutterStageWindow *window, + gboolean is_fullscreen); +void _clutter_stage_window_set_cursor_visible (ClutterStageWindow *window, + gboolean is_visible); +void _clutter_stage_window_set_user_resizable (ClutterStageWindow *window, + gboolean is_resizable); + +gboolean _clutter_stage_window_realize (ClutterStageWindow *window); +void _clutter_stage_window_unrealize (ClutterStageWindow *window); + +void _clutter_stage_window_show (ClutterStageWindow *window, + gboolean do_raise); +void _clutter_stage_window_hide (ClutterStageWindow *window); + +void _clutter_stage_window_resize (ClutterStageWindow *window, + gint width, + gint height); +void _clutter_stage_window_get_geometry (ClutterStageWindow *window, + cairo_rectangle_int_t *geometry); +void _clutter_stage_window_schedule_update (ClutterStageWindow *window, + int sync_delay); +gint64 _clutter_stage_window_get_update_time (ClutterStageWindow *window); +void _clutter_stage_window_clear_update_time (ClutterStageWindow *window); + +void _clutter_stage_window_add_redraw_clip (ClutterStageWindow *window, + cairo_rectangle_int_t *stage_clip); +gboolean _clutter_stage_window_has_redraw_clips (ClutterStageWindow *window); +gboolean _clutter_stage_window_ignoring_redraw_clips (ClutterStageWindow *window); +gboolean _clutter_stage_window_get_redraw_clip_bounds (ClutterStageWindow *window, + cairo_rectangle_int_t *clip); + +void _clutter_stage_window_set_accept_focus (ClutterStageWindow *window, + gboolean accept_focus); + +void _clutter_stage_window_redraw (ClutterStageWindow *window); + +void _clutter_stage_window_get_dirty_pixel (ClutterStageWindow *window, + ClutterStageView *view, + int *x, int *y); + +gboolean _clutter_stage_window_can_clip_redraws (ClutterStageWindow *window); + +void _clutter_stage_window_set_scale_factor (ClutterStageWindow *window, + int factor); +int _clutter_stage_window_get_scale_factor (ClutterStageWindow *window); + +GList * _clutter_stage_window_get_views (ClutterStageWindow *window); + +void _clutter_stage_window_finish_frame (ClutterStageWindow *window); + +int64_t _clutter_stage_window_get_frame_counter (ClutterStageWindow *window); + +G_END_DECLS + +#endif /* __CLUTTER_STAGE_WINDOW_H__ */ diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c new file mode 100644 index 0000000..21968b9 --- /dev/null +++ b/clutter/clutter/clutter-stage.c @@ -0,0 +1,4772 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +/** + * SECTION:clutter-stage + * @short_description: Top level visual element to which actors are placed. + * + * #ClutterStage is a top level 'window' on which child actors are placed + * and manipulated. + * + * Backends might provide support for multiple stages. The support for this + * feature can be checked at run-time using the clutter_feature_available() + * function and the %CLUTTER_FEATURE_STAGE_MULTIPLE flag. If the backend used + * supports multiple stages, new #ClutterStage instances can be created + * using clutter_stage_new(). These stages must be managed by the developer + * using clutter_actor_destroy(), which will take care of destroying all the + * actors contained inside them. + * + * #ClutterStage is a proxy actor, wrapping the backend-specific + * implementation of the windowing system. It is possible to subclass + * #ClutterStage, as long as every overridden virtual function chains up to + * the parent class corresponding function. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#define CLUTTER_ENABLE_EXPERIMENTAL_API + +#include "clutter-stage.h" +#include "deprecated/clutter-stage.h" +#include "deprecated/clutter-container.h" + +#include "clutter-actor-private.h" +#include "clutter-backend-private.h" +#include "clutter-cairo.h" +#include "clutter-color.h" +#include "clutter-container.h" +#include "clutter-debug.h" +#include "clutter-device-manager-private.h" +#include "clutter-enum-types.h" +#include "clutter-event-private.h" +#include "clutter-id-pool.h" +#include "clutter-main.h" +#include "clutter-marshal.h" +#include "clutter-master-clock.h" +#include "clutter-mutter.h" +#include "clutter-paint-volume-private.h" +#include "clutter-private.h" +#include "clutter-stage-manager-private.h" +#include "clutter-stage-private.h" +#include "clutter-version.h" /* For flavour */ +#include "clutter-private.h" + +#include "cogl/cogl.h" + +/* + * ClutterStageHint: + * @CLUTTER_STAGE_NONE: No hint set + * @CLUTTER_STAGE_NO_CLEAR_ON_PAINT: When this hint is set, the stage + * should not clear the viewport; this flag is useful when painting + * fully opaque actors covering the whole visible area of the stage, + * i.e. when no blending with the stage color happens over the whole + * stage viewport + * + * A series of hints that enable or disable behaviours on the stage + */ +typedef enum { /*< prefix=CLUTTER_STAGE >*/ + CLUTTER_STAGE_HINT_NONE = 0, + + CLUTTER_STAGE_NO_CLEAR_ON_PAINT = 1 << 0 +} ClutterStageHint; + +#define STAGE_NO_CLEAR_ON_PAINT(s) ((((ClutterStage *) (s))->priv->stage_hints & CLUTTER_STAGE_NO_CLEAR_ON_PAINT) != 0) + +struct _ClutterStageQueueRedrawEntry +{ + ClutterActor *actor; + gboolean has_clip; + ClutterPaintVolume clip; +}; + +struct _ClutterStagePrivate +{ + /* the stage implementation */ + ClutterStageWindow *impl; + + ClutterPerspective perspective; + CoglMatrix projection; + CoglMatrix inverse_projection; + CoglMatrix view; + float viewport[4]; + + ClutterFog fog; + + gchar *title; + ClutterActor *key_focused_actor; + + GQueue *event_queue; + + ClutterStageHint stage_hints; + + GArray *paint_volume_stack; + + ClutterPlane current_clip_planes[4]; + + GList *pending_queue_redraws; + + CoglFramebuffer *active_framebuffer; + + gint sync_delay; + + GTimer *fps_timer; + gint32 timer_n_frames; + + ClutterIDPool *pick_id_pool; + +#ifdef CLUTTER_ENABLE_DEBUG + gulong redraw_count; +#endif /* CLUTTER_ENABLE_DEBUG */ + + ClutterStageState current_state; + + gpointer paint_data; + GDestroyNotify paint_notify; + + guint relayout_pending : 1; + guint redraw_pending : 1; + guint is_fullscreen : 1; + guint is_cursor_visible : 1; + guint is_user_resizable : 1; + guint use_fog : 1; + guint throttle_motion_events : 1; + guint use_alpha : 1; + guint min_size_changed : 1; + guint accept_focus : 1; + guint motion_events_enabled : 1; + guint has_custom_perspective : 1; +}; + +enum +{ + PROP_0, + + PROP_COLOR, + PROP_FULLSCREEN_SET, + PROP_OFFSCREEN, + PROP_CURSOR_VISIBLE, + PROP_PERSPECTIVE, + PROP_TITLE, + PROP_USER_RESIZABLE, + PROP_USE_FOG, + PROP_FOG, + PROP_USE_ALPHA, + PROP_KEY_FOCUS, + PROP_NO_CLEAR_HINT, + PROP_ACCEPT_FOCUS +}; + +enum +{ + FULLSCREEN, + UNFULLSCREEN, + ACTIVATE, + DEACTIVATE, + DELETE_EVENT, + AFTER_PAINT, + PRESENTED, + + LAST_SIGNAL +}; + +static guint stage_signals[LAST_SIGNAL] = { 0, }; + +static const ClutterColor default_stage_color = { 255, 255, 255, 255 }; + +static void clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage); +static void free_queue_redraw_entry (ClutterStageQueueRedrawEntry *entry); + +static void clutter_container_iface_init (ClutterContainerIface *iface); + +G_DEFINE_TYPE_WITH_CODE (ClutterStage, clutter_stage, CLUTTER_TYPE_GROUP, + G_ADD_PRIVATE (ClutterStage) + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER, + clutter_container_iface_init)) + +static void +clutter_stage_real_add (ClutterContainer *container, + ClutterActor *child) +{ + clutter_actor_add_child (CLUTTER_ACTOR (container), child); +} + +static void +clutter_stage_real_remove (ClutterContainer *container, + ClutterActor *child) +{ + clutter_actor_remove_child (CLUTTER_ACTOR (container), child); +} + +static void +clutter_stage_real_foreach (ClutterContainer *container, + ClutterCallback callback, + gpointer user_data) +{ + ClutterActorIter iter; + ClutterActor *child; + + clutter_actor_iter_init (&iter, CLUTTER_ACTOR (container)); + + while (clutter_actor_iter_next (&iter, &child)) + callback (child, user_data); +} + +static void +clutter_stage_real_raise (ClutterContainer *container, + ClutterActor *child, + ClutterActor *sibling) +{ + clutter_actor_set_child_above_sibling (CLUTTER_ACTOR (container), + child, + sibling); +} + +static void +clutter_stage_real_lower (ClutterContainer *container, + ClutterActor *child, + ClutterActor *sibling) +{ + clutter_actor_set_child_below_sibling (CLUTTER_ACTOR (container), + child, + sibling); +} + +static void +clutter_stage_real_sort_depth_order (ClutterContainer *container) +{ +} + +static void +clutter_container_iface_init (ClutterContainerIface *iface) +{ + iface->add = clutter_stage_real_add; + iface->remove = clutter_stage_real_remove; + iface->foreach = clutter_stage_real_foreach; + iface->raise = clutter_stage_real_raise; + iface->lower = clutter_stage_real_lower; + iface->sort_depth_order = clutter_stage_real_sort_depth_order; +} + +static void +clutter_stage_get_preferred_width (ClutterActor *self, + gfloat for_height, + gfloat *min_width_p, + gfloat *natural_width_p) +{ + ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv; + cairo_rectangle_int_t geom; + + if (priv->impl == NULL) + return; + + _clutter_stage_window_get_geometry (priv->impl, &geom); + + if (min_width_p) + *min_width_p = geom.width; + + if (natural_width_p) + *natural_width_p = geom.width; +} + +static void +clutter_stage_get_preferred_height (ClutterActor *self, + gfloat for_width, + gfloat *min_height_p, + gfloat *natural_height_p) +{ + ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv; + cairo_rectangle_int_t geom; + + if (priv->impl == NULL) + return; + + _clutter_stage_window_get_geometry (priv->impl, &geom); + + if (min_height_p) + *min_height_p = geom.height; + + if (natural_height_p) + *natural_height_p = geom.height; +} + +static inline void +queue_full_redraw (ClutterStage *stage) +{ + ClutterStageWindow *stage_window; + + if (CLUTTER_ACTOR_IN_DESTRUCTION (stage)) + return; + + clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); + + /* Just calling clutter_actor_queue_redraw will typically only + * redraw the bounding box of the children parented on the stage but + * in this case we really need to ensure that the full stage is + * redrawn so we add a NULL redraw clip to the stage window. */ + stage_window = _clutter_stage_get_window (stage); + if (stage_window == NULL) + return; + + _clutter_stage_window_add_redraw_clip (stage_window, NULL); +} + +static gboolean +stage_is_default (ClutterStage *stage) +{ + ClutterStageManager *stage_manager; + ClutterStageWindow *impl; + + stage_manager = clutter_stage_manager_get_default (); + if (stage != clutter_stage_manager_get_default_stage (stage_manager)) + return FALSE; + + impl = _clutter_stage_get_window (stage); + if (impl != _clutter_stage_get_default_window ()) + return FALSE; + + return TRUE; +} + +static void +clutter_stage_allocate (ClutterActor *self, + const ClutterActorBox *box, + ClutterAllocationFlags flags) +{ + ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv; + ClutterActorBox alloc = CLUTTER_ACTOR_BOX_INIT_ZERO; + float old_width, old_height; + float new_width, new_height; + float width, height; + cairo_rectangle_int_t window_size; + int scale_factor; + + if (priv->impl == NULL) + return; + + /* our old allocation */ + clutter_actor_get_allocation_box (self, &alloc); + clutter_actor_box_get_size (&alloc, &old_width, &old_height); + + /* the current allocation */ + clutter_actor_box_get_size (box, &width, &height); + + /* the current Stage implementation size */ + _clutter_stage_window_get_geometry (priv->impl, &window_size); + + /* if the stage is fixed size (for instance, it's using a EGL framebuffer) + * then we simply ignore any allocation request and override the + * allocation chain - because we cannot forcibly change the size of the + * stage window. + */ + if (!clutter_feature_available (CLUTTER_FEATURE_STAGE_STATIC)) + { + CLUTTER_NOTE (LAYOUT, + "Following allocation to %.2fx%.2f (absolute origin %s)", + width, height, + (flags & CLUTTER_ABSOLUTE_ORIGIN_CHANGED) + ? "changed" + : "not changed"); + + clutter_actor_set_allocation (self, box, + flags | CLUTTER_DELEGATE_LAYOUT); + + /* Ensure the window is sized correctly */ + if (!priv->is_fullscreen) + { + if (priv->min_size_changed) + { + gfloat min_width, min_height; + gboolean min_width_set, min_height_set; + + g_object_get (G_OBJECT (self), + "min-width", &min_width, + "min-width-set", &min_width_set, + "min-height", &min_height, + "min-height-set", &min_height_set, + NULL); + + if (!min_width_set) + min_width = 1; + if (!min_height_set) + min_height = 1; + + if (width < min_width) + width = min_width; + if (height < min_height) + height = min_height; + + priv->min_size_changed = FALSE; + } + + if (window_size.width != CLUTTER_NEARBYINT (width) || + window_size.height != CLUTTER_NEARBYINT (height)) + { + _clutter_stage_window_resize (priv->impl, + CLUTTER_NEARBYINT (width), + CLUTTER_NEARBYINT (height)); + } + } + } + else + { + ClutterActorBox override = { 0, }; + + /* override the passed allocation */ + override.x1 = 0; + override.y1 = 0; + override.x2 = window_size.width; + override.y2 = window_size.height; + + CLUTTER_NOTE (LAYOUT, + "Overriding original allocation of %.2fx%.2f " + "with %.2fx%.2f (absolute origin %s)", + width, height, + override.x2, override.y2, + (flags & CLUTTER_ABSOLUTE_ORIGIN_CHANGED) + ? "changed" + : "not changed"); + + /* and store the overridden allocation */ + clutter_actor_set_allocation (self, &override, + flags | CLUTTER_DELEGATE_LAYOUT); + } + + /* XXX: Until Cogl becomes fully responsible for backend windows + * Clutter need to manually keep it informed of the current window + * size. We do this after the allocation above so that the stage + * window has a chance to update the window size based on the + * allocation. + */ + _clutter_stage_window_get_geometry (priv->impl, &window_size); + + scale_factor = _clutter_stage_window_get_scale_factor (priv->impl); + + window_size.width *= scale_factor; + window_size.height *= scale_factor; + + cogl_onscreen_clutter_backend_set_size (window_size.width, + window_size.height); + + /* reset the viewport if the allocation effectively changed */ + clutter_actor_get_allocation_box (self, &alloc); + clutter_actor_box_get_size (&alloc, &new_width, &new_height); + + if (CLUTTER_NEARBYINT (old_width) != CLUTTER_NEARBYINT (new_width) || + CLUTTER_NEARBYINT (old_height) != CLUTTER_NEARBYINT (new_height)) + { + int real_width = CLUTTER_NEARBYINT (new_width); + int real_height = CLUTTER_NEARBYINT (new_height); + + _clutter_stage_set_viewport (CLUTTER_STAGE (self), + 0, 0, + real_width, + real_height); + + /* Note: we don't assume that set_viewport will queue a full redraw + * since it may bail-out early if something preemptively set the + * viewport before the stage was really allocated its new size. + */ + queue_full_redraw (CLUTTER_STAGE (self)); + } +} + +typedef struct _Vector4 +{ + float x, y, z, w; +} Vector4; + +static void +_cogl_util_get_eye_planes_for_screen_poly (float *polygon, + int n_vertices, + float *viewport, + const CoglMatrix *projection, + const CoglMatrix *inverse_project, + ClutterPlane *planes) +{ + float Wc; + Vector4 *tmp_poly; + ClutterPlane *plane; + int i; + float b[3]; + float c[3]; + int count; + + tmp_poly = g_alloca (sizeof (Vector4) * n_vertices * 2); + +#define DEPTH -50 + + /* Determine W in clip-space (Wc) for a point (0, 0, DEPTH, 1) + * + * Note: the depth could be anything except 0. + * + * We will transform the polygon into clip coordinates using this + * depth and then into eye coordinates. Our clip planes will be + * defined by triangles that extend between points of the polygon at + * DEPTH and corresponding points of the same polygon at DEPTH * 2. + * + * NB: Wc defines the position of the clip planes in clip + * coordinates. Given a screen aligned cross section through the + * frustum; coordinates range from [-Wc,Wc] left to right on the + * x-axis and [Wc,-Wc] top to bottom on the y-axis. + */ + Wc = DEPTH * projection->wz + projection->ww; + +#define CLIP_X(X) ((((float)X - viewport[0]) * (2.0 / viewport[2])) - 1) * Wc +#define CLIP_Y(Y) ((((float)Y - viewport[1]) * (2.0 / viewport[3])) - 1) * -Wc + + for (i = 0; i < n_vertices; i++) + { + tmp_poly[i].x = CLIP_X (polygon[i * 2]); + tmp_poly[i].y = CLIP_Y (polygon[i * 2 + 1]); + tmp_poly[i].z = DEPTH; + tmp_poly[i].w = Wc; + } + + Wc = DEPTH * 2 * projection->wz + projection->ww; + + /* FIXME: technically we don't need to project all of the points + * twice, it would be enough project every other point since + * we can share points in this set to define the plane vectors. */ + for (i = 0; i < n_vertices; i++) + { + tmp_poly[n_vertices + i].x = CLIP_X (polygon[i * 2]); + tmp_poly[n_vertices + i].y = CLIP_Y (polygon[i * 2 + 1]); + tmp_poly[n_vertices + i].z = DEPTH * 2; + tmp_poly[n_vertices + i].w = Wc; + } + +#undef CLIP_X +#undef CLIP_Y + + cogl_matrix_project_points (inverse_project, + 4, + sizeof (Vector4), + tmp_poly, + sizeof (Vector4), + tmp_poly, + n_vertices * 2); + + /* XXX: It's quite ugly that we end up with these casts between + * Vector4 types and CoglVector3s, it might be better if the + * cogl_vector APIs just took pointers to floats. + */ + + count = n_vertices - 1; + for (i = 0; i < count; i++) + { + plane = &planes[i]; + memcpy (plane->v0, tmp_poly + i, sizeof (float) * 3); + memcpy (b, tmp_poly + n_vertices + i, sizeof (float) * 3); + memcpy (c, tmp_poly + n_vertices + i + 1, sizeof (float) * 3); + cogl_vector3_subtract (b, b, plane->v0); + cogl_vector3_subtract (c, c, plane->v0); + cogl_vector3_cross_product (plane->n, b, c); + cogl_vector3_normalize (plane->n); + } + + plane = &planes[n_vertices - 1]; + memcpy (plane->v0, tmp_poly + 0, sizeof (float) * 3); + memcpy (b, tmp_poly + (2 * n_vertices - 1), sizeof (float) * 3); + memcpy (c, tmp_poly + n_vertices, sizeof (float) * 3); + cogl_vector3_subtract (b, b, plane->v0); + cogl_vector3_subtract (c, c, plane->v0); + cogl_vector3_cross_product (plane->n, b, c); + cogl_vector3_normalize (plane->n); +} + +static void +_clutter_stage_update_active_framebuffer (ClutterStage *stage, + CoglFramebuffer *framebuffer) +{ + ClutterStagePrivate *priv = stage->priv; + + /* We track the CoglFramebuffer that corresponds to the stage itself + * so, for example, we can disable culling when rendering to an + * offscreen framebuffer. + */ + + priv->active_framebuffer = framebuffer; +} + +/* XXX: Instead of having a toplevel 2D clip region, it might be + * better to have a clip volume within the view frustum. This could + * allow us to avoid projecting actors into window coordinates to + * be able to cull them. + */ +static void +clutter_stage_do_paint_view (ClutterStage *stage, + ClutterStageView *view, + const cairo_rectangle_int_t *clip) +{ + ClutterStagePrivate *priv = stage->priv; + CoglFramebuffer *framebuffer = clutter_stage_view_get_framebuffer (view); + cairo_rectangle_int_t view_layout; + float clip_poly[8]; + float viewport[4]; + cairo_rectangle_int_t geom; + int window_scale; + + _clutter_stage_window_get_geometry (priv->impl, &geom); + window_scale = _clutter_stage_window_get_scale_factor (priv->impl); + + viewport[0] = priv->viewport[0] * window_scale; + viewport[1] = priv->viewport[1] * window_scale; + viewport[2] = priv->viewport[2] * window_scale; + viewport[3] = priv->viewport[3] * window_scale; + + if (!clip) + { + clutter_stage_view_get_layout (view, &view_layout); + clip = &view_layout; + } + + clip_poly[0] = MAX (clip->x * window_scale, 0); + clip_poly[1] = MAX (clip->y * window_scale, 0); + + clip_poly[2] = MIN ((clip->x + clip->width) * window_scale, + geom.width * window_scale); + clip_poly[3] = clip_poly[1]; + + clip_poly[4] = clip_poly[2]; + clip_poly[5] = MIN ((clip->y + clip->height) * window_scale, + geom.height * window_scale); + + clip_poly[6] = clip_poly[0]; + clip_poly[7] = clip_poly[5]; + + CLUTTER_NOTE (CLIPPING, "Setting stage clip too: " + "x=%f, y=%f, width=%f, height=%f", + clip_poly[0], clip_poly[1], + clip_poly[2] - clip_poly[0], + clip_poly[5] - clip_poly[1]); + + _cogl_util_get_eye_planes_for_screen_poly (clip_poly, + 4, + viewport, + &priv->projection, + &priv->inverse_projection, + priv->current_clip_planes); + + _clutter_stage_paint_volume_stack_free_all (stage); + _clutter_stage_update_active_framebuffer (stage, framebuffer); + clutter_actor_paint (CLUTTER_ACTOR (stage)); +} + +/* This provides a common point of entry for painting the scenegraph + * for picking or painting... + */ +void +_clutter_stage_paint_view (ClutterStage *stage, + ClutterStageView *view, + const cairo_rectangle_int_t *clip) +{ + ClutterStagePrivate *priv = stage->priv; + + if (!priv->impl) + return; + + clutter_stage_do_paint_view (stage, view, clip); + g_signal_emit (stage, stage_signals[AFTER_PAINT], 0); +} + +/* If we don't implement this here, we get the paint function + * from the deprecated clutter-group class, which doesn't + * respect the Z order as it uses our empty sort_depth_order. + */ +static void +clutter_stage_paint (ClutterActor *self) +{ + ClutterActorIter iter; + ClutterActor *child; + + clutter_actor_iter_init (&iter, self); + while (clutter_actor_iter_next (&iter, &child)) + clutter_actor_paint (child); +} + +static void +clutter_stage_pick (ClutterActor *self, + const ClutterColor *color) +{ + ClutterActorIter iter; + ClutterActor *child; + + /* Note: we don't chain up to our parent as we don't want any geometry + * emitted for the stage itself. The stage's pick id is effectively handled + * by the call to cogl_clear done in clutter-main.c:_clutter_do_pick_async() + */ + clutter_actor_iter_init (&iter, self); + while (clutter_actor_iter_next (&iter, &child)) + clutter_actor_paint (child); +} + +static gboolean +clutter_stage_get_paint_volume (ClutterActor *self, + ClutterPaintVolume *volume) +{ + /* Returning False effectively means Clutter has to assume it covers + * everything... */ + return FALSE; +} + +static void +clutter_stage_realize (ClutterActor *self) +{ + ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv; + gboolean is_realized; + + g_assert (priv->impl != NULL); + is_realized = _clutter_stage_window_realize (priv->impl); + + if (!is_realized) + CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED); +} + +static void +clutter_stage_unrealize (ClutterActor *self) +{ + ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv; + + /* and then unrealize the implementation */ + g_assert (priv->impl != NULL); + _clutter_stage_window_unrealize (priv->impl); + + CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED); +} + +static void +clutter_stage_show_all (ClutterActor *self) +{ + ClutterActorIter iter; + ClutterActor *child; + + /* we don't do a recursive show_all(), to maintain the old + * invariants from ClutterGroup + */ + clutter_actor_iter_init (&iter, self); + while (clutter_actor_iter_next (&iter, &child)) + clutter_actor_show (child); + + clutter_actor_show (self); +} + +static void +clutter_stage_show (ClutterActor *self) +{ + ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv; + + CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->show (self); + + /* Possibly do an allocation run so that the stage will have the + right size before we map it */ + _clutter_stage_maybe_relayout (self); + + g_assert (priv->impl != NULL); + _clutter_stage_window_show (priv->impl, TRUE); +} + +static void +clutter_stage_hide_all (ClutterActor *self) +{ + ClutterActorIter iter; + ClutterActor *child; + + clutter_actor_hide (self); + + /* we don't do a recursive hide_all(), to maintain the old invariants + * from ClutterGroup + */ + clutter_actor_iter_init (&iter, self); + while (clutter_actor_iter_next (&iter, &child)) + clutter_actor_hide (child); +} + +static void +clutter_stage_hide (ClutterActor *self) +{ + ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv; + + g_assert (priv->impl != NULL); + _clutter_stage_window_hide (priv->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"); + + g_object_notify (G_OBJECT (stage), "key-focus"); +} + +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; + cairo_rectangle_int_t geom; + ClutterActorBox box; + + /* we need to force an allocation here because the size + * of the stage might have been changed by the backend + * + * this is a really bad solution to the issues caused by + * the fact that fullscreening the stage on the X11 backends + * is really an asynchronous operation + */ + _clutter_stage_window_get_geometry (priv->impl, &geom); + + box.x1 = 0; + box.y1 = 0; + box.x2 = geom.width; + box.y2 = geom.height; + + /* we need to blow the caching on the Stage size, given that + * we're about to force an allocation, because if anything + * ends up querying the size of the stage during the allocate() + * call, like constraints or signal handlers, we'll get into an + * inconsistent state: the stage will report the old cached size, + * but the allocation will be updated anyway. + */ + clutter_actor_set_size (CLUTTER_ACTOR (stage), -1.0, -1.0); + clutter_actor_allocate (CLUTTER_ACTOR (stage), + &box, + CLUTTER_ALLOCATION_NONE); +} + +void +_clutter_stage_queue_event (ClutterStage *stage, + ClutterEvent *event, + gboolean copy_event) +{ + ClutterStagePrivate *priv; + gboolean first_event; + ClutterInputDevice *device; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + priv = stage->priv; + + first_event = priv->event_queue->length == 0; + + if (copy_event) + event = clutter_event_copy (event); + + g_queue_push_tail (priv->event_queue, event); + + if (first_event) + { + ClutterMasterClock *master_clock = _clutter_master_clock_get_default (); + _clutter_master_clock_start_running (master_clock); + _clutter_stage_schedule_update (stage); + } + + /* if needed, update the state of the input device of the event. + * we do it here to avoid calling the same code from every backend + * event processing function + */ + device = clutter_event_get_device (event); + if (device != NULL && + event->type != CLUTTER_PROXIMITY_IN && + event->type != CLUTTER_PROXIMITY_OUT) + { + ClutterModifierType event_state = clutter_event_get_state (event); + ClutterEventSequence *sequence = clutter_event_get_event_sequence (event); + guint32 event_time = clutter_event_get_time (event); + gfloat event_x, event_y; + + clutter_event_get_coords (event, &event_x, &event_y); + + _clutter_input_device_set_coords (device, sequence, event_x, event_y, stage); + _clutter_input_device_set_state (device, event_state); + _clutter_input_device_set_time (device, event_time); + } +} + +gboolean +_clutter_stage_has_queued_events (ClutterStage *stage) +{ + ClutterStagePrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); + + priv = stage->priv; + + return priv->event_queue->length > 0; +} + +void +_clutter_stage_process_queued_events (ClutterStage *stage) +{ + ClutterStagePrivate *priv; + GList *events, *l; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + priv = stage->priv; + + if (priv->event_queue->length == 0) + return; + + /* In case the stage gets destroyed during event processing */ + g_object_ref (stage); + + /* Steal events before starting processing to avoid reentrancy + * issues */ + events = priv->event_queue->head; + priv->event_queue->head = NULL; + priv->event_queue->tail = NULL; + priv->event_queue->length = 0; + + for (l = events; l != NULL; l = l->next) + { + ClutterEvent *event; + ClutterEvent *next_event; + ClutterInputDevice *device; + ClutterInputDevice *next_device; + gboolean check_device = FALSE; + + event = l->data; + next_event = l->next ? l->next->data : NULL; + + device = clutter_event_get_device (event); + + if (next_event != NULL) + next_device = clutter_event_get_device (next_event); + else + next_device = NULL; + + if (device != NULL && next_device != NULL) + check_device = TRUE; + + /* Skip consecutive motion events coming from the same device */ + if (priv->throttle_motion_events && next_event != NULL) + { + if (event->type == CLUTTER_MOTION && + (next_event->type == CLUTTER_MOTION || + next_event->type == CLUTTER_LEAVE) && + (!check_device || (device == next_device))) + { + CLUTTER_NOTE (EVENT, + "Omitting motion event at %d, %d", + (int) event->motion.x, + (int) event->motion.y); + + if (next_event->type == CLUTTER_MOTION) + { + ClutterDeviceManager *device_manager = + clutter_device_manager_get_default (); + + _clutter_device_manager_compress_motion (device_manager, + next_event, event); + } + + goto next_event; + } + else if (event->type == CLUTTER_TOUCH_UPDATE && + next_event->type == CLUTTER_TOUCH_UPDATE && + event->touch.sequence == next_event->touch.sequence && + (!check_device || (device == next_device))) + { + CLUTTER_NOTE (EVENT, + "Omitting touch update event at %d, %d", + (int) event->touch.x, + (int) event->touch.y); + goto next_event; + } + } + + _clutter_process_event (event); + + next_event: + clutter_event_free (event); + } + + g_list_free (events); + + g_object_unref (stage); +} + +/** + * _clutter_stage_needs_update: + * @stage: A #ClutterStage + * + * Determines if _clutter_stage_do_update() needs to be called. + * + * Return value: %TRUE if the stage need layout or painting + */ +gboolean +_clutter_stage_needs_update (ClutterStage *stage) +{ + ClutterStagePrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); + + priv = stage->priv; + + return priv->relayout_pending || priv->redraw_pending; +} + +void +_clutter_stage_maybe_relayout (ClutterActor *actor) +{ + ClutterStage *stage = CLUTTER_STAGE (actor); + ClutterStagePrivate *priv = stage->priv; + gfloat natural_width, natural_height; + ClutterActorBox box = { 0, }; + + if (!priv->relayout_pending) + return; + + /* avoid reentrancy */ + if (!CLUTTER_ACTOR_IN_RELAYOUT (stage)) + { + priv->relayout_pending = FALSE; + + CLUTTER_NOTE (ACTOR, "Recomputing layout"); + + CLUTTER_SET_PRIVATE_FLAGS (stage, CLUTTER_IN_RELAYOUT); + + natural_width = natural_height = 0; + clutter_actor_get_preferred_size (CLUTTER_ACTOR (stage), + NULL, NULL, + &natural_width, &natural_height); + + box.x1 = 0; + box.y1 = 0; + box.x2 = natural_width; + box.y2 = natural_height; + + CLUTTER_NOTE (ACTOR, "Allocating (0, 0 - %d, %d) for the stage", + (int) natural_width, + (int) natural_height); + + clutter_actor_allocate (CLUTTER_ACTOR (stage), + &box, CLUTTER_ALLOCATION_NONE); + + CLUTTER_UNSET_PRIVATE_FLAGS (stage, CLUTTER_IN_RELAYOUT); + } +} + +static void +clutter_stage_do_redraw (ClutterStage *stage) +{ + ClutterActor *actor = CLUTTER_ACTOR (stage); + ClutterStagePrivate *priv = stage->priv; + + if (CLUTTER_ACTOR_IN_DESTRUCTION (stage)) + return; + + if (priv->impl == NULL) + return; + + CLUTTER_NOTE (PAINT, "Redraw started for stage '%s'[%p]", + _clutter_actor_get_debug_name (actor), + stage); + + if (_clutter_context_get_show_fps ()) + { + if (priv->fps_timer == NULL) + priv->fps_timer = g_timer_new (); + } + + _clutter_stage_window_redraw (priv->impl); + + if (_clutter_context_get_show_fps ()) + { + priv->timer_n_frames += 1; + + if (g_timer_elapsed (priv->fps_timer, NULL) >= 1.0) + { + g_print ("*** FPS for %s: %i ***\n", + _clutter_actor_get_debug_name (actor), + priv->timer_n_frames); + + priv->timer_n_frames = 0; + g_timer_start (priv->fps_timer); + } + } + + CLUTTER_NOTE (PAINT, "Redraw finished for stage '%s'[%p]", + _clutter_actor_get_debug_name (actor), + stage); +} + +/** + * _clutter_stage_do_update: + * @stage: A #ClutterStage + * + * Handles per-frame layout and repaint for the stage. + * + * Return value: %TRUE if the stage was updated + */ +gboolean +_clutter_stage_do_update (ClutterStage *stage) +{ + ClutterStagePrivate *priv = stage->priv; + + /* if the stage is being destroyed, or if the destruction already + * happened and we don't have an StageWindow any more, then we + * should bail out + */ + if (CLUTTER_ACTOR_IN_DESTRUCTION (stage) || priv->impl == NULL) + return FALSE; + + if (!CLUTTER_ACTOR_IS_REALIZED (stage)) + return FALSE; + + /* NB: We need to ensure we have an up to date layout *before* we + * check or clear the pending redraws flag since a relayout may + * queue a redraw. + */ + _clutter_stage_maybe_relayout (CLUTTER_ACTOR (stage)); + + if (!priv->redraw_pending) + return FALSE; + + clutter_stage_maybe_finish_queue_redraws (stage); + + clutter_stage_do_redraw (stage); + + /* reset the guard, so that new redraws are possible */ + priv->redraw_pending = FALSE; + +#ifdef CLUTTER_ENABLE_DEBUG + if (priv->redraw_count > 0) + { + CLUTTER_NOTE (SCHEDULER, "Queued %lu redraws during the last cycle", + priv->redraw_count); + + priv->redraw_count = 0; + } +#endif /* CLUTTER_ENABLE_DEBUG */ + + return TRUE; +} + +static void +clutter_stage_real_queue_relayout (ClutterActor *self) +{ + ClutterStage *stage = CLUTTER_STAGE (self); + ClutterStagePrivate *priv = stage->priv; + ClutterActorClass *parent_class; + + if (!priv->relayout_pending) + { + _clutter_stage_schedule_update (stage); + priv->relayout_pending = TRUE; + } + + /* chain up */ + parent_class = CLUTTER_ACTOR_CLASS (clutter_stage_parent_class); + parent_class->queue_relayout (self); +} + +static void +clutter_stage_real_queue_redraw (ClutterActor *actor, + ClutterActor *leaf) +{ + ClutterStage *stage = CLUTTER_STAGE (actor); + ClutterStageWindow *stage_window; + ClutterPaintVolume *redraw_clip; + ClutterActorBox bounding_box; + ClutterActorBox intersection_box; + cairo_rectangle_int_t geom, stage_clip; + + if (CLUTTER_ACTOR_IN_DESTRUCTION (actor)) + return; + + /* If the backend can't do anything with redraw clips (e.g. it already knows + * it needs to redraw everything anyway) then don't spend time transforming + * any clip volume into stage coordinates... */ + stage_window = _clutter_stage_get_window (stage); + if (stage_window == NULL) + return; + + if (_clutter_stage_window_ignoring_redraw_clips (stage_window)) + { + _clutter_stage_window_add_redraw_clip (stage_window, NULL); + return; + } + + /* Convert the clip volume into stage coordinates and then into an + * axis aligned stage coordinates bounding box... + */ + redraw_clip = _clutter_actor_get_queue_redraw_clip (leaf); + if (redraw_clip == NULL) + { + _clutter_stage_window_add_redraw_clip (stage_window, NULL); + return; + } + + if (redraw_clip->is_empty) + return; + + _clutter_paint_volume_get_stage_paint_box (redraw_clip, + stage, + &bounding_box); + + _clutter_stage_window_get_geometry (stage_window, &geom); + + intersection_box.x1 = MAX (bounding_box.x1, 0); + intersection_box.y1 = MAX (bounding_box.y1, 0); + intersection_box.x2 = MIN (bounding_box.x2, geom.width); + intersection_box.y2 = MIN (bounding_box.y2, geom.height); + + /* There is no need to track degenerate/empty redraw clips */ + if (intersection_box.x2 <= intersection_box.x1 || + intersection_box.y2 <= intersection_box.y1) + return; + + /* when converting to integer coordinates make sure we round the edges of the + * clip rectangle outwards... */ + stage_clip.x = intersection_box.x1; + stage_clip.y = intersection_box.y1; + stage_clip.width = intersection_box.x2 - stage_clip.x; + stage_clip.height = intersection_box.y2 - stage_clip.y; + + _clutter_stage_window_add_redraw_clip (stage_window, &stage_clip); +} + +gboolean +_clutter_stage_has_full_redraw_queued (ClutterStage *stage) +{ + ClutterStageWindow *stage_window = _clutter_stage_get_window (stage); + + if (CLUTTER_ACTOR_IN_DESTRUCTION (stage) || stage_window == NULL) + return FALSE; + + if (stage->priv->redraw_pending && + !_clutter_stage_window_has_redraw_clips (stage_window)) + return TRUE; + else + return FALSE; +} + +/** + * clutter_stage_get_redraw_clip_bounds: + * @stage: A #ClutterStage + * @clip: (out caller-allocates): Return location for the clip bounds + * + * Gets the bounds of the current redraw for @stage in stage pixel + * coordinates. E.g., if only a single actor has queued a redraw then + * Clutter may redraw the stage with a clip so that it doesn't have to + * paint every pixel in the stage. This function would then return the + * bounds of that clip. An application can use this information to + * avoid some extra work if it knows that some regions of the stage + * aren't going to be painted. This should only be called while the + * stage is being painted. If there is no current redraw clip then + * this function will set @clip to the full extents of the stage. + * + * Since: 1.8 + */ +void +clutter_stage_get_redraw_clip_bounds (ClutterStage *stage, + cairo_rectangle_int_t *clip) +{ + ClutterStagePrivate *priv; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + g_return_if_fail (clip != NULL); + + priv = stage->priv; + + if (!_clutter_stage_window_get_redraw_clip_bounds (priv->impl, clip)) + { + /* Set clip to the full extents of the stage */ + _clutter_stage_window_get_geometry (priv->impl, clip); + } +} + +static void +read_pixels_to_file (char *filename_stem, + int x, + int y, + int width, + int height) +{ + guint8 *data; + cairo_surface_t *surface; + static int read_count = 0; + char *filename = g_strdup_printf ("%s-%05d.png", + filename_stem, + read_count); + + data = g_malloc (4 * width * height); + cogl_read_pixels (x, y, width, height, + COGL_READ_PIXELS_COLOR_BUFFER, + CLUTTER_CAIRO_FORMAT_ARGB32, + data); + + surface = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_RGB24, + width, height, + width * 4); + + cairo_surface_write_to_png (surface, filename); + cairo_surface_destroy (surface); + + g_free (data); + g_free (filename); + + read_count++; +} + +static ClutterActor * +_clutter_stage_do_pick_on_view (ClutterStage *stage, + gint x, + gint y, + ClutterPickMode mode, + ClutterStageView *view) +{ + ClutterActor *actor = CLUTTER_ACTOR (stage); + ClutterStagePrivate *priv = stage->priv; + CoglFramebuffer *fb = clutter_stage_view_get_framebuffer (view); + cairo_rectangle_int_t view_layout; + ClutterMainContext *context; + guchar pixel[4] = { 0xff, 0xff, 0xff, 0xff }; + CoglColor stage_pick_id; + gboolean dither_enabled_save; + ClutterActor *retval; + gint dirty_x; + gint dirty_y; + gint read_x; + gint read_y; + int window_scale; + float fb_width, fb_height; + int viewport_offset_x; + int viewport_offset_y; + + priv = stage->priv; + + context = _clutter_context_get_default (); + window_scale = _clutter_stage_window_get_scale_factor (priv->impl); + clutter_stage_view_get_layout (view, &view_layout); + + fb_width = view_layout.width; + fb_height = view_layout.height; + cogl_push_framebuffer (fb); + + /* needed for when a context switch happens */ + _clutter_stage_maybe_setup_viewport (stage, view); + + /* FIXME: For some reason leaving the cogl clip stack empty causes the + * picking to not work at all, so setting it the whole framebuffer content + * for now. */ + cogl_framebuffer_push_scissor_clip (fb, 0, 0, + view_layout.width, + view_layout.height); + + _clutter_stage_window_get_dirty_pixel (priv->impl, view, &dirty_x, &dirty_y); + + if (G_LIKELY (!(clutter_pick_debug_flags & CLUTTER_DEBUG_DUMP_PICK_BUFFERS))) + { + CLUTTER_NOTE (PICK, "Pushing pick scissor clip x: %d, y: %d, 1x1", + dirty_x * window_scale, + dirty_y * window_scale); + cogl_framebuffer_push_scissor_clip (fb, dirty_x * window_scale, dirty_y * window_scale, 1, 1); + } + + viewport_offset_x = x * window_scale - dirty_x * window_scale; + viewport_offset_y = y * window_scale - dirty_y * window_scale; + CLUTTER_NOTE (PICK, "Setting viewport to %f, %f, %f, %f", + priv->viewport[0] * window_scale - viewport_offset_x, + priv->viewport[1] * window_scale - viewport_offset_y, + priv->viewport[2] * window_scale, + priv->viewport[3] * window_scale); + cogl_set_viewport (priv->viewport[0] * window_scale - viewport_offset_x, + priv->viewport[1] * window_scale - viewport_offset_y, + priv->viewport[2] * window_scale, + priv->viewport[3] * window_scale); + + read_x = dirty_x * window_scale; + read_y = dirty_y * window_scale; + + CLUTTER_NOTE (PICK, "Performing pick at %i,%i on view %dx%d+%d+%d", + x, y, + view_layout.width, view_layout.height, + view_layout.x, view_layout.y); + + cogl_color_init_from_4ub (&stage_pick_id, 255, 255, 255, 255); + cogl_clear (&stage_pick_id, COGL_BUFFER_BIT_COLOR | COGL_BUFFER_BIT_DEPTH); + + /* Disable dithering (if any) when doing the painting in pick mode */ + dither_enabled_save = cogl_framebuffer_get_dither_enabled (fb); + cogl_framebuffer_set_dither_enabled (fb, FALSE); + + /* Render the entire scence in pick mode - just single colored silhouette's + * are drawn offscreen (as we never swap buffers) + */ + context->pick_mode = mode; + _clutter_stage_paint_view (stage, view, NULL); + context->pick_mode = CLUTTER_PICK_NONE; + + /* Read the color of the screen co-ords pixel. RGBA_8888_PRE is used + even though we don't care about the alpha component because under + GLES this is the only format that is guaranteed to work so Cogl + will end up having to do a conversion if any other format is + used. The format is requested as pre-multiplied because Cogl + assumes that all pixels in the framebuffer are premultiplied so + it avoids a conversion. */ + cogl_framebuffer_read_pixels (fb, + read_x, read_y, 1, 1, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + pixel); + + if (G_UNLIKELY (clutter_pick_debug_flags & CLUTTER_DEBUG_DUMP_PICK_BUFFERS)) + { + char *file_name = + g_strdup_printf ("pick-buffer-%s-view-x-%d", + _clutter_actor_get_debug_name (actor), + view_layout.x); + + read_pixels_to_file (file_name, 0, 0, fb_width, fb_height); + + g_free (file_name); + } + + /* Restore whether GL_DITHER was enabled */ + cogl_framebuffer_set_dither_enabled (fb, dither_enabled_save); + + if (G_LIKELY (!(clutter_pick_debug_flags & CLUTTER_DEBUG_DUMP_PICK_BUFFERS))) + cogl_framebuffer_pop_clip (fb); + + cogl_framebuffer_pop_clip (fb); + + _clutter_stage_dirty_viewport (stage); + + if (pixel[0] == 0xff && pixel[1] == 0xff && pixel[2] == 0xff) + retval = actor; + else + { + guint32 id_ = _clutter_pixel_to_id (pixel); + + retval = _clutter_stage_get_actor_by_pick_id (stage, id_); + CLUTTER_NOTE (PICK, "Picking actor %s with id %u (pixel: 0x%x%x%x%x", + G_OBJECT_TYPE_NAME (retval), + id_, + pixel[0], pixel[1], pixel[2], pixel[3]); + } + + cogl_pop_framebuffer (); + + return retval; +} + +static ClutterStageView * +get_view_at (ClutterStage *stage, + int x, + int y) +{ + ClutterStagePrivate *priv = stage->priv; + GList *l; + + for (l = _clutter_stage_window_get_views (priv->impl); l; l = l->next) + { + ClutterStageView *view = l->data; + cairo_rectangle_int_t view_layout; + + clutter_stage_view_get_layout (view, &view_layout); + if (x >= view_layout.x && + x < view_layout.x + view_layout.width && + y >= view_layout.y && + y < view_layout.y + view_layout.height) + return view; + } + + return NULL; +} + +ClutterActor * +_clutter_stage_do_pick (ClutterStage *stage, + gint x, + gint y, + ClutterPickMode mode) +{ + ClutterActor *actor = CLUTTER_ACTOR (stage); + ClutterStagePrivate *priv = stage->priv; + float stage_width, stage_height; + ClutterStageView *view = NULL; + + priv = stage->priv; + + if (CLUTTER_ACTOR_IN_DESTRUCTION (stage)) + return actor; + + if (G_UNLIKELY (clutter_pick_debug_flags & CLUTTER_DEBUG_NOP_PICKING)) + return actor; + + if (G_UNLIKELY (priv->impl == NULL)) + return actor; + + clutter_actor_get_size (CLUTTER_ACTOR (stage), &stage_width, &stage_height); + if (x < 0 || x >= stage_width || y < 0 || y >= stage_height) + return actor; + + view = get_view_at (stage, x, y); + if (view) + return _clutter_stage_do_pick_on_view (stage, x, y, mode, view); + + return actor; +} + +static gboolean +clutter_stage_real_delete_event (ClutterStage *stage, + ClutterEvent *event) +{ + if (stage_is_default (stage)) + clutter_main_quit (); + else + clutter_actor_destroy (CLUTTER_ACTOR (stage)); + + return CLUTTER_EVENT_STOP; +} + +static void +clutter_stage_real_apply_transform (ClutterActor *stage, + CoglMatrix *matrix) +{ + ClutterStagePrivate *priv = CLUTTER_STAGE (stage)->priv; + + /* FIXME: we probably shouldn't be explicitly reseting the matrix + * here... */ + cogl_matrix_init_identity (matrix); + cogl_matrix_multiply (matrix, matrix, &priv->view); +} + +static void +clutter_stage_constructed (GObject *gobject) +{ + ClutterStage *self = CLUTTER_STAGE (gobject); + ClutterStageManager *stage_manager; + + stage_manager = clutter_stage_manager_get_default (); + + /* this will take care to sinking the floating reference */ + _clutter_stage_manager_add_stage (stage_manager, self); + + /* if this stage has been created on a backend that does not + * support multiple stages then it becomes the default stage + * as well; any other attempt at creating a ClutterStage will + * fail. + */ + if (!clutter_feature_available (CLUTTER_FEATURE_STAGE_MULTIPLE)) + { + if (G_UNLIKELY (clutter_stage_manager_get_default_stage (stage_manager) != NULL)) + { + g_error ("Unable to create another stage: the backend of " + "type '%s' does not support multiple stages. Use " + "clutter_stage_manager_get_default_stage() instead " + "to access the stage singleton.", + G_OBJECT_TYPE_NAME (clutter_get_default_backend ())); + } + + _clutter_stage_manager_set_default_stage (stage_manager, self); + } + + G_OBJECT_CLASS (clutter_stage_parent_class)->constructed (gobject); +} + +static void +clutter_stage_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterStage *stage = CLUTTER_STAGE (object); + + switch (prop_id) + { + case PROP_COLOR: + clutter_actor_set_background_color (CLUTTER_ACTOR (stage), + clutter_value_get_color (value)); + break; + + case PROP_OFFSCREEN: + if (g_value_get_boolean (value)) + g_warning ("Offscreen stages are currently not supported\n"); + break; + + case PROP_CURSOR_VISIBLE: + if (g_value_get_boolean (value)) + clutter_stage_show_cursor (stage); + else + clutter_stage_hide_cursor (stage); + break; + + case PROP_PERSPECTIVE: + clutter_stage_set_perspective (stage, g_value_get_boxed (value)); + break; + + case PROP_TITLE: + clutter_stage_set_title (stage, g_value_get_string (value)); + break; + + case PROP_USER_RESIZABLE: + clutter_stage_set_user_resizable (stage, g_value_get_boolean (value)); + break; + + case PROP_USE_FOG: + clutter_stage_set_use_fog (stage, g_value_get_boolean (value)); + break; + + case PROP_FOG: + clutter_stage_set_fog (stage, g_value_get_boxed (value)); + break; + + case PROP_USE_ALPHA: + clutter_stage_set_use_alpha (stage, g_value_get_boolean (value)); + break; + + case PROP_KEY_FOCUS: + clutter_stage_set_key_focus (stage, g_value_get_object (value)); + break; + + case PROP_NO_CLEAR_HINT: + clutter_stage_set_no_clear_hint (stage, g_value_get_boolean (value)); + break; + + case PROP_ACCEPT_FOCUS: + clutter_stage_set_accept_focus (stage, g_value_get_boolean (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_stage_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterStagePrivate *priv = CLUTTER_STAGE (gobject)->priv; + + switch (prop_id) + { + case PROP_COLOR: + { + ClutterColor bg_color; + + clutter_actor_get_background_color (CLUTTER_ACTOR (gobject), + &bg_color); + clutter_value_set_color (value, &bg_color); + } + break; + + case PROP_OFFSCREEN: + g_value_set_boolean (value, FALSE); + break; + + case PROP_FULLSCREEN_SET: + g_value_set_boolean (value, priv->is_fullscreen); + break; + + case PROP_CURSOR_VISIBLE: + g_value_set_boolean (value, priv->is_cursor_visible); + break; + + case PROP_PERSPECTIVE: + g_value_set_boxed (value, &priv->perspective); + break; + + case PROP_TITLE: + g_value_set_string (value, priv->title); + break; + + case PROP_USER_RESIZABLE: + g_value_set_boolean (value, priv->is_user_resizable); + break; + + case PROP_USE_FOG: + g_value_set_boolean (value, priv->use_fog); + break; + + case PROP_FOG: + g_value_set_boxed (value, &priv->fog); + break; + + case PROP_USE_ALPHA: + g_value_set_boolean (value, priv->use_alpha); + break; + + case PROP_KEY_FOCUS: + g_value_set_object (value, priv->key_focused_actor); + break; + + case PROP_NO_CLEAR_HINT: + { + gboolean hint = + (priv->stage_hints & CLUTTER_STAGE_NO_CLEAR_ON_PAINT) != 0; + + g_value_set_boolean (value, hint); + } + break; + + case PROP_ACCEPT_FOCUS: + g_value_set_boolean (value, priv->accept_focus); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_stage_dispose (GObject *object) +{ + ClutterStage *stage = CLUTTER_STAGE (object); + ClutterStagePrivate *priv = stage->priv; + ClutterStageManager *stage_manager; + + clutter_actor_hide (CLUTTER_ACTOR (object)); + + _clutter_clear_events_queue_for_stage (stage); + + if (priv->impl != NULL) + { + CLUTTER_NOTE (BACKEND, "Disposing of the stage implementation"); + + if (CLUTTER_ACTOR_IS_REALIZED (object)) + _clutter_stage_window_unrealize (priv->impl); + + g_object_unref (priv->impl); + priv->impl = NULL; + } + + clutter_actor_destroy_all_children (CLUTTER_ACTOR (object)); + + g_list_free_full (priv->pending_queue_redraws, + (GDestroyNotify) free_queue_redraw_entry); + priv->pending_queue_redraws = NULL; + + /* this will release the reference on the stage */ + stage_manager = clutter_stage_manager_get_default (); + _clutter_stage_manager_remove_stage (stage_manager, stage); + + G_OBJECT_CLASS (clutter_stage_parent_class)->dispose (object); +} + +static void +clutter_stage_finalize (GObject *object) +{ + ClutterStage *stage = CLUTTER_STAGE (object); + ClutterStagePrivate *priv = stage->priv; + + g_queue_foreach (priv->event_queue, (GFunc) clutter_event_free, NULL); + g_queue_free (priv->event_queue); + + g_free (priv->title); + + g_array_free (priv->paint_volume_stack, TRUE); + + _clutter_id_pool_free (priv->pick_id_pool); + + if (priv->fps_timer != NULL) + g_timer_destroy (priv->fps_timer); + + if (priv->paint_notify != NULL) + priv->paint_notify (priv->paint_data); + + G_OBJECT_CLASS (clutter_stage_parent_class)->finalize (object); +} + +static void +clutter_stage_class_init (ClutterStageClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + GParamSpec *pspec; + + gobject_class->constructed = clutter_stage_constructed; + gobject_class->set_property = clutter_stage_set_property; + gobject_class->get_property = clutter_stage_get_property; + gobject_class->dispose = clutter_stage_dispose; + gobject_class->finalize = clutter_stage_finalize; + + actor_class->allocate = clutter_stage_allocate; + actor_class->get_preferred_width = clutter_stage_get_preferred_width; + actor_class->get_preferred_height = clutter_stage_get_preferred_height; + actor_class->paint = clutter_stage_paint; + actor_class->pick = clutter_stage_pick; + actor_class->get_paint_volume = clutter_stage_get_paint_volume; + actor_class->realize = clutter_stage_realize; + actor_class->unrealize = clutter_stage_unrealize; + actor_class->show = clutter_stage_show; + actor_class->show_all = clutter_stage_show_all; + actor_class->hide = clutter_stage_hide; + actor_class->hide_all = clutter_stage_hide_all; + actor_class->queue_relayout = clutter_stage_real_queue_relayout; + actor_class->queue_redraw = clutter_stage_real_queue_redraw; + actor_class->apply_transform = clutter_stage_real_apply_transform; + + /** + * ClutterStage:fullscreen: + * + * Whether the stage should be fullscreen or not. + * + * This property is set by calling clutter_stage_set_fullscreen() + * but since the actual implementation is delegated to the backend + * you should connect to the notify::fullscreen-set signal in order + * to get notification if the fullscreen state has been successfully + * achieved. + * + * Since: 1.0 + */ + pspec = g_param_spec_boolean ("fullscreen-set", + P_("Fullscreen Set"), + P_("Whether the main stage is fullscreen"), + FALSE, + CLUTTER_PARAM_READABLE); + g_object_class_install_property (gobject_class, + PROP_FULLSCREEN_SET, + pspec); + /** + * ClutterStage:offscreen: + * + * Whether the stage should be rendered in an offscreen buffer. + * + * Deprecated: 1.10: This property does not do anything. + */ + pspec = g_param_spec_boolean ("offscreen", + P_("Offscreen"), + P_("Whether the main stage should be rendered offscreen"), + FALSE, + CLUTTER_PARAM_READWRITE | G_PARAM_DEPRECATED); + g_object_class_install_property (gobject_class, + PROP_OFFSCREEN, + pspec); + /** + * ClutterStage:cursor-visible: + * + * Whether the mouse pointer should be visible + */ + pspec = g_param_spec_boolean ("cursor-visible", + P_("Cursor Visible"), + P_("Whether the mouse pointer is visible on the main stage"), + TRUE, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_CURSOR_VISIBLE, + pspec); + /** + * ClutterStage:user-resizable: + * + * Whether the stage is resizable via user interaction. + * + * Since: 0.4 + */ + pspec = g_param_spec_boolean ("user-resizable", + P_("User Resizable"), + P_("Whether the stage is able to be resized via user interaction"), + FALSE, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_USER_RESIZABLE, + pspec); + /** + * ClutterStage:color: + * + * The background color of the main stage. + * + * Deprecated: 1.10: Use the #ClutterActor:background-color property of + * #ClutterActor instead. + */ + pspec = clutter_param_spec_color ("color", + P_("Color"), + P_("The color of the stage"), + &default_stage_color, + CLUTTER_PARAM_READWRITE | + G_PARAM_DEPRECATED); + g_object_class_install_property (gobject_class, PROP_COLOR, pspec); + + /** + * ClutterStage:perspective: + * + * The parameters used for the perspective projection from 3D + * coordinates to 2D + * + * Since: 0.8 + */ + pspec = g_param_spec_boxed ("perspective", + P_("Perspective"), + P_("Perspective projection parameters"), + CLUTTER_TYPE_PERSPECTIVE, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_PERSPECTIVE, + pspec); + + /** + * ClutterStage:title: + * + * The stage's title - usually displayed in stage windows title decorations. + * + * Since: 0.4 + */ + pspec = g_param_spec_string ("title", + P_("Title"), + P_("Stage Title"), + NULL, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_TITLE, pspec); + + /** + * ClutterStage:use-fog: + * + * Whether the stage should use a linear GL "fog" in creating the + * depth-cueing effect, to enhance the perception of depth by fading + * actors farther from the viewpoint. + * + * Since: 0.6 + * + * Deprecated: 1.10: This property does not do anything. + */ + pspec = g_param_spec_boolean ("use-fog", + P_("Use Fog"), + P_("Whether to enable depth cueing"), + FALSE, + CLUTTER_PARAM_READWRITE | G_PARAM_DEPRECATED); + g_object_class_install_property (gobject_class, PROP_USE_FOG, pspec); + + /** + * ClutterStage:fog: + * + * The settings for the GL "fog", used only if #ClutterStage:use-fog + * is set to %TRUE + * + * Since: 1.0 + * + * Deprecated: 1.10: This property does not do anything. + */ + pspec = g_param_spec_boxed ("fog", + P_("Fog"), + P_("Settings for the depth cueing"), + CLUTTER_TYPE_FOG, + CLUTTER_PARAM_READWRITE | G_PARAM_DEPRECATED); + g_object_class_install_property (gobject_class, PROP_FOG, pspec); + + /** + * ClutterStage:use-alpha: + * + * Whether the #ClutterStage should honour the alpha component of the + * #ClutterStage:color property when painting. If Clutter is run under + * a compositing manager this will result in the stage being blended + * with the underlying window(s) + * + * Since: 1.2 + */ + pspec = g_param_spec_boolean ("use-alpha", + P_("Use Alpha"), + P_("Whether to honour the alpha component of the stage color"), + FALSE, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_USE_ALPHA, pspec); + + /** + * ClutterStage:key-focus: + * + * The #ClutterActor that will receive key events from the underlying + * windowing system. + * + * If %NULL, the #ClutterStage will receive the events. + * + * Since: 1.2 + */ + pspec = g_param_spec_object ("key-focus", + P_("Key Focus"), + P_("The currently key focused actor"), + CLUTTER_TYPE_ACTOR, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_KEY_FOCUS, pspec); + + /** + * ClutterStage:no-clear-hint: + * + * Whether or not the #ClutterStage should clear its contents + * before each paint cycle. + * + * See clutter_stage_set_no_clear_hint() for further information. + * + * Since: 1.4 + */ + pspec = g_param_spec_boolean ("no-clear-hint", + P_("No Clear Hint"), + P_("Whether the stage should clear its contents"), + FALSE, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_NO_CLEAR_HINT, pspec); + + /** + * ClutterStage:accept-focus: + * + * Whether the #ClutterStage should accept key focus when shown. + * + * Since: 1.6 + */ + pspec = g_param_spec_boolean ("accept-focus", + P_("Accept Focus"), + P_("Whether the stage should accept focus on show"), + TRUE, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_ACCEPT_FOCUS, pspec); + + /** + * ClutterStage::fullscreen: + * @stage: the stage which was fullscreened + * + * The ::fullscreen signal is emitted when the stage is made fullscreen. + * + * Since: 0.6 + */ + stage_signals[FULLSCREEN] = + g_signal_new (I_("fullscreen"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ClutterStageClass, fullscreen), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + /** + * ClutterStage::unfullscreen: + * @stage: the stage which has left a fullscreen state. + * + * The ::unfullscreen signal is emitted when the stage leaves a fullscreen + * state. + * + * Since: 0.6 + */ + stage_signals[UNFULLSCREEN] = + g_signal_new (I_("unfullscreen"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterStageClass, unfullscreen), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + /** + * ClutterStage::activate: + * @stage: the stage which was activated + * + * The ::activate signal is emitted when the stage receives key focus + * from the underlying window system. + * + * Since: 0.6 + */ + stage_signals[ACTIVATE] = + g_signal_new (I_("activate"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterStageClass, activate), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + /** + * ClutterStage::deactivate: + * @stage: the stage which was deactivated + * + * The ::deactivate signal is emitted when the stage loses key focus + * from the underlying window system. + * + * Since: 0.6 + */ + stage_signals[DEACTIVATE] = + g_signal_new (I_("deactivate"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterStageClass, deactivate), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * ClutterStage::delete-event: + * @stage: the stage that received the event + * @event: a #ClutterEvent of type %CLUTTER_DELETE + * + * The ::delete-event signal is emitted when the user closes a + * #ClutterStage window using the window controls. + * + * Clutter by default will call clutter_main_quit() if @stage is + * the default stage, and clutter_actor_destroy() for any other + * stage. + * + * It is possible to override the default behaviour by connecting + * a new handler and returning %TRUE there. + * + * This signal is emitted only on Clutter backends that + * embed #ClutterStage in native windows. It is not emitted for + * backends that use a static frame buffer. + * + * Since: 1.2 + */ + stage_signals[DELETE_EVENT] = + g_signal_new (I_("delete-event"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterStageClass, delete_event), + _clutter_boolean_handled_accumulator, NULL, + _clutter_marshal_BOOLEAN__BOXED, + G_TYPE_BOOLEAN, 1, + CLUTTER_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); + + /** + * ClutterStage::after-paint: + * @stage: the stage that received the event + * + * The ::after-paint signal is emitted after the stage is painted, + * but before the results are displayed on the screen. + * + * Since: 1.20 + */ + stage_signals[AFTER_PAINT] = + g_signal_new (I_("after-paint"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + 0, /* no corresponding vfunc */ + NULL, NULL, NULL, + G_TYPE_NONE, 0); + + /** + * ClutterStage::presented: (skip) + * @stage: the stage that received the event + * @frame_event: a #CoglFrameEvent + * @frame_info: a #ClutterFrameInfo + */ + stage_signals[PRESENTED] = + g_signal_new (I_("presented"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 2, + G_TYPE_INT, G_TYPE_POINTER); + + klass->fullscreen = clutter_stage_real_fullscreen; + klass->activate = clutter_stage_real_activate; + klass->deactivate = clutter_stage_real_deactivate; + klass->delete_event = clutter_stage_real_delete_event; +} + +static void +clutter_stage_notify_min_size (ClutterStage *self) +{ + self->priv->min_size_changed = TRUE; +} + +static void +clutter_stage_init (ClutterStage *self) +{ + cairo_rectangle_int_t geom = { 0, }; + ClutterStagePrivate *priv; + ClutterStageWindow *impl; + ClutterBackend *backend; + int window_scale = 1; + GError *error; + + /* a stage is a top-level object */ + CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_IS_TOPLEVEL); + + self->priv = priv = clutter_stage_get_instance_private (self); + + CLUTTER_NOTE (BACKEND, "Creating stage from the default backend"); + backend = clutter_get_default_backend (); + + error = NULL; + impl = _clutter_backend_create_stage (backend, self, &error); + + if (G_LIKELY (impl != NULL)) + { + _clutter_stage_set_window (self, impl); + _clutter_stage_window_get_geometry (priv->impl, &geom); + window_scale = _clutter_stage_window_get_scale_factor (priv->impl); + } + else + { + if (error != NULL) + { + g_critical ("Unable to create a new stage implementation: %s", + error->message); + g_error_free (error); + } + else + g_critical ("Unable to create a new stage implementation."); + } + + priv->event_queue = g_queue_new (); + + priv->is_fullscreen = FALSE; + priv->is_user_resizable = FALSE; + priv->is_cursor_visible = TRUE; + priv->use_fog = FALSE; + priv->throttle_motion_events = TRUE; + priv->min_size_changed = FALSE; + priv->sync_delay = -1; + + /* XXX - we need to keep the invariant that calling + * clutter_set_motion_event_enabled() before the stage creation + * will cause motion event delivery to be disabled on any newly + * created stage. this can go away when we break API and remove + * deprecated functions. + */ + priv->motion_events_enabled = _clutter_context_get_motion_events_enabled (); + + clutter_actor_set_background_color (CLUTTER_ACTOR (self), + &default_stage_color); + + priv->perspective.fovy = 60.0; /* 60 Degrees */ + priv->perspective.aspect = (float) geom.width / (float) geom.height; + priv->perspective.z_near = 0.1; + priv->perspective.z_far = 100.0; + + cogl_matrix_init_identity (&priv->projection); + cogl_matrix_perspective (&priv->projection, + priv->perspective.fovy, + priv->perspective.aspect, + priv->perspective.z_near, + priv->perspective.z_far); + cogl_matrix_get_inverse (&priv->projection, + &priv->inverse_projection); + cogl_matrix_init_identity (&priv->view); + cogl_matrix_view_2d_in_perspective (&priv->view, + priv->perspective.fovy, + priv->perspective.aspect, + priv->perspective.z_near, + 50, /* distance to 2d plane */ + geom.width * window_scale, + geom.height * window_scale); + + + /* FIXME - remove for 2.0 */ + priv->fog.z_near = 1.0; + priv->fog.z_far = 2.0; + + priv->relayout_pending = TRUE; + + clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE); + clutter_stage_set_title (self, g_get_prgname ()); + clutter_stage_set_key_focus (self, NULL); + + g_signal_connect (self, "notify::min-width", + G_CALLBACK (clutter_stage_notify_min_size), NULL); + g_signal_connect (self, "notify::min-height", + G_CALLBACK (clutter_stage_notify_min_size), NULL); + + _clutter_stage_set_viewport (self, + 0, 0, + geom.width, + geom.height); + + priv->paint_volume_stack = + g_array_new (FALSE, FALSE, sizeof (ClutterPaintVolume)); + + priv->pick_id_pool = _clutter_id_pool_new (256); +} + +/** + * clutter_stage_get_default: + * + * Retrieves a #ClutterStage singleton. + * + * This function is not as useful as it sounds, and will most likely + * by deprecated in the future. Application code should only create + * a #ClutterStage instance using clutter_stage_new(), and manage the + * lifetime of the stage manually. + * + * The default stage singleton has a platform-specific behaviour: on + * platforms without the %CLUTTER_FEATURE_STAGE_MULTIPLE feature flag + * set, the first #ClutterStage instance will also be set to be the + * default stage instance, and this function will always return a + * pointer to it. + * + * On platforms with the %CLUTTER_FEATURE_STAGE_MULTIPLE feature flag + * set, the default stage will be created by the first call to this + * function, and every following call will return the same pointer to + * it. + * + * Return value: (transfer none) (type Clutter.Stage): the main + * #ClutterStage. You should never destroy or unref the returned + * actor. + * + * Deprecated: 1.10: Use clutter_stage_new() instead. + */ +ClutterActor * +clutter_stage_get_default (void) +{ + ClutterStageManager *stage_manager = clutter_stage_manager_get_default (); + ClutterStage *stage; + + stage = clutter_stage_manager_get_default_stage (stage_manager); + if (G_UNLIKELY (stage == NULL)) + { + /* This will take care of automatically adding the stage to the + * stage manager and setting it as the default. Its floating + * reference will be claimed by the stage manager. + */ + stage = g_object_new (CLUTTER_TYPE_STAGE, NULL); + _clutter_stage_manager_set_default_stage (stage_manager, stage); + + /* the default stage is realized by default */ + clutter_actor_realize (CLUTTER_ACTOR (stage)); + } + + return CLUTTER_ACTOR (stage); +} + +/** + * clutter_stage_set_color: + * @stage: A #ClutterStage + * @color: A #ClutterColor + * + * Sets the stage color. + * + * Deprecated: 1.10: Use clutter_actor_set_background_color() instead. + */ +void +clutter_stage_set_color (ClutterStage *stage, + const ClutterColor *color) +{ + clutter_actor_set_background_color (CLUTTER_ACTOR (stage), color); + + g_object_notify (G_OBJECT (stage), "color"); +} + +/** + * clutter_stage_get_color: + * @stage: A #ClutterStage + * @color: (out caller-allocates): return location for a #ClutterColor + * + * Retrieves the stage color. + * + * Deprecated: 1.10: Use clutter_actor_get_background_color() instead. + */ +void +clutter_stage_get_color (ClutterStage *stage, + ClutterColor *color) +{ + clutter_actor_get_background_color (CLUTTER_ACTOR (stage), color); +} + +static void +clutter_stage_set_perspective_internal (ClutterStage *stage, + ClutterPerspective *perspective) +{ + ClutterStagePrivate *priv = stage->priv; + + if (priv->perspective.fovy == perspective->fovy && + priv->perspective.aspect == perspective->aspect && + priv->perspective.z_near == perspective->z_near && + priv->perspective.z_far == perspective->z_far) + return; + + priv->perspective = *perspective; + + cogl_matrix_init_identity (&priv->projection); + cogl_matrix_perspective (&priv->projection, + priv->perspective.fovy, + priv->perspective.aspect, + priv->perspective.z_near, + priv->perspective.z_far); + cogl_matrix_get_inverse (&priv->projection, + &priv->inverse_projection); + + _clutter_stage_dirty_projection (stage); + clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); +} + +/** + * clutter_stage_set_perspective: + * @stage: A #ClutterStage + * @perspective: A #ClutterPerspective + * + * Sets the stage perspective. Using this function is not recommended + * because it will disable Clutter's attempts to generate an + * appropriate perspective based on the size of the stage. + */ +void +clutter_stage_set_perspective (ClutterStage *stage, + ClutterPerspective *perspective) +{ + ClutterStagePrivate *priv; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + g_return_if_fail (perspective != NULL); + g_return_if_fail (perspective->z_far - perspective->z_near != 0); + + priv = stage->priv; + + /* If the application ever calls this function then we'll stop + automatically updating the perspective when the stage changes + size */ + priv->has_custom_perspective = TRUE; + + clutter_stage_set_perspective_internal (stage, perspective); +} + +/** + * clutter_stage_get_perspective: + * @stage: A #ClutterStage + * @perspective: (out caller-allocates) (allow-none): return location for a + * #ClutterPerspective + * + * Retrieves the stage perspective. + */ +void +clutter_stage_get_perspective (ClutterStage *stage, + ClutterPerspective *perspective) +{ + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + g_return_if_fail (perspective != NULL); + + *perspective = stage->priv->perspective; +} + +/* + * clutter_stage_get_projection_matrix: + * @stage: A #ClutterStage + * @projection: return location for a #CoglMatrix representing the + * perspective projection applied to actors on the given + * @stage. + * + * Retrieves the @stage's projection matrix. This is derived from the + * current perspective set using clutter_stage_set_perspective(). + * + * Since: 1.6 + */ +void +_clutter_stage_get_projection_matrix (ClutterStage *stage, + CoglMatrix *projection) +{ + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + g_return_if_fail (projection != NULL); + + *projection = stage->priv->projection; +} + +/* This simply provides a simple mechanism for us to ensure that + * the projection matrix gets re-asserted before painting. + * + * This is used when switching between multiple stages */ +void +_clutter_stage_dirty_projection (ClutterStage *stage) +{ + ClutterStagePrivate *priv; + GList *l; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + priv = stage->priv; + + for (l = _clutter_stage_window_get_views (priv->impl); l; l = l->next) + { + ClutterStageView *view = l->data; + + clutter_stage_view_set_dirty_projection (view, TRUE); + } +} + +/* + * clutter_stage_set_viewport: + * @stage: A #ClutterStage + * @x: The X postition to render the stage at, in window coordinates + * @y: The Y position to render the stage at, in window coordinates + * @width: The width to render the stage at, in window coordinates + * @height: The height to render the stage at, in window coordinates + * + * Sets the stage viewport. The viewport defines a final scale and + * translation of your rendered stage and actors. This lets you render + * your stage into a subregion of the stage window or you could use it to + * pan a subregion of the stage if your stage window is smaller then + * the stage. (XXX: currently this isn't possible) + * + * Unlike a scale and translation done using the modelview matrix this + * is done after everything has had perspective projection applied, so + * for example if you were to pan across a subregion of the stage using + * the viewport then you would not see a change in perspective for the + * actors on the stage. + * + * Normally the stage viewport will automatically track the size of the + * stage window with no offset so the stage will fill your window. This + * behaviour can be changed with the "viewport-mimics-window" property + * which will automatically be set to FALSE if you use this API. If + * you want to revert to the original behaviour then you should set + * this property back to %TRUE using + * clutter_stage_set_viewport_mimics_window(). + * (XXX: If we were to make this API public then we might want to do + * add that property.) + * + * Note: currently this interface only support integer precision + * offsets and sizes for viewports but the interface takes floats because + * OpenGL 4.0 has introduced floating point viewports which we might + * want to expose via this API eventually. + * + * Since: 1.6 + */ +void +_clutter_stage_set_viewport (ClutterStage *stage, + float x, + float y, + float width, + float height) +{ + ClutterStagePrivate *priv; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + priv = stage->priv; + + + if (x == priv->viewport[0] && + y == priv->viewport[1] && + width == priv->viewport[2] && + height == priv->viewport[3]) + return; + + priv->viewport[0] = x; + priv->viewport[1] = y; + priv->viewport[2] = width; + priv->viewport[3] = height; + + _clutter_stage_dirty_viewport (stage); + + queue_full_redraw (stage); +} + +/* This simply provides a simple mechanism for us to ensure that + * the viewport gets re-asserted before next painting. + * + * This is used when switching between multiple stages */ +void +_clutter_stage_dirty_viewport (ClutterStage *stage) +{ + ClutterStagePrivate *priv; + GList *l; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + priv = stage->priv; + + for (l = _clutter_stage_window_get_views (priv->impl); l; l = l->next) + { + ClutterStageView *view = l->data; + + clutter_stage_view_set_dirty_viewport (view, TRUE); + } +} + +/* + * clutter_stage_get_viewport: + * @stage: A #ClutterStage + * @x: A location for the X position where the stage is rendered, + * in window coordinates. + * @y: A location for the Y position where the stage is rendered, + * in window coordinates. + * @width: A location for the width the stage is rendered at, + * in window coordinates. + * @height: A location for the height the stage is rendered at, + * in window coordinates. + * + * Returns the viewport offset and size set using + * clutter_stage_set_viewport() or if the "viewport-mimics-window" property + * is TRUE then @x and @y will be set to 0 and @width and @height will equal + * the width if the stage window. + * + * Since: 1.6 + */ +void +_clutter_stage_get_viewport (ClutterStage *stage, + float *x, + float *y, + float *width, + float *height) +{ + ClutterStagePrivate *priv; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + priv = stage->priv; + + *x = priv->viewport[0]; + *y = priv->viewport[1]; + *width = priv->viewport[2]; + *height = priv->viewport[3]; +} + +/** + * clutter_stage_set_fullscreen: + * @stage: a #ClutterStage + * @fullscreen: %TRUE to to set the stage fullscreen + * + * Asks to place the stage window in the fullscreen or unfullscreen + * states. + * + ( Note that you shouldn't assume the window is definitely full screen + * afterward, because other entities (e.g. the user or window manager) + * could unfullscreen it again, and not all window managers honor + * requests to fullscreen windows. + * + * If you want to receive notification of the fullscreen state you + * should either use the #ClutterStage::fullscreen and + * #ClutterStage::unfullscreen signals, or use the notify signal + * for the #ClutterStage:fullscreen-set property + * + * Since: 1.0 + */ +void +clutter_stage_set_fullscreen (ClutterStage *stage, + gboolean fullscreen) +{ + ClutterStagePrivate *priv; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + priv = stage->priv; + + if (priv->is_fullscreen != fullscreen) + { + ClutterStageWindow *impl = CLUTTER_STAGE_WINDOW (priv->impl); + ClutterStageWindowIface *iface; + + iface = CLUTTER_STAGE_WINDOW_GET_IFACE (impl); + + /* Only set if backend implements. + * + * Also see clutter_stage_event() for setting priv->is_fullscreen + * on state change event. + */ + if (iface->set_fullscreen) + iface->set_fullscreen (impl, fullscreen); + } + + /* If the backend did fullscreen the stage window then we need to resize + * the stage and update its viewport so we queue a relayout. Note: if the + * fullscreen request is handled asynchronously we can't rely on this + * queue_relayout to update the viewport, but for example the X backend + * will recieve a ConfigureNotify after a successful resize which is how + * we ensure the viewport is updated on X. + */ + clutter_actor_queue_relayout (CLUTTER_ACTOR (stage)); +} + +/** + * clutter_stage_get_fullscreen: + * @stage: a #ClutterStage + * + * Retrieves whether the stage is full screen or not + * + * Return value: %TRUE if the stage is full screen + * + * Since: 1.0 + */ +gboolean +clutter_stage_get_fullscreen (ClutterStage *stage) +{ + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); + + return stage->priv->is_fullscreen; +} + +/** + * clutter_stage_set_user_resizable: + * @stage: a #ClutterStage + * @resizable: whether the stage should be user resizable. + * + * Sets if the stage is resizable by user interaction (e.g. via + * window manager controls) + * + * Since: 0.4 + */ +void +clutter_stage_set_user_resizable (ClutterStage *stage, + gboolean resizable) +{ + ClutterStagePrivate *priv; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + priv = stage->priv; + + if (clutter_feature_available (CLUTTER_FEATURE_STAGE_USER_RESIZE) + && priv->is_user_resizable != resizable) + { + ClutterStageWindow *impl = CLUTTER_STAGE_WINDOW (priv->impl); + ClutterStageWindowIface *iface; + + iface = CLUTTER_STAGE_WINDOW_GET_IFACE (impl); + if (iface->set_user_resizable) + { + priv->is_user_resizable = resizable; + + iface->set_user_resizable (impl, resizable); + + g_object_notify (G_OBJECT (stage), "user-resizable"); + } + } +} + +/** + * clutter_stage_get_user_resizable: + * @stage: a #ClutterStage + * + * Retrieves the value set with clutter_stage_set_user_resizable(). + * + * Return value: %TRUE if the stage is resizable by the user. + * + * Since: 0.4 + */ +gboolean +clutter_stage_get_user_resizable (ClutterStage *stage) +{ + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); + + return stage->priv->is_user_resizable; +} + +/** + * clutter_stage_show_cursor: + * @stage: a #ClutterStage + * + * Shows the cursor on the stage window + */ +void +clutter_stage_show_cursor (ClutterStage *stage) +{ + ClutterStagePrivate *priv; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + priv = stage->priv; + if (!priv->is_cursor_visible) + { + ClutterStageWindow *impl = CLUTTER_STAGE_WINDOW (priv->impl); + ClutterStageWindowIface *iface; + + iface = CLUTTER_STAGE_WINDOW_GET_IFACE (impl); + if (iface->set_cursor_visible) + { + priv->is_cursor_visible = TRUE; + + iface->set_cursor_visible (impl, TRUE); + + g_object_notify (G_OBJECT (stage), "cursor-visible"); + } + } +} + +/** + * clutter_stage_hide_cursor: + * @stage: a #ClutterStage + * + * Makes the cursor invisible on the stage window + * + * Since: 0.4 + */ +void +clutter_stage_hide_cursor (ClutterStage *stage) +{ + ClutterStagePrivate *priv; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + priv = stage->priv; + if (priv->is_cursor_visible) + { + ClutterStageWindow *impl = CLUTTER_STAGE_WINDOW (priv->impl); + ClutterStageWindowIface *iface; + + iface = CLUTTER_STAGE_WINDOW_GET_IFACE (impl); + if (iface->set_cursor_visible) + { + priv->is_cursor_visible = FALSE; + + iface->set_cursor_visible (impl, FALSE); + + g_object_notify (G_OBJECT (stage), "cursor-visible"); + } + } +} + +/** + * clutter_stage_read_pixels: + * @stage: A #ClutterStage + * @x: x coordinate of the first pixel that is read from stage + * @y: y coordinate of the first pixel that is read from stage + * @width: Width dimention of pixels to be read, or -1 for the + * entire stage width + * @height: Height dimention of pixels to be read, or -1 for the + * entire stage height + * + * Makes a screenshot of the stage in RGBA 8bit data, returns a + * linear buffer with @width * 4 as rowstride. + * + * The alpha data contained in the returned buffer is driver-dependent, + * and not guaranteed to hold any sensible value. + * + * Return value: (transfer full) (array): a pointer to newly allocated memory with the buffer + * or %NULL if the read failed. Use g_free() on the returned data + * to release the resources it has allocated. + */ +guchar * +clutter_stage_read_pixels (ClutterStage *stage, + gint x, + gint y, + gint width, + gint height) +{ + ClutterStagePrivate *priv; + ClutterActorBox box; + GList *l; + ClutterStageView *view; + cairo_region_t *clip; + cairo_rectangle_int_t clip_rect; + CoglFramebuffer *framebuffer; + uint8_t *pixels; + + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL); + + priv = stage->priv; + + clutter_actor_get_allocation_box (CLUTTER_ACTOR (stage), &box); + + if (width < 0) + width = ceilf (box.x2 - box.x1); + + if (height < 0) + height = ceilf (box.y2 - box.y1); + + l = _clutter_stage_window_get_views (priv->impl); + + if (!l) + return NULL; + + /* XXX: We only read the first view. Needs different API for multi view screen + * capture. */ + view = l->data; + + clutter_stage_view_get_layout (view, &clip_rect); + clip = cairo_region_create_rectangle (&clip_rect); + cairo_region_intersect_rectangle (clip, + &(cairo_rectangle_int_t) { + .x = x, + .y = y, + .width = width, + .height = height, + }); + cairo_region_get_extents (clip, &clip_rect); + cairo_region_destroy (clip); + + if (clip_rect.width == 0 || clip_rect.height == 0) + return NULL; + + framebuffer = clutter_stage_view_get_framebuffer (view); + cogl_push_framebuffer (framebuffer); + clutter_stage_do_paint_view (stage, view, &clip_rect); + + pixels = g_malloc0 (clip_rect.width * clip_rect.height * 4); + cogl_framebuffer_read_pixels (framebuffer, + clip_rect.x, clip_rect.y, + clip_rect.width, clip_rect.height, + COGL_PIXEL_FORMAT_RGBA_8888, + pixels); + + cogl_pop_framebuffer (); + + return pixels; +} + +/** + * 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. + * + * 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, + ClutterPickMode pick_mode, + gint x, + gint y) +{ + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL); + + return _clutter_stage_do_pick (stage, x, y, pick_mode); +} + +/** + * clutter_stage_event: + * @stage: a #ClutterStage + * @event: a #ClutterEvent + * + * This function is used to emit an event on the main stage. + * + * You should rarely need to use this function, except for + * synthetised events. + * + * Return value: the return value from the signal emission + * + * Since: 0.4 + */ +gboolean +clutter_stage_event (ClutterStage *stage, + ClutterEvent *event) +{ + ClutterStagePrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + priv = stage->priv; + + if (event->type == CLUTTER_DELETE) + { + gboolean retval = FALSE; + + g_signal_emit_by_name (stage, "event", event, &retval); + + if (!retval) + g_signal_emit_by_name (stage, "delete-event", event, &retval); + + return retval; + } + + if (event->type != CLUTTER_STAGE_STATE) + return FALSE; + + /* emit raw event */ + if (clutter_actor_event (CLUTTER_ACTOR (stage), event, FALSE)) + return TRUE; + + if (event->stage_state.changed_mask & CLUTTER_STAGE_STATE_FULLSCREEN) + { + if (event->stage_state.new_state & CLUTTER_STAGE_STATE_FULLSCREEN) + { + priv->is_fullscreen = TRUE; + g_signal_emit (stage, stage_signals[FULLSCREEN], 0); + + g_object_notify (G_OBJECT (stage), "fullscreen-set"); + } + else + { + priv->is_fullscreen = FALSE; + g_signal_emit (stage, stage_signals[UNFULLSCREEN], 0); + + g_object_notify (G_OBJECT (stage), "fullscreen-set"); + } + } + + if (event->stage_state.changed_mask & CLUTTER_STAGE_STATE_ACTIVATED) + { + if (event->stage_state.new_state & CLUTTER_STAGE_STATE_ACTIVATED) + g_signal_emit (stage, stage_signals[ACTIVATE], 0); + else + g_signal_emit (stage, stage_signals[DEACTIVATE], 0); + } + + return TRUE; +} + +/** + * clutter_stage_set_title: + * @stage: A #ClutterStage + * @title: A utf8 string for the stage windows title. + * + * Sets the stage title. + * + * Since: 0.4 + **/ +void +clutter_stage_set_title (ClutterStage *stage, + const gchar *title) +{ + ClutterStagePrivate *priv; + ClutterStageWindow *impl; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + priv = stage->priv; + + g_free (priv->title); + priv->title = g_strdup (title); + + impl = CLUTTER_STAGE_WINDOW (priv->impl); + if (CLUTTER_STAGE_WINDOW_GET_IFACE(impl)->set_title != NULL) + CLUTTER_STAGE_WINDOW_GET_IFACE (impl)->set_title (impl, priv->title); + + g_object_notify (G_OBJECT (stage), "title"); +} + +/** + * clutter_stage_get_title: + * @stage: A #ClutterStage + * + * Gets the stage title. + * + * Return value: pointer to the title string for the stage. The + * returned string is owned by the actor and should not + * be modified or freed. + * + * Since: 0.4 + **/ +const gchar * +clutter_stage_get_title (ClutterStage *stage) +{ + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL); + + return stage->priv->title; +} + +static void +on_key_focus_destroy (ClutterActor *actor, + ClutterStage *stage) +{ + /* unset the key focus */ + clutter_stage_set_key_focus (stage, NULL); +} + +/** + * clutter_stage_set_key_focus: + * @stage: the #ClutterStage + * @actor: (allow-none): the actor to set key focus to, or %NULL + * + * Sets the key focus on @actor. An actor with key focus will receive + * all the key events. If @actor is %NULL, the stage will receive + * focus. + * + * Since: 0.6 + */ +void +clutter_stage_set_key_focus (ClutterStage *stage, + ClutterActor *actor) +{ + ClutterStagePrivate *priv; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + g_return_if_fail (actor == NULL || CLUTTER_IS_ACTOR (actor)); + + priv = stage->priv; + + /* normalize the key focus. NULL == stage */ + if (actor == CLUTTER_ACTOR (stage)) + actor = NULL; + + /* avoid emitting signals and notifications if we're setting the same + * actor as the key focus + */ + if (priv->key_focused_actor == actor) + return; + + if (priv->key_focused_actor != NULL) + { + ClutterActor *old_focused_actor; + + old_focused_actor = priv->key_focused_actor; + + /* set key_focused_actor to NULL before emitting the signal or someone + * might hide the previously focused actor in the signal handler and we'd + * get re-entrant call and get glib critical from g_object_weak_unref + */ + g_signal_handlers_disconnect_by_func (priv->key_focused_actor, + G_CALLBACK (on_key_focus_destroy), + stage); + priv->key_focused_actor = NULL; + + g_signal_emit_by_name (old_focused_actor, "key-focus-out"); + } + else + g_signal_emit_by_name (stage, "key-focus-out"); + + /* Note, if someone changes key focus in focus-out signal handler we'd be + * overriding the latter call below moving the focus where it was originally + * intended. The order of events would be: + * 1st focus-out, 2nd focus-out (on stage), 2nd focus-in, 1st focus-in + */ + if (actor != NULL) + { + priv->key_focused_actor = actor; + + g_signal_connect (actor, + "destroy", G_CALLBACK (on_key_focus_destroy), + stage); + g_signal_emit_by_name (priv->key_focused_actor, "key-focus-in"); + } + else + g_signal_emit_by_name (stage, "key-focus-in"); + + g_object_notify (G_OBJECT (stage), "key-focus"); +} + +/** + * clutter_stage_get_key_focus: + * @stage: the #ClutterStage + * + * Retrieves the actor that is currently under key focus. + * + * Return value: (transfer none): the actor with key focus, or the stage + * + * Since: 0.6 + */ +ClutterActor * +clutter_stage_get_key_focus (ClutterStage *stage) +{ + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL); + + if (stage->priv->key_focused_actor) + return stage->priv->key_focused_actor; + + return CLUTTER_ACTOR (stage); +} + +/** + * clutter_stage_get_use_fog: + * @stage: the #ClutterStage + * + * Gets whether the depth cueing effect is enabled on @stage. + * + * Return value: %TRUE if the depth cueing effect is enabled + * + * Since: 0.6 + * + * Deprecated: 1.10: This function will always return %FALSE + */ +gboolean +clutter_stage_get_use_fog (ClutterStage *stage) +{ + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); + + return stage->priv->use_fog; +} + +/** + * clutter_stage_set_use_fog: + * @stage: the #ClutterStage + * @fog: %TRUE for enabling the depth cueing effect + * + * Sets whether the depth cueing effect on the stage should be enabled + * or not. + * + * Depth cueing is a 3D effect that makes actors farther away from the + * viewing point less opaque, by fading them with the stage color. + + * The parameters of the GL fog used can be changed using the + * clutter_stage_set_fog() function. + * + * Since: 0.6 + * + * Deprecated: 1.10: Calling this function produces no visible effect + */ +void +clutter_stage_set_use_fog (ClutterStage *stage, + gboolean fog) +{ +} + +/** + * clutter_stage_set_fog: + * @stage: the #ClutterStage + * @fog: a #ClutterFog structure + * + * Sets the fog (also known as "depth cueing") settings for the @stage. + * + * A #ClutterStage will only use a linear fog progression, which + * depends solely on the distance from the viewer. The cogl_set_fog() + * function in COGL exposes more of the underlying implementation, + * and allows changing the for progression function. It can be directly + * used by disabling the #ClutterStage:use-fog property and connecting + * a signal handler to the #ClutterActor::paint signal on the @stage, + * like: + * + * |[ + * clutter_stage_set_use_fog (stage, FALSE); + * g_signal_connect (stage, "paint", G_CALLBACK (on_stage_paint), NULL); + * ]| + * + * The paint signal handler will call cogl_set_fog() with the + * desired settings: + * + * |[ + * static void + * on_stage_paint (ClutterActor *actor) + * { + * ClutterColor stage_color = { 0, }; + * CoglColor fog_color = { 0, }; + * + * // set the fog color to the stage background color + * clutter_stage_get_color (CLUTTER_STAGE (actor), &stage_color); + * cogl_color_init_from_4ub (&fog_color, + * stage_color.red, + * stage_color.green, + * stage_color.blue, + * stage_color.alpha); + * + * // enable fog // + * cogl_set_fog (&fog_color, + * COGL_FOG_MODE_EXPONENTIAL, // mode + * 0.5, // density + * 5.0, 30.0); // z_near and z_far + * } + * ]| + * + * The fogging functions only work correctly when the visible actors use + * unmultiplied alpha colors. By default Cogl will premultiply textures and + * cogl_set_source_color() will premultiply colors, so unless you explicitly + * load your textures requesting an unmultiplied internal format and use + * cogl_material_set_color() you can only use fogging with fully opaque actors. + * Support for premultiplied colors will improve in the future when we can + * depend on fragment shaders. + * + * Since: 0.6 + * + * Deprecated: 1.10: Fog settings are ignored. + */ +void +clutter_stage_set_fog (ClutterStage *stage, + ClutterFog *fog) +{ +} + +/** + * clutter_stage_get_fog: + * @stage: the #ClutterStage + * @fog: (out): return location for a #ClutterFog structure + * + * Retrieves the current depth cueing settings from the stage. + * + * Since: 0.6 + * + * Deprecated: 1.10: This function will always return the default + * values of #ClutterFog + */ +void +clutter_stage_get_fog (ClutterStage *stage, + ClutterFog *fog) +{ + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + g_return_if_fail (fog != NULL); + + *fog = stage->priv->fog; +} + +/*** Perspective boxed type ******/ + +static gpointer +clutter_perspective_copy (gpointer data) +{ + if (G_LIKELY (data)) + return g_slice_dup (ClutterPerspective, data); + + return NULL; +} + +static void +clutter_perspective_free (gpointer data) +{ + if (G_LIKELY (data)) + g_slice_free (ClutterPerspective, data); +} + +G_DEFINE_BOXED_TYPE (ClutterPerspective, clutter_perspective, + clutter_perspective_copy, + clutter_perspective_free); + +static gpointer +clutter_fog_copy (gpointer data) +{ + if (G_LIKELY (data)) + return g_slice_dup (ClutterFog, data); + + return NULL; +} + +static void +clutter_fog_free (gpointer data) +{ + if (G_LIKELY (data)) + g_slice_free (ClutterFog, data); +} + +G_DEFINE_BOXED_TYPE (ClutterFog, clutter_fog, clutter_fog_copy, clutter_fog_free); + +/** + * clutter_stage_new: + * + * Creates a new, non-default stage. A non-default stage is a new + * top-level actor which can be used as another container. It works + * exactly like the default stage, but while clutter_stage_get_default() + * will always return the same instance, you will have to keep a pointer + * to any #ClutterStage returned by clutter_stage_new(). + * + * The ability to support multiple stages depends on the current + * backend. Use clutter_feature_available() and + * %CLUTTER_FEATURE_STAGE_MULTIPLE to check at runtime whether a + * backend supports multiple stages. + * + * Return value: a new stage, or %NULL if the default backend does + * not support multiple stages. Use clutter_actor_destroy() to + * programmatically close the returned stage. + * + * Since: 0.8 + */ +ClutterActor * +clutter_stage_new (void) +{ + return g_object_new (CLUTTER_TYPE_STAGE, NULL); +} + +/** + * clutter_stage_ensure_current: + * @stage: the #ClutterStage + * + * This function essentially makes sure the right GL context is + * current for the passed stage. It is not intended to + * be used by applications. + * + * Since: 0.8 + * Deprecated: mutter: This function does not do anything. + */ +void +clutter_stage_ensure_current (ClutterStage *stage) +{ + g_return_if_fail (CLUTTER_IS_STAGE (stage)); +} + +/** + * clutter_stage_ensure_viewport: + * @stage: a #ClutterStage + * + * Ensures that the GL viewport is updated with the current + * stage window size. + * + * This function will queue a redraw of @stage. + * + * This function should not be called by applications; it is used + * when embedding a #ClutterStage into a toolkit with another + * windowing system, like GTK+. + * + * Since: 1.0 + */ +void +clutter_stage_ensure_viewport (ClutterStage *stage) +{ + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + _clutter_stage_dirty_viewport (stage); + + clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); +} + +static void +clutter_stage_apply_scale (ClutterStage *stage) +{ + int factor; + + factor = _clutter_stage_window_get_scale_factor (stage->priv->impl); + if (factor != 1) + cogl_matrix_scale (&stage->priv->view, factor, factor, 1.f); +} + +# define _DEG_TO_RAD(d) ((d) * ((float) G_PI / 180.0f)) + +/* This calculates a distance into the view frustum to position the + * stage so there is a decent amount of space to position geometry + * between the stage and the near clipping plane. + * + * Some awkward issues with this problem are: + * - It's not possible to have a gap as large as the stage size with + * a fov > 53° which is basically always the case since the default + * fov is 60°. + * - This can be deduced if you consider that this requires a + * triangle as wide as it is deep to fit in the frustum in front + * of the z_near plane. That triangle will always have an angle + * of 53.13° at the point sitting on the z_near plane, but if the + * frustum has a wider fov angle the left/right clipping planes + * can never converge with the two corners of our triangle no + * matter what size the triangle has. + * - With a fov > 53° there is a trade off between maximizing the gap + * size relative to the stage size but not loosing depth precision. + * - Perhaps ideally we wouldn't just consider the fov on the y-axis + * that is usually used to define a perspective, we would consider + * the fov of the axis with the largest stage size so the gap would + * accommodate that size best. + * + * After going around in circles a few times with how to handle these + * issues, we decided in the end to go for the simplest solution to + * start with instead of an elaborate function that handles arbitrary + * fov angles that we currently have no use-case for. + * + * The solution assumes a fovy of 60° and for that case gives a gap + * that's 85% of the stage height. We can consider more elaborate + * functions if necessary later. + * + * One guide we had to steer the gap size we support is the + * interactive test, test-texture-quality which expects to animate an + * actor to +400 on the z axis with a stage size of 640x480. A gap + * that's 85% of the stage height gives a gap of 408 in that case. + */ +static float +calculate_z_translation (float z_near) +{ + /* This solution uses fairly basic trigonometry, but is seems worth + * clarifying the particular geometry we are looking at in-case + * anyone wants to develop this further later. Not sure how well an + * ascii diagram is going to work :-) + * + * |--- stage_height ---| + * | stage line | + * ╲━━━━━━━━━━━━━━━━━━━━━╱------------ + * ╲. (2) │ .╱ | | + * C ╲ . │ . ╱ gap| | + * =0.5°╲ . a │ . ╱ | | + * b╲(1). D│ . ╱ | | + * ╲ B.│. ╱near plane | | + * A= ╲━━━━━━━━━╱------------- | + * 120° ╲ c │ ╱ | z_2d + * ╲ │ ╱ z_near | + * left ╲ │ ╱ | | + * clip 60°fovy | | + * plane ╳---------------------- + * | + * | + * origin line + * + * The area of interest is the triangle labeled (1) at the top left + * marked with the ... line (a) from where the origin line crosses + * the near plane to the top left where the stage line cross the + * left clip plane. + * + * The sides of the triangle are a, b and c and the corresponding + * angles opposite those sides are A, B and C. + * + * The angle of C is what trades off the gap size we have relative + * to the stage size vs the depth precision we have. + * + * As mentioned above we arove at the angle for C is by working + * backwards from how much space we want for test-texture-quality. + * With a stage_height of 480 we want a gap > 400, ideally we also + * wanted a somewhat round number as a percentage of the height for + * documentation purposes. ~87% or a gap of ~416 is the limit + * because that's where we approach a C angle of 0° and effectively + * loose all depth precision. + * + * So for our test app with a stage_height of 480 if we aim for a + * gap of 408 (85% of 480) we can get the angle D as + * atan (stage_height/2/408) = 30.5°. + * + * That gives us the angle for B as 90° - 30.5° = 59.5° + * + * We can already determine that A has an angle of (fovy/2 + 90°) = + * 120° + * + * Therefore C = 180 - A - B = 0.5° + * + * The length of c = z_near * tan (30°) + * + * Now we can use the rule a/SinA = c/SinC to calculate the + * length of a. After some rearranging that gives us: + * + * a c + * ---------- = ---------- + * sin (120°) sin (0.5°) + * + * c * sin (120°) + * a = -------------- + * sin (0.5°) + * + * And with that we can determine z_2d = cos (D) * a = + * cos (30.5°) * a + z_near: + * + * c * sin (120°) * cos (30.5°) + * z_2d = --------------------------- + z_near + * sin (0.5°) + */ + + /* We expect the compiler should boil this down to z_near * CONSTANT + * already, but just in case we use precomputed constants + */ +#if 0 +# define A tanf (_DEG_TO_RAD (30.f)) +# define B sinf (_DEG_TO_RAD (120.f)) +# define C cosf (_DEG_TO_RAD (30.5f)) +# define D sinf (_DEG_TO_RAD (.5f)) +#else +# define A 0.57735025882720947265625f +# define B 0.866025388240814208984375f +# define C 0.86162912845611572265625f +# define D 0.00872653536498546600341796875f +#endif + + return z_near + * A * B * C + / D + + z_near; +} + +void +_clutter_stage_maybe_setup_viewport (ClutterStage *stage, + ClutterStageView *view) +{ + ClutterStagePrivate *priv = stage->priv; + + if (clutter_stage_view_is_dirty_viewport (view)) + { + cairo_rectangle_int_t view_layout; + ClutterPerspective perspective; + int window_scale; + int viewport_offset_x; + int viewport_offset_y; + float z_2d; + + CLUTTER_NOTE (PAINT, + "Setting up the viewport { w:%f, h:%f }", + priv->viewport[2], + priv->viewport[3]); + + window_scale = _clutter_stage_window_get_scale_factor (priv->impl); + clutter_stage_view_get_layout (view, &view_layout); + + viewport_offset_x = view_layout.x * window_scale; + viewport_offset_y = view_layout.y * window_scale; + cogl_set_viewport (priv->viewport[0] * window_scale - viewport_offset_x, + priv->viewport[1] * window_scale - viewport_offset_y, + priv->viewport[2] * window_scale, + priv->viewport[3] * window_scale); + + perspective = priv->perspective; + + /* Ideally we want to regenerate the perspective matrix whenever + * the size changes but if the user has provided a custom matrix + * then we don't want to override it */ + if (!priv->has_custom_perspective) + { + perspective.aspect = priv->viewport[2] / priv->viewport[3]; + z_2d = calculate_z_translation (perspective.z_near); + + /* NB: z_2d is only enough room for 85% of the stage_height between + * the stage and the z_near plane. For behind the stage plane we + * want a more consistent gap of 10 times the stage_height before + * hitting the far plane so we calculate that relative to the final + * height of the stage plane at the z_2d_distance we got... */ + perspective.z_far = z_2d + + tanf (_DEG_TO_RAD (perspective.fovy / 2.0f)) * z_2d * 20.0f; + + clutter_stage_set_perspective_internal (stage, &perspective); + } + else + z_2d = calculate_z_translation (perspective.z_near); + + cogl_matrix_init_identity (&priv->view); + cogl_matrix_view_2d_in_perspective (&priv->view, + perspective.fovy, + perspective.aspect, + perspective.z_near, + z_2d, + priv->viewport[2] * window_scale, + priv->viewport[3] * window_scale); + + clutter_stage_apply_scale (stage); + + clutter_stage_view_set_dirty_viewport (view, FALSE); + } + + if (clutter_stage_view_is_dirty_projection (view)) + { + cogl_set_projection_matrix (&priv->projection); + + clutter_stage_view_set_dirty_projection (view, FALSE); + } +} + +#undef _DEG_TO_RAD + +/** + * clutter_stage_ensure_redraw: + * @stage: a #ClutterStage + * + * Ensures that @stage is redrawn + * + * This function should not be called by applications: it is + * used when embedding a #ClutterStage into a toolkit with + * another windowing system, like GTK+. + * + * Since: 1.0 + */ +void +clutter_stage_ensure_redraw (ClutterStage *stage) +{ + ClutterMasterClock *master_clock; + ClutterStagePrivate *priv; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + priv = stage->priv; + + if (!priv->relayout_pending && !priv->redraw_pending) + _clutter_stage_schedule_update (stage); + + priv->relayout_pending = TRUE; + priv->redraw_pending = TRUE; + + master_clock = _clutter_master_clock_get_default (); + _clutter_master_clock_start_running (master_clock); +} + +/** + * clutter_stage_queue_redraw: + * @stage: the #ClutterStage + * + * Queues a redraw for the passed stage. + * + * Applications should call clutter_actor_queue_redraw() and not + * this function. + * + * Since: 0.8 + * + * Deprecated: 1.10: Use clutter_actor_queue_redraw() instead. + */ +void +clutter_stage_queue_redraw (ClutterStage *stage) +{ + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); +} + +/** + * clutter_stage_is_default: + * @stage: a #ClutterStage + * + * Checks if @stage is the default stage, or an instance created using + * clutter_stage_new() but internally using the same implementation. + * + * Return value: %TRUE if the passed stage is the default one + * + * Since: 0.8 + * + * Deprecated: 1.10: Track the stage pointer inside your application + * code, or use clutter_actor_get_stage() to retrieve the stage for + * a given actor. + */ +gboolean +clutter_stage_is_default (ClutterStage *stage) +{ + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); + + return stage_is_default (stage); +} + +void +_clutter_stage_set_window (ClutterStage *stage, + ClutterStageWindow *stage_window) +{ + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (stage_window)); + + if (stage->priv->impl != NULL) + g_object_unref (stage->priv->impl); + + stage->priv->impl = stage_window; +} + +ClutterStageWindow * +_clutter_stage_get_window (ClutterStage *stage) +{ + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL); + + return CLUTTER_STAGE_WINDOW (stage->priv->impl); +} + +ClutterStageWindow * +_clutter_stage_get_default_window (void) +{ + ClutterStageManager *manager = clutter_stage_manager_get_default (); + ClutterStage *stage; + + stage = clutter_stage_manager_get_default_stage (manager); + if (stage == NULL) + return NULL; + + return _clutter_stage_get_window (stage); +} + +/** + * clutter_stage_set_throttle_motion_events: + * @stage: a #ClutterStage + * @throttle: %TRUE to throttle motion events + * + * Sets whether motion events received between redraws should + * be throttled or not. If motion events are throttled, those + * events received by the windowing system between redraws will + * be compressed so that only the last event will be propagated + * to the @stage and its actors. + * + * This function should only be used if you want to have all + * the motion events delivered to your application code. + * + * Since: 1.0 + */ +void +clutter_stage_set_throttle_motion_events (ClutterStage *stage, + gboolean throttle) +{ + ClutterStagePrivate *priv; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + priv = stage->priv; + + if (priv->throttle_motion_events != throttle) + priv->throttle_motion_events = throttle; +} + +/** + * clutter_stage_get_throttle_motion_events: + * @stage: a #ClutterStage + * + * Retrieves the value set with clutter_stage_set_throttle_motion_events() + * + * Return value: %TRUE if the motion events are being throttled, + * and %FALSE otherwise + * + * Since: 1.0 + */ +gboolean +clutter_stage_get_throttle_motion_events (ClutterStage *stage) +{ + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); + + return stage->priv->throttle_motion_events; +} + +/** + * clutter_stage_set_use_alpha: + * @stage: a #ClutterStage + * @use_alpha: whether the stage should honour the opacity or the + * alpha channel of the stage color + * + * Sets whether the @stage should honour the #ClutterActor:opacity and + * the alpha channel of the #ClutterStage:color + * + * Since: 1.2 + */ +void +clutter_stage_set_use_alpha (ClutterStage *stage, + gboolean use_alpha) +{ + ClutterStagePrivate *priv; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + priv = stage->priv; + + if (priv->use_alpha != use_alpha) + { + priv->use_alpha = use_alpha; + + clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); + + g_object_notify (G_OBJECT (stage), "use-alpha"); + } +} + +/** + * clutter_stage_get_use_alpha: + * @stage: a #ClutterStage + * + * Retrieves the value set using clutter_stage_set_use_alpha() + * + * Return value: %TRUE if the stage should honour the opacity and the + * alpha channel of the stage color + * + * Since: 1.2 + */ +gboolean +clutter_stage_get_use_alpha (ClutterStage *stage) +{ + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); + + return stage->priv->use_alpha; +} + +/** + * clutter_stage_set_minimum_size: + * @stage: a #ClutterStage + * @width: width, in pixels + * @height: height, in pixels + * + * Sets the minimum size for a stage window, if the default backend + * uses #ClutterStage inside a window + * + * This is a convenience function, and it is equivalent to setting the + * #ClutterActor:min-width and #ClutterActor:min-height on @stage + * + * If the current size of @stage is smaller than the minimum size, the + * @stage will be resized to the new @width and @height + * + * This function has no effect if @stage is fullscreen + * + * Since: 1.2 + */ +void +clutter_stage_set_minimum_size (ClutterStage *stage, + guint width, + guint height) +{ + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + g_return_if_fail ((width > 0) && (height > 0)); + + g_object_set (G_OBJECT (stage), + "min-width", (gfloat) width, + "min-height", (gfloat )height, + NULL); +} + +/** + * clutter_stage_get_minimum_size: + * @stage: a #ClutterStage + * @width: (out): return location for the minimum width, in pixels, + * or %NULL + * @height: (out): return location for the minimum height, in pixels, + * or %NULL + * + * Retrieves the minimum size for a stage window as set using + * clutter_stage_set_minimum_size(). + * + * The returned size may not correspond to the actual minimum size and + * it is specific to the #ClutterStage implementation inside the + * Clutter backend + * + * Since: 1.2 + */ +void +clutter_stage_get_minimum_size (ClutterStage *stage, + guint *width_p, + guint *height_p) +{ + gfloat width, height; + gboolean width_set, height_set; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + g_object_get (G_OBJECT (stage), + "min-width", &width, + "min-width-set", &width_set, + "min-height", &height, + "min-height-set", &height_set, + NULL); + + /* if not width or height have been set, then the Stage + * minimum size is defined to be 1x1 + */ + if (!width_set) + width = 1; + + if (!height_set) + height = 1; + + if (width_p) + *width_p = (guint) width; + + if (height_p) + *height_p = (guint) height; +} + +void +_clutter_stage_schedule_update (ClutterStage *stage) +{ + ClutterStageWindow *stage_window; + + if (CLUTTER_ACTOR_IN_DESTRUCTION (stage)) + return; + + stage_window = _clutter_stage_get_window (stage); + if (stage_window == NULL) + return; + + return _clutter_stage_window_schedule_update (stage_window, + stage->priv->sync_delay); +} + +/* Returns the earliest time the stage is ready to update */ +gint64 +_clutter_stage_get_update_time (ClutterStage *stage) +{ + ClutterStageWindow *stage_window; + + if (CLUTTER_ACTOR_IN_DESTRUCTION (stage)) + return 0; + + stage_window = _clutter_stage_get_window (stage); + if (stage_window == NULL) + return 0; + + return _clutter_stage_window_get_update_time (stage_window); +} + +void +_clutter_stage_clear_update_time (ClutterStage *stage) +{ + ClutterStageWindow *stage_window; + + stage_window = _clutter_stage_get_window (stage); + if (stage_window) + _clutter_stage_window_clear_update_time (stage_window); +} + +/** + * clutter_stage_set_no_clear_hint: + * @stage: a #ClutterStage + * @no_clear: %TRUE if the @stage should not clear itself on every + * repaint cycle + * + * Sets whether the @stage should clear itself at the beginning + * of each paint cycle or not. + * + * Clearing the #ClutterStage can be a costly operation, especially + * if the stage is always covered - for instance, in a full-screen + * video player or in a game with a background texture. + * + * This setting is a hint; Clutter might discard this hint + * depending on its internal state. + * + * If parts of the stage are visible and you disable clearing you + * might end up with visual artifacts while painting the contents of + * the stage. + * + * Since: 1.4 + */ +void +clutter_stage_set_no_clear_hint (ClutterStage *stage, + gboolean no_clear) +{ + ClutterStagePrivate *priv; + ClutterStageHint new_hints; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + priv = stage->priv; + new_hints = priv->stage_hints; + + if (no_clear) + new_hints |= CLUTTER_STAGE_NO_CLEAR_ON_PAINT; + else + new_hints &= ~CLUTTER_STAGE_NO_CLEAR_ON_PAINT; + + if (priv->stage_hints == new_hints) + return; + + priv->stage_hints = new_hints; + + g_object_notify (G_OBJECT (stage), "no-clear-hint"); +} + +/** + * clutter_stage_get_no_clear_hint: + * @stage: a #ClutterStage + * + * Retrieves the hint set with clutter_stage_set_no_clear_hint() + * + * Return value: %TRUE if the stage should not clear itself on every paint + * cycle, and %FALSE otherwise + * + * Since: 1.4 + */ +gboolean +clutter_stage_get_no_clear_hint (ClutterStage *stage) +{ + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); + + return (stage->priv->stage_hints & CLUTTER_STAGE_NO_CLEAR_ON_PAINT) != 0; +} + +ClutterPaintVolume * +_clutter_stage_paint_volume_stack_allocate (ClutterStage *stage) +{ + GArray *paint_volume_stack = stage->priv->paint_volume_stack; + + g_array_set_size (paint_volume_stack, + paint_volume_stack->len+1); + + return &g_array_index (paint_volume_stack, + ClutterPaintVolume, + paint_volume_stack->len - 1); +} + +void +_clutter_stage_paint_volume_stack_free_all (ClutterStage *stage) +{ + GArray *paint_volume_stack = stage->priv->paint_volume_stack; + int i; + + for (i = 0; i < paint_volume_stack->len; i++) + { + ClutterPaintVolume *pv = + &g_array_index (paint_volume_stack, ClutterPaintVolume, i); + clutter_paint_volume_free (pv); + } + + g_array_set_size (paint_volume_stack, 0); +} + +/* The is an out-of-band paramater available while painting that + * can be used to cull actors. */ +const ClutterPlane * +_clutter_stage_get_clip (ClutterStage *stage) +{ + return stage->priv->current_clip_planes; +} + +/* When an actor queues a redraw we add it to a list on the stage that + * gets processed once all updates to the stage have been finished. + * + * This deferred approach to processing queue_redraw requests means + * that we can avoid redundant transformations of clip volumes if + * something later triggers a full stage redraw anyway. It also means + * we can be more sure that all the referenced actors will have valid + * allocations improving the chance that we can determine the actors + * paint volume so we can clip the redraw request even if the user + * didn't explicitly do so. + */ +ClutterStageQueueRedrawEntry * +_clutter_stage_queue_actor_redraw (ClutterStage *stage, + ClutterStageQueueRedrawEntry *entry, + ClutterActor *actor, + ClutterPaintVolume *clip) +{ + ClutterStagePrivate *priv = stage->priv; + + CLUTTER_NOTE (CLIPPING, "stage_queue_actor_redraw (actor=%s, clip=%p): ", + _clutter_actor_get_debug_name (actor), clip); + + if (!priv->redraw_pending) + { + ClutterMasterClock *master_clock; + + CLUTTER_NOTE (PAINT, "First redraw request"); + + _clutter_stage_schedule_update (stage); + priv->redraw_pending = TRUE; + + master_clock = _clutter_master_clock_get_default (); + _clutter_master_clock_start_running (master_clock); + } +#ifdef CLUTTER_ENABLE_DEBUG + else + { + CLUTTER_NOTE (PAINT, "Redraw request number %lu", + priv->redraw_count + 1); + + priv->redraw_count += 1; + } +#endif /* CLUTTER_ENABLE_DEBUG */ + + if (entry) + { + /* Ignore all requests to queue a redraw for an actor if a full + * (non-clipped) redraw of the actor has already been queued. */ + if (!entry->has_clip) + { + CLUTTER_NOTE (CLIPPING, "Bail from stage_queue_actor_redraw (%s): " + "Unclipped redraw of actor already queued", + _clutter_actor_get_debug_name (actor)); + return entry; + } + + /* If queuing a clipped redraw and a clipped redraw has + * previously been queued for this actor then combine the latest + * clip together with the existing clip */ + if (clip) + clutter_paint_volume_union (&entry->clip, clip); + else + { + clutter_paint_volume_free (&entry->clip); + entry->has_clip = FALSE; + } + return entry; + } + else + { + entry = g_slice_new (ClutterStageQueueRedrawEntry); + entry->actor = g_object_ref (actor); + + if (clip) + { + entry->has_clip = TRUE; + _clutter_paint_volume_init_static (&entry->clip, actor); + _clutter_paint_volume_set_from_volume (&entry->clip, clip); + } + else + entry->has_clip = FALSE; + + stage->priv->pending_queue_redraws = + g_list_prepend (stage->priv->pending_queue_redraws, entry); + + return entry; + } +} + +static void +free_queue_redraw_entry (ClutterStageQueueRedrawEntry *entry) +{ + if (entry->actor) + g_object_unref (entry->actor); + if (entry->has_clip) + clutter_paint_volume_free (&entry->clip); + g_slice_free (ClutterStageQueueRedrawEntry, entry); +} + +void +_clutter_stage_queue_redraw_entry_invalidate (ClutterStageQueueRedrawEntry *entry) +{ + if (entry == NULL) + return; + + if (entry->actor != NULL) + { + g_object_unref (entry->actor); + entry->actor = NULL; + } + + if (entry->has_clip) + { + clutter_paint_volume_free (&entry->clip); + entry->has_clip = FALSE; + } +} + +static void +clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage) +{ + /* Note: we have to repeat until the pending_queue_redraws list is + * empty because actors are allowed to queue redraws in response to + * the queue-redraw signal. For example Clone actors or + * texture_new_from_actor actors will have to queue a redraw if + * their source queues a redraw. + */ + while (stage->priv->pending_queue_redraws) + { + GList *l; + /* XXX: we need to allow stage->priv->pending_queue_redraws to + * be updated while we process the current entries in the list + * so we steal the list pointer and then reset it to an empty + * list before processing... */ + GList *stolen_list = stage->priv->pending_queue_redraws; + stage->priv->pending_queue_redraws = NULL; + + for (l = stolen_list; l; l = l->next) + { + ClutterStageQueueRedrawEntry *entry = l->data; + ClutterPaintVolume *clip; + + /* NB: Entries may be invalidated if the actor gets destroyed */ + if (G_LIKELY (entry->actor != NULL)) + { + clip = entry->has_clip ? &entry->clip : NULL; + + _clutter_actor_finish_queue_redraw (entry->actor, clip); + } + + free_queue_redraw_entry (entry); + } + g_list_free (stolen_list); + } +} + +/** + * clutter_stage_set_accept_focus: + * @stage: a #ClutterStage + * @accept_focus: %TRUE to accept focus on show + * + * Sets whether the @stage should accept the key focus when shown. + * + * This function should be called before showing @stage using + * clutter_actor_show(). + * + * Since: 1.6 + */ +void +clutter_stage_set_accept_focus (ClutterStage *stage, + gboolean accept_focus) +{ + ClutterStagePrivate *priv; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + accept_focus = !!accept_focus; + + priv = stage->priv; + + if (priv->accept_focus != accept_focus) + { + _clutter_stage_window_set_accept_focus (priv->impl, accept_focus); + g_object_notify (G_OBJECT (stage), "accept-focus"); + } +} + +/** + * clutter_stage_get_accept_focus: + * @stage: a #ClutterStage + * + * Retrieves the value set with clutter_stage_set_accept_focus(). + * + * Return value: %TRUE if the #ClutterStage should accept focus, and %FALSE + * otherwise + * + * Since: 1.6 + */ +gboolean +clutter_stage_get_accept_focus (ClutterStage *stage) +{ + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), TRUE); + + return stage->priv->accept_focus; +} + +/** + * clutter_stage_set_motion_events_enabled: + * @stage: a #ClutterStage + * @enabled: %TRUE to enable the motion events delivery, and %FALSE + * otherwise + * + * Sets whether per-actor motion events (and relative crossing + * events) should be disabled or not. + * + * The default is %TRUE. + * + * If @enable is %FALSE the following signals will not be emitted + * by the actors children of @stage: + * + * - #ClutterActor::motion-event + * - #ClutterActor::enter-event + * - #ClutterActor::leave-event + * + * The events will still be delivered to the #ClutterStage. + * + * The main side effect of this function is that disabling the motion + * events will disable picking to detect the #ClutterActor underneath + * the pointer for each motion event. This is useful, for instance, + * when dragging a #ClutterActor across the @stage: the actor underneath + * the pointer is not going to change, so it's meaningless to perform + * a pick. + * + * Since: 1.8 + */ +void +clutter_stage_set_motion_events_enabled (ClutterStage *stage, + gboolean enabled) +{ + ClutterStagePrivate *priv; + + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + priv = stage->priv; + + enabled = !!enabled; + + if (priv->motion_events_enabled != enabled) + priv->motion_events_enabled = enabled; +} + +/** + * clutter_stage_get_motion_events_enabled: + * @stage: a #ClutterStage + * + * Retrieves the value set using clutter_stage_set_motion_events_enabled(). + * + * Return value: %TRUE if the per-actor motion event delivery is enabled + * and %FALSE otherwise + * + * Since: 1.8 + */ +gboolean +clutter_stage_get_motion_events_enabled (ClutterStage *stage) +{ + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); + + return stage->priv->motion_events_enabled; +} + +/* NB: The presumption shouldn't be that a stage can't be comprised + * of multiple internal framebuffers, so instead of simply naming + * this function _clutter_stage_get_framebuffer(), the "active" + * infix is intended to clarify that it gets the framebuffer that + * is currently in use/being painted. + */ +CoglFramebuffer * +_clutter_stage_get_active_framebuffer (ClutterStage *stage) +{ + return stage->priv->active_framebuffer; +} + +gint32 +_clutter_stage_acquire_pick_id (ClutterStage *stage, + ClutterActor *actor) +{ + ClutterStagePrivate *priv = stage->priv; + + g_assert (priv->pick_id_pool != NULL); + + return _clutter_id_pool_add (priv->pick_id_pool, actor); +} + +void +_clutter_stage_release_pick_id (ClutterStage *stage, + gint32 pick_id) +{ + ClutterStagePrivate *priv = stage->priv; + + g_assert (priv->pick_id_pool != NULL); + + _clutter_id_pool_remove (priv->pick_id_pool, pick_id); +} + +ClutterActor * +_clutter_stage_get_actor_by_pick_id (ClutterStage *stage, + gint32 pick_id) +{ + ClutterStagePrivate *priv = stage->priv; + + g_assert (priv->pick_id_pool != NULL); + + return _clutter_id_pool_lookup (priv->pick_id_pool, pick_id); +} + +void +_clutter_stage_add_pointer_drag_actor (ClutterStage *stage, + ClutterInputDevice *device, + ClutterActor *actor) +{ + GHashTable *drag_actors; + + drag_actors = g_object_get_data (G_OBJECT (stage), + "__clutter_stage_pointer_drag_actors"); + if (drag_actors == NULL) + { + drag_actors = g_hash_table_new (NULL, NULL); + g_object_set_data_full (G_OBJECT (stage), + "__clutter_stage_pointer_drag_actors", + drag_actors, + (GDestroyNotify) g_hash_table_destroy); + } + + g_hash_table_replace (drag_actors, device, actor); +} + +ClutterActor * +_clutter_stage_get_pointer_drag_actor (ClutterStage *stage, + ClutterInputDevice *device) +{ + GHashTable *drag_actors; + + drag_actors = g_object_get_data (G_OBJECT (stage), + "__clutter_stage_pointer_drag_actors"); + if (drag_actors == NULL) + return NULL; + + return g_hash_table_lookup (drag_actors, device); +} + +void +_clutter_stage_remove_pointer_drag_actor (ClutterStage *stage, + ClutterInputDevice *device) +{ + GHashTable *drag_actors; + + drag_actors = g_object_get_data (G_OBJECT (stage), + "__clutter_stage_pointer_drag_actors"); + if (drag_actors == NULL) + return; + + g_hash_table_remove (drag_actors, device); + + if (g_hash_table_size (drag_actors) == 0) + g_object_set_data (G_OBJECT (stage), + "__clutter_stage_pointer_drag_actors", + NULL); +} + +void +_clutter_stage_add_touch_drag_actor (ClutterStage *stage, + ClutterEventSequence *sequence, + ClutterActor *actor) +{ + GHashTable *drag_actors; + + drag_actors = g_object_get_data (G_OBJECT (stage), + "__clutter_stage_touch_drag_actors"); + if (drag_actors == NULL) + { + drag_actors = g_hash_table_new (NULL, NULL); + g_object_set_data_full (G_OBJECT (stage), + "__clutter_stage_touch_drag_actors", + drag_actors, + (GDestroyNotify) g_hash_table_destroy); + } + + g_hash_table_replace (drag_actors, sequence, actor); +} + +ClutterActor * +_clutter_stage_get_touch_drag_actor (ClutterStage *stage, + ClutterEventSequence *sequence) +{ + GHashTable *drag_actors; + + drag_actors = g_object_get_data (G_OBJECT (stage), + "__clutter_stage_touch_drag_actors"); + if (drag_actors == NULL) + return NULL; + + return g_hash_table_lookup (drag_actors, sequence); +} + +void +_clutter_stage_remove_touch_drag_actor (ClutterStage *stage, + ClutterEventSequence *sequence) +{ + GHashTable *drag_actors; + + drag_actors = g_object_get_data (G_OBJECT (stage), + "__clutter_stage_touch_drag_actors"); + if (drag_actors == NULL) + return; + + g_hash_table_remove (drag_actors, sequence); + + if (g_hash_table_size (drag_actors) == 0) + g_object_set_data (G_OBJECT (stage), + "__clutter_stage_touch_drag_actors", + NULL); +} + +/*< private > + * _clutter_stage_get_state: + * @stage: a #ClutterStage + * + * Retrieves the current #ClutterStageState flags associated to the @stage. + * + * Return value: a bitwise OR of #ClutterStageState flags + */ +ClutterStageState +_clutter_stage_get_state (ClutterStage *stage) +{ + return stage->priv->current_state; +} + +/*< private > + * _clutter_stage_is_activated: + * @stage: a #ClutterStage + * + * Checks whether the @stage state includes %CLUTTER_STAGE_STATE_ACTIVATED. + * + * Return value: %TRUE if the @stage is active + */ +gboolean +_clutter_stage_is_activated (ClutterStage *stage) +{ + return (stage->priv->current_state & CLUTTER_STAGE_STATE_ACTIVATED) != 0; +} + +/*< private > + * _clutter_stage_is_fullscreen: + * @stage: a #ClutterStage + * + * Checks whether the @stage state includes %CLUTTER_STAGE_STATE_FULLSCREEN. + * + * Return value: %TRUE if the @stage is fullscreen + */ +gboolean +_clutter_stage_is_fullscreen (ClutterStage *stage) +{ + return (stage->priv->current_state & CLUTTER_STAGE_STATE_FULLSCREEN) != 0; +} + +/*< private > + * _clutter_stage_update_state: + * @stage: a #ClutterStage + * @unset_flags: flags to unset + * @set_flags: flags to set + * + * Updates the state of @stage, by unsetting the @unset_flags and setting + * the @set_flags. + * + * If the stage state has been changed, this function will queue a + * #ClutterEvent of type %CLUTTER_STAGE_STATE. + * + * Return value: %TRUE if the state was updated, and %FALSE otherwise + */ +gboolean +_clutter_stage_update_state (ClutterStage *stage, + ClutterStageState unset_flags, + ClutterStageState set_flags) +{ + ClutterStageState new_state; + ClutterEvent event; + + new_state = stage->priv->current_state; + new_state |= set_flags; + new_state &= ~unset_flags; + + if (new_state == stage->priv->current_state) + return FALSE; + + memset (&event, 0, sizeof (event)); + event.type = CLUTTER_STAGE_STATE; + clutter_event_set_stage (&event, stage); + + event.stage_state.new_state = new_state; + event.stage_state.changed_mask = new_state ^ stage->priv->current_state; + + stage->priv->current_state = new_state; + + clutter_stage_event (stage, &event); + + return TRUE; +} + +/** + * clutter_stage_set_sync_delay: + * @stage: a #ClutterStage + * @sync_delay: number of milliseconds after frame presentation to wait + * before painting the next frame. If less than zero, restores the + * default behavior where redraw is throttled to the refresh rate but + * not synchronized to it. + * + * This function enables an alternate behavior where Clutter draws at + * a fixed point in time after the frame presentation time (also known + * as the VBlank time). This is most useful when the application + * wants to show incoming data with predictable latency. (The primary + * example of this would be a window system compositor.) By synchronizing + * to provide new data before Clutter redraws, an external source of + * updates (in the compositor, an application) can get a reliable latency. + * + * The appropriate value of @sync_delay depends on the complexity of + * drawing the stage's scene graph - in general a value of between 0 + * and 8 ms (up to one-half of a typical 60hz frame rate) is appropriate. + * using a larger value will reduce latency but risks skipping a frame if + * drawing the stage takes too long. + * + * Since: 1.14 + * Stability: unstable + */ +void +clutter_stage_set_sync_delay (ClutterStage *stage, + gint sync_delay) +{ + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + stage->priv->sync_delay = sync_delay; +} + +/** + * clutter_stage_skip_sync_delay: + * @stage: a #ClutterStage + * + * Causes the next frame for the stage to be drawn as quickly as + * possible, ignoring any delay that clutter_stage_set_sync_delay() + * would normally cause. + * + * Since: 1.14 + * Stability: unstable + */ +void +clutter_stage_skip_sync_delay (ClutterStage *stage) +{ + ClutterStageWindow *stage_window; + + stage_window = _clutter_stage_get_window (stage); + if (stage_window) + _clutter_stage_window_schedule_update (stage_window, -1); +} + +void +_clutter_stage_set_scale_factor (ClutterStage *stage, + int factor) +{ + ClutterStagePrivate *priv = stage->priv; + + if (CLUTTER_ACTOR_IN_DESTRUCTION (stage)) + return; + + if (priv->impl == NULL) + return; + + _clutter_stage_window_set_scale_factor (priv->impl, factor); + + clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); +} + +int64_t +clutter_stage_get_frame_counter (ClutterStage *stage) +{ + ClutterStageWindow *stage_window; + + stage_window = _clutter_stage_get_window (stage); + return _clutter_stage_window_get_frame_counter (stage_window); +} + +void +_clutter_stage_presented (ClutterStage *stage, + CoglFrameEvent frame_event, + ClutterFrameInfo *frame_info) +{ + g_signal_emit (stage, stage_signals[PRESENTED], 0, + (int) frame_event, frame_info); +} + +static void +capture_view (ClutterStage *stage, + gboolean paint, + ClutterStageView *view, + cairo_rectangle_int_t *rect, + ClutterCapture *capture) +{ + CoglFramebuffer *framebuffer; + ClutterBackend *backend; + CoglContext *context; + cairo_surface_t *image; + uint8_t *data; + int stride; + CoglBitmap *bitmap; + cairo_rectangle_int_t view_layout; + + framebuffer = clutter_stage_view_get_framebuffer (view); + + if (paint) + { + _clutter_stage_maybe_setup_viewport (stage, view); + cogl_push_framebuffer (framebuffer); + clutter_stage_do_paint_view (stage, view, rect); + } + + image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, + rect->width, rect->height); + + data = cairo_image_surface_get_data (image); + stride = cairo_image_surface_get_stride (image); + + backend = clutter_get_default_backend (); + context = clutter_backend_get_cogl_context (backend); + bitmap = cogl_bitmap_new_for_data (context, + rect->width, rect->height, + CLUTTER_CAIRO_FORMAT_ARGB32, + stride, + data); + + clutter_stage_view_get_layout (view, &view_layout); + + cogl_framebuffer_read_pixels_into_bitmap (framebuffer, + rect->x - view_layout.x, + rect->y - view_layout.y, + COGL_READ_PIXELS_COLOR_BUFFER, + bitmap); + + if (paint) + cogl_pop_framebuffer (); + + capture->rect = *rect; + capture->image = image; + + cairo_surface_mark_dirty (capture->image); + cogl_object_unref (bitmap); +} + +gboolean +clutter_stage_capture (ClutterStage *stage, + gboolean paint, + cairo_rectangle_int_t *rect, + ClutterCapture **out_captures, + int *out_n_captures) +{ + ClutterStagePrivate *priv = stage->priv; + GList *views = _clutter_stage_window_get_views (priv->impl); + GList *l; + ClutterCapture *captures; + int n_captures; + + captures = g_new0 (ClutterCapture, g_list_length (views)); + n_captures = 0; + + for (l = views; l; l = l->next) + { + ClutterStageView *view = l->data; + cairo_rectangle_int_t view_layout; + cairo_region_t *region; + cairo_rectangle_int_t view_capture_rect; + + clutter_stage_view_get_layout (view, &view_layout); + region = cairo_region_create_rectangle (&view_layout); + cairo_region_intersect_rectangle (region, rect); + cairo_region_get_extents (region, &view_capture_rect); + cairo_region_destroy (region); + + if (view_capture_rect.width == 0 || view_capture_rect.height == 0) + continue; + + capture_view (stage, paint, view, &view_capture_rect, + &captures[n_captures]); + + n_captures++; + } + + *out_captures = captures; + *out_n_captures = n_captures; + + return TRUE; +} diff --git a/clutter/clutter/clutter-stage.h b/clutter/clutter/clutter-stage.h new file mode 100644 index 0000000..e8fbda8 --- /dev/null +++ b/clutter/clutter/clutter-stage.h @@ -0,0 +1,270 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __CLUTTER_STAGE_H__ +#define __CLUTTER_STAGE_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_STAGE (clutter_stage_get_type()) + +#define CLUTTER_STAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STAGE, ClutterStage)) +#define CLUTTER_STAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_STAGE, ClutterStageClass)) +#define CLUTTER_IS_STAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_STAGE)) +#define CLUTTER_IS_STAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_STAGE)) +#define CLUTTER_STAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_STAGE, ClutterStageClass)) + +typedef struct _ClutterStageClass ClutterStageClass; +typedef struct _ClutterStagePrivate ClutterStagePrivate; + +/** + * ClutterStage: + * + * The #ClutterStage structure contains only private data + * and should be accessed using the provided API + * + * Since: 0.2 + */ +struct _ClutterStage +{ + /*< private >*/ + ClutterGroup parent_instance; + + ClutterStagePrivate *priv; +}; +/** + * ClutterStageClass: + * @fullscreen: handler for the #ClutterStage::fullscreen signal + * @unfullscreen: handler for the #ClutterStage::unfullscreen signal + * @activate: handler for the #ClutterStage::activate signal + * @deactivate: handler for the #ClutterStage::deactivate signal + * @delete_event: handler for the #ClutterStage::delete-event signal + * + * The #ClutterStageClass structure contains only private data + * + * Since: 0.2 + */ + +struct _ClutterStageClass +{ + /*< private >*/ + ClutterGroupClass parent_class; + + /*< public >*/ + /* signals */ + void (* fullscreen) (ClutterStage *stage); + void (* unfullscreen) (ClutterStage *stage); + void (* activate) (ClutterStage *stage); + void (* deactivate) (ClutterStage *stage); + + gboolean (* delete_event) (ClutterStage *stage, + ClutterEvent *event); + + /*< private >*/ + /* padding for future expansion */ + gpointer _padding_dummy[31]; +}; + +/** + * ClutterPerspective: + * @fovy: the field of view angle, in degrees, in the y direction + * @aspect: the aspect ratio that determines the field of view in the x + * direction. The aspect ratio is the ratio of x (width) to y (height) + * @z_near: the distance from the viewer to the near clipping + * plane (always positive) + * @z_far: the distance from the viewer to the far clipping + * plane (always positive) + * + * Stage perspective definition. #ClutterPerspective is only used by + * the fixed point version of clutter_stage_set_perspective(). + * + * Since: 0.4 + */ +struct _ClutterPerspective +{ + gfloat fovy; + gfloat aspect; + gfloat z_near; + gfloat z_far; +}; + +/** + * ClutterFog: + * @z_near: starting distance from the viewer to the near clipping + * plane (always positive) + * @z_far: final distance from the viewer to the far clipping + * plane (always positive) + * + * Fog settings used to create the depth cueing effect. + * + * Since: 0.6 + * + * Deprecated: 1.10: The fog-related API in #ClutterStage has been + * deprecated as well. + */ +struct _ClutterFog +{ + gfloat z_near; + gfloat z_far; +}; + +/** + * ClutterFrameInfo: (skip) + */ +struct _ClutterFrameInfo +{ + int64_t frame_counter; + int64_t presentation_time; + float refresh_rate; +}; + +typedef struct _ClutterCapture +{ + cairo_surface_t *image; + cairo_rectangle_int_t rect; +} ClutterCapture; + +CLUTTER_AVAILABLE_IN_ALL +GType clutter_perspective_get_type (void) G_GNUC_CONST; +CLUTTER_DEPRECATED_IN_1_10 +GType clutter_fog_get_type (void) G_GNUC_CONST; +CLUTTER_AVAILABLE_IN_ALL +GType clutter_stage_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_ALL +ClutterActor * clutter_stage_new (void); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_stage_set_perspective (ClutterStage *stage, + ClutterPerspective *perspective); +CLUTTER_AVAILABLE_IN_ALL +void clutter_stage_get_perspective (ClutterStage *stage, + ClutterPerspective *perspective); +CLUTTER_AVAILABLE_IN_ALL +void clutter_stage_set_fullscreen (ClutterStage *stage, + gboolean fullscreen); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_stage_get_fullscreen (ClutterStage *stage); +CLUTTER_AVAILABLE_IN_ALL +void clutter_stage_show_cursor (ClutterStage *stage); +CLUTTER_AVAILABLE_IN_ALL +void clutter_stage_hide_cursor (ClutterStage *stage); +CLUTTER_AVAILABLE_IN_ALL +void clutter_stage_set_title (ClutterStage *stage, + const gchar *title); +CLUTTER_AVAILABLE_IN_ALL +const gchar * clutter_stage_get_title (ClutterStage *stage); +CLUTTER_AVAILABLE_IN_ALL +void clutter_stage_set_user_resizable (ClutterStage *stage, + gboolean resizable); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_stage_get_user_resizable (ClutterStage *stage); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_stage_set_minimum_size (ClutterStage *stage, + guint width, + guint height); +CLUTTER_AVAILABLE_IN_ALL +void clutter_stage_get_minimum_size (ClutterStage *stage, + guint *width, + guint *height); +CLUTTER_AVAILABLE_IN_ALL +void clutter_stage_set_no_clear_hint (ClutterStage *stage, + gboolean no_clear); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_stage_get_no_clear_hint (ClutterStage *stage); +CLUTTER_AVAILABLE_IN_ALL +void clutter_stage_set_use_alpha (ClutterStage *stage, + gboolean use_alpha); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_stage_get_use_alpha (ClutterStage *stage); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_stage_set_key_focus (ClutterStage *stage, + ClutterActor *actor); +CLUTTER_AVAILABLE_IN_ALL +ClutterActor * clutter_stage_get_key_focus (ClutterStage *stage); +CLUTTER_AVAILABLE_IN_ALL +void clutter_stage_set_throttle_motion_events (ClutterStage *stage, + gboolean throttle); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_stage_get_throttle_motion_events (ClutterStage *stage); +CLUTTER_AVAILABLE_IN_ALL +void clutter_stage_set_motion_events_enabled (ClutterStage *stage, + gboolean enabled); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_stage_get_motion_events_enabled (ClutterStage *stage); +CLUTTER_AVAILABLE_IN_ALL +void clutter_stage_set_accept_focus (ClutterStage *stage, + gboolean accept_focus); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_stage_get_accept_focus (ClutterStage *stage); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_stage_event (ClutterStage *stage, + ClutterEvent *event); + +CLUTTER_AVAILABLE_IN_ALL +ClutterActor * clutter_stage_get_actor_at_pos (ClutterStage *stage, + ClutterPickMode pick_mode, + gint x, + gint y); +CLUTTER_AVAILABLE_IN_ALL +guchar * clutter_stage_read_pixels (ClutterStage *stage, + gint x, + gint y, + gint width, + gint height); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_stage_get_redraw_clip_bounds (ClutterStage *stage, + cairo_rectangle_int_t *clip); +CLUTTER_AVAILABLE_IN_ALL +void clutter_stage_ensure_viewport (ClutterStage *stage); +CLUTTER_AVAILABLE_IN_ALL +void clutter_stage_ensure_redraw (ClutterStage *stage); + +#ifdef CLUTTER_ENABLE_EXPERIMENTAL_API +CLUTTER_AVAILABLE_IN_1_14 +void clutter_stage_set_sync_delay (ClutterStage *stage, + gint sync_delay); +CLUTTER_AVAILABLE_IN_1_14 +void clutter_stage_skip_sync_delay (ClutterStage *stage); +#endif + +CLUTTER_AVAILABLE_IN_MUTTER +gboolean clutter_stage_capture (ClutterStage *stage, + gboolean paint, + cairo_rectangle_int_t *rect, + ClutterCapture **captures, + int *n_captures); + +G_END_DECLS + +#endif /* __CLUTTER_STAGE_H__ */ diff --git a/clutter/clutter/clutter-swipe-action.c b/clutter/clutter/clutter-swipe-action.c new file mode 100644 index 0000000..554f360 --- /dev/null +++ b/clutter/clutter/clutter-swipe-action.c @@ -0,0 +1,280 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * Copyright (C) 2011 Robert Bosch Car Multimedia GmbH. + * + * 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 . + * + * Author: + * Tomeu Vizoso + * + * Based on ClutterDragAction, written by: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-swipe-action + * @Title: ClutterSwipeAction + * @Short_Description: Action for swipe gestures + * + * #ClutterSwipeAction is a sub-class of #ClutterGestureAction that implements + * the logic for recognizing swipe gestures. + * + * Since: 1.8 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-swipe-action.h" + +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-gesture-action-private.h" +#include "clutter-marshal.h" +#include "clutter-private.h" + +struct _ClutterSwipeActionPrivate +{ + ClutterSwipeDirection h_direction; + ClutterSwipeDirection v_direction; + + float distance_x, distance_y; +}; + +enum +{ + SWEPT, + SWIPE, + + LAST_SIGNAL +}; + +static guint swipe_signals[LAST_SIGNAL] = { 0, }; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterSwipeAction, clutter_swipe_action, CLUTTER_TYPE_GESTURE_ACTION) + +static gboolean +gesture_begin (ClutterGestureAction *action, + ClutterActor *actor) +{ + ClutterSwipeActionPrivate *priv = CLUTTER_SWIPE_ACTION (action)->priv; + + /* reset the state at the beginning of a new gesture */ + priv->h_direction = 0; + priv->v_direction = 0; + + g_object_get (action, + "threshold-trigger-distance-x", &priv->distance_x, + "threshold-trigger-distance-y", &priv->distance_y, + NULL); + + return TRUE; +} + +static gboolean +gesture_progress (ClutterGestureAction *action, + ClutterActor *actor) +{ + ClutterSwipeActionPrivate *priv = CLUTTER_SWIPE_ACTION (action)->priv; + gfloat press_x, press_y; + gfloat motion_x, motion_y; + gfloat delta_x, delta_y; + ClutterSwipeDirection h_direction = 0, v_direction = 0; + + clutter_gesture_action_get_press_coords (action, + 0, + &press_x, + &press_y); + + clutter_gesture_action_get_motion_coords (action, + 0, + &motion_x, + &motion_y); + + delta_x = press_x - motion_x; + delta_y = press_y - motion_y; + + if (delta_x >= priv->distance_x) + h_direction = CLUTTER_SWIPE_DIRECTION_RIGHT; + else if (delta_x < -priv->distance_x) + h_direction = CLUTTER_SWIPE_DIRECTION_LEFT; + + if (delta_y >= priv->distance_y) + v_direction = CLUTTER_SWIPE_DIRECTION_DOWN; + else if (delta_y < -priv->distance_y) + v_direction = CLUTTER_SWIPE_DIRECTION_UP; + + /* cancel gesture on direction reversal */ + if (priv->h_direction == 0) + priv->h_direction = h_direction; + + if (priv->v_direction == 0) + priv->v_direction = v_direction; + + if (priv->h_direction != h_direction) + return FALSE; + + if (priv->v_direction != v_direction) + return FALSE; + + return TRUE; +} + +static void +gesture_end (ClutterGestureAction *action, + ClutterActor *actor) +{ + ClutterSwipeActionPrivate *priv = CLUTTER_SWIPE_ACTION (action)->priv; + gfloat press_x, press_y; + gfloat release_x, release_y; + ClutterSwipeDirection direction = 0; + gboolean can_emit_swipe; + const ClutterEvent *last_event; + + clutter_gesture_action_get_press_coords (action, + 0, + &press_x, &press_y); + + /* Check the last event instead of get_release_coords(), this + * might not be the sequence that finished on multi-finger swipes. + */ + last_event = clutter_gesture_action_get_last_event (action, 0); + clutter_event_get_coords (last_event, &release_x, &release_y); + + if (release_x - press_x > priv->distance_x) + direction |= CLUTTER_SWIPE_DIRECTION_RIGHT; + else if (press_x - release_x > priv->distance_x) + direction |= CLUTTER_SWIPE_DIRECTION_LEFT; + + if (release_y - press_y > priv->distance_y) + direction |= CLUTTER_SWIPE_DIRECTION_DOWN; + else if (press_y - release_y > priv->distance_y) + direction |= CLUTTER_SWIPE_DIRECTION_UP; + + /* XXX:2.0 remove */ + g_signal_emit (action, swipe_signals[SWIPE], 0, actor, direction, + &can_emit_swipe); + if (can_emit_swipe) + g_signal_emit (action, swipe_signals[SWEPT], 0, actor, direction); +} + +/* XXX:2.0 remove */ +static gboolean +clutter_swipe_action_real_swipe (ClutterSwipeAction *action, + ClutterActor *actor, + ClutterSwipeDirection direction) +{ + return TRUE; +} + +static void +clutter_swipe_action_constructed (GObject *object) +{ + clutter_gesture_action_set_threshold_trigger_edge (CLUTTER_GESTURE_ACTION (object), + CLUTTER_GESTURE_TRIGGER_EDGE_AFTER); +} + +static void +clutter_swipe_action_class_init (ClutterSwipeActionClass *klass) +{ + ClutterGestureActionClass *gesture_class = + CLUTTER_GESTURE_ACTION_CLASS (klass); + GObjectClass *object_class = + G_OBJECT_CLASS (klass); + + object_class->constructed = clutter_swipe_action_constructed; + + gesture_class->gesture_begin = gesture_begin; + gesture_class->gesture_progress = gesture_progress; + gesture_class->gesture_end = gesture_end; + + /* XXX:2.0 remove */ + klass->swipe = clutter_swipe_action_real_swipe; + + /** + * ClutterSwipeAction::swept: + * @action: the #ClutterSwipeAction that emitted the signal + * @actor: the #ClutterActor attached to the @action + * @direction: the main direction of the swipe gesture + * + * The ::swept signal is emitted when a swipe gesture is recognized on the + * attached actor. + * + * Deprecated: 1.14: Use the ::swipe signal instead. + * + * Since: 1.8 + */ + swipe_signals[SWEPT] = + g_signal_new (I_("swept"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | + G_SIGNAL_DEPRECATED, + G_STRUCT_OFFSET (ClutterSwipeActionClass, swept), + NULL, NULL, + _clutter_marshal_VOID__OBJECT_FLAGS, + G_TYPE_NONE, 2, + CLUTTER_TYPE_ACTOR, + CLUTTER_TYPE_SWIPE_DIRECTION); + + /** + * ClutterSwipeAction::swipe: + * @action: the #ClutterSwipeAction that emitted the signal + * @actor: the #ClutterActor attached to the @action + * @direction: the main direction of the swipe gesture + * + * The ::swipe signal is emitted when a swipe gesture is recognized on the + * attached actor. + * + * Return value: %TRUE if the swipe should continue, and %FALSE if + * the swipe should be cancelled. + * + * Since: 1.14 + */ + swipe_signals[SWIPE] = + g_signal_new (I_("swipe"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterSwipeActionClass, swipe), + _clutter_boolean_continue_accumulator, NULL, + _clutter_marshal_BOOLEAN__OBJECT_FLAGS, + G_TYPE_BOOLEAN, 2, + CLUTTER_TYPE_ACTOR, + CLUTTER_TYPE_SWIPE_DIRECTION); +} + +static void +clutter_swipe_action_init (ClutterSwipeAction *self) +{ + self->priv = clutter_swipe_action_get_instance_private (self); +} + +/** + * clutter_swipe_action_new: + * + * Creates a new #ClutterSwipeAction instance + * + * Return value: the newly created #ClutterSwipeAction + * + * Since: 1.8 + */ +ClutterAction * +clutter_swipe_action_new (void) +{ + return g_object_new (CLUTTER_TYPE_SWIPE_ACTION, NULL); +} diff --git a/clutter/clutter/clutter-swipe-action.h b/clutter/clutter/clutter-swipe-action.h new file mode 100644 index 0000000..9c18e94 --- /dev/null +++ b/clutter/clutter/clutter-swipe-action.h @@ -0,0 +1,109 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * Copyright (C) 2011 Robert Bosch Car Multimedia GmbH. + * + * 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 . + * + * Author: + * Tomeu Vizoso + * + * Based on ClutterDragAction, written by: + * Emmanuele Bassi + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_SWIPE_ACTION_H__ +#define __CLUTTER_SWIPE_ACTION_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_SWIPE_ACTION (clutter_swipe_action_get_type ()) +#define CLUTTER_SWIPE_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_SWIPE_ACTION, ClutterSwipeAction)) +#define CLUTTER_IS_SWIPE_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_SWIPE_ACTION)) +#define CLUTTER_SWIPE_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_SWIPE_ACTION, ClutterSwipeActionClass)) +#define CLUTTER_IS_SWIPE_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_SWIPE_ACTION)) +#define CLUTTER_SWIPE_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_SWIPE_ACTION, ClutterSwipeActionClass)) + +typedef struct _ClutterSwipeAction ClutterSwipeAction; +typedef struct _ClutterSwipeActionPrivate ClutterSwipeActionPrivate; +typedef struct _ClutterSwipeActionClass ClutterSwipeActionClass; + +/** + * ClutterSwipeAction: + * + * The #ClutterSwipeAction structure contains + * only private data and should be accessed using the provided API + * + * Since: 1.8 + */ +struct _ClutterSwipeAction +{ + /*< private >*/ + ClutterGestureAction parent_instance; + + ClutterSwipeActionPrivate *priv; +}; + +/** + * ClutterSwipeActionClass: + * @swept: class handler for the #ClutterSwipeAction::swept signal; + * deprecated since 1.14 + * @swipe: class handler for the #ClutterSwipeAction::swipe signal + * + * The #ClutterSwipeActionClass structure contains + * only private data. + * + * Since: 1.8 + */ +struct _ClutterSwipeActionClass +{ + /*< private >*/ + ClutterGestureActionClass parent_class; + + /*< public >*/ + void (* swept) (ClutterSwipeAction *action, + ClutterActor *actor, + ClutterSwipeDirection direction); + + gboolean (* swipe) (ClutterSwipeAction *action, + ClutterActor *actor, + ClutterSwipeDirection direction); + + /*< private >*/ + void (* _clutter_swipe_action1) (void); + void (* _clutter_swipe_action2) (void); + void (* _clutter_swipe_action3) (void); + void (* _clutter_swipe_action4) (void); + void (* _clutter_swipe_action5) (void); + void (* _clutter_swipe_action6) (void); +}; + +CLUTTER_AVAILABLE_IN_1_8 +GType clutter_swipe_action_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_8 +ClutterAction * clutter_swipe_action_new (void); + +G_END_DECLS + +#endif /* __CLUTTER_SWIPE_ACTION_H__ */ diff --git a/clutter/clutter/clutter-tap-action.c b/clutter/clutter/clutter-tap-action.c new file mode 100644 index 0000000..ae9f69d --- /dev/null +++ b/clutter/clutter/clutter-tap-action.c @@ -0,0 +1,151 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * Copyright (C) 2011 Robert Bosch Car Multimedia GmbH. + * Copyright (C) 2012 Collabora Ltd. + * + * 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 . + * + * Author: + * Emanuele Aina + * + * Based on ClutterPanAction + * Based on ClutterDragAction, ClutterSwipeAction, and MxKineticScrollView, + * written by: + * Emmanuele Bassi + * Tomeu Vizoso + * Chris Lord + */ + +/** + * SECTION:clutter-tap-action + * @Title: ClutterTapAction + * @Short_Description: Action for tap gestures + * + * #ClutterTapAction is a sub-class of #ClutterGestureAction that implements + * the logic for recognizing mouse clicks and touch tap gestures. + * + * The simplest usage of #ClutterTapAction consists in adding it to + * a #ClutterActor, setting it as reactive and connecting a + * callback for the #ClutterTapAction::tap signal, along the lines of the + * following code: + * + * |[ + * clutter_actor_add_action (actor, clutter_tap_action_new ()); + * clutter_actor_set_reactive (actor, TRUE); + * g_signal_connect (action, "tap", G_CALLBACK (on_tap_callback), NULL); + * ]| + * + * Since: 1.14 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-tap-action.h" + +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-gesture-action-private.h" +#include "clutter-marshal.h" +#include "clutter-private.h" + +enum +{ + TAP, + + LAST_SIGNAL +}; + +static guint tap_signals[LAST_SIGNAL] = { 0, }; + +G_DEFINE_TYPE (ClutterTapAction, clutter_tap_action, + CLUTTER_TYPE_GESTURE_ACTION); + +static void +emit_tap (ClutterTapAction *self, + ClutterActor *actor) +{ + g_signal_emit (self, tap_signals[TAP], 0, actor); +} + +static void +gesture_end (ClutterGestureAction *gesture, + ClutterActor *actor) +{ + emit_tap (CLUTTER_TAP_ACTION (gesture), actor); +} + +static void +clutter_tap_action_constructed (GObject *object) +{ + clutter_gesture_action_set_threshold_trigger_edge (CLUTTER_GESTURE_ACTION (object), + CLUTTER_GESTURE_TRIGGER_EDGE_BEFORE); +} + +static void +clutter_tap_action_class_init (ClutterTapActionClass *klass) +{ + ClutterGestureActionClass *gesture_class = + CLUTTER_GESTURE_ACTION_CLASS (klass); + GObjectClass *object_class = + G_OBJECT_CLASS (klass); + + object_class->constructed = clutter_tap_action_constructed; + + gesture_class->gesture_end = gesture_end; + + /** + * ClutterTapAction::tap: + * @action: the #ClutterTapAction that emitted the signal + * @actor: the #ClutterActor attached to the @action + * + * The ::tap signal is emitted when the tap gesture is complete. + * + * Since: 1.14 + */ + tap_signals[TAP] = + g_signal_new (I_("tap"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterTapActionClass, tap), + NULL, NULL, + _clutter_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CLUTTER_TYPE_ACTOR); +} + +static void +clutter_tap_action_init (ClutterTapAction *self) +{ +} + +/** + * clutter_tap_action_new: + * + * Creates a new #ClutterTapAction instance + * + * Return value: the newly created #ClutterTapAction + * + * Since: 1.14 + */ +ClutterAction * +clutter_tap_action_new (void) +{ + return g_object_new (CLUTTER_TYPE_TAP_ACTION, NULL); +} diff --git a/clutter/clutter/clutter-tap-action.h b/clutter/clutter/clutter-tap-action.h new file mode 100644 index 0000000..ade9c42 --- /dev/null +++ b/clutter/clutter/clutter-tap-action.h @@ -0,0 +1,102 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * Copyright (C) 2011 Robert Bosch Car Multimedia GmbH. + * Copyright (C) 2012 Collabora Ltd. + * + * 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 . + * + * Author: + * Emanuele Aina + * + * Based on ClutterPanAction + * Based on ClutterDragAction, ClutterSwipeAction, and MxKineticScrollView, + * written by: + * Emmanuele Bassi + * Tomeu Vizoso + * Chris Lord + */ + +#ifndef __CLUTTER_TAP_ACTION_H__ +#define __CLUTTER_TAP_ACTION_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_TAP_ACTION (clutter_tap_action_get_type ()) +#define CLUTTER_TAP_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_TAP_ACTION, ClutterTapAction)) +#define CLUTTER_IS_TAP_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_TAP_ACTION)) +#define CLUTTER_TAP_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_TAP_ACTION, ClutterTapActionClass)) +#define CLUTTER_IS_TAP_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_TAP_ACTION)) +#define CLUTTER_TAP_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_TAP_ACTION, ClutterTapActionClass)) + +typedef struct _ClutterTapAction ClutterTapAction; +typedef struct _ClutterTapActionPrivate ClutterTapActionPrivate; +typedef struct _ClutterTapActionClass ClutterTapActionClass; + +/** + * ClutterTapAction: + * + * The #ClutterTapAction structure contains + * only private data and should be accessed using the provided API + * + * Since: 1.14 + */ +struct _ClutterTapAction +{ + /*< private >*/ + ClutterGestureAction parent_instance; +}; + +/** + * ClutterTapActionClass: + * @tap: class handler for the #ClutterTapAction::tap signal + * + * The #ClutterTapActionClass structure contains + * only private data. + */ +struct _ClutterTapActionClass +{ + /*< private >*/ + ClutterGestureActionClass parent_class; + + /*< public >*/ + gboolean (* tap) (ClutterTapAction *action, + ClutterActor *actor); + + /*< private >*/ + void (* _clutter_tap_action1) (void); + void (* _clutter_tap_action2) (void); + void (* _clutter_tap_action3) (void); + void (* _clutter_tap_action4) (void); + void (* _clutter_tap_action5) (void); + void (* _clutter_tap_action6) (void); +}; + +CLUTTER_AVAILABLE_IN_1_14 +GType clutter_tap_action_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_14 +ClutterAction * clutter_tap_action_new (void); +G_END_DECLS + +#endif /* __CLUTTER_TAP_ACTION_H__ */ diff --git a/clutter/clutter/clutter-test-utils.c b/clutter/clutter/clutter-test-utils.c new file mode 100644 index 0000000..edc413e --- /dev/null +++ b/clutter/clutter/clutter-test-utils.c @@ -0,0 +1,467 @@ +#include "clutter-build-config.h" + +#include "clutter-test-utils.h" + +#include +#include + +#include "clutter-actor.h" +#include "clutter-color.h" +#include "clutter-event.h" +#include "clutter-keysyms.h" +#include "clutter-main.h" +#include "clutter-private.h" +#include "clutter-stage.h" + +typedef struct { + ClutterActor *stage; + + guint no_display : 1; +} ClutterTestEnvironment; + +static ClutterTestEnvironment *test_environ = NULL; + +/* + * clutter_test_init: + * @argc: (inout): number of arguments in @argv + * @argv: (inout) (array length=argc) (nullable): array of arguments + * + * Initializes the Clutter test environment. + * + * Since: 1.18 + */ +void +clutter_test_init (int *argc, + char ***argv) +{ + gboolean no_display = FALSE; + + if (G_UNLIKELY (test_environ != NULL)) + g_error ("Attempting to initialize the test suite more than once, " + "aborting...\n"); + +#ifdef CLUTTER_WINDOWING_X11 + /* on X11 backends we need the DISPLAY environment set. + * + * check_windowing_backend() will pre-initialize the Clutter + * backend object. + */ + if (clutter_check_windowing_backend (CLUTTER_WINDOWING_X11)) + { + const char *display = g_getenv ("DISPLAY"); + + if (display == NULL || *display == '\0') + { + g_test_message ("No DISPLAY environment variable found, but we require a " + "DISPLAY set in order to run the conformance test suite.\n" + "Skipping all tests.\n"); + no_display = TRUE; + + goto out; + } + } +#endif + + /* we explicitly disable the synchronisation to the vertical refresh + * rate, and run the master clock using a 60 fps timer instead. + */ + _clutter_set_sync_to_vblank (FALSE); + + /* perform the actual initialization */ + g_assert (clutter_init (NULL, NULL) == CLUTTER_INIT_SUCCESS); + +out: + g_test_init (argc, argv, NULL); + g_test_bug_base ("https://bugzilla.gnome.org/show_bug.cgi?id=%s"); + + /* our global state, accessible from each test unit */ + test_environ = g_new0 (ClutterTestEnvironment, 1); + test_environ->no_display = no_display; +} + +/** + * clutter_test_get_stage: + * + * Retrieves the #ClutterStage used for testing. + * + * Return value: (transfer none): the stage used for testing + * + * Since: 1.18 + */ +ClutterActor * +clutter_test_get_stage (void) +{ + g_assert (test_environ != NULL); + + if (test_environ->stage == NULL) + { + /* create a stage, and ensure that it goes away at the end */ + test_environ->stage = clutter_stage_new (); + clutter_actor_set_name (test_environ->stage, "Test Stage"); + g_object_add_weak_pointer (G_OBJECT (test_environ->stage), + (gpointer *) &test_environ->stage); + } + + return test_environ->stage; +} + +typedef struct { + gpointer test_func; + gpointer test_data; + GDestroyNotify test_notify; +} ClutterTestData; + +static void +clutter_test_func_wrapper (gconstpointer data_) +{ + const ClutterTestData *data = data_; + + /* ensure that the previous test state has been cleaned up */ + g_assert_null (test_environ->stage); + + if (test_environ->no_display) + { + g_test_skip ("No DISPLAY set"); + goto out; + } + + if (data->test_data != NULL) + { + GTestDataFunc test_func = data->test_func; + + test_func (data->test_data); + } + else + { + GTestFunc test_func = data->test_func; + + test_func (); + } + +out: + if (data->test_notify != NULL) + data->test_notify (data->test_data); + + if (test_environ->stage != NULL) + { + clutter_actor_destroy (test_environ->stage); + g_assert_null (test_environ->stage); + } +} + +/** + * clutter_test_add: (skip) + * @test_path: unique path for identifying the test + * @test_func: function containing the test + * + * Adds a test unit to the Clutter test environment. + * + * See also: g_test_add() + * + * Since: 1.18 + */ +void +clutter_test_add (const char *test_path, + GTestFunc test_func) +{ + clutter_test_add_data_full (test_path, (GTestDataFunc) test_func, NULL, NULL); +} + +/** + * clutter_test_add_data: (skip) + * @test_path: unique path for identifying the test + * @test_func: function containing the test + * @test_data: data to pass to the test function + * + * Adds a test unit to the Clutter test environment. + * + * See also: g_test_add_data_func() + * + * Since: 1.18 + */ +void +clutter_test_add_data (const char *test_path, + GTestDataFunc test_func, + gpointer test_data) +{ + clutter_test_add_data_full (test_path, test_func, test_data, NULL); +} + +/** + * clutter_test_add_data_full: + * @test_path: unique path for identifying the test + * @test_func: (scope notified): function containing the test + * @test_data: (closure): data to pass to the test function + * @test_notify: function called when the test function ends + * + * Adds a test unit to the Clutter test environment. + * + * See also: g_test_add_data_func_full() + * + * Since: 1.18 + */ +void +clutter_test_add_data_full (const char *test_path, + GTestDataFunc test_func, + gpointer test_data, + GDestroyNotify test_notify) +{ + ClutterTestData *data; + + g_return_if_fail (test_path != NULL); + g_return_if_fail (test_func != NULL); + + g_assert (test_environ != NULL); + + data = g_new (ClutterTestData, 1); + data->test_func = test_func; + data->test_data = test_data; + data->test_notify = test_notify; + + g_test_add_data_func_full (test_path, data, + clutter_test_func_wrapper, + g_free); +} + +/** + * clutter_test_run: + * + * Runs the test suite using the units added by calling + * clutter_test_add(). + * + * The typical test suite is composed of a list of functions + * called by clutter_test_run(), for instance: + * + * |[ + * static void unit_foo (void) { ... } + * + * static void unit_bar (void) { ... } + * + * static void unit_baz (void) { ... } + * + * int + * main (int argc, char *argv[]) + * { + * clutter_test_init (&argc, &argv); + * + * clutter_test_add ("/unit/foo", unit_foo); + * clutter_test_add ("/unit/bar", unit_bar); + * clutter_test_add ("/unit/baz", unit_baz); + * + * return clutter_test_run (); + * } + * ]| + * + * Return value: the exit code for the test suite + * + * Since: 1.18 + */ +int +clutter_test_run (void) +{ + int res; + + g_assert (test_environ != NULL); + + res = g_test_run (); + + g_free (test_environ); + + return res; +} + +typedef struct { + ClutterActor *stage; + + ClutterPoint point; + + gpointer result; + + guint check_actor : 1; + guint check_color : 1; + + guint was_painted : 1; +} ValidateData; + +static gboolean +validate_stage (gpointer data_) +{ + ValidateData *data = data_; + + if (data->check_actor) + { + data->result = + clutter_stage_get_actor_at_pos (CLUTTER_STAGE (data->stage), + CLUTTER_PICK_ALL, + data->point.x, + data->point.y); + } + + if (data->check_color) + { + data->result = + clutter_stage_read_pixels (CLUTTER_STAGE (data->stage), + data->point.x, + data->point.y, + 1, 1); + } + + if (!g_test_verbose ()) + { + clutter_actor_hide (data->stage); + data->was_painted = TRUE; + } + + return G_SOURCE_REMOVE; +} + +static gboolean +on_key_press_event (ClutterActor *stage, + ClutterEvent *event, + gpointer data_) +{ + ValidateData *data = data_; + + if (data->stage == stage && + clutter_event_get_key_symbol (event) == CLUTTER_KEY_Escape) + { + clutter_actor_hide (stage); + + data->was_painted = TRUE; + } + + return CLUTTER_EVENT_PROPAGATE; +} + +/** + * clutter_test_check_actor_at_point: + * @stage: a #ClutterStage + * @point: coordinates to check + * @actor: the expected actor at the given coordinates + * @result: (out) (nullable): actor at the coordinates + * + * Checks the given coordinates of the @stage and compares the + * actor found there with the given @actor. + * + * Returns: %TRUE if the actor at the given coordinates matches + * + * Since: 1.18 + */ +gboolean +clutter_test_check_actor_at_point (ClutterActor *stage, + const ClutterPoint *point, + ClutterActor *actor, + ClutterActor **result) +{ + ValidateData *data; + guint press_id = 0; + + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); + g_return_val_if_fail (point != NULL, FALSE); + g_return_val_if_fail (CLUTTER_IS_ACTOR (stage), FALSE); + g_return_val_if_fail (result != NULL, FALSE); + + data = g_new0 (ValidateData, 1); + data->stage = stage; + data->point = *point; + data->check_actor = TRUE; + + if (g_test_verbose ()) + { + g_printerr ("Press ESC to close the stage and resume the test\n"); + press_id = g_signal_connect (stage, "key-press-event", + G_CALLBACK (on_key_press_event), + data); + } + + clutter_actor_show (stage); + + clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT, + validate_stage, + data, + NULL); + + while (!data->was_painted) + g_main_context_iteration (NULL, TRUE); + + *result = data->result; + + if (press_id != 0) + g_signal_handler_disconnect (stage, press_id); + + g_free (data); + + return *result == actor; +} + +/** + * clutter_test_check_color_at_point: + * @stage: a #ClutterStage + * @point: coordinates to check + * @color: expected color + * @result: (out caller-allocates): color at the given coordinates + * + * Checks the color at the given coordinates on @stage, and matches + * it with the red, green, and blue channels of @color. The alpha + * component of @color and @result is ignored. + * + * Returns: %TRUE if the colors match + * + * Since: 1.18 + */ +gboolean +clutter_test_check_color_at_point (ClutterActor *stage, + const ClutterPoint *point, + const ClutterColor *color, + ClutterColor *result) +{ + ValidateData *data; + gboolean retval; + guint8 *buffer; + guint press_id = 0; + + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); + g_return_val_if_fail (point != NULL, FALSE); + g_return_val_if_fail (color != NULL, FALSE); + g_return_val_if_fail (result != NULL, FALSE); + + data = g_new0 (ValidateData, 1); + data->stage = stage; + data->point = *point; + data->check_color = TRUE; + + if (g_test_verbose ()) + { + g_printerr ("Press ESC to close the stage and resume the test\n"); + press_id = g_signal_connect (stage, "key-press-event", + G_CALLBACK (on_key_press_event), + data); + } + + clutter_actor_show (stage); + + clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT, + validate_stage, + data, + NULL); + + while (!data->was_painted) + g_main_context_iteration (NULL, TRUE); + + if (press_id != 0) + g_signal_handler_disconnect (stage, press_id); + + buffer = data->result; + + clutter_color_init (result, buffer[0], buffer[1], buffer[2], 255); + + /* we only check the color channels, so we can't use clutter_color_equal() */ + retval = buffer[0] == color->red && + buffer[1] == color->green && + buffer[2] == color->blue; + + g_free (data->result); + g_free (data); + + return retval; +} diff --git a/clutter/clutter/clutter-test-utils.h b/clutter/clutter/clutter-test-utils.h new file mode 100644 index 0000000..81dad97 --- /dev/null +++ b/clutter/clutter/clutter-test-utils.h @@ -0,0 +1,164 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2013 Emmanuele Bassi + * + * 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 . + */ + +#ifndef __CLUTTER_TEST_UTILS_H__ +#define __CLUTTER_TEST_UTILS_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include +#include + +G_BEGIN_DECLS + +/** + * CLUTTER_TEST_UNIT: + * @path: the GTest path for the test function + * @func: the GTestFunc function + * + * Adds @func at the given @path in the test suite. + * + * Since: 1.18 + */ +#define CLUTTER_TEST_UNIT(path,func) \ + clutter_test_add (path, func); + +/** + * CLUTTER_TEST_SUITE: + * @units: a list of %CLUTTER_TEST_UNIT definitions + * + * Defines the entry point and initializes a Clutter test unit, e.g.: + * + * |[ + * CLUTTER_TEST_SUITE ( + * CLUTTER_TEST_UNIT ("/foobarize", foobarize) + * CLUTTER_TEST_UNIT ("/bar-enabled", bar_enabled) + * ) + * ]| + * + * Expands to: + * + * |[ + * int + * main (int argc, + * char *argv[]) + * { + * clutter_test_init (&argc, &argv); + * + * clutter_test_add ("/foobarize", foobarize); + * clutter_test_add ("/bar-enabled", bar_enabled); + * + * return clutter_test_run (); + * } + * ]| + * + * Since: 1.18 + */ +#define CLUTTER_TEST_SUITE(units) \ +int \ +main (int argc, char *argv[]) \ +{ \ + clutter_test_init (&argc, &argv); \ +\ + { \ + units \ + } \ +\ + return clutter_test_run (); \ +} + +CLUTTER_AVAILABLE_IN_1_18 +void clutter_test_init (int *argc, + char ***argv); +CLUTTER_AVAILABLE_IN_1_18 +int clutter_test_run (void); + +CLUTTER_AVAILABLE_IN_1_18 +void clutter_test_add (const char *test_path, + GTestFunc test_func); +CLUTTER_AVAILABLE_IN_1_18 +void clutter_test_add_data (const char *test_path, + GTestDataFunc test_func, + gpointer test_data); +CLUTTER_AVAILABLE_IN_1_18 +void clutter_test_add_data_full (const char *test_path, + GTestDataFunc test_func, + gpointer test_data, + GDestroyNotify test_notify); + +CLUTTER_AVAILABLE_IN_1_18 +ClutterActor * clutter_test_get_stage (void); + +#define clutter_test_assert_actor_at_point(stage,point,actor) \ +G_STMT_START { \ + const ClutterPoint *__p = (point); \ + ClutterActor *__actor = (actor); \ + ClutterActor *__stage = (stage); \ + ClutterActor *__res; \ + if (clutter_test_check_actor_at_point (__stage, __p, actor, &__res)) ; else { \ + const char *__str1 = clutter_actor_get_name (__actor) != NULL \ + ? clutter_actor_get_name (__actor) \ + : G_OBJECT_TYPE_NAME (__actor); \ + const char *__str2 = clutter_actor_get_name (__res) != NULL \ + ? clutter_actor_get_name (__res) \ + : G_OBJECT_TYPE_NAME (__res); \ + char *__msg = g_strdup_printf ("assertion failed (actor %s at %.2f,%.2f): found actor %s", \ + __str1, __p->x, __p->y, __str2); \ + g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, __msg); \ + g_free (__msg); \ + } \ +} G_STMT_END + +#define clutter_test_assert_color_at_point(stage,point,color) \ +G_STMT_START { \ + const ClutterPoint *__p = (point); \ + const ClutterColor *__c = (color); \ + ClutterActor *__stage = (stage); \ + ClutterColor __res; \ + if (clutter_test_check_color_at_point (__stage, __p, __c, &__res)) ; else { \ + char *__str1 = clutter_color_to_string (__c); \ + char *__str2 = clutter_color_to_string (&__res); \ + char *__msg = g_strdup_printf ("assertion failed (color %s at %.2f,%.2f): found color %s", \ + __str1, __p->x, __p->y, __str2); \ + g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, __msg); \ + g_free (__msg); \ + g_free (__str1); \ + g_free (__str2); \ + } \ +} G_STMT_END + +CLUTTER_AVAILABLE_IN_1_18 +gboolean clutter_test_check_actor_at_point (ClutterActor *stage, + const ClutterPoint *point, + ClutterActor *actor, + ClutterActor **result); +CLUTTER_AVAILABLE_IN_1_18 +gboolean clutter_test_check_color_at_point (ClutterActor *stage, + const ClutterPoint *point, + const ClutterColor *color, + ClutterColor *result); + +G_END_DECLS + +#endif /* __CLUTTER_TEST_UTILS_H__ */ diff --git a/clutter/clutter/clutter-text-buffer.c b/clutter/clutter/clutter-text-buffer.c new file mode 100644 index 0000000..5aaee36 --- /dev/null +++ b/clutter/clutter/clutter-text-buffer.c @@ -0,0 +1,766 @@ +/* clutter-text-buffer.c + * Copyright (C) 2011 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + * + * Author: Stef Walter + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-text-buffer.h" +#include "clutter-marshal.h" +#include "clutter-private.h" + +#include + +/** + * SECTION:clutter-text-buffer + * @title: ClutterTextBuffer + * @short_description: Text buffer for ClutterText + * + * The #ClutterTextBuffer class contains the actual text displayed in a + * #ClutterText widget. + * + * A single #ClutterTextBuffer object can be shared by multiple #ClutterText + * widgets which will then share the same text content, but not the cursor + * position, visibility attributes, icon etc. + * + * #ClutterTextBuffer may be derived from. Such a derived class might allow + * text to be stored in an alternate location, such as non-pageable memory, + * useful in the case of important passwords. Or a derived class could + * integrate with an application's concept of undo/redo. + * + * Since: 1.10 + */ + +/* Initial size of buffer, in bytes */ +#define MIN_SIZE 16 + +enum { + PROP_0, + PROP_TEXT, + PROP_LENGTH, + PROP_MAX_LENGTH, + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST] = { NULL, }; + +enum { + INSERTED_TEXT, + DELETED_TEXT, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +struct _ClutterTextBufferPrivate +{ + gint max_length; + + /* Only valid if this class is not derived */ + gchar *normal_text; + gsize normal_text_size; + gsize normal_text_bytes; + guint normal_text_chars; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterTextBuffer, clutter_text_buffer, G_TYPE_OBJECT) + +/* -------------------------------------------------------------------------------- + * DEFAULT IMPLEMENTATIONS OF TEXT BUFFER + * + * These may be overridden by a derived class, behavior may be changed etc... + * The normal_text and normal_text_xxxx fields may not be valid when + * this class is derived from. + */ + +/* Overwrite a memory that might contain sensitive information. */ +static void +trash_area (gchar *area, + gsize len) +{ + volatile gchar *varea = (volatile gchar *)area; + while (len-- > 0) + *varea++ = 0; +} + +static const gchar* +clutter_text_buffer_normal_get_text (ClutterTextBuffer *buffer, + gsize *n_bytes) +{ + if (n_bytes) + *n_bytes = buffer->priv->normal_text_bytes; + if (!buffer->priv->normal_text) + return ""; + return buffer->priv->normal_text; +} + +static guint +clutter_text_buffer_normal_get_length (ClutterTextBuffer *buffer) +{ + return buffer->priv->normal_text_chars; +} + +static guint +clutter_text_buffer_normal_insert_text (ClutterTextBuffer *buffer, + guint position, + const gchar *chars, + guint n_chars) +{ + ClutterTextBufferPrivate *pv = buffer->priv; + gsize prev_size; + gsize n_bytes; + gsize at; + + n_bytes = g_utf8_offset_to_pointer (chars, n_chars) - chars; + + /* Need more memory */ + if (n_bytes + pv->normal_text_bytes + 1 > pv->normal_text_size) + { + gchar *et_new; + + prev_size = pv->normal_text_size; + + /* Calculate our new buffer size */ + while (n_bytes + pv->normal_text_bytes + 1 > pv->normal_text_size) + { + if (pv->normal_text_size == 0) + pv->normal_text_size = MIN_SIZE; + else + { + if (2 * pv->normal_text_size < CLUTTER_TEXT_BUFFER_MAX_SIZE) + pv->normal_text_size *= 2; + else + { + pv->normal_text_size = CLUTTER_TEXT_BUFFER_MAX_SIZE; + if (n_bytes > pv->normal_text_size - pv->normal_text_bytes - 1) + { + n_bytes = pv->normal_text_size - pv->normal_text_bytes - 1; + n_bytes = g_utf8_find_prev_char (chars, chars + n_bytes + 1) - chars; + n_chars = g_utf8_strlen (chars, n_bytes); + } + break; + } + } + } + + /* Could be a password, so can't leave stuff in memory. */ + et_new = g_malloc (pv->normal_text_size); + memcpy (et_new, pv->normal_text, MIN (prev_size, pv->normal_text_size)); + trash_area (pv->normal_text, prev_size); + g_free (pv->normal_text); + pv->normal_text = et_new; + } + + /* Actual text insertion */ + at = g_utf8_offset_to_pointer (pv->normal_text, position) - pv->normal_text; + g_memmove (pv->normal_text + at + n_bytes, pv->normal_text + at, pv->normal_text_bytes - at); + memcpy (pv->normal_text + at, chars, n_bytes); + + /* Book keeping */ + pv->normal_text_bytes += n_bytes; + pv->normal_text_chars += n_chars; + pv->normal_text[pv->normal_text_bytes] = '\0'; + + clutter_text_buffer_emit_inserted_text (buffer, position, chars, n_chars); + return n_chars; +} + +static guint +clutter_text_buffer_normal_delete_text (ClutterTextBuffer *buffer, + guint position, + guint n_chars) +{ + ClutterTextBufferPrivate *pv = buffer->priv; + gsize start, end; + + if (position > pv->normal_text_chars) + position = pv->normal_text_chars; + if (position + n_chars > pv->normal_text_chars) + n_chars = pv->normal_text_chars - position; + + if (n_chars > 0) + { + start = g_utf8_offset_to_pointer (pv->normal_text, position) - pv->normal_text; + end = g_utf8_offset_to_pointer (pv->normal_text, position + n_chars) - pv->normal_text; + + g_memmove (pv->normal_text + start, pv->normal_text + end, pv->normal_text_bytes + 1 - end); + pv->normal_text_chars -= n_chars; + pv->normal_text_bytes -= (end - start); + + /* + * Could be a password, make sure we don't leave anything sensitive after + * the terminating zero. Note, that the terminating zero already trashed + * one byte. + */ + trash_area (pv->normal_text + pv->normal_text_bytes + 1, end - start - 1); + + clutter_text_buffer_emit_deleted_text (buffer, position, n_chars); + } + + return n_chars; +} + +/* -------------------------------------------------------------------------------- + * + */ + +static void +clutter_text_buffer_real_inserted_text (ClutterTextBuffer *buffer, + guint position, + const gchar *chars, + guint n_chars) +{ + g_object_notify (G_OBJECT (buffer), "text"); + g_object_notify (G_OBJECT (buffer), "length"); +} + +static void +clutter_text_buffer_real_deleted_text (ClutterTextBuffer *buffer, + guint position, + guint n_chars) +{ + g_object_notify (G_OBJECT (buffer), "text"); + g_object_notify (G_OBJECT (buffer), "length"); +} + +/* -------------------------------------------------------------------------------- + * + */ + +static void +clutter_text_buffer_init (ClutterTextBuffer *self) +{ + self->priv = clutter_text_buffer_get_instance_private (self); + + self->priv->normal_text = NULL; + self->priv->normal_text_chars = 0; + self->priv->normal_text_bytes = 0; + self->priv->normal_text_size = 0; +} + +static void +clutter_text_buffer_finalize (GObject *obj) +{ + ClutterTextBuffer *buffer = CLUTTER_TEXT_BUFFER (obj); + ClutterTextBufferPrivate *pv = buffer->priv; + + if (pv->normal_text) + { + trash_area (pv->normal_text, pv->normal_text_size); + g_free (pv->normal_text); + pv->normal_text = NULL; + pv->normal_text_bytes = pv->normal_text_size = 0; + pv->normal_text_chars = 0; + } + + G_OBJECT_CLASS (clutter_text_buffer_parent_class)->finalize (obj); +} + +static void +clutter_text_buffer_set_property (GObject *obj, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterTextBuffer *buffer = CLUTTER_TEXT_BUFFER (obj); + + switch (prop_id) + { + case PROP_MAX_LENGTH: + clutter_text_buffer_set_max_length (buffer, g_value_get_int (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); + break; + } +} + +static void +clutter_text_buffer_get_property (GObject *obj, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterTextBuffer *buffer = CLUTTER_TEXT_BUFFER (obj); + + switch (prop_id) + { + case PROP_TEXT: + g_value_set_string (value, clutter_text_buffer_get_text (buffer)); + break; + case PROP_LENGTH: + g_value_set_uint (value, clutter_text_buffer_get_length (buffer)); + break; + case PROP_MAX_LENGTH: + g_value_set_int (value, clutter_text_buffer_get_max_length (buffer)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); + break; + } +} + +static void +clutter_text_buffer_class_init (ClutterTextBufferClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = clutter_text_buffer_finalize; + gobject_class->set_property = clutter_text_buffer_set_property; + gobject_class->get_property = clutter_text_buffer_get_property; + + klass->get_text = clutter_text_buffer_normal_get_text; + klass->get_length = clutter_text_buffer_normal_get_length; + klass->insert_text = clutter_text_buffer_normal_insert_text; + klass->delete_text = clutter_text_buffer_normal_delete_text; + + klass->inserted_text = clutter_text_buffer_real_inserted_text; + klass->deleted_text = clutter_text_buffer_real_deleted_text; + + /** + * ClutterTextBuffer:text: + * + * The contents of the buffer. + * + * Since: 1.10 + */ + obj_props[PROP_TEXT] = + g_param_spec_string ("text", + P_("Text"), + P_("The contents of the buffer"), + "", + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + /** + * ClutterTextBuffer:length: + * + * The length (in characters) of the text in buffer. + * + * Since: 1.10 + */ + obj_props[PROP_LENGTH] = + g_param_spec_uint ("length", + P_("Text length"), + P_("Length of the text currently in the buffer"), + 0, CLUTTER_TEXT_BUFFER_MAX_SIZE, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + /** + * ClutterTextBuffer:max-length: + * + * The maximum length (in characters) of the text in the buffer. + * + * Since: 1.10 + */ + obj_props[PROP_MAX_LENGTH] = + g_param_spec_int ("max-length", + P_("Maximum length"), + P_("Maximum number of characters for this entry. Zero if no maximum"), + 0, CLUTTER_TEXT_BUFFER_MAX_SIZE, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); + + /** + * ClutterTextBuffer::inserted-text: + * @buffer: a #ClutterTextBuffer + * @position: the position the text was inserted at. + * @chars: The text that was inserted. + * @n_chars: The number of characters that were inserted. + * + * This signal is emitted after text is inserted into the buffer. + * + * Since: 1.10 + */ + signals[INSERTED_TEXT] = + g_signal_new (I_("inserted-text"), + CLUTTER_TYPE_TEXT_BUFFER, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ClutterTextBufferClass, inserted_text), + NULL, NULL, + _clutter_marshal_VOID__UINT_STRING_UINT, + G_TYPE_NONE, 3, + G_TYPE_UINT, + G_TYPE_STRING, + G_TYPE_UINT); + + /** + * ClutterTextBuffer::deleted-text: + * @buffer: a #ClutterTextBuffer + * @position: the position the text was deleted at. + * @n_chars: The number of characters that were deleted. + * + * This signal is emitted after text is deleted from the buffer. + * + * Since: 1.10 + */ + signals[DELETED_TEXT] = + g_signal_new (I_("deleted-text"), + CLUTTER_TYPE_TEXT_BUFFER, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ClutterTextBufferClass, deleted_text), + NULL, NULL, + _clutter_marshal_VOID__UINT_UINT, + G_TYPE_NONE, 2, + G_TYPE_UINT, + G_TYPE_UINT); +} + +/* -------------------------------------------------------------------------------- + * + */ + +/** + * clutter_text_buffer_new: + * + * Create a new ClutterTextBuffer object. + * + * Return value: A new ClutterTextBuffer object. + * + * Since: 1.10 + **/ +ClutterTextBuffer* +clutter_text_buffer_new (void) +{ + return g_object_new (CLUTTER_TYPE_TEXT_BUFFER, NULL); +} + + +/** + * clutter_text_buffer_new_with_text: + * @text: (allow-none): initial buffer text + * @text_len: initial buffer text length, or -1 for null-terminated. + * + * Create a new ClutterTextBuffer object with some text. + * + * Return value: A new ClutterTextBuffer object. + * + * Since: 1.10 + **/ +ClutterTextBuffer* +clutter_text_buffer_new_with_text (const gchar *text, + gssize text_len) +{ + ClutterTextBuffer *buffer; + buffer = clutter_text_buffer_new (); + clutter_text_buffer_set_text (buffer, text, text_len); + return buffer; +} + + +/** + * clutter_text_buffer_get_length: + * @buffer: a #ClutterTextBuffer + * + * Retrieves the length in characters of the buffer. + * + * Return value: The number of characters in the buffer. + * + * Since: 1.10 + **/ +guint +clutter_text_buffer_get_length (ClutterTextBuffer *buffer) +{ + ClutterTextBufferClass *klass; + + g_return_val_if_fail (CLUTTER_IS_TEXT_BUFFER (buffer), 0); + + klass = CLUTTER_TEXT_BUFFER_GET_CLASS (buffer); + g_return_val_if_fail (klass->get_length != NULL, 0); + + return (*klass->get_length) (buffer); +} + +/** + * clutter_text_buffer_get_bytes: + * @buffer: a #ClutterTextBuffer + * + * Retrieves the length in bytes of the buffer. + * See clutter_text_buffer_get_length(). + * + * Return value: The byte length of the buffer. + * + * Since: 1.10 + **/ +gsize +clutter_text_buffer_get_bytes (ClutterTextBuffer *buffer) +{ + ClutterTextBufferClass *klass; + gsize bytes = 0; + + g_return_val_if_fail (CLUTTER_IS_TEXT_BUFFER (buffer), 0); + + klass = CLUTTER_TEXT_BUFFER_GET_CLASS (buffer); + g_return_val_if_fail (klass->get_text != NULL, 0); + + (*klass->get_text) (buffer, &bytes); + return bytes; +} + +/** + * clutter_text_buffer_get_text: + * @buffer: a #ClutterTextBuffer + * + * Retrieves the contents of the buffer. + * + * The memory pointer returned by this call will not change + * unless this object emits a signal, or is finalized. + * + * Return value: a pointer to the contents of the widget as a + * string. This string points to internally allocated + * storage in the buffer and must not be freed, modified or + * stored. + * + * Since: 1.10 + **/ +const gchar* +clutter_text_buffer_get_text (ClutterTextBuffer *buffer) +{ + ClutterTextBufferClass *klass; + + g_return_val_if_fail (CLUTTER_IS_TEXT_BUFFER (buffer), NULL); + + klass = CLUTTER_TEXT_BUFFER_GET_CLASS (buffer); + g_return_val_if_fail (klass->get_text != NULL, NULL); + + return (*klass->get_text) (buffer, NULL); +} + +/** + * clutter_text_buffer_set_text: + * @buffer: a #ClutterTextBuffer + * @chars: the new text + * @n_chars: the number of characters in @text, or -1 + * + * Sets the text in the buffer. + * + * This is roughly equivalent to calling clutter_text_buffer_delete_text() + * and clutter_text_buffer_insert_text(). + * + * Note that @n_chars is in characters, not in bytes. + * + * Since: 1.10 + **/ +void +clutter_text_buffer_set_text (ClutterTextBuffer *buffer, + const gchar *chars, + gint n_chars) +{ + g_return_if_fail (CLUTTER_IS_TEXT_BUFFER (buffer)); + g_return_if_fail (chars != NULL); + + g_object_freeze_notify (G_OBJECT (buffer)); + clutter_text_buffer_delete_text (buffer, 0, -1); + clutter_text_buffer_insert_text (buffer, 0, chars, n_chars); + g_object_thaw_notify (G_OBJECT (buffer)); +} + +/** + * clutter_text_buffer_set_max_length: + * @buffer: a #ClutterTextBuffer + * @max_length: the maximum length of the entry buffer, or 0 for no maximum. + * (other than the maximum length of entries.) The value passed in will + * be clamped to the range [ 0, %CLUTTER_TEXT_BUFFER_MAX_SIZE ]. + * + * Sets the maximum allowed length of the contents of the buffer. If + * the current contents are longer than the given length, then they + * will be truncated to fit. + * + * Since: 1.10 + **/ +void +clutter_text_buffer_set_max_length (ClutterTextBuffer *buffer, + gint max_length) +{ + g_return_if_fail (CLUTTER_IS_TEXT_BUFFER (buffer)); + + max_length = CLAMP (max_length, 0, CLUTTER_TEXT_BUFFER_MAX_SIZE); + + if (max_length > 0 && clutter_text_buffer_get_length (buffer) > max_length) + clutter_text_buffer_delete_text (buffer, max_length, -1); + + buffer->priv->max_length = max_length; + g_object_notify (G_OBJECT (buffer), "max-length"); +} + +/** + * clutter_text_buffer_get_max_length: + * @buffer: a #ClutterTextBuffer + * + * Retrieves the maximum allowed length of the text in + * @buffer. See clutter_text_buffer_set_max_length(). + * + * Return value: the maximum allowed number of characters + * in #ClutterTextBuffer, or 0 if there is no maximum. + * + * Since: 1.10 + */ +gint +clutter_text_buffer_get_max_length (ClutterTextBuffer *buffer) +{ + g_return_val_if_fail (CLUTTER_IS_TEXT_BUFFER (buffer), 0); + return buffer->priv->max_length; +} + +/** + * clutter_text_buffer_insert_text: + * @buffer: a #ClutterTextBuffer + * @position: the position at which to insert text. + * @chars: the text to insert into the buffer. + * @n_chars: the length of the text in characters, or -1 + * + * Inserts @n_chars characters of @chars into the contents of the + * buffer, at position @position. + * + * If @n_chars is negative, then characters from chars will be inserted + * until a null-terminator is found. If @position or @n_chars are out of + * bounds, or the maximum buffer text length is exceeded, then they are + * coerced to sane values. + * + * Note that the position and length are in characters, not in bytes. + * + * Returns: The number of characters actually inserted. + * + * Since: 1.10 + */ +guint +clutter_text_buffer_insert_text (ClutterTextBuffer *buffer, + guint position, + const gchar *chars, + gint n_chars) +{ + ClutterTextBufferClass *klass; + ClutterTextBufferPrivate *pv; + guint length; + + g_return_val_if_fail (CLUTTER_IS_TEXT_BUFFER (buffer), 0); + + length = clutter_text_buffer_get_length (buffer); + pv = buffer->priv; + + if (n_chars < 0) + n_chars = g_utf8_strlen (chars, -1); + + /* Bring position into bounds */ + if (position > length) + position = length; + + /* Make sure not entering too much data */ + if (pv->max_length > 0) + { + if (length >= pv->max_length) + n_chars = 0; + else if (length + n_chars > pv->max_length) + n_chars -= (length + n_chars) - pv->max_length; + } + + klass = CLUTTER_TEXT_BUFFER_GET_CLASS (buffer); + g_return_val_if_fail (klass->insert_text != NULL, 0); + + return (klass->insert_text) (buffer, position, chars, n_chars); +} + +/** + * clutter_text_buffer_delete_text: + * @buffer: a #ClutterTextBuffer + * @position: position at which to delete text + * @n_chars: number of characters to delete + * + * Deletes a sequence of characters from the buffer. @n_chars characters are + * deleted starting at @position. If @n_chars is negative, then all characters + * until the end of the text are deleted. + * + * If @position or @n_chars are out of bounds, then they are coerced to sane + * values. + * + * Note that the positions are specified in characters, not bytes. + * + * Returns: The number of characters deleted. + * + * Since: 1.10 + */ +guint +clutter_text_buffer_delete_text (ClutterTextBuffer *buffer, + guint position, + gint n_chars) +{ + ClutterTextBufferClass *klass; + guint length; + + g_return_val_if_fail (CLUTTER_IS_TEXT_BUFFER (buffer), 0); + + length = clutter_text_buffer_get_length (buffer); + if (n_chars < 0) + n_chars = length; + if (position > length) + position = length; + if (position + n_chars > length) + n_chars = length - position; + + klass = CLUTTER_TEXT_BUFFER_GET_CLASS (buffer); + g_return_val_if_fail (klass->delete_text != NULL, 0); + + return (klass->delete_text) (buffer, position, n_chars); +} + +/** + * clutter_text_buffer_emit_inserted_text: + * @buffer: a #ClutterTextBuffer + * @position: position at which text was inserted + * @chars: text that was inserted + * @n_chars: number of characters inserted + * + * Emits the #ClutterTextBuffer::inserted-text signal on @buffer. + * + * Used when subclassing #ClutterTextBuffer + * + * Since: 1.10 + */ +void +clutter_text_buffer_emit_inserted_text (ClutterTextBuffer *buffer, + guint position, + const gchar *chars, + guint n_chars) +{ + g_return_if_fail (CLUTTER_IS_TEXT_BUFFER (buffer)); + g_signal_emit (buffer, signals[INSERTED_TEXT], 0, position, chars, n_chars); +} + +/** + * clutter_text_buffer_emit_deleted_text: + * @buffer: a #ClutterTextBuffer + * @position: position at which text was deleted + * @n_chars: number of characters deleted + * + * Emits the #ClutterTextBuffer::deleted-text signal on @buffer. + * + * Used when subclassing #ClutterTextBuffer + * + * Since: 1.10 + */ +void +clutter_text_buffer_emit_deleted_text (ClutterTextBuffer *buffer, + guint position, + guint n_chars) +{ + g_return_if_fail (CLUTTER_IS_TEXT_BUFFER (buffer)); + g_signal_emit (buffer, signals[DELETED_TEXT], 0, position, n_chars); +} diff --git a/clutter/clutter/clutter-text-buffer.h b/clutter/clutter/clutter-text-buffer.h new file mode 100644 index 0000000..468b060 --- /dev/null +++ b/clutter/clutter/clutter-text-buffer.h @@ -0,0 +1,172 @@ +/* clutter-text-buffer.h + * Copyright (C) 2011 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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. + * + * Author: Stef Walter + */ + +#ifndef __CLUTTER_TEXT_BUFFER_H__ +#define __CLUTTER_TEXT_BUFFER_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_TEXT_BUFFER (clutter_text_buffer_get_type ()) +#define CLUTTER_TEXT_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_TEXT_BUFFER, ClutterTextBuffer)) +#define CLUTTER_TEXT_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_TEXT_BUFFER, ClutterTextBufferClass)) +#define CLUTTER_IS_TEXT_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_TEXT_BUFFER)) +#define CLUTTER_IS_TEXT_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_TEXT_BUFFER)) +#define CLUTTER_TEXT_BUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_TEXT_BUFFER, ClutterTextBufferClass)) + +/** + * CLUTTER_TEXT_BUFFER_MAX_SIZE: + * + * Maximum size of text buffer, in bytes. + * + * Since: 1.10 + */ +#define CLUTTER_TEXT_BUFFER_MAX_SIZE G_MAXUSHORT + +typedef struct _ClutterTextBuffer ClutterTextBuffer; +typedef struct _ClutterTextBufferClass ClutterTextBufferClass; +typedef struct _ClutterTextBufferPrivate ClutterTextBufferPrivate; + +/** + * ClutterTextBuffer: + * + * The #ClutterTextBuffer structure contains private + * data and it should only be accessed using the provided API. + * + * Since: 1.10 + */ +struct _ClutterTextBuffer +{ + /*< private >*/ + GObject parent_instance; + + ClutterTextBufferPrivate *priv; +}; + +/** + * ClutterTextBufferClass: + * @inserted_text: default handler for the #ClutterTextBuffer::inserted-text signal + * @deleted_text: default hanlder for the #ClutterTextBuffer::deleted-text signal + * @get_text: virtual function + * @get_length: virtual function + * @insert_text: virtual function + * @delete_text: virtual function + * + * The #ClutterTextBufferClass structure contains + * only private data. + * + * Since: 1.10 + */ +struct _ClutterTextBufferClass +{ + /*< private >*/ + GObjectClass parent_class; + + /*< public >*/ + /* Signals */ + void (*inserted_text) (ClutterTextBuffer *buffer, + guint position, + const gchar *chars, + guint n_chars); + + void (*deleted_text) (ClutterTextBuffer *buffer, + guint position, + guint n_chars); + + /* Virtual Methods */ + const gchar* (*get_text) (ClutterTextBuffer *buffer, + gsize *n_bytes); + + guint (*get_length) (ClutterTextBuffer *buffer); + + guint (*insert_text) (ClutterTextBuffer *buffer, + guint position, + const gchar *chars, + guint n_chars); + + guint (*delete_text) (ClutterTextBuffer *buffer, + guint position, + guint n_chars); + + /*< private >*/ + /* Padding for future expansion */ + void (*_clutter_reserved1) (void); + void (*_clutter_reserved2) (void); + void (*_clutter_reserved3) (void); + void (*_clutter_reserved4) (void); + void (*_clutter_reserved5) (void); + void (*_clutter_reserved6) (void); + void (*_clutter_reserved7) (void); + void (*_clutter_reserved8) (void); +}; + +CLUTTER_AVAILABLE_IN_1_10 +GType clutter_text_buffer_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_10 +ClutterTextBuffer* clutter_text_buffer_new (void); +CLUTTER_AVAILABLE_IN_1_10 +ClutterTextBuffer* clutter_text_buffer_new_with_text (const gchar *text, + gssize text_len); + +CLUTTER_AVAILABLE_IN_1_10 +gsize clutter_text_buffer_get_bytes (ClutterTextBuffer *buffer); +CLUTTER_AVAILABLE_IN_1_10 +guint clutter_text_buffer_get_length (ClutterTextBuffer *buffer); +CLUTTER_AVAILABLE_IN_1_10 +const gchar* clutter_text_buffer_get_text (ClutterTextBuffer *buffer); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_text_buffer_set_text (ClutterTextBuffer *buffer, + const gchar *chars, + gint n_chars); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_text_buffer_set_max_length (ClutterTextBuffer *buffer, + gint max_length); +CLUTTER_AVAILABLE_IN_1_10 +gint clutter_text_buffer_get_max_length (ClutterTextBuffer *buffer); + +CLUTTER_AVAILABLE_IN_1_10 +guint clutter_text_buffer_insert_text (ClutterTextBuffer *buffer, + guint position, + const gchar *chars, + gint n_chars); +CLUTTER_AVAILABLE_IN_1_10 +guint clutter_text_buffer_delete_text (ClutterTextBuffer *buffer, + guint position, + gint n_chars); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_text_buffer_emit_inserted_text (ClutterTextBuffer *buffer, + guint position, + const gchar *chars, + guint n_chars); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_text_buffer_emit_deleted_text (ClutterTextBuffer *buffer, + guint position, + guint n_chars); + +G_END_DECLS + +#endif /* __CLUTTER_TEXT_BUFFER_H__ */ diff --git a/clutter/clutter/clutter-text.c b/clutter/clutter/clutter-text.c new file mode 100644 index 0000000..b57b3c5 --- /dev/null +++ b/clutter/clutter/clutter-text.c @@ -0,0 +1,6300 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2008 Intel Corporation. + * + * Authored By: Øyvind KolÃ¥s + * Emmanuele Bassi + * + * 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 . + */ + +/** + * SECTION:clutter-text + * @short_description: An actor for displaying and editing text + * + * #ClutterText is an actor that displays custom text using Pango + * as the text rendering engine. + * + * #ClutterText also allows inline editing of the text if the + * actor is set editable using clutter_text_set_editable(). + * + * Selection using keyboard or pointers can be enabled using + * clutter_text_set_selectable(). + * + * #ClutterText is available since Clutter 1.0 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include +#include + +#include "clutter-text.h" + +#include "clutter-actor-private.h" +#include "clutter-animatable.h" +#include "clutter-backend-private.h" +#include "clutter-binding-pool.h" +#include "clutter-color.h" +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-keysyms.h" +#include "clutter-main.h" +#include "clutter-marshal.h" +#include "clutter-private.h" /* includes */ +#include "clutter-property-transition.h" +#include "clutter-text-buffer.h" +#include "clutter-units.h" +#include "clutter-paint-volume-private.h" +#include "clutter-scriptable.h" + +/* cursor width in pixels */ +#define DEFAULT_CURSOR_SIZE 2 + +/* vertical padding for the cursor */ +#define CURSOR_Y_PADDING 2 + +/* We need at least three cached layouts to run the allocation without + * regenerating a new layout. First the layout will be generated at + * full width to get the preferred width, then it will be generated at + * the preferred width to get the preferred height and then it might + * be regenerated at a different width to get the height for the + * actual allocated width + * + * since we might get multiple queries from layout managers doing a + * double-pass allocations, like tabular ones, we should use 6 slots + */ +#define N_CACHED_LAYOUTS 6 + +typedef struct _LayoutCache LayoutCache; + +struct _LayoutCache +{ + /* Cached layout. Pango internally caches the computed extents + * when they are requested so there is no need to cache that as + * well + */ + PangoLayout *layout; + + /* A number representing the age of this cache (so that when a + * new layout is needed the last used cache is replaced) + */ + guint age; +}; + +struct _ClutterTextPrivate +{ + PangoFontDescription *font_desc; + + /* the displayed text */ + ClutterTextBuffer *buffer; + + gchar *font_name; + + gchar *preedit_str; + + ClutterColor text_color; + + LayoutCache cached_layouts[N_CACHED_LAYOUTS]; + guint cache_age; + + /* These are the attributes set by the attributes property */ + PangoAttrList *attrs; + /* These are the attributes derived from the text when the + use-markup property is set */ + PangoAttrList *markup_attrs; + /* This is the combination of the above two lists. It is set to NULL + whenever either of them changes and then regenerated by merging + the two lists whenever a layout is needed */ + PangoAttrList *effective_attrs; + /* These are the attributes for the preedit string. These are merged + with the effective attributes into a temporary list before + creating a layout */ + PangoAttrList *preedit_attrs; + + /* current cursor position */ + gint position; + + /* current 'other end of selection' position */ + gint selection_bound; + + /* the x position in the PangoLayout, used to + * avoid drifting when repeatedly moving up|down + */ + gint x_pos; + + /* the x position of the PangoLayout when in + * single line mode, to scroll the contents of the + * text actor + */ + gint text_x; + + /* the y position of the PangoLayout, fixed to 0 by + * default for now */ + gint text_y; + + /* Where to draw the cursor */ + ClutterRect cursor_rect; + ClutterColor cursor_color; + guint cursor_size; + + /* Box representing the paint volume. The box is lazily calculated + and cached */ + ClutterPaintVolume paint_volume; + + guint preedit_cursor_pos; + gint preedit_n_chars; + + ClutterColor selection_color; + + ClutterColor selected_text_color; + + gunichar password_char; + + guint password_hint_id; + guint password_hint_timeout; + + /* Signal handler for when the backend changes its font settings */ + guint settings_changed_id; + + /* Signal handler for when the :text-direction changes */ + guint direction_changed_id; + + /* bitfields */ + guint alignment : 2; + guint wrap : 1; + guint use_underline : 1; + guint use_markup : 1; + guint ellipsize : 3; + guint single_line_mode : 1; + guint wrap_mode : 3; + guint justify : 1; + guint editable : 1; + guint cursor_visible : 1; + guint activatable : 1; + guint selectable : 1; + guint selection_color_set : 1; + guint in_select_drag : 1; + guint in_select_touch : 1; + guint cursor_color_set : 1; + guint preedit_set : 1; + guint is_default_font : 1; + guint has_focus : 1; + guint selected_text_color_set : 1; + guint paint_volume_valid : 1; + guint show_password_hint : 1; + guint password_hint_visible : 1; + guint resolved_direction : 4; +}; + +enum +{ + PROP_0, + + PROP_BUFFER, + PROP_FONT_NAME, + PROP_FONT_DESCRIPTION, + PROP_TEXT, + PROP_COLOR, + PROP_USE_MARKUP, + PROP_ATTRIBUTES, + PROP_LINE_ALIGNMENT, + PROP_LINE_WRAP, + PROP_LINE_WRAP_MODE, + PROP_JUSTIFY, + PROP_ELLIPSIZE, + PROP_POSITION, /* XXX:2.0 - remove */ + PROP_SELECTION_BOUND, + PROP_SELECTION_COLOR, + PROP_SELECTION_COLOR_SET, + PROP_CURSOR_VISIBLE, + PROP_CURSOR_COLOR, + PROP_CURSOR_COLOR_SET, + PROP_CURSOR_SIZE, + PROP_CURSOR_POSITION, + PROP_EDITABLE, + PROP_SELECTABLE, + PROP_ACTIVATABLE, + PROP_PASSWORD_CHAR, + PROP_MAX_LENGTH, + PROP_SINGLE_LINE_MODE, + PROP_SELECTED_TEXT_COLOR, + PROP_SELECTED_TEXT_COLOR_SET, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +enum +{ + TEXT_CHANGED, + CURSOR_EVENT, /* XXX:2.0 - remove */ + ACTIVATE, + INSERT_TEXT, + DELETE_TEXT, + CURSOR_CHANGED, + + LAST_SIGNAL +}; + +static guint text_signals[LAST_SIGNAL] = { 0, }; + +static void clutter_text_settings_changed_cb (ClutterText *text); +static void buffer_connect_signals (ClutterText *self); +static void buffer_disconnect_signals (ClutterText *self); +static ClutterTextBuffer *get_buffer (ClutterText *self); + +static const ClutterColor default_cursor_color = { 0, 0, 0, 255 }; +static const ClutterColor default_selection_color = { 0, 0, 0, 255 }; +static const ClutterColor default_text_color = { 0, 0, 0, 255 }; +static const ClutterColor default_selected_text_color = { 0, 0, 0, 255 }; + +static ClutterAnimatableIface *parent_animatable_iface = NULL; +static ClutterScriptableIface *parent_scriptable_iface = NULL; + +static void clutter_scriptable_iface_init (ClutterScriptableIface *iface); +static void clutter_animatable_iface_init (ClutterAnimatableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (ClutterText, + clutter_text, + CLUTTER_TYPE_ACTOR, + G_ADD_PRIVATE (ClutterText) + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_SCRIPTABLE, + clutter_scriptable_iface_init) + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_ANIMATABLE, + clutter_animatable_iface_init)); + +static inline void +clutter_text_dirty_paint_volume (ClutterText *text) +{ + ClutterTextPrivate *priv = text->priv; + + if (priv->paint_volume_valid) + { + clutter_paint_volume_free (&priv->paint_volume); + priv->paint_volume_valid = FALSE; + } +} + +static inline void +clutter_text_queue_redraw (ClutterActor *self) +{ + /* This is a wrapper for clutter_actor_queue_redraw that also + dirties the cached paint volume. It would be nice if we could + just override the default implementation of the queue redraw + signal to do this instead but that doesn't work because the + signal isn't immediately emitted when queue_redraw is called. + Clutter will however immediately call get_paint_volume when + queue_redraw is called so we do need to dirty it immediately. */ + + clutter_text_dirty_paint_volume (CLUTTER_TEXT (self)); + + clutter_actor_queue_redraw (self); +} + +static gboolean +clutter_text_should_draw_cursor (ClutterText *self) +{ + ClutterTextPrivate *priv = self->priv; + + return (priv->editable || priv->selectable) && + priv->cursor_visible && + priv->has_focus; +} + +#define clutter_actor_queue_redraw \ + Please_use_clutter_text_queue_redraw_instead + +#define offset_real(t,p) ((p) == -1 ? g_utf8_strlen ((t), -1) : (p)) + +static gint +offset_to_bytes (const gchar *text, + gint pos) +{ + const gchar *ptr; + + if (pos < 0) + return strlen (text); + + /* Loop over each character in the string until we either reach the + end or the requested position */ + for (ptr = text; *ptr && pos-- > 0; ptr = g_utf8_next_char (ptr)); + + return ptr - text; +} + +#define bytes_to_offset(t,p) (g_utf8_pointer_to_offset ((t), (t) + (p))) + +static inline void +clutter_text_clear_selection (ClutterText *self) +{ + ClutterTextPrivate *priv = self->priv; + + if (priv->selection_bound != priv->position) + { + priv->selection_bound = priv->position; + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SELECTION_BOUND]); + clutter_text_queue_redraw (CLUTTER_ACTOR (self)); + } +} + +static gboolean +clutter_text_is_empty (ClutterText *self) +{ + if (self->priv->buffer == NULL) + return TRUE; + + if (clutter_text_buffer_get_length (self->priv->buffer) == 0) + return TRUE; + + return FALSE; +} + +static gchar * +clutter_text_get_display_text (ClutterText *self) +{ + ClutterTextPrivate *priv = self->priv; + ClutterTextBuffer *buffer; + const gchar *text; + + /* short-circuit the case where the buffer is unset or it's empty, + * to avoid creating a pointless TextBuffer and emitting + * notifications with it + */ + if (clutter_text_is_empty (self)) + return g_strdup (""); + + buffer = get_buffer (self); + text = clutter_text_buffer_get_text (buffer); + + /* simple short-circuit to avoid going through GString + * with an empty text and a password char set + */ + if (text[0] == '\0') + return g_strdup (""); + + if (G_LIKELY (priv->password_char == 0)) + return g_strdup (text); + else + { + GString *str; + gunichar invisible_char; + gchar buf[7]; + gint char_len, i; + guint n_chars; + + n_chars = clutter_text_buffer_get_length (buffer); + str = g_string_sized_new (clutter_text_buffer_get_bytes (buffer)); + invisible_char = priv->password_char; + + /* we need to convert the string built of invisible + * characters into UTF-8 for it to be fed to the Pango + * layout + */ + memset (buf, 0, sizeof (buf)); + char_len = g_unichar_to_utf8 (invisible_char, buf); + + if (priv->show_password_hint && priv->password_hint_visible) + { + char *last_char; + + for (i = 0; i < n_chars - 1; i++) + g_string_append_len (str, buf, char_len); + + last_char = g_utf8_offset_to_pointer (text, n_chars - 1); + g_string_append (str, last_char); + } + else + { + for (i = 0; i < n_chars; i++) + g_string_append_len (str, buf, char_len); + } + + return g_string_free (str, FALSE); + } +} + +static inline void +clutter_text_ensure_effective_attributes (ClutterText *self) +{ + ClutterTextPrivate *priv = self->priv; + + /* If we already have the effective attributes then we don't need to + do anything */ + if (priv->effective_attrs != NULL) + return; + + /* Same as if we don't have any attribute at all. + * We also ignore markup attributes for editable. */ + if (priv->attrs == NULL && (priv->editable || priv->markup_attrs == NULL)) + return; + + if (priv->attrs != NULL) + { + /* If there are no markup attributes, or if this is editable (in which + * case we ignore markup), then we can just use these attrs directly */ + if (priv->editable || priv->markup_attrs == NULL) + priv->effective_attrs = pango_attr_list_ref (priv->attrs); + else + { + /* Otherwise we need to merge the two lists */ + PangoAttrIterator *iter; + GSList *attributes, *l; + + priv->effective_attrs = pango_attr_list_copy (priv->markup_attrs); + + iter = pango_attr_list_get_iterator (priv->attrs); + do + { + attributes = pango_attr_iterator_get_attrs (iter); + + for (l = attributes; l != NULL; l = l->next) + { + PangoAttribute *attr = l->data; + + pango_attr_list_insert (priv->effective_attrs, attr); + } + + g_slist_free (attributes); + } + while (pango_attr_iterator_next (iter)); + + pango_attr_iterator_destroy (iter); + } + } + else if (priv->markup_attrs != NULL) + { + /* We can just use the markup attributes directly */ + priv->effective_attrs = pango_attr_list_ref (priv->markup_attrs); + } +} + +static PangoLayout * +clutter_text_create_layout_no_cache (ClutterText *text, + gint width, + gint height, + PangoEllipsizeMode ellipsize) +{ + ClutterTextPrivate *priv = text->priv; + PangoLayout *layout; + gchar *contents; + gsize contents_len; + + layout = clutter_actor_create_pango_layout (CLUTTER_ACTOR (text), NULL); + pango_layout_set_font_description (layout, priv->font_desc); + + contents = clutter_text_get_display_text (text); + contents_len = strlen (contents); + + if (priv->editable && priv->preedit_set) + { + GString *tmp = g_string_new (contents); + PangoAttrList *tmp_attrs = pango_attr_list_new (); + gint cursor_index; + + if (priv->position == 0) + cursor_index = 0; + else + cursor_index = offset_to_bytes (contents, priv->position); + + g_string_insert (tmp, cursor_index, priv->preedit_str); + + pango_layout_set_text (layout, tmp->str, tmp->len); + + if (priv->preedit_attrs != NULL) + { + pango_attr_list_splice (tmp_attrs, priv->preedit_attrs, + cursor_index, + strlen (priv->preedit_str)); + + pango_layout_set_attributes (layout, tmp_attrs); + } + + g_string_free (tmp, TRUE); + pango_attr_list_unref (tmp_attrs); + } + else + { + PangoDirection pango_dir; + + if (priv->password_char != 0) + pango_dir = PANGO_DIRECTION_NEUTRAL; + else + pango_dir = pango_find_base_dir (contents, contents_len); + + if (pango_dir == PANGO_DIRECTION_NEUTRAL) + { + ClutterBackend *backend = clutter_get_default_backend (); + ClutterTextDirection text_dir; + + if (clutter_actor_has_key_focus (CLUTTER_ACTOR (text))) + pango_dir = _clutter_backend_get_keymap_direction (backend); + else + { + text_dir = clutter_actor_get_text_direction (CLUTTER_ACTOR (text)); + + if (text_dir == CLUTTER_TEXT_DIRECTION_RTL) + pango_dir = PANGO_DIRECTION_RTL; + else + pango_dir = PANGO_DIRECTION_LTR; + } + } + + pango_context_set_base_dir (clutter_actor_get_pango_context (CLUTTER_ACTOR (text)), pango_dir); + + priv->resolved_direction = pango_dir; + + pango_layout_set_text (layout, contents, contents_len); + } + + /* This will merge the markup attributes and the attributes + * property if needed */ + clutter_text_ensure_effective_attributes (text); + + if (priv->effective_attrs != NULL) + pango_layout_set_attributes (layout, priv->effective_attrs); + + pango_layout_set_alignment (layout, priv->alignment); + pango_layout_set_single_paragraph_mode (layout, priv->single_line_mode); + pango_layout_set_justify (layout, priv->justify); + pango_layout_set_wrap (layout, priv->wrap_mode); + + pango_layout_set_ellipsize (layout, ellipsize); + pango_layout_set_width (layout, width); + pango_layout_set_height (layout, height); + + g_free (contents); + + return layout; +} + +static void +clutter_text_dirty_cache (ClutterText *text) +{ + ClutterTextPrivate *priv = text->priv; + int i; + + /* Delete the cached layouts so they will be recreated the next time + they are needed */ + for (i = 0; i < N_CACHED_LAYOUTS; i++) + if (priv->cached_layouts[i].layout) + { + g_object_unref (priv->cached_layouts[i].layout); + priv->cached_layouts[i].layout = NULL; + } + + clutter_text_dirty_paint_volume (text); +} + +/* + * clutter_text_set_font_description_internal: + * @self: a #ClutterText + * @desc: a #PangoFontDescription + * + * Sets @desc as the font description to be used by the #ClutterText + * actor. The #PangoFontDescription is copied. + * + * This function will also set the :font-name field as a side-effect + * + * This function will evict the layout cache, and queue a relayout if + * the #ClutterText actor has contents. + */ +static inline void +clutter_text_set_font_description_internal (ClutterText *self, + PangoFontDescription *desc, + gboolean is_default_font) +{ + ClutterTextPrivate *priv = self->priv; + + priv->is_default_font = is_default_font; + + if (priv->font_desc == desc || + pango_font_description_equal (priv->font_desc, desc)) + return; + + if (priv->font_desc != NULL) + pango_font_description_free (priv->font_desc); + + priv->font_desc = pango_font_description_copy (desc); + + /* update the font name string we use */ + g_free (priv->font_name); + priv->font_name = pango_font_description_to_string (priv->font_desc); + + clutter_text_dirty_cache (self); + + if (clutter_text_buffer_get_length (get_buffer (self)) != 0) + clutter_actor_queue_relayout (CLUTTER_ACTOR (self)); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_FONT_DESCRIPTION]); +} + +static void +clutter_text_settings_changed_cb (ClutterText *text) +{ + ClutterTextPrivate *priv = text->priv; + guint password_hint_time = 0; + ClutterSettings *settings; + + settings = clutter_settings_get_default (); + + g_object_get (settings, "password-hint-time", &password_hint_time, NULL); + + priv->show_password_hint = password_hint_time > 0; + priv->password_hint_timeout = password_hint_time; + + if (priv->is_default_font) + { + PangoFontDescription *font_desc; + gchar *font_name = NULL; + + g_object_get (settings, "font-name", &font_name, NULL); + + CLUTTER_NOTE (ACTOR, "Text[%p]: default font changed to '%s'", + text, + font_name); + + font_desc = pango_font_description_from_string (font_name); + clutter_text_set_font_description_internal (text, font_desc, TRUE); + + pango_font_description_free (font_desc); + g_free (font_name); + } + + clutter_text_dirty_cache (text); + clutter_actor_queue_relayout (CLUTTER_ACTOR (text)); +} + +static void +clutter_text_direction_changed_cb (GObject *gobject, + GParamSpec *pspec) +{ + clutter_text_dirty_cache (CLUTTER_TEXT (gobject)); + + /* no need to queue a relayout: set_text_direction() will do that for us */ +} + +/* + * clutter_text_create_layout: + * @text: a #ClutterText + * @allocation_width: the allocation width + * @allocation_height: the allocation height + * + * Like clutter_text_create_layout_no_cache(), but will also ensure + * the glyphs cache. If a previously cached layout generated using the + * same width is available then that will be used instead of + * generating a new one. + */ +static PangoLayout * +clutter_text_create_layout (ClutterText *text, + gfloat allocation_width, + gfloat allocation_height) +{ + ClutterTextPrivate *priv = text->priv; + LayoutCache *oldest_cache = priv->cached_layouts; + gboolean found_free_cache = FALSE; + gint width = -1; + gint height = -1; + PangoEllipsizeMode ellipsize = PANGO_ELLIPSIZE_NONE; + int i; + + /* First determine the width, height, and ellipsize mode that + * we need for the layout. The ellipsize mode depends on + * allocation_width/allocation_size as follows: + * + * Cases, assuming ellipsize != NONE on actor: + * + * Width request: ellipsization can be set or not on layout, + * doesn't matter. + * + * Height request: ellipsization must never be set on layout + * if wrap=true, because we need to measure the wrapped + * height. It must always be set if wrap=false. + * + * Allocate: ellipsization must always be set. + * + * See http://bugzilla.gnome.org/show_bug.cgi?id=560931 + */ + + if (priv->ellipsize != PANGO_ELLIPSIZE_NONE) + { + if (allocation_height < 0 && priv->wrap) + ; /* must not set ellipsization on wrap=true height request */ + else + { + if (!priv->editable) + ellipsize = priv->ellipsize; + } + } + + /* When painting, we always need to set the width, since + * we might need to align to the right. When getting the + * height, however, there are some cases where we know that + * the width won't affect the width. + * + * - editable, single-line text actors, since those can + * scroll the layout. + * - non-wrapping, non-ellipsizing actors. + */ + if (allocation_width >= 0 && + (allocation_height >= 0 || + !((priv->editable && priv->single_line_mode) || + (priv->ellipsize == PANGO_ELLIPSIZE_NONE && !priv->wrap)))) + { + width = allocation_width * 1024 + 0.5f; + } + + /* Pango only uses height if ellipsization is enabled, so don't set + * height if ellipsize isn't set. Pango implicitly enables wrapping + * if height is set, so don't set height if wrapping is disabled. + * In other words, only set height if we want to both wrap then + * ellipsize and we're not in single line mode. + * + * See http://bugzilla.gnome.org/show_bug.cgi?id=560931 if this + * seems odd. + */ + if (allocation_height >= 0 && + priv->wrap && + priv->ellipsize != PANGO_ELLIPSIZE_NONE && + !priv->single_line_mode) + { + height = allocation_height * 1024 + 0.5f; + } + + /* Search for a cached layout with the same width and keep + * track of the oldest one + */ + for (i = 0; i < N_CACHED_LAYOUTS; i++) + { + if (priv->cached_layouts[i].layout == NULL) + { + /* Always prefer free cache spaces */ + found_free_cache = TRUE; + oldest_cache = priv->cached_layouts + i; + } + else + { + PangoLayout *cached = priv->cached_layouts[i].layout; + gint cached_width = pango_layout_get_width (cached); + gint cached_height = pango_layout_get_height (cached); + gint cached_ellipsize = pango_layout_get_ellipsize (cached); + + if (cached_width == width && + cached_height == height && + cached_ellipsize == ellipsize) + { + /* If this cached layout is using the same size then we can + * just return that directly + */ + CLUTTER_NOTE (ACTOR, + "ClutterText: %p: cache hit for size %.2fx%.2f", + text, + allocation_width, + allocation_height); + + return priv->cached_layouts[i].layout; + } + + /* When getting the preferred height for a specific width, + * we might be able to reuse the layout from getting the + * preferred width. If the width that the layout gives + * unconstrained is less than the width that we are using + * than the height will be unaffected by that width. + */ + if (allocation_height < 0 && + cached_width == -1 && + cached_ellipsize == ellipsize) + { + PangoRectangle logical_rect; + + pango_layout_get_extents (priv->cached_layouts[i].layout, + NULL, + &logical_rect); + + if (logical_rect.width <= width) + { + /* We've been asked for our height for the width we gave as a result + * of a _get_preferred_width call + */ + CLUTTER_NOTE (ACTOR, + "ClutterText: %p: cache hit for size %.2fx%.2f " + "(unwrapped width narrower than given width)", + text, + allocation_width, + allocation_height); + + return priv->cached_layouts[i].layout; + } + } + + if (!found_free_cache && + (priv->cached_layouts[i].age < oldest_cache->age)) + { + oldest_cache = priv->cached_layouts + i; + } + } + } + + CLUTTER_NOTE (ACTOR, "ClutterText: %p: cache miss for size %.2fx%.2f", + text, + allocation_width, + allocation_height); + + /* If we make it here then we didn't have a cached version so we + need to recreate the layout */ + if (oldest_cache->layout) + g_object_unref (oldest_cache->layout); + + oldest_cache->layout = + clutter_text_create_layout_no_cache (text, width, height, ellipsize); + + cogl_pango_ensure_glyph_cache_for_layout (oldest_cache->layout); + + /* Mark the 'time' this cache was created and advance the time */ + oldest_cache->age = priv->cache_age++; + return oldest_cache->layout; +} + +/** + * clutter_text_coords_to_position: + * @self: a #ClutterText + * @x: the X coordinate, relative to the actor + * @y: the Y coordinate, relative to the actor + * + * Retrieves the position of the character at the given coordinates. + * + * Return: the position of the character + * + * Since: 1.10 + */ +gint +clutter_text_coords_to_position (ClutterText *self, + gfloat x, + gfloat y) +{ + gint index_; + gint px, py; + gint trailing; + + g_return_val_if_fail (CLUTTER_IS_TEXT (self), 0); + + /* Take any offset due to scrolling into account, and normalize + * the coordinates to PangoScale units + */ + px = (x - self->priv->text_x) * PANGO_SCALE; + py = (y - self->priv->text_y) * PANGO_SCALE; + + pango_layout_xy_to_index (clutter_text_get_layout (self), + px, py, + &index_, &trailing); + + return index_ + trailing; +} + +/** + * clutter_text_position_to_coords: + * @self: a #ClutterText + * @position: position in characters + * @x: (out): return location for the X coordinate, or %NULL + * @y: (out): return location for the Y coordinate, or %NULL + * @line_height: (out): return location for the line height, or %NULL + * + * Retrieves the coordinates of the given @position. + * + * Return value: %TRUE if the conversion was successful + * + * Since: 1.0 + */ +gboolean +clutter_text_position_to_coords (ClutterText *self, + gint position, + gfloat *x, + gfloat *y, + gfloat *line_height) +{ + ClutterTextPrivate *priv; + PangoRectangle rect; + gint n_chars; + gint password_char_bytes = 1; + gint index_; + gsize n_bytes; + + g_return_val_if_fail (CLUTTER_IS_TEXT (self), FALSE); + + priv = self->priv; + + n_chars = clutter_text_buffer_get_length (get_buffer (self)); + if (priv->preedit_set) + n_chars += priv->preedit_n_chars; + + if (position < -1 || position > n_chars) + return FALSE; + + if (priv->password_char != 0) + password_char_bytes = g_unichar_to_utf8 (priv->password_char, NULL); + + if (position == -1) + { + if (priv->password_char == 0) + { + n_bytes = clutter_text_buffer_get_bytes (get_buffer (self)); + if (priv->editable && priv->preedit_set) + index_ = n_bytes + strlen (priv->preedit_str); + else + index_ = n_bytes; + } + else + index_ = n_chars * password_char_bytes; + } + else if (position == 0) + { + index_ = 0; + } + else + { + gchar *text = clutter_text_get_display_text (self); + GString *tmp = g_string_new (text); + gint cursor_index; + + cursor_index = offset_to_bytes (text, priv->position); + + if (priv->preedit_str != NULL) + g_string_insert (tmp, cursor_index, priv->preedit_str); + + if (priv->password_char == 0) + index_ = offset_to_bytes (tmp->str, position); + else + index_ = position * password_char_bytes; + + g_free (text); + g_string_free (tmp, TRUE); + } + + pango_layout_get_cursor_pos (clutter_text_get_layout (self), + index_, + &rect, NULL); + + if (x) + { + *x = (gfloat) rect.x / 1024.0f; + + /* Take any offset due to scrolling into account */ + if (priv->single_line_mode) + *x += priv->text_x; + } + + if (y) + *y = (gfloat) rect.y / 1024.0f; + + if (line_height) + *line_height = (gfloat) rect.height / 1024.0f; + + return TRUE; +} + +static inline void +clutter_text_ensure_cursor_position (ClutterText *self) +{ + ClutterTextPrivate *priv = self->priv; + gfloat x, y, cursor_height; + ClutterRect cursor_rect = CLUTTER_RECT_INIT_ZERO; + gint position; + + position = priv->position; + + if (priv->editable && priv->preedit_set) + { + if (position == -1) + position = clutter_text_buffer_get_length (get_buffer (self)); + + position += priv->preedit_cursor_pos; + } + + CLUTTER_NOTE (MISC, "Cursor at %d (preedit %s at pos: %d)", + position, + priv->preedit_set ? "set" : "unset", + priv->preedit_set ? priv->preedit_cursor_pos : 0); + + x = y = cursor_height = 0; + clutter_text_position_to_coords (self, position, + &x, &y, + &cursor_height); + + clutter_rect_init (&cursor_rect, + x, + y + CURSOR_Y_PADDING, + priv->cursor_size, + cursor_height - 2 * CURSOR_Y_PADDING); + + if (!clutter_rect_equals (&priv->cursor_rect, &cursor_rect)) + { + ClutterGeometry cursor_pos; + + priv->cursor_rect = cursor_rect; + + /* XXX:2.0 - remove */ + cursor_pos.x = clutter_rect_get_x (&priv->cursor_rect); + cursor_pos.y = clutter_rect_get_y (&priv->cursor_rect); + cursor_pos.width = clutter_rect_get_width (&priv->cursor_rect); + cursor_pos.height = clutter_rect_get_height (&priv->cursor_rect); + g_signal_emit (self, text_signals[CURSOR_EVENT], 0, &cursor_pos); + + g_signal_emit (self, text_signals[CURSOR_CHANGED], 0); + } +} + +/** + * clutter_text_delete_selection: + * @self: a #ClutterText + * + * Deletes the currently selected text + * + * This function is only useful in subclasses of #ClutterText + * + * Return value: %TRUE if text was deleted or if the text actor + * is empty, and %FALSE otherwise + * + * Since: 1.0 + */ +gboolean +clutter_text_delete_selection (ClutterText *self) +{ + ClutterTextPrivate *priv; + gint start_index; + gint end_index; + gint old_position, old_selection; + guint n_chars; + + g_return_val_if_fail (CLUTTER_IS_TEXT (self), FALSE); + + priv = self->priv; + + n_chars = clutter_text_buffer_get_length (get_buffer (self)); + if (n_chars == 0) + return TRUE; + + start_index = priv->position == -1 ? n_chars : priv->position; + end_index = priv->selection_bound == -1 ? n_chars : priv->selection_bound; + + if (end_index == start_index) + return FALSE; + + if (end_index < start_index) + { + gint temp = start_index; + start_index = end_index; + end_index = temp; + } + + old_position = priv->position; + old_selection = priv->selection_bound; + + clutter_text_delete_text (self, start_index, end_index); + + priv->position = start_index; + priv->selection_bound = start_index; + + /* Not required to be guarded by g_object_freeze/thaw_notify */ + if (priv->position != old_position) + { + /* XXX:2.0 - remove */ + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_POSITION]); + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_CURSOR_POSITION]); + } + + if (priv->selection_bound != old_selection) + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SELECTION_BOUND]); + + return TRUE; +} + +/* + * Utility function to update both cursor position and selection bound + * at once + */ +static inline void +clutter_text_set_positions (ClutterText *self, + gint new_pos, + gint new_bound) +{ + g_object_freeze_notify (G_OBJECT (self)); + clutter_text_set_cursor_position (self, new_pos); + clutter_text_set_selection_bound (self, new_bound); + g_object_thaw_notify (G_OBJECT (self)); +} + +static inline void +clutter_text_set_markup_internal (ClutterText *self, + const gchar *str) +{ + ClutterTextPrivate *priv = self->priv; + GError *error; + gchar *text = NULL; + PangoAttrList *attrs = NULL; + gboolean res; + + g_assert (str != NULL); + + error = NULL; + res = pango_parse_markup (str, -1, 0, + &attrs, + &text, + NULL, + &error); + + if (!res) + { + if (G_LIKELY (error != NULL)) + { + g_warning ("Failed to set the markup of the actor '%s': %s", + _clutter_actor_get_debug_name (CLUTTER_ACTOR (self)), + error->message); + g_error_free (error); + } + else + g_warning ("Failed to set the markup of the actor '%s'", + _clutter_actor_get_debug_name (CLUTTER_ACTOR (self))); + + return; + } + + if (text) + { + clutter_text_buffer_set_text (get_buffer (self), text, -1); + g_free (text); + } + + /* Store the new markup attributes */ + if (priv->markup_attrs != NULL) + pango_attr_list_unref (priv->markup_attrs); + + priv->markup_attrs = attrs; + + /* Clear the effective attributes so they will be regenerated when a + layout is created */ + if (priv->effective_attrs != NULL) + { + pango_attr_list_unref (priv->effective_attrs); + priv->effective_attrs = NULL; + } +} + +static void +clutter_text_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterText *self = CLUTTER_TEXT (gobject); + + switch (prop_id) + { + case PROP_BUFFER: + clutter_text_set_buffer (self, g_value_get_object (value)); + break; + + case PROP_TEXT: + { + const char *str = g_value_get_string (value); + if (self->priv->use_markup) + clutter_text_set_markup_internal (self, str ? str : ""); + else + clutter_text_buffer_set_text (get_buffer (self), str ? str : "", -1); + } + break; + + case PROP_COLOR: + clutter_text_set_color (self, clutter_value_get_color (value)); + break; + + case PROP_FONT_NAME: + clutter_text_set_font_name (self, g_value_get_string (value)); + break; + + case PROP_FONT_DESCRIPTION: + clutter_text_set_font_description (self, g_value_get_boxed (value)); + break; + + case PROP_USE_MARKUP: + clutter_text_set_use_markup (self, g_value_get_boolean (value)); + break; + + case PROP_ATTRIBUTES: + clutter_text_set_attributes (self, g_value_get_boxed (value)); + break; + + case PROP_LINE_ALIGNMENT: + clutter_text_set_line_alignment (self, g_value_get_enum (value)); + break; + + case PROP_LINE_WRAP: + clutter_text_set_line_wrap (self, g_value_get_boolean (value)); + break; + + case PROP_LINE_WRAP_MODE: + clutter_text_set_line_wrap_mode (self, g_value_get_enum (value)); + break; + + case PROP_JUSTIFY: + clutter_text_set_justify (self, g_value_get_boolean (value)); + break; + + case PROP_ELLIPSIZE: + clutter_text_set_ellipsize (self, g_value_get_enum (value)); + break; + + case PROP_POSITION: /* XXX:2.0: remove */ + case PROP_CURSOR_POSITION: + clutter_text_set_cursor_position (self, g_value_get_int (value)); + break; + + case PROP_SELECTION_BOUND: + clutter_text_set_selection_bound (self, g_value_get_int (value)); + break; + + case PROP_SELECTION_COLOR: + clutter_text_set_selection_color (self, g_value_get_boxed (value)); + break; + + case PROP_CURSOR_VISIBLE: + clutter_text_set_cursor_visible (self, g_value_get_boolean (value)); + break; + + case PROP_CURSOR_COLOR: + clutter_text_set_cursor_color (self, g_value_get_boxed (value)); + break; + + case PROP_CURSOR_SIZE: + clutter_text_set_cursor_size (self, g_value_get_int (value)); + break; + + case PROP_EDITABLE: + clutter_text_set_editable (self, g_value_get_boolean (value)); + break; + + case PROP_ACTIVATABLE: + clutter_text_set_activatable (self, g_value_get_boolean (value)); + break; + + case PROP_SELECTABLE: + clutter_text_set_selectable (self, g_value_get_boolean (value)); + break; + + case PROP_PASSWORD_CHAR: + clutter_text_set_password_char (self, g_value_get_uint (value)); + break; + + case PROP_MAX_LENGTH: + clutter_text_set_max_length (self, g_value_get_int (value)); + break; + + case PROP_SINGLE_LINE_MODE: + clutter_text_set_single_line_mode (self, g_value_get_boolean (value)); + break; + + case PROP_SELECTED_TEXT_COLOR: + clutter_text_set_selected_text_color (self, clutter_value_get_color (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + } +} + +static void +clutter_text_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterText *self = CLUTTER_TEXT (gobject); + ClutterTextPrivate *priv = self->priv; + + switch (prop_id) + { + case PROP_BUFFER: + g_value_set_object (value, clutter_text_get_buffer (self)); + break; + + case PROP_TEXT: + g_value_set_string (value, clutter_text_buffer_get_text (get_buffer (self))); + break; + + case PROP_FONT_NAME: + g_value_set_string (value, priv->font_name); + break; + + case PROP_FONT_DESCRIPTION: + g_value_set_boxed (value, priv->font_desc); + break; + + case PROP_USE_MARKUP: + g_value_set_boolean (value, priv->use_markup); + break; + + case PROP_COLOR: + clutter_value_set_color (value, &priv->text_color); + break; + + case PROP_CURSOR_VISIBLE: + g_value_set_boolean (value, priv->cursor_visible); + break; + + case PROP_CURSOR_COLOR: + clutter_value_set_color (value, &priv->cursor_color); + break; + + case PROP_CURSOR_COLOR_SET: + g_value_set_boolean (value, priv->cursor_color_set); + break; + + case PROP_CURSOR_SIZE: + g_value_set_int (value, priv->cursor_size); + break; + + case PROP_POSITION: /* XXX:2.0 - remove */ + case PROP_CURSOR_POSITION: + g_value_set_int (value, priv->position); + break; + + case PROP_SELECTION_BOUND: + g_value_set_int (value, priv->selection_bound); + break; + + case PROP_EDITABLE: + g_value_set_boolean (value, priv->editable); + break; + + case PROP_SELECTABLE: + g_value_set_boolean (value, priv->selectable); + break; + + case PROP_SELECTION_COLOR: + clutter_value_set_color (value, &priv->selection_color); + break; + + case PROP_SELECTION_COLOR_SET: + g_value_set_boolean (value, priv->selection_color_set); + break; + + case PROP_ACTIVATABLE: + g_value_set_boolean (value, priv->activatable); + break; + + case PROP_PASSWORD_CHAR: + g_value_set_uint (value, priv->password_char); + break; + + case PROP_MAX_LENGTH: + g_value_set_int (value, clutter_text_buffer_get_max_length (get_buffer (self))); + break; + + case PROP_SINGLE_LINE_MODE: + g_value_set_boolean (value, priv->single_line_mode); + break; + + case PROP_ELLIPSIZE: + g_value_set_enum (value, priv->ellipsize); + break; + + case PROP_LINE_WRAP: + g_value_set_boolean (value, priv->wrap); + break; + + case PROP_LINE_WRAP_MODE: + g_value_set_enum (value, priv->wrap_mode); + break; + + case PROP_LINE_ALIGNMENT: + g_value_set_enum (value, priv->alignment); + break; + + case PROP_JUSTIFY: + g_value_set_boolean (value, priv->justify); + break; + + case PROP_ATTRIBUTES: + g_value_set_boxed (value, priv->attrs); + break; + + case PROP_SELECTED_TEXT_COLOR: + clutter_value_set_color (value, &priv->selected_text_color); + break; + + case PROP_SELECTED_TEXT_COLOR_SET: + g_value_set_boolean (value, priv->selected_text_color_set); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + } +} + +static void +clutter_text_dispose (GObject *gobject) +{ + ClutterText *self = CLUTTER_TEXT (gobject); + ClutterTextPrivate *priv = self->priv; + + /* get rid of the entire cache */ + clutter_text_dirty_cache (self); + + if (priv->direction_changed_id) + { + g_signal_handler_disconnect (self, priv->direction_changed_id); + priv->direction_changed_id = 0; + } + + if (priv->settings_changed_id) + { + g_signal_handler_disconnect (clutter_get_default_backend (), + priv->settings_changed_id); + priv->settings_changed_id = 0; + } + + if (priv->password_hint_id) + { + g_source_remove (priv->password_hint_id); + priv->password_hint_id = 0; + } + + clutter_text_set_buffer (self, NULL); + + G_OBJECT_CLASS (clutter_text_parent_class)->dispose (gobject); +} + +static void +clutter_text_finalize (GObject *gobject) +{ + ClutterText *self = CLUTTER_TEXT (gobject); + ClutterTextPrivate *priv = self->priv; + + if (priv->font_desc) + pango_font_description_free (priv->font_desc); + + if (priv->attrs) + pango_attr_list_unref (priv->attrs); + if (priv->markup_attrs) + pango_attr_list_unref (priv->markup_attrs); + if (priv->effective_attrs) + pango_attr_list_unref (priv->effective_attrs); + if (priv->preedit_attrs) + pango_attr_list_unref (priv->preedit_attrs); + + clutter_text_dirty_paint_volume (self); + + clutter_text_set_buffer (self, NULL); + g_free (priv->font_name); + + G_OBJECT_CLASS (clutter_text_parent_class)->finalize (gobject); +} + +typedef void (* ClutterTextSelectionFunc) (ClutterText *text, + const ClutterActorBox *box, + gpointer user_data); + +static void +clutter_text_foreach_selection_rectangle (ClutterText *self, + ClutterTextSelectionFunc func, + gpointer user_data) +{ + ClutterTextPrivate *priv = self->priv; + PangoLayout *layout = clutter_text_get_layout (self); + gchar *utf8 = clutter_text_get_display_text (self); + gint lines; + gint start_index; + gint end_index; + gint line_no; + + if (priv->position == 0) + start_index = 0; + else + start_index = offset_to_bytes (utf8, priv->position); + + if (priv->selection_bound == 0) + end_index = 0; + else + end_index = offset_to_bytes (utf8, priv->selection_bound); + + if (start_index > end_index) + { + gint temp = start_index; + start_index = end_index; + end_index = temp; + } + + lines = pango_layout_get_line_count (layout); + + for (line_no = 0; line_no < lines; line_no++) + { + PangoLayoutLine *line; + gint n_ranges; + gint *ranges; + gint i; + gint index_; + gint maxindex; + ClutterActorBox box; + gfloat y, height; + + line = pango_layout_get_line_readonly (layout, line_no); + pango_layout_line_x_to_index (line, G_MAXINT, &maxindex, NULL); + if (maxindex < start_index) + continue; + + pango_layout_line_get_x_ranges (line, start_index, end_index, + &ranges, + &n_ranges); + pango_layout_line_x_to_index (line, 0, &index_, NULL); + + clutter_text_position_to_coords (self, + bytes_to_offset (utf8, index_), + NULL, &y, &height); + + box.y1 = y; + box.y2 = y + height; + + for (i = 0; i < n_ranges; i++) + { + gfloat range_x; + gfloat range_width; + + 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_width = ((gfloat) ranges[i * 2 + 1] - (gfloat) ranges[i * 2]) + / PANGO_SCALE; + + box.x1 = range_x; + box.x2 = ceilf (range_x + range_width + .5f); + + func (self, &box, user_data); + } + + g_free (ranges); + } + + g_free (utf8); +} + +static void +add_selection_rectangle_to_path (ClutterText *text, + const ClutterActorBox *box, + gpointer user_data) +{ + cogl_path_rectangle (user_data, box->x1, box->y1, box->x2, box->y2); +} + +/* Draws the selected text, its background, and the cursor */ +static void +selection_paint (ClutterText *self) +{ + ClutterTextPrivate *priv = self->priv; + ClutterActor *actor = CLUTTER_ACTOR (self); + guint8 paint_opacity = clutter_actor_get_paint_opacity (actor); + const ClutterColor *color; + + if (!clutter_text_should_draw_cursor (self)) + return; + + if (priv->position == priv->selection_bound) + { + /* No selection, just draw the cursor */ + if (priv->cursor_color_set) + color = &priv->cursor_color; + else + color = &priv->text_color; + + cogl_set_source_color4ub (color->red, + color->green, + color->blue, + paint_opacity * color->alpha / 255); + + cogl_rectangle (priv->cursor_rect.origin.x, + priv->cursor_rect.origin.y, + priv->cursor_rect.origin.x + priv->cursor_rect.size.width, + priv->cursor_rect.origin.y + priv->cursor_rect.size.height); + } + else + { + /* Paint selection background first */ + PangoLayout *layout = clutter_text_get_layout (self); + CoglPath *selection_path = cogl_path_new (); + CoglColor cogl_color = { 0, }; + CoglFramebuffer *fb; + + fb = _clutter_actor_get_active_framebuffer (actor); + if (G_UNLIKELY (fb == NULL)) + return; + + /* Paint selection background */ + if (priv->selection_color_set) + color = &priv->selection_color; + else if (priv->cursor_color_set) + color = &priv->cursor_color; + else + color = &priv->text_color; + + cogl_set_source_color4ub (color->red, + color->green, + color->blue, + paint_opacity * color->alpha / 255); + + clutter_text_foreach_selection_rectangle (self, + add_selection_rectangle_to_path, + selection_path); + + cogl_path_fill (selection_path); + + /* Paint selected text */ + cogl_framebuffer_push_path_clip (fb, selection_path); + cogl_object_unref (selection_path); + + if (priv->selected_text_color_set) + color = &priv->selected_text_color; + else + color = &priv->text_color; + + cogl_color_init_from_4ub (&cogl_color, + color->red, + color->green, + color->blue, + paint_opacity * color->alpha / 255); + + cogl_pango_render_layout (layout, priv->text_x, 0, &cogl_color, 0); + + cogl_framebuffer_pop_clip (fb); + } +} + +static gint +clutter_text_move_word_backward (ClutterText *self, + gint start) +{ + gint retval = start; + + if (clutter_text_buffer_get_length (get_buffer (self)) > 0 && start > 0) + { + PangoLayout *layout = clutter_text_get_layout (self); + PangoLogAttr *log_attrs = NULL; + gint n_attrs = 0; + + pango_layout_get_log_attrs (layout, &log_attrs, &n_attrs); + + retval = start - 1; + while (retval > 0 && !log_attrs[retval].is_word_start) + retval -= 1; + + g_free (log_attrs); + } + + return retval; +} + +static gint +clutter_text_move_word_forward (ClutterText *self, + gint start) +{ + gint retval = start; + guint n_chars; + + n_chars = clutter_text_buffer_get_length (get_buffer (self)); + if (n_chars > 0 && start < n_chars) + { + PangoLayout *layout = clutter_text_get_layout (self); + PangoLogAttr *log_attrs = NULL; + gint n_attrs = 0; + + pango_layout_get_log_attrs (layout, &log_attrs, &n_attrs); + + retval = start + 1; + while (retval < n_chars && !log_attrs[retval].is_word_end) + retval += 1; + + g_free (log_attrs); + } + + return retval; +} + +static gint +clutter_text_move_line_start (ClutterText *self, + gint start) +{ + PangoLayoutLine *layout_line; + PangoLayout *layout; + gint line_no; + gint index_; + gint position; + const gchar *text; + + layout = clutter_text_get_layout (self); + text = clutter_text_buffer_get_text (get_buffer (self)); + + if (start == 0) + index_ = 0; + else + index_ = offset_to_bytes (text, start); + + pango_layout_index_to_line_x (layout, index_, + 0, + &line_no, NULL); + + layout_line = pango_layout_get_line_readonly (layout, line_no); + if (!layout_line) + return FALSE; + + pango_layout_line_x_to_index (layout_line, 0, &index_, NULL); + + position = bytes_to_offset (text, index_); + + return position; +} + +static gint +clutter_text_move_line_end (ClutterText *self, + gint start) +{ + ClutterTextPrivate *priv = self->priv; + PangoLayoutLine *layout_line; + PangoLayout *layout; + gint line_no; + gint index_; + gint trailing; + gint position; + const gchar *text; + + layout = clutter_text_get_layout (self); + text = clutter_text_buffer_get_text (get_buffer (self)); + + if (start == 0) + index_ = 0; + else + index_ = offset_to_bytes (text, priv->position); + + pango_layout_index_to_line_x (layout, index_, + 0, + &line_no, NULL); + + layout_line = pango_layout_get_line_readonly (layout, line_no); + if (!layout_line) + return FALSE; + + pango_layout_line_x_to_index (layout_line, G_MAXINT, &index_, &trailing); + index_ += trailing; + + position = bytes_to_offset (text, index_); + + return position; +} + +static void +clutter_text_select_word (ClutterText *self) +{ + gint cursor_pos = self->priv->position; + gint start_pos, end_pos; + + start_pos = clutter_text_move_word_backward (self, cursor_pos); + end_pos = clutter_text_move_word_forward (self, cursor_pos); + + clutter_text_set_selection (self, start_pos, end_pos); +} + +static void +clutter_text_select_line (ClutterText *self) +{ + ClutterTextPrivate *priv = self->priv; + gint cursor_pos = priv->position; + gint start_pos, end_pos; + + if (priv->single_line_mode) + { + start_pos = 0; + end_pos = -1; + } + else + { + start_pos = clutter_text_move_line_start (self, cursor_pos); + end_pos = clutter_text_move_line_end (self, cursor_pos); + } + + clutter_text_set_selection (self, start_pos, end_pos); +} + +static gboolean +clutter_text_press (ClutterActor *actor, + ClutterEvent *event) +{ + ClutterText *self = CLUTTER_TEXT (actor); + ClutterTextPrivate *priv = self->priv; + ClutterEventType type = clutter_event_type (event); + gboolean res = FALSE; + gfloat x, y; + gint index_; + + /* if a ClutterText is just used for display purposes, then we + * should ignore the events we receive + */ + if (!(priv->editable || priv->selectable)) + return CLUTTER_EVENT_PROPAGATE; + + clutter_actor_grab_key_focus (actor); + + /* if the actor is empty we just reset everything and not + * set up the dragging of the selection since there's nothing + * to select + */ + if (clutter_text_buffer_get_length (get_buffer (self)) == 0) + { + clutter_text_set_positions (self, -1, -1); + + return CLUTTER_EVENT_STOP; + } + + clutter_event_get_coords (event, &x, &y); + + res = clutter_actor_transform_stage_point (actor, x, y, &x, &y); + if (res) + { + const char *text; + int offset; + + index_ = clutter_text_coords_to_position (self, x, y); + text = clutter_text_buffer_get_text (get_buffer (self)); + offset = bytes_to_offset (text, index_); + + /* what we select depends on the number of button clicks we + * receive, and whether we are selectable: + * + * 1: just position the cursor and the selection + * 2: select the current word + * 3: select the contents of the whole actor + */ + if (type == CLUTTER_BUTTON_PRESS) + { + gint click_count = clutter_event_get_click_count (event); + + if (click_count == 1) + { + clutter_text_set_positions (self, offset, offset); + } + else if (priv->selectable && click_count == 2) + { + clutter_text_select_word (self); + } + else if (priv->selectable && click_count == 3) + { + clutter_text_select_line (self); + } + } + else + { + /* touch events do not have click count */ + clutter_text_set_positions (self, offset, offset); + } + } + + /* we don't need to go any further if we're not selectable */ + if (!priv->selectable) + return CLUTTER_EVENT_STOP; + + /* grab the pointer */ + priv->in_select_drag = TRUE; + + if (type == CLUTTER_BUTTON_PRESS) + clutter_grab_pointer (actor); + else + { + clutter_input_device_sequence_grab (clutter_event_get_device (event), + clutter_event_get_event_sequence (event), + actor); + priv->in_select_touch = TRUE; + } + + return CLUTTER_EVENT_STOP; +} + +static gboolean +clutter_text_move (ClutterActor *actor, + ClutterEvent *event) +{ + ClutterText *self = CLUTTER_TEXT (actor); + ClutterTextPrivate *priv = self->priv; + gfloat x, y; + gint index_, offset; + gboolean res; + const gchar *text; + + if (!priv->in_select_drag) + return CLUTTER_EVENT_PROPAGATE; + + clutter_event_get_coords (event, &x, &y); + + res = clutter_actor_transform_stage_point (actor, x, y, &x, &y); + if (!res) + return CLUTTER_EVENT_PROPAGATE; + + index_ = clutter_text_coords_to_position (self, x, y); + text = clutter_text_buffer_get_text (get_buffer (self)); + offset = bytes_to_offset (text, index_); + + if (priv->selectable) + clutter_text_set_cursor_position (self, offset); + else + clutter_text_set_positions (self, offset, offset); + + return CLUTTER_EVENT_STOP; +} + +static gboolean +clutter_text_release (ClutterActor *actor, + ClutterEvent *event) +{ + ClutterText *self = CLUTTER_TEXT (actor); + ClutterTextPrivate *priv = self->priv; + ClutterEventType type = clutter_event_type (event); + + if (priv->in_select_drag) + { + if (type == CLUTTER_BUTTON_RELEASE) + { + if (!priv->in_select_touch) + { + clutter_ungrab_pointer (); + priv->in_select_drag = FALSE; + + return CLUTTER_EVENT_STOP; + } + } + else + { + if (priv->in_select_touch) + { + ClutterInputDevice *device = clutter_event_get_device (event); + ClutterEventSequence *sequence = + clutter_event_get_event_sequence (event); + + clutter_input_device_sequence_ungrab (device, sequence); + priv->in_select_touch = FALSE; + priv->in_select_drag = FALSE; + + return CLUTTER_EVENT_STOP; + } + } + } + + return CLUTTER_EVENT_PROPAGATE; +} + +static gboolean +clutter_text_button_press (ClutterActor *actor, + ClutterButtonEvent *event) +{ + return clutter_text_press (actor, (ClutterEvent *) event); +} + +static gboolean +clutter_text_motion (ClutterActor *actor, + ClutterMotionEvent *event) +{ + return clutter_text_move (actor, (ClutterEvent *) event); +} + +static gboolean +clutter_text_button_release (ClutterActor *actor, + ClutterButtonEvent *event) +{ + return clutter_text_release (actor, (ClutterEvent *) event); +} + +static gboolean +clutter_text_touch_event (ClutterActor *actor, + ClutterTouchEvent *event) +{ + switch (event->type) + { + case CLUTTER_TOUCH_BEGIN: + return clutter_text_press (actor, (ClutterEvent *) event); + + case CLUTTER_TOUCH_END: + case CLUTTER_TOUCH_CANCEL: + /* TODO: the cancel case probably need a special handler */ + return clutter_text_release (actor, (ClutterEvent *) event); + + case CLUTTER_TOUCH_UPDATE: + return clutter_text_move (actor, (ClutterEvent *) event); + + default: + break; + } + + return CLUTTER_EVENT_PROPAGATE; +} + +static gboolean +clutter_text_remove_password_hint (gpointer data) +{ + ClutterText *self = data; + + self->priv->password_hint_visible = FALSE; + self->priv->password_hint_id = 0; + + clutter_text_dirty_cache (data); + clutter_text_queue_redraw (data); + + return G_SOURCE_REMOVE; +} + +static gboolean +clutter_text_key_press (ClutterActor *actor, + ClutterKeyEvent *event) +{ + ClutterText *self = CLUTTER_TEXT (actor); + ClutterTextPrivate *priv = self->priv; + ClutterBindingPool *pool; + gboolean res; + + if (!priv->editable) + return CLUTTER_EVENT_PROPAGATE; + + /* we need to use the ClutterText type name to find our own + * key bindings; subclasses will override or chain up this + * event handler, so they can do whatever they want there + */ + pool = clutter_binding_pool_find (g_type_name (CLUTTER_TYPE_TEXT)); + g_assert (pool != NULL); + + /* we allow passing synthetic events that only contain + * the Unicode value and not the key symbol + */ + if (event->keyval == 0 && (event->flags & CLUTTER_EVENT_FLAG_SYNTHETIC)) + res = FALSE; + else + res = clutter_binding_pool_activate (pool, event->keyval, + event->modifier_state, + G_OBJECT (actor)); + + /* if the key binding has handled the event we bail out + * as fast as we can; otherwise, we try to insert the + * Unicode character inside the key event into the text + * actor + */ + if (res) + return CLUTTER_EVENT_STOP; + else if ((event->modifier_state & CLUTTER_CONTROL_MASK) == 0) + { + gunichar key_unichar; + + /* Skip keys when control is pressed */ + key_unichar = clutter_event_get_key_unicode ((ClutterEvent *) event); + + /* return is reported as CR, but we want LF */ + if (key_unichar == '\r') + key_unichar = '\n'; + + if ((key_unichar == '\n' && !priv->single_line_mode) || + (g_unichar_validate (key_unichar) && + !g_unichar_iscntrl (key_unichar))) + { + /* truncate the eventual selection so that the + * Unicode character can replace it + */ + clutter_text_delete_selection (self); + clutter_text_insert_unichar (self, key_unichar); + + if (priv->show_password_hint) + { + if (priv->password_hint_id != 0) + g_source_remove (priv->password_hint_id); + + priv->password_hint_visible = TRUE; + priv->password_hint_id = + clutter_threads_add_timeout (priv->password_hint_timeout, + clutter_text_remove_password_hint, + self); + } + + return CLUTTER_EVENT_STOP; + } + } + + return CLUTTER_EVENT_PROPAGATE; +} + +static void +clutter_text_compute_layout_offsets (ClutterText *self, + PangoLayout *layout, + const ClutterActorBox *alloc, + int *text_x, + int *text_y) +{ + ClutterActor *actor = CLUTTER_ACTOR (self); + ClutterActorAlign x_align, y_align; + PangoRectangle logical_rect; + float alloc_width, alloc_height; + float x, y; + + clutter_actor_box_get_size (alloc, &alloc_width, &alloc_height); + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + + if (clutter_actor_needs_expand (actor, CLUTTER_ORIENTATION_HORIZONTAL)) + x_align = _clutter_actor_get_effective_x_align (actor); + else + x_align = CLUTTER_ACTOR_ALIGN_FILL; + + if (clutter_actor_needs_expand (actor, CLUTTER_ORIENTATION_VERTICAL)) + y_align = clutter_actor_get_y_align (actor); + else + y_align = CLUTTER_ACTOR_ALIGN_FILL; + + x = 0.f; + switch (x_align) + { + case CLUTTER_ACTOR_ALIGN_FILL: + case CLUTTER_ACTOR_ALIGN_START: + break; + + case CLUTTER_ACTOR_ALIGN_END: + if (alloc_width > logical_rect.width) + x = alloc_width - logical_rect.width; + break; + + case CLUTTER_ACTOR_ALIGN_CENTER: + if (alloc_width > logical_rect.width) + x = (alloc_width - logical_rect.width) / 2.f; + break; + } + + y = 0.f; + switch (y_align) + { + case CLUTTER_ACTOR_ALIGN_FILL: + case CLUTTER_ACTOR_ALIGN_START: + break; + + case CLUTTER_ACTOR_ALIGN_END: + if (alloc_height > logical_rect.height) + y = alloc_height - logical_rect.height; + break; + + case CLUTTER_ACTOR_ALIGN_CENTER: + if (alloc_height > logical_rect.height) + y = (alloc_height - logical_rect.height) / 2.f; + break; + } + + if (text_x != NULL) + *text_x = floorf (x); + + if (text_y != NULL) + *text_y = floorf (y); +} + +#define TEXT_PADDING 2 + +static void +clutter_text_paint (ClutterActor *self) +{ + ClutterText *text = CLUTTER_TEXT (self); + ClutterTextPrivate *priv = text->priv; + CoglFramebuffer *fb; + PangoLayout *layout; + ClutterActorBox alloc = { 0, }; + CoglColor color = { 0, }; + guint8 real_opacity; + gint text_x = priv->text_x; + gint text_y = priv->text_y; + gboolean clip_set = FALSE; + gboolean bg_color_set = FALSE; + guint n_chars; + float alloc_width; + float alloc_height; + + /* FIXME: this should not be needed, but apparently the text-cache + * test unit manages to get in a situation where the active frame + * buffer is NULL + */ + fb = _clutter_actor_get_active_framebuffer (self); + if (fb == NULL) + fb = cogl_get_draw_framebuffer (); + + /* Note that if anything in this paint method changes it needs to be + reflected in the get_paint_volume implementation which is tightly + tied to the workings of this function */ + n_chars = clutter_text_buffer_get_length (get_buffer (text)); + + clutter_actor_get_allocation_box (self, &alloc); + alloc_width = alloc.x2 - alloc.x1; + alloc_height = alloc.y2 - alloc.y1; + + g_object_get (self, "background-color-set", &bg_color_set, NULL); + if (bg_color_set) + { + ClutterColor bg_color; + + clutter_actor_get_background_color (self, &bg_color); + bg_color.alpha = clutter_actor_get_paint_opacity (self) + * bg_color.alpha + / 255; + + cogl_set_source_color4ub (bg_color.red, + bg_color.green, + bg_color.blue, + bg_color.alpha); + cogl_rectangle (0, 0, alloc_width, alloc_height); + } + + /* don't bother painting an empty text actor, unless it's + * editable, in which case we want to paint at least the + * cursor + */ + if (n_chars == 0 && + !clutter_text_should_draw_cursor (text)) + return; + + if (priv->editable && priv->single_line_mode) + layout = clutter_text_create_layout (text, -1, -1); + else + { + /* the only time when we create the PangoLayout using the full + * width and height of the allocation is when we can both wrap + * and ellipsize + */ + if (priv->wrap && priv->ellipsize) + { + layout = clutter_text_create_layout (text, alloc_width, alloc_height); + } + else + { + /* if we're not wrapping we cannot set the height of the + * layout, otherwise Pango will happily wrap the text to + * fit in the rectangle - thus making the :wrap property + * useless + * + * see bug: + * + * http://bugzilla.clutter-project.org/show_bug.cgi?id=2339 + * + * in order to fix this, we create a layout that would fit + * in the assigned width, then we clip the actor if the + * logical rectangle overflows the allocation. + */ + layout = clutter_text_create_layout (text, alloc_width, -1); + } + } + + if (clutter_text_should_draw_cursor (text)) + clutter_text_ensure_cursor_position (text); + + if (priv->editable && priv->single_line_mode) + { + PangoRectangle logical_rect = { 0, }; + gint actor_width, text_width; + gboolean rtl; + + pango_layout_get_extents (layout, NULL, &logical_rect); + + cogl_framebuffer_push_rectangle_clip (fb, 0, 0, alloc_width, alloc_height); + clip_set = TRUE; + + actor_width = alloc_width - 2 * TEXT_PADDING; + text_width = logical_rect.width / PANGO_SCALE; + + rtl = priv->resolved_direction == PANGO_DIRECTION_RTL; + + if (actor_width < text_width) + { + gint cursor_x = clutter_rect_get_x (&priv->cursor_rect); + + if (priv->position == -1) + { + text_x = rtl ? TEXT_PADDING : actor_width - text_width; + } + else if (priv->position == 0) + { + text_x = rtl ? actor_width - text_width : TEXT_PADDING; + } + else + { + if (cursor_x < 0) + { + text_x = text_x - cursor_x - TEXT_PADDING; + } + else if (cursor_x > actor_width) + { + text_x = text_x + (actor_width - cursor_x) - TEXT_PADDING; + } + } + } + else + { + text_x = rtl ? actor_width - text_width : TEXT_PADDING; + } + } + else if (!priv->editable && !(priv->wrap && priv->ellipsize)) + { + PangoRectangle logical_rect = { 0, }; + + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + + /* don't clip if the layout managed to fit inside our allocation */ + if (logical_rect.width > alloc_width || + logical_rect.height > alloc_height) + { + cogl_framebuffer_push_rectangle_clip (fb, 0, 0, alloc_width, alloc_height); + clip_set = TRUE; + } + + clutter_text_compute_layout_offsets (text, layout, &alloc, &text_x, &text_y); + } + else + clutter_text_compute_layout_offsets (text, layout, &alloc, &text_x, &text_y); + + if (priv->text_x != text_x || + priv->text_y != text_y) + { + priv->text_x = text_x; + priv->text_y = text_y; + + clutter_text_ensure_cursor_position (text); + } + + real_opacity = clutter_actor_get_paint_opacity (self) + * priv->text_color.alpha + / 255; + + CLUTTER_NOTE (PAINT, "painting text (text: '%s')", + clutter_text_buffer_get_text (get_buffer (text))); + + cogl_color_init_from_4ub (&color, + priv->text_color.red, + priv->text_color.green, + priv->text_color.blue, + real_opacity); + cogl_pango_render_layout (layout, priv->text_x, priv->text_y, &color, 0); + + selection_paint (text); + + if (clip_set) + cogl_framebuffer_pop_clip (fb); +} + +static void +add_selection_to_paint_volume (ClutterText *text, + const ClutterActorBox *box, + gpointer user_data) +{ + ClutterPaintVolume *total_volume = user_data; + ClutterPaintVolume rect_volume; + ClutterVertex vertex; + + _clutter_paint_volume_init_static (&rect_volume, CLUTTER_ACTOR (text)); + + vertex.x = box->x1; + vertex.y = box->y1; + vertex.z = 0.0f; + clutter_paint_volume_set_origin (&rect_volume, &vertex); + clutter_paint_volume_set_width (&rect_volume, box->x2 - box->x1); + clutter_paint_volume_set_height (&rect_volume, box->y2 - box->y1); + + clutter_paint_volume_union (total_volume, &rect_volume); + + clutter_paint_volume_free (&rect_volume); +} + +static void +clutter_text_get_paint_volume_for_cursor (ClutterText *text, + ClutterPaintVolume *volume) +{ + ClutterTextPrivate *priv = text->priv; + ClutterVertex origin; + + clutter_text_ensure_cursor_position (text); + + if (priv->position == priv->selection_bound) + { + origin.x = priv->cursor_rect.origin.x; + origin.y = priv->cursor_rect.origin.y; + origin.z = 0; + + clutter_paint_volume_set_origin (volume, &origin); + clutter_paint_volume_set_width (volume, priv->cursor_rect.size.width); + clutter_paint_volume_set_height (volume, priv->cursor_rect.size.height); + } + else + { + clutter_text_foreach_selection_rectangle (text, + add_selection_to_paint_volume, + volume); + } +} + +static gboolean +clutter_text_get_paint_volume (ClutterActor *self, + ClutterPaintVolume *volume) +{ + ClutterText *text = CLUTTER_TEXT (self); + ClutterTextPrivate *priv = text->priv; + + /* ClutterText uses the logical layout as the natural size of the + actor. This means that it can sometimes paint outside of its + allocation for example with italic fonts with serifs. Therefore + we should use the ink rectangle of the layout instead */ + + if (!priv->paint_volume_valid) + { + PangoLayout *layout; + PangoRectangle ink_rect; + ClutterVertex origin; + + /* If the text is single line editable then it gets clipped to + the allocation anyway so we can just use that */ + if (priv->editable && priv->single_line_mode) + return _clutter_actor_set_default_paint_volume (self, + CLUTTER_TYPE_TEXT, + volume); + + if (G_OBJECT_TYPE (self) != CLUTTER_TYPE_TEXT) + return FALSE; + + if (!clutter_actor_has_allocation (self)) + return FALSE; + + _clutter_paint_volume_init_static (&priv->paint_volume, self); + + layout = clutter_text_get_layout (text); + pango_layout_get_extents (layout, &ink_rect, NULL); + + origin.x = ink_rect.x / (float) PANGO_SCALE; + origin.y = ink_rect.y / (float) PANGO_SCALE; + origin.z = 0; + clutter_paint_volume_set_origin (&priv->paint_volume, &origin); + clutter_paint_volume_set_width (&priv->paint_volume, + ink_rect.width / (float) PANGO_SCALE); + clutter_paint_volume_set_height (&priv->paint_volume, + ink_rect.height / (float) PANGO_SCALE); + + /* If the cursor is visible then that will likely be drawn + outside of the ink rectangle so we should merge that in */ + if (clutter_text_should_draw_cursor (text)) + { + ClutterPaintVolume cursor_paint_volume; + + _clutter_paint_volume_init_static (&cursor_paint_volume, self); + + clutter_text_get_paint_volume_for_cursor (text, &cursor_paint_volume); + + clutter_paint_volume_union (&priv->paint_volume, + &cursor_paint_volume); + + clutter_paint_volume_free (&cursor_paint_volume); + } + + priv->paint_volume_valid = TRUE; + } + + _clutter_paint_volume_copy_static (&priv->paint_volume, volume); + + return TRUE; +} + +static void +clutter_text_get_preferred_width (ClutterActor *self, + 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; + gfloat layout_width; + + layout = clutter_text_create_layout (text, -1, -1); + + pango_layout_get_extents (layout, NULL, &logical_rect); + + /* the X coordinate of the logical rectangle might be non-zero + * according to the Pango documentation; hence, we need to offset + * the width accordingly + */ + logical_width = logical_rect.x + logical_rect.width; + + layout_width = logical_width > 0 + ? ceilf (logical_width / 1024.0f) + : 1; + + if (min_width_p) + { + if (priv->wrap || priv->ellipsize || priv->editable) + *min_width_p = 1; + else + *min_width_p = layout_width; + } + + if (natural_width_p) + { + if (priv->editable && priv->single_line_mode) + *natural_width_p = layout_width + TEXT_PADDING * 2; + else + *natural_width_p = layout_width; + } +} + +static void +clutter_text_get_preferred_height (ClutterActor *self, + gfloat for_width, + gfloat *min_height_p, + gfloat *natural_height_p) +{ + ClutterTextPrivate *priv = CLUTTER_TEXT (self)->priv; + + if (for_width == 0) + { + if (min_height_p) + *min_height_p = 0; + + if (natural_height_p) + *natural_height_p = 0; + } + else + { + PangoLayout *layout; + PangoRectangle logical_rect = { 0, }; + gint logical_height; + gfloat layout_height; + + if (priv->single_line_mode) + for_width = -1; + + layout = clutter_text_create_layout (CLUTTER_TEXT (self), + for_width, -1); + + pango_layout_get_extents (layout, NULL, &logical_rect); + + /* the Y coordinate of the logical rectangle might be non-zero + * according to the Pango documentation; hence, we need to offset + * the height accordingly + */ + logical_height = logical_rect.y + logical_rect.height; + layout_height = ceilf (logical_height / 1024.0f); + + if (min_height_p) + { + /* if we wrap and ellipsize then the minimum height is + * going to be at least the size of the first line + */ + if ((priv->ellipsize && priv->wrap) && !priv->single_line_mode) + { + PangoLayoutLine *line; + 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 = ceilf (logical_height / 1024.0f); + + *min_height_p = line_height; + } + else + *min_height_p = layout_height; + } + + if (natural_height_p) + *natural_height_p = layout_height; + } +} + +static void +clutter_text_allocate (ClutterActor *self, + const ClutterActorBox *box, + ClutterAllocationFlags flags) +{ + ClutterText *text = CLUTTER_TEXT (self); + ClutterActorClass *parent_class; + + /* Ensure that there is a cached layout with the right width so + * that we don't need to create the text during the paint run + * + * if the Text is editable and in single line mode we don't want + * to have any limit on the layout size, since the paint will clip + * it to the allocation of the actor + */ + if (text->priv->editable && text->priv->single_line_mode) + clutter_text_create_layout (text, -1, -1); + else + clutter_text_create_layout (text, + box->x2 - box->x1, + box->y2 - box->y1); + + parent_class = CLUTTER_ACTOR_CLASS (clutter_text_parent_class); + parent_class->allocate (self, box, flags); +} + +static gboolean +clutter_text_has_overlaps (ClutterActor *self) +{ + return clutter_text_should_draw_cursor ((ClutterText *) self); +} + +static void +clutter_text_key_focus_in (ClutterActor *actor) +{ + ClutterTextPrivate *priv = CLUTTER_TEXT (actor)->priv; + + priv->has_focus = TRUE; + + clutter_text_queue_redraw (actor); +} + +static void +clutter_text_key_focus_out (ClutterActor *actor) +{ + ClutterTextPrivate *priv = CLUTTER_TEXT (actor)->priv; + + priv->has_focus = FALSE; + + clutter_text_queue_redraw (actor); +} + +static gboolean +clutter_text_real_move_left (ClutterText *self, + const gchar *action, + guint keyval, + ClutterModifierType modifiers) +{ + ClutterTextPrivate *priv = self->priv; + gint pos = priv->position; + gint new_pos = 0; + gint len; + + len = clutter_text_buffer_get_length (get_buffer (self)); + + g_object_freeze_notify (G_OBJECT (self)); + + if (pos != 0 && len != 0) + { + if (modifiers & CLUTTER_CONTROL_MASK) + { + if (pos == -1) + new_pos = clutter_text_move_word_backward (self, len); + else + new_pos = clutter_text_move_word_backward (self, pos); + } + else + { + if (pos == -1) + new_pos = len - 1; + else + new_pos = pos - 1; + } + + clutter_text_set_cursor_position (self, new_pos); + } + + if (!(priv->selectable && (modifiers & CLUTTER_SHIFT_MASK))) + clutter_text_clear_selection (self); + + g_object_thaw_notify (G_OBJECT (self)); + + return TRUE; +} + +static gboolean +clutter_text_real_move_right (ClutterText *self, + const gchar *action, + guint keyval, + ClutterModifierType modifiers) +{ + ClutterTextPrivate *priv = self->priv; + gint pos = priv->position; + gint len = clutter_text_buffer_get_length (get_buffer (self)); + gint new_pos = 0; + + g_object_freeze_notify (G_OBJECT (self)); + + if (pos != -1 && len !=0) + { + if (modifiers & CLUTTER_CONTROL_MASK) + { + if (pos != len) + new_pos = clutter_text_move_word_forward (self, pos); + } + else + { + if (pos != len) + new_pos = pos + 1; + } + + clutter_text_set_cursor_position (self, new_pos); + } + + if (!(priv->selectable && (modifiers & CLUTTER_SHIFT_MASK))) + clutter_text_clear_selection (self); + + g_object_thaw_notify (G_OBJECT (self)); + + return TRUE; +} + +static gboolean +clutter_text_real_move_up (ClutterText *self, + const gchar *action, + guint keyval, + ClutterModifierType modifiers) +{ + ClutterTextPrivate *priv = self->priv; + PangoLayoutLine *layout_line; + PangoLayout *layout; + gint line_no; + gint index_, trailing; + gint pos; + gint x; + const gchar *text; + + layout = clutter_text_get_layout (self); + text = clutter_text_buffer_get_text (get_buffer (self)); + + if (priv->position == 0) + index_ = 0; + else + index_ = offset_to_bytes (text, priv->position); + + pango_layout_index_to_line_x (layout, index_, + 0, + &line_no, &x); + + line_no -= 1; + if (line_no < 0) + return FALSE; + + if (priv->x_pos != -1) + x = priv->x_pos; + + layout_line = pango_layout_get_line_readonly (layout, line_no); + if (!layout_line) + return FALSE; + + pango_layout_line_x_to_index (layout_line, x, &index_, &trailing); + + g_object_freeze_notify (G_OBJECT (self)); + + pos = bytes_to_offset (text, index_); + clutter_text_set_cursor_position (self, pos + trailing); + + /* Store the target x position to avoid drifting left and right when + moving the cursor up and down */ + priv->x_pos = x; + + if (!(priv->selectable && (modifiers & CLUTTER_SHIFT_MASK))) + clutter_text_clear_selection (self); + + g_object_thaw_notify (G_OBJECT (self)); + + return TRUE; +} + +static gboolean +clutter_text_real_move_down (ClutterText *self, + const gchar *action, + guint keyval, + ClutterModifierType modifiers) +{ + ClutterTextPrivate *priv = self->priv; + PangoLayoutLine *layout_line; + PangoLayout *layout; + gint line_no; + gint index_, trailing; + gint x; + gint pos; + const gchar *text; + + layout = clutter_text_get_layout (self); + text = clutter_text_buffer_get_text (get_buffer (self)); + + if (priv->position == 0) + index_ = 0; + else + index_ = offset_to_bytes (text, priv->position); + + pango_layout_index_to_line_x (layout, index_, + 0, + &line_no, &x); + + if (priv->x_pos != -1) + x = priv->x_pos; + + layout_line = pango_layout_get_line_readonly (layout, line_no + 1); + if (!layout_line) + return FALSE; + + pango_layout_line_x_to_index (layout_line, x, &index_, &trailing); + + g_object_freeze_notify (G_OBJECT (self)); + + pos = bytes_to_offset (text, index_); + clutter_text_set_cursor_position (self, pos + trailing); + + /* Store the target x position to avoid drifting left and right when + moving the cursor up and down */ + priv->x_pos = x; + + if (!(priv->selectable && (modifiers & CLUTTER_SHIFT_MASK))) + clutter_text_clear_selection (self); + + g_object_thaw_notify (G_OBJECT (self)); + + return TRUE; +} + +static gboolean +clutter_text_real_line_start (ClutterText *self, + const gchar *action, + guint keyval, + ClutterModifierType modifiers) +{ + ClutterTextPrivate *priv = self->priv; + gint position; + + g_object_freeze_notify (G_OBJECT (self)); + + position = clutter_text_move_line_start (self, priv->position); + clutter_text_set_cursor_position (self, position); + + if (!(priv->selectable && (modifiers & CLUTTER_SHIFT_MASK))) + clutter_text_clear_selection (self); + + g_object_thaw_notify (G_OBJECT (self)); + + return TRUE; +} + +static gboolean +clutter_text_real_line_end (ClutterText *self, + const gchar *action, + guint keyval, + ClutterModifierType modifiers) +{ + ClutterTextPrivate *priv = self->priv; + gint position; + + g_object_freeze_notify (G_OBJECT (self)); + + position = clutter_text_move_line_end (self, priv->position); + clutter_text_set_cursor_position (self, position); + + if (!(priv->selectable && (modifiers & CLUTTER_SHIFT_MASK))) + clutter_text_clear_selection (self); + + g_object_thaw_notify (G_OBJECT (self)); + + return TRUE; +} + +static gboolean +clutter_text_real_select_all (ClutterText *self, + const gchar *action, + guint keyval, + ClutterModifierType modifiers) +{ + guint n_chars = clutter_text_buffer_get_length (get_buffer (self)); + clutter_text_set_positions (self, 0, n_chars); + + return TRUE; +} + +static gboolean +clutter_text_real_del_next (ClutterText *self, + const gchar *action, + guint keyval, + ClutterModifierType modifiers) +{ + ClutterTextPrivate *priv = self->priv; + gint pos; + gint len; + + if (clutter_text_delete_selection (self)) + return TRUE; + + pos = priv->position; + len = clutter_text_buffer_get_length (get_buffer (self)); + + if (len && pos != -1 && pos < len) + clutter_text_delete_text (self, pos, pos + 1); + + return TRUE; +} + +static gboolean +clutter_text_real_del_word_next (ClutterText *self, + const gchar *action, + guint keyval, + ClutterModifierType modifiers) +{ + ClutterTextPrivate *priv = self->priv; + gint pos; + gint len; + + pos = priv->position; + len = clutter_text_buffer_get_length (get_buffer (self)); + + if (len && pos != -1 && pos < len) + { + gint end; + + end = clutter_text_move_word_forward (self, pos); + clutter_text_delete_text (self, pos, end); + + if (priv->selection_bound >= end) + { + gint new_bound; + + new_bound = priv->selection_bound - (end - pos); + clutter_text_set_selection_bound (self, new_bound); + } + else if (priv->selection_bound > pos) + { + clutter_text_set_selection_bound (self, pos); + } + } + + return TRUE; +} + +static gboolean +clutter_text_real_del_prev (ClutterText *self, + const gchar *action, + guint keyval, + ClutterModifierType modifiers) +{ + ClutterTextPrivate *priv = self->priv; + gint pos; + gint len; + + if (clutter_text_delete_selection (self)) + return TRUE; + + pos = priv->position; + len = clutter_text_buffer_get_length (get_buffer (self)); + + if (pos != 0 && len != 0) + { + if (pos == -1) + { + clutter_text_delete_text (self, len - 1, len); + + clutter_text_set_positions (self, -1, -1); + } + else + { + clutter_text_delete_text (self, pos - 1, pos); + + clutter_text_set_positions (self, pos - 1, pos - 1); + } + } + + return TRUE; +} + +static gboolean +clutter_text_real_del_word_prev (ClutterText *self, + const gchar *action, + guint keyval, + ClutterModifierType modifiers) +{ + ClutterTextPrivate *priv = self->priv; + gint pos; + gint len; + + pos = priv->position; + len = clutter_text_buffer_get_length (get_buffer (self)); + + if (pos != 0 && len != 0) + { + gint new_pos; + + if (pos == -1) + { + new_pos = clutter_text_move_word_backward (self, len); + clutter_text_delete_text (self, new_pos, len); + + clutter_text_set_positions (self, -1, -1); + } + else + { + new_pos = clutter_text_move_word_backward (self, pos); + clutter_text_delete_text (self, new_pos, pos); + + clutter_text_set_cursor_position (self, new_pos); + if (priv->selection_bound >= pos) + { + gint new_bound; + + new_bound = priv->selection_bound - (pos - new_pos); + clutter_text_set_selection_bound (self, new_bound); + } + else if (priv->selection_bound >= new_pos) + { + clutter_text_set_selection_bound (self, new_pos); + } + } + } + + return TRUE; +} + +static gboolean +clutter_text_real_activate (ClutterText *self, + const gchar *action, + guint keyval, + ClutterModifierType modifiers) +{ + return clutter_text_activate (self); +} + +static inline void +clutter_text_add_move_binding (ClutterBindingPool *pool, + const gchar *action, + guint key_val, + ClutterModifierType additional_modifiers, + GCallback callback) +{ + clutter_binding_pool_install_action (pool, action, + key_val, + 0, + callback, + NULL, NULL); + clutter_binding_pool_install_action (pool, action, + key_val, + CLUTTER_SHIFT_MASK, + callback, + NULL, NULL); + + if (additional_modifiers != 0) + { + clutter_binding_pool_install_action (pool, action, + key_val, + additional_modifiers, + callback, + NULL, NULL); + clutter_binding_pool_install_action (pool, action, + key_val, + CLUTTER_SHIFT_MASK | + additional_modifiers, + callback, + NULL, NULL); + } +} + +static gboolean +clutter_text_parse_custom_node (ClutterScriptable *scriptable, + ClutterScript *script, + GValue *value, + const gchar *name, + JsonNode *node) +{ + if (strncmp (name, "font-description", 16) == 0) + { + g_value_init (value, G_TYPE_STRING); + g_value_set_string (value, json_node_get_string (node)); + + return TRUE; + } + + return parent_scriptable_iface->parse_custom_node (scriptable, script, + value, + name, + node); +} + +static void +clutter_text_set_color_internal (ClutterText *self, + GParamSpec *pspec, + const ClutterColor *color) +{ + ClutterTextPrivate *priv = CLUTTER_TEXT (self)->priv; + GParamSpec *other = NULL; + + switch (pspec->param_id) + { + case PROP_COLOR: + priv->text_color = *color; + break; + + case PROP_CURSOR_COLOR: + if (color) + { + priv->cursor_color = *color; + priv->cursor_color_set = TRUE; + } + else + priv->cursor_color_set = FALSE; + + other = obj_props[PROP_CURSOR_COLOR_SET]; + break; + + case PROP_SELECTION_COLOR: + if (color) + { + priv->selection_color = *color; + priv->selection_color_set = TRUE; + } + else + priv->selection_color_set = FALSE; + + other = obj_props[PROP_SELECTION_COLOR_SET]; + break; + + case PROP_SELECTED_TEXT_COLOR: + if (color) + { + priv->selected_text_color = *color; + priv->selected_text_color_set = TRUE; + } + else + priv->selected_text_color_set = FALSE; + + other = obj_props[PROP_SELECTED_TEXT_COLOR_SET]; + break; + + default: + g_assert_not_reached (); + break; + } + + clutter_text_queue_redraw (CLUTTER_ACTOR (self)); + g_object_notify_by_pspec (G_OBJECT (self), pspec); + if (other) + g_object_notify_by_pspec (G_OBJECT (self), other); +} + +static void +clutter_text_set_color_animated (ClutterText *self, + GParamSpec *pspec, + const ClutterColor *color) +{ + ClutterActor *actor = CLUTTER_ACTOR (self); + ClutterTextPrivate *priv = self->priv; + const ClutterAnimationInfo *info; + ClutterTransition *transition; + + info = _clutter_actor_get_animation_info (actor); + transition = clutter_actor_get_transition (actor, pspec->name); + + /* jump to the end if there is no easing state, or if the easing + * state has a duration of 0 msecs + */ + if (info->cur_state == NULL || + info->cur_state->easing_duration == 0) + { + /* ensure that we remove any currently running transition */ + if (transition != NULL) + { + clutter_actor_remove_transition (actor, pspec->name); + transition = NULL; + } + + clutter_text_set_color_internal (self, pspec, color); + + return; + } + + if (transition == NULL) + { + transition = clutter_property_transition_new (pspec->name); + clutter_transition_set_animatable (transition, + CLUTTER_ANIMATABLE (self)); + clutter_transition_set_remove_on_complete (transition, TRUE); + + /* delay only makes sense if the transition has just been created */ + clutter_timeline_set_delay (CLUTTER_TIMELINE (transition), + info->cur_state->easing_delay); + + clutter_actor_add_transition (actor, pspec->name, transition); + + /* the actor now owns the transition */ + g_object_unref (transition); + } + + /* if a transition already exist, update its bounds */ + switch (pspec->param_id) + { + case PROP_COLOR: + clutter_transition_set_from (transition, CLUTTER_TYPE_COLOR, + &priv->text_color); + break; + + case PROP_CURSOR_COLOR: + clutter_transition_set_from (transition, CLUTTER_TYPE_COLOR, + &priv->cursor_color); + break; + + case PROP_SELECTION_COLOR: + clutter_transition_set_from (transition, CLUTTER_TYPE_COLOR, + &priv->selection_color); + break; + + case PROP_SELECTED_TEXT_COLOR: + clutter_transition_set_from (transition, CLUTTER_TYPE_COLOR, + &priv->selected_text_color); + break; + + default: + g_assert_not_reached (); + } + + clutter_transition_set_to (transition, CLUTTER_TYPE_COLOR, color); + + /* always use the current easing state */ + clutter_timeline_set_duration (CLUTTER_TIMELINE (transition), + info->cur_state->easing_duration); + clutter_timeline_set_progress_mode (CLUTTER_TIMELINE (transition), + info->cur_state->easing_mode); + + /* ensure that we start from the beginning */ + clutter_timeline_rewind (CLUTTER_TIMELINE (transition)); + clutter_timeline_start (CLUTTER_TIMELINE (transition)); +} + +static void +clutter_text_set_custom_property (ClutterScriptable *scriptable, + ClutterScript *script, + const gchar *name, + const GValue *value) +{ + if (strncmp (name, "font-description", 16) == 0) + { + g_assert (G_VALUE_HOLDS (value, G_TYPE_STRING)); + if (g_value_get_string (value) != NULL) + clutter_text_set_font_name (CLUTTER_TEXT (scriptable), + g_value_get_string (value)); + } + else + parent_scriptable_iface->set_custom_property (scriptable, script, + name, + value); +} + +static void +clutter_scriptable_iface_init (ClutterScriptableIface *iface) +{ + parent_scriptable_iface = g_type_interface_peek_parent (iface); + + iface->parse_custom_node = clutter_text_parse_custom_node; + iface->set_custom_property = clutter_text_set_custom_property; +} + +static void +clutter_text_set_final_state (ClutterAnimatable *animatable, + const char *property_name, + const GValue *value) +{ + if (strcmp (property_name, "color") == 0) + { + const ClutterColor *color = clutter_value_get_color (value); + clutter_text_set_color_internal (CLUTTER_TEXT (animatable), + obj_props[PROP_COLOR], color); + } + else if (strcmp (property_name, "cursor-color") == 0) + { + const ClutterColor *color = clutter_value_get_color (value); + clutter_text_set_color_internal (CLUTTER_TEXT (animatable), + obj_props[PROP_CURSOR_COLOR], + color); + } + else if (strcmp (property_name, "selected-text-color") == 0) + { + const ClutterColor *color = clutter_value_get_color (value); + clutter_text_set_color_internal (CLUTTER_TEXT (animatable), + obj_props[PROP_SELECTED_TEXT_COLOR], + color); + } + else if (strcmp (property_name, "selection-color") == 0) + { + const ClutterColor *color = clutter_value_get_color (value); + clutter_text_set_color_internal (CLUTTER_TEXT (animatable), + obj_props[PROP_SELECTION_COLOR], + color); + } + else + parent_animatable_iface->set_final_state (animatable, property_name, value); +} + +static void +clutter_animatable_iface_init (ClutterAnimatableIface *iface) +{ + parent_animatable_iface = g_type_interface_peek_parent (iface); + + iface->set_final_state = clutter_text_set_final_state; +} + +static void +clutter_text_class_init (ClutterTextClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + ClutterBindingPool *binding_pool; + GParamSpec *pspec; + + gobject_class->set_property = clutter_text_set_property; + gobject_class->get_property = clutter_text_get_property; + gobject_class->dispose = clutter_text_dispose; + gobject_class->finalize = clutter_text_finalize; + + actor_class->paint = clutter_text_paint; + actor_class->get_paint_volume = clutter_text_get_paint_volume; + actor_class->get_preferred_width = clutter_text_get_preferred_width; + actor_class->get_preferred_height = clutter_text_get_preferred_height; + actor_class->allocate = clutter_text_allocate; + actor_class->key_press_event = clutter_text_key_press; + actor_class->button_press_event = clutter_text_button_press; + actor_class->button_release_event = clutter_text_button_release; + actor_class->motion_event = clutter_text_motion; + actor_class->touch_event = clutter_text_touch_event; + actor_class->key_focus_in = clutter_text_key_focus_in; + actor_class->key_focus_out = clutter_text_key_focus_out; + actor_class->has_overlaps = clutter_text_has_overlaps; + + /** + * ClutterText:buffer: + * + * The buffer which stores the text for this #ClutterText. + * + * If set to %NULL, a default buffer will be created. + * + * Since: 1.8 + */ + pspec = g_param_spec_object ("buffer", + P_("Buffer"), + P_("The buffer for the text"), + CLUTTER_TYPE_TEXT_BUFFER, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_BUFFER] = pspec; + g_object_class_install_property (gobject_class, PROP_BUFFER, pspec); + + /** + * ClutterText:font-name: + * + * The font to be used by the #ClutterText, as a string + * that can be parsed by pango_font_description_from_string(). + * + * If set to %NULL, the default system font will be used instead. + * + * Since: 1.0 + */ + pspec = g_param_spec_string ("font-name", + P_("Font Name"), + P_("The font to be used by the text"), + NULL, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_FONT_NAME] = pspec; + g_object_class_install_property (gobject_class, PROP_FONT_NAME, pspec); + + /** + * ClutterText:font-description: + * + * The #PangoFontDescription that should be used by the #ClutterText + * + * If you have a string describing the font then you should look at + * #ClutterText:font-name instead + * + * Since: 1.2 + */ + pspec = g_param_spec_boxed ("font-description", + P_("Font Description"), + P_("The font description to be used"), + PANGO_TYPE_FONT_DESCRIPTION, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_FONT_DESCRIPTION] = pspec; + g_object_class_install_property (gobject_class, + PROP_FONT_DESCRIPTION, + pspec); + + /** + * ClutterText:text: + * + * The text to render inside the actor. + * + * Since: 1.0 + */ + pspec = g_param_spec_string ("text", + P_("Text"), + P_("The text to render"), + "", + CLUTTER_PARAM_READWRITE); + obj_props[PROP_TEXT] = pspec; + g_object_class_install_property (gobject_class, PROP_TEXT, pspec); + + /** + * ClutterText:color: + * + * The color used to render the text. + * + * Since: 1.0 + */ + pspec = clutter_param_spec_color ("color", + P_("Font Color"), + P_("Color of the font used by the text"), + &default_text_color, + CLUTTER_PARAM_READWRITE | + CLUTTER_PARAM_ANIMATABLE); + obj_props[PROP_COLOR] = pspec; + g_object_class_install_property (gobject_class, PROP_COLOR, pspec); + + /** + * ClutterText:editable: + * + * Whether key events delivered to the actor causes editing. + * + * Since: 1.0 + */ + pspec = g_param_spec_boolean ("editable", + P_("Editable"), + P_("Whether the text is editable"), + FALSE, + G_PARAM_READWRITE); + obj_props[PROP_EDITABLE] = pspec; + g_object_class_install_property (gobject_class, PROP_EDITABLE, pspec); + + /** + * ClutterText:selectable: + * + * Whether it is possible to select text, either using the pointer + * or the keyboard. + * + * This property depends on the #ClutterActor:reactive property being + * set to %TRUE. + * + * Since: 1.0 + */ + pspec = g_param_spec_boolean ("selectable", + P_("Selectable"), + P_("Whether the text is selectable"), + TRUE, + G_PARAM_READWRITE); + obj_props[PROP_SELECTABLE] = pspec; + g_object_class_install_property (gobject_class, PROP_SELECTABLE, pspec); + + /** + * ClutterText:activatable: + * + * Toggles whether return invokes the activate signal or not. + * + * Since: 1.0 + */ + pspec = g_param_spec_boolean ("activatable", + P_("Activatable"), + P_("Whether pressing return causes the activate signal to be emitted"), + TRUE, + G_PARAM_READWRITE); + obj_props[PROP_ACTIVATABLE] = pspec; + g_object_class_install_property (gobject_class, PROP_ACTIVATABLE, pspec); + + /** + * ClutterText:cursor-visible: + * + * Whether the input cursor is visible or not. + * + * The cursor will only be visible if this property and either + * the #ClutterText:editable or the #ClutterText:selectable properties + * are set to %TRUE. + * + * Since: 1.0 + */ + pspec = g_param_spec_boolean ("cursor-visible", + P_("Cursor Visible"), + P_("Whether the input cursor is visible"), + TRUE, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_CURSOR_VISIBLE] = pspec; + g_object_class_install_property (gobject_class, PROP_CURSOR_VISIBLE, pspec); + + /** + * ClutterText:cursor-color: + * + * The color of the cursor. + * + * Since: 1.0 + */ + pspec = clutter_param_spec_color ("cursor-color", + P_("Cursor Color"), + P_("Cursor Color"), + &default_cursor_color, + CLUTTER_PARAM_READWRITE | + CLUTTER_PARAM_ANIMATABLE); + obj_props[PROP_CURSOR_COLOR] = pspec; + g_object_class_install_property (gobject_class, PROP_CURSOR_COLOR, pspec); + + /** + * ClutterText:cursor-color-set: + * + * Will be set to %TRUE if #ClutterText:cursor-color has been set. + * + * Since: 1.0 + */ + pspec = g_param_spec_boolean ("cursor-color-set", + P_("Cursor Color Set"), + P_("Whether the cursor color has been set"), + FALSE, + CLUTTER_PARAM_READABLE); + obj_props[PROP_CURSOR_COLOR_SET] = pspec; + g_object_class_install_property (gobject_class, PROP_CURSOR_COLOR_SET, pspec); + + /** + * ClutterText:cursor-size: + * + * The size of the cursor, in pixels. If set to -1 the size used will + * be the default cursor size of 2 pixels. + * + * Since: 1.0 + */ + pspec = g_param_spec_int ("cursor-size", + P_("Cursor Size"), + P_("The width of the cursor, in pixels"), + -1, G_MAXINT, DEFAULT_CURSOR_SIZE, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_CURSOR_SIZE] = pspec; + g_object_class_install_property (gobject_class, PROP_CURSOR_SIZE, pspec); + + /** + * ClutterText:position: + * + * The current input cursor position. -1 is taken to be the end of the text + * + * Since: 1.0 + * + * Deprecated: 1.12: Use ClutterText:cursor-position instead. + */ + pspec = g_param_spec_int ("position", + P_("Cursor Position"), + P_("The cursor position"), + -1, G_MAXINT, + -1, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + G_PARAM_DEPRECATED); + obj_props[PROP_POSITION] = pspec; + g_object_class_install_property (gobject_class, PROP_POSITION, pspec); + + /** + * ClutterText:cursor-position: + * + * The current input cursor position. -1 is taken to be the end of the text + * + * Since: 1.12 + */ + pspec = g_param_spec_int ("cursor-position", + P_("Cursor Position"), + P_("The cursor position"), + -1, G_MAXINT, + -1, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_CURSOR_POSITION] = pspec; + g_object_class_install_property (gobject_class, PROP_CURSOR_POSITION, pspec); + + /** + * ClutterText:selection-bound: + * + * The current input cursor position. -1 is taken to be the end of the text + * + * Since: 1.0 + */ + pspec = g_param_spec_int ("selection-bound", + P_("Selection-bound"), + P_("The cursor position of the other end of the selection"), + -1, G_MAXINT, + -1, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_SELECTION_BOUND] = pspec; + g_object_class_install_property (gobject_class, PROP_SELECTION_BOUND, pspec); + + /** + * ClutterText:selection-color: + * + * The color of the selection. + * + * Since: 1.0 + */ + pspec = clutter_param_spec_color ("selection-color", + P_("Selection Color"), + P_("Selection Color"), + &default_selection_color, + CLUTTER_PARAM_READWRITE | + CLUTTER_PARAM_ANIMATABLE); + obj_props[PROP_SELECTION_COLOR] = pspec; + g_object_class_install_property (gobject_class, PROP_SELECTION_COLOR, pspec); + + /** + * ClutterText:selection-color-set: + * + * Will be set to %TRUE if #ClutterText:selection-color has been set. + * + * Since: 1.0 + */ + pspec = g_param_spec_boolean ("selection-color-set", + P_("Selection Color Set"), + P_("Whether the selection color has been set"), + FALSE, + CLUTTER_PARAM_READABLE); + obj_props[PROP_SELECTION_COLOR_SET] = pspec; + g_object_class_install_property (gobject_class, PROP_SELECTION_COLOR_SET, pspec); + + /** + * ClutterText:attributes: + * + * A list of #PangoStyleAttributes to be applied to the + * contents of the #ClutterText actor. + * + * Since: 1.0 + */ + pspec = g_param_spec_boxed ("attributes", + P_("Attributes"), + P_("A list of style attributes to apply to the contents of the actor"), + PANGO_TYPE_ATTR_LIST, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_ATTRIBUTES] = pspec; + g_object_class_install_property (gobject_class, PROP_ATTRIBUTES, pspec); + + /** + * ClutterText:use-markup: + * + * Whether the text includes Pango markup. + * + * For more informations about the Pango markup format, see + * pango_layout_set_markup() in the Pango documentation. + * + * It is not possible to round-trip this property between + * %TRUE and %FALSE. Once a string with markup has been set on + * a #ClutterText actor with :use-markup set to %TRUE, the markup + * is stripped from the string. + * + * Since: 1.0 + */ + pspec = g_param_spec_boolean ("use-markup", + P_("Use markup"), + P_("Whether or not the text includes Pango markup"), + FALSE, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_USE_MARKUP] = pspec; + g_object_class_install_property (gobject_class, PROP_USE_MARKUP, pspec); + + /** + * ClutterText:line-wrap: + * + * Whether to wrap the lines of #ClutterText:text if the contents + * exceed the available allocation. The wrapping strategy is + * controlled by the #ClutterText:line-wrap-mode property. + * + * Since: 1.0 + */ + pspec = g_param_spec_boolean ("line-wrap", + P_("Line wrap"), + P_("If set, wrap the lines if the text becomes too wide"), + FALSE, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_LINE_WRAP] = pspec; + g_object_class_install_property (gobject_class, PROP_LINE_WRAP, pspec); + + /** + * ClutterText:line-wrap-mode: + * + * If #ClutterText:line-wrap is set to %TRUE, this property will + * control how the text is wrapped. + * + * Since: 1.0 + */ + pspec = g_param_spec_enum ("line-wrap-mode", + P_("Line wrap mode"), + P_("Control how line-wrapping is done"), + PANGO_TYPE_WRAP_MODE, + PANGO_WRAP_WORD, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_LINE_WRAP_MODE] = pspec; + g_object_class_install_property (gobject_class, PROP_LINE_WRAP_MODE, pspec); + + /** + * ClutterText:ellipsize: + * + * The preferred place to ellipsize the contents of the #ClutterText actor + * + * Since: 1.0 + */ + pspec = g_param_spec_enum ("ellipsize", + P_("Ellipsize"), + P_("The preferred place to ellipsize the string"), + PANGO_TYPE_ELLIPSIZE_MODE, + PANGO_ELLIPSIZE_NONE, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_ELLIPSIZE] = pspec; + g_object_class_install_property (gobject_class, PROP_ELLIPSIZE, pspec); + + /** + * ClutterText:line-alignment: + * + * The preferred alignment for the text. This property controls + * the alignment of multi-line paragraphs. + * + * Since: 1.0 + */ + pspec = g_param_spec_enum ("line-alignment", + P_("Line Alignment"), + P_("The preferred alignment for the string, for multi-line text"), + PANGO_TYPE_ALIGNMENT, + PANGO_ALIGN_LEFT, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_LINE_ALIGNMENT] = pspec; + g_object_class_install_property (gobject_class, PROP_LINE_ALIGNMENT, pspec); + + /** + * ClutterText:justify: + * + * Whether the contents of the #ClutterText should be justified + * on both margins. + * + * Since: 1.0 + */ + pspec = g_param_spec_boolean ("justify", + P_("Justify"), + P_("Whether the text should be justified"), + FALSE, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_JUSTIFY] = pspec; + g_object_class_install_property (gobject_class, PROP_JUSTIFY, pspec); + + /** + * ClutterText:password-char: + * + * If non-zero, the character that should be used in place of + * the actual text in a password text actor. + * + * Since: 1.0 + */ + pspec = g_param_spec_unichar ("password-char", + P_("Password Character"), + P_("If non-zero, use this character to display the actor's contents"), + 0, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_PASSWORD_CHAR] = pspec; + g_object_class_install_property (gobject_class, PROP_PASSWORD_CHAR, pspec); + + /** + * ClutterText:max-length: + * + * The maximum length of the contents of the #ClutterText actor. + * + * Since: 1.0 + */ + pspec = g_param_spec_int ("max-length", + P_("Max Length"), + P_("Maximum length of the text inside the actor"), + -1, G_MAXINT, 0, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_MAX_LENGTH] = pspec; + g_object_class_install_property (gobject_class, PROP_MAX_LENGTH, pspec); + + /** + * ClutterText:single-line-mode: + * + * Whether the #ClutterText actor should be in single line mode + * or not. A single line #ClutterText actor will only contain a + * single line of text, scrolling it in case its length is bigger + * than the allocated size. + * + * Setting this property will also set the #ClutterText:activatable + * property as a side-effect. + * + * The #ClutterText:single-line-mode property is used only if the + * #ClutterText:editable property is set to %TRUE. + * + * Since: 1.0 + */ + pspec = g_param_spec_boolean ("single-line-mode", + P_("Single Line Mode"), + P_("Whether the text should be a single line"), + FALSE, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_SINGLE_LINE_MODE] = pspec; + g_object_class_install_property (gobject_class, PROP_SINGLE_LINE_MODE, pspec); + + /** + * ClutterText:selected-text-color: + * + * The color of selected text. + * + * Since: 1.8 + */ + pspec = clutter_param_spec_color ("selected-text-color", + P_("Selected Text Color"), + P_("Selected Text Color"), + &default_selected_text_color, + CLUTTER_PARAM_READWRITE | + CLUTTER_PARAM_ANIMATABLE); + obj_props[PROP_SELECTED_TEXT_COLOR] = pspec; + g_object_class_install_property (gobject_class, PROP_SELECTED_TEXT_COLOR, pspec); + + /** + * ClutterText:selected-text-color-set: + * + * Will be set to %TRUE if #ClutterText:selected-text-color has been set. + * + * Since: 1.8 + */ + pspec = g_param_spec_boolean ("selected-text-color-set", + P_("Selected Text Color Set"), + P_("Whether the selected text color has been set"), + FALSE, + CLUTTER_PARAM_READABLE); + obj_props[PROP_SELECTED_TEXT_COLOR_SET] = pspec; + g_object_class_install_property (gobject_class, PROP_SELECTED_TEXT_COLOR_SET, pspec); + + /** + * ClutterText::text-changed: + * @self: the #ClutterText that emitted the signal + * + * The ::text-changed signal is emitted after @actor's text changes + * + * Since: 1.0 + */ + text_signals[TEXT_CHANGED] = + g_signal_new (I_("text-changed"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterTextClass, text_changed), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * ClutterText::insert-text: + * @self: the #ClutterText that emitted the signal + * @new_text: the new text to insert + * @new_text_length: the length of the new text, in bytes, or -1 if + * new_text is nul-terminated + * @position: the position, in characters, at which to insert the + * new text. this is an in-out parameter. After the signal + * emission is finished, it should point after the newly + * inserted text. + * + * This signal is emitted when text is inserted into the actor by + * the user. It is emitted before @self text changes. + * + * Since: 1.2 + */ + text_signals[INSERT_TEXT] = + g_signal_new (I_("insert-text"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, + NULL, NULL, + _clutter_marshal_VOID__STRING_INT_POINTER, + G_TYPE_NONE, 3, + G_TYPE_STRING, + G_TYPE_INT, + G_TYPE_POINTER); + + /** + * ClutterText::delete-text: + * @self: the #ClutterText that emitted the signal + * @start_pos: the starting position + * @end_pos: the end position + * + * This signal is emitted when text is deleted from the actor by + * the user. It is emitted before @self text changes. + * + * Since: 1.2 + */ + text_signals[DELETE_TEXT] = + g_signal_new (I_("delete-text"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, + NULL, NULL, + _clutter_marshal_VOID__INT_INT, + G_TYPE_NONE, 2, + G_TYPE_INT, + G_TYPE_INT); + + /** + * ClutterText::cursor-event: + * @self: the #ClutterText that emitted the signal + * @geometry: the coordinates of the cursor + * + * The ::cursor-event signal is emitted whenever the cursor position + * changes inside a #ClutterText actor. Inside @geometry it is stored + * the current position and size of the cursor, relative to the actor + * itself. + * + * Since: 1.0 + * + * Deprecated: 1.16: Use the #ClutterText::cursor-changed signal instead + */ + text_signals[CURSOR_EVENT] = + g_signal_new (I_("cursor-event"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_DEPRECATED, + G_STRUCT_OFFSET (ClutterTextClass, cursor_event), + NULL, NULL, + _clutter_marshal_VOID__BOXED, + G_TYPE_NONE, 1, + CLUTTER_TYPE_GEOMETRY | G_SIGNAL_TYPE_STATIC_SCOPE); + + /** + * ClutterText::cursor-changed: + * @self: the #ClutterText that emitted the signal + * + * The ::cursor-changed signal is emitted whenever the cursor + * position or size changes. + * + * Since: 1.16 + */ + text_signals[CURSOR_CHANGED] = + g_signal_new (I_("cursor-changed"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterTextClass, cursor_changed), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * ClutterText::activate: + * @self: the #ClutterText that emitted the signal + * + * The ::activate signal is emitted each time the actor is 'activated' + * by the user, normally by pressing the 'Enter' key. The signal is + * emitted only if #ClutterText:activatable is set to %TRUE. + * + * Since: 1.0 + */ + text_signals[ACTIVATE] = + g_signal_new (I_("activate"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterTextClass, activate), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + binding_pool = clutter_binding_pool_get_for_class (klass); + + clutter_text_add_move_binding (binding_pool, "move-left", + CLUTTER_KEY_Left, CLUTTER_CONTROL_MASK, + G_CALLBACK (clutter_text_real_move_left)); + clutter_text_add_move_binding (binding_pool, "move-left", + CLUTTER_KEY_KP_Left, CLUTTER_CONTROL_MASK, + G_CALLBACK (clutter_text_real_move_left)); + clutter_text_add_move_binding (binding_pool, "move-right", + CLUTTER_KEY_Right, CLUTTER_CONTROL_MASK, + G_CALLBACK (clutter_text_real_move_right)); + clutter_text_add_move_binding (binding_pool, "move-right", + CLUTTER_KEY_KP_Right, CLUTTER_CONTROL_MASK, + G_CALLBACK (clutter_text_real_move_right)); + clutter_text_add_move_binding (binding_pool, "move-up", + CLUTTER_KEY_Up, 0, + G_CALLBACK (clutter_text_real_move_up)); + clutter_text_add_move_binding (binding_pool, "move-up", + CLUTTER_KEY_KP_Up, 0, + G_CALLBACK (clutter_text_real_move_up)); + clutter_text_add_move_binding (binding_pool, "move-down", + CLUTTER_KEY_Down, 0, + G_CALLBACK (clutter_text_real_move_down)); + clutter_text_add_move_binding (binding_pool, "move-down", + CLUTTER_KEY_KP_Down, 0, + G_CALLBACK (clutter_text_real_move_down)); + + clutter_text_add_move_binding (binding_pool, "line-start", + CLUTTER_KEY_Home, 0, + G_CALLBACK (clutter_text_real_line_start)); + clutter_text_add_move_binding (binding_pool, "line-start", + CLUTTER_KEY_KP_Home, 0, + G_CALLBACK (clutter_text_real_line_start)); + clutter_text_add_move_binding (binding_pool, "line-start", + CLUTTER_KEY_Begin, 0, + G_CALLBACK (clutter_text_real_line_start)); + clutter_text_add_move_binding (binding_pool, "line-end", + CLUTTER_KEY_End, 0, + G_CALLBACK (clutter_text_real_line_end)); + clutter_text_add_move_binding (binding_pool, "line-end", + CLUTTER_KEY_KP_End, 0, + G_CALLBACK (clutter_text_real_line_end)); + + clutter_binding_pool_install_action (binding_pool, "select-all", + CLUTTER_KEY_a, CLUTTER_CONTROL_MASK, + G_CALLBACK (clutter_text_real_select_all), + NULL, NULL); + clutter_binding_pool_install_action (binding_pool, "select-all", + CLUTTER_KEY_A, CLUTTER_CONTROL_MASK, + G_CALLBACK (clutter_text_real_select_all), + NULL, NULL); + + clutter_binding_pool_install_action (binding_pool, "delete-next", + CLUTTER_KEY_Delete, 0, + G_CALLBACK (clutter_text_real_del_next), + NULL, NULL); + clutter_binding_pool_install_action (binding_pool, "delete-next", + CLUTTER_KEY_Delete, CLUTTER_CONTROL_MASK, + G_CALLBACK (clutter_text_real_del_word_next), + NULL, NULL); + clutter_binding_pool_install_action (binding_pool, "delete-next", + CLUTTER_KEY_KP_Delete, 0, + G_CALLBACK (clutter_text_real_del_next), + NULL, NULL); + clutter_binding_pool_install_action (binding_pool, "delete-next", + CLUTTER_KEY_KP_Delete, CLUTTER_CONTROL_MASK, + G_CALLBACK (clutter_text_real_del_word_next), + NULL, NULL); + clutter_binding_pool_install_action (binding_pool, "delete-prev", + CLUTTER_KEY_BackSpace, 0, + G_CALLBACK (clutter_text_real_del_prev), + NULL, NULL); + clutter_binding_pool_install_action (binding_pool, "delete-prev", + CLUTTER_KEY_BackSpace, CLUTTER_SHIFT_MASK, + G_CALLBACK (clutter_text_real_del_prev), + NULL, NULL); + clutter_binding_pool_install_action (binding_pool, "delete-prev", + CLUTTER_KEY_BackSpace, CLUTTER_CONTROL_MASK, + G_CALLBACK (clutter_text_real_del_word_prev), + NULL, NULL); + + clutter_binding_pool_install_action (binding_pool, "activate", + CLUTTER_KEY_Return, 0, + G_CALLBACK (clutter_text_real_activate), + NULL, NULL); + clutter_binding_pool_install_action (binding_pool, "activate", + CLUTTER_KEY_KP_Enter, 0, + G_CALLBACK (clutter_text_real_activate), + NULL, NULL); + clutter_binding_pool_install_action (binding_pool, "activate", + CLUTTER_KEY_ISO_Enter, 0, + G_CALLBACK (clutter_text_real_activate), + NULL, NULL); +} + +static void +clutter_text_init (ClutterText *self) +{ + ClutterSettings *settings; + ClutterTextPrivate *priv; + gchar *font_name; + int i, password_hint_time; + + self->priv = priv = clutter_text_get_instance_private (self); + + priv->alignment = PANGO_ALIGN_LEFT; + priv->wrap = FALSE; + priv->wrap_mode = PANGO_WRAP_WORD; + priv->ellipsize = PANGO_ELLIPSIZE_NONE; + priv->use_underline = FALSE; + priv->use_markup = FALSE; + priv->justify = FALSE; + + for (i = 0; i < N_CACHED_LAYOUTS; i++) + priv->cached_layouts[i].layout = NULL; + + /* default to "" so that clutter_text_get_text() will + * return a valid string and we can safely call strlen() + * or strcmp() on it + */ + priv->buffer = NULL; + + priv->text_color = default_text_color; + priv->cursor_color = default_cursor_color; + priv->selection_color = default_selection_color; + priv->selected_text_color = default_selected_text_color; + + /* get the default font name from the context; we don't use + * set_font_description() here because we are initializing + * the Text and we don't need notifications and sanity checks + */ + settings = clutter_settings_get_default (); + g_object_get (settings, + "font-name", &font_name, + "password-hint-time", &password_hint_time, + NULL); + + priv->font_name = font_name; /* font_name is allocated */ + priv->font_desc = pango_font_description_from_string (font_name); + priv->is_default_font = TRUE; + + priv->position = -1; + priv->selection_bound = -1; + + priv->x_pos = -1; + priv->cursor_visible = TRUE; + priv->editable = FALSE; + priv->selectable = TRUE; + + priv->selection_color_set = FALSE; + priv->cursor_color_set = FALSE; + priv->selected_text_color_set = FALSE; + priv->preedit_set = FALSE; + + priv->password_char = 0; + priv->show_password_hint = password_hint_time > 0; + priv->password_hint_timeout = password_hint_time; + + priv->text_y = 0; + + priv->cursor_size = DEFAULT_CURSOR_SIZE; + + priv->settings_changed_id = + g_signal_connect_swapped (clutter_get_default_backend (), + "settings-changed", + G_CALLBACK (clutter_text_settings_changed_cb), + self); + + priv->direction_changed_id = + g_signal_connect (self, "notify::text-direction", + G_CALLBACK (clutter_text_direction_changed_cb), + NULL); +} + +/** + * clutter_text_new: + * + * Creates a new #ClutterText actor. This actor can be used to + * display and edit text. + * + * Return value: the newly created #ClutterText actor + * + * Since: 1.0 + */ +ClutterActor * +clutter_text_new (void) +{ + return g_object_new (CLUTTER_TYPE_TEXT, NULL); +} + +/** + * clutter_text_new_full: + * @font_name: a string with a font description + * @text: the contents of the actor + * @color: the color to be used to render @text + * + * Creates a new #ClutterText actor, using @font_name as the font + * description; @text will be used to set the contents of the actor; + * and @color will be used as the color to render @text. + * + * This function is equivalent to calling clutter_text_new(), + * clutter_text_set_font_name(), clutter_text_set_text() and + * clutter_text_set_color(). + * + * Return value: the newly created #ClutterText actor + * + * Since: 1.0 + */ +ClutterActor * +clutter_text_new_full (const gchar *font_name, + const gchar *text, + const ClutterColor *color) +{ + return g_object_new (CLUTTER_TYPE_TEXT, + "font-name", font_name, + "text", text, + "color", color, + NULL); +} + +/** + * clutter_text_new_with_text: + * @font_name: (allow-none): a string with a font description + * @text: the contents of the actor + * + * Creates a new #ClutterText actor, using @font_name as the font + * description; @text will be used to set the contents of the actor. + * + * This function is equivalent to calling clutter_text_new(), + * clutter_text_set_font_name(), and clutter_text_set_text(). + * + * Return value: the newly created #ClutterText actor + * + * Since: 1.0 + */ +ClutterActor * +clutter_text_new_with_text (const gchar *font_name, + const gchar *text) +{ + return g_object_new (CLUTTER_TYPE_TEXT, + "font-name", font_name, + "text", text, + NULL); +} + +static ClutterTextBuffer* +get_buffer (ClutterText *self) +{ + ClutterTextPrivate *priv = self->priv; + + if (priv->buffer == NULL) + { + ClutterTextBuffer *buffer; + buffer = clutter_text_buffer_new (); + clutter_text_set_buffer (self, buffer); + g_object_unref (buffer); + } + + return priv->buffer; +} + +/* GtkEntryBuffer signal handlers + */ +static void +buffer_inserted_text (ClutterTextBuffer *buffer, + guint position, + const gchar *chars, + guint n_chars, + ClutterText *self) +{ + ClutterTextPrivate *priv; + gint new_position; + gint new_selection_bound; + + priv = self->priv; + if (priv->position >= 0 || priv->selection_bound >= 0) + { + new_position = priv->position; + new_selection_bound = priv->selection_bound; + + if (position <= new_position) + new_position += n_chars; + if (position <= new_selection_bound) + new_selection_bound += n_chars; + + if (priv->position != new_position || priv->selection_bound != new_selection_bound) + clutter_text_set_positions (self, new_position, new_selection_bound); + } + + /* TODO: What are we supposed to with the out value of position? */ +} + +static void +buffer_deleted_text (ClutterTextBuffer *buffer, + guint position, + guint n_chars, + ClutterText *self) +{ + ClutterTextPrivate *priv; + gint new_position; + gint new_selection_bound; + + priv = self->priv; + if (priv->position >= 0 || priv->selection_bound >= 0) + { + new_position = priv->position; + new_selection_bound = priv->selection_bound; + + if (position < new_position) + new_position -= n_chars; + if (position < new_selection_bound) + new_selection_bound -= n_chars; + + if (priv->position != new_position || priv->selection_bound != new_selection_bound) + clutter_text_set_positions (self, new_position, new_selection_bound); + } +} + +static void +buffer_notify_text (ClutterTextBuffer *buffer, + GParamSpec *spec, + ClutterText *self) +{ + g_object_freeze_notify (G_OBJECT (self)); + + clutter_text_dirty_cache (self); + + clutter_actor_queue_relayout (CLUTTER_ACTOR (self)); + + g_signal_emit (self, text_signals[TEXT_CHANGED], 0); + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_TEXT]); + + g_object_thaw_notify (G_OBJECT (self)); +} + +static void +buffer_notify_max_length (ClutterTextBuffer *buffer, + GParamSpec *spec, + ClutterText *self) +{ + g_object_notify (G_OBJECT (self), "max-length"); +} + +static void +buffer_connect_signals (ClutterText *self) +{ + ClutterTextPrivate *priv = self->priv; + g_signal_connect (priv->buffer, "inserted-text", G_CALLBACK (buffer_inserted_text), self); + g_signal_connect (priv->buffer, "deleted-text", G_CALLBACK (buffer_deleted_text), self); + g_signal_connect (priv->buffer, "notify::text", G_CALLBACK (buffer_notify_text), self); + g_signal_connect (priv->buffer, "notify::max-length", G_CALLBACK (buffer_notify_max_length), self); +} + +static void +buffer_disconnect_signals (ClutterText *self) +{ + ClutterTextPrivate *priv = self->priv; + g_signal_handlers_disconnect_by_func (priv->buffer, buffer_inserted_text, self); + g_signal_handlers_disconnect_by_func (priv->buffer, buffer_deleted_text, self); + g_signal_handlers_disconnect_by_func (priv->buffer, buffer_notify_text, self); + g_signal_handlers_disconnect_by_func (priv->buffer, buffer_notify_max_length, self); +} + +/** + * clutter_text_new_with_buffer: + * @buffer: The buffer to use for the new #ClutterText. + * + * Creates a new entry with the specified text buffer. + * + * Return value: a new #ClutterText + * + * Since: 1.10 + */ +ClutterActor * +clutter_text_new_with_buffer (ClutterTextBuffer *buffer) +{ + g_return_val_if_fail (CLUTTER_IS_TEXT_BUFFER (buffer), NULL); + return g_object_new (CLUTTER_TYPE_TEXT, "buffer", buffer, NULL); +} + +/** + * clutter_text_get_buffer: + * @self: a #ClutterText + * + * Get the #ClutterTextBuffer object which holds the text for + * this widget. + * + * Returns: (transfer none): A #GtkEntryBuffer object. + * + * Since: 1.10 + */ +ClutterTextBuffer* +clutter_text_get_buffer (ClutterText *self) +{ + g_return_val_if_fail (CLUTTER_IS_TEXT (self), NULL); + + return get_buffer (self); +} + +/** + * clutter_text_set_buffer: + * @self: a #ClutterText + * @buffer: a #ClutterTextBuffer + * + * Set the #ClutterTextBuffer object which holds the text for + * this widget. + * + * Since: 1.10 + */ +void +clutter_text_set_buffer (ClutterText *self, + ClutterTextBuffer *buffer) +{ + ClutterTextPrivate *priv; + GObject *obj; + + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + priv = self->priv; + + if (buffer) + { + g_return_if_fail (CLUTTER_IS_TEXT_BUFFER (buffer)); + g_object_ref (buffer); + } + + if (priv->buffer) + { + buffer_disconnect_signals (self); + g_object_unref (priv->buffer); + } + + priv->buffer = buffer; + + if (priv->buffer) + buffer_connect_signals (self); + + obj = G_OBJECT (self); + g_object_freeze_notify (obj); + g_object_notify (obj, "buffer"); + g_object_notify (obj, "text"); + g_object_notify (obj, "max-length"); + g_object_thaw_notify (obj); +} + +/** + * clutter_text_set_editable: + * @self: a #ClutterText + * @editable: whether the #ClutterText should be editable + * + * Sets whether the #ClutterText actor should be editable. + * + * An editable #ClutterText with key focus set using + * clutter_actor_grab_key_focus() or clutter_stage_set_key_focus() + * will receive key events and will update its contents accordingly. + * + * Since: 1.0 + */ +void +clutter_text_set_editable (ClutterText *self, + gboolean editable) +{ + ClutterTextPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + priv = self->priv; + + if (priv->editable != editable) + { + priv->editable = editable; + + clutter_text_queue_redraw (CLUTTER_ACTOR (self)); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_EDITABLE]); + } +} + +/** + * clutter_text_get_editable: + * @self: a #ClutterText + * + * Retrieves whether a #ClutterText is editable or not. + * + * Return value: %TRUE if the actor is editable + * + * Since: 1.0 + */ +gboolean +clutter_text_get_editable (ClutterText *self) +{ + g_return_val_if_fail (CLUTTER_IS_TEXT (self), FALSE); + + return self->priv->editable; +} + +/** + * clutter_text_set_selectable: + * @self: a #ClutterText + * @selectable: whether the #ClutterText actor should be selectable + * + * Sets whether a #ClutterText actor should be selectable. + * + * A selectable #ClutterText will allow selecting its contents using + * the pointer or the keyboard. + * + * Since: 1.0 + */ +void +clutter_text_set_selectable (ClutterText *self, + gboolean selectable) +{ + ClutterTextPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + priv = self->priv; + + if (priv->selectable != selectable) + { + priv->selectable = selectable; + + clutter_text_queue_redraw (CLUTTER_ACTOR (self)); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SELECTABLE]); + } +} + +/** + * clutter_text_get_selectable: + * @self: a #ClutterText + * + * Retrieves whether a #ClutterText is selectable or not. + * + * Return value: %TRUE if the actor is selectable + * + * Since: 1.0 + */ +gboolean +clutter_text_get_selectable (ClutterText *self) +{ + g_return_val_if_fail (CLUTTER_IS_TEXT (self), TRUE); + + return self->priv->selectable; +} + +/** + * clutter_text_set_activatable: + * @self: a #ClutterText + * @activatable: whether the #ClutterText actor should be activatable + * + * Sets whether a #ClutterText actor should be activatable. + * + * An activatable #ClutterText actor will emit the #ClutterText::activate + * signal whenever the 'Enter' (or 'Return') key is pressed; if it is not + * activatable, a new line will be appended to the current content. + * + * An activatable #ClutterText must also be set as editable using + * clutter_text_set_editable(). + * + * Since: 1.0 + */ +void +clutter_text_set_activatable (ClutterText *self, + gboolean activatable) +{ + ClutterTextPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + priv = self->priv; + + if (priv->activatable != activatable) + { + priv->activatable = activatable; + + clutter_text_queue_redraw (CLUTTER_ACTOR (self)); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ACTIVATABLE]); + } +} + +/** + * clutter_text_get_activatable: + * @self: a #ClutterText + * + * Retrieves whether a #ClutterText is activatable or not. + * + * Return value: %TRUE if the actor is activatable + * + * Since: 1.0 + */ +gboolean +clutter_text_get_activatable (ClutterText *self) +{ + g_return_val_if_fail (CLUTTER_IS_TEXT (self), TRUE); + + return self->priv->activatable; +} + +/** + * clutter_text_activate: + * @self: a #ClutterText + * + * Emits the #ClutterText::activate signal, if @self has been set + * as activatable using clutter_text_set_activatable(). + * + * This function can be used to emit the ::activate signal inside + * a #ClutterActor::captured-event or #ClutterActor::key-press-event + * signal handlers before the default signal handler for the + * #ClutterText is invoked. + * + * Return value: %TRUE if the ::activate signal has been emitted, + * and %FALSE otherwise + * + * Since: 1.0 + */ +gboolean +clutter_text_activate (ClutterText *self) +{ + ClutterTextPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_TEXT (self), FALSE); + + priv = self->priv; + + if (priv->activatable) + { + g_signal_emit (self, text_signals[ACTIVATE], 0); + return TRUE; + } + + return FALSE; +} + +/** + * clutter_text_set_cursor_visible: + * @self: a #ClutterText + * @cursor_visible: whether the cursor should be visible + * + * Sets whether the cursor of a #ClutterText actor should be + * visible or not. + * + * The color of the cursor will be the same as the text color + * unless clutter_text_set_cursor_color() has been called. + * + * The size of the cursor can be set using clutter_text_set_cursor_size(). + * + * The position of the cursor can be changed programmatically using + * clutter_text_set_cursor_position(). + * + * Since: 1.0 + */ +void +clutter_text_set_cursor_visible (ClutterText *self, + gboolean cursor_visible) +{ + ClutterTextPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + priv = self->priv; + + cursor_visible = !!cursor_visible; + + if (priv->cursor_visible != cursor_visible) + { + priv->cursor_visible = cursor_visible; + + clutter_text_dirty_cache (self); + clutter_actor_queue_relayout (CLUTTER_ACTOR (self)); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_CURSOR_VISIBLE]); + } +} + +/** + * clutter_text_get_cursor_visible: + * @self: a #ClutterText + * + * Retrieves whether the cursor of a #ClutterText actor is visible. + * + * Return value: %TRUE if the cursor is visible + * + * Since: 1.0 + */ +gboolean +clutter_text_get_cursor_visible (ClutterText *self) +{ + g_return_val_if_fail (CLUTTER_IS_TEXT (self), TRUE); + + return self->priv->cursor_visible; +} + +/** + * clutter_text_set_cursor_color: + * @self: a #ClutterText + * @color: (allow-none): the color of the cursor, or %NULL to unset it + * + * Sets the color of the cursor of a #ClutterText actor. + * + * If @color is %NULL, the cursor color will be the same as the + * text color. + * + * Since: 1.0 + */ +void +clutter_text_set_cursor_color (ClutterText *self, + const ClutterColor *color) +{ + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + clutter_text_set_color_animated (self, obj_props[PROP_CURSOR_COLOR], color); +} + +/** + * clutter_text_get_cursor_color: + * @self: a #ClutterText + * @color: (out): return location for a #ClutterColor + * + * Retrieves the color of the cursor of a #ClutterText actor. + * + * Since: 1.0 + */ +void +clutter_text_get_cursor_color (ClutterText *self, + ClutterColor *color) +{ + ClutterTextPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TEXT (self)); + g_return_if_fail (color != NULL); + + priv = self->priv; + + *color = priv->cursor_color; +} + +/** + * clutter_text_set_selection: + * @self: a #ClutterText + * @start_pos: start of the selection, in characters + * @end_pos: end of the selection, in characters + * + * Selects the region of text between @start_pos and @end_pos. + * + * This function changes the position of the cursor to match + * @start_pos and the selection bound to match @end_pos. + * + * Since: 1.0 + */ +void +clutter_text_set_selection (ClutterText *self, + gssize start_pos, + gssize end_pos) +{ + guint n_chars; + + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + n_chars = clutter_text_buffer_get_length (get_buffer (self)); + if (end_pos < 0) + end_pos = n_chars; + + start_pos = MIN (n_chars, start_pos); + end_pos = MIN (n_chars, end_pos); + + clutter_text_set_positions (self, start_pos, end_pos); +} + +/** + * clutter_text_get_selection: + * @self: a #ClutterText + * + * Retrieves the currently selected text. + * + * Return value: a newly allocated string containing the currently + * selected text, or %NULL. Use g_free() to free the returned + * string. + * + * Since: 1.0 + */ +gchar * +clutter_text_get_selection (ClutterText *self) +{ + ClutterTextPrivate *priv; + gchar *str; + gint len; + gint start_index, end_index; + gint start_offset, end_offset; + const gchar *text; + + g_return_val_if_fail (CLUTTER_IS_TEXT (self), NULL); + + priv = self->priv; + + start_index = priv->position; + end_index = priv->selection_bound; + + if (end_index == start_index) + return g_strdup (""); + + if ((end_index != -1 && end_index < start_index) || + start_index == -1) + { + gint temp = start_index; + start_index = end_index; + end_index = temp; + } + + text = clutter_text_buffer_get_text (get_buffer (self)); + start_offset = offset_to_bytes (text, start_index); + end_offset = offset_to_bytes (text, end_index); + len = end_offset - start_offset; + + str = g_malloc (len + 1); + g_utf8_strncpy (str, text + start_offset, end_index - start_index); + + return str; +} + +/** + * clutter_text_set_selection_bound: + * @self: a #ClutterText + * @selection_bound: the position of the end of the selection, in characters + * + * Sets the other end of the selection, starting from the current + * cursor position. + * + * If @selection_bound is -1, the selection unset. + * + * Since: 1.0 + */ +void +clutter_text_set_selection_bound (ClutterText *self, + gint selection_bound) +{ + ClutterTextPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + priv = self->priv; + + if (priv->selection_bound != selection_bound) + { + gint len = clutter_text_buffer_get_length (get_buffer (self));; + + if (selection_bound < 0 || selection_bound >= len) + priv->selection_bound = -1; + else + priv->selection_bound = selection_bound; + + clutter_text_queue_redraw (CLUTTER_ACTOR (self)); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SELECTION_BOUND]); + } +} + +/** + * clutter_text_get_selection_bound: + * @self: a #ClutterText + * + * Retrieves the other end of the selection of a #ClutterText actor, + * in characters from the current cursor position. + * + * Return value: the position of the other end of the selection + * + * Since: 1.0 + */ +gint +clutter_text_get_selection_bound (ClutterText *self) +{ + g_return_val_if_fail (CLUTTER_IS_TEXT (self), -1); + + return self->priv->selection_bound; +} + +/** + * clutter_text_set_selection_color: + * @self: a #ClutterText + * @color: (allow-none): the color of the selection, or %NULL to unset it + * + * Sets the color of the selection of a #ClutterText actor. + * + * If @color is %NULL, the selection color will be the same as the + * cursor color, or if no cursor color is set either then it will be + * the same as the text color. + * + * Since: 1.0 + */ +void +clutter_text_set_selection_color (ClutterText *self, + const ClutterColor *color) +{ + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + clutter_text_set_color_animated (self, obj_props[PROP_SELECTION_COLOR], + color); +} + +/** + * clutter_text_get_selection_color: + * @self: a #ClutterText + * @color: (out caller-allocates): return location for a #ClutterColor + * + * Retrieves the color of the selection of a #ClutterText actor. + * + * Since: 1.0 + */ +void +clutter_text_get_selection_color (ClutterText *self, + ClutterColor *color) +{ + ClutterTextPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TEXT (self)); + g_return_if_fail (color != NULL); + + priv = self->priv; + + *color = priv->selection_color; +} + +/** + * clutter_text_set_selected_text_color: + * @self: a #ClutterText + * @color: (allow-none): the selected text color, or %NULL to unset it + * + * Sets the selected text color of a #ClutterText actor. + * + * If @color is %NULL, the selected text color will be the same as the + * selection color, which then falls back to cursor, and then text color. + * + * Since: 1.8 + */ +void +clutter_text_set_selected_text_color (ClutterText *self, + const ClutterColor *color) +{ + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + clutter_text_set_color_animated (self, obj_props[PROP_SELECTED_TEXT_COLOR], + color); +} + +/** + * clutter_text_get_selected_text_color: + * @self: a #ClutterText + * @color: (out caller-allocates): return location for a #ClutterColor + * + * Retrieves the color of selected text of a #ClutterText actor. + * + * Since: 1.8 + */ +void +clutter_text_get_selected_text_color (ClutterText *self, + ClutterColor *color) +{ + ClutterTextPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TEXT (self)); + g_return_if_fail (color != NULL); + + priv = self->priv; + + *color = priv->selected_text_color; +} + +/** + * clutter_text_set_font_description: + * @self: a #ClutterText + * @font_desc: a #PangoFontDescription + * + * Sets @font_desc as the font description for a #ClutterText + * + * The #PangoFontDescription is copied by the #ClutterText actor + * so you can safely call pango_font_description_free() on it after + * calling this function. + * + * Since: 1.2 + */ +void +clutter_text_set_font_description (ClutterText *self, + PangoFontDescription *font_desc) +{ + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + clutter_text_set_font_description_internal (self, font_desc, + font_desc == NULL); +} + +/** + * clutter_text_get_font_description: + * @self: a #ClutterText + * + * Retrieves the #PangoFontDescription used by @self + * + * Return value: a #PangoFontDescription. The returned value is owned + * by the #ClutterText actor and it should not be modified or freed + * + * Since: 1.2 + */ +PangoFontDescription * +clutter_text_get_font_description (ClutterText *self) +{ + g_return_val_if_fail (CLUTTER_IS_TEXT (self), NULL); + + return self->priv->font_desc; +} + +/** + * clutter_text_get_font_name: + * @self: a #ClutterText + * + * Retrieves the font name as set by clutter_text_set_font_name(). + * + * Return value: a string containing the font name. The returned + * string is owned by the #ClutterText actor and should not be + * modified or freed + * + * Since: 1.0 + */ +const gchar * +clutter_text_get_font_name (ClutterText *text) +{ + g_return_val_if_fail (CLUTTER_IS_TEXT (text), NULL); + + return text->priv->font_name; +} + +/** + * clutter_text_set_font_name: + * @self: a #ClutterText + * @font_name: (allow-none): a font name, or %NULL to set the default font name + * + * Sets the font used by a #ClutterText. The @font_name string + * must either be %NULL, which means that the font name from the + * default #ClutterBackend will be used; or be something that can + * be parsed by the pango_font_description_from_string() function, + * like: + * + * |[ + * // Set the font to the system's Sans, 10 points + * clutter_text_set_font_name (text, "Sans 10"); + * + * // Set the font to the system's Serif, 16 pixels + * clutter_text_set_font_name (text, "Serif 16px"); + * + * // Set the font to Helvetica, 10 points + * clutter_text_set_font_name (text, "Helvetica 10"); + * ]| + * + * Since: 1.0 + */ +void +clutter_text_set_font_name (ClutterText *self, + const gchar *font_name) +{ + ClutterTextPrivate *priv; + PangoFontDescription *desc; + gboolean is_default_font; + + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + /* get the default font name from the backend */ + if (font_name == NULL || font_name[0] == '\0') + { + ClutterSettings *settings = clutter_settings_get_default (); + gchar *default_font_name = NULL; + + g_object_get (settings, "font-name", &default_font_name, NULL); + + if (default_font_name != NULL) + font_name = default_font_name; + else + { + /* last fallback */ + font_name = g_strdup ("Sans 12"); + } + + is_default_font = TRUE; + } + else + is_default_font = FALSE; + + priv = self->priv; + + if (g_strcmp0 (priv->font_name, font_name) == 0) + goto out; + + desc = pango_font_description_from_string (font_name); + if (desc == NULL) + { + g_warning ("Attempting to create a PangoFontDescription for " + "font name '%s', but failed.", + font_name); + goto out; + } + + /* this will set the font_name field as well */ + clutter_text_set_font_description_internal (self, desc, is_default_font); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_FONT_NAME]); + + pango_font_description_free (desc); + +out: + if (is_default_font) + g_free ((gchar *) font_name); +} + +/** + * clutter_text_get_text: + * @self: a #ClutterText + * + * Retrieves a pointer to the current contents of a #ClutterText + * actor. + * + * If you need a copy of the contents for manipulating, either + * use g_strdup() on the returned string, or use: + * + * |[ + * copy = clutter_text_get_chars (text, 0, -1); + * ]| + * + * Which will return a newly allocated string. + * + * If the #ClutterText actor is empty, this function will return + * an empty string, and not %NULL. + * + * Return value: (transfer none): the contents of the actor. The returned + * string is owned by the #ClutterText actor and should never be modified + * or freed + * + * Since: 1.0 + */ +const gchar * +clutter_text_get_text (ClutterText *self) +{ + g_return_val_if_fail (CLUTTER_IS_TEXT (self), NULL); + + return clutter_text_buffer_get_text (get_buffer (self)); +} + +static inline void +clutter_text_set_use_markup_internal (ClutterText *self, + gboolean use_markup) +{ + ClutterTextPrivate *priv = self->priv; + + if (priv->use_markup != use_markup) + { + priv->use_markup = use_markup; + + /* reset the attributes lists so that they can be + * re-generated + */ + if (priv->effective_attrs != NULL) + { + pango_attr_list_unref (priv->effective_attrs); + priv->effective_attrs = NULL; + } + + if (priv->markup_attrs) + { + pango_attr_list_unref (priv->markup_attrs); + priv->markup_attrs = NULL; + } + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_USE_MARKUP]); + } +} + +/** + * clutter_text_set_text: + * @self: a #ClutterText + * @text: (allow-none): the text to set. Passing %NULL is the same + * as passing "" (the empty string) + * + * Sets the contents of a #ClutterText actor. + * + * If the #ClutterText:use-markup property was set to %TRUE it + * will be reset to %FALSE as a side effect. If you want to + * maintain the #ClutterText:use-markup you should use the + * clutter_text_set_markup() function instead + * + * Since: 1.0 + */ +void +clutter_text_set_text (ClutterText *self, + const gchar *text) +{ + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + /* if the text is editable (i.e. there is not markup flag to reset) then + * changing the contents will result in selection and cursor changes that + * we should avoid + */ + if (self->priv->editable) + { + if (g_strcmp0 (clutter_text_buffer_get_text (get_buffer (self)), text) == 0) + return; + } + + clutter_text_set_use_markup_internal (self, FALSE); + clutter_text_buffer_set_text (get_buffer (self), text ? text : "", -1); +} + +/** + * clutter_text_set_markup: + * @self: a #ClutterText + * @markup: (allow-none): a string containing Pango markup. + * Passing %NULL is the same as passing "" (the empty string) + * + * Sets @markup as the contents of a #ClutterText. + * + * This is a convenience function for setting a string containing + * Pango markup, and it is logically equivalent to: + * + * |[ + * /* the order is important */ + * clutter_text_set_text (CLUTTER_TEXT (actor), markup); + * clutter_text_set_use_markup (CLUTTER_TEXT (actor), TRUE); + * ]| + * + * Since: 1.0 + */ +void +clutter_text_set_markup (ClutterText *self, + const gchar *markup) +{ + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + clutter_text_set_use_markup_internal (self, TRUE); + if (markup != NULL && *markup != '\0') + clutter_text_set_markup_internal (self, markup); + else + clutter_text_buffer_set_text (get_buffer (self), "", 0); +} + +/** + * clutter_text_get_layout: + * @self: a #ClutterText + * + * Retrieves the current #PangoLayout used by a #ClutterText actor. + * + * Return value: (transfer none): a #PangoLayout. The returned object is owned by + * the #ClutterText actor and should not be modified or freed + * + * Since: 1.0 + */ +PangoLayout * +clutter_text_get_layout (ClutterText *self) +{ + gfloat width, height; + + g_return_val_if_fail (CLUTTER_IS_TEXT (self), NULL); + + if (self->priv->editable && self->priv->single_line_mode) + return clutter_text_create_layout (self, -1, -1); + + clutter_actor_get_size (CLUTTER_ACTOR (self), &width, &height); + + return clutter_text_create_layout (self, width, height); +} + +/** + * clutter_text_set_color: + * @self: a #ClutterText + * @color: a #ClutterColor + * + * Sets the color of the contents of a #ClutterText actor. + * + * The overall opacity of the #ClutterText actor will be the + * result of the alpha value of @color and the composited + * opacity of the actor itself on the scenegraph, as returned + * by clutter_actor_get_paint_opacity(). + * + * Since: 1.0 + */ +void +clutter_text_set_color (ClutterText *self, + const ClutterColor *color) +{ + g_return_if_fail (CLUTTER_IS_TEXT (self)); + g_return_if_fail (color != NULL); + + clutter_text_set_color_animated (self, obj_props[PROP_COLOR], color); +} + +/** + * clutter_text_get_color: + * @self: a #ClutterText + * @color: (out caller-allocates): return location for a #ClutterColor + * + * Retrieves the text color as set by clutter_text_set_color(). + * + * Since: 1.0 + */ +void +clutter_text_get_color (ClutterText *self, + ClutterColor *color) +{ + ClutterTextPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TEXT (self)); + g_return_if_fail (color != NULL); + + priv = self->priv; + + *color = priv->text_color; +} + +/** + * clutter_text_set_ellipsize: + * @self: a #ClutterText + * @mode: a #PangoEllipsizeMode + * + * Sets the mode used to ellipsize (add an ellipsis: "...") to the + * text if there is not enough space to render the entire contents + * of a #ClutterText actor + * + * Since: 1.0 + */ +void +clutter_text_set_ellipsize (ClutterText *self, + PangoEllipsizeMode mode) +{ + ClutterTextPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TEXT (self)); + g_return_if_fail (mode >= PANGO_ELLIPSIZE_NONE && + mode <= PANGO_ELLIPSIZE_END); + + priv = self->priv; + + if ((PangoEllipsizeMode) priv->ellipsize != mode) + { + priv->ellipsize = mode; + + clutter_text_dirty_cache (self); + + clutter_actor_queue_relayout (CLUTTER_ACTOR (self)); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ELLIPSIZE]); + } +} + +/** + * clutter_text_get_ellipsize: + * @self: a #ClutterText + * + * Returns the ellipsizing position of a #ClutterText actor, as + * set by clutter_text_set_ellipsize(). + * + * Return value: #PangoEllipsizeMode + * + * Since: 1.0 + */ +PangoEllipsizeMode +clutter_text_get_ellipsize (ClutterText *self) +{ + g_return_val_if_fail (CLUTTER_IS_TEXT (self), PANGO_ELLIPSIZE_NONE); + + return self->priv->ellipsize; +} + +/** + * clutter_text_get_line_wrap: + * @self: a #ClutterText + * + * Retrieves the value set using clutter_text_set_line_wrap(). + * + * Return value: %TRUE if the #ClutterText actor should wrap + * its contents + * + * Since: 1.0 + */ +gboolean +clutter_text_get_line_wrap (ClutterText *self) +{ + g_return_val_if_fail (CLUTTER_IS_TEXT (self), FALSE); + + return self->priv->wrap; +} + +/** + * clutter_text_set_line_wrap: + * @self: a #ClutterText + * @line_wrap: whether the contents should wrap + * + * Sets whether the contents of a #ClutterText actor should wrap, + * if they don't fit the size assigned to the actor. + * + * Since: 1.0 + */ +void +clutter_text_set_line_wrap (ClutterText *self, + gboolean line_wrap) +{ + ClutterTextPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + priv = self->priv; + + if (priv->wrap != line_wrap) + { + priv->wrap = line_wrap; + + clutter_text_dirty_cache (self); + + clutter_actor_queue_relayout (CLUTTER_ACTOR (self)); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_LINE_WRAP]); + } +} + +/** + * clutter_text_set_line_wrap_mode: + * @self: a #ClutterText + * @wrap_mode: the line wrapping mode + * + * If line wrapping is enabled (see clutter_text_set_line_wrap()) this + * function controls how the line wrapping is performed. The default is + * %PANGO_WRAP_WORD which means wrap on word boundaries. + * + * Since: 1.0 + */ +void +clutter_text_set_line_wrap_mode (ClutterText *self, + PangoWrapMode wrap_mode) +{ + ClutterTextPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + priv = self->priv; + + if (priv->wrap_mode != wrap_mode) + { + priv->wrap_mode = wrap_mode; + + clutter_text_dirty_cache (self); + + clutter_actor_queue_relayout (CLUTTER_ACTOR (self)); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_LINE_WRAP_MODE]); + } +} + +/** + * clutter_text_get_line_wrap_mode: + * @self: a #ClutterText + * + * Retrieves the line wrap mode used by the #ClutterText actor. + * + * See clutter_text_set_line_wrap_mode (). + * + * Return value: the wrap mode used by the #ClutterText + * + * Since: 1.0 + */ +PangoWrapMode +clutter_text_get_line_wrap_mode (ClutterText *self) +{ + g_return_val_if_fail (CLUTTER_IS_TEXT (self), PANGO_WRAP_WORD); + + return self->priv->wrap_mode; +} + +/** + * clutter_text_set_attributes: + * @self: a #ClutterText + * @attrs: (allow-none): a #PangoAttrList or %NULL to unset the attributes + * + * Sets the attributes list that are going to be applied to the + * #ClutterText contents. + * + * The #ClutterText actor will take a reference on the #PangoAttrList + * passed to this function. + * + * Since: 1.0 + */ +void +clutter_text_set_attributes (ClutterText *self, + PangoAttrList *attrs) +{ + ClutterTextPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + priv = self->priv; + + /* While we should probably test for equality, Pango doesn't + * provide us an easy method to check for AttrList equality. + */ + if (priv->attrs == attrs) + return; + + if (attrs) + pango_attr_list_ref (attrs); + + if (priv->attrs) + pango_attr_list_unref (priv->attrs); + + priv->attrs = attrs; + + /* Clear the effective attributes so they will be regenerated when a + layout is created */ + if (priv->effective_attrs) + { + pango_attr_list_unref (priv->effective_attrs); + priv->effective_attrs = NULL; + } + + clutter_text_dirty_cache (self); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ATTRIBUTES]); + + clutter_actor_queue_relayout (CLUTTER_ACTOR (self)); +} + +/** + * clutter_text_get_attributes: + * @self: a #ClutterText + * + * Gets the attribute list that was set on the #ClutterText actor + * clutter_text_set_attributes(), if any. + * + * Return value: (transfer none): the attribute list, or %NULL if none was set. The + * returned value is owned by the #ClutterText and should not be unreferenced. + * + * Since: 1.0 + */ +PangoAttrList * +clutter_text_get_attributes (ClutterText *self) +{ + g_return_val_if_fail (CLUTTER_IS_TEXT (self), NULL); + + return self->priv->attrs; +} + +/** + * clutter_text_set_line_alignment: + * @self: a #ClutterText + * @alignment: A #PangoAlignment + * + * Sets the way that the lines of a wrapped label are aligned with + * respect to each other. This does not affect the overall alignment + * of the label within its allocated or specified width. + * + * To align a #ClutterText actor you should add it to a container + * that supports alignment, or use the anchor point. + * + * Since: 1.0 + */ +void +clutter_text_set_line_alignment (ClutterText *self, + PangoAlignment alignment) +{ + ClutterTextPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + priv = self->priv; + + if (priv->alignment != alignment) + { + priv->alignment = alignment; + + clutter_text_dirty_cache (self); + + clutter_actor_queue_relayout (CLUTTER_ACTOR (self)); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_LINE_ALIGNMENT]); + } +} + +/** + * clutter_text_get_line_alignment: + * @self: a #ClutterText + * + * Retrieves the alignment of a #ClutterText, as set by + * clutter_text_set_line_alignment(). + * + * Return value: a #PangoAlignment + * + * Since: 1.0 + */ +PangoAlignment +clutter_text_get_line_alignment (ClutterText *self) +{ + g_return_val_if_fail (CLUTTER_IS_TEXT (self), PANGO_ALIGN_LEFT); + + return self->priv->alignment; +} + +/** + * clutter_text_set_use_markup: + * @self: a #ClutterText + * @setting: %TRUE if the text should be parsed for markup. + * + * Sets whether the contents of the #ClutterText actor contains markup + * in Pango's text markup language. + * + * Setting #ClutterText:use-markup on an editable #ClutterText will + * not have any effect except hiding the markup. + * + * See also #ClutterText:use-markup. + * + * Since: 1.0 + */ +void +clutter_text_set_use_markup (ClutterText *self, + gboolean setting) +{ + const gchar *text; + + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + text = clutter_text_buffer_get_text (get_buffer (self)); + + clutter_text_set_use_markup_internal (self, setting); + + if (setting) + clutter_text_set_markup_internal (self, text); + + clutter_text_dirty_cache (self); + + clutter_actor_queue_relayout (CLUTTER_ACTOR (self)); +} + +/** + * clutter_text_get_use_markup: + * @self: a #ClutterText + * + * Retrieves whether the contents of the #ClutterText actor should be + * parsed for the Pango text markup. + * + * Return value: %TRUE if the contents will be parsed for markup + * + * Since: 1.0 + */ +gboolean +clutter_text_get_use_markup (ClutterText *self) +{ + g_return_val_if_fail (CLUTTER_IS_TEXT (self), FALSE); + + return self->priv->use_markup; +} + +/** + * clutter_text_set_justify: + * @self: a #ClutterText + * @justify: whether the text should be justified + * + * Sets whether the text of the #ClutterText actor should be justified + * on both margins. This setting is ignored if Clutter is compiled + * against Pango < 1.18. + * + * Since: 1.0 + */ +void +clutter_text_set_justify (ClutterText *self, + gboolean justify) +{ + ClutterTextPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + priv = self->priv; + + if (priv->justify != justify) + { + priv->justify = justify; + + clutter_text_dirty_cache (self); + + clutter_actor_queue_relayout (CLUTTER_ACTOR (self)); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_JUSTIFY]); + } +} + +/** + * clutter_text_get_justify: + * @self: a #ClutterText + * + * Retrieves whether the #ClutterText actor should justify its contents + * on both margins. + * + * Return value: %TRUE if the text should be justified + * + * Since: 0.6 + */ +gboolean +clutter_text_get_justify (ClutterText *self) +{ + g_return_val_if_fail (CLUTTER_IS_TEXT (self), FALSE); + + return self->priv->justify; +} + +/** + * clutter_text_get_cursor_position: + * @self: a #ClutterText + * + * Retrieves the cursor position. + * + * Return value: the cursor position, in characters + * + * Since: 1.0 + */ +gint +clutter_text_get_cursor_position (ClutterText *self) +{ + g_return_val_if_fail (CLUTTER_IS_TEXT (self), -1); + + return self->priv->position; +} + +/** + * clutter_text_set_cursor_position: + * @self: a #ClutterText + * @position: the new cursor position, in characters + * + * Sets the cursor of a #ClutterText actor at @position. + * + * The position is expressed in characters, not in bytes. + * + * Since: 1.0 + */ +void +clutter_text_set_cursor_position (ClutterText *self, + gint position) +{ + ClutterTextPrivate *priv; + gint len; + + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + priv = self->priv; + + if (priv->position == position) + return; + + len = clutter_text_buffer_get_length (get_buffer (self)); + + if (position < 0 || position >= len) + priv->position = -1; + else + priv->position = position; + + /* Forget the target x position so that it will be recalculated next + time the cursor is moved up or down */ + priv->x_pos = -1; + + clutter_text_queue_redraw (CLUTTER_ACTOR (self)); + + /* XXX:2.0 - remove */ + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_POSITION]); + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_CURSOR_POSITION]); +} + +/** + * clutter_text_set_cursor_size: + * @self: a #ClutterText + * @size: the size of the cursor, in pixels, or -1 to use the + * default value + * + * Sets the size of the cursor of a #ClutterText. The cursor + * will only be visible if the #ClutterText:cursor-visible property + * is set to %TRUE. + * + * Since: 1.0 + */ +void +clutter_text_set_cursor_size (ClutterText *self, + gint size) +{ + ClutterTextPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + priv = self->priv; + + if (priv->cursor_size != size) + { + if (size < 0) + size = DEFAULT_CURSOR_SIZE; + + priv->cursor_size = size; + + clutter_text_queue_redraw (CLUTTER_ACTOR (self)); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_CURSOR_SIZE]); + } +} + +/** + * clutter_text_get_cursor_size: + * @self: a #ClutterText + * + * Retrieves the size of the cursor of a #ClutterText actor. + * + * Return value: the size of the cursor, in pixels + * + * Since: 1.0 + */ +guint +clutter_text_get_cursor_size (ClutterText *self) +{ + g_return_val_if_fail (CLUTTER_IS_TEXT (self), DEFAULT_CURSOR_SIZE); + + return self->priv->cursor_size; +} + +/** + * clutter_text_set_password_char: + * @self: a #ClutterText + * @wc: a Unicode character, or 0 to unset the password character + * + * Sets the character to use in place of the actual text in a + * password text actor. + * + * If @wc is 0 the text will be displayed as it is entered in the + * #ClutterText actor. + * + * Since: 1.0 + */ +void +clutter_text_set_password_char (ClutterText *self, + gunichar wc) +{ + ClutterTextPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + priv = self->priv; + + if (priv->password_char != wc) + { + priv->password_char = wc; + + clutter_text_dirty_cache (self); + clutter_actor_queue_relayout (CLUTTER_ACTOR (self)); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_PASSWORD_CHAR]); + } +} + +/** + * clutter_text_get_password_char: + * @self: a #ClutterText + * + * Retrieves the character to use in place of the actual text + * as set by clutter_text_set_password_char(). + * + * Return value: a Unicode character or 0 if the password + * character is not set + * + * Since: 1.0 + */ +gunichar +clutter_text_get_password_char (ClutterText *self) +{ + g_return_val_if_fail (CLUTTER_IS_TEXT (self), 0); + + return self->priv->password_char; +} + +/** + * clutter_text_set_max_length: + * @self: a #ClutterText + * @max: the maximum number of characters allowed in the text actor; 0 + * to disable or -1 to set the length of the current string + * + * Sets the maximum allowed length of the contents of the actor. If the + * current contents are longer than the given length, then they will be + * truncated to fit. + * + * Since: 1.0 + */ +void +clutter_text_set_max_length (ClutterText *self, + gint max) +{ + g_return_if_fail (CLUTTER_IS_TEXT (self)); + clutter_text_buffer_set_max_length (get_buffer (self), max); +} + +/** + * clutter_text_get_max_length: + * @self: a #ClutterText + * + * Gets the maximum length of text that can be set into a text actor. + * + * See clutter_text_set_max_length(). + * + * Return value: the maximum number of characters. + * + * Since: 1.0 + */ +gint +clutter_text_get_max_length (ClutterText *self) +{ + g_return_val_if_fail (CLUTTER_IS_TEXT (self), 0); + + return clutter_text_buffer_get_max_length (get_buffer (self)); +} + +static void +clutter_text_real_insert_text (ClutterText *self, + guint start_pos, + const gchar *chars, + guint n_chars) +{ + gsize n_bytes; + + n_bytes = g_utf8_offset_to_pointer (chars, n_chars) - chars; + + /* + * insert-text is emitted here instead of as part of a + * buffer_inserted_text() callback because that should be emitted + * before the buffer changes, while ClutterTextBuffer::deleted-text + * is emitter after. See BG#722220 for more info. + */ + g_signal_emit (self, text_signals[INSERT_TEXT], 0, chars, + n_bytes, &start_pos); + + /* + * The actual insertion from the buffer. This will end firing the + * following signal handlers: buffer_inserted_text(), + * buffer_notify_text(), buffer_notify_max_length() + */ + clutter_text_buffer_insert_text (get_buffer (self), start_pos, chars, n_chars); +} + +/** + * clutter_text_insert_unichar: + * @self: a #ClutterText + * @wc: a Unicode character + * + * Inserts @wc at the current cursor position of a + * #ClutterText actor. + * + * Since: 1.0 + */ +void +clutter_text_insert_unichar (ClutterText *self, + gunichar wc) +{ + ClutterTextPrivate *priv; + GString *new; + + priv = self->priv; + + new = g_string_new (""); + g_string_append_unichar (new, wc); + + clutter_text_real_insert_text (self, priv->position, new->str, 1); + + g_string_free (new, TRUE); +} + + +/** + * clutter_text_insert_text: + * @self: a #ClutterText + * @text: the text to be inserted + * @position: the position of the insertion, or -1 + * + * Inserts @text into a #ClutterActor at the given position. + * + * If @position is a negative number, the text will be appended + * at the end of the current contents of the #ClutterText. + * + * The position is expressed in characters, not in bytes. + * + * Since: 1.0 + */ +void +clutter_text_insert_text (ClutterText *self, + const gchar *text, + gssize position) +{ + g_return_if_fail (CLUTTER_IS_TEXT (self)); + g_return_if_fail (text != NULL); + + clutter_text_real_insert_text (self, position, text, g_utf8_strlen (text, -1)); +} + +static +void clutter_text_real_delete_text (ClutterText *self, + gssize start_pos, + gssize end_pos) +{ + /* + * delete-text is emitted here instead of as part of a + * buffer_deleted_text() callback because that should be emitted + * before the buffer changes, while ClutterTextBuffer::deleted-text + * is emitter after. See BG#722220 for more info. + */ + g_signal_emit (self, text_signals[DELETE_TEXT], 0, start_pos, end_pos); + + /* + * The actual deletion from the buffer. This will end firing the + * following signal handlers: buffer_deleted_text(), + * buffer_notify_text(), buffer_notify_max_length() + */ + clutter_text_buffer_delete_text (get_buffer (self), start_pos, end_pos - start_pos); +} + + + +/** + * clutter_text_delete_text: + * @self: a #ClutterText + * @start_pos: starting position + * @end_pos: ending position + * + * Deletes the text inside a #ClutterText actor between @start_pos + * and @end_pos. + * + * The starting and ending positions are expressed in characters, + * not in bytes. + * + * Since: 1.0 + */ +void +clutter_text_delete_text (ClutterText *self, + gssize start_pos, + gssize end_pos) +{ + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + clutter_text_real_delete_text (self, start_pos, end_pos); +} + +/** + * clutter_text_delete_chars: + * @self: a #ClutterText + * @n_chars: the number of characters to delete + * + * Deletes @n_chars inside a #ClutterText actor, starting from the + * current cursor position. + * + * Somewhat awkwardly, the cursor position is decremented by the same + * number of characters you've deleted. + * + * Since: 1.0 + */ +void +clutter_text_delete_chars (ClutterText *self, + guint n_chars) +{ + ClutterTextPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + priv = self->priv; + + clutter_text_real_delete_text (self, priv->position, priv->position + n_chars); + + if (priv->position > 0) + clutter_text_set_cursor_position (self, priv->position - n_chars); +} + +/** + * clutter_text_get_chars: + * @self: a #ClutterText + * @start_pos: start of text, in characters + * @end_pos: end of text, in characters + * + * Retrieves the contents of the #ClutterText actor between + * @start_pos and @end_pos, but not including @end_pos. + * + * The positions are specified in characters, not in bytes. + * + * Return value: a newly allocated string with the contents of + * the text actor between the specified positions. Use g_free() + * to free the resources when done + * + * Since: 1.0 + */ +gchar * +clutter_text_get_chars (ClutterText *self, + gssize start_pos, + gssize end_pos) +{ + gint start_index, end_index; + guint n_chars; + const gchar *text; + + g_return_val_if_fail (CLUTTER_IS_TEXT (self), NULL); + + n_chars = clutter_text_buffer_get_length (get_buffer (self)); + text = clutter_text_buffer_get_text (get_buffer (self)); + + if (end_pos < 0) + end_pos = n_chars; + + start_pos = MIN (n_chars, start_pos); + end_pos = MIN (n_chars, end_pos); + + start_index = g_utf8_offset_to_pointer (text, start_pos) - text; + end_index = g_utf8_offset_to_pointer (text, end_pos) - text; + + return g_strndup (text + start_index, end_index - start_index); +} + +/** + * clutter_text_set_single_line_mode: + * @self: a #ClutterText + * @single_line: whether to enable single line mode + * + * Sets whether a #ClutterText actor should be in single line mode + * or not. Only editable #ClutterTexts can be in single line + * mode. + * + * A text actor in single line mode will not wrap text and will clip + * the visible area to the predefined size. The contents of the + * text actor will scroll to display the end of the text if its length + * is bigger than the allocated width. + * + * When setting the single line mode the #ClutterText:activatable + * property is also set as a side effect. Instead of entering a new + * line character, the text actor will emit the #ClutterText::activate + * signal. + * + * Since: 1.0 + */ +void +clutter_text_set_single_line_mode (ClutterText *self, + gboolean single_line) +{ + ClutterTextPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + priv = self->priv; + + if (priv->single_line_mode != single_line) + { + g_object_freeze_notify (G_OBJECT (self)); + + priv->single_line_mode = single_line; + + if (priv->single_line_mode) + { + priv->activatable = TRUE; + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ACTIVATABLE]); + } + + clutter_text_dirty_cache (self); + clutter_actor_queue_relayout (CLUTTER_ACTOR (self)); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SINGLE_LINE_MODE]); + + g_object_thaw_notify (G_OBJECT (self)); + } +} + +/** + * clutter_text_get_single_line_mode: + * @self: a #ClutterText + * + * Retrieves whether the #ClutterText actor is in single line mode. + * + * Return value: %TRUE if the #ClutterText actor is in single line mode + * + * Since: 1.0 + */ +gboolean +clutter_text_get_single_line_mode (ClutterText *self) +{ + g_return_val_if_fail (CLUTTER_IS_TEXT (self), FALSE); + + return self->priv->single_line_mode; +} + +/** + * clutter_text_set_preedit_string: + * @self: a #ClutterText + * @preedit_str: (allow-none): the pre-edit string, or %NULL to unset it + * @preedit_attrs: (allow-none): the pre-edit string attributes + * @cursor_pos: the cursor position for the pre-edit string + * + * Sets, or unsets, the pre-edit string. This function is useful + * for input methods to display a string (with eventual specific + * Pango attributes) before it is entered inside the #ClutterText + * buffer. + * + * The preedit string and attributes are ignored if the #ClutterText + * actor is not editable. + * + * This function should not be used by applications + * + * Since: 1.2 + */ +void +clutter_text_set_preedit_string (ClutterText *self, + const gchar *preedit_str, + PangoAttrList *preedit_attrs, + guint cursor_pos) +{ + ClutterTextPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + priv = self->priv; + + g_free (priv->preedit_str); + priv->preedit_str = NULL; + + if (priv->preedit_attrs != NULL) + { + pango_attr_list_unref (priv->preedit_attrs); + priv->preedit_attrs = NULL; + } + + priv->preedit_n_chars = 0; + priv->preedit_cursor_pos = 0; + + if (preedit_str == NULL || *preedit_str == '\0') + priv->preedit_set = FALSE; + else + { + priv->preedit_str = g_strdup (preedit_str); + + if (priv->preedit_str != NULL) + priv->preedit_n_chars = g_utf8_strlen (priv->preedit_str, -1); + else + priv->preedit_n_chars = 0; + + if (preedit_attrs != NULL) + priv->preedit_attrs = pango_attr_list_ref (preedit_attrs); + + priv->preedit_cursor_pos = + CLAMP (cursor_pos, 0, priv->preedit_n_chars); + + priv->preedit_set = TRUE; + } + + clutter_text_dirty_cache (self); + clutter_actor_queue_relayout (CLUTTER_ACTOR (self)); +} + + +/** + * clutter_text_get_layout_offsets: + * @self: a #ClutterText + * @x: (out): location to store X offset of layout, or %NULL + * @y: (out): location to store Y offset of layout, or %NULL + * + * Obtains the coordinates where the #ClutterText will draw the #PangoLayout + * representing the text. + * + * Since: 1.8 + */ +void +clutter_text_get_layout_offsets (ClutterText *self, + gint *x, + gint *y) +{ + ClutterTextPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TEXT (self)); + + priv = self->priv; + + if (x != NULL) + *x = priv->text_x; + + if (y != NULL) + *y = priv->text_y; +} + +/** + * clutter_text_get_cursor_rect: + * @self: a #ClutterText + * @rect: (out caller-allocates): return location of a #ClutterRect + * + * Retrieves the rectangle that contains the cursor. + * + * The coordinates of the rectangle's origin are in actor-relative + * coordinates. + * + * Since: 1.16 + */ +void +clutter_text_get_cursor_rect (ClutterText *self, + ClutterRect *rect) +{ + g_return_if_fail (CLUTTER_IS_TEXT (self)); + g_return_if_fail (rect != NULL); + + *rect = self->priv->cursor_rect; +} diff --git a/clutter/clutter/clutter-text.h b/clutter/clutter/clutter-text.h new file mode 100644 index 0000000..c046dd4 --- /dev/null +++ b/clutter/clutter/clutter-text.h @@ -0,0 +1,307 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2008 Intel Corporation. + * + * Authored By: Øyvind KolÃ¥s + * Emmanuele Bassi + * + * 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 . + */ + +#ifndef __CLUTTER_TEXT_H__ +#define __CLUTTER_TEXT_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_TEXT (clutter_text_get_type ()) +#define CLUTTER_TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_TEXT, ClutterText)) +#define CLUTTER_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_TEXT, ClutterTextClass)) +#define CLUTTER_IS_TEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_TEXT)) +#define CLUTTER_IS_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_TEXT)) +#define CLUTTER_TEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_TEXT, ClutterTextClass)) + +typedef struct _ClutterText ClutterText; +typedef struct _ClutterTextPrivate ClutterTextPrivate; +typedef struct _ClutterTextClass ClutterTextClass; + +/** + * ClutterText: + * + * The #ClutterText struct contains only private data. + * + * Since: 1.0 + */ +struct _ClutterText +{ + /*< private >*/ + ClutterActor parent_instance; + + ClutterTextPrivate *priv; +}; + +/** + * ClutterTextClass: + * @text_changed: class handler for the #ClutterText::text-changed signal + * @activate: class handler for the #ClutterText::activate signal + * @cursor_event: class handler for the #ClutterText::cursor-event signal + * @cursor_changed: class handler for the #ClutterText::cursor-changed signal + * + * The #ClutterTextClass struct contains only private data. + * + * Since: 1.0 + */ +struct _ClutterTextClass +{ + /*< private >*/ + ClutterActorClass parent_class; + + /*< public >*/ + /* signals, not vfuncs */ + void (* text_changed) (ClutterText *self); + void (* activate) (ClutterText *self); + void (* cursor_event) (ClutterText *self, + const ClutterGeometry *geometry); + void (* cursor_changed) (ClutterText *self); + + /*< private >*/ + /* padding for future expansion */ + void (* _clutter_reserved1) (void); + void (* _clutter_reserved2) (void); + void (* _clutter_reserved3) (void); + void (* _clutter_reserved4) (void); + void (* _clutter_reserved5) (void); + void (* _clutter_reserved6) (void); + void (* _clutter_reserved7) (void); +}; + +CLUTTER_AVAILABLE_IN_1_0 +GType clutter_text_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_0 +ClutterActor * clutter_text_new (void); +CLUTTER_AVAILABLE_IN_1_0 +ClutterActor * clutter_text_new_full (const gchar *font_name, + const gchar *text, + const ClutterColor *color); +CLUTTER_AVAILABLE_IN_1_0 +ClutterActor * clutter_text_new_with_text (const gchar *font_name, + const gchar *text); +CLUTTER_AVAILABLE_IN_1_10 +ClutterActor * clutter_text_new_with_buffer (ClutterTextBuffer *buffer); +CLUTTER_AVAILABLE_IN_1_10 +ClutterTextBuffer * clutter_text_get_buffer (ClutterText *self); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_text_set_buffer (ClutterText *self, + ClutterTextBuffer *buffer); +CLUTTER_AVAILABLE_IN_1_0 +const gchar * clutter_text_get_text (ClutterText *self); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_set_text (ClutterText *self, + const gchar *text); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_set_markup (ClutterText *self, + const gchar *markup); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_set_color (ClutterText *self, + const ClutterColor *color); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_get_color (ClutterText *self, + ClutterColor *color); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_set_font_name (ClutterText *self, + const gchar *font_name); +CLUTTER_AVAILABLE_IN_1_0 +const gchar * clutter_text_get_font_name (ClutterText *self); +CLUTTER_AVAILABLE_IN_1_2 +void clutter_text_set_font_description (ClutterText *self, + PangoFontDescription *font_desc); +CLUTTER_AVAILABLE_IN_1_2 +PangoFontDescription *clutter_text_get_font_description (ClutterText *self); + +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_set_ellipsize (ClutterText *self, + PangoEllipsizeMode mode); +CLUTTER_AVAILABLE_IN_1_0 +PangoEllipsizeMode clutter_text_get_ellipsize (ClutterText *self); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_set_line_wrap (ClutterText *self, + gboolean line_wrap); +CLUTTER_AVAILABLE_IN_1_0 +gboolean clutter_text_get_line_wrap (ClutterText *self); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_set_line_wrap_mode (ClutterText *self, + PangoWrapMode wrap_mode); +CLUTTER_AVAILABLE_IN_1_0 +PangoWrapMode clutter_text_get_line_wrap_mode (ClutterText *self); +CLUTTER_AVAILABLE_IN_1_0 +PangoLayout * clutter_text_get_layout (ClutterText *self); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_set_attributes (ClutterText *self, + PangoAttrList *attrs); +CLUTTER_AVAILABLE_IN_1_0 +PangoAttrList * clutter_text_get_attributes (ClutterText *self); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_set_use_markup (ClutterText *self, + gboolean setting); +CLUTTER_AVAILABLE_IN_1_0 +gboolean clutter_text_get_use_markup (ClutterText *self); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_set_line_alignment (ClutterText *self, + PangoAlignment alignment); +CLUTTER_AVAILABLE_IN_1_0 +PangoAlignment clutter_text_get_line_alignment (ClutterText *self); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_set_justify (ClutterText *self, + gboolean justify); +CLUTTER_AVAILABLE_IN_1_0 +gboolean clutter_text_get_justify (ClutterText *self); + +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_insert_unichar (ClutterText *self, + gunichar wc); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_delete_chars (ClutterText *self, + guint n_chars); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_insert_text (ClutterText *self, + const gchar *text, + gssize position); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_delete_text (ClutterText *self, + gssize start_pos, + gssize end_pos); +CLUTTER_AVAILABLE_IN_1_0 +gchar * clutter_text_get_chars (ClutterText *self, + gssize start_pos, + gssize end_pos); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_set_editable (ClutterText *self, + gboolean editable); +CLUTTER_AVAILABLE_IN_1_0 +gboolean clutter_text_get_editable (ClutterText *self); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_set_activatable (ClutterText *self, + gboolean activatable); +CLUTTER_AVAILABLE_IN_1_0 +gboolean clutter_text_get_activatable (ClutterText *self); + +CLUTTER_AVAILABLE_IN_1_0 +gint clutter_text_get_cursor_position (ClutterText *self); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_set_cursor_position (ClutterText *self, + gint position); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_set_cursor_visible (ClutterText *self, + gboolean cursor_visible); +CLUTTER_AVAILABLE_IN_1_0 +gboolean clutter_text_get_cursor_visible (ClutterText *self); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_set_cursor_color (ClutterText *self, + const ClutterColor *color); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_get_cursor_color (ClutterText *self, + ClutterColor *color); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_set_cursor_size (ClutterText *self, + gint size); +CLUTTER_AVAILABLE_IN_1_0 +guint clutter_text_get_cursor_size (ClutterText *self); +CLUTTER_AVAILABLE_IN_1_16 +void clutter_text_get_cursor_rect (ClutterText *self, + ClutterRect *rect); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_set_selectable (ClutterText *self, + gboolean selectable); +CLUTTER_AVAILABLE_IN_1_0 +gboolean clutter_text_get_selectable (ClutterText *self); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_set_selection_bound (ClutterText *self, + gint selection_bound); +CLUTTER_AVAILABLE_IN_1_0 +gint clutter_text_get_selection_bound (ClutterText *self); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_set_selection (ClutterText *self, + gssize start_pos, + gssize end_pos); +CLUTTER_AVAILABLE_IN_1_0 +gchar * clutter_text_get_selection (ClutterText *self); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_set_selection_color (ClutterText *self, + const ClutterColor *color); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_get_selection_color (ClutterText *self, + ClutterColor *color); +CLUTTER_AVAILABLE_IN_1_0 +gboolean clutter_text_delete_selection (ClutterText *self); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_set_password_char (ClutterText *self, + gunichar wc); +CLUTTER_AVAILABLE_IN_1_0 +gunichar clutter_text_get_password_char (ClutterText *self); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_set_max_length (ClutterText *self, + gint max); +CLUTTER_AVAILABLE_IN_1_0 +gint clutter_text_get_max_length (ClutterText *self); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_text_set_single_line_mode (ClutterText *self, + gboolean single_line); +CLUTTER_AVAILABLE_IN_1_0 +gboolean clutter_text_get_single_line_mode (ClutterText *self); + +CLUTTER_AVAILABLE_IN_1_8 +void clutter_text_set_selected_text_color (ClutterText *self, + const ClutterColor *color); +CLUTTER_AVAILABLE_IN_1_8 +void clutter_text_get_selected_text_color (ClutterText *self, + ClutterColor *color); + +CLUTTER_AVAILABLE_IN_1_0 +gboolean clutter_text_activate (ClutterText *self); +CLUTTER_AVAILABLE_IN_1_10 +gint clutter_text_coords_to_position (ClutterText *self, + gfloat x, + gfloat y); +CLUTTER_AVAILABLE_IN_1_0 +gboolean clutter_text_position_to_coords (ClutterText *self, + gint position, + gfloat *x, + gfloat *y, + gfloat *line_height); + +CLUTTER_AVAILABLE_IN_1_2 +void clutter_text_set_preedit_string (ClutterText *self, + const gchar *preedit_str, + PangoAttrList *preedit_attrs, + guint cursor_pos); + +CLUTTER_AVAILABLE_IN_1_8 +void clutter_text_get_layout_offsets (ClutterText *self, + gint *x, + gint *y); + +G_END_DECLS + +#endif /* __CLUTTER_TEXT_H__ */ diff --git a/clutter/clutter/clutter-texture.h b/clutter/clutter/clutter-texture.h new file mode 100644 index 0000000..f890969 --- /dev/null +++ b/clutter/clutter/clutter-texture.h @@ -0,0 +1,130 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 . + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_TEXTURE_H__ +#define __CLUTTER_TEXTURE_H__ + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_TEXTURE (clutter_texture_get_type ()) +#define CLUTTER_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_TEXTURE, ClutterTexture)) +#define CLUTTER_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_TEXTURE, ClutterTextureClass)) +#define CLUTTER_IS_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_TEXTURE)) +#define CLUTTER_IS_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_TEXTURE)) +#define CLUTTER_TEXTURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_TEXTURE, ClutterTextureClass)) + +/** + * ClutterTextureError: + * @CLUTTER_TEXTURE_ERROR_OUT_OF_MEMORY: OOM condition + * @CLUTTER_TEXTURE_ERROR_NO_YUV: YUV operation attempted but no YUV support + * found + * @CLUTTER_TEXTURE_ERROR_BAD_FORMAT: The requested format for + * clutter_texture_set_from_rgb_data or + * clutter_texture_set_from_yuv_data is unsupported. + * + * Error enumeration for #ClutterTexture + * + * Since: 0.4 + */ +typedef enum { + CLUTTER_TEXTURE_ERROR_OUT_OF_MEMORY, + CLUTTER_TEXTURE_ERROR_NO_YUV, + CLUTTER_TEXTURE_ERROR_BAD_FORMAT +} ClutterTextureError; + +/** + * CLUTTER_TEXTURE_ERROR: + * + * Error domain for #ClutterTexture errors + * + * Since: 0.4 + */ +#define CLUTTER_TEXTURE_ERROR (clutter_texture_error_quark ()) +CLUTTER_AVAILABLE_IN_ALL +GQuark clutter_texture_error_quark (void); + +typedef struct _ClutterTexture ClutterTexture; +typedef struct _ClutterTextureClass ClutterTextureClass; +typedef struct _ClutterTexturePrivate ClutterTexturePrivate; + +/** + * ClutterTexture: + * + * The #ClutterTexture structure contains only private data + * and should be accessed using the provided API + * + * Since: 0.2 + */ +struct _ClutterTexture +{ + /*< private >*/ + ClutterActor parent; + + ClutterTexturePrivate *priv; +}; + +/** + * ClutterTextureClass: + * @size_change: handler for the #ClutterTexture::size-change signal + * @pixbuf_change: handler for the #ClutterTexture::pixbuf-change signal + * @load_finished: handler for the #ClutterTexture::load-finished signal + * + * The #ClutterTextureClass structure contains only private data + * + * Since: 0.2 + */ +struct _ClutterTextureClass +{ + /*< private >*/ + ClutterActorClass parent_class; + + /*< public >*/ + void (* size_change) (ClutterTexture *texture, + gint width, + gint height); + void (* pixbuf_change) (ClutterTexture *texture); + void (* load_finished) (ClutterTexture *texture, + const GError *error); + + /*< private >*/ + /* padding, for future expansion */ + void (*_clutter_texture1) (void); + void (*_clutter_texture2) (void); + void (*_clutter_texture3) (void); + void (*_clutter_texture4) (void); + void (*_clutter_texture5) (void); +}; + +CLUTTER_AVAILABLE_IN_ALL +GType clutter_texture_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* __CLUTTER_TEXTURE_H__ */ diff --git a/clutter/clutter/clutter-timeline.c b/clutter/clutter/clutter-timeline.c new file mode 100644 index 0000000..d3db947 --- /dev/null +++ b/clutter/clutter/clutter-timeline.c @@ -0,0 +1,2555 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +/** + * SECTION:clutter-timeline + * @short_description: A class for time-based events + * @see_also: #ClutterAnimation, #ClutterAnimator, #ClutterState + * + * #ClutterTimeline is a base class for managing time-based event that cause + * Clutter to redraw a stage, such as animations. + * + * Each #ClutterTimeline instance has a duration: once a timeline has been + * started, using clutter_timeline_start(), it will emit a signal that can + * be used to update the state of the actors. + * + * It is important to note that #ClutterTimeline is not a generic API for + * calling closures after an interval; each Timeline is tied into the master + * clock used to drive the frame cycle. If you need to schedule a closure + * after an interval, see clutter_threads_add_timeout() instead. + * + * Users of #ClutterTimeline should connect to the #ClutterTimeline::new-frame + * signal, which is emitted each time a timeline is advanced during the maste + * clock iteration. The #ClutterTimeline::new-frame signal provides the time + * elapsed since the beginning of the timeline, in milliseconds. A normalized + * progress value can be obtained by calling clutter_timeline_get_progress(). + * By using clutter_timeline_get_delta() it is possible to obtain the wallclock + * time elapsed since the last emission of the #ClutterTimeline::new-frame + * signal. + * + * Initial state can be set up by using the #ClutterTimeline::started signal, + * while final state can be set up by using the #ClutterTimeline::stopped + * signal. The #ClutterTimeline guarantees the emission of at least a single + * #ClutterTimeline::new-frame signal, as well as the emission of the + * #ClutterTimeline::completed signal every time the #ClutterTimeline reaches + * its #ClutterTimeline:duration. + * + * It is possible to connect to specific points in the timeline progress by + * adding markers using clutter_timeline_add_marker_at_time() and connecting + * to the #ClutterTimeline::marker-reached signal. + * + * Timelines can be made to loop once they reach the end of their duration, by + * using clutter_timeline_set_repeat_count(); a looping timeline will still + * emit the #ClutterTimeline::completed signal once it reaches the end of its + * duration at each repeat. If you want to be notified of the end of the last + * repeat, use the #ClutterTimeline::stopped signal. + * + * Timelines have a #ClutterTimeline:direction: the default direction is + * %CLUTTER_TIMELINE_FORWARD, and goes from 0 to the duration; it is possible + * to change the direction to %CLUTTER_TIMELINE_BACKWARD, and have the timeline + * go from the duration to 0. The direction can be automatically reversed + * when reaching completion by using the #ClutterTimeline:auto-reverse property. + * + * Timelines are used in the Clutter animation framework by classes like + * #ClutterAnimation, #ClutterAnimator, and #ClutterState. + * + * ## Defining Timelines in ClutterScript + * + * A #ClutterTimeline can be described in #ClutterScript like any + * other object. Additionally, it is possible to define markers directly + * inside the JSON definition by using the `markers` JSON object member, + * such as: + * + * |[ +{ + "type" : "ClutterTimeline", + "duration" : 1000, + "markers" : [ + { "name" : "quarter", "time" : 250 }, + { "name" : "half-time", "time" : 500 }, + { "name" : "three-quarters", "time" : 750 } + ] +} + * ]| + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-timeline.h" + +#include "clutter-debug.h" +#include "clutter-easing.h" +#include "clutter-enum-types.h" +#include "clutter-main.h" +#include "clutter-marshal.h" +#include "clutter-master-clock.h" +#include "clutter-private.h" +#include "clutter-scriptable.h" + +#include "deprecated/clutter-timeline.h" + +struct _ClutterTimelinePrivate +{ + ClutterTimelineDirection direction; + + guint delay_id; + + /* The total length in milliseconds of this timeline */ + guint duration; + guint delay; + + /* The current amount of elapsed time */ + gint64 elapsed_time; + + /* The elapsed time since the last frame was fired */ + gint64 msecs_delta; + + GHashTable *markers_by_name; + + /* Time we last advanced the elapsed time and showed a frame */ + gint64 last_frame_time; + + /* How many times the timeline should repeat */ + gint repeat_count; + + /* The number of times the timeline has repeated */ + gint current_repeat; + + ClutterTimelineProgressFunc progress_func; + gpointer progress_data; + GDestroyNotify progress_notify; + ClutterAnimationMode progress_mode; + + /* step() parameters */ + gint n_steps; + ClutterStepMode step_mode; + + /* cubic-bezier() parameters */ + ClutterPoint cb_1; + ClutterPoint cb_2; + + guint is_playing : 1; + + /* If we've just started playing and haven't yet gotten + * a tick from the master clock + */ + guint waiting_first_tick : 1; + guint auto_reverse : 1; +}; + +typedef struct { + gchar *name; + GQuark quark; + + union { + guint msecs; + gdouble progress; + } data; + + guint is_relative : 1; +} TimelineMarker; + +enum +{ + PROP_0, + + PROP_LOOP, + PROP_DELAY, + PROP_DURATION, + PROP_DIRECTION, + PROP_AUTO_REVERSE, + PROP_REPEAT_COUNT, + PROP_PROGRESS_MODE, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST] = { NULL, }; + +enum +{ + NEW_FRAME, + STARTED, + PAUSED, + COMPLETED, + MARKER_REACHED, + STOPPED, + + LAST_SIGNAL +}; + +static guint timeline_signals[LAST_SIGNAL] = { 0, }; + +static void clutter_scriptable_iface_init (ClutterScriptableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (ClutterTimeline, clutter_timeline, G_TYPE_OBJECT, + G_ADD_PRIVATE (ClutterTimeline) + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_SCRIPTABLE, + clutter_scriptable_iface_init)) + +static TimelineMarker * +timeline_marker_new_time (const gchar *name, + guint msecs) +{ + TimelineMarker *marker = g_slice_new (TimelineMarker); + + marker->name = g_strdup (name); + marker->quark = g_quark_from_string (marker->name); + marker->is_relative = FALSE; + marker->data.msecs = msecs; + + return marker; +} + +static TimelineMarker * +timeline_marker_new_progress (const gchar *name, + gdouble progress) +{ + TimelineMarker *marker = g_slice_new (TimelineMarker); + + marker->name = g_strdup (name); + marker->quark = g_quark_from_string (marker->name); + marker->is_relative = TRUE; + marker->data.progress = CLAMP (progress, 0.0, 1.0); + + return marker; +} + +static void +timeline_marker_free (gpointer data) +{ + if (G_LIKELY (data)) + { + TimelineMarker *marker = data; + + g_free (marker->name); + g_slice_free (TimelineMarker, marker); + } +} + +/*< private > + * clutter_timeline_add_marker_internal: + * @timeline: a #ClutterTimeline + * @marker: a TimelineMarker + * + * Adds @marker into the hash table of markers for @timeline. + * + * The TimelineMarker will either be added or, in case of collisions + * with another existing marker, freed. In any case, this function + * assumes the ownership of the passed @marker. + */ +static inline void +clutter_timeline_add_marker_internal (ClutterTimeline *timeline, + TimelineMarker *marker) +{ + ClutterTimelinePrivate *priv = timeline->priv; + TimelineMarker *old_marker; + + /* create the hash table that will hold the markers */ + if (G_UNLIKELY (priv->markers_by_name == NULL)) + priv->markers_by_name = g_hash_table_new_full (g_str_hash, g_str_equal, + NULL, + timeline_marker_free); + + old_marker = g_hash_table_lookup (priv->markers_by_name, marker->name); + if (old_marker != NULL) + { + guint msecs; + + if (old_marker->is_relative) + msecs = old_marker->data.progress * priv->duration; + else + msecs = old_marker->data.msecs; + + g_warning ("A marker named '%s' already exists at time %d", + old_marker->name, + msecs); + timeline_marker_free (marker); + return; + } + + g_hash_table_insert (priv->markers_by_name, marker->name, marker); +} + +static inline void +clutter_timeline_set_loop_internal (ClutterTimeline *timeline, + gboolean loop) +{ + gint old_repeat_count; + + old_repeat_count = timeline->priv->repeat_count; + + if (loop) + clutter_timeline_set_repeat_count (timeline, -1); + else + clutter_timeline_set_repeat_count (timeline, 0); + + if (old_repeat_count != timeline->priv->repeat_count) + g_object_notify_by_pspec (G_OBJECT (timeline), obj_props[PROP_LOOP]); +} + +/* Scriptable */ +typedef struct _ParseClosure { + ClutterTimeline *timeline; + ClutterScript *script; + GValue *value; + gboolean result; +} ParseClosure; + +static void +parse_timeline_markers (JsonArray *array, + guint index_, + JsonNode *element, + gpointer data) +{ + ParseClosure *clos = data; + JsonObject *object; + TimelineMarker *marker; + GList *markers; + + if (JSON_NODE_TYPE (element) != JSON_NODE_OBJECT) + { + g_warning ("The 'markers' member of a ClutterTimeline description " + "should be an array of objects, but the element %d of the " + "array is of type '%s'. The element will be ignored.", + index_, + json_node_type_name (element)); + return; + } + + object = json_node_get_object (element); + + if (!(json_object_has_member (object, "name") && + (json_object_has_member (object, "time") || + json_object_has_member (object, "progress")))) + { + g_warning ("The marker definition in a ClutterTimeline description " + "must be an object with the 'name' and either the 'time' " + "or the 'progress' members, but the element %d of the " + "'markers' array does not have any of them.", + index_); + return; + } + + if (G_IS_VALUE (clos->value)) + markers = g_value_get_pointer (clos->value); + else + { + g_value_init (clos->value, G_TYPE_POINTER); + markers = NULL; + } + + if (json_object_has_member (object, "time")) + marker = timeline_marker_new_time (json_object_get_string_member (object, "name"), + json_object_get_int_member (object, "time")); + else + marker = timeline_marker_new_progress (json_object_get_string_member (object, "name"), + json_object_get_double_member (object, "progress")); + + markers = g_list_prepend (markers, marker); + + g_value_set_pointer (clos->value, markers); + + clos->result = TRUE; +} + +static gboolean +clutter_timeline_parse_custom_node (ClutterScriptable *scriptable, + ClutterScript *script, + GValue *value, + const gchar *name, + JsonNode *node) +{ + ParseClosure clos; + + if (strcmp (name, "markers") != 0) + return FALSE; + + if (JSON_NODE_TYPE (node) != JSON_NODE_ARRAY) + return FALSE; + + clos.timeline = CLUTTER_TIMELINE (scriptable); + clos.script = script; + clos.value = value; + clos.result = FALSE; + + json_array_foreach_element (json_node_get_array (node), + parse_timeline_markers, + &clos); + + return clos.result; +} + +static void +clutter_timeline_set_custom_property (ClutterScriptable *scriptable, + ClutterScript *script, + const gchar *name, + const GValue *value) +{ + if (strcmp (name, "markers") == 0) + { + ClutterTimeline *timeline = CLUTTER_TIMELINE (scriptable); + GList *markers = g_value_get_pointer (value); + GList *m; + + /* the list was created through prepend() */ + markers = g_list_reverse (markers); + + for (m = markers; m != NULL; m = m->next) + clutter_timeline_add_marker_internal (timeline, m->data); + + g_list_free (markers); + } + else + g_object_set_property (G_OBJECT (scriptable), name, value); +} + + +static void +clutter_scriptable_iface_init (ClutterScriptableIface *iface) +{ + iface->parse_custom_node = clutter_timeline_parse_custom_node; + iface->set_custom_property = clutter_timeline_set_custom_property; +} + +/* Object */ + +static void +clutter_timeline_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterTimeline *timeline = CLUTTER_TIMELINE (object); + + switch (prop_id) + { + case PROP_LOOP: + clutter_timeline_set_loop_internal (timeline, g_value_get_boolean (value)); + break; + + case PROP_DELAY: + clutter_timeline_set_delay (timeline, g_value_get_uint (value)); + break; + + case PROP_DURATION: + clutter_timeline_set_duration (timeline, g_value_get_uint (value)); + break; + + case PROP_DIRECTION: + clutter_timeline_set_direction (timeline, g_value_get_enum (value)); + break; + + case PROP_AUTO_REVERSE: + clutter_timeline_set_auto_reverse (timeline, g_value_get_boolean (value)); + break; + + case PROP_REPEAT_COUNT: + clutter_timeline_set_repeat_count (timeline, g_value_get_int (value)); + break; + + case PROP_PROGRESS_MODE: + clutter_timeline_set_progress_mode (timeline, g_value_get_enum (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_timeline_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterTimeline *timeline = CLUTTER_TIMELINE (object); + ClutterTimelinePrivate *priv = timeline->priv; + + switch (prop_id) + { + case PROP_LOOP: + g_value_set_boolean (value, priv->repeat_count != 0); + break; + + case PROP_DELAY: + g_value_set_uint (value, priv->delay); + break; + + case PROP_DURATION: + g_value_set_uint (value, clutter_timeline_get_duration (timeline)); + break; + + case PROP_DIRECTION: + g_value_set_enum (value, priv->direction); + break; + + case PROP_AUTO_REVERSE: + g_value_set_boolean (value, priv->auto_reverse); + break; + + case PROP_REPEAT_COUNT: + g_value_set_int (value, priv->repeat_count); + break; + + case PROP_PROGRESS_MODE: + g_value_set_enum (value, priv->progress_mode); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_timeline_finalize (GObject *object) +{ + ClutterTimeline *self = CLUTTER_TIMELINE (object); + ClutterTimelinePrivate *priv = self->priv; + ClutterMasterClock *master_clock; + + if (priv->markers_by_name) + g_hash_table_destroy (priv->markers_by_name); + + if (priv->is_playing) + { + master_clock = _clutter_master_clock_get_default (); + _clutter_master_clock_remove_timeline (master_clock, self); + } + + G_OBJECT_CLASS (clutter_timeline_parent_class)->finalize (object); +} + +static void +clutter_timeline_dispose (GObject *object) +{ + ClutterTimeline *self = CLUTTER_TIMELINE(object); + ClutterTimelinePrivate *priv; + + priv = self->priv; + + if (priv->delay_id) + { + g_source_remove (priv->delay_id); + priv->delay_id = 0; + } + + if (priv->progress_notify != NULL) + { + priv->progress_notify (priv->progress_data); + priv->progress_func = NULL; + priv->progress_data = NULL; + priv->progress_notify = NULL; + } + + G_OBJECT_CLASS (clutter_timeline_parent_class)->dispose (object); +} + +static void +clutter_timeline_class_init (ClutterTimelineClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + /** + * ClutterTimeline:loop: + * + * Whether the timeline should automatically rewind and restart. + * + * As a side effect, setting this property to %TRUE will set the + * #ClutterTimeline:repeat-count property to -1, while setting this + * property to %FALSE will set the #ClutterTimeline:repeat-count + * property to 0. + * + * Deprecated: 1.10: Use the #ClutterTimeline:repeat-count property instead. + */ + obj_props[PROP_LOOP] = + g_param_spec_boolean ("loop", + P_("Loop"), + P_("Should the timeline automatically restart"), + FALSE, + CLUTTER_PARAM_READWRITE | G_PARAM_DEPRECATED); + + /** + * ClutterTimeline:delay: + * + * A delay, in milliseconds, that should be observed by the + * timeline before actually starting. + * + * Since: 0.4 + */ + obj_props[PROP_DELAY] = + g_param_spec_uint ("delay", + P_("Delay"), + P_("Delay before start"), + 0, G_MAXUINT, + 0, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterTimeline:duration: + * + * Duration of the timeline in milliseconds, depending on the + * ClutterTimeline:fps value. + * + * Since: 0.6 + */ + obj_props[PROP_DURATION] = + g_param_spec_uint ("duration", + P_("Duration"), + P_("Duration of the timeline in milliseconds"), + 0, G_MAXUINT, + 1000, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterTimeline:direction: + * + * The direction of the timeline, either %CLUTTER_TIMELINE_FORWARD or + * %CLUTTER_TIMELINE_BACKWARD. + * + * Since: 0.6 + */ + obj_props[PROP_DIRECTION] = + g_param_spec_enum ("direction", + P_("Direction"), + P_("Direction of the timeline"), + CLUTTER_TYPE_TIMELINE_DIRECTION, + CLUTTER_TIMELINE_FORWARD, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterTimeline:auto-reverse: + * + * If the direction of the timeline should be automatically reversed + * when reaching the end. + * + * Since: 1.6 + */ + obj_props[PROP_AUTO_REVERSE] = + g_param_spec_boolean ("auto-reverse", + P_("Auto Reverse"), + P_("Whether the direction should be reversed when reaching the end"), + FALSE, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterTimeline:repeat-count: + * + * Defines how many times the timeline should repeat. + * + * If the repeat count is 0, the timeline does not repeat. + * + * If the repeat count is set to -1, the timeline will repeat until it is + * stopped. + * + * Since: 1.10 + */ + obj_props[PROP_REPEAT_COUNT] = + g_param_spec_int ("repeat-count", + P_("Repeat Count"), + P_("How many times the timeline should repeat"), + -1, G_MAXINT, + 0, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterTimeline:progress-mode: + * + * Controls the way a #ClutterTimeline computes the normalized progress. + * + * Since: 1.10 + */ + obj_props[PROP_PROGRESS_MODE] = + g_param_spec_enum ("progress-mode", + P_("Progress Mode"), + P_("How the timeline should compute the progress"), + CLUTTER_TYPE_ANIMATION_MODE, + CLUTTER_LINEAR, + CLUTTER_PARAM_READWRITE); + + object_class->dispose = clutter_timeline_dispose; + object_class->finalize = clutter_timeline_finalize; + object_class->set_property = clutter_timeline_set_property; + object_class->get_property = clutter_timeline_get_property; + g_object_class_install_properties (object_class, PROP_LAST, obj_props); + + /** + * ClutterTimeline::new-frame: + * @timeline: the timeline which received the signal + * @msecs: the elapsed time between 0 and duration + * + * The ::new-frame signal is emitted for each timeline running + * timeline before a new frame is drawn to give animations a chance + * to update the scene. + */ + timeline_signals[NEW_FRAME] = + g_signal_new (I_("new-frame"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterTimelineClass, new_frame), + NULL, NULL, + _clutter_marshal_VOID__INT, + G_TYPE_NONE, + 1, G_TYPE_INT); + /** + * ClutterTimeline::completed: + * @timeline: the #ClutterTimeline which received the signal + * + * The #ClutterTimeline::completed signal is emitted when the timeline's + * elapsed time reaches the value of the #ClutterTimeline:duration + * property. + * + * This signal will be emitted even if the #ClutterTimeline is set to be + * repeating. + * + * If you want to get notification on whether the #ClutterTimeline has + * been stopped or has finished its run, including its eventual repeats, + * you should use the #ClutterTimeline::stopped signal instead. + */ + timeline_signals[COMPLETED] = + g_signal_new (I_("completed"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterTimelineClass, completed), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + /** + * ClutterTimeline::started: + * @timeline: the #ClutterTimeline which received the signal + * + * The ::started signal is emitted when the timeline starts its run. + * This might be as soon as clutter_timeline_start() is invoked or + * after the delay set in the ClutterTimeline:delay property has + * expired. + */ + timeline_signals[STARTED] = + g_signal_new (I_("started"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterTimelineClass, started), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + /** + * ClutterTimeline::paused: + * @timeline: the #ClutterTimeline which received the signal + * + * The ::paused signal is emitted when clutter_timeline_pause() is invoked. + */ + timeline_signals[PAUSED] = + g_signal_new (I_("paused"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterTimelineClass, paused), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + /** + * ClutterTimeline::marker-reached: + * @timeline: the #ClutterTimeline which received the signal + * @marker_name: the name of the marker reached + * @msecs: the elapsed time + * + * The ::marker-reached signal is emitted each time a timeline + * reaches a marker set with + * clutter_timeline_add_marker_at_time(). This signal is detailed + * with the name of the marker as well, so it is possible to connect + * a callback to the ::marker-reached signal for a specific marker + * with: + * + * + * clutter_timeline_add_marker_at_time (timeline, "foo", 500); + * clutter_timeline_add_marker_at_time (timeline, "bar", 750); + * + * g_signal_connect (timeline, "marker-reached", + * G_CALLBACK (each_marker_reached), NULL); + * g_signal_connect (timeline, "marker-reached::foo", + * G_CALLBACK (foo_marker_reached), NULL); + * g_signal_connect (timeline, "marker-reached::bar", + * G_CALLBACK (bar_marker_reached), NULL); + * + * + * In the example, the first callback will be invoked for both + * the "foo" and "bar" marker, while the second and third callbacks + * will be invoked for the "foo" or "bar" markers, respectively. + * + * Since: 0.8 + */ + timeline_signals[MARKER_REACHED] = + g_signal_new (I_("marker-reached"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | + G_SIGNAL_DETAILED | G_SIGNAL_NO_HOOKS, + G_STRUCT_OFFSET (ClutterTimelineClass, marker_reached), + NULL, NULL, + _clutter_marshal_VOID__STRING_INT, + G_TYPE_NONE, 2, + G_TYPE_STRING, + G_TYPE_INT); + /** + * ClutterTimeline::stopped: + * @timeline: the #ClutterTimeline that emitted the signal + * @is_finished: %TRUE if the signal was emitted at the end of the + * timeline. + * + * The #ClutterTimeline::stopped signal is emitted when the timeline + * has been stopped, either because clutter_timeline_stop() has been + * called, or because it has been exhausted. + * + * This is different from the #ClutterTimeline::completed signal, + * which gets emitted after every repeat finishes. + * + * If the #ClutterTimeline has is marked as infinitely repeating, + * this signal will never be emitted. + * + * Since: 1.12 + */ + timeline_signals[STOPPED] = + g_signal_new (I_("stopped"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterTimelineClass, stopped), + NULL, NULL, + _clutter_marshal_VOID__BOOLEAN, + G_TYPE_NONE, 1, + G_TYPE_BOOLEAN); +} + +static void +clutter_timeline_init (ClutterTimeline *self) +{ + self->priv = clutter_timeline_get_instance_private (self); + + self->priv->progress_mode = CLUTTER_LINEAR; + + /* default steps() parameters are 1, end */ + self->priv->n_steps = 1; + self->priv->step_mode = CLUTTER_STEP_MODE_END; + + /* default cubic-bezier() paramereters are (0, 0, 1, 1) */ + clutter_point_init (&self->priv->cb_1, 0, 0); + clutter_point_init (&self->priv->cb_2, 1, 1); +} + +struct CheckIfMarkerHitClosure +{ + ClutterTimeline *timeline; + ClutterTimelineDirection direction; + gint new_time; + gint duration; + gint delta; +}; + +static gboolean +have_passed_time (const struct CheckIfMarkerHitClosure *data, + gint msecs) +{ + /* Ignore markers that are outside the duration of the timeline */ + if (msecs < 0 || msecs > data->duration) + return FALSE; + + if (data->direction == CLUTTER_TIMELINE_FORWARD) + { + /* We need to special case when a marker is added at the + beginning of the timeline */ + if (msecs == 0 && + data->delta > 0 && + data->new_time - data->delta <= 0) + return TRUE; + + /* Otherwise it's just a simple test if the time is in range of + the previous time and the new time */ + return (msecs > data->new_time - data->delta && + msecs <= data->new_time); + } + else + { + /* We need to special case when a marker is added at the + end of the timeline */ + if (msecs == data->duration && + data->delta > 0 && + data->new_time + data->delta >= data->duration) + return TRUE; + + /* Otherwise it's just a simple test if the time is in range of + the previous time and the new time */ + return (msecs >= data->new_time && + msecs < data->new_time + data->delta); + } +} + +static void +check_if_marker_hit (const gchar *name, + TimelineMarker *marker, + struct CheckIfMarkerHitClosure *data) +{ + gint msecs; + + if (marker->is_relative) + msecs = (gdouble) data->duration * marker->data.progress; + else + msecs = marker->data.msecs; + + if (have_passed_time (data, msecs)) + { + CLUTTER_NOTE (SCHEDULER, "Marker '%s' reached", name); + + g_signal_emit (data->timeline, timeline_signals[MARKER_REACHED], + marker->quark, + name, + msecs); + } +} + +static void +check_markers (ClutterTimeline *timeline, + gint delta) +{ + ClutterTimelinePrivate *priv = timeline->priv; + struct CheckIfMarkerHitClosure data; + + /* shortcircuit here if we don't have any marker installed */ + if (priv->markers_by_name == NULL) + return; + + /* store the details of the timeline so that changing them in a + marker signal handler won't affect which markers are hit */ + data.timeline = timeline; + data.direction = priv->direction; + data.new_time = priv->elapsed_time; + data.duration = priv->duration; + data.delta = delta; + + g_hash_table_foreach (priv->markers_by_name, + (GHFunc) check_if_marker_hit, + &data); +} + +static void +emit_frame_signal (ClutterTimeline *timeline) +{ + ClutterTimelinePrivate *priv = timeline->priv; + + /* see bug https://bugzilla.gnome.org/show_bug.cgi?id=654066 */ + gint elapsed = (gint) priv->elapsed_time; + + CLUTTER_NOTE (SCHEDULER, "Emitting ::new-frame signal on timeline[%p]", timeline); + + g_signal_emit (timeline, timeline_signals[NEW_FRAME], 0, elapsed); +} + +static gboolean +is_complete (ClutterTimeline *timeline) +{ + ClutterTimelinePrivate *priv = timeline->priv; + + return (priv->direction == CLUTTER_TIMELINE_FORWARD + ? priv->elapsed_time >= priv->duration + : priv->elapsed_time <= 0); +} + +static void +set_is_playing (ClutterTimeline *timeline, + gboolean is_playing) +{ + ClutterTimelinePrivate *priv = timeline->priv; + ClutterMasterClock *master_clock; + + is_playing = !!is_playing; + + if (is_playing == priv->is_playing) + return; + + priv->is_playing = is_playing; + + master_clock = _clutter_master_clock_get_default (); + if (priv->is_playing) + { + priv->waiting_first_tick = TRUE; + priv->current_repeat = 0; + _clutter_master_clock_add_timeline (master_clock, timeline); + } + else + _clutter_master_clock_remove_timeline (master_clock, timeline); +} + +static gboolean +clutter_timeline_do_frame (ClutterTimeline *timeline) +{ + ClutterTimelinePrivate *priv; + + priv = timeline->priv; + + g_object_ref (timeline); + + CLUTTER_NOTE (SCHEDULER, "Timeline [%p] activated (elapsed time: %ld, " + "duration: %ld, msecs_delta: %ld)\n", + timeline, + (long) priv->elapsed_time, + (long) priv->duration, + (long) priv->msecs_delta); + + /* Advance time */ + if (priv->direction == CLUTTER_TIMELINE_FORWARD) + priv->elapsed_time += priv->msecs_delta; + else + priv->elapsed_time -= priv->msecs_delta; + + /* If we have not reached the end of the timeline: */ + if (!is_complete (timeline)) + { + /* Emit the signal */ + emit_frame_signal (timeline); + check_markers (timeline, priv->msecs_delta); + + g_object_unref (timeline); + + return priv->is_playing; + } + else + { + /* Handle loop or stop */ + ClutterTimelineDirection saved_direction = priv->direction; + gint elapsed_time_delta = priv->msecs_delta; + guint overflow_msecs = priv->elapsed_time; + gint end_msecs; + + /* Update the current elapsed time in case the signal handlers + * want to take a peek. If we clamp elapsed time, then we need + * to correpondingly reduce elapsed_time_delta to reflect the correct + * range of times */ + if (priv->direction == CLUTTER_TIMELINE_FORWARD) + { + elapsed_time_delta -= (priv->elapsed_time - priv->duration); + priv->elapsed_time = priv->duration; + } + else if (priv->direction == CLUTTER_TIMELINE_BACKWARD) + { + elapsed_time_delta -= - priv->elapsed_time; + priv->elapsed_time = 0; + } + + end_msecs = priv->elapsed_time; + + /* Emit the signal */ + emit_frame_signal (timeline); + check_markers (timeline, elapsed_time_delta); + + /* Did the signal handler modify the elapsed time? */ + if (priv->elapsed_time != end_msecs) + { + g_object_unref (timeline); + return TRUE; + } + + /* Note: If the new-frame signal handler paused the timeline + * on the last frame we will still go ahead and send the + * completed signal */ + CLUTTER_NOTE (SCHEDULER, + "Timeline [%p] completed (cur: %ld, tot: %ld)", + timeline, + (long) priv->elapsed_time, + (long) priv->msecs_delta); + + if (priv->is_playing && + (priv->repeat_count == 0 || + priv->repeat_count == priv->current_repeat)) + { + /* We stop the timeline now, so that the completed signal handler + * may choose to re-start the timeline + * + * XXX Perhaps we should do this earlier, and regardless of + * priv->repeat_count. Are we limiting the things that could be + * done in the above new-frame signal handler? + */ + set_is_playing (timeline, FALSE); + + g_signal_emit (timeline, timeline_signals[COMPLETED], 0); + g_signal_emit (timeline, timeline_signals[STOPPED], 0, TRUE); + } + else + g_signal_emit (timeline, timeline_signals[COMPLETED], 0); + + priv->current_repeat += 1; + + if (priv->auto_reverse) + { + /* :auto-reverse changes the direction of the timeline */ + if (priv->direction == CLUTTER_TIMELINE_FORWARD) + priv->direction = CLUTTER_TIMELINE_BACKWARD; + else + priv->direction = CLUTTER_TIMELINE_FORWARD; + + g_object_notify_by_pspec (G_OBJECT (timeline), + obj_props[PROP_DIRECTION]); + } + + /* Again check to see if the user has manually played with + * the elapsed time, before we finally stop or loop the timeline */ + + if (priv->elapsed_time != end_msecs && + !(/* Except allow changing time from 0 -> duration (or vice-versa) + since these are considered equivalent */ + (priv->elapsed_time == 0 && end_msecs == priv->duration) || + (priv->elapsed_time == priv->duration && end_msecs == 0) + )) + { + g_object_unref (timeline); + return TRUE; + } + + if (priv->repeat_count != 0) + { + /* We try and interpolate smoothly around a loop */ + if (saved_direction == CLUTTER_TIMELINE_FORWARD) + priv->elapsed_time = overflow_msecs - priv->duration; + else + priv->elapsed_time = priv->duration + overflow_msecs; + + /* Or if the direction changed, we try and bounce */ + if (priv->direction != saved_direction) + priv->elapsed_time = priv->duration - priv->elapsed_time; + + /* If we have overflowed then we are changing the elapsed + time without emitting the new frame signal so we need to + check for markers again */ + check_markers (timeline, + priv->direction == CLUTTER_TIMELINE_FORWARD + ? priv->elapsed_time + : priv->duration - priv->elapsed_time); + + g_object_unref (timeline); + return TRUE; + } + else + { + clutter_timeline_rewind (timeline); + + g_object_unref (timeline); + return FALSE; + } + } +} + +static gboolean +delay_timeout_func (gpointer data) +{ + ClutterTimeline *timeline = data; + ClutterTimelinePrivate *priv = timeline->priv; + + priv->delay_id = 0; + priv->msecs_delta = 0; + set_is_playing (timeline, TRUE); + + g_signal_emit (timeline, timeline_signals[STARTED], 0); + + return FALSE; +} + +/** + * clutter_timeline_start: + * @timeline: A #ClutterTimeline + * + * Starts the #ClutterTimeline playing. + **/ +void +clutter_timeline_start (ClutterTimeline *timeline) +{ + ClutterTimelinePrivate *priv; + + g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); + + priv = timeline->priv; + + if (priv->delay_id || priv->is_playing) + return; + + if (priv->duration == 0) + return; + + if (priv->delay) + priv->delay_id = clutter_threads_add_timeout (priv->delay, + delay_timeout_func, + timeline); + else + { + priv->msecs_delta = 0; + set_is_playing (timeline, TRUE); + + g_signal_emit (timeline, timeline_signals[STARTED], 0); + } +} + +/** + * clutter_timeline_pause: + * @timeline: A #ClutterTimeline + * + * Pauses the #ClutterTimeline on current frame + **/ +void +clutter_timeline_pause (ClutterTimeline *timeline) +{ + ClutterTimelinePrivate *priv; + + g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); + + priv = timeline->priv; + + if (priv->delay_id == 0 && !priv->is_playing) + return; + + if (priv->delay_id) + { + g_source_remove (priv->delay_id); + priv->delay_id = 0; + } + + priv->msecs_delta = 0; + set_is_playing (timeline, FALSE); + + g_signal_emit (timeline, timeline_signals[PAUSED], 0); +} + +/** + * clutter_timeline_stop: + * @timeline: A #ClutterTimeline + * + * Stops the #ClutterTimeline and moves to frame 0 + **/ +void +clutter_timeline_stop (ClutterTimeline *timeline) +{ + gboolean was_playing; + + g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); + + /* we check the is_playing here because pause() will return immediately + * if the timeline wasn't playing, so we don't know if it was actually + * stopped, and yet we still don't want to emit a ::stopped signal if + * the timeline was not playing in the first place. + */ + was_playing = timeline->priv->is_playing; + + clutter_timeline_pause (timeline); + clutter_timeline_rewind (timeline); + + if (was_playing) + g_signal_emit (timeline, timeline_signals[STOPPED], 0, FALSE); +} + +/** + * clutter_timeline_set_loop: + * @timeline: a #ClutterTimeline + * @loop: %TRUE for enable looping + * + * Sets whether @timeline should loop. + * + * This function is equivalent to calling clutter_timeline_set_repeat_count() + * with -1 if @loop is %TRUE, and with 0 if @loop is %FALSE. + * + * Deprecated: 1.10: Use clutter_timeline_set_repeat_count() instead. + */ +void +clutter_timeline_set_loop (ClutterTimeline *timeline, + gboolean loop) +{ + g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); + + clutter_timeline_set_loop_internal (timeline, loop); +} + +/** + * clutter_timeline_get_loop: + * @timeline: a #ClutterTimeline + * + * Gets whether @timeline is looping + * + * Return value: %TRUE if the timeline is looping + * + * Deprecated: 1.10: Use clutter_timeline_get_repeat_count() instead. + */ +gboolean +clutter_timeline_get_loop (ClutterTimeline *timeline) +{ + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), FALSE); + + return timeline->priv->repeat_count != 0; +} + +/** + * clutter_timeline_rewind: + * @timeline: A #ClutterTimeline + * + * Rewinds #ClutterTimeline to the first frame if its direction is + * %CLUTTER_TIMELINE_FORWARD and the last frame if it is + * %CLUTTER_TIMELINE_BACKWARD. + */ +void +clutter_timeline_rewind (ClutterTimeline *timeline) +{ + ClutterTimelinePrivate *priv; + + g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); + + priv = timeline->priv; + + if (priv->direction == CLUTTER_TIMELINE_FORWARD) + clutter_timeline_advance (timeline, 0); + else if (priv->direction == CLUTTER_TIMELINE_BACKWARD) + clutter_timeline_advance (timeline, priv->duration); +} + +/** + * clutter_timeline_skip: + * @timeline: A #ClutterTimeline + * @msecs: Amount of time to skip + * + * Advance timeline by the requested time in milliseconds + */ +void +clutter_timeline_skip (ClutterTimeline *timeline, + guint msecs) +{ + ClutterTimelinePrivate *priv; + + g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); + + priv = timeline->priv; + + if (priv->direction == CLUTTER_TIMELINE_FORWARD) + { + priv->elapsed_time += msecs; + + if (priv->elapsed_time > priv->duration) + priv->elapsed_time = 1; + } + else if (priv->direction == CLUTTER_TIMELINE_BACKWARD) + { + priv->elapsed_time -= msecs; + + if (priv->elapsed_time < 1) + priv->elapsed_time = priv->duration - 1; + } + + priv->msecs_delta = 0; +} + +/** + * clutter_timeline_advance: + * @timeline: A #ClutterTimeline + * @msecs: Time to advance to + * + * Advance timeline to the requested point. The point is given as a + * time in milliseconds since the timeline started. + * + * The @timeline will not emit the #ClutterTimeline::new-frame + * signal for the given time. The first ::new-frame signal after the call to + * clutter_timeline_advance() will be emit the skipped markers. + */ +void +clutter_timeline_advance (ClutterTimeline *timeline, + guint msecs) +{ + ClutterTimelinePrivate *priv; + + g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); + + priv = timeline->priv; + + priv->elapsed_time = CLAMP (msecs, 0, priv->duration); +} + +/** + * clutter_timeline_get_elapsed_time: + * @timeline: A #ClutterTimeline + * + * Request the current time position of the timeline. + * + * Return value: current elapsed time in milliseconds. + */ +guint +clutter_timeline_get_elapsed_time (ClutterTimeline *timeline) +{ + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), 0); + + return timeline->priv->elapsed_time; +} + +/** + * clutter_timeline_is_playing: + * @timeline: A #ClutterTimeline + * + * Queries state of a #ClutterTimeline. + * + * Return value: %TRUE if timeline is currently playing + */ +gboolean +clutter_timeline_is_playing (ClutterTimeline *timeline) +{ + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), FALSE); + + return timeline->priv->is_playing; +} + +/** + * clutter_timeline_clone: + * @timeline: #ClutterTimeline to duplicate. + * + * Create a new #ClutterTimeline instance which has property values + * matching that of supplied timeline. The cloned timeline will not + * be started and will not be positioned to the current position of + * the original @timeline: you will have to start it with + * clutter_timeline_start(). + * + * The only cloned properties are: + * + * - #ClutterTimeline:duration + * - #ClutterTimeline:loop + * - #ClutterTimeline:delay + * - #ClutterTimeline:direction + * + * Return value: (transfer full): a new #ClutterTimeline, cloned + * from @timeline + * + * Since: 0.4 + * + * Deprecated: 1.10: Use clutter_timeline_new() or g_object_new() + * instead + */ +ClutterTimeline * +clutter_timeline_clone (ClutterTimeline *timeline) +{ + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), NULL); + + return g_object_new (CLUTTER_TYPE_TIMELINE, + "duration", timeline->priv->duration, + "loop", timeline->priv->repeat_count != 0, + "delay", timeline->priv->delay, + "direction", timeline->priv->direction, + NULL); +} + +/** + * clutter_timeline_new: + * @msecs: Duration of the timeline in milliseconds + * + * Creates a new #ClutterTimeline with a duration of @msecs. + * + * Return value: the newly created #ClutterTimeline instance. Use + * g_object_unref() when done using it + * + * Since: 0.6 + */ +ClutterTimeline * +clutter_timeline_new (guint msecs) +{ + return g_object_new (CLUTTER_TYPE_TIMELINE, + "duration", msecs, + NULL); +} + +/** + * clutter_timeline_get_delay: + * @timeline: a #ClutterTimeline + * + * Retrieves the delay set using clutter_timeline_set_delay(). + * + * Return value: the delay in milliseconds. + * + * Since: 0.4 + */ +guint +clutter_timeline_get_delay (ClutterTimeline *timeline) +{ + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), 0); + + return timeline->priv->delay; +} + +/** + * clutter_timeline_set_delay: + * @timeline: a #ClutterTimeline + * @msecs: delay in milliseconds + * + * Sets the delay, in milliseconds, before @timeline should start. + * + * Since: 0.4 + */ +void +clutter_timeline_set_delay (ClutterTimeline *timeline, + guint msecs) +{ + ClutterTimelinePrivate *priv; + + g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); + + priv = timeline->priv; + + if (priv->delay != msecs) + { + priv->delay = msecs; + g_object_notify_by_pspec (G_OBJECT (timeline), obj_props[PROP_DELAY]); + } +} + +/** + * clutter_timeline_get_duration: + * @timeline: a #ClutterTimeline + * + * Retrieves the duration of a #ClutterTimeline in milliseconds. + * See clutter_timeline_set_duration(). + * + * Return value: the duration of the timeline, in milliseconds. + * + * Since: 0.6 + */ +guint +clutter_timeline_get_duration (ClutterTimeline *timeline) +{ + ClutterTimelinePrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), 0); + + priv = timeline->priv; + + return priv->duration; +} + +/** + * clutter_timeline_set_duration: + * @timeline: a #ClutterTimeline + * @msecs: duration of the timeline in milliseconds + * + * Sets the duration of the timeline, in milliseconds. The speed + * of the timeline depends on the ClutterTimeline:fps setting. + * + * Since: 0.6 + */ +void +clutter_timeline_set_duration (ClutterTimeline *timeline, + guint msecs) +{ + ClutterTimelinePrivate *priv; + + g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); + g_return_if_fail (msecs > 0); + + priv = timeline->priv; + + if (priv->duration != msecs) + { + priv->duration = msecs; + + g_object_notify_by_pspec (G_OBJECT (timeline), obj_props[PROP_DURATION]); + } +} + +/** + * clutter_timeline_get_progress: + * @timeline: a #ClutterTimeline + * + * The position of the timeline in a normalized [-1, 2] interval. + * + * The return value of this function is determined by the progress + * mode set using clutter_timeline_set_progress_mode(), or by the + * progress function set using clutter_timeline_set_progress_func(). + * + * Return value: the normalized current position in the timeline. + * + * Since: 0.6 + */ +gdouble +clutter_timeline_get_progress (ClutterTimeline *timeline) +{ + ClutterTimelinePrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), 0.0); + + priv = timeline->priv; + + /* short-circuit linear progress */ + if (priv->progress_func == NULL) + return (gdouble) priv->elapsed_time / (gdouble) priv->duration; + else + return priv->progress_func (timeline, + (gdouble) priv->elapsed_time, + (gdouble) priv->duration, + priv->progress_data); +} + +/** + * clutter_timeline_get_direction: + * @timeline: a #ClutterTimeline + * + * Retrieves the direction of the timeline set with + * clutter_timeline_set_direction(). + * + * Return value: the direction of the timeline + * + * Since: 0.6 + */ +ClutterTimelineDirection +clutter_timeline_get_direction (ClutterTimeline *timeline) +{ + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), + CLUTTER_TIMELINE_FORWARD); + + return timeline->priv->direction; +} + +/** + * clutter_timeline_set_direction: + * @timeline: a #ClutterTimeline + * @direction: the direction of the timeline + * + * Sets the direction of @timeline, either %CLUTTER_TIMELINE_FORWARD or + * %CLUTTER_TIMELINE_BACKWARD. + * + * Since: 0.6 + */ +void +clutter_timeline_set_direction (ClutterTimeline *timeline, + ClutterTimelineDirection direction) +{ + ClutterTimelinePrivate *priv; + + g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); + + priv = timeline->priv; + + if (priv->direction != direction) + { + priv->direction = direction; + + if (priv->elapsed_time == 0) + priv->elapsed_time = priv->duration; + + g_object_notify_by_pspec (G_OBJECT (timeline), obj_props[PROP_DIRECTION]); + } +} + +/** + * clutter_timeline_get_delta: + * @timeline: a #ClutterTimeline + * + * Retrieves the amount of time elapsed since the last + * ClutterTimeline::new-frame signal. + * + * This function is only useful inside handlers for the ::new-frame + * signal, and its behaviour is undefined if the timeline is not + * playing. + * + * Return value: the amount of time in milliseconds elapsed since the + * last frame + * + * Since: 0.6 + */ +guint +clutter_timeline_get_delta (ClutterTimeline *timeline) +{ + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), 0); + + if (!clutter_timeline_is_playing (timeline)) + return 0; + + return timeline->priv->msecs_delta; +} + +void +_clutter_timeline_advance (ClutterTimeline *timeline, + gint64 tick_time) +{ + ClutterTimelinePrivate *priv = timeline->priv; + + g_object_ref (timeline); + + CLUTTER_NOTE (SCHEDULER, + "Timeline [%p] advancing (cur: %ld, tot: %ld, " + "tick_time: %lu)", + timeline, + (long) priv->elapsed_time, + (long) priv->msecs_delta, + (long) tick_time); + + priv->msecs_delta = tick_time; + priv->is_playing = TRUE; + + clutter_timeline_do_frame (timeline); + + priv->is_playing = FALSE; + + g_object_unref (timeline); +} + +/*< private > + * clutter_timeline_do_tick + * @timeline: a #ClutterTimeline + * @tick_time: time of advance + * + * Advances @timeline based on the time passed in @tick_time. This + * function is called by the master clock. The @timeline will use this + * interval to emit the #ClutterTimeline::new-frame signal and + * eventually skip frames. + */ +void +_clutter_timeline_do_tick (ClutterTimeline *timeline, + gint64 tick_time) +{ + ClutterTimelinePrivate *priv; + + priv = timeline->priv; + + CLUTTER_NOTE (SCHEDULER, + "Timeline [%p] ticked (elapsed_time: %ld, msecs_delta: %ld, " + "last_frame_time: %ld, tick_time: %ld)", + timeline, + (long) priv->elapsed_time, + (long) priv->msecs_delta, + (long) priv->last_frame_time, + (long) tick_time); + + /* Check the is_playing variable before performing the timeline tick. + * This is necessary, as if a timeline is stopped in response to a + * master-clock generated signal of a different timeline, this code can + * still be reached. + */ + if (!priv->is_playing) + return; + + if (priv->waiting_first_tick) + { + priv->last_frame_time = tick_time; + priv->msecs_delta = 0; + priv->waiting_first_tick = FALSE; + clutter_timeline_do_frame (timeline); + } + else + { + gint64 msecs; + + msecs = tick_time - priv->last_frame_time; + + /* if the clock rolled back between ticks we need to + * account for it; the best course of action, since the + * clock roll back can happen by any arbitrary amount + * of milliseconds, is to drop a frame here + */ + if (msecs < 0) + { + priv->last_frame_time = tick_time; + return; + } + + if (msecs != 0) + { + /* Avoid accumulating error */ + priv->last_frame_time += msecs; + priv->msecs_delta = msecs; + clutter_timeline_do_frame (timeline); + } + } +} + +/** + * clutter_timeline_add_marker: + * @timeline: a #ClutterTimeline + * @marker_name: the unique name for this marker + * @progress: the normalized value of the position of the martke + * + * Adds a named marker that will be hit when the timeline has reached + * the specified @progress. + * + * Markers are unique string identifiers for a given position on the + * timeline. Once @timeline reaches the given @progress of its duration, + * if will emit a ::marker-reached signal for each marker attached to + * that particular point. + * + * A marker can be removed with clutter_timeline_remove_marker(). The + * timeline can be advanced to a marker using + * clutter_timeline_advance_to_marker(). + * + * See also: clutter_timeline_add_marker_at_time() + * + * Since: 1.14 + */ +void +clutter_timeline_add_marker (ClutterTimeline *timeline, + const gchar *marker_name, + gdouble progress) +{ + TimelineMarker *marker; + + g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); + g_return_if_fail (marker_name != NULL); + + marker = timeline_marker_new_progress (marker_name, progress); + clutter_timeline_add_marker_internal (timeline, marker); +} + +/** + * clutter_timeline_add_marker_at_time: + * @timeline: a #ClutterTimeline + * @marker_name: the unique name for this marker + * @msecs: position of the marker in milliseconds + * + * Adds a named marker that will be hit when the timeline has been + * running for @msecs milliseconds. + * + * Markers are unique string identifiers for a given position on the + * timeline. Once @timeline reaches the given @msecs, it will emit + * a ::marker-reached signal for each marker attached to that position. + * + * A marker can be removed with clutter_timeline_remove_marker(). The + * timeline can be advanced to a marker using + * clutter_timeline_advance_to_marker(). + * + * See also: clutter_timeline_add_marker() + * + * Since: 0.8 + */ +void +clutter_timeline_add_marker_at_time (ClutterTimeline *timeline, + const gchar *marker_name, + guint msecs) +{ + TimelineMarker *marker; + + g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); + g_return_if_fail (marker_name != NULL); + g_return_if_fail (msecs <= clutter_timeline_get_duration (timeline)); + + marker = timeline_marker_new_time (marker_name, msecs); + clutter_timeline_add_marker_internal (timeline, marker); +} + +struct CollectMarkersClosure +{ + guint duration; + guint msecs; + GArray *markers; +}; + +static void +collect_markers (const gchar *key, + TimelineMarker *marker, + struct CollectMarkersClosure *data) +{ + guint msecs; + + if (marker->is_relative) + msecs = marker->data.progress * data->duration; + else + msecs = marker->data.msecs; + + if (msecs == data->msecs) + { + gchar *name_copy = g_strdup (key); + g_array_append_val (data->markers, name_copy); + } +} + +/** + * clutter_timeline_list_markers: + * @timeline: a #ClutterTimeline + * @msecs: the time to check, or -1 + * @n_markers: the number of markers returned + * + * Retrieves the list of markers at time @msecs. If @msecs is a + * negative integer, all the markers attached to @timeline will be + * returned. + * + * Return value: (transfer full) (array zero-terminated=1 length=n_markers): + * a newly allocated, %NULL terminated string array containing the names + * of the markers. Use g_strfreev() when done. + * + * Since: 0.8 + */ +gchar ** +clutter_timeline_list_markers (ClutterTimeline *timeline, + gint msecs, + gsize *n_markers) +{ + ClutterTimelinePrivate *priv; + gchar **retval = NULL; + gsize i; + + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), NULL); + + priv = timeline->priv; + + if (G_UNLIKELY (priv->markers_by_name == NULL)) + { + if (n_markers) + *n_markers = 0; + + return NULL; + } + + if (msecs < 0) + { + GList *markers, *l; + + markers = g_hash_table_get_keys (priv->markers_by_name); + retval = g_new0 (gchar*, g_list_length (markers) + 1); + + for (i = 0, l = markers; l != NULL; i++, l = l->next) + retval[i] = g_strdup (l->data); + + g_list_free (markers); + } + else + { + struct CollectMarkersClosure data; + + data.duration = priv->duration; + data.msecs = msecs; + data.markers = g_array_new (TRUE, FALSE, sizeof (gchar *)); + + g_hash_table_foreach (priv->markers_by_name, + (GHFunc) collect_markers, + &data); + + i = data.markers->len; + retval = (gchar **) (void *) g_array_free (data.markers, FALSE); + } + + if (n_markers) + *n_markers = i; + + return retval; +} + +/** + * clutter_timeline_advance_to_marker: + * @timeline: a #ClutterTimeline + * @marker_name: the name of the marker + * + * Advances @timeline to the time of the given @marker_name. + * + * Like clutter_timeline_advance(), this function will not + * emit the #ClutterTimeline::new-frame for the time where @marker_name + * is set, nor it will emit #ClutterTimeline::marker-reached for + * @marker_name. + * + * Since: 0.8 + */ +void +clutter_timeline_advance_to_marker (ClutterTimeline *timeline, + const gchar *marker_name) +{ + ClutterTimelinePrivate *priv; + TimelineMarker *marker; + guint msecs; + + g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); + g_return_if_fail (marker_name != NULL); + + priv = timeline->priv; + + if (G_UNLIKELY (priv->markers_by_name == NULL)) + { + g_warning ("No marker named '%s' found.", marker_name); + return; + } + + marker = g_hash_table_lookup (priv->markers_by_name, marker_name); + if (marker == NULL) + { + g_warning ("No marker named '%s' found.", marker_name); + return; + } + + if (marker->is_relative) + msecs = marker->data.progress * priv->duration; + else + msecs = marker->data.msecs; + + clutter_timeline_advance (timeline, msecs); +} + +/** + * clutter_timeline_remove_marker: + * @timeline: a #ClutterTimeline + * @marker_name: the name of the marker to remove + * + * Removes @marker_name, if found, from @timeline. + * + * Since: 0.8 + */ +void +clutter_timeline_remove_marker (ClutterTimeline *timeline, + const gchar *marker_name) +{ + ClutterTimelinePrivate *priv; + TimelineMarker *marker; + + g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); + g_return_if_fail (marker_name != NULL); + + priv = timeline->priv; + + if (G_UNLIKELY (priv->markers_by_name == NULL)) + { + g_warning ("No marker named '%s' found.", marker_name); + return; + } + + marker = g_hash_table_lookup (priv->markers_by_name, marker_name); + if (!marker) + { + g_warning ("No marker named '%s' found.", marker_name); + return; + } + + /* this will take care of freeing the marker as well */ + g_hash_table_remove (priv->markers_by_name, marker_name); +} + +/** + * clutter_timeline_has_marker: + * @timeline: a #ClutterTimeline + * @marker_name: the name of the marker + * + * Checks whether @timeline has a marker set with the given name. + * + * Return value: %TRUE if the marker was found + * + * Since: 0.8 + */ +gboolean +clutter_timeline_has_marker (ClutterTimeline *timeline, + const gchar *marker_name) +{ + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), FALSE); + g_return_val_if_fail (marker_name != NULL, FALSE); + + if (G_UNLIKELY (timeline->priv->markers_by_name == NULL)) + return FALSE; + + return NULL != g_hash_table_lookup (timeline->priv->markers_by_name, + marker_name); +} + +/** + * clutter_timeline_set_auto_reverse: + * @timeline: a #ClutterTimeline + * @reverse: %TRUE if the @timeline should reverse the direction + * + * Sets whether @timeline should reverse the direction after the + * emission of the #ClutterTimeline::completed signal. + * + * Setting the #ClutterTimeline:auto-reverse property to %TRUE is the + * equivalent of connecting a callback to the #ClutterTimeline::completed + * signal and changing the direction of the timeline from that callback; + * for instance, this code: + * + * |[ + * static void + * reverse_timeline (ClutterTimeline *timeline) + * { + * ClutterTimelineDirection dir = clutter_timeline_get_direction (timeline); + * + * if (dir == CLUTTER_TIMELINE_FORWARD) + * dir = CLUTTER_TIMELINE_BACKWARD; + * else + * dir = CLUTTER_TIMELINE_FORWARD; + * + * clutter_timeline_set_direction (timeline, dir); + * } + * ... + * timeline = clutter_timeline_new (1000); + * clutter_timeline_set_repeat_count (timeline, -1); + * g_signal_connect (timeline, "completed", + * G_CALLBACK (reverse_timeline), + * NULL); + * ]| + * + * can be effectively replaced by: + * + * |[ + * timeline = clutter_timeline_new (1000); + * clutter_timeline_set_repeat_count (timeline, -1); + * clutter_timeline_set_auto_reverse (timeline); + * ]| + * + * Since: 1.6 + */ +void +clutter_timeline_set_auto_reverse (ClutterTimeline *timeline, + gboolean reverse) +{ + ClutterTimelinePrivate *priv; + + g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); + + reverse = !!reverse; + + priv = timeline->priv; + + if (priv->auto_reverse != reverse) + { + priv->auto_reverse = reverse; + + g_object_notify_by_pspec (G_OBJECT (timeline), + obj_props[PROP_AUTO_REVERSE]); + } +} + +/** + * clutter_timeline_get_auto_reverse: + * @timeline: a #ClutterTimeline + * + * Retrieves the value set by clutter_timeline_set_auto_reverse(). + * + * Return value: %TRUE if the timeline should automatically reverse, and + * %FALSE otherwise + * + * Since: 1.6 + */ +gboolean +clutter_timeline_get_auto_reverse (ClutterTimeline *timeline) +{ + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), FALSE); + + return timeline->priv->auto_reverse; +} + +/** + * clutter_timeline_set_repeat_count: + * @timeline: a #ClutterTimeline + * @count: the number of times the timeline should repeat + * + * Sets the number of times the @timeline should repeat. + * + * If @count is 0, the timeline never repeats. + * + * If @count is -1, the timeline will always repeat until + * it's stopped. + * + * Since: 1.10 + */ +void +clutter_timeline_set_repeat_count (ClutterTimeline *timeline, + gint count) +{ + ClutterTimelinePrivate *priv; + + g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); + g_return_if_fail (count >= -1); + + priv = timeline->priv; + + if (priv->repeat_count != count) + { + priv->repeat_count = count; + + g_object_notify_by_pspec (G_OBJECT (timeline), + obj_props[PROP_REPEAT_COUNT]); + } +} + +/** + * clutter_timeline_get_repeat_count: + * @timeline: a #ClutterTimeline + * + * Retrieves the number set using clutter_timeline_set_repeat_count(). + * + * Return value: the number of repeats + * + * Since: 1.10 + */ +gint +clutter_timeline_get_repeat_count (ClutterTimeline *timeline) +{ + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), 0); + + return timeline->priv->repeat_count; +} + +/** + * clutter_timeline_set_progress_func: + * @timeline: a #ClutterTimeline + * @func: (scope notified) (allow-none): a progress function, or %NULL + * @data: (closure): data to pass to @func + * @notify: a function to be called when the progress function is removed + * or the timeline is disposed + * + * Sets a custom progress function for @timeline. The progress function will + * be called by clutter_timeline_get_progress() and will be used to compute + * the progress value based on the elapsed time and the total duration of the + * timeline. + * + * If @func is not %NULL, the #ClutterTimeline:progress-mode property will + * be set to %CLUTTER_CUSTOM_MODE. + * + * If @func is %NULL, any previously set progress function will be unset, and + * the #ClutterTimeline:progress-mode property will be set to %CLUTTER_LINEAR. + * + * Since: 1.10 + */ +void +clutter_timeline_set_progress_func (ClutterTimeline *timeline, + ClutterTimelineProgressFunc func, + gpointer data, + GDestroyNotify notify) +{ + ClutterTimelinePrivate *priv; + + g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); + + priv = timeline->priv; + + if (priv->progress_notify != NULL) + priv->progress_notify (priv->progress_data); + + priv->progress_func = func; + priv->progress_data = data; + priv->progress_notify = notify; + + if (priv->progress_func != NULL) + priv->progress_mode = CLUTTER_CUSTOM_MODE; + else + priv->progress_mode = CLUTTER_LINEAR; + + g_object_notify_by_pspec (G_OBJECT (timeline), obj_props[PROP_PROGRESS_MODE]); +} + +static gdouble +clutter_timeline_progress_func (ClutterTimeline *timeline, + gdouble elapsed, + gdouble duration, + gpointer user_data G_GNUC_UNUSED) +{ + ClutterTimelinePrivate *priv = timeline->priv; + + /* parametrized easing functions need to be handled separately */ + switch (priv->progress_mode) + { + case CLUTTER_STEPS: + if (priv->step_mode == CLUTTER_STEP_MODE_START) + return clutter_ease_steps_start (elapsed, duration, priv->n_steps); + else if (priv->step_mode == CLUTTER_STEP_MODE_END) + return clutter_ease_steps_end (elapsed, duration, priv->n_steps); + else + g_assert_not_reached (); + break; + + case CLUTTER_STEP_START: + return clutter_ease_steps_start (elapsed, duration, 1); + + case CLUTTER_STEP_END: + return clutter_ease_steps_end (elapsed, duration, 1); + + case CLUTTER_CUBIC_BEZIER: + return clutter_ease_cubic_bezier (elapsed, duration, + priv->cb_1.x, priv->cb_1.y, + priv->cb_2.x, priv->cb_2.y); + + case CLUTTER_EASE: + return clutter_ease_cubic_bezier (elapsed, duration, + 0.25, 0.1, 0.25, 1.0); + + case CLUTTER_EASE_IN: + return clutter_ease_cubic_bezier (elapsed, duration, + 0.42, 0.0, 1.0, 1.0); + + case CLUTTER_EASE_OUT: + return clutter_ease_cubic_bezier (elapsed, duration, + 0.0, 0.0, 0.58, 1.0); + + case CLUTTER_EASE_IN_OUT: + return clutter_ease_cubic_bezier (elapsed, duration, + 0.42, 0.0, 0.58, 1.0); + + default: + break; + } + + return clutter_easing_for_mode (priv->progress_mode, elapsed, duration); +} + +/** + * clutter_timeline_set_progress_mode: + * @timeline: a #ClutterTimeline + * @mode: the progress mode, as a #ClutterAnimationMode + * + * Sets the progress function using a value from the #ClutterAnimationMode + * enumeration. The @mode cannot be %CLUTTER_CUSTOM_MODE or bigger than + * %CLUTTER_ANIMATION_LAST. + * + * Since: 1.10 + */ +void +clutter_timeline_set_progress_mode (ClutterTimeline *timeline, + ClutterAnimationMode mode) +{ + ClutterTimelinePrivate *priv; + + g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); + g_return_if_fail (mode < CLUTTER_ANIMATION_LAST); + g_return_if_fail (mode != CLUTTER_CUSTOM_MODE); + + priv = timeline->priv; + + if (priv->progress_mode == mode) + return; + + if (priv->progress_notify != NULL) + priv->progress_notify (priv->progress_data); + + priv->progress_mode = mode; + + /* short-circuit linear progress */ + if (priv->progress_mode != CLUTTER_LINEAR) + priv->progress_func = clutter_timeline_progress_func; + else + priv->progress_func = NULL; + + priv->progress_data = NULL; + priv->progress_notify = NULL; + + g_object_notify_by_pspec (G_OBJECT (timeline), obj_props[PROP_PROGRESS_MODE]); +} + +/** + * clutter_timeline_get_progress_mode: + * @timeline: a #ClutterTimeline + * + * Retrieves the progress mode set using clutter_timeline_set_progress_mode() + * or clutter_timeline_set_progress_func(). + * + * Return value: a #ClutterAnimationMode + * + * Since: 1.10 + */ +ClutterAnimationMode +clutter_timeline_get_progress_mode (ClutterTimeline *timeline) +{ + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), CLUTTER_LINEAR); + + return timeline->priv->progress_mode; +} + +/** + * clutter_timeline_get_duration_hint: + * @timeline: a #ClutterTimeline + * + * Retrieves the full duration of the @timeline, taking into account the + * current value of the #ClutterTimeline:repeat-count property. + * + * If the #ClutterTimeline:repeat-count property is set to -1, this function + * will return %G_MAXINT64. + * + * The returned value is to be considered a hint, and it's only valid + * as long as the @timeline hasn't been changed. + * + * Return value: the full duration of the #ClutterTimeline + * + * Since: 1.10 + */ +gint64 +clutter_timeline_get_duration_hint (ClutterTimeline *timeline) +{ + ClutterTimelinePrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), 0); + + priv = timeline->priv; + + if (priv->repeat_count == 0) + return priv->duration; + else if (priv->repeat_count < 0) + return G_MAXINT64; + else + return priv->repeat_count * priv->duration; +} + +/** + * clutter_timeline_get_current_repeat: + * @timeline: a #ClutterTimeline + * + * Retrieves the current repeat for a timeline. + * + * Repeats start at 0. + * + * Return value: the current repeat + * + * Since: 1.10 + */ +gint +clutter_timeline_get_current_repeat (ClutterTimeline *timeline) +{ + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), 0); + + return timeline->priv->current_repeat; +} + +/** + * clutter_timeline_set_step_progress: + * @timeline: a #ClutterTimeline + * @n_steps: the number of steps + * @step_mode: whether the change should happen at the start + * or at the end of the step + * + * Sets the #ClutterTimeline:progress-mode of the @timeline to %CLUTTER_STEPS + * and provides the parameters of the step function. + * + * Since: 1.12 + */ +void +clutter_timeline_set_step_progress (ClutterTimeline *timeline, + gint n_steps, + ClutterStepMode step_mode) +{ + ClutterTimelinePrivate *priv; + + g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); + g_return_if_fail (n_steps > 0); + + priv = timeline->priv; + + if (priv->progress_mode == CLUTTER_STEPS && + priv->n_steps == n_steps && + priv->step_mode == step_mode) + return; + + priv->n_steps = n_steps; + priv->step_mode = step_mode; + clutter_timeline_set_progress_mode (timeline, CLUTTER_STEPS); +} + +/** + * clutter_timeline_get_step_progress: + * @timeline: a #ClutterTimeline + * @n_steps: (out): return location for the number of steps, or %NULL + * @step_mode: (out): return location for the value change policy, + * or %NULL + * + * Retrieves the parameters of the step progress mode used by @timeline. + * + * Return value: %TRUE if the @timeline is using a step progress + * mode, and %FALSE otherwise + * + * Since: 1.12 + */ +gboolean +clutter_timeline_get_step_progress (ClutterTimeline *timeline, + gint *n_steps, + ClutterStepMode *step_mode) +{ + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), FALSE); + + if (!(timeline->priv->progress_mode == CLUTTER_STEPS || + timeline->priv->progress_mode == CLUTTER_STEP_START || + timeline->priv->progress_mode == CLUTTER_STEP_END)) + return FALSE; + + if (n_steps != NULL) + *n_steps = timeline->priv->n_steps; + + if (step_mode != NULL) + *step_mode = timeline->priv->step_mode; + + return TRUE; +} + +/** + * clutter_timeline_set_cubic_bezier_progress: + * @timeline: a #ClutterTimeline + * @c_1: the first control point for the cubic bezier + * @c_2: the second control point for the cubic bezier + * + * Sets the #ClutterTimeline:progress-mode of @timeline + * to %CLUTTER_CUBIC_BEZIER, and sets the two control + * points for the cubic bezier. + * + * The cubic bezier curve is between (0, 0) and (1, 1). The X coordinate + * of the two control points must be in the [ 0, 1 ] range, while the + * Y coordinate of the two control points can exceed this range. + * + * Since: 1.12 + */ +void +clutter_timeline_set_cubic_bezier_progress (ClutterTimeline *timeline, + const ClutterPoint *c_1, + const ClutterPoint *c_2) +{ + ClutterTimelinePrivate *priv; + + g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); + g_return_if_fail (c_1 != NULL && c_2 != NULL); + + priv = timeline->priv; + + priv->cb_1 = *c_1; + priv->cb_2 = *c_2; + + /* ensure the range on the X coordinate */ + priv->cb_1.x = CLAMP (priv->cb_1.x, 0.f, 1.f); + priv->cb_2.x = CLAMP (priv->cb_2.x, 0.f, 1.f); + + clutter_timeline_set_progress_mode (timeline, CLUTTER_CUBIC_BEZIER); +} + +/** + * clutter_timeline_get_cubic_bezier_progress: + * @timeline: a #ClutterTimeline + * @c_1: (out caller-allocates): return location for the first control + * point of the cubic bezier, or %NULL + * @c_2: (out caller-allocates): return location for the second control + * point of the cubic bezier, or %NULL + * + * Retrieves the control points for the cubic bezier progress mode. + * + * Return value: %TRUE if the @timeline is using a cubic bezier progress + * more, and %FALSE otherwise + * + * Since: 1.12 + */ +gboolean +clutter_timeline_get_cubic_bezier_progress (ClutterTimeline *timeline, + ClutterPoint *c_1, + ClutterPoint *c_2) +{ + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), FALSE); + + if (!(timeline->priv->progress_mode == CLUTTER_CUBIC_BEZIER || + timeline->priv->progress_mode == CLUTTER_EASE || + timeline->priv->progress_mode == CLUTTER_EASE_IN || + timeline->priv->progress_mode == CLUTTER_EASE_OUT || + timeline->priv->progress_mode == CLUTTER_EASE_IN_OUT)) + return FALSE; + + if (c_1 != NULL) + *c_1 = timeline->priv->cb_1; + + if (c_2 != NULL) + *c_2 = timeline->priv->cb_2; + + return TRUE; +} diff --git a/clutter/clutter/clutter-timeline.h b/clutter/clutter/clutter-timeline.h new file mode 100644 index 0000000..267dc63 --- /dev/null +++ b/clutter/clutter/clutter-timeline.h @@ -0,0 +1,226 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_TIMELINE_H__ +#define __CLUTTER_TIMELINE_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_TIMELINE (clutter_timeline_get_type ()) +#define CLUTTER_TIMELINE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_TIMELINE, ClutterTimeline)) +#define CLUTTER_TIMELINE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_TIMELINE, ClutterTimelineClass)) +#define CLUTTER_IS_TIMELINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_TIMELINE)) +#define CLUTTER_IS_TIMELINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_TIMELINE)) +#define CLUTTER_TIMELINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_TIMELINE, ClutterTimelineClass)) + +typedef struct _ClutterTimelineClass ClutterTimelineClass; +typedef struct _ClutterTimelinePrivate ClutterTimelinePrivate; + +/** + * ClutterTimelineProgressFunc: + * @timeline: a #ClutterTimeline + * @elapsed: the elapsed time, in milliseconds + * @total: the total duration of the timeline, in milliseconds, + * @user_data: data passed to the function + * + * A function for defining a custom progress. + * + * Return value: the progress, as a floating point value between -1.0 and 2.0. + * + * Since: 1.10 + */ +typedef gdouble (* ClutterTimelineProgressFunc) (ClutterTimeline *timeline, + gdouble elapsed, + gdouble total, + gpointer user_data); + +/** + * ClutterTimeline: + * + * The #ClutterTimeline structure contains only private data + * and should be accessed using the provided API + * + * Since: 0.2 + */ +struct _ClutterTimeline +{ + /*< private >*/ + GObject parent_instance; + + ClutterTimelinePrivate *priv; +}; + +/** + * ClutterTimelineClass: + * @started: class handler for the #ClutterTimeline::started signal + * @completed: class handler for the #ClutterTimeline::completed signal + * @paused: class handler for the #ClutterTimeline::paused signal + * @new_frame: class handler for the #ClutterTimeline::new-frame signal + * @marker_reached: class handler for the #ClutterTimeline::marker-reached signal + * @stopped: class handler for the #ClutterTimeline::stopped signal + * + * The #ClutterTimelineClass structure contains only private data + * + * Since: 0.2 + */ +struct _ClutterTimelineClass +{ + /*< private >*/ + GObjectClass parent_class; + + /*< public >*/ + void (*started) (ClutterTimeline *timeline); + void (*completed) (ClutterTimeline *timeline); + void (*paused) (ClutterTimeline *timeline); + + void (*new_frame) (ClutterTimeline *timeline, + gint msecs); + + void (*marker_reached) (ClutterTimeline *timeline, + const gchar *marker_name, + gint msecs); + void (*stopped) (ClutterTimeline *timeline, + gboolean is_finished); + + /*< private >*/ + void (*_clutter_timeline_1) (void); + void (*_clutter_timeline_2) (void); + void (*_clutter_timeline_3) (void); + void (*_clutter_timeline_4) (void); +}; + +CLUTTER_AVAILABLE_IN_ALL +GType clutter_timeline_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_ALL +ClutterTimeline * clutter_timeline_new (guint msecs); + +CLUTTER_AVAILABLE_IN_ALL +guint clutter_timeline_get_duration (ClutterTimeline *timeline); +CLUTTER_AVAILABLE_IN_ALL +void clutter_timeline_set_duration (ClutterTimeline *timeline, + guint msecs); +CLUTTER_AVAILABLE_IN_ALL +ClutterTimelineDirection clutter_timeline_get_direction (ClutterTimeline *timeline); +CLUTTER_AVAILABLE_IN_ALL +void clutter_timeline_set_direction (ClutterTimeline *timeline, + ClutterTimelineDirection direction); +CLUTTER_AVAILABLE_IN_ALL +void clutter_timeline_start (ClutterTimeline *timeline); +CLUTTER_AVAILABLE_IN_ALL +void clutter_timeline_pause (ClutterTimeline *timeline); +CLUTTER_AVAILABLE_IN_ALL +void clutter_timeline_stop (ClutterTimeline *timeline); +CLUTTER_AVAILABLE_IN_1_6 +void clutter_timeline_set_auto_reverse (ClutterTimeline *timeline, + gboolean reverse); +CLUTTER_AVAILABLE_IN_1_6 +gboolean clutter_timeline_get_auto_reverse (ClutterTimeline *timeline); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_timeline_set_repeat_count (ClutterTimeline *timeline, + gint count); +CLUTTER_AVAILABLE_IN_1_10 +gint clutter_timeline_get_repeat_count (ClutterTimeline *timeline); +CLUTTER_AVAILABLE_IN_ALL +void clutter_timeline_rewind (ClutterTimeline *timeline); +CLUTTER_AVAILABLE_IN_ALL +void clutter_timeline_skip (ClutterTimeline *timeline, + guint msecs); +CLUTTER_AVAILABLE_IN_ALL +void clutter_timeline_advance (ClutterTimeline *timeline, + guint msecs); +CLUTTER_AVAILABLE_IN_ALL +guint clutter_timeline_get_elapsed_time (ClutterTimeline *timeline); +CLUTTER_AVAILABLE_IN_ALL +gdouble clutter_timeline_get_progress (ClutterTimeline *timeline); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_timeline_is_playing (ClutterTimeline *timeline); +CLUTTER_AVAILABLE_IN_ALL +void clutter_timeline_set_delay (ClutterTimeline *timeline, + guint msecs); +CLUTTER_AVAILABLE_IN_ALL +guint clutter_timeline_get_delay (ClutterTimeline *timeline); +CLUTTER_AVAILABLE_IN_ALL +guint clutter_timeline_get_delta (ClutterTimeline *timeline); +CLUTTER_AVAILABLE_IN_1_14 +void clutter_timeline_add_marker (ClutterTimeline *timeline, + const gchar *marker_name, + gdouble progress); +CLUTTER_AVAILABLE_IN_ALL +void clutter_timeline_add_marker_at_time (ClutterTimeline *timeline, + const gchar *marker_name, + guint msecs); +CLUTTER_AVAILABLE_IN_ALL +void clutter_timeline_remove_marker (ClutterTimeline *timeline, + const gchar *marker_name); +CLUTTER_AVAILABLE_IN_ALL +gchar ** clutter_timeline_list_markers (ClutterTimeline *timeline, + gint msecs, + gsize *n_markers) G_GNUC_MALLOC; +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_timeline_has_marker (ClutterTimeline *timeline, + const gchar *marker_name); +CLUTTER_AVAILABLE_IN_ALL +void clutter_timeline_advance_to_marker (ClutterTimeline *timeline, + const gchar *marker_name); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_timeline_set_progress_func (ClutterTimeline *timeline, + ClutterTimelineProgressFunc func, + gpointer data, + GDestroyNotify notify); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_timeline_set_progress_mode (ClutterTimeline *timeline, + ClutterAnimationMode mode); +CLUTTER_AVAILABLE_IN_1_10 +ClutterAnimationMode clutter_timeline_get_progress_mode (ClutterTimeline *timeline); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_timeline_set_step_progress (ClutterTimeline *timeline, + gint n_steps, + ClutterStepMode step_mode); +CLUTTER_AVAILABLE_IN_1_12 +gboolean clutter_timeline_get_step_progress (ClutterTimeline *timeline, + gint *n_steps, + ClutterStepMode *step_mode); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_timeline_set_cubic_bezier_progress (ClutterTimeline *timeline, + const ClutterPoint *c_1, + const ClutterPoint *c_2); +CLUTTER_AVAILABLE_IN_1_12 +gboolean clutter_timeline_get_cubic_bezier_progress (ClutterTimeline *timeline, + ClutterPoint *c_1, + ClutterPoint *c_2); + +CLUTTER_AVAILABLE_IN_1_10 +gint64 clutter_timeline_get_duration_hint (ClutterTimeline *timeline); +CLUTTER_AVAILABLE_IN_1_10 +gint clutter_timeline_get_current_repeat (ClutterTimeline *timeline); + +G_END_DECLS + +#endif /* _CLUTTER_TIMELINE_H__ */ diff --git a/clutter/clutter/clutter-transition-group.c b/clutter/clutter/clutter-transition-group.c new file mode 100644 index 0000000..0063564 --- /dev/null +++ b/clutter/clutter/clutter-transition-group.c @@ -0,0 +1,252 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2012 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 . + * + * Author: Emmanuele Bassi + */ + +/** + * SECTION:clutter-transition-group + * @Title: ClutterTransitionGroup + * @Short_Description: Group transitions together + * + * The #ClutterTransitionGroup allows running multiple #ClutterTransition + * instances concurrently. + * + * The transitions inside a group will run within the boundaries of the + * group; for instance, if a transition has a duration of 10 seconds, and + * the group that contains it has a duration of 5 seconds, only the first + * 5 seconds of the transition will be played. + * + * #ClutterTransitionGroup is available since Clutter 1.12 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-transition-group.h" + +#include "clutter-debug.h" +#include "clutter-private.h" + +struct _ClutterTransitionGroupPrivate +{ + GHashTable *transitions; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterTransitionGroup, clutter_transition_group, CLUTTER_TYPE_TRANSITION) + +static void +clutter_transition_group_new_frame (ClutterTimeline *timeline, + gint elapsed) +{ + ClutterTransitionGroupPrivate *priv; + GHashTableIter iter; + gpointer element; + gint64 msecs; + + priv = CLUTTER_TRANSITION_GROUP (timeline)->priv; + + /* get the time elapsed since the last ::new-frame... */ + msecs = clutter_timeline_get_delta (timeline); + + g_hash_table_iter_init (&iter, priv->transitions); + while (g_hash_table_iter_next (&iter, &element, NULL)) + { + ClutterTimeline *t = element; + + /* ... and advance every timeline */ + clutter_timeline_set_direction (t, clutter_timeline_get_direction (timeline)); + clutter_timeline_set_duration (t, clutter_timeline_get_duration (timeline)); + + _clutter_timeline_advance (t, msecs); + } +} + +static void +clutter_transition_group_attached (ClutterTransition *transition, + ClutterAnimatable *animatable) +{ + ClutterTransitionGroupPrivate *priv; + GHashTableIter iter; + gpointer element; + + priv = CLUTTER_TRANSITION_GROUP (transition)->priv; + + g_hash_table_iter_init (&iter, priv->transitions); + while (g_hash_table_iter_next (&iter, &element, NULL)) + { + ClutterTransition *t = element; + + clutter_transition_set_animatable (t, animatable); + } +} + +static void +clutter_transition_group_detached (ClutterTransition *transition, + ClutterAnimatable *animatable) +{ + ClutterTransitionGroupPrivate *priv; + GHashTableIter iter; + gpointer element; + + priv = CLUTTER_TRANSITION_GROUP (transition)->priv; + + g_hash_table_iter_init (&iter, priv->transitions); + while (g_hash_table_iter_next (&iter, &element, NULL)) + { + ClutterTransition *t = element; + + clutter_transition_set_animatable (t, NULL); + } +} + +static void +clutter_transition_group_started (ClutterTimeline *timeline) +{ + ClutterTransitionGroupPrivate *priv; + GHashTableIter iter; + gpointer element; + + priv = CLUTTER_TRANSITION_GROUP (timeline)->priv; + + g_hash_table_iter_init (&iter, priv->transitions); + while (g_hash_table_iter_next (&iter, &element, NULL)) + { + ClutterTransition *t = element; + + g_signal_emit_by_name (t, "started"); + } +} + +static void +clutter_transition_group_finalize (GObject *gobject) +{ + ClutterTransitionGroupPrivate *priv; + + priv = CLUTTER_TRANSITION_GROUP (gobject)->priv; + + g_hash_table_unref (priv->transitions); + + G_OBJECT_CLASS (clutter_transition_group_parent_class)->finalize (gobject); +} + +static void +clutter_transition_group_class_init (ClutterTransitionGroupClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterTimelineClass *timeline_class = CLUTTER_TIMELINE_CLASS (klass); + ClutterTransitionClass *transition_class = CLUTTER_TRANSITION_CLASS (klass); + + gobject_class->finalize = clutter_transition_group_finalize; + + timeline_class->started = clutter_transition_group_started; + timeline_class->new_frame = clutter_transition_group_new_frame; + + transition_class->attached = clutter_transition_group_attached; + transition_class->detached = clutter_transition_group_detached; +} + +static void +clutter_transition_group_init (ClutterTransitionGroup *self) +{ + self->priv = clutter_transition_group_get_instance_private (self); + self->priv->transitions = + g_hash_table_new_full (NULL, NULL, (GDestroyNotify) g_object_unref, NULL); +} + +/** + * clutter_transition_group_new: + * + * Creates a new #ClutterTransitionGroup instance. + * + * Return value: the newly created #ClutterTransitionGroup. Use + * g_object_unref() when done to deallocate the resources it + * uses + * + * Since: 1.12 + */ +ClutterTransition * +clutter_transition_group_new (void) +{ + return g_object_new (CLUTTER_TYPE_TRANSITION_GROUP, NULL); +} + +/** + * clutter_transition_group_add_transition: + * @group: a #ClutterTransitionGroup + * @transition: a #ClutterTransition + * + * Adds @transition to @group. + * + * This function acquires a reference on @transition that will be released + * when calling clutter_transition_group_remove_transition(). + * + * Since: 1.12 + */ +void +clutter_transition_group_add_transition (ClutterTransitionGroup *group, + ClutterTransition *transition) +{ + g_return_if_fail (CLUTTER_IS_TRANSITION_GROUP (group)); + g_return_if_fail (CLUTTER_IS_TRANSITION (transition)); + + g_hash_table_add (group->priv->transitions, g_object_ref (transition)); +} + +/** + * clutter_transition_group_remove_transition: + * @group: a #ClutterTransitionGroup + * @transition: a #ClutterTransition + * + * Removes @transition from @group. + * + * This function releases the reference acquired on @transition when + * calling clutter_transition_group_add_transition(). + * + * Since: 1.12 + */ +void +clutter_transition_group_remove_transition (ClutterTransitionGroup *group, + ClutterTransition *transition) +{ + g_return_if_fail (CLUTTER_IS_TRANSITION_GROUP (group)); + + g_hash_table_remove (group->priv->transitions, transition); +} + +/** + * clutter_transition_group_remove_all: + * @group: a #ClutterTransitionGroup + * + * Removes all transitions from @group. + * + * This function releases the reference acquired when calling + * clutter_transition_group_add_transition(). + * + * Since: 1.12 + */ +void +clutter_transition_group_remove_all (ClutterTransitionGroup *group) +{ + g_return_if_fail (CLUTTER_IS_TRANSITION_GROUP (group)); + + g_hash_table_remove_all (group->priv->transitions); +} diff --git a/clutter/clutter/clutter-transition-group.h b/clutter/clutter/clutter-transition-group.h new file mode 100644 index 0000000..b2a9ce1 --- /dev/null +++ b/clutter/clutter/clutter-transition-group.h @@ -0,0 +1,95 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2012 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 . + * + * Author: Emmanuele Bassi + */ + +#ifndef __CLUTTER_TRANSITION_GROUP_H__ +#define __CLUTTER_TRANSITION_GROUP_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_TRANSITION_GROUP (clutter_transition_group_get_type ()) +#define CLUTTER_TRANSITION_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_TRANSITION_GROUP, ClutterTransitionGroup)) +#define CLUTTER_IS_TRANSITION_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_TRANSITION_GROUP)) +#define CLUTTER_TRANSITION_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_TRANSITION_GROUP, ClutterTransitionGroupClass)) +#define CLUTTER_IS_TRANSITION_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_TRANSITION_GROUP)) +#define CLUTTER_TRANSITION_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_TRANSITION_GROUP, ClutterTransitionGroup)) + +typedef struct _ClutterTransitionGroupPrivate ClutterTransitionGroupPrivate; +typedef struct _ClutterTransitionGroupClass ClutterTransitionGroupClass; + +/** + * ClutterTransitionGroup: + * + * The #ClutterTransitionGroup structure contains + * private data and should only be accessed using the provided API. + * + * Since: 1.12 + */ +struct _ClutterTransitionGroup +{ + /*< private >*/ + ClutterTransition parent_instance; + + ClutterTransitionGroupPrivate *priv; +}; + +/** + * ClutterTransitionGroupClass: + * + * The #ClutterTransitionGroupClass structure + * contains only private data. + * + * Since: 1.12 + */ +struct _ClutterTransitionGroupClass +{ + /*< private >*/ + ClutterTransitionClass parent_class; + + gpointer _padding[8]; +}; + +CLUTTER_AVAILABLE_IN_1_12 +GType clutter_transition_group_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_12 +ClutterTransition * clutter_transition_group_new (void); + +CLUTTER_AVAILABLE_IN_1_12 +void clutter_transition_group_add_transition (ClutterTransitionGroup *group, + ClutterTransition *transition); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_transition_group_remove_transition (ClutterTransitionGroup *group, + ClutterTransition *transition); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_transition_group_remove_all (ClutterTransitionGroup *group); + +G_END_DECLS + +#endif /* __CLUTTER_TRANSITION_GROUP_H__ */ diff --git a/clutter/clutter/clutter-transition.c b/clutter/clutter/clutter-transition.c new file mode 100644 index 0000000..83e9677 --- /dev/null +++ b/clutter/clutter/clutter-transition.c @@ -0,0 +1,683 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2012 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 . + * + * Author: Emmanuele Bassi + */ + +/** + * SECTION:clutter-transition + * @Title: ClutterTransition + * @Short_Description: Transition between two values + * + * #ClutterTransition is an abstract subclass of #ClutterTimeline that + * computes the interpolation between two values, stored by a #ClutterInterval. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-transition.h" + +#include "clutter-animatable.h" +#include "clutter-debug.h" +#include "clutter-interval.h" +#include "clutter-private.h" +#include "clutter-timeline.h" + +#include + +struct _ClutterTransitionPrivate +{ + ClutterInterval *interval; + ClutterAnimatable *animatable; + + guint remove_on_complete : 1; +}; + +enum +{ + PROP_0, + + PROP_INTERVAL, + PROP_ANIMATABLE, + PROP_REMOVE_ON_COMPLETE, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST] = { NULL, }; + +static GQuark quark_animatable_set = 0; + +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterTransition, clutter_transition, CLUTTER_TYPE_TIMELINE) + +static void +clutter_transition_attach (ClutterTransition *transition, + ClutterAnimatable *animatable) +{ + CLUTTER_TRANSITION_GET_CLASS (transition)->attached (transition, animatable); +} + +static void +clutter_transition_detach (ClutterTransition *transition, + ClutterAnimatable *animatable) +{ + CLUTTER_TRANSITION_GET_CLASS (transition)->detached (transition, animatable); +} + +static void +clutter_transition_real_compute_value (ClutterTransition *transition, + ClutterAnimatable *animatable, + ClutterInterval *interval, + gdouble progress) +{ +} + +static void +clutter_transition_real_attached (ClutterTransition *transition, + ClutterAnimatable *animatable) +{ +} + +static void +clutter_transition_real_detached (ClutterTransition *transition, + ClutterAnimatable *animatable) +{ +} + +static void +clutter_transition_new_frame (ClutterTimeline *timeline, + gint elapsed G_GNUC_UNUSED) +{ + ClutterTransition *transition = CLUTTER_TRANSITION (timeline); + ClutterTransitionPrivate *priv = transition->priv; + gdouble progress; + + if (priv->interval == NULL || + priv->animatable == NULL) + return; + + progress = clutter_timeline_get_progress (timeline); + + CLUTTER_TRANSITION_GET_CLASS (timeline)->compute_value (transition, + priv->animatable, + priv->interval, + progress); +} + +static void +clutter_transition_stopped (ClutterTimeline *timeline, + gboolean is_finished) +{ + ClutterTransitionPrivate *priv = CLUTTER_TRANSITION (timeline)->priv; + + if (is_finished && + priv->animatable != NULL && + priv->remove_on_complete) + { + clutter_transition_detach (CLUTTER_TRANSITION (timeline), + priv->animatable); + g_clear_object (&priv->animatable); + g_object_unref (timeline); + } +} + +static void +clutter_transition_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterTransition *transition = CLUTTER_TRANSITION (gobject); + + switch (prop_id) + { + case PROP_INTERVAL: + clutter_transition_set_interval (transition, g_value_get_object (value)); + break; + + case PROP_ANIMATABLE: + clutter_transition_set_animatable (transition, g_value_get_object (value)); + break; + + case PROP_REMOVE_ON_COMPLETE: + clutter_transition_set_remove_on_complete (transition, g_value_get_boolean (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_transition_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterTransitionPrivate *priv = CLUTTER_TRANSITION (gobject)->priv; + + switch (prop_id) + { + case PROP_INTERVAL: + g_value_set_object (value, priv->interval); + break; + + case PROP_ANIMATABLE: + g_value_set_object (value, priv->animatable); + break; + + case PROP_REMOVE_ON_COMPLETE: + g_value_set_boolean (value, priv->remove_on_complete); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_transition_dispose (GObject *gobject) +{ + ClutterTransitionPrivate *priv = CLUTTER_TRANSITION (gobject)->priv; + + if (priv->animatable != NULL) + clutter_transition_detach (CLUTTER_TRANSITION (gobject), + priv->animatable); + + g_clear_object (&priv->interval); + g_clear_object (&priv->animatable); + + G_OBJECT_CLASS (clutter_transition_parent_class)->dispose (gobject); +} + +static void +clutter_transition_class_init (ClutterTransitionClass *klass) +{ + ClutterTimelineClass *timeline_class = CLUTTER_TIMELINE_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + quark_animatable_set = + g_quark_from_static_string ("-clutter-transition-animatable-set"); + + klass->compute_value = clutter_transition_real_compute_value; + klass->attached = clutter_transition_real_attached; + klass->detached = clutter_transition_real_detached; + + timeline_class->new_frame = clutter_transition_new_frame; + timeline_class->stopped = clutter_transition_stopped; + + gobject_class->set_property = clutter_transition_set_property; + gobject_class->get_property = clutter_transition_get_property; + gobject_class->dispose = clutter_transition_dispose; + + /** + * ClutterTransition:interval: + * + * The #ClutterInterval used to describe the initial and final states + * of the transition. + * + * Since: 1.10 + */ + obj_props[PROP_INTERVAL] = + g_param_spec_object ("interval", + P_("Interval"), + P_("The interval of values to transition"), + CLUTTER_TYPE_INTERVAL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + /** + * ClutterTransition:animatable: + * + * The #ClutterAnimatable instance currently being animated. + * + * Since: 1.10 + */ + obj_props[PROP_ANIMATABLE] = + g_param_spec_object ("animatable", + P_("Animatable"), + P_("The animatable object"), + CLUTTER_TYPE_ANIMATABLE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + /** + * ClutterTransition:remove-on-complete: + * + * Whether the #ClutterTransition should be automatically detached + * from the #ClutterTransition:animatable instance whenever the + * #ClutterTimeline::stopped signal is emitted. + * + * The #ClutterTransition:remove-on-complete property takes into + * account the value of the #ClutterTimeline:repeat-count property, + * and it only detaches the transition if the transition is not + * repeating. + * + * Since: 1.10 + */ + obj_props[PROP_REMOVE_ON_COMPLETE] = + g_param_spec_boolean ("remove-on-complete", + P_("Remove on Complete"), + P_("Detach the transition when completed"), + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); +} + +static void +clutter_transition_init (ClutterTransition *self) +{ + self->priv = clutter_transition_get_instance_private (self); +} + +/** + * clutter_transition_set_interval: + * @transition: a #ClutterTransition + * @interval: (allow-none): a #ClutterInterval, or %NULL + * + * Sets the #ClutterTransition:interval property using @interval. + * + * The @transition will acquire a reference on the @interval, sinking + * the floating flag on it if necessary. + * + * Since: 1.10 + */ +void +clutter_transition_set_interval (ClutterTransition *transition, + ClutterInterval *interval) +{ + ClutterTransitionPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TRANSITION (transition)); + g_return_if_fail (interval == NULL || CLUTTER_IS_INTERVAL (interval)); + + priv = transition->priv; + + if (priv->interval == interval) + return; + + g_clear_object (&priv->interval); + + if (interval != NULL) + priv->interval = g_object_ref_sink (interval); + + g_object_notify_by_pspec (G_OBJECT (transition), obj_props[PROP_INTERVAL]); +} + +/** + * clutter_transition_get_interval: + * @transition: a #ClutterTransition + * + * Retrieves the interval set using clutter_transition_set_interval() + * + * Return value: (transfer none): a #ClutterInterval, or %NULL; the returned + * interval is owned by the #ClutterTransition and it should not be freed + * directly + * + * Since: 1.10 + */ +ClutterInterval * +clutter_transition_get_interval (ClutterTransition *transition) +{ + g_return_val_if_fail (CLUTTER_IS_TRANSITION (transition), NULL); + + return transition->priv->interval; +} + +/** + * clutter_transition_set_animatable: + * @transition: a #ClutterTransition + * @animatable: (allow-none): a #ClutterAnimatable, or %NULL + * + * Sets the #ClutterTransition:animatable property. + * + * The @transition will acquire a reference to the @animatable instance, + * and will call the #ClutterTransitionClass.attached() virtual function. + * + * If an existing #ClutterAnimatable is attached to @transition, the + * reference will be released, and the #ClutterTransitionClass.detached() + * virtual function will be called. + * + * Since: 1.10 + */ +void +clutter_transition_set_animatable (ClutterTransition *transition, + ClutterAnimatable *animatable) +{ + ClutterTransitionPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TRANSITION (transition)); + g_return_if_fail (animatable == NULL || CLUTTER_IS_ANIMATABLE (animatable)); + + priv = transition->priv; + + if (priv->animatable == animatable) + return; + + if (priv->animatable != NULL) + clutter_transition_detach (transition, priv->animatable); + + g_clear_object (&priv->animatable); + + if (animatable != NULL) + { + priv->animatable = g_object_ref (animatable); + clutter_transition_attach (transition, priv->animatable); + } +} + +/** + * clutter_transition_get_animatable: + * @transition: a #ClutterTransition + * + * Retrieves the #ClutterAnimatable set using clutter_transition_set_animatable(). + * + * Return value: (transfer none): a #ClutterAnimatable, or %NULL; the returned + * animatable is owned by the #ClutterTransition, and it should not be freed + * directly. + * + * Since: 1.10 + */ +ClutterAnimatable * +clutter_transition_get_animatable (ClutterTransition *transition) +{ + g_return_val_if_fail (CLUTTER_IS_TRANSITION (transition), NULL); + + return transition->priv->animatable; +} + +/** + * clutter_transition_set_remove_on_complete: + * @transition: a #ClutterTransition + * @remove_complete: whether to detach @transition when complete + * + * Sets whether @transition should be detached from the #ClutterAnimatable + * set using clutter_transition_set_animatable() when the + * #ClutterTimeline::completed signal is emitted. + * + * Since: 1.10 + */ +void +clutter_transition_set_remove_on_complete (ClutterTransition *transition, + gboolean remove_complete) +{ + g_return_if_fail (CLUTTER_IS_TRANSITION (transition)); + + remove_complete = !!remove_complete; + + if (transition->priv->remove_on_complete == remove_complete) + return; + + transition->priv->remove_on_complete = remove_complete; + + g_object_notify_by_pspec (G_OBJECT (transition), + obj_props[PROP_REMOVE_ON_COMPLETE]); +} + +/** + * clutter_transition_get_remove_on_complete: + * @transition: a #ClutterTransition + * + * Retrieves the value of the #ClutterTransition:remove-on-complete property. + * + * Return value: %TRUE if the @transition should be detached when complete, + * and %FALSE otherwise + * + * Since: 1.10 + */ +gboolean +clutter_transition_get_remove_on_complete (ClutterTransition *transition) +{ + g_return_val_if_fail (CLUTTER_IS_TRANSITION (transition), FALSE); + + return transition->priv->remove_on_complete; +} + +typedef void (* IntervalSetFunc) (ClutterInterval *interval, + const GValue *value); + +static inline void +clutter_transition_set_value (ClutterTransition *transition, + IntervalSetFunc interval_set_func, + const GValue *value) +{ + ClutterTransitionPrivate *priv = transition->priv; + GType interval_type; + + if (priv->interval == NULL) + { + priv->interval = clutter_interval_new_with_values (G_VALUE_TYPE (value), + NULL, + NULL); + g_object_ref_sink (priv->interval); + } + + interval_type = clutter_interval_get_value_type (priv->interval); + + if (!g_type_is_a (G_VALUE_TYPE (value), interval_type)) + { + if (g_value_type_compatible (G_VALUE_TYPE (value), interval_type)) + { + interval_set_func (priv->interval, value); + return; + } + + if (g_value_type_transformable (G_VALUE_TYPE (value), interval_type)) + { + GValue transform = G_VALUE_INIT; + + g_value_init (&transform, interval_type); + if (g_value_transform (value, &transform)) + interval_set_func (priv->interval, &transform); + else + { + g_warning ("%s: Unable to convert a value of type '%s' into " + "the value type '%s' of the interval used by the " + "transition.", + G_STRLOC, + g_type_name (G_VALUE_TYPE (value)), + g_type_name (interval_type)); + } + + g_value_unset (&transform); + } + } + else + interval_set_func (priv->interval, value); +} + +/** + * clutter_transition_set_from_value: (rename-to clutter_transition_set_from) + * @transition: a #ClutterTransition + * @value: a #GValue with the initial value of the transition + * + * Sets the initial value of the transition. + * + * This is a convenience function that will either create the + * #ClutterInterval used by @transition, or will update it if + * the #ClutterTransition:interval is already set. + * + * This function will copy the contents of @value, so it is + * safe to call g_value_unset() after it returns. + * + * If @transition already has a #ClutterTransition:interval set, + * then @value must hold the same type, or a transformable type, + * as the interval's #ClutterInterval:value-type property. + * + * This function is meant to be used by language bindings. + * + * Since: 1.12 + */ +void +clutter_transition_set_from_value (ClutterTransition *transition, + const GValue *value) +{ + g_return_if_fail (CLUTTER_IS_TRANSITION (transition)); + g_return_if_fail (G_IS_VALUE (value)); + + clutter_transition_set_value (transition, + clutter_interval_set_initial_value, + value); +} + +/** + * clutter_transition_set_to_value: (rename-to clutter_transition_set_to) + * @transition: a #ClutterTransition + * @value: a #GValue with the final value of the transition + * + * Sets the final value of the transition. + * + * This is a convenience function that will either create the + * #ClutterInterval used by @transition, or will update it if + * the #ClutterTransition:interval is already set. + * + * This function will copy the contents of @value, so it is + * safe to call g_value_unset() after it returns. + * + * If @transition already has a #ClutterTransition:interval set, + * then @value must hold the same type, or a transformable type, + * as the interval's #ClutterInterval:value-type property. + * + * This function is meant to be used by language bindings. + * + * Since: 1.12 + */ +void +clutter_transition_set_to_value (ClutterTransition *transition, + const GValue *value) +{ + g_return_if_fail (CLUTTER_IS_TRANSITION (transition)); + g_return_if_fail (G_IS_VALUE (value)); + + clutter_transition_set_value (transition, + clutter_interval_set_final_value, + value); +} + +/** + * clutter_transition_set_from: (skip) + * @transition: a #ClutterTransition + * @value_type: the type of the value to set + * @...: the initial value + * + * Sets the initial value of the transition. + * + * This is a convenience function that will either create the + * #ClutterInterval used by @transition, or will update it if + * the #ClutterTransition:interval is already set. + * + * If @transition already has a #ClutterTransition:interval set, + * then @value must hold the same type, or a transformable type, + * as the interval's #ClutterInterval:value-type property. + * + * This is a convenience function for the C API; language bindings + * should use clutter_transition_set_from_value() instead. + * + * Since: 1.12 + */ +void +clutter_transition_set_from (ClutterTransition *transition, + GType value_type, + ...) +{ + GValue value = G_VALUE_INIT; + gchar *error = NULL; + va_list args; + + g_return_if_fail (CLUTTER_IS_TRANSITION (transition)); + g_return_if_fail (value_type != G_TYPE_INVALID); + + va_start (args, value_type); + + G_VALUE_COLLECT_INIT (&value, value_type, args, 0, &error); + + va_end (args); + + if (error != NULL) + { + g_warning ("%s: %s", G_STRLOC, error); + g_free (error); + return; + } + + clutter_transition_set_value (transition, + clutter_interval_set_initial_value, + &value); + + g_value_unset (&value); +} + +/** + * clutter_transition_set_to: (skip) + * @transition: a #ClutterTransition + * @value_type: the type of the value to set + * @...: the final value + * + * Sets the final value of the transition. + * + * This is a convenience function that will either create the + * #ClutterInterval used by @transition, or will update it if + * the #ClutterTransition:interval is already set. + * + * If @transition already has a #ClutterTransition:interval set, + * then @value must hold the same type, or a transformable type, + * as the interval's #ClutterInterval:value-type property. + * + * This is a convenience function for the C API; language bindings + * should use clutter_transition_set_to_value() instead. + * + * Since: 1.12 + */ +void +clutter_transition_set_to (ClutterTransition *transition, + GType value_type, + ...) +{ + GValue value = G_VALUE_INIT; + gchar *error = NULL; + va_list args; + + g_return_if_fail (CLUTTER_IS_TRANSITION (transition)); + g_return_if_fail (value_type != G_TYPE_INVALID); + + va_start (args, value_type); + + G_VALUE_COLLECT_INIT (&value, value_type, args, 0, &error); + + va_end (args); + + if (error != NULL) + { + g_warning ("%s: %s", G_STRLOC, error); + g_free (error); + return; + } + + clutter_transition_set_value (transition, + clutter_interval_set_final_value, + &value); + + g_value_unset (&value); +} diff --git a/clutter/clutter/clutter-transition.h b/clutter/clutter/clutter-transition.h new file mode 100644 index 0000000..7ea9bfa --- /dev/null +++ b/clutter/clutter/clutter-transition.h @@ -0,0 +1,132 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2012 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 . + * + * Author: Emmanuele Bassi + */ + +#ifndef __CLUTTER_TRANSITION_H__ +#define __CLUTTER_TRANSITION_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_TRANSITION (clutter_transition_get_type ()) +#define CLUTTER_TRANSITION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_TRANSITION, ClutterTransition)) +#define CLUTTER_IS_TRANSITION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_TRANSITION)) +#define CLUTTER_TRANSITION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_TRANSITION, ClutterTransitionClass)) +#define CLUTTER_IS_TRANSITION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_TRANSITION)) +#define CLUTTER_TRANSITION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_TRANSITION, ClutterTransitionClass)) + +typedef struct _ClutterTransitionPrivate ClutterTransitionPrivate; +typedef struct _ClutterTransitionClass ClutterTransitionClass; + +/** + * ClutterTransition: + * + * The #ClutterTransition structure contains private + * data and should only be accessed using the provided API. + * + * Since: 1.10 + */ +struct _ClutterTransition +{ + /*< private >*/ + ClutterTimeline parent_instance; + + ClutterTransitionPrivate *priv; +}; + +/** + * ClutterTransitionClass: + * @attached: virtual function; called when a transition is attached to + * a #ClutterAnimatable instance + * @detached: virtual function; called when a transition is detached from + * a #ClutterAnimatable instance + * @compute_value: virtual function; called each frame to compute and apply + * the interpolation of the interval + * + * The #ClutterTransitionClass structure contains + * private data. + * + * Since: 1.10 + */ +struct _ClutterTransitionClass +{ + /*< private >*/ + ClutterTimelineClass parent_class; + + /*< public >*/ + void (* attached) (ClutterTransition *transition, + ClutterAnimatable *animatable); + void (* detached) (ClutterTransition *transition, + ClutterAnimatable *animatable); + + void (* compute_value) (ClutterTransition *transition, + ClutterAnimatable *animatable, + ClutterInterval *interval, + gdouble progress); + + /*< private >*/ + gpointer _padding[8]; +}; + +CLUTTER_AVAILABLE_IN_1_10 +GType clutter_transition_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_10 +void clutter_transition_set_interval (ClutterTransition *transition, + ClutterInterval *interval); +CLUTTER_AVAILABLE_IN_1_10 +ClutterInterval * clutter_transition_get_interval (ClutterTransition *transition); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_transition_set_from_value (ClutterTransition *transition, + const GValue *value); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_transition_set_to_value (ClutterTransition *transition, + const GValue *value); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_transition_set_from (ClutterTransition *transition, + GType value_type, + ...); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_transition_set_to (ClutterTransition *transition, + GType value_type, + ...); + +CLUTTER_AVAILABLE_IN_1_10 +void clutter_transition_set_animatable (ClutterTransition *transition, + ClutterAnimatable *animatable); +CLUTTER_AVAILABLE_IN_1_10 +ClutterAnimatable * clutter_transition_get_animatable (ClutterTransition *transition); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_transition_set_remove_on_complete (ClutterTransition *transition, + gboolean remove_complete); +CLUTTER_AVAILABLE_IN_1_10 +gboolean clutter_transition_get_remove_on_complete (ClutterTransition *transition); + +G_END_DECLS + +#endif /* __CLUTTER_TRANSITION_H__ */ diff --git a/clutter/clutter/clutter-types.h b/clutter/clutter/clutter-types.h new file mode 100644 index 0000000..bc71c7d --- /dev/null +++ b/clutter/clutter/clutter-types.h @@ -0,0 +1,776 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __CLUTTER_TYPES_H__ +#define __CLUTTER_TYPES_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_ACTOR_BOX (clutter_actor_box_get_type ()) +#define CLUTTER_TYPE_FOG (clutter_fog_get_type ()) +#define CLUTTER_TYPE_GEOMETRY (clutter_geometry_get_type ()) +#define CLUTTER_TYPE_KNOT (clutter_knot_get_type ()) +#define CLUTTER_TYPE_MARGIN (clutter_margin_get_type ()) +#define CLUTTER_TYPE_MATRIX (clutter_matrix_get_type ()) +#define CLUTTER_TYPE_PAINT_VOLUME (clutter_paint_volume_get_type ()) +#define CLUTTER_TYPE_PERSPECTIVE (clutter_perspective_get_type ()) +#define CLUTTER_TYPE_VERTEX (clutter_vertex_get_type ()) +#define CLUTTER_TYPE_POINT (clutter_point_get_type ()) +#define CLUTTER_TYPE_SIZE (clutter_size_get_type ()) +#define CLUTTER_TYPE_RECT (clutter_rect_get_type ()) + +typedef struct _ClutterActor ClutterActor; + +typedef struct _ClutterStage ClutterStage; +typedef struct _ClutterFrameInfo ClutterFrameInfo; +typedef struct _ClutterContainer ClutterContainer; /* dummy */ +typedef struct _ClutterChildMeta ClutterChildMeta; +typedef struct _ClutterLayoutMeta ClutterLayoutMeta; +typedef struct _ClutterActorMeta ClutterActorMeta; +typedef struct _ClutterLayoutManager ClutterLayoutManager; +typedef struct _ClutterActorIter ClutterActorIter; +typedef struct _ClutterPaintNode ClutterPaintNode; +typedef struct _ClutterContent ClutterContent; /* dummy */ +typedef struct _ClutterScrollActor ClutterScrollActor; + +typedef struct _ClutterInterval ClutterInterval; +typedef struct _ClutterAnimatable ClutterAnimatable; /* dummy */ +typedef struct _ClutterTimeline ClutterTimeline; +typedef struct _ClutterTransition ClutterTransition; +typedef struct _ClutterPropertyTransition ClutterPropertyTransition; +typedef struct _ClutterKeyframeTransition ClutterKeyframeTransition; +typedef struct _ClutterTransitionGroup ClutterTransitionGroup; + +typedef struct _ClutterAction ClutterAction; +typedef struct _ClutterConstraint ClutterConstraint; +typedef struct _ClutterEffect ClutterEffect; + +typedef struct _ClutterPath ClutterPath; +typedef struct _ClutterPathNode ClutterPathNode; + +typedef struct _ClutterActorBox ClutterActorBox; +typedef struct _ClutterColor ClutterColor; +typedef struct _ClutterGeometry ClutterGeometry; /* XXX:2.0 - remove */ +typedef struct _ClutterKnot ClutterKnot; +typedef struct _ClutterMargin ClutterMargin; +typedef struct _ClutterPerspective ClutterPerspective; +typedef struct _ClutterPoint ClutterPoint; +typedef struct _ClutterRect ClutterRect; +typedef struct _ClutterSize ClutterSize; +typedef struct _ClutterVertex ClutterVertex; + +typedef struct _ClutterAlpha ClutterAlpha; +typedef struct _ClutterAnimation ClutterAnimation; +typedef struct _ClutterAnimator ClutterAnimator; +typedef struct _ClutterState ClutterState; + +typedef struct _ClutterInputDeviceTool ClutterInputDeviceTool; +typedef struct _ClutterInputDevice ClutterInputDevice; +typedef struct _ClutterVirtualInputDevice ClutterVirtualInputDevice; + +typedef CoglMatrix ClutterMatrix; + +typedef union _ClutterEvent ClutterEvent; + +/** + * ClutterEventSequence: + * + * The #ClutterEventSequence structure is an opaque + * type used to denote the event sequence of a touch event. + * + * Since: 1.12 + */ +typedef struct _ClutterEventSequence ClutterEventSequence; + +typedef struct _ClutterFog ClutterFog; /* deprecated */ +typedef struct _ClutterBehaviour ClutterBehaviour; /* deprecated */ +typedef struct _ClutterShader ClutterShader; /* deprecated */ + +/** + * ClutterPaintVolume: + * + * #ClutterPaintVolume is an opaque structure + * whose members cannot be directly accessed. + * + * A #ClutterPaintVolume represents an + * a bounding volume whose internal representation isn't defined but + * can be set and queried in terms of an axis aligned bounding box. + * + * A #ClutterPaintVolume for a #ClutterActor + * is defined to be relative from the current actor modelview matrix. + * + * Other internal representation and methods for describing the + * bounding volume may be added in the future. + * + * Since: 1.4 + */ +typedef struct _ClutterPaintVolume ClutterPaintVolume; + +/** + * ClutterPoint: + * @x: X coordinate, in pixels + * @y: Y coordinate, in pixels + * + * A point in 2D space. + * + * Since: 1.12 + */ +struct _ClutterPoint +{ + float x; + float y; +}; + +/** + * CLUTTER_POINT_INIT: + * @x: X coordinate + * @y: Y coordinate + * + * A simple macro for initializing a #ClutterPoint when declaring it, e.g.: + * + * |[ + * ClutterPoint p = CLUTTER_POINT_INIT (100, 100); + * ]| + * + * Since: 1.12 + */ +#define CLUTTER_POINT_INIT(x,y) { (x), (y) } + +/** + * CLUTTER_POINT_INIT_ZERO: + * + * A simple macro for initializing a #ClutterPoint to (0, 0) when + * declaring it. + * + * Since: 1.12 + */ +#define CLUTTER_POINT_INIT_ZERO CLUTTER_POINT_INIT (0.f, 0.f) + +CLUTTER_AVAILABLE_IN_1_12 +GType clutter_point_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_12 +const ClutterPoint * clutter_point_zero (void); +CLUTTER_AVAILABLE_IN_1_12 +ClutterPoint * clutter_point_alloc (void); +CLUTTER_AVAILABLE_IN_1_12 +ClutterPoint * clutter_point_init (ClutterPoint *point, + float x, + float y); +CLUTTER_AVAILABLE_IN_1_12 +ClutterPoint * clutter_point_copy (const ClutterPoint *point); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_point_free (ClutterPoint *point); +CLUTTER_AVAILABLE_IN_1_12 +gboolean clutter_point_equals (const ClutterPoint *a, + const ClutterPoint *b); +CLUTTER_AVAILABLE_IN_1_12 +float clutter_point_distance (const ClutterPoint *a, + const ClutterPoint *b, + float *x_distance, + float *y_distance); + +/** + * ClutterSize: + * @width: the width, in pixels + * @height: the height, in pixels + * + * A size, in 2D space. + * + * Since: 1.12 + */ +struct _ClutterSize +{ + float width; + float height; +}; + +/** + * CLUTTER_SIZE_INIT: + * @width: the width + * @height: the height + * + * A simple macro for initializing a #ClutterSize when declaring it, e.g.: + * + * |[ + * ClutterSize s = CLUTTER_SIZE_INIT (200, 200); + * ]| + * + * Since: 1.12 + */ +#define CLUTTER_SIZE_INIT(width,height) { (width), (height) } + +/** + * CLUTTER_SIZE_INIT_ZERO: + * + * A simple macro for initializing a #ClutterSize to (0, 0) when + * declaring it. + * + * Since: 1.12 + */ +#define CLUTTER_SIZE_INIT_ZERO CLUTTER_SIZE_INIT (0.f, 0.f) + +CLUTTER_AVAILABLE_IN_1_12 +GType clutter_size_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_12 +ClutterSize * clutter_size_alloc (void); +CLUTTER_AVAILABLE_IN_1_12 +ClutterSize * clutter_size_init (ClutterSize *size, + float width, + float height); +CLUTTER_AVAILABLE_IN_1_12 +ClutterSize * clutter_size_copy (const ClutterSize *size); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_size_free (ClutterSize *size); +CLUTTER_AVAILABLE_IN_1_12 +gboolean clutter_size_equals (const ClutterSize *a, + const ClutterSize *b); + +/** + * ClutterRect: + * @origin: the origin of the rectangle + * @size: the size of the rectangle + * + * The location and size of a rectangle. + * + * The width and height of a #ClutterRect can be negative; Clutter considers + * a rectangle with an origin of [ 0.0, 0.0 ] and a size of [ 10.0, 10.0 ] to + * be equivalent to a rectangle with origin of [ 10.0, 10.0 ] and size of + * [ -10.0, -10.0 ]. + * + * Application code can normalize rectangles using clutter_rect_normalize(): + * this function will ensure that the width and height of a #ClutterRect are + * positive values. All functions taking a #ClutterRect as an argument will + * implicitly normalize it before computing eventual results. For this reason + * it is safer to access the contents of a #ClutterRect by using the provided + * API at all times, instead of directly accessing the structure members. + * + * Since: 1.12 + */ +struct _ClutterRect +{ + ClutterPoint origin; + ClutterSize size; +}; + +/** + * CLUTTER_RECT_INIT: + * @x: the X coordinate + * @y: the Y coordinate + * @width: the width + * @height: the height + * + * A simple macro for initializing a #ClutterRect when declaring it, e.g.: + * + * |[ + * ClutterRect r = CLUTTER_RECT_INIT (100, 100, 200, 200); + * ]| + * + * Since: 1.12 + */ +#define CLUTTER_RECT_INIT(x,y,width,height) { { (x), (y) }, { (width), (height) } } + +/** + * CLUTTER_RECT_INIT_ZERO: + * + * A simple macro for initializing a #ClutterRect to (0, 0, 0, 0) when + * declaring it. + * + * Since: 1.12 + */ +#define CLUTTER_RECT_INIT_ZERO CLUTTER_RECT_INIT (0.f, 0.f, 0.f, 0.f) + +CLUTTER_AVAILABLE_IN_1_12 +GType clutter_rect_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_12 +const ClutterRect * clutter_rect_zero (void); +CLUTTER_AVAILABLE_IN_1_12 +ClutterRect * clutter_rect_alloc (void); +CLUTTER_AVAILABLE_IN_1_12 +ClutterRect * clutter_rect_init (ClutterRect *rect, + float x, + float y, + float width, + float height); +CLUTTER_AVAILABLE_IN_1_12 +ClutterRect * clutter_rect_copy (const ClutterRect *rect); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_rect_free (ClutterRect *rect); +CLUTTER_AVAILABLE_IN_1_12 +gboolean clutter_rect_equals (ClutterRect *a, + ClutterRect *b); + +CLUTTER_AVAILABLE_IN_1_12 +ClutterRect * clutter_rect_normalize (ClutterRect *rect); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_rect_get_center (ClutterRect *rect, + ClutterPoint *center); +CLUTTER_AVAILABLE_IN_1_12 +gboolean clutter_rect_contains_point (ClutterRect *rect, + ClutterPoint *point); +CLUTTER_AVAILABLE_IN_1_12 +gboolean clutter_rect_contains_rect (ClutterRect *a, + ClutterRect *b); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_rect_union (ClutterRect *a, + ClutterRect *b, + ClutterRect *res); +CLUTTER_AVAILABLE_IN_1_12 +gboolean clutter_rect_intersection (ClutterRect *a, + ClutterRect *b, + ClutterRect *res); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_rect_offset (ClutterRect *rect, + float d_x, + float d_y); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_rect_inset (ClutterRect *rect, + float d_x, + float d_y); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_rect_clamp_to_pixel (ClutterRect *rect); +CLUTTER_AVAILABLE_IN_1_12 +float clutter_rect_get_x (ClutterRect *rect); +CLUTTER_AVAILABLE_IN_1_12 +float clutter_rect_get_y (ClutterRect *rect); +CLUTTER_AVAILABLE_IN_1_12 +float clutter_rect_get_width (ClutterRect *rect); +CLUTTER_AVAILABLE_IN_1_12 +float clutter_rect_get_height (ClutterRect *rect); + +/** + * ClutterVertex: + * @x: X coordinate of the vertex + * @y: Y coordinate of the vertex + * @z: Z coordinate of the vertex + * + * A point in 3D space, expressed in pixels + * + * Since: 0.4 + */ +struct _ClutterVertex +{ + gfloat x; + gfloat y; + gfloat z; +}; + +/** + * CLUTTER_VERTEX_INIT: + * @x: the X coordinate of the vertex + * @y: the Y coordinate of the vertex + * @z: the Z coordinate of the vertex + * + * A simple macro for initializing a #ClutterVertex when declaring it, e.g.: + * + * |[ + * ClutterVertex v = CLUTTER_VERTEX_INIT (x, y, z); + * ]| + * + * Since: 1.10 + */ +#define CLUTTER_VERTEX_INIT(x,y,z) { (x), (y), (z) } + +/** + * CLUTTER_VERTEX_INIT_ZERO: + * + * A simple macro for initializing a #ClutterVertex to (0, 0, 0). + * + * Since: 1.12 + */ +#define CLUTTER_VERTEX_INIT_ZERO CLUTTER_VERTEX_INIT (0.f, 0.f, 0.f) + +CLUTTER_AVAILABLE_IN_ALL +GType clutter_vertex_get_type (void) G_GNUC_CONST; +CLUTTER_AVAILABLE_IN_ALL +ClutterVertex *clutter_vertex_new (gfloat x, + gfloat y, + gfloat z); +CLUTTER_AVAILABLE_IN_1_12 +ClutterVertex *clutter_vertex_alloc (void); +CLUTTER_AVAILABLE_IN_ALL +ClutterVertex *clutter_vertex_init (ClutterVertex *vertex, + gfloat x, + gfloat y, + gfloat z); +CLUTTER_AVAILABLE_IN_ALL +ClutterVertex *clutter_vertex_copy (const ClutterVertex *vertex); +CLUTTER_AVAILABLE_IN_ALL +void clutter_vertex_free (ClutterVertex *vertex); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_vertex_equal (const ClutterVertex *vertex_a, + const ClutterVertex *vertex_b); + +/** + * ClutterActorBox: + * @x1: X coordinate of the top left corner + * @y1: Y coordinate of the top left corner + * @x2: X coordinate of the bottom right corner + * @y2: Y coordinate of the bottom right corner + * + * 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 + * pixels with sub-pixel precision + */ +struct _ClutterActorBox +{ + gfloat x1; + gfloat y1; + + gfloat x2; + gfloat y2; +}; + +/** + * CLUTTER_ACTOR_BOX_INIT: + * @x_1: the X coordinate of the top left corner + * @y_1: the Y coordinate of the top left corner + * @x_2: the X coordinate of the bottom right corner + * @y_2: the Y coordinate of the bottom right corner + * + * A simple macro for initializing a #ClutterActorBox when declaring + * it, e.g.: + * + * |[ + * ClutterActorBox box = CLUTTER_ACTOR_BOX_INIT (0, 0, 400, 600); + * ]| + * + * Since: 1.10 + */ +#define CLUTTER_ACTOR_BOX_INIT(x_1,y_1,x_2,y_2) { (x_1), (y_1), (x_2), (y_2) } + +/** + * CLUTTER_ACTOR_BOX_INIT_ZERO: + * + * A simple macro for initializing a #ClutterActorBox to 0 when + * declaring it, e.g.: + * + * |[ + * ClutterActorBox box = CLUTTER_ACTOR_BOX_INIT_ZERO; + * ]| + * + * Since: 1.12 + */ +#define CLUTTER_ACTOR_BOX_INIT_ZERO CLUTTER_ACTOR_BOX_INIT (0.f, 0.f, 0.f, 0.f) + +CLUTTER_AVAILABLE_IN_ALL +GType clutter_actor_box_get_type (void) G_GNUC_CONST; +CLUTTER_AVAILABLE_IN_ALL +ClutterActorBox *clutter_actor_box_new (gfloat x_1, + gfloat y_1, + gfloat x_2, + gfloat y_2); +CLUTTER_AVAILABLE_IN_1_12 +ClutterActorBox *clutter_actor_box_alloc (void); +CLUTTER_AVAILABLE_IN_ALL +ClutterActorBox *clutter_actor_box_init (ClutterActorBox *box, + gfloat x_1, + gfloat y_1, + gfloat x_2, + gfloat y_2); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_box_init_rect (ClutterActorBox *box, + gfloat x, + gfloat y, + gfloat width, + gfloat height); +CLUTTER_AVAILABLE_IN_ALL +ClutterActorBox *clutter_actor_box_copy (const ClutterActorBox *box); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_box_free (ClutterActorBox *box); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_actor_box_equal (const ClutterActorBox *box_a, + const ClutterActorBox *box_b); +CLUTTER_AVAILABLE_IN_ALL +gfloat clutter_actor_box_get_x (const ClutterActorBox *box); +CLUTTER_AVAILABLE_IN_ALL +gfloat clutter_actor_box_get_y (const ClutterActorBox *box); +CLUTTER_AVAILABLE_IN_ALL +gfloat clutter_actor_box_get_width (const ClutterActorBox *box); +CLUTTER_AVAILABLE_IN_ALL +gfloat clutter_actor_box_get_height (const ClutterActorBox *box); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_box_get_origin (const ClutterActorBox *box, + gfloat *x, + gfloat *y); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_box_get_size (const ClutterActorBox *box, + gfloat *width, + gfloat *height); +CLUTTER_AVAILABLE_IN_ALL +gfloat clutter_actor_box_get_area (const ClutterActorBox *box); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_actor_box_contains (const ClutterActorBox *box, + gfloat x, + gfloat y); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_box_from_vertices (ClutterActorBox *box, + const ClutterVertex verts[]); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_box_interpolate (const ClutterActorBox *initial, + const ClutterActorBox *final, + gdouble progress, + ClutterActorBox *result); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_box_clamp_to_pixel (ClutterActorBox *box); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_box_union (const ClutterActorBox *a, + const ClutterActorBox *b, + ClutterActorBox *result); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_box_set_origin (ClutterActorBox *box, + gfloat x, + gfloat y); +CLUTTER_AVAILABLE_IN_ALL +void clutter_actor_box_set_size (ClutterActorBox *box, + gfloat width, + gfloat height); + +/** + * ClutterGeometry: + * @x: X coordinate of the top left corner of an actor + * @y: Y coordinate of the top left corner of an actor + * @width: width of an actor + * @height: height of an actor + * + * The rectangle containing an actor's bounding box, measured in pixels. + * + * You should not use #ClutterGeometry, or operate on its fields + * directly; you should use #cairo_rectangle_int_t or #ClutterRect if you + * need a rectangle type, depending on the precision required. + * + * Deprecated: 1.16 + */ +struct _ClutterGeometry +{ + /*< public >*/ + gint x; + gint y; + guint width; + guint height; +}; + +CLUTTER_AVAILABLE_IN_ALL +GType clutter_geometry_get_type (void) G_GNUC_CONST; + +CLUTTER_DEPRECATED_IN_1_16 +void clutter_geometry_union (const ClutterGeometry *geometry_a, + const ClutterGeometry *geometry_b, + ClutterGeometry *result); +CLUTTER_DEPRECATED_IN_1_16 +gboolean clutter_geometry_intersects (const ClutterGeometry *geometry0, + const ClutterGeometry *geometry1); + +/** + * ClutterKnot: + * @x: X coordinate of the knot + * @y: Y coordinate of the knot + * + * Point in a path behaviour. + * + * Since: 0.2 + */ +struct _ClutterKnot +{ + gint x; + gint y; +}; + +CLUTTER_AVAILABLE_IN_ALL +GType clutter_knot_get_type (void) G_GNUC_CONST; +CLUTTER_AVAILABLE_IN_ALL +ClutterKnot *clutter_knot_copy (const ClutterKnot *knot); +CLUTTER_AVAILABLE_IN_ALL +void clutter_knot_free (ClutterKnot *knot); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_knot_equal (const ClutterKnot *knot_a, + const ClutterKnot *knot_b); + +/** + * ClutterPathNode: + * @type: the node's type + * @points: the coordinates of the node + * + * Represents a single node of a #ClutterPath. + * + * Some of the coordinates in @points may be unused for some node + * types. %CLUTTER_PATH_MOVE_TO and %CLUTTER_PATH_LINE_TO use only one + * pair of coordinates, %CLUTTER_PATH_CURVE_TO uses all three and + * %CLUTTER_PATH_CLOSE uses none. + * + * Since: 1.0 + */ +struct _ClutterPathNode +{ + ClutterPathNodeType type; + + ClutterKnot points[3]; +}; + +CLUTTER_AVAILABLE_IN_1_0 +GType clutter_path_node_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_0 +ClutterPathNode *clutter_path_node_copy (const ClutterPathNode *node); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_path_node_free (ClutterPathNode *node); +CLUTTER_AVAILABLE_IN_1_0 +gboolean clutter_path_node_equal (const ClutterPathNode *node_a, + const ClutterPathNode *node_b); + +/* + * ClutterPaintVolume + */ + +CLUTTER_AVAILABLE_IN_1_2 +GType clutter_paint_volume_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_2 +ClutterPaintVolume *clutter_paint_volume_copy (const ClutterPaintVolume *pv); +CLUTTER_AVAILABLE_IN_1_2 +void clutter_paint_volume_free (ClutterPaintVolume *pv); + +CLUTTER_AVAILABLE_IN_1_2 +void clutter_paint_volume_set_origin (ClutterPaintVolume *pv, + const ClutterVertex *origin); +CLUTTER_AVAILABLE_IN_1_2 +void clutter_paint_volume_get_origin (const ClutterPaintVolume *pv, + ClutterVertex *vertex); +CLUTTER_AVAILABLE_IN_1_2 +void clutter_paint_volume_set_width (ClutterPaintVolume *pv, + gfloat width); +CLUTTER_AVAILABLE_IN_1_2 +gfloat clutter_paint_volume_get_width (const ClutterPaintVolume *pv); +CLUTTER_AVAILABLE_IN_1_2 +void clutter_paint_volume_set_height (ClutterPaintVolume *pv, + gfloat height); +CLUTTER_AVAILABLE_IN_1_2 +gfloat clutter_paint_volume_get_height (const ClutterPaintVolume *pv); +CLUTTER_AVAILABLE_IN_1_2 +void clutter_paint_volume_set_depth (ClutterPaintVolume *pv, + gfloat depth); +CLUTTER_AVAILABLE_IN_1_2 +gfloat clutter_paint_volume_get_depth (const ClutterPaintVolume *pv); +CLUTTER_AVAILABLE_IN_1_2 +void clutter_paint_volume_union (ClutterPaintVolume *pv, + const ClutterPaintVolume *another_pv); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_paint_volume_union_box (ClutterPaintVolume *pv, + const ClutterActorBox *box); + +CLUTTER_AVAILABLE_IN_1_2 +gboolean clutter_paint_volume_set_from_allocation (ClutterPaintVolume *pv, + ClutterActor *actor); + +/** + * ClutterMargin: + * @left: the margin from the left + * @right: the margin from the right + * @top: the margin from the top + * @bottom: the margin from the bottom + * + * A representation of the components of a margin. + * + * Since: 1.10 + */ +struct _ClutterMargin +{ + float left; + float right; + float top; + float bottom; +}; + +CLUTTER_AVAILABLE_IN_1_10 +GType clutter_margin_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_10 +ClutterMargin * clutter_margin_new (void) G_GNUC_MALLOC; +CLUTTER_AVAILABLE_IN_1_10 +ClutterMargin * clutter_margin_copy (const ClutterMargin *margin_); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_margin_free (ClutterMargin *margin_); + +/** + * ClutterProgressFunc: + * @a: the initial value of an interval + * @b: the final value of an interval + * @progress: the progress factor, between 0 and 1 + * @retval: the value used to store the progress + * + * Prototype of the progress function used to compute the value + * between the two ends @a and @b of an interval depending on + * the value of @progress. + * + * The #GValue in @retval is already initialized with the same + * type as @a and @b. + * + * This function will be called by #ClutterInterval if the + * type of the values of the interval was registered using + * clutter_interval_register_progress_func(). + * + * Return value: %TRUE if the function successfully computed + * the value and stored it inside @retval + * + * Since: 1.0 + */ +typedef gboolean (* ClutterProgressFunc) (const GValue *a, + const GValue *b, + gdouble progress, + GValue *retval); + +CLUTTER_AVAILABLE_IN_1_0 +void clutter_interval_register_progress_func (GType value_type, + ClutterProgressFunc func); + +CLUTTER_AVAILABLE_IN_1_12 +GType clutter_matrix_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_12 +ClutterMatrix * clutter_matrix_alloc (void); +CLUTTER_AVAILABLE_IN_1_12 +ClutterMatrix * clutter_matrix_init_identity (ClutterMatrix *matrix); +CLUTTER_AVAILABLE_IN_1_12 +ClutterMatrix * clutter_matrix_init_from_array (ClutterMatrix *matrix, + const float values[16]); +CLUTTER_AVAILABLE_IN_1_12 +ClutterMatrix * clutter_matrix_init_from_matrix (ClutterMatrix *a, + const ClutterMatrix *b); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_matrix_free (ClutterMatrix *matrix); + +G_END_DECLS + +#endif /* __CLUTTER_TYPES_H__ */ diff --git a/clutter/clutter/clutter-units.c b/clutter/clutter/clutter-units.c new file mode 100644 index 0000000..64ac570 --- /dev/null +++ b/clutter/clutter/clutter-units.c @@ -0,0 +1,934 @@ +/* -*- mode:C; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By: Tomas Frydrych + * Emmanuele Bassi + * + * Copyright (C) 2007 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +/** + * SECTION:clutter-units + * @short_description: A logical distance unit + * + * #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 #ClutterActorClass.allocate() virtual function, or inside the + * #ClutterActorClass.get_preferred_width() and #ClutterActorClass.get_preferred_height() + * virtual functions. + * + * In order to register a #ClutterUnits property, the #ClutterParamSpecUnits + * #GParamSpec sub-class should be used: + * + * |[ + * GParamSpec *pspec; + * + * 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_units() + * and clutter_value_get_units(). #GValues containing a #ClutterUnits + * value can also be transformed to #GValues initialized with + * %G_TYPE_INT, %G_TYPE_FLOAT and %G_TYPE_STRING through implicit conversion + * and using g_value_transform(). + * + * #ClutterUnits is available since Clutter 1.0 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#include +#include + +#include "clutter-backend-private.h" +#include "clutter-interval.h" +#include "clutter-private.h" +#include "clutter-units.h" + +#define DPI_FALLBACK (96.0) + +#define FLOAT_EPSILON (1e-30) + +static gfloat +units_mm_to_pixels (gfloat mm) +{ + ClutterBackend *backend; + gdouble dpi; + + backend = clutter_get_default_backend (); + dpi = clutter_backend_get_resolution (backend); + if (dpi < 0) + dpi = DPI_FALLBACK; + + return mm * dpi / 25.4; +} + +static gfloat +units_cm_to_pixels (gfloat cm) +{ + return units_mm_to_pixels (cm * 10); +} + +static gfloat +units_pt_to_pixels (gfloat pt) +{ + ClutterBackend *backend; + gdouble dpi; + + backend = clutter_get_default_backend (); + dpi = clutter_backend_get_resolution (backend); + if (dpi < 0) + dpi = DPI_FALLBACK; + + 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_from_mm: + * @units: (out caller-allocates): a #ClutterUnits + * @mm: millimeters + * + * Stores a value in millimiters inside @units + * + * Since: 1.0 + */ +void +clutter_units_from_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; + units->serial = _clutter_backend_get_units_serial (backend); +} + +/** + * clutter_units_from_cm: + * @units: (out caller-allocates): a #ClutterUnits + * @cm: centimeters + * + * Stores a value in centimeters inside @units + * + * Since: 1.2 + */ +void +clutter_units_from_cm (ClutterUnits *units, + gfloat cm) +{ + ClutterBackend *backend; + + g_return_if_fail (units != NULL); + + backend = clutter_get_default_backend (); + + units->unit_type = CLUTTER_UNIT_CM; + units->value = cm; + units->pixels = units_cm_to_pixels (cm); + units->pixels_set = TRUE; + units->serial = _clutter_backend_get_units_serial (backend); +} + +/** + * clutter_units_from_pt: + * @units: (out caller-allocates): a #ClutterUnits + * @pt: typographic points + * + * Stores a value in typographic points inside @units + * + * Since: 1.0 + */ +void +clutter_units_from_pt (ClutterUnits *units, + gfloat pt) +{ + ClutterBackend *backend; + + g_return_if_fail (units != NULL); + + backend = clutter_get_default_backend (); + + units->unit_type = CLUTTER_UNIT_POINT; + units->value = pt; + units->pixels = units_pt_to_pixels (pt); + units->pixels_set = TRUE; + units->serial = _clutter_backend_get_units_serial (backend); +} + +/** + * clutter_units_from_em: + * @units: (out caller-allocates): 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_from_em (ClutterUnits *units, + gfloat em) +{ + ClutterBackend *backend; + + g_return_if_fail (units != NULL); + + backend = clutter_get_default_backend (); + + units->unit_type = CLUTTER_UNIT_EM; + units->value = em; + units->pixels = units_em_to_pixels (NULL, em); + units->pixels_set = TRUE; + units->serial = _clutter_backend_get_units_serial (backend); +} + +/** + * clutter_units_from_em_for_font: + * @units: (out caller-allocates): a #ClutterUnits + * @font_name: (allow-none): the font name and size + * @em: em + * + * Stores a value in em inside @units using @font_name + * + * Since: 1.0 + */ +void +clutter_units_from_em_for_font (ClutterUnits *units, + const gchar *font_name, + gfloat em) +{ + ClutterBackend *backend; + + g_return_if_fail (units != NULL); + + backend = clutter_get_default_backend (); + + units->unit_type = CLUTTER_UNIT_EM; + units->value = em; + units->pixels = units_em_to_pixels (font_name, em); + units->pixels_set = TRUE; + units->serial = _clutter_backend_get_units_serial (backend); +} + +/** + * clutter_units_from_pixels: + * @units: (out caller-allocates): a #ClutterUnits + * @px: pixels + * + * Stores a value in pixels inside @units + * + * Since: 1.0 + */ +void +clutter_units_from_pixels (ClutterUnits *units, + gint px) +{ + ClutterBackend *backend; + + g_return_if_fail (units != NULL); + + backend = clutter_get_default_backend (); + + units->unit_type = CLUTTER_UNIT_PIXEL; + units->value = px; + units->pixels = px; + units->pixels_set = TRUE; + units->serial = _clutter_backend_get_units_serial (backend); +} + +/** + * 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: (transfer full): 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); +} + +/** + * clutter_units_to_pixels: + * @units: units to convert + * + * Converts a value in #ClutterUnits to pixels + * + * Return value: the value in pixels + * + * Since: 1.0 + */ +gfloat +clutter_units_to_pixels (ClutterUnits *units) +{ + ClutterBackend *backend; + + g_return_val_if_fail (units != NULL, 0.0); + + /* if the backend settings changed we evict the cached value */ + backend = clutter_get_default_backend (); + if (units->serial != _clutter_backend_get_units_serial (backend)) + units->pixels_set = FALSE; + + 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_CM: + units->pixels = units_cm_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; + units->serial = _clutter_backend_get_units_serial (backend); + + return units->pixels; +} + +/** + * clutter_units_from_string: + * @units: (out caller-allocates): a #ClutterUnits + * @str: the string to convert + * + * Parses a value and updates @units with it + * + * A #ClutterUnits expressed in string should match: + * + * |[ + * units: wsp* unit-value wsp* unit-name? wsp* + * unit-value: number + * unit-name: 'px' | 'pt' | 'mm' | 'em' | 'cm' + * number: digit+ + * | digit* sep digit+ + * sep: '.' | ',' + * digit: '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' + * wsp: (#0x20 | #0x9 | #0xA | #0xB | #0xC | #0xD)+ + * ]| + * + * For instance, these are valid strings: + * + * |[ + * 10 px + * 5.1 em + * 24 pt + * 12.6 mm + * .3 cm + * ]| + * + * While these are not: + * + * |[ + * 42 cats + * omg!1!ponies + * ]| + * + * If no unit is specified, pixels are assumed. + * + * Return value: %TRUE if the string was successfully parsed, + * and %FALSE otherwise + * + * Since: 1.0 + */ +gboolean +clutter_units_from_string (ClutterUnits *units, + const gchar *str) +{ + ClutterBackend *backend; + ClutterUnitType unit_type; + gfloat value; + + g_return_val_if_fail (units != NULL, FALSE); + g_return_val_if_fail (str != NULL, FALSE); + + /* strip leading space */ + while (g_ascii_isspace (*str)) + str++; + + if (*str == '\0') + return FALSE; + + /* integer part */ + value = (gfloat) strtoul (str, (char **) &str, 10); + + if (*str == '.' || *str == ',') + { + gfloat divisor = 0.1; + + /* 5.cm is not a valid number */ + if (!g_ascii_isdigit (*++str)) + return FALSE; + + while (g_ascii_isdigit (*str)) + { + value += (*str - '0') * divisor; + divisor *= 0.1; + str++; + } + } + + while (g_ascii_isspace (*str)) + str++; + + /* assume pixels by default, if no unit is specified */ + if (*str == '\0') + unit_type = CLUTTER_UNIT_PIXEL; + else if (strncmp (str, "em", 2) == 0) + { + unit_type = CLUTTER_UNIT_EM; + str += 2; + } + else if (strncmp (str, "mm", 2) == 0) + { + unit_type = CLUTTER_UNIT_MM; + str += 2; + } + else if (strncmp (str, "cm", 2) == 0) + { + unit_type = CLUTTER_UNIT_CM; + str += 2; + } + else if (strncmp (str, "pt", 2) == 0) + { + unit_type = CLUTTER_UNIT_POINT; + str += 2; + } + else if (strncmp (str, "px", 2) == 0) + { + unit_type = CLUTTER_UNIT_PIXEL; + str += 2; + } + else + return FALSE; + + /* ensure the unit is only followed by white space */ + while (g_ascii_isspace (*str)) + str++; + if (*str != '\0') + return FALSE; + + backend = clutter_get_default_backend (); + + units->unit_type = unit_type; + units->value = value; + units->pixels_set = FALSE; + units->serial = _clutter_backend_get_units_serial (backend); + + return TRUE; +} + +static const gchar * +clutter_unit_type_name (ClutterUnitType unit_type) +{ + switch (unit_type) + { + case CLUTTER_UNIT_MM: + return "mm"; + + case CLUTTER_UNIT_CM: + return "cm"; + + 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 ""; +} + +/** + * 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 output + * + * Fractional values are truncated to the second decimal + * position for em, mm and cm, and to the first decimal position for + * typographic points. Pixels are integers. + * + * 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 = NULL; + const gchar *fmt = NULL; + gchar buf[G_ASCII_DTOSTR_BUF_SIZE]; + + g_return_val_if_fail (units != NULL, NULL); + + switch (units->unit_type) + { + /* special case: there is no such thing as "half a pixel", so + * we round up to the nearest integer using C default + */ + case CLUTTER_UNIT_PIXEL: + return g_strdup_printf ("%d px", (int) units->value); + + case CLUTTER_UNIT_MM: + unit_name = "mm"; + fmt = "%.2f"; + break; + + case CLUTTER_UNIT_CM: + unit_name = "cm"; + fmt = "%.2f"; + break; + + case CLUTTER_UNIT_POINT: + unit_name = "pt"; + fmt = "%.1f"; + break; + + case CLUTTER_UNIT_EM: + unit_name = "em"; + fmt = "%.2f"; + break; + + default: + g_assert_not_reached (); + break; + } + + g_ascii_formatd (buf, G_ASCII_DTOSTR_BUF_SIZE, fmt, units->value); + + return g_strconcat (buf, " ", unit_name, NULL); +} + +/* + * ClutterInterval integration + */ + +static gboolean +clutter_units_progress (const GValue *a, + const GValue *b, + gdouble progress, + GValue *retval) +{ + ClutterUnits *a_units = (ClutterUnits *) clutter_value_get_units (a); + ClutterUnits *b_units = (ClutterUnits *) clutter_value_get_units (b); + ClutterUnits res; + gfloat a_px, b_px, value; + + a_px = clutter_units_to_pixels (a_units); + b_px = clutter_units_to_pixels (b_units); + value = progress * (b_px - a_px) + a_px; + + clutter_units_from_pixels (&res, value); + clutter_value_set_units (retval, &res); + + return TRUE; +} + +/* + * GValue and GParamSpec integration + */ + +/* units to integer */ +static void +clutter_value_transform_units_int (const GValue *src, + GValue *dest) +{ + dest->data[0].v_int = clutter_units_to_pixels (src->data[0].v_pointer); +} + +/* integer to units */ +static void +clutter_value_transform_int_units (const GValue *src, + GValue *dest) +{ + clutter_units_from_pixels (dest->data[0].v_pointer, src->data[0].v_int); +} + +/* units to float */ +static void +clutter_value_transform_units_float (const GValue *src, + GValue *dest) +{ + dest->data[0].v_float = clutter_units_to_pixels (src->data[0].v_pointer); +} + +/* float to units */ +static void +clutter_value_transform_float_units (const GValue *src, + GValue *dest) +{ + clutter_units_from_pixels (dest->data[0].v_pointer, src->data[0].v_float); +} + +/* units to string */ +static void +clutter_value_transform_units_string (const GValue *src, + GValue *dest) +{ + 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_string_units (const GValue *src, + GValue *dest) +{ + ClutterUnits units = { CLUTTER_UNIT_PIXEL, 0.0f }; + + clutter_units_from_string (&units, g_value_get_string (src)); + + clutter_value_set_units (dest, &units); +} + +G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterUnits, clutter_units, + clutter_units_copy, + clutter_units_free, + CLUTTER_REGISTER_VALUE_TRANSFORM_TO (G_TYPE_INT, clutter_value_transform_units_int) + CLUTTER_REGISTER_VALUE_TRANSFORM_TO (G_TYPE_FLOAT, clutter_value_transform_units_float) + CLUTTER_REGISTER_VALUE_TRANSFORM_TO (G_TYPE_STRING, clutter_value_transform_units_string) + CLUTTER_REGISTER_VALUE_TRANSFORM_FROM (G_TYPE_INT, clutter_value_transform_int_units) + CLUTTER_REGISTER_VALUE_TRANSFORM_FROM (G_TYPE_FLOAT, clutter_value_transform_float_units) + CLUTTER_REGISTER_VALUE_TRANSFORM_FROM (G_TYPE_STRING, clutter_value_transform_string_units) + CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_units_progress)); + +/** + * clutter_value_set_units: + * @value: a #GValue initialized to %CLUTTER_TYPE_UNITS + * @units: the units to set + * + * Sets @value to @units + * + * Since: 0.8 + */ +void +clutter_value_set_units (GValue *value, + const ClutterUnits *units) +{ + g_return_if_fail (CLUTTER_VALUE_HOLDS_UNITS (value)); + + value->data[0].v_pointer = clutter_units_copy (units); +} + +/** + * clutter_value_get_units: + * @value: a #GValue initialized to %CLUTTER_TYPE_UNITS + * + * Gets the #ClutterUnits contained in @value. + * + * Return value: the units inside the passed #GValue + * + * Since: 0.8 + */ +const ClutterUnits * +clutter_value_get_units (const GValue *value) +{ + g_return_val_if_fail (CLUTTER_VALUE_HOLDS_UNITS (value), NULL); + + return value->data[0].v_pointer; +} + +static void +param_units_init (GParamSpec *pspec) +{ + ClutterParamSpecUnits *uspec = CLUTTER_PARAM_SPEC_UNITS (pspec); + + uspec->minimum = -G_MAXFLOAT; + uspec->maximum = G_MAXFLOAT; + uspec->default_value = 0.0f; + uspec->default_type = CLUTTER_UNIT_PIXEL; +} + +static void +param_units_set_default (GParamSpec *pspec, + GValue *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_units_validate (GParamSpec *pspec, + GValue *value) +{ + 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_UNITS (pspec)); + + if (otype != uspec->default_type) + { + gchar *str = clutter_units_to_string (units); + + 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 (uspec->default_type)); + + g_free (str); + + return FALSE; + } + + units->value = CLAMP (units->value, + uspec->minimum, + uspec->maximum); + + return units->value != oval; +} + +static gint +param_units_values_cmp (GParamSpec *pspec, + const GValue *value1, + const GValue *value2) +{ + ClutterUnits *units1 = value1->data[0].v_pointer; + ClutterUnits *units2 = value2->data[0].v_pointer; + gfloat v1, v2; + + if (units1->unit_type == units2->unit_type) + { + v1 = units1->value; + v2 = units2->value; + } + else + { + 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_units_get_type (void) +{ + static GType pspec_type = 0; + + if (G_UNLIKELY (pspec_type == 0)) + { + const GParamSpecTypeInfo pspec_info = { + sizeof (ClutterParamSpecUnits), + 16, + param_units_init, + CLUTTER_TYPE_UNITS, + NULL, + param_units_set_default, + param_units_validate, + param_units_values_cmp, + }; + + pspec_type = g_param_type_register_static (I_("ClutterParamSpecUnit"), + &pspec_info); + } + + return pspec_type; +} + +/** + * clutter_param_spec_units: (skip) + * @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 #ClutterUnits. + * + * Return value: the newly created #GParamSpec + * + * Since: 1.0 + */ +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) +{ + ClutterParamSpecUnits *uspec; + + g_return_val_if_fail (default_value >= minimum && default_value <= maximum, + NULL); + + 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; + + return G_PARAM_SPEC (uspec); +} diff --git a/clutter/clutter/clutter-units.h b/clutter/clutter/clutter-units.h new file mode 100644 index 0000000..549be9f --- /dev/null +++ b/clutter/clutter/clutter-units.h @@ -0,0 +1,184 @@ +/* -*- mode:C; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By: Tomas Frydrych + * Emmanuele Bassu + * + * Copyright (C) 2007, 2008 OpenedHand + * Copyright (C) 2009 Intel Corp. + * + * 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 . + */ + +#ifndef __CLUTTER_UNITS_H__ +#define __CLUTTER_UNITS_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +#include + +G_BEGIN_DECLS + +/** + * ClutterUnits: + * + * An opaque structure, to be used to store sizing and positioning + * values along with their unit. + * + * Since: 1.0 + */ +typedef struct _ClutterUnits ClutterUnits; + +struct _ClutterUnits +{ + /*< private >*/ + ClutterUnitType unit_type; + + gfloat value; + + /* pre-filled by the provided constructors */ + + /* cached pixel value */ + gfloat pixels; + + /* whether the :pixels field is set */ + guint pixels_set; + + /* the serial coming from the backend, used to evict the cache */ + gint32 serial; + + /* padding for eventual expansion */ + gint32 __padding_1; + gint64 __padding_2; +}; + +CLUTTER_AVAILABLE_IN_1_0 +GType clutter_units_get_type (void) G_GNUC_CONST; +CLUTTER_AVAILABLE_IN_1_0 +ClutterUnitType clutter_units_get_unit_type (const ClutterUnits *units); +CLUTTER_AVAILABLE_IN_1_0 +gfloat clutter_units_get_unit_value (const ClutterUnits *units); + +CLUTTER_AVAILABLE_IN_1_0 +ClutterUnits * clutter_units_copy (const ClutterUnits *units); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_units_free (ClutterUnits *units); + +CLUTTER_AVAILABLE_IN_1_0 +void clutter_units_from_pixels (ClutterUnits *units, + gint px); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_units_from_em (ClutterUnits *units, + gfloat em); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_units_from_em_for_font (ClutterUnits *units, + const gchar *font_name, + gfloat em); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_units_from_mm (ClutterUnits *units, + gfloat mm); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_units_from_cm (ClutterUnits *units, + gfloat cm); +CLUTTER_AVAILABLE_IN_1_0 +void clutter_units_from_pt (ClutterUnits *units, + gfloat pt); + +CLUTTER_AVAILABLE_IN_1_0 +gfloat clutter_units_to_pixels (ClutterUnits *units); + +CLUTTER_AVAILABLE_IN_1_0 +gboolean clutter_units_from_string (ClutterUnits *units, + const gchar *str); +CLUTTER_AVAILABLE_IN_1_0 +gchar * clutter_units_to_string (const ClutterUnits *units); + +/* shorthands for the constructors */ +#define clutter_units_pixels clutter_units_from_pixels +#define clutter_units_em clutter_units_from_em +#define clutter_units_em_for_font clutter_units_from_em_for_font +#define clutter_units_mm clutter_units_from_mm +#define clutter_units_cm clutter_units_from_cm +#define clutter_units_pt clutter_units_from_pt + +#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_UNITS: + * @x: a #GValue + * + * Evaluates to %TRUE if @x holds a #ClutterUnits value + * + * Since: 0.8 + */ +#define CLUTTER_VALUE_HOLDS_UNITS(x) (G_VALUE_HOLDS ((x), CLUTTER_TYPE_UNITS)) + +typedef struct _ClutterParamSpecUnits ClutterParamSpecUnits; + +/** + * ClutterParamSpecUnits: (skip) + * @default_type: default type + * @default_value: default value + * @minimum: lower boundary + * @maximum: higher boundary + * + * #GParamSpec subclass for unit based properties. + * + * Since: 1.0 + */ +struct _ClutterParamSpecUnits +{ + /*< private >*/ + GParamSpec parent_instance; + + /*< public >*/ + ClutterUnitType default_type; + + gfloat default_value; + gfloat minimum; + gfloat maximum; +}; + +CLUTTER_AVAILABLE_IN_1_0 +GType clutter_param_units_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_0 +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); + +CLUTTER_AVAILABLE_IN_1_0 +void clutter_value_set_units (GValue *value, + const ClutterUnits *units); +CLUTTER_AVAILABLE_IN_1_0 +const ClutterUnits * clutter_value_get_units (const GValue *value); + +G_END_DECLS + +#endif /* __CLUTTER_UNITS_H__ */ diff --git a/clutter/clutter/clutter-util.c b/clutter/clutter/clutter-util.c new file mode 100644 index 0000000..14ef740 --- /dev/null +++ b/clutter/clutter/clutter-util.c @@ -0,0 +1,682 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +/** + * SECTION:clutter-util + * @short_description: Utility functions + * + * Various miscellaneous utilility functions. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#include "clutter-debug.h" +#include "clutter-main.h" +#include "clutter-interval.h" +#include "clutter-private.h" + +#include "deprecated/clutter-util.h" + +/** + * clutter_util_next_p2: + * @a: Value to get the next power + * + * Calculates the nearest power of two, greater than or equal to @a. + * + * Return value: The nearest power of two, greater or equal to @a. + * + * Deprecated: 1.2 + */ +gint +clutter_util_next_p2 (gint a) +{ + int rval = 1; + + while (rval < a) + rval <<= 1; + + return rval; +} + +/* Help macros to scale from OpenGL <-1,1> coordinates system to + * window coordinates ranging [0,window-size] + */ +#define MTX_GL_SCALE_X(x,w,v1,v2) ((((((x) / (w)) + 1.0f) / 2.0f) * (v1)) + (v2)) +#define MTX_GL_SCALE_Y(y,w,v1,v2) ((v1) - (((((y) / (w)) + 1.0f) / 2.0f) * (v1)) + (v2)) +#define MTX_GL_SCALE_Z(z,w,v1,v2) (MTX_GL_SCALE_X ((z), (w), (v1), (v2))) + +void +_clutter_util_fully_transform_vertices (const CoglMatrix *modelview, + const CoglMatrix *projection, + const float *viewport, + const ClutterVertex *vertices_in, + ClutterVertex *vertices_out, + int n_vertices) +{ + CoglMatrix modelview_projection; + ClutterVertex4 *vertices_tmp; + int i; + + vertices_tmp = g_alloca (sizeof (ClutterVertex4) * n_vertices); + + if (n_vertices >= 4) + { + /* XXX: we should find a way to cache this per actor */ + cogl_matrix_multiply (&modelview_projection, + projection, + modelview); + cogl_matrix_project_points (&modelview_projection, + 3, + sizeof (ClutterVertex), + vertices_in, + sizeof (ClutterVertex4), + vertices_tmp, + n_vertices); + } + else + { + cogl_matrix_transform_points (modelview, + 3, + sizeof (ClutterVertex), + vertices_in, + sizeof (ClutterVertex4), + vertices_tmp, + n_vertices); + + cogl_matrix_project_points (projection, + 3, + sizeof (ClutterVertex4), + vertices_tmp, + sizeof (ClutterVertex4), + vertices_tmp, + n_vertices); + } + + for (i = 0; i < n_vertices; i++) + { + ClutterVertex4 vertex_tmp = vertices_tmp[i]; + ClutterVertex *vertex_out = &vertices_out[i]; + /* Finally translate from OpenGL coords to window coords */ + vertex_out->x = MTX_GL_SCALE_X (vertex_tmp.x, vertex_tmp.w, + viewport[2], viewport[0]); + vertex_out->y = MTX_GL_SCALE_Y (vertex_tmp.y, vertex_tmp.w, + viewport[3], viewport[1]); + } +} + +/*< private > + * _clutter_util_rectangle_union: + * @src1: first rectangle to union + * @src2: second rectangle to union + * @dest: (out): return location for the unioned rectangle + * + * Calculates the union of two rectangles. + * + * The union of rectangles @src1 and @src2 is the smallest rectangle which + * includes both @src1 and @src2 within it. + * + * It is allowed for @dest to be the same as either @src1 or @src2. + * + * This function should really be in Cairo. + */ +void +_clutter_util_rectangle_union (const cairo_rectangle_int_t *src1, + const cairo_rectangle_int_t *src2, + cairo_rectangle_int_t *dest) +{ + int dest_x, dest_y; + + dest_x = MIN (src1->x, src2->x); + dest_y = MIN (src1->y, src2->y); + + dest->width = MAX (src1->x + src1->width, src2->x + src2->width) - dest_x; + dest->height = MAX (src1->y + src1->height, src2->y + src2->height) - dest_y; + dest->x = dest_x; + dest->y = dest_y; +} + +gboolean +_clutter_util_rectangle_intersection (const cairo_rectangle_int_t *src1, + const cairo_rectangle_int_t *src2, + cairo_rectangle_int_t *dest) +{ + int x1, y1, x2, y2; + + x1 = MAX (src1->x, src2->x); + y1 = MAX (src1->y, src2->y); + + x2 = MIN (src1->x + (int) src1->width, src2->x + (int) src2->width); + y2 = MIN (src1->y + (int) src1->height, src2->y + (int) src2->height); + + if (x1 >= x2 || y1 >= y2) + { + dest->x = 0; + dest->y = 0; + dest->width = 0; + dest->height = 0; + + return FALSE; + } + else + { + dest->x = x1; + dest->y = y1; + dest->width = x2 - x1; + dest->height = y2 - y1; + + return TRUE; + } +} + +float +_clutter_util_matrix_determinant (const ClutterMatrix *matrix) +{ + return matrix->xw * matrix->yz * matrix->zy * matrix->wz + - matrix->xz * matrix->yw * matrix->zy * matrix->wz + - matrix->xw * matrix->yy * matrix->zz * matrix->wz + + matrix->xy * matrix->yw * matrix->zz * matrix->wz + + matrix->xz * matrix->yy * matrix->zw * matrix->wz + - matrix->xy * matrix->yz * matrix->zw * matrix->wz + - matrix->xw * matrix->yz * matrix->zx * matrix->wy + + matrix->xz * matrix->yw * matrix->zx * matrix->wy + + matrix->xw * matrix->yx * matrix->zz * matrix->wy + - matrix->xx * matrix->yw * matrix->zz * matrix->wy + - matrix->xz * matrix->yx * matrix->zw * matrix->wy + + matrix->xx * matrix->yz * matrix->zw * matrix->wy + + matrix->xw * matrix->yy * matrix->zx * matrix->wz + - matrix->xy * matrix->yw * matrix->zx * matrix->wz + - matrix->xw * matrix->yx * matrix->zy * matrix->wz + + matrix->xx * matrix->yw * matrix->zy * matrix->wz + + matrix->xy * matrix->yx * matrix->zw * matrix->wz + - matrix->xx * matrix->yy * matrix->zw * matrix->wz + - matrix->xz * matrix->yy * matrix->zx * matrix->ww + + matrix->xy * matrix->yz * matrix->zx * matrix->ww + + matrix->xz * matrix->yx * matrix->zy * matrix->ww + - matrix->xx * matrix->yz * matrix->zy * matrix->ww + - matrix->xy * matrix->yx * matrix->zz * matrix->ww + + matrix->xx * matrix->yy * matrix->zz * matrix->ww; +} + +static void +_clutter_util_matrix_transpose_vector4_transform (const ClutterMatrix *matrix, + const ClutterVertex4 *point, + ClutterVertex4 *res) +{ + res->x = matrix->xx * point->x + + matrix->xy * point->y + + matrix->xz * point->z + + matrix->xw * point->w; + + res->y = matrix->yx * point->x + + matrix->yy * point->y + + matrix->yz * point->z + + matrix->yw * point->w; + + res->z = matrix->zx * point->x + + matrix->zy * point->y + + matrix->zz * point->z + + matrix->zw * point->w; + + res->w = matrix->wz * point->x + + matrix->wy * point->w + + matrix->wz * point->z + + matrix->ww * point->w; +} + +void +_clutter_util_matrix_skew_xy (ClutterMatrix *matrix, + float factor) +{ + matrix->yx += matrix->xx * factor; + matrix->yy += matrix->xy * factor; + matrix->yz += matrix->xz * factor; + matrix->yw += matrix->xw * factor; +} + +void +_clutter_util_matrix_skew_xz (ClutterMatrix *matrix, + float factor) +{ + matrix->zx += matrix->xx * factor; + matrix->zy += matrix->xy * factor; + matrix->zz += matrix->xz * factor; + matrix->zw += matrix->xw * factor; +} + +void +_clutter_util_matrix_skew_yz (ClutterMatrix *matrix, + float factor) +{ + matrix->zx += matrix->yx * factor; + matrix->zy += matrix->yy * factor; + matrix->zz += matrix->yz * factor; + matrix->zw += matrix->yw * factor; +} + +static float +_clutter_util_vertex_length (const ClutterVertex *vertex) +{ + return sqrtf (vertex->x * vertex->x + vertex->y * vertex->y + vertex->z * vertex->z); +} + +static void +_clutter_util_vertex_normalize (ClutterVertex *vertex) +{ + float factor = _clutter_util_vertex_length (vertex); + + if (factor == 0.f) + return; + + vertex->x /= factor; + vertex->y /= factor; + vertex->z /= factor; +} + +static float +_clutter_util_vertex_dot (const ClutterVertex *v1, + const ClutterVertex *v2) +{ + return v1->x * v2->x + v1->y * v2->y + v1->z * v2->z; +} + +static void +_clutter_util_vertex_cross (const ClutterVertex *v1, + const ClutterVertex *v2, + ClutterVertex *res) +{ + res->x = v1->y * v2->z - v2->y * v1->z; + res->y = v1->z * v2->x - v2->z * v1->x; + res->z = v1->x * v2->y - v2->x * v1->y; +} + +static void +_clutter_util_vertex_combine (const ClutterVertex *a, + const ClutterVertex *b, + double ascl, + double bscl, + ClutterVertex *res) +{ + res->x = (ascl * a->x) + (bscl * b->x); + res->y = (ascl * a->y) + (bscl * b->y); + res->z = (ascl * a->z) + (bscl * b->z); +} + +void +_clutter_util_vertex4_interpolate (const ClutterVertex4 *a, + const ClutterVertex4 *b, + double progress, + ClutterVertex4 *res) +{ + res->x = a->x + (b->x - a->x) * progress; + res->y = a->y + (b->y - a->y) * progress; + res->z = a->z + (b->z - a->z) * progress; + res->w = a->w + (b->w - a->w) * progress; +} + +/*< private > + * clutter_util_matrix_decompose: + * @src: the matrix to decompose + * @scale_p: (out caller-allocates): return location for a vertex containing + * the scaling factors + * @shear_p: (out) (array length=3): return location for an array of 3 + * elements containing the skew factors (XY, XZ, and YZ respectively) + * @rotate_p: (out caller-allocates): return location for a vertex containing + * the Euler angles + * @translate_p: (out caller-allocates): return location for a vertex + * containing the translation vector + * @perspective_p: (out caller-allocates: return location for a 4D vertex + * containing the perspective + * + * Decomposes a #ClutterMatrix into the transformations that compose it. + * + * This code is based on the matrix decomposition algorithm as published in + * the CSS Transforms specification by the W3C CSS working group, available + * at http://www.w3.org/TR/css3-transforms/. + * + * The algorithm, in turn, is based on the "unmatrix" method published in + * "Graphics Gems II, edited by Jim Arvo", which is available at: + * http://tog.acm.org/resources/GraphicsGems/gemsii/unmatrix.c + * + * Return value: %TRUE if the decomposition was successful, and %FALSE + * if the matrix is singular + */ +gboolean +_clutter_util_matrix_decompose (const ClutterMatrix *src, + ClutterVertex *scale_p, + float shear_p[3], + ClutterVertex *rotate_p, + ClutterVertex *translate_p, + ClutterVertex4 *perspective_p) +{ + CoglMatrix matrix = *src; + CoglMatrix perspective; + ClutterVertex4 vertex_tmp; + ClutterVertex row[3], pdum; + int i, j; + +#define XY_SHEAR 0 +#define XZ_SHEAR 1 +#define YZ_SHEAR 2 +#define MAT(m,r,c) ((float *)(m))[(c) * 4 + (r)] + + /* normalize the matrix */ + if (matrix.ww == 0.f) + return FALSE; + + for (i = 0; i < 4; i++) + { + for (j = 0; j < 4; j++) + { + MAT (&matrix, j, i) /= MAT (&matrix, 3, 3); + } + } + + /* perspective is used to solve for perspective, but it also provides + * an easy way to test for singularity of the upper 3x3 component + */ + perspective = matrix; + + /* transpose */ + MAT (&perspective, 3, 0) = 0.f; + MAT (&perspective, 3, 1) = 0.f; + MAT (&perspective, 3, 2) = 0.f; + MAT (&perspective, 3, 3) = 1.f; + + if (_clutter_util_matrix_determinant (&perspective) == 0.f) + return FALSE; + + if (MAT (&matrix, 3, 0) != 0.f || + MAT (&matrix, 3, 1) != 0.f || + MAT (&matrix, 3, 2) != 0.f) + { + CoglMatrix perspective_inv; + ClutterVertex4 p; + + vertex_tmp.x = MAT (&matrix, 3, 0); + vertex_tmp.y = MAT (&matrix, 3, 1); + vertex_tmp.z = MAT (&matrix, 3, 2); + vertex_tmp.w = MAT (&matrix, 3, 3); + + /* solve the equation by inverting perspective... */ + cogl_matrix_get_inverse (&perspective, &perspective_inv); + + /* ... and multiplying vertex_tmp by the inverse */ + _clutter_util_matrix_transpose_vector4_transform (&perspective_inv, + &vertex_tmp, + &p); + + *perspective_p = p; + + /* clear the perspective part */ + MAT (&matrix, 3, 0) = 0.0f; + MAT (&matrix, 3, 1) = 0.0f; + MAT (&matrix, 3, 2) = 0.0f; + MAT (&matrix, 3, 3) = 1.0f; + } + else + { + /* no perspective */ + perspective_p->x = 0.0f; + perspective_p->y = 0.0f; + perspective_p->z = 0.0f; + perspective_p->w = 1.0f; + } + + /* translation */ + translate_p->x = MAT (&matrix, 0, 3); + MAT (&matrix, 0, 3) = 0.f; + translate_p->y = MAT (&matrix, 1, 3); + MAT (&matrix, 1, 3) = 0.f; + translate_p->z = MAT (&matrix, 2, 3); + MAT (&matrix, 2, 3) = 0.f; + + /* scale and shear; we split the upper 3x3 matrix into rows */ + for (i = 0; i < 3; i++) + { + row[i].x = MAT (&matrix, i, 0); + row[i].y = MAT (&matrix, i, 1); + row[i].z = MAT (&matrix, i, 2); + } + + /* compute scale.x and normalize the first row */ + scale_p->x = _clutter_util_vertex_length (&row[0]); + _clutter_util_vertex_normalize (&row[0]); + + /* compute XY shear and make the second row orthogonal to the first */ + shear_p[XY_SHEAR] = _clutter_util_vertex_dot (&row[0], &row[1]); + _clutter_util_vertex_combine (&row[1], &row[0], + 1.0, -shear_p[XY_SHEAR], + &row[1]); + + /* compute the Y scale and normalize the second row */ + scale_p->y = _clutter_util_vertex_length (&row[1]); + _clutter_util_vertex_normalize (&row[1]); + shear_p[XY_SHEAR] /= scale_p->y; + + /* compute XZ and YZ shears, orthogonalize the third row */ + shear_p[XZ_SHEAR] = _clutter_util_vertex_dot (&row[0], &row[2]); + _clutter_util_vertex_combine (&row[2], &row[0], + 1.0, -shear_p[XZ_SHEAR], + &row[2]); + + shear_p[YZ_SHEAR] = _clutter_util_vertex_dot (&row[1], &row[2]); + _clutter_util_vertex_combine (&row[2], &row[1], + 1.0, -shear_p[YZ_SHEAR], + &row[2]); + + /* get the Z scale and normalize the third row*/ + scale_p->z = _clutter_util_vertex_length (&row[2]); + _clutter_util_vertex_normalize (&row[2]); + shear_p[XZ_SHEAR] /= scale_p->z; + shear_p[YZ_SHEAR] /= scale_p->z; + + /* at this point, the matrix (inside row[]) is orthonormal. + * check for a coordinate system flip; if the determinant + * is -1, then negate the matrix and scaling factors + */ + _clutter_util_vertex_cross (&row[1], &row[2], &pdum); + if (_clutter_util_vertex_dot (&row[0], &pdum) < 0.f) + { + scale_p->x *= -1.f; + + for (i = 0; i < 3; i++) + { + row[i].x *= -1.f; + row[i].y *= -1.f; + row[i].z *= -1.f; + } + } + + /* now get the rotations out */ + rotate_p->y = asinf (-row[0].z); + if (cosf (rotate_p->y) != 0.f) + { + rotate_p->x = atan2f (row[1].z, row[2].z); + rotate_p->z = atan2f (row[0].y, row[0].x); + } + else + { + rotate_p->x = atan2f (-row[2].x, row[1].y); + rotate_p->z = 0.f; + } + +#undef XY_SHEAR +#undef XZ_SHEAR +#undef YZ_SHEAR +#undef MAT + + return TRUE; +} + +typedef struct +{ + GType value_type; + ClutterProgressFunc func; +} ProgressData; + +G_LOCK_DEFINE_STATIC (progress_funcs); +static GHashTable *progress_funcs = NULL; + +gboolean +_clutter_has_progress_function (GType gtype) +{ + const char *type_name = g_type_name (gtype); + + if (progress_funcs == NULL) + return FALSE; + + return g_hash_table_lookup (progress_funcs, type_name) != NULL; +} + +gboolean +_clutter_run_progress_function (GType gtype, + const GValue *initial, + const GValue *final, + gdouble progress, + GValue *retval) +{ + ProgressData *pdata; + gboolean res; + + G_LOCK (progress_funcs); + + if (G_UNLIKELY (progress_funcs == NULL)) + { + res = FALSE; + goto out; + } + + pdata = g_hash_table_lookup (progress_funcs, g_type_name (gtype)); + if (G_UNLIKELY (pdata == NULL)) + { + res = FALSE; + goto out; + } + + res = pdata->func (initial, final, progress, retval); + +out: + G_UNLOCK (progress_funcs); + + return res; +} + +static void +progress_data_destroy (gpointer data_) +{ + g_slice_free (ProgressData, data_); +} + +/** + * clutter_interval_register_progress_func: (skip) + * @value_type: a #GType + * @func: a #ClutterProgressFunc, or %NULL to unset a previously + * set progress function + * + * Sets the progress function for a given @value_type, like: + * + * |[ + * clutter_interval_register_progress_func (MY_TYPE_FOO, + * my_foo_progress); + * ]| + * + * Whenever a #ClutterInterval instance using the default + * #ClutterInterval::compute_value implementation is set as an + * interval between two #GValue of type @value_type, it will call + * @func to establish the value depending on the given progress, + * for instance: + * + * |[ + * static gboolean + * my_int_progress (const GValue *a, + * const GValue *b, + * gdouble progress, + * GValue *retval) + * { + * gint ia = g_value_get_int (a); + * gint ib = g_value_get_int (b); + * gint res = factor * (ib - ia) + ia; + * + * g_value_set_int (retval, res); + * + * return TRUE; + * } + * + * clutter_interval_register_progress_func (G_TYPE_INT, my_int_progress); + * ]| + * + * To unset a previously set progress function of a #GType, pass %NULL + * for @func. + * + * Since: 1.0 + */ +void +clutter_interval_register_progress_func (GType value_type, + ClutterProgressFunc func) +{ + ProgressData *progress_func; + const char *type_name; + + g_return_if_fail (value_type != G_TYPE_INVALID); + + type_name = g_type_name (value_type); + + G_LOCK (progress_funcs); + + if (G_UNLIKELY (progress_funcs == NULL)) + progress_funcs = g_hash_table_new_full (NULL, NULL, + NULL, + progress_data_destroy); + + progress_func = + g_hash_table_lookup (progress_funcs, type_name); + + if (G_UNLIKELY (progress_func)) + { + if (func == NULL) + { + g_hash_table_remove (progress_funcs, type_name); + g_slice_free (ProgressData, progress_func); + } + else + progress_func->func = func; + } + else + { + progress_func = g_slice_new (ProgressData); + progress_func->value_type = value_type; + progress_func->func = func; + + g_hash_table_replace (progress_funcs, + (gpointer) type_name, + progress_func); + } + + G_UNLOCK (progress_funcs); +} diff --git a/clutter/clutter/clutter-version.h b/clutter/clutter/clutter-version.h new file mode 100644 index 0000000..8255168 --- /dev/null +++ b/clutter/clutter/clutter-version.h @@ -0,0 +1,347 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +#ifndef __CLUTTER_VERSION_H__ +#define __CLUTTER_VERSION_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +/** + * SECTION:clutter-version + * @short_description: Versioning utility macros + * + * Clutter offers a set of macros for checking the version of the library + * at compile time; it also provides a function to perform the same check + * at run time. + * + * Clutter adds version information to both API deprecations and additions; + * by definining the macros %CLUTTER_VERSION_MIN_REQUIRED and + * %CLUTTER_VERSION_MAX_ALLOWED, you can specify the range of Clutter versions + * whose API you want to use. Functions that were deprecated before, or + * introduced after, this range will trigger compiler warnings. For instance, + * if we define the following symbols: + * + * |[ + * CLUTTER_VERSION_MIN_REQUIRED = CLUTTER_VERSION_1_6 + * CLUTTER_VERSION_MAX_ALLOWED = CLUTTER_VERSION_1_8 + * ]| + * + * and we have the following functions annotated in the Clutter headers: + * + * |[ + * void clutter_function_A (void) CLUTTER_DEPRECATED_IN_1_4; + * void clutter_function_B (void) CLUTTER_DEPRECATED_IN_1_6; + * void clutter_function_C (void) CLUTTER_AVAILABLE_IN_1_8; + * void clutter_function_D (void) CLUTTER_AVAILABLE_IN_1_10; + * ]| + * + * then any application code using the functions above will get the output: + * + * |[ + * clutter_function_A: deprecation warning + * clutter_function_B: no warning + * clutter_function_C: no warning + * clutter_function_D: symbol not available warning + * ]| + * + * It is possible to disable the compiler warnings by defining the macro + * %CLUTTER_DISABLE_DEPRECATION_WARNINGS before including the clutter.h + * header. + */ + +#include + +G_BEGIN_DECLS + +/** + * CLUTTER_MAJOR_VERSION: + * + * The major version of the Clutter library (1, if %CLUTTER_VERSION is 1.2.3) + */ +#define CLUTTER_MAJOR_VERSION (1) + +/** + * CLUTTER_MINOR_VERSION: + * + * The minor version of the Clutter library (2, if %CLUTTER_VERSION is 1.2.3) + */ +#define CLUTTER_MINOR_VERSION (26) + +/** + * CLUTTER_MICRO_VERSION: + * + * The micro version of the Clutter library (3, if %CLUTTER_VERSION is 1.2.3) + */ +#define CLUTTER_MICRO_VERSION (1) + +/** + * CLUTTER_VERSION: + * + * The full version of the Clutter library, like 1.2.3 + */ +#define CLUTTER_VERSION 1.26.1 + +/** + * CLUTTER_VERSION_S: + * + * The full version of the Clutter library, in string form (suited for + * string concatenation) + */ +#define CLUTTER_VERSION_S "1.26.1" + +/** + * CLUTTER_VERSION_HEX: + * + * Numerically encoded version of the Clutter library, like 0x010203 + */ +#define CLUTTER_VERSION_HEX ((CLUTTER_MAJOR_VERSION << 24) | \ + (CLUTTER_MINOR_VERSION << 16) | \ + (CLUTTER_MICRO_VERSION << 8)) + +/* XXX - Every new stable minor release bump should add a macro here */ + +/** + * CLUTTER_VERSION_1_0: + * + * A macro that evaluates to the 1.0 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.10 + */ +#define CLUTTER_VERSION_1_0 (G_ENCODE_VERSION (1, 0)) + +/** + * CLUTTER_VERSION_1_2: + * + * A macro that evaluates to the 1.2 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.10 + */ +#define CLUTTER_VERSION_1_2 (G_ENCODE_VERSION (1, 2)) + +/** + * CLUTTER_VERSION_1_4: + * + * A macro that evaluates to the 1.4 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.10 + */ +#define CLUTTER_VERSION_1_4 (G_ENCODE_VERSION (1, 4)) + +/** + * CLUTTER_VERSION_1_6: + * + * A macro that evaluates to the 1.6 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.10 + */ +#define CLUTTER_VERSION_1_6 (G_ENCODE_VERSION (1, 6)) + +/** + * CLUTTER_VERSION_1_8: + * + * A macro that evaluates to the 1.8 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.10 + */ +#define CLUTTER_VERSION_1_8 (G_ENCODE_VERSION (1, 8)) + +/** + * CLUTTER_VERSION_1_10: + * + * A macro that evaluates to the 1.10 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.10 + */ +#define CLUTTER_VERSION_1_10 (G_ENCODE_VERSION (1, 10)) + +/** + * CLUTTER_VERSION_1_12: + * + * A macro that evaluates to the 1.12 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.12 + */ +#define CLUTTER_VERSION_1_12 (G_ENCODE_VERSION (1, 12)) + +/** + * CLUTTER_VERSION_1_14: + * + * A macro that evaluates to the 1.14 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.14 + */ +#define CLUTTER_VERSION_1_14 (G_ENCODE_VERSION (1, 14)) + +/** + * CLUTTER_VERSION_1_16: + * + * A macro that evaluates to the 1.16 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.16 + */ +#define CLUTTER_VERSION_1_16 (G_ENCODE_VERSION (1, 16)) + +/** + * CLUTTER_VERSION_1_18: + * + * A macro that evaluates to the 1.18 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.18 + */ +#define CLUTTER_VERSION_1_18 (G_ENCODE_VERSION (1, 18)) + +/** + * CLUTTER_VERSION_1_20: + * + * A macro that evaluates to the 1.20 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.20 + */ +#define CLUTTER_VERSION_1_20 (G_ENCODE_VERSION (1, 20)) + +/** + * CLUTTER_VERSION_1_22: + * + * A macro that evaluates to the 1.22 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.22 + */ +#define CLUTTER_VERSION_1_22 (G_ENCODE_VERSION (1, 22)) + +/** + * CLUTTER_VERSION_1_24: + * + * A macro that evaluates to the 1.24 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.24 + */ +#define CLUTTER_VERSION_1_24 (G_ENCODE_VERSION (1, 24)) + +/** + * CLUTTER_VERSION_1_26: + * + * A macro that evaluates to the 1.26 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.26 + */ +#define CLUTTER_VERSION_1_26 (G_ENCODE_VERSION (1, 26)) + +/* evaluates to the current stable version; for development cycles, + * this means the next stable target + */ +#if (CLUTTER_MINOR_VERSION % 2) +# define CLUTTER_VERSION_CUR_STABLE (G_ENCODE_VERSION (CLUTTER_MAJOR_VERSION, CLUTTER_MINOR_VERSION + 1)) +#else +# define CLUTTER_VERSION_CUR_STABLE (G_ENCODE_VERSION (CLUTTER_MAJOR_VERSION, CLUTTER_MINOR_VERSION)) +#endif + +/* evaluates to the previous stable version */ +#if (CLUTTER_MINOR_VERSION % 2) +# define CLUTTER_VERSION_PREV_STABLE (G_ENCODE_VERSION (CLUTTER_MAJOR_VERSION, CLUTTER_MINOR_VERSION - 1)) +#else +# define CLUTTER_VERSION_PREV_STABLE (G_ENCODE_VERSION (CLUTTER_MAJOR_VERSION, CLUTTER_MINOR_VERSION - 2)) +#endif + +/** + * CLUTTER_CHECK_VERSION: + * @major: major version, like 1 in 1.2.3 + * @minor: minor version, like 2 in 1.2.3 + * @micro: micro version, like 3 in 1.2.3 + * + * Evaluates to %TRUE if the version of the Clutter library is greater + * than @major, @minor and @micro + */ +#define CLUTTER_CHECK_VERSION(major,minor,micro) \ + (CLUTTER_MAJOR_VERSION > (major) || \ + (CLUTTER_MAJOR_VERSION == (major) && CLUTTER_MINOR_VERSION > (minor)) || \ + (CLUTTER_MAJOR_VERSION == (major) && CLUTTER_MINOR_VERSION == (minor) && CLUTTER_MICRO_VERSION >= (micro))) + +#ifndef _CLUTTER_EXTERN +#define _CLUTTER_EXTERN extern +#endif + +#define CLUTTER_VAR _CLUTTER_EXTERN + +/** + * clutter_major_version: + * + * The major component of the Clutter library version, e.g. 1 if the version + * is 1.2.3 + * + * This value can be used for run-time version checks + * + * For a compile-time check, use %CLUTTER_MAJOR_VERSION + * + * Since: 1.2 + */ +const guint clutter_major_version; + +/** + * clutter_minor_version: + * + * The minor component of the Clutter library version, e.g. 2 if the version + * is 1.2.3 + * + * This value can be used for run-time version checks + * + * For a compile-time check, use %CLUTTER_MINOR_VERSION + * + * Since: 1.2 + */ +const guint clutter_minor_version; + +/** + * clutter_micro_version: + * + * The micro component of the Clutter library version, e.g. 3 if the version + * is 1.2.3 + * + * This value can be used for run-time version checks + * + * For a compile-time check, use %CLUTTER_MICRO_VERSION + * + * Since: 1.2 + */ +const guint clutter_micro_version; + +G_END_DECLS + +#endif /* __CLUTTER_VERSION_H__ */ diff --git a/clutter/clutter/clutter-version.h.in b/clutter/clutter/clutter-version.h.in new file mode 100644 index 0000000..29cf537 --- /dev/null +++ b/clutter/clutter/clutter-version.h.in @@ -0,0 +1,347 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +#ifndef __CLUTTER_VERSION_H__ +#define __CLUTTER_VERSION_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +/** + * SECTION:clutter-version + * @short_description: Versioning utility macros + * + * Clutter offers a set of macros for checking the version of the library + * at compile time; it also provides a function to perform the same check + * at run time. + * + * Clutter adds version information to both API deprecations and additions; + * by definining the macros %CLUTTER_VERSION_MIN_REQUIRED and + * %CLUTTER_VERSION_MAX_ALLOWED, you can specify the range of Clutter versions + * whose API you want to use. Functions that were deprecated before, or + * introduced after, this range will trigger compiler warnings. For instance, + * if we define the following symbols: + * + * |[ + * CLUTTER_VERSION_MIN_REQUIRED = CLUTTER_VERSION_1_6 + * CLUTTER_VERSION_MAX_ALLOWED = CLUTTER_VERSION_1_8 + * ]| + * + * and we have the following functions annotated in the Clutter headers: + * + * |[ + * void clutter_function_A (void) CLUTTER_DEPRECATED_IN_1_4; + * void clutter_function_B (void) CLUTTER_DEPRECATED_IN_1_6; + * void clutter_function_C (void) CLUTTER_AVAILABLE_IN_1_8; + * void clutter_function_D (void) CLUTTER_AVAILABLE_IN_1_10; + * ]| + * + * then any application code using the functions above will get the output: + * + * |[ + * clutter_function_A: deprecation warning + * clutter_function_B: no warning + * clutter_function_C: no warning + * clutter_function_D: symbol not available warning + * ]| + * + * It is possible to disable the compiler warnings by defining the macro + * %CLUTTER_DISABLE_DEPRECATION_WARNINGS before including the clutter.h + * header. + */ + +#include + +G_BEGIN_DECLS + +/** + * CLUTTER_MAJOR_VERSION: + * + * The major version of the Clutter library (1, if %CLUTTER_VERSION is 1.2.3) + */ +#define CLUTTER_MAJOR_VERSION (@CLUTTER_MAJOR_VERSION@) + +/** + * CLUTTER_MINOR_VERSION: + * + * The minor version of the Clutter library (2, if %CLUTTER_VERSION is 1.2.3) + */ +#define CLUTTER_MINOR_VERSION (@CLUTTER_MINOR_VERSION@) + +/** + * CLUTTER_MICRO_VERSION: + * + * The micro version of the Clutter library (3, if %CLUTTER_VERSION is 1.2.3) + */ +#define CLUTTER_MICRO_VERSION (@CLUTTER_MICRO_VERSION@) + +/** + * CLUTTER_VERSION: + * + * The full version of the Clutter library, like 1.2.3 + */ +#define CLUTTER_VERSION @CLUTTER_VERSION@ + +/** + * CLUTTER_VERSION_S: + * + * The full version of the Clutter library, in string form (suited for + * string concatenation) + */ +#define CLUTTER_VERSION_S "@CLUTTER_VERSION@" + +/** + * CLUTTER_VERSION_HEX: + * + * Numerically encoded version of the Clutter library, like 0x010203 + */ +#define CLUTTER_VERSION_HEX ((CLUTTER_MAJOR_VERSION << 24) | \ + (CLUTTER_MINOR_VERSION << 16) | \ + (CLUTTER_MICRO_VERSION << 8)) + +/* XXX - Every new stable minor release bump should add a macro here */ + +/** + * CLUTTER_VERSION_1_0: + * + * A macro that evaluates to the 1.0 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.10 + */ +#define CLUTTER_VERSION_1_0 (G_ENCODE_VERSION (1, 0)) + +/** + * CLUTTER_VERSION_1_2: + * + * A macro that evaluates to the 1.2 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.10 + */ +#define CLUTTER_VERSION_1_2 (G_ENCODE_VERSION (1, 2)) + +/** + * CLUTTER_VERSION_1_4: + * + * A macro that evaluates to the 1.4 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.10 + */ +#define CLUTTER_VERSION_1_4 (G_ENCODE_VERSION (1, 4)) + +/** + * CLUTTER_VERSION_1_6: + * + * A macro that evaluates to the 1.6 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.10 + */ +#define CLUTTER_VERSION_1_6 (G_ENCODE_VERSION (1, 6)) + +/** + * CLUTTER_VERSION_1_8: + * + * A macro that evaluates to the 1.8 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.10 + */ +#define CLUTTER_VERSION_1_8 (G_ENCODE_VERSION (1, 8)) + +/** + * CLUTTER_VERSION_1_10: + * + * A macro that evaluates to the 1.10 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.10 + */ +#define CLUTTER_VERSION_1_10 (G_ENCODE_VERSION (1, 10)) + +/** + * CLUTTER_VERSION_1_12: + * + * A macro that evaluates to the 1.12 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.12 + */ +#define CLUTTER_VERSION_1_12 (G_ENCODE_VERSION (1, 12)) + +/** + * CLUTTER_VERSION_1_14: + * + * A macro that evaluates to the 1.14 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.14 + */ +#define CLUTTER_VERSION_1_14 (G_ENCODE_VERSION (1, 14)) + +/** + * CLUTTER_VERSION_1_16: + * + * A macro that evaluates to the 1.16 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.16 + */ +#define CLUTTER_VERSION_1_16 (G_ENCODE_VERSION (1, 16)) + +/** + * CLUTTER_VERSION_1_18: + * + * A macro that evaluates to the 1.18 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.18 + */ +#define CLUTTER_VERSION_1_18 (G_ENCODE_VERSION (1, 18)) + +/** + * CLUTTER_VERSION_1_20: + * + * A macro that evaluates to the 1.20 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.20 + */ +#define CLUTTER_VERSION_1_20 (G_ENCODE_VERSION (1, 20)) + +/** + * CLUTTER_VERSION_1_22: + * + * A macro that evaluates to the 1.22 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.22 + */ +#define CLUTTER_VERSION_1_22 (G_ENCODE_VERSION (1, 22)) + +/** + * CLUTTER_VERSION_1_24: + * + * A macro that evaluates to the 1.24 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.24 + */ +#define CLUTTER_VERSION_1_24 (G_ENCODE_VERSION (1, 24)) + +/** + * CLUTTER_VERSION_1_26: + * + * A macro that evaluates to the 1.26 version of Clutter, in a format + * that can be used by the C pre-processor. + * + * Since: 1.26 + */ +#define CLUTTER_VERSION_1_26 (G_ENCODE_VERSION (1, 26)) + +/* evaluates to the current stable version; for development cycles, + * this means the next stable target + */ +#if (CLUTTER_MINOR_VERSION % 2) +# define CLUTTER_VERSION_CUR_STABLE (G_ENCODE_VERSION (CLUTTER_MAJOR_VERSION, CLUTTER_MINOR_VERSION + 1)) +#else +# define CLUTTER_VERSION_CUR_STABLE (G_ENCODE_VERSION (CLUTTER_MAJOR_VERSION, CLUTTER_MINOR_VERSION)) +#endif + +/* evaluates to the previous stable version */ +#if (CLUTTER_MINOR_VERSION % 2) +# define CLUTTER_VERSION_PREV_STABLE (G_ENCODE_VERSION (CLUTTER_MAJOR_VERSION, CLUTTER_MINOR_VERSION - 1)) +#else +# define CLUTTER_VERSION_PREV_STABLE (G_ENCODE_VERSION (CLUTTER_MAJOR_VERSION, CLUTTER_MINOR_VERSION - 2)) +#endif + +/** + * CLUTTER_CHECK_VERSION: + * @major: major version, like 1 in 1.2.3 + * @minor: minor version, like 2 in 1.2.3 + * @micro: micro version, like 3 in 1.2.3 + * + * Evaluates to %TRUE if the version of the Clutter library is greater + * than @major, @minor and @micro + */ +#define CLUTTER_CHECK_VERSION(major,minor,micro) \ + (CLUTTER_MAJOR_VERSION > (major) || \ + (CLUTTER_MAJOR_VERSION == (major) && CLUTTER_MINOR_VERSION > (minor)) || \ + (CLUTTER_MAJOR_VERSION == (major) && CLUTTER_MINOR_VERSION == (minor) && CLUTTER_MICRO_VERSION >= (micro))) + +#ifndef _CLUTTER_EXTERN +#define _CLUTTER_EXTERN extern +#endif + +#define CLUTTER_VAR _CLUTTER_EXTERN + +/** + * clutter_major_version: + * + * The major component of the Clutter library version, e.g. 1 if the version + * is 1.2.3 + * + * This value can be used for run-time version checks + * + * For a compile-time check, use %CLUTTER_MAJOR_VERSION + * + * Since: 1.2 + */ +const guint clutter_major_version; + +/** + * clutter_minor_version: + * + * The minor component of the Clutter library version, e.g. 2 if the version + * is 1.2.3 + * + * This value can be used for run-time version checks + * + * For a compile-time check, use %CLUTTER_MINOR_VERSION + * + * Since: 1.2 + */ +const guint clutter_minor_version; + +/** + * clutter_micro_version: + * + * The micro component of the Clutter library version, e.g. 3 if the version + * is 1.2.3 + * + * This value can be used for run-time version checks + * + * For a compile-time check, use %CLUTTER_MICRO_VERSION + * + * Since: 1.2 + */ +const guint clutter_micro_version; + +G_END_DECLS + +#endif /* __CLUTTER_VERSION_H__ */ diff --git a/clutter/clutter/clutter-virtual-input-device.c b/clutter/clutter/clutter-virtual-input-device.c new file mode 100644 index 0000000..9ffd013 --- /dev/null +++ b/clutter/clutter/clutter-virtual-input-device.c @@ -0,0 +1,222 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2016 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: Jonas Ådahl + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#include "clutter-virtual-input-device.h" + +#include "clutter-device-manager.h" +#include "clutter-private.h" +#include "clutter-enum-types.h" + +enum +{ + PROP_0, + + PROP_DEVICE_MANAGER, + PROP_DEVICE_TYPE, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +typedef struct _ClutterVirtualInputDevicePrivate +{ + ClutterDeviceManager *manager; + ClutterInputDeviceType device_type; +} ClutterVirtualInputDevicePrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterVirtualInputDevice, + clutter_virtual_input_device, + G_TYPE_OBJECT) + +void +clutter_virtual_input_device_notify_relative_motion (ClutterVirtualInputDevice *virtual_device, + uint64_t time_us, + double dx, + double dy) +{ + ClutterVirtualInputDeviceClass *klass = + CLUTTER_VIRTUAL_INPUT_DEVICE_GET_CLASS (virtual_device); + + klass->notify_relative_motion (virtual_device, time_us, dx, dy); +} + +void +clutter_virtual_input_device_notify_absolute_motion (ClutterVirtualInputDevice *virtual_device, + uint64_t time_us, + double x, + double y) +{ + ClutterVirtualInputDeviceClass *klass = + CLUTTER_VIRTUAL_INPUT_DEVICE_GET_CLASS (virtual_device); + + klass->notify_absolute_motion (virtual_device, time_us, x, y); +} + +void +clutter_virtual_input_device_notify_button (ClutterVirtualInputDevice *virtual_device, + uint64_t time_us, + uint32_t button, + ClutterButtonState button_state) +{ + ClutterVirtualInputDeviceClass *klass = + CLUTTER_VIRTUAL_INPUT_DEVICE_GET_CLASS (virtual_device); + + klass->notify_button (virtual_device, time_us, button, button_state); +} + +void +clutter_virtual_input_device_notify_key (ClutterVirtualInputDevice *virtual_device, + uint64_t time_us, + uint32_t key, + ClutterKeyState key_state) +{ + ClutterVirtualInputDeviceClass *klass = + CLUTTER_VIRTUAL_INPUT_DEVICE_GET_CLASS (virtual_device); + + klass->notify_key (virtual_device, time_us, key, key_state); +} + +void +clutter_virtual_input_device_notify_keyval (ClutterVirtualInputDevice *virtual_device, + uint64_t time_us, + uint32_t keyval, + ClutterKeyState key_state) +{ + ClutterVirtualInputDeviceClass *klass = + CLUTTER_VIRTUAL_INPUT_DEVICE_GET_CLASS (virtual_device); + + klass->notify_keyval (virtual_device, time_us, keyval, key_state); +} + +/** + * clutter_virtual_input_device_get_manager: + * @virtual_device: a virtual device + * + * Gets the device manager of this virtual device. + * + * Returns: (transfer none): The #ClutterDeviceManager of this virtual device + **/ +ClutterDeviceManager * +clutter_virtual_input_device_get_manager (ClutterVirtualInputDevice *virtual_device) +{ + ClutterVirtualInputDevicePrivate *priv = + clutter_virtual_input_device_get_instance_private (virtual_device); + + return priv->manager; +} + +int +clutter_virtual_input_device_get_device_type (ClutterVirtualInputDevice *virtual_device) +{ + ClutterVirtualInputDevicePrivate *priv = + clutter_virtual_input_device_get_instance_private (virtual_device); + + return priv->device_type; +} + +static void +clutter_virtual_input_device_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterVirtualInputDevice *virtual_device = + CLUTTER_VIRTUAL_INPUT_DEVICE (object); + ClutterVirtualInputDevicePrivate *priv = + clutter_virtual_input_device_get_instance_private (virtual_device); + + switch (prop_id) + { + case PROP_DEVICE_MANAGER: + g_value_set_object (value, priv->manager); + break; + case PROP_DEVICE_TYPE: + g_value_set_enum (value, priv->device_type); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_virtual_input_device_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterVirtualInputDevice *virtual_device = + CLUTTER_VIRTUAL_INPUT_DEVICE (object); + ClutterVirtualInputDevicePrivate *priv = + clutter_virtual_input_device_get_instance_private (virtual_device); + + switch (prop_id) + { + case PROP_DEVICE_MANAGER: + priv->manager = g_value_get_object (value); + break; + case PROP_DEVICE_TYPE: + priv->device_type = g_value_get_enum (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_virtual_input_device_init (ClutterVirtualInputDevice *virtual_device) +{ +} + +static void +clutter_virtual_input_device_class_init (ClutterVirtualInputDeviceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = clutter_virtual_input_device_get_property; + object_class->set_property = clutter_virtual_input_device_set_property; + + obj_props[PROP_DEVICE_MANAGER] = + g_param_spec_object ("device-manager", + P_("Device Manager"), + P_("The device manager instance"), + CLUTTER_TYPE_DEVICE_MANAGER, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + obj_props[PROP_DEVICE_TYPE] = + g_param_spec_enum ("device-type", + P_("Device type"), + P_("Device type"), + CLUTTER_TYPE_INPUT_DEVICE_TYPE, + CLUTTER_POINTER_DEVICE, + CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + + g_object_class_install_properties (object_class, PROP_LAST, obj_props); +} diff --git a/clutter/clutter/clutter-virtual-input-device.h b/clutter/clutter/clutter-virtual-input-device.h new file mode 100644 index 0000000..c6c6deb --- /dev/null +++ b/clutter/clutter/clutter-virtual-input-device.h @@ -0,0 +1,116 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2016 Red Hat inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: Jonas Ådahl + */ + +#ifndef __CLUTTER_VIRTUAL_INPUT_DEVICE_H__ +#define __CLUTTER_VIRTUAL_INPUT_DEVICE_H__ + +#include +#include + +#include "clutter-device-manager.h" + +#define CLUTTER_TYPE_VIRTUAL_INPUT_DEVICE (clutter_virtual_input_device_get_type ()) + +CLUTTER_AVAILABLE_IN_ALL +G_DECLARE_DERIVABLE_TYPE (ClutterVirtualInputDevice, + clutter_virtual_input_device, + CLUTTER, VIRTUAL_INPUT_DEVICE, + GObject) + +typedef enum _ClutterButtonState +{ + CLUTTER_BUTTON_STATE_RELEASED, + CLUTTER_BUTTON_STATE_PRESSED +} ClutterButtonState; + +typedef enum _ClutterKeyState +{ + CLUTTER_KEY_STATE_RELEASED, + CLUTTER_KEY_STATE_PRESSED +} ClutterKeyState; + +struct _ClutterVirtualInputDeviceClass +{ + GObjectClass parent_class; + + void (*notify_relative_motion) (ClutterVirtualInputDevice *virtual_device, + uint64_t time_us, + double dx, + double dy); + + void (*notify_absolute_motion) (ClutterVirtualInputDevice *virtual_device, + uint64_t time_us, + double x, + double y); + + void (*notify_button) (ClutterVirtualInputDevice *virtual_device, + uint64_t time_us, + uint32_t button, + ClutterButtonState button_state); + + void (*notify_key) (ClutterVirtualInputDevice *virtual_device, + uint64_t time_us, + uint32_t key, + ClutterKeyState key_state); + void (*notify_keyval) (ClutterVirtualInputDevice *virtual_device, + uint64_t time_us, + uint32_t keyval, + ClutterKeyState key_state); +}; + +CLUTTER_AVAILABLE_IN_ALL +void clutter_virtual_input_device_notify_relative_motion (ClutterVirtualInputDevice *virtual_device, + uint64_t time_us, + double dx, + double dy); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_virtual_input_device_notify_absolute_motion (ClutterVirtualInputDevice *virtual_device, + uint64_t time_us, + double x, + double y); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_virtual_input_device_notify_button (ClutterVirtualInputDevice *virtual_device, + uint64_t time_us, + uint32_t button, + ClutterButtonState button_state); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_virtual_input_device_notify_key (ClutterVirtualInputDevice *virtual_device, + uint64_t time_us, + uint32_t key, + ClutterKeyState key_state); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_virtual_input_device_notify_keyval (ClutterVirtualInputDevice *virtual_device, + uint64_t time_us, + uint32_t keyval, + ClutterKeyState key_state); + +CLUTTER_AVAILABLE_IN_ALL +ClutterDeviceManager * clutter_virtual_input_device_get_manager (ClutterVirtualInputDevice *virtual_device); + +int clutter_virtual_input_device_get_device_type (ClutterVirtualInputDevice *virtual_device); + +#endif /* __CLUTTER_VIRTUAL_INPUT_DEVICE_H__ */ diff --git a/clutter/clutter/clutter-zoom-action.c b/clutter/clutter/clutter-zoom-action.c new file mode 100644 index 0000000..b60973d --- /dev/null +++ b/clutter/clutter/clutter-zoom-action.c @@ -0,0 +1,517 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2012 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 . + * + * Author: + * Lionel Landwerlin + */ + +/** + * SECTION:clutter-zoom-action + * @Title: ClutterZoomAction + * @Short_Description: Action enabling zooming on actors + * + * #ClutterZoomAction is a sub-class of #ClutterGestureAction that + * implements all the necessary logic for zooming actors using a "pinch" + * gesture between two touch points. + * + * The simplest usage of #ClutterZoomAction consists in adding it to + * a #ClutterActor and setting it as reactive; for instance, the following + * code: + * + * |[ + * clutter_actor_add_action (actor, clutter_zoom_action_new ()); + * clutter_actor_set_reactive (actor, TRUE); + * ]| + * + * will automatically result in the actor to be scale according to the + * distance between two touch points. + * + * Since: 1.12 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#include "clutter-zoom-action.h" + +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-gesture-action-private.h" +#include "clutter-marshal.h" +#include "clutter-private.h" +#include "clutter-stage-private.h" + +typedef struct +{ + gfloat start_x; + gfloat start_y; + gfloat transformed_start_x; + gfloat transformed_start_y; + + gfloat update_x; + gfloat update_y; + gfloat transformed_update_x; + gfloat transformed_update_y; +} ZoomPoint; + +struct _ClutterZoomActionPrivate +{ + ClutterStage *stage; + + ClutterZoomAxis zoom_axis; + + ZoomPoint points[2]; + + ClutterPoint initial_focal_point; + ClutterPoint focal_point; + ClutterPoint transformed_focal_point; + + gfloat initial_x; + gfloat initial_y; + gfloat initial_z; + + gdouble initial_scale_x; + gdouble initial_scale_y; + + gdouble zoom_initial_distance; +}; + +enum +{ + PROP_0, + + PROP_ZOOM_AXIS, + + PROP_LAST +}; + +static GParamSpec *zoom_props[PROP_LAST] = { NULL, }; + +enum +{ + ZOOM, + + LAST_SIGNAL +}; + +static guint zoom_signals[LAST_SIGNAL] = { 0, }; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterZoomAction, clutter_zoom_action, CLUTTER_TYPE_GESTURE_ACTION) + +static void +capture_point_initial_position (ClutterGestureAction *action, + ClutterActor *actor, + gint index, + ZoomPoint *point) +{ + clutter_gesture_action_get_motion_coords (action, index, + &point->start_x, + &point->start_y); + + point->transformed_start_x = point->update_x = point->start_x; + point->transformed_start_y = point->update_x = point->start_y; + clutter_actor_transform_stage_point (actor, + point->start_x, point->start_y, + &point->transformed_start_x, + &point->transformed_start_y); + point->transformed_update_x = point->transformed_start_x; + point->transformed_update_y = point->transformed_start_y; +} + +static void +capture_point_update_position (ClutterGestureAction *action, + ClutterActor *actor, + gint index, + ZoomPoint *point) +{ + clutter_gesture_action_get_motion_coords (action, index, + &point->update_x, + &point->update_y); + + point->transformed_update_x = point->update_x; + point->transformed_update_y = point->update_y; + clutter_actor_transform_stage_point (actor, + point->update_x, point->update_y, + &point->transformed_update_x, + &point->transformed_update_y); +} + +static gboolean +clutter_zoom_action_gesture_begin (ClutterGestureAction *action, + ClutterActor *actor) +{ + ClutterZoomActionPrivate *priv = ((ClutterZoomAction *) action)->priv; + gfloat dx, dy; + + capture_point_initial_position (action, actor, 0, &priv->points[0]); + capture_point_initial_position (action, actor, 1, &priv->points[1]); + + dx = priv->points[1].transformed_start_x - priv->points[0].transformed_start_x; + dy = priv->points[1].transformed_start_y - priv->points[0].transformed_start_y; + priv->zoom_initial_distance = sqrt (dx * dx + dy * dy); + + clutter_actor_get_translation (actor, + &priv->initial_x, + &priv->initial_y, + &priv->initial_z); + clutter_actor_get_scale (actor, + &priv->initial_scale_x, + &priv->initial_scale_y); + + priv->initial_focal_point.x = (priv->points[0].start_x + priv->points[1].start_x) / 2; + priv->initial_focal_point.y = (priv->points[0].start_y + priv->points[1].start_y) / 2; + clutter_actor_transform_stage_point (actor, + priv->initial_focal_point.x, + priv->initial_focal_point.y, + &priv->transformed_focal_point.x, + &priv->transformed_focal_point.y); + + clutter_actor_set_pivot_point (actor, + priv->transformed_focal_point.x / clutter_actor_get_width (actor), + priv->transformed_focal_point.y / clutter_actor_get_height (actor)); + + return TRUE; +} + +static gboolean +clutter_zoom_action_gesture_progress (ClutterGestureAction *action, + ClutterActor *actor) +{ + ClutterZoomActionPrivate *priv = ((ClutterZoomAction *) action)->priv; + gdouble distance, new_scale; + gfloat dx, dy; + gboolean retval; + + capture_point_update_position (action, actor, 0, &priv->points[0]); + capture_point_update_position (action, actor, 1, &priv->points[1]); + + dx = priv->points[1].update_x - priv->points[0].update_x; + dy = priv->points[1].update_y - priv->points[0].update_y; + distance = sqrt (dx * dx + dy * dy); + + if (distance == 0) + return TRUE; + + priv->focal_point.x = (priv->points[0].update_x + priv->points[1].update_x) / 2; + priv->focal_point.y = (priv->points[0].update_y + priv->points[1].update_y) / 2; + + new_scale = distance / priv->zoom_initial_distance; + + g_signal_emit (action, zoom_signals[ZOOM], 0, + actor, &priv->focal_point, new_scale, + &retval); + + return TRUE; +} + +static void +clutter_zoom_action_gesture_cancel (ClutterGestureAction *action, + ClutterActor *actor) +{ + ClutterZoomActionPrivate *priv = ((ClutterZoomAction *) action)->priv; + + clutter_actor_set_translation (actor, + priv->initial_x, + priv->initial_y, + priv->initial_z); + clutter_actor_set_scale (actor, priv->initial_scale_x, priv->initial_scale_y); +} + +static gboolean +clutter_zoom_action_real_zoom (ClutterZoomAction *action, + ClutterActor *actor, + ClutterPoint *focal_point, + gdouble factor) +{ + ClutterZoomActionPrivate *priv = action->priv; + gfloat x, y, z; + gdouble scale_x, scale_y; + ClutterVertex out, in; + + in.x = priv->transformed_focal_point.x; + in.y = priv->transformed_focal_point.y; + in.z = 0; + + clutter_actor_apply_transform_to_point (actor, &in, &out); + + clutter_actor_get_scale (actor, &scale_x, &scale_y); + + switch (priv->zoom_axis) + { + case CLUTTER_ZOOM_BOTH: + clutter_actor_set_scale (actor, factor, factor); + break; + + case CLUTTER_ZOOM_X_AXIS: + clutter_actor_set_scale (actor, factor, scale_y); + break; + + case CLUTTER_ZOOM_Y_AXIS: + clutter_actor_set_scale (actor, scale_x, factor); + break; + + default: + break; + } + + x = priv->initial_x + priv->focal_point.x - priv->initial_focal_point.x; + y = priv->initial_y + priv->focal_point.y - priv->initial_focal_point.y; + clutter_actor_get_translation (actor, NULL, NULL, &z); + clutter_actor_set_translation (actor, x, y, z); + + return TRUE; +} + +static void +clutter_zoom_action_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterZoomAction *action = CLUTTER_ZOOM_ACTION (gobject); + + switch (prop_id) + { + case PROP_ZOOM_AXIS: + clutter_zoom_action_set_zoom_axis (action, g_value_get_enum (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + } +} + +static void +clutter_zoom_action_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterZoomActionPrivate *priv = CLUTTER_ZOOM_ACTION (gobject)->priv; + + switch (prop_id) + { + case PROP_ZOOM_AXIS: + g_value_set_enum (value, priv->zoom_axis); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + } +} + +static void +clutter_zoom_action_dispose (GObject *gobject) +{ + G_OBJECT_CLASS (clutter_zoom_action_parent_class)->dispose (gobject); +} + +static void +clutter_zoom_action_constructed (GObject *gobject) +{ + ClutterGestureAction *gesture; + + gesture = CLUTTER_GESTURE_ACTION (gobject); + clutter_gesture_action_set_threshold_trigger_edge (gesture, CLUTTER_GESTURE_TRIGGER_EDGE_NONE); +} + +static void +clutter_zoom_action_class_init (ClutterZoomActionClass *klass) +{ + ClutterGestureActionClass *gesture_class = + CLUTTER_GESTURE_ACTION_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->constructed = clutter_zoom_action_constructed; + gobject_class->set_property = clutter_zoom_action_set_property; + gobject_class->get_property = clutter_zoom_action_get_property; + gobject_class->dispose = clutter_zoom_action_dispose; + + gesture_class->gesture_begin = clutter_zoom_action_gesture_begin; + gesture_class->gesture_progress = clutter_zoom_action_gesture_progress; + gesture_class->gesture_cancel = clutter_zoom_action_gesture_cancel; + + klass->zoom = clutter_zoom_action_real_zoom; + + /** + * ClutterZoomAction:zoom-axis: + * + * Constraints the zooming action to the specified axis + * + * Since: 1.12 + */ + zoom_props[PROP_ZOOM_AXIS] = + g_param_spec_enum ("zoom-axis", + P_("Zoom Axis"), + P_("Constraints the zoom to an axis"), + CLUTTER_TYPE_ZOOM_AXIS, + CLUTTER_ZOOM_BOTH, + CLUTTER_PARAM_READWRITE); + + g_object_class_install_properties (gobject_class, + PROP_LAST, + zoom_props); + + /** + * ClutterZoomAction::zoom: + * @action: the #ClutterZoomAction that emitted the signal + * @actor: the #ClutterActor attached to the action + * @focal_point: the focal point of the zoom + * @factor: the initial distance between the 2 touch points + * + * The ::zoom signal is emitted for each series of touch events that + * change the distance and focal point between the touch points. + * + * The default handler of the signal will call + * clutter_actor_set_scale() on @actor using the ratio of the first + * distance between the touch points and the current distance. To + * override the default behaviour, connect to this signal and return + * %FALSE. + * + * Return value: %TRUE if the zoom should continue, and %FALSE if + * the zoom should be cancelled. + * + * Since: 1.12 + */ + zoom_signals[ZOOM] = + g_signal_new (I_("zoom"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterZoomActionClass, zoom), + _clutter_boolean_continue_accumulator, NULL, + _clutter_marshal_BOOLEAN__OBJECT_BOXED_DOUBLE, + G_TYPE_BOOLEAN, 3, + CLUTTER_TYPE_ACTOR, + CLUTTER_TYPE_POINT, + G_TYPE_DOUBLE); +} + +static void +clutter_zoom_action_init (ClutterZoomAction *self) +{ + ClutterGestureAction *gesture; + + self->priv = clutter_zoom_action_get_instance_private (self); + self->priv->zoom_axis = CLUTTER_ZOOM_BOTH; + + gesture = CLUTTER_GESTURE_ACTION (self); + clutter_gesture_action_set_n_touch_points (gesture, 2); +} + +/** + * clutter_zoom_action_new: + * + * Creates a new #ClutterZoomAction instance + * + * Return value: the newly created #ClutterZoomAction + * + * Since: 1.12 + */ +ClutterAction * +clutter_zoom_action_new (void) +{ + return g_object_new (CLUTTER_TYPE_ZOOM_ACTION, NULL); +} + +/** + * clutter_zoom_action_set_zoom_axis: + * @action: a #ClutterZoomAction + * @axis: the axis to constraint the zooming to + * + * Restricts the zooming action to a specific axis + * + * Since: 1.12 + */ +void +clutter_zoom_action_set_zoom_axis (ClutterZoomAction *action, + ClutterZoomAxis axis) +{ + g_return_if_fail (CLUTTER_IS_ZOOM_ACTION (action)); + g_return_if_fail (axis >= CLUTTER_ZOOM_X_AXIS && + axis <= CLUTTER_ZOOM_BOTH); + + if (action->priv->zoom_axis == axis) + return; + + action->priv->zoom_axis = axis; + + g_object_notify_by_pspec (G_OBJECT (action), zoom_props[PROP_ZOOM_AXIS]); +} + +/** + * clutter_zoom_action_get_zoom_axis: + * @action: a #ClutterZoomAction + * + * Retrieves the axis constraint set by clutter_zoom_action_set_zoom_axis() + * + * Return value: the axis constraint + * + * Since: 1.12 + */ +ClutterZoomAxis +clutter_zoom_action_get_zoom_axis (ClutterZoomAction *action) +{ + g_return_val_if_fail (CLUTTER_IS_ZOOM_ACTION (action), + CLUTTER_ZOOM_BOTH); + + return action->priv->zoom_axis; +} + +/** + * clutter_zoom_action_get_focal_point: + * @action: a #ClutterZoomAction + * @point: (out): a #ClutterPoint + * + * Retrieves the focal point of the current zoom + * + * Since: 1.12 + */ +void +clutter_zoom_action_get_focal_point (ClutterZoomAction *action, + ClutterPoint *point) +{ + g_return_if_fail (CLUTTER_IS_ZOOM_ACTION (action)); + g_return_if_fail (point != NULL); + + *point = action->priv->focal_point; +} + +/** + * clutter_zoom_action_get_transformed_focal_point: + * @action: a #ClutterZoomAction + * @point: (out): a #ClutterPoint + * + * Retrieves the focal point relative to the actor's coordinates of + * the current zoom + * + * Since: 1.12 + */ +void +clutter_zoom_action_get_transformed_focal_point (ClutterZoomAction *action, + ClutterPoint *point) +{ + g_return_if_fail (CLUTTER_IS_ZOOM_ACTION (action)); + g_return_if_fail (point != NULL); + + *point = action->priv->transformed_focal_point; +} diff --git a/clutter/clutter/clutter-zoom-action.h b/clutter/clutter/clutter-zoom-action.h new file mode 100644 index 0000000..496b36e --- /dev/null +++ b/clutter/clutter/clutter-zoom-action.h @@ -0,0 +1,114 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2012 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 . + * + * Author: + * Lionel Landwerlin + */ + +#ifndef __CLUTTER_ZOOM_ACTION_H__ +#define __CLUTTER_ZOOM_ACTION_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_ZOOM_ACTION (clutter_zoom_action_get_type ()) +#define CLUTTER_ZOOM_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ZOOM_ACTION, ClutterZoomAction)) +#define CLUTTER_IS_ZOOM_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ZOOM_ACTION)) +#define CLUTTER_ZOOM_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_ZOOM_ACTION, ClutterZoomActionClass)) +#define CLUTTER_IS_ZOOM_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_ZOOM_ACTION)) +#define CLUTTER_ZOOM_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_ZOOM_ACTION, ClutterZoomActionClass)) + +typedef struct _ClutterZoomAction ClutterZoomAction; +typedef struct _ClutterZoomActionPrivate ClutterZoomActionPrivate; +typedef struct _ClutterZoomActionClass ClutterZoomActionClass; + +/** + * ClutterZoomAction: + * + * The #ClutterZoomAction structure contains only + * private data and should be accessed using the provided API + * + * Since: 1.12 + */ +struct _ClutterZoomAction +{ + /*< private >*/ + ClutterGestureAction parent_instance; + + ClutterZoomActionPrivate *priv; +}; + +/** + * ClutterZoomActionClass: + * @zoom: class handler of the #ClutterZoomAction::zoom signal + * + * The #ClutterZoomActionClass structure contains + * only private data + * + * Since: 1.12 + */ +struct _ClutterZoomActionClass +{ + /*< private >*/ + ClutterGestureActionClass parent_class; + + /*< public >*/ + gboolean (* zoom) (ClutterZoomAction *action, + ClutterActor *actor, + ClutterPoint *focal_point, + gdouble factor); + + /*< private >*/ + void (* _clutter_zoom_action1) (void); + void (* _clutter_zoom_action2) (void); + void (* _clutter_zoom_action3) (void); + void (* _clutter_zoom_action4) (void); + void (* _clutter_zoom_action5) (void); +}; + +CLUTTER_AVAILABLE_IN_1_12 +GType clutter_zoom_action_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_12 +ClutterAction * clutter_zoom_action_new (void); + +CLUTTER_AVAILABLE_IN_1_12 +void clutter_zoom_action_set_zoom_axis (ClutterZoomAction *action, + ClutterZoomAxis axis); +CLUTTER_AVAILABLE_IN_1_12 +ClutterZoomAxis clutter_zoom_action_get_zoom_axis (ClutterZoomAction *action); + +CLUTTER_AVAILABLE_IN_1_12 +void clutter_zoom_action_get_focal_point (ClutterZoomAction *action, + ClutterPoint *point); +CLUTTER_AVAILABLE_IN_1_12 +void clutter_zoom_action_get_transformed_focal_point (ClutterZoomAction *action, + ClutterPoint *point); + +G_END_DECLS + +#endif /* __CLUTTER_ZOOM_ACTION_H__ */ diff --git a/clutter/clutter/clutter.h b/clutter/clutter/clutter.h new file mode 100644 index 0000000..cdf54ac --- /dev/null +++ b/clutter/clutter/clutter.h @@ -0,0 +1,119 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +#ifndef __CLUTTER_H__ +#define __CLUTTER_H__ + +#define __CLUTTER_H_INSIDE__ + +#include "clutter-config.h" +#include "clutter-types.h" + +#include "clutter-action.h" +#include "clutter-actor.h" +#include "clutter-actor-meta.h" +#include "clutter-align-constraint.h" +#include "clutter-animatable.h" +#include "clutter-backend.h" +#include "clutter-bind-constraint.h" +#include "clutter-binding-pool.h" +#include "clutter-bin-layout.h" +#include "clutter-blur-effect.h" +#include "clutter-box-layout.h" +#include "clutter-brightness-contrast-effect.h" +#include "clutter-cairo.h" +#include "clutter-canvas.h" +#include "clutter-child-meta.h" +#include "clutter-click-action.h" +#include "clutter-clone.h" +#include "clutter-color.h" +#include "clutter-color-static.h" +#include "clutter-colorize-effect.h" +#include "clutter-constraint.h" +#include "clutter-container.h" +#include "clutter-content.h" +#include "clutter-deform-effect.h" +#include "clutter-desaturate-effect.h" +#include "clutter-device-manager.h" +#include "clutter-drag-action.h" +#include "clutter-drop-action.h" +#include "clutter-effect.h" +#include "clutter-enums.h" +#include "clutter-enum-types.h" +#include "clutter-event.h" +#include "clutter-feature.h" +#include "clutter-fixed-layout.h" +#include "clutter-flow-layout.h" +#include "clutter-gesture-action.h" +#include "clutter-grid-layout.h" +#include "clutter-group.h" +#include "clutter-image.h" +#include "clutter-input-device.h" +#include "clutter-input-device-tool.h" +#include "clutter-interval.h" +#include "clutter-keyframe-transition.h" +#include "clutter-keysyms.h" +#include "clutter-layout-manager.h" +#include "clutter-layout-meta.h" +#include "clutter-macros.h" +#include "clutter-main.h" +#include "clutter-offscreen-effect.h" +#include "clutter-page-turn-effect.h" +#include "clutter-paint-nodes.h" +#include "clutter-paint-node.h" +#include "clutter-pan-action.h" +#include "clutter-path-constraint.h" +#include "clutter-path.h" +#include "clutter-property-transition.h" +#include "clutter-rotate-action.h" +#include "clutter-scriptable.h" +#include "clutter-script.h" +#include "clutter-scroll-actor.h" +#include "clutter-settings.h" +#include "clutter-shader-effect.h" +#include "clutter-shader-types.h" +#include "clutter-swipe-action.h" +#include "clutter-snap-constraint.h" +#include "clutter-stage.h" +#include "clutter-stage-manager.h" +#include "clutter-tap-action.h" +#include "clutter-test-utils.h" +#include "clutter-texture.h" +#include "clutter-text.h" +#include "clutter-timeline.h" +#include "clutter-transition-group.h" +#include "clutter-transition.h" +#include "clutter-units.h" +#include "clutter-version.h" +#include "clutter-virtual-input-device.h" +#include "clutter-zoom-action.h" + +#include "clutter-deprecated.h" + +#include "clutter-autocleanups.h" + +#undef __CLUTTER_H_INSIDE__ + +#endif /* __CLUTTER_H__ */ diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c new file mode 100644 index 0000000..2c525af --- /dev/null +++ b/clutter/clutter/cogl/clutter-stage-cogl.c @@ -0,0 +1,907 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2007,2008,2009,2010,2011 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + + * Authors: + * Matthew Allum + * Robert Bragg + * Neil Roberts + * Emmanuele Bassi + */ + + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#define CLUTTER_ENABLE_EXPERIMENTAL_API + +#include "clutter-config.h" + +#include "clutter-stage-cogl.h" + +#include +#include + +#include "clutter-actor-private.h" +#include "clutter-backend-private.h" +#include "clutter-debug.h" +#include "clutter-event.h" +#include "clutter-enum-types.h" +#include "clutter-feature.h" +#include "clutter-main.h" +#include "clutter-private.h" +#include "clutter-stage-private.h" + +typedef struct _ClutterStageViewCoglPrivate +{ + /* Stores a list of previous damaged areas in the stage coordinate space */ +#define DAMAGE_HISTORY_MAX 16 +#define DAMAGE_HISTORY(x) ((x) & (DAMAGE_HISTORY_MAX - 1)) + cairo_rectangle_int_t damage_history[DAMAGE_HISTORY_MAX]; + unsigned int damage_index; +} ClutterStageViewCoglPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterStageViewCogl, clutter_stage_view_cogl, + CLUTTER_TYPE_STAGE_VIEW) + +static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface); + +G_DEFINE_TYPE_WITH_CODE (ClutterStageCogl, + _clutter_stage_cogl, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW, + clutter_stage_window_iface_init)); + +enum { + PROP_0, + PROP_WRAPPER, + PROP_BACKEND, + PROP_LAST +}; + +static void +clutter_stage_cogl_unrealize (ClutterStageWindow *stage_window) +{ + CLUTTER_NOTE (BACKEND, "Unrealizing Cogl stage [%p]", stage_window); +} + +void +_clutter_stage_cogl_presented (ClutterStageCogl *stage_cogl, + CoglFrameEvent frame_event, + ClutterFrameInfo *frame_info) +{ + + if (frame_event == COGL_FRAME_EVENT_SYNC) + { + /* Early versions of the swap_event implementation in Mesa + * deliver BufferSwapComplete event when not selected for, + * so if we get a swap event we aren't expecting, just ignore it. + * + * https://bugs.freedesktop.org/show_bug.cgi?id=27962 + * + * FIXME: This issue can be hidden inside Cogl so we shouldn't + * need to care about this bug here. + */ + if (stage_cogl->pending_swaps > 0) + stage_cogl->pending_swaps--; + } + else if (frame_event == COGL_FRAME_EVENT_COMPLETE) + { + gint64 presentation_time_cogl = frame_info->presentation_time; + + if (presentation_time_cogl != 0) + { + ClutterBackend *backend = stage_cogl->backend; + CoglContext *context = clutter_backend_get_cogl_context (backend); + gint64 current_time_cogl = cogl_get_clock_time (context); + gint64 now = g_get_monotonic_time (); + + stage_cogl->last_presentation_time = + now + (presentation_time_cogl - current_time_cogl) / 1000; + } + + stage_cogl->refresh_rate = frame_info->refresh_rate; + } + + _clutter_stage_presented (stage_cogl->wrapper, frame_event, frame_info); +} + +static gboolean +clutter_stage_cogl_realize (ClutterStageWindow *stage_window) +{ + ClutterBackend *backend; + + CLUTTER_NOTE (BACKEND, "Realizing stage '%s' [%p]", + G_OBJECT_TYPE_NAME (stage_window), + stage_window); + + backend = clutter_get_default_backend (); + + if (backend->cogl_context == NULL) + { + g_warning ("Failed to realize stage: missing Cogl context"); + return FALSE; + } + + return TRUE; +} + +static void +clutter_stage_cogl_schedule_update (ClutterStageWindow *stage_window, + gint sync_delay) +{ + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); + gint64 now; + float refresh_rate; + gint64 refresh_interval; + + if (stage_cogl->update_time != -1) + return; + + now = g_get_monotonic_time (); + + if (sync_delay < 0) + { + stage_cogl->update_time = now; + return; + } + + /* We only extrapolate presentation times for 150ms - this is somewhat + * arbitrary. The reasons it might not be accurate for larger times are + * that the refresh interval might be wrong or the vertical refresh + * might be downclocked if nothing is going on onscreen. + */ + if (stage_cogl->last_presentation_time == 0|| + stage_cogl->last_presentation_time < now - 150000) + { + stage_cogl->update_time = now; + return; + } + + refresh_rate = stage_cogl->refresh_rate; + if (refresh_rate == 0.0) + refresh_rate = 60.0; + + refresh_interval = (gint64) (0.5 + 1000000 / refresh_rate); + if (refresh_interval == 0) + refresh_interval = 16667; /* 1/60th second */ + + stage_cogl->update_time = stage_cogl->last_presentation_time + 1000 * sync_delay; + + while (stage_cogl->update_time < now) + stage_cogl->update_time += refresh_interval; +} + +static gint64 +clutter_stage_cogl_get_update_time (ClutterStageWindow *stage_window) +{ + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); + + if (stage_cogl->pending_swaps) + return -1; /* in the future, indefinite */ + + return stage_cogl->update_time; +} + +static void +clutter_stage_cogl_clear_update_time (ClutterStageWindow *stage_window) +{ + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); + + stage_cogl->update_time = -1; +} + +static ClutterActor * +clutter_stage_cogl_get_wrapper (ClutterStageWindow *stage_window) +{ + return CLUTTER_ACTOR (CLUTTER_STAGE_COGL (stage_window)->wrapper); +} + +static void +clutter_stage_cogl_show (ClutterStageWindow *stage_window, + gboolean do_raise) +{ + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); + + clutter_actor_map (CLUTTER_ACTOR (stage_cogl->wrapper)); +} + +static void +clutter_stage_cogl_hide (ClutterStageWindow *stage_window) +{ + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); + + clutter_actor_unmap (CLUTTER_ACTOR (stage_cogl->wrapper)); +} + +static void +clutter_stage_cogl_resize (ClutterStageWindow *stage_window, + gint width, + gint height) +{ +} + +static gboolean +clutter_stage_cogl_has_redraw_clips (ClutterStageWindow *stage_window) +{ + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); + + /* NB: at the start of each new frame there is an implied clip that + * clips everything (i.e. nothing would be drawn) so we need to make + * sure we return True in the un-initialized case here. + * + * NB: a clip width of 0 means a full stage redraw has been queued + * so we effectively don't have any redraw clips in that case. + */ + if (!stage_cogl->initialized_redraw_clip || + (stage_cogl->initialized_redraw_clip && + stage_cogl->bounding_redraw_clip.width != 0)) + return TRUE; + else + return FALSE; +} + +static gboolean +clutter_stage_cogl_ignoring_redraw_clips (ClutterStageWindow *stage_window) +{ + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); + + /* NB: a clip width of 0 means a full stage redraw is required */ + if (stage_cogl->initialized_redraw_clip && + stage_cogl->bounding_redraw_clip.width == 0) + return TRUE; + else + return FALSE; +} + +/* A redraw clip represents (in stage coordinates) the bounding box of + * something that needs to be redraw. Typically they are added to the + * StageWindow as a result of clutter_actor_queue_clipped_redraw() by + * actors such as ClutterGLXTexturePixmap. All redraw clips are + * discarded after the next paint. + * + * A NULL stage_clip means the whole stage needs to be redrawn. + * + * What we do with this information: + * - we keep track of the bounding box for all redraw clips + * - when we come to redraw; we scissor the redraw to that box and use + * glBlitFramebuffer to present the redraw to the front + * buffer. + */ +static void +clutter_stage_cogl_add_redraw_clip (ClutterStageWindow *stage_window, + cairo_rectangle_int_t *stage_clip) +{ + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); + + /* If we are already forced to do a full stage redraw then bail early */ + if (clutter_stage_cogl_ignoring_redraw_clips (stage_window)) + return; + + /* A NULL stage clip means a full stage redraw has been queued and + * we keep track of this by setting a zero width + * stage_cogl->bounding_redraw_clip */ + if (stage_clip == NULL) + { + stage_cogl->bounding_redraw_clip.width = 0; + stage_cogl->initialized_redraw_clip = TRUE; + return; + } + + /* Ignore requests to add degenerate/empty clip rectangles */ + if (stage_clip->width == 0 || stage_clip->height == 0) + return; + + if (!stage_cogl->initialized_redraw_clip) + { + stage_cogl->bounding_redraw_clip = *stage_clip; + } + else if (stage_cogl->bounding_redraw_clip.width > 0) + { + _clutter_util_rectangle_union (&stage_cogl->bounding_redraw_clip, + stage_clip, + &stage_cogl->bounding_redraw_clip); + } + + stage_cogl->initialized_redraw_clip = TRUE; +} + +static gboolean +clutter_stage_cogl_get_redraw_clip_bounds (ClutterStageWindow *stage_window, + cairo_rectangle_int_t *stage_clip) +{ + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); + + if (stage_cogl->using_clipped_redraw) + { + *stage_clip = stage_cogl->bounding_redraw_clip; + + return TRUE; + } + + return FALSE; +} + +static inline gboolean +valid_buffer_age (ClutterStageViewCogl *view_cogl, + int age) +{ + ClutterStageViewCoglPrivate *view_priv = + clutter_stage_view_cogl_get_instance_private (view_cogl); + + if (age <= 0) + return FALSE; + + return age < MIN (view_priv->damage_index, DAMAGE_HISTORY_MAX); +} + +static gboolean +swap_framebuffer (ClutterStageWindow *stage_window, + ClutterStageView *view, + cairo_rectangle_int_t *swap_region, + gboolean swap_with_damage) +{ + CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (view); + int damage[4], ndamage; + + damage[0] = swap_region->x; + damage[1] = swap_region->y; + damage[2] = swap_region->width; + damage[3] = swap_region->height; + + if (swap_region->width != 0) + ndamage = 1; + else + ndamage = 0; + + if (cogl_is_onscreen (framebuffer)) + { + CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); + + /* push on the screen */ + if (ndamage == 1 && !swap_with_damage) + { + CLUTTER_NOTE (BACKEND, + "cogl_onscreen_swap_region (onscreen: %p, " + "x: %d, y: %d, " + "width: %d, height: %d)", + onscreen, + damage[0], damage[1], damage[2], damage[3]); + + cogl_onscreen_swap_region (onscreen, + damage, ndamage); + + return FALSE; + } + else + { + CLUTTER_NOTE (BACKEND, "cogl_onscreen_swap_buffers (onscreen: %p)", + onscreen); + + cogl_onscreen_swap_buffers_with_damage (onscreen, + damage, ndamage); + + return TRUE; + } + } + else + { + CLUTTER_NOTE (BACKEND, "cogl_framebuffer_finish (framebuffer: %p)", + framebuffer); + cogl_framebuffer_finish (framebuffer); + + return FALSE; + } +} + +static void +paint_stage (ClutterStageCogl *stage_cogl, + ClutterStageView *view, + const cairo_rectangle_int_t *clip) +{ + ClutterStage *stage = stage_cogl->wrapper; + + _clutter_stage_maybe_setup_viewport (stage, view); + _clutter_stage_paint_view (stage, view, clip); + + if (clutter_stage_view_get_onscreen (view) != + clutter_stage_view_get_framebuffer (view)) + { + clutter_stage_view_blit_offscreen (view, clip); + } +} + +static void +fill_current_damage_history_and_step (ClutterStageView *view) +{ + ClutterStageViewCogl *view_cogl = CLUTTER_STAGE_VIEW_COGL (view); + ClutterStageViewCoglPrivate *view_priv = + clutter_stage_view_cogl_get_instance_private (view_cogl); + cairo_rectangle_int_t view_rect; + cairo_rectangle_int_t *current_damage; + + current_damage = + &view_priv->damage_history[DAMAGE_HISTORY (view_priv->damage_index)]; + clutter_stage_view_get_layout (view, &view_rect); + + *current_damage = view_rect; + view_priv->damage_index++; +} + +static void +transform_swap_region_to_onscreen (ClutterStageView *view, + cairo_rectangle_int_t *swap_region) +{ + CoglFramebuffer *framebuffer; + cairo_rectangle_int_t layout; + gfloat x1, y1, x2, y2; + gint width, height; + + framebuffer = clutter_stage_view_get_onscreen (view); + clutter_stage_view_get_layout (view, &layout); + + x1 = (float) swap_region->x / layout.width; + y1 = (float) swap_region->y / layout.height; + x2 = (float) (swap_region->x + swap_region->width) / layout.width; + y2 = (float) (swap_region->y + swap_region->height) / layout.height; + + clutter_stage_view_transform_to_onscreen (view, &x1, &y1); + clutter_stage_view_transform_to_onscreen (view, &x2, &y2); + + width = cogl_framebuffer_get_width (framebuffer); + height = cogl_framebuffer_get_height (framebuffer); + + x1 = floor (x1 * width); + y1 = floor (height - (y1 * height)); + x2 = ceil (x2 * width); + y2 = ceil (height - (y2 * height)); + + *swap_region = (cairo_rectangle_int_t) { + .x = x1, + .y = y1, + .width = x2 - x1, + .height = y2 - y1 + }; +} + +static gboolean +clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window, + ClutterStageView *view) +{ + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); + ClutterStageViewCogl *view_cogl = CLUTTER_STAGE_VIEW_COGL (view); + ClutterStageViewCoglPrivate *view_priv = + clutter_stage_view_cogl_get_instance_private (view_cogl); + CoglFramebuffer *fb = clutter_stage_view_get_framebuffer (view); + cairo_rectangle_int_t view_rect; + gboolean have_clip; + gboolean may_use_clipped_redraw; + gboolean use_clipped_redraw; + gboolean can_blit_sub_buffer; + gboolean has_buffer_age; + gboolean do_swap_buffer; + gboolean swap_with_damage; + ClutterActor *wrapper; + cairo_rectangle_int_t redraw_clip; + cairo_rectangle_int_t swap_region; + cairo_rectangle_int_t clip_region; + gboolean clip_region_empty; + int window_scale; + + wrapper = CLUTTER_ACTOR (stage_cogl->wrapper); + + clutter_stage_view_get_layout (view, &view_rect); + + can_blit_sub_buffer = + cogl_is_onscreen (fb) && + cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_REGION); + + has_buffer_age = + cogl_is_onscreen (fb) && + cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_BUFFER_AGE); + + /* NB: a zero width redraw clip == full stage redraw */ + if (stage_cogl->bounding_redraw_clip.width == 0) + have_clip = FALSE; + else + { + redraw_clip = stage_cogl->bounding_redraw_clip; + _clutter_util_rectangle_intersection (&redraw_clip, + &view_rect, + &redraw_clip); + + have_clip = !(redraw_clip.x == view_rect.x && + redraw_clip.y == view_rect.y && + redraw_clip.width == view_rect.width && + redraw_clip.height == view_rect.height); + } + + may_use_clipped_redraw = FALSE; + if (_clutter_stage_window_can_clip_redraws (stage_window) && + (can_blit_sub_buffer || has_buffer_age) && + have_clip && + /* some drivers struggle to get going and produce some junk + * frames when starting up... */ + cogl_onscreen_get_frame_counter (COGL_ONSCREEN (fb)) > 3) + { + may_use_clipped_redraw = TRUE; + clip_region = redraw_clip; + } + else + { + clip_region = (cairo_rectangle_int_t){ 0 }; + } + + if (may_use_clipped_redraw && + G_LIKELY (!(clutter_paint_debug_flags & CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS))) + use_clipped_redraw = TRUE; + else + use_clipped_redraw = FALSE; + + clip_region_empty = may_use_clipped_redraw && clip_region.width == 0; + + window_scale = _clutter_stage_window_get_scale_factor (stage_window); + + swap_with_damage = FALSE; + if (has_buffer_age) + { + if (use_clipped_redraw && !clip_region_empty) + { + int age, i; + cairo_rectangle_int_t *current_damage = + &view_priv->damage_history[DAMAGE_HISTORY (view_priv->damage_index++)]; + + age = cogl_onscreen_get_buffer_age (COGL_ONSCREEN (fb)); + + if (valid_buffer_age (view_cogl, age)) + { + *current_damage = clip_region; + + for (i = 1; i <= age; i++) + { + cairo_rectangle_int_t *damage = + &view_priv->damage_history[DAMAGE_HISTORY (view_priv->damage_index - i - 1)]; + + _clutter_util_rectangle_union (&clip_region, damage, &clip_region); + } + + /* Update the bounding redraw clip state with the extra damage. */ + _clutter_util_rectangle_union (&stage_cogl->bounding_redraw_clip, + &clip_region, + &stage_cogl->bounding_redraw_clip); + + CLUTTER_NOTE (CLIPPING, "Reusing back buffer(age=%d) - repairing region: x=%d, y=%d, width=%d, height=%d\n", + age, + clip_region.x, + clip_region.y, + clip_region.width, + clip_region.height); + + swap_with_damage = TRUE; + } + else + { + CLUTTER_NOTE (CLIPPING, "Invalid back buffer(age=%d): forcing full redraw\n", age); + use_clipped_redraw = FALSE; + *current_damage = view_rect; + } + } + else if (!use_clipped_redraw) + { + fill_current_damage_history_and_step (view); + } + } + + cogl_push_framebuffer (fb); + if (use_clipped_redraw && clip_region_empty) + { + CLUTTER_NOTE (CLIPPING, "Empty stage output paint\n"); + } + else if (use_clipped_redraw) + { + int scissor_x; + int scissor_y; + + CLUTTER_NOTE (CLIPPING, + "Stage clip pushed: x=%d, y=%d, width=%d, height=%d\n", + clip_region.x, + clip_region.y, + clip_region.width, + clip_region.height); + + stage_cogl->using_clipped_redraw = TRUE; + + scissor_x = (clip_region.x - view_rect.x) * window_scale; + scissor_y = (clip_region.y - view_rect.y) * window_scale; + cogl_framebuffer_push_scissor_clip (fb, + scissor_x, + scissor_y, + clip_region.width * window_scale, + clip_region.height * window_scale); + paint_stage (stage_cogl, view, &clip_region); + cogl_framebuffer_pop_clip (fb); + + stage_cogl->using_clipped_redraw = FALSE; + } + else + { + CLUTTER_NOTE (CLIPPING, "Unclipped stage paint\n"); + + /* If we are trying to debug redraw issues then we want to pass + * the bounding_redraw_clip so it can be visualized */ + if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS) && + may_use_clipped_redraw && + !clip_region_empty) + { + int scissor_x; + int scissor_y; + + scissor_x = (clip_region.x - view_rect.x) * window_scale;; + scissor_y = (clip_region.y - view_rect.y) * window_scale; + cogl_framebuffer_push_scissor_clip (fb, + scissor_x, + scissor_y, + clip_region.width * window_scale, + clip_region.height * window_scale); + paint_stage (stage_cogl, view, &clip_region); + cogl_framebuffer_pop_clip (fb); + } + else + paint_stage (stage_cogl, view, &view_rect); + } + cogl_pop_framebuffer (); + + if (may_use_clipped_redraw && + G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_REDRAWS))) + { + CoglContext *ctx = cogl_framebuffer_get_context (fb); + static CoglPipeline *outline = NULL; + ClutterActor *actor = CLUTTER_ACTOR (wrapper); + float x_1 = redraw_clip.x; + float x_2 = redraw_clip.x + redraw_clip.width; + float y_1 = redraw_clip.y; + float y_2 = redraw_clip.y + redraw_clip.height; + CoglVertexP2 quad[4] = { + { x_1, y_1 }, + { x_2, y_1 }, + { x_2, y_2 }, + { x_1, y_2 } + }; + CoglPrimitive *prim; + CoglMatrix modelview; + + if (outline == NULL) + { + outline = cogl_pipeline_new (ctx); + cogl_pipeline_set_color4ub (outline, 0xff, 0x00, 0x00, 0xff); + } + + prim = cogl_primitive_new_p2 (ctx, + COGL_VERTICES_MODE_LINE_LOOP, + 4, /* n_vertices */ + quad); + + cogl_framebuffer_push_matrix (fb); + cogl_matrix_init_identity (&modelview); + _clutter_actor_apply_modelview_transform (actor, &modelview); + cogl_framebuffer_set_modelview_matrix (fb, &modelview); + cogl_framebuffer_draw_primitive (fb, outline, prim); + cogl_framebuffer_pop_matrix (fb); + cogl_object_unref (prim); + } + + /* XXX: It seems there will be a race here in that the stage + * window may be resized before the cogl_onscreen_swap_region + * is handled and so we may copy the wrong region. I can't + * really see how we can handle this with the current state of X + * but at least in this case a full redraw should be queued by + * the resize anyway so it should only exhibit temporary + * artefacts. + */ + if (use_clipped_redraw) + { + if (use_clipped_redraw && clip_region_empty) + { + do_swap_buffer = FALSE; + } + else if (use_clipped_redraw) + { + swap_region = (cairo_rectangle_int_t) { + .x = (clip_region.x - view_rect.x) * window_scale, + .y = (clip_region.y - view_rect.y) * window_scale, + .width = clip_region.width * window_scale, + .height = clip_region.height * window_scale, + }; + g_assert (swap_region.width > 0); + do_swap_buffer = TRUE; + } + else + { + swap_region = (cairo_rectangle_int_t) { + .x = 0, + .y = 0, + .width = view_rect.width * window_scale, + .height = view_rect.height * window_scale, + }; + do_swap_buffer = TRUE; + } + } + else + { + swap_region = (cairo_rectangle_int_t) { 0 }; + do_swap_buffer = TRUE; + } + + if (do_swap_buffer) + { + if (clutter_stage_view_get_onscreen (view) != + clutter_stage_view_get_framebuffer (view)) + { + transform_swap_region_to_onscreen (view, &swap_region); + } + + return swap_framebuffer (stage_window, + view, + &swap_region, + swap_with_damage); + } + else + { + return FALSE; + } +} + +static void +clutter_stage_cogl_redraw (ClutterStageWindow *stage_window) +{ + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); + gboolean swap_event = FALSE; + GList *l; + + for (l = _clutter_stage_window_get_views (stage_window); l; l = l->next) + { + ClutterStageView *view = l->data; + + swap_event = + clutter_stage_cogl_redraw_view (stage_window, view) || swap_event; + } + + _clutter_stage_window_finish_frame (stage_window); + + if (swap_event) + { + /* If we have swap buffer events then cogl_onscreen_swap_buffers + * will return immediately and we need to track that there is a + * swap in progress... */ + if (clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS)) + stage_cogl->pending_swaps++; + } + + /* reset the redraw clipping for the next paint... */ + stage_cogl->initialized_redraw_clip = FALSE; + + stage_cogl->frame_count++; +} + +static void +clutter_stage_cogl_get_dirty_pixel (ClutterStageWindow *stage_window, + ClutterStageView *view, + int *x, + int *y) +{ + CoglFramebuffer *framebuffer = clutter_stage_view_get_framebuffer (view); + gboolean has_buffer_age = + cogl_is_onscreen (framebuffer) && + cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_BUFFER_AGE); + cairo_rectangle_int_t *rect; + + if (!has_buffer_age) + { + *x = 0; + *y = 0; + } + else + { + ClutterStageViewCogl *view_cogl = CLUTTER_STAGE_VIEW_COGL (view); + ClutterStageViewCoglPrivate *view_priv = + clutter_stage_view_cogl_get_instance_private (view_cogl); + cairo_rectangle_int_t view_layout; + + clutter_stage_view_get_layout (view, &view_layout); + + rect = &view_priv->damage_history[DAMAGE_HISTORY (view_priv->damage_index - 1)]; + *x = rect->x - view_layout.x; + *y = rect->y - view_layout.y; + } +} + +static void +clutter_stage_window_iface_init (ClutterStageWindowIface *iface) +{ + iface->realize = clutter_stage_cogl_realize; + iface->unrealize = clutter_stage_cogl_unrealize; + iface->get_wrapper = clutter_stage_cogl_get_wrapper; + iface->resize = clutter_stage_cogl_resize; + iface->show = clutter_stage_cogl_show; + iface->hide = clutter_stage_cogl_hide; + iface->schedule_update = clutter_stage_cogl_schedule_update; + iface->get_update_time = clutter_stage_cogl_get_update_time; + iface->clear_update_time = clutter_stage_cogl_clear_update_time; + iface->add_redraw_clip = clutter_stage_cogl_add_redraw_clip; + iface->has_redraw_clips = clutter_stage_cogl_has_redraw_clips; + iface->ignoring_redraw_clips = clutter_stage_cogl_ignoring_redraw_clips; + iface->get_redraw_clip_bounds = clutter_stage_cogl_get_redraw_clip_bounds; + iface->redraw = clutter_stage_cogl_redraw; + iface->get_dirty_pixel = clutter_stage_cogl_get_dirty_pixel; +} + +static void +clutter_stage_cogl_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterStageCogl *self = CLUTTER_STAGE_COGL (gobject); + + switch (prop_id) + { + case PROP_WRAPPER: + self->wrapper = g_value_get_object (value); + break; + + case PROP_BACKEND: + self->backend = g_value_get_object (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +_clutter_stage_cogl_class_init (ClutterStageCoglClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = clutter_stage_cogl_set_property; + + g_object_class_override_property (gobject_class, PROP_WRAPPER, "wrapper"); + g_object_class_override_property (gobject_class, PROP_BACKEND, "backend"); +} + +static void +_clutter_stage_cogl_init (ClutterStageCogl *stage) +{ + stage->last_presentation_time = 0; + stage->refresh_rate = 0.0; + + stage->update_time = -1; +} + +static void +clutter_stage_view_cogl_init (ClutterStageViewCogl *view_cogl) +{ +} + +static void +clutter_stage_view_cogl_class_init (ClutterStageViewCoglClass *klass) +{ +} diff --git a/clutter/clutter/cogl/clutter-stage-cogl.h b/clutter/clutter/cogl/clutter-stage-cogl.h new file mode 100644 index 0000000..6122f2b --- /dev/null +++ b/clutter/clutter/cogl/clutter-stage-cogl.h @@ -0,0 +1,86 @@ +#ifndef __CLUTTER_STAGE_COGL_H__ +#define __CLUTTER_STAGE_COGL_H__ + +#include +#include +#include + +#ifdef COGL_HAS_X11_SUPPORT +#include +#include +#include +#endif + +#include "clutter/clutter-stage-window.h" + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_STAGE_COGL (_clutter_stage_cogl_get_type ()) +#define CLUTTER_STAGE_COGL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STAGE_COGL, ClutterStageCogl)) +#define CLUTTER_IS_STAGE_COGL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_STAGE_COGL)) +#define CLUTTER_STAGE_COGL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_STAGE_COGL, ClutterStageCoglClass)) +#define CLUTTER_IS_STAGE_COGL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_STAGE_COGL)) +#define CLUTTER_STAGE_COGL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_STAGE_COGL, ClutterStageCoglClass)) + +typedef struct _ClutterStageCogl ClutterStageCogl; +typedef struct _ClutterStageCoglClass ClutterStageCoglClass; + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterStageCogl, g_object_unref) + +#define CLUTTER_TYPE_STAGE_VIEW_COGL (clutter_stage_view_cogl_get_type ()) +CLUTTER_AVAILABLE_IN_MUTTER +G_DECLARE_DERIVABLE_TYPE (ClutterStageViewCogl, clutter_stage_view_cogl, + CLUTTER, STAGE_VIEW_COGL, + ClutterStageView) + +struct _ClutterStageViewCoglClass +{ + ClutterStageViewClass parent_class; +}; + +struct _ClutterStageCogl +{ + GObject parent_instance; + + /* the stage wrapper */ + ClutterStage *wrapper; + + /* back pointer to the backend */ + ClutterBackend *backend; + + float refresh_rate; + int pending_swaps; + + gint64 last_presentation_time; + gint64 update_time; + + /* We only enable clipped redraws after 2 frames, since we've seen + * a lot of drivers can struggle to get going and may output some + * junk frames to start with. */ + unsigned int frame_count; + + cairo_rectangle_int_t bounding_redraw_clip; + + guint initialized_redraw_clip : 1; + + /* TRUE if the current paint cycle has a clipped redraw. In that + case bounding_redraw_clip specifies the the bounds. */ + guint using_clipped_redraw : 1; +}; + +struct _ClutterStageCoglClass +{ + GObjectClass parent_class; +}; + +CLUTTER_AVAILABLE_IN_MUTTER +GType _clutter_stage_cogl_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_MUTTER +void _clutter_stage_cogl_presented (ClutterStageCogl *stage_cogl, + CoglFrameEvent frame_event, + ClutterFrameInfo *frame_info); + +G_END_DECLS + +#endif /* __CLUTTER_STAGE_COGL_H__ */ diff --git a/clutter/clutter/deprecated/clutter-actor-deprecated.c b/clutter/clutter/deprecated/clutter-actor-deprecated.c new file mode 100644 index 0000000..65d98dc --- /dev/null +++ b/clutter/clutter/deprecated/clutter-actor-deprecated.c @@ -0,0 +1,411 @@ +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include "deprecated/clutter-actor.h" + +#include "clutter-actor-private.h" +#include "clutter-private.h" +#include "clutter-shader.h" + +typedef struct _ShaderData ShaderData; + +struct _ShaderData +{ + ClutterShader *shader; + + /* back pointer to the actor */ + ClutterActor *actor; + + /* list of values that should be set on the shader + * before each paint cycle + */ + GHashTable *value_hash; +}; + +static void +shader_value_free (gpointer data) +{ + GValue *var = data; + g_value_unset (var); + g_slice_free (GValue, var); +} + +static void +destroy_shader_data (gpointer data) +{ + ShaderData *shader_data = data; + + if (shader_data == NULL) + return; + + if (shader_data->shader != NULL) + { + g_object_unref (shader_data->shader); + shader_data->shader = NULL; + } + + if (shader_data->value_hash != NULL) + { + g_hash_table_destroy (shader_data->value_hash); + shader_data->value_hash = NULL; + } + + g_slice_free (ShaderData, shader_data); +} + +/** + * clutter_actor_get_shader: + * @self: a #ClutterActor + * + * Queries the currently set #ClutterShader on @self. + * + * Return value: (transfer none): The currently set #ClutterShader + * or %NULL if no shader is set. + * + * Since: 0.6 + * + * Deprecated: 1.8: Use clutter_actor_get_effect() instead. + */ +ClutterShader * +clutter_actor_get_shader (ClutterActor *self) +{ + ShaderData *shader_data; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + + shader_data = g_object_get_data (G_OBJECT (self), "-clutter-actor-shader-data"); + if (shader_data != NULL) + return shader_data->shader; + + return NULL; +} + +/** + * clutter_actor_set_shader: + * @self: a #ClutterActor + * @shader: (allow-none): a #ClutterShader or %NULL to unset the shader. + * + * Sets the #ClutterShader to be used when rendering @self. + * + * If @shader is %NULL this function will unset any currently set shader + * for the actor. + * + * Any #ClutterEffect applied to @self will take the precedence + * over the #ClutterShader set using this function. + * + * Return value: %TRUE if the shader was successfully applied + * or removed + * + * Since: 0.6 + * + * Deprecated: 1.8: Use #ClutterShaderEffect and + * clutter_actor_add_effect() instead. + */ +gboolean +clutter_actor_set_shader (ClutterActor *self, + ClutterShader *shader) +{ + ShaderData *shader_data; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); + g_return_val_if_fail (shader == NULL || CLUTTER_IS_SHADER (shader), FALSE); + + if (shader != NULL) + g_object_ref (shader); + else + { + /* if shader passed in is NULL we destroy the shader */ + g_object_set_data (G_OBJECT (self), "-clutter-actor-shader-data", NULL); + return TRUE; + } + + shader_data = g_object_get_data (G_OBJECT (self), "-clutter-actor-shader-data"); + if (shader_data == NULL) + { + shader_data = g_slice_new (ShaderData); + shader_data->actor = self; + shader_data->shader = NULL; + shader_data->value_hash = + g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, + shader_value_free); + + g_object_set_data_full (G_OBJECT (self), "-clutter-actor-shader-data", + shader_data, + destroy_shader_data); + } + + if (shader_data->shader != NULL) + g_object_unref (shader_data->shader); + + shader_data->shader = shader; + + clutter_actor_queue_redraw (self); + + return TRUE; +} + +static void +set_each_param (gpointer key, + gpointer value, + gpointer user_data) +{ + ClutterShader *shader = user_data; + const gchar *uniform = key; + GValue *var = value; + + clutter_shader_set_uniform (shader, uniform, var); +} + +void +_clutter_actor_shader_pre_paint (ClutterActor *actor, + gboolean repeat) +{ + ShaderData *shader_data; + ClutterShader *shader; + + shader_data = g_object_get_data (G_OBJECT (actor), "-clutter-actor-shader-data"); + if (shader_data == NULL) + return; + + shader = shader_data->shader; + if (shader != NULL) + { + clutter_shader_set_is_enabled (shader, TRUE); + + g_hash_table_foreach (shader_data->value_hash, set_each_param, shader); + + if (!repeat) + _clutter_context_push_shader_stack (actor); + } +} + +void +_clutter_actor_shader_post_paint (ClutterActor *actor) +{ + ShaderData *shader_data; + ClutterShader *shader; + + shader_data = g_object_get_data (G_OBJECT (actor), "-clutter-actor-shader-data"); + if (G_LIKELY (shader_data == NULL)) + return; + + shader = shader_data->shader; + if (shader != NULL) + { + ClutterActor *head; + + clutter_shader_set_is_enabled (shader, FALSE); + + /* remove the actor from the shaders stack; if there is another + * actor inside it, then call pre-paint again to set its shader + * but this time with the second argument being TRUE, indicating + * that we are re-applying an existing shader and thus should it + * not be prepended to the stack + */ + head = _clutter_context_pop_shader_stack (actor); + if (head != NULL) + _clutter_actor_shader_pre_paint (head, TRUE); + } +} + +static inline void +clutter_actor_set_shader_param_internal (ClutterActor *self, + const gchar *param, + const GValue *value) +{ + ShaderData *shader_data; + GValue *var; + + shader_data = g_object_get_data (G_OBJECT (self), "-clutter-actor-shader-data"); + if (shader_data == NULL) + return; + + var = g_slice_new0 (GValue); + g_value_init (var, G_VALUE_TYPE (value)); + g_value_copy (value, var); + g_hash_table_insert (shader_data->value_hash, g_strdup (param), var); + + clutter_actor_queue_redraw (self); +} + +/** + * clutter_actor_set_shader_param: + * @self: a #ClutterActor + * @param: the name of the parameter + * @value: the value of the parameter + * + * Sets the value for a named parameter of the shader applied + * to @actor. + * + * Since: 1.0 + * + * Deprecated: 1.8: Use clutter_shader_effect_set_uniform_value() instead + */ +void +clutter_actor_set_shader_param (ClutterActor *self, + const gchar *param, + const GValue *value) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (param != NULL); + g_return_if_fail (CLUTTER_VALUE_HOLDS_SHADER_FLOAT (value) || + CLUTTER_VALUE_HOLDS_SHADER_INT (value) || + CLUTTER_VALUE_HOLDS_SHADER_MATRIX (value) || + G_VALUE_HOLDS_FLOAT (value) || + G_VALUE_HOLDS_INT (value)); + + clutter_actor_set_shader_param_internal (self, param, value); +} + +/** + * clutter_actor_set_shader_param_float: + * @self: a #ClutterActor + * @param: the name of the parameter + * @value: the value of the parameter + * + * Sets the value for a named float parameter of the shader applied + * to @actor. + * + * Since: 0.8 + * + * Deprecated: 1.8: Use clutter_shader_effect_set_uniform() instead + */ +void +clutter_actor_set_shader_param_float (ClutterActor *self, + const gchar *param, + gfloat value) +{ + GValue var = { 0, }; + + g_value_init (&var, G_TYPE_FLOAT); + g_value_set_float (&var, value); + + clutter_actor_set_shader_param_internal (self, param, &var); + + g_value_unset (&var); +} + +/** + * clutter_actor_set_shader_param_int: + * @self: a #ClutterActor + * @param: the name of the parameter + * @value: the value of the parameter + * + * Sets the value for a named int parameter of the shader applied to + * @actor. + * + * Since: 0.8 + * + * Deprecated: 1.8: Use clutter_shader_effect_set_uniform() instead + */ +void +clutter_actor_set_shader_param_int (ClutterActor *self, + const gchar *param, + gint value) +{ + GValue var = { 0, }; + + g_value_init (&var, G_TYPE_INT); + g_value_set_int (&var, value); + + clutter_actor_set_shader_param_internal (self, param, &var); + + g_value_unset (&var); +} + +/** + * clutter_actor_set_geometry: + * @self: A #ClutterActor + * @geometry: A #ClutterGeometry + * + * Sets the actor's fixed position and forces its minimum and natural + * size, in pixels. This means the untransformed actor will have the + * given geometry. This is the same as calling clutter_actor_set_position() + * and clutter_actor_set_size(). + * + * Deprecated: 1.10: Use clutter_actor_set_position() and + * clutter_actor_set_size() instead. + */ +void +clutter_actor_set_geometry (ClutterActor *self, + const ClutterGeometry *geometry) +{ + g_object_freeze_notify (G_OBJECT (self)); + + clutter_actor_set_position (self, geometry->x, geometry->y); + clutter_actor_set_size (self, geometry->width, geometry->height); + + g_object_thaw_notify (G_OBJECT (self)); +} + +/** + * clutter_actor_get_geometry: + * @self: A #ClutterActor + * @geometry: (out caller-allocates): A location to store actors #ClutterGeometry + * + * Gets the size and position of an actor relative to its parent + * actor. This is the same as calling clutter_actor_get_position() and + * clutter_actor_get_size(). It tries to "do what you mean" and get the + * requested size and position if the actor's allocation is invalid. + * + * Deprecated: 1.10: Use clutter_actor_get_position() and + * clutter_actor_get_size(), or clutter_actor_get_allocation_geometry() + * instead. + */ +void +clutter_actor_get_geometry (ClutterActor *self, + ClutterGeometry *geometry) +{ + gfloat x, y, width, height; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (geometry != NULL); + + clutter_actor_get_position (self, &x, &y); + clutter_actor_get_size (self, &width, &height); + + geometry->x = (int) x; + geometry->y = (int) y; + geometry->width = (int) width; + geometry->height = (int) height; +} + +/** + * clutter_actor_get_allocation_geometry: + * @self: A #ClutterActor + * @geom: (out): allocation geometry in pixels + * + * Gets the layout box an actor has been assigned. The allocation can + * only be assumed valid inside a paint() method; anywhere else, it + * may be out-of-date. + * + * An allocation does not incorporate the actor's scale or anchor point; + * those transformations do not affect layout, only rendering. + * + * The returned rectangle is in pixels. + * + * Since: 0.8 + * + * Deprecated: 1.12: Use clutter_actor_get_allocation_box() instead. + */ +void +clutter_actor_get_allocation_geometry (ClutterActor *self, + ClutterGeometry *geom) +{ + ClutterActorBox box; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (geom != NULL); + + clutter_actor_get_allocation_box (self, &box); + + geom->x = CLUTTER_NEARBYINT (clutter_actor_box_get_x (&box)); + geom->y = CLUTTER_NEARBYINT (clutter_actor_box_get_y (&box)); + geom->width = CLUTTER_NEARBYINT (clutter_actor_box_get_width (&box)); + geom->height = CLUTTER_NEARBYINT (clutter_actor_box_get_height (&box)); +} diff --git a/clutter/clutter/deprecated/clutter-actor.h b/clutter/clutter/deprecated/clutter-actor.h new file mode 100644 index 0000000..9302e94 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-actor.h @@ -0,0 +1,161 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006, 2007, 2008 OpenedHand Ltd + * Copyright (C) 2009, 2010 Intel Corp + * + * 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 . + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_ACTOR_DEPRECATED_H__ +#define __CLUTTER_ACTOR_DEPRECATED_H__ + +#include + +G_BEGIN_DECLS + +CLUTTER_DEPRECATED_IN_1_10 +void clutter_actor_set_geometry (ClutterActor *self, + const ClutterGeometry *geometry); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_get_allocation_geometry) +void clutter_actor_get_geometry (ClutterActor *self, + ClutterGeometry *geometry); +CLUTTER_DEPRECATED_IN_1_8 +guint32 clutter_actor_get_gid (ClutterActor *self); + +CLUTTER_DEPRECATED_IN_1_8 +ClutterActor * clutter_get_actor_by_gid (guint32 id_); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_remove_child() and clutter_actor_add_child()) +void clutter_actor_reparent (ClutterActor *self, + ClutterActor *new_parent); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_add_child) +void clutter_actor_set_parent (ClutterActor *self, + ClutterActor *parent); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_remove_child) +void clutter_actor_unparent (ClutterActor *self); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_set_child_above_sibling) +void clutter_actor_raise (ClutterActor *self, + ClutterActor *below); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_set_child_below_sibling) +void clutter_actor_lower (ClutterActor *self, + ClutterActor *above); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_set_child_above_sibling() with NULL sibling) +void clutter_actor_raise_top (ClutterActor *self); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_set_child_below_sibling() with NULL sibling) +void clutter_actor_lower_bottom (ClutterActor *self); + +CLUTTER_DEPRECATED_IN_1_10 +void clutter_actor_push_internal (ClutterActor *self); + +CLUTTER_DEPRECATED_IN_1_10 +void clutter_actor_pop_internal (ClutterActor *self); + +CLUTTER_DEPRECATED_IN_1_10 +void clutter_actor_show_all (ClutterActor *self); + +CLUTTER_DEPRECATED_IN_1_10 +void clutter_actor_hide_all (ClutterActor *self); + +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_actor_set_z_position) +void clutter_actor_set_depth (ClutterActor *self, + gfloat depth); + +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_actor_get_z_position) +gfloat clutter_actor_get_depth (ClutterActor *self); + +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_actor_set_rotation_angle) +void clutter_actor_set_rotation (ClutterActor *self, + ClutterRotateAxis axis, + gdouble angle, + gfloat x, + gfloat y, + gfloat z); +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_actor_set_rotation_angle and clutter_actor_set_pivot_point) +void clutter_actor_set_z_rotation_from_gravity (ClutterActor *self, + gdouble angle, + ClutterGravity gravity); +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_actor_get_rotation_angle) +gdouble clutter_actor_get_rotation (ClutterActor *self, + ClutterRotateAxis axis, + gfloat *x, + gfloat *y, + gfloat *z); +CLUTTER_DEPRECATED_IN_1_12 +ClutterGravity clutter_actor_get_z_rotation_gravity (ClutterActor *self); + +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_actor_set_scale and clutter_actor_set_pivot_point) +void clutter_actor_set_scale_full (ClutterActor *self, + gdouble scale_x, + gdouble scale_y, + gfloat center_x, + gfloat center_y); +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_actor_set_scale and clutter_actor_set_pivot_point) +void clutter_actor_set_scale_with_gravity (ClutterActor *self, + gdouble scale_x, + gdouble scale_y, + ClutterGravity gravity); +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_actor_get_pivot_point) +void clutter_actor_get_scale_center (ClutterActor *self, + gfloat *center_x, + gfloat *center_y); +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_actor_get_pivot_point) +ClutterGravity clutter_actor_get_scale_gravity (ClutterActor *self); + +CLUTTER_DEPRECATED_IN_1_12 +void clutter_actor_set_anchor_point (ClutterActor *self, + gfloat anchor_x, + gfloat anchor_y); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_actor_move_anchor_point (ClutterActor *self, + gfloat anchor_x, + gfloat anchor_y); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_actor_get_anchor_point (ClutterActor *self, + gfloat *anchor_x, + gfloat *anchor_y); +CLUTTER_DEPRECATED_IN_1_12 +ClutterGravity clutter_actor_get_anchor_point_gravity (ClutterActor *self); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_actor_set_anchor_point_from_gravity (ClutterActor *self, + ClutterGravity gravity); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_actor_move_anchor_point_from_gravity (ClutterActor *self, + ClutterGravity gravity); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_actor_get_transformation_matrix (ClutterActor *self, + ClutterMatrix *matrix); + +CLUTTER_DEPRECATED_IN_1_12_FOR (clutter_actor_get_allocation_box) +void clutter_actor_get_allocation_geometry (ClutterActor *self, + ClutterGeometry *geom); + +G_END_DECLS + +#endif /* __CLUTTER_ACTOR_DEPRECATED_H__ */ diff --git a/clutter/clutter/deprecated/clutter-alpha.c b/clutter/clutter/deprecated/clutter-alpha.c new file mode 100644 index 0000000..c3936da --- /dev/null +++ b/clutter/clutter/deprecated/clutter-alpha.c @@ -0,0 +1,952 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * Jorn Baayen + * Emmanuele Bassi + * Tomas Frydrych + * + * Copyright (C) 2006, 2007, 2008 OpenedHand + * Copyright (C) 2009, 2010 Intel Corp. + * + * 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 . + */ + +/** + * SECTION:clutter-alpha + * @short_description: A class for calculating a value as a function of time + * + * #ClutterAlpha is a class for calculating an floating point value + * dependent only on the position of a #ClutterTimeline. + * + * For newly written code, it is recommended to use the + * #ClutterTimeline:progress-mode property of #ClutterTimeline, or the + * clutter_timeline_set_progress_func() function instead of #ClutterAlpha. + * The #ClutterAlpha class will be deprecated in the future, and will not + * be available any more in the next major version of Clutter. + * + * A #ClutterAlpha binds a #ClutterTimeline to a progress function which + * translates the time T into an adimensional factor alpha. The factor can + * then be used to drive a #ClutterBehaviour, which will translate the + * alpha value into something meaningful for a #ClutterActor. + * + * You should provide a #ClutterTimeline and bind it to the #ClutterAlpha + * instance using clutter_alpha_set_timeline(). You should also set an + * "animation mode", either by using the #ClutterAnimationMode values that + * Clutter itself provides or by registering custom functions using + * clutter_alpha_register_func(). + * + * Instead of a #ClutterAnimationMode you may provide a function returning + * the alpha value depending on the progress of the timeline, using + * clutter_alpha_set_func() or clutter_alpha_set_closure(). The alpha + * function will be executed each time a new frame in the #ClutterTimeline + * is reached. + * + * Since the alpha function is controlled by the timeline instance, you can + * pause, stop or resume the #ClutterAlpha from calling the alpha function by + * using the appropriate functions of the #ClutterTimeline object. + * + * #ClutterAlpha is used to "drive" a #ClutterBehaviour instance, and it + * is internally used by the #ClutterAnimation API. + * + * #ClutterAlpha is available since Clutter 0.2. + * + * #ClutterAlpha is deprecated since Clutter 1.12. #ClutterTimeline and + * the #ClutterTimeline:progress-mode property replace this whole class. + * + * ## ClutterAlpha custom properties for #ClutterScript + * + * #ClutterAlpha defines a custom `function` property for + * #ClutterScript which allows to reference a custom alpha function + * available in the source code. Setting the `function` property + * is equivalent to calling clutter_alpha_set_func() with the + * specified function name. No user data or #GDestroyNotify is + * available to be passed. + * + * The following JSON fragment defines a #ClutterAlpha + * using a #ClutterTimeline with id "sine-timeline" and an alpha + * function called `my_sine_alpha`. The defined #ClutterAlpha + * instance can be reused in multiple #ClutterBehaviour + * definitions or for #ClutterAnimation definitions. + * + * |[ + * { + * "id" : "sine-alpha", + * "timeline" : { + * "id" : "sine-timeline", + * "duration" : 500, + * "loop" : true + * }, + * "function" : "my_sine_alpha" + * } + * ]| + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS + +#include "clutter-alpha.h" +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-easing.h" +#include "clutter-main.h" +#include "clutter-marshal.h" +#include "clutter-private.h" +#include "clutter-scriptable.h" +#include "clutter-script-private.h" + +struct _ClutterAlphaPrivate +{ + ClutterTimeline *timeline; + guint timeline_new_frame_id; + + gdouble alpha; + + GClosure *closure; + + ClutterAlphaFunc func; + gpointer user_data; + GDestroyNotify notify; + + gulong mode; +}; + +enum +{ + PROP_0, + + PROP_TIMELINE, + PROP_ALPHA, + PROP_MODE, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +static void clutter_scriptable_iface_init (ClutterScriptableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (ClutterAlpha, + clutter_alpha, + G_TYPE_INITIALLY_UNOWNED, + G_ADD_PRIVATE (ClutterAlpha) + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_SCRIPTABLE, + clutter_scriptable_iface_init)); + +static void +timeline_new_frame_cb (ClutterTimeline *timeline, + guint msecs, + ClutterAlpha *alpha) +{ + ClutterAlphaPrivate *priv = alpha->priv; + + /* Update alpha value and notify */ + priv->alpha = clutter_alpha_get_alpha (alpha); + g_object_notify_by_pspec (G_OBJECT (alpha), obj_props[PROP_ALPHA]); +} + +static void +clutter_alpha_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterAlpha *alpha = CLUTTER_ALPHA (object); + + switch (prop_id) + { + case PROP_TIMELINE: + clutter_alpha_set_timeline (alpha, g_value_get_object (value)); + break; + + case PROP_MODE: + clutter_alpha_set_mode (alpha, g_value_get_ulong (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_alpha_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterAlphaPrivate *priv = CLUTTER_ALPHA (object)->priv; + + switch (prop_id) + { + case PROP_TIMELINE: + g_value_set_object (value, priv->timeline); + break; + + case PROP_ALPHA: + g_value_set_double (value, priv->alpha); + break; + + case PROP_MODE: + g_value_set_ulong (value, priv->mode); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_alpha_finalize (GObject *object) +{ + ClutterAlphaPrivate *priv = CLUTTER_ALPHA (object)->priv; + + if (priv->notify != NULL) + priv->notify (priv->user_data); + else if (priv->closure != NULL) + g_closure_unref (priv->closure); + + G_OBJECT_CLASS (clutter_alpha_parent_class)->finalize (object); +} + +static void +clutter_alpha_dispose (GObject *object) +{ + ClutterAlpha *self = CLUTTER_ALPHA(object); + + clutter_alpha_set_timeline (self, NULL); + + G_OBJECT_CLASS (clutter_alpha_parent_class)->dispose (object); +} + +static ClutterAlphaFunc +resolve_alpha_func (const gchar *name) +{ + static GModule *module = NULL; + ClutterAlphaFunc func; + + CLUTTER_NOTE (SCRIPT, "Looking up '%s' alpha function", name); + + if (G_UNLIKELY (module == NULL)) + module = g_module_open (NULL, 0); + + if (g_module_symbol (module, name, (gpointer) &func)) + { + CLUTTER_NOTE (SCRIPT, "Found '%s' alpha function in the symbols table", + name); + return func; + } + + return NULL; +} + +static void +clutter_alpha_set_custom_property (ClutterScriptable *scriptable, + ClutterScript *script, + const gchar *name, + const GValue *value) +{ + if (strncmp (name, "function", 8) == 0) + { + g_assert (G_VALUE_HOLDS (value, G_TYPE_POINTER)); + if (g_value_get_pointer (value) != NULL) + { + clutter_alpha_set_func (CLUTTER_ALPHA (scriptable), + g_value_get_pointer (value), + NULL, NULL); + } + } + else + g_object_set_property (G_OBJECT (scriptable), name, value); +} + +static gboolean +clutter_alpha_parse_custom_node (ClutterScriptable *scriptable, + ClutterScript *script, + GValue *value, + const gchar *name, + JsonNode *node) +{ + if (strncmp (name, "function", 8) == 0) + { + const gchar *func_name = json_node_get_string (node); + + g_value_init (value, G_TYPE_POINTER); + g_value_set_pointer (value, resolve_alpha_func (func_name)); + + return TRUE; + } + + /* we need to do this because we use gulong in place + * of ClutterAnimationMode for ClutterAlpha:mode + */ + if (strncmp (name, "mode", 4) == 0) + { + gulong mode; + + mode = _clutter_script_resolve_animation_mode (node); + + g_value_init (value, G_TYPE_ULONG); + g_value_set_ulong (value, mode); + + return TRUE; + } + + return FALSE; +} + +static void +clutter_scriptable_iface_init (ClutterScriptableIface *iface) +{ + iface->parse_custom_node = clutter_alpha_parse_custom_node; + iface->set_custom_property = clutter_alpha_set_custom_property; +} + +static void +clutter_alpha_class_init (ClutterAlphaClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->set_property = clutter_alpha_set_property; + object_class->get_property = clutter_alpha_get_property; + object_class->finalize = clutter_alpha_finalize; + object_class->dispose = clutter_alpha_dispose; + + /** + * ClutterAlpha:timeline: + * + * A #ClutterTimeline instance used to drive the alpha function. + * + * Since: 0.2 + * + * Deprecated: 1.12 + */ + obj_props[PROP_TIMELINE] = + g_param_spec_object ("timeline", + P_("Timeline"), + P_("Timeline used by the alpha"), + CLUTTER_TYPE_TIMELINE, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterAlpha:alpha: + * + * The alpha value as computed by the alpha function. The linear + * interval is 0.0 to 1.0, but the Alpha allows overshooting by + * one unit in each direction, so the valid interval is -1.0 to 2.0. + * + * Since: 0.2 + * Deprecated: 1.12: Use #ClutterTimeline::new-frame and + * clutter_timeline_get_progress() instead + */ + obj_props[PROP_ALPHA] = + g_param_spec_double ("alpha", + P_("Alpha value"), + P_("Alpha value as computed by the alpha"), + -1.0, 2.0, + 0.0, + CLUTTER_PARAM_READABLE); + + /** + * ClutterAlpha:mode: + * + * The progress function logical id - either a value from the + * #ClutterAnimationMode enumeration or a value returned by + * clutter_alpha_register_func(). + * + * If %CLUTTER_CUSTOM_MODE is used then the function set using + * clutter_alpha_set_closure() or clutter_alpha_set_func() + * will be used. + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterTimeline:progress-mode + */ + obj_props[PROP_MODE] = + g_param_spec_ulong ("mode", + P_("Mode"), + P_("Progress mode"), + 0, G_MAXULONG, + CLUTTER_CUSTOM_MODE, + G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE); + + g_object_class_install_properties (object_class, + PROP_LAST, + obj_props); +} + +static void +clutter_alpha_init (ClutterAlpha *self) +{ + self->priv = clutter_alpha_get_instance_private (self); + self->priv->mode = CLUTTER_CUSTOM_MODE; + self->priv->alpha = 0.0; +} + +/** + * clutter_alpha_get_alpha: + * @alpha: A #ClutterAlpha + * + * Query the current alpha value. + * + * Return Value: The current alpha value for the alpha + * + * Since: 0.2 + * + * Deprecated: 1.12: Use clutter_timeline_get_progress() + */ +gdouble +clutter_alpha_get_alpha (ClutterAlpha *alpha) +{ + ClutterAlphaPrivate *priv; + gdouble retval = 0; + + g_return_val_if_fail (CLUTTER_IS_ALPHA (alpha), 0); + + priv = alpha->priv; + + if (G_LIKELY (priv->func)) + { + return priv->func (alpha, priv->user_data); + } + else if (priv->closure) + { + GValue params = G_VALUE_INIT; + GValue result_value = G_VALUE_INIT; + + g_object_ref (alpha); + + g_value_init (&result_value, G_TYPE_DOUBLE); + + g_value_init (¶ms, CLUTTER_TYPE_ALPHA); + g_value_set_object (¶ms, alpha); + + g_closure_invoke (priv->closure, &result_value, 1, ¶ms, NULL); + + retval = g_value_get_double (&result_value); + + g_value_unset (&result_value); + g_value_unset (¶ms); + + g_object_unref (alpha); + } + + return retval; +} + +/* + * clutter_alpha_set_closure_internal: + * @alpha: a #ClutterAlpha + * @closure: a #GClosure + * + * Sets the @closure for @alpha. This function does not + * set the #ClutterAlpha:mode property and does not emit + * the #GObject::notify signal for it. + */ +static inline void +clutter_alpha_set_closure_internal (ClutterAlpha *alpha, + GClosure *closure) +{ + ClutterAlphaPrivate *priv = alpha->priv; + + if (priv->notify != NULL) + priv->notify (priv->user_data); + else if (priv->closure != NULL) + g_closure_unref (priv->closure); + + priv->func = NULL; + priv->user_data = NULL; + priv->notify = NULL; + + if (closure == NULL) + return; + + /* need to take ownership of the closure before sinking it */ + priv->closure = g_closure_ref (closure); + g_closure_sink (closure); + + /* set the marshaller */ + if (G_CLOSURE_NEEDS_MARSHAL (closure)) + { + GClosureMarshal marshal = _clutter_marshal_DOUBLE__VOID; + + g_closure_set_marshal (priv->closure, marshal); + } +} + +/** + * clutter_alpha_set_closure: + * @alpha: A #ClutterAlpha + * @closure: A #GClosure + * + * Sets the #GClosure used to compute the alpha value at each + * frame of the #ClutterTimeline bound to @alpha. + * + * Since: 0.8 + * + * Deprecated: 1.12: Use clutter_timeline_set_progress_func() + */ +void +clutter_alpha_set_closure (ClutterAlpha *alpha, + GClosure *closure) +{ + ClutterAlphaPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ALPHA (alpha)); + g_return_if_fail (closure != NULL); + + priv = alpha->priv; + + clutter_alpha_set_closure_internal (alpha, closure); + + priv->mode = CLUTTER_CUSTOM_MODE; + g_object_notify_by_pspec (G_OBJECT (alpha), obj_props[PROP_MODE]); +} + +/** + * clutter_alpha_set_func: + * @alpha: A #ClutterAlpha + * @func: A #ClutterAlphaFunc + * @data: user data to be passed to the alpha function, or %NULL + * @destroy: notify function used when disposing the alpha function + * + * Sets the #ClutterAlphaFunc function used to compute + * the alpha value at each frame of the #ClutterTimeline + * bound to @alpha. + * + * This function will not register @func as a global alpha function. + * + * Since: 0.2 + * + * Deprecated: 1.12: Use clutter_timeline_set_progress_func() + */ +void +clutter_alpha_set_func (ClutterAlpha *alpha, + ClutterAlphaFunc func, + gpointer data, + GDestroyNotify destroy) +{ + ClutterAlphaPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ALPHA (alpha)); + g_return_if_fail (func != NULL); + + priv = alpha->priv; + + if (priv->notify != NULL) + { + priv->notify (priv->user_data); + } + else if (priv->closure != NULL) + { + g_closure_unref (priv->closure); + priv->closure = NULL; + } + + priv->func = func; + priv->user_data = data; + priv->notify = destroy; + + priv->mode = CLUTTER_CUSTOM_MODE; + + g_object_notify_by_pspec (G_OBJECT (alpha), obj_props[PROP_MODE]); +} + +/** + * clutter_alpha_set_timeline: + * @alpha: A #ClutterAlpha + * @timeline: A #ClutterTimeline + * + * Binds @alpha to @timeline. + * + * Since: 0.2 + * + * Deprecated: 1.12: Use #ClutterTimeline directly + */ +void +clutter_alpha_set_timeline (ClutterAlpha *alpha, + ClutterTimeline *timeline) +{ + ClutterAlphaPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ALPHA (alpha)); + g_return_if_fail (timeline == NULL || CLUTTER_IS_TIMELINE (timeline)); + + priv = alpha->priv; + + if (priv->timeline == timeline) + return; + + if (priv->timeline) + { + g_signal_handlers_disconnect_by_func (priv->timeline, + timeline_new_frame_cb, + alpha); + + g_object_unref (priv->timeline); + priv->timeline = NULL; + } + + if (timeline) + { + priv->timeline = g_object_ref (timeline); + + g_signal_connect (priv->timeline, "new-frame", + G_CALLBACK (timeline_new_frame_cb), + alpha); + } + + g_object_notify_by_pspec (G_OBJECT (alpha), obj_props[PROP_TIMELINE]); +} + +/** + * clutter_alpha_get_timeline: + * @alpha: A #ClutterAlpha + * + * Gets the #ClutterTimeline bound to @alpha. + * + * Return value: (transfer none): a #ClutterTimeline instance + * + * Since: 0.2 + * + * Deprecated: 1.12: Use #ClutterTimeline directlry + */ +ClutterTimeline * +clutter_alpha_get_timeline (ClutterAlpha *alpha) +{ + g_return_val_if_fail (CLUTTER_IS_ALPHA (alpha), NULL); + + return alpha->priv->timeline; +} + +/** + * clutter_alpha_new: + * + * Creates a new #ClutterAlpha instance. You must set a function + * to compute the alpha value using clutter_alpha_set_func() and + * bind a #ClutterTimeline object to the #ClutterAlpha instance + * using clutter_alpha_set_timeline(). + * + * You should use the newly created #ClutterAlpha instance inside + * a #ClutterBehaviour object. + * + * Return value: the newly created empty #ClutterAlpha instance. + * + * Since: 0.2 + * + * Deprecated: 1.12: Use #ClutterTimeline instead + */ +ClutterAlpha * +clutter_alpha_new (void) +{ + return g_object_new (CLUTTER_TYPE_ALPHA, NULL); +} + +/** + * clutter_alpha_new_full: + * @timeline: #ClutterTimeline timeline + * @mode: animation mode + * + * Creates a new #ClutterAlpha instance and sets the timeline + * and animation mode. + * + * See also clutter_alpha_set_timeline() and clutter_alpha_set_mode(). + * + * Return Value: the newly created #ClutterAlpha + * + * Since: 1.0 + * + * Deprecated: 1.12: Use #ClutterTimeline instead + */ +ClutterAlpha * +clutter_alpha_new_full (ClutterTimeline *timeline, + gulong mode) +{ + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), NULL); + g_return_val_if_fail (mode != CLUTTER_ANIMATION_LAST, NULL); + + return g_object_new (CLUTTER_TYPE_ALPHA, + "timeline", timeline, + "mode", mode, + NULL); +} + +/** + * clutter_alpha_new_with_func: + * @timeline: a #ClutterTimeline + * @func: a #ClutterAlphaFunc + * @data: data to pass to the function, or %NULL + * @destroy: function to call when removing the alpha function, or %NULL + * + * Creates a new #ClutterAlpha instances and sets the timeline + * and the alpha function. + * + * This function will not register @func as a global alpha function. + * + * See also clutter_alpha_set_timeline() and clutter_alpha_set_func(). + * + * Return value: the newly created #ClutterAlpha + * + * Since: 1.0 + * + * Deprecated: 1.12: Use #ClutterTimeline instead + */ +ClutterAlpha * +clutter_alpha_new_with_func (ClutterTimeline *timeline, + ClutterAlphaFunc func, + gpointer data, + GDestroyNotify destroy) +{ + ClutterAlpha *retval; + + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), NULL); + g_return_val_if_fail (func != NULL, NULL); + + retval = clutter_alpha_new (); + clutter_alpha_set_timeline (retval, timeline); + clutter_alpha_set_func (retval, func, data, destroy); + + return retval; +} + +/** + * clutter_alpha_get_mode: + * @alpha: a #ClutterAlpha + * + * Retrieves the #ClutterAnimationMode used by @alpha. + * + * Return value: the animation mode + * + * Since: 1.0 + * + * Deprecated: 1.12: Use #ClutterTimeline instead + */ +gulong +clutter_alpha_get_mode (ClutterAlpha *alpha) +{ + g_return_val_if_fail (CLUTTER_IS_ALPHA (alpha), CLUTTER_CUSTOM_MODE); + + return alpha->priv->mode; +} + +typedef struct _AlphaData { + guint closure_set : 1; + + ClutterAlphaFunc func; + gpointer data; + + GClosure *closure; +} AlphaData; + +static GPtrArray *clutter_alphas = NULL; + +static gdouble +clutter_alpha_easing_func (ClutterAlpha *alpha, + gpointer data G_GNUC_UNUSED) +{ + ClutterAlphaPrivate *priv = alpha->priv; + ClutterTimeline *timeline = priv->timeline; + gdouble t, d; + + if (G_UNLIKELY (priv->timeline == NULL)) + return 0.0; + + t = clutter_timeline_get_elapsed_time (timeline); + d = clutter_timeline_get_duration (timeline); + + return clutter_easing_for_mode (priv->mode, t, d); +} + +/** + * clutter_alpha_set_mode: + * @alpha: a #ClutterAlpha + * @mode: a #ClutterAnimationMode + * + * Sets the progress function of @alpha using the symbolic value + * of @mode, as taken by the #ClutterAnimationMode enumeration or + * using the value returned by clutter_alpha_register_func(). + * + * Since: 1.0 + * + * Deprecated: 1.12: Use #ClutterTimeline and + * clutter_timeline_set_progress_mode() instead + */ +void +clutter_alpha_set_mode (ClutterAlpha *alpha, + gulong mode) +{ + ClutterAlphaPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ALPHA (alpha)); + g_return_if_fail (mode != CLUTTER_ANIMATION_LAST); + + priv = alpha->priv; + + if (mode == CLUTTER_CUSTOM_MODE) + { + priv->mode = mode; + } + else if (mode < CLUTTER_ANIMATION_LAST) + { + if (priv->mode == mode) + return; + + /* sanity check to avoid getting an out of sync + * enum/function mapping + */ + g_assert (clutter_get_easing_func_for_mode (mode) != NULL); + + clutter_alpha_set_closure_internal (alpha, NULL); + + priv->mode = mode; + + CLUTTER_NOTE (ANIMATION, "New easing mode '%s'[%lu]\n", + clutter_get_easing_name_for_mode (priv->mode), + priv->mode); + + priv->func = clutter_alpha_easing_func; + priv->user_data = NULL; + priv->notify = NULL; + } + else if (mode > CLUTTER_ANIMATION_LAST) + { + AlphaData *alpha_data = NULL; + gulong real_index = 0; + + if (priv->mode == mode) + return; + + if (G_UNLIKELY (clutter_alphas == NULL)) + { + g_warning ("No alpha functions defined for ClutterAlpha to use. " + "Use clutter_alpha_register_func() to register an " + "alpha function."); + return; + } + + real_index = mode - CLUTTER_ANIMATION_LAST - 1; + + alpha_data = g_ptr_array_index (clutter_alphas, real_index); + if (G_UNLIKELY (alpha_data == NULL)) + { + g_warning ("No alpha function registered for mode %lu.", + mode); + return; + } + + if (alpha_data->closure_set) + clutter_alpha_set_closure (alpha, alpha_data->closure); + else + { + clutter_alpha_set_closure_internal (alpha, NULL); + + priv->func = alpha_data->func; + priv->user_data = alpha_data->data; + priv->notify = NULL; + } + + priv->mode = mode; + } + else + g_assert_not_reached (); + + g_object_notify_by_pspec (G_OBJECT (alpha), obj_props[PROP_MODE]); +} + +static gulong +register_alpha_internal (AlphaData *alpha_data) +{ + if (G_UNLIKELY (clutter_alphas == NULL)) + clutter_alphas = g_ptr_array_new (); + + g_ptr_array_add (clutter_alphas, alpha_data); + + return clutter_alphas->len + CLUTTER_ANIMATION_LAST; +} + +/** + * clutter_alpha_register_func: (skip) + * @func: a #ClutterAlphaFunc + * @data: user data to pass to @func, or %NULL + * + * Registers a global alpha function and returns its logical id + * to be used by clutter_alpha_set_mode() or by #ClutterAnimation. + * + * The logical id is always greater than %CLUTTER_ANIMATION_LAST. + * + * Return value: the logical id of the alpha function + * + * Since: 1.0 + * + * Deprecated: 1.12: There is no direct replacement for this + * function. Use clutter_timeline_set_progress_func() on each + * specific #ClutterTimeline instance + */ +gulong +clutter_alpha_register_func (ClutterAlphaFunc func, + gpointer data) +{ + AlphaData *alpha_data; + + g_return_val_if_fail (func != NULL, 0); + + alpha_data = g_slice_new (AlphaData); + alpha_data->closure_set = FALSE; + alpha_data->func = func; + alpha_data->data = data; + + return register_alpha_internal (alpha_data); +} + +/** + * clutter_alpha_register_closure: (rename-to clutter_alpha_register_func) + * @closure: a #GClosure + * + * #GClosure variant of clutter_alpha_register_func(). + * + * Registers a global alpha function and returns its logical id + * to be used by clutter_alpha_set_mode() or by #ClutterAnimation. + * + * The logical id is always greater than %CLUTTER_ANIMATION_LAST. + * + * Return value: the logical id of the alpha function + * + * Since: 1.0 + * + * Deprecated: 1.12: There is no direct replacement for this + * function. Use clutter_timeline_set_progress_func() on each + * specific #ClutterTimeline instance + */ +gulong +clutter_alpha_register_closure (GClosure *closure) +{ + AlphaData *alpha_data; + + g_return_val_if_fail (closure != NULL, 0); + + alpha_data = g_slice_new (AlphaData); + alpha_data->closure_set = TRUE; + alpha_data->closure = closure; + + return register_alpha_internal (alpha_data); +} diff --git a/clutter/clutter/deprecated/clutter-alpha.h b/clutter/clutter/deprecated/clutter-alpha.h new file mode 100644 index 0000000..8a0dff6 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-alpha.h @@ -0,0 +1,150 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * Jorn Baayen + * Emmanuele Bassi + * Tomas Frydrych + * + * Copyright (C) 2006, 2007, 2008 OpenedHand + * Copyright (C) 2009 Intel Corp. + * + * 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 . + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_ALPHA_H__ +#define __CLUTTER_ALPHA_H__ + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_ALPHA (clutter_alpha_get_type ()) +#define CLUTTER_ALPHA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ALPHA, ClutterAlpha)) +#define CLUTTER_ALPHA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_ALPHA, ClutterAlphaClass)) +#define CLUTTER_IS_ALPHA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ALPHA)) +#define CLUTTER_IS_ALPHA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_ALPHA)) +#define CLUTTER_ALPHA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_ALPHA, ClutterAlphaClass)) + +typedef struct _ClutterAlphaClass ClutterAlphaClass; +typedef struct _ClutterAlphaPrivate ClutterAlphaPrivate; + +/** + * ClutterAlphaFunc: + * @alpha: a #ClutterAlpha + * @user_data: user data passed to the function + * + * A function returning a value depending on the position of + * the #ClutterTimeline bound to @alpha. + * + * Return value: a floating point value + * + * Since: 0.2 + * + * Deprecated: 1.12: Use #ClutterTimelineProgressFunc instead. + */ +typedef gdouble (*ClutterAlphaFunc) (ClutterAlpha *alpha, + gpointer user_data); + +/** + * ClutterAlpha: + * + * #ClutterAlpha combines a #ClutterTimeline and a function. + * The contents of the #ClutterAlpha structure are private and should + * only be accessed using the provided API. + * + * Since: 0.2 + * + * Deprecated: 1.12: Use #ClutterTimeline instead + */ +struct _ClutterAlpha +{ + /*< private >*/ + GInitiallyUnowned parent; + + ClutterAlphaPrivate *priv; +}; + +/** + * ClutterAlphaClass: + * + * Base class for #ClutterAlpha + * + * Since: 0.2 + * + * Deprecated: 1.12: Use #ClutterTimeline instead + */ +struct _ClutterAlphaClass +{ + /*< private >*/ + GInitiallyUnownedClass parent_class; + + void (*_clutter_alpha_1) (void); + void (*_clutter_alpha_2) (void); + void (*_clutter_alpha_3) (void); + void (*_clutter_alpha_4) (void); + void (*_clutter_alpha_5) (void); +}; + +CLUTTER_DEPRECATED_IN_1_12 +GType clutter_alpha_get_type (void) G_GNUC_CONST; + +CLUTTER_DEPRECATED_IN_1_12 +ClutterAlpha * clutter_alpha_new (void); +CLUTTER_DEPRECATED_IN_1_12 +ClutterAlpha * clutter_alpha_new_full (ClutterTimeline *timeline, + gulong mode); +CLUTTER_DEPRECATED_IN_1_12 +ClutterAlpha * clutter_alpha_new_with_func (ClutterTimeline *timeline, + ClutterAlphaFunc func, + gpointer data, + GDestroyNotify destroy); + +CLUTTER_DEPRECATED_IN_1_12 +gdouble clutter_alpha_get_alpha (ClutterAlpha *alpha); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_alpha_set_func (ClutterAlpha *alpha, + ClutterAlphaFunc func, + gpointer data, + GDestroyNotify destroy); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_alpha_set_closure (ClutterAlpha *alpha, + GClosure *closure); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_alpha_set_timeline (ClutterAlpha *alpha, + ClutterTimeline *timeline); +CLUTTER_DEPRECATED_IN_1_12 +ClutterTimeline *clutter_alpha_get_timeline (ClutterAlpha *alpha); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_alpha_set_mode (ClutterAlpha *alpha, + gulong mode); +CLUTTER_DEPRECATED_IN_1_12 +gulong clutter_alpha_get_mode (ClutterAlpha *alpha); + +CLUTTER_DEPRECATED_IN_1_12 +gulong clutter_alpha_register_func (ClutterAlphaFunc func, + gpointer data); +CLUTTER_DEPRECATED_IN_1_12 +gulong clutter_alpha_register_closure (GClosure *closure); + +G_END_DECLS + +#endif /* __CLUTTER_ALPHA_H__ */ diff --git a/clutter/clutter/deprecated/clutter-animatable.h b/clutter/clutter/deprecated/clutter-animatable.h new file mode 100644 index 0000000..df40e28 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-animatable.h @@ -0,0 +1,47 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * 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 . + * + * Author: + * Emmanuele Bassi + */ + +#ifndef __CLUTTER_ANIMATABLE_DEPRECATED_H__ +#define __CLUTTER_ANIMATABLE_DEPRECATED_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +CLUTTER_DEPRECATED_IN_1_8_FOR(clutter_animatable_interpolate_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 + +#endif /* __CLUTTER_ANIMATABLE_DEPRECATED_H__ */ diff --git a/clutter/clutter/deprecated/clutter-animation.c b/clutter/clutter/deprecated/clutter-animation.c new file mode 100644 index 0000000..14b9e72 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-animation.c @@ -0,0 +1,2632 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2008 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 . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-animation + * @short_description: Simple implicit animations + * @See_Also: #ClutterAnimatable, #ClutterInterval, #ClutterAlpha, + * #ClutterTimeline + * + * #ClutterAnimation is an object providing simple, implicit animations + * for #GObjects. + * + * #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. + * + * #ClutterAnimations are distinguished from #ClutterBehaviours + * 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 #ClutterActors + * 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 + * a #ClutterAnimation instance and animate an actor between its current + * state and the specified final state. + * + * #ClutterAnimation is available since Clutter 1.0. + * + * #ClutterAnimation has been deprecated in Clutter 1.12. You should use + * the [implicit animation API][clutter-actor-animation] available inside + * #ClutterActor instead. If you require to define explicit transitions for + * one or more properties in order to reuse them, see #ClutterTransition + * instead. + * + * ## Defining ClutterAnimationMode inside ClutterScript + * + * When defining a #ClutterAnimation inside a ClutterScript + * file or string the #ClutterAnimation:mode can be defined either + * using the #ClutterAnimationMode enumeration values through their + * "nick" (the short string used inside #GEnumValue), their numeric + * id, or using the following strings: + * + * - easeInQuad, easeOutQuad, easeInOutQuad + * - easeInCubic, easeOutCubic, easeInOutCubic + * - easeInQuart, easeOutQuart, easeInOutQuart + * - easeInQuint, easeOutQuint, easeInOutQuint + * - easeInSine, easeOutSine, easeInOutSine + * - easeInExpo, easeOutExpo, easeInOutExpo + * - easeInCirc, easeOutCirc, easeInOutCirc + * - easeInElastic, easeOutElastic, easeInOutElastic + * - easeInBack, easeOutBack, easeInOutBack + * - easeInBounce, easeOutBounce, easeInOutBounce + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS + +#include "clutter-alpha.h" +#include "clutter-animatable.h" +#include "clutter-animation.h" +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-interval.h" +#include "clutter-marshal.h" +#include "clutter-private.h" +#include "clutter-scriptable.h" +#include "clutter-script-private.h" + +#include "deprecated/clutter-animation.h" + +enum +{ + PROP_0, + + PROP_OBJECT, + PROP_MODE, + PROP_DURATION, + PROP_LOOP, + PROP_TIMELINE, + PROP_ALPHA, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +enum +{ + STARTED, + COMPLETED, + + LAST_SIGNAL +}; + +struct _ClutterAnimationPrivate +{ + GObject *object; + + GHashTable *properties; + + ClutterAlpha *alpha; + ClutterTimeline *timeline; + + guint timeline_started_id; + guint timeline_completed_id; + guint timeline_frame_id; +}; + +static guint animation_signals[LAST_SIGNAL] = { 0, }; + +static GQuark quark_object_animation = 0; + +static void clutter_scriptable_init (ClutterScriptableIface *iface); + +static void clutter_animation_set_alpha_internal (ClutterAnimation *animation, + ClutterAlpha *alpha); +static ClutterAlpha * clutter_animation_get_alpha_internal (ClutterAnimation *animation); +static ClutterTimeline * clutter_animation_get_timeline_internal (ClutterAnimation *animation); + +G_DEFINE_TYPE_WITH_CODE (ClutterAnimation, clutter_animation, G_TYPE_OBJECT, + G_ADD_PRIVATE (ClutterAnimation) + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_SCRIPTABLE, + clutter_scriptable_init)); + +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 = g_object_ref_sink (alpha); + + g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_ALPHA]); + } + + return priv->alpha; +} + +static void +on_actor_destroy (ClutterActor *actor, + ClutterAnimation *animation) +{ + ClutterAnimationPrivate *priv = animation->priv; + GObject *obj = G_OBJECT (actor); + + if (obj == priv->object) + { + g_object_set_qdata (priv->object, quark_object_animation, NULL); + g_signal_handlers_disconnect_by_func (priv->object, + G_CALLBACK (on_actor_destroy), + animation); + g_object_unref (animation); + } +} + +static void +clutter_animation_real_completed (ClutterAnimation *self) +{ + ClutterAnimationPrivate *priv = self->priv; + ClutterAnimatable *animatable = NULL; + ClutterAnimation *animation; + ClutterTimeline *timeline; + ClutterTimelineDirection direction; + gpointer key, value; + GHashTableIter iter; + + timeline = clutter_animation_get_timeline (self); + direction = clutter_timeline_get_direction (timeline); + + if (CLUTTER_IS_ANIMATABLE (priv->object)) + animatable = CLUTTER_ANIMATABLE (priv->object); + + /* explicitly set the final state of the animation */ + CLUTTER_NOTE (ANIMATION, "Set final state on object [%p]", priv->object); + g_hash_table_iter_init (&iter, priv->properties); + while (g_hash_table_iter_next (&iter, &key, &value)) + { + const gchar *p_name = key; + ClutterInterval *interval = value; + GValue *p_value; + + if (direction == CLUTTER_TIMELINE_FORWARD) + p_value = clutter_interval_peek_final_value (interval); + else + p_value = clutter_interval_peek_initial_value (interval); + + if (animatable != NULL) + clutter_animatable_set_final_state (animatable, p_name, p_value); + else + g_object_set_property (priv->object, p_name, p_value); + } + + /* at this point, if this animation was created by clutter_actor_animate() + * and friends, the animation will be attached to the object's data; since + * we want to allow developers to use g_signal_connect_after("completed") + * to concatenate a new animation, we need to remove the animation back + * pointer here, and unref() the animation. FIXME - we might want to + * provide a clutter_animation_attach()/clutter_animation_detach() pair + * to let the user reattach an animation + */ + animation = g_object_get_qdata (priv->object, quark_object_animation); + if (animation == self) + { + CLUTTER_NOTE (ANIMATION, "Unsetting animation for actor [%p]", + priv->object); + + g_object_set_qdata (priv->object, quark_object_animation, NULL); + g_signal_handlers_disconnect_by_func (priv->object, + G_CALLBACK (on_actor_destroy), + animation); + + CLUTTER_NOTE (ANIMATION, "Releasing the reference Animation [%p]", + animation); + g_object_unref (animation); + } +} + +static void +clutter_animation_finalize (GObject *gobject) +{ + ClutterAnimationPrivate *priv = CLUTTER_ANIMATION (gobject)->priv; + + CLUTTER_NOTE (ANIMATION, + "Destroying properties table for Animation [%p]", + gobject); + g_hash_table_destroy (priv->properties); + + G_OBJECT_CLASS (clutter_animation_parent_class)->finalize (gobject); +} + +static void +clutter_animation_dispose (GObject *gobject) +{ + ClutterAnimationPrivate *priv = CLUTTER_ANIMATION (gobject)->priv; + ClutterTimeline *timeline; + + if (priv->alpha != NULL) + timeline = clutter_alpha_get_timeline (priv->alpha); + else + timeline = priv->timeline; + + 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); + + if (timeline != NULL && priv->timeline_frame_id != 0) + g_signal_handler_disconnect (timeline, priv->timeline_frame_id); + + priv->timeline_started_id = 0; + priv->timeline_completed_id = 0; + priv->timeline_frame_id = 0; + + if (priv->timeline != NULL) + { + g_object_unref (priv->timeline); + priv->timeline = NULL; + } + + if (priv->alpha != NULL) + { + g_object_unref (priv->alpha); + priv->alpha = NULL; + } + + if (priv->object != NULL) + { + g_object_unref (priv->object); + priv->object = NULL; + } + + G_OBJECT_CLASS (clutter_animation_parent_class)->dispose (gobject); +} + +static void +clutter_animation_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterAnimation *animation = CLUTTER_ANIMATION (gobject); + + switch (prop_id) + { + case PROP_OBJECT: + clutter_animation_set_object (animation, g_value_get_object (value)); + break; + + case PROP_MODE: + clutter_animation_set_mode (animation, g_value_get_ulong (value)); + break; + + case PROP_DURATION: + clutter_animation_set_duration (animation, g_value_get_uint (value)); + break; + + case PROP_LOOP: + clutter_animation_set_loop (animation, g_value_get_boolean (value)); + break; + + case PROP_TIMELINE: + clutter_animation_set_timeline (animation, g_value_get_object (value)); + break; + + case PROP_ALPHA: + clutter_animation_set_alpha_internal (animation, g_value_get_object (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_animation_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterAnimation *animation = CLUTTER_ANIMATION (gobject); + ClutterAnimationPrivate *priv = animation->priv; + + switch (prop_id) + { + case PROP_OBJECT: + g_value_set_object (value, priv->object); + break; + + case PROP_MODE: + g_value_set_ulong (value, clutter_animation_get_mode (animation)); + break; + + case PROP_DURATION: + g_value_set_uint (value, clutter_animation_get_duration (animation)); + break; + + case PROP_LOOP: + g_value_set_boolean (value, clutter_animation_get_loop (animation)); + break; + + case PROP_TIMELINE: + g_value_set_object (value, clutter_animation_get_timeline (animation)); + break; + + case PROP_ALPHA: + g_value_set_object (value, clutter_animation_get_alpha_internal (animation)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static gboolean +clutter_animation_parse_custom_node (ClutterScriptable *scriptable, + ClutterScript *script, + GValue *value, + const gchar *name, + JsonNode *node) +{ + if (strncmp (name, "mode", 4) == 0) + { + gulong mode; + + mode = _clutter_script_resolve_animation_mode (node); + + g_value_init (value, G_TYPE_ULONG); + g_value_set_ulong (value, mode); + + return TRUE; + } + + return FALSE; +} + +static void +clutter_scriptable_init (ClutterScriptableIface *iface) +{ + iface->parse_custom_node = clutter_animation_parse_custom_node; +} + +static void +clutter_animation_class_init (ClutterAnimationClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + quark_object_animation = + g_quark_from_static_string ("clutter-actor-animation"); + + klass->completed = clutter_animation_real_completed; + + gobject_class->set_property = clutter_animation_set_property; + gobject_class->get_property = clutter_animation_get_property; + gobject_class->dispose = clutter_animation_dispose; + gobject_class->finalize = clutter_animation_finalize; + + /** + * ClutterAnimation:object: + * + * The #GObject to which the animation applies. + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterPropertyTransition instead + */ + obj_props[PROP_OBJECT] = + g_param_spec_object ("object", + P_("Object"), + P_("Object to which the animation applies"), + G_TYPE_OBJECT, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterAnimation:mode: + * + * The animation mode, either a value from #ClutterAnimationMode + * or a value returned by clutter_alpha_register_func(). The + * default value is %CLUTTER_LINEAR. + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterPropertyTransition instead + */ + obj_props[PROP_MODE] = + g_param_spec_ulong ("mode", + P_("Mode"), + P_("The mode of the animation"), + 0, G_MAXULONG, + CLUTTER_LINEAR, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterAnimation:duration: + * + * The duration of the animation, expressed in milliseconds. + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterPropertyTransition instead + */ + obj_props[PROP_DURATION] = + g_param_spec_uint ("duration", + P_("Duration"), + P_("Duration of the animation, in milliseconds"), + 0, G_MAXUINT, + 0, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterAnimation:loop: + * + * Whether the animation should loop. + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterPropertyTransition instead + */ + obj_props[PROP_LOOP] = + g_param_spec_boolean ("loop", + P_("Loop"), + P_("Whether the animation should loop"), + FALSE, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterAnimation:timeline: + * + * The #ClutterTimeline used by the animation. + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterPropertyTransition instead + */ + obj_props[PROP_TIMELINE] = + g_param_spec_object ("timeline", + P_("Timeline"), + P_("The timeline used by the animation"), + CLUTTER_TYPE_TIMELINE, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterAnimation:alpha: + * + * The #ClutterAlpha used by the animation. + * + * Since: 1.0 + * + * Deprecated: 1.10: Use the #ClutterAnimation:timeline property and + * the #ClutterTimeline:progress-mode property instead. + */ + obj_props[PROP_ALPHA] = + g_param_spec_object ("alpha", + P_("Alpha"), + P_("The alpha used by the animation"), + CLUTTER_TYPE_ALPHA, + CLUTTER_PARAM_READWRITE | G_PARAM_DEPRECATED); + + g_object_class_install_properties (gobject_class, + PROP_LAST, + obj_props); + + /** + * ClutterAnimation::started: + * @animation: the animation that emitted the signal + * + * The ::started signal is emitted once the animation has been + * started + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterPropertyTransition instead + */ + animation_signals[STARTED] = + g_signal_new (I_("started"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterAnimationClass, started), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * ClutterAnimation::completed: + * @animation: the animation that emitted the signal + * + * The ::completed signal is emitted once the animation has + * been completed. + * + * The @animation instance is guaranteed to be valid for the entire + * duration of the signal emission chain. + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterPropertyTransition instead + */ + animation_signals[COMPLETED] = + g_signal_new (I_("completed"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterAnimationClass, completed), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +clutter_animation_init (ClutterAnimation *self) +{ + self->priv = clutter_animation_get_instance_private (self); + + self->priv->properties = + g_hash_table_new_full (g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_object_unref); +} + +static inline void +clutter_animation_bind_property_internal (ClutterAnimation *animation, + const gchar *property_name, + GParamSpec *pspec, + ClutterInterval *interval) +{ + ClutterAnimationPrivate *priv = animation->priv; + + if (!clutter_interval_validate (interval, pspec)) + { + g_warning ("Cannot bind property '%s': the interval is out " + "of bounds", + property_name); + return; + } + + g_hash_table_insert (priv->properties, + g_strdup (property_name), + g_object_ref_sink (interval)); +} + +static inline void +clutter_animation_update_property_internal (ClutterAnimation *animation, + const gchar *property_name, + GParamSpec *pspec, + ClutterInterval *interval) +{ + ClutterAnimationPrivate *priv = animation->priv; + + if (!clutter_interval_validate (interval, pspec)) + { + g_warning ("Cannot bind property '%s': the interval is out " + "of bounds", + property_name); + return; + } + + g_hash_table_replace (priv->properties, + g_strdup (property_name), + g_object_ref_sink (interval)); +} + +static GParamSpec * +clutter_animation_validate_bind (ClutterAnimation *animation, + const char *property_name, + GType argtype) +{ + ClutterAnimationPrivate *priv; + GParamSpec *pspec; + GType pspec_type; + + priv = animation->priv; + + if (G_UNLIKELY (!priv->object)) + { + g_warning ("Cannot bind property '%s': the animation has no " + "object set. You need to call clutter_animation_set_object() " + "first to be able to bind a property", + property_name); + return NULL; + } + + if (G_UNLIKELY (clutter_animation_has_property (animation, property_name))) + { + g_warning ("Cannot bind property '%s': the animation already has " + "a bound property with the same name", + property_name); + return NULL; + } + + if (CLUTTER_IS_ANIMATABLE (priv->object)) + { + ClutterAnimatable *animatable = CLUTTER_ANIMATABLE (priv->object); + + pspec = clutter_animatable_find_property (animatable, property_name); + } + else + { + GObjectClass *klass = G_OBJECT_GET_CLASS (priv->object); + + pspec = g_object_class_find_property (klass, property_name); + } + + if (pspec == NULL) + { + g_warning ("Cannot bind property '%s': objects of type '%s' have " + "no such property", + property_name, + g_type_name (G_OBJECT_TYPE (priv->object))); + return NULL; + } + + if (!(pspec->flags & G_PARAM_WRITABLE)) + { + g_warning ("Cannot bind property '%s': the property is not writable", + property_name); + return NULL; + } + + pspec_type = G_PARAM_SPEC_VALUE_TYPE (pspec); + + if (g_value_type_transformable (argtype, pspec_type)) + return pspec; + else + { + g_warning ("Cannot bind property '%s': the interval value of " + "type '%s' is not compatible with the property value " + "of type '%s'", + property_name, + g_type_name (argtype), + g_type_name (pspec_type)); + return NULL; + } +} + +/** + * clutter_animation_bind_interval: + * @animation: a #ClutterAnimation + * @property_name: the property to control + * @interval: (transfer full): a #ClutterInterval + * + * Binds @interval to the @property_name of the #GObject + * attached to @animation. The #ClutterAnimation will take + * ownership of the passed #ClutterInterval. For more information + * about animations, see clutter_actor_animate(). + * + * If you need to update the interval instance use + * clutter_animation_update_interval() instead. + * + * Return value: (transfer none): The animation itself. + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterPropertyTransition instead + */ +ClutterAnimation * +clutter_animation_bind_interval (ClutterAnimation *animation, + const gchar *property_name, + ClutterInterval *interval) +{ + GParamSpec *pspec; + + g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), NULL); + g_return_val_if_fail (property_name != NULL, NULL); + g_return_val_if_fail (CLUTTER_IS_INTERVAL (interval), NULL); + + pspec = clutter_animation_validate_bind (animation, property_name, + clutter_interval_get_value_type (interval)); + if (pspec == NULL) + return NULL; + + clutter_animation_bind_property_internal (animation, property_name, + pspec, + interval); + + return animation; +} + + +/** + * clutter_animation_bind: + * @animation: a #ClutterAnimation + * @property_name: the property to control + * @final: The final value of the property + * + * Adds a single property with name @property_name to the + * animation @animation. For more information about animations, + * see clutter_actor_animate(). + * + * This method returns the animation primarily to make chained + * calls convenient in language bindings. + * + * Return value: (transfer none): The animation itself. + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterPropertyTransition instead + */ +ClutterAnimation * +clutter_animation_bind (ClutterAnimation *animation, + const gchar *property_name, + const GValue *final) +{ + ClutterAnimationPrivate *priv; + GParamSpec *pspec; + ClutterInterval *interval; + GType type; + GValue initial = G_VALUE_INIT; + GValue real_final = G_VALUE_INIT; + + g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), NULL); + g_return_val_if_fail (property_name != NULL, NULL); + + priv = animation->priv; + + type = G_VALUE_TYPE (final); + pspec = clutter_animation_validate_bind (animation, property_name, type); + if (pspec == NULL) + return NULL; + + g_value_init (&real_final, G_PARAM_SPEC_VALUE_TYPE (pspec)); + if (!g_value_transform (final, &real_final)) + { + g_value_unset (&real_final); + g_warning ("Unable to transform the value of type '%s' to a value " + "of '%s' compatible with the property '%s'of the object " + "of type '%s'", + g_type_name (type), + g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)), + property_name, + G_OBJECT_TYPE_NAME (priv->object)); + return NULL; + } + + g_value_init (&initial, G_PARAM_SPEC_VALUE_TYPE (pspec)); + + if (CLUTTER_IS_ANIMATABLE (priv->object)) + clutter_animatable_get_initial_state (CLUTTER_ANIMATABLE (priv->object), + property_name, + &initial); + else + g_object_get_property (priv->object, property_name, &initial); + + interval = clutter_interval_new_with_values (G_PARAM_SPEC_VALUE_TYPE (pspec), + &initial, + &real_final); + + g_value_unset (&initial); + g_value_unset (&real_final); + + clutter_animation_bind_property_internal (animation, property_name, + pspec, + interval); + + return animation; +} + + +/** + * clutter_animation_unbind_property: + * @animation: a #ClutterAnimation + * @property_name: name of the property + * + * Removes @property_name from the list of animated properties. + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterPropertyTransition instead + */ +void +clutter_animation_unbind_property (ClutterAnimation *animation, + const gchar *property_name) +{ + ClutterAnimationPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ANIMATION (animation)); + g_return_if_fail (property_name != NULL); + + priv = animation->priv; + + if (!clutter_animation_has_property (animation, property_name)) + { + g_warning ("Cannot unbind property '%s': the animation has " + "no bound property with that name", + property_name); + return; + } + + g_hash_table_remove (priv->properties, property_name); +} + +/** + * clutter_animation_has_property: + * @animation: a #ClutterAnimation + * @property_name: name of the property + * + * Checks whether @animation is controlling @property_name. + * + * Return value: %TRUE if the property is animated by the + * #ClutterAnimation, %FALSE otherwise + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterPropertyTransition instead + */ +gboolean +clutter_animation_has_property (ClutterAnimation *animation, + const gchar *property_name) +{ + ClutterAnimationPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), FALSE); + g_return_val_if_fail (property_name != NULL, FALSE); + + priv = animation->priv; + + return g_hash_table_lookup (priv->properties, property_name) != NULL; +} + +/** + * clutter_animation_update_interval: + * @animation: a #ClutterAnimation + * @property_name: name of the property + * @interval: a #ClutterInterval + * + * Changes the @interval for @property_name. The #ClutterAnimation + * will take ownership of the passed #ClutterInterval. + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterPropertyTransition instead + */ +void +clutter_animation_update_interval (ClutterAnimation *animation, + const gchar *property_name, + ClutterInterval *interval) +{ + ClutterAnimationPrivate *priv; + GParamSpec *pspec; + GType pspec_type, int_type; + + g_return_if_fail (CLUTTER_IS_ANIMATION (animation)); + g_return_if_fail (property_name != NULL); + g_return_if_fail (CLUTTER_IS_INTERVAL (interval)); + + priv = animation->priv; + + if (!clutter_animation_has_property (animation, property_name)) + { + g_warning ("Cannot update property '%s': the animation has " + "no bound property with that name", + property_name); + return; + } + + if (CLUTTER_IS_ANIMATABLE (priv->object)) + { + ClutterAnimatable *animatable = CLUTTER_ANIMATABLE (priv->object); + + pspec = clutter_animatable_find_property (animatable, property_name); + } + else + { + GObjectClass *klass = G_OBJECT_GET_CLASS (priv->object); + + pspec = g_object_class_find_property (klass, property_name); + } + + if (pspec == NULL) + { + g_warning ("Cannot update property '%s': objects of type '%s' have " + "no such property", + property_name, + g_type_name (G_OBJECT_TYPE (priv->object))); + return; + } + + pspec_type = G_PARAM_SPEC_VALUE_TYPE (pspec); + int_type = clutter_interval_get_value_type (interval); + + if (!g_value_type_compatible (int_type, pspec_type) || + !g_value_type_transformable (int_type, pspec_type)) + { + g_warning ("Cannot update property '%s': the interval value of " + "type '%s' is not compatible with the property value " + "of type '%s'", + property_name, + g_type_name (int_type), + g_type_name (pspec_type)); + return; + } + + clutter_animation_update_property_internal (animation, property_name, + pspec, + interval); +} + +/** + * clutter_animation_update: + * @animation: a #ClutterAnimation + * @property_name: name of the property + * @final: The final value of the property + * + * Updates the @final value of the interval for @property_name + * + * Return value: (transfer none): The animation itself. + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterPropertyTransition instead + */ +ClutterAnimation * +clutter_animation_update (ClutterAnimation *animation, + const gchar *property_name, + const GValue *final) +{ + ClutterInterval *interval; + GType int_type; + + g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), NULL); + g_return_val_if_fail (property_name != NULL, NULL); + g_return_val_if_fail (final != NULL, NULL); + g_return_val_if_fail (G_VALUE_TYPE (final) != G_TYPE_INVALID, NULL); + + interval = clutter_animation_get_interval (animation, property_name); + if (interval == NULL) + { + g_warning ("Cannot update property '%s': the animation has " + "no bound property with that name", + property_name); + return NULL; + } + + int_type = clutter_interval_get_value_type (interval); + + if (!g_value_type_compatible (G_VALUE_TYPE (final), int_type) || + !g_value_type_transformable (G_VALUE_TYPE (final), int_type)) + { + g_warning ("Cannot update property '%s': the interval value of " + "type '%s' is not compatible with the property value " + "of type '%s'", + property_name, + g_type_name (int_type), + g_type_name (G_VALUE_TYPE (final))); + return NULL; + } + + clutter_interval_set_final_value (interval, final); + + return animation; +} + +/** + * clutter_animation_get_interval: + * @animation: a #ClutterAnimation + * @property_name: name of the property + * + * Retrieves the #ClutterInterval associated to @property_name + * inside @animation. + * + * Return value: (transfer none): a #ClutterInterval or %NULL if no + * property with the same name was found. The returned interval is + * owned by the #ClutterAnimation and should not be unreferenced + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterPropertyTransition instead + */ +ClutterInterval * +clutter_animation_get_interval (ClutterAnimation *animation, + const gchar *property_name) +{ + ClutterAnimationPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), NULL); + g_return_val_if_fail (property_name != NULL, NULL); + + priv = animation->priv; + + return g_hash_table_lookup (priv->properties, property_name); +} + +static void +on_timeline_started (ClutterTimeline *timeline, + ClutterAnimation *animation) +{ + g_signal_emit (animation, animation_signals[STARTED], 0); +} + +static void +on_timeline_completed (ClutterTimeline *timeline, + ClutterAnimation *animation) +{ + CLUTTER_NOTE (ANIMATION, "Timeline [%p] complete", timeline); + + if (!clutter_animation_get_loop (animation)) + g_signal_emit (animation, animation_signals[COMPLETED], 0); +} + +static void +on_timeline_frame (ClutterTimeline *timeline, + gint elapsed, + ClutterAnimation *animation) +{ + ClutterAnimationPrivate *priv; + GList *properties, *p; + gdouble alpha_value; + gboolean is_animatable = FALSE; + ClutterAnimatable *animatable = NULL; + + /* make sure the animation survives the notification */ + g_object_ref (animation); + + priv = animation->priv; + + if (priv->alpha != NULL) + alpha_value = clutter_alpha_get_alpha (priv->alpha); + else + alpha_value = clutter_timeline_get_progress (priv->timeline); + + if (CLUTTER_IS_ANIMATABLE (priv->object)) + { + animatable = CLUTTER_ANIMATABLE (priv->object); + is_animatable = TRUE; + } + + g_object_freeze_notify (priv->object); + + properties = g_hash_table_get_keys (priv->properties); + for (p = properties; p != NULL; p = p->next) + { + const gchar *p_name = p->data; + ClutterInterval *interval; + GValue value = G_VALUE_INIT; + gboolean apply; + + interval = g_hash_table_lookup (priv->properties, p_name); + g_assert (CLUTTER_IS_INTERVAL (interval)); + + g_value_init (&value, clutter_interval_get_value_type (interval)); + + if (is_animatable) + { + apply = clutter_animatable_interpolate_value (animatable, p_name, + interval, + alpha_value, + &value); + } + else + { + apply = clutter_interval_compute_value (interval, + alpha_value, + &value); + } + + if (apply) + { + if (is_animatable) + clutter_animatable_set_final_state (animatable, p_name, &value); + else + g_object_set_property (priv->object, p_name, &value); + } + + g_value_unset (&value); + } + + g_list_free (properties); + + g_object_thaw_notify (priv->object); + + g_object_unref (animation); +} + +static ClutterTimeline * +clutter_animation_get_timeline_internal (ClutterAnimation *animation) +{ + ClutterAnimationPrivate *priv = animation->priv; + ClutterTimeline *timeline; + + if (priv->timeline != NULL) + return priv->timeline; + + if (priv->alpha != NULL) + { + timeline = clutter_alpha_get_timeline (priv->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); + + priv->timeline_frame_id = + g_signal_connect (timeline, "new-frame", + G_CALLBACK (on_timeline_frame), + animation); + + if (priv->alpha != NULL) + { + clutter_alpha_set_timeline (priv->alpha, timeline); + + /* the alpha owns the timeline now */ + g_object_unref (timeline); + } + + priv->timeline = timeline; + + g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_TIMELINE]); + + return priv->timeline; +} + +static void +clutter_animation_set_alpha_internal (ClutterAnimation *animation, + ClutterAlpha *alpha) +{ + ClutterAnimationPrivate *priv; + ClutterTimeline *timeline; + + priv = animation->priv; + + 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) + { + g_signal_handler_disconnect (timeline, priv->timeline_started_id); + priv->timeline_started_id = 0; + } + + if (timeline != NULL && priv->timeline_completed_id != 0) + { + g_signal_handler_disconnect (timeline, priv->timeline_completed_id); + priv->timeline_completed_id = 0; + } + + /* then we need to disconnect the signal handler from the old alpha */ + if (timeline != NULL && priv->timeline_frame_id != 0) + { + g_signal_handler_disconnect (timeline, priv->timeline_frame_id); + priv->timeline_frame_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; + } + + if (alpha == NULL) + goto out; + + priv->alpha = g_object_ref_sink (alpha); + + /* 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); + priv->timeline_frame_id = + g_signal_connect (timeline, "new-frame", + G_CALLBACK (on_timeline_frame), + animation); + } + else + { + /* FIXME - add a create_timeline_internal() because this does + * not look very good + */ + (void) clutter_animation_get_timeline_internal (animation); + } + +out: + /* emit all relevant notifications */ + g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_MODE]); + g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_DURATION]); + g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_LOOP]); + g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_ALPHA]); + g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_TIMELINE]); + + g_object_thaw_notify (G_OBJECT (animation)); +} + +/** + * clutter_animation_new: + * + * Creates a new #ClutterAnimation instance. You should set the + * #GObject to be animated using clutter_animation_set_object(), + * set the duration with clutter_animation_set_duration() and the + * easing mode using clutter_animation_set_mode(). + * + * Use clutter_animation_bind() or clutter_animation_bind_interval() + * to define the properties to be animated. The interval and the + * animated properties can be updated at runtime. + * + * The clutter_actor_animate() and relative family of functions provide + * an easy way to animate a #ClutterActor and automatically manage the + * lifetime of a #ClutterAnimation instance, so you should consider using + * those functions instead of manually creating an animation. + * + * Return value: the newly created #ClutterAnimation. Use g_object_unref() + * to release the associated resources + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterPropertyTransition instead + */ +ClutterAnimation * +clutter_animation_new (void) +{ + return g_object_new (CLUTTER_TYPE_ANIMATION, NULL); +} + +/** + * clutter_animation_set_object: + * @animation: a #ClutterAnimation + * @object: a #GObject + * + * Attaches @animation to @object. The #ClutterAnimation will take a + * reference on @object. + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterPropertyTransition instead + */ +void +clutter_animation_set_object (ClutterAnimation *animation, + GObject *object) +{ + ClutterAnimationPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ANIMATION (animation)); + g_return_if_fail (object == NULL || G_IS_OBJECT (object)); + + priv = animation->priv; + + if (priv->object != NULL) + { + g_object_set_qdata (priv->object, quark_object_animation, NULL); + + g_object_unref (priv->object); + priv->object = NULL; + } + + if (object != NULL) + priv->object = g_object_ref (object); + + g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_OBJECT]); +} + +/** + * clutter_animation_get_object: + * @animation: a #ClutterAnimation + * + * Retrieves the #GObject attached to @animation. + * + * Return value: (transfer none): a #GObject + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterPropertyTransition instead + */ +GObject * +clutter_animation_get_object (ClutterAnimation *animation) +{ + g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), NULL); + + return animation->priv->object; +} + +/** + * clutter_animation_set_mode: + * @animation: a #ClutterAnimation + * @mode: an animation mode logical id + * + * Sets the animation @mode of @animation. The animation @mode is + * 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 + * Deprecated: 1.12: Use #ClutterPropertyTransition instead + */ +void +clutter_animation_set_mode (ClutterAnimation *animation, + gulong mode) +{ + g_return_if_fail (CLUTTER_IS_ANIMATION (animation)); + + g_object_freeze_notify (G_OBJECT (animation)); + + if (animation->priv->alpha != NULL || mode > CLUTTER_ANIMATION_LAST) + { + ClutterAlpha *alpha; + + if (animation->priv->alpha == NULL) + alpha = clutter_animation_get_alpha_internal (animation); + else + alpha = animation->priv->alpha; + + clutter_alpha_set_mode (alpha, mode); + } + else + { + ClutterTimeline *timeline; + + timeline = clutter_animation_get_timeline_internal (animation); + + clutter_timeline_set_progress_mode (timeline, mode); + } + + g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_MODE]); + + g_object_thaw_notify (G_OBJECT (animation)); +} + +/** + * clutter_animation_get_mode: + * @animation: a #ClutterAnimation + * + * Retrieves the animation mode of @animation, as set by + * clutter_animation_set_mode(). + * + * Return value: the mode for the animation + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterPropertyTransition instead + */ +gulong +clutter_animation_get_mode (ClutterAnimation *animation) +{ + ClutterTimeline *timeline; + + g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), CLUTTER_LINEAR); + + if (animation->priv->alpha != NULL) + return clutter_alpha_get_mode (animation->priv->alpha); + + timeline = clutter_animation_get_timeline_internal (animation); + + return clutter_timeline_get_progress_mode (timeline); +} + +/** + * clutter_animation_set_duration: + * @animation: a #ClutterAnimation + * @msecs: the duration in milliseconds + * + * Sets the duration of @animation in milliseconds. + * + * This function will set #ClutterAnimation:alpha and + * #ClutterAnimation:timeline if needed. + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterPropertyTransition instead + */ +void +clutter_animation_set_duration (ClutterAnimation *animation, + guint msecs) +{ + ClutterTimeline *timeline; + + g_return_if_fail (CLUTTER_IS_ANIMATION (animation)); + + g_object_freeze_notify (G_OBJECT (animation)); + + timeline = clutter_animation_get_timeline_internal (animation); + clutter_timeline_set_duration (timeline, msecs); + clutter_timeline_rewind (timeline); + + g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_DURATION]); + + g_object_thaw_notify (G_OBJECT (animation)); +} + +/** + * clutter_animation_set_loop: + * @animation: a #ClutterAnimation + * @loop: %TRUE if the animation should loop + * + * Sets whether @animation should loop over itself once finished. + * + * 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 + * Deprecated: 1.12: Use #ClutterPropertyTransition instead + */ +void +clutter_animation_set_loop (ClutterAnimation *animation, + gboolean loop) +{ + ClutterTimeline *timeline; + + g_return_if_fail (CLUTTER_IS_ANIMATION (animation)); + + g_object_freeze_notify (G_OBJECT (animation)); + + timeline = clutter_animation_get_timeline_internal (animation); + clutter_timeline_set_repeat_count (timeline, loop ? -1 : 0); + + g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_LOOP]); + + g_object_thaw_notify (G_OBJECT (animation)); +} + +/** + * clutter_animation_get_loop: + * @animation: a #ClutterAnimation + * + * Retrieves whether @animation is looping. + * + * Return value: %TRUE if the animation is looping + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterPropertyTransition instead + */ +gboolean +clutter_animation_get_loop (ClutterAnimation *animation) +{ + ClutterTimeline *timeline; + + g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), FALSE); + + timeline = clutter_animation_get_timeline_internal (animation); + + return clutter_timeline_get_repeat_count (timeline) != 0; +} + +/** + * clutter_animation_get_duration: + * @animation: a #ClutterAnimation + * + * Retrieves the duration of @animation, in milliseconds. + * + * Return value: the duration of the animation + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterPropertyTransition instead + */ +guint +clutter_animation_get_duration (ClutterAnimation *animation) +{ + ClutterTimeline *timeline; + + g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), 0); + + timeline = clutter_animation_get_timeline_internal (animation); + + return clutter_timeline_get_duration (timeline); +} + +/** + * clutter_animation_set_timeline: + * @animation: a #ClutterAnimation + * @timeline: (allow-none): a #ClutterTimeline, or %NULL to unset the + * current #ClutterTimeline + * + * Sets the #ClutterTimeline used by @animation. + * + * This function will take a reference on the passed @timeline. + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterPropertyTransition instead + */ +void +clutter_animation_set_timeline (ClutterAnimation *animation, + ClutterTimeline *timeline) +{ + ClutterAnimationPrivate *priv; + ClutterTimeline *cur_timeline; + + g_return_if_fail (CLUTTER_IS_ANIMATION (animation)); + g_return_if_fail (timeline == NULL || CLUTTER_IS_TIMELINE (timeline)); + + priv = animation->priv; + + if (priv->alpha != NULL) + cur_timeline = clutter_alpha_get_timeline (priv->alpha); + else + cur_timeline = priv->timeline; + + if (cur_timeline == timeline) + return; + + g_object_freeze_notify (G_OBJECT (animation)); + + if (cur_timeline != NULL && priv->timeline_started_id != 0) + g_signal_handler_disconnect (cur_timeline, priv->timeline_started_id); + + if (cur_timeline != NULL && priv->timeline_completed_id != 0) + g_signal_handler_disconnect (cur_timeline, priv->timeline_completed_id); + + if (cur_timeline != NULL && priv->timeline_frame_id != 0) + g_signal_handler_disconnect (cur_timeline, priv->timeline_frame_id); + + priv->timeline_started_id = 0; + priv->timeline_completed_id = 0; + priv->timeline_frame_id = 0; + + /* Release previously set timeline if any */ + g_clear_object (&priv->timeline); + + if (priv->alpha != NULL) + clutter_alpha_set_timeline (priv->alpha, timeline); + else + { + /* Hold a reference to the timeline if it's not reffed by the priv->alpha */ + priv->timeline = timeline; + + if (priv->timeline) + g_object_ref (priv->timeline); + } + + g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_TIMELINE]); + g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_DURATION]); + g_object_notify_by_pspec (G_OBJECT (animation), obj_props[PROP_LOOP]); + + 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); + priv->timeline_frame_id = + g_signal_connect (timeline, "new-frame", + G_CALLBACK (on_timeline_frame), + animation); + } + + g_object_thaw_notify (G_OBJECT (animation)); +} + +/** + * clutter_animation_get_timeline: + * @animation: a #ClutterAnimation + * + * Retrieves the #ClutterTimeline used by @animation + * + * Return value: (transfer none): the timeline used by the animation + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterPropertyTransition instead + */ +ClutterTimeline * +clutter_animation_get_timeline (ClutterAnimation *animation) +{ + g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), NULL); + + return clutter_animation_get_timeline_internal (animation); +} + +/** + * clutter_animation_set_alpha: + * @animation: a #ClutterAnimation + * @alpha: a #ClutterAlpha, or %NULL to unset the current #ClutterAlpha + * + * Sets @alpha as the #ClutterAlpha used by @animation. + * + * If @alpha is not %NULL, the #ClutterAnimation will take ownership + * of the #ClutterAlpha instance. + * + * Since: 1.0 + * + * Deprecated: 1.10: Use clutter_animation_get_timeline() and + * clutter_timeline_set_progress_mode() instead. + */ +void +clutter_animation_set_alpha (ClutterAnimation *animation, + ClutterAlpha *alpha) +{ + g_return_if_fail (CLUTTER_IS_ANIMATION (animation)); + g_return_if_fail (alpha == NULL || CLUTTER_IS_ALPHA (alpha)); + + clutter_animation_set_alpha_internal (animation, alpha); +} + +/** + * clutter_animation_get_alpha: + * @animation: a #ClutterAnimation + * + * Retrieves the #ClutterAlpha used by @animation. + * + * Return value: (transfer none): the alpha object used by the animation + * + * Since: 1.0 + * + * Deprecated: 1.10: Use clutter_animation_get_timeline() and + * clutter_timeline_get_progress_mode() instead. + */ +ClutterAlpha * +clutter_animation_get_alpha (ClutterAnimation *animation) +{ + g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), NULL); + + return clutter_animation_get_alpha_internal (animation); +} + +/** + * clutter_animation_completed: + * @animation: a #ClutterAnimation + * + * Emits the ::completed signal on @animation + * + * When using this function with a #ClutterAnimation created + * by the clutter_actor_animate() family of functions, @animation + * will be unreferenced and it will not be valid anymore, + * unless g_object_ref() was called before calling this function + * or unless a reference was taken inside a handler for the + * #ClutterAnimation::completed signal + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterPropertyTransition instead + */ +void +clutter_animation_completed (ClutterAnimation *animation) +{ + g_return_if_fail (CLUTTER_IS_ANIMATION (animation)); + + g_signal_emit (animation, animation_signals[COMPLETED], 0); +} + +/* + * starts the timeline + */ +static void +clutter_animation_start (ClutterAnimation *animation) +{ + ClutterTimeline *timeline; + + timeline = clutter_animation_get_timeline_internal (animation); + + if (G_LIKELY (timeline != NULL)) + clutter_timeline_start (timeline); + else + { + /* sanity check */ + g_warning (G_STRLOC ": no timeline found, unable to start the animation"); + } +} + +static void +clutter_animation_setup_property (ClutterAnimation *animation, + const gchar *property_name, + const GValue *value, + GParamSpec *pspec, + gboolean is_fixed) +{ + ClutterAnimationPrivate *priv = animation->priv; + GValue real_value = G_VALUE_INIT; + + if (pspec->flags & G_PARAM_CONSTRUCT_ONLY) + { + g_warning ("Cannot bind property '%s': the property is " + "construct-only", + property_name); + return; + } + + if (!(pspec->flags & G_PARAM_WRITABLE)) + { + g_warning ("Cannot bind property '%s': the property is " + "not writable", + property_name); + return; + } + + /* initialize the real value that will be used to store the + * final state of the animation + */ + g_value_init (&real_value, G_PARAM_SPEC_VALUE_TYPE (pspec)); + + /* if it's not the same type of the GParamSpec value, try to + * convert it using the GValue transformation API, otherwise + * just copy it + */ + if (!g_type_is_a (G_VALUE_TYPE (value), G_VALUE_TYPE (&real_value))) + { + /* are these two types compatible (can be directly copied)? */ + if (g_value_type_compatible (G_VALUE_TYPE (value), + G_VALUE_TYPE (&real_value))) + { + g_value_copy (value, &real_value); + goto done; + } + + /* are these two type transformable? */ + if (g_value_type_transformable (G_VALUE_TYPE (value), + G_VALUE_TYPE (&real_value))) + { + if (g_value_transform (value, &real_value)) + goto done; + } + + /* if not compatible and not transformable then we can't do much */ + g_warning ("%s: Unable to convert from %s to %s for " + "the property '%s' of object %s", + G_STRLOC, + g_type_name (G_VALUE_TYPE (value)), + g_type_name (G_VALUE_TYPE (&real_value)), + property_name, + G_OBJECT_TYPE_NAME (priv->object)); + g_value_unset (&real_value); + return; + } + else + g_value_copy (value, &real_value); + +done: + /* create an interval and bind it to the property, in case + * it's not a fixed property, otherwise just set it + */ + if (G_LIKELY (!is_fixed)) + { + ClutterInterval *interval; + GValue cur_value = G_VALUE_INIT; + + g_value_init (&cur_value, G_PARAM_SPEC_VALUE_TYPE (pspec)); + + if (CLUTTER_IS_ANIMATABLE (priv->object)) + clutter_animatable_get_initial_state (CLUTTER_ANIMATABLE (priv->object), + property_name, + &cur_value); + else + g_object_get_property (priv->object, property_name, &cur_value); + + interval = + clutter_interval_new_with_values (G_PARAM_SPEC_VALUE_TYPE (pspec), + &cur_value, + &real_value); + + if (!clutter_animation_has_property (animation, property_name)) + clutter_animation_bind_property_internal (animation, property_name, + pspec, + interval); + else + clutter_animation_update_property_internal (animation, property_name, + pspec, + interval); + + g_value_unset (&cur_value); + } + else + { + if (CLUTTER_IS_ANIMATABLE (priv->object)) + clutter_animatable_set_final_state (CLUTTER_ANIMATABLE (priv->object), + property_name, + &real_value); + else + g_object_set_property (priv->object, property_name, &real_value); + } + + g_value_unset (&real_value); +} + +static void +clutter_animation_setupv (ClutterAnimation *animation, + gint n_properties, + const gchar * const properties[], + const GValue *values) +{ + ClutterAnimationPrivate *priv = animation->priv; + ClutterAnimatable *animatable = NULL; + GObjectClass *klass = NULL; + gint i; + + if (CLUTTER_IS_ANIMATABLE (priv->object)) + animatable = CLUTTER_ANIMATABLE (priv->object); + else + klass = G_OBJECT_GET_CLASS (priv->object); + + for (i = 0; i < n_properties; i++) + { + const gchar *property_name = properties[i]; + GParamSpec *pspec; + gboolean is_fixed = FALSE; + + if (g_str_has_prefix (property_name, "fixed::")) + { + property_name += 7; /* strlen("fixed::") */ + is_fixed = TRUE; + } + + if (animatable != NULL) + pspec = clutter_animatable_find_property (animatable, property_name); + else + pspec = g_object_class_find_property (klass, property_name); + + if (pspec == NULL) + { + g_warning ("Cannot bind property '%s': objects of type '%s' do " + "not have this property", + property_name, + g_type_name (G_OBJECT_TYPE (priv->object))); + break; + } + + clutter_animation_setup_property (animation, property_name, + &values[i], + pspec, + is_fixed); + } +} + +static const struct +{ + const gchar *name; + GConnectFlags flags; +} signal_prefixes[] = + { + { "::", 0 }, + { "-swapped::", G_CONNECT_SWAPPED }, + { "-after::", G_CONNECT_AFTER }, + { "-swapped-after::", G_CONNECT_SWAPPED | G_CONNECT_AFTER } + }; + +static gboolean +clutter_animation_has_signal_prefix (const gchar *property_name, + GConnectFlags *flags, + int *offset) +{ + int i; + + if (!g_str_has_prefix (property_name, "signal")) + return FALSE; + + for (i = 0; i < G_N_ELEMENTS (signal_prefixes); i++) + if (g_str_has_prefix (property_name + 6, signal_prefixes[i].name)) + { + *offset = strlen (signal_prefixes[i].name) + 6; + *flags = signal_prefixes[i].flags; + return TRUE; + } + + return FALSE; +} + +static void +clutter_animation_setup_valist (ClutterAnimation *animation, + const gchar *first_property_name, + va_list var_args) +{ + ClutterAnimationPrivate *priv = animation->priv; + ClutterAnimatable *animatable = NULL; + GObjectClass *klass = NULL; + const gchar *property_name; + + if (CLUTTER_IS_ANIMATABLE (priv->object)) + animatable = CLUTTER_ANIMATABLE (priv->object); + else + klass = G_OBJECT_GET_CLASS (priv->object); + + property_name = first_property_name; + while (property_name != NULL) + { + GParamSpec *pspec; + GValue final = G_VALUE_INIT; + gchar *error = NULL; + gboolean is_fixed = FALSE; + GConnectFlags flags; + int offset; + + if (clutter_animation_has_signal_prefix (property_name, + &flags, + &offset)) + { + const gchar *signal_name = property_name + offset; + GCallback callback = va_arg (var_args, GCallback); + gpointer userdata = va_arg (var_args, gpointer); + + g_signal_connect_data (animation, signal_name, + callback, userdata, + NULL, flags); + } + else + { + if (g_str_has_prefix (property_name, "fixed::")) + { + property_name += 7; /* strlen("fixed::") */ + is_fixed = TRUE; + } + + if (animatable != NULL) + pspec = clutter_animatable_find_property (animatable, + property_name); + else + pspec = g_object_class_find_property (klass, property_name); + + if (pspec == NULL) + { + g_warning ("Cannot bind property '%s': objects of type '%s' do " + "not have this property", + property_name, + g_type_name (G_OBJECT_TYPE (priv->object))); + break; + } + + G_VALUE_COLLECT_INIT (&final, G_PARAM_SPEC_VALUE_TYPE (pspec), + var_args, 0, + &error); + + if (error) + { + g_warning ("%s: %s", G_STRLOC, error); + g_free (error); + break; + } + + clutter_animation_setup_property (animation, property_name, + &final, + pspec, + is_fixed); + + + g_value_unset (&final); + } + + property_name = va_arg (var_args, gchar*); + } +} + +static ClutterAnimation * +animation_create_for_actor (ClutterActor *actor) +{ + ClutterAnimation *animation; + GObject *object = G_OBJECT (actor); + + animation = g_object_get_qdata (object, quark_object_animation); + if (animation == NULL) + { + animation = clutter_animation_new (); + clutter_animation_set_object (animation, object); + g_object_set_qdata (object, quark_object_animation, animation); + + /* use the ::destroy signal to get a notification + * that the actor went away mid-animation + */ + g_signal_connect (object, "destroy", + G_CALLBACK (on_actor_destroy), + animation); + + CLUTTER_NOTE (ANIMATION, + "Created new Animation [%p] for actor [%p]", + animation, + actor); + } + else + { + CLUTTER_NOTE (ANIMATION, + "Reusing Animation [%p] for actor [%p]", + animation, + actor); + } + + return animation; +} + +/** + * clutter_actor_animate_with_alpha: + * @actor: a #ClutterActor + * @alpha: a #ClutterAlpha + * @first_property_name: the name of a property + * @...: a %NULL terminated list of property names and + * property values + * + * Animates the given list of properties of @actor between the current + * value for each property and a new final value. The animation has a + * definite behaviour given by the passed @alpha. + * + * See clutter_actor_animate() for further details. + * + * This function is useful if you want to use an existing #ClutterAlpha + * to animate @actor. + * + * Return value: (transfer none): a #ClutterAnimation object. The object is owned by the + * #ClutterActor and should not be unreferenced with g_object_unref() + * + * Since: 1.0 + * + * Deprecated: 1.10: Use the implicit transition for animatable properties + * in #ClutterActor instead. See clutter_actor_save_easing_state(), + * clutter_actor_set_easing_mode(), clutter_actor_set_easing_duration(), + * clutter_actor_set_easing_delay(), and clutter_actor_restore_easing_state(). + */ +ClutterAnimation * +clutter_actor_animate_with_alpha (ClutterActor *actor, + ClutterAlpha *alpha, + const gchar *first_property_name, + ...) +{ + ClutterAnimation *animation; + ClutterTimeline *timeline; + va_list args; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), NULL); + g_return_val_if_fail (CLUTTER_IS_ALPHA (alpha), NULL); + g_return_val_if_fail (first_property_name != NULL, NULL); + + timeline = clutter_alpha_get_timeline (alpha); + if (timeline == NULL) + { + g_warning ("The passed ClutterAlpha does not have an " + "associated ClutterTimeline."); + return NULL; + } + + animation = animation_create_for_actor (actor); + clutter_animation_set_alpha_internal (animation, alpha); + + va_start (args, first_property_name); + clutter_animation_setup_valist (animation, first_property_name, args); + va_end (args); + + clutter_animation_start (animation); + + return animation; +} + +/** + * clutter_actor_animate_with_timeline: + * @actor: a #ClutterActor + * @mode: an animation mode logical id + * @timeline: a #ClutterTimeline + * @first_property_name: the name of a property + * @...: a %NULL terminated list of property names and + * property values + * + * Animates the given list of properties of @actor between the current + * value for each property and a new final value. The animation has a + * definite duration given by @timeline and a speed given by the @mode. + * + * See clutter_actor_animate() for further details. + * + * This function is useful if you want to use an existing timeline + * to animate @actor. + * + * Return value: (transfer none): a #ClutterAnimation object. The object is + * owned by the #ClutterActor and should not be unreferenced with + * g_object_unref() + * + * Since: 1.0 + * Deprecated: 1.12: Use the implicit transition for animatable properties + * in #ClutterActor instead. See clutter_actor_save_easing_state(), + * clutter_actor_set_easing_mode(), clutter_actor_set_easing_duration(), + * clutter_actor_set_easing_delay(), and clutter_actor_restore_easing_state(). + */ +ClutterAnimation * +clutter_actor_animate_with_timeline (ClutterActor *actor, + gulong mode, + ClutterTimeline *timeline, + const gchar *first_property_name, + ...) +{ + ClutterAnimation *animation; + va_list args; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), NULL); + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), NULL); + g_return_val_if_fail (first_property_name != NULL, NULL); + + animation = animation_create_for_actor (actor); + clutter_animation_set_mode (animation, mode); + clutter_animation_set_timeline (animation, timeline); + + va_start (args, first_property_name); + clutter_animation_setup_valist (animation, first_property_name, args); + va_end (args); + + clutter_animation_start (animation); + + return animation; +} + +/** + * clutter_actor_animate: + * @actor: a #ClutterActor + * @mode: an animation mode logical id + * @duration: duration of the animation, in milliseconds + * @first_property_name: the name of a property + * @...: a %NULL terminated list of property names and + * property values + * + * Animates the given list of properties of @actor between the current + * value for each property and a new final value. The animation has a + * definite duration and a speed given by the @mode. + * + * For example, this: + * + * |[ + * clutter_actor_animate (rectangle, CLUTTER_LINEAR, 250, + * "width", 100.0, + * "height", 100.0, + * NULL); + * ]| + * + * will make width and height properties of the #ClutterActor "rectangle" + * grow linearly between the current value and 100 pixels, in 250 milliseconds. + * + * The animation @mode is a logical id, either from the #ClutterAnimationMode + * enumeration of from clutter_alpha_register_func(). + * + * All the properties specified will be animated between the current value + * and the final value. If a property should be set at the beginning of + * the animation but not updated during the animation, it should be prefixed + * by the "fixed::" string, for instance: + * + * |[ + * clutter_actor_animate (actor, CLUTTER_EASE_IN_SINE, 100, + * "rotation-angle-z", 360.0, + * "fixed::rotation-center-z", ¢er, + * NULL); + * ]| + * + * Will animate the "rotation-angle-z" property between the current value + * and 360 degrees, and set the "rotation-center-z" property to the fixed + * value of the #ClutterVertex "center". + * + * This function will implicitly create a #ClutterAnimation object which + * will be assigned to the @actor and will be returned to the developer + * to control the animation or to know when the animation has been + * completed. + * + * If a name argument starts with "signal::", "signal-after::", + * "signal-swapped::" or "signal-swapped-after::" the two following arguments + * are used as callback function and data for a signal handler installed on + * the #ClutterAnimation object for the specified signal name, for instance: + * + * |[ + * static void + * on_animation_completed (ClutterAnimation *animation, + * ClutterActor *actor) + * { + * clutter_actor_hide (actor); + * } + * + * clutter_actor_animate (actor, CLUTTER_EASE_IN_CUBIC, 100, + * "opacity", 0, + * "signal::completed", on_animation_completed, actor, + * NULL); + * ]| + * + * or, to automatically destroy an actor at the end of the animation: + * + * |[ + * clutter_actor_animate (actor, CLUTTER_EASE_IN_CUBIC, 100, + * "opacity", 0, + * "signal-swapped-after::completed", + * clutter_actor_destroy, + * actor, + * NULL); + * ]| + * + * The "signal::" modifier is the equivalent of using g_signal_connect(); + * the "signal-after::" modifier is the equivalent of using + * g_signal_connect_after() or g_signal_connect_data() with the + * %G_CONNECT_AFTER; the "signal-swapped::" modifier is the equivalent + * of using g_signal_connect_swapped() or g_signal_connect_data() with the + * %G_CONNECT_SWAPPED flah; finally, the "signal-swapped-after::" modifier + * is the equivalent of using g_signal_connect_data() with both the + * %G_CONNECT_AFTER and %G_CONNECT_SWAPPED flags. The clutter_actor_animate() + * function will not keep track of multiple connections to the same signal, + * so it is your responsability to avoid them when calling + * clutter_actor_animate() multiple times on the same actor. + * + * Calling this function on an actor that is already being animated + * will cause the current animation to change with the new final values, + * the new easing mode and the new duration - that is, this code: + * + * |[ + * clutter_actor_animate (actor, CLUTTER_LINEAR, 250, + * "width", 100.0, + * "height", 100.0, + * NULL); + * clutter_actor_animate (actor, CLUTTER_EASE_IN_CUBIC, 500, + * "x", 100.0, + * "y", 100.0, + * "width", 200.0, + * NULL); + * ]| + * + * is the equivalent of: + * + * |[ + * clutter_actor_animate (actor, CLUTTER_EASE_IN_CUBIC, 500, + * "x", 100.0, + * "y", 100.0, + * "width", 200.0, + * "height", 100.0, + * NULL); + * ]| + * + * Unless the animation is looping, the #ClutterAnimation created by + * clutter_actor_animate() will become invalid as soon as it is + * complete. + * + * Since the created #ClutterAnimation instance attached to @actor + * is guaranteed to be valid throughout the #ClutterAnimation::completed + * signal emission chain, you will not be able to create a new animation + * using clutter_actor_animate() on the same @actor from within the + * #ClutterAnimation::completed signal handler unless you use + * g_signal_connect_after() to connect the callback function, for instance: + * + * |[ + * static void + * on_animation_completed (ClutterAnimation *animation, + * ClutterActor *actor) + * { + * clutter_actor_animate (actor, CLUTTER_EASE_OUT_CUBIC, 250, + * "x", 500.0, + * "y", 500.0, + * NULL); + * } + * + * ... + * animation = clutter_actor_animate (actor, CLUTTER_EASE_IN_CUBIC, 250, + * "x", 100.0, + * "y", 100.0, + * NULL); + * g_signal_connect (animation, "completed", + * G_CALLBACK (on_animation_completed), + * actor); + * ... + * ]| + * + * Return value: (transfer none): a #ClutterAnimation object. The object is + * owned by the #ClutterActor and should not be unreferenced with + * g_object_unref() + * + * Since: 1.0 + * Deprecated: 1.12: Use the implicit transition for animatable properties + * in #ClutterActor instead. See clutter_actor_save_easing_state(), + * clutter_actor_set_easing_mode(), clutter_actor_set_easing_duration(), + * clutter_actor_set_easing_delay(), and clutter_actor_restore_easing_state(). + */ +ClutterAnimation * +clutter_actor_animate (ClutterActor *actor, + gulong mode, + guint duration, + const gchar *first_property_name, + ...) +{ + ClutterAnimation *animation; + va_list args; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), NULL); + g_return_val_if_fail (mode != CLUTTER_CUSTOM_MODE, NULL); + g_return_val_if_fail (duration > 0, NULL); + g_return_val_if_fail (first_property_name != NULL, NULL); + + animation = animation_create_for_actor (actor); + 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); + va_end (args); + + clutter_animation_start (animation); + + return animation; +} + +/** + * clutter_actor_animatev: + * @actor: a #ClutterActor + * @mode: an animation mode logical id + * @duration: duration of the animation, in milliseconds + * @n_properties: number of property names and values + * @properties: (array length=n_properties) (element-type utf8): a vector + * containing the property names to set + * @values: (array length=n_properties): a vector containing the + * property values to set + * + * Animates the given list of properties of @actor between the current + * value for each property and a new final value. The animation has a + * definite duration and a speed given by the @mode. + * + * This is the vector-based variant of clutter_actor_animate(), useful + * for language bindings. + * + * Unlike clutter_actor_animate(), this function will not + * allow you to specify "signal::" names and callbacks. + * + * Return value: (transfer none): a #ClutterAnimation object. The object is + * owned by the #ClutterActor and should not be unreferenced with + * g_object_unref() + * + * Since: 1.0 + * Deprecated: 1.12: Use the implicit transition for animatable properties + * in #ClutterActor instead. See clutter_actor_save_easing_state(), + * clutter_actor_set_easing_mode(), clutter_actor_set_easing_duration(), + * clutter_actor_set_easing_delay(), and clutter_actor_restore_easing_state(). + */ +ClutterAnimation * +clutter_actor_animatev (ClutterActor *actor, + gulong mode, + guint duration, + gint n_properties, + const gchar * const properties[], + const GValue *values) +{ + ClutterAnimation *animation; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), NULL); + g_return_val_if_fail (mode != CLUTTER_CUSTOM_MODE, NULL); + g_return_val_if_fail (duration > 0, NULL); + g_return_val_if_fail (properties != NULL, NULL); + g_return_val_if_fail (values != NULL, NULL); + + animation = animation_create_for_actor (actor); + clutter_animation_set_mode (animation, mode); + clutter_animation_set_duration (animation, duration); + clutter_animation_setupv (animation, n_properties, properties, values); + clutter_animation_start (animation); + + return animation; +} + +/** + * clutter_actor_animate_with_timelinev: + * @actor: a #ClutterActor + * @mode: an animation mode logical id + * @timeline: a #ClutterTimeline + * @n_properties: number of property names and values + * @properties: (array length=n_properties) (element-type utf8): a vector + * containing the property names to set + * @values: (array length=n_properties): a vector containing the + * property values to set + * + * Animates the given list of properties of @actor between the current + * value for each property and a new final value. The animation has a + * definite duration given by @timeline and a speed given by the @mode. + * + * See clutter_actor_animate() for further details. + * + * This function is useful if you want to use an existing timeline + * to animate @actor. + * + * This is the vector-based variant of clutter_actor_animate_with_timeline(), + * useful for language bindings. + * + * Unlike clutter_actor_animate_with_timeline(), this function + * will not allow you to specify "signal::" names and callbacks. + * + * Return value: (transfer none): a #ClutterAnimation object. The object is + * owned by the #ClutterActor and should not be unreferenced with + * g_object_unref() + * + * Since: 1.0 + * Deprecated: 1.12: Use the implicit transition for animatable properties + * in #ClutterActor instead. See clutter_actor_save_easing_state(), + * clutter_actor_set_easing_mode(), clutter_actor_set_easing_duration(), + * clutter_actor_set_easing_delay(), and clutter_actor_restore_easing_state(). + */ +ClutterAnimation * +clutter_actor_animate_with_timelinev (ClutterActor *actor, + gulong mode, + ClutterTimeline *timeline, + gint n_properties, + const gchar * const properties[], + const GValue *values) +{ + ClutterAnimation *animation; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), NULL); + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), NULL); + g_return_val_if_fail (properties != NULL, NULL); + g_return_val_if_fail (values != NULL, NULL); + + animation = animation_create_for_actor (actor); + clutter_animation_set_mode (animation, mode); + clutter_animation_set_timeline (animation, timeline); + clutter_animation_setupv (animation, n_properties, properties, values); + clutter_animation_start (animation); + + return animation; +} + +/** + * clutter_actor_animate_with_alphav: + * @actor: a #ClutterActor + * @alpha: a #ClutterAlpha + * @n_properties: number of property names and values + * @properties: (array length=n_properties) (element-type utf8): a vector + * containing the property names to set + * @values: (array length=n_properties): a vector containing the + * property values to set + * + * Animates the given list of properties of @actor between the current + * value for each property and a new final value. The animation has a + * definite behaviour given by the passed @alpha. + * + * See clutter_actor_animate() for further details. + * + * This function is useful if you want to use an existing #ClutterAlpha + * to animate @actor. + * + * This is the vector-based variant of clutter_actor_animate_with_alpha(), + * useful for language bindings. + * + * Unlike clutter_actor_animate_with_alpha(), this function will + * not allow you to specify "signal::" names and callbacks. + * + * Return value: (transfer none): a #ClutterAnimation object. The object is owned by the + * #ClutterActor and should not be unreferenced with g_object_unref() + * + * Since: 1.0 + * + * Deprecated: 1.10: Use the implicit transition for animatable properties + * in #ClutterActor instead. See clutter_actor_save_easing_state(), + * clutter_actor_set_easing_mode(), clutter_actor_set_easing_duration(), + * clutter_actor_set_easing_delay(), and clutter_actor_restore_easing_state(). + */ +ClutterAnimation * +clutter_actor_animate_with_alphav (ClutterActor *actor, + ClutterAlpha *alpha, + gint n_properties, + const gchar * const properties[], + const GValue *values) +{ + ClutterAnimation *animation; + ClutterTimeline *timeline; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), NULL); + g_return_val_if_fail (CLUTTER_IS_ALPHA (alpha), NULL); + g_return_val_if_fail (properties != NULL, NULL); + g_return_val_if_fail (values != NULL, NULL); + + timeline = clutter_alpha_get_timeline (alpha); + if (timeline == NULL) + { + g_warning ("The passed ClutterAlpha does not have an " + "associated ClutterTimeline."); + return NULL; + } + + animation = animation_create_for_actor (actor); + clutter_animation_set_alpha_internal (animation, alpha); + clutter_animation_setupv (animation, n_properties, properties, values); + clutter_animation_start (animation); + + return animation; +} + +/** + * clutter_actor_get_animation: + * @actor: a #ClutterActor + * + * Retrieves the #ClutterAnimation used by @actor, if clutter_actor_animate() + * has been called on @actor. + * + * Return value: (transfer none): a #ClutterAnimation, or %NULL + * + * Since: 1.0 + * Deprecated: 1.12: Use the implicit transition for animatable properties + * in #ClutterActor instead, and clutter_actor_get_transition() to retrieve + * the transition. + */ +ClutterAnimation * +clutter_actor_get_animation (ClutterActor *actor) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), NULL); + + return g_object_get_qdata (G_OBJECT (actor), quark_object_animation); +} + +/** + * clutter_actor_detach_animation: + * @actor: a #ClutterActor + * + * Detaches the #ClutterAnimation used by @actor, if clutter_actor_animate() + * has been called on @actor. + * + * Once the animation has been detached, it loses a reference. If it was + * the only reference then the #ClutterAnimation becomes invalid. + * + * The #ClutterAnimation::completed signal will not be emitted. + * + * Since: 1.4 + * Deprecated: 1.12: Use the implicit transition for animatable properties + * in #ClutterActor instead, and clutter_actor_remove_transition() to + * remove the transition. + */ +void +clutter_actor_detach_animation (ClutterActor *actor) +{ + ClutterAnimation *animation; + ClutterAnimationPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + animation = g_object_get_qdata (G_OBJECT (actor), quark_object_animation); + if (animation == NULL) + return; + + priv = animation->priv; + + g_assert (priv->object == G_OBJECT (actor)); + + /* we can't call get_timeline_internal() here because it would be + * pointless to create a timeline on an animation we want to detach + */ + if (priv->alpha != NULL) + { + ClutterTimeline *timeline; + + timeline = clutter_alpha_get_timeline (priv->alpha); + if (timeline != NULL) + clutter_timeline_stop (timeline); + } + + /* disconnect the ::destroy handler added by animation_create_for_actor() */ + g_signal_handlers_disconnect_by_func (actor, + G_CALLBACK (on_actor_destroy), + animation); + + clutter_animation_set_object (animation, NULL); + + /* drop the reference on the animation */ + g_object_unref (animation); +} diff --git a/clutter/clutter/deprecated/clutter-animation.h b/clutter/clutter/deprecated/clutter-animation.h new file mode 100644 index 0000000..3b2310b --- /dev/null +++ b/clutter/clutter/deprecated/clutter-animation.h @@ -0,0 +1,210 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2008 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 . + * + * Author: + * Emmanuele Bassi + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_ANIMATION_H__ +#define __CLUTTER_ANIMATION_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_ANIMATION (clutter_animation_get_type ()) +#define CLUTTER_ANIMATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ANIMATION, ClutterAnimation)) +#define CLUTTER_IS_ANIMATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ANIMATION)) +#define CLUTTER_ANIMATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_ANIMATION, ClutterAnimationClass)) +#define CLUTTER_IS_ANIMATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_ANIMATION)) +#define CLUTTER_ANIMATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_ANIMATION, ClutterAnimationClass)) + +typedef struct _ClutterAnimationPrivate ClutterAnimationPrivate; +typedef struct _ClutterAnimationClass ClutterAnimationClass; + +/** + * ClutterAnimation: + * + * The #ClutterAnimation structure contains only private data and should + * be accessed using the provided functions. + * + * Since: 1.0 + * + * Deprecated: 1.12: Use the implicit animation on #ClutterActor + */ +struct _ClutterAnimation +{ + /*< private >*/ + GObject parent_instance; + + ClutterAnimationPrivate *priv; +}; + +/** + * ClutterAnimationClass: + * @started: class handler for the #ClutterAnimation::started signal + * @completed: class handler for the #ClutterAnimation::completed signal + * + * The #ClutterAnimationClass structure contains only private data and + * should be accessed using the provided functions. + * + * Since: 1.0 + * + * Deprecated: 1.12: Use the implicit animation on #ClutterActor + */ +struct _ClutterAnimationClass +{ + /*< private >*/ + GObjectClass parent_class; + + /*< public >*/ + void (* started) (ClutterAnimation *animation); + void (* completed) (ClutterAnimation *animation); + + /*< private >*/ + /* padding for future expansion */ + void (*_clutter_reserved1) (void); + void (*_clutter_reserved2) (void); + void (*_clutter_reserved3) (void); + void (*_clutter_reserved4) (void); + void (*_clutter_reserved5) (void); + void (*_clutter_reserved6) (void); + void (*_clutter_reserved7) (void); + void (*_clutter_reserved8) (void); +}; + +CLUTTER_DEPRECATED_IN_1_12 +GType clutter_animation_get_type (void) G_GNUC_CONST; + +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_property_transition_new) +ClutterAnimation * clutter_animation_new (void); + +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_transition_set_animatable) +void clutter_animation_set_object (ClutterAnimation *animation, + GObject *object); +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_transition_get_animatable) +GObject * clutter_animation_get_object (ClutterAnimation *animation); +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_timeline_set_progress_mode) +void clutter_animation_set_mode (ClutterAnimation *animation, + gulong mode); +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_timeline_get_progress_mode) +gulong clutter_animation_get_mode (ClutterAnimation *animation); +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_timeline_set_duration) +void clutter_animation_set_duration (ClutterAnimation *animation, + guint msecs); +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_timeline_get_duration) +guint clutter_animation_get_duration (ClutterAnimation *animation); +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_timeline_set_repeat_count) +void clutter_animation_set_loop (ClutterAnimation *animation, + gboolean loop); +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_timeline_get_repeat_count) +gboolean clutter_animation_get_loop (ClutterAnimation *animation); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_animation_set_timeline (ClutterAnimation *animation, + ClutterTimeline *timeline); +CLUTTER_DEPRECATED_IN_1_12 +ClutterTimeline * clutter_animation_get_timeline (ClutterAnimation *animation); +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_animation_set_timeline) +void clutter_animation_set_alpha (ClutterAnimation *animation, + ClutterAlpha *alpha); +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_animation_get_timeline) +ClutterAlpha * clutter_animation_get_alpha (ClutterAnimation *animation); +CLUTTER_DEPRECATED_IN_1_12 +ClutterAnimation * clutter_animation_bind (ClutterAnimation *animation, + const gchar *property_name, + const GValue *final); +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_transition_set_interval) +ClutterAnimation * clutter_animation_bind_interval (ClutterAnimation *animation, + const gchar *property_name, + ClutterInterval *interval); +CLUTTER_DEPRECATED_IN_1_12 +gboolean clutter_animation_has_property (ClutterAnimation *animation, + const gchar *property_name); +CLUTTER_DEPRECATED_IN_1_12 +ClutterAnimation * clutter_animation_update (ClutterAnimation *animation, + const gchar *property_name, + const GValue *final); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_animation_update_interval (ClutterAnimation *animation, + const gchar *property_name, + ClutterInterval *interval); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_animation_unbind_property (ClutterAnimation *animation, + const gchar *property_name); +CLUTTER_DEPRECATED_IN_1_12 +ClutterInterval * clutter_animation_get_interval (ClutterAnimation *animation, + const gchar *property_name); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_animation_completed (ClutterAnimation *animation); + +/* + * ClutterActor API + */ + +CLUTTER_DEPRECATED_IN_1_12 +ClutterAnimation * clutter_actor_animate (ClutterActor *actor, + gulong mode, + guint duration, + const gchar *first_property_name, + ...) G_GNUC_NULL_TERMINATED; +CLUTTER_DEPRECATED_IN_1_12 +ClutterAnimation * clutter_actor_animate_with_timeline (ClutterActor *actor, + gulong mode, + ClutterTimeline *timeline, + const gchar *first_property_name, + ...) G_GNUC_NULL_TERMINATED; +CLUTTER_DEPRECATED_IN_1_12 +ClutterAnimation * clutter_actor_animatev (ClutterActor *actor, + gulong mode, + guint duration, + gint n_properties, + const gchar * const properties[], + const GValue *values); +CLUTTER_DEPRECATED_IN_1_12 +ClutterAnimation * clutter_actor_animate_with_timelinev (ClutterActor *actor, + gulong mode, + ClutterTimeline *timeline, + gint n_properties, + const gchar * const properties[], + const GValue *values); +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_animate_with_timeline) +ClutterAnimation * clutter_actor_animate_with_alpha (ClutterActor *actor, + ClutterAlpha *alpha, + const gchar *first_property_name, + ...) G_GNUC_NULL_TERMINATED; +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_animate_with_timelinev) +ClutterAnimation * clutter_actor_animate_with_alphav (ClutterActor *actor, + ClutterAlpha *alpha, + gint n_properties, + const gchar * const properties[], + const GValue *values); + +CLUTTER_DEPRECATED_IN_1_12 +ClutterAnimation * clutter_actor_get_animation (ClutterActor *actor); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_actor_detach_animation (ClutterActor *actor); + +G_END_DECLS + +#endif /* __CLUTTER_ANIMATION_DEPRECATED_H__ */ diff --git a/clutter/clutter/deprecated/clutter-animator.c b/clutter/clutter/deprecated/clutter-animator.c new file mode 100644 index 0000000..8464c05 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-animator.c @@ -0,0 +1,2166 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Øyvind KolÃ¥s + */ + +/** + * SECTION:clutter-animator + * @short_description: Multi-actor tweener + * @See_Also: #ClutterAnimatable, #ClutterInterval, #ClutterAlpha, + * #ClutterTimeline + * + * #ClutterAnimator is an object providing declarative animations for + * #GObject properties belonging to one or more #GObjects to + * #ClutterIntervals. + * + * #ClutterAnimator is used to build and describe complex animations + * in terms of "key frames". #ClutterAnimator is meant to be used + * through the #ClutterScript definition format, but it comes with a + * convenience C API. + * + * #ClutterAnimator is available since Clutter 1.2 + * + * #ClutterAnimator has been deprecated in Clutter 1.12. If you + * want to combine multiple transitions using key frames, use + * #ClutterKeyframeTransition and #ClutterTransitionGroup instead. + * + * ## Key Frames + * + * Every animation handled by a #ClutterAnimator can be + * described in terms of "key frames". For each #GObject property + * there can be multiple key frames, each one defined by the end + * value for the property to be computed starting from the current + * value to a specific point in time, using a given easing + * mode. + * + * The point in time is defined using a value representing + * the progress in the normalized interval of [ 0, 1 ]. This maps + * the value returned by clutter_timeline_get_duration(). + * + * ## ClutterAnimator description for ClutterScript + * + * #ClutterAnimator defines a custom "properties" key + * which allows describing the key frames for objects as + * an array of key frames. + * + * The `properties` array has the following syntax: + * + * |[ + * { + * "properties" : [ + * { + * "object" : object_id + * "name" : property_name + * "ease-in" : true_or_false + * "interpolation" : interpolation_value + * "keys" : [ + * [ progress, easing_mode, final_value ] + * ] + * ] + * } + * ]| + * + * The following JSON fragment defines a #ClutterAnimator + * with the duration of 1 second and operating on the x and y + * properties of a #ClutterActor named "rect-01", with two frames + * for each property. The first frame will linearly move the actor + * from its current position to the 100, 100 position in 20 percent + * of the duration of the animation; the second will using a cubic + * easing to move the actor to the 200, 200 coordinates. + * + * |[ + * { + * "type" : "ClutterAnimator", + * "duration" : 1000, + * "properties" : [ + * { + * "object" : "rect-01", + * "name" : "x", + * "ease-in" : true, + * "keys" : [ + * [ 0.2, "linear", 100.0 ], + * [ 1.0, "easeOutCubic", 200.0 ] + * ] + * }, + * { + * "object" : "rect-01", + * "name" : "y", + * "ease-in" : true, + * "keys" : [ + * [ 0.2, "linear", 100.0 ], + * [ 1.0, "easeOutCubic", 200.0 ] + * ] + * } + * ] + * } + * ]| + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include +#include + +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS + +#include "clutter-animator.h" + +#include "clutter-alpha.h" +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-interval.h" +#include "clutter-private.h" +#include "clutter-script-private.h" +#include "clutter-scriptable.h" + +/* progress values varying by less than this are considered equal */ +#define PROGRESS_EPSILON 0.00001 + +struct _ClutterAnimatorPrivate +{ + ClutterTimeline *timeline; + ClutterTimeline *slave_timeline; + + GList *score; + + GHashTable *properties; +}; + +struct _ClutterAnimatorKey +{ + GObject *object; + const gchar *property_name; + guint mode; + + GValue value; + + /* normalized progress, between 0.0 and 1.0 */ + gdouble progress; + + /* back-pointer to the animator which owns the key */ + ClutterAnimator *animator; + + /* interpolation mode */ + ClutterInterpolation interpolation; + + /* ease from the current object state into the animation when it starts */ + guint ease_in : 1; + + /* This key is already being destroyed and shouldn't + * trigger additional weak unrefs + */ + guint is_inert : 1; + + gint ref_count; +}; + +enum +{ + PROP_0, + + PROP_DURATION, + PROP_TIMELINE, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +static void clutter_scriptable_init (ClutterScriptableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (ClutterAnimator, + clutter_animator, + G_TYPE_OBJECT, + G_ADD_PRIVATE (ClutterAnimator) + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_SCRIPTABLE, + clutter_scriptable_init)); +/** + * clutter_animator_new: + * + * Creates a new #ClutterAnimator instance + * + * Return value: a new #ClutterAnimator. + * + * Since: 1.2 + * + * Deprecated: 1.12: Use #ClutterKeyframeTransition instead + */ +ClutterAnimator * +clutter_animator_new (void) +{ + return g_object_new (CLUTTER_TYPE_ANIMATOR, NULL); +} + +/***/ + +typedef struct _PropObjectKey { + GObject *object; + const gchar *property_name; + guint mode; + gdouble progress; +} PropObjectKey; + +/* Iterator that walks the keys of a property*/ +typedef struct _PropertyIter { + PropObjectKey *key; + ClutterInterval *interval; + ClutterAlpha *alpha; + + GList *current; + + gdouble start; /* the progress of current */ + gdouble end; /* until which progress it is valid */ + ClutterInterpolation interpolation; + + guint ease_in : 1; +} PropertyIter; + +static PropObjectKey * +prop_actor_key_new (GObject *object, + const gchar *property_name) +{ + PropObjectKey *key = g_slice_new0 (PropObjectKey); + + key->object = object; + key->property_name = g_intern_string (property_name); + + return key; +} + +static void +prop_actor_key_free (gpointer key) +{ + if (key != NULL) + g_slice_free (PropObjectKey, key); +} + +static void +property_iter_free (gpointer key) +{ + if (key != NULL) + { + PropertyIter *property_iter = key; + + g_object_unref (property_iter->interval); + g_object_unref (property_iter->alpha); + + g_slice_free (PropertyIter, property_iter); + } +} + +static PropertyIter * +property_iter_new (ClutterAnimator *animator, + PropObjectKey *key, + GType type) +{ + ClutterAnimatorPrivate *priv = animator->priv; + PropertyIter *property_iter = g_slice_new (PropertyIter); + ClutterInterval *interval = g_object_new (CLUTTER_TYPE_INTERVAL, + "value-type", type, + NULL); + + /* we own this interval */ + g_object_ref_sink (interval); + + property_iter->interval = interval; + property_iter->key = key; + property_iter->alpha = clutter_alpha_new (); + clutter_alpha_set_timeline (property_iter->alpha, priv->slave_timeline); + + /* as well as the alpha */ + g_object_ref_sink (property_iter->alpha); + + return property_iter; +} + +static guint +prop_actor_hash (gconstpointer value) +{ + const PropObjectKey *info = value; + + return GPOINTER_TO_INT (info->property_name) + ^ GPOINTER_TO_INT (info->object); +} + +static gboolean +prop_actor_equal (gconstpointer a, gconstpointer b) +{ + const PropObjectKey *infoa = a; + const PropObjectKey *infob = b; + + /* property name strings are interned so we can just compare pointers */ + if (infoa->object == infob->object && + (infoa->property_name == infob->property_name)) + return TRUE; + + return FALSE; +} + +static gint +sort_actor_prop_progress_func (gconstpointer a, + gconstpointer b) +{ + const ClutterAnimatorKey *pa = a; + const ClutterAnimatorKey *pb = b; + + if (pa->object == pb->object) + { + gint pdiff = pb->property_name - pa->property_name; + + if (pdiff) + return pdiff; + + if (fabs (pa->progress - pb->progress) < PROGRESS_EPSILON) + return 0; + + if (pa->progress > pb->progress) + return 1; + + return -1; + } + + return pa->object - pb->object; +} + +static gint +sort_actor_prop_func (gconstpointer a, + gconstpointer b) +{ + const ClutterAnimatorKey *pa = a; + const ClutterAnimatorKey *pb = b; + + if (pa->object == pb->object) + return pa->property_name - pb->property_name; + + return pa->object - pb->object; +} + +static void +clutter_animator_remove_key_internal (ClutterAnimator *animator, + GObject *object, + const gchar *property_name, + gdouble progress, + gboolean is_inert); + +static void +object_disappeared (gpointer data, + GObject *where_the_object_was) +{ + clutter_animator_remove_key_internal (data, where_the_object_was, NULL, -1.0, + TRUE); +} + +static ClutterAnimatorKey * +clutter_animator_key_new (ClutterAnimator *animator, + GObject *object, + const gchar *property_name, + gdouble progress, + guint mode) +{ + ClutterAnimatorKey *animator_key; + + animator_key = g_slice_new (ClutterAnimatorKey); + + animator_key->ref_count = 1; + animator_key->animator = animator; + animator_key->object = object; + animator_key->mode = mode; + memset (&(animator_key->value), 0, sizeof (GValue)); + animator_key->progress = progress; + animator_key->property_name = g_intern_string (property_name); + animator_key->interpolation = CLUTTER_INTERPOLATION_LINEAR; + animator_key->ease_in = FALSE; + animator_key->is_inert = FALSE; + + /* keep a weak reference on the animator, so that we can release the + * back-pointer when needed + */ + g_object_weak_ref (object, object_disappeared, + animator_key->animator); + + return animator_key; +} + +static gpointer +clutter_animator_key_copy (gpointer boxed) +{ + ClutterAnimatorKey *key = boxed; + + if (key != NULL) + key->ref_count += 1; + + return key; +} + +static void +clutter_animator_key_free (gpointer boxed) +{ + ClutterAnimatorKey *key = boxed; + + if (key == NULL) + return; + + key->ref_count -= 1; + + if (key->ref_count > 0) + return; + + if (!key->is_inert) + g_object_weak_unref (key->object, object_disappeared, key->animator); + + g_slice_free (ClutterAnimatorKey, key); +} + +static void +clutter_animator_dispose (GObject *object) +{ + ClutterAnimator *animator = CLUTTER_ANIMATOR (object); + ClutterAnimatorPrivate *priv = animator->priv; + + clutter_animator_set_timeline (animator, NULL); + g_object_unref (priv->slave_timeline); + + G_OBJECT_CLASS (clutter_animator_parent_class)->dispose (object); +} + +static void +clutter_animator_finalize (GObject *object) +{ + ClutterAnimator *animator = CLUTTER_ANIMATOR (object); + ClutterAnimatorPrivate *priv = animator->priv; + + g_list_foreach (priv->score, (GFunc) clutter_animator_key_free, NULL); + g_list_free (priv->score); + priv->score = NULL; + + g_hash_table_destroy (priv->properties); + + G_OBJECT_CLASS (clutter_animator_parent_class)->finalize (object); +} + +/* XXX: this is copied and slightly modified from glib, + * there is only one way to do this. */ +static GList * +list_find_custom_reverse (GList *list, + gconstpointer data, + GCompareFunc func) +{ + while (list) + { + if (! func (list->data, data)) + return list; + + list = list->prev; + } + + return NULL; +} + +/* Ensures that the interval provided by the animator is correct + * for the requested progress value. + */ +static void +animation_animator_ensure_animator (ClutterAnimator *animator, + PropertyIter *property_iter, + PropObjectKey *key, + gdouble progress) +{ + + if (progress > property_iter->end) + { + while (progress > property_iter->end) + { + ClutterAnimatorKey *initial_key, *next_key; + GList *initial, *next; + + initial = g_list_find_custom (property_iter->current->next, + key, + sort_actor_prop_func); + + if (initial) + { + initial_key = initial->data; + + clutter_interval_set_initial_value (property_iter->interval, + &initial_key->value); + property_iter->current = initial; + property_iter->start = initial_key->progress; + + next = g_list_find_custom (initial->next, + key, + sort_actor_prop_func); + if (next) + { + next_key = next->data; + + property_iter->end = next_key->progress; + } + else + { + next_key = initial_key; + + property_iter->end = property_iter->start; + } + + clutter_interval_set_final_value (property_iter->interval, + &next_key->value); + + if ((clutter_alpha_get_mode (property_iter->alpha) != next_key->mode)) + clutter_alpha_set_mode (property_iter->alpha, next_key->mode); + } + else /* no relevant interval */ + { + ClutterAnimatorKey *current_key = property_iter->current->data; + clutter_interval_set_initial_value (property_iter->interval, + ¤t_key->value); + clutter_interval_set_final_value (property_iter->interval, + ¤t_key->value); + break; + } + } + } + else if (progress < property_iter->start) + { + while (progress < property_iter->start) + { + ClutterAnimatorKey *initial_key, *next_key; + GList *initial; + GList *old = property_iter->current; + + initial = list_find_custom_reverse (property_iter->current->prev, + key, + sort_actor_prop_func); + + if (initial) + { + initial_key = initial->data; + + clutter_interval_set_initial_value (property_iter->interval, + &initial_key->value); + property_iter->current = initial; + property_iter->end = property_iter->start; + property_iter->start = initial_key->progress; + + if (old) + { + next_key = old->data; + + property_iter->end = next_key->progress; + } + else + { + next_key = initial_key; + + property_iter->end = 1.0; + } + + clutter_interval_set_final_value (property_iter->interval, + &next_key->value); + if ((clutter_alpha_get_mode (property_iter->alpha) != next_key->mode)) + clutter_alpha_set_mode (property_iter->alpha, next_key->mode); + } + else + break; + } + } +} + +/* XXX - this might be useful as an internal function exposed somewhere */ +static gdouble +cubic_interpolation (const gdouble dx, + const gdouble prev, + const gdouble j, + const gdouble next, + const gdouble nextnext) +{ + return (((( - prev + 3 * j - 3 * next + nextnext ) * dx + + ( 2 * prev - 5 * j + 4 * next - nextnext ) ) * dx + + ( - prev + next ) ) * dx + (j + j) ) / 2.0; +} + +/* try to get a floating point key value from a key for a property, + * failing use the closest key in that direction or the starting point. + */ +static gfloat +list_try_get_rel (GList *list, + gint count) +{ + ClutterAnimatorKey *key; + GList *iter = list; + GList *best = list; + + if (count > 0) + { + while (count -- && iter != NULL) + { + iter = g_list_find_custom (iter->next, list->data, + sort_actor_prop_func); + if (iter != NULL) + best = iter; + } + } + else + { + while (count ++ < 0 && iter != NULL) + { + iter = list_find_custom_reverse (iter->prev, list->data, + sort_actor_prop_func); + if (iter != NULL) + best = iter; + } + } + + if (best != NULL && best->data != NULL) + { + key = best->data; + + return g_value_get_float (&(key->value)); + } + + return 0; +} + +static void +animation_animator_new_frame (ClutterTimeline *timeline, + gint msecs, + ClutterAnimator *animator) +{ + gdouble progress; + GHashTableIter iter; + gpointer key, value; + + progress = 1.0 * msecs / clutter_timeline_get_duration (timeline); + + /* for each property that is managed figure out the GValue to set, + * avoid creating new ClutterInterval's for each interval crossed + */ + g_hash_table_iter_init (&iter, animator->priv->properties); + + key = value = NULL; + while (g_hash_table_iter_next (&iter, &key, &value)) + { + PropObjectKey *prop_actor_key = key; + PropertyIter *property_iter = value; + ClutterAnimatorKey *start_key; + gdouble sub_progress; + + animation_animator_ensure_animator (animator, property_iter, + key, + progress); + start_key = property_iter->current->data; + + if (property_iter->end == property_iter->start) + sub_progress = 0.0; /* we're past the final value */ + else + sub_progress = (progress - property_iter->start) + / (property_iter->end - property_iter->start); + + /* only change values if we active (delayed start) */ + if (sub_progress >= 0.0 && sub_progress <= 1.0) + { + GValue tmp_value = G_VALUE_INIT; + GType int_type; + + g_value_init (&tmp_value, G_VALUE_TYPE (&start_key->value)); + + clutter_timeline_advance (animator->priv->slave_timeline, + sub_progress * 10000); + + sub_progress = clutter_alpha_get_alpha (property_iter->alpha); + int_type = clutter_interval_get_value_type (property_iter->interval); + + if (property_iter->interpolation == CLUTTER_INTERPOLATION_CUBIC && + int_type == G_TYPE_FLOAT) + { + gdouble prev, current, next, nextnext; + gdouble res; + + if ((property_iter->ease_in == FALSE || + (property_iter->ease_in && + list_find_custom_reverse (property_iter->current->prev, + property_iter->current->data, + sort_actor_prop_func)))) + { + current = g_value_get_float (&start_key->value); + prev = list_try_get_rel (property_iter->current, -1); + } + else + { + /* interpolated and easing in */ + clutter_interval_get_initial_value (property_iter->interval, + &tmp_value); + prev = current = g_value_get_float (&tmp_value); + } + + next = list_try_get_rel (property_iter->current, 1); + nextnext = list_try_get_rel (property_iter->current, 2); + res = cubic_interpolation (sub_progress, prev, current, next, + nextnext); + + g_value_set_float (&tmp_value, res); + } + else + clutter_interval_compute_value (property_iter->interval, + sub_progress, + &tmp_value); + + g_object_set_property (prop_actor_key->object, + prop_actor_key->property_name, + &tmp_value); + + g_value_unset (&tmp_value); + } + } +} + +static void +animation_animator_started (ClutterTimeline *timeline, + ClutterAnimator *animator) +{ + GList *k; + + /* Ensure that animators exist for all involved properties */ + for (k = animator->priv->score; k != NULL; k = k->next) + { + ClutterAnimatorKey *key = k->data; + PropertyIter *property_iter; + PropObjectKey *prop_actor_key; + + prop_actor_key = prop_actor_key_new (key->object, key->property_name); + property_iter = g_hash_table_lookup (animator->priv->properties, + prop_actor_key); + if (property_iter) + { + prop_actor_key_free (prop_actor_key); + } + else + { + GObjectClass *klass = G_OBJECT_GET_CLASS (key->object); + GParamSpec *pspec; + + pspec = g_object_class_find_property (klass, key->property_name); + + property_iter = property_iter_new (animator, prop_actor_key, + G_PARAM_SPEC_VALUE_TYPE (pspec)); + g_hash_table_insert (animator->priv->properties, + prop_actor_key, + property_iter); + } + } + + /* initialize animator with initial list pointers */ + { + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init (&iter, animator->priv->properties); + while (g_hash_table_iter_next (&iter, &key, &value)) + { + PropertyIter *property_iter = value; + ClutterAnimatorKey *initial_key, *next_key; + GList *initial; + GList *next; + + initial = g_list_find_custom (animator->priv->score, + key, + sort_actor_prop_func); + g_assert (initial != NULL); + initial_key = initial->data; + clutter_interval_set_initial_value (property_iter->interval, + &initial_key->value); + + property_iter->current = initial; + property_iter->start = initial_key->progress; + property_iter->ease_in = initial_key->ease_in; + property_iter->interpolation = initial_key->interpolation; + + if (property_iter->ease_in) + { + GValue tmp_value = G_VALUE_INIT; + GType int_type; + + int_type = clutter_interval_get_value_type (property_iter->interval); + g_value_init (&tmp_value, int_type); + + g_object_get_property (initial_key->object, + initial_key->property_name, + &tmp_value); + + clutter_interval_set_initial_value (property_iter->interval, + &tmp_value); + + g_value_unset (&tmp_value); + } + + next = g_list_find_custom (initial->next, key, sort_actor_prop_func); + if (next) + { + next_key = next->data; + property_iter->end = next_key->progress; + } + else + { + next_key = initial_key; + property_iter->end = 1.0; + } + + clutter_interval_set_final_value (property_iter->interval, + &next_key->value); + if ((clutter_alpha_get_mode (property_iter->alpha) != next_key->mode)) + clutter_alpha_set_mode (property_iter->alpha, next_key->mode); + } + } +} + +/** + * clutter_animator_compute_value: + * @animator: a #ClutterAnimator + * @object: a #GObject + * @property_name: the name of the property on object to check + * @progress: a value between 0.0 and 1.0 + * @value: an initialized value to store the computed result + * + * Compute the value for a managed property at a given progress. + * + * If the property is an ease-in property, the current value of the property + * on the object will be used as the starting point for computation. + * + * Return value: %TRUE if the computation yields has a value, otherwise (when + * an error occurs or the progress is before any of the keys) %FALSE is + * returned and the #GValue is left untouched + * + * Since: 1.2 + * Deprecated: 1.12: Use #ClutterKeyframeTransition instead + */ +gboolean +clutter_animator_compute_value (ClutterAnimator *animator, + GObject *object, + const gchar *property_name, + gdouble progress, + GValue *value) +{ + ClutterAnimatorPrivate *priv; + ClutterAnimatorKey key; + ClutterAnimatorKey *previous; + ClutterAnimatorKey *next = NULL; + GParamSpec *pspec; + GList *initial_l; + GList *previous_l; + GList *next_l; + gboolean ease_in; + ClutterInterpolation interpolation; + + g_return_val_if_fail (CLUTTER_IS_ANIMATOR (animator), FALSE); + g_return_val_if_fail (G_IS_OBJECT (object), FALSE); + g_return_val_if_fail (property_name, FALSE); + g_return_val_if_fail (value, FALSE); + + priv = animator->priv; + + ease_in = clutter_animator_property_get_ease_in (animator, object, + property_name); + interpolation = clutter_animator_property_get_interpolation (animator, + object, property_name); + + property_name = g_intern_string (property_name); + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), + property_name); + + key.object = object; + key.property_name = property_name; + + initial_l = g_list_find_custom (animator->priv->score, &key, + sort_actor_prop_func); + if (initial_l == NULL) + return FALSE; + + /* first find the interval we belong in, that is the first interval + * existing between keys + */ + + for (previous_l = initial_l, next_l = previous_l->next ; + previous_l->next ; + previous_l = previous_l->next, next_l = previous_l->next) + { + previous = previous_l->data; + if (next_l) + { + next = next_l->data; + if (next->object != object || + next->property_name != property_name) + { + next_l = NULL; + next = NULL; + } + } + else + next = NULL; + + if (progress < previous->progress) + { + /* we are before the defined values */ + + /* value has not been set */ + return FALSE; + } + + if (!next && previous->progress <= progress) + { + /* we only had one key for this object/property */ + /* and we are past it, that is our value */ + g_value_copy (&previous->value, value); + return TRUE; + } + + if (next && next->progress >= progress) + { + ClutterInterval *interval; + ClutterAlpha *alpha; + + gdouble sub_progress = (progress - previous->progress) + / (next->progress - previous->progress); + /* this should be our interval */ + interval = g_object_new (CLUTTER_TYPE_INTERVAL, + "value-type", pspec->value_type, + NULL); + + if (ease_in && previous_l == initial_l) + { + GValue tmp_value = {0, }; + g_value_init (&tmp_value, pspec->value_type); + g_object_get_property (object, property_name, &tmp_value); + clutter_interval_set_initial_value (interval, &tmp_value); + g_value_unset (&tmp_value); + } + else + clutter_interval_set_initial_value (interval, &previous->value); + + clutter_interval_set_final_value (interval, &next->value); + + alpha = clutter_alpha_new (); + clutter_alpha_set_timeline (alpha, priv->slave_timeline); + clutter_alpha_set_mode (alpha, next->mode); + + clutter_timeline_advance (priv->slave_timeline, + sub_progress * 10000); + sub_progress = clutter_alpha_get_alpha (alpha); + + if (interpolation == CLUTTER_INTERPOLATION_CUBIC && + pspec->value_type == G_TYPE_FLOAT) + { + gdouble prev, current, nextv, nextnext; + gdouble res; + + if ((ease_in == FALSE || + (ease_in && + list_find_custom_reverse (previous_l->prev, + previous_l->data, + sort_actor_prop_func)))) + { + current = g_value_get_float (&previous->value); + prev = list_try_get_rel (previous_l, -1); + } + else + { + /* interpolated and easing in */ + GValue tmp_value = {0, }; + g_value_init (&tmp_value, pspec->value_type); + clutter_interval_get_initial_value (interval, + &tmp_value); + prev = current = g_value_get_float (&tmp_value); + g_value_unset (&tmp_value); + } + + nextv = list_try_get_rel (previous_l, 1); + nextnext = list_try_get_rel (previous_l, 2); + res = cubic_interpolation (sub_progress, prev, current, nextv, + nextnext); + g_value_set_float (value, res); + } + else + clutter_interval_compute_value (interval, + sub_progress, + value); + + g_object_ref_sink (interval); + g_object_unref (interval); + g_object_ref_sink (alpha); + g_object_unref (alpha); + + return TRUE; + } + + } + + if (!next) + return FALSE; + + /* We're at, or past the end, use the last value */ + g_value_copy (&next->value, value); + + return TRUE; +} + + +/** + * clutter_animator_set_timeline: + * @animator: a #ClutterAnimator + * @timeline: a #ClutterTimeline + * + * Sets an external timeline that will be used for driving the animation + * + * Since: 1.2 + * Deprecated: 1.12: Use #ClutterKeyframeTransition instead + */ +void +clutter_animator_set_timeline (ClutterAnimator *animator, + ClutterTimeline *timeline) +{ + ClutterAnimatorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ANIMATOR (animator)); + + priv = animator->priv; + + if (priv->timeline != NULL) + { + g_signal_handlers_disconnect_by_func (priv->timeline, + animation_animator_new_frame, + animator); + g_signal_handlers_disconnect_by_func (priv->timeline, + animation_animator_started, + animator); + g_object_unref (priv->timeline); + } + + priv->timeline = timeline; + if (timeline != NULL) + { + g_object_ref (priv->timeline); + + g_signal_connect (priv->timeline, "new-frame", + G_CALLBACK (animation_animator_new_frame), + animator); + g_signal_connect (priv->timeline, "started", + G_CALLBACK (animation_animator_started), + animator); + } +} + +/** + * clutter_animator_get_timeline: + * @animator: a #ClutterAnimator + * + * Get the timeline hooked up for driving the #ClutterAnimator + * + * Return value: (transfer none): the #ClutterTimeline that drives the animator + * + * Since: 1.2 + * Deprecated: 1.12: Use #ClutterKeyframeTransition instead + */ +ClutterTimeline * +clutter_animator_get_timeline (ClutterAnimator *animator) +{ + g_return_val_if_fail (CLUTTER_IS_ANIMATOR (animator), NULL); + return animator->priv->timeline; +} + +/** + * clutter_animator_start: + * @animator: a #ClutterAnimator + * + * Start the ClutterAnimator, this is a thin wrapper that rewinds + * and starts the animators current timeline. + * + * Return value: (transfer none): the #ClutterTimeline that drives + * the animator. The returned timeline is owned by the #ClutterAnimator + * and it should not be unreferenced + * + * Since: 1.2 + * Deprecated: 1.12: Use #ClutterKeyframeTransition instead + */ +ClutterTimeline * +clutter_animator_start (ClutterAnimator *animator) +{ + ClutterAnimatorPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_ANIMATOR (animator), NULL); + + priv = animator->priv; + + clutter_timeline_rewind (priv->timeline); + clutter_timeline_start (priv->timeline); + + return priv->timeline; +} + +/** + * clutter_animator_set_duration: + * @animator: a #ClutterAnimator + * @duration: milliseconds a run of the animator should last. + * + * Runs the timeline of the #ClutterAnimator with a duration in msecs + * as specified. + * + * Since: 1.2 + * Deprecated: 1.12: Use #ClutterKeyframeTransition instead + */ +void +clutter_animator_set_duration (ClutterAnimator *animator, + guint duration) +{ + g_return_if_fail (CLUTTER_IS_ANIMATOR (animator)); + + clutter_timeline_set_duration (animator->priv->timeline, duration); +} + +/** + * clutter_animator_get_duration: + * @animator: a #ClutterAnimator + * + * Retrieves the current duration of an animator + * + * Return value: the duration of the animation, in milliseconds + * + * Since: 1.2 + * Deprecated: 1.12: Use #ClutterKeyframeTransition instead + */ +guint +clutter_animator_get_duration (ClutterAnimator *animator) +{ + g_return_val_if_fail (CLUTTER_IS_ANIMATOR (animator), 0); + + return clutter_timeline_get_duration (animator->priv->timeline); +} + +/** + * clutter_animator_set: + * @animator: a #ClutterAnimator + * @first_object: a #GObject + * @first_property_name: the property to specify a key for + * @first_mode: the id of the alpha function to use + * @first_progress: at which stage of the animation this value applies; the + * range is a normalized floating point value between 0 and 1 + * @...: the value first_property_name should have for first_object + * at first_progress, followed by more (object, property_name, mode, + * progress, value) tuples, followed by %NULL + * + * Adds multiple keys to a #ClutterAnimator, specifying the value a given + * property should have at a given progress of the animation. The mode + * specified is the mode used when going to this key from the previous key of + * the @property_name + * + * If a given (object, property, progress) tuple already exist the mode and + * value will be replaced with the new values. + * + * Since: 1.2 + * Deprecated: 1.12: Use #ClutterKeyframeTransition instead + */ +void +clutter_animator_set (ClutterAnimator *animator, + gpointer first_object, + const gchar *first_property_name, + guint first_mode, + gdouble first_progress, + ...) +{ + GObject *object; + const gchar *property_name; + guint mode; + gdouble progress; + va_list args; + + g_return_if_fail (CLUTTER_IS_ANIMATOR (animator)); + + object = first_object; + property_name = first_property_name; + + g_return_if_fail (object); + g_return_if_fail (property_name); + + mode = first_mode; + progress = first_progress; + + va_start (args, first_progress); + + while (object != NULL) + { + GParamSpec *pspec; + GObjectClass *klass; + GValue value = G_VALUE_INIT; + gchar *error = NULL; + + klass = G_OBJECT_GET_CLASS (object); + pspec = g_object_class_find_property (klass, property_name); + + if (!pspec) + { + g_warning ("Cannot bind property '%s': object of type '%s' " + "do not have this property", + property_name, G_OBJECT_TYPE_NAME (object)); + break; + } + + G_VALUE_COLLECT_INIT (&value, G_PARAM_SPEC_VALUE_TYPE (pspec), + args, 0, + &error); + + if (error) + { + g_warning ("%s: %s", G_STRLOC, error); + g_free (error); + break; + } + + clutter_animator_set_key (animator, + object, + property_name, + mode, + progress, + &value); + + object= va_arg (args, GObject *); + if (object) + { + property_name = va_arg (args, gchar*); + if (!property_name) + { + g_warning ("%s: expected a property name", G_STRLOC); + break; + } + mode = va_arg (args, guint); + progress = va_arg (args, gdouble); + } + } + + va_end (args); +} + +static inline void +clutter_animator_set_key_internal (ClutterAnimator *animator, + ClutterAnimatorKey *key) +{ + ClutterAnimatorPrivate *priv = animator->priv; + GList *old_item; + GList *initial_item; + ClutterAnimatorKey *initial_key = NULL; + + if ((initial_item = g_list_find_custom (animator->priv->score, key, + sort_actor_prop_func))) + initial_key = initial_item->data; + + /* The first key for a property specifies ease-in and interpolation, + * if we are replacing; or becoming a new first key we should + * inherit the old flags. + */ + if (initial_key && + initial_key->progress >= key->progress) + { + key->interpolation = initial_key->interpolation; + key->ease_in = initial_key->ease_in; + } + + old_item = g_list_find_custom (priv->score, key, + sort_actor_prop_progress_func); + + /* replace the key if we already have a similar one */ + if (old_item != NULL) + { + ClutterAnimatorKey *old_key = old_item->data; + + clutter_animator_key_free (old_key); + + priv->score = g_list_remove (priv->score, old_key); + } + + priv->score = g_list_insert_sorted (priv->score, key, + sort_actor_prop_progress_func); + + /* if the animator is already running reinitialize internal iterators */ + if (clutter_timeline_is_playing (priv->timeline)) + animation_animator_started (priv->timeline, animator); +} + +/** + * clutter_animator_set_key: + * @animator: a #ClutterAnimator + * @object: a #GObject + * @property_name: the property to specify a key for + * @mode: the id of the alpha function to use + * @progress: the normalized range at which stage of the animation this + * value applies + * @value: the value property_name should have at progress. + * + * Sets a single key in the #ClutterAnimator for the @property_name of + * @object at @progress. + * + * See also: clutter_animator_set() + * + * Return value: (transfer none): The animator instance + * + * Since: 1.2 + * Deprecated: 1.12: Use #ClutterKeyframeTransition instead + */ +ClutterAnimator * +clutter_animator_set_key (ClutterAnimator *animator, + GObject *object, + const gchar *property_name, + guint mode, + gdouble progress, + const GValue *value) +{ + ClutterAnimatorKey *animator_key; + + g_return_val_if_fail (CLUTTER_IS_ANIMATOR (animator), NULL); + g_return_val_if_fail (G_IS_OBJECT (object), NULL); + g_return_val_if_fail (property_name, NULL); + g_return_val_if_fail (value, NULL); + + property_name = g_intern_string (property_name); + + animator_key = clutter_animator_key_new (animator, + object, property_name, + progress, + mode); + + g_value_init (&animator_key->value, G_VALUE_TYPE (value)); + g_value_copy (value, &animator_key->value); + + clutter_animator_set_key_internal (animator, animator_key); + + return animator; +} + +/** + * clutter_animator_get_keys: + * @animator: a #ClutterAnimator instance + * @object: (allow-none): a #GObject to search for, or %NULL for all objects + * @property_name: (allow-none): a specific property name to query for, + * or %NULL for all properties + * @progress: a specific progress to search for, or a negative value for all + * progresses + * + * Returns a list of pointers to opaque structures with accessor functions + * that describe the keys added to an animator. + * + * Return value: (transfer container) (element-type Clutter.AnimatorKey): a + * list of #ClutterAnimatorKeys; the contents of the list are owned + * by the #ClutterAnimator, but you should free the returned list when done, + * using g_list_free() + * + * Since: 1.2 + * Deprecated: 1.12: Use #ClutterKeyframeTransition instead + */ +GList * +clutter_animator_get_keys (ClutterAnimator *animator, + GObject *object, + const gchar *property_name, + gdouble progress) +{ + GList *keys = NULL; + GList *k; + + g_return_val_if_fail (CLUTTER_IS_ANIMATOR (animator), NULL); + g_return_val_if_fail (object == NULL || G_IS_OBJECT (object), NULL); + + property_name = g_intern_string (property_name); + + for (k = animator->priv->score; k; k = k->next) + { + ClutterAnimatorKey *key = k->data; + + if ((object == NULL || (object == key->object)) && + (property_name == NULL || (property_name == key->property_name)) && + (progress < 0 || fabs (progress - key->progress) < PROGRESS_EPSILON)) + { + keys = g_list_prepend (keys, key); + } + } + + return g_list_reverse (keys); +} + +static void +clutter_animator_remove_key_internal (ClutterAnimator *animator, + GObject *object, + const gchar *property_name, + gdouble progress, + gboolean is_inert) +{ + ClutterAnimatorPrivate *priv; + GList *k; + + g_return_if_fail (CLUTTER_IS_ANIMATOR (animator)); + g_return_if_fail (object == NULL || G_IS_OBJECT (object)); + + property_name = g_intern_string (property_name); + + priv = animator->priv; + +again: + for (k = priv->score; k != NULL; k = k->next) + { + ClutterAnimatorKey *key = k->data; + + if ((object == NULL || (object == key->object)) && + (property_name == NULL || ((property_name == key->property_name))) && + (progress < 0 || fabs (progress - key->progress) < PROGRESS_EPSILON) + ) + { + ClutterAnimatorKey *prev_key = NULL; + key->is_inert = is_inert; + + + /* FIXME: non performant since we reiterate the list many times */ + + prev_key = k->prev ? k->prev->data : NULL; + + if (!prev_key || prev_key->object != key->object || + prev_key->property_name != key->property_name) + { /* We are removing the first key for a property ... */ + ClutterAnimatorKey *next_key = k->next ? k->next->data : NULL; + if (next_key && next_key->object == key->object && + next_key->property_name == key->property_name) + { + /* ... and there is a key of our own type following us, + * copy interpolation/ease_in flags to the new first key + */ + next_key->interpolation = key->interpolation; + next_key->ease_in = key->ease_in; + } + } + + clutter_animator_key_free (key); + priv->score = g_list_remove (priv->score, key); + goto again; + } + } + + /* clear off cached state for all properties, this is regenerated in a + * correct state by animation_animator_started + */ + g_hash_table_remove_all (priv->properties); + + /* if the animator is already running reinitialize internal iterators */ + if (priv->timeline != NULL && clutter_timeline_is_playing (priv->timeline)) + animation_animator_started (priv->timeline, animator); +} + +/** + * clutter_animator_remove_key: + * @animator: a #ClutterAnimator + * @object: (allow-none): a #GObject to search for, or %NULL for all + * @property_name: (allow-none): a specific property name to query for, + * or %NULL for all + * @progress: a specific progress to search for or a negative value + * for all + * + * Removes all keys matching the conditions specificed in the arguments. + * + * Since: 1.2 + * Deprecated: 1.12: Use #ClutterKeyframeTransition instead + */ +void +clutter_animator_remove_key (ClutterAnimator *animator, + GObject *object, + const gchar *property_name, + gdouble progress) +{ + clutter_animator_remove_key_internal (animator, object, property_name, + progress, FALSE); +} + + + + +typedef struct _ParseClosure { + ClutterAnimator *animator; + ClutterScript *script; + + GValue *value; + + gboolean result; +} ParseClosure; + +static ClutterInterpolation +resolve_interpolation (JsonNode *node) +{ + if ((JSON_NODE_TYPE (node) != JSON_NODE_VALUE)) + return CLUTTER_INTERPOLATION_LINEAR; + + if (json_node_get_value_type (node) == G_TYPE_INT64) + { + return json_node_get_int (node); + } + else if (json_node_get_value_type (node) == G_TYPE_STRING) + { + const gchar *str = json_node_get_string (node); + gboolean res; + gint enum_value; + + res = _clutter_script_enum_from_string (CLUTTER_TYPE_INTERPOLATION, + str, + &enum_value); + if (res) + return enum_value; + } + + return CLUTTER_INTERPOLATION_LINEAR; +} + +static void +parse_animator_property (JsonArray *array, + guint index_, + JsonNode *element, + gpointer data) +{ + ParseClosure *clos = data; + JsonObject *object; + JsonArray *keys; + GObject *gobject; + const gchar *id_, *pname; + GObjectClass *klass; + GParamSpec *pspec; + GSList *valid_keys = NULL; + GList *array_keys, *k; + ClutterInterpolation interpolation = CLUTTER_INTERPOLATION_LINEAR; + gboolean ease_in = FALSE; + + if (JSON_NODE_TYPE (element) != JSON_NODE_OBJECT) + { + g_warning ("The 'properties' member of a ClutterAnimator description " + "should be an array of objects, but the element %d of the " + "array is of type '%s'. The element will be ignored.", + index_, + json_node_type_name (element)); + return; + } + + object = json_node_get_object (element); + + if (!json_object_has_member (object, "object") || + !json_object_has_member (object, "name") || + !json_object_has_member (object, "keys")) + { + g_warning ("The property description at index %d is missing one of " + "the mandatory fields: object, name and keys", + index_); + return; + } + + id_ = json_object_get_string_member (object, "object"); + gobject = clutter_script_get_object (clos->script, id_); + if (gobject == NULL) + { + g_warning ("No object with id '%s' has been defined.", id_); + return; + } + + pname = json_object_get_string_member (object, "name"); + klass = G_OBJECT_GET_CLASS (gobject); + pspec = g_object_class_find_property (klass, pname); + if (pspec == NULL) + { + g_warning ("The object of type '%s' and name '%s' has no " + "property named '%s'", + G_OBJECT_TYPE_NAME (gobject), + id_, + pname); + return; + } + + if (json_object_has_member (object, "ease-in")) + ease_in = json_object_get_boolean_member (object, "ease-in"); + + if (json_object_has_member (object, "interpolation")) + { + JsonNode *node = json_object_get_member (object, "interpolation"); + + interpolation = resolve_interpolation (node); + } + + keys = json_object_get_array_member (object, "keys"); + if (keys == NULL) + { + g_warning ("The property description at index %d has an invalid " + "key field of type '%s' when an array was expected.", + index_, + json_node_type_name (json_object_get_member (object, "keys"))); + return; + } + + if (G_IS_VALUE (clos->value)) + valid_keys = g_slist_reverse (g_value_get_pointer (clos->value)); + else + g_value_init (clos->value, G_TYPE_POINTER); + + array_keys = json_array_get_elements (keys); + for (k = array_keys; k != NULL; k = k->next) + { + JsonNode *node = k->data; + JsonArray *key = json_node_get_array (node); + ClutterAnimatorKey *animator_key; + gdouble progress; + gulong mode; + gboolean res; + + progress = json_array_get_double_element (key, 0); + mode = _clutter_script_resolve_animation_mode (json_array_get_element (key, 1)); + + animator_key = clutter_animator_key_new (clos->animator, + gobject, + pname, + progress, + mode); + + res = _clutter_script_parse_node (clos->script, + &(animator_key->value), + pname, + json_array_get_element (key, 2), + pspec); + if (!res) + { + g_warning ("Unable to parse the key value for the " + "property '%s' (progress: %.2f) at index %d", + pname, + progress, + index_); + continue; + } + + animator_key->ease_in = ease_in; + animator_key->interpolation = interpolation; + + valid_keys = g_slist_prepend (valid_keys, animator_key); + } + + g_list_free (array_keys); + + g_value_set_pointer (clos->value, g_slist_reverse (valid_keys)); + + clos->result = TRUE; +} + +static gboolean +clutter_animator_parse_custom_node (ClutterScriptable *scriptable, + ClutterScript *script, + GValue *value, + const gchar *name, + JsonNode *node) +{ + ParseClosure parse_closure; + + if (strcmp (name, "properties") != 0) + return FALSE; + + if (JSON_NODE_TYPE (node) != JSON_NODE_ARRAY) + return FALSE; + + parse_closure.animator = CLUTTER_ANIMATOR (scriptable); + parse_closure.script = script; + parse_closure.value = value; + parse_closure.result = FALSE; + + json_array_foreach_element (json_node_get_array (node), + parse_animator_property, + &parse_closure); + + /* we return TRUE if we had at least one key parsed */ + + return parse_closure.result; +} + +static void +clutter_animator_set_custom_property (ClutterScriptable *scriptable, + ClutterScript *script, + const gchar *name, + const GValue *value) +{ + if (strcmp (name, "properties") == 0) + { + ClutterAnimator *animator = CLUTTER_ANIMATOR (scriptable); + GSList *keys = g_value_get_pointer (value); + GSList *k; + + for (k = keys; k != NULL; k = k->next) + clutter_animator_set_key_internal (animator, k->data); + + g_slist_free (keys); + } + else + g_object_set_property (G_OBJECT (scriptable), name, value); +} + +static void +clutter_scriptable_init (ClutterScriptableIface *iface) +{ + iface->parse_custom_node = clutter_animator_parse_custom_node; + iface->set_custom_property = clutter_animator_set_custom_property; +} + +static void +clutter_animator_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterAnimator *self = CLUTTER_ANIMATOR (gobject); + + switch (prop_id) + { + case PROP_DURATION: + clutter_animator_set_duration (self, g_value_get_uint (value)); + break; + + case PROP_TIMELINE: + clutter_animator_set_timeline (self, g_value_get_object (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_animator_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterAnimatorPrivate *priv = CLUTTER_ANIMATOR (gobject)->priv; + + switch (prop_id) + { + case PROP_DURATION: + g_value_set_uint (value, clutter_timeline_get_duration (priv->timeline)); + break; + + case PROP_TIMELINE: + g_value_set_object (value, priv->timeline); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_animator_class_init (ClutterAnimatorClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = clutter_animator_set_property; + gobject_class->get_property = clutter_animator_get_property; + gobject_class->dispose = clutter_animator_dispose; + gobject_class->finalize = clutter_animator_finalize; + + /** + * ClutterAnimator:duration: + * + * The duration of the #ClutterTimeline used by the #ClutterAnimator + * to drive the animation + * + * Since: 1.2 + * Deprecated: 1.12: Use #ClutterKeyframeTransition instead + */ + obj_props[PROP_DURATION] = + g_param_spec_uint ("duration", + P_("Duration"), + P_("The duration of the animation"), + 0, G_MAXUINT, + 2000, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterAnimator:timeline: + * + * The #ClutterTimeline used by the #ClutterAnimator to drive the + * animation + * + * Since: 1.2 + * Deprecated: 1.12: Use #ClutterKeyframeTransition instead + */ + obj_props[PROP_TIMELINE] = + g_param_spec_object ("timeline", + P_("Timeline"), + P_("The timeline of the animation"), + CLUTTER_TYPE_TIMELINE, + CLUTTER_PARAM_READWRITE); + + g_object_class_install_properties (gobject_class, + PROP_LAST, + obj_props); +} + +static void +clutter_animator_init (ClutterAnimator *animator) +{ + ClutterAnimatorPrivate *priv; + ClutterTimeline *timeline; + + animator->priv = priv = clutter_animator_get_instance_private (animator); + + priv->properties = g_hash_table_new_full (prop_actor_hash, + prop_actor_equal, + prop_actor_key_free, + property_iter_free); + + timeline = clutter_timeline_new (2000); + clutter_animator_set_timeline (animator, timeline); + g_object_unref (timeline); + + priv->slave_timeline = clutter_timeline_new (10000); +} + + +/** + * clutter_animator_property_get_ease_in: + * @animator: a #ClutterAnimatorKey + * @object: a #GObject + * @property_name: the name of a property on object + * + * Checks if a property value is to be eased into the animation. + * + * Return value: %TRUE if the property is eased in + * + * Since: 1.2 + * Deprecated: 1.12: Use #ClutterKeyframeTransition instead + */ +gboolean +clutter_animator_property_get_ease_in (ClutterAnimator *animator, + GObject *object, + const gchar *property_name) +{ + ClutterAnimatorKey key, *initial_key; + GList *initial; + + g_return_val_if_fail (CLUTTER_IS_ANIMATOR (animator), FALSE); + g_return_val_if_fail (G_IS_OBJECT (object), FALSE); + g_return_val_if_fail (property_name, FALSE); + + key.object = object; + key.property_name = g_intern_string (property_name); + initial = g_list_find_custom (animator->priv->score, &key, + sort_actor_prop_func); + if (initial != NULL) + { + initial_key = initial->data; + + return initial_key->ease_in; + } + + return FALSE; +} + +/** + * clutter_animator_property_set_ease_in: + * @animator: a #ClutterAnimatorKey + * @object: a #GObject + * @property_name: the name of a property on object + * @ease_in: we are going to be easing in this property + * + * Sets whether a property value is to be eased into the animation. + * + * Since: 1.2 + * Deprecated: 1.12: Use #ClutterKeyframeTransition instead + */ +void +clutter_animator_property_set_ease_in (ClutterAnimator *animator, + GObject *object, + const gchar *property_name, + gboolean ease_in) +{ + ClutterAnimatorKey key, *initial_key; + GList *initial; + + g_return_if_fail (CLUTTER_IS_ANIMATOR (animator)); + g_return_if_fail (G_IS_OBJECT (object)); + g_return_if_fail (property_name); + + key.object = object; + key.property_name = g_intern_string (property_name); + initial = g_list_find_custom (animator->priv->score, &key, + sort_actor_prop_func); + if (initial) + { + initial_key = initial->data; + initial_key->ease_in = ease_in; + } + else + g_warning ("The animator has no object of type '%s' with a " + "property named '%s'", + G_OBJECT_TYPE_NAME (object), + property_name); +} + + +/** + * clutter_animator_property_get_interpolation: + * @animator: a #ClutterAnimatorKey + * @object: a #GObject + * @property_name: the name of a property on object + * + * Get the interpolation used by animator for a property on a particular + * object. + * + * Returns: a ClutterInterpolation value. + * Since: 1.2 + * Deprecated: 1.12: Use #ClutterKeyframeTransition instead + */ +ClutterInterpolation +clutter_animator_property_get_interpolation (ClutterAnimator *animator, + GObject *object, + const gchar *property_name) +{ + GList *initial; + ClutterAnimatorKey key, *initial_key; + + g_return_val_if_fail (CLUTTER_IS_ANIMATOR (animator), + CLUTTER_INTERPOLATION_LINEAR); + g_return_val_if_fail (G_IS_OBJECT (object), + CLUTTER_INTERPOLATION_LINEAR); + g_return_val_if_fail (property_name, + CLUTTER_INTERPOLATION_LINEAR); + + key.object = object; + key.property_name = g_intern_string (property_name); + initial = g_list_find_custom (animator->priv->score, &key, + sort_actor_prop_func); + if (initial) + { + initial_key = initial->data; + + return initial_key->interpolation; + } + + return CLUTTER_INTERPOLATION_LINEAR; +} + +/** + * clutter_animator_property_set_interpolation: + * @animator: a #ClutterAnimatorKey + * @object: a #GObject + * @property_name: the name of a property on object + * @interpolation: the #ClutterInterpolation to use + * + * Set the interpolation method to use, %CLUTTER_INTERPOLATION_LINEAR causes + * the values to linearly change between the values, and + * %CLUTTER_INTERPOLATION_CUBIC causes the values to smoothly change between + * the values. + * + * Since: 1.2 + * Deprecated: 1.12: Use #ClutterKeyframeTransition instead + */ +void +clutter_animator_property_set_interpolation (ClutterAnimator *animator, + GObject *object, + const gchar *property_name, + ClutterInterpolation interpolation) +{ + GList *initial; + ClutterAnimatorKey key, *initial_key; + + g_return_if_fail (CLUTTER_IS_ANIMATOR (animator)); + g_return_if_fail (G_IS_OBJECT (object)); + g_return_if_fail (property_name); + + key.object = object; + key.property_name = g_intern_string (property_name); + initial = g_list_find_custom (animator->priv->score, &key, + sort_actor_prop_func); + if (initial) + { + initial_key = initial->data; + initial_key->interpolation = interpolation; + } +} + +G_DEFINE_BOXED_TYPE (ClutterAnimatorKey, clutter_animator_key, + clutter_animator_key_copy, + clutter_animator_key_free); + +/** + * clutter_animator_key_get_object: + * @key: a #ClutterAnimatorKey + * + * Retrieves the object a key applies to. + * + * Return value: (transfer none): the object an animator_key exist for. + * + * Since: 1.2 + * Deprecated: 1.12: Use #ClutterKeyframeTransition instead + */ +GObject * +clutter_animator_key_get_object (const ClutterAnimatorKey *key) +{ + g_return_val_if_fail (key != NULL, NULL); + + return key->object; +} + +/** + * clutter_animator_key_get_property_name: + * @key: a #ClutterAnimatorKey + * + * Retrieves the name of the property a key applies to. + * + * Return value: the name of the property an animator_key exist for. + * + * Since: 1.2 + * Deprecated: 1.12: Use #ClutterKeyframeTransition instead + */ +const gchar * +clutter_animator_key_get_property_name (const ClutterAnimatorKey *key) +{ + g_return_val_if_fail (key != NULL, NULL); + + return key->property_name; +} + +/** + * clutter_animator_key_get_property_type: + * @key: a #ClutterAnimatorKey + * + * Retrieves the #GType of the property a key applies to + * + * You can use this type to initialize the #GValue to pass to + * clutter_animator_key_get_value() + * + * Return value: the #GType of the property + * + * Since: 1.2 + * Deprecated: 1.12: Use #ClutterKeyframeTransition instead + */ +GType +clutter_animator_key_get_property_type (const ClutterAnimatorKey *key) +{ + g_return_val_if_fail (key != NULL, G_TYPE_INVALID); + + return G_VALUE_TYPE (&key->value); +} + +/** + * clutter_animator_key_get_mode: + * @key: a #ClutterAnimatorKey + * + * Retrieves the mode of a #ClutterAnimator key, for the first key of a + * property for an object this represents the whether the animation is + * open ended and or curved for the remainding keys for the property it + * represents the easing mode. + * + * Return value: the mode of a #ClutterAnimatorKey + * + * Since: 1.2 + * Deprecated: 1.12: Use #ClutterKeyframeTransition instead + */ +gulong +clutter_animator_key_get_mode (const ClutterAnimatorKey *key) +{ + g_return_val_if_fail (key != NULL, 0); + + return key->mode; +} + +/** + * clutter_animator_key_get_progress: + * @key: a #ClutterAnimatorKey + * + * Retrieves the progress of an clutter_animator_key + * + * Return value: the progress defined for a #ClutterAnimator key. + * + * Since: 1.2 + * Deprecated: 1.12: Use #ClutterKeyframeTransition instead + */ +gdouble +clutter_animator_key_get_progress (const ClutterAnimatorKey *key) +{ + g_return_val_if_fail (key != NULL, 0.0); + + return key->progress; +} + +/** + * clutter_animator_key_get_value: + * @key: a #ClutterAnimatorKey + * @value: a #GValue initialized with the correct type for the animator key + * + * Retrieves a copy of the value for a #ClutterAnimatorKey. + * + * The passed in #GValue needs to be already initialized for the value + * type of the key or to a type that allow transformation from the value + * type of the key. + * + * Use g_value_unset() when done. + * + * Return value: %TRUE if the passed #GValue was successfully set, and + * %FALSE otherwise + * + * Since: 1.2 + * Deprecated: 1.12: Use #ClutterKeyframeTransition instead + */ +gboolean +clutter_animator_key_get_value (const ClutterAnimatorKey *key, + GValue *value) +{ + g_return_val_if_fail (key != NULL, FALSE); + g_return_val_if_fail (value != NULL, FALSE); + g_return_val_if_fail (G_VALUE_TYPE (value) != G_TYPE_INVALID, FALSE); + + if (!g_type_is_a (G_VALUE_TYPE (&key->value), G_VALUE_TYPE (value))) + { + if (g_value_type_compatible (G_VALUE_TYPE (&key->value), + G_VALUE_TYPE (value))) + { + g_value_copy (&key->value, value); + return TRUE; + } + + if (g_value_type_transformable (G_VALUE_TYPE (&key->value), + G_VALUE_TYPE (value))) + { + if (g_value_transform (&key->value, value)) + return TRUE; + } + + g_warning ("%s: Unable to convert from %s to %s for the " + "property '%s' of object %s in the animator key", + G_STRLOC, + g_type_name (G_VALUE_TYPE (&key->value)), + g_type_name (G_VALUE_TYPE (value)), + key->property_name, + G_OBJECT_TYPE_NAME (key->object)); + + return FALSE; + } + else + g_value_copy (&key->value, value); + + return TRUE; +} diff --git a/clutter/clutter/deprecated/clutter-animator.h b/clutter/clutter/deprecated/clutter-animator.h new file mode 100644 index 0000000..a72e27a --- /dev/null +++ b/clutter/clutter/deprecated/clutter-animator.h @@ -0,0 +1,188 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Øyvind KolÃ¥s + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_ANIMATOR_H__ +#define __CLUTTER_ANIMATOR_H__ + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_ANIMATOR (clutter_animator_get_type ()) +#define CLUTTER_TYPE_ANIMATOR_KEY (clutter_animator_key_get_type ()) + +#define CLUTTER_ANIMATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ANIMATOR, ClutterAnimator)) +#define CLUTTER_ANIMATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_ANIMATOR, ClutterAnimatorClass)) +#define CLUTTER_IS_ANIMATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ANIMATOR)) +#define CLUTTER_IS_ANIMATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_ANIMATOR)) +#define CLUTTER_ANIMATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_ANIMATOR, ClutterAnimatorClass)) + +/* ClutterAnimator is typedef in clutter-types.h */ + +typedef struct _ClutterAnimatorClass ClutterAnimatorClass; +typedef struct _ClutterAnimatorPrivate ClutterAnimatorPrivate; + +/** + * ClutterAnimatorKey: + * + * A key frame inside a #ClutterAnimator + * + * Since: 1.2 + * + * Deprecated: 1.12 + */ +typedef struct _ClutterAnimatorKey ClutterAnimatorKey; + +/** + * ClutterAnimator: + * + * The #ClutterAnimator structure contains only private data and + * should be accessed using the provided API + * + * Since: 1.2 + * + * Deprecated: 1.12 + */ +struct _ClutterAnimator +{ + /*< private >*/ + GObject parent_instance; + + ClutterAnimatorPrivate *priv; +}; + +/** + * ClutterAnimatorClass: + * + * The #ClutterAnimatorClass structure contains only private data + * + * Since: 1.2 + * + * Deprecated: 1.12 + */ +struct _ClutterAnimatorClass +{ + /*< private >*/ + GObjectClass parent_class; + + /* padding for future expansion */ + gpointer _padding_dummy[16]; +}; + +CLUTTER_DEPRECATED_IN_1_12 +GType clutter_animator_get_type (void) G_GNUC_CONST; + +CLUTTER_DEPRECATED_IN_1_12 +ClutterAnimator * clutter_animator_new (void); +CLUTTER_DEPRECATED_IN_1_12 +ClutterAnimator * clutter_animator_set_key (ClutterAnimator *animator, + GObject *object, + const gchar *property_name, + guint mode, + gdouble progress, + const GValue *value); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_animator_set (ClutterAnimator *animator, + gpointer first_object, + const gchar *first_property_name, + guint first_mode, + gdouble first_progress, + ...) G_GNUC_NULL_TERMINATED; +CLUTTER_DEPRECATED_IN_1_12 +GList * clutter_animator_get_keys (ClutterAnimator *animator, + GObject *object, + const gchar *property_name, + gdouble progress); + +CLUTTER_DEPRECATED_IN_1_12 +void clutter_animator_remove_key (ClutterAnimator *animator, + GObject *object, + const gchar *property_name, + gdouble progress); + +CLUTTER_DEPRECATED_IN_1_12 +ClutterTimeline * clutter_animator_start (ClutterAnimator *animator); + +CLUTTER_DEPRECATED_IN_1_12 +gboolean clutter_animator_compute_value (ClutterAnimator *animator, + GObject *object, + const gchar *property_name, + gdouble progress, + GValue *value); + +CLUTTER_DEPRECATED_IN_1_12 +ClutterTimeline * clutter_animator_get_timeline (ClutterAnimator *animator); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_animator_set_timeline (ClutterAnimator *animator, + ClutterTimeline *timeline); +CLUTTER_DEPRECATED_IN_1_12 +guint clutter_animator_get_duration (ClutterAnimator *animator); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_animator_set_duration (ClutterAnimator *animator, + guint duration); + +CLUTTER_DEPRECATED_IN_1_12 +gboolean clutter_animator_property_get_ease_in (ClutterAnimator *animator, + GObject *object, + const gchar *property_name); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_animator_property_set_ease_in (ClutterAnimator *animator, + GObject *object, + const gchar *property_name, + gboolean ease_in); + +CLUTTER_DEPRECATED_IN_1_12 +ClutterInterpolation clutter_animator_property_get_interpolation (ClutterAnimator *animator, + GObject *object, + const gchar *property_name); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_animator_property_set_interpolation (ClutterAnimator *animator, + GObject *object, + const gchar *property_name, + ClutterInterpolation interpolation); + +CLUTTER_DEPRECATED_IN_1_12 +GType clutter_animator_key_get_type (void) G_GNUC_CONST; +CLUTTER_DEPRECATED_IN_1_12 +GObject * clutter_animator_key_get_object (const ClutterAnimatorKey *key); +CLUTTER_DEPRECATED_IN_1_12 +const gchar * clutter_animator_key_get_property_name (const ClutterAnimatorKey *key); +CLUTTER_DEPRECATED_IN_1_12 +GType clutter_animator_key_get_property_type (const ClutterAnimatorKey *key); +CLUTTER_DEPRECATED_IN_1_12 +gulong clutter_animator_key_get_mode (const ClutterAnimatorKey *key); +CLUTTER_DEPRECATED_IN_1_12 +gdouble clutter_animator_key_get_progress (const ClutterAnimatorKey *key); +CLUTTER_DEPRECATED_IN_1_12 +gboolean clutter_animator_key_get_value (const ClutterAnimatorKey *key, + GValue *value); + +G_END_DECLS + +#endif /* __CLUTTER_ANIMATOR_H__ */ diff --git a/clutter/clutter/deprecated/clutter-backend.h b/clutter/clutter/deprecated/clutter-backend.h new file mode 100644 index 0000000..3fe0274 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-backend.h @@ -0,0 +1,64 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006, 2007, 2008 OpenedHand Ltd + * Copyright (C) 2009, 2010 Intel Corp + * + * 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 . + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_BACKEND_DEPRECATED_H__ +#define __CLUTTER_BACKEND_DEPRECATED_H__ + +#include + +G_BEGIN_DECLS + +CLUTTER_DEPRECATED_IN_1_4_FOR(ClutterSettings:font_dpi) +void clutter_backend_set_resolution (ClutterBackend *backend, + gdouble dpi); + +CLUTTER_DEPRECATED_IN_1_4_FOR(ClutterSettings:double_click_time) +void clutter_backend_set_double_click_time (ClutterBackend *backend, + guint msec); + +CLUTTER_DEPRECATED_IN_1_4_FOR(ClutterSettings:double_click_time) +guint clutter_backend_get_double_click_time (ClutterBackend *backend); + +CLUTTER_DEPRECATED_IN_1_4_FOR(ClutterSettings:double_click_distance) +void clutter_backend_set_double_click_distance (ClutterBackend *backend, + guint distance); + +CLUTTER_DEPRECATED_IN_1_4_FOR(ClutterSettings:double_click_distance) +guint clutter_backend_get_double_click_distance (ClutterBackend *backend); + +CLUTTER_DEPRECATED_IN_1_4_FOR(ClutterSettings:font_name) +void clutter_backend_set_font_name (ClutterBackend *backend, + const gchar *font_name); + +CLUTTER_DEPRECATED_IN_1_4_FOR(ClutterSettings:font_name) +const gchar * clutter_backend_get_font_name (ClutterBackend *backend); + + +G_END_DECLS + +#endif /* __CLUTTER_BACKEND_DEPRECATED_H__ */ diff --git a/clutter/clutter/deprecated/clutter-behaviour-depth.c b/clutter/clutter/deprecated/clutter-behaviour-depth.c new file mode 100644 index 0000000..9282ac8 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-behaviour-depth.c @@ -0,0 +1,305 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * Jorn Baayen + * Emmanuele Bassi + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS + +#include "deprecated/clutter-actor.h" +#include "clutter-alpha.h" +#include "clutter-behaviour.h" +#include "clutter-behaviour-depth.h" +#include "clutter-enum-types.h" +#include "clutter-main.h" +#include "clutter-debug.h" +#include "clutter-private.h" + +/** + * SECTION:clutter-behaviour-depth + * @Title: ClutterBehaviourDepth + * @short_description: A behaviour controlling the Z position + * @Deprecated: 1.6: Use clutter_actor_animate() instead + * + * #ClutterBehaviourDepth is a simple #ClutterBehaviour controlling the + * depth of a set of actors between a start and end depth. + * + * #ClutterBehaviourDepth is available since Clutter 0.4. + * + * Deprecated: 1.6: Use the #ClutterActor:depth property and + * clutter_actor_animate(), or #ClutterAnimator, or #ClutterState + * instead. + */ + +struct _ClutterBehaviourDepthPrivate +{ + gint depth_start; + gint depth_end; +}; + +enum +{ + PROP_0, + + PROP_DEPTH_START, + PROP_DEPTH_END +}; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterBehaviourDepth, + clutter_behaviour_depth, + CLUTTER_TYPE_BEHAVIOUR) + +static void +alpha_notify_foreach (ClutterBehaviour *behaviour, + ClutterActor *actor, + gpointer user_data) +{ + clutter_actor_set_depth (actor, GPOINTER_TO_INT (user_data)); +} + +static void +clutter_behaviour_depth_alpha_notify (ClutterBehaviour *behaviour, + gdouble alpha_value) +{ + ClutterBehaviourDepthPrivate *priv; + gint depth; + + priv = CLUTTER_BEHAVIOUR_DEPTH (behaviour)->priv; + + /* Need to create factor as to avoid borking signedness */ + depth = (alpha_value * (priv->depth_end - priv->depth_start)) + + priv->depth_start; + + CLUTTER_NOTE (ANIMATION, "alpha: %.4f, depth: %d", alpha_value, depth); + + clutter_behaviour_actors_foreach (behaviour, + alpha_notify_foreach, + GINT_TO_POINTER (depth)); +} + +static void +clutter_behaviour_depth_applied (ClutterBehaviour *behaviour, + ClutterActor *actor) +{ + ClutterBehaviourDepth *depth = CLUTTER_BEHAVIOUR_DEPTH (behaviour); + + clutter_actor_set_depth (actor, depth->priv->depth_start); +} + +static void +clutter_behaviour_depth_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterBehaviourDepth *depth = CLUTTER_BEHAVIOUR_DEPTH (gobject); + + switch (prop_id) + { + case PROP_DEPTH_START: + depth->priv->depth_start = g_value_get_int (value); + break; + case PROP_DEPTH_END: + depth->priv->depth_end = g_value_get_int (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_behaviour_depth_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterBehaviourDepth *depth = CLUTTER_BEHAVIOUR_DEPTH (gobject); + + switch (prop_id) + { + case PROP_DEPTH_START: + g_value_set_int (value, depth->priv->depth_start); + break; + case PROP_DEPTH_END: + g_value_set_int (value, depth->priv->depth_end); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_behaviour_depth_class_init (ClutterBehaviourDepthClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterBehaviourClass *behaviour_class = CLUTTER_BEHAVIOUR_CLASS (klass); + + gobject_class->set_property = clutter_behaviour_depth_set_property; + gobject_class->get_property = clutter_behaviour_depth_get_property; + + behaviour_class->alpha_notify = clutter_behaviour_depth_alpha_notify; + behaviour_class->applied = clutter_behaviour_depth_applied; + + /** + * ClutterBehaviourDepth:depth-start: + * + * Start depth level to apply to the actors. + * + * Since: 0.4 + * + * Deprecated: 1.6 + */ + g_object_class_install_property (gobject_class, + PROP_DEPTH_START, + g_param_spec_int ("depth-start", + P_("Start Depth"), + P_("Initial depth to apply"), + G_MININT, G_MAXINT, 0, + CLUTTER_PARAM_READWRITE)); + /** + * ClutterBehaviourDepth:depth-end: + * + * End depth level to apply to the actors. + * + * Since: 0.4 + * + * Deprecated: 1.6 + */ + g_object_class_install_property (gobject_class, + PROP_DEPTH_END, + g_param_spec_int ("depth-end", + P_("End Depth"), + P_("Final depth to apply"), + G_MININT, G_MAXINT, 0, + CLUTTER_PARAM_READWRITE)); +} + +static void +clutter_behaviour_depth_init (ClutterBehaviourDepth *depth) +{ + depth->priv = clutter_behaviour_depth_get_instance_private (depth); +} + +/** + * clutter_behaviour_depth_new: + * @alpha: (allow-none): a #ClutterAlpha instance, or %NULL + * @depth_start: initial value of the depth + * @depth_end: final value of the depth + * + * Creates a new #ClutterBehaviourDepth which can be used to control + * the ClutterActor:depth property of a set of #ClutterActors. + * + * If @alpha is not %NULL, the #ClutterBehaviour will take ownership + * of the #ClutterAlpha instance. In the case when @alpha is %NULL, + * it can be set later with clutter_behaviour_set_alpha(). + * + * Return value: (transfer full): the newly created behaviour + * + * Since: 0.4 + * + * Deprecated: 1.6 + */ +ClutterBehaviour * +clutter_behaviour_depth_new (ClutterAlpha *alpha, + gint depth_start, + gint depth_end) +{ + g_return_val_if_fail (alpha == NULL || CLUTTER_IS_ALPHA (alpha), NULL); + + return g_object_new (CLUTTER_TYPE_BEHAVIOUR_DEPTH, + "alpha", alpha, + "depth-start", depth_start, + "depth-end", depth_end, + NULL); +} + +/** + * clutter_behaviour_depth_set_bounds: + * @behaviour: a #ClutterBehaviourDepth + * @depth_start: initial value of the depth + * @depth_end: final value of the depth + * + * Sets the boundaries of the @behaviour. + * + * Since: 0.6 + * + * Deprecated: 1.6 + */ +void +clutter_behaviour_depth_set_bounds (ClutterBehaviourDepth *behaviour, + gint depth_start, + gint depth_end) +{ + ClutterBehaviourDepthPrivate *priv; + + g_return_if_fail (CLUTTER_IS_BEHAVIOUR_DEPTH (behaviour)); + + priv = behaviour->priv; + + g_object_freeze_notify (G_OBJECT (behaviour)); + + if (priv->depth_start != depth_start) + { + priv->depth_start = depth_start; + g_object_notify (G_OBJECT (behaviour), "depth-start"); + } + + if (priv->depth_end != depth_end) + { + priv->depth_end = depth_end; + g_object_notify (G_OBJECT (behaviour), "depth-end"); + } + + g_object_thaw_notify (G_OBJECT (behaviour)); +} + +/** + * clutter_behaviour_depth_get_bounds: + * @behaviour: a #ClutterBehaviourDepth + * @depth_start: (out): return location for the initial depth value, or %NULL + * @depth_end: (out): return location for the final depth value, or %NULL + * + * Gets the boundaries of the @behaviour + * + * Since: 0.6 + * + * Deprecated: 1.6 + */ +void +clutter_behaviour_depth_get_bounds (ClutterBehaviourDepth *behaviour, + gint *depth_start, + gint *depth_end) +{ + g_return_if_fail (CLUTTER_IS_BEHAVIOUR_DEPTH (behaviour)); + + if (depth_start) + *depth_start = behaviour->priv->depth_start; + + if (depth_end) + *depth_end = behaviour->priv->depth_end; +} diff --git a/clutter/clutter/deprecated/clutter-behaviour-depth.h b/clutter/clutter/deprecated/clutter-behaviour-depth.h new file mode 100644 index 0000000..b3b8ae1 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-behaviour-depth.h @@ -0,0 +1,101 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * Jorn Baayen + * Emmanuele Bassi + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_BEHAVIOUR_DEPTH__ +#define __CLUTTER_BEHAVIOUR_DEPTH__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BEHAVIOUR_DEPTH (clutter_behaviour_depth_get_type ()) +#define CLUTTER_BEHAVIOUR_DEPTH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BEHAVIOUR_DEPTH, ClutterBehaviourDepth)) +#define CLUTTER_IS_BEHAVIOUR_DEPTH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BEHAVIOUR_DEPTH)) +#define CLUTTER_BEHAVIOUR_DEPTH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BEHAVIOUR_DEPTH, ClutterBehaviourDepthClass)) +#define CLUTTER_IS_BEHAVIOUR_DEPTH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BEHAVIOUR_DEPTH)) +#define CLUTTER_BEHAVIOUR_DEPTH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BEHAVIOUR_DEPTH, ClutterBehaviourDepthClass)) + +typedef struct _ClutterBehaviourDepth ClutterBehaviourDepth; +typedef struct _ClutterBehaviourDepthPrivate ClutterBehaviourDepthPrivate; +typedef struct _ClutterBehaviourDepthClass ClutterBehaviourDepthClass; + +/** + * ClutterBehaviourDepth: + * + * The #ClutterBehaviourDepth structure contains only private data + * and should be accessed using the provided API + * + * Since: 0.2 + * + * Deprecated: 1.6: Use clutter_actor_animate() with #ClutterActor:depth + * instead. + */ +struct _ClutterBehaviourDepth +{ + /*< private >*/ + ClutterBehaviour parent_instance; + + ClutterBehaviourDepthPrivate *priv; +}; + +/** + * ClutterBehaviourDepthClass: + * + * The #ClutterBehaviourDepthClass structure contains only private data + * + * Since: 0.2 + * + * Deprecated: 1.6 + */ +struct _ClutterBehaviourDepthClass +{ + /*< private >*/ + ClutterBehaviourClass parent_class; +}; + +CLUTTER_DEPRECATED_IN_1_6 +GType clutter_behaviour_depth_get_type (void) G_GNUC_CONST; + +CLUTTER_DEPRECATED_IN_1_6_FOR(clutter_actor_animate and ClutterActor:depth) +ClutterBehaviour *clutter_behaviour_depth_new (ClutterAlpha *alpha, + gint depth_start, + gint depth_end); + +CLUTTER_DEPRECATED_IN_1_6 +void clutter_behaviour_depth_set_bounds (ClutterBehaviourDepth *behaviour, + gint depth_start, + gint depth_end); +CLUTTER_DEPRECATED_IN_1_6 +void clutter_behaviour_depth_get_bounds (ClutterBehaviourDepth *behaviour, + gint *depth_start, + gint *depth_end); + +G_END_DECLS + +#endif /* __CLUTTER_BEHAVIOUR_DEPTH__ */ diff --git a/clutter/clutter/deprecated/clutter-behaviour-ellipse.c b/clutter/clutter/deprecated/clutter-behaviour-ellipse.c new file mode 100644 index 0000000..659b752 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-behaviour-ellipse.c @@ -0,0 +1,1061 @@ + +/* -*- mode:C; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Tomas Frydrych + * + * Copyright (C) 2007 OpenedHand Ltd + * Copyright (C) 2009 Intel Corp. + * + * 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 . + */ + +/** + * SECTION:clutter-behaviour-ellipse + * @Title: ClutterBehaviourEllipse + * @short_description: A behaviour interpolating position along an ellipse + * @Deprecated: 1.6: Use clutter_actor_animate() instead + * + * #ClutterBehaviourEllipse interpolates actors along a path defined by + * an ellipse. + * + * When applying an ellipse behaviour to an actor, the + * behaviour will update the actor's position and depth and set them + * to what is dictated by the ellipses initial position. + * + * Deprecated: 1.6: Use clutter_actor_animate(), #ClutterPath and a + * #ClutterPathConstraint instead. + * + * Since: 0.4 + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include "deprecated/clutter-actor.h" + +#include "clutter-alpha.h" +#include "clutter-behaviour.h" +#include "clutter-behaviour-ellipse.h" +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-private.h" + +enum +{ + PROP_0, + + PROP_CENTER, + PROP_WIDTH, + PROP_HEIGHT, + PROP_ANGLE_START, + PROP_ANGLE_END, + PROP_ANGLE_TILT_X, + PROP_ANGLE_TILT_Y, + PROP_ANGLE_TILT_Z, + PROP_DIRECTION, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +struct _ClutterBehaviourEllipsePrivate +{ + ClutterKnot center; + + /* a = width / 2 */ + gint a; + + /* b = height / 2 */ + gint b; + + gdouble angle_start; + gdouble angle_end; + + gdouble angle_tilt_x; + gdouble angle_tilt_y; + gdouble angle_tilt_z; + + ClutterRotateDirection direction; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterBehaviourEllipse, + clutter_behaviour_ellipse, + CLUTTER_TYPE_BEHAVIOUR) + +typedef struct _knot3d +{ + gint x; + gint y; + gint z; +} knot3d; + +static void +clutter_behaviour_ellipse_advance (ClutterBehaviourEllipse *e, + float angle, + knot3d *knot) +{ + ClutterBehaviourEllipsePrivate *priv = e->priv; + gint x, y, z; + + x = priv->a * cosf (angle * (G_PI / 180.0)); + y = priv->b * sinf (angle * (G_PI / 180.0)); + z = 0; + + if (priv->angle_tilt_z) + { + /* + * x2 = r * cos (angle + tilt_z) + * y2 = r * sin (angle + tilt_z) + * + * These can be trasformed to the formulas below using properties of + * sin (a + b) and cos (a + b) + * + */ + gfloat x2, y2; + + x2 = x * cosf (priv->angle_tilt_z * (G_PI / 180.0)) + - y * sinf (priv->angle_tilt_z * (G_PI / 180.0)); + + y2 = y * cosf (priv->angle_tilt_z * (G_PI / 180.0)) + + x * sinf (priv->angle_tilt_z * (G_PI / 180.0)); + + x = (x2); + y = (y2); + } + + if (priv->angle_tilt_x) + { + gfloat z2, y2; + + z2 = - y * sinf (priv->angle_tilt_x * (G_PI / 180.0)); + y2 = y * cosf (priv->angle_tilt_x * (G_PI / 180.0)); + + z = z2; + y = y2; + } + + if (priv->angle_tilt_y) + { + gfloat x2, z2; + + x2 = x * cosf (priv->angle_tilt_y * (G_PI / 180.0)) + - z * sinf (priv->angle_tilt_y * (G_PI / 180.0)); + + z2 = z * cosf (priv->angle_tilt_y * (G_PI / 180.0)) + + x * sinf (priv->angle_tilt_y * (G_PI / 180.0)); + + x = x2; + z = z2; + } + + knot->x = x; + knot->y = y; + knot->z = z; + + CLUTTER_NOTE (ANIMATION, "advancing to angle %.2f [%d, %d] (a: %d, b: %d)", + angle, + knot->x, knot->y, + priv->a, priv->b); +} + + +static void +actor_apply_knot_foreach (ClutterBehaviour *behave, + ClutterActor *actor, + gpointer data) +{ + ClutterBehaviourEllipsePrivate *priv; + knot3d *knot = data; + + priv = ((ClutterBehaviourEllipse *) behave)->priv; + + clutter_actor_set_position (actor, knot->x, knot->y); + + if (priv->angle_tilt_x != 0 || priv->angle_tilt_y != 0) + clutter_actor_set_depth (actor, knot->z); +} + +static inline float +clamp_angle (float a) +{ + gint rounds; + + rounds = a / 360; + if (a < 0) + rounds--; + + return a - 360 * rounds; +} + +static void +clutter_behaviour_ellipse_alpha_notify (ClutterBehaviour *behave, + gdouble alpha) +{ + ClutterBehaviourEllipse *self = CLUTTER_BEHAVIOUR_ELLIPSE (behave); + ClutterBehaviourEllipsePrivate *priv = self->priv; + gfloat start, end; + gfloat angle = 0; + knot3d knot; + + /* we do everything in single precision because it's easier, even + * though all the parameters are stored in double precision for + * consistency with the equivalent ClutterActor API + */ + start = priv->angle_start; + end = priv->angle_end; + + if (priv->direction == CLUTTER_ROTATE_CW && start >= end) + end += 360; + else if (priv->direction == CLUTTER_ROTATE_CCW && start <= end) + end -= 360; + + angle = (end - start) * alpha + start; + + clutter_behaviour_ellipse_advance (self, angle, &knot); + + knot.x += priv->center.x; + knot.y += priv->center.y; + + clutter_behaviour_actors_foreach (behave, actor_apply_knot_foreach, &knot); +} + +static void +clutter_behaviour_ellipse_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterBehaviourEllipse *el = CLUTTER_BEHAVIOUR_ELLIPSE (gobject); + ClutterBehaviourEllipsePrivate *priv = el->priv; + + switch (prop_id) + { + case PROP_ANGLE_START: + priv->angle_start = g_value_get_double (value); + break; + + case PROP_ANGLE_END: + priv->angle_end = g_value_get_double (value); + break; + + case PROP_ANGLE_TILT_X: + priv->angle_tilt_x = g_value_get_double (value); + break; + + case PROP_ANGLE_TILT_Y: + priv->angle_tilt_y = g_value_get_double (value); + break; + + case PROP_ANGLE_TILT_Z: + priv->angle_tilt_z = g_value_get_double (value); + break; + + case PROP_WIDTH: + clutter_behaviour_ellipse_set_width (el, g_value_get_int (value)); + break; + + case PROP_HEIGHT: + clutter_behaviour_ellipse_set_height (el, g_value_get_int (value)); + break; + + case PROP_CENTER: + { + ClutterKnot *knot = g_value_get_boxed (value); + if (knot) + clutter_behaviour_ellipse_set_center (el, knot->x, knot->y); + } + break; + + case PROP_DIRECTION: + priv->direction = g_value_get_enum (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_behaviour_ellipse_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterBehaviourEllipsePrivate *priv; + + priv = CLUTTER_BEHAVIOUR_ELLIPSE (gobject)->priv; + + switch (prop_id) + { + case PROP_ANGLE_START: + g_value_set_double (value, priv->angle_start); + break; + + case PROP_ANGLE_END: + g_value_set_double (value, priv->angle_end); + break; + + case PROP_ANGLE_TILT_X: + g_value_set_double (value, priv->angle_tilt_x); + break; + + case PROP_ANGLE_TILT_Y: + g_value_set_double (value, priv->angle_tilt_y); + break; + + case PROP_ANGLE_TILT_Z: + g_value_set_double (value, priv->angle_tilt_z); + break; + + case PROP_WIDTH: + g_value_set_int (value, (priv->a * 2)); + break; + + case PROP_HEIGHT: + g_value_set_int (value, (priv->b * 2)); + break; + + case PROP_CENTER: + g_value_set_boxed (value, &priv->center); + break; + + case PROP_DIRECTION: + g_value_set_enum (value, priv->direction); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_behaviour_ellipse_applied (ClutterBehaviour *behave, + ClutterActor *actor) +{ + ClutterBehaviourEllipse *e = CLUTTER_BEHAVIOUR_ELLIPSE (behave); + ClutterBehaviourEllipsePrivate *priv = e->priv; + knot3d knot = { 0, }; + + clutter_behaviour_ellipse_advance (e, priv->angle_start, &knot); + + clutter_actor_set_position (actor, knot.x, knot.y); + + /* the depth should be changed only if there is a tilt on + * any of the X or the Y axis + */ + if (priv->angle_tilt_x != 0 || priv->angle_tilt_y != 0) + clutter_actor_set_depth (actor, knot.z); +} + +static void +clutter_behaviour_ellipse_class_init (ClutterBehaviourEllipseClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + ClutterBehaviourClass *behave_class = CLUTTER_BEHAVIOUR_CLASS (klass); + GParamSpec *pspec = NULL; + + object_class->set_property = clutter_behaviour_ellipse_set_property; + object_class->get_property = clutter_behaviour_ellipse_get_property; + + behave_class->alpha_notify = clutter_behaviour_ellipse_alpha_notify; + behave_class->applied = clutter_behaviour_ellipse_applied; + + /** + * ClutterBehaviourEllipse:angle-start: + * + * The initial angle from where the rotation should start. + * + * Since: 0.4 + */ + pspec = g_param_spec_double ("angle-start", + P_("Start Angle"), + P_("Initial angle"), + 0.0, 360.0, + 0.0, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_ANGLE_START] = pspec; + g_object_class_install_property (object_class, PROP_ANGLE_START, pspec); + + /** + * ClutterBehaviourEllipse:angle-end: + * + * The final angle to where the rotation should end. + * + * Since: 0.4 + */ + pspec = g_param_spec_double ("angle-end", + P_("End Angle"), + P_("Final angle"), + 0.0, 360.0, + 0.0, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_ANGLE_END] = pspec; + g_object_class_install_property (object_class, PROP_ANGLE_END, pspec); + + /** + * ClutterBehaviourEllipse:angle-tilt-x: + * + * The tilt angle for the rotation around center in X axis + * + * Since: 0.4 + */ + pspec = g_param_spec_double ("angle-tilt-x", + P_("Angle x tilt"), + P_("Tilt of the ellipse around x axis"), + 0.0, 360.0, + 360.0, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_ANGLE_TILT_X] = pspec; + g_object_class_install_property (object_class, PROP_ANGLE_TILT_X, pspec); + + /** + * ClutterBehaviourEllipse:angle-tilt-y: + * + * The tilt angle for the rotation around center in Y axis + * + * Since: 0.4 + */ + pspec = g_param_spec_double ("angle-tilt-y", + P_("Angle y tilt"), + P_("Tilt of the ellipse around y axis"), + 0.0, 360.0, + 360.0, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_ANGLE_TILT_Y] = pspec; + g_object_class_install_property (object_class, PROP_ANGLE_TILT_Y, pspec); + + /** + * ClutterBehaviourEllipse:angle-tilt-z: + * + * The tilt angle for the rotation on the Z axis + * + * Since: 0.4 + */ + pspec = g_param_spec_double ("angle-tilt-z", + P_("Angle z tilt"), + P_("Tilt of the ellipse around z axis"), + 0.0, 360.0, + 360.0, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_ANGLE_TILT_Z] = pspec; + g_object_class_install_property (object_class, PROP_ANGLE_TILT_Z, pspec); + + /** + * ClutterBehaviourEllipse:width: + * + * Width of the ellipse, in pixels + * + * Since: 0.4 + */ + pspec = g_param_spec_int ("width", + P_("Width"), + P_("Width of the ellipse"), + 0, G_MAXINT, + 100, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_WIDTH] = pspec; + g_object_class_install_property (object_class, PROP_WIDTH, pspec); + + /** + * ClutterBehaviourEllipse:height: + * + * Height of the ellipse, in pixels + * + * Since: 0.4 + */ + pspec = g_param_spec_int ("height", + P_("Height"), + P_("Height of ellipse"), + 0, G_MAXINT, + 50, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_HEIGHT] = pspec; + g_object_class_install_property (object_class, PROP_HEIGHT, pspec); + + /** + * ClutterBehaviourEllipse:center: + * + * The center of the ellipse. + * + * Since: 0.4 + */ + pspec = g_param_spec_boxed ("center", + P_("Center"), + P_("Center of ellipse"), + CLUTTER_TYPE_KNOT, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_CENTER] = pspec; + g_object_class_install_property (object_class, PROP_CENTER, pspec); + + /** + * ClutterBehaviourEllipse:direction: + * + * The direction of the rotation. + * + * Since: 0.4 + */ + pspec = g_param_spec_enum ("direction", + P_("Direction"), + P_("Direction of rotation"), + CLUTTER_TYPE_ROTATE_DIRECTION, + CLUTTER_ROTATE_CW, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_DIRECTION] = pspec; + g_object_class_install_property (object_class, PROP_DIRECTION, pspec); +} + +static void +clutter_behaviour_ellipse_init (ClutterBehaviourEllipse * self) +{ + ClutterBehaviourEllipsePrivate *priv; + + self->priv = priv = clutter_behaviour_ellipse_get_instance_private (self); + + priv->direction = CLUTTER_ROTATE_CW; + + priv->angle_start = 0; + priv->angle_end = 0; + + priv->a = 50; + priv->b = 25; + + priv->angle_tilt_x = 360; + priv->angle_tilt_y = 360; + priv->angle_tilt_z = 360; +} + +/** + * clutter_behaviour_ellipse_new: + * @alpha: (allow-none): a #ClutterAlpha instance, or %NULL + * @x: x coordinace of the center + * @y: y coordiance of the center + * @width: width of the ellipse + * @height: height of the ellipse + * @direction: #ClutterRotateDirection of rotation + * @start: angle in degrees at which movement starts, between 0 and 360 + * @end: angle in degrees at which movement ends, between 0 and 360 + * + * Creates a behaviour that drives actors along an elliptical path with + * given center, width and height; the movement starts at @start + * degrees (with 0 corresponding to 12 o'clock) and ends at @end + * degrees. Angles greated than 360 degrees get clamped to the canonical + * interval <0, 360); if @start is equal to @end, the behaviour will + * rotate by exacly 360 degrees. + * + * If @alpha is not %NULL, the #ClutterBehaviour will take ownership + * of the #ClutterAlpha instance. In the case when @alpha is %NULL, + * it can be set later with clutter_behaviour_set_alpha(). + * + * Return value: the newly created #ClutterBehaviourEllipse + * + * Since: 0.4 + */ +ClutterBehaviour * +clutter_behaviour_ellipse_new (ClutterAlpha *alpha, + gint x, + gint y, + gint width, + gint height, + ClutterRotateDirection direction, + gdouble start, + gdouble end) +{ + ClutterKnot center; + + g_return_val_if_fail (alpha == NULL || CLUTTER_IS_ALPHA (alpha), NULL); + + center.x = x; + center.y = y; + + return g_object_new (CLUTTER_TYPE_BEHAVIOUR_ELLIPSE, + "alpha", alpha, + "center", ¢er, + "width", width, + "height", height, + "direction", direction, + "angle-start", start, + "angle-end", end, + NULL); +} + +/** + * clutter_behaviour_ellipse_set_center: + * @self: a #ClutterBehaviourEllipse + * @x: x coordinace of centre + * @y: y coordinace of centre + * + * Sets the center of the elliptical path to the point represented by knot. + * + * Since: 0.4 + */ +void +clutter_behaviour_ellipse_set_center (ClutterBehaviourEllipse *self, + gint x, + gint y) +{ + ClutterBehaviourEllipsePrivate *priv; + + g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self)); + + priv = self->priv; + + if (priv->center.x != x || priv->center.y != y) + { + priv->center.x = x; + priv->center.y = y; + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_CENTER]); + } +} + +/** + * clutter_behaviour_ellipse_get_center: + * @self: a #ClutterBehaviourEllipse + * @x: (out): return location for the X coordinate of the center, or %NULL + * @y: (out): return location for the Y coordinate of the center, or %NULL + * + * Gets the center of the elliptical path path. + * + * Since: 0.4 + */ +void +clutter_behaviour_ellipse_get_center (ClutterBehaviourEllipse *self, + gint *x, + gint *y) +{ + ClutterBehaviourEllipsePrivate *priv; + + g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self)); + + priv = self->priv; + + if (x) + *x = priv->center.x; + + if (y) + *y = priv->center.y; +} + + +/** + * clutter_behaviour_ellipse_set_width: + * @self: a #ClutterBehaviourEllipse + * @width: width of the ellipse + * + * Sets the width of the elliptical path. + * + * Since: 0.4 + */ +void +clutter_behaviour_ellipse_set_width (ClutterBehaviourEllipse *self, + gint width) +{ + ClutterBehaviourEllipsePrivate *priv; + + g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self)); + + priv = self->priv; + + if (priv->a != width / 2) + { + priv->a = width / 2; + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_WIDTH]); + } +} + +/** + * clutter_behaviour_ellipse_get_width: + * @self: a #ClutterBehaviourEllipse + * + * Gets the width of the elliptical path. + * + * Return value: the width of the path + * + * Since: 0.4 + */ +gint +clutter_behaviour_ellipse_get_width (ClutterBehaviourEllipse *self) +{ + g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self), 0); + + return self->priv->a * 2; +} + +/** + * clutter_behaviour_ellipse_set_height: + * @self: a #ClutterBehaviourEllipse + * @height: height of the ellipse + * + * Sets the height of the elliptical path. + * + * Since: 0.4 + */ +void +clutter_behaviour_ellipse_set_height (ClutterBehaviourEllipse *self, + gint height) +{ + ClutterBehaviourEllipsePrivate *priv; + + g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self)); + + priv = self->priv; + + if (priv->b != height / 2) + { + priv->b = height / 2; + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_HEIGHT]); + } +} + +/** + * clutter_behaviour_ellipse_get_height: + * @self: a #ClutterBehaviourEllipse + * + * Gets the height of the elliptical path. + * + * Return value: the height of the path + * + * Since: 0.4 + */ +gint +clutter_behaviour_ellipse_get_height (ClutterBehaviourEllipse *self) +{ + g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self), 0); + + return self->priv->b * 2; +} + +/** + * clutter_behaviour_ellipse_set_angle_start: + * @self: a #ClutterBehaviourEllipse + * @angle_start: angle at which movement starts in degrees, between 0 and 360. + * + * Sets the angle at which movement starts; angles >= 360 degress get clamped + * to the canonical interval <0, 360). + * + * Since: 0.6 + */ +void +clutter_behaviour_ellipse_set_angle_start (ClutterBehaviourEllipse *self, + gdouble angle_start) +{ + ClutterBehaviourEllipsePrivate *priv; + gdouble new_angle; + + g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self)); + + new_angle = clamp_angle (angle_start); + + priv = self->priv; + + if (priv->angle_start != new_angle) + { + priv->angle_start = new_angle; + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ANGLE_START]); + } +} + +/** + * clutter_behaviour_ellipse_get_angle_start: + * @self: a #ClutterBehaviourEllipse + * + * Gets the angle at which movements starts. + * + * Return value: angle in degrees + * + * Since: 0.6 + */ +gdouble +clutter_behaviour_ellipse_get_angle_start (ClutterBehaviourEllipse *self) +{ + g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self), 0.0); + + return self->priv->angle_start; +} + +/** + * clutter_behaviour_ellipse_set_angle_end: + * @self: a #ClutterBehaviourEllipse + * @angle_end: angle at which movement ends in degrees, between 0 and 360. + * + * Sets the angle at which movement ends; angles >= 360 degress get clamped + * to the canonical interval <0, 360). + * + * Since: 0.4 + */ +void +clutter_behaviour_ellipse_set_angle_end (ClutterBehaviourEllipse *self, + gdouble angle_end) +{ + ClutterBehaviourEllipsePrivate *priv; + gdouble new_angle; + + g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self)); + + new_angle = clamp_angle (angle_end); + + priv = self->priv; + + if (priv->angle_end != new_angle) + { + priv->angle_end = new_angle; + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ANGLE_END]); + } +} + +/** + * clutter_behaviour_ellipse_get_angle_end: + * @self: a #ClutterBehaviourEllipse + * + * Gets the at which movements ends. + * + * Return value: angle in degrees + * + * Since: 0.4 + */ +gdouble +clutter_behaviour_ellipse_get_angle_end (ClutterBehaviourEllipse *self) +{ + g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self), 0.0); + + return self->priv->angle_end; +} + +/** + * clutter_behaviour_ellipse_set_angle_tilt: + * @self: a #ClutterBehaviourEllipse + * @axis: a #ClutterRotateAxis + * @angle_tilt: tilt of the elipse around the center in the given axis in + * degrees. + * + * Sets the angle at which the ellipse should be tilted around it's center. + * + * Since: 0.4 + */ +void +clutter_behaviour_ellipse_set_angle_tilt (ClutterBehaviourEllipse *self, + ClutterRotateAxis axis, + gdouble angle_tilt) +{ + ClutterBehaviourEllipsePrivate *priv; + + g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self)); + + priv = self->priv; + + switch (axis) + { + case CLUTTER_X_AXIS: + if (priv->angle_tilt_x != angle_tilt) + { + priv->angle_tilt_x = angle_tilt; + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ANGLE_TILT_X]); + } + break; + + case CLUTTER_Y_AXIS: + if (priv->angle_tilt_y != angle_tilt) + { + priv->angle_tilt_y = angle_tilt; + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ANGLE_TILT_Y]); + } + break; + + case CLUTTER_Z_AXIS: + if (priv->angle_tilt_z != angle_tilt) + { + priv->angle_tilt_z = angle_tilt; + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ANGLE_TILT_Z]); + } + break; + } +} + +/** + * clutter_behaviour_ellipse_get_angle_tilt: + * @self: a #ClutterBehaviourEllipse + * @axis: a #ClutterRotateAxis + * + * Gets the tilt of the ellipse around the center in the given axis. + * + * Return value: angle in degrees. + * + * Since: 0.4 + */ +gdouble +clutter_behaviour_ellipse_get_angle_tilt (ClutterBehaviourEllipse *self, + ClutterRotateAxis axis) +{ + g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self), 0.0); + + switch (axis) + { + case CLUTTER_X_AXIS: + return self->priv->angle_tilt_x; + + case CLUTTER_Y_AXIS: + return self->priv->angle_tilt_y; + + case CLUTTER_Z_AXIS: + return self->priv->angle_tilt_z; + } + + return 0.0; +} + +/** + * clutter_behaviour_ellipse_set_tilt: + * @self: a #ClutterBehaviourEllipse + * @angle_tilt_x: tilt of the elipse around the center in X axis in degrees. + * @angle_tilt_y: tilt of the elipse around the center in Y axis in degrees. + * @angle_tilt_z: tilt of the elipse around the center in Z axis in degrees. + * + * Sets the angles at which the ellipse should be tilted around it's center. + * + * Since: 0.4 + */ +void +clutter_behaviour_ellipse_set_tilt (ClutterBehaviourEllipse *self, + gdouble angle_tilt_x, + gdouble angle_tilt_y, + gdouble angle_tilt_z) +{ + ClutterBehaviourEllipsePrivate *priv; + + g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self)); + + priv = self->priv; + + g_object_freeze_notify (G_OBJECT (self)); + + if (priv->angle_tilt_x != angle_tilt_x) + { + priv->angle_tilt_x = angle_tilt_x; + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ANGLE_TILT_X]); + } + + if (priv->angle_tilt_y != angle_tilt_y) + { + priv->angle_tilt_y = angle_tilt_y; + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ANGLE_TILT_Y]); + } + + if (priv->angle_tilt_z != angle_tilt_z) + { + priv->angle_tilt_z = angle_tilt_z; + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ANGLE_TILT_Z]); + } + + g_object_thaw_notify (G_OBJECT (self)); +} + +/** + * clutter_behaviour_ellipse_get_tilt: + * @self: a #ClutterBehaviourEllipse + * @angle_tilt_x: (out): return location for tilt angle on the X axis, or %NULL. + * @angle_tilt_y: (out): return location for tilt angle on the Y axis, or %NULL. + * @angle_tilt_z: (out): return location for tilt angle on the Z axis, or %NULL. + * + * Gets the tilt of the ellipse around the center in Y axis. + * + * Since: 0.4 + */ +void +clutter_behaviour_ellipse_get_tilt (ClutterBehaviourEllipse *self, + gdouble *angle_tilt_x, + gdouble *angle_tilt_y, + gdouble *angle_tilt_z) +{ + ClutterBehaviourEllipsePrivate *priv; + + g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self)); + + priv = self->priv; + + if (angle_tilt_x) + *angle_tilt_x = priv->angle_tilt_x; + + if (angle_tilt_y) + *angle_tilt_y = priv->angle_tilt_y; + + if (angle_tilt_z) + *angle_tilt_z = priv->angle_tilt_z; +} + +/** + * clutter_behaviour_ellipse_get_direction: + * @self: a #ClutterBehaviourEllipse + * + * Retrieves the #ClutterRotateDirection used by the ellipse behaviour. + * + * Return value: the rotation direction + * + * Since: 0.4 + */ +ClutterRotateDirection +clutter_behaviour_ellipse_get_direction (ClutterBehaviourEllipse *self) +{ + g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self), + CLUTTER_ROTATE_CW); + + return self->priv->direction; +} + +/** + * clutter_behaviour_ellipse_set_direction: + * @self: a #ClutterBehaviourEllipse + * @direction: the rotation direction + * + * Sets the rotation direction used by the ellipse behaviour. + * + * Since: 0.4 + */ +void +clutter_behaviour_ellipse_set_direction (ClutterBehaviourEllipse *self, + ClutterRotateDirection direction) +{ + ClutterBehaviourEllipsePrivate *priv; + + g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ELLIPSE (self)); + + priv = self->priv; + + if (priv->direction != direction) + { + priv->direction = direction; + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_DIRECTION]); + } +} diff --git a/clutter/clutter/deprecated/clutter-behaviour-ellipse.h b/clutter/clutter/deprecated/clutter-behaviour-ellipse.h new file mode 100644 index 0000000..bd9983f --- /dev/null +++ b/clutter/clutter/deprecated/clutter-behaviour-ellipse.h @@ -0,0 +1,159 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Tomas Frydrych + * + * Copyright (C) 2007 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_BEHAVIOUR_ELLIPSE_H__ +#define __CLUTTER_BEHAVIOUR_ELLIPSE_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BEHAVIOUR_ELLIPSE (clutter_behaviour_ellipse_get_type ()) + +#define CLUTTER_BEHAVIOUR_ELLIPSE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + CLUTTER_TYPE_BEHAVIOUR_ELLIPSE, ClutterBehaviourEllipse)) + +#define CLUTTER_BEHAVIOUR_ELLIPSE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + CLUTTER_TYPE_BEHAVIOUR_ELLIPSE, ClutterBehaviourEllipseClass)) + +#define CLUTTER_IS_BEHAVIOUR_ELLIPSE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + CLUTTER_TYPE_BEHAVIOUR_ELLIPSE)) + +#define CLUTTER_IS_BEHAVIOUR_ELLIPSE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + CLUTTER_TYPE_BEHAVIOUR_ELLIPSE)) + +#define CLUTTER_BEHAVIOUR_ELLIPSE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + CLUTTER_TYPE_BEHAVIOUR_ELLIPSE, ClutterBehaviourEllipseClass)) + +typedef struct _ClutterBehaviourEllipse ClutterBehaviourEllipse; +typedef struct _ClutterBehaviourEllipsePrivate ClutterBehaviourEllipsePrivate; +typedef struct _ClutterBehaviourEllipseClass ClutterBehaviourEllipseClass; + +/** + * ClutterBehaviourEllipse: + * + * The #ClutterBehaviourEllipse struct contains only private data + * and should be accessed using the provided API + * + * Since: 0.4 + * + * Deprecated: 1.6 + */ +struct _ClutterBehaviourEllipse +{ + /*< private >*/ + ClutterBehaviour parent_instance; + ClutterBehaviourEllipsePrivate *priv; +}; + +/** + * ClutterBehaviourEllipseClass: + * + * The #ClutterBehaviourEllipseClass struct contains only private data + * + * Since: 0.4 + * + * Deprecated: 1.6 + */ +struct _ClutterBehaviourEllipseClass +{ + /*< private >*/ + ClutterBehaviourClass parent_class; +}; + +CLUTTER_DEPRECATED_IN_1_8 +GType clutter_behaviour_ellipse_get_type (void) G_GNUC_CONST; + +CLUTTER_DEPRECATED_IN_1_8_FOR(clutter_actor_animate) +ClutterBehaviour * clutter_behaviour_ellipse_new (ClutterAlpha *alpha, + gint x, + gint y, + gint width, + gint height, + ClutterRotateDirection direction, + gdouble start, + gdouble end); + +CLUTTER_DEPRECATED_IN_1_8 +void clutter_behaviour_ellipse_set_center (ClutterBehaviourEllipse *self, + gint x, + gint y); +CLUTTER_DEPRECATED_IN_1_8 +void clutter_behaviour_ellipse_get_center (ClutterBehaviourEllipse *self, + gint *x, + gint *y); +CLUTTER_DEPRECATED_IN_1_6 +void clutter_behaviour_ellipse_set_width (ClutterBehaviourEllipse *self, + gint width); +CLUTTER_DEPRECATED_IN_1_6 +gint clutter_behaviour_ellipse_get_width (ClutterBehaviourEllipse *self); +CLUTTER_DEPRECATED_IN_1_6 +void clutter_behaviour_ellipse_set_height (ClutterBehaviourEllipse *self, + gint height); +CLUTTER_DEPRECATED_IN_1_6 +gint clutter_behaviour_ellipse_get_height (ClutterBehaviourEllipse *self); +CLUTTER_DEPRECATED_IN_1_6 +void clutter_behaviour_ellipse_set_angle_start (ClutterBehaviourEllipse *self, + gdouble angle_start); +CLUTTER_DEPRECATED_IN_1_6 +gdouble clutter_behaviour_ellipse_get_angle_start (ClutterBehaviourEllipse *self); +CLUTTER_DEPRECATED_IN_1_6 +void clutter_behaviour_ellipse_set_angle_end (ClutterBehaviourEllipse *self, + gdouble angle_end); +CLUTTER_DEPRECATED_IN_1_6 +gdouble clutter_behaviour_ellipse_get_angle_end (ClutterBehaviourEllipse *self); +CLUTTER_DEPRECATED_IN_1_6 +void clutter_behaviour_ellipse_set_angle_tilt (ClutterBehaviourEllipse *self, + ClutterRotateAxis axis, + gdouble angle_tilt); +CLUTTER_DEPRECATED_IN_1_6 +gdouble clutter_behaviour_ellipse_get_angle_tilt (ClutterBehaviourEllipse *self, + ClutterRotateAxis axis); +CLUTTER_DEPRECATED_IN_1_6 +void clutter_behaviour_ellipse_set_tilt (ClutterBehaviourEllipse *self, + gdouble angle_tilt_x, + gdouble angle_tilt_y, + gdouble angle_tilt_z); +CLUTTER_DEPRECATED_IN_1_6 +void clutter_behaviour_ellipse_get_tilt (ClutterBehaviourEllipse *self, + gdouble *angle_tilt_x, + gdouble *angle_tilt_y, + gdouble *angle_tilt_z); +CLUTTER_DEPRECATED_IN_1_6 +ClutterRotateDirection clutter_behaviour_ellipse_get_direction (ClutterBehaviourEllipse *self); +CLUTTER_DEPRECATED_IN_1_6 +void clutter_behaviour_ellipse_set_direction (ClutterBehaviourEllipse *self, + ClutterRotateDirection direction); + +G_END_DECLS + +#endif /* __CLUTTER_BEHAVIOUR_ELLIPSE_H__ */ diff --git a/clutter/clutter/deprecated/clutter-behaviour-opacity.c b/clutter/clutter/deprecated/clutter-behaviour-opacity.c new file mode 100644 index 0000000..26fb47f --- /dev/null +++ b/clutter/clutter/deprecated/clutter-behaviour-opacity.c @@ -0,0 +1,312 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +/** + * SECTION:clutter-behaviour-opacity + * @Title: ClutterBehaviourOpacity + * @short_description: A behaviour controlling opacity + * @Deprecated: 1.6: Use clutter_actor_animate() instead. + * + * #ClutterBehaviourOpacity controls the opacity of a set of actors. + * + * Since: 0.2 + * + * Deprecated: 1.6: Use the #ClutterActor:opacity property and + * clutter_actor_animate(), or #ClutterAnimator, or #ClutterState + * instead. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS + +#include "clutter-alpha.h" +#include "clutter-behaviour.h" +#include "clutter-behaviour-opacity.h" +#include "clutter-private.h" +#include "clutter-debug.h" + +struct _ClutterBehaviourOpacityPrivate +{ + guint8 opacity_start; + guint8 opacity_end; +}; + +enum +{ + PROP_0, + + PROP_OPACITY_START, + PROP_OPACITY_END, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterBehaviourOpacity, + clutter_behaviour_opacity, + CLUTTER_TYPE_BEHAVIOUR) + +static void +alpha_notify_foreach (ClutterBehaviour *behaviour, + ClutterActor *actor, + gpointer data) +{ + clutter_actor_set_opacity (actor, GPOINTER_TO_UINT(data)); +} + +static void +clutter_behaviour_alpha_notify (ClutterBehaviour *behave, + gdouble alpha_value) +{ + ClutterBehaviourOpacityPrivate *priv; + guint8 opacity; + + priv = CLUTTER_BEHAVIOUR_OPACITY (behave)->priv; + + opacity = alpha_value + * (priv->opacity_end - priv->opacity_start) + + priv->opacity_start; + + CLUTTER_NOTE (ANIMATION, "alpha: %.4f, opacity: %u", + alpha_value, + opacity); + + clutter_behaviour_actors_foreach (behave, + alpha_notify_foreach, + GUINT_TO_POINTER ((guint) opacity)); +} + +static void +clutter_behaviour_opacity_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterBehaviourOpacity *self = CLUTTER_BEHAVIOUR_OPACITY (gobject); + + switch (prop_id) + { + case PROP_OPACITY_START: + clutter_behaviour_opacity_set_bounds (self, + g_value_get_uint (value), + self->priv->opacity_end); + break; + + case PROP_OPACITY_END: + clutter_behaviour_opacity_set_bounds (self, + self->priv->opacity_start, + g_value_get_uint (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_behaviour_opacity_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterBehaviourOpacity *self = CLUTTER_BEHAVIOUR_OPACITY (gobject); + + switch (prop_id) + { + case PROP_OPACITY_START: + g_value_set_uint (value, self->priv->opacity_start); + break; + + case PROP_OPACITY_END: + g_value_set_uint (value, self->priv->opacity_end); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_behaviour_opacity_class_init (ClutterBehaviourOpacityClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterBehaviourClass *behave_class = CLUTTER_BEHAVIOUR_CLASS (klass); + GParamSpec *pspec; + + gobject_class->set_property = clutter_behaviour_opacity_set_property; + gobject_class->get_property = clutter_behaviour_opacity_get_property; + + /** + * ClutterBehaviourOpacity:opacity-start: + * + * Initial opacity level of the behaviour. + * + * Since: 0.2 + * + * Deprecated: 1.6 + */ + pspec = g_param_spec_uint ("opacity-start", + P_("Opacity Start"), + P_("Initial opacity level"), + 0, 255, + 0, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_OPACITY_START] = pspec; + g_object_class_install_property (gobject_class, PROP_OPACITY_START, pspec); + + /** + * ClutterBehaviourOpacity:opacity-end: + * + * Final opacity level of the behaviour. + * + * Since: 0.2 + * + * Deprecated: 1.6 + */ + pspec = g_param_spec_uint ("opacity-end", + P_("Opacity End"), + P_("Final opacity level"), + 0, 255, + 0, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_OPACITY_END] = pspec; + g_object_class_install_property (gobject_class, PROP_OPACITY_END, pspec); + + behave_class->alpha_notify = clutter_behaviour_alpha_notify; +} + +static void +clutter_behaviour_opacity_init (ClutterBehaviourOpacity *self) +{ + self->priv = clutter_behaviour_opacity_get_instance_private (self); +} + +/** + * clutter_behaviour_opacity_new: + * @alpha: (allow-none): a #ClutterAlpha instance, or %NULL + * @opacity_start: minimum level of opacity + * @opacity_end: maximum level of opacity + * + * Creates a new #ClutterBehaviourOpacity object, driven by @alpha + * which controls the opacity property of every actor, making it + * change in the interval between @opacity_start and @opacity_end. + * + * If @alpha is not %NULL, the #ClutterBehaviour will take ownership + * of the #ClutterAlpha instance. In the case when @alpha is %NULL, + * it can be set later with clutter_behaviour_set_alpha(). + * + * Return value: the newly created #ClutterBehaviourOpacity + * + * Since: 0.2 + * + * Deprecated: 1.6 + */ +ClutterBehaviour * +clutter_behaviour_opacity_new (ClutterAlpha *alpha, + guint8 opacity_start, + guint8 opacity_end) +{ + return g_object_new (CLUTTER_TYPE_BEHAVIOUR_OPACITY, + "alpha", alpha, + "opacity-start", opacity_start, + "opacity-end", opacity_end, + NULL); +} + +/** + * clutter_behaviour_opacity_set_bounds: + * @behaviour: a #ClutterBehaviourOpacity + * @opacity_start: minimum level of opacity + * @opacity_end: maximum level of opacity + * + * Sets the initial and final levels of the opacity applied by @behaviour + * on each actor it controls. + * + * Since: 0.6 + * + * Deprecated: 1.6 + */ +void +clutter_behaviour_opacity_set_bounds (ClutterBehaviourOpacity *behaviour, + guint8 opacity_start, + guint8 opacity_end) +{ + ClutterBehaviourOpacityPrivate *priv; + + g_return_if_fail (CLUTTER_IS_BEHAVIOUR_OPACITY (behaviour)); + + priv = behaviour->priv; + + g_object_freeze_notify (G_OBJECT (behaviour)); + + if (priv->opacity_start != opacity_start) + { + priv->opacity_start = opacity_start; + + g_object_notify_by_pspec (G_OBJECT (behaviour), obj_props[PROP_OPACITY_START]); + } + + if (priv->opacity_end != opacity_end) + { + priv->opacity_end = opacity_end; + + g_object_notify_by_pspec (G_OBJECT (behaviour), obj_props[PROP_OPACITY_END]); + } + + g_object_thaw_notify (G_OBJECT (behaviour)); +} + +/** + * clutter_behaviour_opacity_get_bounds: + * @behaviour: a #ClutterBehaviourOpacity + * @opacity_start: (out): return location for the minimum level of opacity, or %NULL + * @opacity_end: (out): return location for the maximum level of opacity, or %NULL + * + * Gets the initial and final levels of the opacity applied by @behaviour + * on each actor it controls. + * + * Since: 0.6 + * + * Deprecated: 1.6 + */ +void +clutter_behaviour_opacity_get_bounds (ClutterBehaviourOpacity *behaviour, + guint8 *opacity_start, + guint8 *opacity_end) +{ + g_return_if_fail (CLUTTER_IS_BEHAVIOUR_OPACITY (behaviour)); + + if (opacity_start) + *opacity_start = behaviour->priv->opacity_start; + + if (opacity_end) + *opacity_end = behaviour->priv->opacity_end; +} diff --git a/clutter/clutter/deprecated/clutter-behaviour-opacity.h b/clutter/clutter/deprecated/clutter-behaviour-opacity.h new file mode 100644 index 0000000..a8beef1 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-behaviour-opacity.h @@ -0,0 +1,115 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * Jorn Baayen + * Emmanuele Bassi + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_BEHAVIOUR_OPACITY_H__ +#define __CLUTTER_BEHAVIOUR_OPACITY_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BEHAVIOUR_OPACITY (clutter_behaviour_opacity_get_type ()) + +#define CLUTTER_BEHAVIOUR_OPACITY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + CLUTTER_TYPE_BEHAVIOUR_OPACITY, ClutterBehaviourOpacity)) + +#define CLUTTER_BEHAVIOUR_OPACITY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + CLUTTER_TYPE_BEHAVIOUR_OPACITY, ClutterBehaviourOpacityClass)) + +#define CLUTTER_IS_BEHAVIOUR_OPACITY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + CLUTTER_TYPE_BEHAVIOUR_OPACITY)) + +#define CLUTTER_IS_BEHAVIOUR_OPACITY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + CLUTTER_TYPE_BEHAVIOUR_OPACITY)) + +#define CLUTTER_BEHAVIOUR_OPACITY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + CLUTTER_TYPE_BEHAVIOUR_OPACITY, ClutterBehaviourOpacityClass)) + +typedef struct _ClutterBehaviourOpacity ClutterBehaviourOpacity; +typedef struct _ClutterBehaviourOpacityPrivate ClutterBehaviourOpacityPrivate; +typedef struct _ClutterBehaviourOpacityClass ClutterBehaviourOpacityClass; + +/** + * ClutterBehaviourOpacity: + * + * The #ClutterBehaviourOpacity structure contains only private data and + * should be accessed using the provided API + * + * Since: 0.2 + * + * Deprecated: 1.6: Use clutter_actor_animate() and #ClutterActor:opacity + * instead. + */ +struct _ClutterBehaviourOpacity +{ + /*< private >*/ + ClutterBehaviour parent; + ClutterBehaviourOpacityPrivate *priv; +}; + +/** + * ClutterBehaviourOpacityClass: + * + * The #ClutterBehaviourOpacityClass structure contains only private data + * + * Since: 0.2 + * + * Deprecated: 1.6 + */ +struct _ClutterBehaviourOpacityClass +{ + /*< private >*/ + ClutterBehaviourClass parent_class; +}; + +CLUTTER_DEPRECATED_IN_1_6 +GType clutter_behaviour_opacity_get_type (void) G_GNUC_CONST; + +CLUTTER_DEPRECATED_IN_1_6_FOR(clutter_actor_animate and ClutterActor:opacity) +ClutterBehaviour *clutter_behaviour_opacity_new (ClutterAlpha *alpha, + guint8 opacity_start, + guint8 opacity_end); + +CLUTTER_DEPRECATED_IN_1_6 +void clutter_behaviour_opacity_set_bounds (ClutterBehaviourOpacity *behaviour, + guint8 opacity_start, + guint8 opacity_end); +CLUTTER_DEPRECATED_IN_1_6 +void clutter_behaviour_opacity_get_bounds (ClutterBehaviourOpacity *behaviour, + guint8 *opacity_start, + guint8 *opacity_end); + +G_END_DECLS + +#endif /* __CLUTTER_BEHAVIOUR_OPACITY_H__ */ diff --git a/clutter/clutter/deprecated/clutter-behaviour-path.c b/clutter/clutter/deprecated/clutter-behaviour-path.c new file mode 100644 index 0000000..81064fa --- /dev/null +++ b/clutter/clutter/deprecated/clutter-behaviour-path.c @@ -0,0 +1,467 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By: + * Matthew Allum + * Neil Roberts + * + * Copyright (C) 2006, 2007, 2008 OpenedHand Ltd + * Copyright (C) 2009, 2010 Intel Corp + * + * 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 . + */ + +/** + * SECTION:clutter-behaviour-path + * @Title: ClutterBehaviourPath + * @short_description: A behaviour for moving actors along a #ClutterPath + * @Deprecated: 1.6: Use #ClutterPathConstraint and clutter_actor_animate() + * with the #ClutterPathConstraint:offset property instead. + * + * #ClutterBehaviourPath interpolates actors along a defined path. + * + * A path is described by a #ClutterPath object. The path can contain + * straight line parts and bezier curves. If the path contains + * %CLUTTER_PATH_MOVE_TO parts then the actors will jump to those + * coordinates. This can be used make disjoint paths. + * + * When creating a path behaviour in a #ClutterScript, you can specify + * the path property directly as a string. For example: + * + * |[ + * { + * "id" : "spline-path", + * "type" : "ClutterBehaviourPath", + * "path" : "M 50 50 L 100 100", + * "alpha" : { + * "timeline" : "main-timeline", + * "function" : "ramp + * } + * } + * ]| + * + * If the alpha function is a periodic function, i.e. it returns to + * 0.0 after reaching 1.0, then the actors will walk the path back to the + * starting #ClutterKnot. + * + * #ClutterBehaviourPath is available since Clutter 0.2 + * + * Deprecated: 1.6: Use #ClutterPath and #ClutterPathConstraint with + * clutter_actor_animate() instead. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS + +#include "clutter-alpha.h" +#include "clutter-behaviour.h" +#include "clutter-behaviour-path.h" +#include "clutter-bezier.h" +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-main.h" +#include "clutter-marshal.h" +#include "clutter-private.h" +#include "clutter-script-private.h" +#include "clutter-scriptable.h" + +#include + +struct _ClutterBehaviourPathPrivate +{ + ClutterPath *path; + guint last_knot_passed; +}; + +enum +{ + KNOT_REACHED, + + LAST_SIGNAL +}; + +static guint path_signals[LAST_SIGNAL] = { 0, }; + +enum +{ + PROP_0, + + PROP_PATH, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +static void clutter_scriptable_iface_init (ClutterScriptableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (ClutterBehaviourPath, + clutter_behaviour_path, + CLUTTER_TYPE_BEHAVIOUR, + G_ADD_PRIVATE (ClutterBehaviourPath) + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_SCRIPTABLE, + clutter_scriptable_iface_init)) + +static void +actor_apply_knot_foreach (ClutterBehaviour *behaviour, + ClutterActor *actor, + gpointer data) +{ + ClutterKnot *knot = data; + + CLUTTER_NOTE (ANIMATION, "Setting actor to %ix%i", knot->x, knot->y); + + clutter_actor_set_position (actor, knot->x, knot->y); +} + +static void +clutter_behaviour_path_alpha_notify (ClutterBehaviour *behave, + gdouble alpha_value) +{ + ClutterBehaviourPath *pathb = CLUTTER_BEHAVIOUR_PATH (behave); + ClutterBehaviourPathPrivate *priv = pathb->priv; + ClutterKnot position; + guint knot_num; + + if (priv->path) + knot_num = clutter_path_get_position (priv->path, alpha_value, &position); + else + { + memset (&position, 0, sizeof (position)); + knot_num = 0; + } + + clutter_behaviour_actors_foreach (behave, + actor_apply_knot_foreach, + &position); + + if (knot_num != priv->last_knot_passed) + { + g_signal_emit (behave, path_signals[KNOT_REACHED], 0, knot_num); + priv->last_knot_passed = knot_num; + } +} + +static void +clutter_behaviour_path_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterBehaviourPath *pathb = CLUTTER_BEHAVIOUR_PATH (gobject); + + switch (prop_id) + { + case PROP_PATH: + g_value_set_object (value, clutter_behaviour_path_get_path (pathb)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_behaviour_path_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterBehaviourPath *pathb = CLUTTER_BEHAVIOUR_PATH (gobject); + + switch (prop_id) + { + case PROP_PATH: + clutter_behaviour_path_set_path (pathb, g_value_get_object (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_behaviour_path_dispose (GObject *gobject) +{ + ClutterBehaviourPath *pathb = CLUTTER_BEHAVIOUR_PATH (gobject); + + clutter_behaviour_path_set_path (pathb, NULL); + + G_OBJECT_CLASS (clutter_behaviour_path_parent_class)->dispose (gobject); +} + +static void +clutter_behaviour_path_class_init (ClutterBehaviourPathClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterBehaviourClass *behave_class = CLUTTER_BEHAVIOUR_CLASS (klass); + GParamSpec *pspec; + + gobject_class->get_property = clutter_behaviour_path_get_property; + gobject_class->set_property = clutter_behaviour_path_set_property; + gobject_class->dispose = clutter_behaviour_path_dispose; + + pspec = g_param_spec_object ("path", + P_("Path"), + P_("The ClutterPath object representing the path " + "to animate along"), + CLUTTER_TYPE_PATH, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_PATH] = pspec; + g_object_class_install_property (gobject_class, PROP_PATH, pspec); + + /** + * ClutterBehaviourPath::knot-reached: + * @pathb: the object which received the signal + * @knot_num: the index of the #ClutterKnot reached + * + * This signal is emitted each time a node defined inside the path + * is reached. + * + * Since: 0.2 + * + * Deprecated: 1.6 + */ + path_signals[KNOT_REACHED] = + g_signal_new ("knot-reached", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterBehaviourPathClass, knot_reached), + NULL, NULL, + _clutter_marshal_VOID__UINT, + G_TYPE_NONE, 1, + G_TYPE_UINT); + + behave_class->alpha_notify = clutter_behaviour_path_alpha_notify; +} + +static ClutterScriptableIface *parent_scriptable_iface = NULL; + +static gboolean +clutter_behaviour_path_parse_custom_node (ClutterScriptable *scriptable, + ClutterScript *script, + GValue *value, + const gchar *name, + JsonNode *node) +{ + if (strcmp ("path", name) == 0) + { + ClutterPath *path; + GValue node_value = { 0 }; + + path = g_object_ref_sink (clutter_path_new ()); + + json_node_get_value (node, &node_value); + + if (!G_VALUE_HOLDS (&node_value, G_TYPE_STRING) + || !clutter_path_set_description (path, + g_value_get_string (&node_value))) + g_warning ("Invalid path description"); + + g_value_unset (&node_value); + + g_value_init (value, G_TYPE_OBJECT); + g_value_take_object (value, path); + + return TRUE; + } + /* chain up */ + else if (parent_scriptable_iface->parse_custom_node) + return parent_scriptable_iface->parse_custom_node (scriptable, script, + value, name, node); + else + return FALSE; +} + +static void +clutter_scriptable_iface_init (ClutterScriptableIface *iface) +{ + parent_scriptable_iface = g_type_interface_peek_parent (iface); + + if (!parent_scriptable_iface) + parent_scriptable_iface + = g_type_default_interface_peek (CLUTTER_TYPE_SCRIPTABLE); + + iface->parse_custom_node = clutter_behaviour_path_parse_custom_node; +} + +static void +clutter_behaviour_path_init (ClutterBehaviourPath *self) +{ + self->priv = clutter_behaviour_path_get_instance_private (self); + self->priv->last_knot_passed = G_MAXUINT; +} + +/** + * clutter_behaviour_path_new: + * @alpha: (allow-none): a #ClutterAlpha instance, or %NULL + * @path: a #ClutterPath or %NULL for an empty path + * + * Creates a new path behaviour. You can use this behaviour to drive + * actors along the nodes of a path, described by @path. + * + * This will claim the floating reference on the #ClutterPath so you + * do not need to unref if it. + * + * If @alpha is not %NULL, the #ClutterBehaviour will take ownership + * of the #ClutterAlpha instance. In the case when @alpha is %NULL, + * it can be set later with clutter_behaviour_set_alpha(). + * + * Return value: (transfer full): a #ClutterBehaviour + * + * Since: 0.2 + * + * Deprecated: 1.6 + */ +ClutterBehaviour * +clutter_behaviour_path_new (ClutterAlpha *alpha, + ClutterPath *path) +{ + return g_object_new (CLUTTER_TYPE_BEHAVIOUR_PATH, + "alpha", alpha, + "path", path, + NULL); +} + +/** + * clutter_behaviour_path_new_with_description: + * @alpha: (allow-none): a #ClutterAlpha instance, or %NULL + * @desc: a string description of the path + * + * Creates a new path behaviour using the path described by @desc. See + * clutter_path_add_string() for a description of the format. + * + * If @alpha is not %NULL, the #ClutterBehaviour will take ownership + * of the #ClutterAlpha instance. In the case when @alpha is %NULL, + * it can be set later with clutter_behaviour_set_alpha(). + * + * Return value: (transfer full): a #ClutterBehaviour + * + * Since: 1.0 + * + * Deprecated: 1.6 + */ +ClutterBehaviour * +clutter_behaviour_path_new_with_description (ClutterAlpha *alpha, + const gchar *desc) +{ + return g_object_new (CLUTTER_TYPE_BEHAVIOUR_PATH, + "alpha", alpha, + "path", clutter_path_new_with_description (desc), + NULL); +} + +/** + * clutter_behaviour_path_new_with_knots: + * @alpha: (allow-none): a #ClutterAlpha instance, or %NULL + * @knots: (array length=n_knots): an array of #ClutterKnots + * @n_knots: number of entries in @knots + * + * Creates a new path behaviour that will make the actors visit all of + * the given knots in order with straight lines in between. + * + * A path will be created where the first knot is used in a + * %CLUTTER_PATH_MOVE_TO and the subsequent knots are used in + * %CLUTTER_PATH_LINE_TOs. + * + * If @alpha is not %NULL, the #ClutterBehaviour will take ownership + * of the #ClutterAlpha instance. In the case when @alpha is %NULL, + * it can be set later with clutter_behaviour_set_alpha(). + * + * Return value: (transfer full): a #ClutterBehaviour + * + * Since: 1.0 + * + * Deprecated: 1.6 + */ +ClutterBehaviour * +clutter_behaviour_path_new_with_knots (ClutterAlpha *alpha, + const ClutterKnot *knots, + guint n_knots) +{ + ClutterPath *path = clutter_path_new (); + guint i; + + if (n_knots > 0) + { + clutter_path_add_move_to (path, knots[0].x, knots[0].y); + + for (i = 1; i < n_knots; i++) + clutter_path_add_line_to (path, knots[i].x, knots[i].y); + } + + return g_object_new (CLUTTER_TYPE_BEHAVIOUR_PATH, + "alpha", alpha, + "path", path, + NULL); +} + +/** + * clutter_behaviour_path_set_path: + * @pathb: the path behaviour + * @path: the new path to follow + * + * Change the path that the actors will follow. This will take the + * floating reference on the #ClutterPath so you do not need to unref + * it. + * + * Since: 1.0 + * + * Deprecated: 1.6 + */ +void +clutter_behaviour_path_set_path (ClutterBehaviourPath *pathb, + ClutterPath *path) +{ + ClutterBehaviourPathPrivate *priv; + + g_return_if_fail (CLUTTER_IS_BEHAVIOUR_PATH (pathb)); + + priv = pathb->priv; + + if (path) + g_object_ref_sink (path); + + if (priv->path) + g_object_unref (priv->path); + + priv->path = path; + + g_object_notify_by_pspec (G_OBJECT (pathb), obj_props[PROP_PATH]); +} + +/** + * clutter_behaviour_path_get_path: + * @pathb: a #ClutterBehaviourPath instance + * + * Get the current path of the behaviour + * + * Return value: (transfer none): the path + * + * Since: 1.0 + * + * Deprecated: 1.6 + */ +ClutterPath * +clutter_behaviour_path_get_path (ClutterBehaviourPath *pathb) +{ + g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR_PATH (pathb), NULL); + + return pathb->priv->path; +} diff --git a/clutter/clutter/deprecated/clutter-behaviour-path.h b/clutter/clutter/deprecated/clutter-behaviour-path.h new file mode 100644 index 0000000..f78ebcb --- /dev/null +++ b/clutter/clutter/deprecated/clutter-behaviour-path.h @@ -0,0 +1,135 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * Jorn Baayen + * Emmanuele Bassi + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_BEHAVIOUR_PATH_H__ +#define __CLUTTER_BEHAVIOUR_PATH_H__ + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BEHAVIOUR_PATH (clutter_behaviour_path_get_type ()) + +#define CLUTTER_BEHAVIOUR_PATH(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + CLUTTER_TYPE_BEHAVIOUR_PATH, ClutterBehaviourPath)) + +#define CLUTTER_BEHAVIOUR_PATH_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + CLUTTER_TYPE_BEHAVIOUR_PATH, ClutterBehaviourPathClass)) + +#define CLUTTER_IS_BEHAVIOUR_PATH(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + CLUTTER_TYPE_BEHAVIOUR_PATH)) + +#define CLUTTER_IS_BEHAVIOUR_PATH_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + CLUTTER_TYPE_BEHAVIOUR_PATH)) + +#define CLUTTER_BEHAVIOUR_PATH_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + CLUTTER_TYPE_BEHAVIOUR_PATH, ClutterBehaviourPathClass)) + +typedef struct _ClutterBehaviourPath ClutterBehaviourPath; +typedef struct _ClutterBehaviourPathPrivate ClutterBehaviourPathPrivate; +typedef struct _ClutterBehaviourPathClass ClutterBehaviourPathClass; + +/** + * ClutterBehaviourPath: + * + * The #ClutterBehaviourPath structure contains only private data + * and should be accessed using the provided API + * + * Since: 0.2 + * + * Deprecated: 1.6: Use #ClutterPathConstraint and clutter_actor_animate() + * instead. + */ +struct _ClutterBehaviourPath +{ + /*< private >*/ + ClutterBehaviour parent; + ClutterBehaviourPathPrivate *priv; +}; + +/** + * ClutterBehaviourPathClass: + * @knot_reached: signal class handler for the + * ClutterBehaviourPath::knot_reached signal + * + * The #ClutterBehaviourPathClass struct contains only private data + * + * Since: 0.2 + * + * Deprecated: 1.6 + */ +struct _ClutterBehaviourPathClass +{ + /*< private >*/ + ClutterBehaviourClass parent_class; + + /*< public >*/ + void (*knot_reached) (ClutterBehaviourPath *pathb, + guint knot_num); + + /*< private >*/ + void (*_clutter_path_1) (void); + void (*_clutter_path_2) (void); + void (*_clutter_path_3) (void); + void (*_clutter_path_4) (void); +}; + +CLUTTER_DEPRECATED_IN_1_6 +GType clutter_behaviour_path_get_type (void) G_GNUC_CONST; + +CLUTTER_DEPRECATED_IN_1_6_FOR(clutter_actor_animate) +ClutterBehaviour *clutter_behaviour_path_new (ClutterAlpha *alpha, + ClutterPath *path); + +CLUTTER_DEPRECATED_IN_1_6_FOR(clutter_actor_animate) +ClutterBehaviour *clutter_behaviour_path_new_with_description + (ClutterAlpha *alpha, + const gchar *desc); + +CLUTTER_DEPRECATED_IN_1_6_FOR(clutter_actor_animate) +ClutterBehaviour *clutter_behaviour_path_new_with_knots + (ClutterAlpha *alpha, + const ClutterKnot *knots, + guint n_knots); + +CLUTTER_DEPRECATED_IN_1_6 +void clutter_behaviour_path_set_path (ClutterBehaviourPath *pathb, + ClutterPath *path); +CLUTTER_DEPRECATED_IN_1_6 +ClutterPath * clutter_behaviour_path_get_path (ClutterBehaviourPath *pathb); + +G_END_DECLS + +#endif /* __CLUTTER_BEHAVIOUR_PATH_H__ */ diff --git a/clutter/clutter/deprecated/clutter-behaviour-rotate.c b/clutter/clutter/deprecated/clutter-behaviour-rotate.c new file mode 100644 index 0000000..7096e83 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-behaviour-rotate.c @@ -0,0 +1,690 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2007 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +/** + * SECTION:clutter-behaviour-rotate + * @short_description: A behaviour controlling rotation + * + * A #ClutterBehaviourRotate rotate actors between a starting and ending + * angle on a given axis. + * + * The #ClutterBehaviourRotate is available since version 0.4. + * + * Deprecated: 1.6: Use the #ClutterActor rotation properties and + * clutter_actor_animate(), or #ClutterAnimator, or #ClutterState + * instead. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include "deprecated/clutter-actor.h" + +#include "clutter-alpha.h" +#include "clutter-behaviour.h" +#include "clutter-behaviour-rotate.h" +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-main.h" +#include "clutter-private.h" + +struct _ClutterBehaviourRotatePrivate +{ + gdouble angle_start; + gdouble angle_end; + + ClutterRotateAxis axis; + ClutterRotateDirection direction; + + gint center_x; + gint center_y; + gint center_z; +}; + +enum +{ + PROP_0, + + PROP_ANGLE_START, + PROP_ANGLE_END, + PROP_AXIS, + PROP_DIRECTION, + PROP_CENTER_X, + PROP_CENTER_Y, + PROP_CENTER_Z, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterBehaviourRotate, + clutter_behaviour_rotate, + CLUTTER_TYPE_BEHAVIOUR) + +typedef struct { + gdouble angle; +} RotateFrameClosure; + +static void +alpha_notify_foreach (ClutterBehaviour *behaviour, + ClutterActor *actor, + gpointer data) +{ + RotateFrameClosure *closure = data; + ClutterBehaviourRotate *rotate_behaviour; + ClutterBehaviourRotatePrivate *priv; + + rotate_behaviour = CLUTTER_BEHAVIOUR_ROTATE (behaviour); + priv = rotate_behaviour->priv; + + clutter_actor_set_rotation (actor, priv->axis, + closure->angle, + priv->center_x, + priv->center_y, + priv->center_z); +} + +static inline float +clamp_angle (float a) +{ + float a1, a2; + gint rounds; + + rounds = a / 360.0; + a1 = rounds * 360.0; + a2 = a - a1; + + return a2; +} + +static void +clutter_behaviour_rotate_alpha_notify (ClutterBehaviour *behaviour, + gdouble alpha_value) +{ + ClutterBehaviourRotate *rotate_behaviour; + ClutterBehaviourRotatePrivate *priv; + RotateFrameClosure closure; + gdouble start, end; + + rotate_behaviour = CLUTTER_BEHAVIOUR_ROTATE (behaviour); + priv = rotate_behaviour->priv; + + closure.angle = 0; + start = priv->angle_start; + end = priv->angle_end; + + if (priv->direction == CLUTTER_ROTATE_CW && start >= end) + end += 360.0; + else if (priv->direction == CLUTTER_ROTATE_CCW && start <= end) + end -= 360.0; + + closure.angle = (end - start) * alpha_value + start; + + clutter_behaviour_actors_foreach (behaviour, + alpha_notify_foreach, + &closure); +} + +static void +clutter_behaviour_rotate_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterBehaviourRotate *rotate; + ClutterBehaviourRotatePrivate *priv; + + rotate = CLUTTER_BEHAVIOUR_ROTATE (gobject); + priv = rotate->priv; + + switch (prop_id) + { + case PROP_ANGLE_START: + priv->angle_start = g_value_get_double (value); + break; + + case PROP_ANGLE_END: + priv->angle_end = g_value_get_double (value); + break; + + case PROP_AXIS: + priv->axis = g_value_get_enum (value); + break; + + case PROP_DIRECTION: + priv->direction = g_value_get_enum (value); + break; + + case PROP_CENTER_X: + clutter_behaviour_rotate_set_center (rotate, + g_value_get_int (value), + priv->center_y, + priv->center_z); + break; + + case PROP_CENTER_Y: + clutter_behaviour_rotate_set_center (rotate, + priv->center_x, + g_value_get_int (value), + priv->center_z); + break; + + case PROP_CENTER_Z: + clutter_behaviour_rotate_set_center (rotate, + priv->center_x, + priv->center_y, + g_value_get_int (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_behaviour_rotate_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterBehaviourRotatePrivate *priv; + + priv = CLUTTER_BEHAVIOUR_ROTATE (gobject)->priv; + + switch (prop_id) + { + case PROP_ANGLE_START: + g_value_set_double (value, priv->angle_start); + break; + + case PROP_ANGLE_END: + g_value_set_double (value, priv->angle_end); + break; + + case PROP_AXIS: + g_value_set_enum (value, priv->axis); + break; + + case PROP_DIRECTION: + g_value_set_enum (value, priv->direction); + break; + + case PROP_CENTER_X: + g_value_set_int (value, priv->center_x); + break; + + case PROP_CENTER_Y: + g_value_set_int (value, priv->center_y); + break; + + case PROP_CENTER_Z: + g_value_set_int (value, priv->center_z); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_behaviour_rotate_class_init (ClutterBehaviourRotateClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterBehaviourClass *behaviour_class = CLUTTER_BEHAVIOUR_CLASS (klass); + GParamSpec *pspec = NULL; + + gobject_class->set_property = clutter_behaviour_rotate_set_property; + gobject_class->get_property = clutter_behaviour_rotate_get_property; + + behaviour_class->alpha_notify = clutter_behaviour_rotate_alpha_notify; + + /** + * ClutterBehaviourRotate:angle-start: + * + * The initial angle from whence the rotation should start. + * + * Since: 0.4 + */ + pspec = g_param_spec_double ("angle-start", + P_("Angle Begin"), + P_("Initial angle"), + 0.0, 360.0, + 0.0, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_ANGLE_START] = pspec; + g_object_class_install_property (gobject_class, + PROP_ANGLE_START, + pspec); + + /** + * ClutterBehaviourRotate:angle-end: + * + * The final angle to where the rotation should end. + * + * Since: 0.4 + */ + pspec = g_param_spec_double ("angle-end", + P_("Angle End"), + P_("Final angle"), + 0.0, 360.0, + 0.0, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_ANGLE_END] = pspec; + g_object_class_install_property (gobject_class, + PROP_ANGLE_END, + pspec); + + /** + * ClutterBehaviourRotate:axis: + * + * The axis of rotation. + * + * Since: 0.4 + */ + pspec = g_param_spec_enum ("axis", + P_("Axis"), + P_("Axis of rotation"), + CLUTTER_TYPE_ROTATE_AXIS, + CLUTTER_Z_AXIS, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_AXIS] = pspec; + g_object_class_install_property (gobject_class, + PROP_AXIS, + pspec); + + /** + * ClutterBehaviourRotate:direction: + * + * The direction of the rotation. + * + * Since: 0.4 + */ + pspec = g_param_spec_enum ("direction", + P_("Direction"), + P_("Direction of rotation"), + CLUTTER_TYPE_ROTATE_DIRECTION, + CLUTTER_ROTATE_CW, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_DIRECTION] = pspec; + g_object_class_install_property (gobject_class, + PROP_DIRECTION, + pspec); + + /** + * ClutterBehaviourRotate:center-x: + * + * The x center of rotation. + * + * Since: 0.4 + */ + pspec = g_param_spec_int ("center-x", + P_("Center X"), + P_("X coordinate of the center of rotation"), + -G_MAXINT, G_MAXINT, + 0, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_CENTER_X] = pspec; + g_object_class_install_property (gobject_class, + PROP_CENTER_X, + pspec); + + /** + * ClutterBehaviourRotate:center-y: + * + * The y center of rotation. + * + * Since: 0.4 + */ + pspec = g_param_spec_int ("center-y", + P_("Center Y"), + P_("Y coordinate of the center of rotation"), + -G_MAXINT, G_MAXINT, + 0, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_CENTER_Y] = pspec; + g_object_class_install_property (gobject_class, + PROP_CENTER_Y, + pspec); + + /** + * ClutterBehaviourRotate:center-z: + * + * The z center of rotation. + * + * Since: 0.4 + */ + pspec = g_param_spec_int ("center-z", + P_("Center Z"), + P_("Z coordinate of the center of rotation"), + -G_MAXINT, G_MAXINT, + 0, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_CENTER_Z] = pspec; + g_object_class_install_property (gobject_class, + PROP_CENTER_Z, + pspec); +} + +static void +clutter_behaviour_rotate_init (ClutterBehaviourRotate *self) +{ + self->priv = clutter_behaviour_rotate_get_instance_private (self); + + self->priv->angle_start = 0.0; + self->priv->angle_end = 0.0; + + self->priv->axis = CLUTTER_Z_AXIS; + self->priv->direction = CLUTTER_ROTATE_CW; + + self->priv->center_x = 0; + self->priv->center_y = 0; + self->priv->center_z = 0; +} + +/** + * clutter_behaviour_rotate_new: + * @alpha: (allow-none): a #ClutterAlpha instance, or %NULL + * @axis: the rotation axis + * @direction: the rotation direction + * @angle_start: the starting angle in degrees, between 0 and 360. + * @angle_end: the final angle in degrees, between 0 and 360. + * + * Creates a new #ClutterBehaviourRotate. This behaviour will rotate actors + * bound to it on @axis, following @direction, between @angle_start and + * @angle_end. Angles >= 360 degrees will be clamped to the canonical interval + * <0, 360), if angle_start == angle_end, the behaviour will carry out a + * single rotation of 360 degrees. + * + * If @alpha is not %NULL, the #ClutterBehaviour will take ownership + * of the #ClutterAlpha instance. In the case when @alpha is %NULL, + * it can be set later with clutter_behaviour_set_alpha(). + * + * Return value: the newly created #ClutterBehaviourRotate. + * + * Since: 0.4 + */ +ClutterBehaviour * +clutter_behaviour_rotate_new (ClutterAlpha *alpha, + ClutterRotateAxis axis, + ClutterRotateDirection direction, + gdouble angle_start, + gdouble angle_end) +{ + g_return_val_if_fail (alpha == NULL || CLUTTER_IS_ALPHA (alpha), NULL); + + return g_object_new (CLUTTER_TYPE_BEHAVIOUR_ROTATE, + "alpha", alpha, + "axis", axis, + "direction", direction, + "angle-start", angle_start, + "angle-end", angle_end, + NULL); +} + +/** + * clutter_behaviour_rotate_get_axis: + * @rotate: a #ClutterBehaviourRotate + * + * Retrieves the #ClutterRotateAxis used by the rotate behaviour. + * + * Return value: the rotation axis + * + * Since: 0.4 + */ +ClutterRotateAxis +clutter_behaviour_rotate_get_axis (ClutterBehaviourRotate *rotate) +{ + g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR_ROTATE (rotate), CLUTTER_Z_AXIS); + + return rotate->priv->axis; +} + +/** + * clutter_behaviour_rotate_set_axis: + * @rotate: a #ClutterBehaviourRotate + * @axis: a #ClutterRotateAxis + * + * Sets the axis used by the rotate behaviour. + * + * Since: 0.4 + */ +void +clutter_behaviour_rotate_set_axis (ClutterBehaviourRotate *rotate, + ClutterRotateAxis axis) +{ + ClutterBehaviourRotatePrivate *priv; + + g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ROTATE (rotate)); + + priv = rotate->priv; + + if (priv->axis != axis) + { + priv->axis = axis; + + g_object_notify_by_pspec (G_OBJECT (rotate), obj_props[PROP_AXIS]); + } +} + +/** + * clutter_behaviour_rotate_get_direction: + * @rotate: a #ClutterBehaviourRotate + * + * Retrieves the #ClutterRotateDirection used by the rotate behaviour. + * + * Return value: the rotation direction + * + * Since: 0.4 + */ +ClutterRotateDirection +clutter_behaviour_rotate_get_direction (ClutterBehaviourRotate *rotate) +{ + g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR_ROTATE (rotate), + CLUTTER_ROTATE_CW); + + return rotate->priv->direction; +} + +/** + * clutter_behaviour_rotate_set_direction: + * @rotate: a #ClutterBehaviourRotate + * @direction: the rotation direction + * + * Sets the rotation direction used by the rotate behaviour. + * + * Since: 0.4 + */ +void +clutter_behaviour_rotate_set_direction (ClutterBehaviourRotate *rotate, + ClutterRotateDirection direction) +{ + ClutterBehaviourRotatePrivate *priv; + + g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ROTATE (rotate)); + + priv = rotate->priv; + + if (priv->direction != direction) + { + priv->direction = direction; + + g_object_notify_by_pspec (G_OBJECT (rotate), obj_props[PROP_DIRECTION]); + } +} + +/** + * clutter_behaviour_rotate_get_bounds: + * @rotate: a #ClutterBehaviourRotate + * @angle_start: (out): return value for the initial angle + * @angle_end: (out): return value for the final angle + * + * Retrieves the rotation boundaries of the rotate behaviour. + * + * Since: 0.4 + */ +void +clutter_behaviour_rotate_get_bounds (ClutterBehaviourRotate *rotate, + gdouble *angle_start, + gdouble *angle_end) +{ + ClutterBehaviourRotatePrivate *priv; + + g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ROTATE (rotate)); + + priv = rotate->priv; + + if (angle_start) + *angle_start = priv->angle_start; + + if (angle_end) + *angle_end = priv->angle_end; +} + +/** + * clutter_behaviour_rotate_set_bounds: + * @rotate: a #ClutterBehaviourRotate + * @angle_start: initial angle in degrees, between 0 and 360. + * @angle_end: final angle in degrees, between 0 and 360. + * + * Sets the initial and final angles of a rotation behaviour; angles >= 360 + * degrees get clamped to the canonical interval <0, 360). + * + * Since: 0.4 + */ +void +clutter_behaviour_rotate_set_bounds (ClutterBehaviourRotate *rotate, + gdouble angle_start, + gdouble angle_end) +{ + ClutterBehaviourRotatePrivate *priv; + + g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ROTATE (rotate)); + + priv = rotate->priv; + + g_object_freeze_notify (G_OBJECT (rotate)); + + if (priv->angle_start != angle_start) + { + priv->angle_start = clamp_angle (angle_start); + + g_object_notify_by_pspec (G_OBJECT (rotate), obj_props[PROP_ANGLE_START]); + } + + if (priv->angle_end != angle_end) + { + priv->angle_end = clamp_angle (angle_end); + + g_object_notify_by_pspec (G_OBJECT (rotate), obj_props[PROP_ANGLE_END]); + } + + g_object_thaw_notify (G_OBJECT (rotate)); +} + +/** + * clutter_behaviour_rotate_set_center: + * @rotate: a #ClutterBehaviourRotate + * @x: X axis center of rotation + * @y: Y axis center of rotation + * @z: Z axis center of rotation + * + * Sets the center of rotation. The coordinates are relative to the plane + * normal to the rotation axis set with clutter_behaviour_rotate_set_axis(). + * + * Since: 0.4 + */ +void +clutter_behaviour_rotate_set_center (ClutterBehaviourRotate *rotate, + gint x, + gint y, + gint z) +{ + ClutterBehaviourRotatePrivate *priv; + + g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ROTATE (rotate)); + + priv = rotate->priv; + + g_object_freeze_notify (G_OBJECT (rotate)); + + if (priv->center_x != x) + { + priv->center_x = x; + g_object_notify_by_pspec (G_OBJECT (rotate), obj_props[PROP_CENTER_X]); + } + + if (priv->center_y != y) + { + priv->center_y = y; + g_object_notify_by_pspec (G_OBJECT (rotate), obj_props[PROP_CENTER_Y]); + } + + if (priv->center_z != z) + { + priv->center_z = z; + g_object_notify_by_pspec (G_OBJECT (rotate), obj_props[PROP_CENTER_Z]); + } + + g_object_thaw_notify (G_OBJECT (rotate)); +} + +/** + * clutter_behaviour_rotate_get_center: + * @rotate: a #ClutterBehaviourRotate + * @x: (out): return location for the X center of rotation + * @y: (out): return location for the Y center of rotation + * @z: (out): return location for the Z center of rotation + * + * Retrieves the center of rotation set using + * clutter_behaviour_rotate_set_center(). + * + * Since: 0.4 + */ +void +clutter_behaviour_rotate_get_center (ClutterBehaviourRotate *rotate, + gint *x, + gint *y, + gint *z) +{ + ClutterBehaviourRotatePrivate *priv; + + g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ROTATE (rotate)); + + priv = rotate->priv; + + if (x) + *x = priv->center_x; + + if (y) + *y = priv->center_y; + + if (z) + *z = priv->center_z; +} diff --git a/clutter/clutter/deprecated/clutter-behaviour-rotate.h b/clutter/clutter/deprecated/clutter-behaviour-rotate.h new file mode 100644 index 0000000..55f58b3 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-behaviour-rotate.h @@ -0,0 +1,119 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2007 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_BEHAVIOUR_ROTATE_H__ +#define __CLUTTER_BEHAVIOUR_ROTATE_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BEHAVIOUR_ROTATE (clutter_behaviour_rotate_get_type ()) +#define CLUTTER_BEHAVIOUR_ROTATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BEHAVIOUR_ROTATE, ClutterBehaviourRotate)) +#define CLUTTER_IS_BEHAVIOUR_ROTATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BEHAVIOUR_ROTATE)) +#define CLUTTER_BEHAVIOUR_ROTATE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BEHAVIOUR_ROTATE, ClutterBehaviourRotateClass)) +#define CLUTTER_IS_BEHAVIOUR_ROTATE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BEHAVIOUR_ROTATE)) +#define CLUTTER_BEHAVIOUR_ROTATE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((klass), CLUTTER_TYPE_BEHAVIOUR_ROTATE, ClutterBehaviourRotateClass)) + +typedef struct _ClutterBehaviourRotate ClutterBehaviourRotate; +typedef struct _ClutterBehaviourRotatePrivate ClutterBehaviourRotatePrivate; +typedef struct _ClutterBehaviourRotateClass ClutterBehaviourRotateClass; + +/** + * ClutterBehaviourRotate: + * + * The #ClutterBehaviourRotate struct contains only private data and + * should be accessed using the provided API + * + * Since: 0.4 + * + * Deprecated: 1.6: Use clutter_actor_animate() instead. + */ +struct _ClutterBehaviourRotate +{ + /*< private >*/ + ClutterBehaviour parent_instance; + + ClutterBehaviourRotatePrivate *priv; +}; + +/** + * ClutterBehaviourRotateClass: + * + * The #ClutterBehaviourRotateClass struct contains only private data + * + * Since: 0.4 + * + * Deprecated: 1.6 + */ +struct _ClutterBehaviourRotateClass +{ + /*< private >*/ + ClutterBehaviourClass parent_class; +}; + +CLUTTER_DEPRECATED_IN_1_6 +GType clutter_behaviour_rotate_get_type (void) G_GNUC_CONST; + +CLUTTER_DEPRECATED_IN_1_6_FOR(clutter_actor_animate) +ClutterBehaviour * clutter_behaviour_rotate_new (ClutterAlpha *alpha, + ClutterRotateAxis axis, + ClutterRotateDirection direction, + gdouble angle_start, + gdouble angle_end); +CLUTTER_DEPRECATED_IN_1_6 +void clutter_behaviour_rotate_get_center (ClutterBehaviourRotate *rotate, + gint *x, + gint *y, + gint *z); +CLUTTER_DEPRECATED_IN_1_6 +void clutter_behaviour_rotate_set_center (ClutterBehaviourRotate *rotate, + gint x, + gint y, + gint z); +CLUTTER_DEPRECATED_IN_1_6 +ClutterRotateAxis clutter_behaviour_rotate_get_axis (ClutterBehaviourRotate *rotate); +CLUTTER_DEPRECATED_IN_1_6 +void clutter_behaviour_rotate_set_axis (ClutterBehaviourRotate *rotate, + ClutterRotateAxis axis); +CLUTTER_DEPRECATED_IN_1_6 +ClutterRotateDirection clutter_behaviour_rotate_get_direction (ClutterBehaviourRotate *rotate); +CLUTTER_DEPRECATED_IN_1_6 +void clutter_behaviour_rotate_set_direction (ClutterBehaviourRotate *rotate, + ClutterRotateDirection direction); +CLUTTER_DEPRECATED_IN_1_6 +void clutter_behaviour_rotate_get_bounds (ClutterBehaviourRotate *rotate, + gdouble *angle_start, + gdouble *angle_end); +CLUTTER_DEPRECATED_IN_1_6 +void clutter_behaviour_rotate_set_bounds (ClutterBehaviourRotate *rotate, + gdouble angle_start, + gdouble angle_end); + +G_END_DECLS + +#endif /* __CLUTTER_BEHAVIOUR_ROTATE_H__ */ diff --git a/clutter/clutter/deprecated/clutter-behaviour-scale.c b/clutter/clutter/deprecated/clutter-behaviour-scale.c new file mode 100644 index 0000000..82976fd --- /dev/null +++ b/clutter/clutter/deprecated/clutter-behaviour-scale.c @@ -0,0 +1,439 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +/** + * SECTION:clutter-behaviour-scale + * @Title: ClutterBehaviourScale + * @short_description: A behaviour controlling scale + * @Deprecated: 1.6: Use clutter_actor_animate() with #ClutterActor:scale-x + * and #ClutterActor:scale-y instead. + * + * A #ClutterBehaviourScale interpolates actors size between two values. + * + * Deprecated: 1.6: Use the #ClutterActor:scale-x and #ClutterActor:scale-y + * properties, and clutter_actor_animate(), or #ClutterAnimator or + * #ClutterState instead. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include "deprecated/clutter-actor.h" + +#include "clutter-alpha.h" +#include "clutter-behaviour.h" +#include "clutter-behaviour-scale.h" +#include "clutter-debug.h" +#include "clutter-main.h" +#include "clutter-private.h" + +struct _ClutterBehaviourScalePrivate +{ + gdouble x_scale_start; + gdouble y_scale_start; + + gdouble x_scale_end; + gdouble y_scale_end; +}; + +enum +{ + PROP_0, + + PROP_X_SCALE_START, + PROP_Y_SCALE_START, + PROP_X_SCALE_END, + PROP_Y_SCALE_END, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterBehaviourScale, + clutter_behaviour_scale, + CLUTTER_TYPE_BEHAVIOUR) + +typedef struct { + gdouble scale_x; + gdouble scale_y; +} ScaleFrameClosure; + +static void +scale_frame_foreach (ClutterBehaviour *behaviour, + ClutterActor *actor, + gpointer data) +{ + ScaleFrameClosure *closure = data; + + clutter_actor_set_scale (actor, closure->scale_x, closure->scale_y); +} + +static void +clutter_behaviour_scale_alpha_notify (ClutterBehaviour *behave, + gdouble alpha_value) +{ + ClutterBehaviourScalePrivate *priv; + ScaleFrameClosure closure = { 0, }; + + priv = CLUTTER_BEHAVIOUR_SCALE (behave)->priv; + + /* Fix the start/end values, avoids potential rounding errors on large + * values. + */ + if (alpha_value == 1.0) + { + closure.scale_x = priv->x_scale_end; + closure.scale_y = priv->y_scale_end; + } + else if (alpha_value == 0) + { + closure.scale_x = priv->x_scale_start; + closure.scale_y = priv->y_scale_start; + } + else + { + closure.scale_x = (priv->x_scale_end - priv->x_scale_start) + * alpha_value + + priv->x_scale_start; + + closure.scale_y = (priv->y_scale_end - priv->y_scale_start) + * alpha_value + + priv->y_scale_start; + } + + clutter_behaviour_actors_foreach (behave, + scale_frame_foreach, + &closure); +} + +static void +clutter_behaviour_scale_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterBehaviourScalePrivate *priv; + + priv = CLUTTER_BEHAVIOUR_SCALE (gobject)->priv; + + switch (prop_id) + { + case PROP_X_SCALE_START: + priv->x_scale_start = g_value_get_double (value); + break; + + case PROP_X_SCALE_END: + priv->x_scale_end = g_value_get_double (value); + break; + + case PROP_Y_SCALE_START: + priv->y_scale_start = g_value_get_double (value); + break; + + case PROP_Y_SCALE_END: + priv->y_scale_end = g_value_get_double (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_behaviour_scale_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterBehaviourScalePrivate *priv; + + priv = CLUTTER_BEHAVIOUR_SCALE (gobject)->priv; + + switch (prop_id) + { + case PROP_X_SCALE_START: + g_value_set_double (value, priv->x_scale_start); + break; + + case PROP_X_SCALE_END: + g_value_set_double (value, priv->x_scale_end); + break; + + case PROP_Y_SCALE_START: + g_value_set_double (value, priv->y_scale_start); + break; + + case PROP_Y_SCALE_END: + g_value_set_double (value, priv->y_scale_end); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_behaviour_scale_class_init (ClutterBehaviourScaleClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterBehaviourClass *behave_class = CLUTTER_BEHAVIOUR_CLASS (klass); + GParamSpec *pspec = NULL; + + gobject_class->set_property = clutter_behaviour_scale_set_property; + gobject_class->get_property = clutter_behaviour_scale_get_property; + + /** + * ClutterBehaviourScale:x-scale-start: + * + * The initial scaling factor on the X axis for the actors. + * + * Since: 0.6 + * + * Deprecated: 1.6 + */ + pspec = g_param_spec_double ("x-scale-start", + P_("X Start Scale"), + P_("Initial scale on the X axis"), + 0.0, G_MAXDOUBLE, + 1.0, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_X_SCALE_START] = pspec; + g_object_class_install_property (gobject_class, + PROP_X_SCALE_START, + pspec); + /** + * ClutterBehaviourScale:x-scale-end: + * + * The final scaling factor on the X axis for the actors. + * + * Since: 0.6 + * + * Deprecated: 1.6 + */ + pspec = g_param_spec_double ("x-scale-end", + P_("X End Scale"), + P_("Final scale on the X axis"), + 0.0, G_MAXDOUBLE, + 1.0, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_X_SCALE_END] = pspec; + g_object_class_install_property (gobject_class, + PROP_X_SCALE_END, + pspec); + /** + * ClutterBehaviourScale:y-scale-start: + * + * The initial scaling factor on the Y axis for the actors. + * + * Since: 0.6 + * + * Deprecated: 1.6 + */ + pspec = g_param_spec_double ("y-scale-start", + P_("Y Start Scale"), + P_("Initial scale on the Y axis"), + 0.0, G_MAXDOUBLE, + 1.0, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_Y_SCALE_START] = pspec; + g_object_class_install_property (gobject_class, + PROP_Y_SCALE_START, + pspec); + /** + * ClutterBehaviourScale:y-scale-end: + * + * The final scaling factor on the Y axis for the actors. + * + * Since: 0.6 + * + * Deprecated: 1.6 + */ + pspec = g_param_spec_double ("y-scale-end", + P_("Y End Scale"), + P_("Final scale on the Y axis"), + 0.0, G_MAXDOUBLE, + 1.0, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_Y_SCALE_END] = pspec; + g_object_class_install_property (gobject_class, + PROP_Y_SCALE_END, + pspec); + + behave_class->alpha_notify = clutter_behaviour_scale_alpha_notify; +} + +static void +clutter_behaviour_scale_init (ClutterBehaviourScale *self) +{ + ClutterBehaviourScalePrivate *priv; + + self->priv = priv = clutter_behaviour_scale_get_instance_private (self); + + priv->x_scale_start = priv->x_scale_end = 1.0; + priv->y_scale_start = priv->y_scale_end = 1.0; +} + +/** + * clutter_behaviour_scale_new: + * @alpha: (allow-none): a #ClutterAlpha instance, or %NULL + * @x_scale_start: initial scale factor on the X axis + * @y_scale_start: initial scale factor on the Y axis + * @x_scale_end: final scale factor on the X axis + * @y_scale_end: final scale factor on the Y axis + * + * Creates a new #ClutterBehaviourScale instance. + * + * If @alpha is not %NULL, the #ClutterBehaviour will take ownership + * of the #ClutterAlpha instance. In the case when @alpha is %NULL, + * it can be set later with clutter_behaviour_set_alpha(). + * + * Return value: (transfer full): the newly created #ClutterBehaviourScale + * + * Since: 0.2 + * + * Deprecated: 1.6 + */ +ClutterBehaviour * +clutter_behaviour_scale_new (ClutterAlpha *alpha, + gdouble x_scale_start, + gdouble y_scale_start, + gdouble x_scale_end, + gdouble y_scale_end) +{ + g_return_val_if_fail (alpha == NULL || CLUTTER_IS_ALPHA (alpha), NULL); + + return g_object_new (CLUTTER_TYPE_BEHAVIOUR_SCALE, + "alpha", alpha, + "x-scale-start", x_scale_start, + "y-scale-start", y_scale_start, + "x-scale-end", x_scale_end, + "y-scale-end", y_scale_end, + NULL); +} + +/** + * clutter_behaviour_scale_set_bounds: + * @scale: a #ClutterBehaviourScale + * @x_scale_start: initial scale factor on the X axis + * @y_scale_start: initial scale factor on the Y axis + * @x_scale_end: final scale factor on the X axis + * @y_scale_end: final scale factor on the Y axis + * + * Sets the bounds used by scale behaviour. + * + * Since: 0.6 + * + * Deprecated: 1.6 + */ +void +clutter_behaviour_scale_set_bounds (ClutterBehaviourScale *scale, + gdouble x_scale_start, + gdouble y_scale_start, + gdouble x_scale_end, + gdouble y_scale_end) +{ + ClutterBehaviourScalePrivate *priv; + + g_return_if_fail (CLUTTER_IS_BEHAVIOUR_SCALE (scale)); + + priv = scale->priv; + + g_object_freeze_notify (G_OBJECT (scale)); + + if (priv->x_scale_start != x_scale_start) + { + priv->x_scale_start = x_scale_start; + g_object_notify_by_pspec (G_OBJECT (scale), obj_props[PROP_X_SCALE_START]); + } + + if (priv->y_scale_start != y_scale_start) + { + priv->y_scale_start = y_scale_start; + g_object_notify_by_pspec (G_OBJECT (scale), obj_props[PROP_Y_SCALE_START]); + } + + if (priv->x_scale_end != x_scale_end) + { + priv->x_scale_end = x_scale_end; + g_object_notify_by_pspec (G_OBJECT (scale), obj_props[PROP_X_SCALE_END]); + } + + if (priv->y_scale_end != y_scale_end) + { + priv->y_scale_end = y_scale_end; + g_object_notify_by_pspec (G_OBJECT (scale), obj_props[PROP_Y_SCALE_END]); + } + + g_object_thaw_notify (G_OBJECT (scale)); +} + +/** + * clutter_behaviour_scale_get_bounds: + * @scale: a #ClutterBehaviourScale + * @x_scale_start: (out): return location for the initial scale factor on the X + * axis, or %NULL + * @y_scale_start: (out): return location for the initial scale factor on the Y + * axis, or %NULL + * @x_scale_end: (out): return location for the final scale factor on the X axis, + * or %NULL + * @y_scale_end: (out): return location for the final scale factor on the Y axis, + * or %NULL + * + * Retrieves the bounds used by scale behaviour. + * + * Since: 0.4 + * + * Deprecated: 1.6 + */ +void +clutter_behaviour_scale_get_bounds (ClutterBehaviourScale *scale, + gdouble *x_scale_start, + gdouble *y_scale_start, + gdouble *x_scale_end, + gdouble *y_scale_end) +{ + ClutterBehaviourScalePrivate *priv; + + g_return_if_fail (CLUTTER_IS_BEHAVIOUR_SCALE (scale)); + + priv = scale->priv; + + if (x_scale_start) + *x_scale_start = priv->x_scale_start; + + if (x_scale_end) + *x_scale_end = priv->x_scale_end; + + if (y_scale_start) + *y_scale_start = priv->y_scale_start; + + if (y_scale_end) + *y_scale_end = priv->y_scale_end; +} diff --git a/clutter/clutter/deprecated/clutter-behaviour-scale.h b/clutter/clutter/deprecated/clutter-behaviour-scale.h new file mode 100644 index 0000000..e3f7797 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-behaviour-scale.h @@ -0,0 +1,107 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * Jorn Baayen + * Emmanuele Bassi + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_BEHAVIOUR_SCALE_H__ +#define __CLUTTER_BEHAVIOUR_SCALE_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BEHAVIOUR_SCALE (clutter_behaviour_scale_get_type ()) +#define CLUTTER_BEHAVIOUR_SCALE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BEHAVIOUR_SCALE, ClutterBehaviourScale)) +#define CLUTTER_BEHAVIOUR_SCALE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BEHAVIOUR_SCALE, ClutterBehaviourScaleClass)) +#define CLUTTER_IS_BEHAVIOUR_SCALE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BEHAVIOUR_SCALE)) +#define CLUTTER_IS_BEHAVIOUR_SCALE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BEHAVIOUR_SCALE)) +#define CLUTTER_BEHAVIOUR_SCALE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BEHAVIOUR_SCALE, ClutterBehaviourScaleClass)) + +typedef struct _ClutterBehaviourScale ClutterBehaviourScale; +typedef struct _ClutterBehaviourScalePrivate ClutterBehaviourScalePrivate; +typedef struct _ClutterBehaviourScaleClass ClutterBehaviourScaleClass; + +/** + * ClutterBehaviourScale: + * + * The #ClutterBehaviourScale struct contains only private data and + * should be accessed using the provided API + * + * Since: 0.2 + * + * Deprecated: 1.6: Use clutter_actor_animate() with #ClutterActor:scale-x + * and #ClutterActor:scale-y instead. + */ +struct _ClutterBehaviourScale +{ + /*< private >*/ + ClutterBehaviour parent_instance; + + ClutterBehaviourScalePrivate *priv; +}; + +/** + * ClutterBehaviourScaleClass: + * + * The #ClutterBehaviourScaleClass struct contains only private data + * + * Since: 0.2 + * + * Deprecated: 1.6 + */ +struct _ClutterBehaviourScaleClass +{ + /*< private >*/ + ClutterBehaviourClass parent_class; +}; + +CLUTTER_DEPRECATED_IN_1_6 +GType clutter_behaviour_scale_get_type (void) G_GNUC_CONST; + +CLUTTER_DEPRECATED_IN_1_6_FOR(clutter_actor_animate with ClutterActor:scale-x and ClutterActor:scale-y) +ClutterBehaviour *clutter_behaviour_scale_new (ClutterAlpha *alpha, + gdouble x_scale_start, + gdouble y_scale_start, + gdouble x_scale_end, + gdouble y_scale_end); + +CLUTTER_DEPRECATED_IN_1_6 +void clutter_behaviour_scale_set_bounds (ClutterBehaviourScale *scale, + gdouble x_scale_start, + gdouble y_scale_start, + gdouble x_scale_end, + gdouble y_scale_end); +CLUTTER_DEPRECATED_IN_1_6 +void clutter_behaviour_scale_get_bounds (ClutterBehaviourScale *scale, + gdouble *x_scale_start, + gdouble *y_scale_start, + gdouble *x_scale_end, + gdouble *y_scale_end); + +G_END_DECLS + +#endif /* __CLUTTER_BEHAVIOUR_SCALE_H__ */ diff --git a/clutter/clutter/deprecated/clutter-behaviour.c b/clutter/clutter/deprecated/clutter-behaviour.c new file mode 100644 index 0000000..11f9507 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-behaviour.c @@ -0,0 +1,660 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +/** + * SECTION:clutter-behaviour + * @Title: ClutterBehaviour + * @short_description: Class for providing behaviours to actors + * @Deprecated: 1.6: Use clutter_actor_animate(), #ClutterAnimator or + * #ClutterState instead + * + * #ClutterBehaviour is the base class for implementing behaviours. A + * behaviour is a controller object for #ClutterActors; you can + * use a behaviour to control one or more properties of an actor (such + * as its opacity, or its position). A #ClutterBehaviour is driven by + * an "alpha function" stored inside a #ClutterAlpha object; an alpha + * function is a function depending solely on time. The alpha function + * computes a value which is then applied to the properties of the + * actors driven by a behaviour. + * + * Clutter provides some pre-defined behaviours, like #ClutterBehaviourPath, + * which controls the position of a set of actors making them "walk" along + * a set of nodes; #ClutterBehaviourOpacity, which controls the opacity + * of a set of actors; #ClutterBehaviourScale, which controls the width + * and height of a set of actors. + * + * To visualize the effects of different alpha functions on a + * #ClutterBehaviour implementation it is possible to take the + * #ClutterBehaviourPath as an example: + * + * ![](path-alpha-func.png) + * + * The actors position between the path's end points directly correlates + * to the #ClutterAlpha's current alpha value driving the behaviour. With + * the #ClutterAlpha's function set to a linear ramp the actor + * will follow the path at a constant velocity, but when changing to + * a sine wave the actor initially accelerates before quickly + * decelerating. + * + * In order to implement a new behaviour you should subclass #ClutterBehaviour + * and override the "alpha_notify" virtual function; inside the overridden + * function you should obtain the alpha value from the #ClutterAlpha + * instance bound to the behaviour and apply it to the desiderd property + * (or properties) of every actor controlled by the behaviour. + * + * #ClutterBehaviour is available since Clutter 0.2. + * + * #ClutterBehaviour and its sub-classes have been discouraged sing Clutter + * 1.0, and formally deprecated since Clutter 1.6. You should use the + * [implicit animation][clutter-actor-animation] support inside #ClutterActor + * if you still have code using #ClutterBehaviour. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include "clutter-behaviour.h" +#include "clutter-alpha.h" + +#include "clutter-debug.h" +#include "clutter-main.h" +#include "clutter-marshal.h" +#include "clutter-private.h" +#include "clutter-scriptable.h" +#include "clutter-script-private.h" + +struct _ClutterBehaviourPrivate +{ + ClutterAlpha *alpha; + + guint notify_id; + GSList *actors; +}; + +enum +{ + PROP_0, + PROP_ALPHA, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +enum { + APPLIED, + REMOVED, + LAST_SIGNAL +}; + +static guint behave_signals[LAST_SIGNAL] = { 0 }; + +static void clutter_scriptable_iface_init (ClutterScriptableIface *iface); + +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (ClutterBehaviour, + clutter_behaviour, + G_TYPE_OBJECT, + G_ADD_PRIVATE (ClutterBehaviour) + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_SCRIPTABLE, + clutter_scriptable_iface_init)) + +static gboolean +clutter_behaviour_parse_custom_node (ClutterScriptable *scriptable, + ClutterScript *script, + GValue *value, + const gchar *name, + JsonNode *node) +{ + if (strncmp (name, "alpha", 5) == 0) + { + GObject *alpha; + + alpha = _clutter_script_parse_alpha (script, node); + if (alpha != NULL) + { + g_value_init (value, CLUTTER_TYPE_ALPHA); + g_value_set_object (value, alpha); + + return TRUE; + } + } + + return FALSE; +} + +static void +clutter_scriptable_iface_init (ClutterScriptableIface *iface) +{ + iface->parse_custom_node = clutter_behaviour_parse_custom_node; +} + +static void +clutter_behaviour_dispose (GObject *gobject) +{ + ClutterBehaviour *self = CLUTTER_BEHAVIOUR (gobject); + + clutter_behaviour_set_alpha (self, NULL); + clutter_behaviour_remove_all (self); + + G_OBJECT_CLASS (clutter_behaviour_parent_class)->dispose (gobject); +} + +static void +clutter_behaviour_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterBehaviour *behaviour = CLUTTER_BEHAVIOUR (object); + + switch (prop_id) + { + case PROP_ALPHA: + clutter_behaviour_set_alpha (behaviour, g_value_get_object (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_behaviour_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterBehaviour *behaviour = CLUTTER_BEHAVIOUR (object); + ClutterBehaviourPrivate *priv = behaviour->priv; + + switch (prop_id) + { + case PROP_ALPHA: + g_value_set_object (value, priv->alpha); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_behaviour_alpha_notify_unimplemented (ClutterBehaviour *behaviour, + gdouble alpha_value) +{ + g_warning ("ClutterBehaviourClass::alpha_notify not implemented for '%s'", + g_type_name (G_TYPE_FROM_INSTANCE (behaviour))); +} + +static void +clutter_behaviour_class_init (ClutterBehaviourClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = clutter_behaviour_dispose; + object_class->set_property = clutter_behaviour_set_property; + object_class->get_property = clutter_behaviour_get_property; + + /** + * ClutterBehaviour:alpha: + * + * The #ClutterAlpha object used to drive this behaviour. A #ClutterAlpha + * object binds a #ClutterTimeline and a function which computes a value + * (the "alpha") depending on the time. Each time the alpha value changes + * the alpha-notify virtual function is called. + * + * Since: 0.2 + * + * Deprecated: 1.6 + */ + obj_props[PROP_ALPHA] = + g_param_spec_object ("alpha", + P_("Alpha"), + P_("Alpha Object to drive the behaviour"), + CLUTTER_TYPE_ALPHA, + CLUTTER_PARAM_READWRITE); + + g_object_class_install_properties (object_class, + PROP_LAST, + obj_props); + + klass->alpha_notify = clutter_behaviour_alpha_notify_unimplemented; + + /** + * ClutterBehaviour::applied: + * @behaviour: the #ClutterBehaviour that received the signal + * @actor: the actor the behaviour was applied to. + * + * The ::apply signal is emitted each time the behaviour is applied + * to an actor. + * + * Since: 0.4 + * + * Deprecated: 1.6 + */ + behave_signals[APPLIED] = + g_signal_new ("applied", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ClutterBehaviourClass, applied), + NULL, NULL, + _clutter_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CLUTTER_TYPE_ACTOR); + /** + * ClutterBehaviour::removed: + * @behaviour: the #ClutterBehaviour that received the signal + * @actor: the removed actor + * + * The ::removed signal is emitted each time a behaviour is not applied + * to an actor anymore. + * + * Since: 0.4 + * + * Deprecated: 1.6 + */ + behave_signals[REMOVED] = + g_signal_new ("removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ClutterBehaviourClass, removed), + NULL, NULL, + _clutter_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CLUTTER_TYPE_ACTOR); +} + +static void +clutter_behaviour_init (ClutterBehaviour *self) +{ + self->priv = clutter_behaviour_get_instance_private (self); +} + +static void +remove_actor_on_destroy (ClutterActor *actor, + ClutterBehaviour *behaviour) +{ + clutter_behaviour_remove (behaviour, actor); +} + +/** + * clutter_behaviour_apply: + * @behave: a #ClutterBehaviour + * @actor: a #ClutterActor + * + * Applies @behave to @actor. This function adds a reference on + * the actor. + * + * Since: 0.2 + * + * Deprecated: 1.6 + */ +void +clutter_behaviour_apply (ClutterBehaviour *behave, + ClutterActor *actor) +{ + ClutterBehaviourPrivate *priv; + + g_return_if_fail (CLUTTER_IS_BEHAVIOUR (behave)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + priv = behave->priv; + + if (g_slist_find (priv->actors, actor)) + { + g_warning ("The behaviour of type %s already applies " + "to the actor of type %s", + g_type_name (G_OBJECT_TYPE (behave)), + g_type_name (G_OBJECT_TYPE (actor))); + return; + } + + priv->actors = g_slist_append (priv->actors, g_object_ref (actor)); + g_signal_connect (actor, "destroy", + G_CALLBACK (remove_actor_on_destroy), + behave); + + g_signal_emit (behave, behave_signals[APPLIED], 0, actor); +} + +/** + * clutter_behaviour_is_applied: + * @behave: a #ClutterBehaviour + * @actor: a #ClutterActor + * + * Check if @behave applied to @actor. + * + * Return value: TRUE if actor has behaviour. FALSE otherwise. + * + * Since: 0.4 + * + * Deprecated: 1.6 + */ +gboolean +clutter_behaviour_is_applied (ClutterBehaviour *behave, + ClutterActor *actor) +{ + g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR (behave), FALSE); + g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), FALSE); + + return (g_slist_find (behave->priv->actors, actor) != NULL); +} + +/** + * clutter_behaviour_remove: + * @behave: a #ClutterBehaviour + * @actor: a #ClutterActor + * + * Removes @actor from the list of #ClutterActors to which + * @behave applies. This function removes a reference on the actor. + * + * Since: 0.2 + * + * Deprecated: 1.6 + */ +void +clutter_behaviour_remove (ClutterBehaviour *behave, + ClutterActor *actor) +{ + ClutterBehaviourPrivate *priv; + + g_return_if_fail (CLUTTER_IS_BEHAVIOUR (behave)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + priv = behave->priv; + + if (!g_slist_find (priv->actors, actor)) + { + g_warning ("The behaviour of type %s is not applied " + "to the actor of type %s", + g_type_name (G_OBJECT_TYPE (behave)), + g_type_name (G_OBJECT_TYPE (actor))); + return; + } + + g_signal_handlers_disconnect_by_func (actor, + G_CALLBACK (remove_actor_on_destroy), + behave); + + priv->actors = g_slist_remove (priv->actors, actor); + + g_signal_emit (behave, behave_signals[REMOVED], 0, actor); + + g_object_unref (actor); +} + +/** + * clutter_behaviour_get_n_actors: + * @behave: a #ClutterBehaviour + * + * Gets the number of actors this behaviour is applied too. + * + * Return value: The number of applied actors + * + * Since: 0.2 + * + * Deprecated: 1.6 + */ +gint +clutter_behaviour_get_n_actors (ClutterBehaviour *behave) +{ + g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR (behave), 0); + + return g_slist_length (behave->priv->actors); +} + +/** + * clutter_behaviour_get_nth_actor: + * @behave: a #ClutterBehaviour + * @index_: the index of an actor this behaviour is applied too. + * + * Gets an actor the behaviour was applied to referenced by index num. + * + * Return value: (transfer none): A Clutter actor or NULL if @index_ is invalid. + * + * Since: 0.2 + * + * Deprecated: 1.6 + */ +ClutterActor * +clutter_behaviour_get_nth_actor (ClutterBehaviour *behave, + gint index_) +{ + g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR (behave), NULL); + + return g_slist_nth_data (behave->priv->actors, index_); +} + + +/** + * clutter_behaviour_actors_foreach: + * @behave: a #ClutterBehaviour + * @func: (scope call): a function called for each actor + * @data: optional data to be passed to the function, or %NULL + * + * Calls @func for every actor driven by @behave. + * + * Since: 0.2 + * + * Deprecated: 1.6 + */ +void +clutter_behaviour_actors_foreach (ClutterBehaviour *behave, + ClutterBehaviourForeachFunc func, + gpointer data) +{ + GSList *l; + + g_return_if_fail (CLUTTER_IS_BEHAVIOUR (behave)); + g_return_if_fail (func != NULL); + + for (l = behave->priv->actors; l != NULL; l = l->next) + { + ClutterActor *actor = l->data; + + g_assert (CLUTTER_IS_ACTOR (actor)); + + func (behave, actor, data); + } +} + +/** + * clutter_behaviour_get_alpha: + * @behave: a #ClutterBehaviour + * + * Retrieves the #ClutterAlpha object bound to @behave. + * + * Return value: (transfer none): a #ClutterAlpha object, or %NULL if no alpha + * object has been bound to this behaviour. + * + * Since: 0.2 + * + * Deprecated: 1.6 + */ +ClutterAlpha * +clutter_behaviour_get_alpha (ClutterBehaviour *behave) +{ + g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR (behave), NULL); + + return behave->priv->alpha; +} + +static void +notify_cb (GObject *object, + GParamSpec *param_spec, + ClutterBehaviour *behave) +{ + ClutterBehaviourClass *klass; + + klass = CLUTTER_BEHAVIOUR_GET_CLASS (behave); + + CLUTTER_NOTE (ANIMATION, "notify::alpha"); + + /* no actors, we can stop right here */ + if (behave->priv->actors == NULL) + return; + + if (klass->alpha_notify != NULL) + { + gdouble alpha_value = clutter_alpha_get_alpha (behave->priv->alpha); + + CLUTTER_NOTE (ANIMATION, "calling %s::alpha_notify (%p, %.4f)", + g_type_name (G_TYPE_FROM_CLASS (klass)), + behave, alpha_value); + + klass->alpha_notify (behave, alpha_value); + } +} + +/** + * clutter_behaviour_set_alpha: + * @behave: a #ClutterBehaviour + * @alpha: a #ClutterAlpha or %NULL to unset a previously set alpha + * + * 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 + * + * Deprecated: 1.6 + */ +void +clutter_behaviour_set_alpha (ClutterBehaviour *behave, + ClutterAlpha *alpha) +{ + ClutterBehaviourPrivate *priv; + + g_return_if_fail (CLUTTER_IS_BEHAVIOUR (behave)); + g_return_if_fail (alpha == NULL || CLUTTER_IS_ALPHA (alpha)); + + priv = behave->priv; + + if (priv->alpha == alpha) + return; + + if (priv->notify_id) + { + CLUTTER_NOTE (ANIMATION, "removing previous notify-id (%d)", + priv->notify_id); + + g_signal_handler_disconnect (priv->alpha, priv->notify_id); + priv->notify_id = 0; + } + + if (priv->alpha != NULL) + { + CLUTTER_NOTE (ANIMATION, "removing previous alpha object"); + + g_object_unref (priv->alpha); + priv->alpha = NULL; + } + + if (alpha != NULL) + { + priv->alpha = g_object_ref_sink (alpha); + + priv->notify_id = g_signal_connect (priv->alpha, "notify::alpha", + G_CALLBACK(notify_cb), + behave); + + CLUTTER_NOTE (ANIMATION, "setting new alpha object (%p, notify:%d)", + priv->alpha, priv->notify_id); + } + + g_object_notify_by_pspec (G_OBJECT (behave), obj_props[PROP_ALPHA]); +} + +/** + * clutter_behaviour_get_actors: + * @behave: a #ClutterBehaviour + * + * Retrieves all the actors to which @behave applies. It is not recommended + * for derived classes to use this in there alpha notify method but use + * #clutter_behaviour_actors_foreach as it avoids alot of needless allocations. + * + * Return value: (transfer container) (element-type Clutter.Actor): a list of + * actors. You should free the returned list with g_slist_free() when + * finished using it. + * + * Since: 0.2 + * + * Deprecated: 1.6 + */ +GSList * +clutter_behaviour_get_actors (ClutterBehaviour *behave) +{ + ClutterBehaviourPrivate *priv; + GSList *retval, *l; + + g_return_val_if_fail (CLUTTER_BEHAVIOUR (behave), NULL); + + priv = behave->priv; + retval = NULL; + for (l = priv->actors; l != NULL; l = l->next) + retval = g_slist_prepend (retval, l->data); + + return g_slist_reverse (retval); +} + +/** + * clutter_behaviour_remove_all: + * @behave: a #ClutterBehaviour + * + * Removes every actor from the list that @behave holds. + * + * Since: 0.4 + * + * Deprecated: 1.6 + */ +void +clutter_behaviour_remove_all (ClutterBehaviour *behave) +{ + ClutterBehaviourPrivate *priv; + GSList *l; + + g_return_if_fail (CLUTTER_IS_BEHAVIOUR (behave)); + + priv = behave->priv; + for (l = priv->actors; l != NULL; l = l->next) + { + ClutterActor *actor = l->data; + + g_signal_emit (behave, behave_signals[REMOVED], 0, actor); + g_signal_handlers_disconnect_by_func (actor, + G_CALLBACK (remove_actor_on_destroy), + behave); + g_object_unref (actor); + } + + g_slist_free (priv->actors); + priv->actors = NULL; +} diff --git a/clutter/clutter/deprecated/clutter-behaviour.h b/clutter/clutter/deprecated/clutter-behaviour.h new file mode 100644 index 0000000..295d1cf --- /dev/null +++ b/clutter/clutter/deprecated/clutter-behaviour.h @@ -0,0 +1,170 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * Jorn Baayen + * Emmanuele Bassi + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_BEHAVIOUR_H__ +#define __CLUTTER_BEHAVIOUR_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BEHAVIOUR clutter_behaviour_get_type() + +#define CLUTTER_BEHAVIOUR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + CLUTTER_TYPE_BEHAVIOUR, ClutterBehaviour)) + +#define CLUTTER_BEHAVIOUR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + CLUTTER_TYPE_BEHAVIOUR, ClutterBehaviourClass)) + +#define CLUTTER_IS_BEHAVIOUR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + CLUTTER_TYPE_BEHAVIOUR)) + +#define CLUTTER_IS_BEHAVIOUR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + CLUTTER_TYPE_BEHAVIOUR)) + +#define CLUTTER_BEHAVIOUR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + CLUTTER_TYPE_BEHAVIOUR, ClutterBehaviourClass)) + +typedef struct _ClutterBehaviourPrivate ClutterBehaviourPrivate; +typedef struct _ClutterBehaviourClass ClutterBehaviourClass; + +/** + * ClutterBehaviourForeachFunc: + * @behaviour: the #ClutterBehaviour + * @actor: an actor driven by @behaviour + * @data: (closure): optional data passed to the function + * + * This function is passed to clutter_behaviour_actors_foreach() and + * will be called for each actor driven by @behaviour. + * + * Since: 0.2 + * + * Deprecated: 1.6 + */ +typedef void (*ClutterBehaviourForeachFunc) (ClutterBehaviour *behaviour, + ClutterActor *actor, + gpointer data); + +/** + * ClutterBehaviour: + * + * #ClutterBehaviour-struct contains only private data and should + * be accessed with the functions below. + * + * Since: 0.2 + * + * Deprecated: 1.6 + */ +struct _ClutterBehaviour +{ + /*< private >*/ + GObject parent; + ClutterBehaviourPrivate *priv; +}; + +/** + * ClutterBehaviourClass: + * @alpha_notify: virtual function, called each time the #ClutterAlpha + * computes a new alpha value; the actors to which the behaviour applies + * should be changed in this function. Every subclass of #ClutterBehaviour + * must implement this virtual function + * @applied: signal class handler for the ClutterBehaviour::applied signal + * @removed: signal class handler for the ClutterBehaviour::removed signal + * + * Base class for behaviours. + * + * Since: 0.2 + * + * Deprecated: 1.6 + */ +struct _ClutterBehaviourClass +{ + /*< private >*/ + GObjectClass parent_class; + + /*< public >*/ + /* vfunc, not signal */ + void (*alpha_notify) (ClutterBehaviour *behave, + gdouble alpha_value); + + /* signals */ + void (*applied) (ClutterBehaviour *behave, + ClutterActor *actor); + void (*removed) (ClutterBehaviour *behave, + ClutterActor *actor); + + /*< private >*/ + /* padding, for future expansion */ + void (*_clutter_behaviour1) (void); + void (*_clutter_behaviour2) (void); + void (*_clutter_behaviour3) (void); + void (*_clutter_behaviour4) (void); + void (*_clutter_behaviour5) (void); + void (*_clutter_behaviour6) (void); +}; + +CLUTTER_DEPRECATED_IN_1_6 +GType clutter_behaviour_get_type (void) G_GNUC_CONST; + +CLUTTER_DEPRECATED_IN_1_6 +void clutter_behaviour_apply (ClutterBehaviour *behave, + ClutterActor *actor); +CLUTTER_DEPRECATED_IN_1_6 +void clutter_behaviour_remove (ClutterBehaviour *behave, + ClutterActor *actor); +CLUTTER_DEPRECATED_IN_1_6 +void clutter_behaviour_remove_all (ClutterBehaviour *behave); +CLUTTER_DEPRECATED_IN_1_6 +void clutter_behaviour_actors_foreach (ClutterBehaviour *behave, + ClutterBehaviourForeachFunc func, + gpointer data); +CLUTTER_DEPRECATED_IN_1_6 +gint clutter_behaviour_get_n_actors (ClutterBehaviour *behave); +CLUTTER_DEPRECATED_IN_1_6 +ClutterActor *clutter_behaviour_get_nth_actor (ClutterBehaviour *behave, + gint index_); +CLUTTER_DEPRECATED_IN_1_6 +GSList * clutter_behaviour_get_actors (ClutterBehaviour *behave); +CLUTTER_DEPRECATED_IN_1_6 +ClutterAlpha *clutter_behaviour_get_alpha (ClutterBehaviour *behave); +CLUTTER_DEPRECATED_IN_1_6 +void clutter_behaviour_set_alpha (ClutterBehaviour *behave, + ClutterAlpha *alpha); +CLUTTER_DEPRECATED_IN_1_6 +gboolean clutter_behaviour_is_applied (ClutterBehaviour *behave, + ClutterActor *actor); + +G_END_DECLS + +#endif /* __CLUTTER_BEHAVIOUR_H__ */ diff --git a/clutter/clutter/deprecated/clutter-bin-layout.h b/clutter/clutter/deprecated/clutter-bin-layout.h new file mode 100644 index 0000000..2d56d1f --- /dev/null +++ b/clutter/clutter/deprecated/clutter-bin-layout.h @@ -0,0 +1,56 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * 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 . + * + * Author: + * Emmanuele Bassi + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_BIN_LAYOUT_DEPRECATED_H__ +#define __CLUTTER_BIN_LAYOUT_DEPRECATED_H__ + +#include + +G_BEGIN_DECLS + +CLUTTER_DEPRECATED_IN_1_12 +void clutter_bin_layout_set_alignment (ClutterBinLayout *self, + ClutterActor *child, + ClutterBinAlignment x_align, + ClutterBinAlignment y_align); + +CLUTTER_DEPRECATED_IN_1_12 +void clutter_bin_layout_get_alignment (ClutterBinLayout *self, + ClutterActor *child, + ClutterBinAlignment *x_align, + ClutterBinAlignment *y_align); + +CLUTTER_DEPRECATED_IN_1_12 +void clutter_bin_layout_add (ClutterBinLayout *self, + ClutterActor *child, + ClutterBinAlignment x_align, + ClutterBinAlignment y_align); + +G_END_DECLS + +#endif /* __CLUTTER_BIN_LAYOUT_DEPRECATED_H__ */ diff --git a/clutter/clutter/deprecated/clutter-box.c b/clutter/clutter/deprecated/clutter-box.c new file mode 100644 index 0000000..74780e8 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-box.c @@ -0,0 +1,747 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2009,2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-box + * @short_description: A Generic layout container + * + * #ClutterBox is a #ClutterActor sub-class implementing the #ClutterContainer + * interface. A Box delegates the whole size requisition and size allocation to + * a #ClutterLayoutManager instance. + * + * #ClutterBox is available since Clutter 1.2 + * + * #ClutterBox is deprecated since Clutter 1.10; all its relevant API is provided + * by #ClutterActor, via the #ClutterActor:layout-manager property. + * + * ## Using ClutterBox + * + * The following code shows how to create a #ClutterBox with + * a #ClutterLayoutManager sub-class, and how to add children to + * it via clutter_box_pack(). + * + * |[ + * ClutterActor *box; + * ClutterLayoutManager *layout; + * + * // Create the layout manager first + * layout = clutter_box_layout_new (); + * clutter_box_layout_set_homogeneous (CLUTTER_BOX_LAYOUT (layout), TRUE); + * clutter_box_layout_set_spacing (CLUTTER_BOX_LAYOUT (layout), 12); + * + * // Then create the ClutterBox actor. The Box will take + * // ownership of the ClutterLayoutManager instance by sinking + * // its floating reference + * box = clutter_box_new (layout); + * + * // Now add children to the Box using the variadic arguments + * // function clutter_box_pack() to set layout properties + * clutter_box_pack (CLUTTER_BOX (box), actor, + * "x-align", CLUTTER_BOX_ALIGNMENT_CENTER, + * "y-align", CLUTTER_BOX_ALIGNMENT_END, + * "expand", TRUE, + * NULL); + * ]| + * + * #ClutterBox's clutter_box_pack() wraps the generic + * clutter_container_add_actor() function, but it also allows setting + * layout properties while adding the new child to the box. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include "deprecated/clutter-container.h" + +#include "clutter-box.h" + +#include "clutter-actor-private.h" +#include "clutter-color.h" +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-marshal.h" +#include "clutter-private.h" + +struct _ClutterBoxPrivate +{ + ClutterLayoutManager *manager; + + guint changed_id; +}; + +enum +{ + PROP_0, + + PROP_COLOR, + PROP_COLOR_SET, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST] = { NULL, }; + +static const ClutterColor default_box_color = { 255, 255, 255, 255 }; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterBox, clutter_box, CLUTTER_TYPE_ACTOR) + +static inline void +clutter_box_set_color_internal (ClutterBox *box, + const ClutterColor *color) +{ + clutter_actor_set_background_color (CLUTTER_ACTOR (box), color); + + g_object_notify_by_pspec (G_OBJECT (box), obj_props[PROP_COLOR_SET]); + g_object_notify_by_pspec (G_OBJECT (box), obj_props[PROP_COLOR]); +} + +static gboolean +clutter_box_real_get_paint_volume (ClutterActor *actor, + ClutterPaintVolume *volume) +{ + gboolean retval = FALSE; + ClutterActorIter iter; + ClutterActor *child; + + /* if we have a background color, and an allocation, then we need to + * set it as the base of our paint volume + */ + retval = clutter_paint_volume_set_from_allocation (volume, actor); + + /* bail out early if we don't have any child */ + if (clutter_actor_get_n_children (actor) == 0) + return retval; + + retval = TRUE; + + /* otherwise, union the paint volumes of our children, in case + * any one of them decides to paint outside the parent's allocation + */ + clutter_actor_iter_init (&iter, actor); + while (clutter_actor_iter_next (&iter, &child)) + { + const ClutterPaintVolume *child_volume; + + /* This gets the paint volume of the child transformed into the + * group's coordinate space... */ + child_volume = clutter_actor_get_transformed_paint_volume (child, actor); + if (!child_volume) + return FALSE; + + clutter_paint_volume_union (volume, child_volume); + } + + return retval; +} + +static void +clutter_box_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterBox *self = CLUTTER_BOX (gobject); + + switch (prop_id) + { + case PROP_COLOR: + clutter_box_set_color_internal (self, clutter_value_get_color (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_box_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) + { + case PROP_COLOR: + { + ClutterColor color; + + clutter_actor_get_background_color (CLUTTER_ACTOR (gobject), + &color); + clutter_value_set_color (value, &color); + } + break; + + case PROP_COLOR_SET: + { + gboolean color_set; + + g_object_get (gobject, "background-color-set", &color_set, NULL); + g_value_set_boolean (value, color_set); + } + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_box_real_destroy (ClutterActor *actor) +{ + ClutterActor *iter; + + iter = clutter_actor_get_first_child (actor); + while (iter != NULL) + { + ClutterActor *next = clutter_actor_get_next_sibling (iter); + + clutter_actor_destroy (iter); + + iter = next; + } +} + +static void +clutter_box_class_init (ClutterBoxClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + + actor_class->destroy = clutter_box_real_destroy; + actor_class->get_paint_volume = clutter_box_real_get_paint_volume; + + gobject_class->set_property = clutter_box_set_property; + gobject_class->get_property = clutter_box_get_property; + + /** + * ClutterBox:color: + * + * The color to be used to paint the background of the + * #ClutterBox. Setting this property will set the + * #ClutterBox:color-set property as a side effect + * + * This property sets the #ClutterActor:background-color property + * internally. + * + * Since: 1.2 + * + * Deprecated: 1.10: Use the #ClutterActor:background-color property + */ + obj_props[PROP_COLOR] = + clutter_param_spec_color ("color", + P_("Color"), + P_("The background color of the box"), + &default_box_color, + CLUTTER_PARAM_READWRITE); + + /** + * ClutterBox:color-set: + * + * Whether the #ClutterBox:color property has been set. + * + * This property reads the #ClutterActor:background-color-set property + * internally. + * + * Since: 1.2 + * + * Deprecated: 1.10: Use the #ClutterActor:background-color-set property + */ + obj_props[PROP_COLOR_SET] = + g_param_spec_boolean ("color-set", + P_("Color Set"), + P_("Whether the background color is set"), + FALSE, + CLUTTER_PARAM_READWRITE); + + g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); +} + +static void +clutter_box_init (ClutterBox *self) +{ + self->priv = clutter_box_get_instance_private (self); +} + +/** + * clutter_box_new: + * @manager: a #ClutterLayoutManager + * + * Creates a new #ClutterBox. The children of the box will be layed + * out by the passed @manager + * + * Return value: the newly created #ClutterBox actor + * + * Since: 1.2 + * + * Deprecated: 1.10: Use clutter_actor_new() instead. + */ +ClutterActor * +clutter_box_new (ClutterLayoutManager *manager) +{ + g_return_val_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager), NULL); + + return g_object_new (CLUTTER_TYPE_BOX, + "layout-manager", manager, + NULL); +} + +/** + * clutter_box_set_layout_manager: + * @box: a #ClutterBox + * @manager: a #ClutterLayoutManager + * + * Sets the #ClutterLayoutManager for @box + * + * A #ClutterLayoutManager is a delegate object that controls the + * layout of the children of @box + * + * Since: 1.2 + * + * Deprecated: 1.10: Use clutter_actor_set_layout_manager() instead. + */ +void +clutter_box_set_layout_manager (ClutterBox *box, + ClutterLayoutManager *manager) +{ + clutter_actor_set_layout_manager (CLUTTER_ACTOR (box), manager); +} + +/** + * clutter_box_get_layout_manager: + * @box: a #ClutterBox + * + * Retrieves the #ClutterLayoutManager instance used by @box + * + * Return value: (transfer none): a #ClutterLayoutManager. The returned + * #ClutterLayoutManager is owned by the #ClutterBox and it should not + * be unreferenced + * + * Since: 1.2 + * + * Deprecated: 1.10: Use clutter_actor_get_layout_manager() instead. + */ +ClutterLayoutManager * +clutter_box_get_layout_manager (ClutterBox *box) +{ + return clutter_actor_get_layout_manager (CLUTTER_ACTOR (box)); +} + +/** + * clutter_box_packv: + * @box: a #ClutterBox + * @actor: a #ClutterActor + * @n_properties: the number of properties to set + * @properties: (array length=n_properties) (element-type utf8): a vector + * containing the property names to set + * @values: (array length=n_properties): a vector containing the property + * values to set + * + * Vector-based variant of clutter_box_pack(), intended for language + * bindings to use + * + * Since: 1.2 + * + * Deprecated: 1.10: Use clutter_actor_add_child() instead. To set + * specific layout properties, use clutter_layout_manager_child_set() + */ +void +clutter_box_packv (ClutterBox *box, + ClutterActor *actor, + guint n_properties, + const gchar * const properties[], + const GValue *values) +{ + ClutterLayoutManager *manager; + ClutterContainer *container; + ClutterLayoutMeta *meta; + GObjectClass *klass; + gint i; + + g_return_if_fail (CLUTTER_IS_BOX (box)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + container = CLUTTER_CONTAINER (box); + clutter_container_add_actor (container, actor); + + manager = clutter_actor_get_layout_manager (CLUTTER_ACTOR (box)); + if (manager == NULL) + return; + + meta = clutter_layout_manager_get_child_meta (manager, + container, + actor); + + if (meta == NULL) + return; + + klass = G_OBJECT_GET_CLASS (meta); + + for (i = 0; i < n_properties; i++) + { + const gchar *pname = properties[i]; + GParamSpec *pspec; + + pspec = g_object_class_find_property (klass, pname); + if (pspec == NULL) + { + g_warning ("%s: the layout property '%s' for managers " + "of type '%s' (meta type '%s') does not exist", + G_STRLOC, + pname, + G_OBJECT_TYPE_NAME (manager), + G_OBJECT_TYPE_NAME (meta)); + break; + } + + if (!(pspec->flags & G_PARAM_WRITABLE)) + { + g_warning ("%s: the layout property '%s' for managers " + "of type '%s' (meta type '%s') is not writable", + G_STRLOC, + pspec->name, + G_OBJECT_TYPE_NAME (manager), + G_OBJECT_TYPE_NAME (meta)); + break; + } + + clutter_layout_manager_child_set_property (manager, + container, actor, + pname, &values[i]); + } +} + +static inline void +clutter_box_set_property_valist (ClutterBox *box, + ClutterActor *actor, + const gchar *first_property, + va_list var_args) +{ + ClutterContainer *container = CLUTTER_CONTAINER (box); + ClutterLayoutManager *manager; + ClutterLayoutMeta *meta; + GObjectClass *klass; + const gchar *pname; + + manager = clutter_actor_get_layout_manager (CLUTTER_ACTOR (box)); + if (manager == NULL) + return; + + meta = clutter_layout_manager_get_child_meta (manager, + container, + actor); + + if (meta == NULL) + return; + + klass = G_OBJECT_GET_CLASS (meta); + + pname = first_property; + while (pname) + { + GValue value = { 0, }; + GParamSpec *pspec; + gchar *error; + + pspec = g_object_class_find_property (klass, pname); + if (pspec == NULL) + { + g_warning ("%s: the layout property '%s' for managers " + "of type '%s' (meta type '%s') does not exist", + G_STRLOC, + pname, + G_OBJECT_TYPE_NAME (manager), + G_OBJECT_TYPE_NAME (meta)); + break; + } + + if (!(pspec->flags & G_PARAM_WRITABLE)) + { + g_warning ("%s: the layout property '%s' for managers " + "of type '%s' (meta type '%s') is not writable", + G_STRLOC, + pspec->name, + G_OBJECT_TYPE_NAME (manager), + G_OBJECT_TYPE_NAME (meta)); + break; + } + + G_VALUE_COLLECT_INIT (&value, G_PARAM_SPEC_VALUE_TYPE (pspec), + var_args, 0, + &error); + + if (error) + { + g_warning ("%s: %s", G_STRLOC, error); + g_free (error); + break; + } + + clutter_layout_manager_child_set_property (manager, + container, actor, + pspec->name, &value); + + g_value_unset (&value); + + pname = va_arg (var_args, gchar*); + } +} + +/** + * clutter_box_pack: + * @box: a #ClutterBox + * @actor: a #ClutterActor + * @first_property: the name of the first property to set, or %NULL + * @...: a list of property name and value pairs, terminated by %NULL + * + * Adds @actor to @box and sets layout properties at the same time, + * if the #ClutterLayoutManager used by @box has them + * + * This function is a wrapper around clutter_container_add_actor() + * and clutter_layout_manager_child_set() + * + * Language bindings should use the vector-based clutter_box_packv() + * variant instead + * + * Since: 1.2 + * + * Deprecated: 1.10: Use clutter_actor_add_child() instead. To set + * specific layout properties, use clutter_layout_manager_child_set() + */ +void +clutter_box_pack (ClutterBox *box, + ClutterActor *actor, + const gchar *first_property, + ...) +{ + va_list var_args; + + g_return_if_fail (CLUTTER_IS_BOX (box)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + clutter_container_add_actor (CLUTTER_CONTAINER (box), actor); + + if (first_property == NULL || *first_property == '\0') + return; + + va_start (var_args, first_property); + clutter_box_set_property_valist (box, actor, first_property, var_args); + va_end (var_args); +} + +/** + * clutter_box_pack_after: + * @box: a #ClutterBox + * @actor: a #ClutterActor + * @sibling: (allow-none): a #ClutterActor or %NULL + * @first_property: the name of the first property to set, or %NULL + * @...: a list of property name and value pairs, terminated by %NULL + * + * Adds @actor to @box, placing it after @sibling, and sets layout + * properties at the same time, if the #ClutterLayoutManager used by + * @box supports them + * + * If @sibling is %NULL then @actor is placed at the end of the + * list of children, to be allocated and painted after every other child + * + * This function is a wrapper around clutter_container_add_actor(), + * clutter_container_raise_child() and clutter_layout_manager_child_set() + * + * Since: 1.2 + * + * Deprecated: 1.10: Use clutter_actor_insert_child_above() instead. + * To set specific layout properties, use clutter_layout_manager_child_set() + */ +void +clutter_box_pack_after (ClutterBox *box, + ClutterActor *actor, + ClutterActor *sibling, + const gchar *first_property, + ...) +{ + va_list var_args; + + g_return_if_fail (CLUTTER_IS_BOX (box)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + g_return_if_fail (sibling == NULL || CLUTTER_IS_ACTOR (sibling)); + + clutter_container_add_actor (CLUTTER_CONTAINER (box), actor); + clutter_container_raise_child (CLUTTER_CONTAINER (box), actor, sibling); + + if (first_property == NULL || *first_property == '\0') + return; + + va_start (var_args, first_property); + clutter_box_set_property_valist (box, actor, first_property, var_args); + va_end (var_args); +} + +/** + * clutter_box_pack_before: + * @box: a #ClutterBox + * @actor: a #ClutterActor + * @sibling: (allow-none): a #ClutterActor or %NULL + * @first_property: the name of the first property to set, or %NULL + * @...: a list of property name and value pairs, terminated by %NULL + * + * Adds @actor to @box, placing it before @sibling, and sets layout + * properties at the same time, if the #ClutterLayoutManager used by + * @box supports them + * + * If @sibling is %NULL then @actor is placed at the beginning of the + * list of children, to be allocated and painted below every other child + * + * This function is a wrapper around clutter_container_add_actor(), + * clutter_container_lower_child() and clutter_layout_manager_child_set() + * + * Since: 1.2 + * + * Deprecated: 1.10: Use clutter_actor_insert_child_below() instead. + * To set specific layout properties, use clutter_layout_manager_child_set() + */ +void +clutter_box_pack_before (ClutterBox *box, + ClutterActor *actor, + ClutterActor *sibling, + const gchar *first_property, + ...) +{ + va_list var_args; + + g_return_if_fail (CLUTTER_IS_BOX (box)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + g_return_if_fail (sibling == NULL || CLUTTER_IS_ACTOR (sibling)); + + clutter_container_add_actor (CLUTTER_CONTAINER (box), actor); + clutter_container_lower_child (CLUTTER_CONTAINER (box), actor, sibling); + + if (first_property == NULL || *first_property == '\0') + return; + + va_start (var_args, first_property); + clutter_box_set_property_valist (box, actor, first_property, var_args); + va_end (var_args); +} + +/** + * clutter_box_pack_at: + * @box: a #ClutterBox + * @actor: a #ClutterActor + * @position: the position to insert the @actor at + * @first_property: the name of the first property to set, or %NULL + * @...: a list of property name and value pairs, terminated by %NULL + * + * Adds @actor to @box, placing it at @position, and sets layout + * properties at the same time, if the #ClutterLayoutManager used by + * @box supports them + * + * If @position is a negative number, or is larger than the number of + * children of @box, the new child is added at the end of the list of + * children + * + * Since: 1.2 + * + * Deprecated: 1.10: Use clutter_actor_insert_child_at_index() instead. + * To set specific layout properties, use clutter_layout_manager_child_set() + */ +void +clutter_box_pack_at (ClutterBox *box, + ClutterActor *actor, + gint position, + const gchar *first_property, + ...) +{ + va_list var_args; + + g_return_if_fail (CLUTTER_IS_BOX (box)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + clutter_actor_insert_child_at_index (CLUTTER_ACTOR (box), + actor, + position); + + /* we need to explicitly call this, because we're not going through + * the default code paths provided by clutter_container_add() + */ + clutter_container_create_child_meta (CLUTTER_CONTAINER (box), actor); + + g_signal_emit_by_name (box, "actor-added", actor); + + if (first_property == NULL || *first_property == '\0') + return; + + va_start (var_args, first_property); + clutter_box_set_property_valist (box, actor, first_property, var_args); + va_end (var_args); +} + +/** + * clutter_box_set_color: + * @box: a #ClutterBox + * @color: (allow-none): the background color, or %NULL to unset + * + * Sets (or unsets) the background color for @box + * + * Since: 1.2 + * + * Deprecated: 1.10: Use clutter_actor_set_background_color() instead. + */ +void +clutter_box_set_color (ClutterBox *box, + const ClutterColor *color) +{ + g_return_if_fail (CLUTTER_IS_BOX (box)); + + clutter_box_set_color_internal (box, color); +} + +/** + * clutter_box_get_color: + * @box: a #ClutterBox + * @color: (out caller-allocates): return location for a #ClutterColor + * + * Retrieves the background color of @box + * + * If the #ClutterBox:color-set property is set to %FALSE the + * returned #ClutterColor is undefined + * + * Since: 1.2 + * + * Deprecated: 1.10: Use clutter_actor_get_background_color() instead. + */ +void +clutter_box_get_color (ClutterBox *box, + ClutterColor *color) +{ + g_return_if_fail (CLUTTER_IS_BOX (box)); + g_return_if_fail (color != NULL); + + clutter_actor_get_background_color (CLUTTER_ACTOR (box), color); +} diff --git a/clutter/clutter/deprecated/clutter-box.h b/clutter/clutter/deprecated/clutter-box.h new file mode 100644 index 0000000..0293aac --- /dev/null +++ b/clutter/clutter/deprecated/clutter-box.h @@ -0,0 +1,143 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2009,2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_BOX_H__ +#define __CLUTTER_BOX_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BOX (clutter_box_get_type ()) +#define CLUTTER_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BOX, ClutterBox)) +#define CLUTTER_IS_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BOX)) +#define CLUTTER_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BOX, ClutterBoxClass)) +#define CLUTTER_IS_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BOX)) +#define CLUTTER_BOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BOX, ClutterBoxClass)) + +typedef struct _ClutterBox ClutterBox; +typedef struct _ClutterBoxPrivate ClutterBoxPrivate; +typedef struct _ClutterBoxClass ClutterBoxClass; + +/** + * ClutterBox: + * + * The #ClutterBox structure contains only private data and should + * be accessed using the provided API + * + * Since: 1.2 + */ +struct _ClutterBox +{ + /*< private >*/ + ClutterActor parent_instance; + + ClutterBoxPrivate *priv; +}; + +/** + * ClutterBoxClass: + * + * The #ClutterBoxClass structure contains only private data + * + * Since: 1.2 + */ +struct _ClutterBoxClass +{ + /*< private >*/ + ClutterActorClass parent_class; + + /* padding, for future expansion */ + void (*clutter_padding_1) (void); + void (*clutter_padding_2) (void); + void (*clutter_padding_3) (void); + void (*clutter_padding_4) (void); + void (*clutter_padding_5) (void); + void (*clutter_padding_6) (void); +}; + +CLUTTER_DEPRECATED_IN_1_10 +GType clutter_box_get_type (void) G_GNUC_CONST; + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_new) +ClutterActor * clutter_box_new (ClutterLayoutManager *manager); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_set_layout_manager) +void clutter_box_set_layout_manager (ClutterBox *box, + ClutterLayoutManager *manager); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_get_layout_manager) +ClutterLayoutManager *clutter_box_get_layout_manager (ClutterBox *box); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_set_background_color) +void clutter_box_set_color (ClutterBox *box, + const ClutterColor *color); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_get_background_color) +void clutter_box_get_color (ClutterBox *box, + ClutterColor *color); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_add_child) +void clutter_box_pack (ClutterBox *box, + ClutterActor *actor, + const gchar *first_property, + ...); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_add_child) +void clutter_box_packv (ClutterBox *box, + ClutterActor *actor, + guint n_properties, + const gchar * const properties[], + const GValue *values); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_insert_child_above) +void clutter_box_pack_after (ClutterBox *box, + ClutterActor *actor, + ClutterActor *sibling, + const gchar *first_property, + ...); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_insert_child_below) +void clutter_box_pack_before (ClutterBox *box, + ClutterActor *actor, + ClutterActor *sibling, + const gchar *first_property, + ...); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_insert_child_at_index) +void clutter_box_pack_at (ClutterBox *box, + ClutterActor *actor, + gint position, + const gchar *first_property, + ...); + +G_END_DECLS + +#endif /* __CLUTTER_BOX_H__ */ diff --git a/clutter/clutter/deprecated/clutter-cairo-texture.c b/clutter/clutter/deprecated/clutter-cairo-texture.c new file mode 100644 index 0000000..6de16d4 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-cairo-texture.c @@ -0,0 +1,1165 @@ +/* + * Clutter + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By: Emmanuele Bassi + * Matthew Allum + * Chris Lord + * Iain Holmes + * Neil Roberts + * + * Copyright (C) 2008, 2009, 2010, 2011 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +/** + * SECTION:clutter-cairo-texture + * @short_description: Texture with Cairo integration + * + * #ClutterCairoTexture is a #ClutterTexture that displays the contents + * of a Cairo context. The #ClutterCairoTexture actor will create a + * Cairo image surface which will then be uploaded to a GL texture when + * needed. + * + * Since #ClutterCairoTexture uses a Cairo image surface + * internally all the drawing operations will be performed in + * software and not using hardware acceleration. This can lead to + * performance degradation if the contents of the texture change + * frequently. + * + * In order to use a #ClutterCairoTexture you should connect to the + * #ClutterCairoTexture::draw signal; the signal is emitted each time + * the #ClutterCairoTexture has been told to invalidate its contents, + * by using clutter_cairo_texture_invalidate_rectangle() or its + * sister function, clutter_cairo_texture_invalidate(). + * + * Each callback to the #ClutterCairoTexture::draw signal will receive + * a #cairo_t context which can be used for drawing; the Cairo context + * is owned by the #ClutterCairoTexture and should not be destroyed + * explicitly. + * + * #ClutterCairoTexture is available since Clutter 1.0. + * + * #ClutterCairoTexture is deprecated since Clutter 1.12. You should + * use #ClutterCanvas instead. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include "deprecated/clutter-texture.h" +#include "deprecated/clutter-cairo-texture.h" + +#include "clutter-cairo-texture.h" + +#include "clutter-actor-private.h" +#include "clutter-cairo.h" +#include "clutter-color.h" +#include "clutter-debug.h" +#include "clutter-marshal.h" +#include "clutter-private.h" + +struct _ClutterCairoTexturePrivate +{ + cairo_surface_t *cr_surface; + + guint surface_width; + guint surface_height; + + cairo_t *cr_context; + + guint auto_resize : 1; +}; + +enum +{ + PROP_0, + + PROP_SURFACE_WIDTH, + PROP_SURFACE_HEIGHT, + PROP_AUTO_RESIZE, + + PROP_LAST +}; + +enum +{ + CREATE_SURFACE, + DRAW, + + LAST_SIGNAL +}; + +static GParamSpec *obj_props[PROP_LAST] = { NULL, }; + +static guint cairo_signals[LAST_SIGNAL] = { 0, }; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterCairoTexture, + clutter_cairo_texture, + CLUTTER_TYPE_TEXTURE) + +#ifdef CLUTTER_ENABLE_DEBUG +#define clutter_warn_if_paint_fail(obj) G_STMT_START { \ + if (CLUTTER_ACTOR_IN_PAINT (obj)) { \ + g_warning ("%s should not be called during the paint sequence " \ + "of a ClutterCairoTexture as it will likely cause " \ + "performance issues.", G_STRFUNC); \ + } } G_STMT_END +#else +#define clutter_warn_if_paint_fail(obj) /* void */ +#endif /* CLUTTER_ENABLE_DEBUG */ + +typedef struct { + ClutterCairoTexture *texture; + + cairo_rectangle_int_t rect; + + guint is_clipped : 1; +} DrawContext; + +static const cairo_user_data_key_t clutter_cairo_texture_context_key; + +static DrawContext * +draw_context_create (ClutterCairoTexture *texture) +{ + DrawContext *context = g_slice_new0 (DrawContext); + + context->texture = g_object_ref (texture); + + return context; +} + +static void +draw_context_destroy (gpointer data) +{ + if (G_LIKELY (data != NULL)) + { + DrawContext *context = data; + + g_object_unref (context->texture); + + g_slice_free (DrawContext, data); + } +} + +static void +clutter_cairo_texture_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterCairoTexturePrivate *priv; + + priv = CLUTTER_CAIRO_TEXTURE (object)->priv; + + switch (prop_id) + { + case PROP_SURFACE_WIDTH: + /* we perform the resize on notify to coalesce separate + * surface-width/surface-height property set + */ + priv->surface_width = g_value_get_uint (value); + break; + + case PROP_SURFACE_HEIGHT: + priv->surface_height = g_value_get_uint (value); + break; + + case PROP_AUTO_RESIZE: + clutter_cairo_texture_set_auto_resize (CLUTTER_CAIRO_TEXTURE (object), + g_value_get_boolean (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_cairo_texture_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterCairoTexturePrivate *priv; + + priv = CLUTTER_CAIRO_TEXTURE (object)->priv; + + switch (prop_id) + { + case PROP_SURFACE_WIDTH: + g_value_set_uint (value, priv->surface_width); + break; + + case PROP_SURFACE_HEIGHT: + g_value_set_uint (value, priv->surface_height); + break; + + case PROP_AUTO_RESIZE: + g_value_set_boolean (value, priv->auto_resize); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_cairo_texture_finalize (GObject *object) +{ + ClutterCairoTexturePrivate *priv = CLUTTER_CAIRO_TEXTURE (object)->priv; + + if (priv->cr_surface != NULL) + { + cairo_surface_t *surface = priv->cr_surface; + + priv->cr_surface = NULL; + + cairo_surface_finish (surface); + cairo_surface_destroy (surface); + } + + G_OBJECT_CLASS (clutter_cairo_texture_parent_class)->finalize (object); +} + +static cairo_surface_t * +get_surface (ClutterCairoTexture *self) +{ + ClutterCairoTexturePrivate *priv = self->priv; + + if (priv->cr_surface == NULL) + { + g_signal_emit (self, cairo_signals[CREATE_SURFACE], 0, + priv->surface_width, + priv->surface_height, + &priv->cr_surface); + } + + return priv->cr_surface; +} + +static void +clutter_cairo_texture_context_destroy (void *data) +{ + DrawContext *ctxt = data; + ClutterCairoTexture *cairo = ctxt->texture; + ClutterCairoTexturePrivate *priv = cairo->priv; + guint8 *cairo_data; + gint cairo_width, cairo_height, cairo_stride; + gint surface_width, surface_height; + CoglHandle cogl_texture; + + if (priv->cr_surface == NULL) + { + /* the surface went away before we could use it */ + draw_context_destroy (ctxt); + return; + } + + /* for any other surface type, we presume that there exists a native + * communication between Cairo and GL that is triggered by cairo_destroy(). + * + * for instance, cairo-drm will flush the outstanding modifications to the + * surface upon context destruction and so the texture is automatically + * updated. + */ + if (cairo_surface_get_type (priv->cr_surface) != CAIRO_SURFACE_TYPE_IMAGE) + goto out; + + surface_width = cairo_image_surface_get_width (priv->cr_surface); + surface_height = cairo_image_surface_get_height (priv->cr_surface); + + cairo_width = MIN (ctxt->rect.width, surface_width); + cairo_height = MIN (ctxt->rect.height, surface_height); + + cogl_texture = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (cairo)); + if (cairo_width == 0 || + cairo_height == 0 || + cogl_texture == COGL_INVALID_HANDLE) + { + draw_context_destroy (ctxt); + return; + } + + cairo_stride = cairo_image_surface_get_stride (priv->cr_surface); + cairo_data = cairo_image_surface_get_data (priv->cr_surface); + cairo_data += cairo_stride * ctxt->rect.y; + cairo_data += 4 * ctxt->rect.x; + + cogl_texture_set_region (cogl_texture, + 0, 0, + ctxt->rect.x, ctxt->rect.y, + cairo_width, cairo_height, + cairo_width, cairo_height, + CLUTTER_CAIRO_FORMAT_ARGB32, + cairo_stride, + cairo_data); + +out: + draw_context_destroy (ctxt); + clutter_actor_queue_redraw (CLUTTER_ACTOR (cairo)); +} + +static inline void +clutter_cairo_texture_emit_draw (ClutterCairoTexture *self, + DrawContext *ctxt) +{ + gboolean result; + cairo_t *cr; + + /* 0x0 surfaces don't need a ::draw */ + if (self->priv->surface_width == 0 || + self->priv->surface_height == 0) + return; + + /* if the size is !0 then we must have a surface */ + g_assert (self->priv->cr_surface != NULL); + + cr = cairo_create (self->priv->cr_surface); + + if (ctxt->is_clipped) + { + cairo_rectangle (cr, + ctxt->rect.x, + ctxt->rect.y, + ctxt->rect.width, + ctxt->rect.height); + cairo_clip (cr); + } + + /* store the cairo_t as a guard */ + self->priv->cr_context = cr; + + g_signal_emit (self, cairo_signals[DRAW], 0, cr, &result); + + self->priv->cr_context = NULL; + + clutter_cairo_texture_context_destroy (ctxt); + + cairo_destroy (cr); +} + +static inline void +clutter_cairo_texture_surface_resize_internal (ClutterCairoTexture *cairo) +{ + ClutterCairoTexturePrivate *priv = cairo->priv; + + if (priv->cr_surface != NULL) + { + cairo_surface_t *surface = priv->cr_surface; + + /* if the surface is an image one, and the size is already the + * same, then we don't need to do anything + */ + if (cairo_surface_get_type (surface) != CAIRO_SURFACE_TYPE_IMAGE) + { + gint surface_width = cairo_image_surface_get_width (surface); + gint surface_height = cairo_image_surface_get_height (surface); + + if (priv->surface_width == surface_width && + priv->surface_height == surface_height) + return; + } + + cairo_surface_finish (surface); + cairo_surface_destroy (surface); + priv->cr_surface = NULL; + } + + if (priv->surface_width == 0 || + priv->surface_height == 0) + return; + + g_signal_emit (cairo, cairo_signals[CREATE_SURFACE], 0, + priv->surface_width, + priv->surface_height, + &priv->cr_surface); +} + +static void +clutter_cairo_texture_notify (GObject *object, + GParamSpec *pspec) +{ + /* When the surface width or height changes then resize the cairo + surface. This is done here instead of directly in set_property so + that if both the width and height properties are set using a + single call to g_object_set then the surface will only be resized + once because the notifications will be frozen in between */ + + if (obj_props[PROP_SURFACE_WIDTH]->name == pspec->name || + obj_props[PROP_SURFACE_HEIGHT]->name == pspec->name) + { + ClutterCairoTexture *cairo = CLUTTER_CAIRO_TEXTURE (object); + + clutter_cairo_texture_surface_resize_internal (cairo); + } + + if (G_OBJECT_CLASS (clutter_cairo_texture_parent_class)->notify) + G_OBJECT_CLASS (clutter_cairo_texture_parent_class)->notify (object, pspec); +} + +static void +clutter_cairo_texture_get_preferred_width (ClutterActor *actor, + gfloat for_height, + gfloat *min_width, + gfloat *natural_width) +{ + ClutterCairoTexturePrivate *priv = CLUTTER_CAIRO_TEXTURE (actor)->priv; + + if (min_width) + *min_width = 0; + + if (natural_width) + *natural_width = (gfloat) priv->surface_width; +} + +static void +clutter_cairo_texture_get_preferred_height (ClutterActor *actor, + gfloat for_width, + gfloat *min_height, + gfloat *natural_height) +{ + ClutterCairoTexturePrivate *priv = CLUTTER_CAIRO_TEXTURE (actor)->priv; + + if (min_height) + *min_height = 0; + + if (natural_height) + *natural_height = (gfloat) priv->surface_height; +} + +static void +clutter_cairo_texture_allocate (ClutterActor *self, + const ClutterActorBox *allocation, + ClutterAllocationFlags flags) +{ + ClutterCairoTexturePrivate *priv = CLUTTER_CAIRO_TEXTURE (self)->priv; + ClutterActorClass *parent_class; + + parent_class = CLUTTER_ACTOR_CLASS (clutter_cairo_texture_parent_class); + parent_class->allocate (self, allocation, flags); + + if (priv->auto_resize) + { + ClutterCairoTexture *texture = CLUTTER_CAIRO_TEXTURE (self); + gfloat width, height; + + clutter_actor_box_get_size (allocation, &width, &height); + + priv->surface_width = ceilf (width); + priv->surface_height = ceilf (height); + + clutter_cairo_texture_surface_resize_internal (texture); + clutter_cairo_texture_invalidate (texture); + } +} + +static gboolean +clutter_cairo_texture_get_paint_volume (ClutterActor *self, + ClutterPaintVolume *volume) +{ + return _clutter_actor_set_default_paint_volume (self, + CLUTTER_TYPE_CAIRO_TEXTURE, + volume); +} + +static cairo_surface_t * +clutter_cairo_texture_create_surface (ClutterCairoTexture *self, + guint width, + guint height) +{ + cairo_surface_t *surface; + guint cairo_stride; + guint8 *cairo_data; + CoglHandle cogl_texture; + + surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, + width, + height); + + cairo_stride = cairo_image_surface_get_stride (surface); + cairo_data = cairo_image_surface_get_data (surface); + + /* create a backing Cogl texture */ + cogl_texture = cogl_texture_new_from_data (width, height, + COGL_TEXTURE_NONE, + CLUTTER_CAIRO_FORMAT_ARGB32, + COGL_PIXEL_FORMAT_ANY, + cairo_stride, + cairo_data); + clutter_texture_set_cogl_texture (CLUTTER_TEXTURE (self), cogl_texture); + cogl_handle_unref (cogl_texture); + + return surface; +} + +static gboolean +create_surface_accum (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer data) +{ + g_value_copy (handler_return, return_accu); + + /* stop on the first non-NULL return value */ + return g_value_get_boxed (handler_return) == NULL; +} + +static void +clutter_cairo_texture_draw_marshaller (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + cairo_t *cr = g_value_get_boxed (¶m_values[1]); + + cairo_save (cr); + + _clutter_marshal_BOOLEAN__BOXED (closure, + return_value, + n_param_values, + param_values, + invocation_hint, + marshal_data); + + cairo_restore (cr); +} + +static void +clutter_cairo_texture_class_init (ClutterCairoTextureClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + + gobject_class->finalize = clutter_cairo_texture_finalize; + gobject_class->set_property = clutter_cairo_texture_set_property; + gobject_class->get_property = clutter_cairo_texture_get_property; + gobject_class->notify = clutter_cairo_texture_notify; + + actor_class->get_paint_volume = + clutter_cairo_texture_get_paint_volume; + actor_class->get_preferred_width = + clutter_cairo_texture_get_preferred_width; + actor_class->get_preferred_height = + clutter_cairo_texture_get_preferred_height; + actor_class->allocate = + clutter_cairo_texture_allocate; + + klass->create_surface = clutter_cairo_texture_create_surface; + + /** + * ClutterCairoTexture:surface-width: + * + * The width of the Cairo surface used by the #ClutterCairoTexture + * actor, in pixels. + * + * Since: 1.0 + * + * Deprecated: 1.12 + */ + obj_props[PROP_SURFACE_WIDTH] = + g_param_spec_uint ("surface-width", + P_("Surface Width"), + P_("The width of the Cairo surface"), + 0, G_MAXUINT, + 0, + CLUTTER_PARAM_READWRITE | + G_PARAM_DEPRECATED); + /** + * ClutterCairoTexture:surface-height: + * + * The height of the Cairo surface used by the #ClutterCairoTexture + * actor, in pixels. + * + * Since: 1.0 + * + * Deprecated: 1.12 + */ + obj_props[PROP_SURFACE_HEIGHT] = + g_param_spec_uint ("surface-height", + P_("Surface Height"), + P_("The height of the Cairo surface"), + 0, G_MAXUINT, + 0, + CLUTTER_PARAM_READWRITE | + G_PARAM_DEPRECATED); + + /** + * ClutterCairoTexture:auto-resize: + * + * Controls whether the #ClutterCairoTexture should automatically + * resize the Cairo surface whenever the actor's allocation changes. + * If :auto-resize is set to %TRUE the surface contents will also + * be invalidated automatically. + * + * Since: 1.8 + * + * Deprecated: 1.12 + */ + obj_props[PROP_AUTO_RESIZE] = + g_param_spec_boolean ("auto-resize", + P_("Auto Resize"), + P_("Whether the surface should match the allocation"), + FALSE, + CLUTTER_PARAM_READWRITE | + G_PARAM_DEPRECATED); + + g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); + + /** + * ClutterCairoTexture::create-surface: + * @texture: the #ClutterCairoTexture that emitted the signal + * @width: the width of the surface to create + * @height: the height of the surface to create + * + * The ::create-surface signal is emitted when a #ClutterCairoTexture + * news its surface (re)created, which happens either when the Cairo + * context is created with clutter_cairo_texture_create() or + * clutter_cairo_texture_create_region(), or when the surface is resized + * through clutter_cairo_texture_set_surface_size(). + * + * The first signal handler that returns a non-%NULL, valid surface will + * stop any further signal emission, and the returned surface will be + * the one used. + * + * Return value: the newly created #cairo_surface_t for the texture + * + * Since: 1.6 + * + * Deprecated: 1.12 + */ + cairo_signals[CREATE_SURFACE] = + g_signal_new (I_("create-surface"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (ClutterCairoTextureClass, create_surface), + create_surface_accum, NULL, + _clutter_marshal_BOXED__UINT_UINT, + CAIRO_GOBJECT_TYPE_SURFACE, 2, + G_TYPE_UINT, + G_TYPE_UINT); + + /** + * ClutterCairoTexture::draw: + * @texture: the #ClutterCairoTexture that emitted the signal + * @cr: the Cairo context to use to draw + * + * The ::draw signal is emitted each time a #ClutterCairoTexture has + * been invalidated. + * + * The passed Cairo context passed will be clipped to the invalidated + * area. + * + * It is safe to connect multiple callbacks to this signals; the state + * of the Cairo context passed to each callback is automatically saved + * and restored, so it's not necessary to call cairo_save() and + * cairo_restore(). + * + * Return value: %TRUE if the signal emission should stop, and %FALSE + * to continue + * + * Since: 1.8 + * + * Deprecated: 1.12 + */ + cairo_signals[DRAW] = + g_signal_new (I_("draw"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (ClutterCairoTextureClass, draw), + _clutter_boolean_handled_accumulator, NULL, + clutter_cairo_texture_draw_marshaller, + G_TYPE_BOOLEAN, 1, + CAIRO_GOBJECT_TYPE_CONTEXT); +} + +static void +clutter_cairo_texture_init (ClutterCairoTexture *self) +{ + self->priv = clutter_cairo_texture_get_instance_private (self); + + /* FIXME - we are hardcoding the format; it would be good to have + * a :surface-format construct-only property for creating + * textures with a different format and have the cairo surface + * match that format + * + * priv->format = CAIRO_FORMAT_ARGB32; + */ + + /* the Cairo surface is responsible for driving the size of + * the texture; if we let sync_size to its default of TRUE, + * the Texture will try to queue a relayout every time we + * change the size of the Cairo surface - which is not what + * we want + */ + clutter_texture_set_sync_size (CLUTTER_TEXTURE (self), FALSE); +} + +/** + * clutter_cairo_texture_new: + * @width: the width of the surface + * @height: the height of the surface + * + * Creates a new #ClutterCairoTexture actor, with a surface of @width by + * @height pixels. + * + * Return value: the newly created #ClutterCairoTexture actor + * + * Since: 1.0 + * + * Deprecated: 1.12: Use #ClutterCanvas instead + */ +ClutterActor* +clutter_cairo_texture_new (guint width, + guint height) +{ + return g_object_new (CLUTTER_TYPE_CAIRO_TEXTURE, + "surface-width", width, + "surface-height", height, + NULL); +} + +static void +intersect_rectangles (cairo_rectangle_int_t *a, + cairo_rectangle_int_t *b, + cairo_rectangle_int_t *inter) +{ + gint dest_x, dest_y; + gint dest_width, dest_height; + + dest_x = MAX (a->x, b->x); + dest_y = MAX (a->y, b->y); + dest_width = MIN (a->x + a->width, b->x + b->width) - dest_x; + dest_height = MIN (a->y + a->height, b->y + b->height) - dest_y; + + if (dest_width > 0 && dest_height > 0) + { + inter->x = dest_x; + inter->y = dest_y; + inter->width = dest_width; + inter->height = dest_height; + } + else + { + inter->x = 0; + inter->y = 0; + inter->width = 0; + inter->height = 0; + } +} + +static cairo_t * +clutter_cairo_texture_create_region_internal (ClutterCairoTexture *self, + gint x_offset, + gint y_offset, + gint width, + gint height) +{ + ClutterCairoTexturePrivate *priv = self->priv; + cairo_rectangle_int_t region, area, inter; + cairo_surface_t *surface; + DrawContext *ctxt; + cairo_t *cr; + + if (width < 0) + width = priv->surface_width; + + if (height < 0) + height = priv->surface_height; + + if (width == 0 || height == 0) + { + g_warning ("Unable to create a context for an image surface of " + "width %d and height %d. Set the surface size to be " + "at least 1 pixel by 1 pixel.", + width, height); + return NULL; + } + + surface = get_surface (self); + + ctxt = draw_context_create (self); + + region.x = x_offset; + region.y = y_offset; + region.width = width; + region.height = height; + + area.x = 0; + area.y = 0; + area.width = priv->surface_width; + area.height = priv->surface_height; + + /* Limit the region to the visible rectangle */ + intersect_rectangles (&area, ®ion, &inter); + + ctxt->rect = inter; + + cr = cairo_create (surface); + cairo_set_user_data (cr, &clutter_cairo_texture_context_key, + ctxt, + clutter_cairo_texture_context_destroy); + + return cr; +} + +/** + * clutter_cairo_texture_create_region: + * @self: a #ClutterCairoTexture + * @x_offset: offset of the region on the X axis + * @y_offset: offset of the region on the Y axis + * @width: width of the region, or -1 for the full surface width + * @height: height of the region, or -1 for the full surface height + * + * Creates a new Cairo context that will updat the region defined + * by @x_offset, @y_offset, @width and @height. + * + * Do not call this function within the paint virtual + * function or from a callback to the #ClutterActor::paint + * signal. + * + * Return value: a newly created Cairo context. Use cairo_destroy() + * to upload the contents of the context when done drawing + * + * Since: 1.0 + * + * Deprecated: 1.8: Use the #ClutterCairoTexture::draw signal and + * clutter_cairo_texture_invalidate_rectangle() to obtain a + * clipped Cairo context for 2D drawing. + */ +cairo_t * +clutter_cairo_texture_create_region (ClutterCairoTexture *self, + gint x_offset, + gint y_offset, + gint width, + gint height) +{ + g_return_val_if_fail (CLUTTER_IS_CAIRO_TEXTURE (self), NULL); + + clutter_warn_if_paint_fail (self); + + return clutter_cairo_texture_create_region_internal (self, + x_offset, y_offset, + width, height); +} + +/** + * clutter_cairo_texture_invalidate_rectangle: + * @self: a #ClutterCairoTexture + * @rect: (allow-none): a rectangle with the area to invalida, + * or %NULL to perform an unbounded invalidation + * + * Invalidates a rectangular region of a #ClutterCairoTexture. + * + * The invalidation will cause the #ClutterCairoTexture::draw signal + * to be emitted. + * + * See also: clutter_cairo_texture_invalidate() + * + * Since: 1.8 + * Deprecated: 1.12: Use #ClutterCanvas instead + */ +void +clutter_cairo_texture_invalidate_rectangle (ClutterCairoTexture *self, + cairo_rectangle_int_t *rect) +{ + DrawContext *ctxt = NULL; + + g_return_if_fail (CLUTTER_IS_CAIRO_TEXTURE (self)); + + if (self->priv->cr_context != NULL) + { + g_warning ("It is not possible to invalidate a Cairo texture" + "while drawing into it."); + return; + } + + ctxt = draw_context_create (self); + + if (rect != NULL) + { + cairo_rectangle_int_t area, inter; + + area.x = 0; + area.y = 0; + area.width = self->priv->surface_width; + area.height = self->priv->surface_height; + + /* Limit the region to the visible rectangle */ + intersect_rectangles (&area, rect, &inter); + + ctxt->is_clipped = TRUE; + ctxt->rect = inter; + } + else + { + ctxt->is_clipped = FALSE; + ctxt->rect.x = ctxt->rect.y = 0; + ctxt->rect.width = self->priv->surface_width; + ctxt->rect.height = self->priv->surface_height; + } + + /* XXX - it might be good to move the emission inside the paint cycle + * using a repaint function, to avoid blocking inside this function + */ + clutter_cairo_texture_emit_draw (self, ctxt); +} + +/** + * clutter_cairo_texture_invalidate: + * @self: a #ClutterCairoTexture + * + * Invalidates the whole surface of a #ClutterCairoTexture. + * + * This function will cause the #ClutterCairoTexture::draw signal + * to be emitted. + * + * See also: clutter_cairo_texture_invalidate_rectangle() + * + * Since: 1.8 + * Deprecated: 1.12: Use #ClutterCanvas instead + */ +void +clutter_cairo_texture_invalidate (ClutterCairoTexture *self) +{ + g_return_if_fail (CLUTTER_IS_CAIRO_TEXTURE (self)); + + clutter_cairo_texture_invalidate_rectangle (self, NULL); +} + +/** + * clutter_cairo_texture_create: + * @self: a #ClutterCairoTexture + * + * Creates a new Cairo context for the @cairo texture. It is + * similar to using clutter_cairo_texture_create_region() with @x_offset + * and @y_offset of 0, @width equal to the @cairo texture surface width + * and @height equal to the @cairo texture surface height. + * + * Do not call this function within the paint virtual + * function or from a callback to the #ClutterActor::paint + * signal. + * + * Return value: a newly created Cairo context. Use cairo_destroy() + * to upload the contents of the context when done drawing + * + * Since: 1.0 + * + * Deprecated: 1.8: Use the #ClutterCairoTexture::draw signal and + * the clutter_cairo_texture_invalidate() function to obtain a + * Cairo context for 2D drawing. + */ +cairo_t * +clutter_cairo_texture_create (ClutterCairoTexture *self) +{ + g_return_val_if_fail (CLUTTER_IS_CAIRO_TEXTURE (self), NULL); + + clutter_warn_if_paint_fail (self); + + return clutter_cairo_texture_create_region_internal (self, 0, 0, -1, -1); +} + +/** + * clutter_cairo_texture_set_surface_size: + * @self: a #ClutterCairoTexture + * @width: the new width of the surface + * @height: the new height of the surface + * + * Resizes the Cairo surface used by @self to @width and @height. + * + * This function will not invalidate the contents of the Cairo + * texture: you will have to explicitly call either + * clutter_cairo_texture_invalidate_rectangle() or + * clutter_cairo_texture_invalidate(). + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterCanvas instead + */ +void +clutter_cairo_texture_set_surface_size (ClutterCairoTexture *self, + guint width, + guint height) +{ + ClutterCairoTexturePrivate *priv; + + g_return_if_fail (CLUTTER_IS_CAIRO_TEXTURE (self)); + + priv = self->priv; + + if (width == priv->surface_width && + height == priv->surface_height) + return; + + g_object_freeze_notify (G_OBJECT (self)); + + if (priv->surface_width != width) + { + priv->surface_width = width; + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SURFACE_WIDTH]); + } + + if (priv->surface_height != height) + { + priv->surface_height = height; + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SURFACE_HEIGHT]); + } + + clutter_cairo_texture_surface_resize_internal (self); + + g_object_thaw_notify (G_OBJECT (self)); +} + +/** + * clutter_cairo_texture_get_surface_size: + * @self: a #ClutterCairoTexture + * @width: (out): return location for the surface width, or %NULL + * @height: (out): return location for the surface height, or %NULL + * + * Retrieves the surface width and height for @self. + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterCanvas instead + */ +void +clutter_cairo_texture_get_surface_size (ClutterCairoTexture *self, + guint *width, + guint *height) +{ + g_return_if_fail (CLUTTER_IS_CAIRO_TEXTURE (self)); + + if (width) + *width = self->priv->surface_width; + + if (height) + *height = self->priv->surface_height; +} + +/** + * clutter_cairo_texture_clear: + * @self: a #ClutterCairoTexture + * + * Clears @self's internal drawing surface, so that the next upload + * will replace the previous contents of the #ClutterCairoTexture + * rather than adding to it. + * + * Calling this function from within a #ClutterCairoTexture::draw + * signal handler will clear the invalidated area. + * + * Since: 1.0 + * Deprecated: 1.12: Use #ClutterCanvas instead + */ +void +clutter_cairo_texture_clear (ClutterCairoTexture *self) +{ + ClutterCairoTexturePrivate *priv; + cairo_t *cr; + + g_return_if_fail (CLUTTER_IS_CAIRO_TEXTURE (self)); + + priv = self->priv; + + /* if we got called outside of a ::draw signal handler + * then we clear the whole surface by creating a temporary + * cairo_t; otherwise, we clear the current cairo_t, which + * will take into account the clip region. + */ + if (priv->cr_context == NULL) + { + cairo_surface_t *surface; + + surface = get_surface (self); + + cr = cairo_create (surface); + } + else + cr = priv->cr_context; + + cairo_save (cr); + + cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); + cairo_paint (cr); + + cairo_restore (cr); + + if (priv->cr_context == NULL) + cairo_destroy (cr); +} + +/** + * clutter_cairo_texture_set_auto_resize: + * @self: a #ClutterCairoTexture + * @value: %TRUE if the #ClutterCairoTexture should bind the surface + * size to the allocation + * + * Sets whether the #ClutterCairoTexture should ensure that the + * backing Cairo surface used matches the allocation assigned to + * the actor. If the allocation changes, the contents of the + * #ClutterCairoTexture will also be invalidated automatically. + * + * Since: 1.8 + * Deprecated: 1.12: Use #ClutterCanvas instead + */ +void +clutter_cairo_texture_set_auto_resize (ClutterCairoTexture *self, + gboolean value) +{ + ClutterCairoTexturePrivate *priv; + + g_return_if_fail (CLUTTER_IS_CAIRO_TEXTURE (self)); + + value = !!value; + + priv = self->priv; + + if (priv->auto_resize == value) + return; + + priv->auto_resize = value; + + clutter_actor_queue_relayout (CLUTTER_ACTOR (self)); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_AUTO_RESIZE]); +} + +/** + * clutter_cairo_texture_get_auto_resize: + * @self: a #ClutterCairoTexture + * + * Retrieves the value set using clutter_cairo_texture_set_auto_resize(). + * + * Return value: %TRUE if the #ClutterCairoTexture should track the + * allocation, and %FALSE otherwise + * + * Since: 1.8 + * Deprecated: 1.12: Use #ClutterCanvas instead + */ +gboolean +clutter_cairo_texture_get_auto_resize (ClutterCairoTexture *self) +{ + g_return_val_if_fail (CLUTTER_IS_CAIRO_TEXTURE (self), FALSE); + + return self->priv->auto_resize; +} diff --git a/clutter/clutter/deprecated/clutter-cairo-texture.h b/clutter/clutter/deprecated/clutter-cairo-texture.h new file mode 100644 index 0000000..63b6158 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-cairo-texture.h @@ -0,0 +1,139 @@ +/* + * Clutter + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By: Emmanuele Bassi + * Matthew Allum + * Chris Lord + * Iain Holmes + * Neil Roberts + * + * Copyright (C) 2008, 2009, 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_CAIRO_TEXTURE_H__ +#define __CLUTTER_CAIRO_TEXTURE_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_CAIRO_TEXTURE (clutter_cairo_texture_get_type ()) +#define CLUTTER_CAIRO_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_CAIRO_TEXTURE, ClutterCairoTexture)) +#define CLUTTER_CAIRO_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_CAIRO_TEXTURE, ClutterCairoTextureClass)) +#define CLUTTER_IS_CAIRO_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_CAIRO_TEXTURE)) +#define CLUTTER_IS_CAIRO_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_CAIRO_TEXTURE)) +#define CLUTTER_CAIRO_TEXTURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_CAIRO_TEXTURE, ClutterCairoTextureClass)) + +typedef struct _ClutterCairoTexture ClutterCairoTexture; +typedef struct _ClutterCairoTextureClass ClutterCairoTextureClass; +typedef struct _ClutterCairoTexturePrivate ClutterCairoTexturePrivate; + +/** + * ClutterCairoTexture: + * + * The #ClutterCairoTexture struct contains only private data. + * + * Since: 1.0 + * + * Deprecated: 1.12: Use #ClutterCanvas instead + */ +struct _ClutterCairoTexture +{ + /*< private >*/ + ClutterTexture parent_instance; + + ClutterCairoTexturePrivate *priv; +}; + +/** + * ClutterCairoTextureClass: + * @create_surface: class handler for the #ClutterCairoTexture::create-surface + * signal + * @draw: class handler for the #ClutterCairoTexture::draw signal + * + * The #ClutterCairoTextureClass struct contains only private data. + * + * Since: 1.0 + * + * Deprecated: 1.12: Use #ClutterCanvas instead + */ +struct _ClutterCairoTextureClass +{ + /*< private >*/ + ClutterTextureClass parent_class; + + /*< public >*/ + cairo_surface_t *(* create_surface) (ClutterCairoTexture *texture, + guint width, + guint height); + + gboolean (* draw) (ClutterCairoTexture *texture, + cairo_t *cr); + + /*< private >*/ + void (*_clutter_cairo_3) (void); + void (*_clutter_cairo_4) (void); +}; + +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_canvas_get_type) +GType clutter_cairo_texture_get_type (void) G_GNUC_CONST; + +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_canvas_new) +ClutterActor * clutter_cairo_texture_new (guint width, + guint height); + +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_canvas_set_size) +void clutter_cairo_texture_set_surface_size (ClutterCairoTexture *self, + guint width, + guint height); +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_canvas_get_size) +void clutter_cairo_texture_get_surface_size (ClutterCairoTexture *self, + guint *width, + guint *height); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_cairo_texture_set_auto_resize (ClutterCairoTexture *self, + gboolean value); +CLUTTER_DEPRECATED_IN_1_12 +gboolean clutter_cairo_texture_get_auto_resize (ClutterCairoTexture *self); + +CLUTTER_DEPRECATED_IN_1_12 +void clutter_cairo_texture_clear (ClutterCairoTexture *self); + +CLUTTER_DEPRECATED_IN_1_12 +void clutter_cairo_texture_invalidate_rectangle (ClutterCairoTexture *self, + cairo_rectangle_int_t *rect); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_cairo_texture_invalidate (ClutterCairoTexture *self); + +CLUTTER_DEPRECATED_IN_1_8_FOR(clutter_cairo_texture_invalidate_rectangle) +cairo_t * clutter_cairo_texture_create_region (ClutterCairoTexture *self, + gint x_offset, + gint y_offset, + gint width, + gint height); + +CLUTTER_DEPRECATED_IN_1_8_FOR(clutter_cairo_texture_invalidate) +cairo_t * clutter_cairo_texture_create (ClutterCairoTexture *self); + +G_END_DECLS + +#endif /* __CLUTTER_CAIRO_TEXTURE_DEPRECATED_H__ */ diff --git a/clutter/clutter/deprecated/clutter-container.h b/clutter/clutter/deprecated/clutter-container.h new file mode 100644 index 0000000..38e7898 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-container.h @@ -0,0 +1,93 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2011 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * ClutterContainer: Generic actor container interface. + * + * Author: Emmanuele Bassi + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_CONTAINER_DEPRECATED_H__ +#define __CLUTTER_CONTAINER_DEPRECATED_H__ + +#include + +G_BEGIN_DECLS + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_add_child) +void clutter_container_add (ClutterContainer *container, + ClutterActor *first_actor, + ...) G_GNUC_NULL_TERMINATED; + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_add_child) +void clutter_container_add_actor (ClutterContainer *container, + ClutterActor *actor); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_add_child) +void clutter_container_add_valist (ClutterContainer *container, + ClutterActor *first_actor, + va_list var_args); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_remove_child) +void clutter_container_remove (ClutterContainer *container, + ClutterActor *first_actor, + ...) G_GNUC_NULL_TERMINATED; + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_remove_child) +void clutter_container_remove_actor (ClutterContainer *container, + ClutterActor *actor); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_remove_child) +void clutter_container_remove_valist (ClutterContainer *container, + ClutterActor *first_actor, + va_list var_args); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_get_children) +GList * clutter_container_get_children (ClutterContainer *container); + +CLUTTER_DEPRECATED_IN_1_10 +void clutter_container_foreach (ClutterContainer *container, + ClutterCallback callback, + gpointer user_data); + +CLUTTER_DEPRECATED_IN_1_10 +void clutter_container_foreach_with_internals (ClutterContainer *container, + ClutterCallback callback, + gpointer user_data); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_set_child_above_sibling) +void clutter_container_raise_child (ClutterContainer *container, + ClutterActor *actor, + ClutterActor *sibling); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_set_child_below_sibling) +void clutter_container_lower_child (ClutterContainer *container, + ClutterActor *actor, + ClutterActor *sibling); + +CLUTTER_DEPRECATED_IN_1_10 +void clutter_container_sort_depth_order (ClutterContainer *container); + +G_END_DECLS + +#endif /* __CLUTTER_CONTAINER_DEPRECATED_H__ */ diff --git a/clutter/clutter/deprecated/clutter-frame-source.c b/clutter/clutter/deprecated/clutter-frame-source.c new file mode 100644 index 0000000..5bff608 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-frame-source.c @@ -0,0 +1,263 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Neil Roberts + * + * Copyright (C) 2008 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS + +#include "clutter-main.h" +#include "clutter-private.h" + +#include "deprecated/clutter-frame-source.h" +#include "deprecated/clutter-timeout-interval.h" + +typedef struct _ClutterFrameSource ClutterFrameSource; + +struct _ClutterFrameSource +{ + GSource source; + + ClutterTimeoutInterval timeout; +}; + +static gboolean clutter_frame_source_prepare (GSource *source, + gint *timeout); +static gboolean clutter_frame_source_check (GSource *source); +static gboolean clutter_frame_source_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data); + +static GSourceFuncs clutter_frame_source_funcs = +{ + clutter_frame_source_prepare, + clutter_frame_source_check, + clutter_frame_source_dispatch, + NULL +}; + +/** + * clutter_frame_source_add_full: (rename-to clutter_frame_source_add) + * @priority: the priority of the frame source. Typically this will be in the + * range between %G_PRIORITY_DEFAULT and %G_PRIORITY_HIGH. + * @fps: the number of times per second to call the function + * @func: function to call + * @data: data to pass to the function + * @notify: function to call when the timeout source is removed + * + * Sets a function to be called at regular intervals with the given + * priority. The function is called repeatedly until it returns + * %FALSE, at which point the timeout is automatically destroyed and + * the function will not be called again. The @notify function is + * called when the timeout is destroyed. The first call to the + * function will be at the end of the first @interval. + * + * This function is similar to g_timeout_add_full() except that it + * will try to compensate for delays. For example, if @func takes half + * the interval time to execute then the function will be called again + * half the interval time after it finished. In contrast + * g_timeout_add_full() would not fire until a full interval after the + * function completes so the delay between calls would be 1.0 / @fps * + * 1.5. This function does not however try to invoke the function + * multiple times to catch up missing frames if @func takes more than + * @interval ms to execute. + * + * Return value: the ID (greater than 0) of the event source. + * + * Since: 0.8 + * + * Deprecated: 1.6: There is no direct replacement for this API. + */ +guint +clutter_frame_source_add_full (gint priority, + guint fps, + GSourceFunc func, + gpointer data, + GDestroyNotify notify) +{ + guint ret; + GSource *source = g_source_new (&clutter_frame_source_funcs, + sizeof (ClutterFrameSource)); + ClutterFrameSource *frame_source = (ClutterFrameSource *) source; + + _clutter_timeout_interval_init (&frame_source->timeout, fps); + + if (priority != G_PRIORITY_DEFAULT) + g_source_set_priority (source, priority); + + g_source_set_name (source, "Clutter frame timeout"); + g_source_set_callback (source, func, data, notify); + + ret = g_source_attach (source, NULL); + + g_source_unref (source); + + return ret; +} + +/** + * clutter_frame_source_add: (skip) + * @fps: the number of times per second to call the function + * @func: function to call + * @data: data to pass to the function + * + * Simple wrapper around clutter_frame_source_add_full(). + * + * Return value: the ID (greater than 0) of the event source. + * + * Since: 0.8 + * + * Deprecated: 1.6: There is no direct replacement for this API + */ +guint +clutter_frame_source_add (guint fps, + GSourceFunc func, + gpointer data) +{ + return clutter_frame_source_add_full (G_PRIORITY_DEFAULT, + fps, func, data, NULL); +} + +static gboolean +clutter_frame_source_prepare (GSource *source, + gint *delay) +{ + ClutterFrameSource *frame_source = (ClutterFrameSource *) source; + gint64 current_time; + +#if GLIB_CHECK_VERSION (2, 27, 3) + current_time = g_source_get_time (source) / 1000; +#else + { + GTimeVal source_time; + g_source_get_current_time (source, &source_time); + current_time = source_time.tv_sec * 1000 + source_time.tv_usec / 1000; + } +#endif + + return _clutter_timeout_interval_prepare (current_time, + &frame_source->timeout, + delay); +} + +static gboolean +clutter_frame_source_check (GSource *source) +{ + return clutter_frame_source_prepare (source, NULL); +} + +static gboolean +clutter_frame_source_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + ClutterFrameSource *frame_source = (ClutterFrameSource *) source; + + return _clutter_timeout_interval_dispatch (&frame_source->timeout, + callback, user_data); +} + +/** + * clutter_threads_add_frame_source_full: (rename-to clutter_threads_add_frame_source) + * @priority: the priority of the frame source. Typically this will be in the + * range between %G_PRIORITY_DEFAULT and %G_PRIORITY_HIGH. + * @fps: the number of times per second to call the function + * @func: function to call + * @data: data to pass to the function + * @notify: function to call when the timeout source is removed + * + * Sets a function to be called at regular intervals holding the Clutter + * threads lock, with the given priority. The function is called repeatedly + * until it returns %FALSE, at which point the timeout is automatically + * removed and the function will not be called again. The @notify function + * is called when the timeout is removed. + * + * This function is similar to clutter_threads_add_timeout_full() + * except that it will try to compensate for delays. For example, if + * @func takes half the interval time to execute then the function + * will be called again half the interval time after it finished. In + * contrast clutter_threads_add_timeout_full() would not fire until a + * full interval after the function completes so the delay between + * calls would be @interval * 1.5. This function does not however try + * to invoke the function multiple times to catch up missing frames if + * @func takes more than @interval ms to execute. + * + * See also clutter_threads_add_idle_full(). + * + * Return value: the ID (greater than 0) of the event source. + * + * Since: 0.8 + * + * Deprecated: 1.6: There is no direct replacement for this API + */ +guint +clutter_threads_add_frame_source_full (gint priority, + guint fps, + GSourceFunc func, + gpointer data, + GDestroyNotify notify) +{ + ClutterThreadsDispatch *dispatch; + + g_return_val_if_fail (func != NULL, 0); + + dispatch = g_slice_new (ClutterThreadsDispatch); + dispatch->func = func; + dispatch->data = data; + dispatch->notify = notify; + + return clutter_frame_source_add_full (priority, + fps, + _clutter_threads_dispatch, dispatch, + _clutter_threads_dispatch_free); +} + +/** + * clutter_threads_add_frame_source: (skip) + * @fps: the number of times per second to call the function + * @func: function to call + * @data: data to pass to the function + * + * Simple wrapper around clutter_threads_add_frame_source_full(). + * + * Return value: the ID (greater than 0) of the event source. + * + * Since: 0.8 + * + * Deprecated: 1.6: There is no direct replacement for this API + */ +guint +clutter_threads_add_frame_source (guint fps, + GSourceFunc func, + gpointer data) +{ + g_return_val_if_fail (func != NULL, 0); + + return clutter_threads_add_frame_source_full (G_PRIORITY_DEFAULT, + fps, + func, data, + NULL); +} diff --git a/clutter/clutter/deprecated/clutter-frame-source.h b/clutter/clutter/deprecated/clutter-frame-source.h new file mode 100644 index 0000000..f451341 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-frame-source.h @@ -0,0 +1,49 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2008 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_FRAME_SOURCE_H__ +#define __CLUTTER_FRAME_SOURCE_H__ + +#include + +G_BEGIN_DECLS + +CLUTTER_DEPRECATED_IN_1_6 +guint clutter_frame_source_add (guint fps, + GSourceFunc func, + gpointer data); + +CLUTTER_DEPRECATED_IN_1_6 +guint clutter_frame_source_add_full (gint priority, + guint fps, + GSourceFunc func, + gpointer data, + GDestroyNotify notify); + +G_END_DECLS + +#endif /* __CLUTTER_FRAME_SOURCE_H__ */ diff --git a/clutter/clutter/deprecated/clutter-group.c b/clutter/clutter/deprecated/clutter-group.c new file mode 100644 index 0000000..050cdfa --- /dev/null +++ b/clutter/clutter/deprecated/clutter-group.c @@ -0,0 +1,564 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +/** + * SECTION:clutter-group + * @short_description: A fixed layout container + * + * A #ClutterGroup is an Actor which contains multiple child actors positioned + * relative to the #ClutterGroup position. Other operations such as scaling, + * rotating and clipping of the group will apply to the child actors. + * + * A #ClutterGroup's size is defined by the size and position of its children; + * it will be the smallest non-negative size that covers the right and bottom + * edges of all of its children. + * + * Setting the size on a Group using #ClutterActor methods like + * clutter_actor_set_size() will override the natural size of the Group, + * however this will not affect the size of the children and they may still + * be painted outside of the allocation of the group. One way to constrain + * the visible area of a #ClutterGroup to a specified allocation is to + * explicitly set the size of the #ClutterGroup and then use the + * #ClutterActor:clip-to-allocation property. + * + * #ClutterGroup as a concrete class has been superceded by #ClutterActor + * since Clutter 1.10. The type itself is not deprecated as it is used by + * #ClutterStage. You should instantiate #ClutterActor and use its API to + * manage child actors. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include "clutter-group.h" + +#include "clutter-actor.h" +#include "clutter-actor-private.h" +#include "clutter-container.h" +#include "clutter-fixed-layout.h" +#include "clutter-main.h" +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-marshal.h" +#include "clutter-private.h" + +#include "cogl/cogl.h" + +struct _ClutterGroupPrivate +{ + GList *children; + + ClutterLayoutManager *layout; +}; + +static void clutter_container_iface_init (ClutterContainerIface *iface); + +G_DEFINE_TYPE_WITH_CODE (ClutterGroup, clutter_group, CLUTTER_TYPE_ACTOR, + G_ADD_PRIVATE (ClutterGroup) + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER, + clutter_container_iface_init)); + +static gint +sort_by_depth (gconstpointer a, + gconstpointer b) +{ + gfloat depth_a = clutter_actor_get_depth (CLUTTER_ACTOR(a)); + gfloat depth_b = clutter_actor_get_depth (CLUTTER_ACTOR(b)); + + if (depth_a < depth_b) + return -1; + + if (depth_a > depth_b) + return 1; + + return 0; +} + +static void +clutter_group_real_add (ClutterContainer *container, + ClutterActor *actor) +{ + ClutterGroupPrivate *priv = CLUTTER_GROUP (container)->priv; + + g_object_ref (actor); + + priv->children = g_list_append (priv->children, actor); + clutter_actor_set_parent (actor, CLUTTER_ACTOR (container)); + + clutter_actor_queue_relayout (CLUTTER_ACTOR (container)); + + g_signal_emit_by_name (container, "actor-added", actor); + + clutter_container_sort_depth_order (container); + + g_object_unref (actor); +} + +static void +clutter_group_real_actor_added (ClutterContainer *container, + ClutterActor *actor) +{ + ClutterGroupPrivate *priv = CLUTTER_GROUP (container)->priv; + + /* XXX - children added using clutter_actor_add_child() will + * cause actor-added to be emitted without going through the + * add() virtual function. + * + * if we get an actor-added for a child that is not in our + * list of children already, then we go in compatibility + * mode. + */ + if (g_list_find (priv->children, actor) != NULL) + return; + + priv->children = g_list_append (priv->children, actor); + clutter_container_sort_depth_order (container); +} + +static void +clutter_group_real_remove (ClutterContainer *container, + ClutterActor *actor) +{ + ClutterGroupPrivate *priv = CLUTTER_GROUP (container)->priv; + + g_object_ref (actor); + + priv->children = g_list_remove (priv->children, actor); + clutter_actor_unparent (actor); + + clutter_actor_queue_relayout (CLUTTER_ACTOR (container)); + + g_signal_emit_by_name (container, "actor-removed", actor); + + clutter_actor_queue_redraw (CLUTTER_ACTOR (container)); + + g_object_unref (actor); +} + +static void +clutter_group_real_actor_removed (ClutterContainer *container, + ClutterActor *actor) +{ + ClutterGroupPrivate *priv = CLUTTER_GROUP (container)->priv; + + /* XXX - same compatibility mode of the ::actor-added implementation */ + if (g_list_find (priv->children, actor) == NULL) + return; + + priv->children = g_list_remove (priv->children, actor); +} + +static void +clutter_group_real_foreach (ClutterContainer *container, + ClutterCallback callback, + gpointer user_data) +{ + ClutterGroupPrivate *priv = CLUTTER_GROUP (container)->priv; + + /* Using g_list_foreach instead of iterating the list manually + because it has better protection against the current node being + removed. This will happen for example if someone calls + clutter_container_foreach(container, clutter_actor_destroy) */ + g_list_foreach (priv->children, (GFunc) callback, user_data); +} + +static void +clutter_group_real_raise (ClutterContainer *container, + ClutterActor *actor, + ClutterActor *sibling) +{ + ClutterGroupPrivate *priv = CLUTTER_GROUP (container)->priv; + + priv->children = g_list_remove (priv->children, actor); + + /* Raise at the top */ + if (!sibling) + { + GList *last_item; + + last_item = g_list_last (priv->children); + + if (last_item) + sibling = last_item->data; + + priv->children = g_list_append (priv->children, actor); + } + else + { + gint index_ = g_list_index (priv->children, sibling) + 1; + + priv->children = g_list_insert (priv->children, actor, index_); + } + + /* set Z ordering a value below, this will then call sort + * as values are equal ordering shouldn't change but Z + * values will be correct. + * + * FIXME: get rid of this crap; this is so utterly broken and wrong on + * so many levels it's not even funny. sadly, we get to keep this until + * we can break API and remove Group for good. + */ + if (sibling && + clutter_actor_get_depth (sibling) != clutter_actor_get_depth (actor)) + { + clutter_actor_set_depth (actor, clutter_actor_get_depth (sibling)); + } + + clutter_actor_queue_redraw (CLUTTER_ACTOR (container)); +} + +static void +clutter_group_real_lower (ClutterContainer *container, + ClutterActor *actor, + ClutterActor *sibling) +{ + ClutterGroup *self = CLUTTER_GROUP (container); + ClutterGroupPrivate *priv = self->priv; + + priv->children = g_list_remove (priv->children, actor); + + /* Push to bottom */ + if (!sibling) + { + GList *last_item; + + last_item = g_list_first (priv->children); + + if (last_item) + sibling = last_item->data; + + priv->children = g_list_prepend (priv->children, actor); + } + else + { + gint index_ = g_list_index (priv->children, sibling); + + priv->children = g_list_insert (priv->children, actor, index_); + } + + /* See comment in group_raise for this */ + if (sibling && + clutter_actor_get_depth (sibling) != clutter_actor_get_depth (actor)) + { + clutter_actor_set_depth (actor, clutter_actor_get_depth (sibling)); + } + + clutter_actor_queue_redraw (CLUTTER_ACTOR (container)); +} + +static void +clutter_group_real_sort_depth_order (ClutterContainer *container) +{ + ClutterGroupPrivate *priv = CLUTTER_GROUP (container)->priv; + + priv->children = g_list_sort (priv->children, sort_by_depth); + + clutter_actor_queue_redraw (CLUTTER_ACTOR (container)); +} + +static void +clutter_container_iface_init (ClutterContainerIface *iface) +{ + iface->add = clutter_group_real_add; + iface->actor_added = clutter_group_real_actor_added; + iface->remove = clutter_group_real_remove; + iface->actor_removed = clutter_group_real_actor_removed; + iface->foreach = clutter_group_real_foreach; + iface->raise = clutter_group_real_raise; + iface->lower = clutter_group_real_lower; + iface->sort_depth_order = clutter_group_real_sort_depth_order; +} + +static void +clutter_group_real_paint (ClutterActor *actor) +{ + ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv; + + CLUTTER_NOTE (PAINT, "ClutterGroup paint enter '%s'", + _clutter_actor_get_debug_name (actor)); + + g_list_foreach (priv->children, (GFunc) clutter_actor_paint, NULL); + + CLUTTER_NOTE (PAINT, "ClutterGroup paint leave '%s'", + _clutter_actor_get_debug_name (actor)); +} + +static void +clutter_group_real_pick (ClutterActor *actor, + const ClutterColor *pick) +{ + ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv; + + /* Chain up so we get a bounding box pained (if we are reactive) */ + CLUTTER_ACTOR_CLASS (clutter_group_parent_class)->pick (actor, pick); + + g_list_foreach (priv->children, (GFunc) clutter_actor_paint, NULL); +} + +static void +clutter_group_real_get_preferred_width (ClutterActor *actor, + gfloat for_height, + gfloat *min_width, + gfloat *natural_width) +{ + ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv; + + clutter_layout_manager_get_preferred_width (priv->layout, + CLUTTER_CONTAINER (actor), + for_height, + min_width, natural_width); +} + +static void +clutter_group_real_get_preferred_height (ClutterActor *actor, + gfloat for_width, + gfloat *min_height, + gfloat *natural_height) +{ + ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv; + + clutter_layout_manager_get_preferred_height (priv->layout, + CLUTTER_CONTAINER (actor), + for_width, + min_height, natural_height); +} + +static void +clutter_group_real_allocate (ClutterActor *actor, + const ClutterActorBox *allocation, + ClutterAllocationFlags flags) +{ + ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv; + ClutterActorClass *klass; + + klass = CLUTTER_ACTOR_CLASS (clutter_group_parent_class); + klass->allocate (actor, allocation, flags); + + if (priv->children == NULL) + return; + + clutter_layout_manager_allocate (priv->layout, + CLUTTER_CONTAINER (actor), + allocation, flags); +} + +static void +clutter_group_dispose (GObject *object) +{ + ClutterGroup *self = CLUTTER_GROUP (object); + ClutterGroupPrivate *priv = self->priv; + + /* Note: we are careful to consider that destroying children could + * have the side-effect of destroying other children so + * priv->children may be modified during clutter_actor_destroy. */ + while (priv->children != NULL) + { + ClutterActor *child = priv->children->data; + priv->children = g_list_delete_link (priv->children, priv->children); + clutter_actor_destroy (child); + } + + if (priv->layout) + { + clutter_layout_manager_set_container (priv->layout, NULL); + g_object_unref (priv->layout); + priv->layout = NULL; + } + + G_OBJECT_CLASS (clutter_group_parent_class)->dispose (object); +} + +static void +clutter_group_real_show_all (ClutterActor *actor) +{ + clutter_container_foreach (CLUTTER_CONTAINER (actor), + CLUTTER_CALLBACK (clutter_actor_show), + NULL); + clutter_actor_show (actor); +} + +static void +clutter_group_real_hide_all (ClutterActor *actor) +{ + clutter_actor_hide (actor); + clutter_container_foreach (CLUTTER_CONTAINER (actor), + CLUTTER_CALLBACK (clutter_actor_hide), + NULL); +} + +static gboolean +clutter_group_real_get_paint_volume (ClutterActor *actor, + ClutterPaintVolume *volume) +{ + ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv; + GList *l; + + if (priv->children == NULL) + return TRUE; + + for (l = priv->children; l != NULL; l = l->next) + { + ClutterActor *child = l->data; + const ClutterPaintVolume *child_volume; + + /* This gets the paint volume of the child transformed into the + * group's coordinate space... */ + child_volume = clutter_actor_get_transformed_paint_volume (child, actor); + if (!child_volume) + return FALSE; + + clutter_paint_volume_union (volume, child_volume); + } + + return TRUE; +} + +static void +clutter_group_class_init (ClutterGroupClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + + actor_class->get_preferred_width = clutter_group_real_get_preferred_width; + actor_class->get_preferred_height = clutter_group_real_get_preferred_height; + actor_class->allocate = clutter_group_real_allocate; + actor_class->paint = clutter_group_real_paint; + actor_class->pick = clutter_group_real_pick; + actor_class->show_all = clutter_group_real_show_all; + actor_class->hide_all = clutter_group_real_hide_all; + actor_class->get_paint_volume = clutter_group_real_get_paint_volume; + + gobject_class->dispose = clutter_group_dispose; +} + +static void +clutter_group_init (ClutterGroup *self) +{ + ClutterActor *actor = CLUTTER_ACTOR (self); + + self->priv = clutter_group_get_instance_private (self); + + /* turn on some optimization + * + * XXX - these so-called "optimizations" are insane and should have never + * been used. they introduce some weird behaviour that breaks invariants + * and have to be explicitly worked around. + * + * this flag was set by the ClutterFixedLayout, but since that layout + * manager is now the default for ClutterActor, we set the flag explicitly + * here, to avoid breaking perfectly working actors overriding the + * allocate() virtual function. + * + * also, we keep this flag here so that it can die once we get rid of + * ClutterGroup. + */ + clutter_actor_set_flags (actor, CLUTTER_ACTOR_NO_LAYOUT); + + self->priv->layout = clutter_fixed_layout_new (); + g_object_ref_sink (self->priv->layout); + + clutter_actor_set_layout_manager (actor, self->priv->layout); +} + +/** + * clutter_group_new: + * + * Create a new #ClutterGroup. + * + * Return value: the newly created #ClutterGroup actor + * + * Deprecated: 1.10: Use clutter_actor_new() instead. + */ +ClutterActor * +clutter_group_new (void) +{ + return g_object_new (CLUTTER_TYPE_GROUP, NULL); +} + +/** + * clutter_group_remove_all: + * @self: A #ClutterGroup + * + * Removes all children actors from the #ClutterGroup. + * + * Deprecated: 1.10: Use clutter_actor_remove_all_children() instead. + */ +void +clutter_group_remove_all (ClutterGroup *self) +{ + g_return_if_fail (CLUTTER_IS_GROUP (self)); + + clutter_actor_remove_all_children (CLUTTER_ACTOR (self)); +} + +/** + * clutter_group_get_n_children: + * @self: A #ClutterGroup + * + * Gets the number of actors held in the group. + * + * Return value: The number of child actors held in the group. + * + * Since: 0.2 + * + * Deprecated: 1.10: Use clutter_actor_get_n_children() instead. + */ +gint +clutter_group_get_n_children (ClutterGroup *self) +{ + g_return_val_if_fail (CLUTTER_IS_GROUP (self), 0); + + return clutter_actor_get_n_children (CLUTTER_ACTOR (self)); +} + +/** + * clutter_group_get_nth_child: + * @self: A #ClutterGroup + * @index_: the position of the requested actor. + * + * Gets a groups child held at @index_ in stack. + * + * Return value: (transfer none): A Clutter actor, or %NULL if + * @index_ is invalid. + * + * Since: 0.2 + * + * Deprecated: 1.10: Use clutter_actor_get_child_at_index() instead. + */ +ClutterActor * +clutter_group_get_nth_child (ClutterGroup *self, + gint index_) +{ + ClutterActor *actor; + + g_return_val_if_fail (CLUTTER_IS_GROUP (self), NULL); + + actor = CLUTTER_ACTOR (self); + g_return_val_if_fail (index_ <= clutter_actor_get_n_children (actor), NULL); + + return clutter_actor_get_child_at_index (actor, index_); +} diff --git a/clutter/clutter/deprecated/clutter-group.h b/clutter/clutter/deprecated/clutter-group.h new file mode 100644 index 0000000..5bc378f --- /dev/null +++ b/clutter/clutter/deprecated/clutter-group.h @@ -0,0 +1,62 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2011 Intel Corp + * + * 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 . + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_GROUP_DEPRECATED_H__ +#define __CLUTTER_GROUP_DEPRECATED_H__ + +#include +#include + +G_BEGIN_DECLS + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_new) +ClutterActor * clutter_group_new (void); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_get_child_at_index) +ClutterActor * clutter_group_get_nth_child (ClutterGroup *self, + gint index_); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_get_n_children) +gint clutter_group_get_n_children (ClutterGroup *self); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_remove_all_children) +void clutter_group_remove_all (ClutterGroup *self); + +#ifndef CLUTTER_DISABLE_DEPRECATED + +/* for Mr. Mallum only */ +#define clutter_group_add(group,actor) G_STMT_START { \ + ClutterActor *_actor = (ClutterActor *) (actor); \ + if (CLUTTER_IS_GROUP ((group)) && CLUTTER_IS_ACTOR ((_actor))) \ + { \ + ClutterContainer *_container = (ClutterContainer *) (group); \ + clutter_container_add_actor (_container, _actor); \ + } } G_STMT_END + +#endif /* CLUTTER_DISABLE_DEPRECATED */ + +G_END_DECLS + +#endif /* __CLUTTER_GROUP_DEPRECATED_H__ */ diff --git a/clutter/clutter/deprecated/clutter-input-device-deprecated.c b/clutter/clutter/deprecated/clutter-input-device-deprecated.c new file mode 100644 index 0000000..3b9e697 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-input-device-deprecated.c @@ -0,0 +1,38 @@ +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS + +#include "clutter-device-manager-private.h" +#include "deprecated/clutter-input-device.h" + +/** + * clutter_input_device_get_device_coords: + * @device: a #ClutterInputDevice of type %CLUTTER_POINTER_DEVICE + * @x: (out): return location for the X coordinate + * @y: (out): return location for the Y coordinate + * + * Retrieves the latest coordinates of the pointer of @device + * + * Since: 1.2 + * + * Deprecated: 1.12: Use clutter_input_device_get_coords() instead. + */ +void +clutter_input_device_get_device_coords (ClutterInputDevice *device, + gint *x, + gint *y) +{ + ClutterPoint point; + + clutter_input_device_get_coords (device, NULL, &point); + + if (x) + *x = point.x; + + if (y) + *y = point.y; +} diff --git a/clutter/clutter/deprecated/clutter-input-device.h b/clutter/clutter/deprecated/clutter-input-device.h new file mode 100644 index 0000000..692459d --- /dev/null +++ b/clutter/clutter/deprecated/clutter-input-device.h @@ -0,0 +1,41 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright © 2009, 2010, 2011 Intel Corp. + * + * 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 . + * + * Author: Emmanuele Bassi + */ +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_INPUT_DEVICE_DEPRECATED_H__ +#define __CLUTTER_INPUT_DEVICE_DEPRECATED_H__ + +#include + +G_BEGIN_DECLS + +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_input_device_get_coords) +void clutter_input_device_get_device_coords (ClutterInputDevice *device, + gint *x, + gint *y); + +G_END_DECLS + +#endif /* __CLUTTER_INPUT_DEVICE_DEPRECATED_H__ */ diff --git a/clutter/clutter/deprecated/clutter-keysyms.h b/clutter/clutter/deprecated/clutter-keysyms.h new file mode 100644 index 0000000..3374b0b --- /dev/null +++ b/clutter/clutter/deprecated/clutter-keysyms.h @@ -0,0 +1,2311 @@ +/* Clutter + * + * Copyright (C) 2006, 2007, 2008 OpenedHand Ltd + * Copyright (C) 2009, 2010 Intel Corp + * + * 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 . + */ + +/* + * Compatibility version of clutter-keysyms.h. + * + * Since Clutter 1.4, the key symbol defines have been changed to have + * a KEY_ prefix. This is a compatibility header that is included when + * deprecated symbols are enabled. Consider porting to the new names + * instead. + */ + +#ifndef __CLUTTER_KEYSYMS_DEPRECATED_H__ +#define __CLUTTER_KEYSYMS_DEPRECATED_H__ + +#ifndef CLUTTER_DISABLE_DEPRECATED + +#define CLUTTER_VoidSymbol 0xffffff CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_VoidSymbol instead.") +#define CLUTTER_BackSpace 0xff08 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_BackSpace instead.") +#define CLUTTER_Tab 0xff09 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Tab instead.") +#define CLUTTER_Linefeed 0xff0a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Linefeed instead.") +#define CLUTTER_Clear 0xff0b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Clear instead.") +#define CLUTTER_Return 0xff0d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Return instead.") +#define CLUTTER_Pause 0xff13 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pause instead.") +#define CLUTTER_Scroll_Lock 0xff14 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Scroll_Lock instead.") +#define CLUTTER_Sys_Req 0xff15 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sys_Req instead.") +#define CLUTTER_Escape 0xff1b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Escape instead.") +#define CLUTTER_Delete 0xffff CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Delete instead.") +#define CLUTTER_Multi_key 0xff20 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Multi_key instead.") +#define CLUTTER_Codeinput 0xff37 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Codeinput instead.") +#define CLUTTER_SingleCandidate 0xff3c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_SingleCandidate instead.") +#define CLUTTER_MultipleCandidate 0xff3d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_MultipleCandidate instead.") +#define CLUTTER_PreviousCandidate 0xff3e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_PreviousCandidate instead.") +#define CLUTTER_Kanji 0xff21 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Kanji instead.") +#define CLUTTER_Muhenkan 0xff22 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Muhenkan instead.") +#define CLUTTER_Henkan_Mode 0xff23 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Henkan_Mode instead.") +#define CLUTTER_Henkan 0xff23 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Henkan instead.") +#define CLUTTER_Romaji 0xff24 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Romaji instead.") +#define CLUTTER_Hiragana 0xff25 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hiragana instead.") +#define CLUTTER_Katakana 0xff26 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Katakana instead.") +#define CLUTTER_Hiragana_Katakana 0xff27 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hiragana_Katakana instead.") +#define CLUTTER_Zenkaku 0xff28 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Zenkaku instead.") +#define CLUTTER_Hankaku 0xff29 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hankaku instead.") +#define CLUTTER_Zenkaku_Hankaku 0xff2a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Zenkaku_Hankaku instead.") +#define CLUTTER_Touroku 0xff2b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Touroku instead.") +#define CLUTTER_Massyo 0xff2c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Massyo instead.") +#define CLUTTER_Kana_Lock 0xff2d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Kana_Lock instead.") +#define CLUTTER_Kana_Shift 0xff2e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Kana_Shift instead.") +#define CLUTTER_Eisu_Shift 0xff2f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Eisu_Shift instead.") +#define CLUTTER_Eisu_toggle 0xff30 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Eisu_toggle instead.") +#define CLUTTER_Kanji_Bangou 0xff37 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Kanji_Bangou instead.") +#define CLUTTER_Zen_Koho 0xff3d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Zen_Koho instead.") +#define CLUTTER_Mae_Koho 0xff3e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Mae_Koho instead.") +#define CLUTTER_Home 0xff50 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Home instead.") +#define CLUTTER_Left 0xff51 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Left instead.") +#define CLUTTER_Up 0xff52 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Up instead.") +#define CLUTTER_Right 0xff53 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Right instead.") +#define CLUTTER_Down 0xff54 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Down instead.") +#define CLUTTER_Prior 0xff55 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Prior instead.") +#define CLUTTER_Page_Up 0xff55 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Page_Up instead.") +#define CLUTTER_Next 0xff56 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Next instead.") +#define CLUTTER_Page_Down 0xff56 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Page_Down instead.") +#define CLUTTER_End 0xff57 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_End instead.") +#define CLUTTER_Begin 0xff58 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Begin instead.") +#define CLUTTER_Select 0xff60 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Select instead.") +#define CLUTTER_Print 0xff61 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Print instead.") +#define CLUTTER_Execute 0xff62 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Execute instead.") +#define CLUTTER_Insert 0xff63 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Insert instead.") +#define CLUTTER_Undo 0xff65 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Undo instead.") +#define CLUTTER_Redo 0xff66 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Redo instead.") +#define CLUTTER_Menu 0xff67 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Menu instead.") +#define CLUTTER_Find 0xff68 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Find instead.") +#define CLUTTER_Cancel 0xff69 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cancel instead.") +#define CLUTTER_Help 0xff6a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Help instead.") +#define CLUTTER_Break 0xff6b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Break instead.") +#define CLUTTER_Mode_switch 0xff7e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Mode_switch instead.") +#define CLUTTER_script_switch 0xff7e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_script_switch instead.") +#define CLUTTER_Num_Lock 0xff7f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Num_Lock instead.") +#define CLUTTER_KP_Space 0xff80 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_Space instead.") +#define CLUTTER_KP_Tab 0xff89 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_Tab instead.") +#define CLUTTER_KP_Enter 0xff8d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_Enter instead.") +#define CLUTTER_KP_F1 0xff91 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_F1 instead.") +#define CLUTTER_KP_F2 0xff92 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_F2 instead.") +#define CLUTTER_KP_F3 0xff93 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_F3 instead.") +#define CLUTTER_KP_F4 0xff94 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_F4 instead.") +#define CLUTTER_KP_Home 0xff95 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_Home instead.") +#define CLUTTER_KP_Left 0xff96 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_Left instead.") +#define CLUTTER_KP_Up 0xff97 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_Up instead.") +#define CLUTTER_KP_Right 0xff98 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_Right instead.") +#define CLUTTER_KP_Down 0xff99 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_Down instead.") +#define CLUTTER_KP_Prior 0xff9a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_Prior instead.") +#define CLUTTER_KP_Page_Up 0xff9a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_Page_Up instead.") +#define CLUTTER_KP_Next 0xff9b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_Next instead.") +#define CLUTTER_KP_Page_Down 0xff9b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_Page_Down instead.") +#define CLUTTER_KP_End 0xff9c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_End instead.") +#define CLUTTER_KP_Begin 0xff9d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_Begin instead.") +#define CLUTTER_KP_Insert 0xff9e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_Insert instead.") +#define CLUTTER_KP_Delete 0xff9f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_Delete instead.") +#define CLUTTER_KP_Equal 0xffbd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_Equal instead.") +#define CLUTTER_KP_Multiply 0xffaa CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_Multiply instead.") +#define CLUTTER_KP_Add 0xffab CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_Add instead.") +#define CLUTTER_KP_Separator 0xffac CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_Separator instead.") +#define CLUTTER_KP_Subtract 0xffad CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_Subtract instead.") +#define CLUTTER_KP_Decimal 0xffae CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_Decimal instead.") +#define CLUTTER_KP_Divide 0xffaf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_Divide instead.") +#define CLUTTER_KP_0 0xffb0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_0 instead.") +#define CLUTTER_KP_1 0xffb1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_1 instead.") +#define CLUTTER_KP_2 0xffb2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_2 instead.") +#define CLUTTER_KP_3 0xffb3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_3 instead.") +#define CLUTTER_KP_4 0xffb4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_4 instead.") +#define CLUTTER_KP_5 0xffb5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_5 instead.") +#define CLUTTER_KP_6 0xffb6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_6 instead.") +#define CLUTTER_KP_7 0xffb7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_7 instead.") +#define CLUTTER_KP_8 0xffb8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_8 instead.") +#define CLUTTER_KP_9 0xffb9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_KP_9 instead.") +#define CLUTTER_F1 0xffbe CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F1 instead.") +#define CLUTTER_F2 0xffbf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F2 instead.") +#define CLUTTER_F3 0xffc0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F3 instead.") +#define CLUTTER_F4 0xffc1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F4 instead.") +#define CLUTTER_F5 0xffc2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F5 instead.") +#define CLUTTER_F6 0xffc3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F6 instead.") +#define CLUTTER_F7 0xffc4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F7 instead.") +#define CLUTTER_F8 0xffc5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F8 instead.") +#define CLUTTER_F9 0xffc6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F9 instead.") +#define CLUTTER_F10 0xffc7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F10 instead.") +#define CLUTTER_F11 0xffc8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F11 instead.") +#define CLUTTER_L1 0xffc8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_L1 instead.") +#define CLUTTER_F12 0xffc9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F12 instead.") +#define CLUTTER_L2 0xffc9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_L2 instead.") +#define CLUTTER_F13 0xffca CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F13 instead.") +#define CLUTTER_L3 0xffca CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_L3 instead.") +#define CLUTTER_F14 0xffcb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F14 instead.") +#define CLUTTER_L4 0xffcb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_L4 instead.") +#define CLUTTER_F15 0xffcc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F15 instead.") +#define CLUTTER_L5 0xffcc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_L5 instead.") +#define CLUTTER_F16 0xffcd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F16 instead.") +#define CLUTTER_L6 0xffcd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_L6 instead.") +#define CLUTTER_F17 0xffce CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F17 instead.") +#define CLUTTER_L7 0xffce CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_L7 instead.") +#define CLUTTER_F18 0xffcf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F18 instead.") +#define CLUTTER_L8 0xffcf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_L8 instead.") +#define CLUTTER_F19 0xffd0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F19 instead.") +#define CLUTTER_L9 0xffd0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_L9 instead.") +#define CLUTTER_F20 0xffd1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F20 instead.") +#define CLUTTER_L10 0xffd1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_L10 instead.") +#define CLUTTER_F21 0xffd2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F21 instead.") +#define CLUTTER_R1 0xffd2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_R1 instead.") +#define CLUTTER_F22 0xffd3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F22 instead.") +#define CLUTTER_R2 0xffd3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_R2 instead.") +#define CLUTTER_F23 0xffd4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F23 instead.") +#define CLUTTER_R3 0xffd4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_R3 instead.") +#define CLUTTER_F24 0xffd5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F24 instead.") +#define CLUTTER_R4 0xffd5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_R4 instead.") +#define CLUTTER_F25 0xffd6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F25 instead.") +#define CLUTTER_R5 0xffd6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_R5 instead.") +#define CLUTTER_F26 0xffd7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F26 instead.") +#define CLUTTER_R6 0xffd7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_R6 instead.") +#define CLUTTER_F27 0xffd8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F27 instead.") +#define CLUTTER_R7 0xffd8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_R7 instead.") +#define CLUTTER_F28 0xffd9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F28 instead.") +#define CLUTTER_R8 0xffd9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_R8 instead.") +#define CLUTTER_F29 0xffda CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F29 instead.") +#define CLUTTER_R9 0xffda CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_R9 instead.") +#define CLUTTER_F30 0xffdb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F30 instead.") +#define CLUTTER_R10 0xffdb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_R10 instead.") +#define CLUTTER_F31 0xffdc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F31 instead.") +#define CLUTTER_R11 0xffdc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_R11 instead.") +#define CLUTTER_F32 0xffdd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F32 instead.") +#define CLUTTER_R12 0xffdd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_R12 instead.") +#define CLUTTER_F33 0xffde CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F33 instead.") +#define CLUTTER_R13 0xffde CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_R13 instead.") +#define CLUTTER_F34 0xffdf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F34 instead.") +#define CLUTTER_R14 0xffdf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_R14 instead.") +#define CLUTTER_F35 0xffe0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F35 instead.") +#define CLUTTER_R15 0xffe0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_R15 instead.") +#define CLUTTER_Shift_L 0xffe1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Shift_L instead.") +#define CLUTTER_Shift_R 0xffe2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Shift_R instead.") +#define CLUTTER_Control_L 0xffe3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Control_L instead.") +#define CLUTTER_Control_R 0xffe4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Control_R instead.") +#define CLUTTER_Caps_Lock 0xffe5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Caps_Lock instead.") +#define CLUTTER_Shift_Lock 0xffe6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Shift_Lock instead.") +#define CLUTTER_Meta_L 0xffe7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Meta_L instead.") +#define CLUTTER_Meta_R 0xffe8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Meta_R instead.") +#define CLUTTER_Alt_L 0xffe9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Alt_L instead.") +#define CLUTTER_Alt_R 0xffea CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Alt_R instead.") +#define CLUTTER_Super_L 0xffeb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Super_L instead.") +#define CLUTTER_Super_R 0xffec CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Super_R instead.") +#define CLUTTER_Hyper_L 0xffed CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hyper_L instead.") +#define CLUTTER_Hyper_R 0xffee CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hyper_R instead.") +#define CLUTTER_ISO_Lock 0xfe01 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Lock instead.") +#define CLUTTER_ISO_Level2_Latch 0xfe02 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Level2_Latch instead.") +#define CLUTTER_ISO_Level3_Shift 0xfe03 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Level3_Shift instead.") +#define CLUTTER_ISO_Level3_Latch 0xfe04 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Level3_Latch instead.") +#define CLUTTER_ISO_Level3_Lock 0xfe05 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Level3_Lock instead.") +#define CLUTTER_ISO_Level5_Shift 0xfe11 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Level5_Shift instead.") +#define CLUTTER_ISO_Level5_Latch 0xfe12 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Level5_Latch instead.") +#define CLUTTER_ISO_Level5_Lock 0xfe13 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Level5_Lock instead.") +#define CLUTTER_ISO_Group_Shift 0xff7e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Group_Shift instead.") +#define CLUTTER_ISO_Group_Latch 0xfe06 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Group_Latch instead.") +#define CLUTTER_ISO_Group_Lock 0xfe07 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Group_Lock instead.") +#define CLUTTER_ISO_Next_Group 0xfe08 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Next_Group instead.") +#define CLUTTER_ISO_Next_Group_Lock 0xfe09 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Next_Group_Lock instead.") +#define CLUTTER_ISO_Prev_Group 0xfe0a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Prev_Group instead.") +#define CLUTTER_ISO_Prev_Group_Lock 0xfe0b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Prev_Group_Lock instead.") +#define CLUTTER_ISO_First_Group 0xfe0c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_First_Group instead.") +#define CLUTTER_ISO_First_Group_Lock 0xfe0d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_First_Group_Lock instead.") +#define CLUTTER_ISO_Last_Group 0xfe0e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Last_Group instead.") +#define CLUTTER_ISO_Last_Group_Lock 0xfe0f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Last_Group_Lock instead.") +#define CLUTTER_ISO_Left_Tab 0xfe20 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Left_Tab instead.") +#define CLUTTER_ISO_Move_Line_Up 0xfe21 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Move_Line_Up instead.") +#define CLUTTER_ISO_Move_Line_Down 0xfe22 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Move_Line_Down instead.") +#define CLUTTER_ISO_Partial_Line_Up 0xfe23 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Partial_Line_Up instead.") +#define CLUTTER_ISO_Partial_Line_Down 0xfe24 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Partial_Line_Down instead.") +#define CLUTTER_ISO_Partial_Space_Left 0xfe25 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Partial_Space_Left instead.") +#define CLUTTER_ISO_Partial_Space_Right 0xfe26 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Partial_Space_Right instead.") +#define CLUTTER_ISO_Set_Margin_Left 0xfe27 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Set_Margin_Left instead.") +#define CLUTTER_ISO_Set_Margin_Right 0xfe28 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Set_Margin_Right instead.") +#define CLUTTER_ISO_Release_Margin_Left 0xfe29 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Release_Margin_Left instead.") +#define CLUTTER_ISO_Release_Margin_Right 0xfe2a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Release_Margin_Right instead.") +#define CLUTTER_ISO_Release_Both_Margins 0xfe2b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Release_Both_Margins instead.") +#define CLUTTER_ISO_Fast_Cursor_Left 0xfe2c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Fast_Cursor_Left instead.") +#define CLUTTER_ISO_Fast_Cursor_Right 0xfe2d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Fast_Cursor_Right instead.") +#define CLUTTER_ISO_Fast_Cursor_Up 0xfe2e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Fast_Cursor_Up instead.") +#define CLUTTER_ISO_Fast_Cursor_Down 0xfe2f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Fast_Cursor_Down instead.") +#define CLUTTER_ISO_Continuous_Underline 0xfe30 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Continuous_Underline instead.") +#define CLUTTER_ISO_Discontinuous_Underline 0xfe31 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Discontinuous_Underline instead.") +#define CLUTTER_ISO_Emphasize 0xfe32 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Emphasize instead.") +#define CLUTTER_ISO_Center_Object 0xfe33 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Center_Object instead.") +#define CLUTTER_ISO_Enter 0xfe34 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ISO_Enter instead.") +#define CLUTTER_dead_grave 0xfe50 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_grave instead.") +#define CLUTTER_dead_acute 0xfe51 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_acute instead.") +#define CLUTTER_dead_circumflex 0xfe52 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_circumflex instead.") +#define CLUTTER_dead_tilde 0xfe53 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_tilde instead.") +#define CLUTTER_dead_perispomeni 0xfe53 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_perispomeni instead.") +#define CLUTTER_dead_macron 0xfe54 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_macron instead.") +#define CLUTTER_dead_breve 0xfe55 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_breve instead.") +#define CLUTTER_dead_abovedot 0xfe56 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_abovedot instead.") +#define CLUTTER_dead_diaeresis 0xfe57 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_diaeresis instead.") +#define CLUTTER_dead_abovering 0xfe58 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_abovering instead.") +#define CLUTTER_dead_doubleacute 0xfe59 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_doubleacute instead.") +#define CLUTTER_dead_caron 0xfe5a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_caron instead.") +#define CLUTTER_dead_cedilla 0xfe5b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_cedilla instead.") +#define CLUTTER_dead_ogonek 0xfe5c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_ogonek instead.") +#define CLUTTER_dead_iota 0xfe5d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_iota instead.") +#define CLUTTER_dead_voiced_sound 0xfe5e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_voiced_sound instead.") +#define CLUTTER_dead_semivoiced_sound 0xfe5f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_semivoiced_sound instead.") +#define CLUTTER_dead_belowdot 0xfe60 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_belowdot instead.") +#define CLUTTER_dead_hook 0xfe61 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_hook instead.") +#define CLUTTER_dead_horn 0xfe62 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_horn instead.") +#define CLUTTER_dead_stroke 0xfe63 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_stroke instead.") +#define CLUTTER_dead_abovecomma 0xfe64 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_abovecomma instead.") +#define CLUTTER_dead_psili 0xfe64 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_psili instead.") +#define CLUTTER_dead_abovereversedcomma 0xfe65 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_abovereversedcomma instead.") +#define CLUTTER_dead_dasia 0xfe65 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_dasia instead.") +#define CLUTTER_dead_doublegrave 0xfe66 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_doublegrave instead.") +#define CLUTTER_dead_belowring 0xfe67 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_belowring instead.") +#define CLUTTER_dead_belowmacron 0xfe68 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_belowmacron instead.") +#define CLUTTER_dead_belowcircumflex 0xfe69 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_belowcircumflex instead.") +#define CLUTTER_dead_belowtilde 0xfe6a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_belowtilde instead.") +#define CLUTTER_dead_belowbreve 0xfe6b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_belowbreve instead.") +#define CLUTTER_dead_belowdiaeresis 0xfe6c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_belowdiaeresis instead.") +#define CLUTTER_dead_invertedbreve 0xfe6d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_invertedbreve instead.") +#define CLUTTER_dead_belowcomma 0xfe6e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_belowcomma instead.") +#define CLUTTER_dead_currency 0xfe6f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_currency instead.") +#define CLUTTER_dead_lowline 0xfe90 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_lowline instead.") +#define CLUTTER_dead_aboveverticalline 0xfe91 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_aboveverticalline instead.") +#define CLUTTER_dead_belowverticalline 0xfe92 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_belowverticalline instead.") +#define CLUTTER_dead_longsolidusoverlay 0xfe93 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_longsolidusoverlay instead.") +#define CLUTTER_dead_a 0xfe80 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_a instead.") +#define CLUTTER_dead_A 0xfe81 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_A instead.") +#define CLUTTER_dead_e 0xfe82 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_e instead.") +#define CLUTTER_dead_E 0xfe83 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_E instead.") +#define CLUTTER_dead_i 0xfe84 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_i instead.") +#define CLUTTER_dead_I 0xfe85 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_I instead.") +#define CLUTTER_dead_o 0xfe86 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_o instead.") +#define CLUTTER_dead_O 0xfe87 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_O instead.") +#define CLUTTER_dead_u 0xfe88 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_u instead.") +#define CLUTTER_dead_U 0xfe89 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_U instead.") +#define CLUTTER_dead_small_schwa 0xfe8a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_small_schwa instead.") +#define CLUTTER_dead_capital_schwa 0xfe8b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_capital_schwa instead.") +#define CLUTTER_dead_greek 0xfe8c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dead_greek instead.") +#define CLUTTER_First_Virtual_Screen 0xfed0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_First_Virtual_Screen instead.") +#define CLUTTER_Prev_Virtual_Screen 0xfed1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Prev_Virtual_Screen instead.") +#define CLUTTER_Next_Virtual_Screen 0xfed2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Next_Virtual_Screen instead.") +#define CLUTTER_Last_Virtual_Screen 0xfed4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Last_Virtual_Screen instead.") +#define CLUTTER_Terminate_Server 0xfed5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Terminate_Server instead.") +#define CLUTTER_AccessX_Enable 0xfe70 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_AccessX_Enable instead.") +#define CLUTTER_AccessX_Feedback_Enable 0xfe71 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_AccessX_Feedback_Enable instead.") +#define CLUTTER_RepeatKeys_Enable 0xfe72 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_RepeatKeys_Enable instead.") +#define CLUTTER_SlowKeys_Enable 0xfe73 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_SlowKeys_Enable instead.") +#define CLUTTER_BounceKeys_Enable 0xfe74 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_BounceKeys_Enable instead.") +#define CLUTTER_StickyKeys_Enable 0xfe75 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_StickyKeys_Enable instead.") +#define CLUTTER_MouseKeys_Enable 0xfe76 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_MouseKeys_Enable instead.") +#define CLUTTER_MouseKeys_Accel_Enable 0xfe77 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_MouseKeys_Accel_Enable instead.") +#define CLUTTER_Overlay1_Enable 0xfe78 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Overlay1_Enable instead.") +#define CLUTTER_Overlay2_Enable 0xfe79 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Overlay2_Enable instead.") +#define CLUTTER_AudibleBell_Enable 0xfe7a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_AudibleBell_Enable instead.") +#define CLUTTER_Pointer_Left 0xfee0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_Left instead.") +#define CLUTTER_Pointer_Right 0xfee1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_Right instead.") +#define CLUTTER_Pointer_Up 0xfee2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_Up instead.") +#define CLUTTER_Pointer_Down 0xfee3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_Down instead.") +#define CLUTTER_Pointer_UpLeft 0xfee4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_UpLeft instead.") +#define CLUTTER_Pointer_UpRight 0xfee5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_UpRight instead.") +#define CLUTTER_Pointer_DownLeft 0xfee6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_DownLeft instead.") +#define CLUTTER_Pointer_DownRight 0xfee7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_DownRight instead.") +#define CLUTTER_Pointer_Button_Dflt 0xfee8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_Button_Dflt instead.") +#define CLUTTER_Pointer_Button1 0xfee9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_Button1 instead.") +#define CLUTTER_Pointer_Button2 0xfeea CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_Button2 instead.") +#define CLUTTER_Pointer_Button3 0xfeeb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_Button3 instead.") +#define CLUTTER_Pointer_Button4 0xfeec CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_Button4 instead.") +#define CLUTTER_Pointer_Button5 0xfeed CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_Button5 instead.") +#define CLUTTER_Pointer_DblClick_Dflt 0xfeee CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_DblClick_Dflt instead.") +#define CLUTTER_Pointer_DblClick1 0xfeef CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_DblClick1 instead.") +#define CLUTTER_Pointer_DblClick2 0xfef0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_DblClick2 instead.") +#define CLUTTER_Pointer_DblClick3 0xfef1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_DblClick3 instead.") +#define CLUTTER_Pointer_DblClick4 0xfef2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_DblClick4 instead.") +#define CLUTTER_Pointer_DblClick5 0xfef3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_DblClick5 instead.") +#define CLUTTER_Pointer_Drag_Dflt 0xfef4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_Drag_Dflt instead.") +#define CLUTTER_Pointer_Drag1 0xfef5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_Drag1 instead.") +#define CLUTTER_Pointer_Drag2 0xfef6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_Drag2 instead.") +#define CLUTTER_Pointer_Drag3 0xfef7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_Drag3 instead.") +#define CLUTTER_Pointer_Drag4 0xfef8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_Drag4 instead.") +#define CLUTTER_Pointer_Drag5 0xfefd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_Drag5 instead.") +#define CLUTTER_Pointer_EnableKeys 0xfef9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_EnableKeys instead.") +#define CLUTTER_Pointer_Accelerate 0xfefa CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_Accelerate instead.") +#define CLUTTER_Pointer_DfltBtnNext 0xfefb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_DfltBtnNext instead.") +#define CLUTTER_Pointer_DfltBtnPrev 0xfefc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pointer_DfltBtnPrev instead.") +#define CLUTTER_ch 0xfea0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ch instead.") +#define CLUTTER_Ch 0xfea1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ch instead.") +#define CLUTTER_CH 0xfea2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_CH instead.") +#define CLUTTER_c_h 0xfea3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_c_h instead.") +#define CLUTTER_C_h 0xfea4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_C_h instead.") +#define CLUTTER_C_H 0xfea5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_C_H instead.") +#define CLUTTER_3270_Duplicate 0xfd01 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_Duplicate instead.") +#define CLUTTER_3270_FieldMark 0xfd02 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_FieldMark instead.") +#define CLUTTER_3270_Right2 0xfd03 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_Right2 instead.") +#define CLUTTER_3270_Left2 0xfd04 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_Left2 instead.") +#define CLUTTER_3270_BackTab 0xfd05 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_BackTab instead.") +#define CLUTTER_3270_EraseEOF 0xfd06 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_EraseEOF instead.") +#define CLUTTER_3270_EraseInput 0xfd07 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_EraseInput instead.") +#define CLUTTER_3270_Reset 0xfd08 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_Reset instead.") +#define CLUTTER_3270_Quit 0xfd09 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_Quit instead.") +#define CLUTTER_3270_PA1 0xfd0a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_PA1 instead.") +#define CLUTTER_3270_PA2 0xfd0b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_PA2 instead.") +#define CLUTTER_3270_PA3 0xfd0c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_PA3 instead.") +#define CLUTTER_3270_Test 0xfd0d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_Test instead.") +#define CLUTTER_3270_Attn 0xfd0e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_Attn instead.") +#define CLUTTER_3270_CursorBlink 0xfd0f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_CursorBlink instead.") +#define CLUTTER_3270_AltCursor 0xfd10 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_AltCursor instead.") +#define CLUTTER_3270_KeyClick 0xfd11 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_KeyClick instead.") +#define CLUTTER_3270_Jump 0xfd12 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_Jump instead.") +#define CLUTTER_3270_Ident 0xfd13 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_Ident instead.") +#define CLUTTER_3270_Rule 0xfd14 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_Rule instead.") +#define CLUTTER_3270_Copy 0xfd15 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_Copy instead.") +#define CLUTTER_3270_Play 0xfd16 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_Play instead.") +#define CLUTTER_3270_Setup 0xfd17 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_Setup instead.") +#define CLUTTER_3270_Record 0xfd18 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_Record instead.") +#define CLUTTER_3270_ChangeScreen 0xfd19 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_ChangeScreen instead.") +#define CLUTTER_3270_DeleteWord 0xfd1a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_DeleteWord instead.") +#define CLUTTER_3270_ExSelect 0xfd1b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_ExSelect instead.") +#define CLUTTER_3270_CursorSelect 0xfd1c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_CursorSelect instead.") +#define CLUTTER_3270_PrintScreen 0xfd1d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_PrintScreen instead.") +#define CLUTTER_3270_Enter 0xfd1e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3270_Enter instead.") +#define CLUTTER_space 0x020 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_space instead.") +#define CLUTTER_exclam 0x021 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_exclam instead.") +#define CLUTTER_quotedbl 0x022 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_quotedbl instead.") +#define CLUTTER_numbersign 0x023 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_numbersign instead.") +#define CLUTTER_dollar 0x024 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dollar instead.") +#define CLUTTER_percent 0x025 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_percent instead.") +#define CLUTTER_ampersand 0x026 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ampersand instead.") +#define CLUTTER_apostrophe 0x027 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_apostrophe instead.") +#define CLUTTER_quoteright 0x027 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_quoteright instead.") +#define CLUTTER_parenleft 0x028 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_parenleft instead.") +#define CLUTTER_parenright 0x029 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_parenright instead.") +#define CLUTTER_asterisk 0x02a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_asterisk instead.") +#define CLUTTER_plus 0x02b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_plus instead.") +#define CLUTTER_comma 0x02c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_comma instead.") +#define CLUTTER_minus 0x02d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_minus instead.") +#define CLUTTER_period 0x02e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_period instead.") +#define CLUTTER_slash 0x02f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_slash instead.") +#define CLUTTER_0 0x030 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_0 instead.") +#define CLUTTER_1 0x031 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_1 instead.") +#define CLUTTER_2 0x032 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_2 instead.") +#define CLUTTER_3 0x033 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_3 instead.") +#define CLUTTER_4 0x034 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_4 instead.") +#define CLUTTER_5 0x035 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_5 instead.") +#define CLUTTER_6 0x036 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_6 instead.") +#define CLUTTER_7 0x037 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_7 instead.") +#define CLUTTER_8 0x038 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_8 instead.") +#define CLUTTER_9 0x039 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_9 instead.") +#define CLUTTER_colon 0x03a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_colon instead.") +#define CLUTTER_semicolon 0x03b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_semicolon instead.") +#define CLUTTER_less 0x03c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_less instead.") +#define CLUTTER_equal 0x03d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_equal instead.") +#define CLUTTER_greater 0x03e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_greater instead.") +#define CLUTTER_question 0x03f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_question instead.") +#define CLUTTER_at 0x040 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_at instead.") +#define CLUTTER_A 0x041 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_A instead.") +#define CLUTTER_B 0x042 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_B instead.") +#define CLUTTER_C 0x043 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_C instead.") +#define CLUTTER_D 0x044 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_D instead.") +#define CLUTTER_E 0x045 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_E instead.") +#define CLUTTER_F 0x046 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_F instead.") +#define CLUTTER_G 0x047 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_G instead.") +#define CLUTTER_H 0x048 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_H instead.") +#define CLUTTER_I 0x049 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_I instead.") +#define CLUTTER_J 0x04a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_J instead.") +#define CLUTTER_K 0x04b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_K instead.") +#define CLUTTER_L 0x04c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_L instead.") +#define CLUTTER_M 0x04d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_M instead.") +#define CLUTTER_N 0x04e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_N instead.") +#define CLUTTER_O 0x04f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_O instead.") +#define CLUTTER_P 0x050 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_P instead.") +#define CLUTTER_Q 0x051 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Q instead.") +#define CLUTTER_R 0x052 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_R instead.") +#define CLUTTER_S 0x053 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_S instead.") +#define CLUTTER_T 0x054 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_T instead.") +#define CLUTTER_U 0x055 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_U instead.") +#define CLUTTER_V 0x056 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_V instead.") +#define CLUTTER_W 0x057 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_W instead.") +#define CLUTTER_X 0x058 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_X instead.") +#define CLUTTER_Y 0x059 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Y instead.") +#define CLUTTER_Z 0x05a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Z instead.") +#define CLUTTER_bracketleft 0x05b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_bracketleft instead.") +#define CLUTTER_backslash 0x05c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_backslash instead.") +#define CLUTTER_bracketright 0x05d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_bracketright instead.") +#define CLUTTER_asciicircum 0x05e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_asciicircum instead.") +#define CLUTTER_underscore 0x05f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_underscore instead.") +#define CLUTTER_grave 0x060 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_grave instead.") +#define CLUTTER_quoteleft 0x060 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_quoteleft instead.") +#define CLUTTER_a 0x061 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_a instead.") +#define CLUTTER_b 0x062 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_b instead.") +#define CLUTTER_c 0x063 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_c instead.") +#define CLUTTER_d 0x064 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_d instead.") +#define CLUTTER_e 0x065 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_e instead.") +#define CLUTTER_f 0x066 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_f instead.") +#define CLUTTER_g 0x067 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_g instead.") +#define CLUTTER_h 0x068 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_h instead.") +#define CLUTTER_i 0x069 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_i instead.") +#define CLUTTER_j 0x06a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_j instead.") +#define CLUTTER_k 0x06b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_k instead.") +#define CLUTTER_l 0x06c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_l instead.") +#define CLUTTER_m 0x06d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_m instead.") +#define CLUTTER_n 0x06e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_n instead.") +#define CLUTTER_o 0x06f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_o instead.") +#define CLUTTER_p 0x070 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_p instead.") +#define CLUTTER_q 0x071 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_q instead.") +#define CLUTTER_r 0x072 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_r instead.") +#define CLUTTER_s 0x073 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_s instead.") +#define CLUTTER_t 0x074 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_t instead.") +#define CLUTTER_u 0x075 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_u instead.") +#define CLUTTER_v 0x076 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_v instead.") +#define CLUTTER_w 0x077 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_w instead.") +#define CLUTTER_x 0x078 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_x instead.") +#define CLUTTER_y 0x079 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_y instead.") +#define CLUTTER_z 0x07a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_z instead.") +#define CLUTTER_braceleft 0x07b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braceleft instead.") +#define CLUTTER_bar 0x07c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_bar instead.") +#define CLUTTER_braceright 0x07d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braceright instead.") +#define CLUTTER_asciitilde 0x07e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_asciitilde instead.") +#define CLUTTER_nobreakspace 0x0a0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_nobreakspace instead.") +#define CLUTTER_exclamdown 0x0a1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_exclamdown instead.") +#define CLUTTER_cent 0x0a2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_cent instead.") +#define CLUTTER_sterling 0x0a3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_sterling instead.") +#define CLUTTER_currency 0x0a4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_currency instead.") +#define CLUTTER_yen 0x0a5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_yen instead.") +#define CLUTTER_brokenbar 0x0a6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_brokenbar instead.") +#define CLUTTER_section 0x0a7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_section instead.") +#define CLUTTER_diaeresis 0x0a8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_diaeresis instead.") +#define CLUTTER_copyright 0x0a9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_copyright instead.") +#define CLUTTER_ordfeminine 0x0aa CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ordfeminine instead.") +#define CLUTTER_guillemotleft 0x0ab CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_guillemotleft instead.") +#define CLUTTER_notsign 0x0ac CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_notsign instead.") +#define CLUTTER_hyphen 0x0ad CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hyphen instead.") +#define CLUTTER_registered 0x0ae CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_registered instead.") +#define CLUTTER_macron 0x0af CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_macron instead.") +#define CLUTTER_degree 0x0b0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_degree instead.") +#define CLUTTER_plusminus 0x0b1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_plusminus instead.") +#define CLUTTER_twosuperior 0x0b2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_twosuperior instead.") +#define CLUTTER_threesuperior 0x0b3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_threesuperior instead.") +#define CLUTTER_acute 0x0b4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_acute instead.") +#define CLUTTER_mu 0x0b5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_mu instead.") +#define CLUTTER_paragraph 0x0b6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_paragraph instead.") +#define CLUTTER_periodcentered 0x0b7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_periodcentered instead.") +#define CLUTTER_cedilla 0x0b8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_cedilla instead.") +#define CLUTTER_onesuperior 0x0b9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_onesuperior instead.") +#define CLUTTER_masculine 0x0ba CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_masculine instead.") +#define CLUTTER_guillemotright 0x0bb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_guillemotright instead.") +#define CLUTTER_onequarter 0x0bc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_onequarter instead.") +#define CLUTTER_onehalf 0x0bd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_onehalf instead.") +#define CLUTTER_threequarters 0x0be CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_threequarters instead.") +#define CLUTTER_questiondown 0x0bf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_questiondown instead.") +#define CLUTTER_Agrave 0x0c0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Agrave instead.") +#define CLUTTER_Aacute 0x0c1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Aacute instead.") +#define CLUTTER_Acircumflex 0x0c2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Acircumflex instead.") +#define CLUTTER_Atilde 0x0c3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Atilde instead.") +#define CLUTTER_Adiaeresis 0x0c4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Adiaeresis instead.") +#define CLUTTER_Aring 0x0c5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Aring instead.") +#define CLUTTER_AE 0x0c6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_AE instead.") +#define CLUTTER_Ccedilla 0x0c7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ccedilla instead.") +#define CLUTTER_Egrave 0x0c8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Egrave instead.") +#define CLUTTER_Eacute 0x0c9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Eacute instead.") +#define CLUTTER_Ecircumflex 0x0ca CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ecircumflex instead.") +#define CLUTTER_Ediaeresis 0x0cb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ediaeresis instead.") +#define CLUTTER_Igrave 0x0cc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Igrave instead.") +#define CLUTTER_Iacute 0x0cd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Iacute instead.") +#define CLUTTER_Icircumflex 0x0ce CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Icircumflex instead.") +#define CLUTTER_Idiaeresis 0x0cf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Idiaeresis instead.") +#define CLUTTER_ETH 0x0d0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ETH instead.") +#define CLUTTER_Eth 0x0d0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Eth instead.") +#define CLUTTER_Ntilde 0x0d1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ntilde instead.") +#define CLUTTER_Ograve 0x0d2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ograve instead.") +#define CLUTTER_Oacute 0x0d3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Oacute instead.") +#define CLUTTER_Ocircumflex 0x0d4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ocircumflex instead.") +#define CLUTTER_Otilde 0x0d5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Otilde instead.") +#define CLUTTER_Odiaeresis 0x0d6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Odiaeresis instead.") +#define CLUTTER_multiply 0x0d7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_multiply instead.") +#define CLUTTER_Oslash 0x0d8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Oslash instead.") +#define CLUTTER_Ooblique 0x0d8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ooblique instead.") +#define CLUTTER_Ugrave 0x0d9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ugrave instead.") +#define CLUTTER_Uacute 0x0da CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Uacute instead.") +#define CLUTTER_Ucircumflex 0x0db CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ucircumflex instead.") +#define CLUTTER_Udiaeresis 0x0dc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Udiaeresis instead.") +#define CLUTTER_Yacute 0x0dd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Yacute instead.") +#define CLUTTER_THORN 0x0de CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_THORN instead.") +#define CLUTTER_Thorn 0x0de CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thorn instead.") +#define CLUTTER_ssharp 0x0df CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ssharp instead.") +#define CLUTTER_agrave 0x0e0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_agrave instead.") +#define CLUTTER_aacute 0x0e1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_aacute instead.") +#define CLUTTER_acircumflex 0x0e2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_acircumflex instead.") +#define CLUTTER_atilde 0x0e3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_atilde instead.") +#define CLUTTER_adiaeresis 0x0e4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_adiaeresis instead.") +#define CLUTTER_aring 0x0e5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_aring instead.") +#define CLUTTER_ae 0x0e6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ae instead.") +#define CLUTTER_ccedilla 0x0e7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ccedilla instead.") +#define CLUTTER_egrave 0x0e8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_egrave instead.") +#define CLUTTER_eacute 0x0e9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_eacute instead.") +#define CLUTTER_ecircumflex 0x0ea CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ecircumflex instead.") +#define CLUTTER_ediaeresis 0x0eb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ediaeresis instead.") +#define CLUTTER_igrave 0x0ec CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_igrave instead.") +#define CLUTTER_iacute 0x0ed CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_iacute instead.") +#define CLUTTER_icircumflex 0x0ee CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_icircumflex instead.") +#define CLUTTER_idiaeresis 0x0ef CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_idiaeresis instead.") +#define CLUTTER_eth 0x0f0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_eth instead.") +#define CLUTTER_ntilde 0x0f1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ntilde instead.") +#define CLUTTER_ograve 0x0f2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ograve instead.") +#define CLUTTER_oacute 0x0f3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_oacute instead.") +#define CLUTTER_ocircumflex 0x0f4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ocircumflex instead.") +#define CLUTTER_otilde 0x0f5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_otilde instead.") +#define CLUTTER_odiaeresis 0x0f6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_odiaeresis instead.") +#define CLUTTER_division 0x0f7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_division instead.") +#define CLUTTER_oslash 0x0f8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_oslash instead.") +#define CLUTTER_ooblique 0x0f8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ooblique instead.") +#define CLUTTER_ugrave 0x0f9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ugrave instead.") +#define CLUTTER_uacute 0x0fa CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_uacute instead.") +#define CLUTTER_ucircumflex 0x0fb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ucircumflex instead.") +#define CLUTTER_udiaeresis 0x0fc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_udiaeresis instead.") +#define CLUTTER_yacute 0x0fd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_yacute instead.") +#define CLUTTER_thorn 0x0fe CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_thorn instead.") +#define CLUTTER_ydiaeresis 0x0ff CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ydiaeresis instead.") +#define CLUTTER_Aogonek 0x1a1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Aogonek instead.") +#define CLUTTER_breve 0x1a2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_breve instead.") +#define CLUTTER_Lstroke 0x1a3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Lstroke instead.") +#define CLUTTER_Lcaron 0x1a5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Lcaron instead.") +#define CLUTTER_Sacute 0x1a6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sacute instead.") +#define CLUTTER_Scaron 0x1a9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Scaron instead.") +#define CLUTTER_Scedilla 0x1aa CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Scedilla instead.") +#define CLUTTER_Tcaron 0x1ab CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Tcaron instead.") +#define CLUTTER_Zacute 0x1ac CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Zacute instead.") +#define CLUTTER_Zcaron 0x1ae CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Zcaron instead.") +#define CLUTTER_Zabovedot 0x1af CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Zabovedot instead.") +#define CLUTTER_aogonek 0x1b1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_aogonek instead.") +#define CLUTTER_ogonek 0x1b2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ogonek instead.") +#define CLUTTER_lstroke 0x1b3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_lstroke instead.") +#define CLUTTER_lcaron 0x1b5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_lcaron instead.") +#define CLUTTER_sacute 0x1b6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_sacute instead.") +#define CLUTTER_caron 0x1b7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_caron instead.") +#define CLUTTER_scaron 0x1b9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_scaron instead.") +#define CLUTTER_scedilla 0x1ba CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_scedilla instead.") +#define CLUTTER_tcaron 0x1bb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_tcaron instead.") +#define CLUTTER_zacute 0x1bc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_zacute instead.") +#define CLUTTER_doubleacute 0x1bd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_doubleacute instead.") +#define CLUTTER_zcaron 0x1be CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_zcaron instead.") +#define CLUTTER_zabovedot 0x1bf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_zabovedot instead.") +#define CLUTTER_Racute 0x1c0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Racute instead.") +#define CLUTTER_Abreve 0x1c3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Abreve instead.") +#define CLUTTER_Lacute 0x1c5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Lacute instead.") +#define CLUTTER_Cacute 0x1c6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cacute instead.") +#define CLUTTER_Ccaron 0x1c8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ccaron instead.") +#define CLUTTER_Eogonek 0x1ca CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Eogonek instead.") +#define CLUTTER_Ecaron 0x1cc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ecaron instead.") +#define CLUTTER_Dcaron 0x1cf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Dcaron instead.") +#define CLUTTER_Dstroke 0x1d0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Dstroke instead.") +#define CLUTTER_Nacute 0x1d1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Nacute instead.") +#define CLUTTER_Ncaron 0x1d2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ncaron instead.") +#define CLUTTER_Odoubleacute 0x1d5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Odoubleacute instead.") +#define CLUTTER_Rcaron 0x1d8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Rcaron instead.") +#define CLUTTER_Uring 0x1d9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Uring instead.") +#define CLUTTER_Udoubleacute 0x1db CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Udoubleacute instead.") +#define CLUTTER_Tcedilla 0x1de CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Tcedilla instead.") +#define CLUTTER_racute 0x1e0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_racute instead.") +#define CLUTTER_abreve 0x1e3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_abreve instead.") +#define CLUTTER_lacute 0x1e5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_lacute instead.") +#define CLUTTER_cacute 0x1e6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_cacute instead.") +#define CLUTTER_ccaron 0x1e8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ccaron instead.") +#define CLUTTER_eogonek 0x1ea CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_eogonek instead.") +#define CLUTTER_ecaron 0x1ec CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ecaron instead.") +#define CLUTTER_dcaron 0x1ef CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dcaron instead.") +#define CLUTTER_dstroke 0x1f0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dstroke instead.") +#define CLUTTER_nacute 0x1f1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_nacute instead.") +#define CLUTTER_ncaron 0x1f2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ncaron instead.") +#define CLUTTER_odoubleacute 0x1f5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_odoubleacute instead.") +#define CLUTTER_rcaron 0x1f8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_rcaron instead.") +#define CLUTTER_uring 0x1f9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_uring instead.") +#define CLUTTER_udoubleacute 0x1fb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_udoubleacute instead.") +#define CLUTTER_tcedilla 0x1fe CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_tcedilla instead.") +#define CLUTTER_abovedot 0x1ff CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_abovedot instead.") +#define CLUTTER_Hstroke 0x2a1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hstroke instead.") +#define CLUTTER_Hcircumflex 0x2a6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hcircumflex instead.") +#define CLUTTER_Iabovedot 0x2a9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Iabovedot instead.") +#define CLUTTER_Gbreve 0x2ab CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Gbreve instead.") +#define CLUTTER_Jcircumflex 0x2ac CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Jcircumflex instead.") +#define CLUTTER_hstroke 0x2b1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hstroke instead.") +#define CLUTTER_hcircumflex 0x2b6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hcircumflex instead.") +#define CLUTTER_idotless 0x2b9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_idotless instead.") +#define CLUTTER_gbreve 0x2bb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_gbreve instead.") +#define CLUTTER_jcircumflex 0x2bc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_jcircumflex instead.") +#define CLUTTER_Cabovedot 0x2c5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cabovedot instead.") +#define CLUTTER_Ccircumflex 0x2c6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ccircumflex instead.") +#define CLUTTER_Gabovedot 0x2d5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Gabovedot instead.") +#define CLUTTER_Gcircumflex 0x2d8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Gcircumflex instead.") +#define CLUTTER_Ubreve 0x2dd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ubreve instead.") +#define CLUTTER_Scircumflex 0x2de CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Scircumflex instead.") +#define CLUTTER_cabovedot 0x2e5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_cabovedot instead.") +#define CLUTTER_ccircumflex 0x2e6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ccircumflex instead.") +#define CLUTTER_gabovedot 0x2f5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_gabovedot instead.") +#define CLUTTER_gcircumflex 0x2f8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_gcircumflex instead.") +#define CLUTTER_ubreve 0x2fd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ubreve instead.") +#define CLUTTER_scircumflex 0x2fe CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_scircumflex instead.") +#define CLUTTER_kra 0x3a2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kra instead.") +#define CLUTTER_kappa 0x3a2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kappa instead.") +#define CLUTTER_Rcedilla 0x3a3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Rcedilla instead.") +#define CLUTTER_Itilde 0x3a5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Itilde instead.") +#define CLUTTER_Lcedilla 0x3a6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Lcedilla instead.") +#define CLUTTER_Emacron 0x3aa CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Emacron instead.") +#define CLUTTER_Gcedilla 0x3ab CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Gcedilla instead.") +#define CLUTTER_Tslash 0x3ac CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Tslash instead.") +#define CLUTTER_rcedilla 0x3b3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_rcedilla instead.") +#define CLUTTER_itilde 0x3b5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_itilde instead.") +#define CLUTTER_lcedilla 0x3b6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_lcedilla instead.") +#define CLUTTER_emacron 0x3ba CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_emacron instead.") +#define CLUTTER_gcedilla 0x3bb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_gcedilla instead.") +#define CLUTTER_tslash 0x3bc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_tslash instead.") +#define CLUTTER_ENG 0x3bd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ENG instead.") +#define CLUTTER_eng 0x3bf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_eng instead.") +#define CLUTTER_Amacron 0x3c0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Amacron instead.") +#define CLUTTER_Iogonek 0x3c7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Iogonek instead.") +#define CLUTTER_Eabovedot 0x3cc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Eabovedot instead.") +#define CLUTTER_Imacron 0x3cf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Imacron instead.") +#define CLUTTER_Ncedilla 0x3d1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ncedilla instead.") +#define CLUTTER_Omacron 0x3d2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Omacron instead.") +#define CLUTTER_Kcedilla 0x3d3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Kcedilla instead.") +#define CLUTTER_Uogonek 0x3d9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Uogonek instead.") +#define CLUTTER_Utilde 0x3dd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Utilde instead.") +#define CLUTTER_Umacron 0x3de CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Umacron instead.") +#define CLUTTER_amacron 0x3e0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_amacron instead.") +#define CLUTTER_iogonek 0x3e7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_iogonek instead.") +#define CLUTTER_eabovedot 0x3ec CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_eabovedot instead.") +#define CLUTTER_imacron 0x3ef CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_imacron instead.") +#define CLUTTER_ncedilla 0x3f1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ncedilla instead.") +#define CLUTTER_omacron 0x3f2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_omacron instead.") +#define CLUTTER_kcedilla 0x3f3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kcedilla instead.") +#define CLUTTER_uogonek 0x3f9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_uogonek instead.") +#define CLUTTER_utilde 0x3fd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_utilde instead.") +#define CLUTTER_umacron 0x3fe CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_umacron instead.") +#define CLUTTER_Wcircumflex 0x1000174 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Wcircumflex instead.") +#define CLUTTER_wcircumflex 0x1000175 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_wcircumflex instead.") +#define CLUTTER_Ycircumflex 0x1000176 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ycircumflex instead.") +#define CLUTTER_ycircumflex 0x1000177 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ycircumflex instead.") +#define CLUTTER_Babovedot 0x1001e02 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Babovedot instead.") +#define CLUTTER_babovedot 0x1001e03 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_babovedot instead.") +#define CLUTTER_Dabovedot 0x1001e0a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Dabovedot instead.") +#define CLUTTER_dabovedot 0x1001e0b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dabovedot instead.") +#define CLUTTER_Fabovedot 0x1001e1e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Fabovedot instead.") +#define CLUTTER_fabovedot 0x1001e1f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_fabovedot instead.") +#define CLUTTER_Mabovedot 0x1001e40 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Mabovedot instead.") +#define CLUTTER_mabovedot 0x1001e41 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_mabovedot instead.") +#define CLUTTER_Pabovedot 0x1001e56 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Pabovedot instead.") +#define CLUTTER_pabovedot 0x1001e57 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_pabovedot instead.") +#define CLUTTER_Sabovedot 0x1001e60 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sabovedot instead.") +#define CLUTTER_sabovedot 0x1001e61 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_sabovedot instead.") +#define CLUTTER_Tabovedot 0x1001e6a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Tabovedot instead.") +#define CLUTTER_tabovedot 0x1001e6b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_tabovedot instead.") +#define CLUTTER_Wgrave 0x1001e80 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Wgrave instead.") +#define CLUTTER_wgrave 0x1001e81 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_wgrave instead.") +#define CLUTTER_Wacute 0x1001e82 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Wacute instead.") +#define CLUTTER_wacute 0x1001e83 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_wacute instead.") +#define CLUTTER_Wdiaeresis 0x1001e84 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Wdiaeresis instead.") +#define CLUTTER_wdiaeresis 0x1001e85 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_wdiaeresis instead.") +#define CLUTTER_Ygrave 0x1001ef2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ygrave instead.") +#define CLUTTER_ygrave 0x1001ef3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ygrave instead.") +#define CLUTTER_OE 0x13bc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_OE instead.") +#define CLUTTER_oe 0x13bd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_oe instead.") +#define CLUTTER_Ydiaeresis 0x13be CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ydiaeresis instead.") +#define CLUTTER_overline 0x47e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_overline instead.") +#define CLUTTER_kana_fullstop 0x4a1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_fullstop instead.") +#define CLUTTER_kana_openingbracket 0x4a2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_openingbracket instead.") +#define CLUTTER_kana_closingbracket 0x4a3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_closingbracket instead.") +#define CLUTTER_kana_comma 0x4a4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_comma instead.") +#define CLUTTER_kana_conjunctive 0x4a5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_conjunctive instead.") +#define CLUTTER_kana_middledot 0x4a5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_middledot instead.") +#define CLUTTER_kana_WO 0x4a6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_WO instead.") +#define CLUTTER_kana_a 0x4a7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_a instead.") +#define CLUTTER_kana_i 0x4a8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_i instead.") +#define CLUTTER_kana_u 0x4a9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_u instead.") +#define CLUTTER_kana_e 0x4aa CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_e instead.") +#define CLUTTER_kana_o 0x4ab CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_o instead.") +#define CLUTTER_kana_ya 0x4ac CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_ya instead.") +#define CLUTTER_kana_yu 0x4ad CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_yu instead.") +#define CLUTTER_kana_yo 0x4ae CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_yo instead.") +#define CLUTTER_kana_tsu 0x4af CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_tsu instead.") +#define CLUTTER_kana_tu 0x4af CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_tu instead.") +#define CLUTTER_prolongedsound 0x4b0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_prolongedsound instead.") +#define CLUTTER_kana_A 0x4b1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_A instead.") +#define CLUTTER_kana_I 0x4b2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_I instead.") +#define CLUTTER_kana_U 0x4b3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_U instead.") +#define CLUTTER_kana_E 0x4b4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_E instead.") +#define CLUTTER_kana_O 0x4b5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_O instead.") +#define CLUTTER_kana_KA 0x4b6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_KA instead.") +#define CLUTTER_kana_KI 0x4b7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_KI instead.") +#define CLUTTER_kana_KU 0x4b8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_KU instead.") +#define CLUTTER_kana_KE 0x4b9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_KE instead.") +#define CLUTTER_kana_KO 0x4ba CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_KO instead.") +#define CLUTTER_kana_SA 0x4bb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_SA instead.") +#define CLUTTER_kana_SHI 0x4bc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_SHI instead.") +#define CLUTTER_kana_SU 0x4bd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_SU instead.") +#define CLUTTER_kana_SE 0x4be CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_SE instead.") +#define CLUTTER_kana_SO 0x4bf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_SO instead.") +#define CLUTTER_kana_TA 0x4c0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_TA instead.") +#define CLUTTER_kana_CHI 0x4c1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_CHI instead.") +#define CLUTTER_kana_TI 0x4c1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_TI instead.") +#define CLUTTER_kana_TSU 0x4c2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_TSU instead.") +#define CLUTTER_kana_TU 0x4c2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_TU instead.") +#define CLUTTER_kana_TE 0x4c3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_TE instead.") +#define CLUTTER_kana_TO 0x4c4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_TO instead.") +#define CLUTTER_kana_NA 0x4c5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_NA instead.") +#define CLUTTER_kana_NI 0x4c6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_NI instead.") +#define CLUTTER_kana_NU 0x4c7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_NU instead.") +#define CLUTTER_kana_NE 0x4c8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_NE instead.") +#define CLUTTER_kana_NO 0x4c9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_NO instead.") +#define CLUTTER_kana_HA 0x4ca CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_HA instead.") +#define CLUTTER_kana_HI 0x4cb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_HI instead.") +#define CLUTTER_kana_FU 0x4cc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_FU instead.") +#define CLUTTER_kana_HU 0x4cc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_HU instead.") +#define CLUTTER_kana_HE 0x4cd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_HE instead.") +#define CLUTTER_kana_HO 0x4ce CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_HO instead.") +#define CLUTTER_kana_MA 0x4cf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_MA instead.") +#define CLUTTER_kana_MI 0x4d0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_MI instead.") +#define CLUTTER_kana_MU 0x4d1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_MU instead.") +#define CLUTTER_kana_ME 0x4d2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_ME instead.") +#define CLUTTER_kana_MO 0x4d3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_MO instead.") +#define CLUTTER_kana_YA 0x4d4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_YA instead.") +#define CLUTTER_kana_YU 0x4d5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_YU instead.") +#define CLUTTER_kana_YO 0x4d6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_YO instead.") +#define CLUTTER_kana_RA 0x4d7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_RA instead.") +#define CLUTTER_kana_RI 0x4d8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_RI instead.") +#define CLUTTER_kana_RU 0x4d9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_RU instead.") +#define CLUTTER_kana_RE 0x4da CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_RE instead.") +#define CLUTTER_kana_RO 0x4db CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_RO instead.") +#define CLUTTER_kana_WA 0x4dc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_WA instead.") +#define CLUTTER_kana_N 0x4dd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_N instead.") +#define CLUTTER_voicedsound 0x4de CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_voicedsound instead.") +#define CLUTTER_semivoicedsound 0x4df CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_semivoicedsound instead.") +#define CLUTTER_kana_switch 0xff7e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_kana_switch instead.") +#define CLUTTER_Farsi_0 0x10006f0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Farsi_0 instead.") +#define CLUTTER_Farsi_1 0x10006f1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Farsi_1 instead.") +#define CLUTTER_Farsi_2 0x10006f2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Farsi_2 instead.") +#define CLUTTER_Farsi_3 0x10006f3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Farsi_3 instead.") +#define CLUTTER_Farsi_4 0x10006f4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Farsi_4 instead.") +#define CLUTTER_Farsi_5 0x10006f5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Farsi_5 instead.") +#define CLUTTER_Farsi_6 0x10006f6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Farsi_6 instead.") +#define CLUTTER_Farsi_7 0x10006f7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Farsi_7 instead.") +#define CLUTTER_Farsi_8 0x10006f8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Farsi_8 instead.") +#define CLUTTER_Farsi_9 0x10006f9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Farsi_9 instead.") +#define CLUTTER_Arabic_percent 0x100066a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_percent instead.") +#define CLUTTER_Arabic_superscript_alef 0x1000670 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_superscript_alef instead.") +#define CLUTTER_Arabic_tteh 0x1000679 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_tteh instead.") +#define CLUTTER_Arabic_peh 0x100067e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_peh instead.") +#define CLUTTER_Arabic_tcheh 0x1000686 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_tcheh instead.") +#define CLUTTER_Arabic_ddal 0x1000688 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_ddal instead.") +#define CLUTTER_Arabic_rreh 0x1000691 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_rreh instead.") +#define CLUTTER_Arabic_comma 0x5ac CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_comma instead.") +#define CLUTTER_Arabic_fullstop 0x10006d4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_fullstop instead.") +#define CLUTTER_Arabic_0 0x1000660 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_0 instead.") +#define CLUTTER_Arabic_1 0x1000661 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_1 instead.") +#define CLUTTER_Arabic_2 0x1000662 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_2 instead.") +#define CLUTTER_Arabic_3 0x1000663 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_3 instead.") +#define CLUTTER_Arabic_4 0x1000664 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_4 instead.") +#define CLUTTER_Arabic_5 0x1000665 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_5 instead.") +#define CLUTTER_Arabic_6 0x1000666 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_6 instead.") +#define CLUTTER_Arabic_7 0x1000667 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_7 instead.") +#define CLUTTER_Arabic_8 0x1000668 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_8 instead.") +#define CLUTTER_Arabic_9 0x1000669 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_9 instead.") +#define CLUTTER_Arabic_semicolon 0x5bb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_semicolon instead.") +#define CLUTTER_Arabic_question_mark 0x5bf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_question_mark instead.") +#define CLUTTER_Arabic_hamza 0x5c1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_hamza instead.") +#define CLUTTER_Arabic_maddaonalef 0x5c2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_maddaonalef instead.") +#define CLUTTER_Arabic_hamzaonalef 0x5c3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_hamzaonalef instead.") +#define CLUTTER_Arabic_hamzaonwaw 0x5c4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_hamzaonwaw instead.") +#define CLUTTER_Arabic_hamzaunderalef 0x5c5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_hamzaunderalef instead.") +#define CLUTTER_Arabic_hamzaonyeh 0x5c6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_hamzaonyeh instead.") +#define CLUTTER_Arabic_alef 0x5c7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_alef instead.") +#define CLUTTER_Arabic_beh 0x5c8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_beh instead.") +#define CLUTTER_Arabic_tehmarbuta 0x5c9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_tehmarbuta instead.") +#define CLUTTER_Arabic_teh 0x5ca CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_teh instead.") +#define CLUTTER_Arabic_theh 0x5cb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_theh instead.") +#define CLUTTER_Arabic_jeem 0x5cc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_jeem instead.") +#define CLUTTER_Arabic_hah 0x5cd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_hah instead.") +#define CLUTTER_Arabic_khah 0x5ce CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_khah instead.") +#define CLUTTER_Arabic_dal 0x5cf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_dal instead.") +#define CLUTTER_Arabic_thal 0x5d0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_thal instead.") +#define CLUTTER_Arabic_ra 0x5d1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_ra instead.") +#define CLUTTER_Arabic_zain 0x5d2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_zain instead.") +#define CLUTTER_Arabic_seen 0x5d3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_seen instead.") +#define CLUTTER_Arabic_sheen 0x5d4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_sheen instead.") +#define CLUTTER_Arabic_sad 0x5d5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_sad instead.") +#define CLUTTER_Arabic_dad 0x5d6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_dad instead.") +#define CLUTTER_Arabic_tah 0x5d7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_tah instead.") +#define CLUTTER_Arabic_zah 0x5d8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_zah instead.") +#define CLUTTER_Arabic_ain 0x5d9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_ain instead.") +#define CLUTTER_Arabic_ghain 0x5da CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_ghain instead.") +#define CLUTTER_Arabic_tatweel 0x5e0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_tatweel instead.") +#define CLUTTER_Arabic_feh 0x5e1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_feh instead.") +#define CLUTTER_Arabic_qaf 0x5e2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_qaf instead.") +#define CLUTTER_Arabic_kaf 0x5e3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_kaf instead.") +#define CLUTTER_Arabic_lam 0x5e4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_lam instead.") +#define CLUTTER_Arabic_meem 0x5e5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_meem instead.") +#define CLUTTER_Arabic_noon 0x5e6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_noon instead.") +#define CLUTTER_Arabic_ha 0x5e7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_ha instead.") +#define CLUTTER_Arabic_heh 0x5e7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_heh instead.") +#define CLUTTER_Arabic_waw 0x5e8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_waw instead.") +#define CLUTTER_Arabic_alefmaksura 0x5e9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_alefmaksura instead.") +#define CLUTTER_Arabic_yeh 0x5ea CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_yeh instead.") +#define CLUTTER_Arabic_fathatan 0x5eb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_fathatan instead.") +#define CLUTTER_Arabic_dammatan 0x5ec CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_dammatan instead.") +#define CLUTTER_Arabic_kasratan 0x5ed CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_kasratan instead.") +#define CLUTTER_Arabic_fatha 0x5ee CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_fatha instead.") +#define CLUTTER_Arabic_damma 0x5ef CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_damma instead.") +#define CLUTTER_Arabic_kasra 0x5f0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_kasra instead.") +#define CLUTTER_Arabic_shadda 0x5f1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_shadda instead.") +#define CLUTTER_Arabic_sukun 0x5f2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_sukun instead.") +#define CLUTTER_Arabic_madda_above 0x1000653 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_madda_above instead.") +#define CLUTTER_Arabic_hamza_above 0x1000654 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_hamza_above instead.") +#define CLUTTER_Arabic_hamza_below 0x1000655 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_hamza_below instead.") +#define CLUTTER_Arabic_jeh 0x1000698 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_jeh instead.") +#define CLUTTER_Arabic_veh 0x10006a4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_veh instead.") +#define CLUTTER_Arabic_keheh 0x10006a9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_keheh instead.") +#define CLUTTER_Arabic_gaf 0x10006af CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_gaf instead.") +#define CLUTTER_Arabic_noon_ghunna 0x10006ba CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_noon_ghunna instead.") +#define CLUTTER_Arabic_heh_doachashmee 0x10006be CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_heh_doachashmee instead.") +#define CLUTTER_Farsi_yeh 0x10006cc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Farsi_yeh instead.") +#define CLUTTER_Arabic_farsi_yeh 0x10006cc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_farsi_yeh instead.") +#define CLUTTER_Arabic_yeh_baree 0x10006d2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_yeh_baree instead.") +#define CLUTTER_Arabic_heh_goal 0x10006c1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_heh_goal instead.") +#define CLUTTER_Arabic_switch 0xff7e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Arabic_switch instead.") +#define CLUTTER_Cyrillic_GHE_bar 0x1000492 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_GHE_bar instead.") +#define CLUTTER_Cyrillic_ghe_bar 0x1000493 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_ghe_bar instead.") +#define CLUTTER_Cyrillic_ZHE_descender 0x1000496 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_ZHE_descender instead.") +#define CLUTTER_Cyrillic_zhe_descender 0x1000497 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_zhe_descender instead.") +#define CLUTTER_Cyrillic_KA_descender 0x100049a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_KA_descender instead.") +#define CLUTTER_Cyrillic_ka_descender 0x100049b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_ka_descender instead.") +#define CLUTTER_Cyrillic_KA_vertstroke 0x100049c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_KA_vertstroke instead.") +#define CLUTTER_Cyrillic_ka_vertstroke 0x100049d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_ka_vertstroke instead.") +#define CLUTTER_Cyrillic_EN_descender 0x10004a2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_EN_descender instead.") +#define CLUTTER_Cyrillic_en_descender 0x10004a3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_en_descender instead.") +#define CLUTTER_Cyrillic_U_straight 0x10004ae CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_U_straight instead.") +#define CLUTTER_Cyrillic_u_straight 0x10004af CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_u_straight instead.") +#define CLUTTER_Cyrillic_U_straight_bar 0x10004b0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_U_straight_bar instead.") +#define CLUTTER_Cyrillic_u_straight_bar 0x10004b1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_u_straight_bar instead.") +#define CLUTTER_Cyrillic_HA_descender 0x10004b2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_HA_descender instead.") +#define CLUTTER_Cyrillic_ha_descender 0x10004b3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_ha_descender instead.") +#define CLUTTER_Cyrillic_CHE_descender 0x10004b6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_CHE_descender instead.") +#define CLUTTER_Cyrillic_che_descender 0x10004b7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_che_descender instead.") +#define CLUTTER_Cyrillic_CHE_vertstroke 0x10004b8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_CHE_vertstroke instead.") +#define CLUTTER_Cyrillic_che_vertstroke 0x10004b9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_che_vertstroke instead.") +#define CLUTTER_Cyrillic_SHHA 0x10004ba CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_SHHA instead.") +#define CLUTTER_Cyrillic_shha 0x10004bb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_shha instead.") +#define CLUTTER_Cyrillic_SCHWA 0x10004d8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_SCHWA instead.") +#define CLUTTER_Cyrillic_schwa 0x10004d9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_schwa instead.") +#define CLUTTER_Cyrillic_I_macron 0x10004e2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_I_macron instead.") +#define CLUTTER_Cyrillic_i_macron 0x10004e3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_i_macron instead.") +#define CLUTTER_Cyrillic_O_bar 0x10004e8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_O_bar instead.") +#define CLUTTER_Cyrillic_o_bar 0x10004e9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_o_bar instead.") +#define CLUTTER_Cyrillic_U_macron 0x10004ee CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_U_macron instead.") +#define CLUTTER_Cyrillic_u_macron 0x10004ef CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_u_macron instead.") +#define CLUTTER_Serbian_dje 0x6a1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Serbian_dje instead.") +#define CLUTTER_Macedonia_gje 0x6a2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Macedonia_gje instead.") +#define CLUTTER_Cyrillic_io 0x6a3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_io instead.") +#define CLUTTER_Ukrainian_ie 0x6a4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ukrainian_ie instead.") +#define CLUTTER_Ukranian_je 0x6a4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ukranian_je instead.") +#define CLUTTER_Macedonia_dse 0x6a5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Macedonia_dse instead.") +#define CLUTTER_Ukrainian_i 0x6a6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ukrainian_i instead.") +#define CLUTTER_Ukranian_i 0x6a6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ukranian_i instead.") +#define CLUTTER_Ukrainian_yi 0x6a7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ukrainian_yi instead.") +#define CLUTTER_Ukranian_yi 0x6a7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ukranian_yi instead.") +#define CLUTTER_Cyrillic_je 0x6a8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_je instead.") +#define CLUTTER_Serbian_je 0x6a8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Serbian_je instead.") +#define CLUTTER_Cyrillic_lje 0x6a9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_lje instead.") +#define CLUTTER_Serbian_lje 0x6a9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Serbian_lje instead.") +#define CLUTTER_Cyrillic_nje 0x6aa CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_nje instead.") +#define CLUTTER_Serbian_nje 0x6aa CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Serbian_nje instead.") +#define CLUTTER_Serbian_tshe 0x6ab CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Serbian_tshe instead.") +#define CLUTTER_Macedonia_kje 0x6ac CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Macedonia_kje instead.") +#define CLUTTER_Ukrainian_ghe_with_upturn 0x6ad CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ukrainian_ghe_with_upturn instead.") +#define CLUTTER_Byelorussian_shortu 0x6ae CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Byelorussian_shortu instead.") +#define CLUTTER_Cyrillic_dzhe 0x6af CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_dzhe instead.") +#define CLUTTER_Serbian_dze 0x6af CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Serbian_dze instead.") +#define CLUTTER_numerosign 0x6b0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_numerosign instead.") +#define CLUTTER_Serbian_DJE 0x6b1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Serbian_DJE instead.") +#define CLUTTER_Macedonia_GJE 0x6b2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Macedonia_GJE instead.") +#define CLUTTER_Cyrillic_IO 0x6b3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_IO instead.") +#define CLUTTER_Ukrainian_IE 0x6b4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ukrainian_IE instead.") +#define CLUTTER_Ukranian_JE 0x6b4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ukranian_JE instead.") +#define CLUTTER_Macedonia_DSE 0x6b5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Macedonia_DSE instead.") +#define CLUTTER_Ukrainian_I 0x6b6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ukrainian_I instead.") +#define CLUTTER_Ukranian_I 0x6b6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ukranian_I instead.") +#define CLUTTER_Ukrainian_YI 0x6b7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ukrainian_YI instead.") +#define CLUTTER_Ukranian_YI 0x6b7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ukranian_YI instead.") +#define CLUTTER_Cyrillic_JE 0x6b8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_JE instead.") +#define CLUTTER_Serbian_JE 0x6b8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Serbian_JE instead.") +#define CLUTTER_Cyrillic_LJE 0x6b9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_LJE instead.") +#define CLUTTER_Serbian_LJE 0x6b9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Serbian_LJE instead.") +#define CLUTTER_Cyrillic_NJE 0x6ba CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_NJE instead.") +#define CLUTTER_Serbian_NJE 0x6ba CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Serbian_NJE instead.") +#define CLUTTER_Serbian_TSHE 0x6bb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Serbian_TSHE instead.") +#define CLUTTER_Macedonia_KJE 0x6bc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Macedonia_KJE instead.") +#define CLUTTER_Ukrainian_GHE_WITH_UPTURN 0x6bd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ukrainian_GHE_WITH_UPTURN instead.") +#define CLUTTER_Byelorussian_SHORTU 0x6be CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Byelorussian_SHORTU instead.") +#define CLUTTER_Cyrillic_DZHE 0x6bf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_DZHE instead.") +#define CLUTTER_Serbian_DZE 0x6bf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Serbian_DZE instead.") +#define CLUTTER_Cyrillic_yu 0x6c0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_yu instead.") +#define CLUTTER_Cyrillic_a 0x6c1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_a instead.") +#define CLUTTER_Cyrillic_be 0x6c2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_be instead.") +#define CLUTTER_Cyrillic_tse 0x6c3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_tse instead.") +#define CLUTTER_Cyrillic_de 0x6c4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_de instead.") +#define CLUTTER_Cyrillic_ie 0x6c5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_ie instead.") +#define CLUTTER_Cyrillic_ef 0x6c6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_ef instead.") +#define CLUTTER_Cyrillic_ghe 0x6c7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_ghe instead.") +#define CLUTTER_Cyrillic_ha 0x6c8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_ha instead.") +#define CLUTTER_Cyrillic_i 0x6c9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_i instead.") +#define CLUTTER_Cyrillic_shorti 0x6ca CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_shorti instead.") +#define CLUTTER_Cyrillic_ka 0x6cb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_ka instead.") +#define CLUTTER_Cyrillic_el 0x6cc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_el instead.") +#define CLUTTER_Cyrillic_em 0x6cd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_em instead.") +#define CLUTTER_Cyrillic_en 0x6ce CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_en instead.") +#define CLUTTER_Cyrillic_o 0x6cf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_o instead.") +#define CLUTTER_Cyrillic_pe 0x6d0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_pe instead.") +#define CLUTTER_Cyrillic_ya 0x6d1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_ya instead.") +#define CLUTTER_Cyrillic_er 0x6d2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_er instead.") +#define CLUTTER_Cyrillic_es 0x6d3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_es instead.") +#define CLUTTER_Cyrillic_te 0x6d4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_te instead.") +#define CLUTTER_Cyrillic_u 0x6d5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_u instead.") +#define CLUTTER_Cyrillic_zhe 0x6d6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_zhe instead.") +#define CLUTTER_Cyrillic_ve 0x6d7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_ve instead.") +#define CLUTTER_Cyrillic_softsign 0x6d8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_softsign instead.") +#define CLUTTER_Cyrillic_yeru 0x6d9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_yeru instead.") +#define CLUTTER_Cyrillic_ze 0x6da CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_ze instead.") +#define CLUTTER_Cyrillic_sha 0x6db CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_sha instead.") +#define CLUTTER_Cyrillic_e 0x6dc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_e instead.") +#define CLUTTER_Cyrillic_shcha 0x6dd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_shcha instead.") +#define CLUTTER_Cyrillic_che 0x6de CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_che instead.") +#define CLUTTER_Cyrillic_hardsign 0x6df CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_hardsign instead.") +#define CLUTTER_Cyrillic_YU 0x6e0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_YU instead.") +#define CLUTTER_Cyrillic_A 0x6e1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_A instead.") +#define CLUTTER_Cyrillic_BE 0x6e2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_BE instead.") +#define CLUTTER_Cyrillic_TSE 0x6e3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_TSE instead.") +#define CLUTTER_Cyrillic_DE 0x6e4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_DE instead.") +#define CLUTTER_Cyrillic_IE 0x6e5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_IE instead.") +#define CLUTTER_Cyrillic_EF 0x6e6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_EF instead.") +#define CLUTTER_Cyrillic_GHE 0x6e7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_GHE instead.") +#define CLUTTER_Cyrillic_HA 0x6e8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_HA instead.") +#define CLUTTER_Cyrillic_I 0x6e9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_I instead.") +#define CLUTTER_Cyrillic_SHORTI 0x6ea CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_SHORTI instead.") +#define CLUTTER_Cyrillic_KA 0x6eb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_KA instead.") +#define CLUTTER_Cyrillic_EL 0x6ec CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_EL instead.") +#define CLUTTER_Cyrillic_EM 0x6ed CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_EM instead.") +#define CLUTTER_Cyrillic_EN 0x6ee CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_EN instead.") +#define CLUTTER_Cyrillic_O 0x6ef CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_O instead.") +#define CLUTTER_Cyrillic_PE 0x6f0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_PE instead.") +#define CLUTTER_Cyrillic_YA 0x6f1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_YA instead.") +#define CLUTTER_Cyrillic_ER 0x6f2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_ER instead.") +#define CLUTTER_Cyrillic_ES 0x6f3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_ES instead.") +#define CLUTTER_Cyrillic_TE 0x6f4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_TE instead.") +#define CLUTTER_Cyrillic_U 0x6f5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_U instead.") +#define CLUTTER_Cyrillic_ZHE 0x6f6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_ZHE instead.") +#define CLUTTER_Cyrillic_VE 0x6f7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_VE instead.") +#define CLUTTER_Cyrillic_SOFTSIGN 0x6f8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_SOFTSIGN instead.") +#define CLUTTER_Cyrillic_YERU 0x6f9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_YERU instead.") +#define CLUTTER_Cyrillic_ZE 0x6fa CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_ZE instead.") +#define CLUTTER_Cyrillic_SHA 0x6fb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_SHA instead.") +#define CLUTTER_Cyrillic_E 0x6fc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_E instead.") +#define CLUTTER_Cyrillic_SHCHA 0x6fd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_SHCHA instead.") +#define CLUTTER_Cyrillic_CHE 0x6fe CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_CHE instead.") +#define CLUTTER_Cyrillic_HARDSIGN 0x6ff CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Cyrillic_HARDSIGN instead.") +#define CLUTTER_Greek_ALPHAaccent 0x7a1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_ALPHAaccent instead.") +#define CLUTTER_Greek_EPSILONaccent 0x7a2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_EPSILONaccent instead.") +#define CLUTTER_Greek_ETAaccent 0x7a3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_ETAaccent instead.") +#define CLUTTER_Greek_IOTAaccent 0x7a4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_IOTAaccent instead.") +#define CLUTTER_Greek_IOTAdieresis 0x7a5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_IOTAdieresis instead.") +#define CLUTTER_Greek_IOTAdiaeresis 0x7a5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_IOTAdiaeresis instead.") +#define CLUTTER_Greek_OMICRONaccent 0x7a7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_OMICRONaccent instead.") +#define CLUTTER_Greek_UPSILONaccent 0x7a8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_UPSILONaccent instead.") +#define CLUTTER_Greek_UPSILONdieresis 0x7a9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_UPSILONdieresis instead.") +#define CLUTTER_Greek_OMEGAaccent 0x7ab CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_OMEGAaccent instead.") +#define CLUTTER_Greek_accentdieresis 0x7ae CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_accentdieresis instead.") +#define CLUTTER_Greek_horizbar 0x7af CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_horizbar instead.") +#define CLUTTER_Greek_alphaaccent 0x7b1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_alphaaccent instead.") +#define CLUTTER_Greek_epsilonaccent 0x7b2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_epsilonaccent instead.") +#define CLUTTER_Greek_etaaccent 0x7b3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_etaaccent instead.") +#define CLUTTER_Greek_iotaaccent 0x7b4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_iotaaccent instead.") +#define CLUTTER_Greek_iotadieresis 0x7b5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_iotadieresis instead.") +#define CLUTTER_Greek_iotaaccentdieresis 0x7b6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_iotaaccentdieresis instead.") +#define CLUTTER_Greek_omicronaccent 0x7b7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_omicronaccent instead.") +#define CLUTTER_Greek_upsilonaccent 0x7b8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_upsilonaccent instead.") +#define CLUTTER_Greek_upsilondieresis 0x7b9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_upsilondieresis instead.") +#define CLUTTER_Greek_upsilonaccentdieresis 0x7ba CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_upsilonaccentdieresis instead.") +#define CLUTTER_Greek_omegaaccent 0x7bb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_omegaaccent instead.") +#define CLUTTER_Greek_ALPHA 0x7c1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_ALPHA instead.") +#define CLUTTER_Greek_BETA 0x7c2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_BETA instead.") +#define CLUTTER_Greek_GAMMA 0x7c3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_GAMMA instead.") +#define CLUTTER_Greek_DELTA 0x7c4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_DELTA instead.") +#define CLUTTER_Greek_EPSILON 0x7c5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_EPSILON instead.") +#define CLUTTER_Greek_ZETA 0x7c6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_ZETA instead.") +#define CLUTTER_Greek_ETA 0x7c7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_ETA instead.") +#define CLUTTER_Greek_THETA 0x7c8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_THETA instead.") +#define CLUTTER_Greek_IOTA 0x7c9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_IOTA instead.") +#define CLUTTER_Greek_KAPPA 0x7ca CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_KAPPA instead.") +#define CLUTTER_Greek_LAMDA 0x7cb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_LAMDA instead.") +#define CLUTTER_Greek_LAMBDA 0x7cb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_LAMBDA instead.") +#define CLUTTER_Greek_MU 0x7cc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_MU instead.") +#define CLUTTER_Greek_NU 0x7cd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_NU instead.") +#define CLUTTER_Greek_XI 0x7ce CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_XI instead.") +#define CLUTTER_Greek_OMICRON 0x7cf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_OMICRON instead.") +#define CLUTTER_Greek_PI 0x7d0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_PI instead.") +#define CLUTTER_Greek_RHO 0x7d1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_RHO instead.") +#define CLUTTER_Greek_SIGMA 0x7d2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_SIGMA instead.") +#define CLUTTER_Greek_TAU 0x7d4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_TAU instead.") +#define CLUTTER_Greek_UPSILON 0x7d5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_UPSILON instead.") +#define CLUTTER_Greek_PHI 0x7d6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_PHI instead.") +#define CLUTTER_Greek_CHI 0x7d7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_CHI instead.") +#define CLUTTER_Greek_PSI 0x7d8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_PSI instead.") +#define CLUTTER_Greek_OMEGA 0x7d9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_OMEGA instead.") +#define CLUTTER_Greek_alpha 0x7e1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_alpha instead.") +#define CLUTTER_Greek_beta 0x7e2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_beta instead.") +#define CLUTTER_Greek_gamma 0x7e3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_gamma instead.") +#define CLUTTER_Greek_delta 0x7e4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_delta instead.") +#define CLUTTER_Greek_epsilon 0x7e5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_epsilon instead.") +#define CLUTTER_Greek_zeta 0x7e6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_zeta instead.") +#define CLUTTER_Greek_eta 0x7e7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_eta instead.") +#define CLUTTER_Greek_theta 0x7e8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_theta instead.") +#define CLUTTER_Greek_iota 0x7e9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_iota instead.") +#define CLUTTER_Greek_kappa 0x7ea CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_kappa instead.") +#define CLUTTER_Greek_lamda 0x7eb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_lamda instead.") +#define CLUTTER_Greek_lambda 0x7eb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_lambda instead.") +#define CLUTTER_Greek_mu 0x7ec CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_mu instead.") +#define CLUTTER_Greek_nu 0x7ed CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_nu instead.") +#define CLUTTER_Greek_xi 0x7ee CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_xi instead.") +#define CLUTTER_Greek_omicron 0x7ef CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_omicron instead.") +#define CLUTTER_Greek_pi 0x7f0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_pi instead.") +#define CLUTTER_Greek_rho 0x7f1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_rho instead.") +#define CLUTTER_Greek_sigma 0x7f2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_sigma instead.") +#define CLUTTER_Greek_finalsmallsigma 0x7f3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_finalsmallsigma instead.") +#define CLUTTER_Greek_tau 0x7f4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_tau instead.") +#define CLUTTER_Greek_upsilon 0x7f5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_upsilon instead.") +#define CLUTTER_Greek_phi 0x7f6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_phi instead.") +#define CLUTTER_Greek_chi 0x7f7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_chi instead.") +#define CLUTTER_Greek_psi 0x7f8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_psi instead.") +#define CLUTTER_Greek_omega 0x7f9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_omega instead.") +#define CLUTTER_Greek_switch 0xff7e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Greek_switch instead.") +#define CLUTTER_leftradical 0x8a1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_leftradical instead.") +#define CLUTTER_topleftradical 0x8a2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_topleftradical instead.") +#define CLUTTER_horizconnector 0x8a3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_horizconnector instead.") +#define CLUTTER_topintegral 0x8a4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_topintegral instead.") +#define CLUTTER_botintegral 0x8a5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_botintegral instead.") +#define CLUTTER_vertconnector 0x8a6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_vertconnector instead.") +#define CLUTTER_topleftsqbracket 0x8a7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_topleftsqbracket instead.") +#define CLUTTER_botleftsqbracket 0x8a8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_botleftsqbracket instead.") +#define CLUTTER_toprightsqbracket 0x8a9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_toprightsqbracket instead.") +#define CLUTTER_botrightsqbracket 0x8aa CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_botrightsqbracket instead.") +#define CLUTTER_topleftparens 0x8ab CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_topleftparens instead.") +#define CLUTTER_botleftparens 0x8ac CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_botleftparens instead.") +#define CLUTTER_toprightparens 0x8ad CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_toprightparens instead.") +#define CLUTTER_botrightparens 0x8ae CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_botrightparens instead.") +#define CLUTTER_leftmiddlecurlybrace 0x8af CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_leftmiddlecurlybrace instead.") +#define CLUTTER_rightmiddlecurlybrace 0x8b0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_rightmiddlecurlybrace instead.") +#define CLUTTER_topleftsummation 0x8b1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_topleftsummation instead.") +#define CLUTTER_botleftsummation 0x8b2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_botleftsummation instead.") +#define CLUTTER_topvertsummationconnector 0x8b3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_topvertsummationconnector instead.") +#define CLUTTER_botvertsummationconnector 0x8b4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_botvertsummationconnector instead.") +#define CLUTTER_toprightsummation 0x8b5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_toprightsummation instead.") +#define CLUTTER_botrightsummation 0x8b6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_botrightsummation instead.") +#define CLUTTER_rightmiddlesummation 0x8b7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_rightmiddlesummation instead.") +#define CLUTTER_lessthanequal 0x8bc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_lessthanequal instead.") +#define CLUTTER_notequal 0x8bd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_notequal instead.") +#define CLUTTER_greaterthanequal 0x8be CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_greaterthanequal instead.") +#define CLUTTER_integral 0x8bf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_integral instead.") +#define CLUTTER_therefore 0x8c0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_therefore instead.") +#define CLUTTER_variation 0x8c1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_variation instead.") +#define CLUTTER_infinity 0x8c2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_infinity instead.") +#define CLUTTER_nabla 0x8c5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_nabla instead.") +#define CLUTTER_approximate 0x8c8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_approximate instead.") +#define CLUTTER_similarequal 0x8c9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_similarequal instead.") +#define CLUTTER_ifonlyif 0x8cd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ifonlyif instead.") +#define CLUTTER_implies 0x8ce CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_implies instead.") +#define CLUTTER_identical 0x8cf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_identical instead.") +#define CLUTTER_radical 0x8d6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_radical instead.") +#define CLUTTER_includedin 0x8da CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_includedin instead.") +#define CLUTTER_includes 0x8db CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_includes instead.") +#define CLUTTER_intersection 0x8dc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_intersection instead.") +#define CLUTTER_union 0x8dd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_union instead.") +#define CLUTTER_logicaland 0x8de CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_logicaland instead.") +#define CLUTTER_logicalor 0x8df CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_logicalor instead.") +#define CLUTTER_partialderivative 0x8ef CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_partialderivative instead.") +#define CLUTTER_function 0x8f6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_function instead.") +#define CLUTTER_leftarrow 0x8fb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_leftarrow instead.") +#define CLUTTER_uparrow 0x8fc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_uparrow instead.") +#define CLUTTER_rightarrow 0x8fd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_rightarrow instead.") +#define CLUTTER_downarrow 0x8fe CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_downarrow instead.") +#define CLUTTER_blank 0x9df CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_blank instead.") +#define CLUTTER_soliddiamond 0x9e0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_soliddiamond instead.") +#define CLUTTER_checkerboard 0x9e1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_checkerboard instead.") +#define CLUTTER_ht 0x9e2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ht instead.") +#define CLUTTER_ff 0x9e3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ff instead.") +#define CLUTTER_cr 0x9e4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_cr instead.") +#define CLUTTER_lf 0x9e5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_lf instead.") +#define CLUTTER_nl 0x9e8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_nl instead.") +#define CLUTTER_vt 0x9e9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_vt instead.") +#define CLUTTER_lowrightcorner 0x9ea CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_lowrightcorner instead.") +#define CLUTTER_uprightcorner 0x9eb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_uprightcorner instead.") +#define CLUTTER_upleftcorner 0x9ec CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_upleftcorner instead.") +#define CLUTTER_lowleftcorner 0x9ed CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_lowleftcorner instead.") +#define CLUTTER_crossinglines 0x9ee CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_crossinglines instead.") +#define CLUTTER_horizlinescan1 0x9ef CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_horizlinescan1 instead.") +#define CLUTTER_horizlinescan3 0x9f0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_horizlinescan3 instead.") +#define CLUTTER_horizlinescan5 0x9f1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_horizlinescan5 instead.") +#define CLUTTER_horizlinescan7 0x9f2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_horizlinescan7 instead.") +#define CLUTTER_horizlinescan9 0x9f3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_horizlinescan9 instead.") +#define CLUTTER_leftt 0x9f4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_leftt instead.") +#define CLUTTER_rightt 0x9f5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_rightt instead.") +#define CLUTTER_bott 0x9f6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_bott instead.") +#define CLUTTER_topt 0x9f7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_topt instead.") +#define CLUTTER_vertbar 0x9f8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_vertbar instead.") +#define CLUTTER_emspace 0xaa1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_emspace instead.") +#define CLUTTER_enspace 0xaa2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_enspace instead.") +#define CLUTTER_em3space 0xaa3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_em3space instead.") +#define CLUTTER_em4space 0xaa4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_em4space instead.") +#define CLUTTER_digitspace 0xaa5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_digitspace instead.") +#define CLUTTER_punctspace 0xaa6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_punctspace instead.") +#define CLUTTER_thinspace 0xaa7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_thinspace instead.") +#define CLUTTER_hairspace 0xaa8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hairspace instead.") +#define CLUTTER_emdash 0xaa9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_emdash instead.") +#define CLUTTER_endash 0xaaa CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_endash instead.") +#define CLUTTER_signifblank 0xaac CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_signifblank instead.") +#define CLUTTER_ellipsis 0xaae CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ellipsis instead.") +#define CLUTTER_doubbaselinedot 0xaaf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_doubbaselinedot instead.") +#define CLUTTER_onethird 0xab0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_onethird instead.") +#define CLUTTER_twothirds 0xab1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_twothirds instead.") +#define CLUTTER_onefifth 0xab2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_onefifth instead.") +#define CLUTTER_twofifths 0xab3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_twofifths instead.") +#define CLUTTER_threefifths 0xab4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_threefifths instead.") +#define CLUTTER_fourfifths 0xab5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_fourfifths instead.") +#define CLUTTER_onesixth 0xab6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_onesixth instead.") +#define CLUTTER_fivesixths 0xab7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_fivesixths instead.") +#define CLUTTER_careof 0xab8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_careof instead.") +#define CLUTTER_figdash 0xabb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_figdash instead.") +#define CLUTTER_leftanglebracket 0xabc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_leftanglebracket instead.") +#define CLUTTER_decimalpoint 0xabd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_decimalpoint instead.") +#define CLUTTER_rightanglebracket 0xabe CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_rightanglebracket instead.") +#define CLUTTER_marker 0xabf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_marker instead.") +#define CLUTTER_oneeighth 0xac3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_oneeighth instead.") +#define CLUTTER_threeeighths 0xac4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_threeeighths instead.") +#define CLUTTER_fiveeighths 0xac5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_fiveeighths instead.") +#define CLUTTER_seveneighths 0xac6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_seveneighths instead.") +#define CLUTTER_trademark 0xac9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_trademark instead.") +#define CLUTTER_signaturemark 0xaca CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_signaturemark instead.") +#define CLUTTER_trademarkincircle 0xacb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_trademarkincircle instead.") +#define CLUTTER_leftopentriangle 0xacc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_leftopentriangle instead.") +#define CLUTTER_rightopentriangle 0xacd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_rightopentriangle instead.") +#define CLUTTER_emopencircle 0xace CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_emopencircle instead.") +#define CLUTTER_emopenrectangle 0xacf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_emopenrectangle instead.") +#define CLUTTER_leftsinglequotemark 0xad0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_leftsinglequotemark instead.") +#define CLUTTER_rightsinglequotemark 0xad1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_rightsinglequotemark instead.") +#define CLUTTER_leftdoublequotemark 0xad2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_leftdoublequotemark instead.") +#define CLUTTER_rightdoublequotemark 0xad3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_rightdoublequotemark instead.") +#define CLUTTER_prescription 0xad4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_prescription instead.") +#define CLUTTER_permille 0xad5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_permille instead.") +#define CLUTTER_minutes 0xad6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_minutes instead.") +#define CLUTTER_seconds 0xad7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_seconds instead.") +#define CLUTTER_latincross 0xad9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_latincross instead.") +#define CLUTTER_hexagram 0xada CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hexagram instead.") +#define CLUTTER_filledrectbullet 0xadb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_filledrectbullet instead.") +#define CLUTTER_filledlefttribullet 0xadc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_filledlefttribullet instead.") +#define CLUTTER_filledrighttribullet 0xadd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_filledrighttribullet instead.") +#define CLUTTER_emfilledcircle 0xade CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_emfilledcircle instead.") +#define CLUTTER_emfilledrect 0xadf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_emfilledrect instead.") +#define CLUTTER_enopencircbullet 0xae0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_enopencircbullet instead.") +#define CLUTTER_enopensquarebullet 0xae1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_enopensquarebullet instead.") +#define CLUTTER_openrectbullet 0xae2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_openrectbullet instead.") +#define CLUTTER_opentribulletup 0xae3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_opentribulletup instead.") +#define CLUTTER_opentribulletdown 0xae4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_opentribulletdown instead.") +#define CLUTTER_openstar 0xae5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_openstar instead.") +#define CLUTTER_enfilledcircbullet 0xae6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_enfilledcircbullet instead.") +#define CLUTTER_enfilledsqbullet 0xae7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_enfilledsqbullet instead.") +#define CLUTTER_filledtribulletup 0xae8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_filledtribulletup instead.") +#define CLUTTER_filledtribulletdown 0xae9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_filledtribulletdown instead.") +#define CLUTTER_leftpointer 0xaea CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_leftpointer instead.") +#define CLUTTER_rightpointer 0xaeb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_rightpointer instead.") +#define CLUTTER_club 0xaec CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_club instead.") +#define CLUTTER_diamond 0xaed CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_diamond instead.") +#define CLUTTER_heart 0xaee CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_heart instead.") +#define CLUTTER_maltesecross 0xaf0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_maltesecross instead.") +#define CLUTTER_dagger 0xaf1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dagger instead.") +#define CLUTTER_doubledagger 0xaf2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_doubledagger instead.") +#define CLUTTER_checkmark 0xaf3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_checkmark instead.") +#define CLUTTER_ballotcross 0xaf4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ballotcross instead.") +#define CLUTTER_musicalsharp 0xaf5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_musicalsharp instead.") +#define CLUTTER_musicalflat 0xaf6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_musicalflat instead.") +#define CLUTTER_malesymbol 0xaf7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_malesymbol instead.") +#define CLUTTER_femalesymbol 0xaf8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_femalesymbol instead.") +#define CLUTTER_telephone 0xaf9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_telephone instead.") +#define CLUTTER_telephonerecorder 0xafa CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_telephonerecorder instead.") +#define CLUTTER_phonographcopyright 0xafb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_phonographcopyright instead.") +#define CLUTTER_caret 0xafc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_caret instead.") +#define CLUTTER_singlelowquotemark 0xafd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_singlelowquotemark instead.") +#define CLUTTER_doublelowquotemark 0xafe CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_doublelowquotemark instead.") +#define CLUTTER_cursor 0xaff CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_cursor instead.") +#define CLUTTER_leftcaret 0xba3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_leftcaret instead.") +#define CLUTTER_rightcaret 0xba6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_rightcaret instead.") +#define CLUTTER_downcaret 0xba8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_downcaret instead.") +#define CLUTTER_upcaret 0xba9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_upcaret instead.") +#define CLUTTER_overbar 0xbc0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_overbar instead.") +#define CLUTTER_downtack 0xbc2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_downtack instead.") +#define CLUTTER_upshoe 0xbc3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_upshoe instead.") +#define CLUTTER_downstile 0xbc4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_downstile instead.") +#define CLUTTER_underbar 0xbc6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_underbar instead.") +#define CLUTTER_jot 0xbca CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_jot instead.") +#define CLUTTER_quad 0xbcc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_quad instead.") +#define CLUTTER_uptack 0xbce CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_uptack instead.") +#define CLUTTER_circle 0xbcf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_circle instead.") +#define CLUTTER_upstile 0xbd3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_upstile instead.") +#define CLUTTER_downshoe 0xbd6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_downshoe instead.") +#define CLUTTER_rightshoe 0xbd8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_rightshoe instead.") +#define CLUTTER_leftshoe 0xbda CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_leftshoe instead.") +#define CLUTTER_lefttack 0xbdc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_lefttack instead.") +#define CLUTTER_righttack 0xbfc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_righttack instead.") +#define CLUTTER_hebrew_doublelowline 0xcdf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_doublelowline instead.") +#define CLUTTER_hebrew_aleph 0xce0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_aleph instead.") +#define CLUTTER_hebrew_bet 0xce1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_bet instead.") +#define CLUTTER_hebrew_beth 0xce1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_beth instead.") +#define CLUTTER_hebrew_gimel 0xce2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_gimel instead.") +#define CLUTTER_hebrew_gimmel 0xce2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_gimmel instead.") +#define CLUTTER_hebrew_dalet 0xce3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_dalet instead.") +#define CLUTTER_hebrew_daleth 0xce3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_daleth instead.") +#define CLUTTER_hebrew_he 0xce4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_he instead.") +#define CLUTTER_hebrew_waw 0xce5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_waw instead.") +#define CLUTTER_hebrew_zain 0xce6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_zain instead.") +#define CLUTTER_hebrew_zayin 0xce6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_zayin instead.") +#define CLUTTER_hebrew_chet 0xce7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_chet instead.") +#define CLUTTER_hebrew_het 0xce7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_het instead.") +#define CLUTTER_hebrew_tet 0xce8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_tet instead.") +#define CLUTTER_hebrew_teth 0xce8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_teth instead.") +#define CLUTTER_hebrew_yod 0xce9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_yod instead.") +#define CLUTTER_hebrew_finalkaph 0xcea CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_finalkaph instead.") +#define CLUTTER_hebrew_kaph 0xceb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_kaph instead.") +#define CLUTTER_hebrew_lamed 0xcec CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_lamed instead.") +#define CLUTTER_hebrew_finalmem 0xced CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_finalmem instead.") +#define CLUTTER_hebrew_mem 0xcee CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_mem instead.") +#define CLUTTER_hebrew_finalnun 0xcef CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_finalnun instead.") +#define CLUTTER_hebrew_nun 0xcf0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_nun instead.") +#define CLUTTER_hebrew_samech 0xcf1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_samech instead.") +#define CLUTTER_hebrew_samekh 0xcf1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_samekh instead.") +#define CLUTTER_hebrew_ayin 0xcf2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_ayin instead.") +#define CLUTTER_hebrew_finalpe 0xcf3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_finalpe instead.") +#define CLUTTER_hebrew_pe 0xcf4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_pe instead.") +#define CLUTTER_hebrew_finalzade 0xcf5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_finalzade instead.") +#define CLUTTER_hebrew_finalzadi 0xcf5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_finalzadi instead.") +#define CLUTTER_hebrew_zade 0xcf6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_zade instead.") +#define CLUTTER_hebrew_zadi 0xcf6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_zadi instead.") +#define CLUTTER_hebrew_qoph 0xcf7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_qoph instead.") +#define CLUTTER_hebrew_kuf 0xcf7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_kuf instead.") +#define CLUTTER_hebrew_resh 0xcf8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_resh instead.") +#define CLUTTER_hebrew_shin 0xcf9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_shin instead.") +#define CLUTTER_hebrew_taw 0xcfa CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_taw instead.") +#define CLUTTER_hebrew_taf 0xcfa CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_hebrew_taf instead.") +#define CLUTTER_Hebrew_switch 0xff7e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hebrew_switch instead.") +#define CLUTTER_Thai_kokai 0xda1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_kokai instead.") +#define CLUTTER_Thai_khokhai 0xda2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_khokhai instead.") +#define CLUTTER_Thai_khokhuat 0xda3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_khokhuat instead.") +#define CLUTTER_Thai_khokhwai 0xda4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_khokhwai instead.") +#define CLUTTER_Thai_khokhon 0xda5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_khokhon instead.") +#define CLUTTER_Thai_khorakhang 0xda6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_khorakhang instead.") +#define CLUTTER_Thai_ngongu 0xda7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_ngongu instead.") +#define CLUTTER_Thai_chochan 0xda8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_chochan instead.") +#define CLUTTER_Thai_choching 0xda9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_choching instead.") +#define CLUTTER_Thai_chochang 0xdaa CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_chochang instead.") +#define CLUTTER_Thai_soso 0xdab CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_soso instead.") +#define CLUTTER_Thai_chochoe 0xdac CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_chochoe instead.") +#define CLUTTER_Thai_yoying 0xdad CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_yoying instead.") +#define CLUTTER_Thai_dochada 0xdae CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_dochada instead.") +#define CLUTTER_Thai_topatak 0xdaf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_topatak instead.") +#define CLUTTER_Thai_thothan 0xdb0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_thothan instead.") +#define CLUTTER_Thai_thonangmontho 0xdb1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_thonangmontho instead.") +#define CLUTTER_Thai_thophuthao 0xdb2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_thophuthao instead.") +#define CLUTTER_Thai_nonen 0xdb3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_nonen instead.") +#define CLUTTER_Thai_dodek 0xdb4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_dodek instead.") +#define CLUTTER_Thai_totao 0xdb5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_totao instead.") +#define CLUTTER_Thai_thothung 0xdb6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_thothung instead.") +#define CLUTTER_Thai_thothahan 0xdb7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_thothahan instead.") +#define CLUTTER_Thai_thothong 0xdb8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_thothong instead.") +#define CLUTTER_Thai_nonu 0xdb9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_nonu instead.") +#define CLUTTER_Thai_bobaimai 0xdba CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_bobaimai instead.") +#define CLUTTER_Thai_popla 0xdbb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_popla instead.") +#define CLUTTER_Thai_phophung 0xdbc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_phophung instead.") +#define CLUTTER_Thai_fofa 0xdbd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_fofa instead.") +#define CLUTTER_Thai_phophan 0xdbe CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_phophan instead.") +#define CLUTTER_Thai_fofan 0xdbf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_fofan instead.") +#define CLUTTER_Thai_phosamphao 0xdc0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_phosamphao instead.") +#define CLUTTER_Thai_moma 0xdc1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_moma instead.") +#define CLUTTER_Thai_yoyak 0xdc2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_yoyak instead.") +#define CLUTTER_Thai_rorua 0xdc3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_rorua instead.") +#define CLUTTER_Thai_ru 0xdc4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_ru instead.") +#define CLUTTER_Thai_loling 0xdc5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_loling instead.") +#define CLUTTER_Thai_lu 0xdc6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_lu instead.") +#define CLUTTER_Thai_wowaen 0xdc7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_wowaen instead.") +#define CLUTTER_Thai_sosala 0xdc8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_sosala instead.") +#define CLUTTER_Thai_sorusi 0xdc9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_sorusi instead.") +#define CLUTTER_Thai_sosua 0xdca CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_sosua instead.") +#define CLUTTER_Thai_hohip 0xdcb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_hohip instead.") +#define CLUTTER_Thai_lochula 0xdcc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_lochula instead.") +#define CLUTTER_Thai_oang 0xdcd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_oang instead.") +#define CLUTTER_Thai_honokhuk 0xdce CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_honokhuk instead.") +#define CLUTTER_Thai_paiyannoi 0xdcf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_paiyannoi instead.") +#define CLUTTER_Thai_saraa 0xdd0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_saraa instead.") +#define CLUTTER_Thai_maihanakat 0xdd1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_maihanakat instead.") +#define CLUTTER_Thai_saraaa 0xdd2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_saraaa instead.") +#define CLUTTER_Thai_saraam 0xdd3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_saraam instead.") +#define CLUTTER_Thai_sarai 0xdd4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_sarai instead.") +#define CLUTTER_Thai_saraii 0xdd5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_saraii instead.") +#define CLUTTER_Thai_saraue 0xdd6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_saraue instead.") +#define CLUTTER_Thai_sarauee 0xdd7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_sarauee instead.") +#define CLUTTER_Thai_sarau 0xdd8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_sarau instead.") +#define CLUTTER_Thai_sarauu 0xdd9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_sarauu instead.") +#define CLUTTER_Thai_phinthu 0xdda CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_phinthu instead.") +#define CLUTTER_Thai_maihanakat_maitho 0xdde CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_maihanakat_maitho instead.") +#define CLUTTER_Thai_baht 0xddf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_baht instead.") +#define CLUTTER_Thai_sarae 0xde0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_sarae instead.") +#define CLUTTER_Thai_saraae 0xde1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_saraae instead.") +#define CLUTTER_Thai_sarao 0xde2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_sarao instead.") +#define CLUTTER_Thai_saraaimaimuan 0xde3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_saraaimaimuan instead.") +#define CLUTTER_Thai_saraaimaimalai 0xde4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_saraaimaimalai instead.") +#define CLUTTER_Thai_lakkhangyao 0xde5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_lakkhangyao instead.") +#define CLUTTER_Thai_maiyamok 0xde6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_maiyamok instead.") +#define CLUTTER_Thai_maitaikhu 0xde7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_maitaikhu instead.") +#define CLUTTER_Thai_maiek 0xde8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_maiek instead.") +#define CLUTTER_Thai_maitho 0xde9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_maitho instead.") +#define CLUTTER_Thai_maitri 0xdea CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_maitri instead.") +#define CLUTTER_Thai_maichattawa 0xdeb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_maichattawa instead.") +#define CLUTTER_Thai_thanthakhat 0xdec CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_thanthakhat instead.") +#define CLUTTER_Thai_nikhahit 0xded CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_nikhahit instead.") +#define CLUTTER_Thai_leksun 0xdf0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_leksun instead.") +#define CLUTTER_Thai_leknung 0xdf1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_leknung instead.") +#define CLUTTER_Thai_leksong 0xdf2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_leksong instead.") +#define CLUTTER_Thai_leksam 0xdf3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_leksam instead.") +#define CLUTTER_Thai_leksi 0xdf4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_leksi instead.") +#define CLUTTER_Thai_lekha 0xdf5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_lekha instead.") +#define CLUTTER_Thai_lekhok 0xdf6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_lekhok instead.") +#define CLUTTER_Thai_lekchet 0xdf7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_lekchet instead.") +#define CLUTTER_Thai_lekpaet 0xdf8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_lekpaet instead.") +#define CLUTTER_Thai_lekkao 0xdf9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Thai_lekkao instead.") +#define CLUTTER_Hangul 0xff31 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul instead.") +#define CLUTTER_Hangul_Start 0xff32 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_Start instead.") +#define CLUTTER_Hangul_End 0xff33 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_End instead.") +#define CLUTTER_Hangul_Hanja 0xff34 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_Hanja instead.") +#define CLUTTER_Hangul_Jamo 0xff35 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_Jamo instead.") +#define CLUTTER_Hangul_Romaja 0xff36 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_Romaja instead.") +#define CLUTTER_Hangul_Codeinput 0xff37 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_Codeinput instead.") +#define CLUTTER_Hangul_Jeonja 0xff38 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_Jeonja instead.") +#define CLUTTER_Hangul_Banja 0xff39 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_Banja instead.") +#define CLUTTER_Hangul_PreHanja 0xff3a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_PreHanja instead.") +#define CLUTTER_Hangul_PostHanja 0xff3b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_PostHanja instead.") +#define CLUTTER_Hangul_SingleCandidate 0xff3c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_SingleCandidate instead.") +#define CLUTTER_Hangul_MultipleCandidate 0xff3d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_MultipleCandidate instead.") +#define CLUTTER_Hangul_PreviousCandidate 0xff3e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_PreviousCandidate instead.") +#define CLUTTER_Hangul_Special 0xff3f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_Special instead.") +#define CLUTTER_Hangul_switch 0xff7e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_switch instead.") +#define CLUTTER_Hangul_Kiyeog 0xea1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_Kiyeog instead.") +#define CLUTTER_Hangul_SsangKiyeog 0xea2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_SsangKiyeog instead.") +#define CLUTTER_Hangul_KiyeogSios 0xea3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_KiyeogSios instead.") +#define CLUTTER_Hangul_Nieun 0xea4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_Nieun instead.") +#define CLUTTER_Hangul_NieunJieuj 0xea5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_NieunJieuj instead.") +#define CLUTTER_Hangul_NieunHieuh 0xea6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_NieunHieuh instead.") +#define CLUTTER_Hangul_Dikeud 0xea7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_Dikeud instead.") +#define CLUTTER_Hangul_SsangDikeud 0xea8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_SsangDikeud instead.") +#define CLUTTER_Hangul_Rieul 0xea9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_Rieul instead.") +#define CLUTTER_Hangul_RieulKiyeog 0xeaa CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_RieulKiyeog instead.") +#define CLUTTER_Hangul_RieulMieum 0xeab CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_RieulMieum instead.") +#define CLUTTER_Hangul_RieulPieub 0xeac CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_RieulPieub instead.") +#define CLUTTER_Hangul_RieulSios 0xead CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_RieulSios instead.") +#define CLUTTER_Hangul_RieulTieut 0xeae CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_RieulTieut instead.") +#define CLUTTER_Hangul_RieulPhieuf 0xeaf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_RieulPhieuf instead.") +#define CLUTTER_Hangul_RieulHieuh 0xeb0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_RieulHieuh instead.") +#define CLUTTER_Hangul_Mieum 0xeb1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_Mieum instead.") +#define CLUTTER_Hangul_Pieub 0xeb2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_Pieub instead.") +#define CLUTTER_Hangul_SsangPieub 0xeb3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_SsangPieub instead.") +#define CLUTTER_Hangul_PieubSios 0xeb4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_PieubSios instead.") +#define CLUTTER_Hangul_Sios 0xeb5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_Sios instead.") +#define CLUTTER_Hangul_SsangSios 0xeb6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_SsangSios instead.") +#define CLUTTER_Hangul_Ieung 0xeb7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_Ieung instead.") +#define CLUTTER_Hangul_Jieuj 0xeb8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_Jieuj instead.") +#define CLUTTER_Hangul_SsangJieuj 0xeb9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_SsangJieuj instead.") +#define CLUTTER_Hangul_Cieuc 0xeba CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_Cieuc instead.") +#define CLUTTER_Hangul_Khieuq 0xebb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_Khieuq instead.") +#define CLUTTER_Hangul_Tieut 0xebc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_Tieut instead.") +#define CLUTTER_Hangul_Phieuf 0xebd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_Phieuf instead.") +#define CLUTTER_Hangul_Hieuh 0xebe CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_Hieuh instead.") +#define CLUTTER_Hangul_A 0xebf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_A instead.") +#define CLUTTER_Hangul_AE 0xec0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_AE instead.") +#define CLUTTER_Hangul_YA 0xec1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_YA instead.") +#define CLUTTER_Hangul_YAE 0xec2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_YAE instead.") +#define CLUTTER_Hangul_EO 0xec3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_EO instead.") +#define CLUTTER_Hangul_E 0xec4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_E instead.") +#define CLUTTER_Hangul_YEO 0xec5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_YEO instead.") +#define CLUTTER_Hangul_YE 0xec6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_YE instead.") +#define CLUTTER_Hangul_O 0xec7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_O instead.") +#define CLUTTER_Hangul_WA 0xec8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_WA instead.") +#define CLUTTER_Hangul_WAE 0xec9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_WAE instead.") +#define CLUTTER_Hangul_OE 0xeca CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_OE instead.") +#define CLUTTER_Hangul_YO 0xecb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_YO instead.") +#define CLUTTER_Hangul_U 0xecc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_U instead.") +#define CLUTTER_Hangul_WEO 0xecd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_WEO instead.") +#define CLUTTER_Hangul_WE 0xece CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_WE instead.") +#define CLUTTER_Hangul_WI 0xecf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_WI instead.") +#define CLUTTER_Hangul_YU 0xed0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_YU instead.") +#define CLUTTER_Hangul_EU 0xed1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_EU instead.") +#define CLUTTER_Hangul_YI 0xed2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_YI instead.") +#define CLUTTER_Hangul_I 0xed3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_I instead.") +#define CLUTTER_Hangul_J_Kiyeog 0xed4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_Kiyeog instead.") +#define CLUTTER_Hangul_J_SsangKiyeog 0xed5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_SsangKiyeog instead.") +#define CLUTTER_Hangul_J_KiyeogSios 0xed6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_KiyeogSios instead.") +#define CLUTTER_Hangul_J_Nieun 0xed7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_Nieun instead.") +#define CLUTTER_Hangul_J_NieunJieuj 0xed8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_NieunJieuj instead.") +#define CLUTTER_Hangul_J_NieunHieuh 0xed9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_NieunHieuh instead.") +#define CLUTTER_Hangul_J_Dikeud 0xeda CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_Dikeud instead.") +#define CLUTTER_Hangul_J_Rieul 0xedb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_Rieul instead.") +#define CLUTTER_Hangul_J_RieulKiyeog 0xedc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_RieulKiyeog instead.") +#define CLUTTER_Hangul_J_RieulMieum 0xedd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_RieulMieum instead.") +#define CLUTTER_Hangul_J_RieulPieub 0xede CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_RieulPieub instead.") +#define CLUTTER_Hangul_J_RieulSios 0xedf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_RieulSios instead.") +#define CLUTTER_Hangul_J_RieulTieut 0xee0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_RieulTieut instead.") +#define CLUTTER_Hangul_J_RieulPhieuf 0xee1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_RieulPhieuf instead.") +#define CLUTTER_Hangul_J_RieulHieuh 0xee2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_RieulHieuh instead.") +#define CLUTTER_Hangul_J_Mieum 0xee3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_Mieum instead.") +#define CLUTTER_Hangul_J_Pieub 0xee4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_Pieub instead.") +#define CLUTTER_Hangul_J_PieubSios 0xee5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_PieubSios instead.") +#define CLUTTER_Hangul_J_Sios 0xee6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_Sios instead.") +#define CLUTTER_Hangul_J_SsangSios 0xee7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_SsangSios instead.") +#define CLUTTER_Hangul_J_Ieung 0xee8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_Ieung instead.") +#define CLUTTER_Hangul_J_Jieuj 0xee9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_Jieuj instead.") +#define CLUTTER_Hangul_J_Cieuc 0xeea CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_Cieuc instead.") +#define CLUTTER_Hangul_J_Khieuq 0xeeb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_Khieuq instead.") +#define CLUTTER_Hangul_J_Tieut 0xeec CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_Tieut instead.") +#define CLUTTER_Hangul_J_Phieuf 0xeed CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_Phieuf instead.") +#define CLUTTER_Hangul_J_Hieuh 0xeee CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_Hieuh instead.") +#define CLUTTER_Hangul_RieulYeorinHieuh 0xeef CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_RieulYeorinHieuh instead.") +#define CLUTTER_Hangul_SunkyeongeumMieum 0xef0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_SunkyeongeumMieum instead.") +#define CLUTTER_Hangul_SunkyeongeumPieub 0xef1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_SunkyeongeumPieub instead.") +#define CLUTTER_Hangul_PanSios 0xef2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_PanSios instead.") +#define CLUTTER_Hangul_KkogjiDalrinIeung 0xef3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_KkogjiDalrinIeung instead.") +#define CLUTTER_Hangul_SunkyeongeumPhieuf 0xef4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_SunkyeongeumPhieuf instead.") +#define CLUTTER_Hangul_YeorinHieuh 0xef5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_YeorinHieuh instead.") +#define CLUTTER_Hangul_AraeA 0xef6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_AraeA instead.") +#define CLUTTER_Hangul_AraeAE 0xef7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_AraeAE instead.") +#define CLUTTER_Hangul_J_PanSios 0xef8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_PanSios instead.") +#define CLUTTER_Hangul_J_KkogjiDalrinIeung 0xef9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_KkogjiDalrinIeung instead.") +#define CLUTTER_Hangul_J_YeorinHieuh 0xefa CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Hangul_J_YeorinHieuh instead.") +#define CLUTTER_Korean_Won 0xeff CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Korean_Won instead.") +#define CLUTTER_Armenian_ligature_ew 0x1000587 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_ligature_ew instead.") +#define CLUTTER_Armenian_full_stop 0x1000589 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_full_stop instead.") +#define CLUTTER_Armenian_verjaket 0x1000589 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_verjaket instead.") +#define CLUTTER_Armenian_separation_mark 0x100055d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_separation_mark instead.") +#define CLUTTER_Armenian_but 0x100055d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_but instead.") +#define CLUTTER_Armenian_hyphen 0x100058a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_hyphen instead.") +#define CLUTTER_Armenian_yentamna 0x100058a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_yentamna instead.") +#define CLUTTER_Armenian_exclam 0x100055c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_exclam instead.") +#define CLUTTER_Armenian_amanak 0x100055c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_amanak instead.") +#define CLUTTER_Armenian_accent 0x100055b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_accent instead.") +#define CLUTTER_Armenian_shesht 0x100055b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_shesht instead.") +#define CLUTTER_Armenian_question 0x100055e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_question instead.") +#define CLUTTER_Armenian_paruyk 0x100055e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_paruyk instead.") +#define CLUTTER_Armenian_AYB 0x1000531 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_AYB instead.") +#define CLUTTER_Armenian_ayb 0x1000561 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_ayb instead.") +#define CLUTTER_Armenian_BEN 0x1000532 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_BEN instead.") +#define CLUTTER_Armenian_ben 0x1000562 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_ben instead.") +#define CLUTTER_Armenian_GIM 0x1000533 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_GIM instead.") +#define CLUTTER_Armenian_gim 0x1000563 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_gim instead.") +#define CLUTTER_Armenian_DA 0x1000534 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_DA instead.") +#define CLUTTER_Armenian_da 0x1000564 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_da instead.") +#define CLUTTER_Armenian_YECH 0x1000535 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_YECH instead.") +#define CLUTTER_Armenian_yech 0x1000565 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_yech instead.") +#define CLUTTER_Armenian_ZA 0x1000536 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_ZA instead.") +#define CLUTTER_Armenian_za 0x1000566 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_za instead.") +#define CLUTTER_Armenian_E 0x1000537 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_E instead.") +#define CLUTTER_Armenian_e 0x1000567 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_e instead.") +#define CLUTTER_Armenian_AT 0x1000538 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_AT instead.") +#define CLUTTER_Armenian_at 0x1000568 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_at instead.") +#define CLUTTER_Armenian_TO 0x1000539 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_TO instead.") +#define CLUTTER_Armenian_to 0x1000569 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_to instead.") +#define CLUTTER_Armenian_ZHE 0x100053a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_ZHE instead.") +#define CLUTTER_Armenian_zhe 0x100056a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_zhe instead.") +#define CLUTTER_Armenian_INI 0x100053b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_INI instead.") +#define CLUTTER_Armenian_ini 0x100056b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_ini instead.") +#define CLUTTER_Armenian_LYUN 0x100053c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_LYUN instead.") +#define CLUTTER_Armenian_lyun 0x100056c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_lyun instead.") +#define CLUTTER_Armenian_KHE 0x100053d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_KHE instead.") +#define CLUTTER_Armenian_khe 0x100056d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_khe instead.") +#define CLUTTER_Armenian_TSA 0x100053e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_TSA instead.") +#define CLUTTER_Armenian_tsa 0x100056e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_tsa instead.") +#define CLUTTER_Armenian_KEN 0x100053f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_KEN instead.") +#define CLUTTER_Armenian_ken 0x100056f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_ken instead.") +#define CLUTTER_Armenian_HO 0x1000540 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_HO instead.") +#define CLUTTER_Armenian_ho 0x1000570 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_ho instead.") +#define CLUTTER_Armenian_DZA 0x1000541 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_DZA instead.") +#define CLUTTER_Armenian_dza 0x1000571 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_dza instead.") +#define CLUTTER_Armenian_GHAT 0x1000542 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_GHAT instead.") +#define CLUTTER_Armenian_ghat 0x1000572 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_ghat instead.") +#define CLUTTER_Armenian_TCHE 0x1000543 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_TCHE instead.") +#define CLUTTER_Armenian_tche 0x1000573 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_tche instead.") +#define CLUTTER_Armenian_MEN 0x1000544 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_MEN instead.") +#define CLUTTER_Armenian_men 0x1000574 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_men instead.") +#define CLUTTER_Armenian_HI 0x1000545 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_HI instead.") +#define CLUTTER_Armenian_hi 0x1000575 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_hi instead.") +#define CLUTTER_Armenian_NU 0x1000546 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_NU instead.") +#define CLUTTER_Armenian_nu 0x1000576 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_nu instead.") +#define CLUTTER_Armenian_SHA 0x1000547 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_SHA instead.") +#define CLUTTER_Armenian_sha 0x1000577 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_sha instead.") +#define CLUTTER_Armenian_VO 0x1000548 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_VO instead.") +#define CLUTTER_Armenian_vo 0x1000578 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_vo instead.") +#define CLUTTER_Armenian_CHA 0x1000549 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_CHA instead.") +#define CLUTTER_Armenian_cha 0x1000579 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_cha instead.") +#define CLUTTER_Armenian_PE 0x100054a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_PE instead.") +#define CLUTTER_Armenian_pe 0x100057a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_pe instead.") +#define CLUTTER_Armenian_JE 0x100054b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_JE instead.") +#define CLUTTER_Armenian_je 0x100057b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_je instead.") +#define CLUTTER_Armenian_RA 0x100054c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_RA instead.") +#define CLUTTER_Armenian_ra 0x100057c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_ra instead.") +#define CLUTTER_Armenian_SE 0x100054d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_SE instead.") +#define CLUTTER_Armenian_se 0x100057d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_se instead.") +#define CLUTTER_Armenian_VEV 0x100054e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_VEV instead.") +#define CLUTTER_Armenian_vev 0x100057e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_vev instead.") +#define CLUTTER_Armenian_TYUN 0x100054f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_TYUN instead.") +#define CLUTTER_Armenian_tyun 0x100057f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_tyun instead.") +#define CLUTTER_Armenian_RE 0x1000550 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_RE instead.") +#define CLUTTER_Armenian_re 0x1000580 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_re instead.") +#define CLUTTER_Armenian_TSO 0x1000551 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_TSO instead.") +#define CLUTTER_Armenian_tso 0x1000581 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_tso instead.") +#define CLUTTER_Armenian_VYUN 0x1000552 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_VYUN instead.") +#define CLUTTER_Armenian_vyun 0x1000582 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_vyun instead.") +#define CLUTTER_Armenian_PYUR 0x1000553 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_PYUR instead.") +#define CLUTTER_Armenian_pyur 0x1000583 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_pyur instead.") +#define CLUTTER_Armenian_KE 0x1000554 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_KE instead.") +#define CLUTTER_Armenian_ke 0x1000584 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_ke instead.") +#define CLUTTER_Armenian_O 0x1000555 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_O instead.") +#define CLUTTER_Armenian_o 0x1000585 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_o instead.") +#define CLUTTER_Armenian_FE 0x1000556 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_FE instead.") +#define CLUTTER_Armenian_fe 0x1000586 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_fe instead.") +#define CLUTTER_Armenian_apostrophe 0x100055a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Armenian_apostrophe instead.") +#define CLUTTER_Georgian_an 0x10010d0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_an instead.") +#define CLUTTER_Georgian_ban 0x10010d1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_ban instead.") +#define CLUTTER_Georgian_gan 0x10010d2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_gan instead.") +#define CLUTTER_Georgian_don 0x10010d3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_don instead.") +#define CLUTTER_Georgian_en 0x10010d4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_en instead.") +#define CLUTTER_Georgian_vin 0x10010d5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_vin instead.") +#define CLUTTER_Georgian_zen 0x10010d6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_zen instead.") +#define CLUTTER_Georgian_tan 0x10010d7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_tan instead.") +#define CLUTTER_Georgian_in 0x10010d8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_in instead.") +#define CLUTTER_Georgian_kan 0x10010d9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_kan instead.") +#define CLUTTER_Georgian_las 0x10010da CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_las instead.") +#define CLUTTER_Georgian_man 0x10010db CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_man instead.") +#define CLUTTER_Georgian_nar 0x10010dc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_nar instead.") +#define CLUTTER_Georgian_on 0x10010dd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_on instead.") +#define CLUTTER_Georgian_par 0x10010de CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_par instead.") +#define CLUTTER_Georgian_zhar 0x10010df CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_zhar instead.") +#define CLUTTER_Georgian_rae 0x10010e0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_rae instead.") +#define CLUTTER_Georgian_san 0x10010e1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_san instead.") +#define CLUTTER_Georgian_tar 0x10010e2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_tar instead.") +#define CLUTTER_Georgian_un 0x10010e3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_un instead.") +#define CLUTTER_Georgian_phar 0x10010e4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_phar instead.") +#define CLUTTER_Georgian_khar 0x10010e5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_khar instead.") +#define CLUTTER_Georgian_ghan 0x10010e6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_ghan instead.") +#define CLUTTER_Georgian_qar 0x10010e7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_qar instead.") +#define CLUTTER_Georgian_shin 0x10010e8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_shin instead.") +#define CLUTTER_Georgian_chin 0x10010e9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_chin instead.") +#define CLUTTER_Georgian_can 0x10010ea CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_can instead.") +#define CLUTTER_Georgian_jil 0x10010eb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_jil instead.") +#define CLUTTER_Georgian_cil 0x10010ec CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_cil instead.") +#define CLUTTER_Georgian_char 0x10010ed CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_char instead.") +#define CLUTTER_Georgian_xan 0x10010ee CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_xan instead.") +#define CLUTTER_Georgian_jhan 0x10010ef CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_jhan instead.") +#define CLUTTER_Georgian_hae 0x10010f0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_hae instead.") +#define CLUTTER_Georgian_he 0x10010f1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_he instead.") +#define CLUTTER_Georgian_hie 0x10010f2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_hie instead.") +#define CLUTTER_Georgian_we 0x10010f3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_we instead.") +#define CLUTTER_Georgian_har 0x10010f4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_har instead.") +#define CLUTTER_Georgian_hoe 0x10010f5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_hoe instead.") +#define CLUTTER_Georgian_fi 0x10010f6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Georgian_fi instead.") +#define CLUTTER_Xabovedot 0x1001e8a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Xabovedot instead.") +#define CLUTTER_Ibreve 0x100012c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ibreve instead.") +#define CLUTTER_Zstroke 0x10001b5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Zstroke instead.") +#define CLUTTER_Gcaron 0x10001e6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Gcaron instead.") +#define CLUTTER_Ocaron 0x10001d1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ocaron instead.") +#define CLUTTER_Obarred 0x100019f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Obarred instead.") +#define CLUTTER_xabovedot 0x1001e8b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_xabovedot instead.") +#define CLUTTER_ibreve 0x100012d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ibreve instead.") +#define CLUTTER_zstroke 0x10001b6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_zstroke instead.") +#define CLUTTER_gcaron 0x10001e7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_gcaron instead.") +#define CLUTTER_ocaron 0x10001d2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ocaron instead.") +#define CLUTTER_obarred 0x1000275 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_obarred instead.") +#define CLUTTER_SCHWA 0x100018f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_SCHWA instead.") +#define CLUTTER_schwa 0x1000259 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_schwa instead.") +#define CLUTTER_EZH 0x10001b7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_EZH instead.") +#define CLUTTER_ezh 0x1000292 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ezh instead.") +#define CLUTTER_Lbelowdot 0x1001e36 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Lbelowdot instead.") +#define CLUTTER_lbelowdot 0x1001e37 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_lbelowdot instead.") +#define CLUTTER_Abelowdot 0x1001ea0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Abelowdot instead.") +#define CLUTTER_abelowdot 0x1001ea1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_abelowdot instead.") +#define CLUTTER_Ahook 0x1001ea2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ahook instead.") +#define CLUTTER_ahook 0x1001ea3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ahook instead.") +#define CLUTTER_Acircumflexacute 0x1001ea4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Acircumflexacute instead.") +#define CLUTTER_acircumflexacute 0x1001ea5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_acircumflexacute instead.") +#define CLUTTER_Acircumflexgrave 0x1001ea6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Acircumflexgrave instead.") +#define CLUTTER_acircumflexgrave 0x1001ea7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_acircumflexgrave instead.") +#define CLUTTER_Acircumflexhook 0x1001ea8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Acircumflexhook instead.") +#define CLUTTER_acircumflexhook 0x1001ea9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_acircumflexhook instead.") +#define CLUTTER_Acircumflextilde 0x1001eaa CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Acircumflextilde instead.") +#define CLUTTER_acircumflextilde 0x1001eab CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_acircumflextilde instead.") +#define CLUTTER_Acircumflexbelowdot 0x1001eac CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Acircumflexbelowdot instead.") +#define CLUTTER_acircumflexbelowdot 0x1001ead CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_acircumflexbelowdot instead.") +#define CLUTTER_Abreveacute 0x1001eae CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Abreveacute instead.") +#define CLUTTER_abreveacute 0x1001eaf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_abreveacute instead.") +#define CLUTTER_Abrevegrave 0x1001eb0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Abrevegrave instead.") +#define CLUTTER_abrevegrave 0x1001eb1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_abrevegrave instead.") +#define CLUTTER_Abrevehook 0x1001eb2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Abrevehook instead.") +#define CLUTTER_abrevehook 0x1001eb3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_abrevehook instead.") +#define CLUTTER_Abrevetilde 0x1001eb4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Abrevetilde instead.") +#define CLUTTER_abrevetilde 0x1001eb5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_abrevetilde instead.") +#define CLUTTER_Abrevebelowdot 0x1001eb6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Abrevebelowdot instead.") +#define CLUTTER_abrevebelowdot 0x1001eb7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_abrevebelowdot instead.") +#define CLUTTER_Ebelowdot 0x1001eb8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ebelowdot instead.") +#define CLUTTER_ebelowdot 0x1001eb9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ebelowdot instead.") +#define CLUTTER_Ehook 0x1001eba CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ehook instead.") +#define CLUTTER_ehook 0x1001ebb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ehook instead.") +#define CLUTTER_Etilde 0x1001ebc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Etilde instead.") +#define CLUTTER_etilde 0x1001ebd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_etilde instead.") +#define CLUTTER_Ecircumflexacute 0x1001ebe CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ecircumflexacute instead.") +#define CLUTTER_ecircumflexacute 0x1001ebf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ecircumflexacute instead.") +#define CLUTTER_Ecircumflexgrave 0x1001ec0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ecircumflexgrave instead.") +#define CLUTTER_ecircumflexgrave 0x1001ec1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ecircumflexgrave instead.") +#define CLUTTER_Ecircumflexhook 0x1001ec2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ecircumflexhook instead.") +#define CLUTTER_ecircumflexhook 0x1001ec3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ecircumflexhook instead.") +#define CLUTTER_Ecircumflextilde 0x1001ec4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ecircumflextilde instead.") +#define CLUTTER_ecircumflextilde 0x1001ec5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ecircumflextilde instead.") +#define CLUTTER_Ecircumflexbelowdot 0x1001ec6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ecircumflexbelowdot instead.") +#define CLUTTER_ecircumflexbelowdot 0x1001ec7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ecircumflexbelowdot instead.") +#define CLUTTER_Ihook 0x1001ec8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ihook instead.") +#define CLUTTER_ihook 0x1001ec9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ihook instead.") +#define CLUTTER_Ibelowdot 0x1001eca CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ibelowdot instead.") +#define CLUTTER_ibelowdot 0x1001ecb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ibelowdot instead.") +#define CLUTTER_Obelowdot 0x1001ecc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Obelowdot instead.") +#define CLUTTER_obelowdot 0x1001ecd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_obelowdot instead.") +#define CLUTTER_Ohook 0x1001ece CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ohook instead.") +#define CLUTTER_ohook 0x1001ecf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ohook instead.") +#define CLUTTER_Ocircumflexacute 0x1001ed0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ocircumflexacute instead.") +#define CLUTTER_ocircumflexacute 0x1001ed1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ocircumflexacute instead.") +#define CLUTTER_Ocircumflexgrave 0x1001ed2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ocircumflexgrave instead.") +#define CLUTTER_ocircumflexgrave 0x1001ed3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ocircumflexgrave instead.") +#define CLUTTER_Ocircumflexhook 0x1001ed4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ocircumflexhook instead.") +#define CLUTTER_ocircumflexhook 0x1001ed5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ocircumflexhook instead.") +#define CLUTTER_Ocircumflextilde 0x1001ed6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ocircumflextilde instead.") +#define CLUTTER_ocircumflextilde 0x1001ed7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ocircumflextilde instead.") +#define CLUTTER_Ocircumflexbelowdot 0x1001ed8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ocircumflexbelowdot instead.") +#define CLUTTER_ocircumflexbelowdot 0x1001ed9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ocircumflexbelowdot instead.") +#define CLUTTER_Ohornacute 0x1001eda CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ohornacute instead.") +#define CLUTTER_ohornacute 0x1001edb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ohornacute instead.") +#define CLUTTER_Ohorngrave 0x1001edc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ohorngrave instead.") +#define CLUTTER_ohorngrave 0x1001edd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ohorngrave instead.") +#define CLUTTER_Ohornhook 0x1001ede CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ohornhook instead.") +#define CLUTTER_ohornhook 0x1001edf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ohornhook instead.") +#define CLUTTER_Ohorntilde 0x1001ee0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ohorntilde instead.") +#define CLUTTER_ohorntilde 0x1001ee1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ohorntilde instead.") +#define CLUTTER_Ohornbelowdot 0x1001ee2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ohornbelowdot instead.") +#define CLUTTER_ohornbelowdot 0x1001ee3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ohornbelowdot instead.") +#define CLUTTER_Ubelowdot 0x1001ee4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ubelowdot instead.") +#define CLUTTER_ubelowdot 0x1001ee5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ubelowdot instead.") +#define CLUTTER_Uhook 0x1001ee6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Uhook instead.") +#define CLUTTER_uhook 0x1001ee7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_uhook instead.") +#define CLUTTER_Uhornacute 0x1001ee8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Uhornacute instead.") +#define CLUTTER_uhornacute 0x1001ee9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_uhornacute instead.") +#define CLUTTER_Uhorngrave 0x1001eea CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Uhorngrave instead.") +#define CLUTTER_uhorngrave 0x1001eeb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_uhorngrave instead.") +#define CLUTTER_Uhornhook 0x1001eec CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Uhornhook instead.") +#define CLUTTER_uhornhook 0x1001eed CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_uhornhook instead.") +#define CLUTTER_Uhorntilde 0x1001eee CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Uhorntilde instead.") +#define CLUTTER_uhorntilde 0x1001eef CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_uhorntilde instead.") +#define CLUTTER_Uhornbelowdot 0x1001ef0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Uhornbelowdot instead.") +#define CLUTTER_uhornbelowdot 0x1001ef1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_uhornbelowdot instead.") +#define CLUTTER_Ybelowdot 0x1001ef4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ybelowdot instead.") +#define CLUTTER_ybelowdot 0x1001ef5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ybelowdot instead.") +#define CLUTTER_Yhook 0x1001ef6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Yhook instead.") +#define CLUTTER_yhook 0x1001ef7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_yhook instead.") +#define CLUTTER_Ytilde 0x1001ef8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ytilde instead.") +#define CLUTTER_ytilde 0x1001ef9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ytilde instead.") +#define CLUTTER_Ohorn 0x10001a0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Ohorn instead.") +#define CLUTTER_ohorn 0x10001a1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ohorn instead.") +#define CLUTTER_Uhorn 0x10001af CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Uhorn instead.") +#define CLUTTER_uhorn 0x10001b0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_uhorn instead.") +#define CLUTTER_EcuSign 0x10020a0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_EcuSign instead.") +#define CLUTTER_ColonSign 0x10020a1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ColonSign instead.") +#define CLUTTER_CruzeiroSign 0x10020a2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_CruzeiroSign instead.") +#define CLUTTER_FFrancSign 0x10020a3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_FFrancSign instead.") +#define CLUTTER_LiraSign 0x10020a4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_LiraSign instead.") +#define CLUTTER_MillSign 0x10020a5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_MillSign instead.") +#define CLUTTER_NairaSign 0x10020a6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_NairaSign instead.") +#define CLUTTER_PesetaSign 0x10020a7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_PesetaSign instead.") +#define CLUTTER_RupeeSign 0x10020a8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_RupeeSign instead.") +#define CLUTTER_WonSign 0x10020a9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_WonSign instead.") +#define CLUTTER_NewSheqelSign 0x10020aa CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_NewSheqelSign instead.") +#define CLUTTER_DongSign 0x10020ab CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_DongSign instead.") +#define CLUTTER_EuroSign 0x20ac CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_EuroSign instead.") +#define CLUTTER_zerosuperior 0x1002070 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_zerosuperior instead.") +#define CLUTTER_foursuperior 0x1002074 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_foursuperior instead.") +#define CLUTTER_fivesuperior 0x1002075 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_fivesuperior instead.") +#define CLUTTER_sixsuperior 0x1002076 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_sixsuperior instead.") +#define CLUTTER_sevensuperior 0x1002077 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_sevensuperior instead.") +#define CLUTTER_eightsuperior 0x1002078 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_eightsuperior instead.") +#define CLUTTER_ninesuperior 0x1002079 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ninesuperior instead.") +#define CLUTTER_zerosubscript 0x1002080 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_zerosubscript instead.") +#define CLUTTER_onesubscript 0x1002081 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_onesubscript instead.") +#define CLUTTER_twosubscript 0x1002082 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_twosubscript instead.") +#define CLUTTER_threesubscript 0x1002083 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_threesubscript instead.") +#define CLUTTER_foursubscript 0x1002084 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_foursubscript instead.") +#define CLUTTER_fivesubscript 0x1002085 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_fivesubscript instead.") +#define CLUTTER_sixsubscript 0x1002086 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_sixsubscript instead.") +#define CLUTTER_sevensubscript 0x1002087 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_sevensubscript instead.") +#define CLUTTER_eightsubscript 0x1002088 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_eightsubscript instead.") +#define CLUTTER_ninesubscript 0x1002089 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_ninesubscript instead.") +#define CLUTTER_partdifferential 0x1002202 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_partdifferential instead.") +#define CLUTTER_emptyset 0x1002205 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_emptyset instead.") +#define CLUTTER_elementof 0x1002208 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_elementof instead.") +#define CLUTTER_notelementof 0x1002209 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_notelementof instead.") +#define CLUTTER_containsas 0x100220b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_containsas instead.") +#define CLUTTER_squareroot 0x100221a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_squareroot instead.") +#define CLUTTER_cuberoot 0x100221b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_cuberoot instead.") +#define CLUTTER_fourthroot 0x100221c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_fourthroot instead.") +#define CLUTTER_dintegral 0x100222c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_dintegral instead.") +#define CLUTTER_tintegral 0x100222d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_tintegral instead.") +#define CLUTTER_because 0x1002235 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_because instead.") +#define CLUTTER_approxeq 0x1002248 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_approxeq instead.") +#define CLUTTER_notapproxeq 0x1002247 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_notapproxeq instead.") +#define CLUTTER_notidentical 0x1002262 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_notidentical instead.") +#define CLUTTER_stricteq 0x1002263 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_stricteq instead.") +#define CLUTTER_braille_dot_1 0xfff1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dot_1 instead.") +#define CLUTTER_braille_dot_2 0xfff2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dot_2 instead.") +#define CLUTTER_braille_dot_3 0xfff3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dot_3 instead.") +#define CLUTTER_braille_dot_4 0xfff4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dot_4 instead.") +#define CLUTTER_braille_dot_5 0xfff5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dot_5 instead.") +#define CLUTTER_braille_dot_6 0xfff6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dot_6 instead.") +#define CLUTTER_braille_dot_7 0xfff7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dot_7 instead.") +#define CLUTTER_braille_dot_8 0xfff8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dot_8 instead.") +#define CLUTTER_braille_dot_9 0xfff9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dot_9 instead.") +#define CLUTTER_braille_dot_10 0xfffa CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dot_10 instead.") +#define CLUTTER_braille_blank 0x1002800 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_blank instead.") +#define CLUTTER_braille_dots_1 0x1002801 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1 instead.") +#define CLUTTER_braille_dots_2 0x1002802 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_2 instead.") +#define CLUTTER_braille_dots_12 0x1002803 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_12 instead.") +#define CLUTTER_braille_dots_3 0x1002804 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_3 instead.") +#define CLUTTER_braille_dots_13 0x1002805 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_13 instead.") +#define CLUTTER_braille_dots_23 0x1002806 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_23 instead.") +#define CLUTTER_braille_dots_123 0x1002807 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_123 instead.") +#define CLUTTER_braille_dots_4 0x1002808 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_4 instead.") +#define CLUTTER_braille_dots_14 0x1002809 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_14 instead.") +#define CLUTTER_braille_dots_24 0x100280a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_24 instead.") +#define CLUTTER_braille_dots_124 0x100280b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_124 instead.") +#define CLUTTER_braille_dots_34 0x100280c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_34 instead.") +#define CLUTTER_braille_dots_134 0x100280d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_134 instead.") +#define CLUTTER_braille_dots_234 0x100280e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_234 instead.") +#define CLUTTER_braille_dots_1234 0x100280f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1234 instead.") +#define CLUTTER_braille_dots_5 0x1002810 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_5 instead.") +#define CLUTTER_braille_dots_15 0x1002811 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_15 instead.") +#define CLUTTER_braille_dots_25 0x1002812 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_25 instead.") +#define CLUTTER_braille_dots_125 0x1002813 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_125 instead.") +#define CLUTTER_braille_dots_35 0x1002814 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_35 instead.") +#define CLUTTER_braille_dots_135 0x1002815 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_135 instead.") +#define CLUTTER_braille_dots_235 0x1002816 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_235 instead.") +#define CLUTTER_braille_dots_1235 0x1002817 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1235 instead.") +#define CLUTTER_braille_dots_45 0x1002818 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_45 instead.") +#define CLUTTER_braille_dots_145 0x1002819 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_145 instead.") +#define CLUTTER_braille_dots_245 0x100281a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_245 instead.") +#define CLUTTER_braille_dots_1245 0x100281b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1245 instead.") +#define CLUTTER_braille_dots_345 0x100281c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_345 instead.") +#define CLUTTER_braille_dots_1345 0x100281d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1345 instead.") +#define CLUTTER_braille_dots_2345 0x100281e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_2345 instead.") +#define CLUTTER_braille_dots_12345 0x100281f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_12345 instead.") +#define CLUTTER_braille_dots_6 0x1002820 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_6 instead.") +#define CLUTTER_braille_dots_16 0x1002821 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_16 instead.") +#define CLUTTER_braille_dots_26 0x1002822 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_26 instead.") +#define CLUTTER_braille_dots_126 0x1002823 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_126 instead.") +#define CLUTTER_braille_dots_36 0x1002824 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_36 instead.") +#define CLUTTER_braille_dots_136 0x1002825 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_136 instead.") +#define CLUTTER_braille_dots_236 0x1002826 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_236 instead.") +#define CLUTTER_braille_dots_1236 0x1002827 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1236 instead.") +#define CLUTTER_braille_dots_46 0x1002828 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_46 instead.") +#define CLUTTER_braille_dots_146 0x1002829 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_146 instead.") +#define CLUTTER_braille_dots_246 0x100282a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_246 instead.") +#define CLUTTER_braille_dots_1246 0x100282b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1246 instead.") +#define CLUTTER_braille_dots_346 0x100282c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_346 instead.") +#define CLUTTER_braille_dots_1346 0x100282d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1346 instead.") +#define CLUTTER_braille_dots_2346 0x100282e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_2346 instead.") +#define CLUTTER_braille_dots_12346 0x100282f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_12346 instead.") +#define CLUTTER_braille_dots_56 0x1002830 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_56 instead.") +#define CLUTTER_braille_dots_156 0x1002831 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_156 instead.") +#define CLUTTER_braille_dots_256 0x1002832 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_256 instead.") +#define CLUTTER_braille_dots_1256 0x1002833 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1256 instead.") +#define CLUTTER_braille_dots_356 0x1002834 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_356 instead.") +#define CLUTTER_braille_dots_1356 0x1002835 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1356 instead.") +#define CLUTTER_braille_dots_2356 0x1002836 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_2356 instead.") +#define CLUTTER_braille_dots_12356 0x1002837 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_12356 instead.") +#define CLUTTER_braille_dots_456 0x1002838 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_456 instead.") +#define CLUTTER_braille_dots_1456 0x1002839 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1456 instead.") +#define CLUTTER_braille_dots_2456 0x100283a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_2456 instead.") +#define CLUTTER_braille_dots_12456 0x100283b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_12456 instead.") +#define CLUTTER_braille_dots_3456 0x100283c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_3456 instead.") +#define CLUTTER_braille_dots_13456 0x100283d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_13456 instead.") +#define CLUTTER_braille_dots_23456 0x100283e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_23456 instead.") +#define CLUTTER_braille_dots_123456 0x100283f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_123456 instead.") +#define CLUTTER_braille_dots_7 0x1002840 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_7 instead.") +#define CLUTTER_braille_dots_17 0x1002841 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_17 instead.") +#define CLUTTER_braille_dots_27 0x1002842 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_27 instead.") +#define CLUTTER_braille_dots_127 0x1002843 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_127 instead.") +#define CLUTTER_braille_dots_37 0x1002844 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_37 instead.") +#define CLUTTER_braille_dots_137 0x1002845 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_137 instead.") +#define CLUTTER_braille_dots_237 0x1002846 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_237 instead.") +#define CLUTTER_braille_dots_1237 0x1002847 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1237 instead.") +#define CLUTTER_braille_dots_47 0x1002848 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_47 instead.") +#define CLUTTER_braille_dots_147 0x1002849 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_147 instead.") +#define CLUTTER_braille_dots_247 0x100284a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_247 instead.") +#define CLUTTER_braille_dots_1247 0x100284b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1247 instead.") +#define CLUTTER_braille_dots_347 0x100284c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_347 instead.") +#define CLUTTER_braille_dots_1347 0x100284d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1347 instead.") +#define CLUTTER_braille_dots_2347 0x100284e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_2347 instead.") +#define CLUTTER_braille_dots_12347 0x100284f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_12347 instead.") +#define CLUTTER_braille_dots_57 0x1002850 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_57 instead.") +#define CLUTTER_braille_dots_157 0x1002851 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_157 instead.") +#define CLUTTER_braille_dots_257 0x1002852 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_257 instead.") +#define CLUTTER_braille_dots_1257 0x1002853 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1257 instead.") +#define CLUTTER_braille_dots_357 0x1002854 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_357 instead.") +#define CLUTTER_braille_dots_1357 0x1002855 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1357 instead.") +#define CLUTTER_braille_dots_2357 0x1002856 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_2357 instead.") +#define CLUTTER_braille_dots_12357 0x1002857 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_12357 instead.") +#define CLUTTER_braille_dots_457 0x1002858 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_457 instead.") +#define CLUTTER_braille_dots_1457 0x1002859 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1457 instead.") +#define CLUTTER_braille_dots_2457 0x100285a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_2457 instead.") +#define CLUTTER_braille_dots_12457 0x100285b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_12457 instead.") +#define CLUTTER_braille_dots_3457 0x100285c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_3457 instead.") +#define CLUTTER_braille_dots_13457 0x100285d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_13457 instead.") +#define CLUTTER_braille_dots_23457 0x100285e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_23457 instead.") +#define CLUTTER_braille_dots_123457 0x100285f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_123457 instead.") +#define CLUTTER_braille_dots_67 0x1002860 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_67 instead.") +#define CLUTTER_braille_dots_167 0x1002861 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_167 instead.") +#define CLUTTER_braille_dots_267 0x1002862 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_267 instead.") +#define CLUTTER_braille_dots_1267 0x1002863 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1267 instead.") +#define CLUTTER_braille_dots_367 0x1002864 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_367 instead.") +#define CLUTTER_braille_dots_1367 0x1002865 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1367 instead.") +#define CLUTTER_braille_dots_2367 0x1002866 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_2367 instead.") +#define CLUTTER_braille_dots_12367 0x1002867 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_12367 instead.") +#define CLUTTER_braille_dots_467 0x1002868 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_467 instead.") +#define CLUTTER_braille_dots_1467 0x1002869 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1467 instead.") +#define CLUTTER_braille_dots_2467 0x100286a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_2467 instead.") +#define CLUTTER_braille_dots_12467 0x100286b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_12467 instead.") +#define CLUTTER_braille_dots_3467 0x100286c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_3467 instead.") +#define CLUTTER_braille_dots_13467 0x100286d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_13467 instead.") +#define CLUTTER_braille_dots_23467 0x100286e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_23467 instead.") +#define CLUTTER_braille_dots_123467 0x100286f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_123467 instead.") +#define CLUTTER_braille_dots_567 0x1002870 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_567 instead.") +#define CLUTTER_braille_dots_1567 0x1002871 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1567 instead.") +#define CLUTTER_braille_dots_2567 0x1002872 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_2567 instead.") +#define CLUTTER_braille_dots_12567 0x1002873 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_12567 instead.") +#define CLUTTER_braille_dots_3567 0x1002874 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_3567 instead.") +#define CLUTTER_braille_dots_13567 0x1002875 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_13567 instead.") +#define CLUTTER_braille_dots_23567 0x1002876 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_23567 instead.") +#define CLUTTER_braille_dots_123567 0x1002877 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_123567 instead.") +#define CLUTTER_braille_dots_4567 0x1002878 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_4567 instead.") +#define CLUTTER_braille_dots_14567 0x1002879 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_14567 instead.") +#define CLUTTER_braille_dots_24567 0x100287a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_24567 instead.") +#define CLUTTER_braille_dots_124567 0x100287b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_124567 instead.") +#define CLUTTER_braille_dots_34567 0x100287c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_34567 instead.") +#define CLUTTER_braille_dots_134567 0x100287d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_134567 instead.") +#define CLUTTER_braille_dots_234567 0x100287e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_234567 instead.") +#define CLUTTER_braille_dots_1234567 0x100287f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1234567 instead.") +#define CLUTTER_braille_dots_8 0x1002880 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_8 instead.") +#define CLUTTER_braille_dots_18 0x1002881 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_18 instead.") +#define CLUTTER_braille_dots_28 0x1002882 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_28 instead.") +#define CLUTTER_braille_dots_128 0x1002883 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_128 instead.") +#define CLUTTER_braille_dots_38 0x1002884 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_38 instead.") +#define CLUTTER_braille_dots_138 0x1002885 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_138 instead.") +#define CLUTTER_braille_dots_238 0x1002886 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_238 instead.") +#define CLUTTER_braille_dots_1238 0x1002887 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1238 instead.") +#define CLUTTER_braille_dots_48 0x1002888 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_48 instead.") +#define CLUTTER_braille_dots_148 0x1002889 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_148 instead.") +#define CLUTTER_braille_dots_248 0x100288a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_248 instead.") +#define CLUTTER_braille_dots_1248 0x100288b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1248 instead.") +#define CLUTTER_braille_dots_348 0x100288c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_348 instead.") +#define CLUTTER_braille_dots_1348 0x100288d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1348 instead.") +#define CLUTTER_braille_dots_2348 0x100288e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_2348 instead.") +#define CLUTTER_braille_dots_12348 0x100288f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_12348 instead.") +#define CLUTTER_braille_dots_58 0x1002890 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_58 instead.") +#define CLUTTER_braille_dots_158 0x1002891 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_158 instead.") +#define CLUTTER_braille_dots_258 0x1002892 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_258 instead.") +#define CLUTTER_braille_dots_1258 0x1002893 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1258 instead.") +#define CLUTTER_braille_dots_358 0x1002894 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_358 instead.") +#define CLUTTER_braille_dots_1358 0x1002895 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1358 instead.") +#define CLUTTER_braille_dots_2358 0x1002896 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_2358 instead.") +#define CLUTTER_braille_dots_12358 0x1002897 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_12358 instead.") +#define CLUTTER_braille_dots_458 0x1002898 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_458 instead.") +#define CLUTTER_braille_dots_1458 0x1002899 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1458 instead.") +#define CLUTTER_braille_dots_2458 0x100289a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_2458 instead.") +#define CLUTTER_braille_dots_12458 0x100289b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_12458 instead.") +#define CLUTTER_braille_dots_3458 0x100289c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_3458 instead.") +#define CLUTTER_braille_dots_13458 0x100289d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_13458 instead.") +#define CLUTTER_braille_dots_23458 0x100289e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_23458 instead.") +#define CLUTTER_braille_dots_123458 0x100289f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_123458 instead.") +#define CLUTTER_braille_dots_68 0x10028a0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_68 instead.") +#define CLUTTER_braille_dots_168 0x10028a1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_168 instead.") +#define CLUTTER_braille_dots_268 0x10028a2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_268 instead.") +#define CLUTTER_braille_dots_1268 0x10028a3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1268 instead.") +#define CLUTTER_braille_dots_368 0x10028a4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_368 instead.") +#define CLUTTER_braille_dots_1368 0x10028a5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1368 instead.") +#define CLUTTER_braille_dots_2368 0x10028a6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_2368 instead.") +#define CLUTTER_braille_dots_12368 0x10028a7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_12368 instead.") +#define CLUTTER_braille_dots_468 0x10028a8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_468 instead.") +#define CLUTTER_braille_dots_1468 0x10028a9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1468 instead.") +#define CLUTTER_braille_dots_2468 0x10028aa CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_2468 instead.") +#define CLUTTER_braille_dots_12468 0x10028ab CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_12468 instead.") +#define CLUTTER_braille_dots_3468 0x10028ac CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_3468 instead.") +#define CLUTTER_braille_dots_13468 0x10028ad CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_13468 instead.") +#define CLUTTER_braille_dots_23468 0x10028ae CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_23468 instead.") +#define CLUTTER_braille_dots_123468 0x10028af CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_123468 instead.") +#define CLUTTER_braille_dots_568 0x10028b0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_568 instead.") +#define CLUTTER_braille_dots_1568 0x10028b1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1568 instead.") +#define CLUTTER_braille_dots_2568 0x10028b2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_2568 instead.") +#define CLUTTER_braille_dots_12568 0x10028b3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_12568 instead.") +#define CLUTTER_braille_dots_3568 0x10028b4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_3568 instead.") +#define CLUTTER_braille_dots_13568 0x10028b5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_13568 instead.") +#define CLUTTER_braille_dots_23568 0x10028b6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_23568 instead.") +#define CLUTTER_braille_dots_123568 0x10028b7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_123568 instead.") +#define CLUTTER_braille_dots_4568 0x10028b8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_4568 instead.") +#define CLUTTER_braille_dots_14568 0x10028b9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_14568 instead.") +#define CLUTTER_braille_dots_24568 0x10028ba CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_24568 instead.") +#define CLUTTER_braille_dots_124568 0x10028bb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_124568 instead.") +#define CLUTTER_braille_dots_34568 0x10028bc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_34568 instead.") +#define CLUTTER_braille_dots_134568 0x10028bd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_134568 instead.") +#define CLUTTER_braille_dots_234568 0x10028be CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_234568 instead.") +#define CLUTTER_braille_dots_1234568 0x10028bf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1234568 instead.") +#define CLUTTER_braille_dots_78 0x10028c0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_78 instead.") +#define CLUTTER_braille_dots_178 0x10028c1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_178 instead.") +#define CLUTTER_braille_dots_278 0x10028c2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_278 instead.") +#define CLUTTER_braille_dots_1278 0x10028c3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1278 instead.") +#define CLUTTER_braille_dots_378 0x10028c4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_378 instead.") +#define CLUTTER_braille_dots_1378 0x10028c5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1378 instead.") +#define CLUTTER_braille_dots_2378 0x10028c6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_2378 instead.") +#define CLUTTER_braille_dots_12378 0x10028c7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_12378 instead.") +#define CLUTTER_braille_dots_478 0x10028c8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_478 instead.") +#define CLUTTER_braille_dots_1478 0x10028c9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1478 instead.") +#define CLUTTER_braille_dots_2478 0x10028ca CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_2478 instead.") +#define CLUTTER_braille_dots_12478 0x10028cb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_12478 instead.") +#define CLUTTER_braille_dots_3478 0x10028cc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_3478 instead.") +#define CLUTTER_braille_dots_13478 0x10028cd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_13478 instead.") +#define CLUTTER_braille_dots_23478 0x10028ce CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_23478 instead.") +#define CLUTTER_braille_dots_123478 0x10028cf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_123478 instead.") +#define CLUTTER_braille_dots_578 0x10028d0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_578 instead.") +#define CLUTTER_braille_dots_1578 0x10028d1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1578 instead.") +#define CLUTTER_braille_dots_2578 0x10028d2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_2578 instead.") +#define CLUTTER_braille_dots_12578 0x10028d3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_12578 instead.") +#define CLUTTER_braille_dots_3578 0x10028d4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_3578 instead.") +#define CLUTTER_braille_dots_13578 0x10028d5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_13578 instead.") +#define CLUTTER_braille_dots_23578 0x10028d6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_23578 instead.") +#define CLUTTER_braille_dots_123578 0x10028d7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_123578 instead.") +#define CLUTTER_braille_dots_4578 0x10028d8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_4578 instead.") +#define CLUTTER_braille_dots_14578 0x10028d9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_14578 instead.") +#define CLUTTER_braille_dots_24578 0x10028da CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_24578 instead.") +#define CLUTTER_braille_dots_124578 0x10028db CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_124578 instead.") +#define CLUTTER_braille_dots_34578 0x10028dc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_34578 instead.") +#define CLUTTER_braille_dots_134578 0x10028dd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_134578 instead.") +#define CLUTTER_braille_dots_234578 0x10028de CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_234578 instead.") +#define CLUTTER_braille_dots_1234578 0x10028df CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1234578 instead.") +#define CLUTTER_braille_dots_678 0x10028e0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_678 instead.") +#define CLUTTER_braille_dots_1678 0x10028e1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1678 instead.") +#define CLUTTER_braille_dots_2678 0x10028e2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_2678 instead.") +#define CLUTTER_braille_dots_12678 0x10028e3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_12678 instead.") +#define CLUTTER_braille_dots_3678 0x10028e4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_3678 instead.") +#define CLUTTER_braille_dots_13678 0x10028e5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_13678 instead.") +#define CLUTTER_braille_dots_23678 0x10028e6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_23678 instead.") +#define CLUTTER_braille_dots_123678 0x10028e7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_123678 instead.") +#define CLUTTER_braille_dots_4678 0x10028e8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_4678 instead.") +#define CLUTTER_braille_dots_14678 0x10028e9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_14678 instead.") +#define CLUTTER_braille_dots_24678 0x10028ea CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_24678 instead.") +#define CLUTTER_braille_dots_124678 0x10028eb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_124678 instead.") +#define CLUTTER_braille_dots_34678 0x10028ec CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_34678 instead.") +#define CLUTTER_braille_dots_134678 0x10028ed CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_134678 instead.") +#define CLUTTER_braille_dots_234678 0x10028ee CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_234678 instead.") +#define CLUTTER_braille_dots_1234678 0x10028ef CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1234678 instead.") +#define CLUTTER_braille_dots_5678 0x10028f0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_5678 instead.") +#define CLUTTER_braille_dots_15678 0x10028f1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_15678 instead.") +#define CLUTTER_braille_dots_25678 0x10028f2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_25678 instead.") +#define CLUTTER_braille_dots_125678 0x10028f3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_125678 instead.") +#define CLUTTER_braille_dots_35678 0x10028f4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_35678 instead.") +#define CLUTTER_braille_dots_135678 0x10028f5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_135678 instead.") +#define CLUTTER_braille_dots_235678 0x10028f6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_235678 instead.") +#define CLUTTER_braille_dots_1235678 0x10028f7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1235678 instead.") +#define CLUTTER_braille_dots_45678 0x10028f8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_45678 instead.") +#define CLUTTER_braille_dots_145678 0x10028f9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_145678 instead.") +#define CLUTTER_braille_dots_245678 0x10028fa CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_245678 instead.") +#define CLUTTER_braille_dots_1245678 0x10028fb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1245678 instead.") +#define CLUTTER_braille_dots_345678 0x10028fc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_345678 instead.") +#define CLUTTER_braille_dots_1345678 0x10028fd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_1345678 instead.") +#define CLUTTER_braille_dots_2345678 0x10028fe CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_2345678 instead.") +#define CLUTTER_braille_dots_12345678 0x10028ff CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_braille_dots_12345678 instead.") +#define CLUTTER_Sinh_ng 0x1000d82 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ng instead.") +#define CLUTTER_Sinh_h2 0x1000d83 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_h2 instead.") +#define CLUTTER_Sinh_a 0x1000d85 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_a instead.") +#define CLUTTER_Sinh_aa 0x1000d86 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_aa instead.") +#define CLUTTER_Sinh_ae 0x1000d87 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ae instead.") +#define CLUTTER_Sinh_aee 0x1000d88 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_aee instead.") +#define CLUTTER_Sinh_i 0x1000d89 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_i instead.") +#define CLUTTER_Sinh_ii 0x1000d8a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ii instead.") +#define CLUTTER_Sinh_u 0x1000d8b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_u instead.") +#define CLUTTER_Sinh_uu 0x1000d8c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_uu instead.") +#define CLUTTER_Sinh_ri 0x1000d8d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ri instead.") +#define CLUTTER_Sinh_rii 0x1000d8e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_rii instead.") +#define CLUTTER_Sinh_lu 0x1000d8f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_lu instead.") +#define CLUTTER_Sinh_luu 0x1000d90 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_luu instead.") +#define CLUTTER_Sinh_e 0x1000d91 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_e instead.") +#define CLUTTER_Sinh_ee 0x1000d92 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ee instead.") +#define CLUTTER_Sinh_ai 0x1000d93 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ai instead.") +#define CLUTTER_Sinh_o 0x1000d94 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_o instead.") +#define CLUTTER_Sinh_oo 0x1000d95 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_oo instead.") +#define CLUTTER_Sinh_au 0x1000d96 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_au instead.") +#define CLUTTER_Sinh_ka 0x1000d9a CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ka instead.") +#define CLUTTER_Sinh_kha 0x1000d9b CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_kha instead.") +#define CLUTTER_Sinh_ga 0x1000d9c CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ga instead.") +#define CLUTTER_Sinh_gha 0x1000d9d CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_gha instead.") +#define CLUTTER_Sinh_ng2 0x1000d9e CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ng2 instead.") +#define CLUTTER_Sinh_nga 0x1000d9f CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_nga instead.") +#define CLUTTER_Sinh_ca 0x1000da0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ca instead.") +#define CLUTTER_Sinh_cha 0x1000da1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_cha instead.") +#define CLUTTER_Sinh_ja 0x1000da2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ja instead.") +#define CLUTTER_Sinh_jha 0x1000da3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_jha instead.") +#define CLUTTER_Sinh_nya 0x1000da4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_nya instead.") +#define CLUTTER_Sinh_jnya 0x1000da5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_jnya instead.") +#define CLUTTER_Sinh_nja 0x1000da6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_nja instead.") +#define CLUTTER_Sinh_tta 0x1000da7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_tta instead.") +#define CLUTTER_Sinh_ttha 0x1000da8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ttha instead.") +#define CLUTTER_Sinh_dda 0x1000da9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_dda instead.") +#define CLUTTER_Sinh_ddha 0x1000daa CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ddha instead.") +#define CLUTTER_Sinh_nna 0x1000dab CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_nna instead.") +#define CLUTTER_Sinh_ndda 0x1000dac CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ndda instead.") +#define CLUTTER_Sinh_tha 0x1000dad CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_tha instead.") +#define CLUTTER_Sinh_thha 0x1000dae CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_thha instead.") +#define CLUTTER_Sinh_dha 0x1000daf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_dha instead.") +#define CLUTTER_Sinh_dhha 0x1000db0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_dhha instead.") +#define CLUTTER_Sinh_na 0x1000db1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_na instead.") +#define CLUTTER_Sinh_ndha 0x1000db3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ndha instead.") +#define CLUTTER_Sinh_pa 0x1000db4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_pa instead.") +#define CLUTTER_Sinh_pha 0x1000db5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_pha instead.") +#define CLUTTER_Sinh_ba 0x1000db6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ba instead.") +#define CLUTTER_Sinh_bha 0x1000db7 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_bha instead.") +#define CLUTTER_Sinh_ma 0x1000db8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ma instead.") +#define CLUTTER_Sinh_mba 0x1000db9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_mba instead.") +#define CLUTTER_Sinh_ya 0x1000dba CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ya instead.") +#define CLUTTER_Sinh_ra 0x1000dbb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ra instead.") +#define CLUTTER_Sinh_la 0x1000dbd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_la instead.") +#define CLUTTER_Sinh_va 0x1000dc0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_va instead.") +#define CLUTTER_Sinh_sha 0x1000dc1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_sha instead.") +#define CLUTTER_Sinh_ssha 0x1000dc2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ssha instead.") +#define CLUTTER_Sinh_sa 0x1000dc3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_sa instead.") +#define CLUTTER_Sinh_ha 0x1000dc4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ha instead.") +#define CLUTTER_Sinh_lla 0x1000dc5 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_lla instead.") +#define CLUTTER_Sinh_fa 0x1000dc6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_fa instead.") +#define CLUTTER_Sinh_al 0x1000dca CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_al instead.") +#define CLUTTER_Sinh_aa2 0x1000dcf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_aa2 instead.") +#define CLUTTER_Sinh_ae2 0x1000dd0 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ae2 instead.") +#define CLUTTER_Sinh_aee2 0x1000dd1 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_aee2 instead.") +#define CLUTTER_Sinh_i2 0x1000dd2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_i2 instead.") +#define CLUTTER_Sinh_ii2 0x1000dd3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ii2 instead.") +#define CLUTTER_Sinh_u2 0x1000dd4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_u2 instead.") +#define CLUTTER_Sinh_uu2 0x1000dd6 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_uu2 instead.") +#define CLUTTER_Sinh_ru2 0x1000dd8 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ru2 instead.") +#define CLUTTER_Sinh_e2 0x1000dd9 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_e2 instead.") +#define CLUTTER_Sinh_ee2 0x1000dda CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ee2 instead.") +#define CLUTTER_Sinh_ai2 0x1000ddb CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ai2 instead.") +#define CLUTTER_Sinh_o2 0x1000ddc CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_o2 instead.") +#define CLUTTER_Sinh_oo2 0x1000ddd CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_oo2 instead.") +#define CLUTTER_Sinh_au2 0x1000dde CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_au2 instead.") +#define CLUTTER_Sinh_lu2 0x1000ddf CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_lu2 instead.") +#define CLUTTER_Sinh_ruu2 0x1000df2 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_ruu2 instead.") +#define CLUTTER_Sinh_luu2 0x1000df3 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_luu2 instead.") +#define CLUTTER_Sinh_kunddaliya 0x1000df4 CLUTTER_DEPRECATED_MACRO_FOR("Deprecated key symbol. Use CLUTTER_KEY_Sinh_kunddaliya instead.") +#define CLUTTER_ModeLock 0x1008ff01 +#define CLUTTER_MonBrightnessUp 0x1008ff02 +#define CLUTTER_MonBrightnessDown 0x1008ff03 +#define CLUTTER_KbdLightOnOff 0x1008ff04 +#define CLUTTER_KbdBrightnessUp 0x1008ff05 +#define CLUTTER_KbdBrightnessDown 0x1008ff06 +#define CLUTTER_Standby 0x1008ff10 +#define CLUTTER_AudioLowerVolume 0x1008ff11 +#define CLUTTER_AudioMute 0x1008ff12 +#define CLUTTER_AudioRaiseVolume 0x1008ff13 +#define CLUTTER_AudioPlay 0x1008ff14 +#define CLUTTER_AudioStop 0x1008ff15 +#define CLUTTER_AudioPrev 0x1008ff16 +#define CLUTTER_AudioNext 0x1008ff17 +#define CLUTTER_HomePage 0x1008ff18 +#define CLUTTER_Mail 0x1008ff19 +#define CLUTTER_Start 0x1008ff1a +#define CLUTTER_Search 0x1008ff1b +#define CLUTTER_AudioRecord 0x1008ff1c +#define CLUTTER_Calculator 0x1008ff1d +#define CLUTTER_Memo 0x1008ff1e +#define CLUTTER_ToDoList 0x1008ff1f +#define CLUTTER_Calendar 0x1008ff20 +#define CLUTTER_PowerDown 0x1008ff21 +#define CLUTTER_ContrastAdjust 0x1008ff22 +#define CLUTTER_RockerUp 0x1008ff23 +#define CLUTTER_RockerDown 0x1008ff24 +#define CLUTTER_RockerEnter 0x1008ff25 +#define CLUTTER_Back 0x1008ff26 +#define CLUTTER_Forward 0x1008ff27 +#define CLUTTER_Stop 0x1008ff28 +#define CLUTTER_Refresh 0x1008ff29 +#define CLUTTER_PowerOff 0x1008ff2a +#define CLUTTER_WakeUp 0x1008ff2b +#define CLUTTER_Eject 0x1008ff2c +#define CLUTTER_ScreenSaver 0x1008ff2d +#define CLUTTER_WWW 0x1008ff2e +#define CLUTTER_Sleep 0x1008ff2f +#define CLUTTER_Favorites 0x1008ff30 +#define CLUTTER_AudioPause 0x1008ff31 +#define CLUTTER_AudioMedia 0x1008ff32 +#define CLUTTER_MyComputer 0x1008ff33 +#define CLUTTER_VendorHome 0x1008ff34 +#define CLUTTER_LightBulb 0x1008ff35 +#define CLUTTER_Shop 0x1008ff36 +#define CLUTTER_History 0x1008ff37 +#define CLUTTER_OpenURL 0x1008ff38 +#define CLUTTER_AddFavorite 0x1008ff39 +#define CLUTTER_HotLinks 0x1008ff3a +#define CLUTTER_BrightnessAdjust 0x1008ff3b +#define CLUTTER_Finance 0x1008ff3c +#define CLUTTER_Community 0x1008ff3d +#define CLUTTER_AudioRewind 0x1008ff3e +#define CLUTTER_BackForward 0x1008ff3f +#define CLUTTER_Launch0 0x1008ff40 +#define CLUTTER_Launch1 0x1008ff41 +#define CLUTTER_Launch2 0x1008ff42 +#define CLUTTER_Launch3 0x1008ff43 +#define CLUTTER_Launch4 0x1008ff44 +#define CLUTTER_Launch5 0x1008ff45 +#define CLUTTER_Launch6 0x1008ff46 +#define CLUTTER_Launch7 0x1008ff47 +#define CLUTTER_Launch8 0x1008ff48 +#define CLUTTER_Launch9 0x1008ff49 +#define CLUTTER_LaunchA 0x1008ff4a +#define CLUTTER_LaunchB 0x1008ff4b +#define CLUTTER_LaunchC 0x1008ff4c +#define CLUTTER_LaunchD 0x1008ff4d +#define CLUTTER_LaunchE 0x1008ff4e +#define CLUTTER_LaunchF 0x1008ff4f +#define CLUTTER_ApplicationLeft 0x1008ff50 +#define CLUTTER_ApplicationRight 0x1008ff51 +#define CLUTTER_Book 0x1008ff52 +#define CLUTTER_CD 0x1008ff53 +#define CLUTTER_WindowClear 0x1008ff55 +#define CLUTTER_Close 0x1008ff56 +#define CLUTTER_Copy 0x1008ff57 +#define CLUTTER_Cut 0x1008ff58 +#define CLUTTER_Display 0x1008ff59 +#define CLUTTER_DOS 0x1008ff5a +#define CLUTTER_Documents 0x1008ff5b +#define CLUTTER_Excel 0x1008ff5c +#define CLUTTER_Explorer 0x1008ff5d +#define CLUTTER_Game 0x1008ff5e +#define CLUTTER_Go 0x1008ff5f +#define CLUTTER_iTouch 0x1008ff60 +#define CLUTTER_LogOff 0x1008ff61 +#define CLUTTER_Market 0x1008ff62 +#define CLUTTER_Meeting 0x1008ff63 +#define CLUTTER_MenuKB 0x1008ff65 +#define CLUTTER_MenuPB 0x1008ff66 +#define CLUTTER_MySites 0x1008ff67 +#define CLUTTER_New 0x1008ff68 +#define CLUTTER_News 0x1008ff69 +#define CLUTTER_OfficeHome 0x1008ff6a +#define CLUTTER_Open 0x1008ff6b +#define CLUTTER_Option 0x1008ff6c +#define CLUTTER_Paste 0x1008ff6d +#define CLUTTER_Phone 0x1008ff6e +#define CLUTTER_Reply 0x1008ff72 +#define CLUTTER_Reload 0x1008ff73 +#define CLUTTER_RotateWindows 0x1008ff74 +#define CLUTTER_RotationPB 0x1008ff75 +#define CLUTTER_RotationKB 0x1008ff76 +#define CLUTTER_Save 0x1008ff77 +#define CLUTTER_ScrollUp 0x1008ff78 +#define CLUTTER_ScrollDown 0x1008ff79 +#define CLUTTER_ScrollClick 0x1008ff7a +#define CLUTTER_Send 0x1008ff7b +#define CLUTTER_Spell 0x1008ff7c +#define CLUTTER_SplitScreen 0x1008ff7d +#define CLUTTER_Support 0x1008ff7e +#define CLUTTER_TaskPane 0x1008ff7f +#define CLUTTER_Terminal 0x1008ff80 +#define CLUTTER_Tools 0x1008ff81 +#define CLUTTER_Travel 0x1008ff82 +#define CLUTTER_UserPB 0x1008ff84 +#define CLUTTER_User1KB 0x1008ff85 +#define CLUTTER_User2KB 0x1008ff86 +#define CLUTTER_Video 0x1008ff87 +#define CLUTTER_WheelButton 0x1008ff88 +#define CLUTTER_Word 0x1008ff89 +#define CLUTTER_Xfer 0x1008ff8a +#define CLUTTER_ZoomIn 0x1008ff8b +#define CLUTTER_ZoomOut 0x1008ff8c +#define CLUTTER_Away 0x1008ff8d +#define CLUTTER_Messenger 0x1008ff8e +#define CLUTTER_WebCam 0x1008ff8f +#define CLUTTER_MailForward 0x1008ff90 +#define CLUTTER_Pictures 0x1008ff91 +#define CLUTTER_Music 0x1008ff92 +#define CLUTTER_Battery 0x1008ff93 +#define CLUTTER_Bluetooth 0x1008ff94 +#define CLUTTER_WLAN 0x1008ff95 +#define CLUTTER_UWB 0x1008ff96 +#define CLUTTER_AudioForward 0x1008ff97 +#define CLUTTER_AudioRepeat 0x1008ff98 +#define CLUTTER_AudioRandomPlay 0x1008ff99 +#define CLUTTER_Subtitle 0x1008ff9a +#define CLUTTER_AudioCycleTrack 0x1008ff9b +#define CLUTTER_CycleAngle 0x1008ff9c +#define CLUTTER_FrameBack 0x1008ff9d +#define CLUTTER_FrameForward 0x1008ff9e +#define CLUTTER_Time 0x1008ff9f +#define CLUTTER_SelectButton 0x1008ffa0 +#define CLUTTER_View 0x1008ffa1 +#define CLUTTER_TopMenu 0x1008ffa2 +#define CLUTTER_Red 0x1008ffa3 +#define CLUTTER_Green 0x1008ffa4 +#define CLUTTER_Yellow 0x1008ffa5 +#define CLUTTER_Blue 0x1008ffa6 +#define CLUTTER_Suspend 0x1008ffa7 +#define CLUTTER_Hibernate 0x1008ffa8 +#define CLUTTER_TouchpadToggle 0x1008ffa9 +#define CLUTTER_TouchpadOn 0x1008ffb0 +#define CLUTTER_TouchpadOff 0x1008ffb1 +#define CLUTTER_AudioMicMute 0x1008ffb2 +#define CLUTTER_Switch_VT_1 0x1008fe01 +#define CLUTTER_Switch_VT_2 0x1008fe02 +#define CLUTTER_Switch_VT_3 0x1008fe03 +#define CLUTTER_Switch_VT_4 0x1008fe04 +#define CLUTTER_Switch_VT_5 0x1008fe05 +#define CLUTTER_Switch_VT_6 0x1008fe06 +#define CLUTTER_Switch_VT_7 0x1008fe07 +#define CLUTTER_Switch_VT_8 0x1008fe08 +#define CLUTTER_Switch_VT_9 0x1008fe09 +#define CLUTTER_Switch_VT_10 0x1008fe0a +#define CLUTTER_Switch_VT_11 0x1008fe0b +#define CLUTTER_Switch_VT_12 0x1008fe0c +#define CLUTTER_Ungrab 0x1008fe20 +#define CLUTTER_ClearGrab 0x1008fe21 +#define CLUTTER_Next_VMode 0x1008fe22 +#define CLUTTER_Prev_VMode 0x1008fe23 +#define CLUTTER_LogWindowTree 0x1008fe24 +#define CLUTTER_LogGrabInfo 0x1008fe25 + +#endif /* CLUTTER_DISABLE_DEPRECATED */ + +#endif /* __CLUTTER_KEYSYMS_DEPRECATED_H__ */ diff --git a/clutter/clutter/deprecated/clutter-layout-manager-deprecated.c b/clutter/clutter/deprecated/clutter-layout-manager-deprecated.c new file mode 100644 index 0000000..94f0e35 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-layout-manager-deprecated.c @@ -0,0 +1,89 @@ +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-layout-manager.h" + +/** + * clutter_layout_manager_begin_animation: + * @manager: a #ClutterLayoutManager + * @duration: the duration of the animation, in milliseconds + * @mode: the easing mode of the animation + * + * Begins an animation of @duration milliseconds, using the provided + * easing @mode + * + * The easing mode can be specified either as a #ClutterAnimationMode + * or as a logical id returned by clutter_alpha_register_func() + * + * The result of this function depends on the @manager implementation + * + * Return value: (transfer none): The #ClutterAlpha created by the + * layout manager; the returned instance is owned by the layout + * manager and should not be unreferenced + * + * Since: 1.2 + * + * Deprecated: 1.12 + */ +ClutterAlpha * +clutter_layout_manager_begin_animation (ClutterLayoutManager *manager, + guint duration, + gulong mode) +{ + ClutterLayoutManagerClass *klass; + + g_return_val_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager), NULL); + + klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager); + + return klass->begin_animation (manager, duration, mode); +} + +/** + * clutter_layout_manager_end_animation: + * @manager: a #ClutterLayoutManager + * + * Ends an animation started by clutter_layout_manager_begin_animation() + * + * The result of this call depends on the @manager implementation + * + * Since: 1.2 + * + * Deprecated: 1.12 + */ +void +clutter_layout_manager_end_animation (ClutterLayoutManager *manager) +{ + g_return_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager)); + + CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager)->end_animation (manager); +} + +/** + * clutter_layout_manager_get_animation_progress: + * @manager: a #ClutterLayoutManager + * + * Retrieves the progress of the animation, if one has been started by + * clutter_layout_manager_begin_animation() + * + * The returned value has the same semantics of the #ClutterAlpha:alpha + * value + * + * Return value: the progress of the animation + * + * Since: 1.2 + * + * Deprecated: 1.12 + */ +gdouble +clutter_layout_manager_get_animation_progress (ClutterLayoutManager *manager) +{ + ClutterLayoutManagerClass *klass; + + g_return_val_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager), 1.0); + + klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager); + + return klass->get_animation_progress (manager); +} diff --git a/clutter/clutter/deprecated/clutter-list-model.c b/clutter/clutter/deprecated/clutter-list-model.c new file mode 100644 index 0000000..2072a25 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-list-model.c @@ -0,0 +1,836 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * Neil Jagdish Patel + * Emmanuele Bassi + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +/** + * SECTION:clutter-list-model + * @short_description: List model implementation + * + * #ClutterListModel is a #ClutterModel implementation provided by + * Clutter. #ClutterListModel uses a #GSequence for storing the + * values for each row, so it's optimized for insertion and look up + * in sorted lists. + * + * #ClutterListModel is available since Clutter 0.6 + * + * Deprecated: 1.24: Use a #GListStore instance containing a custom + * object type with properties for each column instead. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include +#include + +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include "clutter-list-model.h" + +#include "clutter-model.h" +#include "clutter-model-private.h" +#include "clutter-private.h" +#include "clutter-debug.h" + +#define CLUTTER_TYPE_LIST_MODEL_ITER \ + (clutter_list_model_iter_get_type()) +#define CLUTTER_LIST_MODEL_ITER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + CLUTTER_TYPE_LIST_MODEL_ITER, \ + ClutterListModelIter)) +#define CLUTTER_IS_LIST_MODEL_ITER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), \ + CLUTTER_TYPE_LIST_MODEL_ITER)) +#define CLUTTER_LIST_MODEL_ITER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + CLUTTER_TYPE_LIST_MODEL_ITER, \ + ClutterListModelIterClass)) +#define CLUTTER_IS_LIST_MODEL_ITER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + CLUTTER_TYPE_LIST_MODEL_ITER)) +#define CLUTTER_LIST_MODEL_ITER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + CLUTTER_TYPE_LIST_MODEL_ITER, \ + ClutterListModelIterClass)) + +typedef struct _ClutterListModelIter ClutterListModelIter; +typedef struct _ClutterModelIterClass ClutterListModelIterClass; + +struct _ClutterListModelPrivate +{ + GSequence *sequence; + + ClutterModelIter *temp_iter; +}; + +struct _ClutterListModelIter +{ + ClutterModelIter parent_instance; + + GSequenceIter *seq_iter; +}; + + + +GType clutter_list_model_iter_get_type (void); + +/* + * ClutterListModel + */ + +G_DEFINE_TYPE (ClutterListModelIter, + clutter_list_model_iter, + CLUTTER_TYPE_MODEL_ITER) + +static void +clutter_list_model_iter_get_value (ClutterModelIter *iter, + guint column, + GValue *value) +{ + ClutterListModelIter *iter_default; + GValue *values; + GValue *iter_value; + GValue real_value = G_VALUE_INIT; + gboolean converted = FALSE; + + iter_default = CLUTTER_LIST_MODEL_ITER (iter); + g_assert (iter_default->seq_iter != NULL); + + values = g_sequence_get (iter_default->seq_iter); + iter_value = &values[column]; + g_assert (iter_value != NULL); + + if (!g_type_is_a (G_VALUE_TYPE (value), G_VALUE_TYPE (iter_value))) + { + if (!g_value_type_compatible (G_VALUE_TYPE (value), + G_VALUE_TYPE (iter_value)) && + !g_value_type_compatible (G_VALUE_TYPE (iter_value), + G_VALUE_TYPE (value))) + { + g_warning ("%s: Unable to convert from %s to %s", + G_STRLOC, + g_type_name (G_VALUE_TYPE (value)), + g_type_name (G_VALUE_TYPE (iter_value))); + return; + } + + if (!g_value_transform (iter_value, &real_value)) + { + g_warning ("%s: Unable to make conversion from %s to %s", + G_STRLOC, + g_type_name (G_VALUE_TYPE (value)), + g_type_name (G_VALUE_TYPE (iter_value))); + g_value_unset (&real_value); + } + + converted = TRUE; + } + + if (converted) + { + g_value_copy (&real_value, value); + g_value_unset (&real_value); + } + else + g_value_copy (iter_value, value); +} + +static void +clutter_list_model_iter_set_value (ClutterModelIter *iter, + guint column, + const GValue *value) +{ + ClutterListModelIter *iter_default; + GValue *values; + GValue *iter_value; + GValue real_value = G_VALUE_INIT; + gboolean converted = FALSE; + + iter_default = CLUTTER_LIST_MODEL_ITER (iter); + g_assert (iter_default->seq_iter != NULL); + + values = g_sequence_get (iter_default->seq_iter); + iter_value = &values[column]; + g_assert (iter_value != NULL); + + if (!g_type_is_a (G_VALUE_TYPE (value), G_VALUE_TYPE (iter_value))) + { + if (!g_value_type_compatible (G_VALUE_TYPE (value), + G_VALUE_TYPE (iter_value)) && + !g_value_type_compatible (G_VALUE_TYPE (iter_value), + G_VALUE_TYPE (value))) + { + g_warning ("%s: Unable to convert from %s to %s\n", + G_STRLOC, + g_type_name (G_VALUE_TYPE (value)), + g_type_name (G_VALUE_TYPE (iter_value))); + return; + } + + if (!g_value_transform (value, &real_value)) + { + g_warning ("%s: Unable to make conversion from %s to %s\n", + G_STRLOC, + g_type_name (G_VALUE_TYPE (value)), + g_type_name (G_VALUE_TYPE (iter_value))); + g_value_unset (&real_value); + } + + converted = TRUE; + } + + if (converted) + { + g_value_copy (&real_value, iter_value); + g_value_unset (&real_value); + } + else + g_value_copy (value, iter_value); +} + +static gboolean +clutter_list_model_iter_is_first (ClutterModelIter *iter) +{ + ClutterListModelIter *iter_default; + ClutterModel *model; + ClutterModelIter *temp_iter; + GSequence *sequence; + GSequenceIter *begin, *end; + + iter_default = CLUTTER_LIST_MODEL_ITER (iter); + g_assert (iter_default->seq_iter != NULL); + + model = clutter_model_iter_get_model (iter); + + sequence = CLUTTER_LIST_MODEL (model)->priv->sequence; + + begin = g_sequence_get_begin_iter (sequence); + end = iter_default->seq_iter; + + temp_iter = CLUTTER_LIST_MODEL (model)->priv->temp_iter; + + while (!g_sequence_iter_is_begin (begin)) + { + CLUTTER_LIST_MODEL_ITER (temp_iter)->seq_iter = begin; + + if (clutter_model_filter_iter (model, temp_iter)) + { + end = begin; + break; + } + + begin = g_sequence_iter_next (begin); + } + + /* This is because the 'begin_iter' is always *before* the last valid + * iter, otherwise we'd have endless loops + */ + end = g_sequence_iter_prev (end); + + return iter_default->seq_iter == end; +} + +static gboolean +clutter_list_model_iter_is_last (ClutterModelIter *iter) +{ + ClutterListModelIter *iter_default; + ClutterModelIter *temp_iter; + ClutterModel *model; + GSequence *sequence; + GSequenceIter *begin, *end; + + iter_default = CLUTTER_LIST_MODEL_ITER (iter); + g_assert (iter_default->seq_iter != NULL); + + if (g_sequence_iter_is_end (iter_default->seq_iter)) + return TRUE; + + model = clutter_model_iter_get_model (iter); + + sequence = CLUTTER_LIST_MODEL (model)->priv->sequence; + + begin = g_sequence_get_end_iter (sequence); + begin = g_sequence_iter_prev (begin); + end = iter_default->seq_iter; + + temp_iter = CLUTTER_LIST_MODEL (model)->priv->temp_iter; + + while (!g_sequence_iter_is_begin (begin)) + { + CLUTTER_LIST_MODEL_ITER (temp_iter)->seq_iter = begin; + + if (clutter_model_filter_iter (model, temp_iter)) + { + end = begin; + break; + } + + begin = g_sequence_iter_prev (begin); + } + + /* This is because the 'end_iter' is always *after* the last valid iter. + * Otherwise we'd have endless loops + */ + end = g_sequence_iter_next (end); + + return iter_default->seq_iter == end; +} + +static ClutterModelIter * +clutter_list_model_iter_next (ClutterModelIter *iter) +{ + ClutterListModelIter *iter_default; + ClutterModelIter *temp_iter; + ClutterModel *model = NULL; + GSequenceIter *filter_next; + guint row; + + iter_default = CLUTTER_LIST_MODEL_ITER (iter); + g_assert (iter_default->seq_iter != NULL); + + model = clutter_model_iter_get_model (iter); + row = clutter_model_iter_get_row (iter); + + filter_next = g_sequence_iter_next (iter_default->seq_iter); + g_assert (filter_next != NULL); + + temp_iter = CLUTTER_LIST_MODEL (model)->priv->temp_iter; + + while (!g_sequence_iter_is_end (filter_next)) + { + CLUTTER_LIST_MODEL_ITER (temp_iter)->seq_iter = filter_next; + + if (clutter_model_filter_iter (model, temp_iter)) + { + row += 1; + break; + } + + filter_next = g_sequence_iter_next (filter_next); + } + + if (g_sequence_iter_is_end (filter_next)) + row += 1; + + /* update the iterator and return it */ + _clutter_model_iter_set_row (CLUTTER_MODEL_ITER (iter_default), row); + iter_default->seq_iter = filter_next; + + return CLUTTER_MODEL_ITER (iter_default); +} + +static ClutterModelIter * +clutter_list_model_iter_prev (ClutterModelIter *iter) +{ + ClutterListModelIter *iter_default; + ClutterModelIter *temp_iter; + ClutterModel *model; + GSequenceIter *filter_prev; + guint row; + + iter_default = CLUTTER_LIST_MODEL_ITER (iter); + g_assert (iter_default->seq_iter != NULL); + + model = clutter_model_iter_get_model (iter); + row = clutter_model_iter_get_row (iter); + + filter_prev = g_sequence_iter_prev (iter_default->seq_iter); + g_assert (filter_prev != NULL); + + temp_iter = CLUTTER_LIST_MODEL (model)->priv->temp_iter; + + while (!g_sequence_iter_is_begin (filter_prev)) + { + CLUTTER_LIST_MODEL_ITER (temp_iter)->seq_iter = filter_prev; + + if (clutter_model_filter_iter (model, temp_iter)) + { + row -= 1; + break; + } + + filter_prev = g_sequence_iter_prev (filter_prev); + } + + if (g_sequence_iter_is_begin (filter_prev)) + row -= 1; + + /* update the iterator and return it */ + _clutter_model_iter_set_row (CLUTTER_MODEL_ITER (iter_default), row); + iter_default->seq_iter = filter_prev; + + return CLUTTER_MODEL_ITER (iter_default); +} + +static ClutterModelIter * +clutter_list_model_iter_copy (ClutterModelIter *iter) +{ + ClutterListModelIter *iter_default; + ClutterListModelIter *iter_copy; + ClutterModel *model; + guint row; + + iter_default = CLUTTER_LIST_MODEL_ITER (iter); + + model = clutter_model_iter_get_model (iter); + row = clutter_model_iter_get_row (iter) - 1; + + iter_copy = g_object_new (CLUTTER_TYPE_LIST_MODEL_ITER, + "model", model, + "row", row, + NULL); + + /* this is safe, because the seq_iter pointer on the passed + * iterator will be always be overwritten in ::next or ::prev + */ + iter_copy->seq_iter = iter_default->seq_iter; + + return CLUTTER_MODEL_ITER (iter_copy); +} + +static void +clutter_list_model_iter_class_init (ClutterListModelIterClass *klass) +{ + ClutterModelIterClass *iter_class = CLUTTER_MODEL_ITER_CLASS (klass); + + iter_class->get_value = clutter_list_model_iter_get_value; + iter_class->set_value = clutter_list_model_iter_set_value; + iter_class->is_first = clutter_list_model_iter_is_first; + iter_class->is_last = clutter_list_model_iter_is_last; + iter_class->next = clutter_list_model_iter_next; + iter_class->prev = clutter_list_model_iter_prev; + iter_class->copy = clutter_list_model_iter_copy; +} + +static void +clutter_list_model_iter_init (ClutterListModelIter *iter) +{ + iter->seq_iter = NULL; +} + +/* + * ClutterListModel + */ + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterListModel, clutter_list_model, CLUTTER_TYPE_MODEL) + +static ClutterModelIter * +clutter_list_model_get_iter_at_row (ClutterModel *model, + guint row) +{ + ClutterListModel *model_default = CLUTTER_LIST_MODEL (model); + GSequence *sequence = model_default->priv->sequence; + GSequenceIter *filter_next; + gint seq_length = g_sequence_get_length (sequence); + ClutterListModelIter *retval; + gint count = -1; + + if (row >= seq_length) + return NULL; + + retval = g_object_new (CLUTTER_TYPE_LIST_MODEL_ITER, + "model", model, + "row", row, + NULL); + + /* short-circuit in case we don't have a filter in place */ + if (!clutter_model_get_filter_set (model)) + { + retval->seq_iter = g_sequence_get_iter_at_pos (sequence, row); + + return CLUTTER_MODEL_ITER (retval); + } + + filter_next = g_sequence_get_begin_iter (sequence); + g_assert (filter_next != NULL); + + while (!g_sequence_iter_is_end (filter_next)) + { + retval->seq_iter = filter_next; + + if (clutter_model_filter_iter (model, CLUTTER_MODEL_ITER (retval))) + { + /* We've found a row that is valid under the filter */ + count++; + if (count == row) + break; + } + + filter_next = g_sequence_iter_next (filter_next); + } + + if (count != row) + { + g_object_unref (retval); + return NULL; + } + return CLUTTER_MODEL_ITER (retval); +} + +static ClutterModelIter * +clutter_list_model_insert_row (ClutterModel *model, + gint index_) +{ + ClutterListModel *model_default = CLUTTER_LIST_MODEL (model); + GSequence *sequence = model_default->priv->sequence; + ClutterListModelIter *retval; + guint n_columns, i, pos; + GValue *values; + GSequenceIter *seq_iter; + + n_columns = clutter_model_get_n_columns (model); + values = g_new0 (GValue, n_columns); + + for (i = 0; i < n_columns; i++) + g_value_init (&values[i], clutter_model_get_column_type (model, i)); + + if (index_ < 0) + { + seq_iter = g_sequence_append (sequence, values); + pos = g_sequence_get_length (sequence) - 1; + } + else if (index_ == 0) + { + seq_iter = g_sequence_prepend (sequence, values); + pos = 0; + } + else + { + seq_iter = g_sequence_get_iter_at_pos (sequence, index_); + seq_iter = g_sequence_insert_before (seq_iter, values); + pos = index_; + } + + retval = g_object_new (CLUTTER_TYPE_LIST_MODEL_ITER, + "model", model, + "row", pos, + NULL); + retval->seq_iter = seq_iter; + + return CLUTTER_MODEL_ITER (retval); +} + +static void +clutter_list_model_remove_row (ClutterModel *model, + guint row) +{ + ClutterListModel *model_default = CLUTTER_LIST_MODEL (model); + GSequence *sequence = model_default->priv->sequence; + GSequenceIter *seq_iter; + guint pos = 0; + + seq_iter = g_sequence_get_begin_iter (sequence); + while (!g_sequence_iter_is_end (seq_iter)) + { + if (clutter_model_filter_row (model, pos)) + { + if (pos == row) + { + ClutterModelIter *iter; + + iter = g_object_new (CLUTTER_TYPE_LIST_MODEL_ITER, + "model", model, + "row", pos, + NULL); + CLUTTER_LIST_MODEL_ITER (iter)->seq_iter = seq_iter; + + /* the actual row is removed from the sequence inside + * the ::row-removed signal class handler, so that every + * handler connected to ::row-removed will still get + * a valid iterator, and every signal connected to + * ::row-removed with the AFTER flag will get an updated + * model + */ + g_signal_emit_by_name (model, "row-removed", iter); + + g_object_unref (iter); + + break; + } + } + + pos += 1; + seq_iter = g_sequence_iter_next (seq_iter); + } +} + +typedef struct +{ + ClutterModel *model; + guint column; + ClutterModelSortFunc func; + gpointer data; +} SortClosure; + +static gint +sort_model_default (gconstpointer a, + gconstpointer b, + gpointer data) +{ + const GValue *row_a = a; + const GValue *row_b = b; + SortClosure *clos = data; + + return clos->func (clos->model, + &row_a[clos->column], + &row_b[clos->column], + clos->data); +} + +static void +clutter_list_model_resort (ClutterModel *model, + ClutterModelSortFunc func, + gpointer data) +{ + SortClosure sort_closure = { NULL, 0, NULL, NULL }; + + sort_closure.model = model; + sort_closure.column = clutter_model_get_sorting_column (model); + sort_closure.func = func; + sort_closure.data = data; + + g_sequence_sort (CLUTTER_LIST_MODEL (model)->priv->sequence, + sort_model_default, + &sort_closure); +} + +static guint +clutter_list_model_get_n_rows (ClutterModel *model) +{ + ClutterListModel *list_model = CLUTTER_LIST_MODEL (model); + + /* short-circuit in case we don't have a filter in place */ + if (!clutter_model_get_filter_set (model)) + return g_sequence_get_length (list_model->priv->sequence); + + return CLUTTER_MODEL_CLASS (clutter_list_model_parent_class)->get_n_rows (model); +} + +static void +clutter_list_model_row_removed (ClutterModel *model, + ClutterModelIter *iter) +{ + ClutterListModelIter *iter_default; + guint i, n_columns; + GValue *values; + + n_columns = clutter_model_get_n_columns (model); + + iter_default = CLUTTER_LIST_MODEL_ITER (iter); + + values = g_sequence_get (iter_default->seq_iter); + + for (i = 0; i < n_columns; i++) + g_value_unset (&values[i]); + + g_free (values); + + g_sequence_remove (iter_default->seq_iter); + iter_default->seq_iter = NULL; +} + +static void +clutter_list_model_finalize (GObject *gobject) +{ + ClutterListModel *model = CLUTTER_LIST_MODEL (gobject); + GSequence *sequence = model->priv->sequence; + GSequenceIter *iter; + guint n_columns, i; + + n_columns = clutter_model_get_n_columns (CLUTTER_MODEL (gobject)); + + iter = g_sequence_get_begin_iter (sequence); + while (!g_sequence_iter_is_end (iter)) + { + GValue *values = g_sequence_get (iter); + + for (i = 0; i < n_columns; i++) + g_value_unset (&values[i]); + + g_free (values); + + iter = g_sequence_iter_next (iter); + } + g_sequence_free (sequence); + + G_OBJECT_CLASS (clutter_list_model_parent_class)->finalize (gobject); +} + +static void +clutter_list_model_dispose (GObject *gobject) +{ + ClutterListModel *model = CLUTTER_LIST_MODEL (gobject); + + if (model->priv->temp_iter) + { + g_object_unref (model->priv->temp_iter); + model->priv->temp_iter = NULL; + } + + G_OBJECT_CLASS (clutter_list_model_parent_class)->dispose (gobject); +} + +static void +clutter_list_model_class_init (ClutterListModelClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterModelClass *model_class = CLUTTER_MODEL_CLASS (klass); + + gobject_class->finalize = clutter_list_model_finalize; + gobject_class->dispose = clutter_list_model_dispose; + + model_class->get_iter_at_row = clutter_list_model_get_iter_at_row; + model_class->insert_row = clutter_list_model_insert_row; + model_class->remove_row = clutter_list_model_remove_row; + model_class->resort = clutter_list_model_resort; + model_class->get_n_rows = clutter_list_model_get_n_rows; + model_class->row_removed = clutter_list_model_row_removed; +} + +static void +clutter_list_model_init (ClutterListModel *model) +{ + model->priv = clutter_list_model_get_instance_private (model); + + model->priv->sequence = g_sequence_new (NULL); + model->priv->temp_iter = g_object_new (CLUTTER_TYPE_LIST_MODEL_ITER, + "model", + model, + NULL); +} + +/** + * clutter_list_model_new: + * @n_columns: number of columns in the model + * @...: @n_columns number of #GType and string pairs + * + * Creates a new default model with @n_columns columns with the types + * and names passed in. + * + * For example: + * + * + * model = clutter_list_model_new (3, + * G_TYPE_INT, "Score", + * G_TYPE_STRING, "Team", + * GDK_TYPE_PIXBUF, "Logo"); + * + * + * will create a new #ClutterModel with three columns of type int, + * string and #GdkPixbuf respectively. + * + * Note that the name of the column can be set to %NULL, in which case + * the canonical name of the type held by the column will be used as + * the title. + * + * Return value: a new #ClutterListModel + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListStore instead + */ +ClutterModel * +clutter_list_model_new (guint n_columns, + ...) +{ + ClutterModel *model; + va_list args; + gint i; + + g_return_val_if_fail (n_columns > 0, NULL); + + model = g_object_new (CLUTTER_TYPE_LIST_MODEL, NULL); + _clutter_model_set_n_columns (model, n_columns, TRUE, TRUE); + + va_start (args, n_columns); + + for (i = 0; i < n_columns; i++) + { + GType type = va_arg (args, GType); + const gchar *name = va_arg (args, gchar*); + + if (!_clutter_model_check_type (type)) + { + g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (type)); + g_object_unref (model); + model = NULL; + goto out; + } + + _clutter_model_set_column_type (model, i, type); + _clutter_model_set_column_name (model, i, name); + } + + out: + va_end (args); + return model; +} + +/** + * clutter_list_model_newv: + * @n_columns: number of columns in the model + * @types: (array length=n_columns): an array of #GType types for the columns, from first to last + * @names: (array length=n_columns): an array of names for the columns, from first to last + * + * Non-vararg version of clutter_list_model_new(). This function is + * useful for language bindings. + * + * Return value: (transfer full): a new default #ClutterModel + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListStore instead + */ +ClutterModel * +clutter_list_model_newv (guint n_columns, + GType *types, + const gchar * const names[]) +{ + ClutterModel *model; + gint i; + + g_return_val_if_fail (n_columns > 0, NULL); + + model = g_object_new (CLUTTER_TYPE_LIST_MODEL, NULL); + _clutter_model_set_n_columns (model, n_columns, TRUE, TRUE); + + for (i = 0; i < n_columns; i++) + { + if (!_clutter_model_check_type (types[i])) + { + g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (types[i])); + g_object_unref (model); + return NULL; + } + + _clutter_model_set_column_type (model, i, types[i]); + _clutter_model_set_column_name (model, i, names[i]); + } + + return model; +} diff --git a/clutter/clutter/deprecated/clutter-list-model.h b/clutter/clutter/deprecated/clutter-list-model.h new file mode 100644 index 0000000..021b3cd --- /dev/null +++ b/clutter/clutter/deprecated/clutter-list-model.h @@ -0,0 +1,95 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * Neil Jagdish Patel + * Emmanuele Bassi + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * NB: Inspiration for column storage taken from GtkListStore + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_LIST_MODEL_H__ +#define __CLUTTER_LIST_MODEL_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_LIST_MODEL (clutter_list_model_get_type ()) +#define CLUTTER_LIST_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_LIST_MODEL, ClutterListModel)) +#define CLUTTER_IS_LIST_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_LIST_MODEL)) +#define CLUTTER_LIST_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_LIST_MODEL, ClutterListModeClass)) +#define CLUTTER_IS_LIST_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_LIST_MODEL)) +#define CLUTTER_LIST_MODEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_LIST_MODEL, ClutterListModeClass)) + +typedef struct _ClutterListModel ClutterListModel; +typedef struct _ClutterListModelPrivate ClutterListModelPrivate; +typedef struct _ClutterListModelClass ClutterListModelClass; + +/** + * ClutterListModel: + * + * The #ClutterListModel struct contains only private data. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListStore instead + */ +struct _ClutterListModel +{ + /*< private >*/ + ClutterModel parent_instance; + + ClutterListModelPrivate *priv; +}; + +/** + * ClutterListModelClass: + * + * The #ClutterListModelClass struct contains only private data. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListStore instead + */ +struct _ClutterListModelClass +{ + /*< private >*/ + ClutterModelClass parent_class; +}; + +CLUTTER_DEPRECATED_IN_1_24_FOR(g_list_store_get_type) +GType clutter_list_model_get_type (void) G_GNUC_CONST; + +CLUTTER_DEPRECATED_IN_1_24_FOR(g_list_store_new) +ClutterModel *clutter_list_model_new (guint n_columns, + ...); +CLUTTER_DEPRECATED_IN_1_24_FOR(g_list_store_new) +ClutterModel *clutter_list_model_newv (guint n_columns, + GType *types, + const gchar * const names[]); + +G_END_DECLS + +#endif /* __CLUTTER_LIST_MODEL_H__ */ diff --git a/clutter/clutter/deprecated/clutter-main.h b/clutter/clutter/deprecated/clutter-main.h new file mode 100644 index 0000000..257ac5a --- /dev/null +++ b/clutter/clutter/deprecated/clutter-main.h @@ -0,0 +1,96 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2011 Intel Corp + * + * 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 . + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_MAIN_DEPRECATED_H__ +#define __CLUTTER_MAIN_DEPRECATED_H__ + +#include +#include + +G_BEGIN_DECLS + +CLUTTER_DEPRECATED_IN_1_10 +void clutter_threads_init (void); + +CLUTTER_DEPRECATED_IN_1_12 +void clutter_threads_enter (void); + +CLUTTER_DEPRECATED_IN_1_12 +void clutter_threads_leave (void); + +CLUTTER_DEPRECATED_IN_1_6 +guint clutter_threads_add_frame_source (guint fps, + GSourceFunc func, + gpointer data); +CLUTTER_DEPRECATED_IN_1_6 +guint clutter_threads_add_frame_source_full (gint priority, + guint fps, + GSourceFunc func, + gpointer data, + GDestroyNotify notify); + +CLUTTER_DEPRECATED_IN_1_8_FOR(clutter_stage_set_motion_events_enabled) +void clutter_set_motion_events_enabled (gboolean enable); + +CLUTTER_DEPRECATED_IN_1_8_FOR(clutter_stage_get_motion_events_enabled) +gboolean clutter_get_motion_events_enabled (void); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_stage_ensure_redraw) +void clutter_redraw (ClutterStage *stage); + +CLUTTER_DEPRECATED_IN_1_10_FOR(cogl_pango_font_map_clear_glyph_cache) +void clutter_clear_glyph_cache (void); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_backend_set_font_options) +void clutter_set_font_flags (ClutterFontFlags flags); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_backend_get_font_options) +ClutterFontFlags clutter_get_font_flags (void); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_device_manager_get_device) +ClutterInputDevice * clutter_get_input_device_for_id (gint id_); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_input_device_grab) +void clutter_grab_pointer_for_device (ClutterActor *actor, + gint id_); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_input_device_ungrab) +void clutter_ungrab_pointer_for_device (gint id_); + +CLUTTER_DEPRECATED_IN_1_10 +void clutter_set_default_frame_rate (guint frames_per_sec); + +CLUTTER_DEPRECATED_IN_1_10 +gulong clutter_get_timestamp (void); + +CLUTTER_DEPRECATED_IN_1_10 +gboolean clutter_get_debug_enabled (void); + +CLUTTER_DEPRECATED_IN_1_10 +gboolean clutter_get_show_fps (void); + +G_END_DECLS + +#endif /* __CLUTTER_MAIN_DEPRECATED_H__ */ diff --git a/clutter/clutter/deprecated/clutter-media.c b/clutter/clutter/deprecated/clutter-media.c new file mode 100644 index 0000000..7336a78 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-media.c @@ -0,0 +1,666 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By: Matthew Allum + * Emmanuele Bassi + * + * Copyright (C) 2006 OpenedHand + * Copyright (C) 2009 Intel Corp. + * + * 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 . + */ + +/** + * SECTION:clutter-media + * @short_description: An interface for controlling playback of media data + * + * #ClutterMedia is an interface for controlling playback of media sources. + * + * Clutter core does not provide an implementation of this interface, but + * other integration libraries like Clutter-GStreamer implement it to offer + * a uniform API for applications. + * + * #ClutterMedia is available since Clutter 0.2 + * + * #ClutterMedia is deprecated since Clutter 1.12. Use the Clutter-GStreamer + * API directly instead. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS + +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-marshal.h" +#include "clutter-media.h" +#include "clutter-main.h" +#include "clutter-private.h" /* for DBG */ + +enum +{ + EOS_SIGNAL, + ERROR_SIGNAL, /* can't be called 'ERROR' otherwise it clashes with wingdi.h */ + + LAST_SIGNAL +}; + +static guint media_signals[LAST_SIGNAL] = { 0, }; + +typedef ClutterMediaIface ClutterMediaInterface; + +G_DEFINE_INTERFACE (ClutterMedia, clutter_media, G_TYPE_OBJECT); + +static void +clutter_media_default_init (ClutterMediaInterface *iface) +{ + GParamSpec *pspec = NULL; + + /** + * ClutterMedia:uri: + * + * The location of a media file, expressed as a valid URI. + * + * Since: 0.2 + * + * Deprecated: 1.12 + */ + pspec = g_param_spec_string ("uri", + P_("URI"), + P_("URI of a media file"), + NULL, + CLUTTER_PARAM_READWRITE | + G_PARAM_DEPRECATED); + g_object_interface_install_property (iface, pspec); + + /** + * ClutterMedia:playing: + * + * Whether the #ClutterMedia actor is playing. + * + * Since: 0.2 + * + * Deprecated: 1.12 + */ + pspec = g_param_spec_boolean ("playing", + P_("Playing"), + P_("Whether the actor is playing"), + FALSE, + CLUTTER_PARAM_READWRITE | + G_PARAM_DEPRECATED); + g_object_interface_install_property (iface, pspec); + + /** + * ClutterMedia:progress: + * + * The current progress of the playback, as a normalized + * value between 0.0 and 1.0. + * + * Since: 1.0 + * + * Deprecated: 1.12 + */ + pspec = g_param_spec_double ("progress", + P_("Progress"), + P_("Current progress of the playback"), + 0.0, 1.0, 0.0, + CLUTTER_PARAM_READWRITE | + G_PARAM_DEPRECATED); + g_object_interface_install_property (iface, pspec); + + /** + * ClutterMedia:subtitle-uri: + * + * The location of a subtitle file, expressed as a valid URI. + * + * Since: 1.2 + * + * Deprecated: 1.12 + */ + pspec = g_param_spec_string ("subtitle-uri", + P_("Subtitle URI"), + P_("URI of a subtitle file"), + NULL, + CLUTTER_PARAM_READWRITE | + G_PARAM_DEPRECATED); + g_object_interface_install_property (iface, pspec); + + /** + * ClutterMedia:subtitle-font-name: + * + * The font used to display subtitles. The font description has to + * follow the same grammar as the one recognized by + * pango_font_description_from_string(). + * + * Since: 1.2 + * + * Deprecated: 1.12 + */ + pspec = g_param_spec_string ("subtitle-font-name", + P_("Subtitle Font Name"), + P_("The font used to display subtitles"), + NULL, + CLUTTER_PARAM_READWRITE | + G_PARAM_DEPRECATED); + g_object_interface_install_property (iface, pspec); + + /** + * ClutterMedia:audio-volume: + * + * The volume of the audio, as a normalized value between + * 0.0 and 1.0. + * + * Since: 1.0 + * + * Deprecated: 1.12 + */ + pspec = g_param_spec_double ("audio-volume", + P_("Audio Volume"), + P_("The volume of the audio"), + 0.0, 1.0, 0.5, + CLUTTER_PARAM_READWRITE | + G_PARAM_DEPRECATED); + g_object_interface_install_property (iface, pspec); + + /** + * ClutterMedia:can-seek: + * + * Whether the current stream is seekable. + * + * Since: 0.2 + * + * Deprecated: 1.12 + */ + pspec = g_param_spec_boolean ("can-seek", + P_("Can Seek"), + P_("Whether the current stream is seekable"), + FALSE, + CLUTTER_PARAM_READABLE | + G_PARAM_DEPRECATED); + g_object_interface_install_property (iface, pspec); + + /** + * ClutterMedia:buffer-fill: + * + * The fill level of the buffer for the current stream, + * as a value between 0.0 and 1.0. + * + * Since: 1.0 + * + * Deprecated: 1.12 + */ + pspec = g_param_spec_double ("buffer-fill", + P_("Buffer Fill"), + P_("The fill level of the buffer"), + 0.0, 1.0, 0.0, + CLUTTER_PARAM_READABLE | + G_PARAM_DEPRECATED); + g_object_interface_install_property (iface, pspec); + + /** + * ClutterMedia:duration: + * + * The duration of the current stream, in seconds + * + * Since: 0.2 + * + * Deprecated: 1.12 + */ + pspec = g_param_spec_double ("duration", + P_("Duration"), + P_("The duration of the stream, in seconds"), + 0, G_MAXDOUBLE, 0, + CLUTTER_PARAM_READABLE); + g_object_interface_install_property (iface, pspec); + + /** + * ClutterMedia::eos: + * @media: the #ClutterMedia instance that received the signal + * + * The ::eos signal is emitted each time the media stream ends. + * + * Since: 0.2 + * + * Deprecated: 1.12 + */ + media_signals[EOS_SIGNAL] = + g_signal_new (I_("eos"), + CLUTTER_TYPE_MEDIA, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterMediaIface, eos), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + /** + * ClutterMedia::error: + * @media: the #ClutterMedia instance that received the signal + * @error: the #GError + * + * The ::error signal is emitted each time an error occurred. + * + * Since: 0.2 + * + * Deprecated: 1.12 + */ + media_signals[ERROR_SIGNAL] = + g_signal_new (I_("error"), + CLUTTER_TYPE_MEDIA, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterMediaIface, error), + NULL, NULL, + _clutter_marshal_VOID__BOXED, + G_TYPE_NONE, 1, + G_TYPE_ERROR); +} + + +/** + * clutter_media_set_uri: + * @media: a #ClutterMedia + * @uri: the URI of the media stream + * + * Sets the URI of @media to @uri. + * + * Since: 0.2 + * + * Deprecated: 1.12 + */ +void +clutter_media_set_uri (ClutterMedia *media, + const gchar *uri) +{ + g_return_if_fail (CLUTTER_IS_MEDIA(media)); + + g_object_set (G_OBJECT (media), "uri", uri, NULL); +} + +/** + * clutter_media_get_uri: + * @media: a #ClutterMedia + * + * Retrieves the URI from @media. + * + * Return value: the URI of the media stream. Use g_free() + * to free the returned string + * + * Since: 0.2 + * + * Deprecated: 1.12 + */ +gchar * +clutter_media_get_uri (ClutterMedia *media) +{ + gchar *retval = NULL; + + g_return_val_if_fail (CLUTTER_IS_MEDIA(media), NULL); + + g_object_get (G_OBJECT (media), "uri", &retval, NULL); + + return retval; +} + +/** + * clutter_media_set_playing: + * @media: a #ClutterMedia + * @playing: %TRUE to start playing + * + * Starts or stops playing of @media. + + * The implementation might be asynchronous, so the way to know whether + * the actual playing state of the @media is to use the #GObject::notify + * signal on the #ClutterMedia:playing property and then retrieve the + * current state with clutter_media_get_playing(). ClutterGstVideoTexture + * in clutter-gst is an example of such an asynchronous implementation. + * + * Since: 0.2 + * + * Deprecated: 1.12 + */ +void +clutter_media_set_playing (ClutterMedia *media, + gboolean playing) +{ + g_return_if_fail (CLUTTER_IS_MEDIA(media)); + + g_object_set (G_OBJECT (media), "playing", playing, NULL); +} + +/** + * clutter_media_get_playing: + * @media: A #ClutterMedia object + * + * Retrieves the playing status of @media. + * + * Return value: %TRUE if playing, %FALSE if stopped. + * + * Since: 0.2 + * + * Deprecated: 1.12 + */ +gboolean +clutter_media_get_playing (ClutterMedia *media) +{ + gboolean is_playing = FALSE; + + g_return_val_if_fail (CLUTTER_IS_MEDIA (media), FALSE); + + g_object_get (G_OBJECT (media), "playing", &is_playing, NULL); + + return is_playing; +} + +/** + * clutter_media_set_progress: + * @media: a #ClutterMedia + * @progress: the progress of the playback, between 0.0 and 1.0 + * + * Sets the playback progress of @media. The @progress is + * a normalized value between 0.0 (begin) and 1.0 (end). + * + * Since: 1.0 + * + * Deprecated: 1.12 + */ +void +clutter_media_set_progress (ClutterMedia *media, + gdouble progress) +{ + g_return_if_fail (CLUTTER_IS_MEDIA (media)); + + g_object_set (G_OBJECT (media), "progress", progress, NULL); +} + +/** + * clutter_media_get_progress: + * @media: a #ClutterMedia + * + * Retrieves the playback progress of @media. + * + * Return value: the playback progress, between 0.0 and 1.0 + * + * Since: 1.0 + * + * Deprecated: 1.12 + */ +gdouble +clutter_media_get_progress (ClutterMedia *media) +{ + gdouble retval = 0.0; + + g_return_val_if_fail (CLUTTER_IS_MEDIA (media), 0); + + g_object_get (G_OBJECT (media), "progress", &retval, NULL); + + return retval; +} + +/** + * clutter_media_set_subtitle_uri: + * @media: a #ClutterMedia + * @uri: the URI of a subtitle file + * + * Sets the location of a subtitle file to display while playing @media. + * + * Since: 1.2 + * + * Deprecated: 1.12 + */ +void +clutter_media_set_subtitle_uri (ClutterMedia *media, + const char *uri) +{ + g_return_if_fail (CLUTTER_IS_MEDIA (media)); + + g_object_set (G_OBJECT (media), "subtitle-uri", uri, NULL); +} + +/** + * clutter_media_get_subtitle_uri: + * @media: a #ClutterMedia + * + * Retrieves the URI of the subtitle file in use. + * + * Return value: the URI of the subtitle file. Use g_free() + * to free the returned string + * + * Since: 1.2 + * + * Deprecated: 1.12 + */ +gchar * +clutter_media_get_subtitle_uri (ClutterMedia *media) +{ + gchar *retval = NULL; + + g_return_val_if_fail (CLUTTER_IS_MEDIA(media), NULL); + + g_object_get (G_OBJECT (media), "subtitle-uri", &retval, NULL); + + return retval; +} + +/** + * clutter_media_set_subtitle_font_name: + * @media: a #ClutterMedia + * @font_name: a font name, or %NULL to set the default font name + * + * Sets the font used by the subtitle renderer. The @font_name string must be + * either %NULL, which means that the default font name of the underlying + * implementation will be used; or must follow the grammar recognized by + * pango_font_description_from_string() like: + * + * |[ + * clutter_media_set_subtitle_font_name (media, "Sans 24pt"); + * ]| + * + * Since: 1.2 + * + * Deprecated: 1.12 + */ +void +clutter_media_set_subtitle_font_name (ClutterMedia *media, + const char *font_name) +{ + g_return_if_fail (CLUTTER_IS_MEDIA (media)); + + g_object_set (G_OBJECT (media), "subtitle-font-name", font_name, NULL); +} + +/** + * clutter_media_get_subtitle_font_name: + * @media: a #ClutterMedia + * + * Retrieves the font name currently used. + * + * Return value: a string containing the font name. Use g_free() + * to free the returned string + * + * Since: 1.2 + * + * Deprecated: 1.12 + */ +gchar * +clutter_media_get_subtitle_font_name (ClutterMedia *media) +{ + gchar *retval = NULL; + + g_return_val_if_fail (CLUTTER_IS_MEDIA(media), NULL); + + g_object_get (G_OBJECT (media), "subtitle-font-name", &retval, NULL); + + return retval; +} + +/** + * clutter_media_set_audio_volume: + * @media: a #ClutterMedia + * @volume: the volume as a double between 0.0 and 1.0 + * + * Sets the playback volume of @media to @volume. + * + * Since: 1.0 + * + * Deprecated: 1.12 + */ +void +clutter_media_set_audio_volume (ClutterMedia *media, + gdouble volume) +{ + g_return_if_fail (CLUTTER_IS_MEDIA(media)); + + g_object_set (G_OBJECT (media), "audio-volume", volume, NULL); +} + +/** + * clutter_media_get_audio_volume: + * @media: a #ClutterMedia + * + * Retrieves the playback volume of @media. + * + * Return value: The playback volume between 0.0 and 1.0 + * + * Since: 1.0 + * + * Deprecated: 1.12 + */ +gdouble +clutter_media_get_audio_volume (ClutterMedia *media) +{ + gdouble retval = 0.0; + + g_return_val_if_fail (CLUTTER_IS_MEDIA (media), 0.0); + + g_object_get (G_OBJECT (media), "audio-volume", &retval, NULL); + + return retval; +} + +/** + * clutter_media_get_can_seek: + * @media: a #ClutterMedia + * + * Retrieves whether @media is seekable or not. + * + * Return value: %TRUE if @media can seek, %FALSE otherwise. + * + * Since: 0.2 + * + * Deprecated: 1.12 + */ +gboolean +clutter_media_get_can_seek (ClutterMedia *media) +{ + gboolean retval = FALSE; + + g_return_val_if_fail (CLUTTER_IS_MEDIA (media), FALSE); + + g_object_get (G_OBJECT (media), "can-seek", &retval, NULL); + + return retval; +} + +/** + * clutter_media_get_buffer_fill: + * @media: a #ClutterMedia + * + * Retrieves the amount of the stream that is buffered. + * + * Return value: the fill level, between 0.0 and 1.0 + * + * Since: 1.0 + * + * Deprecated: 1.12 + */ +gdouble +clutter_media_get_buffer_fill (ClutterMedia *media) +{ + gdouble retval = 0.0; + + g_return_val_if_fail (CLUTTER_IS_MEDIA (media), 0); + + g_object_get (G_OBJECT (media), "buffer-fill", &retval, NULL); + + return retval; +} + +/** + * clutter_media_get_duration: + * @media: a #ClutterMedia + * + * Retrieves the duration of the media stream that @media represents. + * + * Return value: the duration of the media stream, in seconds + * + * Since: 0.2 + * + * Deprecated: 1.12 + */ +gdouble +clutter_media_get_duration (ClutterMedia *media) +{ + gdouble retval = 0; + + g_return_val_if_fail (CLUTTER_IS_MEDIA(media), 0); + + g_object_get (G_OBJECT (media), "duration", &retval, NULL); + + return retval; +} + +/* helper funcs */ + +/** + * clutter_media_set_filename: + * @media: a #ClutterMedia + * @filename: A filename + * + * Sets the source of @media using a file path. + * + * Since: 0.2 + * + * Deprecated: 1.12 + */ +void +clutter_media_set_filename (ClutterMedia *media, + const gchar *filename) +{ + gchar *uri; + GError *uri_error = NULL; + + if (!g_path_is_absolute (filename)) + { + gchar *abs_path; + + abs_path = g_build_filename (g_get_current_dir (), filename, NULL); + uri = g_filename_to_uri (abs_path, NULL, &uri_error); + g_free (abs_path); + } + else + uri = g_filename_to_uri (filename, NULL, &uri_error); + + if (uri_error) + { + g_signal_emit (media, media_signals[ERROR_SIGNAL], 0, uri_error); + g_error_free (uri_error); + return; + } + + clutter_media_set_uri (media, uri); + + g_free (uri); +} diff --git a/clutter/clutter/deprecated/clutter-media.h b/clutter/clutter/deprecated/clutter-media.h new file mode 100644 index 0000000..ad1068a --- /dev/null +++ b/clutter/clutter/deprecated/clutter-media.h @@ -0,0 +1,121 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By: Matthew Allum + * Emmanuele Bassi + * + * Copyright (C) 2006 OpenedHand + * Copyright (C) 2009 Intel Corp. + * + * 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 . + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_MEDIA_H__ +#define __CLUTTER_MEDIA_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_MEDIA (clutter_media_get_type ()) +#define CLUTTER_MEDIA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_MEDIA, ClutterMedia)) +#define CLUTTER_IS_MEDIA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_MEDIA)) +#define CLUTTER_MEDIA_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), CLUTTER_TYPE_MEDIA, ClutterMediaIface)) + +typedef struct _ClutterMedia ClutterMedia; /* dummy typedef */ +typedef struct _ClutterMediaIface ClutterMediaIface; + +/** + * ClutterMedia: + * + * #ClutterMedia is an opaque structure whose members cannot be directly + * accessed + * + * Since: 0.2 + */ + +/** + * ClutterMediaIface: + * @eos: handler for the #ClutterMedia::eos signal + * @error: handler for the #ClutterMedia::error signal + * + * Interface vtable for #ClutterMedia implementations + * + * Since: 0.2 + */ +struct _ClutterMediaIface +{ + /*< private >*/ + GTypeInterface base_iface; + + /*< public >*/ + /* signals */ + void (* eos) (ClutterMedia *media); + void (* error) (ClutterMedia *media, + const GError *error); +}; + +CLUTTER_DEPRECATED_IN_1_12 +GType clutter_media_get_type (void) G_GNUC_CONST; + +CLUTTER_DEPRECATED_IN_1_12 +void clutter_media_set_uri (ClutterMedia *media, + const gchar *uri); +CLUTTER_DEPRECATED_IN_1_12 +gchar * clutter_media_get_uri (ClutterMedia *media); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_media_set_filename (ClutterMedia *media, + const gchar *filename); + +CLUTTER_DEPRECATED_IN_1_12 +void clutter_media_set_playing (ClutterMedia *media, + gboolean playing); +CLUTTER_DEPRECATED_IN_1_12 +gboolean clutter_media_get_playing (ClutterMedia *media); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_media_set_progress (ClutterMedia *media, + gdouble progress); +CLUTTER_DEPRECATED_IN_1_12 +gdouble clutter_media_get_progress (ClutterMedia *media); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_media_set_subtitle_uri (ClutterMedia *media, + const gchar *uri); +CLUTTER_DEPRECATED_IN_1_12 +gchar * clutter_media_get_subtitle_uri (ClutterMedia *media); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_media_set_subtitle_font_name (ClutterMedia *media, + const char *font_name); +CLUTTER_DEPRECATED_IN_1_12 +gchar * clutter_media_get_subtitle_font_name (ClutterMedia *media); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_media_set_audio_volume (ClutterMedia *media, + gdouble volume); +CLUTTER_DEPRECATED_IN_1_12 +gdouble clutter_media_get_audio_volume (ClutterMedia *media); +CLUTTER_DEPRECATED_IN_1_12 +gboolean clutter_media_get_can_seek (ClutterMedia *media); +CLUTTER_DEPRECATED_IN_1_12 +gdouble clutter_media_get_buffer_fill (ClutterMedia *media); +CLUTTER_DEPRECATED_IN_1_12 +gdouble clutter_media_get_duration (ClutterMedia *media); + +G_END_DECLS + +#endif /* __CLUTTER_MEDIA_H__ */ diff --git a/clutter/clutter/deprecated/clutter-model-private.h b/clutter/clutter/deprecated/clutter-model-private.h new file mode 100644 index 0000000..2791c83 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-model-private.h @@ -0,0 +1,52 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * Neil Jagdish Patel + * Emmanuele Bassi + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __CLUTTER_MODEL_PRIVATE_H__ +#define __CLUTTER_MODEL_PRIVATE_H__ + +#include "clutter-types.h" +#include "clutter-model.h" + +G_BEGIN_DECLS + +void _clutter_model_set_n_columns (ClutterModel *model, + gint n_columns, + gboolean set_types, + gboolean set_names); +gboolean _clutter_model_check_type (GType gtype); + +void _clutter_model_set_column_type (ClutterModel *model, + gint column, + GType gtype); +void _clutter_model_set_column_name (ClutterModel *model, + gint column, + const gchar *name); + +void _clutter_model_iter_set_row (ClutterModelIter *iter, + guint row); + +G_END_DECLS + +#endif /* __CLUTTER_MODEL_PRIVATE_H__ */ diff --git a/clutter/clutter/deprecated/clutter-model.c b/clutter/clutter/deprecated/clutter-model.c new file mode 100644 index 0000000..5cd8c07 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-model.c @@ -0,0 +1,2477 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * Neil Jagdish Patel + * Emmanuele Bassi + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * NB: Inspiration for column storage taken from GtkListStore + */ + +/** + * SECTION:clutter-model + * @short_description: A generic model implementation + * + * #ClutterModel is a generic list model API which can be used to implement + * the model-view-controller architectural pattern in Clutter. + * + * The #ClutterModel class is a list model which can accept most GObject + * types as a column type. + * + * ## Creating a simple ClutterModel + * + * The example below shows how to create a simple list model. + * + * |[ + * enum + * { + * COLUMN_INT, + * COLUMN_STRING, + * + * N_COLUMNS + * }; + * + * { + * ClutterModel *model; + * gint i; + * + * model = clutter_list_model_new (N_COLUMNS, + * // column type, title + * G_TYPE_INT, "my integers", + * G_TYPE_STRING, "my strings"); + * for (i = 0; i < 10; i++) + * { + * gchar *string = g_strdup_printf ("String %d", i); + * clutter_model_append (model, + * COLUMN_INT, i, + * COLUMN_STRING, string, + * -1); + * g_free (string); + * } + * + * + * } + * ]| + * + * ## Iterating through a ClutterModel + * + * Iterating through the model consists of retrieving a new #ClutterModelIter + * pointing to the starting row, and calling clutter_model_iter_next() or + * clutter_model_iter_prev() to move forward or backwards, repectively. + * + * A valid #ClutterModelIter represents the position between two rows in the + * model. For example, the "first" iterator represents the gap immediately + * before the first row, and the "last" iterator represents the gap immediately + * after the last row. In an empty sequence, the first and last iterators are + * the same. + * + * |[ + * enum + * { + * COLUMN_INT, + * COLUMN_STRING. + * + * N_COLUMNS + * }; + * + * { + * ClutterModel *model; + * ClutterModelIter *iter = NULL; + * + * // fill the model + * model = populate_model (); + * + * // get the iterator for the first row in the model + * iter = clutter_model_get_first_iter (model); + * while (!clutter_model_iter_is_last (iter)) + * { + * print_row (iter); + * + * iter = clutter_model_iter_next (iter); + * } + * + * // Make sure to unref the iter + * g_object_unref (iter); + * } + * ]| + * + * #ClutterModel is an abstract class. Clutter provides a list model + * implementation called #ClutterListModel which has been optimised + * for insertion and look up in sorted lists. + * + * #ClutterModel is available since Clutter 0.6 + * + * ## ClutterModel custom properties for ClutterScript + * + * #ClutterModel defines a custom property "columns" for #ClutterScript + * which allows defining the column names and types. It also defines a custom + * "rows" property which allows filling the #ClutterModel with some + * data. + * + * The definition below will create a #ClutterListModel with three + * columns: the first one with name "Name" and containing strings; the + * second one with name "Score" and containing integers; the third one with + * name "Icon" and containing #ClutterTextures. The model is filled + * with three rows. A row can be defined either with an array that holds + * all columns of a row, or an object that holds "column-name" : + * "column-value" pairs. + * + * |[ + * { + * "type" : "ClutterListModel", + * "id" : "teams-model", + * "columns" : [ + * [ "Name", "gchararray" ], + * [ "Score", "gint" ], + * [ "Icon", "ClutterTexture" ] + * ], + * "rows" : [ + * [ "Team 1", 42, { "type" : "ClutterTexture", "filename" : "team1.png" } ], + * [ "Team 2", 23, "team2-icon-script-id" ], + * { "Name" : "Team 3", "Icon" : "team3-icon-script-id" } + * ] + * } + * + * Deprecated: 1.24: You should implement the #GListModel interface on your + * own storage data type instead. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include +#include +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS + +#include "clutter-model.h" +#include "clutter-model-private.h" + +#include "clutter-marshal.h" +#include "clutter-private.h" +#include "clutter-debug.h" +#include "clutter-scriptable.h" +#include "clutter-script-private.h" + +enum +{ + PROP_0, + + PROP_FILTER_SET +}; + +enum +{ + ROW_ADDED, + ROW_REMOVED, + ROW_CHANGED, + + SORT_CHANGED, + FILTER_CHANGED, + + LAST_SIGNAL +}; + +static guint model_signals[LAST_SIGNAL] = { 0, }; + +struct _ClutterModelPrivate +{ + GType *column_types; + gchar **column_names; + + /* we use an integer here because we want to be able to use -1 as a + * guard value, to allow calling set_names() and set_types() from + * sub-classes of ClutterModel. see bug: + * + * http://bugzilla.openedhand.com/show_bug.cgi?id=2032 + * + * for a reference. + */ + gint n_columns; + + ClutterModelFilterFunc filter_func; + gpointer filter_data; + GDestroyNotify filter_notify; + + gint sort_column; + ClutterModelSortFunc sort_func; + gpointer sort_data; + GDestroyNotify sort_notify; +}; + +static void clutter_scriptable_iface_init (ClutterScriptableIface *iface); + +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (ClutterModel, clutter_model, G_TYPE_OBJECT, + G_ADD_PRIVATE (ClutterModel) + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_SCRIPTABLE, + clutter_scriptable_iface_init)) + +static GType +clutter_model_real_get_column_type (ClutterModel *model, + guint column) +{ + ClutterModelPrivate *priv = model->priv; + + if (column >= clutter_model_get_n_columns (model)) + return G_TYPE_INVALID; + + return priv->column_types[column]; +} + +static const gchar * +clutter_model_real_get_column_name (ClutterModel *model, + guint column) +{ + ClutterModelPrivate *priv = model->priv; + + if (column >= clutter_model_get_n_columns (model)) + return NULL; + + if (priv->column_names && priv->column_names[column]) + return priv->column_names[column]; + + return g_type_name (priv->column_types[column]); +} + +static guint +clutter_model_real_get_n_columns (ClutterModel *model) +{ + ClutterModelPrivate *priv = model->priv; + + if (priv->n_columns < 0) + return 0; + + return priv->n_columns; +} + +static guint +clutter_model_real_get_n_rows (ClutterModel *model) +{ + ClutterModelIter *iter; + guint row_count; + + g_return_val_if_fail (CLUTTER_IS_MODEL (model), 0); + + iter = clutter_model_get_first_iter (model); + if (iter == NULL) + return 0; + + row_count = 0; + while (!clutter_model_iter_is_last (iter)) + { + if (clutter_model_filter_iter (model, iter)) + row_count += 1; + + iter = clutter_model_iter_next (iter); + } + + g_object_unref (iter); + + return row_count; +} + +static void +clutter_model_finalize (GObject *object) +{ + ClutterModelPrivate *priv = CLUTTER_MODEL (object)->priv; + gint i; + + if (priv->sort_notify) + priv->sort_notify (priv->sort_data); + + if (priv->filter_notify) + priv->filter_notify (priv->filter_data); + + g_free (priv->column_types); + + if (priv->column_names != NULL) + { + /* the column_names vector might have holes in it, so we need + * to use the columns number to clear up everything + */ + for (i = 0; i < priv->n_columns; i++) + g_free (priv->column_names[i]); + + g_free (priv->column_names); + } + + G_OBJECT_CLASS (clutter_model_parent_class)->finalize (object); +} + +static void +clutter_model_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterModelPrivate *priv = CLUTTER_MODEL (gobject)->priv; + + switch (prop_id) + { + case PROP_FILTER_SET: + g_value_set_boolean (value, priv->filter_func != NULL); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_model_class_init (ClutterModelClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GParamSpec *pspec; + + gobject_class->get_property = clutter_model_get_property; + gobject_class->finalize = clutter_model_finalize; + + klass->get_column_name = clutter_model_real_get_column_name; + klass->get_column_type = clutter_model_real_get_column_type; + klass->get_n_columns = clutter_model_real_get_n_columns; + klass->get_n_rows = clutter_model_real_get_n_rows; + + /** + * ClutterModel:filter-set: + * + * Whether the #ClutterModel has a filter set + * + * This property is set to %TRUE if a filter function has been + * set using clutter_model_set_filter() + * + * Since: 1.0 + * + * Deprecated: 1.24: Use #GListModel instead + */ + pspec = g_param_spec_boolean ("filter-set", + "Filter Set", + "Whether the model has a filter", + FALSE, + CLUTTER_PARAM_READABLE); + g_object_class_install_property (gobject_class, PROP_FILTER_SET, pspec); + + /** + * ClutterModel::row-added: + * @model: the #ClutterModel on which the signal is emitted + * @iter: a #ClutterModelIter pointing to the new row + * + * The ::row-added signal is emitted when a new row has been added. + * The data on the row has already been set when the ::row-added signal + * has been emitted. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ + model_signals[ROW_ADDED] = + g_signal_new ("row-added", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterModelClass, row_added), + NULL, NULL, + _clutter_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CLUTTER_TYPE_MODEL_ITER); + /** + * ClutterModel::row-removed: + * @model: the #ClutterModel on which the signal is emitted + * @iter: a #ClutterModelIter pointing to the removed row + * + * The ::row-removed signal is emitted when a row has been removed. + * The data on the row pointed by the passed iterator is still valid + * when the ::row-removed signal has been emitted. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ + model_signals[ROW_REMOVED] = + g_signal_new ("row-removed", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterModelClass, row_removed), + NULL, NULL, + _clutter_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CLUTTER_TYPE_MODEL_ITER); + /** + * ClutterModel::row-changed: + * @model: the #ClutterModel on which the signal is emitted + * @iter: a #ClutterModelIter pointing to the changed row + * + * The ::row-removed signal is emitted when a row has been changed. + * The data on the row has already been updated when the ::row-changed + * signal has been emitted. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ + model_signals[ROW_CHANGED] = + g_signal_new ("row-changed", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterModelClass, row_changed), + NULL, NULL, + _clutter_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CLUTTER_TYPE_MODEL_ITER); + /** + * ClutterModel::sort-changed: + * @model: the #ClutterModel on which the signal is emitted + * + * The ::sort-changed signal is emitted after the model has been sorted + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ + model_signals[SORT_CHANGED] = + g_signal_new ("sort-changed", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterModelClass, sort_changed), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + /** + * ClutterModel::filter-changed: + * @model: the #ClutterModel on which the signal is emitted + * + * The ::filter-changed signal is emitted when a new filter has been applied + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ + model_signals[FILTER_CHANGED] = + g_signal_new ("filter-changed", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterModelClass, filter_changed), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +clutter_model_init (ClutterModel *self) +{ + ClutterModelPrivate *priv; + + self->priv = priv = clutter_model_get_instance_private (self); + + priv->n_columns = -1; + priv->column_types = NULL; + priv->column_names = NULL; + + priv->filter_func = NULL; + priv->filter_data = NULL; + priv->filter_notify = NULL; + + priv->sort_column = -1; + priv->sort_func = NULL; + priv->sort_data = NULL; + priv->sort_notify = NULL; +} + +/* XXX - is this whitelist really necessary? we accept every fundamental + * type. + */ +gboolean +_clutter_model_check_type (GType gtype) +{ + gint i = 0; + static const GType type_list[] = + { + G_TYPE_BOOLEAN, + G_TYPE_CHAR, + G_TYPE_UCHAR, + G_TYPE_INT, + G_TYPE_UINT, + G_TYPE_LONG, + G_TYPE_ULONG, + G_TYPE_INT64, + G_TYPE_UINT64, + G_TYPE_ENUM, + G_TYPE_FLAGS, + G_TYPE_FLOAT, + G_TYPE_DOUBLE, + G_TYPE_STRING, + G_TYPE_POINTER, + G_TYPE_BOXED, + G_TYPE_OBJECT, + G_TYPE_INVALID + }; + + if (! G_TYPE_IS_VALUE_TYPE (gtype)) + return FALSE; + + while (type_list[i] != G_TYPE_INVALID) + { + if (g_type_is_a (gtype, type_list[i])) + return TRUE; + i++; + } + return FALSE; +} + + +typedef struct { + gchar *name; + GType type; +} ColumnInfo; + +static gboolean +clutter_model_parse_custom_node (ClutterScriptable *scriptable, + ClutterScript *script, + GValue *value, + const gchar *name, + JsonNode *node) +{ + if (strcmp (name, "columns") == 0) + { + GSList *columns = NULL; + GList *elements, *l; + + if (JSON_NODE_TYPE (node) != JSON_NODE_ARRAY) + return FALSE; + + elements = json_array_get_elements (json_node_get_array (node)); + + for (l = elements; l != NULL; l = l->next) + { + JsonNode *child_node = l->data; + JsonArray *array = json_node_get_array (child_node); + ColumnInfo *cinfo; + const gchar *column_name; + const gchar *type_name; + + if (JSON_NODE_TYPE (node) != JSON_NODE_ARRAY || + json_array_get_length (array) != 2) + { + g_warning ("A column must be an array of " + "[\"column-name\", \"GType-name\"] pairs"); + return FALSE; + } + + column_name = json_array_get_string_element (array, 0); + type_name = json_array_get_string_element (array, 1); + + cinfo = g_slice_new0 (ColumnInfo); + cinfo->name = g_strdup (column_name); + cinfo->type = clutter_script_get_type_from_name (script, type_name); + + columns = g_slist_prepend (columns, cinfo); + } + + g_list_free (elements); + + g_value_init (value, G_TYPE_POINTER); + g_value_set_pointer (value, g_slist_reverse (columns)); + + return TRUE; + } + else if (strcmp (name, "rows") == 0) + { + GSList *rows = NULL; + GList *elements, *l; + + if (JSON_NODE_TYPE (node) != JSON_NODE_ARRAY) + return FALSE; + + /* + * at this point we have no information about the column types, so + * we just copy the json elements and resolve them in the + * set_custom_property method + */ + elements = json_array_get_elements (json_node_get_array (node)); + for (l = elements; l != NULL; l = l->next) + rows = g_slist_prepend (rows, json_node_copy (l->data)); + g_list_free (elements); + + g_value_init (value, G_TYPE_POINTER); + g_value_set_pointer (value, g_slist_reverse (rows)); + + return TRUE; + } + return FALSE; +} + +static void +clutter_model_set_custom_property (ClutterScriptable *scriptable, + ClutterScript *script, + const gchar *name, + const GValue *value) +{ + if (strcmp (name, "columns") == 0) + { + ClutterModel *model = CLUTTER_MODEL (scriptable); + GSList *columns, *l; + guint n_columns; + gint i; + + columns = g_value_get_pointer (value); + n_columns = g_slist_length (columns); + + _clutter_model_set_n_columns (model, n_columns, TRUE, TRUE); + + for (i = 0, l = columns; l != NULL; l = l->next, i++) + { + ColumnInfo *cinfo = l->data; + + _clutter_model_set_column_name (model, i, cinfo->name); + _clutter_model_set_column_type (model, i, cinfo->type); + + g_free (cinfo->name); + g_slice_free (ColumnInfo, cinfo); + } + + g_slist_free (columns); + } + else if (strcmp (name, "rows") == 0) + { + ClutterModel *model = CLUTTER_MODEL (scriptable); + GSList *rows, *l; + guint n_columns, row = 0; + + rows = g_value_get_pointer (value); + n_columns = clutter_model_get_n_columns (model); + + for (l = rows; l; l = l->next) + { + JsonNode *node = l->data; + guint *columns = NULL, i, n_values = 0; + GValue *values = NULL; + + if (JSON_NODE_TYPE (node) == JSON_NODE_ARRAY) + { + JsonArray *array = json_node_get_array (node); + + if (json_array_get_length (array) != n_columns) + { + g_warning ("Row %d contains the wrong count of columns", + g_slist_position (rows, l) + 1); + row += 1; + continue; + } + + /* array more requires all columns */ + n_values = n_columns; + + columns = g_new (guint, n_values); + values = g_new0 (GValue, n_values); + + for (i = 0; i < n_values; i++) + { + GType column_type; + const gchar *column_name; + + column_type = clutter_model_get_column_type (model, i); + column_name = clutter_model_get_column_name (model, i); + + columns[i] = i; + g_value_init (&values[i], column_type); + + _clutter_script_parse_node (script, &values[i], column_name, + json_array_get_element (array, i), + NULL); + } + } + else if (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT) + { + JsonObject *object = json_node_get_object (node); + GList *members, *m; + guint column = 0; + + /* object mode does not require all columns */ + n_values = json_object_get_size (object); + + columns = g_new (guint, n_values); + values = g_new0 (GValue, n_values); + + members = json_object_get_members (object); + for (m = members; m; m = m->next) + { + const gchar *mname = m->data; + + for (i = 0; i < clutter_model_get_n_columns (model); i++) + { + const gchar *cname; + + cname = clutter_model_get_column_name (model, i); + if (strcmp (mname, cname) == 0) + { + JsonNode *member; + GType col_type; + const gchar *col_name; + + member = json_object_get_member (object, mname); + + col_type = clutter_model_get_column_type (model, i); + col_name = clutter_model_get_column_name (model, i); + + columns[column] = i; + g_value_init (&values[column], col_type); + + _clutter_script_parse_node (script, &values[column], + col_name, member, + NULL); + break; + } + } + + column += 1; + } + } + else + { + row += 1; + continue; + } + + clutter_model_insertv (model, row, n_values, columns, values); + + g_free (values); + g_free (columns); + json_node_free (node); + + row += 1; + } + g_slist_free (rows); + } +} + + +static void +clutter_scriptable_iface_init (ClutterScriptableIface *iface) +{ + iface->parse_custom_node = clutter_model_parse_custom_node; + iface->set_custom_property = clutter_model_set_custom_property; +} + +/** + * clutter_model_resort: + * @model: a #ClutterModel + * + * Force a resort on the @model. This function should only be + * used by subclasses of #ClutterModel. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +void +clutter_model_resort (ClutterModel *model) +{ + ClutterModelPrivate *priv; + ClutterModelClass *klass; + + g_return_if_fail (CLUTTER_IS_MODEL (model)); + priv = model->priv; + + klass = CLUTTER_MODEL_GET_CLASS (model); + + if (klass->resort) + klass->resort (model, priv->sort_func, priv->sort_data); +} + +/** + * clutter_model_filter_row: + * @model: a #ClutterModel + * @row: the row to filter + * + * Checks whether @row should be filtered or not using the + * filtering function set on @model. + * + * This function should be used only by subclasses of #ClutterModel. + * + * Return value: %TRUE if the row should be displayed, + * %FALSE otherwise + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +gboolean +clutter_model_filter_row (ClutterModel *model, + guint row) +{ + ClutterModelPrivate *priv; + ClutterModelIter *iter; + gboolean res = TRUE; + + g_return_val_if_fail (CLUTTER_IS_MODEL (model), TRUE); + + priv = model->priv; + + if (!priv->filter_func) + return TRUE; + + iter = clutter_model_get_iter_at_row (model, row); + if (iter == NULL) + return FALSE; + + res = priv->filter_func (model, iter, priv->filter_data); + + g_object_unref (iter); + + return res; +} + +/** + * clutter_model_filter_iter: + * @model: a #ClutterModel + * @iter: the row to filter + * + * Checks whether the row pointer by @iter should be filtered or not using + * the filtering function set on @model. + * + * This function should be used only by subclasses of #ClutterModel. + * + * Return value: %TRUE if the row should be displayed, + * %FALSE otherwise + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +gboolean +clutter_model_filter_iter (ClutterModel *model, + ClutterModelIter *iter) +{ + ClutterModelPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_MODEL (model), TRUE); + g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), TRUE); + + priv = model->priv; + + if (!priv->filter_func) + return TRUE; + + return priv->filter_func (model, iter, priv->filter_data); +} + +/*< private > + * clutter_model_set_n_columns: + * @model: a #ClutterModel + * @n_columns: number of columns + * @set_types: set the columns type + * @set_names: set the columns name + * + * Sets the number of columns in @model to @n_columns. If @set_types + * or @set_names are %TRUE, initialises the columns type and name + * arrays as well. + * + * This function can only be called once. + * + * Deprecated: 1.24: Use #GListModel instead + */ +void +_clutter_model_set_n_columns (ClutterModel *model, + gint n_columns, + gboolean set_types, + gboolean set_names) +{ + ClutterModelPrivate *priv = model->priv; + + if (priv->n_columns > 0 && priv->n_columns != n_columns) + return; + + priv->n_columns = n_columns; + + if (set_types && !priv->column_types) + priv->column_types = g_new0 (GType, n_columns); + + if (set_names && !priv->column_names) + priv->column_names = g_new0 (gchar*, n_columns); +} + +/*< private > + * _clutter_model_set_column_type: + * @model: a #ClutterModel + * @column: column index + * @gtype: type of the column + * + * Sets the type of @column inside @model + */ +void +_clutter_model_set_column_type (ClutterModel *model, + gint column, + GType gtype) +{ + ClutterModelPrivate *priv = model->priv; + + priv->column_types[column] = gtype; +} + +/*< private > + * _clutter_model_set_column_name: + * @model: a #ClutterModel + * @column: column index + * @name: name of the column, or %NULL + * + * Sets the name of @column inside @model + */ +void +_clutter_model_set_column_name (ClutterModel *model, + gint column, + const gchar *name) +{ + ClutterModelPrivate *priv = model->priv; + + priv->column_names[column] = g_strdup (name); +} + +/** + * clutter_model_set_types: + * @model: a #ClutterModel + * @n_columns: number of columns for the model + * @types: (array length=n_columns): an array of #GType types + * + * Sets the types of the columns inside a #ClutterModel. + * + * This function is meant primarily for #GObjects that inherit from + * #ClutterModel, and should only be used when contructing a #ClutterModel. + * It will not work after the initial creation of the #ClutterModel. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +void +clutter_model_set_types (ClutterModel *model, + guint n_columns, + GType *types) +{ + ClutterModelPrivate *priv; + gint i; + + g_return_if_fail (CLUTTER_IS_MODEL (model)); + g_return_if_fail (n_columns > 0); + + priv = model->priv; + + g_return_if_fail (priv->n_columns < 0 || priv->n_columns == n_columns); + g_return_if_fail (priv->column_types == NULL); + + _clutter_model_set_n_columns (model, n_columns, TRUE, FALSE); + + for (i = 0; i < n_columns; i++) + { + if (!_clutter_model_check_type (types[i])) + { + g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (types[i])); + return; + } + + _clutter_model_set_column_type (model, i, types[i]); + } +} + +/** + * clutter_model_set_names: + * @model: a #ClutterModel + * @n_columns: the number of column names + * @names: (array length=n_columns): an array of strings + * + * Assigns a name to the columns of a #ClutterModel. + * + * This function is meant primarily for #GObjects that inherit from + * #ClutterModel, and should only be used when contructing a #ClutterModel. + * It will not work after the initial creation of the #ClutterModel. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +void +clutter_model_set_names (ClutterModel *model, + guint n_columns, + const gchar * const names[]) +{ + ClutterModelPrivate *priv; + gint i; + + g_return_if_fail (CLUTTER_IS_MODEL (model)); + g_return_if_fail (n_columns > 0); + + priv = model->priv; + + g_return_if_fail (priv->n_columns < 0 || priv->n_columns == n_columns); + g_return_if_fail (priv->column_names == NULL); + + _clutter_model_set_n_columns (model, n_columns, FALSE, TRUE); + + for (i = 0; i < n_columns; i++) + _clutter_model_set_column_name (model, i, names[i]); +} + +/** + * clutter_model_get_n_columns: + * @model: a #ClutterModel + * + * Retrieves the number of columns inside @model. + * + * Return value: the number of columns + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +guint +clutter_model_get_n_columns (ClutterModel *model) +{ + g_return_val_if_fail (CLUTTER_IS_MODEL (model), 0); + + return CLUTTER_MODEL_GET_CLASS (model)->get_n_columns (model); +} + +/** + * clutter_model_appendv: + * @model: a #ClutterModel + * @n_columns: the number of columns and values + * @columns: (array length=n_columns): a vector with the columns to set + * @values: (array length=n_columns): a vector with the values + * + * Creates and appends a new row to the #ClutterModel, setting the row + * values for the given @columns upon creation. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +void +clutter_model_appendv (ClutterModel *model, + guint n_columns, + guint *columns, + GValue *values) +{ + ClutterModelPrivate *priv; + ClutterModelIter *iter; + gint i; + gboolean resort = FALSE; + + g_return_if_fail (CLUTTER_IS_MODEL (model)); + g_return_if_fail (n_columns <= clutter_model_get_n_columns (model)); + g_return_if_fail (columns != NULL); + g_return_if_fail (values != NULL); + + priv = model->priv; + + iter = CLUTTER_MODEL_GET_CLASS (model)->insert_row (model, -1); + g_assert (CLUTTER_IS_MODEL_ITER (iter)); + + for (i = 0; i < n_columns; i++) + { + if (priv->sort_column == columns[i]) + resort = TRUE; + + clutter_model_iter_set_value (iter, columns[i], &values[i]); + } + + g_signal_emit (model, model_signals[ROW_ADDED], 0, iter); + + if (resort) + clutter_model_resort (model); + + g_object_unref (iter); +} + +/* forward declaration */ +static void clutter_model_iter_set_internal_valist (ClutterModelIter *iter, + va_list args); + +/** + * clutter_model_append: + * @model: a #ClutterModel + * @...: pairs of column number and value, terminated with -1 + * + * Creates and appends a new row to the #ClutterModel, setting the + * row values upon creation. For example, to append a new row where + * column 0 is type %G_TYPE_INT and column 1 is of type %G_TYPE_STRING: + * + * + * ClutterModel *model; + * model = clutter_model_default_new (2, + * G_TYPE_INT, "Score", + * G_TYPE_STRING, "Team"); + * clutter_model_append (model, 0, 42, 1, "Team #1", -1); + * + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +void +clutter_model_append (ClutterModel *model, + ...) +{ + ClutterModelIter *iter; + va_list args; + + g_return_if_fail (CLUTTER_IS_MODEL (model)); + + iter = CLUTTER_MODEL_GET_CLASS (model)->insert_row (model, -1); + g_assert (CLUTTER_IS_MODEL_ITER (iter)); + + /* do not emit the ::row-changed signal */ + va_start (args, model); + clutter_model_iter_set_internal_valist (iter, args); + va_end (args); + + g_signal_emit (model, model_signals[ROW_ADDED], 0, iter); + + g_object_unref (iter); +} + +/** + * clutter_model_prependv: + * @model: a #ClutterModel + * @n_columns: the number of columns and values to set + * @columns: (array length=n_columns): a vector containing the columns to set + * @values: (array length=n_columns): a vector containing the values for the cells + * + * Creates and prepends a new row to the #ClutterModel, setting the row + * values for the given @columns upon creation. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +void +clutter_model_prependv (ClutterModel *model, + guint n_columns, + guint *columns, + GValue *values) +{ + ClutterModelPrivate *priv; + ClutterModelIter *iter; + gint i; + gboolean resort = FALSE; + + g_return_if_fail (CLUTTER_IS_MODEL (model)); + g_return_if_fail (n_columns <= clutter_model_get_n_columns (model)); + g_return_if_fail (columns != NULL); + g_return_if_fail (values != NULL); + + priv = model->priv; + + iter = CLUTTER_MODEL_GET_CLASS (model)->insert_row (model, 0); + g_assert (CLUTTER_IS_MODEL_ITER (iter)); + + for (i = 0; i < n_columns; i++) + { + if (priv->sort_column == columns[i]) + resort = TRUE; + + clutter_model_iter_set_value (iter, columns[i], &values[i]); + } + + g_signal_emit (model, model_signals[ROW_ADDED], 0, iter); + + if (resort) + clutter_model_resort (model); + + g_object_unref (iter); +} + +/** + * clutter_model_prepend: + * @model: a #ClutterModel + * @...: pairs of column number and value, terminated with -1 + * + * Creates and prepends a new row to the #ClutterModel, setting the row + * values upon creation. For example, to prepend a new row where column 0 + * is type %G_TYPE_INT and column 1 is of type %G_TYPE_STRING: + * + * + * ClutterModel *model; + * model = clutter_model_default_new (2, + * G_TYPE_INT, "Score", + * G_TYPE_STRING, "Team"); + * clutter_model_prepend (model, 0, 42, 1, "Team #1", -1); + * + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +void +clutter_model_prepend (ClutterModel *model, + ...) +{ + ClutterModelIter *iter; + va_list args; + + g_return_if_fail (CLUTTER_IS_MODEL (model)); + + iter = CLUTTER_MODEL_GET_CLASS (model)->insert_row (model, 0); + g_assert (CLUTTER_IS_MODEL_ITER (iter)); + + va_start (args, model); + clutter_model_iter_set_internal_valist (iter, args); + va_end (args); + + g_signal_emit (model, model_signals[ROW_ADDED], 0, iter); + + g_object_unref (iter); +} + + +/** + * clutter_model_insert: + * @model: a #ClutterModel + * @row: the position to insert the new row + * @...: pairs of column number and value, terminated with -1 + * + * Inserts a new row to the #ClutterModel at @row, setting the row + * values upon creation. For example, to insert a new row at index 100, + * where column 0 is type %G_TYPE_INT and column 1 is of type + * %G_TYPE_STRING: + * + * + * ClutterModel *model; + * model = clutter_model_default_new (2, + * G_TYPE_INT, "Score", + * G_TYPE_STRING, "Team"); + * clutter_model_insert (model, 3, 0, 42, 1, "Team #1", -1); + * + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +void +clutter_model_insert (ClutterModel *model, + guint row, + ...) +{ + ClutterModelIter *iter; + va_list args; + + g_return_if_fail (CLUTTER_IS_MODEL (model)); + + iter = CLUTTER_MODEL_GET_CLASS (model)->insert_row (model, row); + g_assert (CLUTTER_IS_MODEL_ITER (iter)); + + /* set_valist() will call clutter_model_resort() if one of the + * passed columns matches the model sorting column index + */ + va_start (args, row); + clutter_model_iter_set_internal_valist (iter, args); + va_end (args); + + g_signal_emit (model, model_signals[ROW_ADDED], 0, iter); + + g_object_unref (iter); +} + +/** + * clutter_model_insertv: + * @model: a #ClutterModel + * @row: row index + * @n_columns: the number of columns and values to set + * @columns: (array length=n_columns): a vector containing the columns to set + * @values: (array length=n_columns): a vector containing the values for the cells + * + * Inserts data at @row into the #ClutterModel, setting the row + * values for the given @columns upon creation. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +void +clutter_model_insertv (ClutterModel *model, + guint row, + guint n_columns, + guint *columns, + GValue *values) +{ + ClutterModelPrivate *priv; + ClutterModelIter *iter; + gint i; + gboolean resort = FALSE; + + g_return_if_fail (CLUTTER_IS_MODEL (model)); + g_return_if_fail (n_columns <= clutter_model_get_n_columns (model)); + g_return_if_fail (columns != NULL); + g_return_if_fail (values != NULL); + + priv = model->priv; + + iter = CLUTTER_MODEL_GET_CLASS (model)->insert_row (model, row); + g_assert (CLUTTER_IS_MODEL_ITER (iter)); + + for (i = 0; i < n_columns; i++) + { + if (priv->sort_column == columns[i]) + resort = TRUE; + + clutter_model_iter_set_value (iter, columns[i], &values[i]); + } + + g_signal_emit (model, model_signals[ROW_ADDED], 0, iter); + + if (resort) + clutter_model_resort (model); + + g_object_unref (iter); +} + +/** + * clutter_model_insert_value: + * @model: a #ClutterModel + * @row: position of the row to modify + * @column: column to modify + * @value: new value for the cell + * + * Sets the data in the cell specified by @iter and @column. The type of + * @value must be convertable to the type of the column. If the row does + * not exist then it is created. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +void +clutter_model_insert_value (ClutterModel *model, + guint row, + guint column, + const GValue *value) +{ + ClutterModelPrivate *priv; + ClutterModelClass *klass; + ClutterModelIter *iter; + gboolean added = FALSE; + + g_return_if_fail (CLUTTER_IS_MODEL (model)); + + priv = model->priv; + klass = CLUTTER_MODEL_GET_CLASS (model); + + iter = klass->get_iter_at_row (model, row); + if (!iter) + { + iter = klass->insert_row (model, row); + added = TRUE; + } + + g_assert (CLUTTER_IS_MODEL_ITER (iter)); + + clutter_model_iter_set_value (iter, column, value); + + if (added) + g_signal_emit (model, model_signals[ROW_ADDED], 0, iter); + + if (priv->sort_column == column) + clutter_model_resort (model); + + g_object_unref (iter); +} + +/** + * clutter_model_remove: + * @model: a #ClutterModel + * @row: position of row to remove + * + * Removes the row at the given position from the model. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +void +clutter_model_remove (ClutterModel *model, + guint row) +{ + ClutterModelClass *klass; + + g_return_if_fail (CLUTTER_IS_MODEL (model)); + + klass = CLUTTER_MODEL_GET_CLASS (model); + if (klass->remove_row) + klass->remove_row (model, row); +} + +/** + * clutter_model_get_column_name: + * @model: #ClutterModel + * @column: the column number + * + * Retrieves the name of the @column + * + * Return value: the name of the column. The model holds the returned + * string, and it should not be modified or freed + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +const gchar * +clutter_model_get_column_name (ClutterModel *model, + guint column) +{ + ClutterModelClass *klass; + + g_return_val_if_fail (CLUTTER_IS_MODEL (model), NULL); + + if (column >= clutter_model_get_n_columns (model)) + { + g_warning ("%s: Invalid column id value %d\n", G_STRLOC, column); + return NULL; + } + + klass = CLUTTER_MODEL_GET_CLASS (model); + if (klass->get_column_name) + return klass->get_column_name (model, column); + + return NULL; +} + +/** + * clutter_model_get_column_type: + * @model: #ClutterModel + * @column: the column number + * + * Retrieves the type of the @column. + * + * Return value: the type of the column. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +GType +clutter_model_get_column_type (ClutterModel *model, + guint column) +{ + ClutterModelClass *klass; + + g_return_val_if_fail (CLUTTER_IS_MODEL (model), G_TYPE_INVALID); + + if (column >= clutter_model_get_n_columns (model)) + { + g_warning ("%s: Invalid column id value %d\n", G_STRLOC, column); + return G_TYPE_INVALID; + } + + klass = CLUTTER_MODEL_GET_CLASS (model); + if (klass->get_column_type) + return klass->get_column_type (model, column); + + return G_TYPE_INVALID; +} + +/** + * clutter_model_get_iter_at_row: + * @model: a #ClutterModel + * @row: position of the row to retrieve + * + * Retrieves a #ClutterModelIter representing the row at the given index. + * + * If a filter function has been set using clutter_model_set_filter() + * then the @model implementation will return the first non filtered + * row. + * + * Return value: (transfer full): A new #ClutterModelIter, or %NULL if @row was + * out of bounds. When done using the iterator object, call g_object_unref() + * to deallocate its resources + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +ClutterModelIter * +clutter_model_get_iter_at_row (ClutterModel *model, + guint row) +{ + ClutterModelClass *klass; + + g_return_val_if_fail (CLUTTER_IS_MODEL (model), NULL); + + klass = CLUTTER_MODEL_GET_CLASS (model); + if (klass->get_iter_at_row) + return klass->get_iter_at_row (model, row); + + return NULL; +} + + +/** + * clutter_model_get_first_iter: + * @model: a #ClutterModel + * + * Retrieves a #ClutterModelIter representing the first non-filtered + * row in @model. + * + * Return value: (transfer full): A new #ClutterModelIter. + * Call g_object_unref() when done using it + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +ClutterModelIter * +clutter_model_get_first_iter (ClutterModel *model) +{ + ClutterModelIter *retval; + + g_return_val_if_fail (CLUTTER_IS_MODEL (model), NULL); + + retval = clutter_model_get_iter_at_row (model, 0); + if (retval != NULL) + { + g_assert (clutter_model_filter_iter (model, retval) != FALSE); + g_assert (clutter_model_iter_get_row (retval) == 0); + } + + return retval; +} + +/** + * clutter_model_get_last_iter: + * @model: a #ClutterModel + * + * Retrieves a #ClutterModelIter representing the last non-filtered + * row in @model. + * + * Return value: (transfer full): A new #ClutterModelIter. + * Call g_object_unref() when done using it + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +ClutterModelIter * +clutter_model_get_last_iter (ClutterModel *model) +{ + ClutterModelIter *retval; + guint length; + + g_return_val_if_fail (CLUTTER_IS_MODEL (model), NULL); + + length = clutter_model_get_n_rows (model); + retval = clutter_model_get_iter_at_row (model, length - 1); + if (retval != NULL) + g_assert (clutter_model_filter_iter (model, retval) != FALSE); + + return retval; +} + +/** + * clutter_model_get_n_rows: + * @model: a #ClutterModel + * + * Retrieves the number of rows inside @model, eventually taking + * into account any filtering function set using clutter_model_set_filter(). + * + * Return value: The length of the @model. If there is a filter set, then + * the length of the filtered @model is returned. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +guint +clutter_model_get_n_rows (ClutterModel *model) +{ + g_return_val_if_fail (CLUTTER_IS_MODEL (model), 0); + + return CLUTTER_MODEL_GET_CLASS (model)->get_n_rows (model); +} + +/** + * clutter_model_set_sorting_column: + * @model: a #ClutterModel + * @column: the column of the @model to sort, or -1 + * + * Sets the model to sort by @column. If @column is a negative value + * the sorting column will be unset. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +void +clutter_model_set_sorting_column (ClutterModel *model, + gint column) +{ + ClutterModelPrivate *priv; + + g_return_if_fail (CLUTTER_IS_MODEL (model)); + priv = model->priv; + + /* The extra comparison for >= 0 is because column gets promoted to + unsigned in the second comparison */ + if (column >= 0 && column >= clutter_model_get_n_columns (model)) + { + g_warning ("%s: Invalid column id value %d\n", G_STRLOC, column); + return; + } + + priv->sort_column = column; + + if (priv->sort_column >= 0) + clutter_model_resort (model); + + g_signal_emit (model, model_signals[SORT_CHANGED], 0); +} + +/** + * clutter_model_get_sorting_column: + * @model: a #ClutterModel + * + * Retrieves the number of column used for sorting the @model. + * + * Return value: a column number, or -1 if the model is not sorted + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +gint +clutter_model_get_sorting_column (ClutterModel *model) +{ + g_return_val_if_fail (CLUTTER_IS_MODEL (model), -1); + + return model->priv->sort_column; +} + +/** + * clutter_model_foreach: + * @model: a #ClutterModel + * @func: (scope call): a #ClutterModelForeachFunc + * @user_data: user data to pass to @func + * + * Calls @func for each row in the model. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +void +clutter_model_foreach (ClutterModel *model, + ClutterModelForeachFunc func, + gpointer user_data) +{ + ClutterModelIter *iter; + + g_return_if_fail (CLUTTER_IS_MODEL (model)); + + iter = clutter_model_get_first_iter (model); + if (!iter) + return; + + while (!clutter_model_iter_is_last (iter)) + { + if (clutter_model_filter_iter (model, iter)) + { + if (!func (model, iter, user_data)) + break; + } + + iter = clutter_model_iter_next (iter); + } + + g_object_unref (iter); +} + +/** + * clutter_model_set_sort: + * @model: a #ClutterModel + * @column: the column to sort on + * @func: (allow-none): a #ClutterModelSortFunc, or #NULL + * @user_data: user data to pass to @func, or #NULL + * @notify: destroy notifier of @user_data, or #NULL + * + * Sorts @model using the given sorting function. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +void +clutter_model_set_sort (ClutterModel *model, + gint column, + ClutterModelSortFunc func, + gpointer user_data, + GDestroyNotify notify) +{ + ClutterModelPrivate *priv; + + g_return_if_fail (CLUTTER_IS_MODEL (model)); + g_return_if_fail ((func != NULL && column >= 0) || + (func == NULL && column == -1)); + + priv = model->priv; + + if (priv->sort_notify) + priv->sort_notify (priv->sort_data); + + priv->sort_func = func; + priv->sort_data = user_data; + priv->sort_notify = notify; + + /* This takes care of calling _model_sort & emitting the signal*/ + clutter_model_set_sorting_column (model, column); +} + +/** + * clutter_model_set_filter: + * @model: a #ClutterModel + * @func: (allow-none): a #ClutterModelFilterFunc, or #NULL + * @user_data: user data to pass to @func, or #NULL + * @notify: destroy notifier of @user_data, or #NULL + * + * Filters the @model using the given filtering function. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +void +clutter_model_set_filter (ClutterModel *model, + ClutterModelFilterFunc func, + gpointer user_data, + GDestroyNotify notify) +{ + ClutterModelPrivate *priv; + + g_return_if_fail (CLUTTER_IS_MODEL (model)); + priv = model->priv; + + if (priv->filter_notify) + priv->filter_notify (priv->filter_data); + + priv->filter_func = func; + priv->filter_data = user_data; + priv->filter_notify = notify; + + g_signal_emit (model, model_signals[FILTER_CHANGED], 0); + g_object_notify (G_OBJECT (model), "filter-set"); +} + +/** + * clutter_model_get_filter_set: + * @model: a #ClutterModel + * + * Returns whether the @model has a filter in place, set + * using clutter_model_set_filter() + * + * Return value: %TRUE if a filter is set + * + * Since: 1.0 + * + * Deprecated: 1.24: Use #GListModel instead + */ +gboolean +clutter_model_get_filter_set (ClutterModel *model) +{ + g_return_val_if_fail (CLUTTER_IS_MODEL (model), FALSE); + + return model->priv->filter_func != NULL; +} + +/* + * ClutterModelIter Object + */ + +/** + * SECTION:clutter-model-iter + * @short_description: Iterates through a model + * + * #ClutterModelIter is an object used for iterating through all the rows + * of a #ClutterModel. It allows setting and getting values on the row + * which is currently pointing at. + * + * A #ClutterModelIter represents a position between two elements + * of the sequence. For example, the iterator returned by + * clutter_model_get_first_iter() represents the gap immediately before + * the first row of the #ClutterModel, and the iterator returned by + * clutter_model_get_last_iter() represents the gap immediately after the + * last row. + * + * A #ClutterModelIter can only be created by a #ClutterModel implementation + * and it is valid as long as the model does not change. + * + * #ClutterModelIter is available since Clutter 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ + +struct _ClutterModelIterPrivate +{ + ClutterModel *model; + + gint row; +}; + +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterModelIter, clutter_model_iter, G_TYPE_OBJECT) + +enum +{ + ITER_PROP_0, + + ITER_PROP_MODEL, + ITER_PROP_ROW +}; + +static ClutterModel * +clutter_model_iter_real_get_model (ClutterModelIter *iter) +{ + return iter->priv->model; +} + +static guint +clutter_model_iter_real_get_row (ClutterModelIter *iter) +{ + return iter->priv->row; +} + +/* private function */ +void +_clutter_model_iter_set_row (ClutterModelIter *iter, + guint row) +{ + iter->priv->row = row; +} + +static void +clutter_model_iter_get_value_unimplemented (ClutterModelIter *iter, + guint column, + GValue *value) +{ + g_warning ("%s: Iterator of type '%s' does not implement the " + "ClutterModelIter::get_value() virtual function", + G_STRLOC, + g_type_name (G_OBJECT_TYPE (iter))); +} + +static void +clutter_model_iter_set_value_unimplemented (ClutterModelIter *iter, + guint column, + const GValue *value) +{ + g_warning ("%s: Iterator of type '%s' does not implement the " + "ClutterModelIter::set_value() virtual function", + G_STRLOC, + g_type_name (G_OBJECT_TYPE (iter))); +} + +static gboolean +clutter_model_iter_is_first_unimplemented (ClutterModelIter *iter) +{ + g_warning ("%s: Iterator of type '%s' does not implement the " + "ClutterModelIter::is_first() virtual function", + G_STRLOC, + g_type_name (G_OBJECT_TYPE (iter))); + return FALSE; +} + +static gboolean +clutter_model_iter_is_last_unimplemented (ClutterModelIter *iter) +{ + g_warning ("%s: Iterator of type '%s' does not implement the " + "ClutterModelIter::is_last() virtual function", + G_STRLOC, + g_type_name (G_OBJECT_TYPE (iter))); + return FALSE; +} + +static ClutterModelIter * +clutter_model_iter_next_unimplemented (ClutterModelIter *iter) +{ + g_warning ("%s: Iterator of type '%s' does not implement the " + "ClutterModelIter::next() virtual function", + G_STRLOC, + g_type_name (G_OBJECT_TYPE (iter))); + return NULL; +} + +static ClutterModelIter * +clutter_model_iter_prev_unimplemented (ClutterModelIter *iter) +{ + g_warning ("%s: Iterator of type '%s' does not implement the " + "ClutterModelIter::prev() virtual function", + G_STRLOC, + g_type_name (G_OBJECT_TYPE (iter))); + return NULL; +} + +static ClutterModelIter * +clutter_model_iter_copy_unimplemented (ClutterModelIter *iter) +{ + g_warning ("%s: Iterator of type '%s' does not implement the " + "ClutterModelIter::copy() virtual function", + G_STRLOC, + g_type_name (G_OBJECT_TYPE (iter))); + return NULL; +} + +static void +clutter_model_iter_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterModelIter *iter = CLUTTER_MODEL_ITER (object); + ClutterModelIterPrivate *priv = iter->priv; + + switch (prop_id) + { + case ITER_PROP_MODEL: + g_value_set_object (value, priv->model); + break; + case ITER_PROP_ROW: + g_value_set_uint (value, priv->row); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_model_iter_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterModelIter *iter = CLUTTER_MODEL_ITER (object); + ClutterModelIterPrivate *priv = iter->priv; + + switch (prop_id) + { + case ITER_PROP_MODEL: + priv->model = g_value_get_object (value); + break; + case ITER_PROP_ROW: + priv->row = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_model_iter_class_init (ClutterModelIterClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GParamSpec *pspec; + + gobject_class->get_property = clutter_model_iter_get_property; + gobject_class->set_property = clutter_model_iter_set_property; + + klass->get_model = clutter_model_iter_real_get_model; + klass->get_row = clutter_model_iter_real_get_row; + klass->is_first = clutter_model_iter_is_first_unimplemented; + klass->is_last = clutter_model_iter_is_last_unimplemented; + klass->next = clutter_model_iter_next_unimplemented; + klass->prev = clutter_model_iter_prev_unimplemented; + klass->get_value = clutter_model_iter_get_value_unimplemented; + klass->set_value = clutter_model_iter_set_value_unimplemented; + klass->copy = clutter_model_iter_copy_unimplemented; + + /* Properties */ + + /** + * ClutterModelIter:model: + * + * A reference to the #ClutterModel that this iter belongs to. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ + pspec = g_param_spec_object ("model", + "Model", + "The model to which the iterator belongs to", + CLUTTER_TYPE_MODEL, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, ITER_PROP_MODEL, pspec); + + /** + * ClutterModelIter:row: + * + * The row number to which this iter points to. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ + pspec = g_param_spec_uint ("row", + "Row", + "The row to which the iterator points to", + 0, G_MAXUINT, 0, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, ITER_PROP_ROW, pspec); +} + +static void +clutter_model_iter_init (ClutterModelIter *self) +{ + self->priv = clutter_model_iter_get_instance_private (self); +} + +/* + * Public functions + */ + +static inline void +clutter_model_iter_set_value_internal (ClutterModelIter *iter, + guint column, + const GValue *value) +{ + CLUTTER_MODEL_ITER_GET_CLASS (iter)->set_value (iter, column, value); +} + +static void +clutter_model_iter_set_internal_valist (ClutterModelIter *iter, + va_list args) +{ + ClutterModelIterPrivate *priv = iter->priv; + ClutterModel *model = priv->model; + guint column = 0; + gboolean sort = FALSE; + + g_assert (CLUTTER_IS_MODEL (model)); + + column = va_arg (args, gint); + + while (column != -1) + { + GValue value = G_VALUE_INIT; + gchar *error = NULL; + GType col_type; + + if (column >= clutter_model_get_n_columns (model)) + { + g_warning ("%s: Invalid column number %d added to iter " + "(remember to end you list of columns with a -1)", + G_STRLOC, column); + break; + } + + col_type = clutter_model_get_column_type (model, column); + + G_VALUE_COLLECT_INIT (&value, col_type, args, 0, &error); + if (error) + { + g_warning ("%s: %s", G_STRLOC, error); + g_free (error); + + /* Leak value as it might not be in a sane state */ + break; + } + + clutter_model_iter_set_value_internal (iter, column, &value); + + g_value_unset (&value); + + if (column == clutter_model_get_sorting_column (model)) + sort = TRUE; + + column = va_arg (args, gint); + } + + if (sort) + clutter_model_resort (model); +} + +static void inline +clutter_model_iter_emit_row_changed (ClutterModelIter *iter) +{ + ClutterModelIterPrivate *priv = iter->priv; + ClutterModel *model = priv->model; + + g_assert (CLUTTER_IS_MODEL (model)); + + g_signal_emit (model, model_signals[ROW_CHANGED], 0, iter); +} + +/** + * clutter_model_iter_set_valist: + * @iter: a #ClutterModelIter + * @args: va_list of column/value pairs, terminiated by -1 + * + * See clutter_model_iter_set(); this version takes a va_list for language + * bindings. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +void +clutter_model_iter_set_valist (ClutterModelIter *iter, + va_list args) +{ + g_return_if_fail (CLUTTER_IS_MODEL_ITER (iter)); + + clutter_model_iter_set_internal_valist (iter, args); + clutter_model_iter_emit_row_changed (iter); +} + +/** + * clutter_model_iter_get: + * @iter: a #ClutterModelIter + * @...: a list of column/return location pairs, terminated by -1 + * + * Gets the value of one or more cells in the row referenced by @iter. The + * variable argument list should contain integer column numbers, each column + * column number followed by a place to store the value being retrieved. The + * list is terminated by a -1. + * + * For example, to get a value from column 0 with type %G_TYPE_STRING use: + * + * clutter_model_iter_get (iter, 0, &place_string_here, -1); + * + * + * where place_string_here is a gchar* to be filled with the string. If + * appropriate, the returned values have to be freed or unreferenced. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +void +clutter_model_iter_get (ClutterModelIter *iter, + ...) +{ + va_list args; + + g_return_if_fail (CLUTTER_IS_MODEL_ITER (iter)); + + va_start (args, iter); + clutter_model_iter_get_valist (iter, args); + va_end (args); +} + +static inline void +clutter_model_iter_get_value_internal (ClutterModelIter *iter, + guint column, + GValue *value) +{ + CLUTTER_MODEL_ITER_GET_CLASS (iter)->get_value (iter, column, value); +} + +/** + * clutter_model_iter_get_value: + * @iter: a #ClutterModelIter + * @column: column number to retrieve the value from + * @value: (out): an empty #GValue to set + * + * Sets an initializes @value to that at @column. When done with @value, + * g_value_unset() needs to be called to free any allocated memory. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +void +clutter_model_iter_get_value (ClutterModelIter *iter, + guint column, + GValue *value) +{ + ClutterModel *model; + + g_return_if_fail (CLUTTER_IS_MODEL_ITER (iter)); + + model = iter->priv->model; + + if (G_VALUE_TYPE (value) == G_TYPE_INVALID) + g_value_init (value, clutter_model_get_column_type (model, column)); + + CLUTTER_MODEL_ITER_GET_CLASS (iter)->get_value (iter, column, value); +} + +/** + * clutter_model_iter_get_valist: + * @iter: a #ClutterModelIter + * @args: a list of column/return location pairs, terminated by -1 + * + * See clutter_model_iter_get(). This version takes a va_list for language + * bindings. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +void +clutter_model_iter_get_valist (ClutterModelIter *iter, + va_list args) +{ + ClutterModelIterPrivate *priv; + ClutterModel *model; + guint column = 0; + + g_return_if_fail (CLUTTER_IS_MODEL_ITER (iter)); + + priv = iter->priv; + model = priv->model; + g_assert (CLUTTER_IS_MODEL (model)); + + column = va_arg (args, gint); + + while (column != -1) + { + GValue value = G_VALUE_INIT; + gchar *error = NULL; + GType col_type; + + if (column >= clutter_model_get_n_columns (model)) + { + g_warning ("%s: Invalid column number %d added to iter " + "(remember to end you list of columns with a -1)", + G_STRLOC, column); + break; + } + + col_type = clutter_model_get_column_type (model, column); + g_value_init (&value, col_type); + + clutter_model_iter_get_value_internal (iter, column, &value); + + G_VALUE_LCOPY (&value, args, 0, &error); + if (error) + { + g_warning ("%s: %s", G_STRLOC, error); + g_free (error); + + /* Leak value as it might not be in a sane state */ + break; + } + + g_value_unset (&value); + + column = va_arg (args, gint); + } +} + +/** + * clutter_model_iter_set: + * @iter: a #ClutterModelIter + * @...: a list of column/return location pairs, terminated by -1 + * + * Sets the value of one or more cells in the row referenced by @iter. The + * variable argument list should contain integer column numbers, each column + * column number followed by the value to be set. The list is terminated by a + * -1. + * + * For example, to set column 0 with type %G_TYPE_STRING, use: + * + * clutter_model_iter_set (iter, 0, "foo", -1); + * + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +void +clutter_model_iter_set (ClutterModelIter *iter, + ...) +{ + va_list args; + + g_return_if_fail (CLUTTER_IS_MODEL_ITER (iter)); + + va_start (args, iter); + clutter_model_iter_set_internal_valist (iter, args); + clutter_model_iter_emit_row_changed (iter); + va_end (args); +} + +/** + * clutter_model_iter_set_value: + * @iter: a #ClutterModelIter + * @column: column number to retrieve the value from + * @value: new value for the cell + * + * Sets the data in the cell specified by @iter and @column. The type of + * @value must be convertable to the type of the column. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +void +clutter_model_iter_set_value (ClutterModelIter *iter, + guint column, + const GValue *value) +{ + g_return_if_fail (CLUTTER_IS_MODEL_ITER (iter)); + + clutter_model_iter_set_value_internal (iter, column, value); + clutter_model_iter_emit_row_changed (iter); +} + +/** + * clutter_model_iter_is_first: + * @iter: a #ClutterModelIter + * + * Gets whether the current iterator is at the beginning of the model + * to which it belongs. + * + * Return value: #TRUE if @iter is the first iter in the filtered model + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +gboolean +clutter_model_iter_is_first (ClutterModelIter *iter) +{ + g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), FALSE); + + return CLUTTER_MODEL_ITER_GET_CLASS (iter)->is_first (iter); +} + +/** + * clutter_model_iter_is_last: + * @iter: a #ClutterModelIter + * + * Gets whether the iterator is at the end of the model to which it + * belongs. + * + * Return value: #TRUE if @iter is the last iter in the filtered model. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +gboolean +clutter_model_iter_is_last (ClutterModelIter *iter) +{ + g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), FALSE); + + return CLUTTER_MODEL_ITER_GET_CLASS (iter)->is_last (iter); +} + +/** + * clutter_model_iter_next: + * @iter: a #ClutterModelIter + * + * Updates the @iter to point at the next position in the model. + * The model implementation should take into account the presence of + * a filter function. + * + * Return value: (transfer none): The passed iterator, updated to point at the next + * row in the model. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +ClutterModelIter * +clutter_model_iter_next (ClutterModelIter *iter) +{ + g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), NULL); + + return CLUTTER_MODEL_ITER_GET_CLASS (iter)->next (iter); +} + +/** + * clutter_model_iter_prev: + * @iter: a #ClutterModelIter + * + * Sets the @iter to point at the previous position in the model. + * The model implementation should take into account the presence of + * a filter function. + * + * Return value: (transfer none): The passed iterator, updated to point at the previous + * row in the model. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +ClutterModelIter * +clutter_model_iter_prev (ClutterModelIter *iter) +{ + g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), NULL); + + return CLUTTER_MODEL_ITER_GET_CLASS (iter)->prev (iter); +} + +/** + * clutter_model_iter_get_model: + * @iter: a #ClutterModelIter + * + * Retrieves a pointer to the #ClutterModel that this iter is part of. + * + * Return value: (transfer none): a pointer to a #ClutterModel. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +ClutterModel * +clutter_model_iter_get_model (ClutterModelIter *iter) +{ + g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), NULL); + + return CLUTTER_MODEL_ITER_GET_CLASS (iter)->get_model (iter); +} + +/** + * clutter_model_iter_get_row: + * @iter: a #ClutterModelIter + * + * Retrieves the position of the row that the @iter points to. + * + * Return value: the position of the @iter in the model + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +guint +clutter_model_iter_get_row (ClutterModelIter *iter) +{ + g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), 0); + + return CLUTTER_MODEL_ITER_GET_CLASS (iter)->get_row (iter); +} + +/** + * clutter_model_iter_copy: + * @iter: a #ClutterModelIter + * + * Copies the passed iterator. + * + * Return value: (transfer full): a copy of the iterator, or %NULL + * + * Since: 0.8 + * + * Deprecated: 1.24: Use #GListModel instead + */ +ClutterModelIter * +clutter_model_iter_copy (ClutterModelIter *iter) +{ + g_return_val_if_fail (CLUTTER_IS_MODEL_ITER (iter), NULL); + + return CLUTTER_MODEL_ITER_GET_CLASS (iter)->copy (iter); +} diff --git a/clutter/clutter/deprecated/clutter-model.h b/clutter/clutter/deprecated/clutter-model.h new file mode 100644 index 0000000..f598f39 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-model.h @@ -0,0 +1,436 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * Neil Jagdish Patel + * Emmanuele Bassi + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_MODEL_H__ +#define __CLUTTER_MODEL_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_MODEL (clutter_model_get_type ()) +#define CLUTTER_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_MODEL, ClutterModel)) +#define CLUTTER_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_MODEL, ClutterModelClass)) +#define CLUTTER_IS_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_MODEL)) +#define CLUTTER_IS_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_MODEL)) +#define CLUTTER_MODEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_MODEL, ClutterModelClass)) + +typedef struct _ClutterModel ClutterModel; +typedef struct _ClutterModelClass ClutterModelClass; +typedef struct _ClutterModelPrivate ClutterModelPrivate; +typedef struct _ClutterModelIter ClutterModelIter; +typedef struct _ClutterModelIterClass ClutterModelIterClass; +typedef struct _ClutterModelIterPrivate ClutterModelIterPrivate; + + +/** + * ClutterModelFilterFunc: + * @model: a #ClutterModel + * @iter: the iterator for the row + * @user_data: data passed to clutter_model_set_filter() + * + * Filters the content of a row in the model. + * + * Return value: If the row should be displayed, return %TRUE + * + * Since: 0.6 + * + * Deprecated: 1.24: Implement filters using a custom #GListModel instead + */ +typedef gboolean (*ClutterModelFilterFunc) (ClutterModel *model, + ClutterModelIter *iter, + gpointer user_data); + +/** + * ClutterModelSortFunc: + * @model: a #ClutterModel + * @a: a #GValue representing the contents of the row + * @b: a #GValue representing the contents of the second row + * @user_data: data passed to clutter_model_set_sort() + * + * Compares the content of two rows in the model. + * + * Return value: a positive integer if @a is after @b, a negative integer if + * @a is before @b, or 0 if the rows are the same + * + * Since: 0.6 + * + * Deprecated: 1.24: Implement sorting using a custom #GListModel instead + */ +typedef gint (*ClutterModelSortFunc) (ClutterModel *model, + const GValue *a, + const GValue *b, + gpointer user_data); + +/** + * ClutterModelForeachFunc: + * @model: a #ClutterModel + * @iter: the iterator for the row + * @user_data: data passed to clutter_model_foreach() + * + * Iterates on the content of a row in the model + * + * Return value: %TRUE if the iteration should continue, %FALSE otherwise + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel + */ +typedef gboolean (*ClutterModelForeachFunc) (ClutterModel *model, + ClutterModelIter *iter, + gpointer user_data); + +/** + * ClutterModel: + * + * Base class for list models. The #ClutterModel structure contains + * only private data and should be manipulated using the provided + * API. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +struct _ClutterModel +{ + /*< private >*/ + GObject parent_instance; + + ClutterModelPrivate *priv; +}; + +/** + * ClutterModelClass: + * @row_added: signal class handler for ClutterModel::row-added + * @row_removed: signal class handler for ClutterModel::row-removed + * @row_changed: signal class handler for ClutterModel::row-changed + * @sort_changed: signal class handler for ClutterModel::sort-changed + * @filter_changed: signal class handler for ClutterModel::filter-changed + * @get_column_name: virtual function for returning the name of a column + * @get_column_type: virtual function for returning the type of a column + * @get_iter_at_row: virtual function for returning an iterator for the + * given row + * @get_n_rows: virtual function for returning the number of rows + * of the model + * @get_n_columns: virtual function for retuning the number of columns + * of the model + * @resort: virtual function for sorting the model using the passed + * sorting function + * @insert_row: virtual function for inserting a row at the given index + * and returning an iterator pointing to it; if the index is a negative + * integer, the row should be appended to the model + * @remove_row: virtual function for removing a row at the given index + * + * Class for #ClutterModel instances. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use #GListModel instead + */ +struct _ClutterModelClass +{ + /*< private >*/ + GObjectClass parent_class; + + /*< public >*/ + /* vtable */ + guint (* get_n_rows) (ClutterModel *model); + guint (* get_n_columns) (ClutterModel *model); + const gchar * (* get_column_name) (ClutterModel *model, + guint column); + GType (* get_column_type) (ClutterModel *model, + guint column); + ClutterModelIter *(* insert_row) (ClutterModel *model, + gint index_); + void (* remove_row) (ClutterModel *model, + guint row); + ClutterModelIter *(* get_iter_at_row) (ClutterModel *model, + guint row); + void (* resort) (ClutterModel *model, + ClutterModelSortFunc func, + gpointer data); + + /* signals */ + void (* row_added) (ClutterModel *model, + ClutterModelIter *iter); + void (* row_removed) (ClutterModel *model, + ClutterModelIter *iter); + void (* row_changed) (ClutterModel *model, + ClutterModelIter *iter); + void (* sort_changed) (ClutterModel *model); + void (* filter_changed) (ClutterModel *model); + + /*< private >*/ + /* padding for future expansion */ + void (*_clutter_model_1) (void); + void (*_clutter_model_2) (void); + void (*_clutter_model_3) (void); + void (*_clutter_model_4) (void); + void (*_clutter_model_5) (void); + void (*_clutter_model_6) (void); + void (*_clutter_model_7) (void); + void (*_clutter_model_8) (void); +}; + +CLUTTER_DEPRECATED_IN_1_24_FOR(g_list_model_get_type) +GType clutter_model_get_type (void) G_GNUC_CONST; + +CLUTTER_DEPRECATED_IN_1_24_FOR(GListModel) +void clutter_model_set_types (ClutterModel *model, + guint n_columns, + GType *types); +CLUTTER_DEPRECATED_IN_1_24_FOR(GListModel) +void clutter_model_set_names (ClutterModel *model, + guint n_columns, + const gchar * const names[]); + +CLUTTER_DEPRECATED_IN_1_24_FOR(GListModel) +void clutter_model_append (ClutterModel *model, + ...); +CLUTTER_DEPRECATED_IN_1_24_FOR(GListModel) +void clutter_model_appendv (ClutterModel *model, + guint n_columns, + guint *columns, + GValue *values); +CLUTTER_DEPRECATED_IN_1_24_FOR(GListModel) +void clutter_model_prepend (ClutterModel *model, + ...); +CLUTTER_DEPRECATED_IN_1_24_FOR(GListModel) +void clutter_model_prependv (ClutterModel *model, + guint n_columns, + guint *columns, + GValue *values); +CLUTTER_DEPRECATED_IN_1_24_FOR(GListModel) +void clutter_model_insert (ClutterModel *model, + guint row, + ...); +CLUTTER_DEPRECATED_IN_1_24_FOR(GListModel) +void clutter_model_insertv (ClutterModel *model, + guint row, + guint n_columns, + guint *columns, + GValue *values); +CLUTTER_DEPRECATED_IN_1_24_FOR(GListModel) +void clutter_model_insert_value (ClutterModel *model, + guint row, + guint column, + const GValue *value); +CLUTTER_DEPRECATED_IN_1_24_FOR(GListModel) +void clutter_model_remove (ClutterModel *model, + guint row); + +CLUTTER_DEPRECATED_IN_1_24_FOR(GListModel) +guint clutter_model_get_n_rows (ClutterModel *model); +CLUTTER_DEPRECATED_IN_1_24_FOR(GListModel) +guint clutter_model_get_n_columns (ClutterModel *model); +CLUTTER_DEPRECATED_IN_1_24_FOR(GListModel) +const gchar * clutter_model_get_column_name (ClutterModel *model, + guint column); +CLUTTER_DEPRECATED_IN_1_24_FOR(GListModel) +GType clutter_model_get_column_type (ClutterModel *model, + guint column); + +CLUTTER_DEPRECATED_IN_1_24_FOR(GListModel) +ClutterModelIter * clutter_model_get_first_iter (ClutterModel *model); +CLUTTER_DEPRECATED_IN_1_24_FOR(GListModel) +ClutterModelIter * clutter_model_get_last_iter (ClutterModel *model); +CLUTTER_DEPRECATED_IN_1_24_FOR(GListModel) +ClutterModelIter * clutter_model_get_iter_at_row (ClutterModel *model, + guint row); + +CLUTTER_DEPRECATED_IN_1_24_FOR(GListModel) +void clutter_model_set_sorting_column (ClutterModel *model, + gint column); +CLUTTER_DEPRECATED_IN_1_24_FOR(GListModel) +gint clutter_model_get_sorting_column (ClutterModel *model); + +CLUTTER_DEPRECATED_IN_1_24_FOR(GListModel) +void clutter_model_foreach (ClutterModel *model, + ClutterModelForeachFunc func, + gpointer user_data); +CLUTTER_DEPRECATED_IN_1_24_FOR(GListModel) +void clutter_model_set_sort (ClutterModel *model, + gint column, + ClutterModelSortFunc func, + gpointer user_data, + GDestroyNotify notify); +CLUTTER_DEPRECATED_IN_1_24_FOR(GListModel) +void clutter_model_set_filter (ClutterModel *model, + ClutterModelFilterFunc func, + gpointer user_data, + GDestroyNotify notify); +CLUTTER_DEPRECATED_IN_1_24_FOR(GListModel) +gboolean clutter_model_get_filter_set (ClutterModel *model); + +CLUTTER_DEPRECATED_IN_1_24_FOR(GListModel) +void clutter_model_resort (ClutterModel *model); +CLUTTER_DEPRECATED_IN_1_24_FOR(GListModel) +gboolean clutter_model_filter_row (ClutterModel *model, + guint row); +CLUTTER_DEPRECATED_IN_1_24_FOR(GListModel) +gboolean clutter_model_filter_iter (ClutterModel *model, + ClutterModelIter *iter); + +/* + * ClutterModelIter + */ + +#define CLUTTER_TYPE_MODEL_ITER (clutter_model_iter_get_type ()) +#define CLUTTER_MODEL_ITER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_MODEL_ITER, ClutterModelIter)) +#define CLUTTER_MODEL_ITER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_MODEL_ITER, ClutterModelIterClass)) +#define CLUTTER_IS_MODEL_ITER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_MODEL_ITER)) +#define CLUTTER_IS_MODEL_ITER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_MODEL_ITER)) +#define CLUTTER_MODEL_ITER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_MODEL_ITER, ClutterModelIterClass)) + +/** + * ClutterModelIter: + * + * Base class for list models iters. The #ClutterModelIter structure + * contains only private data and should be manipulated using the + * provided API. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use custom iterators for #GListModel + */ +struct _ClutterModelIter +{ + /*< private >*/ + GObject parent_instance; + + ClutterModelIterPrivate *priv; +}; + +/** + * ClutterModelIterClass: + * @get_value: Virtual function for retrieving the value at the given + * column of the row pointed by the iterator + * @set_value: Virtual function for setting the value at the given + * column of the row pointer by the iterator + * @is_last: Virtual function for knowing whether the iterator points + * at the last row in the model + * @is_first: Virtual function for knowing whether the iterator points + * at the first row in the model + * @next: Virtual function for moving the iterator to the following + * row in the model + * @prev: Virtual function for moving the iterator toe the previous + * row in the model + * @get_model: Virtual function for getting the model to which the + * iterator belongs to + * @get_row: Virtual function for getting the row to which the iterator + * points + * @copy: Virtual function for copying a #ClutterModelIter. + * + * Class for #ClutterModelIter instances. + * + * Since: 0.6 + * + * Deprecated: 1.24: Use custom iterators for #GListModel + */ +struct _ClutterModelIterClass +{ + /*< private >*/ + GObjectClass parent_class; + + /*< public >*/ + /* vtable not signals */ + void (* get_value) (ClutterModelIter *iter, + guint column, + GValue *value); + void (* set_value) (ClutterModelIter *iter, + guint column, + const GValue *value); + + gboolean (* is_first) (ClutterModelIter *iter); + gboolean (* is_last) (ClutterModelIter *iter); + + ClutterModelIter *(* next) (ClutterModelIter *iter); + ClutterModelIter *(* prev) (ClutterModelIter *iter); + + ClutterModel * (* get_model) (ClutterModelIter *iter); + guint (* get_row) (ClutterModelIter *iter); + + ClutterModelIter *(* copy) (ClutterModelIter *iter); + + /*< private >*/ + /* padding for future expansion */ + void (*_clutter_model_iter_1) (void); + void (*_clutter_model_iter_2) (void); + void (*_clutter_model_iter_3) (void); + void (*_clutter_model_iter_4) (void); + void (*_clutter_model_iter_5) (void); + void (*_clutter_model_iter_6) (void); + void (*_clutter_model_iter_7) (void); + void (*_clutter_model_iter_8) (void); +}; + +CLUTTER_DEPRECATED_IN_1_24 +GType clutter_model_iter_get_type (void) G_GNUC_CONST; + +CLUTTER_DEPRECATED_IN_1_24 +void clutter_model_iter_get (ClutterModelIter *iter, + ...); +CLUTTER_DEPRECATED_IN_1_24 +void clutter_model_iter_get_valist (ClutterModelIter *iter, + va_list args); +CLUTTER_DEPRECATED_IN_1_24 +void clutter_model_iter_get_value (ClutterModelIter *iter, + guint column, + GValue *value); +CLUTTER_DEPRECATED_IN_1_24 +void clutter_model_iter_set (ClutterModelIter *iter, + ...); +CLUTTER_DEPRECATED_IN_1_24 +void clutter_model_iter_set_valist (ClutterModelIter *iter, + va_list args); +CLUTTER_DEPRECATED_IN_1_24 +void clutter_model_iter_set_value (ClutterModelIter *iter, + guint column, + const GValue *value); + +CLUTTER_DEPRECATED_IN_1_24 +gboolean clutter_model_iter_is_first (ClutterModelIter *iter); +CLUTTER_DEPRECATED_IN_1_24 +gboolean clutter_model_iter_is_last (ClutterModelIter *iter); +CLUTTER_DEPRECATED_IN_1_24 +ClutterModelIter *clutter_model_iter_next (ClutterModelIter *iter); +CLUTTER_DEPRECATED_IN_1_24 +ClutterModelIter *clutter_model_iter_prev (ClutterModelIter *iter); + +CLUTTER_DEPRECATED_IN_1_24 +ClutterModel * clutter_model_iter_get_model (ClutterModelIter *iter); +CLUTTER_DEPRECATED_IN_1_24 +guint clutter_model_iter_get_row (ClutterModelIter *iter); + +CLUTTER_DEPRECATED_IN_1_24 +ClutterModelIter *clutter_model_iter_copy (ClutterModelIter *iter); + +G_END_DECLS + +#endif /* __CLUTTER_MODEL_H__ */ diff --git a/clutter/clutter/deprecated/clutter-rectangle.c b/clutter/clutter/deprecated/clutter-rectangle.c new file mode 100644 index 0000000..e4cfeb4 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-rectangle.c @@ -0,0 +1,602 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +/** + * SECTION:clutter-rectangle + * @short_description: An actor that displays a simple rectangle. + * + * #ClutterRectangle is a #ClutterActor which draws a simple filled rectangle. + * + * #ClutterRectangle is deprecated since Clutter 1.10. If you want an actor + * painting a solid color, you can replace it with #ClutterActor and set the + * #ClutterActor:background-color property to the desired #ClutterColor. If + * you are drawing more complex shapes, use #ClutterCanvas to draw using the + * Cairo 2D API instead. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include "deprecated/clutter-rectangle.h" +#include "deprecated/clutter-actor.h" + +#include "clutter-actor-private.h" +#include "clutter-color.h" +#include "clutter-debug.h" +#include "clutter-main.h" +#include "clutter-private.h" + +#include "cogl/cogl.h" + +struct _ClutterRectanglePrivate +{ + ClutterColor color; + ClutterColor border_color; + + guint border_width; + + guint has_border : 1; +}; + +enum +{ + PROP_0, + + PROP_COLOR, + PROP_BORDER_COLOR, + PROP_BORDER_WIDTH, + PROP_HAS_BORDER + + /* FIXME: Add gradient, rounded corner props etc */ +}; + +static const ClutterColor default_color = { 255, 255, 255, 255 }; +static const ClutterColor default_border_color = { 0, 0, 0, 255 }; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterRectangle, clutter_rectangle, CLUTTER_TYPE_ACTOR) + +static void +clutter_rectangle_paint (ClutterActor *self) +{ + ClutterRectanglePrivate *priv = CLUTTER_RECTANGLE (self)->priv; + ClutterGeometry geom; + guint8 tmp_alpha; + + CLUTTER_NOTE (PAINT, + "painting rect '%s'", + clutter_actor_get_name (self) ? clutter_actor_get_name (self) + : "unknown"); + clutter_actor_get_allocation_geometry (self, &geom); + + if (priv->has_border) + { + /* We paint the border and the content only if the rectangle + * is big enough to show them + */ + if ((priv->border_width * 2) < geom.width && + (priv->border_width * 2) < geom.height) + { + /* compute the composited opacity of the actor taking into + * account the opacity of the color set by the user + */ + tmp_alpha = clutter_actor_get_paint_opacity (self) + * priv->border_color.alpha + / 255; + + /* paint the border */ + cogl_set_source_color4ub (priv->border_color.red, + priv->border_color.green, + priv->border_color.blue, + tmp_alpha); + + /* this sucks, but it's the only way to make a border */ + cogl_rectangle (priv->border_width, 0, + geom.width, + priv->border_width); + + cogl_rectangle (geom.width - priv->border_width, + priv->border_width, + geom.width, + geom.height); + + cogl_rectangle (0, geom.height - priv->border_width, + geom.width - priv->border_width, + geom.height); + + cogl_rectangle (0, 0, + priv->border_width, + geom.height - priv->border_width); + + tmp_alpha = clutter_actor_get_paint_opacity (self) + * priv->color.alpha + / 255; + + /* now paint the rectangle */ + cogl_set_source_color4ub (priv->color.red, + priv->color.green, + priv->color.blue, + tmp_alpha); + + cogl_rectangle (priv->border_width, priv->border_width, + geom.width - priv->border_width, + geom.height - priv->border_width); + } + else + { + /* Otherwise, we draw a rectangle with the same color + * as the border, since we can only fit that into the + * allocation. + */ + tmp_alpha = clutter_actor_get_paint_opacity (self) + * priv->border_color.alpha + / 255; + + cogl_set_source_color4ub (priv->border_color.red, + priv->border_color.green, + priv->border_color.blue, + tmp_alpha); + + cogl_rectangle (0, 0, geom.width, geom.height); + } + } + else + { + /* compute the composited opacity of the actor taking into + * account the opacity of the color set by the user + */ + tmp_alpha = clutter_actor_get_paint_opacity (self) + * priv->color.alpha + / 255; + + cogl_set_source_color4ub (priv->color.red, + priv->color.green, + priv->color.blue, + tmp_alpha); + + cogl_rectangle (0, 0, geom.width, geom.height); + } +} + +static gboolean +clutter_rectangle_get_paint_volume (ClutterActor *self, + ClutterPaintVolume *volume) +{ + return _clutter_actor_set_default_paint_volume (self, + CLUTTER_TYPE_RECTANGLE, + volume); +} + +static gboolean +clutter_rectangle_has_overlaps (ClutterActor *self) +{ + /* Rectangles never need an offscreen redirect because there are + never any overlapping primitives */ + return FALSE; +} + +static void +clutter_rectangle_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterRectangle *rectangle = CLUTTER_RECTANGLE(object); + + switch (prop_id) + { + case PROP_COLOR: + clutter_rectangle_set_color (rectangle, clutter_value_get_color (value)); + break; + case PROP_BORDER_COLOR: + clutter_rectangle_set_border_color (rectangle, + clutter_value_get_color (value)); + break; + case PROP_BORDER_WIDTH: + clutter_rectangle_set_border_width (rectangle, + g_value_get_uint (value)); + break; + case PROP_HAS_BORDER: + rectangle->priv->has_border = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_rectangle_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterRectanglePrivate *priv = CLUTTER_RECTANGLE(object)->priv; + + switch (prop_id) + { + case PROP_COLOR: + clutter_value_set_color (value, &priv->color); + break; + case PROP_BORDER_COLOR: + clutter_value_set_color (value, &priv->border_color); + break; + case PROP_BORDER_WIDTH: + g_value_set_uint (value, priv->border_width); + break; + case PROP_HAS_BORDER: + g_value_set_boolean (value, priv->has_border); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +static void +clutter_rectangle_finalize (GObject *object) +{ + G_OBJECT_CLASS (clutter_rectangle_parent_class)->finalize (object); +} + +static void +clutter_rectangle_dispose (GObject *object) +{ + G_OBJECT_CLASS (clutter_rectangle_parent_class)->dispose (object); +} + + +static void +clutter_rectangle_class_init (ClutterRectangleClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + GParamSpec *pspec; + + actor_class->paint = clutter_rectangle_paint; + actor_class->get_paint_volume = clutter_rectangle_get_paint_volume; + actor_class->has_overlaps = clutter_rectangle_has_overlaps; + + gobject_class->finalize = clutter_rectangle_finalize; + gobject_class->dispose = clutter_rectangle_dispose; + gobject_class->set_property = clutter_rectangle_set_property; + gobject_class->get_property = clutter_rectangle_get_property; + + /** + * ClutterRectangle:color: + * + * The color of the rectangle. + */ + pspec = clutter_param_spec_color ("color", + P_("Color"), + P_("The color of the rectangle"), + &default_color, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_COLOR, pspec); + + /** + * ClutterRectangle:border-color: + * + * The color of the border of the rectangle. + * + * Since: 0.2 + */ + pspec = clutter_param_spec_color ("border-color", + P_("Border Color"), + P_("The color of the border of the rectangle"), + &default_border_color, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_BORDER_COLOR, pspec); + + /** + * ClutterRectangle:border-width: + * + * The width of the border of the rectangle, in pixels. + * + * Since: 0.2 + */ + g_object_class_install_property (gobject_class, + PROP_BORDER_WIDTH, + g_param_spec_uint ("border-width", + P_("Border Width"), + P_("The width of the border of the rectangle"), + 0, G_MAXUINT, + 0, + CLUTTER_PARAM_READWRITE)); + /** + * ClutterRectangle:has-border: + * + * Whether the #ClutterRectangle should be displayed with a border. + * + * Since: 0.2 + */ + g_object_class_install_property (gobject_class, + PROP_HAS_BORDER, + g_param_spec_boolean ("has-border", + P_("Has Border"), + P_("Whether the rectangle should have a border"), + FALSE, + CLUTTER_PARAM_READWRITE)); +} + +static void +clutter_rectangle_init (ClutterRectangle *self) +{ + ClutterRectanglePrivate *priv; + + self->priv = priv = clutter_rectangle_get_instance_private (self); + + priv->color = default_color; + priv->border_color = default_border_color; + + priv->border_width = 0; + + priv->has_border = FALSE; +} + +/** + * clutter_rectangle_new: + * + * Creates a new #ClutterActor with a rectangular shape. + * + * Return value: a new #ClutterRectangle + * + * Deprecated: 1.10: Use clutter_actor_new() instead + */ +ClutterActor* +clutter_rectangle_new (void) +{ + return g_object_new (CLUTTER_TYPE_RECTANGLE, NULL); +} + +/** + * clutter_rectangle_new_with_color: + * @color: a #ClutterColor + * + * Creates a new #ClutterActor with a rectangular shape + * and of the given @color. + * + * Return value: a new #ClutterRectangle + * + * Deprecated: 1.10: Use clutter_actor_new() and + * clutter_actor_set_background_color() instead + */ +ClutterActor * +clutter_rectangle_new_with_color (const ClutterColor *color) +{ + return g_object_new (CLUTTER_TYPE_RECTANGLE, + "color", color, + NULL); +} + +/** + * clutter_rectangle_get_color: + * @rectangle: a #ClutterRectangle + * @color: (out caller-allocates): return location for a #ClutterColor + * + * Retrieves the color of @rectangle. + * + * Deprecated: 1.10: Use #ClutterActor and clutter_actor_get_background_color() + * instead + */ +void +clutter_rectangle_get_color (ClutterRectangle *rectangle, + ClutterColor *color) +{ + ClutterRectanglePrivate *priv; + + g_return_if_fail (CLUTTER_IS_RECTANGLE (rectangle)); + g_return_if_fail (color != NULL); + + priv = rectangle->priv; + + color->red = priv->color.red; + color->green = priv->color.green; + color->blue = priv->color.blue; + color->alpha = priv->color.alpha; +} + +/** + * clutter_rectangle_set_color: + * @rectangle: a #ClutterRectangle + * @color: a #ClutterColor + * + * Sets the color of @rectangle. + * + * Deprecated: 1.10: Use #ClutterActor and clutter_actor_set_background_color() + * instead + */ +void +clutter_rectangle_set_color (ClutterRectangle *rectangle, + const ClutterColor *color) +{ + ClutterRectanglePrivate *priv; + + g_return_if_fail (CLUTTER_IS_RECTANGLE (rectangle)); + g_return_if_fail (color != NULL); + + g_object_ref (rectangle); + + priv = rectangle->priv; + + priv->color.red = color->red; + priv->color.green = color->green; + priv->color.blue = color->blue; + priv->color.alpha = color->alpha; + +#if 0 + /* FIXME - appears to be causing border to always get drawn */ + if (clutter_color_equal (&priv->color, &priv->border_color)) + priv->has_border = FALSE; + else + priv->has_border = TRUE; +#endif + + clutter_actor_queue_redraw (CLUTTER_ACTOR (rectangle)); + + g_object_notify (G_OBJECT (rectangle), "color"); + g_object_notify (G_OBJECT (rectangle), "has-border"); + g_object_unref (rectangle); +} + +/** + * clutter_rectangle_get_border_width: + * @rectangle: a #ClutterRectangle + * + * Gets the width (in pixels) of the border used by @rectangle + * + * Return value: the border's width + * + * Since: 0.2 + * + * Deprecated: 1.10: Use #ClutterActor and a #ClutterCanvas content + * to draw the border using Cairo + */ +guint +clutter_rectangle_get_border_width (ClutterRectangle *rectangle) +{ + g_return_val_if_fail (CLUTTER_IS_RECTANGLE (rectangle), 0); + + return rectangle->priv->border_width; +} + +/** + * clutter_rectangle_set_border_width: + * @rectangle: a #ClutterRectangle + * @width: the width of the border + * + * Sets the width (in pixel) of the border used by @rectangle. + * A @width of 0 will unset the border. + * + * Since: 0.2 + * + * Deprecated: 1.10: Use #ClutterActor and a #ClutterCanvas content + * to draw the border using Cairo + */ +void +clutter_rectangle_set_border_width (ClutterRectangle *rectangle, + guint width) +{ + ClutterRectanglePrivate *priv; + + g_return_if_fail (CLUTTER_IS_RECTANGLE (rectangle)); + priv = rectangle->priv; + + if (priv->border_width != width) + { + g_object_ref (rectangle); + + priv->border_width = width; + + if (priv->border_width != 0) + priv->has_border = TRUE; + else + priv->has_border = FALSE; + + clutter_actor_queue_redraw (CLUTTER_ACTOR (rectangle)); + + g_object_notify (G_OBJECT (rectangle), "border-width"); + g_object_notify (G_OBJECT (rectangle), "has-border"); + g_object_unref (rectangle); + } +} + +/** + * clutter_rectangle_get_border_color: + * @rectangle: a #ClutterRectangle + * @color: (out caller-allocates): return location for a #ClutterColor + * + * Gets the color of the border used by @rectangle and places + * it into @color. + * + * Since: 0.2 + * + * Deprecated: 1.10: Use #ClutterActor and a #ClutterCanvas to draw + * the border with Cairo + */ +void +clutter_rectangle_get_border_color (ClutterRectangle *rectangle, + ClutterColor *color) +{ + ClutterRectanglePrivate *priv; + + g_return_if_fail (CLUTTER_IS_RECTANGLE (rectangle)); + g_return_if_fail (color != NULL); + + priv = rectangle->priv; + + color->red = priv->border_color.red; + color->green = priv->border_color.green; + color->blue = priv->border_color.blue; + color->alpha = priv->border_color.alpha; +} + +/** + * clutter_rectangle_set_border_color: + * @rectangle: a #ClutterRectangle + * @color: the color of the border + * + * Sets the color of the border used by @rectangle using @color + * + * Deprecated: 1.10: Use #ClutterActor and a #ClutterCanvas to draw + * the border with Cairo + */ +void +clutter_rectangle_set_border_color (ClutterRectangle *rectangle, + const ClutterColor *color) +{ + ClutterRectanglePrivate *priv; + + g_return_if_fail (CLUTTER_IS_RECTANGLE (rectangle)); + g_return_if_fail (color != NULL); + + priv = rectangle->priv; + + if (priv->border_color.red != color->red || + priv->border_color.green != color->green || + priv->border_color.blue != color->blue || + priv->border_color.alpha != color->alpha) + { + g_object_ref (rectangle); + + priv->border_color.red = color->red; + priv->border_color.green = color->green; + priv->border_color.blue = color->blue; + priv->border_color.alpha = color->alpha; + + if (clutter_color_equal (&priv->color, &priv->border_color)) + priv->has_border = FALSE; + else + priv->has_border = TRUE; + + clutter_actor_queue_redraw (CLUTTER_ACTOR (rectangle)); + + g_object_notify (G_OBJECT (rectangle), "border-color"); + g_object_notify (G_OBJECT (rectangle), "has-border"); + g_object_unref (rectangle); + } +} diff --git a/clutter/clutter/deprecated/clutter-rectangle.h b/clutter/clutter/deprecated/clutter-rectangle.h new file mode 100644 index 0000000..ba58bbc --- /dev/null +++ b/clutter/clutter/deprecated/clutter-rectangle.h @@ -0,0 +1,117 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_RECTANGLE_H__ +#define __CLUTTER_RECTANGLE_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_RECTANGLE (clutter_rectangle_get_type()) +#define CLUTTER_RECTANGLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_RECTANGLE, ClutterRectangle)) +#define CLUTTER_RECTANGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_RECTANGLE, ClutterRectangleClass)) +#define CLUTTER_IS_RECTANGLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_RECTANGLE)) +#define CLUTTER_IS_RECTANGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_RECTANGLE)) +#define CLUTTER_RECTANGLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_RECTANGLE, ClutterRectangleClass)) + +typedef struct _ClutterRectangle ClutterRectangle; +typedef struct _ClutterRectangleClass ClutterRectangleClass; +typedef struct _ClutterRectanglePrivate ClutterRectanglePrivate; + +/** + * ClutterRectangle: + * + * The #ClutterRectangle structure contains only private data + * and should be accessed using the provided API + * + * Since: 0.2 + */ +struct _ClutterRectangle +{ + /*< private >*/ + ClutterActor parent; + + ClutterRectanglePrivate *priv; +}; + +/** + * ClutterRectangleClass: + * + * The #ClutterRectangleClass structure contains only private data + * + * Since: 0.2 + */ +struct _ClutterRectangleClass +{ + /*< private >*/ + ClutterActorClass parent_class; + + /* padding for future expansion */ + void (*_clutter_rectangle1) (void); + void (*_clutter_rectangle2) (void); + void (*_clutter_rectangle3) (void); + void (*_clutter_rectangle4) (void); +}; + +CLUTTER_DEPRECATED_IN_1_10 +GType clutter_rectangle_get_type (void) G_GNUC_CONST; + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_new) +ClutterActor *clutter_rectangle_new (void); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_new) +ClutterActor *clutter_rectangle_new_with_color (const ClutterColor *color); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_get_background_color) +void clutter_rectangle_get_color (ClutterRectangle *rectangle, + ClutterColor *color); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_set_background_color) +void clutter_rectangle_set_color (ClutterRectangle *rectangle, + const ClutterColor *color); + +CLUTTER_DEPRECATED_IN_1_10 +guint clutter_rectangle_get_border_width (ClutterRectangle *rectangle); + +CLUTTER_DEPRECATED_IN_1_10 +void clutter_rectangle_set_border_width (ClutterRectangle *rectangle, + guint width); + +CLUTTER_DEPRECATED_IN_1_10 +void clutter_rectangle_get_border_color (ClutterRectangle *rectangle, + ClutterColor *color); + +CLUTTER_DEPRECATED_IN_1_10 +void clutter_rectangle_set_border_color (ClutterRectangle *rectangle, + const ClutterColor *color); + +G_END_DECLS + +#endif /* __CLUTTER_RECTANGLE_H__ */ diff --git a/clutter/clutter/deprecated/clutter-score.c b/clutter/clutter/deprecated/clutter-score.c new file mode 100644 index 0000000..a37dd3d --- /dev/null +++ b/clutter/clutter/deprecated/clutter-score.c @@ -0,0 +1,1168 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2007 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +/** + * SECTION:clutter-score + * @short_description: Controller for multiple timelines + * + * #ClutterScore is a base class for sequencing multiple timelines in order. + * Using #ClutterScore it is possible to start multiple timelines at the + * same time or launch multiple timelines when a particular timeline has + * emitted the ClutterTimeline::completed signal. + * + * Each time a #ClutterTimeline is started and completed, a signal will be + * emitted. + * + * For example, this code will start two #ClutterTimelines after + * a third timeline terminates: + * + * |[ + * ClutterTimeline *timeline_1, *timeline_2, *timeline_3; + * ClutterScore *score; + * + * timeline_1 = clutter_timeline_new_for_duration (1000); + * timeline_2 = clutter_timeline_new_for_duration (500); + * timeline_3 = clutter_timeline_new_for_duration (500); + * + * score = clutter_score_new (); + * + * clutter_score_append (score, NULL, timeline_1); + * clutter_score_append (score, timeline_1, timeline_2); + * clutter_score_append (score, timeline_1, timeline_3); + * + * clutter_score_start (score); + * ]| + * + * A #ClutterScore takes a reference on the timelines it manages, + * so timelines can be safely unreferenced after being appended. + * + * New timelines can be appended to the #ClutterScore using + * clutter_score_append() and removed using clutter_score_remove(). + * + * Timelines can also be appended to a specific marker on the + * parent timeline, using clutter_score_append_at_marker(). + * + * The score can be cleared using clutter_score_remove_all(). + * + * The list of timelines can be retrieved using + * clutter_score_list_timelines(). + * + * The score state is controlled using clutter_score_start(), + * clutter_score_pause(), clutter_score_stop() and clutter_score_rewind(). + * The state can be queried using clutter_score_is_playing(). + * + * #ClutterScore is available since Clutter 0.6 + * + * Deprecated: 1.8: Use #ClutterAnimator or #ClutterState to create + * complex animations involving multiple timelines. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS + +#include "clutter-score.h" +#include "clutter-main.h" +#include "clutter-marshal.h" +#include "clutter-private.h" +#include "clutter-debug.h" + +typedef struct _ClutterScoreEntry ClutterScoreEntry; + +struct _ClutterScoreEntry +{ + /* the entry unique id */ + gulong id; + + ClutterTimeline *timeline; + ClutterTimeline *parent; + + /* the optional marker on the parent */ + gchar *marker; + + /* signal handlers id */ + gulong complete_id; + gulong marker_id; + + ClutterScore *score; + + /* pointer back to the tree structure */ + GNode *node; +}; + +struct _ClutterScorePrivate +{ + GNode *root; + + GHashTable *running_timelines; + + gulong last_id; + + guint is_paused : 1; + guint loop : 1; +}; + +enum +{ + PROP_0, + + PROP_LOOP +}; + +enum +{ + TIMELINE_STARTED, + TIMELINE_COMPLETED, + + STARTED, + PAUSED, + COMPLETED, + + LAST_SIGNAL +}; + +static inline void clutter_score_clear (ClutterScore *score); + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterScore, clutter_score, G_TYPE_OBJECT) + +static int score_signals[LAST_SIGNAL] = { 0 }; + +/* Object */ + +static void +clutter_score_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterScorePrivate *priv; + + priv = clutter_score_get_instance_private (CLUTTER_SCORE (gobject)); + + switch (prop_id) + { + case PROP_LOOP: + priv->loop = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_score_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterScorePrivate *priv; + + priv = clutter_score_get_instance_private (CLUTTER_SCORE (gobject)); + + switch (prop_id) + { + case PROP_LOOP: + g_value_set_boolean (value, priv->loop); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_score_finalize (GObject *object) +{ + ClutterScore *score = CLUTTER_SCORE (object); + + clutter_score_stop (score); + clutter_score_clear (score); + + G_OBJECT_CLASS (clutter_score_parent_class)->finalize (object); +} + +static void +clutter_score_class_init (ClutterScoreClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = clutter_score_set_property; + gobject_class->get_property = clutter_score_get_property; + gobject_class->finalize = clutter_score_finalize; + + /** + * ClutterScore:loop: + * + * Whether the #ClutterScore should restart once finished. + * + * Since: 0.6 + * Deprecated: 1.8 + */ + g_object_class_install_property (gobject_class, + PROP_LOOP, + g_param_spec_boolean ("loop", + "Loop", + "Whether the score should restart once finished", + FALSE, + CLUTTER_PARAM_READWRITE)); + + /** + * ClutterScore::timeline-started: + * @score: the score which received the signal + * @timeline: the current timeline + * + * The ::timeline-started signal is emitted each time a new timeline + * inside a #ClutterScore starts playing. + * + * Since: 0.6 + * Deprecated: 1.8 + */ + score_signals[TIMELINE_STARTED] = + g_signal_new ("timeline-started", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterScoreClass, timeline_started), + NULL, NULL, + _clutter_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, CLUTTER_TYPE_TIMELINE); + /** + * ClutterScore::timeline-completed: + * @score: the score which received the signal + * @timeline: the completed timeline + * + * The ::timeline-completed signal is emitted each time a timeline + * inside a #ClutterScore terminates. + * + * Since: 0.6 + * Deprecated: 1.8 + */ + score_signals[TIMELINE_COMPLETED] = + g_signal_new ("timeline-completed", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterScoreClass, timeline_completed), + NULL, NULL, + _clutter_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CLUTTER_TYPE_TIMELINE); + /** + * ClutterScore::completed: + * @score: the score which received the signal + * + * The ::completed signal is emitted each time a #ClutterScore terminates. + * + * Since: 0.6 + * Deprecated: 1.8 + */ + score_signals[COMPLETED] = + g_signal_new ("completed", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterScoreClass, completed), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + /** + * ClutterScore::started: + * @score: the score which received the signal + * + * The ::started signal is emitted each time a #ClutterScore starts playing. + * + * Since: 0.6 + * Deprecated: 1.8 + */ + score_signals[STARTED] = + g_signal_new ("started", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterScoreClass, started), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + /** + * ClutterScore::paused: + * @score: the score which received the signal + * + * The ::paused signal is emitted each time a #ClutterScore + * is paused. + * + * Since: 0.6 + * Deprecated: 1.8 + */ + score_signals[PAUSED] = + g_signal_new ("paused", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterScoreClass, paused), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +clutter_score_init (ClutterScore *self) +{ + ClutterScorePrivate *priv; + + self->priv = priv = clutter_score_get_instance_private (self); + + /* sentinel */ + priv->root = g_node_new (NULL); + + priv->running_timelines = NULL; + + priv->is_paused = FALSE; + priv->loop = FALSE; + + priv->last_id = 1; +} + +/** + * clutter_score_new: + * + * Creates a new #ClutterScore. A #ClutterScore is an object that can + * hold multiple #ClutterTimelines in a sequential order. + * + * Return value: the newly created #ClutterScore. Use g_object_unref() + * when done. + * + * Since: 0.6 + * Deprecated: 1.8 + */ +ClutterScore * +clutter_score_new (void) +{ + return g_object_new (CLUTTER_TYPE_SCORE, NULL); +} + +/** + * clutter_score_set_loop: + * @score: a #ClutterScore + * @loop: %TRUE for enable looping + * + * Sets whether @score should loop. A looping #ClutterScore will start + * from its initial state after the ::complete signal has been fired. + * + * Since: 0.6 + * Deprecated: 1.8 + */ +void +clutter_score_set_loop (ClutterScore *score, + gboolean loop) +{ + g_return_if_fail (CLUTTER_IS_SCORE (score)); + + if (score->priv->loop != loop) + { + score->priv->loop = loop; + + g_object_notify (G_OBJECT (score), "loop"); + } +} + +/** + * clutter_score_get_loop: + * @score: a #ClutterScore + * + * Gets whether @score is looping + * + * Return value: %TRUE if the score is looping + * + * Since: 0.6 + * Deprecated: 1.8 + */ +gboolean +clutter_score_get_loop (ClutterScore *score) +{ + g_return_val_if_fail (CLUTTER_IS_SCORE (score), FALSE); + + return score->priv->loop; +} + +/** + * clutter_score_is_playing: + * @score: A #ClutterScore + * + * Query state of a #ClutterScore instance. + * + * Return Value: %TRUE if score is currently playing + * + * Since: 0.6 + * Deprecated: 1.8 + */ +gboolean +clutter_score_is_playing (ClutterScore *score) +{ + g_return_val_if_fail (CLUTTER_IS_SCORE (score), FALSE); + + if (score->priv->is_paused) + return FALSE; + + return score->priv->running_timelines + && g_hash_table_size (score->priv->running_timelines) != 0; +} + +/* destroy_entry: + * @node: a #GNode + * + * Frees the #ClutterScoreEntry attached to @node. + */ +static gboolean +destroy_entry (GNode *node, + G_GNUC_UNUSED gpointer data) +{ + ClutterScoreEntry *entry = node->data; + + if (G_LIKELY (entry != NULL)) + { + if (entry->marker_id) + { + g_signal_handler_disconnect (entry->parent, entry->marker_id); + entry->marker_id = 0; + } + + if (entry->complete_id) + { + g_signal_handler_disconnect (entry->timeline, entry->complete_id); + entry->complete_id = 0; + } + + g_object_unref (entry->timeline); + g_free (entry->marker); + g_slice_free (ClutterScoreEntry, entry); + + node->data = NULL; + } + + /* continue */ + return FALSE; +} + +typedef enum { + FIND_BY_TIMELINE, + FIND_BY_ID, + REMOVE_BY_ID, + LIST_TIMELINES +} TraverseAction; + +typedef struct { + TraverseAction action; + + ClutterScore *score; + + /* parameters */ + union { + ClutterTimeline *timeline; + gulong id; + ClutterScoreEntry *entry; + } d; + + gpointer result; +} TraverseClosure; + +/* multi-purpose traversal function for the N-ary tree used by the score */ +static gboolean +traverse_children (GNode *node, + gpointer data) +{ + TraverseClosure *closure = data; + ClutterScoreEntry *entry = node->data; + gboolean retval = FALSE; + + /* root */ + if (!entry) + return TRUE; + + switch (closure->action) + { + case FIND_BY_TIMELINE: + if (closure->d.timeline == entry->timeline) + { + closure->result = node; + retval = TRUE; + } + break; + + case FIND_BY_ID: + if (closure->d.id == entry->id) + { + closure->result = node; + retval = TRUE; + } + break; + + case REMOVE_BY_ID: + if (closure->d.id == entry->id) + { + /* Destroy all the child entries of this node */ + g_node_traverse (node, + G_POST_ORDER, + G_TRAVERSE_ALL, + -1, + destroy_entry, NULL); + + /* Keep track of this node so that it will be destroyed + further up */ + closure->result = node; + + retval = TRUE; + } + break; + + case LIST_TIMELINES: + closure->result = g_slist_prepend (closure->result, entry->timeline); + retval = FALSE; + break; + } + + return retval; +} + +static GNode * +find_entry_by_timeline (ClutterScore *score, + ClutterTimeline *timeline) +{ + ClutterScorePrivate *priv = score->priv; + TraverseClosure closure; + + closure.action = FIND_BY_TIMELINE; + closure.score = score; + closure.d.timeline = timeline; + closure.result = NULL; + + g_node_traverse (priv->root, + G_POST_ORDER, + G_TRAVERSE_ALL, + -1, + traverse_children, &closure); + + if (closure.result) + return closure.result; + + return NULL; +} + +static GNode * +find_entry_by_id (ClutterScore *score, + gulong id_) +{ + ClutterScorePrivate *priv = score->priv; + TraverseClosure closure; + + closure.action = FIND_BY_ID; + closure.score = score; + closure.d.id = id_; + closure.result = NULL; + + g_node_traverse (priv->root, + G_POST_ORDER, + G_TRAVERSE_ALL, + -1, + traverse_children, &closure); + + if (closure.result) + return closure.result; + + return NULL; +} + +/* forward declaration */ +static void start_entry (ClutterScoreEntry *entry); + +static void +start_children_entries (GNode *node, + gpointer data) +{ + ClutterScoreEntry *entry = node->data; + + /* If data is NULL, start all entries that have no marker, otherwise + only start entries that have the same marker */ + if (data == NULL + ? entry->marker == NULL + : (entry->marker && !strcmp (data, entry->marker))) + start_entry (entry); +} + +static void +on_timeline_marker (ClutterTimeline *timeline, + const gchar *marker_name, + gint frame_num, + ClutterScoreEntry *entry) +{ + GNode *parent; + CLUTTER_NOTE (SCHEDULER, "timeline [%p] marker ('%s') reached", + entry->timeline, + entry->marker); + + parent = find_entry_by_timeline (entry->score, timeline); + if (!parent) + return; + + /* start every child */ + if (parent->children) + { + g_node_children_foreach (parent, + G_TRAVERSE_ALL, + start_children_entries, + (gpointer) marker_name); + } +} + +static void +on_timeline_completed (ClutterTimeline *timeline, + ClutterScoreEntry *entry) +{ + ClutterScorePrivate *priv = entry->score->priv; + + g_hash_table_remove (priv->running_timelines, + GUINT_TO_POINTER (entry->id)); + + g_signal_handler_disconnect (timeline, entry->complete_id); + entry->complete_id = 0; + + CLUTTER_NOTE (SCHEDULER, "timeline [%p] ('%lu') completed", + entry->timeline, + entry->id); + + g_signal_emit (entry->score, score_signals[TIMELINE_COMPLETED], 0, + entry->timeline); + + /* start every child */ + if (entry->node->children) + { + g_node_children_foreach (entry->node, + G_TRAVERSE_ALL, + start_children_entries, + NULL); + } + + /* score has finished - fire 'completed' signal */ + if (g_hash_table_size (priv->running_timelines) == 0) + { + CLUTTER_NOTE (SCHEDULER, "looks like we finished"); + + g_signal_emit (entry->score, score_signals[COMPLETED], 0); + + clutter_score_stop (entry->score); + + if (priv->loop) + clutter_score_start (entry->score); + } +} + +static void +start_entry (ClutterScoreEntry *entry) +{ + ClutterScorePrivate *priv = entry->score->priv; + + /* timelines attached to a marker might already be playing when we + * end up here from the ::completed handler, so we need to perform + * this check to avoid restarting those timelines + */ + if (clutter_timeline_is_playing (entry->timeline)) + return; + + entry->complete_id = g_signal_connect (entry->timeline, + "completed", + G_CALLBACK (on_timeline_completed), + entry); + + CLUTTER_NOTE (SCHEDULER, "timeline [%p] ('%lu') started", + entry->timeline, + entry->id); + + if (G_UNLIKELY (priv->running_timelines == NULL)) + priv->running_timelines = g_hash_table_new (NULL, NULL); + + g_hash_table_insert (priv->running_timelines, + GUINT_TO_POINTER (entry->id), + entry); + + clutter_timeline_start (entry->timeline); + + g_signal_emit (entry->score, score_signals[TIMELINE_STARTED], 0, + entry->timeline); +} + +enum +{ + ACTION_START, + ACTION_PAUSE, + ACTION_STOP +}; + +static void +foreach_running_timeline (gpointer key, + gpointer value, + gpointer user_data) +{ + ClutterScoreEntry *entry = value; + gint action = GPOINTER_TO_INT (user_data); + + switch (action) + { + case ACTION_START: + clutter_timeline_start (entry->timeline); + break; + + case ACTION_PAUSE: + clutter_timeline_pause (entry->timeline); + break; + + case ACTION_STOP: + if (entry->complete_id) + { + g_signal_handler_disconnect (entry->timeline, entry->complete_id); + entry->complete_id = 0; + } + clutter_timeline_stop (entry->timeline); + break; + } +} + +/** + * clutter_score_start: + * @score: A #ClutterScore + * + * Starts the score. + * + * Since: 0.6 + * Deprecated: 1.8 + */ +void +clutter_score_start (ClutterScore *score) +{ + ClutterScorePrivate *priv; + + g_return_if_fail (CLUTTER_IS_SCORE (score)); + + priv = score->priv; + + if (priv->is_paused) + { + g_hash_table_foreach (priv->running_timelines, + foreach_running_timeline, + GINT_TO_POINTER (ACTION_START)); + priv->is_paused = FALSE; + } + else + { + g_signal_emit (score, score_signals[STARTED], 0); + g_node_children_foreach (priv->root, + G_TRAVERSE_ALL, + start_children_entries, + NULL); + } +} + +/** + * clutter_score_stop: + * @score: A #ClutterScore + * + * Stops and rewinds a playing #ClutterScore instance. + * + * Since: 0.6 + * Deprecated: 1.8 + */ +void +clutter_score_stop (ClutterScore *score) +{ + ClutterScorePrivate *priv; + + g_return_if_fail (CLUTTER_IS_SCORE (score)); + + priv = score->priv; + + if (priv->running_timelines) + { + g_hash_table_foreach (priv->running_timelines, + foreach_running_timeline, + GINT_TO_POINTER (ACTION_STOP)); + g_hash_table_destroy (priv->running_timelines); + priv->running_timelines = NULL; + } +} + +/** + * clutter_score_pause: + * @score: a #ClutterScore + * + * Pauses a playing score @score. + * + * Since: 0.6 + * Deprecated: 1.8 + */ +void +clutter_score_pause (ClutterScore *score) +{ + ClutterScorePrivate *priv; + + g_return_if_fail (CLUTTER_IS_SCORE (score)); + + priv = score->priv; + + if (!clutter_score_is_playing (score)) + return; + + g_hash_table_foreach (priv->running_timelines, + foreach_running_timeline, + GINT_TO_POINTER (ACTION_PAUSE)); + + priv->is_paused = TRUE; + + g_signal_emit (score, score_signals[PAUSED], 0); +} + +/** + * clutter_score_rewind: + * @score: A #ClutterScore + * + * Rewinds a #ClutterScore to its initial state. + * + * Since: 0.6 + * Deprecated: 1.8 + */ +void +clutter_score_rewind (ClutterScore *score) +{ + gboolean was_playing; + + g_return_if_fail (CLUTTER_IS_SCORE (score)); + + was_playing = clutter_score_is_playing (score); + + clutter_score_stop (score); + + if (was_playing) + clutter_score_start (score); +} + +static inline void +clutter_score_clear (ClutterScore *score) +{ + ClutterScorePrivate *priv = score->priv; + + g_node_traverse (priv->root, + G_POST_ORDER, + G_TRAVERSE_ALL, + -1, + destroy_entry, NULL); + g_node_destroy (priv->root); +} + +/** + * clutter_score_append: + * @score: a #ClutterScore + * @parent: (allow-none): a #ClutterTimeline in the score, or %NULL + * @timeline: a #ClutterTimeline + * + * Appends a timeline to another one existing in the score; the newly + * appended timeline will be started when @parent is complete. + * + * If @parent is %NULL, the new #ClutterTimeline will be started when + * clutter_score_start() is called. + * + * #ClutterScore will take a reference on @timeline. + * + * Return value: the id of the #ClutterTimeline inside the score, or + * 0 on failure. The returned id can be used with clutter_score_remove() + * or clutter_score_get_timeline(). + * + * Since: 0.6 + * Deprecated: 1.8 + */ +gulong +clutter_score_append (ClutterScore *score, + ClutterTimeline *parent, + ClutterTimeline *timeline) +{ + ClutterScorePrivate *priv; + ClutterScoreEntry *entry; + + g_return_val_if_fail (CLUTTER_IS_SCORE (score), 0); + g_return_val_if_fail (parent == NULL || CLUTTER_IS_TIMELINE (parent), 0); + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), 0); + + priv = score->priv; + + if (!parent) + { + entry = g_slice_new (ClutterScoreEntry); + entry->timeline = g_object_ref (timeline); + entry->parent = NULL; + entry->id = priv->last_id; + entry->marker = NULL; + entry->marker_id = 0; + entry->complete_id = 0; + entry->score = score; + + entry->node = g_node_append_data (priv->root, entry); + } + else + { + GNode *node; + + node = find_entry_by_timeline (score, parent); + if (G_UNLIKELY (!node)) + { + g_warning ("Unable to find the parent timeline inside the score."); + return 0; + } + + entry = g_slice_new (ClutterScoreEntry); + entry->timeline = g_object_ref (timeline); + entry->parent = parent; + entry->id = priv->last_id; + entry->marker = NULL; + entry->marker_id = 0; + entry->complete_id = 0; + entry->score = score; + + entry->node = g_node_append_data (node, entry); + } + + priv->last_id += 1; + + return entry->id; +} + +/** + * clutter_score_append_at_marker: + * @score: a #ClutterScore + * @parent: the parent #ClutterTimeline + * @marker_name: the name of the marker to use + * @timeline: the #ClutterTimeline to append + * + * Appends @timeline at the given @marker_name on the @parent + * #ClutterTimeline. + * + * If you want to append @timeline at the end of @parent, use + * clutter_score_append(). + * + * The #ClutterScore will take a reference on @timeline. + * + * Return value: the id of the #ClutterTimeline inside the score, or + * 0 on failure. The returned id can be used with clutter_score_remove() + * or clutter_score_get_timeline(). + * + * Since: 0.8 + * Deprecated: 1.8 + */ +gulong +clutter_score_append_at_marker (ClutterScore *score, + ClutterTimeline *parent, + const gchar *marker_name, + ClutterTimeline *timeline) +{ + ClutterScorePrivate *priv; + GNode *node; + ClutterScoreEntry *entry; + gchar *marker_reached_signal; + + g_return_val_if_fail (CLUTTER_IS_SCORE (score), 0); + g_return_val_if_fail (CLUTTER_IS_TIMELINE (parent), 0); + g_return_val_if_fail (marker_name != NULL, 0); + g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), 0); + + if (!clutter_timeline_has_marker (parent, marker_name)) + { + g_warning ("The parent timeline has no marker '%s'", marker_name); + return 0; + } + + priv = score->priv; + + node = find_entry_by_timeline (score, parent); + if (G_UNLIKELY (!node)) + { + g_warning ("Unable to find the parent timeline inside the score."); + return 0; + } + + entry = g_slice_new (ClutterScoreEntry); + entry->timeline = g_object_ref (timeline); + entry->parent = parent; + entry->marker = g_strdup (marker_name); + entry->id = priv->last_id; + entry->score = score; + entry->complete_id = 0; + + marker_reached_signal = g_strdup_printf ("marker-reached::%s", marker_name); + entry->marker_id = g_signal_connect (entry->parent, + marker_reached_signal, + G_CALLBACK (on_timeline_marker), + entry); + + entry->node = g_node_append_data (node, entry); + + g_free (marker_reached_signal); + + priv->last_id += 1; + + return entry->id; +} + +/** + * clutter_score_remove: + * @score: a #ClutterScore + * @id_: the id of the timeline to remove + * + * Removes the #ClutterTimeline with the given id inside @score. If + * the timeline has other timelines attached to it, those are removed + * as well. + * + * Since: 0.6 + * Deprecated: 1.8 + */ +void +clutter_score_remove (ClutterScore *score, + gulong id_) +{ + ClutterScorePrivate *priv; + TraverseClosure closure; + + g_return_if_fail (CLUTTER_IS_SCORE (score)); + g_return_if_fail (id_ > 0); + + priv = score->priv; + + closure.action = REMOVE_BY_ID; + closure.score = score; + closure.d.id = id_; + closure.result = NULL; + + g_node_traverse (priv->root, + G_POST_ORDER, + G_TRAVERSE_ALL, + -1, + traverse_children, &closure); + + if (closure.result) + g_node_destroy (closure.result); +} + +/** + * clutter_score_remove_all: + * @score: a #ClutterScore + * + * Removes all the timelines inside @score. + * + * Since: 0.6 + * Deprecated: 1.8 + */ +void +clutter_score_remove_all (ClutterScore *score) +{ + ClutterScorePrivate *priv; + + g_return_if_fail (CLUTTER_IS_SCORE (score)); + + priv = score->priv; + + /* this will take care of the running timelines */ + clutter_score_stop (score); + + /* destroy all the contents of the tree */ + clutter_score_clear (score); + + /* recreate the sentinel */ + priv->root = g_node_new (NULL); +} + +/** + * clutter_score_get_timeline: + * @score: a #ClutterScore + * @id_: the id of the timeline + * + * Retrieves the #ClutterTimeline for @id_ inside @score. + * + * Return value: (transfer none): the requested timeline, or %NULL. This + * function does not increase the reference count on the returned + * #ClutterTimeline + * + * Since: 0.6 + * Deprecated: 1.8 + */ +ClutterTimeline * +clutter_score_get_timeline (ClutterScore *score, + gulong id_) +{ + GNode *node; + ClutterScoreEntry *entry; + + g_return_val_if_fail (CLUTTER_IS_SCORE (score), NULL); + g_return_val_if_fail (id_ > 0, NULL); + + node = find_entry_by_id (score, id_); + if (G_UNLIKELY (!node)) + return NULL; + + entry = node->data; + + return entry->timeline; +} + +/** + * clutter_score_list_timelines: + * @score: a #ClutterScore + * + * Retrieves a list of all the #ClutterTimelines managed by @score. + * + * Return value: (transfer container) (element-type Clutter.Timeline): a + * #GSList containing all the timelines in the score. This function does + * not increase the reference count of the returned timelines. Use + * g_slist_free() on the returned list to deallocate its resources. + * + * Since: 0.6 + * Deprecated: 1.8 + */ +GSList * +clutter_score_list_timelines (ClutterScore *score) +{ + ClutterScorePrivate *priv; + TraverseClosure closure; + GSList *retval; + + g_return_val_if_fail (CLUTTER_IS_SCORE (score), NULL); + + priv = score->priv; + + closure.action = LIST_TIMELINES; + closure.result = NULL; + + g_node_traverse (priv->root, + G_POST_ORDER, + G_TRAVERSE_ALL, + -1, + traverse_children, &closure); + + retval = closure.result; + + return retval; +} diff --git a/clutter/clutter/deprecated/clutter-score.h b/clutter/clutter/deprecated/clutter-score.h new file mode 100644 index 0000000..301dabd --- /dev/null +++ b/clutter/clutter/deprecated/clutter-score.h @@ -0,0 +1,144 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_SCORE_H__ +#define __CLUTTER_SCORE_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_SCORE (clutter_score_get_type ()) + +#define CLUTTER_SCORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_SCORE, ClutterScore)) +#define CLUTTER_SCORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_SCORE, ClutterScoreClass)) +#define CLUTTER_IS_SCORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_SCORE)) +#define CLUTTER_IS_SCORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_SCORE)) +#define CLUTTER_SCORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_SCORE, ClutterScoreClass)) + +typedef struct _ClutterScore ClutterScore; +typedef struct _ClutterScorePrivate ClutterScorePrivate; +typedef struct _ClutterScoreClass ClutterScoreClass; + +/** + * ClutterScore: + * + * The #ClutterScore structure contains only private data + * and should be accessed using the provided API + * + * Since: 0.6 + */ +struct _ClutterScore +{ + /*< private >*/ + GObject parent; + ClutterScorePrivate *priv; +}; + +/** + * ClutterScoreClass: + * @timeline_started: handler for the #ClutterScore::timeline-started signal + * @timeline_completed: handler for the #ClutterScore::timeline-completed + * signal + * @started: handler for the #ClutterScore::started signal + * @completed: handler for the #ClutterScore::completed signal + * @paused: handler for the #ClutterScore::paused signal + * + * The #ClutterScoreClass structure contains only private data + * + * Since: 0.6 + */ +struct _ClutterScoreClass +{ + /*< private >*/ + GObjectClass parent_class; + + /*< public >*/ + void (* timeline_started) (ClutterScore *score, + ClutterTimeline *timeline); + void (* timeline_completed) (ClutterScore *score, + ClutterTimeline *timeline); + + void (* started) (ClutterScore *score); + void (* completed) (ClutterScore *score); + void (* paused) (ClutterScore *score); + + /*< private >*/ + /* padding for future expansion */ + void (*_clutter_score_1) (void); + void (*_clutter_score_2) (void); + void (*_clutter_score_3) (void); + void (*_clutter_score_4) (void); + void (*_clutter_score_5) (void); +}; + +CLUTTER_DEPRECATED_IN_1_8 +GType clutter_score_get_type (void) G_GNUC_CONST; + +CLUTTER_DEPRECATED_IN_1_8 +ClutterScore * clutter_score_new (void); + +CLUTTER_DEPRECATED_IN_1_8 +void clutter_score_set_loop (ClutterScore *score, + gboolean loop); +CLUTTER_DEPRECATED_IN_1_8 +gboolean clutter_score_get_loop (ClutterScore *score); + +CLUTTER_DEPRECATED_IN_1_8 +gulong clutter_score_append (ClutterScore *score, + ClutterTimeline *parent, + ClutterTimeline *timeline); +CLUTTER_DEPRECATED_IN_1_8 +gulong clutter_score_append_at_marker (ClutterScore *score, + ClutterTimeline *parent, + const gchar *marker_name, + ClutterTimeline *timeline); +CLUTTER_DEPRECATED_IN_1_8 +void clutter_score_remove (ClutterScore *score, + gulong id_); +CLUTTER_DEPRECATED_IN_1_8 +void clutter_score_remove_all (ClutterScore *score); +CLUTTER_DEPRECATED_IN_1_8 +ClutterTimeline *clutter_score_get_timeline (ClutterScore *score, + gulong id_); +CLUTTER_DEPRECATED_IN_1_8 +GSList * clutter_score_list_timelines (ClutterScore *score); + +CLUTTER_DEPRECATED_IN_1_8 +void clutter_score_start (ClutterScore *score); +CLUTTER_DEPRECATED_IN_1_8 +void clutter_score_stop (ClutterScore *score); +CLUTTER_DEPRECATED_IN_1_8 +void clutter_score_pause (ClutterScore *score); +CLUTTER_DEPRECATED_IN_1_8 +void clutter_score_rewind (ClutterScore *score); +CLUTTER_DEPRECATED_IN_1_8 +gboolean clutter_score_is_playing (ClutterScore *score); + +G_END_DECLS + +#endif /* __CLUTTER_SCORE_H__ */ diff --git a/clutter/clutter/deprecated/clutter-shader.c b/clutter/clutter/deprecated/clutter-shader.c new file mode 100644 index 0000000..60f15c6 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-shader.c @@ -0,0 +1,933 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By: Matthew Allum + * Øyvind KolÃ¥s + * Emmanuele Bassi + * + * Copyright (C) 2007, 2008 OpenedHand + * Copyright (C) 2009 Intel Corp + * + * 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 . + * + * + */ + +/** + * SECTION:clutter-shader + * @short_description: Programmable pipeline abstraction + * + * #ClutterShader is an object providing an abstraction over the + * OpenGL programmable pipeline. By using #ClutterShaders is + * possible to override the drawing pipeline by using small programs + * also known as "shaders". + * + * #ClutterShader is available since Clutter 0.6. + * + * #ClutterShader is deprecated since Clutter 1.8; use #ClutterShaderEffect + * in newly written code, instead. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS + +#include + +#include + +#include "clutter-shader.h" + +#include "clutter-debug.h" +#include "clutter-private.h" + +/* global list of shaders */ +static GList *clutter_shaders_list = NULL; + +struct _ClutterShaderPrivate +{ + guint compiled : 1; /* Shader is bound to the GL context */ + guint is_enabled : 1; + guint vertex_is_glsl : 1; + guint fragment_is_glsl : 1; + + gchar *vertex_source; /* GLSL source for vertex shader */ + gchar *fragment_source; /* GLSL source for fragment shader */ + + CoglHandle program; + + CoglHandle vertex_shader; + CoglHandle fragment_shader; +}; + +enum +{ + PROP_0, + + PROP_VERTEX_SOURCE, + PROP_FRAGMENT_SOURCE, + PROP_COMPILED, + PROP_ENABLED, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterShader, clutter_shader, G_TYPE_OBJECT) + +static inline void +clutter_shader_release_internal (ClutterShader *shader) +{ + ClutterShaderPrivate *priv = shader->priv; + + if (!priv->compiled) + return; + + g_assert (priv->program != COGL_INVALID_HANDLE); + + if (priv->vertex_is_glsl && priv->vertex_shader != COGL_INVALID_HANDLE) + cogl_handle_unref (priv->vertex_shader); + + if (priv->fragment_is_glsl && priv->fragment_shader != COGL_INVALID_HANDLE) + cogl_handle_unref (priv->fragment_shader); + + if (priv->program != COGL_INVALID_HANDLE) + cogl_handle_unref (priv->program); + + priv->vertex_shader = COGL_INVALID_HANDLE; + priv->fragment_shader = COGL_INVALID_HANDLE; + priv->program = COGL_INVALID_HANDLE; + priv->compiled = FALSE; +} + +static void +clutter_shader_finalize (GObject *object) +{ + ClutterShader *shader; + ClutterShaderPrivate *priv; + + shader = CLUTTER_SHADER (object); + priv = shader->priv; + + clutter_shaders_list = g_list_remove (clutter_shaders_list, object); + + g_free (priv->fragment_source); + g_free (priv->vertex_source); + + G_OBJECT_CLASS (clutter_shader_parent_class)->finalize (object); +} + +static void +clutter_shader_dispose (GObject *object) +{ + ClutterShader *shader = CLUTTER_SHADER (object); + + clutter_shader_release_internal (shader); + + G_OBJECT_CLASS (clutter_shader_parent_class)->finalize (object); +} + +static void +clutter_shader_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterShader *shader = CLUTTER_SHADER(object); + + switch (prop_id) + { + case PROP_VERTEX_SOURCE: + clutter_shader_set_vertex_source (shader, + g_value_get_string (value), -1); + break; + case PROP_FRAGMENT_SOURCE: + clutter_shader_set_fragment_source (shader, + g_value_get_string (value), -1); + break; + case PROP_ENABLED: + clutter_shader_set_is_enabled (shader, g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_shader_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterShader *shader; + ClutterShaderPrivate *priv; + + shader = CLUTTER_SHADER(object); + priv = shader->priv; + + switch (prop_id) + { + case PROP_VERTEX_SOURCE: + g_value_set_string (value, priv->vertex_source); + break; + case PROP_FRAGMENT_SOURCE: + g_value_set_string (value, priv->fragment_source); + break; + case PROP_COMPILED: + g_value_set_boolean (value, priv->compiled); + break; + case PROP_ENABLED: + g_value_set_boolean (value, priv->is_enabled); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GObject * +clutter_shader_constructor (GType type, + guint n_params, + GObjectConstructParam *params) +{ + GObjectClass *parent_class; + GObject *object; + + parent_class = G_OBJECT_CLASS (clutter_shader_parent_class); + object = parent_class->constructor (type, n_params, params); + + /* add this instance to the global list of shaders */ + clutter_shaders_list = g_list_prepend (clutter_shaders_list, object); + + return object; +} + +static void +clutter_shader_class_init (ClutterShaderClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GParamSpec *pspec = NULL; + + object_class->finalize = clutter_shader_finalize; + object_class->dispose = clutter_shader_dispose; + object_class->set_property = clutter_shader_set_property; + object_class->get_property = clutter_shader_get_property; + object_class->constructor = clutter_shader_constructor; + + /** + * ClutterShader:vertex-source: + * + * GLSL source code for the vertex shader part of the shader + * program, if any + * + * Since: 0.6 + * + * Deprecated: 1.8: Use #ClutterShaderEffect instead. + */ + pspec = g_param_spec_string ("vertex-source", + P_("Vertex Source"), + P_("Source of vertex shader"), + NULL, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_VERTEX_SOURCE] = pspec; + g_object_class_install_property (object_class, PROP_VERTEX_SOURCE, pspec); + + /** + * ClutterShader:fragment-source: + * + * GLSL source code for the fragment shader part of the shader program. + * + * Since: 0.6 + * + * Deprecated: 1.8: Use #ClutterShaderEffect instead. + */ + pspec = g_param_spec_string ("fragment-source", + P_("Fragment Source"), + P_("Source of fragment shader"), + NULL, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_FRAGMENT_SOURCE] = pspec; + g_object_class_install_property (object_class, PROP_FRAGMENT_SOURCE, pspec); + + /** + * ClutterShader:compiled: + * + * Whether the shader is compiled and linked, ready for use + * in the GL context. + * + * Since: 0.8 + * + * Deprecated: 1.8: Use #ClutterShaderEffect instead. + */ + pspec = g_param_spec_boolean ("compiled", + P_("Compiled"), + P_("Whether the shader is compiled and linked"), + FALSE, + CLUTTER_PARAM_READABLE); + obj_props[PROP_COMPILED] = pspec; + g_object_class_install_property (object_class, PROP_COMPILED, pspec); + + /** + * ClutterShader:enabled: + * + * Whether the shader is currently used in the GL rendering pipeline. + * + * Since: 0.6 + * + * Deprecated: 1.8: Use #ClutterShaderEffect instead. + */ + pspec = g_param_spec_boolean ("enabled", + P_("Enabled"), + P_("Whether the shader is enabled"), + FALSE, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_ENABLED] = pspec; + g_object_class_install_property (object_class, PROP_ENABLED, pspec); +} + +static void +clutter_shader_init (ClutterShader *self) +{ + ClutterShaderPrivate *priv; + + priv = self->priv = clutter_shader_get_instance_private (self); + + priv->compiled = FALSE; + + priv->vertex_source = NULL; + priv->fragment_source = NULL; + + priv->program = COGL_INVALID_HANDLE; + priv->vertex_shader = COGL_INVALID_HANDLE; + priv->fragment_shader = COGL_INVALID_HANDLE; +} + +/** + * clutter_shader_new: + * + * Create a new #ClutterShader instance. + * + * Return value: a new #ClutterShader. + * + * Since: 0.6 + * + * Deprecated: 1.8: Use #ClutterShaderEffect instead. + */ +ClutterShader * +clutter_shader_new (void) +{ + return g_object_new (CLUTTER_TYPE_SHADER, NULL); +} + +static inline void +clutter_shader_set_source (ClutterShader *shader, + ClutterShaderType shader_type, + const gchar *data, + gssize length) +{ + ClutterShaderPrivate *priv = shader->priv; + gboolean is_glsl = FALSE; + + if (length < 0) + length = strlen (data); + + g_object_freeze_notify (G_OBJECT (shader)); + + /* release shader if bound when changing the source, the shader will + * automatically be rebound on the next use. + */ + if (clutter_shader_is_compiled (shader)) + clutter_shader_release (shader); + + is_glsl = !g_str_has_prefix (data, "!!ARBfp"); + + CLUTTER_NOTE (SHADER, + "setting %s shader (GLSL:%s, len:%" G_GSSIZE_FORMAT ")", + shader_type == CLUTTER_VERTEX_SHADER ? "vertex" : "fragment", + is_glsl ? "yes" : "no", + length); + + switch (shader_type) + { + case CLUTTER_FRAGMENT_SHADER: + g_free (priv->fragment_source); + + priv->fragment_source = g_strndup (data, length); + priv->fragment_is_glsl = is_glsl; + g_object_notify_by_pspec (G_OBJECT (shader), obj_props[PROP_FRAGMENT_SOURCE]); + break; + + case CLUTTER_VERTEX_SHADER: + g_free (priv->vertex_source); + + priv->vertex_source = g_strndup (data, length); + priv->vertex_is_glsl = is_glsl; + g_object_notify_by_pspec (G_OBJECT (shader), obj_props[PROP_VERTEX_SOURCE]); + break; + } + + g_object_thaw_notify (G_OBJECT (shader)); +} + +/** + * clutter_shader_set_fragment_source: + * @shader: a #ClutterShader + * @data: GLSL source code. + * @length: length of source buffer (currently ignored) + * + * Sets the GLSL source code to be used by a #ClutterShader for the fragment + * program. + * + * Since: 0.6 + * + * Deprecated: 1.8: Use #ClutterShaderEffect instead. + */ +void +clutter_shader_set_fragment_source (ClutterShader *shader, + const gchar *data, + gssize length) +{ + g_return_if_fail (CLUTTER_IS_SHADER (shader)); + g_return_if_fail (data != NULL); + + clutter_shader_set_source (shader, CLUTTER_FRAGMENT_SHADER, data, length); +} + +/** + * clutter_shader_set_vertex_source: + * @shader: a #ClutterShader + * @data: GLSL source code. + * @length: length of source buffer (currently ignored) + * + * Sets the GLSL source code to be used by a #ClutterShader for the vertex + * program. + * + * Since: 0.6 + * + * Deprecated: 1.8: Use #ClutterShaderEffect instead. + */ +void +clutter_shader_set_vertex_source (ClutterShader *shader, + const gchar *data, + gssize length) +{ + g_return_if_fail (CLUTTER_IS_SHADER (shader)); + g_return_if_fail (data != NULL); + + clutter_shader_set_source (shader, CLUTTER_VERTEX_SHADER, data, length); +} + +static const gchar * +clutter_shader_get_source (ClutterShader *shader, + ClutterShaderType shader_type) +{ + switch (shader_type) + { + case CLUTTER_FRAGMENT_SHADER: + return shader->priv->fragment_source; + + case CLUTTER_VERTEX_SHADER: + return shader->priv->vertex_source; + } + + return NULL; +} + +static CoglHandle +clutter_shader_get_cogl_shader (ClutterShader *shader, + ClutterShaderType shader_type) +{ + switch (shader_type) + { + case CLUTTER_FRAGMENT_SHADER: + return shader->priv->fragment_shader; + + case CLUTTER_VERTEX_SHADER: + return shader->priv->vertex_shader; + } + + return COGL_INVALID_HANDLE; +} + +static gboolean +clutter_shader_glsl_bind (ClutterShader *self, + ClutterShaderType shader_type, + GError **error) +{ + ClutterShaderPrivate *priv = self->priv; + CoglHandle shader = COGL_INVALID_HANDLE; + + switch (shader_type) + { + case CLUTTER_VERTEX_SHADER: + shader = cogl_create_shader (COGL_SHADER_TYPE_VERTEX); + cogl_shader_source (shader, priv->vertex_source); + + priv->vertex_shader = shader; + break; + + case CLUTTER_FRAGMENT_SHADER: + shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT); + cogl_shader_source (shader, priv->fragment_source); + + priv->fragment_shader = shader; + break; + } + + g_assert (shader != COGL_INVALID_HANDLE); + + cogl_shader_compile (shader); + if (!cogl_shader_is_compiled (shader)) + { + gchar *log_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"), + log_buf); + + g_free (log_buf); + + return FALSE; + } + + cogl_program_attach_shader (priv->program, shader); + + return TRUE; +} + +static gboolean +bind_glsl_shader (ClutterShader *self, + GError **error) +{ + ClutterShaderPrivate *priv = self->priv; + GError *bind_error = NULL; + gboolean res; + + priv->program = cogl_create_program (); + + if (priv->vertex_is_glsl && priv->vertex_source != COGL_INVALID_HANDLE) + { + res = clutter_shader_glsl_bind (self, + CLUTTER_VERTEX_SHADER, + &bind_error); + + if (!res) + { + g_propagate_error (error, bind_error); + return FALSE; + } + } + + if (priv->fragment_is_glsl && priv->fragment_source != COGL_INVALID_HANDLE) + { + res = clutter_shader_glsl_bind (self, + CLUTTER_FRAGMENT_SHADER, + &bind_error); + + if (!res) + { + g_propagate_error (error, bind_error); + return FALSE; + } + } + + cogl_program_link (priv->program); + + return TRUE; +} + +/** + * clutter_shader_compile: + * @shader: a #ClutterShader + * @error: return location for a #GError, or %NULL + * + * Compiles and links GLSL sources set for vertex and fragment shaders for + * a #ClutterShader. If the compilation fails and a #GError return location is + * provided the error will contain the errors from the compiler, if any. + * + * Return value: returns TRUE if the shader was succesfully compiled. + * + * Since: 0.8 + * + * Deprecated: 1.8: Use #ClutterShaderEffect instead. + */ +gboolean +clutter_shader_compile (ClutterShader *shader, + GError **error) +{ + ClutterShaderPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_SHADER (shader), FALSE); + + priv = shader->priv; + + if (priv->compiled) + return priv->compiled; + + if ((priv->vertex_source != COGL_INVALID_HANDLE && !priv->vertex_is_glsl) || + (priv->fragment_source != COGL_INVALID_HANDLE && !priv->fragment_is_glsl)) + { + /* XXX: Could remove this check, since we only advertise support for GLSL + * shaders anyways. */ + g_set_error (error, CLUTTER_SHADER_ERROR, + CLUTTER_SHADER_ERROR_NO_ASM, + "ASM shaders not supported"); + priv->compiled = FALSE; + return priv->compiled; + } + + if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) + { + g_set_error (error, CLUTTER_SHADER_ERROR, + CLUTTER_SHADER_ERROR_NO_GLSL, + "GLSL shaders not supported"); + priv->compiled = FALSE; + return priv->compiled; + } + + priv->compiled = bind_glsl_shader (shader, error); + g_object_notify_by_pspec (G_OBJECT (shader), obj_props[PROP_COMPILED]); + + return priv->compiled; +} + +/** + * clutter_shader_release: + * @shader: a #ClutterShader + * + * Frees up any GL context resources held by the shader. + * + * Since: 0.6 + * + * Deprecated: 1.8: Use #ClutterShaderEffect instead. + */ +void +clutter_shader_release (ClutterShader *shader) +{ + g_return_if_fail (CLUTTER_IS_SHADER (shader)); + + clutter_shader_release_internal (shader); + + g_object_notify_by_pspec (G_OBJECT (shader), obj_props[PROP_COMPILED]); +} + +/** + * clutter_shader_is_compiled: + * @shader: a #ClutterShader + * + * Checks whether @shader is is currently compiled, linked and bound + * to the GL context. + * + * Return value: %TRUE if the shader is compiled, linked and ready for use. + * + * Since: 0.8 + * + * Deprecated: 1.8: Use #ClutterShaderEffect instead. + */ +gboolean +clutter_shader_is_compiled (ClutterShader *shader) +{ + g_return_val_if_fail (CLUTTER_IS_SHADER (shader), FALSE); + + return shader->priv->compiled; +} + +/** + * clutter_shader_set_is_enabled: + * @shader: a #ClutterShader + * @enabled: The new state of the shader. + * + * Enables a shader. This function will attempt to compile and link + * the shader, if it isn't already. + * + * When @enabled is %FALSE the default state of the GL pipeline will be + * used instead. + * + * Since: 0.6 + * + * Deprecated: 1.8: Use #ClutterShaderEffect instead. + */ +void +clutter_shader_set_is_enabled (ClutterShader *shader, + gboolean enabled) +{ + ClutterShaderPrivate *priv; + + g_return_if_fail (CLUTTER_IS_SHADER (shader)); + + priv = shader->priv; + + if (priv->is_enabled != enabled) + { + GError *error = NULL; + gboolean res; + + res = clutter_shader_compile (shader, &error); + if (!res) + { + g_warning ("Unable to bind the shader: %s", + error ? error->message : "unknown error"); + if (error) + g_error_free (error); + + return; + } + + priv->is_enabled = enabled; + + if (priv->is_enabled) + cogl_program_use (priv->program); + else + cogl_program_use (COGL_INVALID_HANDLE); + + g_object_notify_by_pspec (G_OBJECT (shader), obj_props[PROP_ENABLED]); + } +} + +/** + * clutter_shader_get_is_enabled: + * @shader: a #ClutterShader + * + * Checks whether @shader is enabled. + * + * Return value: %TRUE if the shader is enabled. + * + * Since: 0.6 + * + * Deprecated: 1.8: Use #ClutterShaderEffect instead. + */ +gboolean +clutter_shader_get_is_enabled (ClutterShader *shader) +{ + g_return_val_if_fail (CLUTTER_IS_SHADER (shader), FALSE); + + return shader->priv->is_enabled; +} + +/** + * clutter_shader_set_uniform: + * @shader: a #ClutterShader. + * @name: name of uniform in GLSL shader program to set. + * @value: a #ClutterShaderFloat, #ClutterShaderInt or #ClutterShaderMatrix + * #GValue. + * + * Sets a user configurable variable in the GLSL shader programs attached to + * a #ClutterShader. + * + * Since: 1.0 + * + * Deprecated: 1.8: Use #ClutterShaderEffect instead. + */ +void +clutter_shader_set_uniform (ClutterShader *shader, + const gchar *name, + const GValue *value) +{ + ClutterShaderPrivate *priv; + int location = 0; + gsize size; + + g_return_if_fail (CLUTTER_IS_SHADER (shader)); + g_return_if_fail (name != NULL); + g_return_if_fail (value != NULL); + g_return_if_fail (CLUTTER_VALUE_HOLDS_SHADER_FLOAT (value) || + CLUTTER_VALUE_HOLDS_SHADER_INT (value) || + CLUTTER_VALUE_HOLDS_SHADER_MATRIX (value) || + G_VALUE_HOLDS_FLOAT (value) || + G_VALUE_HOLDS_INT (value)); + + priv = shader->priv; + g_return_if_fail (priv->program != COGL_INVALID_HANDLE); + + location = cogl_program_get_uniform_location (priv->program, name); + + if (CLUTTER_VALUE_HOLDS_SHADER_FLOAT (value)) + { + const float *floats; + + floats = clutter_value_get_shader_float (value, &size); + cogl_program_set_uniform_float (priv->program, + location, size, 1, floats); + } + else if (CLUTTER_VALUE_HOLDS_SHADER_INT (value)) + { + const int *ints; + + ints = clutter_value_get_shader_int (value, &size); + cogl_program_set_uniform_int (priv->program, + location, size, 1, ints); + } + else if (CLUTTER_VALUE_HOLDS_SHADER_MATRIX (value)) + { + const float *matrix; + + matrix = clutter_value_get_shader_matrix (value, &size); + cogl_program_set_uniform_matrix (priv->program, + location, size, 1, FALSE, matrix); + } + else if (G_VALUE_HOLDS_FLOAT (value)) + { + float float_val = g_value_get_float (value); + + cogl_program_set_uniform_float (priv->program, + location, 1, 1, &float_val); + } + else if (G_VALUE_HOLDS_INT (value)) + { + int int_val = g_value_get_int (value); + + cogl_program_set_uniform_int (priv->program, + location, 1, 1, &int_val); + } + else + g_assert_not_reached (); +} + +/** + * clutter_shader_get_fragment_source: + * @shader: a #ClutterShader + * + * Query the current GLSL fragment source set on @shader. + * + * Return value: the source of the fragment shader for this + * ClutterShader object or %NULL. The returned string is owned by the + * shader object and should never be modified or freed + * + * Since: 0.6 + * + * Deprecated: 1.8: Use #ClutterShaderEffect instead. + */ +const gchar * +clutter_shader_get_fragment_source (ClutterShader *shader) +{ + g_return_val_if_fail (CLUTTER_IS_SHADER (shader), NULL); + + return clutter_shader_get_source (shader, CLUTTER_FRAGMENT_SHADER); +} + +/** + * clutter_shader_get_vertex_source: + * @shader: a #ClutterShader + * + * Query the current GLSL vertex source set on @shader. + * + * Return value: the source of the vertex shader for this + * ClutterShader object or %NULL. The returned string is owned by the + * shader object and should never be modified or freed + * + * Since: 0.6 + * + * Deprecated: 1.8: Use #ClutterShaderEffect instead. + */ +const gchar * +clutter_shader_get_vertex_source (ClutterShader *shader) +{ + g_return_val_if_fail (CLUTTER_IS_SHADER (shader), NULL); + + return clutter_shader_get_source (shader, CLUTTER_VERTEX_SHADER); +} + +/** + * clutter_shader_get_cogl_program: + * @shader: a #ClutterShader + * + * Retrieves the underlying #CoglHandle for the shader program. + * + * Return value: (transfer none): A #CoglHandle for the shader program, + * or %NULL. The handle is owned by the #ClutterShader and it should + * not be unreferenced + * + * Since: 1.0 + * + * Deprecated: 1.8: Use #ClutterShaderEffect instead. + */ +CoglHandle +clutter_shader_get_cogl_program (ClutterShader *shader) +{ + g_return_val_if_fail (CLUTTER_IS_SHADER (shader), NULL); + + return shader->priv->program; +} + +/** + * clutter_shader_get_cogl_fragment_shader: + * @shader: a #ClutterShader + * + * Retrieves the underlying #CoglHandle for the fragment shader. + * + * Return value: (transfer none): A #CoglHandle for the fragment + * shader, or %NULL. The handle is owned by the #ClutterShader + * and it should not be unreferenced + * + * Since: 1.0 + * + * Deprecated: 1.8: Use #ClutterShaderEffect instead. + */ +CoglHandle +clutter_shader_get_cogl_fragment_shader (ClutterShader *shader) +{ + g_return_val_if_fail (CLUTTER_IS_SHADER (shader), NULL); + + return clutter_shader_get_cogl_shader (shader, CLUTTER_FRAGMENT_SHADER); +} + +/** + * clutter_shader_get_cogl_vertex_shader: + * @shader: a #ClutterShader + * + * Retrieves the underlying #CoglHandle for the vertex shader. + * + * Return value: (transfer none): A #CoglHandle for the vertex + * shader, or %NULL. The handle is owned by the #ClutterShader + * and it should not be unreferenced + * + * Since: 1.0 + * + * Deprecated: 1.8: Use #ClutterShaderEffect instead. + */ +CoglHandle +clutter_shader_get_cogl_vertex_shader (ClutterShader *shader) +{ + g_return_val_if_fail (CLUTTER_IS_SHADER (shader), NULL); + + return clutter_shader_get_cogl_shader (shader, CLUTTER_VERTEX_SHADER); +} + +GQuark +clutter_shader_error_quark (void) +{ + return g_quark_from_static_string ("clutter-shader-error"); +} diff --git a/clutter/clutter/deprecated/clutter-shader.h b/clutter/clutter/deprecated/clutter-shader.h new file mode 100644 index 0000000..a04b8dd --- /dev/null +++ b/clutter/clutter/deprecated/clutter-shader.h @@ -0,0 +1,182 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * Øyvind KolÃ¥s + * + * Copyright (C) 2007 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_SHADER_H__ +#define __CLUTTER_SHADER_H__ + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_SHADER (clutter_shader_get_type ()) +#define CLUTTER_SHADER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CLUTTER_TYPE_SHADER, ClutterShader)) +#define CLUTTER_SHADER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CLUTTER_TYPE_SHADER, ClutterShaderClass)) +#define CLUTTER_IS_SHADER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CLUTTER_TYPE_SHADER)) +#define CLUTTER_IS_SHADER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CLUTTER_TYPE_SHADER)) +#define CLUTTER_SHADER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CLUTTER_TYPE_SHADER, ClutterShaderClass)) + +/** + * CLUTTER_SHADER_ERROR: + * + * Error domain for #ClutterShader errors + * + * Since: 0.6 + * + * Deprecated: 1.8 + */ +#define CLUTTER_SHADER_ERROR (clutter_shader_error_quark ()) + +/** + * ClutterShaderError: + * @CLUTTER_SHADER_ERROR_NO_ASM: No ASM shaders support + * @CLUTTER_SHADER_ERROR_NO_GLSL: No GLSL shaders support + * @CLUTTER_SHADER_ERROR_COMPILE: Compilation error + * + * #ClutterShader error enumeration + * + * Since: 0.6 + * + * Deprecated: 1.8 + */ +typedef enum { + CLUTTER_SHADER_ERROR_NO_ASM, + CLUTTER_SHADER_ERROR_NO_GLSL, + CLUTTER_SHADER_ERROR_COMPILE +} ClutterShaderError; + +typedef struct _ClutterShaderPrivate ClutterShaderPrivate; +typedef struct _ClutterShaderClass ClutterShaderClass; + +/** + * ClutterShader: + * + * The #ClutterShader structure contains only private data + * and should be accessed using the provided API + * + * Since: 0.6 + * + * Deprecated: 1.8: Use #ClutterShaderEffect instead + */ +struct _ClutterShader +{ + /*< private >*/ + GObject parent; + ClutterShaderPrivate *priv; +}; + +/** + * ClutterShaderClass: + * + * The #ClutterShaderClass structure contains only private data + * + * Since: 0.6 + * + * Deprecated: 1.8: Use #ClutterShaderEffectClass instead + */ +struct _ClutterShaderClass +{ + /*< private >*/ + GObjectClass parent_class; +}; + +CLUTTER_DEPRECATED_IN_1_8 +GQuark clutter_shader_error_quark (void); + +CLUTTER_DEPRECATED_IN_1_8 +GType clutter_shader_get_type (void) G_GNUC_CONST; + +CLUTTER_DEPRECATED_IN_1_8_FOR(ClutterShaderEffect) +ClutterShader * clutter_shader_new (void); + +CLUTTER_DEPRECATED_IN_1_8_FOR(ClutterShaderEffect) +void clutter_shader_set_is_enabled (ClutterShader *shader, + gboolean enabled); +CLUTTER_DEPRECATED_IN_1_8_FOR(ClutterShaderEffect) +gboolean clutter_shader_get_is_enabled (ClutterShader *shader); + +CLUTTER_DEPRECATED_IN_1_8_FOR(ClutterShaderEffect) +gboolean clutter_shader_compile (ClutterShader *shader, + GError **error); +CLUTTER_DEPRECATED_IN_1_8_FOR(ClutterShaderEffect) +void clutter_shader_release (ClutterShader *shader); +CLUTTER_DEPRECATED_IN_1_8_FOR(ClutterShaderEffect) +gboolean clutter_shader_is_compiled (ClutterShader *shader); + +CLUTTER_DEPRECATED_IN_1_8_FOR(ClutterShaderEffect) +void clutter_shader_set_vertex_source (ClutterShader *shader, + const gchar *data, + gssize length); +CLUTTER_DEPRECATED_IN_1_8_FOR(ClutterShaderEffect) +void clutter_shader_set_fragment_source (ClutterShader *shader, + const gchar *data, + gssize length); +CLUTTER_DEPRECATED_IN_1_8_FOR(ClutterShaderEffect) +const gchar * clutter_shader_get_vertex_source (ClutterShader *shader); +CLUTTER_DEPRECATED_IN_1_8_FOR(ClutterShaderEffect) +const gchar * clutter_shader_get_fragment_source (ClutterShader *shader); + +CLUTTER_DEPRECATED_IN_1_8_FOR(ClutterShaderEffect) +void clutter_shader_set_uniform (ClutterShader *shader, + const gchar *name, + const GValue *value); + +CLUTTER_DEPRECATED_IN_1_8_FOR(ClutterShaderEffect) +CoglHandle clutter_shader_get_cogl_program (ClutterShader *shader); +CLUTTER_DEPRECATED_IN_1_8_FOR(ClutterShaderEffect) +CoglHandle clutter_shader_get_cogl_fragment_shader (ClutterShader *shader); +CLUTTER_DEPRECATED_IN_1_8_FOR(ClutterShaderEffect) +CoglHandle clutter_shader_get_cogl_vertex_shader (ClutterShader *shader); + +/* ClutterActor methods */ + +CLUTTER_DEPRECATED_IN_1_8_FOR(clutter_actor_add_effect) +gboolean clutter_actor_set_shader (ClutterActor *self, + ClutterShader *shader); + +CLUTTER_DEPRECATED_IN_1_8_FOR(clutter_actor_get_effect) +ClutterShader * clutter_actor_get_shader (ClutterActor *self); + +CLUTTER_DEPRECATED_IN_1_8_FOR(clutter_shader_effect_set_uniform_value) +void clutter_actor_set_shader_param (ClutterActor *self, + const gchar *param, + const GValue *value); + +CLUTTER_DEPRECATED_IN_1_8_FOR(clutter_shader_effect_set_uniform) +void clutter_actor_set_shader_param_int (ClutterActor *self, + const gchar *param, + gint value); + +CLUTTER_DEPRECATED_IN_1_8_FOR(clutter_shader_effect_set_uniform) +void clutter_actor_set_shader_param_float (ClutterActor *self, + const gchar *param, + gfloat value); + +G_END_DECLS + +#endif /* __CLUTTER_SHADER_H__ */ diff --git a/clutter/clutter/deprecated/clutter-stage-manager.h b/clutter/clutter/deprecated/clutter-stage-manager.h new file mode 100644 index 0000000..df19298 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-stage-manager.h @@ -0,0 +1,42 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2008 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: Emmanuele Bassi + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_STAGE_MANAGER_DEPRECATED_H__ +#define __CLUTTER_STAGE_MANAGER_DEPRECATED_H__ + +#include + +G_BEGIN_DECLS + +CLUTTER_DEPRECATED_IN_1_2 +void clutter_stage_manager_set_default_stage (ClutterStageManager *stage_manager, + ClutterStage *stage); + +G_END_DECLS + +#endif /*__CLUTTER_STAGE_MANAGER_DEPRECATED_H__ */ + diff --git a/clutter/clutter/deprecated/clutter-stage.h b/clutter/clutter/deprecated/clutter-stage.h new file mode 100644 index 0000000..1a0f288 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-stage.h @@ -0,0 +1,105 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2011 Intel Corp + * + * 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 . + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_STAGE_DEPRECATED_H__ +#define __CLUTTER_STAGE_DEPRECATED_H__ + +#include + +G_BEGIN_DECLS + +#ifndef CLUTTER_DISABLE_DEPRECATED + +/** + * CLUTTER_STAGE_WIDTH: + * + * Macro that evaluates to the width of the default stage + * + * Since: 0.2 + * + * Deprecated: 1.2: Use clutter_actor_get_width() instead + */ +#define CLUTTER_STAGE_WIDTH() (clutter_actor_get_width (clutter_stage_get_default ())) + +/** + * CLUTTER_STAGE_HEIGHT: + * + * Macro that evaluates to the height of the default stage + * + * Since: 0.2 + * + * Deprecated: 1.2: use clutter_actor_get_height() instead + */ +#define CLUTTER_STAGE_HEIGHT() (clutter_actor_get_height (clutter_stage_get_default ())) + +/* Commodity macro, for mallum only */ +#define clutter_stage_add(stage,actor) G_STMT_START { \ + if (CLUTTER_IS_STAGE ((stage)) && CLUTTER_IS_ACTOR ((actor))) \ + { \ + ClutterContainer *_container = (ClutterContainer *) (stage); \ + ClutterActor *_actor = (ClutterActor *) (actor); \ + clutter_container_add_actor (_container, _actor); \ + } } G_STMT_END + +#endif /* CLUTTER_DISABLE_DEPRECATED */ + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_stage_new) +ClutterActor * clutter_stage_get_default (void); + +CLUTTER_DEPRECATED_IN_1_10 +gboolean clutter_stage_is_default (ClutterStage *stage); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_queue_redraw) +void clutter_stage_queue_redraw (ClutterStage *stage); + +CLUTTER_DEPRECATED_IN_1_10 +void clutter_stage_set_use_fog (ClutterStage *stage, + gboolean fog); + +CLUTTER_DEPRECATED_IN_1_10 +gboolean clutter_stage_get_use_fog (ClutterStage *stage); + +CLUTTER_DEPRECATED_IN_1_10 +void clutter_stage_set_fog (ClutterStage *stage, + ClutterFog *fog); + +CLUTTER_DEPRECATED_IN_1_10 +void clutter_stage_get_fog (ClutterStage *stage, + ClutterFog *fog); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_set_background_color) +void clutter_stage_set_color (ClutterStage *stage, + const ClutterColor *color); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_actor_get_background_color) +void clutter_stage_get_color (ClutterStage *stage, + ClutterColor *color); + +CLUTTER_DEPRECATED_IN_MUTTER +void clutter_stage_ensure_current (ClutterStage *stage); + +G_END_DECLS + +#endif /* __CLUTTER_STAGE_DEPRECATED_H__ */ diff --git a/clutter/clutter/deprecated/clutter-state.c b/clutter/clutter/deprecated/clutter-state.c new file mode 100644 index 0000000..5a83a82 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-state.c @@ -0,0 +1,2310 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Øyvind KolÃ¥s + * + * 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 . + */ + +/** + * SECTION:clutter-state + * @short_description: State machine with animated transitions + * + * #ClutterState is an object controlling the tweening of properties on + * multiple actors between a set of named states. #ClutterStateKeys + * define how the properties are animated. If the source_state_name for a key + * is NULL it is used for transition to the target state unless a specific key + * exists for transitioning from the current state to the requested state. + * + * #ClutterState is available since Clutter 1.4. + * + * #ClutterState has been deprecated in Clutter 1.12. There is no direct + * replacement for this API, but it's highly suggested you use a combination + * of [implicit transitions][clutter-actor-animation] and explicit transitions + * using #ClutterTransition and its subclasses. + * + * ## Using ClutterState + * + * The following example defines a "base" and a "hover" state in a + * #ClutterState instance. + * + * |[ + * ClutterState *state = clutter_state_new (); + * ClutterColor color = { 0, }; + * + * // transition from any state to the "base" state + * clutter_color_from_string (&color, "rgb(255, 0, 0)"); + * clutter_state_set (state, NULL, "base", + * actor, "color", CLUTTER_LINEAR, &color, + * actor, "scale-x", CLUTTER_EASE_IN_BOUNCE, 1.0, + * actor, "scale-y", CLUTTER_EASE_IN_BOUNCE, 1.0, + * NULL); + * + * // transition from the "base" state to the "hover" state + * clutter_color_from_string (&color, "rgb(0, 0, 255)"); + * clutter_state_set (state, "base", "hover", + * actor, "color", CLUTTER_LINEAR, &color, + * actor, "scale-x", CLUTTER_EASE_OUT_BOUNCE, 1.7, + * actor, "scale-y", CLUTTER_EASE_OUT_BOUNCE, 1.7, + * NULL); + * + * // the default duration of any transition + * clutter_state_set_duration (state, NULL, NULL, 500); + * + * // set "base" as the initial state + * clutter_state_warp_to_state (state, "base"); + * ]| + * + * The actor then uses the #ClutterState to animate through the + * two states using callbacks for the #ClutterActor::enter-event and + * #ClutterActor::leave-event signals. + * + * |[ + * static gboolean + * on_enter (ClutterActor *actor, + * ClutterEvent *event, + * ClutterState *state) + * { + * clutter_state_set_state (state, "hover"); + * + * return CLUTTER_EVENT_STOP; + * } + * + * static gboolean + * on_leave (ClutterActor *actor, + * ClutterEvent *event, + * ClutterState *state) + * { + * clutter_state_set_state (state, "base"); + * + * return CLUTTER_EVENT_STOP; + * } + * + * ## ClutterState description for ClutterScript + * + * #ClutterState defines a custom `transitions` JSON object member which + * allows describing the states. + * + * The `transitions` property has the following syntax: + * + * |[ + * { + * "transitions" : [ + * { + * "source" : "source-state", + * "target" : "target-state", + * "duration" : milliseconds, + * "keys" : [ + * [ + * "object-id", + * "property-name", + * "easing-mode", + * "final-value", + * ], + * [ + * "object-id", + * "property-name", + * "easing-mode", + * "final-value", + * pre-delay, + * post-delay; + * ], + * ... + * ] + * }, + * { + * "source" : "source-state", + * "target" : "target-state", + * "duration" : milliseconds, + * "animator" : "animator-definition" + * }, + * ... + * ] + * } + * ]| + * + * Each element of the transitions array follows the same rules and order + * as clutter_state_set_key() function arguments. + * + * The source and target values control the source and target state of the + * transition. The key and animator properties are mutually exclusive. + * + * The pre-delay and post-delay values are optional. + * + * The example below is a translation into a #ClutterScript definition of + * the code in the #ClutterState example above. + * + * |[ + * { + * "id" : "button-state", + * "type" : "ClutterState", + * "duration" : 500, + * "transitions" : [ + * { + * "source" : "*", + * "target" : "base", + * "keys" : [ + * [ "button", "color", "linear", "rgb(255, 0, 0)" ], + * [ "button", "scale-x", "easeInBounce", 1.0 ], + * [ "button", "scale-y", "easeInBounce", 1.0 ] + * ] + * }, + * { + * "source" : "base", + * "target" : "hover", + * "keys" : [ + * [ "button", "color", "linear", "rgb(0, 0, 255)" ], + * [ "button", "scale-x", "easeOutBounce", 1.7 ], + * [ "button", "scale-y", "easeOutBounce", 1.7 ] + * ] + * } + * ] + * } + * ]| + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS + +#include "clutter-state.h" + +#include "clutter-alpha.h" +#include "clutter-animatable.h" +#include "clutter-animator.h" +#include "clutter-enum-types.h" +#include "clutter-interval.h" +#include "clutter-marshal.h" +#include "clutter-private.h" +#include "clutter-scriptable.h" +#include "clutter-script-private.h" + +typedef struct StateAnimator { + const gchar *source_state_name; /* interned string identifying entry */ + ClutterAnimator *animator; /* pointer to animator itself */ +} StateAnimator; + +typedef struct State +{ + const gchar *name; /* interned string for this state name */ + GHashTable *durations; /* durations for transitions from various state + names */ + GList *keys; /* list of all keys pertaining to transitions + from other states to this one */ + GArray *animators; /* list of animators for transitioning from + * specific source states */ + ClutterState *clutter_state; /* the ClutterState object this state belongs to + */ +} State; + +struct _ClutterStatePrivate +{ + GHashTable *states; /* contains state objects */ + guint duration; /* global fallback duration */ + ClutterTimeline *timeline; /* The timeline used for doing the + progress */ + ClutterTimeline *slave_timeline; /* a slave timeline used to compute + alphas */ + const gchar *source_state_name; /* current source state */ + State *source_state; /* current source_state */ + const gchar *target_state_name; /* current target state */ + State *target_state; /* target state name */ + ClutterAnimator *current_animator; /* !NULL if the current transition is + overriden by an animator */ +}; + +#define SLAVE_TIMELINE_LENGTH 10000 + +/* + * ClutterStateKey: + * + * An opaque data structure with accessor functions. + * + */ +typedef struct _ClutterStateKey +{ + GObject *object; /* an Gobject */ + const gchar *property_name;/* the name of a property */ + gulong mode; /* alpha to use */ + GValue value; /* target value */ + gdouble pre_delay; /* fraction of duration to delay before + starting */ + gdouble pre_pre_delay;/* fraction of duration to add to + pre_delay. This is used to set keys + during transitions. */ + gdouble post_delay; /* fraction of duration to be done in */ + + State *source_state; /* source state */ + State *target_state; /* target state */ + + ClutterAlpha *alpha; /* The alpha this key uses for interpolation */ + ClutterInterval *interval; /* The interval this key uses for + interpolation */ + + guint is_animatable : 1; + guint is_inert : 1; /* set if the key is being destroyed due to + weak reference */ + gint ref_count; /* reference count for boxed life time */ +} _ClutterStateKey; + +enum +{ + PROP_0, + PROP_DURATION, + PROP_STATE, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +enum +{ + COMPLETED, + LAST_SIGNAL +}; + +static void clutter_scriptable_iface_init (ClutterScriptableIface *iface); + +static guint state_signals[LAST_SIGNAL] = {0, }; + +G_DEFINE_TYPE_WITH_CODE (ClutterState, clutter_state, G_TYPE_OBJECT, + G_ADD_PRIVATE (ClutterState) + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_SCRIPTABLE, + clutter_scriptable_iface_init)) + +/** + * clutter_state_new: + * + * Creates a new #ClutterState + * + * Return value: the newly create #ClutterState instance + * + * Since: 1.4 + * Deprecated: 1.12: Use #ClutterKeyframeTransition and + * #ClutterTransitionGroup instead + */ +ClutterState * +clutter_state_new (void) +{ + return g_object_new (CLUTTER_TYPE_STATE, NULL); +} + +static gint +sort_props_func (gconstpointer a, + gconstpointer b) +{ + const ClutterStateKey *pa = a; + const ClutterStateKey *pb = b; + + if (pa->object == pb->object) + { + gint propnamediff = pa->property_name-pb->property_name; + if (propnamediff == 0) + return pb->source_state - pa->source_state; + + return propnamediff; + } + + return pa->object - pb->object; +} + +static State * clutter_state_fetch_state (ClutterState *state, + const gchar *state_name, + gboolean force_creation); +static void object_disappeared (gpointer data, + GObject *where_the_object_was); + +static ClutterStateKey * +clutter_state_key_new (State *state, + GObject *object, + const gchar *property_name, + GParamSpec *pspec, + guint mode) +{ + ClutterStatePrivate *priv = state->clutter_state->priv; + ClutterStateKey *state_key; + GValue value = G_VALUE_INIT; + + state_key = g_slice_new0 (ClutterStateKey); + + state_key->target_state = state; + state_key->object = object; + state_key->property_name = g_intern_string (property_name); + state_key->mode = mode; + state_key->is_animatable = CLUTTER_IS_ANIMATABLE (object); + + state_key->alpha = clutter_alpha_new (); + g_object_ref_sink (state_key->alpha); + clutter_alpha_set_mode (state_key->alpha, mode); + clutter_alpha_set_timeline (state_key->alpha, priv->slave_timeline); + + state_key->interval = + g_object_new (CLUTTER_TYPE_INTERVAL, + "value-type", G_PARAM_SPEC_VALUE_TYPE (pspec), + NULL); + g_object_ref_sink (state_key->interval); + + g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec)); + clutter_interval_set_initial_value (state_key->interval, &value); + clutter_interval_set_final_value (state_key->interval, &value); + g_value_unset (&value); + + g_object_weak_ref (object, object_disappeared, + state_key->target_state->clutter_state); + + return state_key; +} + +static void +clutter_state_key_free (gpointer clutter_state_key) +{ + ClutterStateKey *key = clutter_state_key; + + if (key == NULL) + return; + + key->ref_count -= 1; + + if (key->ref_count > 0) + return; + + if (!key->is_inert) + { + g_object_weak_unref (key->object, + object_disappeared, + key->target_state->clutter_state); + } + + g_value_unset (&key->value); + + g_object_unref (key->alpha); + g_object_unref (key->interval); + + g_slice_free (ClutterStateKey, key); +} + + +static inline void +clutter_state_remove_key_internal (ClutterState *this, + const gchar *source_state_name, + const gchar *target_state_name, + GObject *object, + const gchar *property_name, + gboolean is_inert) +{ + GList *s, *state_list; + State *source_state = NULL; + + source_state_name = g_intern_string (source_state_name); + target_state_name = g_intern_string (target_state_name); + property_name = g_intern_string (property_name); + + if (source_state_name) + source_state = clutter_state_fetch_state (this, source_state_name, FALSE); + +again_from_start: + + if (target_state_name != NULL) + state_list = g_list_append (NULL, (gpointer) target_state_name); + else + state_list = clutter_state_get_states (this); + + for (s = state_list; s != NULL; s = s->next) + { + State *target_state; + target_state = clutter_state_fetch_state (this, s->data, FALSE); + /* Go through each TargetState */ + if (target_state) + { + GList *k = target_state->keys; + + /* Note the safe while() loop, because we modify the list inline */ + while (k != NULL) + { + ClutterStateKey *key = k->data; + + k = k->next; + + /* Check if each key matches query */ + if ( (object == NULL || (object == key->object)) + && (source_state == NULL || (source_state == key->source_state)) + && (property_name == NULL || ((property_name == key->property_name)))) + { + /* Remove matching key */ + target_state->keys = g_list_remove (target_state->keys, key); + key->is_inert = is_inert; + clutter_state_key_free (key); + + /* no more keys with transitions to this target_state*/ + if (target_state->keys == NULL) + { + /* If this state is the current state, unset the state */ + if (target_state == this->priv->target_state) + clutter_state_set_state (this, NULL); + + /* remove any keys that exist that uses this state as a source */ + clutter_state_remove_key_internal (this, s->data, NULL, NULL, NULL, is_inert); + + g_hash_table_remove (this->priv->states, s->data); + goto again_from_start; /* we have just freed State *target_state, so + need to restart removal */ + } + } + } + } + } + + g_list_free (state_list); +} + +static void +object_disappeared (gpointer data, + GObject *where_the_object_was) +{ + clutter_state_remove_key_internal (data, NULL, NULL, + (gpointer) where_the_object_was, + NULL, + TRUE); +} + + +static void +state_free (gpointer data) +{ + State *state = data; + + for (; state->keys; + state->keys = g_list_remove (state->keys, state->keys->data)) + clutter_state_key_free (state->keys->data); + + g_array_free (state->animators, TRUE); + g_hash_table_destroy (state->durations); + g_free (state); +} + +static State * +state_new (ClutterState *clutter_state, + const gchar *name) +{ + State *state; + + state = g_new0 (State, 1); + state->clutter_state = clutter_state; + state->name = name; + state->animators = g_array_new (TRUE, TRUE, sizeof (StateAnimator)); + state->durations = g_hash_table_new (g_direct_hash, g_direct_equal); + + return state; +} + +static void +clutter_state_finalize (GObject *object) +{ + ClutterStatePrivate *priv = CLUTTER_STATE (object)->priv; + + g_hash_table_destroy (priv->states); + + g_object_unref (priv->timeline); + g_object_unref (priv->slave_timeline); + + G_OBJECT_CLASS (clutter_state_parent_class)->finalize (object); +} + +static void +clutter_state_completed (ClutterTimeline *timeline, + ClutterState *state) +{ + ClutterStatePrivate *priv = state->priv; + + if (priv->current_animator) + { + clutter_animator_set_timeline (priv->current_animator, NULL); + priv->current_animator = NULL; + } + + g_signal_emit (state, state_signals[COMPLETED], 0); +} + +static void +clutter_state_new_frame (ClutterTimeline *timeline, + gint msecs, + ClutterState *state) +{ + ClutterStatePrivate *priv = state->priv; + GList *k; + gdouble progress; + const gchar *curprop = NULL; + GObject *curobj = NULL; + gboolean found_specific = FALSE; + + if (priv->current_animator) + return; + + progress = clutter_timeline_get_progress (timeline); + + for (k = priv->target_state->keys; k; k = k->next) + { + ClutterStateKey *key = k->data; + gdouble sub_progress; + + if ((curprop && !(curprop == key->property_name)) || + key->object != curobj) + { + curprop = key->property_name; + curobj = key->object; + found_specific = FALSE; + } + + if (!found_specific) + { + if (key->source_state != NULL && + key->source_state->name != NULL && + priv->source_state_name != NULL && + g_str_equal (priv->source_state_name, key->source_state->name)) + { + found_specific = TRUE; + } + + if (found_specific || key->source_state == NULL) + { + gdouble pre_delay = key->pre_delay + key->pre_pre_delay; + + sub_progress = (progress - pre_delay) + / (1.0 - (pre_delay + key->post_delay)); + + if (sub_progress >= 0.0) + { + if (sub_progress >= 1.0) + sub_progress = 1.0; + + clutter_timeline_advance (priv->slave_timeline, + sub_progress * SLAVE_TIMELINE_LENGTH); + sub_progress = clutter_alpha_get_alpha (key->alpha); + + if (key->is_animatable) + { + ClutterAnimatable *animatable; + GValue value = G_VALUE_INIT; + gboolean res; + + animatable = CLUTTER_ANIMATABLE (key->object); + + g_value_init (&value, clutter_state_key_get_property_type (key)); + + res = + clutter_animatable_interpolate_value (animatable, + key->property_name, + key->interval, + sub_progress, + &value); + + if (res) + clutter_animatable_set_final_state (animatable, + key->property_name, + &value); + + g_value_unset (&value); + } + else + { + const GValue *value; + + value = clutter_interval_compute (key->interval, sub_progress); + if (value != NULL) + g_object_set_property (key->object, key->property_name, value); + } + } + + /* XXX: should the target value of the default destination be + * used even when found a specific source_state key? + */ + } + } + } +} + + +static ClutterTimeline * +clutter_state_change (ClutterState *state, + const gchar *target_state_name, + gboolean animate) +{ + ClutterStatePrivate *priv; + ClutterAnimator *animator; + State *new_state; + guint duration; + GList *k; + + g_return_val_if_fail (CLUTTER_IS_STATE (state), NULL); + + priv = state->priv; + + /* If we've been asked to change state to NULL, reset the + * ClutterState to its initial state, but leave the keys + * alone. + */ + if (!target_state_name) + { + if (!priv->target_state) + return NULL; + + priv->source_state_name = priv->target_state_name = NULL; + priv->source_state = priv->target_state = NULL; + + clutter_timeline_stop (priv->timeline); + clutter_timeline_rewind (priv->timeline); + + if (priv->current_animator) + { + clutter_animator_set_timeline (priv->current_animator, NULL); + priv->current_animator = NULL; + } + + return NULL; + } + + target_state_name = g_intern_string (target_state_name); + + if (target_state_name == priv->target_state_name) + { + /* Avoid transitioning if the desired state is already current, + * unless we're warping to it and the state transition is in + * progress (in that case, immediately warp to the state). + */ + if (!clutter_timeline_is_playing (priv->timeline) || animate) + return priv->timeline; + } + + if (priv->current_animator != NULL) + { + clutter_animator_set_timeline (priv->current_animator, NULL); + priv->current_animator = NULL; + } + + priv->source_state_name = priv->target_state_name; + priv->target_state_name = target_state_name; + + g_object_notify_by_pspec (G_OBJECT (state), obj_props[PROP_STATE]); + + duration = clutter_state_get_duration (state, + priv->source_state_name, + priv->target_state_name); + clutter_timeline_set_duration (priv->timeline, duration); + + new_state = clutter_state_fetch_state (state, target_state_name, FALSE); + if (new_state == NULL) + { + g_warning ("State '%s' not found", target_state_name); + + return NULL; + } + + animator = clutter_state_get_animator (state, + priv->source_state_name, + priv->target_state_name); + priv->target_state = new_state; + + if (animator == NULL && new_state->keys == NULL) + animator = clutter_state_get_animator (state, NULL, + priv->target_state_name); + + if (animator != NULL) + { + /* we've got an animator overriding the tweened animation */ + priv->current_animator = animator; + clutter_animator_set_timeline (animator, priv->timeline); + } + else + { + for (k = new_state->keys; k != NULL; k = k->next) + { + ClutterStateKey *key = k->data; + GValue initial = G_VALUE_INIT; + + /* Reset the pre-pre-delay - this is only used for setting keys + * during transitions. + */ + key->pre_pre_delay = 0; + + g_value_init (&initial, clutter_interval_get_value_type (key->interval)); + + if (key->is_animatable) + { + ClutterAnimatable *animatable; + + animatable = CLUTTER_ANIMATABLE (key->object); + clutter_animatable_get_initial_state (animatable, + key->property_name, + &initial); + } + else + g_object_get_property (key->object, key->property_name, &initial); + + if (clutter_alpha_get_mode (key->alpha) != key->mode) + clutter_alpha_set_mode (key->alpha, key->mode); + + clutter_interval_set_initial_value (key->interval, &initial); + clutter_interval_set_final_value (key->interval, &key->value); + + g_value_unset (&initial); + } + } + + if (!animate) + { + clutter_timeline_stop (priv->timeline); + clutter_timeline_advance (priv->timeline, duration); + + /* emit signals, to change properties, and indicate that the + * state change is complete */ + g_signal_emit_by_name (priv->timeline, "new-frame", + GINT_TO_POINTER (duration), + NULL); + g_signal_emit_by_name (priv->timeline, "completed", NULL); + } + else + { + clutter_timeline_stop (priv->timeline); + clutter_timeline_rewind (priv->timeline); + clutter_timeline_start (priv->timeline); + } + + return priv->timeline; +} + +/** + * clutter_state_set_state: + * @state: a #ClutterState + * @target_state_name: the state to transition to + * + * Change the current state of #ClutterState to @target_state_name. + * + * The state will animate during its transition, see + * #clutter_state_warp_to_state for animation-free state switching. + * + * Setting a %NULL state will stop the current animation and unset + * the current state, but keys will be left intact. + * + * Return value: (transfer none): the #ClutterTimeline that drives the + * state transition. The returned timeline is owned by the #ClutterState + * and it should not be unreferenced + * + * Since: 1.4 + * Deprecated: 1.12: Use #ClutterKeyframeTransition and + * #ClutterTransitionGroup instead + */ +ClutterTimeline * +clutter_state_set_state (ClutterState *state, + const gchar *target_state_name) +{ + return clutter_state_change (state, target_state_name, TRUE); +} + +/** + * clutter_state_warp_to_state: + * @state: a #ClutterState + * @target_state_name: the state to transition to + * + * Change to the specified target state immediately with no animation. + * + * See clutter_state_set_state(). + * + * Return value: (transfer none): the #ClutterTimeline that drives the + * state transition. The returned timeline is owned by the #ClutterState + * and it should not be unreferenced + * + * Since: 1.4 + * Deprecated: 1.12: Use #ClutterKeyframeTransition and + * #ClutterTransitionGroup instead + */ +ClutterTimeline * +clutter_state_warp_to_state (ClutterState *state, + const gchar *target_state_name) +{ + return clutter_state_change (state, target_state_name, FALSE); +} + +static GParamSpec * +get_property_from_object (GObject *gobject, + const gchar *property_name) +{ + GParamSpec *pspec; + + if (CLUTTER_IS_ANIMATABLE (gobject)) + { + ClutterAnimatable *animatable = CLUTTER_ANIMATABLE (gobject); + + pspec = clutter_animatable_find_property (animatable, property_name); + } + else + { + GObjectClass *klass = G_OBJECT_GET_CLASS (gobject); + + pspec = g_object_class_find_property (klass, property_name); + } + + if (pspec == NULL) + { + g_warning ("Cannot bind property '%s': objects of type '%s' " + "do not have this property", + property_name, + G_OBJECT_TYPE_NAME (gobject)); + return NULL; + } + + if (!(pspec->flags & G_PARAM_WRITABLE)) + { + g_warning ("Cannot bind property '%s' of object of type '%s': " + "the property is not writable", + property_name, + G_OBJECT_TYPE_NAME (gobject)); + return NULL; + } + + if (!(pspec->flags & G_PARAM_READABLE)) + { + g_warning ("Cannot bind property '%s' of object of type '%s': " + "the property is not readable", + property_name, + G_OBJECT_TYPE_NAME (gobject)); + return NULL; + } + + if (pspec->flags & G_PARAM_CONSTRUCT_ONLY) + { + g_warning ("Cannot bind property '%s' of object of type '%s': " + "the property is set as constructor-only", + property_name, + G_OBJECT_TYPE_NAME (gobject)); + return NULL; + } + + return pspec; +} + +/** + * clutter_state_set: + * @state: a #ClutterState instance. + * @source_state_name: (allow-none): the name of the source state keys are being added for + * @target_state_name: the name of the target state keys are being added for + * @first_object: a #GObject + * @first_property_name: a property of @first_object to specify a key for + * @first_mode: the id of the alpha function to use + * @...: the value @first_property_name should have in @target_state_name, + * followed by object, property name, mode, value tuples, terminated + * by %NULL + * + * Adds multiple keys to a named state of a #ClutterState instance, specifying + * the easing mode and value a given property of an object should have at a + * given progress of the animation. + * + * The mode specified is the easing mode used when going to from the previous + * key to the specified key. + * + * For instance, the code below: + * + * |[ + * clutter_state_set (state, NULL, "hover", + * button, "opacity", CLUTTER_LINEAR, 255, + * button, "scale-x", CLUTTER_EASE_OUT_CUBIC, 1.2, + * button, "scale-y", CLUTTER_EASE_OUT_CUBIC, 1.2, + * NULL); + * ]| + * + * will create a transition from any state (a @source_state_name or NULL is + * treated as a wildcard) and a state named "hover"; the + * button object will have the #ClutterActor:opacity + * property animated to a value of 255 using %CLUTTER_LINEAR as the animation + * mode, and the #ClutterActor:scale-x and #ClutterActor:scale-y properties + * animated to a value of 1.2 using %CLUTTER_EASE_OUT_CUBIC as the animation + * mode. To change the state (and start the transition) you can use the + * clutter_state_set_state() function: + * + * |[ + * clutter_state_set_state (state, "hover"); + * ]| + * + * If a given object, state_name, property tuple already exist in the + * #ClutterState instance, then the mode and value will be replaced with + * the new specified values. + * + * If a property name is prefixed with "delayed::" two additional + * arguments per key are expected: a value relative to the full state time + * to pause before transitioning and a similar value to pause after + * transitioning, e.g.: + * + * |[ + * clutter_state_set (state, "hover", "toggled", + * button, "delayed::scale-x", CLUTTER_LINEAR, 1.0, 0.2, 0.2, + * button, "delayed::scale-y", CLUTTER_LINEAR, 1.0, 0.2, 0.2, + * NULL); + * ]| + * + * will pause for 20% of the duration of the transition before animating, + * and 20% of the duration after animating. + * + * Since: 1.4 + * Deprecated: 1.12: Use #ClutterKeyframeTransition and + * #ClutterTransitionGroup instead + */ +void +clutter_state_set (ClutterState *state, + const gchar *source_state_name, + const gchar *target_state_name, + gpointer first_object, + const gchar *first_property_name, + gulong first_mode, + ...) +{ + gpointer object; + const gchar *property_name; + gulong mode; + va_list args; + + g_return_if_fail (CLUTTER_IS_STATE (state)); + + object = first_object; + + property_name = first_property_name; + mode = first_mode; + + g_return_if_fail (G_IS_OBJECT (first_object)); + g_return_if_fail (first_property_name); + + va_start (args, first_mode); + + while (object != NULL) + { + GParamSpec *pspec; + GValue value = G_VALUE_INIT; + gchar *error = NULL; + gboolean is_delayed = FALSE; + + if (g_str_has_prefix (property_name, "delayed::")) + { + property_name = strstr (property_name, "::") + 2; + is_delayed = TRUE; + } + + pspec = get_property_from_object (object, property_name); + if (pspec == NULL) + break; + + G_VALUE_COLLECT_INIT (&value, G_PARAM_SPEC_VALUE_TYPE (pspec), + args, 0, + &error); + + if (error != NULL) + { + g_warning ("%s: %s", G_STRLOC, error); + g_free (error); + break; + } + + if (is_delayed) + { + gdouble pre_delay = va_arg (args, gdouble); + gdouble post_delay = va_arg (args, gdouble); + + clutter_state_set_key (state, + source_state_name, + target_state_name, + object, + property_name, + mode, + &value, + pre_delay, + post_delay); + } + else + { + clutter_state_set_key (state, + source_state_name, + target_state_name, + object, + property_name, + mode, + &value, + 0.0, + 0.0); + } + + g_value_unset (&value); + + object = va_arg (args, gpointer); + if (object != NULL) + { + property_name = va_arg (args, gchar*); + mode = va_arg (args, gulong); + } + } + + va_end (args); +} + +static void +clutter_state_set_key_internal (ClutterState *state, + ClutterStateKey *key) +{ + ClutterStatePrivate *priv = state->priv; + State *target_state = key->target_state; + GList *old_item = NULL; + + if ((old_item = g_list_find_custom (target_state->keys, + key, + sort_props_func))) + { + ClutterStateKey *old_key = old_item->data; + + target_state->keys = g_list_remove (target_state->keys, old_key); + clutter_state_key_free (old_key); + } + + target_state->keys = g_list_insert_sorted (target_state->keys, + key, + sort_props_func); + + /* If the current target state is modified, we have some work to do. + * + * If the animation is running, we add a key to the current animation + * with a delay of the current duration so that the new animation will + * animate into place. + * + * If the animation isn't running, but the state is set, we immediately + * warp to that state. + */ + if (key->target_state == priv->target_state) + { + if (!clutter_timeline_is_playing (priv->timeline)) + { + /* We can warp to the state by setting a NULL state, then setting + * the target state again. + */ + clutter_state_change (state, NULL, FALSE); + clutter_state_change (state, target_state->name, FALSE); + } + else + { + /* Set the ClutterInterval associated with the state */ + GValue initial = G_VALUE_INIT; + gdouble progress = clutter_timeline_get_progress (priv->timeline); + + g_value_init (&initial, + clutter_interval_get_value_type (key->interval)); + + if (key->is_animatable) + { + ClutterAnimatable *animatable; + + animatable = CLUTTER_ANIMATABLE (key->object); + clutter_animatable_get_initial_state (animatable, + key->property_name, + &initial); + } + else + g_object_get_property (key->object, key->property_name, &initial); + + if (clutter_alpha_get_mode (key->alpha) != key->mode) + clutter_alpha_set_mode (key->alpha, key->mode); + + clutter_interval_set_initial_value (key->interval, &initial); + clutter_interval_set_final_value (key->interval, &key->value); + + g_value_unset (&initial); + + /* Set the delay as if the interval had just begun */ + if (progress > key->pre_delay) + key->pre_pre_delay = MIN (progress - key->pre_delay, + 1.0 - key->post_delay); + } + } +} + +/* + * clutter_state_fetch_state: + * @state: a #ClutterState + * @state_name: the name of the state to be retrieved + * @create: %TRUE if the state should be instantiated if not found + * + * Retrieves the #State structure for @state_name inside the given + * #ClutterState instance + * + * If @state_name is %NULL and @create is %TRUE then NULL will + * be returned. + * + * Return value: a #State structure for the given name, or %NULL + */ +static State * +clutter_state_fetch_state (ClutterState *state, + const gchar *state_name, + gboolean create) +{ + ClutterStatePrivate *priv = state->priv; + State *retval; + + if (state_name == NULL) + { + return NULL; + } + else + state_name = g_intern_string (state_name); + + retval = g_hash_table_lookup (priv->states, state_name); + if (retval == NULL && create) + { + retval = state_new (state, state_name); + g_hash_table_insert (priv->states, (gpointer) state_name, retval); + } + + return retval; +} + +/** + * clutter_state_set_key: + * @state: a #ClutterState instance. + * @source_state_name: (allow-none): the source transition to specify + * transition for, or %NULL to specify the default fallback when a + * more specific source state doesn't exist. + * @target_state_name: the name of the transition to set a key value for. + * @object: the #GObject to set a key for + * @property_name: the property to set a key for + * @mode: the id of the alpha function to use + * @value: the value for property_name of object in state_name + * @pre_delay: relative time of the transition to be idle in the beginning + * of the transition + * @post_delay: relative time of the transition to be idle in the end of + * the transition + * + * Sets one specific end key for a state name, @object, @property_name + * combination. + * + * Return value: (transfer none): the #ClutterState instance, allowing + * chaining of multiple calls + * + * Since: 1.4 + * Deprecated: 1.12: Use #ClutterKeyframeTransition and + * #ClutterTransitionGroup instead + */ +ClutterState * +clutter_state_set_key (ClutterState *state, + const gchar *source_state_name, + const gchar *target_state_name, + GObject *object, + const gchar *property_name, + guint mode, + const GValue *value, + gdouble pre_delay, + gdouble post_delay) +{ + GParamSpec *pspec; + ClutterStateKey *state_key; + State *source_state = NULL; + State *target_state; + + g_return_val_if_fail (CLUTTER_IS_STATE (state), NULL); + g_return_val_if_fail (G_IS_OBJECT (object), NULL); + g_return_val_if_fail (property_name, NULL); + g_return_val_if_fail (value, NULL); + + pspec = get_property_from_object (object, property_name); + if (pspec == NULL) + return state; + + source_state = clutter_state_fetch_state (state, source_state_name, TRUE); + target_state = clutter_state_fetch_state (state, target_state_name, TRUE); + + property_name = g_intern_string (property_name); + state_key = clutter_state_key_new (target_state, + object, property_name, pspec, + mode); + + state_key->source_state = source_state; + state_key->pre_delay = pre_delay; + state_key->post_delay = post_delay; + + g_value_init (&state_key->value, G_VALUE_TYPE (value)); + g_value_copy (value, &state_key->value); + + clutter_state_set_key_internal (state, state_key); + + return state; +} + +/** + * clutter_state_get_states: + * @state: a #ClutterState instance. + * + * Gets a list of all the state names managed by this #ClutterState. + * + * Return value: (transfer container) (element-type utf8): a newly allocated + * #GList of state names. The contents of the returned #GList are owned + * by the #ClutterState and should not be modified or freed. Use + * g_list_free() to free the resources allocated by the returned list when + * done using it + * + * Since: 1.4 + * Deprecated: 1.12: Use #ClutterKeyframeTransition and + * #ClutterTransitionGroup instead + */ +GList * +clutter_state_get_states (ClutterState *state) +{ + g_return_val_if_fail (CLUTTER_IS_STATE (state), NULL); + return g_hash_table_get_keys (state->priv->states); +} + +/** + * clutter_state_get_keys: + * @state: a #ClutterState instance. + * @source_state_name: (allow-none): the source transition name to query, + * or %NULL for all source states + * @target_state_name: (allow-none): the target transition name to query, + * or %NULL for all target states + * @object: (allow-none): the specific object instance to list keys for, + * or %NULL for all managed objects + * @property_name: (allow-none): the property name to search for, or %NULL + * for all properties. + * + * Returns a list of pointers to opaque structures with accessor functions + * that describe the keys added to an animator. + * + * Return value: (transfer container) (element-type Clutter.StateKey): a + * newly allocated #GList of #ClutterStateKeys. The contents of + * the returned list are owned by the #ClutterState and should not be + * modified or freed. Use g_list_free() to free the resources allocated + * by the returned list when done using it + * + * Since: 1.4 + * Deprecated: 1.12: Use #ClutterKeyframeTransition and + * #ClutterTransitionGroup instead + */ +GList * +clutter_state_get_keys (ClutterState *state, + const gchar *source_state_name, + const gchar *target_state_name, + GObject *object, + const gchar *property_name) +{ + GList *s, *state_list; + GList *targets = NULL; + State *source_state = NULL; + + g_return_val_if_fail (CLUTTER_IS_STATE (state), NULL); + + source_state_name = g_intern_string (source_state_name); + target_state_name = g_intern_string (target_state_name); + property_name = g_intern_string (property_name); + + if (target_state_name != NULL) + state_list = g_list_append (NULL, (gpointer) target_state_name); + else + state_list = clutter_state_get_states (state); + + if (source_state_name) + source_state = clutter_state_fetch_state (state, source_state_name, FALSE); + + for (s = state_list; s != NULL; s = s->next) + { + State *target_state; + + target_state = clutter_state_fetch_state (state, s->data, FALSE); + if (target_state != NULL) + { + GList *k; + + for (k = target_state->keys; k; k = k->next) + { + ClutterStateKey *key = k->data; + + if ((object == NULL || (object == key->object)) && + (source_state_name == NULL || + source_state == key->source_state) && + (property_name == NULL || + (property_name == key->property_name))) + { + targets = g_list_prepend (targets, key); + } + } + } + } + + g_list_free (state_list); + + return g_list_reverse (targets); +} + + +/** + * clutter_state_remove_key: + * @state: a #ClutterState instance. + * @source_state_name: (allow-none): the source state name to query, + * or %NULL for all source states + * @target_state_name: (allow-none): the target state name to query, + * or %NULL for all target states + * @object: (allow-none): the specific object instance to list keys for, + * or %NULL for all managed objects + * @property_name: (allow-none): the property name to search for, + * or %NULL for all properties. + * + * Removes all keys matching the search criteria passed in arguments. + * + * Since: 1.4 + * Deprecated: 1.12: Use #ClutterKeyframeTransition and + * #ClutterTransitionGroup instead + */ +void +clutter_state_remove_key (ClutterState *state, + const gchar *source_state_name, + const gchar *target_state_name, + GObject *object, + const gchar *property_name) +{ + g_return_if_fail (CLUTTER_IS_STATE (state)); + + clutter_state_remove_key_internal (state, + source_state_name, target_state_name, + object, property_name, + FALSE); +} + +/** + * clutter_state_get_timeline: + * @state: a #ClutterState + * + * Gets the timeline driving the #ClutterState + * + * Return value: (transfer none): the #ClutterTimeline that drives + * the state change animations. The returned timeline is owned + * by the #ClutterState and it should not be unreferenced directly + * + * Since: 1.4 + * Deprecated: 1.12: Use #ClutterKeyframeTransition and + * #ClutterTransitionGroup instead + */ +ClutterTimeline * +clutter_state_get_timeline (ClutterState *state) +{ + g_return_val_if_fail (CLUTTER_IS_STATE (state), NULL); + + return state->priv->timeline; +} + + +static void +clutter_state_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterState *state = CLUTTER_STATE (object); + + switch (prop_id) + { + case PROP_STATE: + clutter_state_set_state (state, g_value_get_string (value)); + break; + case PROP_DURATION: + state->priv->duration = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +clutter_state_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterState *state = CLUTTER_STATE (object); + switch (prop_id) + { + case PROP_STATE: + g_value_set_string (value, + clutter_state_get_state (state)); + break; + case PROP_DURATION: + g_value_set_uint (value, state->priv->duration); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +clutter_state_class_init (ClutterStateClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GParamSpec *pspec; + + gobject_class->finalize = clutter_state_finalize; + gobject_class->set_property = clutter_state_set_property; + gobject_class->get_property = clutter_state_get_property; + + /** + * ClutterState::completed: + * @state: the #ClutterState that emitted the signal + * + * The ::completed signal is emitted when a #ClutterState reaches + * the target state specified by clutter_state_set_state() or + * clutter_state_warp_to_state(). + * + * Since: 1.4 + * Deprecated: 1.12: Use #ClutterKeyframeTransition and + * #ClutterTransitionGroup instead + */ + state_signals[COMPLETED] = + g_signal_new (I_("completed"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterStateClass, completed), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * ClutterState:state: + * + * The currently set target state, setting it causes the + * state machine to transition to the new state, use + * clutter_state_warp_to_state() to change state without + * a transition. + * + * Since: 1.4 + * Deprecated: 1.12: Use #ClutterKeyframeTransition and + * #ClutterTransitionGroup instead + */ + pspec = g_param_spec_string ("state", + P_("State"), + P_("Currently set state, (transition to this state might not be complete)"), + NULL, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_STATE] = pspec; + g_object_class_install_property (gobject_class, PROP_STATE, pspec); + + /** + * ClutterState:duration: + * + * Default duration used if an duration has not been specified for a specific + * source/target state pair. The values is in milliseconds. + * + * Since: 1.4 + * Deprecated: 1.12: Use #ClutterKeyframeTransition and + * #ClutterTransitionGroup instead + */ + pspec = g_param_spec_uint ("duration", + P_("Duration"), + P_("Default transition duration"), + 0, 86400000, 1000, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_DURATION] = pspec; + g_object_class_install_property (gobject_class, PROP_DURATION, pspec); +} + +static void +clutter_state_init (ClutterState *self) +{ + ClutterStatePrivate *priv; + + priv = self->priv = clutter_state_get_instance_private (self); + + priv->states = g_hash_table_new_full (g_direct_hash, g_direct_equal, + NULL, + state_free); + + self->priv->source_state_name = NULL; + self->priv->target_state_name = NULL; + + self->priv->duration = 1000; + + priv->timeline = clutter_timeline_new (1000); + g_signal_connect (priv->timeline, "new-frame", + G_CALLBACK (clutter_state_new_frame), + self); + g_signal_connect (priv->timeline, "completed", + G_CALLBACK (clutter_state_completed), + self); + + priv->slave_timeline = clutter_timeline_new (SLAVE_TIMELINE_LENGTH); +} + + +/** + * clutter_state_get_animator: + * @state: a #ClutterState instance. + * @source_state_name: the name of a source state + * @target_state_name: the name of a target state + * + * Retrieves the #ClutterAnimator that is being used for transitioning + * between the two states, if any has been set + * + * Return value: (transfer none): a #ClutterAnimator instance, or %NULL + * + * Since: 1.4 + * Deprecated: 1.12: Use #ClutterKeyframeTransition and + * #ClutterTransitionGroup instead + */ +ClutterAnimator * +clutter_state_get_animator (ClutterState *state, + const gchar *source_state_name, + const gchar *target_state_name) +{ + State *target_state; + guint i; + + g_return_val_if_fail (CLUTTER_IS_STATE (state), NULL); + + source_state_name = g_intern_string (source_state_name); + if (source_state_name == g_intern_static_string ("")) + source_state_name = NULL; + + target_state_name = g_intern_string (target_state_name); + + target_state = clutter_state_fetch_state (state, target_state_name, FALSE); + if (target_state == NULL) + return NULL; + + for (i = 0; i < target_state->animators->len; i++) + { + const StateAnimator *animator; + + animator = &g_array_index (target_state->animators, StateAnimator, i); + if (animator->source_state_name == source_state_name) + return animator->animator; + } + + return NULL; +} + +/** + * clutter_state_set_animator: + * @state: a #ClutterState instance. + * @source_state_name: the name of a source state + * @target_state_name: the name of a target state + * @animator: (allow-none): a #ClutterAnimator instance, or %NULL to + * unset an existing #ClutterAnimator + * + * Specifies a #ClutterAnimator to be used when transitioning between + * the two named states. + * + * The @animator allows specifying a transition between the state that is + * more elaborate than the basic transitions allowed by the tweening of + * properties defined in the #ClutterState keys. + * + * If @animator is %NULL it will unset an existing animator. + * + * #ClutterState will take a reference on the passed @animator, if any + * + * Since: 1.4 + * Deprecated: 1.12: Use #ClutterKeyframeTransition and + * #ClutterTransitionGroup instead + */ +void +clutter_state_set_animator (ClutterState *state, + const gchar *source_state_name, + const gchar *target_state_name, + ClutterAnimator *animator) +{ + State *target_state; + guint i; + + g_return_if_fail (CLUTTER_IS_STATE (state)); + + source_state_name = g_intern_string (source_state_name); + target_state_name = g_intern_string (target_state_name); + + target_state = clutter_state_fetch_state (state, target_state_name, TRUE); + if (target_state == NULL) + return; + + for (i = 0; target_state->animators->len; i++) + { + StateAnimator *a; + + a = &g_array_index (target_state->animators, StateAnimator, i); + if (a->source_state_name == source_state_name) + { + g_object_unref (a->animator); + + if (animator != NULL) + a->animator = g_object_ref (animator); + else + { + /* remove the matched animator if passed NULL */ + g_array_remove_index (target_state->animators, i); + } + + return; + } + } + + if (animator != NULL) + { + StateAnimator state_animator = { + source_state_name, + g_object_ref (animator) + }; + + g_array_append_val (target_state->animators, state_animator); + } +} + +static gpointer +clutter_state_key_copy (gpointer boxed) +{ + if (boxed != NULL) + { + ClutterStateKey *key = boxed; + + key->ref_count += 1; + } + + return boxed; +} + +G_DEFINE_BOXED_TYPE (ClutterStateKey, clutter_state_key, + clutter_state_key_copy, + clutter_state_key_free); + +/** + * clutter_state_key_get_pre_delay: + * @state_key: a #ClutterStateKey + * + * Retrieves the pause before transitioning starts as a fraction of + * the total transition time. + * + * Return value: the pre delay used before starting the transition. + * + * Since: 1.4 + * Deprecated: 1.12: Use #ClutterKeyframeTransition and + * #ClutterTransitionGroup instead + */ +gdouble +clutter_state_key_get_pre_delay (const ClutterStateKey *state_key) +{ + g_return_val_if_fail (state_key != NULL, 0.0); + + return state_key->pre_delay; +} + +/** + * clutter_state_key_get_post_delay: + * @state_key: a #ClutterStateKey + * + * Retrieves the duration of the pause after transitioning is complete + * as a fraction of the total transition time. + * + * Return value: the post delay, used after doing the transition. + * + * Since: 1.4 + * Deprecated: 1.12: Use #ClutterKeyframeTransition and + * #ClutterTransitionGroup instead + */ +gdouble +clutter_state_key_get_post_delay (const ClutterStateKey *state_key) +{ + g_return_val_if_fail (state_key != NULL, 0.0); + + return state_key->post_delay; +} + +/** + * clutter_state_key_get_mode: + * @state_key: a #ClutterStateKey + * + * Retrieves the easing mode used for @state_key. + * + * Return value: the mode of a #ClutterStateKey + * + * Since: 1.4 + * Deprecated: 1.12: Use #ClutterKeyframeTransition and + * #ClutterTransitionGroup instead + */ +gulong +clutter_state_key_get_mode (const ClutterStateKey *state_key) +{ + g_return_val_if_fail (state_key != NULL, 0); + + return state_key->mode; +} + +/** + * clutter_state_key_get_value: + * @state_key: a #ClutterStateKey + * @value: a #GValue initialized with the correct type for the @state_key + * + * Retrieves a copy of the value for a #ClutterStateKey. + * + * The #GValue needs to be already initialized for the value type + * of the property or to a type that allow transformation from the value + * type of the key. + * + * Use g_value_unset() when done. + * + * Return value: %TRUE if the value was successfully retrieved, + * and %FALSE otherwise + * + * Since: 1.4 + * Deprecated: 1.12: Use #ClutterKeyframeTransition and + * #ClutterTransitionGroup instead + */ +gboolean +clutter_state_key_get_value (const ClutterStateKey *state_key, + GValue *value) +{ + g_return_val_if_fail (state_key != NULL, FALSE); + g_return_val_if_fail (value != NULL, FALSE); + g_return_val_if_fail (G_VALUE_TYPE (value) != G_TYPE_INVALID, FALSE); + + if (!g_type_is_a (G_VALUE_TYPE (&state_key->value), G_VALUE_TYPE (value))) + { + if (g_value_type_compatible (G_VALUE_TYPE (&state_key->value), + G_VALUE_TYPE (value))) + { + g_value_copy (&state_key->value, value); + return TRUE; + } + + if (g_value_type_transformable (G_VALUE_TYPE (&state_key->value), + G_VALUE_TYPE (value))) + { + if (g_value_transform (&state_key->value, value)) + return TRUE; + } + + g_warning ("%s: Unable to convert from %s to %s for the " + "property '%s' of object %s in the state key", + G_STRLOC, + g_type_name (G_VALUE_TYPE (&state_key->value)), + g_type_name (G_VALUE_TYPE (value)), + state_key->property_name, + G_OBJECT_TYPE_NAME (state_key->object)); + + return FALSE; + } + else + g_value_copy (&state_key->value, value); + + return TRUE; +} + +/** + * clutter_state_key_get_object: + * @state_key: a #ClutterStateKey + * + * Retrieves the object instance this #ClutterStateKey applies to. + * + * Return value: (transfer none): the object this state key applies to. + * + * Since: 1.4 + * Deprecated: 1.12: Use #ClutterKeyframeTransition and + * #ClutterTransitionGroup instead + */ +GObject * +clutter_state_key_get_object (const ClutterStateKey *state_key) +{ + g_return_val_if_fail (state_key, NULL); + + return state_key->object; +} + +/** + * clutter_state_key_get_property_name: + * @state_key: a #ClutterStateKey + * + * Retrieves the name of the property this #ClutterStateKey applies to + * + * Return value: the name of the property. The returned string is owned + * by the #ClutterStateKey and should never be modified or freed + * + * Since: 1.4 + * Deprecated: 1.12: Use #ClutterKeyframeTransition and + * #ClutterTransitionGroup instead + */ +const gchar * +clutter_state_key_get_property_name (const ClutterStateKey *state_key) +{ + g_return_val_if_fail (state_key, NULL); + + return state_key->property_name; +} + +/** + * clutter_state_key_get_source_state_name: + * @state_key: a #ClutterStateKey + * + * Retrieves the name of the source state of the @state_key + * + * Return value: the name of the source state for this key, or %NULL + * if this is the generic state key for the given property when + * transitioning to the target state. The returned string is owned + * by the #ClutterStateKey and should never be modified or freed + * + * Since: 1.4 + * Deprecated: 1.12: Use #ClutterKeyframeTransition and + * #ClutterTransitionGroup instead + */ +const gchar * +clutter_state_key_get_source_state_name (const ClutterStateKey *state_key) +{ + g_return_val_if_fail (state_key, NULL); + + if (state_key->source_state != NULL) + return state_key->source_state->name; + + return NULL; +} + +/** + * clutter_state_key_get_target_state_name: + * @state_key: a #ClutterStateKey + * + * Get the name of the source state this #ClutterStateKey contains, + * or NULL if this is the generic state key for the given property + * when transitioning to the target state. + * + * Return value: the name of the source state for this key, or NULL if + * the key is generic + * + * Since: 1.4 + * Deprecated: 1.12: Use #ClutterKeyframeTransition and + * #ClutterTransitionGroup instead + */ +const gchar * +clutter_state_key_get_target_state_name (const ClutterStateKey *state_key) +{ + g_return_val_if_fail (state_key, NULL); + + return state_key->target_state->name; +} + +/** + * clutter_state_key_get_property_type: + * @key: a #ClutterStateKey + * + * Retrieves the #GType of the property a key applies to + * + * You can use this type to initialize the #GValue to pass to + * clutter_state_key_get_value() + * + * Return value: the #GType of the property + * + * Since: 1.4 + * Deprecated: 1.12: Use #ClutterKeyframeTransition and + * #ClutterTransitionGroup instead + */ +GType +clutter_state_key_get_property_type (const ClutterStateKey *key) +{ + g_return_val_if_fail (key != NULL, G_TYPE_INVALID); + + return G_VALUE_TYPE (&key->value); +} + + +/** + * clutter_state_set_duration: + * @state: a #ClutterState + * @source_state_name: (allow-none): the name of the source state, or %NULL + * @target_state_name: (allow-none): the name of the target state, or %NULL + * @duration: the duration of the transition, in milliseconds + * + * Sets the duration of a transition. + * + * If both state names are %NULL the default duration for @state is set. + * + * If only @target_state_name is specified, the passed @duration becomes + * the default duration for transitions to the target state. + * + * If both states names are specified, the passed @duration only applies + * to the specified transition. + * + * Since: 1.4 + * Deprecated: 1.12: Use #ClutterKeyframeTransition and + * #ClutterTransitionGroup instead + */ +void +clutter_state_set_duration (ClutterState *state, + const gchar *source_state_name, + const gchar *target_state_name, + guint duration) +{ + State *target_state; + + g_return_if_fail (CLUTTER_IS_STATE (state)); + + source_state_name = g_intern_string (source_state_name); + if (source_state_name == g_intern_static_string ("")) + source_state_name = NULL; + + target_state_name = g_intern_string (target_state_name); + if (target_state_name == g_intern_static_string ("")) + target_state_name = NULL; + + if (target_state_name == NULL) + { + state->priv->duration = duration; + return; + } + + target_state = clutter_state_fetch_state (state, target_state_name, FALSE); + if (target_state != NULL) + { + if (source_state_name != NULL) + g_hash_table_insert (target_state->durations, + (gpointer) source_state_name, + GINT_TO_POINTER (duration)); + else + g_hash_table_insert (target_state->durations, + NULL, + GINT_TO_POINTER (duration)); + } +} + +/** + * clutter_state_get_duration: + * @state: a #ClutterState + * @source_state_name: (allow-none): the name of the source state to + * get the duration of, or %NULL + * @target_state_name: (allow-none): the name of the source state to + * get the duration of, or %NULL + * + * Queries the duration used for transitions between a source and + * target state pair + * + * The semantics for the query are the same as the semantics used for + * setting the duration with clutter_state_set_duration() + * + * Return value: the duration, in milliseconds + * + * Since: 1.4 + * Deprecated: 1.12: Use #ClutterKeyframeTransition and + * #ClutterTransitionGroup instead + */ +guint +clutter_state_get_duration (ClutterState *state, + const gchar *source_state_name, + const gchar *target_state_name) +{ + State *target_state; + guint ret = 0; + + g_return_val_if_fail (CLUTTER_IS_STATE (state), 0); + + source_state_name = g_intern_string (source_state_name); + if (source_state_name == g_intern_static_string ("")) + source_state_name = NULL; + + target_state_name = g_intern_string (target_state_name); + if (target_state_name == g_intern_static_string ("")) + target_state_name = NULL; + + if (target_state_name == NULL) + return state->priv->duration; + + target_state = clutter_state_fetch_state (state, target_state_name, FALSE); + if (target_state != NULL) + { + if (source_state_name) + { + ret = GPOINTER_TO_INT (g_hash_table_lookup (target_state->durations, + source_state_name)); + if(!ret) + ret = GPOINTER_TO_INT (g_hash_table_lookup (target_state->durations, + NULL)); + } + else + ret = GPOINTER_TO_INT (g_hash_table_lookup (target_state->durations, + NULL)); + } + + if (!ret) + ret = state->priv->duration; + + return ret; +} + +/** + * clutter_state_get_state: + * @state: a #ClutterState + * + * Queries the currently set target state. + * + * During a transition this function will return the target of the transition. + * + * This function is useful when called from handlers of the + * #ClutterState::completed signal. + * + * Return value: a string containing the target state. The returned string + * is owned by the #ClutterState and should not be modified or freed + * + * Since: 1.4 + * Deprecated: 1.12: Use #ClutterKeyframeTransition and + * #ClutterTransitionGroup instead + */ +const gchar * +clutter_state_get_state (ClutterState *state) +{ + g_return_val_if_fail (CLUTTER_IS_STATE (state), NULL); + + return state->priv->target_state_name; +} + +typedef struct _ParseClosure { + ClutterState *state; + ClutterScript *script; + + GValue *value; + + gboolean result; +} ParseClosure; + +static void +parse_state_transition (JsonArray *array, + guint index_, + JsonNode *element, + gpointer data) +{ + ParseClosure *clos = data; + JsonObject *object; + const gchar *source_name, *target_name; + State *source_state, *target_state; + JsonArray *keys; + GSList *valid_keys = NULL; + GList *array_keys, *k; + + if (JSON_NODE_TYPE (element) != JSON_NODE_OBJECT) + { + g_warning ("The 'transitions' member of a ClutterState description " + "should be an array of objects, but the element %d of the " + "array is of type '%s'. The element will be ignored.", + index_, + json_node_type_name (element)); + return; + } + + object = json_node_get_object (element); + + if (!json_object_has_member (object, "source") || + !json_object_has_member (object, "target") || + !(json_object_has_member (object, "keys") || + json_object_has_member (object, "animator"))) + { + g_warning ("The transition description at index %d is missing one " + "of the mandatory members: source, target and keys or " + "animator", index_); + return; + } + + source_name = json_object_get_string_member (object, "source"); + source_state = clutter_state_fetch_state (clos->state, source_name, TRUE); + + target_name = json_object_get_string_member (object, "target"); + target_state = clutter_state_fetch_state (clos->state, target_name, TRUE); + + if (json_object_has_member (object, "duration")) + { + guint duration = json_object_get_int_member (object, "duration"); + + clutter_state_set_duration (clos->state, + source_name, target_name, + duration); + } + + if (json_object_has_member (object, "animator")) + { + const gchar *id_ = json_object_get_string_member (object, "animator"); + GObject *animator; + + animator = clutter_script_get_object (clos->script, id_); + if (animator == NULL) + { + g_warning ("No object with id '%s' has been defined.", id_); + return; + } + + clutter_state_set_animator (clos->state, + source_name, + target_name, + CLUTTER_ANIMATOR (animator)); + } + + if (!json_object_has_member (object, "keys")) + return; + + keys = json_object_get_array_member (object, "keys"); + if (keys == NULL && !json_object_has_member (object, "animator")) + { + g_warning ("The transition description at index %d has an invalid " + "key member of type '%s' when an array was expected.", + index_, + json_node_type_name (json_object_get_member (object, "keys"))); + return; + } + + if (G_IS_VALUE (clos->value)) + valid_keys = g_slist_reverse (g_value_get_pointer (clos->value)); + else + g_value_init (clos->value, G_TYPE_POINTER); + + array_keys = json_array_get_elements (keys); + for (k = array_keys; k != NULL; k = k->next) + { + JsonNode *node = k->data; + JsonArray *key = json_node_get_array (node); + ClutterStateKey *state_key; + GObject *gobject; + GParamSpec *pspec; + const gchar *id_; + const gchar *property; + gulong mode; + gboolean res; + + id_ = json_array_get_string_element (key, 0); + gobject = clutter_script_get_object (clos->script, id_); + if (gobject == NULL) + { + g_warning ("No object with id '%s' has been defined.", id_); + continue; + } + + property = json_array_get_string_element (key, 1); + pspec = get_property_from_object (gobject, property); + if (pspec == NULL) + { + g_warning ("The object of type '%s' and name '%s' has no " + "property named '%s'.", + G_OBJECT_TYPE_NAME (gobject), + id_, + property); + continue; + } + + mode = _clutter_script_resolve_animation_mode (json_array_get_element (key, 2)); + + state_key = clutter_state_key_new (target_state, + gobject, property, pspec, + mode); + + res = _clutter_script_parse_node (clos->script, + &(state_key->value), + property, + json_array_get_element (key, 3), + pspec); + if (!res) + { + g_warning ("Unable to parse the key value for the " + "property '%s' of object '%s' at index %d", + property, + id_, + index_); + clutter_state_key_free (state_key); + continue; + } + + switch (json_array_get_length (key)) + { + case 5: + state_key->pre_delay = json_array_get_double_element (key, 4); + state_key->post_delay = 0.0; + break; + + case 6: + state_key->pre_delay = json_array_get_double_element (key, 4); + state_key->post_delay = json_array_get_double_element (key, 5); + break; + + default: + state_key->pre_delay = 0.0; + state_key->post_delay = 0.0; + break; + } + + state_key->source_state = source_state; + + valid_keys = g_slist_prepend (valid_keys, state_key); + } + + g_list_free (array_keys); + + g_value_set_pointer (clos->value, g_slist_reverse (valid_keys)); + + clos->result = TRUE; +} + +static gboolean +clutter_state_parse_custom_node (ClutterScriptable *scriptable, + ClutterScript *script, + GValue *value, + const gchar *name, + JsonNode *node) +{ + ParseClosure clos; + + if (strcmp (name, "transitions") != 0) + return FALSE; + + if (JSON_NODE_TYPE (node) != JSON_NODE_ARRAY) + return FALSE; + + clos.state = CLUTTER_STATE (scriptable); + clos.script = script; + clos.value = value; + clos.result = FALSE; + + json_array_foreach_element (json_node_get_array (node), + parse_state_transition, + &clos); + + return clos.result; +} + +static void +clutter_state_set_custom_property (ClutterScriptable *scriptable, + ClutterScript *script, + const gchar *name, + const GValue *value) +{ + if (strcmp (name, "transitions") == 0) + { + ClutterState *state = CLUTTER_STATE (scriptable); + GSList *keys = g_value_get_pointer (value); + GSList *k; + + for (k = keys; k != NULL; k = k->next) + clutter_state_set_key_internal (state, k->data); + + g_slist_free (keys); + } + else + g_object_set_property (G_OBJECT (scriptable), name, value); +} + +static void +clutter_scriptable_iface_init (ClutterScriptableIface *iface) +{ + iface->parse_custom_node = clutter_state_parse_custom_node; + iface->set_custom_property = clutter_state_set_custom_property; +} diff --git a/clutter/clutter/deprecated/clutter-state.h b/clutter/clutter/deprecated/clutter-state.h new file mode 100644 index 0000000..e33ae0f --- /dev/null +++ b/clutter/clutter/deprecated/clutter-state.h @@ -0,0 +1,187 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Øyvind KolÃ¥s + * + * 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 . + */ + +#ifndef __CLUTTER_STATE_H__ +#define __CLUTTER_STATE_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_STATE_KEY (clutter_state_key_get_type ()) +#define CLUTTER_TYPE_STATE (clutter_state_get_type ()) +#define CLUTTER_STATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STATE, ClutterState)) +#define CLUTTER_STATE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_STATE, ClutterStateClass)) +#define CLUTTER_IS_STATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_STATE)) +#define CLUTTER_IS_STATE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_STATE)) +#define CLUTTER_STATE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_STATE, ClutterStateClass)) + +typedef struct _ClutterStatePrivate ClutterStatePrivate; +typedef struct _ClutterStateClass ClutterStateClass; + +/** + * ClutterStateKey: + * + * #ClutterStateKey is an opaque structure whose + * members cannot be accessed directly + * + * Since: 1.4 + */ +typedef struct _ClutterStateKey ClutterStateKey; + +/** + * ClutterState: + * + * The #ClutterState structure contains only + * private data and should be accessed using the provided API + * + * Since: 1.4 + */ +struct _ClutterState +{ + /*< private >*/ + GObject parent; + ClutterStatePrivate *priv; +}; + +/** + * ClutterStateClass: + * @completed: class handler for the #ClutterState::completed signal + * + * The #ClutterStateClass structure contains + * only private data + * + * Since: 1.4 + * + * Deprecated: 1.12 + */ +struct _ClutterStateClass +{ + /*< private >*/ + GObjectClass parent_class; + + /*< public >*/ + void (* completed) (ClutterState *state); + + /*< private >*/ + /* padding for future expansion */ + gpointer _padding_dummy[8]; +}; + +CLUTTER_DEPRECATED_IN_1_12 +GType clutter_state_get_type (void) G_GNUC_CONST; + +CLUTTER_DEPRECATED_IN_1_12 +ClutterState *clutter_state_new (void); + + +CLUTTER_DEPRECATED_IN_1_12 +ClutterTimeline * clutter_state_set_state (ClutterState *state, + const gchar *target_state_name); +CLUTTER_DEPRECATED_IN_1_12 +ClutterTimeline * clutter_state_warp_to_state (ClutterState *state, + const gchar *target_state_name); +CLUTTER_DEPRECATED_IN_1_12 +ClutterState * clutter_state_set_key (ClutterState *state, + const gchar *source_state_name, + const gchar *target_state_name, + GObject *object, + const gchar *property_name, + guint mode, + const GValue *value, + gdouble pre_delay, + gdouble post_delay); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_state_set_duration (ClutterState *state, + const gchar *source_state_name, + const gchar *target_state_name, + guint duration); +CLUTTER_DEPRECATED_IN_1_12 +guint clutter_state_get_duration (ClutterState *state, + const gchar *source_state_name, + const gchar *target_state_name); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_state_set (ClutterState *state, + const gchar *source_state_name, + const gchar *target_state_name, + gpointer first_object, + const gchar *first_property_name, + gulong first_mode, + ...) G_GNUC_NULL_TERMINATED; +CLUTTER_DEPRECATED_IN_1_12 +GList * clutter_state_get_states (ClutterState *state); +CLUTTER_DEPRECATED_IN_1_12 +GList * clutter_state_get_keys (ClutterState *state, + const gchar *source_state_name, + const gchar *target_state_name, + GObject *object, + const gchar *property_name); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_state_remove_key (ClutterState *state, + const gchar *source_state_name, + const gchar *target_state_name, + GObject *object, + const gchar *property_name); +CLUTTER_DEPRECATED_IN_1_12 +ClutterTimeline * clutter_state_get_timeline (ClutterState *state); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_state_set_animator (ClutterState *state, + const gchar *source_state_name, + const gchar *target_state_name, + ClutterAnimator *animator); +CLUTTER_DEPRECATED_IN_1_12 +ClutterAnimator * clutter_state_get_animator (ClutterState *state, + const gchar *source_state_name, + const gchar *target_state_name); +CLUTTER_DEPRECATED_IN_1_12 +const gchar * clutter_state_get_state (ClutterState *state); + +/* + * ClutterStateKey + */ + +CLUTTER_DEPRECATED_IN_1_12 +GType clutter_state_key_get_type (void) G_GNUC_CONST; +CLUTTER_DEPRECATED_IN_1_12 +gdouble clutter_state_key_get_pre_delay (const ClutterStateKey *state_key); +CLUTTER_DEPRECATED_IN_1_12 +gdouble clutter_state_key_get_post_delay (const ClutterStateKey *state_key); +CLUTTER_DEPRECATED_IN_1_12 +gulong clutter_state_key_get_mode (const ClutterStateKey *state_key); +CLUTTER_DEPRECATED_IN_1_12 +gboolean clutter_state_key_get_value (const ClutterStateKey *state_key, + GValue *value); +CLUTTER_DEPRECATED_IN_1_12 +GType clutter_state_key_get_property_type (const ClutterStateKey *key); +CLUTTER_DEPRECATED_IN_1_12 +GObject * clutter_state_key_get_object (const ClutterStateKey *state_key); +CLUTTER_DEPRECATED_IN_1_12 +const gchar * clutter_state_key_get_property_name (const ClutterStateKey *state_key); +CLUTTER_DEPRECATED_IN_1_12 +const gchar * clutter_state_key_get_source_state_name (const ClutterStateKey *state_key); +CLUTTER_DEPRECATED_IN_1_12 +const gchar * clutter_state_key_get_target_state_name (const ClutterStateKey *state_key); + +G_END_DECLS + +#endif /* __CLUTTER_STATE_H__ */ diff --git a/clutter/clutter/deprecated/clutter-table-layout.c b/clutter/clutter/deprecated/clutter-table-layout.c new file mode 100644 index 0000000..f8b1b87 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-table-layout.c @@ -0,0 +1,2611 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * 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 . + * + * Author: + * Jose Dapena Paz + * + * Based on the MX MxTable actor by: + * Thomas Wood + * and ClutterBoxLayout by: + * Emmanuele Bassi + */ + +/** + * SECTION:clutter-table-layout + * @title: ClutterTableLayout + * @short_description: A layout manager arranging children in rows + * and columns + * + * The #ClutterTableLayout is a #ClutterLayoutManager implementing the + * following layout policy: + * + * - children are arranged in a table + * - each child specifies the specific row and column + * cell to appear; + * - a child can also set a span, and this way, take + * more than one cell both horizontally and vertically; + * - each child will be allocated to its natural + * size or, if set to expand, the available size; + * - if a child is set to fill on either (or both) + * axis, its allocation will match all the available size; the + * fill layout property only makes sense if the expand property is + * also set; + * - if a child is set to expand but not to fill then + * it is possible to control the alignment using the horizontal and + * vertical alignment layout properties. + * + * It is possible to control the spacing between children of a + * #ClutterTableLayout by using clutter_table_layout_set_row_spacing() + * and clutter_table_layout_set_column_spacing(). + * + * In order to set the layout properties when packing an actor inside a + * #ClutterTableLayout you should use the clutter_table_layout_pack() + * function. + * + * A #ClutterTableLayout can use animations to transition between different + * values of the layout management properties; the easing mode and duration + * used for the animations are controlled by the + * #ClutterTableLayout:easing-mode and #ClutterTableLayout:easing-duration + * properties and their accessor functions. + * + * #ClutterTableLayout is available since Clutter 1.4 + * + * Since Clutter 1.18 it's recommended to use #ClutterGridLayout instead + * of #ClutterTableLayout; the former supports right-to-left text direction, + * as well as using the alignment and expansion flags on #ClutterActor. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include "deprecated/clutter-container.h" +#include "deprecated/clutter-alpha.h" + +#include "clutter-table-layout.h" + +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-layout-meta.h" +#include "clutter-private.h" +#include "clutter-types.h" + +#define CLUTTER_TYPE_TABLE_CHILD (clutter_table_child_get_type ()) +#define CLUTTER_TABLE_CHILD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_TABLE_CHILD, ClutterTableChild)) +#define CLUTTER_IS_TABLE_CHILD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_TABLE_CHILD)) + +typedef struct _ClutterTableChild ClutterTableChild; +typedef struct _ClutterLayoutMetaClass ClutterTableChildClass; + +typedef struct _DimensionData { + gfloat min_size; + gfloat pref_size; + gfloat final_size; + + guint expand : 1; + guint visible : 1; +} DimensionData; + +struct _ClutterTableLayoutPrivate +{ + ClutterContainer *container; + + guint col_spacing; + guint row_spacing; + + gint n_rows; + gint n_cols; + gint active_row; + gint active_col; + gint visible_rows; + gint visible_cols; + + GArray *columns; + GArray *rows; + + gulong easing_mode; + guint easing_duration; + + guint is_animating : 1; + guint use_animations : 1; +}; + +struct _ClutterTableChild +{ + ClutterLayoutMeta parent_instance; + + gint col; + gint row; + + gint col_span; + gint row_span; + + ClutterTableAlignment x_align; + ClutterTableAlignment y_align; + + guint x_expand : 1; + guint y_expand : 1; + guint x_fill : 1; + guint y_fill : 1; +}; + +enum +{ + PROP_CHILD_0, + + PROP_CHILD_ROW, + PROP_CHILD_COLUMN, + PROP_CHILD_ROW_SPAN, + PROP_CHILD_COLUMN_SPAN, + PROP_CHILD_X_ALIGN, + PROP_CHILD_Y_ALIGN, + PROP_CHILD_X_FILL, + PROP_CHILD_Y_FILL, + PROP_CHILD_X_EXPAND, + PROP_CHILD_Y_EXPAND +}; + +enum +{ + PROP_0, + + PROP_ROW_SPACING, + PROP_COLUMN_SPACING, + PROP_USE_ANIMATIONS, + PROP_EASING_MODE, + PROP_EASING_DURATION +}; + +GType clutter_table_child_get_type (void); + +G_DEFINE_TYPE (ClutterTableChild, clutter_table_child, CLUTTER_TYPE_LAYOUT_META) + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterTableLayout, clutter_table_layout, CLUTTER_TYPE_LAYOUT_MANAGER) + +/* + * ClutterBoxChild + */ + +static void +table_child_set_position (ClutterTableChild *self, + gint col, + gint row) +{ + gboolean row_changed = FALSE, col_changed = FALSE; + + if (self->col != col) + { + self->col = col; + + col_changed = TRUE; + } + + if (self->row != row) + { + self->row = row; + + row_changed = TRUE; + } + + if (row_changed || col_changed) + { + ClutterLayoutManager *layout; + + layout = clutter_layout_meta_get_manager (CLUTTER_LAYOUT_META (self)); + clutter_layout_manager_layout_changed (layout); + + g_object_freeze_notify (G_OBJECT (self)); + + if (row_changed) + g_object_notify (G_OBJECT (self), "row"); + + if (col_changed) + g_object_notify (G_OBJECT (self), "column"); + + g_object_thaw_notify (G_OBJECT (self)); + } +} + +static void +table_child_set_span (ClutterTableChild *self, + gint col_span, + gint row_span) +{ + gboolean row_changed = FALSE, col_changed = FALSE; + + if (self->col_span != col_span) + { + self->col_span = col_span; + + col_changed = TRUE; + } + + if (self->row_span != row_span) + { + self->row_span = row_span; + + row_changed = TRUE; + } + + if (row_changed || col_changed) + { + ClutterLayoutManager *layout; + + layout = clutter_layout_meta_get_manager (CLUTTER_LAYOUT_META (self)); + clutter_layout_manager_layout_changed (layout); + + if (row_changed) + g_object_notify (G_OBJECT (self), "row-span"); + + if (col_changed) + g_object_notify (G_OBJECT (self), "column-span"); + } +} + +static void +table_child_set_align (ClutterTableChild *self, + ClutterTableAlignment x_align, + ClutterTableAlignment y_align) +{ + gboolean x_changed = FALSE, y_changed = FALSE; + + if (self->x_align != x_align) + { + self->x_align = x_align; + + x_changed = TRUE; + } + + if (self->y_align != y_align) + { + self->y_align = y_align; + + y_changed = TRUE; + } + + if (x_changed || y_changed) + { + ClutterLayoutManager *layout; + + layout = clutter_layout_meta_get_manager (CLUTTER_LAYOUT_META (self)); + clutter_layout_manager_layout_changed (layout); + + g_object_freeze_notify (G_OBJECT (self)); + + if (x_changed) + g_object_notify (G_OBJECT (self), "x-align"); + + if (y_changed) + g_object_notify (G_OBJECT (self), "y-align"); + + g_object_thaw_notify (G_OBJECT (self)); + } +} + +static void +table_child_set_fill (ClutterTableChild *self, + gboolean x_fill, + gboolean y_fill) +{ + gboolean x_changed = FALSE, y_changed = FALSE; + + x_fill = !!x_fill; + y_fill = !!y_fill; + + if (self->x_fill != x_fill) + { + self->x_fill = x_fill; + + x_changed = TRUE; + } + + if (self->y_fill != y_fill) + { + self->y_fill = y_fill; + + y_changed = TRUE; + } + + if (x_changed || y_changed) + { + ClutterLayoutManager *layout; + + layout = clutter_layout_meta_get_manager (CLUTTER_LAYOUT_META (self)); + clutter_layout_manager_layout_changed (layout); + + g_object_freeze_notify (G_OBJECT (self)); + + if (x_changed) + g_object_notify (G_OBJECT (self), "x-fill"); + + if (y_changed) + g_object_notify (G_OBJECT (self), "y-fill"); + + g_object_thaw_notify (G_OBJECT (self)); + } +} + +static void +table_child_set_expand (ClutterTableChild *self, + gboolean x_expand, + gboolean y_expand) +{ + gboolean x_changed = FALSE, y_changed = FALSE; + + x_expand = !!x_expand; + y_expand = !!y_expand; + + if (self->x_expand != x_expand) + { + self->x_expand = x_expand; + + x_changed = TRUE; + } + + if (self->y_expand != y_expand) + { + self->y_expand = y_expand; + + y_changed = TRUE; + } + + if (x_changed || y_changed) + { + ClutterLayoutManager *layout; + + layout = clutter_layout_meta_get_manager (CLUTTER_LAYOUT_META (self)); + clutter_layout_manager_layout_changed (layout); + + g_object_freeze_notify (G_OBJECT (self)); + + if (x_changed) + g_object_notify (G_OBJECT (self), "x-expand"); + + if (y_changed) + g_object_notify (G_OBJECT (self), "y-expand"); + + g_object_thaw_notify (G_OBJECT (self)); + } +} + +static void +clutter_table_child_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterTableChild *self = CLUTTER_TABLE_CHILD (gobject); + + switch (prop_id) + { + case PROP_CHILD_COLUMN: + table_child_set_position (self, + g_value_get_int (value), + self->row); + break; + + case PROP_CHILD_ROW: + table_child_set_position (self, + self->col, + g_value_get_int (value)); + break; + + case PROP_CHILD_COLUMN_SPAN: + table_child_set_span (self, + g_value_get_int (value), + self->row_span); + break; + + case PROP_CHILD_ROW_SPAN: + table_child_set_span (self, + self->col_span, + g_value_get_int (value)); + break; + + case PROP_CHILD_X_ALIGN: + table_child_set_align (self, + g_value_get_enum (value), + self->y_align); + break; + + case PROP_CHILD_Y_ALIGN: + table_child_set_align (self, + self->x_align, + g_value_get_enum (value)); + break; + + case PROP_CHILD_X_FILL: + table_child_set_fill (self, + g_value_get_boolean (value), + self->y_fill); + break; + + case PROP_CHILD_Y_FILL: + table_child_set_fill (self, + self->x_fill, + g_value_get_boolean (value)); + break; + + case PROP_CHILD_X_EXPAND: + table_child_set_expand (self, + g_value_get_boolean (value), + self->y_expand); + break; + + case PROP_CHILD_Y_EXPAND: + table_child_set_expand (self, + self->x_expand, + g_value_get_boolean (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_table_child_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterTableChild *self = CLUTTER_TABLE_CHILD (gobject); + + switch (prop_id) + { + case PROP_CHILD_ROW: + g_value_set_int (value, self->row); + break; + + case PROP_CHILD_COLUMN: + g_value_set_int (value, self->col); + break; + + case PROP_CHILD_ROW_SPAN: + g_value_set_int (value, self->row_span); + break; + + case PROP_CHILD_COLUMN_SPAN: + g_value_set_int (value, self->col_span); + break; + + case PROP_CHILD_X_ALIGN: + g_value_set_enum (value, self->x_align); + break; + + case PROP_CHILD_Y_ALIGN: + g_value_set_enum (value, self->y_align); + break; + + case PROP_CHILD_X_FILL: + g_value_set_boolean (value, self->x_fill); + break; + + case PROP_CHILD_Y_FILL: + g_value_set_boolean (value, self->y_fill); + break; + + case PROP_CHILD_X_EXPAND: + g_value_set_boolean (value, self->x_expand); + break; + + case PROP_CHILD_Y_EXPAND: + g_value_set_boolean (value, self->y_expand); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_table_child_class_init (ClutterTableChildClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GParamSpec *pspec; + + gobject_class->set_property = clutter_table_child_set_property; + gobject_class->get_property = clutter_table_child_get_property; + + pspec = g_param_spec_int ("column", + P_("Column Number"), + P_("The column the widget resides in"), + 0, G_MAXINT, + 0, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_CHILD_COLUMN, pspec); + + pspec = g_param_spec_int ("row", + P_("Row Number"), + P_("The row the widget resides in"), + 0, G_MAXINT, + 0, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_CHILD_ROW, pspec); + + pspec = g_param_spec_int ("column-span", + P_("Column Span"), + P_("The number of columns the widget should span"), + 1, G_MAXINT, + 1, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_CHILD_COLUMN_SPAN, pspec); + + pspec = g_param_spec_int ("row-span", + P_("Row Span"), + P_("The number of rows the widget should span"), + 1, G_MAXINT, + 1, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_CHILD_ROW_SPAN, pspec); + + pspec = g_param_spec_boolean ("x-expand", + P_("Horizontal Expand"), + P_("Allocate extra space for the child in horizontal axis"), + TRUE, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_CHILD_X_EXPAND, pspec); + + pspec = g_param_spec_boolean ("y-expand", + P_("Vertical Expand"), + P_("Allocate extra space for the child in vertical axis"), + TRUE, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_CHILD_Y_EXPAND, pspec); + + pspec = g_param_spec_boolean ("x-fill", + P_("Horizontal Fill"), + P_("Whether the child should receive priority when the container is allocating spare space on the horizontal axis"), + TRUE, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_CHILD_X_FILL, pspec); + + pspec = g_param_spec_boolean ("y-fill", + P_("Vertical Fill"), + P_("Whether the child should receive priority when the container is allocating spare space on the vertical axis"), + TRUE, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_CHILD_Y_FILL, pspec); + + /** + * ClutterTableLayout:x-align: + * + * The horizontal alignment of the actor within the cell + * + * Since: 1.4 + */ + pspec = g_param_spec_enum ("x-align", + P_("Horizontal Alignment"), + P_("Horizontal alignment of the actor within the cell"), + CLUTTER_TYPE_TABLE_ALIGNMENT, + CLUTTER_TABLE_ALIGNMENT_CENTER, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_CHILD_X_ALIGN, pspec); + + /** + * ClutterTableLayout:y-align: + * + * The vertical alignment of the actor within the cell + * + * Since: 1.4 + */ + pspec = g_param_spec_enum ("y-align", + P_("Vertical Alignment"), + P_("Vertical alignment of the actor within the cell"), + CLUTTER_TYPE_TABLE_ALIGNMENT, + CLUTTER_TABLE_ALIGNMENT_CENTER, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_CHILD_Y_ALIGN, pspec); +} + +static void +clutter_table_child_init (ClutterTableChild *self) +{ + self->col_span = 1; + self->row_span = 1; + + self->x_align = CLUTTER_TABLE_ALIGNMENT_CENTER; + self->y_align = CLUTTER_TABLE_ALIGNMENT_CENTER; + + self->x_expand = TRUE; + self->y_expand = TRUE; + + self->x_fill = TRUE; + self->y_fill = TRUE; +} + +static GType +clutter_table_layout_get_child_meta_type (ClutterLayoutManager *manager) +{ + return CLUTTER_TYPE_TABLE_CHILD; +} + +static void +clutter_table_layout_set_container (ClutterLayoutManager *layout, + ClutterContainer *container) +{ + ClutterTableLayoutPrivate *priv = CLUTTER_TABLE_LAYOUT (layout)->priv; + + priv->container = container; +} + + +static void +update_row_col (ClutterTableLayout *layout, + ClutterContainer *container) +{ + ClutterTableLayoutPrivate *priv = layout->priv; + ClutterLayoutManager *manager = CLUTTER_LAYOUT_MANAGER (layout); + ClutterActor *actor, *child; + gint n_cols, n_rows; + + n_cols = n_rows = 0; + + if (container == NULL) + goto out; + + actor = CLUTTER_ACTOR (container); + for (child = clutter_actor_get_first_child (actor); + child != NULL; + child = clutter_actor_get_next_sibling (child)) + { + ClutterTableChild *meta; + + meta = + CLUTTER_TABLE_CHILD (clutter_layout_manager_get_child_meta (manager, + container, + child)); + + n_cols = MAX (n_cols, meta->col + meta->col_span); + n_rows = MAX (n_rows, meta->row + meta->row_span); + } + +out: + priv->n_cols = n_cols; + priv->n_rows = n_rows; + +} + +static void +calculate_col_widths (ClutterTableLayout *self, + ClutterContainer *container, + gint for_width) +{ + ClutterTableLayoutPrivate *priv = self->priv; + ClutterLayoutManager *manager = CLUTTER_LAYOUT_MANAGER (self); + ClutterActor *actor, *child; + gint i; + DimensionData *columns; + ClutterOrientation orientation = CLUTTER_ORIENTATION_HORIZONTAL; + + update_row_col (self, container); + g_array_set_size (priv->columns, 0); + g_array_set_size (priv->columns, priv->n_cols); + columns = (DimensionData *) (void *) priv->columns->data; + + /* reset the visibility of all columns */ + priv->visible_cols = 0; + for (i = 0; i < priv->n_cols; i++) + { + columns[i].expand = FALSE; + columns[i].visible = FALSE; + } + + actor = CLUTTER_ACTOR (container); + + /* STAGE ONE: calculate column widths for non-spanned children */ + for (child = clutter_actor_get_first_child (actor); + child != NULL; + child = clutter_actor_get_next_sibling (child)) + { + ClutterTableChild *meta; + DimensionData *col; + gfloat c_min, c_pref; + + if (!clutter_actor_is_visible (child)) + continue; + + meta = + CLUTTER_TABLE_CHILD (clutter_layout_manager_get_child_meta (manager, + container, + child)); + + if (meta->col_span > 1) + continue; + + col = &columns[meta->col]; + + if (!col->visible) + { + col->visible = TRUE; + priv->visible_cols += 1; + } + + clutter_actor_get_preferred_width (child, -1, &c_min, &c_pref); + + col->min_size = MAX (col->min_size, c_min); + col->pref_size = MAX (col->pref_size, c_pref); + + if (!col->expand) + { + col->expand = clutter_actor_needs_expand (child, orientation) || + meta->x_expand; + } + } + + /* STAGE TWO: take spanning children into account */ + for (child = clutter_actor_get_first_child (actor); + child != NULL; + child = clutter_actor_get_next_sibling (child)) + { + ClutterTableChild *meta; + gfloat c_min, c_pref; + gfloat min_width, pref_width; + gint start_col, end_col; + gint n_expand; + + if (!clutter_actor_is_visible (child)) + continue; + + meta = + CLUTTER_TABLE_CHILD (clutter_layout_manager_get_child_meta (manager, + container, + child)); + + if (meta->col_span < 2) + continue; + + start_col = meta->col; + end_col = meta->col + meta->col_span - 1; + + clutter_actor_get_preferred_width (child, -1, &c_min, &c_pref); + + /* check there is enough room for this actor */ + min_width = 0; + pref_width = 0; + n_expand = 0; + for (i = start_col; i <= end_col; i++) + { + min_width += columns[i].min_size; + pref_width += columns[i].pref_size; + + if (columns[i].expand) + n_expand++; + + if (!columns[i].visible) + { + columns[i].visible = TRUE; + priv->visible_cols += 1; + } + + if (!columns[i].expand) + { + columns[i].expand = clutter_actor_needs_expand (child, + orientation) || + meta->x_expand; + } + } + min_width += priv->col_spacing * (meta->col_span - 1); + pref_width += priv->col_spacing * (meta->col_span - 1); + + /* see calculate_row_heights() for comments */ + /* (1) */ + if (c_min > min_width) + { + + /* (2) */ + /* we can start from preferred width and decrease */ + if (pref_width > c_min) + { + for (i = start_col; i <= end_col; i++) + columns[i].final_size = columns[i].pref_size; + + while (pref_width > c_min) + { + for (i = start_col; i <= end_col; i++) + { + if (columns[i].final_size > columns[i].min_size) + { + columns[i].final_size--; + pref_width--; + } + } + } + + for (i = start_col; i <= end_col; i++) + columns[i].min_size = columns[i].final_size; + } + else + { + /* (3) */ + /* we can expand from preferred size */ + gfloat expand_by; + + expand_by = c_pref - pref_width; + + for (i = start_col; i <= end_col; i++) + { + if (n_expand) + { + if (columns[i].expand) + columns[i].min_size = columns[i].pref_size + + expand_by / n_expand; + } + else + columns[i].min_size = columns[i].pref_size + + expand_by / meta->col_span; + } + } + } + } + + /* calculate final widths */ + if (for_width >= 0) + { + gfloat min_width, pref_width; + gint n_expand; + + min_width = 0; + pref_width = 0; + n_expand = 0; + + for (i = 0; i < self->priv->n_cols; i++) + { + pref_width += columns[i].pref_size; + min_width += columns[i].min_size; + if (columns[i].expand) + n_expand++; + } + + pref_width += priv->col_spacing * MAX (priv->visible_cols - 1, 0); + min_width += priv->col_spacing * MAX (priv->visible_cols - 1, 0); + + if (for_width <= min_width) + { + /* erk, we can't shrink this! */ + for (i = 0; i < priv->n_cols; i++) + columns[i].final_size = columns[i].min_size; + + return; + } + + if (for_width == pref_width) + { + /* perfect! */ + for (i = 0; i < self->priv->n_cols; i++) + columns[i].final_size = columns[i].pref_size; + + return; + } + + /* for_width is between min_width and pref_width */ + if (for_width < pref_width && for_width > min_width) + { + gfloat width; + + /* shrink columns until they reach min_width */ + + /* start with all columns at preferred size */ + for (i = 0; i < self->priv->n_cols; i++) + columns[i].final_size = columns[i].pref_size; + + width = pref_width; + + while (width > for_width) + { + for (i = 0; i < self->priv->n_cols; i++) + { + if (columns[i].final_size > columns[i].min_size) + { + columns[i].final_size--; + width--; + } + } + } + + return; + } + + /* expand columns */ + if (for_width > pref_width) + { + gfloat extra_width = for_width - pref_width; + gint remaining; + + if (n_expand) + remaining = (gint) extra_width % n_expand; + else + remaining = (gint) extra_width % priv->n_cols; + + for (i = 0; i < self->priv->n_cols; i++) + { + if (columns[i].expand) + { + columns[i].final_size = columns[i].pref_size + + (extra_width / n_expand); + } + else + columns[i].final_size = columns[i].pref_size; + } + + /* distribute the remainder among children */ + i = 0; + while (remaining) + { + columns[i].final_size++; + i++; + remaining--; + } + } + } + +} + +static void +calculate_row_heights (ClutterTableLayout *self, + ClutterContainer *container, + gint for_height) +{ + ClutterTableLayoutPrivate *priv = self->priv; + ClutterLayoutManager *manager = CLUTTER_LAYOUT_MANAGER (self); + ClutterActor *actor, *child; + gint i; + DimensionData *rows, *columns; + ClutterOrientation orientation = CLUTTER_ORIENTATION_VERTICAL; + + update_row_col (self, container); + g_array_set_size (priv->rows, 0); + g_array_set_size (priv->rows, self->priv->n_rows); + + rows = (DimensionData *) (void *) priv->rows->data; + columns = (DimensionData *) (void *) priv->columns->data; + + /* reset the visibility of all rows */ + priv->visible_rows = 0; + for (i = 0; i < priv->n_rows; i++) + { + rows[i].expand = FALSE; + rows[i].visible = FALSE; + } + + actor = CLUTTER_ACTOR (container); + + /* STAGE ONE: calculate row heights for non-spanned children */ + for (child = clutter_actor_get_first_child (actor); + child != NULL; + child = clutter_actor_get_next_sibling (child)) + { + ClutterTableChild *meta; + DimensionData *row; + gfloat c_min, c_pref; + + if (!clutter_actor_is_visible (child)) + continue; + + meta = + CLUTTER_TABLE_CHILD (clutter_layout_manager_get_child_meta (manager, + container, + child)); + + if (meta->row_span > 1) + continue; + + row = &rows[meta->row]; + + if (!row->visible) + { + row->visible = TRUE; + priv->visible_rows += 1; + } + + clutter_actor_get_preferred_height (child, columns[meta->col].final_size, + &c_min, &c_pref); + + row->min_size = MAX (row->min_size, c_min); + row->pref_size = MAX (row->pref_size, c_pref); + + if (!row->expand) + { + row->expand = clutter_actor_needs_expand (child, orientation) || + meta->y_expand; + } + } + + /* STAGE TWO: take spanning children into account */ + for (child = clutter_actor_get_first_child (actor); + child != NULL; + child = clutter_actor_get_next_sibling (child)) + { + ClutterTableChild *meta; + gfloat c_min, c_pref; + gfloat min_height, pref_height; + gint start_row, end_row; + gint n_expand; + + if (!clutter_actor_is_visible (child)) + continue; + + meta = + CLUTTER_TABLE_CHILD (clutter_layout_manager_get_child_meta (manager, + container, + child)); + + if (meta->row_span < 2) + continue; + + start_row = meta->row; + end_row = meta->row + meta->row_span - 1; + + clutter_actor_get_preferred_height (child, columns[meta->col].final_size, + &c_min, &c_pref); + + + /* check there is enough room for this actor */ + min_height = 0; + pref_height = 0; + n_expand = 0; + for (i = start_row; i <= end_row; i++) + { + min_height += rows[i].min_size; + pref_height += rows[i].pref_size; + + if (rows[i].expand) + n_expand++; + + if (!rows[i].visible) + { + rows[i].visible = TRUE; + priv->visible_rows += 1; + } + + if (!rows[i].expand) + { + rows[i].expand = clutter_actor_needs_expand (child, orientation) || + meta->y_expand; + } + } + + min_height += priv->row_spacing * (meta->row_span - 1); + pref_height += priv->row_spacing * (meta->row_span - 1); + + /* 1) If the minimum height of the rows spanned is less than the + * minimum height of the child that is spanning them, then we + * must increase the minimum height of the rows spanned. + * + * 2) If the preferred height of the spanned rows is more than + * the minimum height of the spanning child, then we can start + * at this size and decrease each row evenly. + * + * 3) If the preferred height of the rows is more than the minimum + * height of the spanned child, then we can start at the preferred + * height and expand. + */ + + /* (1) */ + if (c_min > min_height) + { + + /* (2) */ + /* we can start from preferred height and decrease */ + if (pref_height > c_min) + { + for (i = start_row; i <= end_row; i++) + rows[i].final_size = rows[i].pref_size; + + while (pref_height > c_min) + { + for (i = start_row; i <= end_row; i++) + { + if (rows[i].final_size > rows[i].min_size) + { + rows[i].final_size--; + pref_height--; + } + } + } + + for (i = start_row; i <= end_row; i++) + rows[i].min_size = rows[i].final_size; + } + else + { + /* (3) */ + /* we can expand from preferred size */ + gfloat expand_by = c_pref - pref_height; + + for (i = start_row; i <= end_row; i++) + { + if (n_expand) + { + if (rows[i].expand) + rows[i].min_size = rows[i].pref_size + + expand_by / n_expand; + } + else + rows[i].min_size = rows[i].pref_size + + expand_by / meta->row_span; + } + } + } + } + + /* calculate final heights */ + if (for_height >= 0) + { + gfloat min_height, pref_height; + gint n_expand; + + min_height = 0; + pref_height = 0; + n_expand = 0; + + for (i = 0; i < self->priv->n_rows; i++) + { + pref_height += rows[i].pref_size; + min_height += rows[i].min_size; + if (rows[i].expand) + n_expand++; + } + + pref_height += priv->row_spacing * MAX (priv->visible_rows - 1, 0); + min_height += priv->row_spacing * MAX (priv->visible_rows - 1, 0); + + if (for_height <= min_height) + { + /* erk, we can't shrink this! */ + for (i = 0; i < self->priv->n_rows; i++) + rows[i].final_size = rows[i].min_size; + + return; + } + + if (for_height == pref_height) + { + /* perfect! */ + for (i = 0; i < self->priv->n_rows; i++) + rows[i].final_size = rows[i].pref_size; + + return; + } + + /* for_height is between min_height and pref_height */ + if (for_height < pref_height && for_height > min_height) + { + gfloat height; + + /* shrink rows until they reach min_height */ + + /* start with all rows at preferred size */ + for (i = 0; i < self->priv->n_rows; i++) + rows[i].final_size = rows[i].pref_size; + + height = pref_height; + + while (height > for_height) + { + for (i = 0; i < priv->n_rows; i++) + { + if (rows[i].final_size > rows[i].min_size) + { + rows[i].final_size--; + height--; + } + } + } + + return; + } + + /* expand rows */ + if (for_height > pref_height) + { + gfloat extra_height = for_height - pref_height; + gint remaining; + + if (n_expand) + remaining = (gint) extra_height % n_expand; + else + remaining = (gint) extra_height % self->priv->n_rows; + + for (i = 0; i < self->priv->n_rows; i++) + { + if (rows[i].expand) + { + rows[i].final_size = rows[i].pref_size + + (extra_height / n_expand); + } + else + rows[i].final_size = rows[i].pref_size; + } + + /* distribute the remainder among children */ + i = 0; + while (remaining) + { + rows[i].final_size++; + i++; + remaining--; + } + } + } + +} + +static void +calculate_table_dimensions (ClutterTableLayout *self, + ClutterContainer *container, + gfloat for_width, + gfloat for_height) +{ + calculate_col_widths (self, container, for_width); + calculate_row_heights (self, container, for_height); +} + +static void +clutter_table_layout_get_preferred_width (ClutterLayoutManager *layout, + ClutterContainer *container, + gfloat for_height, + gfloat *min_width_p, + gfloat *natural_width_p) +{ + ClutterTableLayout *self = CLUTTER_TABLE_LAYOUT (layout); + ClutterTableLayoutPrivate *priv = self->priv; + gfloat total_min_width, total_pref_width; + DimensionData *columns; + gint i; + + update_row_col (self, container); + if (priv->n_cols < 1) + { + *min_width_p = 0; + *natural_width_p = 0; + return; + } + + calculate_table_dimensions (self, container, -1, for_height); + columns = (DimensionData *) (void *) priv->columns->data; + + total_min_width = MAX ((priv->visible_cols - 1) * (float) priv->col_spacing, 0); + total_pref_width = total_min_width; + + for (i = 0; i < priv->n_cols; i++) + { + total_min_width += columns[i].min_size; + total_pref_width += columns[i].pref_size; + } + + if (min_width_p) + *min_width_p = total_min_width; + + if (natural_width_p) + *natural_width_p = total_pref_width; +} + +static void +clutter_table_layout_get_preferred_height (ClutterLayoutManager *layout, + ClutterContainer *container, + gfloat for_width, + gfloat *min_height_p, + gfloat *natural_height_p) +{ + ClutterTableLayout *self = CLUTTER_TABLE_LAYOUT (layout); + ClutterTableLayoutPrivate *priv = self->priv; + gfloat total_min_height, total_pref_height; + DimensionData *rows; + gint i; + + update_row_col (self, container); + if (priv->n_rows < 1) + { + *min_height_p = 0; + *natural_height_p = 0; + return; + } + + calculate_table_dimensions (self, container, for_width, -1); + rows = (DimensionData *) (void *) priv->rows->data; + + total_min_height = MAX ((priv->visible_rows - 1) * (float) priv->row_spacing, 0); + total_pref_height = total_min_height; + + for (i = 0; i < self->priv->n_rows; i++) + { + total_min_height += rows[i].min_size; + total_pref_height += rows[i].pref_size; + } + + if (min_height_p) + *min_height_p = total_min_height; + + if (natural_height_p) + *natural_height_p = total_pref_height; +} + +static gdouble +get_table_alignment_factor (ClutterTableAlignment alignment) +{ + switch (alignment) + { + case CLUTTER_TABLE_ALIGNMENT_START: + return 0.0; + + case CLUTTER_TABLE_ALIGNMENT_CENTER: + return 0.5; + + case CLUTTER_TABLE_ALIGNMENT_END: + return 1.0; + } + + return 0.0; +} + +static void +clutter_table_layout_allocate (ClutterLayoutManager *layout, + ClutterContainer *container, + const ClutterActorBox *box, + ClutterAllocationFlags flags) +{ + ClutterTableLayout *self = CLUTTER_TABLE_LAYOUT (layout); + ClutterTableLayoutPrivate *priv = self->priv; + ClutterActor *actor, *child; + gint row_spacing, col_spacing; + gint i; + DimensionData *rows, *columns; + + update_row_col (self, container); + if (priv->n_cols < 1 || priv->n_rows < 1) + return; + + actor = CLUTTER_ACTOR (container); + + if (clutter_actor_get_n_children (actor) == 0) + return; + + col_spacing = (priv->col_spacing); + row_spacing = (priv->row_spacing); + + calculate_table_dimensions (self, container, + box->x2 - box->x1, + box->y2 - box->y1); + + rows = (DimensionData *) (void *) priv->rows->data; + columns = (DimensionData *) (void *) priv->columns->data; + + for (child = clutter_actor_get_first_child (actor); + child != NULL; + child = clutter_actor_get_next_sibling (child)) + { + gint row, col, row_span, col_span; + gint col_width, row_height; + ClutterTableChild *meta; + ClutterActorBox childbox; + gint child_x, child_y; + gdouble x_align, y_align; + gboolean x_fill, y_fill; + + if (!clutter_actor_is_visible (child)) + continue; + + meta = + CLUTTER_TABLE_CHILD (clutter_layout_manager_get_child_meta (layout, + container, + child)); + + /* get child properties */ + col = meta->col; + row = meta->row; + row_span = meta->row_span; + col_span = meta->col_span; + x_align = get_table_alignment_factor (meta->x_align); + y_align = get_table_alignment_factor (meta->y_align); + x_fill = meta->x_fill; + y_fill = meta->y_fill; + + /* initialise the width and height */ + col_width = columns[col].final_size; + row_height = rows[row].final_size; + + /* Add the widths of the spanned columns: + * + * First check that we have a non-zero span. Then we loop over each of + * the columns that we're spanning but we stop short if we go past the + * number of columns in the table. This is necessary to avoid accessing + * uninitialised memory. We add the spacing in here too since we only + * want to add as much spacing as times we successfully span. + */ + if (col + col_span > priv->n_cols) + g_warning (G_STRLOC ": column-span exceeds number of columns"); + if (row + row_span > priv->n_rows) + g_warning (G_STRLOC ": row-span exceeds number of rows"); + + if (col_span > 1) + { + for (i = col + 1; i < col + col_span && i < priv->n_cols; i++) + { + col_width += columns[i].final_size; + col_width += col_spacing; + } + } + + /* add the height of the spanned rows */ + if (row_span > 1) + { + for (i = row + 1; i < row + row_span && i < priv->n_rows; i++) + { + row_height += rows[i].final_size; + row_height += row_spacing; + } + } + + /* calculate child x */ + child_x = clutter_actor_box_get_x (box); + for (i = 0; i < col; i++) + { + if (columns[i].visible) + { + child_x += columns[i].final_size; + child_x += col_spacing; + } + } + + /* calculate child y */ + child_y = clutter_actor_box_get_y (box); + for (i = 0; i < row; i++) + { + if (rows[i].visible) + { + child_y += rows[i].final_size; + child_y += row_spacing; + } + } + + /* set up childbox */ + childbox.x1 = (float) child_x; + childbox.x2 = (float) MAX (0, child_x + col_width); + + childbox.y1 = (float) child_y; + childbox.y2 = (float) MAX (0, child_y + row_height); + + if (priv->use_animations) + { + clutter_actor_save_easing_state (child); + clutter_actor_set_easing_mode (child, priv->easing_mode); + clutter_actor_set_easing_duration (child, priv->easing_duration); + } + + if (clutter_actor_needs_expand (child, CLUTTER_ORIENTATION_HORIZONTAL) || + clutter_actor_needs_expand (child, CLUTTER_ORIENTATION_VERTICAL)) + clutter_actor_allocate (child, &childbox, flags); + else + clutter_actor_allocate_align_fill (child, &childbox, + x_align, y_align, + x_fill, y_fill, + flags); + + if (priv->use_animations) + clutter_actor_restore_easing_state (child); + } +} + +static void +clutter_table_layout_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterTableLayout *self = CLUTTER_TABLE_LAYOUT (gobject); + + switch (prop_id) + { + case PROP_COLUMN_SPACING: + clutter_table_layout_set_column_spacing (self, g_value_get_uint (value)); + break; + + case PROP_ROW_SPACING: + clutter_table_layout_set_row_spacing (self, g_value_get_uint (value)); + break; + + case PROP_USE_ANIMATIONS: + clutter_table_layout_set_use_animations (self, g_value_get_boolean (value)); + break; + + case PROP_EASING_MODE: + clutter_table_layout_set_easing_mode (self, g_value_get_ulong (value)); + break; + + case PROP_EASING_DURATION: + clutter_table_layout_set_easing_duration (self, g_value_get_uint (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_table_layout_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterTableLayoutPrivate *priv = CLUTTER_TABLE_LAYOUT (gobject)->priv; + + switch (prop_id) + { + case PROP_ROW_SPACING: + g_value_set_uint (value, priv->row_spacing); + break; + + case PROP_COLUMN_SPACING: + g_value_set_uint (value, priv->col_spacing); + break; + + case PROP_USE_ANIMATIONS: + g_value_set_boolean (value, priv->use_animations); + break; + + case PROP_EASING_MODE: + g_value_set_ulong (value, priv->easing_mode); + break; + + case PROP_EASING_DURATION: + g_value_set_uint (value, priv->easing_duration); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_table_layout_finalize (GObject *gobject) +{ + ClutterTableLayoutPrivate *priv = CLUTTER_TABLE_LAYOUT (gobject)->priv; + + g_array_free (priv->columns, TRUE); + g_array_free (priv->rows, TRUE); + + G_OBJECT_CLASS (clutter_table_layout_parent_class)->finalize (gobject); +} + +static void +clutter_table_layout_class_init (ClutterTableLayoutClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterLayoutManagerClass *layout_class; + GParamSpec *pspec; + + layout_class = CLUTTER_LAYOUT_MANAGER_CLASS (klass); + + gobject_class->set_property = clutter_table_layout_set_property; + gobject_class->get_property = clutter_table_layout_get_property; + gobject_class->finalize = clutter_table_layout_finalize; + + layout_class->get_preferred_width = + clutter_table_layout_get_preferred_width; + layout_class->get_preferred_height = + clutter_table_layout_get_preferred_height; + layout_class->allocate = clutter_table_layout_allocate; + layout_class->set_container = clutter_table_layout_set_container; + layout_class->get_child_meta_type = + clutter_table_layout_get_child_meta_type; + + /** + * ClutterTableLayout:column-spacing: + * + * The spacing between columns of the #ClutterTableLayout, in pixels + * + * Since: 1.4 + * + * Deprecated: 1.18: Use #ClutterGridLayout:column-spacing instead + */ + pspec = g_param_spec_uint ("column-spacing", + P_("Column Spacing"), + P_("Spacing between columns"), + 0, G_MAXUINT, 0, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_COLUMN_SPACING, pspec); + + /** + * ClutterTableLayout:row-spacing: + * + * The spacing between rows of the #ClutterTableLayout, in pixels + * + * Since: 1.4 + * + * Deprecated: 1.18: Use #ClutterGridLayout:row-spacing instead + */ + pspec = g_param_spec_uint ("row-spacing", + P_("Row Spacing"), + P_("Spacing between rows"), + 0, G_MAXUINT, 0, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_ROW_SPACING, pspec); + + /** + * ClutterTableLayout:use-animations: + * + * Whether the #ClutterTableLayout should animate changes in the + * layout properties. + * + * By default, #ClutterTableLayout will honour the easing state of + * the children when allocating them. Setting this property to + * %TRUE will override the easing state with the layout manager's + * #ClutterTableLayout:easing-mode and #ClutterTableLayout:easing-duration + * properties. + * + * Since: 1.4 + * + * Deprecated: 1.12: #ClutterTableLayout will honour the easing state + * of the children when allocating them + */ + pspec = g_param_spec_boolean ("use-animations", + P_("Use Animations"), + P_("Whether layout changes should be animated"), + FALSE, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_USE_ANIMATIONS, pspec); + + /** + * ClutterTableLayout:easing-mode: + * + * The easing mode for the animations, in case + * #ClutterTableLayout:use-animations is set to %TRUE. + * + * The easing mode has the same semantics of #ClutterAnimation:mode: it can + * either be a value from the #ClutterAnimationMode enumeration, like + * %CLUTTER_EASE_OUT_CUBIC, or a logical id as returned by + * clutter_alpha_register_func(). + * + * The default value is %CLUTTER_EASE_OUT_CUBIC. + * + * Since: 1.4 + * + * Deprecated: 1.12: #ClutterTableLayout will honour the easing state + * of the children when allocating them + */ + pspec = g_param_spec_ulong ("easing-mode", + P_("Easing Mode"), + P_("The easing mode of the animations"), + 0, G_MAXULONG, + CLUTTER_EASE_OUT_CUBIC, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_EASING_MODE, pspec); + + /** + * ClutterTableLayout:easing-duration: + * + * The duration of the animations, in case #ClutterTableLayout:use-animations + * is set to %TRUE. + * + * The duration is expressed in milliseconds. + * + * Since: 1.4 + * + * Deprecated: 1.12: #ClutterTableLayout will honour the easing state + * of the children when allocating them + */ + pspec = g_param_spec_uint ("easing-duration", + P_("Easing Duration"), + P_("The duration of the animations"), + 0, G_MAXUINT, + 500, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_EASING_DURATION, pspec); +} + +static void +clutter_table_layout_init (ClutterTableLayout *layout) +{ + ClutterTableLayoutPrivate *priv; + + layout->priv = priv = clutter_table_layout_get_instance_private (layout); + + priv->row_spacing = 0; + priv->col_spacing = 0; + + priv->use_animations = FALSE; + priv->easing_mode = CLUTTER_EASE_OUT_CUBIC; + priv->easing_duration = 500; + + priv->columns = g_array_new (FALSE, TRUE, sizeof (DimensionData)); + priv->rows = g_array_new (FALSE, TRUE, sizeof (DimensionData)); +} + +/** + * clutter_table_layout_new: + * + * Creates a new #ClutterTableLayout layout manager + * + * Return value: the newly created #ClutterTableLayout + * + * Since: 1.4 + * + * Deprecated: 1.18: Use #ClutterGridLayout instead + */ +ClutterLayoutManager * +clutter_table_layout_new (void) +{ + return g_object_new (CLUTTER_TYPE_TABLE_LAYOUT, NULL); +} + +/** + * clutter_table_layout_set_column_spacing: + * @layout: a #ClutterTableLayout + * @spacing: the spacing between columns of the layout, in pixels + * + * Sets the spacing between columns of @layout + * + * Since: 1.4 + * + * Deprecated: 1.18: Use #ClutterGridLayout:column-spacing instead + */ +void +clutter_table_layout_set_column_spacing (ClutterTableLayout *layout, + guint spacing) +{ + ClutterTableLayoutPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout)); + + priv = layout->priv; + + if (priv->col_spacing != spacing) + { + ClutterLayoutManager *manager; + + priv->col_spacing = spacing; + + manager = CLUTTER_LAYOUT_MANAGER (layout); + clutter_layout_manager_layout_changed (manager); + + g_object_notify (G_OBJECT (layout), "column-spacing"); + } +} + +/** + * clutter_table_layout_get_column_spacing: + * @layout: a #ClutterTableLayout + * + * Retrieves the spacing set using clutter_table_layout_set_column_spacing() + * + * Return value: the spacing between columns of the #ClutterTableLayout + * + * Since: 1.4 + * + * Deprecated: 1.18: Use #ClutterGridLayout:column-spacing + */ +guint +clutter_table_layout_get_column_spacing (ClutterTableLayout *layout) +{ + g_return_val_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout), 0); + + return layout->priv->col_spacing; +} + +/** + * clutter_table_layout_set_row_spacing: + * @layout: a #ClutterTableLayout + * @spacing: the spacing between rows of the layout, in pixels + * + * Sets the spacing between rows of @layout + * + * Since: 1.4 + * + * Deprecated: 1.18: Use #ClutterGridLayout:row-spacing instead + */ +void +clutter_table_layout_set_row_spacing (ClutterTableLayout *layout, + guint spacing) +{ + ClutterTableLayoutPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout)); + + priv = layout->priv; + + if (priv->row_spacing != spacing) + { + ClutterLayoutManager *manager; + + priv->row_spacing = spacing; + + manager = CLUTTER_LAYOUT_MANAGER (layout); + clutter_layout_manager_layout_changed (manager); + + g_object_notify (G_OBJECT (layout), "row-spacing"); + } +} + +/** + * clutter_table_layout_get_row_spacing: + * @layout: a #ClutterTableLayout + * + * Retrieves the spacing set using clutter_table_layout_set_row_spacing() + * + * Return value: the spacing between rows of the #ClutterTableLayout + * + * Since: 1.4 + * + * Deprecated: 1.18: Use #ClutterGridLayout:row-spacing instead + */ +guint +clutter_table_layout_get_row_spacing (ClutterTableLayout *layout) +{ + g_return_val_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout), 0); + + return layout->priv->row_spacing; +} + +/** + * clutter_table_layout_pack: + * @layout: a #ClutterTableLayout + * @actor: a #ClutterActor + * @column: the column the @actor should be put, or -1 to append + * @row: the row the @actor should be put, or -1 to append + * + * Packs @actor inside the #ClutterContainer associated to @layout + * at the given row and column. + * + * Since: 1.4 + * + * Deprecated: 1.18: Use clutter_grid_layout_attach_child() instead + */ +void +clutter_table_layout_pack (ClutterTableLayout *layout, + ClutterActor *actor, + gint column, + gint row) +{ + ClutterTableLayoutPrivate *priv; + ClutterLayoutManager *manager; + ClutterLayoutMeta *meta; + + g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + priv = layout->priv; + + if (priv->container == NULL) + { + g_warning ("The layout of type '%s' must be associated to " + "a ClutterContainer before adding children", + G_OBJECT_TYPE_NAME (layout)); + return; + } + + update_row_col (CLUTTER_TABLE_LAYOUT (layout), priv->container); + + clutter_container_add_actor (priv->container, actor); + + manager = CLUTTER_LAYOUT_MANAGER (layout); + meta = clutter_layout_manager_get_child_meta (manager, + priv->container, + actor); + g_assert (CLUTTER_IS_TABLE_CHILD (meta)); + + if (row < 0) + row = priv->n_rows; + + if (column < 0) + column = priv->n_cols; + + table_child_set_position (CLUTTER_TABLE_CHILD (meta), column, row); +} + +/** + * clutter_table_layout_set_span: + * @layout: a #ClutterTableLayout + * @actor: a #ClutterActor child of @layout + * @column_span: Column span for @actor + * @row_span: Row span for @actor + * + * Sets the row and column span for @actor + * inside @layout + * + * Since: 1.4 + * + * Deprecated: 1.18: Use the `width` and `height` layout properties + * of #ClutterGridLayout instead + */ +void +clutter_table_layout_set_span (ClutterTableLayout *layout, + ClutterActor *actor, + gint column_span, + gint row_span) +{ + ClutterTableLayoutPrivate *priv; + ClutterLayoutManager *manager; + ClutterLayoutMeta *meta; + + g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + priv = layout->priv; + + if (priv->container == NULL) + { + g_warning ("The layout of type '%s' must be associated to " + "a ClutterContainer before querying layout " + "properties", + G_OBJECT_TYPE_NAME (layout)); + return; + } + + manager = CLUTTER_LAYOUT_MANAGER (layout); + meta = clutter_layout_manager_get_child_meta (manager, + priv->container, + actor); + if (meta == NULL) + { + g_warning ("No layout meta found for the child of type '%s' " + "inside the layout manager of type '%s'", + G_OBJECT_TYPE_NAME (actor), + G_OBJECT_TYPE_NAME (manager)); + return; + } + + g_assert (CLUTTER_IS_TABLE_CHILD (meta)); + + table_child_set_span (CLUTTER_TABLE_CHILD (meta), column_span, row_span); +} + +/** + * clutter_table_layout_get_span: + * @layout: a #ClutterTableLayout + * @actor: a #ClutterActor child of @layout + * @column_span: (out): return location for the col span + * @row_span: (out): return location for the row span + * + * Retrieves the row and column span for @actor as set using + * clutter_table_layout_pack() or clutter_table_layout_set_span() + * + * Since: 1.4 + * + * Deprecated: 1.18: Use the `width` and `height` layout properties + * of #ClutterGridLayout instead + */ +void +clutter_table_layout_get_span (ClutterTableLayout *layout, + ClutterActor *actor, + gint *column_span, + gint *row_span) +{ + ClutterTableLayoutPrivate *priv; + ClutterLayoutManager *manager; + ClutterLayoutMeta *meta; + + g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + priv = layout->priv; + + if (priv->container == NULL) + { + g_warning ("The layout of type '%s' must be associated to " + "a ClutterContainer before querying layout " + "properties", + G_OBJECT_TYPE_NAME (layout)); + return; + } + + manager = CLUTTER_LAYOUT_MANAGER (layout); + meta = clutter_layout_manager_get_child_meta (manager, + priv->container, + actor); + if (meta == NULL) + { + g_warning ("No layout meta found for the child of type '%s' " + "inside the layout manager of type '%s'", + G_OBJECT_TYPE_NAME (actor), + G_OBJECT_TYPE_NAME (manager)); + return; + } + + g_assert (CLUTTER_IS_TABLE_CHILD (meta)); + + if (column_span) + *column_span = CLUTTER_TABLE_CHILD (meta)->col_span; + + if (row_span) + *row_span = CLUTTER_TABLE_CHILD (meta)->row_span; +} + +/** + * clutter_table_layout_set_alignment: + * @layout: a #ClutterTableLayout + * @actor: a #ClutterActor child of @layout + * @x_align: Horizontal alignment policy for @actor + * @y_align: Vertical alignment policy for @actor + * + * Sets the horizontal and vertical alignment policies for @actor + * inside @layout + * + * Since: 1.4 + * + * Deprecated: 1.12: Use clutter_actor_set_x_align() and + * clutter_actor_set_y_align() instead. + */ +void +clutter_table_layout_set_alignment (ClutterTableLayout *layout, + ClutterActor *actor, + ClutterTableAlignment x_align, + ClutterTableAlignment y_align) +{ + ClutterTableLayoutPrivate *priv; + ClutterLayoutManager *manager; + ClutterLayoutMeta *meta; + + g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + priv = layout->priv; + + if (priv->container == NULL) + { + g_warning ("The layout of type '%s' must be associated to " + "a ClutterContainer before querying layout " + "properties", + G_OBJECT_TYPE_NAME (layout)); + return; + } + + manager = CLUTTER_LAYOUT_MANAGER (layout); + meta = clutter_layout_manager_get_child_meta (manager, + priv->container, + actor); + if (meta == NULL) + { + g_warning ("No layout meta found for the child of type '%s' " + "inside the layout manager of type '%s'", + G_OBJECT_TYPE_NAME (actor), + G_OBJECT_TYPE_NAME (manager)); + return; + } + + g_assert (CLUTTER_IS_TABLE_CHILD (meta)); + + table_child_set_align (CLUTTER_TABLE_CHILD (meta), x_align, y_align); +} + +/** + * clutter_table_layout_get_alignment: + * @layout: a #ClutterTableLayout + * @actor: a #ClutterActor child of @layout + * @x_align: (out): return location for the horizontal alignment policy + * @y_align: (out): return location for the vertical alignment policy + * + * Retrieves the horizontal and vertical alignment policies for @actor + * as set using clutter_table_layout_pack() or + * clutter_table_layout_set_alignment(). + * + * Since: 1.4 + * + * Deprecated: 1.12: Use clutter_actor_get_x_align() and + * clutter_actor_get_y_align() instead. + */ +void +clutter_table_layout_get_alignment (ClutterTableLayout *layout, + ClutterActor *actor, + ClutterTableAlignment *x_align, + ClutterTableAlignment *y_align) +{ + ClutterTableLayoutPrivate *priv; + ClutterLayoutManager *manager; + ClutterLayoutMeta *meta; + + g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + priv = layout->priv; + + if (priv->container == NULL) + { + g_warning ("The layout of type '%s' must be associated to " + "a ClutterContainer before querying layout " + "properties", + G_OBJECT_TYPE_NAME (layout)); + return; + } + + manager = CLUTTER_LAYOUT_MANAGER (layout); + meta = clutter_layout_manager_get_child_meta (manager, + priv->container, + actor); + if (meta == NULL) + { + g_warning ("No layout meta found for the child of type '%s' " + "inside the layout manager of type '%s'", + G_OBJECT_TYPE_NAME (actor), + G_OBJECT_TYPE_NAME (manager)); + return; + } + + g_assert (CLUTTER_IS_TABLE_CHILD (meta)); + + if (x_align) + *x_align = CLUTTER_TABLE_CHILD (meta)->x_align; + + if (y_align) + *y_align = CLUTTER_TABLE_CHILD (meta)->y_align; +} + +/** + * clutter_table_layout_set_fill: + * @layout: a #ClutterTableLayout + * @actor: a #ClutterActor child of @layout + * @x_fill: whether @actor should fill horizontally the allocated space + * @y_fill: whether @actor should fill vertically the allocated space + * + * Sets the horizontal and vertical fill policies for @actor + * inside @layout + * + * Since: 1.4 + * + * Deprecated: 1.12: Use clutter_actor_set_x_align() and + * clutter_actor_set_y_align() instead. + */ +void +clutter_table_layout_set_fill (ClutterTableLayout *layout, + ClutterActor *actor, + gboolean x_fill, + gboolean y_fill) +{ + ClutterTableLayoutPrivate *priv; + ClutterLayoutManager *manager; + ClutterLayoutMeta *meta; + + g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + priv = layout->priv; + + if (priv->container == NULL) + { + g_warning ("The layout of type '%s' must be associated to " + "a ClutterContainer before querying layout " + "properties", + G_OBJECT_TYPE_NAME (layout)); + return; + } + + manager = CLUTTER_LAYOUT_MANAGER (layout); + meta = clutter_layout_manager_get_child_meta (manager, + priv->container, + actor); + if (meta == NULL) + { + g_warning ("No layout meta found for the child of type '%s' " + "inside the layout manager of type '%s'", + G_OBJECT_TYPE_NAME (actor), + G_OBJECT_TYPE_NAME (manager)); + return; + } + + g_assert (CLUTTER_IS_TABLE_CHILD (meta)); + + table_child_set_fill (CLUTTER_TABLE_CHILD (meta), x_fill, y_fill); +} + +/** + * clutter_table_layout_get_fill: + * @layout: a #ClutterTableLayout + * @actor: a #ClutterActor child of @layout + * @x_fill: (out): return location for the horizontal fill policy + * @y_fill: (out): return location for the vertical fill policy + * + * Retrieves the horizontal and vertical fill policies for @actor + * as set using clutter_table_layout_pack() or clutter_table_layout_set_fill() + * + * Since: 1.4 + * + * Deprecated: 1.12: Use clutter_actor_get_x_align() and + * clutter_actor_get_y_align() instead. + */ +void +clutter_table_layout_get_fill (ClutterTableLayout *layout, + ClutterActor *actor, + gboolean *x_fill, + gboolean *y_fill) +{ + ClutterTableLayoutPrivate *priv; + ClutterLayoutManager *manager; + ClutterLayoutMeta *meta; + + g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + priv = layout->priv; + + if (priv->container == NULL) + { + g_warning ("The layout of type '%s' must be associated to " + "a ClutterContainer before querying layout " + "properties", + G_OBJECT_TYPE_NAME (layout)); + return; + } + + manager = CLUTTER_LAYOUT_MANAGER (layout); + meta = clutter_layout_manager_get_child_meta (manager, + priv->container, + actor); + if (meta == NULL) + { + g_warning ("No layout meta found for the child of type '%s' " + "inside the layout manager of type '%s'", + G_OBJECT_TYPE_NAME (actor), + G_OBJECT_TYPE_NAME (manager)); + return; + } + + g_assert (CLUTTER_IS_TABLE_CHILD (meta)); + + if (x_fill) + *x_fill = CLUTTER_TABLE_CHILD (meta)->x_fill; + + if (y_fill) + *y_fill = CLUTTER_TABLE_CHILD (meta)->y_fill; +} + + +/** + * clutter_table_layout_set_expand: + * @layout: a #ClutterTableLayout + * @actor: a #ClutterActor child of @layout + * @x_expand: whether @actor should allocate extra space horizontally + * @y_expand: whether @actor should allocate extra space vertically + * + * Sets the horizontal and vertical expand policies for @actor + * inside @layout + * + * Since: 1.4 + * + * Deprecated: 1.12: Use clutter_actor_set_x_expand() or + * clutter_actor_set_y_expand() instead. + */ +void +clutter_table_layout_set_expand (ClutterTableLayout *layout, + ClutterActor *actor, + gboolean x_expand, + gboolean y_expand) +{ + ClutterTableLayoutPrivate *priv; + ClutterLayoutManager *manager; + ClutterLayoutMeta *meta; + + g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + priv = layout->priv; + + if (priv->container == NULL) + { + g_warning ("The layout of type '%s' must be associated to " + "a ClutterContainer before querying layout " + "properties", + G_OBJECT_TYPE_NAME (layout)); + return; + } + + manager = CLUTTER_LAYOUT_MANAGER (layout); + meta = clutter_layout_manager_get_child_meta (manager, + priv->container, + actor); + if (meta == NULL) + { + g_warning ("No layout meta found for the child of type '%s' " + "inside the layout manager of type '%s'", + G_OBJECT_TYPE_NAME (actor), + G_OBJECT_TYPE_NAME (manager)); + return; + } + + g_assert (CLUTTER_IS_TABLE_CHILD (meta)); + + table_child_set_expand (CLUTTER_TABLE_CHILD (meta), x_expand, y_expand); +} + +/** + * clutter_table_layout_get_expand: + * @layout: a #ClutterTableLayout + * @actor: a #ClutterActor child of @layout + * @x_expand: (out): return location for the horizontal expand policy + * @y_expand: (out): return location for the vertical expand policy + * + * Retrieves the horizontal and vertical expand policies for @actor + * as set using clutter_table_layout_pack() or clutter_table_layout_set_expand() + * + * Since: 1.4 + * + * Deprecated: 1.12: Use clutter_actor_get_x_expand() and + * clutter_actor_get_y_expand() instead. + */ +void +clutter_table_layout_get_expand (ClutterTableLayout *layout, + ClutterActor *actor, + gboolean *x_expand, + gboolean *y_expand) +{ + ClutterTableLayoutPrivate *priv; + ClutterLayoutManager *manager; + ClutterLayoutMeta *meta; + + g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout)); + g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + + priv = layout->priv; + + if (priv->container == NULL) + { + g_warning ("The layout of type '%s' must be associated to " + "a ClutterContainer before querying layout " + "properties", + G_OBJECT_TYPE_NAME (layout)); + return; + } + + manager = CLUTTER_LAYOUT_MANAGER (layout); + meta = clutter_layout_manager_get_child_meta (manager, + priv->container, + actor); + if (meta == NULL) + { + g_warning ("No layout meta found for the child of type '%s' " + "inside the layout manager of type '%s'", + G_OBJECT_TYPE_NAME (actor), + G_OBJECT_TYPE_NAME (manager)); + return; + } + + g_assert (CLUTTER_IS_TABLE_CHILD (meta)); + + if (x_expand) + *x_expand = CLUTTER_TABLE_CHILD (meta)->x_expand; + + if (y_expand) + *y_expand = CLUTTER_TABLE_CHILD (meta)->y_expand; +} + +/** + * clutter_table_layout_set_use_animations: + * @layout: a #ClutterTableLayout + * @animate: %TRUE if the @layout should use animations + * + * Sets whether @layout should animate changes in the layout properties + * + * The duration of the animations is controlled by + * clutter_table_layout_set_easing_duration(); the easing mode to be used + * by the animations is controlled by clutter_table_layout_set_easing_mode() + * + * Since: 1.4 + * + * Deprecated: 1.12: #ClutterTableLayout will honour the easing state + * of the children when allocating them. See clutter_actor_set_easing_mode() + * and clutter_actor_set_easing_duration(). + */ +void +clutter_table_layout_set_use_animations (ClutterTableLayout *layout, + gboolean animate) +{ + ClutterTableLayoutPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout)); + + priv = layout->priv; + + animate = !!animate; + if (priv->use_animations != animate) + { + priv->use_animations = animate; + + g_object_notify (G_OBJECT (layout), "use-animations"); + } +} + +/** + * clutter_table_layout_get_use_animations: + * @layout: a #ClutterTableLayout + * + * Retrieves whether @layout should animate changes in the layout properties + * + * Since clutter_table_layout_set_use_animations() + * + * Return value: %TRUE if the animations should be used, %FALSE otherwise + * + * Since: 1.4 + * + * Deprecated: 1.12: #ClutterTableLayout will honour the easing state + * of the children when allocating them. See clutter_actor_set_easing_mode() + * and clutter_actor_set_easing_duration(). + */ +gboolean +clutter_table_layout_get_use_animations (ClutterTableLayout *layout) +{ + g_return_val_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout), FALSE); + + return layout->priv->use_animations; +} + +/** + * clutter_table_layout_set_easing_mode: + * @layout: a #ClutterTableLayout + * @mode: an easing mode, either from #ClutterAnimationMode or a logical id + * from clutter_alpha_register_func() + * + * Sets the easing mode to be used by @layout when animating changes in layout + * properties + * + * Use clutter_table_layout_set_use_animations() to enable and disable the + * animations + * + * Since: 1.4 + * + * Deprecated: 1.12: #ClutterTableLayout will honour the easing state + * of the children when allocating them. See clutter_actor_set_easing_mode() + * and clutter_actor_set_easing_duration(). + */ +void +clutter_table_layout_set_easing_mode (ClutterTableLayout *layout, + gulong mode) +{ + ClutterTableLayoutPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout)); + + priv = layout->priv; + + if (priv->easing_mode != mode) + { + priv->easing_mode = mode; + + g_object_notify (G_OBJECT (layout), "easing-mode"); + } +} + +/** + * clutter_table_layout_get_easing_mode: + * @layout: a #ClutterTableLayout + * + * Retrieves the easing mode set using clutter_table_layout_set_easing_mode() + * + * Return value: an easing mode + * + * Since: 1.4 + * + * Deprecated: 1.12: #ClutterTableLayout will honour the easing state + * of the children when allocating them. See clutter_actor_set_easing_mode() + * and clutter_actor_set_easing_duration(). + */ +gulong +clutter_table_layout_get_easing_mode (ClutterTableLayout *layout) +{ + g_return_val_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout), + CLUTTER_EASE_OUT_CUBIC); + + return layout->priv->easing_mode; +} + +/** + * clutter_table_layout_set_easing_duration: + * @layout: a #ClutterTableLayout + * @msecs: the duration of the animations, in milliseconds + * + * Sets the duration of the animations used by @layout when animating changes + * in the layout properties + * + * Use clutter_table_layout_set_use_animations() to enable and disable the + * animations + * + * Since: 1.4 + * + * Deprecated: 1.12: #ClutterTableLayout will honour the easing state + * of the children when allocating them. See clutter_actor_set_easing_mode() + * and clutter_actor_set_easing_duration(). + */ +void +clutter_table_layout_set_easing_duration (ClutterTableLayout *layout, + guint msecs) +{ + ClutterTableLayoutPrivate *priv; + + g_return_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout)); + + priv = layout->priv; + + if (priv->easing_duration != msecs) + { + priv->easing_duration = msecs; + + g_object_notify (G_OBJECT (layout), "easing-duration"); + } +} + +/** + * clutter_table_layout_get_easing_duration: + * @layout: a #ClutterTableLayout + * + * Retrieves the duration set using clutter_table_layout_set_easing_duration() + * + * Return value: the duration of the animations, in milliseconds + * + * Since: 1.4 + * + * Deprecated: 1.12: #ClutterTableLayout will honour the easing state + * of the children when allocating them. See clutter_actor_set_easing_mode() + * and clutter_actor_set_easing_duration(). + */ +guint +clutter_table_layout_get_easing_duration (ClutterTableLayout *layout) +{ + g_return_val_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout), 500); + + return layout->priv->easing_duration; +} + + +/** + * clutter_table_layout_get_row_count: + * @layout: A #ClutterTableLayout + * + * Retrieve the current number rows in the @layout + * + * Returns: the number of rows + * + * Since: 1.4 + * + * Deprecated: 1.18: No direct replacement is available + */ +gint +clutter_table_layout_get_row_count (ClutterTableLayout *layout) +{ + g_return_val_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout), -1); + + update_row_col (layout, layout->priv->container); + return CLUTTER_TABLE_LAYOUT (layout)->priv->n_rows; +} + +/** + * clutter_table_layout_get_column_count: + * @layout: A #ClutterTableLayout + * + * Retrieve the current number of columns in @layout + * + * Returns: the number of columns + * + * Since: 1.4 + * + * Deprecated: 1.18: No direct replacement is available + */ +gint +clutter_table_layout_get_column_count (ClutterTableLayout *layout) +{ + g_return_val_if_fail (CLUTTER_IS_TABLE_LAYOUT (layout), -1); + + update_row_col (layout, layout->priv->container); + return CLUTTER_TABLE_LAYOUT (layout)->priv->n_cols; +} diff --git a/clutter/clutter/deprecated/clutter-table-layout.h b/clutter/clutter/deprecated/clutter-table-layout.h new file mode 100644 index 0000000..dffbfb7 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-table-layout.h @@ -0,0 +1,172 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Jose Dapena Paz + * + * Based on the MX MxTable actor by: + * Thomas Wood + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_TABLE_LAYOUT_H__ +#define __CLUTTER_TABLE_LAYOUT_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_TABLE_LAYOUT (clutter_table_layout_get_type ()) +#define CLUTTER_TABLE_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_TABLE_LAYOUT, ClutterTableLayout)) +#define CLUTTER_IS_TABLE_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_TABLE_LAYOUT)) +#define CLUTTER_TABLE_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_TABLE_LAYOUT, ClutterTableLayoutClass)) +#define CLUTTER_IS_TABLE_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_TABLE_LAYOUT)) +#define CLUTTER_TABLE_LAYOUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_TABLE_LAYOUT, ClutterTableLayoutClass)) + +typedef struct _ClutterTableLayout ClutterTableLayout; +typedef struct _ClutterTableLayoutPrivate ClutterTableLayoutPrivate; +typedef struct _ClutterTableLayoutClass ClutterTableLayoutClass; + +/** + * ClutterTableLayout: + * + * The #ClutterTableLayout structure contains only private data + * and should be accessed using the provided API + * + * Since: 1.4 + * + * Deprecated: 1.18: Use #ClutterGridLayout instead + */ +struct _ClutterTableLayout +{ + /*< private >*/ + ClutterLayoutManager parent_instance; + + ClutterTableLayoutPrivate *priv; +}; + +/** + * ClutterTableLayoutClass: + * + * The #ClutterTableLayoutClass structure contains only private + * data and should be accessed using the provided API + * + * Since: 1.4 + * + * Deprecated: 1.18: Use #ClutterGridLayout instead + */ +struct _ClutterTableLayoutClass +{ + /*< private >*/ + ClutterLayoutManagerClass parent_class; +}; + +CLUTTER_DEPRECATED_IN_1_18_FOR (clutter_grid_layout_get_type) +GType clutter_table_layout_get_type (void) G_GNUC_CONST; + +CLUTTER_DEPRECATED_IN_1_18_FOR (clutter_grid_layout_new) +ClutterLayoutManager *clutter_table_layout_new (void); + +CLUTTER_DEPRECATED_IN_1_18_FOR (clutter_grid_layout_attach) +void clutter_table_layout_pack (ClutterTableLayout *layout, + ClutterActor *actor, + gint column, + gint row); + +CLUTTER_DEPRECATED_IN_1_18_FOR (clutter_grid_layout_set_column_spacing) +void clutter_table_layout_set_column_spacing (ClutterTableLayout *layout, + guint spacing); +CLUTTER_DEPRECATED_IN_1_18_FOR (clutter_grid_layout_set_row_spacing) +void clutter_table_layout_set_row_spacing (ClutterTableLayout *layout, + guint spacing); +CLUTTER_DEPRECATED_IN_1_18_FOR (clutter_grid_layout_get_column_spacing) +guint clutter_table_layout_get_column_spacing (ClutterTableLayout *layout); +CLUTTER_DEPRECATED_IN_1_18_FOR (clutter_grid_layout_get_row_spacing) +guint clutter_table_layout_get_row_spacing (ClutterTableLayout *layout); + +CLUTTER_DEPRECATED_IN_1_18 +void clutter_table_layout_set_span (ClutterTableLayout *layout, + ClutterActor *actor, + gint column_span, + gint row_span); +CLUTTER_DEPRECATED_IN_1_18 +void clutter_table_layout_get_span (ClutterTableLayout *layout, + ClutterActor *actor, + gint *column_span, + gint *row_span); + +CLUTTER_DEPRECATED_IN_1_12 +void clutter_table_layout_set_alignment (ClutterTableLayout *layout, + ClutterActor *actor, + ClutterTableAlignment x_align, + ClutterTableAlignment y_align); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_table_layout_get_alignment (ClutterTableLayout *layout, + ClutterActor *actor, + ClutterTableAlignment *x_align, + ClutterTableAlignment *y_align); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_table_layout_set_fill (ClutterTableLayout *layout, + ClutterActor *actor, + gboolean x_fill, + gboolean y_fill); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_table_layout_get_fill (ClutterTableLayout *layout, + ClutterActor *actor, + gboolean *x_fill, + gboolean *y_fill); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_table_layout_set_expand (ClutterTableLayout *layout, + ClutterActor *actor, + gboolean x_expand, + gboolean y_expand); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_table_layout_get_expand (ClutterTableLayout *layout, + ClutterActor *actor, + gboolean *x_expand, + gboolean *y_expand); + +CLUTTER_DEPRECATED_IN_1_18 +gint clutter_table_layout_get_row_count (ClutterTableLayout *layout); +CLUTTER_DEPRECATED_IN_1_18 +gint clutter_table_layout_get_column_count (ClutterTableLayout *layout); + +CLUTTER_DEPRECATED_IN_1_12 +void clutter_table_layout_set_use_animations (ClutterTableLayout *layout, + gboolean animate); +CLUTTER_DEPRECATED_IN_1_12 +gboolean clutter_table_layout_get_use_animations (ClutterTableLayout *layout); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_table_layout_set_easing_mode (ClutterTableLayout *layout, + gulong mode); +CLUTTER_DEPRECATED_IN_1_12 +gulong clutter_table_layout_get_easing_mode (ClutterTableLayout *layout); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_table_layout_set_easing_duration (ClutterTableLayout *layout, + guint msecs); +CLUTTER_DEPRECATED_IN_1_12 +guint clutter_table_layout_get_easing_duration (ClutterTableLayout *layout); + +G_END_DECLS + +#endif /* __CLUTTER_TABLE_LAYOUT_H__ */ diff --git a/clutter/clutter/deprecated/clutter-texture.c b/clutter/clutter/deprecated/clutter-texture.c new file mode 100644 index 0000000..ee57155 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-texture.c @@ -0,0 +1,3106 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +/** + * SECTION:clutter-texture + * @short_description: An actor for displaying and manipulating images. + * + * #ClutterTexture is a base class for displaying and manipulating pixel + * buffer type data. + * + * The clutter_texture_set_from_rgb_data() and + * clutter_texture_set_from_file() functions are used to copy image + * data into texture memory and subsequently realize the texture. + * + * Note: a ClutterTexture will scale its contents to fit the bounding + * box requested using clutter_actor_set_size(). To display an area of + * a texture without scaling, you should set the clip area using + * clutter_actor_set_clip(). + * + * The #ClutterTexture API is deprecated since Clutter 1.12. It is strongly + * recommended to use #ClutterImage instead. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +/* sadly, we are still using ClutterShader internally */ +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS + +#include + +#include "clutter-texture.h" + +#include "clutter-actor-private.h" +#include "clutter-color.h" +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-feature.h" +#include "clutter-main.h" +#include "clutter-marshal.h" +#include "clutter-private.h" +#include "clutter-scriptable.h" +#include "clutter-stage-private.h" +#include "clutter-backend.h" + +#include "deprecated/clutter-shader.h" +#include "deprecated/clutter-texture.h" +#include "deprecated/clutter-util.h" + +typedef struct _ClutterTextureAsyncData ClutterTextureAsyncData; + +struct _ClutterTexturePrivate +{ + gint image_width; + gint image_height; + + CoglPipeline *pipeline; + + ClutterActor *fbo_source; + CoglHandle fbo_handle; + + CoglPipeline *pick_pipeline; + + gchar *filename; + + ClutterTextureAsyncData *async_data; + + guint no_slice : 1; + guint sync_actor_size : 1; + guint repeat_x : 1; + guint repeat_y : 1; + guint keep_aspect_ratio : 1; + guint load_size_async : 1; + guint load_data_async : 1; + guint load_async_set : 1; /* used to make load_async possible */ + guint pick_with_alpha : 1; + guint pick_with_alpha_supported : 1; + guint seen_create_pick_pipeline_warning : 1; +}; + +#define ASYNC_STATE_LOCKED 1 +#define ASYNC_STATE_CANCELLED 2 +#define ASYNC_STATE_QUEUED 3 + +struct _ClutterTextureAsyncData +{ + /* The texture for which the data is being loaded */ + ClutterTexture *texture; + + gchar *load_filename; + CoglHandle load_bitmap; + + guint load_idle; + + GError *load_error; + + gint state; +}; + +static inline void +clutter_texture_async_data_lock (ClutterTextureAsyncData *data) +{ + g_bit_lock (&data->state, 0); +} + +static inline void +clutter_texture_async_data_unlock (ClutterTextureAsyncData *data) +{ + g_bit_unlock (&data->state, 0); +} + +enum +{ + PROP_0, + PROP_NO_SLICE, + PROP_MAX_TILE_WASTE, + PROP_SYNC_SIZE, + PROP_REPEAT_Y, + PROP_REPEAT_X, + PROP_FILTER_QUALITY, + PROP_COGL_TEXTURE, + PROP_COGL_MATERIAL, + PROP_FILENAME, + PROP_KEEP_ASPECT_RATIO, + PROP_LOAD_ASYNC, + PROP_LOAD_DATA_ASYNC, + PROP_PICK_WITH_ALPHA, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +enum +{ + SIZE_CHANGE, + PIXBUF_CHANGE, + LOAD_SUCCESS, + LOAD_FINISHED, + LAST_SIGNAL +}; + +static int texture_signals[LAST_SIGNAL] = { 0 }; + +static GThreadPool *async_thread_pool = NULL; +static guint repaint_upload_func = 0; +static GList *upload_list = NULL; +static GMutex upload_list_mutex; + +static CoglPipeline *texture_template_pipeline = NULL; + +static void +texture_fbo_free_resources (ClutterTexture *texture); + +static void clutter_scriptable_iface_init (ClutterScriptableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (ClutterTexture, + clutter_texture, + CLUTTER_TYPE_ACTOR, + G_ADD_PRIVATE (ClutterTexture) + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_SCRIPTABLE, + clutter_scriptable_iface_init)); + + +GQuark +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_PIPELINE_FILTER_NEAREST, COGL_PIPELINE_FILTER_NEAREST }, + + /* CLUTTER_TEXTURE_QUALITY_MEDIUM */ + { COGL_PIPELINE_FILTER_LINEAR, COGL_PIPELINE_FILTER_LINEAR }, + + /* CLUTTER_TEXTURE_QUALITY_HIGH */ + { COGL_PIPELINE_FILTER_LINEAR_MIPMAP_LINEAR, COGL_PIPELINE_FILTER_LINEAR } + }; + +static inline void +clutter_texture_quality_to_filters (ClutterTextureQuality quality, + gint *min_filter_p, + gint *mag_filter_p) +{ + g_return_if_fail (quality < G_N_ELEMENTS (clutter_texture_quality_filters)); + + if (min_filter_p) + *min_filter_p = clutter_texture_quality_filters[quality].min_filter; + + if (mag_filter_p) + *mag_filter_p = clutter_texture_quality_filters[quality].mag_filter; +} + +static void +texture_free_gl_resources (ClutterTexture *texture) +{ + ClutterTexturePrivate *priv = texture->priv; + + if (priv->pipeline != NULL) + { + /* 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_pipeline_set_layer_texture (priv->pipeline, 0, NULL); + } +} + +static void +clutter_texture_unrealize (ClutterActor *actor) +{ + ClutterTexture *texture; + ClutterTexturePrivate *priv; + + texture = CLUTTER_TEXTURE(actor); + priv = texture->priv; + + if (priv->pipeline == NULL) + return; + + if (priv->fbo_source != NULL) + { + /* Free up our fbo handle and texture resources, realize will recreate */ + cogl_object_unref (priv->fbo_handle); + priv->fbo_handle = NULL; + texture_free_gl_resources (texture); + return; + } + + CLUTTER_NOTE (TEXTURE, "Texture unrealized"); +} + +static void +clutter_texture_realize (ClutterActor *actor) +{ + ClutterTexture *texture; + ClutterTexturePrivate *priv; + + texture = CLUTTER_TEXTURE(actor); + priv = texture->priv; + + if (priv->fbo_source) + { + CoglTextureFlags flags = COGL_TEXTURE_NONE; + CoglHandle tex; + + /* Handle FBO's */ + + if (priv->no_slice) + flags |= COGL_TEXTURE_NO_SLICING; + + tex = cogl_texture_new_with_size (priv->image_width, + priv->image_height, + flags, + COGL_PIXEL_FORMAT_RGBA_8888_PRE); + + cogl_pipeline_set_layer_texture (priv->pipeline, 0, tex); + + priv->fbo_handle = cogl_offscreen_new_to_texture (tex); + + /* The pipeline now has a reference to the texture so it will + stick around */ + cogl_object_unref (tex); + + if (priv->fbo_handle == NULL) + { + g_warning ("%s: Offscreen texture creation failed", G_STRLOC); + CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED); + return; + } + + clutter_actor_set_size (actor, priv->image_width, priv->image_height); + + return; + } + + /* If the texture is not a FBO, then realization is a no-op but we + * still want to be in REALIZED state to maintain invariants. + * ClutterTexture doesn't need to be realized to have a Cogl texture + * because Clutter assumes that a GL context is always current so + * there is no need to wait to realization time to create the + * texture. Although this is slightly odd it would be wasteful to + * redundantly store a copy of the texture data in local memory just + * so that we can make a texture during realize. + */ + + CLUTTER_NOTE (TEXTURE, "Texture realized"); +} + +static void +clutter_texture_get_preferred_width (ClutterActor *self, + gfloat for_height, + gfloat *min_width_p, + gfloat *natural_width_p) +{ + ClutterTexture *texture = CLUTTER_TEXTURE (self); + ClutterTexturePrivate *priv = texture->priv; + + /* Min request is always 0 since we can scale down or clip */ + if (min_width_p) + *min_width_p = 0; + + if (priv->sync_actor_size) + { + if (natural_width_p) + { + if (!priv->keep_aspect_ratio || + for_height < 0 || + priv->image_height <= 0) + { + *natural_width_p = priv->image_width; + } + else + { + /* Set the natural width so as to preserve the aspect ratio */ + gfloat ratio = (gfloat) priv->image_width + / (gfloat) priv->image_height; + + *natural_width_p = ratio * for_height; + } + } + } + else + { + if (natural_width_p) + *natural_width_p = 0; + } +} + +static void +clutter_texture_get_preferred_height (ClutterActor *self, + gfloat for_width, + gfloat *min_height_p, + gfloat *natural_height_p) +{ + ClutterTexture *texture = CLUTTER_TEXTURE (self); + ClutterTexturePrivate *priv = texture->priv; + + /* Min request is always 0 since we can scale down or clip */ + if (min_height_p) + *min_height_p = 0; + + if (priv->sync_actor_size) + { + if (natural_height_p) + { + if (!priv->keep_aspect_ratio || + for_width < 0 || + priv->image_width <= 0) + { + *natural_height_p = priv->image_height; + } + else + { + /* Set the natural height so as to preserve the aspect ratio */ + gfloat ratio = (gfloat) priv->image_height + / (gfloat) priv->image_width; + + *natural_height_p = ratio * for_width; + } + } + } + else + { + if (natural_height_p) + *natural_height_p = 0; + } +} + +static void +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, + 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, flags); +} + +static gboolean +clutter_texture_has_overlaps (ClutterActor *self) +{ + /* Textures never need an offscreen redirect because there are never + any overlapping primitives */ + return FALSE; +} + +static void +set_viewport_with_buffer_under_fbo_source (ClutterActor *fbo_source, + int viewport_width, + int viewport_height) +{ + ClutterActorBox box = { 0, }; + float x_offset, y_offset; + + if (clutter_actor_get_paint_box (fbo_source, &box)) + clutter_actor_box_get_origin (&box, &x_offset, &y_offset); + else + { + /* As a fallback when the paint box can't be determined we use + * the transformed allocation to come up with an offset instead. + * + * FIXME: when we don't have a paint box we should instead be + * falling back to a stage sized fbo with an offset of (0,0) + */ + + ClutterVertex verts[4]; + float x_min = G_MAXFLOAT, y_min = G_MAXFLOAT; + int i; + + /* Get the actors allocation transformed into screen coordinates. + * + * XXX: Note: this may not be a bounding box for the actor, since an + * actor with depth may escape the box due to its perspective + * projection. */ + clutter_actor_get_abs_allocation_vertices (fbo_source, verts); + + for (i = 0; i < G_N_ELEMENTS (verts); ++i) + { + if (verts[i].x < x_min) + x_min = verts[i].x; + if (verts[i].y < y_min) + y_min = verts[i].y; + } + + /* XXX: It's not good enough to round by simply truncating the fraction here + * via a cast, as it results in offscreen rendering being offset by 1 pixel + * in many cases... */ +#define ROUND(x) ((x) >= 0 ? (long)((x) + 0.5) : (long)((x) - 0.5)) + + x_offset = ROUND (x_min); + y_offset = ROUND (y_min); + +#undef ROUND + } + + /* translate the viewport so that the source actor lands on the + * sub-region backed by the offscreen framebuffer... */ + cogl_set_viewport (-x_offset, -y_offset, viewport_width, viewport_height); +} + +static void +update_fbo (ClutterActor *self) +{ + ClutterTexture *texture = CLUTTER_TEXTURE (self); + ClutterTexturePrivate *priv = texture->priv; + ClutterActor *head; + ClutterShader *shader = NULL; + ClutterActor *stage = NULL; + CoglMatrix projection; + CoglColor transparent_col; + + head = _clutter_context_peek_shader_stack (); + if (head != NULL) + shader = clutter_actor_get_shader (head); + + /* Temporarily turn off the shader on the top of the context's + * shader stack, to restore the GL pipeline to it's natural state. + */ + if (shader != NULL) + clutter_shader_set_is_enabled (shader, FALSE); + + /* Redirect drawing to the fbo */ + cogl_push_framebuffer (priv->fbo_handle); + + if ((stage = clutter_actor_get_stage (self)) != NULL) + { + gfloat stage_width, stage_height; + ClutterActor *source_parent; + + /* We copy the projection and modelview matrices from the stage to + * the offscreen framebuffer and create a viewport larger than the + * offscreen framebuffer - the same size as the stage. + * + * The fbo source actor gets rendered into this stage size viewport at the + * same position it normally would after applying all it's usual parent + * transforms and it's own scale and rotate transforms etc. + * + * The viewport is offset such that the offscreen buffer will be positioned + * under the actor. + */ + + _clutter_stage_get_projection_matrix (CLUTTER_STAGE (stage), &projection); + + /* Set the projection matrix modelview matrix as it is for the + * stage... */ + cogl_set_projection_matrix (&projection); + + clutter_actor_get_size (stage, &stage_width, &stage_height); + + /* Set a negatively offset the viewport so that the offscreen + * framebuffer is position underneath the fbo_source actor... */ + set_viewport_with_buffer_under_fbo_source (priv->fbo_source, + stage_width, + stage_height); + + /* Apply the source's parent transformations to the modelview */ + if ((source_parent = clutter_actor_get_parent (priv->fbo_source))) + { + CoglMatrix modelview; + cogl_matrix_init_identity (&modelview); + _clutter_actor_apply_relative_transformation_matrix (source_parent, + NULL, + &modelview); + cogl_set_modelview_matrix (&modelview); + } + } + + + /* cogl_clear is called to clear the buffers */ + cogl_color_init_from_4ub (&transparent_col, 0, 0, 0, 0); + cogl_clear (&transparent_col, + COGL_BUFFER_BIT_COLOR | + COGL_BUFFER_BIT_DEPTH); + + /* Render the actor to the fbo */ + clutter_actor_paint (priv->fbo_source); + + /* Restore drawing to the previous framebuffer */ + cogl_pop_framebuffer (); + + /* If there is a shader on top of the shader stack, turn it back on. */ + if (shader != NULL) + clutter_shader_set_is_enabled (shader, TRUE); +} + +static void +gen_texcoords_and_draw_cogl_rectangle (ClutterActor *self) +{ + ClutterTexture *texture = CLUTTER_TEXTURE (self); + ClutterTexturePrivate *priv = texture->priv; + ClutterActorBox box; + float t_w, t_h; + + clutter_actor_get_allocation_box (self, &box); + + if (priv->repeat_x && priv->image_width > 0) + t_w = (box.x2 - box.x1) / (float) priv->image_width; + else + t_w = 1.0; + + if (priv->repeat_y && priv->image_height > 0) + t_h = (box.y2 - box.y1) / (float) priv->image_height; + else + t_h = 1.0; + + cogl_rectangle_with_texture_coords (0, 0, + box.x2 - box.x1, + box.y2 - box.y1, + 0, 0, t_w, t_h); +} + +static CoglPipeline * +create_pick_pipeline (ClutterActor *self) +{ + ClutterTexture *texture = CLUTTER_TEXTURE (self); + ClutterTexturePrivate *priv = texture->priv; + CoglPipeline *pick_pipeline = cogl_pipeline_copy (texture_template_pipeline); + GError *error = NULL; + + if (!cogl_pipeline_set_layer_combine (pick_pipeline, 0, + "RGBA = " + " MODULATE (CONSTANT, TEXTURE[A])", + &error)) + { + if (!priv->seen_create_pick_pipeline_warning) + g_warning ("Error setting up texture combine for shaped " + "texture picking: %s", error->message); + priv->seen_create_pick_pipeline_warning = TRUE; + g_error_free (error); + cogl_object_unref (pick_pipeline); + return NULL; + } + + cogl_pipeline_set_blend (pick_pipeline, + "RGBA = ADD (SRC_COLOR[RGBA], 0)", + NULL); + + cogl_pipeline_set_alpha_test_function (pick_pipeline, + COGL_PIPELINE_ALPHA_FUNC_EQUAL, + 1.0); + + return pick_pipeline; +} + +static void +clutter_texture_pick (ClutterActor *self, + const ClutterColor *color) +{ + ClutterTexture *texture = CLUTTER_TEXTURE (self); + ClutterTexturePrivate *priv = texture->priv; + + if (!clutter_actor_should_pick_paint (self)) + return; + + if (G_LIKELY (priv->pick_with_alpha_supported) && priv->pick_with_alpha) + { + CoglColor pick_color; + + if (priv->pick_pipeline == NULL) + priv->pick_pipeline = create_pick_pipeline (self); + + if (priv->pick_pipeline == NULL) + { + priv->pick_with_alpha_supported = FALSE; + CLUTTER_ACTOR_CLASS (clutter_texture_parent_class)->pick (self, + color); + return; + } + + if (priv->fbo_handle != NULL) + update_fbo (self); + + cogl_color_init_from_4ub (&pick_color, + color->red, + color->green, + color->blue, + 0xff); + cogl_pipeline_set_layer_combine_constant (priv->pick_pipeline, + 0, &pick_color); + cogl_pipeline_set_layer_texture (priv->pick_pipeline, 0, + clutter_texture_get_cogl_texture (texture)); + cogl_set_source (priv->pick_pipeline); + gen_texcoords_and_draw_cogl_rectangle (self); + } + else + CLUTTER_ACTOR_CLASS (clutter_texture_parent_class)->pick (self, color); +} + +static void +clutter_texture_paint (ClutterActor *self) +{ + ClutterTexture *texture = CLUTTER_TEXTURE (self); + ClutterTexturePrivate *priv = texture->priv; + guint8 paint_opacity = clutter_actor_get_paint_opacity (self); + + CLUTTER_NOTE (PAINT, + "painting texture '%s'", + clutter_actor_get_name (self) ? clutter_actor_get_name (self) + : "unknown"); + + if (priv->fbo_handle != NULL) + update_fbo (self); + + cogl_pipeline_set_color4ub (priv->pipeline, + paint_opacity, + paint_opacity, + paint_opacity, + paint_opacity); + cogl_set_source (priv->pipeline); + + gen_texcoords_and_draw_cogl_rectangle (self); +} + +static gboolean +clutter_texture_get_paint_volume (ClutterActor *self, + ClutterPaintVolume *volume) +{ + ClutterTexturePrivate *priv; + + priv = CLUTTER_TEXTURE (self)->priv; + + if (priv->pipeline == NULL) + return FALSE; + + if (priv->image_width == 0 || priv->image_height == 0) + return FALSE; + + return _clutter_actor_set_default_paint_volume (self, + CLUTTER_TYPE_TEXTURE, + volume); +} + +static void +clutter_texture_async_data_free (ClutterTextureAsyncData *data) +{ + /* This function should only be called either from the main thread + once it is known that the load thread has completed or from the + load thread/upload function itself if the abort flag is true (in + which case the main thread has disowned the data) */ + g_free (data->load_filename); + + if (data->load_bitmap != NULL) + cogl_object_unref (data->load_bitmap); + + if (data->load_error != NULL) + g_error_free (data->load_error); + + g_slice_free (ClutterTextureAsyncData, data); +} + +/* + * clutter_texture_async_load_cancel: + * @texture: a #ClutterTexture + * + * Cancels an asynchronous loading operation, whether done + * with threads enabled or just using the main loop + */ +static void +clutter_texture_async_load_cancel (ClutterTexture *texture) +{ + ClutterTexturePrivate *priv = texture->priv; + + if (priv->async_data != NULL) + { + ClutterTextureAsyncData *async_data = priv->async_data; + + priv->async_data = NULL; + + if (async_data->load_idle != 0) + { + g_source_remove (async_data->load_idle); + async_data->load_idle = 0; + + clutter_texture_async_data_free (async_data); + } + else + { + clutter_texture_async_data_lock (async_data); + + CLUTTER_NOTE (TEXTURE, "[async] cancelling operation for '%s'", + async_data->load_filename); + + async_data->state |= ASYNC_STATE_CANCELLED; + + clutter_texture_async_data_unlock (async_data); + } + } +} + +static void +clutter_texture_dispose (GObject *object) +{ + ClutterTexture *texture = CLUTTER_TEXTURE (object); + ClutterTexturePrivate *priv = texture->priv; + + texture_free_gl_resources (texture); + texture_fbo_free_resources (texture); + + clutter_texture_async_load_cancel (texture); + + if (priv->pipeline != NULL) + { + cogl_object_unref (priv->pipeline); + priv->pipeline = NULL; + } + + if (priv->pick_pipeline != NULL) + { + cogl_object_unref (priv->pick_pipeline); + priv->pick_pipeline = NULL; + } + + G_OBJECT_CLASS (clutter_texture_parent_class)->dispose (object); +} + +static void +clutter_texture_finalize (GObject *object) +{ + ClutterTexturePrivate *priv = CLUTTER_TEXTURE (object)->priv; + + g_free (priv->filename); + + G_OBJECT_CLASS (clutter_texture_parent_class)->finalize (object); +} + +static void +clutter_texture_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterTexture *texture; + ClutterTexturePrivate *priv; + + texture = CLUTTER_TEXTURE (object); + priv = texture->priv; + + switch (prop_id) + { + case PROP_SYNC_SIZE: + clutter_texture_set_sync_size (texture, g_value_get_boolean (value)); + break; + + case PROP_REPEAT_X: + clutter_texture_set_repeat (texture, + g_value_get_boolean (value), + priv->repeat_y); + break; + + case PROP_REPEAT_Y: + clutter_texture_set_repeat (texture, + priv->repeat_x, + g_value_get_boolean (value)); + break; + + case PROP_FILTER_QUALITY: + clutter_texture_set_filter_quality (texture, + g_value_get_enum (value)); + break; + + case PROP_COGL_TEXTURE: + { + CoglHandle hnd = g_value_get_boxed (value); + + clutter_texture_set_cogl_texture (texture, hnd); + } + break; + + case PROP_COGL_MATERIAL: + { + CoglHandle hnd = g_value_get_boxed (value); + + clutter_texture_set_cogl_material (texture, hnd); + } + break; + + case PROP_FILENAME: + clutter_texture_set_from_file (texture, + g_value_get_string (value), + NULL); + break; + + case PROP_NO_SLICE: + priv->no_slice = g_value_get_boolean (value); + break; + + case PROP_KEEP_ASPECT_RATIO: + clutter_texture_set_keep_aspect_ratio (texture, + g_value_get_boolean (value)); + break; + + case PROP_LOAD_DATA_ASYNC: + clutter_texture_set_load_data_async (texture, + g_value_get_boolean (value)); + break; + + case PROP_LOAD_ASYNC: + clutter_texture_set_load_async (texture, g_value_get_boolean (value)); + break; + + case PROP_PICK_WITH_ALPHA: + clutter_texture_set_pick_with_alpha (texture, + g_value_get_boolean (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_texture_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterTexture *texture; + ClutterTexturePrivate *priv; + + texture = CLUTTER_TEXTURE(object); + priv = texture->priv; + + switch (prop_id) + { + 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; + + case PROP_REPEAT_X: + g_value_set_boolean (value, priv->repeat_x); + break; + + case PROP_REPEAT_Y: + g_value_set_boolean (value, priv->repeat_y); + break; + + case PROP_FILTER_QUALITY: + g_value_set_enum (value, clutter_texture_get_filter_quality (texture)); + break; + + case PROP_COGL_TEXTURE: + g_value_set_boxed (value, clutter_texture_get_cogl_texture (texture)); + break; + + case PROP_COGL_MATERIAL: + g_value_set_boxed (value, clutter_texture_get_cogl_material (texture)); + break; + + case PROP_NO_SLICE: + g_value_set_boolean (value, priv->no_slice); + break; + + case PROP_KEEP_ASPECT_RATIO: + g_value_set_boolean (value, priv->keep_aspect_ratio); + break; + + case PROP_PICK_WITH_ALPHA: + g_value_set_boolean (value, priv->pick_with_alpha); + break; + + case PROP_FILENAME: + g_value_set_string (value, priv->filename); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_texture_class_init (ClutterTextureClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + GParamSpec *pspec; + + actor_class->paint = clutter_texture_paint; + actor_class->pick = clutter_texture_pick; + actor_class->get_paint_volume = clutter_texture_get_paint_volume; + actor_class->realize = clutter_texture_realize; + actor_class->unrealize = clutter_texture_unrealize; + actor_class->has_overlaps = clutter_texture_has_overlaps; + + actor_class->get_preferred_width = clutter_texture_get_preferred_width; + actor_class->get_preferred_height = clutter_texture_get_preferred_height; + actor_class->allocate = clutter_texture_allocate; + + gobject_class->dispose = clutter_texture_dispose; + gobject_class->finalize = clutter_texture_finalize; + gobject_class->set_property = clutter_texture_set_property; + gobject_class->get_property = clutter_texture_get_property; + + pspec = g_param_spec_boolean ("sync-size", + P_("Sync size of actor"), + P_("Auto sync size of actor to underlying pixbuf dimensions"), + TRUE, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_SYNC_SIZE] = pspec; + g_object_class_install_property (gobject_class, PROP_SYNC_SIZE, pspec); + + pspec = g_param_spec_boolean ("disable-slicing", + P_("Disable Slicing"), + P_("Forces the underlying texture to be singular and not made of smaller space saving " + "individual textures"), + FALSE, + G_PARAM_CONSTRUCT_ONLY | + CLUTTER_PARAM_READWRITE); + obj_props[PROP_NO_SLICE] = pspec; + g_object_class_install_property (gobject_class, PROP_NO_SLICE, pspec); + + pspec = g_param_spec_int ("tile-waste", + P_("Tile Waste"), + P_("Maximum waste area of a sliced texture"), + -1, G_MAXINT, + COGL_TEXTURE_MAX_WASTE, + CLUTTER_PARAM_READABLE); + obj_props[PROP_MAX_TILE_WASTE] = pspec; + g_object_class_install_property (gobject_class, PROP_MAX_TILE_WASTE, pspec); + + pspec = g_param_spec_boolean ("repeat-x", + P_("Horizontal repeat"), + P_("Repeat the contents rather than scaling them horizontally"), + FALSE, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_REPEAT_X] = pspec; + g_object_class_install_property (gobject_class, PROP_REPEAT_X, pspec); + + pspec = g_param_spec_boolean ("repeat-y", + P_("Vertical repeat"), + P_("Repeat the contents rather than scaling them vertically"), + FALSE, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_REPEAT_Y] = pspec; + g_object_class_install_property (gobject_class, PROP_REPEAT_Y, pspec); + + pspec = g_param_spec_enum ("filter-quality", + P_("Filter Quality"), + P_("Rendering quality used when drawing the texture"), + CLUTTER_TYPE_TEXTURE_QUALITY, + CLUTTER_TEXTURE_QUALITY_MEDIUM, + G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE); + obj_props[PROP_FILTER_QUALITY] = pspec; + g_object_class_install_property (gobject_class, PROP_FILTER_QUALITY, pspec); + + pspec = g_param_spec_boxed ("cogl-texture", + P_("Cogl Texture"), + P_("The underlying Cogl texture handle used to draw this actor"), + COGL_TYPE_HANDLE, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_COGL_TEXTURE] = pspec; + g_object_class_install_property (gobject_class, PROP_COGL_TEXTURE, pspec); + + pspec = g_param_spec_boxed ("cogl-material", + P_("Cogl Material"), + P_("The underlying Cogl material handle used to draw this actor"), + COGL_TYPE_HANDLE, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_COGL_MATERIAL] = pspec; + g_object_class_install_property (gobject_class, PROP_COGL_MATERIAL, pspec); + + /** + * ClutterTexture:filename: + * + * The path of the file containing the image data to be displayed by + * the texture. + * + * This property is unset when using the clutter_texture_set_from_*_data() + * family of functions. + * + * Deprecated: 1.12: Use #ClutterImage and platform-specific image loading + * API, like GdkPixbuf + */ + pspec = g_param_spec_string ("filename", + P_("Filename"), + P_("The path of the file containing the image data"), + NULL, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_FILENAME] = pspec; + g_object_class_install_property (gobject_class, PROP_FILENAME, pspec); + + pspec = g_param_spec_boolean ("keep-aspect-ratio", + P_("Keep Aspect Ratio"), + P_("Keep the aspect ratio of the texture when requesting the preferred width or height"), + FALSE, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_KEEP_ASPECT_RATIO] = pspec; + g_object_class_install_property (gobject_class, PROP_KEEP_ASPECT_RATIO, pspec); + + /** + * ClutterTexture:load-async: + * + * Tries to load a texture from a filename by using a local thread to perform + * the read operations. The initially created texture has dimensions 0x0 when + * the true size becomes available the #ClutterTexture::size-change signal is + * emitted and when the image has completed loading the + * #ClutterTexture::load-finished signal is emitted. + * + * Threading is only enabled if g_thread_init() has been called prior to + * clutter_init(), otherwise #ClutterTexture will use the main loop to load + * the image. + * + * The upload of the texture data on the GL pipeline is not asynchronous, as + * it must be performed from within the same thread that called + * clutter_main(). + * + * Since: 1.0 + * + * Deprecated: 1.12: Use platform-specific image loading API, like GdkPixbuf + */ + pspec = g_param_spec_boolean ("load-async", + P_("Load asynchronously"), + P_("Load files inside a thread to avoid blocking when loading images from disk"), + FALSE, + CLUTTER_PARAM_WRITABLE); + obj_props[PROP_LOAD_ASYNC] = pspec; + g_object_class_install_property (gobject_class, PROP_LOAD_ASYNC, pspec); + + + /** + * ClutterTexture:load-data-async: + * + * Like #ClutterTexture:load-async but loads the width and height + * synchronously causing some blocking. + * + * Since: 1.0 + * + * Deprecated: 1.12: Use platform-specific image loading API, like GdkPixbuf + */ + pspec = g_param_spec_boolean ("load-data-async", + P_("Load data asynchronously"), + P_("Decode image data files inside a thread to reduce blocking when loading images from disk"), + FALSE, + CLUTTER_PARAM_WRITABLE); + obj_props[PROP_LOAD_DATA_ASYNC] = pspec; + g_object_class_install_property (gobject_class, PROP_LOAD_DATA_ASYNC, pspec); + + /** + * ClutterTexture::pick-with-alpha: + * + * Determines whether a #ClutterTexture should have it's shape defined + * by its alpha channel when picking. + * + * Be aware that this is a bit more costly than the default picking + * due to the texture lookup, extra test against the alpha value and + * the fact that it will also interrupt the batching of geometry + * done internally. + * + * Also there is currently no control over the threshold used to + * determine what value of alpha is considered pickable, and so + * only fully opaque parts of the texture will react to picking. + * + * Since: 1.4 + * + * Deprecated: 1.12: No replacement is available + */ + pspec = g_param_spec_boolean ("pick-with-alpha", + P_("Pick With Alpha"), + P_("Shape actor with alpha channel when picking"), + FALSE, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_PICK_WITH_ALPHA] = pspec; + g_object_class_install_property (gobject_class, PROP_PICK_WITH_ALPHA, pspec); + + /** + * ClutterTexture::size-change: + * @texture: the texture which received the signal + * @width: the width of the new texture + * @height: the height of the new texture + * + * The ::size-change signal is emitted each time the size of the + * pixbuf used by @texture changes. The new size is given as + * argument to the callback. + * + * Deprecated: 1.12: No replacement is available + */ + texture_signals[SIZE_CHANGE] = + g_signal_new ("size-change", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterTextureClass, size_change), + NULL, NULL, + _clutter_marshal_VOID__INT_INT, + G_TYPE_NONE, 2, + G_TYPE_INT, + G_TYPE_INT); + /** + * ClutterTexture::pixbuf-change: + * @texture: the texture which received the signal + * + * The ::pixbuf-change signal is emitted each time the pixbuf + * used by @texture changes. + * + * Deprecated: 1.12: No replacement is available + */ + texture_signals[PIXBUF_CHANGE] = + g_signal_new ("pixbuf-change", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterTextureClass, pixbuf_change), + NULL, NULL, + _clutter_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + /** + * ClutterTexture::load-finished: + * @texture: the texture which received the signal + * @error: A set error, or %NULL + * + * The ::load-finished signal is emitted when a texture load has + * completed. If there was an error during loading, @error will + * be set, otherwise it will be %NULL + * + * Since: 1.0 + * + * Deprecated: 1.12: No replacement is available + */ + texture_signals[LOAD_FINISHED] = + g_signal_new (I_("load-finished"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterTextureClass, load_finished), + NULL, NULL, + _clutter_marshal_VOID__BOXED, + G_TYPE_NONE, + 1, + G_TYPE_ERROR); +} + +static ClutterScriptableIface *parent_scriptable_iface = NULL; + +static void +clutter_texture_set_custom_property (ClutterScriptable *scriptable, + ClutterScript *script, + const gchar *name, + const GValue *value) +{ + ClutterTexture *texture = CLUTTER_TEXTURE (scriptable); + + if (strcmp ("filename", name) == 0) + { + const gchar *str = g_value_get_string (value); + gchar *path; + GError *error; + + path = clutter_script_lookup_filename (script, str); + if (G_UNLIKELY (!path)) + { + g_warning ("Unable to find image %s", str); + return; + } + + error = NULL; + clutter_texture_set_from_file (texture, path, &error); + if (error) + { + g_warning ("Unable to open image path at '%s': %s", + path, + error->message); + g_error_free (error); + } + + g_free (path); + } + else + { + /* chain up */ + if (parent_scriptable_iface->set_custom_property) + parent_scriptable_iface->set_custom_property (scriptable, script, + name, + value); + } +} + +static void +clutter_scriptable_iface_init (ClutterScriptableIface *iface) +{ + parent_scriptable_iface = g_type_interface_peek_parent (iface); + + if (!parent_scriptable_iface) + parent_scriptable_iface = g_type_default_interface_peek + (CLUTTER_TYPE_SCRIPTABLE); + + iface->set_custom_property = clutter_texture_set_custom_property; +} + +static void +clutter_texture_init (ClutterTexture *self) +{ + ClutterTexturePrivate *priv; + + self->priv = priv = clutter_texture_get_instance_private (self); + + priv->repeat_x = FALSE; + priv->repeat_y = FALSE; + priv->sync_actor_size = TRUE; + priv->fbo_handle = NULL; + priv->pick_pipeline = NULL; + priv->keep_aspect_ratio = FALSE; + priv->pick_with_alpha = FALSE; + priv->pick_with_alpha_supported = TRUE; + priv->seen_create_pick_pipeline_warning = FALSE; + + if (G_UNLIKELY (texture_template_pipeline == NULL)) + { + CoglPipeline *pipeline; + CoglContext *ctx = + clutter_backend_get_cogl_context (clutter_get_default_backend ()); + + texture_template_pipeline = cogl_pipeline_new (ctx); + pipeline = COGL_PIPELINE (texture_template_pipeline); + cogl_pipeline_set_layer_null_texture (pipeline, + 0, /* layer_index */ + COGL_TEXTURE_TYPE_2D); + } + + g_assert (texture_template_pipeline != NULL); + priv->pipeline = cogl_pipeline_copy (texture_template_pipeline); +} + +/** + * clutter_texture_get_cogl_material: + * @texture: A #ClutterTexture + * + * Returns a handle to the underlying COGL material used for drawing + * the actor. + * + * Return value: (transfer none): a handle for a #CoglMaterial. The + * material is owned by the #ClutterTexture and it should not be + * unreferenced + * + * Since: 1.0 + * + * Deprecated: 1.12: No replacement is available; it's not advisable + * to modify the Cogl pipeline of an actor. Use a #ClutterContent + * implementation and modify the pipeline during the paint sequence + */ +CoglHandle +clutter_texture_get_cogl_material (ClutterTexture *texture) +{ + g_return_val_if_fail (CLUTTER_IS_TEXTURE (texture), NULL); + + return texture->priv->pipeline; +} + +/** + * clutter_texture_set_cogl_material: + * @texture: A #ClutterTexture + * @cogl_material: A CoglHandle for a material + * + * Replaces the underlying Cogl material drawn by this actor with + * @cogl_material. A reference to the material is taken so if the + * handle is no longer needed it should be deref'd with + * cogl_handle_unref. Texture data is attached to the material so + * calling this function also replaces the Cogl + * texture. #ClutterTexture requires that the material have a texture + * layer so you should set one on the material before calling this + * function. + * + * Since: 0.8 + * + * Deprecated: 1.12: No replacement is available; it's not advisable + * to modify the Cogl pipeline of an actor. Use a #ClutterContent + * implementation and modify the pipeline during the paint sequence + */ +void +clutter_texture_set_cogl_material (ClutterTexture *texture, + CoglHandle cogl_material) +{ + CoglPipeline *cogl_pipeline = cogl_material; + CoglHandle cogl_texture; + + g_return_if_fail (CLUTTER_IS_TEXTURE (texture)); + + cogl_object_ref (cogl_pipeline); + + if (texture->priv->pipeline) + cogl_object_unref (texture->priv->pipeline); + + texture->priv->pipeline = cogl_pipeline; + + /* XXX: We are re-asserting the first layer of the new pipeline to ensure the + * priv state is in sync with the contents of the pipeline. */ + cogl_texture = clutter_texture_get_cogl_texture (texture); + clutter_texture_set_cogl_texture (texture, cogl_texture); + /* XXX: If we add support for more pipeline layers, this will need + * extending */ +} + +typedef struct _GetLayerState +{ + gboolean has_layer; + int first_layer; +} GetLayerState; + +static gboolean +layer_cb (CoglPipeline *pipeline, int layer, void *user_data) +{ + GetLayerState *state = user_data; + + state->has_layer = TRUE; + state->first_layer = layer; + + /* We only care about the first layer. */ + return FALSE; +} + +static gboolean +get_first_layer_index (CoglPipeline *pipeline, int *layer_index) +{ + GetLayerState state = { FALSE }; + cogl_pipeline_foreach_layer (pipeline, + layer_cb, + &state); + if (state.has_layer) + *layer_index = state.first_layer; + + return state.has_layer; +} + +/** + * clutter_texture_get_cogl_texture: + * @texture: A #ClutterTexture + * + * Retrieves the handle to the underlying COGL texture used for drawing + * the actor. No extra reference is taken so if you need to keep the + * handle then you should call cogl_handle_ref() on it. + * + * The texture handle returned is the first layer of the material + * handle used by the #ClutterTexture. If you need to access the other + * layers you should use clutter_texture_get_cogl_material() instead + * and use the #CoglMaterial API. + * + * Return value: (transfer none): a #CoglHandle for the texture. The returned + * handle is owned by the #ClutterTexture and it should not be unreferenced + * + * Since: 0.8 + * + * Deprecated: 1.12: No replacement available; it's not advisable to + * modify the Cogl pipeline of an actor. Use a #ClutterContent + * implementation and set up the pipeline during the paint sequence + * instead. + */ +CoglHandle +clutter_texture_get_cogl_texture (ClutterTexture *texture) +{ + ClutterTexturePrivate *priv; + int layer_index; + + g_return_val_if_fail (CLUTTER_IS_TEXTURE (texture), NULL); + + priv = texture->priv; + + if (get_first_layer_index (priv->pipeline, &layer_index)) + return cogl_pipeline_get_layer_texture (priv->pipeline, layer_index); + else + return NULL; +} + +/** + * clutter_texture_set_cogl_texture: + * @texture: A #ClutterTexture + * @cogl_tex: A CoglHandle for a texture + * + * Replaces the underlying COGL texture drawn by this actor with + * @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. + * + * Since: 0.8 + * + * Deprecated: 1.12: No replacement available; it's not advisable to + * modify the Cogl pipeline of an actor. Use a #ClutterContent + * implementation and set up the pipeline during the paint sequence + * instead. + */ +void +clutter_texture_set_cogl_texture (ClutterTexture *texture, + CoglHandle cogl_tex) +{ + ClutterTexturePrivate *priv; + gboolean size_changed; + guint width, height; + + g_return_if_fail (CLUTTER_IS_TEXTURE (texture)); + g_return_if_fail (cogl_is_texture (cogl_tex)); + + /* This function can set the texture without the actor being + realized. This is ok because Clutter requires that the GL context + always be current so there is no point in waiting to realization + to set the texture. */ + + priv = texture->priv; + + width = cogl_texture_get_width (cogl_tex); + height = cogl_texture_get_height (cogl_tex); + + /* Reference the new texture now in case it is the same one we are + already using */ + cogl_object_ref (cogl_tex); + + /* Remove FBO if exisiting */ + if (priv->fbo_source) + texture_fbo_free_resources (texture); + + /* Remove old texture */ + texture_free_gl_resources (texture); + + /* Use the new texture */ + if (priv->pipeline == NULL) + priv->pipeline = cogl_pipeline_copy (texture_template_pipeline); + + g_assert (priv->pipeline != NULL); + cogl_pipeline_set_layer_texture (priv->pipeline, 0, cogl_tex); + + /* The pipeline now holds a reference to the texture so we can + safely release the reference we claimed above */ + cogl_object_unref (cogl_tex); + + size_changed = (width != priv->image_width || height != priv->image_height); + priv->image_width = width; + priv->image_height = height; + + CLUTTER_NOTE (TEXTURE, "set size (w:%d, h:%d)", + priv->image_width, + priv->image_height); + + if (size_changed) + { + g_signal_emit (texture, texture_signals[SIZE_CHANGE], 0, + priv->image_width, + priv->image_height); + + if (priv->sync_actor_size) + { + ClutterActor *actor = CLUTTER_ACTOR (texture); + + /* we have been requested to keep the actor size in + * sync with the texture data; if we also want to + * maintain the aspect ratio we want to change the + * requisition mode depending on the orientation of + * the texture, so that the parent container can do + * the right thing + */ + if (priv->keep_aspect_ratio) + { + ClutterRequestMode request; + + if (priv->image_width >= priv->image_height) + request = CLUTTER_REQUEST_HEIGHT_FOR_WIDTH; + else + request = CLUTTER_REQUEST_WIDTH_FOR_HEIGHT; + + clutter_actor_set_request_mode (actor, request); + } + + clutter_actor_queue_relayout (CLUTTER_ACTOR (texture)); + } + } + + /* rename signal */ + g_signal_emit (texture, texture_signals[PIXBUF_CHANGE], 0); + + /* If resized actor may need resizing but paint() will do this */ + clutter_actor_queue_redraw (CLUTTER_ACTOR (texture)); + + g_object_notify_by_pspec (G_OBJECT (texture), obj_props[PROP_COGL_TEXTURE]); +} + +static gboolean +clutter_texture_set_from_data (ClutterTexture *texture, + const guchar *data, + CoglPixelFormat source_format, + gint width, + gint height, + gint rowstride, + gint bpp, + GError **error) +{ + ClutterTexturePrivate *priv = texture->priv; + CoglHandle new_texture = NULL; + CoglTextureFlags flags = COGL_TEXTURE_NONE; + + if (priv->no_slice) + flags |= COGL_TEXTURE_NO_SLICING; + + /* 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, + flags, + source_format, + COGL_PIXEL_FORMAT_ANY, + rowstride, + data); + + if (G_UNLIKELY (new_texture == NULL)) + { + GError *inner_error = NULL; + + g_set_error (&inner_error, CLUTTER_TEXTURE_ERROR, + CLUTTER_TEXTURE_ERROR_BAD_FORMAT, + _("Failed to load the image data")); + + g_signal_emit (texture, texture_signals[LOAD_FINISHED], 0, inner_error); + + if (error != NULL) + g_propagate_error (error, inner_error); + else + g_error_free (inner_error); + + return FALSE; + } + + g_free (priv->filename); + priv->filename = NULL; + + clutter_texture_set_cogl_texture (texture, new_texture); + + cogl_object_unref (new_texture); + + g_signal_emit (texture, texture_signals[LOAD_FINISHED], 0, NULL); + + return TRUE; +} + +static inline gboolean +get_pixel_format_from_texture_flags (gint bpp, + gboolean has_alpha, + ClutterTextureFlags flags, + CoglPixelFormat *source_format) +{ + /* Convert the flags to a CoglPixelFormat */ + if (has_alpha) + { + if (G_UNLIKELY (bpp != 4)) + { + g_warning ("Unsupported bytes per pixel value '%d': " + "Clutter supports only a value of 4 " + "for RGBA data", + bpp); + return FALSE; + } + + *source_format = COGL_PIXEL_FORMAT_RGBA_8888; + } + else + { + if (G_UNLIKELY (bpp != 3)) + { + g_warning ("Unsupported bytes 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)) + *source_format |= COGL_PREMULT_BIT; + + return TRUE; +} + +/** + * clutter_texture_set_from_rgb_data: + * @texture: a #ClutterTexture + * @data: (array): image data in RGBA type colorspace. + * @has_alpha: set to %TRUE if image data has an alpha channel. + * @width: width in pixels of image data. + * @height: height in pixels of image data + * @rowstride: distance in bytes between row starts. + * @bpp: bytes per pixel (currently only 3 and 4 supported, depending + * on the value of @has_alpha) + * @flags: #ClutterTextureFlags + * @error: return location for a #GError, or %NULL. + * + * Sets #ClutterTexture image data. + * + * Return value: %TRUE on success, %FALSE on failure. + * + * Since: 0.4 + * + * Deprecated: 1.12: Use #ClutterImage and clutter_image_set_data() instead + */ +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) +{ + CoglPixelFormat source_format; + + g_return_val_if_fail (CLUTTER_IS_TEXTURE (texture), FALSE); + + if (!get_pixel_format_from_texture_flags (bpp, + has_alpha, + flags, + &source_format)) + { + return FALSE; + } + + return clutter_texture_set_from_data (texture, data, + source_format, + width, height, + rowstride, bpp, + error); +} + +/** + * clutter_texture_set_from_yuv_data: + * @texture: A #ClutterTexture + * @data: (array): Image data in YUV type colorspace. + * @width: Width in pixels of image data. + * @height: Height in pixels of image data + * @flags: #ClutterTextureFlags + * @error: Return location for a #GError, or %NULL. + * + * Sets a #ClutterTexture from YUV image data. If an error occurred, + * %FALSE is returned and @error is set. + * + * The YUV support depends on the driver; the format supported by the + * few drivers exposing this capability are not really useful. + * + * The proper way to convert image data in any YUV colorspace to any + * RGB colorspace is to use a fragment shader associated with the + * #ClutterTexture material. + * + * Return value: %TRUE if the texture was successfully updated + * + * Since: 0.4 + * + * Deprecated: 1.10: Use a custom #ClutterContent implementation and + * set up the Cogl pipeline using a #ClutterPipelineNode with a + * fragment shader instead. + */ +gboolean +clutter_texture_set_from_yuv_data (ClutterTexture *texture, + const guchar *data, + gint width, + gint height, + ClutterTextureFlags flags, + GError **error) +{ + g_return_val_if_fail (CLUTTER_IS_TEXTURE (texture), FALSE); + + if (!clutter_feature_available (CLUTTER_FEATURE_TEXTURE_YUV)) + { + g_set_error (error, CLUTTER_TEXTURE_ERROR, + CLUTTER_TEXTURE_ERROR_NO_YUV, + _("YUV textures are not supported")); + return FALSE; + } + + /* Convert the flags to a CoglPixelFormat */ + if ((flags & CLUTTER_TEXTURE_YUV_FLAG_YUV2)) + { + g_set_error (error, CLUTTER_TEXTURE_ERROR, + CLUTTER_TEXTURE_ERROR_BAD_FORMAT, + _("YUV2 textures are not supported")); + return FALSE; + } + + return clutter_texture_set_from_data (texture, data, + COGL_PIXEL_FORMAT_YUV, + width, height, + width * 3, 3, + error); +} + +/* + * clutter_texture_async_load_complete: + * @self: a #ClutterTexture + * @bitmap: a handle to a CoglBitmap + * @error: load error + * + * If @error is %NULL, loads @bitmap into a #CoglTexture. + * + * This function emits the ::load-finished signal on @self. + */ +static void +clutter_texture_async_load_complete (ClutterTexture *self, + CoglHandle bitmap, + const GError *error) +{ + ClutterTexturePrivate *priv = self->priv; + CoglTextureFlags flags = COGL_TEXTURE_NONE; + CoglHandle handle; + + priv->async_data = NULL; + + if (error == NULL) + { + if (priv->no_slice) + flags |= COGL_TEXTURE_NO_SLICING; + + handle = cogl_texture_new_from_bitmap (bitmap, + flags, + COGL_PIXEL_FORMAT_ANY); + clutter_texture_set_cogl_texture (self, handle); + + if (priv->load_size_async) + { + g_signal_emit (self, texture_signals[SIZE_CHANGE], 0, + cogl_texture_get_width (handle), + cogl_texture_get_height (handle)); + } + + cogl_object_unref (handle); + } + + g_signal_emit (self, texture_signals[LOAD_FINISHED], 0, error); + + clutter_actor_queue_relayout (CLUTTER_ACTOR (self)); +} + +static gboolean +texture_repaint_upload_func (gpointer user_data) +{ + g_mutex_lock (&upload_list_mutex); + + if (upload_list != NULL) + { + gint64 start_time = g_get_monotonic_time (); + + /* continue uploading textures as long as we havent spent more + * then 5ms doing so this stage redraw cycle. + */ + do + { + ClutterTextureAsyncData *async_data = upload_list->data; + + clutter_texture_async_data_lock (async_data); + + if (async_data->state & ASYNC_STATE_QUEUED) + { + CLUTTER_NOTE (TEXTURE, "[async] operation complete for '%s'", + async_data->load_filename); + + clutter_texture_async_load_complete (async_data->texture, + async_data->load_bitmap, + async_data->load_error); + } + else + CLUTTER_NOTE (TEXTURE, "[async] operation cancelled for '%s'", + async_data->load_filename); + + clutter_texture_async_data_unlock (async_data); + + upload_list = g_list_remove (upload_list, async_data); + clutter_texture_async_data_free (async_data); + } + while (upload_list != NULL && + g_get_monotonic_time () < start_time + 5 * 1000L); + } + + if (upload_list != NULL) + { + ClutterMasterClock *master_clock; + + master_clock = _clutter_master_clock_get_default (); + _clutter_master_clock_ensure_next_iteration (master_clock); + } + + g_mutex_unlock (&upload_list_mutex); + + return TRUE; +} + +static void +clutter_texture_thread_load (gpointer user_data, + gpointer pool_data) +{ + ClutterTextureAsyncData *async_data = user_data; + ClutterMasterClock *master_clock = _clutter_master_clock_get_default (); + + clutter_texture_async_data_lock (async_data); + + if (~async_data->state & ASYNC_STATE_CANCELLED) + { + CLUTTER_NOTE (TEXTURE, "[async] loading bitmap from file '%s'", + async_data->load_filename); + + async_data->load_bitmap = + cogl_bitmap_new_from_file (async_data->load_filename, + &async_data->load_error); + + g_mutex_lock (&upload_list_mutex); + + if (repaint_upload_func == 0) + { + repaint_upload_func = + clutter_threads_add_repaint_func (texture_repaint_upload_func, + NULL, NULL); + } + + upload_list = g_list_append (upload_list, async_data); + async_data->state |= ASYNC_STATE_QUEUED; + + CLUTTER_NOTE (TEXTURE, "[async] operation queued"); + + g_mutex_unlock (&upload_list_mutex); + } + else + { + clutter_texture_async_data_unlock (async_data); + clutter_texture_async_data_free (async_data); + + return; + } + + clutter_texture_async_data_unlock (async_data); + + _clutter_master_clock_ensure_next_iteration (master_clock); +} + +static gboolean +clutter_texture_idle_load (gpointer data) +{ + ClutterTextureAsyncData *async_data = data; + + async_data->load_bitmap = + cogl_bitmap_new_from_file (async_data->load_filename, + &async_data->load_error); + + clutter_texture_async_load_complete (async_data->texture, + async_data->load_bitmap, + async_data->load_error); + + clutter_texture_async_data_free (async_data); + + return FALSE; +} + +/* + * clutter_texture_async_load: + * @self: a #ClutterTExture + * @filename: name of the file to load + * @error: return location for a #GError + * + * Starts an asynchronous load of the file name stored inside + * the load_filename member of @data. + * + * If threading is enabled we use a GThread to perform the actual + * I/O; if threading is not enabled, we use an idle GSource. + * + * The I/O is the only bit done in a thread -- uploading the + * texture data to the GL pipeline must be done from within the + * same thread that called clutter_main(). Threaded upload should + * be part of the GL implementation. + * + * This function will block until we get a size from the file + * so that we can effectively get the size the texture actor after + * clutter_texture_set_from_file(). + * + * Return value: %TRUE if the asynchronous loading was successfully + * initiated, %FALSE otherwise + */ +static gboolean +clutter_texture_async_load (ClutterTexture *self, + const gchar *filename, + GError **error) +{ + ClutterTexturePrivate *priv = self->priv; + ClutterTextureAsyncData *data; + gint width, height; + gboolean res; + + /* ask the file for a size; if we cannot get the size then + * there's no point in even continuing the asynchronous + * loading, so we just stop there + */ + + if (priv->load_size_async) + { + res = TRUE; + width = 0; + height = 0; + } + else + res = cogl_bitmap_get_size_from_file (filename, &width, &height); + + if (!res) + { + g_set_error (error, CLUTTER_TEXTURE_ERROR, + CLUTTER_TEXTURE_ERROR_BAD_FORMAT, + _("Failed to load the image data")); + return FALSE; + } + else + { + priv->image_width = width; + priv->image_height = height; + } + + clutter_texture_async_load_cancel (self); + + data = g_slice_new0 (ClutterTextureAsyncData); + + data->texture = self; + data->load_filename = g_strdup (filename); + + priv->async_data = data; + + if (1) + { + if (G_UNLIKELY (async_thread_pool == NULL)) + { + /* This apparently can't fail if exclusive == FALSE */ + async_thread_pool = + g_thread_pool_new (clutter_texture_thread_load, NULL, + 1, + FALSE, + NULL); + } + + g_thread_pool_push (async_thread_pool, data, NULL); + } + else + { + data->load_idle = + clutter_threads_add_idle_full (G_PRIORITY_DEFAULT_IDLE, + clutter_texture_idle_load, + data, + NULL); + } + + return TRUE; +} + +/** + * clutter_texture_set_from_file: + * @texture: A #ClutterTexture + * @filename: The filename of the image in GLib file name encoding + * @error: Return location for a #GError, or %NULL + * + * Sets the #ClutterTexture image data from an image file. In case of + * failure, %FALSE is returned and @error is set. + * + * If #ClutterTexture:load-async is set to %TRUE, this function + * will return as soon as possible, and the actual image loading + * from disk will be performed asynchronously. #ClutterTexture::size-change + * will be emitten when the size of the texture is available and + * #ClutterTexture::load-finished will be emitted when the image has been + * loaded or if an error occurred. + * + * Return value: %TRUE if the image was successfully loaded and set + * + * Since: 0.8 + * + * Deprecated: 1.12: Use #ClutterImage and platform-specific image + * loading API, like GdkPixbuf, instead + */ +gboolean +clutter_texture_set_from_file (ClutterTexture *texture, + const gchar *filename, + GError **error) +{ + ClutterTexturePrivate *priv; + CoglHandle new_texture = NULL; + GError *internal_error = NULL; + CoglTextureFlags flags = COGL_TEXTURE_NONE; + + priv = texture->priv; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (priv->load_data_async) + return clutter_texture_async_load (texture, filename, error); + + if (priv->no_slice) + flags |= COGL_TEXTURE_NO_SLICING; + + new_texture = cogl_texture_new_from_file (filename, + flags, + COGL_PIXEL_FORMAT_ANY, + &internal_error); + + /* If COGL didn't give an error then make one up */ + if (internal_error == NULL && new_texture == NULL) + { + g_set_error (&internal_error, CLUTTER_TEXTURE_ERROR, + CLUTTER_TEXTURE_ERROR_BAD_FORMAT, + _("Failed to load the image data")); + } + + if (internal_error != NULL) + { + g_signal_emit (texture, texture_signals[LOAD_FINISHED], 0, + internal_error); + + g_propagate_error (error, internal_error); + + return FALSE; + } + + g_free (priv->filename); + priv->filename = g_strdup (filename); + + clutter_texture_set_cogl_texture (texture, new_texture); + + cogl_object_unref (new_texture); + + g_signal_emit (texture, texture_signals[LOAD_FINISHED], 0, NULL); + + g_object_notify_by_pspec (G_OBJECT (texture), obj_props[PROP_FILENAME]); + + return TRUE; +} + +/** + * clutter_texture_set_filter_quality: + * @texture: a #ClutterTexture + * @filter_quality: new filter quality value + * + * Sets the filter quality when scaling a texture. The quality is an + * enumeration currently the following values are supported: + * %CLUTTER_TEXTURE_QUALITY_LOW which is fast but only uses nearest neighbour + * interpolation. %CLUTTER_TEXTURE_QUALITY_MEDIUM which is computationally a + * bit more expensive (bilinear interpolation), and + * %CLUTTER_TEXTURE_QUALITY_HIGH which uses extra texture memory resources to + * improve scaled down rendering as well (by using mipmaps). The default value + * is %CLUTTER_TEXTURE_QUALITY_MEDIUM. + * + * Since: 0.8 + * + * Deprecated: 1.12: Use #ClutterImage and clutter_actor_set_content_scaling_filters() + * instead + */ +void +clutter_texture_set_filter_quality (ClutterTexture *texture, + ClutterTextureQuality filter_quality) +{ + ClutterTexturePrivate *priv; + ClutterTextureQuality old_quality; + + g_return_if_fail (CLUTTER_IS_TEXTURE (texture)); + + priv = texture->priv; + + old_quality = clutter_texture_get_filter_quality (texture); + + if (filter_quality != old_quality) + { + gint min_filter, mag_filter; + + min_filter = mag_filter = COGL_PIPELINE_FILTER_LINEAR; + clutter_texture_quality_to_filters (filter_quality, + &min_filter, + &mag_filter); + + cogl_pipeline_set_layer_filters (priv->pipeline, 0, + min_filter, mag_filter); + + clutter_actor_queue_redraw (CLUTTER_ACTOR (texture)); + + g_object_notify_by_pspec (G_OBJECT (texture), obj_props[PROP_FILTER_QUALITY]); + } +} + +/** + * clutter_texture_get_filter_quality: + * @texture: A #ClutterTexture + * + * Gets the filter quality used when scaling a texture. + * + * Return value: The filter quality value. + * + * Since: 0.8 + * + * Deprecated: 1.12: Use #ClutterImage and clutter_actor_get_content_scaling_filters() + * instead + */ +ClutterTextureQuality +clutter_texture_get_filter_quality (ClutterTexture *texture) +{ + ClutterTexturePrivate *priv; + int layer_index; + CoglPipelineFilter min_filter, mag_filter; + int i; + + g_return_val_if_fail (CLUTTER_IS_TEXTURE (texture), 0); + + priv = texture->priv; + + if (get_first_layer_index (priv->pipeline, &layer_index)) + { + min_filter = cogl_pipeline_get_layer_min_filter (priv->pipeline, + layer_index); + mag_filter = cogl_pipeline_get_layer_mag_filter (priv->pipeline, + layer_index); + } + else + return CLUTTER_TEXTURE_QUALITY_MEDIUM; + + 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; + + /* Unknown filter combination */ + return CLUTTER_TEXTURE_QUALITY_LOW; +} + +/** + * clutter_texture_get_max_tile_waste: + * @texture: A #ClutterTexture + * + * Gets the maximum waste that will be used when creating a texture or + * -1 if slicing is disabled. + * + * Return value: The maximum waste or -1 if the texture waste is + * unlimited. + * + * Since: 0.8 + * + * Deprecated: 1.12: No replacement is available + */ +gint +clutter_texture_get_max_tile_waste (ClutterTexture *texture) +{ + ClutterTexturePrivate *priv; + CoglHandle cogl_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 == NULL) + return priv->no_slice ? -1 : COGL_TEXTURE_MAX_WASTE; + else + return cogl_texture_get_max_waste (cogl_texture); +} + +/** + * clutter_texture_new_from_file: + * @filename: The name of an image file to load. + * @error: Return locatoin for an error. + * + * Creates a new ClutterTexture actor to display the image contained a + * file. If the image failed to load then NULL is returned and @error + * is set. + * + * Return value: A newly created #ClutterTexture object or NULL on + * error. + * + * Since: 0.8 + * + * Deprecated: 1.12: No direct replacement is available. Use #ClutterImage + * and platform-specific image loading API, like GdkPixbuf, instead + */ +ClutterActor* +clutter_texture_new_from_file (const gchar *filename, + GError **error) +{ + ClutterActor *texture = clutter_texture_new (); + + if (!clutter_texture_set_from_file (CLUTTER_TEXTURE (texture), + filename, error)) + { + g_object_ref_sink (texture); + g_object_unref (texture); + + return NULL; + } + else + return texture; +} + +/** + * clutter_texture_new: + * + * Creates a new empty #ClutterTexture object. + * + * Return value: A newly created #ClutterTexture object. + * + * Deprecated: 1.12: Use #ClutterImage instead + */ +ClutterActor * +clutter_texture_new (void) +{ + return g_object_new (CLUTTER_TYPE_TEXTURE, NULL); +} + +/** + * clutter_texture_get_base_size: + * @texture: a #ClutterTexture + * @width: (out): return location for the width, or %NULL + * @height: (out): return location for the height, or %NULL + * + * Gets the size in pixels of the untransformed underlying image + * + * Deprecated: 1.12: Use #ClutterImage and clutter_content_get_preferred_size() + * instead + */ +void +clutter_texture_get_base_size (ClutterTexture *texture, + gint *width, + gint *height) +{ + g_return_if_fail (CLUTTER_IS_TEXTURE (texture)); + + if (width) + *width = texture->priv->image_width; + + if (height) + *height = texture->priv->image_height; +} + +/** + * clutter_texture_set_area_from_rgb_data: + * @texture: A #ClutterTexture + * @data: (array): Image data in RGB type colorspace. + * @has_alpha: Set to TRUE if image data has an alpha channel. + * @x: X coordinate of upper left corner of region to update. + * @y: Y coordinate of upper left corner of region to update. + * @width: Width in pixels of region to update. + * @height: Height in pixels of region to update. + * @rowstride: Distance in bytes between row starts on source buffer. + * @bpp: bytes per pixel (Currently only 3 and 4 supported, + * depending on @has_alpha) + * @flags: #ClutterTextureFlags + * @error: return location for a #GError, or %NULL + * + * Updates a sub-region of the pixel data in a #ClutterTexture. + * + * Return value: %TRUE on success, %FALSE on failure. + * + * Since: 0.6 + * + * Deprecated: 1.12: Use #ClutterImage and clutter_image_set_area() instead + */ +gboolean +clutter_texture_set_area_from_rgb_data (ClutterTexture *texture, + const guchar *data, + gboolean has_alpha, + gint x, + gint y, + gint width, + gint height, + gint rowstride, + gint bpp, + ClutterTextureFlags flags, + GError **error) +{ + CoglPixelFormat source_format; + CoglHandle cogl_texture; + + if (!get_pixel_format_from_texture_flags (bpp, has_alpha, flags, + &source_format)) + { + return FALSE; + } + + /* 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 == NULL) + { + g_warning ("Failed to realize actor '%s'", + _clutter_actor_get_debug_name (CLUTTER_ACTOR (texture))); + return FALSE; + } + + if (!cogl_texture_set_region (cogl_texture, + 0, 0, + x, y, width, height, + width, height, + source_format, + rowstride, + data)) + { + g_set_error (error, CLUTTER_TEXTURE_ERROR, + CLUTTER_TEXTURE_ERROR_BAD_FORMAT, + _("Failed to load the image data")); + return FALSE; + } + + g_free (texture->priv->filename); + texture->priv->filename = NULL; + + /* rename signal */ + g_signal_emit (texture, texture_signals[PIXBUF_CHANGE], 0); + + clutter_actor_queue_redraw (CLUTTER_ACTOR (texture)); + + return TRUE; +} + +static void +on_fbo_source_size_change (GObject *object, + GParamSpec *param_spec, + ClutterTexture *texture) +{ + ClutterTexturePrivate *priv = texture->priv; + gfloat w, h; + ClutterActorBox box; + gboolean status; + + status = clutter_actor_get_paint_box (priv->fbo_source, &box); + if (status) + clutter_actor_box_get_size (&box, &w, &h); + + /* In the end we will size the framebuffer according to the paint + * box, but for code that does: + * tex = clutter_texture_new_from_actor (src); + * clutter_actor_get_size (tex, &width, &height); + * it seems more helpfull to return the src actor size if it has a + * degenerate paint box. The most likely reason it will have a + * degenerate paint box is simply that the src currently has no + * parent. */ + if (status == FALSE || w == 0 || h == 0) + clutter_actor_get_size (priv->fbo_source, &w, &h); + + /* We can't create a texture with a width or height of 0... */ + w = MAX (1, w); + h = MAX (1, h); + + if (w != priv->image_width || h != priv->image_height) + { + CoglTextureFlags flags = COGL_TEXTURE_NONE; + CoglHandle tex; + + /* tear down the FBO */ + if (priv->fbo_handle != NULL) + cogl_object_unref (priv->fbo_handle); + + texture_free_gl_resources (texture); + + priv->image_width = w; + priv->image_height = h; + + flags |= COGL_TEXTURE_NO_SLICING; + + tex = cogl_texture_new_with_size (MAX (priv->image_width, 1), + MAX (priv->image_height, 1), + flags, + COGL_PIXEL_FORMAT_RGBA_8888_PRE); + + cogl_pipeline_set_layer_texture (priv->pipeline, 0, tex); + + priv->fbo_handle = cogl_offscreen_new_to_texture (tex); + + /* The pipeline now has a reference to the texture so it will + stick around */ + cogl_object_unref (tex); + + if (priv->fbo_handle == NULL) + { + g_warning ("%s: Offscreen texture creation failed", G_STRLOC); + return; + } + + clutter_actor_set_size (CLUTTER_ACTOR (texture), w, h); + } +} + +static void +on_fbo_parent_change (ClutterActor *actor, + ClutterActor *old_parent, + ClutterTexture *texture) +{ + ClutterActor *parent = CLUTTER_ACTOR(texture); + + while ((parent = clutter_actor_get_parent (parent)) != NULL) + { + if (parent == actor) + { + g_warning ("Offscreen texture is ancestor of source!"); + /* Desperate but will avoid infinite loops */ + clutter_actor_remove_child (parent, actor); + } + } +} + +static void +fbo_source_queue_redraw_cb (ClutterActor *source, + ClutterActor *origin, + ClutterTexture *texture) +{ + clutter_actor_queue_redraw (CLUTTER_ACTOR (texture)); +} + +static void +fbo_source_queue_relayout_cb (ClutterActor *source, + ClutterTexture *texture) +{ + clutter_actor_queue_relayout (CLUTTER_ACTOR (texture)); +} + +/** + * clutter_texture_new_from_actor: + * @actor: A source #ClutterActor + * + * Creates a new #ClutterTexture object with its source a prexisting + * actor (and associated children). The textures content will contain + * 'live' redirected output of the actors scene. + * + * Note this function is intented as a utility call for uniformly applying + * shaders to groups and other potential visual effects. It requires that + * the %CLUTTER_FEATURE_OFFSCREEN feature is supported by the current backend + * and the target system. + * + * Some tips on usage: + * + * - The source actor must be visible + * - The source actor must have a parent in order for it to be + * allocated a size from the layouting mechanism. If the source + * actor does not have a parent when this function is called then + * the ClutterTexture will adopt it and allocate it at its + * preferred size. Using this you can clone an actor that is + * otherwise not displayed. Because of this feature if you do + * intend to display the source actor then you must make sure that + * the actor is parented before calling + * clutter_texture_new_from_actor() or that you unparent it before + * adding it to a container. + * - When getting the image for the clone texture, Clutter + * will attempt to render the source actor exactly as it would + * appear if it was rendered on screen. The source actor's parent + * transformations are taken into account. Therefore if your + * source actor is rotated along the X or Y axes so that it has + * some depth, the texture will appear differently depending on + * the on-screen location of the source actor. While painting the + * source actor, Clutter will set up a temporary asymmetric + * perspective matrix as the projection matrix so that the source + * actor will be projected as if a small section of the screen was + * being viewed. Before version 0.8.2, an orthogonal identity + * projection was used which meant that the source actor would be + * clipped if any part of it was not on the zero Z-plane. + * - Avoid reparenting the source with the created texture. + * - A group can be padded with a transparent rectangle as to + * provide a border to contents for shader output (blurring text + * for example). + * - The texture will automatically resize to contain a further + * transformed source. However, this involves overhead and can be + * avoided by placing the source actor in a bounding group + * sized large enough to contain any child tranformations. + * - Uploading pixel data to the texture (e.g by using + * clutter_texture_set_from_file()) will destroy the offscreen texture + * data and end redirection. + * - cogl_texture_get_data() with the handle returned by + * clutter_texture_get_cogl_texture() can be used to read the + * offscreen texture pixels into a pixbuf. + * + * Return value: A newly created #ClutterTexture object, or %NULL on failure. + * + * Since: 0.6 + * + * Deprecated: 1.8: Use the #ClutterOffscreenEffect and #ClutterShaderEffect + * directly on the intended #ClutterActor to replace the functionality of + * this function. + */ +ClutterActor * +clutter_texture_new_from_actor (ClutterActor *actor) +{ + ClutterTexture *texture; + ClutterTexturePrivate *priv; + gfloat w, h; + ClutterActorBox box; + gboolean status; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), NULL); + + if (clutter_feature_available (CLUTTER_FEATURE_OFFSCREEN) == FALSE) + return NULL; + + if (!CLUTTER_ACTOR_IS_REALIZED (actor)) + { + clutter_actor_realize (actor); + + if (!CLUTTER_ACTOR_IS_REALIZED (actor)) + return NULL; + } + + status = clutter_actor_get_paint_box (actor, &box); + if (status) + clutter_actor_box_get_size (&box, &w, &h); + + /* In the end we will size the framebuffer according to the paint + * box, but for code that does: + * tex = clutter_texture_new_from_actor (src); + * clutter_actor_get_size (tex, &width, &height); + * it seems more helpfull to return the src actor size if it has a + * degenerate paint box. The most likely reason it will have a + * degenerate paint box is simply that the src currently has no + * parent. */ + if (status == FALSE || w == 0 || h == 0) + clutter_actor_get_size (actor, &w, &h); + + /* We can't create a 0x0 fbo so always bump the size up to at least + * 1 */ + w = MAX (1, w); + h = MAX (1, h); + + /* Hopefully now were good.. */ + texture = g_object_new (CLUTTER_TYPE_TEXTURE, + "disable-slicing", TRUE, + NULL); + + priv = texture->priv; + + priv->fbo_source = g_object_ref_sink (actor); + + /* If the actor doesn't have a parent then claim it so that it will + get a size allocation during layout */ + if (clutter_actor_get_parent (actor) == NULL) + clutter_actor_add_child (CLUTTER_ACTOR (texture), actor); + + /* Connect up any signals which could change our underlying size */ + g_signal_connect (actor, + "notify::width", + G_CALLBACK(on_fbo_source_size_change), + texture); + g_signal_connect (actor, + "notify::height", + G_CALLBACK(on_fbo_source_size_change), + texture); + g_signal_connect (actor, + "notify::scale-x", + G_CALLBACK(on_fbo_source_size_change), + texture); + g_signal_connect (actor, + "notify::scale-y", + G_CALLBACK(on_fbo_source_size_change), + texture); + g_signal_connect (actor, + "notify::rotation-angle-x", + G_CALLBACK(on_fbo_source_size_change), + texture); + g_signal_connect (actor, + "notify::rotation-angle-y", + G_CALLBACK(on_fbo_source_size_change), + texture); + g_signal_connect (actor, + "notify::rotation-angle-z", + G_CALLBACK(on_fbo_source_size_change), + texture); + + g_signal_connect (actor, "queue-relayout", + G_CALLBACK (fbo_source_queue_relayout_cb), texture); + g_signal_connect (actor, "queue-redraw", + G_CALLBACK (fbo_source_queue_redraw_cb), texture); + + /* And a warning if the source becomes a child of the texture */ + g_signal_connect (actor, + "parent-set", + G_CALLBACK(on_fbo_parent_change), + texture); + + priv->image_width = w; + priv->image_height = h; + + clutter_actor_set_size (CLUTTER_ACTOR (texture), + priv->image_width, + priv->image_height); + + return CLUTTER_ACTOR (texture); +} + +static void +texture_fbo_free_resources (ClutterTexture *texture) +{ + ClutterTexturePrivate *priv; + + priv = texture->priv; + + if (priv->fbo_source != NULL) + { + ClutterActor *parent; + + parent = clutter_actor_get_parent (priv->fbo_source); + + /* If we parented the texture then unparent it again so that it + will lose the reference */ + if (parent == CLUTTER_ACTOR (texture)) + clutter_actor_remove_child (parent, priv->fbo_source); + + g_signal_handlers_disconnect_by_func + (priv->fbo_source, + G_CALLBACK(on_fbo_parent_change), + texture); + + g_signal_handlers_disconnect_by_func + (priv->fbo_source, + G_CALLBACK(on_fbo_source_size_change), + texture); + + g_signal_handlers_disconnect_by_func + (priv->fbo_source, + G_CALLBACK(fbo_source_queue_relayout_cb), + texture); + + g_signal_handlers_disconnect_by_func + (priv->fbo_source, + G_CALLBACK(fbo_source_queue_redraw_cb), + texture); + + g_object_unref (priv->fbo_source); + + priv->fbo_source = NULL; + } + + if (priv->fbo_handle != NULL) + { + cogl_object_unref (priv->fbo_handle); + priv->fbo_handle = NULL; + } +} + +/** + * clutter_texture_set_sync_size: + * @texture: a #ClutterTexture + * @sync_size: %TRUE if the texture should have the same size of the + * underlying image data + * + * Sets whether @texture should have the same preferred size as the + * underlying image data. + * + * Since: 1.0 + * + * Deprecated: 1.12: No replacement is available. A #ClutterActor using + * #ClutterImage with a %CLUTTER_REQUEST_CONTENT_SIZE request mode + * will automatically bind the preferred size of the content to the + * preferred size of the actor + */ +void +clutter_texture_set_sync_size (ClutterTexture *texture, + gboolean sync_size) +{ + ClutterTexturePrivate *priv; + + g_return_if_fail (CLUTTER_IS_TEXTURE (texture)); + + priv = texture->priv; + + if (priv->sync_actor_size != sync_size) + { + priv->sync_actor_size = sync_size; + + clutter_actor_queue_relayout (CLUTTER_ACTOR (texture)); + + g_object_notify_by_pspec (G_OBJECT (texture), obj_props[PROP_SYNC_SIZE]); + } +} + +/** + * clutter_texture_get_sync_size: + * @texture: a #ClutterTexture + * + * Retrieves the value set with clutter_texture_set_sync_size() + * + * Return value: %TRUE if the #ClutterTexture should have the same + * preferred size of the underlying image data + * + * Since: 1.0 + * + * Deprecated: 1.12: There is no direct replacement + */ +gboolean +clutter_texture_get_sync_size (ClutterTexture *texture) +{ + g_return_val_if_fail (CLUTTER_IS_TEXTURE (texture), FALSE); + + return texture->priv->sync_actor_size; +} + +/** + * clutter_texture_set_repeat: + * @texture: a #ClutterTexture + * @repeat_x: %TRUE if the texture should repeat horizontally + * @repeat_y: %TRUE if the texture should repeat vertically + * + * Sets whether the @texture should repeat horizontally or + * vertically when the actor size is bigger than the image size + * + * Since: 1.0 + * + * Deprecated: 1.12: Use #ClutterImage and clutter_actor_set_content_repeat() + * instead + */ +void +clutter_texture_set_repeat (ClutterTexture *texture, + gboolean repeat_x, + gboolean repeat_y) +{ + ClutterTexturePrivate *priv; + gboolean changed = FALSE; + + g_return_if_fail (CLUTTER_IS_TEXTURE (texture)); + + priv = texture->priv; + + g_object_freeze_notify (G_OBJECT (texture)); + + if (priv->repeat_x != repeat_x) + { + priv->repeat_x = repeat_x; + + g_object_notify_by_pspec (G_OBJECT (texture), obj_props[PROP_REPEAT_X]); + + changed = TRUE; + } + + if (priv->repeat_y != repeat_y) + { + priv->repeat_y = repeat_y; + + g_object_notify_by_pspec (G_OBJECT (texture), obj_props[PROP_REPEAT_Y]); + + changed = TRUE; + } + + if (changed) + clutter_actor_queue_redraw (CLUTTER_ACTOR (texture)); + + g_object_thaw_notify (G_OBJECT (texture)); +} + +/** + * clutter_texture_get_repeat: + * @texture: a #ClutterTexture + * @repeat_x: (out): return location for the horizontal repeat + * @repeat_y: (out): return location for the vertical repeat + * + * Retrieves the horizontal and vertical repeat values set + * using clutter_texture_set_repeat() + * + * Since: 1.0 + * + * Deprecated: 1.12: Use #ClutterImage and clutter_actor_get_content_repeat() + * instead + */ +void +clutter_texture_get_repeat (ClutterTexture *texture, + gboolean *repeat_x, + gboolean *repeat_y) +{ + g_return_if_fail (CLUTTER_IS_TEXTURE (texture)); + + if (repeat_x != NULL) + *repeat_x = texture->priv->repeat_x; + + if (repeat_y != NULL) + *repeat_y = texture->priv->repeat_y; +} + +/** + * clutter_texture_set_keep_aspect_ratio: + * @texture: a #ClutterTexture + * @keep_aspect: %TRUE to maintain aspect ratio + * + * Sets whether @texture should have a preferred size maintaining + * the aspect ratio of the underlying image + * + * Since: 1.0 + * + * Deprecated: 1.12: Use #ClutterImage and clutter_actor_set_content_gravity() + * with %CLUTTER_CONTENT_GRAVITY_RESIZE_ASPECT instead + */ +void +clutter_texture_set_keep_aspect_ratio (ClutterTexture *texture, + gboolean keep_aspect) +{ + ClutterTexturePrivate *priv; + + g_return_if_fail (CLUTTER_IS_TEXTURE (texture)); + + priv = texture->priv; + + if (priv->keep_aspect_ratio != keep_aspect) + { + priv->keep_aspect_ratio = keep_aspect; + + clutter_actor_queue_relayout (CLUTTER_ACTOR (texture)); + + g_object_notify_by_pspec (G_OBJECT (texture), obj_props[PROP_KEEP_ASPECT_RATIO]); + } +} + +/** + * clutter_texture_get_keep_aspect_ratio: + * @texture: a #ClutterTexture + * + * Retrieves the value set using clutter_texture_set_keep_aspect_ratio() + * + * Return value: %TRUE if the #ClutterTexture should maintain the + * aspect ratio of the underlying image + * + * Since: 1.0 + * + * Deprecated: 1.12: Use #ClutterImage and clutter_actor_get_content_gravity() + * instead + */ +gboolean +clutter_texture_get_keep_aspect_ratio (ClutterTexture *texture) +{ + g_return_val_if_fail (CLUTTER_IS_TEXTURE (texture), FALSE); + + return texture->priv->keep_aspect_ratio; +} + +/** + * clutter_texture_set_load_async: + * @texture: a #ClutterTexture + * @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 + * from disk asynchronously. Setting @load_async to %TRUE will make + * clutter_texture_set_from_file() return immediately. + * + * See the #ClutterTexture:load-async property documentation, and + * clutter_texture_set_load_data_async(). + * + * Since: 1.0 + * + * Deprecated: 1.12: There is no direct replacement for this function. + * Use #ClutterImage and platform-specific API for loading image data + * asynchronously, like GdkPixbuf + */ +void +clutter_texture_set_load_async (ClutterTexture *texture, + gboolean load_async) +{ + ClutterTexturePrivate *priv; + + g_return_if_fail (CLUTTER_IS_TEXTURE (texture)); + + priv = texture->priv; + + load_async = !!load_async; + + if (priv->load_async_set != load_async) + { + priv->load_data_async = load_async; + priv->load_size_async = load_async; + + priv->load_async_set = load_async; + + g_object_notify_by_pspec (G_OBJECT (texture), obj_props[PROP_LOAD_ASYNC]); + g_object_notify_by_pspec (G_OBJECT (texture), obj_props[PROP_LOAD_DATA_ASYNC]); + } +} + +/** + * clutter_texture_get_load_async: + * @texture: a #ClutterTexture + * + * Retrieves the value set using clutter_texture_set_load_async() + * + * Return value: %TRUE if the #ClutterTexture should load the data from + * disk asynchronously + * + * Since: 1.0 + * + * Deprecated: 1.12: There is no direct replacement for this function + */ +gboolean +clutter_texture_get_load_async (ClutterTexture *texture) +{ + g_return_val_if_fail (CLUTTER_IS_TEXTURE (texture), FALSE); + + return texture->priv->load_async_set; +} + +/** + * clutter_texture_set_load_data_async: + * @texture: a #ClutterTexture + * @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 + * from disk asynchronously. Setting @load_async to %TRUE will make + * clutter_texture_set_from_file() block until the #ClutterTexture has + * determined the width and height of the image data. + * + * See the #ClutterTexture:load-async property documentation, and + * clutter_texture_set_load_async(). + * + * Since: 1.0 + * + * Deprecated: 1.12: There is no direct replacement for this function. + * Use #ClutterImage and platform-specific API for loading image data + * asynchronously, like GdkPixbuf + */ +void +clutter_texture_set_load_data_async (ClutterTexture *texture, + gboolean load_async) +{ + ClutterTexturePrivate *priv; + + g_return_if_fail (CLUTTER_IS_TEXTURE (texture)); + + priv = texture->priv; + + if (priv->load_data_async != load_async) + { + /* load-data-async always unsets load-size-async */ + priv->load_data_async = load_async; + priv->load_size_async = FALSE; + + priv->load_async_set = load_async; + + g_object_notify_by_pspec (G_OBJECT (texture), obj_props[PROP_LOAD_ASYNC]); + g_object_notify_by_pspec (G_OBJECT (texture), obj_props[PROP_LOAD_DATA_ASYNC]); + } +} + +/** + * clutter_texture_get_load_data_async: + * @texture: a #ClutterTexture + * + * Retrieves the value set by clutter_texture_set_load_data_async() + * + * Return value: %TRUE if the #ClutterTexture should load the image + * data from a file asynchronously + * + * Since: 1.0 + * + * Deprecated: 1.12: There is no direct replacement for this function + */ +gboolean +clutter_texture_get_load_data_async (ClutterTexture *texture) +{ + g_return_val_if_fail (CLUTTER_IS_TEXTURE (texture), FALSE); + + return texture->priv->load_async_set && + texture->priv->load_data_async; +} + +/** + * clutter_texture_set_pick_with_alpha: + * @texture: a #ClutterTexture + * @pick_with_alpha: %TRUE if the alpha channel should affect the + * picking shape + * + * Sets whether @texture should have it's shape defined by the alpha + * channel when picking. + * + * Be aware that this is a bit more costly than the default picking + * due to the texture lookup, extra test against the alpha value and + * the fact that it will also interrupt the batching of geometry done + * internally. + * + * Also there is currently no control over the threshold used to + * determine what value of alpha is considered pickable, and so only + * fully opaque parts of the texture will react to picking. + * + * Since: 1.4 + * + * Deprecated: 1.12: There is no direct replacement for this function + */ +void +clutter_texture_set_pick_with_alpha (ClutterTexture *texture, + gboolean pick_with_alpha) +{ + ClutterTexturePrivate *priv; + + g_return_if_fail (CLUTTER_IS_TEXTURE (texture)); + + priv = texture->priv; + + if (priv->pick_with_alpha == pick_with_alpha) + return; + + if (!pick_with_alpha && priv->pick_pipeline != NULL) + { + cogl_object_unref (priv->pick_pipeline); + priv->pick_pipeline = NULL; + } + + /* NB: the pick pipeline is created lazily when we first pick */ + priv->pick_with_alpha = pick_with_alpha; + + /* NB: actors are expected to call clutter_actor_queue_redraw when + * ever some state changes that will affect painting *or picking... + */ + clutter_actor_queue_redraw (CLUTTER_ACTOR (texture)); +} + +/** + * clutter_texture_get_pick_with_alpha: + * @texture: a #ClutterTexture + * + * Retrieves the value set by clutter_texture_set_load_data_async() + * + * Return value: %TRUE if the #ClutterTexture should define its shape + * using the alpha channel when picking. + * + * Since: 1.4 + * + * Deprecated: 1.12: There is no direct replacement for this function + */ +gboolean +clutter_texture_get_pick_with_alpha (ClutterTexture *texture) +{ + g_return_val_if_fail (CLUTTER_IS_TEXTURE (texture), FALSE); + + return texture->priv->pick_with_alpha ? TRUE : FALSE; +} + diff --git a/clutter/clutter/deprecated/clutter-texture.h b/clutter/clutter/deprecated/clutter-texture.h new file mode 100644 index 0000000..6e04943 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-texture.h @@ -0,0 +1,136 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 . + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_TEXTURE_DEPRECATED_H__ +#define __CLUTTER_TEXTURE_DEPRECATED_H__ + +#include + +G_BEGIN_DECLS + +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_image_new) +ClutterActor * clutter_texture_new (void); + +CLUTTER_DEPRECATED_IN_1_12_FOR(ClutterImage and platform-specific image loading) +ClutterActor * clutter_texture_new_from_file (const gchar *filename, + GError **error); + +CLUTTER_DEPRECATED_IN_1_12_FOR(ClutterImage and platform-specific image loading) +gboolean clutter_texture_set_from_file (ClutterTexture *texture, + const gchar *filename, + GError **error); +CLUTTER_DEPRECATED_IN_1_12_FOR(clutter_image_set_data) +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_DEPRECATED_IN_1_12_FOR(clutter_image_set_area) +gboolean clutter_texture_set_area_from_rgb_data (ClutterTexture *texture, + const guchar *data, + gboolean has_alpha, + gint x, + gint y, + gint width, + gint height, + gint rowstride, + gint bpp, + ClutterTextureFlags flags, + GError **error); +CLUTTER_DEPRECATED_IN_1_12_FOR(ClutterImage and clutter_content_get_preferred_size) +void clutter_texture_get_base_size (ClutterTexture *texture, + gint *width, + gint *height); +CLUTTER_DEPRECATED_IN_1_12_FOR(ClutterImage and clutter_actor_set_content_scaling_filters) +void clutter_texture_set_filter_quality (ClutterTexture *texture, + ClutterTextureQuality filter_quality); +CLUTTER_DEPRECATED_IN_1_12_FOR(ClutterImage and clutter_actor_get_content_scaling_filters) +ClutterTextureQuality clutter_texture_get_filter_quality (ClutterTexture *texture); +CLUTTER_DEPRECATED_IN_1_12 +CoglHandle clutter_texture_get_cogl_texture (ClutterTexture *texture); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_texture_set_cogl_texture (ClutterTexture *texture, + CoglHandle cogl_tex); +CLUTTER_DEPRECATED_IN_1_12 +CoglHandle clutter_texture_get_cogl_material (ClutterTexture *texture); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_texture_set_cogl_material (ClutterTexture *texture, + CoglHandle cogl_material); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_texture_set_sync_size (ClutterTexture *texture, + gboolean sync_size); +CLUTTER_DEPRECATED_IN_1_12 +gboolean clutter_texture_get_sync_size (ClutterTexture *texture); +CLUTTER_DEPRECATED_IN_1_12_FOR(ClutterImage and clutter_actor_set_content_repeat) +void clutter_texture_set_repeat (ClutterTexture *texture, + gboolean repeat_x, + gboolean repeat_y); +CLUTTER_DEPRECATED_IN_1_12_FOR(ClutterImage and clutter_actor_get_content_repeat) +void clutter_texture_get_repeat (ClutterTexture *texture, + gboolean *repeat_x, + gboolean *repeat_y); +CLUTTER_DEPRECATED_IN_1_12 +gint clutter_texture_get_max_tile_waste (ClutterTexture *texture); +CLUTTER_DEPRECATED_IN_1_12_FOR(ClutterImage and clutter_actor_set_content_gravity) +void clutter_texture_set_keep_aspect_ratio (ClutterTexture *texture, + gboolean keep_aspect); +CLUTTER_DEPRECATED_IN_1_12_FOR(ClutterImage and clutter_actor_get_content_gravity) +gboolean clutter_texture_get_keep_aspect_ratio (ClutterTexture *texture); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_texture_set_load_async (ClutterTexture *texture, + gboolean load_async); +CLUTTER_DEPRECATED_IN_1_12 +gboolean clutter_texture_get_load_async (ClutterTexture *texture); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_texture_set_load_data_async (ClutterTexture *texture, + gboolean load_async); +CLUTTER_DEPRECATED_IN_1_12 +gboolean clutter_texture_get_load_data_async (ClutterTexture *texture); +CLUTTER_DEPRECATED_IN_1_12 +void clutter_texture_set_pick_with_alpha (ClutterTexture *texture, + gboolean pick_with_alpha); +CLUTTER_DEPRECATED_IN_1_12 +gboolean clutter_texture_get_pick_with_alpha (ClutterTexture *texture); + +CLUTTER_DEPRECATED_IN_1_8_FOR(ClutterOffscreenEffect) +ClutterActor * clutter_texture_new_from_actor (ClutterActor *actor); + +CLUTTER_DEPRECATED_IN_1_10 +gboolean clutter_texture_set_from_yuv_data (ClutterTexture *texture, + const guchar *data, + gint width, + gint height, + ClutterTextureFlags flags, + GError **error); + +G_END_DECLS + +#endif /* __CLUTTER_TEXTURE_DEPRECATED_H__ */ diff --git a/clutter/clutter/deprecated/clutter-timeline.h b/clutter/clutter/deprecated/clutter-timeline.h new file mode 100644 index 0000000..e99c7df --- /dev/null +++ b/clutter/clutter/deprecated/clutter-timeline.h @@ -0,0 +1,41 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2012 Intel Corp + * + * 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 . + */ + +#ifndef __CLUTTER_TIMELINE_PRIVATE_H__ +#define __CLUTTER_TIMELINE_PRIVATE_H__ + +#include + +G_BEGIN_DECLS + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_timeline_new) +ClutterTimeline * clutter_timeline_clone (ClutterTimeline *timeline); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_timeline_set_repeat_count) +void clutter_timeline_set_loop (ClutterTimeline *timeline, + gboolean loop); + +CLUTTER_DEPRECATED_IN_1_10_FOR(clutter_timeline_get_repeat_count) +gboolean clutter_timeline_get_loop (ClutterTimeline *timeline); + +G_END_DECLS + +#endif /* __CLUTTER_TIMELINE_PRIVATE_H__ */ diff --git a/clutter/clutter/deprecated/clutter-timeout-interval.c b/clutter/clutter/deprecated/clutter-timeout-interval.c new file mode 100644 index 0000000..bb9f141 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-timeout-interval.c @@ -0,0 +1,142 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Neil Roberts + * + * 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 . + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS + +/* This file contains the common code to check whether an interval has + expired used in clutter-frame-source and clutter-timeout-pool. */ + +#include "clutter-timeout-interval.h" + +void +_clutter_timeout_interval_init (ClutterTimeoutInterval *interval, + guint fps) +{ +#if GLIB_CHECK_VERSION (2, 27, 3) + interval->start_time = g_get_monotonic_time () / 1000; +#else + { + GTimeVal start_time; + g_get_current_time (&start_time); + interval->start_time = start_time.tv_sec * 1000 + + start_time.tv_usec / 1000; + } +#endif + + interval->fps = fps; + interval->frame_count = 0; +} + +static gint64 +_clutter_timeout_interval_get_ticks (gint64 current_time, + ClutterTimeoutInterval *interval) +{ + return MAX (current_time - interval->start_time, 0); +} + +gboolean +_clutter_timeout_interval_prepare (gint64 current_time, + ClutterTimeoutInterval *interval, + gint *delay) +{ + gint elapsed_time, new_frame_num; + + elapsed_time = _clutter_timeout_interval_get_ticks (current_time, interval); + new_frame_num = elapsed_time * interval->fps / 1000; + + /* If time has gone backwards or the time since the last frame is + greater than the two frames worth then reset the time and do a + frame now */ + if (new_frame_num < interval->frame_count || + new_frame_num - interval->frame_count > 2) + { + /* Get the frame time rounded up to the nearest ms */ + guint frame_time = (1000 + interval->fps - 1) / interval->fps; + + /* Reset the start time */ + interval->start_time = current_time; + + /* Move the start time as if one whole frame has elapsed */ + interval->start_time -= frame_time; + + interval->frame_count = 0; + + if (delay) + *delay = 0; + + return TRUE; + } + else if (new_frame_num > interval->frame_count) + { + if (delay) + *delay = 0; + + return TRUE; + } + else + { + if (delay) + *delay = ((interval->frame_count + 1) * 1000 / interval->fps + - elapsed_time); + + return FALSE; + } +} + +gboolean +_clutter_timeout_interval_dispatch (ClutterTimeoutInterval *interval, + GSourceFunc callback, + gpointer user_data) +{ + if ((* callback) (user_data)) + { + interval->frame_count++; + + return TRUE; + } + + return FALSE; +} + +gint +_clutter_timeout_interval_compare_expiration (const ClutterTimeoutInterval *a, + const ClutterTimeoutInterval *b) +{ + guint a_delay = 1000 / a->fps; + guint b_delay = 1000 / b->fps; + gint64 b_difference; + gint comparison; + + b_difference = a->start_time - b->start_time; + + comparison = ((gint) ((a->frame_count + 1) * a_delay) + - (gint) ((b->frame_count + 1) * b_delay + b_difference)); + + return (comparison < 0 ? -1 + : comparison > 0 ? 1 + : 0); +} diff --git a/clutter/clutter/deprecated/clutter-timeout-interval.h b/clutter/clutter/deprecated/clutter-timeout-interval.h new file mode 100644 index 0000000..57df959 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-timeout-interval.h @@ -0,0 +1,58 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Neil Roberts + * + * 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 . + */ + +#ifndef __CLUTTER_TIMEOUT_INTERVAL_H__ +#define __CLUTTER_TIMEOUT_INTERVAL_H__ + +#include + +G_BEGIN_DECLS + +typedef struct _ClutterTimeoutInterval ClutterTimeoutInterval; + +struct _ClutterTimeoutInterval +{ + /* milliseconds */ + gint64 start_time; + + guint frame_count; + guint fps; +}; + +void _clutter_timeout_interval_init (ClutterTimeoutInterval *interval, + guint fps); + +gboolean _clutter_timeout_interval_prepare (gint64 current_time, + ClutterTimeoutInterval *interval, + gint *delay); + +gboolean _clutter_timeout_interval_dispatch (ClutterTimeoutInterval *interval, + GSourceFunc callback, + gpointer user_data); + +gint _clutter_timeout_interval_compare_expiration (const ClutterTimeoutInterval *a, + const ClutterTimeoutInterval *b); + +G_END_DECLS + +#endif /* __CLUTTER_TIMEOUT_INTERVAL_H__ */ diff --git a/clutter/clutter/deprecated/clutter-timeout-pool.c b/clutter/clutter/deprecated/clutter-timeout-pool.c new file mode 100644 index 0000000..21b3543 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-timeout-pool.c @@ -0,0 +1,500 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + * + * ClutterTimeoutPool: pool of timeout functions using the same slice of + * the GLib main loop + * + * Author: Emmanuele Bassi + * + * Based on similar code by Tristan van Berkom + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include "deprecated/clutter-main.h" + +#include "clutter-timeout-pool.h" + +#include "clutter-debug.h" +#include "clutter-timeout-interval.h" + +typedef struct _ClutterTimeout ClutterTimeout; +typedef enum { + CLUTTER_TIMEOUT_NONE = 0, + CLUTTER_TIMEOUT_READY = 1 << 1 +} ClutterTimeoutFlags; + +struct _ClutterTimeout +{ + guint id; + ClutterTimeoutFlags flags; + gint refcount; + + ClutterTimeoutInterval interval; + + GSourceFunc func; + gpointer data; + GDestroyNotify notify; +}; + +struct _ClutterTimeoutPool +{ + GSource source; + + guint next_id; + + GList *timeouts; + GList *dispatched_timeouts; + + gint ready; + + guint id; +}; + +#define TIMEOUT_READY(timeout) (timeout->flags & CLUTTER_TIMEOUT_READY) + +static gboolean clutter_timeout_pool_prepare (GSource *source, + gint *next_timeout); +static gboolean clutter_timeout_pool_check (GSource *source); +static gboolean clutter_timeout_pool_dispatch (GSource *source, + GSourceFunc callback, + gpointer data); +static void clutter_timeout_pool_finalize (GSource *source); + +static GSourceFuncs clutter_timeout_pool_funcs = +{ + clutter_timeout_pool_prepare, + clutter_timeout_pool_check, + clutter_timeout_pool_dispatch, + clutter_timeout_pool_finalize +}; + +static gint +clutter_timeout_sort (gconstpointer a, + gconstpointer b) +{ + const ClutterTimeout *t_a = a; + const ClutterTimeout *t_b = b; + + /* Keep 'ready' timeouts at the front */ + if (TIMEOUT_READY (t_a)) + return -1; + + if (TIMEOUT_READY (t_b)) + return 1; + + return _clutter_timeout_interval_compare_expiration (&t_a->interval, + &t_b->interval); +} + +static gint +clutter_timeout_find_by_id (gconstpointer a, + gconstpointer b) +{ + const ClutterTimeout *t_a = a; + + return t_a->id == GPOINTER_TO_UINT (b) ? 0 : 1; +} + +static ClutterTimeout * +clutter_timeout_new (guint fps) +{ + ClutterTimeout *timeout; + + timeout = g_slice_new0 (ClutterTimeout); + _clutter_timeout_interval_init (&timeout->interval, fps); + timeout->flags = CLUTTER_TIMEOUT_NONE; + timeout->refcount = 1; + + return timeout; +} + +static gboolean +clutter_timeout_prepare (ClutterTimeoutPool *pool, + ClutterTimeout *timeout, + gint *next_timeout) +{ + GSource *source = (GSource *) pool; + gint64 now; + +#if GLIB_CHECK_VERSION (2, 27, 3) + now = g_source_get_time (source) / 1000; +#else + { + GTimeVal source_time; + g_source_get_current_time (source, &source_time); + now = source_time.tv_sec * 1000 + source_time.tv_usec / 1000; + } +#endif + + return _clutter_timeout_interval_prepare (now, + &timeout->interval, + next_timeout); +} + +/* ref and unref are always called under the main Clutter lock, so there + * is not need for us to use g_atomic_int_* API. + */ + +static ClutterTimeout * +clutter_timeout_ref (ClutterTimeout *timeout) +{ + g_return_val_if_fail (timeout != NULL, timeout); + g_return_val_if_fail (timeout->refcount > 0, timeout); + + timeout->refcount += 1; + + return timeout; +} + +static void +clutter_timeout_unref (ClutterTimeout *timeout) +{ + g_return_if_fail (timeout != NULL); + g_return_if_fail (timeout->refcount > 0); + + timeout->refcount -= 1; + + if (timeout->refcount == 0) + { + if (timeout->notify) + timeout->notify (timeout->data); + + g_slice_free (ClutterTimeout, timeout); + } +} + +static void +clutter_timeout_free (ClutterTimeout *timeout) +{ + if (G_LIKELY (timeout)) + { + if (timeout->notify) + timeout->notify (timeout->data); + + g_slice_free (ClutterTimeout, timeout); + } +} + +static gboolean +clutter_timeout_pool_prepare (GSource *source, + gint *next_timeout) +{ + ClutterTimeoutPool *pool = (ClutterTimeoutPool *) source; + GList *l = pool->timeouts; + + /* the pool is ready if the first timeout is ready */ + if (l && l->data) + { + ClutterTimeout *timeout = l->data; + return clutter_timeout_prepare (pool, timeout, next_timeout); + } + else + { + *next_timeout = -1; + return FALSE; + } +} + +static gboolean +clutter_timeout_pool_check (GSource *source) +{ + ClutterTimeoutPool *pool = (ClutterTimeoutPool *) source; + GList *l; + + clutter_threads_enter (); + + for (l = pool->timeouts; l; l = l->next) + { + ClutterTimeout *timeout = l->data; + + /* since the timeouts are sorted by expiration, as soon + * as we get a check returning FALSE we know that the + * following timeouts are not expiring, so we break as + * soon as possible + */ + if (clutter_timeout_prepare (pool, timeout, NULL)) + { + timeout->flags |= CLUTTER_TIMEOUT_READY; + pool->ready += 1; + } + else + break; + } + + clutter_threads_leave (); + + return (pool->ready > 0); +} + +static gboolean +clutter_timeout_pool_dispatch (GSource *source, + GSourceFunc func, + gpointer data) +{ + ClutterTimeoutPool *pool = (ClutterTimeoutPool *) source; + GList *dispatched_timeouts; + + /* the main loop might have predicted this, so we repeat the + * check for ready timeouts. + */ + if (!pool->ready) + clutter_timeout_pool_check (source); + + clutter_threads_enter (); + + /* Iterate by moving the actual start of the list along so that it + * can cope with adds and removes while a timeout is being dispatched + */ + while (pool->timeouts && pool->timeouts->data && pool->ready-- > 0) + { + ClutterTimeout *timeout = pool->timeouts->data; + GList *l; + + /* One of the ready timeouts may have been removed during dispatch, + * in which case pool->ready will be wrong, but the ready timeouts + * are always kept at the start of the list so we can stop once + * we've reached the first non-ready timeout + */ + if (!(TIMEOUT_READY (timeout))) + break; + + /* Add a reference to the timeout so it can't disappear + * while it's being dispatched + */ + clutter_timeout_ref (timeout); + + timeout->flags &= ~CLUTTER_TIMEOUT_READY; + + /* Move the list node to a list of dispatched timeouts */ + l = pool->timeouts; + if (l->next) + l->next->prev = NULL; + + pool->timeouts = l->next; + + if (pool->dispatched_timeouts) + pool->dispatched_timeouts->prev = l; + + l->prev = NULL; + l->next = pool->dispatched_timeouts; + pool->dispatched_timeouts = l; + + if (!_clutter_timeout_interval_dispatch (&timeout->interval, + timeout->func, timeout->data)) + { + /* The timeout may have already been removed, but nothing + * can be added to the dispatched_timeout list except in this + * function so it will always either be at the head of the + * dispatched list or have been removed + */ + if (pool->dispatched_timeouts && + pool->dispatched_timeouts->data == timeout) + { + pool->dispatched_timeouts = + g_list_delete_link (pool->dispatched_timeouts, + pool->dispatched_timeouts); + + /* Remove the reference that was held by it being in the list */ + clutter_timeout_unref (timeout); + } + } + + clutter_timeout_unref (timeout); + } + + /* Re-insert the dispatched timeouts in sorted order */ + dispatched_timeouts = pool->dispatched_timeouts; + while (dispatched_timeouts) + { + ClutterTimeout *timeout = dispatched_timeouts->data; + GList *next = dispatched_timeouts->next; + + if (timeout) + pool->timeouts = g_list_insert_sorted (pool->timeouts, timeout, + clutter_timeout_sort); + + dispatched_timeouts = next; + } + + g_list_free (pool->dispatched_timeouts); + pool->dispatched_timeouts = NULL; + + pool->ready = 0; + + clutter_threads_leave (); + + return TRUE; +} + +static void +clutter_timeout_pool_finalize (GSource *source) +{ + ClutterTimeoutPool *pool = (ClutterTimeoutPool *) source; + + /* force destruction */ + g_list_foreach (pool->timeouts, (GFunc) clutter_timeout_free, NULL); + g_list_free (pool->timeouts); +} + +/** + * clutter_timeout_pool_new: + * @priority: the priority of the timeout pool. Typically this will + * be #G_PRIORITY_DEFAULT + * + * Creates a new timeout pool source. A timeout pool should be used when + * multiple timeout functions, running at the same priority, are needed and + * the g_timeout_add() API might lead to starvation of the time slice of + * the main loop. A timeout pool allocates a single time slice of the main + * loop and runs every timeout function inside it. The timeout pool is + * always sorted, so that the extraction of the next timeout function is + * a constant time operation. + * + * Return value: the newly created #ClutterTimeoutPool. The created pool + * is owned by the GLib default context and will be automatically + * destroyed when the context is destroyed. It is possible to force + * the destruction of the timeout pool using g_source_destroy() + * + * Since: 0.4 + * + * Deprecated: 1.6: There is no direct replacement for this API + */ +ClutterTimeoutPool * +clutter_timeout_pool_new (gint priority) +{ + ClutterTimeoutPool *pool; + GSource *source; + + source = g_source_new (&clutter_timeout_pool_funcs, + sizeof (ClutterTimeoutPool)); + if (!source) + return NULL; + + g_source_set_name (source, "Clutter timeout pool"); + + if (priority != G_PRIORITY_DEFAULT) + g_source_set_priority (source, priority); + + pool = (ClutterTimeoutPool *) source; + pool->next_id = 1; + pool->id = g_source_attach (source, NULL); + + /* let the default GLib context manage the pool */ + g_source_unref (source); + + return pool; +} + +/** + * clutter_timeout_pool_add: + * @pool: a #ClutterTimeoutPool + * @fps: the time between calls to the function, in frames per second + * @func: function to call + * @data: (closure): data to pass to the function, or %NULL + * @notify: function to call when the timeout is removed, or %NULL + * + * Sets a function to be called at regular intervals, and puts it inside + * the @pool. The function is repeatedly called until it returns %FALSE, + * at which point the timeout is automatically destroyed and the function + * won't be called again. If @notify is not %NULL, the @notify function + * will be called. The first call to @func will be at the end of @interval. + * + * Since Clutter 0.8 this will try to compensate for delays. For + * example, if @func takes half the interval time to execute then the + * function will be called again half the interval time after it + * finished. Before version 0.8 it would not fire until a full + * interval after the function completes so the delay between calls + * would be @interval * 1.5. This function does not however try to + * invoke the function multiple times to catch up missing frames if + * @func takes more than @interval ms to execute. + * + * Return value: the ID (greater than 0) of the timeout inside the pool. + * Use clutter_timeout_pool_remove() to stop the timeout. + * + * Since: 0.4 + * + * Deprecated: 1.6: There is no direct replacement for this API + */ +guint +clutter_timeout_pool_add (ClutterTimeoutPool *pool, + guint fps, + GSourceFunc func, + gpointer data, + GDestroyNotify notify) +{ + ClutterTimeout *timeout; + guint retval = 0; + + timeout = clutter_timeout_new (fps); + + retval = timeout->id = pool->next_id++; + + timeout->func = func; + timeout->data = data; + timeout->notify = notify; + + pool->timeouts = g_list_insert_sorted (pool->timeouts, timeout, + clutter_timeout_sort); + + return retval; +} + +/** + * clutter_timeout_pool_remove: + * @pool: a #ClutterTimeoutPool + * @id_: the id of the timeout to remove + * + * Removes a timeout function with @id_ from the timeout pool. The id + * is the same returned when adding a function to the timeout pool with + * clutter_timeout_pool_add(). + * + * Since: 0.4 + * + * Deprecated: 1.6: There is no direct replacement for this API + */ +void +clutter_timeout_pool_remove (ClutterTimeoutPool *pool, + guint id_) +{ + GList *l; + + if ((l = g_list_find_custom (pool->timeouts, GUINT_TO_POINTER (id_), + clutter_timeout_find_by_id))) + { + clutter_timeout_unref (l->data); + pool->timeouts = g_list_delete_link (pool->timeouts, l); + } + else if ((l = g_list_find_custom (pool->dispatched_timeouts, + GUINT_TO_POINTER (id_), + clutter_timeout_find_by_id))) + { + clutter_timeout_unref (l->data); + + pool->dispatched_timeouts = + g_list_delete_link (pool->dispatched_timeouts, l); + } +} diff --git a/clutter/clutter/deprecated/clutter-timeout-pool.h b/clutter/clutter/deprecated/clutter-timeout-pool.h new file mode 100644 index 0000000..61780e5 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-timeout-pool.h @@ -0,0 +1,69 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * ClutterTimeoutPool: pool of timeout functions using the same slice of + * the GLib main loop + * + * Author: Emmanuele Bassi + * + * Based on similar code by Tristan van Berkom + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_TIMEOUT_POOL_H__ +#define __CLUTTER_TIMEOUT_POOL_H__ + +#include + +G_BEGIN_DECLS + +/** + * ClutterTimeoutPool: (skip) + * + * #ClutterTimeoutPool is an opaque structure + * whose members cannot be directly accessed. + * + * Since: 0.6 + * + * Deprecated: 1.6 + */ +typedef struct _ClutterTimeoutPool ClutterTimeoutPool; + +CLUTTER_DEPRECATED_IN_1_6 +ClutterTimeoutPool *clutter_timeout_pool_new (gint priority); + +CLUTTER_DEPRECATED_IN_1_6 +guint clutter_timeout_pool_add (ClutterTimeoutPool *pool, + guint fps, + GSourceFunc func, + gpointer data, + GDestroyNotify notify); +CLUTTER_DEPRECATED_IN_1_6 +void clutter_timeout_pool_remove (ClutterTimeoutPool *pool, + guint id_); + +G_END_DECLS + +#endif /* __CLUTTER_TIMEOUT_POOL_H__ */ diff --git a/clutter/clutter/deprecated/clutter-util.h b/clutter/clutter/deprecated/clutter-util.h new file mode 100644 index 0000000..ff9b325 --- /dev/null +++ b/clutter/clutter/deprecated/clutter-util.h @@ -0,0 +1,40 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_UTIL_H__ +#define __CLUTTER_UTIL_H__ + +#include + +G_BEGIN_DECLS + +CLUTTER_DEPRECATED_IN_1_2 +gint clutter_util_next_p2 (gint a); + +G_END_DECLS + +#endif /* __CLUTTER_UTIL_H__ */ diff --git a/clutter/clutter/egl/clutter-backend-eglnative.c b/clutter/clutter/egl/clutter-backend-eglnative.c new file mode 100644 index 0000000..6f64379 --- /dev/null +++ b/clutter/clutter/egl/clutter-backend-eglnative.c @@ -0,0 +1,214 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010,2011 Intel Corporation. + * 2011 Giovanni Campagna + * + * 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 . + + * Authors: + * Matthew Allum + * Emmanuele Bassi + * Robert Bragg + * Neil Roberts + */ + +#include "clutter-build-config.h" + +#include +#include +#include +#include + +#include + +#include "clutter-backend-eglnative.h" + +/* This is a Cogl based backend */ +#include "cogl/clutter-stage-cogl.h" + +#ifdef HAVE_EVDEV +#include "evdev/clutter-device-manager-evdev.h" +#endif + +#include "clutter-debug.h" +#include "clutter-private.h" +#include "clutter-main.h" +#include "clutter-stage-private.h" + +#ifdef COGL_HAS_EGL_SUPPORT +#include "clutter-egl.h" +#endif + +G_DEFINE_TYPE (ClutterBackendEglNative, clutter_backend_egl_native, CLUTTER_TYPE_BACKEND); + +static void +clutter_backend_egl_native_dispose (GObject *gobject) +{ + ClutterBackendEglNative *backend_egl_native = CLUTTER_BACKEND_EGL_NATIVE (gobject); + + if (backend_egl_native->event_timer != NULL) + { + g_timer_destroy (backend_egl_native->event_timer); + backend_egl_native->event_timer = NULL; + } + + G_OBJECT_CLASS (clutter_backend_egl_native_parent_class)->dispose (gobject); +} + +static void +clutter_backend_egl_native_class_init (ClutterBackendEglNativeClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->dispose = clutter_backend_egl_native_dispose; +} + +static void +clutter_backend_egl_native_init (ClutterBackendEglNative *backend_egl_native) +{ + backend_egl_native->event_timer = g_timer_new (); +} + +ClutterBackend * +clutter_backend_egl_native_new (void) +{ + return g_object_new (CLUTTER_TYPE_BACKEND_EGL_NATIVE, NULL); +} + +/** + * clutter_eglx_display: + * + * Retrieves the EGL display used by Clutter. + * + * Return value: the EGL display, or 0 + * + * Since: 0.6 + * + * Deprecated: 1.6: Use clutter_egl_get_egl_display() instead. + */ +EGLDisplay +clutter_eglx_display (void) +{ + return clutter_egl_get_egl_display (); +} + +/** + * clutter_egl_display: + * + * Retrieves the EGL display used by Clutter. + * + * Return value: the EGL display used by Clutter, or 0 + * + * Since: 0.6 + * + * Deprecated: 1.6: Use clutter_egl_get_egl_display() instead. + */ +EGLDisplay +clutter_egl_display (void) +{ + return clutter_egl_get_egl_display (); +} + +/** + * clutter_egl_get_egl_display: + * + * Retrieves the EGL display used by Clutter, if it supports the + * EGL windowing system and if it is running using an EGL backend. + * + * Return value: the EGL display used by Clutter, or 0 + * + * Since: 1.6 + */ +EGLDisplay +clutter_egl_get_egl_display (void) +{ + ClutterBackend *backend; + + if (!_clutter_context_is_initialized ()) + { + g_critical ("The Clutter backend has not been initialized yet"); + return 0; + } + + backend = clutter_get_default_backend (); + + if (!CLUTTER_IS_BACKEND_EGL_NATIVE (backend)) + { + g_critical ("The Clutter backend is not an EGL backend"); + return 0; + } + +#if COGL_HAS_EGL_SUPPORT + return cogl_egl_context_get_egl_display (backend->cogl_context); +#else + return 0; +#endif +} + +/** + * clutter_egl_freeze_master_clock: + * + * Freezing the master clock makes Clutter stop processing events, + * redrawing, and advancing timelines. This is necessary when implementing + * a display server, to ensure that Clutter doesn't keep trying to page + * flip when DRM master has been dropped, e.g. when VT switched away. + * + * The master clock starts out running, so if you are VT switched away on + * startup, you need to call this immediately. + * + * If you're also using the evdev backend, make sure to also use + * clutter_evdev_release_devices() to make sure that Clutter doesn't also + * access revoked evdev devices when VT switched away. + * + * To unthaw a frozen master clock, use clutter_egl_thaw_master_clock(). + * + * Since: 1.20 + */ +void +clutter_egl_freeze_master_clock (void) +{ + ClutterMasterClock *master_clock; + + g_return_if_fail (CLUTTER_IS_BACKEND_EGL_NATIVE (clutter_get_default_backend ())); + + master_clock = _clutter_master_clock_get_default (); + _clutter_master_clock_set_paused (master_clock, TRUE); +} + +/** + * clutter_egl_thaw_master_clock: + * + * Thaws a master clock that has previously been frozen with + * clutter_egl_freeze_master_clock(), and start pumping the master clock + * again at the next iteration. Note that if you're switching back to your + * own VT, you should probably also queue a stage redraw with + * clutter_stage_ensure_redraw(). + * + * Since: 1.20 + */ +void +clutter_egl_thaw_master_clock (void) +{ + ClutterMasterClock *master_clock; + + g_return_if_fail (CLUTTER_IS_BACKEND_EGL_NATIVE (clutter_get_default_backend ())); + + master_clock = _clutter_master_clock_get_default (); + _clutter_master_clock_set_paused (master_clock, FALSE); + + _clutter_master_clock_start_running (master_clock); +} diff --git a/clutter/clutter/egl/clutter-backend-eglnative.h b/clutter/clutter/egl/clutter-backend-eglnative.h new file mode 100644 index 0000000..d98013d --- /dev/null +++ b/clutter/clutter/egl/clutter-backend-eglnative.h @@ -0,0 +1,78 @@ +/* Clutter. + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2006, 2007 OpenedHand + * Copyright (C) 2010 Intel Corp + * 2011 Giovanni Campagna + * + * 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 . + * + * Authors: + * Matthew Allum + * Robert Bragg + */ + +#ifndef __CLUTTER_BACKEND_EGL_NATIVE_H__ +#define __CLUTTER_BACKEND_EGL_NATIVE_H__ + +#include +#include +#include +#include +#include +#include + +#include "clutter-backend-private.h" + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BACKEND_EGL_NATIVE (clutter_backend_egl_native_get_type ()) +#define CLUTTER_BACKEND_EGL_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BACKEND_EGL_NATIVE, ClutterBackendEglNative)) +#define CLUTTER_IS_BACKEND_EGL_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BACKEND_EGL_NATIVE)) +#define CLUTTER_BACKEND_EGL_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BACKEND_EGL_NATIVE, ClutterBackendEglNativeClass)) +#define CLUTTER_IS_BACKEND_EGL_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BACKEND_EGL_NATIVE)) +#define CLUTTER_BACKEND_EGL_NATIVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BACKEND_EGL_NATIVE, ClutterBackendEglNativeClass)) + +typedef struct _ClutterBackendEglNative ClutterBackendEglNative; +typedef struct _ClutterBackendEglNativeClass ClutterBackendEglNativeClass; + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBackendEglNative, g_object_unref) + +struct _ClutterBackendEglNative +{ + ClutterBackend parent_instance; + + /* device manager (ie evdev) */ + ClutterDeviceManager *device_manager; + + /* event source */ + GSource *event_source; + + /* event timer */ + GTimer *event_timer; +}; + +struct _ClutterBackendEglNativeClass +{ + ClutterBackendClass parent_class; +}; + +CLUTTER_AVAILABLE_IN_MUTTER +GType clutter_backend_egl_native_get_type (void) G_GNUC_CONST; + +ClutterBackend *clutter_backend_egl_native_new (void); + +G_END_DECLS + +#endif /* __CLUTTER_BACKEND_EGL_NATIVE_H__ */ diff --git a/clutter/clutter/egl/clutter-egl-headers.h b/clutter/clutter/egl/clutter-egl-headers.h new file mode 100644 index 0000000..d7b2f3f --- /dev/null +++ b/clutter/clutter/egl/clutter-egl-headers.h @@ -0,0 +1,41 @@ +/* Clutter. + * An OpenGL based 'interactive canvas' library. + * Authored By Matthew Allum + * Copyright (C) 2006-2007 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +#ifndef __CLUTTER_EGL_HEADERS_H__ +#define __CLUTTER_EGL_HEADERS_H__ + +/* Clutter relies on Cogl to abstract GLES1/2/OpenGL and GLX/EGL etc + * so we simply include the Cogl header to pull in the appropriate EGL + * header. */ + +#include + +/* Since Cogl 1.11.2, the EGL headers are no longer included from + * cogl.h when the experimental 2.0 API is requested. Clutter requests + * this in its configure script so we need to switch the header we + * include in that case. COGL_VERSION_CHECK is also new in 1.11.2 */ +#ifdef COGL_VERSION_CHECK +#if COGL_VERSION_CHECK (1, 11, 2) +#include +#endif +#endif + +#endif /* __CLUTTER_EGL_HEADERS_H__ */ diff --git a/clutter/clutter/egl/clutter-egl.h b/clutter/clutter/egl/clutter-egl.h new file mode 100644 index 0000000..83b0213 --- /dev/null +++ b/clutter/clutter/egl/clutter-egl.h @@ -0,0 +1,102 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +/** + * SECTION:clutter-egl + * @short_description: EGL specific API + * + * The EGL backend for Clutter provides some EGL specific API + * + * You need to include `clutter-egl.h` to have access to the functions documented here. + */ + +#ifndef __CLUTTER_EGL_H__ +#define __CLUTTER_EGL_H__ + +#include + +#ifdef COGL_HAS_XLIB_SUPPORT +#include +#include +#include +#endif + +#include "clutter-egl-headers.h" +#include + +G_BEGIN_DECLS + +/** + * clutter_eglx_display: + * + * Retrieves the #EGLDisplay used by Clutter, + * if Clutter has been compiled with EGL and X11 support. + * + * Return value: the EGL display + * + * Since: 0.4 + * + * Deprecated: 1.6: Use clutter_egl_get_egl_display() instead + */ +CLUTTER_DEPRECATED_FOR(clutter_egl_get_egl_display) +EGLDisplay clutter_eglx_display (void); + +/** + * clutter_egl_display: + * + * Retrieves the #EGLDisplay used by Clutter + * + * Return value: the EGL display + * + * Deprecated: 1.6: Use clutter_egl_get_egl_display() instead + */ +CLUTTER_DEPRECATED_FOR(clutter_egl_get_egl_display) +EGLDisplay clutter_egl_display (void); + +/** + * clutter_egl_get_egl_display: + * + * Retrieves the #EGLDisplay used by Clutter. + * + * Return value: the EGL display + * + * Since: 1.6 + */ +CLUTTER_AVAILABLE_IN_1_6 +EGLDisplay clutter_egl_get_egl_display (void); + +#ifdef COGL_HAS_EGL_PLATFORM_KMS_SUPPORT +CLUTTER_AVAILABLE_IN_1_18 +void clutter_egl_set_kms_fd (int fd); +#endif + +CLUTTER_AVAILABLE_IN_1_20 +void clutter_egl_freeze_master_clock (void); +CLUTTER_AVAILABLE_IN_1_20 +void clutter_egl_thaw_master_clock (void); + +G_END_DECLS + +#endif /* __CLUTTER_EGL_H__ */ diff --git a/clutter/clutter/evdev/clutter-device-manager-evdev.c b/clutter/clutter/evdev/clutter-device-manager-evdev.c new file mode 100644 index 0000000..04dcb2e --- /dev/null +++ b/clutter/clutter/evdev/clutter-device-manager-evdev.c @@ -0,0 +1,2779 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corp. + * Copyright (C) 2014 Jonas Ådahl + * + * 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 . + * + * Author: Damien Lespiau + * Author: Jonas Ådahl + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "clutter-backend.h" +#include "clutter-debug.h" +#include "clutter-device-manager.h" +#include "clutter-device-manager-private.h" +#include "clutter-event-private.h" +#include "clutter-input-device-evdev.h" +#include "clutter-seat-evdev.h" +#include "clutter-virtual-input-device-evdev.h" +#include "clutter-main.h" +#include "clutter-private.h" +#include "clutter-stage-manager.h" +#include "clutter-xkb-utils.h" +#include "clutter-backend-private.h" +#include "clutter-evdev.h" +#include "clutter-stage-private.h" +#include "clutter-input-device-tool-evdev.h" + +#include "clutter-device-manager-evdev.h" + +#define DISCRETE_SCROLL_STEP 10.0 + + +/* + * Clutter makes the assumption that two core devices have ID's 2 and 3 (core + * pointer and core keyboard). + * + * Since the two first devices that will ever be created will be the virtual + * pointer and virtual keyboard of the first seat, we fulfill the made + * assumptions by having the first device having ID 2 and following 3. + */ +#define INITIAL_DEVICE_ID 2 + +typedef struct _ClutterEventFilter ClutterEventFilter; + +struct _ClutterEventFilter +{ + ClutterEvdevFilterFunc func; + gpointer data; + GDestroyNotify destroy_notify; +}; + +typedef struct _ClutterEventSource ClutterEventSource; + +struct _ClutterDeviceManagerEvdevPrivate +{ + struct libinput *libinput; + + ClutterStage *stage; + gboolean released; + + ClutterEventSource *event_source; + + GSList *devices; + GSList *seats; + + ClutterSeatEvdev *main_seat; + struct xkb_keymap *keymap; + + ClutterPointerConstrainCallback constrain_callback; + gpointer constrain_data; + GDestroyNotify constrain_data_notify; + + ClutterStageManager *stage_manager; + guint stage_added_handler; + guint stage_removed_handler; + + GSList *event_filters; + + gint device_id_next; + GList *free_device_ids; +}; + +static void clutter_device_manager_evdev_event_extender_init (ClutterEventExtenderInterface *iface); + +G_DEFINE_TYPE_WITH_CODE (ClutterDeviceManagerEvdev, + clutter_device_manager_evdev, + CLUTTER_TYPE_DEVICE_MANAGER, + G_ADD_PRIVATE (ClutterDeviceManagerEvdev) + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_EVENT_EXTENDER, + clutter_device_manager_evdev_event_extender_init)) + +static ClutterOpenDeviceCallback device_open_callback; +static ClutterCloseDeviceCallback device_close_callback; +static gpointer device_callback_data; + +#ifdef CLUTTER_ENABLE_DEBUG +static const char *device_type_str[] = { + "pointer", /* CLUTTER_POINTER_DEVICE */ + "keyboard", /* CLUTTER_KEYBOARD_DEVICE */ + "extension", /* CLUTTER_EXTENSION_DEVICE */ + "joystick", /* CLUTTER_JOYSTICK_DEVICE */ + "tablet", /* CLUTTER_TABLET_DEVICE */ + "touchpad", /* CLUTTER_TOUCHPAD_DEVICE */ + "touchscreen", /* CLUTTER_TOUCHSCREEN_DEVICE */ + "pen", /* CLUTTER_PEN_DEVICE */ + "eraser", /* CLUTTER_ERASER_DEVICE */ + "cursor", /* CLUTTER_CURSOR_DEVICE */ + "pad", /* CLUTTER_PAD_DEVICE */ +}; +#endif /* CLUTTER_ENABLE_DEBUG */ + +/* + * ClutterEventSource management + * + * The device manager is responsible for managing the GSource when devices + * appear and disappear from the system. + */ + +static const char *option_xkb_layout = "us"; +static const char *option_xkb_variant = ""; +static const char *option_xkb_options = ""; + +static void +clutter_device_manager_evdev_copy_event_data (ClutterEventExtender *event_extender, + const ClutterEvent *src, + ClutterEvent *dest) +{ + ClutterEventEvdev *event_evdev; + + event_evdev = _clutter_event_get_platform_data (src); + if (event_evdev != NULL) + _clutter_event_set_platform_data (dest, _clutter_event_evdev_copy (event_evdev)); +} + +static void +clutter_device_manager_evdev_free_event_data (ClutterEventExtender *event_extender, + ClutterEvent *event) +{ + ClutterEventEvdev *event_evdev; + + event_evdev = _clutter_event_get_platform_data (event); + if (event_evdev != NULL) + _clutter_event_evdev_free (event_evdev); +} + +static void +clutter_device_manager_evdev_event_extender_init (ClutterEventExtenderInterface *iface) +{ + iface->copy_event_data = clutter_device_manager_evdev_copy_event_data; + iface->free_event_data = clutter_device_manager_evdev_free_event_data; +} + +/* + * ClutterEventSource for reading input devices + */ + +struct _ClutterEventSource +{ + GSource source; + + ClutterDeviceManagerEvdev *manager_evdev; + GPollFD event_poll_fd; +}; + +static void +process_events (ClutterDeviceManagerEvdev *manager_evdev); + +static gboolean +clutter_event_prepare (GSource *source, + gint *timeout) +{ + gboolean retval; + + _clutter_threads_acquire_lock (); + + *timeout = -1; + retval = clutter_events_pending (); + + _clutter_threads_release_lock (); + + return retval; +} + +static gboolean +clutter_event_check (GSource *source) +{ + ClutterEventSource *event_source = (ClutterEventSource *) source; + gboolean retval; + + _clutter_threads_acquire_lock (); + + retval = ((event_source->event_poll_fd.revents & G_IO_IN) || + clutter_events_pending ()); + + _clutter_threads_release_lock (); + + return retval; +} + +static void +queue_event (ClutterEvent *event) +{ + _clutter_event_push (event, FALSE); +} + +void +_clutter_device_manager_evdev_constrain_pointer (ClutterDeviceManagerEvdev *manager_evdev, + ClutterInputDevice *core_pointer, + uint64_t time_us, + float x, + float y, + float *new_x, + float *new_y) +{ + if (manager_evdev->priv->constrain_callback) + { + manager_evdev->priv->constrain_callback (core_pointer, + us2ms (time_us), + x, y, + new_x, new_y, + manager_evdev->priv->constrain_data); + } + else + { + ClutterActor *stage = CLUTTER_ACTOR (manager_evdev->priv->stage); + float stage_width = clutter_actor_get_width (stage); + float stage_height = clutter_actor_get_height (stage); + + x = CLAMP (x, 0.f, stage_width - 1); + y = CLAMP (y, 0.f, stage_height - 1); + } +} + + +static ClutterEvent * +new_absolute_motion_event (ClutterInputDevice *input_device, + guint64 time_us, + gfloat x, + gfloat y, + gdouble *axes) +{ + gfloat stage_width, stage_height; + ClutterDeviceManagerEvdev *manager_evdev; + ClutterInputDeviceEvdev *device_evdev; + ClutterSeatEvdev *seat; + ClutterStage *stage; + ClutterEvent *event = NULL; + + stage = _clutter_input_device_get_stage (input_device); + device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device); + manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (input_device->device_manager); + seat = _clutter_input_device_evdev_get_seat (device_evdev); + + stage_width = clutter_actor_get_width (CLUTTER_ACTOR (stage)); + stage_height = clutter_actor_get_height (CLUTTER_ACTOR (stage)); + + event = clutter_event_new (CLUTTER_MOTION); + + if (manager_evdev->priv->constrain_callback && + clutter_input_device_get_device_type (input_device) != CLUTTER_TABLET_DEVICE) + { + manager_evdev->priv->constrain_callback (seat->core_pointer, + us2ms (time_us), + seat->pointer_x, + seat->pointer_y, + &x, &y, + manager_evdev->priv->constrain_data); + } + else + { + x = CLAMP (x, 0.f, stage_width - 1); + y = CLAMP (y, 0.f, stage_height - 1); + } + + _clutter_evdev_event_set_time_usec (event, time_us); + event->motion.time = us2ms (time_us); + event->motion.stage = stage; + event->motion.device = seat->core_pointer; + _clutter_xkb_translate_state (event, seat->xkb, seat->button_state); + event->motion.x = x; + event->motion.y = y; + event->motion.axes = axes; + clutter_event_set_source_device (event, input_device); + + if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE) + { + clutter_event_set_device_tool (event, device_evdev->last_tool); + clutter_event_set_device (event, input_device); + } + else + clutter_event_set_device (event, seat->core_pointer); + + _clutter_input_device_set_stage (seat->core_pointer, stage); + + if (clutter_input_device_get_device_type (input_device) != CLUTTER_TABLET_DEVICE) + { + seat->pointer_x = x; + seat->pointer_y = y; + } + + return event; +} + +static void +notify_absolute_motion (ClutterInputDevice *input_device, + guint64 time_us, + gfloat x, + gfloat y, + gdouble *axes) +{ + ClutterEvent *event; + + event = new_absolute_motion_event (input_device, time_us, x, y, axes); + + queue_event (event); +} + +static void +notify_relative_tool_motion (ClutterInputDevice *input_device, + guint64 time_us, + gfloat dx, + gfloat dy, + gdouble *axes) +{ + ClutterEvent *event; + gfloat x, y; + + x = input_device->current_x + dx; + y = input_device->current_y + dy; + event = new_absolute_motion_event (input_device, time_us, x, y, axes); + _clutter_evdev_event_set_relative_motion (event, dx, dy, 0, 0); + + queue_event (event); +} + +static ClutterScrollDirection +discrete_to_direction (gdouble discrete_x, + gdouble discrete_y) +{ + if (discrete_x > 0) + return CLUTTER_SCROLL_RIGHT; + else if (discrete_x < 0) + return CLUTTER_SCROLL_LEFT; + else if (discrete_y > 0) + return CLUTTER_SCROLL_DOWN; + else if (discrete_y < 0) + return CLUTTER_SCROLL_UP; + else + return CLUTTER_SCROLL_SMOOTH; +} + +static void +notify_discrete_scroll (ClutterInputDevice *input_device, + guint64 time_us, + ClutterScrollDirection direction, + ClutterScrollSource scroll_source, + gboolean emulated) +{ + ClutterInputDeviceEvdev *device_evdev; + ClutterSeatEvdev *seat; + ClutterStage *stage; + ClutterEvent *event = NULL; + + if (direction == CLUTTER_SCROLL_SMOOTH) + return; + + /* We can drop the event on the floor if no stage has been + * associated with the device yet. */ + stage = _clutter_input_device_get_stage (input_device); + if (stage == NULL) + return; + + device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device); + seat = _clutter_input_device_evdev_get_seat (device_evdev); + + event = clutter_event_new (CLUTTER_SCROLL); + + _clutter_evdev_event_set_time_usec (event, time_us); + event->scroll.time = us2ms (time_us); + event->scroll.stage = CLUTTER_STAGE (stage); + event->scroll.device = seat->core_pointer; + _clutter_xkb_translate_state (event, seat->xkb, seat->button_state); + + event->scroll.direction = direction; + + event->scroll.x = seat->pointer_x; + event->scroll.y = seat->pointer_y; + clutter_event_set_device (event, seat->core_pointer); + clutter_event_set_source_device (event, input_device); + event->scroll.scroll_source = scroll_source; + + _clutter_event_set_pointer_emulated (event, emulated); + + queue_event (event); +} + +static void +notify_scroll (ClutterInputDevice *input_device, + guint64 time_us, + gdouble dx, + gdouble dy, + ClutterScrollSource source, + ClutterScrollFinishFlags flags, + gboolean emulated) +{ + ClutterInputDeviceEvdev *device_evdev; + ClutterSeatEvdev *seat; + ClutterStage *stage; + ClutterEvent *event = NULL; + gdouble scroll_factor; + + /* We can drop the event on the floor if no stage has been + * associated with the device yet. */ + stage = _clutter_input_device_get_stage (input_device); + if (stage == NULL) + return; + + device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device); + seat = _clutter_input_device_evdev_get_seat (device_evdev); + + event = clutter_event_new (CLUTTER_SCROLL); + + _clutter_evdev_event_set_time_usec (event, time_us); + event->scroll.time = us2ms (time_us); + event->scroll.stage = CLUTTER_STAGE (stage); + event->scroll.device = seat->core_pointer; + _clutter_xkb_translate_state (event, seat->xkb, seat->button_state); + + /* libinput pointer axis events are in pointer motion coordinate space. + * To convert to Xi2 discrete step coordinate space, multiply the factor + * 1/10. */ + event->scroll.direction = CLUTTER_SCROLL_SMOOTH; + scroll_factor = 1.0 / DISCRETE_SCROLL_STEP; + clutter_event_set_scroll_delta (event, + scroll_factor * dx, + scroll_factor * dy); + + event->scroll.x = seat->pointer_x; + event->scroll.y = seat->pointer_y; + clutter_event_set_device (event, seat->core_pointer); + clutter_event_set_source_device (event, input_device); + event->scroll.scroll_source = source; + event->scroll.finish_flags = flags; + + _clutter_event_set_pointer_emulated (event, emulated); + + queue_event (event); +} + +static void +notify_touch_event (ClutterInputDevice *input_device, + ClutterEventType evtype, + guint64 time_us, + gint32 slot, + gdouble x, + gdouble y) +{ + ClutterInputDeviceEvdev *device_evdev; + ClutterSeatEvdev *seat; + ClutterStage *stage; + ClutterEvent *event = NULL; + + /* We can drop the event on the floor if no stage has been + * associated with the device yet. */ + stage = _clutter_input_device_get_stage (input_device); + if (stage == NULL) + return; + + device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device); + seat = _clutter_input_device_evdev_get_seat (device_evdev); + + event = clutter_event_new (evtype); + + _clutter_evdev_event_set_time_usec (event, time_us); + event->touch.time = us2ms (time_us); + event->touch.stage = CLUTTER_STAGE (stage); + event->touch.device = seat->core_pointer; + event->touch.x = x; + event->touch.y = y; + /* "NULL" sequences are special cased in clutter */ + event->touch.sequence = GINT_TO_POINTER (slot + 1); + _clutter_xkb_translate_state (event, seat->xkb, seat->button_state); + + if (evtype == CLUTTER_TOUCH_BEGIN || + evtype == CLUTTER_TOUCH_UPDATE) + event->touch.modifier_state |= CLUTTER_BUTTON1_MASK; + + clutter_event_set_device (event, seat->core_pointer); + clutter_event_set_source_device (event, input_device); + + queue_event (event); +} + +static void +notify_pinch_gesture_event (ClutterInputDevice *input_device, + ClutterTouchpadGesturePhase phase, + guint64 time_us, + gdouble dx, + gdouble dy, + gdouble angle_delta, + gdouble scale) +{ + ClutterInputDeviceEvdev *device_evdev; + ClutterSeatEvdev *seat; + ClutterStage *stage; + ClutterEvent *event = NULL; + ClutterPoint pos; + + /* We can drop the event on the floor if no stage has been + * associated with the device yet. */ + stage = _clutter_input_device_get_stage (input_device); + if (stage == NULL) + return; + + device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device); + seat = _clutter_input_device_evdev_get_seat (device_evdev); + + event = clutter_event_new (CLUTTER_TOUCHPAD_PINCH); + + clutter_input_device_get_coords (seat->core_pointer, NULL, &pos); + + _clutter_evdev_event_set_time_usec (event, time_us); + event->touchpad_pinch.phase = phase; + event->touchpad_pinch.time = us2ms (time_us); + event->touchpad_pinch.stage = CLUTTER_STAGE (stage); + event->touchpad_pinch.x = pos.x; + event->touchpad_pinch.y = pos.y; + event->touchpad_pinch.dx = dx; + event->touchpad_pinch.dy = dy; + event->touchpad_pinch.angle_delta = angle_delta; + event->touchpad_pinch.scale = scale; + + _clutter_xkb_translate_state (event, seat->xkb, seat->button_state); + + clutter_event_set_device (event, seat->core_pointer); + clutter_event_set_source_device (event, input_device); + + queue_event (event); +} + +static void +notify_swipe_gesture_event (ClutterInputDevice *input_device, + ClutterTouchpadGesturePhase phase, + guint64 time_us, + guint n_fingers, + gdouble dx, + gdouble dy) +{ + ClutterInputDeviceEvdev *device_evdev; + ClutterSeatEvdev *seat; + ClutterStage *stage; + ClutterEvent *event = NULL; + ClutterPoint pos; + + /* We can drop the event on the floor if no stage has been + * associated with the device yet. */ + stage = _clutter_input_device_get_stage (input_device); + if (stage == NULL) + return; + + device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device); + seat = _clutter_input_device_evdev_get_seat (device_evdev); + + event = clutter_event_new (CLUTTER_TOUCHPAD_SWIPE); + + _clutter_evdev_event_set_time_usec (event, time_us); + event->touchpad_swipe.phase = phase; + event->touchpad_swipe.time = us2ms (time_us); + event->touchpad_swipe.stage = CLUTTER_STAGE (stage); + + clutter_input_device_get_coords (seat->core_pointer, NULL, &pos); + event->touchpad_swipe.x = pos.x; + event->touchpad_swipe.y = pos.y; + event->touchpad_swipe.dx = dx; + event->touchpad_swipe.dy = dy; + event->touchpad_swipe.n_fingers = n_fingers; + + _clutter_xkb_translate_state (event, seat->xkb, seat->button_state); + + clutter_event_set_device (event, seat->core_pointer); + clutter_event_set_source_device (event, input_device); + + queue_event (event); +} + +static void +notify_proximity (ClutterInputDevice *input_device, + guint64 time_us, + gboolean in) +{ + ClutterInputDeviceEvdev *device_evdev; + ClutterSeatEvdev *seat; + ClutterStage *stage; + ClutterEvent *event = NULL; + + /* We can drop the event on the floor if no stage has been + * associated with the device yet. */ + stage = _clutter_input_device_get_stage (input_device); + if (stage == NULL) + return; + + device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device); + seat = _clutter_input_device_evdev_get_seat (device_evdev); + + if (in) + event = clutter_event_new (CLUTTER_PROXIMITY_IN); + else + event = clutter_event_new (CLUTTER_PROXIMITY_OUT); + + _clutter_evdev_event_set_time_usec (event, time_us); + + event->proximity.time = us2ms (time_us); + event->proximity.stage = CLUTTER_STAGE (stage); + event->proximity.device = seat->core_pointer; + clutter_event_set_device_tool (event, device_evdev->last_tool); + clutter_event_set_device (event, seat->core_pointer); + clutter_event_set_source_device (event, input_device); + + _clutter_input_device_set_stage (seat->core_pointer, stage); + + queue_event (event); +} + +static void +notify_pad_button (ClutterInputDevice *input_device, + guint64 time_us, + guint32 button, + guint32 mode_group, + guint32 pressed) +{ + ClutterInputDeviceEvdev *device_evdev; + ClutterSeatEvdev *seat; + ClutterStage *stage; + ClutterEvent *event; + + /* We can drop the event on the floor if no stage has been + * associated with the device yet. */ + stage = _clutter_input_device_get_stage (input_device); + if (stage == NULL) + return; + + if (pressed) + event = clutter_event_new (CLUTTER_PAD_BUTTON_PRESS); + else + event = clutter_event_new (CLUTTER_PAD_BUTTON_RELEASE); + + device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device); + seat = _clutter_input_device_evdev_get_seat (device_evdev); + + _clutter_evdev_event_set_time_usec (event, time_us); + event->pad_button.stage = stage; + event->pad_button.button = button; + event->pad_button.group = mode_group; + clutter_event_set_device (event, input_device); + clutter_event_set_source_device (event, input_device); + clutter_event_set_time (event, us2ms (time_us)); + + _clutter_input_device_set_stage (seat->core_pointer, stage); + + queue_event (event); +} + +static void +notify_pad_strip (ClutterInputDevice *input_device, + guint64 time_us, + guint32 strip_number, + guint32 strip_source, + guint32 mode_group, + gdouble value) +{ + ClutterInputDeviceEvdev *device_evdev; + ClutterInputDevicePadSource source; + ClutterSeatEvdev *seat; + ClutterStage *stage; + ClutterEvent *event; + + /* We can drop the event on the floor if no stage has been + * associated with the device yet. */ + stage = _clutter_input_device_get_stage (input_device); + if (stage == NULL) + return; + + if (strip_source == LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER) + source = CLUTTER_INPUT_DEVICE_PAD_SOURCE_FINGER; + else + source = CLUTTER_INPUT_DEVICE_PAD_SOURCE_UNKNOWN; + + device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device); + seat = _clutter_input_device_evdev_get_seat (device_evdev); + + event = clutter_event_new (CLUTTER_PAD_STRIP); + _clutter_evdev_event_set_time_usec (event, time_us); + event->pad_strip.strip_source = source; + event->pad_strip.stage = stage; + event->pad_strip.strip_number = strip_number; + event->pad_strip.value = value; + event->pad_strip.group = mode_group; + clutter_event_set_device (event, input_device); + clutter_event_set_source_device (event, input_device); + clutter_event_set_time (event, us2ms (time_us)); + + _clutter_input_device_set_stage (seat->core_pointer, stage); + + queue_event (event); +} + +static void +notify_pad_ring (ClutterInputDevice *input_device, + guint64 time_us, + guint32 ring_number, + guint32 ring_source, + guint32 mode_group, + gdouble angle) +{ + ClutterInputDeviceEvdev *device_evdev; + ClutterInputDevicePadSource source; + ClutterSeatEvdev *seat; + ClutterStage *stage; + ClutterEvent *event; + + /* We can drop the event on the floor if no stage has been + * associated with the device yet. */ + stage = _clutter_input_device_get_stage (input_device); + if (stage == NULL) + return; + + if (ring_source == LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER) + source = CLUTTER_INPUT_DEVICE_PAD_SOURCE_FINGER; + else + source = CLUTTER_INPUT_DEVICE_PAD_SOURCE_UNKNOWN; + + device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device); + seat = _clutter_input_device_evdev_get_seat (device_evdev); + + event = clutter_event_new (CLUTTER_PAD_RING); + _clutter_evdev_event_set_time_usec (event, time_us); + event->pad_ring.ring_source = source; + event->pad_ring.stage = stage; + event->pad_ring.ring_number = ring_number; + event->pad_ring.angle = angle; + event->pad_ring.group = mode_group; + clutter_event_set_device (event, input_device); + clutter_event_set_source_device (event, input_device); + clutter_event_set_time (event, us2ms (time_us)); + + _clutter_input_device_set_stage (seat->core_pointer, stage); + + queue_event (event); +} + +static void +dispatch_libinput (ClutterDeviceManagerEvdev *manager_evdev) +{ + ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv; + + libinput_dispatch (priv->libinput); + process_events (manager_evdev); +} + +static gboolean +clutter_event_dispatch (GSource *g_source, + GSourceFunc callback, + gpointer user_data) +{ + ClutterEventSource *source = (ClutterEventSource *) g_source; + ClutterDeviceManagerEvdev *manager_evdev; + ClutterEvent *event; + + _clutter_threads_acquire_lock (); + + manager_evdev = source->manager_evdev; + + /* Don't queue more events if we haven't finished handling the previous batch + */ + if (clutter_events_pending ()) + goto queue_event; + + dispatch_libinput (manager_evdev); + + queue_event: + event = clutter_event_get (); + + if (event) + { + ClutterModifierType event_state; + ClutterInputDevice *input_device = + clutter_event_get_source_device (event); + ClutterInputDeviceEvdev *device_evdev = + CLUTTER_INPUT_DEVICE_EVDEV (input_device); + ClutterSeatEvdev *seat = + _clutter_input_device_evdev_get_seat (device_evdev); + + /* Drop events if we don't have any stage to forward them to */ + if (!_clutter_input_device_get_stage (input_device)) + goto out; + + /* forward the event into clutter for emission etc. */ + _clutter_stage_queue_event (event->any.stage, event, FALSE); + + /* update the device states *after* the event */ + event_state = seat->button_state | + xkb_state_serialize_mods (seat->xkb, XKB_STATE_MODS_EFFECTIVE); + _clutter_input_device_set_state (seat->core_pointer, event_state); + _clutter_input_device_set_state (seat->core_keyboard, event_state); + } + +out: + _clutter_threads_release_lock (); + + return TRUE; +} +static GSourceFuncs event_funcs = { + clutter_event_prepare, + clutter_event_check, + clutter_event_dispatch, + NULL +}; + +static ClutterEventSource * +clutter_event_source_new (ClutterDeviceManagerEvdev *manager_evdev) +{ + ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv; + GSource *source; + ClutterEventSource *event_source; + gint fd; + + source = g_source_new (&event_funcs, sizeof (ClutterEventSource)); + event_source = (ClutterEventSource *) source; + + /* setup the source */ + event_source->manager_evdev = manager_evdev; + + fd = libinput_get_fd (priv->libinput); + event_source->event_poll_fd.fd = fd; + event_source->event_poll_fd.events = G_IO_IN; + + /* and finally configure and attach the GSource */ + g_source_set_priority (source, CLUTTER_PRIORITY_EVENTS); + g_source_add_poll (source, &event_source->event_poll_fd); + g_source_set_can_recurse (source, TRUE); + g_source_attach (source, NULL); + + return event_source; +} + +static void +clutter_event_source_free (ClutterEventSource *source) +{ + GSource *g_source = (GSource *) source; + + CLUTTER_NOTE (EVENT, "Removing GSource for evdev device manager"); + + /* ignore the return value of close, it's not like we can do something + * about it */ + close (source->event_poll_fd.fd); + + g_source_destroy (g_source); + g_source_unref (g_source); +} + +static void +evdev_add_device (ClutterDeviceManagerEvdev *manager_evdev, + struct libinput_device *libinput_device) +{ + ClutterDeviceManager *manager = (ClutterDeviceManager *) manager_evdev; + ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv; + ClutterInputDeviceType type; + struct libinput_seat *libinput_seat; + ClutterSeatEvdev *seat; + ClutterInputDevice *device; + + libinput_seat = libinput_device_get_seat (libinput_device); + seat = libinput_seat_get_user_data (libinput_seat); + if (seat == NULL) + { + /* Clutter has the notion of global "core" pointers and keyboard devices, + * which are located on the main seat. Make whatever seat comes first the + * main seat. */ + if (priv->main_seat->libinput_seat == NULL) + seat = priv->main_seat; + else + seat = clutter_seat_evdev_new (manager_evdev); + + clutter_seat_evdev_set_libinput_seat (seat, libinput_seat); + priv->seats = g_slist_append (priv->seats, seat); + } + + device = _clutter_input_device_evdev_new (manager, seat, libinput_device); + _clutter_input_device_set_stage (device, manager_evdev->priv->stage); + + _clutter_device_manager_add_device (manager, device); + + /* Clutter assumes that device types are exclusive in the + * ClutterInputDevice API */ + type = _clutter_input_device_evdev_determine_type (libinput_device); + + if (type == CLUTTER_KEYBOARD_DEVICE) + { + _clutter_input_device_set_associated_device (device, seat->core_keyboard); + _clutter_input_device_add_slave (seat->core_keyboard, device); + } + else if (type == CLUTTER_POINTER_DEVICE) + { + _clutter_input_device_set_associated_device (device, seat->core_pointer); + _clutter_input_device_add_slave (seat->core_pointer, device); + } + + CLUTTER_NOTE (EVENT, "Added physical device '%s', type %s", + clutter_input_device_get_device_name (device), + device_type_str[type]); +} + +static void +evdev_remove_device (ClutterDeviceManagerEvdev *manager_evdev, + ClutterInputDeviceEvdev *device_evdev) +{ + ClutterDeviceManager *manager = CLUTTER_DEVICE_MANAGER (manager_evdev); + ClutterInputDevice *input_device = CLUTTER_INPUT_DEVICE (device_evdev); + + _clutter_device_manager_remove_device (manager, input_device); +} + +/* + * ClutterDeviceManager implementation + */ + +static void +clutter_device_manager_evdev_add_device (ClutterDeviceManager *manager, + ClutterInputDevice *device) +{ + ClutterDeviceManagerEvdev *manager_evdev; + ClutterDeviceManagerEvdevPrivate *priv; + ClutterInputDeviceEvdev *device_evdev; + ClutterSeatEvdev *seat; + + manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager); + priv = manager_evdev->priv; + device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (device); + seat = _clutter_input_device_evdev_get_seat (device_evdev); + + seat->devices = g_slist_prepend (seat->devices, device); + priv->devices = g_slist_prepend (priv->devices, device); +} + +static void +clutter_device_manager_evdev_remove_device (ClutterDeviceManager *manager, + ClutterInputDevice *device) +{ + ClutterDeviceManagerEvdev *manager_evdev; + ClutterDeviceManagerEvdevPrivate *priv; + ClutterInputDeviceEvdev *device_evdev; + ClutterSeatEvdev *seat; + + device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (device); + seat = _clutter_input_device_evdev_get_seat (device_evdev); + manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager); + priv = manager_evdev->priv; + + /* Remove the device */ + seat->devices = g_slist_remove (seat->devices, device); + priv->devices = g_slist_remove (priv->devices, device); + + if (seat->repeat_timer && seat->repeat_device == device) + clutter_seat_evdev_clear_repeat_timer (seat); + + g_object_unref (device); +} + +static const GSList * +clutter_device_manager_evdev_get_devices (ClutterDeviceManager *manager) +{ + return CLUTTER_DEVICE_MANAGER_EVDEV (manager)->priv->devices; +} + +static ClutterInputDevice * +clutter_device_manager_evdev_get_core_device (ClutterDeviceManager *manager, + ClutterInputDeviceType type) +{ + ClutterDeviceManagerEvdev *manager_evdev; + ClutterDeviceManagerEvdevPrivate *priv; + + manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager); + priv = manager_evdev->priv; + + switch (type) + { + case CLUTTER_POINTER_DEVICE: + return priv->main_seat->core_pointer; + + case CLUTTER_KEYBOARD_DEVICE: + return priv->main_seat->core_keyboard; + + case CLUTTER_EXTENSION_DEVICE: + default: + return NULL; + } + + return NULL; +} + +static ClutterInputDevice * +clutter_device_manager_evdev_get_device (ClutterDeviceManager *manager, + gint id) +{ + ClutterDeviceManagerEvdev *manager_evdev; + ClutterDeviceManagerEvdevPrivate *priv; + GSList *l; + GSList *device_it; + + manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager); + priv = manager_evdev->priv; + + for (l = priv->seats; l; l = l->next) + { + ClutterSeatEvdev *seat = l->data; + + for (device_it = seat->devices; device_it; device_it = device_it->next) + { + ClutterInputDevice *device = device_it->data; + + if (clutter_input_device_get_device_id (device) == id) + return device; + } + } + + return NULL; +} + +static void +flush_event_queue (void) +{ + ClutterEvent *event; + + while ((event = clutter_event_get ()) != NULL) + { + _clutter_process_event (event); + clutter_event_free (event); + } +} + +static gboolean +process_base_event (ClutterDeviceManagerEvdev *manager_evdev, + struct libinput_event *event) +{ + ClutterInputDevice *device; + struct libinput_device *libinput_device; + gboolean handled = TRUE; + + switch (libinput_event_get_type (event)) + { + case LIBINPUT_EVENT_DEVICE_ADDED: + libinput_device = libinput_event_get_device (event); + + evdev_add_device (manager_evdev, libinput_device); + break; + + case LIBINPUT_EVENT_DEVICE_REMOVED: + /* Flush all queued events, there + * might be some from this device. + */ + flush_event_queue (); + + libinput_device = libinput_event_get_device (event); + + device = libinput_device_get_user_data (libinput_device); + evdev_remove_device (manager_evdev, + CLUTTER_INPUT_DEVICE_EVDEV (device)); + break; + + default: + handled = FALSE; + } + + return handled; +} + +static void +check_notify_discrete_scroll (ClutterDeviceManagerEvdev *manager_evdev, + ClutterInputDevice *device, + guint64 time_us, + ClutterScrollSource scroll_source) +{ + ClutterInputDeviceEvdev *device_evdev = + CLUTTER_INPUT_DEVICE_EVDEV (device); + ClutterSeatEvdev *seat = _clutter_input_device_evdev_get_seat (device_evdev); + int i, n_xscrolls, n_yscrolls; + + n_xscrolls = floor (fabs (seat->accum_scroll_dx) / DISCRETE_SCROLL_STEP); + n_yscrolls = floor (fabs (seat->accum_scroll_dy) / DISCRETE_SCROLL_STEP); + + for (i = 0; i < n_xscrolls; i++) + { + notify_discrete_scroll (device, time_us, + seat->accum_scroll_dx > 0 ? + CLUTTER_SCROLL_RIGHT : CLUTTER_SCROLL_LEFT, + scroll_source, TRUE); + } + + for (i = 0; i < n_yscrolls; i++) + { + notify_discrete_scroll (device, time_us, + seat->accum_scroll_dy > 0 ? + CLUTTER_SCROLL_DOWN : CLUTTER_SCROLL_UP, + scroll_source, TRUE); + } + + seat->accum_scroll_dx = fmodf (seat->accum_scroll_dx, DISCRETE_SCROLL_STEP); + seat->accum_scroll_dy = fmodf (seat->accum_scroll_dy, DISCRETE_SCROLL_STEP); +} + +static ClutterScrollSource +translate_scroll_source (enum libinput_pointer_axis_source source) +{ + switch (source) + { + case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL: + return CLUTTER_SCROLL_SOURCE_WHEEL; + case LIBINPUT_POINTER_AXIS_SOURCE_FINGER: + return CLUTTER_SCROLL_SOURCE_FINGER; + case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS: + return CLUTTER_SCROLL_SOURCE_CONTINUOUS; + default: + return CLUTTER_SCROLL_SOURCE_UNKNOWN; + } +} + +static ClutterInputDeviceToolType +translate_tool_type (struct libinput_tablet_tool *libinput_tool) +{ + enum libinput_tablet_tool_type tool; + + tool = libinput_tablet_tool_get_type (libinput_tool); + + switch (tool) + { + case LIBINPUT_TABLET_TOOL_TYPE_PEN: + return CLUTTER_INPUT_DEVICE_TOOL_PEN; + case LIBINPUT_TABLET_TOOL_TYPE_ERASER: + return CLUTTER_INPUT_DEVICE_TOOL_ERASER; + case LIBINPUT_TABLET_TOOL_TYPE_BRUSH: + return CLUTTER_INPUT_DEVICE_TOOL_BRUSH; + case LIBINPUT_TABLET_TOOL_TYPE_PENCIL: + return CLUTTER_INPUT_DEVICE_TOOL_PENCIL; + case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH: + return CLUTTER_INPUT_DEVICE_TOOL_AIRBRUSH; + case LIBINPUT_TABLET_TOOL_TYPE_MOUSE: + return CLUTTER_INPUT_DEVICE_TOOL_MOUSE; + case LIBINPUT_TABLET_TOOL_TYPE_LENS: + return CLUTTER_INPUT_DEVICE_TOOL_LENS; + default: + return CLUTTER_INPUT_DEVICE_TOOL_NONE; + } +} + +static void +input_device_update_tool (ClutterInputDevice *input_device, + struct libinput_tablet_tool *libinput_tool) +{ + ClutterInputDeviceEvdev *evdev_device = CLUTTER_INPUT_DEVICE_EVDEV (input_device); + ClutterInputDeviceTool *tool = NULL; + ClutterInputDeviceToolType tool_type; + guint64 tool_serial; + + if (libinput_tool) + { + tool_serial = libinput_tablet_tool_get_serial (libinput_tool); + tool_type = translate_tool_type (libinput_tool); + tool = clutter_input_device_lookup_tool (input_device, + tool_serial, tool_type); + + if (!tool) + { + tool = clutter_input_device_tool_evdev_new (libinput_tool, + tool_serial, tool_type); + clutter_input_device_add_tool (input_device, tool); + } + } + + evdev_device->last_tool = tool; +} + +static gdouble * +translate_tablet_axes (struct libinput_event_tablet_tool *tablet_event) +{ + GArray *axes = g_array_new (FALSE, FALSE, sizeof (gdouble)); + struct libinput_tablet_tool *libinput_tool; + gdouble value; + + libinput_tool = libinput_event_tablet_tool_get_tool (tablet_event); + + value = libinput_event_tablet_tool_get_x (tablet_event); + g_array_append_val (axes, value); + value = libinput_event_tablet_tool_get_y (tablet_event); + g_array_append_val (axes, value); + + if (libinput_tablet_tool_has_distance (libinput_tool)) + { + value = libinput_event_tablet_tool_get_distance (tablet_event); + g_array_append_val (axes, value); + } + + if (libinput_tablet_tool_has_pressure (libinput_tool)) + { + value = libinput_event_tablet_tool_get_pressure (tablet_event); + g_array_append_val (axes, value); + } + + if (libinput_tablet_tool_has_tilt (libinput_tool)) + { + value = libinput_event_tablet_tool_get_tilt_x (tablet_event); + g_array_append_val (axes, value); + value = libinput_event_tablet_tool_get_tilt_y (tablet_event); + g_array_append_val (axes, value); + } + + if (libinput_tablet_tool_has_rotation (libinput_tool)) + { + value = libinput_event_tablet_tool_get_rotation (tablet_event); + g_array_append_val (axes, value); + } + + if (libinput_tablet_tool_has_slider (libinput_tool)) + { + value = libinput_event_tablet_tool_get_slider_position (tablet_event); + g_array_append_val (axes, value); + } + + if (libinput_tablet_tool_has_wheel (libinput_tool)) + { + value = libinput_event_tablet_tool_get_wheel_delta (tablet_event); + g_array_append_val (axes, value); + } + + if (axes->len == 0) + { + g_array_free (axes, TRUE); + return NULL; + } + else + return (gdouble *) g_array_free (axes, FALSE); +} + +static ClutterSeatEvdev * +seat_from_device (ClutterInputDevice *device) +{ + ClutterInputDeviceEvdev *device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (device); + + return _clutter_input_device_evdev_get_seat (device_evdev); +} + +static gboolean +process_device_event (ClutterDeviceManagerEvdev *manager_evdev, + struct libinput_event *event) +{ + gboolean handled = TRUE; + struct libinput_device *libinput_device = libinput_event_get_device(event); + ClutterInputDevice *device; + + switch (libinput_event_get_type (event)) + { + case LIBINPUT_EVENT_KEYBOARD_KEY: + { + guint32 key, key_state, seat_key_count; + guint64 time_us; + struct libinput_event_keyboard *key_event = + libinput_event_get_keyboard_event (event); + + device = libinput_device_get_user_data (libinput_device); + time_us = libinput_event_keyboard_get_time_usec (key_event); + key = libinput_event_keyboard_get_key (key_event); + key_state = libinput_event_keyboard_get_key_state (key_event) == + LIBINPUT_KEY_STATE_PRESSED; + seat_key_count = + libinput_event_keyboard_get_seat_key_count (key_event); + + /* Ignore key events that are not seat wide state changes. */ + if ((key_state == LIBINPUT_KEY_STATE_PRESSED && + seat_key_count != 1) || + (key_state == LIBINPUT_KEY_STATE_RELEASED && + seat_key_count != 0)) + break; + + clutter_seat_evdev_notify_key (seat_from_device (device), + device, + time_us, key, key_state, TRUE); + + break; + } + + case LIBINPUT_EVENT_POINTER_MOTION: + { + struct libinput_event_pointer *pointer_event = + libinput_event_get_pointer_event (event); + uint64_t time_us; + double dx; + double dy; + double dx_unaccel; + double dy_unaccel; + + device = libinput_device_get_user_data (libinput_device); + time_us = libinput_event_pointer_get_time_usec (pointer_event); + dx = libinput_event_pointer_get_dx (pointer_event); + dy = libinput_event_pointer_get_dy (pointer_event); + dx_unaccel = libinput_event_pointer_get_dx_unaccelerated (pointer_event); + dy_unaccel = libinput_event_pointer_get_dy_unaccelerated (pointer_event); + + clutter_seat_evdev_notify_relative_motion (seat_from_device (device), + device, + time_us, + dx, dy, + dx_unaccel, dy_unaccel); + + break; + } + + case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: + { + guint64 time_us; + double x, y; + gfloat stage_width, stage_height; + ClutterStage *stage; + struct libinput_event_pointer *motion_event = + libinput_event_get_pointer_event (event); + device = libinput_device_get_user_data (libinput_device); + + stage = _clutter_input_device_get_stage (device); + if (stage == NULL) + break; + + stage_width = clutter_actor_get_width (CLUTTER_ACTOR (stage)); + stage_height = clutter_actor_get_height (CLUTTER_ACTOR (stage)); + + time_us = libinput_event_pointer_get_time_usec (motion_event); + x = libinput_event_pointer_get_absolute_x_transformed (motion_event, + stage_width); + y = libinput_event_pointer_get_absolute_y_transformed (motion_event, + stage_height); + + clutter_seat_evdev_notify_absolute_motion (seat_from_device (device), + device, + time_us, + x, y, + NULL); + + break; + } + + case LIBINPUT_EVENT_POINTER_BUTTON: + { + guint32 button, button_state, seat_button_count; + guint64 time_us; + struct libinput_event_pointer *button_event = + libinput_event_get_pointer_event (event); + device = libinput_device_get_user_data (libinput_device); + + time_us = libinput_event_pointer_get_time_usec (button_event); + button = libinput_event_pointer_get_button (button_event); + button_state = libinput_event_pointer_get_button_state (button_event) == + LIBINPUT_BUTTON_STATE_PRESSED; + seat_button_count = + libinput_event_pointer_get_seat_button_count (button_event); + + /* Ignore button events that are not seat wide state changes. */ + if ((button_state == LIBINPUT_BUTTON_STATE_PRESSED && + seat_button_count != 1) || + (button_state == LIBINPUT_BUTTON_STATE_RELEASED && + seat_button_count != 0)) + break; + + clutter_seat_evdev_notify_button (seat_from_device (device), device, + time_us, button, button_state); + break; + } + + case LIBINPUT_EVENT_POINTER_AXIS: + { + gdouble dx = 0.0, dy = 0.0; + gdouble discrete_x = 0.0, discrete_y = 0.0; + guint64 time_us; + gboolean wheel = FALSE; + enum libinput_pointer_axis axis; + enum libinput_pointer_axis_source source; + struct libinput_event_pointer *axis_event = + libinput_event_get_pointer_event (event); + ClutterSeatEvdev *seat; + ClutterScrollSource scroll_source; + ClutterScrollFinishFlags finish_flags = 0; + + device = libinput_device_get_user_data (libinput_device); + seat = _clutter_input_device_evdev_get_seat (CLUTTER_INPUT_DEVICE_EVDEV (device)); + + time_us = libinput_event_pointer_get_time_usec (axis_event); + source = libinput_event_pointer_get_axis_source (axis_event); + scroll_source = translate_scroll_source (source); + + /* libinput < 0.8 sent wheel click events with value 10. Since 0.8 + the value is the angle of the click in degrees. To keep + backwards-compat with existing clients, we just send multiples of + the click count. */ + + if (source == LIBINPUT_POINTER_AXIS_SOURCE_WHEEL) + wheel = TRUE; + + axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL; + if (libinput_event_pointer_has_axis (axis_event, axis)) + { + discrete_y = libinput_event_pointer_get_axis_value_discrete (axis_event, axis); + dy = libinput_event_pointer_get_axis_value (axis_event, axis); + + if (wheel) + seat->accum_scroll_dy = 0; + else if (fabs (dy) < DBL_EPSILON) + { + finish_flags |= CLUTTER_SCROLL_FINISHED_VERTICAL; + seat->accum_scroll_dy = 0; + } + else + seat->accum_scroll_dy += dy; + } + + axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL; + if (libinput_event_pointer_has_axis (axis_event, axis)) + { + discrete_x = libinput_event_pointer_get_axis_value_discrete (axis_event, axis); + dx = libinput_event_pointer_get_axis_value (axis_event, axis); + + if (wheel) + seat->accum_scroll_dx = 0; + else if (fabs (dx) < DBL_EPSILON) + { + finish_flags |= CLUTTER_SCROLL_FINISHED_HORIZONTAL; + seat->accum_scroll_dx = 0; + } + else + seat->accum_scroll_dx += dx; + } + + if (wheel) + { + notify_scroll (device, time_us, + discrete_x * DISCRETE_SCROLL_STEP, + discrete_y * DISCRETE_SCROLL_STEP, + scroll_source, finish_flags, TRUE); + notify_discrete_scroll (device, time_us, + discrete_to_direction (discrete_x, discrete_y), + scroll_source, FALSE); + } + else + { + notify_scroll (device, time_us, dx, dy, + scroll_source, finish_flags, FALSE); + check_notify_discrete_scroll (manager_evdev, device, + time_us, scroll_source); + } + + break; + + } + + case LIBINPUT_EVENT_TOUCH_DOWN: + { + gint32 slot; + guint64 time_us; + double x, y; + gfloat stage_width, stage_height; + ClutterSeatEvdev *seat; + ClutterStage *stage; + ClutterTouchState *touch_state; + struct libinput_event_touch *touch_event = + libinput_event_get_touch_event (event); + + device = libinput_device_get_user_data (libinput_device); + seat = _clutter_input_device_evdev_get_seat (CLUTTER_INPUT_DEVICE_EVDEV (device)); + + stage = _clutter_input_device_get_stage (device); + if (stage == NULL) + break; + + stage_width = clutter_actor_get_width (CLUTTER_ACTOR (stage)); + stage_height = clutter_actor_get_height (CLUTTER_ACTOR (stage)); + + slot = libinput_event_touch_get_slot (touch_event); + time_us = libinput_event_touch_get_time_usec (touch_event); + x = libinput_event_touch_get_x_transformed (touch_event, + stage_width); + y = libinput_event_touch_get_y_transformed (touch_event, + stage_height); + + touch_state = clutter_seat_evdev_add_touch (seat, slot); + touch_state->coords.x = x; + touch_state->coords.y = y; + + notify_touch_event (device, CLUTTER_TOUCH_BEGIN, time_us, slot, + touch_state->coords.x, touch_state->coords.y); + break; + } + + case LIBINPUT_EVENT_TOUCH_UP: + { + gint32 slot; + guint64 time_us; + ClutterSeatEvdev *seat; + ClutterTouchState *touch_state; + struct libinput_event_touch *touch_event = + libinput_event_get_touch_event (event); + + device = libinput_device_get_user_data (libinput_device); + seat = _clutter_input_device_evdev_get_seat (CLUTTER_INPUT_DEVICE_EVDEV (device)); + + slot = libinput_event_touch_get_slot (touch_event); + time_us = libinput_event_touch_get_time_usec (touch_event); + touch_state = clutter_seat_evdev_get_touch (seat, slot); + + notify_touch_event (device, CLUTTER_TOUCH_END, time_us, slot, + touch_state->coords.x, touch_state->coords.y); + clutter_seat_evdev_remove_touch (seat, slot); + + break; + } + + case LIBINPUT_EVENT_TOUCH_MOTION: + { + gint32 slot; + guint64 time_us; + double x, y; + gfloat stage_width, stage_height; + ClutterSeatEvdev *seat; + ClutterStage *stage; + ClutterTouchState *touch_state; + struct libinput_event_touch *touch_event = + libinput_event_get_touch_event (event); + + device = libinput_device_get_user_data (libinput_device); + seat = _clutter_input_device_evdev_get_seat (CLUTTER_INPUT_DEVICE_EVDEV (device)); + + stage = _clutter_input_device_get_stage (device); + if (stage == NULL) + break; + + stage_width = clutter_actor_get_width (CLUTTER_ACTOR (stage)); + stage_height = clutter_actor_get_height (CLUTTER_ACTOR (stage)); + + slot = libinput_event_touch_get_slot (touch_event); + time_us = libinput_event_touch_get_time_usec (touch_event); + x = libinput_event_touch_get_x_transformed (touch_event, + stage_width); + y = libinput_event_touch_get_y_transformed (touch_event, + stage_height); + + touch_state = clutter_seat_evdev_get_touch (seat, slot); + touch_state->coords.x = x; + touch_state->coords.y = y; + + notify_touch_event (device, CLUTTER_TOUCH_UPDATE, time_us, slot, + touch_state->coords.x, touch_state->coords.y); + break; + } + case LIBINPUT_EVENT_TOUCH_CANCEL: + { + ClutterTouchState *touch_state; + GHashTableIter iter; + guint64 time_us; + struct libinput_event_touch *touch_event = + libinput_event_get_touch_event (event); + ClutterSeatEvdev *seat; + + device = libinput_device_get_user_data (libinput_device); + time_us = libinput_event_touch_get_time_usec (touch_event); + seat = _clutter_input_device_evdev_get_seat (CLUTTER_INPUT_DEVICE_EVDEV (device)); + g_hash_table_iter_init (&iter, seat->touches); + + while (g_hash_table_iter_next (&iter, NULL, (gpointer*) &touch_state)) + { + notify_touch_event (device, CLUTTER_TOUCH_CANCEL, + time_us, touch_state->id, + touch_state->coords.x, touch_state->coords.y); + g_hash_table_iter_remove (&iter); + } + + break; + } + case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN: + case LIBINPUT_EVENT_GESTURE_PINCH_END: + { + struct libinput_event_gesture *gesture_event = + libinput_event_get_gesture_event (event); + ClutterTouchpadGesturePhase phase; + guint64 time_us; + + if (libinput_event_get_type (event) == LIBINPUT_EVENT_GESTURE_PINCH_BEGIN) + phase = CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN; + else + phase = libinput_event_gesture_get_cancelled (gesture_event) ? + CLUTTER_TOUCHPAD_GESTURE_PHASE_CANCEL : CLUTTER_TOUCHPAD_GESTURE_PHASE_END; + + device = libinput_device_get_user_data (libinput_device); + time_us = libinput_event_gesture_get_time_usec (gesture_event); + notify_pinch_gesture_event (device, phase, time_us, 0, 0, 0, 0); + break; + } + case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE: + { + struct libinput_event_gesture *gesture_event = + libinput_event_get_gesture_event (event); + gdouble angle_delta, scale, dx, dy; + guint64 time_us; + + device = libinput_device_get_user_data (libinput_device); + time_us = libinput_event_gesture_get_time_usec (gesture_event); + angle_delta = libinput_event_gesture_get_angle_delta (gesture_event); + scale = libinput_event_gesture_get_scale (gesture_event); + dx = libinput_event_gesture_get_dx (gesture_event); + dy = libinput_event_gesture_get_dx (gesture_event); + + notify_pinch_gesture_event (device, + CLUTTER_TOUCHPAD_GESTURE_PHASE_UPDATE, + time_us, dx, dy, angle_delta, scale); + break; + } + case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN: + case LIBINPUT_EVENT_GESTURE_SWIPE_END: + { + struct libinput_event_gesture *gesture_event = + libinput_event_get_gesture_event (event); + ClutterTouchpadGesturePhase phase; + guint32 n_fingers; + guint64 time_us; + + device = libinput_device_get_user_data (libinput_device); + time_us = libinput_event_gesture_get_time_usec (gesture_event); + n_fingers = libinput_event_gesture_get_finger_count (gesture_event); + + if (libinput_event_get_type (event) == LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN) + phase = CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN; + else + phase = libinput_event_gesture_get_cancelled (gesture_event) ? + CLUTTER_TOUCHPAD_GESTURE_PHASE_CANCEL : CLUTTER_TOUCHPAD_GESTURE_PHASE_END; + + notify_swipe_gesture_event (device, phase, time_us, n_fingers, 0, 0); + break; + } + case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE: + { + struct libinput_event_gesture *gesture_event = + libinput_event_get_gesture_event (event); + guint32 n_fingers; + guint64 time_us; + gdouble dx, dy; + + device = libinput_device_get_user_data (libinput_device); + time_us = libinput_event_gesture_get_time_usec (gesture_event); + n_fingers = libinput_event_gesture_get_finger_count (gesture_event); + dx = libinput_event_gesture_get_dx (gesture_event); + dy = libinput_event_gesture_get_dy (gesture_event); + + notify_swipe_gesture_event (device, + CLUTTER_TOUCHPAD_GESTURE_PHASE_UPDATE, + time_us, n_fingers, dx, dy); + break; + } + case LIBINPUT_EVENT_TABLET_TOOL_AXIS: + { + guint64 time; + double x, y, dx, dy, *axes; + gfloat stage_width, stage_height; + ClutterStage *stage; + struct libinput_event_tablet_tool *tablet_event = + libinput_event_get_tablet_tool_event (event); + ClutterInputDeviceEvdev *evdev_device; + + device = libinput_device_get_user_data (libinput_device); + evdev_device = CLUTTER_INPUT_DEVICE_EVDEV (device); + + stage = _clutter_input_device_get_stage (device); + if (!stage) + break; + + axes = translate_tablet_axes (tablet_event); + if (!axes) + break; + + stage_width = clutter_actor_get_width (CLUTTER_ACTOR (stage)); + stage_height = clutter_actor_get_height (CLUTTER_ACTOR (stage)); + + time = libinput_event_tablet_tool_get_time_usec (tablet_event); + + if (clutter_input_device_get_mapping_mode (device) == CLUTTER_INPUT_DEVICE_MAPPING_RELATIVE || + clutter_input_device_tool_get_tool_type (evdev_device->last_tool) == CLUTTER_INPUT_DEVICE_TOOL_MOUSE || + clutter_input_device_tool_get_tool_type (evdev_device->last_tool) == CLUTTER_INPUT_DEVICE_TOOL_LENS) + { + dx = libinput_event_tablet_tool_get_dx (tablet_event); + dy = libinput_event_tablet_tool_get_dy (tablet_event); + notify_relative_tool_motion (device, time, dx, dy, axes); + } + else + { + x = libinput_event_tablet_tool_get_x_transformed (tablet_event, stage_width); + y = libinput_event_tablet_tool_get_y_transformed (tablet_event, stage_height); + notify_absolute_motion (device, time, x, y, axes); + } + + break; + } + case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY: + { + guint64 time; + struct libinput_event_tablet_tool *tablet_event = + libinput_event_get_tablet_tool_event (event); + struct libinput_tablet_tool *libinput_tool = NULL; + enum libinput_tablet_tool_proximity_state state; + + state = libinput_event_tablet_tool_get_proximity_state (tablet_event); + time = libinput_event_tablet_tool_get_time_usec (tablet_event); + device = libinput_device_get_user_data (libinput_device); + + libinput_tool = libinput_event_tablet_tool_get_tool (tablet_event); + + input_device_update_tool (device, libinput_tool); + notify_proximity (device, time, state == LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN); + break; + } + case LIBINPUT_EVENT_TABLET_TOOL_BUTTON: + { + guint64 time_us; + guint32 button_state; + struct libinput_event_tablet_tool *tablet_event = + libinput_event_get_tablet_tool_event (event); + guint tablet_button; + + device = libinput_device_get_user_data (libinput_device); + time_us = libinput_event_tablet_tool_get_time_usec (tablet_event); + tablet_button = libinput_event_tablet_tool_get_button (tablet_event); + + button_state = libinput_event_tablet_tool_get_button_state (tablet_event) == + LIBINPUT_BUTTON_STATE_PRESSED; + + clutter_seat_evdev_notify_button (seat_from_device (device), device, + time_us, tablet_button, button_state); + break; + } + case LIBINPUT_EVENT_TABLET_TOOL_TIP: + { + guint64 time_us; + guint32 button_state; + struct libinput_event_tablet_tool *tablet_event = + libinput_event_get_tablet_tool_event (event); + + device = libinput_device_get_user_data (libinput_device); + time_us = libinput_event_tablet_tool_get_time_usec (tablet_event); + + button_state = libinput_event_tablet_tool_get_tip_state (tablet_event) == + LIBINPUT_TABLET_TOOL_TIP_DOWN; + + clutter_seat_evdev_notify_button (seat_from_device (device), device, + time_us, BTN_TOUCH, button_state); + break; + } + case LIBINPUT_EVENT_TABLET_PAD_BUTTON: + { + guint64 time; + guint32 button_state, button, group; + struct libinput_tablet_pad_mode_group *mode_group; + struct libinput_event_tablet_pad *pad_event = + libinput_event_get_tablet_pad_event (event); + + device = libinput_device_get_user_data (libinput_device); + time = libinput_event_tablet_pad_get_time_usec (pad_event); + + mode_group = libinput_event_tablet_pad_get_mode_group (pad_event); + group = libinput_tablet_pad_mode_group_get_index (mode_group); + + button = libinput_event_tablet_pad_get_button_number (pad_event); + button_state = libinput_event_tablet_pad_get_button_state (pad_event) == + LIBINPUT_BUTTON_STATE_PRESSED; + notify_pad_button (device, time, button, group, button_state); + break; + } + case LIBINPUT_EVENT_TABLET_PAD_STRIP: + { + guint64 time; + guint32 number, source, group; + struct libinput_tablet_pad_mode_group *mode_group; + struct libinput_event_tablet_pad *pad_event = + libinput_event_get_tablet_pad_event (event); + gdouble value; + + device = libinput_device_get_user_data (libinput_device); + time = libinput_event_tablet_pad_get_time_usec (pad_event); + number = libinput_event_tablet_pad_get_strip_number (pad_event); + value = libinput_event_tablet_pad_get_strip_position (pad_event); + source = libinput_event_tablet_pad_get_strip_source (pad_event); + + mode_group = libinput_event_tablet_pad_get_mode_group (pad_event); + group = libinput_tablet_pad_mode_group_get_index (mode_group); + + notify_pad_strip (device, time, number, source, group, value); + break; + } + case LIBINPUT_EVENT_TABLET_PAD_RING: + { + guint64 time; + guint32 number, source, group; + struct libinput_tablet_pad_mode_group *mode_group; + struct libinput_event_tablet_pad *pad_event = + libinput_event_get_tablet_pad_event (event); + gdouble angle; + + device = libinput_device_get_user_data (libinput_device); + time = libinput_event_tablet_pad_get_time_usec (pad_event); + number = libinput_event_tablet_pad_get_ring_number (pad_event); + angle = libinput_event_tablet_pad_get_ring_position (pad_event); + source = libinput_event_tablet_pad_get_ring_source (pad_event); + + mode_group = libinput_event_tablet_pad_get_mode_group (pad_event); + group = libinput_tablet_pad_mode_group_get_index (mode_group); + + notify_pad_ring (device, time, number, source, group, angle); + break; + } + default: + handled = FALSE; + } + + return handled; +} + +static gboolean +filter_event (ClutterDeviceManagerEvdev *manager_evdev, + struct libinput_event *event) +{ + gboolean retval = CLUTTER_EVENT_PROPAGATE; + ClutterEventFilter *filter; + GSList *tmp_list; + + tmp_list = manager_evdev->priv->event_filters; + + while (tmp_list) + { + filter = tmp_list->data; + retval = filter->func (event, filter->data); + tmp_list = tmp_list->next; + + if (retval != CLUTTER_EVENT_PROPAGATE) + break; + } + + return retval; +} + +static void +process_event (ClutterDeviceManagerEvdev *manager_evdev, + struct libinput_event *event) +{ + gboolean retval; + + retval = filter_event (manager_evdev, event); + + if (retval != CLUTTER_EVENT_PROPAGATE) + return; + + if (process_base_event (manager_evdev, event)) + return; + if (process_device_event (manager_evdev, event)) + return; +} + +static void +process_events (ClutterDeviceManagerEvdev *manager_evdev) +{ + ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv; + struct libinput_event *event; + + while ((event = libinput_get_event (priv->libinput))) + { + process_event(manager_evdev, event); + libinput_event_destroy(event); + } +} + +static int +open_restricted (const char *path, + int flags, + void *user_data) +{ + gint fd; + + if (device_open_callback) + { + GError *error = NULL; + + fd = device_open_callback (path, flags, device_callback_data, &error); + + if (fd < 0) + { + g_warning ("Could not open device %s: %s", path, error->message); + g_error_free (error); + } + } + else + { + fd = open (path, O_RDWR | O_NONBLOCK); + if (fd < 0) + { + g_warning ("Could not open device %s: %s", path, strerror (errno)); + } + } + + return fd; +} + +static void +close_restricted (int fd, + void *user_data) +{ + if (device_close_callback) + device_close_callback (fd, device_callback_data); + else + close (fd); +} + +static const struct libinput_interface libinput_interface = { + open_restricted, + close_restricted +}; + +static ClutterVirtualInputDevice * +clutter_device_manager_evdev_create_virtual_device (ClutterDeviceManager *manager, + ClutterInputDeviceType device_type) +{ + ClutterDeviceManagerEvdev *manager_evdev = + CLUTTER_DEVICE_MANAGER_EVDEV (manager); + ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv; + + return g_object_new (CLUTTER_TYPE_VIRTUAL_INPUT_DEVICE_EVDEV, + "device-manager", manager, + "seat", priv->main_seat, + "device-type", device_type, + NULL); +} + +static void +clutter_device_manager_evdev_compress_motion (ClutterDeviceManager *device_manger, + ClutterEvent *event, + const ClutterEvent *to_discard) +{ + double dx, dy; + double dx_unaccel, dy_unaccel; + double dst_dx = 0.0, dst_dy = 0.0; + double dst_dx_unaccel = 0.0, dst_dy_unaccel = 0.0; + + if (!clutter_evdev_event_get_relative_motion (to_discard, + &dx, &dy, + &dx_unaccel, &dy_unaccel)) + return; + + clutter_evdev_event_get_relative_motion (event, + &dst_dx, &dst_dy, + &dst_dx_unaccel, &dst_dy_unaccel); + _clutter_evdev_event_set_relative_motion (event, + dx + dst_dx, + dy + dst_dy, + dx_unaccel + dst_dx_unaccel, + dy_unaccel + dst_dy_unaccel); +} + +/* + * GObject implementation + */ + +static void +clutter_device_manager_evdev_constructed (GObject *gobject) +{ + ClutterDeviceManagerEvdev *manager_evdev; + ClutterDeviceManagerEvdevPrivate *priv; + ClutterEventSource *source; + struct udev *udev; + struct xkb_context *ctx; + struct xkb_rule_names names; + + udev = udev_new (); + if (G_UNLIKELY (udev == NULL)) + { + g_warning ("Failed to create udev object"); + return; + } + + manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (gobject); + priv = manager_evdev->priv; + + priv->libinput = libinput_udev_create_context (&libinput_interface, + manager_evdev, + udev); + if (priv->libinput == NULL) + { + g_critical ("Failed to create the libinput object."); + return; + } + + if (libinput_udev_assign_seat (priv->libinput, "seat0") == -1) + { + g_critical ("Failed to assign a seat to the libinput object."); + libinput_unref (priv->libinput); + priv->libinput = NULL; + return; + } + + udev_unref (udev); + + names.rules = "evdev"; + names.model = "pc105"; + names.layout = option_xkb_layout; + names.variant = option_xkb_variant; + names.options = option_xkb_options; + + ctx = xkb_context_new (0); + g_assert (ctx); + priv->keymap = xkb_keymap_new_from_names (ctx, &names, 0); + xkb_context_unref (ctx); + + priv->main_seat = clutter_seat_evdev_new (manager_evdev); + + dispatch_libinput (manager_evdev); + + source = clutter_event_source_new (manager_evdev); + priv->event_source = source; +} + +static void +clutter_device_manager_evdev_dispose (GObject *object) +{ + ClutterDeviceManagerEvdev *manager_evdev; + ClutterDeviceManagerEvdevPrivate *priv; + + manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (object); + priv = manager_evdev->priv; + + if (priv->stage_added_handler) + { + g_signal_handler_disconnect (priv->stage_manager, + priv->stage_added_handler); + priv->stage_added_handler = 0; + } + + if (priv->stage_removed_handler) + { + g_signal_handler_disconnect (priv->stage_manager, + priv->stage_removed_handler); + priv->stage_removed_handler = 0; + } + + if (priv->stage_manager) + { + g_object_unref (priv->stage_manager); + priv->stage_manager = NULL; + } + + G_OBJECT_CLASS (clutter_device_manager_evdev_parent_class)->dispose (object); +} + +static void +clutter_device_manager_evdev_finalize (GObject *object) +{ + ClutterDeviceManagerEvdev *manager_evdev; + ClutterDeviceManagerEvdevPrivate *priv; + + manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (object); + priv = manager_evdev->priv; + + g_slist_free_full (priv->seats, (GDestroyNotify) clutter_seat_evdev_free); + g_slist_free (priv->devices); + + if (priv->keymap) + xkb_keymap_unref (priv->keymap); + + if (priv->event_source != NULL) + clutter_event_source_free (priv->event_source); + + if (priv->constrain_data_notify != NULL) + priv->constrain_data_notify (priv->constrain_data); + + if (priv->libinput != NULL) + libinput_unref (priv->libinput); + + g_list_free (priv->free_device_ids); + + G_OBJECT_CLASS (clutter_device_manager_evdev_parent_class)->finalize (object); +} + +static void +clutter_device_manager_evdev_class_init (ClutterDeviceManagerEvdevClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterDeviceManagerClass *manager_class; + + gobject_class->constructed = clutter_device_manager_evdev_constructed; + gobject_class->finalize = clutter_device_manager_evdev_finalize; + gobject_class->dispose = clutter_device_manager_evdev_dispose; + + manager_class = CLUTTER_DEVICE_MANAGER_CLASS (klass); + manager_class->add_device = clutter_device_manager_evdev_add_device; + manager_class->remove_device = clutter_device_manager_evdev_remove_device; + manager_class->get_devices = clutter_device_manager_evdev_get_devices; + manager_class->get_core_device = clutter_device_manager_evdev_get_core_device; + manager_class->get_device = clutter_device_manager_evdev_get_device; + manager_class->create_virtual_device = clutter_device_manager_evdev_create_virtual_device; + manager_class->compress_motion = clutter_device_manager_evdev_compress_motion; +} + +static void +clutter_device_manager_evdev_stage_added_cb (ClutterStageManager *manager, + ClutterStage *stage, + ClutterDeviceManagerEvdev *self) +{ + ClutterDeviceManagerEvdevPrivate *priv = self->priv; + GSList *l; + + /* NB: Currently we can only associate a single stage with all evdev + * devices. + * + * We save a pointer to the stage so if we release/reclaim input + * devices due to switching virtual terminals then we know what + * stage to re associate the devices with. + */ + priv->stage = stage; + + /* Set the stage of any devices that don't already have a stage */ + for (l = priv->seats; l; l = l->next) + { + ClutterSeatEvdev *seat = l->data; + + clutter_seat_evdev_set_stage (seat, stage); + } + + /* We only want to do this once so we can catch the default + stage. If the application has multiple stages then it will need + to manage the stage of the input devices itself */ + g_signal_handler_disconnect (priv->stage_manager, + priv->stage_added_handler); + priv->stage_added_handler = 0; +} + +static void +clutter_device_manager_evdev_stage_removed_cb (ClutterStageManager *manager, + ClutterStage *stage, + ClutterDeviceManagerEvdev *self) +{ + ClutterDeviceManagerEvdevPrivate *priv = self->priv; + GSList *l; + + /* Remove the stage of any input devices that were pointing to this + stage so we don't send events to invalid stages */ + for (l = priv->seats; l; l = l->next) + { + ClutterSeatEvdev *seat = l->data; + + clutter_seat_evdev_set_stage (seat, NULL); + } +} + +static void +clutter_device_manager_evdev_init (ClutterDeviceManagerEvdev *self) +{ + ClutterDeviceManagerEvdevPrivate *priv; + + priv = self->priv = clutter_device_manager_evdev_get_instance_private (self); + + priv->stage_manager = clutter_stage_manager_get_default (); + g_object_ref (priv->stage_manager); + + /* evdev doesn't have any way to link an event to a particular stage + so we'll have to leave it up to applications to set the + corresponding stage for an input device. However to make it + easier for applications that are only using one fullscreen stage + (which is probably the most frequent use-case for the evdev + backend) we'll associate any input devices that don't have a + stage with the first stage created. */ + priv->stage_added_handler = + g_signal_connect (priv->stage_manager, + "stage-added", + G_CALLBACK (clutter_device_manager_evdev_stage_added_cb), + self); + priv->stage_removed_handler = + g_signal_connect (priv->stage_manager, + "stage-removed", + G_CALLBACK (clutter_device_manager_evdev_stage_removed_cb), + self); + + priv->device_id_next = INITIAL_DEVICE_ID; +} + +void +_clutter_events_evdev_init (ClutterBackend *backend) +{ + CLUTTER_NOTE (EVENT, "Initializing evdev backend"); + + backend->device_manager = g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_EVDEV, + "backend", backend, + NULL); +} + +void +_clutter_events_evdev_uninit (ClutterBackend *backend) +{ + CLUTTER_NOTE (EVENT, "Uninitializing evdev backend"); +} + +gint +_clutter_device_manager_evdev_acquire_device_id (ClutterDeviceManagerEvdev *manager_evdev) +{ + ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv; + GList *first; + gint next_id; + + if (priv->free_device_ids == NULL) + { + gint i; + + /* We ran out of free ID's, so append 10 new ones. */ + for (i = 0; i < 10; i++) + priv->free_device_ids = + g_list_append (priv->free_device_ids, + GINT_TO_POINTER (priv->device_id_next++)); + } + + first = g_list_first (priv->free_device_ids); + next_id = GPOINTER_TO_INT (first->data); + priv->free_device_ids = g_list_remove_link (priv->free_device_ids, first); + + return next_id; +} + +void +_clutter_device_manager_evdev_dispatch (ClutterDeviceManagerEvdev *manager_evdev) +{ + dispatch_libinput (manager_evdev); +} + +static int +compare_ids (gconstpointer a, + gconstpointer b) +{ + return GPOINTER_TO_INT (a) - GPOINTER_TO_INT (b); +} + +void +_clutter_device_manager_evdev_release_device_id (ClutterDeviceManagerEvdev *manager_evdev, + ClutterInputDevice *device) +{ + ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv; + gint device_id; + + device_id = clutter_input_device_get_device_id (device); + priv->free_device_ids = g_list_insert_sorted (priv->free_device_ids, + GINT_TO_POINTER (device_id), + compare_ids); +} + +struct xkb_keymap * +_clutter_device_manager_evdev_get_keymap (ClutterDeviceManagerEvdev *manager_evdev) +{ + ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv; + + return priv->keymap; +} + +ClutterStage * +_clutter_device_manager_evdev_get_stage (ClutterDeviceManagerEvdev *manager_evdev) +{ + ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv; + + return priv->stage; +} + +/** + * clutter_evdev_release_devices: + * + * Releases all the evdev devices that Clutter is currently managing. This api + * is typically used when switching away from the Clutter application when + * switching tty. The devices can be reclaimed later with a call to + * clutter_evdev_reclaim_devices(). + * + * This function should only be called after clutter has been initialized. + * + * Since: 1.10 + * Stability: unstable + */ +void +clutter_evdev_release_devices (void) +{ + ClutterDeviceManager *manager = clutter_device_manager_get_default (); + ClutterDeviceManagerEvdev *manager_evdev; + ClutterDeviceManagerEvdevPrivate *priv; + + if (!manager) + { + g_warning ("clutter_evdev_release_devices shouldn't be called " + "before clutter_init()"); + return; + } + + g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER_EVDEV (manager)); + + manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager); + priv = manager_evdev->priv; + + if (priv->released) + { + g_warning ("clutter_evdev_release_devices() shouldn't be called " + "multiple times without a corresponding call to " + "clutter_evdev_reclaim_devices() first"); + return; + } + + libinput_suspend (priv->libinput); + process_events (manager_evdev); + + priv->released = TRUE; +} + +static void +clutter_evdev_update_xkb_state (ClutterDeviceManagerEvdev *manager_evdev) +{ + ClutterDeviceManagerEvdevPrivate *priv; + GSList *iter; + ClutterSeatEvdev *seat; + xkb_mod_mask_t latched_mods; + xkb_mod_mask_t locked_mods; + + priv = manager_evdev->priv; + + for (iter = priv->seats; iter; iter = iter->next) + { + seat = iter->data; + + latched_mods = xkb_state_serialize_mods (seat->xkb, + XKB_STATE_MODS_LATCHED); + locked_mods = xkb_state_serialize_mods (seat->xkb, + XKB_STATE_MODS_LOCKED); + xkb_state_unref (seat->xkb); + seat->xkb = xkb_state_new (priv->keymap); + + xkb_state_update_mask (seat->xkb, + 0, /* depressed */ + latched_mods, + locked_mods, + 0, 0, 0); + + seat->caps_lock_led = xkb_keymap_led_get_index (priv->keymap, XKB_LED_NAME_CAPS); + seat->num_lock_led = xkb_keymap_led_get_index (priv->keymap, XKB_LED_NAME_NUM); + seat->scroll_lock_led = xkb_keymap_led_get_index (priv->keymap, XKB_LED_NAME_SCROLL); + + clutter_seat_evdev_sync_leds (seat); + } +} + +/** + * clutter_evdev_reclaim_devices: + * + * This causes Clutter to re-probe for evdev devices. This is must only be + * called after a corresponding call to clutter_evdev_release_devices() + * was previously used to release all evdev devices. This API is typically + * used when a clutter application using evdev has regained focus due to + * switching ttys. + * + * This function should only be called after clutter has been initialized. + * + * Since: 1.10 + * Stability: unstable + */ +void +clutter_evdev_reclaim_devices (void) +{ + ClutterDeviceManager *manager = clutter_device_manager_get_default (); + ClutterDeviceManagerEvdev *manager_evdev = + CLUTTER_DEVICE_MANAGER_EVDEV (manager); + ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv; + + if (!priv->released) + { + g_warning ("Spurious call to clutter_evdev_reclaim_devices() without " + "previous call to clutter_evdev_release_devices"); + return; + } + + libinput_resume (priv->libinput); + clutter_evdev_update_xkb_state (manager_evdev); + process_events (manager_evdev); + + priv->released = FALSE; +} + +/** + * clutter_evdev_set_device_callbacks: (skip) + * @open_callback: the user replacement for open() + * @close_callback: the user replacement for close() + * @user_data: user data for @callback + * + * Through this function, the application can set a custom callback + * to invoked when Clutter is about to open an evdev device. It can do + * so if special handling is needed, for example to circumvent permission + * problems. + * + * Setting @callback to %NULL will reset the default behavior. + * + * For reliable effects, this function must be called before clutter_init(). + * + * Since: 1.16 + * Stability: unstable + */ +void +clutter_evdev_set_device_callbacks (ClutterOpenDeviceCallback open_callback, + ClutterCloseDeviceCallback close_callback, + gpointer user_data) +{ + device_open_callback = open_callback; + device_close_callback = close_callback; + device_callback_data = user_data; +} + +/** + * clutter_evdev_set_keyboard_map: (skip) + * @evdev: the #ClutterDeviceManager created by the evdev backend + * @keymap: the new keymap + * + * Instructs @evdev to use the speficied keyboard map. This will cause + * the backend to drop the state and create a new one with the new + * map. To avoid state being lost, callers should ensure that no key + * is pressed when calling this function. + * + * Since: 1.16 + * Stability: unstable + */ +void +clutter_evdev_set_keyboard_map (ClutterDeviceManager *evdev, + struct xkb_keymap *keymap) +{ + ClutterDeviceManagerEvdev *manager_evdev; + ClutterDeviceManagerEvdevPrivate *priv; + + g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER_EVDEV (evdev)); + + manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (evdev); + priv = manager_evdev->priv; + + if (priv->keymap) + xkb_keymap_unref (priv->keymap); + + priv->keymap = xkb_keymap_ref (keymap); + clutter_evdev_update_xkb_state (manager_evdev); +} + +/** + * clutter_evdev_get_keyboard_map: (skip) + * @evdev: the #ClutterDeviceManager created by the evdev backend + * + * Retrieves the #xkb_keymap in use by the evdev backend. + * + * Return value: the #xkb_keymap. + * + * Since: 1.18 + * Stability: unstable + */ +struct xkb_keymap * +clutter_evdev_get_keyboard_map (ClutterDeviceManager *evdev) +{ + ClutterDeviceManagerEvdev *manager_evdev; + + g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER_EVDEV (evdev), NULL); + + manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (evdev); + + return xkb_state_get_keymap (manager_evdev->priv->main_seat->xkb); +} + +/** + * clutter_evdev_set_keyboard_layout_index: (skip) + * @evdev: the #ClutterDeviceManager created by the evdev backend + * @idx: the xkb layout index to set + * + * Sets the xkb layout index on the backend's #xkb_state . + * + * Since: 1.20 + * Stability: unstable + */ +void +clutter_evdev_set_keyboard_layout_index (ClutterDeviceManager *evdev, + xkb_layout_index_t idx) +{ + ClutterDeviceManagerEvdev *manager_evdev; + xkb_mod_mask_t depressed_mods; + xkb_mod_mask_t latched_mods; + xkb_mod_mask_t locked_mods; + struct xkb_state *state; + + g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER_EVDEV (evdev)); + + manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (evdev); + state = manager_evdev->priv->main_seat->xkb; + + depressed_mods = xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED); + latched_mods = xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED); + locked_mods = xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED); + + xkb_state_update_mask (state, depressed_mods, latched_mods, locked_mods, 0, 0, idx); +} + +/** + * clutter_evdev_set_keyboard_numlock: (skip) + * @evdev: the #ClutterDeviceManager created by the evdev backend + * @numlock_set: TRUE to set NumLock ON, FALSE otherwise. + * + * Sets the NumLock state on the backend's #xkb_state . + * + * Stability: unstable + */ +void +clutter_evdev_set_keyboard_numlock (ClutterDeviceManager *evdev, + gboolean numlock_state) +{ + ClutterDeviceManagerEvdev *manager_evdev; + ClutterDeviceManagerEvdevPrivate *priv; + GSList *iter; + xkb_mod_mask_t numlock; + + g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER_EVDEV (evdev)); + + manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (evdev); + priv = manager_evdev->priv; + numlock = (1 << xkb_keymap_mod_get_index(priv->keymap, "Mod2")); + + for (iter = priv->seats; iter; iter = iter->next) + { + ClutterSeatEvdev *seat = iter->data; + xkb_mod_mask_t depressed_mods; + xkb_mod_mask_t latched_mods; + xkb_mod_mask_t locked_mods; + xkb_mod_mask_t group_mods; + + depressed_mods = xkb_state_serialize_mods (seat->xkb, XKB_STATE_MODS_DEPRESSED); + latched_mods = xkb_state_serialize_mods (seat->xkb, XKB_STATE_MODS_LATCHED); + locked_mods = xkb_state_serialize_mods (seat->xkb, XKB_STATE_MODS_LOCKED); + group_mods = xkb_state_serialize_layout (seat->xkb, XKB_STATE_LAYOUT_EFFECTIVE); + + if (numlock_state) + locked_mods |= numlock; + else + locked_mods &= ~numlock; + + xkb_state_update_mask (seat->xkb, + depressed_mods, + latched_mods, + locked_mods, + 0, 0, + group_mods); + + clutter_seat_evdev_sync_leds (seat); + } +} + + +/** + * clutter_evdev_set_pointer_constrain_callback: + * @evdev: the #ClutterDeviceManager created by the evdev backend + * @callback: the callback + * @user_data: data to pass to the callback + * @user_data_notify: function to be called when removing the callback + * + * Sets a callback to be invoked for every pointer motion. The callback + * can then modify the new pointer coordinates to constrain movement within + * a specific region. + * + * Since: 1.16 + * Stability: unstable + */ +void +clutter_evdev_set_pointer_constrain_callback (ClutterDeviceManager *evdev, + ClutterPointerConstrainCallback callback, + gpointer user_data, + GDestroyNotify user_data_notify) +{ + ClutterDeviceManagerEvdev *manager_evdev; + ClutterDeviceManagerEvdevPrivate *priv; + + g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER_EVDEV (evdev)); + + manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (evdev); + priv = manager_evdev->priv; + + if (priv->constrain_data_notify) + priv->constrain_data_notify (priv->constrain_data); + + priv->constrain_callback = callback; + priv->constrain_data = user_data; + priv->constrain_data_notify = user_data_notify; +} + +/** + * clutter_evdev_set_keyboard_repeat: + * @evdev: the #ClutterDeviceManager created by the evdev backend + * @repeat: whether to enable or disable keyboard repeat events + * @delay: the delay in ms between the hardware key press event and + * the first synthetic event + * @interval: the period in ms between consecutive synthetic key + * press events + * + * Enables or disables sythetic key press events, allowing for initial + * delay and interval period to be specified. + * + * Since: 1.18 + * Stability: unstable + */ +void +clutter_evdev_set_keyboard_repeat (ClutterDeviceManager *evdev, + gboolean repeat, + guint32 delay, + guint32 interval) +{ + ClutterDeviceManagerEvdev *manager_evdev; + ClutterSeatEvdev *seat; + + g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER_EVDEV (evdev)); + + manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (evdev); + seat = manager_evdev->priv->main_seat; + + seat->repeat = repeat; + seat->repeat_delay = delay; + seat->repeat_interval = interval; +} + +/** + * clutter_evdev_add_filter: (skip) + * @func: (closure data): a filter function + * @data: (allow-none): user data to be passed to the filter function, or %NULL + * @destroy_notify: (allow-none): function to call on @data when the filter is removed, or %NULL + * + * Adds an event filter function. + * + * Since: 1.20 + * Stability: unstable + */ +void +clutter_evdev_add_filter (ClutterEvdevFilterFunc func, + gpointer data, + GDestroyNotify destroy_notify) +{ + ClutterDeviceManagerEvdev *manager_evdev; + ClutterDeviceManager *manager; + ClutterEventFilter *filter; + + g_return_if_fail (func != NULL); + + manager = clutter_device_manager_get_default (); + + if (!CLUTTER_IS_DEVICE_MANAGER_EVDEV (manager)) + { + g_critical ("The Clutter input backend is not a evdev backend"); + return; + } + + manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager); + + filter = g_new0 (ClutterEventFilter, 1); + filter->func = func; + filter->data = data; + filter->destroy_notify = destroy_notify; + + manager_evdev->priv->event_filters = + g_slist_append (manager_evdev->priv->event_filters, filter); +} + +/** + * clutter_evdev_remove_filter: (skip) + * @func: a filter function + * @data: (allow-none): user data to be passed to the filter function, or %NULL + * + * Removes the given filter function. + * + * Since: 1.20 + * Stability: unstable + */ +void +clutter_evdev_remove_filter (ClutterEvdevFilterFunc func, + gpointer data) +{ + ClutterDeviceManagerEvdev *manager_evdev; + ClutterDeviceManager *manager; + ClutterEventFilter *filter; + GSList *tmp_list; + + g_return_if_fail (func != NULL); + + manager = clutter_device_manager_get_default (); + + if (!CLUTTER_IS_DEVICE_MANAGER_EVDEV (manager)) + { + g_critical ("The Clutter input backend is not a evdev backend"); + return; + } + + manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager); + tmp_list = manager_evdev->priv->event_filters; + + while (tmp_list) + { + filter = tmp_list->data; + + if (filter->func == func && filter->data == data) + { + if (filter->destroy_notify) + filter->destroy_notify (filter->data); + g_free (filter); + manager_evdev->priv->event_filters = + g_slist_delete_link (manager_evdev->priv->event_filters, tmp_list); + return; + } + + tmp_list = tmp_list->next; + } +} + +/** + * clutter_evdev_warp_pointer: + * @pointer_device: the pointer device to warp + * @time: the timestamp for the warp event + * @x: the new X position of the pointer + * @y: the new Y position of the pointer + * + * Warps the pointer to a new location. Technically, this is + * processed the same way as an absolute motion event from + * libinput: it simply generates an absolute motion event that + * will be processed on the next iteration of the mainloop. + * + * The intended use for this is for display servers that need + * to warp cursor the cursor to a new location. + * + * Since: 1.20 + * Stability: unstable + */ +void +clutter_evdev_warp_pointer (ClutterInputDevice *pointer_device, + guint32 time_, + int x, + int y) +{ + notify_absolute_motion (pointer_device, ms2us(time_), x, y, NULL); +} diff --git a/clutter/clutter/evdev/clutter-device-manager-evdev.h b/clutter/clutter/evdev/clutter-device-manager-evdev.h new file mode 100644 index 0000000..c2dbe31 --- /dev/null +++ b/clutter/clutter/evdev/clutter-device-manager-evdev.h @@ -0,0 +1,101 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corp. + * + * 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 . + * + * Author: Damien Lespiau + */ + +#ifndef __CLUTTER_DEVICE_MANAGER_EVDEV_H__ +#define __CLUTTER_DEVICE_MANAGER_EVDEV_H__ + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_DEVICE_MANAGER_EVDEV (clutter_device_manager_evdev_get_type ()) +#define CLUTTER_DEVICE_MANAGER_EVDEV(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_DEVICE_MANAGER_EVDEV, ClutterDeviceManagerEvdev)) +#define CLUTTER_IS_DEVICE_MANAGER_EVDEV(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_DEVICE_MANAGER_EVDEV)) +#define CLUTTER_DEVICE_MANAGER_EVDEV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_DEVICE_MANAGER_EVDEV, ClutterDeviceManagerEvdevClass)) +#define CLUTTER_IS_DEVICE_MANAGER_EVDEV_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_DEVICE_MANAGER_EVDEV)) +#define CLUTTER_DEVICE_MANAGER_EVDEV_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_DEVICE_MANAGER_EVDEV, ClutterDeviceManagerEvdevClass)) + +typedef struct _ClutterDeviceManagerEvdev ClutterDeviceManagerEvdev; +typedef struct _ClutterDeviceManagerEvdevClass ClutterDeviceManagerEvdevClass; +typedef struct _ClutterDeviceManagerEvdevPrivate ClutterDeviceManagerEvdevPrivate; + +typedef struct _ClutterSeatEvdev ClutterSeatEvdev; + +struct _ClutterDeviceManagerEvdev +{ + ClutterDeviceManager parent_instance; + + ClutterDeviceManagerEvdevPrivate *priv; +}; + +struct _ClutterDeviceManagerEvdevClass +{ + ClutterDeviceManagerClass parent_class; +}; + +GType clutter_device_manager_evdev_get_type (void) G_GNUC_CONST; + +void _clutter_events_evdev_init (ClutterBackend *backend); +void _clutter_events_evdev_uninit (ClutterBackend *backend); + +gint _clutter_device_manager_evdev_acquire_device_id (ClutterDeviceManagerEvdev *manager_evdev); + +void _clutter_device_manager_evdev_release_device_id (ClutterDeviceManagerEvdev *manager_evdev, + ClutterInputDevice *device); + +struct xkb_keymap * _clutter_device_manager_evdev_get_keymap (ClutterDeviceManagerEvdev *manager_evdev); + +ClutterStage * _clutter_device_manager_evdev_get_stage (ClutterDeviceManagerEvdev *manager_evdev); + +void _clutter_device_manager_evdev_constrain_pointer (ClutterDeviceManagerEvdev *manager_evdev, + ClutterInputDevice *core_pointer, + uint64_t time_us, + float x, + float y, + float *new_x, + float *new_y); + +void _clutter_device_manager_evdev_dispatch (ClutterDeviceManagerEvdev *manager_evdev); + +static inline guint64 +us (guint64 us) +{ + return us; +} + +static inline guint64 +ms2us (guint64 ms) +{ + return us (ms * 1000); +} + +static inline guint32 +us2ms (guint64 us) +{ + return (guint32) (us / 1000); +} + +G_END_DECLS + +#endif /* __CLUTTER_DEVICE_MANAGER_EVDEV_H__ */ diff --git a/clutter/clutter/evdev/clutter-evdev.h b/clutter/clutter/evdev/clutter-evdev.h new file mode 100644 index 0000000..1f5485c --- /dev/null +++ b/clutter/clutter/evdev/clutter-evdev.h @@ -0,0 +1,155 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2012 Intel Corp. + * + * 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 . + * + * + */ + +#ifndef __CLUTTER_EVDEV_H__ +#define __CLUTTER_EVDEV_H__ + +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +#if !defined(CLUTTER_ENABLE_COMPOSITOR_API) && !defined(CLUTTER_COMPILATION) +#error "You need to define CLUTTER_ENABLE_COMPOSITOR_API before including clutter-evdev.h" +#endif + +/** + * ClutterOpenDeviceCallback: + * @path: the device path + * @flags: flags to be passed to open + * + * This callback will be called when Clutter needs to access an input + * device. It should return an open file descriptor for the file at @path, + * or -1 if opening failed. + */ +typedef int (*ClutterOpenDeviceCallback) (const char *path, + int flags, + gpointer user_data, + GError **error); +typedef void (*ClutterCloseDeviceCallback) (int fd, + gpointer user_data); + +CLUTTER_AVAILABLE_IN_1_16 +void clutter_evdev_set_device_callbacks (ClutterOpenDeviceCallback open_callback, + ClutterCloseDeviceCallback close_callback, + gpointer user_data); + +CLUTTER_AVAILABLE_IN_1_10 +void clutter_evdev_release_devices (void); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_evdev_reclaim_devices (void); + +/** + * ClutterPointerConstrainCallback: + * @device: the core pointer device + * @time: the event time in milliseconds + * @x: (inout): the new X coordinate + * @y: (inout): the new Y coordinate + * @user_data: user data passed to this function + * + * This callback will be called for all pointer motion events, and should + * update (@x, @y) to constrain the pointer position appropriately. + * The subsequent motion event will use the updated values as the new coordinates. + * Note that the coordinates are not clamped to the stage size, and the callback + * must make sure that this happens before it returns. + * Also note that the event will be emitted even if the pointer is constrained + * to be in the same position. + * + * Since: 1.16 + */ +typedef void (*ClutterPointerConstrainCallback) (ClutterInputDevice *device, + guint32 time, + float prev_x, + float prev_y, + float *x, + float *y, + gpointer user_data); + +CLUTTER_AVAILABLE_IN_1_16 +void clutter_evdev_set_pointer_constrain_callback (ClutterDeviceManager *evdev, + ClutterPointerConstrainCallback callback, + gpointer user_data, + GDestroyNotify user_data_notify); + +CLUTTER_AVAILABLE_IN_1_16 +void clutter_evdev_set_keyboard_map (ClutterDeviceManager *evdev, + struct xkb_keymap *keymap); + +CLUTTER_AVAILABLE_IN_1_18 +struct xkb_keymap * clutter_evdev_get_keyboard_map (ClutterDeviceManager *evdev); + +CLUTTER_AVAILABLE_IN_1_20 +void clutter_evdev_set_keyboard_layout_index (ClutterDeviceManager *evdev, + xkb_layout_index_t idx); + +CLUTTER_AVAILABLE_IN_1_26 +void clutter_evdev_set_keyboard_numlock (ClutterDeviceManager *evdev, + gboolean numlock_state); + +CLUTTER_AVAILABLE_IN_1_18 +void clutter_evdev_set_keyboard_repeat (ClutterDeviceManager *evdev, + gboolean repeat, + guint32 delay, + guint32 interval); + +typedef gboolean (* ClutterEvdevFilterFunc) (struct libinput_event *event, + gpointer data); + +CLUTTER_AVAILABLE_IN_1_20 +void clutter_evdev_add_filter (ClutterEvdevFilterFunc func, + gpointer data, + GDestroyNotify destroy_notify); +CLUTTER_AVAILABLE_IN_1_20 +void clutter_evdev_remove_filter (ClutterEvdevFilterFunc func, + gpointer data); +CLUTTER_AVAILABLE_IN_1_20 +struct libinput_device * clutter_evdev_input_device_get_libinput_device (ClutterInputDevice *device); + +CLUTTER_AVAILABLE_IN_1_20 +gint32 clutter_evdev_event_sequence_get_slot (const ClutterEventSequence *sequence); + +CLUTTER_AVAILABLE_IN_1_20 +void clutter_evdev_warp_pointer (ClutterInputDevice *pointer_device, + guint32 time_, + int x, + int y); + +CLUTTER_AVAILABLE_IN_1_26 +guint32 clutter_evdev_event_get_event_code (const ClutterEvent *event); + +CLUTTER_AVAILABLE_IN_1_26 +guint64 clutter_evdev_event_get_time_usec (const ClutterEvent *event); + +CLUTTER_AVAILABLE_IN_1_26 +gboolean clutter_evdev_event_get_relative_motion (const ClutterEvent *event, + double *dx, + double *dy, + double *dx_unaccel, + double *dy_unaccel); + +G_END_DECLS + +#endif /* __CLUTTER_EVDEV_H__ */ diff --git a/clutter/clutter/evdev/clutter-event-evdev.c b/clutter/clutter/evdev/clutter-event-evdev.c new file mode 100644 index 0000000..737859d --- /dev/null +++ b/clutter/clutter/evdev/clutter-event-evdev.c @@ -0,0 +1,191 @@ +/* Clutter. + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2015 Red Hat + * + * 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 . + * + * Authored by: + * Carlos Garnacho + */ + +#include "clutter-build-config.h" + +#include "clutter/clutter-device-manager-private.h" +#include "clutter/clutter-event-private.h" +#include "clutter-input-device-evdev.h" +#include "clutter-evdev.h" + +typedef struct _ClutterEventEvdev ClutterEventEvdev; + +struct _ClutterEventEvdev +{ + guint32 evcode; + + guint64 time_usec; + + gboolean has_relative_motion; + double dx; + double dy; + double dx_unaccel; + double dy_unaccel; +}; + +static ClutterEventEvdev * +_clutter_event_evdev_new (void) +{ + return g_slice_new0 (ClutterEventEvdev); +} + +ClutterEventEvdev * +_clutter_event_evdev_copy (ClutterEventEvdev *event_evdev) +{ + if (event_evdev != NULL) + return g_slice_dup (ClutterEventEvdev, event_evdev); + + return NULL; +} + +void +_clutter_event_evdev_free (ClutterEventEvdev *event_evdev) +{ + if (event_evdev != NULL) + g_slice_free (ClutterEventEvdev, event_evdev); +} + +static ClutterEventEvdev * +clutter_evdev_event_ensure_platform_data (ClutterEvent *event) +{ + ClutterEventEvdev *event_evdev = _clutter_event_get_platform_data (event); + + if (!event_evdev) + { + event_evdev = _clutter_event_evdev_new (); + _clutter_event_set_platform_data (event, event_evdev); + } + + return event_evdev; +} + +void +_clutter_evdev_event_set_event_code (ClutterEvent *event, + guint32 evcode) +{ + ClutterEventEvdev *event_evdev; + + event_evdev = clutter_evdev_event_ensure_platform_data (event); + event_evdev->evcode = evcode; +} + +void +_clutter_evdev_event_set_time_usec (ClutterEvent *event, + guint64 time_usec) +{ + ClutterEventEvdev *event_evdev; + + event_evdev = clutter_evdev_event_ensure_platform_data (event); + event_evdev->time_usec = time_usec; +} + +void +_clutter_evdev_event_set_relative_motion (ClutterEvent *event, + double dx, + double dy, + double dx_unaccel, + double dy_unaccel) +{ + ClutterEventEvdev *event_evdev; + + event_evdev = clutter_evdev_event_ensure_platform_data (event); + event_evdev->dx = dx; + event_evdev->dy = dy; + event_evdev->dx_unaccel = dx_unaccel; + event_evdev->dy_unaccel = dy_unaccel; + event_evdev->has_relative_motion = TRUE; +} + +/** + * clutter_evdev_event_get_event_code: + * @event: a #ClutterEvent + * + * Returns the event code of the original event. See linux/input.h for more + * information. + * + * Returns: The event code. + **/ +guint32 +clutter_evdev_event_get_event_code (const ClutterEvent *event) +{ + ClutterEventEvdev *event_evdev = _clutter_event_get_platform_data (event); + + if (event_evdev) + return event_evdev->evcode; + + return 0; +} + +/** + * clutter_evdev_event_get_time_usec: + * @event: a #ClutterEvent + * + * Returns the time in microsecond granularity, or 0 if unavailable. + * + * Returns: The time in microsecond granularity, or 0 if unavailable. + */ +guint64 +clutter_evdev_event_get_time_usec (const ClutterEvent *event) +{ + ClutterEventEvdev *event_evdev = _clutter_event_get_platform_data (event); + + if (event_evdev) + return event_evdev->time_usec; + + return 0; +} + +/** + * clutter_evdev_event_get_pointer_motion + * @event: a #ClutterEvent + * + * If available, the normal and unaccelerated motion deltas are written + * to the dx, dy, dx_unaccel and dy_unaccel and TRUE is returned. + * + * If unavailable, FALSE is returned. + * + * Returns: TRUE on success, otherwise FALSE. + **/ +gboolean +clutter_evdev_event_get_relative_motion (const ClutterEvent *event, + double *dx, + double *dy, + double *dx_unaccel, + double *dy_unaccel) +{ + ClutterEventEvdev *event_evdev = _clutter_event_get_platform_data (event); + + if (event_evdev && event_evdev->has_relative_motion) + { + if (dx) + *dx = event_evdev->dx; + if (dy) + *dy = event_evdev->dy; + if (dx_unaccel) + *dx_unaccel = event_evdev->dx_unaccel; + if (dy_unaccel) + *dy_unaccel = event_evdev->dy_unaccel; + return TRUE; + } + else + return FALSE; +} diff --git a/clutter/clutter/evdev/clutter-input-device-evdev.c b/clutter/clutter/evdev/clutter-input-device-evdev.c new file mode 100644 index 0000000..c6f515f --- /dev/null +++ b/clutter/clutter/evdev/clutter-input-device-evdev.c @@ -0,0 +1,315 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corp. + * Copyright (C) 2014 Jonas Ådahl + * + * 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 . + * + * Author: Damien Lespiau + * Author: Jonas Ådahl + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter/clutter-device-manager-private.h" +#include "clutter-private.h" +#include "clutter-evdev.h" +#include "clutter-input-device-tool-evdev.h" + +#include "clutter-input-device-evdev.h" +#include "clutter-device-manager-evdev.h" + +typedef struct _ClutterInputDeviceClass ClutterInputDeviceEvdevClass; + +#define clutter_input_device_evdev_get_type _clutter_input_device_evdev_get_type + +G_DEFINE_TYPE (ClutterInputDeviceEvdev, + clutter_input_device_evdev, + CLUTTER_TYPE_INPUT_DEVICE) + +static void +clutter_input_device_evdev_finalize (GObject *object) +{ + ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (object); + ClutterInputDeviceEvdev *device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (object); + ClutterDeviceManagerEvdev *manager_evdev = + CLUTTER_DEVICE_MANAGER_EVDEV (device->device_manager); + + if (device_evdev->libinput_device) + libinput_device_unref (device_evdev->libinput_device); + + _clutter_device_manager_evdev_release_device_id (manager_evdev, device); + + G_OBJECT_CLASS (clutter_input_device_evdev_parent_class)->finalize (object); +} + +static gboolean +clutter_input_device_evdev_keycode_to_evdev (ClutterInputDevice *device, + guint hardware_keycode, + guint *evdev_keycode) +{ + /* The hardware keycodes from the evdev backend are almost evdev + keycodes: we use the evdev keycode file, but xkb rules have an + offset by 8. See the comment in _clutter_key_event_new_from_evdev() + */ + *evdev_keycode = hardware_keycode - 8; + return TRUE; +} + +static void +clutter_input_device_evdev_update_from_tool (ClutterInputDevice *device, + ClutterInputDeviceTool *tool) +{ + ClutterInputDeviceToolEvdev *evdev_tool; + + evdev_tool = CLUTTER_INPUT_DEVICE_TOOL_EVDEV (tool); + + g_object_freeze_notify (G_OBJECT (device)); + + _clutter_input_device_reset_axes (device); + + _clutter_input_device_add_axis (device, CLUTTER_INPUT_AXIS_X, 0, 0, 0); + _clutter_input_device_add_axis (device, CLUTTER_INPUT_AXIS_Y, 0, 0, 0); + + if (libinput_tablet_tool_has_distance (evdev_tool->tool)) + _clutter_input_device_add_axis (device, CLUTTER_INPUT_AXIS_DISTANCE, 0, 1, 0); + + if (libinput_tablet_tool_has_pressure (evdev_tool->tool)) + _clutter_input_device_add_axis (device, CLUTTER_INPUT_AXIS_PRESSURE, 0, 1, 0); + + if (libinput_tablet_tool_has_tilt (evdev_tool->tool)) + { + _clutter_input_device_add_axis (device, CLUTTER_INPUT_AXIS_XTILT, -90, 90, 0); + _clutter_input_device_add_axis (device, CLUTTER_INPUT_AXIS_YTILT, -90, 90, 0); + } + + if (libinput_tablet_tool_has_rotation (evdev_tool->tool)) + _clutter_input_device_add_axis (device, CLUTTER_INPUT_AXIS_ROTATION, 0, 360, 0); + + if (libinput_tablet_tool_has_slider (evdev_tool->tool)) + _clutter_input_device_add_axis (device, CLUTTER_INPUT_AXIS_SLIDER, -1, 1, 0); + + g_object_thaw_notify (G_OBJECT (device)); +} + +static void +clutter_input_device_evdev_class_init (ClutterInputDeviceEvdevClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = clutter_input_device_evdev_finalize; + klass->keycode_to_evdev = clutter_input_device_evdev_keycode_to_evdev; + klass->update_from_tool = clutter_input_device_evdev_update_from_tool; +} + +static void +clutter_input_device_evdev_init (ClutterInputDeviceEvdev *self) +{ +} + +/* + * _clutter_input_device_evdev_new: + * @manager: the device manager + * @seat: the seat the device will belong to + * @libinput_device: the libinput device + * + * Create a new ClutterInputDevice given a libinput device and associate + * it with the provided seat. + */ +ClutterInputDevice * +_clutter_input_device_evdev_new (ClutterDeviceManager *manager, + ClutterSeatEvdev *seat, + struct libinput_device *libinput_device) +{ + ClutterInputDeviceEvdev *device; + ClutterInputDeviceType type; + ClutterDeviceManagerEvdev *manager_evdev; + gchar *vendor, *product; + gint device_id, n_rings = 0, n_strips = 0, n_groups = 1; + gchar *node_path; + + type = _clutter_input_device_evdev_determine_type (libinput_device); + vendor = g_strdup_printf ("%.4x", libinput_device_get_id_vendor (libinput_device)); + product = g_strdup_printf ("%.4x", libinput_device_get_id_product (libinput_device)); + manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager); + device_id = _clutter_device_manager_evdev_acquire_device_id (manager_evdev); + node_path = g_strdup_printf ("/dev/input/%s", libinput_device_get_sysname (libinput_device)); + + if (libinput_device_has_capability (libinput_device, + LIBINPUT_DEVICE_CAP_TABLET_PAD)) + { + n_rings = libinput_device_tablet_pad_get_num_rings (libinput_device); + n_strips = libinput_device_tablet_pad_get_num_strips (libinput_device); + n_groups = libinput_device_tablet_pad_get_num_mode_groups (libinput_device); + } + + device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_EVDEV, + "id", device_id, + "name", libinput_device_get_name (libinput_device), + "device-manager", manager, + "device-type", type, + "device-mode", CLUTTER_INPUT_MODE_SLAVE, + "enabled", TRUE, + "vendor-id", vendor, + "product-id", product, + "n-rings", n_rings, + "n-strips", n_strips, + "n-mode-groups", n_groups, + "device-node", node_path, + NULL); + + device->seat = seat; + device->libinput_device = libinput_device; + + libinput_device_set_user_data (libinput_device, device); + libinput_device_ref (libinput_device); + g_free (vendor); + g_free (product); + + return CLUTTER_INPUT_DEVICE (device); +} + +/* + * _clutter_input_device_evdev_new_virtual: + * @manager: the device manager + * @seat: the seat the device will belong to + * @type: the input device type + * + * Create a new virtual ClutterInputDevice of the given type. + */ +ClutterInputDevice * +_clutter_input_device_evdev_new_virtual (ClutterDeviceManager *manager, + ClutterSeatEvdev *seat, + ClutterInputDeviceType type, + ClutterInputMode mode) +{ + ClutterInputDeviceEvdev *device; + ClutterDeviceManagerEvdev *manager_evdev; + const char *name; + gint device_id; + + switch (type) + { + case CLUTTER_KEYBOARD_DEVICE: + name = "Virtual keyboard device for seat"; + break; + case CLUTTER_POINTER_DEVICE: + name = "Virtual pointer device for seat"; + break; + default: + name = "Virtual device for seat"; + break; + }; + + manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager); + device_id = _clutter_device_manager_evdev_acquire_device_id (manager_evdev); + device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_EVDEV, + "id", device_id, + "name", name, + "device-manager", manager, + "device-type", type, + "device-mode", mode, + "enabled", TRUE, + NULL); + + device->seat = seat; + + return CLUTTER_INPUT_DEVICE (device); +} + +ClutterSeatEvdev * +_clutter_input_device_evdev_get_seat (ClutterInputDeviceEvdev *device) +{ + return device->seat; +} + +void +_clutter_input_device_evdev_update_leds (ClutterInputDeviceEvdev *device, + enum libinput_led leds) +{ + if (!device->libinput_device) + return; + + libinput_device_led_update (device->libinput_device, leds); +} + +ClutterInputDeviceType +_clutter_input_device_evdev_determine_type (struct libinput_device *ldev) +{ + /* This setting is specific to touchpads and alike, only in these + * devices there is this additional layer of touch event interpretation. + */ + if (libinput_device_config_tap_get_finger_count (ldev) > 0) + return CLUTTER_TOUCHPAD_DEVICE; + else if (libinput_device_has_capability (ldev, LIBINPUT_DEVICE_CAP_TABLET_TOOL)) + return CLUTTER_TABLET_DEVICE; + else if (libinput_device_has_capability (ldev, LIBINPUT_DEVICE_CAP_TABLET_PAD)) + return CLUTTER_PAD_DEVICE; + else if (libinput_device_has_capability (ldev, LIBINPUT_DEVICE_CAP_POINTER)) + return CLUTTER_POINTER_DEVICE; + else if (libinput_device_has_capability (ldev, LIBINPUT_DEVICE_CAP_TOUCH)) + return CLUTTER_TOUCHSCREEN_DEVICE; + else if (libinput_device_has_capability (ldev, LIBINPUT_DEVICE_CAP_KEYBOARD)) + return CLUTTER_KEYBOARD_DEVICE; + else + return CLUTTER_EXTENSION_DEVICE; +} + +/** + * clutter_evdev_input_device_get_libinput_device: + * @device: a #ClutterInputDevice + * + * Retrieves the libinput_device struct held in @device. + * + * Returns: The libinput_device struct + * + * Since: 1.20 + * Stability: unstable + **/ +struct libinput_device * +clutter_evdev_input_device_get_libinput_device (ClutterInputDevice *device) +{ + ClutterInputDeviceEvdev *device_evdev; + + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE_EVDEV (device), NULL); + + device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (device); + + return device_evdev->libinput_device; +} + +/** + * clutter_evdev_event_sequence_get_slot: + * @sequence: a #ClutterEventSequence + * + * Retrieves the touch slot triggered by this @sequence + * + * Returns: the libinput touch slot. + * + * Since: 1.20 + * Stability: unstable + **/ +gint32 +clutter_evdev_event_sequence_get_slot (const ClutterEventSequence *sequence) +{ + if (!sequence) + return -1; + + return GPOINTER_TO_INT (sequence) - 1; +} diff --git a/clutter/clutter/evdev/clutter-input-device-evdev.h b/clutter/clutter/evdev/clutter-input-device-evdev.h new file mode 100644 index 0000000..be2c7ef --- /dev/null +++ b/clutter/clutter/evdev/clutter-input-device-evdev.h @@ -0,0 +1,107 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corp. + * Copyright (C) 2014 Jonas Ådahl + * + * 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 . + * + * Author: Damien Lespiau + * Author: Jonas Ådahl + */ + +#ifndef __CLUTTER_INPUT_DEVICE_EVDEV_H__ +#define __CLUTTER_INPUT_DEVICE_EVDEV_H__ + +#include +#include + +#include "clutter/clutter-device-manager-private.h" +#include "evdev/clutter-seat-evdev.h" + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_INPUT_DEVICE_EVDEV _clutter_input_device_evdev_get_type() + +#define CLUTTER_INPUT_DEVICE_EVDEV(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + CLUTTER_TYPE_INPUT_DEVICE_EVDEV, ClutterInputDeviceEvdev)) + +#define CLUTTER_INPUT_DEVICE_EVDEV_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + CLUTTER_TYPE_INPUT_DEVICE_EVDEV, ClutterInputDeviceEvdevClass)) + +#define CLUTTER_IS_INPUT_DEVICE_EVDEV(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + CLUTTER_TYPE_INPUT_DEVICE_EVDEV)) + +#define CLUTTER_IS_INPUT_DEVICE_EVDEV_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + CLUTTER_TYPE_INPUT_DEVICE_EVDEV)) + +#define CLUTTER_INPUT_DEVICE_EVDEV_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + CLUTTER_TYPE_INPUT_DEVICE_EVDEV, ClutterInputDeviceEvdevClass)) + +typedef struct _ClutterInputDeviceEvdev ClutterInputDeviceEvdev; +typedef struct _ClutterEventEvdev ClutterEventEvdev; + +struct _ClutterInputDeviceEvdev +{ + ClutterInputDevice parent; + + struct libinput_device *libinput_device; + ClutterSeatEvdev *seat; + ClutterInputDeviceTool *last_tool; +}; + +GType _clutter_input_device_evdev_get_type (void) G_GNUC_CONST; + +ClutterInputDevice * _clutter_input_device_evdev_new (ClutterDeviceManager *manager, + ClutterSeatEvdev *seat, + struct libinput_device *libinput_device); + +ClutterInputDevice * _clutter_input_device_evdev_new_virtual (ClutterDeviceManager *manager, + ClutterSeatEvdev *seat, + ClutterInputDeviceType type, + ClutterInputMode mode); + +ClutterSeatEvdev * _clutter_input_device_evdev_get_seat (ClutterInputDeviceEvdev *device); + +void _clutter_input_device_evdev_update_leds (ClutterInputDeviceEvdev *device, + enum libinput_led leds); + +ClutterInputDeviceType _clutter_input_device_evdev_determine_type (struct libinput_device *libinput_device); + + +ClutterEventEvdev * _clutter_event_evdev_copy (ClutterEventEvdev *event_evdev); +void _clutter_event_evdev_free (ClutterEventEvdev *event_evdev); + +void _clutter_evdev_event_set_event_code (ClutterEvent *event, + guint32 evcode); + +void _clutter_evdev_event_set_time_usec (ClutterEvent *event, + guint64 time_usec); + +void _clutter_evdev_event_set_relative_motion (ClutterEvent *event, + double dx, + double dy, + double dx_unaccel, + double dy_unaccel); + +G_END_DECLS + +#endif /* __CLUTTER_INPUT_DEVICE_EVDEV_H__ */ diff --git a/clutter/clutter/evdev/clutter-input-device-tool-evdev.c b/clutter/clutter/evdev/clutter-input-device-tool-evdev.c new file mode 100644 index 0000000..e0cdb31 --- /dev/null +++ b/clutter/clutter/evdev/clutter-input-device-tool-evdev.c @@ -0,0 +1,72 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright © 2009, 2010, 2011 Intel Corp. + * + * 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 . + * + * Author: Carlos Garnacho + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-input-device-tool-evdev.h" + +G_DEFINE_TYPE (ClutterInputDeviceToolEvdev, clutter_input_device_tool_evdev, + CLUTTER_TYPE_INPUT_DEVICE_TOOL) + +static void +clutter_input_device_tool_evdev_finalize (GObject *object) +{ + ClutterInputDeviceToolEvdev *tool = CLUTTER_INPUT_DEVICE_TOOL_EVDEV (object); + + libinput_tablet_tool_unref (tool->tool); + + G_OBJECT_CLASS (clutter_input_device_tool_evdev_parent_class)->finalize (object); +} + +static void +clutter_input_device_tool_evdev_class_init (ClutterInputDeviceToolEvdevClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = clutter_input_device_tool_evdev_finalize; +} + +static void +clutter_input_device_tool_evdev_init (ClutterInputDeviceToolEvdev *tool) +{ +} + +ClutterInputDeviceTool * +clutter_input_device_tool_evdev_new (struct libinput_tablet_tool *tool, + guint64 serial, + ClutterInputDeviceToolType type) +{ + ClutterInputDeviceToolEvdev *evdev_tool; + + evdev_tool = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_TOOL_EVDEV, + "type", type, + "serial", serial, + "id", libinput_tablet_tool_get_tool_id (tool), + NULL); + + evdev_tool->tool = libinput_tablet_tool_ref (tool); + + return CLUTTER_INPUT_DEVICE_TOOL (evdev_tool); +} diff --git a/clutter/clutter/evdev/clutter-input-device-tool-evdev.h b/clutter/clutter/evdev/clutter-input-device-tool-evdev.h new file mode 100644 index 0000000..c92a2ca --- /dev/null +++ b/clutter/clutter/evdev/clutter-input-device-tool-evdev.h @@ -0,0 +1,77 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright © 2009, 2010, 2011 Intel Corp. + * + * 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 . + * + * Author: Carlos Garnacho + */ + +#ifndef __CLUTTER_INPUT_DEVICE_EVDEV_TOOL_H__ +#define __CLUTTER_INPUT_DEVICE_EVDEV_TOOL_H__ + +#include + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_INPUT_DEVICE_TOOL_EVDEV (clutter_input_device_tool_evdev_get_type ()) + +#define CLUTTER_INPUT_DEVICE_TOOL_EVDEV(o) \ + (G_TYPE_CHECK_INSTANCE_CAST ((o), \ + CLUTTER_TYPE_INPUT_DEVICE_TOOL_EVDEV, ClutterInputDeviceToolEvdev)) + +#define CLUTTER_IS_INPUT_DEVICE_TOOL_EVDEV(o) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((o), \ + CLUTTER_TYPE_INPUT_DEVICE_TOOL_EVDEV)) + +#define CLUTTER_INPUT_DEVICE_TOOL_EVDEV_CLASS(c) \ + (G_TYPE_CHECK_CLASS_CAST ((c), \ + CLUTTER_TYPE_INPUT_DEVICE_TOOL_EVDEV, ClutterInputDeviceToolEvdevClass)) + +#define CLUTTER_IS_INPUT_DEVICE_TOOL_EVDEV_CLASS(c) \ + (G_TYPE_CHECK_CLASS_TYPE ((c), \ + CLUTTER_TYPE_INPUT_DEVICE_TOOL_EVDEV)) + +#define CLUTTER_INPUT_DEVICE_TOOL_EVDEV_GET_CLASS(o) \ + (G_TYPE_INSTANCE_GET_CLASS ((o), \ + CLUTTER_TYPE_INPUT_DEVICE_TOOL_EVDEV, ClutterInputDeviceToolEvdevClass)) + +typedef struct _ClutterInputDeviceToolEvdev ClutterInputDeviceToolEvdev; +typedef struct _ClutterInputDeviceToolEvdevClass ClutterInputDeviceToolEvdevClass; + +struct _ClutterInputDeviceToolEvdev +{ + ClutterInputDeviceTool parent_instance; + struct libinput_tablet_tool *tool; +}; + +struct _ClutterInputDeviceToolEvdevClass +{ + ClutterInputDeviceToolClass parent_class; +}; + +GType clutter_input_device_tool_evdev_get_type (void) G_GNUC_CONST; + +ClutterInputDeviceTool * clutter_input_device_tool_evdev_new (struct libinput_tablet_tool *tool, + guint64 serial, + ClutterInputDeviceToolType type); + +G_END_DECLS + +#endif /* __CLUTTER_INPUT_DEVICE_EVDEV_TOOL_H__ */ diff --git a/clutter/clutter/evdev/clutter-seat-evdev.c b/clutter/clutter/evdev/clutter-seat-evdev.c new file mode 100644 index 0000000..17464cf --- /dev/null +++ b/clutter/clutter/evdev/clutter-seat-evdev.c @@ -0,0 +1,594 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corp. + * Copyright (C) 2014 Jonas Ådahl + * Copyright (C) 2016 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: Damien Lespiau + * Author: Jonas Ådahl + */ + +#include "clutter-build-config.h" + +#include "clutter-seat-evdev.h" + +#include + +#include "clutter-event-private.h" +#include "clutter-input-device-evdev.h" +#include "clutter-main.h" + +/* Try to keep the pointer inside the stage. Hopefully no one is using + * this backend with stages smaller than this. */ +#define INITIAL_POINTER_X 16 +#define INITIAL_POINTER_Y 16 + +#define AUTOREPEAT_VALUE 2 + +void +clutter_seat_evdev_set_libinput_seat (ClutterSeatEvdev *seat, + struct libinput_seat *libinput_seat) +{ + g_assert (seat->libinput_seat == NULL); + + libinput_seat_ref (libinput_seat); + libinput_seat_set_user_data (libinput_seat, seat); + seat->libinput_seat = libinput_seat; +} + +void +clutter_seat_evdev_sync_leds (ClutterSeatEvdev *seat) +{ + GSList *iter; + ClutterInputDeviceEvdev *device_evdev; + int caps_lock, num_lock, scroll_lock; + enum libinput_led leds = 0; + + caps_lock = xkb_state_led_index_is_active (seat->xkb, seat->caps_lock_led); + num_lock = xkb_state_led_index_is_active (seat->xkb, seat->num_lock_led); + scroll_lock = xkb_state_led_index_is_active (seat->xkb, seat->scroll_lock_led); + + if (caps_lock) + leds |= LIBINPUT_LED_CAPS_LOCK; + if (num_lock) + leds |= LIBINPUT_LED_NUM_LOCK; + if (scroll_lock) + leds |= LIBINPUT_LED_SCROLL_LOCK; + + for (iter = seat->devices; iter; iter = iter->next) + { + device_evdev = iter->data; + _clutter_input_device_evdev_update_leds (device_evdev, leds); + } +} + +static void +clutter_touch_state_free (ClutterTouchState *touch_state) +{ + g_slice_free (ClutterTouchState, touch_state); +} + +ClutterTouchState * +clutter_seat_evdev_add_touch (ClutterSeatEvdev *seat, + guint32 id) +{ + ClutterTouchState *touch; + + touch = g_slice_new0 (ClutterTouchState); + touch->id = id; + + g_hash_table_insert (seat->touches, GUINT_TO_POINTER (id), touch); + + return touch; +} + +void +clutter_seat_evdev_remove_touch (ClutterSeatEvdev *seat, + guint32 id) +{ + g_hash_table_remove (seat->touches, GUINT_TO_POINTER (id)); +} + +ClutterTouchState * +clutter_seat_evdev_get_touch (ClutterSeatEvdev *seat, + guint32 id) +{ + return g_hash_table_lookup (seat->touches, GUINT_TO_POINTER (id)); +} + +ClutterSeatEvdev * +clutter_seat_evdev_new (ClutterDeviceManagerEvdev *manager_evdev) +{ + ClutterDeviceManager *manager = CLUTTER_DEVICE_MANAGER (manager_evdev); + ClutterSeatEvdev *seat; + ClutterInputDevice *device; + ClutterStage *stage; + struct xkb_keymap *keymap; + + seat = g_new0 (ClutterSeatEvdev, 1); + if (!seat) + return NULL; + + seat->manager_evdev = manager_evdev; + device = _clutter_input_device_evdev_new_virtual ( + manager, seat, CLUTTER_POINTER_DEVICE, + CLUTTER_INPUT_MODE_MASTER); + stage = _clutter_device_manager_evdev_get_stage (manager_evdev); + _clutter_input_device_set_stage (device, stage); + seat->pointer_x = INITIAL_POINTER_X; + seat->pointer_y = INITIAL_POINTER_Y; + _clutter_input_device_set_coords (device, NULL, + seat->pointer_x, seat->pointer_y, + NULL); + _clutter_device_manager_add_device (manager, device); + seat->core_pointer = device; + + device = _clutter_input_device_evdev_new_virtual ( + manager, seat, CLUTTER_KEYBOARD_DEVICE, + CLUTTER_INPUT_MODE_MASTER); + _clutter_input_device_set_stage (device, stage); + _clutter_device_manager_add_device (manager, device); + seat->core_keyboard = device; + + seat->touches = g_hash_table_new_full (NULL, NULL, NULL, + (GDestroyNotify) clutter_touch_state_free); + + seat->repeat = TRUE; + seat->repeat_delay = 250; /* ms */ + seat->repeat_interval = 33; /* ms */ + + keymap = _clutter_device_manager_evdev_get_keymap (manager_evdev); + if (keymap) + { + seat->xkb = xkb_state_new (keymap); + + seat->caps_lock_led = + xkb_keymap_led_get_index (keymap, XKB_LED_NAME_CAPS); + seat->num_lock_led = + xkb_keymap_led_get_index (keymap, XKB_LED_NAME_NUM); + seat->scroll_lock_led = + xkb_keymap_led_get_index (keymap, XKB_LED_NAME_SCROLL); + } + + return seat; +} + +void +clutter_seat_evdev_clear_repeat_timer (ClutterSeatEvdev *seat) +{ + if (seat->repeat_timer) + { + g_source_remove (seat->repeat_timer); + seat->repeat_timer = 0; + g_clear_object (&seat->repeat_device); + } +} + +static gboolean +keyboard_repeat (gpointer data) +{ + ClutterSeatEvdev *seat = data; + GSource *source; + + /* There might be events queued in libinput that could cancel the + repeat timer. */ + _clutter_device_manager_evdev_dispatch (seat->manager_evdev); + if (!seat->repeat_timer) + return G_SOURCE_REMOVE; + + g_return_val_if_fail (seat->repeat_device != NULL, G_SOURCE_REMOVE); + source = g_main_context_find_source_by_id (NULL, seat->repeat_timer); + + clutter_seat_evdev_notify_key (seat, + seat->repeat_device, + g_source_get_time (source), + seat->repeat_key, + AUTOREPEAT_VALUE, + FALSE); + + return G_SOURCE_CONTINUE; +} + +static void +queue_event (ClutterEvent *event) +{ + _clutter_event_push (event, FALSE); +} + +static int +update_button_count (ClutterSeatEvdev *seat, + uint32_t button, + uint32_t state) +{ + if (state) + { + return ++seat->button_count[button]; + } + else + { + /* Handle cases where we newer saw the initial pressed event. */ + if (seat->button_count[button] == 0) + return 0; + + return --seat->button_count[button]; + } +} + +void +clutter_seat_evdev_notify_key (ClutterSeatEvdev *seat, + ClutterInputDevice *device, + uint64_t time_us, + uint32_t key, + uint32_t state, + gboolean update_keys) +{ + ClutterStage *stage; + ClutterEvent *event = NULL; + enum xkb_state_component changed_state; + + if (state != AUTOREPEAT_VALUE) + { + /* Drop any repeated button press (for example from virtual devices. */ + int count = update_button_count (seat, key, state); + if (state && count > 1) + return; + if (!state && count != 0) + return; + } + + /* We can drop the event on the floor if no stage has been + * associated with the device yet. */ + stage = _clutter_input_device_get_stage (device); + if (stage == NULL) + { + clutter_seat_evdev_clear_repeat_timer (seat); + return; + } + + event = _clutter_key_event_new_from_evdev (device, + seat->core_keyboard, + stage, + seat->xkb, + seat->button_state, + us2ms (time_us), key, state); + _clutter_evdev_event_set_event_code (event, key); + + /* We must be careful and not pass multiple releases to xkb, otherwise it gets + confused and locks the modifiers */ + if (state != AUTOREPEAT_VALUE) + { + changed_state = xkb_state_update_key (seat->xkb, + event->key.hardware_keycode, + state ? XKB_KEY_DOWN : XKB_KEY_UP); + } + else + { + changed_state = 0; + clutter_event_set_flags (event, CLUTTER_EVENT_FLAG_SYNTHETIC); + } + + queue_event (event); + + if (update_keys && (changed_state & XKB_STATE_LEDS)) + clutter_seat_evdev_sync_leds (seat); + + if (state == 0 || /* key release */ + !seat->repeat || + !xkb_keymap_key_repeats (xkb_state_get_keymap (seat->xkb), + event->key.hardware_keycode)) + { + clutter_seat_evdev_clear_repeat_timer (seat); + return; + } + + if (state == 1) /* key press */ + seat->repeat_count = 0; + + seat->repeat_count += 1; + seat->repeat_key = key; + + switch (seat->repeat_count) + { + case 1: + case 2: + { + guint32 interval; + + clutter_seat_evdev_clear_repeat_timer (seat); + seat->repeat_device = g_object_ref (device); + + if (seat->repeat_count == 1) + interval = seat->repeat_delay; + else + interval = seat->repeat_interval; + + seat->repeat_timer = + clutter_threads_add_timeout_full (CLUTTER_PRIORITY_EVENTS, + interval, + keyboard_repeat, + seat, + NULL); + return; + } + default: + return; + } +} + +static ClutterEvent * +new_absolute_motion_event (ClutterSeatEvdev *seat, + ClutterInputDevice *input_device, + guint64 time_us, + gfloat x, + gfloat y, + gdouble *axes) +{ + ClutterStage *stage = _clutter_input_device_get_stage (input_device); + ClutterEvent *event; + + event = clutter_event_new (CLUTTER_MOTION); + + if (clutter_input_device_get_device_type (input_device) != CLUTTER_TABLET_DEVICE) + _clutter_device_manager_evdev_constrain_pointer (seat->manager_evdev, + seat->core_pointer, + time_us, + seat->pointer_x, + seat->pointer_y, + &x, &y); + + _clutter_evdev_event_set_time_usec (event, time_us); + event->motion.time = us2ms (time_us); + event->motion.stage = stage; + event->motion.device = seat->core_pointer; + _clutter_xkb_translate_state (event, seat->xkb, seat->button_state); + event->motion.x = x; + event->motion.y = y; + event->motion.axes = axes; + clutter_event_set_device (event, seat->core_pointer); + clutter_event_set_source_device (event, input_device); + + if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE) + { + ClutterInputDeviceEvdev *device_evdev = + CLUTTER_INPUT_DEVICE_EVDEV (input_device); + + clutter_event_set_device_tool (event, device_evdev->last_tool); + clutter_event_set_device (event, input_device); + } + else + { + clutter_event_set_device (event, seat->core_pointer); + } + + _clutter_input_device_set_stage (seat->core_pointer, stage); + + if (clutter_input_device_get_device_type (input_device) != CLUTTER_TABLET_DEVICE) + { + seat->pointer_x = x; + seat->pointer_y = y; + } + + return event; +} + +void +clutter_seat_evdev_notify_relative_motion (ClutterSeatEvdev *seat, + ClutterInputDevice *input_device, + uint64_t time_us, + float dx, + float dy, + float dx_unaccel, + float dy_unaccel) +{ + gfloat new_x, new_y; + ClutterEvent *event; + + /* We can drop the event on the floor if no stage has been + * associated with the device yet. */ + if (!_clutter_input_device_get_stage (input_device)) + return; + + new_x = seat->pointer_x + dx; + new_y = seat->pointer_y + dy; + event = new_absolute_motion_event (seat, input_device, + time_us, new_x, new_y, NULL); + + _clutter_evdev_event_set_relative_motion (event, + dx, dy, + dx_unaccel, dy_unaccel); + + queue_event (event); +} + +void clutter_seat_evdev_notify_absolute_motion (ClutterSeatEvdev *seat, + ClutterInputDevice *input_device, + uint64_t time_us, + float x, + float y, + double *axes) +{ + ClutterEvent *event; + + event = new_absolute_motion_event (seat, input_device, time_us, x, y, axes); + + queue_event (event); +} + +void +clutter_seat_evdev_notify_button (ClutterSeatEvdev *seat, + ClutterInputDevice *input_device, + uint64_t time_us, + uint32_t button, + uint32_t state) +{ + ClutterStage *stage; + ClutterEvent *event = NULL; + gint button_nr; + static gint maskmap[8] = + { + CLUTTER_BUTTON1_MASK, CLUTTER_BUTTON3_MASK, CLUTTER_BUTTON2_MASK, + CLUTTER_BUTTON4_MASK, CLUTTER_BUTTON5_MASK, 0, 0, 0 + }; + int button_count; + + /* Drop any repeated button press (for example from virtual devices. */ + button_count = update_button_count (seat, button, state); + if (state && button_count > 1) + return; + if (!state && button_count != 0) + return; + + /* We can drop the event on the floor if no stage has been + * associated with the device yet. */ + stage = _clutter_input_device_get_stage (input_device); + if (stage == NULL) + return; + + /* The evdev button numbers don't map sequentially to clutter button + * numbers (the right and middle mouse buttons are in the opposite + * order) so we'll map them directly with a switch statement */ + switch (button) + { + case BTN_LEFT: + case BTN_TOUCH: + button_nr = CLUTTER_BUTTON_PRIMARY; + break; + + case BTN_RIGHT: + case BTN_STYLUS: + button_nr = CLUTTER_BUTTON_SECONDARY; + break; + + case BTN_MIDDLE: + case BTN_STYLUS2: + button_nr = CLUTTER_BUTTON_MIDDLE; + break; + + default: + /* For compatibility reasons, all additional buttons go after the old 4-7 scroll ones */ + if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE) + button_nr = button - BTN_TOOL_PEN + 4; + else + button_nr = button - (BTN_LEFT - 1) + 4; + break; + } + + if (button_nr < 1 || button_nr > 12) + { + g_warning ("Unhandled button event 0x%x", button); + return; + } + + if (state) + event = clutter_event_new (CLUTTER_BUTTON_PRESS); + else + event = clutter_event_new (CLUTTER_BUTTON_RELEASE); + + if (button_nr < G_N_ELEMENTS (maskmap)) + { + /* Update the modifiers */ + if (state) + seat->button_state |= maskmap[button_nr - 1]; + else + seat->button_state &= ~maskmap[button_nr - 1]; + } + + _clutter_evdev_event_set_time_usec (event, time_us); + event->button.time = us2ms (time_us); + event->button.stage = CLUTTER_STAGE (stage); + _clutter_xkb_translate_state (event, seat->xkb, seat->button_state); + event->button.button = button_nr; + + if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE) + { + ClutterPoint point; + + clutter_input_device_get_coords (input_device, NULL, &point); + event->button.x = point.x; + event->button.y = point.y; + } + else + { + event->button.x = seat->pointer_x; + event->button.y = seat->pointer_y; + } + + clutter_event_set_device (event, seat->core_pointer); + clutter_event_set_source_device (event, input_device); + + _clutter_evdev_event_set_event_code (event, button); + + if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE) + { + ClutterInputDeviceEvdev *device_evdev = + CLUTTER_INPUT_DEVICE_EVDEV (input_device); + + clutter_event_set_device_tool (event, device_evdev->last_tool); + clutter_event_set_device (event, input_device); + } + else + { + clutter_event_set_device (event, seat->core_pointer); + } + + _clutter_input_device_set_stage (seat->core_pointer, stage); + + queue_event (event); +} + +void +clutter_seat_evdev_free (ClutterSeatEvdev *seat) +{ + GSList *iter; + + for (iter = seat->devices; iter; iter = g_slist_next (iter)) + { + ClutterInputDevice *device = iter->data; + + g_object_unref (device); + } + g_slist_free (seat->devices); + g_hash_table_unref (seat->touches); + + xkb_state_unref (seat->xkb); + + clutter_seat_evdev_clear_repeat_timer (seat); + + if (seat->libinput_seat) + libinput_seat_unref (seat->libinput_seat); + + g_free (seat); +} + +void +clutter_seat_evdev_set_stage (ClutterSeatEvdev *seat, + ClutterStage *stage) +{ + GSList *l; + + _clutter_input_device_set_stage (seat->core_pointer, stage); + _clutter_input_device_set_stage (seat->core_keyboard, stage); + + for (l = seat->devices; l; l = l->next) + { + ClutterInputDevice *device = l->data; + + _clutter_input_device_set_stage (device, stage); + } +} diff --git a/clutter/clutter/evdev/clutter-seat-evdev.h b/clutter/clutter/evdev/clutter-seat-evdev.h new file mode 100644 index 0000000..35f4ea2 --- /dev/null +++ b/clutter/clutter/evdev/clutter-seat-evdev.h @@ -0,0 +1,132 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corp. + * Copyright (C) 2014 Jonas Ådahl + * Copyright (C) 2016 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: Damien Lespiau + * Author: Jonas Ådahl + */ + +#ifndef __CLUTTER_SEAT_EVDEV_H__ +#define __CLUTTER_SEAT_EVDEV_H__ + +#include +#include + +#include "clutter-input-device.h" +#include "clutter-device-manager-evdev.h" +#include "clutter-xkb-utils.h" + +typedef struct _ClutterTouchState ClutterTouchState; + +struct _ClutterTouchState +{ + guint32 id; + ClutterPoint coords; +}; + +struct _ClutterSeatEvdev +{ + struct libinput_seat *libinput_seat; + ClutterDeviceManagerEvdev *manager_evdev; + + GSList *devices; + + ClutterInputDevice *core_pointer; + ClutterInputDevice *core_keyboard; + + GHashTable *touches; + + struct xkb_state *xkb; + xkb_led_index_t caps_lock_led; + xkb_led_index_t num_lock_led; + xkb_led_index_t scroll_lock_led; + uint32_t button_state; + int button_count[KEY_CNT]; + + /* keyboard repeat */ + gboolean repeat; + guint32 repeat_delay; + guint32 repeat_interval; + guint32 repeat_key; + guint32 repeat_count; + guint32 repeat_timer; + ClutterInputDevice *repeat_device; + + gfloat pointer_x; + gfloat pointer_y; + + /* Emulation of discrete scroll events out of smooth ones */ + gfloat accum_scroll_dx; + gfloat accum_scroll_dy; +}; + +void clutter_seat_evdev_notify_key (ClutterSeatEvdev *seat, + ClutterInputDevice *device, + uint64_t time_us, + uint32_t key, + uint32_t state, + gboolean update_keys); + +void clutter_seat_evdev_notify_relative_motion (ClutterSeatEvdev *seat_evdev, + ClutterInputDevice *input_device, + uint64_t time_us, + float dx, + float dy, + float dx_unaccel, + float dy_unaccel); + +void clutter_seat_evdev_notify_absolute_motion (ClutterSeatEvdev *seat_evdev, + ClutterInputDevice *input_device, + uint64_t time_us, + float x, + float y, + double *axes); + +void clutter_seat_evdev_notify_button (ClutterSeatEvdev *seat, + ClutterInputDevice *input_device, + uint64_t time_us, + uint32_t button, + uint32_t state); + +void clutter_seat_evdev_set_libinput_seat (ClutterSeatEvdev *seat, + struct libinput_seat *libinput_seat); + +void clutter_seat_evdev_sync_leds (ClutterSeatEvdev *seat); + +ClutterTouchState * clutter_seat_evdev_add_touch (ClutterSeatEvdev *seat, + guint32 id); + +void clutter_seat_evdev_remove_touch (ClutterSeatEvdev *seat, + guint32 id); + +ClutterTouchState * clutter_seat_evdev_get_touch (ClutterSeatEvdev *seat, + guint32 id); + +void clutter_seat_evdev_set_stage (ClutterSeatEvdev *seat, + ClutterStage *stage); + +void clutter_seat_evdev_clear_repeat_timer (ClutterSeatEvdev *seat); + +ClutterSeatEvdev * clutter_seat_evdev_new (ClutterDeviceManagerEvdev *manager_evdev); + +void clutter_seat_evdev_free (ClutterSeatEvdev *seat); + +#endif /* __CLUTTER_SEAT_EVDEV_H__ */ diff --git a/clutter/clutter/evdev/clutter-virtual-input-device-evdev.c b/clutter/clutter/evdev/clutter-virtual-input-device-evdev.c new file mode 100644 index 0000000..3d8c204 --- /dev/null +++ b/clutter/clutter/evdev/clutter-virtual-input-device-evdev.c @@ -0,0 +1,495 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2016 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: Jonas Ådahl + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include +#include + +#include "clutter-private.h" +#include "clutter-virtual-input-device.h" +#include "evdev/clutter-input-device-evdev.h" +#include "evdev/clutter-seat-evdev.h" +#include "evdev/clutter-virtual-input-device-evdev.h" + +enum +{ + PROP_0, + + PROP_SEAT, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +struct _ClutterVirtualInputDeviceEvdev +{ + ClutterVirtualInputDevice parent; + + ClutterInputDevice *device; + ClutterSeatEvdev *seat; + int button_count[KEY_CNT]; +}; + +G_DEFINE_TYPE (ClutterVirtualInputDeviceEvdev, + clutter_virtual_input_device_evdev, + CLUTTER_TYPE_VIRTUAL_INPUT_DEVICE) + +typedef enum _EvdevButtonType +{ + EVDEV_BUTTON_TYPE_NONE, + EVDEV_BUTTON_TYPE_KEY, + EVDEV_BUTTON_TYPE_BUTTON, +} EvdevButtonType; + +static int +update_button_count (ClutterVirtualInputDeviceEvdev *virtual_evdev, + uint32_t button, + uint32_t state) +{ + if (state) + return ++virtual_evdev->button_count[button]; + else + return --virtual_evdev->button_count[button]; +} + +static EvdevButtonType +get_button_type (uint16_t code) +{ + switch (code) + { + case BTN_TOOL_PEN: + case BTN_TOOL_RUBBER: + case BTN_TOOL_BRUSH: + case BTN_TOOL_PENCIL: + case BTN_TOOL_AIRBRUSH: + case BTN_TOOL_MOUSE: + case BTN_TOOL_LENS: + case BTN_TOOL_QUINTTAP: + case BTN_TOOL_DOUBLETAP: + case BTN_TOOL_TRIPLETAP: + case BTN_TOOL_QUADTAP: + case BTN_TOOL_FINGER: + case BTN_TOUCH: + return EVDEV_BUTTON_TYPE_NONE; + } + + if (code >= KEY_ESC && code <= KEY_MICMUTE) + return EVDEV_BUTTON_TYPE_KEY; + if (code >= BTN_MISC && code <= BTN_GEAR_UP) + return EVDEV_BUTTON_TYPE_BUTTON; + if (code >= KEY_OK && code <= KEY_LIGHTS_TOGGLE) + return EVDEV_BUTTON_TYPE_KEY; + if (code >= BTN_DPAD_UP && code <= BTN_DPAD_RIGHT) + return EVDEV_BUTTON_TYPE_BUTTON; + if (code >= KEY_ALS_TOGGLE && code <= KEY_KBDINPUTASSIST_CANCEL) + return EVDEV_BUTTON_TYPE_KEY; + if (code >= BTN_TRIGGER_HAPPY && code <= BTN_TRIGGER_HAPPY40) + return EVDEV_BUTTON_TYPE_BUTTON; + return EVDEV_BUTTON_TYPE_NONE; +} + +static void +release_pressed_buttons (ClutterVirtualInputDevice *virtual_device) +{ + ClutterVirtualInputDeviceEvdev *virtual_evdev = + CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (virtual_device); + int code; + uint64_t time_us; + + time_us = g_get_monotonic_time (); + + for (code = 0; code < G_N_ELEMENTS (virtual_evdev->button_count); code++) + { + if (virtual_evdev->button_count[code] == 0) + continue; + + switch (get_button_type (code)) + { + case EVDEV_BUTTON_TYPE_KEY: + clutter_virtual_input_device_notify_key (virtual_device, + time_us, + code, + CLUTTER_KEY_STATE_RELEASED); + break; + case EVDEV_BUTTON_TYPE_BUTTON: + clutter_virtual_input_device_notify_button (virtual_device, + time_us, + code, + CLUTTER_BUTTON_STATE_RELEASED); + break; + case EVDEV_BUTTON_TYPE_NONE: + g_assert_not_reached (); + } + } +} + +static void +clutter_virtual_input_device_evdev_notify_relative_motion (ClutterVirtualInputDevice *virtual_device, + uint64_t time_us, + double dx, + double dy) +{ + ClutterVirtualInputDeviceEvdev *virtual_evdev = + CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (virtual_device); + + clutter_seat_evdev_notify_relative_motion (virtual_evdev->seat, + virtual_evdev->device, + time_us, + dx, dy, + dx, dy); +} + +static void +clutter_virtual_input_device_evdev_notify_absolute_motion (ClutterVirtualInputDevice *virtual_device, + uint64_t time_us, + double x, + double y) +{ + ClutterVirtualInputDeviceEvdev *virtual_evdev = + CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (virtual_device); + + clutter_seat_evdev_notify_absolute_motion (virtual_evdev->seat, + virtual_evdev->device, + time_us, + x, y, + NULL); +} + +static void +clutter_virtual_input_device_evdev_notify_button (ClutterVirtualInputDevice *virtual_device, + uint64_t time_us, + uint32_t button, + ClutterButtonState button_state) +{ + ClutterVirtualInputDeviceEvdev *virtual_evdev = + CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (virtual_device); + int button_count; + + if (get_button_type (button) != EVDEV_BUTTON_TYPE_BUTTON) + { + g_warning ("Unknown/invalid virtual device button 0x%x pressed", + button); + return; + } + + button_count = update_button_count (virtual_evdev, button, button_state); + if (button_count < 0 || button_count > 1) + { + g_warning ("Received multiple virtual 0x%x button %s (ignoring)", button, + button_state == CLUTTER_BUTTON_STATE_PRESSED ? "presses" : "releases"); + update_button_count (virtual_evdev, button, 1 - button_state); + return; + } + + clutter_seat_evdev_notify_button (virtual_evdev->seat, + virtual_evdev->device, + time_us, + button, + button_state); +} + +static void +clutter_virtual_input_device_evdev_notify_key (ClutterVirtualInputDevice *virtual_device, + uint64_t time_us, + uint32_t key, + ClutterKeyState key_state) +{ + ClutterVirtualInputDeviceEvdev *virtual_evdev = + CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (virtual_device); + int key_count; + + if (get_button_type (key) != EVDEV_BUTTON_TYPE_KEY) + { + g_warning ("Unknown/invalid virtual device key 0x%x pressed\n", key); + return; + } + + key_count = update_button_count (virtual_evdev, key, key_state); + if (key_count < 0 || key_count > 1) + { + g_warning ("Received multiple virtual 0x%x key %s (ignoring)", key, + key_state == CLUTTER_KEY_STATE_PRESSED ? "presses" : "releases"); + update_button_count (virtual_evdev, key, 1 - key_state); + return; + } + + clutter_seat_evdev_notify_key (virtual_evdev->seat, + virtual_evdev->device, + time_us, + key, + key_state, + TRUE); +} + +static gboolean +pick_keycode_for_keyval_in_current_group (ClutterVirtualInputDevice *virtual_device, + guint keyval, + guint *keycode_out, + guint *level_out) +{ + ClutterVirtualInputDeviceEvdev *virtual_evdev = + CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (virtual_device); + ClutterDeviceManager *manager; + struct xkb_keymap *xkb_keymap; + struct xkb_state *state; + guint keycode, layout; + xkb_keycode_t min_keycode, max_keycode; + + manager = clutter_virtual_input_device_get_manager (virtual_device); + xkb_keymap = _clutter_device_manager_evdev_get_keymap (CLUTTER_DEVICE_MANAGER_EVDEV (manager)); + state = virtual_evdev->seat->xkb; + + layout = xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE); + min_keycode = xkb_keymap_min_keycode (xkb_keymap); + max_keycode = xkb_keymap_max_keycode (xkb_keymap); + for (keycode = min_keycode; keycode < max_keycode; keycode++) + { + gint num_levels, level; + num_levels = xkb_keymap_num_levels_for_key (xkb_keymap, keycode, layout); + for (level = 0; level < num_levels; level++) + { + const xkb_keysym_t *syms; + gint num_syms, sym; + num_syms = xkb_keymap_key_get_syms_by_level (xkb_keymap, keycode, layout, level, &syms); + for (sym = 0; sym < num_syms; sym++) + { + if (syms[sym] == keyval) + { + *keycode_out = keycode; + if (level_out) + *level_out = level; + return TRUE; + } + } + } + } + + return FALSE; +} + +static void +apply_level_modifiers (ClutterVirtualInputDevice *virtual_device, + uint64_t time_us, + uint32_t level, + uint32_t key_state) +{ + ClutterVirtualInputDeviceEvdev *virtual_evdev = + CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (virtual_device); + guint keysym, keycode, evcode; + + if (level == 0) + return; + + if (level == 1) + { + keysym = XKB_KEY_Shift_L; + } + else if (level == 2) + { + keysym = XKB_KEY_ISO_Level3_Shift; + } + else + { + g_warning ("Unhandled level: %d\n", level); + return; + } + + if (!pick_keycode_for_keyval_in_current_group (virtual_device, keysym, + &keycode, NULL)) + return; + + clutter_input_device_keycode_to_evdev (virtual_evdev->device, + keycode, &evcode); + clutter_seat_evdev_notify_key (virtual_evdev->seat, + virtual_evdev->device, + time_us, + evcode, + key_state, + TRUE); +} + +static void +clutter_virtual_input_device_evdev_notify_keyval (ClutterVirtualInputDevice *virtual_device, + uint64_t time_us, + uint32_t keyval, + ClutterKeyState key_state) +{ + ClutterVirtualInputDeviceEvdev *virtual_evdev = + CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (virtual_device); + int key_count; + guint keycode = 0, level = 0, evcode = 0; + + if (!pick_keycode_for_keyval_in_current_group (virtual_device, + keyval, &keycode, &level)) + { + g_warning ("No keycode found for keyval %x in current group", keyval); + return; + } + + clutter_input_device_keycode_to_evdev (virtual_evdev->device, + keycode, &evcode); + + if (get_button_type (evcode) != EVDEV_BUTTON_TYPE_KEY) + { + g_warning ("Unknown/invalid virtual device key 0x%x pressed\n", evcode); + return; + } + + key_count = update_button_count (virtual_evdev, evcode, key_state); + if (key_count < 0 || key_count > 1) + { + g_warning ("Received multiple virtual 0x%x key %s (ignoring)", keycode, + key_state == CLUTTER_KEY_STATE_PRESSED ? "presses" : "releases"); + update_button_count (virtual_evdev, evcode, 1 - key_state); + return; + } + + if (key_state) + apply_level_modifiers (virtual_device, time_us, level, key_state); + + clutter_seat_evdev_notify_key (virtual_evdev->seat, + virtual_evdev->device, + time_us, + evcode, + key_state, + TRUE); + + if (!key_state) + apply_level_modifiers (virtual_device, time_us, level, key_state); +} + +static void +clutter_virtual_input_device_evdev_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterVirtualInputDeviceEvdev *virtual_evdev = + CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (object); + + switch (prop_id) + { + case PROP_SEAT: + g_value_set_pointer (value, virtual_evdev->seat); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_virtual_input_device_evdev_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterVirtualInputDeviceEvdev *virtual_evdev = + CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (object); + + switch (prop_id) + { + case PROP_SEAT: + virtual_evdev->seat = g_value_get_pointer (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_virtual_input_device_evdev_constructed (GObject *object) +{ + ClutterVirtualInputDevice *virtual_device = + CLUTTER_VIRTUAL_INPUT_DEVICE (object); + ClutterVirtualInputDeviceEvdev *virtual_evdev = + CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (object); + ClutterDeviceManager *manager; + ClutterInputDeviceType device_type; + ClutterStage *stage; + + manager = clutter_virtual_input_device_get_manager (virtual_device); + device_type = clutter_virtual_input_device_get_device_type (virtual_device); + + virtual_evdev->device = + _clutter_input_device_evdev_new_virtual (manager, + virtual_evdev->seat, + device_type, + CLUTTER_INPUT_MODE_SLAVE); + + stage = _clutter_device_manager_evdev_get_stage (CLUTTER_DEVICE_MANAGER_EVDEV (manager)); + _clutter_input_device_set_stage (virtual_evdev->device, stage); +} + +static void +clutter_virtual_input_device_evdev_finalize (GObject *object) +{ + ClutterVirtualInputDevice *virtual_device = + CLUTTER_VIRTUAL_INPUT_DEVICE (object); + ClutterVirtualInputDeviceEvdev *virtual_evdev = + CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (object); + GObjectClass *object_class; + + release_pressed_buttons (virtual_device); + g_clear_object (&virtual_evdev->device); + + object_class = + G_OBJECT_CLASS (clutter_virtual_input_device_evdev_parent_class); + object_class->finalize (object); +} + +static void +clutter_virtual_input_device_evdev_init (ClutterVirtualInputDeviceEvdev *virtual_device_evdev) +{ +} + +static void +clutter_virtual_input_device_evdev_class_init (ClutterVirtualInputDeviceEvdevClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + ClutterVirtualInputDeviceClass *virtual_input_device_class = + CLUTTER_VIRTUAL_INPUT_DEVICE_CLASS (klass); + + object_class->get_property = clutter_virtual_input_device_evdev_get_property; + object_class->set_property = clutter_virtual_input_device_evdev_set_property; + object_class->constructed = clutter_virtual_input_device_evdev_constructed; + object_class->finalize = clutter_virtual_input_device_evdev_finalize; + + virtual_input_device_class->notify_relative_motion = clutter_virtual_input_device_evdev_notify_relative_motion; + virtual_input_device_class->notify_absolute_motion = clutter_virtual_input_device_evdev_notify_absolute_motion; + virtual_input_device_class->notify_button = clutter_virtual_input_device_evdev_notify_button; + virtual_input_device_class->notify_key = clutter_virtual_input_device_evdev_notify_key; + virtual_input_device_class->notify_keyval = clutter_virtual_input_device_evdev_notify_keyval; + + obj_props[PROP_SEAT] = g_param_spec_pointer ("seat", + P_("ClutterSeatEvdev"), + P_("ClutterSeatEvdev"), + CLUTTER_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_properties (object_class, PROP_LAST, obj_props); +} diff --git a/clutter/clutter/evdev/clutter-virtual-input-device-evdev.h b/clutter/clutter/evdev/clutter-virtual-input-device-evdev.h new file mode 100644 index 0000000..9bb8db0 --- /dev/null +++ b/clutter/clutter/evdev/clutter-virtual-input-device-evdev.h @@ -0,0 +1,35 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2016 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: Jonas Ådahl + */ + +#ifndef __CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV_H__ +#define __CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV_H__ + +#include "clutter-virtual-input-device.h" + +#define CLUTTER_TYPE_VIRTUAL_INPUT_DEVICE_EVDEV (clutter_virtual_input_device_evdev_get_type ()) +G_DECLARE_FINAL_TYPE (ClutterVirtualInputDeviceEvdev, + clutter_virtual_input_device_evdev, + CLUTTER, VIRTUAL_INPUT_DEVICE_EVDEV, + ClutterVirtualInputDevice) + +#endif /* __CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV_H__ */ diff --git a/clutter/clutter/evdev/clutter-xkb-utils.c b/clutter/clutter/evdev/clutter-xkb-utils.c new file mode 100644 index 0000000..7f47682 --- /dev/null +++ b/clutter/clutter/evdev/clutter-xkb-utils.c @@ -0,0 +1,115 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + + * Authors: + * Kristian Høgsberg + * Damien Lespiau + */ + +#include "clutter-build-config.h" + +#include "clutter-keysyms.h" +#include "clutter-event-private.h" +#include "clutter-xkb-utils.h" + +/* + * _clutter_event_new_from_evdev: Create a new Clutter ClutterKeyEvent + * @device: a ClutterInputDevice + * @stage: the stage the event should be delivered to + * @xkb: XKB rules to translate the event + * @_time: timestamp of the event + * @key: a key code coming from a Linux input device + * @state: TRUE if a press event, FALSE if a release event + * @modifer_state: in/out + * + * Translate @key to a #ClutterKeyEvent using rules from xbbcommon. + * + * Return value: the new #ClutterEvent + */ +ClutterEvent * +_clutter_key_event_new_from_evdev (ClutterInputDevice *device, + ClutterInputDevice *core_device, + ClutterStage *stage, + struct xkb_state *xkb_state, + uint32_t button_state, + uint32_t _time, + xkb_keycode_t key, + uint32_t state) +{ + ClutterEvent *event; + xkb_keysym_t sym; + const xkb_keysym_t *syms; + char buffer[8]; + int n; + + if (state) + event = clutter_event_new (CLUTTER_KEY_PRESS); + else + event = clutter_event_new (CLUTTER_KEY_RELEASE); + + /* We use a fixed offset of 8 because evdev starts KEY_* numbering from + * 0, whereas X11's minimum keycode, for really stupid reasons, is 8. + * So the evdev XKB rules are based on the keycodes all being shifted + * upwards by 8. */ + key += 8; + + n = xkb_key_get_syms (xkb_state, key, &syms); + if (n == 1) + sym = syms[0]; + else + sym = XKB_KEY_NoSymbol; + + event->key.device = core_device; + event->key.stage = stage; + event->key.time = _time; + _clutter_xkb_translate_state (event, xkb_state, button_state); + event->key.hardware_keycode = key; + event->key.keyval = sym; + clutter_event_set_source_device (event, device); + + n = xkb_keysym_to_utf8 (sym, buffer, sizeof (buffer)); + + if (n == 0) + { + /* not printable */ + event->key.unicode_value = (gunichar) '\0'; + } + else + { + event->key.unicode_value = g_utf8_get_char_validated (buffer, n); + if (event->key.unicode_value == -1 || event->key.unicode_value == -2) + event->key.unicode_value = (gunichar) '\0'; + } + + return event; +} + +void +_clutter_xkb_translate_state (ClutterEvent *event, + struct xkb_state *state, + uint32_t button_state) +{ + _clutter_event_set_state_full (event, + button_state, + xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED), + xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED), + xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED), + xkb_state_serialize_mods (state, XKB_STATE_MODS_EFFECTIVE) | button_state); +} diff --git a/clutter/clutter/evdev/clutter-xkb-utils.h b/clutter/clutter/evdev/clutter-xkb-utils.h new file mode 100644 index 0000000..ae057dd --- /dev/null +++ b/clutter/clutter/evdev/clutter-xkb-utils.h @@ -0,0 +1,46 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + + * Authors: + * Damien Lespiau + */ + +#ifndef __CLUTTER_XKB_UTILS_H__ +#define __CLUTTER_XKB_UTILS_H__ + +#include + +#include "clutter-stage.h" +#include "clutter-event.h" +#include "clutter-input-device.h" + +ClutterEvent * _clutter_key_event_new_from_evdev (ClutterInputDevice *device, + ClutterInputDevice *core_keyboard, + ClutterStage *stage, + struct xkb_state *xkb_state, + uint32_t button_state, + uint32_t _time, + uint32_t key, + uint32_t state); +void _clutter_xkb_translate_state (ClutterEvent *event, + struct xkb_state *xkb_state, + uint32_t button_state); + +#endif /* __CLUTTER_XKB_UTILS_H__ */ diff --git a/clutter/clutter/mutter-clutter.pc.in b/clutter/clutter/mutter-clutter.pc.in new file mode 100644 index 0000000..c3e31a5 --- /dev/null +++ b/clutter/clutter/mutter-clutter.pc.in @@ -0,0 +1,24 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@/mutter +includedir=@includedir@/mutter + +apiversion=@CLUTTER_API_VERSION@ +requires=@CLUTTER_REQUIRES@ mutter-cogl-1.0 +requires_private=@CLUTTER_REQUIRES_PRIVATE@ +backends=@CLUTTER_BACKENDS@ + +# only kept for backward compatibility +soname_infix=@CLUTTER_SONAME_INFIX@ +winsys=@CLUTTER_WINSYS@ +backend=@CLUTTER_WINSYS@ +cogl=deprecated +cogl_driver=deprecated + +Name: Mutter Clutter +Description: Mutter's Clutter Private Library +Version: @VERSION@ +Libs: -L${libdir} -lmutter-clutter-${apiversion} +Cflags: -I${includedir}/clutter-${apiversion} +Requires: ${requires} +Requires.private: ${requires_private} diff --git a/clutter/clutter/wayland/clutter-wayland-compositor.h b/clutter/clutter/wayland/clutter-wayland-compositor.h new file mode 100644 index 0000000..703a7e2 --- /dev/null +++ b/clutter/clutter/wayland/clutter-wayland-compositor.h @@ -0,0 +1,45 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2011 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: + * Robert Bragg + */ + +/** + * SECTION:clutter-wayland-compositor + * @short_description: Wayland compositor specific APIs + * + * Clutter provides some Wayland specific APIs to aid in writing + * Clutter based compositors. + * + * The Clutter Wayland compositor API is available since Clutter 1.8 + */ + +#ifndef __CLUTTER_WAYLAND_COMPOSITOR_H__ +#define __CLUTTER_WAYLAND_COMPOSITOR_H__ + +G_BEGIN_DECLS + +CLUTTER_AVAILABLE_IN_1_10 +void clutter_wayland_set_compositor_display (void *display); + +G_END_DECLS + +#endif /* __CLUTTER_WAYLAND_COMPOSITOR_H__ */ diff --git a/clutter/clutter/wayland/clutter-wayland-surface.c b/clutter/clutter/wayland/clutter-wayland-surface.c new file mode 100644 index 0000000..2465a18 --- /dev/null +++ b/clutter/clutter/wayland/clutter-wayland-surface.c @@ -0,0 +1,652 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2011 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + * Authors: + * Robert Bragg + */ + +/** + * SECTION:clutter-wayland-surface + * @Title: ClutterWaylandSurface + * @short_description: An actor which displays the content of a client surface + * + * #ClutterWaylandSurface is an actor for displaying the contents of a client + * surface. It is intended to support developers implementing Clutter based + * wayland compositors. + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#define CLUTTER_ENABLE_EXPERIMENTAL_API + +#include "clutter-wayland-surface.h" + +#include "clutter-actor-private.h" +#include "clutter-marshal.h" +#include "clutter-paint-volume-private.h" +#include "clutter-private.h" +#include "clutter-backend.h" + +#include +#include + +enum +{ + PROP_SURFACE = 1, + PROP_SURFACE_WIDTH, + PROP_SURFACE_HEIGHT, + PROP_COGL_TEXTURE, + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +enum +{ + QUEUE_DAMAGE_REDRAW, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0, }; + +struct _ClutterWaylandSurfacePrivate +{ + struct wl_surface *surface; + CoglTexture2D *buffer; + int width, height; + CoglPipeline *pipeline; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterWaylandSurface, + clutter_wayland_surface, + CLUTTER_TYPE_ACTOR) + +static gboolean +clutter_wayland_surface_get_paint_volume (ClutterActor *self, + ClutterPaintVolume *volume) +{ + return clutter_paint_volume_set_from_allocation (volume, self); +} + +static void +clutter_wayland_surface_queue_damage_redraw (ClutterWaylandSurface *texture, + gint x, + gint y, + gint width, + gint height) +{ + ClutterWaylandSurfacePrivate *priv = texture->priv; + ClutterActor *self = CLUTTER_ACTOR (texture); + ClutterActorBox allocation; + float scale_x; + float scale_y; + cairo_rectangle_int_t clip; + + /* NB: clutter_actor_queue_redraw_with_clip expects a box in the actor's + * coordinate space so we need to convert from surface coordinates to + * actor coordinates... + */ + + /* Calling clutter_actor_get_allocation_box() is enormously expensive + * if the actor has an out-of-date allocation, since it triggers + * a full redraw. clutter_actor_queue_redraw_with_clip() would redraw + * the whole stage anyways in that case, so just go ahead and do + * it here. + */ + if (!clutter_actor_has_allocation (self)) + { + clutter_actor_queue_redraw (self); + return; + } + + if (priv->width == 0 || priv->height == 0) + return; + + clutter_actor_get_allocation_box (self, &allocation); + + scale_x = (allocation.x2 - allocation.x1) / priv->width; + scale_y = (allocation.y2 - allocation.y1) / priv->height; + + clip.x = x * scale_x; + clip.y = y * scale_y; + clip.width = width * scale_x; + clip.height = height * scale_y; + clutter_actor_queue_redraw_with_clip (self, &clip); +} + +static void +free_pipeline (ClutterWaylandSurface *self) +{ + ClutterWaylandSurfacePrivate *priv = self->priv; + + if (priv->pipeline) + { + cogl_object_unref (priv->pipeline); + priv->pipeline = NULL; + } +} + +static void +opacity_change_cb (ClutterWaylandSurface *self) +{ + free_pipeline (self); +} + +static void +clutter_wayland_surface_init (ClutterWaylandSurface *self) +{ + ClutterWaylandSurfacePrivate *priv; + + priv = clutter_wayland_surface_get_instance_private (self); + priv->surface = NULL; + priv->width = 0; + priv->height = 0; + + self->priv = priv; + + g_signal_connect (self, "notify::opacity", G_CALLBACK (opacity_change_cb), NULL); +} + +static void +free_surface_buffers (ClutterWaylandSurface *self) +{ + ClutterWaylandSurfacePrivate *priv = self->priv; + + if (priv->buffer) + { + cogl_object_unref (priv->buffer); + priv->buffer = NULL; + free_pipeline (self); + } +} + +static void +clutter_wayland_surface_dispose (GObject *object) +{ + ClutterWaylandSurface *self = CLUTTER_WAYLAND_SURFACE (object); + ClutterWaylandSurfacePrivate *priv = self->priv; + + free_pipeline (self); + free_surface_buffers (self); + priv->surface = NULL; + + G_OBJECT_CLASS (clutter_wayland_surface_parent_class)->dispose (object); +} + +static void +set_size (ClutterWaylandSurface *self, + int width, + int height) +{ + ClutterWaylandSurfacePrivate *priv = self->priv; + + if (priv->width != width) + { + priv->width = width; + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SURFACE_WIDTH]); + } + if (priv->height != height) + { + priv->height = height; + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SURFACE_HEIGHT]); + } + + clutter_actor_set_size (CLUTTER_ACTOR (self), priv->width, priv->height); +} + +/** + * clutter_wayland_surface_get_surface: + * @self: a #ClutterWaylandSurface + * + * Retrieves a point to the Wayland surface used by the actor. + * + * Return value: (transfer none): a wl_surface pointer, or %NULL + * + * Since: 1.10 + */ +struct wl_surface * +clutter_wayland_surface_get_surface (ClutterWaylandSurface *self) +{ + ClutterWaylandSurfacePrivate *priv = self->priv; + return priv->surface; +} + +/** + * clutter_wayland_surface_set_surface: + * @self: a #ClutterWaylandSurface + * @surface: a Wayland wl_surface pointer + * + * Sets the Wayland surface to be used by the actor. + * + * Since: 1.10 + */ +void +clutter_wayland_surface_set_surface (ClutterWaylandSurface *self, + struct wl_surface *surface) +{ + ClutterWaylandSurfacePrivate *priv; + + g_return_if_fail (CLUTTER_WAYLAND_IS_SURFACE (self)); + + priv = self->priv; + + if (priv->surface == surface) + return; + + if (priv->surface) + { + free_pipeline (self); + free_surface_buffers (self); + g_signal_emit (self, signals[QUEUE_DAMAGE_REDRAW], + 0, + 0, 0, priv->width, priv->height); + } + + priv->surface = surface; + + /* XXX: should we freeze/thaw notifications? */ + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SURFACE]); + + /* We have to wait until the next attach event to find out the surface + * geometry... */ + set_size (self, 0, 0); +} + +static void +clutter_wayland_surface_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterWaylandSurface *self = CLUTTER_WAYLAND_SURFACE (object); + + switch (prop_id) + { + case PROP_SURFACE: + clutter_wayland_surface_set_surface (self, g_value_get_pointer (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_wayland_surface_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterWaylandSurface *self = CLUTTER_WAYLAND_SURFACE (object); + ClutterWaylandSurfacePrivate *priv = self->priv; + + switch (prop_id) + { + case PROP_SURFACE: + g_value_set_pointer (value, priv->surface); + break; + case PROP_SURFACE_WIDTH: + g_value_set_uint (value, priv->width); + break; + case PROP_SURFACE_HEIGHT: + g_value_set_uint (value, priv->height); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_wayland_surface_paint (ClutterActor *self) +{ + ClutterWaylandSurfacePrivate *priv; + ClutterActorBox box; + + g_return_if_fail (CLUTTER_WAYLAND_IS_SURFACE (self)); + + priv = CLUTTER_WAYLAND_SURFACE (self)->priv; + + if (G_UNLIKELY (priv->pipeline == NULL)) + { + CoglContext *ctx = + clutter_backend_get_cogl_context (clutter_get_default_backend ()); + guint8 paint_opacity = clutter_actor_get_paint_opacity (self); + + priv->pipeline = cogl_pipeline_new (ctx); + cogl_pipeline_set_color4ub (priv->pipeline, + paint_opacity, + paint_opacity, + paint_opacity, + paint_opacity); + cogl_pipeline_set_layer_texture (priv->pipeline, 0, + COGL_TEXTURE (priv->buffer)); + } + + cogl_set_source (priv->pipeline); + clutter_actor_get_allocation_box (self, &box); + cogl_rectangle (0, 0, box.x2 - box.x1, box.y2 - box.y1); +} + +static void +clutter_wayland_surface_get_preferred_width (ClutterActor *self, + gfloat for_height, + gfloat *min_width_p, + gfloat *natural_width_p) +{ + ClutterWaylandSurfacePrivate *priv; + + g_return_if_fail (CLUTTER_WAYLAND_IS_SURFACE (self)); + + priv = CLUTTER_WAYLAND_SURFACE (self)->priv; + + if (min_width_p) + *min_width_p = 0; + + if (natural_width_p) + *natural_width_p = priv->width; +} + +static void +clutter_wayland_surface_get_preferred_height (ClutterActor *self, + gfloat for_width, + gfloat *min_height_p, + gfloat *natural_height_p) +{ + ClutterWaylandSurfacePrivate *priv; + + g_return_if_fail (CLUTTER_WAYLAND_IS_SURFACE (self)); + + priv = CLUTTER_WAYLAND_SURFACE (self)->priv; + + if (min_height_p) + *min_height_p = 0; + + if (natural_height_p) + *natural_height_p = priv->height; +} + +static gboolean +clutter_wayland_surface_has_overlaps (ClutterActor *self) +{ + /* Rectangles never need an offscreen redirect because there are + never any overlapping primitives */ + return FALSE; +} + +static void +clutter_wayland_surface_class_init (ClutterWaylandSurfaceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + GParamSpec *pspec; + + actor_class->get_paint_volume = clutter_wayland_surface_get_paint_volume; + actor_class->paint = clutter_wayland_surface_paint; + actor_class->get_preferred_width = + clutter_wayland_surface_get_preferred_width; + actor_class->get_preferred_height = + clutter_wayland_surface_get_preferred_height; + actor_class->has_overlaps = clutter_wayland_surface_has_overlaps; + + object_class->dispose = clutter_wayland_surface_dispose; + object_class->set_property = clutter_wayland_surface_set_property; + object_class->get_property = clutter_wayland_surface_get_property; + + pspec = g_param_spec_pointer ("surface", + P_("Surface"), + P_("The underlying wayland surface"), + CLUTTER_PARAM_READWRITE| + G_PARAM_CONSTRUCT_ONLY); + obj_props[PROP_SURFACE] = pspec; + g_object_class_install_property (object_class, PROP_SURFACE, pspec); + + pspec = g_param_spec_uint ("surface-width", + P_("Surface width"), + P_("The width of the underlying wayland surface"), + 0, G_MAXUINT, + 0, + G_PARAM_READABLE); + obj_props[PROP_SURFACE_WIDTH] = pspec; + g_object_class_install_property (object_class, PROP_SURFACE_WIDTH, pspec); + + pspec = g_param_spec_uint ("surface-height", + P_("Surface height"), + P_("The height of the underlying wayland surface"), + 0, G_MAXUINT, + 0, + G_PARAM_READABLE); + obj_props[PROP_SURFACE_HEIGHT] = pspec; + g_object_class_install_property (object_class, PROP_SURFACE_HEIGHT, pspec); + + pspec = g_param_spec_boxed ("cogl-texture", + P_("Cogl Texture"), + P_("The underlying Cogl texture handle used to draw this actor"), + COGL_TYPE_HANDLE, + CLUTTER_PARAM_READWRITE); + obj_props[PROP_COGL_TEXTURE] = pspec; + g_object_class_install_property (object_class, PROP_COGL_TEXTURE, pspec); + + /** + * ClutterWaylandSurface::queue-damage-redraw: + * @texture: the object which received the signal + * @x: The top left x position of the damage region + * @y: The top left y position of the damage region + * @width: The width of the damage region + * @height: The height of the damage region + * + * ::queue-damage-redraw is emitted to notify that some sub-region + * of the texture has been changed. This usually means a redraw + * needs to be queued for the actor. + * + * The default handler will queue a clipped redraw in response to + * the damage, using the assumption that the pixmap is being painted + * to a rectangle covering the transformed allocation of the actor. + * If you sub-class and change the paint method so this isn't true + * then you must also provide your own damage signal handler to + * queue a redraw that blocks this default behaviour. + * + * Since: 1.10 + */ + signals[QUEUE_DAMAGE_REDRAW] = + g_signal_new (g_intern_static_string ("queue-damage-redraw"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ClutterWaylandSurfaceClass, queue_damage_redraw), + NULL, NULL, + _clutter_marshal_VOID__INT_INT_INT_INT, + G_TYPE_NONE, 4, + G_TYPE_INT, + G_TYPE_INT, + G_TYPE_INT, + G_TYPE_INT); + klass->queue_damage_redraw = clutter_wayland_surface_queue_damage_redraw; +} + +/** + * clutter_wayland_surface_new: + * @surface: the Wayland surface this actor should represent + * + * Creates a new #ClutterWaylandSurface for @surface + * + * Return value: A new #ClutterWaylandSurface representing @surface + * + * Since: 1.8 + * Stability: unstable + */ +ClutterActor * +clutter_wayland_surface_new (struct wl_surface *surface) +{ + ClutterActor *actor; + + actor = g_object_new (CLUTTER_WAYLAND_TYPE_SURFACE, + "surface", surface, + NULL); + + return actor; +} + +/** + * clutter_wayland_surface_attach_buffer: + * @self: A #ClutterWaylandSurface actor + * @buffer: A compositor side resource representing a wl_buffer + * @error: A #GError + * + * This associates a client's buffer with the #ClutterWaylandSurface + * actor @self. This will automatically result in @self being re-drawn + * with the new buffer contents. + * + * Since: 1.8 + * Stability: unstable + */ +gboolean +clutter_wayland_surface_attach_buffer (ClutterWaylandSurface *self, + struct wl_resource *buffer, + GError **error) +{ + ClutterWaylandSurfacePrivate *priv; + ClutterBackend *backend = clutter_get_default_backend (); + CoglContext *context = clutter_backend_get_cogl_context (backend); + + g_return_val_if_fail (CLUTTER_WAYLAND_IS_SURFACE (self), TRUE); + + priv = self->priv; + + free_surface_buffers (self); + + priv->buffer = + cogl_wayland_texture_2d_new_from_buffer (context, buffer, error); + + g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_COGL_TEXTURE]); + + /* NB: We don't queue a redraw of the actor here because we don't + * know how much of the buffer has changed with respect to the + * previous buffer. We only ever queue a redraw in response to + * surface damage. */ + + if (!priv->buffer) + return FALSE; + + set_size (self, + cogl_texture_get_width (COGL_TEXTURE (priv->buffer)), + cogl_texture_get_height (COGL_TEXTURE (priv->buffer))); + + return TRUE; +} + +/** + * clutter_wayland_surface_damage_buffer: + * @self: A #ClutterWaylandSurface actor + * @buffer: A wayland resource for a buffer + * @x: The x coordinate of the damaged rectangle + * @y: The y coordinate of the damaged rectangle + * @width: The width of the damaged rectangle + * @height: The height of the damaged rectangle + * + * This marks a region of the given @buffer has having been changed by + * the client. This will automatically result in the corresponding damaged + * region of the actor @self being redrawn. + * + * If multiple regions are changed then this should be called multiple + * times with different damage rectangles. + * + * Since: 1.8 + * Stability: unstable + */ +void +clutter_wayland_surface_damage_buffer (ClutterWaylandSurface *self, + struct wl_resource *buffer, + gint32 x, + gint32 y, + gint32 width, + gint32 height) +{ + ClutterWaylandSurfacePrivate *priv; + struct wl_shm_buffer *shm_buffer; + + g_return_if_fail (CLUTTER_WAYLAND_IS_SURFACE (self)); + + priv = self->priv; + + shm_buffer = wl_shm_buffer_get (buffer); + + if (priv->buffer && shm_buffer) + { + CoglPixelFormat format; + + switch (wl_shm_buffer_get_format (shm_buffer)) + { +#if G_BYTE_ORDER == G_BIG_ENDIAN + case WL_SHM_FORMAT_ARGB8888: + format = COGL_PIXEL_FORMAT_ARGB_8888_PRE; + break; + case WL_SHM_FORMAT_XRGB8888: + format = COGL_PIXEL_FORMAT_ARGB_8888; + break; +#elif G_BYTE_ORDER == G_LITTLE_ENDIAN + case WL_SHM_FORMAT_ARGB8888: + format = COGL_PIXEL_FORMAT_BGRA_8888_PRE; + break; + case WL_SHM_FORMAT_XRGB8888: + format = COGL_PIXEL_FORMAT_BGRA_8888; + break; +#endif + default: + g_warn_if_reached (); + format = COGL_PIXEL_FORMAT_ARGB_8888; + } + + cogl_texture_set_region (COGL_TEXTURE (priv->buffer), + x, y, + x, y, + width, height, + width, height, + format, + wl_shm_buffer_get_stride (shm_buffer), + wl_shm_buffer_get_data (shm_buffer)); + } + + g_signal_emit (self, signals[QUEUE_DAMAGE_REDRAW], + 0, + x, y, width, height); +} + +/** + * clutter_wayland_surface_get_cogl_texture: + * @self: a #ClutterWaylandSurface + * + * Retrieves the Cogl texture with the contents of the Wayland surface. + * + * Return value: (transfer none): a Cogl texture, or %NULL + * + * Since: 1.10 + */ +CoglTexture * +clutter_wayland_surface_get_cogl_texture (ClutterWaylandSurface *self) +{ + g_return_val_if_fail (CLUTTER_WAYLAND_IS_SURFACE (self), NULL); + + return COGL_TEXTURE (self->priv->buffer); +} diff --git a/clutter/clutter/wayland/clutter-wayland-surface.h b/clutter/clutter/wayland/clutter-wayland-surface.h new file mode 100644 index 0000000..f674af8 --- /dev/null +++ b/clutter/clutter/wayland/clutter-wayland-surface.h @@ -0,0 +1,117 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2011 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + * Authors: + * Robert Bragg + * + */ + +#ifndef __CLUTTER_WAYLAND_SURFACE_H__ +#define __CLUTTER_WAYLAND_SURFACE_H__ + +#include +#include +#include + +#include + +G_BEGIN_DECLS + +#define CLUTTER_WAYLAND_TYPE_SURFACE (clutter_wayland_surface_get_type ()) +#define CLUTTER_WAYLAND_SURFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_WAYLAND_TYPE_SURFACE, ClutterWaylandSurface)) +#define CLUTTER_WAYLAND_SURFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_WAYLAND_TYPE_SURFACE, ClutterWaylandSurfaceClass)) +#define CLUTTER_WAYLAND_IS_SURFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_WAYLAND_TYPE_SURFACE)) +#define CLUTTER_WAYLAND_IS_SURFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_WAYLAND_TYPE_SURFACE)) +#define CLUTTER_WAYLAND_SURFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_WAYLAND_TYPE_SURFACE, ClutterWaylandSurfaceClass)) + +typedef struct _ClutterWaylandSurface ClutterWaylandSurface; +typedef struct _ClutterWaylandSurfaceClass ClutterWaylandSurfaceClass; +typedef struct _ClutterWaylandSurfacePrivate ClutterWaylandSurfacePrivate; + +/** + * ClutterWaylandSurface: + * + * The #ClutterWaylandSurface structure contains only private data + * + * Since: 1.10 + * Stability: unstable + */ +struct _ClutterWaylandSurface +{ + /*< private >*/ + ClutterActor parent; + + ClutterWaylandSurfacePrivate *priv; +}; + +/** + * ClutterWaylandSurfaceClass: + * @queue_damage_redraw: class handler of the #ClutterWaylandSurface::queue-damage-redraw signal + * + * The #ClutterWaylandSurfaceClass structure contains only private data + * + * Since: 1.10 + * Stability: unstable + */ +struct _ClutterWaylandSurfaceClass +{ + /*< private >*/ + ClutterActorClass parent_class; + + /*< public >*/ + void (*queue_damage_redraw) (ClutterWaylandSurface *texture, + gint x, + gint y, + gint width, + gint height); + + /*< private >*/ + /* padding for future expansion */ + gpointer _padding_dummy[8]; +}; + +CLUTTER_AVAILABLE_IN_1_10 +GType clutter_wayland_surface_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_1_8 +ClutterActor *clutter_wayland_surface_new (struct wl_surface *surface); +CLUTTER_AVAILABLE_IN_1_10 +void clutter_wayland_surface_set_surface (ClutterWaylandSurface *self, + struct wl_surface *surface); +CLUTTER_AVAILABLE_IN_1_10 +struct wl_surface *clutter_wayland_surface_get_surface (ClutterWaylandSurface *self); +CLUTTER_AVAILABLE_IN_1_8 +gboolean clutter_wayland_surface_attach_buffer (ClutterWaylandSurface *self, + struct wl_resource *buffer, + GError **error); +CLUTTER_AVAILABLE_IN_1_8 +void clutter_wayland_surface_damage_buffer (ClutterWaylandSurface *self, + struct wl_resource *buffer, + gint32 x, + gint32 y, + gint32 width, + gint32 height); +CLUTTER_AVAILABLE_IN_1_10 +CoglTexture *clutter_wayland_surface_get_cogl_texture (ClutterWaylandSurface *self); + +G_END_DECLS + +#endif diff --git a/clutter/clutter/x11/clutter-backend-x11.c b/clutter/clutter/x11/clutter-backend-x11.c new file mode 100644 index 0000000..50fe293 --- /dev/null +++ b/clutter/clutter/x11/clutter-backend-x11.c @@ -0,0 +1,1501 @@ +/* Clutter. + * An OpenGL based 'interactive canvas' library. + * Authored By Matthew Allum + * Copyright (C) 2006-2007 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#include + +#include +#include +#include + +#include + +#include + +#include "clutter-backend-x11.h" +#include "clutter-device-manager-core-x11.h" +#include "clutter-device-manager-xi2.h" +#include "clutter-settings-x11.h" +#include "clutter-stage-x11.h" +#include "clutter-x11.h" + +#include "xsettings/xsettings-common.h" + +#if HAVE_XCOMPOSITE +#include +#endif + +#if HAVE_XINPUT_2 +#include +#endif + +#include +#include + +#include "clutter-backend.h" +#include "clutter-debug.h" +#include "clutter-device-manager-private.h" +#include "clutter-event-private.h" +#include "clutter-main.h" +#include "clutter-private.h" +#include "clutter-settings-private.h" + +G_DEFINE_TYPE (ClutterBackendX11, clutter_backend_x11, CLUTTER_TYPE_BACKEND) + +GType +clutter_x11_filter_return_get_type (void) +{ + static volatile gsize g_define_type__volatile; + + if (g_once_init_enter (&g_define_type__volatile)) + { + static const GEnumValue values[] = { + { CLUTTER_X11_FILTER_CONTINUE, "CLUTTER_X11_FILTER_CONTINUE", "continue" }, + { CLUTTER_X11_FILTER_TRANSLATE, "CLUTTER_X11_FILTER_TRANSLATE", "translate" }, + { CLUTTER_X11_FILTER_REMOVE, "CLUTTER_X11_FILTER_REMOVE", "remove" }, + { 0, NULL, NULL }, + }; + + GType g_define_type = + g_enum_register_static (g_intern_static_string ("ClutterX11FilterReturn"), values); + + g_once_init_leave (&g_define_type__volatile, g_define_type); + } + + return g_define_type__volatile; +} + +/* atoms; remember to add the code that assigns the atom value to + * the member of the ClutterBackendX11 structure if you add an + * atom name here. do not change the order! + */ +static const gchar *atom_names[] = { + "_NET_WM_PID", + "_NET_WM_PING", + "_NET_WM_STATE", + "_NET_WM_STATE_FULLSCREEN", + "_NET_WM_USER_TIME", + "WM_PROTOCOLS", + "WM_DELETE_WINDOW", + "_XEMBED", + "_XEMBED_INFO", + "_NET_WM_NAME", + "UTF8_STRING", +}; + +#define N_ATOM_NAMES G_N_ELEMENTS (atom_names) + +/* various flags corresponding to pre init setup calls */ +static gboolean _want_reset_on_video_memory_purge = FALSE; +static gboolean _no_xevent_retrieval = FALSE; +static gboolean clutter_enable_xinput = TRUE; +static gboolean clutter_enable_argb = FALSE; +static gboolean clutter_enable_stereo = FALSE; +static Display *_foreign_dpy = NULL; + +/* options */ +static gchar *clutter_display_name = NULL; +static gint clutter_screen = -1; +static gboolean clutter_synchronise = FALSE; + +/* X error trap */ +static int TrappedErrorCode = 0; +static int (* old_error_handler) (Display *, XErrorEvent *); + +static ClutterX11FilterReturn +xsettings_filter (XEvent *xevent, + ClutterEvent *event, + gpointer data) +{ + ClutterBackendX11 *backend_x11 = data; + + _clutter_xsettings_client_process_event (backend_x11->xsettings, xevent); + + /* we always want the rest of the stack to get XSettings events, even + * if Clutter already handled them + */ + + return CLUTTER_X11_FILTER_CONTINUE; +} + +static ClutterX11FilterReturn +cogl_xlib_filter (XEvent *xevent, + ClutterEvent *event, + gpointer data) +{ + ClutterBackend *backend = data; + ClutterX11FilterReturn retval; + CoglFilterReturn ret; + + ret = cogl_xlib_renderer_handle_event (backend->cogl_renderer, xevent); + switch (ret) + { + case COGL_FILTER_REMOVE: + retval = CLUTTER_X11_FILTER_REMOVE; + break; + + case COGL_FILTER_CONTINUE: + default: + retval = CLUTTER_X11_FILTER_CONTINUE; + break; + } + + return retval; +} + +static void +clutter_backend_x11_xsettings_notify (const char *name, + XSettingsAction action, + XSettingsSetting *setting, + void *cb_data) +{ + ClutterSettings *settings = clutter_settings_get_default (); + gint i; + + if (name == NULL || *name == '\0') + return; + + if (setting == NULL) + return; + + g_object_freeze_notify (G_OBJECT (settings)); + + for (i = 0; i < _n_clutter_settings_map; i++) + { + if (g_strcmp0 (name, CLUTTER_SETTING_X11_NAME (i)) == 0) + { + GValue value = G_VALUE_INIT; + + switch (setting->type) + { + case XSETTINGS_TYPE_INT: + g_value_init (&value, G_TYPE_INT); + g_value_set_int (&value, setting->data.v_int); + break; + + case XSETTINGS_TYPE_STRING: + g_value_init (&value, G_TYPE_STRING); + g_value_set_string (&value, setting->data.v_string); + break; + + case XSETTINGS_TYPE_COLOR: + { + ClutterColor color; + + color.red = (guint8) ((float) setting->data.v_color.red + / 65535.0 * 255); + color.green = (guint8) ((float) setting->data.v_color.green + / 65535.0 * 255); + color.blue = (guint8) ((float) setting->data.v_color.blue + / 65535.0 * 255); + color.alpha = (guint8) ((float) setting->data.v_color.alpha + / 65535.0 * 255); + + g_value_init (&value, G_TYPE_BOXED); + clutter_value_set_color (&value, &color); + } + break; + } + + CLUTTER_NOTE (BACKEND, + "Mapping XSETTING '%s' to 'ClutterSettings:%s'", + CLUTTER_SETTING_X11_NAME (i), + CLUTTER_SETTING_PROPERTY (i)); + + clutter_settings_set_property_internal (settings, + CLUTTER_SETTING_PROPERTY (i), + &value); + + g_value_unset (&value); + + break; + } + } + + g_object_thaw_notify (G_OBJECT (settings)); +} + +static void +clutter_backend_x11_create_device_manager (ClutterBackendX11 *backend_x11) +{ + ClutterEventTranslator *translator; + ClutterBackend *backend; + +#ifdef HAVE_XINPUT_2 + if (clutter_enable_xinput) + { + int event_base, first_event, first_error; + + if (XQueryExtension (backend_x11->xdpy, "XInputExtension", + &event_base, + &first_event, + &first_error)) + { + int major = 2; + int minor = 3; + + if (XIQueryVersion (backend_x11->xdpy, &major, &minor) != BadRequest) + { + CLUTTER_NOTE (BACKEND, "Creating XI2 device manager"); + backend_x11->has_xinput = TRUE; + backend_x11->device_manager = + g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_XI2, + "backend", backend_x11, + "opcode", event_base, + NULL); + + backend_x11->xi_minor = minor; + } + } + } + + if (backend_x11->device_manager == NULL) +#endif /* HAVE_XINPUT_2 */ + { + CLUTTER_NOTE (BACKEND, "Creating Core device manager"); + backend_x11->has_xinput = FALSE; + backend_x11->device_manager = + g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_X11, + "backend", backend_x11, + NULL); + + backend_x11->xi_minor = -1; + } + + backend = CLUTTER_BACKEND (backend_x11); + backend->device_manager = backend_x11->device_manager; + + translator = CLUTTER_EVENT_TRANSLATOR (backend_x11->device_manager); + _clutter_backend_add_event_translator (backend, translator); +} + +static void +clutter_backend_x11_create_keymap (ClutterBackendX11 *backend_x11) +{ + if (backend_x11->keymap == NULL) + { + ClutterEventTranslator *translator; + ClutterBackend *backend; + + backend_x11->keymap = + g_object_new (CLUTTER_TYPE_KEYMAP_X11, + "backend", backend_x11, + NULL); + + backend = CLUTTER_BACKEND (backend_x11); + translator = CLUTTER_EVENT_TRANSLATOR (backend_x11->keymap); + _clutter_backend_add_event_translator (backend, translator); + } +} + +static gboolean +clutter_backend_x11_pre_parse (ClutterBackend *backend, + GError **error) +{ + const gchar *env_string; + + /* we don't fail here if DISPLAY is not set, as the user + * might pass the --display command line switch + */ + env_string = g_getenv ("DISPLAY"); + if (env_string) + { + clutter_display_name = g_strdup (env_string); + env_string = NULL; + } + + env_string = g_getenv ("CLUTTER_DISABLE_ARGB_VISUAL"); + if (env_string) + { + clutter_enable_argb = FALSE; + env_string = NULL; + } + + env_string = g_getenv ("CLUTTER_DISABLE_XINPUT"); + if (env_string) + { + clutter_enable_xinput = FALSE; + env_string = NULL; + } + + return TRUE; +} + +static gboolean +clutter_backend_x11_post_parse (ClutterBackend *backend, + GError **error) +{ + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend); + ClutterSettings *settings; + Atom atoms[N_ATOM_NAMES]; + double dpi; + + if (_foreign_dpy) + backend_x11->xdpy = _foreign_dpy; + + /* Only open connection if not already set by prior call to + * clutter_x11_set_display() + */ + if (backend_x11->xdpy == NULL) + { + if (clutter_display_name != NULL && + *clutter_display_name != '\0') + { + CLUTTER_NOTE (BACKEND, "XOpenDisplay on '%s'", clutter_display_name); + + backend_x11->xdpy = XOpenDisplay (clutter_display_name); + if (backend_x11->xdpy == NULL) + { + g_set_error (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_BACKEND, + "Unable to open display '%s'", + clutter_display_name); + return FALSE; + } + } + else + { + g_set_error_literal (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_BACKEND, + "Unable to open display. You have to set the " + "DISPLAY environment variable, or use the " + "--display command line argument"); + return FALSE; + } + } + + g_assert (backend_x11->xdpy != NULL); + + CLUTTER_NOTE (BACKEND, "Getting the X screen"); + + settings = clutter_settings_get_default (); + + /* add event filter for Cogl events */ + clutter_x11_add_filter (cogl_xlib_filter, backend); + + if (clutter_screen == -1) + backend_x11->xscreen = DefaultScreenOfDisplay (backend_x11->xdpy); + else + backend_x11->xscreen = ScreenOfDisplay (backend_x11->xdpy, + clutter_screen); + + backend_x11->xscreen_num = XScreenNumberOfScreen (backend_x11->xscreen); + backend_x11->xscreen_width = WidthOfScreen (backend_x11->xscreen); + backend_x11->xscreen_height = HeightOfScreen (backend_x11->xscreen); + + backend_x11->xwin_root = RootWindow (backend_x11->xdpy, + backend_x11->xscreen_num); + + backend_x11->display_name = g_strdup (clutter_display_name); + + dpi = (((double) DisplayHeight (backend_x11->xdpy, backend_x11->xscreen_num) * 25.4) + / (double) DisplayHeightMM (backend_x11->xdpy, backend_x11->xscreen_num)); + + g_object_set (settings, "font-dpi", (int) dpi * 1024, NULL); + + /* create XSETTINGS client */ + backend_x11->xsettings = + _clutter_xsettings_client_new (backend_x11->xdpy, + backend_x11->xscreen_num, + clutter_backend_x11_xsettings_notify, + NULL, + backend_x11); + + /* add event filter for XSETTINGS events */ + clutter_x11_add_filter (xsettings_filter, backend_x11); + + if (clutter_synchronise) + XSynchronize (backend_x11->xdpy, True); + + XInternAtoms (backend_x11->xdpy, + (char **) atom_names, N_ATOM_NAMES, + False, atoms); + + backend_x11->atom_NET_WM_PID = atoms[0]; + backend_x11->atom_NET_WM_PING = atoms[1]; + backend_x11->atom_NET_WM_STATE = atoms[2]; + backend_x11->atom_NET_WM_STATE_FULLSCREEN = atoms[3]; + backend_x11->atom_NET_WM_USER_TIME = atoms[4]; + backend_x11->atom_WM_PROTOCOLS = atoms[5]; + backend_x11->atom_WM_DELETE_WINDOW = atoms[6]; + backend_x11->atom_XEMBED = atoms[7]; + backend_x11->atom_XEMBED_INFO = atoms[8]; + backend_x11->atom_NET_WM_NAME = atoms[9]; + backend_x11->atom_UTF8_STRING = atoms[10]; + + g_free (clutter_display_name); + + CLUTTER_NOTE (BACKEND, + "X Display '%s'[%p] opened (screen:%d, root:%u, dpi:%f)", + backend_x11->display_name, + backend_x11->xdpy, + backend_x11->xscreen_num, + (unsigned int) backend_x11->xwin_root, + clutter_backend_get_resolution (backend)); + + return TRUE; +} + +void +_clutter_backend_x11_events_init (ClutterBackend *backend) +{ + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend); + + CLUTTER_NOTE (EVENT, "initialising the event loop"); + + /* the event source is optional */ + if (!_no_xevent_retrieval) + { + GSource *source; + + source = _clutter_x11_event_source_new (backend_x11); + + /* default priority for events + * + * XXX - at some point we'll have a common EventSource API that + * is created by the backend, and this code will most likely go + * into the default implementation of ClutterBackend + */ + g_source_set_priority (source, CLUTTER_PRIORITY_EVENTS); + + /* attach the source to the default context, and transfer the + * ownership to the GMainContext itself + */ + g_source_attach (source, NULL); + g_source_unref (source); + + backend_x11->event_source = source; + } + + /* create the device manager; we need this because we can effectively + * choose between core+XI1 and XI2 input events + */ + clutter_backend_x11_create_device_manager (backend_x11); + + /* register keymap; unless we create a generic Keymap object, I'm + * afraid this will have to stay + */ + clutter_backend_x11_create_keymap (backend_x11); +} + +static const GOptionEntry entries[] = +{ + { + "display", 0, + G_OPTION_FLAG_IN_MAIN, + G_OPTION_ARG_STRING, &clutter_display_name, + N_("X display to use"), "DISPLAY" + }, + { + "screen", 0, + G_OPTION_FLAG_IN_MAIN, + G_OPTION_ARG_INT, &clutter_screen, + N_("X screen to use"), "SCREEN" + }, + { "synch", 0, + 0, + G_OPTION_ARG_NONE, &clutter_synchronise, + N_("Make X calls synchronous"), NULL + }, +#ifdef HAVE_XINPUT_2 + { + "disable-xinput", 0, + G_OPTION_FLAG_REVERSE, + G_OPTION_ARG_NONE, &clutter_enable_xinput, + N_("Disable XInput support"), NULL + }, +#endif /* HAVE_XINPUT_2 */ + { NULL } +}; + +static void +clutter_backend_x11_add_options (ClutterBackend *backend, + GOptionGroup *group) +{ + g_option_group_add_entries (group, entries); +} + +static void +clutter_backend_x11_finalize (GObject *gobject) +{ + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (gobject); + + g_free (backend_x11->display_name); + + clutter_x11_remove_filter (cogl_xlib_filter, gobject); + + clutter_x11_remove_filter (xsettings_filter, backend_x11); + _clutter_xsettings_client_destroy (backend_x11->xsettings); + + XCloseDisplay (backend_x11->xdpy); + + G_OBJECT_CLASS (clutter_backend_x11_parent_class)->finalize (gobject); +} + +static void +clutter_backend_x11_dispose (GObject *gobject) +{ + G_OBJECT_CLASS (clutter_backend_x11_parent_class)->dispose (gobject); +} + +static ClutterFeatureFlags +clutter_backend_x11_get_features (ClutterBackend *backend) +{ + ClutterFeatureFlags flags = CLUTTER_FEATURE_STAGE_USER_RESIZE + | CLUTTER_FEATURE_STAGE_CURSOR; + + flags |= CLUTTER_BACKEND_CLASS (clutter_backend_x11_parent_class)->get_features (backend); + + return flags; +} + +static void +update_last_event_time (ClutterBackendX11 *backend_x11, + XEvent *xevent) +{ + Time current_time = CurrentTime; + Time last_time = backend_x11->last_event_time; + + switch (xevent->type) + { + case KeyPress: + case KeyRelease: + current_time = xevent->xkey.time; + break; + + case ButtonPress: + case ButtonRelease: + current_time = xevent->xbutton.time; + break; + + case MotionNotify: + current_time = xevent->xmotion.time; + break; + + case EnterNotify: + case LeaveNotify: + current_time = xevent->xcrossing.time; + break; + + case PropertyNotify: + current_time = xevent->xproperty.time; + break; + + default: + break; + } + + /* only change the current event time if it's after the previous event + * time, or if it is at least 30 seconds earlier - in case the system + * clock was changed + */ + if ((current_time != CurrentTime) && + (current_time > last_time || (last_time - current_time > (30 * 1000)))) + backend_x11->last_event_time = current_time; +} + +static gboolean +clutter_backend_x11_translate_event (ClutterBackend *backend, + gpointer native, + ClutterEvent *event) +{ + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend); + ClutterBackendClass *parent_class; + XEvent *xevent = native; + + /* X11 filter functions have a higher priority */ + if (backend_x11->event_filters != NULL) + { + GSList *node = backend_x11->event_filters; + + while (node != NULL) + { + ClutterX11EventFilter *filter = node->data; + + switch (filter->func (xevent, event, filter->data)) + { + case CLUTTER_X11_FILTER_CONTINUE: + break; + + case CLUTTER_X11_FILTER_TRANSLATE: + return TRUE; + + case CLUTTER_X11_FILTER_REMOVE: + return FALSE; + + default: + break; + } + + node = node->next; + } + } + + /* we update the event time only for events that can + * actually reach Clutter's event queue + */ + update_last_event_time (backend_x11, xevent); + + /* chain up to the parent implementation, which will handle + * event translators + */ + parent_class = CLUTTER_BACKEND_CLASS (clutter_backend_x11_parent_class); + return parent_class->translate_event (backend, native, event); +} + +static CoglRenderer * +clutter_backend_x11_get_renderer (ClutterBackend *backend, + GError **error) +{ + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend); + Display *xdisplay = backend_x11->xdpy; + CoglRenderer *renderer; + + CLUTTER_NOTE (BACKEND, "Creating a new Xlib renderer"); + + renderer = cogl_renderer_new (); + + cogl_renderer_add_constraint (renderer, COGL_RENDERER_CONSTRAINT_USES_X11); + + /* set the display object we're using */ + cogl_xlib_renderer_set_foreign_display (renderer, xdisplay); + cogl_xlib_renderer_request_reset_on_video_memory_purge (renderer, + _want_reset_on_video_memory_purge); + return renderer; +} + +static gboolean +check_onscreen_template (CoglRenderer *renderer, + CoglSwapChain *swap_chain, + CoglOnscreenTemplate *onscreen_template, + CoglBool enable_argb, + CoglBool enable_stereo, + GError **error) +{ + GError *internal_error = NULL; + + cogl_swap_chain_set_has_alpha (swap_chain, enable_argb); + cogl_onscreen_template_set_stereo_enabled (onscreen_template, + clutter_enable_stereo); + + /* cogl_renderer_check_onscreen_template() is actually just a + * shorthand for creating a CoglDisplay, and calling + * cogl_display_setup() on it, then throwing the display away. If we + * could just return that display, then it would be more efficient + * not to use cogl_renderer_check_onscreen_template(). However, the + * backend API requires that we return an CoglDisplay that has not + * yet been setup, so one way or the other we'll have to discard the + * first display and make a new fresh one. + */ + if (cogl_renderer_check_onscreen_template (renderer, onscreen_template, &internal_error)) + { + clutter_enable_argb = enable_argb; + clutter_enable_stereo = enable_stereo; + + return TRUE; + } + else + { + if (enable_argb || enable_stereo) /* More possibilities to try */ + CLUTTER_NOTE (BACKEND, + "Creation of a CoglDisplay with alpha=%s, stereo=%s failed: %s", + enable_argb ? "enabled" : "disabled", + enable_stereo ? "enabled" : "disabled", + internal_error != NULL + ? internal_error->message + : "Unknown reason"); + else + g_set_error_literal (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_BACKEND, + internal_error != NULL + ? internal_error->message + : "Creation of a CoglDisplay failed"); + + g_clear_error (&internal_error); + + return FALSE; + } +} + +static CoglDisplay * +clutter_backend_x11_get_display (ClutterBackend *backend, + CoglRenderer *renderer, + CoglSwapChain *swap_chain, + GError **error) +{ + CoglOnscreenTemplate *onscreen_template; + CoglDisplay *display = NULL; + gboolean res = FALSE; + + CLUTTER_NOTE (BACKEND, "Creating CoglDisplay, alpha=%s, stereo=%s", + clutter_enable_argb ? "enabled" : "disabled", + clutter_enable_stereo ? "enabled" : "disabled"); + + onscreen_template = cogl_onscreen_template_new (swap_chain); + + /* It's possible that the current renderer doesn't support transparency + * or doesn't support stereo, so we try the different combinations. + */ + if (clutter_enable_argb && clutter_enable_stereo) + res = check_onscreen_template (renderer, swap_chain, onscreen_template, + TRUE, TRUE, error); + + /* Prioritize stereo over alpha */ + if (!res && clutter_enable_stereo) + res = check_onscreen_template (renderer, swap_chain, onscreen_template, + FALSE, TRUE, error); + + if (!res && clutter_enable_argb) + res = check_onscreen_template (renderer, swap_chain, onscreen_template, + TRUE, FALSE, error); + + if (!res) + res = check_onscreen_template (renderer, swap_chain, onscreen_template, + FALSE, FALSE, error); + + if (res) + display = cogl_display_new (renderer, onscreen_template); + + cogl_object_unref (onscreen_template); + + return display; +} + +static ClutterStageWindow * +clutter_backend_x11_create_stage (ClutterBackend *backend, + ClutterStage *wrapper, + GError **error) +{ + ClutterEventTranslator *translator; + ClutterStageWindow *stage; + + stage = g_object_new (CLUTTER_TYPE_STAGE_X11, + "backend", backend, + "wrapper", wrapper, + NULL); + + /* the X11 stage does event translation */ + translator = CLUTTER_EVENT_TRANSLATOR (stage); + _clutter_backend_add_event_translator (backend, translator); + + CLUTTER_NOTE (BACKEND, "X11 stage created (display:%p, screen:%d, root:%u)", + CLUTTER_BACKEND_X11 (backend)->xdpy, + CLUTTER_BACKEND_X11 (backend)->xscreen_num, + (unsigned int) CLUTTER_BACKEND_X11 (backend)->xwin_root); + + return stage; +} + +static PangoDirection +clutter_backend_x11_get_keymap_direction (ClutterBackend *backend) +{ + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend); + + if (G_UNLIKELY (backend_x11->keymap == NULL)) + return PANGO_DIRECTION_NEUTRAL; + + return _clutter_keymap_x11_get_direction (backend_x11->keymap); +} + +static void +clutter_backend_x11_class_init (ClutterBackendX11Class *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass); + + gobject_class->dispose = clutter_backend_x11_dispose; + gobject_class->finalize = clutter_backend_x11_finalize; + + backend_class->create_stage = clutter_backend_x11_create_stage; + + backend_class->pre_parse = clutter_backend_x11_pre_parse; + backend_class->post_parse = clutter_backend_x11_post_parse; + backend_class->add_options = clutter_backend_x11_add_options; + backend_class->get_features = clutter_backend_x11_get_features; + + backend_class->translate_event = clutter_backend_x11_translate_event; + + backend_class->get_renderer = clutter_backend_x11_get_renderer; + backend_class->get_display = clutter_backend_x11_get_display; + + backend_class->get_keymap_direction = clutter_backend_x11_get_keymap_direction; +} + +static void +clutter_backend_x11_init (ClutterBackendX11 *backend_x11) +{ + backend_x11->last_event_time = CurrentTime; +} + +ClutterBackend * +clutter_backend_x11_new (void) +{ + return g_object_new (CLUTTER_TYPE_BACKEND_X11, NULL); +} + +static int +error_handler(Display *xdpy, + XErrorEvent *error) +{ + TrappedErrorCode = error->error_code; + return 0; +} + +/** + * clutter_x11_trap_x_errors: + * + * Traps every X error until clutter_x11_untrap_x_errors() is called. + * + * Since: 0.6 + */ +void +clutter_x11_trap_x_errors (void) +{ + TrappedErrorCode = 0; + old_error_handler = XSetErrorHandler (error_handler); +} + +/** + * clutter_x11_untrap_x_errors: + * + * Removes the X error trap and returns the current status. + * + * Return value: the trapped error code, or 0 for success + * + * Since: 0.4 + */ +gint +clutter_x11_untrap_x_errors (void) +{ + XSetErrorHandler (old_error_handler); + + return TrappedErrorCode; +} + +/** + * clutter_x11_get_default_display: + * + * Retrieves the pointer to the default display. + * + * Return value: (transfer none): the default display + * + * Since: 0.6 + */ +Display * +clutter_x11_get_default_display (void) +{ + ClutterBackend *backend = clutter_get_default_backend (); + + if (backend == NULL) + { + g_critical ("The Clutter backend has not been initialised"); + return NULL; + } + + if (!CLUTTER_IS_BACKEND_X11 (backend)) + { + g_critical ("The Clutter backend is not a X11 backend"); + return NULL; + } + + return CLUTTER_BACKEND_X11 (backend)->xdpy; +} + +/** + * clutter_x11_set_display: + * @xdpy: pointer to a X display connection. + * + * Sets the display connection Clutter should use; must be called + * before clutter_init(), clutter_init_with_args() or other functions + * pertaining Clutter's initialization process. + * + * If you are parsing the command line arguments by retrieving Clutter's + * #GOptionGroup with clutter_get_option_group() and calling + * g_option_context_parse() yourself, you should also call + * clutter_x11_set_display() before g_option_context_parse(). + * + * Since: 0.8 + */ +void +clutter_x11_set_display (Display *xdpy) +{ + if (_clutter_context_is_initialized ()) + { + g_warning ("%s() can only be used before calling clutter_init()", + G_STRFUNC); + return; + } + + _foreign_dpy= xdpy; +} + +/** + * clutter_x11_enable_xinput: + * + * Enables the use of the XInput extension if present on connected + * XServer and support built into Clutter. XInput allows for multiple + * pointing devices to be used. + * + * This function must be called before clutter_init(). + * + * Since XInput might not be supported by the X server, you might + * want to use clutter_x11_has_xinput() to see if support was enabled. + * + * Since: 0.8 + * + * Deprecated: 1.14: This function does not do anything; XInput support + * is enabled by default in Clutter. Use the CLUTTER_DISABLE_XINPUT + * environment variable to disable XInput support and use Xlib core + * events instead. + */ +void +clutter_x11_enable_xinput (void) +{ +} + +/** + * clutter_x11_disable_event_retrieval: + * + * Disables the internal polling of X11 events in the main loop. + * + * Libraries or applications calling this function will be responsible of + * polling all X11 events. + * + * You also must call clutter_x11_handle_event() to let Clutter process + * events and maintain its internal state. + * + * This function can only be called before calling clutter_init(). + * + * Even with event handling disabled, Clutter will still select + * all the events required to maintain its internal state on the stage + * Window; compositors using Clutter and input regions to pass events + * through to application windows should not rely on an empty input + * region, and should instead clear it themselves explicitly using the + * XFixes extension. + * + * This function should not be normally used by applications. + * + * Since: 0.8 + */ +void +clutter_x11_disable_event_retrieval (void) +{ + if (_clutter_context_is_initialized ()) + { + g_warning ("%s() can only be used before calling clutter_init()", + G_STRFUNC); + return; + } + + _no_xevent_retrieval = TRUE; +} + +/** + * clutter_x11_has_event_retrieval: + * + * Queries the X11 backend to check if event collection has been disabled. + * + * Return value: TRUE if event retrival has been disabled. FALSE otherwise. + * + * Since: 0.8 + */ +gboolean +clutter_x11_has_event_retrieval (void) +{ + return !_no_xevent_retrieval; +} + +/** + * clutter_x11_request_reset_on_video_memory_purge: + * + * If the GL driver supports the NV_robustness_video_memory_purge + * extension, this call lets applications request that it gets + * initialized, thus allowing cogl_get_graphics_reset_status() to + * report memory purged errors if they happen. Checking for the + * graphics reset status is the application's responsibility. + * + * This function can only be called before calling clutter_init(). + */ +void +clutter_x11_request_reset_on_video_memory_purge (void) +{ + if (_clutter_context_is_initialized ()) + { + g_warning ("%s() can only be used before calling clutter_init()", + G_STRFUNC); + return; + } + + _want_reset_on_video_memory_purge = TRUE; +} + +/** + * clutter_x11_get_default_screen: + * + * Gets the number of the default X Screen object. + * + * Return value: the number of the default screen + * + * Since: 0.6 + */ +int +clutter_x11_get_default_screen (void) +{ + ClutterBackend *backend = clutter_get_default_backend (); + + if (backend == NULL) + { + g_critical ("The Clutter backend has not been initialised"); + return 0; + } + + if (!CLUTTER_IS_BACKEND_X11 (backend)) + { + g_critical ("The Clutter backend is not a X11 backend"); + return 0; + } + + return CLUTTER_BACKEND_X11 (backend)->xscreen_num; +} + +/** + * clutter_x11_get_root_window: (skip) + * + * Retrieves the root window. + * + * Return value: the id of the root window + * + * Since: 0.6 + */ +Window +clutter_x11_get_root_window (void) +{ + ClutterBackend *backend = clutter_get_default_backend (); + + if (backend == NULL) + { + g_critical ("The Clutter backend has not been initialised"); + return None; + } + + if (!CLUTTER_IS_BACKEND_X11 (backend)) + { + g_critical ("The Clutter backend is not a X11 backend"); + return None; + } + + return CLUTTER_BACKEND_X11 (backend)->xwin_root; +} + +/** + * clutter_x11_add_filter: (skip) + * @func: a filter function + * @data: user data to be passed to the filter function, or %NULL + * + * Adds an event filter function. + * + * Since: 0.6 + */ +void +clutter_x11_add_filter (ClutterX11FilterFunc func, + gpointer data) +{ + ClutterX11EventFilter *filter; + ClutterBackend *backend = clutter_get_default_backend (); + ClutterBackendX11 *backend_x11; + + g_return_if_fail (func != NULL); + + if (backend == NULL) + { + g_critical ("The Clutter backend has not been initialised"); + return; + } + + if (!CLUTTER_IS_BACKEND_X11 (backend)) + { + g_critical ("The Clutter backend is not a X11 backend"); + return; + } + + backend_x11 = CLUTTER_BACKEND_X11 (backend); + + filter = g_new0 (ClutterX11EventFilter, 1); + filter->func = func; + filter->data = data; + + backend_x11->event_filters = + g_slist_append (backend_x11->event_filters, filter); + + return; +} + +/** + * clutter_x11_remove_filter: (skip) + * @func: a filter function + * @data: user data to be passed to the filter function, or %NULL + * + * Removes the given filter function. + * + * Since: 0.6 + */ +void +clutter_x11_remove_filter (ClutterX11FilterFunc func, + gpointer data) +{ + GSList *tmp_list, *this; + ClutterX11EventFilter *filter; + ClutterBackend *backend = clutter_get_default_backend (); + ClutterBackendX11 *backend_x11; + + g_return_if_fail (func != NULL); + + if (backend == NULL) + { + g_critical ("The Clutter backend has not been initialised"); + return; + } + + if (!CLUTTER_IS_BACKEND_X11 (backend)) + { + g_critical ("The Clutter backend is not a X11 backend"); + return; + } + + backend_x11 = CLUTTER_BACKEND_X11 (backend); + + tmp_list = backend_x11->event_filters; + + while (tmp_list) + { + filter = tmp_list->data; + this = tmp_list; + tmp_list = tmp_list->next; + + if (filter->func == func && filter->data == data) + { + backend_x11->event_filters = + g_slist_remove_link (backend_x11->event_filters, this); + + g_slist_free_1 (this); + g_free (filter); + + return; + } + } +} + +/** + * clutter_x11_get_input_devices: + * + * Retrieves a pointer to the list of input devices + * + * Deprecated: 1.2: Use clutter_device_manager_peek_devices() instead + * + * Since: 0.8 + * + * Return value: (transfer none) (element-type Clutter.InputDevice): a + * pointer to the internal list of input devices; the returned list is + * owned by Clutter and should not be modified or freed + */ +const GSList * +clutter_x11_get_input_devices (void) +{ + ClutterDeviceManager *manager; + + manager = clutter_device_manager_get_default (); + if (manager == NULL) + return NULL; + + return clutter_device_manager_peek_devices (manager); +} + +/** + * clutter_x11_has_xinput: + * + * Gets whether Clutter has XInput support. + * + * Return value: %TRUE if Clutter was compiled with XInput support + * and XInput support is available at run time. + * + * Since: 0.8 + */ +gboolean +clutter_x11_has_xinput (void) +{ +#ifdef HAVE_XINPUT_2 + ClutterBackend *backend = clutter_get_default_backend (); + + if (backend == NULL) + { + g_critical ("The Clutter backend has not been initialised"); + return FALSE; + } + + if (!CLUTTER_IS_BACKEND_X11 (backend)) + { + g_critical ("The Clutter backend is not a X11 backend."); + return FALSE; + } + + return CLUTTER_BACKEND_X11 (backend)->has_xinput; +#else + return FALSE; +#endif +} + +/** + * clutter_x11_has_composite_extension: + * + * Retrieves whether Clutter is running on an X11 server with the + * XComposite extension + * + * Return value: %TRUE if the XComposite extension is available + */ +gboolean +clutter_x11_has_composite_extension (void) +{ +#if HAVE_XCOMPOSITE + static gboolean have_composite = FALSE, done_check = FALSE; + int error = 0, event = 0; + Display *dpy; + + if (done_check) + return have_composite; + + if (!_clutter_context_is_initialized ()) + { + g_critical ("X11 backend has not been initialised"); + return FALSE; + } + + dpy = clutter_x11_get_default_display(); + if (dpy == NULL) + return FALSE; + + if (XCompositeQueryExtension (dpy, &event, &error)) + { + int major = 0, minor = 0; + if (XCompositeQueryVersion (dpy, &major, &minor)) + { + if (major >= 0 && minor >= 3) + have_composite = TRUE; + } + } + + done_check = TRUE; + + return have_composite; +#else + return FALSE; +#endif /* HAVE_XCOMPOSITE */ +} + +/** + * clutter_x11_set_use_argb_visual: + * @use_argb: %TRUE if ARGB visuals should be requested by default + * + * Sets whether the Clutter X11 backend should request ARGB visuals by default + * or not. + * + * By default, Clutter requests RGB visuals. + * + * If no ARGB visuals are found, the X11 backend will fall back to + * requesting a RGB visual instead. + * + * ARGB visuals are required for the #ClutterStage:use-alpha property to work. + * + * This function can only be called once, and before clutter_init() is + * called. + * + * Since: 1.2 + */ +void +clutter_x11_set_use_argb_visual (gboolean use_argb) +{ + if (_clutter_context_is_initialized ()) + { + g_warning ("%s() can only be used before calling clutter_init()", + G_STRFUNC); + return; + } + + CLUTTER_NOTE (BACKEND, "ARGB visuals are %s", + use_argb ? "enabled" : "disabled"); + + clutter_enable_argb = use_argb; +} + +/** + * clutter_x11_get_use_argb_visual: + * + * Retrieves whether the Clutter X11 backend is using ARGB visuals by default + * + * Return value: %TRUE if ARGB visuals are queried by default + * + * Since: 1.2 + */ +gboolean +clutter_x11_get_use_argb_visual (void) +{ + return clutter_enable_argb; +} + +/** + * clutter_x11_set_use_stereo_stage: + * @use_stereo: %TRUE if the stereo stages should be used if possible. + * + * Sets whether the backend object for Clutter stages, will, + * if possible, be created with the ability to support stereo drawing + * (drawing separate images for the left and right eyes). + * + * This function must be called before clutter_init() is called. + * During paint callbacks, cogl_framebuffer_is_stereo() can be called + * on the framebuffer retrieved by cogl_get_draw_framebuffer() to + * determine if stereo support was successfully enabled, and + * cogl_framebuffer_set_stereo_mode() to determine which buffers + * will be drawn to. + * + * Note that this function *does not* cause the stage to be drawn + * multiple times with different perspective transformations and thus + * appear in 3D, it simply enables individual ClutterActors to paint + * different images for the left and and right eye. + * + * Since: 1.22 + */ +void +clutter_x11_set_use_stereo_stage (gboolean use_stereo) +{ + if (_clutter_context_is_initialized ()) + { + g_warning ("%s() can only be used before calling clutter_init()", + G_STRFUNC); + return; + } + + CLUTTER_NOTE (BACKEND, "STEREO stages are %s", + use_stereo ? "enabled" : "disabled"); + + clutter_enable_stereo = use_stereo; +} + +/** + * clutter_x11_get_use_stereo_stage: + * + * Retrieves whether the Clutter X11 backend will create stereo + * stages if possible. + * + * Return value: %TRUE if stereo stages are used if possible + * + * Since: 1.22 + */ +gboolean +clutter_x11_get_use_stereo_stage (void) +{ + return clutter_enable_stereo; +} + +XVisualInfo * +_clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11) +{ + return cogl_clutter_winsys_xlib_get_visual_info (); +} + +/** + * clutter_x11_get_visual_info: (skip) + * + * Retrieves the `XVisualInfo` used by the Clutter X11 backend. + * + * Return value: (transfer full): a `XVisualInfo`, or `None`. + * The returned value should be freed using `XFree()` when done + * + * Since: 1.2 + */ +XVisualInfo * +clutter_x11_get_visual_info (void) +{ + ClutterBackendX11 *backend_x11; + ClutterBackend *backend; + + backend = clutter_get_default_backend (); + if (!CLUTTER_IS_BACKEND_X11 (backend)) + { + g_critical ("The Clutter backend is not a X11 backend."); + return NULL; + } + + backend_x11 = CLUTTER_BACKEND_X11 (backend); + + return _clutter_backend_x11_get_visual_info (backend_x11); +} + +gboolean +_clutter_x11_input_device_translate_screen_coord (ClutterInputDevice *device, + gint stage_root_x, + gint stage_root_y, + guint index_, + gdouble value, + gdouble *axis_value) +{ + ClutterAxisInfo *info; + ClutterBackendX11 *backend_x11; + gdouble width, scale, offset; + + backend_x11 = CLUTTER_BACKEND_X11 (device->backend); + + if (device->axes == NULL || index_ >= device->axes->len) + return FALSE; + + info = &g_array_index (device->axes, ClutterAxisInfo, index_); + if (!(info->axis == CLUTTER_INPUT_AXIS_X || info->axis == CLUTTER_INPUT_AXIS_Y)) + return FALSE; + + width = info->max_value - info->min_value; + + if (info->axis == CLUTTER_INPUT_AXIS_X) + { + if (width > 0) + scale = backend_x11->xscreen_width / width; + else + scale = 1; + + offset = - stage_root_x; + } + else + { + if (width > 0) + scale = backend_x11->xscreen_height / width; + else + scale = 1; + + offset = - stage_root_y; + } + + if (axis_value) + *axis_value = offset + scale * (value - info->min_value); + + return TRUE; +} diff --git a/clutter/clutter/x11/clutter-backend-x11.h b/clutter/clutter/x11/clutter-backend-x11.h new file mode 100644 index 0000000..50d0797 --- /dev/null +++ b/clutter/clutter/x11/clutter-backend-x11.h @@ -0,0 +1,148 @@ +/* Clutter. + * An OpenGL based 'interactive canvas' library. + * Authored By Matthew Allum + * Copyright (C) 2006-2007 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +#ifndef __CLUTTER_BACKEND_X11_H__ +#define __CLUTTER_BACKEND_X11_H__ + +#include +#include +#include +#include + +#include "clutter-x11.h" + +#include "clutter-backend-private.h" +#include "clutter-keymap-x11.h" + +#include "xsettings/xsettings-client.h" + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BACKEND_X11 (clutter_backend_x11_get_type ()) +#define CLUTTER_BACKEND_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BACKEND_X11, ClutterBackendX11)) +#define CLUTTER_IS_BACKEND_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BACKEND_X11)) +#define CLUTTER_BACKEND_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BACKEND_X11, ClutterBackendX11Class)) +#define CLUTTER_IS_BACKEND_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BACKEND_X11)) +#define CLUTTER_BACKEND_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BACKEND_X11, ClutterBackendX11Class)) + +typedef struct _ClutterBackendX11 ClutterBackendX11; +typedef struct _ClutterBackendX11Class ClutterBackendX11Class; +typedef struct _ClutterEventX11 ClutterEventX11; +typedef struct _ClutterX11EventFilter ClutterX11EventFilter; + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBackendX11, g_object_unref) + +struct _ClutterX11EventFilter +{ + ClutterX11FilterFunc func; + gpointer data; + +}; + +struct _ClutterEventX11 +{ + /* additional fields for Key events */ + gint key_group; + + guint key_is_modifier : 1; + guint num_lock_set : 1; + guint caps_lock_set : 1; +}; + +struct _ClutterBackendX11 +{ + ClutterBackend parent_instance; + + Display *xdpy; + gchar *display_name; + + Screen *xscreen; + int xscreen_num; + int xscreen_width; + int xscreen_height; + + Window xwin_root; + + /* event source */ + GSource *event_source; + GSList *event_filters; + + /* props */ + Atom atom_NET_WM_PID; + Atom atom_NET_WM_PING; + Atom atom_NET_WM_STATE; + Atom atom_NET_WM_STATE_FULLSCREEN; + Atom atom_NET_WM_USER_TIME; + Atom atom_WM_PROTOCOLS; + Atom atom_WM_DELETE_WINDOW; + Atom atom_XEMBED; + Atom atom_XEMBED_INFO; + Atom atom_NET_WM_NAME; + Atom atom_UTF8_STRING; + + Time last_event_time; + + ClutterDeviceManager *device_manager; + gboolean has_xinput; + int xi_minor; + + XSettingsClient *xsettings; + Window xsettings_xwin; + + ClutterKeymapX11 *keymap; + gboolean use_xkb; + gboolean have_xkb_autorepeat; + guint keymap_serial; +}; + +struct _ClutterBackendX11Class +{ + ClutterBackendClass parent_class; +}; + +CLUTTER_AVAILABLE_IN_MUTTER +GType clutter_backend_x11_get_type (void) G_GNUC_CONST; + +ClutterBackend *clutter_backend_x11_new (void); + +void _clutter_backend_x11_events_init (ClutterBackend *backend); + +GSource * _clutter_x11_event_source_new (ClutterBackendX11 *backend_x11); + +/* Private to glx/eglx backends */ +XVisualInfo * _clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11); + +void _clutter_x11_select_events (Window xwin); + +ClutterEventX11 * _clutter_event_x11_new (void); +ClutterEventX11 * _clutter_event_x11_copy (ClutterEventX11 *event_x11); +void _clutter_event_x11_free (ClutterEventX11 *event_x11); + +gboolean _clutter_x11_input_device_translate_screen_coord (ClutterInputDevice *device, + gint stage_root_x, + gint stage_root_y, + guint index_, + gdouble value, + gdouble *axis_value); + +G_END_DECLS + +#endif /* __CLUTTER_BACKEND_X11_H__ */ diff --git a/clutter/clutter/x11/clutter-device-manager-core-x11.c b/clutter/clutter/x11/clutter-device-manager-core-x11.c new file mode 100644 index 0000000..a410600 --- /dev/null +++ b/clutter/clutter/x11/clutter-device-manager-core-x11.c @@ -0,0 +1,544 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright © 2009, 2010, 2011 Intel Corp. + * + * 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 . + * + * Author: Emmanuele Bassi + */ + +#include "clutter-build-config.h" + +#include "clutter-device-manager-core-x11.h" + +#include "clutter-backend-x11.h" +#include "clutter-input-device-core-x11.h" +#include "clutter-stage-x11.h" +#include "clutter-virtual-input-device-x11.h" + +#include "clutter-backend.h" +#include "clutter-debug.h" +#include "clutter-device-manager-private.h" +#include "clutter-event-private.h" +#include "clutter-event-translator.h" +#include "clutter-stage-private.h" +#include "clutter-private.h" + +enum +{ + PROP_0, + + PROP_EVENT_BASE, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST] = { NULL, }; + +static void clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface); + +#define clutter_device_manager_x11_get_type _clutter_device_manager_x11_get_type + +G_DEFINE_TYPE_WITH_CODE (ClutterDeviceManagerX11, + clutter_device_manager_x11, + CLUTTER_TYPE_DEVICE_MANAGER, + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_EVENT_TRANSLATOR, + clutter_event_translator_iface_init)); + +static inline void +translate_key_event (ClutterBackendX11 *backend_x11, + ClutterDeviceManagerX11 *manager_x11, + ClutterEvent *event, + XEvent *xevent) +{ + ClutterEventX11 *event_x11; + char buffer[256 + 1]; + int n; + + event->key.type = xevent->xany.type == KeyPress ? CLUTTER_KEY_PRESS + : CLUTTER_KEY_RELEASE; + event->key.time = xevent->xkey.time; + + clutter_event_set_device (event, manager_x11->core_keyboard); + + /* KeyEvents have platform specific data associated to them */ + event_x11 = _clutter_event_x11_new (); + _clutter_event_set_platform_data (event, event_x11); + + event->key.modifier_state = (ClutterModifierType) xevent->xkey.state; + event->key.hardware_keycode = xevent->xkey.keycode; + + /* keyval is the key ignoring all modifiers ('1' vs. '!') */ + event->key.keyval = + _clutter_keymap_x11_translate_key_state (backend_x11->keymap, + event->key.hardware_keycode, + &event->key.modifier_state, + NULL); + + event_x11->key_group = + _clutter_keymap_x11_get_key_group (backend_x11->keymap, + event->key.modifier_state); + event_x11->key_is_modifier = + _clutter_keymap_x11_get_is_modifier (backend_x11->keymap, + event->key.hardware_keycode); + event_x11->num_lock_set = + _clutter_keymap_x11_get_num_lock_state (backend_x11->keymap); + event_x11->caps_lock_set = + _clutter_keymap_x11_get_caps_lock_state (backend_x11->keymap); + + /* unicode_value is the printable representation */ + n = XLookupString (&xevent->xkey, buffer, sizeof (buffer) - 1, NULL, NULL); + + if (n != NoSymbol) + { + event->key.unicode_value = g_utf8_get_char_validated (buffer, n); + if ((event->key.unicode_value != (gunichar) -1) && + (event->key.unicode_value != (gunichar) -2)) + goto out; + } + else + event->key.unicode_value = (gunichar)'\0'; + +out: + CLUTTER_NOTE (EVENT, + "%s: win:0x%x, key: %12s (%d)", + event->any.type == CLUTTER_KEY_PRESS + ? "key press " + : "key release", + (unsigned int) xevent->xkey.window, + event->key.keyval ? buffer : "(none)", + event->key.keyval); + return; +} + +static ClutterTranslateReturn +clutter_device_manager_x11_translate_event (ClutterEventTranslator *translator, + gpointer native, + ClutterEvent *event) +{ + ClutterDeviceManagerX11 *manager_x11; + ClutterBackendX11 *backend_x11; + ClutterStageX11 *stage_x11; + ClutterTranslateReturn res; + ClutterStage *stage; + XEvent *xevent; + int window_scale; + + manager_x11 = CLUTTER_DEVICE_MANAGER_X11 (translator); + backend_x11 = CLUTTER_BACKEND_X11 (clutter_get_default_backend ()); + + xevent = native; + + stage = clutter_x11_get_stage_from_window (xevent->xany.window); + if (stage == NULL) + return CLUTTER_TRANSLATE_CONTINUE; + + if (CLUTTER_ACTOR_IN_DESTRUCTION (stage)) + return CLUTTER_TRANSLATE_CONTINUE; + + stage_x11 = CLUTTER_STAGE_X11 (_clutter_stage_get_window (stage)); + + window_scale = stage_x11->scale_factor; + + event->any.stage = stage; + + res = CLUTTER_TRANSLATE_CONTINUE; + + switch (xevent->type) + { + case KeyPress: + translate_key_event (backend_x11, manager_x11, event, xevent); + _clutter_stage_x11_set_user_time (stage_x11, xevent->xkey.time); + res = CLUTTER_TRANSLATE_QUEUE; + break; + + case KeyRelease: + /* old-style X11 terminals require that even modern X11 send + * KeyPress/KeyRelease pairs when auto-repeating. for this + * reason modern(-ish) API like XKB has a way to detect + * auto-repeat and do a single KeyRelease at the end of a + * KeyPress sequence. + * + * this check emulates XKB's detectable auto-repeat; we peek + * the next event and check if it's a KeyPress for the same key + * and timestamp - and then ignore it if it matches the + * KeyRelease + * + * if we have XKB, and autorepeat is enabled, then this becomes + * a no-op + */ + if (!backend_x11->have_xkb_autorepeat && XPending (xevent->xkey.display)) + { + XEvent next_event; + + XPeekEvent (xevent->xkey.display, &next_event); + + if (next_event.type == KeyPress && + next_event.xkey.keycode == xevent->xkey.keycode && + next_event.xkey.time == xevent->xkey.time) + { + res = CLUTTER_TRANSLATE_REMOVE; + break; + } + } + + translate_key_event (backend_x11, manager_x11, event, xevent); + res = CLUTTER_TRANSLATE_QUEUE; + break; + + case ButtonPress: + CLUTTER_NOTE (EVENT, + "button press: win: 0x%x, coords: %d, %d, button: %d", + (unsigned int) stage_x11->xwin, + xevent->xbutton.x, + xevent->xbutton.y, + xevent->xbutton.button); + + switch (xevent->xbutton.button) + { + case 4: /* up */ + case 5: /* down */ + case 6: /* left */ + case 7: /* right */ + event->scroll.type = CLUTTER_SCROLL; + + if (xevent->xbutton.button == 4) + event->scroll.direction = CLUTTER_SCROLL_UP; + else if (xevent->xbutton.button == 5) + event->scroll.direction = CLUTTER_SCROLL_DOWN; + else if (xevent->xbutton.button == 6) + event->scroll.direction = CLUTTER_SCROLL_LEFT; + else + event->scroll.direction = CLUTTER_SCROLL_RIGHT; + + event->scroll.time = xevent->xbutton.time; + event->scroll.x = xevent->xbutton.x / window_scale; + event->scroll.y = xevent->xbutton.y / window_scale; + event->scroll.modifier_state = xevent->xbutton.state; + event->scroll.axes = NULL; + break; + + default: + event->button.type = event->type = CLUTTER_BUTTON_PRESS; + event->button.time = xevent->xbutton.time; + event->button.x = xevent->xbutton.x / window_scale; + event->button.y = xevent->xbutton.y / window_scale; + event->button.modifier_state = xevent->xbutton.state; + event->button.button = xevent->xbutton.button; + event->button.axes = NULL; + break; + } + + clutter_event_set_device (event, manager_x11->core_pointer); + + _clutter_stage_x11_set_user_time (stage_x11, xevent->xbutton.time); + res = CLUTTER_TRANSLATE_QUEUE; + break; + + case ButtonRelease: + CLUTTER_NOTE (EVENT, + "button press: win: 0x%x, coords: %d, %d, button: %d", + (unsigned int) stage_x11->xwin, + xevent->xbutton.x, + xevent->xbutton.y, + xevent->xbutton.button); + + /* scroll events don't have a corresponding release */ + if (xevent->xbutton.button == 4 || + xevent->xbutton.button == 5 || + xevent->xbutton.button == 6 || + xevent->xbutton.button == 7) + { + res = CLUTTER_TRANSLATE_REMOVE; + break; + } + + event->button.type = event->type = CLUTTER_BUTTON_RELEASE; + event->button.time = xevent->xbutton.time; + event->button.x = xevent->xbutton.x / window_scale; + event->button.y = xevent->xbutton.y / window_scale; + event->button.modifier_state = xevent->xbutton.state; + event->button.button = xevent->xbutton.button; + event->button.axes = NULL; + clutter_event_set_device (event, manager_x11->core_pointer); + res = CLUTTER_TRANSLATE_QUEUE; + break; + + case MotionNotify: + CLUTTER_NOTE (EVENT, + "motion: win: 0x%x, coords: %d, %d", + (unsigned int) stage_x11->xwin, + xevent->xmotion.x, + xevent->xmotion.y); + + event->motion.type = event->type = CLUTTER_MOTION; + event->motion.time = xevent->xmotion.time; + event->motion.x = xevent->xmotion.x / window_scale; + event->motion.y = xevent->xmotion.y / window_scale; + event->motion.modifier_state = xevent->xmotion.state; + event->motion.axes = NULL; + clutter_event_set_device (event, manager_x11->core_pointer); + res = CLUTTER_TRANSLATE_QUEUE; + break; + + case EnterNotify: + CLUTTER_NOTE (EVENT, "Entering the stage (time:%u)", + (unsigned int) xevent->xcrossing.time); + + event->crossing.type = CLUTTER_ENTER; + event->crossing.time = xevent->xcrossing.time; + event->crossing.x = xevent->xcrossing.x / window_scale; + event->crossing.y = xevent->xcrossing.y / window_scale; + event->crossing.source = CLUTTER_ACTOR (stage); + event->crossing.related = NULL; + clutter_event_set_device (event, manager_x11->core_pointer); + + _clutter_input_device_set_stage (manager_x11->core_pointer, stage); + + res = CLUTTER_TRANSLATE_QUEUE; + break; + + case LeaveNotify: + if (manager_x11->core_pointer->stage == NULL) + { + CLUTTER_NOTE (EVENT, "Discarding LeaveNotify for " + "ButtonRelease event off-stage"); + res = CLUTTER_TRANSLATE_REMOVE; + break; + } + + /* we know that we are leaving the stage here */ + CLUTTER_NOTE (EVENT, "Leaving the stage (time:%u)", + (unsigned int) xevent->xcrossing.time); + + event->crossing.type = CLUTTER_LEAVE; + event->crossing.time = xevent->xcrossing.time; + event->crossing.x = xevent->xcrossing.x / window_scale; + event->crossing.y = xevent->xcrossing.y / window_scale; + event->crossing.source = CLUTTER_ACTOR (stage); + event->crossing.related = NULL; + clutter_event_set_device (event, manager_x11->core_pointer); + + _clutter_input_device_set_stage (manager_x11->core_pointer, NULL); + + res = CLUTTER_TRANSLATE_QUEUE; + break; + + default: + break; + } + + return res; +} + +static void +clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface) +{ + iface->translate_event = clutter_device_manager_x11_translate_event; +} + +static void +clutter_device_manager_x11_constructed (GObject *gobject) +{ + ClutterDeviceManagerX11 *manager_x11; + ClutterBackendX11 *backend_x11; + + manager_x11 = CLUTTER_DEVICE_MANAGER_X11 (gobject); + + g_object_get (gobject, "backend", &backend_x11, NULL); + g_assert (backend_x11 != NULL); + + manager_x11->core_pointer = + g_object_new (CLUTTER_TYPE_INPUT_DEVICE_X11, + "name", "Core Pointer", + "has-cursor", TRUE, + "device-type", CLUTTER_POINTER_DEVICE, + "device-manager", manager_x11, + "device-mode", CLUTTER_INPUT_MODE_MASTER, + "backend", backend_x11, + "enabled", TRUE, + NULL); + CLUTTER_NOTE (BACKEND, "Added core pointer device"); + + manager_x11->core_keyboard = + g_object_new (CLUTTER_TYPE_INPUT_DEVICE_X11, + "name", "Core Keyboard", + "has-cursor", FALSE, + "device-type", CLUTTER_KEYBOARD_DEVICE, + "device-manager", manager_x11, + "device-mode", CLUTTER_INPUT_MODE_MASTER, + "backend", backend_x11, + "enabled", TRUE, + NULL); + CLUTTER_NOTE (BACKEND, "Added core keyboard device"); + + /* associate core devices */ + _clutter_input_device_set_associated_device (manager_x11->core_pointer, + manager_x11->core_keyboard); + _clutter_input_device_set_associated_device (manager_x11->core_keyboard, + manager_x11->core_pointer); + + if (G_OBJECT_CLASS (clutter_device_manager_x11_parent_class)->constructed) + G_OBJECT_CLASS (clutter_device_manager_x11_parent_class)->constructed (gobject); +} + +static void +clutter_device_manager_x11_add_device (ClutterDeviceManager *manager, + ClutterInputDevice *device) +{ + ClutterDeviceManagerX11 *manager_x11 = CLUTTER_DEVICE_MANAGER_X11 (manager); + + manager_x11->devices = g_slist_prepend (manager_x11->devices, device); + g_hash_table_replace (manager_x11->devices_by_id, + GINT_TO_POINTER (device->id), + device); + + /* blow the cache */ + g_slist_free (manager_x11->all_devices); + manager_x11->all_devices = NULL; +} + +static void +clutter_device_manager_x11_remove_device (ClutterDeviceManager *manager, + ClutterInputDevice *device) +{ + ClutterDeviceManagerX11 *manager_x11 = CLUTTER_DEVICE_MANAGER_X11 (manager); + + g_hash_table_remove (manager_x11->devices_by_id, + GINT_TO_POINTER (device->id)); + manager_x11->devices = g_slist_remove (manager_x11->devices, device); + + /* blow the cache */ + g_slist_free (manager_x11->all_devices); + manager_x11->all_devices = NULL; +} + +static const GSList * +clutter_device_manager_x11_get_devices (ClutterDeviceManager *manager) +{ + ClutterDeviceManagerX11 *manager_x11 = CLUTTER_DEVICE_MANAGER_X11 (manager); + + /* cache the devices list so that we can keep the core pointer + * and keyboard outside of the ManagerX11:devices list + */ + if (manager_x11->all_devices == NULL) + { + GSList *all_devices = manager_x11->devices; + + all_devices = g_slist_prepend (all_devices, manager_x11->core_keyboard); + all_devices = g_slist_prepend (all_devices, manager_x11->core_pointer); + + manager_x11->all_devices = all_devices; + } + + return CLUTTER_DEVICE_MANAGER_X11 (manager)->all_devices; +} + +static ClutterInputDevice * +clutter_device_manager_x11_get_core_device (ClutterDeviceManager *manager, + ClutterInputDeviceType type) +{ + ClutterDeviceManagerX11 *manager_x11; + + manager_x11 = CLUTTER_DEVICE_MANAGER_X11 (manager); + + switch (type) + { + case CLUTTER_POINTER_DEVICE: + return manager_x11->core_pointer; + + case CLUTTER_KEYBOARD_DEVICE: + return manager_x11->core_keyboard; + + default: + return NULL; + } + + return NULL; +} + +static ClutterInputDevice * +clutter_device_manager_x11_get_device (ClutterDeviceManager *manager, + gint id) +{ + ClutterDeviceManagerX11 *manager_x11 = CLUTTER_DEVICE_MANAGER_X11 (manager); + + return g_hash_table_lookup (manager_x11->devices_by_id, + GINT_TO_POINTER (id)); +} + +static ClutterVirtualInputDevice * +clutter_device_manager_x11_create_virtual_device (ClutterDeviceManager *device_manager, + ClutterInputDeviceType device_type) +{ + return g_object_new (CLUTTER_TYPE_VIRTUAL_INPUT_DEVICE_X11, NULL); +} + +static void +clutter_device_manager_x11_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterDeviceManagerX11 *manager_x11 = CLUTTER_DEVICE_MANAGER_X11 (gobject); + + switch (prop_id) + { + case PROP_EVENT_BASE: + manager_x11->xi_event_base = g_value_get_int (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_device_manager_x11_class_init (ClutterDeviceManagerX11Class *klass) +{ + ClutterDeviceManagerClass *manager_class; + GObjectClass *gobject_class; + + obj_props[PROP_EVENT_BASE] = + g_param_spec_int ("event-base", + "Event Base", + "The first XI event", + -1, G_MAXINT, + -1, + CLUTTER_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY); + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->constructed = clutter_device_manager_x11_constructed; + gobject_class->set_property = clutter_device_manager_x11_set_property; + + g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); + + manager_class = CLUTTER_DEVICE_MANAGER_CLASS (klass); + manager_class->add_device = clutter_device_manager_x11_add_device; + manager_class->remove_device = clutter_device_manager_x11_remove_device; + manager_class->get_devices = clutter_device_manager_x11_get_devices; + manager_class->get_core_device = clutter_device_manager_x11_get_core_device; + manager_class->get_device = clutter_device_manager_x11_get_device; + manager_class->create_virtual_device = clutter_device_manager_x11_create_virtual_device; +} + +static void +clutter_device_manager_x11_init (ClutterDeviceManagerX11 *self) +{ + self->devices_by_id = g_hash_table_new (NULL, NULL); +} diff --git a/clutter/clutter/x11/clutter-device-manager-core-x11.h b/clutter/clutter/x11/clutter-device-manager-core-x11.h new file mode 100644 index 0000000..f0f28bc --- /dev/null +++ b/clutter/clutter/x11/clutter-device-manager-core-x11.h @@ -0,0 +1,70 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright © 2009, 2010, 2011 Intel Corp. + * + * 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 . + * + * Author: Emmanuele Bassi + */ + +#ifndef __CLUTTER_DEVICE_MANAGER_X11_H__ +#define __CLUTTER_DEVICE_MANAGER_X11_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_DEVICE_MANAGER_X11 (_clutter_device_manager_x11_get_type ()) +#define CLUTTER_DEVICE_MANAGER_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_DEVICE_MANAGER_X11, ClutterDeviceManagerX11)) +#define CLUTTER_IS_DEVICE_MANAGER_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_DEVICE_MANAGER_X11)) +#define CLUTTER_DEVICE_MANAGER_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_DEVICE_MANAGER_X11, ClutterDeviceManagerX11Class)) +#define CLUTTER_IS_DEVICE_MANAGER_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_DEVICE_MANAGER_X11)) +#define CLUTTER_DEVICE_MANAGER_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_DEVICE_MANAGER_X11, ClutterDeviceManagerX11Class)) + +typedef struct _ClutterDeviceManagerX11 ClutterDeviceManagerX11; +typedef struct _ClutterDeviceManagerX11Class ClutterDeviceManagerX11Class; + +struct _ClutterDeviceManagerX11 +{ + ClutterDeviceManager parent_instance; + + GHashTable *devices_by_id; + + /* the list of transient devices */ + GSList *devices; + + /* the list of all devices, transient and core; this can be + * NULL-ified when adding or removing devices + */ + GSList *all_devices; + + ClutterInputDevice *core_pointer; + ClutterInputDevice *core_keyboard; + + int xi_event_base; +}; + +struct _ClutterDeviceManagerX11Class +{ + ClutterDeviceManagerClass parent_class; +}; + +GType _clutter_device_manager_x11_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* __CLUTTER_DEVICE_MANAGER_X11_H__ */ diff --git a/clutter/clutter/x11/clutter-device-manager-xi2.c b/clutter/clutter/x11/clutter-device-manager-xi2.c new file mode 100644 index 0000000..8c645cc --- /dev/null +++ b/clutter/clutter/x11/clutter-device-manager-xi2.c @@ -0,0 +1,1716 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright © 2011 Intel Corp. + * + * 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 . + * + * Author: Emmanuele Bassi + */ + +#include "clutter-build-config.h" + +#include + +#include "clutter-device-manager-xi2.h" + +#include "clutter-backend-x11.h" +#include "clutter-input-device-xi2.h" +#include "clutter-stage-x11.h" + +#include "clutter-backend.h" +#include "clutter-debug.h" +#include "clutter-device-manager-private.h" +#include "clutter-event-private.h" +#include "clutter-event-translator.h" +#include "clutter-stage-private.h" +#include "clutter-private.h" + +#include + +enum +{ + PROP_0, + + PROP_OPCODE, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST] = { NULL, }; + +static const char *clutter_input_axis_atom_names[] = { + "Abs X", /* CLUTTER_INPUT_AXIS_X */ + "Abs Y", /* CLUTTER_INPUT_AXIS_Y */ + "Abs Pressure", /* CLUTTER_INPUT_AXIS_PRESSURE */ + "Abs Tilt X", /* CLUTTER_INPUT_AXIS_XTILT */ + "Abs Tilt Y", /* CLUTTER_INPUT_AXIS_YTILT */ + "Abs Wheel", /* CLUTTER_INPUT_AXIS_WHEEL */ + "Abs Distance", /* CLUTTER_INPUT_AXIS_DISTANCE */ +}; + +#define N_AXIS_ATOMS G_N_ELEMENTS (clutter_input_axis_atom_names) + +static Atom clutter_input_axis_atoms[N_AXIS_ATOMS] = { 0, }; + +static void clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface); +static void clutter_event_extender_iface_init (ClutterEventExtenderInterface *iface); + +#define clutter_device_manager_xi2_get_type _clutter_device_manager_xi2_get_type + +G_DEFINE_TYPE_WITH_CODE (ClutterDeviceManagerXI2, + clutter_device_manager_xi2, + CLUTTER_TYPE_DEVICE_MANAGER, + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_EVENT_TRANSLATOR, + clutter_event_translator_iface_init) + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_EVENT_EXTENDER, + clutter_event_extender_iface_init)) + +static void +clutter_device_manager_x11_copy_event_data (ClutterEventExtender *event_extender, + const ClutterEvent *src, + ClutterEvent *dest) +{ + gpointer event_x11; + + event_x11 = _clutter_event_get_platform_data (src); + if (event_x11 != NULL) + _clutter_event_set_platform_data (dest, _clutter_event_x11_copy (event_x11)); +} + +static void +clutter_device_manager_x11_free_event_data (ClutterEventExtender *event_extender, + ClutterEvent *event) +{ + gpointer event_x11; + + event_x11 = _clutter_event_get_platform_data (event); + if (event_x11 != NULL) + _clutter_event_x11_free (event_x11); +} + +static void +clutter_event_extender_iface_init (ClutterEventExtenderInterface *iface) +{ + iface->copy_event_data = clutter_device_manager_x11_copy_event_data; + iface->free_event_data = clutter_device_manager_x11_free_event_data; +} + +static void +translate_valuator_class (Display *xdisplay, + ClutterInputDevice *device, + XIValuatorClassInfo *class) +{ + static gboolean atoms_initialized = FALSE; + ClutterInputAxis i, axis = CLUTTER_INPUT_AXIS_IGNORE; + + if (G_UNLIKELY (!atoms_initialized)) + { + XInternAtoms (xdisplay, + (char **) clutter_input_axis_atom_names, N_AXIS_ATOMS, + False, + clutter_input_axis_atoms); + + atoms_initialized = TRUE; + } + + for (i = 0; + i < N_AXIS_ATOMS; + i += 1) + { + if (clutter_input_axis_atoms[i] == class->label) + { + axis = i + 1; + break; + } + } + + _clutter_input_device_add_axis (device, axis, + class->min, + class->max, + class->resolution); + + CLUTTER_NOTE (BACKEND, + "Added axis '%s' (min:%.2f, max:%.2fd, res:%d) of device %d", + clutter_input_axis_atom_names[axis], + class->min, + class->max, + class->resolution, + device->id); +} + +static void +translate_device_classes (Display *xdisplay, + ClutterInputDevice *device, + XIAnyClassInfo **classes, + guint n_classes) +{ + gint i; + + for (i = 0; i < n_classes; i++) + { + XIAnyClassInfo *class_info = classes[i]; + + switch (class_info->type) + { + case XIKeyClass: + { + XIKeyClassInfo *key_info = (XIKeyClassInfo *) class_info; + gint j; + + _clutter_input_device_set_n_keys (device, + key_info->num_keycodes); + + for (j = 0; j < key_info->num_keycodes; j++) + { + clutter_input_device_set_key (device, j, + key_info->keycodes[i], + 0); + } + } + break; + + case XIValuatorClass: + translate_valuator_class (xdisplay, device, + (XIValuatorClassInfo *) class_info); + break; + +#ifdef HAVE_XINPUT_2_2 + case XIScrollClass: + { + XIScrollClassInfo *scroll_info = (XIScrollClassInfo *) class_info; + ClutterScrollDirection direction; + + if (scroll_info->scroll_type == XIScrollTypeVertical) + direction = CLUTTER_SCROLL_DOWN; + else + direction = CLUTTER_SCROLL_RIGHT; + + CLUTTER_NOTE (BACKEND, "Scroll valuator %d: %s, increment: %f", + scroll_info->number, + scroll_info->scroll_type == XIScrollTypeVertical + ? "vertical" + : "horizontal", + scroll_info->increment); + + _clutter_input_device_add_scroll_info (device, + scroll_info->number, + direction, + scroll_info->increment); + } + break; +#endif /* HAVE_XINPUT_2_2 */ + + default: + break; + } + } +} + +static gboolean +is_touch_device (XIAnyClassInfo **classes, + guint n_classes, + ClutterInputDeviceType *device_type, + guint *n_touch_points) +{ +#ifdef HAVE_XINPUT_2_2 + guint i; + + for (i = 0; i < n_classes; i++) + { + XITouchClassInfo *class = (XITouchClassInfo *) classes[i]; + + if (class->type != XITouchClass) + continue; + + if (class->num_touches > 0) + { + if (class->mode == XIDirectTouch) + *device_type = CLUTTER_TOUCHSCREEN_DEVICE; + else if (class->mode == XIDependentTouch) + *device_type = CLUTTER_TOUCHPAD_DEVICE; + else + continue; + + *n_touch_points = class->num_touches; + + return TRUE; + } + } +#endif + + return FALSE; +} + +static gboolean +is_touchpad_device (ClutterBackendX11 *backend_x11, + XIDeviceInfo *info) +{ + gulong nitems, bytes_after; + guint32 *data = NULL; + int rc, format; + Atom type; + Atom prop; + + prop = XInternAtom (backend_x11->xdpy, "libinput Tapping Enabled", True); + if (prop == None) + return FALSE; + + clutter_x11_trap_x_errors (); + rc = XIGetProperty (backend_x11->xdpy, + info->deviceid, + prop, + 0, 1, False, XA_INTEGER, &type, &format, &nitems, &bytes_after, + (guchar **) &data); + clutter_x11_untrap_x_errors (); + + /* We don't care about the data */ + XFree (data); + + if (rc != Success || type != XA_INTEGER || format != 8 || nitems != 1) + return FALSE; + + return TRUE; +} + +static gboolean +get_device_ids (ClutterBackendX11 *backend_x11, + XIDeviceInfo *info, + gchar **vendor_id, + gchar **product_id) +{ + gulong nitems, bytes_after; + guint32 *data = NULL; + int rc, format; + Atom type; + + clutter_x11_trap_x_errors (); + rc = XIGetProperty (backend_x11->xdpy, + info->deviceid, + XInternAtom (backend_x11->xdpy, "Device Product ID", False), + 0, 2, False, XA_INTEGER, &type, &format, &nitems, &bytes_after, + (guchar **) &data); + clutter_x11_untrap_x_errors (); + + if (rc != Success || type != XA_INTEGER || format != 32 || nitems != 2) + { + XFree (data); + return FALSE; + } + + if (vendor_id) + *vendor_id = g_strdup_printf ("%.4x", data[0]); + if (product_id) + *product_id = g_strdup_printf ("%.4x", data[1]); + + XFree (data); + + return TRUE; +} + +static gchar * +get_device_node_path (ClutterBackendX11 *backend_x11, + XIDeviceInfo *info) +{ + gulong nitems, bytes_after; + guchar *data; + int rc, format; + Atom prop, type; + gchar *node_path; + + prop = XInternAtom (backend_x11->xdpy, "Device Node", False); + if (prop == None) + return NULL; + + clutter_x11_trap_x_errors (); + + rc = XIGetProperty (backend_x11->xdpy, + info->deviceid, prop, 0, 1024, False, + XA_STRING, &type, &format, &nitems, &bytes_after, + (guchar **) &data); + + if (clutter_x11_untrap_x_errors ()) + return NULL; + + if (rc != Success || type != XA_STRING || format != 8) + { + XFree (data); + return FALSE; + } + + node_path = g_strdup ((char *) data); + XFree (data); + + return node_path; +} + +static ClutterInputDevice * +create_device (ClutterDeviceManagerXI2 *manager_xi2, + ClutterBackendX11 *backend_x11, + XIDeviceInfo *info) +{ + ClutterInputDeviceType source, touch_source; + ClutterInputDevice *retval; + ClutterInputMode mode; + gboolean is_enabled; + guint num_touches = 0; + gchar *vendor_id = NULL, *product_id = NULL, *node_path = NULL; + + if (info->use == XIMasterKeyboard || info->use == XISlaveKeyboard) + { + source = CLUTTER_KEYBOARD_DEVICE; + } + else if (is_touchpad_device (backend_x11, info)) + { + source = CLUTTER_TOUCHPAD_DEVICE; + } + else if (info->use == XISlavePointer && + is_touch_device (info->classes, info->num_classes, + &touch_source, + &num_touches)) + { + source = touch_source; + } + else + { + gchar *name; + + name = g_ascii_strdown (info->name, -1); + + if (strstr (name, "eraser") != NULL) + source = CLUTTER_ERASER_DEVICE; + else if (strstr (name, "cursor") != NULL) + source = CLUTTER_CURSOR_DEVICE; + else if (strstr (name, "wacom") != NULL || strstr (name, "pen") != NULL) + source = CLUTTER_PEN_DEVICE; + else if (strstr (name, "touchpad") != NULL) + source = CLUTTER_TOUCHPAD_DEVICE; + else + source = CLUTTER_POINTER_DEVICE; + + g_free (name); + } + + switch (info->use) + { + case XIMasterKeyboard: + case XIMasterPointer: + mode = CLUTTER_INPUT_MODE_MASTER; + is_enabled = TRUE; + break; + + case XISlaveKeyboard: + case XISlavePointer: + mode = CLUTTER_INPUT_MODE_SLAVE; + is_enabled = FALSE; + break; + + case XIFloatingSlave: + default: + mode = CLUTTER_INPUT_MODE_FLOATING; + is_enabled = FALSE; + break; + } + + if (info->use != XIMasterKeyboard && + info->use != XIMasterPointer) + { + get_device_ids (backend_x11, info, &vendor_id, &product_id); + node_path = get_device_node_path (backend_x11, info); + } + + retval = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_XI2, + "name", info->name, + "id", info->deviceid, + "has-cursor", (info->use == XIMasterPointer), + "device-manager", manager_xi2, + "device-type", source, + "device-mode", mode, + "backend", backend_x11, + "enabled", is_enabled, + "vendor-id", vendor_id, + "product-id", product_id, + "device-node", node_path, + NULL); + + translate_device_classes (backend_x11->xdpy, retval, + info->classes, + info->num_classes); + g_free (vendor_id); + g_free (product_id); + + CLUTTER_NOTE (BACKEND, "Created device '%s' (id: %d, has-cursor: %s)", + info->name, + info->deviceid, + info->use == XIMasterPointer ? "yes" : "no"); + + return retval; +} + +static ClutterInputDevice * +add_device (ClutterDeviceManagerXI2 *manager_xi2, + ClutterBackendX11 *backend_x11, + XIDeviceInfo *info, + gboolean in_construction) +{ + ClutterInputDevice *device; + + device = create_device (manager_xi2, backend_x11, info); + + /* we don't go through the DeviceManager::add_device() vfunc because + * that emits the signal, and we only do it conditionally + */ + g_hash_table_replace (manager_xi2->devices_by_id, + GINT_TO_POINTER (info->deviceid), + device); + + if (info->use == XIMasterPointer || + info->use == XIMasterKeyboard) + { + manager_xi2->master_devices = + g_list_prepend (manager_xi2->master_devices, device); + } + else if (info->use == XISlavePointer || + info->use == XISlaveKeyboard || + info->use == XIFloatingSlave) + { + manager_xi2->slave_devices = + g_list_prepend (manager_xi2->slave_devices, device); + } + else + g_warning ("Unhandled device: %s", + clutter_input_device_get_device_name (device)); + + /* relationships between devices and signal emissions are not + * necessary while we're constructing the device manager instance + */ + if (!in_construction) + { + if (info->use == XISlavePointer || info->use == XISlaveKeyboard) + { + ClutterInputDevice *master; + + master = g_hash_table_lookup (manager_xi2->devices_by_id, + GINT_TO_POINTER (info->attachment)); + _clutter_input_device_set_associated_device (device, master); + _clutter_input_device_add_slave (master, device); + } + + /* blow the cache */ + g_slist_free (manager_xi2->all_devices); + manager_xi2->all_devices = NULL; + + g_signal_emit_by_name (manager_xi2, "device-added", device); + } + + return device; +} + +static void +remove_device (ClutterDeviceManagerXI2 *manager_xi2, + gint device_id) +{ + ClutterInputDevice *device; + + device = g_hash_table_lookup (manager_xi2->devices_by_id, + GINT_TO_POINTER (device_id)); + + if (device != NULL) + { + manager_xi2->master_devices = + g_list_remove (manager_xi2->master_devices, device); + manager_xi2->slave_devices = + g_list_remove (manager_xi2->slave_devices, device); + + /* blow the cache */ + g_slist_free (manager_xi2->all_devices); + manager_xi2->all_devices = NULL; + + g_signal_emit_by_name (manager_xi2, "device-removed", device); + + g_object_run_dispose (G_OBJECT (device)); + + g_hash_table_remove (manager_xi2->devices_by_id, + GINT_TO_POINTER (device_id)); + } +} + +static void +translate_hierarchy_event (ClutterBackendX11 *backend_x11, + ClutterDeviceManagerXI2 *manager_xi2, + XIHierarchyEvent *ev) +{ + int i; + + for (i = 0; i < ev->num_info; i++) + { + if (ev->info[i].flags & XIDeviceEnabled && + !g_hash_table_lookup (manager_xi2->devices_by_id, + GINT_TO_POINTER (ev->info[i].deviceid))) + { + XIDeviceInfo *info; + int n_devices; + + CLUTTER_NOTE (EVENT, "Hierarchy event: device enabled"); + + clutter_x11_trap_x_errors (); + info = XIQueryDevice (backend_x11->xdpy, + ev->info[i].deviceid, + &n_devices); + clutter_x11_untrap_x_errors (); + if (info != NULL) + { + add_device (manager_xi2, backend_x11, &info[0], FALSE); + XIFreeDeviceInfo (info); + } + } + else if (ev->info[i].flags & XIDeviceDisabled) + { + CLUTTER_NOTE (EVENT, "Hierarchy event: device disabled"); + + remove_device (manager_xi2, ev->info[i].deviceid); + } + else if ((ev->info[i].flags & XISlaveAttached) || + (ev->info[i].flags & XISlaveDetached)) + { + ClutterInputDevice *master, *slave; + XIDeviceInfo *info; + int n_devices; + gboolean send_changed = FALSE; + + CLUTTER_NOTE (EVENT, "Hierarchy event: slave %s", + (ev->info[i].flags & XISlaveAttached) + ? "attached" + : "detached"); + + slave = g_hash_table_lookup (manager_xi2->devices_by_id, + GINT_TO_POINTER (ev->info[i].deviceid)); + master = clutter_input_device_get_associated_device (slave); + + /* detach the slave in both cases */ + if (master != NULL) + { + _clutter_input_device_remove_slave (master, slave); + _clutter_input_device_set_associated_device (slave, NULL); + + send_changed = TRUE; + } + + /* and attach the slave to the new master if needed */ + if (ev->info[i].flags & XISlaveAttached) + { + clutter_x11_trap_x_errors (); + info = XIQueryDevice (backend_x11->xdpy, + ev->info[i].deviceid, + &n_devices); + clutter_x11_untrap_x_errors (); + if (info != NULL) + { + master = g_hash_table_lookup (manager_xi2->devices_by_id, + GINT_TO_POINTER (info->attachment)); + if (master != NULL) + { + _clutter_input_device_set_associated_device (slave, master); + _clutter_input_device_add_slave (master, slave); + + send_changed = TRUE; + } + XIFreeDeviceInfo (info); + } + } + + if (send_changed) + { + ClutterStage *stage = _clutter_input_device_get_stage (master); + if (stage != NULL) + _clutter_stage_x11_events_device_changed (CLUTTER_STAGE_X11 (_clutter_stage_get_window (stage)), + master, + CLUTTER_DEVICE_MANAGER (manager_xi2)); + } + } + } +} + +static void +clutter_device_manager_xi2_select_events (ClutterDeviceManager *manager, + Window xwindow, + XIEventMask *event_mask) +{ + Display *xdisplay; + + xdisplay = clutter_x11_get_default_display (); + + XISelectEvents (xdisplay, xwindow, event_mask, 1); +} + +static ClutterStage * +get_event_stage (ClutterEventTranslator *translator, + XIEvent *xi_event) +{ + Window xwindow = None; + + switch (xi_event->evtype) + { + case XI_KeyPress: + case XI_KeyRelease: + case XI_ButtonPress: + case XI_ButtonRelease: + case XI_Motion: +#ifdef HAVE_XINPUT_2_2 + case XI_TouchBegin: + case XI_TouchUpdate: + case XI_TouchEnd: +#endif /* HAVE_XINPUT_2_2 */ + { + XIDeviceEvent *xev = (XIDeviceEvent *) xi_event; + + xwindow = xev->event; + } + break; + + case XI_Enter: + case XI_Leave: + case XI_FocusIn: + case XI_FocusOut: + { + XIEnterEvent *xev = (XIEnterEvent *) xi_event; + + xwindow = xev->event; + } + break; + + default: + break; + } + + if (xwindow == None) + return NULL; + + return clutter_x11_get_stage_from_window (xwindow); +} + +/* + * print_key_sym: Translate a symbol to its printable form if any + * @symbol: the symbol to translate + * @buffer: the buffer where to put the translated string + * @len: size of the buffer + * + * Translates @symbol into a printable representation in @buffer, if possible. + * + * Return value: The number of bytes of the translated string, 0 if the + * symbol can't be printed + * + * Note: The code is derived from libX11's src/KeyBind.c + * Copyright 1985, 1987, 1998 The Open Group + * + * Note: This code works for Latin-1 symbols. clutter_keysym_to_unicode() + * does the work for the other keysyms. + */ +static int +print_keysym (uint32_t symbol, + char *buffer, + int len) +{ + unsigned long high_bytes; + unsigned char c; + + high_bytes = symbol >> 8; + if (!(len && + ((high_bytes == 0) || + ((high_bytes == 0xFF) && + (((symbol >= CLUTTER_KEY_BackSpace) && + (symbol <= CLUTTER_KEY_Clear)) || + (symbol == CLUTTER_KEY_Return) || + (symbol == CLUTTER_KEY_Escape) || + (symbol == CLUTTER_KEY_KP_Space) || + (symbol == CLUTTER_KEY_KP_Tab) || + (symbol == CLUTTER_KEY_KP_Enter) || + ((symbol >= CLUTTER_KEY_KP_Multiply) && + (symbol <= CLUTTER_KEY_KP_9)) || + (symbol == CLUTTER_KEY_KP_Equal) || + (symbol == CLUTTER_KEY_Delete)))))) + return 0; + + /* if X keysym, convert to ascii by grabbing low 7 bits */ + if (symbol == CLUTTER_KEY_KP_Space) + c = CLUTTER_KEY_space & 0x7F; /* patch encoding botch */ + else if (high_bytes == 0xFF) + c = symbol & 0x7F; + else + c = symbol & 0xFF; + + buffer[0] = c; + return 1; +} + +static gdouble * +translate_axes (ClutterInputDevice *device, + gdouble x, + gdouble y, + XIValuatorState *valuators) +{ + guint n_axes = clutter_input_device_get_n_axes (device); + guint i; + gdouble *retval; + double *values; + + retval = g_new0 (gdouble, n_axes); + values = valuators->values; + + for (i = 0; i < valuators->mask_len * 8; i++) + { + ClutterInputAxis axis; + gdouble val; + + if (!XIMaskIsSet (valuators->mask, i)) + continue; + + axis = clutter_input_device_get_axis (device, i); + val = *values++; + + switch (axis) + { + case CLUTTER_INPUT_AXIS_X: + retval[i] = x; + break; + + case CLUTTER_INPUT_AXIS_Y: + retval[i] = y; + break; + + default: + _clutter_input_device_translate_axis (device, i, val, &retval[i]); + break; + } + } + + return retval; +} + +static void +translate_coords (ClutterStageX11 *stage_x11, + gdouble event_x, + gdouble event_y, + gfloat *x_out, + gfloat *y_out) +{ + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + ClutterActor *stage = CLUTTER_ACTOR (stage_cogl->wrapper); + gfloat stage_width; + gfloat stage_height; + + clutter_actor_get_size (stage, &stage_width, &stage_height); + + *x_out = CLAMP (event_x / stage_x11->scale_factor, 0, stage_width); + *y_out = CLAMP (event_y / stage_x11->scale_factor, 0, stage_height); +} + +static gdouble +scroll_valuators_changed (ClutterInputDevice *device, + XIValuatorState *valuators, + gdouble *dx_p, + gdouble *dy_p) +{ + gboolean retval = FALSE; + guint n_axes, n_val, i; + double *values; + + n_axes = clutter_input_device_get_n_axes (device); + values = valuators->values; + + *dx_p = *dy_p = 0.0; + + n_val = 0; + + for (i = 0; i < MIN (valuators->mask_len * 8, n_axes); i++) + { + ClutterScrollDirection direction; + gdouble delta; + + if (!XIMaskIsSet (valuators->mask, i)) + continue; + + if (_clutter_input_device_get_scroll_delta (device, i, + values[n_val], + &direction, + &delta)) + { + retval = TRUE; + + if (direction == CLUTTER_SCROLL_UP || + direction == CLUTTER_SCROLL_DOWN) + *dy_p = delta; + else + *dx_p = delta; + } + + n_val += 1; + } + + return retval; +} + +static void +clutter_device_manager_xi2_select_stage_events (ClutterDeviceManager *manager, + ClutterStage *stage) +{ + ClutterBackendX11 *backend_x11; + ClutterStageX11 *stage_x11; + XIEventMask xi_event_mask; + unsigned char *mask; + int len; + + backend_x11 = CLUTTER_BACKEND_X11 (clutter_get_default_backend ()); + stage_x11 = CLUTTER_STAGE_X11 (_clutter_stage_get_window (stage)); + + len = XIMaskLen (XI_LASTEVENT); + mask = g_new0 (unsigned char, len); + + XISetMask (mask, XI_Motion); + XISetMask (mask, XI_ButtonPress); + XISetMask (mask, XI_ButtonRelease); + XISetMask (mask, XI_KeyPress); + XISetMask (mask, XI_KeyRelease); + XISetMask (mask, XI_Enter); + XISetMask (mask, XI_Leave); + +#ifdef HAVE_XINPUT_2_2 + /* enable touch event support if we're running on XInput 2.2 */ + if (backend_x11->xi_minor >= 2) + { + XISetMask (mask, XI_TouchBegin); + XISetMask (mask, XI_TouchUpdate); + XISetMask (mask, XI_TouchEnd); + } +#endif /* HAVE_XINPUT_2_2 */ + + xi_event_mask.deviceid = XIAllMasterDevices; + xi_event_mask.mask = mask; + xi_event_mask.mask_len = len; + + XISelectEvents (backend_x11->xdpy, stage_x11->xwin, &xi_event_mask, 1); + + g_free (mask); +} + +static ClutterTranslateReturn +clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator, + gpointer native, + ClutterEvent *event) +{ + ClutterDeviceManagerXI2 *manager_xi2 = CLUTTER_DEVICE_MANAGER_XI2 (translator); + ClutterTranslateReturn retval = CLUTTER_TRANSLATE_CONTINUE; + ClutterBackendX11 *backend_x11; + ClutterStageX11 *stage_x11 = NULL; + ClutterStage *stage = NULL; + ClutterInputDevice *device, *source_device; + XGenericEventCookie *cookie; + XIEvent *xi_event; + XEvent *xevent; + + backend_x11 = CLUTTER_BACKEND_X11 (clutter_get_default_backend ()); + + xevent = native; + + cookie = &xevent->xcookie; + + if (cookie->type != GenericEvent || + cookie->extension != manager_xi2->opcode) + return CLUTTER_TRANSLATE_CONTINUE; + + xi_event = (XIEvent *) cookie->data; + + if (!xi_event) + return CLUTTER_TRANSLATE_REMOVE; + + if (!(xi_event->evtype == XI_HierarchyChanged || + xi_event->evtype == XI_DeviceChanged)) + { + stage = get_event_stage (translator, xi_event); + if (stage == NULL || CLUTTER_ACTOR_IN_DESTRUCTION (stage)) + return CLUTTER_TRANSLATE_CONTINUE; + else + stage_x11 = CLUTTER_STAGE_X11 (_clutter_stage_get_window (stage)); + } + + event->any.stage = stage; + + switch (xi_event->evtype) + { + case XI_HierarchyChanged: + { + XIHierarchyEvent *xev = (XIHierarchyEvent *) xi_event; + + translate_hierarchy_event (backend_x11, manager_xi2, xev); + } + retval = CLUTTER_TRANSLATE_REMOVE; + break; + + case XI_DeviceChanged: + { + XIDeviceChangedEvent *xev = (XIDeviceChangedEvent *) xi_event; + + device = g_hash_table_lookup (manager_xi2->devices_by_id, + GINT_TO_POINTER (xev->deviceid)); + source_device = g_hash_table_lookup (manager_xi2->devices_by_id, + GINT_TO_POINTER (xev->sourceid)); + if (device) + { + _clutter_input_device_reset_axes (device); + translate_device_classes (backend_x11->xdpy, + device, + xev->classes, + xev->num_classes); + } + + if (source_device) + _clutter_input_device_reset_scroll_info (source_device); + } + retval = CLUTTER_TRANSLATE_REMOVE; + break; + + case XI_KeyPress: + case XI_KeyRelease: + { + XIDeviceEvent *xev = (XIDeviceEvent *) xi_event; + ClutterEventX11 *event_x11; + char buffer[7] = { 0, }; + gunichar n; + + event->key.type = event->type = (xev->evtype == XI_KeyPress) + ? CLUTTER_KEY_PRESS + : CLUTTER_KEY_RELEASE; + + event->key.time = xev->time; + event->key.stage = stage; + _clutter_input_device_xi2_translate_state (event, &xev->mods, &xev->buttons, &xev->group); + event->key.hardware_keycode = xev->detail; + + /* keyval is the key ignoring all modifiers ('1' vs. '!') */ + event->key.keyval = + _clutter_keymap_x11_translate_key_state (backend_x11->keymap, + event->key.hardware_keycode, + &event->key.modifier_state, + NULL); + + /* KeyEvents have platform specific data associated to them */ + event_x11 = _clutter_event_x11_new (); + _clutter_event_set_platform_data (event, event_x11); + + event_x11->key_group = + _clutter_keymap_x11_get_key_group (backend_x11->keymap, + event->key.modifier_state); + event_x11->key_is_modifier = + _clutter_keymap_x11_get_is_modifier (backend_x11->keymap, + event->key.hardware_keycode); + event_x11->num_lock_set = + _clutter_keymap_x11_get_num_lock_state (backend_x11->keymap); + event_x11->caps_lock_set = + _clutter_keymap_x11_get_caps_lock_state (backend_x11->keymap); + + source_device = g_hash_table_lookup (manager_xi2->devices_by_id, + GINT_TO_POINTER (xev->sourceid)); + clutter_event_set_source_device (event, source_device); + + device = g_hash_table_lookup (manager_xi2->devices_by_id, + GINT_TO_POINTER (xev->deviceid)); + clutter_event_set_device (event, device); + + /* XXX keep this in sync with the evdev device manager */ + n = print_keysym (event->key.keyval, buffer, sizeof (buffer)); + if (n == 0) + { + /* not printable */ + event->key.unicode_value = (gunichar) '\0'; + } + else + { + event->key.unicode_value = g_utf8_get_char_validated (buffer, n); + if (event->key.unicode_value == -1 || + event->key.unicode_value == -2) + event->key.unicode_value = (gunichar) '\0'; + } + + CLUTTER_NOTE (EVENT, + "%s: win:0x%x device:%d source:%d, key: %12s (%d)", + event->any.type == CLUTTER_KEY_PRESS + ? "key press " + : "key release", + (unsigned int) stage_x11->xwin, + xev->deviceid, + xev->sourceid, + event->key.keyval ? buffer : "(none)", + event->key.keyval); + + if (xi_event->evtype == XI_KeyPress) + _clutter_stage_x11_set_user_time (stage_x11, event->key.time); + + retval = CLUTTER_TRANSLATE_QUEUE; + } + break; + + case XI_ButtonPress: + case XI_ButtonRelease: + { + XIDeviceEvent *xev = (XIDeviceEvent *) xi_event; + + source_device = g_hash_table_lookup (manager_xi2->devices_by_id, + GINT_TO_POINTER (xev->sourceid)); + device = g_hash_table_lookup (manager_xi2->devices_by_id, + GINT_TO_POINTER (xev->deviceid)); + + /* Set the stage for core events coming out of nowhere (see bug #684509) */ + if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER && + clutter_input_device_get_pointer_stage (device) == NULL && + stage != NULL) + _clutter_input_device_set_stage (device, stage); + + switch (xev->detail) + { + case 4: + case 5: + case 6: + case 7: + /* we only generate Scroll events on ButtonPress */ + if (xi_event->evtype == XI_ButtonRelease) + return CLUTTER_TRANSLATE_REMOVE; + + event->scroll.type = event->type = CLUTTER_SCROLL; + + if (xev->detail == 4) + event->scroll.direction = CLUTTER_SCROLL_UP; + else if (xev->detail == 5) + event->scroll.direction = CLUTTER_SCROLL_DOWN; + else if (xev->detail == 6) + event->scroll.direction = CLUTTER_SCROLL_LEFT; + else + event->scroll.direction = CLUTTER_SCROLL_RIGHT; + + event->scroll.stage = stage; + + event->scroll.time = xev->time; + translate_coords (stage_x11, xev->event_x, xev->event_y, &event->scroll.x, &event->scroll.y); + _clutter_input_device_xi2_translate_state (event, + &xev->mods, + &xev->buttons, + &xev->group); + + clutter_event_set_source_device (event, source_device); + clutter_event_set_device (event, device); + + event->scroll.axes = translate_axes (event->scroll.device, + event->scroll.x, + event->scroll.y, + &xev->valuators); + + CLUTTER_NOTE (EVENT, + "scroll: win:0x%x, device:%d '%s', time:%d " + "(direction:%s, " + "x:%.2f, y:%.2f, " + "emulated:%s)", + (unsigned int) stage_x11->xwin, + device->id, + device->device_name, + event->any.time, + event->scroll.direction == CLUTTER_SCROLL_UP ? "up" : + event->scroll.direction == CLUTTER_SCROLL_DOWN ? "down" : + event->scroll.direction == CLUTTER_SCROLL_LEFT ? "left" : + event->scroll.direction == CLUTTER_SCROLL_RIGHT ? "right" : + "invalid", + event->scroll.x, + event->scroll.y, +#ifdef HAVE_XINPUT_2_2 + (xev->flags & XIPointerEmulated) ? "yes" : "no" +#else + "no" +#endif + ); + break; + + default: + event->button.type = event->type = + (xi_event->evtype == XI_ButtonPress) ? CLUTTER_BUTTON_PRESS + : CLUTTER_BUTTON_RELEASE; + + event->button.stage = stage; + + event->button.time = xev->time; + translate_coords (stage_x11, xev->event_x, xev->event_y, &event->button.x, &event->button.y); + event->button.button = xev->detail; + _clutter_input_device_xi2_translate_state (event, + &xev->mods, + &xev->buttons, + &xev->group); + + clutter_event_set_source_device (event, source_device); + clutter_event_set_device (event, device); + + event->button.axes = translate_axes (event->button.device, + event->button.x, + event->button.y, + &xev->valuators); + + CLUTTER_NOTE (EVENT, + "%s: win:0x%x, device:%d '%s', time:%d " + "(button:%d, " + "x:%.2f, y:%.2f, " + "axes:%s, " + "emulated:%s)", + event->any.type == CLUTTER_BUTTON_PRESS + ? "button press " + : "button release", + (unsigned int) stage_x11->xwin, + device->id, + device->device_name, + event->any.time, + event->button.button, + event->button.x, + event->button.y, + event->button.axes != NULL ? "yes" : "no", +#ifdef HAVE_XINPUT_2_2 + (xev->flags & XIPointerEmulated) ? "yes" : "no" +#else + "no" +#endif + ); + break; + } + + if (source_device != NULL && device->stage != NULL) + _clutter_input_device_set_stage (source_device, device->stage); + +#ifdef HAVE_XINPUT_2_2 + if (xev->flags & XIPointerEmulated) + _clutter_event_set_pointer_emulated (event, TRUE); +#endif /* HAVE_XINPUT_2_2 */ + + if (xi_event->evtype == XI_ButtonPress) + _clutter_stage_x11_set_user_time (stage_x11, event->button.time); + + retval = CLUTTER_TRANSLATE_QUEUE; + } + break; + + case XI_Motion: + { + XIDeviceEvent *xev = (XIDeviceEvent *) xi_event; + gdouble delta_x, delta_y; + + source_device = g_hash_table_lookup (manager_xi2->devices_by_id, + GINT_TO_POINTER (xev->sourceid)); + device = g_hash_table_lookup (manager_xi2->devices_by_id, + GINT_TO_POINTER (xev->deviceid)); + + /* Set the stage for core events coming out of nowhere (see bug #684509) */ + if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER && + clutter_input_device_get_pointer_stage (device) == NULL && + stage != NULL) + _clutter_input_device_set_stage (device, stage); + + if (scroll_valuators_changed (source_device, + &xev->valuators, + &delta_x, &delta_y)) + { + event->scroll.type = event->type = CLUTTER_SCROLL; + event->scroll.direction = CLUTTER_SCROLL_SMOOTH; + + event->scroll.stage = stage; + event->scroll.time = xev->time; + translate_coords (stage_x11, xev->event_x, xev->event_y, &event->scroll.x, &event->scroll.y); + _clutter_input_device_xi2_translate_state (event, + &xev->mods, + &xev->buttons, + &xev->group); + + clutter_event_set_scroll_delta (event, delta_x, delta_y); + clutter_event_set_source_device (event, source_device); + clutter_event_set_device (event, device); + + CLUTTER_NOTE (EVENT, + "smooth scroll: win:0x%x device:%d '%s' (x:%.2f, y:%.2f, delta:%f, %f)", + (unsigned int) stage_x11->xwin, + event->scroll.device->id, + event->scroll.device->device_name, + event->scroll.x, + event->scroll.y, + delta_x, delta_y); + + retval = CLUTTER_TRANSLATE_QUEUE; + break; + } + + event->motion.type = event->type = CLUTTER_MOTION; + + event->motion.stage = stage; + + event->motion.time = xev->time; + translate_coords (stage_x11, xev->event_x, xev->event_y, &event->motion.x, &event->motion.y); + _clutter_input_device_xi2_translate_state (event, + &xev->mods, + &xev->buttons, + &xev->group); + + clutter_event_set_source_device (event, source_device); + clutter_event_set_device (event, device); + + event->motion.axes = translate_axes (event->motion.device, + event->motion.x, + event->motion.y, + &xev->valuators); + + if (source_device != NULL && device->stage != NULL) + _clutter_input_device_set_stage (source_device, device->stage); + +#ifdef HAVE_XINPUT_2_2 + if (xev->flags & XIPointerEmulated) + _clutter_event_set_pointer_emulated (event, TRUE); +#endif /* HAVE_XINPUT_2_2 */ + + CLUTTER_NOTE (EVENT, "motion: win:0x%x device:%d '%s' (x:%.2f, y:%.2f, axes:%s)", + (unsigned int) stage_x11->xwin, + event->motion.device->id, + event->motion.device->device_name, + event->motion.x, + event->motion.y, + event->motion.axes != NULL ? "yes" : "no"); + + retval = CLUTTER_TRANSLATE_QUEUE; + } + break; + +#ifdef HAVE_XINPUT_2_2 + case XI_TouchBegin: + { + XIDeviceEvent *xev = (XIDeviceEvent *) xi_event; + device = g_hash_table_lookup (manager_xi2->devices_by_id, + GINT_TO_POINTER (xev->deviceid)); + if (!_clutter_input_device_get_stage (device)) + _clutter_input_device_set_stage (device, stage); + } + /* Fall through */ + case XI_TouchEnd: + { + XIDeviceEvent *xev = (XIDeviceEvent *) xi_event; + + source_device = g_hash_table_lookup (manager_xi2->devices_by_id, + GINT_TO_POINTER (xev->sourceid)); + + if (xi_event->evtype == XI_TouchBegin) + event->touch.type = event->type = CLUTTER_TOUCH_BEGIN; + else + event->touch.type = event->type = CLUTTER_TOUCH_END; + + event->touch.stage = stage; + event->touch.time = xev->time; + translate_coords (stage_x11, xev->event_x, xev->event_y, &event->touch.x, &event->touch.y); + _clutter_input_device_xi2_translate_state (event, + &xev->mods, + &xev->buttons, + &xev->group); + + clutter_event_set_source_device (event, source_device); + + device = g_hash_table_lookup (manager_xi2->devices_by_id, + GINT_TO_POINTER (xev->deviceid)); + clutter_event_set_device (event, device); + + event->touch.axes = translate_axes (event->touch.device, + event->motion.x, + event->motion.y, + &xev->valuators); + + if (xi_event->evtype == XI_TouchBegin) + { + event->touch.modifier_state |= CLUTTER_BUTTON1_MASK; + + _clutter_stage_x11_set_user_time (stage_x11, event->touch.time); + } + + event->touch.sequence = GUINT_TO_POINTER (xev->detail); + + if (xev->flags & XITouchEmulatingPointer) + _clutter_event_set_pointer_emulated (event, TRUE); + + CLUTTER_NOTE (EVENT, "touch %s: win:0x%x device:%d '%s' (seq:%d, x:%.2f, y:%.2f, axes:%s)", + event->type == CLUTTER_TOUCH_BEGIN ? "begin" : "end", + (unsigned int) stage_x11->xwin, + event->touch.device->id, + event->touch.device->device_name, + GPOINTER_TO_UINT (event->touch.sequence), + event->touch.x, + event->touch.y, + event->touch.axes != NULL ? "yes" : "no"); + + retval = CLUTTER_TRANSLATE_QUEUE; + } + break; + + case XI_TouchUpdate: + { + XIDeviceEvent *xev = (XIDeviceEvent *) xi_event; + + source_device = g_hash_table_lookup (manager_xi2->devices_by_id, + GINT_TO_POINTER (xev->sourceid)); + + event->touch.type = event->type = CLUTTER_TOUCH_UPDATE; + event->touch.stage = stage; + event->touch.time = xev->time; + event->touch.sequence = GUINT_TO_POINTER (xev->detail); + translate_coords (stage_x11, xev->event_x, xev->event_y, &event->touch.x, &event->touch.y); + + clutter_event_set_source_device (event, source_device); + + device = g_hash_table_lookup (manager_xi2->devices_by_id, + GINT_TO_POINTER (xev->deviceid)); + clutter_event_set_device (event, device); + + event->touch.axes = translate_axes (event->touch.device, + event->motion.x, + event->motion.y, + &xev->valuators); + + _clutter_input_device_xi2_translate_state (event, + &xev->mods, + &xev->buttons, + &xev->group); + event->touch.modifier_state |= CLUTTER_BUTTON1_MASK; + + if (xev->flags & XITouchEmulatingPointer) + _clutter_event_set_pointer_emulated (event, TRUE); + + CLUTTER_NOTE (EVENT, "touch update: win:0x%x device:%d '%s' (seq:%d, x:%.2f, y:%.2f, axes:%s)", + (unsigned int) stage_x11->xwin, + event->touch.device->id, + event->touch.device->device_name, + GPOINTER_TO_UINT (event->touch.sequence), + event->touch.x, + event->touch.y, + event->touch.axes != NULL ? "yes" : "no"); + + retval = CLUTTER_TRANSLATE_QUEUE; + } + break; +#endif /* HAVE_XINPUT_2_2 */ + + case XI_Enter: + case XI_Leave: + { + XIEnterEvent *xev = (XIEnterEvent *) xi_event; + + device = g_hash_table_lookup (manager_xi2->devices_by_id, + GINT_TO_POINTER (xev->deviceid)); + + source_device = g_hash_table_lookup (manager_xi2->devices_by_id, + GINT_TO_POINTER (xev->sourceid)); + + if (xi_event->evtype == XI_Enter) + { + event->crossing.type = event->type = CLUTTER_ENTER; + + event->crossing.stage = stage; + event->crossing.source = CLUTTER_ACTOR (stage); + event->crossing.related = NULL; + + event->crossing.time = xev->time; + translate_coords (stage_x11, xev->event_x, xev->event_y, &event->crossing.x, &event->crossing.y); + + _clutter_input_device_set_stage (device, stage); + } + else + { + if (device->stage == NULL) + { + CLUTTER_NOTE (EVENT, + "Discarding Leave for ButtonRelease " + "event off-stage"); + + retval = CLUTTER_TRANSLATE_REMOVE; + break; + } + + event->crossing.type = event->type = CLUTTER_LEAVE; + + event->crossing.stage = stage; + event->crossing.source = CLUTTER_ACTOR (stage); + event->crossing.related = NULL; + + event->crossing.time = xev->time; + translate_coords (stage_x11, xev->event_x, xev->event_y, &event->crossing.x, &event->crossing.y); + + _clutter_input_device_set_stage (device, NULL); + } + + _clutter_input_device_reset_scroll_info (source_device); + + clutter_event_set_device (event, device); + clutter_event_set_source_device (event, source_device); + + retval = CLUTTER_TRANSLATE_QUEUE; + } + break; + + case XI_FocusIn: + case XI_FocusOut: + retval = CLUTTER_TRANSLATE_CONTINUE; + break; + } + + return retval; +} + +static void +clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface) +{ + iface->translate_event = clutter_device_manager_xi2_translate_event; +} + +static void +clutter_device_manager_xi2_add_device (ClutterDeviceManager *manager, + ClutterInputDevice *device) +{ + /* XXX implement */ +} + +static void +clutter_device_manager_xi2_remove_device (ClutterDeviceManager *manager, + ClutterInputDevice *device) +{ + /* XXX implement */ +} + +static const GSList * +clutter_device_manager_xi2_get_devices (ClutterDeviceManager *manager) +{ + ClutterDeviceManagerXI2 *manager_xi2 = CLUTTER_DEVICE_MANAGER_XI2 (manager); + GSList *all_devices = NULL; + GList *l; + + if (manager_xi2->all_devices != NULL) + return manager_xi2->all_devices; + + for (l = manager_xi2->master_devices; l != NULL; l = l->next) + all_devices = g_slist_prepend (all_devices, l->data); + + for (l = manager_xi2->slave_devices; l != NULL; l = l->next) + all_devices = g_slist_prepend (all_devices, l->data); + + manager_xi2->all_devices = g_slist_reverse (all_devices); + + return manager_xi2->all_devices; +} + +static ClutterInputDevice * +clutter_device_manager_xi2_get_device (ClutterDeviceManager *manager, + gint id) +{ + ClutterDeviceManagerXI2 *manager_xi2 = CLUTTER_DEVICE_MANAGER_XI2 (manager); + + return g_hash_table_lookup (manager_xi2->devices_by_id, + GINT_TO_POINTER (id)); +} + +static ClutterInputDevice * +clutter_device_manager_xi2_get_core_device (ClutterDeviceManager *manager, + ClutterInputDeviceType device_type) +{ + ClutterDeviceManagerXI2 *manager_xi2 = CLUTTER_DEVICE_MANAGER_XI2 (manager); + ClutterInputDevice *pointer = NULL; + GList *l; + + for (l = manager_xi2->master_devices; l != NULL ; l = l->next) + { + ClutterInputDevice *device = l->data; + if (clutter_input_device_get_device_type (device) == CLUTTER_POINTER_DEVICE) + { + pointer = device; + break; + } + } + + if (pointer == NULL) + return NULL; + + switch (device_type) + { + case CLUTTER_POINTER_DEVICE: + return pointer; + + case CLUTTER_KEYBOARD_DEVICE: + return clutter_input_device_get_associated_device (pointer); + + default: + break; + } + + return NULL; +} + +static void +relate_masters (gpointer key, + gpointer value, + gpointer data) +{ + ClutterDeviceManagerXI2 *manager_xi2 = data; + ClutterInputDevice *device, *relative; + + device = g_hash_table_lookup (manager_xi2->devices_by_id, key); + relative = g_hash_table_lookup (manager_xi2->devices_by_id, value); + + _clutter_input_device_set_associated_device (device, relative); + _clutter_input_device_set_associated_device (relative, device); +} + +static void +relate_slaves (gpointer key, + gpointer value, + gpointer data) +{ + ClutterDeviceManagerXI2 *manager_xi2 = data; + ClutterInputDevice *master, *slave; + + slave = g_hash_table_lookup (manager_xi2->devices_by_id, key); + master = g_hash_table_lookup (manager_xi2->devices_by_id, value); + + _clutter_input_device_set_associated_device (slave, master); + _clutter_input_device_add_slave (master, slave); +} + +static void +clutter_device_manager_xi2_constructed (GObject *gobject) +{ + ClutterDeviceManagerXI2 *manager_xi2 = CLUTTER_DEVICE_MANAGER_XI2 (gobject); + ClutterDeviceManager *manager = CLUTTER_DEVICE_MANAGER (gobject); + ClutterBackendX11 *backend_x11; + GHashTable *masters, *slaves; + XIDeviceInfo *info; + XIEventMask event_mask; + unsigned char mask[2] = { 0, }; + int n_devices, i; + + backend_x11 = + CLUTTER_BACKEND_X11 (_clutter_device_manager_get_backend (manager)); + + masters = g_hash_table_new (NULL, NULL); + slaves = g_hash_table_new (NULL, NULL); + + info = XIQueryDevice (backend_x11->xdpy, XIAllDevices, &n_devices); + + for (i = 0; i < n_devices; i++) + { + XIDeviceInfo *xi_device = &info[i]; + + if (!xi_device->enabled) + continue; + + add_device (manager_xi2, backend_x11, xi_device, TRUE); + + if (xi_device->use == XIMasterPointer || + xi_device->use == XIMasterKeyboard) + { + g_hash_table_insert (masters, + GINT_TO_POINTER (xi_device->deviceid), + GINT_TO_POINTER (xi_device->attachment)); + } + else if (xi_device->use == XISlavePointer || + xi_device->use == XISlaveKeyboard) + { + g_hash_table_insert (slaves, + GINT_TO_POINTER (xi_device->deviceid), + GINT_TO_POINTER (xi_device->attachment)); + } + } + + XIFreeDeviceInfo (info); + + g_hash_table_foreach (masters, relate_masters, manager_xi2); + g_hash_table_destroy (masters); + + g_hash_table_foreach (slaves, relate_slaves, manager_xi2); + g_hash_table_destroy (slaves); + + XISetMask (mask, XI_HierarchyChanged); + XISetMask (mask, XI_DeviceChanged); + + event_mask.deviceid = XIAllDevices; + event_mask.mask_len = sizeof (mask); + event_mask.mask = mask; + + clutter_device_manager_xi2_select_events (manager, + clutter_x11_get_root_window (), + &event_mask); + + XSync (backend_x11->xdpy, False); + + if (G_OBJECT_CLASS (clutter_device_manager_xi2_parent_class)->constructed) + G_OBJECT_CLASS (clutter_device_manager_xi2_parent_class)->constructed (gobject); +} + +static void +clutter_device_manager_xi2_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterDeviceManagerXI2 *manager_xi2 = CLUTTER_DEVICE_MANAGER_XI2 (gobject); + + switch (prop_id) + { + case PROP_OPCODE: + manager_xi2->opcode = g_value_get_int (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_device_manager_xi2_class_init (ClutterDeviceManagerXI2Class *klass) +{ + ClutterDeviceManagerClass *manager_class; + GObjectClass *gobject_class; + + obj_props[PROP_OPCODE] = + g_param_spec_int ("opcode", + "Opcode", + "The XI2 opcode", + -1, G_MAXINT, + -1, + CLUTTER_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY); + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->constructed = clutter_device_manager_xi2_constructed; + gobject_class->set_property = clutter_device_manager_xi2_set_property; + + g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); + + manager_class = CLUTTER_DEVICE_MANAGER_CLASS (klass); + manager_class->add_device = clutter_device_manager_xi2_add_device; + manager_class->remove_device = clutter_device_manager_xi2_remove_device; + manager_class->get_devices = clutter_device_manager_xi2_get_devices; + manager_class->get_core_device = clutter_device_manager_xi2_get_core_device; + manager_class->get_device = clutter_device_manager_xi2_get_device; + manager_class->select_stage_events = clutter_device_manager_xi2_select_stage_events; +} + +static void +clutter_device_manager_xi2_init (ClutterDeviceManagerXI2 *self) +{ + self->devices_by_id = g_hash_table_new_full (NULL, NULL, + NULL, + (GDestroyNotify) g_object_unref); +} diff --git a/clutter/clutter/x11/clutter-device-manager-xi2.h b/clutter/clutter/x11/clutter-device-manager-xi2.h new file mode 100644 index 0000000..2ceb623 --- /dev/null +++ b/clutter/clutter/x11/clutter-device-manager-xi2.h @@ -0,0 +1,64 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright © 2011 Intel Corp. + * + * 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 . + * + * Author: Emmanuele Bassi + */ + +#ifndef __CLUTTER_DEVICE_MANAGER_XI2_H__ +#define __CLUTTER_DEVICE_MANAGER_XI2_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_DEVICE_MANAGER_XI2 (_clutter_device_manager_xi2_get_type ()) +#define CLUTTER_DEVICE_MANAGER_XI2(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_DEVICE_MANAGER_XI2, ClutterDeviceManagerXI2)) +#define CLUTTER_IS_DEVICE_MANAGER_XI2(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_DEVICE_MANAGER_XI2)) +#define CLUTTER_DEVICE_MANAGER_XI2_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_DEVICE_MANAGER_XI2, ClutterDeviceManagerXI2Class)) +#define CLUTTER_IS_DEVICE_MANAGER_XI2_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_DEVICE_MANAGER_XI2)) +#define CLUTTER_DEVICE_MANAGER_XI2_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_DEVICE_MANAGER_XI2, ClutterDeviceManagerXI2Class)) + +typedef struct _ClutterDeviceManagerXI2 ClutterDeviceManagerXI2; +typedef struct _ClutterDeviceManagerXI2Class ClutterDeviceManagerXI2Class; + +struct _ClutterDeviceManagerXI2 +{ + ClutterDeviceManager parent_instance; + + GHashTable *devices_by_id; + + GSList *all_devices; + + GList *master_devices; + GList *slave_devices; + + int opcode; +}; + +struct _ClutterDeviceManagerXI2Class +{ + ClutterDeviceManagerClass parent_class; +}; + +GType _clutter_device_manager_xi2_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* __CLUTTER_DEVICE_MANAGER_XI2_H__ */ diff --git a/clutter/clutter/x11/clutter-event-x11.c b/clutter/clutter/x11/clutter-event-x11.c new file mode 100644 index 0000000..3636ff3 --- /dev/null +++ b/clutter/clutter/x11/clutter-event-x11.c @@ -0,0 +1,394 @@ +/* Clutter. + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2006, 2007, 2008 OpenedHand Ltd + * Copyright (C) 2009, 2010 Intel Corp. + * + * 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 . + * + * + * + * Authored by: + * Matthew Allum + * Emmanuele Bassi + */ + +#include "clutter-build-config.h" + +#include "clutter-backend-x11.h" +#include "clutter-x11.h" + +#include "clutter-backend-private.h" +#include "clutter-debug.h" +#include "clutter-event-private.h" +#include "clutter-main.h" +#include "clutter-private.h" +#include "clutter-stage-private.h" + +#include + +#include + +#if 0 +/* XEMBED protocol support for toolkit embedding */ +#define XEMBED_MAPPED (1 << 0) +#define MAX_SUPPORTED_XEMBED_VERSION 1 + +#define XEMBED_EMBEDDED_NOTIFY 0 +#define XEMBED_WINDOW_ACTIVATE 1 +#define XEMBED_WINDOW_DEACTIVATE 2 +#define XEMBED_REQUEST_FOCUS 3 +#define XEMBED_FOCUS_IN 4 +#define XEMBED_FOCUS_OUT 5 +#define XEMBED_FOCUS_NEXT 6 +#define XEMBED_FOCUS_PREV 7 +/* 8-9 were used for XEMBED_GRAB_KEY/XEMBED_UNGRAB_KEY */ +#define XEMBED_MODALITY_ON 10 +#define XEMBED_MODALITY_OFF 11 +#define XEMBED_REGISTER_ACCELERATOR 12 +#define XEMBED_UNREGISTER_ACCELERATOR 13 +#define XEMBED_ACTIVATE_ACCELERATOR 14 + +static Window ParentEmbedderWin = None; +#endif + +typedef struct _ClutterEventSource ClutterEventSource; + +struct _ClutterEventSource +{ + GSource source; + + ClutterBackendX11 *backend; + + GPollFD event_poll_fd; +}; + +ClutterEventX11 * +_clutter_event_x11_new (void) +{ + return g_slice_new0 (ClutterEventX11); +} + +ClutterEventX11 * +_clutter_event_x11_copy (ClutterEventX11 *event_x11) +{ + if (event_x11 != NULL) + return g_slice_dup (ClutterEventX11, event_x11); + + return NULL; +} + +void +_clutter_event_x11_free (ClutterEventX11 *event_x11) +{ + if (event_x11 != NULL) + g_slice_free (ClutterEventX11, event_x11); +} + +static gboolean clutter_event_prepare (GSource *source, + gint *timeout); +static gboolean clutter_event_check (GSource *source); +static gboolean clutter_event_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data); + +static GSourceFuncs event_funcs = { + clutter_event_prepare, + clutter_event_check, + clutter_event_dispatch, + NULL +}; + +GSource * +_clutter_x11_event_source_new (ClutterBackendX11 *backend_x11) +{ + ClutterEventSource *event_source; + int connection_number; + GSource *source; + gchar *name; + + connection_number = ConnectionNumber (backend_x11->xdpy); + CLUTTER_NOTE (EVENT, "Connection number: %d", connection_number); + + source = g_source_new (&event_funcs, sizeof (ClutterEventSource)); + event_source = (ClutterEventSource *) source; + + name = g_strdup_printf ("Clutter X11 Event (connection: %d)", + connection_number); + g_source_set_name (source, name); + g_free (name); + + event_source->backend = backend_x11; + event_source->event_poll_fd.fd = connection_number; + event_source->event_poll_fd.events = G_IO_IN; + + g_source_add_poll (source, &event_source->event_poll_fd); + g_source_set_can_recurse (source, TRUE); + + return source; +} + +/** + * clutter_x11_handle_event: + * @xevent: pointer to XEvent structure + * + * This function processes a single X event; it can be used to hook + * into external X11 event processing (for example, a GDK filter + * function). + * + * If clutter_x11_disable_event_retrieval() has been called, you must + * let this function process events to update Clutter's internal state. + * + * Return value: #ClutterX11FilterReturn. %CLUTTER_X11_FILTER_REMOVE + * indicates that Clutter has internally handled the event and the + * caller should do no further processing. %CLUTTER_X11_FILTER_CONTINUE + * indicates that Clutter is either not interested in the event, + * or has used the event to update internal state without taking + * any exclusive action. %CLUTTER_X11_FILTER_TRANSLATE will not + * occur. + * + * Since: 0.8 + */ +ClutterX11FilterReturn +clutter_x11_handle_event (XEvent *xevent) +{ + ClutterX11FilterReturn result; + ClutterBackend *backend; + ClutterEvent *event; + gint spin = 1; +#ifdef HAVE_XGE + ClutterBackendX11 *backend_x11; + Display *xdisplay; + gboolean allocated_event; +#endif + + /* The return values here are someone approximate; we return + * CLUTTER_X11_FILTER_REMOVE if a clutter event is + * generated for the event. This mostly, but not entirely, + * corresponds to whether other event processing should be + * excluded. As long as the stage window is not shared with another + * toolkit it should be safe, and never return + * %CLUTTER_X11_FILTER_REMOVE when more processing is needed. + */ + + result = CLUTTER_X11_FILTER_CONTINUE; + + _clutter_threads_acquire_lock (); + + backend = clutter_get_default_backend (); + + event = clutter_event_new (CLUTTER_NOTHING); + +#ifdef HAVE_XGE + backend_x11 = CLUTTER_BACKEND_X11 (backend); + xdisplay = backend_x11->xdpy; + + allocated_event = XGetEventData (xdisplay, &xevent->xcookie); +#endif + + if (_clutter_backend_translate_event (backend, xevent, event)) + { + _clutter_event_push (event, FALSE); + + result = CLUTTER_X11_FILTER_REMOVE; + } + else + { + clutter_event_free (event); + goto out; + } + + /* + * Motion events can generate synthetic enter and leave events, so if we + * are processing a motion event, we need to spin the event loop at least + * two extra times to pump the enter/leave events through (otherwise they + * just get pushed down the queue and never processed). + */ + if (event->type == CLUTTER_MOTION) + spin += 2; + + while (spin > 0 && (event = clutter_event_get ())) + { + /* forward the event into clutter for emission etc. */ + _clutter_stage_queue_event (event->any.stage, event, FALSE); + --spin; + } + +out: +#ifdef HAVE_XGE + if (allocated_event) + XFreeEventData (xdisplay, &xevent->xcookie); +#endif + + _clutter_threads_release_lock (); + + return result; +} + +static gboolean +clutter_event_prepare (GSource *source, + gint *timeout) +{ + ClutterBackendX11 *backend = ((ClutterEventSource *) source)->backend; + gboolean retval; + + _clutter_threads_acquire_lock (); + + *timeout = -1; + retval = (clutter_events_pending () || XPending (backend->xdpy)); + + _clutter_threads_release_lock (); + + return retval; +} + +static gboolean +clutter_event_check (GSource *source) +{ + ClutterEventSource *event_source = (ClutterEventSource *) source; + ClutterBackendX11 *backend = event_source->backend; + gboolean retval; + + _clutter_threads_acquire_lock (); + + if (event_source->event_poll_fd.revents & G_IO_IN) + retval = (clutter_events_pending () || XPending (backend->xdpy)); + else + retval = FALSE; + + _clutter_threads_release_lock (); + + return retval; +} + +static void +events_queue (ClutterBackendX11 *backend_x11) +{ + ClutterBackend *backend = CLUTTER_BACKEND (backend_x11); + Display *xdisplay = backend_x11->xdpy; + ClutterEvent *event; + XEvent xevent; + + while (!clutter_events_pending () && XPending (xdisplay)) + { + XNextEvent (xdisplay, &xevent); + + event = clutter_event_new (CLUTTER_NOTHING); + +#ifdef HAVE_XGE + XGetEventData (xdisplay, &xevent.xcookie); +#endif + + if (_clutter_backend_translate_event (backend, &xevent, event)) + _clutter_event_push (event, FALSE); + else + clutter_event_free (event); + +#ifdef HAVE_XGE + XFreeEventData (xdisplay, &xevent.xcookie); +#endif + } +} + +static gboolean +clutter_event_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + ClutterBackendX11 *backend = ((ClutterEventSource *) source)->backend; + ClutterEvent *event; + + _clutter_threads_acquire_lock (); + + /* Grab the event(s), translate and figure out double click. + * The push onto queue (stack) if valid. + */ + events_queue (backend); + + /* Pop an event off the queue if any */ + event = clutter_event_get (); + if (event != NULL) + { + /* forward the event into clutter for emission etc. */ + _clutter_stage_queue_event (event->any.stage, event, FALSE); + } + + _clutter_threads_release_lock (); + + return TRUE; +} + +/** + * clutter_x11_get_current_event_time: (skip) + * + * Retrieves the timestamp of the last X11 event processed by + * Clutter. This might be different from the timestamp returned + * by clutter_get_current_event_time(), as Clutter may synthesize + * or throttle events. + * + * Return value: a timestamp, in milliseconds + * + * Since: 1.0 + */ +Time +clutter_x11_get_current_event_time (void) +{ + ClutterBackend *backend = clutter_get_default_backend (); + + return CLUTTER_BACKEND_X11 (backend)->last_event_time; +} + +/** + * clutter_x11_event_get_key_group: + * @event: a #ClutterEvent of type %CLUTTER_KEY_PRESS or %CLUTTER_KEY_RELEASE + * + * Retrieves the group for the modifiers set in @event + * + * Return value: the group id + * + * Since: 1.4 + */ +gint +clutter_x11_event_get_key_group (const ClutterEvent *event) +{ + ClutterEventX11 *event_x11; + + g_return_val_if_fail (event != NULL, 0); + g_return_val_if_fail (event->type == CLUTTER_KEY_PRESS || + event->type == CLUTTER_KEY_RELEASE, 0); + + event_x11 = _clutter_event_get_platform_data (event); + if (event_x11 == NULL) + return 0; + + return event_x11->key_group; +} + +/** + * clutter_x11_event_sequence_get_touch_detail: + * @sequence: a #ClutterEventSequence + * + * Retrieves the touch detail froma #ClutterEventSequence. + * + * Return value: the touch detail + * + * Since: 1.12 + */ +guint +clutter_x11_event_sequence_get_touch_detail (const ClutterEventSequence *sequence) +{ + g_return_val_if_fail (sequence != NULL, 0); + + return GPOINTER_TO_UINT (sequence); +} diff --git a/clutter/clutter/x11/clutter-input-device-core-x11.c b/clutter/clutter/x11/clutter-input-device-core-x11.c new file mode 100644 index 0000000..c7543f9 --- /dev/null +++ b/clutter/clutter/x11/clutter-input-device-core-x11.c @@ -0,0 +1,78 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright © 2010, 2011 Intel Corp. + * + * 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 . + * + * Author: Emmanuele Bassi + */ + +#include "clutter-build-config.h" + +#include "clutter-input-device-core-x11.h" + +#include "clutter-debug.h" +#include "clutter-device-manager-private.h" +#include "clutter-private.h" +#include "clutter-stage-private.h" + +#include "clutter-backend-x11.h" +#include "clutter-stage-x11.h" + +typedef struct _ClutterInputDeviceClass ClutterInputDeviceX11Class; + +/* a specific X11 input device */ +struct _ClutterInputDeviceX11 +{ + ClutterInputDevice device; + + int min_keycode; + int max_keycode; +}; + +#define clutter_input_device_x11_get_type _clutter_input_device_x11_get_type + +G_DEFINE_TYPE (ClutterInputDeviceX11, + clutter_input_device_x11, + CLUTTER_TYPE_INPUT_DEVICE); + +static gboolean +clutter_input_device_x11_keycode_to_evdev (ClutterInputDevice *device, + guint hardware_keycode, + guint *evdev_keycode) +{ + /* When using evdev under X11 the hardware keycodes are the evdev + keycodes plus 8. I haven't been able to find any documentation to + know what the +8 is for. FIXME: This should probably verify that + X server is using evdev. */ + *evdev_keycode = hardware_keycode - 8; + + return TRUE; +} + +static void +clutter_input_device_x11_class_init (ClutterInputDeviceX11Class *klass) +{ + ClutterInputDeviceClass *device_class = CLUTTER_INPUT_DEVICE_CLASS (klass); + + device_class->keycode_to_evdev = clutter_input_device_x11_keycode_to_evdev; +} + +static void +clutter_input_device_x11_init (ClutterInputDeviceX11 *self) +{ +} diff --git a/clutter/clutter/x11/clutter-input-device-core-x11.h b/clutter/clutter/x11/clutter-input-device-core-x11.h new file mode 100644 index 0000000..c264051 --- /dev/null +++ b/clutter/clutter/x11/clutter-input-device-core-x11.h @@ -0,0 +1,44 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright © 2010, 2011 Intel Corp. + * + * 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 . + * + * Author: Emmanuele Bassi + */ + +#ifndef __CLUTTER_INPUT_DEVICE_X11_H__ +#define __CLUTTER_INPUT_DEVICE_X11_H__ + +#include +#include + +#include "clutter-stage-x11.h" + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_INPUT_DEVICE_X11 (_clutter_input_device_x11_get_type ()) +#define CLUTTER_INPUT_DEVICE_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_INPUT_DEVICE_X11, ClutterInputDeviceX11)) +#define CLUTTER_IS_INPUT_DEVICE_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_INPUT_DEVICE_X11)) + +typedef struct _ClutterInputDeviceX11 ClutterInputDeviceX11; + +GType _clutter_input_device_x11_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* __CLUTTER_INPUT_DEVICE_X11_H__ */ diff --git a/clutter/clutter/x11/clutter-input-device-xi2.c b/clutter/clutter/x11/clutter-input-device-xi2.c new file mode 100644 index 0000000..00416a3 --- /dev/null +++ b/clutter/clutter/x11/clutter-input-device-xi2.c @@ -0,0 +1,174 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright © 2011 Intel Corp. + * + * 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 . + * + * Author: Emmanuele Bassi + */ + +#include "clutter-build-config.h" + +#include "clutter-input-device-xi2.h" + +#include "clutter-debug.h" +#include "clutter-device-manager-private.h" +#include "clutter-event-private.h" +#include "clutter-private.h" +#include "clutter-stage-private.h" + +#include "clutter-backend-x11.h" +#include "clutter-stage-x11.h" + +#include + +typedef struct _ClutterInputDeviceClass ClutterInputDeviceXI2Class; + +/* a specific XI2 input device */ +struct _ClutterInputDeviceXI2 +{ + ClutterInputDevice device; + + gint device_id; +}; + +#define N_BUTTONS 5 + +#define clutter_input_device_xi2_get_type _clutter_input_device_xi2_get_type + +G_DEFINE_TYPE (ClutterInputDeviceXI2, + clutter_input_device_xi2, + CLUTTER_TYPE_INPUT_DEVICE); + +static void +clutter_input_device_xi2_constructed (GObject *gobject) +{ + ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (gobject); + + g_object_get (gobject, "id", &device_xi2->device_id, NULL); + + if (G_OBJECT_CLASS (clutter_input_device_xi2_parent_class)->constructed) + G_OBJECT_CLASS (clutter_input_device_xi2_parent_class)->constructed (gobject); +} + +static gboolean +clutter_input_device_xi2_keycode_to_evdev (ClutterInputDevice *device, + guint hardware_keycode, + guint *evdev_keycode) +{ + /* When using evdev under X11 the hardware keycodes are the evdev + keycodes plus 8. I haven't been able to find any documentation to + know what the +8 is for. FIXME: This should probably verify that + X server is using evdev. */ + *evdev_keycode = hardware_keycode - 8; + + return TRUE; +} + +static void +clutter_input_device_xi2_class_init (ClutterInputDeviceXI2Class *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterInputDeviceClass *device_class = CLUTTER_INPUT_DEVICE_CLASS (klass); + + gobject_class->constructed = clutter_input_device_xi2_constructed; + + device_class->keycode_to_evdev = clutter_input_device_xi2_keycode_to_evdev; +} + +static void +clutter_input_device_xi2_init (ClutterInputDeviceXI2 *self) +{ +} + +static ClutterModifierType +get_modifier_for_button (int i) +{ + switch (i) + { + case 1: + return CLUTTER_BUTTON1_MASK; + case 2: + return CLUTTER_BUTTON2_MASK; + case 3: + return CLUTTER_BUTTON3_MASK; + case 4: + return CLUTTER_BUTTON4_MASK; + case 5: + return CLUTTER_BUTTON5_MASK; + default: + return 0; + } +} + +void +_clutter_input_device_xi2_translate_state (ClutterEvent *event, + XIModifierState *modifiers_state, + XIButtonState *buttons_state, + XIGroupState *group_state) +{ + guint button = 0; + guint base = 0; + guint latched = 0; + guint locked = 0; + guint effective; + + if (modifiers_state) + { + base = (guint) modifiers_state->base; + latched = (guint) modifiers_state->latched; + locked = (guint) modifiers_state->locked; + } + + if (buttons_state) + { + int len, i; + + len = MIN (N_BUTTONS, buttons_state->mask_len * 8); + + for (i = 0; i < len; i++) + { + if (!XIMaskIsSet (buttons_state->mask, i)) + continue; + + button |= get_modifier_for_button (i); + } + } + + /* The XIButtonState sent in the event specifies the + * state of the buttons before the event. In order to + * get the current state of the buttons, we need to + * filter out the current button. + */ + switch (event->type) + { + case CLUTTER_BUTTON_PRESS: + button |= (get_modifier_for_button (event->button.button)); + break; + case CLUTTER_BUTTON_RELEASE: + button &= ~(get_modifier_for_button (event->button.button)); + break; + default: + break; + } + + effective = button | base | latched | locked; + if (group_state) + effective |= (group_state->effective) << 13; + + _clutter_event_set_state_full (event, button, base, latched, locked, effective); +} diff --git a/clutter/clutter/x11/clutter-input-device-xi2.h b/clutter/clutter/x11/clutter-input-device-xi2.h new file mode 100644 index 0000000..92dadc9 --- /dev/null +++ b/clutter/clutter/x11/clutter-input-device-xi2.h @@ -0,0 +1,47 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright © 2011 Intel Corp. + * + * 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 . + * + * Author: Emmanuele Bassi + */ + +#ifndef __CLUTTER_INPUT_DEVICE_XI2_H__ +#define __CLUTTER_INPUT_DEVICE_XI2_H__ + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_INPUT_DEVICE_XI2 (_clutter_input_device_xi2_get_type ()) +#define CLUTTER_INPUT_DEVICE_XI2(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_INPUT_DEVICE_XI2, ClutterInputDeviceXI2)) +#define CLUTTER_IS_INPUT_DEVICE_XI2(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_INPUT_DEVICE_XI2)) + +typedef struct _ClutterInputDeviceXI2 ClutterInputDeviceXI2; + +GType _clutter_input_device_xi2_get_type (void) G_GNUC_CONST; + +void _clutter_input_device_xi2_translate_state (ClutterEvent *event, + XIModifierState *modifiers_state, + XIButtonState *buttons_state, + XIGroupState *group_state); + +G_END_DECLS + +#endif /* __CLUTTER_INPUT_DEVICE_XI2_H__ */ diff --git a/clutter/clutter/x11/clutter-keymap-x11.c b/clutter/clutter/x11/clutter-keymap-x11.c new file mode 100644 index 0000000..914e314 --- /dev/null +++ b/clutter/clutter/x11/clutter-keymap-x11.c @@ -0,0 +1,667 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corp. + * + * 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 . + * + * Author: Emmanuele Bassi + */ + +#include "clutter-build-config.h" + +#include "clutter-keymap-x11.h" +#include "clutter-backend-x11.h" + +#include "clutter-debug.h" +#include "clutter-event-translator.h" +#include "clutter-private.h" + +#include + +#ifdef HAVE_XKB +#include +#endif + +typedef struct _ClutterKeymapX11Class ClutterKeymapX11Class; +typedef struct _DirectionCacheEntry DirectionCacheEntry; + +struct _DirectionCacheEntry +{ + guint serial; + Atom group_atom; + PangoDirection direction; +}; + +struct _ClutterKeymapX11 +{ + GObject parent_instance; + + ClutterBackend *backend; + + int min_keycode; + int max_keycode; + + ClutterModifierType modmap[8]; + + ClutterModifierType num_lock_mask; + ClutterModifierType scroll_lock_mask; + + PangoDirection current_direction; + +#ifdef HAVE_XKB + XkbDescPtr xkb_desc; + int xkb_event_base; + guint xkb_map_serial; + Atom current_group_atom; + guint current_cache_serial; + DirectionCacheEntry group_direction_cache[4]; +#endif + + guint caps_lock_state : 1; + guint num_lock_state : 1; + guint has_direction : 1; +}; + +struct _ClutterKeymapX11Class +{ + GObjectClass parent_class; +}; + +enum +{ + PROP_0, + + PROP_BACKEND, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST] = { NULL, }; + +static void clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface); + +#define clutter_keymap_x11_get_type _clutter_keymap_x11_get_type + +G_DEFINE_TYPE_WITH_CODE (ClutterKeymapX11, clutter_keymap_x11, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_EVENT_TRANSLATOR, + clutter_event_translator_iface_init)); + +#ifdef HAVE_XKB + +/* code adapted from gdk/x11/gdkkeys-x11.c - update_modmap */ +static void +update_modmap (Display *display, + ClutterKeymapX11 *keymap_x11) +{ + static struct { + const gchar *name; + Atom atom; + ClutterModifierType mask; + } vmods[] = { + { "Meta", 0, CLUTTER_META_MASK }, + { "Super", 0, CLUTTER_SUPER_MASK }, + { "Hyper", 0, CLUTTER_HYPER_MASK }, + { NULL, 0, 0 } + }; + + int i, j, k; + + if (vmods[0].atom == 0) + for (i = 0; vmods[i].name; i++) + vmods[i].atom = XInternAtom (display, vmods[i].name, FALSE); + + for (i = 0; i < 8; i++) + keymap_x11->modmap[i] = 1 << i; + + for (i = 0; i < XkbNumVirtualMods; i++) + { + for (j = 0; vmods[j].atom; j++) + { + if (keymap_x11->xkb_desc->names->vmods[i] == vmods[j].atom) + { + for (k = 0; k < 8; k++) + { + if (keymap_x11->xkb_desc->server->vmods[i] & (1 << k)) + keymap_x11->modmap[k] |= vmods[j].mask; + } + } + } + } +} + +static XkbDescPtr +get_xkb (ClutterKeymapX11 *keymap_x11) +{ + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (keymap_x11->backend); + + if (keymap_x11->max_keycode == 0) + XDisplayKeycodes (backend_x11->xdpy, + &keymap_x11->min_keycode, + &keymap_x11->max_keycode); + + if (keymap_x11->xkb_desc == NULL) + { + int flags = XkbKeySymsMask + | XkbKeyTypesMask + | XkbModifierMapMask + | XkbVirtualModsMask; + + keymap_x11->xkb_desc = XkbGetMap (backend_x11->xdpy, flags, XkbUseCoreKbd); + if (G_UNLIKELY (keymap_x11->xkb_desc == NULL)) + { + g_error ("Failed to get the keymap from XKB"); + return NULL; + } + + flags = XkbGroupNamesMask | XkbVirtualModNamesMask; + XkbGetNames (backend_x11->xdpy, flags, keymap_x11->xkb_desc); + + update_modmap (backend_x11->xdpy, keymap_x11); + } + else if (keymap_x11->xkb_map_serial != backend_x11->keymap_serial) + { + int flags = XkbKeySymsMask + | XkbKeyTypesMask + | XkbModifierMapMask + | XkbVirtualModsMask; + + CLUTTER_NOTE (BACKEND, "Updating XKB keymap"); + + XkbGetUpdatedMap (backend_x11->xdpy, flags, keymap_x11->xkb_desc); + + flags = XkbGroupNamesMask | XkbVirtualModNamesMask; + XkbGetNames (backend_x11->xdpy, flags, keymap_x11->xkb_desc); + + update_modmap (backend_x11->xdpy, keymap_x11); + + keymap_x11->xkb_map_serial = backend_x11->keymap_serial; + } + + if (keymap_x11->num_lock_mask == 0) + keymap_x11->num_lock_mask = XkbKeysymToModifiers (backend_x11->xdpy, + XK_Num_Lock); + + if (keymap_x11->scroll_lock_mask == 0) + keymap_x11->scroll_lock_mask = XkbKeysymToModifiers (backend_x11->xdpy, + XK_Scroll_Lock); + + return keymap_x11->xkb_desc; +} +#endif /* HAVE_XKB */ + +#ifdef HAVE_XKB +static void +update_locked_mods (ClutterKeymapX11 *keymap_x11, + gint locked_mods) +{ +#if 0 + gboolean old_caps_lock_state, old_num_lock_state; + + old_caps_lock_state = keymap_x11->caps_lock_state; + old_num_lock_state = keymap_x11->num_lock_state; +#endif + + keymap_x11->caps_lock_state = (locked_mods & CLUTTER_LOCK_MASK) != 0; + keymap_x11->num_lock_state = (locked_mods & keymap_x11->num_lock_mask) != 0; + + CLUTTER_NOTE (BACKEND, "Locks state changed - Num: %s, Caps: %s", + keymap_x11->num_lock_state ? "set" : "unset", + keymap_x11->caps_lock_state ? "set" : "unset"); + +#if 0 + /* Add signal to ClutterBackend? */ + if ((keymap_x11->caps_lock_state != old_caps_lock_state) || + (keymap_x11->num_lock_state != old_num_lock_state)) + g_signal_emit_by_name (keymap_x11->backend, "key-lock-changed"); +#endif +} +#endif /* HAVE_XKB */ + +#ifdef HAVE_XKB +/* the code to retrieve the keymap direction and cache it + * is taken from GDK: + * gdk/x11/gdkkeys-x11.c + */ +static PangoDirection +get_direction (XkbDescPtr xkb, + int group) +{ + int rtl_minus_ltr = 0; /* total number of RTL keysyms minus LTR ones */ + int code; + + for (code = xkb->min_key_code; + code <= xkb->max_key_code; + code += 1) + { + int level = 0; + KeySym sym = XkbKeySymEntry (xkb, code, level, group); + PangoDirection dir = pango_unichar_direction (clutter_keysym_to_unicode (sym)); + + switch (dir) + { + case PANGO_DIRECTION_RTL: + rtl_minus_ltr++; + break; + + case PANGO_DIRECTION_LTR: + rtl_minus_ltr--; + break; + + default: + break; + } + } + + if (rtl_minus_ltr > 0) + return PANGO_DIRECTION_RTL; + + return PANGO_DIRECTION_LTR; +} + +static PangoDirection +get_direction_from_cache (ClutterKeymapX11 *keymap_x11, + XkbDescPtr xkb, + int group) +{ + Atom group_atom = xkb->names->groups[group]; + gboolean cache_hit = FALSE; + DirectionCacheEntry *cache = keymap_x11->group_direction_cache; + PangoDirection direction = PANGO_DIRECTION_NEUTRAL; + int i; + + if (keymap_x11->has_direction) + { + /* look up in the cache */ + for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++) + { + if (cache[i].group_atom == group_atom) + { + cache_hit = TRUE; + cache[i].serial = keymap_x11->current_cache_serial++; + direction = cache[i].direction; + group_atom = cache[i].group_atom; + break; + } + } + } + else + { + /* initialize the cache */ + for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++) + { + cache[i].group_atom = 0; + cache[i].direction = PANGO_DIRECTION_NEUTRAL; + cache[i].serial = keymap_x11->current_cache_serial; + } + + keymap_x11->current_cache_serial += 1; + } + + /* insert the new entry in the cache */ + if (!cache_hit) + { + int oldest = 0; + + direction = get_direction (xkb, group); + + /* replace the oldest entry */ + for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++) + { + if (cache[i].serial < cache[oldest].serial) + oldest = i; + } + + cache[oldest].group_atom = group_atom; + cache[oldest].direction = direction; + cache[oldest].serial = keymap_x11->current_cache_serial++; + } + + return direction; +} +#endif /* HAVE_XKB */ + +static void +update_direction (ClutterKeymapX11 *keymap_x11, + int group) +{ +#ifdef HAVE_XKB + XkbDescPtr xkb = get_xkb (keymap_x11); + Atom group_atom; + + group_atom = xkb->names->groups[group]; + + if (!keymap_x11->has_direction || keymap_x11->current_group_atom != group_atom) + { + keymap_x11->current_direction = get_direction_from_cache (keymap_x11, xkb, group); + keymap_x11->current_group_atom = group_atom; + keymap_x11->has_direction = TRUE; + } +#endif /* HAVE_XKB */ +} + +static void +clutter_keymap_x11_constructed (GObject *gobject) +{ + ClutterKeymapX11 *keymap_x11 = CLUTTER_KEYMAP_X11 (gobject); + ClutterBackendX11 *backend_x11; + + g_assert (keymap_x11->backend != NULL); + backend_x11 = CLUTTER_BACKEND_X11 (keymap_x11->backend); + +#ifdef HAVE_XKB + { + gint xkb_major = XkbMajorVersion; + gint xkb_minor = XkbMinorVersion; + + if (XkbLibraryVersion (&xkb_major, &xkb_minor)) + { + xkb_major = XkbMajorVersion; + xkb_minor = XkbMinorVersion; + + if (XkbQueryExtension (backend_x11->xdpy, + NULL, + &keymap_x11->xkb_event_base, + NULL, + &xkb_major, &xkb_minor)) + { + Bool detectable_autorepeat_supported; + + backend_x11->use_xkb = TRUE; + + XkbSelectEvents (backend_x11->xdpy, + XkbUseCoreKbd, + XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask, + XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask); + + XkbSelectEventDetails (backend_x11->xdpy, + XkbUseCoreKbd, XkbStateNotify, + XkbAllStateComponentsMask, + XkbGroupLockMask | XkbModifierLockMask); + + /* enable XKB autorepeat */ + XkbSetDetectableAutoRepeat (backend_x11->xdpy, + True, + &detectable_autorepeat_supported); + + backend_x11->have_xkb_autorepeat = detectable_autorepeat_supported; + + CLUTTER_NOTE (BACKEND, "Detectable autorepeat: %s", + backend_x11->have_xkb_autorepeat ? "supported" + : "not supported"); + } + } + } +#endif /* HAVE_XKB */ +} + +static void +clutter_keymap_x11_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterKeymapX11 *keymap = CLUTTER_KEYMAP_X11 (gobject); + + switch (prop_id) + { + case PROP_BACKEND: + keymap->backend = g_value_get_object (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_keymap_x11_finalize (GObject *gobject) +{ + ClutterKeymapX11 *keymap; + ClutterEventTranslator *translator; + + keymap = CLUTTER_KEYMAP_X11 (gobject); + translator = CLUTTER_EVENT_TRANSLATOR (keymap); + +#ifdef HAVE_XKB + _clutter_backend_remove_event_translator (keymap->backend, translator); + + if (keymap->xkb_desc != NULL) + XkbFreeKeyboard (keymap->xkb_desc, XkbAllComponentsMask, True); +#endif + + G_OBJECT_CLASS (clutter_keymap_x11_parent_class)->finalize (gobject); +} + +static void +clutter_keymap_x11_class_init (ClutterKeymapX11Class *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + obj_props[PROP_BACKEND] = + g_param_spec_object ("backend", + P_("Backend"), + P_("The Clutter backend"), + CLUTTER_TYPE_BACKEND, + CLUTTER_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY); + + gobject_class->constructed = clutter_keymap_x11_constructed; + gobject_class->set_property = clutter_keymap_x11_set_property; + gobject_class->finalize = clutter_keymap_x11_finalize; + g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); +} + +static void +clutter_keymap_x11_init (ClutterKeymapX11 *keymap) +{ + keymap->current_direction = PANGO_DIRECTION_NEUTRAL; +} + +static ClutterTranslateReturn +clutter_keymap_x11_translate_event (ClutterEventTranslator *translator, + gpointer native, + ClutterEvent *event) +{ + ClutterKeymapX11 *keymap_x11 = CLUTTER_KEYMAP_X11 (translator); + ClutterBackendX11 *backend_x11; + ClutterTranslateReturn retval; + XEvent *xevent; + + backend_x11 = CLUTTER_BACKEND_X11 (keymap_x11->backend); + if (!backend_x11->use_xkb) + return CLUTTER_TRANSLATE_CONTINUE; + + xevent = native; + + retval = CLUTTER_TRANSLATE_CONTINUE; + +#ifdef HAVE_XKB + if (xevent->type == keymap_x11->xkb_event_base) + { + XkbEvent *xkb_event = (XkbEvent *) xevent; + + switch (xkb_event->any.xkb_type) + { + case XkbStateNotify: + CLUTTER_NOTE (EVENT, "Updating keyboard state"); + update_direction (keymap_x11, XkbStateGroup (&xkb_event->state)); + update_locked_mods (keymap_x11, xkb_event->state.locked_mods); + retval = CLUTTER_TRANSLATE_REMOVE; + break; + + case XkbNewKeyboardNotify: + case XkbMapNotify: + CLUTTER_NOTE (EVENT, "Updating keyboard mapping"); + XkbRefreshKeyboardMapping (&xkb_event->map); + backend_x11->keymap_serial += 1; + retval = CLUTTER_TRANSLATE_REMOVE; + break; + + default: + break; + } + } +#endif /* HAVE_XKB */ + + return retval; +} + +static void +clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface) +{ + iface->translate_event = clutter_keymap_x11_translate_event; +} + +gint +_clutter_keymap_x11_get_key_group (ClutterKeymapX11 *keymap, + ClutterModifierType state) +{ +#ifdef HAVE_XKB + return XkbGroupForCoreState (state); +#else + return 0; +#endif /* HAVE_XKB */ +} + +gboolean +_clutter_keymap_x11_get_num_lock_state (ClutterKeymapX11 *keymap) +{ + g_return_val_if_fail (CLUTTER_IS_KEYMAP_X11 (keymap), FALSE); + + return keymap->num_lock_state; +} + +gboolean +_clutter_keymap_x11_get_caps_lock_state (ClutterKeymapX11 *keymap) +{ + g_return_val_if_fail (CLUTTER_IS_KEYMAP_X11 (keymap), FALSE); + + return keymap->caps_lock_state; +} + +G_GNUC_BEGIN_IGNORE_DEPRECATIONS + +/* XXX - yes, I know that XKeycodeToKeysym() has been deprecated; hopefully, + * this code will never get run on any decent system that is also able to + * run Clutter. I just don't want to copy the implementation inside GDK for + * a fallback path. + */ +static int +translate_keysym (ClutterKeymapX11 *keymap, + guint hardware_keycode) +{ + ClutterBackendX11 *backend_x11; + gint retval; + + backend_x11 = CLUTTER_BACKEND_X11 (keymap->backend); + + retval = XKeycodeToKeysym (backend_x11->xdpy, hardware_keycode, 0); + + return retval; +} + +G_GNUC_END_IGNORE_DEPRECATIONS + +gint +_clutter_keymap_x11_translate_key_state (ClutterKeymapX11 *keymap, + guint hardware_keycode, + ClutterModifierType *modifier_state_p, + ClutterModifierType *mods_p) +{ + ClutterBackendX11 *backend_x11; + ClutterModifierType unconsumed_modifiers = 0; + ClutterModifierType modifier_state = *modifier_state_p; + gint retval; + + g_return_val_if_fail (CLUTTER_IS_KEYMAP_X11 (keymap), 0); + + backend_x11 = CLUTTER_BACKEND_X11 (keymap->backend); + +#ifdef HAVE_XKB + if (backend_x11->use_xkb) + { + XkbDescRec *xkb = get_xkb (keymap); + KeySym tmp_keysym; + + if (XkbTranslateKeyCode (xkb, hardware_keycode, modifier_state, + &unconsumed_modifiers, + &tmp_keysym)) + { + retval = tmp_keysym; + } + else + retval = 0; + } + else +#endif /* HAVE_XKB */ + retval = translate_keysym (keymap, hardware_keycode); + + if (mods_p) + *mods_p = unconsumed_modifiers; + + *modifier_state_p = modifier_state & ~(keymap->num_lock_mask | + keymap->scroll_lock_mask | + LockMask); + + return retval; +} + +gboolean +_clutter_keymap_x11_get_is_modifier (ClutterKeymapX11 *keymap, + gint keycode) +{ + g_return_val_if_fail (CLUTTER_IS_KEYMAP_X11 (keymap), FALSE); + + if (keycode < keymap->min_keycode || keycode > keymap->max_keycode) + return FALSE; + +#ifdef HAVE_XKB + if (CLUTTER_BACKEND_X11 (keymap->backend)->use_xkb) + { + XkbDescRec *xkb = get_xkb (keymap); + + if (xkb->map->modmap && xkb->map->modmap[keycode] != 0) + return TRUE; + } +#endif /* HAVE_XKB */ + + return FALSE; +} + +PangoDirection +_clutter_keymap_x11_get_direction (ClutterKeymapX11 *keymap) +{ + g_return_val_if_fail (CLUTTER_IS_KEYMAP_X11 (keymap), PANGO_DIRECTION_NEUTRAL); + +#ifdef HAVE_XKB + if (CLUTTER_BACKEND_X11 (keymap->backend)->use_xkb) + { + if (!keymap->has_direction) + { + Display *xdisplay = CLUTTER_BACKEND_X11 (keymap->backend)->xdpy; + XkbStateRec state_rec; + + XkbGetState (xdisplay, XkbUseCoreKbd, &state_rec); + update_direction (keymap, XkbStateGroup (&state_rec)); + } + + return keymap->current_direction; + } + else +#endif + return PANGO_DIRECTION_NEUTRAL; +} diff --git a/clutter/clutter/x11/clutter-keymap-x11.h b/clutter/clutter/x11/clutter-keymap-x11.h new file mode 100644 index 0000000..ad673a2 --- /dev/null +++ b/clutter/clutter/x11/clutter-keymap-x11.h @@ -0,0 +1,56 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2009 Intel Corp. + * + * 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 . + * + * Author: Emmanuele Bassi + */ + +#ifndef __CLUTTER_KEYMAP_X11_H__ +#define __CLUTTER_KEYMAP_X11_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_KEYMAP_X11 (_clutter_keymap_x11_get_type ()) +#define CLUTTER_KEYMAP_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_KEYMAP_X11, ClutterKeymapX11)) +#define CLUTTER_IS_KEYMAP_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_KEYMAP_X11)) + +typedef struct _ClutterKeymapX11 ClutterKeymapX11; + +GType _clutter_keymap_x11_get_type (void) G_GNUC_CONST; + +gint _clutter_keymap_x11_get_key_group (ClutterKeymapX11 *keymap, + ClutterModifierType state); +gboolean _clutter_keymap_x11_get_num_lock_state (ClutterKeymapX11 *keymap); +gboolean _clutter_keymap_x11_get_caps_lock_state (ClutterKeymapX11 *keymap); +gint _clutter_keymap_x11_translate_key_state (ClutterKeymapX11 *keymap, + guint hardware_keycode, + ClutterModifierType *modifier_state_p, + ClutterModifierType *mods_p); +gboolean _clutter_keymap_x11_get_is_modifier (ClutterKeymapX11 *keymap, + gint keycode); + +PangoDirection _clutter_keymap_x11_get_direction (ClutterKeymapX11 *keymap); + +G_END_DECLS + +#endif /* __CLUTTER_KEYMAP_X11_H__ */ diff --git a/clutter/clutter/x11/clutter-settings-x11.h b/clutter/clutter/x11/clutter-settings-x11.h new file mode 100644 index 0000000..b06565b --- /dev/null +++ b/clutter/clutter/x11/clutter-settings-x11.h @@ -0,0 +1,28 @@ +#ifndef __CLUTTER_SETTINGS_X11_H__ +#define __CLUTTER_SETTINGS_X11_H__ + +/* XSETTINGS key names to ClutterSettings properties */ +static const struct { + const char *xsetting_name; + const char *settings_property; +} _clutter_settings_map[] = { + { "Net/DoubleClickTime", "double-click-time" }, + { "Net/DoubleClickDistance", "double-click-distance" }, + { "Net/DndDragThreshold", "dnd-drag-threshold" }, + { "Gtk/FontName", "font-name" }, + { "Xft/Antialias", "font-antialias" }, + { "Xft/DPI", "font-dpi" }, + { "Xft/Hinting", "font-hinting" }, + { "Xft/HintStyle", "font-hint-style" }, + { "Xft/RGBA", "font-subpixel-order" }, + { "Fontconfig/Timestamp", "fontconfig-timestamp" }, + { "Gdk/WindowScalingFactor", "window-scaling-factor" }, + { "Gdk/UnscaledDPI", "unscaled-font-dpi" }, +}; + +static const gint _n_clutter_settings_map = G_N_ELEMENTS (_clutter_settings_map); + +#define CLUTTER_SETTING_X11_NAME(id) (_clutter_settings_map[(id)].xsetting_name) +#define CLUTTER_SETTING_PROPERTY(id) (_clutter_settings_map[(id)].settings_property) + +#endif /* __CLUTTER_SETTINGS_X11_H__ */ diff --git a/clutter/clutter/x11/clutter-stage-x11.c b/clutter/clutter/x11/clutter-stage-x11.c new file mode 100644 index 0000000..39ff031 --- /dev/null +++ b/clutter/clutter/x11/clutter-stage-x11.c @@ -0,0 +1,1633 @@ +/* Clutter. + * An OpenGL based 'interactive canvas' library. + * Authored By Matthew Allum + * Copyright (C) 2006-2007 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +#include "clutter-build-config.h" + +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#include + +#include "clutter-backend-x11.h" +#include "clutter-stage-x11.h" +#include "clutter-x11.h" + +#include "clutter-actor-private.h" +#include "clutter-debug.h" +#include "clutter-device-manager-private.h" +#include "clutter-enum-types.h" +#include "clutter-event-translator.h" +#include "clutter-event-private.h" +#include "clutter-feature.h" +#include "clutter-main.h" +#include "clutter-mutter.h" +#include "clutter-paint-volume-private.h" +#include "clutter-private.h" +#include "clutter-stage-private.h" + +#define STAGE_X11_IS_MAPPED(s) ((((ClutterStageX11 *) (s))->wm_state & STAGE_X11_WITHDRAWN) == 0) + +static ClutterStageWindowIface *clutter_stage_window_parent_iface = NULL; + +static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface); +static void clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface); + +static ClutterStageCogl *clutter_x11_get_stage_window_from_window (Window win); + +static GHashTable *clutter_stages_by_xid = NULL; + +#define clutter_stage_x11_get_type _clutter_stage_x11_get_type + +G_DEFINE_TYPE_WITH_CODE (ClutterStageX11, + clutter_stage_x11, + CLUTTER_TYPE_STAGE_COGL, + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW, + clutter_stage_window_iface_init) + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_EVENT_TRANSLATOR, + clutter_event_translator_iface_init)); + +#define _NET_WM_STATE_REMOVE 0 /* remove/unset property */ +#define _NET_WM_STATE_ADD 1 /* add/set property */ +#define _NET_WM_STATE_TOGGLE 2 /* toggle property */ + +#define CLUTTER_STAGE_X11_EVENT_MASK \ + StructureNotifyMask | \ + FocusChangeMask | \ + ExposureMask | \ + PropertyChangeMask | \ + EnterWindowMask | \ + LeaveWindowMask | \ + KeyPressMask | \ + KeyReleaseMask | \ + ButtonPressMask | \ + ButtonReleaseMask | \ + PointerMotionMask + +static void +send_wmspec_change_state (ClutterBackendX11 *backend_x11, + Window window, + Atom state, + gboolean add) +{ + XClientMessageEvent xclient; + + CLUTTER_NOTE (BACKEND, "%s NET_WM state", add ? "adding" : "removing"); + + memset (&xclient, 0, sizeof (xclient)); + + xclient.type = ClientMessage; + xclient.window = window; + xclient.message_type = backend_x11->atom_NET_WM_STATE; + xclient.format = 32; + + xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; + xclient.data.l[1] = state; + xclient.data.l[2] = 0; + xclient.data.l[3] = 0; + xclient.data.l[4] = 0; + + XSendEvent (backend_x11->xdpy, + DefaultRootWindow (backend_x11->xdpy), + False, + SubstructureRedirectMask | SubstructureNotifyMask, + (XEvent *)&xclient); +} + +static void +update_state (ClutterStageX11 *stage_x11, + ClutterBackendX11 *backend_x11, + Atom *state, + gboolean add) +{ + if (add) + { + /* FIXME: This wont work if we support more states */ + XChangeProperty (backend_x11->xdpy, + stage_x11->xwin, + backend_x11->atom_NET_WM_STATE, XA_ATOM, 32, + PropModeReplace, + (unsigned char *) state, 1); + } + else + { + /* FIXME: This wont work if we support more states */ + XDeleteProperty (backend_x11->xdpy, + stage_x11->xwin, + backend_x11->atom_NET_WM_STATE); + } +} + +static void +clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11, + gint new_width, + gint new_height) +{ + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); + + if (stage_x11->xwin != None && !stage_x11->is_foreign_xwin) + { + guint min_width, min_height; + XSizeHints *size_hints; + gboolean resize; + + resize = clutter_stage_get_user_resizable (stage_cogl->wrapper); + + size_hints = XAllocSizeHints(); + + clutter_stage_get_minimum_size (stage_cogl->wrapper, + &min_width, + &min_height); + + if (new_width <= 0) + new_width = min_width * stage_x11->scale_factor; + + if (new_height <= 0) + new_height = min_height * stage_x11->scale_factor; + + size_hints->flags = 0; + + /* If we are going fullscreen then we don't want any + restrictions on the window size */ + if (!stage_x11->fullscreening) + { + if (resize) + { + size_hints->min_width = min_width * stage_x11->scale_factor; + size_hints->min_height = min_height * stage_x11->scale_factor; + size_hints->flags = PMinSize; + } + else + { + size_hints->min_width = new_width; + size_hints->min_height = new_height; + size_hints->max_width = new_width; + size_hints->max_height = new_height; + size_hints->flags = PMinSize | PMaxSize; + } + } + + XSetWMNormalHints (backend_x11->xdpy, stage_x11->xwin, size_hints); + + XFree(size_hints); + } +} + +static void +clutter_stage_x11_set_wm_protocols (ClutterStageX11 *stage_x11) +{ + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); + Atom protocols[2]; + int n = 0; + + protocols[n++] = backend_x11->atom_WM_DELETE_WINDOW; + protocols[n++] = backend_x11->atom_NET_WM_PING; + + XSetWMProtocols (backend_x11->xdpy, stage_x11->xwin, protocols, n); +} + +static void +clutter_stage_x11_get_geometry (ClutterStageWindow *stage_window, + cairo_rectangle_int_t *geometry) +{ + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); + + geometry->x = geometry->y = 0; + + /* If we're fullscreen, return the size of the display. + * + * FIXME - this is utterly broken for anything that is not a single + * head set up; the window manager will give us the right size in a + * ConfigureNotify, but between the fullscreen signal emission on the + * stage and the following frame, the size returned by the stage will + * be wrong. + */ + if (_clutter_stage_is_fullscreen (stage_cogl->wrapper) && + stage_x11->fullscreening) + { + geometry->width = DisplayWidth (backend_x11->xdpy, backend_x11->xscreen_num); + geometry->height = DisplayHeight (backend_x11->xdpy, backend_x11->xscreen_num); + + return; + } + + geometry->width = stage_x11->xwin_width / stage_x11->scale_factor; + geometry->height = stage_x11->xwin_height / stage_x11->scale_factor; +} + +static void +clutter_stage_x11_resize (ClutterStageWindow *stage_window, + gint width, + gint height) +{ + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); + + if (stage_x11->is_foreign_xwin) + { + /* If this is a foreign window we won't get a ConfigureNotify, + * so we need to manually set the size and queue a relayout on the + * stage here (as is normally done in response to ConfigureNotify). + */ + stage_x11->xwin_width = width * stage_x11->scale_factor; + stage_x11->xwin_height = height * stage_x11->scale_factor; + clutter_actor_queue_relayout (CLUTTER_ACTOR (stage_cogl->wrapper)); + return; + } + + /* If we're going fullscreen, don't mess with the size */ + if (stage_x11->fullscreening) + return; + + if (width == 0 || height == 0) + { + /* Should not happen, if this turns up we need to debug it and + * determine the cleanest way to fix. + */ + g_warning ("X11 stage not allowed to have 0 width or height"); + width = 1; + height = 1; + } + + CLUTTER_NOTE (BACKEND, "New size received: (%d, %d)", width, height); + + width *= stage_x11->scale_factor; + height *= stage_x11->scale_factor; + + if (stage_x11->xwin != None) + { + clutter_stage_x11_fix_window_size (stage_x11, width, height); + + if (width != stage_x11->xwin_width || + height != stage_x11->xwin_height) + { + CLUTTER_NOTE (BACKEND, "%s: XResizeWindow[%x] (%d, %d)", + G_STRLOC, + (unsigned int) stage_x11->xwin, + width, + height); + + /* XXX: in this case we can rely on a subsequent + * ConfigureNotify that will result in the stage + * being reallocated so we don't actively do anything + * to affect the stage allocation here. */ + XResizeWindow (backend_x11->xdpy, + stage_x11->xwin, + width, + height); + } + } + else + { + /* if the backing window hasn't been created yet, we just + * need to store the new window size + */ + stage_x11->xwin_width = width; + stage_x11->xwin_height = height; + } +} + +static inline void +set_wm_pid (ClutterStageX11 *stage_x11) +{ + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); + long pid; + + if (stage_x11->xwin == None || stage_x11->is_foreign_xwin) + return; + + /* this will take care of WM_CLIENT_MACHINE and WM_LOCALE_NAME */ + XSetWMProperties (backend_x11->xdpy, stage_x11->xwin, + NULL, + NULL, + NULL, 0, + NULL, NULL, NULL); + + pid = getpid (); + XChangeProperty (backend_x11->xdpy, + stage_x11->xwin, + backend_x11->atom_NET_WM_PID, XA_CARDINAL, 32, + PropModeReplace, + (guchar *) &pid, 1); +} + +static inline void +set_wm_title (ClutterStageX11 *stage_x11) +{ + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); + + if (stage_x11->xwin == None || stage_x11->is_foreign_xwin) + return; + + if (stage_x11->title == NULL) + { + XDeleteProperty (backend_x11->xdpy, + stage_x11->xwin, + backend_x11->atom_NET_WM_NAME); + } + else + { + XChangeProperty (backend_x11->xdpy, + stage_x11->xwin, + backend_x11->atom_NET_WM_NAME, + backend_x11->atom_UTF8_STRING, + 8, + PropModeReplace, + (unsigned char *) stage_x11->title, + (int) strlen (stage_x11->title)); + } +} + +static inline void +set_cursor_visible (ClutterStageX11 *stage_x11) +{ + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); + + if (stage_x11->xwin == None) + return; + + CLUTTER_NOTE (BACKEND, "setting cursor state ('%s') over stage window (%u)", + stage_x11->is_cursor_visible ? "visible" : "invisible", + (unsigned int) stage_x11->xwin); + + if (stage_x11->is_cursor_visible) + { + XUndefineCursor (backend_x11->xdpy, stage_x11->xwin); + } + else + { + XColor col; + Pixmap pix; + Cursor curs; + + pix = XCreatePixmap (backend_x11->xdpy, stage_x11->xwin, 1, 1, 1); + memset (&col, 0, sizeof (col)); + curs = XCreatePixmapCursor (backend_x11->xdpy, + pix, pix, + &col, &col, + 1, 1); + XFreePixmap (backend_x11->xdpy, pix); + XDefineCursor (backend_x11->xdpy, stage_x11->xwin, curs); + } +} + +static void +on_window_scaling_factor_notify (GObject *settings, + GParamSpec *pspec, + ClutterStageX11 *stage_x11) +{ + g_object_get (settings, + "window-scaling-factor", &stage_x11->scale_factor, + NULL); + + clutter_stage_x11_resize (CLUTTER_STAGE_WINDOW (stage_x11), + stage_x11->xwin_width, + stage_x11->xwin_height); +} + +static void +clutter_stage_x11_unrealize (ClutterStageWindow *stage_window) +{ + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); + + if (clutter_stages_by_xid != NULL) + { + CLUTTER_NOTE (BACKEND, "Removing X11 stage 0x%x [%p]", + (unsigned int) stage_x11->xwin, + stage_x11); + + g_hash_table_remove (clutter_stages_by_xid, + GINT_TO_POINTER (stage_x11->xwin)); + } + + /* Clutter still uses part of the deprecated stateful API of Cogl + * (in particulart cogl_set_framebuffer). It means Cogl can keep an + * internal reference to the onscreen object we rendered to. In the + * case of foreign window, we want to avoid this, as we don't know + * what's going to happen to that window. + * + * The following call sets the current Cogl framebuffer to a dummy + * 1x1 one if we're unrealizing the current one, so Cogl doesn't + * keep any reference to the foreign window. + */ + if (cogl_get_draw_framebuffer () == COGL_FRAMEBUFFER (stage_x11->onscreen)) + _clutter_backend_reset_cogl_framebuffer (stage_cogl->backend); + + if (stage_x11->frame_closure) + { + cogl_onscreen_remove_frame_callback (stage_x11->onscreen, + stage_x11->frame_closure); + stage_x11->frame_closure = NULL; + } + + clutter_stage_window_parent_iface->unrealize (stage_window); + + g_list_free (stage_x11->legacy_views); + g_clear_object (&stage_x11->legacy_view); + g_clear_pointer (&stage_x11->onscreen, cogl_object_unref); +} + +static void +_clutter_stage_x11_update_foreign_event_mask (CoglOnscreen *onscreen, + guint32 event_mask, + void *user_data) +{ + ClutterStageX11 *stage_x11 = user_data; + ClutterStageCogl *stage_cogl = user_data; + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); + XSetWindowAttributes attrs; + + attrs.event_mask = event_mask | CLUTTER_STAGE_X11_EVENT_MASK; + + XChangeWindowAttributes (backend_x11->xdpy, + stage_x11->xwin, + CWEventMask, + &attrs); +} + +static void +clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window, + gboolean is_fullscreen) +{ + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); + ClutterStage *stage = stage_cogl->wrapper; + gboolean was_fullscreen; + + if (stage == NULL || CLUTTER_ACTOR_IN_DESTRUCTION (stage)) + return; + + was_fullscreen = _clutter_stage_is_fullscreen (stage); + is_fullscreen = !!is_fullscreen; + + if (was_fullscreen == is_fullscreen) + return; + + CLUTTER_NOTE (BACKEND, "%ssetting fullscreen", is_fullscreen ? "" : "un"); + + if (is_fullscreen) + { +#if 0 + int width, height; + + /* FIXME: this will do the wrong thing for dual-headed + displays. This will return the size of the combined display + but Metacity (at least) will fullscreen to only one of the + displays. This will cause the actor to report the wrong size + until the ConfigureNotify for the correct size is received */ + width = DisplayWidth (backend_x11->xdpy, backend_x11->xscreen_num); + height = DisplayHeight (backend_x11->xdpy, backend_x11->xscreen_num); +#endif + + /* Set the fullscreen hint so we can retain the old size of the window. */ + stage_x11->fullscreening = TRUE; + + if (stage_x11->xwin != None) + { + /* if the actor is not mapped we resize the stage window to match + * the size of the screen; this is useful for e.g. EGLX to avoid + * a resize when calling clutter_stage_fullscreen() before showing + * the stage + */ + if (!STAGE_X11_IS_MAPPED (stage_x11)) + { + CLUTTER_NOTE (BACKEND, "Fullscreening unmapped stage"); + + update_state (stage_x11, backend_x11, + &backend_x11->atom_NET_WM_STATE_FULLSCREEN, + TRUE); + } + else + { + CLUTTER_NOTE (BACKEND, "Fullscreening mapped stage"); + + /* We need to fix the window size so that it will remove + the maximum and minimum window hints. Otherwise + metacity will honour the restrictions and not + fullscreen correctly. */ + clutter_stage_x11_fix_window_size (stage_x11, -1, -1); + + send_wmspec_change_state (backend_x11, stage_x11->xwin, + backend_x11->atom_NET_WM_STATE_FULLSCREEN, + TRUE); + } + } + else + stage_x11->fullscreen_on_realize = TRUE; + } + else + { + stage_x11->fullscreening = FALSE; + + if (stage_x11->xwin != None) + { + if (!STAGE_X11_IS_MAPPED (stage_x11)) + { + CLUTTER_NOTE (BACKEND, "Un-fullscreening unmapped stage"); + + update_state (stage_x11, backend_x11, + &backend_x11->atom_NET_WM_STATE_FULLSCREEN, + FALSE); + } + else + { + CLUTTER_NOTE (BACKEND, "Un-fullscreening mapped stage"); + + send_wmspec_change_state (backend_x11, + stage_x11->xwin, + backend_x11->atom_NET_WM_STATE_FULLSCREEN, + FALSE); + + /* Fix the window size to restore the minimum/maximum + restriction */ + clutter_stage_x11_fix_window_size (stage_x11, + stage_x11->xwin_width, + stage_x11->xwin_height); + } + } + else + stage_x11->fullscreen_on_realize = FALSE; + } + + /* XXX: Note we rely on the ConfigureNotify mechanism as the common + * mechanism to handle notifications of new X window sizes from the + * X server so we don't actively change the stage viewport here or + * queue a relayout etc. */ +} + +void +_clutter_stage_x11_events_device_changed (ClutterStageX11 *stage_x11, + ClutterInputDevice *device, + ClutterDeviceManager *device_manager) +{ + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + + if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_FLOATING) + _clutter_device_manager_select_stage_events (device_manager, + stage_cogl->wrapper); +} + +static void +stage_events_device_added (ClutterDeviceManager *device_manager, + ClutterInputDevice *device, + gpointer user_data) +{ + ClutterStageWindow *stage_window = user_data; + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); + + if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_FLOATING) + _clutter_device_manager_select_stage_events (device_manager, + stage_cogl->wrapper); +} + +static void +frame_cb (CoglOnscreen *onscreen, + CoglFrameEvent frame_event, + CoglFrameInfo *frame_info, + void *user_data) + +{ + ClutterStageCogl *stage_cogl = user_data; + ClutterFrameInfo clutter_frame_info = { + .frame_counter = cogl_frame_info_get_frame_counter (frame_info), + .presentation_time = cogl_frame_info_get_presentation_time (frame_info), + .refresh_rate = cogl_frame_info_get_refresh_rate (frame_info) + }; + + _clutter_stage_cogl_presented (stage_cogl, frame_event, &clutter_frame_info); +} + +static gboolean +clutter_stage_x11_realize (ClutterStageWindow *stage_window) +{ + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); + ClutterBackend *backend = CLUTTER_BACKEND (stage_cogl->backend); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend); + ClutterDeviceManager *device_manager; + gfloat width, height; + GError *error = NULL; + + clutter_actor_get_size (CLUTTER_ACTOR (stage_cogl->wrapper), &width, &height); + + CLUTTER_NOTE (BACKEND, "Wrapper size: %.2f x %.2f", width, height); + + width = width * (float) stage_x11->scale_factor; + height = height * (float) stage_x11->scale_factor; + + CLUTTER_NOTE (BACKEND, "Creating a new Cogl onscreen surface: %.2f x %.2f (factor: %d)", + width, height, + stage_x11->scale_factor); + + stage_x11->onscreen = cogl_onscreen_new (backend->cogl_context, width, height); + + cogl_onscreen_set_swap_throttled (stage_x11->onscreen, + _clutter_get_sync_to_vblank ()); + stage_x11->frame_closure = + cogl_onscreen_add_frame_callback (stage_x11->onscreen, + frame_cb, + stage_cogl, + NULL); + + if (stage_x11->legacy_view) + g_object_set (G_OBJECT (stage_x11->legacy_view), + "framebuffer", stage_x11->onscreen, + NULL); + + /* We just created a window of the size of the actor. No need to fix + the size of the stage, just update it. */ + stage_x11->xwin_width = width; + stage_x11->xwin_height = height; + + if (stage_x11->xwin != None) + { + cogl_x11_onscreen_set_foreign_window_xid (stage_x11->onscreen, + stage_x11->xwin, + _clutter_stage_x11_update_foreign_event_mask, + stage_x11); + + } + + if (!cogl_framebuffer_allocate (stage_x11->onscreen, &error)) + { + g_warning ("Failed to allocate stage: %s", error->message); + g_error_free (error); + cogl_object_unref (stage_x11->onscreen); + abort(); + } + + if (!(clutter_stage_window_parent_iface->realize (stage_window))) + return FALSE; + + if (stage_x11->xwin == None) + stage_x11->xwin = cogl_x11_onscreen_get_window_xid (stage_x11->onscreen); + + if (clutter_stages_by_xid == NULL) + clutter_stages_by_xid = g_hash_table_new (NULL, NULL); + + g_hash_table_insert (clutter_stages_by_xid, + GINT_TO_POINTER (stage_x11->xwin), + stage_x11); + + set_wm_pid (stage_x11); + set_wm_title (stage_x11); + set_cursor_visible (stage_x11); + + /* we unconditionally select input events even with event retrieval + * disabled because we need to guarantee that the Clutter internal + * state is maintained when calling clutter_x11_handle_event() without + * requiring applications or embedding toolkits to select events + * themselves. if we did that, we'd have to document the events to be + * selected, and also update applications and embedding toolkits each + * time we added a new mask, or a new class of events. + * + * see: http://bugzilla.clutter-project.org/show_bug.cgi?id=998 + * for the rationale of why we did conditional selection. it is now + * clear that a compositor should clear out the input region, since + * it cannot assume a perfectly clean slate coming from us. + * + * see: http://bugzilla.clutter-project.org/show_bug.cgi?id=2228 + * for an example of things that break if we do conditional event + * selection. + */ + XSelectInput (backend_x11->xdpy, stage_x11->xwin, CLUTTER_STAGE_X11_EVENT_MASK); + + /* input events also depent on the actual device, so we need to + * use the device manager to let every device select them, using + * the event mask we passed to XSelectInput as the template + */ + device_manager = clutter_device_manager_get_default (); + if (G_UNLIKELY (device_manager != NULL)) + { + _clutter_device_manager_select_stage_events (device_manager, + stage_cogl->wrapper); + + g_signal_connect (device_manager, "device-added", + G_CALLBACK (stage_events_device_added), + stage_window); + } + + clutter_stage_x11_fix_window_size (stage_x11, + stage_x11->xwin_width, + stage_x11->xwin_height); + clutter_stage_x11_set_wm_protocols (stage_x11); + + if (stage_x11->fullscreen_on_realize) + { + stage_x11->fullscreen_on_realize = FALSE; + + clutter_stage_x11_set_fullscreen (stage_window, TRUE); + } + + CLUTTER_NOTE (BACKEND, "Successfully realized stage"); + + return TRUE; +} + +static void +clutter_stage_x11_set_cursor_visible (ClutterStageWindow *stage_window, + gboolean cursor_visible) +{ + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); + + stage_x11->is_cursor_visible = !!cursor_visible; + set_cursor_visible (stage_x11); +} + +static void +clutter_stage_x11_set_title (ClutterStageWindow *stage_window, + const gchar *title) +{ + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); + + g_free (stage_x11->title); + stage_x11->title = g_strdup (title); + set_wm_title (stage_x11); +} + +static void +clutter_stage_x11_set_user_resizable (ClutterStageWindow *stage_window, + gboolean is_resizable) +{ + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); + + clutter_stage_x11_fix_window_size (stage_x11, + stage_x11->xwin_width, + stage_x11->xwin_height); +} + +static inline void +update_wm_hints (ClutterStageX11 *stage_x11) +{ + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); + XWMHints wm_hints; + + if (stage_x11->wm_state & STAGE_X11_WITHDRAWN) + return; + + if (stage_x11->is_foreign_xwin) + return; + + wm_hints.flags = StateHint | InputHint; + wm_hints.initial_state = NormalState; + wm_hints.input = stage_x11->accept_focus ? True : False; + + XSetWMHints (backend_x11->xdpy, stage_x11->xwin, &wm_hints); +} + +static void +clutter_stage_x11_set_accept_focus (ClutterStageWindow *stage_window, + gboolean accept_focus) +{ + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); + + stage_x11->accept_focus = !!accept_focus; + update_wm_hints (stage_x11); +} + +static void +set_stage_x11_state (ClutterStageX11 *stage_x11, + ClutterStageX11State unset_flags, + ClutterStageX11State set_flags) +{ + ClutterStageX11State new_stage_state, old_stage_state; + + old_stage_state = stage_x11->wm_state; + + new_stage_state = old_stage_state; + new_stage_state |= set_flags; + new_stage_state &= ~unset_flags; + + if (new_stage_state == old_stage_state) + return; + + stage_x11->wm_state = new_stage_state; +} + +static void +clutter_stage_x11_show (ClutterStageWindow *stage_window, + gboolean do_raise) +{ + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); + + if (stage_x11->xwin != None) + { + if (do_raise && !stage_x11->is_foreign_xwin) + { + CLUTTER_NOTE (BACKEND, "Raising stage[%lu]", + (unsigned long) stage_x11->xwin); + XRaiseWindow (backend_x11->xdpy, stage_x11->xwin); + } + + if (!STAGE_X11_IS_MAPPED (stage_x11)) + { + CLUTTER_NOTE (BACKEND, "Mapping stage[%lu]", + (unsigned long) stage_x11->xwin); + + set_stage_x11_state (stage_x11, STAGE_X11_WITHDRAWN, 0); + + update_wm_hints (stage_x11); + + if (stage_x11->fullscreening) + clutter_stage_x11_set_fullscreen (stage_window, TRUE); + else + clutter_stage_x11_set_fullscreen (stage_window, FALSE); + } + + g_assert (STAGE_X11_IS_MAPPED (stage_x11)); + + clutter_actor_map (CLUTTER_ACTOR (stage_cogl->wrapper)); + + if (!stage_x11->is_foreign_xwin) + XMapWindow (backend_x11->xdpy, stage_x11->xwin); + } +} + +static void +clutter_stage_x11_hide (ClutterStageWindow *stage_window) +{ + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); + + if (stage_x11->xwin != None) + { + if (STAGE_X11_IS_MAPPED (stage_x11)) + set_stage_x11_state (stage_x11, 0, STAGE_X11_WITHDRAWN); + + g_assert (!STAGE_X11_IS_MAPPED (stage_x11)); + + clutter_actor_unmap (CLUTTER_ACTOR (stage_cogl->wrapper)); + + if (!stage_x11->is_foreign_xwin) + XWithdrawWindow (backend_x11->xdpy, stage_x11->xwin, 0); + } +} + +static gboolean +clutter_stage_x11_can_clip_redraws (ClutterStageWindow *stage_window) +{ + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); + + /* while resizing a window, clipped redraws are disabled in order to + * avoid artefacts. + */ + return stage_x11->clipped_redraws_cool_off == 0; +} + +static void +clutter_stage_x11_set_scale_factor (ClutterStageWindow *stage_window, + int factor) +{ + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); + + if (stage_x11->scale_factor == factor) + return; + + stage_x11->scale_factor = factor; + + clutter_stage_x11_resize (stage_window, stage_x11->xwin_width, stage_x11->xwin_height); +} + +static int +clutter_stage_x11_get_scale_factor (ClutterStageWindow *stage_window) +{ + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); + + return stage_x11->scale_factor; +} + +static void +ensure_legacy_view (ClutterStageWindow *stage_window) +{ + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); + cairo_rectangle_int_t view_layout; + CoglFramebuffer *framebuffer; + + if (stage_x11->legacy_view) + return; + + _clutter_stage_window_get_geometry (stage_window, &view_layout); + framebuffer = COGL_FRAMEBUFFER (stage_x11->onscreen); + stage_x11->legacy_view = g_object_new (CLUTTER_TYPE_STAGE_VIEW_COGL, + "layout", &view_layout, + "framebuffer", framebuffer, + NULL); + stage_x11->legacy_views = g_list_append (stage_x11->legacy_views, + stage_x11->legacy_view); +} + +static GList * +clutter_stage_x11_get_views (ClutterStageWindow *stage_window) +{ + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); + + ensure_legacy_view (stage_window); + + return stage_x11->legacy_views; +} + +static int64_t +clutter_stage_x11_get_frame_counter (ClutterStageWindow *stage_window) +{ + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); + + return cogl_onscreen_get_frame_counter (stage_x11->onscreen); +} + +static void +clutter_stage_x11_finalize (GObject *gobject) +{ + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (gobject); + + g_free (stage_x11->title); + + G_OBJECT_CLASS (clutter_stage_x11_parent_class)->finalize (gobject); +} + +static void +clutter_stage_x11_dispose (GObject *gobject) +{ + ClutterEventTranslator *translator = CLUTTER_EVENT_TRANSLATOR (gobject); + ClutterBackend *backend = CLUTTER_STAGE_COGL (gobject)->backend; + + _clutter_backend_remove_event_translator (backend, translator); + + G_OBJECT_CLASS (clutter_stage_x11_parent_class)->dispose (gobject); +} + +static void +clutter_stage_x11_class_init (ClutterStageX11Class *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = clutter_stage_x11_finalize; + gobject_class->dispose = clutter_stage_x11_dispose; +} + +static void +clutter_stage_x11_init (ClutterStageX11 *stage) +{ + ClutterSettings *settings; + + stage->xwin = None; + stage->xwin_width = 640; + stage->xwin_height = 480; + + stage->wm_state = STAGE_X11_WITHDRAWN; + + stage->is_foreign_xwin = FALSE; + stage->fullscreening = FALSE; + stage->is_cursor_visible = TRUE; + stage->accept_focus = TRUE; + + stage->title = NULL; + + settings = clutter_settings_get_default (); + g_signal_connect (settings, "notify::window-scaling-factor", + G_CALLBACK (on_window_scaling_factor_notify), + stage); + on_window_scaling_factor_notify (G_OBJECT (settings), NULL, stage); +} + +static void +clutter_stage_window_iface_init (ClutterStageWindowIface *iface) +{ + clutter_stage_window_parent_iface = g_type_interface_peek_parent (iface); + + iface->set_title = clutter_stage_x11_set_title; + iface->set_fullscreen = clutter_stage_x11_set_fullscreen; + iface->set_cursor_visible = clutter_stage_x11_set_cursor_visible; + iface->set_user_resizable = clutter_stage_x11_set_user_resizable; + iface->set_accept_focus = clutter_stage_x11_set_accept_focus; + iface->show = clutter_stage_x11_show; + iface->hide = clutter_stage_x11_hide; + iface->resize = clutter_stage_x11_resize; + iface->get_geometry = clutter_stage_x11_get_geometry; + iface->realize = clutter_stage_x11_realize; + iface->unrealize = clutter_stage_x11_unrealize; + iface->can_clip_redraws = clutter_stage_x11_can_clip_redraws; + iface->set_scale_factor = clutter_stage_x11_set_scale_factor; + iface->get_scale_factor = clutter_stage_x11_get_scale_factor; + iface->get_views = clutter_stage_x11_get_views; + iface->get_frame_counter = clutter_stage_x11_get_frame_counter; +} + +static inline void +set_user_time (ClutterBackendX11 *backend_x11, + ClutterStageX11 *stage_x11, + long timestamp) +{ + if (timestamp != CLUTTER_CURRENT_TIME) + { + XChangeProperty (backend_x11->xdpy, + stage_x11->xwin, + backend_x11->atom_NET_WM_USER_TIME, + XA_CARDINAL, 32, + PropModeReplace, + (unsigned char *) ×tamp, 1); + } +} + +static gboolean +handle_wm_protocols_event (ClutterBackendX11 *backend_x11, + ClutterStageX11 *stage_x11, + XEvent *xevent) +{ + Atom atom = (Atom) xevent->xclient.data.l[0]; + + if (atom == backend_x11->atom_WM_DELETE_WINDOW && + xevent->xany.window == stage_x11->xwin) + { +#ifdef CLUTTER_ENABLE_DEBUG + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + + /* the WM_DELETE_WINDOW is a request: we do not destroy + * the window right away, as it might contain vital data; + * we relay the event to the application and we let it + * handle the request + */ + CLUTTER_NOTE (EVENT, "Delete stage %s[%p], win:0x%x", + _clutter_actor_get_debug_name (CLUTTER_ACTOR (stage_cogl->wrapper)), + stage_cogl->wrapper, + (unsigned int) stage_x11->xwin); +#endif /* CLUTTER_ENABLE_DEBUG */ + + set_user_time (backend_x11, stage_x11, xevent->xclient.data.l[1]); + + return TRUE; + } + else if (atom == backend_x11->atom_NET_WM_PING && + xevent->xany.window == stage_x11->xwin) + { + XClientMessageEvent xclient = xevent->xclient; + + xclient.window = backend_x11->xwin_root; + XSendEvent (backend_x11->xdpy, xclient.window, + False, + SubstructureRedirectMask | SubstructureNotifyMask, + (XEvent *) &xclient); + return FALSE; + } + + /* do not send any of the WM_PROTOCOLS events to the queue */ + return FALSE; +} + +static gboolean +clipped_redraws_cool_off_cb (void *data) +{ + ClutterStageX11 *stage_x11 = data; + + stage_x11->clipped_redraws_cool_off = 0; + + return G_SOURCE_REMOVE; +} + +static ClutterTranslateReturn +clutter_stage_x11_translate_event (ClutterEventTranslator *translator, + gpointer native, + ClutterEvent *event) +{ + ClutterStageX11 *stage_x11; + ClutterStageCogl *stage_cogl; + ClutterTranslateReturn res = CLUTTER_TRANSLATE_CONTINUE; + ClutterBackendX11 *backend_x11; + Window stage_xwindow; + XEvent *xevent = native; + ClutterStage *stage; + + stage_cogl = clutter_x11_get_stage_window_from_window (xevent->xany.window); + if (stage_cogl == NULL) + return CLUTTER_TRANSLATE_CONTINUE; + + stage = stage_cogl->wrapper; + stage_x11 = CLUTTER_STAGE_X11 (stage_cogl); + backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); + stage_xwindow = stage_x11->xwin; + + switch (xevent->type) + { + case ConfigureNotify: + if (!stage_x11->is_foreign_xwin) + { + gboolean size_changed = FALSE; + int stage_width; + int stage_height; + + CLUTTER_NOTE (BACKEND, "ConfigureNotify[%x] (%d, %d)", + (unsigned int) stage_x11->xwin, + xevent->xconfigure.width, + xevent->xconfigure.height); + + /* When fullscreen, we'll keep the xwin_width/height + variables to track the old size of the window and we'll + assume all ConfigureNotifies constitute a size change */ + if (_clutter_stage_is_fullscreen (stage)) + size_changed = TRUE; + else if ((stage_x11->xwin_width != xevent->xconfigure.width) || + (stage_x11->xwin_height != xevent->xconfigure.height)) + { + size_changed = TRUE; + stage_x11->xwin_width = xevent->xconfigure.width; + stage_x11->xwin_height = xevent->xconfigure.height; + } + + stage_width = xevent->xconfigure.width / stage_x11->scale_factor; + stage_height = xevent->xconfigure.height / stage_x11->scale_factor; + clutter_actor_set_size (CLUTTER_ACTOR (stage), stage_width, stage_height); + + if (size_changed) + { + /* XXX: This is a workaround for a race condition when + * resizing windows while there are in-flight + * glXCopySubBuffer blits happening. + * + * The problem stems from the fact that rectangles for the + * blits are described relative to the bottom left of the + * window and because we can't guarantee control over the X + * window gravity used when resizing so the gravity is + * typically NorthWest not SouthWest. + * + * This means if you grow a window vertically the server + * will make sure to place the old contents of the window + * at the top-left/north-west of your new larger window, but + * that may happen asynchronous to GLX preparing to do a + * blit specified relative to the bottom-left/south-west of + * the window (based on the old smaller window geometry). + * + * When the GLX issued blit finally happens relative to the + * new bottom of your window, the destination will have + * shifted relative to the top-left where all the pixels you + * care about are so it will result in a nasty artefact + * making resizing look very ugly! + * + * We can't currently fix this completely, in-part because + * the window manager tends to trample any gravity we might + * set. This workaround instead simply disables blits for a + * while if we are notified of any resizes happening so if + * the user is resizing a window via the window manager then + * they may see an artefact for one frame but then we will + * fallback to redrawing the full stage until the cooling + * off period is over. + */ + if (stage_x11->clipped_redraws_cool_off) + g_source_remove (stage_x11->clipped_redraws_cool_off); + + stage_x11->clipped_redraws_cool_off = + clutter_threads_add_timeout (1000, + clipped_redraws_cool_off_cb, + stage_x11); + + /* Queue a relayout - we want glViewport to be called + * with the correct values, and this is done in ClutterStage + * via cogl_onscreen_clutter_backend_set_size (). + * + * We queue a relayout, because if this ConfigureNotify is + * in response to a size we set in the application, the + * set_size() call above is essentially a null-op. + * + * Make sure we do this only when the size has changed, + * otherwise we end up relayouting on window moves. + */ + clutter_actor_queue_relayout (CLUTTER_ACTOR (stage)); + + /* the resize process is complete, so we can ask the stage + * to set up the GL viewport with the new size + */ + clutter_stage_ensure_viewport (stage); + + /* If this was a result of the Xrandr change when running as a + * X11 compositing manager, we need to reset the legacy + * stage view, now that it has a new size. + */ + if (stage_x11->legacy_view) + { + cairo_rectangle_int_t view_layout = { + .width = stage_width, + .height = stage_height + }; + + g_object_set (G_OBJECT (stage_x11->legacy_view), + "layout", &view_layout, + NULL); + } + } + } + break; + + case PropertyNotify: + if (xevent->xproperty.atom == backend_x11->atom_NET_WM_STATE && + xevent->xproperty.window == stage_xwindow && + !stage_x11->is_foreign_xwin) + { + Atom type; + gint format; + gulong n_items, bytes_after; + guchar *data = NULL; + gboolean fullscreen_set = FALSE; + + clutter_x11_trap_x_errors (); + XGetWindowProperty (backend_x11->xdpy, stage_xwindow, + backend_x11->atom_NET_WM_STATE, + 0, G_MAXLONG, + False, XA_ATOM, + &type, &format, &n_items, + &bytes_after, &data); + clutter_x11_untrap_x_errors (); + + if (type != None && data != NULL) + { + gboolean is_fullscreen = FALSE; + Atom *atoms = (Atom *) data; + gulong i; + + for (i = 0; i < n_items; i++) + { + if (atoms[i] == backend_x11->atom_NET_WM_STATE_FULLSCREEN) + fullscreen_set = TRUE; + } + + is_fullscreen = _clutter_stage_is_fullscreen (stage_cogl->wrapper); + + if (fullscreen_set != is_fullscreen) + { + if (fullscreen_set) + _clutter_stage_update_state (stage_cogl->wrapper, + 0, + CLUTTER_STAGE_STATE_FULLSCREEN); + else + _clutter_stage_update_state (stage_cogl->wrapper, + CLUTTER_STAGE_STATE_FULLSCREEN, + 0); + } + + XFree (data); + } + } + break; + + case FocusIn: + if (!_clutter_stage_is_activated (stage_cogl->wrapper)) + { + _clutter_stage_update_state (stage_cogl->wrapper, + 0, + CLUTTER_STAGE_STATE_ACTIVATED); + } + break; + + case FocusOut: + if (_clutter_stage_is_activated (stage_cogl->wrapper)) + { + _clutter_stage_update_state (stage_cogl->wrapper, + CLUTTER_STAGE_STATE_ACTIVATED, + 0); + } + break; + + case Expose: + { + XExposeEvent *expose = (XExposeEvent *) xevent; + cairo_rectangle_int_t clip; + + CLUTTER_NOTE (EVENT, + "expose for stage: %s[%p], win:0x%x - " + "redrawing area (x: %d, y: %d, width: %d, height: %d)", + _clutter_actor_get_debug_name (CLUTTER_ACTOR (stage)), + stage, + (unsigned int) stage_xwindow, + expose->x, + expose->y, + expose->width, + expose->height); + + clip.x = expose->x / stage_x11->scale_factor; + clip.y = expose->y / stage_x11->scale_factor; + clip.width = expose->width / stage_x11->scale_factor; + clip.height = expose->height / stage_x11->scale_factor; + clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip); + } + break; + + case DestroyNotify: + CLUTTER_NOTE (EVENT, + "Destroy notification received for stage %s[%p], win:0x%x", + _clutter_actor_get_debug_name (CLUTTER_ACTOR (stage)), + stage, + (unsigned int) stage_xwindow); + event->any.type = CLUTTER_DESTROY_NOTIFY; + event->any.stage = stage; + res = CLUTTER_TRANSLATE_QUEUE; + break; + + case ClientMessage: + CLUTTER_NOTE (EVENT, "Client message for stage %s[%p], win:0x%x", + _clutter_actor_get_debug_name (CLUTTER_ACTOR (stage)), + stage, + (unsigned int) stage_xwindow); + if (handle_wm_protocols_event (backend_x11, stage_x11, xevent)) + { + event->any.type = CLUTTER_DELETE; + event->any.stage = stage; + res = CLUTTER_TRANSLATE_QUEUE; + } + break; + + case MappingNotify: + CLUTTER_NOTE (EVENT, "Refresh keyboard mapping"); + XRefreshKeyboardMapping (&xevent->xmapping); + backend_x11->keymap_serial += 1; + res = CLUTTER_TRANSLATE_REMOVE; + break; + + default: + res = CLUTTER_TRANSLATE_CONTINUE; + break; + } + + return res; +} + +static void +clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface) +{ + iface->translate_event = clutter_stage_x11_translate_event; +} + +/** + * clutter_x11_get_stage_window: (skip) + * @stage: a #ClutterStage + * + * Gets the stages X Window. + * + * Return value: An XID for the stage window. + * + * Since: 0.4 + */ +Window +clutter_x11_get_stage_window (ClutterStage *stage) +{ + ClutterStageWindow *impl; + + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), None); + + impl = _clutter_stage_get_window (stage); + g_assert (CLUTTER_IS_STAGE_X11 (impl)); + + return CLUTTER_STAGE_X11 (impl)->xwin; +} + +static ClutterStageCogl * +clutter_x11_get_stage_window_from_window (Window win) +{ + if (clutter_stages_by_xid == NULL) + return NULL; + + return g_hash_table_lookup (clutter_stages_by_xid, + GINT_TO_POINTER (win)); +} + +/** + * clutter_x11_get_stage_from_window: + * @win: an X Window ID + * + * Gets the stage for a particular X window. + * + * Return value: (transfer none): A #ClutterStage, or% NULL if a stage + * does not exist for the window + * + * Since: 0.8 + */ +ClutterStage * +clutter_x11_get_stage_from_window (Window win) +{ + ClutterStageCogl *stage_cogl; + + stage_cogl = clutter_x11_get_stage_window_from_window (win); + + if (stage_cogl != NULL) + return stage_cogl->wrapper; + + return NULL; +} + +/** + * clutter_x11_get_stage_visual: (skip) + * @stage: a #ClutterStage + * + * Returns an XVisualInfo suitable for creating a foreign window for the given + * stage. NOTE: It doesn't do as the name may suggest, which is return the + * XVisualInfo that was used to create an existing window for the given stage. + * + * XXX: It might be best to deprecate this function and replace with something + * along the lines of clutter_backend_x11_get_foreign_visual () or perhaps + * clutter_stage_x11_get_foreign_visual () + * + * Return value: (transfer full): An XVisualInfo suitable for creating a + * foreign stage. Use XFree() to free the returned value instead + * + * Deprecated: 1.2: Use clutter_x11_get_visual_info() instead + * + * Since: 0.4 + */ +XVisualInfo * +clutter_x11_get_stage_visual (ClutterStage *stage) +{ + ClutterBackend *backend = clutter_get_default_backend (); + ClutterBackendX11 *backend_x11; + + g_return_val_if_fail (CLUTTER_IS_BACKEND_X11 (backend), NULL); + backend_x11 = CLUTTER_BACKEND_X11 (backend); + + return _clutter_backend_x11_get_visual_info (backend_x11); +} + +typedef struct { + ClutterStageX11 *stage_x11; + cairo_rectangle_int_t geom; + Window xwindow; + guint destroy_old_xwindow : 1; +} ForeignWindowData; + +static void +set_foreign_window_callback (ClutterActor *actor, + void *data) +{ + ForeignWindowData *fwd = data; + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (fwd->stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); + + CLUTTER_NOTE (BACKEND, "Setting foreign window (0x%x)", + (unsigned int) fwd->xwindow); + + if (fwd->destroy_old_xwindow && fwd->stage_x11->xwin != None) + { + CLUTTER_NOTE (BACKEND, "Destroying previous window (0x%x)", + (unsigned int) fwd->xwindow); + XDestroyWindow (backend_x11->xdpy, fwd->stage_x11->xwin); + } + + fwd->stage_x11->xwin = fwd->xwindow; + fwd->stage_x11->is_foreign_xwin = TRUE; + + fwd->stage_x11->xwin_width = fwd->geom.width * fwd->stage_x11->scale_factor; + fwd->stage_x11->xwin_height = fwd->geom.height * fwd->stage_x11->scale_factor; + + clutter_actor_set_size (actor, fwd->geom.width, fwd->geom.height); + + if (clutter_stages_by_xid == NULL) + clutter_stages_by_xid = g_hash_table_new (NULL, NULL); + + g_hash_table_insert (clutter_stages_by_xid, + GINT_TO_POINTER (fwd->stage_x11->xwin), + fwd->stage_x11); +} + +/** + * clutter_x11_set_stage_foreign: + * @stage: a #ClutterStage + * @xwindow: an existing X Window id + * + * Target the #ClutterStage to use an existing external X Window + * + * Return value: %TRUE if foreign window is valid + * + * Since: 0.4 + */ +gboolean +clutter_x11_set_stage_foreign (ClutterStage *stage, + Window xwindow) +{ + ClutterBackendX11 *backend_x11; + ClutterStageX11 *stage_x11; + ClutterStageCogl *stage_cogl; + ClutterStageWindow *impl; + ClutterActor *actor; + gint x, y; + guint width, height, border, depth; + Window root_return; + Status status; + ForeignWindowData fwd; + XVisualInfo *xvisinfo; + + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); + g_return_val_if_fail (!CLUTTER_ACTOR_IN_DESTRUCTION (stage), FALSE); + g_return_val_if_fail (xwindow != None, FALSE); + + impl = _clutter_stage_get_window (stage); + stage_x11 = CLUTTER_STAGE_X11 (impl); + stage_cogl = CLUTTER_STAGE_COGL (impl); + backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); + + xvisinfo = _clutter_backend_x11_get_visual_info (backend_x11); + g_return_val_if_fail (xvisinfo != NULL, FALSE); + + clutter_x11_trap_x_errors (); + + status = XGetGeometry (backend_x11->xdpy, xwindow, + &root_return, + &x, &y, + &width, &height, + &border, + &depth); + + if (clutter_x11_untrap_x_errors () || !status) + { + g_critical ("Unable to retrieve the geometry of the foreign window: " + "XGetGeometry() failed (status code: %d)", status); + return FALSE; + } + + if (width == 0 || height == 0) + { + g_warning ("The size of the foreign window is 0x0"); + return FALSE; + } + + if (depth != xvisinfo->depth) + { + g_warning ("The depth of the visual of the foreign window is %d, but " + "Clutter has been initialized to require a visual depth " + "of %d", + depth, + xvisinfo->depth); + return FALSE; + } + + fwd.stage_x11 = stage_x11; + fwd.xwindow = xwindow; + + /* destroy the old Window, if we have one and it's ours */ + if (stage_x11->xwin != None && !stage_x11->is_foreign_xwin) + fwd.destroy_old_xwindow = TRUE; + else + fwd.destroy_old_xwindow = FALSE; + + fwd.geom.x = x; + fwd.geom.y = y; + fwd.geom.width = width / stage_x11->scale_factor; + fwd.geom.height = height / stage_x11->scale_factor; + + actor = CLUTTER_ACTOR (stage); + + _clutter_actor_rerealize (actor, + set_foreign_window_callback, + &fwd); + + /* Queue a relayout - so the stage will be allocated the new + * window size. + * + * Note also that when the stage gets allocated the new + * window size that will result in the stage's + * priv->viewport being changed, which will in turn result + * in the Cogl viewport changing when _clutter_do_redraw + * calls _clutter_stage_maybe_setup_viewport(). + */ + clutter_actor_queue_relayout (actor); + + return TRUE; +} + +void +_clutter_stage_x11_set_user_time (ClutterStageX11 *stage_x11, + guint32 user_time) +{ + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); + + set_user_time (backend_x11, stage_x11, user_time); +} diff --git a/clutter/clutter/x11/clutter-stage-x11.h b/clutter/clutter/x11/clutter-stage-x11.h new file mode 100644 index 0000000..98ba53b --- /dev/null +++ b/clutter/clutter/x11/clutter-stage-x11.h @@ -0,0 +1,100 @@ +/* Clutter. + * An OpenGL based 'interactive canvas' library. + * Authored By Matthew Allum + * Copyright (C) 2006-2007 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +#ifndef __CLUTTER_STAGE_X11_H__ +#define __CLUTTER_STAGE_X11_H__ + +#include +#include +#include +#include + +#include "clutter-backend-x11.h" +#include "cogl/clutter-stage-cogl.h" + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_STAGE_X11 (_clutter_stage_x11_get_type ()) +#define CLUTTER_STAGE_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STAGE_X11, ClutterStageX11)) +#define CLUTTER_IS_STAGE_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_STAGE_X11)) +#define CLUTTER_STAGE_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_STAGE_X11, ClutterStageX11Class)) +#define CLUTTER_IS_STAGE_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_STAGE_X11)) +#define CLUTTER_STAGE_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_STAGE_X11, ClutterStageX11Class)) + +typedef struct _ClutterStageX11 ClutterStageX11; +typedef struct _ClutterStageX11Class ClutterStageX11Class; + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterStageX11, g_object_unref) + +typedef enum +{ + STAGE_X11_WITHDRAWN = 1 << 1 +} ClutterStageX11State; + +struct _ClutterStageX11 +{ + ClutterStageCogl parent_instance; + + CoglOnscreen *onscreen; + Window xwin; + gint xwin_width; + gint xwin_height; /* FIXME target_width / height */ + + ClutterStageView *legacy_view; + GList *legacy_views; + + CoglFrameClosure *frame_closure; + + gchar *title; + + guint clipped_redraws_cool_off; + + ClutterStageX11State wm_state; + + int scale_factor; + + guint is_foreign_xwin : 1; + guint fullscreening : 1; + guint is_cursor_visible : 1; + guint viewport_initialized : 1; + guint accept_focus : 1; + guint fullscreen_on_realize : 1; +}; + +struct _ClutterStageX11Class +{ + ClutterStageCoglClass parent_class; +}; + +CLUTTER_AVAILABLE_IN_MUTTER +GType _clutter_stage_x11_get_type (void) G_GNUC_CONST; + +void _clutter_stage_x11_events_device_changed (ClutterStageX11 *stage_x11, + ClutterInputDevice *device, + ClutterDeviceManager *device_manager); + +/* Private to subclasses */ +void _clutter_stage_x11_set_user_time (ClutterStageX11 *stage_x11, + guint32 user_time); + +G_END_DECLS + +#endif /* __CLUTTER_STAGE_H__ */ diff --git a/clutter/clutter/x11/clutter-virtual-input-device-x11.c b/clutter/clutter/x11/clutter-virtual-input-device-x11.c new file mode 100644 index 0000000..a13915b --- /dev/null +++ b/clutter/clutter/x11/clutter-virtual-input-device-x11.c @@ -0,0 +1,89 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2016 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: Jonas Ådahl + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include + +#include "clutter-virtual-input-device.h" +#include "x11/clutter-virtual-input-device-x11.h" + +struct _ClutterVirtualInputDeviceX11 +{ + ClutterVirtualInputDevice parent; +}; + +G_DEFINE_TYPE (ClutterVirtualInputDeviceX11, + clutter_virtual_input_device_x11, + CLUTTER_TYPE_VIRTUAL_INPUT_DEVICE) + +static void +clutter_virtual_input_device_x11_notify_relative_motion (ClutterVirtualInputDevice *virtual_device, + uint64_t time_us, + double dx, + double dy) +{ +} + +static void +clutter_virtual_input_device_x11_notify_absolute_motion (ClutterVirtualInputDevice *virtual_device, + uint64_t time_us, + double x, + double y) +{ +} + +static void +clutter_virtual_input_device_x11_notify_button (ClutterVirtualInputDevice *virtual_device, + uint64_t time_us, + uint32_t button, + ClutterButtonState button_state) +{ +} + +static void +clutter_virtual_input_device_x11_notify_key (ClutterVirtualInputDevice *virtual_device, + uint64_t time_us, + uint32_t key, + ClutterKeyState key_state) +{ +} + +static void +clutter_virtual_input_device_x11_init (ClutterVirtualInputDeviceX11 *virtual_device_x11) +{ +} + +static void +clutter_virtual_input_device_x11_class_init (ClutterVirtualInputDeviceX11Class *klass) +{ + ClutterVirtualInputDeviceClass *virtual_input_device_class = + CLUTTER_VIRTUAL_INPUT_DEVICE_CLASS (klass); + + virtual_input_device_class->notify_relative_motion = clutter_virtual_input_device_x11_notify_relative_motion; + virtual_input_device_class->notify_absolute_motion = clutter_virtual_input_device_x11_notify_absolute_motion; + virtual_input_device_class->notify_button = clutter_virtual_input_device_x11_notify_button; + virtual_input_device_class->notify_key = clutter_virtual_input_device_x11_notify_key; +} diff --git a/clutter/clutter/x11/clutter-virtual-input-device-x11.h b/clutter/clutter/x11/clutter-virtual-input-device-x11.h new file mode 100644 index 0000000..b1bb101 --- /dev/null +++ b/clutter/clutter/x11/clutter-virtual-input-device-x11.h @@ -0,0 +1,35 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2016 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: Jonas Ådahl + */ + +#ifndef __CLUTTER_VIRTUAL_INPUT_DEVICE_X11_H__ +#define __CLUTTER_VIRTUAL_INPUT_DEVICE_X11_H__ + +#include "clutter-virtual-input-device.h" + +#define CLUTTER_TYPE_VIRTUAL_INPUT_DEVICE_X11 (clutter_virtual_input_device_x11_get_type ()) +G_DECLARE_FINAL_TYPE (ClutterVirtualInputDeviceX11, + clutter_virtual_input_device_x11, + CLUTTER, VIRTUAL_INPUT_DEVICE_X11, + ClutterVirtualInputDevice) + +#endif /* __CLUTTER_VIRTUAL_INPUT_DEVICE_X11_H__ */ diff --git a/clutter/clutter/x11/clutter-x11-texture-pixmap.c b/clutter/clutter/x11/clutter-x11-texture-pixmap.c new file mode 100644 index 0000000..7c1152f --- /dev/null +++ b/clutter/clutter/x11/clutter-x11-texture-pixmap.c @@ -0,0 +1,1270 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2007 OpenedHand + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: + * Johan Bilien + * Neil Roberts + */ + +/** + * SECTION:clutter-x11-texture-pixmap + * @Title: ClutterX11TexturePixmap + * @short_description: A texture which displays the content of an X Pixmap. + * + * #ClutterX11TexturePixmap is a class for displaying the content of an + * X Pixmap as a ClutterActor. Used together with the X Composite extension, + * it allows to display the content of X Windows inside Clutter. + * + * The class uses the GLX_EXT_texture_from_pixmap OpenGL extension + * (http://people.freedesktop.org/~davidr/GLX_EXT_texture_from_pixmap.txt) + * if available + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#define CLUTTER_ENABLE_EXPERIMENTAL_API +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS + +#include "clutter-x11-texture-pixmap.h" +#include "clutter-x11.h" +#include "clutter-backend-x11.h" + +#include "clutter-actor-private.h" +#include "clutter-marshal.h" +#include "clutter-paint-volume-private.h" +#include "clutter-private.h" + +#include + +#include + +#include + +#if HAVE_XCOMPOSITE +#include +#endif + +enum +{ + PROP_PIXMAP = 1, + PROP_PIXMAP_WIDTH, + PROP_PIXMAP_HEIGHT, + PROP_DEPTH, + PROP_AUTO, + PROP_WINDOW, + PROP_WINDOW_REDIRECT_AUTOMATIC, + PROP_WINDOW_MAPPED, + PROP_DESTROYED, + PROP_WINDOW_X, + PROP_WINDOW_Y, + PROP_WINDOW_OVERRIDE_REDIRECT +}; + +enum +{ + UPDATE_AREA, + QUEUE_DAMAGE_REDRAW, + + /* FIXME: Pixmap lost signal? */ + LAST_SIGNAL +}; + +static ClutterX11FilterReturn +on_x_event_filter (XEvent *xev, ClutterEvent *cev, gpointer data); + +static void +clutter_x11_texture_pixmap_update_area_real (ClutterX11TexturePixmap *texture, + gint x, + gint y, + gint width, + gint height); +static void +clutter_x11_texture_pixmap_sync_window_internal (ClutterX11TexturePixmap *texture, + int x, + int y, + int width, + int height, + gboolean override_redirect); +static void +clutter_x11_texture_pixmap_set_mapped (ClutterX11TexturePixmap *texture, gboolean mapped); +static void +clutter_x11_texture_pixmap_destroyed (ClutterX11TexturePixmap *texture); + +static guint signals[LAST_SIGNAL] = { 0, }; + +struct _ClutterX11TexturePixmapPrivate +{ + Window window; + Pixmap pixmap; + guint pixmap_width, pixmap_height; + guint depth; + + Damage damage; + + gint window_x, window_y; + gint window_width, window_height; + + guint window_redirect_automatic : 1; + /* FIXME: this is inconsistently either whether the window is mapped or whether + * it is viewable, and isn't updated correctly. */ + guint window_mapped : 1; + guint destroyed : 1; + guint owns_pixmap : 1; + guint override_redirect : 1; + guint automatic_updates : 1; +}; + +static int _damage_event_base = 0; + +G_DEFINE_TYPE_WITH_PRIVATE (ClutterX11TexturePixmap, + clutter_x11_texture_pixmap, + CLUTTER_TYPE_TEXTURE) + +static gboolean +check_extensions (ClutterX11TexturePixmap *texture) +{ + int damage_error; + Display *dpy; + + if (_damage_event_base) + return TRUE; + + dpy = clutter_x11_get_default_display(); + + if (!XDamageQueryExtension (dpy, &_damage_event_base, &damage_error)) + { + g_warning ("No Damage extension"); + return FALSE; + } + + return TRUE; +} + +static void +process_damage_event (ClutterX11TexturePixmap *texture, + XDamageNotifyEvent *damage_event) +{ + /* Cogl will deal with updating the texture and subtracting from the + damage region so we only need to queue a redraw */ + g_signal_emit (texture, signals[QUEUE_DAMAGE_REDRAW], + 0, + damage_event->area.x, + damage_event->area.y, + damage_event->area.width, + damage_event->area.height); +} + +static ClutterX11FilterReturn +on_x_event_filter (XEvent *xev, ClutterEvent *cev, gpointer data) +{ + ClutterX11TexturePixmap *texture; + ClutterX11TexturePixmapPrivate *priv; + + texture = CLUTTER_X11_TEXTURE_PIXMAP (data); + + g_return_val_if_fail (CLUTTER_X11_IS_TEXTURE_PIXMAP (texture), \ + CLUTTER_X11_FILTER_CONTINUE); + + priv = texture->priv; + + if (xev->type == _damage_event_base + XDamageNotify) + { + XDamageNotifyEvent *dev = (XDamageNotifyEvent*)xev; + + if (dev->damage != priv->damage) + return CLUTTER_X11_FILTER_CONTINUE; + + process_damage_event (texture, dev); + } + + return CLUTTER_X11_FILTER_CONTINUE; +} + +static ClutterX11FilterReturn +on_x_event_filter_too (XEvent *xev, ClutterEvent *cev, gpointer data) +{ + ClutterX11TexturePixmap *texture; + ClutterX11TexturePixmapPrivate *priv; + + texture = CLUTTER_X11_TEXTURE_PIXMAP (data); + + g_return_val_if_fail (CLUTTER_X11_IS_TEXTURE_PIXMAP (texture), \ + CLUTTER_X11_FILTER_CONTINUE); + + priv = texture->priv; + + if (xev->xany.window != priv->window) + return CLUTTER_X11_FILTER_CONTINUE; + + switch (xev->type) { + case MapNotify: + clutter_x11_texture_pixmap_sync_window_internal (texture, + priv->window_x, + priv->window_y, + priv->window_width, + priv->window_height, + priv->override_redirect); + break; + case ConfigureNotify: + clutter_x11_texture_pixmap_sync_window_internal (texture, + xev->xconfigure.x, + xev->xconfigure.y, + xev->xconfigure.width, + xev->xconfigure.height, + xev->xconfigure.override_redirect); + break; + case UnmapNotify: + clutter_x11_texture_pixmap_set_mapped (texture, FALSE); + break; + case DestroyNotify: + clutter_x11_texture_pixmap_destroyed (texture); + break; + default: + break; + } + + return CLUTTER_X11_FILTER_CONTINUE; +} + +static void +update_pixmap_damage_object (ClutterX11TexturePixmap *texture) +{ + ClutterX11TexturePixmapPrivate *priv = texture->priv; + CoglHandle cogl_texture; + + /* If we already have a CoglTexturePixmapX11 then update its + damage object */ + cogl_texture = + clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (texture)); + + if (cogl_texture && cogl_is_texture_pixmap_x11 (cogl_texture)) + { + if (priv->damage) + { + const CoglTexturePixmapX11ReportLevel report_level = + COGL_TEXTURE_PIXMAP_X11_DAMAGE_BOUNDING_BOX; + cogl_texture_pixmap_x11_set_damage_object (cogl_texture, + priv->damage, + report_level); + } + else + cogl_texture_pixmap_x11_set_damage_object (cogl_texture, 0, 0); + } +} + +static void +create_damage_resources (ClutterX11TexturePixmap *texture) +{ + ClutterX11TexturePixmapPrivate *priv; + Display *dpy; + + priv = texture->priv; + dpy = clutter_x11_get_default_display(); + + if (!priv->pixmap) + return; + + clutter_x11_trap_x_errors (); + + priv->damage = XDamageCreate (dpy, + priv->pixmap, + XDamageReportBoundingBox); + + /* Errors here might occur if the window is already destroyed, we + * simply skip processing damage and assume that the texture pixmap + * will be cleaned up by the app when it gets a DestroyNotify. + */ + XSync (dpy, FALSE); + clutter_x11_untrap_x_errors (); + + if (priv->damage) + { + clutter_x11_add_filter (on_x_event_filter, (gpointer)texture); + + update_pixmap_damage_object (texture); + } +} + +static void +free_damage_resources (ClutterX11TexturePixmap *texture) +{ + ClutterX11TexturePixmapPrivate *priv; + Display *dpy; + + priv = texture->priv; + dpy = clutter_x11_get_default_display(); + + if (priv->damage) + { + clutter_x11_trap_x_errors (); + XDamageDestroy (dpy, priv->damage); + XSync (dpy, FALSE); + clutter_x11_untrap_x_errors (); + priv->damage = None; + + clutter_x11_remove_filter (on_x_event_filter, (gpointer)texture); + + update_pixmap_damage_object (texture); + } +} + +static gboolean +clutter_x11_texture_pixmap_get_paint_volume (ClutterActor *self, + ClutterPaintVolume *volume) +{ + return clutter_paint_volume_set_from_allocation (volume, self); +} + +static void +clutter_x11_texture_pixmap_real_queue_damage_redraw ( + ClutterX11TexturePixmap *texture, + gint x, + gint y, + gint width, + gint height) +{ + ClutterX11TexturePixmapPrivate *priv = texture->priv; + ClutterActor *self = CLUTTER_ACTOR (texture); + ClutterActorBox allocation; + float scale_x, scale_y; + cairo_rectangle_int_t clip; + + /* NB: clutter_actor_queue_clipped_redraw expects a box in the actor's + * coordinate space so we need to convert from pixmap coordinates to + * actor coordinates... + */ + + /* Calling clutter_actor_get_allocation_box() is enormously expensive + * if the actor has an out-of-date allocation, since it triggers + * a full redraw. clutter_actor_queue_clipped_redraw() would redraw + * the whole stage anyways in that case, so just go ahead and do + * it here. + */ + if (!clutter_actor_has_allocation (self)) + { + clutter_actor_queue_redraw (self); + return; + } + + if (priv->pixmap_width == 0 || priv->pixmap_height == 0) + return; + + clutter_actor_get_allocation_box (self, &allocation); + + scale_x = (allocation.x2 - allocation.x1) / priv->pixmap_width; + scale_y = (allocation.y2 - allocation.y1) / priv->pixmap_height; + + clip.x = x * scale_x; + clip.y = y * scale_y; + clip.width = width * scale_x; + clip.height = height * scale_y; + clutter_actor_queue_redraw_with_clip (self, &clip); +} + +static void +clutter_x11_texture_pixmap_init (ClutterX11TexturePixmap *self) +{ + self->priv = clutter_x11_texture_pixmap_get_instance_private (self); + + if (!check_extensions (self)) + { + /* FIMXE: means display lacks needed extensions for at least auto. + * - a _can_autoupdate() method ? + */ + } + + self->priv->automatic_updates = FALSE; + self->priv->damage = None; + self->priv->window = None; + self->priv->pixmap = None; + self->priv->pixmap_height = 0; + self->priv->pixmap_width = 0; + self->priv->window_redirect_automatic = TRUE; + self->priv->window_mapped = FALSE; + self->priv->destroyed = FALSE; + self->priv->override_redirect = FALSE; + self->priv->window_x = 0; + self->priv->window_y = 0; +} + +static void +clutter_x11_texture_pixmap_dispose (GObject *object) +{ + ClutterX11TexturePixmap *texture = CLUTTER_X11_TEXTURE_PIXMAP (object); + + free_damage_resources (texture); + + clutter_x11_remove_filter (on_x_event_filter_too, (gpointer)texture); + clutter_x11_texture_pixmap_set_pixmap (texture, None); + + G_OBJECT_CLASS (clutter_x11_texture_pixmap_parent_class)->dispose (object); +} + +static void +clutter_x11_texture_pixmap_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterX11TexturePixmap *texture = CLUTTER_X11_TEXTURE_PIXMAP (object); + ClutterX11TexturePixmapPrivate *priv = texture->priv; + + switch (prop_id) + { + case PROP_PIXMAP: + clutter_x11_texture_pixmap_set_pixmap (texture, + g_value_get_ulong (value)); + break; + case PROP_AUTO: + clutter_x11_texture_pixmap_set_automatic (texture, + g_value_get_boolean (value)); + break; + case PROP_WINDOW: + clutter_x11_texture_pixmap_set_window (texture, + g_value_get_ulong (value), + priv->window_redirect_automatic); + break; + case PROP_WINDOW_REDIRECT_AUTOMATIC: + { + gboolean new; + new = g_value_get_boolean (value); + + /* Change the update mode.. */ + if (new != priv->window_redirect_automatic && priv->window) + clutter_x11_texture_pixmap_set_window (texture, priv->window, new); + + priv->window_redirect_automatic = new; + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_x11_texture_pixmap_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterX11TexturePixmap *texture = CLUTTER_X11_TEXTURE_PIXMAP (object); + ClutterX11TexturePixmapPrivate *priv = texture->priv; + + switch (prop_id) + { + case PROP_PIXMAP: + g_value_set_ulong (value, priv->pixmap); + break; + case PROP_PIXMAP_WIDTH: + g_value_set_uint (value, priv->pixmap_width); + break; + case PROP_PIXMAP_HEIGHT: + g_value_set_uint (value, priv->pixmap_height); + break; + case PROP_DEPTH: + g_value_set_uint (value, priv->depth); + break; + case PROP_AUTO: + g_value_set_boolean (value, priv->automatic_updates); + break; + case PROP_WINDOW: + g_value_set_ulong (value, priv->window); + break; + case PROP_WINDOW_REDIRECT_AUTOMATIC: + g_value_set_boolean (value, priv->window_redirect_automatic); + break; + case PROP_WINDOW_MAPPED: + g_value_set_boolean (value, priv->window_mapped); + break; + case PROP_DESTROYED: + g_value_set_boolean (value, priv->destroyed); + break; + case PROP_WINDOW_X: + g_value_set_int (value, priv->window_x); + break; + case PROP_WINDOW_Y: + g_value_set_int (value, priv->window_y); + break; + case PROP_WINDOW_OVERRIDE_REDIRECT: + g_value_set_boolean (value, priv->override_redirect); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_x11_texture_pixmap_class_init (ClutterX11TexturePixmapClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + GParamSpec *pspec; + + actor_class->get_paint_volume = clutter_x11_texture_pixmap_get_paint_volume; + + object_class->dispose = clutter_x11_texture_pixmap_dispose; + object_class->set_property = clutter_x11_texture_pixmap_set_property; + object_class->get_property = clutter_x11_texture_pixmap_get_property; + + klass->update_area = clutter_x11_texture_pixmap_update_area_real; + + pspec = g_param_spec_ulong ("pixmap", + P_("Pixmap"), + P_("The X11 Pixmap to be bound"), + 0, G_MAXULONG, + None, + G_PARAM_READWRITE); + + g_object_class_install_property (object_class, PROP_PIXMAP, pspec); + + pspec = g_param_spec_uint ("pixmap-width", + P_("Pixmap width"), + P_("The width of the pixmap bound to this texture"), + 0, G_MAXUINT, + 0, + G_PARAM_READABLE); + + g_object_class_install_property (object_class, PROP_PIXMAP_WIDTH, pspec); + + pspec = g_param_spec_uint ("pixmap-height", + P_("Pixmap height"), + P_("The height of the pixmap bound to this texture"), + 0, G_MAXUINT, + 0, + G_PARAM_READABLE); + + g_object_class_install_property (object_class, PROP_PIXMAP_HEIGHT, pspec); + + pspec = g_param_spec_uint ("pixmap-depth", + P_("Pixmap Depth"), + P_("The depth (in number of bits) of the pixmap bound to this texture"), + 0, G_MAXUINT, + 0, + G_PARAM_READABLE); + + g_object_class_install_property (object_class, PROP_DEPTH, pspec); + + pspec = g_param_spec_boolean ("automatic-updates", + P_("Automatic Updates"), + P_("If the texture should be kept in " + "sync with any pixmap changes."), + FALSE, + G_PARAM_READWRITE); + + g_object_class_install_property (object_class, PROP_AUTO, pspec); + + pspec = g_param_spec_ulong ("window", + P_("Window"), + P_("The X11 Window to be bound"), + 0, G_MAXULONG, + None, + G_PARAM_READWRITE); + + g_object_class_install_property (object_class, PROP_WINDOW, pspec); + + pspec = g_param_spec_boolean ("window-redirect-automatic", + P_("Window Redirect Automatic"), + P_("If composite window redirects are set to " + "Automatic (or Manual if false)"), + TRUE, + G_PARAM_READWRITE); + + g_object_class_install_property (object_class, + PROP_WINDOW_REDIRECT_AUTOMATIC, pspec); + + + pspec = g_param_spec_boolean ("window-mapped", + P_("Window Mapped"), + P_("If window is mapped"), + FALSE, + G_PARAM_READABLE); + + g_object_class_install_property (object_class, + PROP_WINDOW_MAPPED, pspec); + + + pspec = g_param_spec_boolean ("destroyed", + P_("Destroyed"), + P_("If window has been destroyed"), + FALSE, + G_PARAM_READABLE); + + g_object_class_install_property (object_class, + PROP_DESTROYED, pspec); + + pspec = g_param_spec_int ("window-x", + P_("Window X"), + P_("X position of window on screen according to X11"), + G_MININT, G_MAXINT, 0, G_PARAM_READABLE); + + g_object_class_install_property (object_class, + PROP_WINDOW_X, pspec); + + + pspec = g_param_spec_int ("window-y", + P_("Window Y"), + P_("Y position of window on screen according to X11"), + G_MININT, G_MAXINT, 0, G_PARAM_READABLE); + + g_object_class_install_property (object_class, + PROP_WINDOW_Y, pspec); + + pspec = g_param_spec_boolean ("window-override-redirect", + P_("Window Override Redirect"), + P_("If this is an override-redirect window"), + FALSE, + G_PARAM_READABLE); + + g_object_class_install_property (object_class, + PROP_WINDOW_OVERRIDE_REDIRECT, pspec); + + + /** + * ClutterX11TexturePixmap::update-area: + * @texture: the object which received the signal + * @x: X coordinate of the area to update + * @y: Y coordinate of the area to update + * @width: width of the area to update + * @height: height of the area to update + * + * The ::update-area signal is emitted to ask the texture to update its + * content from its source pixmap. + * + * Since: 0.8 + */ + signals[UPDATE_AREA] = + g_signal_new (g_intern_static_string ("update-area"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ClutterX11TexturePixmapClass, \ + update_area), + NULL, NULL, + _clutter_marshal_VOID__INT_INT_INT_INT, + G_TYPE_NONE, 4, + G_TYPE_INT, + G_TYPE_INT, + G_TYPE_INT, + G_TYPE_INT); + + /** + * ClutterX11TexturePixmap::queue-damage-redraw: + * @texture: the object which received the signal + * @x: The top left x position of the damage region + * @y: The top left y position of the damage region + * @width: The width of the damage region + * @height: The height of the damage region + * + * ::queue-damage-redraw is emitted to notify that some sub-region + * of the texture has been changed (either by an automatic damage + * update or by an explicit call to + * clutter_x11_texture_pixmap_update_area). This usually means a + * redraw needs to be queued for the actor. + * + * The default handler will queue a clipped redraw in response to + * the damage, using the assumption that the pixmap is being painted + * to a rectangle covering the transformed allocation of the actor. + * If you sub-class and change the paint method so this isn't true + * then you must also provide your own damage signal handler to + * queue a redraw that blocks this default behaviour. + * + * Since: 1.2 + */ + signals[QUEUE_DAMAGE_REDRAW] = + g_signal_new (g_intern_static_string ("queue-damage-redraw"), + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + _clutter_marshal_VOID__INT_INT_INT_INT, + G_TYPE_NONE, 4, + G_TYPE_INT, + G_TYPE_INT, + G_TYPE_INT, + G_TYPE_INT); + + g_signal_override_class_handler ("queue-damage-redraw", + CLUTTER_X11_TYPE_TEXTURE_PIXMAP, + G_CALLBACK (clutter_x11_texture_pixmap_real_queue_damage_redraw)); +} + +static void +clutter_x11_texture_pixmap_update_area_real (ClutterX11TexturePixmap *texture, + gint x, + gint y, + gint width, + gint height) +{ + CoglHandle cogl_texture; + + cogl_texture = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (texture)); + + if (cogl_texture) + cogl_texture_pixmap_x11_update_area (cogl_texture, x, y, width, height); +} + +/** + * clutter_x11_texture_pixmap_new: + * + * Creates a new #ClutterX11TexturePixmap which can be used to display the + * contents of an X11 Pixmap inside a Clutter scene graph + * + * Return value: A new #ClutterX11TexturePixmap + * + * Since: 0.8 + */ +ClutterActor * +clutter_x11_texture_pixmap_new (void) +{ + ClutterActor *actor; + + actor = g_object_new (CLUTTER_X11_TYPE_TEXTURE_PIXMAP, NULL); + + return actor; +} + +/** + * clutter_x11_texture_pixmap_new_with_pixmap: + * @pixmap: the X Pixmap to which this texture should be bound + * + * Creates a new #ClutterX11TexturePixmap for @pixmap + * + * Return value: A new #ClutterX11TexturePixmap bound to the given X Pixmap + * + * Since: 0.8 + */ +ClutterActor * +clutter_x11_texture_pixmap_new_with_pixmap (Pixmap pixmap) +{ + ClutterActor *actor; + + actor = g_object_new (CLUTTER_X11_TYPE_TEXTURE_PIXMAP, + "pixmap", pixmap, + NULL); + + return actor; +} + +/** + * clutter_x11_texture_pixmap_new_with_window: + * @window: the X window to which this texture should be bound + * + * Creates a new #ClutterX11TexturePixmap for @window + * + * Return value: A new #ClutterX11TexturePixmap bound to the given X window. + * + * Since: 0.8 + **/ +ClutterActor * +clutter_x11_texture_pixmap_new_with_window (Window window) +{ + ClutterActor *actor; + + actor = g_object_new (CLUTTER_X11_TYPE_TEXTURE_PIXMAP, + "window", window, + NULL); + + return actor; +} + +/** + * clutter_x11_texture_pixmap_set_pixmap: + * @texture: the texture to bind + * @pixmap: the X Pixmap to which the texture should be bound + * + * Sets the X Pixmap to which the texture should be bound. + * + * Since: 0.8 + */ +void +clutter_x11_texture_pixmap_set_pixmap (ClutterX11TexturePixmap *texture, + Pixmap pixmap) +{ + Window root; + int x, y; + unsigned int width, height, border_width, depth; + Status status = 0; + gboolean new_pixmap = FALSE, new_pixmap_width = FALSE; + gboolean new_pixmap_height = FALSE, new_pixmap_depth = FALSE; + CoglPipeline *pipeline; + + ClutterX11TexturePixmapPrivate *priv; + + g_return_if_fail (CLUTTER_X11_IS_TEXTURE_PIXMAP (texture)); + + priv = texture->priv; + + /* Get rid of the existing Cogl texture early because it may try to + use the pixmap which we might destroy */ + pipeline = (CoglPipeline *) + clutter_texture_get_cogl_material (CLUTTER_TEXTURE (texture)); + if (pipeline) + cogl_pipeline_set_layer_texture (pipeline, 0, NULL); + + if (pixmap != None) + { + clutter_x11_trap_x_errors (); + status = XGetGeometry (clutter_x11_get_default_display(), + (Drawable)pixmap, + &root, + &x, + &y, + &width, + &height, + &border_width, + &depth); + + if (clutter_x11_untrap_x_errors () || status == 0) + { + g_warning ("Unable to query pixmap: %lx", pixmap); + pixmap = None; + width = height = depth = 0; + } + } + else + { + width = height = depth = 0; + } + + if (priv->pixmap != pixmap) + { + if (priv->pixmap && priv->owns_pixmap) + XFreePixmap (clutter_x11_get_default_display (), priv->pixmap); + + priv->pixmap = pixmap; + new_pixmap = TRUE; + + /* The damage object is created on the pixmap, so it needs to be + * recreated with a change in pixmap. + */ + if (priv->automatic_updates) + { + free_damage_resources (texture); + create_damage_resources (texture); + } + } + + if (priv->pixmap_width != width) + { + priv->pixmap_width = width; + new_pixmap_width = TRUE; + } + + if (priv->pixmap_height != height) + { + priv->pixmap_height = height; + new_pixmap_height = TRUE; + } + + if (priv->depth != depth) + { + priv->depth = depth; + new_pixmap_depth = TRUE; + } + + /* NB: We defer sending the signals until updating all the + * above members so the values are all available to the + * signal handlers. */ + g_object_ref (texture); + + if (new_pixmap) + g_object_notify (G_OBJECT (texture), "pixmap"); + if (new_pixmap_width) + g_object_notify (G_OBJECT (texture), "pixmap-width"); + if (new_pixmap_height) + g_object_notify (G_OBJECT (texture), "pixmap-height"); + if (new_pixmap_depth) + g_object_notify (G_OBJECT (texture), "pixmap-depth"); + + if (pixmap) + { + CoglContext *ctx = + clutter_backend_get_cogl_context (clutter_get_default_backend ()); + GError *error = NULL; + CoglTexturePixmapX11 *texture_pixmap = + cogl_texture_pixmap_x11_new (ctx, pixmap, FALSE, &error); + if (texture_pixmap) + { + clutter_texture_set_cogl_texture (CLUTTER_TEXTURE (texture), + COGL_TEXTURE (texture_pixmap)); + cogl_object_unref (texture_pixmap); + update_pixmap_damage_object (texture); + } + else + { + g_warning ("Failed to create CoglTexturePixmapX11: %s", + error->message); + g_error_free (error); + } + } + + /* + * Keep ref until here in case a notify causes removal from the scene; can't + * lower the notifies because glx's notify handler needs to run before + * update_area + */ + g_object_unref (texture); +} + +/** + * clutter_x11_texture_pixmap_set_window: + * @texture: the texture to bind + * @window: the X window to which the texture should be bound + * @automatic: %TRUE for automatic window updates, %FALSE for manual. + * + * Sets up a suitable pixmap for the window, using the composite and damage + * extensions if possible, and then calls + * clutter_x11_texture_pixmap_set_pixmap(). + * + * If you want to display a window in a #ClutterTexture, you probably want + * this function, or its older sister, clutter_glx_texture_pixmap_set_window(). + * + * This function has no effect unless the XComposite extension is available. + * + * Since: 0.8 + */ +void +clutter_x11_texture_pixmap_set_window (ClutterX11TexturePixmap *texture, + Window window, + gboolean automatic) +{ + ClutterX11TexturePixmapPrivate *priv; + XWindowAttributes attr; + Display *dpy; + + g_return_if_fail (CLUTTER_X11_IS_TEXTURE_PIXMAP (texture)); + + if (!clutter_x11_has_composite_extension ()) + return; + + dpy = clutter_x11_get_default_display (); + if (dpy == NULL) + return; + +#if HAVE_XCOMPOSITE + priv = texture->priv; + + if (priv->window == window && automatic == priv->window_redirect_automatic) + return; + + if (priv->window) + { + clutter_x11_remove_filter (on_x_event_filter_too, (gpointer)texture); + clutter_x11_trap_x_errors (); + XCompositeUnredirectWindow(clutter_x11_get_default_display (), + priv->window, + priv->window_redirect_automatic ? + CompositeRedirectAutomatic : CompositeRedirectManual); + XSync (clutter_x11_get_default_display (), False); + clutter_x11_untrap_x_errors (); + + clutter_x11_texture_pixmap_set_pixmap (texture, None); + } + + priv->window = window; + priv->window_redirect_automatic = automatic; + priv->window_mapped = FALSE; + priv->destroyed = FALSE; + + if (window == None) + return; + + clutter_x11_trap_x_errors (); + { + if (!XGetWindowAttributes (dpy, window, &attr)) + { + XSync (dpy, False); + clutter_x11_untrap_x_errors (); + g_warning ("bad window 0x%x", (guint32)window); + priv->window = None; + return; + } + + XCompositeRedirectWindow + (dpy, + window, + automatic ? + CompositeRedirectAutomatic : CompositeRedirectManual); + XSync (dpy, False); + } + + clutter_x11_untrap_x_errors (); + + XSelectInput (dpy, priv->window, + attr.your_event_mask | StructureNotifyMask); + clutter_x11_add_filter (on_x_event_filter_too, (gpointer)texture); + + g_object_ref (texture); + g_object_notify (G_OBJECT (texture), "window"); + + clutter_x11_texture_pixmap_set_mapped (texture, + attr.map_state == IsViewable); + + clutter_x11_texture_pixmap_sync_window_internal (texture, + attr.x, attr.y, + attr.width, attr.height, + attr.override_redirect); + g_object_unref (texture); + +#endif /* HAVE_XCOMPOSITE */ +} + +static void +clutter_x11_texture_pixmap_sync_window_internal (ClutterX11TexturePixmap *texture, + int x, + int y, + int width, + int height, + gboolean override_redirect) +{ + ClutterX11TexturePixmapPrivate *priv; + Pixmap pixmap = None; + gboolean mapped = FALSE; + gboolean notify_x = FALSE; + gboolean notify_y = FALSE; + gboolean notify_override_redirect = FALSE; + + priv = texture->priv; + + if (priv->destroyed) + return; + + notify_x = x != priv->window_x; + notify_y = y != priv->window_y; + notify_override_redirect = override_redirect != priv->override_redirect; + priv->window_x = x; + priv->window_y = y; + priv->window_width = width; + priv->window_height = height; + priv->override_redirect = override_redirect; + + if (!clutter_x11_has_composite_extension ()) + { + /* FIXME: this should just be an error, this is unlikely to work worth anything */ + clutter_x11_texture_pixmap_set_pixmap (texture, priv->window); + return; + } + + if (priv->pixmap == None || width != priv->pixmap_width || height != priv->pixmap_height) + { + /* Note that we're checking the size from the event against the size we obtained + * from the last XCompositeNameWindowPixmap/XGetGeometry pair. This will always + * end up right in the end, but we can have a series like: + * + * Window sized to 100x100 + * Window sized to 110x110 + * Window sized to 120x120 + * Configure received for 100x100 - NameWindowPixmap + * Configure received for 110x110 - NameWindowPixmap + * Configure received for 120x120 - last size OK + * + * Where we NameWindowPixmap several times in a row. (Using pixmap_width/pixmap_height + * rather than window_width/window_height saves the last one.) + */ + + Display *dpy = clutter_x11_get_default_display (); + + /* NB: It's only valid to name a pixmap if the window is viewable. + * + * We don't explicitly check this though since there would be a race + * between checking and naming unless we use a server grab which is + * undesireable. + * + * Instead we gracefully handle any error with naming the pixmap. + */ + clutter_x11_trap_x_errors (); + + pixmap = XCompositeNameWindowPixmap (dpy, priv->window); + + /* Possible improvement: combine with the XGetGeometry in + * clutter_x11_texture_pixmap_set_pixmap() */ + XSync(dpy, False); + + if (clutter_x11_untrap_x_errors ()) + pixmap = None; + } + + g_object_ref (texture); /* guard against unparent */ + g_object_freeze_notify (G_OBJECT (texture)); + + /* FIXME: mapped is always FALSE */ + clutter_x11_texture_pixmap_set_mapped (texture, mapped); + + if (pixmap) + { + clutter_x11_texture_pixmap_set_pixmap (texture, pixmap); + priv->owns_pixmap = TRUE; + } + + if (notify_override_redirect) + g_object_notify (G_OBJECT (texture), "window-override-redirect"); + if (notify_x) + g_object_notify (G_OBJECT (texture), "window-x"); + if (notify_y) + g_object_notify (G_OBJECT (texture), "window-y"); + + g_object_thaw_notify (G_OBJECT (texture)); + g_object_unref (texture); +} + +/** + * clutter_x11_texture_pixmap_sync_window: + * @texture: the texture to bind + * + * Resets the texture's pixmap from its window, perhaps in response to the + * pixmap's invalidation as the window changed size. + * + * Since: 0.8 + */ +void +clutter_x11_texture_pixmap_sync_window (ClutterX11TexturePixmap *texture) +{ + ClutterX11TexturePixmapPrivate *priv; + + g_return_if_fail (CLUTTER_X11_IS_TEXTURE_PIXMAP (texture)); + + priv = texture->priv; + + if (priv->destroyed) + return; + + if (priv->window != None) + { + Display *dpy = clutter_x11_get_default_display (); + XWindowAttributes attr; + Status status; + + if (dpy == NULL) + return; + + clutter_x11_trap_x_errors (); + + status = XGetWindowAttributes (dpy, priv->window, &attr); + if (status != 0) + clutter_x11_texture_pixmap_sync_window_internal (texture, + attr.x, attr.y, + attr.width, attr.height, + attr.override_redirect); + + clutter_x11_untrap_x_errors (); + } +} + +static void +clutter_x11_texture_pixmap_set_mapped (ClutterX11TexturePixmap *texture, + gboolean mapped) +{ + ClutterX11TexturePixmapPrivate *priv; + + priv = texture->priv; + + if (mapped != priv->window_mapped) + { + priv->window_mapped = mapped; + g_object_notify (G_OBJECT (texture), "window-mapped"); + } +} + +static void +clutter_x11_texture_pixmap_destroyed (ClutterX11TexturePixmap *texture) +{ + ClutterX11TexturePixmapPrivate *priv; + + priv = texture->priv; + + if (!priv->destroyed) + { + priv->destroyed = TRUE; + g_object_notify (G_OBJECT (texture), "destroyed"); + } + + /* + * Don't set window to None, that would destroy the pixmap, which might still + * be useful e.g. for destroy animations -- app's responsibility. + */ +} + +/** + * clutter_x11_texture_pixmap_update_area: + * @texture: The texture whose content shall be updated. + * @x: the X coordinate of the area to update + * @y: the Y coordinate of the area to update + * @width: the width of the area to update + * @height: the height of the area to update + * + * Performs the actual binding of texture to the current content of + * the pixmap. Can be called to update the texture if the pixmap + * content has changed. + * + * Since: 0.8 + **/ +void +clutter_x11_texture_pixmap_update_area (ClutterX11TexturePixmap *texture, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (CLUTTER_X11_IS_TEXTURE_PIXMAP (texture)); + + g_signal_emit (texture, signals[UPDATE_AREA], 0, x, y, width, height); + + /* The default handler for the "queue-damage-redraw" signal is + * clutter_x11_texture_pixmap_real_queue_damage_redraw which will queue a + * clipped redraw. */ + g_signal_emit (texture, signals[QUEUE_DAMAGE_REDRAW], + 0, x, y, width, height); +} + +/** + * clutter_x11_texture_pixmap_set_automatic: + * @texture: a #ClutterX11TexturePixmap + * @setting: %TRUE to enable automatic updates + * + * Enables or disables the automatic updates ot @texture in case the backing + * pixmap or window is damaged + * + * Since: 0.8 + */ +void +clutter_x11_texture_pixmap_set_automatic (ClutterX11TexturePixmap *texture, + gboolean setting) +{ + ClutterX11TexturePixmapPrivate *priv; + + g_return_if_fail (CLUTTER_X11_IS_TEXTURE_PIXMAP (texture)); + + priv = texture->priv; + + setting = !!setting; + if (setting == priv->automatic_updates) + return; + + if (setting) + create_damage_resources (texture); + else + free_damage_resources (texture); + + priv->automatic_updates = setting; +} diff --git a/clutter/clutter/x11/clutter-x11-texture-pixmap.h b/clutter/clutter/x11/clutter-x11-texture-pixmap.h new file mode 100644 index 0000000..8d2dc33 --- /dev/null +++ b/clutter/clutter/x11/clutter-x11-texture-pixmap.h @@ -0,0 +1,116 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Johan Bilien + * + * Copyright (C) 2007 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +#ifndef __CLUTTER_X11_TEXTURE_PIXMAP_H__ +#define __CLUTTER_X11_TEXTURE_PIXMAP_H__ + +#include +#include +#include + +#include + +G_BEGIN_DECLS + +#define CLUTTER_X11_TYPE_TEXTURE_PIXMAP (clutter_x11_texture_pixmap_get_type ()) +#define CLUTTER_X11_TEXTURE_PIXMAP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_X11_TYPE_TEXTURE_PIXMAP, ClutterX11TexturePixmap)) +#define CLUTTER_X11_TEXTURE_PIXMAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_X11_TYPE_TEXTURE_PIXMAP, ClutterX11TexturePixmapClass)) +#define CLUTTER_X11_IS_TEXTURE_PIXMAP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_X11_TYPE_TEXTURE_PIXMAP)) +#define CLUTTER_X11_IS_TEXTURE_PIXMAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_X11_TYPE_TEXTURE_PIXMAP)) +#define CLUTTER_X11_TEXTURE_PIXMAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_X11_TYPE_TEXTURE_PIXMAP, ClutterX11TexturePixmapClass)) + +typedef struct _ClutterX11TexturePixmap ClutterX11TexturePixmap; +typedef struct _ClutterX11TexturePixmapClass ClutterX11TexturePixmapClass; +typedef struct _ClutterX11TexturePixmapPrivate ClutterX11TexturePixmapPrivate; + +/** + * ClutterX11TexturePixmap: + * + * The #ClutterX11TexturePixmap structure contains only private data + * + * Since: 0.8 + */ +struct _ClutterX11TexturePixmap +{ + /*< private >*/ + ClutterTexture parent; + + ClutterX11TexturePixmapPrivate *priv; +}; + +/** + * ClutterX11TexturePixmapClass: + * @update_area: virtual function for updating the area of the texture + * + * The #ClutterX11TexturePixmapClass structure contains only private data + * + * Since: 0.8 + */ +struct _ClutterX11TexturePixmapClass +{ + /*< private >*/ + ClutterTextureClass parent_class; + + /*< public >*/ + void (* update_area) (ClutterX11TexturePixmap *texture, + gint x, + gint y, + gint width, + gint height); +}; + +CLUTTER_AVAILABLE_IN_ALL +GType clutter_x11_texture_pixmap_get_type (void) G_GNUC_CONST; + +CLUTTER_AVAILABLE_IN_ALL +ClutterActor *clutter_x11_texture_pixmap_new (void); +CLUTTER_AVAILABLE_IN_ALL +ClutterActor *clutter_x11_texture_pixmap_new_with_pixmap (Pixmap pixmap); +CLUTTER_AVAILABLE_IN_ALL +ClutterActor *clutter_x11_texture_pixmap_new_with_window (Window window); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_x11_texture_pixmap_set_automatic (ClutterX11TexturePixmap *texture, + gboolean setting); +CLUTTER_AVAILABLE_IN_ALL +void clutter_x11_texture_pixmap_set_pixmap (ClutterX11TexturePixmap *texture, + Pixmap pixmap); +CLUTTER_AVAILABLE_IN_ALL +void clutter_x11_texture_pixmap_set_window (ClutterX11TexturePixmap *texture, + Window window, + gboolean automatic); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_x11_texture_pixmap_sync_window (ClutterX11TexturePixmap *texture); +CLUTTER_AVAILABLE_IN_ALL +void clutter_x11_texture_pixmap_update_area (ClutterX11TexturePixmap *texture, + gint x, + gint y, + gint width, + gint height); + +G_END_DECLS + +#endif diff --git a/clutter/clutter/x11/clutter-x11.h b/clutter/clutter/x11/clutter-x11.h new file mode 100644 index 0000000..bba7ec2 --- /dev/null +++ b/clutter/clutter/x11/clutter-x11.h @@ -0,0 +1,169 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +/** + * SECTION:clutter-x11 + * @short_description: X11 specific API + * + * The X11 backend for Clutter provides some specific API, allowing + * integration with the Xlibs API for embedding and manipulating the + * stage window, or for trapping X errors. + * + * The ClutterX11 API is available since Clutter 0.6 + */ + +#ifndef __CLUTTER_X11_H__ +#define __CLUTTER_X11_H__ + +#include +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +/** + * ClutterX11FilterReturn: + * @CLUTTER_X11_FILTER_CONTINUE: The event was not handled, continues the + * processing + * @CLUTTER_X11_FILTER_TRANSLATE: Native event translated into a Clutter + * event, stops the processing + * @CLUTTER_X11_FILTER_REMOVE: Remove the event, stops the processing + * + * Return values for the #ClutterX11FilterFunc function. + * + * Since: 0.6 + */ +typedef enum { + CLUTTER_X11_FILTER_CONTINUE, + CLUTTER_X11_FILTER_TRANSLATE, + CLUTTER_X11_FILTER_REMOVE +} ClutterX11FilterReturn; + +CLUTTER_AVAILABLE_IN_ALL +GType clutter_x11_filter_return_get_type (void) G_GNUC_CONST; + +/* + * This is not used any more + */ +typedef struct _ClutterX11XInputDevice ClutterX11XInputDevice; + +/** + * ClutterX11FilterFunc: + * @xev: Native X11 event structure + * @cev: Clutter event structure + * @data: (closure): user data passed to the filter function + * + * Filter function for X11 native events. + * + * Return value: the result of the filtering + * + * Since: 0.6 + */ +typedef ClutterX11FilterReturn (*ClutterX11FilterFunc) (XEvent *xev, + ClutterEvent *cev, + gpointer data); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_x11_trap_x_errors (void); +CLUTTER_AVAILABLE_IN_ALL +gint clutter_x11_untrap_x_errors (void); + +CLUTTER_AVAILABLE_IN_ALL +Display *clutter_x11_get_default_display (void); +CLUTTER_AVAILABLE_IN_ALL +int clutter_x11_get_default_screen (void); +CLUTTER_AVAILABLE_IN_ALL +Window clutter_x11_get_root_window (void); +CLUTTER_AVAILABLE_IN_ALL +XVisualInfo *clutter_x11_get_visual_info (void); +CLUTTER_AVAILABLE_IN_ALL +void clutter_x11_set_display (Display * xdpy); + +CLUTTER_DEPRECATED_FOR(clutter_x11_get_visual_info) +XVisualInfo *clutter_x11_get_stage_visual (ClutterStage *stage); + +CLUTTER_AVAILABLE_IN_ALL +Window clutter_x11_get_stage_window (ClutterStage *stage); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_x11_set_stage_foreign (ClutterStage *stage, + Window xwindow); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_x11_add_filter (ClutterX11FilterFunc func, + gpointer data); +CLUTTER_AVAILABLE_IN_ALL +void clutter_x11_remove_filter (ClutterX11FilterFunc func, + gpointer data); + +CLUTTER_AVAILABLE_IN_ALL +ClutterX11FilterReturn clutter_x11_handle_event (XEvent *xevent); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_x11_disable_event_retrieval (void); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_x11_has_event_retrieval (void); + +CLUTTER_AVAILABLE_IN_ALL +ClutterStage *clutter_x11_get_stage_from_window (Window win); + +CLUTTER_DEPRECATED_FOR(clutter_device_manager_peek_devices) +const GSList* clutter_x11_get_input_devices (void); + +CLUTTER_DEPRECATED_IN_1_14 +void clutter_x11_enable_xinput (void); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_x11_has_xinput (void); + +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_x11_has_composite_extension (void); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_x11_set_use_argb_visual (gboolean use_argb); +CLUTTER_AVAILABLE_IN_ALL +gboolean clutter_x11_get_use_argb_visual (void); + +CLUTTER_AVAILABLE_IN_1_22 +void clutter_x11_set_use_stereo_stage (gboolean use_stereo); +CLUTTER_AVAILABLE_IN_1_22 +gboolean clutter_x11_get_use_stereo_stage (void); + +CLUTTER_AVAILABLE_IN_ALL +Time clutter_x11_get_current_event_time (void); + +CLUTTER_AVAILABLE_IN_ALL +gint clutter_x11_event_get_key_group (const ClutterEvent *event); + +CLUTTER_AVAILABLE_IN_ALL +guint clutter_x11_event_sequence_get_touch_detail (const ClutterEventSequence *sequence); + +CLUTTER_AVAILABLE_IN_ALL +void clutter_x11_request_reset_on_video_memory_purge (void); + +G_END_DECLS + +#endif /* __CLUTTER_X11_H__ */ diff --git a/clutter/clutter/x11/xsettings/xsettings-client.c b/clutter/clutter/x11/xsettings/xsettings-client.c new file mode 100644 index 0000000..494d575 --- /dev/null +++ b/clutter/clutter/x11/xsettings/xsettings-client.c @@ -0,0 +1,609 @@ +/* + * Copyright © 2001, 2007 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Red Hat not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Red Hat makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Owen Taylor, Red Hat, Inc. + */ +#include "clutter-build-config.h" +#include +#include +#include +#include + +#include +#include /* For CARD16 */ + +#include "xsettings-client.h" + +struct _XSettingsClient +{ + Display *display; + int screen; + XSettingsNotifyFunc notify; + XSettingsWatchFunc watch; + void *cb_data; + + XSettingsGrabFunc grab; + XSettingsGrabFunc ungrab; + + Window manager_window; + Atom manager_atom; + Atom selection_atom; + Atom xsettings_atom; + + XSettingsList *settings; +}; + +static void +notify_changes (XSettingsClient *client, + XSettingsList *old_list) +{ + XSettingsList *old_iter = old_list; + XSettingsList *new_iter = client->settings; + + if (!client->notify) + return; + + while (old_iter || new_iter) + { + int cmp; + + if (old_iter && new_iter) + cmp = strcmp (old_iter->setting->name, new_iter->setting->name); + else if (old_iter) + cmp = -1; + else + cmp = 1; + + if (cmp < 0) + { + client->notify (old_iter->setting->name, + XSETTINGS_ACTION_DELETED, + NULL, + client->cb_data); + } + else if (cmp == 0) + { + if (!xsettings_setting_equal (old_iter->setting, + new_iter->setting)) + client->notify (old_iter->setting->name, + XSETTINGS_ACTION_CHANGED, + new_iter->setting, + client->cb_data); + } + else + { + client->notify (new_iter->setting->name, + XSETTINGS_ACTION_NEW, + new_iter->setting, + client->cb_data); + } + + if (old_iter) + old_iter = old_iter->next; + if (new_iter) + new_iter = new_iter->next; + } +} + +static int +ignore_errors (Display *display, XErrorEvent *event) +{ + return True; +} + +static char local_byte_order = '\0'; + +#define BYTES_LEFT(buffer) ((buffer)->data + (buffer)->len - (buffer)->pos) + +static XSettingsResult +fetch_card16 (XSettingsBuffer *buffer, + CARD16 *result) +{ + CARD16 x; + + if (BYTES_LEFT (buffer) < 2) + return XSETTINGS_ACCESS; + + x = *(CARD16 *)buffer->pos; + buffer->pos += 2; + + if (buffer->byte_order == local_byte_order) + *result = x; + else + *result = (x << 8) | (x >> 8); + + return XSETTINGS_SUCCESS; +} + +static XSettingsResult +fetch_ushort (XSettingsBuffer *buffer, + unsigned short *result) +{ + CARD16 x; + XSettingsResult r; + + r = fetch_card16 (buffer, &x); + if (r == XSETTINGS_SUCCESS) + *result = x; + + return r; +} + +static XSettingsResult +fetch_card32 (XSettingsBuffer *buffer, + CARD32 *result) +{ + CARD32 x; + + if (BYTES_LEFT (buffer) < 4) + return XSETTINGS_ACCESS; + + x = *(CARD32 *)buffer->pos; + buffer->pos += 4; + + if (buffer->byte_order == local_byte_order) + *result = x; + else + *result = (x << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | (x >> 24); + + return XSETTINGS_SUCCESS; +} + +static XSettingsResult +fetch_card8 (XSettingsBuffer *buffer, + CARD8 *result) +{ + if (BYTES_LEFT (buffer) < 1) + return XSETTINGS_ACCESS; + + *result = *(CARD8 *)buffer->pos; + buffer->pos += 1; + + return XSETTINGS_SUCCESS; +} + +#define XSETTINGS_PAD(n,m) ((n + m - 1) & (~(m-1))) + +static XSettingsList * +parse_settings (unsigned char *data, + size_t len) +{ + XSettingsBuffer buffer; + XSettingsResult result = XSETTINGS_SUCCESS; + XSettingsList *settings = NULL; + CARD32 serial; + CARD32 n_entries; + CARD32 i; + XSettingsSetting *setting = NULL; + + local_byte_order = xsettings_byte_order (); + + buffer.pos = buffer.data = data; + buffer.len = len; + + result = fetch_card8 (&buffer, (unsigned char *)&buffer.byte_order); + if (buffer.byte_order != MSBFirst && + buffer.byte_order != LSBFirst) + { + fprintf (stderr, "Invalid byte order in XSETTINGS property\n"); + result = XSETTINGS_FAILED; + goto out; + } + + buffer.pos += 3; + + result = fetch_card32 (&buffer, &serial); + if (result != XSETTINGS_SUCCESS) + goto out; + + result = fetch_card32 (&buffer, &n_entries); + if (result != XSETTINGS_SUCCESS) + goto out; + + for (i = 0; i < n_entries; i++) + { + CARD8 type; + CARD16 name_len; + CARD32 v_int; + size_t pad_len; + + result = fetch_card8 (&buffer, &type); + if (result != XSETTINGS_SUCCESS) + goto out; + + buffer.pos += 1; + + result = fetch_card16 (&buffer, &name_len); + if (result != XSETTINGS_SUCCESS) + goto out; + + pad_len = XSETTINGS_PAD(name_len, 4); + if (BYTES_LEFT (&buffer) < pad_len) + { + result = XSETTINGS_ACCESS; + goto out; + } + + setting = malloc (sizeof *setting); + if (!setting) + { + result = XSETTINGS_NO_MEM; + goto out; + } + setting->type = XSETTINGS_TYPE_INT; /* No allocated memory */ + + setting->name = malloc (name_len + 1); + if (!setting->name) + { + result = XSETTINGS_NO_MEM; + goto out; + } + + memcpy (setting->name, buffer.pos, name_len); + setting->name[name_len] = '\0'; + buffer.pos += pad_len; + + result = fetch_card32 (&buffer, &v_int); + if (result != XSETTINGS_SUCCESS) + goto out; + setting->last_change_serial = v_int; + + switch (type) + { + case XSETTINGS_TYPE_INT: + result = fetch_card32 (&buffer, &v_int); + if (result != XSETTINGS_SUCCESS) + goto out; + + setting->data.v_int = (INT32)v_int; + break; + case XSETTINGS_TYPE_STRING: + result = fetch_card32 (&buffer, &v_int); + if (result != XSETTINGS_SUCCESS) + goto out; + + pad_len = XSETTINGS_PAD (v_int, 4); + if (v_int + 1 == 0 || /* Guard against wrap-around */ + BYTES_LEFT (&buffer) < pad_len) + { + result = XSETTINGS_ACCESS; + goto out; + } + + setting->data.v_string = malloc (v_int + 1); + if (!setting->data.v_string) + { + result = XSETTINGS_NO_MEM; + goto out; + } + + memcpy (setting->data.v_string, buffer.pos, v_int); + setting->data.v_string[v_int] = '\0'; + buffer.pos += pad_len; + + break; + case XSETTINGS_TYPE_COLOR: + result = fetch_ushort (&buffer, &setting->data.v_color.red); + if (result != XSETTINGS_SUCCESS) + goto out; + result = fetch_ushort (&buffer, &setting->data.v_color.green); + if (result != XSETTINGS_SUCCESS) + goto out; + result = fetch_ushort (&buffer, &setting->data.v_color.blue); + if (result != XSETTINGS_SUCCESS) + goto out; + result = fetch_ushort (&buffer, &setting->data.v_color.alpha); + if (result != XSETTINGS_SUCCESS) + goto out; + + break; + default: + /* Quietly ignore unknown types */ + break; + } + + setting->type = type; + + result = xsettings_list_insert (&settings, setting); + if (result != XSETTINGS_SUCCESS) + goto out; + + setting = NULL; + } + + out: + + if (result != XSETTINGS_SUCCESS) + { + switch (result) + { + case XSETTINGS_NO_MEM: + fprintf(stderr, "Out of memory reading XSETTINGS property\n"); + break; + case XSETTINGS_ACCESS: + fprintf(stderr, "Invalid XSETTINGS property (read off end)\n"); + break; + case XSETTINGS_DUPLICATE_ENTRY: + fprintf (stderr, "Duplicate XSETTINGS entry for '%s'\n", setting->name); + case XSETTINGS_FAILED: + case XSETTINGS_SUCCESS: + case XSETTINGS_NO_ENTRY: + break; + } + + if (setting) + xsettings_setting_free (setting); + + xsettings_list_free (settings); + settings = NULL; + + } + + return settings; +} + +static void +read_settings (XSettingsClient *client) +{ + Atom type; + int format; + unsigned long n_items; + unsigned long bytes_after; + unsigned char *data; + int result; + + int (*old_handler) (Display *, XErrorEvent *); + + XSettingsList *old_list = client->settings; + + client->settings = NULL; + + if (client->manager_window) + { + old_handler = XSetErrorHandler (ignore_errors); + result = XGetWindowProperty (client->display, client->manager_window, + client->xsettings_atom, 0, LONG_MAX, + False, client->xsettings_atom, + &type, &format, &n_items, &bytes_after, &data); + XSetErrorHandler (old_handler); + + if (result == Success && type != None) + { + if (type != client->xsettings_atom) + { + fprintf (stderr, "Invalid type for XSETTINGS property"); + } + else if (format != 8) + { + fprintf (stderr, "Invalid format for XSETTINGS property %d", format); + } + else + client->settings = parse_settings (data, n_items); + + XFree (data); + } + } + + notify_changes (client, old_list); + xsettings_list_free (old_list); +} + +static void +add_events (Display *display, + Window window, + long mask) +{ + XWindowAttributes attr; + + XGetWindowAttributes (display, window, &attr); + XSelectInput (display, window, attr.your_event_mask | mask); +} + +static void +check_manager_window (XSettingsClient *client) +{ + if (client->manager_window && client->watch) + client->watch (client->manager_window, False, 0, client->cb_data); + + if (client->grab) + client->grab (client->display); + else + XGrabServer (client->display); + + client->manager_window = XGetSelectionOwner (client->display, + client->selection_atom); + if (client->manager_window) + XSelectInput (client->display, client->manager_window, + PropertyChangeMask | StructureNotifyMask); + + if (client->ungrab) + client->ungrab (client->display); + else + XUngrabServer (client->display); + + XFlush (client->display); + + if (client->manager_window && client->watch) + { + if (!client->watch (client->manager_window, True, + PropertyChangeMask | StructureNotifyMask, + client->cb_data)) + { + /* Inability to watch the window probably means that it was destroyed + * after we ungrabbed + */ + client->manager_window = None; + return; + } + } + + + read_settings (client); +} + +XSettingsClient * +xsettings_client_new (Display *display, + int screen, + XSettingsNotifyFunc notify, + XSettingsWatchFunc watch, + void *cb_data) +{ + return xsettings_client_new_with_grab_funcs (display, screen, notify, watch, cb_data, + NULL, NULL); +} + +XSettingsClient * +xsettings_client_new_with_grab_funcs (Display *display, + int screen, + XSettingsNotifyFunc notify, + XSettingsWatchFunc watch, + void *cb_data, + XSettingsGrabFunc grab, + XSettingsGrabFunc ungrab) +{ + XSettingsClient *client; + char buffer[256]; + char *atom_names[3]; + Atom atoms[3]; + + client = malloc (sizeof *client); + if (!client) + return NULL; + + client->display = display; + client->screen = screen; + client->notify = notify; + client->watch = watch; + client->cb_data = cb_data; + client->grab = grab; + client->ungrab = ungrab; + + client->manager_window = None; + client->settings = NULL; + + sprintf(buffer, "_XSETTINGS_S%d", screen); + atom_names[0] = buffer; + atom_names[1] = "_XSETTINGS_SETTINGS"; + atom_names[2] = "MANAGER"; + +#ifdef HAVE_XINTERNATOMS + XInternAtoms (display, atom_names, 3, False, atoms); +#else + atoms[0] = XInternAtom (display, atom_names[0], False); + atoms[1] = XInternAtom (display, atom_names[1], False); + atoms[2] = XInternAtom (display, atom_names[2], False); +#endif + + client->selection_atom = atoms[0]; + client->xsettings_atom = atoms[1]; + client->manager_atom = atoms[2]; + + /* Select on StructureNotify so we get MANAGER events + */ + add_events (display, RootWindow (display, screen), StructureNotifyMask); + + if (client->watch) + client->watch (RootWindow (display, screen), True, StructureNotifyMask, + client->cb_data); + + check_manager_window (client); + + return client; +} + + +void +xsettings_client_set_grab_func (XSettingsClient *client, + XSettingsGrabFunc grab) +{ + client->grab = grab; +} + +void +xsettings_client_set_ungrab_func (XSettingsClient *client, + XSettingsGrabFunc ungrab) +{ + client->ungrab = ungrab; +} + +void +xsettings_client_destroy (XSettingsClient *client) +{ + if (client->watch) + client->watch (RootWindow (client->display, client->screen), + False, 0, client->cb_data); + if (client->manager_window && client->watch) + client->watch (client->manager_window, False, 0, client->cb_data); + + xsettings_list_free (client->settings); + free (client); +} + +XSettingsResult +xsettings_client_get_setting (XSettingsClient *client, + const char *name, + XSettingsSetting **setting) +{ + XSettingsSetting *search = xsettings_list_lookup (client->settings, name); + if (search) + { + *setting = xsettings_setting_copy (search); + return *setting ? XSETTINGS_SUCCESS : XSETTINGS_NO_MEM; + } + else + return XSETTINGS_NO_ENTRY; +} + +Bool +xsettings_client_process_event (XSettingsClient *client, + XEvent *xev) +{ + /* The checks here will not unlikely cause us to reread + * the properties from the manager window a number of + * times when the manager changes from A->B. But manager changes + * are going to be pretty rare. + */ + if (xev->xany.window == RootWindow (client->display, client->screen)) + { + if (xev->xany.type == ClientMessage && + xev->xclient.message_type == client->manager_atom && + xev->xclient.data.l[1] == client->selection_atom) + { + check_manager_window (client); + return True; + } + } + else if (xev->xany.window == client->manager_window) + { + if (xev->xany.type == DestroyNotify) + { + check_manager_window (client); + /* let GDK do its cleanup */ + return False; + } + else if (xev->xany.type == PropertyNotify) + { + read_settings (client); + return True; + } + } + + return False; +} diff --git a/clutter/clutter/x11/xsettings/xsettings-client.h b/clutter/clutter/x11/xsettings/xsettings-client.h new file mode 100644 index 0000000..710ed12 --- /dev/null +++ b/clutter/clutter/x11/xsettings/xsettings-client.h @@ -0,0 +1,79 @@ +/* + * Copyright © 2001, 2007 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Red Hat not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Red Hat makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Owen Taylor, Red Hat, Inc. + */ +#ifndef XSETTINGS_CLIENT_H +#define XSETTINGS_CLIENT_H + +#include +#include "xsettings-common.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef struct _XSettingsClient XSettingsClient; + +typedef enum +{ + XSETTINGS_ACTION_NEW, + XSETTINGS_ACTION_CHANGED, + XSETTINGS_ACTION_DELETED +} XSettingsAction; + +typedef void (*XSettingsNotifyFunc) (const char *name, + XSettingsAction action, + XSettingsSetting *setting, + void *cb_data); +typedef Bool (*XSettingsWatchFunc) (Window window, + Bool is_start, + long mask, + void *cb_data); +typedef void (*XSettingsGrabFunc) (Display *display); + +XSettingsClient *xsettings_client_new (Display *display, + int screen, + XSettingsNotifyFunc notify, + XSettingsWatchFunc watch, + void *cb_data); +XSettingsClient *xsettings_client_new_with_grab_funcs (Display *display, + int screen, + XSettingsNotifyFunc notify, + XSettingsWatchFunc watch, + void *cb_data, + XSettingsGrabFunc grab, + XSettingsGrabFunc ungrab); +void xsettings_client_set_grab_func (XSettingsClient *client, + XSettingsGrabFunc grab); +void xsettings_client_set_ungrab_func (XSettingsClient *client, + XSettingsGrabFunc ungrab); +void xsettings_client_destroy (XSettingsClient *client); +Bool xsettings_client_process_event (XSettingsClient *client, + XEvent *xev); +XSettingsResult xsettings_client_get_setting (XSettingsClient *client, + const char *name, + XSettingsSetting **setting); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XSETTINGS_CLIENT_H */ diff --git a/clutter/clutter/x11/xsettings/xsettings-common.c b/clutter/clutter/x11/xsettings/xsettings-common.c new file mode 100644 index 0000000..8a9bcc0 --- /dev/null +++ b/clutter/clutter/x11/xsettings/xsettings-common.c @@ -0,0 +1,265 @@ +/* + * Copyright © 2001 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Red Hat not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Red Hat makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Owen Taylor, Red Hat, Inc. + */ +#include "clutter-build-config.h" +#include "string.h" +#include "stdlib.h" + +#include +#include /* For CARD32 */ + +#include "xsettings-common.h" + +XSettingsSetting * +xsettings_setting_copy (XSettingsSetting *setting) +{ + XSettingsSetting *result; + size_t str_len; + + result = malloc (sizeof *result); + if (!result) + return NULL; + + str_len = strlen (setting->name); + result->name = malloc (str_len + 1); + if (!result->name) + goto err; + + memcpy (result->name, setting->name, str_len + 1); + + result->type = setting->type; + + switch (setting->type) + { + case XSETTINGS_TYPE_INT: + result->data.v_int = setting->data.v_int; + break; + case XSETTINGS_TYPE_COLOR: + result->data.v_color = setting->data.v_color; + break; + case XSETTINGS_TYPE_STRING: + str_len = strlen (setting->data.v_string); + result->data.v_string = malloc (str_len + 1); + if (!result->data.v_string) + goto err; + + memcpy (result->data.v_string, setting->data.v_string, str_len + 1); + break; + } + + result->last_change_serial = setting->last_change_serial; + + return result; + + err: + if (result->name) + free (result->name); + free (result); + + return NULL; +} + +XSettingsList * +xsettings_list_copy (XSettingsList *list) +{ + XSettingsList *new = NULL; + XSettingsList *old_iter = list; + XSettingsList *new_iter = NULL; + + while (old_iter) + { + XSettingsList *new_node; + + new_node = malloc (sizeof *new_node); + if (!new_node) + goto error; + + new_node->setting = xsettings_setting_copy (old_iter->setting); + if (!new_node->setting) + { + free (new_node); + goto error; + } + + if (new_iter) + new_iter->next = new_node; + else + new = new_node; + + new_iter = new_node; + + old_iter = old_iter->next; + } + + return new; + + error: + xsettings_list_free (new); + return NULL; +} + +int +xsettings_setting_equal (XSettingsSetting *setting_a, + XSettingsSetting *setting_b) +{ + if (setting_a->type != setting_b->type) + return 0; + + if (strcmp (setting_a->name, setting_b->name) != 0) + return 0; + + switch (setting_a->type) + { + case XSETTINGS_TYPE_INT: + return setting_a->data.v_int == setting_b->data.v_int; + case XSETTINGS_TYPE_COLOR: + return (setting_a->data.v_color.red == setting_b->data.v_color.red && + setting_a->data.v_color.green == setting_b->data.v_color.green && + setting_a->data.v_color.blue == setting_b->data.v_color.blue && + setting_a->data.v_color.alpha == setting_b->data.v_color.alpha); + case XSETTINGS_TYPE_STRING: + return strcmp (setting_a->data.v_string, setting_b->data.v_string) == 0; + } + + return 0; +} + +void +xsettings_setting_free (XSettingsSetting *setting) +{ + if (setting->type == XSETTINGS_TYPE_STRING) + free (setting->data.v_string); + + if (setting->name) + free (setting->name); + + free (setting); +} + +void +xsettings_list_free (XSettingsList *list) +{ + while (list) + { + XSettingsList *next = list->next; + + xsettings_setting_free (list->setting); + free (list); + + list = next; + } +} + +XSettingsResult +xsettings_list_insert (XSettingsList **list, + XSettingsSetting *setting) +{ + XSettingsList *node; + XSettingsList *iter; + XSettingsList *last = NULL; + + node = malloc (sizeof *node); + if (!node) + return XSETTINGS_NO_MEM; + node->setting = setting; + + iter = *list; + while (iter) + { + int cmp = strcmp (setting->name, iter->setting->name); + + if (cmp < 0) + break; + else if (cmp == 0) + { + free (node); + return XSETTINGS_DUPLICATE_ENTRY; + } + + last = iter; + iter = iter->next; + } + + if (last) + last->next = node; + else + *list = node; + + node->next = iter; + + return XSETTINGS_SUCCESS; +} + +XSettingsResult +xsettings_list_delete (XSettingsList **list, + const char *name) +{ + XSettingsList *iter; + XSettingsList *last = NULL; + + iter = *list; + while (iter) + { + if (strcmp (name, iter->setting->name) == 0) + { + if (last) + last->next = iter->next; + else + *list = iter->next; + + xsettings_setting_free (iter->setting); + free (iter); + + return XSETTINGS_SUCCESS; + } + + last = iter; + iter = iter->next; + } + + return XSETTINGS_FAILED; +} + +XSettingsSetting * +xsettings_list_lookup (XSettingsList *list, + const char *name) +{ + XSettingsList *iter; + + iter = list; + while (iter) + { + if (strcmp (name, iter->setting->name) == 0) + return iter->setting; + + iter = iter->next; + } + + return NULL; +} + +char +xsettings_byte_order (void) +{ + CARD32 myint = 0x01020304; + return (*(char *)&myint == 1) ? MSBFirst : LSBFirst; +} diff --git a/clutter/clutter/x11/xsettings/xsettings-common.h b/clutter/clutter/x11/xsettings/xsettings-common.h new file mode 100644 index 0000000..d8b544b --- /dev/null +++ b/clutter/clutter/x11/xsettings/xsettings-common.h @@ -0,0 +1,132 @@ +/* + * Copyright © 2001 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Red Hat not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Red Hat makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Owen Taylor, Red Hat, Inc. + * + * Modified by: Emmanuele Bassi, Intel Corp. + */ +#ifndef XSETTINGS_COMMON_H +#define XSETTINGS_COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Renames for Clutter inclusion */ + +#define xsettings_byte_order _clutter_xsettings_byte_order +#define xsettings_client_destroy _clutter_xsettings_client_destroy +#define xsettings_client_get_setting _clutter_xsettings_client_get_setting +#define xsettings_client_new _clutter_xsettings_client_new +#define xsettings_client_new_with_grab_funcs _clutter_xsettings_client_new_with_grab_funcs +#define xsettings_client_set_grab_func _clutter_xsettings_client_set_grab_func +#define xsettings_client_set_ungrab_func _clutter_xsettings_client_set_ungrab_func +#define xsettings_client_process_event _clutter_xsettings_client_process_event +#define xsettings_list_copy _clutter_xsettings_list_copy +#define xsettings_list_delete _clutter_xsettings_list_delete +#define xsettings_list_free _clutter_xsettings_list_free +#define xsettings_list_insert _clutter_xsettings_list_insert +#define xsettings_list_lookup _clutter_xsettings_list_lookup +#define xsettings_setting_copy _clutter_xsettings_setting_copy +#define xsettings_setting_equal _clutter_xsettings_setting_equal +#define xsettings_setting_free _clutter_xsettings_setting_free + + +typedef struct _XSettingsBuffer XSettingsBuffer; +typedef struct _XSettingsColor XSettingsColor; +typedef struct _XSettingsList XSettingsList; +typedef struct _XSettingsSetting XSettingsSetting; + +/* Types of settings possible. Enum values correspond to + * protocol values. + */ +typedef enum +{ + XSETTINGS_TYPE_INT = 0, + XSETTINGS_TYPE_STRING = 1, + XSETTINGS_TYPE_COLOR = 2 +} XSettingsType; + +typedef enum +{ + XSETTINGS_SUCCESS, + XSETTINGS_NO_MEM, + XSETTINGS_ACCESS, + XSETTINGS_FAILED, + XSETTINGS_NO_ENTRY, + XSETTINGS_DUPLICATE_ENTRY +} XSettingsResult; + +struct _XSettingsBuffer +{ + char byte_order; + size_t len; + unsigned char *data; + unsigned char *pos; +}; + +struct _XSettingsColor +{ + unsigned short red, green, blue, alpha; +}; + +struct _XSettingsList +{ + XSettingsSetting *setting; + XSettingsList *next; +}; + +struct _XSettingsSetting +{ + char *name; + XSettingsType type; + + union { + int v_int; + char *v_string; + XSettingsColor v_color; + } data; + + unsigned long last_change_serial; +}; + +XSettingsSetting *xsettings_setting_copy (XSettingsSetting *setting); +void xsettings_setting_free (XSettingsSetting *setting); +int xsettings_setting_equal (XSettingsSetting *setting_a, + XSettingsSetting *setting_b); + +void xsettings_list_free (XSettingsList *list); +XSettingsList *xsettings_list_copy (XSettingsList *list); +XSettingsResult xsettings_list_insert (XSettingsList **list, + XSettingsSetting *setting); +XSettingsSetting *xsettings_list_lookup (XSettingsList *list, + const char *name); +XSettingsResult xsettings_list_delete (XSettingsList **list, + const char *name); + +char xsettings_byte_order (void); + +#define XSETTINGS_PAD(n,m) ((n + m - 1) & (~(m-1))) + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XSETTINGS_COMMON_H */ diff --git a/clutter/configure b/clutter/configure new file mode 100755 index 0000000..068cf70 --- /dev/null +++ b/clutter/configure @@ -0,0 +1,17419 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for clutter 1.26.1. +# +# Report bugs to . +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1 + + test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org and +$0: http://bugzilla.gnome.org/enter_bug.cgi?product=clutter +$0: about your system, including any error possibly output +$0: before this message. Then install a modern shell, or +$0: manually run the script under such a shell if you do +$0: have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + +SHELL=${CONFIG_SHELL-/bin/sh} + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='clutter' +PACKAGE_TARNAME='clutter' +PACKAGE_VERSION='1.26.1' +PACKAGE_STRING='clutter 1.26.1' +PACKAGE_BUGREPORT='http://bugzilla.gnome.org/enter_bug.cgi?product=clutter' +PACKAGE_URL='http://www.clutter-project.org' + +ac_unique_file="clutter/clutter.h" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +LIBOBJS +BUILD_EXAMPLES_FALSE +BUILD_EXAMPLES_TRUE +installed_testdir +installed_test_metadir +ENABLE_ALWAYS_BUILD_TESTS_FALSE +ENABLE_ALWAYS_BUILD_TESTS_TRUE +ENABLE_INSTALLED_TESTS_FALSE +ENABLE_INSTALLED_TESTS_TRUE +HAVE_INTROSPECTION_FALSE +HAVE_INTROSPECTION_TRUE +INTROSPECTION_MAKEFILE +INTROSPECTION_LIBS +INTROSPECTION_CFLAGS +INTROSPECTION_TYPELIBDIR +INTROSPECTION_GIRDIR +INTROSPECTION_GENERATE +INTROSPECTION_COMPILER +INTROSPECTION_SCANNER +ENABLE_GCOV_FALSE +ENABLE_GCOV_TRUE +CLUTTER_GCOV_LDADD +CLUTTER_GCOV_CFLAGS +LTP_GENHTML +LTP +SHTOOL +CLUTTER_LIBS +CLUTTER_CFLAGS +CLUTTER_REQUIRES_PRIVATE +CLUTTER_REQUIRES +CLUTTER_DEPS_PRIVATE_LIBS +CLUTTER_DEPS_PRIVATE_CFLAGS +CLUTTER_DEPS_LIBS +CLUTTER_DEPS_CFLAGS +MAINTAINER_CFLAGS +CLUTTER_DEPRECATED_CFLAGS +CLUTTER_DEBUG_CFLAGS +PIXBUF_TESTS_FALSE +PIXBUF_TESTS_TRUE +GDK_PIXBUF_LIBS +GDK_PIXBUF_CFLAGS +X11_TESTS_FALSE +X11_TESTS_TRUE +BUILD_XI2_FALSE +BUILD_XI2_TRUE +XMKMF +COGL_DRIVER +CLUTTER_COGL +CLUTTER_FLAVOUR +CLUTTER_SONAME_INFIX +CLUTTER_STAGE_TYPE +CLUTTER_WINSYS_BASE +CLUTTER_WINSYS +CLUTTER_CONFIG_DEFINES +CLUTTER_INPUT_BACKENDS +CLUTTER_BACKENDS +SUPPORT_WAYLAND_FALSE +SUPPORT_WAYLAND_TRUE +CLUTTER_HIDDEN_VISIBILITY_CFLAGS +CLUTTER_LINK_FLAGS +GLIB_COMPILE_RESOURCES +GLIB_MKENUMS +GOBJECT_QUERY +GLIB_GENMARSHAL +GLIB_LIBS +GLIB_CFLAGS +PKG_CONFIG_LIBDIR +PKG_CONFIG_PATH +PKG_CONFIG +LIBUDEV_REQ_VERSION +LIBINPUT_REQ_VERSION +GDK_REQ_VERSION +XCOMPOSITE_REQ_VERSION +GI_REQ_VERSION +PANGO_REQ_VERSION +CAIRO_REQ_VERSION +ATK_REQ_VERSION +JSON_GLIB_REQ_VERSION +COGL_REQ_VERSION +GLIB_REQ_VERSION +LIBM +CPP +LT_SYS_LIBRARY_PATH +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +MANIFEST_TOOL +RANLIB +ac_ct_AR +AR +DLLTOOL +OBJDUMP +LN_S +NM +ac_ct_DUMPBIN +DUMPBIN +LD +FGREP +EGREP +GREP +LIBTOOL +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +am__nodep +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +CLUTTER_LT_LDFLAGS +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +SED +CLUTTER_LT_VERSION +CLUTTER_LT_REVISION +CLUTTER_LT_CURRENT +CLUTTER_RELEASE_STATUS +CLUTTER_API_VERSION_AM +CLUTTER_API_VERSION +CLUTTER_VERSION +CLUTTER_MICRO_VERSION +CLUTTER_MINOR_VERSION +CLUTTER_MAJOR_VERSION +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +AM_DEFAULT_V +AM_V +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_silent_rules +enable_dependency_tracking +enable_static +enable_shared +with_pic +enable_fast_install +with_aix_soname +with_gnu_ld +with_sysroot +enable_libtool_lock +enable_glibtest +enable_Bsymbolic +enable_wayland_egl_server +with_x +enable_xinput +enable_gdk_pixbuf +enable_debug +enable_deprecated +enable_maintainer_flags +enable_Werror +enable_gcov +enable_introspection +enable_installed_tests +enable_always_build_tests +enable_examples +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +LT_SYS_LIBRARY_PATH +CPP +PKG_CONFIG +PKG_CONFIG_PATH +PKG_CONFIG_LIBDIR +XMKMF +GDK_PIXBUF_CFLAGS +GDK_PIXBUF_LIBS +CLUTTER_DEPS_CFLAGS +CLUTTER_DEPS_LIBS +CLUTTER_DEPS_PRIVATE_CFLAGS +CLUTTER_DEPS_PRIVATE_LIBS' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures clutter 1.26.1 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/clutter] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +X features: + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of clutter 1.26.1:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-silent-rules less verbose build output (undo: "make V=1") + --disable-silent-rules verbose build output (undo: "make V=0") + --enable-dependency-tracking + do not reject slow dependency extractors + --disable-dependency-tracking + speeds up one-time build + --enable-static[=PKGS] build static libraries [default=no] + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + --disable-glibtest do not try to compile and run a test GLIB program + --disable-Bsymbolic Avoid linking with -Bsymbolic + --enable-wayland-egl-server=[no/yes] + Enable server side wayland support [default=no] + --enable-xinput Use the XI X extension + --enable-gdk-pixbuf=[no/yes] + Enable tests using GDK-Pixbuf [default=yes] + --enable-debug=[no/minimum/yes] + Control Clutter debugging level [default=minimum] + --enable-deprecated=[no/yes] + Whether deprecated symbols should be disabled when + compiling Clutter [default=yes] + --enable-maintainer-flags=[no/yes/error] + Use strict compiler flags [default=yes] + --disable-Werror Removes -Werror from compiler flags + --enable-gcov Enable gcov + --enable-introspection=[no/auto/yes] + Enable introspection for this build + --enable-installed-tests + Enable installation of some test cases + --enable-always-build-tests + Enable always building tests during 'make all' + --enable-examples Whether examples should be built + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use + both] + --with-aix-soname=aix|svr4|both + shared library versioning (aka "SONAME") variant to + provide on AIX, [default=aix]. + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-sysroot[=DIR] Search for dependent libraries within DIR (or the + compiler's sysroot if not specified). + --with-x use the X Window System + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + LT_SYS_LIBRARY_PATH + User-defined run-time library search path. + CPP C preprocessor + PKG_CONFIG path to pkg-config utility + PKG_CONFIG_PATH + directories to add to pkg-config's search path + PKG_CONFIG_LIBDIR + path overriding pkg-config's built-in search path + XMKMF Path to xmkmf, Makefile generator for X Window System + GDK_PIXBUF_CFLAGS + C compiler flags for GDK_PIXBUF, overriding pkg-config + GDK_PIXBUF_LIBS + linker flags for GDK_PIXBUF, overriding pkg-config + CLUTTER_DEPS_CFLAGS + C compiler flags for CLUTTER_DEPS, overriding pkg-config + CLUTTER_DEPS_LIBS + linker flags for CLUTTER_DEPS, overriding pkg-config + CLUTTER_DEPS_PRIVATE_CFLAGS + C compiler flags for CLUTTER_DEPS_PRIVATE, overriding pkg-config + CLUTTER_DEPS_PRIVATE_LIBS + linker flags for CLUTTER_DEPS_PRIVATE, overriding pkg-config + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +clutter home page: . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +clutter configure 1.26.1 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## ---------------------------------------------------------------------- ## +## Report this to http://bugzilla.gnome.org/enter_bug.cgi?product=clutter ## +## ---------------------------------------------------------------------- ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES +# ---------------------------------------------------- +# Tries to find if the field MEMBER exists in type AGGR, after including +# INCLUDES, setting cache variable VAR accordingly. +ac_fn_c_check_member () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 +$as_echo_n "checking for $2.$3... " >&6; } +if eval \${$4+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (sizeof ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + eval "$4=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$4 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_member +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by clutter $as_me 1.26.1, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + +ac_config_headers="$ac_config_headers clutter/clutter-build-config.h" + +ac_aux_dir= +for ac_dir in build "$srcdir"/build; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in build \"$srcdir\"/build" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + + + +am__api_version='1.15' + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi + +rm -f conftest.file + +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=1;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='clutter' + VERSION='1.26.1' + + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +mkdir_p='$(MKDIR_P)' + +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar plaintar pax cpio none' + +# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether UID '$am_uid' is supported by ustar format" >&5 +$as_echo_n "checking whether UID '$am_uid' is supported by ustar format... " >&6; } + if test $am_uid -le $am_max_uid; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + _am_tools=none + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GID '$am_gid' is supported by ustar format" >&5 +$as_echo_n "checking whether GID '$am_gid' is supported by ustar format... " >&6; } + if test $am_gid -le $am_max_gid; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + _am_tools=none + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to create a ustar tar archive" >&5 +$as_echo_n "checking how to create a ustar tar archive... " >&6; } + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_ustar-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + { echo "$as_me:$LINENO: $_am_tar --version" >&5 + ($_am_tar --version) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && break + done + am__tar="$_am_tar --format=ustar -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=ustar -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x ustar -w "$$tardir"' + am__tar_='pax -L -x ustar -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H ustar -L' + am__tar_='find "$tardir" -print | cpio -o -H ustar -L' + am__untar='cpio -i -H ustar -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_ustar}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + { echo "$as_me:$LINENO: tardir=conftest.dir && eval $am__tar_ >conftest.tar" >&5 + (tardir=conftest.dir && eval $am__tar_ >conftest.tar) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + rm -rf conftest.dir + if test -s conftest.tar; then + { echo "$as_me:$LINENO: $am__untar &5 + ($am__untar &5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + { echo "$as_me:$LINENO: cat conftest.dir/file" >&5 + (cat conftest.dir/file) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + grep GrepMe conftest.dir/file >/dev/null 2>&1 && break + fi + done + rm -rf conftest.dir + + if ${am_cv_prog_tar_ustar+:} false; then : + $as_echo_n "(cached) " >&6 +else + am_cv_prog_tar_ustar=$_am_tool +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_tar_ustar" >&5 +$as_echo "$am_cv_prog_tar_ustar" >&6; } + + + + + + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 + fi +fi + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=0;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + + +CLUTTER_MAJOR_VERSION=1 + +CLUTTER_MINOR_VERSION=26 + +CLUTTER_MICRO_VERSION=1 + +CLUTTER_VERSION=1.26.1 + +CLUTTER_API_VERSION=1.0 + +CLUTTER_API_VERSION_AM=$CLUTTER_MAJOR_VERSION\_0 + +CLUTTER_RELEASE_STATUS=git + + + + + +CLUTTER_LT_CURRENT=2600 +CLUTTER_LT_REV=1 +CLUTTER_LT_AGE=2600 +CLUTTER_LT_VERSION="$CLUTTER_LT_CURRENT:$CLUTTER_LT_REV:$CLUTTER_LT_AGE" +CLUTTER_LT_LDFLAGS="-avoid-version" +CLUTTER_LT_CURRENT=2600 + +CLUTTER_LT_REVISION=1 + +CLUTTER_LT_VERSION=$CLUTTER_LT_VERSION + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + + + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + + + +$as_echo "#define OS_LINUX 1" >>confdefs.h + + + + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + + +# Checks for programs. +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 +$as_echo_n "checking for style of include used by $am_make... " >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 +$as_echo "$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + + + +# require libtool >= 2.2 + +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.4.6' +macro_revision='2.4.6' + + + + + + + + + + + + + +ltmain=$ac_aux_dir/ltmain.sh + +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case $ECHO in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if ${ac_cv_path_FGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_FGREP" || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if ${lt_cv_path_NM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in dumpbin "link -dump" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if ${lt_cv_nm_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if ${lt_cv_sys_max_cmd_len+:} false; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n "$lt_cv_sys_max_cmd_len"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +$as_echo_n "checking how to convert $build file names to $host format... " >&6; } +if ${lt_cv_to_host_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac + +fi + +to_host_file_cmd=$lt_cv_to_host_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +$as_echo "$lt_cv_to_host_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } +if ${lt_cv_to_tool_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + #assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac + +fi + +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +$as_echo "$lt_cv_to_tool_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if ${lt_cv_ld_reload_flag+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test yes != "$GCC"; then + reload_cmds=false + fi + ;; + darwin*) + if test yes = "$GCC"; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if ${lt_cv_deplibs_check_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + + + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +$as_echo_n "checking how to associate runtime and link libraries... " >&6; } +if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + + + + + + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} +: ${AR_FLAGS=cru} + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 +$as_echo_n "checking for archiver @FILE support... " >&6; } +if ${lt_cv_ar_at_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ar_at_file=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 +$as_echo "$lt_cv_ar_at_file" >&6; } + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if ${lt_cv_sys_global_symbol_pipe+:} false; then : + $as_echo_n "(cached) " >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[ABCDEGRST]' + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 +$as_echo_n "checking for sysroot... " >&6; } + +# Check whether --with-sysroot was given. +if test "${with_sysroot+set}" = set; then : + withval=$with_sysroot; +else + with_sysroot=no +fi + + +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 +$as_echo "$with_sysroot" >&6; } + as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 + ;; +esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 +$as_echo "${lt_sysroot:-no}" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 +$as_echo_n "checking for a working dd... " >&6; } +if ${ac_cv_path_lt_DD+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +if test -z "$lt_DD"; then + ac_path_lt_DD_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in dd; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_lt_DD" || continue +if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi + $ac_path_lt_DD_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_lt_DD"; then + : + fi +else + ac_cv_path_lt_DD=$lt_DD +fi + +rm -f conftest.i conftest2.i conftest.out +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 +$as_echo "$ac_cv_path_lt_DD" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 +$as_echo_n "checking how to truncate binary pipes... " >&6; } +if ${lt_cv_truncate_bin+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 +$as_echo "$lt_cv_truncate_bin" >&6; } + + + + + + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then : + enableval=$enable_libtool_lock; +fi + +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if ${lt_cv_cc_needs_belf+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$lt_cv_cc_needs_belf" >&6; } + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. +set dummy ${ac_tool_prefix}mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MANIFEST_TOOL"; then + ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL +if test -n "$MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 +$as_echo "$MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_MANIFEST_TOOL"; then + ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL + # Extract the first word of "mt", so it can be a program name with args. +set dummy mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_MANIFEST_TOOL"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL +if test -n "$ac_ct_MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 +$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_MANIFEST_TOOL" = x; then + MANIFEST_TOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL + fi +else + MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" +fi + +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 +$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } +if ${lt_cv_path_mainfest_tool+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&5 + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 +$as_echo "$lt_cv_path_mainfest_tool" >&6; } +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi + + + + + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_LIPO="lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL="otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if ${lt_cv_apple_cc_single_mod+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&5 + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if ${lt_cv_ld_exported_symbols_list+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if ${lt_cv_ld_force_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 + echo "$RANLIB libconftest.a" >&5 + $RANLIB libconftest.a 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&5 + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[012][,.]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + + + +# Set options +# Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_static=no +fi + + + + + + + + + + + enable_dlopen=no + + + enable_win32_dll=no + + + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + pic_mode=default +fi + + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_fast_install=yes +fi + + + + + + + + + shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[5-9]*,yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 +$as_echo_n "checking which variant of shared library versioning to provide... " >&6; } + +# Check whether --with-aix-soname was given. +if test "${with_aix_soname+set}" = set; then : + withval=$with_aix_soname; case $withval in + aix|svr4|both) + ;; + *) + as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname +else + if ${lt_cv_with_aix_soname+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_with_aix_soname=aix +fi + + with_aix_soname=$lt_cv_with_aix_soname +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 +$as_echo "$with_aix_soname" >&6; } + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if ${lt_cv_objdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +func_cc_basename $compiler +cc_basename=$func_cc_basename_result + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/${ac_tool_prefix}file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac +fi + +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac +fi + +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +lt_save_CC=$CC +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + + + + + + + lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + + + if test yes = "$GCC"; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + lt_prog_compiler_pic='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + if test -n "$lt_prog_compiler_pic"; then + lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + *Sun\ F* | *Sun*Fortran*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + *Intel*\ [CF]*Compiler*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + *Portland\ Group*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic=$lt_prog_compiler_pic +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 +$as_echo "$lt_cv_prog_compiler_pic" >&6; } +lt_prog_compiler_pic=$lt_cv_prog_compiler_pic + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if ${lt_cv_prog_compiler_pic_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test yes = "$lt_cv_prog_compiler_pic_works"; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi + + + + + + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test yes = "$lt_cv_prog_compiler_static_works"; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + +hard_links=nottested +if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test no = "$hard_links"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + esac + + ld_shlibs=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + export_dynamic_flag_spec='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='$wl--export-all-symbols' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + export_dynamic_flag_spec='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + ld_shlibs=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test no = "$ld_shlibs"; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix[4-9]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + hardcode_direct=no + hardcode_direct_absolute=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + export_dynamic_flag_spec='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' $wl-bernotok' + allow_undefined_flag=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi + archive_cmds_need_lc=yes + archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + always_export_symbols=yes + file_list_spec='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, )='true' + enable_shared_with_static_runtimes=yes + exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + old_postinstall_cmds='chmod 644 $oldlib' + postlink_cmds='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + enable_shared_with_static_runtimes=yes + ;; + esac + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + if test yes = "$lt_cv_ld_force_load"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + + else + whole_archive_flag_spec='' + fi + link_all_deplibs=yes + allow_undefined_flag=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + + else + ld_shlibs=no + fi + + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test yes = "$GCC"; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if ${lt_cv_prog_compiler__b+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -b" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test yes = "$lt_cv_prog_compiler__b"; then + archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +fi + + ;; + esac + fi + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 +$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } +if ${lt_cv_irix_exported_symbol+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo (void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_irix_exported_symbol=yes +else + lt_cv_irix_exported_symbol=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 +$as_echo "$lt_cv_irix_exported_symbol" >&6; } + if test yes = "$lt_cv_irix_exported_symbol"; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + link_all_deplibs=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + ld_shlibs=yes + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' + else + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + fi + else + ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + + osf3*) + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='$wl-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='$wl-z,text' + allow_undefined_flag='$wl-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='$wl-R,$libdir' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='$wl-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test no = "$ld_shlibs" && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([A-Za-z]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + + + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[4-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a(lib.so.V)' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[23].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + hardcode_libdir_flag_spec='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Add ABI-specific directories to the system library path. + sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test yes = "$hardcode_automatic"; then + + # We can hardcode non-existent directories. + if test no != "$hardcode_direct" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && + test no != "$hardcode_minus_L"; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test relink = "$hardcode_action" || + test yes = "$inherit_rpath"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else + + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : + lt_cv_dlopen=shl_load +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + lt_cv_dlopen=dlopen +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if ${ac_cv_lib_svld_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if ${ac_cv_lib_dld_dld_link+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : + lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test yes = "$cross_compiling"; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$lt_cv_dlopen_self" >&6; } + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self_static+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test yes = "$cross_compiling"; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +fi + + + + + + + + + + + + + # Report what library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[4-9]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC=$lt_save_CC + + + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _mwvalidcheckl in -lmw" >&5 +$as_echo_n "checking for _mwvalidcheckl in -lmw... " >&6; } +if ${ac_cv_lib_mw__mwvalidcheckl+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lmw $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char _mwvalidcheckl (); +int +main () +{ +return _mwvalidcheckl (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_mw__mwvalidcheckl=yes +else + ac_cv_lib_mw__mwvalidcheckl=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mw__mwvalidcheckl" >&5 +$as_echo "$ac_cv_lib_mw__mwvalidcheckl" >&6; } +if test "x$ac_cv_lib_mw__mwvalidcheckl" = xyes; then : + LIBM=-lmw +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5 +$as_echo_n "checking for cos in -lm... " >&6; } +if ${ac_cv_lib_m_cos+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char cos (); +int +main () +{ +return cos (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_cos=yes +else + ac_cv_lib_m_cos=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_cos" >&5 +$as_echo "$ac_cv_lib_m_cos" >&6; } +if test "x$ac_cv_lib_m_cos" = xyes; then : + LIBM="$LIBM -lm" +fi + + ;; +*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5 +$as_echo_n "checking for cos in -lm... " >&6; } +if ${ac_cv_lib_m_cos+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char cos (); +int +main () +{ +return cos (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_cos=yes +else + ac_cv_lib_m_cos=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_cos" >&5 +$as_echo "$ac_cv_lib_m_cos" >&6; } +if test "x$ac_cv_lib_m_cos" = xyes; then : + LIBM=-lm +fi + + ;; +esac + + + +# Checks for header files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + + +# required versions for dependencies + + + + + + + + + + + + +GLIB_REQ_VERSION=2.44.0 + +COGL_REQ_VERSION=1.21.2 + +JSON_GLIB_REQ_VERSION=0.12.0 + +ATK_REQ_VERSION=2.5.3 + +CAIRO_REQ_VERSION=1.14.0 + +PANGO_REQ_VERSION=1.30 + +GI_REQ_VERSION=1.39.0 + +XCOMPOSITE_REQ_VERSION=0.4 + +GDK_REQ_VERSION=3.3.18 + +LIBINPUT_REQ_VERSION=1.4.0 + +LIBUDEV_REQ_VERSION=136 + + +# Checks for typedefs, structures, and compiler characteristics. +# Check whether --enable-glibtest was given. +if test "${enable_glibtest+set}" = set; then : + enableval=$enable_glibtest; +else + enable_glibtest=yes +fi + + + pkg_config_args=glib-2.0 + for module in . gobject gio gthread gmodule-no-export + do + case "$module" in + gmodule) + pkg_config_args="$pkg_config_args gmodule-2.0" + ;; + gmodule-no-export) + pkg_config_args="$pkg_config_args gmodule-no-export-2.0" + ;; + gobject) + pkg_config_args="$pkg_config_args gobject-2.0" + ;; + gthread) + pkg_config_args="$pkg_config_args gthread-2.0" + ;; + gio*) + pkg_config_args="$pkg_config_args $module-2.0" + ;; + esac + done + + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.16 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi + + no_glib="" + + if test "x$PKG_CONFIG" = x ; then + no_glib=yes + PKG_CONFIG=no + fi + + min_glib_version=2.44.0 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLIB - version >= $min_glib_version" >&5 +$as_echo_n "checking for GLIB - version >= $min_glib_version... " >&6; } + + if test x$PKG_CONFIG != xno ; then + ## don't try to run the test against uninstalled libtool libs + if $PKG_CONFIG --uninstalled $pkg_config_args; then + echo "Will use uninstalled version of GLib found in PKG_CONFIG_PATH" + enable_glibtest=no + fi + + if $PKG_CONFIG --atleast-version $min_glib_version $pkg_config_args; then + : + else + no_glib=yes + fi + fi + + if test x"$no_glib" = x ; then + GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0` + GOBJECT_QUERY=`$PKG_CONFIG --variable=gobject_query glib-2.0` + GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0` + GLIB_COMPILE_RESOURCES=`$PKG_CONFIG --variable=glib_compile_resources gio-2.0` + + GLIB_CFLAGS=`$PKG_CONFIG --cflags $pkg_config_args` + GLIB_LIBS=`$PKG_CONFIG --libs $pkg_config_args` + glib_config_major_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'` + glib_config_minor_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'` + glib_config_micro_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'` + if test "x$enable_glibtest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GLIB_CFLAGS" + LIBS="$GLIB_LIBS $LIBS" + rm -f conf.glibtest + if test "$cross_compiling" = yes; then : + echo $ac_n "cross compiling; assumed OK... $ac_c" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +#include + +int +main () +{ + unsigned int major, minor, micro; + + fclose (fopen ("conf.glibtest", "w")); + + if (sscanf("$min_glib_version", "%u.%u.%u", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_glib_version"); + exit(1); + } + + if ((glib_major_version != $glib_config_major_version) || + (glib_minor_version != $glib_config_minor_version) || + (glib_micro_version != $glib_config_micro_version)) + { + printf("\n*** 'pkg-config --modversion glib-2.0' returned %d.%d.%d, but GLIB (%d.%d.%d)\n", + $glib_config_major_version, $glib_config_minor_version, $glib_config_micro_version, + glib_major_version, glib_minor_version, glib_micro_version); + printf ("*** was found! If pkg-config was correct, then it is best\n"); + printf ("*** to remove the old version of GLib. You may also be able to fix the error\n"); + printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); + printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); + printf("*** required on your system.\n"); + printf("*** If pkg-config was wrong, set the environment variable PKG_CONFIG_PATH\n"); + printf("*** to point to the correct configuration files\n"); + } + else if ((glib_major_version != GLIB_MAJOR_VERSION) || + (glib_minor_version != GLIB_MINOR_VERSION) || + (glib_micro_version != GLIB_MICRO_VERSION)) + { + printf("*** GLIB header files (version %d.%d.%d) do not match\n", + GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION); + printf("*** library (version %d.%d.%d)\n", + glib_major_version, glib_minor_version, glib_micro_version); + } + else + { + if ((glib_major_version > major) || + ((glib_major_version == major) && (glib_minor_version > minor)) || + ((glib_major_version == major) && (glib_minor_version == minor) && (glib_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** An old version of GLIB (%u.%u.%u) was found.\n", + glib_major_version, glib_minor_version, glib_micro_version); + printf("*** You need a version of GLIB newer than %u.%u.%u. The latest version of\n", + major, minor, micro); + printf("*** GLIB is always available from ftp://ftp.gtk.org.\n"); + printf("***\n"); + printf("*** If you have already installed a sufficiently new version, this error\n"); + printf("*** probably means that the wrong copy of the pkg-config shell script is\n"); + printf("*** being found. The easiest way to fix this is to remove the old version\n"); + printf("*** of GLIB, but you can also set the PKG_CONFIG environment to point to the\n"); + printf("*** correct copy of pkg-config. (In this case, you will have to\n"); + printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); + printf("*** so that the correct libraries are found at run-time))\n"); + } + } + return 1; +} + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + no_glib=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_glib" = x ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (version $glib_config_major_version.$glib_config_minor_version.$glib_config_micro_version)" >&5 +$as_echo "yes (version $glib_config_major_version.$glib_config_minor_version.$glib_config_micro_version)" >&6; } + : + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + if test "$PKG_CONFIG" = "no" ; then + echo "*** A new enough version of pkg-config was not found." + echo "*** See http://www.freedesktop.org/software/pkgconfig/" + else + if test -f conf.glibtest ; then + : + else + echo "*** Could not run GLIB test program, checking why..." + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GLIB_CFLAGS" + LIBS="$LIBS $GLIB_LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include + +int +main () +{ + return ((glib_major_version) || (glib_minor_version) || (glib_micro_version)); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding GLIB or finding the wrong" + echo "*** version of GLIB. If it is not finding GLIB, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" +else + echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means GLIB is incorrectly installed." +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + GLIB_CFLAGS="" + GLIB_LIBS="" + GLIB_GENMARSHAL="" + GOBJECT_QUERY="" + GLIB_MKENUMS="" + GLIB_COMPILE_RESOURCES="" + as_fn_error $? "glib-2.0 is required" "$LINENO" 5 + fi + + + + + + + rm -f conf.glibtest + + +# Check for -Bsymbolic-functions to avoid intra-library PLT jumps +# Check whether --enable-Bsymbolic was given. +if test "${enable_Bsymbolic+set}" = set; then : + enableval=$enable_Bsymbolic; +else + + saved_LDFLAGS="${LDFLAGS}" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -Bsymbolic-functions linker flag" >&5 +$as_echo_n "checking for -Bsymbolic-functions linker flag... " >&6; } + LDFLAGS=-Wl,-Bsymbolic-functions + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +int main (void) { return 0; } + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + enable_Bsymbolic=yes + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + enable_Bsymbolic=no + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="${saved_LDFLAGS}" + +fi + + +if test "x$enable_Bsymbolic" = "xyes"; then : + CLUTTER_LINK_FLAGS=-Wl,-Bsymbolic-functions +fi + + +# Check for the visibility flags +CLUTTER_HIDDEN_VISIBILITY_CFLAGS="" +SAVED_CFLAGS="${CFLAGS}" +CFLAGS="-fvisibility=hidden" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -fvisibility=hidden compiler flag" >&5 +$as_echo_n "checking for -fvisibility=hidden compiler flag... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +int main (void) { return 0; } + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + enable_fvisibility_hidden=yes +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + enable_fvisibility_hidden=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +CFLAGS="${SAVED_CFLAGS}" + +if test "${enable_fvisibility_hidden}" = "yes"; then : + + +$as_echo "#define _CLUTTER_EXTERN __attribute__((visibility(\"default\"))) extern" >>confdefs.h + + CLUTTER_HIDDEN_VISIBILITY_CFLAGS="-fvisibility=hidden" + +fi + + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + + +FLAVOUR_LIBS="" +FLAVOUR_CFLAGS="" +CLUTTER_BACKENDS="" +CLUTTER_INPUT_BACKENDS="" +CLUTTER_CONFIG_DEFINES= + +# base dependencies for core +CLUTTER_BASE_PC_FILES="cairo-gobject >= $CAIRO_REQ_VERSION gio-2.0 >= 2.44.0 atk >= $ATK_REQ_VERSION pangocairo >= $PANGO_REQ_VERSION json-glib-1.0 >= $JSON_GLIB_REQ_VERSION" + +# private base dependencies +CLUTTER_BASE_PC_FILES_PRIVATE="" + +# backend specific pkg-config files +BACKEND_PC_FILES="" + +# private backend specific dependencies +BACKEND_PC_FILES_PRIVATE="" + + +CLUTTER_BACKENDS="$CLUTTER_BACKENDS x11" +CLUTTER_INPUT_BACKENDS="$CLUTTER_INPUT_BACKENDS x11" + +SUPPORT_X11=1 +SUPPORT_GLX=1 +SUPPORT_COGL=1 + +# we use fontconfig API and pango-ft2 when the fontconfig +# configuration changes; we don't expose any API for this +# so we add pango-ft2 to the private Requires. +if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"pangoft2\""; } >&5 + ($PKG_CONFIG --exists --print-errors "pangoft2") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + + +$as_echo "#define HAVE_PANGO_FT2 1" >>confdefs.h + + BACKEND_PC_FILES_PRIVATE="$BACKEND_PC_FILES_PRIVATE pangoft2" + +fi + +# Check whether --enable-wayland-egl-server was given. +if test "${enable_wayland_egl_server+set}" = set; then : + enableval=$enable_wayland_egl_server; +else + enable_wayland_egl_server=yes + +fi + + +if test "x$enable_wayland_egl_server" = "xyes"; then : + + CLUTTER_BACKENDS="$CLUTTER_BACKENDS egl" + SUPPORT_EGL=1 + +$as_echo "#define CLUTTER_EGL_BACKEND_GENERIC 1" >>confdefs.h + + + BACKEND_PC_FILES="$BACKEND_PC_FILES wayland-egl wayland-server libdrm gbm" + + SUPPORT_WAYLAND_COMPOSITOR=1 + CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES + #define CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT 1" + + CLUTTER_INPUT_BACKENDS="$CLUTTER_INPUT_BACKENDS evdev" + + SUPPORT_EVDEV=1 + BACKEND_PC_FILES_PRIVATE="$BACKEND_PC_FILES_PRIVATE libudev >= $LIBUDEV_REQ_VERSION libinput >= $LIBINPUT_REQ_VERSION xkbcommon" + +$as_echo "#define HAVE_EVDEV 1" >>confdefs.h + + +fi + + if test "x$enable_wayland_egl_server" = "xyes"; then + SUPPORT_WAYLAND_TRUE= + SUPPORT_WAYLAND_FALSE='#' +else + SUPPORT_WAYLAND_TRUE='#' + SUPPORT_WAYLAND_FALSE= +fi + + + +cat >>confdefs.h <<_ACEOF +#define CLUTTER_DRIVERS "*" +_ACEOF + + +CLUTTER_BACKENDS=${CLUTTER_BACKENDS#* } + + +CLUTTER_INPUT_BACKENDS=${CLUTTER_INPUT_BACKENDS#* } + + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + + +# windowing systems +if test "x$SUPPORT_X11" = "x1"; then : + CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES +#define CLUTTER_WINDOWING_X11 \"x11\" +#define CLUTTER_INPUT_X11 \"x11\"" +fi +if test "x$SUPPORT_GLX" = "x1"; then : + CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES +#define CLUTTER_WINDOWING_GLX \"glx\"" +fi +if test "x$SUPPORT_EGL" = "x1"; then : + CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES +#define CLUTTER_WINDOWING_EGL \"eglnative\"" +fi +if test "x$SUPPORT_EVDEV" = "x1"; then : + CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES +#define CLUTTER_INPUT_EVDEV \"evdev\"" +fi + +# the 'null' input backend is special +CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES +#define CLUTTER_INPUT_NULL \"null\"" + + + +CLUTTER_WINSYS=deprecated + +CLUTTER_WINSYS_BASE=deprecated + +CLUTTER_STAGE_TYPE=deprecated + +CLUTTER_SONAME_INFIX=deprecated + +CLUTTER_FLAVOUR=deprecated + +CLUTTER_COGL=deprecated + +COGL_DRIVER=deprecated + + +X11_PC_FILES="" +X11_EXTS="" +x11_tests=no + +if test "x$SUPPORT_X11" = "x1"; then : + + # base X11 includes and libraries + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X11" >&5 +$as_echo_n "checking for X11... " >&6; } + + # start with pkg-config + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"x11\""; } >&5 + ($PKG_CONFIG --exists --print-errors "x11") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + have_x11=yes +else + have_x11=no +fi + if test "x$have_x11" = "xyes"; then : + + X11_PC_FILES="x11" + + # we actually need to ask for CFLAGS and LIBS + X11_CFLAGS=`$PKG_CONFIG --cflags $X11_PC_FILES` + X11_LIBS=`$PKG_CONFIG --libs $X11_PC_FILES` + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5 +$as_echo "found" >&6; } + +else + + # no pkg-config, let's go old school + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X" >&5 +$as_echo_n "checking for X... " >&6; } + + +# Check whether --with-x was given. +if test "${with_x+set}" = set; then : + withval=$with_x; +fi + +# $have_x is `yes', `no', `disabled', or empty when we do not yet know. +if test "x$with_x" = xno; then + # The user explicitly disabled X. + have_x=disabled +else + case $x_includes,$x_libraries in #( + *\'*) as_fn_error $? "cannot use X directory names containing '" "$LINENO" 5;; #( + *,NONE | NONE,*) if ${ac_cv_have_x+:} false; then : + $as_echo_n "(cached) " >&6 +else + # One or both of the vars are not set, and there is no cached value. +ac_x_includes=no ac_x_libraries=no +rm -f -r conftest.dir +if mkdir conftest.dir; then + cd conftest.dir + cat >Imakefile <<'_ACEOF' +incroot: + @echo incroot='${INCROOT}' +usrlibdir: + @echo usrlibdir='${USRLIBDIR}' +libdir: + @echo libdir='${LIBDIR}' +_ACEOF + if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then + # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. + for ac_var in incroot usrlibdir libdir; do + eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`" + done + # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. + for ac_extension in a so sl dylib la dll; do + if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" && + test -f "$ac_im_libdir/libX11.$ac_extension"; then + ac_im_usrlibdir=$ac_im_libdir; break + fi + done + # Screen out bogus values from the imake configuration. They are + # bogus both because they are the default anyway, and because + # using them would break gcc on systems where it needs fixed includes. + case $ac_im_incroot in + /usr/include) ac_x_includes= ;; + *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; + esac + case $ac_im_usrlibdir in + /usr/lib | /usr/lib64 | /lib | /lib64) ;; + *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; + esac + fi + cd .. + rm -f -r conftest.dir +fi + +# Standard set of common directories for X headers. +# Check X11 before X11Rn because it is often a symlink to the current release. +ac_x_header_dirs=' +/usr/X11/include +/usr/X11R7/include +/usr/X11R6/include +/usr/X11R5/include +/usr/X11R4/include + +/usr/include/X11 +/usr/include/X11R7 +/usr/include/X11R6 +/usr/include/X11R5 +/usr/include/X11R4 + +/usr/local/X11/include +/usr/local/X11R7/include +/usr/local/X11R6/include +/usr/local/X11R5/include +/usr/local/X11R4/include + +/usr/local/include/X11 +/usr/local/include/X11R7 +/usr/local/include/X11R6 +/usr/local/include/X11R5 +/usr/local/include/X11R4 + +/usr/X386/include +/usr/x386/include +/usr/XFree86/include/X11 + +/usr/include +/usr/local/include +/usr/unsupported/include +/usr/athena/include +/usr/local/x11r5/include +/usr/lpp/Xamples/include + +/usr/openwin/include +/usr/openwin/share/include' + +if test "$ac_x_includes" = no; then + # Guess where to find include files, by looking for Xlib.h. + # First, try using that file with no special directory specified. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # We can compile using X headers with no special include directory. +ac_x_includes= +else + for ac_dir in $ac_x_header_dirs; do + if test -r "$ac_dir/X11/Xlib.h"; then + ac_x_includes=$ac_dir + break + fi +done +fi +rm -f conftest.err conftest.i conftest.$ac_ext +fi # $ac_x_includes = no + +if test "$ac_x_libraries" = no; then + # Check for the libraries. + # See if we find them without any special options. + # Don't add to $LIBS permanently. + ac_save_LIBS=$LIBS + LIBS="-lX11 $LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +XrmInitialize () + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + LIBS=$ac_save_LIBS +# We can link X programs with no special library path. +ac_x_libraries= +else + LIBS=$ac_save_LIBS +for ac_dir in `$as_echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g` +do + # Don't even attempt the hair of trying to link an X program! + for ac_extension in a so sl dylib la dll; do + if test -r "$ac_dir/libX11.$ac_extension"; then + ac_x_libraries=$ac_dir + break 2 + fi + done +done +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi # $ac_x_libraries = no + +case $ac_x_includes,$ac_x_libraries in #( + no,* | *,no | *\'*) + # Didn't find X, or a directory has "'" in its name. + ac_cv_have_x="have_x=no";; #( + *) + # Record where we found X for the cache. + ac_cv_have_x="have_x=yes\ + ac_x_includes='$ac_x_includes'\ + ac_x_libraries='$ac_x_libraries'" +esac +fi +;; #( + *) have_x=yes;; + esac + eval "$ac_cv_have_x" +fi # $with_x != no + +if test "$have_x" != yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_x" >&5 +$as_echo "$have_x" >&6; } + no_x=yes +else + # If each of the values was on the command line, it overrides each guess. + test "x$x_includes" = xNONE && x_includes=$ac_x_includes + test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries + # Update the cache value to reflect the command line values. + ac_cv_have_x="have_x=yes\ + ac_x_includes='$x_includes'\ + ac_x_libraries='$x_libraries'" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: libraries $x_libraries, headers $x_includes" >&5 +$as_echo "libraries $x_libraries, headers $x_includes" >&6; } +fi + + + if test "x$no_x" = "xyes"; then : + as_fn_error $? "No X11 Libraries found" "$LINENO" 5 +else + + if test "x$x_includes" != "xNONE" && test -n "$x_includes"; then : + X11_CFLAGS=-I`echo $x_includes | sed -e "s/:/ -I/g"` +fi + + if test "x$x_libraries" != "xNONE" && test -n "$x_libraries"; then : + X11_LIBS=-L`echo $x_libraries | sed -e "s/:/ -L/g"` +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5 +$as_echo "found" >&6; } + + +fi + + +fi + + # XEXT (required) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XEXT extension" >&5 +$as_echo_n "checking for XEXT extension... " >&6; } + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"xext\""; } >&5 + ($PKG_CONFIG --exists --print-errors "xext") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + have_xext=yes +else + have_xext=no +fi + if test "x$have_xext" = "xyes"; then : + + +$as_echo "#define HAVE_XEXT 1" >>confdefs.h + + + X11_LIBS="$X11_LIBS -lXext" + X11_PC_FILES="$X11_PC_FILES xext" + X11_EXTS="$X11_EXTS xext" + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5 +$as_echo "found" >&6; } + +else + as_fn_error $? "Not found" "$LINENO" 5 + +fi + + # XDAMAGE (required) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XDAMAGE extension" >&5 +$as_echo_n "checking for XDAMAGE extension... " >&6; } + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"xdamage\""; } >&5 + ($PKG_CONFIG --exists --print-errors "xdamage") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + have_xdamage=yes +else + have_xdamage=no +fi + if test "x$have_xdamage" = "xyes"; then : + + +$as_echo "#define HAVE_XDAMAGE 1" >>confdefs.h + + + X11_LIBS="$X11_LIBS -lXdamage" + X11_PC_FILES="$X11_PC_FILES xdamage" + X11_EXTS="$X11_EXTS xdamage" + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5 +$as_echo "found" >&6; } + +else + as_fn_error $? "not found" "$LINENO" 5 + +fi + + # XCOMPOSITE (optional) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XCOMPOSITE extension >= $XCOMPOSITE_REQ_VERSION" >&5 +$as_echo_n "checking for XCOMPOSITE extension >= $XCOMPOSITE_REQ_VERSION... " >&6; } + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"xcomposite >= \$XCOMPOSITE_REQ_VERSION\""; } >&5 + ($PKG_CONFIG --exists --print-errors "xcomposite >= $XCOMPOSITE_REQ_VERSION") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + have_xcomposite=yes +else + have_xcomposite=no +fi + if test "x$have_xcomposite" = "xyes"; then : + + +$as_echo "#define HAVE_XCOMPOSITE 1" >>confdefs.h + + + X11_LIBS="$X11_LIBS -lXcomposite" + X11_PC_FILES="$X11_PC_FILES xcomposite >= $XCOMPOSITE_REQ_VERSION" + X11_EXTS="$X11_EXTS xcomposite" + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5 +$as_echo "found" >&6; } + +else + as_fn_error $? "not found" "$LINENO" 5 + +fi + + # X Generic Extensions (optional) + clutter_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $X11_CFLAGS" + + clutter_save_LIBS="$LIBS" + LIBS="$LIBS $X11_LIBS" + + have_xge=no + ac_fn_c_check_func "$LINENO" "XGetEventData" "ac_cv_func_XGetEventData" +if test "x$ac_cv_func_XGetEventData" = xyes; then : + + +$as_echo "#define HAVE_XGE 1" >>confdefs.h + + have_xge=yes + X11_EXTS="$X11_EXTS xge" + +fi + + + CPPFLAGS="$clutter_save_CPPFLAGS" + LIBS="$clutter_save_LIBS" + + # XI (optional) + # Check whether --enable-xinput was given. +if test "${enable_xinput+set}" = set; then : + enableval=$enable_xinput; +else + enable_xinput=yes +fi + + + if test "x$enable_xinput" = "xyes"; then : + + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"xi\""; } >&5 + ($PKG_CONFIG --exists --print-errors "xi") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + have_xinput=yes +else + have_xinput=no +fi + +else + + have_xinput=no + +fi + + case $have_xinput in #( + yes) : + + for ac_header in X11/extensions/XInput2.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "X11/extensions/XInput2.h" "ac_cv_header_X11_extensions_XInput2_h" "$ac_includes_default" +if test "x$ac_cv_header_X11_extensions_XInput2_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_X11_EXTENSIONS_XINPUT2_H 1 +_ACEOF + + have_xinput2=yes + +$as_echo "#define HAVE_XINPUT_2 1" >>confdefs.h + + +fi + +done + + + clutter_save_LIBS="$LIBS" + LIBS="$LIBS -lXi" + + ac_fn_c_check_func "$LINENO" "XIAllowTouchEvents" "ac_cv_func_XIAllowTouchEvents" +if test "x$ac_cv_func_XIAllowTouchEvents" = xyes; then : + + ac_fn_c_check_member "$LINENO" "XIScrollClassInfo" "number" "ac_cv_member_XIScrollClassInfo_number" "#include +" +if test "x$ac_cv_member_XIScrollClassInfo_number" = xyes; then : + + have_xinput_2_2=yes + +$as_echo "#define HAVE_XINPUT_2_2 1" >>confdefs.h + + +else + have_xinput_2_2=no +fi + +fi + + + LIBS="$clutter_save_LIBS" + + X11_LIBS="$X11_LIBS $XINPUT_LIBS" + X11_PC_FILES="$X11_PC_FILES xi" + + if test "x$have_xinput_2_2" = "xyes"; then : + X11_EXTS="$X11_EXTS xi2.2" +else + X11_EXTS="$X11_EXTS xi2.0" +fi + ;; #( + no) : + have_xinput2=no ;; #( + *) : + as_fn_error $? "Invalid argument for --enable-xinput" "$LINENO" 5 + ;; #( + *) : + ;; +esac + + # XKB + clutter_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $X11_CFLAGS" + + clutter_save_LIBS="$LIBS" + LIBS="$LIBS $X11_LIBS" + + have_xkb=no + ac_fn_c_check_func "$LINENO" "XkbQueryExtension" "ac_cv_func_XkbQueryExtension" +if test "x$ac_cv_func_XkbQueryExtension" = xyes; then : + + +$as_echo "#define HAVE_XKB 1" >>confdefs.h + + have_xkb=yes + + X11_EXTS="$X11_EXTS xkb" + +fi + + + CPPFLAGS="$clutter_save_CPPFLAGS" + LIBS="$clutter_save_LIBS" + + x11_tests=yes + BACKEND_PC_FILES="$BACKEND_PC_FILES $X11_PC_FILES" + FLAVOUR_LIBS="$FLAVOUR_LIBS $X11_LIBS" + FLAVOUR_CFLAGS="$FLAVOUR_CFLAGS $X11_CFLAGS" + + +fi + + if test "x$have_xinput2" = "xyes"; then + BUILD_XI2_TRUE= + BUILD_XI2_FALSE='#' +else + BUILD_XI2_TRUE='#' + BUILD_XI2_FALSE= +fi + + if test "x$x11_tests" = "xyes"; then + X11_TESTS_TRUE= + X11_TESTS_FALSE='#' +else + X11_TESTS_TRUE='#' + X11_TESTS_FALSE= +fi + + +X11_EXTS=${X11_EXTS#* } + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + + + +# Check whether --enable-gdk-pixbuf was given. +if test "${enable_gdk_pixbuf+set}" = set; then : + enableval=$enable_gdk_pixbuf; enable_pixbuf=$enable_val +else + enable_pixbuf=yes +fi + + +case $enable_pixbuf in #( + yes) : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GDK_PIXBUF" >&5 +$as_echo_n "checking for GDK_PIXBUF... " >&6; } + +if test -n "$GDK_PIXBUF_CFLAGS"; then + pkg_cv_GDK_PIXBUF_CFLAGS="$GDK_PIXBUF_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gdk-pixbuf-2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gdk-pixbuf-2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GDK_PIXBUF_CFLAGS=`$PKG_CONFIG --cflags "gdk-pixbuf-2.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$GDK_PIXBUF_LIBS"; then + pkg_cv_GDK_PIXBUF_LIBS="$GDK_PIXBUF_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gdk-pixbuf-2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gdk-pixbuf-2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GDK_PIXBUF_LIBS=`$PKG_CONFIG --libs "gdk-pixbuf-2.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GDK_PIXBUF_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gdk-pixbuf-2.0" 2>&1` + else + GDK_PIXBUF_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gdk-pixbuf-2.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$GDK_PIXBUF_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (gdk-pixbuf-2.0) were not met: + +$GDK_PIXBUF_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables GDK_PIXBUF_CFLAGS +and GDK_PIXBUF_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables GDK_PIXBUF_CFLAGS +and GDK_PIXBUF_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + GDK_PIXBUF_CFLAGS=$pkg_cv_GDK_PIXBUF_CFLAGS + GDK_PIXBUF_LIBS=$pkg_cv_GDK_PIXBUF_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + + + pixbuf_tests=yes + ;; #( + no) : + + pixbuf_tests=no + + ;; #( + *) : + ;; +esac + + if test "x$pixbuf_tests" = "xyes"; then + PIXBUF_TESTS_TRUE= + PIXBUF_TESTS_FALSE='#' +else + PIXBUF_TESTS_TRUE='#' + PIXBUF_TESTS_FALSE= +fi + + + + +# Check whether --enable-debug was given. +if test "${enable_debug+set}" = set; then : + enableval=$enable_debug; +else + enable_debug=minimum +fi + + +case $enable_debug in #( + yes) : + + test "$cflags_set" = set || CFLAGS="$CFLAGS -g" + CLUTTER_DEBUG_CFLAGS="-DCLUTTER_ENABLE_DEBUG" + ;; #( + minimum) : + CLUTTER_DEBUG_CFLAGS="-DG_DISABLE_CAST_CHECKS" ;; #( + no) : + CLUTTER_DEBUG_CFLAGS="-DG_DISABLE_ASSERT -DG_DISABLE_CHECKS -DG_DISABLE_CAST_CHECKS" ;; #( + *) : + as_fn_error $? "Unknown argument for --enable-debug" "$LINENO" 5 + ;; +esac + + + + + + +# Check whether --enable-deprecated was given. +if test "${enable_deprecated+set}" = set; then : + enableval=$enable_deprecated; +else + enable_deprecated=yes +fi + + +case $enable_deprecated in #( + no) : + + CLUTTER_DEPRECATED_CFLAGS="-DG_DISABLE_SINGLE_INCLUDES -DCOGL_DISABLE_DEPRECATED" + ;; #( + yes) : + + CLUTTER_DEPRECATED_CFLAGS="-DGLIB_DISABLE_DEPRECATION_WARNINGS" + ;; #( + *) : + as_fn_error $? "Unknown argument for --enable-deprecated" "$LINENO" 5 + ;; +esac + + + + +# use strict compiler flags only when building from git; the rules for +# distcheck will take care of turning this on when making a release + +# Check whether --enable-maintainer-flags was given. +if test "${enable_maintainer_flags+set}" = set; then : + enableval=$enable_maintainer_flags; +else + enable_maintainer_flags=yes +fi + + +MAINTAINER_COMPILER_FLAGS="$MAINTAINER_COMPILER_FLAGS + -Wall + -Wcast-align + -Wuninitialized + -Wno-strict-aliasing + -Wshadow" + +# Check whether --enable-Werror was given. +if test "${enable_Werror+set}" = set; then : + enableval=$enable_Werror; +else + enable_Werror=yes +fi + + +if test "x$enable_Werror" = xyes; then : + + MAINTAINER_COMPILER_FLAGS="$MAINTAINER_COMPILER_FLAGS + -Werror=logical-op + -Werror=pointer-arith + -Werror=missing-declarations + -Werror=redundant-decls + -Werror=empty-body + -Werror=format + -Werror=format-security + -Werror=format-nonliteral + -Werror=init-self + -Werror=declaration-after-statement + -Werror=vla" + +fi + +case $enable_maintainer_flags in #( + yes) : + + + list=$MAINTAINER_COMPILER_FLAGS + flags_supported="" + flags_unsupported="" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for supported compiler flags" >&5 +$as_echo_n "checking for supported compiler flags... " >&6; } + for each in $list + do + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $each" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + flag_ok=yes +else + flag_ok=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$save_CFLAGS" + + if test "X$flag_ok" = Xyes ; then + flags_supported="$flags_supported $each" + else + flags_unsupported="$flags_unsupported $each" + fi + done + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flags_supported" >&5 +$as_echo "$flags_supported" >&6; } + if test "X$flags_unsupported" != X ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unsupported compiler flags: $flags_unsupported" >&5 +$as_echo "$as_me: WARNING: unsupported compiler flags: $flags_unsupported" >&2;} + fi + MAINTAINER_CFLAGS="$MAINTAINER_CFLAGS $flags_supported" + + ;; #( + no) : + + ;; #( + error) : + + MAINTAINER_COMPILER_FLAGS="$MAINTAINER_COMPILER_FLAGS -Werror" + + list=$MAINTAINER_COMPILER_FLAGS + flags_supported="" + flags_unsupported="" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for supported compiler flags" >&5 +$as_echo_n "checking for supported compiler flags... " >&6; } + for each in $list + do + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $each" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + flag_ok=yes +else + flag_ok=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$save_CFLAGS" + + if test "X$flag_ok" = Xyes ; then + flags_supported="$flags_supported $each" + else + flags_unsupported="$flags_unsupported $each" + fi + done + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flags_supported" >&5 +$as_echo "$flags_supported" >&6; } + if test "X$flags_unsupported" != X ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unsupported compiler flags: $flags_unsupported" >&5 +$as_echo "$as_me: WARNING: unsupported compiler flags: $flags_unsupported" >&2;} + fi + MAINTAINER_CFLAGS="$MAINTAINER_CFLAGS $flags_supported" + + ;; #( + *) : + as_fn_error $? "Invalid option for --enable-maintainer-flags" "$LINENO" 5 + ;; #( + *) : + ;; +esac + +# strip leading spaces +MAINTAINER_CFLAGS=${MAINTAINER_CFLAGS#* } + + +# strip leading space +BACKEND_PC_FILES=${BACKEND_PC_FILES#* } + +# public dependencies, will fill the Requires: field of clutter.pc +CLUTTER_REQUIRES="$CLUTTER_BASE_PC_FILES $BACKEND_PC_FILES" + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CLUTTER_DEPS" >&5 +$as_echo_n "checking for CLUTTER_DEPS... " >&6; } + +if test -n "$CLUTTER_DEPS_CFLAGS"; then + pkg_cv_CLUTTER_DEPS_CFLAGS="$CLUTTER_DEPS_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$CLUTTER_REQUIRES\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$CLUTTER_REQUIRES") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_CLUTTER_DEPS_CFLAGS=`$PKG_CONFIG --cflags "$CLUTTER_REQUIRES" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$CLUTTER_DEPS_LIBS"; then + pkg_cv_CLUTTER_DEPS_LIBS="$CLUTTER_DEPS_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$CLUTTER_REQUIRES\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$CLUTTER_REQUIRES") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_CLUTTER_DEPS_LIBS=`$PKG_CONFIG --libs "$CLUTTER_REQUIRES" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + CLUTTER_DEPS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$CLUTTER_REQUIRES" 2>&1` + else + CLUTTER_DEPS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$CLUTTER_REQUIRES" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$CLUTTER_DEPS_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements ($CLUTTER_REQUIRES) were not met: + +$CLUTTER_DEPS_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables CLUTTER_DEPS_CFLAGS +and CLUTTER_DEPS_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables CLUTTER_DEPS_CFLAGS +and CLUTTER_DEPS_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + CLUTTER_DEPS_CFLAGS=$pkg_cv_CLUTTER_DEPS_CFLAGS + CLUTTER_DEPS_LIBS=$pkg_cv_CLUTTER_DEPS_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + +# private dependencies, will fill the Requires.private: field of clutter.pc +if test "x$CLUTTER_BASE_PC_FILES_PRIVATE" = "x" && test "x$BACKEND_PC_FILES_PRIVATE" = "x"; then : + + CLUTTER_REQUIRES_PRIVATE="" + CLUTTER_DEPS_PRIVATE_CFLAGS="" + CLUTTER_DEPS_PRIVATE_LIBS="" + +else + + CLUTTER_REQUIRES_PRIVATE="$CLUTTER_BASE_PC_FILES_PRIVATE $BACKEND_PC_FILES_PRIVATE" + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CLUTTER_DEPS_PRIVATE" >&5 +$as_echo_n "checking for CLUTTER_DEPS_PRIVATE... " >&6; } + +if test -n "$CLUTTER_DEPS_PRIVATE_CFLAGS"; then + pkg_cv_CLUTTER_DEPS_PRIVATE_CFLAGS="$CLUTTER_DEPS_PRIVATE_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$CLUTTER_REQUIRES_PRIVATE\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$CLUTTER_REQUIRES_PRIVATE") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_CLUTTER_DEPS_PRIVATE_CFLAGS=`$PKG_CONFIG --cflags "$CLUTTER_REQUIRES_PRIVATE" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$CLUTTER_DEPS_PRIVATE_LIBS"; then + pkg_cv_CLUTTER_DEPS_PRIVATE_LIBS="$CLUTTER_DEPS_PRIVATE_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$CLUTTER_REQUIRES_PRIVATE\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$CLUTTER_REQUIRES_PRIVATE") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_CLUTTER_DEPS_PRIVATE_LIBS=`$PKG_CONFIG --libs "$CLUTTER_REQUIRES_PRIVATE" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + CLUTTER_DEPS_PRIVATE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$CLUTTER_REQUIRES_PRIVATE" 2>&1` + else + CLUTTER_DEPS_PRIVATE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$CLUTTER_REQUIRES_PRIVATE" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$CLUTTER_DEPS_PRIVATE_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements ($CLUTTER_REQUIRES_PRIVATE) were not met: + +$CLUTTER_DEPS_PRIVATE_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables CLUTTER_DEPS_PRIVATE_CFLAGS +and CLUTTER_DEPS_PRIVATE_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables CLUTTER_DEPS_PRIVATE_CFLAGS +and CLUTTER_DEPS_PRIVATE_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + CLUTTER_DEPS_PRIVATE_CFLAGS=$pkg_cv_CLUTTER_DEPS_PRIVATE_CFLAGS + CLUTTER_DEPS_PRIVATE_LIBS=$pkg_cv_CLUTTER_DEPS_PRIVATE_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + +fi + + + + +CLUTTER_CFLAGS="$FLAVOUR_CFLAGS $CLUTTER_DEPS_CFLAGS $CLUTTER_DEPS_PRIVATE_CFLAGS $GLIB_CFLAGS" +CLUTTER_LIBS="$FLAVOUR_LIBS $CLUTTER_DEPS_LIBS $CLUTTER_DEPS_PRIVATE_LIBS $GLIB_LIBS" + + + + +# Check whether --enable-gcov was given. +if test "${enable_gcov+set}" = set; then : + enableval=$enable_gcov; use_gcov=$enableval +else + use_gcov=no +fi + + +if test "x$use_gcov" = "xyes"; then : + + if test "$GCC" != "yes"; then : + as_fn_error $? "GCC is required for --enable-gcov" "$LINENO" 5 +fi + + # Extract the first word of "shtool", so it can be a program name with args. +set dummy shtool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_SHTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$SHTOOL"; then + ac_cv_prog_SHTOOL="$SHTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_SHTOOL="shtool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +SHTOOL=$ac_cv_prog_SHTOOL +if test -n "$SHTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SHTOOL" >&5 +$as_echo "$SHTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + case `$SHTOOL path $CC` in #( + *ccache*) : + gcc_ccache=yes ;; #( + *) : + gcc_ccache=no ;; +esac + + if test "$gcc_ccache" = "yes" && (test -z "$CCACHE_DISABLE" || test "$CCACHE_DISABLE" != "1"); then + as_fn_error $? "ccache must be disabled when --enable-gcov option is used. You can disable ccache by setting environment variable CCACHE_DISABLE=1." "$LINENO" 5 + fi + + ltp_version_list="1.6 1.7 1.8 1.9 1.10" + # Extract the first word of "lcov", so it can be a program name with args. +set dummy lcov; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LTP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LTP"; then + ac_cv_prog_LTP="$LTP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LTP="lcov" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LTP=$ac_cv_prog_LTP +if test -n "$LTP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LTP" >&5 +$as_echo "$LTP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + # Extract the first word of "genhtml", so it can be a program name with args. +set dummy genhtml; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LTP_GENHTML+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LTP_GENHTML"; then + ac_cv_prog_LTP_GENHTML="$LTP_GENHTML" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LTP_GENHTML="genhtml" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LTP_GENHTML=$ac_cv_prog_LTP_GENHTML +if test -n "$LTP_GENHTML"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LTP_GENHTML" >&5 +$as_echo "$LTP_GENHTML" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + if test "$LTP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ltp version" >&5 +$as_echo_n "checking for ltp version... " >&6; } +if ${clutter_cv_ltp_version+:} false; then : + $as_echo_n "(cached) " >&6 +else + + clutter_cv_ltp_version=invalid + ltp_version=`$LTP -v 2>/dev/null | $SED -e 's/^.* //'` + for ltp_check_version in $ltp_version_list; do + if test "$ltp_version" = "$ltp_check_version"; then + clutter_cv_ltp_version="$ltp_check_version (ok)" + fi + done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $clutter_cv_ltp_version" >&5 +$as_echo "$clutter_cv_ltp_version" >&6; } + else + ltp_msg="To enable code coverage reporting you must have one of the following LTP versions installed: $ltp_version_list" + as_fn_error $? "$ltp_msg" "$LINENO" 5 + fi + + case $clutter_cv_ltp_version in + ""|invalid) + ltp_msg="You must have one of the following versions of LTP: $ltp_version_list (found: $ltp_version)." + as_fn_error $? "$ltp_msg" "$LINENO" 5 + LTP="exit 0;" + ;; + esac + + if test -z "$LTP_GENHTML"; then + as_fn_error $? "Could not find genhtml from the LTP package" "$LINENO" 5 + fi + + +$as_echo "#define HAVE_GCOV 1" >>confdefs.h + + + + CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9]*//g'` + CLUTTER_CFLAGS=`echo "$CLUTTER_CFLAGS" | $SED -e 's/-O[0-9]*//g'` + + + CLUTTER_GCOV_CFLAGS="-O0 -fprofile-arcs -ftest-coverage" + CLUTTER_GCOV_LDADD="-lgcov" + + + + + CLUTTER_CFLAGS="$CLUTTER_CFLAGS $CLUTTER_GCOV_CFLAGS" + CLUTTER_LIBS="$CLUTTER_LIBS $CLUTTER_GCOV_LDADD" + +fi + + if test "x$use_gcov" = "xyes"; then + ENABLE_GCOV_TRUE= + ENABLE_GCOV_FALSE='#' +else + ENABLE_GCOV_TRUE='#' + ENABLE_GCOV_FALSE= +fi + + + + + + + # Check whether --enable-introspection was given. +if test "${enable_introspection+set}" = set; then : + enableval=$enable_introspection; +else + enable_introspection=auto +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gobject-introspection" >&5 +$as_echo_n "checking for gobject-introspection... " >&6; } + + case $enable_introspection in #( + no) : + found_introspection="no (disabled, use --enable-introspection to enable)" + ;; #( + yes) : + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-introspection-1.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gobject-introspection-1.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + : +else + as_fn_error $? "gobject-introspection-1.0 is not installed" "$LINENO" 5 +fi + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-introspection-1.0 >= 1.39.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gobject-introspection-1.0 >= 1.39.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + found_introspection=yes +else + as_fn_error $? "You need to have gobject-introspection >= 1.39.0 installed to build clutter" "$LINENO" 5 +fi + ;; #( + auto) : + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-introspection-1.0 >= 1.39.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gobject-introspection-1.0 >= 1.39.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + found_introspection=yes +else + found_introspection=no +fi + enable_introspection=$found_introspection + ;; #( + *) : + as_fn_error $? "invalid argument passed to --enable-introspection, should be one of [no/auto/yes]" "$LINENO" 5 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $found_introspection" >&5 +$as_echo "$found_introspection" >&6; } + + INTROSPECTION_SCANNER= + INTROSPECTION_COMPILER= + INTROSPECTION_GENERATE= + INTROSPECTION_GIRDIR= + INTROSPECTION_TYPELIBDIR= + if test "x$found_introspection" = "xyes"; then + INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0` + INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0` + INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0` + INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0` + INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)" + INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0` + INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0` + INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection + fi + + + + + + + + + + if test "x$found_introspection" = "xyes"; then + HAVE_INTROSPECTION_TRUE= + HAVE_INTROSPECTION_FALSE='#' +else + HAVE_INTROSPECTION_TRUE='#' + HAVE_INTROSPECTION_FALSE= +fi + + + + + + + # Check whether --enable-installed-tests was given. +if test "${enable_installed_tests+set}" = set; then : + enableval=$enable_installed_tests; case ${enableval} in + yes) ENABLE_INSTALLED_TESTS="1" ;; + no) ENABLE_INSTALLED_TESTS="" ;; + *) as_fn_error $? "bad value ${enableval} for --enable-installed-tests" "$LINENO" 5 ;; + esac +fi + + if test "$ENABLE_INSTALLED_TESTS" = "1"; then + ENABLE_INSTALLED_TESTS_TRUE= + ENABLE_INSTALLED_TESTS_FALSE='#' +else + ENABLE_INSTALLED_TESTS_TRUE='#' + ENABLE_INSTALLED_TESTS_FALSE= +fi + + # Check whether --enable-always-build-tests was given. +if test "${enable_always_build_tests+set}" = set; then : + enableval=$enable_always_build_tests; case ${enableval} in + yes) ENABLE_ALWAYS_BUILD_TESTS="1" ;; + no) ENABLE_ALWAYS_BUILD_TESTS="" ;; + *) as_fn_error $? "bad value ${enableval} for --enable-always-build-tests" "$LINENO" 5 ;; + esac +fi + + if test "$ENABLE_ALWAYS_BUILD_TESTS" = "1"; then + ENABLE_ALWAYS_BUILD_TESTS_TRUE= + ENABLE_ALWAYS_BUILD_TESTS_FALSE='#' +else + ENABLE_ALWAYS_BUILD_TESTS_TRUE='#' + ENABLE_ALWAYS_BUILD_TESTS_FALSE= +fi + + if test "$ENABLE_INSTALLED_TESTS" = "1"; then + installed_test_metadir=${datadir}/installed-tests/clutter + + installed_testdir=${libexecdir}/installed-tests/clutter + + fi + + +# Check whether --enable-examples was given. +if test "${enable_examples+set}" = set; then : + enableval=$enable_examples; +else + enable_examples=no +fi + + if test "x$enable_examples" = "xyes"; then + BUILD_EXAMPLES_TRUE= + BUILD_EXAMPLES_FALSE='#' +else + BUILD_EXAMPLES_TRUE='#' + BUILD_EXAMPLES_FALSE= +fi + + + +ac_config_files="$ac_config_files Makefile build/Makefile build/autotools/Makefile clutter/Makefile clutter/clutter-config.h clutter/clutter-version.h clutter/mutter-clutter-$CLUTTER_API_VERSION.pc:clutter/mutter-clutter.pc.in tests/Makefile tests/accessibility/Makefile tests/conform/Makefile tests/interactive/Makefile tests/interactive/wrapper.sh tests/micro-bench/Makefile tests/performance/Makefile examples/Makefile" + + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 +$as_echo_n "checking that generated files are newer than configure... " >&6; } + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 +$as_echo "done" >&6; } + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${SUPPORT_WAYLAND_TRUE}" && test -z "${SUPPORT_WAYLAND_FALSE}"; then + as_fn_error $? "conditional \"SUPPORT_WAYLAND\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_XI2_TRUE}" && test -z "${BUILD_XI2_FALSE}"; then + as_fn_error $? "conditional \"BUILD_XI2\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${X11_TESTS_TRUE}" && test -z "${X11_TESTS_FALSE}"; then + as_fn_error $? "conditional \"X11_TESTS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${PIXBUF_TESTS_TRUE}" && test -z "${PIXBUF_TESTS_FALSE}"; then + as_fn_error $? "conditional \"PIXBUF_TESTS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ENABLE_GCOV_TRUE}" && test -z "${ENABLE_GCOV_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_GCOV\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_INTROSPECTION_TRUE}" && test -z "${HAVE_INTROSPECTION_FALSE}"; then + as_fn_error $? "conditional \"HAVE_INTROSPECTION\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ENABLE_INSTALLED_TESTS_TRUE}" && test -z "${ENABLE_INSTALLED_TESTS_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_INSTALLED_TESTS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ENABLE_ALWAYS_BUILD_TESTS_TRUE}" && test -z "${ENABLE_ALWAYS_BUILD_TESTS_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_ALWAYS_BUILD_TESTS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_EXAMPLES_TRUE}" && test -z "${BUILD_EXAMPLES_FALSE}"; then + as_fn_error $? "conditional \"BUILD_EXAMPLES\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by clutter $as_me 1.26.1, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to . +clutter home page: ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +clutter config.status 1.26.1 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' +lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' +want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' +nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' +lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' +configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in SHELL \ +ECHO \ +PATH_SEPARATOR \ +SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +OBJDUMP \ +deplibs_check_method \ +file_magic_cmd \ +file_magic_glob \ +want_nocaseglob \ +DLLTOOL \ +sharedlib_from_linklib_cmd \ +AR \ +AR_FLAGS \ +archiver_list_spec \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_import \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +lt_cv_nm_interface \ +nm_file_list_spec \ +lt_cv_truncate_bin \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_pic \ +lt_prog_compiler_wl \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +MANIFEST_TOOL \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_separator \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +install_override_mode \ +finish_eval \ +old_striplib \ +striplib; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postlink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +configure_time_dlsearch_path \ +configure_time_lt_sys_library_path; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +ac_aux_dir='$ac_aux_dir' + +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile' + + + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "clutter/clutter-build-config.h") CONFIG_HEADERS="$CONFIG_HEADERS clutter/clutter-build-config.h" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "build/Makefile") CONFIG_FILES="$CONFIG_FILES build/Makefile" ;; + "build/autotools/Makefile") CONFIG_FILES="$CONFIG_FILES build/autotools/Makefile" ;; + "clutter/Makefile") CONFIG_FILES="$CONFIG_FILES clutter/Makefile" ;; + "clutter/clutter-config.h") CONFIG_FILES="$CONFIG_FILES clutter/clutter-config.h" ;; + "clutter/clutter-version.h") CONFIG_FILES="$CONFIG_FILES clutter/clutter-version.h" ;; + "clutter/mutter-clutter-$CLUTTER_API_VERSION.pc") CONFIG_FILES="$CONFIG_FILES clutter/mutter-clutter-$CLUTTER_API_VERSION.pc:clutter/mutter-clutter.pc.in" ;; + "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;; + "tests/accessibility/Makefile") CONFIG_FILES="$CONFIG_FILES tests/accessibility/Makefile" ;; + "tests/conform/Makefile") CONFIG_FILES="$CONFIG_FILES tests/conform/Makefile" ;; + "tests/interactive/Makefile") CONFIG_FILES="$CONFIG_FILES tests/interactive/Makefile" ;; + "tests/interactive/wrapper.sh") CONFIG_FILES="$CONFIG_FILES tests/interactive/wrapper.sh" ;; + "tests/micro-bench/Makefile") CONFIG_FILES="$CONFIG_FILES tests/micro-bench/Makefile" ;; + "tests/performance/Makefile") CONFIG_FILES="$CONFIG_FILES tests/performance/Makefile" ;; + "examples/Makefile") CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "$am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + "libtool":C) + + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +# The names of the tagged configurations supported by this script. +available_tags='' + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# Shared archive member basename,for filename based shared library versioning on AIX. +shared_archive_member_spec=$shared_archive_member_spec + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + +# The PATH separator for the build system. +PATH_SEPARATOR=$lt_PATH_SEPARATOR + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# convert \$build file names to \$host format. +to_host_file_cmd=$lt_cv_to_host_file_cmd + +# convert \$build files to toolchain format. +to_tool_file_cmd=$lt_cv_to_tool_file_cmd + +# An object symbol dumper. +OBJDUMP=$lt_OBJDUMP + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method = "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob=$lt_file_magic_glob + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob=$lt_want_nocaseglob + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd + +# The archiver. +AR=$lt_AR + +# Flags to create an archive. +AR_FLAGS=$lt_AR_FLAGS + +# How to feed a file listing to the archiver. +archiver_list_spec=$lt_archiver_list_spec + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm into a list of symbols to manually relocate. +global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# The name lister interface. +nm_interface=$lt_lt_cv_nm_interface + +# Specify filename containing input files for \$NM. +nm_file_list_spec=$lt_nm_file_list_spec + +# The root where to search for dependent libraries,and where our libraries should be installed. +lt_sysroot=$lt_sysroot + +# Command to truncate a binary pipe. +lt_truncate_bin=$lt_lt_cv_truncate_bin + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Manifest tool. +MANIFEST_TOOL=$lt_MANIFEST_TOOL + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Detected run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path + +# Explicit LT_SYS_LIBRARY_PATH set during ./configure time. +configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \$shlibpath_var if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain=$ac_aux_dir/ltmain.sh + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + + +echo "" +echo "Clutter - $VERSION (${CLUTTER_RELEASE_STATUS})" + +# Global flags +echo "" +echo " • Global:" +echo " Prefix: ${prefix}" +echo " Libdir: ${libdir}" +echo " Sysconfdir: ${sysconfdir}" + +# Compiler/Debug related flags +echo "" +echo " • Compiler options:" +echo " Clutter debug level: ${enable_debug}" +echo " Compiler flags: ${CFLAGS} ${MAINTAINER_CFLAGS}" +echo " Enable coverage tests: ${use_gcov}" +echo " Enable deprecated symbols: ${enable_deprecated}" + +# Miscellaneous +echo "" +echo " • Extra:" +echo " Build introspection data: ${enable_introspection}" +if test "x$x11_tests" = "xyes"; then +echo " Build X11-specific tests: ${x11_tests}" +fi +if test "x$pixbuf_tests" = "xyes"; then +echo " Build tests using GDK-Pixbuf: ${pixbuf_tests}" +fi +echo " Install test suites: ${enable_installed_tests}" +echo " Build examples: ${enable_examples}" + +# Clutter backend related flags +echo "" +echo " • Clutter Backends:" +echo " Windowing systems: ${CLUTTER_BACKENDS}" +echo " Input backends: ${CLUTTER_INPUT_BACKENDS}" + +if test "x$SUPPORT_X11" = "x1"; then +echo "" +echo " - X11 backend options:" +echo " Enabled extensions: ${X11_EXTS}" +fi + +if test "x$SUPPORT_WAYLAND_COMPOSITOR" = "x1"; then +echo "" +echo " - Wayland compositor support enabled" +fi + +echo "" diff --git a/clutter/configure.ac b/clutter/configure.ac new file mode 100644 index 0000000..ad5be7c --- /dev/null +++ b/clutter/configure.ac @@ -0,0 +1,833 @@ +# clutter package version number, (as distinct from shared library version) +# An odd micro number indicates in-progress development from Git +# An even micro number indicates a released version +# +# Making a point release: +# - increase clutter_micro_version to the next even number +# - increase clutter_interface_age to the next even number +# After the release: +# - increase clutter_micro_version to the next odd number +# - increase clutter_interface_version to the next odd number +m4_define([clutter_major_version], [1]) +m4_define([clutter_minor_version], [26]) +m4_define([clutter_micro_version], [1]) + +# • for stable releases: increase the interface age by 1 for each release; +# if the API changes, set to 0. interface_age and binary_age are used to +# create the soname of the shared object: +# +# ( * 100 + ) - +# +# this allows using the same soname for different micro-releases in case +# no API was added or deprecated. for instance: +# +# clutter 1.2.0 -> 100 * 2 + 0 = 200, interface age = 0 -> 200 +# clutter 1.2.2 -> 100 * 2 + 2 = 202, interface age = 2 -> 200 +# clutter 1.2.4 -> 100 * 2 + 4 = 204, interface age = 4 -> 200 +# [ API addition, deprecation ] +# clutter 1.2.6 -> 100 * 2 + 6 = 206, interface age = 0 -> 206 +# clutter 1.2.8 -> 100 * 2 + 8 = 208, interface age = 2 -> 206 +# clutter 1.2.10 -> 100 * 2 + 10 = 210, interface age = 4 -> 206 +# ... +# +# • for development releases: keep clutter_interface_age to 0 +m4_define([clutter_interface_age], [1]) + +m4_define([clutter_binary_age], [m4_eval(100 * clutter_minor_version + clutter_micro_version)]) + +m4_define([clutter_release_status], + [m4_if(m4_eval(clutter_micro_version % 2), [1], [git], + [m4_if(m4_eval(clutter_minor_version % 2), [1], [snapshot], + [release])])]) + +m4_define([clutter_version], [clutter_major_version.clutter_minor_version.clutter_micro_version]) + +# change this only when breaking the API +m4_define([clutter_api_version], [1.0]) + +AC_PREREQ([2.63]) + +AC_INIT([clutter], + [clutter_version], + [http://bugzilla.gnome.org/enter_bug.cgi?product=clutter], + [clutter], + [http://www.clutter-project.org]) + +AC_CONFIG_SRCDIR([clutter/clutter.h]) +AC_CONFIG_HEADERS([clutter/clutter-build-config.h]) +AC_CONFIG_AUX_DIR([build]) +AC_CONFIG_MACRO_DIR([build/autotools]) + +AM_INIT_AUTOMAKE([1.11 foreign -Wno-portability no-define no-dist-gzip dist-xz tar-ustar]) +AM_SILENT_RULES([yes]) + +AC_SUBST([CLUTTER_MAJOR_VERSION], [clutter_major_version]) +AC_SUBST([CLUTTER_MINOR_VERSION], [clutter_minor_version]) +AC_SUBST([CLUTTER_MICRO_VERSION], [clutter_micro_version]) +AC_SUBST([CLUTTER_VERSION], [clutter_version]) +AC_SUBST([CLUTTER_API_VERSION], [clutter_api_version]) +AC_SUBST([CLUTTER_API_VERSION_AM], [$CLUTTER_MAJOR_VERSION\_0]) +AC_SUBST([CLUTTER_RELEASE_STATUS], [clutter_release_status]) + +m4_define([lt_current], [m4_eval(100 * clutter_minor_version + clutter_micro_version - clutter_interface_age)]) +m4_define([lt_revision], [clutter_interface_age]) +m4_define([lt_age], [m4_eval(clutter_binary_age - clutter_interface_age)]) +CLUTTER_LT_CURRENT=lt_current +CLUTTER_LT_REV=lt_revision +CLUTTER_LT_AGE=lt_age +CLUTTER_LT_VERSION="$CLUTTER_LT_CURRENT:$CLUTTER_LT_REV:$CLUTTER_LT_AGE" +CLUTTER_LT_LDFLAGS="-avoid-version" +AC_SUBST([CLUTTER_LT_CURRENT], [lt_current]) +AC_SUBST([CLUTTER_LT_REVISION], [lt_revision]) +AC_SUBST([CLUTTER_LT_VERSION], [$CLUTTER_LT_VERSION]) + +AC_PROG_SED + +dnl = Preliminary platform checks ============================================= + +AC_CANONICAL_HOST + +AC_DEFINE([OS_LINUX], [1], [Define to 1 if building for Linux]) + +AC_SUBST(CLUTTER_LT_LDFLAGS) + +AC_CACHE_SAVE + +dnl = Dependencies ========================================================= + +# Checks for programs. +AM_PROG_CC_C_O + +# require libtool >= 2.2 +LT_PREREQ([2.2.6]) +LT_INIT([disable-static]) +LT_LIB_M + +# Checks for header files. +AC_HEADER_STDC + +# required versions for dependencies +m4_define([glib_req_version], [2.44.0]) +m4_define([cogl_req_version], [1.21.2]) +m4_define([json_glib_req_version], [0.12.0]) +m4_define([atk_req_version], [2.5.3]) +m4_define([cairo_req_version], [1.14.0]) +m4_define([pango_req_version], [1.30]) +m4_define([gi_req_version], [1.39.0]) +m4_define([xcomposite_req_version], [0.4]) +m4_define([gdk_req_version], [3.3.18]) +m4_define([libinput_req_version], [1.4.0]) +m4_define([libudev_req_version], [136]) + +AC_SUBST([GLIB_REQ_VERSION], [glib_req_version]) +AC_SUBST([COGL_REQ_VERSION], [cogl_req_version]) +AC_SUBST([JSON_GLIB_REQ_VERSION], [json_glib_req_version]) +AC_SUBST([ATK_REQ_VERSION], [atk_req_version]) +AC_SUBST([CAIRO_REQ_VERSION], [cairo_req_version]) +AC_SUBST([PANGO_REQ_VERSION], [pango_req_version]) +AC_SUBST([GI_REQ_VERSION], [gi_req_version]) +AC_SUBST([XCOMPOSITE_REQ_VERSION], [xcomposite_req_version]) +AC_SUBST([GDK_REQ_VERSION], [gdk_req_version]) +AC_SUBST([LIBINPUT_REQ_VERSION], [libinput_req_version]) +AC_SUBST([LIBUDEV_REQ_VERSION], [libudev_req_version]) + +# Checks for typedefs, structures, and compiler characteristics. +AM_PATH_GLIB_2_0([glib_req_version], + [], + [AC_MSG_ERROR([glib-2.0 is required])], + [gobject gio gthread gmodule-no-export]) + +# Check for -Bsymbolic-functions to avoid intra-library PLT jumps +AC_ARG_ENABLE([Bsymbolic], + [AS_HELP_STRING([--disable-Bsymbolic], + [Avoid linking with -Bsymbolic])], + [], + [ + saved_LDFLAGS="${LDFLAGS}" + AC_MSG_CHECKING([for -Bsymbolic-functions linker flag]) + LDFLAGS=-Wl,-Bsymbolic-functions + AC_TRY_LINK([], [int main (void) { return 0; }], + [ + AC_MSG_RESULT([yes]) + enable_Bsymbolic=yes + ], + [ + AC_MSG_RESULT([no]) + enable_Bsymbolic=no + ]) + LDFLAGS="${saved_LDFLAGS}" + ]) + +AS_IF([test "x$enable_Bsymbolic" = "xyes"], [CLUTTER_LINK_FLAGS=-Wl[,]-Bsymbolic-functions]) +AC_SUBST(CLUTTER_LINK_FLAGS) + +# Check for the visibility flags +CLUTTER_HIDDEN_VISIBILITY_CFLAGS="" +dnl on other compilers, check if we can do -fvisibility=hidden +SAVED_CFLAGS="${CFLAGS}" +CFLAGS="-fvisibility=hidden" +AC_MSG_CHECKING([for -fvisibility=hidden compiler flag]) +AC_TRY_COMPILE([], [int main (void) { return 0; }], + AC_MSG_RESULT(yes) + enable_fvisibility_hidden=yes, + AC_MSG_RESULT(no) + enable_fvisibility_hidden=no) +CFLAGS="${SAVED_CFLAGS}" + +AS_IF([test "${enable_fvisibility_hidden}" = "yes"], [ + AC_DEFINE([_CLUTTER_EXTERN], [__attribute__((visibility("default"))) extern], + [defines how to decorate public symbols while building]) + CLUTTER_HIDDEN_VISIBILITY_CFLAGS="-fvisibility=hidden" +]) +AC_SUBST(CLUTTER_HIDDEN_VISIBILITY_CFLAGS) + +AC_CACHE_SAVE + +dnl ======================================================================== + +FLAVOUR_LIBS="" +FLAVOUR_CFLAGS="" +CLUTTER_BACKENDS="" +CLUTTER_INPUT_BACKENDS="" +CLUTTER_CONFIG_DEFINES= + +# base dependencies for core +CLUTTER_BASE_PC_FILES="cairo-gobject >= $CAIRO_REQ_VERSION gio-2.0 >= glib_req_version atk >= $ATK_REQ_VERSION pangocairo >= $PANGO_REQ_VERSION json-glib-1.0 >= $JSON_GLIB_REQ_VERSION" + +# private base dependencies +CLUTTER_BASE_PC_FILES_PRIVATE="" + +# backend specific pkg-config files +BACKEND_PC_FILES="" + +# private backend specific dependencies +BACKEND_PC_FILES_PRIVATE="" + +dnl === Clutter windowing system backend ====================================== + +CLUTTER_BACKENDS="$CLUTTER_BACKENDS x11" +CLUTTER_INPUT_BACKENDS="$CLUTTER_INPUT_BACKENDS x11" + +SUPPORT_X11=1 +SUPPORT_GLX=1 +SUPPORT_COGL=1 + +# we use fontconfig API and pango-ft2 when the fontconfig +# configuration changes; we don't expose any API for this +# so we add pango-ft2 to the private Requires. +PKG_CHECK_EXISTS([pangoft2], + [ + AC_DEFINE([HAVE_PANGO_FT2], [1], [Supports PangoFt2]) + BACKEND_PC_FILES_PRIVATE="$BACKEND_PC_FILES_PRIVATE pangoft2" + ], + []) + +AC_ARG_ENABLE( + [wayland-egl-server], + [AC_HELP_STRING([--enable-wayland-egl-server=@<:@no/yes@:>@], [Enable server side wayland support @<:@default=no@:>@])], + [], + enable_wayland_egl_server=yes +) + +AS_IF([test "x$enable_wayland_egl_server" = "xyes"], + [ + CLUTTER_BACKENDS="$CLUTTER_BACKENDS egl" + SUPPORT_EGL=1 + AC_DEFINE([CLUTTER_EGL_BACKEND_GENERIC], [1], [Use Generic EGL backend]) + + BACKEND_PC_FILES="$BACKEND_PC_FILES wayland-egl wayland-server libdrm gbm" + + SUPPORT_WAYLAND_COMPOSITOR=1 + CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES + #define CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT 1" + + CLUTTER_INPUT_BACKENDS="$CLUTTER_INPUT_BACKENDS evdev" + + SUPPORT_EVDEV=1 + BACKEND_PC_FILES_PRIVATE="$BACKEND_PC_FILES_PRIVATE libudev >= $LIBUDEV_REQ_VERSION libinput >= $LIBINPUT_REQ_VERSION xkbcommon" + AC_DEFINE([HAVE_EVDEV], [1], [Have evdev support for input handling]) + ]) + +AM_CONDITIONAL(SUPPORT_WAYLAND, [test "x$enable_wayland_egl_server" = "xyes"]) + +AC_DEFINE_UNQUOTED([CLUTTER_DRIVERS], ["*"], [List of Cogl drivers]) + +dnl strip leading spaces +CLUTTER_BACKENDS=${CLUTTER_BACKENDS#* } +AC_SUBST(CLUTTER_BACKENDS) + +CLUTTER_INPUT_BACKENDS=${CLUTTER_INPUT_BACKENDS#* } +AC_SUBST(CLUTTER_INPUT_BACKENDS) + +AC_CACHE_SAVE + +dnl === Clutter configuration ================================================= + +# windowing systems +AS_IF([test "x$SUPPORT_X11" = "x1"], + [CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES +#define CLUTTER_WINDOWING_X11 \"x11\" +#define CLUTTER_INPUT_X11 \"x11\""]) +AS_IF([test "x$SUPPORT_GLX" = "x1"], + [CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES +#define CLUTTER_WINDOWING_GLX \"glx\""]) +AS_IF([test "x$SUPPORT_EGL" = "x1"], + [CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES +#define CLUTTER_WINDOWING_EGL \"eglnative\""]) +AS_IF([test "x$SUPPORT_EVDEV" = "x1"], + [CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES +#define CLUTTER_INPUT_EVDEV \"evdev\""]) + +# the 'null' input backend is special +CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES +#define CLUTTER_INPUT_NULL \"null\"" + +AC_SUBST([CLUTTER_CONFIG_DEFINES]) + +dnl === Clutter substitutions kept for backwards compatibility ================ +AC_SUBST([CLUTTER_WINSYS], [deprecated]) +AC_SUBST([CLUTTER_WINSYS_BASE], [deprecated]) +AC_SUBST([CLUTTER_STAGE_TYPE], [deprecated]) +AC_SUBST([CLUTTER_SONAME_INFIX], [deprecated]) +AC_SUBST([CLUTTER_FLAVOUR], [deprecated]) +AC_SUBST([CLUTTER_COGL], [deprecated]) +AC_SUBST([COGL_DRIVER], [deprecated]) + +dnl === X11 checks, only for X11-based backends =============================== +X11_PC_FILES="" +X11_EXTS="" +x11_tests=no + +AS_IF([test "x$SUPPORT_X11" = "x1"], + [ + # base X11 includes and libraries + AC_MSG_CHECKING([for X11]) + + # start with pkg-config + PKG_CHECK_EXISTS([x11], [have_x11=yes], [have_x11=no]) + AS_IF([test "x$have_x11" = "xyes"], + [ + X11_PC_FILES="x11" + + # we actually need to ask for CFLAGS and LIBS + X11_CFLAGS=`$PKG_CONFIG --cflags $X11_PC_FILES` + X11_LIBS=`$PKG_CONFIG --libs $X11_PC_FILES` + + AC_MSG_RESULT([found]) + ], + [ + # no pkg-config, let's go old school + AC_PATH_X + + AS_IF([test "x$no_x" = "xyes"], + [AC_MSG_ERROR([No X11 Libraries found])], + [ + AS_IF([test "x$x_includes" != "xNONE" && test -n "$x_includes"], + [X11_CFLAGS=-I`echo $x_includes | sed -e "s/:/ -I/g"`]) + + AS_IF([test "x$x_libraries" != "xNONE" && test -n "$x_libraries"], + [X11_LIBS=-L`echo $x_libraries | sed -e "s/:/ -L/g"`]) + + AC_MSG_RESULT([found]) + ] + ) + ] + ) + + # XEXT (required) + AC_MSG_CHECKING([for XEXT extension]) + PKG_CHECK_EXISTS([xext], [have_xext=yes], [have_xext=no]) + AS_IF([test "x$have_xext" = "xyes"], + [ + AC_DEFINE(HAVE_XEXT, [1], [Define to 1 if we have the XEXT X extension]) + + X11_LIBS="$X11_LIBS -lXext" + X11_PC_FILES="$X11_PC_FILES xext" + X11_EXTS="$X11_EXTS xext" + + AC_MSG_RESULT([found]) + ], + [AC_MSG_ERROR([Not found])] + ) + + # XDAMAGE (required) + AC_MSG_CHECKING([for XDAMAGE extension]) + PKG_CHECK_EXISTS([xdamage], [have_xdamage=yes], [have_xdamage=no]) + AS_IF([test "x$have_xdamage" = "xyes"], + [ + AC_DEFINE(HAVE_XDAMAGE, [1], [Define to 1 if we have the XDAMAGE X extension]) + + X11_LIBS="$X11_LIBS -lXdamage" + X11_PC_FILES="$X11_PC_FILES xdamage" + X11_EXTS="$X11_EXTS xdamage" + + AC_MSG_RESULT([found]) + ], + [AC_MSG_ERROR([not found])] + ) + + # XCOMPOSITE (optional) + AC_MSG_CHECKING([for XCOMPOSITE extension >= $XCOMPOSITE_REQ_VERSION]) + PKG_CHECK_EXISTS([xcomposite >= $XCOMPOSITE_REQ_VERSION], [have_xcomposite=yes], [have_xcomposite=no]) + AS_IF([test "x$have_xcomposite" = "xyes"], + [ + AC_DEFINE(HAVE_XCOMPOSITE, [1], [Define to 1 if we have the XCOMPOSITE X extension]) + + X11_LIBS="$X11_LIBS -lXcomposite" + X11_PC_FILES="$X11_PC_FILES xcomposite >= $XCOMPOSITE_REQ_VERSION" + X11_EXTS="$X11_EXTS xcomposite" + + AC_MSG_RESULT([found]) + ], + [AC_MSG_ERROR([not found])] + ) + + # X Generic Extensions (optional) + clutter_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $X11_CFLAGS" + + clutter_save_LIBS="$LIBS" + LIBS="$LIBS $X11_LIBS" + + have_xge=no + AC_CHECK_FUNC([XGetEventData], + [ + AC_DEFINE([HAVE_XGE], [1], [Define to 1 if X Generic Extensions is available]) + have_xge=yes + X11_EXTS="$X11_EXTS xge" + ]) + + CPPFLAGS="$clutter_save_CPPFLAGS" + LIBS="$clutter_save_LIBS" + + # XI (optional) + AC_ARG_ENABLE([xinput], + [AS_HELP_STRING([--enable-xinput], [Use the XI X extension])], + [], + [enable_xinput=yes]) + + AS_IF([test "x$enable_xinput" = "xyes"], + [ + PKG_CHECK_EXISTS([xi], [have_xinput=yes], [have_xinput=no]) + ], + [ + have_xinput=no + ]) + + AS_CASE([$have_xinput], + + [yes], + [ + AC_CHECK_HEADERS([X11/extensions/XInput2.h], + [ + have_xinput2=yes + AC_DEFINE([HAVE_XINPUT_2], + [1], + [Define to 1 if XI2 is available]) + ]) + + clutter_save_LIBS="$LIBS" + LIBS="$LIBS -lXi" + + AC_CHECK_FUNC([XIAllowTouchEvents], + [ + AC_CHECK_MEMBER([XIScrollClassInfo.number], + [ + have_xinput_2_2=yes + AC_DEFINE([HAVE_XINPUT_2_2], [1], [Define to 1 if XInput 2.2 is available]) + ], + [have_xinput_2_2=no], + [[#include ]])]) + + LIBS="$clutter_save_LIBS" + + X11_LIBS="$X11_LIBS $XINPUT_LIBS" + X11_PC_FILES="$X11_PC_FILES xi" + + AS_IF([test "x$have_xinput_2_2" = "xyes"], + [X11_EXTS="$X11_EXTS xi2.2"], + [X11_EXTS="$X11_EXTS xi2.0"]) + ], + + [no], + [have_xinput2=no], + + [*], + [AC_MSG_ERROR([Invalid argument for --enable-xinput])] + ) + + # XKB + clutter_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $X11_CFLAGS" + + clutter_save_LIBS="$LIBS" + LIBS="$LIBS $X11_LIBS" + + have_xkb=no + AC_CHECK_FUNC([XkbQueryExtension], + [ + AC_DEFINE(HAVE_XKB, 1, [Define to use XKB extension]) + have_xkb=yes + + X11_EXTS="$X11_EXTS xkb" + ]) + + CPPFLAGS="$clutter_save_CPPFLAGS" + LIBS="$clutter_save_LIBS" + + x11_tests=yes + BACKEND_PC_FILES="$BACKEND_PC_FILES $X11_PC_FILES" + FLAVOUR_LIBS="$FLAVOUR_LIBS $X11_LIBS" + FLAVOUR_CFLAGS="$FLAVOUR_CFLAGS $X11_CFLAGS" + ] +) + +AM_CONDITIONAL([BUILD_XI2], [test "x$have_xinput2" = "xyes"]) +AM_CONDITIONAL([X11_TESTS], [test "x$x11_tests" = "xyes"]) + +X11_EXTS=${X11_EXTS#* } + +AC_CACHE_SAVE + +dnl === Enable GDK-Pixbuf in tests ============================================ + +m4_define([pixbuf_default], [yes]) +AC_ARG_ENABLE([gdk-pixbuf], + [AS_HELP_STRING([--enable-gdk-pixbuf=@<:@no/yes@:>@], + [Enable tests using GDK-Pixbuf @<:@default=]pixbuf_default[@:>@])], + [enable_pixbuf=$enable_val], + [enable_pixbuf=pixbuf_default]) + +AS_CASE([$enable_pixbuf], + + [yes], + [ + PKG_CHECK_MODULES([GDK_PIXBUF], [gdk-pixbuf-2.0]) + AC_SUBST(GDK_PIXBUF_CFLAGS) + AC_SUBST(GDK_PIXBUF_LIBS) + pixbuf_tests=yes + ], + + [no], + [ + pixbuf_tests=no + ] +) + +AM_CONDITIONAL([PIXBUF_TESTS], [test "x$pixbuf_tests" = "xyes"]) + +dnl === Enable debug level ==================================================== + +m4_define([debug_default], [m4_if(m4_eval(clutter_minor_version % 2), [1], [yes], [minimum])]) +AC_ARG_ENABLE([debug], + [AS_HELP_STRING([--enable-debug=@<:@no/minimum/yes@:>@], + [Control Clutter debugging level @<:@default=]debug_default[@:>@])], + [], + [enable_debug=debug_default]) + +AS_CASE([$enable_debug], + + [yes], + [ + test "$cflags_set" = set || CFLAGS="$CFLAGS -g" + CLUTTER_DEBUG_CFLAGS="-DCLUTTER_ENABLE_DEBUG" + ], + + [minimum], + [CLUTTER_DEBUG_CFLAGS="-DG_DISABLE_CAST_CHECKS"], + + [no], + [CLUTTER_DEBUG_CFLAGS="-DG_DISABLE_ASSERT -DG_DISABLE_CHECKS -DG_DISABLE_CAST_CHECKS"], + + [AC_MSG_ERROR([Unknown argument for --enable-debug])] +) + +AC_SUBST(CLUTTER_DEBUG_CFLAGS) + +dnl === Enable deprecation guards ================================================== + +m4_define([deprecated_default], + [m4_if(m4_eval(clutter_minor_version % 2), + [1], + [no], + [yes])]) + +AC_ARG_ENABLE([deprecated], + [AS_HELP_STRING([--enable-deprecated=@<:@no/yes@:>@], + [Whether deprecated symbols should be disabled when compiling Clutter @<:@default=]deprecated_default[@:>@])], + [], + [enable_deprecated=deprecated_default]) + +AS_CASE([$enable_deprecated], + + [no], + [ + CLUTTER_DEPRECATED_CFLAGS="-DG_DISABLE_SINGLE_INCLUDES -DCOGL_DISABLE_DEPRECATED" + ], + + [yes], + [ + CLUTTER_DEPRECATED_CFLAGS="-DGLIB_DISABLE_DEPRECATION_WARNINGS" + ], + + [AC_MSG_ERROR([Unknown argument for --enable-deprecated])] +) + +AC_SUBST([CLUTTER_DEPRECATED_CFLAGS]) + +dnl === Enable strict compiler flags ========================================== + +# use strict compiler flags only when building from git; the rules for +# distcheck will take care of turning this on when making a release +m4_define([maintainer_flags_default], [m4_if(m4_eval(clutter_micro_version % 2), [1], [yes], [no])]) +AC_ARG_ENABLE([maintainer-flags], + [AS_HELP_STRING([--enable-maintainer-flags=@<:@no/yes/error@:>@], + [Use strict compiler flags @<:@default=]maintainer_flags_default[@:>@])], + [], + [enable_maintainer_flags=maintainer_flags_default]) + +MAINTAINER_COMPILER_FLAGS="$MAINTAINER_COMPILER_FLAGS + -Wall + -Wcast-align + -Wuninitialized + -Wno-strict-aliasing + -Wshadow" + +AC_ARG_ENABLE([Werror], + [AS_HELP_STRING([--disable-Werror], [Removes -Werror from compiler flags])], + [], + [enable_Werror=yes]) + +AS_IF([test "x$enable_Werror" = xyes], [ + MAINTAINER_COMPILER_FLAGS="$MAINTAINER_COMPILER_FLAGS + -Werror=logical-op + -Werror=pointer-arith + -Werror=missing-declarations + -Werror=redundant-decls + -Werror=empty-body + -Werror=format + -Werror=format-security + -Werror=format-nonliteral + -Werror=init-self + -Werror=declaration-after-statement + -Werror=vla" +]) + +AS_CASE([$enable_maintainer_flags], + [yes], + [ + AS_COMPILER_FLAGS([MAINTAINER_CFLAGS], [$MAINTAINER_COMPILER_FLAGS]) + ], + + [no], + [ + ], + + [error], + [ + MAINTAINER_COMPILER_FLAGS="$MAINTAINER_COMPILER_FLAGS -Werror" + AS_COMPILER_FLAGS([MAINTAINER_CFLAGS], [$MAINTAINER_COMPILER_FLAGS]) + ], + + [*], + [AC_MSG_ERROR([Invalid option for --enable-maintainer-flags])] +) + +# strip leading spaces +MAINTAINER_CFLAGS=${MAINTAINER_CFLAGS#* } +AC_SUBST(MAINTAINER_CFLAGS) + +dnl === Dependencies, compiler flags and linker libraries ===================== +# strip leading space +BACKEND_PC_FILES=${BACKEND_PC_FILES#* } + +# public dependencies, will fill the Requires: field of clutter.pc +CLUTTER_REQUIRES="$CLUTTER_BASE_PC_FILES $BACKEND_PC_FILES" +PKG_CHECK_MODULES(CLUTTER_DEPS, [$CLUTTER_REQUIRES]) + +# private dependencies, will fill the Requires.private: field of clutter.pc +AS_IF([test "x$CLUTTER_BASE_PC_FILES_PRIVATE" = "x" && test "x$BACKEND_PC_FILES_PRIVATE" = "x"], + [ + CLUTTER_REQUIRES_PRIVATE="" + CLUTTER_DEPS_PRIVATE_CFLAGS="" + CLUTTER_DEPS_PRIVATE_LIBS="" + ], + [ + CLUTTER_REQUIRES_PRIVATE="$CLUTTER_BASE_PC_FILES_PRIVATE $BACKEND_PC_FILES_PRIVATE" + PKG_CHECK_MODULES(CLUTTER_DEPS_PRIVATE, [$CLUTTER_REQUIRES_PRIVATE]) + ]) + +AC_SUBST(CLUTTER_REQUIRES) +AC_SUBST(CLUTTER_REQUIRES_PRIVATE) + +CLUTTER_CFLAGS="$FLAVOUR_CFLAGS $CLUTTER_DEPS_CFLAGS $CLUTTER_DEPS_PRIVATE_CFLAGS $GLIB_CFLAGS" +CLUTTER_LIBS="$FLAVOUR_LIBS $CLUTTER_DEPS_LIBS $CLUTTER_DEPS_PRIVATE_LIBS $GLIB_LIBS" +AC_SUBST(CLUTTER_CFLAGS) +AC_SUBST(CLUTTER_LIBS) + +dnl === Test coverage ========================================================= + +AC_ARG_ENABLE([gcov], + [AS_HELP_STRING([--enable-gcov], [Enable gcov])], + [use_gcov=$enableval], + [use_gcov=no]) + +AS_IF([test "x$use_gcov" = "xyes"], + [ + dnl we need gcc: + AS_IF([test "$GCC" != "yes"], [AC_MSG_ERROR([GCC is required for --enable-gcov])]) + + dnl Check if ccache is being used + AC_CHECK_PROG(SHTOOL, shtool, shtool) + AS_CASE([`$SHTOOL path $CC`], + [*ccache*], [gcc_ccache=yes], + [gcc_ccache=no]) + + if test "$gcc_ccache" = "yes" && (test -z "$CCACHE_DISABLE" || test "$CCACHE_DISABLE" != "1"); then + AC_MSG_ERROR([ccache must be disabled when --enable-gcov option is used. You can disable ccache by setting environment variable CCACHE_DISABLE=1.]) + fi + + ltp_version_list="1.6 1.7 1.8 1.9 1.10" + AC_CHECK_PROG(LTP, lcov, lcov) + AC_CHECK_PROG(LTP_GENHTML, genhtml, genhtml) + + if test "$LTP"; then + AC_CACHE_CHECK([for ltp version], clutter_cv_ltp_version, + [ + clutter_cv_ltp_version=invalid + ltp_version=`$LTP -v 2>/dev/null | $SED -e 's/^.* //'` + for ltp_check_version in $ltp_version_list; do + if test "$ltp_version" = "$ltp_check_version"; then + clutter_cv_ltp_version="$ltp_check_version (ok)" + fi + done + ]) + else + ltp_msg="To enable code coverage reporting you must have one of the following LTP versions installed: $ltp_version_list" + AC_MSG_ERROR([$ltp_msg]) + fi + + case $clutter_cv_ltp_version in + ""|invalid[)] + ltp_msg="You must have one of the following versions of LTP: $ltp_version_list (found: $ltp_version)." + AC_MSG_ERROR([$ltp_msg]) + LTP="exit 0;" + ;; + esac + + if test -z "$LTP_GENHTML"; then + AC_MSG_ERROR([Could not find genhtml from the LTP package]) + fi + + AC_DEFINE(HAVE_GCOV, 1, [Whether you have gcov]) + + dnl Remove all optimization flags from CFLAGS + changequote({,}) + CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9]*//g'` + CLUTTER_CFLAGS=`echo "$CLUTTER_CFLAGS" | $SED -e 's/-O[0-9]*//g'` + changequote([,]) + + dnl Define the special gcc flags + CLUTTER_GCOV_CFLAGS="-O0 -fprofile-arcs -ftest-coverage" + CLUTTER_GCOV_LDADD="-lgcov" + + AC_SUBST(CLUTTER_GCOV_CFLAGS) + AC_SUBST(CLUTTER_GCOV_LDADD) + + CLUTTER_CFLAGS="$CLUTTER_CFLAGS $CLUTTER_GCOV_CFLAGS" + CLUTTER_LIBS="$CLUTTER_LIBS $CLUTTER_GCOV_LDADD" + ]) + +AM_CONDITIONAL(ENABLE_GCOV, test "x$use_gcov" = "xyes") + +dnl === GObject-Introspection check =========================================== + +GOBJECT_INTROSPECTION_CHECK([gi_req_version]) + +dnl === Conformance test suite ================================================ + +GLIB_TESTS + +AC_ARG_ENABLE([examples], + [AS_HELP_STRING([--enable-examples], [Whether examples should be built])], + [], + [enable_examples=no]) +AM_CONDITIONAL(BUILD_EXAMPLES, [test "x$enable_examples" = "xyes"]) + +dnl =========================================================================== + +AC_CONFIG_FILES([ + Makefile + + build/Makefile + build/autotools/Makefile + + clutter/Makefile + clutter/clutter-config.h + clutter/clutter-version.h + clutter/mutter-clutter-$CLUTTER_API_VERSION.pc:clutter/mutter-clutter.pc.in + + tests/Makefile + tests/accessibility/Makefile + tests/conform/Makefile + tests/interactive/Makefile + tests/interactive/wrapper.sh + tests/micro-bench/Makefile + tests/performance/Makefile + + examples/Makefile +]) + +AC_OUTPUT + +dnl === Summary =============================================================== + +echo "" +echo "Clutter - $VERSION (${CLUTTER_RELEASE_STATUS})" + +# Global flags +echo "" +echo " • Global:" +echo " Prefix: ${prefix}" +echo " Libdir: ${libdir}" +echo " Sysconfdir: ${sysconfdir}" + +# Compiler/Debug related flags +echo "" +echo " • Compiler options:" +echo " Clutter debug level: ${enable_debug}" +echo " Compiler flags: ${CFLAGS} ${MAINTAINER_CFLAGS}" +echo " Enable coverage tests: ${use_gcov}" +echo " Enable deprecated symbols: ${enable_deprecated}" + +# Miscellaneous +echo "" +echo " • Extra:" +echo " Build introspection data: ${enable_introspection}" +if test "x$x11_tests" = "xyes"; then +echo " Build X11-specific tests: ${x11_tests}" +fi +if test "x$pixbuf_tests" = "xyes"; then +echo " Build tests using GDK-Pixbuf: ${pixbuf_tests}" +fi +echo " Install test suites: ${enable_installed_tests}" +echo " Build examples: ${enable_examples}" + +# Clutter backend related flags +echo "" +echo " • Clutter Backends:" +echo " Windowing systems: ${CLUTTER_BACKENDS}" +echo " Input backends: ${CLUTTER_INPUT_BACKENDS}" + +if test "x$SUPPORT_X11" = "x1"; then +echo "" +echo " - X11 backend options:" +echo " Enabled extensions: ${X11_EXTS}" +fi + +if test "x$SUPPORT_WAYLAND_COMPOSITOR" = "x1"; then +echo "" +echo " - Wayland compositor support enabled" +fi + +echo "" diff --git a/clutter/examples/Makefile.am b/clutter/examples/Makefile.am new file mode 100644 index 0000000..71c4459 --- /dev/null +++ b/clutter/examples/Makefile.am @@ -0,0 +1,36 @@ +all_examples = \ + actor-model \ + basic-actor \ + box-layout \ + canvas \ + constraints \ + drag-action \ + drop-action \ + easing-modes \ + flow-layout \ + grid-layout \ + layout-manager \ + pan-action \ + rounded-rectangle \ + scroll-actor \ + threads + +if PIXBUF_TESTS +all_examples += \ + bin-layout \ + image-content +endif + +LDADD = $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la $(CLUTTER_LIBS) $(GDK_PIXBUF_LIBS) $(LIBM) +AM_CFLAGS = $(CLUTTER_CFLAGS) $(GDK_PIXBUF_CFLAGS) $(MAINTAINER_CFLAGS) +AM_CPPFLAGS = \ + -DG_DISABLE_SINGLE_INCLUDES \ + -DGLIB_DISABLE_DEPRECATION_WARNINGS \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + -I$(top_srcdir)/clutter \ + -I$(top_builddir)/clutter + +noinst_PROGRAMS = $(all_examples) + +EXTRA_DIST = redhand.png diff --git a/clutter/examples/Makefile.in b/clutter/examples/Makefile.in new file mode 100644 index 0000000..9792f55 --- /dev/null +++ b/clutter/examples/Makefile.in @@ -0,0 +1,876 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@PIXBUF_TESTS_TRUE@am__append_1 = \ +@PIXBUF_TESTS_TRUE@ bin-layout \ +@PIXBUF_TESTS_TRUE@ image-content + +noinst_PROGRAMS = $(am__EXEEXT_2) +subdir = examples +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/build/autotools/as-compiler-flag.m4 \ + $(top_srcdir)/build/autotools/glibtests.m4 \ + $(top_srcdir)/build/autotools/introspection.m4 \ + $(top_srcdir)/build/autotools/libtool.m4 \ + $(top_srcdir)/build/autotools/ltoptions.m4 \ + $(top_srcdir)/build/autotools/ltsugar.m4 \ + $(top_srcdir)/build/autotools/ltversion.m4 \ + $(top_srcdir)/build/autotools/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/clutter/clutter-build-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +@PIXBUF_TESTS_TRUE@am__EXEEXT_1 = bin-layout$(EXEEXT) \ +@PIXBUF_TESTS_TRUE@ image-content$(EXEEXT) +am__EXEEXT_2 = actor-model$(EXEEXT) basic-actor$(EXEEXT) \ + box-layout$(EXEEXT) canvas$(EXEEXT) constraints$(EXEEXT) \ + drag-action$(EXEEXT) drop-action$(EXEEXT) \ + easing-modes$(EXEEXT) flow-layout$(EXEEXT) \ + grid-layout$(EXEEXT) layout-manager$(EXEEXT) \ + pan-action$(EXEEXT) rounded-rectangle$(EXEEXT) \ + scroll-actor$(EXEEXT) threads$(EXEEXT) $(am__EXEEXT_1) +PROGRAMS = $(noinst_PROGRAMS) +actor_model_SOURCES = actor-model.c +actor_model_OBJECTS = actor-model.$(OBJEXT) +actor_model_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +actor_model_DEPENDENCIES = $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +basic_actor_SOURCES = basic-actor.c +basic_actor_OBJECTS = basic-actor.$(OBJEXT) +basic_actor_LDADD = $(LDADD) +basic_actor_DEPENDENCIES = $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +bin_layout_SOURCES = bin-layout.c +bin_layout_OBJECTS = bin-layout.$(OBJEXT) +bin_layout_LDADD = $(LDADD) +bin_layout_DEPENDENCIES = $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +box_layout_SOURCES = box-layout.c +box_layout_OBJECTS = box-layout.$(OBJEXT) +box_layout_LDADD = $(LDADD) +box_layout_DEPENDENCIES = $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +canvas_SOURCES = canvas.c +canvas_OBJECTS = canvas.$(OBJEXT) +canvas_LDADD = $(LDADD) +canvas_DEPENDENCIES = $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +constraints_SOURCES = constraints.c +constraints_OBJECTS = constraints.$(OBJEXT) +constraints_LDADD = $(LDADD) +constraints_DEPENDENCIES = $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +drag_action_SOURCES = drag-action.c +drag_action_OBJECTS = drag-action.$(OBJEXT) +drag_action_LDADD = $(LDADD) +drag_action_DEPENDENCIES = $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +drop_action_SOURCES = drop-action.c +drop_action_OBJECTS = drop-action.$(OBJEXT) +drop_action_LDADD = $(LDADD) +drop_action_DEPENDENCIES = $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +easing_modes_SOURCES = easing-modes.c +easing_modes_OBJECTS = easing-modes.$(OBJEXT) +easing_modes_LDADD = $(LDADD) +easing_modes_DEPENDENCIES = $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +flow_layout_SOURCES = flow-layout.c +flow_layout_OBJECTS = flow-layout.$(OBJEXT) +flow_layout_LDADD = $(LDADD) +flow_layout_DEPENDENCIES = $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +grid_layout_SOURCES = grid-layout.c +grid_layout_OBJECTS = grid-layout.$(OBJEXT) +grid_layout_LDADD = $(LDADD) +grid_layout_DEPENDENCIES = $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +image_content_SOURCES = image-content.c +image_content_OBJECTS = image-content.$(OBJEXT) +image_content_LDADD = $(LDADD) +image_content_DEPENDENCIES = $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +layout_manager_SOURCES = layout-manager.c +layout_manager_OBJECTS = layout-manager.$(OBJEXT) +layout_manager_LDADD = $(LDADD) +layout_manager_DEPENDENCIES = $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +pan_action_SOURCES = pan-action.c +pan_action_OBJECTS = pan-action.$(OBJEXT) +pan_action_LDADD = $(LDADD) +pan_action_DEPENDENCIES = $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +rounded_rectangle_SOURCES = rounded-rectangle.c +rounded_rectangle_OBJECTS = rounded-rectangle.$(OBJEXT) +rounded_rectangle_LDADD = $(LDADD) +rounded_rectangle_DEPENDENCIES = $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +scroll_actor_SOURCES = scroll-actor.c +scroll_actor_OBJECTS = scroll-actor.$(OBJEXT) +scroll_actor_LDADD = $(LDADD) +scroll_actor_DEPENDENCIES = $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +threads_SOURCES = threads.c +threads_OBJECTS = threads.$(OBJEXT) +threads_LDADD = $(LDADD) +threads_DEPENDENCIES = $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/clutter +depcomp = $(SHELL) $(top_srcdir)/build/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = actor-model.c basic-actor.c bin-layout.c box-layout.c \ + canvas.c constraints.c drag-action.c drop-action.c \ + easing-modes.c flow-layout.c grid-layout.c image-content.c \ + layout-manager.c pan-action.c rounded-rectangle.c \ + scroll-actor.c threads.c +DIST_SOURCES = actor-model.c basic-actor.c bin-layout.c box-layout.c \ + canvas.c constraints.c drag-action.c drop-action.c \ + easing-modes.c flow-layout.c grid-layout.c image-content.c \ + layout-manager.c pan-action.c rounded-rectangle.c \ + scroll-actor.c threads.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/build/depcomp \ + README +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ATK_REQ_VERSION = @ATK_REQ_VERSION@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_REQ_VERSION = @CAIRO_REQ_VERSION@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CLUTTER_API_VERSION = @CLUTTER_API_VERSION@ +CLUTTER_API_VERSION_AM = @CLUTTER_API_VERSION_AM@ +CLUTTER_BACKENDS = @CLUTTER_BACKENDS@ +CLUTTER_CFLAGS = @CLUTTER_CFLAGS@ +CLUTTER_COGL = @CLUTTER_COGL@ +CLUTTER_CONFIG_DEFINES = @CLUTTER_CONFIG_DEFINES@ +CLUTTER_DEBUG_CFLAGS = @CLUTTER_DEBUG_CFLAGS@ +CLUTTER_DEPRECATED_CFLAGS = @CLUTTER_DEPRECATED_CFLAGS@ +CLUTTER_DEPS_CFLAGS = @CLUTTER_DEPS_CFLAGS@ +CLUTTER_DEPS_LIBS = @CLUTTER_DEPS_LIBS@ +CLUTTER_DEPS_PRIVATE_CFLAGS = @CLUTTER_DEPS_PRIVATE_CFLAGS@ +CLUTTER_DEPS_PRIVATE_LIBS = @CLUTTER_DEPS_PRIVATE_LIBS@ +CLUTTER_FLAVOUR = @CLUTTER_FLAVOUR@ +CLUTTER_GCOV_CFLAGS = @CLUTTER_GCOV_CFLAGS@ +CLUTTER_GCOV_LDADD = @CLUTTER_GCOV_LDADD@ +CLUTTER_HIDDEN_VISIBILITY_CFLAGS = @CLUTTER_HIDDEN_VISIBILITY_CFLAGS@ +CLUTTER_INPUT_BACKENDS = @CLUTTER_INPUT_BACKENDS@ +CLUTTER_LIBS = @CLUTTER_LIBS@ +CLUTTER_LINK_FLAGS = @CLUTTER_LINK_FLAGS@ +CLUTTER_LT_CURRENT = @CLUTTER_LT_CURRENT@ +CLUTTER_LT_LDFLAGS = @CLUTTER_LT_LDFLAGS@ +CLUTTER_LT_REVISION = @CLUTTER_LT_REVISION@ +CLUTTER_LT_VERSION = @CLUTTER_LT_VERSION@ +CLUTTER_MAJOR_VERSION = @CLUTTER_MAJOR_VERSION@ +CLUTTER_MICRO_VERSION = @CLUTTER_MICRO_VERSION@ +CLUTTER_MINOR_VERSION = @CLUTTER_MINOR_VERSION@ +CLUTTER_RELEASE_STATUS = @CLUTTER_RELEASE_STATUS@ +CLUTTER_REQUIRES = @CLUTTER_REQUIRES@ +CLUTTER_REQUIRES_PRIVATE = @CLUTTER_REQUIRES_PRIVATE@ +CLUTTER_SONAME_INFIX = @CLUTTER_SONAME_INFIX@ +CLUTTER_STAGE_TYPE = @CLUTTER_STAGE_TYPE@ +CLUTTER_VERSION = @CLUTTER_VERSION@ +CLUTTER_WINSYS = @CLUTTER_WINSYS@ +CLUTTER_WINSYS_BASE = @CLUTTER_WINSYS_BASE@ +COGL_DRIVER = @COGL_DRIVER@ +COGL_REQ_VERSION = @COGL_REQ_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@ +GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@ +GDK_REQ_VERSION = @GDK_REQ_VERSION@ +GI_REQ_VERSION = @GI_REQ_VERSION@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQ_VERSION = @GLIB_REQ_VERSION@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +JSON_GLIB_REQ_VERSION = @JSON_GLIB_REQ_VERSION@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBINPUT_REQ_VERSION = @LIBINPUT_REQ_VERSION@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUDEV_REQ_VERSION = @LIBUDEV_REQ_VERSION@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTP = @LTP@ +LTP_GENHTML = @LTP_GENHTML@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINTAINER_CFLAGS = @MAINTAINER_CFLAGS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGO_REQ_VERSION = @PANGO_REQ_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SHTOOL = @SHTOOL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +XCOMPOSITE_REQ_VERSION = @XCOMPOSITE_REQ_VERSION@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +installed_test_metadir = @installed_test_metadir@ +installed_testdir = @installed_testdir@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +all_examples = actor-model basic-actor box-layout canvas constraints \ + drag-action drop-action easing-modes flow-layout grid-layout \ + layout-manager pan-action rounded-rectangle scroll-actor \ + threads $(am__append_1) +LDADD = $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la $(CLUTTER_LIBS) $(GDK_PIXBUF_LIBS) $(LIBM) +AM_CFLAGS = $(CLUTTER_CFLAGS) $(GDK_PIXBUF_CFLAGS) $(MAINTAINER_CFLAGS) +AM_CPPFLAGS = \ + -DG_DISABLE_SINGLE_INCLUDES \ + -DGLIB_DISABLE_DEPRECATION_WARNINGS \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + -I$(top_srcdir)/clutter \ + -I$(top_builddir)/clutter + +EXTRA_DIST = redhand.png +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign examples/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign examples/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +actor-model$(EXEEXT): $(actor_model_OBJECTS) $(actor_model_DEPENDENCIES) $(EXTRA_actor_model_DEPENDENCIES) + @rm -f actor-model$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(actor_model_OBJECTS) $(actor_model_LDADD) $(LIBS) + +basic-actor$(EXEEXT): $(basic_actor_OBJECTS) $(basic_actor_DEPENDENCIES) $(EXTRA_basic_actor_DEPENDENCIES) + @rm -f basic-actor$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(basic_actor_OBJECTS) $(basic_actor_LDADD) $(LIBS) + +bin-layout$(EXEEXT): $(bin_layout_OBJECTS) $(bin_layout_DEPENDENCIES) $(EXTRA_bin_layout_DEPENDENCIES) + @rm -f bin-layout$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(bin_layout_OBJECTS) $(bin_layout_LDADD) $(LIBS) + +box-layout$(EXEEXT): $(box_layout_OBJECTS) $(box_layout_DEPENDENCIES) $(EXTRA_box_layout_DEPENDENCIES) + @rm -f box-layout$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(box_layout_OBJECTS) $(box_layout_LDADD) $(LIBS) + +canvas$(EXEEXT): $(canvas_OBJECTS) $(canvas_DEPENDENCIES) $(EXTRA_canvas_DEPENDENCIES) + @rm -f canvas$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(canvas_OBJECTS) $(canvas_LDADD) $(LIBS) + +constraints$(EXEEXT): $(constraints_OBJECTS) $(constraints_DEPENDENCIES) $(EXTRA_constraints_DEPENDENCIES) + @rm -f constraints$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(constraints_OBJECTS) $(constraints_LDADD) $(LIBS) + +drag-action$(EXEEXT): $(drag_action_OBJECTS) $(drag_action_DEPENDENCIES) $(EXTRA_drag_action_DEPENDENCIES) + @rm -f drag-action$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(drag_action_OBJECTS) $(drag_action_LDADD) $(LIBS) + +drop-action$(EXEEXT): $(drop_action_OBJECTS) $(drop_action_DEPENDENCIES) $(EXTRA_drop_action_DEPENDENCIES) + @rm -f drop-action$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(drop_action_OBJECTS) $(drop_action_LDADD) $(LIBS) + +easing-modes$(EXEEXT): $(easing_modes_OBJECTS) $(easing_modes_DEPENDENCIES) $(EXTRA_easing_modes_DEPENDENCIES) + @rm -f easing-modes$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(easing_modes_OBJECTS) $(easing_modes_LDADD) $(LIBS) + +flow-layout$(EXEEXT): $(flow_layout_OBJECTS) $(flow_layout_DEPENDENCIES) $(EXTRA_flow_layout_DEPENDENCIES) + @rm -f flow-layout$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(flow_layout_OBJECTS) $(flow_layout_LDADD) $(LIBS) + +grid-layout$(EXEEXT): $(grid_layout_OBJECTS) $(grid_layout_DEPENDENCIES) $(EXTRA_grid_layout_DEPENDENCIES) + @rm -f grid-layout$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(grid_layout_OBJECTS) $(grid_layout_LDADD) $(LIBS) + +image-content$(EXEEXT): $(image_content_OBJECTS) $(image_content_DEPENDENCIES) $(EXTRA_image_content_DEPENDENCIES) + @rm -f image-content$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(image_content_OBJECTS) $(image_content_LDADD) $(LIBS) + +layout-manager$(EXEEXT): $(layout_manager_OBJECTS) $(layout_manager_DEPENDENCIES) $(EXTRA_layout_manager_DEPENDENCIES) + @rm -f layout-manager$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(layout_manager_OBJECTS) $(layout_manager_LDADD) $(LIBS) + +pan-action$(EXEEXT): $(pan_action_OBJECTS) $(pan_action_DEPENDENCIES) $(EXTRA_pan_action_DEPENDENCIES) + @rm -f pan-action$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pan_action_OBJECTS) $(pan_action_LDADD) $(LIBS) + +rounded-rectangle$(EXEEXT): $(rounded_rectangle_OBJECTS) $(rounded_rectangle_DEPENDENCIES) $(EXTRA_rounded_rectangle_DEPENDENCIES) + @rm -f rounded-rectangle$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(rounded_rectangle_OBJECTS) $(rounded_rectangle_LDADD) $(LIBS) + +scroll-actor$(EXEEXT): $(scroll_actor_OBJECTS) $(scroll_actor_DEPENDENCIES) $(EXTRA_scroll_actor_DEPENDENCIES) + @rm -f scroll-actor$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(scroll_actor_OBJECTS) $(scroll_actor_LDADD) $(LIBS) + +threads$(EXEEXT): $(threads_OBJECTS) $(threads_DEPENDENCIES) $(EXTRA_threads_DEPENDENCIES) + @rm -f threads$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(threads_OBJECTS) $(threads_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/actor-model.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/basic-actor.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bin-layout.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/box-layout.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/canvas.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/constraints.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drag-action.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drop-action.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/easing-modes.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flow-layout.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/grid-layout.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/image-content.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/layout-manager.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pan-action.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rounded-rectangle.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scroll-actor.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/threads.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/clutter/examples/README b/clutter/examples/README new file mode 100644 index 0000000..d3e3556 --- /dev/null +++ b/clutter/examples/README @@ -0,0 +1,10 @@ +The code in this directory is meant to be XIncluded into the Clutter API +reference, and thus is to be considered part of the Clutter documentation. + +As such, the code MUST be: + + - correct; + - idiomatic, i.e. show how a task is meant to be achieved using the + best possible practices given the current API; + - well documented; + - ready for copy and paste. diff --git a/clutter/examples/actor-model.c b/clutter/examples/actor-model.c new file mode 100644 index 0000000..4a6ec77 --- /dev/null +++ b/clutter/examples/actor-model.c @@ -0,0 +1,522 @@ +#include +#include +#include + +/* {{{ MenuItemModel */ + +/* This is our "model" of a Menu item; it has a "label" property, and + * a "selected" state property. The user is supposed to operate on the + * model instance, and change its state. + */ + +#define EXAMPLE_TYPE_MENU_ITEM_MODEL (example_menu_item_model_get_type ()) + +G_DECLARE_FINAL_TYPE (ExampleMenuItemModel, example_menu_item_model, EXAMPLE, MENU_ITEM_MODEL, GObject) + +struct _ExampleMenuItemModel +{ + GObject parent_instance; + + char *label; + + gboolean selected; +}; + +struct _ExampleMenuItemModelClass +{ + GObjectClass parent_class; +}; + +enum { + MENU_ITEM_MODEL_PROP_LABEL = 1, + MENU_ITEM_MODEL_PROP_SELECTED, + MENU_ITEM_MODEL_N_PROPS +}; + +static GParamSpec *menu_item_model_props[MENU_ITEM_MODEL_N_PROPS] = { NULL, }; + +G_DEFINE_TYPE (ExampleMenuItemModel, example_menu_item_model, G_TYPE_OBJECT) + +static void +example_menu_item_model_finalize (GObject *gobject) +{ + ExampleMenuItemModel *self = (ExampleMenuItemModel *) gobject; + + g_free (self->label); + + G_OBJECT_CLASS (example_menu_item_model_parent_class)->finalize (gobject); +} + +static void +example_menu_item_model_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ExampleMenuItemModel *self = (ExampleMenuItemModel *) gobject; + + switch (prop_id) + { + case MENU_ITEM_MODEL_PROP_LABEL: + g_free (self->label); + self->label = g_value_dup_string (value); + break; + + case MENU_ITEM_MODEL_PROP_SELECTED: + self->selected = g_value_get_boolean (value); + break; + } +} + +static void +example_menu_item_model_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ExampleMenuItemModel *self = (ExampleMenuItemModel *) gobject; + + switch (prop_id) + { + case MENU_ITEM_MODEL_PROP_LABEL: + g_value_set_string (value, self->label); + break; + + case MENU_ITEM_MODEL_PROP_SELECTED: + g_value_set_boolean (value, self->selected); + break; + } +} + +static void +example_menu_item_model_class_init (ExampleMenuItemModelClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = example_menu_item_model_set_property; + gobject_class->get_property = example_menu_item_model_get_property; + gobject_class->finalize = example_menu_item_model_finalize; + + menu_item_model_props[MENU_ITEM_MODEL_PROP_LABEL] = + g_param_spec_string ("label", NULL, NULL, + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + menu_item_model_props[MENU_ITEM_MODEL_PROP_SELECTED] = + g_param_spec_boolean ("selected", NULL, NULL, + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (gobject_class, MENU_ITEM_MODEL_N_PROPS, menu_item_model_props); +} + +static void +example_menu_item_model_init (ExampleMenuItemModel *self) +{ +} +/* }}} */ + +/* {{{ MenuItemView */ + +/* This is our "view" of a Menu item; it changes state depending on whether + * the "selected" property is set. The "view" reflects the state of the + * "model" instance, though it has no direct connection to it. + */ +#define EXAMPLE_TYPE_MENU_ITEM_VIEW (example_menu_item_view_get_type ()) + +G_DECLARE_FINAL_TYPE (ExampleMenuItemView, example_menu_item_view, EXAMPLE, MENU_ITEM_VIEW, ClutterText) + +struct _ExampleMenuItemView +{ + ClutterText parent_instance; + + gboolean is_selected; +}; + +struct _ExampleMenuItemViewClass +{ + ClutterTextClass parent_class; +}; + +G_DEFINE_TYPE (ExampleMenuItemView, example_menu_item_view, CLUTTER_TYPE_TEXT) + +enum { + MENU_ITEM_VIEW_PROP_SELECTED = 1, + MENU_ITEM_VIEW_N_PROPS +}; + +static GParamSpec *menu_item_view_props[MENU_ITEM_VIEW_N_PROPS] = { NULL, }; + +static void +example_menu_item_view_set_selected (ExampleMenuItemView *self, + gboolean selected) +{ + selected = !!selected; + if (self->is_selected == selected) + return; + + self->is_selected = selected; + + if (self->is_selected) + clutter_text_set_color (CLUTTER_TEXT (self), CLUTTER_COLOR_LightSkyBlue); + else + clutter_text_set_color (CLUTTER_TEXT (self), CLUTTER_COLOR_White); + + g_object_notify_by_pspec (G_OBJECT (self), menu_item_view_props[MENU_ITEM_VIEW_PROP_SELECTED]); +} + +static void +example_menu_item_view_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) + { + case MENU_ITEM_VIEW_PROP_SELECTED: + example_menu_item_view_set_selected (EXAMPLE_MENU_ITEM_VIEW (gobject), + g_value_get_boolean (value)); + break; + } +} + +static void +example_menu_item_view_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) + { + case MENU_ITEM_VIEW_PROP_SELECTED: + g_value_set_boolean (value, EXAMPLE_MENU_ITEM_VIEW (gobject)->is_selected); + break; + } +} + +static void +example_menu_item_view_class_init (ExampleMenuItemViewClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = example_menu_item_view_set_property; + gobject_class->get_property = example_menu_item_view_get_property; + + menu_item_view_props[MENU_ITEM_VIEW_PROP_SELECTED] = + g_param_spec_boolean ("selected", NULL, NULL, + FALSE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (gobject_class, MENU_ITEM_VIEW_N_PROPS, menu_item_view_props); +} + +static void +example_menu_item_view__transition_stopped (ClutterActor *actor, + const char *transition, + gboolean is_finished) +{ + clutter_actor_set_scale (actor, 1.0, 1.0); + clutter_actor_set_opacity (actor, 255); +} + +static void +example_menu_item_view_init (ExampleMenuItemView *self) +{ + ClutterText *text = CLUTTER_TEXT (self); + ClutterActor *actor = CLUTTER_ACTOR (self); + ClutterTransition *scalex_trans, *scaley_trans, *fade_trans; + ClutterTransition *group; + + clutter_text_set_font_name (text, "Sans Bold 24px"); + clutter_text_set_color (text, CLUTTER_COLOR_White); + + clutter_actor_set_margin_left (actor, 12); + clutter_actor_set_margin_right (actor, 12); + + clutter_actor_set_pivot_point (actor, 0.5, 0.5); + + scalex_trans = clutter_property_transition_new ("scale-x"); + clutter_transition_set_from (scalex_trans, G_TYPE_FLOAT, 1.0); + clutter_transition_set_to (scalex_trans, G_TYPE_FLOAT, 3.0); + + scaley_trans = clutter_property_transition_new ("scale-y"); + clutter_transition_set_from (scaley_trans, G_TYPE_FLOAT, 1.0); + clutter_transition_set_to (scaley_trans, G_TYPE_FLOAT, 3.0); + + fade_trans = clutter_property_transition_new ("opacity"); + clutter_transition_set_to (fade_trans, G_TYPE_UINT, 0); + + group = clutter_transition_group_new (); + clutter_transition_group_add_transition (CLUTTER_TRANSITION_GROUP (group), scalex_trans); + clutter_transition_group_add_transition (CLUTTER_TRANSITION_GROUP (group), scaley_trans); + clutter_transition_group_add_transition (CLUTTER_TRANSITION_GROUP (group), fade_trans); + clutter_timeline_set_duration (CLUTTER_TIMELINE (group), 250); + clutter_timeline_set_progress_mode (CLUTTER_TIMELINE (group), CLUTTER_EASE_OUT); + + clutter_actor_add_transition (actor, "activateTransition", group); + g_object_unref (group); + + clutter_timeline_stop (CLUTTER_TIMELINE (group)); + + g_signal_connect (actor, "transition-stopped", + G_CALLBACK (example_menu_item_view__transition_stopped), + group); +} + +static void +example_menu_item_view_activate (ExampleMenuItemView *self) +{ + ClutterTransition *t; + + t = clutter_actor_get_transition (CLUTTER_ACTOR (self), "activateTransition"); + clutter_timeline_start (CLUTTER_TIMELINE (t)); +} + +/* }}} */ + +/* {{{ Menu */ + +/* This is our container actor, which binds the GListStore with the + * ExampleMenuItemModel instances to the ExampleMenuItemView actors + */ + +#define EXAMPLE_TYPE_MENU (example_menu_get_type ()) + +G_DECLARE_FINAL_TYPE (ExampleMenu, example_menu, EXAMPLE, MENU, ClutterActor) + +struct _ExampleMenu +{ + ClutterActor parent_instance; + + int current_idx; +}; + +struct _ExampleMenuClass +{ + ClutterActorClass parent_class; +}; + +G_DEFINE_TYPE (ExampleMenu, example_menu, CLUTTER_TYPE_ACTOR) + +static void +example_menu_class_init (ExampleMenuClass *klass) +{ +} + +static void +example_menu_init (ExampleMenu *self) +{ + ClutterActor *actor = CLUTTER_ACTOR (self); + ClutterLayoutManager *layout; + + layout = clutter_box_layout_new (); + clutter_box_layout_set_orientation (CLUTTER_BOX_LAYOUT (layout), CLUTTER_ORIENTATION_VERTICAL); + clutter_box_layout_set_spacing (CLUTTER_BOX_LAYOUT (layout), 12); + + clutter_actor_set_layout_manager (actor, layout); + clutter_actor_set_background_color (actor, CLUTTER_COLOR_Black); + + self->current_idx = -1; +} + +static ClutterActor * +example_menu_select_item (ExampleMenu *self, + int idx) +{ + ClutterActor *item; + + /* Any change in the view is reflected into the model */ + + if (idx == self->current_idx) + return clutter_actor_get_child_at_index (CLUTTER_ACTOR (self), self->current_idx); + + item = clutter_actor_get_child_at_index (CLUTTER_ACTOR (self), self->current_idx); + if (item != NULL) + example_menu_item_view_set_selected ((ExampleMenuItemView *) item, FALSE); + + if (idx < 0) + idx = clutter_actor_get_n_children (CLUTTER_ACTOR (self)) - 1; + else if (idx >= clutter_actor_get_n_children (CLUTTER_ACTOR (self))) + idx = 0; + + self->current_idx = idx; + + item = clutter_actor_get_child_at_index (CLUTTER_ACTOR (self), self->current_idx); + if (item != NULL) + example_menu_item_view_set_selected ((ExampleMenuItemView *) item, TRUE); + + return item; +} + +static ClutterActor * +example_menu_select_next (ExampleMenu *self) +{ + return example_menu_select_item (self, self->current_idx + 1); +} + +static ClutterActor * +example_menu_select_prev (ExampleMenu *self) +{ + return example_menu_select_item (self, self->current_idx - 1); +} + +static void +example_menu_activate_item (ExampleMenu *self) +{ + ClutterActor *child; + + child = clutter_actor_get_child_at_index (CLUTTER_ACTOR (self), + self->current_idx); + if (child == NULL) + return; + + example_menu_item_view_activate ((ExampleMenuItemView *) child); +} + +/* }}} */ + +/* {{{ main */ +static gboolean +on_key_press (ClutterActor *stage, + ClutterEvent *event) +{ + ClutterActor *scroll = clutter_actor_get_first_child (stage); + ClutterActor *menu = clutter_actor_get_first_child (scroll); + ClutterActor *item = NULL; + guint key = clutter_event_get_key_symbol (event); + ClutterPoint p; + + switch (key) + { + case CLUTTER_KEY_q: + clutter_main_quit (); + break; + + case CLUTTER_KEY_Up: + item = example_menu_select_prev ((ExampleMenu *) menu); + clutter_actor_get_position (item, &p.x, &p.y); + break; + + case CLUTTER_KEY_Down: + item = example_menu_select_next ((ExampleMenu *) menu); + clutter_actor_get_position (item, &p.x, &p.y); + break; + + case CLUTTER_KEY_Return: + case CLUTTER_KEY_KP_Enter: + example_menu_activate_item ((ExampleMenu *) menu); + break; + } + + if (item != NULL) + clutter_scroll_actor_scroll_to_point (CLUTTER_SCROLL_ACTOR (scroll), &p); + + return CLUTTER_EVENT_PROPAGATE; +} + +static void +on_model_item_selection (GObject *model_item, + GParamSpec *pspec, + gpointer data) +{ + char *label = NULL; + gboolean is_selected = FALSE; + + g_object_get (model_item, "label", &label, "selected", &is_selected, NULL); + + if (is_selected) + g_print ("Item '%s' selected!\n", label); + + g_free (label); +} + +static ClutterActor * +create_menu_actor (void) +{ + /* Our store of menu item models */ + GListStore *model = g_list_store_new (EXAMPLE_TYPE_MENU_ITEM_MODEL); + ClutterActor *menu = g_object_new (EXAMPLE_TYPE_MENU, NULL); + int i; + + /* Populate the model */ + for (i = 0; i < 12; i++) + { + char *label = g_strdup_printf ("Option %02d", i + 1); + + ExampleMenuItemModel *item = g_object_new (EXAMPLE_TYPE_MENU_ITEM_MODEL, + "label", label, + NULL); + + g_list_store_append (model, item); + + g_signal_connect (item, "notify::selected", + G_CALLBACK (on_model_item_selection), + NULL); + + g_object_unref (item); + g_free (label); + } + + /* Bind the list of menu item models to the menu actor; this will + * create ClutterActor views of each item in the model, and add them + * to the menu actor + */ + clutter_actor_bind_model_with_properties (menu, G_LIST_MODEL (model), + EXAMPLE_TYPE_MENU_ITEM_VIEW, + "label", "text", G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE, + "selected", "selected", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE, + NULL); + + /* We don't need a pointer to the model any more, so we transfer ownership + * to the menu actor; this means that the model will go away when the menu + * actor is destroyed + */ + g_object_unref (model); + + /* Select the first item in the menu */ + example_menu_select_item ((ExampleMenu *) menu, 0); + + return menu; +} + +/* The scrolling container for the menu */ +static ClutterActor * +create_scroll_actor (void) +{ + ClutterActor *menu = clutter_scroll_actor_new (); + clutter_actor_set_name (menu, "scroll"); + clutter_scroll_actor_set_scroll_mode (CLUTTER_SCROLL_ACTOR (menu), + CLUTTER_SCROLL_VERTICALLY); + clutter_actor_set_easing_duration (menu, 250); + clutter_actor_add_child (menu, create_menu_actor ()); + + return menu; +} + +int +main (int argc, char *argv[]) +{ + ClutterActor *stage, *menu; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Actor Model"); + clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + g_signal_connect (stage, "key-press-event", G_CALLBACK (on_key_press), NULL); + clutter_actor_show (stage); + +#define PADDING 18.f + + menu = create_scroll_actor (); + clutter_actor_set_position (menu, 0, PADDING); + clutter_actor_add_constraint (menu, clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0.5)); + clutter_actor_add_constraint (menu, clutter_bind_constraint_new (stage, CLUTTER_BIND_HEIGHT, -PADDING * 2)); + clutter_actor_add_child (stage, menu); + + clutter_main (); + + return 0; +} +/* }}} */ diff --git a/clutter/examples/basic-actor.c b/clutter/examples/basic-actor.c new file mode 100644 index 0000000..e74f33e --- /dev/null +++ b/clutter/examples/basic-actor.c @@ -0,0 +1,153 @@ +#include +#include + +#define SIZE 128 + +static gboolean +animate_color (ClutterActor *actor, + ClutterEvent *event) +{ + static gboolean toggled = TRUE; + const ClutterColor *end_color; + + if (toggled) + end_color = CLUTTER_COLOR_Blue; + else + end_color = CLUTTER_COLOR_Red; + + clutter_actor_save_easing_state (actor); + clutter_actor_set_easing_duration (actor, 500); + clutter_actor_set_easing_mode (actor, CLUTTER_LINEAR); + clutter_actor_set_background_color (actor, end_color); + clutter_actor_restore_easing_state (actor); + + toggled = !toggled; + + return CLUTTER_EVENT_STOP; +} + +static gboolean +on_crossing (ClutterActor *actor, + ClutterEvent *event) +{ + gboolean is_enter = clutter_event_type (event) == CLUTTER_ENTER; + float zpos; + + if (is_enter) + zpos = -250.0; + else + zpos = 0.0; + + clutter_actor_save_easing_state (actor); + clutter_actor_set_easing_duration (actor, 500); + clutter_actor_set_easing_mode (actor, CLUTTER_EASE_OUT_BOUNCE); + clutter_actor_set_z_position (actor, zpos); + clutter_actor_restore_easing_state (actor); + + return CLUTTER_EVENT_STOP; +} + +static void +on_transition_stopped (ClutterActor *actor, + const gchar *transition_name, + gboolean is_finished) +{ + clutter_actor_save_easing_state (actor); + clutter_actor_set_rotation_angle (actor, CLUTTER_Y_AXIS, 0.0f); + clutter_actor_restore_easing_state (actor); + + /* disconnect so we don't get multiple notifications */ + g_signal_handlers_disconnect_by_func (actor, + on_transition_stopped, + NULL); +} + +static gboolean +animate_rotation (ClutterActor *actor, + ClutterEvent *event) +{ + clutter_actor_save_easing_state (actor); + clutter_actor_set_easing_duration (actor, 1000); + + clutter_actor_set_rotation_angle (actor, CLUTTER_Y_AXIS, 360.0); + + clutter_actor_restore_easing_state (actor); + + /* get a notification when the rotation-angle-y transition ends */ + g_signal_connect (actor, + "transition-stopped::rotation-angle-y", + G_CALLBACK (on_transition_stopped), + NULL); + + return CLUTTER_EVENT_STOP; +} + +int +main (int argc, char *argv[]) +{ + ClutterActor *stage, *vase; + ClutterActor *flowers[3]; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return EXIT_FAILURE; + + stage = clutter_stage_new (); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Three Flowers in a Vase"); + clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); + + /* there are three flowers in a vase */ + vase = clutter_actor_new (); + clutter_actor_set_name (vase, "vase"); + clutter_actor_set_layout_manager (vase, clutter_box_layout_new ()); + clutter_actor_set_background_color (vase, CLUTTER_COLOR_LightSkyBlue); + clutter_actor_add_constraint (vase, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5)); + clutter_actor_add_child (stage, vase); + + flowers[0] = clutter_actor_new (); + clutter_actor_set_name (flowers[0], "flower.1"); + clutter_actor_set_size (flowers[0], SIZE, SIZE); + clutter_actor_set_margin_left (flowers[0], 12); + clutter_actor_set_background_color (flowers[0], CLUTTER_COLOR_Red); + clutter_actor_set_reactive (flowers[0], TRUE); + clutter_actor_add_child (vase, flowers[0]); + g_signal_connect (flowers[0], "button-press-event", + G_CALLBACK (animate_color), + NULL); + + flowers[1] = clutter_actor_new (); + clutter_actor_set_name (flowers[1], "flower.2"); + clutter_actor_set_size (flowers[1], SIZE, SIZE); + clutter_actor_set_margin_top (flowers[1], 12); + clutter_actor_set_margin_left (flowers[1], 6); + clutter_actor_set_margin_right (flowers[1], 6); + clutter_actor_set_margin_bottom (flowers[1], 12); + clutter_actor_set_background_color (flowers[1], CLUTTER_COLOR_Yellow); + clutter_actor_set_reactive (flowers[1], TRUE); + clutter_actor_add_child (vase, flowers[1]); + g_signal_connect (flowers[1], "enter-event", + G_CALLBACK (on_crossing), + NULL); + g_signal_connect (flowers[1], "leave-event", + G_CALLBACK (on_crossing), + NULL); + + /* the third one is green */ + flowers[2] = clutter_actor_new (); + clutter_actor_set_name (flowers[2], "flower.3"); + clutter_actor_set_size (flowers[2], SIZE, SIZE); + clutter_actor_set_margin_right (flowers[2], 12); + clutter_actor_set_background_color (flowers[2], CLUTTER_COLOR_Green); + clutter_actor_set_pivot_point (flowers[2], 0.5f, 0.0f); + clutter_actor_set_reactive (flowers[2], TRUE); + clutter_actor_add_child (vase, flowers[2]); + g_signal_connect (flowers[2], "button-press-event", + G_CALLBACK (animate_rotation), + NULL); + + clutter_actor_show (stage); + + clutter_main (); + + return EXIT_SUCCESS; +} diff --git a/clutter/examples/bin-layout.c b/clutter/examples/bin-layout.c new file mode 100644 index 0000000..b6098d6 --- /dev/null +++ b/clutter/examples/bin-layout.c @@ -0,0 +1,307 @@ +#include +#include +#include +#include + +static const ClutterColor bg_color = { 0xcc, 0xcc, 0xcc, 0x99 }; + +static gboolean is_expanded = FALSE; + +static gboolean +on_canvas_draw (ClutterCanvas *canvas, + cairo_t *cr, + gint width, + gint height) +{ + cairo_pattern_t *pat; + gfloat x, y; + + g_print (G_STRLOC ": Painting at %d x %d\n", width, height); + + cairo_save (cr); + cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); + cairo_paint (cr); + cairo_restore (cr); + +#define BG_ROUND_RADIUS 12 + + x = y = 0; + + cairo_move_to (cr, BG_ROUND_RADIUS, y); + cairo_line_to (cr, width - BG_ROUND_RADIUS, y); + cairo_curve_to (cr, width, y, width, y, width, BG_ROUND_RADIUS); + cairo_line_to (cr, width, height - BG_ROUND_RADIUS); + cairo_curve_to (cr, width, height, width, height, width - BG_ROUND_RADIUS, height); + cairo_line_to (cr, BG_ROUND_RADIUS, height); + cairo_curve_to (cr, x, height, x, height, x, height - BG_ROUND_RADIUS); + cairo_line_to (cr, x, BG_ROUND_RADIUS); + cairo_curve_to (cr, x, y, x, y, BG_ROUND_RADIUS, y); + + cairo_close_path (cr); + + clutter_cairo_set_source_color (cr, &bg_color); + cairo_stroke (cr); + + x += 4; + y += 4; + width -= 4; + height -= 4; + + cairo_move_to (cr, BG_ROUND_RADIUS, y); + cairo_line_to (cr, width - BG_ROUND_RADIUS, y); + cairo_curve_to (cr, width, y, width, y, width, BG_ROUND_RADIUS); + cairo_line_to (cr, width, height - BG_ROUND_RADIUS); + cairo_curve_to (cr, width, height, width, height, width - BG_ROUND_RADIUS, height); + cairo_line_to (cr, BG_ROUND_RADIUS, height); + cairo_curve_to (cr, x, height, x, height, x, height - BG_ROUND_RADIUS); + cairo_line_to (cr, x, BG_ROUND_RADIUS); + cairo_curve_to (cr, x, y, x, y, BG_ROUND_RADIUS, y); + + cairo_close_path (cr); + + pat = cairo_pattern_create_linear (0, 0, 0, height); + cairo_pattern_add_color_stop_rgba (pat, 1, .85, .85, .85, 1); + cairo_pattern_add_color_stop_rgba (pat, .95, 1, 1, 1, 1); + cairo_pattern_add_color_stop_rgba (pat, .05, 1, 1, 1, 1); + cairo_pattern_add_color_stop_rgba (pat, 0, .85, .85, .85, 1); + + cairo_set_source (cr, pat); + cairo_fill (cr); + + cairo_pattern_destroy (pat); + +#undef BG_ROUND_RADIUS + + return TRUE; +} + +static gboolean +on_box_enter (ClutterActor *box, + ClutterEvent *event, + ClutterActor *emblem) +{ + /* we ease the opacity linearly */ + clutter_actor_save_easing_state (emblem); + clutter_actor_set_easing_mode (emblem, CLUTTER_LINEAR); + clutter_actor_set_opacity (emblem, 255); + clutter_actor_restore_easing_state (emblem); + + return CLUTTER_EVENT_STOP; +} + +static gboolean +on_box_leave (ClutterActor *box, + ClutterEvent *event, + ClutterActor *emblem) +{ + clutter_actor_save_easing_state (emblem); + clutter_actor_set_easing_mode (emblem, CLUTTER_LINEAR); + clutter_actor_set_opacity (emblem, 0); + clutter_actor_restore_easing_state (emblem); + + return CLUTTER_EVENT_STOP; +} + +static void +on_emblem_clicked (ClutterClickAction *action, + ClutterActor *emblem, + ClutterActor *box) +{ + /* we add a little bounce to the resizing of the box */ + clutter_actor_save_easing_state (box); + clutter_actor_set_easing_mode (box, CLUTTER_EASE_OUT_BOUNCE); + clutter_actor_set_easing_duration (box, 500); + + if (!is_expanded) + clutter_actor_set_size (box, 400, 400); + else + clutter_actor_set_size (box, 200, 200); + + clutter_actor_restore_easing_state (box); + + is_expanded = !is_expanded; +} + +static gboolean +on_emblem_long_press (ClutterClickAction *action, + ClutterActor *emblem, + ClutterLongPressState state, + ClutterActor *box) +{ + switch (state) + { + case CLUTTER_LONG_PRESS_QUERY: + g_print ("*** long press: query ***\n"); + return is_expanded; + + case CLUTTER_LONG_PRESS_CANCEL: + g_print ("*** long press: cancel ***\n"); + break; + + case CLUTTER_LONG_PRESS_ACTIVATE: + g_print ("*** long press: activate ***\n"); + break; + } + + return TRUE; +} + +static void +redraw_canvas (ClutterActor *actor, + ClutterCanvas *canvas) +{ + /* we want to invalidate the canvas and redraw its contents + * only when the size changes at the end of the animation, + * to avoid drawing all the states inbetween + */ + clutter_canvas_set_size (canvas, + clutter_actor_get_width (actor), + clutter_actor_get_height (actor)); +} + +int +main (int argc, char *argv[]) +{ + ClutterActor *stage, *box, *bg, *icon, *emblem, *label; + ClutterLayoutManager *layout; + ClutterContent *canvas, *image; + ClutterColor *color; + ClutterAction *action; + GdkPixbuf *pixbuf; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + /* prepare the stage */ + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "BinLayout"); + clutter_actor_set_background_color (stage, CLUTTER_COLOR_Aluminium2); + clutter_actor_set_size (stage, 640, 480); + clutter_actor_show (stage); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + /* this is our BinLayout, with its default alignments */ + layout = clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_CENTER, + CLUTTER_BIN_ALIGNMENT_CENTER); + + /* the main container; this actor will use the BinLayout to lay + * out its children; we use the anchor point to keep it centered + * on the same position even when we change its size + */ + box = clutter_actor_new (); + clutter_actor_set_layout_manager (box, layout); + clutter_actor_add_constraint (box, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5)); + clutter_actor_set_position (box, 320, 240); + clutter_actor_set_reactive (box, TRUE); + clutter_actor_set_name (box, "box"); + clutter_actor_add_child (stage, box); + + /* the background is drawn using a canvas content */ + canvas = clutter_canvas_new (); + g_signal_connect (canvas, "draw", G_CALLBACK (on_canvas_draw), NULL); + clutter_canvas_set_size (CLUTTER_CANVAS (canvas), 200, 200); + + /* this is the background actor; we want it to fill the whole + * of the allocation given to it by its parent + */ + bg = clutter_actor_new (); + clutter_actor_set_name (bg, "background"); + clutter_actor_set_size (bg, 200, 200); + clutter_actor_set_content (bg, canvas); + clutter_actor_set_x_expand (bg, TRUE); + clutter_actor_set_y_expand (bg, TRUE); + clutter_actor_set_x_align (bg, CLUTTER_ACTOR_ALIGN_FILL); + clutter_actor_set_y_align (bg, CLUTTER_ACTOR_ALIGN_FILL); + clutter_actor_add_child (box, bg); + /* we use the ::transitions-completed signal to get notification + * of the end of the sizing animation; this allows us to redraw + * the canvas only once the animation has stopped + */ + g_signal_connect (box, "transitions-completed", + G_CALLBACK (redraw_canvas), + canvas); + + /* we use GdkPixbuf to load an image from our data directory */ + pixbuf = gdk_pixbuf_new_from_file ("redhand.png", NULL); + image = clutter_image_new (); + clutter_image_set_data (CLUTTER_IMAGE (image), + gdk_pixbuf_get_pixels (pixbuf), + gdk_pixbuf_get_has_alpha (pixbuf) + ? COGL_PIXEL_FORMAT_RGBA_8888 + : COGL_PIXEL_FORMAT_RGB_888, + gdk_pixbuf_get_width (pixbuf), + gdk_pixbuf_get_height (pixbuf), + gdk_pixbuf_get_rowstride (pixbuf), + NULL); + g_object_unref (pixbuf); + + /* this is the icon; it's going to be centered inside the box actor. + * we use the content gravity to keep the aspect ratio of the image, + * and the scaling filters to get a better result when scaling the + * image down. + */ + icon = clutter_actor_new (); + clutter_actor_set_name (icon, "icon"); + clutter_actor_set_size (icon, 196, 196); + clutter_actor_set_x_expand (icon, TRUE); + clutter_actor_set_y_expand (icon, TRUE); + clutter_actor_set_x_align (icon, CLUTTER_ACTOR_ALIGN_CENTER); + clutter_actor_set_y_align (icon, CLUTTER_ACTOR_ALIGN_CENTER); + clutter_actor_set_content_gravity (icon, CLUTTER_CONTENT_GRAVITY_RESIZE_ASPECT); + clutter_actor_set_content_scaling_filters (icon, + CLUTTER_SCALING_FILTER_TRILINEAR, + CLUTTER_SCALING_FILTER_LINEAR); + clutter_actor_set_content (icon, image); + clutter_actor_add_child (box, icon); + + color = clutter_color_new (g_random_int_range (0, 255), + g_random_int_range (0, 255), + g_random_int_range (0, 255), + 224); + + /* this is the emblem: a small rectangle with a random color, that we + * want to put in the bottom right corner + */ + emblem = clutter_actor_new (); + clutter_actor_set_name (emblem, "emblem"); + clutter_actor_set_size (emblem, 48, 48); + clutter_actor_set_background_color (emblem, color); + clutter_actor_set_x_expand (emblem, TRUE); + clutter_actor_set_y_expand (emblem, TRUE); + clutter_actor_set_x_align (emblem, CLUTTER_ACTOR_ALIGN_END); + clutter_actor_set_y_align (emblem, CLUTTER_ACTOR_ALIGN_END); + clutter_actor_set_reactive (emblem, TRUE); + clutter_actor_set_opacity (emblem, 0); + clutter_actor_add_child (box, emblem); + clutter_color_free (color); + + /* when clicking on the emblem, we want to perform an action */ + action = clutter_click_action_new (); + clutter_actor_add_action (emblem, action); + g_signal_connect (action, "clicked", G_CALLBACK (on_emblem_clicked), box); + g_signal_connect (action, "long-press", G_CALLBACK (on_emblem_long_press), box); + + /* whenever the pointer enters the box, we show the emblem; we hide + * the emblem when the pointer leaves the box + */ + g_signal_connect (box, + "enter-event", G_CALLBACK (on_box_enter), + emblem); + g_signal_connect (box, + "leave-event", G_CALLBACK (on_box_leave), + emblem); + + /* a label, that we want to position at the top and center of the box */ + label = clutter_text_new (); + clutter_actor_set_name (label, "text"); + clutter_text_set_text (CLUTTER_TEXT (label), "A simple test"); + clutter_actor_set_x_expand (label, TRUE); + clutter_actor_set_x_align (label, CLUTTER_ACTOR_ALIGN_CENTER); + clutter_actor_set_y_expand (label, TRUE); + clutter_actor_set_y_align (label, CLUTTER_ACTOR_ALIGN_START); + clutter_actor_add_child (box, label); + + clutter_main (); + + return EXIT_SUCCESS; +} diff --git a/clutter/examples/box-layout.c b/clutter/examples/box-layout.c new file mode 100644 index 0000000..867b9f6 --- /dev/null +++ b/clutter/examples/box-layout.c @@ -0,0 +1,314 @@ +/* + * Copyright 2009 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * Boston, MA 02111-1307, USA. + * + */ +#include +#include + +#define INSTRUCTIONS \ + "Press v\t\342\236\236\tSwitch horizontal/vertical\n" \ + "Press h\t\342\236\236\tToggle homogeneous\n" \ + "Press p\t\342\236\236\tToggle pack start/end\n" \ + "Press s\t\342\236\236\tIncrement spacing (up to 12px)\n" \ + "Press +\t\342\236\236\tAdd a new actor\n" \ + "Press a\t\342\236\236\tToggle animations\n" \ + "Press q\t\342\236\236\tQuit" + + +static const gchar * +get_align_name (ClutterActorAlign align) +{ + switch (align) + { + case CLUTTER_ACTOR_ALIGN_FILL: + return "fill"; + + case CLUTTER_ACTOR_ALIGN_START: + return "start"; + + case CLUTTER_ACTOR_ALIGN_CENTER: + return "center"; + + case CLUTTER_ACTOR_ALIGN_END: + return "end"; + + default: + g_assert_not_reached (); + } +} + +static gboolean +button_release_cb (ClutterActor *rect, + ClutterEvent *event, + gpointer user_data) +{ + ClutterActorAlign x_align, y_align; + gboolean x_expand, y_expand; + + g_object_get (rect, + "x-align", &x_align, + "y-align", &y_align, + "x-expand", &x_expand, + "y-expand", &y_expand, + NULL); + + switch (clutter_event_get_button (event)) + { + case CLUTTER_BUTTON_PRIMARY: + if (clutter_event_has_shift_modifier (event)) + { + if (y_align < 3) + y_align += 1; + else + y_align = 0; + break; + } + else + { + if (x_align < 3) + x_align += 1; + else + x_align = 0; + } + break; + + case CLUTTER_BUTTON_SECONDARY: + if (clutter_event_has_shift_modifier (event)) + y_expand = !y_expand; + else + x_expand = !x_expand; + break; + + default: + break; + } + + g_object_set (rect, + "x-align", x_align, + "y-align", y_align, + "x-expand", x_expand, + "y-expand", y_expand, + NULL); + return TRUE; +} + +static void +changed_cb (ClutterActor *actor, + GParamSpec *pspec, + ClutterActor *text) +{ + ClutterActorAlign x_align, y_align; + gboolean x_expand, y_expand; + gchar *label; + + g_object_get (actor, + "x-align", &x_align, + "y-align", &y_align, + "x-expand", &x_expand, + "y-expand", &y_expand, + NULL); + + label = g_strdup_printf ("%d,%d\n" + "%s\n%s", + x_expand, y_expand, + get_align_name (x_align), + get_align_name (y_align)); + clutter_text_set_text (CLUTTER_TEXT (text), label); + g_free (label); +} + +static void +add_actor (ClutterActor *box, + gint position) +{ + ClutterActor *rect, *text; + ClutterColor color; + ClutterLayoutManager *layout; + + clutter_color_from_hls (&color, + g_random_double_range (0.0, 360.0), + 0.5, + 0.5); + color.alpha = 255; + + layout = clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_CENTER, + CLUTTER_BIN_ALIGNMENT_CENTER); + rect = clutter_actor_new (); + clutter_actor_set_layout_manager (rect, layout); + clutter_actor_set_background_color (rect, &color); + clutter_actor_set_reactive (rect, TRUE); + clutter_actor_set_size (rect, 32, 64); + clutter_actor_set_x_expand (rect, TRUE); + clutter_actor_set_y_expand (rect, TRUE); + clutter_actor_set_x_align (rect, CLUTTER_ACTOR_ALIGN_CENTER); + clutter_actor_set_y_align (rect, CLUTTER_ACTOR_ALIGN_CENTER); + + text = clutter_text_new_with_text ("Sans 8px", NULL); + clutter_text_set_line_alignment (CLUTTER_TEXT (text), + PANGO_ALIGN_CENTER); + clutter_actor_add_child (rect, text); + + g_signal_connect (rect, "button-release-event", + G_CALLBACK (button_release_cb), NULL); + g_signal_connect (rect, "notify::x-expand", + G_CALLBACK (changed_cb), text); + g_signal_connect (rect, "notify::y-expand", + G_CALLBACK (changed_cb), text); + g_signal_connect (rect, "notify::x-align", + G_CALLBACK (changed_cb), text); + g_signal_connect (rect, "notify::y-align", + G_CALLBACK (changed_cb), text); + changed_cb (rect, NULL, text); + + clutter_actor_insert_child_at_index (box, rect, position); +} + +static gboolean +key_release_cb (ClutterActor *stage, + ClutterEvent *event, + ClutterActor *box) +{ + ClutterBoxLayout *layout; + gboolean toggle; + guint spacing; + + layout = CLUTTER_BOX_LAYOUT (clutter_actor_get_layout_manager (box)); + + switch (clutter_event_get_key_symbol (event)) + { + case CLUTTER_KEY_a: + { + ClutterActorIter iter; + ClutterActor *child; + + clutter_actor_iter_init (&iter, box); + while (clutter_actor_iter_next (&iter, &child)) + { + guint duration; + + duration = clutter_actor_get_easing_duration (child); + if (duration != 0) + duration = 0; + else + duration = 250; + + clutter_actor_set_easing_duration (child, duration); + } + } + break; + + case CLUTTER_KEY_v: + { + ClutterOrientation orientation; + + orientation = clutter_box_layout_get_orientation (layout); + + if (orientation == CLUTTER_ORIENTATION_HORIZONTAL) + orientation = CLUTTER_ORIENTATION_VERTICAL; + else + orientation = CLUTTER_ORIENTATION_HORIZONTAL; + + clutter_box_layout_set_orientation (layout, orientation); + } + break; + + case CLUTTER_KEY_h: + toggle = clutter_box_layout_get_homogeneous (layout); + clutter_box_layout_set_homogeneous (layout, !toggle); + break; + + case CLUTTER_KEY_p: + toggle = clutter_box_layout_get_pack_start (layout); + clutter_box_layout_set_pack_start (layout, !toggle); + break; + + case CLUTTER_KEY_s: + spacing = clutter_box_layout_get_spacing (layout); + + if (spacing > 12) + spacing = 0; + else + spacing++; + + clutter_box_layout_set_spacing (layout, spacing); + break; + + case CLUTTER_KEY_plus: + add_actor (box, g_random_int_range (0, clutter_actor_get_n_children (box))); + break; + + case CLUTTER_KEY_q: + clutter_main_quit (); + break; + + default: + return FALSE; + } + + return TRUE; +} + +int +main (int argc, char *argv[]) +{ + ClutterActor *stage, *box, *instructions; + ClutterLayoutManager *layout; + gint i; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return EXIT_FAILURE; + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Box Layout"); + clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); + + /* make the stage a vbox */ + layout = clutter_box_layout_new (); + clutter_box_layout_set_orientation (CLUTTER_BOX_LAYOUT (layout), + CLUTTER_ORIENTATION_VERTICAL); + clutter_actor_set_layout_manager (stage, layout); + + box = clutter_actor_new (); + clutter_actor_set_background_color (box, CLUTTER_COLOR_LightGray); + clutter_actor_set_x_expand (box, TRUE); + clutter_actor_set_y_expand (box, TRUE); + layout = clutter_box_layout_new (); + clutter_actor_set_layout_manager (box, layout); + clutter_actor_add_child (stage, box); + + instructions = clutter_text_new_with_text ("Sans 12px", INSTRUCTIONS); + clutter_actor_set_x_expand (instructions, TRUE); + clutter_actor_set_y_expand (instructions, FALSE); + clutter_actor_set_x_align (instructions, CLUTTER_ACTOR_ALIGN_START); + clutter_actor_set_margin_top (instructions, 4); + clutter_actor_set_margin_left (instructions, 4); + clutter_actor_set_margin_bottom (instructions, 4); + clutter_actor_add_child (stage, instructions); + + for (i = 0; i < 5; i++) + add_actor (box, i); + + g_signal_connect (stage, "destroy", + G_CALLBACK (clutter_main_quit), NULL); + g_signal_connect (stage, "key-release-event", + G_CALLBACK (key_release_cb), box); + + clutter_actor_show (stage); + clutter_main (); + + return EXIT_SUCCESS; +} diff --git a/clutter/examples/canvas.c b/clutter/examples/canvas.c new file mode 100644 index 0000000..2371f96 --- /dev/null +++ b/clutter/examples/canvas.c @@ -0,0 +1,170 @@ +#include +#include +#include +#include + +static gboolean +draw_clock (ClutterCanvas *canvas, + cairo_t *cr, + int width, + int height) +{ + GDateTime *now; + float hours, minutes, seconds; + ClutterColor color; + + /* get the current time and compute the angles */ + now = g_date_time_new_now_local (); + seconds = g_date_time_get_second (now) * G_PI / 30; + minutes = g_date_time_get_minute (now) * G_PI / 30; + hours = g_date_time_get_hour (now) * G_PI / 6; + + cairo_save (cr); + + /* clear the contents of the canvas, to avoid painting + * over the previous frame + */ + cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); + cairo_paint (cr); + + cairo_restore (cr); + + cairo_set_operator (cr, CAIRO_OPERATOR_OVER); + + /* scale the modelview to the size of the surface */ + cairo_scale (cr, width, height); + + cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); + cairo_set_line_width (cr, 0.1); + + /* the black rail that holds the seconds indicator */ + clutter_cairo_set_source_color (cr, CLUTTER_COLOR_Black); + cairo_translate (cr, 0.5, 0.5); + cairo_arc (cr, 0, 0, 0.4, 0, G_PI * 2); + cairo_stroke (cr); + + /* the seconds indicator */ + color = *CLUTTER_COLOR_White; + color.alpha = 128; + clutter_cairo_set_source_color (cr, &color); + cairo_move_to (cr, 0, 0); + cairo_arc (cr, sinf (seconds) * 0.4, - cosf (seconds) * 0.4, 0.05, 0, G_PI * 2); + cairo_fill (cr); + + /* the minutes hand */ + color = *CLUTTER_COLOR_DarkChameleon; + color.alpha = 196; + clutter_cairo_set_source_color (cr, &color); + cairo_move_to (cr, 0, 0); + cairo_line_to (cr, sinf (minutes) * 0.4, -cosf (minutes) * 0.4); + cairo_stroke (cr); + + /* the hours hand */ + cairo_move_to (cr, 0, 0); + cairo_line_to (cr, sinf (hours) * 0.2, -cosf (hours) * 0.2); + cairo_stroke (cr); + + g_date_time_unref (now); + + /* we're done drawing */ + return TRUE; +} + +static gboolean +invalidate_clock (gpointer data_) +{ + /* invalidate the contents of the canvas */ + clutter_content_invalidate (data_); + + /* keep the timeout source */ + return G_SOURCE_CONTINUE; +} + +static guint idle_resize_id; + +static gboolean +idle_resize (gpointer data) +{ + ClutterActor *actor = data; + float width, height; + + /* match the canvas size to the actor's */ + clutter_actor_get_size (actor, &width, &height); + clutter_canvas_set_size (CLUTTER_CANVAS (clutter_actor_get_content (actor)), + ceilf (width), + ceilf (height)); + + /* unset the guard */ + idle_resize_id = 0; + + /* remove the timeout */ + return G_SOURCE_REMOVE; +} + +static void +on_actor_resize (ClutterActor *actor, + const ClutterActorBox *allocation, + ClutterAllocationFlags flags, + gpointer user_data) +{ + /* throttle multiple actor allocations to one canvas resize; we use a guard + * variable to avoid queueing multiple resize operations + */ + if (idle_resize_id == 0) + idle_resize_id = clutter_threads_add_timeout (1000, idle_resize, actor); +} + +int +main (int argc, char *argv[]) +{ + ClutterActor *stage, *actor; + ClutterContent *canvas; + + /* initialize Clutter */ + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return EXIT_FAILURE; + + /* create a resizable stage */ + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "2D Clock"); + clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); + clutter_actor_set_background_color (stage, CLUTTER_COLOR_LightSkyBlue); + clutter_actor_set_size (stage, 300, 300); + clutter_actor_show (stage); + + /* our 2D canvas, courtesy of Cairo */ + canvas = clutter_canvas_new (); + clutter_canvas_set_size (CLUTTER_CANVAS (canvas), 300, 300); + + actor = clutter_actor_new (); + clutter_actor_set_content (actor, canvas); + clutter_actor_set_content_scaling_filters (actor, + CLUTTER_SCALING_FILTER_TRILINEAR, + CLUTTER_SCALING_FILTER_LINEAR); + clutter_actor_add_child (stage, actor); + + /* the actor now owns the canvas */ + g_object_unref (canvas); + + /* bind the size of the actor to that of the stage */ + clutter_actor_add_constraint (actor, clutter_bind_constraint_new (stage, CLUTTER_BIND_SIZE, 0)); + + /* resize the canvas whenever the actor changes size */ + g_signal_connect (actor, "allocation-changed", G_CALLBACK (on_actor_resize), NULL); + + /* quit on destroy */ + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + /* connect our drawing code */ + g_signal_connect (canvas, "draw", G_CALLBACK (draw_clock), NULL); + + /* invalidate the canvas, so that we can draw before the main loop starts */ + clutter_content_invalidate (canvas); + + /* set up a timer that invalidates the canvas every second */ + clutter_threads_add_timeout (1000, invalidate_clock, canvas); + + clutter_main (); + + return EXIT_SUCCESS; +} diff --git a/clutter/examples/constraints.c b/clutter/examples/constraints.c new file mode 100644 index 0000000..99af0a4 --- /dev/null +++ b/clutter/examples/constraints.c @@ -0,0 +1,90 @@ +#include +#include + +int +main (int argc, char *argv[]) +{ + ClutterActor *stage, *layer_a, *layer_b, *layer_c; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + /* the main container */ + stage = clutter_stage_new (); + clutter_actor_set_name (stage, "stage"); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Snap Constraint"); + clutter_actor_set_background_color (stage, CLUTTER_COLOR_Aluminium1); + clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + /* first layer, with a fixed (100, 25) size */ + layer_a = clutter_actor_new (); + clutter_actor_set_background_color (layer_a, CLUTTER_COLOR_ScarletRed); + clutter_actor_set_name (layer_a, "layerA"); + clutter_actor_set_size (layer_a, 100.0, 25.0); + clutter_actor_add_child (stage, layer_a); + + /* the first layer is anchored to the middle of the stage */ + clutter_actor_add_constraint (layer_a, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5)); + + /* second layer, with no implicit size */ + layer_b = clutter_actor_new (); + clutter_actor_set_background_color (layer_b, CLUTTER_COLOR_DarkButter); + clutter_actor_set_name (layer_b, "layerB"); + clutter_actor_add_child (stage, layer_b); + + /* the second layer tracks the X coordinate and the width of + * the first layer + */ + clutter_actor_add_constraint (layer_b, clutter_bind_constraint_new (layer_a, CLUTTER_BIND_X, 0.0)); + clutter_actor_add_constraint (layer_b, clutter_bind_constraint_new (layer_a, CLUTTER_BIND_WIDTH, 0.0)); + + /* the second layer is snapped between the bottom edge of + * the first layer, and the bottom edge of the stage; a + * spacing of 10 pixels in each direction is added for padding + */ + clutter_actor_add_constraint (layer_b, + clutter_snap_constraint_new (layer_a, + CLUTTER_SNAP_EDGE_TOP, + CLUTTER_SNAP_EDGE_BOTTOM, + 10.0)); + + clutter_actor_add_constraint (layer_b, + clutter_snap_constraint_new (stage, + CLUTTER_SNAP_EDGE_BOTTOM, + CLUTTER_SNAP_EDGE_BOTTOM, + -10.0)); + + /* the third layer, with no implicit size */ + layer_c = clutter_actor_new (); + clutter_actor_set_background_color (layer_c, CLUTTER_COLOR_LightChameleon); + clutter_actor_set_name (layer_c, "layerC"); + clutter_actor_add_child (stage, layer_c); + + /* as for the second layer, the third layer tracks the X + * coordinate and width of the first layer + */ + clutter_actor_add_constraint (layer_c, clutter_bind_constraint_new (layer_a, CLUTTER_BIND_X, 0.0)); + clutter_actor_add_constraint (layer_c, clutter_bind_constraint_new (layer_a, CLUTTER_BIND_WIDTH, 0.0)); + + /* the third layer is snapped between the top edge of the stage + * and the top edge of the first layer; again, a spacing of + * 10 pixels in each direction is added for padding + */ + clutter_actor_add_constraint (layer_c, + clutter_snap_constraint_new (layer_a, + CLUTTER_SNAP_EDGE_BOTTOM, + CLUTTER_SNAP_EDGE_TOP, + -10.0)); + clutter_actor_add_constraint (layer_c, + clutter_snap_constraint_new (stage, + CLUTTER_SNAP_EDGE_TOP, + CLUTTER_SNAP_EDGE_TOP, + 10.0)); + + clutter_actor_show (stage); + + clutter_main (); + + return EXIT_SUCCESS; +} diff --git a/clutter/examples/drag-action.c b/clutter/examples/drag-action.c new file mode 100644 index 0000000..d6ed567 --- /dev/null +++ b/clutter/examples/drag-action.c @@ -0,0 +1,249 @@ +#include +#include + +static gboolean +on_enter (ClutterActor *actor, + ClutterEvent *event) +{ + ClutterTransition *t; + + t = clutter_actor_get_transition (actor, "curl"); + if (t == NULL) + { + t = clutter_property_transition_new ("@effects.curl.period"); + clutter_timeline_set_duration (CLUTTER_TIMELINE (t), 250); + clutter_actor_add_transition (actor, "curl", t); + g_object_unref (t); + } + + clutter_transition_set_from (t, G_TYPE_DOUBLE, 0.0); + clutter_transition_set_to (t, G_TYPE_DOUBLE, 0.25); + clutter_timeline_rewind (CLUTTER_TIMELINE (t)); + clutter_timeline_start (CLUTTER_TIMELINE (t)); + + return CLUTTER_EVENT_STOP; +} + +static gboolean +on_leave (ClutterActor *actor, + ClutterEvent *event) +{ + ClutterTransition *t; + + t = clutter_actor_get_transition (actor, "curl"); + if (t == NULL) + { + t = clutter_property_transition_new ("@effects.curl.period"); + clutter_timeline_set_duration (CLUTTER_TIMELINE (t), 250); + clutter_actor_add_transition (actor, "curl", t); + g_object_unref (t); + } + + clutter_transition_set_from (t, G_TYPE_DOUBLE, 0.25); + clutter_transition_set_to (t, G_TYPE_DOUBLE, 0.0); + clutter_timeline_rewind (CLUTTER_TIMELINE (t)); + clutter_timeline_start (CLUTTER_TIMELINE (t)); + + return CLUTTER_EVENT_STOP; +} + +static void +on_drag_begin (ClutterDragAction *action, + ClutterActor *actor, + gfloat event_x, + gfloat event_y, + ClutterModifierType modifiers) +{ + gboolean is_copy = (modifiers & CLUTTER_SHIFT_MASK) ? TRUE : FALSE; + ClutterActor *drag_handle = NULL; + ClutterTransition *t; + + if (is_copy) + { + ClutterActor *stage = clutter_actor_get_stage (actor); + + drag_handle = clutter_actor_new (); + clutter_actor_set_size (drag_handle, 48, 48); + + clutter_actor_set_background_color (drag_handle, CLUTTER_COLOR_DarkSkyBlue); + + clutter_actor_add_child (stage, drag_handle); + clutter_actor_set_position (drag_handle, event_x, event_y); + } + else + drag_handle = actor; + + clutter_drag_action_set_drag_handle (action, drag_handle); + + /* fully desaturate the actor */ + t = clutter_actor_get_transition (actor, "disable"); + if (t == NULL) + { + t = clutter_property_transition_new ("@effects.disable.factor"); + clutter_timeline_set_duration (CLUTTER_TIMELINE (t), 250); + clutter_actor_add_transition (actor, "disable", t); + g_object_unref (t); + } + + clutter_transition_set_from (t, G_TYPE_DOUBLE, 0.0); + clutter_transition_set_to (t, G_TYPE_DOUBLE, 1.0); + clutter_timeline_rewind (CLUTTER_TIMELINE (t)); + clutter_timeline_start (CLUTTER_TIMELINE (t)); +} + +static void +on_drag_end (ClutterDragAction *action, + ClutterActor *actor, + gfloat event_x, + gfloat event_y, + ClutterModifierType modifiers) +{ + ClutterActor *drag_handle; + ClutterTransition *t; + + drag_handle = clutter_drag_action_get_drag_handle (action); + if (actor != drag_handle) + { + gfloat real_x, real_y; + ClutterActor *parent; + + /* if we are dragging a copy we can destroy the copy now + * and animate the real actor to the drop coordinates, + * transformed in the parent's coordinate space + */ + clutter_actor_save_easing_state (drag_handle); + clutter_actor_set_easing_mode (drag_handle, CLUTTER_LINEAR); + clutter_actor_set_opacity (drag_handle, 0); + clutter_actor_restore_easing_state (drag_handle); + g_signal_connect (drag_handle, "transitions-completed", + G_CALLBACK (clutter_actor_destroy), + NULL); + + parent = clutter_actor_get_parent (actor); + clutter_actor_transform_stage_point (parent, event_x, event_y, + &real_x, + &real_y); + + clutter_actor_save_easing_state (actor); + clutter_actor_set_easing_mode (actor, CLUTTER_EASE_OUT_CUBIC); + clutter_actor_set_position (actor, real_x, real_y); + clutter_actor_restore_easing_state (actor); + } + + t = clutter_actor_get_transition (actor, "disable"); + if (t == NULL) + { + t = clutter_property_transition_new ("@effects.disable.factor"); + clutter_timeline_set_duration (CLUTTER_TIMELINE (t), 250); + clutter_actor_add_transition (actor, "disable", t); + g_object_unref (t); + } + + clutter_transition_set_from (t, G_TYPE_DOUBLE, 1.0); + clutter_transition_set_to (t, G_TYPE_DOUBLE, 0.0); + clutter_timeline_rewind (CLUTTER_TIMELINE (t)); + clutter_timeline_start (CLUTTER_TIMELINE (t)); +} + +static ClutterDragAxis +get_drag_axis (const gchar *str) +{ + if (str == NULL || *str == '\0') + return CLUTTER_DRAG_AXIS_NONE; + + if (*str == 'x' || *str == 'X') + return CLUTTER_DRAG_X_AXIS; + + if (*str == 'y' || *str == 'Y') + return CLUTTER_DRAG_Y_AXIS; + + g_warn_if_reached (); + + return CLUTTER_DRAG_AXIS_NONE; +} + +static gchar *drag_axis = NULL; +static gint x_drag_threshold = 0; +static gint y_drag_threshold = 0; + +static GOptionEntry entries[] = { + { + "x-threshold", 'x', + 0, + G_OPTION_ARG_INT, + &x_drag_threshold, + "Set the horizontal drag threshold", "PIXELS" + }, + { + "y-threshold", 'y', + 0, + G_OPTION_ARG_INT, + &y_drag_threshold, + "Set the vertical drag threshold", "PIXELS" + }, + { + "axis", 'a', + 0, + G_OPTION_ARG_STRING, + &drag_axis, + "Set the drag axis", "AXIS" + }, + + { NULL } +}; + +int +main (int argc, char *argv[]) +{ + ClutterActor *stage, *handle; + ClutterAction *action; + GError *error; + + error = NULL; + if (clutter_init_with_args (&argc, &argv, + "test-drag", + entries, + NULL, + &error) != CLUTTER_INIT_SUCCESS) + { + g_print ("Unable to run drag-action: %s\n", error->message); + g_error_free (error); + + return EXIT_FAILURE; + } + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Drag Test"); + clutter_actor_set_size (stage, 800, 600); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + handle = clutter_actor_new (); + clutter_actor_set_background_color (handle, CLUTTER_COLOR_SkyBlue); + clutter_actor_set_size (handle, 128, 128); + clutter_actor_set_position (handle, (800 - 128) / 2, (600 - 128) / 2); + clutter_actor_set_reactive (handle, TRUE); + clutter_actor_add_child (stage, handle); + g_signal_connect (handle, "enter-event", G_CALLBACK (on_enter), NULL); + g_signal_connect (handle, "leave-event", G_CALLBACK (on_leave), NULL); + + action = clutter_drag_action_new (); + clutter_drag_action_set_drag_threshold (CLUTTER_DRAG_ACTION (action), + x_drag_threshold, + y_drag_threshold); + clutter_drag_action_set_drag_axis (CLUTTER_DRAG_ACTION (action), + get_drag_axis (drag_axis)); + + g_signal_connect (action, "drag-begin", G_CALLBACK (on_drag_begin), NULL); + g_signal_connect (action, "drag-end", G_CALLBACK (on_drag_end), NULL); + + clutter_actor_add_action (handle, action); + + clutter_actor_add_effect_with_name (handle, "disable", clutter_desaturate_effect_new (0.0)); + clutter_actor_add_effect_with_name (handle, "curl", clutter_page_turn_effect_new (0.0, 45.0, 12.0)); + + clutter_actor_show (stage); + + clutter_main (); + + return EXIT_SUCCESS; +} diff --git a/clutter/examples/drop-action.c b/clutter/examples/drop-action.c new file mode 100644 index 0000000..55615e1 --- /dev/null +++ b/clutter/examples/drop-action.c @@ -0,0 +1,263 @@ +#include +#include + +#define TARGET_SIZE 200 +#define HANDLE_SIZE 128 + +static ClutterActor *stage = NULL; +static ClutterActor *target1 = NULL; +static ClutterActor *target2 = NULL; +static ClutterActor *drag = NULL; + +static gboolean drop_successful = FALSE; + +static void add_drag_object (ClutterActor *target); + +static void +on_drag_end (ClutterDragAction *action, + ClutterActor *actor, + gfloat event_x, + gfloat event_y, + ClutterModifierType modifiers) +{ + ClutterActor *handle = clutter_drag_action_get_drag_handle (action); + + g_print ("Drag ended at: %.0f, %.0f\n", + event_x, event_y); + + clutter_actor_save_easing_state (actor); + clutter_actor_set_easing_mode (actor, CLUTTER_LINEAR); + clutter_actor_set_opacity (actor, 255); + clutter_actor_restore_easing_state (actor); + + clutter_actor_save_easing_state (handle); + + if (!drop_successful) + { + ClutterActor *parent = clutter_actor_get_parent (actor); + gfloat x_pos, y_pos; + + clutter_actor_save_easing_state (parent); + clutter_actor_set_easing_mode (parent, CLUTTER_LINEAR); + clutter_actor_set_opacity (parent, 255); + clutter_actor_restore_easing_state (parent); + + clutter_actor_get_transformed_position (actor, &x_pos, &y_pos); + + clutter_actor_set_easing_mode (handle, CLUTTER_EASE_OUT_BOUNCE); + clutter_actor_set_position (handle, x_pos, y_pos); + clutter_actor_set_opacity (handle, 0); + + } + else + { + clutter_actor_set_easing_mode (handle, CLUTTER_LINEAR); + clutter_actor_set_opacity (handle, 0); + } + + clutter_actor_restore_easing_state (handle); + + g_signal_connect (handle, "transitions-completed", + G_CALLBACK (clutter_actor_destroy), + NULL); +} + +static void +on_drag_begin (ClutterDragAction *action, + ClutterActor *actor, + gfloat event_x, + gfloat event_y, + ClutterModifierType modifiers) +{ + ClutterActor *handle; + gfloat x_pos, y_pos; + + clutter_actor_get_position (actor, &x_pos, &y_pos); + + handle = clutter_actor_new (); + clutter_actor_set_background_color (handle, CLUTTER_COLOR_DarkSkyBlue); + clutter_actor_set_size (handle, 128, 128); + clutter_actor_set_position (handle, event_x - x_pos, event_y - y_pos); + clutter_actor_add_child (stage, handle); + + clutter_drag_action_set_drag_handle (action, handle); + + clutter_actor_save_easing_state (actor); + clutter_actor_set_easing_mode (actor, CLUTTER_LINEAR); + clutter_actor_set_opacity (actor, 128); + clutter_actor_restore_easing_state (actor); + + drop_successful = FALSE; +} + +static void +add_drag_object (ClutterActor *target) +{ + ClutterActor *parent; + + if (drag == NULL) + { + ClutterAction *action; + + drag = clutter_actor_new (); + clutter_actor_set_background_color (drag, CLUTTER_COLOR_LightSkyBlue); + clutter_actor_set_size (drag, HANDLE_SIZE, HANDLE_SIZE); + clutter_actor_set_position (drag, + (TARGET_SIZE - HANDLE_SIZE) / 2.0, + (TARGET_SIZE - HANDLE_SIZE) / 2.0); + clutter_actor_set_reactive (drag, TRUE); + + action = clutter_drag_action_new (); + g_signal_connect (action, "drag-begin", G_CALLBACK (on_drag_begin), NULL); + g_signal_connect (action, "drag-end", G_CALLBACK (on_drag_end), NULL); + + clutter_actor_add_action (drag, action); + } + + parent = clutter_actor_get_parent (drag); + if (parent == target) + { + clutter_actor_save_easing_state (target); + clutter_actor_set_easing_mode (target, CLUTTER_LINEAR); + clutter_actor_set_opacity (target, 255); + clutter_actor_restore_easing_state (target); + return; + } + + g_object_ref (drag); + if (parent != NULL && parent != stage) + { + clutter_actor_remove_child (parent, drag); + + clutter_actor_save_easing_state (parent); + clutter_actor_set_easing_mode (parent, CLUTTER_LINEAR); + clutter_actor_set_opacity (parent, 64); + clutter_actor_restore_easing_state (parent); + } + + clutter_actor_add_child (target, drag); + + clutter_actor_save_easing_state (target); + clutter_actor_set_easing_mode (target, CLUTTER_LINEAR); + clutter_actor_set_opacity (target, 255); + clutter_actor_restore_easing_state (target); + + g_object_unref (drag); +} + +static void +on_target_over (ClutterDropAction *action, + ClutterActor *actor, + gpointer _data) +{ + gboolean is_over = GPOINTER_TO_UINT (_data); + guint8 final_opacity = is_over ? 128 : 64; + ClutterActor *target; + + target = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action)); + + clutter_actor_save_easing_state (target); + clutter_actor_set_easing_mode (target, CLUTTER_LINEAR); + clutter_actor_set_opacity (target, final_opacity); + clutter_actor_restore_easing_state (target); +} + +static void +on_target_drop (ClutterDropAction *action, + ClutterActor *actor, + gfloat event_x, + gfloat event_y) +{ + gfloat actor_x, actor_y; + + actor_x = actor_y = 0.0f; + + clutter_actor_transform_stage_point (actor, event_x, event_y, + &actor_x, + &actor_y); + + g_print ("Dropped at %.0f, %.0f (screen: %.0f, %.0f)\n", + actor_x, actor_y, + event_x, event_y); + + drop_successful = TRUE; + add_drag_object (actor); +} + +int +main (int argc, char *argv[]) +{ + ClutterActor *dummy; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return EXIT_FAILURE; + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Drop Action"); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + target1 = clutter_actor_new (); + clutter_actor_set_background_color (target1, CLUTTER_COLOR_LightScarletRed); + clutter_actor_set_size (target1, TARGET_SIZE, TARGET_SIZE); + clutter_actor_set_opacity (target1, 64); + clutter_actor_add_constraint (target1, clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.5)); + clutter_actor_set_x (target1, 10); + clutter_actor_set_reactive (target1, TRUE); + + clutter_actor_add_action_with_name (target1, "drop", clutter_drop_action_new ()); + g_signal_connect (clutter_actor_get_action (target1, "drop"), + "over-in", + G_CALLBACK (on_target_over), + GUINT_TO_POINTER (TRUE)); + g_signal_connect (clutter_actor_get_action (target1, "drop"), + "over-out", + G_CALLBACK (on_target_over), + GUINT_TO_POINTER (FALSE)); + g_signal_connect (clutter_actor_get_action (target1, "drop"), + "drop", + G_CALLBACK (on_target_drop), + NULL); + + dummy = clutter_actor_new (); + clutter_actor_set_background_color (dummy, CLUTTER_COLOR_DarkOrange); + clutter_actor_set_size (dummy, + 640 - (2 * 10) - (2 * (TARGET_SIZE + 10)), + TARGET_SIZE); + clutter_actor_add_constraint (dummy, clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0.5)); + clutter_actor_add_constraint (dummy, clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.5)); + clutter_actor_set_reactive (dummy, TRUE); + + target2 = clutter_actor_new (); + clutter_actor_set_background_color (target2, CLUTTER_COLOR_LightChameleon); + clutter_actor_set_size (target2, TARGET_SIZE, TARGET_SIZE); + clutter_actor_set_opacity (target2, 64); + clutter_actor_add_constraint (target2, clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.5)); + clutter_actor_set_x (target2, 640 - TARGET_SIZE - 10); + clutter_actor_set_reactive (target2, TRUE); + + clutter_actor_add_action_with_name (target2, "drop", clutter_drop_action_new ()); + g_signal_connect (clutter_actor_get_action (target2, "drop"), + "over-in", + G_CALLBACK (on_target_over), + GUINT_TO_POINTER (TRUE)); + g_signal_connect (clutter_actor_get_action (target2, "drop"), + "over-out", + G_CALLBACK (on_target_over), + GUINT_TO_POINTER (FALSE)); + g_signal_connect (clutter_actor_get_action (target2, "drop"), + "drop", + G_CALLBACK (on_target_drop), + NULL); + + clutter_actor_add_child (stage, target1); + clutter_actor_add_child (stage, dummy); + clutter_actor_add_child (stage, target2); + + add_drag_object (target1); + + clutter_actor_show (stage); + + clutter_main (); + + return EXIT_SUCCESS; +} diff --git a/clutter/examples/easing-modes.c b/clutter/examples/easing-modes.c new file mode 100644 index 0000000..379efb1 --- /dev/null +++ b/clutter/examples/easing-modes.c @@ -0,0 +1,241 @@ +#include +#include + +/* all the easing modes provided by Clutter */ +static const struct { + const gchar *name; + ClutterAnimationMode mode; +} easing_modes[] = { + { "linear", CLUTTER_LINEAR }, + { "easeInQuad", CLUTTER_EASE_IN_QUAD }, + { "easeOutQuad", CLUTTER_EASE_OUT_QUAD }, + { "easeInOutQuad", CLUTTER_EASE_IN_OUT_QUAD }, + { "easeInCubic", CLUTTER_EASE_IN_CUBIC }, + { "easeOutCubic", CLUTTER_EASE_OUT_CUBIC }, + { "easeInOutCubic", CLUTTER_EASE_IN_OUT_CUBIC }, + { "easeInQuart", CLUTTER_EASE_IN_QUART }, + { "easeOutQuart", CLUTTER_EASE_OUT_QUART }, + { "easeInOutQuart", CLUTTER_EASE_IN_OUT_QUART }, + { "easeInQuint", CLUTTER_EASE_IN_QUINT }, + { "easeOutQuint", CLUTTER_EASE_OUT_QUINT }, + { "easeInOutQuint", CLUTTER_EASE_IN_OUT_QUINT }, + { "easeInSine", CLUTTER_EASE_IN_SINE }, + { "easeOutSine", CLUTTER_EASE_OUT_SINE }, + { "easeInOutSine", CLUTTER_EASE_IN_OUT_SINE }, + { "easeInExpo", CLUTTER_EASE_IN_EXPO }, + { "easeOutExpo", CLUTTER_EASE_OUT_EXPO }, + { "easeInOutExpo", CLUTTER_EASE_IN_OUT_EXPO }, + { "easeInCirc", CLUTTER_EASE_IN_CIRC }, + { "easeOutCirc", CLUTTER_EASE_OUT_CIRC }, + { "easeInOutCirc", CLUTTER_EASE_IN_OUT_CIRC }, + { "easeInElastic", CLUTTER_EASE_IN_ELASTIC }, + { "easeOutElastic", CLUTTER_EASE_OUT_ELASTIC }, + { "easeInOutElastic", CLUTTER_EASE_IN_OUT_ELASTIC }, + { "easeInBack", CLUTTER_EASE_IN_BACK }, + { "easeOutBack", CLUTTER_EASE_OUT_BACK }, + { "easeInOutBack", CLUTTER_EASE_IN_OUT_BACK }, + { "easeInBounce", CLUTTER_EASE_IN_BOUNCE }, + { "easeOutBounce", CLUTTER_EASE_OUT_BOUNCE }, + { "easeInOutBounce", CLUTTER_EASE_IN_OUT_BOUNCE }, + { "stepStart", CLUTTER_STEP_START }, + { "stepEnd", CLUTTER_STEP_END }, + { "ease", CLUTTER_EASE }, + { "easeIn", CLUTTER_EASE_IN }, + { "easeOut", CLUTTER_EASE_OUT }, + { "easeInOut", CLUTTER_EASE_IN_OUT }, +}; + +#define HELP_TEXT "Easing mode: %s (%d of %d)\n" \ + "Left click to tween\n" \ + "Middle click to jump\n" \ + "Right click to change the easing mode" + +static const gint n_easing_modes = G_N_ELEMENTS (easing_modes); +static gint current_mode = 0; + +static gint duration = 1; + +static ClutterActor *main_stage = NULL; +static ClutterActor *easing_mode_label = NULL; + +static gboolean +on_button_press (ClutterActor *actor, + ClutterButtonEvent *event, + ClutterActor *rectangle) +{ + if (event->button == CLUTTER_BUTTON_SECONDARY) + { + gchar *text; + + /* cycle through the various easing modes */ + current_mode = (current_mode + 1 < n_easing_modes) + ? current_mode + 1 + : 0; + + /* update the text of the label */ + text = g_strdup_printf (HELP_TEXT, + easing_modes[current_mode].name, + current_mode + 1, + n_easing_modes); + + clutter_text_set_markup (CLUTTER_TEXT (easing_mode_label), text); + g_free (text); + } + else if (event->button == CLUTTER_BUTTON_MIDDLE) + { + clutter_actor_set_position (rectangle, event->x, event->y); + } + else if (event->button == CLUTTER_BUTTON_PRIMARY) + { + ClutterAnimationMode cur_mode; + + cur_mode = easing_modes[current_mode].mode; + + clutter_actor_save_easing_state (rectangle); + + /* tween the actor using the current easing mode */ + clutter_actor_set_easing_mode (rectangle, cur_mode); + clutter_actor_set_easing_duration (rectangle, duration * 1000); + + clutter_actor_set_position (rectangle, event->x, event->y); + + clutter_actor_restore_easing_state (rectangle); + } + + return CLUTTER_EVENT_STOP; +} + +static gboolean +draw_bouncer (ClutterCanvas *canvas, + cairo_t *cr, + int width, + int height) +{ + const ClutterColor *bouncer_color; + cairo_pattern_t *pattern; + float radius; + + cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); + cairo_paint (cr); + + cairo_set_operator (cr, CAIRO_OPERATOR_OVER); + + radius = MAX (width, height); + + cairo_arc (cr, radius / 2, radius / 2, radius / 2, 0.0, 2.0 * G_PI); + + bouncer_color = CLUTTER_COLOR_DarkScarletRed; + + pattern = cairo_pattern_create_radial (radius / 2, radius / 2, 0, + radius, radius, radius); + cairo_pattern_add_color_stop_rgba (pattern, + 0, + bouncer_color->red / 255.0, + bouncer_color->green / 255.0, + bouncer_color->blue / 255.0, + bouncer_color->alpha / 255.0); + cairo_pattern_add_color_stop_rgba (pattern, + 0.85, + bouncer_color->red / 255.0, + bouncer_color->green / 255.0, + bouncer_color->blue / 255.0, + 0.25); + + cairo_set_source (cr, pattern); + cairo_fill_preserve (cr); + + cairo_pattern_destroy (pattern); + + return TRUE; +} + +static ClutterActor * +make_bouncer (gfloat width, + gfloat height) +{ + ClutterActor *retval; + ClutterContent *canvas; + + retval = clutter_actor_new (); + + canvas = clutter_canvas_new (); + g_signal_connect (canvas, "draw", G_CALLBACK (draw_bouncer), NULL); + clutter_canvas_set_size (CLUTTER_CANVAS (canvas), width, height); + + clutter_actor_set_name (retval, "bouncer"); + clutter_actor_set_size (retval, width, height); + clutter_actor_set_pivot_point (retval, 0.5f, 0.5f); + clutter_actor_set_translation (retval, width / -2.f, height / -2.f, 0.f); + clutter_actor_set_reactive (retval, TRUE); + clutter_actor_set_content (retval, canvas); + + g_object_unref (canvas); + + return retval; +} + +static GOptionEntry test_easing_entries[] = { + { + "duration", 'd', + 0, + G_OPTION_ARG_INT, &duration, + "Duration of the animation", + "SECONDS" + }, + + { NULL } +}; + +int +main (int argc, char *argv[]) +{ + ClutterActor *stage, *rect, *label; + gchar *text; + gfloat stage_width, stage_height; + GError *error = NULL; + + if (clutter_init_with_args (&argc, &argv, + NULL, + test_easing_entries, + NULL, + &error) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Easing Modes"); + clutter_actor_set_background_color (stage, CLUTTER_COLOR_LightSkyBlue); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + main_stage = stage; + + clutter_actor_get_size (stage, &stage_width, &stage_height); + + /* create the actor that we want to tween */ + rect = make_bouncer (50, 50); + clutter_actor_add_child (stage, rect); + clutter_actor_set_position (rect, stage_width / 2, stage_height / 2); + + text = g_strdup_printf (HELP_TEXT, + easing_modes[current_mode].name, + current_mode + 1, + n_easing_modes); + + label = clutter_text_new (); + clutter_actor_add_child (stage, label); + clutter_text_set_markup (CLUTTER_TEXT (label), text); + clutter_text_set_line_alignment (CLUTTER_TEXT (label), PANGO_ALIGN_RIGHT); + clutter_actor_add_constraint (label, clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0.95)); + clutter_actor_add_constraint (label, clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.95)); + easing_mode_label = label; + + g_free (text); + + g_signal_connect (stage, + "button-press-event", G_CALLBACK (on_button_press), + rect); + + clutter_actor_show (stage); + + clutter_main (); + + return EXIT_SUCCESS; +} diff --git a/clutter/examples/flow-layout.c b/clutter/examples/flow-layout.c new file mode 100644 index 0000000..f688884 --- /dev/null +++ b/clutter/examples/flow-layout.c @@ -0,0 +1,164 @@ +#include +#include +#include +#include + +#define N_RECTS 20 + +static gboolean is_homogeneous = FALSE; +static gboolean vertical = FALSE; +static gboolean random_size = FALSE; +static gboolean fixed_size = FALSE; +static gboolean snap_to_grid = TRUE; + +static gint n_rects = N_RECTS; +static gint x_spacing = 0; +static gint y_spacing = 0; + +static GOptionEntry entries[] = { + { + "random-size", 'r', + 0, + G_OPTION_ARG_NONE, + &random_size, + "Randomly size the rectangles", NULL + }, + { + "num-rects", 'n', + 0, + G_OPTION_ARG_INT, + &n_rects, + "Number of rectangles", "RECTS" + }, + { + "vertical", 'v', + 0, + G_OPTION_ARG_NONE, + &vertical, + "Set vertical orientation", NULL + }, + { + "homogeneous", 'h', + 0, + G_OPTION_ARG_NONE, + &is_homogeneous, + "Whether the layout should be homogeneous", NULL + }, + { + "x-spacing", 0, + 0, + G_OPTION_ARG_INT, + &x_spacing, + "Horizontal spacing between elements", "PX" + }, + { + "y-spacing", 0, + 0, + G_OPTION_ARG_INT, + &y_spacing, + "Vertical spacing between elements", "PX" + }, + { + "fixed-size", 'f', + 0, + G_OPTION_ARG_NONE, + &fixed_size, + "Fix the layout size", NULL + }, + { + "no-snap-to-grid", 's', + G_OPTION_FLAG_REVERSE, + G_OPTION_ARG_NONE, + &snap_to_grid, + "Don't snap elements to grid", NULL + }, + { NULL } +}; + +int +main (int argc, char *argv[]) +{ + ClutterActor *stage, *box; + ClutterLayoutManager *layout; + GError *error; + gint i; + + error = NULL; + if (clutter_init_with_args (&argc, &argv, + NULL, + entries, + NULL, + &error) != CLUTTER_INIT_SUCCESS) + { + g_print ("Unable to run flow-layout: %s", error->message); + g_error_free (error); + + return EXIT_FAILURE; + } + + stage = clutter_stage_new (); + clutter_actor_set_background_color (stage, CLUTTER_COLOR_LightSkyBlue); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Flow Layout"); + clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + layout = clutter_flow_layout_new (vertical ? CLUTTER_FLOW_VERTICAL + : CLUTTER_FLOW_HORIZONTAL); + clutter_flow_layout_set_homogeneous (CLUTTER_FLOW_LAYOUT (layout), + is_homogeneous); + clutter_flow_layout_set_column_spacing (CLUTTER_FLOW_LAYOUT (layout), + x_spacing); + clutter_flow_layout_set_row_spacing (CLUTTER_FLOW_LAYOUT (layout), + y_spacing); + clutter_flow_layout_set_snap_to_grid (CLUTTER_FLOW_LAYOUT (layout), + snap_to_grid); + + box = clutter_actor_new (); + clutter_actor_set_layout_manager (box, layout); + clutter_actor_set_background_color (box, CLUTTER_COLOR_Aluminium2); + clutter_actor_add_child (stage, box); + + if (!fixed_size) + clutter_actor_add_constraint (box, clutter_bind_constraint_new (stage, CLUTTER_BIND_SIZE, 0.0)); + + clutter_actor_set_position (box, 0, 0); + clutter_actor_set_name (box, "box"); + + for (i = 0; i < n_rects; i++) + { + ClutterColor color = CLUTTER_COLOR_INIT (255, 255, 255, 255); + gfloat width, height; + ClutterActor *rect; + gchar *name; + + name = g_strdup_printf ("rect%02d", i); + + clutter_color_from_hls (&color, + 360.0 / n_rects * i, + 0.5, + 0.8); + rect = clutter_actor_new (); + clutter_actor_set_background_color (rect, &color); + + if (random_size) + { + width = g_random_int_range (50, 100); + height = g_random_int_range (50, 100); + } + else + width = height = 50.f; + + clutter_actor_set_size (rect, width, height); + clutter_actor_set_name (rect, name); + + clutter_actor_add_child (box, rect); + + g_free (name); + } + + clutter_actor_show (stage); + + clutter_main (); + + return EXIT_SUCCESS; +} diff --git a/clutter/examples/grid-layout.c b/clutter/examples/grid-layout.c new file mode 100644 index 0000000..c47d881 --- /dev/null +++ b/clutter/examples/grid-layout.c @@ -0,0 +1,378 @@ +/* + * Copyright 2012 Bastian Winkler + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * Boston, MA 02111-1307, USA. + * + */ +#include +#include + +#define INSTRUCTIONS \ + "Press r\t\342\236\236\tSwitch row homogeneous\n" \ + "Press c\t\342\236\236\tSwitch column homogeneous\n" \ + "Press s\t\342\236\236\tIncrement spacing (up to 12px)\n" \ + "Press q\t\342\236\236\tQuit\n\n" \ + "Left/right click\t\t\342\236\236\tChange actor align\n" \ + "Shift left/right click\t\342\236\236\tChange actor expand" + +static gboolean random_size = FALSE; +static gboolean random_align = FALSE; +static gboolean default_expand = TRUE; +static gboolean use_box = FALSE; +static gboolean is_vertical = FALSE; + +static GOptionEntry entries[] = { + { + "random-size", 'r', + 0, + G_OPTION_ARG_NONE, + &random_size, + "Randomly size the rectangles", NULL + }, + { + "random-align", 'f', + 0, + G_OPTION_ARG_NONE, + &random_align, + "Randomly set the align values", NULL + }, + { + "no-expand", 'e', + G_OPTION_FLAG_REVERSE, + G_OPTION_ARG_NONE, + &default_expand, + "Don't expand all actors by default", NULL, + }, + { + "box", 'b', + 0, + G_OPTION_ARG_NONE, + &use_box, + "Use the layout in a ClutterBoxLayout style", NULL + }, + { + "vertical", 'v', + 0, + G_OPTION_ARG_NONE, + &is_vertical, + "Use a vertical orientation when used with --box", NULL + }, + { NULL } +}; + +static gboolean +button_release_cb (ClutterActor *actor, + ClutterEvent *event, + gpointer data) +{ + ClutterActorAlign x_align, y_align; + gboolean x_expand, y_expand; + + g_object_get (actor, + "x-align", &x_align, + "y-align", &y_align, + "x-expand", &x_expand, + "y-expand", &y_expand, + NULL); + + switch (clutter_event_get_button (event)) + { + case CLUTTER_BUTTON_PRIMARY: + if (clutter_event_has_shift_modifier (event)) + x_expand = !x_expand; + else + { + if (x_align < 3) + x_align += 1; + else + x_align = 0; + } + break; + + case CLUTTER_BUTTON_SECONDARY: + if (clutter_event_has_shift_modifier (event)) + y_expand = !y_expand; + else + { + if (y_align < 3) + y_align += 1; + else + y_align = 0; + } + break; + + default: + return FALSE; + } + + g_object_set (actor, + "x-align", x_align, + "y-align", y_align, + "x-expand", x_expand, + "y-expand", y_expand, + NULL); + return TRUE; +} + +static const gchar * +get_align_name (ClutterActorAlign align) +{ + switch (align) + { + case CLUTTER_ACTOR_ALIGN_FILL: + return "fill"; + + case CLUTTER_ACTOR_ALIGN_START: + return "start"; + + case CLUTTER_ACTOR_ALIGN_CENTER: + return "center"; + + case CLUTTER_ACTOR_ALIGN_END: + return "end"; + + default: + g_assert_not_reached (); + } +} +static void +changed_cb (ClutterActor *actor, + GParamSpec *pspec, + ClutterActor *text) +{ + ClutterActorAlign x_align, y_align; + ClutterActor *box; + ClutterLayoutManager *layout; + ClutterLayoutMeta *meta; + gboolean x_expand, y_expand; + gchar *label; + gint left, top, width, height; + + box = clutter_actor_get_parent (actor); + layout = clutter_actor_get_layout_manager (box); + meta = clutter_layout_manager_get_child_meta (layout, + CLUTTER_CONTAINER (box), + actor); + + g_object_get (actor, + "x-align", &x_align, + "y-align", &y_align, + "x-expand", &x_expand, + "y-expand", &y_expand, + NULL); + + g_object_get (meta, + "left-attach", &left, + "top-attach", &top, + "width", &width, + "height", &height, + NULL); + + label = g_strdup_printf ("attach: %d,%d\n" + "span: %d,%d\n" + "expand: %d,%d\n" + "align: %s,%s", + left, top, width, height, + x_expand, y_expand, + get_align_name (x_align), + get_align_name (y_align)); + clutter_text_set_text (CLUTTER_TEXT (text), label); + g_free (label); +} + +static void +add_actor (ClutterActor *box, + gint left, + gint top, + gint width, + gint height) +{ + ClutterActor *rect, *text; + ClutterColor color; + ClutterLayoutManager *layout; + + clutter_color_from_hls (&color, + g_random_double_range (0.0, 360.0), + 0.5, + 0.5); + color.alpha = 255; + + layout = clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_CENTER, + CLUTTER_BIN_ALIGNMENT_CENTER); + rect = clutter_actor_new (); + clutter_actor_set_layout_manager (rect, layout); + clutter_actor_set_background_color (rect, &color); + clutter_actor_set_reactive (rect, TRUE); + + if (random_size) + clutter_actor_set_size (rect, + g_random_int_range (40, 80), + g_random_int_range (40, 80)); + else + clutter_actor_set_size (rect, 60, 60); + + clutter_actor_set_x_expand (rect, default_expand); + clutter_actor_set_y_expand (rect, default_expand); + + if (!default_expand) + { + clutter_actor_set_x_align (rect, CLUTTER_ACTOR_ALIGN_CENTER); + clutter_actor_set_y_align (rect, CLUTTER_ACTOR_ALIGN_CENTER); + } + + if (random_align) + { + clutter_actor_set_x_align (rect, g_random_int_range (0, 3)); + clutter_actor_set_y_align (rect, g_random_int_range (0, 3)); + } + + text = clutter_text_new_with_text ("Sans 8px", NULL); + clutter_text_set_line_alignment (CLUTTER_TEXT (text), + PANGO_ALIGN_CENTER); + clutter_actor_add_child (rect, text); + + g_signal_connect (rect, "button-release-event", + G_CALLBACK (button_release_cb), NULL); + g_signal_connect (rect, "notify::x-expand", + G_CALLBACK (changed_cb), text); + g_signal_connect (rect, "notify::y-expand", + G_CALLBACK (changed_cb), text); + g_signal_connect (rect, "notify::x-align", + G_CALLBACK (changed_cb), text); + g_signal_connect (rect, "notify::y-align", + G_CALLBACK (changed_cb), text); + + layout = clutter_actor_get_layout_manager (box); + if (use_box) + clutter_actor_add_child (box, rect); + else + clutter_grid_layout_attach (CLUTTER_GRID_LAYOUT (layout), rect, + left, top, width, height); + changed_cb (rect, NULL, text); +} + +static gboolean +key_release_cb (ClutterActor *stage, + ClutterEvent *event, + ClutterActor *box) +{ + ClutterGridLayout *layout; + gboolean toggle; + guint spacing; + + layout = CLUTTER_GRID_LAYOUT (clutter_actor_get_layout_manager (box)); + + switch (clutter_event_get_key_symbol (event)) + { + case CLUTTER_KEY_c: + toggle = clutter_grid_layout_get_column_homogeneous (layout); + clutter_grid_layout_set_column_homogeneous (layout, !toggle); + break; + + case CLUTTER_KEY_r: + toggle = clutter_grid_layout_get_row_homogeneous (layout); + clutter_grid_layout_set_row_homogeneous (layout, !toggle); + break; + + case CLUTTER_KEY_s: + spacing = clutter_grid_layout_get_column_spacing (layout); + if (spacing < 12) + spacing += 1; + else + spacing = 0; + clutter_grid_layout_set_column_spacing (layout, spacing); + clutter_grid_layout_set_row_spacing (layout, spacing); + break; + + case CLUTTER_KEY_q: + clutter_main_quit (); + break; + + default: + return FALSE; + } + + return TRUE; +} +int +main (int argc, char *argv[]) +{ + ClutterActor *stage, *box, *instructions; + ClutterLayoutManager *stage_layout, *grid_layout; + GError *error = NULL; + + if (clutter_init_with_args (&argc, &argv, + NULL, + entries, + NULL, + &error) != CLUTTER_INIT_SUCCESS) + { + g_print ("Unable to run grid-layout: %s", error->message); + g_error_free (error); + + return EXIT_FAILURE; + } + + stage = clutter_stage_new (); + clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); + stage_layout = clutter_box_layout_new (); + clutter_box_layout_set_orientation (CLUTTER_BOX_LAYOUT (stage_layout), + CLUTTER_ORIENTATION_VERTICAL); + clutter_actor_set_layout_manager (stage, stage_layout); + + grid_layout = clutter_grid_layout_new (); + if (is_vertical) + clutter_grid_layout_set_orientation (CLUTTER_GRID_LAYOUT (grid_layout), + CLUTTER_ORIENTATION_VERTICAL); + box = clutter_actor_new (); + clutter_actor_set_background_color (box, CLUTTER_COLOR_LightGray); + clutter_actor_set_x_expand (box, TRUE); + clutter_actor_set_y_expand (box, TRUE); + clutter_actor_set_layout_manager (box, grid_layout); + clutter_box_layout_pack (CLUTTER_BOX_LAYOUT (stage_layout), box, + TRUE, TRUE, TRUE, + CLUTTER_BOX_ALIGNMENT_CENTER, + CLUTTER_BOX_ALIGNMENT_CENTER); + + add_actor (box, 0, 0, 1, 1); + add_actor (box, 1, 0, 1, 1); + add_actor (box, 2, 0, 1, 1); + add_actor (box, 0, 1, 1, 1); + add_actor (box, 1, 1, 2, 1); + add_actor (box, 0, 2, 3, 1); + add_actor (box, 0, 3, 2, 2); + add_actor (box, 2, 3, 1, 1); + add_actor (box, 2, 4, 1, 1); + + instructions = clutter_text_new_with_text ("Sans 12px", INSTRUCTIONS); + clutter_actor_set_margin_top (instructions, 4); + clutter_actor_set_margin_left (instructions, 4); + clutter_actor_set_margin_bottom (instructions, 4); + clutter_box_layout_pack (CLUTTER_BOX_LAYOUT (stage_layout), instructions, + FALSE, TRUE, FALSE, + CLUTTER_BOX_ALIGNMENT_START, + CLUTTER_BOX_ALIGNMENT_CENTER); + + g_signal_connect (stage, "destroy", + G_CALLBACK (clutter_main_quit), NULL); + g_signal_connect (stage, "key-release-event", + G_CALLBACK (key_release_cb), box); + + clutter_actor_show (stage); + + clutter_main (); + + return 0; +} diff --git a/clutter/examples/image-content.c b/clutter/examples/image-content.c new file mode 100644 index 0000000..c9c01c6 --- /dev/null +++ b/clutter/examples/image-content.c @@ -0,0 +1,110 @@ +#include +#include +#include + +static const struct { + ClutterContentGravity gravity; + const char *name; +} gravities[] = { + { CLUTTER_CONTENT_GRAVITY_TOP_LEFT, "Top Left" }, + { CLUTTER_CONTENT_GRAVITY_TOP, "Top" }, + { CLUTTER_CONTENT_GRAVITY_TOP_RIGHT, "Top Right" }, + + { CLUTTER_CONTENT_GRAVITY_LEFT, "Left" }, + { CLUTTER_CONTENT_GRAVITY_CENTER, "Center" }, + { CLUTTER_CONTENT_GRAVITY_RIGHT, "Right" }, + + { CLUTTER_CONTENT_GRAVITY_BOTTOM_LEFT, "Bottom Left" }, + { CLUTTER_CONTENT_GRAVITY_BOTTOM, "Bottom" }, + { CLUTTER_CONTENT_GRAVITY_BOTTOM_RIGHT, "Bottom Right" }, + + { CLUTTER_CONTENT_GRAVITY_RESIZE_FILL, "Resize Fill" }, + { CLUTTER_CONTENT_GRAVITY_RESIZE_ASPECT, "Resize Aspect" }, +}; + +static int n_gravities = G_N_ELEMENTS (gravities); +static int cur_gravity = 0; + +static void +on_tap (ClutterTapAction *action, + ClutterActor *actor, + ClutterText *label) +{ + gchar *str; + + clutter_actor_save_easing_state (actor); + clutter_actor_set_content_gravity (actor, gravities[cur_gravity].gravity); + clutter_actor_restore_easing_state (actor); + + str = g_strconcat ("Content gravity: ", gravities[cur_gravity].name, NULL); + clutter_text_set_text (label, str); + g_free (str); + + cur_gravity += 1; + + if (cur_gravity >= n_gravities) + cur_gravity = 0; +} + +int +main (int argc, char *argv[]) +{ + ClutterActor *stage, *text; + ClutterContent *image; + ClutterAction *action; + GdkPixbuf *pixbuf; + gchar *str; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return EXIT_FAILURE; + + stage = clutter_stage_new (); + clutter_actor_set_name (stage, "Stage"); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Content Box"); + clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + clutter_actor_set_margin_top (stage, 12); + clutter_actor_set_margin_right (stage, 12); + clutter_actor_set_margin_bottom (stage, 12); + clutter_actor_set_margin_left (stage, 12); + clutter_actor_show (stage); + + pixbuf = gdk_pixbuf_new_from_file ("redhand.png", NULL); + image = clutter_image_new (); + clutter_image_set_data (CLUTTER_IMAGE (image), + gdk_pixbuf_get_pixels (pixbuf), + gdk_pixbuf_get_has_alpha (pixbuf) + ? COGL_PIXEL_FORMAT_RGBA_8888 + : COGL_PIXEL_FORMAT_RGB_888, + gdk_pixbuf_get_width (pixbuf), + gdk_pixbuf_get_height (pixbuf), + gdk_pixbuf_get_rowstride (pixbuf), + NULL); + g_object_unref (pixbuf); + + clutter_actor_set_content_scaling_filters (stage, + CLUTTER_SCALING_FILTER_TRILINEAR, + CLUTTER_SCALING_FILTER_LINEAR); + clutter_actor_set_content_gravity (stage, gravities[n_gravities - 1].gravity); + clutter_actor_set_content (stage, image); + g_object_unref (image); + + str = g_strconcat ("Content gravity: ", + gravities[n_gravities - 1].name, + NULL); + + text = clutter_text_new (); + clutter_text_set_text (CLUTTER_TEXT (text), str); + clutter_actor_add_constraint (text, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5)); + clutter_actor_add_child (stage, text); + + g_free (str); + + action = clutter_tap_action_new (); + g_signal_connect (action, "tap", G_CALLBACK (on_tap), text); + clutter_actor_add_action (stage, action); + + clutter_main (); + + return EXIT_SUCCESS; +} diff --git a/clutter/examples/layout-manager.c b/clutter/examples/layout-manager.c new file mode 100644 index 0000000..c5518f2 --- /dev/null +++ b/clutter/examples/layout-manager.c @@ -0,0 +1,461 @@ +#include +#include +#include + +typedef struct _MultiLayout MultiLayout; +typedef struct _MultiLayoutClass MultiLayoutClass; + +typedef enum { + MULTI_LAYOUT_GRID, + MULTI_LAYOUT_CIRCLE +} MultiLayoutState; + +struct _MultiLayout +{ + ClutterLayoutManager parent_instance; + + /* the state of the layout */ + MultiLayoutState state; + + /* spacing between children */ + float spacing; + + /* cell size */ + float cell_width; + float cell_height; +}; + +struct _MultiLayoutClass +{ + ClutterLayoutManagerClass parent_class; +}; + +GType multi_layout_get_type (void); + +ClutterLayoutManager * multi_layout_new (void); +void multi_layout_set_state (MultiLayout *layout, + MultiLayoutState state); +MultiLayoutState multi_layout_get_state (MultiLayout *layout); +void multi_layout_set_spacing (MultiLayout *layout, + float spacing); + +G_DEFINE_TYPE (MultiLayout, multi_layout, CLUTTER_TYPE_LAYOUT_MANAGER) + +static void +multi_layout_get_preferred_width (ClutterLayoutManager *manager, + ClutterContainer *container, + float for_height, + float *min_width_p, + float *nat_width_p) +{ + MultiLayout *self = (MultiLayout *) manager; + float minimum, natural; + float max_natural_width; + ClutterActorIter iter; + ClutterActor *child; + int n_children; + + minimum = natural = 0.f; + max_natural_width = 0.f; + n_children = 0; + + clutter_actor_iter_init (&iter, CLUTTER_ACTOR (container)); + while (clutter_actor_iter_next (&iter, &child)) + { + float child_minimum, child_natural; + + if (!clutter_actor_is_visible (child)) + continue; + + clutter_actor_get_preferred_width (child, -1.f, + &child_minimum, + &child_natural); + + max_natural_width = MAX (max_natural_width, child_natural); + + if (self->state == MULTI_LAYOUT_GRID) + { + minimum += child_minimum; + natural += child_natural; + } + else if (self->state == MULTI_LAYOUT_CIRCLE) + { + minimum = MAX (minimum, child_minimum); + natural = MAX (natural, child_natural); + } + + n_children += 1; + } + + self->cell_width = max_natural_width; + + minimum += (self->spacing * (n_children - 1)); + natural += (self->spacing * (n_children - 1)); + + if (min_width_p != NULL) + *min_width_p = minimum; + + if (nat_width_p != NULL) + *nat_width_p = natural; +} + +static void +multi_layout_get_preferred_height (ClutterLayoutManager *manager, + ClutterContainer *container, + float for_width, + float *min_height_p, + float *nat_height_p) +{ + MultiLayout *self = (MultiLayout *) manager; + float minimum, natural; + ClutterActorIter iter; + ClutterActor *child; + int n_children; + + minimum = natural = self->spacing * 2.f; + n_children = 0; + + clutter_actor_iter_init (&iter, CLUTTER_ACTOR (container)); + while (clutter_actor_iter_next (&iter, &child)) + { + float child_minimum, child_natural; + + if (!clutter_actor_is_visible (child)) + continue; + + clutter_actor_get_preferred_height (child, -1.f, + &child_minimum, + &child_natural); + + minimum = MAX (minimum, child_minimum); + natural = MAX (natural, child_natural); + + n_children += 1; + } + + self->cell_height = natural; + + minimum += (self->spacing * (n_children - 1)); + natural += (self->spacing * (n_children - 1)); + + if (min_height_p != NULL) + *min_height_p = minimum; + + if (nat_height_p != NULL) + *nat_height_p = natural; +} + +static int +get_items_per_row (MultiLayout *self, + float for_width) +{ + int n_columns; + + if (for_width < 0) + return 1; + + if (self->cell_width <= 0) + return 1; + + n_columns = (int) ((for_width + self->spacing) / (self->cell_width + self->spacing)); + + return MAX (n_columns, 1); +} + +static int +get_visible_children (ClutterActor *actor) +{ + ClutterActorIter iter; + ClutterActor *child; + int n_visible_children = 0; + + clutter_actor_iter_init (&iter, actor); + while (clutter_actor_iter_next (&iter, &child)) + { + if (clutter_actor_is_visible (child)) + n_visible_children += 1; + } + + return n_visible_children; +} + +static void +multi_layout_allocate (ClutterLayoutManager *manager, + ClutterContainer *container, + const ClutterActorBox *allocation, + ClutterAllocationFlags flags) +{ + MultiLayout *self = (MultiLayout *) manager; + float avail_width, avail_height; + float x_offset, y_offset; + ClutterActorIter iter; + ClutterActor *child; + float item_x = 0.f, item_y = 0.f; + int n_items, n_items_per_row = 0, item_index; + ClutterPoint center = CLUTTER_POINT_INIT_ZERO; + double radius = 0, theta = 0; + + n_items = get_visible_children (CLUTTER_ACTOR (container)); + if (n_items == 0) + return; + + clutter_actor_box_get_origin (allocation, &x_offset, &y_offset); + clutter_actor_box_get_size (allocation, &avail_width, &avail_height); + + /* ensure we have an updated value of cell_width and cell_height */ + multi_layout_get_preferred_width (manager, container, avail_width, NULL, NULL); + multi_layout_get_preferred_height (manager, container, avail_height, NULL, NULL); + + item_index = 0; + + if (self->state == MULTI_LAYOUT_GRID) + { + n_items_per_row = get_items_per_row (self, avail_width); + item_x = x_offset; + item_y = y_offset; + } + else if (self->state == MULTI_LAYOUT_CIRCLE) + { + center.x = allocation->x2 / 2.f; + center.y = allocation->y2 / 2.f; + radius = MIN ((avail_width - self->cell_width) / 2.0, + (avail_height - self->cell_height) / 2.0); + } + + clutter_actor_iter_init (&iter, CLUTTER_ACTOR (container)); + while (clutter_actor_iter_next (&iter, &child)) + { + ClutterActorBox child_allocation = CLUTTER_ACTOR_BOX_INIT_ZERO; + + if (!clutter_actor_is_visible (child)) + continue; + + if (self->state == MULTI_LAYOUT_GRID) + { + if (item_index == n_items_per_row) + { + item_index = 0; + item_x = x_offset; + item_y += self->cell_height + self->spacing; + } + + child_allocation.x1 = item_x; + child_allocation.y1 = item_y; + child_allocation.x2 = child_allocation.x1 + self->cell_width; + child_allocation.y2 = child_allocation.y1 + self->cell_height; + + item_x += self->cell_width + self->spacing; + } + else if (self->state == MULTI_LAYOUT_CIRCLE) + { + theta = 2.0 * G_PI / n_items * item_index; + child_allocation.x1 = center.x + radius * sinf (theta) - (self->cell_width / 2.f); + child_allocation.y1 = center.y + radius * -cosf (theta) - (self->cell_height / 2.f); + child_allocation.x2 = child_allocation.x1 + self->cell_width; + child_allocation.y2 = child_allocation.y1 + self->cell_height; + } + + clutter_actor_allocate (child, &child_allocation, flags); + + item_index += 1; + } +} + +static void +multi_layout_class_init (MultiLayoutClass *klass) +{ + ClutterLayoutManagerClass *manager_class = CLUTTER_LAYOUT_MANAGER_CLASS (klass); + + manager_class->get_preferred_width = multi_layout_get_preferred_width; + manager_class->get_preferred_height = multi_layout_get_preferred_height; + manager_class->allocate = multi_layout_allocate; +} + +static void +multi_layout_init (MultiLayout *self) +{ + self->state = MULTI_LAYOUT_GRID; + + self->cell_width = -1.f; + self->cell_height = -1.f; + + self->spacing = 0.f; +} + +ClutterLayoutManager * +multi_layout_new (void) +{ + return g_object_new (multi_layout_get_type (), NULL); +} + +void +multi_layout_set_state (MultiLayout *self, + MultiLayoutState state) +{ + if (self->state == state) + return; + + self->state = state; + + clutter_layout_manager_layout_changed (CLUTTER_LAYOUT_MANAGER (self)); +} + +MultiLayoutState +multi_layout_get_state (MultiLayout *self) +{ + return self->state; +} + +void +multi_layout_set_spacing (MultiLayout *self, + float spacing) +{ + self->spacing = spacing; + + clutter_layout_manager_layout_changed (CLUTTER_LAYOUT_MANAGER (self)); +} + +#define N_RECTS 16 +#define RECT_SIZE 64.0 +#define N_ROWS 4 +#define PADDING 12.0 +#define BOX_SIZE (RECT_SIZE * (N_RECTS / N_ROWS) + PADDING * (N_RECTS / N_ROWS - 1)) + +static gboolean +on_enter (ClutterActor *rect, + ClutterEvent *event) +{ + clutter_actor_set_scale (rect, 1.2, 1.2); + + return CLUTTER_EVENT_STOP; +} + +static gboolean +on_leave (ClutterActor *rect, + ClutterEvent *event) +{ + clutter_actor_set_scale (rect, 1.0, 1.0); + + return CLUTTER_EVENT_STOP; +} + +static gboolean +on_key_press (ClutterActor *stage, + ClutterEvent *event, + ClutterActor *box) +{ + guint keysym = clutter_event_get_key_symbol (event); + MultiLayout *layout = (MultiLayout *) clutter_actor_get_layout_manager (box); + + + switch (keysym) + { + case CLUTTER_KEY_q: + clutter_main_quit (); + break; + + case CLUTTER_KEY_t: + { + MultiLayoutState state = multi_layout_get_state (layout); + + if (state == MULTI_LAYOUT_GRID) + multi_layout_set_state (layout, MULTI_LAYOUT_CIRCLE); + + if (state == MULTI_LAYOUT_CIRCLE) + multi_layout_set_state (layout, MULTI_LAYOUT_GRID); + } + break; + + default: + break; + } + + return CLUTTER_EVENT_STOP; +} + +int +main (int argc, char *argv[]) +{ + ClutterActor *stage, *box, *label; + ClutterLayoutManager *manager; + ClutterMargin margin; + ClutterTransition *transition; + int i; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return EXIT_FAILURE; + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Multi-layout"); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + clutter_actor_show (stage); + + /* the layout manager for the main container */ + manager = multi_layout_new (); + multi_layout_set_spacing ((MultiLayout *) manager, PADDING); + + margin.top = margin.bottom = margin.left = margin.right = PADDING; + + /* our main container, centered on the stage */ + box = clutter_actor_new (); + clutter_actor_set_margin (box, &margin); + clutter_actor_set_layout_manager (box, manager); + clutter_actor_set_size (box, BOX_SIZE, BOX_SIZE); + clutter_actor_add_constraint (box, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5)); + clutter_actor_add_child (stage, box); + + for (i = 0; i < N_RECTS; i++) + { + ClutterActor *rect = clutter_actor_new (); + ClutterColor color; + + clutter_color_from_hls (&color, + 360.0 / N_RECTS * i, + 0.5, + 0.8); + + color.alpha = 128 + 128 / N_RECTS * i; + + /* elements on the layout */ + clutter_actor_set_size (rect, RECT_SIZE, RECT_SIZE); + clutter_actor_set_pivot_point (rect, .5f, .5f); + clutter_actor_set_background_color (rect, &color); + clutter_actor_set_opacity (rect, 0); + clutter_actor_set_reactive (rect, TRUE); + + /* explicit transition that fades in the element; the delay on + * the transition staggers the fade depending on the index + */ + transition = clutter_property_transition_new ("opacity"); + clutter_timeline_set_duration (CLUTTER_TIMELINE (transition), 250); + clutter_timeline_set_delay (CLUTTER_TIMELINE (transition), i * 50); + clutter_transition_set_from (transition, G_TYPE_UINT, 0); + clutter_transition_set_to (transition, G_TYPE_UINT, 255); + clutter_actor_add_transition (rect, "fadeIn", transition); + g_object_unref (transition); + + /* we want all state transitions to be animated */ + clutter_actor_set_easing_duration (rect, 250); + clutter_actor_set_easing_mode (rect, CLUTTER_EASE_OUT_CUBIC); + + clutter_actor_add_child (box, rect); + + /* simple hover effect */ + g_signal_connect (rect, "enter-event", G_CALLBACK (on_enter), NULL); + g_signal_connect (rect, "leave-event", G_CALLBACK (on_leave), NULL); + } + + label = clutter_text_new (); + clutter_text_set_text (CLUTTER_TEXT (label), + "Press t\t\342\236\236\tToggle layout\n" + "Press q\t\342\236\236\tQuit"); + clutter_actor_add_constraint (label, clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0.5)); + clutter_actor_add_constraint (label, clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.95)); + clutter_actor_add_child (stage, label); + + g_signal_connect (stage, "key-press-event", G_CALLBACK (on_key_press), box); + + clutter_main (); + + return EXIT_SUCCESS; +} diff --git a/clutter/examples/pan-action.c b/clutter/examples/pan-action.c new file mode 100644 index 0000000..4e3f73f --- /dev/null +++ b/clutter/examples/pan-action.c @@ -0,0 +1,194 @@ +#include +#include +#include +#ifdef CLUTTER_WINDOWING_X11 +#include +#endif + +static ClutterActor * +create_content_actor (void) +{ + ClutterActor *content; + ClutterContent *image; + GdkPixbuf *pixbuf; + + content = clutter_actor_new (); + clutter_actor_set_size (content, 720, 720); + + pixbuf = gdk_pixbuf_new_from_file ("redhand.png", NULL); + image = clutter_image_new (); + clutter_image_set_data (CLUTTER_IMAGE (image), + gdk_pixbuf_get_pixels (pixbuf), + gdk_pixbuf_get_has_alpha (pixbuf) + ? COGL_PIXEL_FORMAT_RGBA_8888 + : COGL_PIXEL_FORMAT_RGB_888, + gdk_pixbuf_get_width (pixbuf), + gdk_pixbuf_get_height (pixbuf), + gdk_pixbuf_get_rowstride (pixbuf), + NULL); + g_object_unref (pixbuf); + + clutter_actor_set_content_scaling_filters (content, + CLUTTER_SCALING_FILTER_TRILINEAR, + CLUTTER_SCALING_FILTER_LINEAR); + clutter_actor_set_content_gravity (content, CLUTTER_CONTENT_GRAVITY_RESIZE_ASPECT); + clutter_actor_set_content (content, image); + g_object_unref (image); + + return content; +} + +static gboolean +on_pan (ClutterPanAction *action, + ClutterActor *scroll, + gboolean is_interpolated, + gpointer *user_data) +{ + gfloat delta_x, delta_y; + const ClutterEvent *event = NULL; + + if (is_interpolated) + clutter_pan_action_get_interpolated_delta (action, &delta_x, &delta_y); + else + { + clutter_gesture_action_get_motion_delta (CLUTTER_GESTURE_ACTION (action), 0, &delta_x, &delta_y); + event = clutter_gesture_action_get_last_event (CLUTTER_GESTURE_ACTION (action), 0); + } + + g_print ("[%s] panning dx:%.2f dy:%.2f\n", + event == NULL ? "INTERPOLATED" : + event->type == CLUTTER_MOTION ? "MOTION" : + event->type == CLUTTER_TOUCH_UPDATE ? "TOUCH UPDATE" : + "?", + delta_x, delta_y); + + return TRUE; +} + +static ClutterActor * +create_scroll_actor (ClutterActor *stage) +{ + ClutterActor *scroll; + ClutterAction *pan_action; + + /* our scrollable viewport */ + scroll = clutter_actor_new (); + clutter_actor_set_name (scroll, "scroll"); + + clutter_actor_add_constraint (scroll, clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0)); + clutter_actor_add_constraint (scroll, clutter_bind_constraint_new (stage, CLUTTER_BIND_SIZE, 0)); + + clutter_actor_add_child (scroll, create_content_actor ()); + + pan_action = clutter_pan_action_new (); + clutter_pan_action_set_interpolate (CLUTTER_PAN_ACTION (pan_action), TRUE); + g_signal_connect (pan_action, "pan", G_CALLBACK (on_pan), NULL); + clutter_actor_add_action_with_name (scroll, "pan", pan_action); + + clutter_actor_set_reactive (scroll, TRUE); + + return scroll; +} + +static gboolean +on_key_press (ClutterActor *stage, + ClutterEvent *event, + gpointer unused) +{ + ClutterActor *scroll; + guint key_symbol; + + scroll = clutter_actor_get_first_child (stage); + + key_symbol = clutter_event_get_key_symbol (event); + + if (key_symbol == CLUTTER_KEY_space) + { + clutter_actor_save_easing_state (scroll); + clutter_actor_set_easing_duration (scroll, 1000); + clutter_actor_set_child_transform (scroll, NULL); + clutter_actor_restore_easing_state (scroll); + } + + return CLUTTER_EVENT_STOP; +} + +static gboolean +label_clicked_cb (ClutterText *label, ClutterEvent *event, ClutterActor *scroll) +{ + ClutterPanAction *action = CLUTTER_PAN_ACTION (clutter_actor_get_action (scroll, "pan")); + const gchar *label_text = clutter_text_get_text (label); + + if (g_str_equal (label_text, "X AXIS")) + clutter_pan_action_set_pan_axis (action, CLUTTER_PAN_X_AXIS); + else if (g_str_equal (label_text, "Y AXIS")) + clutter_pan_action_set_pan_axis (action, CLUTTER_PAN_Y_AXIS); + else if (g_str_equal (label_text, "AUTO")) + clutter_pan_action_set_pan_axis (action, CLUTTER_PAN_AXIS_AUTO); + else + clutter_pan_action_set_pan_axis (action, CLUTTER_PAN_AXIS_NONE); + + return TRUE; +} + +static void +add_label (const gchar *text, ClutterActor *box, ClutterActor *scroll) +{ + ClutterActor *label; + + label = clutter_text_new_with_text (NULL, text); + clutter_actor_set_reactive (label, TRUE); + clutter_actor_set_x_align (label, CLUTTER_ACTOR_ALIGN_START); + clutter_actor_set_x_expand (label, TRUE); + + clutter_actor_add_child (box, label); + + g_signal_connect (label, "button-release-event", + G_CALLBACK (label_clicked_cb), scroll); +} + +int +main (int argc, char *argv[]) +{ + ClutterActor *stage, *scroll, *box, *info; + ClutterLayoutManager *layout; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return EXIT_FAILURE; + + /* create a new stage */ + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Pan Action"); + clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); + + scroll = create_scroll_actor (stage); + clutter_actor_add_child (stage, scroll); + + box = clutter_actor_new (); + clutter_actor_add_child (stage, box); + clutter_actor_set_position (box, 12, 12); + + layout = clutter_box_layout_new (); + clutter_box_layout_set_orientation (CLUTTER_BOX_LAYOUT (layout), CLUTTER_ORIENTATION_VERTICAL); + clutter_actor_set_layout_manager (box, layout); + + info = clutter_text_new_with_text (NULL, "Press to reset the image position."); + clutter_actor_add_child (box, info); + + info = clutter_text_new_with_text (NULL, "Click labels below to change AXIS pinning."); + clutter_actor_add_child (box, info); + + add_label ("NONE", box, scroll); + add_label ("X AXIS", box, scroll); + add_label ("Y AXIS", box, scroll); + add_label ("AUTO", box, scroll); + + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + g_signal_connect (stage, "key-press-event", G_CALLBACK (on_key_press), scroll); + + clutter_actor_show (stage); + + clutter_main (); + + return EXIT_SUCCESS; +} diff --git a/clutter/examples/redhand.png b/clutter/examples/redhand.png new file mode 100644 index 0000000000000000000000000000000000000000..c07d8acd33d54996512f6e2b6ca4d17b5ffc4f20 GIT binary patch literal 8250 zcmZ`;Wmr_v)*gE3p#+8+Lb^c&q=pb2x^?Iv#L#Gna z;9~}DGo8|sclaT%M4lM0sJI~^@yle1Nun*Qtas*mx9*&F^7#69TJZ3qQ-xoJo%DX| znaMt;`2V;vDHOLbxeD%3@fWQ(yl9B0{<|x|zEzBir7;y0eIx5!CM!yB=ABC^n0Zqi zULG=FeZ+x^fuZI}U%)~*L0t=1xN;I9lps7>s{tfzeLxhvh7rStBEoj>Xy*5;3&sCx z4C0EZ2}Qzg*pggWz|2@mv*DQiw{83&9ld&Dk*Q5sh^U0i+KJ$MwOg)&9U3ckTWL-! zXP$!k4!uMjM3D|cAY;jf4?$~{rG;QEuO2dZzisK(*sR7Cn5MHmV(flByu^`IbMGv; zTjwp9{^Z`Q&xp2;Sj{%~!fWmZ!zPn6SoFex&gX6qSE0uYcg?1d2*FjLyT9C`I2})u z>!QHLpuxr0fH&8KO(}L!Q8zv<%e?)KfVl5@&G{s4l8)qLcwIf^+|7cy^BVWMztY3d zB`K?*fL|c-f$?4&uWCZX))U9MaGk4Rb?(AO7mYhtx-_HS+~mrKD7E^e#&W9|9}d(> zeP~OvNM8^;O3IZq{AG;GLlhAv#G0eA*#d$()=-BawhU46&!nza-E9-W@$n#h{V4D)ibK`(ZFg>gnw`Nn*^ zuoX2v5ygJ~tPVBLNC{I_O{BYe3%kWAW(9dp0=8@rFtBeB)(tJ9`h zUp^=y;l6W5wV-1A0p=`FM9s~`N;FTy2%GBtg%Ck^m&1)7e#*yhvB-|k<_rcZKSHyEn2l z2na;dnMP8;oXDj*z})umle9{f2;S+dRk8KgVG()1y29)wyo;TEgeE6fSKsXCEJrYX zjd?ogk~aq1t@$?UFvik!t$JtVn#OI(1=m2_g8Xb2Bu#IYu>?cmCO9}442uC2V{UCY zkevs^-j7|E$1e_xrF;-aPrl^k#$OCQK8THN_?czdZ(M`(UMc&tKqm!QA@>Gt3QrUD?r?em>(C;rw6K{*ceA41RYA`F9AMIlP8sFo1Q#Gi)rWmXo zL87$Q;AAk>o2Nv0ve5S2alR1^5uP41sOdv^GMxQYn#@(IB?8dXtPP5@6fEFUD@Nn) z`;*PM9|IH~MUV-VWen$b7(AZ}zR?!*1j+sV@TgxiQS4CXBZ(cmT6`FN2i{pxUu8Di?SJMK@?*1P81RJZ%*8=SOX|B2s)2Zf`IpBw5R zkAD>nK8?Gdww>f1x1b6}Tpm$dWUsD2dlhBOue1n{S@szc;<3c{U zN??MjcHF0I=tq43%kyUP!WPMl@vv?0{<|YpE;PG15gZgLvl(DD#b0t))Eipse(f6_ zY;l1Oo*oZTdg5m?zqm6nkeiyS1fY-UT+77j((J6*R8o=>A9co9cLF$`!6n(Xn>gN0(nM=}@Sa$119Orcg|TqJ{3UvkA3=5>DyxyAgsOnw@Pyc*`HqUKdV= zVM||E!|R9JEQOiSht5f#T*p=;EgK~Sw)&N;^B{^RI;vJLbB1^-s)|EOYR34tEgd9c zbVMIe&3xh4tBPo^Kl$sE>R>!&ekI3;jJ%U_s@EPp$D8UydOFh*J}ZsRRBbgldu!R~ zVDIjTjNI1_!+rbkw;+P5l%S5O)yR?V$u>ut4kQi5N`e`-{Ub9I7K08Vlmk~CyF@bs za9Ig6g*PGHaaIVrs8Bp$!~d+1q4WAL|N8jCaaNYy9o(r0_04#D)w<1iN%}U)81uaj zU?2b40e=0L*Z#FK()S-t@>jutv6fV7Ak0lFVZPz5W@+E4dN3*X7h}7z@Vbni6Y2&^ z7k7fR2y(~d4o*-RX!H>O{5nA{KhSw2P~fY}y?up}Qe+$t7!4QqC+f0-kQBvc{Qtm~ z|Fs$VuS+C=X?e)EyFzs>|MFLP5A7Qr|vfCX#V^e)YAAkCiF<0=5*=t3f{>>`>xJ5HC zJi?WYVk*rHVVr^p(mAC}xG2;nMVP57`$ zNg;3$HU=ub@VPG+&ZGBoK9Ydnj~W?8hJTS7|GkmBv8ps~`X%y;$577ayNiRUo zi34M(cpZ{cJ~9M^&BmU4`SmS$dxEfCNNDupB2wppz36CDtHRnAzF%;#e|R`cwlezO zlZu#%su-cFa9P!nEBX-U(biVL?*TY?)pI9*HXDYLI)RwP(!a}=30$5mfA6v&0uK=r zr(q7oWwsuL_5AomY^F^Xb^f>ablqByUiR;(^@>m=MTos9c>5RL%7{#KszUg5CZ!*1 zjGYk;OJA%)kJm_!j4TrXD4h*_&p#lYNEkyo#b_25#ytBW^}(n57k)do!2{Ibw|l1W-(&uV^*vi0yFNk~xyD#RQqv8V|4rd6*cneWJQL|uZA}Q81?JGdubpjg|>Ed==$Yb zr1Af0@ZpjCa>*Xq`oyoM2{}&-%x2C~$9*h7E6f}ZnQb@J*w`O-=Gmyq+#b`ckC>IF z&(tL}IV25|B*x=0R%Z;n{RZ>JjxFLKH>gyMc)VE6^H_oJ{OHqA#@N;2w`QUP8f^FT zbLEkIwtA>U;`#Re$DNh87XlrM>+1tjxE?k*hxRk%ZFhHmqD+Dzb*qyY+Z*9cm&arx zP6od;tVp!oFDlp>`Ao9U8(j`!<2Kq}wQ5jed#B4VKs7Z@GaqY?iEv5bY9}oO1*y!} zzf07jo)H)Djs&^dlA49q=5OgGk~magkKb>j@{f{ zUuIJ~J&DCNlewee3nyCXi+>CAeRh9V)gD#-jd87wqv2PB30t`lMivPJuz8&c$mgq= za+d;<(4MrbpHUNKIfp0feeS6=J*;fl3kK!xm*^1BPFWd7hRvZhp-7P?BgH)UO`1iQ z2yYD9nU+k*mEI(lrqhg9*{^06$Y10c1LD#4%^Zwyxy|0_9Ac7F8soCA^xVe-{({JZwA9CMNRc9h6LWB9nP7ib+9n>Fhzc8&vk}#r~rG?YOS5 zgOsirL+P(y+CFEz+x!+!&3wg(Qc?uR$3tj|)VEXu1D0n>sRAUuL)@HsG2fh_3>8re zAD!8t#FBw0WN{=61h%3_G(Gaj;=fFOR|g8Mv(|RyCGf-cK+gF_;uH>z`OCx)vQ9}E zbYECmMlBCspkkpo9hGK#;k0mOYg9+UHTLmNDMUhb}m2B(CM zS0X1iHb3q3^2mH7B>K(jZ~+tzvzV&1KmX2Sf7#CpsW+LJn+ci~rMx)^b)I57py{za zf{)&vPE8ob%$iv9o1heKubAJ=2$%IA;?-(JmDY=9zL%m^W_%5PczssF*y^vW#2k}V zQj-oV9g}Ucki}l~LYMY&Ew)m35J6G90_`C+g?)uK6V}$t>*+$`A`ax{S_YXY-^mhVNik6TLV{zNV> zf&d7Xkf&jVPEf2O1j65a&cPVk&yab(PwJu-zgl;?MQvU^;=C2ZY}JWL>AFzrKUVQH z#=U8MQG+RT+S6`p&)wnBGPy8++J!?X34hb>hn)J;@Z8_8m6bX>oD3O5rwJoru=Sh> zO1?Vl`=Ir5Q-^Z~o6@rGnSrDX*YEleKE|MQp2)TySkU3&0T^G~b#!8Ct?S487wkz2 z-UjMVacetnbjE};NTEGekT)JR$r?AQZQfkl$4B&~-JXW!a%R4bmcMb>*o=JaSp90O z6#;*ZN-5ysf&(0tWa?#M-&51O6W!nQ=8qp^pX?5p@lKfW%2P_C-G7%=y(q2n>(}5> z(=a$841Q5%KHsZDXTGxHZum!wa$+m~eCRRBoWqY7Unfp?sCY(ZQ+R>7AcPTT?BNz&om{7<(8IyejeLYbH5r|z@pnX`c9vs

>E{@fRQy3@FN~J}p2Nt@97Uf0{oU|re+3NWF8_n@k&H~DCY}MkY^70m_tQ9( zpI)+pugQ9}0C$Vc(}5rlMPw$`wN42wf?G#7CE8<@z!lpyf^hgE(FF!%Z@ z&7z=RMR_0w&ph{%N6)m67jx?&i{6;e~N(ZJx53FKH?b4n|0*4(>n7YSDE}g1jH6}UBS)c8g_pXLG&_-(Am!}=AHQfLCxxF%1u6-ehk_5-_}0|eRNSS zpn64#*Df=d_ZR-XgJK4TYgd}Gof9v&R3L$Gv)t5T*6Rqu=02Atn!W{NTG|fD7ola4 z%PTpK-vG{&JA#(&l4XXc91(tYGu(w_bWzm_0ZGo-p zE+UhO^`}Xix%-u72M$Z-DQ6;i{}hnHV}5GMBz{Q}hew|I>ruZeO>lIr@*KnQ)zlO_ zq~Aa!JaX5QA6u?aF~*^)+T}mn43@W?{V*|Is! zS+N=N+g*CL_7|=!RnUORDevw^*Xqvz=eSB5kZX3pGphmz#y4zFVAcs zTdiq)pjQ-{fhL{*@F>)-%;3Ovs&b3*={sYKWVyw@*kYOBPlJ6!*wn{Xh!Rrfbpnuf zMjDX!yZe6y4bYKwX9YnI=LH(MfB-D+y%Z>@XYl=Mv6$LIaUO|d$wb#l(|QW6c7#JH zWhXheqtjo_4J`FOSf!%~h4A^HZ|^ktOg%qWmj~yvht;@Oxmr`lh82 zTQG!!NGogP%#aClLH1cy8~ZDtaP26-82g=`@Cp%n;Vj!BwxXxeG2(A z3V8xRdQJYR%vE6Ss{lDxRv7#B>V;+Q`mM3tujW57m&cd(skB$M!ujeMg?}XI-!Bus zz-G3lV`fX!xsoavSNB1t+lBqs`4s)?+NJDF!p!(H37{?_^cu#pd9$Hz5L|7VRLFGw zbzQEJ#w;;nAX_tNXt&?gFin@9BMVj4AM@XXYQ!)S2fk|N5uHkd90@q7SndsE|JKn{ zJUEa`)0C-souRb&cxm}(;=?GWF&{k|Zfzl}A_pGC2#MS8a0|q=?TZ(3V-$YC zTg@Guq}!?wWaQIU=w|P5MUiJDQMU$`kKjMJg_Xb8K?MZZ%1yZj4<`XC<`Hz|oz~`j zWVS`gbnC%_pzUYiMf3LOAr)) zSAMqMp{da(TFL}U7yZ|1Qv8MrFOh=>kFTZs zT=PT4j{(CiXK@0lr5=@+~ZslHXq>#4caPBItw@a2&oZ`sjx-vTcG+WM_NiTwXYFIfvKMHug zD3kaqTi0BA)YJjj(1 zAO+4n00#z%Krj1K@&96A&}63kPXD*MBFtP*8)(GU0Z~fwR>TYy+?8d3MnZ+fz9I6H5Y{aq!~(yLZ}w=8TmAr&I*(*Kq=bPnhSi zusnhtx#xS`NF~+5TU!ud)_Ty8TIvw>T$ey4oTH?~_^jmddYdq}HFtkVEbcc`4U_-#lZFa-+IAI1Z2|KJeQmhP$HT zy-1YeGa`jQKx)ZY1fW!ez+yz5?p!;G!5XaeYd=aHycF90TAN3s#sDbt^{u0 zF*a*$&zqu8E5~z3v;5xjE*1}>e|UYKxBEwXJiq8z(c2fi^vB-Y{0mLzxp7KUATKl9 zKn}iV(%>mc$mi^X(u|ryTz$KdTy8$%iLI^TW_OI!=H_f%EKRRccdg|ye#I~2LTl2G&U$$lO9 zi>afv$I)I&I)@nlt(&(f@^2e;kXh?@AO3GFr|z7{`F!>&kP(PyxW%hU^o&fNw>>FS z+>(&1zzm-`3q-S9?6RzdLj@uSGe5|(@a^YyM8YyTP(<)wZ8K^99bQHt+!r5cJjHq8 zce1Xm_iU&hkbf#g*c!io7UZbnkI;smuHr9=B+_w`b%|XPCw%6_#L_1P_pa>UO+kCF zVpflgl)>-WW>h_F2elCUtf&~Q1F4JBw6Z>Wo^sDMvre64onZNX8c>y&z6ZWFmj7Zv z4uv?pr`f^`BL+*5T<(eZg*?tTCcQNg5Fwbkc0Oz6rwCVpC=w!!`Slib*R>!R!QMAw zk67_C8m9I#TvSu68Juqer~II2N*aol@-LA8 E2il-`3jhEB literal 0 HcmV?d00001 diff --git a/clutter/examples/rounded-rectangle.c b/clutter/examples/rounded-rectangle.c new file mode 100644 index 0000000..6ffdb4c --- /dev/null +++ b/clutter/examples/rounded-rectangle.c @@ -0,0 +1,110 @@ +#include +#include +#include +#include + +static gboolean +draw_content (ClutterCanvas *canvas, + cairo_t *cr, + int surface_width, + int surface_height) +{ + /* rounded rectangle taken from: + * + * http://cairographics.org/samples/rounded_rectangle/ + * + * we leave 1 pixel around the edges to avoid jagged edges + * when rotating the actor + */ + double x = 1.0, /* parameters like cairo_rectangle */ + y = 1.0, + width = surface_width - 2.0, + height = surface_height - 2.0, + aspect = 1.0, /* aspect ratio */ + corner_radius = height / 20.0; /* and corner curvature radius */ + + double radius = corner_radius / aspect; + double degrees = M_PI / 180.0; + + cairo_save (cr); + cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); + cairo_paint (cr); + cairo_restore (cr); + + cairo_new_sub_path (cr); + cairo_arc (cr, x + width - radius, y + radius, radius, -90 * degrees, 0 * degrees); + cairo_arc (cr, x + width - radius, y + height - radius, radius, 0 * degrees, 90 * degrees); + cairo_arc (cr, x + radius, y + height - radius, radius, 90 * degrees, 180 * degrees); + cairo_arc (cr, x + radius, y + radius, radius, 180 * degrees, 270 * degrees); + cairo_close_path (cr); + + cairo_set_source_rgba (cr, 0.5, 0.5, 1, 0.95); + cairo_fill (cr); + + /* we're done drawing */ + return TRUE; +} + +int +main (int argc, char *argv[]) +{ + ClutterActor *stage, *actor; + ClutterContent *canvas; + ClutterTransition *transition; + + /* initialize Clutter */ + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return EXIT_FAILURE; + + /* create a stage */ + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Rectangle with rounded corners"); + clutter_stage_set_use_alpha (CLUTTER_STAGE (stage), TRUE); + clutter_actor_set_background_color (stage, CLUTTER_COLOR_Black); + clutter_actor_set_size (stage, 500, 500); + clutter_actor_set_opacity (stage, 64); + clutter_actor_show (stage); + + /* our 2D canvas, courtesy of Cairo */ + canvas = clutter_canvas_new (); + clutter_canvas_set_size (CLUTTER_CANVAS (canvas), 300, 300); + + /* the actor that will display the contents of the canvas */ + actor = clutter_actor_new (); + clutter_actor_set_content (actor, canvas); + clutter_actor_set_content_gravity (actor, CLUTTER_CONTENT_GRAVITY_CENTER); + clutter_actor_set_content_scaling_filters (actor, + CLUTTER_SCALING_FILTER_TRILINEAR, + CLUTTER_SCALING_FILTER_LINEAR); + clutter_actor_set_pivot_point (actor, 0.5f, 0.5f); + clutter_actor_add_constraint (actor, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5)); + clutter_actor_set_request_mode (actor, CLUTTER_REQUEST_CONTENT_SIZE); + clutter_actor_add_child (stage, actor); + + /* the actor now owns the canvas */ + g_object_unref (canvas); + + /* create the continuous animation of the actor spinning around its center */ + transition = clutter_property_transition_new ("rotation-angle-y"); + clutter_transition_set_from (transition, G_TYPE_DOUBLE, 0.0); + clutter_transition_set_to (transition, G_TYPE_DOUBLE, 360.0); + clutter_timeline_set_duration (CLUTTER_TIMELINE (transition), 2000); + clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (transition), -1); + clutter_actor_add_transition (actor, "rotateActor", transition); + + /* the actor now owns the transition */ + g_object_unref (transition); + + /* quit on destroy */ + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + /* connect our drawing code */ + g_signal_connect (canvas, "draw", G_CALLBACK (draw_content), NULL); + + /* invalidate the canvas, so that we can draw before the main loop starts */ + clutter_content_invalidate (canvas); + + clutter_main (); + + return EXIT_SUCCESS; +} diff --git a/clutter/examples/scroll-actor.c b/clutter/examples/scroll-actor.c new file mode 100644 index 0000000..a5ffe3c --- /dev/null +++ b/clutter/examples/scroll-actor.c @@ -0,0 +1,193 @@ +#include +#include +#include + +static const char *menu_items_name[] = { + "Option 1", + "Option 2", + "Option 3", + "Option 4", + "Option 5", + "Option 6", + "Option 7", + "Option 8", + "Option 9", + "Option 10", + "Option 11", +}; + +static const guint menu_items_len = G_N_ELEMENTS (menu_items_name); + +static void +select_item_at_index (ClutterActor *scroll, + int index_) +{ + ClutterPoint point; + ClutterActor *menu, *item; + gpointer old_selected; + + menu = clutter_actor_get_first_child (scroll); + + old_selected = g_object_get_data (G_OBJECT (scroll), "selected-item"); + if (old_selected != NULL) + { + item = clutter_actor_get_child_at_index (menu, GPOINTER_TO_INT (old_selected)); + clutter_text_set_color (CLUTTER_TEXT (item), CLUTTER_COLOR_White); + } + + /* wrap around the index */ + if (index_ < 0) + index_ = clutter_actor_get_n_children (menu) - 1; + else if (index_ >= clutter_actor_get_n_children (menu)) + index_ = 0; + + item = clutter_actor_get_child_at_index (menu, index_); + clutter_actor_get_position (item, &point.x, &point.y); + + /* scroll to the actor's position; the menu actor is always set at (0, 0), + * so it does not contribute any further offset, and we can use the position + * of its children to ask the ScrollActor to scroll the visible region; if + * the menu actor had an offset, or was transformed, we would have needed to + * get their relative transformed position instead. + */ + clutter_actor_save_easing_state (scroll); + clutter_scroll_actor_scroll_to_point (CLUTTER_SCROLL_ACTOR (scroll), &point); + clutter_actor_restore_easing_state (scroll); + + clutter_text_set_color (CLUTTER_TEXT (item), CLUTTER_COLOR_LightSkyBlue); + + /* store the index of the currently selected item, so that we can + * implement select_next_item() and select_prev_item() + */ + g_object_set_data (G_OBJECT (scroll), "selected-item", + GINT_TO_POINTER (index_)); +} + +static void +select_next_item (ClutterActor *scroll) +{ + gpointer selected_ = g_object_get_data (G_OBJECT (scroll), "selected-item"); + + select_item_at_index (scroll, GPOINTER_TO_INT (selected_) + 1); +} + +static void +select_prev_item (ClutterActor *scroll) +{ + gpointer selected_ = g_object_get_data (G_OBJECT (scroll), "selected-item"); + + select_item_at_index (scroll, GPOINTER_TO_INT (selected_) - 1); +} + +static ClutterActor * +create_menu_item (const char *name) +{ + ClutterActor *text; + + text = clutter_text_new (); + clutter_text_set_font_name (CLUTTER_TEXT (text), "Sans Bold 24"); + clutter_text_set_text (CLUTTER_TEXT (text), name); + clutter_text_set_color (CLUTTER_TEXT (text), CLUTTER_COLOR_White); + clutter_actor_set_margin_left (text, 12.f); + clutter_actor_set_margin_right (text, 12.f); + + return text; +} + +static ClutterActor * +create_menu_actor (ClutterActor *scroll) +{ + ClutterActor *menu; + ClutterLayoutManager *layout_manager; + guint i; + + /* this is our menu; it contains items in a vertical layout */ + layout_manager = clutter_box_layout_new (); + clutter_box_layout_set_orientation (CLUTTER_BOX_LAYOUT (layout_manager), + CLUTTER_ORIENTATION_VERTICAL); + clutter_box_layout_set_spacing (CLUTTER_BOX_LAYOUT (layout_manager), 12.f); + + menu = clutter_actor_new (); + clutter_actor_set_layout_manager (menu, layout_manager); + clutter_actor_set_background_color (menu, CLUTTER_COLOR_Black); + + /* these are the items */ + for (i = 0; i < menu_items_len; i++) + clutter_actor_add_child (menu, create_menu_item (menu_items_name[i])); + + return menu; +} + +static ClutterActor * +create_scroll_actor (ClutterActor *stage) +{ + ClutterActor *scroll; + + /* our scrollable viewport */ + scroll = clutter_scroll_actor_new (); + clutter_actor_set_name (scroll, "scroll"); + + /* give a vertical offset, and constrain the viewport so that its size + * is bound to the stage size + */ + clutter_actor_set_position (scroll, 0.f, 18.f); + clutter_actor_add_constraint (scroll, clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0.5)); + clutter_actor_add_constraint (scroll, clutter_bind_constraint_new (stage, CLUTTER_BIND_HEIGHT, -36.f)); + + /* we only want to scroll the contents vertically, and + * ignore any horizontal component + */ + clutter_scroll_actor_set_scroll_mode (CLUTTER_SCROLL_ACTOR (scroll), + CLUTTER_SCROLL_VERTICALLY); + + clutter_actor_add_child (scroll, create_menu_actor (scroll)); + + /* select the first item */ + select_item_at_index (scroll, 0); + + return scroll; +} + +static gboolean +on_key_press (ClutterActor *stage, + ClutterEvent *event, + gpointer unused) +{ + ClutterActor *scroll; + guint key_symbol; + + scroll = clutter_actor_get_first_child (stage); + + key_symbol = clutter_event_get_key_symbol (event); + + if (key_symbol == CLUTTER_KEY_Up) + select_prev_item (scroll); + else if (key_symbol == CLUTTER_KEY_Down) + select_next_item (scroll); + + return CLUTTER_EVENT_STOP; +} + +int +main (int argc, char *argv[]) +{ + ClutterActor *stage; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return EXIT_FAILURE; + + /* create a new stage */ + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Scroll Actor"); + clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + g_signal_connect (stage, "key-press-event", G_CALLBACK (on_key_press), NULL); + + clutter_actor_add_child (stage, create_scroll_actor (stage)); + + clutter_actor_show (stage); + + clutter_main (); + + return EXIT_SUCCESS; +} diff --git a/clutter/examples/threads.c b/clutter/examples/threads.c new file mode 100644 index 0000000..7a1e71e --- /dev/null +++ b/clutter/examples/threads.c @@ -0,0 +1,292 @@ +#include +#include +#include + +/* our thread-specific data */ +typedef struct +{ + ClutterActor *stage; + ClutterActor *label; + ClutterActor *progress; + ClutterActor *rect; + + ClutterTransition *flip; + ClutterTransition *bounce; +} TestThreadData; + +static TestThreadData * +test_thread_data_new (void) +{ + TestThreadData *data; + + data = g_new0 (TestThreadData, 1); + + return data; +} + +static void +test_thread_data_free (gpointer _data) +{ + TestThreadData *data = _data; + + if (data == NULL) + return; + + g_print ("Removing thread data [%p]\n", _data); + + g_clear_object (&data->progress); + g_clear_object (&data->label); + g_clear_object (&data->stage); + g_clear_object (&data->rect); + g_clear_object (&data->flip); + g_clear_object (&data->bounce); + + g_free (data); +} + +static gboolean +test_thread_done_idle (gpointer user_data) +{ + TestThreadData *data = user_data; + + g_print ("Last update [%p]\n", data); + + clutter_text_set_text (CLUTTER_TEXT (data->label), "Completed"); + + clutter_actor_remove_transition (data->rect, "bounce"); + clutter_actor_remove_transition (data->rect, "flip"); + + return G_SOURCE_REMOVE; +} + +static void +test_thread_data_done (gpointer _data) +{ + if (_data == NULL) + return; + + g_print ("Thread completed\n"); + + /* since the TestThreadData structure references Clutter data structures + * we need to free it from within the same thread that called clutter_main() + * which means using an idle handler in the main loop. + * + * clutter_threads_add_idle() is guaranteed to run the callback passed to + * to it under the Big Clutter Lock. + */ + clutter_threads_add_idle_full (G_PRIORITY_DEFAULT, + test_thread_done_idle, + _data, + test_thread_data_free); +} + +/* thread local storage */ +static GPrivate test_thread_data = G_PRIVATE_INIT (test_thread_data_done); + +typedef struct { + gint count; + TestThreadData *thread_data; +} TestUpdate; + +static gboolean +update_label_idle (gpointer data) +{ + TestUpdate *update = data; + guint width; + gchar *text; + + if (update->thread_data->label == NULL) + return G_SOURCE_REMOVE; + + text = g_strdup_printf ("Count to %d", update->count); + clutter_text_set_text (CLUTTER_TEXT (update->thread_data->label), text); + + clutter_actor_set_width (update->thread_data->label, -1); + + if (update->count == 0) + width = 0; + else if (update->count == 100) + width = 350; + else + width = (guint) (update->count / 100.0 * 350.0); + + clutter_actor_save_easing_state (update->thread_data->progress); + clutter_actor_set_width (update->thread_data->progress, width); + clutter_actor_restore_easing_state (update->thread_data->progress); + + g_free (text); + g_free (update); + + return G_SOURCE_REMOVE; +} + +static void +do_something_very_slow (void) +{ + TestThreadData *data; + gint i; + + data = g_private_get (&test_thread_data); + + for (i = 0; i <= 100; i++) + { + gint msecs; + + msecs = 1 + (int) (100.0 * rand () / ((RAND_MAX + 1.0) / 3)); + + /* sleep for a while, to emulate some work being done */ + g_usleep (msecs * 1000); + + if ((i % 10) == 0) + { + TestUpdate *update; + + /* update the UI from within the main loop, making sure that the + * Big Clutter Lock is held; only one thread at a time can call + * Clutter API, and it's mandatory to do this from the same thread + * that called clutter_init()/clutter_main(). + */ + update = g_new (TestUpdate, 1); + update->count = i; + update->thread_data = data; + + clutter_threads_add_idle_full (G_PRIORITY_HIGH, + update_label_idle, + update, NULL); + } + } +} + +static gpointer +test_thread_func (gpointer user_data) +{ + TestThreadData *data = user_data; + + g_private_set (&test_thread_data, data); + + /* this function will block */ + do_something_very_slow (); + + return NULL; +} + +static ClutterActor *count_label = NULL; +static ClutterActor *help_label = NULL; +static ClutterActor *progress_rect = NULL; +static ClutterActor *rect = NULL; +static ClutterTransition *flip = NULL; +static ClutterTransition *bounce = NULL; + +static gboolean +on_key_press_event (ClutterStage *stage, + ClutterEvent *event, + gpointer user_data) +{ + TestThreadData *data; + + switch (clutter_event_get_key_symbol (event)) + { + case CLUTTER_KEY_s: + clutter_text_set_text (CLUTTER_TEXT (help_label), "Press 'q' to quit"); + + /* start the animations */ + clutter_actor_add_transition (rect, "flip", flip); + clutter_actor_add_transition (rect, "bounce", bounce); + + /* the data structure holding all our objects */ + data = test_thread_data_new (); + data->stage = g_object_ref (stage); + data->label = g_object_ref (count_label); + data->progress = g_object_ref (progress_rect); + data->rect = g_object_ref (rect); + data->flip = g_object_ref (flip); + data->bounce = g_object_ref (bounce); + + /* start the thread that updates the counter and the progress bar */ + g_thread_new ("counter", test_thread_func, data); + + return CLUTTER_EVENT_STOP; + + case CLUTTER_KEY_q: + clutter_main_quit (); + + return CLUTTER_EVENT_STOP; + + default: + break; + } + + return CLUTTER_EVENT_PROPAGATE; +} + +int +main (int argc, char *argv[]) +{ + ClutterTransition *transition; + ClutterActor *stage; + ClutterPoint start = CLUTTER_POINT_INIT (75.f, 150.f); + ClutterPoint end = CLUTTER_POINT_INIT (400.f, 150.f); + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Threading"); + clutter_actor_set_background_color (stage, CLUTTER_COLOR_Aluminium3); + clutter_actor_set_size (stage, 600, 300); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + count_label = clutter_text_new_with_text ("Mono 12", "Counter"); + clutter_actor_set_position (count_label, 350, 50); + clutter_actor_add_child (stage, count_label); + + help_label = clutter_text_new_with_text ("Mono 12", "Press 's' to start"); + clutter_actor_set_position (help_label, 50, 50); + clutter_actor_add_child (stage, help_label); + + /* a progress bar */ + progress_rect = clutter_actor_new (); + clutter_actor_set_background_color (progress_rect, CLUTTER_COLOR_DarkChameleon); + clutter_actor_set_position (progress_rect, 50, 225); + clutter_actor_set_size (progress_rect, 350, 50); + clutter_actor_add_child (stage, progress_rect); + + /* an actor we bounce around */ + rect = clutter_actor_new (); + clutter_actor_set_background_color (rect, CLUTTER_COLOR_LightScarletRed); + clutter_actor_set_position (rect, 75, 150); + clutter_actor_set_size (rect, 50, 50); + clutter_actor_set_pivot_point (rect, .5f, .5f); + clutter_actor_set_opacity (rect, 224); + clutter_actor_add_child (stage, rect); + + /* two transitions we use to bounce rect around */ + transition = clutter_property_transition_new ("rotation-angle-z"); + clutter_transition_set_from (transition, G_TYPE_DOUBLE, 0.0); + clutter_transition_set_to (transition, G_TYPE_DOUBLE, 360.0); + clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (transition), -1); + clutter_timeline_set_auto_reverse (CLUTTER_TIMELINE (transition), TRUE); + clutter_timeline_set_duration (CLUTTER_TIMELINE (transition), 3000); + flip = transition; + + transition = clutter_property_transition_new ("position"); + clutter_transition_set_from (transition, CLUTTER_TYPE_POINT, &start); + clutter_transition_set_to (transition, CLUTTER_TYPE_POINT, &end); + clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (transition), -1); + clutter_timeline_set_auto_reverse (CLUTTER_TIMELINE (transition), TRUE); + clutter_timeline_set_duration (CLUTTER_TIMELINE (transition), 3000); + bounce = transition; + + g_signal_connect (stage, + "button-press-event", G_CALLBACK (clutter_main_quit), + NULL); + g_signal_connect (stage, + "key-press-event", G_CALLBACK (on_key_press_event), + NULL); + + clutter_actor_show (stage); + + clutter_main (); + + return EXIT_SUCCESS; +} diff --git a/clutter/tests/Makefile.am b/clutter/tests/Makefile.am new file mode 100644 index 0000000..65b474a --- /dev/null +++ b/clutter/tests/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = accessibility conform interactive micro-bench performance + +EXTRA_DIST = README clutter-1.0.suppressions diff --git a/clutter/tests/Makefile.in b/clutter/tests/Makefile.in new file mode 100644 index 0000000..bda2137 --- /dev/null +++ b/clutter/tests/Makefile.in @@ -0,0 +1,695 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = tests +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/build/autotools/as-compiler-flag.m4 \ + $(top_srcdir)/build/autotools/glibtests.m4 \ + $(top_srcdir)/build/autotools/introspection.m4 \ + $(top_srcdir)/build/autotools/libtool.m4 \ + $(top_srcdir)/build/autotools/ltoptions.m4 \ + $(top_srcdir)/build/autotools/ltsugar.m4 \ + $(top_srcdir)/build/autotools/ltversion.m4 \ + $(top_srcdir)/build/autotools/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/clutter/clutter-build-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in README +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ATK_REQ_VERSION = @ATK_REQ_VERSION@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_REQ_VERSION = @CAIRO_REQ_VERSION@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CLUTTER_API_VERSION = @CLUTTER_API_VERSION@ +CLUTTER_API_VERSION_AM = @CLUTTER_API_VERSION_AM@ +CLUTTER_BACKENDS = @CLUTTER_BACKENDS@ +CLUTTER_CFLAGS = @CLUTTER_CFLAGS@ +CLUTTER_COGL = @CLUTTER_COGL@ +CLUTTER_CONFIG_DEFINES = @CLUTTER_CONFIG_DEFINES@ +CLUTTER_DEBUG_CFLAGS = @CLUTTER_DEBUG_CFLAGS@ +CLUTTER_DEPRECATED_CFLAGS = @CLUTTER_DEPRECATED_CFLAGS@ +CLUTTER_DEPS_CFLAGS = @CLUTTER_DEPS_CFLAGS@ +CLUTTER_DEPS_LIBS = @CLUTTER_DEPS_LIBS@ +CLUTTER_DEPS_PRIVATE_CFLAGS = @CLUTTER_DEPS_PRIVATE_CFLAGS@ +CLUTTER_DEPS_PRIVATE_LIBS = @CLUTTER_DEPS_PRIVATE_LIBS@ +CLUTTER_FLAVOUR = @CLUTTER_FLAVOUR@ +CLUTTER_GCOV_CFLAGS = @CLUTTER_GCOV_CFLAGS@ +CLUTTER_GCOV_LDADD = @CLUTTER_GCOV_LDADD@ +CLUTTER_HIDDEN_VISIBILITY_CFLAGS = @CLUTTER_HIDDEN_VISIBILITY_CFLAGS@ +CLUTTER_INPUT_BACKENDS = @CLUTTER_INPUT_BACKENDS@ +CLUTTER_LIBS = @CLUTTER_LIBS@ +CLUTTER_LINK_FLAGS = @CLUTTER_LINK_FLAGS@ +CLUTTER_LT_CURRENT = @CLUTTER_LT_CURRENT@ +CLUTTER_LT_LDFLAGS = @CLUTTER_LT_LDFLAGS@ +CLUTTER_LT_REVISION = @CLUTTER_LT_REVISION@ +CLUTTER_LT_VERSION = @CLUTTER_LT_VERSION@ +CLUTTER_MAJOR_VERSION = @CLUTTER_MAJOR_VERSION@ +CLUTTER_MICRO_VERSION = @CLUTTER_MICRO_VERSION@ +CLUTTER_MINOR_VERSION = @CLUTTER_MINOR_VERSION@ +CLUTTER_RELEASE_STATUS = @CLUTTER_RELEASE_STATUS@ +CLUTTER_REQUIRES = @CLUTTER_REQUIRES@ +CLUTTER_REQUIRES_PRIVATE = @CLUTTER_REQUIRES_PRIVATE@ +CLUTTER_SONAME_INFIX = @CLUTTER_SONAME_INFIX@ +CLUTTER_STAGE_TYPE = @CLUTTER_STAGE_TYPE@ +CLUTTER_VERSION = @CLUTTER_VERSION@ +CLUTTER_WINSYS = @CLUTTER_WINSYS@ +CLUTTER_WINSYS_BASE = @CLUTTER_WINSYS_BASE@ +COGL_DRIVER = @COGL_DRIVER@ +COGL_REQ_VERSION = @COGL_REQ_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@ +GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@ +GDK_REQ_VERSION = @GDK_REQ_VERSION@ +GI_REQ_VERSION = @GI_REQ_VERSION@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQ_VERSION = @GLIB_REQ_VERSION@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +JSON_GLIB_REQ_VERSION = @JSON_GLIB_REQ_VERSION@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBINPUT_REQ_VERSION = @LIBINPUT_REQ_VERSION@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUDEV_REQ_VERSION = @LIBUDEV_REQ_VERSION@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTP = @LTP@ +LTP_GENHTML = @LTP_GENHTML@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINTAINER_CFLAGS = @MAINTAINER_CFLAGS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGO_REQ_VERSION = @PANGO_REQ_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SHTOOL = @SHTOOL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +XCOMPOSITE_REQ_VERSION = @XCOMPOSITE_REQ_VERSION@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +installed_test_metadir = @installed_test_metadir@ +installed_testdir = @installed_testdir@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = accessibility conform interactive micro-bench performance +EXTRA_DIST = README clutter-1.0.suppressions +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/clutter/tests/README b/clutter/tests/README new file mode 100644 index 0000000..b5665e6 --- /dev/null +++ b/clutter/tests/README @@ -0,0 +1,38 @@ +Outline of test categories: + +The conform/ tests should be non-interactive unit-tests that verify a single +feature is behaving as documented. Use the GLib and Clutter test API and macros +to write the test units. The conformance test suites are meant to be used with +continuous integration builds. + +The performance/ tests are performance tests, both focused tests testing single +metrics and larger tests. These tests are used to report one or more +performance markers for the build of Clutter. Each performance marker is picked +up from the standard output of running the tests from strings having the form +"\n@ marker-name: 42.23" where 'marker-name' and '42.23' are the key/value pairs +of a single metric. Each test can provide multiple key/value pairs. Note that +if framerate is the feedback metric the test should forcibly enable FPS +debugging itself. The file test-common.h contains utility function helping to +do fps reporting. + +The interactive/ tests are any tests whose status can not be determined without +a user looking at some visual output, or providing some manual input etc. This +covers most of the original Clutter tests. Ideally some of these tests will be +migrated into the conform/ directory. + +The accessibility/ tests are tests created to test the accessibility support of +clutter, testing some of the atk interfaces. + +Other notes: + +• All tests should ideally include a detailed description in the source +explaining exactly what the test is for, how the test was designed to work, +and possibly a rationale for the approach taken for testing. Tests for specific +bugs should reference the bug report URL or number. + +• When running tests under Valgrind, you should follow the instructions +available here: + + https://wiki.gnome.org/Valgrind + +and also use the suppression file available in the Git repository. diff --git a/clutter/tests/accessibility/Makefile.am b/clutter/tests/accessibility/Makefile.am new file mode 100644 index 0000000..f3531db --- /dev/null +++ b/clutter/tests/accessibility/Makefile.am @@ -0,0 +1,36 @@ +common_ldadd = \ + $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la + +common_sources = \ + cally-examples-util.c \ + cally-examples-util.h + +AM_CPPFLAGS = \ + -DPREFIXDIR=\"$(libdir)\" \ + -DCLUTTER_DISABLE_DEPRECATION_WARNINGS \ + -DGLIB_DISABLE_DEPRECATION_WARNINGS \ + -I$(top_srcdir)/../cogl \ + -I$(top_builddir)/../cogl \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + -I$(top_srcdir)/clutter \ + -I$(top_builddir)/clutter \ + -I$(top_srcdir)/tests/accessibility + +AM_CFLAGS = $(CLUTTER_CFLAGS) $(MAINTAINER_CFLAGS) +LDADD = $(common_ldadd) $(CLUTTER_LIBS) + +check_PROGRAMS = \ + cally-atkcomponent-example \ + cally-atkeditabletext-example \ + cally-atkevents-example \ + cally-atktext-example \ + cally-clone-example + +cally_atkcomponent_example_SOURCES = $(common_sources) cally-atkcomponent-example.c +cally_atktext_example_SOURCES = $(common_sources) cally-atktext-example.c +cally_atkevents_example_SOURCES = $(common_sources) cally-atkevents-example.c +cally_atkeditabletext_example_SOURCES = $(common_sources) cally-atkeditabletext-example.c +cally_clone_example_SOURCES = $(common_sources) cally-clone-example.c + +DISTCLEANFILES = diff --git a/clutter/tests/accessibility/Makefile.in b/clutter/tests/accessibility/Makefile.in new file mode 100644 index 0000000..ec1fe9e --- /dev/null +++ b/clutter/tests/accessibility/Makefile.in @@ -0,0 +1,750 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +check_PROGRAMS = cally-atkcomponent-example$(EXEEXT) \ + cally-atkeditabletext-example$(EXEEXT) \ + cally-atkevents-example$(EXEEXT) \ + cally-atktext-example$(EXEEXT) cally-clone-example$(EXEEXT) +subdir = tests/accessibility +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/build/autotools/as-compiler-flag.m4 \ + $(top_srcdir)/build/autotools/glibtests.m4 \ + $(top_srcdir)/build/autotools/introspection.m4 \ + $(top_srcdir)/build/autotools/libtool.m4 \ + $(top_srcdir)/build/autotools/ltoptions.m4 \ + $(top_srcdir)/build/autotools/ltsugar.m4 \ + $(top_srcdir)/build/autotools/ltversion.m4 \ + $(top_srcdir)/build/autotools/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/clutter/clutter-build-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__objects_1 = cally-examples-util.$(OBJEXT) +am_cally_atkcomponent_example_OBJECTS = $(am__objects_1) \ + cally-atkcomponent-example.$(OBJEXT) +cally_atkcomponent_example_OBJECTS = \ + $(am_cally_atkcomponent_example_OBJECTS) +cally_atkcomponent_example_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +cally_atkcomponent_example_DEPENDENCIES = $(common_ldadd) \ + $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +am_cally_atkeditabletext_example_OBJECTS = $(am__objects_1) \ + cally-atkeditabletext-example.$(OBJEXT) +cally_atkeditabletext_example_OBJECTS = \ + $(am_cally_atkeditabletext_example_OBJECTS) +cally_atkeditabletext_example_LDADD = $(LDADD) +cally_atkeditabletext_example_DEPENDENCIES = $(common_ldadd) \ + $(am__DEPENDENCIES_1) +am_cally_atkevents_example_OBJECTS = $(am__objects_1) \ + cally-atkevents-example.$(OBJEXT) +cally_atkevents_example_OBJECTS = \ + $(am_cally_atkevents_example_OBJECTS) +cally_atkevents_example_LDADD = $(LDADD) +cally_atkevents_example_DEPENDENCIES = $(common_ldadd) \ + $(am__DEPENDENCIES_1) +am_cally_atktext_example_OBJECTS = $(am__objects_1) \ + cally-atktext-example.$(OBJEXT) +cally_atktext_example_OBJECTS = $(am_cally_atktext_example_OBJECTS) +cally_atktext_example_LDADD = $(LDADD) +cally_atktext_example_DEPENDENCIES = $(common_ldadd) \ + $(am__DEPENDENCIES_1) +am_cally_clone_example_OBJECTS = $(am__objects_1) \ + cally-clone-example.$(OBJEXT) +cally_clone_example_OBJECTS = $(am_cally_clone_example_OBJECTS) +cally_clone_example_LDADD = $(LDADD) +cally_clone_example_DEPENDENCIES = $(common_ldadd) \ + $(am__DEPENDENCIES_1) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/clutter +depcomp = $(SHELL) $(top_srcdir)/build/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(cally_atkcomponent_example_SOURCES) \ + $(cally_atkeditabletext_example_SOURCES) \ + $(cally_atkevents_example_SOURCES) \ + $(cally_atktext_example_SOURCES) \ + $(cally_clone_example_SOURCES) +DIST_SOURCES = $(cally_atkcomponent_example_SOURCES) \ + $(cally_atkeditabletext_example_SOURCES) \ + $(cally_atkevents_example_SOURCES) \ + $(cally_atktext_example_SOURCES) \ + $(cally_clone_example_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/build/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ATK_REQ_VERSION = @ATK_REQ_VERSION@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_REQ_VERSION = @CAIRO_REQ_VERSION@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CLUTTER_API_VERSION = @CLUTTER_API_VERSION@ +CLUTTER_API_VERSION_AM = @CLUTTER_API_VERSION_AM@ +CLUTTER_BACKENDS = @CLUTTER_BACKENDS@ +CLUTTER_CFLAGS = @CLUTTER_CFLAGS@ +CLUTTER_COGL = @CLUTTER_COGL@ +CLUTTER_CONFIG_DEFINES = @CLUTTER_CONFIG_DEFINES@ +CLUTTER_DEBUG_CFLAGS = @CLUTTER_DEBUG_CFLAGS@ +CLUTTER_DEPRECATED_CFLAGS = @CLUTTER_DEPRECATED_CFLAGS@ +CLUTTER_DEPS_CFLAGS = @CLUTTER_DEPS_CFLAGS@ +CLUTTER_DEPS_LIBS = @CLUTTER_DEPS_LIBS@ +CLUTTER_DEPS_PRIVATE_CFLAGS = @CLUTTER_DEPS_PRIVATE_CFLAGS@ +CLUTTER_DEPS_PRIVATE_LIBS = @CLUTTER_DEPS_PRIVATE_LIBS@ +CLUTTER_FLAVOUR = @CLUTTER_FLAVOUR@ +CLUTTER_GCOV_CFLAGS = @CLUTTER_GCOV_CFLAGS@ +CLUTTER_GCOV_LDADD = @CLUTTER_GCOV_LDADD@ +CLUTTER_HIDDEN_VISIBILITY_CFLAGS = @CLUTTER_HIDDEN_VISIBILITY_CFLAGS@ +CLUTTER_INPUT_BACKENDS = @CLUTTER_INPUT_BACKENDS@ +CLUTTER_LIBS = @CLUTTER_LIBS@ +CLUTTER_LINK_FLAGS = @CLUTTER_LINK_FLAGS@ +CLUTTER_LT_CURRENT = @CLUTTER_LT_CURRENT@ +CLUTTER_LT_LDFLAGS = @CLUTTER_LT_LDFLAGS@ +CLUTTER_LT_REVISION = @CLUTTER_LT_REVISION@ +CLUTTER_LT_VERSION = @CLUTTER_LT_VERSION@ +CLUTTER_MAJOR_VERSION = @CLUTTER_MAJOR_VERSION@ +CLUTTER_MICRO_VERSION = @CLUTTER_MICRO_VERSION@ +CLUTTER_MINOR_VERSION = @CLUTTER_MINOR_VERSION@ +CLUTTER_RELEASE_STATUS = @CLUTTER_RELEASE_STATUS@ +CLUTTER_REQUIRES = @CLUTTER_REQUIRES@ +CLUTTER_REQUIRES_PRIVATE = @CLUTTER_REQUIRES_PRIVATE@ +CLUTTER_SONAME_INFIX = @CLUTTER_SONAME_INFIX@ +CLUTTER_STAGE_TYPE = @CLUTTER_STAGE_TYPE@ +CLUTTER_VERSION = @CLUTTER_VERSION@ +CLUTTER_WINSYS = @CLUTTER_WINSYS@ +CLUTTER_WINSYS_BASE = @CLUTTER_WINSYS_BASE@ +COGL_DRIVER = @COGL_DRIVER@ +COGL_REQ_VERSION = @COGL_REQ_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@ +GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@ +GDK_REQ_VERSION = @GDK_REQ_VERSION@ +GI_REQ_VERSION = @GI_REQ_VERSION@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQ_VERSION = @GLIB_REQ_VERSION@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +JSON_GLIB_REQ_VERSION = @JSON_GLIB_REQ_VERSION@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBINPUT_REQ_VERSION = @LIBINPUT_REQ_VERSION@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUDEV_REQ_VERSION = @LIBUDEV_REQ_VERSION@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTP = @LTP@ +LTP_GENHTML = @LTP_GENHTML@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINTAINER_CFLAGS = @MAINTAINER_CFLAGS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGO_REQ_VERSION = @PANGO_REQ_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SHTOOL = @SHTOOL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +XCOMPOSITE_REQ_VERSION = @XCOMPOSITE_REQ_VERSION@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +installed_test_metadir = @installed_test_metadir@ +installed_testdir = @installed_testdir@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +common_ldadd = \ + $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la + +common_sources = \ + cally-examples-util.c \ + cally-examples-util.h + +AM_CPPFLAGS = \ + -DPREFIXDIR=\"$(libdir)\" \ + -DCLUTTER_DISABLE_DEPRECATION_WARNINGS \ + -DGLIB_DISABLE_DEPRECATION_WARNINGS \ + -I$(top_srcdir)/../cogl \ + -I$(top_builddir)/../cogl \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + -I$(top_srcdir)/clutter \ + -I$(top_builddir)/clutter \ + -I$(top_srcdir)/tests/accessibility + +AM_CFLAGS = $(CLUTTER_CFLAGS) $(MAINTAINER_CFLAGS) +LDADD = $(common_ldadd) $(CLUTTER_LIBS) +cally_atkcomponent_example_SOURCES = $(common_sources) cally-atkcomponent-example.c +cally_atktext_example_SOURCES = $(common_sources) cally-atktext-example.c +cally_atkevents_example_SOURCES = $(common_sources) cally-atkevents-example.c +cally_atkeditabletext_example_SOURCES = $(common_sources) cally-atkeditabletext-example.c +cally_clone_example_SOURCES = $(common_sources) cally-clone-example.c +DISTCLEANFILES = +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/accessibility/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/accessibility/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +cally-atkcomponent-example$(EXEEXT): $(cally_atkcomponent_example_OBJECTS) $(cally_atkcomponent_example_DEPENDENCIES) $(EXTRA_cally_atkcomponent_example_DEPENDENCIES) + @rm -f cally-atkcomponent-example$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(cally_atkcomponent_example_OBJECTS) $(cally_atkcomponent_example_LDADD) $(LIBS) + +cally-atkeditabletext-example$(EXEEXT): $(cally_atkeditabletext_example_OBJECTS) $(cally_atkeditabletext_example_DEPENDENCIES) $(EXTRA_cally_atkeditabletext_example_DEPENDENCIES) + @rm -f cally-atkeditabletext-example$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(cally_atkeditabletext_example_OBJECTS) $(cally_atkeditabletext_example_LDADD) $(LIBS) + +cally-atkevents-example$(EXEEXT): $(cally_atkevents_example_OBJECTS) $(cally_atkevents_example_DEPENDENCIES) $(EXTRA_cally_atkevents_example_DEPENDENCIES) + @rm -f cally-atkevents-example$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(cally_atkevents_example_OBJECTS) $(cally_atkevents_example_LDADD) $(LIBS) + +cally-atktext-example$(EXEEXT): $(cally_atktext_example_OBJECTS) $(cally_atktext_example_DEPENDENCIES) $(EXTRA_cally_atktext_example_DEPENDENCIES) + @rm -f cally-atktext-example$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(cally_atktext_example_OBJECTS) $(cally_atktext_example_LDADD) $(LIBS) + +cally-clone-example$(EXEEXT): $(cally_clone_example_OBJECTS) $(cally_clone_example_DEPENDENCIES) $(EXTRA_cally_clone_example_DEPENDENCIES) + @rm -f cally-clone-example$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(cally_clone_example_OBJECTS) $(cally_clone_example_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cally-atkcomponent-example.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cally-atkeditabletext-example.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cally-atkevents-example.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cally-atktext-example.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cally-clone-example.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cally-examples-util.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ + clean-checkPROGRAMS clean-generic clean-libtool cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/clutter/tests/accessibility/cally-atkcomponent-example.c b/clutter/tests/accessibility/cally-atkcomponent-example.c new file mode 100644 index 0000000..79a816b --- /dev/null +++ b/clutter/tests/accessibility/cally-atkcomponent-example.c @@ -0,0 +1,94 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2009 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * 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. + */ + +#include + +#include "cally-examples-util.h" + +#define WIDTH 300 +#define HEIGHT 300 +#define SIZE 50 +#define DEPTH -100 + +int +main (int argc, char *argv[]) +{ + ClutterActor *stage = NULL; + ClutterActor *button1 = NULL; + ClutterActor *button2 = NULL; + ClutterActor *button3 = NULL; + ClutterActor *button4 = NULL; + ClutterActor *group[4]; + int i = 0; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + cally_util_a11y_init (&argc, &argv); + + stage = clutter_stage_new (); + + clutter_stage_set_title (CLUTTER_STAGE (stage), "Cally - AtkComponent Test"); + clutter_stage_set_color (CLUTTER_STAGE (stage), CLUTTER_COLOR_White); + clutter_actor_set_size (stage, WIDTH, HEIGHT); + + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + button1 = clutter_rectangle_new_with_color (CLUTTER_COLOR_Yellow); + clutter_actor_set_size (button1, SIZE, SIZE); + + button2 = clutter_rectangle_new_with_color (CLUTTER_COLOR_Green); + clutter_actor_set_position (button2, 2 * SIZE, 0); + clutter_actor_set_size (button2, SIZE, SIZE); + + button3 = clutter_rectangle_new_with_color (CLUTTER_COLOR_Blue); + clutter_actor_set_position (button3, 0, 2 * SIZE); + clutter_actor_set_size (button3, SIZE, SIZE); + clutter_actor_set_depth( button3, DEPTH); + + /* a nested hierarchy, to check that the relative positions are + computed properly */ + button4 = clutter_rectangle_new_with_color (CLUTTER_COLOR_Magenta); + clutter_actor_set_position (button4, SIZE / 2, SIZE / 2); + clutter_actor_set_size (button4, SIZE, SIZE); + + for (i = 0; i < 4; i++) { + group[i] = clutter_group_new (); + clutter_actor_set_position (group[i], SIZE / 2, SIZE / 2); + clutter_actor_set_size (group[i], SIZE, SIZE); + + if (i > 0) + clutter_container_add_actor (CLUTTER_CONTAINER (group[i]), group [i - 1]); + } + + clutter_container_add_actor (CLUTTER_CONTAINER (stage), button1); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), button2); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), button3); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), group[3]); + clutter_container_add_actor (CLUTTER_CONTAINER (group[0]), button4); + + clutter_actor_show (stage); + + clutter_main (); + + return 0; +} diff --git a/clutter/tests/accessibility/cally-atkeditabletext-example.c b/clutter/tests/accessibility/cally-atkeditabletext-example.c new file mode 100644 index 0000000..433ee92 --- /dev/null +++ b/clutter/tests/accessibility/cally-atkeditabletext-example.c @@ -0,0 +1,268 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2009 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * 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. + */ + +#include +#include + +#include "cally-examples-util.h" + +#define WIDTH 800 +#define HEIGHT 600 + +static ClutterActor *text_actor = NULL; +static ClutterActor *text_editable_actor = NULL; + +/* + * Test AtkText interface + */ +static void +test_atk_text (ClutterActor *actor) +{ + AtkObject *object = NULL; + AtkEditableText *cally_editable_text = NULL; + gint pos = 0; + + object = atk_gobject_accessible_for_object (G_OBJECT (actor)); + cally_editable_text = ATK_EDITABLE_TEXT (object); + + if (cally_editable_text != NULL) { + atk_editable_text_set_text_contents (cally_editable_text, "New text"); + atk_editable_text_delete_text (cally_editable_text, 0, 3); + pos = 3; + atk_editable_text_insert_text (cally_editable_text, "New", 0, &pos); + + /* Not implemented in cally, just checking that we can call this + functions */ + atk_editable_text_copy_text (cally_editable_text, 0, -1); + atk_editable_text_paste_text (cally_editable_text, 5); + atk_editable_text_cut_text (cally_editable_text, 0, -1); + } +} + +static gboolean +insert_text_press_cb (ClutterActor *actor, + ClutterButtonEvent *event, + gpointer data) +{ + AtkObject *object = NULL; + AtkEditableText *cally_editable_text = NULL; + gint pos = 0; + + object = atk_gobject_accessible_for_object (G_OBJECT (text_editable_actor)); + cally_editable_text = ATK_EDITABLE_TEXT (object); + + pos = 3; + atk_editable_text_insert_text (cally_editable_text, "New", 0, &pos); + + return TRUE; +} + +static gboolean +delete_text_press_cb (ClutterActor *actor, + ClutterButtonEvent *event, + gpointer data) +{ + AtkObject *object = NULL; + AtkEditableText *cally_editable_text = NULL; + + object = atk_gobject_accessible_for_object (G_OBJECT (text_editable_actor)); + cally_editable_text = ATK_EDITABLE_TEXT (object); + + atk_editable_text_delete_text (cally_editable_text, 0, 3); + + return TRUE; +} + +static gboolean +set_text_press_cb (ClutterActor *actor, + ClutterButtonEvent *event, + gpointer data) +{ + AtkObject *object = NULL; + AtkEditableText *cally_editable_text = NULL; + + object = atk_gobject_accessible_for_object (G_OBJECT (text_editable_actor)); + cally_editable_text = ATK_EDITABLE_TEXT (object); + + atk_editable_text_set_text_contents (cally_editable_text, "New text"); + + return TRUE; +} + +static gboolean +activate_deactivate_press_cb (ClutterActor *actor, + ClutterButtonEvent *event, + gpointer data) +{ + gboolean active = FALSE; + + active = clutter_text_get_activatable (CLUTTER_TEXT (text_editable_actor)); + clutter_text_set_activatable (CLUTTER_TEXT (text_editable_actor), !active); + + return TRUE; +} + +static gboolean +print_cursor_position_press_cb (ClutterActor *actor, + ClutterButtonEvent *event, + gpointer data) +{ + gint pos = 0; + + pos = clutter_text_get_cursor_position (CLUTTER_TEXT (text_editable_actor)); + + g_print ("current cursor position %i\n", pos); + + return TRUE; +} + +static void +activate_cb (ClutterActor *actor, + gpointer data) +{ + g_print ("Actor activated\n"); +} + +static ClutterActor* +_create_button (const gchar *text) +{ + ClutterActor *button = NULL; + ClutterActor *rectangle = NULL; + ClutterActor *label = NULL; + + button = clutter_group_new (); + rectangle = clutter_rectangle_new_with_color (CLUTTER_COLOR_Magenta); + clutter_actor_set_size (rectangle, 375, 35); + + label = clutter_text_new_full ("Sans Bold 32px", + text, + CLUTTER_COLOR_Black); + clutter_container_add_actor (CLUTTER_CONTAINER (button), rectangle); + clutter_container_add_actor (CLUTTER_CONTAINER (button), label); + clutter_actor_set_reactive (button, TRUE); + + return button; +} + +static void +make_ui (ClutterActor *stage) +{ + ClutterActor *button = NULL; + + clutter_stage_set_title (CLUTTER_STAGE (stage), "Cally - AtkEditable Test"); + clutter_stage_set_color (CLUTTER_STAGE (stage), CLUTTER_COLOR_White); + clutter_actor_set_size (stage, WIDTH, HEIGHT); + + /* text */ + text_actor = clutter_text_new_full ("Sans Bold 32px", + "Lorem ipsum dolor sit amet", + CLUTTER_COLOR_Red); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), text_actor); + + /* text_editable */ + text_editable_actor = clutter_text_new_full ("Sans Bold 32px", + "consectetur adipisicing elit", + CLUTTER_COLOR_Red); + clutter_actor_set_position (text_editable_actor, 0, 100); + clutter_text_set_editable (CLUTTER_TEXT (text_editable_actor), TRUE); + clutter_text_set_selectable (CLUTTER_TEXT (text_editable_actor), TRUE); + clutter_text_set_selection_color (CLUTTER_TEXT (text_editable_actor), + CLUTTER_COLOR_Green); + clutter_text_set_activatable (CLUTTER_TEXT (text_editable_actor), + TRUE); + clutter_text_set_line_wrap (CLUTTER_TEXT (text_editable_actor), TRUE); + clutter_actor_grab_key_focus (text_editable_actor); + clutter_actor_set_reactive (text_editable_actor, TRUE); + + clutter_container_add_actor (CLUTTER_CONTAINER (stage), text_editable_actor); + g_signal_connect (text_editable_actor, "activate", + G_CALLBACK (activate_cb), NULL); + + /* test buttons */ + button = _create_button ("Set"); + clutter_actor_set_position (button, 100, 200); + + g_signal_connect_after (button, "button-press-event", + G_CALLBACK (set_text_press_cb), NULL); + + clutter_container_add_actor (CLUTTER_CONTAINER (stage), button); + + button = _create_button ("Delete"); + clutter_actor_set_position (button, 100, 250); + + g_signal_connect_after (button, "button-press-event", + G_CALLBACK (delete_text_press_cb), NULL); + + clutter_container_add_actor (CLUTTER_CONTAINER (stage), button); + + button = _create_button ("Insert"); + clutter_actor_set_position (button, 100, 300); + + g_signal_connect_after (button, "button-press-event", + G_CALLBACK (insert_text_press_cb), NULL); + + clutter_container_add_actor (CLUTTER_CONTAINER (stage), button); + + button = _create_button ("Activate/Deactivate"); + clutter_actor_set_position (button, 100, 350); + + g_signal_connect_after (button, "button-press-event", + G_CALLBACK (activate_deactivate_press_cb), NULL); + + clutter_container_add_actor (CLUTTER_CONTAINER (stage), button); + + button = _create_button ("Cursor position"); + clutter_actor_set_position (button, 100, 450); + + g_signal_connect_after (button, "button-press-event", + G_CALLBACK (print_cursor_position_press_cb), NULL); + + clutter_container_add_actor (CLUTTER_CONTAINER (stage), button); + +} + +int +main (int argc, char *argv[]) +{ + ClutterActor *stage = NULL; + + g_set_application_name ("AtkEditableText"); + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + cally_util_a11y_init (&argc, &argv); + + stage = clutter_stage_new (); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + make_ui (stage); + + clutter_actor_show_all (stage); + + test_atk_text (text_actor); + test_atk_text (text_editable_actor); + + clutter_main (); + + return 0; +} diff --git a/clutter/tests/accessibility/cally-atkevents-example.c b/clutter/tests/accessibility/cally-atkevents-example.c new file mode 100644 index 0000000..6740cb8 --- /dev/null +++ b/clutter/tests/accessibility/cally-atkevents-example.c @@ -0,0 +1,196 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2009 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * 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. + */ + +/* + * The purpose of this example is test key event and global event + * implementation, specifically: + * + * atk_add_global_event_listener + * atk_remove_global_event_listener + * atk_add_key_event_listener + * atk_remove_key_event_listener + */ +#include +#include +#include + +#include "cally-examples-util.h" + +#define WIDTH 800 +#define HEIGHT 600 +#define HEIGHT_STEP 100 +#define NUM_ENTRIES 3 + +struct _Data{ + gint value; +}; +typedef struct _Data Data; + +static gboolean +atk_key_listener (AtkKeyEventStruct *event, gpointer data) +{ + Data *my_data = (Data*) data; + + g_print ("atk_listener: 0x%x ", event->keyval); + + if (my_data != NULL) { + g_print ("\t Data value: %i\n", my_data->value); + } else { + g_print ("\tNo data!!\n"); + } + + return FALSE; +} + +static gboolean +window_event_listener (GSignalInvocationHint * signal_hint, + guint n_param_values, + const GValue * param_values, gpointer data) +{ + AtkObject *accessible; + GSignalQuery signal_query; + const gchar *name, *s; + + g_signal_query (signal_hint->signal_id, &signal_query); + name = signal_query.signal_name; + + accessible = ATK_OBJECT (g_value_get_object (¶m_values[0])); + s = atk_object_get_name (accessible); + + g_print ("Detected window event \"%s\" from object \"%p\" named \"%s\"\n", + name, accessible, s); + + return TRUE; +} +static void +make_ui (ClutterActor *stage) +{ + gint i = 0; + ClutterActor *editable = NULL; + ClutterActor *rectangle = NULL; + ClutterActor *label = NULL; + ClutterColor color_sel = { 0x00, 0xff, 0x00, 0x55 }; + ClutterColor color_label = { 0x00, 0xff, 0x55, 0xff }; + ClutterColor color_rect = { 0x00, 0xff, 0xff, 0x55 }; + float label_geom_y, editable_geom_y; + + clutter_stage_set_color (CLUTTER_STAGE (stage), CLUTTER_COLOR_White); + clutter_actor_set_size (stage, WIDTH, HEIGHT); + + label_geom_y = 50; + editable_geom_y = 50; + + for (i = 0; i < NUM_ENTRIES; i++) + { + /* label */ + label = clutter_text_new_full ("Sans Bold 32px", + "Entry", + &color_label); + clutter_actor_set_position (label, 0, label_geom_y); + + /* editable */ + editable = clutter_text_new_full ("Sans Bold 32px", + "ddd", + CLUTTER_COLOR_Red); + clutter_actor_set_position (editable, 150, editable_geom_y); + clutter_actor_set_size (editable, 500, 75); + clutter_text_set_editable (CLUTTER_TEXT (editable), TRUE); + clutter_text_set_selectable (CLUTTER_TEXT (editable), TRUE); + clutter_text_set_selection_color (CLUTTER_TEXT (editable), + &color_sel); + clutter_actor_grab_key_focus (editable); + clutter_actor_set_reactive (editable, TRUE); + + /* rectangle: to create a entry "feeling" */ + rectangle = clutter_rectangle_new_with_color (&color_rect); + clutter_actor_set_position (rectangle, 150, editable_geom_y); + clutter_actor_set_size (rectangle, 500, 75); + + clutter_container_add_actor (CLUTTER_CONTAINER (stage), label); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), editable); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), rectangle); + + label_geom_y += HEIGHT_STEP; + editable_geom_y += HEIGHT_STEP; + } +} + +int +main (int argc, char *argv[]) +{ + ClutterActor *stage, *stage_main; + Data data1, data2, data3; + guint id_1 = 0, id_2 = 0, id_3 = 0; + + g_set_application_name ("AtkText"); + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + if (cally_util_a11y_init (&argc, &argv) == FALSE) + { + g_error ("This example requires the accessibility support, " + "especifically AtkUtil implementation loaded, " + "as it tries to register and remove event listeners"); + } + + data1.value = 10; + data2.value = 20; + data3.value = 30; + + /* key event listeners */ + id_1 = atk_add_key_event_listener ((AtkKeySnoopFunc)atk_key_listener, &data1); + atk_remove_key_event_listener (id_1); + id_2 = atk_add_key_event_listener ((AtkKeySnoopFunc)atk_key_listener, &data2); + id_3 = atk_add_key_event_listener ((AtkKeySnoopFunc)atk_key_listener, &data3); + + atk_remove_key_event_listener (id_2); + + g_print ("key event listener ids registered: (%i, %i, %i)\n", id_1, id_2, id_3); + + /* event listeners */ + atk_add_global_event_listener (window_event_listener, "Atk:AtkWindow:create"); + atk_add_global_event_listener (window_event_listener, "Atk:AtkWindow:destroy"); + atk_add_global_event_listener (window_event_listener, "Atk:AtkWindow:activate"); + atk_add_global_event_listener (window_event_listener, "Atk:AtkWindow:deactivate"); + + stage_main = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage_main), "Cally - AtkEvents/1"); + g_signal_connect (stage_main, "destroy", G_CALLBACK (clutter_main_quit), NULL); + make_ui (stage_main); + + clutter_actor_show_all (stage_main); + + if (clutter_feature_available (CLUTTER_FEATURE_STAGE_MULTIPLE)) + { + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Cally - AtkEvents/2"); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + make_ui (stage); + clutter_actor_show_all (stage); + } + + clutter_main (); + + return 0; +} diff --git a/clutter/tests/accessibility/cally-atktext-example.c b/clutter/tests/accessibility/cally-atktext-example.c new file mode 100644 index 0000000..f7218ce --- /dev/null +++ b/clutter/tests/accessibility/cally-atktext-example.c @@ -0,0 +1,268 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2009 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * 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. + */ + +#include +#include + +#include "cally-examples-util.h" + +#define WIDTH 800 +#define HEIGHT 600 + +static ClutterActor *text_actor = NULL; +static ClutterActor *text_editable_actor = NULL; + +/* + * Test AtkText interface + */ +static void +test_atk_text (ClutterActor *actor) +{ + gchar *text = NULL; + AtkObject *object = NULL; + AtkText *cally_text = NULL; + gboolean bool = FALSE; + gunichar unichar; + gint count = -1; + gint start = -1; + gint end = -1; + gint pos = -1; + AtkAttributeSet *at_set = NULL; + GSList *attrs; + gchar *buf; + gint x, y, width, height; + + object = atk_gobject_accessible_for_object (G_OBJECT (actor)); + cally_text = ATK_TEXT (object); + + if (!cally_text) + return; + + text = atk_text_get_text (cally_text, 0, -1); + g_print ("atk_text_get_text output: %s\n", text); + + unichar = atk_text_get_character_at_offset (cally_text, 5); + buf = g_ucs4_to_utf8 (&unichar, 1, NULL, NULL, NULL); + g_print ("atk_text_get_character_at_offset(5): '%s' vs '%c'\n", buf, text[5]); + g_free (text); text = NULL; + g_free (buf); buf = NULL; + + text = atk_text_get_text_before_offset (cally_text, + 5, ATK_TEXT_BOUNDARY_WORD_END, + &start, &end); + g_print ("atk_text_get_text_before_offset: %s, %i, %i\n", + text, start, end); + g_free (text); text = NULL; + + text = atk_text_get_text_at_offset (cally_text, + 5, ATK_TEXT_BOUNDARY_WORD_END, + &start, &end); + g_print ("atk_text_get_text_at_offset: %s, %i, %i\n", + text, start, end); + g_free (text); text = NULL; + + text = atk_text_get_text_after_offset (cally_text, + 5, ATK_TEXT_BOUNDARY_WORD_END, + &start, &end); + g_print ("atk_text_get_text_after_offset: %s, %i, %i\n", + text, start, end); + g_free (text); text = NULL; + + pos = atk_text_get_caret_offset (cally_text); + g_print ("atk_text_get_caret_offset: %i\n", pos); + + atk_text_set_caret_offset (cally_text, 5); + + count = atk_text_get_character_count (cally_text); + g_print ("atk_text_get_character_count: %i\n", count); + + count = atk_text_get_n_selections (cally_text); + g_print ("atk_text_get_n_selections: %i\n", count); + + text = atk_text_get_selection (cally_text, 0, &start, &end); + g_print ("atk_text_get_selection: %s, %i, %i\n", text, start, end); + g_free(text); text = NULL; + + bool = atk_text_remove_selection (cally_text, 0); + g_print ("atk_text_remove_selection (0): %i\n", bool); + + bool = atk_text_remove_selection (cally_text, 1); + g_print ("atk_text_remove_selection (1): %i\n", bool); + + bool = atk_text_add_selection (cally_text, 5, 10); + g_print ("atk_text_add_selection: %i\n", bool); + + bool = atk_text_set_selection (cally_text, 0, 6, 10); + g_print ("atk_text_set_selection: %i\n", bool); + + at_set = atk_text_get_run_attributes (cally_text, 0, + &start, &end); + g_print ("atk_text_get_run_attributes: %i, %i\n", start, end); + attrs = (GSList*) at_set; + while (attrs) + { + AtkAttribute *at = (AtkAttribute *) attrs->data; + g_print ("text run %s = %s\n", at->name, at->value); + attrs = g_slist_next (attrs); + } + + atk_text_get_character_extents (cally_text, 0, &x, &y, &width, &height, + ATK_XY_WINDOW); + g_print ("atk_text_get_character_extents (0, window): x=%i y=%i width=%i height=%i\n", + x, y, width, height); + + atk_text_get_character_extents (cally_text, 0, &x, &y, &width, &height, + ATK_XY_SCREEN); + g_print ("atk_text_get_character_extents (0, screen): x=%i y=%i width=%i height=%i\n", + x, y, width, height); + + pos = atk_text_get_offset_at_point (cally_text, 200, 10, ATK_XY_WINDOW); + g_print ("atk_text_get_offset_at_point (200, 10, window): %i\n", pos); + + pos = atk_text_get_offset_at_point (cally_text, 200, 100, ATK_XY_SCREEN); + g_print ("atk_text_get_offset_at_point (200, 100, screen): %i\n", pos); + +} + +static void +dump_actor_default_atk_attributes (ClutterActor *actor) +{ + AtkObject *object = NULL; + AtkText *cally_text = NULL; + AtkAttributeSet *at_set = NULL; + GSList *attrs; + const gchar *text_value = NULL; + + object = atk_gobject_accessible_for_object (G_OBJECT (actor)); + cally_text = ATK_TEXT (object); + + if (!cally_text) + return; + + text_value = clutter_text_get_text (CLUTTER_TEXT (actor)); + g_print ("text value = %s\n", text_value); + + at_set = atk_text_get_default_attributes (cally_text); + attrs = (GSList*) at_set; + while (attrs) { + AtkAttribute *at = (AtkAttribute *) attrs->data; + g_print ("text default %s = %s\n", at->name, at->value); + attrs = g_slist_next (attrs); + } +} + +static gboolean +button_press_cb (ClutterActor *actor, + ClutterButtonEvent *event, + gpointer data) +{ + test_atk_text (text_actor); + test_atk_text (text_editable_actor); + + return TRUE; +} + +static void +make_ui (ClutterActor *stage) +{ + ClutterColor color_stage = { 0x00, 0x00, 0x00, 0xff }; + ClutterColor color_text = { 0xff, 0x00, 0x00, 0xff }; + ClutterColor color_sel = { 0x00, 0xff, 0x00, 0x55 }; + ClutterColor color_rect = { 0x00, 0xff, 0xff, 0xff }; + ClutterColor color_label = { 0x00, 0x00, 0x00, 0xff }; + ClutterActor *button = NULL; + ClutterActor *rectangle = NULL; + ClutterActor *label = NULL; + + clutter_stage_set_color (CLUTTER_STAGE (stage), &color_stage); + clutter_actor_set_size (stage, WIDTH, HEIGHT); + + /* text */ + text_actor = clutter_text_new_full ("Sans Bold 32px", + "", + &color_text); + clutter_text_set_markup (CLUTTER_TEXT(text_actor), + "Lorem ipsum dolor sit amet"); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), text_actor); + dump_actor_default_atk_attributes (text_actor); + + /* text_editable */ + text_editable_actor = clutter_text_new_full ("Sans Bold 32px", + "consectetur adipisicing elit", + &color_text); + clutter_actor_set_position (text_editable_actor, 20, 100); + clutter_text_set_editable (CLUTTER_TEXT (text_editable_actor), TRUE); + clutter_text_set_selectable (CLUTTER_TEXT (text_editable_actor), TRUE); + clutter_text_set_selection_color (CLUTTER_TEXT (text_editable_actor), + &color_sel); + clutter_text_set_line_wrap (CLUTTER_TEXT (text_editable_actor), TRUE); + clutter_actor_grab_key_focus (text_editable_actor); + clutter_actor_set_reactive (text_editable_actor, TRUE); + dump_actor_default_atk_attributes (text_editable_actor); + + clutter_container_add_actor (CLUTTER_CONTAINER (stage), text_editable_actor); + + /* test button */ + button = clutter_group_new (); + rectangle = clutter_rectangle_new_with_color (&color_rect); + clutter_actor_set_size (rectangle, 75, 35); + + label = clutter_text_new_full ("Sans Bold 32px", + "Test", &color_label); + clutter_actor_set_position (button, 100, 200); + clutter_container_add_actor (CLUTTER_CONTAINER (button), rectangle); + clutter_container_add_actor (CLUTTER_CONTAINER (button), label); + clutter_actor_set_reactive (button, TRUE); + + g_signal_connect_after (button, "button-press-event", + G_CALLBACK (button_press_cb), NULL); + + clutter_container_add_actor (CLUTTER_CONTAINER (stage), button); +} + +int +main (int argc, char *argv[]) +{ + ClutterActor *stage; + + g_set_application_name ("AtkText"); + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + cally_util_a11y_init (&argc, &argv); + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Cally - AtkText Test"); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + make_ui (stage); + + clutter_actor_show_all (stage); + + test_atk_text (text_actor); + test_atk_text (text_editable_actor); + + clutter_main (); + + return 0; +} diff --git a/clutter/tests/accessibility/cally-clone-example.c b/clutter/tests/accessibility/cally-clone-example.c new file mode 100644 index 0000000..9cc2d68 --- /dev/null +++ b/clutter/tests/accessibility/cally-clone-example.c @@ -0,0 +1,116 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2009 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * 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. + */ + +#include +#include + +#include "cally-examples-util.h" + +#define WIDTH 800 +#define HEIGHT 600 +#define HEIGHT_STEP 100 +#define NUM_ENTRIES 3 + +static void +make_ui (ClutterActor *stage) +{ + ClutterActor *editable = NULL; + ClutterActor *rectangle = NULL; + ClutterActor *label = NULL; + ClutterColor color_stage = { 0x00, 0x00, 0x00, 0xff }; + ClutterColor color_text = { 0xff, 0x00, 0x00, 0xff }; + ClutterColor color_sel = { 0x00, 0xff, 0x00, 0x55 }; + ClutterColor color_label = { 0x00, 0xff, 0x55, 0xff }; + ClutterColor color_rect = { 0x00, 0xff, 0xff, 0x55 }; + ClutterActor *full_entry = NULL; + ClutterActor *cloned_entry = NULL; + + + clutter_stage_set_color (CLUTTER_STAGE (stage), &color_stage); + clutter_actor_set_size (stage, WIDTH, HEIGHT); + + label = clutter_text_new_full ("Sans Bold 32px", + "Entry", + &color_label); + clutter_actor_set_position (label, 0, 50); + + /* editable */ + editable = clutter_text_new_full ("Sans Bold 32px", + "ddd", + &color_text); + clutter_actor_set_position (editable, 150, 50); + clutter_text_set_editable (CLUTTER_TEXT (editable), TRUE); + clutter_text_set_selectable (CLUTTER_TEXT (editable), TRUE); + clutter_text_set_selection_color (CLUTTER_TEXT (editable), + &color_sel); + clutter_actor_grab_key_focus (editable); + clutter_actor_set_reactive (editable, TRUE); + + /* rectangle: to create a entry "feeling" */ + rectangle = clutter_rectangle_new_with_color (&color_rect); + clutter_actor_set_position (rectangle, 150, 50); + clutter_actor_add_constraint (rectangle, clutter_bind_constraint_new (editable, CLUTTER_BIND_SIZE, 0)); + + full_entry = clutter_group_new (); + clutter_actor_set_position (full_entry, 0, 50); + clutter_actor_set_size (full_entry, 100, 75); + clutter_container_add_actor (CLUTTER_CONTAINER (full_entry), label); + clutter_container_add_actor (CLUTTER_CONTAINER (full_entry), editable); + clutter_container_add_actor (CLUTTER_CONTAINER (full_entry), rectangle); + clutter_actor_show_all (full_entry); + clutter_actor_set_scale (full_entry, 2, 1); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), full_entry); + + /* Cloning! */ + cloned_entry = clutter_clone_new (full_entry); + clutter_actor_set_position (cloned_entry, 50, 200); + clutter_actor_set_scale (cloned_entry, 1, 2); + clutter_actor_show_all (cloned_entry); + clutter_actor_set_reactive (cloned_entry, TRUE); + + clutter_container_add_actor (CLUTTER_CONTAINER (stage), cloned_entry); +} + +int +main (int argc, char *argv[]) +{ + ClutterActor *stage; + + g_set_application_name ("Clone Example"); + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + cally_util_a11y_init (&argc, &argv); + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Cally - Clone Test"); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + make_ui (stage); + + clutter_actor_show_all (stage); + + clutter_main (); + + return 0; +} diff --git a/clutter/tests/accessibility/cally-examples-util.c b/clutter/tests/accessibility/cally-examples-util.c new file mode 100644 index 0000000..ea3e31a --- /dev/null +++ b/clutter/tests/accessibility/cally-examples-util.c @@ -0,0 +1,146 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2009 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * 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. + */ + + +#include +#include + +#include + +#include "cally-examples-util.h" + +/* Checking the at-spi sources, the module directory is + * $(libdir)/gtk-2.0/modules + * + * It is supposed cally would be installed on the same libdir. + * + * You could use the option atk-bridge-dir to use other directory. + */ +#define ATK_BRIDGE_DEFAULT_MODULE_DIRECTORY PREFIXDIR"/gtk-2.0/modules" + +static gchar * +_search_for_bridge_module (const gchar *module_name) +{ + /* We simplify the search for the atk bridge, see see the definition + * of the macro for more information*/ + return g_strdup (ATK_BRIDGE_DEFAULT_MODULE_DIRECTORY); +} + +static gchar* +_a11y_check_custom_bridge (int *argc, + char ***argv) +{ + GError *error = NULL; + GOptionContext *context; + static gchar *bridge_dir = NULL; + static GOptionEntry entries [] = + { + {"atk-bridge-dir", 'd', 0, G_OPTION_ARG_STRING, &bridge_dir, "atk-bridge module directory", NULL} + }; + + context = g_option_context_new ("- cally examples"); + g_option_context_add_main_entries (context, entries, NULL); + if (!g_option_context_parse (context, argc, argv, &error)) + { + g_print ("%s\n", error->message); + g_print ("Use --help for more information.\n"); + exit (0); + } + + return bridge_dir; +} + + +static gboolean +_a11y_invoke_module (const gchar *module_path, + gboolean init) +{ + GModule *handle; + void (*invoke_fn) (void); + const char *method; + + if (init) + method = "gnome_accessibility_module_init"; + else + method = "gnome_accessibility_module_shutdown"; + + if (!module_path) + return FALSE; + + if (!(handle = g_module_open (module_path, G_MODULE_BIND_LAZY))) + { + g_warning ("Accessibility: failed to load module '%s': '%s'", + module_path, g_module_error ()); + + return FALSE; + } + + if (!g_module_symbol (handle, method, (gpointer *)&invoke_fn)) + { + g_warning ("Accessibility: error library '%s' does not include " + "method '%s' required for accessibility support", + module_path, method); + g_module_close (handle); + + return FALSE; + } + + g_debug ("Module %s loaded successfully", module_path); + invoke_fn (); + + return TRUE; +} + +/** + * This method will initialize the accessibility support provided by cally. + * + * Basically it will load the cally module using gmodule functions. + * + * Returns if it was able to init the a11y support or not. + */ +gboolean +cally_util_a11y_init (int *argc, char ***argv) +{ + gchar *bridge_dir = NULL; + gchar *bridge_path = NULL; + gboolean result = FALSE; + + if (clutter_get_accessibility_enabled () == FALSE) + { + g_warning ("Accessibility: clutter has no accessibility enabled" + " skipping the atk-bridge load"); + return FALSE; + } + + bridge_dir = _a11y_check_custom_bridge (argc, argv); + if (bridge_dir == NULL) + bridge_dir = _search_for_bridge_module ("atk-bridge"); + + bridge_path = g_module_build_path (bridge_dir, "libatk-bridge"); + + result = _a11y_invoke_module (bridge_path, TRUE); + + g_free (bridge_dir); + g_free (bridge_path); + + return result; +} diff --git a/clutter/tests/accessibility/cally-examples-util.h b/clutter/tests/accessibility/cally-examples-util.h new file mode 100644 index 0000000..dab5926 --- /dev/null +++ b/clutter/tests/accessibility/cally-examples-util.h @@ -0,0 +1,24 @@ +/* CALLY - The Clutter Accessibility Implementation Library + * + * Copyright (C) 2009 Igalia, S.L. + * + * Author: Alejandro Piñeiro Iglesias + * + * 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. + */ + +gboolean +cally_util_a11y_init (int *argc, char ***argv); diff --git a/clutter/tests/clutter-1.0.suppressions b/clutter/tests/clutter-1.0.suppressions new file mode 100644 index 0000000..f47498d --- /dev/null +++ b/clutter/tests/clutter-1.0.suppressions @@ -0,0 +1,173 @@ +{ + ioctl_1 + Memcheck:Param + ioctl(generic) + fun:ioctl + fun:driDrawableInitVBlank + fun:intelMakeCurrent + fun:glXMakeContextCurrent +} + +{ + ioctl_2 + Memcheck:Param + ioctl(generic) + fun:ioctl + fun:driDrawableGetMSC32 + fun:clutter_backend_glx_redraw +} + +{ + ioctl_3 + Memcheck:Param + ioctl(generic) + fun:ioctl + fun:driWaitForMSC32 + fun:clutter_backend_glx_redraw +} + +{ + mesa_init_context + Memcheck:Leak + fun:*alloc + ... + fun:glXCreateNewContext +} + +{ + type_register + Memcheck:Leak + fun:*alloc + ... + fun:g_type_register_* +} + +{ + type_ref + Memcheck:Leak + fun:*alloc + ... + fun:g_type_class_ref +} + +{ + type_interface_prereq + Memcheck:Leak + fun:*alloc + ... + fun:g_type_interface_add_prerequisite +} + +{ + get_charset + Memcheck:Leak + fun:*alloc + ... + fun:g_get_charset +} + +{ + cogl_features + Memcheck:Leak + fun:*alloc + ... + fun:cogl_get_features +} + +{ + glx_query_version + Memcheck:Leak + fun:*alloc + ... + fun:glXQueryVersion +} + +{ + glx_create_context + Memcheck:Leak + fun:*alloc + ... + fun:glXCreateNewContext +} + +{ + glx_make_current + Memcheck:Leak + fun:*alloc + ... + fun:glXMakeContextCurrent +} + +{ + gl_draw_arrays + Memcheck:Leak + fun:*malloc + ... + fun:glDrawArrays +} + +{ + cogl_clear + Memcheck:Leak + fun:*alloc + ... + fun:cogl_clear +} + +{ + default_font + Memcheck:Leak + fun:*alloc + ... + fun:clutter_backend_get_font_name +} + +{ + id_pool + Memcheck:Leak + fun:*alloc + ... + fun:clutter_id_pool_new +} + +{ + x_open_display + Memcheck:Leak + fun:*alloc + ... + fun:XOpenDisplay +} + +# ... and font descriptions from every "sans 12" type string +{ + pango_font_description_from_string + Memcheck:Leak + fun:*alloc + ... + fun:pango_font_description_from_string +} + +# other lib init +{ + fontconfig_init + Memcheck:Leak + fun:*alloc + ... + fun:FcConfigParseAndLoad +} + +{ + freetype_init + Memcheck:Leak + fun:*alloc + ... + fun:FT_Open_Face +} + +{ + x_init_ext + Memcheck:Leak + fun:*alloc + ... + fun:XInitExtension +} diff --git a/clutter/tests/conform/Makefile.am b/clutter/tests/conform/Makefile.am new file mode 100644 index 0000000..69e5dd4 --- /dev/null +++ b/clutter/tests/conform/Makefile.am @@ -0,0 +1,97 @@ +installed_test_metadir = $(datadir)/installed-tests/mutter-clutter +installed_testdir = $(libexecdir)/installed-tests/mutter-clutter +include $(top_srcdir)/build/autotools/glib-tap.mk + +AM_CFLAGS = -g $(CLUTTER_CFLAGS) $(MAINTAINER_CFLAGS) +LDADD = $(top_builddir)/../cogl/cogl/libmutter-cogl.la $(top_builddir)/clutter/libmutter-clutter-1.0.la $(CLUTTER_LIBS) $(LIBM) +AM_LDFLAGS = -export-dynamic +AM_CPPFLAGS = \ + -DG_LOG_DOMAIN=\"Clutter-Conform\" \ + -I$(top_srcdir)/../cogl \ + -I$(top_builddir)/../cogl \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + -DCOGL_DISABLE_DEPRECATION_WARNINGS \ + $(CLUTTER_DEPRECATED_CFLAGS) \ + $(CLUTTER_DEBUG_CFLAGS) + +# Basic actor API +actor_tests = \ + actor-anchors \ + actor-destroy \ + actor-graph \ + actor-invariants \ + actor-iter \ + actor-layout \ + actor-meta \ + actor-offscreen-limit-max-size \ + actor-offscreen-redirect \ + actor-paint-opacity \ + actor-pick \ + actor-shader-effect \ + actor-size \ + $(NULL) + +# Actor classes +classes_tests = \ + text \ + $(NULL) + +# General API +general_tests = \ + binding-pool \ + color \ + events-touch \ + interval \ + model \ + script-parser \ + units \ + $(NULL) + +# Test for deprecated functionality +deprecated_tests = \ + animator \ + behaviours \ + group \ + rectangle \ + texture \ + $(NULL) + +test_programs = $(actor_tests) $(general_tests) $(classes_tests) $(deprecated_tests) + +dist_test_data = $(script_ui_files) +script_ui_files = $(addprefix scripts/,$(script_tests)) +script_tests = \ + test-animator-1.json \ + test-animator-2.json \ + test-animator-3.json \ + test-script-animation.json \ + test-script-child.json \ + test-script-implicit-alpha.json \ + test-script-interval.json \ + test-script-layout-property.json \ + test-script-margin.json \ + test-script-model.json \ + test-script-named-object.json \ + test-script-object-property.json \ + test-script-single.json \ + test-script-timeline-markers.json \ + test-state-1.json + +TESTS_ENVIRONMENT += G_ENABLE_DIAGNOSTIC=0 CLUTTER_ENABLE_DIAGNOSTIC=0 + +# simple rules for generating a Git ignore file for the conformance test suite +$(srcdir)/.gitignore: Makefile + $(AM_V_GEN)( echo "/*.trs" ; \ + echo "/*.log" ; \ + echo "/*.test" ; \ + echo "/.gitignore" ; \ + for p in $(test_programs); do \ + echo "/$$p" ; \ + done ) > $(@F) + +gitignore: $(srcdir)/.gitignore + +all-am: gitignore + +DISTCLEANFILES += .gitignore diff --git a/clutter/tests/conform/Makefile.in b/clutter/tests/conform/Makefile.in new file mode 100644 index 0000000..47c91b7 --- /dev/null +++ b/clutter/tests/conform/Makefile.in @@ -0,0 +1,1955 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# GLIB - Library of useful C routines + + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +TESTS = $(am__EXEEXT_6) +installed_test_PROGRAMS = $(am__EXEEXT_9) +noinst_PROGRAMS = $(am__EXEEXT_10) +check_PROGRAMS = $(am__EXEEXT_8) +@ENABLE_ALWAYS_BUILD_TESTS_TRUE@am__append_1 = $(all_test_ltlibs) +@ENABLE_ALWAYS_BUILD_TESTS_TRUE@am__append_2 = $(all_test_programs) +@ENABLE_ALWAYS_BUILD_TESTS_TRUE@am__append_3 = $(all_test_scripts) +@ENABLE_ALWAYS_BUILD_TESTS_TRUE@am__append_4 = $(all_test_data) +@ENABLE_ALWAYS_BUILD_TESTS_FALSE@am__append_5 = $(all_test_ltlibs) +@ENABLE_ALWAYS_BUILD_TESTS_FALSE@am__append_6 = $(all_test_programs) +@ENABLE_ALWAYS_BUILD_TESTS_FALSE@am__append_7 = $(all_test_scripts) +@ENABLE_ALWAYS_BUILD_TESTS_FALSE@am__append_8 = $(all_test_data) +@ENABLE_INSTALLED_TESTS_TRUE@am__append_9 = $(test_programs) $(installed_test_programs) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(test_extra_programs) $(installed_test_extra_programs) + +@ENABLE_INSTALLED_TESTS_TRUE@am__append_10 = $(test_scripts) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(installed_test_scripts) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(test_extra_scripts) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(test_installed_extra_scripts) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(dist_test_scripts) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(dist_test_extra_scripts) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(dist_installed_test_scripts) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(dist_installed_test_extra_scripts) +@ENABLE_INSTALLED_TESTS_TRUE@am__append_11 = $(test_data) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(installed_test_data) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(dist_test_data) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(dist_installed_test_data) +@ENABLE_INSTALLED_TESTS_TRUE@am__append_12 = $(test_ltlibraries) $(installed_test_ltlibraries) +@ENABLE_INSTALLED_TESTS_TRUE@am__append_13 = $(installed_test_meta_DATA) +subdir = tests/conform +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/build/autotools/as-compiler-flag.m4 \ + $(top_srcdir)/build/autotools/glibtests.m4 \ + $(top_srcdir)/build/autotools/introspection.m4 \ + $(top_srcdir)/build/autotools/libtool.m4 \ + $(top_srcdir)/build/autotools/ltoptions.m4 \ + $(top_srcdir)/build/autotools/ltsugar.m4 \ + $(top_srcdir)/build/autotools/ltversion.m4 \ + $(top_srcdir)/build/autotools/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/clutter/clutter-build-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(installed_testdir)" \ + "$(DESTDIR)$(installed_testdir)" \ + "$(DESTDIR)$(installed_testdir)" \ + "$(DESTDIR)$(installed_test_metadir)" \ + "$(DESTDIR)$(installed_testdir)" +LTLIBRARIES = $(installed_test_LTLIBRARIES) $(noinst_LTLIBRARIES) +am__EXEEXT_1 = +am__EXEEXT_2 = actor-anchors$(EXEEXT) actor-destroy$(EXEEXT) \ + actor-graph$(EXEEXT) actor-invariants$(EXEEXT) \ + actor-iter$(EXEEXT) actor-layout$(EXEEXT) actor-meta$(EXEEXT) \ + actor-offscreen-limit-max-size$(EXEEXT) \ + actor-offscreen-redirect$(EXEEXT) actor-paint-opacity$(EXEEXT) \ + actor-pick$(EXEEXT) actor-shader-effect$(EXEEXT) \ + actor-size$(EXEEXT) $(am__EXEEXT_1) +am__EXEEXT_3 = binding-pool$(EXEEXT) color$(EXEEXT) \ + events-touch$(EXEEXT) interval$(EXEEXT) model$(EXEEXT) \ + script-parser$(EXEEXT) units$(EXEEXT) $(am__EXEEXT_1) +am__EXEEXT_4 = text$(EXEEXT) $(am__EXEEXT_1) +am__EXEEXT_5 = animator$(EXEEXT) behaviours$(EXEEXT) group$(EXEEXT) \ + rectangle$(EXEEXT) texture$(EXEEXT) $(am__EXEEXT_1) +am__EXEEXT_6 = $(am__EXEEXT_2) $(am__EXEEXT_3) $(am__EXEEXT_4) \ + $(am__EXEEXT_5) +am__EXEEXT_7 = $(am__EXEEXT_6) +@ENABLE_ALWAYS_BUILD_TESTS_FALSE@am__EXEEXT_8 = $(am__EXEEXT_7) +@ENABLE_INSTALLED_TESTS_TRUE@am__EXEEXT_9 = $(am__EXEEXT_6) +@ENABLE_ALWAYS_BUILD_TESTS_TRUE@am__EXEEXT_10 = $(am__EXEEXT_7) +PROGRAMS = $(installed_test_PROGRAMS) $(noinst_PROGRAMS) +actor_anchors_SOURCES = actor-anchors.c +actor_anchors_OBJECTS = actor-anchors.$(OBJEXT) +actor_anchors_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +actor_anchors_DEPENDENCIES = \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/clutter/libmutter-clutter-1.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +actor_destroy_SOURCES = actor-destroy.c +actor_destroy_OBJECTS = actor-destroy.$(OBJEXT) +actor_destroy_LDADD = $(LDADD) +actor_destroy_DEPENDENCIES = \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/clutter/libmutter-clutter-1.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +actor_graph_SOURCES = actor-graph.c +actor_graph_OBJECTS = actor-graph.$(OBJEXT) +actor_graph_LDADD = $(LDADD) +actor_graph_DEPENDENCIES = \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/clutter/libmutter-clutter-1.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +actor_invariants_SOURCES = actor-invariants.c +actor_invariants_OBJECTS = actor-invariants.$(OBJEXT) +actor_invariants_LDADD = $(LDADD) +actor_invariants_DEPENDENCIES = \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/clutter/libmutter-clutter-1.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +actor_iter_SOURCES = actor-iter.c +actor_iter_OBJECTS = actor-iter.$(OBJEXT) +actor_iter_LDADD = $(LDADD) +actor_iter_DEPENDENCIES = \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/clutter/libmutter-clutter-1.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +actor_layout_SOURCES = actor-layout.c +actor_layout_OBJECTS = actor-layout.$(OBJEXT) +actor_layout_LDADD = $(LDADD) +actor_layout_DEPENDENCIES = \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/clutter/libmutter-clutter-1.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +actor_meta_SOURCES = actor-meta.c +actor_meta_OBJECTS = actor-meta.$(OBJEXT) +actor_meta_LDADD = $(LDADD) +actor_meta_DEPENDENCIES = \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/clutter/libmutter-clutter-1.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +actor_offscreen_limit_max_size_SOURCES = \ + actor-offscreen-limit-max-size.c +actor_offscreen_limit_max_size_OBJECTS = \ + actor-offscreen-limit-max-size.$(OBJEXT) +actor_offscreen_limit_max_size_LDADD = $(LDADD) +actor_offscreen_limit_max_size_DEPENDENCIES = \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/clutter/libmutter-clutter-1.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +actor_offscreen_redirect_SOURCES = actor-offscreen-redirect.c +actor_offscreen_redirect_OBJECTS = actor-offscreen-redirect.$(OBJEXT) +actor_offscreen_redirect_LDADD = $(LDADD) +actor_offscreen_redirect_DEPENDENCIES = \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/clutter/libmutter-clutter-1.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +actor_paint_opacity_SOURCES = actor-paint-opacity.c +actor_paint_opacity_OBJECTS = actor-paint-opacity.$(OBJEXT) +actor_paint_opacity_LDADD = $(LDADD) +actor_paint_opacity_DEPENDENCIES = \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/clutter/libmutter-clutter-1.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +actor_pick_SOURCES = actor-pick.c +actor_pick_OBJECTS = actor-pick.$(OBJEXT) +actor_pick_LDADD = $(LDADD) +actor_pick_DEPENDENCIES = \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/clutter/libmutter-clutter-1.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +actor_shader_effect_SOURCES = actor-shader-effect.c +actor_shader_effect_OBJECTS = actor-shader-effect.$(OBJEXT) +actor_shader_effect_LDADD = $(LDADD) +actor_shader_effect_DEPENDENCIES = \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/clutter/libmutter-clutter-1.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +actor_size_SOURCES = actor-size.c +actor_size_OBJECTS = actor-size.$(OBJEXT) +actor_size_LDADD = $(LDADD) +actor_size_DEPENDENCIES = \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/clutter/libmutter-clutter-1.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +animator_SOURCES = animator.c +animator_OBJECTS = animator.$(OBJEXT) +animator_LDADD = $(LDADD) +animator_DEPENDENCIES = \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/clutter/libmutter-clutter-1.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +behaviours_SOURCES = behaviours.c +behaviours_OBJECTS = behaviours.$(OBJEXT) +behaviours_LDADD = $(LDADD) +behaviours_DEPENDENCIES = \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/clutter/libmutter-clutter-1.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +binding_pool_SOURCES = binding-pool.c +binding_pool_OBJECTS = binding-pool.$(OBJEXT) +binding_pool_LDADD = $(LDADD) +binding_pool_DEPENDENCIES = \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/clutter/libmutter-clutter-1.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +color_SOURCES = color.c +color_OBJECTS = color.$(OBJEXT) +color_LDADD = $(LDADD) +color_DEPENDENCIES = $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/clutter/libmutter-clutter-1.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +events_touch_SOURCES = events-touch.c +events_touch_OBJECTS = events-touch.$(OBJEXT) +events_touch_LDADD = $(LDADD) +events_touch_DEPENDENCIES = \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/clutter/libmutter-clutter-1.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +group_SOURCES = group.c +group_OBJECTS = group.$(OBJEXT) +group_LDADD = $(LDADD) +group_DEPENDENCIES = $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/clutter/libmutter-clutter-1.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +interval_SOURCES = interval.c +interval_OBJECTS = interval.$(OBJEXT) +interval_LDADD = $(LDADD) +interval_DEPENDENCIES = \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/clutter/libmutter-clutter-1.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +model_SOURCES = model.c +model_OBJECTS = model.$(OBJEXT) +model_LDADD = $(LDADD) +model_DEPENDENCIES = $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/clutter/libmutter-clutter-1.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +rectangle_SOURCES = rectangle.c +rectangle_OBJECTS = rectangle.$(OBJEXT) +rectangle_LDADD = $(LDADD) +rectangle_DEPENDENCIES = \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/clutter/libmutter-clutter-1.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +script_parser_SOURCES = script-parser.c +script_parser_OBJECTS = script-parser.$(OBJEXT) +script_parser_LDADD = $(LDADD) +script_parser_DEPENDENCIES = \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/clutter/libmutter-clutter-1.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +text_SOURCES = text.c +text_OBJECTS = text.$(OBJEXT) +text_LDADD = $(LDADD) +text_DEPENDENCIES = $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/clutter/libmutter-clutter-1.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +texture_SOURCES = texture.c +texture_OBJECTS = texture.$(OBJEXT) +texture_LDADD = $(LDADD) +texture_DEPENDENCIES = $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/clutter/libmutter-clutter-1.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +units_SOURCES = units.c +units_OBJECTS = units.$(OBJEXT) +units_LDADD = $(LDADD) +units_DEPENDENCIES = $(top_builddir)/../cogl/cogl/libmutter-cogl.la \ + $(top_builddir)/clutter/libmutter-clutter-1.0.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +SCRIPTS = $(installed_test_SCRIPTS) $(noinst_SCRIPTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/clutter +depcomp = $(SHELL) $(top_srcdir)/build/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = actor-anchors.c actor-destroy.c actor-graph.c \ + actor-invariants.c actor-iter.c actor-layout.c actor-meta.c \ + actor-offscreen-limit-max-size.c actor-offscreen-redirect.c \ + actor-paint-opacity.c actor-pick.c actor-shader-effect.c \ + actor-size.c animator.c behaviours.c binding-pool.c color.c \ + events-touch.c group.c interval.c model.c rectangle.c \ + script-parser.c text.c texture.c units.c +DIST_SOURCES = actor-anchors.c actor-destroy.c actor-graph.c \ + actor-invariants.c actor-iter.c actor-layout.c actor-meta.c \ + actor-offscreen-limit-max-size.c actor-offscreen-redirect.c \ + actor-paint-opacity.c actor-pick.c actor-shader-effect.c \ + actor-size.c animator.c behaviours.c binding-pool.c color.c \ + events-touch.c group.c interval.c model.c rectangle.c \ + script-parser.c text.c texture.c units.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(installed_test_meta_DATA) $(nobase_installed_test_DATA) \ + $(noinst_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red=''; \ + grn=''; \ + lgn=''; \ + blu=''; \ + mgn=''; \ + brg=''; \ + std=''; \ + fi; \ +} +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/build/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build/autotools/glib-tap.mk \ + $(top_srcdir)/build/depcomp $(top_srcdir)/build/test-driver +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ATK_REQ_VERSION = @ATK_REQ_VERSION@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_REQ_VERSION = @CAIRO_REQ_VERSION@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CLUTTER_API_VERSION = @CLUTTER_API_VERSION@ +CLUTTER_API_VERSION_AM = @CLUTTER_API_VERSION_AM@ +CLUTTER_BACKENDS = @CLUTTER_BACKENDS@ +CLUTTER_CFLAGS = @CLUTTER_CFLAGS@ +CLUTTER_COGL = @CLUTTER_COGL@ +CLUTTER_CONFIG_DEFINES = @CLUTTER_CONFIG_DEFINES@ +CLUTTER_DEBUG_CFLAGS = @CLUTTER_DEBUG_CFLAGS@ +CLUTTER_DEPRECATED_CFLAGS = @CLUTTER_DEPRECATED_CFLAGS@ +CLUTTER_DEPS_CFLAGS = @CLUTTER_DEPS_CFLAGS@ +CLUTTER_DEPS_LIBS = @CLUTTER_DEPS_LIBS@ +CLUTTER_DEPS_PRIVATE_CFLAGS = @CLUTTER_DEPS_PRIVATE_CFLAGS@ +CLUTTER_DEPS_PRIVATE_LIBS = @CLUTTER_DEPS_PRIVATE_LIBS@ +CLUTTER_FLAVOUR = @CLUTTER_FLAVOUR@ +CLUTTER_GCOV_CFLAGS = @CLUTTER_GCOV_CFLAGS@ +CLUTTER_GCOV_LDADD = @CLUTTER_GCOV_LDADD@ +CLUTTER_HIDDEN_VISIBILITY_CFLAGS = @CLUTTER_HIDDEN_VISIBILITY_CFLAGS@ +CLUTTER_INPUT_BACKENDS = @CLUTTER_INPUT_BACKENDS@ +CLUTTER_LIBS = @CLUTTER_LIBS@ +CLUTTER_LINK_FLAGS = @CLUTTER_LINK_FLAGS@ +CLUTTER_LT_CURRENT = @CLUTTER_LT_CURRENT@ +CLUTTER_LT_LDFLAGS = @CLUTTER_LT_LDFLAGS@ +CLUTTER_LT_REVISION = @CLUTTER_LT_REVISION@ +CLUTTER_LT_VERSION = @CLUTTER_LT_VERSION@ +CLUTTER_MAJOR_VERSION = @CLUTTER_MAJOR_VERSION@ +CLUTTER_MICRO_VERSION = @CLUTTER_MICRO_VERSION@ +CLUTTER_MINOR_VERSION = @CLUTTER_MINOR_VERSION@ +CLUTTER_RELEASE_STATUS = @CLUTTER_RELEASE_STATUS@ +CLUTTER_REQUIRES = @CLUTTER_REQUIRES@ +CLUTTER_REQUIRES_PRIVATE = @CLUTTER_REQUIRES_PRIVATE@ +CLUTTER_SONAME_INFIX = @CLUTTER_SONAME_INFIX@ +CLUTTER_STAGE_TYPE = @CLUTTER_STAGE_TYPE@ +CLUTTER_VERSION = @CLUTTER_VERSION@ +CLUTTER_WINSYS = @CLUTTER_WINSYS@ +CLUTTER_WINSYS_BASE = @CLUTTER_WINSYS_BASE@ +COGL_DRIVER = @COGL_DRIVER@ +COGL_REQ_VERSION = @COGL_REQ_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@ +GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@ +GDK_REQ_VERSION = @GDK_REQ_VERSION@ +GI_REQ_VERSION = @GI_REQ_VERSION@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQ_VERSION = @GLIB_REQ_VERSION@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +JSON_GLIB_REQ_VERSION = @JSON_GLIB_REQ_VERSION@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBINPUT_REQ_VERSION = @LIBINPUT_REQ_VERSION@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUDEV_REQ_VERSION = @LIBUDEV_REQ_VERSION@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTP = @LTP@ +LTP_GENHTML = @LTP_GENHTML@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINTAINER_CFLAGS = @MAINTAINER_CFLAGS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGO_REQ_VERSION = @PANGO_REQ_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SHTOOL = @SHTOOL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +XCOMPOSITE_REQ_VERSION = @XCOMPOSITE_REQ_VERSION@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +installed_test_metadir = $(datadir)/installed-tests/mutter-clutter +installed_testdir = $(libexecdir)/installed-tests/mutter-clutter +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +TESTS_ENVIRONMENT = G_TEST_SRCDIR="$(abs_srcdir)" \ + G_TEST_BUILDDIR="$(abs_builddir)" G_DEBUG=gc-friendly \ + MALLOC_CHECK_=2 MALLOC_PERTURB_=$$(($${RANDOM:-256} % 256)) \ + G_ENABLE_DIAGNOSTIC=0 CLUTTER_ENABLE_DIAGNOSTIC=0 +LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) $(top_srcdir)/build/autotools/tap-driver.sh +LOG_COMPILER = $(top_srcdir)/build/autotools/tap-test +NULL = + +# initialize variables for unconditional += appending +BUILT_SOURCES = +BUILT_EXTRA_DIST = +CLEANFILES = *.log *.trs $(am__append_13) +DISTCLEANFILES = .gitignore +MAINTAINERCLEANFILES = +EXTRA_DIST = $(all_dist_test_scripts) $(all_dist_test_data) +installed_test_LTLIBRARIES = $(am__append_12) +installed_test_SCRIPTS = $(am__append_10) +nobase_installed_test_DATA = $(am__append_11) +noinst_LTLIBRARIES = $(am__append_1) +noinst_SCRIPTS = $(am__append_3) +noinst_DATA = $(am__append_4) +check_LTLIBRARIES = $(am__append_5) +check_SCRIPTS = $(am__append_7) +check_DATA = $(am__append_8) + +# Note: build even the installed-only targets during 'make check' to ensure that they still work. +# We need to do a bit of trickery here and manage disting via EXTRA_DIST instead of using dist_ prefixes to +# prevent automake from mistreating gmake functions like $(wildcard ...) and $(addprefix ...) as if they were +# filenames, including removing duplicate instances of the opening part before the space, eg. '$(addprefix'. +all_test_programs = $(test_programs) $(uninstalled_test_programs) $(installed_test_programs) \ + $(test_extra_programs) $(uninstalled_test_extra_programs) $(installed_test_extra_programs) + +all_test_scripts = $(test_scripts) $(uninstalled_test_scripts) \ + $(installed_test_scripts) $(test_extra_scripts) \ + $(uninstalled_test_extra_scripts) \ + $(installed_test_extra_scripts) $(all_dist_test_scripts) +all_dist_test_scripts = $(dist_test_scripts) $(dist_uninstalled_test_scripts) $(dist_installed_test_scripts) \ + $(dist_test_extra_scripts) $(dist_uninstalled_test_extra_scripts) $(dist_installed_test_extra_scripts) + +all_test_data = $(test_data) $(uninstalled_test_data) \ + $(installed_test_data) $(all_dist_test_data) +all_dist_test_data = $(dist_test_data) $(dist_uninstalled_test_data) $(dist_installed_test_data) +all_test_ltlibs = $(test_ltlibraries) $(uninstalled_test_ltlibraries) $(installed_test_ltlibraries) +@ENABLE_INSTALLED_TESTS_TRUE@installed_testcases = $(test_programs) $(installed_test_programs) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(test_scripts) $(installed_test_scripts) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(dist_test_scripts) $(dist_installed_test_scripts) + +@ENABLE_INSTALLED_TESTS_TRUE@installed_test_meta_DATA = $(installed_testcases:=.test) +AM_CFLAGS = -g $(CLUTTER_CFLAGS) $(MAINTAINER_CFLAGS) +LDADD = $(top_builddir)/../cogl/cogl/libmutter-cogl.la $(top_builddir)/clutter/libmutter-clutter-1.0.la $(CLUTTER_LIBS) $(LIBM) +AM_LDFLAGS = -export-dynamic +AM_CPPFLAGS = \ + -DG_LOG_DOMAIN=\"Clutter-Conform\" \ + -I$(top_srcdir)/../cogl \ + -I$(top_builddir)/../cogl \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + -DCOGL_DISABLE_DEPRECATION_WARNINGS \ + $(CLUTTER_DEPRECATED_CFLAGS) \ + $(CLUTTER_DEBUG_CFLAGS) + + +# Basic actor API +actor_tests = \ + actor-anchors \ + actor-destroy \ + actor-graph \ + actor-invariants \ + actor-iter \ + actor-layout \ + actor-meta \ + actor-offscreen-limit-max-size \ + actor-offscreen-redirect \ + actor-paint-opacity \ + actor-pick \ + actor-shader-effect \ + actor-size \ + $(NULL) + + +# Actor classes +classes_tests = \ + text \ + $(NULL) + + +# General API +general_tests = \ + binding-pool \ + color \ + events-touch \ + interval \ + model \ + script-parser \ + units \ + $(NULL) + + +# Test for deprecated functionality +deprecated_tests = \ + animator \ + behaviours \ + group \ + rectangle \ + texture \ + $(NULL) + +test_programs = $(actor_tests) $(general_tests) $(classes_tests) $(deprecated_tests) +dist_test_data = $(script_ui_files) +script_ui_files = $(addprefix scripts/,$(script_tests)) +script_tests = \ + test-animator-1.json \ + test-animator-2.json \ + test-animator-3.json \ + test-script-animation.json \ + test-script-child.json \ + test-script-implicit-alpha.json \ + test-script-interval.json \ + test-script-layout-property.json \ + test-script-margin.json \ + test-script-model.json \ + test-script-named-object.json \ + test-script-object-property.json \ + test-script-single.json \ + test-script-timeline-markers.json \ + test-state-1.json + +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/build/autotools/glib-tap.mk $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/conform/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/conform/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(top_srcdir)/build/autotools/glib-tap.mk $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-checkLTLIBRARIES: + -test -z "$(check_LTLIBRARIES)" || rm -f $(check_LTLIBRARIES) + @list='$(check_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +install-installed_testLTLIBRARIES: $(installed_test_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(installed_test_LTLIBRARIES)'; test -n "$(installed_testdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(installed_testdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(installed_testdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(installed_testdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(installed_testdir)"; \ + } + +uninstall-installed_testLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(installed_test_LTLIBRARIES)'; test -n "$(installed_testdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(installed_testdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(installed_testdir)/$$f"; \ + done + +clean-installed_testLTLIBRARIES: + -test -z "$(installed_test_LTLIBRARIES)" || rm -f $(installed_test_LTLIBRARIES) + @list='$(installed_test_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +install-installed_testPROGRAMS: $(installed_test_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(installed_test_PROGRAMS)'; test -n "$(installed_testdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(installed_testdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(installed_testdir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(installed_testdir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(installed_testdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-installed_testPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(installed_test_PROGRAMS)'; test -n "$(installed_testdir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(installed_testdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(installed_testdir)" && rm -f $$files + +clean-installed_testPROGRAMS: + @list='$(installed_test_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +actor-anchors$(EXEEXT): $(actor_anchors_OBJECTS) $(actor_anchors_DEPENDENCIES) $(EXTRA_actor_anchors_DEPENDENCIES) + @rm -f actor-anchors$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(actor_anchors_OBJECTS) $(actor_anchors_LDADD) $(LIBS) + +actor-destroy$(EXEEXT): $(actor_destroy_OBJECTS) $(actor_destroy_DEPENDENCIES) $(EXTRA_actor_destroy_DEPENDENCIES) + @rm -f actor-destroy$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(actor_destroy_OBJECTS) $(actor_destroy_LDADD) $(LIBS) + +actor-graph$(EXEEXT): $(actor_graph_OBJECTS) $(actor_graph_DEPENDENCIES) $(EXTRA_actor_graph_DEPENDENCIES) + @rm -f actor-graph$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(actor_graph_OBJECTS) $(actor_graph_LDADD) $(LIBS) + +actor-invariants$(EXEEXT): $(actor_invariants_OBJECTS) $(actor_invariants_DEPENDENCIES) $(EXTRA_actor_invariants_DEPENDENCIES) + @rm -f actor-invariants$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(actor_invariants_OBJECTS) $(actor_invariants_LDADD) $(LIBS) + +actor-iter$(EXEEXT): $(actor_iter_OBJECTS) $(actor_iter_DEPENDENCIES) $(EXTRA_actor_iter_DEPENDENCIES) + @rm -f actor-iter$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(actor_iter_OBJECTS) $(actor_iter_LDADD) $(LIBS) + +actor-layout$(EXEEXT): $(actor_layout_OBJECTS) $(actor_layout_DEPENDENCIES) $(EXTRA_actor_layout_DEPENDENCIES) + @rm -f actor-layout$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(actor_layout_OBJECTS) $(actor_layout_LDADD) $(LIBS) + +actor-meta$(EXEEXT): $(actor_meta_OBJECTS) $(actor_meta_DEPENDENCIES) $(EXTRA_actor_meta_DEPENDENCIES) + @rm -f actor-meta$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(actor_meta_OBJECTS) $(actor_meta_LDADD) $(LIBS) + +actor-offscreen-limit-max-size$(EXEEXT): $(actor_offscreen_limit_max_size_OBJECTS) $(actor_offscreen_limit_max_size_DEPENDENCIES) $(EXTRA_actor_offscreen_limit_max_size_DEPENDENCIES) + @rm -f actor-offscreen-limit-max-size$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(actor_offscreen_limit_max_size_OBJECTS) $(actor_offscreen_limit_max_size_LDADD) $(LIBS) + +actor-offscreen-redirect$(EXEEXT): $(actor_offscreen_redirect_OBJECTS) $(actor_offscreen_redirect_DEPENDENCIES) $(EXTRA_actor_offscreen_redirect_DEPENDENCIES) + @rm -f actor-offscreen-redirect$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(actor_offscreen_redirect_OBJECTS) $(actor_offscreen_redirect_LDADD) $(LIBS) + +actor-paint-opacity$(EXEEXT): $(actor_paint_opacity_OBJECTS) $(actor_paint_opacity_DEPENDENCIES) $(EXTRA_actor_paint_opacity_DEPENDENCIES) + @rm -f actor-paint-opacity$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(actor_paint_opacity_OBJECTS) $(actor_paint_opacity_LDADD) $(LIBS) + +actor-pick$(EXEEXT): $(actor_pick_OBJECTS) $(actor_pick_DEPENDENCIES) $(EXTRA_actor_pick_DEPENDENCIES) + @rm -f actor-pick$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(actor_pick_OBJECTS) $(actor_pick_LDADD) $(LIBS) + +actor-shader-effect$(EXEEXT): $(actor_shader_effect_OBJECTS) $(actor_shader_effect_DEPENDENCIES) $(EXTRA_actor_shader_effect_DEPENDENCIES) + @rm -f actor-shader-effect$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(actor_shader_effect_OBJECTS) $(actor_shader_effect_LDADD) $(LIBS) + +actor-size$(EXEEXT): $(actor_size_OBJECTS) $(actor_size_DEPENDENCIES) $(EXTRA_actor_size_DEPENDENCIES) + @rm -f actor-size$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(actor_size_OBJECTS) $(actor_size_LDADD) $(LIBS) + +animator$(EXEEXT): $(animator_OBJECTS) $(animator_DEPENDENCIES) $(EXTRA_animator_DEPENDENCIES) + @rm -f animator$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(animator_OBJECTS) $(animator_LDADD) $(LIBS) + +behaviours$(EXEEXT): $(behaviours_OBJECTS) $(behaviours_DEPENDENCIES) $(EXTRA_behaviours_DEPENDENCIES) + @rm -f behaviours$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(behaviours_OBJECTS) $(behaviours_LDADD) $(LIBS) + +binding-pool$(EXEEXT): $(binding_pool_OBJECTS) $(binding_pool_DEPENDENCIES) $(EXTRA_binding_pool_DEPENDENCIES) + @rm -f binding-pool$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(binding_pool_OBJECTS) $(binding_pool_LDADD) $(LIBS) + +color$(EXEEXT): $(color_OBJECTS) $(color_DEPENDENCIES) $(EXTRA_color_DEPENDENCIES) + @rm -f color$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(color_OBJECTS) $(color_LDADD) $(LIBS) + +events-touch$(EXEEXT): $(events_touch_OBJECTS) $(events_touch_DEPENDENCIES) $(EXTRA_events_touch_DEPENDENCIES) + @rm -f events-touch$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(events_touch_OBJECTS) $(events_touch_LDADD) $(LIBS) + +group$(EXEEXT): $(group_OBJECTS) $(group_DEPENDENCIES) $(EXTRA_group_DEPENDENCIES) + @rm -f group$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(group_OBJECTS) $(group_LDADD) $(LIBS) + +interval$(EXEEXT): $(interval_OBJECTS) $(interval_DEPENDENCIES) $(EXTRA_interval_DEPENDENCIES) + @rm -f interval$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(interval_OBJECTS) $(interval_LDADD) $(LIBS) + +model$(EXEEXT): $(model_OBJECTS) $(model_DEPENDENCIES) $(EXTRA_model_DEPENDENCIES) + @rm -f model$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(model_OBJECTS) $(model_LDADD) $(LIBS) + +rectangle$(EXEEXT): $(rectangle_OBJECTS) $(rectangle_DEPENDENCIES) $(EXTRA_rectangle_DEPENDENCIES) + @rm -f rectangle$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(rectangle_OBJECTS) $(rectangle_LDADD) $(LIBS) + +script-parser$(EXEEXT): $(script_parser_OBJECTS) $(script_parser_DEPENDENCIES) $(EXTRA_script_parser_DEPENDENCIES) + @rm -f script-parser$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(script_parser_OBJECTS) $(script_parser_LDADD) $(LIBS) + +text$(EXEEXT): $(text_OBJECTS) $(text_DEPENDENCIES) $(EXTRA_text_DEPENDENCIES) + @rm -f text$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(text_OBJECTS) $(text_LDADD) $(LIBS) + +texture$(EXEEXT): $(texture_OBJECTS) $(texture_DEPENDENCIES) $(EXTRA_texture_DEPENDENCIES) + @rm -f texture$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(texture_OBJECTS) $(texture_LDADD) $(LIBS) + +units$(EXEEXT): $(units_OBJECTS) $(units_DEPENDENCIES) $(EXTRA_units_DEPENDENCIES) + @rm -f units$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(units_OBJECTS) $(units_LDADD) $(LIBS) +install-installed_testSCRIPTS: $(installed_test_SCRIPTS) + @$(NORMAL_INSTALL) + @list='$(installed_test_SCRIPTS)'; test -n "$(installed_testdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(installed_testdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(installed_testdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n' \ + -e 'h;s|.*|.|' \ + -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) { files[d] = files[d] " " $$1; \ + if (++n[d] == $(am__install_max)) { \ + print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ + else { print "f", d "/" $$4, $$1 } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(installed_testdir)$$dir'"; \ + $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(installed_testdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-installed_testSCRIPTS: + @$(NORMAL_UNINSTALL) + @list='$(installed_test_SCRIPTS)'; test -n "$(installed_testdir)" || exit 0; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 's,.*/,,;$(transform)'`; \ + dir='$(DESTDIR)$(installed_testdir)'; $(am__uninstall_files_from_dir) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/actor-anchors.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/actor-destroy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/actor-graph.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/actor-invariants.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/actor-iter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/actor-layout.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/actor-meta.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/actor-offscreen-limit-max-size.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/actor-offscreen-redirect.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/actor-paint-opacity.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/actor-pick.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/actor-shader-effect.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/actor-size.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/animator.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/behaviours.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/binding-pool.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/color.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/events-touch.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/group.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interval.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/model.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rectangle.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script-parser.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/text.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/texture.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/units.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-installed_test_metaDATA: $(installed_test_meta_DATA) + @$(NORMAL_INSTALL) + @list='$(installed_test_meta_DATA)'; test -n "$(installed_test_metadir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(installed_test_metadir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(installed_test_metadir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(installed_test_metadir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(installed_test_metadir)" || exit $$?; \ + done + +uninstall-installed_test_metaDATA: + @$(NORMAL_UNINSTALL) + @list='$(installed_test_meta_DATA)'; test -n "$(installed_test_metadir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(installed_test_metadir)'; $(am__uninstall_files_from_dir) +install-nobase_installed_testDATA: $(nobase_installed_test_DATA) + @$(NORMAL_INSTALL) + @list='$(nobase_installed_test_DATA)'; test -n "$(installed_testdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(installed_testdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(installed_testdir)" || exit 1; \ + fi; \ + $(am__nobase_list) | while read dir files; do \ + xfiles=; for file in $$files; do \ + if test -f "$$file"; then xfiles="$$xfiles $$file"; \ + else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ + test -z "$$xfiles" || { \ + test "x$$dir" = x. || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(installed_testdir)/$$dir'"; \ + $(MKDIR_P) "$(DESTDIR)$(installed_testdir)/$$dir"; }; \ + echo " $(INSTALL_DATA) $$xfiles '$(DESTDIR)$(installed_testdir)/$$dir'"; \ + $(INSTALL_DATA) $$xfiles "$(DESTDIR)$(installed_testdir)/$$dir" || exit $$?; }; \ + done + +uninstall-nobase_installed_testDATA: + @$(NORMAL_UNINSTALL) + @list='$(nobase_installed_test_DATA)'; test -n "$(installed_testdir)" || list=; \ + $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ + dir='$(DESTDIR)$(installed_testdir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all $(check_LTLIBRARIES) $(check_PROGRAMS) $(check_SCRIPTS) $(check_DATA) + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +actor-anchors.log: actor-anchors$(EXEEXT) + @p='actor-anchors$(EXEEXT)'; \ + b='actor-anchors'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +actor-destroy.log: actor-destroy$(EXEEXT) + @p='actor-destroy$(EXEEXT)'; \ + b='actor-destroy'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +actor-graph.log: actor-graph$(EXEEXT) + @p='actor-graph$(EXEEXT)'; \ + b='actor-graph'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +actor-invariants.log: actor-invariants$(EXEEXT) + @p='actor-invariants$(EXEEXT)'; \ + b='actor-invariants'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +actor-iter.log: actor-iter$(EXEEXT) + @p='actor-iter$(EXEEXT)'; \ + b='actor-iter'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +actor-layout.log: actor-layout$(EXEEXT) + @p='actor-layout$(EXEEXT)'; \ + b='actor-layout'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +actor-meta.log: actor-meta$(EXEEXT) + @p='actor-meta$(EXEEXT)'; \ + b='actor-meta'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +actor-offscreen-limit-max-size.log: actor-offscreen-limit-max-size$(EXEEXT) + @p='actor-offscreen-limit-max-size$(EXEEXT)'; \ + b='actor-offscreen-limit-max-size'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +actor-offscreen-redirect.log: actor-offscreen-redirect$(EXEEXT) + @p='actor-offscreen-redirect$(EXEEXT)'; \ + b='actor-offscreen-redirect'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +actor-paint-opacity.log: actor-paint-opacity$(EXEEXT) + @p='actor-paint-opacity$(EXEEXT)'; \ + b='actor-paint-opacity'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +actor-pick.log: actor-pick$(EXEEXT) + @p='actor-pick$(EXEEXT)'; \ + b='actor-pick'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +actor-shader-effect.log: actor-shader-effect$(EXEEXT) + @p='actor-shader-effect$(EXEEXT)'; \ + b='actor-shader-effect'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +actor-size.log: actor-size$(EXEEXT) + @p='actor-size$(EXEEXT)'; \ + b='actor-size'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +binding-pool.log: binding-pool$(EXEEXT) + @p='binding-pool$(EXEEXT)'; \ + b='binding-pool'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +color.log: color$(EXEEXT) + @p='color$(EXEEXT)'; \ + b='color'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +events-touch.log: events-touch$(EXEEXT) + @p='events-touch$(EXEEXT)'; \ + b='events-touch'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +interval.log: interval$(EXEEXT) + @p='interval$(EXEEXT)'; \ + b='interval'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +model.log: model$(EXEEXT) + @p='model$(EXEEXT)'; \ + b='model'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +script-parser.log: script-parser$(EXEEXT) + @p='script-parser$(EXEEXT)'; \ + b='script-parser'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +units.log: units$(EXEEXT) + @p='units$(EXEEXT)'; \ + b='units'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +text.log: text$(EXEEXT) + @p='text$(EXEEXT)'; \ + b='text'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +animator.log: animator$(EXEEXT) + @p='animator$(EXEEXT)'; \ + b='animator'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +behaviours.log: behaviours$(EXEEXT) + @p='behaviours$(EXEEXT)'; \ + b='behaviours'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +group.log: group$(EXEEXT) + @p='group$(EXEEXT)'; \ + b='group'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +rectangle.log: rectangle$(EXEEXT) + @p='rectangle$(EXEEXT)'; \ + b='rectangle'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +texture.log: texture$(EXEEXT) + @p='texture$(EXEEXT)'; \ + b='texture'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_LTLIBRARIES) $(check_PROGRAMS) \ + $(check_SCRIPTS) $(check_DATA) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(SCRIPTS) $(DATA) +installdirs: + for dir in "$(DESTDIR)$(installed_testdir)" "$(DESTDIR)$(installed_testdir)" "$(DESTDIR)$(installed_testdir)" "$(DESTDIR)$(installed_test_metadir)" "$(DESTDIR)$(installed_testdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-am + +clean-am: clean-checkLTLIBRARIES clean-checkPROGRAMS clean-generic \ + clean-installed_testLTLIBRARIES clean-installed_testPROGRAMS \ + clean-libtool clean-noinstLTLIBRARIES clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-installed_testLTLIBRARIES \ + install-installed_testPROGRAMS install-installed_testSCRIPTS \ + install-installed_test_metaDATA \ + install-nobase_installed_testDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-installed_testLTLIBRARIES \ + uninstall-installed_testPROGRAMS \ + uninstall-installed_testSCRIPTS \ + uninstall-installed_test_metaDATA \ + uninstall-nobase_installed_testDATA + +.MAKE: all check check-am install install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ + clean-checkLTLIBRARIES clean-checkPROGRAMS clean-generic \ + clean-installed_testLTLIBRARIES clean-installed_testPROGRAMS \ + clean-libtool clean-noinstLTLIBRARIES clean-noinstPROGRAMS \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-installed_testLTLIBRARIES \ + install-installed_testPROGRAMS install-installed_testSCRIPTS \ + install-installed_test_metaDATA install-man \ + install-nobase_installed_testDATA install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + recheck tags tags-am uninstall uninstall-am \ + uninstall-installed_testLTLIBRARIES \ + uninstall-installed_testPROGRAMS \ + uninstall-installed_testSCRIPTS \ + uninstall-installed_test_metaDATA \ + uninstall-nobase_installed_testDATA + +.PRECIOUS: Makefile + + +@ENABLE_INSTALLED_TESTS_TRUE@%.test: %$(EXEEXT) Makefile +@ENABLE_INSTALLED_TESTS_TRUE@ $(AM_V_GEN) (echo '[Test]' > $@.tmp; \ +@ENABLE_INSTALLED_TESTS_TRUE@ echo 'Type=session' >> $@.tmp; \ +@ENABLE_INSTALLED_TESTS_TRUE@ echo 'Exec=env G_ENABLE_DIAGNOSTIC=0 CLUTTER_ENABLE_DIAGNOSTIC=0 $(installed_testdir)/$<' >> $@.tmp; \ +@ENABLE_INSTALLED_TESTS_TRUE@ mv $@.tmp $@) + +# simple rules for generating a Git ignore file for the conformance test suite +$(srcdir)/.gitignore: Makefile + $(AM_V_GEN)( echo "/*.trs" ; \ + echo "/*.log" ; \ + echo "/*.test" ; \ + echo "/.gitignore" ; \ + for p in $(test_programs); do \ + echo "/$$p" ; \ + done ) > $(@F) + +gitignore: $(srcdir)/.gitignore + +all-am: gitignore + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/clutter/tests/conform/actor-anchors.c b/clutter/tests/conform/actor-anchors.c new file mode 100644 index 0000000..ee3b6a5 --- /dev/null +++ b/clutter/tests/conform/actor-anchors.c @@ -0,0 +1,741 @@ +#include +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include + +#define NOTIFY_ANCHOR_X (1 << 0) +#define NOTIFY_ANCHOR_Y (1 << 1) +#define NOTIFY_ANCHOR_GRAVITY (1 << 2) +#define NOTIFY_SCALE_X (1 << 3) +#define NOTIFY_SCALE_Y (1 << 4) +#define NOTIFY_SCALE_CENTER_X (1 << 5) +#define NOTIFY_SCALE_CENTER_Y (1 << 6) +#define NOTIFY_SCALE_GRAVITY (1 << 7) +#define NOTIFY_ROTATION_ANGLE_X (1 << 8) +#define NOTIFY_ROTATION_ANGLE_Y (1 << 9) +#define NOTIFY_ROTATION_ANGLE_Z (1 << 10) +#define NOTIFY_ROTATION_CENTER_X (1 << 11) +#define NOTIFY_ROTATION_CENTER_Y (1 << 12) +#define NOTIFY_ROTATION_CENTER_Z (1 << 13) +#define NOTIFY_ROTATION_CENTER_Z_GRAVITY (1 << 14) + +#define RECT_WIDTH 100.0 +#define RECT_HEIGHT 80.0 + +/* Allow the transformed position by off by a certain number of + pixels */ +#define POSITION_TOLERANCE 2 + +typedef struct _TestState +{ + gulong notifications; + ClutterActor *rect; +} TestState; + +static const struct +{ + ClutterGravity gravity; + gfloat x_pos; + gfloat y_pos; +} gravities[] = + { + { CLUTTER_GRAVITY_NORTH, RECT_WIDTH / 2, 0 }, + { CLUTTER_GRAVITY_NORTH_EAST, RECT_WIDTH, 0 }, + { CLUTTER_GRAVITY_EAST, RECT_WIDTH, RECT_HEIGHT / 2 }, + { CLUTTER_GRAVITY_SOUTH_EAST, RECT_WIDTH, RECT_HEIGHT }, + { CLUTTER_GRAVITY_SOUTH, RECT_WIDTH / 2, RECT_HEIGHT }, + { CLUTTER_GRAVITY_SOUTH_WEST, 0, RECT_HEIGHT }, + { CLUTTER_GRAVITY_WEST, 0, RECT_HEIGHT / 2 }, + { CLUTTER_GRAVITY_NORTH_WEST, 0, 0 }, + { CLUTTER_GRAVITY_CENTER, RECT_WIDTH / 2, RECT_HEIGHT / 2 } + }; + +static const char * const properties[] = { + "anchor-x", + "anchor-y", + "anchor-gravity", + "scale-x", + "scale-y", + "scale-center-x", + "scale-center-y", + "scale-gravity", + "rotation-angle-x", + "rotation-angle-y", + "rotation-angle-z", + "rotation-center-x", + "rotation-center-y", + "rotation-center-z", + "rotation-center-z-gravity" +}; + +static const int n_properties = G_N_ELEMENTS (properties); + +static void +notify_cb (GObject *object, GParamSpec *pspec, TestState *state) +{ + int i; + int new_flags = 0; + int flag = 1; + + for (i = 0; i < n_properties; i++) + { + if (!strcmp (properties[i], pspec->name)) + new_flags |= flag; + + flag <<= 1; + } + + g_assert ((new_flags & state->notifications) == 0); + + state->notifications |= new_flags; +} + +#define assert_notifications(flags) G_STMT_START { \ + g_assert (state->notifications == (flags)); \ + state->notifications = 0; } G_STMT_END + +/* Helper macro to assert the transformed position. This needs to be a + macro so that the assertion failure will report the right line + number */ +#define assert_coords(state, x_1, y_1, x_2, y_2) G_STMT_START { \ + ClutterVertex verts[4]; \ + clutter_actor_get_abs_allocation_vertices ((state)->rect, verts); \ + check_coords ((state), (x_1), (y_1), (x_2), (y_2), verts); \ + g_assert (approx_equal ((x_1), verts[0].x)); \ + g_assert (approx_equal ((y_1), verts[0].y)); \ + g_assert (approx_equal ((x_2), verts[3].x)); \ + g_assert (approx_equal ((y_2), verts[3].y)); } G_STMT_END + +#define assert_position(state, x, y) \ + assert_coords((state), (x), (y), (x) + RECT_WIDTH, (y) + RECT_HEIGHT) + +#define assert_vertex_and_free(v, xc, yc, zc) G_STMT_START { \ + g_assert (approx_equal (v->x, xc) && \ + approx_equal (v->y, yc) && \ + approx_equal (v->z, zc)); \ + g_boxed_free (CLUTTER_TYPE_VERTEX, v); } G_STMT_END + +static inline gboolean +approx_equal (int a, int b) +{ + return abs (a - b) <= POSITION_TOLERANCE; +} + +static void +check_coords (TestState *state, + gint x_1, + gint y_1, + gint x_2, + gint y_2, + const ClutterVertex *verts) +{ + if (g_test_verbose ()) + g_print ("checking that (%i,%i,%i,%i) \xe2\x89\x88 (%i,%i,%i,%i): %s\n", + x_1, y_1, x_2, y_2, + (int) (verts[0].x), + (int) (verts[0].y), + (int) (verts[3].x), + (int) (verts[3].y), + approx_equal (x_1, verts[0].x) && + approx_equal (y_1, verts[0].y) && + approx_equal (x_2, verts[3].x) && + approx_equal (y_2, verts[3].y) ? "yes" + : "NO"); +} + +static void +test_anchor_point (TestState *state) +{ + ClutterActor *rect = state->rect; + gfloat anchor_x, anchor_y; + ClutterGravity anchor_gravity; + int i; + + /* Assert the default settings */ + g_assert (clutter_actor_get_x (rect) == 100); + g_assert (clutter_actor_get_y (rect) == 200); + g_assert (clutter_actor_get_width (rect) == RECT_WIDTH); + g_assert (clutter_actor_get_height (rect) == RECT_HEIGHT); + g_object_get (rect, + "anchor-x", &anchor_x, + "anchor-y", &anchor_y, + "anchor-gravity", &anchor_gravity, + NULL); + g_assert (anchor_x == 0); + g_assert (anchor_y == 0); + g_assert (anchor_gravity == CLUTTER_GRAVITY_NONE); + + /* Change the anchor point */ + clutter_actor_set_anchor_point (rect, 20, 30); + g_object_get (rect, + "anchor-x", &anchor_x, + "anchor-y", &anchor_y, + "anchor-gravity", &anchor_gravity, + NULL); + g_assert (anchor_x == 20); + g_assert (anchor_y == 30); + g_assert (anchor_gravity == CLUTTER_GRAVITY_NONE); + assert_position (state, 80, 170); + assert_notifications (NOTIFY_ANCHOR_X | NOTIFY_ANCHOR_Y); + + /* Move the anchor point */ + clutter_actor_move_anchor_point (rect, 40, 50); + g_object_get (rect, + "anchor-x", &anchor_x, + "anchor-y", &anchor_y, + "anchor-gravity", &anchor_gravity, + NULL); + g_assert (anchor_x == 40); + g_assert (anchor_y == 50); + g_assert (anchor_gravity == CLUTTER_GRAVITY_NONE); + assert_position (state, 80, 170); + assert_notifications (NOTIFY_ANCHOR_X | NOTIFY_ANCHOR_Y); + + /* Put the actor back to its default position */ + clutter_actor_set_position (rect, 100, 200); + + /* Change the anchor point with each of the gravities */ + for (i = 0; i < G_N_ELEMENTS (gravities); i++) + { + if (g_test_verbose ()) + { + GEnumClass *gravity_class = g_type_class_ref (CLUTTER_TYPE_GRAVITY); + GEnumValue *value = g_enum_get_value (gravity_class, + gravities[i].gravity); + g_print ("Setting gravity to %s\n", + value ? value->value_name : "?"); + g_type_class_unref (gravity_class); + } + + g_object_set (rect, "anchor-gravity", gravities[i].gravity, NULL); + + g_object_get (rect, + "anchor-x", &anchor_x, + "anchor-y", &anchor_y, + "anchor-gravity", &anchor_gravity, + NULL); + g_assert (anchor_x == gravities[i].x_pos); + g_assert (anchor_y == gravities[i].y_pos); + g_assert (anchor_gravity == gravities[i].gravity); + assert_position (state, + 100 - gravities[i].x_pos, + 200 - gravities[i].y_pos); + + assert_notifications (NOTIFY_ANCHOR_X | NOTIFY_ANCHOR_Y + | NOTIFY_ANCHOR_GRAVITY); + } + + /* Verify that the anchor point moves if the actor changes size when + it is set from the gravity */ + clutter_actor_set_size (rect, RECT_WIDTH * 2, RECT_HEIGHT * 2); + g_object_get (rect, + "anchor-x", &anchor_x, + "anchor-y", &anchor_y, + "anchor-gravity", &anchor_gravity, + NULL); + g_assert (anchor_x == RECT_WIDTH); + g_assert (anchor_y == RECT_HEIGHT); + g_assert (anchor_gravity == CLUTTER_GRAVITY_CENTER); + assert_coords (state, 100 - RECT_WIDTH, 200 - RECT_HEIGHT, + 100 + RECT_WIDTH, 200 + RECT_HEIGHT); + assert_notifications (0); + clutter_actor_set_size (rect, RECT_WIDTH, RECT_HEIGHT); + + /* Change the anchor point using units again to assert that the + gravity property changes */ + clutter_actor_set_anchor_point (rect, 20, 30); + g_object_get (rect, + "anchor-x", &anchor_x, "anchor-y", &anchor_y, + "anchor-gravity", &anchor_gravity, + NULL); + g_assert (anchor_x == 20); + g_assert (anchor_y == 30); + g_assert (anchor_gravity == CLUTTER_GRAVITY_NONE); + assert_position (state, 80, 170); + assert_notifications (NOTIFY_ANCHOR_X | NOTIFY_ANCHOR_Y + | NOTIFY_ANCHOR_GRAVITY); + + /* Verify that the anchor point doesn't move if the actor changes + size when it is set from units */ + clutter_actor_set_size (rect, RECT_WIDTH * 2, RECT_HEIGHT * 2); + g_object_get (rect, + "anchor-x", &anchor_x, + "anchor-y", &anchor_y, + "anchor-gravity", &anchor_gravity, + NULL); + g_assert (anchor_x == 20); + g_assert (anchor_y == 30); + g_assert (anchor_gravity == CLUTTER_GRAVITY_NONE); + assert_coords (state, 80, 170, 80 + RECT_WIDTH * 2, 170 + RECT_HEIGHT * 2); + assert_notifications (0); + clutter_actor_set_size (rect, RECT_WIDTH, RECT_HEIGHT); + + /* Put the anchor back */ + clutter_actor_set_anchor_point_from_gravity (rect, CLUTTER_GRAVITY_NONE); + assert_notifications (NOTIFY_ANCHOR_X | NOTIFY_ANCHOR_Y); +} + +static void +test_scale_center (TestState *state) +{ + ClutterActor *rect = state->rect; + gdouble scale_x, scale_y; + gfloat center_x, center_y; + ClutterGravity gravity; + int i; + + /* Assert the default settings */ + g_assert (clutter_actor_get_x (rect) == 100); + g_assert (clutter_actor_get_y (rect) == 200); + g_assert (clutter_actor_get_width (rect) == RECT_WIDTH); + g_assert (clutter_actor_get_height (rect) == RECT_HEIGHT); + g_object_get (rect, + "scale-center-x", ¢er_x, + "scale-center-y", ¢er_y, + "scale-x", &scale_x, + "scale-y", &scale_y, + "scale-gravity", &gravity, + NULL); + g_assert (center_x == 0); + g_assert (center_y == 0); + g_assert (scale_x == 1.0); + g_assert (scale_y == 1.0); + g_assert (gravity == CLUTTER_GRAVITY_NONE); + + /* Try changing the scale without affecting the center */ + g_object_set (rect, "scale-x", 2.0, "scale-y", 3.0, NULL); + g_assert (clutter_actor_get_x (rect) == 100); + g_assert (clutter_actor_get_y (rect) == 200); + g_assert (clutter_actor_get_width (rect) == RECT_WIDTH); + g_assert (clutter_actor_get_height (rect) == RECT_HEIGHT); + g_object_get (rect, + "scale-center-x", ¢er_x, + "scale-center-y", ¢er_y, + "scale-x", &scale_x, + "scale-y", &scale_y, + "scale-gravity", &gravity, + NULL); + g_assert (center_x == 0); + g_assert (center_y == 0); + g_assert (scale_x == 2.0); + g_assert (scale_y == 3.0); + g_assert (gravity == CLUTTER_GRAVITY_NONE); + assert_notifications (NOTIFY_SCALE_X | NOTIFY_SCALE_Y); + assert_coords (state, 100, 200, 100 + RECT_WIDTH * 2, 200 + RECT_HEIGHT * 3); + + /* Change the scale and center */ + g_object_set (rect, + "scale-x", 4.0, + "scale-y", 2.0, + "scale-center-x", 10.0, + "scale-center-y", 20.0, + NULL); + g_assert (clutter_actor_get_x (rect) == 100); + g_assert (clutter_actor_get_y (rect) == 200); + g_assert (clutter_actor_get_width (rect) == RECT_WIDTH); + g_assert (clutter_actor_get_height (rect) == RECT_HEIGHT); + g_object_get (rect, + "scale-center-x", ¢er_x, "scale-center-y", ¢er_y, + "scale-x", &scale_x, "scale-y", &scale_y, + "scale-gravity", &gravity, + NULL); + g_assert (center_x == 10); + g_assert (center_y == 20); + g_assert (scale_x == 4.0); + g_assert (scale_y == 2.0); + g_assert (gravity == CLUTTER_GRAVITY_NONE); + assert_notifications (NOTIFY_SCALE_X | NOTIFY_SCALE_Y + | NOTIFY_SCALE_CENTER_X | NOTIFY_SCALE_CENTER_Y); + assert_coords (state, 100 + 10 - 10 * 4, 200 + 20 - 20 * 2, + 100 + 10 + (RECT_WIDTH - 10) * 4, + 200 + 20 + (RECT_HEIGHT - 20) * 2); + + /* Change the anchor point with each of the gravities */ + for (i = 0; i < G_N_ELEMENTS (gravities); i++) + { + if (g_test_verbose ()) + { + GEnumClass *gravity_class = g_type_class_ref (CLUTTER_TYPE_GRAVITY); + GEnumValue *value = g_enum_get_value (gravity_class, + gravities[i].gravity); + g_print ("Setting scale center to %s\n", + value ? value->value_name : "?"); + g_type_class_unref (gravity_class); + } + + g_object_set (rect, "scale-gravity", gravities[i].gravity, NULL); + + g_assert (clutter_actor_get_x (rect) == 100); + g_assert (clutter_actor_get_y (rect) == 200); + g_assert (clutter_actor_get_width (rect) == RECT_WIDTH); + g_assert (clutter_actor_get_height (rect) == RECT_HEIGHT); + g_object_get (rect, + "scale-center-x", ¢er_x, "scale-center-y", ¢er_y, + "scale-x", &scale_x, "scale-y", &scale_y, + "scale-gravity", &gravity, + NULL); + g_assert (center_x == gravities[i].x_pos); + g_assert (center_y == gravities[i].y_pos); + g_assert (scale_x == 4.0); + g_assert (scale_y == 2.0); + g_assert (gravity == gravities[i].gravity); + assert_notifications (NOTIFY_SCALE_CENTER_X | + NOTIFY_SCALE_CENTER_Y | + NOTIFY_SCALE_GRAVITY); + assert_coords (state, + 100 - gravities[i].x_pos * 3, + 200 - gravities[i].y_pos, + 100 + (gravities[i].x_pos + + (RECT_WIDTH - gravities[i].x_pos) * 4), + 200 + (gravities[i].y_pos + + (RECT_HEIGHT - gravities[i].y_pos) * 2)); + } + + /* Change the scale center using units again to assert that the + gravity property changes */ + clutter_actor_set_scale_full (rect, 4, 2, 10, 20); + g_object_get (rect, + "scale-center-x", ¢er_x, + "scale-center-y", ¢er_y, + "scale-x", &scale_x, + "scale-y", &scale_y, + "scale-gravity", &gravity, + NULL); + g_assert (center_x == 10); + g_assert (center_y == 20); + g_assert (scale_x == 4.0); + g_assert (scale_y == 2.0); + g_assert (gravity == CLUTTER_GRAVITY_NONE); + assert_notifications (NOTIFY_SCALE_X | NOTIFY_SCALE_Y + | NOTIFY_SCALE_CENTER_X | NOTIFY_SCALE_CENTER_Y + | NOTIFY_SCALE_GRAVITY); + assert_coords (state, 100 + 10 - 10 * 4, 200 + 20 - 20 * 2, + 100 + 10 + (RECT_WIDTH - 10) * 4, + 200 + 20 + (RECT_HEIGHT - 20) * 2); + + /* Put the scale back to normal */ + clutter_actor_set_scale_full (rect, 1, 1, 0, 0); + assert_notifications (NOTIFY_SCALE_X | NOTIFY_SCALE_Y + | NOTIFY_SCALE_CENTER_X | NOTIFY_SCALE_CENTER_Y); +} + +static void +test_rotate_center (TestState *state) +{ + ClutterActor *rect = state->rect; + gdouble angle_x, angle_y, angle_z; + ClutterVertex *center_x, *center_y, *center_z; + ClutterGravity z_center_gravity; + gfloat stage_width, stage_height; + gfloat rect_x, rect_y; + int i; + + /* Position the rectangle at the center of the stage so that + rotations by 90° along the X or Y axis will cause the actor to be + appear as a flat line. This makes verifying the transformations + easier */ + clutter_actor_get_size (clutter_actor_get_stage (rect), + &stage_width, + &stage_height); + rect_x = stage_width / 2; + rect_y = stage_height / 2; + clutter_actor_set_position (rect, rect_x, rect_y); + + /* Assert the default settings */ + g_assert_cmpfloat (clutter_actor_get_x (rect), ==, rect_x); + g_assert_cmpfloat (clutter_actor_get_y (rect), ==, rect_y); + g_assert_cmpfloat (clutter_actor_get_width (rect), ==, RECT_WIDTH); + g_assert_cmpfloat (clutter_actor_get_height (rect), ==, RECT_HEIGHT); + g_object_get (rect, + "rotation-angle-x", &angle_x, + "rotation-angle-y", &angle_y, + "rotation-angle-z", &angle_z, + "rotation-center-x", ¢er_x, + "rotation-center-y", ¢er_y, + "rotation-center-z", ¢er_z, + "rotation-center-z-gravity", &z_center_gravity, + NULL); + g_assert (angle_x == 0.0); + g_assert (angle_y == 0.0); + g_assert (angle_z == 0.0); + assert_vertex_and_free (center_x, 0, 0, 0); + assert_vertex_and_free (center_y, 0, 0, 0); + assert_vertex_and_free (center_z, 0, 0, 0); + g_assert (z_center_gravity == CLUTTER_GRAVITY_NONE); + + /* Change each of the rotation angles without affecting the center + point */ + for (i = CLUTTER_X_AXIS; i <= CLUTTER_Z_AXIS; i++) + { + char prop_name[] = "rotation-angle- "; + prop_name[sizeof (prop_name) - 2] = i - CLUTTER_X_AXIS + 'x'; + + if (g_test_verbose ()) + g_print ("Setting %s to 90 degrees\n", prop_name); + + g_object_set (rect, prop_name, 90.0, NULL); + assert_notifications (NOTIFY_ROTATION_ANGLE_X << (i - CLUTTER_X_AXIS)); + + g_assert (clutter_actor_get_x (rect) == rect_x); + g_assert (clutter_actor_get_y (rect) == rect_y); + g_assert (clutter_actor_get_width (rect) == RECT_WIDTH); + g_assert (clutter_actor_get_height (rect) == RECT_HEIGHT); + g_object_get (rect, + "rotation-angle-x", &angle_x, + "rotation-angle-y", &angle_y, + "rotation-angle-z", &angle_z, + "rotation-center-x", ¢er_x, + "rotation-center-y", ¢er_y, + "rotation-center-z", ¢er_z, + "rotation-center-z-gravity", &z_center_gravity, + NULL); + if (i == CLUTTER_X_AXIS) + { + g_assert (angle_x == 90.0); + assert_coords (state, rect_x, rect_y, verts[3].x, rect_y); + } + else + g_assert (angle_x == 0.0); + if (i == CLUTTER_Y_AXIS) + { + g_assert (angle_y == 90.0); + assert_coords (state, rect_x, rect_y, rect_x, verts[3].y); + } + else + g_assert (angle_y == 0.0); + if (i == CLUTTER_Z_AXIS) + { + g_assert (angle_z == 90.0); + assert_coords (state, rect_x, rect_y, + rect_x - RECT_HEIGHT, + rect_y + RECT_WIDTH); + } + else + g_assert (angle_z == 0.0); + assert_vertex_and_free (center_x, 0, 0, 0); + assert_vertex_and_free (center_y, 0, 0, 0); + assert_vertex_and_free (center_z, 0, 0, 0); + g_assert (z_center_gravity == CLUTTER_GRAVITY_NONE); + + g_object_set (rect, prop_name, 0.0, NULL); + assert_notifications (NOTIFY_ROTATION_ANGLE_X << (i - CLUTTER_X_AXIS)); + } + + clutter_actor_set_position (rect, rect_x -= 10, rect_y -= 20); + + /* Same test but also change the center position */ + for (i = CLUTTER_X_AXIS; i <= CLUTTER_Z_AXIS; i++) + { + char prop_name[] = "rotation-angle- "; + prop_name[sizeof (prop_name) - 2] = i - CLUTTER_X_AXIS + 'x'; + + if (g_test_verbose ()) + g_print ("Setting %s to 90 degrees with center 10,20,0\n", prop_name); + + clutter_actor_set_rotation (rect, i, 90.0, 10, 20, 0); + assert_notifications ((NOTIFY_ROTATION_ANGLE_X << (i - CLUTTER_X_AXIS)) + | (NOTIFY_ROTATION_CENTER_X + << (i - CLUTTER_X_AXIS))); + + g_assert (clutter_actor_get_x (rect) == rect_x); + g_assert (clutter_actor_get_y (rect) == rect_y); + g_assert (clutter_actor_get_width (rect) == RECT_WIDTH); + g_assert (clutter_actor_get_height (rect) == RECT_HEIGHT); + g_object_get (rect, + "rotation-angle-x", &angle_x, + "rotation-angle-y", &angle_y, + "rotation-angle-z", &angle_z, + "rotation-center-x", ¢er_x, + "rotation-center-y", ¢er_y, + "rotation-center-z", ¢er_z, + "rotation-center-z-gravity", &z_center_gravity, + NULL); + if (i == CLUTTER_X_AXIS) + { + g_assert (angle_x == 90.0); + assert_coords (state, + verts[0].x, rect_y + 20, + verts[3].x, rect_y + 20); + assert_vertex_and_free (center_x, 10, 20, 0); + } + else + { + g_assert (angle_x == 0.0); + assert_vertex_and_free (center_x, 0, 0, 0); + } + if (i == CLUTTER_Y_AXIS) + { + g_assert (angle_y == 90.0); + assert_coords (state, + rect_x + 10, verts[0].y, + rect_x + 10, verts[3].y); + assert_vertex_and_free (center_y, 10, 20, 0); + } + else + { + g_assert (angle_y == 0.0); + assert_vertex_and_free (center_y, 0, 0, 0); + } + if (i == CLUTTER_Z_AXIS) + { + g_assert (angle_z == 90.0); + assert_coords (state, + rect_x + 10 + 20, + rect_y + 20 - 10, + rect_x + 10 + 20 - RECT_HEIGHT, + rect_y + 20 + RECT_WIDTH - 10); + assert_vertex_and_free (center_z, 10, 20, 0); + } + else + { + g_assert (angle_z == 0.0); + assert_vertex_and_free (center_z, 0, 0, 0); + } + g_assert (z_center_gravity == CLUTTER_GRAVITY_NONE); + + clutter_actor_set_rotation (rect, i, 0, 0, 0, 0); + assert_notifications ((NOTIFY_ROTATION_ANGLE_X << (i - CLUTTER_X_AXIS)) + | (NOTIFY_ROTATION_CENTER_X + << (i - CLUTTER_X_AXIS))); + + } + + /* Try rotating the z with all of the gravities */ + for (i = 0; i < G_N_ELEMENTS (gravities); i++) + { + if (g_test_verbose ()) + { + GEnumClass *gravity_class = g_type_class_ref (CLUTTER_TYPE_GRAVITY); + GEnumValue *value = g_enum_get_value (gravity_class, + gravities[i].gravity); + g_print ("Setting z rotation to 90 degrees with center at %s\n", + value ? value->value_name : "?"); + g_type_class_unref (gravity_class); + } + + clutter_actor_set_z_rotation_from_gravity (rect, 90, + gravities[i].gravity); + assert_notifications (NOTIFY_ROTATION_ANGLE_Z + | NOTIFY_ROTATION_CENTER_Z + | NOTIFY_ROTATION_CENTER_Z_GRAVITY); + + g_assert (clutter_actor_get_x (rect) == rect_x); + g_assert (clutter_actor_get_y (rect) == rect_y); + g_assert (clutter_actor_get_width (rect) == RECT_WIDTH); + g_assert (clutter_actor_get_height (rect) == RECT_HEIGHT); + g_object_get (rect, + "rotation-angle-x", &angle_x, + "rotation-angle-y", &angle_y, + "rotation-angle-z", &angle_z, + "rotation-center-x", ¢er_x, + "rotation-center-y", ¢er_y, + "rotation-center-z", ¢er_z, + "rotation-center-z-gravity", &z_center_gravity, + NULL); + g_assert (angle_x == 0.0); + g_assert (angle_y == 0.0); + g_assert (angle_z == 90.0); + assert_vertex_and_free (center_x, 0, 0, 0); + assert_vertex_and_free (center_y, 0, 0, 0); + assert_vertex_and_free (center_z, + gravities[i].x_pos, gravities[i].y_pos, 0); + assert_coords (state, + rect_x + gravities[i].x_pos + gravities[i].y_pos, + rect_y + gravities[i].y_pos - gravities[i].x_pos, + rect_x + gravities[i].x_pos + gravities[i].y_pos + - RECT_HEIGHT, + rect_y + gravities[i].y_pos + RECT_WIDTH + - gravities[i].x_pos); + g_assert (z_center_gravity == gravities[i].gravity); + g_assert (clutter_actor_get_z_rotation_gravity (rect) + == gravities[i].gravity); + + /* Put the rotation back */ + clutter_actor_set_z_rotation_from_gravity (rect, 0, CLUTTER_GRAVITY_NONE); + assert_notifications (NOTIFY_ROTATION_ANGLE_Z + | NOTIFY_ROTATION_CENTER_Z + | NOTIFY_ROTATION_CENTER_Z_GRAVITY); + } +} + +static gboolean +idle_cb (gpointer data) +{ + test_anchor_point (data); + test_scale_center (data); + test_rotate_center (data); + + clutter_main_quit (); + + return G_SOURCE_REMOVE; +} + +static void +actor_anchors (void) +{ + TestState state; + ClutterActor *stage; + + stage = clutter_test_get_stage (); + + state.rect = clutter_actor_new (); + clutter_actor_add_child (stage, state.rect); + clutter_actor_set_position (state.rect, 100, 200); + clutter_actor_set_size (state.rect, RECT_WIDTH, RECT_HEIGHT); + + /* Record notifications on the actor properties */ + state.notifications = 0; + g_signal_connect (state.rect, "notify", + G_CALLBACK (notify_cb), &state); + + /* Run the tests in a low priority idle function so that we can be + sure the stage is correctly setup */ + clutter_threads_add_idle_full (G_PRIORITY_LOW, idle_cb, &state, NULL); + + clutter_actor_show (stage); + + clutter_main (); +} + +static void +actor_pivot (void) +{ + ClutterActor *stage, *actor_implicit, *actor_explicit; + ClutterMatrix transform, result_implicit, result_explicit; + ClutterActorBox allocation = CLUTTER_ACTOR_BOX_INIT (0, 0, 90, 30); + gfloat angle = 30; + + stage = clutter_test_get_stage (); + + actor_implicit = clutter_actor_new (); + actor_explicit = clutter_actor_new (); + + clutter_actor_add_child (stage, actor_implicit); + clutter_actor_add_child (stage, actor_explicit); + + /* Fake allocation or pivot-point will not have any effect */ + clutter_actor_allocate (actor_implicit, &allocation, CLUTTER_ALLOCATION_NONE); + clutter_actor_allocate (actor_explicit, &allocation, CLUTTER_ALLOCATION_NONE); + + clutter_actor_set_pivot_point (actor_implicit, 0.5, 0.5); + clutter_actor_set_pivot_point (actor_explicit, 0.5, 0.5); + + /* Implict transformation */ + clutter_actor_set_rotation_angle (actor_implicit, CLUTTER_Z_AXIS, angle); + + /* Explict transformation */ + clutter_matrix_init_identity(&transform); + cogl_matrix_rotate (&transform, angle, 0, 0, 1.0); + clutter_actor_set_transform (actor_explicit, &transform); + + clutter_actor_get_transform (actor_implicit, &result_implicit); + clutter_actor_get_transform (actor_explicit, &result_explicit); + + g_assert (cogl_matrix_equal (&result_implicit, &result_explicit)); +} + +CLUTTER_TEST_SUITE ( + CLUTTER_TEST_UNIT ("/actor/transforms/anchor-point", actor_anchors) + CLUTTER_TEST_UNIT ("/actor/transforms/pivot-point", actor_pivot) +) diff --git a/clutter/tests/conform/actor-destroy.c b/clutter/tests/conform/actor-destroy.c new file mode 100644 index 0000000..03092a0 --- /dev/null +++ b/clutter/tests/conform/actor-destroy.c @@ -0,0 +1,195 @@ +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include + +#define TEST_TYPE_DESTROY (test_destroy_get_type ()) +#define TEST_DESTROY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_DESTROY, TestDestroy)) +#define TEST_IS_DESTROY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_DESTROY)) + +typedef struct _TestDestroy TestDestroy; +typedef struct _TestDestroyClass TestDestroyClass; + +struct _TestDestroy +{ + ClutterActor parent_instance; + + ClutterActor *bg; + ClutterActor *label; + ClutterActor *tex; + + GList *children; +}; + +struct _TestDestroyClass +{ + ClutterActorClass parent_class; +}; + +static void clutter_container_init (ClutterContainerIface *iface); + +GType test_destroy_get_type (void); + +G_DEFINE_TYPE_WITH_CODE (TestDestroy, test_destroy, CLUTTER_TYPE_ACTOR, + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER, + clutter_container_init)); + +static void +test_destroy_add (ClutterContainer *container, + ClutterActor *actor) +{ + TestDestroy *self = TEST_DESTROY (container); + + if (g_test_verbose ()) + g_print ("Adding '%s' (type:%s)\n", + clutter_actor_get_name (actor), + G_OBJECT_TYPE_NAME (actor)); + + self->children = g_list_prepend (self->children, actor); + clutter_actor_set_parent (actor, CLUTTER_ACTOR (container)); +} + +static void +test_destroy_remove (ClutterContainer *container, + ClutterActor *actor) +{ + TestDestroy *self = TEST_DESTROY (container); + + if (g_test_verbose ()) + g_print ("Removing '%s' (type:%s)\n", + clutter_actor_get_name (actor), + G_OBJECT_TYPE_NAME (actor)); + + g_assert (actor != self->bg); + g_assert (actor != self->label); + + if (!g_list_find (self->children, actor)) + g_assert (actor == self->tex); + else + self->children = g_list_remove (self->children, actor); + + clutter_actor_unparent (actor); +} + +static void +clutter_container_init (ClutterContainerIface *iface) +{ + iface->add = test_destroy_add; + iface->remove = test_destroy_remove; +} + +static void +test_destroy_destroy (ClutterActor *self) +{ + TestDestroy *test = TEST_DESTROY (self); + + if (test->bg != NULL) + { + if (g_test_verbose ()) + g_print ("Destroying '%s' (type:%s)\n", + clutter_actor_get_name (test->bg), + G_OBJECT_TYPE_NAME (test->bg)); + + clutter_actor_destroy (test->bg); + test->bg = NULL; + } + + if (test->label != NULL) + { + if (g_test_verbose ()) + g_print ("Destroying '%s' (type:%s)\n", + clutter_actor_get_name (test->label), + G_OBJECT_TYPE_NAME (test->label)); + + clutter_actor_destroy (test->label); + test->label = NULL; + } + + if (test->tex != NULL) + { + if (g_test_verbose ()) + g_print ("Destroying '%s' (type:%s)\n", + clutter_actor_get_name (test->tex), + G_OBJECT_TYPE_NAME (test->tex)); + + clutter_actor_destroy (test->tex); + test->tex = NULL; + } + + g_list_foreach (test->children, (GFunc) clutter_actor_destroy, NULL); + g_list_free (test->children); + test->children = NULL; + + if (CLUTTER_ACTOR_CLASS (test_destroy_parent_class)->destroy) + CLUTTER_ACTOR_CLASS (test_destroy_parent_class)->destroy (self); +} + +static void +test_destroy_class_init (TestDestroyClass *klass) +{ + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + + actor_class->destroy = test_destroy_destroy; +} + +static void +test_destroy_init (TestDestroy *self) +{ + clutter_actor_push_internal (CLUTTER_ACTOR (self)); + + if (g_test_verbose ()) + g_print ("Adding internal children...\n"); + + self->bg = clutter_rectangle_new (); + clutter_actor_set_parent (self->bg, CLUTTER_ACTOR (self)); + clutter_actor_set_name (self->bg, "Background"); + + self->label = clutter_text_new (); + clutter_actor_set_parent (self->label, CLUTTER_ACTOR (self)); + clutter_actor_set_name (self->label, "Label"); + + clutter_actor_pop_internal (CLUTTER_ACTOR (self)); + + self->tex = clutter_texture_new (); + clutter_actor_set_parent (self->tex, CLUTTER_ACTOR (self)); + clutter_actor_set_name (self->tex, "Texture"); +} + +static void +on_destroy (ClutterActor *actor, + gpointer data) +{ + gboolean *destroy_called = data; + + *destroy_called = TRUE; +} + +static void +actor_destruction (void) +{ + ClutterActor *test = g_object_new (TEST_TYPE_DESTROY, NULL); + ClutterActor *child = clutter_rectangle_new (); + gboolean destroy_called = FALSE; + + g_object_ref_sink (test); + + g_object_add_weak_pointer (G_OBJECT (test), (gpointer *) &test); + g_object_add_weak_pointer (G_OBJECT (child), (gpointer *) &child); + + if (g_test_verbose ()) + g_print ("Adding external child...\n"); + + clutter_actor_set_name (child, "Child"); + clutter_container_add_actor (CLUTTER_CONTAINER (test), child); + g_signal_connect (child, "destroy", G_CALLBACK (on_destroy), &destroy_called); + + if (g_test_verbose ()) + g_print ("Calling destroy()...\n"); + + clutter_actor_destroy (test); + g_assert (destroy_called); + g_assert_null (child); + g_assert_null (test); +} + +CLUTTER_TEST_SUITE ( + CLUTTER_TEST_UNIT ("/actor/destruction", actor_destruction) +) diff --git a/clutter/tests/conform/actor-graph.c b/clutter/tests/conform/actor-graph.c new file mode 100644 index 0000000..0dad49b --- /dev/null +++ b/clutter/tests/conform/actor-graph.c @@ -0,0 +1,549 @@ +#include + +static void +actor_add_child (void) +{ + ClutterActor *actor = clutter_actor_new (); + ClutterActor *iter; + + g_object_ref_sink (actor); + g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor); + + clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, + "name", "foo", + NULL)); + clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, + "name", "bar", + NULL)); + clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, + "name", "baz", + NULL)); + + g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 3); + + iter = clutter_actor_get_first_child (actor); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo"); + + iter = clutter_actor_get_next_sibling (iter); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar"); + + iter = clutter_actor_get_next_sibling (iter); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "baz"); + g_assert (iter == clutter_actor_get_last_child (actor)); + g_assert (clutter_actor_get_next_sibling (iter) == NULL); + + iter = clutter_actor_get_last_child (actor); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "baz"); + + iter = clutter_actor_get_previous_sibling (iter); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar"); + + iter = clutter_actor_get_previous_sibling (iter); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo"); + g_assert (iter == clutter_actor_get_first_child (actor)); + g_assert (clutter_actor_get_previous_sibling (iter) == NULL); + + clutter_actor_destroy (actor); + g_assert (actor == NULL); +} + +static void +actor_insert_child (void) +{ + ClutterActor *actor = clutter_actor_new (); + ClutterActor *iter; + + g_object_ref_sink (actor); + g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor); + + clutter_actor_insert_child_at_index (actor, + g_object_new (CLUTTER_TYPE_ACTOR, + "name", "foo", + NULL), + 0); + + iter = clutter_actor_get_first_child (actor); + g_assert (iter != NULL); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo"); + g_assert (iter == clutter_actor_get_child_at_index (actor, 0)); + + clutter_actor_insert_child_below (actor, + g_object_new (CLUTTER_TYPE_ACTOR, + "name", "bar", + NULL), + iter); + + g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 2); + + iter = clutter_actor_get_first_child (actor); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar"); + iter = clutter_actor_get_next_sibling (iter); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo"); + g_assert (iter == clutter_actor_get_child_at_index (actor, 1)); + + iter = clutter_actor_get_first_child (actor); + clutter_actor_insert_child_above (actor, + g_object_new (CLUTTER_TYPE_ACTOR, + "name", "baz", + NULL), + iter); + + iter = clutter_actor_get_last_child (actor); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo"); + + iter = clutter_actor_get_previous_sibling (iter); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "baz"); + + iter = clutter_actor_get_previous_sibling (iter); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar"); + + clutter_actor_remove_all_children (actor); + + clutter_actor_insert_child_at_index (actor, + g_object_new (CLUTTER_TYPE_ACTOR, + "name", "1", + NULL), + 0); + iter = clutter_actor_get_child_at_index (actor, 0); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "1"); + g_assert (clutter_actor_get_first_child (actor) == iter); + g_assert (clutter_actor_get_last_child (actor) == iter); + + clutter_actor_insert_child_at_index (actor, + g_object_new (CLUTTER_TYPE_ACTOR, + "name", "2", + NULL), + 0); + iter = clutter_actor_get_child_at_index (actor, 0); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "2"); + g_assert (clutter_actor_get_first_child (actor) == iter); + iter = clutter_actor_get_child_at_index (actor, 1); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "1"); + g_assert (clutter_actor_get_last_child (actor) == iter); + + clutter_actor_insert_child_at_index (actor, + g_object_new (CLUTTER_TYPE_ACTOR, + "name", "3", + NULL), + -1); + iter = clutter_actor_get_child_at_index (actor, 2); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "3"); + g_assert (clutter_actor_get_last_child (actor) == iter); + + clutter_actor_destroy (actor); + g_assert (actor == NULL); +} + +static void +actor_remove_child (void) +{ + ClutterActor *actor = clutter_actor_new (); + ClutterActor *iter; + + g_object_ref_sink (actor); + g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor); + + clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, + "name", "foo", + NULL)); + clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, + "name", "bar", + NULL)); + + g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 2); + + g_assert (clutter_actor_get_first_child (actor) != clutter_actor_get_last_child (actor)); + + iter = clutter_actor_get_first_child (actor); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo"); + + iter = clutter_actor_get_last_child (actor); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar"); + + clutter_actor_remove_child (actor, clutter_actor_get_first_child (actor)); + + g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 1); + + iter = clutter_actor_get_first_child (actor); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar"); + g_assert (clutter_actor_get_first_child (actor) == clutter_actor_get_last_child (actor)); + + clutter_actor_remove_child (actor, clutter_actor_get_first_child (actor)); + + g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 0); + g_assert (clutter_actor_get_first_child (actor) == NULL); + g_assert (clutter_actor_get_last_child (actor) == NULL); + + clutter_actor_destroy (actor); + g_assert (actor == NULL); +} + +static void +actor_raise_child (void) +{ + ClutterActor *actor = clutter_actor_new (); + ClutterActor *iter; + gboolean show_on_set_parent; + + g_object_ref_sink (actor); + g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor); + + clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, + "name", "foo", + "visible", FALSE, + NULL)); + clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, + "name", "bar", + "visible", FALSE, + NULL)); + clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, + "name", "baz", + "visible", FALSE, + NULL)); + + g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 3); + + iter = clutter_actor_get_child_at_index (actor, 1); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar"); + + clutter_actor_set_child_above_sibling (actor, iter, + clutter_actor_get_child_at_index (actor, 2)); + + g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 0)), + ==, + "foo"); + g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 1)), + ==, + "baz"); + g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 2)), + ==, + "bar"); + g_assert (!clutter_actor_is_visible (iter)); + g_object_get (iter, "show-on-set-parent", &show_on_set_parent, NULL); + g_assert (!show_on_set_parent); + + iter = clutter_actor_get_child_at_index (actor, 0); + clutter_actor_set_child_above_sibling (actor, iter, NULL); + g_object_add_weak_pointer (G_OBJECT (iter), (gpointer *) &iter); + + g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 0)), + ==, + "baz"); + g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 1)), + ==, + "bar"); + g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 2)), + ==, + "foo"); + g_assert (!clutter_actor_is_visible (iter)); + g_object_get (iter, "show-on-set-parent", &show_on_set_parent, NULL); + g_assert (!show_on_set_parent); + + clutter_actor_destroy (actor); + g_assert (actor == NULL); + g_assert (iter == NULL); +} + +static void +actor_lower_child (void) +{ + ClutterActor *actor = clutter_actor_new (); + ClutterActor *iter; + gboolean show_on_set_parent; + + g_object_ref_sink (actor); + g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor); + + clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, + "name", "foo", + "visible", FALSE, + NULL)); + clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, + "name", "bar", + "visible", FALSE, + NULL)); + clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, + "name", "baz", + "visible", FALSE, + NULL)); + + g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 3); + + iter = clutter_actor_get_child_at_index (actor, 1); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar"); + + clutter_actor_set_child_below_sibling (actor, iter, + clutter_actor_get_child_at_index (actor, 0)); + + g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 0)), + ==, + "bar"); + g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 1)), + ==, + "foo"); + g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 2)), + ==, + "baz"); + g_assert (!clutter_actor_is_visible (iter)); + g_object_get (iter, "show-on-set-parent", &show_on_set_parent, NULL); + g_assert (!show_on_set_parent); + + iter = clutter_actor_get_child_at_index (actor, 2); + clutter_actor_set_child_below_sibling (actor, iter, NULL); + + g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 0)), + ==, + "baz"); + g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 1)), + ==, + "bar"); + g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 2)), + ==, + "foo"); + g_assert (!clutter_actor_is_visible (iter)); + g_object_get (iter, "show-on-set-parent", &show_on_set_parent, NULL); + g_assert (!show_on_set_parent); + + clutter_actor_destroy (actor); + g_assert (actor == NULL); +} + +static void +actor_replace_child (void) +{ + ClutterActor *actor = clutter_actor_new (); + ClutterActor *iter; + + g_object_ref_sink (actor); + g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor); + + clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, + "name", "foo", + NULL)); + clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, + "name", "bar", + NULL)); + + iter = clutter_actor_get_child_at_index (actor, 0); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo"); + + clutter_actor_replace_child (actor, iter, + g_object_new (CLUTTER_TYPE_ACTOR, + "name", "baz", + NULL)); + + iter = clutter_actor_get_child_at_index (actor, 0); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "baz"); + + iter = clutter_actor_get_child_at_index (actor, 1); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar"); + + clutter_actor_replace_child (actor, iter, + g_object_new (CLUTTER_TYPE_ACTOR, + "name", "qux", + NULL)); + + iter = clutter_actor_get_child_at_index (actor, 0); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "baz"); + + iter = clutter_actor_get_child_at_index (actor, 1); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "qux"); + + clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, + "name", "foo")); + + clutter_actor_replace_child (actor, iter, + g_object_new (CLUTTER_TYPE_ACTOR, + "name", "bar", + NULL)); + + iter = clutter_actor_get_last_child (actor); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo"); + iter = clutter_actor_get_previous_sibling (iter); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar"); + iter = clutter_actor_get_previous_sibling (iter); + g_assert_cmpstr (clutter_actor_get_name (iter), ==, "baz"); + + clutter_actor_destroy (actor); + g_assert (actor == NULL); +} + +static void +actor_remove_all (void) +{ + ClutterActor *actor = clutter_actor_new (); + + g_object_ref_sink (actor); + g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor); + + clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, + "name", "foo", + NULL)); + clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, + "name", "bar", + NULL)); + clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, + "name", "baz", + NULL)); + + g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 3); + + clutter_actor_remove_all_children (actor); + + g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 0); + + clutter_actor_destroy (actor); + g_assert (actor == NULL); +} + +static void +actor_added (ClutterContainer *container, + ClutterActor *child, + gpointer data) +{ + ClutterActor *actor = CLUTTER_ACTOR (container); + int *counter = data; + ClutterActor *old_child; + + if (g_test_verbose ()) + g_print ("Adding actor '%s'\n", clutter_actor_get_name (child)); + + old_child = clutter_actor_get_child_at_index (actor, 0); + if (old_child != child) + clutter_actor_remove_child (actor, old_child); + + *counter += 1; +} + +static void +actor_removed (ClutterContainer *container, + ClutterActor *child, + gpointer data) +{ + int *counter = data; + + if (g_test_verbose ()) + g_print ("Removing actor '%s'\n", clutter_actor_get_name (child)); + + *counter += 1; +} + +static void +actor_container_signals (void) +{ + ClutterActor *actor = clutter_actor_new (); + int add_count, remove_count; + + g_object_ref_sink (actor); + g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor); + + add_count = remove_count = 0; + g_signal_connect (actor, + "actor-added", G_CALLBACK (actor_added), + &add_count); + g_signal_connect (actor, + "actor-removed", G_CALLBACK (actor_removed), + &remove_count); + + clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, + "name", "foo", + NULL)); + + g_assert_cmpint (add_count, ==, 1); + g_assert_cmpint (remove_count, ==, 0); + g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 1); + + clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, + "name", "bar", + NULL)); + + g_assert_cmpint (add_count, ==, 2); + g_assert_cmpint (remove_count, ==, 1); + g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 1); + + g_signal_handlers_disconnect_by_func (actor, G_CALLBACK (actor_added), + &add_count); + g_signal_handlers_disconnect_by_func (actor, G_CALLBACK (actor_removed), + &remove_count); + + clutter_actor_destroy (actor); + g_assert (actor == NULL); +} + +static void +actor_contains (void) +{ + /* This build up the following tree: + * + * a + * ╱ │ ╲ + * ╱ │ ╲ + * b c d + * ╱ ╲ ╱ ╲ ╱ ╲ + * e f g h i j + */ + struct { + ClutterActor *actor_a, *actor_b, *actor_c, *actor_d, *actor_e; + ClutterActor *actor_f, *actor_g, *actor_h, *actor_i, *actor_j; + } d; + int x, y; + ClutterActor **actor_array = &d.actor_a; + + /* Matrix of expected results */ + static const gboolean expected_results[] = + { /* a, b, c, d, e, f, g, h, i, j */ + /* a */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* b */ 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, + /* c */ 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, + /* d */ 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, + /* e */ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + /* f */ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + /* g */ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + /* h */ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + /* i */ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + /* j */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 + }; + + d.actor_a = clutter_actor_new (); + d.actor_b = clutter_actor_new (); + d.actor_c = clutter_actor_new (); + d.actor_d = clutter_actor_new (); + d.actor_e = clutter_actor_new (); + d.actor_f = clutter_actor_new (); + d.actor_g = clutter_actor_new (); + d.actor_h = clutter_actor_new (); + d.actor_i = clutter_actor_new (); + d.actor_j = clutter_actor_new (); + + clutter_actor_add_child (d.actor_a, d.actor_b); + clutter_actor_add_child (d.actor_a, d.actor_c); + clutter_actor_add_child (d.actor_a, d.actor_d); + + clutter_actor_add_child (d.actor_b, d.actor_e); + clutter_actor_add_child (d.actor_b, d.actor_f); + + clutter_actor_add_child (d.actor_c, d.actor_g); + clutter_actor_add_child (d.actor_c, d.actor_h); + + clutter_actor_add_child (d.actor_d, d.actor_i); + clutter_actor_add_child (d.actor_d, d.actor_j); + + for (y = 0; y < 10; y++) + for (x = 0; x < 10; x++) + g_assert_cmpint (clutter_actor_contains (actor_array[x], + actor_array[y]), + ==, + expected_results[x * 10 + y]); +} + +CLUTTER_TEST_SUITE ( + CLUTTER_TEST_UNIT ("/actor/graph/add-child", actor_add_child) + CLUTTER_TEST_UNIT ("/actor/graph/insert-child", actor_insert_child) + CLUTTER_TEST_UNIT ("/actor/graph/remove-child", actor_remove_child) + CLUTTER_TEST_UNIT ("/actor/graph/raise-child", actor_raise_child) + CLUTTER_TEST_UNIT ("/actor/graph/lower-child", actor_lower_child) + CLUTTER_TEST_UNIT ("/actor/graph/replace-child", actor_replace_child) + CLUTTER_TEST_UNIT ("/actor/graph/remove-all", actor_remove_all) + CLUTTER_TEST_UNIT ("/actor/graph/container-signals", actor_container_signals) + CLUTTER_TEST_UNIT ("/actor/graph/contains", actor_contains) +) diff --git a/clutter/tests/conform/actor-invariants.c b/clutter/tests/conform/actor-invariants.c new file mode 100644 index 0000000..87df90b --- /dev/null +++ b/clutter/tests/conform/actor-invariants.c @@ -0,0 +1,371 @@ +#include +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include + +static void +actor_initial_state (void) +{ + ClutterActor *actor; + + actor = clutter_actor_new (); + g_object_ref_sink (actor); + g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor); + + if (g_test_verbose ()) + g_print ("initial state - visible: %s, realized: %s, mapped: %s\n", + CLUTTER_ACTOR_IS_VISIBLE (actor) ? "yes" : "no", + CLUTTER_ACTOR_IS_REALIZED (actor) ? "yes" : "no", + CLUTTER_ACTOR_IS_MAPPED (actor) ? "yes" : "no"); + + g_assert (!(CLUTTER_ACTOR_IS_REALIZED (actor))); + g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor))); + g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (actor))); + + clutter_actor_destroy (actor); + g_assert (actor == NULL); +} + +static void +actor_shown_not_parented (void) +{ + ClutterActor *actor; + + actor = clutter_actor_new (); + g_object_ref_sink (actor); + g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor); + + clutter_actor_show (actor); + + if (g_test_verbose ()) + g_print ("show without a parent - visible: %s, realized: %s, mapped: %s\n", + CLUTTER_ACTOR_IS_VISIBLE (actor) ? "yes" : "no", + CLUTTER_ACTOR_IS_REALIZED (actor) ? "yes" : "no", + CLUTTER_ACTOR_IS_MAPPED (actor) ? "yes" : "no"); + + g_assert (!CLUTTER_ACTOR_IS_REALIZED (actor)); + g_assert (!CLUTTER_ACTOR_IS_MAPPED (actor)); + g_assert (CLUTTER_ACTOR_IS_VISIBLE (actor)); + + clutter_actor_destroy (actor); + g_assert (actor == NULL); +} + +static void +actor_realized (void) +{ + ClutterActor *actor; + ClutterActor *stage; + + stage = clutter_test_get_stage (); + + actor = clutter_actor_new (); + + g_assert (!(CLUTTER_ACTOR_IS_REALIZED (actor))); + + clutter_actor_hide (actor); /* don't show, so won't map */ + clutter_actor_add_child (stage, actor); + clutter_actor_realize (actor); + + g_assert (CLUTTER_ACTOR_IS_REALIZED (actor)); + + g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor))); + g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (actor))); +} + +static void +actor_mapped (void) +{ + ClutterActor *actor; + ClutterActor *stage; + + stage = clutter_test_get_stage (); + clutter_actor_show (stage); + + actor = clutter_actor_new (); + + g_assert (!(CLUTTER_ACTOR_IS_REALIZED (actor))); + g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor))); + + clutter_actor_add_child (stage, actor); + + if (g_test_verbose ()) + g_print ("adding to a container should map - " + "visible: %s, realized: %s, mapped: %s\n", + CLUTTER_ACTOR_IS_VISIBLE (actor) ? "yes" : "no", + CLUTTER_ACTOR_IS_REALIZED (actor) ? "yes" : "no", + CLUTTER_ACTOR_IS_MAPPED (actor) ? "yes" : "no"); + + g_assert (CLUTTER_ACTOR_IS_REALIZED (actor)); + g_assert (CLUTTER_ACTOR_IS_MAPPED (actor)); + g_assert (CLUTTER_ACTOR_IS_VISIBLE (actor)); + + clutter_actor_hide (actor); + + if (g_test_verbose ()) + g_print ("hiding should unmap - " + "visible: %s, realized: %s, mapped: %s\n", + CLUTTER_ACTOR_IS_VISIBLE (actor) ? "yes" : "no", + CLUTTER_ACTOR_IS_REALIZED (actor) ? "yes" : "no", + CLUTTER_ACTOR_IS_MAPPED (actor) ? "yes" : "no"); + + g_assert (CLUTTER_ACTOR_IS_REALIZED (actor)); + g_assert (!CLUTTER_ACTOR_IS_MAPPED (actor)); + g_assert (!CLUTTER_ACTOR_IS_VISIBLE (actor)); +} + +static void +actor_visibility_not_recursive (void) +{ + ClutterActor *actor, *group; + ClutterActor *stage; + + stage = clutter_test_get_stage (); + + group = clutter_actor_new (); + actor = clutter_actor_new (); + + clutter_actor_hide (group); /* don't show, so won't map */ + clutter_actor_hide (actor); /* don't show, so won't map */ + + g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (stage))); + g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (group))); + g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (actor))); + + clutter_actor_add_child (stage, group); + clutter_actor_add_child (group, actor); + + clutter_actor_show (actor); + g_assert (CLUTTER_ACTOR_IS_VISIBLE (actor)); + g_assert (!CLUTTER_ACTOR_IS_VISIBLE (group)); + g_assert (!CLUTTER_ACTOR_IS_VISIBLE (stage)); + + clutter_actor_show (stage); + g_assert (CLUTTER_ACTOR_IS_VISIBLE (actor)); + g_assert (!CLUTTER_ACTOR_IS_VISIBLE (group)); + g_assert (CLUTTER_ACTOR_IS_VISIBLE (stage)); + + clutter_actor_hide (actor); + clutter_actor_hide (group); + clutter_actor_hide (stage); + g_assert (!CLUTTER_ACTOR_IS_VISIBLE (actor)); + + clutter_actor_show (stage); + g_assert (!CLUTTER_ACTOR_IS_VISIBLE (actor)); +} + +static void +actor_realize_not_recursive (void) +{ + ClutterActor *actor, *group; + ClutterActor *stage; + + stage = clutter_test_get_stage (); + clutter_actor_show (stage); + + group = clutter_actor_new (); + + actor = clutter_actor_new (); + + clutter_actor_hide (group); /* don't show, so won't map */ + clutter_actor_hide (actor); /* don't show, so won't map */ + + g_assert (!(CLUTTER_ACTOR_IS_REALIZED (group))); + g_assert (!(CLUTTER_ACTOR_IS_REALIZED (actor))); + + clutter_actor_add_child (stage, group); + clutter_actor_add_child (group, actor); + + clutter_actor_realize (group); + + g_assert (CLUTTER_ACTOR_IS_REALIZED (group)); + + g_assert (!(CLUTTER_ACTOR_IS_MAPPED (group))); + g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (group))); + + /* realizing group did not realize the child */ + g_assert (!CLUTTER_ACTOR_IS_REALIZED (actor)); + g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor))); + g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (actor))); +} + +static void +actor_map_recursive (void) +{ + ClutterActor *actor, *group; + ClutterActor *stage; + + stage = clutter_test_get_stage (); + clutter_actor_show (stage); + + group = clutter_actor_new (); + + actor = clutter_actor_new (); + + clutter_actor_hide (group); /* hide at first */ + clutter_actor_show (actor); /* show at first */ + + g_assert (!(CLUTTER_ACTOR_IS_REALIZED (group))); + g_assert (!(CLUTTER_ACTOR_IS_REALIZED (actor))); + g_assert (!(CLUTTER_ACTOR_IS_MAPPED (group))); + g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor))); + g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (group))); + g_assert ((CLUTTER_ACTOR_IS_VISIBLE (actor))); + + clutter_actor_add_child (stage, group); + clutter_actor_add_child (group, actor); + + g_assert (!(CLUTTER_ACTOR_IS_REALIZED (group))); + g_assert (!(CLUTTER_ACTOR_IS_REALIZED (actor))); + g_assert (!(CLUTTER_ACTOR_IS_MAPPED (group))); + g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor))); + g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (group))); + g_assert ((CLUTTER_ACTOR_IS_VISIBLE (actor))); + + /* show group, which should map and realize both + * group and child. + */ + clutter_actor_show (group); + g_assert (CLUTTER_ACTOR_IS_REALIZED (group)); + g_assert (CLUTTER_ACTOR_IS_REALIZED (actor)); + g_assert (CLUTTER_ACTOR_IS_MAPPED (group)); + g_assert (CLUTTER_ACTOR_IS_MAPPED (actor)); + g_assert (CLUTTER_ACTOR_IS_VISIBLE (group)); + g_assert (CLUTTER_ACTOR_IS_VISIBLE (actor)); +} + +static void +actor_show_on_set_parent (void) +{ + ClutterActor *actor, *group; + gboolean show_on_set_parent; + ClutterActor *stage; + + stage = clutter_test_get_stage (); + + group = clutter_actor_new (); + + g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (group))); + + clutter_actor_add_child (stage, group); + + actor = clutter_actor_new (); + g_object_get (actor, + "show-on-set-parent", &show_on_set_parent, + NULL); + + g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (actor))); + g_assert (show_on_set_parent); + + clutter_actor_add_child (group, actor); + g_object_get (actor, + "show-on-set-parent", &show_on_set_parent, + NULL); + + g_assert (CLUTTER_ACTOR_IS_VISIBLE (actor)); + g_assert (show_on_set_parent); + + g_object_ref (actor); + clutter_actor_remove_child (group, actor); + g_object_get (actor, + "show-on-set-parent", &show_on_set_parent, + NULL); + + g_assert (!CLUTTER_ACTOR_IS_REALIZED (actor)); + g_assert (!CLUTTER_ACTOR_IS_MAPPED (actor)); + g_assert (CLUTTER_ACTOR_IS_VISIBLE (actor)); + g_assert (show_on_set_parent); + + clutter_actor_destroy (actor); + clutter_actor_destroy (group); + + actor = clutter_actor_new (); + clutter_actor_add_child (stage, actor); + clutter_actor_hide (actor); + g_object_get (actor, + "show-on-set-parent", &show_on_set_parent, + NULL); + g_assert (!CLUTTER_ACTOR_IS_VISIBLE (actor)); + g_assert (!CLUTTER_ACTOR_IS_MAPPED (actor)); + g_assert (show_on_set_parent); + + clutter_actor_destroy (actor); + + actor = clutter_actor_new (); + clutter_actor_hide (actor); + clutter_actor_add_child (stage, actor); + g_object_get (actor, + "show-on-set-parent", &show_on_set_parent, + NULL); + g_assert (!CLUTTER_ACTOR_IS_VISIBLE (actor)); + g_assert (!CLUTTER_ACTOR_IS_MAPPED (actor)); + g_assert (!show_on_set_parent); + + clutter_actor_destroy (actor); +} + +static void +clone_no_map (void) +{ + ClutterActor *stage; + ClutterActor *group; + ClutterActor *actor; + ClutterActor *clone; + + stage = clutter_test_get_stage (); + clutter_actor_show (stage); + + group = clutter_actor_new (); + actor = clutter_actor_new (); + + clutter_actor_hide (group); + + clutter_actor_add_child (group, actor); + clutter_actor_add_child (stage, group); + + g_assert (!(CLUTTER_ACTOR_IS_MAPPED (group))); + g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor))); + + clone = clutter_clone_new (group); + + clutter_actor_add_child (stage, clone); + + g_assert (CLUTTER_ACTOR_IS_MAPPED (clone)); + g_assert (!(CLUTTER_ACTOR_IS_MAPPED (group))); + g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor))); + + clutter_actor_destroy (CLUTTER_ACTOR (clone)); + clutter_actor_destroy (CLUTTER_ACTOR (group)); +} + +G_GNUC_BEGIN_IGNORE_DEPRECATIONS +static void +default_stage (void) +{ + ClutterActor *stage, *def_stage; + + stage = clutter_test_get_stage (); + def_stage = clutter_stage_get_default (); + + if (clutter_feature_available (CLUTTER_FEATURE_STAGE_MULTIPLE)) + g_assert (stage != def_stage); + else + g_assert (stage == def_stage); + + g_assert (CLUTTER_ACTOR_IS_REALIZED (def_stage)); +} +G_GNUC_END_IGNORE_DEPRECATIONS + +CLUTTER_TEST_SUITE ( + CLUTTER_TEST_UNIT ("/actor/invariants/initial-state", actor_initial_state) + CLUTTER_TEST_UNIT ("/actor/invariants/show-not-parented", actor_shown_not_parented) + CLUTTER_TEST_UNIT ("/actor/invariants/realized", actor_realized) + CLUTTER_TEST_UNIT ("/actor/invariants/mapped", actor_mapped) + CLUTTER_TEST_UNIT ("/actor/invariants/visibility-not-recursive", actor_visibility_not_recursive) + CLUTTER_TEST_UNIT ("/actor/invariants/realize-not-recursive", actor_realize_not_recursive) + CLUTTER_TEST_UNIT ("/actor/invariants/map-recursive", actor_map_recursive) + CLUTTER_TEST_UNIT ("/actor/invariants/show-on-set-parent", actor_show_on_set_parent) + CLUTTER_TEST_UNIT ("/actor/invariants/clone-no-map", clone_no_map) + CLUTTER_TEST_UNIT ("/actor/invariants/default-stage", default_stage) +) diff --git a/clutter/tests/conform/actor-iter.c b/clutter/tests/conform/actor-iter.c new file mode 100644 index 0000000..193f63b --- /dev/null +++ b/clutter/tests/conform/actor-iter.c @@ -0,0 +1,218 @@ +#include +#include + +static void +actor_iter_traverse_children (void) +{ + ClutterActorIter iter; + ClutterActor *actor; + ClutterActor *child; + int i, n_actors; + + actor = clutter_actor_new (); + clutter_actor_set_name (actor, "root"); + g_object_ref_sink (actor); + + n_actors = g_random_int_range (10, 50); + for (i = 0; i < n_actors; i++) + { + char *name; + + name = g_strdup_printf ("actor%d", i); + child = clutter_actor_new (); + clutter_actor_set_name (child, name); + + clutter_actor_add_child (actor, child); + + g_free (name); + } + + g_assert_cmpint (clutter_actor_get_n_children (actor), ==, n_actors); + + i = 0; + clutter_actor_iter_init (&iter, actor); + g_assert (clutter_actor_iter_is_valid (&iter)); + + while (clutter_actor_iter_next (&iter, &child)) + { + g_assert (CLUTTER_IS_ACTOR (child)); + g_assert (clutter_actor_get_parent (child) == actor); + + if (g_test_verbose ()) + g_print ("actor %d = '%s'\n", i, clutter_actor_get_name (child)); + + if (i == 0) + g_assert (child == clutter_actor_get_first_child (actor)); + + if (i == (n_actors - 1)) + g_assert (child == clutter_actor_get_last_child (actor)); + + i += 1; + } + + g_assert_cmpint (i, ==, n_actors); + + i = 0; + clutter_actor_iter_init (&iter, actor); + g_assert (clutter_actor_iter_is_valid (&iter)); + + while (clutter_actor_iter_prev (&iter, &child)) + { + g_assert (CLUTTER_IS_ACTOR (child)); + g_assert (clutter_actor_get_parent (child) == actor); + + if (g_test_verbose ()) + g_print ("actor %d = '%s'\n", i, clutter_actor_get_name (child)); + + if (i == 0) + g_assert (child == clutter_actor_get_last_child (actor)); + + if (i == (n_actors - 1)) + g_assert (child == clutter_actor_get_first_child (actor)); + + i += 1; + } + + g_object_unref (actor); +} + +static void +actor_iter_traverse_remove (void) +{ + ClutterActorIter iter; + ClutterActor *actor; + ClutterActor *child; + int i, n_actors; + + actor = clutter_actor_new (); + clutter_actor_set_name (actor, "root"); + g_object_ref_sink (actor); + + n_actors = g_random_int_range (10, 50); + for (i = 0; i < n_actors; i++) + { + char *name; + + name = g_strdup_printf ("actor%d", i); + child = clutter_actor_new (); + clutter_actor_set_name (child, name); + + clutter_actor_add_child (actor, child); + + g_free (name); + } + + g_assert_cmpint (clutter_actor_get_n_children (actor), ==, n_actors); + + i = 0; + clutter_actor_iter_init (&iter, actor); + g_assert (clutter_actor_iter_is_valid (&iter)); + + while (clutter_actor_iter_next (&iter, &child)) + { + g_assert (CLUTTER_IS_ACTOR (child)); + g_assert (clutter_actor_get_parent (child) == actor); + + if (g_test_verbose ()) + g_print ("actor %d = '%s'\n", i, clutter_actor_get_name (child)); + + if (i == 0) + g_assert (child == clutter_actor_get_first_child (actor)); + + if (i == (n_actors - 1)) + g_assert (child == clutter_actor_get_last_child (actor)); + + clutter_actor_iter_remove (&iter); + g_assert (clutter_actor_iter_is_valid (&iter)); + + i += 1; + } + + g_assert_cmpint (i, ==, n_actors); + g_assert_cmpint (0, ==, clutter_actor_get_n_children (actor)); +} + +static void +actor_iter_assignment (void) +{ + ClutterActorIter iter_a, iter_b; + ClutterActor *actor; + ClutterActor *child; + int i, n_actors; + + actor = clutter_actor_new (); + clutter_actor_set_name (actor, "root"); + g_object_ref_sink (actor); + + n_actors = g_random_int_range (10, 50); + for (i = 0; i < n_actors; i++) + { + char *name; + + name = g_strdup_printf ("actor[%02d]", i); + child = clutter_actor_new (); + clutter_actor_set_name (child, name); + + clutter_actor_add_child (actor, child); + + g_free (name); + } + + g_assert_cmpint (clutter_actor_get_n_children (actor), ==, n_actors); + + i = 0; + + clutter_actor_iter_init (&iter_a, actor); + + iter_b = iter_a; + + g_assert (clutter_actor_iter_is_valid (&iter_a)); + g_assert (clutter_actor_iter_is_valid (&iter_b)); + + while (clutter_actor_iter_next (&iter_a, &child)) + { + g_assert (CLUTTER_IS_ACTOR (child)); + g_assert (clutter_actor_get_parent (child) == actor); + + if (g_test_verbose ()) + g_print ("actor %2d = '%s'\n", i, clutter_actor_get_name (child)); + + if (i == 0) + g_assert (child == clutter_actor_get_first_child (actor)); + + if (i == (n_actors - 1)) + g_assert (child == clutter_actor_get_last_child (actor)); + + i += 1; + } + + g_assert_cmpint (i, ==, n_actors); + + i = n_actors - 1; + + while (clutter_actor_iter_prev (&iter_b, &child)) + { + g_assert (clutter_actor_get_parent (child) == actor); + + if (g_test_verbose ()) + g_print ("actor %2d = '%s'\n", i, clutter_actor_get_name (child)); + + if (i == n_actors - 1) + g_assert (child == clutter_actor_get_last_child (actor)); + + if (i == 0) + g_assert (child == clutter_actor_get_first_child (actor)); + + i -= 1; + } + + g_assert_cmpint (i, ==, -1); + + g_object_unref (actor); +} + +CLUTTER_TEST_SUITE ( + CLUTTER_TEST_UNIT ("/actor/iter/traverse-children", actor_iter_traverse_children) + CLUTTER_TEST_UNIT ("/actor/iter/traverse-remove", actor_iter_traverse_remove) + CLUTTER_TEST_UNIT ("/actor/iter/assignment", actor_iter_assignment) +) diff --git a/clutter/tests/conform/actor-layout.c b/clutter/tests/conform/actor-layout.c new file mode 100644 index 0000000..2cc8940 --- /dev/null +++ b/clutter/tests/conform/actor-layout.c @@ -0,0 +1,92 @@ +#include + +static void +actor_basic_layout (void) +{ + ClutterActor *stage = clutter_test_get_stage (); + ClutterActor *vase; + ClutterActor *flower[3]; + ClutterPoint p; + + vase = clutter_actor_new (); + clutter_actor_set_name (vase, "Vase"); + clutter_actor_set_layout_manager (vase, clutter_flow_layout_new (CLUTTER_FLOW_HORIZONTAL)); + clutter_actor_add_child (stage, vase); + + flower[0] = clutter_actor_new (); + clutter_actor_set_background_color (flower[0], CLUTTER_COLOR_Red); + clutter_actor_set_size (flower[0], 100, 100); + clutter_actor_set_name (flower[0], "Red Flower"); + clutter_actor_add_child (vase, flower[0]); + + flower[1] = clutter_actor_new (); + clutter_actor_set_background_color (flower[1], CLUTTER_COLOR_Yellow); + clutter_actor_set_size (flower[1], 100, 100); + clutter_actor_set_name (flower[1], "Yellow Flower"); + clutter_actor_add_child (vase, flower[1]); + + flower[2] = clutter_actor_new (); + clutter_actor_set_background_color (flower[2], CLUTTER_COLOR_Green); + clutter_actor_set_size (flower[2], 100, 100); + clutter_actor_set_name (flower[2], "Green Flower"); + clutter_actor_add_child (vase, flower[2]); + + clutter_point_init (&p, 50, 50); + clutter_test_assert_actor_at_point (stage, &p, flower[0]); + + clutter_point_init (&p, 150, 50); + clutter_test_assert_actor_at_point (stage, &p, flower[1]); + + clutter_point_init (&p, 250, 50); + clutter_test_assert_actor_at_point (stage, &p, flower[2]); +} + +static void +actor_margin_layout (void) +{ + ClutterActor *stage = clutter_test_get_stage (); + ClutterActor *vase; + ClutterActor *flower[3]; + ClutterPoint p; + + vase = clutter_actor_new (); + clutter_actor_set_name (vase, "Vase"); + clutter_actor_set_layout_manager (vase, clutter_box_layout_new ()); + clutter_actor_add_child (stage, vase); + + flower[0] = clutter_actor_new (); + clutter_actor_set_background_color (flower[0], CLUTTER_COLOR_Red); + clutter_actor_set_size (flower[0], 100, 100); + clutter_actor_set_name (flower[0], "Red Flower"); + clutter_actor_add_child (vase, flower[0]); + + flower[1] = clutter_actor_new (); + clutter_actor_set_background_color (flower[1], CLUTTER_COLOR_Yellow); + clutter_actor_set_size (flower[1], 100, 100); + clutter_actor_set_name (flower[1], "Yellow Flower"); + clutter_actor_set_margin_right (flower[1], 6); + clutter_actor_set_margin_left (flower[1], 6); + clutter_actor_add_child (vase, flower[1]); + + flower[2] = clutter_actor_new (); + clutter_actor_set_background_color (flower[2], CLUTTER_COLOR_Green); + clutter_actor_set_size (flower[2], 100, 100); + clutter_actor_set_name (flower[2], "Green Flower"); + clutter_actor_set_margin_top (flower[2], 6); + clutter_actor_set_margin_bottom (flower[2], 6); + clutter_actor_add_child (vase, flower[2]); + + clutter_point_init (&p, 0, 7); + clutter_test_assert_actor_at_point (stage, &p, flower[0]); + + clutter_point_init (&p, 106, 50); + clutter_test_assert_actor_at_point (stage, &p, flower[1]); + + clutter_point_init (&p, 212, 7); + clutter_test_assert_actor_at_point (stage, &p, flower[2]); +} + +CLUTTER_TEST_SUITE ( + CLUTTER_TEST_UNIT ("/actor/layout/basic", actor_basic_layout) + CLUTTER_TEST_UNIT ("/actor/layout/margin", actor_margin_layout) +) diff --git a/clutter/tests/conform/actor-meta.c b/clutter/tests/conform/actor-meta.c new file mode 100644 index 0000000..52a313d --- /dev/null +++ b/clutter/tests/conform/actor-meta.c @@ -0,0 +1,40 @@ +#include +#include + +#include + +static void +actor_meta_clear (void) +{ + ClutterActor *actor, *stage; + + stage = clutter_test_get_stage (); + + actor = clutter_actor_new (); + g_object_ref_sink (actor); + g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor); + + clutter_actor_add_action (actor, clutter_click_action_new ()); + clutter_actor_add_constraint (actor, clutter_bind_constraint_new (stage, CLUTTER_BIND_ALL, 0)); + clutter_actor_add_effect (actor, clutter_blur_effect_new ()); + + g_assert (clutter_actor_has_actions (actor)); + g_assert (clutter_actor_has_constraints (actor)); + g_assert (clutter_actor_has_effects (actor)); + + clutter_actor_clear_actions (actor); + g_assert (!clutter_actor_has_actions (actor)); + + clutter_actor_clear_constraints (actor); + g_assert (!clutter_actor_has_constraints (actor)); + + clutter_actor_clear_effects (actor); + g_assert (!clutter_actor_has_effects (actor)); + + clutter_actor_destroy (actor); + g_assert (actor == NULL); +} + +CLUTTER_TEST_SUITE ( + CLUTTER_TEST_UNIT ("/actor/meta/clear", actor_meta_clear) +) diff --git a/clutter/tests/conform/actor-offscreen-limit-max-size.c b/clutter/tests/conform/actor-offscreen-limit-max-size.c new file mode 100644 index 0000000..943c7d8 --- /dev/null +++ b/clutter/tests/conform/actor-offscreen-limit-max-size.c @@ -0,0 +1,119 @@ +#define CLUTTER_ENABLE_EXPERIMENTAL_API +#include + +#define STAGE_WIDTH (300) +#define STAGE_HEIGHT (300) + +typedef struct +{ + ClutterActor *stage; + + ClutterActor *actor_group1; + ClutterEffect *blur_effect1; + + ClutterActor *actor_group2; + ClutterEffect *blur_effect2; +} Data; + +static void +check_results (ClutterStage *stage, gpointer user_data) +{ + Data *data = user_data; + gfloat width, height; + ClutterRect rect; + + clutter_offscreen_effect_get_target_rect (CLUTTER_OFFSCREEN_EFFECT (data->blur_effect1), + &rect); + + width = clutter_rect_get_width (&rect); + height = clutter_rect_get_height (&rect); + + if (g_test_verbose ()) + g_print ("Checking effect1 size: %.2f x %.2f\n", + clutter_rect_get_width (&rect), + clutter_rect_get_height (&rect)); + + g_assert_cmpint (width, <, STAGE_WIDTH); + g_assert_cmpint (height, <, STAGE_HEIGHT); + + clutter_offscreen_effect_get_target_rect (CLUTTER_OFFSCREEN_EFFECT (data->blur_effect2), + &rect); + + width = clutter_rect_get_width (&rect); + height = clutter_rect_get_height (&rect); + + if (g_test_verbose ()) + g_print ("Checking effect2 size: %.2f x %.2f\n", width, height); + + g_assert_cmpint (width, ==, STAGE_WIDTH); + g_assert_cmpint (height, ==, STAGE_HEIGHT); + + + clutter_main_quit (); +} + +static ClutterActor * +create_actor (gfloat x, gfloat y, + gfloat width, gfloat height, + const ClutterColor *color) +{ + return g_object_new (CLUTTER_TYPE_ACTOR, + "x", x, + "y", y, + "width", width, + "height", height, + "background-color", color, + NULL); +} + +static void +actor_offscreen_limit_max_size (void) +{ + Data data; + + if (!cogl_features_available (COGL_FEATURE_OFFSCREEN)) + return; + + data.stage = clutter_test_get_stage (); + g_signal_connect (data.stage, "after-paint", + G_CALLBACK (check_results), &data); + clutter_actor_set_size (data.stage, STAGE_WIDTH, STAGE_HEIGHT); + + data.actor_group1 = clutter_actor_new (); + clutter_actor_add_child (data.stage, data.actor_group1); + data.blur_effect1 = clutter_blur_effect_new (); + clutter_actor_add_effect (data.actor_group1, data.blur_effect1); + clutter_actor_add_child (data.actor_group1, + create_actor (10, 10, + 100, 100, + CLUTTER_COLOR_Blue)); + clutter_actor_add_child (data.actor_group1, + create_actor (100, 100, + 100, 100, + CLUTTER_COLOR_Gray)); + + data.actor_group2 = clutter_actor_new (); + clutter_actor_add_child (data.stage, data.actor_group2); + data.blur_effect2 = clutter_blur_effect_new (); + clutter_actor_add_effect (data.actor_group2, data.blur_effect2); + clutter_actor_add_child (data.actor_group2, + create_actor (-10, -10, + 100, 100, + CLUTTER_COLOR_Yellow)); + clutter_actor_add_child (data.actor_group2, + create_actor (250, 10, + 100, 100, + CLUTTER_COLOR_ScarletRed)); + clutter_actor_add_child (data.actor_group2, + create_actor (10, 250, + 100, 100, + CLUTTER_COLOR_Yellow)); + + clutter_actor_show (data.stage); + + clutter_main (); +} + +CLUTTER_TEST_SUITE ( + CLUTTER_TEST_UNIT ("/actor/offscreen/limit-max-size", actor_offscreen_limit_max_size) +) diff --git a/clutter/tests/conform/actor-offscreen-redirect.c b/clutter/tests/conform/actor-offscreen-redirect.c new file mode 100644 index 0000000..63d5e6c --- /dev/null +++ b/clutter/tests/conform/actor-offscreen-redirect.c @@ -0,0 +1,348 @@ +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include + +typedef struct _FooActor FooActor; +typedef struct _FooActorClass FooActorClass; + +struct _FooActorClass +{ + ClutterActorClass parent_class; +}; + +struct _FooActor +{ + ClutterActor parent; + + guint8 last_paint_opacity; + int paint_count; +}; + +typedef struct +{ + ClutterActor *stage; + FooActor *foo_actor; + ClutterActor *parent_container; + ClutterActor *container; + ClutterActor *child; + ClutterActor *unrelated_actor; + gboolean was_painted; +} Data; + +GType foo_actor_get_type (void) G_GNUC_CONST; + +G_DEFINE_TYPE (FooActor, foo_actor, CLUTTER_TYPE_ACTOR); + +static gboolean group_has_overlaps; + +static void +foo_actor_paint (ClutterActor *actor) +{ + FooActor *foo_actor = (FooActor *) actor; + ClutterActorBox allocation; + + foo_actor->last_paint_opacity = clutter_actor_get_paint_opacity (actor); + foo_actor->paint_count++; + + clutter_actor_get_allocation_box (actor, &allocation); + + /* Paint a red rectangle with the right opacity */ + cogl_set_source_color4ub (255, + 0, + 0, + foo_actor->last_paint_opacity); + cogl_rectangle (allocation.x1, + allocation.y1, + allocation.x2, + allocation.y2); +} + +static gboolean +foo_actor_get_paint_volume (ClutterActor *actor, + ClutterPaintVolume *volume) +{ + return clutter_paint_volume_set_from_allocation (volume, actor); +} + +static gboolean +foo_actor_has_overlaps (ClutterActor *actor) +{ + return FALSE; +} + +static void +foo_actor_class_init (FooActorClass *klass) +{ + ClutterActorClass *actor_class = (ClutterActorClass *) klass; + + actor_class->paint = foo_actor_paint; + actor_class->get_paint_volume = foo_actor_get_paint_volume; + actor_class->has_overlaps = foo_actor_has_overlaps; +} + +static void +foo_actor_init (FooActor *self) +{ +} + +typedef struct _FooGroup FooGroup; +typedef struct _FooGroupClass FooGroupClass; + +struct _FooGroupClass +{ + ClutterActorClass parent_class; +}; + +struct _FooGroup +{ + ClutterActor parent; +}; + +GType foo_group_get_type (void); + +G_DEFINE_TYPE (FooGroup, foo_group, CLUTTER_TYPE_ACTOR) + +static gboolean +foo_group_has_overlaps (ClutterActor *actor) +{ + return group_has_overlaps; +} + +static void +foo_group_class_init (FooGroupClass *klass) +{ + ClutterActorClass *actor_class = (ClutterActorClass *) klass; + + actor_class->has_overlaps = foo_group_has_overlaps; +} + +static void +foo_group_init (FooGroup *self) +{ +} + +static void +verify_results (Data *data, + guint8 expected_color_red, + guint8 expected_color_green, + guint8 expected_color_blue, + int expected_paint_count, + int expected_paint_opacity) +{ + guchar *pixel; + + data->foo_actor->paint_count = 0; + + /* Read a pixel at the center of the to determine what color it + painted. This should cause a redraw */ + pixel = clutter_stage_read_pixels (CLUTTER_STAGE (data->stage), + 50, 50, /* x/y */ + 1, 1 /* width/height */); + + g_assert_cmpint (expected_paint_count, ==, data->foo_actor->paint_count); + g_assert_cmpint (expected_paint_opacity, + ==, + data->foo_actor->last_paint_opacity); + + g_assert_cmpint (ABS ((int) expected_color_red - (int) pixel[0]), <=, 2); + g_assert_cmpint (ABS ((int) expected_color_green - (int) pixel[1]), <=, 2); + g_assert_cmpint (ABS ((int) expected_color_blue - (int) pixel[2]), <=, 2); + + g_free (pixel); +} + +static void +verify_redraw (Data *data, int expected_paint_count) +{ + GMainLoop *main_loop = g_main_loop_new (NULL, TRUE); + guint paint_handler; + + paint_handler = g_signal_connect_data (data->stage, + "paint", + G_CALLBACK (g_main_loop_quit), + main_loop, + NULL, + G_CONNECT_SWAPPED | G_CONNECT_AFTER); + + /* Queue a redraw on the stage */ + clutter_actor_queue_redraw (data->stage); + + data->foo_actor->paint_count = 0; + + /* Wait for it to paint */ + g_main_loop_run (main_loop); + + g_signal_handler_disconnect (data->stage, paint_handler); + + g_assert_cmpint (data->foo_actor->paint_count, ==, expected_paint_count); +} + +static gboolean +verify_redraws (gpointer user_data) +{ + Data *data = user_data; + + /* Queueing a redraw on the actor should cause a redraw */ + clutter_actor_queue_redraw (data->container); + verify_redraw (data, 1); + + /* Queueing a redraw on a child should cause a redraw */ + clutter_actor_queue_redraw (data->child); + verify_redraw (data, 1); + + /* Modifying the transformation on the parent should cause a + redraw */ + clutter_actor_set_anchor_point (data->parent_container, 0, 1); + verify_redraw (data, 1); + + /* Redrawing an unrelated actor shouldn't cause a redraw */ + clutter_actor_set_position (data->unrelated_actor, 0, 1); + verify_redraw (data, 0); + + data->was_painted = TRUE; + + return G_SOURCE_REMOVE; +} + +static gboolean +run_verify (gpointer user_data) +{ + Data *data = user_data; + + group_has_overlaps = FALSE; + + /* By default the actor shouldn't be redirected so the redraw should + cause the actor to be painted */ + verify_results (data, + 255, 0, 0, + 1, + 255); + + /* Make the actor semi-transparent and verify the paint opacity */ + clutter_actor_set_opacity (data->container, 127); + verify_results (data, + 255, 127, 127, + 1, + 127); + + /* With automatic redirect for opacity it shouldn't redirect if + * has_overlaps returns FALSE; */ + clutter_actor_set_offscreen_redirect + (data->container, CLUTTER_OFFSCREEN_REDIRECT_AUTOMATIC_FOR_OPACITY); + verify_results (data, + 255, 127, 127, + 1, + 127); + + /* We do a double check here to verify that the actor wasn't cached + * during the last check. If it was cached then this check wouldn't + * result in any foo-actor re-paint. */ + verify_results (data, + 255, 127, 127, + 1, + 127); + + /* With automatic redirect for opacity it should redirect if + * has_overlaps returns TRUE. + * The first paint will still cause the actor to draw because + * it needs to fill the cache first. It should be painted with full + * opacity */ + group_has_overlaps = TRUE; + + verify_results (data, + 255, 127, 127, + 1, + 255); + + /* The second time the actor is painted it should be cached */ + verify_results (data, + 255, 127, 127, + 0, + 255); + + /* We should be able to change the opacity without causing the actor + to redraw */ + clutter_actor_set_opacity (data->container, 64); + verify_results (data, + 255, 191, 191, + 0, + 255); + + /* Changing it back to fully opaque should cause it not to go + through the FBO so it will draw */ + clutter_actor_set_opacity (data->container, 255); + verify_results (data, + 255, 0, 0, + 1, + 255); + + /* Tell it to always redirect through the FBO. This should cause a + paint of the actor because the last draw didn't go through the + FBO */ + clutter_actor_set_offscreen_redirect (data->container, + CLUTTER_OFFSCREEN_REDIRECT_ALWAYS); + verify_results (data, + 255, 0, 0, + 1, + 255); + + /* We should be able to change the opacity without causing the actor + to redraw */ + clutter_actor_set_opacity (data->container, 64); + verify_results (data, + 255, 191, 191, + 0, + 255); + + /* Even changing it back to fully opaque shouldn't cause a redraw */ + clutter_actor_set_opacity (data->container, 255); + verify_results (data, + 255, 0, 0, + 0, + 255); + + /* Check redraws */ + g_idle_add (verify_redraws, data); + + return G_SOURCE_REMOVE; +} + +static void +actor_offscreen_redirect (void) +{ + Data data = { 0 }; + + if (!cogl_features_available (COGL_FEATURE_OFFSCREEN)) + return; + + data.stage = clutter_test_get_stage (); + data.parent_container = clutter_actor_new (); + data.container = g_object_new (foo_group_get_type (), NULL); + data.foo_actor = g_object_new (foo_actor_get_type (), NULL); + clutter_actor_set_size (CLUTTER_ACTOR (data.foo_actor), 100, 100); + + clutter_actor_add_child (data.container, CLUTTER_ACTOR (data.foo_actor)); + clutter_actor_add_child (data.parent_container, data.container); + clutter_actor_add_child (data.stage, data.parent_container); + + data.child = clutter_actor_new (); + clutter_actor_set_size (data.child, 1, 1); + clutter_actor_add_child (data.container, data.child); + + data.unrelated_actor = clutter_actor_new (); + clutter_actor_set_size (data.child, 1, 1); + clutter_actor_add_child (data.stage, data.unrelated_actor); + + clutter_actor_show (data.stage); + + clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT, + run_verify, + &data, + NULL); + + while (!data.was_painted) + g_main_context_iteration (NULL, FALSE); +} + +CLUTTER_TEST_SUITE ( + CLUTTER_TEST_UNIT ("/actor/offscreen/redirect", actor_offscreen_redirect) +) diff --git a/clutter/tests/conform/actor-paint-opacity.c b/clutter/tests/conform/actor-paint-opacity.c new file mode 100644 index 0000000..6df2408 --- /dev/null +++ b/clutter/tests/conform/actor-paint-opacity.c @@ -0,0 +1,141 @@ +#include +#include + +static void +opacity_label (void) +{ + ClutterActor *stage; + ClutterActor *label; + ClutterColor label_color = { 255, 0, 0, 128 }; + ClutterColor color_check = { 0, }; + + stage = clutter_test_get_stage (); + + label = clutter_text_new_with_text ("Sans 18px", "Label, 50% opacity"); + clutter_text_set_color (CLUTTER_TEXT (label), &label_color); + + if (g_test_verbose ()) + g_print ("label 50%%.get_color()/1\n"); + clutter_text_get_color (CLUTTER_TEXT (label), &color_check); + g_assert (color_check.alpha == label_color.alpha); + + clutter_actor_add_child (stage, label); + clutter_actor_set_position (label, 10, 10); + + if (g_test_verbose ()) + g_print ("label 50%%.get_color()/2\n"); + clutter_text_get_color (CLUTTER_TEXT (label), &color_check); + g_assert (color_check.alpha == label_color.alpha); + + if (g_test_verbose ()) + g_print ("label 50%%.get_paint_opacity()/1\n"); + g_assert (clutter_actor_get_paint_opacity (label) == 255); + + if (g_test_verbose ()) + g_print ("label 50%%.get_paint_opacity()/2\n"); + clutter_actor_set_opacity (label, 128); + g_assert (clutter_actor_get_paint_opacity (label) == 128); +} + +G_GNUC_BEGIN_IGNORE_DEPRECATIONS +static void +opacity_rectangle (void) +{ + ClutterActor *stage; + ClutterActor *rect; + ClutterColor rect_color = { 0, 0, 255, 255 }; + ClutterColor color_check = { 0, }; + + stage = clutter_test_get_stage (); + + rect = clutter_rectangle_new_with_color (&rect_color); + clutter_actor_set_size (rect, 128, 128); + clutter_actor_set_position (rect, 150, 90); + + if (g_test_verbose ()) + g_print ("rect 100%%.get_color()/1\n"); + clutter_rectangle_get_color (CLUTTER_RECTANGLE (rect), &color_check); + g_assert (color_check.alpha == rect_color.alpha); + + clutter_actor_add_child (stage, rect); + + if (g_test_verbose ()) + g_print ("rect 100%%.get_color()/2\n"); + clutter_rectangle_get_color (CLUTTER_RECTANGLE (rect), &color_check); + g_assert (color_check.alpha == rect_color.alpha); + + if (g_test_verbose ()) + g_print ("rect 100%%.get_paint_opacity()\n"); + g_assert (clutter_actor_get_paint_opacity (rect) == 255); +} +G_GNUC_END_IGNORE_DEPRECATIONS + +G_GNUC_BEGIN_IGNORE_DEPRECATIONS +static void +opacity_paint (void) +{ + ClutterActor *stage, *group1, *group2; + ClutterActor *label, *rect; + ClutterColor label_color = { 255, 0, 0, 128 }; + ClutterColor rect_color = { 0, 0, 255, 255 }; + ClutterColor color_check = { 0, }; + + stage = clutter_test_get_stage (); + + group1 = clutter_group_new (); + clutter_actor_set_opacity (group1, 128); + clutter_container_add (CLUTTER_CONTAINER (stage), group1, NULL); + clutter_actor_set_position (group1, 10, 30); + clutter_actor_show (group1); + + label = clutter_text_new_with_text ("Sans 18px", "Label+Group, 25% opacity"); + clutter_text_set_color (CLUTTER_TEXT (label), &label_color); + + if (g_test_verbose ()) + g_print ("label 50%% + group 50%%.get_color()/1\n"); + clutter_text_get_color (CLUTTER_TEXT (label), &color_check); + g_assert (color_check.alpha == label_color.alpha); + + clutter_container_add (CLUTTER_CONTAINER (group1), label, NULL); + + if (g_test_verbose ()) + g_print ("label 50%% + group 50%%.get_color()/2\n"); + clutter_text_get_color (CLUTTER_TEXT (label), &color_check); + g_assert (color_check.alpha == label_color.alpha); + + if (g_test_verbose ()) + g_print ("label 50%% + group 50%%.get_paint_opacity() = 128\n"); + g_assert (clutter_actor_get_paint_opacity (label) == 128); + + clutter_actor_destroy (label); + + group2 = clutter_group_new (); + clutter_container_add (CLUTTER_CONTAINER (group1), group2, NULL); + clutter_actor_set_position (group2, 10, 60); + + rect = clutter_rectangle_new_with_color (&rect_color); + clutter_actor_set_size (rect, 128, 128); + + if (g_test_verbose ()) + g_print ("rect 100%% + group 100%% + group 50%%.get_color()/1\n"); + clutter_rectangle_get_color (CLUTTER_RECTANGLE (rect), &color_check); + g_assert (color_check.alpha == rect_color.alpha); + + clutter_container_add (CLUTTER_CONTAINER (group2), rect, NULL); + + if (g_test_verbose ()) + g_print ("rect 100%% + group 100%% + group 50%%.get_color()/2\n"); + clutter_rectangle_get_color (CLUTTER_RECTANGLE (rect), &color_check); + g_assert (color_check.alpha == rect_color.alpha); + + if (g_test_verbose ()) + g_print ("rect 100%%.get_paint_opacity()\n"); + g_assert (clutter_actor_get_paint_opacity (rect) == 128); +} +G_GNUC_END_IGNORE_DEPRECATIONS + +CLUTTER_TEST_SUITE ( + CLUTTER_TEST_UNIT ("/actor/opacity/text", opacity_label) + CLUTTER_TEST_UNIT ("/actor/opacity/rectangle", opacity_rectangle) + CLUTTER_TEST_UNIT ("/actor/opacity/paint", opacity_paint) +) diff --git a/clutter/tests/conform/actor-pick.c b/clutter/tests/conform/actor-pick.c new file mode 100644 index 0000000..969b492 --- /dev/null +++ b/clutter/tests/conform/actor-pick.c @@ -0,0 +1,311 @@ +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include + +#define STAGE_WIDTH 640 +#define STAGE_HEIGHT 480 +#define ACTORS_X 12 +#define ACTORS_Y 16 +#define SHIFT_STEP STAGE_WIDTH / ACTORS_X + +typedef struct _State State; + +struct _State +{ + ClutterActor *stage; + int y, x; + ClutterActor *actors[ACTORS_X * ACTORS_Y]; + guint actor_width, actor_height; + guint failed_pass; + guint failed_idx; + gboolean pass; +}; + +struct _ShiftEffect +{ + ClutterShaderEffect parent_instance; +}; + +struct _ShiftEffectClass +{ + ClutterShaderEffectClass parent_class; +}; + +typedef struct _ShiftEffect ShiftEffect; +typedef struct _ShiftEffectClass ShiftEffectClass; + +#define TYPE_SHIFT_EFFECT (shift_effect_get_type ()) + +GType shift_effect_get_type (void); + +G_DEFINE_TYPE (ShiftEffect, + shift_effect, + CLUTTER_TYPE_SHADER_EFFECT); + +static void +shader_paint (ClutterEffect *effect, + ClutterEffectPaintFlags flags) +{ + ClutterShaderEffect *shader = CLUTTER_SHADER_EFFECT (effect); + float tex_width; + ClutterActor *actor = + clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); + + if (g_test_verbose ()) + g_debug ("shader_paint"); + + clutter_shader_effect_set_shader_source (shader, + "uniform sampler2D tex;\n" + "uniform float step;\n" + "void main (void)\n" + "{\n" + " cogl_color_out = texture2D(tex, vec2 (cogl_tex_coord_in[0].s + step,\n" + " cogl_tex_coord_in[0].t));\n" + "}\n"); + + tex_width = clutter_actor_get_width (actor); + + clutter_shader_effect_set_uniform (shader, "tex", G_TYPE_INT, 1, 0); + clutter_shader_effect_set_uniform (shader, "step", G_TYPE_FLOAT, 1, + SHIFT_STEP / tex_width); + + CLUTTER_EFFECT_CLASS (shift_effect_parent_class)->paint (effect, flags); +} + +static void +shader_pick (ClutterEffect *effect, + ClutterEffectPaintFlags flags) +{ + shader_paint (effect, flags); +} + +static void +shift_effect_class_init (ShiftEffectClass *klass) +{ + ClutterEffectClass *shader_class = CLUTTER_EFFECT_CLASS (klass); + + shader_class->paint = shader_paint; + shader_class->pick = shader_pick; +} + +static void +shift_effect_init (ShiftEffect *self) +{ +} + +static const char *test_passes[] = { + "No covering actor", + "Invisible covering actor", + "Clipped covering actor", + "Blur effect", + "Shift effect", +}; + +static gboolean +on_timeout (gpointer data) +{ + State *state = data; + int test_num = 0; + int y, x; + ClutterActor *over_actor = NULL; + + /* This will cause an unclipped pick redraw that will get buffered. + We'll check below that this buffer is discarded because we also need + to pick non-reactive actors */ + clutter_stage_get_actor_at_pos (CLUTTER_STAGE (state->stage), + CLUTTER_PICK_REACTIVE, 10, 10); + + clutter_stage_get_actor_at_pos (CLUTTER_STAGE (state->stage), + CLUTTER_PICK_REACTIVE, 10, 10); + + for (test_num = 0; test_num < G_N_ELEMENTS (test_passes); test_num++) + { + if (test_num == 0) + { + if (g_test_verbose ()) + g_print ("No covering actor:\n"); + } + if (test_num == 1) + { + static const ClutterColor red = { 0xff, 0x00, 0x00, 0xff }; + /* Create an actor that covers the whole stage but that + isn't visible so it shouldn't affect the picking */ + over_actor = clutter_rectangle_new_with_color (&red); + clutter_actor_set_size (over_actor, STAGE_WIDTH, STAGE_HEIGHT); + clutter_actor_add_child (state->stage, over_actor); + clutter_actor_hide (over_actor); + + if (g_test_verbose ()) + g_print ("Invisible covering actor:\n"); + } + else if (test_num == 2) + { + /* Make the actor visible but set a clip so that only some + of the actors are accessible */ + clutter_actor_show (over_actor); + clutter_actor_set_clip (over_actor, + state->actor_width * 2, + state->actor_height * 2, + state->actor_width * (ACTORS_X - 4), + state->actor_height * (ACTORS_Y - 4)); + + if (g_test_verbose ()) + g_print ("Clipped covering actor:\n"); + } + else if (test_num == 3) + { + if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) + continue; + + clutter_actor_hide (over_actor); + + clutter_actor_add_effect_with_name (CLUTTER_ACTOR (state->stage), + "blur", + clutter_blur_effect_new ()); + + if (g_test_verbose ()) + g_print ("With blur effect:\n"); + } + else if (test_num == 4) + { + if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) + continue; + + clutter_actor_hide (over_actor); + clutter_actor_remove_effect_by_name (CLUTTER_ACTOR (state->stage), + "blur"); + + clutter_actor_add_effect_with_name (CLUTTER_ACTOR (state->stage), + "shift", + g_object_new (TYPE_SHIFT_EFFECT, + NULL)); + + if (g_test_verbose ()) + g_print ("With shift effect:\n"); + } + + for (y = 0; y < ACTORS_Y; y++) + { + if (test_num == 4) + x = 1; + else + x = 0; + + for (; x < ACTORS_X; x++) + { + gboolean pass = FALSE; + gfloat pick_x; + ClutterActor *actor; + + pick_x = x * state->actor_width + state->actor_width / 2; + + if (test_num == 4) + pick_x -= SHIFT_STEP; + + actor = + clutter_stage_get_actor_at_pos (CLUTTER_STAGE (state->stage), + CLUTTER_PICK_ALL, + pick_x, + y * state->actor_height + + state->actor_height / 2); + + if (g_test_verbose ()) + g_print ("% 3i,% 3i / %p -> ", + x, y, state->actors[y * ACTORS_X + x]); + + if (actor == NULL) + { + if (g_test_verbose ()) + g_print ("NULL: FAIL\n"); + } + else if (actor == over_actor) + { + if (test_num == 2 + && x >= 2 && x < ACTORS_X - 2 + && y >= 2 && y < ACTORS_Y - 2) + pass = TRUE; + + if (g_test_verbose ()) + g_print ("over_actor: %s\n", pass ? "pass" : "FAIL"); + } + else + { + if (actor == state->actors[y * ACTORS_X + x] + && (test_num != 2 + || x < 2 || x >= ACTORS_X - 2 + || y < 2 || y >= ACTORS_Y - 2)) + pass = TRUE; + + if (g_test_verbose ()) + g_print ("%p: %s\n", actor, pass ? "pass" : "FAIL"); + } + + if (!pass) + { + state->failed_pass = test_num; + state->failed_idx = y * ACTORS_X + x; + state->pass = FALSE; + } + } + } + } + + clutter_main_quit (); + + return G_SOURCE_REMOVE; +} + +static void +actor_pick (void) +{ + int y, x; + State state; + + state.pass = TRUE; + + state.stage = clutter_test_get_stage (); + + state.actor_width = STAGE_WIDTH / ACTORS_X; + state.actor_height = STAGE_HEIGHT / ACTORS_Y; + + for (y = 0; y < ACTORS_Y; y++) + for (x = 0; x < ACTORS_X; x++) + { + ClutterColor color = { x * 255 / (ACTORS_X - 1), + y * 255 / (ACTORS_Y - 1), + 128, 255 }; + ClutterActor *rect = clutter_rectangle_new_with_color (&color); + + clutter_actor_set_position (rect, + x * state.actor_width, + y * state.actor_height); + clutter_actor_set_size (rect, + state.actor_width, + state.actor_height); + + clutter_actor_add_child (state.stage, rect); + + state.actors[y * ACTORS_X + x] = rect; + } + + clutter_actor_show (state.stage); + + clutter_threads_add_idle (on_timeout, &state); + + clutter_main (); + + if (g_test_verbose ()) + { + if (!state.pass) + g_test_message ("Failed pass: %s[%d], actor index: %d [%p]\n", + test_passes[state.failed_pass], + state.failed_pass, + state.failed_idx, + state.actors[state.failed_idx]); + } + + g_assert (state.pass); +} + +CLUTTER_TEST_SUITE ( + CLUTTER_TEST_UNIT ("/actor/pick", actor_pick) +) diff --git a/clutter/tests/conform/actor-shader-effect.c b/clutter/tests/conform/actor-shader-effect.c new file mode 100644 index 0000000..d3ddd38 --- /dev/null +++ b/clutter/tests/conform/actor-shader-effect.c @@ -0,0 +1,284 @@ +#define CLUTTER_ENABLE_EXPERIMENTAL_API +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include + +/**************************************************************** + Old style shader effect + This uses clutter_shader_effect_set_source + ****************************************************************/ + +static const gchar +old_shader_effect_source[] = + "uniform vec3 override_color;\n" + "\n" + "void\n" + "main ()\n" + "{\n" + " cogl_color_out = vec4 (override_color, 1.0);\n" + "}"; + +typedef struct _FooOldShaderEffectClass +{ + ClutterShaderEffectClass parent_class; +} FooOldShaderEffectClass; + +typedef struct _FooOldShaderEffect +{ + ClutterShaderEffect parent; +} FooOldShaderEffect; + +GType foo_old_shader_effect_get_type (void); + +G_DEFINE_TYPE (FooOldShaderEffect, + foo_old_shader_effect, + CLUTTER_TYPE_SHADER_EFFECT); + +static void +foo_old_shader_effect_paint_target (ClutterOffscreenEffect *effect) +{ + clutter_shader_effect_set_shader_source (CLUTTER_SHADER_EFFECT (effect), + old_shader_effect_source); + clutter_shader_effect_set_uniform (CLUTTER_SHADER_EFFECT (effect), + "override_color", + G_TYPE_FLOAT, 3, + 1.0f, 0.0f, 0.0f); + + CLUTTER_OFFSCREEN_EFFECT_CLASS (foo_old_shader_effect_parent_class)-> + paint_target (effect); +} + +static void +foo_old_shader_effect_class_init (FooOldShaderEffectClass *klass) +{ + ClutterOffscreenEffectClass *offscreen_effect_class = + CLUTTER_OFFSCREEN_EFFECT_CLASS (klass); + + offscreen_effect_class->paint_target = foo_old_shader_effect_paint_target; +} + +static void +foo_old_shader_effect_init (FooOldShaderEffect *self) +{ +} + +/**************************************************************** + New style shader effect + This overrides get_static_shader_source() + ****************************************************************/ + +static const gchar +new_shader_effect_source[] = + "uniform vec3 override_color;\n" + "\n" + "void\n" + "main ()\n" + "{\n" + " cogl_color_out = (vec4 (override_color, 1.0) +\n" + " vec4 (0.0, 0.0, 1.0, 0.0));\n" + "}"; + +typedef struct _FooNewShaderEffectClass +{ + ClutterShaderEffectClass parent_class; +} FooNewShaderEffectClass; + +typedef struct _FooNewShaderEffect +{ + ClutterShaderEffect parent; +} FooNewShaderEffect; + +GType foo_new_shader_effect_get_type (void); + +G_DEFINE_TYPE (FooNewShaderEffect, + foo_new_shader_effect, + CLUTTER_TYPE_SHADER_EFFECT); + +static gchar * +foo_new_shader_effect_get_static_source (ClutterShaderEffect *effect) +{ + static gboolean already_called = FALSE; + + /* This should only be called once even though we have two actors + using this effect */ + g_assert (!already_called); + + already_called = TRUE; + + return g_strdup (new_shader_effect_source); +} + +static void +foo_new_shader_effect_paint_target (ClutterOffscreenEffect *effect) +{ + clutter_shader_effect_set_uniform (CLUTTER_SHADER_EFFECT (effect), + "override_color", + G_TYPE_FLOAT, 3, + 0.0f, 1.0f, 0.0f); + + CLUTTER_OFFSCREEN_EFFECT_CLASS (foo_new_shader_effect_parent_class)-> + paint_target (effect); +} + +static void +foo_new_shader_effect_class_init (FooNewShaderEffectClass *klass) +{ + ClutterOffscreenEffectClass *offscreen_effect_class = + CLUTTER_OFFSCREEN_EFFECT_CLASS (klass); + ClutterShaderEffectClass *shader_effect_class = + CLUTTER_SHADER_EFFECT_CLASS (klass); + + offscreen_effect_class->paint_target = foo_new_shader_effect_paint_target; + + shader_effect_class->get_static_shader_source = + foo_new_shader_effect_get_static_source; +} + +static void +foo_new_shader_effect_init (FooNewShaderEffect *self) +{ +} + +/**************************************************************** + Another new style shader effect + This is the same but with a different shader. This is just + sanity check that each class gets its own copy of the private + data + ****************************************************************/ + +static const gchar +another_new_shader_effect_source[] = + "\n" + "void\n" + "main ()\n" + "{\n" + " cogl_color_out = vec4 (1.0, 0.0, 1.0, 1.0);\n" + "}"; + +typedef struct _FooAnotherNewShaderEffectClass +{ + ClutterShaderEffectClass parent_class; +} FooAnotherNewShaderEffectClass; + +typedef struct _FooAnotherNewShaderEffect +{ + ClutterShaderEffect parent; +} FooAnotherNewShaderEffect; + +GType foo_another_new_shader_effect_get_type (void); + +G_DEFINE_TYPE (FooAnotherNewShaderEffect, + foo_another_new_shader_effect, + CLUTTER_TYPE_SHADER_EFFECT); + +static gchar * +foo_another_new_shader_effect_get_static_source (ClutterShaderEffect *effect) +{ + return g_strdup (another_new_shader_effect_source); +} + +static void +foo_another_new_shader_effect_class_init (FooAnotherNewShaderEffectClass *klass) +{ + ClutterShaderEffectClass *shader_effect_class = + CLUTTER_SHADER_EFFECT_CLASS (klass); + + shader_effect_class->get_static_shader_source = + foo_another_new_shader_effect_get_static_source; +} + +static void +foo_another_new_shader_effect_init (FooAnotherNewShaderEffect *self) +{ +} + +/****************************************************************/ + +static ClutterActor * +make_actor (GType shader_type) +{ + ClutterActor *rect; + const ClutterColor white = { 0xff, 0xff, 0xff, 0xff }; + + rect = clutter_rectangle_new (); + clutter_rectangle_set_color (CLUTTER_RECTANGLE (rect), &white); + clutter_actor_set_size (rect, 50, 50); + + clutter_actor_add_effect (rect, g_object_new (shader_type, NULL)); + + return rect; +} + +static guint32 +get_pixel (int x, int y) +{ + guint8 data[4]; + + cogl_read_pixels (x, y, 1, 1, + COGL_READ_PIXELS_COLOR_BUFFER, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + data); + + return (((guint32) data[0] << 16) | + ((guint32) data[1] << 8) | + data[2]); +} + +static void +paint_cb (ClutterStage *stage, + gpointer data) +{ + gboolean *was_painted = data; + + /* old shader effect */ + g_assert_cmpint (get_pixel (50, 50), ==, 0xff0000); + /* new shader effect */ + g_assert_cmpint (get_pixel (150, 50), ==, 0x00ffff); + /* another new shader effect */ + g_assert_cmpint (get_pixel (250, 50), ==, 0xff00ff); + /* new shader effect */ + g_assert_cmpint (get_pixel (350, 50), ==, 0x00ffff); + + *was_painted = TRUE; +} + +static void +actor_shader_effect (void) +{ + ClutterActor *stage; + ClutterActor *rect; + gboolean was_painted; + + if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) + return; + + stage = clutter_stage_new (); + + rect = make_actor (foo_old_shader_effect_get_type ()); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); + + rect = make_actor (foo_new_shader_effect_get_type ()); + clutter_actor_set_x (rect, 100); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); + + rect = make_actor (foo_another_new_shader_effect_get_type ()); + clutter_actor_set_x (rect, 200); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); + + rect = make_actor (foo_new_shader_effect_get_type ()); + clutter_actor_set_x (rect, 300); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); + + clutter_actor_show (stage); + + was_painted = FALSE; + g_signal_connect (stage, "after-paint", + G_CALLBACK (paint_cb), + &was_painted); + + while (!was_painted) + g_main_context_iteration (NULL, FALSE); +} + +CLUTTER_TEST_SUITE ( + CLUTTER_TEST_UNIT ("/actor/shader-effect", actor_shader_effect) +) diff --git a/clutter/tests/conform/actor-size.c b/clutter/tests/conform/actor-size.c new file mode 100644 index 0000000..7245f15 --- /dev/null +++ b/clutter/tests/conform/actor-size.c @@ -0,0 +1,216 @@ +#include +#include + +#include + +#define TEST_TYPE_ACTOR (test_actor_get_type ()) + +typedef struct _TestActor TestActor; +typedef struct _ClutterActorClass TestActorClass; + +struct _TestActor +{ + ClutterActor parent_instance; + + guint preferred_width_called : 1; + guint preferred_height_called : 1; +}; + +GType test_actor_get_type (void); + +G_DEFINE_TYPE (TestActor, test_actor, CLUTTER_TYPE_ACTOR); + +static void +test_actor_get_preferred_width (ClutterActor *self, + gfloat for_height, + gfloat *min_width_p, + gfloat *nat_width_p) +{ + TestActor *test = (TestActor *) self; + + test->preferred_width_called = TRUE; + + if (for_height == 10) + { + *min_width_p = 10; + *nat_width_p = 100; + } + else + { + *min_width_p = 100; + *nat_width_p = 100; + } +} + +static void +test_actor_get_preferred_height (ClutterActor *self, + gfloat for_width, + gfloat *min_height_p, + gfloat *nat_height_p) +{ + TestActor *test = (TestActor *) self; + + test->preferred_height_called = TRUE; + + if (for_width == 10) + { + *min_height_p = 50; + *nat_height_p = 100; + } + else + { + *min_height_p = 100; + *nat_height_p = 100; + } +} + +static void +test_actor_class_init (TestActorClass *klass) +{ + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + + actor_class->get_preferred_width = test_actor_get_preferred_width; + actor_class->get_preferred_height = test_actor_get_preferred_height; +} + +static void +test_actor_init (TestActor *self) +{ +} + +static void +actor_preferred_size (void) +{ + ClutterActor *test; + TestActor *self; + gfloat min_width, min_height; + gfloat nat_width, nat_height; + + test = g_object_new (TEST_TYPE_ACTOR, NULL); + self = (TestActor *) test; + + if (g_test_verbose ()) + g_print ("Preferred size\n"); + + clutter_actor_get_preferred_size (test, + &min_width, &min_height, + &nat_width, &nat_height); + + g_assert (self->preferred_width_called); + g_assert (self->preferred_height_called); + g_assert_cmpfloat (min_width, ==, 100); + g_assert_cmpfloat (min_height, ==, 100); + g_assert_cmpfloat (nat_width, ==, min_width); + g_assert_cmpfloat (nat_height, ==, min_height); + + if (g_test_verbose ()) + g_print ("Preferred width\n"); + self->preferred_width_called = FALSE; + clutter_actor_get_preferred_width (test, 10, &min_width, &nat_width); + g_assert (self->preferred_width_called); + g_assert_cmpfloat (min_width, ==, 10); + g_assert_cmpfloat (nat_width, ==, 100); + + if (g_test_verbose ()) + g_print ("Preferred height\n"); + self->preferred_height_called = FALSE; + clutter_actor_get_preferred_height (test, 200, &min_height, &nat_height); + g_assert (self->preferred_height_called); + g_assert_cmpfloat (min_height, !=, 10); + g_assert_cmpfloat (nat_height, ==, 100); + + if (g_test_verbose ()) + g_print ("Preferred width (cached)\n"); + self->preferred_width_called = FALSE; + clutter_actor_get_preferred_width (test, 10, &min_width, &nat_width); + g_assert (!self->preferred_width_called); + g_assert_cmpfloat (min_width, ==, 10); + g_assert_cmpfloat (nat_width, ==, 100); + + if (g_test_verbose ()) + g_print ("Preferred height (cache eviction)\n"); + self->preferred_height_called = FALSE; + clutter_actor_get_preferred_height (test, 10, &min_height, &nat_height); + g_assert (self->preferred_height_called); + g_assert_cmpfloat (min_height, ==, 50); + g_assert_cmpfloat (nat_height, ==, 100); + + clutter_actor_destroy (test); +} + +static void +actor_fixed_size (void) +{ + ClutterActor *rect; + gboolean min_width_set, nat_width_set; + gboolean min_height_set, nat_height_set; + gfloat min_width, min_height; + gfloat nat_width, nat_height; + + rect = clutter_actor_new (); + g_object_ref_sink (rect); + + if (g_test_verbose ()) + g_print ("Initial size is 0\n"); + + g_assert_cmpfloat (clutter_actor_get_width (rect), ==, 0); + g_assert_cmpfloat (clutter_actor_get_height (rect), ==, 0); + + clutter_actor_set_size (rect, 100, 100); + + if (g_test_verbose ()) + g_print ("Explicit size set\n"); + + g_assert_cmpfloat (clutter_actor_get_width (rect), ==, 100); + g_assert_cmpfloat (clutter_actor_get_height (rect), ==, 100); + + g_object_get (G_OBJECT (rect), + "min-width-set", &min_width_set, + "min-height-set", &min_height_set, + "natural-width-set", &nat_width_set, + "natural-height-set", &nat_height_set, + NULL); + + if (g_test_verbose ()) + g_print ("Notification properties\n"); + + g_assert (min_width_set && nat_width_set); + g_assert (min_height_set && nat_height_set); + + clutter_actor_get_preferred_size (rect, + &min_width, &min_height, + &nat_width, &nat_height); + + if (g_test_verbose ()) + g_print ("Preferred size\n"); + + g_assert_cmpfloat (min_width, ==, 100); + g_assert_cmpfloat (min_height, ==, 100); + g_assert_cmpfloat (min_width, ==, nat_width); + g_assert_cmpfloat (min_height, ==, nat_height); + + clutter_actor_set_size (rect, -1, -1); + + if (g_test_verbose ()) + g_print ("Explicit size unset\n"); + + g_object_get (G_OBJECT (rect), + "min-width-set", &min_width_set, + "min-height-set", &min_height_set, + "natural-width-set", &nat_width_set, + "natural-height-set", &nat_height_set, + NULL); + g_assert (!min_width_set && !nat_width_set); + g_assert (!min_height_set && !nat_height_set); + + g_assert_cmpfloat (clutter_actor_get_width (rect), ==, 0); + g_assert_cmpfloat (clutter_actor_get_height (rect), ==, 0); + + clutter_actor_destroy (rect); + g_object_unref (rect); +} + +CLUTTER_TEST_SUITE ( + CLUTTER_TEST_UNIT ("/actor/size/preferred", actor_preferred_size) + CLUTTER_TEST_UNIT ("/actor/size/fixed", actor_fixed_size) +) diff --git a/clutter/tests/conform/animator.c b/clutter/tests/conform/animator.c new file mode 100644 index 0000000..9711699 --- /dev/null +++ b/clutter/tests/conform/animator.c @@ -0,0 +1,199 @@ +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include + +static void +animator_multi_properties (void) +{ + ClutterScript *script = clutter_script_new (); + GObject *animator = NULL, *foo = NULL; + GError *error = NULL; + gchar *test_file; + GList *keys; + ClutterAnimatorKey *key; + GValue value = { 0, }; + + test_file = g_test_build_filename (G_TEST_DIST, + "scripts", + "test-animator-3.json", + NULL); + clutter_script_load_from_file (script, test_file, &error); + if (g_test_verbose () && error) + g_print ("Error: %s", error->message); + + g_assert_no_error (error); + + foo = clutter_script_get_object (script, "foo"); + g_assert (G_IS_OBJECT (foo)); + + animator = clutter_script_get_object (script, "animator"); + g_assert (CLUTTER_IS_ANIMATOR (animator)); + + /* get all the keys for foo:x */ + keys = clutter_animator_get_keys (CLUTTER_ANIMATOR (animator), + foo, "x", + -1.0); + g_assert_cmpint (g_list_length (keys), ==, 3); + + key = g_list_nth_data (keys, 1); + g_assert (key != NULL); + + if (g_test_verbose ()) + { + g_print ("(foo, x).keys[1] = \n" + ".object = %s\n" + ".progress = %.2f\n" + ".name = '%s'\n" + ".type = '%s'\n", + clutter_get_script_id (clutter_animator_key_get_object (key)), + clutter_animator_key_get_progress (key), + clutter_animator_key_get_property_name (key), + g_type_name (clutter_animator_key_get_property_type (key))); + } + + g_assert (clutter_animator_key_get_object (key) != NULL); + g_assert_cmpfloat (clutter_animator_key_get_progress (key), ==, 0.2); + g_assert_cmpstr (clutter_animator_key_get_property_name (key), ==, "x"); + + g_assert (clutter_animator_key_get_property_type (key) == G_TYPE_FLOAT); + + g_value_init (&value, G_TYPE_FLOAT); + g_assert (clutter_animator_key_get_value (key, &value)); + g_assert_cmpfloat (g_value_get_float (&value), ==, 150.0); + g_value_unset (&value); + + g_list_free (keys); + + /* get all the keys for foo:y */ + keys = clutter_animator_get_keys (CLUTTER_ANIMATOR (animator), + foo, "y", + -1.0); + g_assert_cmpint (g_list_length (keys), ==, 3); + + key = g_list_nth_data (keys, 2); + g_assert (key != NULL); + + if (g_test_verbose ()) + { + g_print ("(foo, y).keys[2] = \n" + ".object = %s\n" + ".progress = %.2f\n" + ".name = '%s'\n" + ".type = '%s'\n", + clutter_get_script_id (clutter_animator_key_get_object (key)), + clutter_animator_key_get_progress (key), + clutter_animator_key_get_property_name (key), + g_type_name (clutter_animator_key_get_property_type (key))); + } + + g_assert (clutter_animator_key_get_object (key) != NULL); + g_assert_cmpfloat (clutter_animator_key_get_progress (key), ==, 0.8); + g_assert_cmpstr (clutter_animator_key_get_property_name (key), ==, "y"); + + g_assert (clutter_animator_key_get_property_type (key) == G_TYPE_FLOAT); + + g_value_init (&value, G_TYPE_FLOAT); + g_assert (clutter_animator_key_get_value (key, &value)); + g_assert_cmpfloat (g_value_get_float (&value), ==, 200.0); + g_value_unset (&value); + + g_list_free (keys); + + g_object_unref (script); + g_free (test_file); +} + +static void +animator_properties (void) +{ + ClutterScript *script = clutter_script_new (); + GObject *animator = NULL; + GError *error = NULL; + gchar *test_file; + GList *keys; + ClutterAnimatorKey *key; + GValue value = { 0, }; + + test_file = g_test_build_filename (G_TEST_DIST, + "scripts", + "test-animator-2.json", + NULL); + clutter_script_load_from_file (script, test_file, &error); + if (g_test_verbose () && error) + g_print ("Error: %s", error->message); + + g_assert_no_error (error); + + animator = clutter_script_get_object (script, "animator"); + g_assert (CLUTTER_IS_ANIMATOR (animator)); + + /* get all the keys */ + keys = clutter_animator_get_keys (CLUTTER_ANIMATOR (animator), + NULL, NULL, -1.0); + g_assert_cmpint (g_list_length (keys), ==, 3); + + key = g_list_nth_data (keys, 1); + g_assert (key != NULL); + + if (g_test_verbose ()) + { + g_print ("keys[1] = \n" + ".object = %s\n" + ".progress = %.2f\n" + ".name = '%s'\n" + ".type = '%s'\n", + clutter_get_script_id (clutter_animator_key_get_object (key)), + clutter_animator_key_get_progress (key), + clutter_animator_key_get_property_name (key), + g_type_name (clutter_animator_key_get_property_type (key))); + } + + g_assert (clutter_animator_key_get_object (key) != NULL); + g_assert_cmpfloat (clutter_animator_key_get_progress (key), ==, 0.2); + g_assert_cmpstr (clutter_animator_key_get_property_name (key), ==, "x"); + + g_assert (clutter_animator_key_get_property_type (key) == G_TYPE_FLOAT); + + g_value_init (&value, G_TYPE_FLOAT); + g_assert (clutter_animator_key_get_value (key, &value)); + g_assert_cmpfloat (g_value_get_float (&value), ==, 150.0); + g_value_unset (&value); + + g_list_free (keys); + g_object_unref (script); + g_free (test_file); +} + +static void +animator_base (void) +{ + ClutterScript *script = clutter_script_new (); + GObject *animator = NULL; + GError *error = NULL; + guint duration = 0; + gchar *test_file; + + test_file = g_test_build_filename (G_TEST_DIST, + "scripts", + "test-animator-1.json", + NULL); + clutter_script_load_from_file (script, test_file, &error); + if (g_test_verbose () && error) + g_print ("Error: %s", error->message); + + g_assert_no_error (error); + + animator = clutter_script_get_object (script, "animator"); + g_assert (CLUTTER_IS_ANIMATOR (animator)); + + duration = clutter_animator_get_duration (CLUTTER_ANIMATOR (animator)); + g_assert_cmpint (duration, ==, 1000); + + g_object_unref (script); + g_free (test_file); +} + +CLUTTER_TEST_SUITE ( + CLUTTER_TEST_UNIT ("/script/animator/base", animator_base) + CLUTTER_TEST_UNIT ("/script/animator/properties", animator_properties) + CLUTTER_TEST_UNIT ("/script/animator/multi-properties", animator_multi_properties) +) diff --git a/clutter/tests/conform/behaviours.c b/clutter/tests/conform/behaviours.c new file mode 100644 index 0000000..6c531be --- /dev/null +++ b/clutter/tests/conform/behaviours.c @@ -0,0 +1,80 @@ +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include + +static void +behaviour_opacity (void) +{ + ClutterBehaviour *behaviour; + ClutterTimeline *timeline; + ClutterAlpha *alpha; + guint8 start, end; + guint starti; + + timeline = clutter_timeline_new (500); + alpha = clutter_alpha_new_full (timeline, CLUTTER_LINEAR); + behaviour = clutter_behaviour_opacity_new (alpha, 0, 255); + g_assert (CLUTTER_IS_BEHAVIOUR_OPACITY (behaviour)); + g_object_add_weak_pointer (G_OBJECT (behaviour), (gpointer *) &behaviour); + g_object_add_weak_pointer (G_OBJECT (timeline), (gpointer *) &timeline); + + clutter_behaviour_opacity_get_bounds (CLUTTER_BEHAVIOUR_OPACITY (behaviour), + &start, + &end); + + if (g_test_verbose ()) + g_print ("BehaviourOpacity:bounds = %d, %d (expected: 0, 255)\n", + start, + end); + + g_assert_cmpint (start, ==, 0); + g_assert_cmpint (end, ==, 255); + + clutter_behaviour_opacity_set_bounds (CLUTTER_BEHAVIOUR_OPACITY (behaviour), + 255, + 0); + /* XXX: The gobject property is actually a unsigned int not unsigned char + * property so we have to be careful not to corrupt the stack by passing + * a guint8 pointer here... */ + starti = 0; + g_object_get (G_OBJECT (behaviour), "opacity-start", &starti, NULL); + + if (g_test_verbose ()) + g_print ("BehaviourOpacity:start = %d (expected: 255)\n", start); + + g_assert_cmpint (starti, ==, 255); + + g_object_unref (behaviour); + g_object_unref (timeline); + + g_assert_null (behaviour); + g_assert_null (timeline); +} + +static struct +{ + const gchar *path; + GTestFunc func; +} behaviour_tests[] = { + { "opacity", behaviour_opacity }, +}; + +static const int n_behaviour_tests = G_N_ELEMENTS (behaviour_tests); + +int +main (int argc, char *argv[]) +{ + int i; + + clutter_test_init (&argc, &argv); + + for (i = 0; i < n_behaviour_tests; i++) + { + char *path = g_strconcat ("/behaviours/", behaviour_tests[i].path, NULL); + + clutter_test_add (path, behaviour_tests[i].func); + + g_free (path); + } + + return clutter_test_run (); +} diff --git a/clutter/tests/conform/binding-pool.c b/clutter/tests/conform/binding-pool.c new file mode 100644 index 0000000..4e4752b --- /dev/null +++ b/clutter/tests/conform/binding-pool.c @@ -0,0 +1,297 @@ +#include + +#include + +#define TYPE_KEY_GROUP (key_group_get_type ()) +#define KEY_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_KEY_GROUP, KeyGroup)) +#define IS_KEY_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_KEY_GROUP)) +#define KEY_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_KEY_GROUP, KeyGroupClass)) +#define IS_KEY_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_KEY_GROUP)) + +typedef struct _KeyGroup KeyGroup; +typedef struct _KeyGroupClass KeyGroupClass; + +struct _KeyGroup +{ + ClutterActor parent_instance; + + gint selected_index; +}; + +struct _KeyGroupClass +{ + ClutterActorClass parent_class; + + void (* activate) (KeyGroup *group, + ClutterActor *child); +}; + +GType key_group_get_type (void); + +G_DEFINE_TYPE (KeyGroup, key_group, CLUTTER_TYPE_ACTOR) + +enum +{ + ACTIVATE, + + LAST_SIGNAL +}; + +static guint group_signals[LAST_SIGNAL] = { 0, }; + +static gboolean +key_group_action_move_left (KeyGroup *self, + const gchar *action_name, + guint key_val, + ClutterModifierType modifiers) +{ + gint n_children; + + g_assert_cmpstr (action_name, ==, "move-left"); + g_assert_cmpint (key_val, ==, CLUTTER_KEY_Left); + + n_children = clutter_actor_get_n_children (CLUTTER_ACTOR (self)); + + self->selected_index -= 1; + + if (self->selected_index < 0) + self->selected_index = n_children - 1; + + return TRUE; +} + +static gboolean +key_group_action_move_right (KeyGroup *self, + const gchar *action_name, + guint key_val, + ClutterModifierType modifiers) +{ + gint n_children; + + g_assert_cmpstr (action_name, ==, "move-right"); + g_assert_cmpint (key_val, ==, CLUTTER_KEY_Right); + + n_children = clutter_actor_get_n_children (CLUTTER_ACTOR (self)); + + self->selected_index += 1; + + if (self->selected_index >= n_children) + self->selected_index = 0; + + return TRUE; +} + +static gboolean +key_group_action_activate (KeyGroup *self, + const gchar *action_name, + guint key_val, + ClutterModifierType modifiers) +{ + ClutterActor *child = NULL; + + g_assert_cmpstr (action_name, ==, "activate"); + g_assert (key_val == CLUTTER_KEY_Return || + key_val == CLUTTER_KEY_KP_Enter || + key_val == CLUTTER_KEY_ISO_Enter); + + if (self->selected_index == -1) + return FALSE; + + child = clutter_actor_get_child_at_index (CLUTTER_ACTOR (self), self->selected_index); + if (child != NULL) + { + g_signal_emit (self, group_signals[ACTIVATE], 0, child); + return TRUE; + } + else + return FALSE; +} + +static gboolean +key_group_key_press (ClutterActor *actor, + ClutterKeyEvent *event) +{ + ClutterBindingPool *pool; + gboolean res; + + pool = clutter_binding_pool_find (G_OBJECT_TYPE_NAME (actor)); + g_assert (pool != NULL); + + res = clutter_binding_pool_activate (pool, + event->keyval, + event->modifier_state, + G_OBJECT (actor)); + + /* if we activate a key binding, redraw the actor */ + if (res) + clutter_actor_queue_redraw (actor); + + return res; +} + +static void +key_group_paint (ClutterActor *actor) +{ + KeyGroup *self = KEY_GROUP (actor); + ClutterActorIter iter; + ClutterActor *child; + gint i = 0; + + clutter_actor_iter_init (&iter, actor); + while (clutter_actor_iter_next (&iter, &child)) + { + /* paint the selection rectangle */ + if (i == self->selected_index) + { + ClutterActorBox box = { 0, }; + + clutter_actor_get_allocation_box (child, &box); + + box.x1 -= 2; + box.y1 -= 2; + box.x2 += 2; + box.y2 += 2; + + cogl_set_source_color4ub (255, 255, 0, 224); + cogl_rectangle (box.x1, box.y1, box.x2, box.y2); + } + + clutter_actor_paint (child); + } +} + +static void +key_group_class_init (KeyGroupClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + ClutterBindingPool *binding_pool; + + actor_class->paint = key_group_paint; + actor_class->key_press_event = key_group_key_press; + + group_signals[ACTIVATE] = + g_signal_new (g_intern_static_string ("activate"), + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (KeyGroupClass, activate), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CLUTTER_TYPE_ACTOR); + + binding_pool = clutter_binding_pool_get_for_class (klass); + + clutter_binding_pool_install_action (binding_pool, "move-right", + CLUTTER_KEY_Right, 0, + G_CALLBACK (key_group_action_move_right), + NULL, NULL); + clutter_binding_pool_install_action (binding_pool, "move-left", + CLUTTER_KEY_Left, 0, + G_CALLBACK (key_group_action_move_left), + NULL, NULL); + clutter_binding_pool_install_action (binding_pool, "activate", + CLUTTER_KEY_Return, 0, + G_CALLBACK (key_group_action_activate), + NULL, NULL); + clutter_binding_pool_install_action (binding_pool, "activate", + CLUTTER_KEY_KP_Enter, 0, + G_CALLBACK (key_group_action_activate), + NULL, NULL); + clutter_binding_pool_install_action (binding_pool, "activate", + CLUTTER_KEY_ISO_Enter, 0, + G_CALLBACK (key_group_action_activate), + NULL, NULL); +} + +static void +key_group_init (KeyGroup *self) +{ + self->selected_index = -1; +} + +static void +init_event (ClutterKeyEvent *event) +{ + event->type = CLUTTER_KEY_PRESS; + event->time = 0; /* not needed */ + event->flags = CLUTTER_EVENT_FLAG_SYNTHETIC; + event->stage = NULL; /* not needed */ + event->source = NULL; /* not needed */ + event->modifier_state = 0; + event->hardware_keycode = 0; /* not needed */ +} + +static void +send_keyval (KeyGroup *group, int keyval) +{ + ClutterKeyEvent event; + + init_event (&event); + event.keyval = keyval; + event.unicode_value = 0; /* should be ignored for cursor keys etc. */ + + clutter_actor_event (CLUTTER_ACTOR (group), (ClutterEvent *) &event, FALSE); +} + +static void +on_activate (KeyGroup *key_group, + ClutterActor *child, + gpointer data) +{ + gint _index = GPOINTER_TO_INT (data); + + g_assert_cmpint (key_group->selected_index, ==, _index); +} + +static void +binding_pool (void) +{ + KeyGroup *key_group = g_object_new (TYPE_KEY_GROUP, NULL); + g_object_ref_sink (key_group); + + clutter_actor_add_child (CLUTTER_ACTOR (key_group), + g_object_new (CLUTTER_TYPE_ACTOR, + "width", 50.0, + "height", 50.0, + "x", 0.0, "y", 0.0, + NULL)); + clutter_actor_add_child (CLUTTER_ACTOR (key_group), + g_object_new (CLUTTER_TYPE_ACTOR, + "width", 50.0, + "height", 50.0, + "x", 75.0, "y", 0.0, + NULL)); + clutter_actor_add_child (CLUTTER_ACTOR (key_group), + g_object_new (CLUTTER_TYPE_ACTOR, + "width", 50.0, + "height", 50.0, + "x", 150.0, "y", 0.0, + NULL)); + + g_assert_cmpint (key_group->selected_index, ==, -1); + + send_keyval (key_group, CLUTTER_KEY_Left); + g_assert_cmpint (key_group->selected_index, ==, 2); + + send_keyval (key_group, CLUTTER_KEY_Left); + g_assert_cmpint (key_group->selected_index, ==, 1); + + send_keyval (key_group, CLUTTER_KEY_Right); + g_assert_cmpint (key_group->selected_index, ==, 2); + + send_keyval (key_group, CLUTTER_KEY_Right); + g_assert_cmpint (key_group->selected_index, ==, 0); + + g_signal_connect (key_group, + "activate", G_CALLBACK (on_activate), + GINT_TO_POINTER (0)); + + send_keyval (key_group, CLUTTER_KEY_Return); + + clutter_actor_destroy (CLUTTER_ACTOR (key_group)); +} + +CLUTTER_TEST_SUITE ( + CLUTTER_TEST_UNIT ("/binding-pool", binding_pool) +) diff --git a/clutter/tests/conform/color.c b/clutter/tests/conform/color.c new file mode 100644 index 0000000..03ecf3f --- /dev/null +++ b/clutter/tests/conform/color.c @@ -0,0 +1,319 @@ +#include + +static void +color_hls_roundtrip (void) +{ + ClutterColor color; + gfloat hue, luminance, saturation; + + /* test luminance only */ + clutter_color_from_string (&color, "#7f7f7f"); + g_assert_cmpuint (color.red, ==, 0x7f); + g_assert_cmpuint (color.green, ==, 0x7f); + g_assert_cmpuint (color.blue, ==, 0x7f); + + clutter_color_to_hls (&color, &hue, &luminance, &saturation); + g_assert_cmpfloat (hue, ==, 0.0); + g_assert (luminance >= 0.0 && luminance <= 1.0); + g_assert_cmpfloat (saturation, ==, 0.0); + if (g_test_verbose ()) + { + g_print ("RGB = { %x, %x, %x }, HLS = { %.2f, %.2f, %.2f }\n", + color.red, + color.green, + color.blue, + hue, + luminance, + saturation); + } + + color.red = color.green = color.blue = 0; + clutter_color_from_hls (&color, hue, luminance, saturation); + + g_assert_cmpuint (color.red, ==, 0x7f); + g_assert_cmpuint (color.green, ==, 0x7f); + g_assert_cmpuint (color.blue, ==, 0x7f); + + /* full conversion */ + clutter_color_from_string (&color, "#7f8f7f"); + color.alpha = 255; + + g_assert_cmpuint (color.red, ==, 0x7f); + g_assert_cmpuint (color.green, ==, 0x8f); + g_assert_cmpuint (color.blue, ==, 0x7f); + + clutter_color_to_hls (&color, &hue, &luminance, &saturation); + g_assert (hue >= 0.0 && hue < 360.0); + g_assert (luminance >= 0.0 && luminance <= 1.0); + g_assert (saturation >= 0.0 && saturation <= 1.0); + if (g_test_verbose ()) + { + g_print ("RGB = { %x, %x, %x }, HLS = { %.2f, %.2f, %.2f }\n", + color.red, + color.green, + color.blue, + hue, + luminance, + saturation); + } + + color.red = color.green = color.blue = 0; + clutter_color_from_hls (&color, hue, luminance, saturation); + + g_assert_cmpuint (color.red, ==, 0x7f); + g_assert_cmpuint (color.green, ==, 0x8f); + g_assert_cmpuint (color.blue, ==, 0x7f); + + /* the alpha channel should be untouched */ + g_assert_cmpuint (color.alpha, ==, 255); +} + +static void +color_from_string_invalid (void) +{ + ClutterColor color; + + g_assert (!clutter_color_from_string (&color, "ff0000ff")); + g_assert (!clutter_color_from_string (&color, "#decaffbad")); + g_assert (!clutter_color_from_string (&color, "ponies")); + g_assert (!clutter_color_from_string (&color, "rgb(255, 0, 0, 0)")); + g_assert (!clutter_color_from_string (&color, "rgba(1.0, 0, 0)")); + g_assert (!clutter_color_from_string (&color, "hsl(100, 0, 0)")); + g_assert (!clutter_color_from_string (&color, "hsla(10%, 0%, 50%)")); + g_assert (!clutter_color_from_string (&color, "hsla(100%, 0%, 50%, 20%)")); + g_assert (!clutter_color_from_string (&color, "hsla(0.5, 0.9, 0.2, 0.4)")); +} + +static void +color_from_string_valid (void) +{ + ClutterColor color; + + g_assert (clutter_color_from_string (&color, "#ff0000ff")); + if (g_test_verbose ()) + { + g_print ("color = { %x, %x, %x, %x }, expected = { 0xff, 0, 0, 0xff }\n", + color.red, + color.green, + color.blue, + color.alpha); + } + g_assert_cmpuint (color.red, ==, 0xff); + g_assert_cmpuint (color.green, ==, 0); + g_assert_cmpuint (color.blue, ==, 0); + g_assert_cmpuint (color.alpha, ==, 0xff); + + g_assert (clutter_color_from_string (&color, "#0f0f")); + if (g_test_verbose ()) + { + g_print ("color = { %x, %x, %x, %x }, expected = { 0, 0xff, 0, 0xff }\n", + color.red, + color.green, + color.blue, + color.alpha); + } + g_assert_cmpuint (color.red, ==, 0); + g_assert_cmpuint (color.green, ==, 0xff); + g_assert_cmpuint (color.blue, ==, 0); + g_assert_cmpuint (color.alpha, ==, 0xff); + + g_assert (clutter_color_from_string (&color, "#0000ff")); + if (g_test_verbose ()) + { + g_print ("color = { %x, %x, %x, %x }, expected = { 0, 0, 0xff, 0xff }\n", + color.red, + color.green, + color.blue, + color.alpha); + } + g_assert_cmpuint (color.red, ==, 0); + g_assert_cmpuint (color.green, ==, 0); + g_assert_cmpuint (color.blue, ==, 0xff); + g_assert_cmpuint (color.alpha, ==, 0xff); + + g_assert (clutter_color_from_string (&color, "#abc")); + if (g_test_verbose ()) + { + g_print ("color = { %x, %x, %x, %x }, expected = { 0xaa, 0xbb, 0xcc, 0xff }\n", + color.red, + color.green, + color.blue, + color.alpha); + } + g_assert_cmpuint (color.red, ==, 0xaa); + g_assert_cmpuint (color.green, ==, 0xbb); + g_assert_cmpuint (color.blue, ==, 0xcc); + g_assert_cmpuint (color.alpha, ==, 0xff); + + g_assert (clutter_color_from_string (&color, "#123abc")); + if (g_test_verbose ()) + { + g_print ("color = { %x, %x, %x, %x }, expected = { 0x12, 0x3a, 0xbc, 0xff }\n", + color.red, + color.green, + color.blue, + color.alpha); + } + g_assert (color.red == 0x12); + g_assert (color.green == 0x3a); + g_assert (color.blue == 0xbc); + g_assert (color.alpha == 0xff); + + g_assert (clutter_color_from_string (&color, "rgb(255, 128, 64)")); + if (g_test_verbose ()) + { + g_print ("color = { %x, %x, %x, %x }, expected = { 255, 128, 64, 255 }\n", + color.red, + color.green, + color.blue, + color.alpha); + } + g_assert_cmpuint (color.red, ==, 255); + g_assert_cmpuint (color.green, ==, 128); + g_assert_cmpuint (color.blue, ==, 64); + g_assert_cmpuint (color.alpha, ==, 255); + + g_assert (clutter_color_from_string (&color, "rgba ( 30%, 0, 25%, 0.5 ) ")); + if (g_test_verbose ()) + { + g_print ("color = { %x, %x, %x, %x }, expected = { %.1f, 0, %.1f, 128 }\n", + color.red, + color.green, + color.blue, + color.alpha, + CLAMP (255.0 / 100.0 * 30.0, 0, 255), + CLAMP (255.0 / 100.0 * 25.0, 0, 255)); + } + g_assert_cmpuint (color.red, ==, (255.0 / 100.0 * 30.0)); + g_assert_cmpuint (color.green, ==, 0); + g_assert_cmpuint (color.blue, ==, (255.0 / 100.0 * 25.0)); + g_assert_cmpuint (color.alpha, ==, 127); + + g_assert (clutter_color_from_string (&color, "rgb( 50%, -50%, 150% )")); + if (g_test_verbose ()) + { + g_print ("color = { %x, %x, %x, %x }, expected = { 127, 0, 255, 255 }\n", + color.red, + color.green, + color.blue, + color.alpha); + } + g_assert_cmpuint (color.red, ==, 127); + g_assert_cmpuint (color.green, ==, 0); + g_assert_cmpuint (color.blue, ==, 255); + g_assert_cmpuint (color.alpha, ==, 255); + + g_assert (clutter_color_from_string (&color, "hsl( 0, 100%, 50% )")); + if (g_test_verbose ()) + { + g_print ("color = { %x, %x, %x, %x }, expected = { 255, 0, 0, 255 }\n", + color.red, + color.green, + color.blue, + color.alpha); + } + g_assert_cmpuint (color.red, ==, 255); + g_assert_cmpuint (color.green, ==, 0); + g_assert_cmpuint (color.blue, ==, 0); + g_assert_cmpuint (color.alpha, ==, 255); + + g_assert (clutter_color_from_string (&color, "hsl( 0, 100%, 50% )")); + + g_assert (clutter_color_from_string (&color, "hsla( 0, 100%, 50%, 0.5 )")); + if (g_test_verbose ()) + { + g_print ("color = { %x, %x, %x, %x }, expected = { 255, 0, 0, 127 }\n", + color.red, + color.green, + color.blue, + color.alpha); + } + g_assert_cmpuint (color.red, ==, 255); + g_assert_cmpuint (color.green, ==, 0); + g_assert_cmpuint (color.blue, ==, 0); + g_assert_cmpuint (color.alpha, ==, 127); + + g_test_bug ("662818"); + g_assert (clutter_color_from_string (&color, "hsla(0,100%,50% , 0.5)")); +} + +static void +color_to_string (void) +{ + ClutterColor color; + gchar *str; + + color.red = 0xcc; + color.green = 0xcc; + color.blue = 0xcc; + color.alpha = 0x22; + + str = clutter_color_to_string (&color); + g_assert_cmpstr (str, ==, "#cccccc22"); + + g_free (str); +} + +static void +color_operators (void) +{ + ClutterColor op1, op2; + ClutterColor res; + + clutter_color_from_pixel (&op1, 0xff0000ff); + g_assert_cmpuint (op1.red, ==, 0xff); + g_assert_cmpuint (op1.green, ==, 0); + g_assert_cmpuint (op1.blue, ==, 0); + g_assert_cmpuint (op1.alpha, ==, 0xff); + + clutter_color_from_pixel (&op2, 0x00ff00ff); + g_assert_cmpuint (op2.red, ==, 0); + g_assert_cmpuint (op2.green, ==, 0xff); + g_assert_cmpuint (op2.blue, ==, 0); + g_assert_cmpuint (op2.alpha, ==, 0xff); + + if (g_test_verbose ()) + g_print ("Adding %x, %x; expected result: %x\n", + clutter_color_to_pixel (&op1), + clutter_color_to_pixel (&op2), + 0xffff00ff); + + clutter_color_add (&op1, &op2, &res); + g_assert_cmpuint (clutter_color_to_pixel (&res), ==, 0xffff00ff); + + if (g_test_verbose ()) + g_print ("Checking alpha channel on color add\n"); + + op1.alpha = 0xdd; + op2.alpha = 0xcc; + clutter_color_add (&op1, &op2, &res); + g_assert_cmpuint (clutter_color_to_pixel (&res), ==, 0xffff00dd); + + clutter_color_from_pixel (&op1, 0xffffffff); + clutter_color_from_pixel (&op2, 0xff00ffff); + + if (g_test_verbose ()) + g_print ("Subtracting %x, %x; expected result: %x\n", + clutter_color_to_pixel (&op1), + clutter_color_to_pixel (&op2), + 0x00ff00ff); + + clutter_color_subtract (&op1, &op2, &res); + g_assert_cmpuint (clutter_color_to_pixel (&res), ==, 0x00ff00ff); + + if (g_test_verbose ()) + g_print ("Checking alpha channel on color subtract\n"); + + op1.alpha = 0xdd; + op2.alpha = 0xcc; + clutter_color_subtract (&op1, &op2, &res); + g_assert_cmpuint (clutter_color_to_pixel (&res), ==, 0x00ff00cc); +} + +CLUTTER_TEST_SUITE ( + CLUTTER_TEST_UNIT ("/color/hls-roundtrip", color_hls_roundtrip) + CLUTTER_TEST_UNIT ("/color/from-string/invalid", color_from_string_invalid) + CLUTTER_TEST_UNIT ("/color/from-string/valid", color_from_string_valid) + CLUTTER_TEST_UNIT ("/color/to-string", color_to_string) + CLUTTER_TEST_UNIT ("/color/operators", color_operators) +) diff --git a/clutter/tests/conform/events-touch.c b/clutter/tests/conform/events-touch.c new file mode 100644 index 0000000..124b821 --- /dev/null +++ b/clutter/tests/conform/events-touch.c @@ -0,0 +1,392 @@ +/* + * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2012 Collabora Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * Boston, MA 02111-1307, USA. + * + */ + +#include + +#if defined CLUTTER_WINDOWING_X11 && OS_LINUX && HAVE_XINPUT_2_2 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define ABS_MAX_X 32768 +#define ABS_MAX_Y 32768 + +#define TOUCH_POINTS 10 + +static ClutterPoint gesture_points[] = { + { 100., 100. }, + { 110., 100. }, + { 120., 100. }, + { 130., 100. }, + { 140., 100. }, + { 150., 100. }, + { 160., 100. }, + { 170., 100. }, + { 180., 100. }, + { 190., 100. }, +}; + +typedef struct _State State; + +struct _State +{ + gboolean pass; + ClutterPoint gesture_points_to_check[TOUCH_POINTS]; + int gesture_points; +}; + +static int fd = -1; + +static void send_event(int fd, int type, int code, int value, int sec, int usec) +{ + static int sec_offset = -1; + static long last_time = -1; + long newtime; + struct input_event event; + + event.type = type; + event.code = code; + event.value = value; + + if (sec_offset == -1) + sec_offset = sec; + + sec -= sec_offset; + newtime = sec * 1000000 + usec; + + if (last_time > 0) + usleep(newtime - last_time); + + gettimeofday(&event.time, NULL); + + if (write(fd, &event, sizeof(event)) < sizeof(event)) + perror("Send event failed."); + + last_time = newtime; +} + +static gboolean +event_cb (ClutterActor *actor, ClutterEvent *event, State *state) +{ + int i; + + if (event->type != CLUTTER_TOUCH_BEGIN && + event->type != CLUTTER_TOUCH_UPDATE) + return FALSE; + + state->gesture_points_to_check[state->gesture_points].x = ceil (event->touch.x); + state->gesture_points_to_check[state->gesture_points].y = ceil (event->touch.y); + state->gesture_points++; + + if (state->gesture_points == TOUCH_POINTS) + { + for (i = 0; i < TOUCH_POINTS; i++) + { + if (state->gesture_points_to_check[i].x != gesture_points[i].x || + state->gesture_points_to_check[i].y != gesture_points[i].y) + { + if (g_test_verbose ()) + g_print ("error: expected (%d, %d) but found (%d, %d) at position %d\n", + (int) gesture_points[i].x, (int) gesture_points[i].y, + (int) state->gesture_points_to_check[i].x, + (int) state->gesture_points_to_check[i].y, + i); + state->pass = FALSE; + break; + } + } + + clutter_main_quit (); + } + + return TRUE; +} + +static void +screen_coords_to_device (int screen_x, int screen_y, + int *device_x, int *device_y) +{ + int display_width = DisplayWidth (clutter_x11_get_default_display (), + clutter_x11_get_default_screen ()); + int display_height = DisplayHeight (clutter_x11_get_default_display (), + clutter_x11_get_default_screen ()); + + *device_x = (screen_x * ABS_MAX_X) / display_width; + *device_y = (screen_y * ABS_MAX_Y) / display_height; +} + +static gboolean +perform_gesture (gpointer data) +{ + int i; + + for (i = 0; i < TOUCH_POINTS; i++) + { + int x = gesture_points[i].x; + int y = gesture_points[i].y; + + screen_coords_to_device (x, y, &x, &y); + + send_event(fd, EV_ABS, ABS_MT_SLOT, 0, 1, i * 100); + send_event(fd, EV_ABS, ABS_MT_TRACKING_ID, 1, 1, i * 100 + 10); + + send_event(fd, EV_ABS, ABS_MT_POSITION_X, x, 1, i * 100 + 20); + send_event(fd, EV_ABS, ABS_MT_POSITION_Y, y, 1, i * 100 + 30); + send_event(fd, EV_SYN, SYN_MT_REPORT, 0, 1, i * 100 + 40); + send_event(fd, EV_SYN, SYN_REPORT, 0, 1, i * 100 + 50); + } + + send_event(fd, EV_ABS, ABS_MT_TRACKING_ID, -1, 1, TOUCH_POINTS * 100 + 10); + send_event(fd, EV_SYN, SYN_MT_REPORT, 0, 1, TOUCH_POINTS * 100 + 20); + send_event(fd, EV_SYN, SYN_REPORT, 0, 1, TOUCH_POINTS * 100 + 30); + + return G_SOURCE_REMOVE; +} + +static int +setup (struct uinput_user_dev *dev, int fd) +{ + strcpy (dev->name, "eGalax Touch Screen"); + dev->id.bustype = 0x18; + dev->id.vendor = 0xeef; + dev->id.product = 0x20; + dev->id.version = 0x1; + + if (ioctl (fd, UI_SET_EVBIT, EV_SYN) == -1) + goto error; + + if (ioctl (fd, UI_SET_EVBIT, EV_KEY) == -1) + goto error; + + if (ioctl (fd, UI_SET_KEYBIT, BTN_TOUCH) == -1) + goto error; + + if (ioctl (fd, UI_SET_EVBIT, EV_ABS) == -1) + goto error; + + if (ioctl (fd, UI_SET_ABSBIT, ABS_X) == -1) + goto error; + else + { + int idx = ABS_X; + dev->absmin[idx] = 0; + dev->absmax[idx] = ABS_MAX_X; + dev->absfuzz[idx] = 1; + dev->absflat[idx] = 0; + + if (dev->absmin[idx] == dev->absmax[idx]) + dev->absmax[idx]++; + } + + if (ioctl (fd, UI_SET_ABSBIT, ABS_Y) == -1) + goto error; + else + { + int idx = ABS_Y; + dev->absmin[idx] = 0; + dev->absmax[idx] = ABS_MAX_Y; + dev->absfuzz[idx] = 1; + dev->absflat[idx] = 0; + + if (dev->absmin[idx] == dev->absmax[idx]) + dev->absmax[idx]++; + } + + if (ioctl (fd, UI_SET_ABSBIT, ABS_PRESSURE) == -1) + goto error; + else + { + int idx = ABS_PRESSURE; + dev->absmin[idx] = 0; + dev->absmax[idx] = 0; + dev->absfuzz[idx] = 0; + dev->absflat[idx] = 0; + + if (dev->absmin[idx] == dev->absmax[idx]) + dev->absmax[idx]++; + } + + if (ioctl (fd, UI_SET_ABSBIT, ABS_MT_TOUCH_MAJOR) == -1) + goto error; + else + { + int idx = ABS_MT_TOUCH_MAJOR; + dev->absmin[idx] = 0; + dev->absmax[idx] = 255; + dev->absfuzz[idx] = 1; + dev->absflat[idx] = 0; + + if (dev->absmin[idx] == dev->absmax[idx]) + dev->absmax[idx]++; + } + + if (ioctl (fd, UI_SET_ABSBIT, ABS_MT_WIDTH_MAJOR) == -1) + goto error; + else + { + int idx = ABS_MT_WIDTH_MAJOR; + dev->absmin[idx] = 0; + dev->absmax[idx] = 255; + dev->absfuzz[idx] = 1; + dev->absflat[idx] = 0; + + if (dev->absmin[idx] == dev->absmax[idx]) + dev->absmax[idx]++; + } + + if (ioctl (fd, UI_SET_ABSBIT, ABS_MT_POSITION_X) == -1) + goto error; + else + { + int idx = ABS_MT_POSITION_X; + dev->absmin[idx] = 0; + dev->absmax[idx] = ABS_MAX_X; + dev->absfuzz[idx] = 1; + dev->absflat[idx] = 0; + + if (dev->absmin[idx] == dev->absmax[idx]) + dev->absmax[idx]++; + } + + if (ioctl (fd, UI_SET_ABSBIT, ABS_MT_POSITION_Y) == -1) + goto error; + else + { + int idx = ABS_MT_POSITION_Y; + dev->absmin[idx] = 0; + dev->absmax[idx] = ABS_MAX_Y; + dev->absfuzz[idx] = 1; + dev->absflat[idx] = 0; + + if (dev->absmin[idx] == dev->absmax[idx]) + dev->absmax[idx]++; + } + + if (ioctl (fd, UI_SET_ABSBIT, ABS_MT_TRACKING_ID) == -1) + goto error; + else + { + int idx = ABS_MT_TRACKING_ID; + dev->absmin[idx] = 0; + dev->absmax[idx] = 5; + dev->absfuzz[idx] = 0; + dev->absflat[idx] = 0; + + if (dev->absmin[idx] == dev->absmax[idx]) + dev->absmax[idx]++; + } + + + + return 0; +error: + perror ("ioctl failed."); + return -1; +} + +static int +init_uinput (void) +{ + struct uinput_user_dev dev; + + fd = open ("/dev/uinput", O_RDWR); + if (fd < 0 && errno == ENODEV) + fd = open ("/dev/input/uinput", O_RDWR); + if (fd < 0) + { + if (g_test_verbose ()) + perror ("open"); + + return 0; + }; + + memset (&dev, 0, sizeof (dev)); + setup (&dev, fd); + + if (write (fd, &dev, sizeof (dev)) < sizeof (dev)) + { + if (g_test_verbose ()) + perror ("write"); + + goto error; + } + + if (ioctl (fd, UI_DEV_CREATE, NULL) == -1) + { + if (g_test_verbose ()) + perror ("ioctl"); + + goto error; + } + + return 1; + +error: + if (fd != -1) + close (fd); + + return 0; +} + +#endif /* defined CLUTTER_WINDOWING_X11 && OS_LINUX && HAVE_XINPUT_2_2 */ + +static void +events_touch (void) +{ +#if defined CLUTTER_WINDOWING_X11 && OS_LINUX && HAVE_XINPUT_2_2 + ClutterActor *stage; + State state; + + /* bail out if we could not initialize evdev */ + if (!init_uinput ()) + return; + + state.pass = TRUE; + state.gesture_points = 0; + + stage = clutter_test_get_stage (); + g_signal_connect (stage, "event", G_CALLBACK (event_cb), &state); + clutter_stage_set_fullscreen (CLUTTER_STAGE (stage), TRUE); + clutter_actor_show (stage); + + clutter_threads_add_timeout (500, perform_gesture, &state); + + clutter_main (); + + if (g_test_verbose ()) + g_print ("end result: %s\n", state.pass ? "pass" : "FAIL"); + + g_assert (state.pass); +#endif /* defined CLUTTER_WINDOWING_X11 && OS_LINUX && HAVE_XINPUT_2_2 */ +} + +CLUTTER_TEST_SUITE ( + CLUTTER_TEST_UNIT ("/events/touch", events_touch) +) diff --git a/clutter/tests/conform/group.c b/clutter/tests/conform/group.c new file mode 100644 index 0000000..3f7b1fb --- /dev/null +++ b/clutter/tests/conform/group.c @@ -0,0 +1,60 @@ +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include + +static void +group_depth_sorting (void) +{ + ClutterActor *group; + ClutterActor *child, *test; + ClutterGroup *g; + GList *children; + + group = clutter_group_new (); + g = CLUTTER_GROUP (group); + + child = clutter_rectangle_new (); + clutter_actor_set_size (child, 20, 20); + clutter_actor_set_depth (child, 0); + clutter_actor_set_name (child, "zero"); + clutter_container_add_actor (CLUTTER_CONTAINER (group), child); + + children = clutter_container_get_children (CLUTTER_CONTAINER (group)); + g_assert (children->data == child); + g_assert (children->next == NULL); + g_list_free (children); + + child = clutter_rectangle_new (); + clutter_actor_set_size (child, 20, 20); + clutter_actor_set_depth (child, 10); + clutter_actor_set_name (child, "plus-ten"); + clutter_container_add_actor (CLUTTER_CONTAINER (group), child); + + test = clutter_group_get_nth_child (g, 0); + g_assert_cmpstr (clutter_actor_get_name (test), ==, "zero"); + + test = clutter_group_get_nth_child (g, 1); + g_assert_cmpstr (clutter_actor_get_name (test), ==, "plus-ten"); + + child = clutter_rectangle_new (); + clutter_actor_set_size (child, 20, 20); + clutter_actor_set_depth (child, -10); + clutter_actor_set_name (child, "minus-ten"); + clutter_container_add_actor (CLUTTER_CONTAINER (group), child); + + g_assert_cmpint (clutter_group_get_n_children (g), ==, 3); + + test = clutter_group_get_nth_child (g, 0); + g_assert_cmpstr (clutter_actor_get_name (test), ==, "minus-ten"); + + test = clutter_group_get_nth_child (g, 1); + g_assert_cmpstr (clutter_actor_get_name (test), ==, "zero"); + + test = clutter_group_get_nth_child (g, 2); + g_assert_cmpstr (clutter_actor_get_name (test), ==, "plus-ten"); + + clutter_actor_destroy (group); +} + +CLUTTER_TEST_SUITE ( + CLUTTER_TEST_UNIT ("/group/depth-sorting", group_depth_sorting) +) diff --git a/clutter/tests/conform/interval.c b/clutter/tests/conform/interval.c new file mode 100644 index 0000000..5204378 --- /dev/null +++ b/clutter/tests/conform/interval.c @@ -0,0 +1,117 @@ +#include + +static void +interval_initial_state (void) +{ + ClutterInterval *interval; + int initial, final; + const GValue *value; + + interval = clutter_interval_new (G_TYPE_INT, 0, 100); + g_assert (CLUTTER_IS_INTERVAL (interval)); + g_assert (clutter_interval_get_value_type (interval) == G_TYPE_INT); + + clutter_interval_get_interval (interval, &initial, &final); + g_assert_cmpint (initial, ==, 0); + g_assert_cmpint (final, ==, 100); + + value = clutter_interval_compute (interval, 0); + g_assert (G_VALUE_HOLDS_INT (value)); + g_assert_cmpint (g_value_get_int (value), ==, 0); + + value = clutter_interval_compute (interval, 1); + g_assert (G_VALUE_HOLDS_INT (value)); + g_assert_cmpint (g_value_get_int (value), ==, 100); + + value = clutter_interval_compute (interval, 0.5); + g_assert (G_VALUE_HOLDS_INT (value)); + g_assert_cmpint (g_value_get_int (value), ==, 50); + + clutter_interval_set_final (interval, 200); + value = clutter_interval_peek_final_value (interval); + g_assert (G_VALUE_HOLDS_INT (value)); + g_assert_cmpint (g_value_get_int (value), ==, 200); + + g_object_unref (interval); +} + +static void +interval_transform (void) +{ + ClutterInterval *interval; + GValue value = G_VALUE_INIT; + const GValue *value_p = NULL; + + interval = clutter_interval_new_with_values (G_TYPE_FLOAT, NULL, NULL); + + g_value_init (&value, G_TYPE_DOUBLE); + + g_value_set_double (&value, 0.0); + clutter_interval_set_initial_value (interval, &value); + + g_value_set_double (&value, 100.0); + clutter_interval_set_final_value (interval, &value); + + g_value_unset (&value); + + value_p = clutter_interval_peek_initial_value (interval); + g_assert (G_VALUE_HOLDS_FLOAT (value_p)); + g_assert_cmpfloat (g_value_get_float (value_p), ==, 0.f); + + value_p = clutter_interval_peek_final_value (interval); + g_assert (G_VALUE_HOLDS_FLOAT (value_p)); + g_assert_cmpfloat (g_value_get_float (value_p), ==, 100.f); + + g_object_unref (interval); +} + +static void +interval_from_script (void) +{ + ClutterScript *script = clutter_script_new (); + ClutterInterval *interval; + gchar *test_file; + GError *error = NULL; + GValue *initial, *final; + + test_file = g_test_build_filename (G_TEST_DIST, + "scripts", + "test-script-interval.json", + NULL); + clutter_script_load_from_file (script, test_file, &error); + if (g_test_verbose () && error) + g_printerr ("\tError: %s", error->message); + + g_assert_no_error (error); + + interval = CLUTTER_INTERVAL (clutter_script_get_object (script, "int-1")); + initial = clutter_interval_peek_initial_value (interval); + if (g_test_verbose ()) + g_test_message ("\tinitial ['%s'] = '%.2f'", + g_type_name (G_VALUE_TYPE (initial)), + g_value_get_float (initial)); + g_assert (G_VALUE_HOLDS (initial, G_TYPE_FLOAT)); + g_assert_cmpfloat (g_value_get_float (initial), ==, 23.3f); + final = clutter_interval_peek_final_value (interval); + if (g_test_verbose ()) + g_test_message ("\tfinal ['%s'] = '%.2f'", + g_type_name (G_VALUE_TYPE (final)), + g_value_get_float (final)); + g_assert (G_VALUE_HOLDS (final, G_TYPE_FLOAT)); + g_assert_cmpfloat (g_value_get_float (final), ==, 42.2f); + + interval = CLUTTER_INTERVAL (clutter_script_get_object (script, "int-2")); + initial = clutter_interval_peek_initial_value (interval); + g_assert (G_VALUE_HOLDS (initial, CLUTTER_TYPE_COLOR)); + final = clutter_interval_peek_final_value (interval); + g_assert (G_VALUE_HOLDS (final, CLUTTER_TYPE_COLOR)); + + g_object_unref (script); + g_free (test_file); +} + +CLUTTER_TEST_SUITE ( + CLUTTER_TEST_UNIT ("/interval/initial-state", interval_initial_state) + CLUTTER_TEST_UNIT ("/interval/transform", interval_transform) + CLUTTER_TEST_UNIT ("/interval/from-script", interval_from_script) +) diff --git a/clutter/tests/conform/model.c b/clutter/tests/conform/model.c new file mode 100644 index 0000000..f7b0c0b --- /dev/null +++ b/clutter/tests/conform/model.c @@ -0,0 +1,528 @@ +#include +#include +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include + +typedef struct _ModelData +{ + ClutterModel *model; + + guint n_row; +} ModelData; + +typedef struct _ChangedData +{ + ClutterModel *model; + + ClutterModelIter *iter; + + guint row; + guint n_emissions; + + gint value_check; +} ChangedData; + +enum +{ + COLUMN_FOO, /* G_TYPE_STRING */ + COLUMN_BAR, /* G_TYPE_INT */ + + N_COLUMNS +}; + +static const struct { + const gchar *expected_foo; + gint expected_bar; +} base_model[] = { + { "String 1", 1 }, + { "String 2", 2 }, + { "String 3", 3 }, + { "String 4", 4 }, + { "String 5", 5 }, + { "String 6", 6 }, + { "String 7", 7 }, + { "String 8", 8 }, + { "String 9", 9 }, +}; + +static const struct { + const gchar *expected_foo; + gint expected_bar; +} forward_base[] = { + { "String 1", 1 }, + { "String 2", 2 }, + { "String 3", 3 }, + { "String 4", 4 }, + { "String 5", 5 }, + { "String 6", 6 }, + { "String 7", 7 }, + { "String 8", 8 }, + { "String 9", 9 }, +}; + +static const struct { + const gchar *expected_foo; + gint expected_bar; +} backward_base[] = { + { "String 9", 9 }, + { "String 8", 8 }, + { "String 7", 7 }, + { "String 6", 6 }, + { "String 5", 5 }, + { "String 4", 4 }, + { "String 3", 3 }, + { "String 2", 2 }, + { "String 1", 1 }, +}; + +static const struct { + const gchar *expected_foo; + gint expected_bar; +} filter_odd[] = { + { "String 1", 1 }, + { "String 3", 3 }, + { "String 5", 5 }, + { "String 7", 7 }, + { "String 9", 9 }, +}; + +static const struct { + const gchar *expected_foo; + gint expected_bar; +} filter_even[] = { + { "String 8", 8 }, + { "String 6", 6 }, + { "String 4", 4 }, + { "String 2", 2 }, +}; + +static inline void +compare_iter (ClutterModelIter *iter, + const gint expected_row, + const gchar *expected_foo, + const gint expected_bar) +{ + gchar *foo = NULL; + gint bar = 0; + gint row = 0; + + row = clutter_model_iter_get_row (iter); + clutter_model_iter_get (iter, + COLUMN_FOO, &foo, + COLUMN_BAR, &bar, + -1); + + if (g_test_verbose ()) + g_print ("Row %d => %d: Got [ '%s', '%d' ], expected [ '%s', '%d' ]\n", + row, expected_row, + foo, bar, + expected_foo, expected_bar); + + g_assert_cmpint (row, ==, expected_row); + g_assert_cmpstr (foo, ==, expected_foo); + g_assert_cmpint (bar, ==, expected_bar); + + g_free (foo); +} + +static void +on_row_added (ClutterModel *model, + ClutterModelIter *iter, + gpointer data) +{ + ModelData *model_data = data; + + compare_iter (iter, + model_data->n_row, + base_model[model_data->n_row].expected_foo, + base_model[model_data->n_row].expected_bar); + + model_data->n_row += 1; +} + +static gboolean +filter_even_rows (ClutterModel *model, + ClutterModelIter *iter, + gpointer dummy G_GNUC_UNUSED) +{ + gint bar_value; + + clutter_model_iter_get (iter, COLUMN_BAR, &bar_value, -1); + + if (bar_value % 2 == 0) + return TRUE; + + return FALSE; +} + +static gboolean +filter_odd_rows (ClutterModel *model, + ClutterModelIter *iter, + gpointer dummy G_GNUC_UNUSED) +{ + gint bar_value; + + clutter_model_iter_get (iter, COLUMN_BAR, &bar_value, -1); + + if (bar_value % 2 != 0) + return TRUE; + + return FALSE; +} + +static void +list_model_filter (void) +{ + ModelData test_data = { NULL, 0 }; + ClutterModelIter *iter; + gint i; + + test_data.model = clutter_list_model_new (N_COLUMNS, + G_TYPE_STRING, "Foo", + G_TYPE_INT, "Bar"); + test_data.n_row = 0; + + for (i = 1; i < 10; i++) + { + gchar *foo = g_strdup_printf ("String %d", i); + + clutter_model_append (test_data.model, + COLUMN_FOO, foo, + COLUMN_BAR, i, + -1); + + g_free (foo); + } + + if (g_test_verbose ()) + g_print ("Forward iteration (filter odd)...\n"); + + clutter_model_set_filter (test_data.model, filter_odd_rows, NULL, NULL); + + iter = clutter_model_get_first_iter (test_data.model); + g_assert (iter != NULL); + + i = 0; + while (!clutter_model_iter_is_last (iter)) + { + compare_iter (iter, i, + filter_odd[i].expected_foo, + filter_odd[i].expected_bar); + + iter = clutter_model_iter_next (iter); + i += 1; + } + + g_object_unref (iter); + + if (g_test_verbose ()) + g_print ("Backward iteration (filter even)...\n"); + + clutter_model_set_filter (test_data.model, filter_even_rows, NULL, NULL); + + iter = clutter_model_get_last_iter (test_data.model); + g_assert (iter != NULL); + + i = 0; + do + { + compare_iter (iter, G_N_ELEMENTS (filter_even) - i - 1, + filter_even[i].expected_foo, + filter_even[i].expected_bar); + + iter = clutter_model_iter_prev (iter); + i += 1; + } + while (!clutter_model_iter_is_first (iter)); + + g_object_unref (iter); + + if (g_test_verbose ()) + g_print ("get_iter_at_row...\n"); + + clutter_model_set_filter (test_data.model, filter_odd_rows, NULL, NULL); + + for (i = 0; i < 5; i++) + { + iter = clutter_model_get_iter_at_row (test_data.model, i); + compare_iter (iter, i , + filter_odd[i].expected_foo, + filter_odd[i].expected_bar); + g_object_unref (iter); + } + + iter = clutter_model_get_iter_at_row (test_data.model, 5); + g_assert (iter == NULL); + + g_object_unref (test_data.model); +} + +static void +list_model_iterate (void) +{ + ModelData test_data = { NULL, 0 }; + ClutterModelIter *iter; + gint i; + + test_data.model = clutter_list_model_new (N_COLUMNS, + G_TYPE_STRING, "Foo", + G_TYPE_INT, "Bar"); + test_data.n_row = 0; + + g_signal_connect (test_data.model, "row-added", + G_CALLBACK (on_row_added), + &test_data); + + for (i = 1; i < 10; i++) + { + gchar *foo = g_strdup_printf ("String %d", i); + + clutter_model_append (test_data.model, + COLUMN_FOO, foo, + COLUMN_BAR, i, + -1); + + g_free (foo); + } + + if (g_test_verbose ()) + g_print ("Forward iteration...\n"); + + iter = clutter_model_get_first_iter (test_data.model); + g_assert (iter != NULL); + + i = 0; + while (!clutter_model_iter_is_last (iter)) + { + compare_iter (iter, i, + forward_base[i].expected_foo, + forward_base[i].expected_bar); + + iter = clutter_model_iter_next (iter); + i += 1; + } + + g_object_unref (iter); + + if (g_test_verbose ()) + g_print ("Backward iteration...\n"); + + iter = clutter_model_get_last_iter (test_data.model); + g_assert (iter != NULL); + + i = 0; + do + { + compare_iter (iter, G_N_ELEMENTS (backward_base) - i - 1, + backward_base[i].expected_foo, + backward_base[i].expected_bar); + + iter = clutter_model_iter_prev (iter); + i += 1; + } + while (!clutter_model_iter_is_first (iter)); + + compare_iter (iter, G_N_ELEMENTS (backward_base) - i - 1, + backward_base[i].expected_foo, + backward_base[i].expected_bar); + + g_object_unref (iter); + + g_object_unref (test_data.model); +} + +static void +list_model_populate (void) +{ + ModelData test_data = { NULL, 0 }; + gint i; + + test_data.model = clutter_list_model_new (N_COLUMNS, + G_TYPE_STRING, "Foo", + G_TYPE_INT, "Bar"); + test_data.n_row = 0; + + g_signal_connect (test_data.model, "row-added", + G_CALLBACK (on_row_added), + &test_data); + + for (i = 1; i < 10; i++) + { + gchar *foo = g_strdup_printf ("String %d", i); + + clutter_model_append (test_data.model, + COLUMN_FOO, foo, + COLUMN_BAR, i, + -1); + + g_free (foo); + } + + g_object_unref (test_data.model); +} + +static void +list_model_from_script (void) +{ + ClutterScript *script = clutter_script_new (); + GObject *model; + GError *error = NULL; + gchar *test_file; + const gchar *name; + GType type; + ClutterModelIter *iter; + GValue value = { 0, }; + + test_file = g_test_build_filename (G_TEST_DIST, "scripts", "test-script-model.json", NULL); + clutter_script_load_from_file (script, test_file, &error); + if (g_test_verbose () && error) + g_print ("Error: %s", error->message); + + g_assert_no_error (error); + + model = clutter_script_get_object (script, "test-model"); + + g_assert (CLUTTER_IS_MODEL (model)); + g_assert (clutter_model_get_n_columns (CLUTTER_MODEL (model)) == 3); + + name = clutter_model_get_column_name (CLUTTER_MODEL (model), 0); + type = clutter_model_get_column_type (CLUTTER_MODEL (model), 0); + + if (g_test_verbose ()) + g_print ("column[0]: %s, type: %s\n", name, g_type_name (type)); + + g_assert (strcmp (name, "text-column") == 0); + g_assert (type == G_TYPE_STRING); + + name = clutter_model_get_column_name (CLUTTER_MODEL (model), 2); + type = clutter_model_get_column_type (CLUTTER_MODEL (model), 2); + + if (g_test_verbose ()) + g_print ("column[2]: %s, type: %s\n", name, g_type_name (type)); + + g_assert (strcmp (name, "actor-column") == 0); + g_assert (g_type_is_a (type, CLUTTER_TYPE_ACTOR)); + + g_assert (clutter_model_get_n_rows (CLUTTER_MODEL (model)) == 3); + + iter = clutter_model_get_iter_at_row (CLUTTER_MODEL (model), 0); + clutter_model_iter_get_value (iter, 0, &value); + g_assert (G_VALUE_HOLDS_STRING (&value)); + g_assert (strcmp (g_value_get_string (&value), "text-row-1") == 0); + g_value_unset (&value); + + clutter_model_iter_get_value (iter, 1, &value); + g_assert (G_VALUE_HOLDS_INT (&value)); + g_assert (g_value_get_int (&value) == 1); + g_value_unset (&value); + + clutter_model_iter_get_value (iter, 2, &value); + g_assert (G_VALUE_HOLDS_OBJECT (&value)); + g_assert (g_value_get_object (&value) == NULL); + g_value_unset (&value); + + iter = clutter_model_iter_next (iter); + clutter_model_iter_get_value (iter, 2, &value); + g_assert (G_VALUE_HOLDS_OBJECT (&value)); + g_assert (CLUTTER_IS_ACTOR (g_value_get_object (&value))); + g_value_unset (&value); + + iter = clutter_model_iter_next (iter); + clutter_model_iter_get_value (iter, 2, &value); + g_assert (G_VALUE_HOLDS_OBJECT (&value)); + g_assert (CLUTTER_IS_ACTOR (g_value_get_object (&value))); + g_assert (strcmp (clutter_actor_get_name (g_value_get_object (&value)), + "actor-row-3") == 0); + g_value_unset (&value); + g_object_unref (iter); +} + +static void +on_row_changed (ClutterModel *model, + ClutterModelIter *iter, + ChangedData *data) +{ + gint value = -1; + + clutter_model_iter_get (iter, COLUMN_BAR, &value, -1); + + if (g_test_verbose ()) + g_print ("row-changed value-check: %d, expected: %d\n", + value, data->value_check); + + g_assert_cmpint (value, ==, data->value_check); + + data->n_emissions += 1; +} + +static void +list_model_row_changed (void) +{ + ChangedData test_data = { NULL, NULL, 0, 0 }; + GValue value = { 0, }; + gint i; + + test_data.model = clutter_list_model_new (N_COLUMNS, + G_TYPE_STRING, "Foo", + G_TYPE_INT, "Bar"); + for (i = 1; i < 10; i++) + { + gchar *foo = g_strdup_printf ("String %d", i); + + clutter_model_append (test_data.model, + COLUMN_FOO, foo, + COLUMN_BAR, i, + -1); + + g_free (foo); + } + + g_signal_connect (test_data.model, "row-changed", + G_CALLBACK (on_row_changed), + &test_data); + + test_data.row = g_random_int_range (0, 9); + test_data.iter = clutter_model_get_iter_at_row (test_data.model, + test_data.row); + g_assert (CLUTTER_IS_MODEL_ITER (test_data.iter)); + + test_data.value_check = 47; + + g_value_init (&value, G_TYPE_INT); + g_value_set_int (&value, test_data.value_check); + + clutter_model_iter_set_value (test_data.iter, COLUMN_BAR, &value); + + g_value_unset (&value); + + if (g_test_verbose ()) + g_print ("iter.set_value() emissions: %d, expected: 1\n", + test_data.n_emissions); + + g_assert_cmpint (test_data.n_emissions, ==, 1); + + test_data.n_emissions = 0; + test_data.value_check = 42; + + clutter_model_iter_set (test_data.iter, + COLUMN_FOO, "changed", + COLUMN_BAR, test_data.value_check, + -1); + + if (g_test_verbose ()) + g_print ("iter.set() emissions: %d, expected: 1\n", + test_data.n_emissions); + + g_assert_cmpint (test_data.n_emissions, ==, 1); + + g_object_unref (test_data.iter); + g_object_unref (test_data.model); +} + +CLUTTER_TEST_SUITE ( + CLUTTER_TEST_UNIT ("/list-model/populate", list_model_populate) + CLUTTER_TEST_UNIT ("/list-model/iterate", list_model_iterate) + CLUTTER_TEST_UNIT ("/list-model/filter", list_model_filter) + CLUTTER_TEST_UNIT ("/list-model/row-changed", list_model_row_changed) + CLUTTER_TEST_UNIT ("/list-model/from-script", list_model_from_script) +) diff --git a/clutter/tests/conform/rectangle.c b/clutter/tests/conform/rectangle.c new file mode 100644 index 0000000..1c09f00 --- /dev/null +++ b/clutter/tests/conform/rectangle.c @@ -0,0 +1,51 @@ +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include + +static void +rectangle_set_size (void) +{ + ClutterActor *rect = clutter_rectangle_new (); + + /* initial positioning */ + g_assert_cmpint (clutter_actor_get_x (rect), ==, 0); + g_assert_cmpint (clutter_actor_get_y (rect), ==, 0); + + clutter_actor_set_size (rect, 100, 100); + + /* make sure that changing the size does not affect the + * rest of the bounding box + */ + g_assert_cmpint (clutter_actor_get_x (rect), ==, 0); + g_assert_cmpint (clutter_actor_get_y (rect), ==, 0); + + g_assert_cmpint (clutter_actor_get_width (rect), ==, 100); + g_assert_cmpint (clutter_actor_get_height (rect), ==, 100); + + clutter_actor_destroy (rect); +} + +static void +rectangle_set_color (void) +{ + ClutterActor *rect = clutter_rectangle_new (); + ClutterColor white = { 255, 255, 255, 255 }; + ClutterColor black = { 0, 0, 0, 255 }; + ClutterColor check = { 0, }; + + clutter_rectangle_set_color (CLUTTER_RECTANGLE (rect), &black); + clutter_rectangle_get_color (CLUTTER_RECTANGLE (rect), &check); + g_assert_cmpint (check.blue, ==, black.blue); + + clutter_rectangle_set_color (CLUTTER_RECTANGLE (rect), &white); + clutter_rectangle_get_color (CLUTTER_RECTANGLE (rect), &check); + g_assert_cmpint (check.green, ==, white.green); + + g_assert_cmpint (clutter_actor_get_opacity (rect), ==, white.alpha); + + clutter_actor_destroy (rect); +} + +CLUTTER_TEST_SUITE ( + CLUTTER_TEST_UNIT ("/rectangle/set-size", rectangle_set_size) + CLUTTER_TEST_UNIT ("/rectangle/set-color", rectangle_set_color) +) diff --git a/clutter/tests/conform/script-parser.c b/clutter/tests/conform/script-parser.c new file mode 100644 index 0000000..c2e2dbd --- /dev/null +++ b/clutter/tests/conform/script-parser.c @@ -0,0 +1,427 @@ +#include +#include + +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include + +#define TEST_TYPE_GROUP (test_group_get_type ()) +#define TEST_TYPE_GROUP_META (test_group_meta_get_type ()) + +#define TEST_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_GROUP, TestGroup)) +#define TEST_IS_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_GROUP)) + +#define TEST_GROUP_META(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_GROUP_META, TestGroupMeta)) +#define TEST_IS_GROUP_META(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_GROUP_META)) + +typedef struct _ClutterActor TestGroup; +typedef struct _ClutterActorClass TestGroupClass; + +typedef struct _TestGroupMeta { + ClutterChildMeta parent_instance; + + guint is_focus : 1; +} TestGroupMeta; + +typedef struct _ClutterChildMetaClass TestGroupMetaClass; + +GType test_group_meta_get_type (void); + +G_DEFINE_TYPE (TestGroupMeta, test_group_meta, CLUTTER_TYPE_CHILD_META) + +enum +{ + PROP_META_0, + + PROP_META_FOCUS +}; + +static void +test_group_meta_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + TestGroupMeta *self = TEST_GROUP_META (gobject); + + switch (prop_id) + { + case PROP_META_FOCUS: + self->is_focus = g_value_get_boolean (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +test_group_meta_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + TestGroupMeta *self = TEST_GROUP_META (gobject); + + switch (prop_id) + { + case PROP_META_FOCUS: + g_value_set_boolean (value, self->is_focus); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +test_group_meta_class_init (TestGroupMetaClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GParamSpec *pspec; + + gobject_class->set_property = test_group_meta_set_property; + gobject_class->get_property = test_group_meta_get_property; + + pspec = g_param_spec_boolean ("focus", "Focus", "Focus", + FALSE, + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_META_FOCUS, pspec); +} + +static void +test_group_meta_init (TestGroupMeta *meta) +{ + meta->is_focus = FALSE; +} + +static void +clutter_container_iface_init (ClutterContainerIface *iface) +{ + iface->child_meta_type = TEST_TYPE_GROUP_META; +} + +GType test_group_get_type (void); + +G_DEFINE_TYPE_WITH_CODE (TestGroup, test_group, CLUTTER_TYPE_ACTOR, + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER, + clutter_container_iface_init)) + +static void +test_group_class_init (TestGroupClass *klass) +{ +} + +static void +test_group_init (TestGroup *self) +{ +} + +static void +script_child (void) +{ + ClutterScript *script = clutter_script_new (); + GObject *container, *actor; + GError *error = NULL; + gboolean focus_ret; + gchar *test_file; + + test_file = g_test_build_filename (G_TEST_DIST, "scripts", "test-script-child.json", NULL); + clutter_script_load_from_file (script, test_file, &error); + if (g_test_verbose () && error) + g_print ("Error: %s", error->message); + + g_assert_no_error (error); + + container = actor = NULL; + clutter_script_get_objects (script, + "test-group", &container, + "test-rect-1", &actor, + NULL); + g_assert (TEST_IS_GROUP (container)); + g_assert (CLUTTER_IS_RECTANGLE (actor)); + + focus_ret = FALSE; + clutter_container_child_get (CLUTTER_CONTAINER (container), + CLUTTER_ACTOR (actor), + "focus", &focus_ret, + NULL); + g_assert (focus_ret); + + actor = clutter_script_get_object (script, "test-rect-2"); + g_assert (CLUTTER_IS_RECTANGLE (actor)); + + focus_ret = FALSE; + clutter_container_child_get (CLUTTER_CONTAINER (container), + CLUTTER_ACTOR (actor), + "focus", &focus_ret, + NULL); + g_assert (!focus_ret); + + g_object_unref (script); + g_free (test_file); +} + +static void +script_single (void) +{ + ClutterScript *script = clutter_script_new (); + ClutterColor color = { 0, }; + GObject *actor = NULL; + GError *error = NULL; + ClutterActor *rect; + gchar *test_file; + + test_file = g_test_build_filename (G_TEST_DIST, "scripts", "test-script-single.json", NULL); + clutter_script_load_from_file (script, test_file, &error); + if (g_test_verbose () && error) + g_print ("Error: %s", error->message); + + g_assert_no_error (error); + + actor = clutter_script_get_object (script, "test"); + g_assert (CLUTTER_IS_RECTANGLE (actor)); + + rect = CLUTTER_ACTOR (actor); + g_assert_cmpfloat (clutter_actor_get_width (rect), ==, 50.0); + g_assert_cmpfloat (clutter_actor_get_y (rect), ==, 100.0); + + clutter_rectangle_get_color (CLUTTER_RECTANGLE (rect), &color); + g_assert_cmpint (color.red, ==, 255); + g_assert_cmpint (color.green, ==, 0xcc); + g_assert_cmpint (color.alpha, ==, 0xff); + + g_object_unref (script); + g_free (test_file); +} + +static void +script_implicit_alpha (void) +{ + ClutterScript *script = clutter_script_new (); + ClutterTimeline *timeline; + GObject *behaviour = NULL; + GError *error = NULL; + ClutterAlpha *alpha; + gchar *test_file; + + test_file = g_test_build_filename (G_TEST_DIST, "scripts", "test-script-implicit-alpha.json", NULL); + clutter_script_load_from_file (script, test_file, &error); + if (g_test_verbose () && error) + g_print ("Error: %s", error->message); + +#if GLIB_CHECK_VERSION (2, 20, 0) + g_assert_no_error (error); +#else + g_assert (error == NULL); +#endif + + behaviour = clutter_script_get_object (script, "test"); + g_assert (CLUTTER_IS_BEHAVIOUR (behaviour)); + + alpha = clutter_behaviour_get_alpha (CLUTTER_BEHAVIOUR (behaviour)); + g_assert (CLUTTER_IS_ALPHA (alpha)); + + g_assert_cmpint (clutter_alpha_get_mode (alpha), ==, CLUTTER_EASE_OUT_CIRC); + + timeline = clutter_alpha_get_timeline (alpha); + g_assert (CLUTTER_IS_TIMELINE (timeline)); + + g_assert_cmpint (clutter_timeline_get_duration (timeline), ==, 500); + + g_object_unref (script); + g_free (test_file); +} + +static void +script_object_property (void) +{ + ClutterScript *script = clutter_script_new (); + ClutterLayoutManager *manager; + GObject *actor = NULL; + GError *error = NULL; + gchar *test_file; + + test_file = g_test_build_filename (G_TEST_DIST, "scripts", "test-script-object-property.json", NULL); + clutter_script_load_from_file (script, test_file, &error); + if (g_test_verbose () && error) + g_print ("Error: %s", error->message); + + g_assert_no_error (error); + + actor = clutter_script_get_object (script, "test"); + g_assert (CLUTTER_IS_BOX (actor)); + + manager = clutter_box_get_layout_manager (CLUTTER_BOX (actor)); + g_assert (CLUTTER_IS_BIN_LAYOUT (manager)); + + g_object_unref (script); + g_free (test_file); +} + +static void +script_named_object (void) +{ + ClutterScript *script = clutter_script_new (); + ClutterLayoutManager *manager; + GObject *actor = NULL; + GError *error = NULL; + gchar *test_file; + + test_file = g_test_build_filename (G_TEST_DIST, "scripts", "test-script-named-object.json", NULL); + clutter_script_load_from_file (script, test_file, &error); + if (g_test_verbose () && error) + g_print ("Error: %s", error->message); + + g_assert_no_error (error); + + actor = clutter_script_get_object (script, "test"); + g_assert (CLUTTER_IS_BOX (actor)); + + manager = clutter_box_get_layout_manager (CLUTTER_BOX (actor)); + g_assert (CLUTTER_IS_BOX_LAYOUT (manager)); + g_assert (clutter_box_layout_get_vertical (CLUTTER_BOX_LAYOUT (manager))); + + g_object_unref (script); + g_free (test_file); +} + +static void +script_animation (void) +{ + ClutterScript *script = clutter_script_new (); + GObject *animation = NULL; + GError *error = NULL; + gchar *test_file; + + test_file = g_test_build_filename (G_TEST_DIST, "scripts", "test-script-animation.json", NULL); + clutter_script_load_from_file (script, test_file, &error); + if (g_test_verbose () && error) + g_print ("Error: %s", error->message); + + g_assert_no_error (error); + + animation = clutter_script_get_object (script, "test"); + g_assert (CLUTTER_IS_ANIMATION (animation)); + + g_object_unref (script); + g_free (test_file); +} + +static void +script_layout_property (void) +{ + ClutterScript *script = clutter_script_new (); + GObject *manager, *container, *actor1, *actor2; + GError *error = NULL; + gchar *test_file; + gboolean x_fill, expand; + ClutterBoxAlignment y_align; + + test_file = g_test_build_filename (G_TEST_DIST, "scripts", "test-script-layout-property.json", NULL); + clutter_script_load_from_file (script, test_file, &error); + if (g_test_verbose () && error) + g_print ("Error: %s", error->message); + + g_assert_no_error (error); + + manager = container = actor1 = actor2 = NULL; + clutter_script_get_objects (script, + "manager", &manager, + "container", &container, + "actor-1", &actor1, + "actor-2", &actor2, + NULL); + + g_assert (CLUTTER_IS_LAYOUT_MANAGER (manager)); + g_assert (CLUTTER_IS_CONTAINER (container)); + g_assert (CLUTTER_IS_ACTOR (actor1)); + g_assert (CLUTTER_IS_ACTOR (actor2)); + + x_fill = FALSE; + y_align = CLUTTER_BOX_ALIGNMENT_START; + expand = FALSE; + clutter_layout_manager_child_get (CLUTTER_LAYOUT_MANAGER (manager), + CLUTTER_CONTAINER (container), + CLUTTER_ACTOR (actor1), + "x-fill", &x_fill, + "y-align", &y_align, + "expand", &expand, + NULL); + + g_assert (x_fill); + g_assert (y_align == CLUTTER_BOX_ALIGNMENT_CENTER); + g_assert (expand); + + x_fill = TRUE; + y_align = CLUTTER_BOX_ALIGNMENT_START; + expand = TRUE; + clutter_layout_manager_child_get (CLUTTER_LAYOUT_MANAGER (manager), + CLUTTER_CONTAINER (container), + CLUTTER_ACTOR (actor2), + "x-fill", &x_fill, + "y-align", &y_align, + "expand", &expand, + NULL); + + g_assert (x_fill == FALSE); + g_assert (y_align == CLUTTER_BOX_ALIGNMENT_END); + g_assert (expand == FALSE); + + g_object_unref (script); +} + +static void +script_margin (void) +{ + ClutterScript *script = clutter_script_new (); + ClutterActor *actor; + gchar *test_file; + GError *error = NULL; + + test_file = g_test_build_filename (G_TEST_DIST, "scripts", "test-script-margin.json", NULL); + clutter_script_load_from_file (script, test_file, &error); + if (g_test_verbose () && error) + g_print ("Error: %s", error->message); + + g_assert_no_error (error); + + actor = CLUTTER_ACTOR (clutter_script_get_object (script, "actor-1")); + g_assert_cmpfloat (clutter_actor_get_margin_top (actor), ==, 10.0f); + g_assert_cmpfloat (clutter_actor_get_margin_right (actor), ==, 10.0f); + g_assert_cmpfloat (clutter_actor_get_margin_bottom (actor), ==, 10.0f); + g_assert_cmpfloat (clutter_actor_get_margin_left (actor), ==, 10.0f); + + actor = CLUTTER_ACTOR (clutter_script_get_object (script, "actor-2")); + g_assert_cmpfloat (clutter_actor_get_margin_top (actor), ==, 10.0f); + g_assert_cmpfloat (clutter_actor_get_margin_right (actor), ==, 20.0f); + g_assert_cmpfloat (clutter_actor_get_margin_bottom (actor), ==, 10.0f); + g_assert_cmpfloat (clutter_actor_get_margin_left (actor), ==, 20.0f); + + actor = CLUTTER_ACTOR (clutter_script_get_object (script, "actor-3")); + g_assert_cmpfloat (clutter_actor_get_margin_top (actor), ==, 10.0f); + g_assert_cmpfloat (clutter_actor_get_margin_right (actor), ==, 20.0f); + g_assert_cmpfloat (clutter_actor_get_margin_bottom (actor), ==, 30.0f); + g_assert_cmpfloat (clutter_actor_get_margin_left (actor), ==, 20.0f); + + actor = CLUTTER_ACTOR (clutter_script_get_object (script, "actor-4")); + g_assert_cmpfloat (clutter_actor_get_margin_top (actor), ==, 10.0f); + g_assert_cmpfloat (clutter_actor_get_margin_right (actor), ==, 20.0f); + g_assert_cmpfloat (clutter_actor_get_margin_bottom (actor), ==, 30.0f); + g_assert_cmpfloat (clutter_actor_get_margin_left (actor), ==, 40.0f); + + g_object_unref (script); + g_free (test_file); +} + +CLUTTER_TEST_SUITE ( + CLUTTER_TEST_UNIT ("/script/single-object", script_single) + CLUTTER_TEST_UNIT ("/script/container-child", script_child) + CLUTTER_TEST_UNIT ("/script/named-object", script_named_object) + CLUTTER_TEST_UNIT ("/script/animation", script_animation) + CLUTTER_TEST_UNIT ("/script/implicit-alpha", script_implicit_alpha) + CLUTTER_TEST_UNIT ("/script/object-property", script_object_property) + CLUTTER_TEST_UNIT ("/script/layout-property", script_layout_property) + CLUTTER_TEST_UNIT ("/script/actor-margin", script_margin) +) diff --git a/clutter/tests/conform/scripts/test-animator-1.json b/clutter/tests/conform/scripts/test-animator-1.json new file mode 100644 index 0000000..2d6aab9 --- /dev/null +++ b/clutter/tests/conform/scripts/test-animator-1.json @@ -0,0 +1,5 @@ +{ + "type" : "ClutterAnimator", + "id" : "animator", + "duration" : 1000 +} diff --git a/clutter/tests/conform/scripts/test-animator-2.json b/clutter/tests/conform/scripts/test-animator-2.json new file mode 100644 index 0000000..9059f57 --- /dev/null +++ b/clutter/tests/conform/scripts/test-animator-2.json @@ -0,0 +1,29 @@ +[ + { + "type" : "ClutterRectangle", + "id" : "foo", + "x" : 0, + "y" : 0, + "width" : 100, + "height" : 100 + }, + { + "type" : "ClutterAnimator", + "id" : "animator", + "duration" : 1000, + + "properties" : [ + { + "object" : "foo", + "name" : "x", + "ease-in" : true, + "interpolation" : "linear", + "keys" : [ + [ 0.0, "easeInCubic", 100.0 ], + [ 0.2, "easeOutCubic", 150.0 ], + [ 0.8, "linear", 200.0 ] + ] + } + ] + } +] diff --git a/clutter/tests/conform/scripts/test-animator-3.json b/clutter/tests/conform/scripts/test-animator-3.json new file mode 100644 index 0000000..26d779b --- /dev/null +++ b/clutter/tests/conform/scripts/test-animator-3.json @@ -0,0 +1,40 @@ +[ + { + "type" : "ClutterRectangle", + "id" : "foo", + "x" : 0, + "y" : 0, + "width" : 100, + "height" : 100 + }, + { + "type" : "ClutterAnimator", + "id" : "animator", + "duration" : 1000, + + "properties" : [ + { + "object" : "foo", + "name" : "x", + "ease-in" : true, + "interpolation" : "linear", + "keys" : [ + [ 0.0, "easeInCubic", 100.0 ], + [ 0.2, "easeOutCubic", 150.0 ], + [ 0.8, "linear", 200.0 ] + ] + }, + { + "object" : "foo", + "name" : "y", + "ease-in" : true, + "interpolation" : "linear", + "keys" : [ + [ 0.0, "easeInCubic", 100.0 ], + [ 0.2, "easeOutCubic", 150.0 ], + [ 0.8, "linear", 200.0 ] + ] + } + ] + } +] diff --git a/clutter/tests/conform/scripts/test-script-animation.json b/clutter/tests/conform/scripts/test-script-animation.json new file mode 100644 index 0000000..d6ef903 --- /dev/null +++ b/clutter/tests/conform/scripts/test-script-animation.json @@ -0,0 +1,14 @@ +{ + "type" : "ClutterAnimation", + "id" : "test", + "mode" : "easeInCubic", + "duration" : 500, + "object" : { + "type" : "ClutterRectangle", + "id" : "rect", + "opacity" : 128, + "width" : 100, + "height" : 16, + "color" : "white" + } +} diff --git a/clutter/tests/conform/scripts/test-script-child.json b/clutter/tests/conform/scripts/test-script-child.json new file mode 100644 index 0000000..5e8ac52 --- /dev/null +++ b/clutter/tests/conform/scripts/test-script-child.json @@ -0,0 +1,21 @@ +{ + "type" : "TestGroup", + "id" : "test-group", + "children" : [ + { + "type" : "ClutterRectangle", + "id" : "test-rect-1", + "width" : 100.0, + "height" : 100.0, + "color" : [ 255, 0, 0, 255 ], + "child::focus" : true + }, + { + "type" : "ClutterRectangle", + "id" : "test-rect-2", + "width" : 100.0, + "height" : 100.0, + "color" : [ 0, 255, 0, 255 ] + } + ] +} diff --git a/clutter/tests/conform/scripts/test-script-implicit-alpha.json b/clutter/tests/conform/scripts/test-script-implicit-alpha.json new file mode 100644 index 0000000..5aab70d --- /dev/null +++ b/clutter/tests/conform/scripts/test-script-implicit-alpha.json @@ -0,0 +1,8 @@ +{ + "id" : "test", + "type" : "ClutterBehaviourOpacity", + "alpha" : { + "mode" : "easeOutCirc", + "timeline" : { "duration" : 500 } + } +} diff --git a/clutter/tests/conform/scripts/test-script-interval.json b/clutter/tests/conform/scripts/test-script-interval.json new file mode 100644 index 0000000..35fe5c2 --- /dev/null +++ b/clutter/tests/conform/scripts/test-script-interval.json @@ -0,0 +1,16 @@ +[ + { + "id" : "int-1", + "type" : "ClutterInterval", + "value-type" : "gfloat", + "initial" : 23.3, + "final" : 42.2 + }, + { + "id" : "int-2", + "type" : "ClutterInterval", + "value-type" : "ClutterColor", + "initial" : "red", + "final" : "blue" + } +] diff --git a/clutter/tests/conform/scripts/test-script-layout-property.json b/clutter/tests/conform/scripts/test-script-layout-property.json new file mode 100644 index 0000000..17e9f48 --- /dev/null +++ b/clutter/tests/conform/scripts/test-script-layout-property.json @@ -0,0 +1,21 @@ +[ + { "id" : "manager", "type" : "ClutterBoxLayout" }, + + { + "id" : "container", "type" : "ClutterBox", + "layout-manager" : "manager", + "children" : [ + { + "id" : "actor-1", "type" : "ClutterRectangle", + "layout::x-fill" : true, + "layout::y-align" : "center", + "layout::expand" : true + }, { + "id" : "actor-2", "type" : "ClutterRectangle", + "layout::x-fill" : false, + "layout::y-align" : "end", + "layout::expand" : false + } + ] + } +] diff --git a/clutter/tests/conform/scripts/test-script-margin.json b/clutter/tests/conform/scripts/test-script-margin.json new file mode 100644 index 0000000..1f5289f --- /dev/null +++ b/clutter/tests/conform/scripts/test-script-margin.json @@ -0,0 +1,22 @@ +[ + { + "id" : "actor-1", + "type" : "ClutterActor", + "margin" : [ 10 ] + }, + { + "id" : "actor-2", + "type" : "ClutterActor", + "margin" : [ 10, 20 ] + }, + { + "id" : "actor-3", + "type" : "ClutterActor", + "margin" : [ 10, 20, 30 ] + }, + { + "id" : "actor-4", + "type" : "ClutterActor", + "margin" : [ 10, 20, 30, 40] + } +] diff --git a/clutter/tests/conform/scripts/test-script-model.json b/clutter/tests/conform/scripts/test-script-model.json new file mode 100644 index 0000000..9bd6aef --- /dev/null +++ b/clutter/tests/conform/scripts/test-script-model.json @@ -0,0 +1,17 @@ +{ + "id" : "test-model", + "type" : "ClutterListModel", + "columns" : [ + [ "text-column", "gchararray" ], + [ "int-column", "gint" ], + [ "actor-column", "ClutterRectangle" ] + ], + "rows" : [ + [ "text-row-1", 1, null ], + [ "text-row-2", 2, { "type" : "ClutterRectangle", "color" : "blue" } ], + { + "int-column" : 3, + "actor-column" : { "type" : "ClutterRectangle", "name" : "actor-row-3" } + } + ] +} diff --git a/clutter/tests/conform/scripts/test-script-named-object.json b/clutter/tests/conform/scripts/test-script-named-object.json new file mode 100644 index 0000000..6611b62 --- /dev/null +++ b/clutter/tests/conform/scripts/test-script-named-object.json @@ -0,0 +1,44 @@ +[ + { + "id" : "layout", + "type" : "ClutterBoxLayout", + "orientation" : "vertical", + "spacing" : 12, + "pack-start" : false + }, + { + "type" : "ClutterStage", + "id" : "main-stage", + "children" : [ + { + "id" : "test", + "type" : "ClutterBox", + "layout-manager" : "layout", + "children" : [ + { + "id" : "child-1", + "type" : "ClutterRectangle", + "width" : "3 em", + "height" : "3 em" + } + ], + "constraints" : [ + { + "type" : "ClutterAlignConstraint", + "name" : "x-align", + "factor" : 0.5, + "align-axis" : "x-axis", + "source" : "main-stage" + }, + { + "type" : "ClutterAlignConstraint", + "name" : "y-align", + "factor" : 0.5, + "align-axis" : "y-axis", + "source" : "main-stage" + } + ] + } + ] + } +] diff --git a/clutter/tests/conform/scripts/test-script-object-property.json b/clutter/tests/conform/scripts/test-script-object-property.json new file mode 100644 index 0000000..18a02fb --- /dev/null +++ b/clutter/tests/conform/scripts/test-script-object-property.json @@ -0,0 +1,13 @@ +{ + "id" : "test", + "type" : "ClutterBox", + "layout-manager" : { "id" : "layout", "type" : "ClutterBinLayout" }, + "children" : [ + { + "id" : "child-1", + "type" : "ClutterRectangle", + "width" : "3 em", + "height" : "3 em" + } + ] +} diff --git a/clutter/tests/conform/scripts/test-script-single.json b/clutter/tests/conform/scripts/test-script-single.json new file mode 100644 index 0000000..e20a318 --- /dev/null +++ b/clutter/tests/conform/scripts/test-script-single.json @@ -0,0 +1,10 @@ +{ + "type" : "ClutterRectangle", + "id" : "test", + "width" : 50.0, + "height" : 100.0, + "x" : 100.0, + "y" : 100.0, + "color" : "#ffccdd", + "name" : "Test Rectangle" +} diff --git a/clutter/tests/conform/scripts/test-script-timeline-markers.json b/clutter/tests/conform/scripts/test-script-timeline-markers.json new file mode 100644 index 0000000..f5fff5c --- /dev/null +++ b/clutter/tests/conform/scripts/test-script-timeline-markers.json @@ -0,0 +1,12 @@ +{ + "id" : "timeline0", + "type" : "ClutterTimeline", + "duration" : 1000, + + "markers" : [ + { "name" : "marker0", "time" : 250 }, + { "name" : "marker1", "time" : 500 }, + { "name" : "marker2", "time" : 750 }, + { "name" : "marker3", "progress" : 0.5 } + ] +} diff --git a/clutter/tests/conform/scripts/test-state-1.json b/clutter/tests/conform/scripts/test-state-1.json new file mode 100644 index 0000000..78ab5de --- /dev/null +++ b/clutter/tests/conform/scripts/test-state-1.json @@ -0,0 +1,33 @@ +[ + { + "type" : "ClutterRectangle", + "id" : "rect", + "width" : 100, + "height" : 100 + }, + { + "type" : "ClutterState", + "id" : "state", + + "transitions" : [ + { + "source" : "base", + "target" : "clicked", + "duration" : 250, + + "keys" : [ + [ "rect", "opacity", "linear", 128 ] + ] + }, + { + "source" : "clicked", + "target" : "base", + "duration" : 150, + + "keys" : [ + [ "rect", "opacity", "linear", 255 ] + ] + } + ] + } +] diff --git a/clutter/tests/conform/text.c b/clutter/tests/conform/text.c new file mode 100644 index 0000000..30101ce --- /dev/null +++ b/clutter/tests/conform/text.c @@ -0,0 +1,550 @@ +#include +#include +#include + +typedef struct { + gunichar unichar; + const char bytes[6]; + gint nbytes; +} TestData; + +static const TestData +test_text_data[] = { + { 0xe4, "\xc3\xa4", 2 }, /* LATIN SMALL LETTER A WITH DIAERESIS */ + { 0x2665, "\xe2\x99\xa5", 3 } /* BLACK HEART SUIT */ +}; + +static void +text_utf8_validation (void) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS (test_text_data); i++) + { + const TestData *t = &test_text_data[i]; + gunichar unichar; + char bytes[6]; + int nbytes; + + g_assert (g_unichar_validate (t->unichar)); + + nbytes = g_unichar_to_utf8 (t->unichar, bytes); + bytes[nbytes] = '\0'; + g_assert_cmpint (nbytes, ==, t->nbytes); + g_assert (memcmp (t->bytes, bytes, nbytes) == 0); + + unichar = g_utf8_get_char_validated (bytes, nbytes); + g_assert_cmpint (unichar, ==, t->unichar); + } +} + +static int +get_nbytes (ClutterText *text) +{ + const char *s = clutter_text_get_text (text); + return strlen (s); +} + +static int +get_nchars (ClutterText *text) +{ + const char *s = clutter_text_get_text (text); + g_assert (g_utf8_validate (s, -1, NULL)); + return g_utf8_strlen (s, -1); +} + +#define DONT_MOVE_CURSOR (-2) + +static void +insert_unichar (ClutterText *text, gunichar unichar, int position) +{ + if (position > DONT_MOVE_CURSOR) + { + clutter_text_set_cursor_position (text, position); + g_assert_cmpint (clutter_text_get_cursor_position (text), ==, position); + } + + clutter_text_insert_unichar (text, unichar); +} + +static void +text_set_empty (void) +{ + ClutterText *text = CLUTTER_TEXT (clutter_text_new ()); + g_object_ref_sink (text); + + g_assert_cmpstr (clutter_text_get_text (text), ==, ""); + g_assert_cmpint (*clutter_text_get_text (text), ==, '\0'); + g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1); + + clutter_text_set_text (text, ""); + g_assert_cmpint (get_nchars (text), ==, 0); + g_assert_cmpint (get_nbytes (text), ==, 0); + g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1); + + clutter_actor_destroy (CLUTTER_ACTOR (text)); +} + +static void +text_set_text (void) +{ + ClutterText *text = CLUTTER_TEXT (clutter_text_new ()); + g_object_ref_sink (text); + + clutter_text_set_text (text, "abcdef"); + g_assert_cmpint (get_nchars (text), ==, 6); + g_assert_cmpint (get_nbytes (text), ==, 6); + g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1); + + clutter_text_set_cursor_position (text, 5); + g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 5); + + /* FIXME: cursor position should be -1? + clutter_text_set_text (text, ""); + g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1); + */ + + clutter_actor_destroy (CLUTTER_ACTOR (text)); +} + +static void +text_append_some (void) +{ + ClutterText *text = CLUTTER_TEXT (clutter_text_new ()); + int i; + + g_object_ref_sink (text); + + for (i = 0; i < G_N_ELEMENTS (test_text_data); i++) + { + const TestData *t = &test_text_data[i]; + int j; + + for (j = 1; j <= 4; j++) + { + insert_unichar (text, t->unichar, DONT_MOVE_CURSOR); + + g_assert_cmpint (get_nchars (text), ==, j); + g_assert_cmpint (get_nbytes (text), ==, j * t->nbytes); + g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1); + } + + clutter_text_set_text (text, ""); + } + + clutter_actor_destroy (CLUTTER_ACTOR (text)); +} + +static void +text_prepend_some (void) +{ + ClutterText *text = CLUTTER_TEXT (clutter_text_new ()); + int i; + + g_object_ref_sink (text); + + for (i = 0; i < G_N_ELEMENTS (test_text_data); i++) + { + const TestData *t = &test_text_data[i]; + int j; + + clutter_text_insert_unichar (text, t->unichar); + + g_assert_cmpint (get_nchars (text), ==, 1); + g_assert_cmpint (get_nbytes (text), ==, 1 * t->nbytes); + g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1); + + for (j = 2; j <= 4; j++) + { + insert_unichar (text, t->unichar, 0); + + g_assert_cmpint (get_nchars (text), ==, j); + g_assert_cmpint (get_nbytes (text), ==, j * t->nbytes); + g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 1); + } + + clutter_text_set_text (text, ""); + } + + clutter_actor_destroy (CLUTTER_ACTOR (text)); +} + +static void +text_insert (void) +{ + ClutterText *text = CLUTTER_TEXT (clutter_text_new ()); + int i; + + g_object_ref_sink (text); + + for (i = 0; i < G_N_ELEMENTS (test_text_data); i++) + { + const TestData *t = &test_text_data[i]; + + clutter_text_insert_unichar (text, t->unichar); + clutter_text_insert_unichar (text, t->unichar); + + insert_unichar (text, t->unichar, 1); + + g_assert_cmpint (get_nchars (text), ==, 3); + g_assert_cmpint (get_nbytes (text), ==, 3 * t->nbytes); + g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 2); + + clutter_text_set_text (text, ""); + } + + clutter_actor_destroy (CLUTTER_ACTOR (text)); +} + +static void +text_delete_chars (void) +{ + ClutterText *text = CLUTTER_TEXT (clutter_text_new ()); + int i; + + g_object_ref_sink (text); + + for (i = 0; i < G_N_ELEMENTS (test_text_data); i++) + { + const TestData *t = &test_text_data[i]; + int j; + + for (j = 0; j < 4; j++) + clutter_text_insert_unichar (text, t->unichar); + + if (g_test_verbose ()) + g_print ("text: %s\n", clutter_text_get_text (text)); + + clutter_text_set_cursor_position (text, 2); + clutter_text_delete_chars (text, 1); + if (g_test_verbose ()) + g_print ("text: %s (cursor at: %d)\n", + clutter_text_get_text (text), + clutter_text_get_cursor_position (text)); + g_assert_cmpint (get_nchars (text), ==, 3); + g_assert_cmpint (get_nbytes (text), ==, 3 * t->nbytes); + g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 1); + + clutter_text_set_cursor_position (text, 2); + clutter_text_delete_chars (text, 1); + if (g_test_verbose ()) + g_print ("text: %s (cursor at: %d)\n", + clutter_text_get_text (text), + clutter_text_get_cursor_position (text)); + g_assert_cmpint (get_nchars (text), ==, 2); + g_assert_cmpint (get_nbytes (text), ==, 2 * t->nbytes); + g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 1); + + clutter_text_set_text (text, ""); + } + + clutter_actor_destroy (CLUTTER_ACTOR (text)); +} + +static void +text_get_chars (void) +{ + ClutterText *text = CLUTTER_TEXT (clutter_text_new ()); + gchar *chars; + + g_object_ref_sink (text); + + clutter_text_set_text (text, "00abcdef11"); + g_assert_cmpint (get_nchars (text), ==, 10); + g_assert_cmpint (get_nbytes (text), ==, 10); + g_assert_cmpstr (clutter_text_get_text (text), ==, "00abcdef11"); + + chars = clutter_text_get_chars (text, 2, -1); + g_assert_cmpstr (chars, ==, "abcdef11"); + g_free (chars); + + chars = clutter_text_get_chars (text, 0, 8); + g_assert_cmpstr (chars, ==, "00abcdef"); + g_free (chars); + + chars = clutter_text_get_chars (text, 2, 8); + g_assert_cmpstr (chars, ==, "abcdef"); + g_free (chars); + + chars = clutter_text_get_chars (text, 8, 12); + g_assert_cmpstr (chars, ==, "11"); + g_free (chars); + + clutter_actor_destroy (CLUTTER_ACTOR (text)); +} + +static void +text_delete_text (void) +{ + ClutterText *text = CLUTTER_TEXT (clutter_text_new ()); + int i; + + g_object_ref_sink (text); + + for (i = 0; i < G_N_ELEMENTS (test_text_data); i++) + { + const TestData *t = &test_text_data[i]; + int j; + + for (j = 0; j < 4; j++) + clutter_text_insert_unichar (text, t->unichar); + + clutter_text_set_cursor_position (text, 3); + clutter_text_delete_text (text, 2, 4); + + g_assert_cmpint (get_nchars (text), ==, 2); + g_assert_cmpint (get_nbytes (text), ==, 2 * t->nbytes); + + /* FIXME: cursor position should be -1? + g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1); + */ + + clutter_text_set_text (text, ""); + } + + clutter_actor_destroy (CLUTTER_ACTOR (text)); +} + +static void +text_password_char (void) +{ + ClutterText *text = CLUTTER_TEXT (clutter_text_new ()); + + g_object_ref_sink (text); + + g_assert_cmpint (clutter_text_get_password_char (text), ==, 0); + + clutter_text_set_text (text, "hello"); + g_assert_cmpstr (clutter_text_get_text (text), ==, "hello"); + + clutter_text_set_password_char (text, '*'); + g_assert_cmpint (clutter_text_get_password_char (text), ==, '*'); + + g_assert_cmpstr (clutter_text_get_text (text), ==, "hello"); + + clutter_actor_destroy (CLUTTER_ACTOR (text)); +} + +static ClutterEvent * +init_event (void) +{ + ClutterEvent *retval = clutter_event_new (CLUTTER_KEY_PRESS); + + clutter_event_set_time (retval, CLUTTER_CURRENT_TIME); + clutter_event_set_flags (retval, CLUTTER_EVENT_FLAG_SYNTHETIC); + + return retval; +} + +static void +send_keyval (ClutterText *text, int keyval) +{ + ClutterEvent *event = init_event (); + + /* Unicode should be ignored for cursor keys etc. */ + clutter_event_set_key_unicode (event, 0); + clutter_event_set_key_symbol (event, keyval); + + clutter_actor_event (CLUTTER_ACTOR (text), event, FALSE); + + clutter_event_free (event); +} + +static void +send_unichar (ClutterText *text, gunichar unichar) +{ + ClutterEvent *event = init_event (); + + /* Key symbol should be ignored for printable characters */ + clutter_event_set_key_symbol (event, 0); + clutter_event_set_key_unicode (event, unichar); + + clutter_actor_event (CLUTTER_ACTOR (text), event, FALSE); + + clutter_event_free (event); +} + +static void +text_cursor (void) +{ + ClutterText *text = CLUTTER_TEXT (clutter_text_new ()); + int i; + + g_object_ref_sink (text); + + /* only editable entries listen to events */ + clutter_text_set_editable (text, TRUE); + + for (i = 0; i < G_N_ELEMENTS (test_text_data); i++) + { + const TestData *t = &test_text_data[i]; + int j; + + for (j = 0; j < 4; ++j) + clutter_text_insert_unichar (text, t->unichar); + + clutter_text_set_cursor_position (text, 2); + + /* test cursor moves and is clamped */ + send_keyval (text, CLUTTER_KEY_Left); + g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 1); + + send_keyval (text, CLUTTER_KEY_Left); + g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 0); + + send_keyval (text, CLUTTER_KEY_Left); + g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 0); + + /* delete text containing the cursor */ + clutter_text_set_cursor_position (text, 3); + g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 3); + + clutter_text_delete_text (text, 2, 4); + send_keyval (text, CLUTTER_KEY_Left); + + /* FIXME: cursor position should be -1? + g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1); + */ + + clutter_text_set_text (text, ""); + } + + clutter_actor_destroy (CLUTTER_ACTOR (text)); +} + +static void +text_event (void) +{ + ClutterText *text = CLUTTER_TEXT (clutter_text_new ()); + int i; + + g_object_ref_sink (text); + + /* only editable entries listen to events */ + clutter_text_set_editable (text, TRUE); + + for (i = 0; i < G_N_ELEMENTS (test_text_data); i++) + { + const TestData *t = &test_text_data[i]; + + send_unichar (text, t->unichar); + + g_assert_cmpint (get_nchars (text), ==, 1); + g_assert_cmpint (get_nbytes (text), ==, 1 * t->nbytes); + g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1); + + clutter_text_set_text (text, ""); + } + + clutter_actor_destroy (CLUTTER_ACTOR (text)); +} + +static inline void +validate_markup_attributes (ClutterText *text, + PangoAttrType attr_type, + int start_index, + int end_index) +{ + PangoLayout *layout; + PangoAttrList *attrs; + PangoAttrIterator *iter; + + layout = clutter_text_get_layout (text); + g_assert (layout != NULL); + + attrs = pango_layout_get_attributes (layout); + g_assert (attrs != NULL); + + iter = pango_attr_list_get_iterator (attrs); + while (pango_attr_iterator_next (iter)) + { + GSList *attributes = pango_attr_iterator_get_attrs (iter); + PangoAttribute *a; + + if (attributes == NULL) + break; + + g_assert (attributes->data != NULL); + + a = attributes->data; + + g_assert (a->klass->type == attr_type); + g_assert_cmpint (a->start_index, ==, start_index); + g_assert_cmpint (a->end_index, ==, end_index); + + g_slist_free_full (attributes, (GDestroyNotify) pango_attribute_destroy); + } + + pango_attr_iterator_destroy (iter); +} + +static void +text_idempotent_use_markup (void) +{ + ClutterText *text; + const char *contents = "foo bar"; + const char *display = "foo bar"; + int bar_start_index = strstr (display, "bar") - display; + int bar_end_index = bar_start_index + strlen ("bar"); + + /* case 1: text -> use_markup */ + if (g_test_verbose ()) + g_print ("text: '%s' -> use-markup: TRUE\n", contents); + + text = g_object_new (CLUTTER_TYPE_TEXT, + "text", contents, "use-markup", TRUE, + NULL); + g_object_ref_sink (text); + + if (g_test_verbose ()) + g_print ("Contents: '%s' (expected: '%s')\n", + clutter_text_get_text (text), + display); + + g_assert_cmpstr (clutter_text_get_text (text), ==, display); + + validate_markup_attributes (text, + PANGO_ATTR_WEIGHT, + bar_start_index, + bar_end_index); + + clutter_actor_destroy (CLUTTER_ACTOR (text)); + + /* case 2: use_markup -> text */ + if (g_test_verbose ()) + g_print ("use-markup: TRUE -> text: '%s'\n", contents); + + text = g_object_new (CLUTTER_TYPE_TEXT, + "use-markup", TRUE, "text", contents, + NULL); + + if (g_test_verbose ()) + g_print ("Contents: '%s' (expected: '%s')\n", + clutter_text_get_text (text), + display); + + g_assert_cmpstr (clutter_text_get_text (text), ==, display); + + validate_markup_attributes (text, + PANGO_ATTR_WEIGHT, + bar_start_index, + bar_end_index); + + clutter_actor_destroy (CLUTTER_ACTOR (text)); +} + +CLUTTER_TEST_SUITE ( + CLUTTER_TEST_UNIT ("/text/utf8-validation", text_utf8_validation) + CLUTTER_TEST_UNIT ("/text/set-empty", text_set_empty) + CLUTTER_TEST_UNIT ("/text/set-text", text_set_text) + CLUTTER_TEST_UNIT ("/text/append-some", text_append_some) + CLUTTER_TEST_UNIT ("/text/prepend-some", text_prepend_some) + CLUTTER_TEST_UNIT ("/text/insert", text_insert) + CLUTTER_TEST_UNIT ("/text/delete-chars", text_delete_chars) + CLUTTER_TEST_UNIT ("/text/get-chars", text_get_chars) + CLUTTER_TEST_UNIT ("/text/delete-text", text_delete_text) + CLUTTER_TEST_UNIT ("/text/password-char", text_password_char) + CLUTTER_TEST_UNIT ("/text/cursor", text_cursor) + CLUTTER_TEST_UNIT ("/text/event", text_event) + CLUTTER_TEST_UNIT ("/text/idempotent-use-markup", text_idempotent_use_markup) +) diff --git a/clutter/tests/conform/texture.c b/clutter/tests/conform/texture.c new file mode 100644 index 0000000..392fd5c --- /dev/null +++ b/clutter/tests/conform/texture.c @@ -0,0 +1,84 @@ +#define CLUTTER_DISABLE_DEPRECATION_WARNINGS +#include +#include + +static CoglHandle +make_texture (void) +{ + guint32 *data = g_malloc (100 * 100 * 4); + int x; + int y; + + for (y = 0; y < 100; y ++) + for (x = 0; x < 100; x++) + { + if (x < 50 && y < 50) + data[y * 100 + x] = 0xff00ff00; + else + data[y * 100 + x] = 0xff00ffff; + } + return cogl_texture_new_from_data (100, + 100, + COGL_TEXTURE_NONE, + COGL_PIXEL_FORMAT_ARGB_8888, + COGL_PIXEL_FORMAT_ARGB_8888, + 400, + (guchar *)data); +} + +static void +texture_pick_with_alpha (void) +{ + ClutterTexture *tex = CLUTTER_TEXTURE (clutter_texture_new ()); + ClutterStage *stage = CLUTTER_STAGE (clutter_test_get_stage ()); + ClutterActor *actor; + + clutter_texture_set_cogl_texture (tex, make_texture ()); + + clutter_actor_add_child (CLUTTER_ACTOR (stage), CLUTTER_ACTOR (tex)); + + clutter_actor_show (CLUTTER_ACTOR (stage)); + + if (g_test_verbose ()) + { + g_print ("\nstage = %p\n", stage); + g_print ("texture = %p\n\n", tex); + } + + clutter_texture_set_pick_with_alpha (tex, TRUE); + if (g_test_verbose ()) + g_print ("Testing with pick-with-alpha enabled:\n"); + + /* This should fall through and hit the stage: */ + actor = clutter_stage_get_actor_at_pos (stage, CLUTTER_PICK_ALL, 10, 10); + if (g_test_verbose ()) + g_print ("actor @ (10, 10) = %p\n", actor); + g_assert (actor == CLUTTER_ACTOR (stage)); + + /* The rest should hit the texture */ + actor = clutter_stage_get_actor_at_pos (stage, CLUTTER_PICK_ALL, 90, 10); + if (g_test_verbose ()) + g_print ("actor @ (90, 10) = %p\n", actor); + g_assert (actor == CLUTTER_ACTOR (tex)); + actor = clutter_stage_get_actor_at_pos (stage, CLUTTER_PICK_ALL, 90, 90); + if (g_test_verbose ()) + g_print ("actor @ (90, 90) = %p\n", actor); + g_assert (actor == CLUTTER_ACTOR (tex)); + actor = clutter_stage_get_actor_at_pos (stage, CLUTTER_PICK_ALL, 10, 90); + if (g_test_verbose ()) + g_print ("actor @ (10, 90) = %p\n", actor); + g_assert (actor == CLUTTER_ACTOR (tex)); + + clutter_texture_set_pick_with_alpha (tex, FALSE); + if (g_test_verbose ()) + g_print ("Testing with pick-with-alpha disabled:\n"); + + actor = clutter_stage_get_actor_at_pos (stage, CLUTTER_PICK_ALL, 10, 10); + if (g_test_verbose ()) + g_print ("actor @ (10, 10) = %p\n", actor); + g_assert (actor == CLUTTER_ACTOR (tex)); +} + +CLUTTER_TEST_SUITE ( + CLUTTER_TEST_UNIT ("/texture/pick-with-alpha", texture_pick_with_alpha) +) diff --git a/clutter/tests/conform/units.c b/clutter/tests/conform/units.c new file mode 100644 index 0000000..06bfaf5 --- /dev/null +++ b/clutter/tests/conform/units.c @@ -0,0 +1,131 @@ +#include + +static void +units_cache (void) +{ + ClutterUnits units; + ClutterSettings *settings; + gfloat pixels; + gint old_dpi; + + settings = clutter_settings_get_default (); + g_object_get (settings, "font-dpi", &old_dpi, NULL); + + g_object_set (settings, "font-dpi", 96 * 1024, NULL); + clutter_units_from_em (&units, 1.0); + pixels = clutter_units_to_pixels (&units); + + g_object_set (settings, "font-dpi", ((96 * 2) * 1024), NULL); + g_assert_cmpfloat (clutter_units_to_pixels (&units), !=, pixels); + + g_object_set (settings, "font-dpi", (96 * 1024), NULL); + g_assert_cmpfloat (clutter_units_to_pixels (&units), ==, pixels); + + g_object_set (settings, "font-dpi", old_dpi, NULL); +} + +static void +units_constructors (void) +{ + ClutterUnits units, units_cm; + + clutter_units_from_pixels (&units, 100); + g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_PIXEL); + g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 100.0); + g_assert_cmpfloat (clutter_units_to_pixels (&units), ==, 100.0); + + clutter_units_from_em (&units, 5.0); + g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_EM); + g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 5.0); + g_assert_cmpfloat (clutter_units_to_pixels (&units), !=, 5.0); + + clutter_units_from_cm (&units_cm, 5.0); + g_assert (clutter_units_get_unit_type (&units_cm) == CLUTTER_UNIT_CM); + g_assert_cmpfloat (clutter_units_get_unit_value (&units_cm), ==, 5.0); + g_assert_cmpfloat (clutter_units_to_pixels (&units_cm), !=, 5.0); + + clutter_units_from_mm (&units, 50.0); + g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_MM); + g_assert_cmpfloat (clutter_units_to_pixels (&units), + ==, + clutter_units_to_pixels (&units_cm)); +} + +static void +units_string (void) +{ + ClutterUnits units; + gchar *string; + + g_assert (clutter_units_from_string (&units, "") == FALSE); + + g_assert (clutter_units_from_string (&units, "10") == TRUE); + g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_PIXEL); + g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 10); + + g_assert (clutter_units_from_string (&units, "10 px") == TRUE); + g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_PIXEL); + + g_assert (clutter_units_from_string (&units, "10 mm") == TRUE); + g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_MM); + + g_assert (clutter_units_from_string (&units, "10 cm") == TRUE); + g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_CM); + + g_assert (clutter_units_from_string (&units, "10 ") == TRUE); + g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_PIXEL); + g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 10); + + g_assert (clutter_units_from_string (&units, "5 em") == TRUE); + g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_EM); + g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 5); + + g_assert (clutter_units_from_string (&units, "5 emeralds") == FALSE); + + g_assert (clutter_units_from_string (&units, " 16 mm") == TRUE); + g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_MM); + g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 16); + + g_assert (clutter_units_from_string (&units, " 24 pt ") == TRUE); + g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_POINT); + g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 24); + + g_assert (clutter_units_from_string (&units, " 32 em garbage") == FALSE); + + g_assert (clutter_units_from_string (&units, "5.1cm") == TRUE); + g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_CM); + g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 5.1f); + + g_assert (clutter_units_from_string (&units, "5,mm") == FALSE); + + g_assert (clutter_units_from_string (&units, ".5pt") == TRUE); + g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_POINT); + g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 0.5f); + + g_assert (clutter_units_from_string (&units, "1 omg!!pony") == FALSE); + + clutter_units_from_pt (&units, 24.0); + string = clutter_units_to_string (&units); + g_assert_cmpstr (string, ==, "24.0 pt"); + g_free (string); + + clutter_units_from_em (&units, 3.0); + string = clutter_units_to_string (&units); + g_assert_cmpstr (string, ==, "3.00 em"); + + units.unit_type = CLUTTER_UNIT_PIXEL; + units.value = 0; + + g_assert (clutter_units_from_string (&units, string) == TRUE); + g_assert (clutter_units_get_unit_type (&units) != CLUTTER_UNIT_PIXEL); + g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_EM); + g_assert_cmpint ((int) clutter_units_get_unit_value (&units), ==, 3); + + g_free (string); +} + +CLUTTER_TEST_SUITE ( + CLUTTER_TEST_UNIT ("/units/string", units_string) + CLUTTER_TEST_UNIT ("/units/cache", units_cache) + CLUTTER_TEST_UNIT ("/units/constructors", units_constructors) +) diff --git a/clutter/tests/interactive/Makefile.am b/clutter/tests/interactive/Makefile.am new file mode 100644 index 0000000..24a7f48 --- /dev/null +++ b/clutter/tests/interactive/Makefile.am @@ -0,0 +1,147 @@ +UNIT_TESTS = \ + test-texture-slicing.c \ + test-texture-async.c \ + test-texture-material.c \ + test-events.c \ + test-scale.c \ + test-actors.c \ + test-shader-effects.c \ + test-script.c \ + test-grab.c \ + test-cogl-shader-arbfp.c \ + test-cogl-shader-glsl.c \ + test-animator.c \ + test-state.c \ + test-state-animator.c \ + test-fbo.c \ + test-multistage.c \ + test-cogl-tex-tile.c \ + test-cogl-tex-convert.c \ + test-cogl-tex-foreign.c \ + test-cogl-offscreen.c \ + test-cogl-tex-polygon.c \ + test-cogl-multitexture.c \ + test-stage-read-pixels.c \ + test-paint-wrapper.c \ + test-texture-quality.c \ + test-layout.c \ + test-animation.c \ + test-easing.c \ + test-binding-pool.c \ + test-text.c \ + test-text-field.c \ + test-cairo-clock.c \ + test-cairo-flowers.c \ + test-cogl-vertex-buffer.c \ + test-stage-sizing.c \ + test-scrolling.c \ + test-swipe-action.c \ + test-cogl-point-sprites.c \ + test-table-layout.c \ + test-path-constraint.c \ + test-state-script.c \ + test-devices.c \ + test-content.c \ + test-keyframe-transition.c \ + test-bind-constraint.c \ + test-touch-events.c \ + test-rotate-zoom.c + +if X11_TESTS +UNIT_TESTS += test-pixmap.c +endif + +if PIXBUF_TESTS +UNIT_TESTS += \ + test-image.c +endif + +SHEXT = $(EXEEXT) + +# For convenience, this provides a way to easily run individual unit tests: +wrappers: stamp-test-interactive + @true + +GIT_IGNORE_EXTRA = \ + stamp-test-interactive \ + stamp-test-unit-names \ + test-unit-names.h \ + $(UNIT_TESTS:.c=$(SHEXT)) + +stamp-test-interactive: Makefile + @wrapper=$(abs_builddir)/wrapper.sh ; \ + chmod +x $$wrapper && \ + for i in $(UNIT_TESTS); \ + do \ + test_bin=$${i%*.c} ; \ + echo " GEN $$test_bin" ; \ + ( echo "#!/bin/sh" ; \ + echo "$$wrapper $$test_bin \$$@" \ + ) > $$test_bin$(SHEXT) ; \ + chmod +x $$test_bin$(SHEXT) ; \ + done \ + && echo timestamp > $(@F) + +test-unit-names.h: stamp-test-unit-names + @true + +stamp-test-unit-names: Makefile + @( echo "/* ** This file is autogenerated. Do not edit. ** */" ; \ + echo "" ; \ + echo "const char *test_unit_names[] = {" ) > test-unit-names.h ; \ + for i in $(UNIT_TESTS); \ + do \ + test_bin=$${i%*.c} ; \ + echo " \"$$test_bin\"," >> test-unit-names.h ; \ + done \ + && echo "};" >> test-unit-names.h \ + && echo timestamp > $(@F) + +clean-wrappers: + @for i in $(UNIT_TESTS); \ + do \ + test_bin=$${i%*.c} ; \ + echo " RM $$test_bin"; \ + rm -f $$test_bin$(SHEXT); \ + done \ + && rm -f stamp-test-unit-names \ + && rm -f stamp-test-interactive + +.PHONY: wrappers clean-wrappers + +common_ldadd = \ + $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la + +check_PROGRAMS = test-interactive +check_SCRIPTS = wrappers + +test_interactive_SOURCES = test-main.c $(UNIT_TESTS) +nodist_test_interactive_SOURCES = test-unit-names.h +test_interactive_CFLAGS = $(CLUTTER_CFLAGS) $(GDK_PIXBUF_CFLAGS) +test_interactive_CPPFLAGS = \ + -DTESTS_DATADIR=\""$(abs_srcdir)"\" \ + -DG_DISABLE_SINGLE_INCLUDES \ + -DGLIB_DISABLE_DEPRECATION_WARNINGS \ + -DCOGL_DISABLE_DEPRECATION_WARNINGS \ + -DCLUTTER_DISABLE_DEPRECATION_WARNINGS \ + -I$(top_srcdir)/../cogl \ + -I$(top_builddir)/../cogl \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + -I$(top_srcdir)/clutter \ + -I$(top_builddir)/clutter +test_interactive_LDFLAGS = -export-dynamic +test_interactive_LDADD = $(CLUTTER_LIBS) $(GDK_PIXBUF_LIBS) $(common_ldadd) $(LIBM) + +EXTRA_DIST = \ + wrapper.sh.in \ + test-script.json \ + test-script-signals.json \ + redhand.png + +DISTCLEANFILES = wrapper.sh .gitignore test-unit-names.h + +BUILT_SOURCES = test-unit-names.h + +clean-local: clean-wrappers diff --git a/clutter/tests/interactive/Makefile.in b/clutter/tests/interactive/Makefile.in new file mode 100644 index 0000000..fa5db43 --- /dev/null +++ b/clutter/tests/interactive/Makefile.in @@ -0,0 +1,1602 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@X11_TESTS_TRUE@am__append_1 = test-pixmap.c +@PIXBUF_TESTS_TRUE@am__append_2 = \ +@PIXBUF_TESTS_TRUE@ test-image.c + +check_PROGRAMS = test-interactive$(EXEEXT) +subdir = tests/interactive +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/build/autotools/as-compiler-flag.m4 \ + $(top_srcdir)/build/autotools/glibtests.m4 \ + $(top_srcdir)/build/autotools/introspection.m4 \ + $(top_srcdir)/build/autotools/libtool.m4 \ + $(top_srcdir)/build/autotools/ltoptions.m4 \ + $(top_srcdir)/build/autotools/ltsugar.m4 \ + $(top_srcdir)/build/autotools/ltversion.m4 \ + $(top_srcdir)/build/autotools/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/clutter/clutter-build-config.h +CONFIG_CLEAN_FILES = wrapper.sh +CONFIG_CLEAN_VPATH_FILES = +am__test_interactive_SOURCES_DIST = test-main.c test-texture-slicing.c \ + test-texture-async.c test-texture-material.c test-events.c \ + test-scale.c test-actors.c test-shader-effects.c test-script.c \ + test-grab.c test-cogl-shader-arbfp.c test-cogl-shader-glsl.c \ + test-animator.c test-state.c test-state-animator.c test-fbo.c \ + test-multistage.c test-cogl-tex-tile.c test-cogl-tex-convert.c \ + test-cogl-tex-foreign.c test-cogl-offscreen.c \ + test-cogl-tex-polygon.c test-cogl-multitexture.c \ + test-stage-read-pixels.c test-paint-wrapper.c \ + test-texture-quality.c test-layout.c test-animation.c \ + test-easing.c test-binding-pool.c test-text.c \ + test-text-field.c test-cairo-clock.c test-cairo-flowers.c \ + test-cogl-vertex-buffer.c test-stage-sizing.c test-scrolling.c \ + test-swipe-action.c test-cogl-point-sprites.c \ + test-table-layout.c test-path-constraint.c test-state-script.c \ + test-devices.c test-content.c test-keyframe-transition.c \ + test-bind-constraint.c test-touch-events.c test-rotate-zoom.c \ + test-pixmap.c test-image.c +@X11_TESTS_TRUE@am__objects_1 = \ +@X11_TESTS_TRUE@ test_interactive-test-pixmap.$(OBJEXT) +@PIXBUF_TESTS_TRUE@am__objects_2 = \ +@PIXBUF_TESTS_TRUE@ test_interactive-test-image.$(OBJEXT) +am__objects_3 = test_interactive-test-texture-slicing.$(OBJEXT) \ + test_interactive-test-texture-async.$(OBJEXT) \ + test_interactive-test-texture-material.$(OBJEXT) \ + test_interactive-test-events.$(OBJEXT) \ + test_interactive-test-scale.$(OBJEXT) \ + test_interactive-test-actors.$(OBJEXT) \ + test_interactive-test-shader-effects.$(OBJEXT) \ + test_interactive-test-script.$(OBJEXT) \ + test_interactive-test-grab.$(OBJEXT) \ + test_interactive-test-cogl-shader-arbfp.$(OBJEXT) \ + test_interactive-test-cogl-shader-glsl.$(OBJEXT) \ + test_interactive-test-animator.$(OBJEXT) \ + test_interactive-test-state.$(OBJEXT) \ + test_interactive-test-state-animator.$(OBJEXT) \ + test_interactive-test-fbo.$(OBJEXT) \ + test_interactive-test-multistage.$(OBJEXT) \ + test_interactive-test-cogl-tex-tile.$(OBJEXT) \ + test_interactive-test-cogl-tex-convert.$(OBJEXT) \ + test_interactive-test-cogl-tex-foreign.$(OBJEXT) \ + test_interactive-test-cogl-offscreen.$(OBJEXT) \ + test_interactive-test-cogl-tex-polygon.$(OBJEXT) \ + test_interactive-test-cogl-multitexture.$(OBJEXT) \ + test_interactive-test-stage-read-pixels.$(OBJEXT) \ + test_interactive-test-paint-wrapper.$(OBJEXT) \ + test_interactive-test-texture-quality.$(OBJEXT) \ + test_interactive-test-layout.$(OBJEXT) \ + test_interactive-test-animation.$(OBJEXT) \ + test_interactive-test-easing.$(OBJEXT) \ + test_interactive-test-binding-pool.$(OBJEXT) \ + test_interactive-test-text.$(OBJEXT) \ + test_interactive-test-text-field.$(OBJEXT) \ + test_interactive-test-cairo-clock.$(OBJEXT) \ + test_interactive-test-cairo-flowers.$(OBJEXT) \ + test_interactive-test-cogl-vertex-buffer.$(OBJEXT) \ + test_interactive-test-stage-sizing.$(OBJEXT) \ + test_interactive-test-scrolling.$(OBJEXT) \ + test_interactive-test-swipe-action.$(OBJEXT) \ + test_interactive-test-cogl-point-sprites.$(OBJEXT) \ + test_interactive-test-table-layout.$(OBJEXT) \ + test_interactive-test-path-constraint.$(OBJEXT) \ + test_interactive-test-state-script.$(OBJEXT) \ + test_interactive-test-devices.$(OBJEXT) \ + test_interactive-test-content.$(OBJEXT) \ + test_interactive-test-keyframe-transition.$(OBJEXT) \ + test_interactive-test-bind-constraint.$(OBJEXT) \ + test_interactive-test-touch-events.$(OBJEXT) \ + test_interactive-test-rotate-zoom.$(OBJEXT) $(am__objects_1) \ + $(am__objects_2) +am_test_interactive_OBJECTS = test_interactive-test-main.$(OBJEXT) \ + $(am__objects_3) +nodist_test_interactive_OBJECTS = +test_interactive_OBJECTS = $(am_test_interactive_OBJECTS) \ + $(nodist_test_interactive_OBJECTS) +am__DEPENDENCIES_1 = +test_interactive_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(common_ldadd) $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +test_interactive_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(test_interactive_CFLAGS) $(CFLAGS) \ + $(test_interactive_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/clutter +depcomp = $(SHELL) $(top_srcdir)/build/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(test_interactive_SOURCES) \ + $(nodist_test_interactive_SOURCES) +DIST_SOURCES = $(am__test_interactive_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/wrapper.sh.in \ + $(top_srcdir)/build/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ATK_REQ_VERSION = @ATK_REQ_VERSION@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_REQ_VERSION = @CAIRO_REQ_VERSION@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CLUTTER_API_VERSION = @CLUTTER_API_VERSION@ +CLUTTER_API_VERSION_AM = @CLUTTER_API_VERSION_AM@ +CLUTTER_BACKENDS = @CLUTTER_BACKENDS@ +CLUTTER_CFLAGS = @CLUTTER_CFLAGS@ +CLUTTER_COGL = @CLUTTER_COGL@ +CLUTTER_CONFIG_DEFINES = @CLUTTER_CONFIG_DEFINES@ +CLUTTER_DEBUG_CFLAGS = @CLUTTER_DEBUG_CFLAGS@ +CLUTTER_DEPRECATED_CFLAGS = @CLUTTER_DEPRECATED_CFLAGS@ +CLUTTER_DEPS_CFLAGS = @CLUTTER_DEPS_CFLAGS@ +CLUTTER_DEPS_LIBS = @CLUTTER_DEPS_LIBS@ +CLUTTER_DEPS_PRIVATE_CFLAGS = @CLUTTER_DEPS_PRIVATE_CFLAGS@ +CLUTTER_DEPS_PRIVATE_LIBS = @CLUTTER_DEPS_PRIVATE_LIBS@ +CLUTTER_FLAVOUR = @CLUTTER_FLAVOUR@ +CLUTTER_GCOV_CFLAGS = @CLUTTER_GCOV_CFLAGS@ +CLUTTER_GCOV_LDADD = @CLUTTER_GCOV_LDADD@ +CLUTTER_HIDDEN_VISIBILITY_CFLAGS = @CLUTTER_HIDDEN_VISIBILITY_CFLAGS@ +CLUTTER_INPUT_BACKENDS = @CLUTTER_INPUT_BACKENDS@ +CLUTTER_LIBS = @CLUTTER_LIBS@ +CLUTTER_LINK_FLAGS = @CLUTTER_LINK_FLAGS@ +CLUTTER_LT_CURRENT = @CLUTTER_LT_CURRENT@ +CLUTTER_LT_LDFLAGS = @CLUTTER_LT_LDFLAGS@ +CLUTTER_LT_REVISION = @CLUTTER_LT_REVISION@ +CLUTTER_LT_VERSION = @CLUTTER_LT_VERSION@ +CLUTTER_MAJOR_VERSION = @CLUTTER_MAJOR_VERSION@ +CLUTTER_MICRO_VERSION = @CLUTTER_MICRO_VERSION@ +CLUTTER_MINOR_VERSION = @CLUTTER_MINOR_VERSION@ +CLUTTER_RELEASE_STATUS = @CLUTTER_RELEASE_STATUS@ +CLUTTER_REQUIRES = @CLUTTER_REQUIRES@ +CLUTTER_REQUIRES_PRIVATE = @CLUTTER_REQUIRES_PRIVATE@ +CLUTTER_SONAME_INFIX = @CLUTTER_SONAME_INFIX@ +CLUTTER_STAGE_TYPE = @CLUTTER_STAGE_TYPE@ +CLUTTER_VERSION = @CLUTTER_VERSION@ +CLUTTER_WINSYS = @CLUTTER_WINSYS@ +CLUTTER_WINSYS_BASE = @CLUTTER_WINSYS_BASE@ +COGL_DRIVER = @COGL_DRIVER@ +COGL_REQ_VERSION = @COGL_REQ_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@ +GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@ +GDK_REQ_VERSION = @GDK_REQ_VERSION@ +GI_REQ_VERSION = @GI_REQ_VERSION@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQ_VERSION = @GLIB_REQ_VERSION@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +JSON_GLIB_REQ_VERSION = @JSON_GLIB_REQ_VERSION@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBINPUT_REQ_VERSION = @LIBINPUT_REQ_VERSION@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUDEV_REQ_VERSION = @LIBUDEV_REQ_VERSION@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTP = @LTP@ +LTP_GENHTML = @LTP_GENHTML@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINTAINER_CFLAGS = @MAINTAINER_CFLAGS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGO_REQ_VERSION = @PANGO_REQ_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SHTOOL = @SHTOOL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +XCOMPOSITE_REQ_VERSION = @XCOMPOSITE_REQ_VERSION@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +installed_test_metadir = @installed_test_metadir@ +installed_testdir = @installed_testdir@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +UNIT_TESTS = test-texture-slicing.c test-texture-async.c \ + test-texture-material.c test-events.c test-scale.c \ + test-actors.c test-shader-effects.c test-script.c test-grab.c \ + test-cogl-shader-arbfp.c test-cogl-shader-glsl.c \ + test-animator.c test-state.c test-state-animator.c test-fbo.c \ + test-multistage.c test-cogl-tex-tile.c test-cogl-tex-convert.c \ + test-cogl-tex-foreign.c test-cogl-offscreen.c \ + test-cogl-tex-polygon.c test-cogl-multitexture.c \ + test-stage-read-pixels.c test-paint-wrapper.c \ + test-texture-quality.c test-layout.c test-animation.c \ + test-easing.c test-binding-pool.c test-text.c \ + test-text-field.c test-cairo-clock.c test-cairo-flowers.c \ + test-cogl-vertex-buffer.c test-stage-sizing.c test-scrolling.c \ + test-swipe-action.c test-cogl-point-sprites.c \ + test-table-layout.c test-path-constraint.c test-state-script.c \ + test-devices.c test-content.c test-keyframe-transition.c \ + test-bind-constraint.c test-touch-events.c test-rotate-zoom.c \ + $(am__append_1) $(am__append_2) +SHEXT = $(EXEEXT) +GIT_IGNORE_EXTRA = \ + stamp-test-interactive \ + stamp-test-unit-names \ + test-unit-names.h \ + $(UNIT_TESTS:.c=$(SHEXT)) + +common_ldadd = \ + $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la + +check_SCRIPTS = wrappers +test_interactive_SOURCES = test-main.c $(UNIT_TESTS) +nodist_test_interactive_SOURCES = test-unit-names.h +test_interactive_CFLAGS = $(CLUTTER_CFLAGS) $(GDK_PIXBUF_CFLAGS) +test_interactive_CPPFLAGS = \ + -DTESTS_DATADIR=\""$(abs_srcdir)"\" \ + -DG_DISABLE_SINGLE_INCLUDES \ + -DGLIB_DISABLE_DEPRECATION_WARNINGS \ + -DCOGL_DISABLE_DEPRECATION_WARNINGS \ + -DCLUTTER_DISABLE_DEPRECATION_WARNINGS \ + -I$(top_srcdir)/../cogl \ + -I$(top_builddir)/../cogl \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + -I$(top_srcdir)/clutter \ + -I$(top_builddir)/clutter + +test_interactive_LDFLAGS = -export-dynamic +test_interactive_LDADD = $(CLUTTER_LIBS) $(GDK_PIXBUF_LIBS) $(common_ldadd) $(LIBM) +EXTRA_DIST = \ + wrapper.sh.in \ + test-script.json \ + test-script-signals.json \ + redhand.png + +DISTCLEANFILES = wrapper.sh .gitignore test-unit-names.h +BUILT_SOURCES = test-unit-names.h +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/interactive/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/interactive/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +wrapper.sh: $(top_builddir)/config.status $(srcdir)/wrapper.sh.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +test-interactive$(EXEEXT): $(test_interactive_OBJECTS) $(test_interactive_DEPENDENCIES) $(EXTRA_test_interactive_DEPENDENCIES) + @rm -f test-interactive$(EXEEXT) + $(AM_V_CCLD)$(test_interactive_LINK) $(test_interactive_OBJECTS) $(test_interactive_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-actors.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-animation.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-animator.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-bind-constraint.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-binding-pool.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-cairo-clock.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-cairo-flowers.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-cogl-multitexture.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-cogl-offscreen.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-cogl-point-sprites.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-cogl-shader-arbfp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-cogl-shader-glsl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-cogl-tex-convert.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-cogl-tex-foreign.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-cogl-tex-polygon.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-cogl-tex-tile.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-cogl-vertex-buffer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-content.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-devices.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-easing.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-events.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-fbo.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-grab.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-image.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-keyframe-transition.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-layout.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-multistage.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-paint-wrapper.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-path-constraint.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-pixmap.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-rotate-zoom.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-scale.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-script.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-scrolling.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-shader-effects.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-stage-read-pixels.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-stage-sizing.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-state-animator.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-state-script.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-state.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-swipe-action.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-table-layout.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-text-field.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-text.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-texture-async.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-texture-material.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-texture-quality.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-texture-slicing.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_interactive-test-touch-events.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +test_interactive-test-main.o: test-main.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-main.o -MD -MP -MF $(DEPDIR)/test_interactive-test-main.Tpo -c -o test_interactive-test-main.o `test -f 'test-main.c' || echo '$(srcdir)/'`test-main.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-main.Tpo $(DEPDIR)/test_interactive-test-main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-main.c' object='test_interactive-test-main.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-main.o `test -f 'test-main.c' || echo '$(srcdir)/'`test-main.c + +test_interactive-test-main.obj: test-main.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-main.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-main.Tpo -c -o test_interactive-test-main.obj `if test -f 'test-main.c'; then $(CYGPATH_W) 'test-main.c'; else $(CYGPATH_W) '$(srcdir)/test-main.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-main.Tpo $(DEPDIR)/test_interactive-test-main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-main.c' object='test_interactive-test-main.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-main.obj `if test -f 'test-main.c'; then $(CYGPATH_W) 'test-main.c'; else $(CYGPATH_W) '$(srcdir)/test-main.c'; fi` + +test_interactive-test-texture-slicing.o: test-texture-slicing.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-texture-slicing.o -MD -MP -MF $(DEPDIR)/test_interactive-test-texture-slicing.Tpo -c -o test_interactive-test-texture-slicing.o `test -f 'test-texture-slicing.c' || echo '$(srcdir)/'`test-texture-slicing.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-texture-slicing.Tpo $(DEPDIR)/test_interactive-test-texture-slicing.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-texture-slicing.c' object='test_interactive-test-texture-slicing.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-texture-slicing.o `test -f 'test-texture-slicing.c' || echo '$(srcdir)/'`test-texture-slicing.c + +test_interactive-test-texture-slicing.obj: test-texture-slicing.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-texture-slicing.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-texture-slicing.Tpo -c -o test_interactive-test-texture-slicing.obj `if test -f 'test-texture-slicing.c'; then $(CYGPATH_W) 'test-texture-slicing.c'; else $(CYGPATH_W) '$(srcdir)/test-texture-slicing.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-texture-slicing.Tpo $(DEPDIR)/test_interactive-test-texture-slicing.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-texture-slicing.c' object='test_interactive-test-texture-slicing.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-texture-slicing.obj `if test -f 'test-texture-slicing.c'; then $(CYGPATH_W) 'test-texture-slicing.c'; else $(CYGPATH_W) '$(srcdir)/test-texture-slicing.c'; fi` + +test_interactive-test-texture-async.o: test-texture-async.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-texture-async.o -MD -MP -MF $(DEPDIR)/test_interactive-test-texture-async.Tpo -c -o test_interactive-test-texture-async.o `test -f 'test-texture-async.c' || echo '$(srcdir)/'`test-texture-async.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-texture-async.Tpo $(DEPDIR)/test_interactive-test-texture-async.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-texture-async.c' object='test_interactive-test-texture-async.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-texture-async.o `test -f 'test-texture-async.c' || echo '$(srcdir)/'`test-texture-async.c + +test_interactive-test-texture-async.obj: test-texture-async.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-texture-async.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-texture-async.Tpo -c -o test_interactive-test-texture-async.obj `if test -f 'test-texture-async.c'; then $(CYGPATH_W) 'test-texture-async.c'; else $(CYGPATH_W) '$(srcdir)/test-texture-async.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-texture-async.Tpo $(DEPDIR)/test_interactive-test-texture-async.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-texture-async.c' object='test_interactive-test-texture-async.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-texture-async.obj `if test -f 'test-texture-async.c'; then $(CYGPATH_W) 'test-texture-async.c'; else $(CYGPATH_W) '$(srcdir)/test-texture-async.c'; fi` + +test_interactive-test-texture-material.o: test-texture-material.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-texture-material.o -MD -MP -MF $(DEPDIR)/test_interactive-test-texture-material.Tpo -c -o test_interactive-test-texture-material.o `test -f 'test-texture-material.c' || echo '$(srcdir)/'`test-texture-material.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-texture-material.Tpo $(DEPDIR)/test_interactive-test-texture-material.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-texture-material.c' object='test_interactive-test-texture-material.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-texture-material.o `test -f 'test-texture-material.c' || echo '$(srcdir)/'`test-texture-material.c + +test_interactive-test-texture-material.obj: test-texture-material.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-texture-material.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-texture-material.Tpo -c -o test_interactive-test-texture-material.obj `if test -f 'test-texture-material.c'; then $(CYGPATH_W) 'test-texture-material.c'; else $(CYGPATH_W) '$(srcdir)/test-texture-material.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-texture-material.Tpo $(DEPDIR)/test_interactive-test-texture-material.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-texture-material.c' object='test_interactive-test-texture-material.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-texture-material.obj `if test -f 'test-texture-material.c'; then $(CYGPATH_W) 'test-texture-material.c'; else $(CYGPATH_W) '$(srcdir)/test-texture-material.c'; fi` + +test_interactive-test-events.o: test-events.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-events.o -MD -MP -MF $(DEPDIR)/test_interactive-test-events.Tpo -c -o test_interactive-test-events.o `test -f 'test-events.c' || echo '$(srcdir)/'`test-events.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-events.Tpo $(DEPDIR)/test_interactive-test-events.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-events.c' object='test_interactive-test-events.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-events.o `test -f 'test-events.c' || echo '$(srcdir)/'`test-events.c + +test_interactive-test-events.obj: test-events.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-events.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-events.Tpo -c -o test_interactive-test-events.obj `if test -f 'test-events.c'; then $(CYGPATH_W) 'test-events.c'; else $(CYGPATH_W) '$(srcdir)/test-events.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-events.Tpo $(DEPDIR)/test_interactive-test-events.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-events.c' object='test_interactive-test-events.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-events.obj `if test -f 'test-events.c'; then $(CYGPATH_W) 'test-events.c'; else $(CYGPATH_W) '$(srcdir)/test-events.c'; fi` + +test_interactive-test-scale.o: test-scale.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-scale.o -MD -MP -MF $(DEPDIR)/test_interactive-test-scale.Tpo -c -o test_interactive-test-scale.o `test -f 'test-scale.c' || echo '$(srcdir)/'`test-scale.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-scale.Tpo $(DEPDIR)/test_interactive-test-scale.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-scale.c' object='test_interactive-test-scale.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-scale.o `test -f 'test-scale.c' || echo '$(srcdir)/'`test-scale.c + +test_interactive-test-scale.obj: test-scale.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-scale.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-scale.Tpo -c -o test_interactive-test-scale.obj `if test -f 'test-scale.c'; then $(CYGPATH_W) 'test-scale.c'; else $(CYGPATH_W) '$(srcdir)/test-scale.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-scale.Tpo $(DEPDIR)/test_interactive-test-scale.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-scale.c' object='test_interactive-test-scale.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-scale.obj `if test -f 'test-scale.c'; then $(CYGPATH_W) 'test-scale.c'; else $(CYGPATH_W) '$(srcdir)/test-scale.c'; fi` + +test_interactive-test-actors.o: test-actors.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-actors.o -MD -MP -MF $(DEPDIR)/test_interactive-test-actors.Tpo -c -o test_interactive-test-actors.o `test -f 'test-actors.c' || echo '$(srcdir)/'`test-actors.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-actors.Tpo $(DEPDIR)/test_interactive-test-actors.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-actors.c' object='test_interactive-test-actors.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-actors.o `test -f 'test-actors.c' || echo '$(srcdir)/'`test-actors.c + +test_interactive-test-actors.obj: test-actors.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-actors.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-actors.Tpo -c -o test_interactive-test-actors.obj `if test -f 'test-actors.c'; then $(CYGPATH_W) 'test-actors.c'; else $(CYGPATH_W) '$(srcdir)/test-actors.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-actors.Tpo $(DEPDIR)/test_interactive-test-actors.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-actors.c' object='test_interactive-test-actors.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-actors.obj `if test -f 'test-actors.c'; then $(CYGPATH_W) 'test-actors.c'; else $(CYGPATH_W) '$(srcdir)/test-actors.c'; fi` + +test_interactive-test-shader-effects.o: test-shader-effects.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-shader-effects.o -MD -MP -MF $(DEPDIR)/test_interactive-test-shader-effects.Tpo -c -o test_interactive-test-shader-effects.o `test -f 'test-shader-effects.c' || echo '$(srcdir)/'`test-shader-effects.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-shader-effects.Tpo $(DEPDIR)/test_interactive-test-shader-effects.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-shader-effects.c' object='test_interactive-test-shader-effects.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-shader-effects.o `test -f 'test-shader-effects.c' || echo '$(srcdir)/'`test-shader-effects.c + +test_interactive-test-shader-effects.obj: test-shader-effects.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-shader-effects.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-shader-effects.Tpo -c -o test_interactive-test-shader-effects.obj `if test -f 'test-shader-effects.c'; then $(CYGPATH_W) 'test-shader-effects.c'; else $(CYGPATH_W) '$(srcdir)/test-shader-effects.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-shader-effects.Tpo $(DEPDIR)/test_interactive-test-shader-effects.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-shader-effects.c' object='test_interactive-test-shader-effects.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-shader-effects.obj `if test -f 'test-shader-effects.c'; then $(CYGPATH_W) 'test-shader-effects.c'; else $(CYGPATH_W) '$(srcdir)/test-shader-effects.c'; fi` + +test_interactive-test-script.o: test-script.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-script.o -MD -MP -MF $(DEPDIR)/test_interactive-test-script.Tpo -c -o test_interactive-test-script.o `test -f 'test-script.c' || echo '$(srcdir)/'`test-script.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-script.Tpo $(DEPDIR)/test_interactive-test-script.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-script.c' object='test_interactive-test-script.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-script.o `test -f 'test-script.c' || echo '$(srcdir)/'`test-script.c + +test_interactive-test-script.obj: test-script.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-script.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-script.Tpo -c -o test_interactive-test-script.obj `if test -f 'test-script.c'; then $(CYGPATH_W) 'test-script.c'; else $(CYGPATH_W) '$(srcdir)/test-script.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-script.Tpo $(DEPDIR)/test_interactive-test-script.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-script.c' object='test_interactive-test-script.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-script.obj `if test -f 'test-script.c'; then $(CYGPATH_W) 'test-script.c'; else $(CYGPATH_W) '$(srcdir)/test-script.c'; fi` + +test_interactive-test-grab.o: test-grab.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-grab.o -MD -MP -MF $(DEPDIR)/test_interactive-test-grab.Tpo -c -o test_interactive-test-grab.o `test -f 'test-grab.c' || echo '$(srcdir)/'`test-grab.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-grab.Tpo $(DEPDIR)/test_interactive-test-grab.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-grab.c' object='test_interactive-test-grab.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-grab.o `test -f 'test-grab.c' || echo '$(srcdir)/'`test-grab.c + +test_interactive-test-grab.obj: test-grab.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-grab.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-grab.Tpo -c -o test_interactive-test-grab.obj `if test -f 'test-grab.c'; then $(CYGPATH_W) 'test-grab.c'; else $(CYGPATH_W) '$(srcdir)/test-grab.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-grab.Tpo $(DEPDIR)/test_interactive-test-grab.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-grab.c' object='test_interactive-test-grab.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-grab.obj `if test -f 'test-grab.c'; then $(CYGPATH_W) 'test-grab.c'; else $(CYGPATH_W) '$(srcdir)/test-grab.c'; fi` + +test_interactive-test-cogl-shader-arbfp.o: test-cogl-shader-arbfp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-cogl-shader-arbfp.o -MD -MP -MF $(DEPDIR)/test_interactive-test-cogl-shader-arbfp.Tpo -c -o test_interactive-test-cogl-shader-arbfp.o `test -f 'test-cogl-shader-arbfp.c' || echo '$(srcdir)/'`test-cogl-shader-arbfp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-cogl-shader-arbfp.Tpo $(DEPDIR)/test_interactive-test-cogl-shader-arbfp.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cogl-shader-arbfp.c' object='test_interactive-test-cogl-shader-arbfp.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-cogl-shader-arbfp.o `test -f 'test-cogl-shader-arbfp.c' || echo '$(srcdir)/'`test-cogl-shader-arbfp.c + +test_interactive-test-cogl-shader-arbfp.obj: test-cogl-shader-arbfp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-cogl-shader-arbfp.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-cogl-shader-arbfp.Tpo -c -o test_interactive-test-cogl-shader-arbfp.obj `if test -f 'test-cogl-shader-arbfp.c'; then $(CYGPATH_W) 'test-cogl-shader-arbfp.c'; else $(CYGPATH_W) '$(srcdir)/test-cogl-shader-arbfp.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-cogl-shader-arbfp.Tpo $(DEPDIR)/test_interactive-test-cogl-shader-arbfp.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cogl-shader-arbfp.c' object='test_interactive-test-cogl-shader-arbfp.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-cogl-shader-arbfp.obj `if test -f 'test-cogl-shader-arbfp.c'; then $(CYGPATH_W) 'test-cogl-shader-arbfp.c'; else $(CYGPATH_W) '$(srcdir)/test-cogl-shader-arbfp.c'; fi` + +test_interactive-test-cogl-shader-glsl.o: test-cogl-shader-glsl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-cogl-shader-glsl.o -MD -MP -MF $(DEPDIR)/test_interactive-test-cogl-shader-glsl.Tpo -c -o test_interactive-test-cogl-shader-glsl.o `test -f 'test-cogl-shader-glsl.c' || echo '$(srcdir)/'`test-cogl-shader-glsl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-cogl-shader-glsl.Tpo $(DEPDIR)/test_interactive-test-cogl-shader-glsl.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cogl-shader-glsl.c' object='test_interactive-test-cogl-shader-glsl.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-cogl-shader-glsl.o `test -f 'test-cogl-shader-glsl.c' || echo '$(srcdir)/'`test-cogl-shader-glsl.c + +test_interactive-test-cogl-shader-glsl.obj: test-cogl-shader-glsl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-cogl-shader-glsl.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-cogl-shader-glsl.Tpo -c -o test_interactive-test-cogl-shader-glsl.obj `if test -f 'test-cogl-shader-glsl.c'; then $(CYGPATH_W) 'test-cogl-shader-glsl.c'; else $(CYGPATH_W) '$(srcdir)/test-cogl-shader-glsl.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-cogl-shader-glsl.Tpo $(DEPDIR)/test_interactive-test-cogl-shader-glsl.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cogl-shader-glsl.c' object='test_interactive-test-cogl-shader-glsl.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-cogl-shader-glsl.obj `if test -f 'test-cogl-shader-glsl.c'; then $(CYGPATH_W) 'test-cogl-shader-glsl.c'; else $(CYGPATH_W) '$(srcdir)/test-cogl-shader-glsl.c'; fi` + +test_interactive-test-animator.o: test-animator.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-animator.o -MD -MP -MF $(DEPDIR)/test_interactive-test-animator.Tpo -c -o test_interactive-test-animator.o `test -f 'test-animator.c' || echo '$(srcdir)/'`test-animator.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-animator.Tpo $(DEPDIR)/test_interactive-test-animator.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-animator.c' object='test_interactive-test-animator.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-animator.o `test -f 'test-animator.c' || echo '$(srcdir)/'`test-animator.c + +test_interactive-test-animator.obj: test-animator.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-animator.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-animator.Tpo -c -o test_interactive-test-animator.obj `if test -f 'test-animator.c'; then $(CYGPATH_W) 'test-animator.c'; else $(CYGPATH_W) '$(srcdir)/test-animator.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-animator.Tpo $(DEPDIR)/test_interactive-test-animator.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-animator.c' object='test_interactive-test-animator.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-animator.obj `if test -f 'test-animator.c'; then $(CYGPATH_W) 'test-animator.c'; else $(CYGPATH_W) '$(srcdir)/test-animator.c'; fi` + +test_interactive-test-state.o: test-state.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-state.o -MD -MP -MF $(DEPDIR)/test_interactive-test-state.Tpo -c -o test_interactive-test-state.o `test -f 'test-state.c' || echo '$(srcdir)/'`test-state.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-state.Tpo $(DEPDIR)/test_interactive-test-state.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-state.c' object='test_interactive-test-state.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-state.o `test -f 'test-state.c' || echo '$(srcdir)/'`test-state.c + +test_interactive-test-state.obj: test-state.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-state.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-state.Tpo -c -o test_interactive-test-state.obj `if test -f 'test-state.c'; then $(CYGPATH_W) 'test-state.c'; else $(CYGPATH_W) '$(srcdir)/test-state.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-state.Tpo $(DEPDIR)/test_interactive-test-state.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-state.c' object='test_interactive-test-state.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-state.obj `if test -f 'test-state.c'; then $(CYGPATH_W) 'test-state.c'; else $(CYGPATH_W) '$(srcdir)/test-state.c'; fi` + +test_interactive-test-state-animator.o: test-state-animator.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-state-animator.o -MD -MP -MF $(DEPDIR)/test_interactive-test-state-animator.Tpo -c -o test_interactive-test-state-animator.o `test -f 'test-state-animator.c' || echo '$(srcdir)/'`test-state-animator.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-state-animator.Tpo $(DEPDIR)/test_interactive-test-state-animator.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-state-animator.c' object='test_interactive-test-state-animator.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-state-animator.o `test -f 'test-state-animator.c' || echo '$(srcdir)/'`test-state-animator.c + +test_interactive-test-state-animator.obj: test-state-animator.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-state-animator.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-state-animator.Tpo -c -o test_interactive-test-state-animator.obj `if test -f 'test-state-animator.c'; then $(CYGPATH_W) 'test-state-animator.c'; else $(CYGPATH_W) '$(srcdir)/test-state-animator.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-state-animator.Tpo $(DEPDIR)/test_interactive-test-state-animator.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-state-animator.c' object='test_interactive-test-state-animator.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-state-animator.obj `if test -f 'test-state-animator.c'; then $(CYGPATH_W) 'test-state-animator.c'; else $(CYGPATH_W) '$(srcdir)/test-state-animator.c'; fi` + +test_interactive-test-fbo.o: test-fbo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-fbo.o -MD -MP -MF $(DEPDIR)/test_interactive-test-fbo.Tpo -c -o test_interactive-test-fbo.o `test -f 'test-fbo.c' || echo '$(srcdir)/'`test-fbo.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-fbo.Tpo $(DEPDIR)/test_interactive-test-fbo.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-fbo.c' object='test_interactive-test-fbo.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-fbo.o `test -f 'test-fbo.c' || echo '$(srcdir)/'`test-fbo.c + +test_interactive-test-fbo.obj: test-fbo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-fbo.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-fbo.Tpo -c -o test_interactive-test-fbo.obj `if test -f 'test-fbo.c'; then $(CYGPATH_W) 'test-fbo.c'; else $(CYGPATH_W) '$(srcdir)/test-fbo.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-fbo.Tpo $(DEPDIR)/test_interactive-test-fbo.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-fbo.c' object='test_interactive-test-fbo.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-fbo.obj `if test -f 'test-fbo.c'; then $(CYGPATH_W) 'test-fbo.c'; else $(CYGPATH_W) '$(srcdir)/test-fbo.c'; fi` + +test_interactive-test-multistage.o: test-multistage.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-multistage.o -MD -MP -MF $(DEPDIR)/test_interactive-test-multistage.Tpo -c -o test_interactive-test-multistage.o `test -f 'test-multistage.c' || echo '$(srcdir)/'`test-multistage.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-multistage.Tpo $(DEPDIR)/test_interactive-test-multistage.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-multistage.c' object='test_interactive-test-multistage.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-multistage.o `test -f 'test-multistage.c' || echo '$(srcdir)/'`test-multistage.c + +test_interactive-test-multistage.obj: test-multistage.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-multistage.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-multistage.Tpo -c -o test_interactive-test-multistage.obj `if test -f 'test-multistage.c'; then $(CYGPATH_W) 'test-multistage.c'; else $(CYGPATH_W) '$(srcdir)/test-multistage.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-multistage.Tpo $(DEPDIR)/test_interactive-test-multistage.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-multistage.c' object='test_interactive-test-multistage.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-multistage.obj `if test -f 'test-multistage.c'; then $(CYGPATH_W) 'test-multistage.c'; else $(CYGPATH_W) '$(srcdir)/test-multistage.c'; fi` + +test_interactive-test-cogl-tex-tile.o: test-cogl-tex-tile.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-cogl-tex-tile.o -MD -MP -MF $(DEPDIR)/test_interactive-test-cogl-tex-tile.Tpo -c -o test_interactive-test-cogl-tex-tile.o `test -f 'test-cogl-tex-tile.c' || echo '$(srcdir)/'`test-cogl-tex-tile.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-cogl-tex-tile.Tpo $(DEPDIR)/test_interactive-test-cogl-tex-tile.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cogl-tex-tile.c' object='test_interactive-test-cogl-tex-tile.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-cogl-tex-tile.o `test -f 'test-cogl-tex-tile.c' || echo '$(srcdir)/'`test-cogl-tex-tile.c + +test_interactive-test-cogl-tex-tile.obj: test-cogl-tex-tile.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-cogl-tex-tile.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-cogl-tex-tile.Tpo -c -o test_interactive-test-cogl-tex-tile.obj `if test -f 'test-cogl-tex-tile.c'; then $(CYGPATH_W) 'test-cogl-tex-tile.c'; else $(CYGPATH_W) '$(srcdir)/test-cogl-tex-tile.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-cogl-tex-tile.Tpo $(DEPDIR)/test_interactive-test-cogl-tex-tile.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cogl-tex-tile.c' object='test_interactive-test-cogl-tex-tile.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-cogl-tex-tile.obj `if test -f 'test-cogl-tex-tile.c'; then $(CYGPATH_W) 'test-cogl-tex-tile.c'; else $(CYGPATH_W) '$(srcdir)/test-cogl-tex-tile.c'; fi` + +test_interactive-test-cogl-tex-convert.o: test-cogl-tex-convert.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-cogl-tex-convert.o -MD -MP -MF $(DEPDIR)/test_interactive-test-cogl-tex-convert.Tpo -c -o test_interactive-test-cogl-tex-convert.o `test -f 'test-cogl-tex-convert.c' || echo '$(srcdir)/'`test-cogl-tex-convert.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-cogl-tex-convert.Tpo $(DEPDIR)/test_interactive-test-cogl-tex-convert.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cogl-tex-convert.c' object='test_interactive-test-cogl-tex-convert.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-cogl-tex-convert.o `test -f 'test-cogl-tex-convert.c' || echo '$(srcdir)/'`test-cogl-tex-convert.c + +test_interactive-test-cogl-tex-convert.obj: test-cogl-tex-convert.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-cogl-tex-convert.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-cogl-tex-convert.Tpo -c -o test_interactive-test-cogl-tex-convert.obj `if test -f 'test-cogl-tex-convert.c'; then $(CYGPATH_W) 'test-cogl-tex-convert.c'; else $(CYGPATH_W) '$(srcdir)/test-cogl-tex-convert.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-cogl-tex-convert.Tpo $(DEPDIR)/test_interactive-test-cogl-tex-convert.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cogl-tex-convert.c' object='test_interactive-test-cogl-tex-convert.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-cogl-tex-convert.obj `if test -f 'test-cogl-tex-convert.c'; then $(CYGPATH_W) 'test-cogl-tex-convert.c'; else $(CYGPATH_W) '$(srcdir)/test-cogl-tex-convert.c'; fi` + +test_interactive-test-cogl-tex-foreign.o: test-cogl-tex-foreign.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-cogl-tex-foreign.o -MD -MP -MF $(DEPDIR)/test_interactive-test-cogl-tex-foreign.Tpo -c -o test_interactive-test-cogl-tex-foreign.o `test -f 'test-cogl-tex-foreign.c' || echo '$(srcdir)/'`test-cogl-tex-foreign.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-cogl-tex-foreign.Tpo $(DEPDIR)/test_interactive-test-cogl-tex-foreign.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cogl-tex-foreign.c' object='test_interactive-test-cogl-tex-foreign.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-cogl-tex-foreign.o `test -f 'test-cogl-tex-foreign.c' || echo '$(srcdir)/'`test-cogl-tex-foreign.c + +test_interactive-test-cogl-tex-foreign.obj: test-cogl-tex-foreign.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-cogl-tex-foreign.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-cogl-tex-foreign.Tpo -c -o test_interactive-test-cogl-tex-foreign.obj `if test -f 'test-cogl-tex-foreign.c'; then $(CYGPATH_W) 'test-cogl-tex-foreign.c'; else $(CYGPATH_W) '$(srcdir)/test-cogl-tex-foreign.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-cogl-tex-foreign.Tpo $(DEPDIR)/test_interactive-test-cogl-tex-foreign.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cogl-tex-foreign.c' object='test_interactive-test-cogl-tex-foreign.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-cogl-tex-foreign.obj `if test -f 'test-cogl-tex-foreign.c'; then $(CYGPATH_W) 'test-cogl-tex-foreign.c'; else $(CYGPATH_W) '$(srcdir)/test-cogl-tex-foreign.c'; fi` + +test_interactive-test-cogl-offscreen.o: test-cogl-offscreen.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-cogl-offscreen.o -MD -MP -MF $(DEPDIR)/test_interactive-test-cogl-offscreen.Tpo -c -o test_interactive-test-cogl-offscreen.o `test -f 'test-cogl-offscreen.c' || echo '$(srcdir)/'`test-cogl-offscreen.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-cogl-offscreen.Tpo $(DEPDIR)/test_interactive-test-cogl-offscreen.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cogl-offscreen.c' object='test_interactive-test-cogl-offscreen.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-cogl-offscreen.o `test -f 'test-cogl-offscreen.c' || echo '$(srcdir)/'`test-cogl-offscreen.c + +test_interactive-test-cogl-offscreen.obj: test-cogl-offscreen.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-cogl-offscreen.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-cogl-offscreen.Tpo -c -o test_interactive-test-cogl-offscreen.obj `if test -f 'test-cogl-offscreen.c'; then $(CYGPATH_W) 'test-cogl-offscreen.c'; else $(CYGPATH_W) '$(srcdir)/test-cogl-offscreen.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-cogl-offscreen.Tpo $(DEPDIR)/test_interactive-test-cogl-offscreen.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cogl-offscreen.c' object='test_interactive-test-cogl-offscreen.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-cogl-offscreen.obj `if test -f 'test-cogl-offscreen.c'; then $(CYGPATH_W) 'test-cogl-offscreen.c'; else $(CYGPATH_W) '$(srcdir)/test-cogl-offscreen.c'; fi` + +test_interactive-test-cogl-tex-polygon.o: test-cogl-tex-polygon.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-cogl-tex-polygon.o -MD -MP -MF $(DEPDIR)/test_interactive-test-cogl-tex-polygon.Tpo -c -o test_interactive-test-cogl-tex-polygon.o `test -f 'test-cogl-tex-polygon.c' || echo '$(srcdir)/'`test-cogl-tex-polygon.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-cogl-tex-polygon.Tpo $(DEPDIR)/test_interactive-test-cogl-tex-polygon.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cogl-tex-polygon.c' object='test_interactive-test-cogl-tex-polygon.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-cogl-tex-polygon.o `test -f 'test-cogl-tex-polygon.c' || echo '$(srcdir)/'`test-cogl-tex-polygon.c + +test_interactive-test-cogl-tex-polygon.obj: test-cogl-tex-polygon.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-cogl-tex-polygon.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-cogl-tex-polygon.Tpo -c -o test_interactive-test-cogl-tex-polygon.obj `if test -f 'test-cogl-tex-polygon.c'; then $(CYGPATH_W) 'test-cogl-tex-polygon.c'; else $(CYGPATH_W) '$(srcdir)/test-cogl-tex-polygon.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-cogl-tex-polygon.Tpo $(DEPDIR)/test_interactive-test-cogl-tex-polygon.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cogl-tex-polygon.c' object='test_interactive-test-cogl-tex-polygon.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-cogl-tex-polygon.obj `if test -f 'test-cogl-tex-polygon.c'; then $(CYGPATH_W) 'test-cogl-tex-polygon.c'; else $(CYGPATH_W) '$(srcdir)/test-cogl-tex-polygon.c'; fi` + +test_interactive-test-cogl-multitexture.o: test-cogl-multitexture.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-cogl-multitexture.o -MD -MP -MF $(DEPDIR)/test_interactive-test-cogl-multitexture.Tpo -c -o test_interactive-test-cogl-multitexture.o `test -f 'test-cogl-multitexture.c' || echo '$(srcdir)/'`test-cogl-multitexture.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-cogl-multitexture.Tpo $(DEPDIR)/test_interactive-test-cogl-multitexture.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cogl-multitexture.c' object='test_interactive-test-cogl-multitexture.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-cogl-multitexture.o `test -f 'test-cogl-multitexture.c' || echo '$(srcdir)/'`test-cogl-multitexture.c + +test_interactive-test-cogl-multitexture.obj: test-cogl-multitexture.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-cogl-multitexture.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-cogl-multitexture.Tpo -c -o test_interactive-test-cogl-multitexture.obj `if test -f 'test-cogl-multitexture.c'; then $(CYGPATH_W) 'test-cogl-multitexture.c'; else $(CYGPATH_W) '$(srcdir)/test-cogl-multitexture.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-cogl-multitexture.Tpo $(DEPDIR)/test_interactive-test-cogl-multitexture.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cogl-multitexture.c' object='test_interactive-test-cogl-multitexture.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-cogl-multitexture.obj `if test -f 'test-cogl-multitexture.c'; then $(CYGPATH_W) 'test-cogl-multitexture.c'; else $(CYGPATH_W) '$(srcdir)/test-cogl-multitexture.c'; fi` + +test_interactive-test-stage-read-pixels.o: test-stage-read-pixels.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-stage-read-pixels.o -MD -MP -MF $(DEPDIR)/test_interactive-test-stage-read-pixels.Tpo -c -o test_interactive-test-stage-read-pixels.o `test -f 'test-stage-read-pixels.c' || echo '$(srcdir)/'`test-stage-read-pixels.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-stage-read-pixels.Tpo $(DEPDIR)/test_interactive-test-stage-read-pixels.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-stage-read-pixels.c' object='test_interactive-test-stage-read-pixels.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-stage-read-pixels.o `test -f 'test-stage-read-pixels.c' || echo '$(srcdir)/'`test-stage-read-pixels.c + +test_interactive-test-stage-read-pixels.obj: test-stage-read-pixels.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-stage-read-pixels.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-stage-read-pixels.Tpo -c -o test_interactive-test-stage-read-pixels.obj `if test -f 'test-stage-read-pixels.c'; then $(CYGPATH_W) 'test-stage-read-pixels.c'; else $(CYGPATH_W) '$(srcdir)/test-stage-read-pixels.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-stage-read-pixels.Tpo $(DEPDIR)/test_interactive-test-stage-read-pixels.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-stage-read-pixels.c' object='test_interactive-test-stage-read-pixels.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-stage-read-pixels.obj `if test -f 'test-stage-read-pixels.c'; then $(CYGPATH_W) 'test-stage-read-pixels.c'; else $(CYGPATH_W) '$(srcdir)/test-stage-read-pixels.c'; fi` + +test_interactive-test-paint-wrapper.o: test-paint-wrapper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-paint-wrapper.o -MD -MP -MF $(DEPDIR)/test_interactive-test-paint-wrapper.Tpo -c -o test_interactive-test-paint-wrapper.o `test -f 'test-paint-wrapper.c' || echo '$(srcdir)/'`test-paint-wrapper.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-paint-wrapper.Tpo $(DEPDIR)/test_interactive-test-paint-wrapper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-paint-wrapper.c' object='test_interactive-test-paint-wrapper.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-paint-wrapper.o `test -f 'test-paint-wrapper.c' || echo '$(srcdir)/'`test-paint-wrapper.c + +test_interactive-test-paint-wrapper.obj: test-paint-wrapper.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-paint-wrapper.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-paint-wrapper.Tpo -c -o test_interactive-test-paint-wrapper.obj `if test -f 'test-paint-wrapper.c'; then $(CYGPATH_W) 'test-paint-wrapper.c'; else $(CYGPATH_W) '$(srcdir)/test-paint-wrapper.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-paint-wrapper.Tpo $(DEPDIR)/test_interactive-test-paint-wrapper.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-paint-wrapper.c' object='test_interactive-test-paint-wrapper.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-paint-wrapper.obj `if test -f 'test-paint-wrapper.c'; then $(CYGPATH_W) 'test-paint-wrapper.c'; else $(CYGPATH_W) '$(srcdir)/test-paint-wrapper.c'; fi` + +test_interactive-test-texture-quality.o: test-texture-quality.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-texture-quality.o -MD -MP -MF $(DEPDIR)/test_interactive-test-texture-quality.Tpo -c -o test_interactive-test-texture-quality.o `test -f 'test-texture-quality.c' || echo '$(srcdir)/'`test-texture-quality.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-texture-quality.Tpo $(DEPDIR)/test_interactive-test-texture-quality.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-texture-quality.c' object='test_interactive-test-texture-quality.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-texture-quality.o `test -f 'test-texture-quality.c' || echo '$(srcdir)/'`test-texture-quality.c + +test_interactive-test-texture-quality.obj: test-texture-quality.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-texture-quality.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-texture-quality.Tpo -c -o test_interactive-test-texture-quality.obj `if test -f 'test-texture-quality.c'; then $(CYGPATH_W) 'test-texture-quality.c'; else $(CYGPATH_W) '$(srcdir)/test-texture-quality.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-texture-quality.Tpo $(DEPDIR)/test_interactive-test-texture-quality.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-texture-quality.c' object='test_interactive-test-texture-quality.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-texture-quality.obj `if test -f 'test-texture-quality.c'; then $(CYGPATH_W) 'test-texture-quality.c'; else $(CYGPATH_W) '$(srcdir)/test-texture-quality.c'; fi` + +test_interactive-test-layout.o: test-layout.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-layout.o -MD -MP -MF $(DEPDIR)/test_interactive-test-layout.Tpo -c -o test_interactive-test-layout.o `test -f 'test-layout.c' || echo '$(srcdir)/'`test-layout.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-layout.Tpo $(DEPDIR)/test_interactive-test-layout.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-layout.c' object='test_interactive-test-layout.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-layout.o `test -f 'test-layout.c' || echo '$(srcdir)/'`test-layout.c + +test_interactive-test-layout.obj: test-layout.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-layout.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-layout.Tpo -c -o test_interactive-test-layout.obj `if test -f 'test-layout.c'; then $(CYGPATH_W) 'test-layout.c'; else $(CYGPATH_W) '$(srcdir)/test-layout.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-layout.Tpo $(DEPDIR)/test_interactive-test-layout.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-layout.c' object='test_interactive-test-layout.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-layout.obj `if test -f 'test-layout.c'; then $(CYGPATH_W) 'test-layout.c'; else $(CYGPATH_W) '$(srcdir)/test-layout.c'; fi` + +test_interactive-test-animation.o: test-animation.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-animation.o -MD -MP -MF $(DEPDIR)/test_interactive-test-animation.Tpo -c -o test_interactive-test-animation.o `test -f 'test-animation.c' || echo '$(srcdir)/'`test-animation.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-animation.Tpo $(DEPDIR)/test_interactive-test-animation.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-animation.c' object='test_interactive-test-animation.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-animation.o `test -f 'test-animation.c' || echo '$(srcdir)/'`test-animation.c + +test_interactive-test-animation.obj: test-animation.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-animation.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-animation.Tpo -c -o test_interactive-test-animation.obj `if test -f 'test-animation.c'; then $(CYGPATH_W) 'test-animation.c'; else $(CYGPATH_W) '$(srcdir)/test-animation.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-animation.Tpo $(DEPDIR)/test_interactive-test-animation.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-animation.c' object='test_interactive-test-animation.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-animation.obj `if test -f 'test-animation.c'; then $(CYGPATH_W) 'test-animation.c'; else $(CYGPATH_W) '$(srcdir)/test-animation.c'; fi` + +test_interactive-test-easing.o: test-easing.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-easing.o -MD -MP -MF $(DEPDIR)/test_interactive-test-easing.Tpo -c -o test_interactive-test-easing.o `test -f 'test-easing.c' || echo '$(srcdir)/'`test-easing.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-easing.Tpo $(DEPDIR)/test_interactive-test-easing.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-easing.c' object='test_interactive-test-easing.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-easing.o `test -f 'test-easing.c' || echo '$(srcdir)/'`test-easing.c + +test_interactive-test-easing.obj: test-easing.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-easing.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-easing.Tpo -c -o test_interactive-test-easing.obj `if test -f 'test-easing.c'; then $(CYGPATH_W) 'test-easing.c'; else $(CYGPATH_W) '$(srcdir)/test-easing.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-easing.Tpo $(DEPDIR)/test_interactive-test-easing.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-easing.c' object='test_interactive-test-easing.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-easing.obj `if test -f 'test-easing.c'; then $(CYGPATH_W) 'test-easing.c'; else $(CYGPATH_W) '$(srcdir)/test-easing.c'; fi` + +test_interactive-test-binding-pool.o: test-binding-pool.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-binding-pool.o -MD -MP -MF $(DEPDIR)/test_interactive-test-binding-pool.Tpo -c -o test_interactive-test-binding-pool.o `test -f 'test-binding-pool.c' || echo '$(srcdir)/'`test-binding-pool.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-binding-pool.Tpo $(DEPDIR)/test_interactive-test-binding-pool.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-binding-pool.c' object='test_interactive-test-binding-pool.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-binding-pool.o `test -f 'test-binding-pool.c' || echo '$(srcdir)/'`test-binding-pool.c + +test_interactive-test-binding-pool.obj: test-binding-pool.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-binding-pool.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-binding-pool.Tpo -c -o test_interactive-test-binding-pool.obj `if test -f 'test-binding-pool.c'; then $(CYGPATH_W) 'test-binding-pool.c'; else $(CYGPATH_W) '$(srcdir)/test-binding-pool.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-binding-pool.Tpo $(DEPDIR)/test_interactive-test-binding-pool.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-binding-pool.c' object='test_interactive-test-binding-pool.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-binding-pool.obj `if test -f 'test-binding-pool.c'; then $(CYGPATH_W) 'test-binding-pool.c'; else $(CYGPATH_W) '$(srcdir)/test-binding-pool.c'; fi` + +test_interactive-test-text.o: test-text.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-text.o -MD -MP -MF $(DEPDIR)/test_interactive-test-text.Tpo -c -o test_interactive-test-text.o `test -f 'test-text.c' || echo '$(srcdir)/'`test-text.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-text.Tpo $(DEPDIR)/test_interactive-test-text.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-text.c' object='test_interactive-test-text.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-text.o `test -f 'test-text.c' || echo '$(srcdir)/'`test-text.c + +test_interactive-test-text.obj: test-text.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-text.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-text.Tpo -c -o test_interactive-test-text.obj `if test -f 'test-text.c'; then $(CYGPATH_W) 'test-text.c'; else $(CYGPATH_W) '$(srcdir)/test-text.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-text.Tpo $(DEPDIR)/test_interactive-test-text.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-text.c' object='test_interactive-test-text.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-text.obj `if test -f 'test-text.c'; then $(CYGPATH_W) 'test-text.c'; else $(CYGPATH_W) '$(srcdir)/test-text.c'; fi` + +test_interactive-test-text-field.o: test-text-field.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-text-field.o -MD -MP -MF $(DEPDIR)/test_interactive-test-text-field.Tpo -c -o test_interactive-test-text-field.o `test -f 'test-text-field.c' || echo '$(srcdir)/'`test-text-field.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-text-field.Tpo $(DEPDIR)/test_interactive-test-text-field.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-text-field.c' object='test_interactive-test-text-field.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-text-field.o `test -f 'test-text-field.c' || echo '$(srcdir)/'`test-text-field.c + +test_interactive-test-text-field.obj: test-text-field.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-text-field.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-text-field.Tpo -c -o test_interactive-test-text-field.obj `if test -f 'test-text-field.c'; then $(CYGPATH_W) 'test-text-field.c'; else $(CYGPATH_W) '$(srcdir)/test-text-field.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-text-field.Tpo $(DEPDIR)/test_interactive-test-text-field.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-text-field.c' object='test_interactive-test-text-field.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-text-field.obj `if test -f 'test-text-field.c'; then $(CYGPATH_W) 'test-text-field.c'; else $(CYGPATH_W) '$(srcdir)/test-text-field.c'; fi` + +test_interactive-test-cairo-clock.o: test-cairo-clock.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-cairo-clock.o -MD -MP -MF $(DEPDIR)/test_interactive-test-cairo-clock.Tpo -c -o test_interactive-test-cairo-clock.o `test -f 'test-cairo-clock.c' || echo '$(srcdir)/'`test-cairo-clock.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-cairo-clock.Tpo $(DEPDIR)/test_interactive-test-cairo-clock.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cairo-clock.c' object='test_interactive-test-cairo-clock.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-cairo-clock.o `test -f 'test-cairo-clock.c' || echo '$(srcdir)/'`test-cairo-clock.c + +test_interactive-test-cairo-clock.obj: test-cairo-clock.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-cairo-clock.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-cairo-clock.Tpo -c -o test_interactive-test-cairo-clock.obj `if test -f 'test-cairo-clock.c'; then $(CYGPATH_W) 'test-cairo-clock.c'; else $(CYGPATH_W) '$(srcdir)/test-cairo-clock.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-cairo-clock.Tpo $(DEPDIR)/test_interactive-test-cairo-clock.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cairo-clock.c' object='test_interactive-test-cairo-clock.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-cairo-clock.obj `if test -f 'test-cairo-clock.c'; then $(CYGPATH_W) 'test-cairo-clock.c'; else $(CYGPATH_W) '$(srcdir)/test-cairo-clock.c'; fi` + +test_interactive-test-cairo-flowers.o: test-cairo-flowers.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-cairo-flowers.o -MD -MP -MF $(DEPDIR)/test_interactive-test-cairo-flowers.Tpo -c -o test_interactive-test-cairo-flowers.o `test -f 'test-cairo-flowers.c' || echo '$(srcdir)/'`test-cairo-flowers.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-cairo-flowers.Tpo $(DEPDIR)/test_interactive-test-cairo-flowers.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cairo-flowers.c' object='test_interactive-test-cairo-flowers.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-cairo-flowers.o `test -f 'test-cairo-flowers.c' || echo '$(srcdir)/'`test-cairo-flowers.c + +test_interactive-test-cairo-flowers.obj: test-cairo-flowers.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-cairo-flowers.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-cairo-flowers.Tpo -c -o test_interactive-test-cairo-flowers.obj `if test -f 'test-cairo-flowers.c'; then $(CYGPATH_W) 'test-cairo-flowers.c'; else $(CYGPATH_W) '$(srcdir)/test-cairo-flowers.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-cairo-flowers.Tpo $(DEPDIR)/test_interactive-test-cairo-flowers.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cairo-flowers.c' object='test_interactive-test-cairo-flowers.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-cairo-flowers.obj `if test -f 'test-cairo-flowers.c'; then $(CYGPATH_W) 'test-cairo-flowers.c'; else $(CYGPATH_W) '$(srcdir)/test-cairo-flowers.c'; fi` + +test_interactive-test-cogl-vertex-buffer.o: test-cogl-vertex-buffer.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-cogl-vertex-buffer.o -MD -MP -MF $(DEPDIR)/test_interactive-test-cogl-vertex-buffer.Tpo -c -o test_interactive-test-cogl-vertex-buffer.o `test -f 'test-cogl-vertex-buffer.c' || echo '$(srcdir)/'`test-cogl-vertex-buffer.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-cogl-vertex-buffer.Tpo $(DEPDIR)/test_interactive-test-cogl-vertex-buffer.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cogl-vertex-buffer.c' object='test_interactive-test-cogl-vertex-buffer.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-cogl-vertex-buffer.o `test -f 'test-cogl-vertex-buffer.c' || echo '$(srcdir)/'`test-cogl-vertex-buffer.c + +test_interactive-test-cogl-vertex-buffer.obj: test-cogl-vertex-buffer.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-cogl-vertex-buffer.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-cogl-vertex-buffer.Tpo -c -o test_interactive-test-cogl-vertex-buffer.obj `if test -f 'test-cogl-vertex-buffer.c'; then $(CYGPATH_W) 'test-cogl-vertex-buffer.c'; else $(CYGPATH_W) '$(srcdir)/test-cogl-vertex-buffer.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-cogl-vertex-buffer.Tpo $(DEPDIR)/test_interactive-test-cogl-vertex-buffer.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cogl-vertex-buffer.c' object='test_interactive-test-cogl-vertex-buffer.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-cogl-vertex-buffer.obj `if test -f 'test-cogl-vertex-buffer.c'; then $(CYGPATH_W) 'test-cogl-vertex-buffer.c'; else $(CYGPATH_W) '$(srcdir)/test-cogl-vertex-buffer.c'; fi` + +test_interactive-test-stage-sizing.o: test-stage-sizing.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-stage-sizing.o -MD -MP -MF $(DEPDIR)/test_interactive-test-stage-sizing.Tpo -c -o test_interactive-test-stage-sizing.o `test -f 'test-stage-sizing.c' || echo '$(srcdir)/'`test-stage-sizing.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-stage-sizing.Tpo $(DEPDIR)/test_interactive-test-stage-sizing.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-stage-sizing.c' object='test_interactive-test-stage-sizing.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-stage-sizing.o `test -f 'test-stage-sizing.c' || echo '$(srcdir)/'`test-stage-sizing.c + +test_interactive-test-stage-sizing.obj: test-stage-sizing.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-stage-sizing.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-stage-sizing.Tpo -c -o test_interactive-test-stage-sizing.obj `if test -f 'test-stage-sizing.c'; then $(CYGPATH_W) 'test-stage-sizing.c'; else $(CYGPATH_W) '$(srcdir)/test-stage-sizing.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-stage-sizing.Tpo $(DEPDIR)/test_interactive-test-stage-sizing.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-stage-sizing.c' object='test_interactive-test-stage-sizing.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-stage-sizing.obj `if test -f 'test-stage-sizing.c'; then $(CYGPATH_W) 'test-stage-sizing.c'; else $(CYGPATH_W) '$(srcdir)/test-stage-sizing.c'; fi` + +test_interactive-test-scrolling.o: test-scrolling.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-scrolling.o -MD -MP -MF $(DEPDIR)/test_interactive-test-scrolling.Tpo -c -o test_interactive-test-scrolling.o `test -f 'test-scrolling.c' || echo '$(srcdir)/'`test-scrolling.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-scrolling.Tpo $(DEPDIR)/test_interactive-test-scrolling.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-scrolling.c' object='test_interactive-test-scrolling.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-scrolling.o `test -f 'test-scrolling.c' || echo '$(srcdir)/'`test-scrolling.c + +test_interactive-test-scrolling.obj: test-scrolling.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-scrolling.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-scrolling.Tpo -c -o test_interactive-test-scrolling.obj `if test -f 'test-scrolling.c'; then $(CYGPATH_W) 'test-scrolling.c'; else $(CYGPATH_W) '$(srcdir)/test-scrolling.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-scrolling.Tpo $(DEPDIR)/test_interactive-test-scrolling.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-scrolling.c' object='test_interactive-test-scrolling.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-scrolling.obj `if test -f 'test-scrolling.c'; then $(CYGPATH_W) 'test-scrolling.c'; else $(CYGPATH_W) '$(srcdir)/test-scrolling.c'; fi` + +test_interactive-test-swipe-action.o: test-swipe-action.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-swipe-action.o -MD -MP -MF $(DEPDIR)/test_interactive-test-swipe-action.Tpo -c -o test_interactive-test-swipe-action.o `test -f 'test-swipe-action.c' || echo '$(srcdir)/'`test-swipe-action.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-swipe-action.Tpo $(DEPDIR)/test_interactive-test-swipe-action.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-swipe-action.c' object='test_interactive-test-swipe-action.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-swipe-action.o `test -f 'test-swipe-action.c' || echo '$(srcdir)/'`test-swipe-action.c + +test_interactive-test-swipe-action.obj: test-swipe-action.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-swipe-action.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-swipe-action.Tpo -c -o test_interactive-test-swipe-action.obj `if test -f 'test-swipe-action.c'; then $(CYGPATH_W) 'test-swipe-action.c'; else $(CYGPATH_W) '$(srcdir)/test-swipe-action.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-swipe-action.Tpo $(DEPDIR)/test_interactive-test-swipe-action.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-swipe-action.c' object='test_interactive-test-swipe-action.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-swipe-action.obj `if test -f 'test-swipe-action.c'; then $(CYGPATH_W) 'test-swipe-action.c'; else $(CYGPATH_W) '$(srcdir)/test-swipe-action.c'; fi` + +test_interactive-test-cogl-point-sprites.o: test-cogl-point-sprites.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-cogl-point-sprites.o -MD -MP -MF $(DEPDIR)/test_interactive-test-cogl-point-sprites.Tpo -c -o test_interactive-test-cogl-point-sprites.o `test -f 'test-cogl-point-sprites.c' || echo '$(srcdir)/'`test-cogl-point-sprites.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-cogl-point-sprites.Tpo $(DEPDIR)/test_interactive-test-cogl-point-sprites.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cogl-point-sprites.c' object='test_interactive-test-cogl-point-sprites.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-cogl-point-sprites.o `test -f 'test-cogl-point-sprites.c' || echo '$(srcdir)/'`test-cogl-point-sprites.c + +test_interactive-test-cogl-point-sprites.obj: test-cogl-point-sprites.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-cogl-point-sprites.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-cogl-point-sprites.Tpo -c -o test_interactive-test-cogl-point-sprites.obj `if test -f 'test-cogl-point-sprites.c'; then $(CYGPATH_W) 'test-cogl-point-sprites.c'; else $(CYGPATH_W) '$(srcdir)/test-cogl-point-sprites.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-cogl-point-sprites.Tpo $(DEPDIR)/test_interactive-test-cogl-point-sprites.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-cogl-point-sprites.c' object='test_interactive-test-cogl-point-sprites.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-cogl-point-sprites.obj `if test -f 'test-cogl-point-sprites.c'; then $(CYGPATH_W) 'test-cogl-point-sprites.c'; else $(CYGPATH_W) '$(srcdir)/test-cogl-point-sprites.c'; fi` + +test_interactive-test-table-layout.o: test-table-layout.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-table-layout.o -MD -MP -MF $(DEPDIR)/test_interactive-test-table-layout.Tpo -c -o test_interactive-test-table-layout.o `test -f 'test-table-layout.c' || echo '$(srcdir)/'`test-table-layout.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-table-layout.Tpo $(DEPDIR)/test_interactive-test-table-layout.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-table-layout.c' object='test_interactive-test-table-layout.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-table-layout.o `test -f 'test-table-layout.c' || echo '$(srcdir)/'`test-table-layout.c + +test_interactive-test-table-layout.obj: test-table-layout.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-table-layout.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-table-layout.Tpo -c -o test_interactive-test-table-layout.obj `if test -f 'test-table-layout.c'; then $(CYGPATH_W) 'test-table-layout.c'; else $(CYGPATH_W) '$(srcdir)/test-table-layout.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-table-layout.Tpo $(DEPDIR)/test_interactive-test-table-layout.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-table-layout.c' object='test_interactive-test-table-layout.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-table-layout.obj `if test -f 'test-table-layout.c'; then $(CYGPATH_W) 'test-table-layout.c'; else $(CYGPATH_W) '$(srcdir)/test-table-layout.c'; fi` + +test_interactive-test-path-constraint.o: test-path-constraint.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-path-constraint.o -MD -MP -MF $(DEPDIR)/test_interactive-test-path-constraint.Tpo -c -o test_interactive-test-path-constraint.o `test -f 'test-path-constraint.c' || echo '$(srcdir)/'`test-path-constraint.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-path-constraint.Tpo $(DEPDIR)/test_interactive-test-path-constraint.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-path-constraint.c' object='test_interactive-test-path-constraint.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-path-constraint.o `test -f 'test-path-constraint.c' || echo '$(srcdir)/'`test-path-constraint.c + +test_interactive-test-path-constraint.obj: test-path-constraint.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-path-constraint.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-path-constraint.Tpo -c -o test_interactive-test-path-constraint.obj `if test -f 'test-path-constraint.c'; then $(CYGPATH_W) 'test-path-constraint.c'; else $(CYGPATH_W) '$(srcdir)/test-path-constraint.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-path-constraint.Tpo $(DEPDIR)/test_interactive-test-path-constraint.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-path-constraint.c' object='test_interactive-test-path-constraint.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-path-constraint.obj `if test -f 'test-path-constraint.c'; then $(CYGPATH_W) 'test-path-constraint.c'; else $(CYGPATH_W) '$(srcdir)/test-path-constraint.c'; fi` + +test_interactive-test-state-script.o: test-state-script.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-state-script.o -MD -MP -MF $(DEPDIR)/test_interactive-test-state-script.Tpo -c -o test_interactive-test-state-script.o `test -f 'test-state-script.c' || echo '$(srcdir)/'`test-state-script.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-state-script.Tpo $(DEPDIR)/test_interactive-test-state-script.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-state-script.c' object='test_interactive-test-state-script.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-state-script.o `test -f 'test-state-script.c' || echo '$(srcdir)/'`test-state-script.c + +test_interactive-test-state-script.obj: test-state-script.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-state-script.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-state-script.Tpo -c -o test_interactive-test-state-script.obj `if test -f 'test-state-script.c'; then $(CYGPATH_W) 'test-state-script.c'; else $(CYGPATH_W) '$(srcdir)/test-state-script.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-state-script.Tpo $(DEPDIR)/test_interactive-test-state-script.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-state-script.c' object='test_interactive-test-state-script.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-state-script.obj `if test -f 'test-state-script.c'; then $(CYGPATH_W) 'test-state-script.c'; else $(CYGPATH_W) '$(srcdir)/test-state-script.c'; fi` + +test_interactive-test-devices.o: test-devices.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-devices.o -MD -MP -MF $(DEPDIR)/test_interactive-test-devices.Tpo -c -o test_interactive-test-devices.o `test -f 'test-devices.c' || echo '$(srcdir)/'`test-devices.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-devices.Tpo $(DEPDIR)/test_interactive-test-devices.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-devices.c' object='test_interactive-test-devices.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-devices.o `test -f 'test-devices.c' || echo '$(srcdir)/'`test-devices.c + +test_interactive-test-devices.obj: test-devices.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-devices.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-devices.Tpo -c -o test_interactive-test-devices.obj `if test -f 'test-devices.c'; then $(CYGPATH_W) 'test-devices.c'; else $(CYGPATH_W) '$(srcdir)/test-devices.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-devices.Tpo $(DEPDIR)/test_interactive-test-devices.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-devices.c' object='test_interactive-test-devices.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-devices.obj `if test -f 'test-devices.c'; then $(CYGPATH_W) 'test-devices.c'; else $(CYGPATH_W) '$(srcdir)/test-devices.c'; fi` + +test_interactive-test-content.o: test-content.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-content.o -MD -MP -MF $(DEPDIR)/test_interactive-test-content.Tpo -c -o test_interactive-test-content.o `test -f 'test-content.c' || echo '$(srcdir)/'`test-content.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-content.Tpo $(DEPDIR)/test_interactive-test-content.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-content.c' object='test_interactive-test-content.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-content.o `test -f 'test-content.c' || echo '$(srcdir)/'`test-content.c + +test_interactive-test-content.obj: test-content.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-content.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-content.Tpo -c -o test_interactive-test-content.obj `if test -f 'test-content.c'; then $(CYGPATH_W) 'test-content.c'; else $(CYGPATH_W) '$(srcdir)/test-content.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-content.Tpo $(DEPDIR)/test_interactive-test-content.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-content.c' object='test_interactive-test-content.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-content.obj `if test -f 'test-content.c'; then $(CYGPATH_W) 'test-content.c'; else $(CYGPATH_W) '$(srcdir)/test-content.c'; fi` + +test_interactive-test-keyframe-transition.o: test-keyframe-transition.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-keyframe-transition.o -MD -MP -MF $(DEPDIR)/test_interactive-test-keyframe-transition.Tpo -c -o test_interactive-test-keyframe-transition.o `test -f 'test-keyframe-transition.c' || echo '$(srcdir)/'`test-keyframe-transition.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-keyframe-transition.Tpo $(DEPDIR)/test_interactive-test-keyframe-transition.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-keyframe-transition.c' object='test_interactive-test-keyframe-transition.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-keyframe-transition.o `test -f 'test-keyframe-transition.c' || echo '$(srcdir)/'`test-keyframe-transition.c + +test_interactive-test-keyframe-transition.obj: test-keyframe-transition.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-keyframe-transition.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-keyframe-transition.Tpo -c -o test_interactive-test-keyframe-transition.obj `if test -f 'test-keyframe-transition.c'; then $(CYGPATH_W) 'test-keyframe-transition.c'; else $(CYGPATH_W) '$(srcdir)/test-keyframe-transition.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-keyframe-transition.Tpo $(DEPDIR)/test_interactive-test-keyframe-transition.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-keyframe-transition.c' object='test_interactive-test-keyframe-transition.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-keyframe-transition.obj `if test -f 'test-keyframe-transition.c'; then $(CYGPATH_W) 'test-keyframe-transition.c'; else $(CYGPATH_W) '$(srcdir)/test-keyframe-transition.c'; fi` + +test_interactive-test-bind-constraint.o: test-bind-constraint.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-bind-constraint.o -MD -MP -MF $(DEPDIR)/test_interactive-test-bind-constraint.Tpo -c -o test_interactive-test-bind-constraint.o `test -f 'test-bind-constraint.c' || echo '$(srcdir)/'`test-bind-constraint.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-bind-constraint.Tpo $(DEPDIR)/test_interactive-test-bind-constraint.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-bind-constraint.c' object='test_interactive-test-bind-constraint.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-bind-constraint.o `test -f 'test-bind-constraint.c' || echo '$(srcdir)/'`test-bind-constraint.c + +test_interactive-test-bind-constraint.obj: test-bind-constraint.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-bind-constraint.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-bind-constraint.Tpo -c -o test_interactive-test-bind-constraint.obj `if test -f 'test-bind-constraint.c'; then $(CYGPATH_W) 'test-bind-constraint.c'; else $(CYGPATH_W) '$(srcdir)/test-bind-constraint.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-bind-constraint.Tpo $(DEPDIR)/test_interactive-test-bind-constraint.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-bind-constraint.c' object='test_interactive-test-bind-constraint.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-bind-constraint.obj `if test -f 'test-bind-constraint.c'; then $(CYGPATH_W) 'test-bind-constraint.c'; else $(CYGPATH_W) '$(srcdir)/test-bind-constraint.c'; fi` + +test_interactive-test-touch-events.o: test-touch-events.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-touch-events.o -MD -MP -MF $(DEPDIR)/test_interactive-test-touch-events.Tpo -c -o test_interactive-test-touch-events.o `test -f 'test-touch-events.c' || echo '$(srcdir)/'`test-touch-events.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-touch-events.Tpo $(DEPDIR)/test_interactive-test-touch-events.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-touch-events.c' object='test_interactive-test-touch-events.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-touch-events.o `test -f 'test-touch-events.c' || echo '$(srcdir)/'`test-touch-events.c + +test_interactive-test-touch-events.obj: test-touch-events.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-touch-events.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-touch-events.Tpo -c -o test_interactive-test-touch-events.obj `if test -f 'test-touch-events.c'; then $(CYGPATH_W) 'test-touch-events.c'; else $(CYGPATH_W) '$(srcdir)/test-touch-events.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-touch-events.Tpo $(DEPDIR)/test_interactive-test-touch-events.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-touch-events.c' object='test_interactive-test-touch-events.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-touch-events.obj `if test -f 'test-touch-events.c'; then $(CYGPATH_W) 'test-touch-events.c'; else $(CYGPATH_W) '$(srcdir)/test-touch-events.c'; fi` + +test_interactive-test-rotate-zoom.o: test-rotate-zoom.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-rotate-zoom.o -MD -MP -MF $(DEPDIR)/test_interactive-test-rotate-zoom.Tpo -c -o test_interactive-test-rotate-zoom.o `test -f 'test-rotate-zoom.c' || echo '$(srcdir)/'`test-rotate-zoom.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-rotate-zoom.Tpo $(DEPDIR)/test_interactive-test-rotate-zoom.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-rotate-zoom.c' object='test_interactive-test-rotate-zoom.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-rotate-zoom.o `test -f 'test-rotate-zoom.c' || echo '$(srcdir)/'`test-rotate-zoom.c + +test_interactive-test-rotate-zoom.obj: test-rotate-zoom.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-rotate-zoom.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-rotate-zoom.Tpo -c -o test_interactive-test-rotate-zoom.obj `if test -f 'test-rotate-zoom.c'; then $(CYGPATH_W) 'test-rotate-zoom.c'; else $(CYGPATH_W) '$(srcdir)/test-rotate-zoom.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-rotate-zoom.Tpo $(DEPDIR)/test_interactive-test-rotate-zoom.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-rotate-zoom.c' object='test_interactive-test-rotate-zoom.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-rotate-zoom.obj `if test -f 'test-rotate-zoom.c'; then $(CYGPATH_W) 'test-rotate-zoom.c'; else $(CYGPATH_W) '$(srcdir)/test-rotate-zoom.c'; fi` + +test_interactive-test-pixmap.o: test-pixmap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-pixmap.o -MD -MP -MF $(DEPDIR)/test_interactive-test-pixmap.Tpo -c -o test_interactive-test-pixmap.o `test -f 'test-pixmap.c' || echo '$(srcdir)/'`test-pixmap.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-pixmap.Tpo $(DEPDIR)/test_interactive-test-pixmap.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-pixmap.c' object='test_interactive-test-pixmap.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-pixmap.o `test -f 'test-pixmap.c' || echo '$(srcdir)/'`test-pixmap.c + +test_interactive-test-pixmap.obj: test-pixmap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-pixmap.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-pixmap.Tpo -c -o test_interactive-test-pixmap.obj `if test -f 'test-pixmap.c'; then $(CYGPATH_W) 'test-pixmap.c'; else $(CYGPATH_W) '$(srcdir)/test-pixmap.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-pixmap.Tpo $(DEPDIR)/test_interactive-test-pixmap.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-pixmap.c' object='test_interactive-test-pixmap.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-pixmap.obj `if test -f 'test-pixmap.c'; then $(CYGPATH_W) 'test-pixmap.c'; else $(CYGPATH_W) '$(srcdir)/test-pixmap.c'; fi` + +test_interactive-test-image.o: test-image.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-image.o -MD -MP -MF $(DEPDIR)/test_interactive-test-image.Tpo -c -o test_interactive-test-image.o `test -f 'test-image.c' || echo '$(srcdir)/'`test-image.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-image.Tpo $(DEPDIR)/test_interactive-test-image.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-image.c' object='test_interactive-test-image.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-image.o `test -f 'test-image.c' || echo '$(srcdir)/'`test-image.c + +test_interactive-test-image.obj: test-image.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -MT test_interactive-test-image.obj -MD -MP -MF $(DEPDIR)/test_interactive-test-image.Tpo -c -o test_interactive-test-image.obj `if test -f 'test-image.c'; then $(CYGPATH_W) 'test-image.c'; else $(CYGPATH_W) '$(srcdir)/test-image.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_interactive-test-image.Tpo $(DEPDIR)/test_interactive-test-image.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-image.c' object='test_interactive-test-image.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_interactive_CPPFLAGS) $(CPPFLAGS) $(test_interactive_CFLAGS) $(CFLAGS) -c -o test_interactive-test-image.obj `if test -f 'test-image.c'; then $(CYGPATH_W) 'test-image.c'; else $(CYGPATH_W) '$(srcdir)/test-image.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(check_SCRIPTS) +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile +installdirs: +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-checkPROGRAMS clean-generic clean-libtool clean-local \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: all check check-am install install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ + clean-checkPROGRAMS clean-generic clean-libtool clean-local \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# For convenience, this provides a way to easily run individual unit tests: +wrappers: stamp-test-interactive + @true + +stamp-test-interactive: Makefile + @wrapper=$(abs_builddir)/wrapper.sh ; \ + chmod +x $$wrapper && \ + for i in $(UNIT_TESTS); \ + do \ + test_bin=$${i%*.c} ; \ + echo " GEN $$test_bin" ; \ + ( echo "#!/bin/sh" ; \ + echo "$$wrapper $$test_bin \$$@" \ + ) > $$test_bin$(SHEXT) ; \ + chmod +x $$test_bin$(SHEXT) ; \ + done \ + && echo timestamp > $(@F) + +test-unit-names.h: stamp-test-unit-names + @true + +stamp-test-unit-names: Makefile + @( echo "/* ** This file is autogenerated. Do not edit. ** */" ; \ + echo "" ; \ + echo "const char *test_unit_names[] = {" ) > test-unit-names.h ; \ + for i in $(UNIT_TESTS); \ + do \ + test_bin=$${i%*.c} ; \ + echo " \"$$test_bin\"," >> test-unit-names.h ; \ + done \ + && echo "};" >> test-unit-names.h \ + && echo timestamp > $(@F) + +clean-wrappers: + @for i in $(UNIT_TESTS); \ + do \ + test_bin=$${i%*.c} ; \ + echo " RM $$test_bin"; \ + rm -f $$test_bin$(SHEXT); \ + done \ + && rm -f stamp-test-unit-names \ + && rm -f stamp-test-interactive + +.PHONY: wrappers clean-wrappers + +clean-local: clean-wrappers + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/clutter/tests/interactive/redhand.png b/clutter/tests/interactive/redhand.png new file mode 100644 index 0000000000000000000000000000000000000000..c07d8acd33d54996512f6e2b6ca4d17b5ffc4f20 GIT binary patch literal 8250 zcmZ`;Wmr_v)*gE3p#+8+Lb^c&q=pb2x^?Iv#L#Gna z;9~}DGo8|sclaT%M4lM0sJI~^@yle1Nun*Qtas*mx9*&F^7#69TJZ3qQ-xoJo%DX| znaMt;`2V;vDHOLbxeD%3@fWQ(yl9B0{<|x|zEzBir7;y0eIx5!CM!yB=ABC^n0Zqi zULG=FeZ+x^fuZI}U%)~*L0t=1xN;I9lps7>s{tfzeLxhvh7rStBEoj>Xy*5;3&sCx z4C0EZ2}Qzg*pggWz|2@mv*DQiw{83&9ld&Dk*Q5sh^U0i+KJ$MwOg)&9U3ckTWL-! zXP$!k4!uMjM3D|cAY;jf4?$~{rG;QEuO2dZzisK(*sR7Cn5MHmV(flByu^`IbMGv; zTjwp9{^Z`Q&xp2;Sj{%~!fWmZ!zPn6SoFex&gX6qSE0uYcg?1d2*FjLyT9C`I2})u z>!QHLpuxr0fH&8KO(}L!Q8zv<%e?)KfVl5@&G{s4l8)qLcwIf^+|7cy^BVWMztY3d zB`K?*fL|c-f$?4&uWCZX))U9MaGk4Rb?(AO7mYhtx-_HS+~mrKD7E^e#&W9|9}d(> zeP~OvNM8^;O3IZq{AG;GLlhAv#G0eA*#d$()=-BawhU46&!nza-E9-W@$n#h{V4D)ibK`(ZFg>gnw`Nn*^ zuoX2v5ygJ~tPVBLNC{I_O{BYe3%kWAW(9dp0=8@rFtBeB)(tJ9`h zUp^=y;l6W5wV-1A0p=`FM9s~`N;FTy2%GBtg%Ck^m&1)7e#*yhvB-|k<_rcZKSHyEn2l z2na;dnMP8;oXDj*z})umle9{f2;S+dRk8KgVG()1y29)wyo;TEgeE6fSKsXCEJrYX zjd?ogk~aq1t@$?UFvik!t$JtVn#OI(1=m2_g8Xb2Bu#IYu>?cmCO9}442uC2V{UCY zkevs^-j7|E$1e_xrF;-aPrl^k#$OCQK8THN_?czdZ(M`(UMc&tKqm!QA@>Gt3QrUD?r?em>(C;rw6K{*ceA41RYA`F9AMIlP8sFo1Q#Gi)rWmXo zL87$Q;AAk>o2Nv0ve5S2alR1^5uP41sOdv^GMxQYn#@(IB?8dXtPP5@6fEFUD@Nn) z`;*PM9|IH~MUV-VWen$b7(AZ}zR?!*1j+sV@TgxiQS4CXBZ(cmT6`FN2i{pxUu8Di?SJMK@?*1P81RJZ%*8=SOX|B2s)2Zf`IpBw5R zkAD>nK8?Gdww>f1x1b6}Tpm$dWUsD2dlhBOue1n{S@szc;<3c{U zN??MjcHF0I=tq43%kyUP!WPMl@vv?0{<|YpE;PG15gZgLvl(DD#b0t))Eipse(f6_ zY;l1Oo*oZTdg5m?zqm6nkeiyS1fY-UT+77j((J6*R8o=>A9co9cLF$`!6n(Xn>gN0(nM=}@Sa$119Orcg|TqJ{3UvkA3=5>DyxyAgsOnw@Pyc*`HqUKdV= zVM||E!|R9JEQOiSht5f#T*p=;EgK~Sw)&N;^B{^RI;vJLbB1^-s)|EOYR34tEgd9c zbVMIe&3xh4tBPo^Kl$sE>R>!&ekI3;jJ%U_s@EPp$D8UydOFh*J}ZsRRBbgldu!R~ zVDIjTjNI1_!+rbkw;+P5l%S5O)yR?V$u>ut4kQi5N`e`-{Ub9I7K08Vlmk~CyF@bs za9Ig6g*PGHaaIVrs8Bp$!~d+1q4WAL|N8jCaaNYy9o(r0_04#D)w<1iN%}U)81uaj zU?2b40e=0L*Z#FK()S-t@>jutv6fV7Ak0lFVZPz5W@+E4dN3*X7h}7z@Vbni6Y2&^ z7k7fR2y(~d4o*-RX!H>O{5nA{KhSw2P~fY}y?up}Qe+$t7!4QqC+f0-kQBvc{Qtm~ z|Fs$VuS+C=X?e)EyFzs>|MFLP5A7Qr|vfCX#V^e)YAAkCiF<0=5*=t3f{>>`>xJ5HC zJi?WYVk*rHVVr^p(mAC}xG2;nMVP57`$ zNg;3$HU=ub@VPG+&ZGBoK9Ydnj~W?8hJTS7|GkmBv8ps~`X%y;$577ayNiRUo zi34M(cpZ{cJ~9M^&BmU4`SmS$dxEfCNNDupB2wppz36CDtHRnAzF%;#e|R`cwlezO zlZu#%su-cFa9P!nEBX-U(biVL?*TY?)pI9*HXDYLI)RwP(!a}=30$5mfA6v&0uK=r zr(q7oWwsuL_5AomY^F^Xb^f>ablqByUiR;(^@>m=MTos9c>5RL%7{#KszUg5CZ!*1 zjGYk;OJA%)kJm_!j4TrXD4h*_&p#lYNEkyo#b_25#ytBW^}(n57k)do!2{Ibw|l1W-(&uV^*vi0yFNk~xyD#RQqv8V|4rd6*cneWJQL|uZA}Q81?JGdubpjg|>Ed==$Yb zr1Af0@ZpjCa>*Xq`oyoM2{}&-%x2C~$9*h7E6f}ZnQb@J*w`O-=Gmyq+#b`ckC>IF z&(tL}IV25|B*x=0R%Z;n{RZ>JjxFLKH>gyMc)VE6^H_oJ{OHqA#@N;2w`QUP8f^FT zbLEkIwtA>U;`#Re$DNh87XlrM>+1tjxE?k*hxRk%ZFhHmqD+Dzb*qyY+Z*9cm&arx zP6od;tVp!oFDlp>`Ao9U8(j`!<2Kq}wQ5jed#B4VKs7Z@GaqY?iEv5bY9}oO1*y!} zzf07jo)H)Djs&^dlA49q=5OgGk~magkKb>j@{f{ zUuIJ~J&DCNlewee3nyCXi+>CAeRh9V)gD#-jd87wqv2PB30t`lMivPJuz8&c$mgq= za+d;<(4MrbpHUNKIfp0feeS6=J*;fl3kK!xm*^1BPFWd7hRvZhp-7P?BgH)UO`1iQ z2yYD9nU+k*mEI(lrqhg9*{^06$Y10c1LD#4%^Zwyxy|0_9Ac7F8soCA^xVe-{({JZwA9CMNRc9h6LWB9nP7ib+9n>Fhzc8&vk}#r~rG?YOS5 zgOsirL+P(y+CFEz+x!+!&3wg(Qc?uR$3tj|)VEXu1D0n>sRAUuL)@HsG2fh_3>8re zAD!8t#FBw0WN{=61h%3_G(Gaj;=fFOR|g8Mv(|RyCGf-cK+gF_;uH>z`OCx)vQ9}E zbYECmMlBCspkkpo9hGK#;k0mOYg9+UHTLmNDMUhb}m2B(CM zS0X1iHb3q3^2mH7B>K(jZ~+tzvzV&1KmX2Sf7#CpsW+LJn+ci~rMx)^b)I57py{za zf{)&vPE8ob%$iv9o1heKubAJ=2$%IA;?-(JmDY=9zL%m^W_%5PczssF*y^vW#2k}V zQj-oV9g}Ucki}l~LYMY&Ew)m35J6G90_`C+g?)uK6V}$t>*+$`A`ax{S_YXY-^mhVNik6TLV{zNV> zf&d7Xkf&jVPEf2O1j65a&cPVk&yab(PwJu-zgl;?MQvU^;=C2ZY}JWL>AFzrKUVQH z#=U8MQG+RT+S6`p&)wnBGPy8++J!?X34hb>hn)J;@Z8_8m6bX>oD3O5rwJoru=Sh> zO1?Vl`=Ir5Q-^Z~o6@rGnSrDX*YEleKE|MQp2)TySkU3&0T^G~b#!8Ct?S487wkz2 z-UjMVacetnbjE};NTEGekT)JR$r?AQZQfkl$4B&~-JXW!a%R4bmcMb>*o=JaSp90O z6#;*ZN-5ysf&(0tWa?#M-&51O6W!nQ=8qp^pX?5p@lKfW%2P_C-G7%=y(q2n>(}5> z(=a$841Q5%KHsZDXTGxHZum!wa$+m~eCRRBoWqY7Unfp?sCY(ZQ+R>7AcPTT?BNz&om{7<(8IyejeLYbH5r|z@pnX`c9vs

>E{@fRQy3@FN~J}p2Nt@97Uf0{oU|re+3NWF8_n@k&H~DCY}MkY^70m_tQ9( zpI)+pugQ9}0C$Vc(}5rlMPw$`wN42wf?G#7CE8<@z!lpyf^hgE(FF!%Z@ z&7z=RMR_0w&ph{%N6)m67jx?&i{6;e~N(ZJx53FKH?b4n|0*4(>n7YSDE}g1jH6}UBS)c8g_pXLG&_-(Am!}=AHQfLCxxF%1u6-ehk_5-_}0|eRNSS zpn64#*Df=d_ZR-XgJK4TYgd}Gof9v&R3L$Gv)t5T*6Rqu=02Atn!W{NTG|fD7ola4 z%PTpK-vG{&JA#(&l4XXc91(tYGu(w_bWzm_0ZGo-p zE+UhO^`}Xix%-u72M$Z-DQ6;i{}hnHV}5GMBz{Q}hew|I>ruZeO>lIr@*KnQ)zlO_ zq~Aa!JaX5QA6u?aF~*^)+T}mn43@W?{V*|Is! zS+N=N+g*CL_7|=!RnUORDevw^*Xqvz=eSB5kZX3pGphmz#y4zFVAcs zTdiq)pjQ-{fhL{*@F>)-%;3Ovs&b3*={sYKWVyw@*kYOBPlJ6!*wn{Xh!Rrfbpnuf zMjDX!yZe6y4bYKwX9YnI=LH(MfB-D+y%Z>@XYl=Mv6$LIaUO|d$wb#l(|QW6c7#JH zWhXheqtjo_4J`FOSf!%~h4A^HZ|^ktOg%qWmj~yvht;@Oxmr`lh82 zTQG!!NGogP%#aClLH1cy8~ZDtaP26-82g=`@Cp%n;Vj!BwxXxeG2(A z3V8xRdQJYR%vE6Ss{lDxRv7#B>V;+Q`mM3tujW57m&cd(skB$M!ujeMg?}XI-!Bus zz-G3lV`fX!xsoavSNB1t+lBqs`4s)?+NJDF!p!(H37{?_^cu#pd9$Hz5L|7VRLFGw zbzQEJ#w;;nAX_tNXt&?gFin@9BMVj4AM@XXYQ!)S2fk|N5uHkd90@q7SndsE|JKn{ zJUEa`)0C-souRb&cxm}(;=?GWF&{k|Zfzl}A_pGC2#MS8a0|q=?TZ(3V-$YC zTg@Guq}!?wWaQIU=w|P5MUiJDQMU$`kKjMJg_Xb8K?MZZ%1yZj4<`XC<`Hz|oz~`j zWVS`gbnC%_pzUYiMf3LOAr)) zSAMqMp{da(TFL}U7yZ|1Qv8MrFOh=>kFTZs zT=PT4j{(CiXK@0lr5=@+~ZslHXq>#4caPBItw@a2&oZ`sjx-vTcG+WM_NiTwXYFIfvKMHug zD3kaqTi0BA)YJjj(1 zAO+4n00#z%Krj1K@&96A&}63kPXD*MBFtP*8)(GU0Z~fwR>TYy+?8d3MnZ+fz9I6H5Y{aq!~(yLZ}w=8TmAr&I*(*Kq=bPnhSi zusnhtx#xS`NF~+5TU!ud)_Ty8TIvw>T$ey4oTH?~_^jmddYdq}HFtkVEbcc`4U_-#lZFa-+IAI1Z2|KJeQmhP$HT zy-1YeGa`jQKx)ZY1fW!ez+yz5?p!;G!5XaeYd=aHycF90TAN3s#sDbt^{u0 zF*a*$&zqu8E5~z3v;5xjE*1}>e|UYKxBEwXJiq8z(c2fi^vB-Y{0mLzxp7KUATKl9 zKn}iV(%>mc$mi^X(u|ryTz$KdTy8$%iLI^TW_OI!=H_f%EKRRccdg|ye#I~2LTl2G&U$$lO9 zi>afv$I)I&I)@nlt(&(f@^2e;kXh?@AO3GFr|z7{`F!>&kP(PyxW%hU^o&fNw>>FS z+>(&1zzm-`3q-S9?6RzdLj@uSGe5|(@a^YyM8YyTP(<)wZ8K^99bQHt+!r5cJjHq8 zce1Xm_iU&hkbf#g*c!io7UZbnkI;smuHr9=B+_w`b%|XPCw%6_#L_1P_pa>UO+kCF zVpflgl)>-WW>h_F2elCUtf&~Q1F4JBw6Z>Wo^sDMvre64onZNX8c>y&z6ZWFmj7Zv z4uv?pr`f^`BL+*5T<(eZg*?tTCcQNg5Fwbkc0Oz6rwCVpC=w!!`Slib*R>!R!QMAw zk67_C8m9I#TvSu68Juqer~II2N*aol@-LA8 E2il-`3jhEB literal 0 HcmV?d00001 diff --git a/clutter/tests/interactive/test-actors.c b/clutter/tests/interactive/test-actors.c new file mode 100644 index 0000000..aeed9cb --- /dev/null +++ b/clutter/tests/interactive/test-actors.c @@ -0,0 +1,316 @@ +#include + +#include +#include +#include +#include +#include + +#define NHANDS 6 + +typedef struct SuperOH +{ + ClutterActor **hand; + ClutterActor *bgtex; + ClutterActor *real_hand; + ClutterActor *group; + ClutterActor *stage; + + gint stage_width; + gint stage_height; + gfloat radius; + + ClutterBehaviour *scaler_1; + ClutterBehaviour *scaler_2; + ClutterTimeline *timeline; +} SuperOH; + +static gint n_hands = NHANDS; + +static GOptionEntry super_oh_entries[] = { + { + "num-hands", 'n', + 0, + G_OPTION_ARG_INT, &n_hands, + "Number of hands", "HANDS" + }, + { NULL } +}; + +static void +on_group_destroy (ClutterActor *actor, + SuperOH *oh) +{ + oh->group = NULL; +} + +static void +on_hand_destroy (ClutterActor *actor, + SuperOH *oh) +{ + int i; + + for (i = 0; i < n_hands; i++) + { + if (oh->hand[i] == actor) + oh->hand[i] = NULL; + } +} + +static gboolean +on_button_press_event (ClutterActor *actor, + ClutterEvent *event, + SuperOH *oh) +{ + gfloat x, y; + + clutter_event_get_coords (event, &x, &y); + + g_print ("*** button press event (button:%d) at %.2f, %.2f on %s ***\n", + clutter_event_get_button (event), + x, y, + clutter_actor_get_name (actor)); + + clutter_actor_hide (actor); + + return TRUE; +} + +static gboolean +input_cb (ClutterActor *stage, + ClutterEvent *event, + gpointer data) +{ + SuperOH *oh = data; + + if (event->type == CLUTTER_KEY_RELEASE) + { + g_print ("*** key press event (key:%c) ***\n", + clutter_event_get_key_symbol (event)); + + if (clutter_event_get_key_symbol (event) == CLUTTER_KEY_q) + { + clutter_main_quit (); + + return TRUE; + } + else if (clutter_event_get_key_symbol (event) == CLUTTER_KEY_r) + { + gint i; + + for (i = 0; i < n_hands; i++) + { + if (oh->hand[i] != NULL) + clutter_actor_show (oh->hand[i]); + } + + return TRUE; + } + } + + return FALSE; +} + +/* Timeline handler */ +static void +frame_cb (ClutterTimeline *timeline, + gint msecs, + gpointer data) +{ + SuperOH *oh = data; + gint i; + float rotation = clutter_timeline_get_progress (timeline) * 360.0f; + + /* Rotate everything clockwise about stage center*/ + if (oh->group != NULL) + clutter_actor_set_rotation (oh->group, + CLUTTER_Z_AXIS, + rotation, + oh->stage_width / 2, + oh->stage_height / 2, + 0); + + for (i = 0; i < n_hands; i++) + { + /* Rotate each hand around there centers - to get this we need + * to take into account any scaling. + */ + if (oh->hand[i] != NULL) + clutter_actor_set_rotation (oh->hand[i], + CLUTTER_Z_AXIS, + -6.0 * rotation, + 0, 0, 0); + } +} + +static void +stop_and_quit (ClutterActor *stage, + SuperOH *data) +{ + clutter_timeline_stop (data->timeline); + + clutter_main_quit (); +} + +static gdouble +my_sine_wave (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = clutter_alpha_get_timeline (alpha); + gdouble progress = clutter_timeline_get_progress (timeline); + + return sin (progress * G_PI); +} + +G_MODULE_EXPORT int +test_actors_main (int argc, char *argv[]) +{ + ClutterAlpha *alpha; + SuperOH *oh; + gint i; + GError *error; + ClutterActor *real_hand; + gchar *file; + + error = NULL; + + if (clutter_init_with_args (&argc, &argv, + NULL, + super_oh_entries, + NULL, + &error) != CLUTTER_INIT_SUCCESS) + { + g_warning ("Unable to initialise Clutter:\n%s", + error->message); + g_error_free (error); + + return EXIT_FAILURE; + } + + oh = g_new (SuperOH, 1); + + oh->stage = clutter_stage_new (); + clutter_actor_set_size (oh->stage, 800, 600); + clutter_actor_set_name (oh->stage, "Default Stage"); + clutter_actor_set_background_color (oh->stage, CLUTTER_COLOR_LightSkyBlue); + g_signal_connect (oh->stage, "destroy", G_CALLBACK (stop_and_quit), oh); + + clutter_stage_set_title (CLUTTER_STAGE (oh->stage), "Actors"); + clutter_stage_set_user_resizable (CLUTTER_STAGE (oh->stage), TRUE); + + /* Create a timeline to manage animation */ + oh->timeline = clutter_timeline_new (6000); + clutter_timeline_set_repeat_count (oh->timeline, -1); + + /* fire a callback for frame change */ + g_signal_connect (oh->timeline, "new-frame", G_CALLBACK (frame_cb), oh); + + /* Set up some behaviours to handle scaling */ + alpha = clutter_alpha_new_with_func (oh->timeline, my_sine_wave, NULL, NULL); + + oh->scaler_1 = clutter_behaviour_scale_new (alpha, 0.5, 0.5, 1.0, 1.0); + oh->scaler_2 = clutter_behaviour_scale_new (alpha, 1.0, 1.0, 0.5, 0.5); + + file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL); + real_hand = clutter_texture_new_from_file (file, &error); + if (real_hand == NULL) + g_error ("image load failed: %s", error->message); + + g_free (file); + + /* create a new actor to hold other actors */ + oh->group = clutter_actor_new (); + clutter_actor_set_layout_manager (oh->group, clutter_fixed_layout_new ()); + clutter_actor_set_name (oh->group, "Group"); + g_signal_connect (oh->group, "destroy", G_CALLBACK (on_group_destroy), oh); + clutter_actor_add_constraint (oh->group, clutter_align_constraint_new (oh->stage, CLUTTER_ALIGN_BOTH, 0.5)); + clutter_actor_add_constraint (oh->group, clutter_bind_constraint_new (oh->stage, CLUTTER_BIND_SIZE, 0.0f)); + + oh->hand = g_new (ClutterActor*, n_hands); + + oh->stage_width = clutter_actor_get_width (oh->stage); + oh->stage_height = clutter_actor_get_height (oh->stage); + oh->radius = (oh->stage_width + oh->stage_height) + / n_hands; + + for (i = 0; i < n_hands; i++) + { + gint x, y, w, h; + + if (i == 0) + { + oh->hand[i] = real_hand; + clutter_actor_set_name (oh->hand[i], "Real Hand"); + } + else + { + oh->hand[i] = clutter_clone_new (real_hand); + clutter_actor_set_name (oh->hand[i], "Clone Hand"); + } + + clutter_actor_set_reactive (oh->hand[i], TRUE); + + clutter_actor_set_size (oh->hand[i], 200, 213); + + /* Place around a circle */ + w = clutter_actor_get_width (oh->hand[i]); + h = clutter_actor_get_height (oh->hand[i]); + + x = oh->stage_width / 2 + + oh->radius + * cos (i * G_PI / (n_hands / 2)) + - w / 2; + + y = oh->stage_height / 2 + + oh->radius + * sin (i * G_PI / (n_hands / 2)) + - h / 2; + + clutter_actor_set_position (oh->hand[i], x, y); + + clutter_actor_move_anchor_point_from_gravity (oh->hand[i], + CLUTTER_GRAVITY_CENTER); + + /* Add to our group group */ + clutter_container_add_actor (CLUTTER_CONTAINER (oh->group), oh->hand[i]); + + g_signal_connect (oh->hand[i], "button-press-event", + G_CALLBACK (on_button_press_event), + oh); + + g_signal_connect (oh->hand[i], "destroy", + G_CALLBACK (on_hand_destroy), + oh); + + if (i % 2) + clutter_behaviour_apply (oh->scaler_1, oh->hand[i]); + else + clutter_behaviour_apply (oh->scaler_2, oh->hand[i]); + } + + /* Add the group to the stage */ + clutter_container_add_actor (CLUTTER_CONTAINER (oh->stage), oh->group); + + /* Show everying */ + clutter_actor_show (oh->stage); + + g_signal_connect (oh->stage, "key-release-event", + G_CALLBACK (input_cb), + oh); + + /* and start it */ + clutter_timeline_start (oh->timeline); + + clutter_main (); + + clutter_timeline_stop (oh->timeline); + + /* clean up */ + g_object_unref (oh->scaler_1); + g_object_unref (oh->scaler_2); + g_object_unref (oh->timeline); + g_free (oh->hand); + g_free (oh); + + return EXIT_SUCCESS; +} diff --git a/clutter/tests/interactive/test-animation.c b/clutter/tests/interactive/test-animation.c new file mode 100644 index 0000000..5d4aa4e --- /dev/null +++ b/clutter/tests/interactive/test-animation.c @@ -0,0 +1,126 @@ +#include +#include +#include + +static gboolean is_expanded = FALSE; + +static void +on_rect_transitions_completed (ClutterActor *actor) +{ + is_expanded = !is_expanded; + + g_print ("Animation complete\n"); + + clutter_actor_set_reactive (actor, TRUE); +} + +static void +on_clicked (ClutterClickAction *action, + ClutterActor *actor, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterAnimation *animation; + gfloat old_x, old_y, new_x, new_y; + gfloat old_width, old_height, new_width, new_height; + gdouble new_angle; + const ClutterColor *new_color; + guint8 new_opacity; + + clutter_actor_get_position (actor, &old_x, &old_y); + clutter_actor_get_size (actor, &old_width, &old_height); + + /* determine the final state of the animation depending on + * the state of the actor + */ + if (!is_expanded) + { + new_x = old_x - 100; + new_y = old_y - 100; + new_width = old_width + 200; + new_height = old_height + 200; + new_angle = 360.0; + + new_color = CLUTTER_COLOR_DarkScarletRed; + + new_opacity = 255; + } + else + { + new_x = old_x + 100; + new_y = old_y + 100; + new_width = old_width - 200; + new_height = old_height - 200; + new_angle = 0.0; + + new_color = CLUTTER_COLOR_LightOrange; + + new_opacity = 128; + } + + clutter_actor_save_easing_state (actor); + clutter_actor_set_easing_mode (actor, CLUTTER_EASE_IN_EXPO); + clutter_actor_set_easing_duration (actor, 2000); + + clutter_actor_set_position (actor, new_x, new_y); + clutter_actor_set_size (actor, new_width, new_height); + clutter_actor_set_background_color (actor, new_color); + clutter_actor_set_rotation_angle (actor, CLUTTER_Z_AXIS, new_angle); + clutter_actor_set_reactive (actor, FALSE); + + /* animate the opacity halfway through, with a different pacing */ + clutter_actor_save_easing_state (actor); + clutter_actor_set_easing_mode (actor, CLUTTER_LINEAR); + clutter_actor_set_easing_delay (actor, 1000); + clutter_actor_set_easing_duration (actor, 1000); + clutter_actor_set_opacity (actor, new_opacity); + clutter_actor_restore_easing_state (actor); + + clutter_actor_restore_easing_state (actor); +} + +G_MODULE_EXPORT int +test_animation_main (int argc, char *argv[]) +{ + ClutterActor *stage, *rect; + ClutterColor rect_color = { 0x44, 0xdd, 0x44, 0xff }; + ClutterAction *action; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + clutter_actor_set_background_color (stage, CLUTTER_COLOR_LightSkyBlue); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Animation"); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + rect = clutter_actor_new (); + clutter_actor_set_background_color (rect, CLUTTER_COLOR_LightOrange); + clutter_actor_add_child (stage, rect); + clutter_actor_set_size (rect, 50, 50); + clutter_actor_set_pivot_point (rect, .5f, .5f); + clutter_actor_set_translation (rect, -25, -25, 0); + clutter_actor_set_position (rect, + clutter_actor_get_width (stage) / 2, + clutter_actor_get_height (stage) / 2); + clutter_actor_set_opacity (rect, 128); + clutter_actor_set_reactive (rect, TRUE); + g_signal_connect (rect, "transitions-completed", + G_CALLBACK (on_rect_transitions_completed), + NULL); + + action = clutter_click_action_new (); + g_signal_connect (action, "clicked", G_CALLBACK (on_clicked), NULL); + clutter_actor_add_action_with_name (rect, "click", action); + + clutter_actor_show (stage); + + clutter_main (); + + return EXIT_SUCCESS; +} + +G_MODULE_EXPORT const char * +test_animation_describe (void) +{ + return "Simple animation demo"; +} diff --git a/clutter/tests/interactive/test-animator.c b/clutter/tests/interactive/test-animator.c new file mode 100644 index 0000000..fc9f9f5 --- /dev/null +++ b/clutter/tests/interactive/test-animator.c @@ -0,0 +1,138 @@ +#include +#include +#include +#include + +static ClutterAnimator *animator; + +static ClutterActor *new_rect (gint r, + gint g, + gint b, + gint a) +{ + GError *error = NULL; + ClutterColor *color = clutter_color_new (r, g, b, a); + ClutterActor *rectangle; + + gchar *file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL); + rectangle = clutter_texture_new_from_file (file, &error); + if (rectangle == NULL) + g_error ("image load failed: %s", error->message); + g_free (file); + + clutter_actor_set_size (rectangle, 128, 128); + clutter_color_free (color); + return rectangle; +} + +static gboolean nuke_one (gpointer actor) +{ + clutter_actor_destroy (actor); + return FALSE; +} + +#define COUNT 4 + +static void reverse_timeline (ClutterTimeline *timeline, + gpointer data) +{ + ClutterTimelineDirection direction = clutter_timeline_get_direction (timeline); + if (direction == CLUTTER_TIMELINE_FORWARD) + clutter_timeline_set_direction (timeline, CLUTTER_TIMELINE_BACKWARD); + else + clutter_timeline_set_direction (timeline, CLUTTER_TIMELINE_FORWARD); + clutter_timeline_start (timeline); +} + + +G_MODULE_EXPORT gint +test_animator_main (gint argc, + gchar **argv) +{ + ClutterActor *stage; + ClutterActor *rects[COUNT]; + gint i; + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Animator"); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + for (i = 0; i < COUNT; i++) + { + rects[i] = new_rect (255 * (i * 1.0 / COUNT), 50, 160, 255); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), rects[i]); + clutter_actor_set_anchor_point (rects[i], 64, 64); + clutter_actor_set_position (rects[i], 320.0, 240.0); + clutter_actor_set_opacity (rects[i], 0x70); + } + + clutter_threads_add_timeout (10000, nuke_one, rects[2]); + + animator = clutter_animator_new (); + + /* Note: when both animations are active for the same actor at the same + * time there is a race, such races should be handled by avoiding + * controlling the same properties from multiple animations. This is + * an intentional design flaw of this test for testing the corner case. + */ + + clutter_animator_set (animator, + rects[0], "x", 1, 0.0, 180.0, + rects[0], "x", CLUTTER_LINEAR, 0.25, 450.0, + rects[0], "x", CLUTTER_LINEAR, 0.5, 450.0, + rects[0], "x", CLUTTER_LINEAR, 0.75, 180.0, + rects[0], "x", CLUTTER_LINEAR, 1.0, 180.0, + + rects[0], "y", -1, 0.0, 100.0, + rects[0], "y", CLUTTER_LINEAR, 0.25, 100.0, + rects[0], "y", CLUTTER_LINEAR, 0.5, 380.0, + rects[0], "y", CLUTTER_LINEAR, 0.75, 380.0, + rects[0], "y", CLUTTER_LINEAR, 1.0, 100.0, + + rects[3], "x", 0, 0.0, 180.0, + rects[3], "x", CLUTTER_LINEAR, 0.25, 180.0, + rects[3], "x", CLUTTER_LINEAR, 0.5, 450.0, + rects[3], "x", CLUTTER_LINEAR, 0.75, 450.0, + rects[3], "x", CLUTTER_LINEAR, 1.0, 180.0, + + rects[3], "y", 0, 0.0, 100.0, + rects[3], "y", CLUTTER_LINEAR, 0.25, 380.0, + rects[3], "y", CLUTTER_LINEAR, 0.5, 380.0, + rects[3], "y", CLUTTER_LINEAR, 0.75, 100.0, + rects[3], "y", CLUTTER_LINEAR, 1.0, 100.0, + + + rects[2], "rotation-angle-y", 0, 0.0, 0.0, + rects[2], "rotation-angle-y", CLUTTER_LINEAR, 1.0, 360.0, + + rects[1], "scale-x", 0, 0.0, 1.0, + rects[1], "scale-x", CLUTTER_LINEAR, 1.0, 2.0, + rects[1], "scale-y", 0, 0.0, 1.0, + rects[1], "scale-y", CLUTTER_LINEAR, 1.0, 2.0, + NULL); + + + clutter_actor_set_scale (rects[0], 1.4, 1.4); + clutter_animator_property_set_ease_in (animator, G_OBJECT (rects[0]), "x", + TRUE); + clutter_animator_property_set_ease_in (animator, G_OBJECT (rects[0]), "y", + TRUE); + clutter_animator_property_set_interpolation (animator, G_OBJECT (rects[0]), + "x", CLUTTER_INTERPOLATION_CUBIC); + clutter_animator_property_set_interpolation (animator, G_OBJECT (rects[0]), + "y", CLUTTER_INTERPOLATION_CUBIC); + + clutter_stage_hide_cursor(CLUTTER_STAGE (stage)); + clutter_actor_show (stage); + clutter_animator_set_duration (animator, 5000); + + g_signal_connect (clutter_animator_start (animator), + "completed", G_CALLBACK (reverse_timeline), NULL); + clutter_main (); + + g_object_unref (animator); + + return EXIT_SUCCESS; +} diff --git a/clutter/tests/interactive/test-bind-constraint.c b/clutter/tests/interactive/test-bind-constraint.c new file mode 100644 index 0000000..6cceeba --- /dev/null +++ b/clutter/tests/interactive/test-bind-constraint.c @@ -0,0 +1,252 @@ +#include +#include + +#define RECT_SIZE 128 + +#define H_PADDING 32 +#define V_PADDING 32 + +enum +{ + NorthWest, North, NorthEast, + West, Center, East, + SouthWest, South, SouthEast, + + N_RECTS +}; + +static ClutterActor *rects[N_RECTS] = { NULL, }; +static const gchar *colors[N_RECTS] = { + "#8ae234", "#73d216", "#4e9a06", + "#729fcf", "#3465a4", "#204a87", + "#ef2929", "#cc0000", "#a40000" +}; +static const gchar *names[N_RECTS] = { + "North West", "North", "North East", + "West", "Center", "East", + "South West", "South", "South East" +}; + +static const gchar *desaturare_glsl_shader = +"uniform sampler2D tex;\n" +"uniform float factor;\n" +"\n" +"vec3 desaturate (const vec3 color, const float desaturation)\n" +"{\n" +" const vec3 gray_conv = vec3 (0.299, 0.587, 0.114);\n" +" vec3 gray = vec3 (dot (gray_conv, color));\n" +" return vec3 (mix (color.rgb, gray, desaturation));\n" +"}\n" +"\n" +"void main ()\n" +"{\n" +" vec4 color = cogl_color_in * texture2D (tex, vec2 (cogl_tex_coord_in[0].xy));\n" +" color.rgb = desaturate (color.rgb, factor);\n" +" cogl_color_out = color;\n" +"}\n"; + +static gboolean is_expanded = FALSE; + +static gboolean +on_button_release (ClutterActor *actor, + ClutterEvent *event, + gpointer data G_GNUC_UNUSED) +{ + if (!is_expanded) + { + gfloat north_offset, south_offset; + gfloat west_offset, east_offset; + + /* expand the 8 rectangles by animating the offset of the + * bind constraints + */ + + north_offset = (clutter_actor_get_height (rects[Center]) + V_PADDING) + * -1.0f; + south_offset = (clutter_actor_get_height (rects[Center]) + V_PADDING); + + west_offset = (clutter_actor_get_width (rects[Center]) + H_PADDING) + * -1.0f; + east_offset = (clutter_actor_get_width (rects[Center]) + H_PADDING); + + clutter_actor_animate (rects[NorthWest], CLUTTER_EASE_OUT_EXPO, 500, + "opacity", 255, + "@constraints.x-bind.offset", west_offset, + "@constraints.y-bind.offset", north_offset, + "reactive", TRUE, + NULL); + clutter_actor_animate (rects[North], CLUTTER_EASE_OUT_EXPO, 500, + "opacity", 255, + "@constraints.y-bind.offset", north_offset, + "reactive", TRUE, + NULL); + clutter_actor_animate (rects[NorthEast], CLUTTER_EASE_OUT_EXPO, 500, + "opacity", 255, + "@constraints.x-bind.offset", east_offset, + "@constraints.y-bind.offset", north_offset, + "reactive", TRUE, + NULL); + + clutter_actor_animate (rects[West], CLUTTER_EASE_OUT_EXPO, 500, + "opacity", 255, + "@constraints.x-bind.offset", west_offset, + "reactive", TRUE, + NULL); + /* turn on the desaturation effect and set the center + * rectangle not reactive + */ + clutter_actor_animate (rects[Center], CLUTTER_LINEAR, 500, + "@effects.desaturate.enabled", TRUE, + "reactive", FALSE, + NULL); + clutter_actor_animate (rects[East], CLUTTER_EASE_OUT_EXPO, 500, + "opacity", 255, + "@constraints.x-bind.offset", east_offset, + "reactive", TRUE, + NULL); + + clutter_actor_animate (rects[SouthWest], CLUTTER_EASE_OUT_EXPO, 500, + "opacity", 255, + "@constraints.x-bind.offset", west_offset, + "@constraints.y-bind.offset", south_offset, + "reactive", TRUE, + NULL); + clutter_actor_animate (rects[South], CLUTTER_EASE_OUT_EXPO, 500, + "opacity", 255, + "@constraints.y-bind.offset", south_offset, + "reactive", TRUE, + NULL); + clutter_actor_animate (rects[SouthEast], CLUTTER_EASE_OUT_EXPO, 500, + "opacity", 255, + "@constraints.x-bind.offset", east_offset, + "@constraints.y-bind.offset", south_offset, + "reactive", TRUE, + NULL); + } + else + { + gint i; + + clutter_actor_animate (rects[Center], CLUTTER_LINEAR, 500, + "@effects.desaturate.enabled", FALSE, + "reactive", TRUE, + NULL); + + for (i = NorthWest; i < N_RECTS; i++) + { + if (i == Center) + continue; + + /* put the 8 rectangles back into their initial state */ + clutter_actor_animate (rects[i], CLUTTER_EASE_OUT_EXPO, 500, + "opacity", 0, + "@constraints.x-bind.offset", 0.0f, + "@constraints.y-bind.offset", 0.0f, + "reactive", FALSE, + NULL); + } + } + + is_expanded = !is_expanded; + + g_print ("Selected: [%s]\n", clutter_actor_get_name (actor)); + + return TRUE; +} + +G_MODULE_EXPORT const char * +test_bind_constraint_describe (void) +{ + return "Demonstrate the usage of ClutterBindConstraint"; +} + +G_MODULE_EXPORT int +test_bind_constraint_main (int argc, char *argv[]) +{ + ClutterActor *stage, *rect; + ClutterConstraint *constraint; + ClutterEffect *effect; + ClutterColor rect_color; + gint i; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Constraints"); + clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); + clutter_actor_set_size (stage, 800, 600); + + /* main rectangle */ + clutter_color_from_string (&rect_color, "#3465a4"); + rect = clutter_actor_new (); + g_signal_connect (rect, "button-release-event", + G_CALLBACK (on_button_release), + NULL); + clutter_actor_set_background_color (rect, &rect_color); + clutter_actor_set_size (rect, RECT_SIZE, RECT_SIZE); + clutter_actor_set_reactive (rect, TRUE); + clutter_actor_set_name (rect, names[Center]); + clutter_actor_add_child (stage, rect); + + /* align the center rectangle to the center of the stage */ + constraint = clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5); + clutter_actor_add_constraint_with_name (rect, "align", constraint); + + /* this is the equivalent of the DesaturateEffect; we cannot animate + * the factor because the animation API only understands GObject + * properties; so we use the ActorMeta:enabled property to toggle + * the shader + */ + effect = clutter_shader_effect_new (CLUTTER_FRAGMENT_SHADER); + clutter_shader_effect_set_shader_source (CLUTTER_SHADER_EFFECT (effect), + desaturare_glsl_shader); + clutter_shader_effect_set_uniform (CLUTTER_SHADER_EFFECT (effect), + "tex", G_TYPE_INT, 1, 0); + clutter_shader_effect_set_uniform (CLUTTER_SHADER_EFFECT (effect), + "factor", G_TYPE_FLOAT, 1, 0.66); + clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (effect), FALSE); + clutter_actor_add_effect_with_name (rect, "desaturate", effect); + + rects[Center] = rect; + + /* build the other rectangles, and bind their position and size + * to the center rectangle. we are going to animate the offset + * of the BindConstraints + */ + for (i = 0; i < N_RECTS; i++) + { + if (i == Center) + continue; + + clutter_color_from_string (&rect_color, colors[i]); + + rect = clutter_actor_new (); + clutter_actor_set_background_color (rect, &rect_color); + clutter_actor_set_opacity (rect, 0); + clutter_actor_set_name (rect, names[i]); + clutter_actor_add_child (stage, rect); + + constraint = clutter_bind_constraint_new (rects[Center], CLUTTER_BIND_X, 0.0); + clutter_actor_add_constraint_with_name (rect, "x-bind", constraint); + + constraint = clutter_bind_constraint_new (rects[Center], CLUTTER_BIND_Y, 0.0); + clutter_actor_add_constraint_with_name (rect, "y-bind", constraint); + + constraint = clutter_bind_constraint_new (rects[Center], CLUTTER_BIND_SIZE, 0.0); + clutter_actor_add_constraint_with_name (rect, "size-bind", constraint); + + g_signal_connect (rect, "button-release-event", + G_CALLBACK (on_button_release), + NULL); + + rects[i] = rect; + } + + clutter_actor_show (stage); + + clutter_main (); + + return EXIT_SUCCESS; +} diff --git a/clutter/tests/interactive/test-binding-pool.c b/clutter/tests/interactive/test-binding-pool.c new file mode 100644 index 0000000..59b42c1 --- /dev/null +++ b/clutter/tests/interactive/test-binding-pool.c @@ -0,0 +1,308 @@ +#include +#include + +#include +#include + +#include +#include + +#define TYPE_KEY_GROUP (key_group_get_type ()) +#define KEY_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_KEY_GROUP, KeyGroup)) +#define IS_KEY_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_KEY_GROUP)) +#define KEY_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_KEY_GROUP, KeyGroupClass)) +#define IS_KEY_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_KEY_GROUP)) + +typedef struct _KeyGroup KeyGroup; +typedef struct _KeyGroupClass KeyGroupClass; + +struct _KeyGroup +{ + ClutterActor parent_instance; + + gint selected_index; +}; + +struct _KeyGroupClass +{ + ClutterActorClass parent_class; + + void (* activate) (KeyGroup *group, + ClutterActor *child); +}; + +G_DEFINE_TYPE (KeyGroup, key_group, CLUTTER_TYPE_ACTOR) + +enum +{ + ACTIVATE, + + LAST_SIGNAL +}; + +static guint group_signals[LAST_SIGNAL] = { 0, }; + +static gboolean +key_group_action_move_left (KeyGroup *self, + const gchar *action_name, + guint key_val, + ClutterModifierType modifiers) +{ + gint n_children; + + g_debug ("%s: activated '%s' (k:%d, m:%d)", + G_STRLOC, + action_name, + key_val, + modifiers); + + n_children = clutter_actor_get_n_children (CLUTTER_ACTOR (self)); + + self->selected_index -= 1; + + if (self->selected_index < 0) + self->selected_index = n_children - 1; + + return TRUE; +} + +static gboolean +key_group_action_move_right (KeyGroup *self, + const gchar *action_name, + guint key_val, + ClutterModifierType modifiers) +{ + gint n_children; + + g_debug ("%s: activated '%s' (k:%d, m:%d)", + G_STRLOC, + action_name, + key_val, + modifiers); + + n_children = clutter_actor_get_n_children (CLUTTER_ACTOR (self)); + + self->selected_index += 1; + + if (self->selected_index >= n_children) + self->selected_index = 0; + + return TRUE; +} + +static gboolean +key_group_action_activate (KeyGroup *self, + const gchar *action_name, + guint key_val, + ClutterModifierType modifiers) +{ + ClutterActor *child = NULL; + + g_debug ("%s: activated '%s' (k:%d, m:%d)", + G_STRLOC, + action_name, + key_val, + modifiers); + + if (self->selected_index == -1) + return FALSE; + + child = clutter_actor_get_child_at_index (CLUTTER_ACTOR (self), + self->selected_index); + + if (child != NULL) + { + g_signal_emit (self, group_signals[ACTIVATE], 0, child); + return TRUE; + } + else + return FALSE; +} + +static gboolean +key_group_key_press (ClutterActor *actor, + ClutterKeyEvent *event) +{ + ClutterBindingPool *pool; + gboolean res; + + pool = clutter_binding_pool_find (G_OBJECT_TYPE_NAME (actor)); + g_assert (pool != NULL); + + res = clutter_binding_pool_activate (pool, + event->keyval, + event->modifier_state, + G_OBJECT (actor)); + + /* if we activate a key binding, redraw the actor */ + if (res) + clutter_actor_queue_redraw (actor); + + return res ? CLUTTER_EVENT_STOP : CLUTTER_EVENT_PROPAGATE; +} + +static void +key_group_paint (ClutterActor *actor) +{ + KeyGroup *self = KEY_GROUP (actor); + ClutterActorIter iter; + ClutterActor *child; + gint i = 0; + + clutter_actor_iter_init (&iter, actor); + while (clutter_actor_iter_next (&iter, &child)) + { + /* paint the selection rectangle */ + if (i == self->selected_index) + { + ClutterActorBox box = { 0, }; + + clutter_actor_get_allocation_box (child, &box); + + box.x1 -= 2; + box.y1 -= 2; + box.x2 += 2; + box.y2 += 2; + + cogl_set_source_color4ub (255, 255, 0, 224); + cogl_rectangle (box.x1, box.y1, box.x2, box.y2); + } + + clutter_actor_paint (child); + + i += 1; + } +} + +static void +key_group_class_init (KeyGroupClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + ClutterBindingPool *binding_pool; + + actor_class->paint = key_group_paint; + actor_class->key_press_event = key_group_key_press; + + group_signals[ACTIVATE] = + g_signal_new (g_intern_static_string ("activate"), + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (KeyGroupClass, activate), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + CLUTTER_TYPE_ACTOR); + + binding_pool = clutter_binding_pool_get_for_class (klass); + + clutter_binding_pool_install_action (binding_pool, "move-right", + CLUTTER_KEY_Right, 0, + G_CALLBACK (key_group_action_move_right), + NULL, NULL); + clutter_binding_pool_install_action (binding_pool, "move-left", + CLUTTER_KEY_Left, 0, + G_CALLBACK (key_group_action_move_left), + NULL, NULL); + clutter_binding_pool_install_action (binding_pool, "activate", + CLUTTER_KEY_Return, 0, + G_CALLBACK (key_group_action_activate), + NULL, NULL); + clutter_binding_pool_install_action (binding_pool, "activate", + CLUTTER_KEY_KP_Enter, 0, + G_CALLBACK (key_group_action_activate), + NULL, NULL); + clutter_binding_pool_install_action (binding_pool, "activate", + CLUTTER_KEY_ISO_Enter, 0, + G_CALLBACK (key_group_action_activate), + NULL, NULL); +} + +static void +key_group_init (KeyGroup *self) +{ + self->selected_index = -1; +} + +static void +on_key_group_activate (KeyGroup *group, + ClutterActor *child) +{ + g_print ("Child '%s' activated!\n", clutter_actor_get_name (child)); +} + +G_MODULE_EXPORT int +test_binding_pool_main (int argc, char *argv[]) +{ + ClutterActor *stage, *key_group; + gint group_x, group_y; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Key Binding Pool"); + g_signal_connect (stage, + "button-press-event", G_CALLBACK (clutter_main_quit), + NULL); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + key_group = g_object_new (TYPE_KEY_GROUP, NULL); + clutter_actor_add_child (stage, key_group); + + /* add three rectangles to the key group */ + clutter_container_add (CLUTTER_CONTAINER (key_group), + g_object_new (CLUTTER_TYPE_ACTOR, + "background-color", CLUTTER_COLOR_Red, + "name", "Red Rectangle", + "width", 100.0, + "height", 100.0, + "x", 0.0, + "y", 0.0, + NULL), + g_object_new (CLUTTER_TYPE_ACTOR, + "background-color", CLUTTER_COLOR_Green, + "name", "Green Rectangle", + "width", 100.0, + "height", 100.0, + "x", 125.0, + "y", 0.0, + NULL), + g_object_new (CLUTTER_TYPE_ACTOR, + "background-color", CLUTTER_COLOR_Blue, + "name", "Blue Rectangle", + "width", 100.0, + "height", 100.0, + "x", 250.0, + "y", 0.0, + NULL), + NULL); + + g_signal_connect (key_group, + "activate", G_CALLBACK (on_key_group_activate), + NULL); + + group_x = + (clutter_actor_get_width (stage) - clutter_actor_get_width (key_group)) + / 2; + group_y = + (clutter_actor_get_height (stage) - clutter_actor_get_height (key_group)) + / 2; + + clutter_actor_set_position (key_group, group_x, group_y); + clutter_actor_set_reactive (key_group, TRUE); + + clutter_stage_set_key_focus (CLUTTER_STAGE (stage), key_group); + + clutter_actor_show (stage); + + clutter_main (); + + return EXIT_SUCCESS; +} + +G_MODULE_EXPORT const char * +test_binding_pool_describe (void) +{ + return "Binding pools example"; +} diff --git a/clutter/tests/interactive/test-cairo-clock.c b/clutter/tests/interactive/test-cairo-clock.c new file mode 100644 index 0000000..fa5166e --- /dev/null +++ b/clutter/tests/interactive/test-cairo-clock.c @@ -0,0 +1,119 @@ +#include +#include +#include +#include + +static gboolean +draw_clock (ClutterCanvas *canvas, + cairo_t *cr, + int width, + int height) +{ + GDateTime *now; + float hours, minutes, seconds; + + /* get the current time and compute the angles */ + now = g_date_time_new_now_local (); + seconds = g_date_time_get_second (now) * G_PI / 30; + minutes = g_date_time_get_minute (now) * G_PI / 30; + hours = g_date_time_get_hour (now) * G_PI / 6; + + /* clear the contents of the canvas, to avoid painting + * over the previous frame + */ + cairo_save (cr); + cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0); + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_paint (cr); + cairo_restore (cr); + + /* scale the modelview to the size of the surface */ + cairo_scale (cr, width, height); + + cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); + cairo_set_line_width (cr, 0.1); + + /* the black rail that holds the seconds indicator */ + clutter_cairo_set_source_color (cr, CLUTTER_COLOR_Black); + cairo_translate (cr, 0.5, 0.5); + cairo_arc (cr, 0, 0, 0.4, 0, G_PI * 2); + cairo_stroke (cr); + + /* the seconds indicator */ + clutter_cairo_set_source_color (cr, CLUTTER_COLOR_White); + cairo_move_to (cr, 0, 0); + cairo_arc (cr, sinf (seconds) * 0.4, - cosf (seconds) * 0.4, 0.05, 0, G_PI * 2); + cairo_fill (cr); + + /* the minutes hand */ + clutter_cairo_set_source_color (cr, CLUTTER_COLOR_DarkChameleon); + cairo_move_to (cr, 0, 0); + cairo_line_to (cr, sinf (minutes) * 0.4, -cosf (minutes) * 0.4); + cairo_stroke (cr); + + /* the hours hand */ + cairo_move_to (cr, 0, 0); + cairo_line_to (cr, sinf (hours) * 0.2, -cosf (hours) * 0.2); + cairo_stroke (cr); + + g_date_time_unref (now); + + /* we're done drawing */ + return TRUE; +} + +static gboolean +invalidate_clock (gpointer data_) +{ + /* invalidate the contents of the canvas */ + clutter_content_invalidate (data_); + + /* keep the timeout source */ + return TRUE; +} + +G_MODULE_EXPORT int +test_cairo_clock_main (int argc, char *argv[]) +{ + ClutterActor *stage; + ClutterContent *canvas; + + /* initialize Clutter */ + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return EXIT_FAILURE; + + /* create a resizable stage */ + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "2D Clock"); + clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); + clutter_actor_set_background_color (stage, CLUTTER_COLOR_LightSkyBlue); + clutter_actor_set_size (stage, 300, 300); + clutter_actor_show (stage); + + /* our 2D canvas, courtesy of Cairo */ + canvas = clutter_canvas_new (); + clutter_canvas_set_size (CLUTTER_CANVAS (canvas), 300, 300); + clutter_actor_set_content (stage, canvas); + + /* quit on destroy */ + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + /* connect our drawing code */ + g_signal_connect (canvas, "draw", G_CALLBACK (draw_clock), NULL); + + /* invalidate the canvas, so that we can draw before the main loop starts */ + clutter_content_invalidate (canvas); + + /* set up a timer that invalidates the canvas every second */ + clutter_threads_add_timeout (1000, invalidate_clock, canvas); + + clutter_main (); + + return EXIT_SUCCESS; +} + +G_MODULE_EXPORT const char * +test_cairo_clock_describe (void) +{ + return "Simple 2D canvas using a Cairo texture actor"; +} diff --git a/clutter/tests/interactive/test-cairo-flowers.c b/clutter/tests/interactive/test-cairo-flowers.c new file mode 100644 index 0000000..2594d68 --- /dev/null +++ b/clutter/tests/interactive/test-cairo-flowers.c @@ -0,0 +1,256 @@ +/* + * Pretty cairo flower hack. + */ +#include + +#ifndef _MSC_VER +#include /* for sleep(), used for screenshots */ +#endif +#include +#ifdef _MSC_VER +#define _USE_MATH_DEFINES +#endif +#include + +#define PETAL_MIN 20 +#define PETAL_VAR 40 +#define N_FLOWERS 40 /* reduce if you have a small card */ + +typedef struct Flower +{ + ClutterActor *ctex; + gint x,y,rot,v,rv; +} +Flower; + +static ClutterActor *stage = NULL; + +static gboolean +draw_flower (ClutterCanvas *canvas, + cairo_t *cr, + gint width, + gint height, + gpointer user_data) +{ + /* No science here, just a hack from toying */ + gint i, j; + + double colors[] = { + 0.71, 0.81, 0.83, + 1.0, 0.78, 0.57, + 0.64, 0.30, 0.35, + 0.73, 0.40, 0.39, + 0.91, 0.56, 0.64, + 0.70, 0.47, 0.45, + 0.92, 0.75, 0.60, + 0.82, 0.86, 0.85, + 0.51, 0.56, 0.67, + 1.0, 0.79, 0.58, + + }; + + gint size; + gint petal_size; + gint n_groups; /* Num groups of petals 1-3 */ + gint n_petals; /* num of petals 4 - 8 */ + gint pm1, pm2; + + gint idx, last_idx = -1; + + petal_size = GPOINTER_TO_INT (user_data); + size = petal_size * 8; + + n_groups = rand() % 3 + 1; + + cairo_set_tolerance (cr, 0.1); + + /* Clear */ + cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); + cairo_paint(cr); + cairo_set_operator (cr, CAIRO_OPERATOR_OVER); + + cairo_translate(cr, size/2, size/2); + + for (i=0; iy += flowers[i]->v; + flowers[i]->rot += flowers[i]->rv; + + if (flowers[i]->y > (gint) clutter_actor_get_height (stage)) + flowers[i]->y = -clutter_actor_get_height (flowers[i]->ctex); + + clutter_actor_set_position (flowers[i]->ctex, + flowers[i]->x, flowers[i]->y); + + clutter_actor_set_rotation (flowers[i]->ctex, + CLUTTER_Z_AXIS, + flowers[i]->rot, + clutter_actor_get_width (flowers[i]->ctex)/2, + clutter_actor_get_height (flowers[i]->ctex)/2, + 0); + } +} + +static void +stop_and_quit (ClutterActor *actor, + ClutterTimeline *timeline) +{ + clutter_timeline_stop (timeline); + clutter_main_quit (); +} + +G_MODULE_EXPORT int +test_cairo_flowers_main (int argc, char **argv) +{ + Flower *flowers[N_FLOWERS]; + ClutterTimeline *timeline; + int i; + + srand (time (NULL)); + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + /* Create a timeline to manage animation */ + timeline = clutter_timeline_new (6000); + clutter_timeline_set_repeat_count (timeline, -1); + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Cairo Flowers"); + g_signal_connect (stage, "destroy", G_CALLBACK (stop_and_quit), timeline); + + clutter_actor_set_background_color (stage, CLUTTER_COLOR_Black); + + for (i=0; i< N_FLOWERS; i++) + { + flowers[i] = g_new0(Flower, 1); + flowers[i]->ctex = make_flower_actor(); + flowers[i]->x = rand() % (int) clutter_actor_get_width (stage) + - (PETAL_MIN + PETAL_VAR) * 2; + flowers[i]->y = rand() % (int) clutter_actor_get_height (stage); + flowers[i]->rv = rand() % 5 + 1; + flowers[i]->v = rand() % 10 + 2; + + clutter_container_add_actor (CLUTTER_CONTAINER (stage), + flowers[i]->ctex); + clutter_actor_set_position (flowers[i]->ctex, + flowers[i]->x, flowers[i]->y); + } + + /* fire a callback for frame change */ + g_signal_connect (timeline, "new-frame", G_CALLBACK (tick), flowers); + + clutter_actor_show (stage); + + clutter_timeline_start (timeline); + + g_signal_connect (stage, "key-press-event", + G_CALLBACK (clutter_main_quit), + NULL); + + clutter_main(); + + g_object_unref (timeline); + + return EXIT_SUCCESS; +} + +G_MODULE_EXPORT const char * +test_cairo_flowers_describe (void) +{ + return "Drawing pretty flowers with Cairo"; +} diff --git a/clutter/tests/interactive/test-cogl-multitexture.c b/clutter/tests/interactive/test-cogl-multitexture.c new file mode 100644 index 0000000..b815831 --- /dev/null +++ b/clutter/tests/interactive/test-cogl-multitexture.c @@ -0,0 +1,238 @@ +#include +#include +#include + +#include +#include +#include + +#include +#include + +typedef struct _TestMultiLayerMaterialState +{ + ClutterActor *group; + CoglHandle alpha_tex; + CoglHandle redhand_tex; + gfloat *tex_coords; + + ClutterTimeline *timeline; + + CoglHandle material0; + CoglMatrix tex_matrix0; + CoglMatrix rot_matrix0; + CoglHandle light_tex0; + + CoglHandle material1; + CoglMatrix tex_matrix1; + CoglMatrix rot_matrix1; + CoglHandle light_tex1; + +} TestMultiLayerMaterialState; + + +static void +frame_cb (ClutterTimeline *timeline, + gint frame_no, + gpointer data) +{ + TestMultiLayerMaterialState *state = data; + + cogl_matrix_multiply (&state->tex_matrix0, + &state->tex_matrix0, + &state->rot_matrix0); + cogl_material_set_layer_matrix (state->material0, 2, &state->tex_matrix0); + + cogl_matrix_multiply (&state->tex_matrix1, + &state->tex_matrix1, + &state->rot_matrix1); + cogl_material_set_layer_matrix (state->material1, 2, &state->tex_matrix1); +} + +static void +material_rectangle_paint (ClutterActor *actor, gpointer data) +{ + TestMultiLayerMaterialState *state = data; + + cogl_push_matrix (); + + cogl_translate (150, 15, 0); + + cogl_set_source (state->material0); + cogl_rectangle_with_multitexture_coords (0, 0, 200, 213, + state->tex_coords, + 12); + cogl_translate (-300, -30, 0); + cogl_set_source (state->material1); + cogl_rectangle_with_multitexture_coords (0, 0, 200, 213, + state->tex_coords, + 12); + + cogl_pop_matrix (); +} + +static void +animation_completed_cb (ClutterAnimation *animation, + TestMultiLayerMaterialState *state) +{ + static gboolean go_back = FALSE; + gdouble new_rotation_y; + + if (go_back) + new_rotation_y = 30; + else + new_rotation_y = -30; + go_back = !go_back; + + clutter_actor_animate_with_timeline (state->group, + CLUTTER_LINEAR, + state->timeline, + "rotation-angle-y", new_rotation_y, + "signal-after::completed", + animation_completed_cb, state, + NULL); + + +} + +G_MODULE_EXPORT int +test_cogl_multitexture_main (int argc, char *argv[]) +{ + GError *error = NULL; + ClutterActor *stage; + ClutterColor stage_color = { 0x61, 0x56, 0x56, 0xff }; + TestMultiLayerMaterialState *state = g_new0 (TestMultiLayerMaterialState, 1); + gfloat stage_w, stage_h; + gchar **files; + gfloat tex_coords[] = + { + /* tx1 ty1 tx2 ty2 */ + 0, 0, 1, 1, + 0, 0, 1, 1, + 0, 0, 1, 1 + }; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + clutter_actor_get_size (stage, &stage_w, &stage_h); + + clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl: Multi-texturing"); + clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color); + + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + /* We create a non-descript actor that we know doesn't have a + * default paint handler, so that we can easily control + * painting in a paint signal handler, without having to + * sub-class anything etc. */ + state->group = clutter_group_new (); + clutter_actor_set_position (state->group, stage_w / 2, stage_h / 2); + g_signal_connect (state->group, "paint", + G_CALLBACK(material_rectangle_paint), state); + + files = g_new (gchar*, 4); + files[0] = g_build_filename (TESTS_DATADIR, "redhand_alpha.png", NULL); + files[1] = g_build_filename (TESTS_DATADIR, "redhand.png", NULL); + files[2] = g_build_filename (TESTS_DATADIR, "light0.png", NULL); + files[3] = NULL; + + state->alpha_tex = + cogl_texture_new_from_file (files[0], + COGL_TEXTURE_NO_SLICING, + COGL_PIXEL_FORMAT_ANY, + &error); + if (!state->alpha_tex) + g_critical ("Failed to load redhand_alpha.png: %s", error->message); + + state->redhand_tex = + cogl_texture_new_from_file (files[1], + COGL_TEXTURE_NO_SLICING, + COGL_PIXEL_FORMAT_ANY, + &error); + if (!state->redhand_tex) + g_critical ("Failed to load redhand.png: %s", error->message); + + state->light_tex0 = + cogl_texture_new_from_file (files[2], + COGL_TEXTURE_NO_SLICING, + COGL_PIXEL_FORMAT_ANY, + &error); + if (!state->light_tex0) + g_critical ("Failed to load light0.png: %s", error->message); + + state->light_tex1 = + cogl_texture_new_from_file (files[2], + COGL_TEXTURE_NO_SLICING, + COGL_PIXEL_FORMAT_ANY, + &error); + if (!state->light_tex1) + g_critical ("Failed to load light0.png: %s", error->message); + + g_strfreev (files); + + state->material0 = cogl_material_new (); + cogl_material_set_layer (state->material0, 0, state->alpha_tex); + cogl_material_set_layer (state->material0, 1, state->redhand_tex); + cogl_material_set_layer (state->material0, 2, state->light_tex0); + + state->material1 = cogl_material_new (); + cogl_material_set_layer (state->material1, 0, state->alpha_tex); + cogl_material_set_layer (state->material1, 1, state->redhand_tex); + cogl_material_set_layer (state->material1, 2, state->light_tex1); + + state->tex_coords = tex_coords; + + cogl_matrix_init_identity (&state->tex_matrix0); + cogl_matrix_init_identity (&state->tex_matrix1); + cogl_matrix_init_identity (&state->rot_matrix0); + cogl_matrix_init_identity (&state->rot_matrix1); + + cogl_matrix_translate (&state->rot_matrix0, 0.5, 0.5, 0); + cogl_matrix_rotate (&state->rot_matrix0, 10.0, 0, 0, 1.0); + cogl_matrix_translate (&state->rot_matrix0, -0.5, -0.5, 0); + + cogl_matrix_translate (&state->rot_matrix1, 0.5, 0.5, 0); + cogl_matrix_rotate (&state->rot_matrix1, -10.0, 0, 0, 1.0); + cogl_matrix_translate (&state->rot_matrix1, -0.5, -0.5, 0); + + clutter_actor_set_anchor_point (state->group, 86, 125); + clutter_container_add_actor (CLUTTER_CONTAINER(stage), + state->group); + + state->timeline = clutter_timeline_new (2812); + + g_signal_connect (state->timeline, "new-frame", G_CALLBACK (frame_cb), state); + + clutter_actor_animate_with_timeline (state->group, + CLUTTER_LINEAR, + state->timeline, + "rotation-angle-y", 30.0, + "signal-after::completed", + animation_completed_cb, state, + NULL); + + /* start the timeline and thus the animations */ + clutter_timeline_start (state->timeline); + + clutter_actor_show_all (stage); + + clutter_main(); + + cogl_handle_unref (state->material1); + cogl_handle_unref (state->material0); + cogl_handle_unref (state->alpha_tex); + cogl_handle_unref (state->redhand_tex); + cogl_handle_unref (state->light_tex0); + cogl_handle_unref (state->light_tex1); + g_free (state); + + return 0; +} + +G_MODULE_EXPORT const char * +test_cogl_multitexture_describe (void) +{ + return "Multi-texturing support in Cogl."; +} diff --git a/clutter/tests/interactive/test-cogl-offscreen.c b/clutter/tests/interactive/test-cogl-offscreen.c new file mode 100644 index 0000000..72aeb79 --- /dev/null +++ b/clutter/tests/interactive/test-cogl-offscreen.c @@ -0,0 +1,333 @@ +#include +#include +#include +#include +#include + +/* Coglbox declaration + *--------------------------------------------------*/ + +G_BEGIN_DECLS + +#define TEST_TYPE_COGLBOX test_coglbox_get_type() + +#define TEST_COGLBOX(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + TEST_TYPE_COGLBOX, TestCoglboxClass)) + +#define TEST_COGLBOX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + TEST_TYPE_COGLBOX, TestCoglboxClass)) + +#define TEST_IS_COGLBOX(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + TEST_TYPE_COGLBOX)) + +#define TEST_IS_COGLBOX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + TEST_TYPE_COGLBOX)) + +#define TEST_COGLBOX_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + TEST_TYPE_COGLBOX, TestCoglboxClass)) + +typedef struct _TestCoglbox TestCoglbox; +typedef struct _TestCoglboxClass TestCoglboxClass; +typedef struct _TestCoglboxPrivate TestCoglboxPrivate; + +struct _TestCoglbox +{ + ClutterActor parent; + + /*< private >*/ + TestCoglboxPrivate *priv; +}; + +struct _TestCoglboxClass +{ + ClutterActorClass parent_class; + + /* padding for future expansion */ + void (*_test_coglbox1) (void); + void (*_test_coglbox2) (void); + void (*_test_coglbox3) (void); + void (*_test_coglbox4) (void); +}; + +static GType test_coglbox_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +/* Coglbox private declaration + *--------------------------------------------------*/ + +G_DEFINE_TYPE (TestCoglbox, test_coglbox, CLUTTER_TYPE_ACTOR); + +#define TEST_COGLBOX_GET_PRIVATE(obj) \ +(G_TYPE_INSTANCE_GET_PRIVATE ((obj), TEST_TYPE_COGLBOX, TestCoglboxPrivate)) + +struct _TestCoglboxPrivate +{ + CoglHandle texhand_id; + CoglHandle texture_id; + CoglHandle offscreen_id; +}; + +/* Coglbox implementation + *--------------------------------------------------*/ + +static void +test_coglbox_paint (ClutterActor *self) +{ + TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (self); + gfloat texcoords[4] = { 0, 0, 1, 1 }; + CoglHandle material; + + cogl_set_source_color4ub (0x66, 0x66, 0xdd, 0xff); + cogl_rectangle (0, 0, 400, 400); + + cogl_set_source_texture (priv->texhand_id); + cogl_rectangle_with_texture_coords (0, 0, + 400, 400, + 0, 0, + 6, 6); + + cogl_push_framebuffer (priv->offscreen_id); + + cogl_set_source_color4ub (0xff, 0, 0, 0xff); + cogl_rectangle (20, 20, 20 + 100, 20 + 100); + + cogl_set_source_color4ub (0, 0xff, 0, 0xff); + cogl_rectangle (80, 80, 80 + 100, 80 + 100); + + cogl_pop_framebuffer (); + + material = cogl_material_new (); + cogl_material_set_color4ub (material, 0x88, 0x88, 0x88, 0x88); + cogl_material_set_layer (material, 0, priv->texture_id); + cogl_set_source (material); + cogl_rectangle_with_texture_coords (100, 100, + 300, 300, + texcoords[0], + texcoords[1], + texcoords[2], + texcoords[3]); +} + +static void +test_coglbox_finalize (GObject *object) +{ + G_OBJECT_CLASS (test_coglbox_parent_class)->finalize (object); +} + +static void +test_coglbox_dispose (GObject *object) +{ + TestCoglboxPrivate *priv; + + priv = TEST_COGLBOX_GET_PRIVATE (object); + + cogl_handle_unref (priv->texture_id); + cogl_handle_unref (priv->offscreen_id); + + G_OBJECT_CLASS (test_coglbox_parent_class)->dispose (object); +} + +/* A newly created Cogl framebuffer will be initialized with a + * viewport covering the size of the viewport i.e. equavalent to: + * + * calling cogl_framebuffer_set_viewport ( + * fb, + * 0, 0, + * cogl_framebuffer_get_viewport_width (fb), + * cogl_framebuffer_get_viewport_width (fb)); + * + * The projection matrix will be an identity matrix. + * + * The modelview matrix will be an identity matrix, and this will + * create a coordinate system - like OpenGL - with the viewport + * being mapped to a unit cube with the origin (0, 0, 0) in the + * center, x, y and z ranging from -1 to 1 with (-1, -1) being top + * left and (1, 1) bottom right. + * + * This sets up a Clutter like coordinate system for a Cogl + * framebuffer + */ +void +setup_viewport (unsigned int width, + unsigned int height, + float fovy, + float aspect, + float z_near, + float z_far) +{ + float z_camera; + CoglMatrix projection_matrix; + CoglMatrix mv_matrix; + + cogl_set_viewport (0, 0, width, height); + + /* For Ortho projection. + * _cogl_matrix_stack_ortho (projection_stack, 0, width, 0, height, -1, 1); + */ + + cogl_perspective (fovy, aspect, z_near, z_far); + + /* + * In theory, we can compute the camera distance from screen as: + * + * 0.5 * tan (FOV) + * + * However, it's better to compute the z_camera from our projection + * matrix so that we get a 1:1 mapping at the screen distance. Consider + * the upper-left corner of the screen. It has object coordinates + * (0,0,0), so by the transform below, ends up with eye coordinate + * + * x_eye = x_object / width - 0.5 = - 0.5 + * y_eye = (height - y_object) / width - 0.5 = 0.5 + * z_eye = z_object / width - z_camera = - z_camera + * + * From cogl_perspective(), we know that the projection matrix has + * the form: + * + * (x, 0, 0, 0) + * (0, y, 0, 0) + * (0, 0, c, d) + * (0, 0, -1, 0) + * + * Applied to the above, we get clip coordinates of + * + * x_clip = x * (- 0.5) + * y_clip = y * 0.5 + * w_clip = - 1 * (- z_camera) = z_camera + * + * Dividing through by w to get normalized device coordinates, we + * have, x_nd = x * 0.5 / z_camera, y_nd = - y * 0.5 / z_camera. + * The upper left corner of the screen has normalized device coordinates, + * (-1, 1), so to have the correct 1:1 mapping, we have to have: + * + * z_camera = 0.5 * x = 0.5 * y + * + * If x != y, then we have a non-uniform aspect ration, and a 1:1 mapping + * doesn't make sense. + */ + + cogl_get_projection_matrix (&projection_matrix); + z_camera = 0.5 * projection_matrix.xx; + + cogl_matrix_init_identity (&mv_matrix); + cogl_matrix_translate (&mv_matrix, -0.5f, -0.5f, -z_camera); + cogl_matrix_scale (&mv_matrix, 1.0f / width, -1.0f / height, 1.0f / width); + cogl_matrix_translate (&mv_matrix, 0.0f, -1.0 * height, 0.0f); + cogl_set_modelview_matrix (&mv_matrix); +} + +static void +test_coglbox_map (ClutterActor *actor) +{ + TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (actor); + ClutterActor *stage; + ClutterPerspective perspective; + float stage_width; + float stage_height; + + CLUTTER_ACTOR_CLASS (test_coglbox_parent_class)->map (actor); + + printf ("Creating offscreen\n"); + priv->offscreen_id = cogl_offscreen_new_to_texture (priv->texture_id); + + stage = clutter_actor_get_stage (actor); + clutter_stage_get_perspective (CLUTTER_STAGE (stage), &perspective); + clutter_actor_get_size (stage, &stage_width, &stage_height); + + cogl_push_framebuffer (priv->offscreen_id); + + setup_viewport (stage_width, stage_height, + perspective.fovy, + perspective.aspect, + perspective.z_near, + perspective.z_far); + + cogl_pop_framebuffer (); + + if (priv->offscreen_id == COGL_INVALID_HANDLE) + printf ("Failed creating offscreen to texture!\n"); +} + +static void +test_coglbox_init (TestCoglbox *self) +{ + TestCoglboxPrivate *priv; + gchar *file; + + self->priv = priv = TEST_COGLBOX_GET_PRIVATE(self); + + printf ("Loading redhand.png\n"); + file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL); + priv->texhand_id = cogl_texture_new_from_file (file, + COGL_TEXTURE_NONE, + COGL_PIXEL_FORMAT_ANY, + NULL); + g_free (file); + + printf ("Creating texture with size\n"); + priv->texture_id = cogl_texture_new_with_size (200, 200, + COGL_TEXTURE_NONE, + COGL_PIXEL_FORMAT_RGB_888); + + if (priv->texture_id == COGL_INVALID_HANDLE) + printf ("Failed creating texture with size!\n"); +} + +static void +test_coglbox_class_init (TestCoglboxClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + + gobject_class->finalize = test_coglbox_finalize; + gobject_class->dispose = test_coglbox_dispose; + + actor_class->map = test_coglbox_map; + actor_class->paint = test_coglbox_paint; + + g_type_class_add_private (gobject_class, sizeof (TestCoglboxPrivate)); +} + +static ClutterActor* +test_coglbox_new (void) +{ + return g_object_new (TEST_TYPE_COGLBOX, NULL); +} + +G_MODULE_EXPORT int +test_cogl_offscreen_main (int argc, char *argv[]) +{ + ClutterActor *stage; + ClutterActor *coglbox; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + /* Stage */ + stage = clutter_stage_new (); + clutter_actor_set_size (stage, 400, 400); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl Offscreen Buffers"); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + /* Cogl Box */ + coglbox = test_coglbox_new (); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), coglbox); + + clutter_actor_show_all (stage); + + clutter_main (); + + return 0; +} + +G_MODULE_EXPORT const char * +test_cogl_offscreen_describe (void) +{ + return "Offscreen buffer support in Cogl."; +} diff --git a/clutter/tests/interactive/test-cogl-point-sprites.c b/clutter/tests/interactive/test-cogl-point-sprites.c new file mode 100644 index 0000000..f779dcc --- /dev/null +++ b/clutter/tests/interactive/test-cogl-point-sprites.c @@ -0,0 +1,288 @@ +#include +#include +#include +#include +#include + +#define N_FIREWORKS 32 +/* Units per second per second */ +#define GRAVITY -1.5f + +#define N_SPARKS (N_FIREWORKS * 32) /* Must be a power of two */ +#define TIME_PER_SPARK 0.01f /* in seconds */ + +#define TEXTURE_SIZE 32 + +typedef struct _Firework Firework; + +struct _Firework +{ + float size; + float x, y; + float start_x, start_y; + ClutterColor color; + + /* Velocities are in units per second */ + float initial_x_velocity; + float initial_y_velocity; + + GTimer *timer; +}; + +typedef struct _Spark Spark; + +struct _Spark +{ + float x, y; + ClutterColor color; + ClutterColor base_color; +}; + +typedef struct _Data Data; + +struct _Data +{ + Firework fireworks[N_FIREWORKS]; + + int next_spark_num; + Spark sparks[N_SPARKS]; + GTimer *last_spark_time; + + CoglMaterial *material; +}; + +static CoglHandle +generate_round_texture (void) +{ + guint8 *p, *data; + int x, y; + CoglHandle tex; + + p = data = g_malloc (TEXTURE_SIZE * TEXTURE_SIZE * 4); + + /* Generate a yellow circle which gets transparent towards the edges */ + for (y = 0; y < TEXTURE_SIZE; y++) + for (x = 0; x < TEXTURE_SIZE; x++) + { + int dx = x - TEXTURE_SIZE / 2; + int dy = y - TEXTURE_SIZE / 2; + float value = sqrtf (dx * dx + dy * dy) * 255.0 / (TEXTURE_SIZE / 2); + if (value > 255.0f) + value = 255.0f; + value = 255.0f - value; + *(p++) = value; + *(p++) = value; + *(p++) = value; + *(p++) = value; + } + + tex = cogl_texture_new_from_data (TEXTURE_SIZE, TEXTURE_SIZE, + COGL_TEXTURE_NO_SLICING, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + COGL_PIXEL_FORMAT_ANY, + TEXTURE_SIZE * 4, + data); + + g_free (data); + + return tex; +} + +static void +paint_cb (ClutterActor *stage, Data *data) +{ + CoglMatrix old_matrix, new_matrix; + int i; + float diff_time; + CoglHandle vbo; + + cogl_get_projection_matrix (&old_matrix); + /* Use an orthogonal projection from -1 -> 1 in both axes */ + cogl_matrix_init_identity (&new_matrix); + cogl_set_projection_matrix (&new_matrix); + + cogl_push_matrix (); + cogl_set_modelview_matrix (&new_matrix); + + /* Update all of the firework's positions */ + for (i = 0; i < N_FIREWORKS; i++) + { + Firework *firework = data->fireworks + i; + + if ((fabsf (firework->x - firework->start_x) > 2.0f) || + firework->y < -1.0f) + { + firework->size = g_random_double_range (0.001f, 0.1f); + firework->start_x = 1.0f + firework->size; + firework->start_y = -1.0f; + firework->initial_x_velocity = g_random_double_range (-0.1f, -2.0f); + firework->initial_y_velocity = g_random_double_range (0.1f, 4.0f); + g_timer_reset (firework->timer); + + /* Pick a random color out of six */ + if (g_random_boolean ()) + { + memset (&firework->color, 0, sizeof (ClutterColor)); + ((guint8 *) &firework->color)[g_random_int_range (0, 3)] = 255; + } + else + { + memset (&firework->color, 255, sizeof (ClutterColor)); + ((guint8 *) &firework->color)[g_random_int_range (0, 3)] = 0; + } + firework->color.alpha = 255; + + /* Fire some of the fireworks from the other side */ + if (g_random_boolean ()) + { + firework->start_x = -firework->start_x; + firework->initial_x_velocity = -firework->initial_x_velocity; + } + } + + diff_time = g_timer_elapsed (firework->timer, NULL); + + firework->x = (firework->start_x + + firework->initial_x_velocity * diff_time); + + firework->y = ((firework->initial_y_velocity * diff_time + + 0.5f * GRAVITY * diff_time * diff_time) + + firework->start_y); + } + + diff_time = g_timer_elapsed (data->last_spark_time, NULL); + if (diff_time < 0.0f || diff_time >= TIME_PER_SPARK) + { + /* Add a new spark for each firework, overwriting the oldest ones */ + for (i = 0; i < N_FIREWORKS; i++) + { + Spark *spark = data->sparks + data->next_spark_num; + Firework *firework = data->fireworks + i; + + spark->x = (firework->x + + g_random_double_range (-firework->size / 2.0f, + firework->size / 2.0f)); + spark->y = (firework->y + + g_random_double_range (-firework->size / 2.0f, + firework->size / 2.0f)); + spark->base_color = firework->color; + + data->next_spark_num = (data->next_spark_num + 1) & (N_SPARKS - 1); + } + + /* Update the colour of each spark */ + for (i = 0; i < N_SPARKS; i++) + { + float color_value; + + /* First spark is the oldest */ + Spark *spark = data->sparks + ((data->next_spark_num + i) + & (N_SPARKS - 1)); + + color_value = i / (N_SPARKS - 1.0f); + spark->color.red = spark->base_color.red * color_value; + spark->color.green = spark->base_color.green * color_value; + spark->color.blue = spark->base_color.blue * color_value; + spark->color.alpha = 255.0f * color_value; + } + + g_timer_reset (data->last_spark_time); + } + + vbo = cogl_vertex_buffer_new (N_SPARKS); + cogl_vertex_buffer_add (vbo, "gl_Vertex", 2, + COGL_ATTRIBUTE_TYPE_FLOAT, FALSE, + sizeof (Spark), + &data->sparks[0].x); + cogl_vertex_buffer_add (vbo, "gl_Color", 4, + COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE, TRUE, + sizeof (Spark), + &data->sparks[0].color.red); + cogl_vertex_buffer_submit (vbo); + + cogl_set_source (data->material); + cogl_vertex_buffer_draw (vbo, COGL_VERTICES_MODE_POINTS, 0, N_SPARKS); + + cogl_handle_unref (vbo); + + cogl_set_projection_matrix (&old_matrix); + cogl_pop_matrix (); +} + +static gboolean +idle_cb (gpointer data) +{ + clutter_actor_queue_redraw (data); + + return G_SOURCE_CONTINUE; +} + +G_MODULE_EXPORT int +test_cogl_point_sprites_main (int argc, char *argv[]) +{ + ClutterActor *stage; + CoglHandle tex; + Data data; + GError *error = NULL; + int i; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return EXIT_FAILURE; + + data.material = cogl_material_new (); + data.last_spark_time = g_timer_new (); + data.next_spark_num = 0; + cogl_material_set_point_size (data.material, TEXTURE_SIZE); + + tex = generate_round_texture (); + cogl_material_set_layer (data.material, 0, tex); + cogl_handle_unref (tex); + + if (!cogl_material_set_layer_point_sprite_coords_enabled (data.material, + 0, TRUE, + &error)) + { + g_warning ("Failed to enable point sprite coords: %s", error->message); + g_clear_error (&error); + } + + for (i = 0; i < N_FIREWORKS; i++) + { + data.fireworks[i].x = -FLT_MAX; + data.fireworks[i].y = FLT_MAX; + data.fireworks[i].size = 0.0f; + data.fireworks[i].timer = g_timer_new (); + } + + for (i = 0; i < N_SPARKS; i++) + { + data.sparks[i].x = 2.0f; + data.sparks[i].y = 2.0f; + } + + stage = clutter_stage_new (); + clutter_stage_set_color (CLUTTER_STAGE (stage), CLUTTER_COLOR_Black); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl Point Sprites"); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + g_signal_connect_after (stage, "paint", G_CALLBACK (paint_cb), &data); + + clutter_actor_show (stage); + + clutter_threads_add_idle (idle_cb, stage); + + clutter_main (); + + cogl_object_unref (data.material); + g_timer_destroy (data.last_spark_time); + + for (i = 0; i < N_FIREWORKS; i++) + g_timer_destroy (data.fireworks[i].timer); + + return 0; +} + +G_MODULE_EXPORT const char * +test_cogl_point_sprites_describe (void) +{ + return "Point sprites support in Cogl."; +} diff --git a/clutter/tests/interactive/test-cogl-shader-arbfp.c b/clutter/tests/interactive/test-cogl-shader-arbfp.c new file mode 100644 index 0000000..5daca68 --- /dev/null +++ b/clutter/tests/interactive/test-cogl-shader-arbfp.c @@ -0,0 +1,407 @@ +#include + +#include +#include +#include +#include + +typedef struct +{ + char *name; + char *source; +} ShaderSource; + +static ShaderSource shaders[]= + { + /*{"brightness-contrast", + FRAGMENT_SHADER_VARS + "uniform float brightness, contrast;" + FRAGMENT_SHADER_BEGIN + " color.rgb = (color.rgb - vec3(0.5, 0.5, 0.5)) * contrast + " + "vec3 (brightness + 0.5, brightness + 0.5, brightness + 0.5);" + FRAGMENT_SHADER_END + },*/ + {"brightness-contrast", + "!!ARBfp1.0\n" + "PARAM bc = program.local[0];" + "TEMP color;" + "TEMP color2;" + "TEX color.rgba, fragment.texcoord[0], texture[0], 2D;" + "SUB color.rgb, color, 0.5;" + "MUL color2, color, bc.w;" + "ADD color.rgb, color2, bc.z;" + "MOV result.color, color;" + "END" + }, + + /*{"box-blur", + FRAGMENT_SHADER_VARS + + "vec4 get_rgba_rel(sampler2D tex, float dx, float dy)" + "{" + " return texture2D (tex, " TEX_COORD ".st " + " + vec2(dx, dy) * 2.0);" + "}" + + FRAGMENT_SHADER_BEGIN + " float count = 1.0;" + " color += get_rgba_rel (tex, -x_step, -y_step); count++;" + " color += get_rgba_rel (tex, -x_step, 0.0); count++;" + " color += get_rgba_rel (tex, -x_step, y_step); count++;" + " color += get_rgba_rel (tex, 0.0, -y_step); count++;" + " color += get_rgba_rel (tex, 0.0, 0.0); count++;" + " color += get_rgba_rel (tex, 0.0, y_step); count++;" + " color += get_rgba_rel (tex, x_step, -y_step); count++;" + " color += get_rgba_rel (tex, x_step, 0.0); count++;" + " color += get_rgba_rel (tex, x_step, y_step); count++;" + " color = color / count;" + FRAGMENT_SHADER_END + },*/ + {"box-blur", + "!!ARBfp1.0\n" + "PARAM params = program.local[0];" + "TEMP accum;" + "TEMP color;" + "TEMP coord;" + "TEMP step;" + + "MUL step, params, 2.0;" + + "SUB coord, fragment.texcoord[0], step;" + "TEX color.rgba, coord, texture[0], 2D;" + "MOV accum, color;" + + "MOV coord, fragment.texcoord[0];" + "SUB coord.x, coord.x, step.x;" + "TEX color.rgba, coord, texture[0], 2D;" + "ADD accum, accum, color;" + + "MOV coord, fragment.texcoord[0];" + "SUB coord.x, coord.x, step.x;" + "ADD coord.y, coord.y, step.y;" + "TEX color.rgba, coord, texture[0], 2D;" + "ADD accum, accum, color;" + + "MOV coord, fragment.texcoord[0];" + "SUB coord.y, coord.y, step.y;" + "TEX color.rgba, coord, texture[0], 2D;" + "ADD accum, accum, color;" + + "MOV coord, fragment.texcoord[0];" + "TEX color.rgba, coord, texture[0], 2D;" + "ADD accum, accum, color;" + + "MOV coord, fragment.texcoord[0];" + "ADD coord.y, coord.y, step.y;" + "TEX color.rgba, coord, texture[0], 2D;" + "ADD accum, accum, color;" + + "MOV coord, fragment.texcoord[0];" + "ADD coord.x, coord.x, step.x;" + "SUB coord.y, coord.y, step.y;" + "TEX color.rgba, coord, texture[0], 2D;" + "ADD accum, accum, color;" + + "MOV coord, fragment.texcoord[0];" + "ADD coord.x, coord.x, step.x;" + "TEX color.rgba, coord, texture[0], 2D;" + "ADD accum, accum, color;" + + "MOV coord, fragment.texcoord[0];" + "ADD coord.x, coord.x, step.x;" + "ADD coord.y, coord.y, step.y;" + "TEX color.rgba, coord, texture[0], 2D;" + "ADD accum, accum, color;" + + "MUL color, accum, 0.11111111;" + "MOV result.color, color;" + "END" + }, + + /*{"invert", + FRAGMENT_SHADER_VARS + FRAGMENT_SHADER_BEGIN + " color.rgb = vec3(1.0, 1.0, 1.0) - color.rgb;\n" + FRAGMENT_SHADER_END + },*/ + {"invert", + "!!ARBfp1.0\n" + "TEMP color;" + "TEX color.rgba, fragment.texcoord[0], texture[0], 2D;" + "ADD color.rgb, 1.0, -color;" + "MOV result.color, color;" + "END" + }, + + /*{"gray", + FRAGMENT_SHADER_VARS + FRAGMENT_SHADER_BEGIN + " float avg = (color.r + color.g + color.b) / 3.0;" + " color.r = avg;" + " color.g = avg;" + " color.b = avg;" + FRAGMENT_SHADER_END + },*/ + {"gray", + "!!ARBfp1.0\n" + "TEMP color;" + "TEMP grey;" + "TEX color.rgba, fragment.texcoord[0], texture[0], 2D;" + "ADD grey, color.r, color.g;" + "ADD grey, grey, color.b;" + "MUL grey, grey, 0.33333333;" + "MOV color.rgb, grey;" + "MOV result.color, color;" + "END" + }, + +/* {"combined-mirror", + FRAGMENT_SHADER_VARS + FRAGMENT_SHADER_BEGIN + " vec4 colorB = texture2D (tex, vec2(" TEX_COORD ".ts));" + " float avg = (color.r + color.g + color.b) / 3.0;" + " color.r = avg;" + " color.g = avg;" + " color.b = avg;" + " color = (color + colorB)/2.0;" + FRAGMENT_SHADER_END + },*/ + {"combined-mirror", + "!!ARBfp1.0\n" + "TEMP color1;" + "TEMP color2;" + "TEMP coord;" + "MOV coord.x, fragment.texcoord[0].y;" + "MOV coord.y, fragment.texcoord[0].x;" + "TEX color1.rgba, fragment.texcoord[0], texture[0], 2D;" + "TEX color2.rgba, coord, texture[0], 2D;" + "MUL color1, color1, 0.5;" + "MUL color2, color2, 0.5;" + "ADD result.color, color1, color2;" + "END" + }, + +/* {"edge-detect", + FRAGMENT_SHADER_VARS + "float get_avg_rel(sampler2D texB, float dx, float dy)" + "{" + " vec4 colorB = texture2D (texB, " TEX_COORD ".st + vec2(dx, dy));" + " return (colorB.r + colorB.g + colorB.b) / 3.0;" + "}" + FRAGMENT_SHADER_BEGIN + " mat3 sobel_h = mat3( 1.0, 2.0, 1.0," + " 0.0, 0.0, 0.0," + " -1.0, -2.0, -1.0);" + " mat3 sobel_v = mat3( 1.0, 0.0, -1.0," + " 2.0, 0.0, -2.0," + " 1.0, 0.0, -1.0);" + " mat3 map = mat3( get_avg_rel(tex, -x_step, -y_step)," + " get_avg_rel(tex, -x_step, 0.0)," + " get_avg_rel(tex, -x_step, y_step)," + " get_avg_rel(tex, 0.0, -y_step)," + " get_avg_rel(tex, 0.0, 0.0)," + " get_avg_rel(tex, 0.0, y_step)," + " get_avg_rel(tex, x_step, -y_step)," + " get_avg_rel(tex, x_step, 0.0)," + " get_avg_rel(tex, x_step, y_step) );" + " mat3 gh = sobel_h * map;" + " mat3 gv = map * sobel_v;" + " float avgh = (gh[0][0] + gh[0][1] + gh[0][2] +" + " gh[1][0] + gh[1][1] + gh[1][2] +" + " gh[2][0] + gh[2][1] + gh[2][2]) / 18.0 + 0.5;" + " float avgv = (gv[0][0] + gv[0][1] + gv[0][2] +" + " gv[1][0] + gv[1][1] + gv[1][2] +" + " gv[2][0] + gv[2][1] + gv[2][2]) / 18.0 + 0.5;" + " float avg = (avgh + avgv) / 2.0;" + " color.r = avg * color.r;" + " color.g = avg * color.g;" + " color.b = avg * color.b;" + FRAGMENT_SHADER_END + },*/ + + /* Don't really fancy doing this one in assembly :) */ +}; + +static CoglHandle redhand; +static CoglMaterial *material; +static unsigned int timeout_id = 0; +static int shader_no = 0; + +static void +paint_cb (ClutterActor *actor) +{ + int stage_width = clutter_actor_get_width (actor); + int stage_height = clutter_actor_get_height (actor); + int image_width = cogl_texture_get_width (redhand); + int image_height = cogl_texture_get_height (redhand); + + cogl_set_source (material); + cogl_rectangle (stage_width/2.0f - image_width/2.0f, + stage_height/2.0f - image_height/2.0f, + stage_width/2.0f + image_width/2.0f, + stage_height/2.0f + image_height/2.0f); +} + +static void +set_shader_num (int new_no) +{ + CoglHandle shader; + CoglHandle program; + int image_width = cogl_texture_get_width (redhand); + int image_height = cogl_texture_get_height (redhand); + float param0[4]; + int uniform_no; + + g_print ("setting shaders[%i] named '%s'\n", + new_no, + shaders[new_no].name); + + shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT); + cogl_shader_source (shader, shaders[new_no].source); + cogl_shader_compile (shader); + + program = cogl_create_program (); + cogl_program_attach_shader (program, shader); + cogl_handle_unref (shader); + cogl_program_link (program); + + param0[0] = 1.0f/image_width; /* texel x step delta */ + param0[1] = 1.0f/image_height; /* texel y step delta */ + param0[2] = 0.4; /* brightness */ + param0[3] = -1.9; /* contrast */ + + uniform_no = cogl_program_get_uniform_location (program, "program.local[0]"); + cogl_program_set_uniform_float (program, uniform_no, 4, 1, param0); + + cogl_material_set_user_program (material, program); + cogl_handle_unref (program); + + shader_no = new_no; +} + +static gboolean +button_release_cb (ClutterActor *actor, + ClutterEvent *event, + void *data) +{ + int new_no; + + /* Stop the automatic cycling if the user want to manually control + * which shader to display */ + if (timeout_id) + { + g_source_remove (timeout_id); + timeout_id = 0; + } + + if (event->button.button == 1) + { + new_no = shader_no - 1; + if (new_no < 0) + new_no = G_N_ELEMENTS (shaders) - 1; + } + else + { + new_no = shader_no + 1; + if (new_no >= G_N_ELEMENTS (shaders)) + new_no = 0; + } + + set_shader_num (new_no); + + return CLUTTER_EVENT_STOP; +} + +static gboolean +key_release_cb (ClutterActor *actor, + ClutterEvent *event, + gpointer user_data) +{ + guint keysym = clutter_event_get_key_symbol (event); + ClutterModifierType mods = clutter_event_get_state (event); + + if (keysym == CLUTTER_KEY_q || + ((mods & CLUTTER_SHIFT_MASK) && keysym == CLUTTER_KEY_q)) + clutter_main_quit (); + + return CLUTTER_EVENT_STOP; +} + +static gboolean +timeout_cb (gpointer user_data) +{ + shader_no++; + if (shader_no > (G_N_ELEMENTS (shaders) - 1)) + shader_no = 0; + + set_shader_num (shader_no); + + return G_SOURCE_CONTINUE; +} + +static gboolean +idle_cb (gpointer data) +{ + clutter_actor_queue_redraw (data); + + return G_SOURCE_CONTINUE; +} + +static gboolean +destroy_window_cb (ClutterStage *stage, + ClutterEvent *event, + void *user_data) +{ + clutter_main_quit (); + return TRUE; +} + +G_MODULE_EXPORT int +test_cogl_shader_arbfp_main (int argc, char *argv[]) +{ + ClutterActor *stage; + char *file; + GError *error; + ClutterColor stage_color = { 0x61, 0x64, 0x8c, 0xff }; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + + clutter_stage_set_title (CLUTTER_STAGE (stage), "Assembly Shader Test"); + clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color); + + file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL); + error = NULL; + redhand = cogl_texture_new_from_file (file, 0, COGL_PIXEL_FORMAT_ANY, + &error); + if (redhand == COGL_INVALID_HANDLE) + g_error ("image load failed: %s", error->message); + + material = cogl_material_new (); + cogl_material_set_layer (material, 0, redhand); + + set_shader_num (0); + g_signal_connect_after (stage, "paint", G_CALLBACK (paint_cb), NULL); + + clutter_actor_set_reactive (stage, TRUE); + g_signal_connect (stage, "button-release-event", + G_CALLBACK (button_release_cb), NULL); + g_signal_connect (stage, "key-release-event", + G_CALLBACK (key_release_cb), NULL); + + g_signal_connect (stage, "delete-event", + G_CALLBACK (destroy_window_cb), NULL); + + timeout_id = clutter_threads_add_timeout (1000, timeout_cb, NULL); + + clutter_threads_add_idle (idle_cb, stage); + + clutter_actor_show (stage); + + clutter_main (); + + return EXIT_SUCCESS; +} + diff --git a/clutter/tests/interactive/test-cogl-shader-glsl.c b/clutter/tests/interactive/test-cogl-shader-glsl.c new file mode 100644 index 0000000..406d970 --- /dev/null +++ b/clutter/tests/interactive/test-cogl-shader-glsl.c @@ -0,0 +1,365 @@ +#include + +#include +#include +#include +#include + +typedef struct +{ + char *name; + char *source; +} ShaderSource; + +/* a couple of boilerplate defines that are common amongst all the + * sample shaders + */ + +/* FRAGMENT_SHADER_BEGIN: generate boilerplate with a local vec4 color already + * initialized, from a sampler2D in a variable tex. + */ +#define FRAGMENT_SHADER_VARS \ + "uniform sampler2D tex;" \ + "uniform float x_step, y_step;" + +#define FRAGMENT_SHADER_BEGIN \ + "void main (){" \ + " vec4 color = texture2D (tex, vec2(cogl_tex_coord_in[0]));" + +/* FRAGMENT_SHADER_END: apply the changed color to the output buffer correctly + * blended with the gl specified color (makes the opacity of actors work + * correctly). + */ +#define FRAGMENT_SHADER_END \ + " cogl_color_out = color;" \ + " cogl_color_out = cogl_color_out * cogl_color_in;" \ + "}" + +static ShaderSource shaders[]= + { + {"brightness-contrast", + FRAGMENT_SHADER_VARS + "uniform float brightness, contrast;" + FRAGMENT_SHADER_BEGIN + " color.rgb /= color.a;" + " color.rgb = (color.rgb - vec3(0.5, 0.5, 0.5)) * contrast + " + "vec3 (brightness + 0.5, brightness + 0.5, brightness + 0.5);" + " color.rgb *= color.a;" + FRAGMENT_SHADER_END + }, + + {"box-blur", + FRAGMENT_SHADER_VARS + +#if GPU_SUPPORTS_DYNAMIC_BRANCHING + "uniform float radius;" + FRAGMENT_SHADER_BEGIN + "float u, v;" + "int count = 1;" + "for (u=-radius;ubutton.button == 1) + { + new_no = shader_no - 1; + if (new_no < 0) + new_no = G_N_ELEMENTS (shaders) - 1; + } + else + { + new_no = shader_no + 1; + if (new_no >= G_N_ELEMENTS (shaders)) + new_no = 0; + } + + set_shader_num (new_no); + + return CLUTTER_EVENT_STOP; +} + +static gboolean +key_release_cb (ClutterActor *actor, + ClutterEvent *event, + gpointer user_data) +{ + guint keysym = clutter_event_get_key_symbol (event); + ClutterModifierType mods = clutter_event_get_state (event); + + if (keysym == CLUTTER_KEY_q || + ((mods & CLUTTER_SHIFT_MASK) && keysym == CLUTTER_KEY_q)) + clutter_main_quit (); + + return CLUTTER_EVENT_STOP; +} + +static gboolean +timeout_cb (gpointer user_data) +{ + shader_no++; + if (shader_no > (G_N_ELEMENTS (shaders) - 1)) + shader_no = 0; + + set_shader_num (shader_no); + + return G_SOURCE_CONTINUE; +} + +static gboolean +idle_cb (gpointer data) +{ + clutter_actor_queue_redraw (data); + + return G_SOURCE_CONTINUE; +} + +static gboolean +destroy_window_cb (ClutterStage *stage, + ClutterEvent *event, + gpointer user_data) +{ + clutter_main_quit (); + + return CLUTTER_EVENT_STOP; +} + +G_MODULE_EXPORT int +test_cogl_shader_glsl_main (int argc, char *argv[]) +{ + ClutterActor *stage; + char *file; + GError *error; + ClutterColor stage_color = { 0x61, 0x64, 0x8c, 0xff }; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + + clutter_stage_set_title (CLUTTER_STAGE (stage), "Assembly Shader Test"); + clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color); + + file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL); + error = NULL; + redhand = cogl_texture_new_from_file (file, + COGL_TEXTURE_NO_ATLAS, + COGL_PIXEL_FORMAT_ANY, + &error); + if (redhand == COGL_INVALID_HANDLE) + g_error ("image load failed: %s", error->message); + + material = cogl_material_new (); + cogl_material_set_layer (material, 0, redhand); + + set_shader_num (0); + g_signal_connect_after (stage, "paint", G_CALLBACK (paint_cb), NULL); + + clutter_actor_set_reactive (stage, TRUE); + g_signal_connect (stage, "button-release-event", + G_CALLBACK (button_release_cb), NULL); + g_signal_connect (stage, "key-release-event", + G_CALLBACK (key_release_cb), NULL); + + g_signal_connect (stage, "delete-event", + G_CALLBACK (destroy_window_cb), NULL); + + timeout_id = clutter_threads_add_timeout (1000, timeout_cb, NULL); + + clutter_threads_add_idle (idle_cb, stage); + + clutter_actor_show (stage); + + clutter_main (); + + return EXIT_SUCCESS; +} + diff --git a/clutter/tests/interactive/test-cogl-tex-convert.c b/clutter/tests/interactive/test-cogl-tex-convert.c new file mode 100644 index 0000000..84aa9d6 --- /dev/null +++ b/clutter/tests/interactive/test-cogl-tex-convert.c @@ -0,0 +1,225 @@ +#include +#include +#include +#include +#include + +/* Coglbox declaration + *--------------------------------------------------*/ + +G_BEGIN_DECLS + +#define TEST_TYPE_COGLBOX test_coglbox_get_type() + +#define TEST_COGLBOX(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + TEST_TYPE_COGLBOX, TestCoglboxClass)) + +#define TEST_COGLBOX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + TEST_TYPE_COGLBOX, TestCoglboxClass)) + +#define TEST_IS_COGLBOX(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + TEST_TYPE_COGLBOX)) + +#define TEST_IS_COGLBOX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + TEST_TYPE_COGLBOX)) + +#define TEST_COGLBOX_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + TEST_TYPE_COGLBOX, TestCoglboxClass)) + +typedef struct _TestCoglbox TestCoglbox; +typedef struct _TestCoglboxClass TestCoglboxClass; +typedef struct _TestCoglboxPrivate TestCoglboxPrivate; + +struct _TestCoglbox +{ + ClutterActor parent; + + /*< private >*/ + TestCoglboxPrivate *priv; +}; + +struct _TestCoglboxClass +{ + ClutterActorClass parent_class; + + /* padding for future expansion */ + void (*_test_coglbox1) (void); + void (*_test_coglbox2) (void); + void (*_test_coglbox3) (void); + void (*_test_coglbox4) (void); +}; + +static GType test_coglbox_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +/* Coglbox private declaration + *--------------------------------------------------*/ + +G_DEFINE_TYPE (TestCoglbox, test_coglbox, CLUTTER_TYPE_ACTOR); + +#define TEST_COGLBOX_GET_PRIVATE(obj) \ +(G_TYPE_INSTANCE_GET_PRIVATE ((obj), TEST_TYPE_COGLBOX, TestCoglboxPrivate)) + +struct _TestCoglboxPrivate +{ + CoglHandle cogl_tex_id[4]; + gint frame; +}; + +/* Coglbox implementation + *--------------------------------------------------*/ + +static void +test_coglbox_paint(ClutterActor *self) +{ + TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (self); + gfloat texcoords[4] = { 0.0, 0.0, 1.0, 1.0 }; + + priv = TEST_COGLBOX_GET_PRIVATE (self); + + cogl_set_source_color4ub (0x66, 0x66, 0xdd, 0xff); + cogl_rectangle (0, 0, 400, 400); + + cogl_push_matrix (); + cogl_set_source_texture (priv->cogl_tex_id[0]); + cogl_rectangle_with_texture_coords (0, 0, 200, 213, + texcoords[0], texcoords[1], + texcoords[2], texcoords[3]); + + cogl_pop_matrix (); + cogl_push_matrix (); + cogl_translate (200, 0, 0); + cogl_set_source_texture (priv->cogl_tex_id[1]); + cogl_rectangle_with_texture_coords (0, 0, 200, 213, + texcoords[0], texcoords[1], + texcoords[2], texcoords[3]); + + cogl_pop_matrix (); + cogl_push_matrix (); + cogl_translate (0, 200, 0); + cogl_set_source_texture (priv->cogl_tex_id[2]); + cogl_rectangle_with_texture_coords (0, 0, 200, 213, + texcoords[0], texcoords[1], + texcoords[2], texcoords[3]); + + cogl_pop_matrix (); + cogl_push_matrix (); + cogl_translate (200, 200, 0); + cogl_set_source_texture (priv->cogl_tex_id[3]); + cogl_rectangle_with_texture_coords (0, 0, 200, 213, + texcoords[0], texcoords[1], + texcoords[2], texcoords[3]); + + cogl_pop_matrix(); +} + +static void +test_coglbox_finalize (GObject *object) +{ + G_OBJECT_CLASS (test_coglbox_parent_class)->finalize (object); +} + +static void +test_coglbox_dispose (GObject *object) +{ + TestCoglboxPrivate *priv; + + priv = TEST_COGLBOX_GET_PRIVATE (object); + cogl_handle_unref (priv->cogl_tex_id); + + G_OBJECT_CLASS (test_coglbox_parent_class)->dispose (object); +} + +static void +test_coglbox_init (TestCoglbox *self) +{ + TestCoglboxPrivate *priv; + gchar *file; + + self->priv = priv = TEST_COGLBOX_GET_PRIVATE(self); + + file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL); + + priv->cogl_tex_id[0] = + cogl_texture_new_from_file (file, + COGL_TEXTURE_NONE, + COGL_PIXEL_FORMAT_ANY, + NULL); + + priv->cogl_tex_id[1] = + cogl_texture_new_from_file (file, + COGL_TEXTURE_NONE, + COGL_PIXEL_FORMAT_BGRA_8888, + NULL); + + priv->cogl_tex_id[2] = + cogl_texture_new_from_file (file, + COGL_TEXTURE_NONE, + COGL_PIXEL_FORMAT_ARGB_8888, + NULL); + + priv->cogl_tex_id[3] = + cogl_texture_new_from_file (file, + COGL_TEXTURE_NONE, + COGL_PIXEL_FORMAT_G_8, + NULL); + + g_free (file); +} + +static void +test_coglbox_class_init (TestCoglboxClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + + gobject_class->finalize = test_coglbox_finalize; + gobject_class->dispose = test_coglbox_dispose; + actor_class->paint = test_coglbox_paint; + + g_type_class_add_private (gobject_class, sizeof (TestCoglboxPrivate)); +} + +static ClutterActor* +test_coglbox_new (void) +{ + return g_object_new (TEST_TYPE_COGLBOX, NULL); +} + +G_MODULE_EXPORT int +test_cogl_tex_convert_main (int argc, char *argv[]) +{ + ClutterActor *stage; + ClutterActor *coglbox; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + /* Stage */ + stage = clutter_stage_new (); + clutter_actor_set_size (stage, 400, 400); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl Texture Conversion"); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + /* Cogl Box */ + coglbox = test_coglbox_new (); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), coglbox); + + clutter_actor_show_all (stage); + + clutter_main (); + + return 0; +} + +G_MODULE_EXPORT const char * +test_cogl_tex_convert_describe (void) +{ + return "Pixel format conversion of Cogl textures."; +} diff --git a/clutter/tests/interactive/test-cogl-tex-foreign.c b/clutter/tests/interactive/test-cogl-tex-foreign.c new file mode 100644 index 0000000..b499abb --- /dev/null +++ b/clutter/tests/interactive/test-cogl-tex-foreign.c @@ -0,0 +1,272 @@ +#include +#include +#include +#include +#include + +#ifndef GL_UNPACK_ALIGNMENT +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#endif +#ifndef GL_TEXTURE_BINDING_2D +#define GL_TEXTURE_BINDING_2D 0x8069 +#endif +#ifndef GL_TEXTURE_2D +#define GL_TEXTURE_2D 0x0DE1 +#endif +#ifndef GL_RGB +#define GL_RGB 0x1907 +#endif +#ifndef GL_UNSIGNED_BYTE +#define GL_UNSIGNED_BYTE 0x1401 +#endif +#ifndef GL_TEXTURE_MAG_FILTER +#define GL_TEXTURE_MAG_FILTER 0x2800 +#endif +#ifndef GL_LINEAR +#define GL_LINEAR 0x1208 +#endif +#ifndef GL_TEXTURE_MIN_FILTER +#define GL_TEXTURE_MIN_FILTER 0x2801 +#endif + +/* Coglbox declaration + *--------------------------------------------------*/ + +G_BEGIN_DECLS + +#define TEST_TYPE_COGLBOX test_coglbox_get_type() + +#define TEST_COGLBOX(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + TEST_TYPE_COGLBOX, TestCoglboxClass)) + +#define TEST_COGLBOX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + TEST_TYPE_COGLBOX, TestCoglboxClass)) + +#define TEST_IS_COGLBOX(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + TEST_TYPE_COGLBOX)) + +#define TEST_IS_COGLBOX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + TEST_TYPE_COGLBOX)) + +#define TEST_COGLBOX_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + TEST_TYPE_COGLBOX, TestCoglboxClass)) + +typedef struct _TestCoglbox TestCoglbox; +typedef struct _TestCoglboxClass TestCoglboxClass; +typedef struct _TestCoglboxPrivate TestCoglboxPrivate; + +struct _TestCoglbox +{ + ClutterActor parent; + + /*< private >*/ + TestCoglboxPrivate *priv; +}; + +struct _TestCoglboxClass +{ + ClutterActorClass parent_class; + + /* padding for future expansion */ + void (*_test_coglbox1) (void); + void (*_test_coglbox2) (void); + void (*_test_coglbox3) (void); + void (*_test_coglbox4) (void); +}; + +static GType test_coglbox_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +/* Coglbox private declaration + *--------------------------------------------------*/ + +G_DEFINE_TYPE (TestCoglbox, test_coglbox, CLUTTER_TYPE_ACTOR); + +#define TEST_COGLBOX_GET_PRIVATE(obj) \ +(G_TYPE_INSTANCE_GET_PRIVATE ((obj), TEST_TYPE_COGLBOX, TestCoglboxPrivate)) + +struct _TestCoglboxPrivate +{ + guint gl_handle; + CoglHandle cogl_handle; + + void + (* glGetIntegerv) (guint pname, int *params); + void + (* glPixelStorei) (guint pname, int param); + void + (* glTexParameteri) (guint target, guint pname, int param); + void + (* glTexImage2D) (guint target, int level, + int internalFormat, + int width, int height, + int border, guint format, guint type, + const void *pixels); + void + (* glGenTextures) (int n, guint *textures); + void + (* glDeleteTextures) (int n, const guint *textures); + void + (* glBindTexture) (guint target, guint texture); +}; + +/* Coglbox implementation + *--------------------------------------------------*/ + +static void +test_coglbox_paint(ClutterActor *self) +{ + TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (self); + gfloat texcoords[4] = { 0.3f, 0.3f, 0.7f, 0.7f }; + + cogl_set_source_color4ub (0x66, 0x66, 0xdd, 0xff); + cogl_rectangle (0,0,400,400); + + cogl_push_matrix (); + + cogl_translate (100,100,0); + cogl_set_source_texture (priv->cogl_handle); + cogl_rectangle_with_texture_coords (0, 0, 200, 200, + texcoords[0], texcoords[1], + texcoords[2], texcoords[3]); + + cogl_pop_matrix(); +} + +static void +test_coglbox_finalize (GObject *object) +{ + G_OBJECT_CLASS (test_coglbox_parent_class)->finalize (object); +} + +static void +test_coglbox_dispose (GObject *object) +{ + TestCoglboxPrivate *priv; + + priv = TEST_COGLBOX_GET_PRIVATE (object); + + cogl_handle_unref (priv->cogl_handle); + priv->glDeleteTextures (1, &priv->gl_handle); + + G_OBJECT_CLASS (test_coglbox_parent_class)->dispose (object); +} + +static void +test_coglbox_init (TestCoglbox *self) +{ + TestCoglboxPrivate *priv; + guchar data[12]; + int prev_unpack_alignment; + int prev_2d_texture_binding; + + self->priv = priv = TEST_COGLBOX_GET_PRIVATE(self); + + /* Prepare a 2x2 pixels texture */ + + data[0] = 255; data[1] = 0; data[2] = 0; + data[3] = 0; data[4] = 255; data[5] = 0; + data[6] = 0; data[7] = 0; data[8] = 255; + data[9] = 0; data[10] = 0; data[11] = 0; + + priv->glGetIntegerv = (void *) cogl_get_proc_address ("glGetIntegerv"); + priv->glPixelStorei = (void *) cogl_get_proc_address ("glPixelStorei"); + priv->glTexParameteri = (void *) cogl_get_proc_address ("glTexParameteri"); + priv->glTexImage2D = (void *) cogl_get_proc_address ("glTexImage2D"); + priv->glGenTextures = (void *) cogl_get_proc_address ("glGenTextures"); + priv->glDeleteTextures = (void *) cogl_get_proc_address ("glDeleteTextures"); + priv->glBindTexture = (void *) cogl_get_proc_address ("glBindTexture"); + + /* We are about to use OpenGL directly to create a TEXTURE_2D + * texture so we need to save the state that we modify so we can + * restore it afterwards and be sure not to interfere with any state + * caching that Cogl may do internally. + */ + priv->glGetIntegerv (GL_UNPACK_ALIGNMENT, &prev_unpack_alignment); + priv->glGetIntegerv (GL_TEXTURE_BINDING_2D, &prev_2d_texture_binding); + + priv->glGenTextures (1, &priv->gl_handle); + priv->glBindTexture (GL_TEXTURE_2D, priv->gl_handle); + + priv->glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + priv->glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, + 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, data); + + /* Now restore the original GL state as Cogl had left it */ + priv->glPixelStorei (GL_UNPACK_ALIGNMENT, prev_unpack_alignment); + priv->glBindTexture (GL_TEXTURE_2D, prev_2d_texture_binding); + + priv->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + priv->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + /* Create texture from foreign */ + + priv->cogl_handle = + cogl_texture_new_from_foreign (priv->gl_handle, + GL_TEXTURE_2D, + 2, 2, 0, 0, + COGL_PIXEL_FORMAT_RGB_888); + + if (priv->cogl_handle == COGL_INVALID_HANDLE) + { + printf ("Failed creating texture from foreign!\n"); + return; + } +} + +static void +test_coglbox_class_init (TestCoglboxClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + + gobject_class->finalize = test_coglbox_finalize; + gobject_class->dispose = test_coglbox_dispose; + actor_class->paint = test_coglbox_paint; + + g_type_class_add_private (gobject_class, sizeof (TestCoglboxPrivate)); +} + +static ClutterActor* +test_coglbox_new (void) +{ + return g_object_new (TEST_TYPE_COGLBOX, NULL); +} + +G_MODULE_EXPORT int +test_cogl_tex_foreign_main (int argc, char *argv[]) +{ + ClutterActor *stage; + ClutterActor *coglbox; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + /* Stage */ + stage = clutter_stage_new (); + clutter_actor_set_size (stage, 400, 400); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl Foreign Textures"); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + /* Cogl Box */ + coglbox = test_coglbox_new (); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), coglbox); + + clutter_actor_show_all (stage); + + clutter_main (); + + return 0; +} + +G_MODULE_EXPORT const char * +test_cogl_tex_foreign_describe (void) +{ + return "Foreign textures support in Cogl."; +} diff --git a/clutter/tests/interactive/test-cogl-tex-polygon.c b/clutter/tests/interactive/test-cogl-tex-polygon.c new file mode 100644 index 0000000..1b4f600 --- /dev/null +++ b/clutter/tests/interactive/test-cogl-tex-polygon.c @@ -0,0 +1,421 @@ +#include +#include +#include +#include +#include + +/* Coglbox declaration + *--------------------------------------------------*/ + +G_BEGIN_DECLS + +#define TEST_TYPE_COGLBOX test_coglbox_get_type() + +#define TEST_COGLBOX(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + TEST_TYPE_COGLBOX, TestCoglboxClass)) + +#define TEST_COGLBOX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + TEST_TYPE_COGLBOX, TestCoglboxClass)) + +#define TEST_IS_COGLBOX(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + TEST_TYPE_COGLBOX)) + +#define TEST_IS_COGLBOX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + TEST_TYPE_COGLBOX)) + +#define TEST_COGLBOX_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + TEST_TYPE_COGLBOX, TestCoglboxClass)) + +typedef struct _TestCoglbox TestCoglbox; +typedef struct _TestCoglboxClass TestCoglboxClass; +typedef struct _TestCoglboxPrivate TestCoglboxPrivate; + +struct _TestCoglbox +{ + ClutterActor parent; + + /*< private >*/ + TestCoglboxPrivate *priv; +}; + +struct _TestCoglboxClass +{ + ClutterActorClass parent_class; + + /* padding for future expansion */ + void (*_test_coglbox1) (void); + void (*_test_coglbox2) (void); + void (*_test_coglbox3) (void); + void (*_test_coglbox4) (void); +}; + +static GType test_coglbox_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +/* Coglbox private declaration + *--------------------------------------------------*/ + +G_DEFINE_TYPE (TestCoglbox, test_coglbox, CLUTTER_TYPE_ACTOR); + +#define TEST_COGLBOX_GET_PRIVATE(obj) \ +(G_TYPE_INSTANCE_GET_PRIVATE ((obj), TEST_TYPE_COGLBOX, TestCoglboxPrivate)) + +struct _TestCoglboxPrivate +{ + CoglHandle sliced_tex, not_sliced_tex; + gint frame; + gboolean use_sliced; + gboolean use_linear_filtering; +}; + +/* Coglbox implementation + *--------------------------------------------------*/ + +static void +test_coglbox_fade_texture (gfloat x1, + gfloat y1, + gfloat x2, + gfloat y2, + gfloat tx1, + gfloat ty1, + gfloat tx2, + gfloat ty2) +{ + CoglTextureVertex vertices[4]; + int i; + + vertices[0].x = x1; + vertices[0].y = y1; + vertices[0].z = 0; + vertices[0].tx = tx1; + vertices[0].ty = ty1; + vertices[1].x = x1; + vertices[1].y = y2; + vertices[1].z = 0; + vertices[1].tx = tx1; + vertices[1].ty = ty2; + vertices[2].x = x2; + vertices[2].y = y2; + vertices[2].z = 0; + vertices[2].tx = tx2; + vertices[2].ty = ty2; + vertices[3].x = x2; + vertices[3].y = y1; + vertices[3].z = 0; + vertices[3].tx = tx2; + vertices[3].ty = ty1; + + for (i = 0; i < 4; i++) + { + cogl_color_init_from_4ub (&(vertices[i].color), + 255, + 255, + 255, + ((i ^ (i >> 1)) & 1) ? 0 : 128); + cogl_color_premultiply (&(vertices[i].color)); + } + + cogl_polygon (vertices, 4, TRUE); +} + +static void +test_coglbox_triangle_texture (int tex_width, + int tex_height, + gfloat x, + gfloat y, + gfloat tx1, + gfloat ty1, + gfloat tx2, + gfloat ty2, + gfloat tx3, + gfloat ty3) +{ + CoglTextureVertex vertices[3]; + + vertices[0].x = x + tx1 * tex_width; + vertices[0].y = y + ty1 * tex_height; + vertices[0].z = 0; + vertices[0].tx = tx1; + vertices[0].ty = ty1; + + vertices[1].x = x + tx2 * tex_width; + vertices[1].y = y + ty2 * tex_height; + vertices[1].z = 0; + vertices[1].tx = tx2; + vertices[1].ty = ty2; + + vertices[2].x = x + tx3 * tex_width; + vertices[2].y = y + ty3 * tex_height; + vertices[2].z = 0; + vertices[2].tx = tx3; + vertices[2].ty = ty3; + + cogl_polygon (vertices, 3, FALSE); +} + +static void +test_coglbox_paint (ClutterActor *self) +{ + TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (self); + CoglHandle tex_handle = priv->use_sliced ? priv->sliced_tex + : priv->not_sliced_tex; + int tex_width = cogl_texture_get_width (tex_handle); + int tex_height = cogl_texture_get_height (tex_handle); + CoglHandle material = cogl_material_new (); + + cogl_material_set_layer (material, 0, tex_handle); + + cogl_material_set_layer_filters (material, 0, + priv->use_linear_filtering + ? COGL_MATERIAL_FILTER_LINEAR : + COGL_MATERIAL_FILTER_NEAREST, + priv->use_linear_filtering + ? COGL_MATERIAL_FILTER_LINEAR : + COGL_MATERIAL_FILTER_NEAREST); + + cogl_push_matrix (); + cogl_translate (tex_width / 2, 0, 0); + cogl_rotate (priv->frame, 0, 1, 0); + cogl_translate (-tex_width / 2, 0, 0); + + /* Draw a hand and refect it */ + cogl_set_source (material); + cogl_rectangle_with_texture_coords (0, 0, tex_width, tex_height, + 0, 0, 1, 1); + test_coglbox_fade_texture (0, tex_height, + tex_width, (tex_height * 3 / 2), + 0.0, 1.0, + 1.0, 0.5); + + cogl_pop_matrix (); + + cogl_push_matrix (); + cogl_translate (tex_width * 3 / 2 + 60, 0, 0); + cogl_rotate (priv->frame, 0, 1, 0); + cogl_translate (-tex_width / 2 - 10, 0, 0); + + /* Draw the texture split into two triangles */ + test_coglbox_triangle_texture (tex_width, tex_height, + 0, 0, + 0, 0, + 0, 1, + 1, 1); + test_coglbox_triangle_texture (tex_width, tex_height, + 20, 0, + 0, 0, + 1, 0, + 1, 1); + + cogl_pop_matrix (); + + cogl_handle_unref (material); +} + +static void +test_coglbox_finalize (GObject *object) +{ + G_OBJECT_CLASS (test_coglbox_parent_class)->finalize (object); +} + +static void +test_coglbox_dispose (GObject *object) +{ + TestCoglboxPrivate *priv; + + priv = TEST_COGLBOX_GET_PRIVATE (object); + cogl_handle_unref (priv->not_sliced_tex); + cogl_handle_unref (priv->sliced_tex); + + G_OBJECT_CLASS (test_coglbox_parent_class)->dispose (object); +} + +static void +test_coglbox_init (TestCoglbox *self) +{ + TestCoglboxPrivate *priv; + GError *error = NULL; + gchar *file; + + self->priv = priv = TEST_COGLBOX_GET_PRIVATE (self); + + priv->use_linear_filtering = FALSE; + priv->use_sliced = FALSE; + + file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL); + priv->sliced_tex = + cogl_texture_new_from_file (file, + COGL_TEXTURE_NONE, + COGL_PIXEL_FORMAT_ANY, + &error); + if (priv->sliced_tex == COGL_INVALID_HANDLE) + { + if (error) + { + g_warning ("Texture loading failed: %s", error->message); + g_error_free (error); + error = NULL; + } + else + g_warning ("Texture loading failed: "); + } + + priv->not_sliced_tex = + cogl_texture_new_from_file (file, + COGL_TEXTURE_NO_SLICING, + COGL_PIXEL_FORMAT_ANY, + &error); + if (priv->not_sliced_tex == COGL_INVALID_HANDLE) + { + if (error) + { + g_warning ("Texture loading failed: %s", error->message); + g_error_free (error); + } + else + g_warning ("Texture loading failed: "); + } + + g_free (file); +} + +static void +test_coglbox_class_init (TestCoglboxClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + + gobject_class->finalize = test_coglbox_finalize; + gobject_class->dispose = test_coglbox_dispose; + actor_class->paint = test_coglbox_paint; + + g_type_class_add_private (gobject_class, sizeof (TestCoglboxPrivate)); +} + +static ClutterActor* +test_coglbox_new (void) +{ + return g_object_new (TEST_TYPE_COGLBOX, NULL); +} + +static void +frame_cb (ClutterTimeline *timeline, + gint elapsed_msecs, + gpointer data) +{ + TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (data); + gdouble progress = clutter_timeline_get_progress (timeline); + + priv->frame = 360.0 * progress; + clutter_actor_queue_redraw (CLUTTER_ACTOR (data)); +} + +static void +update_toggle_text (ClutterText *button, gboolean val) +{ + clutter_text_set_text (button, val ? "Enabled" : "Disabled"); +} + +static gboolean +on_toggle_click (ClutterActor *button, ClutterEvent *event, + gboolean *toggle_val) +{ + update_toggle_text (CLUTTER_TEXT (button), *toggle_val = !*toggle_val); + + return TRUE; +} + +static ClutterActor * +make_toggle (const char *label_text, gboolean *toggle_val) +{ + ClutterActor *group = clutter_group_new (); + ClutterActor *label = clutter_text_new_with_text ("Sans 14", label_text); + ClutterActor *button = clutter_text_new_with_text ("Sans 14", ""); + + clutter_actor_set_reactive (button, TRUE); + + update_toggle_text (CLUTTER_TEXT (button), *toggle_val); + + clutter_actor_set_position (button, clutter_actor_get_width (label) + 10, 0); + clutter_container_add (CLUTTER_CONTAINER (group), label, button, NULL); + + g_signal_connect (button, "button-press-event", G_CALLBACK (on_toggle_click), + toggle_val); + + return group; +} + +G_MODULE_EXPORT int +test_cogl_tex_polygon_main (int argc, char *argv[]) +{ + ClutterActor *stage; + ClutterActor *coglbox; + ClutterActor *filtering_toggle; + ClutterActor *slicing_toggle; + ClutterActor *note; + ClutterTimeline *timeline; + ClutterColor blue = { 0x30, 0x30, 0xff, 0xff }; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + /* Stage */ + stage = clutter_stage_new (); + clutter_stage_set_color (CLUTTER_STAGE (stage), &blue); + clutter_actor_set_size (stage, 640, 480); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl Texture Polygon"); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + /* Cogl Box */ + coglbox = test_coglbox_new (); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), coglbox); + + /* Timeline for animation */ + timeline = clutter_timeline_new (6000); + clutter_timeline_set_loop (timeline, TRUE); + g_signal_connect (timeline, "new-frame", G_CALLBACK (frame_cb), coglbox); + clutter_timeline_start (timeline); + + /* Labels for toggling settings */ + slicing_toggle = make_toggle ("Texture slicing: ", + &(TEST_COGLBOX_GET_PRIVATE (coglbox) + ->use_sliced)); + clutter_actor_set_position (slicing_toggle, 0, + clutter_actor_get_height (stage) + - clutter_actor_get_height (slicing_toggle)); + filtering_toggle = make_toggle ("Linear filtering: ", + &(TEST_COGLBOX_GET_PRIVATE (coglbox) + ->use_linear_filtering)); + clutter_actor_set_position (filtering_toggle, 0, + clutter_actor_get_y (slicing_toggle) + - clutter_actor_get_height (filtering_toggle)); + note = clutter_text_new_with_text ("Sans 10", "<- Click to change"); + clutter_actor_set_position (note, + clutter_actor_get_width (filtering_toggle) + 10, + (clutter_actor_get_height (stage) + + clutter_actor_get_y (filtering_toggle)) / 2 + - clutter_actor_get_height (note) / 2); + + clutter_container_add (CLUTTER_CONTAINER (stage), + slicing_toggle, + filtering_toggle, + note, + NULL); + + clutter_actor_show (stage); + + clutter_main (); + + return 0; +} + +G_MODULE_EXPORT const char * +test_cogl_tex_polygon_describe (void) +{ + return "Texture polygon primitive."; +} diff --git a/clutter/tests/interactive/test-cogl-tex-tile.c b/clutter/tests/interactive/test-cogl-tex-tile.c new file mode 100644 index 0000000..025e804 --- /dev/null +++ b/clutter/tests/interactive/test-cogl-tex-tile.c @@ -0,0 +1,219 @@ +#include +#include +#include +#include +#include +#include + +/* Coglbox declaration + *--------------------------------------------------*/ + +G_BEGIN_DECLS + +#define TEST_TYPE_COGLBOX test_coglbox_get_type() + +#define TEST_COGLBOX(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + TEST_TYPE_COGLBOX, TestCoglboxClass)) + +#define TEST_COGLBOX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + TEST_TYPE_COGLBOX, TestCoglboxClass)) + +#define TEST_IS_COGLBOX(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + TEST_TYPE_COGLBOX)) + +#define TEST_IS_COGLBOX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + TEST_TYPE_COGLBOX)) + +#define TEST_COGLBOX_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + TEST_TYPE_COGLBOX, TestCoglboxClass)) + +typedef struct _TestCoglbox TestCoglbox; +typedef struct _TestCoglboxClass TestCoglboxClass; +typedef struct _TestCoglboxPrivate TestCoglboxPrivate; + +struct _TestCoglbox +{ + ClutterActor parent; + + /*< private >*/ + TestCoglboxPrivate *priv; +}; + +struct _TestCoglboxClass +{ + ClutterActorClass parent_class; + + /* padding for future expansion */ + void (*_test_coglbox1) (void); + void (*_test_coglbox2) (void); + void (*_test_coglbox3) (void); + void (*_test_coglbox4) (void); +}; + +static GType test_coglbox_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +/* Coglbox private declaration + *--------------------------------------------------*/ + +G_DEFINE_TYPE (TestCoglbox, test_coglbox, CLUTTER_TYPE_ACTOR); + +#define TEST_COGLBOX_GET_PRIVATE(obj) \ +(G_TYPE_INSTANCE_GET_PRIVATE ((obj), TEST_TYPE_COGLBOX, TestCoglboxPrivate)) + +struct _TestCoglboxPrivate +{ + CoglHandle cogl_tex_id; + gdouble animation_progress; +}; + +/* Coglbox implementation + *--------------------------------------------------*/ + +static void +test_coglbox_paint (ClutterActor *self) +{ + TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (self); + gfloat texcoords[4] = { 0.0f, 0.0f, 1.0f, 1.0f }; + gfloat angle; + gfloat frac; + gint t; + + angle = priv->animation_progress * 2 * G_PI; + + frac = ((priv->animation_progress <= 0.5f + ? priv->animation_progress + : 1.0f - priv->animation_progress) + 0.5f) * 2.0f; + + for (t=0; t<4; t+=2) + { + texcoords[t] += cos (angle); + texcoords[t+1] += sin (angle); + + texcoords[t] *= frac; + texcoords[t+1] *= frac; + } + + priv = TEST_COGLBOX_GET_PRIVATE (self); + + cogl_push_matrix (); + + cogl_set_source_color4ub (0x66, 0x66, 0xdd, 0xff); + cogl_rectangle (0, 0, 400, 400); + + cogl_translate (100, 100, 0); + cogl_set_source_texture (priv->cogl_tex_id); + cogl_rectangle_with_texture_coords (0, 0, 200, 213, + texcoords[0], texcoords[1], + texcoords[2], texcoords[3]); + + cogl_pop_matrix(); +} + +static void +test_coglbox_finalize (GObject *object) +{ + G_OBJECT_CLASS (test_coglbox_parent_class)->finalize (object); +} + +static void +test_coglbox_dispose (GObject *object) +{ + TestCoglboxPrivate *priv; + + priv = TEST_COGLBOX_GET_PRIVATE (object); + cogl_handle_unref (priv->cogl_tex_id); + + G_OBJECT_CLASS (test_coglbox_parent_class)->dispose (object); +} + +static void +test_coglbox_init (TestCoglbox *self) +{ + TestCoglboxPrivate *priv; + gchar *file; + + self->priv = priv = TEST_COGLBOX_GET_PRIVATE(self); + + file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL); + priv->cogl_tex_id = cogl_texture_new_from_file (file, + COGL_TEXTURE_NONE, + COGL_PIXEL_FORMAT_ANY, + NULL); + g_free (file); +} + +static void +test_coglbox_class_init (TestCoglboxClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + + gobject_class->finalize = test_coglbox_finalize; + gobject_class->dispose = test_coglbox_dispose; + actor_class->paint = test_coglbox_paint; + + g_type_class_add_private (gobject_class, sizeof (TestCoglboxPrivate)); +} + +static ClutterActor* +test_coglbox_new (void) +{ + return g_object_new (TEST_TYPE_COGLBOX, NULL); +} + +static void +frame_cb (ClutterTimeline *timeline, + gint msecs, + gpointer data) +{ + TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (data); + + priv->animation_progress = clutter_timeline_get_progress (timeline); + clutter_actor_queue_redraw (CLUTTER_ACTOR (data)); +} + +G_MODULE_EXPORT int +test_cogl_tex_tile_main (int argc, char *argv[]) +{ + ClutterActor *stage; + ClutterActor *coglbox; + ClutterTimeline *timeline; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + /* Stage */ + stage = clutter_stage_new (); + clutter_actor_set_size (stage, 400, 400); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl Texture Tiling"); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + /* Cogl Box */ + coglbox = test_coglbox_new (); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), coglbox); + + /* Timeline for animation */ + timeline = clutter_timeline_new (6000); /* 6 second duration */ + clutter_timeline_set_loop (timeline, TRUE); + g_signal_connect (timeline, "new-frame", G_CALLBACK (frame_cb), coglbox); + clutter_timeline_start (timeline); + + clutter_actor_show_all (stage); + + clutter_main (); + + return 0; +} + +G_MODULE_EXPORT const char * +test_cogl_tex_tile_describe (void) +{ + return "Texture tiling."; +} diff --git a/clutter/tests/interactive/test-cogl-vertex-buffer.c b/clutter/tests/interactive/test-cogl-vertex-buffer.c new file mode 100644 index 0000000..e31dcd1 --- /dev/null +++ b/clutter/tests/interactive/test-cogl-vertex-buffer.c @@ -0,0 +1,390 @@ +#include +#include +#include +#include +#include +#include + +/* Defines the size and resolution of the quad mesh we morph: + */ +#define MESH_WIDTH 100.0 /* number of quads along x axis */ +#define MESH_HEIGHT 100.0 /* number of quads along y axis */ +#define QUAD_WIDTH 5.0 /* width in pixels of a single quad */ +#define QUAD_HEIGHT 5.0 /* height in pixels of a single quad */ + +/* Defines a sine wave that sweeps across the mesh: + */ +#define WAVE_DEPTH ((MESH_WIDTH * QUAD_WIDTH) / 16.0) /* peak amplitude */ +#define WAVE_PERIODS 4.0 +#define WAVE_SPEED 10.0 + +/* Defines a rippling sine wave emitted from a point: + */ +#define RIPPLE_CENTER_X ((MESH_WIDTH / 2.0) * QUAD_WIDTH) +#define RIPPLE_CENTER_Y ((MESH_HEIGHT / 2.0) * QUAD_HEIGHT) +#define RIPPLE_RADIUS (MESH_WIDTH * QUAD_WIDTH) +#define RIPPLE_DEPTH ((MESH_WIDTH * QUAD_WIDTH) / 16.0) /* peak amplitude */ +#define RIPPLE_PERIODS 4.0 +#define RIPPLE_SPEED -10.0 + +/* Defines the width of the gaussian bell used to fade out the alpha + * towards the edges of the mesh (starting from the ripple center): + */ +#define GAUSSIAN_RADIUS ((MESH_WIDTH * QUAD_WIDTH) / 6.0) + +/* Our hues lie in the range [0, 1], and this defines how we map amplitude + * to hues (before scaling by {WAVE,RIPPLE}_DEPTH) + * As we are interferring two sine waves together; amplitudes lie in the + * range [-2, 2] + */ +#define HSL_OFFSET 0.5 /* the hue that we map an amplitude of 0 too */ +#define HSL_SCALE 0.25 + +typedef struct _TestState +{ + ClutterActor *dummy; + CoglHandle buffer; + float *quad_mesh_verts; + guint8 *quad_mesh_colors; + guint16 *static_indices; + guint n_static_indices; + CoglHandle indices; + ClutterTimeline *timeline; + guint frame_id; +} TestState; + +static void +frame_cb (ClutterTimeline *timeline, + gint elapsed_msecs, + TestState *state) +{ + guint x, y; + float period_progress = clutter_timeline_get_progress (timeline); + float period_progress_sin = sinf (period_progress); + float wave_shift = period_progress * WAVE_SPEED; + float ripple_shift = period_progress * RIPPLE_SPEED; + + for (y = 0; y <= MESH_HEIGHT; y++) + for (x = 0; x <= MESH_WIDTH; x++) + { + guint vert_index = (MESH_WIDTH + 1) * y + x; + float *vert = &state->quad_mesh_verts[3 * vert_index]; + + float real_x = x * QUAD_WIDTH; + float real_y = y * QUAD_HEIGHT; + + float wave_offset = (float)x / (MESH_WIDTH + 1); + float wave_angle = + (WAVE_PERIODS * 2 * G_PI * wave_offset) + wave_shift; + float wave_sin = sinf (wave_angle); + + float a_sqr = (RIPPLE_CENTER_X - real_x) * (RIPPLE_CENTER_X - real_x); + float b_sqr = (RIPPLE_CENTER_Y - real_y) * (RIPPLE_CENTER_Y - real_y); + float ripple_offset = sqrtf (a_sqr + b_sqr) / RIPPLE_RADIUS; + float ripple_angle = + (RIPPLE_PERIODS * 2 * G_PI * ripple_offset) + ripple_shift; + float ripple_sin = sinf (ripple_angle); + + float h, s, l; + guint8 *color; + + vert[2] = (wave_sin * WAVE_DEPTH) + (ripple_sin * RIPPLE_DEPTH); + + /* Burn some CPU time picking a pretty color... */ + h = (HSL_OFFSET + + wave_sin + + ripple_sin + + period_progress_sin) * HSL_SCALE; + s = 0.5; + l = 0.25 + (period_progress_sin + 1.0) / 4.0; + color = &state->quad_mesh_colors[4 * vert_index]; + /* A bit of a sneaky cast, but it seems safe to assume the ClutterColor + * typedef is set in stone... */ + clutter_color_from_hls ((ClutterColor *)color, h * 360.0, l, s); + + color[0] = (color[0] * color[3] + 128) / 255; + color[1] = (color[1] * color[3] + 128) / 255; + color[2] = (color[2] * color[3] + 128) / 255; + } + + cogl_vertex_buffer_add (state->buffer, + "gl_Vertex", + 3, /* n components */ + COGL_ATTRIBUTE_TYPE_FLOAT, + FALSE, /* normalized */ + 0, /* stride */ + state->quad_mesh_verts); + cogl_vertex_buffer_add (state->buffer, + "gl_Color", + 4, /* n components */ + COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE, + FALSE, /* normalized */ + 0, /* stride */ + state->quad_mesh_colors); + + cogl_vertex_buffer_submit (state->buffer); + + clutter_actor_set_rotation (state->dummy, + CLUTTER_Z_AXIS, + 360 * period_progress, + (MESH_WIDTH * QUAD_WIDTH) / 2, + (MESH_HEIGHT * QUAD_HEIGHT) / 2, + 0); + clutter_actor_set_rotation (state->dummy, + CLUTTER_X_AXIS, + 360 * period_progress, + (MESH_WIDTH * QUAD_WIDTH) / 2, + (MESH_HEIGHT * QUAD_HEIGHT) / 2, + 0); +} + +static void +on_paint (ClutterActor *actor, TestState *state) +{ + cogl_set_source_color4ub (0xff, 0x00, 0x00, 0xff); + cogl_vertex_buffer_draw_elements (state->buffer, + COGL_VERTICES_MODE_TRIANGLE_STRIP, + state->indices, + 0, /* min index */ + (MESH_WIDTH + 1) * + (MESH_HEIGHT + 1) - 1, /* max index */ + 0, /* indices offset */ + state->n_static_indices); +} + +static void +init_static_index_arrays (TestState *state) +{ + guint n_indices; + int x, y; + guint16 *i; + guint dir; + + /* - Each row takes (2 + 2 * MESH_WIDTH indices) + * - Thats 2 to start the triangle strip then 2 indices to add 2 triangles + * per mesh quad. + * - We have MESH_HEIGHT rows + * - It takes one extra index for linking between rows (MESH_HEIGHT - 1) + * - A 2 x 3 mesh == 20 indices... */ + n_indices = (2 + 2 * MESH_WIDTH) * MESH_HEIGHT + (MESH_HEIGHT - 1); + state->static_indices = g_malloc (sizeof (guint16) * n_indices); + state->n_static_indices = n_indices; + +#define MESH_INDEX(X, Y) (Y) * (MESH_WIDTH + 1) + (X) + + i = state->static_indices; + + /* NB: front facing == anti-clockwise winding */ + + i[0] = MESH_INDEX (0, 0); + i[1] = MESH_INDEX (0, 1); + i += 2; + +#define LEFT 0 +#define RIGHT 1 + + dir = RIGHT; + + for (y = 0; y < MESH_HEIGHT; y++) + { + for (x = 0; x < MESH_WIDTH; x++) + { + /* Add 2 triangles per mesh quad... */ + if (dir == RIGHT) + { + i[0] = MESH_INDEX (x + 1, y); + i[1] = MESH_INDEX (x + 1, y + 1); + } + else + { + i[0] = MESH_INDEX (MESH_WIDTH - x - 1, y); + i[1] = MESH_INDEX (MESH_WIDTH - x - 1, y + 1); + } + i += 2; + } + + /* Link rows... */ + + if (y == (MESH_HEIGHT - 1)) + break; + + if (dir == RIGHT) + { + i[0] = MESH_INDEX (MESH_WIDTH, y + 1); + i[1] = MESH_INDEX (MESH_WIDTH, y + 1); + i[2] = MESH_INDEX (MESH_WIDTH, y + 2); + } + else + { + i[0] = MESH_INDEX (0, y + 1); + i[1] = MESH_INDEX (0, y + 1); + i[2] = MESH_INDEX (0, y + 2); + } + i += 3; + dir = !dir; + } + +#undef MESH_INDEX + + state->indices = + cogl_vertex_buffer_indices_new (COGL_INDICES_TYPE_UNSIGNED_SHORT, + state->static_indices, + state->n_static_indices); +} + +static float +gaussian (float x, float y) +{ + /* Bell width */ + float c = GAUSSIAN_RADIUS; + + /* Peak amplitude */ + float a = 1.0; + /* float a = 1.0 / (c * sqrtf (2.0 * G_PI)); */ + + /* Center offset */ + float b = 0.0; + + float dist; + x = x - RIPPLE_CENTER_X; + y = y - RIPPLE_CENTER_Y; + dist = sqrtf (x*x + y*y); + + return a * exp ((- ((dist - b) * (dist - b))) / (2.0 * c * c)); +} + +static void +init_quad_mesh (TestState *state) +{ + int x, y; + float *vert; + guint8 *color; + + /* Note: we maintain the minimum number of vertices possible. This minimizes + * the work required when we come to morph the geometry. + * + * We use static indices into our mesh so that we can treat the data like a + * single triangle list and drawing can be done in one operation (Note: We + * are using degenerate triangles at the edges to link to the next row) + */ + state->quad_mesh_verts = + g_malloc0 (sizeof (float) * 3 * (MESH_WIDTH + 1) * (MESH_HEIGHT + 1)); + + state->quad_mesh_colors = + g_malloc0 (sizeof (guint8) * 4 * (MESH_WIDTH + 1) * (MESH_HEIGHT + 1)); + + vert = state->quad_mesh_verts; + color = state->quad_mesh_colors; + for (y = 0; y <= MESH_HEIGHT; y++) + for (x = 0; x <= MESH_WIDTH; x++) + { + vert[0] = x * QUAD_WIDTH; + vert[1] = y * QUAD_HEIGHT; + vert += 3; + + color[3] = gaussian (x * QUAD_WIDTH, + y * QUAD_HEIGHT) * 255.0; + color += 4; + } + + state->buffer = cogl_vertex_buffer_new ((MESH_WIDTH + 1)*(MESH_HEIGHT + 1)); + cogl_vertex_buffer_add (state->buffer, + "gl_Vertex", + 3, /* n components */ + COGL_ATTRIBUTE_TYPE_FLOAT, + FALSE, /* normalized */ + 0, /* stride */ + state->quad_mesh_verts); + + cogl_vertex_buffer_add (state->buffer, + "gl_Color", + 4, /* n components */ + COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE, + FALSE, /* normalized */ + 0, /* stride */ + state->quad_mesh_colors); + + cogl_vertex_buffer_submit (state->buffer); + + init_static_index_arrays (state); +} + +/* This creates an actor that has a specific size but that does not result + * in any drawing so we can do our own drawing using Cogl... */ +static ClutterActor * +create_dummy_actor (guint width, guint height) +{ + ClutterActor *group, *rect; + ClutterColor clr = { 0xff, 0xff, 0xff, 0xff}; + + group = clutter_group_new (); + rect = clutter_rectangle_new_with_color (&clr); + clutter_actor_set_size (rect, width, height); + clutter_actor_hide (rect); + clutter_container_add_actor (CLUTTER_CONTAINER (group), rect); + return group; +} + +static void +stop_and_quit (ClutterActor *actor, + TestState *state) +{ + clutter_timeline_stop (state->timeline); + clutter_main_quit (); +} + +G_MODULE_EXPORT int +test_cogl_vertex_buffer_main (int argc, char *argv[]) +{ + TestState state; + ClutterActor *stage; + gfloat stage_w, stage_h; + gint dummy_width, dummy_height; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + + clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl Vertex Buffers"); + clutter_stage_set_color (CLUTTER_STAGE (stage), CLUTTER_COLOR_Black); + g_signal_connect (stage, "destroy", G_CALLBACK (stop_and_quit), &state); + clutter_actor_get_size (stage, &stage_w, &stage_h); + + dummy_width = MESH_WIDTH * QUAD_WIDTH; + dummy_height = MESH_HEIGHT * QUAD_HEIGHT; + state.dummy = create_dummy_actor (dummy_width, dummy_height); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), state.dummy); + clutter_actor_set_position (state.dummy, + (stage_w / 2.0) - (dummy_width / 2.0), + (stage_h / 2.0) - (dummy_height / 2.0)); + + state.timeline = clutter_timeline_new (1000); + clutter_timeline_set_loop (state.timeline, TRUE); + + state.frame_id = g_signal_connect (state.timeline, + "new-frame", + G_CALLBACK (frame_cb), + &state); + + g_signal_connect (state.dummy, "paint", G_CALLBACK (on_paint), &state); + + init_quad_mesh (&state); + + clutter_actor_show_all (stage); + + clutter_timeline_start (state.timeline); + + clutter_main (); + + cogl_handle_unref (state.buffer); + cogl_handle_unref (state.indices); + + return 0; +} + +G_MODULE_EXPORT const char * +test_cogl_vertex_buffer_describe (void) +{ + return "Vertex buffers support in Cogl."; +} diff --git a/clutter/tests/interactive/test-content.c b/clutter/tests/interactive/test-content.c new file mode 100644 index 0000000..ecf731d --- /dev/null +++ b/clutter/tests/interactive/test-content.c @@ -0,0 +1,233 @@ +#include +#include +#include + +typedef struct _ColorContent { + GObject parent_instance; + + double red; + double green; + double blue; + double alpha; + + float padding; +} ColorContent; + +typedef struct _ColorContentClass { + GObjectClass parent_class; +} ColorContentClass; + +static void clutter_content_iface_init (ClutterContentIface *iface); + +G_DEFINE_TYPE_WITH_CODE (ColorContent, color_content, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTENT, + clutter_content_iface_init)) + +static void +color_content_paint_content (ClutterContent *content, + ClutterActor *actor, + ClutterPaintNode *root) +{ + ColorContent *self = (ColorContent *) content; + ClutterActorBox box, content_box; + ClutterColor color; + PangoLayout *layout; + PangoRectangle logical; + ClutterPaintNode *node; + +#if 0 + g_debug ("Painting content [%p] " + "{ r:%.2f, g:%.2f, b:%.2f, a:%.2f } " + "for actor [%p] (context: [%p])", + content, + self->red, + self->green, + self->blue, + self->alpha, + actor, context); +#endif + + clutter_actor_get_content_box (actor, &content_box); + + box = content_box; + box.x1 += self->padding; + box.y1 += self->padding; + box.x2 -= self->padding; + box.y2 -= self->padding; + + color.alpha = self->alpha * 255; + + color.red = self->red * 255; + color.green = self->green * 255; + color.blue = self->blue * 255; + + node = clutter_color_node_new (&color); + clutter_paint_node_add_rectangle (node, &box); + clutter_paint_node_add_child (root, node); + clutter_paint_node_unref (node); + + color.red = (1.0 - self->red) * 255; + color.green = (1.0 - self->green) * 255; + color.blue = (1.0 - self->blue) * 255; + + layout = clutter_actor_create_pango_layout (actor, "A"); + pango_layout_get_pixel_extents (layout, NULL, &logical); + + node = clutter_text_node_new (layout, &color); + + /* top-left */ + box.x1 = clutter_actor_box_get_x (&content_box); + box.y1 = clutter_actor_box_get_y (&content_box); + box.x2 = box.x1 + logical.width; + box.y2 = box.y1 + logical.height; + clutter_paint_node_add_rectangle (node, &box); + + /* top-right */ + box.x1 = clutter_actor_box_get_x (&content_box) + + clutter_actor_box_get_width (&content_box) + - logical.width; + box.y1 = clutter_actor_box_get_y (&content_box); + box.x2 = box.x1 + logical.width; + box.y2 = box.y1 + logical.height; + clutter_paint_node_add_rectangle (node, &box); + + /* bottom-right */ + box.x1 = clutter_actor_box_get_x (&content_box) + + clutter_actor_box_get_width (&content_box) + - logical.width; + box.y1 = clutter_actor_box_get_y (&content_box) + + clutter_actor_box_get_height (&content_box) + - logical.height; + box.x2 = box.x1 + logical.width; + box.y2 = box.y1 + logical.height; + clutter_paint_node_add_rectangle (node, &box); + + /* bottom-left */ + box.x1 = clutter_actor_box_get_x (&content_box); + box.y1 = clutter_actor_box_get_y (&content_box) + + clutter_actor_box_get_height (&content_box) + - logical.height; + box.x2 = box.x1 + logical.width; + box.y2 = box.y1 + logical.height; + clutter_paint_node_add_rectangle (node, &box); + + /* center */ + box.x1 = clutter_actor_box_get_x (&content_box) + + (clutter_actor_box_get_width (&content_box) - logical.width) / 2.0; + box.y1 = clutter_actor_box_get_y (&content_box) + + (clutter_actor_box_get_height (&content_box) - logical.height) / 2.0; + box.x2 = box.x1 + logical.width; + box.y2 = box.y1 + logical.height; + clutter_paint_node_add_rectangle (node, &box); + + clutter_paint_node_add_child (root, node); + clutter_paint_node_unref (node); + + g_object_unref (layout); +} + +static void +clutter_content_iface_init (ClutterContentIface *iface) +{ + iface->paint_content = color_content_paint_content; +} + +static void +color_content_class_init (ColorContentClass *klass) +{ +} + +static void +color_content_init (ColorContent *self) +{ +} + +static ClutterContent * +color_content_new (double red, + double green, + double blue, + double alpha, + float padding) +{ + ColorContent *self = g_object_new (color_content_get_type (), NULL); + + self->red = red; + self->green = green; + self->blue = blue; + self->alpha = alpha; + self->padding = padding; + + return (ClutterContent *) self; +} + +G_MODULE_EXPORT int +test_content_main (int argc, char *argv[]) +{ + ClutterActor *stage, *grid; + ClutterContent *content; + int i, n_rects; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return EXIT_FAILURE; + + stage = clutter_stage_new (); + clutter_actor_set_name (stage, "Stage"); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Content"); + clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + clutter_actor_show (stage); + + grid = clutter_actor_new (); + clutter_actor_set_name (grid, "Grid"); + clutter_actor_set_margin_top (grid, 12); + clutter_actor_set_margin_right (grid, 12); + clutter_actor_set_margin_bottom (grid, 12); + clutter_actor_set_margin_left (grid, 12); + clutter_actor_set_layout_manager (grid, clutter_flow_layout_new (CLUTTER_FLOW_HORIZONTAL)); + clutter_actor_add_constraint (grid, clutter_bind_constraint_new (stage, CLUTTER_BIND_SIZE, 0.0)); + clutter_actor_add_child (stage, grid); + + content = color_content_new (g_random_double_range (0.0, 1.0), + g_random_double_range (0.0, 1.0), + g_random_double_range (0.0, 1.0), + 1.0, + 2.0); + + n_rects = g_random_int_range (12, 24); + for (i = 0; i < n_rects; i++) + { + ClutterActor *box = clutter_actor_new (); + ClutterColor bg_color = { + g_random_int_range (0, 255), + g_random_int_range (0, 255), + g_random_int_range (0, 255), + 255 + }; + char *name, *color; + + color = clutter_color_to_string (&bg_color); + name = g_strconcat ("Box <", color, ">", NULL); + clutter_actor_set_name (box, name); + + g_free (name); + g_free (color); + + clutter_actor_set_background_color (box, &bg_color); + clutter_actor_set_content (box, content); + clutter_actor_set_size (box, 64, 64); + + clutter_actor_add_child (grid, box); + } + + clutter_main (); + + g_object_unref (content); + + return EXIT_SUCCESS; +} + +G_MODULE_EXPORT const char * +test_content_describe (void) +{ + return "A simple test for ClutterContent"; +} diff --git a/clutter/tests/interactive/test-devices.c b/clutter/tests/interactive/test-devices.c new file mode 100644 index 0000000..f0dd9fa --- /dev/null +++ b/clutter/tests/interactive/test-devices.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#ifdef CLUTTER_WINDOWING_X11 +#include +#endif + +typedef struct { + ClutterActor *stage; + + GHashTable *devices; +} TestDevicesApp; + +static const gchar * +device_type_name (ClutterInputDevice *device) +{ + ClutterInputDeviceType d_type; + + d_type = clutter_input_device_get_device_type (device); + switch (d_type) + { + case CLUTTER_POINTER_DEVICE: + return "Pointer"; + + case CLUTTER_KEYBOARD_DEVICE: + return "Keyboard"; + + case CLUTTER_EXTENSION_DEVICE: + return "Extension"; + + case CLUTTER_PEN_DEVICE: + return "Pen"; + + case CLUTTER_ERASER_DEVICE: + return "Eraser"; + + case CLUTTER_CURSOR_DEVICE: + return "Cursor"; + + default: + return "Unknown"; + } +} + +static const gchar * +axis_type_name (ClutterInputAxis axis) +{ + switch (axis) + { + case CLUTTER_INPUT_AXIS_X: + return "Absolute X"; + + case CLUTTER_INPUT_AXIS_Y: + return "Absolute Y"; + + case CLUTTER_INPUT_AXIS_PRESSURE: + return "Pressure"; + + case CLUTTER_INPUT_AXIS_XTILT: + return "X Tilt"; + + case CLUTTER_INPUT_AXIS_YTILT: + return "Y Tilt"; + + case CLUTTER_INPUT_AXIS_WHEEL: + return "Wheel"; + + default: + return "Unknown"; + } +} + +static gboolean +stage_button_event_cb (ClutterActor *actor, + ClutterEvent *event, + TestDevicesApp *app) +{ + ClutterInputDevice *device; + ClutterInputDevice *source_device; + ClutterActor *hand = NULL; + gdouble *axes; + guint n_axes, i; + + device = clutter_event_get_device (event); + source_device = clutter_event_get_source_device (event); + + hand = g_hash_table_lookup (app->devices, device); + + g_print ("Device: '%s' (id:%d, type: %s, source: '%s', axes: %d)\n", + clutter_input_device_get_device_name (device), + clutter_input_device_get_device_id (device), + device_type_name (device), + source_device != device + ? clutter_input_device_get_device_name (source_device) + : "", + clutter_input_device_get_n_axes (device)); + + if (hand != NULL) + { + gfloat event_x, event_y; + + clutter_event_get_coords (event, &event_x, &event_y); + clutter_actor_set_position (hand, event_x, event_y); + } + + axes = clutter_event_get_axes (event, &n_axes); + for (i = 0; i < n_axes; i++) + { + ClutterInputAxis axis; + + axis = clutter_input_device_get_axis (device, i); + if (axis == CLUTTER_INPUT_AXIS_IGNORE) + continue; + + g_print ("\tAxis[%2d][%s].value: %.2f\n", + i, + axis_type_name (axis), + axes[i]); + } + + return FALSE; +} + +static gboolean +stage_motion_event_cb (ClutterActor *actor, + ClutterEvent *event, + TestDevicesApp *app) +{ + ClutterInputDevice *device; + ClutterActor *hand = NULL; + + device = clutter_event_get_device (event); + + hand = g_hash_table_lookup (app->devices, device); + if (hand != NULL) + { + gfloat event_x, event_y; + + clutter_event_get_coords (event, &event_x, &event_y); + clutter_actor_set_position (hand, event_x, event_y); + + return TRUE; + } + + return FALSE; +} + +static void +manager_device_added_cb (ClutterDeviceManager *manager, + ClutterInputDevice *device, + TestDevicesApp *app) +{ + ClutterInputDeviceType device_type; + ClutterActor *hand = NULL; + + g_print ("got a %s device '%s' with id %d\n", + device_type_name (device), + clutter_input_device_get_device_name (device), + clutter_input_device_get_device_id (device)); + + device_type = clutter_input_device_get_device_type (device); + if (device_type == CLUTTER_POINTER_DEVICE || + device_type == CLUTTER_PEN_DEVICE || + device_type == CLUTTER_POINTER_DEVICE) + { + g_print ("*** enabling device '%s' ***\n", + clutter_input_device_get_device_name (device)); + + clutter_input_device_set_enabled (device, TRUE); + + hand = clutter_texture_new_from_file (TESTS_DATADIR + G_DIR_SEPARATOR_S + "redhand.png", + NULL); + g_hash_table_insert (app->devices, device, hand); + + clutter_container_add_actor (CLUTTER_CONTAINER (app->stage), hand); + } +} + +static void +manager_device_removed_cb (ClutterDeviceManager *manager, + ClutterInputDevice *device, + TestDevicesApp *app) +{ + ClutterInputDeviceType device_type; + ClutterActor *hand = NULL; + + g_print ("removed a %s device '%s' with id %d\n", + device_type_name (device), + clutter_input_device_get_device_name (device), + clutter_input_device_get_device_id (device)); + + device_type = clutter_input_device_get_device_type (device); + if (device_type == CLUTTER_POINTER_DEVICE || + device_type == CLUTTER_PEN_DEVICE || + device_type == CLUTTER_POINTER_DEVICE) + { + hand = g_hash_table_lookup (app->devices, device); + if (hand != NULL) + clutter_container_add_actor (CLUTTER_CONTAINER (app->stage), hand); + + g_hash_table_remove (app->devices, device); + } +} + +G_MODULE_EXPORT int +test_devices_main (int argc, char **argv) +{ + ClutterActor *stage; + TestDevicesApp *app; + ClutterDeviceManager *manager; + const GSList *stage_devices, *l; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + app = g_new0 (TestDevicesApp, 1); + app->devices = g_hash_table_new (g_direct_hash, g_direct_equal) ; + + stage = clutter_stage_new (); + clutter_actor_set_background_color (stage, CLUTTER_COLOR_LightSkyBlue); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Devices"); + clutter_stage_hide_cursor (CLUTTER_STAGE (stage)); + g_signal_connect (stage, + "destroy", G_CALLBACK (clutter_main_quit), + NULL); + g_signal_connect (stage, + "motion-event", G_CALLBACK (stage_motion_event_cb), + app); + g_signal_connect (stage, + "button-press-event", G_CALLBACK (stage_button_event_cb), + app); + app->stage = stage; + + clutter_actor_show_all (stage); + + manager = clutter_device_manager_get_default (); + g_signal_connect (manager, + "device-added", G_CALLBACK (manager_device_added_cb), + app); + g_signal_connect (manager, + "device-removed", G_CALLBACK (manager_device_removed_cb), + app); + + stage_devices = clutter_device_manager_peek_devices (manager); + + if (stage_devices == NULL) + g_error ("No input devices found."); + + for (l = stage_devices; l != NULL; l = l->next) + { + ClutterInputDevice *device = l->data; + ClutterInputDeviceType device_type; + ClutterActor *hand = NULL; + + g_print ("got a %s device '%s' with id %d\n", + device_type_name (device), + clutter_input_device_get_device_name (device), + clutter_input_device_get_device_id (device)); + + device_type = clutter_input_device_get_device_type (device); + if (device_type == CLUTTER_POINTER_DEVICE || + device_type == CLUTTER_PEN_DEVICE || + device_type == CLUTTER_POINTER_DEVICE) + { + g_print ("*** enabling device '%s' ***\n", + clutter_input_device_get_device_name (device)); + + clutter_input_device_set_enabled (device, TRUE); + + hand = clutter_texture_new_from_file (TESTS_DATADIR + G_DIR_SEPARATOR_S + "redhand.png", + NULL); + g_hash_table_insert (app->devices, device, hand); + + clutter_container_add_actor (CLUTTER_CONTAINER (stage), hand); + } + } + + clutter_main (); + + return EXIT_SUCCESS; +} diff --git a/clutter/tests/interactive/test-easing.c b/clutter/tests/interactive/test-easing.c new file mode 100644 index 0000000..feab40e --- /dev/null +++ b/clutter/tests/interactive/test-easing.c @@ -0,0 +1,270 @@ +#include +#include +#include + +/* all the easing modes provided by Clutter */ +static const struct { + const gchar *name; + ClutterAnimationMode mode; +} easing_modes[] = { + { "linear", CLUTTER_LINEAR }, + { "easeInQuad", CLUTTER_EASE_IN_QUAD }, + { "easeOutQuad", CLUTTER_EASE_OUT_QUAD }, + { "easeInOutQuad", CLUTTER_EASE_IN_OUT_QUAD }, + { "easeInCubic", CLUTTER_EASE_IN_CUBIC }, + { "easeOutCubic", CLUTTER_EASE_OUT_CUBIC }, + { "easeInOutCubic", CLUTTER_EASE_IN_OUT_CUBIC }, + { "easeInQuart", CLUTTER_EASE_IN_QUART }, + { "easeOutQuart", CLUTTER_EASE_OUT_QUART }, + { "easeInOutQuart", CLUTTER_EASE_IN_OUT_QUART }, + { "easeInQuint", CLUTTER_EASE_IN_QUINT }, + { "easeOutQuint", CLUTTER_EASE_OUT_QUINT }, + { "easeInOutQuint", CLUTTER_EASE_IN_OUT_QUINT }, + { "easeInSine", CLUTTER_EASE_IN_SINE }, + { "easeOutSine", CLUTTER_EASE_OUT_SINE }, + { "easeInOutSine", CLUTTER_EASE_IN_OUT_SINE }, + { "easeInExpo", CLUTTER_EASE_IN_EXPO }, + { "easeOutExpo", CLUTTER_EASE_OUT_EXPO }, + { "easeInOutExpo", CLUTTER_EASE_IN_OUT_EXPO }, + { "easeInCirc", CLUTTER_EASE_IN_CIRC }, + { "easeOutCirc", CLUTTER_EASE_OUT_CIRC }, + { "easeInOutCirc", CLUTTER_EASE_IN_OUT_CIRC }, + { "easeInElastic", CLUTTER_EASE_IN_ELASTIC }, + { "easeOutElastic", CLUTTER_EASE_OUT_ELASTIC }, + { "easeInOutElastic", CLUTTER_EASE_IN_OUT_ELASTIC }, + { "easeInBack", CLUTTER_EASE_IN_BACK }, + { "easeOutBack", CLUTTER_EASE_OUT_BACK }, + { "easeInOutBack", CLUTTER_EASE_IN_OUT_BACK }, + { "easeInBounce", CLUTTER_EASE_IN_BOUNCE }, + { "easeOutBounce", CLUTTER_EASE_OUT_BOUNCE }, + { "easeInOutBounce", CLUTTER_EASE_IN_OUT_BOUNCE }, +}; + +#define HELP_TEXT "Easing mode: %s (%d of %d)\n" \ + "Left click to tween\n" \ + "Right click to change the easing mode" + +static const gint n_easing_modes = G_N_ELEMENTS (easing_modes); +static gint current_mode = 0; + +static gint duration = 1; +static gboolean recenter = FALSE; + +static ClutterActor *main_stage = NULL; +static ClutterActor *easing_mode_label = NULL; + +static ClutterAnimation *last_animation = NULL; + +/* recenter_bouncer: + * + * repositions (through an animation) the bouncer at the center of the stage + */ +static void +recenter_bouncer (ClutterAnimation *animation, + ClutterActor *rectangle) +{ + gfloat base_x, base_y; + gint cur_mode; + + base_x = clutter_actor_get_width (main_stage) / 2; + base_y = clutter_actor_get_height (main_stage) / 2; + + cur_mode = easing_modes[current_mode].mode; + + clutter_actor_animate (rectangle, cur_mode, 250, + "x", base_x, + "y", base_y, + NULL); +} + +static gboolean +on_button_press (ClutterActor *actor, + ClutterButtonEvent *event, + ClutterActor *rectangle) +{ + if (event->button == CLUTTER_BUTTON_SECONDARY) + { + gchar *text; + + /* cycle through the various easing modes */ + current_mode = (current_mode + 1 < n_easing_modes) + ? current_mode + 1 + : 0; + + /* update the text of the label */ + text = g_strdup_printf (HELP_TEXT, + easing_modes[current_mode].name, + current_mode + 1, + n_easing_modes); + + clutter_text_set_text (CLUTTER_TEXT (easing_mode_label), text); + g_free (text); + } + else if (event->button == CLUTTER_BUTTON_PRIMARY) + { + ClutterAnimation *animation; + ClutterAnimationMode cur_mode; + + cur_mode = easing_modes[current_mode].mode; + + /* tween the actor using the current easing mode */ + animation = + clutter_actor_animate (rectangle, cur_mode, duration * 1000, + "x", event->x, + "y", event->y, + NULL); + + /* if we were asked to, recenter the bouncer at the end of the + * animation. we keep track of the animation to avoid connecting + * the signal handler to the same Animation twice. + */ + if (recenter && last_animation != animation) + g_signal_connect_after (animation, "completed", + G_CALLBACK (recenter_bouncer), + rectangle); + + last_animation = animation; + } + + return TRUE; +} + +static gboolean +draw_bouncer (ClutterCairoTexture *texture, + cairo_t *cr) +{ + const ClutterColor *bouncer_color; + cairo_pattern_t *pattern; + guint width, height; + float radius; + + clutter_cairo_texture_get_surface_size (texture, &width, &height); + + radius = MAX (width, height); + + clutter_cairo_texture_clear (texture); + + cairo_arc (cr, radius / 2, radius / 2, radius / 2, 0.0, 2.0 * G_PI); + + bouncer_color = CLUTTER_COLOR_DarkScarletRed; + + pattern = cairo_pattern_create_radial (radius / 2, radius / 2, 0, + radius, radius, radius); + cairo_pattern_add_color_stop_rgba (pattern, + 0, + bouncer_color->red / 255.0, + bouncer_color->green / 255.0, + bouncer_color->blue / 255.0, + bouncer_color->alpha / 255.0); + cairo_pattern_add_color_stop_rgba (pattern, + 0.85, + bouncer_color->red / 255.0, + bouncer_color->green / 255.0, + bouncer_color->blue / 255.0, + 0.25); + + cairo_set_source (cr, pattern); + cairo_fill_preserve (cr); + + cairo_pattern_destroy (pattern); + + return TRUE; +} + +static ClutterActor * +make_bouncer (gfloat width, + gfloat height) +{ + ClutterActor *retval; + + retval = clutter_cairo_texture_new (width, height); + g_signal_connect (retval, "draw", G_CALLBACK (draw_bouncer), NULL); + + clutter_actor_set_name (retval, "bouncer"); + clutter_actor_set_size (retval, width, height); + clutter_actor_set_anchor_point (retval, width / 2, height / 2); + clutter_actor_set_reactive (retval, TRUE); + + /* make sure we draw the bouncer immediately */ + clutter_cairo_texture_invalidate (CLUTTER_CAIRO_TEXTURE (retval)); + + return retval; +} + +static GOptionEntry test_easing_entries[] = { + { + "re-center", 'r', + 0, + G_OPTION_ARG_NONE, &recenter, + "Re-center the actor when the animation ends", + NULL + }, + { + "duration", 'd', + 0, + G_OPTION_ARG_INT, &duration, + "Duration of the animation", + "SECONDS" + }, + + { NULL } +}; + +G_MODULE_EXPORT int +test_easing_main (int argc, char *argv[]) +{ + ClutterActor *stage, *rect, *label; + gchar *text; + gfloat stage_width, stage_height; + GError *error = NULL; + + if (clutter_init_with_args (&argc, &argv, + NULL, + test_easing_entries, + NULL, + &error) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Easing Modes"); + clutter_actor_set_background_color (stage, CLUTTER_COLOR_LightSkyBlue); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + main_stage = stage; + + clutter_actor_get_size (stage, &stage_width, &stage_height); + + /* create the actor that we want to tween */ + rect = make_bouncer (50, 50); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); + clutter_actor_set_position (rect, stage_width / 2, stage_height / 2); + + text = g_strdup_printf (HELP_TEXT, + easing_modes[current_mode].name, + current_mode + 1, + n_easing_modes); + + label = clutter_text_new (); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), label); + clutter_text_set_text (CLUTTER_TEXT (label), text); + clutter_actor_add_constraint (label, clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0.95)); + clutter_actor_add_constraint (label, clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.95)); + easing_mode_label = label; + + g_free (text); + + g_signal_connect (stage, + "button-press-event", G_CALLBACK (on_button_press), + rect); + + clutter_actor_show (stage); + + clutter_main (); + + return EXIT_SUCCESS; +} + +G_MODULE_EXPORT const char * +test_easing_describe (void) +{ + return "Visualize all easing modes provided by Clutter"; +} diff --git a/clutter/tests/interactive/test-events.c b/clutter/tests/interactive/test-events.c new file mode 100644 index 0000000..09424de --- /dev/null +++ b/clutter/tests/interactive/test-events.c @@ -0,0 +1,502 @@ +#include +#include +#include + +gboolean IsFullScreen = FALSE, IsMotion = TRUE; + +static const gchar * +get_event_type_name (const ClutterEvent *event) +{ + switch (event->type) + { + case CLUTTER_BUTTON_PRESS: + return "BUTTON PRESS"; + + case CLUTTER_BUTTON_RELEASE: + return "BUTTON_RELEASE"; + + case CLUTTER_KEY_PRESS: + return "KEY PRESS"; + + case CLUTTER_KEY_RELEASE: + return "KEY RELEASE"; + + case CLUTTER_ENTER: + return "ENTER"; + + case CLUTTER_LEAVE: + return "LEAVE"; + + case CLUTTER_MOTION: + return "MOTION"; + + case CLUTTER_DELETE: + return "DELETE"; + + case CLUTTER_TOUCH_BEGIN: + return "TOUCH BEGIN"; + + case CLUTTER_TOUCH_UPDATE: + return "TOUCH UPDATE"; + + case CLUTTER_TOUCH_END: + return "TOUCH END"; + + case CLUTTER_TOUCH_CANCEL: + return "TOUCH CANCEL"; + + default: + return "EVENT"; + } +} + +static gchar * +get_event_state_string (const ClutterEvent *event) +{ + gchar *mods[18]; + int i = 0; + ClutterModifierType state = clutter_event_get_state (event); + + if (state & CLUTTER_SHIFT_MASK) + mods[i++] = "shift"; + if (state & CLUTTER_LOCK_MASK) + mods[i++] = "lock"; + if (state & CLUTTER_CONTROL_MASK) + mods[i++] = "ctrl"; + if (state & CLUTTER_MOD1_MASK) + mods[i++] = "mod1"; + if (state & CLUTTER_MOD2_MASK) + mods[i++] = "mod2"; + if (state & CLUTTER_MOD3_MASK) + mods[i++] = "mod3"; + if (state & CLUTTER_MOD4_MASK) + mods[i++] = "mod4"; + if (state & CLUTTER_MOD5_MASK) + mods[i++] = "mod5"; + if (state & CLUTTER_BUTTON1_MASK) + mods[i++] = "btn1"; + if (state & CLUTTER_BUTTON2_MASK) + mods[i++] = "btn2"; + if (state & CLUTTER_BUTTON3_MASK) + mods[i++] = "btn3"; + if (state & CLUTTER_BUTTON4_MASK) + mods[i++] = "btn4"; + if (state & CLUTTER_BUTTON5_MASK) + mods[i++] = "btn5"; + if (state & CLUTTER_SUPER_MASK) + mods[i++] = "super"; + if (state & CLUTTER_HYPER_MASK) + mods[i++] = "hyper"; + if (state & CLUTTER_META_MASK) + mods[i++] = "meta"; + if (state & CLUTTER_RELEASE_MASK) + mods[i++] = "release"; + + if (i == 0) + mods[i++] = "-"; + + mods[i] = NULL; + return g_strjoinv (",", mods); +} + +static void +stage_state_cb (ClutterStage *stage, + gpointer data) +{ + gchar *detail = (gchar*)data; + + printf("[stage signal] %s\n", detail); +} + +static gboolean +blue_button_cb (ClutterActor *actor, + ClutterEvent *event, + gpointer data) +{ + ClutterActor *stage; + + stage = clutter_actor_get_stage (actor); + + if (IsFullScreen) + IsFullScreen = FALSE; + else + IsFullScreen = TRUE; + + clutter_stage_set_fullscreen (CLUTTER_STAGE (stage), IsFullScreen); + + g_print ("*** Fullscreen %s ***\n", + IsFullScreen ? "enabled" : "disabled"); + + return FALSE; +} + +static gboolean +red_button_cb (ClutterActor *actor, + ClutterEvent *event, + gpointer data) +{ + ClutterActor *stage; + + if (IsMotion) + IsMotion = FALSE; + else + IsMotion = TRUE; + + stage = clutter_actor_get_stage (actor); + clutter_stage_set_motion_events_enabled (CLUTTER_STAGE (stage), + IsMotion); + + g_print ("*** Per actor motion events %s ***\n", + IsMotion ? "enabled" : "disabled"); + + return FALSE; +} + +static gboolean +capture_cb (ClutterActor *actor, + ClutterEvent *event, + gpointer data) +{ + g_print ("* captured event '%s' for type '%s' *\n", + get_event_type_name (event), + G_OBJECT_TYPE_NAME (actor)); + + return FALSE; +} + +static void +key_focus_in_cb (ClutterActor *actor, + gpointer data) +{ + ClutterActor *focus_box = CLUTTER_ACTOR (data); + + if (CLUTTER_IS_STAGE (actor)) + clutter_actor_hide (focus_box); + else + { + clutter_actor_set_position (focus_box, + clutter_actor_get_x (actor) - 5, + clutter_actor_get_y (actor) - 5); + + clutter_actor_set_size (focus_box, + clutter_actor_get_width (actor) + 10, + clutter_actor_get_height (actor) + 10); + clutter_actor_show (focus_box); + } +} + +static void +fill_keybuf (char *keybuf, ClutterKeyEvent *event) +{ + char utf8[6]; + int len; + + /* printable character, if any (ß, ∑) */ + len = g_unichar_to_utf8 (event->unicode_value, utf8); + utf8[len] = '\0'; + sprintf (keybuf, "'%s' ", utf8); + + /* key combination (s, S, Delete) */ + len = g_unichar_to_utf8 (clutter_keysym_to_unicode (event->keyval), utf8); + utf8[len] = '\0'; + + if (event->modifier_state & CLUTTER_SHIFT_MASK) + strcat (keybuf, ""); + + if (event->modifier_state & CLUTTER_LOCK_MASK) + strcat (keybuf, ""); + + if (event->modifier_state & CLUTTER_CONTROL_MASK) + strcat (keybuf, ""); + + if (event->modifier_state & CLUTTER_MOD1_MASK) + strcat (keybuf, ""); + + if (event->modifier_state & CLUTTER_MOD2_MASK) + strcat (keybuf, ""); + + if (event->modifier_state & CLUTTER_MOD3_MASK) + strcat (keybuf, ""); + + if (event->modifier_state & CLUTTER_MOD4_MASK) + strcat (keybuf, ""); + + if (event->modifier_state & CLUTTER_MOD5_MASK) + strcat (keybuf, ""); + + strcat (keybuf, utf8); +} + +static gboolean +input_cb (ClutterActor *actor, + ClutterEvent *event, + gpointer data) +{ + ClutterActor *stage = clutter_actor_get_stage (actor); + ClutterActor *source_actor = clutter_event_get_source (event); + ClutterPoint position; + gchar *state; + gchar keybuf[128]; + gint device_id; + gint source_device_id = 0; + + device_id = clutter_event_get_device_id (event); + if (clutter_event_get_source_device (event) != NULL) + source_device_id = clutter_input_device_get_device_id (clutter_event_get_source_device (event)); + + state = get_event_state_string (event); + + switch (event->type) + { + case CLUTTER_KEY_PRESS: + fill_keybuf (keybuf, &event->key); + printf ("[%s] KEY PRESS %s", + clutter_actor_get_name (source_actor), + keybuf); + break; + case CLUTTER_KEY_RELEASE: + fill_keybuf (keybuf, &event->key); + printf ("[%s] KEY RELEASE %s", + clutter_actor_get_name (source_actor), + keybuf); + break; + case CLUTTER_MOTION: + clutter_event_get_position (event, &position); + g_print ("[%s] MOTION (coords:%.02f,%.02f device:%d/%d state:%s)", + clutter_actor_get_name (source_actor), position.x, position.y, + device_id, source_device_id, state); + break; + case CLUTTER_ENTER: + g_print ("[%s] ENTER (from:%s device:%d/%d state:%s)", + clutter_actor_get_name (source_actor), + clutter_event_get_related (event) != NULL + ? clutter_actor_get_name (clutter_event_get_related (event)) + : "", + device_id, source_device_id, state); + break; + case CLUTTER_LEAVE: + g_print ("[%s] LEAVE (to:%s device:%d/%d state:%s)", + clutter_actor_get_name (source_actor), + clutter_event_get_related (event) != NULL + ? clutter_actor_get_name (clutter_event_get_related (event)) + : "", + device_id, source_device_id, state); + break; + case CLUTTER_BUTTON_PRESS: + clutter_event_get_position (event, &position); + g_print ("[%s] BUTTON PRESS (button:%i, click count:%i coords:%.02f,%.02f device:%d/%d, state:%s)", + clutter_actor_get_name (source_actor), + clutter_event_get_button (event), + clutter_event_get_click_count (event), + position.x, position.y, + device_id, source_device_id, state); + break; + case CLUTTER_BUTTON_RELEASE: + clutter_event_get_position (event, &position); + g_print ("[%s] BUTTON RELEASE (button:%i, click count:%i coords:%.02f,%.02f device:%d/%d state:%s)", + clutter_actor_get_name (source_actor), + clutter_event_get_button (event), + clutter_event_get_click_count (event), + position.x, position.y, + device_id, source_device_id, state); + + if (source_actor == stage) + clutter_stage_set_key_focus (CLUTTER_STAGE (stage), NULL); + else if (source_actor == actor && + clutter_actor_get_parent (actor) == stage) + clutter_stage_set_key_focus (CLUTTER_STAGE (stage), actor); + break; + case CLUTTER_TOUCH_BEGIN: + clutter_event_get_position (event, &position); + g_print ("[%s] TOUCH BEGIN (seq:%p coords:%.02f,%.02f device:%d/%d state:%s)", + clutter_actor_get_name (source_actor), + clutter_event_get_event_sequence (event), + position.x, position.y, + device_id, source_device_id, state); + break; + case CLUTTER_TOUCH_UPDATE: + clutter_event_get_position (event, &position); + g_print ("[%s] TOUCH UPDATE (seq:%p coords:%.02f,%.02f device:%d/%d state:%s)", + clutter_actor_get_name (source_actor), + clutter_event_get_event_sequence (event), + position.x, position.y, + device_id, source_device_id, state); + break; + case CLUTTER_TOUCH_END: + clutter_event_get_position (event, &position); + g_print ("[%s] TOUCH END (seq:%p coords:%.02f,%.02f device:%d/%d state:%s)", + clutter_actor_get_name (source_actor), + clutter_event_get_event_sequence (event), + position.x, position.y, + device_id, source_device_id, state); + break; + case CLUTTER_TOUCH_CANCEL: + clutter_event_get_position (event, &position); + g_print ("[%s] TOUCH CANCEL (seq:%p coords:%.02f,%.02f device:%d/%d state:%s)", + clutter_actor_get_name (source_actor), + clutter_event_get_event_sequence (event), + position.x, position.y, + device_id, source_device_id, state); + break; + case CLUTTER_SCROLL: + { + ClutterScrollDirection dir = clutter_event_get_scroll_direction (event); + + if (dir == CLUTTER_SCROLL_SMOOTH) + { + gdouble dx, dy; + clutter_event_get_scroll_delta (event, &dx, &dy); + g_print ("[%s] BUTTON SCROLL (direction:smooth %.02f,%.02f state:%s)", + clutter_actor_get_name (source_actor), dx, dy, state); + } + else + g_print ("[%s] BUTTON SCROLL (direction:%s state:%s)", + clutter_actor_get_name (source_actor), + dir == CLUTTER_SCROLL_UP ? "up" : + dir == CLUTTER_SCROLL_DOWN ? "down" : + dir == CLUTTER_SCROLL_LEFT ? "left" : + dir == CLUTTER_SCROLL_RIGHT ? "right" : "?", + state); + } + break; + case CLUTTER_STAGE_STATE: + g_print ("[%s] STAGE STATE", clutter_actor_get_name (source_actor)); + break; + case CLUTTER_DESTROY_NOTIFY: + g_print ("[%s] DESTROY NOTIFY", clutter_actor_get_name (source_actor)); + break; + case CLUTTER_CLIENT_MESSAGE: + g_print ("[%s] CLIENT MESSAGE", clutter_actor_get_name (source_actor)); + break; + case CLUTTER_DELETE: + g_print ("[%s] DELETE", clutter_actor_get_name (source_actor)); + break; + case CLUTTER_NOTHING: + return FALSE; + } + + g_free (state); + + if (source_actor == actor) + g_print (" *source*"); + + g_print ("\n"); + + return FALSE; +} + +G_MODULE_EXPORT int +test_events_main (int argc, char *argv[]) +{ + ClutterActor *stage, *actor, *focus_box, *group; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Events"); + clutter_actor_set_name (stage, "Stage"); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + g_signal_connect (stage, "event", G_CALLBACK (input_cb), "stage"); + g_signal_connect (stage, "fullscreen", + G_CALLBACK (stage_state_cb), "fullscreen"); + g_signal_connect (stage, "unfullscreen", + G_CALLBACK (stage_state_cb), "unfullscreen"); + g_signal_connect (stage, "activate", + G_CALLBACK (stage_state_cb), "activate"); + g_signal_connect (stage, "deactivate", + G_CALLBACK (stage_state_cb), "deactivate"); + + focus_box = clutter_rectangle_new_with_color (CLUTTER_COLOR_Black); + clutter_actor_set_name (focus_box, "Focus Box"); + clutter_container_add (CLUTTER_CONTAINER(stage), focus_box, NULL); + + actor = clutter_rectangle_new_with_color (CLUTTER_COLOR_Red); + clutter_actor_set_name (actor, "Red Box"); + clutter_actor_set_size (actor, 100, 100); + clutter_actor_set_position (actor, 100, 100); + clutter_actor_set_reactive (actor, TRUE); + clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL); + g_signal_connect (actor, "event", G_CALLBACK (input_cb), "red box"); + g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb), + focus_box); + /* Toggle motion - enter/leave capture */ + g_signal_connect (actor, "button-press-event", + G_CALLBACK (red_button_cb), NULL); + + clutter_stage_set_key_focus (CLUTTER_STAGE (stage), actor); + + actor = clutter_rectangle_new_with_color (CLUTTER_COLOR_Green); + clutter_actor_set_name (actor, "Green Box"); + clutter_actor_set_size (actor, 100, 100); + clutter_actor_set_position (actor, 250, 100); + clutter_actor_set_reactive (actor, TRUE); + clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL); + g_signal_connect (actor, "event", G_CALLBACK (input_cb), "green box"); + g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb), + focus_box); + g_signal_connect (actor, "captured-event", G_CALLBACK (capture_cb), NULL); + + actor = clutter_rectangle_new_with_color (CLUTTER_COLOR_Blue); + clutter_actor_set_name (actor, "Blue Box"); + clutter_actor_set_size (actor, 100, 100); + clutter_actor_set_position (actor, 400, 100); + clutter_actor_set_reactive (actor, TRUE); + clutter_container_add (CLUTTER_CONTAINER(stage), actor, NULL); + g_signal_connect (actor, "event", G_CALLBACK (input_cb), "blue box"); + g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb), + focus_box); + /* Fullscreen */ + g_signal_connect (actor, "button-press-event", + G_CALLBACK (blue_button_cb), NULL); + + /* non reactive */ + actor = clutter_rectangle_new_with_color (CLUTTER_COLOR_Black); + clutter_actor_set_name (actor, "Black Box"); + clutter_actor_set_size (actor, 400, 50); + clutter_actor_set_position (actor, 100, 250); + clutter_container_add (CLUTTER_CONTAINER(stage), actor, NULL); + g_signal_connect (actor, "event", G_CALLBACK (input_cb), "blue box"); + g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb), + focus_box); + g_signal_connect (stage, "key-focus-in", G_CALLBACK (key_focus_in_cb), + focus_box); + + /* non reactive group, with reactive child */ + actor = clutter_rectangle_new_with_color (CLUTTER_COLOR_Yellow); + clutter_actor_set_name (actor, "Yellow Box"); + clutter_actor_set_size (actor, 100, 100); + clutter_actor_set_reactive (actor, TRUE); + + g_signal_connect (actor, "event", G_CALLBACK (input_cb), "yellow box"); + + /* note group not reactive */ + group = clutter_group_new (); + clutter_container_add (CLUTTER_CONTAINER (group), actor, NULL); + clutter_container_add (CLUTTER_CONTAINER (stage), group, NULL); + clutter_actor_set_position (group, 100, 350); + clutter_actor_show_all (group); + + /* border actor */ + actor = clutter_rectangle_new_with_color (CLUTTER_COLOR_Magenta); + clutter_actor_set_name (actor, "Border Box"); + clutter_actor_set_size (actor, 100, 100); + clutter_actor_set_position (actor, + (clutter_actor_get_width (stage) - 100) / 2, + clutter_actor_get_height (stage) - 100); + clutter_actor_set_reactive (actor, TRUE); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), actor); + g_signal_connect (actor, "event", G_CALLBACK (input_cb), NULL); + + clutter_actor_show_all (CLUTTER_ACTOR (stage)); + + clutter_main(); + + return 0; +} + +G_MODULE_EXPORT const char * +test_events_describe (void) +{ + return "Event handling and propagation."; +} diff --git a/clutter/tests/interactive/test-fbo.c b/clutter/tests/interactive/test-fbo.c new file mode 100644 index 0000000..c659fe1 --- /dev/null +++ b/clutter/tests/interactive/test-fbo.c @@ -0,0 +1,105 @@ +#include + +#include +#include +#include +#include + +#define STAGE_WIDTH 800 +#define STAGE_HEIGHT 600 + +ClutterActor * +make_source (void) +{ + ClutterActor *source, *actor; + GError *error = NULL; + gchar *file; + + ClutterColor yellow = {0xff, 0xff, 0x00, 0xff}; + + source = clutter_group_new (); + + file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL); + actor = clutter_texture_new_from_file (file, &error); + if (!actor) + g_error("pixbuf load failed: %s", error ? error->message : "Unknown"); + + g_free (file); + + clutter_container_add_actor (CLUTTER_CONTAINER (source), actor); + + actor = clutter_text_new_with_text ("Sans Bold 50px", "Clutter"); + + clutter_text_set_color (CLUTTER_TEXT (actor), &yellow); + clutter_actor_set_y (actor, clutter_actor_get_height(source) + 5); + clutter_container_add_actor (CLUTTER_CONTAINER (source), actor); + + return source; +} + +G_MODULE_EXPORT int +test_fbo_main (int argc, char *argv[]) +{ + ClutterActor *fbo; + ClutterActor *onscreen_source; + ClutterActor *stage; + ClutterAnimation *animation; + int x_pos = 200; + int y_pos = 100; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + if (clutter_feature_available (CLUTTER_FEATURE_OFFSCREEN) == FALSE) + g_error("This test requires CLUTTER_FEATURE_OFFSCREEN"); + + stage = clutter_stage_new (); + clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT); + clutter_actor_set_background_color (stage, CLUTTER_COLOR_SkyBlue); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Texture from Actor"); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + /* Create the first source */ + onscreen_source = make_source(); + clutter_actor_show_all (onscreen_source); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), onscreen_source); + + y_pos = (STAGE_HEIGHT/2.0) - + (clutter_actor_get_height (onscreen_source)/2.0); + clutter_actor_set_position (onscreen_source, x_pos, y_pos); + x_pos += clutter_actor_get_width (onscreen_source); + + animation = clutter_actor_animate (onscreen_source, + CLUTTER_LINEAR, + 5000, /* 1 second duration */ + "rotation-angle-y", 360.0f, + NULL); + clutter_animation_set_loop (animation, TRUE); + + /* Second hand = actor from onscreen_source */ + if ((fbo = clutter_texture_new_from_actor (onscreen_source)) == NULL) + g_error("onscreen fbo creation failed"); + + clutter_actor_set_position (fbo, x_pos, y_pos); + x_pos += clutter_actor_get_width (fbo); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), fbo); + + /* Third hand = actor from Second hand */ + if ((fbo = clutter_texture_new_from_actor (fbo)) == NULL) + g_error("fbo from fbo creation failed"); + + clutter_actor_set_position (fbo, x_pos, y_pos); + x_pos += clutter_actor_get_width (fbo); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), fbo); + + clutter_actor_show_all (stage); + clutter_main (); + + return 0; +} + +G_MODULE_EXPORT const char * +test_fbo_describe (void) +{ + return "Create a texture from an actor."; +} diff --git a/clutter/tests/interactive/test-grab.c b/clutter/tests/interactive/test-grab.c new file mode 100644 index 0000000..931d0c4 --- /dev/null +++ b/clutter/tests/interactive/test-grab.c @@ -0,0 +1,251 @@ +#include +#include + +static void +stage_state_cb (ClutterStage *stage, + gpointer data) +{ + gchar *detail = (gchar*)data; + + printf("[stage signal] %s\n", detail); +} + +static gboolean +debug_event_cb (ClutterActor *actor, + ClutterEvent *event, + gpointer data) +{ + gchar keybuf[9], *source = (gchar*)data; + int len = 0; + + switch (event->type) + { + case CLUTTER_KEY_PRESS: + len = g_unichar_to_utf8 (clutter_keysym_to_unicode (event->key.keyval), + keybuf); + keybuf[len] = '\0'; + printf ("[%s] KEY PRESS '%s'", source, keybuf); + break; + case CLUTTER_KEY_RELEASE: + len = g_unichar_to_utf8 (clutter_keysym_to_unicode (event->key.keyval), + keybuf); + keybuf[len] = '\0'; + printf ("[%s] KEY RELEASE '%s'", source, keybuf); + break; + case CLUTTER_MOTION: + printf("[%s] MOTION", source); + break; + case CLUTTER_ENTER: + printf("[%s] ENTER", source); + break; + case CLUTTER_LEAVE: + printf("[%s] LEAVE", source); + break; + case CLUTTER_BUTTON_PRESS: + printf("[%s] BUTTON PRESS (click count:%i)", + source, event->button.click_count); + break; + case CLUTTER_BUTTON_RELEASE: + printf("[%s] BUTTON RELEASE", source); + break; + case CLUTTER_SCROLL: + printf("[%s] BUTTON SCROLL", source); + break; + case CLUTTER_STAGE_STATE: + printf("[%s] STAGE STATE", source); + break; + case CLUTTER_DESTROY_NOTIFY: + printf("[%s] DESTROY NOTIFY", source); + break; + case CLUTTER_CLIENT_MESSAGE: + printf("[%s] CLIENT MESSAGE\n", source); + break; + case CLUTTER_DELETE: + printf("[%s] DELETE", source); + break; + case CLUTTER_NOTHING: + return FALSE; + } + + if (clutter_event_get_source (event) == actor) + printf(" *source*"); + + printf("\n"); + + return FALSE; +} + +static gboolean +grab_pointer_cb (ClutterActor *actor, + ClutterEvent *event, + gpointer data) +{ + clutter_grab_pointer (actor); + return FALSE; +} + +static gboolean +red_release_cb (ClutterActor *actor, + ClutterEvent *event, + gpointer data) +{ + clutter_ungrab_pointer (); + return FALSE; +} + +static gboolean +blue_release_cb (ClutterActor *actor, + ClutterEvent *event, + gpointer data) +{ + clutter_actor_destroy (actor); + return FALSE; +} + +static gboolean +green_press_cb (ClutterActor *actor, + ClutterEvent *event, + gpointer data) +{ + ClutterActor *stage; + gboolean enabled; + + stage = clutter_actor_get_stage (actor); + enabled = !clutter_stage_get_motion_events_enabled (CLUTTER_STAGE (stage)); + + clutter_stage_set_motion_events_enabled (CLUTTER_STAGE (stage), enabled); + + g_print ("per actor motion events are now %s\n", + enabled ? "enabled" : "disabled"); + + return FALSE; +} + +static gboolean +toggle_grab_pointer_cb (ClutterActor *actor, + ClutterEvent *event, + gpointer data) +{ + /* we only deal with the event if the source is ourself */ + if (event->button.source == actor) + { + if (clutter_get_pointer_grab () != NULL) + clutter_ungrab_pointer (); + else + clutter_grab_pointer (actor); + } + return FALSE; +} + +static gboolean +cyan_press_cb (ClutterActor *actor, + ClutterEvent *event, + gpointer data) +{ + if (clutter_get_keyboard_grab () != NULL) + clutter_ungrab_keyboard (); + else + clutter_grab_keyboard (actor); + return FALSE; +} + + + +G_MODULE_EXPORT int +test_grab_main (int argc, char *argv[]) +{ + ClutterActor *stage, *actor; + ClutterColor rcol = { 0xff, 0, 0, 0xff}, + bcol = { 0, 0, 0xff, 0xff }, + gcol = { 0, 0xff, 0, 0xff }, + ccol = { 0, 0xff, 0xff, 0xff }, + ycol = { 0xff, 0xff, 0, 0xff }; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + g_print ("Red box: aquire grab on press, releases it on next button release\n"); + g_print ("Blue box: aquire grab on press, destroys the blue box actor on release\n"); + g_print ("Yellow box: aquire grab on press, releases grab on next press on yellow box\n"); + g_print ("Green box: toggle per actor motion events.\n\n"); + g_print ("Cyan box: toggle grab (from cyan box) for keyboard events.\n\n"); + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Grabs"); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + g_signal_connect (stage, "event", + G_CALLBACK (debug_event_cb), "stage"); + g_signal_connect (stage, "fullscreen", + G_CALLBACK (stage_state_cb), "fullscreen"); + g_signal_connect (stage, "unfullscreen", + G_CALLBACK (stage_state_cb), "unfullscreen"); + g_signal_connect (stage, "activate", + G_CALLBACK (stage_state_cb), "activate"); + g_signal_connect (stage, "deactivate", + G_CALLBACK (stage_state_cb), "deactivate"); + + actor = clutter_rectangle_new_with_color (&rcol); + clutter_actor_set_size (actor, 100, 100); + clutter_actor_set_position (actor, 100, 100); + clutter_actor_set_reactive (actor, TRUE); + clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL); + g_signal_connect (actor, "event", G_CALLBACK (debug_event_cb), "red box"); + g_signal_connect (actor, "button-press-event", + G_CALLBACK (grab_pointer_cb), NULL); + g_signal_connect (actor, "button-release-event", + G_CALLBACK (red_release_cb), NULL); + + actor = clutter_rectangle_new_with_color (&ycol); + clutter_actor_set_size (actor, 100, 100); + clutter_actor_set_position (actor, 100, 300); + clutter_actor_set_reactive (actor, TRUE); + clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL); + g_signal_connect (actor, "event", G_CALLBACK (debug_event_cb), "yellow box"); + g_signal_connect (actor, "button-press-event", + G_CALLBACK (toggle_grab_pointer_cb), NULL); + + actor = clutter_rectangle_new_with_color (&bcol); + clutter_actor_set_size (actor, 100, 100); + clutter_actor_set_position (actor, 300, 100); + clutter_actor_set_reactive (actor, TRUE); + clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL); + g_signal_connect (actor, "event", + G_CALLBACK (debug_event_cb), "blue box"); + g_signal_connect (actor, "button-press-event", + G_CALLBACK (grab_pointer_cb), NULL); + g_signal_connect (actor, "button-release-event", + G_CALLBACK (blue_release_cb), NULL); + + actor = clutter_rectangle_new_with_color (&gcol); + clutter_actor_set_size (actor, 100, 100); + clutter_actor_set_position (actor, 300, 300); + clutter_actor_set_reactive (actor, TRUE); + clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL); + g_signal_connect (actor, "event", + G_CALLBACK (debug_event_cb), "green box"); + g_signal_connect (actor, "button-press-event", + G_CALLBACK (green_press_cb), NULL); + + + actor = clutter_rectangle_new_with_color (&ccol); + clutter_actor_set_size (actor, 100, 100); + clutter_actor_set_position (actor, 500, 100); + clutter_actor_set_reactive (actor, TRUE); + clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL); + g_signal_connect (actor, "event", + G_CALLBACK (debug_event_cb), "cyan box"); + g_signal_connect (actor, "button-press-event", + G_CALLBACK (cyan_press_cb), NULL); + + clutter_actor_show_all (CLUTTER_ACTOR (stage)); + + clutter_main(); + + return 0; +} + +G_MODULE_EXPORT const char * +test_grab_describe (void) +{ + return "Examples of using actor grabs"; +} diff --git a/clutter/tests/interactive/test-image.c b/clutter/tests/interactive/test-image.c new file mode 100644 index 0000000..e77108c --- /dev/null +++ b/clutter/tests/interactive/test-image.c @@ -0,0 +1,252 @@ +#include +#include +#include +#include + +typedef struct _SolidContent { + GObject parent_instance; + + double red; + double green; + double blue; + double alpha; + + float padding; +} SolidContent; + +typedef struct _SolidContentClass { + GObjectClass parent_class; +} SolidContentClass; + +static void clutter_content_iface_init (ClutterContentIface *iface); + +G_DEFINE_TYPE_WITH_CODE (SolidContent, solid_content, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTENT, + clutter_content_iface_init)) + +static void +solid_content_paint_content (ClutterContent *content, + ClutterActor *actor, + ClutterPaintNode *root) +{ + SolidContent *self = (SolidContent *) content; + ClutterActorBox box, content_box; + ClutterColor color; + PangoLayout *layout; + PangoRectangle logical; + ClutterPaintNode *node; + +#if 0 + g_debug ("Painting content [%p] " + "{ r:%.2f, g:%.2f, b:%.2f, a:%.2f } " + "for actor [%p] (context: [%p])", + content, + self->red, + self->green, + self->blue, + self->alpha, + actor, context); +#endif + + clutter_actor_get_content_box (actor, &content_box); + + box = content_box; + box.x1 += self->padding; + box.y1 += self->padding; + box.x2 -= self->padding; + box.y2 -= self->padding; + + color.alpha = self->alpha * 255; + + color.red = self->red * 255; + color.green = self->green * 255; + color.blue = self->blue * 255; + + node = clutter_color_node_new (&color); + clutter_paint_node_add_rectangle (node, &box); + clutter_paint_node_add_child (root, node); + clutter_paint_node_unref (node); + + color.red = (1.0 - self->red) * 255; + color.green = (1.0 - self->green) * 255; + color.blue = (1.0 - self->blue) * 255; + + layout = clutter_actor_create_pango_layout (actor, "A"); + pango_layout_get_pixel_extents (layout, NULL, &logical); + + node = clutter_text_node_new (layout, &color); + + /* top-left */ + box.x1 = clutter_actor_box_get_x (&content_box); + box.y1 = clutter_actor_box_get_y (&content_box); + box.x2 = box.x1 + logical.width; + box.y2 = box.y1 + logical.height; + clutter_paint_node_add_rectangle (node, &box); + + /* top-right */ + box.x1 = clutter_actor_box_get_x (&content_box) + + clutter_actor_box_get_width (&content_box) + - logical.width; + box.y1 = clutter_actor_box_get_y (&content_box); + box.x2 = box.x1 + logical.width; + box.y2 = box.y1 + logical.height; + clutter_paint_node_add_rectangle (node, &box); + + /* bottom-right */ + box.x1 = clutter_actor_box_get_x (&content_box) + + clutter_actor_box_get_width (&content_box) + - logical.width; + box.y1 = clutter_actor_box_get_y (&content_box) + + clutter_actor_box_get_height (&content_box) + - logical.height; + box.x2 = box.x1 + logical.width; + box.y2 = box.y1 + logical.height; + clutter_paint_node_add_rectangle (node, &box); + + /* bottom-left */ + box.x1 = clutter_actor_box_get_x (&content_box); + box.y1 = clutter_actor_box_get_y (&content_box) + + clutter_actor_box_get_height (&content_box) + - logical.height; + box.x2 = box.x1 + logical.width; + box.y2 = box.y1 + logical.height; + clutter_paint_node_add_rectangle (node, &box); + + /* center */ + box.x1 = clutter_actor_box_get_x (&content_box) + + (clutter_actor_box_get_width (&content_box) - logical.width) / 2.0; + box.y1 = clutter_actor_box_get_y (&content_box) + + (clutter_actor_box_get_height (&content_box) - logical.height) / 2.0; + box.x2 = box.x1 + logical.width; + box.y2 = box.y1 + logical.height; + clutter_paint_node_add_rectangle (node, &box); + + clutter_paint_node_add_child (root, node); + clutter_paint_node_unref (node); + + g_object_unref (layout); +} + +static void +clutter_content_iface_init (ClutterContentIface *iface) +{ + iface->paint_content = solid_content_paint_content; +} + +static void +solid_content_class_init (SolidContentClass *klass) +{ +} + +static void +solid_content_init (SolidContent *self) +{ +} + +static ClutterContent * +solid_content_new (double red, + double green, + double blue, + double alpha, + float padding) +{ + SolidContent *self = g_object_new (solid_content_get_type (), NULL); + + self->red = red; + self->green = green; + self->blue = blue; + self->alpha = alpha; + self->padding = padding; + + return (ClutterContent *) self; +} + +G_MODULE_EXPORT const char * +test_image_describe (void) +{ + return "A test with image content."; +} + +G_MODULE_EXPORT int +test_image_main (int argc, char *argv[]) +{ + ClutterActor *stage, *grid; + ClutterContent *color, *image; + GdkPixbuf *pixbuf; + int i, n_rects; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return EXIT_FAILURE; + + stage = clutter_stage_new (); + clutter_actor_set_name (stage, "Stage"); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Content"); + clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + clutter_actor_show (stage); + + grid = clutter_actor_new (); + clutter_actor_set_name (grid, "Grid"); + clutter_actor_set_margin_top (grid, 12); + clutter_actor_set_margin_right (grid, 12); + clutter_actor_set_margin_bottom (grid, 12); + clutter_actor_set_margin_left (grid, 12); + clutter_actor_set_layout_manager (grid, clutter_flow_layout_new (CLUTTER_FLOW_HORIZONTAL)); + clutter_actor_add_constraint (grid, clutter_bind_constraint_new (stage, CLUTTER_BIND_SIZE, 0.0)); + clutter_actor_add_child (stage, grid); + + color = solid_content_new (g_random_double_range (0.0, 1.0), + g_random_double_range (0.0, 1.0), + g_random_double_range (0.0, 1.0), + 1.0, + 2.0); + + pixbuf = gdk_pixbuf_new_from_file (TESTS_DATADIR G_DIR_SEPARATOR_S "redhand.png", NULL); + image = clutter_image_new (); + clutter_image_set_data (CLUTTER_IMAGE (image), + gdk_pixbuf_get_pixels (pixbuf), + gdk_pixbuf_get_has_alpha (pixbuf) + ? COGL_PIXEL_FORMAT_RGBA_8888 + : COGL_PIXEL_FORMAT_RGB_888, + gdk_pixbuf_get_width (pixbuf), + gdk_pixbuf_get_height (pixbuf), + gdk_pixbuf_get_rowstride (pixbuf), + NULL); + g_object_unref (pixbuf); + + n_rects = g_random_int_range (12, 24); + for (i = 0; i < n_rects; i++) + { + ClutterActor *box = clutter_actor_new (); + ClutterColor bg_color = { + g_random_int_range (0, 255), + g_random_int_range (0, 255), + g_random_int_range (0, 255), + 255 + }; + char *name, *str; + + str = clutter_color_to_string (&bg_color); + name = g_strconcat ("Box <", color, ">", NULL); + clutter_actor_set_name (box, name); + + g_free (name); + g_free (str); + + if ((i % 2) == 0) + clutter_actor_set_content (box, color); + else + clutter_actor_set_content (box, image); + + clutter_actor_set_size (box, 64, 64); + + clutter_actor_add_child (grid, box); + } + + clutter_main (); + + g_object_unref (color); + g_object_unref (image); + + return EXIT_SUCCESS; +} diff --git a/clutter/tests/interactive/test-keyframe-transition.c b/clutter/tests/interactive/test-keyframe-transition.c new file mode 100644 index 0000000..747a039 --- /dev/null +++ b/clutter/tests/interactive/test-keyframe-transition.c @@ -0,0 +1,108 @@ +#include +#include +#include + +static const ClutterColor colors[] = { + { 255, 0, 0, 255 }, + { 0, 255, 0, 255 }, + { 0, 0, 255, 255 }, +}; + +#define PADDING (64.0f) +#define SIZE (64.0f) + +static void +on_transition_stopped (ClutterActor *actor, + const gchar *transition_name, + gboolean is_finished) +{ + g_print ("%s: transition stopped: %s (finished: %s)\n", + clutter_actor_get_name (actor), + transition_name, + is_finished ? "yes" : "no"); +} + +G_MODULE_EXPORT const char * +test_keyframe_transition_describe (void) +{ + return "Demonstrate the keyframe transition."; +} + +G_MODULE_EXPORT int +test_keyframe_transition_main (int argc, char *argv[]) +{ + ClutterActor *stage; + int i; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return EXIT_FAILURE; + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Keyframe Transitions"); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + for (i = 0; i < 3; i++) + { + ClutterTransition *transition, *group; + ClutterActor *rect; + float cur_x, cur_y; + float new_x, new_y; + gchar *name; + + cur_x = PADDING; + cur_y = PADDING + ((SIZE + PADDING) * i); + + new_x = clutter_actor_get_width (stage) - PADDING - SIZE; + new_y = g_random_double_range (PADDING, clutter_actor_get_height (stage) - PADDING - SIZE); + + name = g_strdup_printf ("rect%02d", i); + + rect = clutter_actor_new (); + + clutter_actor_set_name (rect, name); + clutter_actor_set_background_color (rect, &colors[i]); + clutter_actor_set_size (rect, SIZE, SIZE); + clutter_actor_set_position (rect, PADDING, cur_y); + clutter_actor_add_child (stage, rect); + + group = clutter_transition_group_new (); + clutter_timeline_set_duration (CLUTTER_TIMELINE (group), 2000); + clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (group), 1); + clutter_timeline_set_auto_reverse (CLUTTER_TIMELINE (group), TRUE); + + transition = clutter_keyframe_transition_new ("x"); + clutter_transition_set_from (transition, G_TYPE_FLOAT, cur_x); + clutter_transition_set_to (transition, G_TYPE_FLOAT, new_x); + + clutter_keyframe_transition_set (CLUTTER_KEYFRAME_TRANSITION (transition), + G_TYPE_FLOAT, 1, + 0.5, new_x / 2.0f, CLUTTER_EASE_OUT_EXPO); + clutter_transition_group_add_transition (CLUTTER_TRANSITION_GROUP (group), transition); + g_object_unref (transition); + + transition = clutter_keyframe_transition_new ("y"); + clutter_transition_set_from (transition, G_TYPE_FLOAT, cur_y); + clutter_transition_set_to (transition, G_TYPE_FLOAT, cur_y); + + clutter_keyframe_transition_set (CLUTTER_KEYFRAME_TRANSITION (transition), + G_TYPE_FLOAT, 1, + 0.5, new_y, CLUTTER_EASE_OUT_EXPO); + clutter_transition_group_add_transition (CLUTTER_TRANSITION_GROUP (group), transition); + g_object_unref (transition); + + clutter_actor_add_transition (rect, "rectAnimation", group); + + g_signal_connect (rect, "transition-stopped", + G_CALLBACK (on_transition_stopped), + NULL); + g_object_unref (group); + + g_free (name); + } + + clutter_actor_show (stage); + + clutter_main (); + + return EXIT_SUCCESS; +} diff --git a/clutter/tests/interactive/test-layout.c b/clutter/tests/interactive/test-layout.c new file mode 100644 index 0000000..ec3ebad --- /dev/null +++ b/clutter/tests/interactive/test-layout.c @@ -0,0 +1,687 @@ +#include +#include + +#include +#include + +#include + +/* layout actor, by Lucas Rocha */ + +#define MY_TYPE_THING (my_thing_get_type ()) +#define MY_THING(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MY_TYPE_THING, MyThing)) +#define MY_IS_THING(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MY_TYPE_THING)) +#define MY_THING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MY_TYPE_THING, MyThingClass)) +#define MY_IS_THING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MY_TYPE_THING)) +#define MY_THING_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MY_TYPE_THING, MyThingClass)) + +typedef struct _MyThing MyThing; +typedef struct _MyThingPrivate MyThingPrivate; +typedef struct _MyThingClass MyThingClass; + +struct _MyThing +{ + ClutterActor parent_instance; + + MyThingPrivate *priv; +}; + +struct _MyThingClass +{ + ClutterActorClass parent_class; +}; + +enum +{ + PROP_0, + + PROP_SPACING, + PROP_PADDING, + PROP_USE_TRANSFORMED_BOX +}; + +G_DEFINE_TYPE (MyThing, my_thing, CLUTTER_TYPE_ACTOR) + +#define MY_THING_GET_PRIVATE(obj) \ +(G_TYPE_INSTANCE_GET_PRIVATE ((obj), MY_TYPE_THING, MyThingPrivate)) + +struct _MyThingPrivate +{ + gfloat spacing; + gfloat padding; + + guint use_transformed_box : 1; +}; + +static void +my_thing_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + MyThingPrivate *priv = MY_THING (gobject)->priv; + gboolean needs_relayout = TRUE; + + switch (prop_id) + { + case PROP_SPACING: + priv->spacing = g_value_get_float (value); + break; + + case PROP_PADDING: + priv->padding = g_value_get_float (value); + break; + + case PROP_USE_TRANSFORMED_BOX: + priv->use_transformed_box = g_value_get_boolean (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + needs_relayout = FALSE; + break; + } + + /* setting spacing or padding queues a relayout + because they are supposed to change the internal + allocation of children */ + if (needs_relayout) + clutter_actor_queue_relayout (CLUTTER_ACTOR (gobject)); +} + +static void +my_thing_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MyThingPrivate *priv = MY_THING (gobject)->priv; + + switch (prop_id) + { + case PROP_SPACING: + g_value_set_float (value, priv->spacing); + break; + + case PROP_PADDING: + g_value_set_float (value, priv->padding); + break; + + case PROP_USE_TRANSFORMED_BOX: + g_value_set_boolean (value, priv->use_transformed_box); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +my_thing_get_preferred_width (ClutterActor *self, + gfloat for_height, + gfloat *min_width_p, + gfloat *natural_width_p) +{ + ClutterActorIter iter; + ClutterActor *child; + gfloat min_left, min_right; + gfloat natural_left, natural_right; + + min_left = 0; + min_right = 0; + natural_left = 0; + natural_right = 0; + + clutter_actor_iter_init (&iter, self); + while (clutter_actor_iter_next (&iter, &child)) + { + gfloat child_x, child_min, child_natural; + + child_x = clutter_actor_get_x (child); + + clutter_actor_get_preferred_size (child, + &child_min, NULL, + &child_natural, NULL); + + if (child == clutter_actor_get_first_child (self)) + { + /* First child */ + min_left = child_x; + natural_left = child_x; + min_right = min_left + child_min; + natural_right = natural_left + child_natural; + } + else + { + /* Union of extents with previous children */ + if (child_x < min_left) + min_left = child_x; + + if (child_x < natural_left) + natural_left = child_x; + + if (child_x + child_min > min_right) + min_right = child_x + child_min; + + if (child_x + child_natural > natural_right) + natural_right = child_x + child_natural; + } + } + + if (min_left < 0) + min_left = 0; + + if (natural_left < 0) + natural_left = 0; + + if (min_right < 0) + min_right = 0; + + if (natural_right < 0) + natural_right = 0; + + g_assert (min_right >= min_left); + g_assert (natural_right >= natural_left); + + if (min_width_p) + *min_width_p = min_right - min_left; + + if (natural_width_p) + *natural_width_p = natural_right - min_left; +} + +static void +my_thing_get_preferred_height (ClutterActor *self, + gfloat for_width, + gfloat *min_height_p, + gfloat *natural_height_p) +{ + ClutterActorIter iter; + ClutterActor *child; + gfloat min_top, min_bottom; + gfloat natural_top, natural_bottom; + + min_top = 0; + min_bottom = 0; + natural_top = 0; + natural_bottom = 0; + + clutter_actor_iter_init (&iter, self); + while (clutter_actor_iter_next (&iter, &child)) + { + gfloat child_y, child_min, child_natural; + + child_y = clutter_actor_get_y (child); + + clutter_actor_get_preferred_size (child, + NULL, &child_min, + NULL, &child_natural); + + if (child == clutter_actor_get_first_child (self)) + { + /* First child */ + min_top = child_y; + natural_top = child_y; + min_bottom = min_top + child_min; + natural_bottom = natural_top + child_natural; + } + else + { + /* Union of extents with previous children */ + if (child_y < min_top) + min_top = child_y; + + if (child_y < natural_top) + natural_top = child_y; + + if (child_y + child_min > min_bottom) + min_bottom = child_y + child_min; + + if (child_y + child_natural > natural_bottom) + natural_bottom = child_y + child_natural; + } + } + + if (min_top < 0) + min_top = 0; + + if (natural_top < 0) + natural_top = 0; + + if (min_bottom < 0) + min_bottom = 0; + + if (natural_bottom < 0) + natural_bottom = 0; + + g_assert (min_bottom >= min_top); + g_assert (natural_bottom >= natural_top); + + if (min_height_p) + *min_height_p = min_bottom - min_top; + + if (natural_height_p) + *natural_height_p = natural_bottom - min_top; +} + +static void +my_thing_allocate (ClutterActor *self, + const ClutterActorBox *box, + ClutterAllocationFlags flags) +{ + MyThingPrivate *priv; + gfloat current_x, current_y, max_row_height; + ClutterActorIter iter; + ClutterActor *child; + + clutter_actor_set_allocation (self, box, flags); + + priv = MY_THING (self)->priv; + + current_x = priv->padding; + current_y = priv->padding; + max_row_height = 0; + + /* The allocation logic here is to horizontally place children + * side-by-side and reflow into a new row when we run out of + * space + */ + clutter_actor_iter_init (&iter, self); + while (clutter_actor_iter_next (&iter, &child)) + { + gfloat natural_width, natural_height; + ClutterActorBox child_box; + + clutter_actor_get_preferred_size (child, + NULL, NULL, + &natural_width, + &natural_height); + + /* if it fits in the current row, keep it there; otherwise + * reflow into another row + */ + if (current_x + natural_width > box->x2 - box->x1 - priv->padding) + { + current_x = priv->padding; + current_y += max_row_height + priv->spacing; + max_row_height = 0; + } + + child_box.x1 = current_x; + child_box.y1 = current_y; + child_box.x2 = child_box.x1 + natural_width; + child_box.y2 = child_box.y1 + natural_height; + + clutter_actor_allocate (child, &child_box, flags); + + /* if we take into account the transformation of the children + * then we first check if it's transformed; then we get the + * onscreen coordinates of the two points of the bounding box + * of the actor (origin(x, y) and (origin + size)(x,y)) and + * we update the coordinates and area given to the next child + */ + if (priv->use_transformed_box) + { + if (clutter_actor_is_scaled (child) || + clutter_actor_is_rotated (child)) + { + ClutterVertex v1 = { 0, }, v2 = { 0, }; + ClutterActorBox transformed_box = { 0, }; + + /* origin */ + if (!(flags & CLUTTER_ABSOLUTE_ORIGIN_CHANGED)) + { + v1.x = 0; + v1.y = 0; + } + else + { + v1.x = box->x1; + v1.y = box->y1; + } + + clutter_actor_apply_transform_to_point (child, &v1, &v2); + transformed_box.x1 = v2.x; + transformed_box.y1 = v2.y; + + /* size */ + v1.x = natural_width; + v1.y = natural_height; + clutter_actor_apply_transform_to_point (child, &v1, &v2); + transformed_box.x2 = v2.x; + transformed_box.y2 = v2.y; + + natural_width = transformed_box.x2 - transformed_box.x1; + natural_height = transformed_box.y2 - transformed_box.y1; + } + } + + /* Record the maximum child height on current row to know + * what's the increment that should be used for the next + * row + */ + if (natural_height > max_row_height) + max_row_height = natural_height; + + current_x += natural_width + priv->spacing; + } +} + +#define MIN_SIZE 24 +#define MAX_SIZE 64 + +static void +my_thing_class_init (MyThingClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + + gobject_class->set_property = my_thing_set_property; + gobject_class->get_property = my_thing_get_property; + + actor_class->get_preferred_width = my_thing_get_preferred_width; + actor_class->get_preferred_height = my_thing_get_preferred_height; + actor_class->allocate = my_thing_allocate; + + g_object_class_install_property (gobject_class, + PROP_SPACING, + g_param_spec_float ("spacing", + "Spacing", + "Spacing of the thing", + 0, G_MAXFLOAT, + 0, + G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + PROP_PADDING, + g_param_spec_float ("padding", + "Padding", + "Padding around the thing", + 0, G_MAXFLOAT, + 0, + G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + PROP_USE_TRANSFORMED_BOX, + g_param_spec_boolean ("use-transformed-box", + "Use Transformed Box", + "Use transformed box when allocating", + FALSE, + G_PARAM_READWRITE)); + + g_type_class_add_private (klass, sizeof (MyThingPrivate)); +} + +static void +my_thing_init (MyThing *thing) +{ + thing->priv = MY_THING_GET_PRIVATE (thing); +} + +ClutterActor * +my_thing_new (gfloat padding, + gfloat spacing) +{ + return g_object_new (MY_TYPE_THING, + "padding", padding, + "spacing", spacing, + NULL); +} + +/* test code */ + +static ClutterActor *box = NULL; +static ClutterActor *icon = NULL; +static ClutterTimeline *main_timeline = NULL; + +static void +toggle_property_value (ClutterActor *actor, + const gchar *property_name) +{ + gboolean value; + + g_object_get (actor, property_name, &value, NULL); + + value = !value; + + g_object_set (box, property_name, value, NULL); +} + +static void +increase_property_value (ClutterActor *actor, + const char *property_name) +{ + gfloat value; + + g_object_get (actor, property_name, &value, NULL); + + value = value + 10.0; + + g_object_set (box, property_name, value, NULL); +} + +static void +decrease_property_value (ClutterActor *actor, + const char *property_name) +{ + gfloat value; + + g_object_get (actor, property_name, &value, NULL); + + value = MAX (0, value - 10.0); + + g_object_set (box, property_name, value, NULL); +} + +static ClutterActor * +create_item (void) +{ + ClutterActor *clone = clutter_clone_new (icon); + + gint32 size = g_random_int_range (MIN_SIZE, MAX_SIZE); + + clutter_actor_set_size (clone, size, size); + clutter_actor_animate_with_timeline (clone, CLUTTER_EASE_OUT_CUBIC, + main_timeline, + "scale-x", 2.0, + "scale-y", 2.0, + "fixed::scale-gravity", CLUTTER_GRAVITY_CENTER, + NULL); + + return clone; +} + +static gboolean +keypress_cb (ClutterActor *actor, + ClutterEvent *event, + gpointer data) +{ + switch (clutter_event_get_key_symbol (event)) + { + case CLUTTER_KEY_q: + clutter_main_quit (); + break; + + case CLUTTER_KEY_a: + { + if (icon != NULL) + { + ClutterActor *clone = create_item (); + + /* Add one item to container */ + clutter_actor_add_child (box, clone); + } + break; + } + + case CLUTTER_KEY_d: + { + ClutterActor *last_child; + + last_child = clutter_actor_get_last_child (box); + if (last_child != NULL) + { + /* Remove last item on container */ + clutter_actor_remove_child (box, last_child); + } + break; + } + + case CLUTTER_KEY_w: + { + decrease_property_value (box, "padding"); + break; + } + + case CLUTTER_KEY_e: + { + increase_property_value (box, "padding"); + break; + } + + case CLUTTER_KEY_r: + { + decrease_property_value (box, "spacing"); + break; + } + + case CLUTTER_KEY_s: + { + toggle_property_value (box, "use-transformed-box"); + break; + } + + case CLUTTER_KEY_t: + { + increase_property_value (box, "spacing"); + break; + } + + case CLUTTER_KEY_z: + { + if (clutter_timeline_is_playing (main_timeline)) + clutter_timeline_pause (main_timeline); + else + clutter_timeline_start (main_timeline); + + break; + } + + default: + break; + } + + return FALSE; +} + +static void +relayout_on_frame (ClutterTimeline *timeline) +{ + gboolean use_transformed_box; + + /* if we care about transformations updating the layout, we need to inform + * the layout that a transformation is happening; this is either done by + * attaching a notification on the transformation properties or by simply + * queuing a relayout on each frame of the timeline used to drive the + * behaviour. for simplicity's sake, we used the latter + */ + + g_object_get (G_OBJECT (box), + "use-transformed-box", &use_transformed_box, + NULL); + + if (use_transformed_box) + clutter_actor_queue_relayout (box); +} + +G_MODULE_EXPORT int +test_layout_main (int argc, char *argv[]) +{ + ClutterActor *stage, *instructions; + gint i, size; + GError *error = NULL; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + clutter_actor_set_size (stage, 800, 600); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Layout"); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + main_timeline = clutter_timeline_new (2000); + clutter_timeline_set_repeat_count (main_timeline, -1); + clutter_timeline_set_auto_reverse (main_timeline, TRUE); + g_signal_connect (main_timeline, "new-frame", + G_CALLBACK (relayout_on_frame), + NULL); + + + box = my_thing_new (10, 10); + + clutter_actor_set_position (box, 20, 20); + clutter_actor_set_size (box, 350, -1); + + icon = clutter_texture_new_from_file (TESTS_DATADIR + G_DIR_SEPARATOR_S + "redhand.png", + &error); + if (error) + g_error ("Unable to load 'redhand.png': %s", error->message); + + size = g_random_int_range (MIN_SIZE, MAX_SIZE); + clutter_actor_set_size (icon, size, size); + clutter_actor_add_child (box, icon); + clutter_actor_animate_with_timeline (icon, CLUTTER_EASE_OUT_CUBIC, + main_timeline, + "scale-x", 2.0, + "scale-y", 2.0, + "fixed::scale-gravity", CLUTTER_GRAVITY_CENTER, + NULL); + + for (i = 1; i < 33; i++) + { + ClutterActor *clone = create_item (); + + clutter_actor_add_child (box, clone); + } + + clutter_actor_add_child (stage, box); + + instructions = clutter_text_new_with_text (NULL, + "Instructions:\n" + "a - add a new item\n" + "d - remove last item\n" + "z - start/pause behaviour\n" + "w - decrease padding\n" + "e - increase padding\n" + "r - decrease spacing\n" + "t - increase spacing\n" + "s - use transformed box\n" + "q - quit"); + + clutter_text_set_use_markup (CLUTTER_TEXT (instructions), TRUE); + clutter_actor_set_position (instructions, 450, 10); + clutter_actor_add_child (stage, instructions); + + g_signal_connect (stage, "key-release-event", + G_CALLBACK (keypress_cb), + NULL); + + clutter_timeline_stop (main_timeline); + + clutter_actor_show (stage); + + clutter_main (); + + g_object_unref (main_timeline); + + return EXIT_SUCCESS; +} + +G_MODULE_EXPORT const char * +test_layout_describe (void) +{ + return "Container implementing a layout policy."; +} diff --git a/clutter/tests/interactive/test-main.c b/clutter/tests/interactive/test-main.c new file mode 100644 index 0000000..586d6dc --- /dev/null +++ b/clutter/tests/interactive/test-main.c @@ -0,0 +1,221 @@ +#include +#include +#include +#include + +#include "test-unit-names.h" + +#define MAX_DESC_SIZE 72 + +static GModule *module = NULL; + +static gpointer +get_symbol_with_suffix (const char *unit_name, + const char *suffix) +{ + char *main_symbol_name; + gpointer func; + + main_symbol_name = g_strconcat (unit_name, "_", suffix, NULL); + main_symbol_name = g_strdelimit (main_symbol_name, "-", '_'); + + g_module_symbol (module, main_symbol_name, &func); + + g_free (main_symbol_name); + + return func; +} + +static gpointer +get_unit_name_main (const char *unit_name) +{ + return get_symbol_with_suffix (unit_name, "main"); +} +static char * +get_unit_name_description (const char *unit_name, + gssize max_len) +{ + const char *description; + gpointer func; + char *retval; + + func = get_symbol_with_suffix (unit_name, "describe"); + if (func == NULL) + description = "No description found"; + else + { + const char *(* unit_test_describe) (void); + + unit_test_describe = func; + + description = unit_test_describe (); + } + + if (max_len > 0 && strlen (description) >= max_len) + { + GString *buf = g_string_sized_new (max_len); + char *newline; + + newline = strchr (description, '\n'); + if (newline != NULL) + { + g_string_append_len (buf, description, + MIN (newline - description - 1, max_len - 3)); + } + else + g_string_append_len (buf, description, max_len - 3); + + g_string_append (buf, "..."); + + retval = g_string_free (buf, FALSE); + } + else + retval = g_strdup (description); + + return retval; +} + +static gboolean list_all = FALSE; +static gboolean describe = FALSE; +static char **unit_names = NULL; + +static GOptionEntry entries[] = { + { + "describe", 'd', + 0, + G_OPTION_ARG_NONE, &describe, + "Describe the interactive unit test", NULL, + }, + { + "list-all", 'l', + 0, + G_OPTION_ARG_NONE, &list_all, + "List all available units", NULL, + }, + { + G_OPTION_REMAINING, 0, + 0, + G_OPTION_ARG_STRING_ARRAY, &unit_names, + "The interactive unit test", "UNIT_NAME" + }, + { NULL } +}; + +int +main (int argc, char **argv) +{ + int ret, i, n_unit_names; + GOptionContext *context; + + context = g_option_context_new (" - Interactive test suite"); + g_option_context_add_main_entries (context, entries, NULL); + g_option_context_set_help_enabled (context, TRUE); + g_option_context_set_ignore_unknown_options (context, TRUE); + if (!g_option_context_parse (context, &argc, &argv, NULL)) + { + g_print ("Usage: test-interactive \n"); + return EXIT_FAILURE; + } + + g_option_context_free (context); + + module = g_module_open (NULL, 0); + if (!module) + g_error ("*** Failed to open self for symbol lookup"); + + ret = EXIT_SUCCESS; + + if (list_all) + { + g_print ("* Available unit tests:\n"); + + for (i = 0; i < G_N_ELEMENTS (test_unit_names); i++) + { + char *str; + gsize len; + + len = MAX_DESC_SIZE - strlen (test_unit_names[i]); + str = get_unit_name_description (test_unit_names[i], len - 2); + + g_print (" - %s:%*s%s\n", + test_unit_names[i], + (int) (len - strlen (str)), " ", + str); + + g_free (str); + } + + ret = EXIT_SUCCESS; + goto out; + } + + if (unit_names != NULL) + n_unit_names = g_strv_length (unit_names); + else + { + g_print ("Usage: test-interactive \n"); + ret = EXIT_FAILURE; + goto out; + } + + for (i = 0; i < n_unit_names; i++) + { + const char *unit_name = unit_names[i]; + char *unit_test = NULL; + gboolean found; + int j; + + unit_test = g_path_get_basename (unit_name); + + found = FALSE; + for (j = 0; j < G_N_ELEMENTS (test_unit_names); j++) + { + if (strcmp (test_unit_names[j], unit_test) == 0) + { + found = TRUE; + break; + } + } + + if (!found) + g_error ("*** Unit '%s' does not exist", unit_test); + + if (describe) + { + char *str; + + str = get_unit_name_description (unit_test, -1); + + g_print ("* %s:\n%s\n\n", unit_test, str); + + g_free (str); + + ret = EXIT_SUCCESS; + } + else + { + int (* unit_test_main) (int argc, char **argv); + gpointer func; + + func = get_unit_name_main (unit_test); + if (func == NULL) + g_error ("*** Unable to find the main entry point for '%s'", unit_test); + + unit_test_main = func; + + ret = unit_test_main (n_unit_names, unit_names); + + g_free (unit_test); + + break; + } + + g_free (unit_test); + } + +out: + g_module_close (module); + + return ret; +} + diff --git a/clutter/tests/interactive/test-multistage.c b/clutter/tests/interactive/test-multistage.c new file mode 100644 index 0000000..4a55f69 --- /dev/null +++ b/clutter/tests/interactive/test-multistage.c @@ -0,0 +1,149 @@ +#include +#include + +static GList *stages = NULL; +static gint n_stages = 1; + +static gboolean +tex_button_cb (ClutterActor *actor, + ClutterEvent *event, + gpointer data) +{ + clutter_actor_hide (actor); + + return TRUE; +} + +static void +on_destroy (ClutterActor *actor) +{ + stages = g_list_remove (stages, actor); +} + +static gboolean +on_button_press (ClutterActor *actor, + ClutterEvent *event, + gpointer data) +{ + ClutterActor *new_stage; + ClutterActor *label, *tex; + gint width, height; + gchar *stage_label, *stage_name; + ClutterTimeline *timeline; + ClutterAlpha *alpha; + ClutterBehaviour *r_behave; + + new_stage = clutter_stage_new (); + if (new_stage == NULL) + return FALSE; + + stage_name = g_strdup_printf ("Stage [%d]", ++n_stages); + + clutter_stage_set_title (CLUTTER_STAGE (new_stage), stage_name); + clutter_actor_set_background_color (new_stage, + CLUTTER_COLOR_DarkScarletRed); + clutter_actor_set_size (new_stage, 320, 240); + clutter_actor_set_name (new_stage, stage_name); + + g_signal_connect (new_stage, "destroy", G_CALLBACK (on_destroy), NULL); + + tex = clutter_texture_new_from_file (TESTS_DATADIR + G_DIR_SEPARATOR_S + "redhand.png", + NULL); + + if (!tex) + g_error ("pixbuf load failed"); + + clutter_actor_set_reactive (tex, TRUE); + g_signal_connect (tex, "button-press-event", + G_CALLBACK (tex_button_cb), NULL); + + clutter_container_add_actor (CLUTTER_CONTAINER (new_stage), tex); + + stage_label = g_strconcat ("", stage_name, "", NULL); + label = clutter_text_new_with_text ("Mono 12", stage_label); + + clutter_text_set_color (CLUTTER_TEXT (label), CLUTTER_COLOR_White); + clutter_text_set_use_markup (CLUTTER_TEXT (label), TRUE); + width = (clutter_actor_get_width (new_stage) + - clutter_actor_get_width (label)) / 2; + height = (clutter_actor_get_height (new_stage) + - clutter_actor_get_height (label)) / 2; + clutter_actor_set_position (label, width, height); + clutter_container_add_actor (CLUTTER_CONTAINER (new_stage), label); + clutter_actor_show (label); + g_free (stage_label); + + /* + g_signal_connect (new_stage, "button-press-event", + G_CALLBACK (clutter_actor_destroy), + NULL); + */ + + timeline = clutter_timeline_new (2000); + clutter_timeline_set_repeat_count (timeline, -1); + + alpha = clutter_alpha_new_full (timeline, CLUTTER_LINEAR); + r_behave = clutter_behaviour_rotate_new (alpha, + CLUTTER_Y_AXIS, + CLUTTER_ROTATE_CW, + 0.0, 360.0); + + clutter_behaviour_rotate_set_center (CLUTTER_BEHAVIOUR_ROTATE (r_behave), + clutter_actor_get_width (label)/2, + 0, + 0); + + clutter_behaviour_apply (r_behave, label); + clutter_timeline_start (timeline); + + clutter_actor_show_all (new_stage); + + stages = g_list_prepend (stages, new_stage); + + g_free (stage_name); + + return TRUE; +} + +G_MODULE_EXPORT int +test_multistage_main (int argc, char *argv[]) +{ + ClutterActor *stage_default; + ClutterActor *label; + gint width, height; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage_default = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage_default), "Default Stage"); + clutter_actor_set_name (stage_default, "Default Stage"); + g_signal_connect (stage_default, "destroy", + G_CALLBACK (clutter_main_quit), + NULL); + g_signal_connect (stage_default, "button-press-event", + G_CALLBACK (on_button_press), + NULL); + + label = clutter_text_new_with_text ("Mono 16", "Default stage"); + width = (clutter_actor_get_width (stage_default) + - clutter_actor_get_width (label)) + / 2; + height = (clutter_actor_get_height (stage_default) + - clutter_actor_get_height (label)) + / 2; + clutter_actor_set_position (label, width, height); + clutter_container_add_actor (CLUTTER_CONTAINER (stage_default), label); + clutter_actor_show (label); + + clutter_actor_show (stage_default); + + clutter_main (); + + g_list_foreach (stages, (GFunc) clutter_actor_destroy, NULL); + g_list_free (stages); + + return 0; +} diff --git a/clutter/tests/interactive/test-paint-wrapper.c b/clutter/tests/interactive/test-paint-wrapper.c new file mode 100644 index 0000000..103f9d0 --- /dev/null +++ b/clutter/tests/interactive/test-paint-wrapper.c @@ -0,0 +1,370 @@ +#include + +#include + +#if defined (_MSC_VER) && !defined (_USE_MATH_DEFINES) +#define _USE_MATH_DEFINES +#endif + +#include +#include +#include +#include + +#ifdef CLUTTER_WINDOWING_X11 +#include "clutter/x11/clutter-x11.h" +#endif + +#define NHANDS 6 + +typedef struct SuperOH +{ + ClutterActor **hand, *bgtex; + ClutterActor *real_hand; + ClutterActor *group; + ClutterActor *stage; + + gint stage_width; + gint stage_height; + gfloat radius; + + ClutterBehaviour *scaler_1; + ClutterBehaviour *scaler_2; + ClutterTimeline *timeline; + + guint frame_id; + + gboolean *paint_guards; +} SuperOH; + +static gint n_hands = NHANDS; +static gint use_alpha = 255; + +static GOptionEntry super_oh_entries[] = { + { + "num-hands", 'n', + 0, + G_OPTION_ARG_INT, &n_hands, + "Number of hands", "HANDS" + }, + { + "use-alpha", 'a', + 0, + G_OPTION_ARG_INT, &use_alpha, + "Stage opacity", "VALUE" + }, + { NULL } +}; + +static gboolean +on_button_press_event (ClutterActor *actor, + ClutterEvent *event, + SuperOH *oh) +{ + gfloat x, y; + + clutter_event_get_coords (event, &x, &y); + + g_print ("*** button press event (button:%d) at %.2f, %.2f ***\n", + clutter_event_get_button (event), + x, y); + + clutter_actor_hide (actor); + + return TRUE; +} + +static gboolean +input_cb (ClutterActor *stage, + ClutterEvent *event, + gpointer data) +{ + SuperOH *oh = data; + + if (event->type == CLUTTER_KEY_RELEASE) + { + g_print ("*** key press event (key:%c) ***\n", + clutter_event_get_key_symbol (event)); + + if (clutter_event_get_key_symbol (event) == CLUTTER_KEY_q) + { + clutter_main_quit (); + + return TRUE; + } + else if (clutter_event_get_key_symbol (event) == CLUTTER_KEY_r) + { + gint i; + + for (i = 0; i < n_hands; i++) + clutter_actor_show (oh->hand[i]); + + return TRUE; + } + } + + return FALSE; +} + +/* Timeline handler */ +static void +frame_cb (ClutterTimeline *timeline, + gint msecs, + gpointer data) +{ + SuperOH *oh = data; + gint i; + float rotation = clutter_timeline_get_progress (timeline) * 360.0f; + + /* Rotate everything clockwise about stage center*/ + + clutter_actor_set_rotation (oh->group, + CLUTTER_Z_AXIS, + rotation, + oh->stage_width / 2, + oh->stage_height / 2, + 0); + + for (i = 0; i < n_hands; i++) + { + /* Rotate each hand around there centers - to get this we need + * to take into account any scaling. + */ + clutter_actor_set_rotation (oh->hand[i], + CLUTTER_Z_AXIS, + -6.0 * rotation, + 0, 0, 0); + } +} + +static gdouble +my_sine_wave (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = clutter_alpha_get_timeline (alpha); + gdouble progress = clutter_timeline_get_progress (timeline); + + return sin (progress * G_PI); +} + +static void +hand_pre_paint (ClutterActor *actor, + gpointer user_data) +{ + SuperOH *oh = user_data; + gfloat w, h; + int actor_num; + + for (actor_num = 0; oh->hand[actor_num] != actor; actor_num++) + ; + + g_assert (oh->paint_guards[actor_num] == FALSE); + + clutter_actor_get_size (actor, &w, &h); + + cogl_set_source_color4ub (255, 0, 0, 128); + cogl_rectangle (0, 0, w / 2, h / 2); + + oh->paint_guards[actor_num] = TRUE; +} + +static void +hand_post_paint (ClutterActor *actor, + gpointer user_data) +{ + SuperOH *oh = user_data; + gfloat w, h; + int actor_num; + + for (actor_num = 0; oh->hand[actor_num] != actor; actor_num++) + ; + + g_assert (oh->paint_guards[actor_num] == TRUE); + + clutter_actor_get_size (actor, &w, &h); + + cogl_set_source_color4ub (0, 255, 0, 128); + cogl_rectangle (w / 2, h / 2, w, h); + + oh->paint_guards[actor_num] = FALSE; +} + +static void +stop_and_quit (ClutterActor *actor, + SuperOH *oh) +{ + g_signal_handler_disconnect (oh->timeline, oh->frame_id); + clutter_timeline_stop (oh->timeline); + + clutter_main_quit (); +} + +G_MODULE_EXPORT int +test_paint_wrapper_main (int argc, char *argv[]) +{ + ClutterAlpha *alpha; + ClutterActor *stage; + ClutterColor stage_color = { 0x61, 0x64, 0x8c, 0xff }; + SuperOH *oh; + gint i; + GError *error; + ClutterActor *real_hand; + + error = NULL; + +#ifdef CLUTTER_WINDOWING_X11 + clutter_x11_set_use_argb_visual (TRUE); +#endif + + if (clutter_init_with_args (&argc, &argv, + NULL, + super_oh_entries, + NULL, + &error) != CLUTTER_INIT_SUCCESS) + { + g_warning ("Unable to initialise Clutter:\n%s", + error->message); + g_error_free (error); + + return EXIT_FAILURE; + } + + oh = g_new(SuperOH, 1); + + stage = clutter_stage_new (); + clutter_actor_set_size (stage, 800, 600); + + if (use_alpha != 255) + { + clutter_stage_set_use_alpha (CLUTTER_STAGE (stage), TRUE); + clutter_actor_set_opacity (stage, use_alpha); + } + + clutter_stage_set_title (CLUTTER_STAGE (stage), "Paint Test"); + clutter_actor_set_background_color (stage, &stage_color); + g_signal_connect (stage, "destroy", G_CALLBACK (stop_and_quit), oh); + + oh->stage = stage; + + /* Create a timeline to manage animation */ + oh->timeline = clutter_timeline_new (6000); + clutter_timeline_set_repeat_count (oh->timeline, -1); + + /* fire a callback for frame change */ + oh->frame_id = + g_signal_connect (oh->timeline, "new-frame", G_CALLBACK (frame_cb), oh); + + /* Set up some behaviours to handle scaling */ + alpha = clutter_alpha_new_with_func (oh->timeline, my_sine_wave, NULL, NULL); + + oh->scaler_1 = clutter_behaviour_scale_new (alpha, 0.5, 0.5, 1.0, 1.0); + oh->scaler_2 = clutter_behaviour_scale_new (alpha, 1.0, 1.0, 0.5, 0.5); + + real_hand = clutter_texture_new_from_file (TESTS_DATADIR + G_DIR_SEPARATOR_S + "redhand.png", + &error); + if (real_hand == NULL) + { + g_error ("image load failed: %s", error->message); + return EXIT_FAILURE; + } + + /* create a new group to hold multiple actors in a group */ + oh->group = clutter_group_new(); + + oh->hand = g_new (ClutterActor*, n_hands); + + oh->stage_width = clutter_actor_get_width (stage); + oh->stage_height = clutter_actor_get_height (stage); + oh->radius = (oh->stage_width + oh->stage_height) + / n_hands; + + for (i = 0; i < n_hands; i++) + { + gint x, y, w, h; + + if (i == 0) + oh->hand[i] = real_hand; + else + oh->hand[i] = clutter_clone_new (real_hand); + + clutter_actor_set_reactive (oh->hand[i], TRUE); + + clutter_actor_set_size (oh->hand[i], 200, 213); + + /* Place around a circle */ + w = clutter_actor_get_width (oh->hand[i]); + h = clutter_actor_get_height (oh->hand[i]); + + x = oh->stage_width / 2 + + oh->radius + * cos (i * G_PI / (n_hands / 2)) + - w / 2; + + y = oh->stage_height / 2 + + oh->radius + * sin (i * G_PI / (n_hands / 2)) + - h / 2; + + clutter_actor_set_position (oh->hand[i], x, y); + + clutter_actor_move_anchor_point_from_gravity (oh->hand[i], + CLUTTER_GRAVITY_CENTER); + + g_signal_connect (oh->hand[i], "button-press-event", + G_CALLBACK (on_button_press_event), + oh); + + /* paint something before each hand */ + g_signal_connect (oh->hand[i], + "paint", G_CALLBACK (hand_pre_paint), + oh); + + /* paint something after each hand */ + g_signal_connect_after (oh->hand[i], + "paint", G_CALLBACK (hand_post_paint), + oh); + + /* Add to our group group */ + clutter_container_add_actor (CLUTTER_CONTAINER (oh->group), oh->hand[i]); + + if (i % 2) + clutter_behaviour_apply (oh->scaler_1, oh->hand[i]); + else + clutter_behaviour_apply (oh->scaler_2, oh->hand[i]); + } + + oh->paint_guards = g_malloc0 (sizeof (gboolean) * n_hands); + + /* Add the group to the stage */ + clutter_container_add_actor (CLUTTER_CONTAINER (stage), + CLUTTER_ACTOR (oh->group)); + + /* Show everying ( and map window ) */ + clutter_actor_show (stage); + + g_signal_connect (stage, "key-release-event", + G_CALLBACK (input_cb), + oh); + + /* and start it */ + clutter_timeline_start (oh->timeline); + + clutter_main (); + + g_object_unref (oh->scaler_1); + g_object_unref (oh->scaler_2); + g_object_unref (oh->timeline); + g_free (oh->paint_guards); + g_free (oh->hand); + g_free (oh); + + return 0; +} + +G_MODULE_EXPORT const char * +test_paint_wrapper_describe (void) +{ + return "Wrap an actor's paint cycle for pre and post processing."; +} diff --git a/clutter/tests/interactive/test-path-constraint.c b/clutter/tests/interactive/test-path-constraint.c new file mode 100644 index 0000000..bded798 --- /dev/null +++ b/clutter/tests/interactive/test-path-constraint.c @@ -0,0 +1,133 @@ +#include +#include +#include + +#define PATH_DESCRIPTION \ + "M 0, 0 " \ + "L 0, 300 " \ + "L 300, 300 " \ + "L 300, 0 " \ + "L 0, 0" + +static gboolean toggled = FALSE; + +static gboolean +on_button_press (ClutterActor *actor, + const ClutterEvent *event, + gpointer dummy G_GNUC_UNUSED) +{ + if (!toggled) + clutter_actor_animate (actor, CLUTTER_EASE_OUT_CUBIC, 500, + "@constraints.path.offset", 1.0, + NULL); + else + clutter_actor_animate (actor, CLUTTER_EASE_OUT_CUBIC, 500, + "@constraints.path.offset", 0.0, + NULL); + + toggled = !toggled; + + return TRUE; +} + +static gchar * +node_to_string (const ClutterPathNode *node) +{ + GString *buffer = g_string_sized_new (256); + gsize len = 0, i; + + switch (node->type) + { + case CLUTTER_PATH_MOVE_TO: + g_string_append (buffer, "move-to "); + len = 1; + break; + + case CLUTTER_PATH_LINE_TO: + g_string_append (buffer, "line-to "); + len = 1; + break; + + case CLUTTER_PATH_CURVE_TO: + g_string_append (buffer, "curve-to "); + len = 3; + break; + + case CLUTTER_PATH_CLOSE: + g_string_append (buffer, "close"); + len = 0; + break; + + default: + break; + } + + for (i = 0; i < len; i++) + { + if (i == 0) + g_string_append (buffer, "[ "); + + g_string_append_printf (buffer, "[ %d, %d ]", + node->points[i].x, + node->points[i].y); + + if (i == len - 1) + g_string_append (buffer, " ]"); + } + + return g_string_free (buffer, FALSE); +} + +static void +on_node_reached (ClutterPathConstraint *constraint, + ClutterActor *actor, + guint index_) +{ + ClutterPath *path = clutter_path_constraint_get_path (constraint); + ClutterPathNode node; + gchar *str; + + clutter_path_get_node (path, index_, &node); + + str = node_to_string (&node); + g_print ("Node %d reached: %s\n", index_, str); + g_free (str); +} + +G_MODULE_EXPORT int +test_path_constraint_main (int argc, + char *argv[]) +{ + ClutterActor *stage, *rect; + ClutterPath *path; + ClutterColor rect_color = { 0xcc, 0x00, 0x00, 0xff }; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Path Constraint"); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + path = clutter_path_new (); + clutter_path_set_description (path, PATH_DESCRIPTION); + + rect = clutter_rectangle_new (); + clutter_rectangle_set_color (CLUTTER_RECTANGLE (rect), &rect_color); + clutter_actor_set_size (rect, 128, 128); + clutter_actor_set_reactive (rect, TRUE); + clutter_actor_add_constraint_with_name (rect, "path", clutter_path_constraint_new (path, 0.0)); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); + + g_signal_connect (rect, "button-press-event", G_CALLBACK (on_button_press), NULL); + g_signal_connect (clutter_actor_get_constraint (rect, "path"), + "node-reached", + G_CALLBACK (on_node_reached), + NULL); + + clutter_actor_show (stage); + + clutter_main (); + + return EXIT_SUCCESS; +} diff --git a/clutter/tests/interactive/test-pixmap.c b/clutter/tests/interactive/test-pixmap.c new file mode 100644 index 0000000..7593457 --- /dev/null +++ b/clutter/tests/interactive/test-pixmap.c @@ -0,0 +1,331 @@ +#include +#include +#include + +#include + +#ifdef CAIRO_HAS_XLIB_SURFACE +#include +#endif + +#include + +#ifdef CLUTTER_WINDOWING_X11 +#include +#include + +#include +#include +#endif + +#define IMAGE TESTS_DATADIR G_DIR_SEPARATOR_S "redhand.png" + +static gboolean disable_x11 = FALSE; +static gboolean disable_animation = FALSE; + +static GOptionEntry g_options[] = +{ + { "disable-x11", + 0, 0, + G_OPTION_ARG_NONE, + &disable_x11, + "Disable redirection through X11 pixmap", + NULL }, + { "disable-animation", + 0, 0, + G_OPTION_ARG_NONE, + &disable_animation, + "Disable the animations", + NULL }, + + { NULL } +}; + +static void +toggle_texture_quality (ClutterActor *actor) +{ + if (CLUTTER_IS_CONTAINER (actor)) + clutter_container_foreach (CLUTTER_CONTAINER (actor), + (ClutterCallback) toggle_texture_quality, + NULL); + + if (CLUTTER_IS_TEXTURE (actor)) + { + ClutterTextureQuality quality; + + quality = clutter_texture_get_filter_quality (CLUTTER_TEXTURE (actor)); + + if (quality == CLUTTER_TEXTURE_QUALITY_HIGH) + quality = CLUTTER_TEXTURE_QUALITY_MEDIUM; + else + quality = CLUTTER_TEXTURE_QUALITY_HIGH; + + g_print ("switching to quality %s for %p\n", + quality == CLUTTER_TEXTURE_QUALITY_HIGH + ? "high" : "medium", + actor); + + clutter_texture_set_filter_quality (CLUTTER_TEXTURE (actor), quality); + } +} + +static gboolean +stage_key_release_cb (ClutterActor *actor, + ClutterEvent *event, + gpointer data) +{ + switch (clutter_event_get_key_symbol (event)) + { + case CLUTTER_KEY_q: + case CLUTTER_KEY_Q: + clutter_main_quit (); + break; + + case CLUTTER_KEY_m: + toggle_texture_quality (actor); + break; + } + return FALSE; +} + +static gboolean +draw_arc (gpointer data) +{ + Pixmap pixmap = GPOINTER_TO_UINT (data); + Display *dpy = clutter_x11_get_default_display (); + + static GC gc = None; + static int x = 100, y = 100; + + if (gc == None) + { + XGCValues gc_values = { 0 }; + + gc_values.line_width = 12; + /* This is an attempt to get a black pixel will full + opacity. Seemingly the BlackPixel macro and the default GC + value are a fully transparent color */ + gc_values.foreground = 0xff000000; + + gc = XCreateGC (dpy, + pixmap, + GCLineWidth | GCForeground, + &gc_values); + } + + XDrawArc (dpy, pixmap, gc, x, y, 100, 100, 0, 360 * 64); + + x -= 5; + y -= 5; + + return G_SOURCE_CONTINUE; +} + +static gboolean +stage_button_press_cb (ClutterActor *actor, + ClutterEvent *event, + gpointer data) +{ + draw_arc (data); + + return CLUTTER_EVENT_STOP; +} + +Pixmap +create_pixmap (guint *width, guint *height, guint *depth) +{ + Display *dpy = clutter_x11_get_default_display (); + cairo_surface_t *image; + Pixmap pixmap; + XVisualInfo xvisinfo; + XVisualInfo *xvisinfos; + int n; + cairo_surface_t *xlib_surface; + cairo_t *cr; + guint w, h; + + image = cairo_image_surface_create_from_png (IMAGE); + if (cairo_surface_status (image) != CAIRO_STATUS_SUCCESS) + g_error ("Failed to load %s", IMAGE); + + w = cairo_image_surface_get_width (image); + h = cairo_image_surface_get_height (image); + + pixmap = XCreatePixmap (dpy, + DefaultRootWindow (dpy), + w, h, + 32); + + xvisinfo.depth = 32; + xvisinfos = XGetVisualInfo (dpy, VisualDepthMask, &xvisinfo, &n); + if (!xvisinfos) + g_error ("Failed to find a 32bit X Visual"); + + xlib_surface = + cairo_xlib_surface_create (dpy, + pixmap, + xvisinfos->visual, + w, h); + XFree (xvisinfos); + + cr = cairo_create (xlib_surface); + cairo_set_source_surface (cr, image, 0, 0); + cairo_paint (cr); + cairo_surface_destroy (image); + + if (width) + *width = w; + if (height) + *height = h; + if (depth) + *depth = 32; + + return pixmap; +} + +/* each time the timeline animating the label completes, swap the direction */ +static void +timeline_completed (ClutterTimeline *timeline, + gpointer user_data) +{ + clutter_timeline_set_direction (timeline, + !clutter_timeline_get_direction (timeline)); + clutter_timeline_start (timeline); +} + +G_MODULE_EXPORT int +test_pixmap_main (int argc, char **argv) +{ + GOptionContext *context; + Display *xdpy; + int screen; + ClutterActor *group = NULL, *label, *stage, *tex; + Pixmap pixmap; + const ClutterColor gry = { 0x99, 0x99, 0x99, 0xFF }; + Window win_remote; + guint w, h, d; + GC gc; + ClutterTimeline *timeline; + ClutterAlpha *alpha; + ClutterBehaviour *depth_behavior; + int i; + int row_height; + +#ifdef CLUTTER_WINDOWING_X11 + clutter_set_windowing_backend (CLUTTER_WINDOWING_X11); +#endif + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + +#ifdef CLUTTER_WINDOWING_X11 + if (!clutter_check_windowing_backend (CLUTTER_WINDOWING_X11)) + g_error ("test-pixmap requires the X11 Clutter backend."); +#endif + + xdpy = clutter_x11_get_default_display (); + XSynchronize (xdpy, True); + + context = g_option_context_new (" - test-pixmap options"); + g_option_context_add_main_entries (context, g_options, NULL); + g_option_context_parse (context, &argc, &argv, NULL); + + pixmap = create_pixmap (&w, &h, &d); + + screen = DefaultScreen(xdpy); + win_remote = XCreateSimpleWindow (xdpy, DefaultRootWindow(xdpy), + 0, 0, 200, 200, + 0, + WhitePixel(xdpy, screen), + WhitePixel(xdpy, screen)); + + XMapWindow (xdpy, win_remote); + + stage = clutter_stage_new (); + clutter_actor_set_position (stage, 0, 150); + clutter_actor_set_background_color (stage, &gry); + clutter_stage_set_title (CLUTTER_STAGE (stage), "X11 Texture from Pixmap"); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + timeline = clutter_timeline_new (5000); + g_signal_connect (timeline, + "completed", G_CALLBACK (timeline_completed), + NULL); + + alpha = clutter_alpha_new_full (timeline, CLUTTER_LINEAR); + depth_behavior = clutter_behaviour_depth_new (alpha, -2500, 400); + + if (!disable_x11) + { + group = clutter_group_new (); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), group); + label = clutter_text_new_with_text ("fixed", + "ClutterX11Texture (Window)"); + clutter_container_add_actor (CLUTTER_CONTAINER (group), label); + tex = clutter_x11_texture_pixmap_new_with_window (win_remote); + clutter_container_add_actor (CLUTTER_CONTAINER (group), tex); + clutter_actor_set_position (tex, 0, 20); + clutter_x11_texture_pixmap_set_automatic (CLUTTER_X11_TEXTURE_PIXMAP (tex), + TRUE); + clutter_texture_set_filter_quality (CLUTTER_TEXTURE (tex), + CLUTTER_TEXTURE_QUALITY_HIGH); + clutter_actor_set_position (group, 0, 0); + if (!disable_animation) + clutter_behaviour_apply (depth_behavior, group); + } + + if (group) + row_height = clutter_actor_get_height (group); + else + row_height = 0; + + /* NB: We only draw on the window after being redirected, so we dont + * have to worry about handling expose events... */ + gc = XCreateGC (xdpy, win_remote, 0, NULL); + XSetForeground (xdpy, gc, BlackPixel (xdpy, screen)); + XSetLineAttributes(xdpy, gc, 5, LineSolid, CapButt, JoinMiter); + + for (i = 0; i < 10; i++) + XDrawLine (xdpy, win_remote, gc, 0+i*20, 0, 10+i*20+i, 200); + + + group = clutter_group_new (); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), group); + label = clutter_text_new_with_text ("fixed", "ClutterX11Texture (Pixmap)"); + clutter_container_add_actor (CLUTTER_CONTAINER (group), label); + tex = clutter_x11_texture_pixmap_new_with_pixmap (pixmap); + clutter_x11_texture_pixmap_set_automatic (CLUTTER_X11_TEXTURE_PIXMAP (tex), + TRUE); + clutter_container_add_actor (CLUTTER_CONTAINER (group), tex); + clutter_actor_set_position (tex, 0, 20); + clutter_texture_set_filter_quality (CLUTTER_TEXTURE (tex), + CLUTTER_TEXTURE_QUALITY_HIGH); + /* oddly, the actor's size is 0 until it is realized, even though + pixmap-height is set */ + clutter_actor_set_position (group, 0, row_height); + if (!disable_animation) + clutter_behaviour_apply (depth_behavior, group); + + + g_signal_connect (stage, "key-release-event", + G_CALLBACK (stage_key_release_cb), (gpointer)pixmap); + g_signal_connect (stage, "button-press-event", + G_CALLBACK (stage_button_press_cb), (gpointer)pixmap); + + clutter_actor_show (stage); + + if (!disable_animation) + clutter_timeline_start (timeline); + + clutter_threads_add_timeout (1000, draw_arc, GUINT_TO_POINTER (pixmap)); + + clutter_main (); + + return EXIT_SUCCESS; +} + +G_MODULE_EXPORT const char * +test_pixmap_describe (void) +{ + return "GLX Texture from pixmap extension support."; +} diff --git a/clutter/tests/interactive/test-rotate-zoom.c b/clutter/tests/interactive/test-rotate-zoom.c new file mode 100644 index 0000000..2c25d7f --- /dev/null +++ b/clutter/tests/interactive/test-rotate-zoom.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2013 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * Boston, MA 02111-1307, USA. + * + */ +#include +#include +#include +#include +#include +#include + +#define STAGE_WIDTH 800 +#define STAGE_HEIGHT 550 + +static ClutterActor * +create_hand (void) +{ + GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (TESTS_DATADIR G_DIR_SEPARATOR_S "redhand.png", NULL); + ClutterContent *image = clutter_image_new (); + ClutterActor *actor = clutter_actor_new (); + + clutter_image_set_data (CLUTTER_IMAGE (image), + gdk_pixbuf_get_pixels (pixbuf), + gdk_pixbuf_get_has_alpha (pixbuf) + ? COGL_PIXEL_FORMAT_RGBA_8888 + : COGL_PIXEL_FORMAT_RGB_888, + gdk_pixbuf_get_width (pixbuf), + gdk_pixbuf_get_height (pixbuf), + gdk_pixbuf_get_rowstride (pixbuf), + NULL); + clutter_actor_set_content (actor, image); + clutter_actor_set_size (actor, + gdk_pixbuf_get_width (pixbuf), + gdk_pixbuf_get_height (pixbuf)); + clutter_actor_set_reactive (actor, TRUE); + + g_object_unref (pixbuf); + + return actor; +} + +G_MODULE_EXPORT int +test_rotate_zoom_main (int argc, char *argv[]) +{ + ClutterActor *stage, *actor; + gfloat width, height; + + /* initialize Clutter */ + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return EXIT_FAILURE; + + /* create a resizable stage */ + stage = clutter_stage_new (); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Rotate and Zoom actions"); + clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); + clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT); + clutter_actor_set_reactive (stage, FALSE); + clutter_actor_show (stage); + + actor = create_hand (); + clutter_actor_add_action (actor, clutter_rotate_action_new ()); + clutter_actor_add_action (actor, clutter_zoom_action_new ()); + clutter_actor_add_child (stage, actor); + + clutter_actor_get_size (actor, &width, &height); + clutter_actor_set_position (actor, + STAGE_WIDTH / 2 - width / 2, + STAGE_HEIGHT / 2 - height / 2); + + clutter_main (); + + return EXIT_SUCCESS; +} + +G_MODULE_EXPORT const char * +test_rotate_zoom_describe (void) +{ + return "Rotates and zooms an actor using touch events"; +} diff --git a/clutter/tests/interactive/test-scale.c b/clutter/tests/interactive/test-scale.c new file mode 100644 index 0000000..a21f6d6 --- /dev/null +++ b/clutter/tests/interactive/test-scale.c @@ -0,0 +1,119 @@ +#include +#include +#include + +static const ClutterGravity gravities[] = { + CLUTTER_GRAVITY_NORTH_EAST, + CLUTTER_GRAVITY_NORTH, + CLUTTER_GRAVITY_NORTH_WEST, + CLUTTER_GRAVITY_WEST, + CLUTTER_GRAVITY_SOUTH_WEST, + CLUTTER_GRAVITY_SOUTH, + CLUTTER_GRAVITY_SOUTH_EAST, + CLUTTER_GRAVITY_EAST, + CLUTTER_GRAVITY_CENTER, + CLUTTER_GRAVITY_NONE +}; + +static gint gindex = 0; +static ClutterActor *label; + +static void +set_next_gravity (ClutterActor *actor) +{ + ClutterGravity gravity = gravities[gindex]; + GEnumClass *eclass; + GEnumValue *evalue; + + clutter_actor_move_anchor_point_from_gravity (actor, gravities[gindex]); + + eclass = g_type_class_ref (CLUTTER_TYPE_GRAVITY); + evalue = g_enum_get_value (eclass, gravity); + clutter_text_set_text (CLUTTER_TEXT (label), evalue->value_nick); + g_type_class_unref (eclass); + + if (++gindex >= G_N_ELEMENTS (gravities)) + gindex = 0; +} + +static gdouble +my_ramp_func (ClutterAlpha *alpha, + gpointer unused) +{ + ClutterTimeline *timeline = clutter_alpha_get_timeline (alpha); + + return clutter_timeline_get_progress (timeline); +} + +G_MODULE_EXPORT int +test_scale_main (int argc, char *argv[]) +{ + ClutterActor *stage, *rect; + ClutterColor rect_color = { 0xff, 0xff, 0xff, 0x99 }; + ClutterTimeline *timeline; + ClutterAlpha *alpha; + ClutterBehaviour *behave; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Scaling"); + clutter_actor_set_background_color (stage, CLUTTER_COLOR_Black); + clutter_actor_set_size (stage, 300, 300); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + rect = clutter_rectangle_new_with_color (&rect_color); + clutter_actor_set_size (rect, 100, 100); + clutter_actor_set_position (rect, 100, 100); + + clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); + + label = clutter_text_new_with_text ("Sans 20px", ""); + clutter_text_set_color (CLUTTER_TEXT (label), CLUTTER_COLOR_White); + clutter_actor_set_position (label, + clutter_actor_get_x (rect), + clutter_actor_get_y (rect) + + clutter_actor_get_height (rect)); + + clutter_container_add_actor (CLUTTER_CONTAINER (stage), label); + + rect_color.alpha = 0xff; + rect = clutter_rectangle_new_with_color (&rect_color); + clutter_actor_set_position (rect, 100, 100); + clutter_actor_set_size (rect, 100, 100); + set_next_gravity (rect); + + clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); + + timeline = clutter_timeline_new (750); + alpha = clutter_alpha_new_with_func (timeline, + my_ramp_func, + NULL, NULL); + + behave = clutter_behaviour_scale_new (alpha, + 0.0, 0.0, /* scale start */ + 1.0, 1.0); /* scale end */ + + clutter_behaviour_apply (behave, rect); + + clutter_timeline_set_repeat_count (timeline, -1); + g_signal_connect_swapped (timeline, "completed", + G_CALLBACK (set_next_gravity), rect); + clutter_timeline_start (timeline); + + clutter_actor_show_all (stage); + + clutter_main(); + + g_object_unref (timeline); + g_object_unref (behave); + + return EXIT_SUCCESS; +} + +G_MODULE_EXPORT const char * +test_scale_describe (void) +{ + return "Scaling animation and scaling center changes"; +} diff --git a/clutter/tests/interactive/test-script-signals.json b/clutter/tests/interactive/test-script-signals.json new file mode 100644 index 0000000..0d3f6bd --- /dev/null +++ b/clutter/tests/interactive/test-script-signals.json @@ -0,0 +1,68 @@ +[ + { + "id" : "button", + "type" : "ClutterRectangle", + + "width" : "16 em", + "height" : "6 em", + + "color" : "rgb(255, 0, 0)", + "opacity" : 128, + + "scale-gravity" : "center", + + "reactive" : true, + + "signals" : [ + { + "name" : "button-press-event", + "handler" : "on_button_press" + }, + { "name" : "enter-event", "states" : "button-states", "target-state" : "hover" }, + { "name" : "leave-event", "states" : "button-states", "target-state" : "base" }, + { "name" : "button-press-event", "states" : "button-states", "target-state" : "active" }, + { "name" : "button-release-event", "states" : "button-states", "target-state" : "hover" } + ] + }, + + { + "id" : "button-states", + "type" : "ClutterState", + + "duration" : 250, + + "transitions" : [ + { + "source" : null, + "target" : "base", + + "keys" : [ + [ "button", "opacity", "linear", 128 ], + [ "button", "scale-x", "ease-in-cubic", 1.0 ], + [ "button", "scale-y", "ease-in-cubic", 1.0 ], + [ "button", "color", "linear", "rgb(255, 0, 0)" ] + ] + }, + { + "source" : null, + "target" : "hover", + + "keys" : [ + [ "button", "opacity", "linear", 255 ], + [ "button", "scale-x", "ease-out-bounce", 1.4 ], + [ "button", "scale-y", "ease-out-bounce", 1.4 ], + [ "button", "color", "linear", "rgb(0, 255, 0)" ] + ] + }, + { + "source" : null, + "target" : "active", + + "keys" : [ + [ "button", "opacity", "linear", 255 ], + [ "button", "color", "linear", "rgb(0, 0, 255)" ] + ] + } + ] + } +] diff --git a/clutter/tests/interactive/test-script.c b/clutter/tests/interactive/test-script.c new file mode 100644 index 0000000..e30de3d --- /dev/null +++ b/clutter/tests/interactive/test-script.c @@ -0,0 +1,207 @@ +#include +#include + +#include + +#include +#include +#include + +static ClutterScript *script = NULL; +static guint merge_id = 0; + +static const gchar *test_unmerge = +"[" +" {" +" \"id\" : \"main-stage\"," +" \"type\" : \"ClutterStage\"," +" \"children\" : [ \"blue-button\" ]" +" }," +" {" +" \"id\" : \"blue-button\"," +" \"type\" : \"ClutterRectangle\"," +" \"color\" : \"#0000ffff\"," +" \"x\" : 350," +" \"y\" : 50," +" \"width\" : 100," +" \"height\" : 100," +" \"visible\" : true," +" \"reactive\" : true" +" }" +"]"; + +static const gchar *test_behaviour = +"[" +" {" +" \"id\" : \"main-timeline\"," +" \"type\" : \"ClutterTimeline\"," +" \"duration\" : 5000," +" \"loop\" : true" +" }," +" {" +" \"id\" : \"sine-alpha\"," +" \"type\" : \"ClutterAlpha\"," +" \"function\" : \"sine_alpha\"," +" \"timeline\" : \"main-timeline\"" +" }," +" {" +" \"id\" : \"path-behaviour\"," +" \"type\" : \"ClutterBehaviourPath\"," +" \"path\" : \"M 50 50 L 100 100\"," +" \"alpha\" : {" +" \"timeline\" : \"main-timeline\"," +" \"function\" : \"double_ramp_alpha\"" +" }" +" }," +" {" +" \"id\" : \"rotate-behaviour\"," +" \"type\" : \"ClutterBehaviourRotate\"," +" \"angle-start\" : 0.0," +" \"angle-end\" : 360.0," +" \"axis\" : \"y-axis\"," +" \"alpha\" : \"sine-alpha\"" +" }," +" {" +" \"id\" : \"fade-behaviour\"," +" \"type\" : \"ClutterBehaviourOpacity\"," +" \"opacity-start\" : 255," +" \"opacity-end\" : 0," +" \"alpha\" : {" +" \"id\" : \"fade-alpha\"," +" \"type\" : \"ClutterAlpha\"," +" \"timeline\" : \"main-timeline\"," +" \"mode\" : \"linear\"" +" }" +" }" +"]"; + +gdouble +sine_alpha (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = clutter_alpha_get_timeline (alpha); + + return sin (clutter_timeline_get_progress (timeline) * G_PI); +} + +gdouble +double_ramp_alpha (ClutterAlpha *alpha, + gpointer dummy G_GNUC_UNUSED) +{ + ClutterTimeline *timeline = clutter_alpha_get_timeline (alpha); + gdouble progress = clutter_timeline_get_progress (timeline); + + if (progress >= 0.5) + return 1.0 - progress; + + return progress; +} + +static gboolean +blue_button_press (ClutterActor *actor, + ClutterButtonEvent *event, + gpointer data) +{ + g_print ("[*] Pressed '%s'\n", clutter_get_script_id (G_OBJECT (actor))); + g_print ("[*] Unmerging objects with merge id: %d\n", merge_id); + + clutter_script_unmerge_objects (script, merge_id); + + return TRUE; +} + +static gboolean +red_button_press (ClutterActor *actor, + ClutterButtonEvent *event, + gpointer data) +{ + GObject *timeline; + + g_print ("[*] Pressed '%s'\n", clutter_get_script_id (G_OBJECT (actor))); + + timeline = clutter_script_get_object (script, "main-timeline"); + g_assert (CLUTTER_IS_TIMELINE (timeline)); + + if (!clutter_timeline_is_playing (CLUTTER_TIMELINE (timeline))) + clutter_timeline_start (CLUTTER_TIMELINE (timeline)); + else + clutter_timeline_pause (CLUTTER_TIMELINE (timeline)); + + return TRUE; +} + +G_MODULE_EXPORT int +test_script_main (int argc, char *argv[]) +{ + GObject *stage, *blue_button, *red_button; + GError *error = NULL; + gchar *file; + gint res; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + script = clutter_script_new (); + g_assert (CLUTTER_IS_SCRIPT (script)); + + clutter_script_load_from_data (script, test_behaviour, -1, &error); + if (error) + { + g_print ("*** Error:\n" + "*** %s\n", error->message); + g_error_free (error); + g_object_unref (script); + return EXIT_FAILURE; + } + + file = g_build_filename (TESTS_DATADIR, "test-script.json", NULL); + clutter_script_load_from_file (script, file, &error); + if (error) + { + g_print ("*** Error:\n" + "*** %s\n", error->message); + g_error_free (error); + g_object_unref (script); + g_free (file); + return EXIT_FAILURE; + } + + g_free (file); + + merge_id = clutter_script_load_from_data (script, test_unmerge, -1, &error); + if (error) + { + g_print ("*** Error:\n" + "*** %s\n", error->message); + g_error_free (error); + g_object_unref (script); + return EXIT_FAILURE; + } + + clutter_script_connect_signals (script, NULL); + + res = clutter_script_get_objects (script, + "main-stage", &stage, + "red-button", &red_button, + "blue-button", &blue_button, + NULL); + g_assert (res == 3); + + clutter_actor_show (CLUTTER_ACTOR (stage)); + + g_signal_connect (red_button, + "button-press-event", + G_CALLBACK (red_button_press), + NULL); + + g_signal_connect (blue_button, + "button-press-event", + G_CALLBACK (blue_button_press), + NULL); + + clutter_main (); + + g_object_unref (script); + + return EXIT_SUCCESS; +} diff --git a/clutter/tests/interactive/test-script.json b/clutter/tests/interactive/test-script.json new file mode 100644 index 0000000..54d4fb4 --- /dev/null +++ b/clutter/tests/interactive/test-script.json @@ -0,0 +1,74 @@ +{ + "My Scene" : { + "id" : "main-stage", + "type" : "ClutterStage", + "title" : { "translatable" : true, "string" : "ClutterScript test" }, + "color" : "white", + "signals" : [ + { "name" : "key-press-event", "handler" : "clutter_main_quit" }, + { "name" : "destroy", "handler" : "clutter_main_quit" } + ], + "children" : [ + { + "id" : "red-button", + "type" : "ClutterRectangle", + "color" : "#ff0000ff", + "x" : 50, "y" : 50, "width" : 100, "height" : 100, + "reactive" : true, + "rotation" : [ + { "z-axis" : [ 45.0, [ 75, 75 ] ] } + ], + "behaviours" : [ "fade-behaviour", "path-behaviour" ] + }, + { + "id" : "green-button", + "type" : "ClutterRectangle", + "color" : "#00ff00ff", + "border-width" : 5, + "border-color" : "#00cc00ff", + "position" : [ 200.0, 50.0 ], + "size" : { "width" : 100.0, "height" : 100.0 }, + "depth" : -200.0, + "reactive" : true, + "signals" : [ + { "name" : "button-press-event", "handler" : "clutter_main_quit" } + ] + }, + { + "id" : "red-hand", + "type" : "ClutterTexture", + "filename" : "redhand.png", + "position" : { "x" : 100.0, "y" : 100.0 }, + "width" : "20 mm", + "keep-aspect-ratio" : true, + "anchor-x" : "5 em", + "anchor-y" : "5 pt", + "opacity" : 100, + "behaviours" : [ "rotate-behaviour", "fade-behaviour" ] + }, + { + "id" : "red-hand-clone", + "type" : "ClutterClone", + "source" : "red-hand", + "position" : [ 250.0, 150.0 ], + "opacity" : 100 + }, + { + "id" : "label", + "type" : "ClutterText", + "x" : 50, + "y" : 200, + "text" : { "translatable" : true, "string" : "Clutter Script" }, + "font-name" : "Sans 24px", + "color" : "black", + "line-alignment" : "center", + "line-wrap" : false, + "ellipsize" : "none", + "rotation" : [ + { "y-axis" : [ 60.0, [ 275, 100 ] ] }, + { "z-axis" : [ 45.0, [ 75, 75 ] ] } + ] + } + ] + } +} diff --git a/clutter/tests/interactive/test-scrolling.c b/clutter/tests/interactive/test-scrolling.c new file mode 100644 index 0000000..173325f --- /dev/null +++ b/clutter/tests/interactive/test-scrolling.c @@ -0,0 +1,134 @@ +#include +#include +#include +#include + +#define RECT_WIDTH 400 +#define RECT_HEIGHT 300 +#define N_RECTS 7 + +static const gchar *rect_color[N_RECTS] = { + "#edd400", + "#f57900", + "#c17d11", + "#73d216", + "#3465a4", + "#75507b", + "#cc0000" +}; + +static ClutterActor *rectangle[N_RECTS]; +static ClutterActor *viewport = NULL; + +static void +on_drag_end (ClutterDragAction *action, + ClutterActor *actor, + gfloat event_x, + gfloat event_y, + ClutterModifierType modifiers) +{ + gfloat viewport_x = clutter_actor_get_x (viewport); + gfloat offset_x; + gint child_visible; + + /* check if we're at the viewport edges */ + if (viewport_x > 0) + { + clutter_actor_save_easing_state (viewport); + clutter_actor_set_easing_mode (viewport, CLUTTER_EASE_OUT_BOUNCE); + clutter_actor_set_x (viewport, 0); + clutter_actor_restore_easing_state (viewport); + return; + } + + if (viewport_x < (-1.0f * (RECT_WIDTH * (N_RECTS - 1)))) + { + clutter_actor_save_easing_state (viewport); + clutter_actor_set_easing_mode (viewport, CLUTTER_EASE_OUT_BOUNCE); + clutter_actor_set_x (viewport, -1.0f * (RECT_WIDTH * (N_RECTS - 1))); + clutter_actor_restore_easing_state (viewport); + return; + } + + /* animate the viewport to fully show the child once we pass + * a certain threshold with the dragging action + */ + offset_x = fabsf (viewport_x) / RECT_WIDTH + 0.5f; + if (offset_x > (RECT_WIDTH * 0.33)) + child_visible = (int) offset_x + 1; + else + child_visible = (int) offset_x; + + /* sanity check on the children number */ + child_visible = CLAMP (child_visible, 0, N_RECTS); + + clutter_actor_save_easing_state (viewport); + clutter_actor_set_x (viewport, -1.0f * RECT_WIDTH * child_visible); + clutter_actor_restore_easing_state (viewport); +} + +G_MODULE_EXPORT int +test_scrolling_main (int argc, char *argv[]) +{ + ClutterActor *stage; + ClutterActor *scroll; + ClutterAction *action; + gint i; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Scrolling"); + clutter_actor_set_size (stage, 800, 600); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + /* scroll: the group that contains the scrolling viewport; we set its + * size to be the same as one rectangle, position it in the middle of + * the stage and set it to clip its contents to the allocated size + */ + scroll = clutter_actor_new (); + clutter_actor_add_child (stage, scroll); + clutter_actor_set_size (scroll, RECT_WIDTH, RECT_HEIGHT); + clutter_actor_add_constraint (scroll, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5)); + clutter_actor_set_clip_to_allocation (scroll, TRUE); + + /* viewport: the actual container for the children; we scroll it using + * the Drag action constrained to the horizontal axis, and every time + * the dragging ends we check whether we're dragging past the end of + * the viewport + */ + viewport = clutter_actor_new (); + clutter_actor_set_layout_manager (viewport, clutter_box_layout_new ()); + clutter_actor_add_child (scroll, viewport); + + /* add dragging capabilities to the viewport; the heavy lifting is + * all done by the DragAction itself, plus the ::drag-end signal + * handler in our code + */ + action = clutter_drag_action_new (); + clutter_actor_add_action (viewport, action); + clutter_drag_action_set_drag_axis (CLUTTER_DRAG_ACTION (action), + CLUTTER_DRAG_X_AXIS); + g_signal_connect (action, "drag-end", G_CALLBACK (on_drag_end), NULL); + clutter_actor_set_reactive (viewport, TRUE); + + /* children of the viewport */ + for (i = 0; i < N_RECTS; i++) + { + ClutterColor color; + + clutter_color_from_string (&color, rect_color[i]); + + rectangle[i] = clutter_actor_new (); + clutter_actor_set_background_color (rectangle[i], &color); + clutter_actor_add_child (viewport, rectangle[i]); + clutter_actor_set_size (rectangle[i], RECT_WIDTH, RECT_HEIGHT); + } + + clutter_actor_show (stage); + + clutter_main (); + + return EXIT_SUCCESS; +} diff --git a/clutter/tests/interactive/test-shader-effects.c b/clutter/tests/interactive/test-shader-effects.c new file mode 100644 index 0000000..d185252 --- /dev/null +++ b/clutter/tests/interactive/test-shader-effects.c @@ -0,0 +1,83 @@ +#include +#include +#include + +#include +#include + +#include + +G_MODULE_EXPORT int +test_shader_effects_main (int argc, char *argv[]) +{ + ClutterTimeline *timeline; + ClutterActor *stage, *hand, *label, *rect; + gchar *file; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + /* Make a timeline */ + timeline = clutter_timeline_new (7692); + clutter_timeline_set_repeat_count (timeline, -1); + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Rotations"); + clutter_actor_set_background_color (stage, CLUTTER_COLOR_Aluminium3); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + /* Make a hand */ + file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL); + hand = clutter_texture_new_from_file (file, NULL); + if (!hand) + g_error("Unable to load '%s'", file); + + g_free (file); + + clutter_actor_set_position (hand, 326, 265); + clutter_actor_add_effect_with_name (hand, "desaturate", clutter_desaturate_effect_new (0.75)); + clutter_actor_add_effect_with_name (hand, "blur", clutter_blur_effect_new ()); + clutter_actor_animate_with_timeline (hand, CLUTTER_LINEAR, timeline, + "@effects.desaturate.factor", 1.0, + "rotation-angle-z", 360.0, + "fixed::anchor-x", 86.0, + "fixed::anchor-y", 125.0, + "opacity", 128, + NULL); + + rect = clutter_rectangle_new_with_color (CLUTTER_COLOR_DarkOrange); + clutter_actor_add_effect_with_name (rect, "blur", clutter_blur_effect_new ()); + clutter_actor_set_position (rect, 415, 215); + clutter_actor_set_size (rect, 150, 150); + clutter_actor_animate_with_timeline (rect, CLUTTER_LINEAR, timeline, + "rotation-angle-z", 360.0, + "fixed::anchor-x", 75.0, + "fixed::anchor-y", 75.0, + NULL); + + label = clutter_text_new_with_text ("Mono 16", + "The Wonder\n" + "of the\n" + "Spinning Hand"); + clutter_text_set_line_alignment (CLUTTER_TEXT (label), PANGO_ALIGN_CENTER); + clutter_actor_set_position (label, 336, 275); + clutter_actor_set_size (label, 500, 100); + clutter_actor_animate_with_timeline (label, CLUTTER_LINEAR, timeline, + "rotation-angle-z", 360.0, + "fixed::anchor-x", 86.0, + "fixed::anchor-y", 125.0, + NULL); + + clutter_container_add (CLUTTER_CONTAINER (stage), rect, hand, label, NULL); + + /* start the timeline and thus the animations */ + clutter_timeline_start (timeline); + + clutter_actor_show_all (stage); + + clutter_main(); + + g_object_unref (timeline); + + return 0; +} diff --git a/clutter/tests/interactive/test-stage-read-pixels.c b/clutter/tests/interactive/test-stage-read-pixels.c new file mode 100644 index 0000000..535fc8d --- /dev/null +++ b/clutter/tests/interactive/test-stage-read-pixels.c @@ -0,0 +1,168 @@ +#include +#include +#include + +#define DOT_SIZE 2 +#define TEX_SIZE 64 + +typedef struct _CallbackData CallbackData; + +struct _CallbackData +{ + ClutterActor *stage; + ClutterActor *tex; + ClutterActor *box; + ClutterMotionEvent event; + guint idle_source; +}; + +static ClutterActor * +make_label (void) +{ + ClutterActor *label; + gchar *text; + gchar *argv[] = { "ls", "--help", NULL }; + + label = clutter_text_new (); + clutter_text_set_font_name (CLUTTER_TEXT (label), "Sans 10"); + + if (g_spawn_sync (NULL, argv, NULL, + G_SPAWN_STDERR_TO_DEV_NULL | G_SPAWN_SEARCH_PATH, + NULL, NULL, &text, NULL, NULL, NULL)) + { + clutter_text_set_text (CLUTTER_TEXT (label), text); + g_free (text); + } + + return label; +} + +static ClutterActor * +make_tex (void) +{ + ClutterActor *tex = clutter_texture_new (); + + clutter_actor_set_size (tex, TEX_SIZE * 2, TEX_SIZE * 2); + + return tex; +} + +static ClutterActor * +make_box (void) +{ + ClutterActor *box; + static const ClutterColor blue = { 0x00, 0x00, 0xff, 0xff }; + + box = clutter_rectangle_new_with_color (&blue); + clutter_actor_set_size (box, DOT_SIZE + 2, DOT_SIZE + 2); + clutter_actor_hide (box); + + return box; +} + +static gboolean +on_motion_idle (gpointer user_data) +{ + CallbackData *data = (CallbackData *) user_data; + guchar *pixels, *p; + gfloat stage_width, stage_height; + gint x, y; + + data->idle_source = 0; + + clutter_actor_get_size (data->stage, &stage_width, &stage_height); + + x = CLAMP (data->event.x - TEX_SIZE / 2, 0, stage_width - TEX_SIZE); + y = CLAMP (data->event.y - TEX_SIZE / 2, 0, stage_height - TEX_SIZE); + + clutter_actor_set_position (data->box, + x + TEX_SIZE / 2 - 1, + y + TEX_SIZE / 2 - 1); + clutter_actor_show (data->box); + + /* Redraw so that the layouting will be done and the box will be + drawn in the right position */ + clutter_stage_ensure_redraw (CLUTTER_STAGE (data->stage)); + + pixels = clutter_stage_read_pixels (CLUTTER_STAGE (data->stage), + x, y, + TEX_SIZE, TEX_SIZE); + + /* Make a red dot in the center */ + p = pixels + (TEX_SIZE / 2 - DOT_SIZE / 2) * TEX_SIZE * 4 + + (TEX_SIZE / 2 - DOT_SIZE / 2) * 4; + for (y = 0; y < DOT_SIZE; y++) + { + for (x = 0; x < DOT_SIZE; x++) + { + *(p++) = 255; + memset (p, 0, 3); + p += 3; + } + p += TEX_SIZE * 4 - DOT_SIZE * 4; + } + + /* Set all of the alpa values to full */ + for (p = pixels + TEX_SIZE * TEX_SIZE * 4; p > pixels; p -= 4) + *(p - 1) = 255; + + clutter_texture_set_from_rgb_data (CLUTTER_TEXTURE (data->tex), + pixels, TRUE, + TEX_SIZE, TEX_SIZE, + TEX_SIZE * 4, 4, 0, NULL); + g_free (pixels); + + return FALSE; +} + +static gboolean +on_motion (ClutterActor *stage, ClutterMotionEvent *event, CallbackData *data) +{ + /* Handle the motion event in an idle handler so that multiple + events will be combined into one */ + if (data->idle_source == 0) + data->idle_source = clutter_threads_add_idle (on_motion_idle, data); + + data->event = *event; + + return FALSE; +} + +G_MODULE_EXPORT int +test_stage_read_pixels_main (int argc, char **argv) +{ + CallbackData data; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + data.idle_source = 0; + data.stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (data.stage), "Read Pixels"); + g_signal_connect (data.stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + data.tex = make_tex (); + data.box = make_box (); + clutter_actor_set_position (data.tex, + clutter_actor_get_width (data.stage) + - clutter_actor_get_width (data.tex), + clutter_actor_get_height (data.stage) + - clutter_actor_get_height (data.tex)); + + clutter_container_add (CLUTTER_CONTAINER (data.stage), + make_label (), data.tex, data.box, NULL); + + g_signal_connect (data.stage, "motion-event", G_CALLBACK (on_motion), &data); + + clutter_actor_show (data.stage); + + clutter_main (); + + return 0; +} + +G_MODULE_EXPORT const char * +test_stage_read_pixels_describe (void) +{ + return "Read back pixels from a Stage."; +} diff --git a/clutter/tests/interactive/test-stage-sizing.c b/clutter/tests/interactive/test-stage-sizing.c new file mode 100644 index 0000000..4522301 --- /dev/null +++ b/clutter/tests/interactive/test-stage-sizing.c @@ -0,0 +1,141 @@ +#include +#include +#include + +static gboolean +fullscreen_clicked_cb (ClutterStage *stage) +{ + clutter_stage_set_fullscreen (stage, !clutter_stage_get_fullscreen (stage)); + return CLUTTER_EVENT_STOP; +} + +static gboolean +resize_clicked_cb (ClutterStage *stage) +{ + clutter_stage_set_user_resizable (stage, + !clutter_stage_get_user_resizable (stage)); + return CLUTTER_EVENT_STOP; +} + +static gboolean +shrink_clicked_cb (ClutterActor *stage) +{ + gfloat width, height; + clutter_actor_get_size (stage, &width, &height); + clutter_actor_set_size (stage, MAX (0, width - 10.f), MAX (0, height - 10.f)); + return CLUTTER_EVENT_STOP; +} + +static gboolean +expand_clicked_cb (ClutterActor *stage) +{ + gfloat width, height; + clutter_actor_get_size (stage, &width, &height); + clutter_actor_set_size (stage, width + 10.f, height + 10.f); + return CLUTTER_EVENT_STOP; +} + +static void +on_fullscreen (ClutterStage *stage) +{ + float width, height; + gboolean is_fullscreen; + + is_fullscreen = clutter_stage_get_fullscreen (stage); + + clutter_actor_get_size (CLUTTER_ACTOR (stage), &width, &height); + + g_print ("Stage size [%s]: %d x %d\n", + is_fullscreen ? "fullscreen" : "not fullscreen", + (int) width, + (int) height); +} + +G_MODULE_EXPORT int +test_stage_sizing_main (int argc, char *argv[]) +{ + ClutterActor *stage, *rect, *label, *box; + ClutterMargin margin = { 12.f, 12.f, 6.f, 6.f }; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Stage Sizing"); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + g_signal_connect_after (stage, "notify::fullscreen-set", G_CALLBACK (on_fullscreen), NULL); + + box = clutter_actor_new (); + clutter_actor_set_layout_manager (box, clutter_box_layout_new ()); + clutter_actor_add_constraint (box, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5)); + clutter_actor_add_child (stage, box); + + rect = clutter_actor_new (); + clutter_actor_set_layout_manager (rect, + clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_CENTER, + CLUTTER_BIN_ALIGNMENT_CENTER)); + clutter_actor_set_background_color (rect, CLUTTER_COLOR_LightScarletRed); + clutter_actor_set_reactive (rect, TRUE); + g_signal_connect_swapped (rect, "button-press-event", + G_CALLBACK (fullscreen_clicked_cb), + stage); + label = clutter_text_new_with_text ("Sans 16", "Toggle fullscreen"); + clutter_actor_set_margin (label, &margin); + clutter_actor_add_child (rect, label); + clutter_actor_add_child (box, rect); + + rect = clutter_actor_new (); + clutter_actor_set_layout_manager (rect, + clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_CENTER, + CLUTTER_BIN_ALIGNMENT_CENTER)); + clutter_actor_set_background_color (rect, CLUTTER_COLOR_Chameleon); + clutter_actor_set_reactive (rect, TRUE); + g_signal_connect_swapped (rect, "button-press-event", + G_CALLBACK (resize_clicked_cb), stage); + label = clutter_text_new_with_text ("Sans 16", "Toggle resizable"); + clutter_actor_set_margin (label, &margin); + clutter_actor_add_child (rect, label); + clutter_actor_add_child (box, rect); + + rect = clutter_actor_new (); + clutter_actor_set_layout_manager (rect, + clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_CENTER, + CLUTTER_BIN_ALIGNMENT_CENTER)); + clutter_actor_set_background_color (rect, CLUTTER_COLOR_SkyBlue); + clutter_actor_set_reactive (rect, TRUE); + g_signal_connect_swapped (rect, "button-press-event", + G_CALLBACK (shrink_clicked_cb), stage); + label = clutter_text_new_with_text ("Sans 16", "Shrink"); + clutter_actor_set_margin (label, &margin); + clutter_actor_add_child (rect, label); + clutter_actor_add_child (box, rect); + + rect = clutter_actor_new (); + clutter_actor_set_layout_manager (rect, + clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_CENTER, + CLUTTER_BIN_ALIGNMENT_CENTER)); + clutter_actor_set_background_color (rect, CLUTTER_COLOR_Butter); + clutter_actor_set_reactive (rect, TRUE); + g_signal_connect_swapped (rect, "button-press-event", + G_CALLBACK (expand_clicked_cb), stage); + label = clutter_text_new_with_text ("Sans 16", "Expand"); + clutter_actor_set_margin (label, &margin); + clutter_actor_add_child (rect, label); + clutter_actor_add_child (box, rect); + + clutter_stage_set_minimum_size (CLUTTER_STAGE (stage), + clutter_actor_get_width (box), + clutter_actor_get_height (box)); + + clutter_actor_show (stage); + + clutter_main (); + + return EXIT_SUCCESS; +} + +G_MODULE_EXPORT const char * +test_stage_sizing_describe (void) +{ + return "Check stage sizing policies."; +} diff --git a/clutter/tests/interactive/test-state-animator.c b/clutter/tests/interactive/test-state-animator.c new file mode 100644 index 0000000..42ae7d2 --- /dev/null +++ b/clutter/tests/interactive/test-state-animator.c @@ -0,0 +1,144 @@ +#include +#include +#include +#include + +static ClutterState *state; +static ClutterAnimator *animator; + +static gboolean press_event (ClutterActor *actor, + ClutterEvent *event, + gpointer user_data) +{ + clutter_grab_pointer (actor); + clutter_state_set_state (state, "end"); + return TRUE; +} + +static gboolean release_event (ClutterActor *actor, + ClutterEvent *event, + gpointer user_data) +{ + clutter_state_set_state (state, "start"); + clutter_ungrab_pointer (); + return TRUE; +} + + +static ClutterActor *new_rect (gint r, + gint g, + gint b, + gint a) +{ + GError *error = NULL; + ClutterColor *color = clutter_color_new (r, g, b, a); + ClutterActor *rectangle; + + gchar *file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL); + rectangle = clutter_texture_new_from_file (file, &error); + if (rectangle == NULL) + g_error ("image load failed: %s", error->message); + g_free (file); + + clutter_actor_set_size (rectangle, 128, 128); + clutter_color_free (color); + return rectangle; +} + +G_MODULE_EXPORT gint +test_state_animator_main (gint argc, + gchar **argv) +{ + ClutterActor *stage; + ClutterActor *rects[40]; + gint i; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "State and Animator"); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + for (i = 0; i < 2; i++) + { + rects[i] = new_rect (255 * (i * 1.0 / 40), 50, 160, 255); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), rects[i]); + clutter_actor_set_anchor_point (rects[i], 64, 64); + clutter_actor_set_position (rects[i], 320.0, 240.0); + clutter_actor_set_opacity (rects[i], 0x70); + + clutter_actor_set_reactive (rects[i], TRUE); + g_signal_connect (rects[i], "button-press-event", G_CALLBACK (press_event), NULL); + g_signal_connect (rects[i], "button-release-event", G_CALLBACK (release_event), NULL); + } + + state = clutter_state_new (); + clutter_state_set (state, NULL, "start", + rects[0], "depth", CLUTTER_LINEAR, 0.0, + rects[0], "x", CLUTTER_LINEAR, 100.0, + rects[0], "y", CLUTTER_LINEAR, 300.0, + rects[1], "opacity", CLUTTER_LINEAR, 0x20, + rects[1], "scale-x", CLUTTER_LINEAR, 1.0, + rects[1], "scale-y", CLUTTER_LINEAR, 1.0, + NULL); + clutter_state_set (state, NULL, "end", + rects[0], "depth", CLUTTER_LINEAR, 200.0, + rects[0], "x", CLUTTER_LINEAR, 320.0, + rects[0], "y", CLUTTER_LINEAR, 240.0, + rects[1], "opacity", CLUTTER_LINEAR, 0xff, + rects[1], "scale-x", CLUTTER_LINEAR, 2.0, + rects[1], "scale-y", CLUTTER_LINEAR, 2.0, + NULL); + + animator = clutter_animator_new (); + clutter_animator_set (animator, + rects[0], "depth", -1, 0.0, 0.0, + rects[0], "depth", CLUTTER_LINEAR, 1.0, 275.0, + rects[0], "x", -1, 0.0, 0.0, + rects[0], "x", CLUTTER_LINEAR, 0.5, 200.0, + rects[0], "x", CLUTTER_LINEAR, 1.0, 320.0, + + rects[0], "y", -1, 0.0, 0.0, + rects[0], "y", CLUTTER_LINEAR, 0.3, 100.0, + rects[0], "y", CLUTTER_LINEAR, 1.0, 240.0, + + rects[1], "opacity", -1, 0.0, 0x20, + rects[1], "opacity", CLUTTER_LINEAR, 1.0, 0xff, + rects[1], "scale-x", -1, 0.0, 1.0, + rects[1], "scale-x", CLUTTER_LINEAR, 0.5, 2.0, + rects[1], "scale-x", CLUTTER_LINEAR, 1.0, 2.0, + rects[1], "scale-y", -1, 0.0, 1.0, + rects[1], "scale-y", CLUTTER_LINEAR, 0.5, 2.0, + rects[1], "scale-y", CLUTTER_LINEAR, 1.0, 2.0, + NULL); + + clutter_animator_property_set_ease_in (animator, G_OBJECT (rects[0]), "depth", TRUE); + clutter_animator_property_set_ease_in (animator, G_OBJECT (rects[0]), "x", TRUE); + clutter_animator_property_set_ease_in (animator, G_OBJECT (rects[0]), "y", TRUE); + clutter_animator_property_set_ease_in (animator, G_OBJECT (rects[1]), "opacity", TRUE); + clutter_animator_property_set_ease_in (animator, G_OBJECT (rects[1]), "scale-x", TRUE); + clutter_animator_property_set_ease_in (animator, G_OBJECT (rects[1]), "scale-y", TRUE); + + clutter_animator_property_set_interpolation (animator, G_OBJECT (rects[0]), "x", + CLUTTER_INTERPOLATION_CUBIC); + clutter_animator_property_set_interpolation (animator, G_OBJECT (rects[0]), "y", + CLUTTER_INTERPOLATION_CUBIC); + + clutter_state_set_animator (state, "start", "end", animator); + g_object_unref (animator); + + clutter_actor_show (stage); + clutter_state_set_state (state, "start"); + + clutter_main (); + g_object_unref (state); + + return EXIT_SUCCESS; +} + +G_MODULE_EXPORT const char * +test_state_animator_describe (void) +{ + return "Animate using the State and Animator classes."; +} diff --git a/clutter/tests/interactive/test-state-script.c b/clutter/tests/interactive/test-state-script.c new file mode 100644 index 0000000..34b1b87 --- /dev/null +++ b/clutter/tests/interactive/test-state-script.c @@ -0,0 +1,53 @@ +#include + +#include + +#include + +#define TEST_STATE_SCRIPT_FILE "test-script-signals.json" + +gboolean +on_button_press (ClutterActor *actor, + ClutterEvent *event, + gpointer dummy G_GNUC_UNUSED) +{ + g_print ("Button pressed!\n"); + + return FALSE; +} + +G_MODULE_EXPORT int +test_state_script_main (int argc, char *argv[]) +{ + ClutterActor *stage, *button; + ClutterScript *script; + GError *error = NULL; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return EXIT_FAILURE; + + script = clutter_script_new (); + clutter_script_load_from_file (script, TEST_STATE_SCRIPT_FILE, &error); + if (error != NULL) + g_error ("Unable to load '%s': %s\n", + TEST_STATE_SCRIPT_FILE, + error->message); + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "State Script"); + clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + clutter_actor_show (stage); + + button = CLUTTER_ACTOR (clutter_script_get_object (script, "button")); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), button); + clutter_actor_add_constraint (button, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5)); + + clutter_script_connect_signals (script, NULL); + + clutter_main (); + + g_object_unref (script); + + return EXIT_SUCCESS; +} diff --git a/clutter/tests/interactive/test-state.c b/clutter/tests/interactive/test-state.c new file mode 100644 index 0000000..0634173 --- /dev/null +++ b/clutter/tests/interactive/test-state.c @@ -0,0 +1,206 @@ +#include +#include +#include +#include + +#define STAGE_WIDTH 1024 +#define STAGE_HEIGHT 768 + +#define ACTOR_WIDTH 128 +#define ACTOR_HEIGHT 128 + +#define COLS (STAGE_WIDTH/ACTOR_WIDTH) +#define ROWS (STAGE_HEIGHT/ACTOR_HEIGHT) +#define TOTAL (ROWS*COLS) + + +static gboolean press_event (ClutterActor *actor, + ClutterEvent *event, + gpointer user_data) +{ + ClutterState *state = CLUTTER_STATE (user_data); + clutter_state_set_state (state, "right"); + return TRUE; +} + +static gboolean release_event (ClutterActor *actor, + ClutterEvent *event, + gpointer user_data) +{ + ClutterState *state = CLUTTER_STATE (user_data); + clutter_state_set_state (state, "active"); + return TRUE; +} + +static gboolean enter_event (ClutterActor *actor, + ClutterEvent *event, + gpointer user_data) +{ + ClutterState *state = CLUTTER_STATE (user_data); + clutter_state_set_state (state, "hover"); + return TRUE; +} + +static gboolean leave_event (ClutterActor *actor, + ClutterEvent *event, + gpointer user_data) +{ + ClutterState *state = CLUTTER_STATE (user_data); + clutter_state_set_state (state, "normal"); + return TRUE; +} + +static void completed (ClutterState *state, + gpointer data) +{ + g_print ("Completed transitioning to state: %s\n", + clutter_state_get_state (state)); + + if (g_str_equal (clutter_state_get_state (state), "right")) + { + /* skip straight to left state when reaching right */ + clutter_state_warp_to_state (state, "left"); + } +} + +static ClutterActor *new_rect (gint r, + gint g, + gint b, + gint a) +{ + GError *error = NULL; + ClutterColor *color = clutter_color_new (r, g, b, a); + ClutterActor *group = clutter_actor_new (); + ClutterActor *rectangle = clutter_actor_new (); + ClutterActor *hand = NULL; + + gchar *file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL); + + hand = clutter_texture_new_from_file (file, &error); + if (rectangle == NULL) + g_error ("image load failed: %s", error->message); + g_free (file); + clutter_actor_set_size (hand, ACTOR_WIDTH,ACTOR_HEIGHT); + + clutter_actor_set_background_color (rectangle, color); + clutter_actor_set_size (rectangle, ACTOR_WIDTH,ACTOR_HEIGHT); + clutter_color_free (color); + + clutter_actor_add_child (group, rectangle); + clutter_actor_add_child (group, hand); + + return group; +} + +G_MODULE_EXPORT gint +test_state_main (gint argc, + gchar **argv) +{ + ClutterActor *stage; + ClutterState *layout_state; + gint i; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + layout_state = clutter_state_new (); + + stage = clutter_stage_new (); + clutter_actor_set_background_color (stage, CLUTTER_COLOR_Black); + clutter_stage_set_title (CLUTTER_STAGE (stage), "State Machine"); + clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + g_signal_connect (stage, "button-press-event", + G_CALLBACK (press_event), layout_state); + g_signal_connect (stage, "button-release-event", + G_CALLBACK (release_event), layout_state); + + for (i = 0; i < TOTAL; i++) + { + ClutterActor *actor; + ClutterState *a_state; + + int row = i/COLS; + int col = i%COLS; + + actor = new_rect (255 * (1.0 * col / COLS), 50, + 255 * (1.0 * row / ROWS), 255); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), actor); + clutter_actor_set_position (actor, 320.0, 240.0); + clutter_actor_set_reactive (actor, TRUE); + clutter_actor_add_effect_with_name (actor, "fade", + clutter_desaturate_effect_new (0.0)); + + + clutter_state_set (layout_state, NULL, "active", + actor, "delayed::x", CLUTTER_LINEAR, + ACTOR_WIDTH * 1.0 * ((TOTAL-1-i) % COLS), + ((row*1.0/ROWS))/2, (1.0-(row*1.0/ROWS))/2, + actor, "delayed::y", CLUTTER_LINEAR, + ACTOR_HEIGHT * 1.0 * ((TOTAL-1-i) / COLS), + ((row*1.0/ROWS))/2, 0.0, + actor, "rotation-angle-x", CLUTTER_LINEAR, 0.0, + actor, "rotation-angle-y", CLUTTER_LINEAR, 0.0, + NULL); + + clutter_state_set (layout_state, NULL, "right", + actor, "delayed::x", CLUTTER_LINEAR, STAGE_WIDTH * 1.0, + ((row*1.0/ROWS))/2, + (1.0-(row*1.0/ROWS))/2, + actor, "delayed::y", CLUTTER_LINEAR, STAGE_HEIGHT * 1.0, + ((row*1.0/ROWS))/2, + 0.0, + NULL); + + clutter_state_set (layout_state, NULL, "left", + actor, "rotation-angle-x", CLUTTER_LINEAR, 45.0, + actor, "rotation-angle-y", CLUTTER_LINEAR, 5.0, + actor, "x", CLUTTER_LINEAR, 0-64.0, + actor, "y", CLUTTER_LINEAR, 0-64.0, + NULL); + + a_state = clutter_state_new (); + g_object_set_data_full (G_OBJECT (actor), "hover-state-machine", + a_state, g_object_unref); + g_signal_connect (actor, "enter-event", + G_CALLBACK (enter_event), a_state); + g_signal_connect (actor, "leave-event", + G_CALLBACK (leave_event), a_state); + + clutter_state_set (a_state, NULL, "normal", + actor, "opacity", CLUTTER_LINEAR, 0x77, + actor, "rotation-angle-z", CLUTTER_LINEAR, 0.0, + actor, "@effects.fade.factor", CLUTTER_LINEAR, 0.0, + NULL); + clutter_state_set (a_state, NULL, "hover", + actor, "opacity", CLUTTER_LINEAR, 0xff, + actor, "rotation-angle-z", CLUTTER_LINEAR, 10.0, + actor, "@effects.fade.factor", CLUTTER_LINEAR, 1.0, + NULL); + clutter_actor_set_opacity (actor, 0x77); + + clutter_state_set_duration (a_state, NULL, NULL, 500); + } + + clutter_state_set_duration (layout_state, NULL, NULL, 1000); + clutter_state_set_duration (layout_state, "active", "left", 1400); + + g_signal_connect (layout_state, "completed", G_CALLBACK (completed), NULL); + + clutter_actor_show (stage); + + clutter_state_warp_to_state (layout_state, "left"); + clutter_state_set_state (layout_state, "active"); + + clutter_main (); + + g_object_unref (layout_state); + + return EXIT_SUCCESS; +} + +G_MODULE_EXPORT const char * +test_state_describe (void) +{ + return "Animating using the State class."; +} diff --git a/clutter/tests/interactive/test-swipe-action.c b/clutter/tests/interactive/test-swipe-action.c new file mode 100644 index 0000000..75b2e75 --- /dev/null +++ b/clutter/tests/interactive/test-swipe-action.c @@ -0,0 +1,194 @@ +#include +#include + +enum { + VERTICAL = 0, + HORIZONTAL = 1, + BOTH = 2 +}; + +static void +swept_cb (ClutterSwipeAction *action, + ClutterActor *actor, + ClutterSwipeDirection direction, + gpointer data_) +{ + guint axis = GPOINTER_TO_UINT (data_); + gchar *direction_str = g_strdup (""); + + if (axis == HORIZONTAL && + ((direction & CLUTTER_SWIPE_DIRECTION_UP) != 0 || + (direction & CLUTTER_SWIPE_DIRECTION_DOWN) != 0)) + { + g_print ("discarding non-horizontal swipe on '%s'\n", + clutter_actor_get_name (actor)); + return; + } + + if (axis == VERTICAL && + ((direction & CLUTTER_SWIPE_DIRECTION_LEFT) != 0 || + (direction & CLUTTER_SWIPE_DIRECTION_RIGHT) != 0)) + { + g_print ("discarding non-vertical swipe on '%s'\n", + clutter_actor_get_name (actor)); + return; + } + + if (direction & CLUTTER_SWIPE_DIRECTION_UP) + { + char *old_str = direction_str; + + direction_str = g_strconcat (direction_str, " up", NULL); + g_free (old_str); + } + + if (direction & CLUTTER_SWIPE_DIRECTION_DOWN) + { + char *old_str = direction_str; + + direction_str = g_strconcat (direction_str, " down", NULL); + g_free (old_str); + } + + if (direction & CLUTTER_SWIPE_DIRECTION_LEFT) + { + char *old_str = direction_str; + + direction_str = g_strconcat (direction_str, " left", NULL); + g_free (old_str); + } + + if (direction & CLUTTER_SWIPE_DIRECTION_RIGHT) + { + char *old_str = direction_str; + + direction_str = g_strconcat (direction_str, " right", NULL); + g_free (old_str); + } + + g_print ("swept: '%s': %s\n", clutter_actor_get_name (actor), direction_str); + + g_free (direction_str); +} + +static void +gesture_cancel_cb (ClutterSwipeAction *action, + ClutterActor *actor, + gpointer user_data) +{ + g_debug ("gesture cancelled: '%s'", clutter_actor_get_name (actor)); +} + +static void +attach_action (ClutterActor *actor, guint axis) +{ + ClutterAction *action; + + action = g_object_new (CLUTTER_TYPE_SWIPE_ACTION, NULL); + clutter_actor_add_action (actor, action); + g_signal_connect (action, "swept", G_CALLBACK (swept_cb), GUINT_TO_POINTER (axis)); + g_signal_connect (action, "gesture-cancel", G_CALLBACK (gesture_cancel_cb), NULL); +} + +G_MODULE_EXPORT int +test_swipe_action_main (int argc, char *argv[]) +{ + ClutterActor *stage, *rect; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Swipe action"); + clutter_actor_set_size (stage, 640, 480); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + rect = clutter_rectangle_new_with_color (CLUTTER_COLOR_Red); + clutter_actor_set_name (rect, "Vertical swipes"); + clutter_actor_set_size (rect, 150, 150); + clutter_actor_set_position (rect, 10, 100); + clutter_actor_set_reactive (rect, TRUE); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); + attach_action (rect, VERTICAL); + + rect = clutter_rectangle_new_with_color (CLUTTER_COLOR_Blue); + clutter_actor_set_name (rect, "Horizontal swipes"); + clutter_actor_set_size (rect, 150, 150); + clutter_actor_set_position (rect, 170, 100); + clutter_actor_set_reactive (rect, TRUE); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); + attach_action (rect, HORIZONTAL); + + rect = clutter_rectangle_new_with_color (CLUTTER_COLOR_Green); + clutter_actor_set_name (rect, "All swipes"); + clutter_actor_set_size (rect, 150, 150); + clutter_actor_set_position (rect, 330, 100); + clutter_actor_set_reactive (rect, TRUE); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); + attach_action (rect, BOTH); + + { + ClutterLayoutManager *layout = clutter_box_layout_new (); + ClutterActor *box, *label; + float offset; + + clutter_box_layout_set_vertical (CLUTTER_BOX_LAYOUT (layout), TRUE); + clutter_box_layout_set_spacing (CLUTTER_BOX_LAYOUT (layout), 6); + + box = clutter_box_new (layout); + + label = clutter_text_new (); + clutter_text_set_markup (CLUTTER_TEXT (label), + "Red: vertical swipes only"); + clutter_box_layout_pack (CLUTTER_BOX_LAYOUT (layout), + label, + TRUE, + TRUE, TRUE, + CLUTTER_BOX_ALIGNMENT_START, + CLUTTER_BOX_ALIGNMENT_CENTER); + + label = clutter_text_new (); + clutter_text_set_markup (CLUTTER_TEXT (label), + "Blue: horizontal swipes only"); + clutter_box_layout_pack (CLUTTER_BOX_LAYOUT (layout), + label, + TRUE, + TRUE, TRUE, + CLUTTER_BOX_ALIGNMENT_START, + CLUTTER_BOX_ALIGNMENT_CENTER); + + label = clutter_text_new (); + clutter_text_set_markup (CLUTTER_TEXT (label), + "Green: both"); + clutter_box_layout_pack (CLUTTER_BOX_LAYOUT (layout), + label, + TRUE, + TRUE, TRUE, + CLUTTER_BOX_ALIGNMENT_START, + CLUTTER_BOX_ALIGNMENT_CENTER); + + offset = clutter_actor_get_height (stage) + - clutter_actor_get_height (box) + - 12.0; + + clutter_container_add_actor (CLUTTER_CONTAINER (stage), box); + clutter_actor_add_constraint (box, clutter_bind_constraint_new (stage, + CLUTTER_BIND_X, + 12.0)); + clutter_actor_add_constraint (box, clutter_bind_constraint_new (stage, + CLUTTER_BIND_Y, + offset)); + } + + clutter_actor_show_all (stage); + + clutter_main (); + + return EXIT_SUCCESS; +} + +G_MODULE_EXPORT const char * +test_swipe_action_describe (void) +{ + return "Swipe gesture recognizer."; +} diff --git a/clutter/tests/interactive/test-table-layout.c b/clutter/tests/interactive/test-table-layout.c new file mode 100644 index 0000000..0e2d564 --- /dev/null +++ b/clutter/tests/interactive/test-table-layout.c @@ -0,0 +1,284 @@ +#include +#include + +#include + +#include +#include +#include + +#define FONT "Sans 12" + +static void +set_text (ClutterActor *actor, const gchar *text) +{ + GList *children, *l; + + children = clutter_container_get_children (CLUTTER_CONTAINER (actor)); + for (l = children; l; l = g_list_next (l)) { + if (CLUTTER_IS_TEXT (l->data)) { + clutter_text_set_text (CLUTTER_TEXT (l->data), text); + break; + } + } + g_list_free (children); +} + +static void +toggle_expand (ClutterActor *actor, ClutterEvent *event, ClutterBox *box) +{ + gboolean x_expand; + gchar *label; + ClutterLayoutManager *layout = clutter_box_get_layout_manager (box); + + + clutter_layout_manager_child_get (layout, CLUTTER_CONTAINER (box), actor, + "x-expand", &x_expand, + NULL); + + x_expand = !x_expand; + + clutter_layout_manager_child_set (layout, CLUTTER_CONTAINER (box), actor, + "x-expand", x_expand, + "y-expand", x_expand, + NULL); + + label = g_strdup_printf ("Expand = %d", x_expand); + set_text (actor, label); + + g_free (label); +} + +static const gchar * +get_alignment_name (ClutterTableAlignment alignment) +{ + switch (alignment) + { + case CLUTTER_TABLE_ALIGNMENT_START: + return "start"; + + case CLUTTER_TABLE_ALIGNMENT_CENTER: + return "center"; + + case CLUTTER_TABLE_ALIGNMENT_END: + return "end"; + } + + return "undefined"; +} + +static void +randomise_align (ClutterActor *actor, ClutterEvent *event, ClutterBox *box) +{ + ClutterTableAlignment x_align, y_align; + gchar *label; + ClutterLayoutManager *layout; + + layout = clutter_box_get_layout_manager (box); + + x_align = (ClutterTableAlignment) g_random_int_range (0, 3); + y_align = (ClutterTableAlignment) g_random_int_range (0, 3); + + clutter_layout_manager_child_set (layout, CLUTTER_CONTAINER (box), actor, + "x-align", x_align, + "y-align", y_align, + NULL); + + label = g_strdup_printf ("Align (%s, %s)", + get_alignment_name (x_align), + get_alignment_name (y_align)); + set_text (actor, label); + g_free (label); +} + +static void +toggle_visible (ClutterActor *actor, ClutterEvent *event, gpointer userdata) +{ + clutter_actor_hide (actor); +} + +gboolean drag = FALSE; + +static ClutterActor * +create_cell (ClutterActor *actor, const gchar *color_str) +{ + ClutterActor *result; + ClutterActor *rectangle; + ClutterColor color; + + result = + clutter_box_new (clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_FILL, + CLUTTER_BIN_ALIGNMENT_FILL)); + + rectangle = clutter_rectangle_new (); + clutter_color_from_string (&color, color_str); + clutter_rectangle_set_color (CLUTTER_RECTANGLE (rectangle), (const ClutterColor *) &color); + clutter_color_from_string (&color, "#000f"); + clutter_rectangle_set_border_color (CLUTTER_RECTANGLE (rectangle), (const ClutterColor *) &color); + clutter_rectangle_set_border_width (CLUTTER_RECTANGLE (rectangle), 2); + + clutter_actor_show (rectangle); + clutter_actor_set_reactive (result, TRUE); + clutter_container_add_actor (CLUTTER_CONTAINER (result), rectangle); + clutter_box_pack (CLUTTER_BOX (result), actor, + "x-align", CLUTTER_BIN_ALIGNMENT_CENTER, + "y-align", CLUTTER_BIN_ALIGNMENT_CENTER, + NULL); + + return result; +} + +static ClutterActor * +create_text (const gchar *label, const gchar *color) +{ + ClutterActor *text; + ClutterActor *result; + + text = clutter_text_new_with_text (FONT, label); + clutter_actor_show (text); + + result = create_cell (text, color); + clutter_actor_show (result); + + return result; +} + +static ClutterActor * +create_image (const gchar *file, const gchar *color) +{ + ClutterActor *texture; + ClutterActor *result; + + texture = clutter_texture_new_from_file (file, NULL); + g_object_set (G_OBJECT (texture), "keep-aspect-ratio", TRUE, NULL); + clutter_actor_show (texture); + + result = create_cell (texture, color); + clutter_actor_show (result); + + return result; +} + +G_MODULE_EXPORT int +test_table_layout_main (int argc, char *argv[]) +{ + ClutterActor *stage; + ClutterLayoutManager *layout; + ClutterActor *actor1, *actor2, *actor3, *actor4, *actor5, *actor6, *actor7, *actor8, *actor9, *actor10; + ClutterActor *box; + gchar *file; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Table Layout"); + clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); + clutter_actor_set_size (stage, 640, 480); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + layout = clutter_table_layout_new (); + clutter_table_layout_set_column_spacing (CLUTTER_TABLE_LAYOUT (layout), 10); + clutter_table_layout_set_row_spacing (CLUTTER_TABLE_LAYOUT (layout), 10); + clutter_table_layout_set_use_animations (CLUTTER_TABLE_LAYOUT (layout), TRUE); + + box = clutter_box_new (layout); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), box); + clutter_actor_add_constraint (box, clutter_bind_constraint_new (stage, CLUTTER_BIND_WIDTH, -10.0)); + clutter_actor_add_constraint (box, clutter_bind_constraint_new (stage, CLUTTER_BIND_HEIGHT, -10.0)); + + actor1 = create_text ("label 1", "#f66f"); + file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL); + actor2 = create_image (file, "#bbcf"); + g_free (file); + actor3 = create_text ("label 3", "#6f6f"); + actor4 = create_text ("Expand = 1", "#66ff"); + actor5 = create_text ("label 5", "#f6ff"); + actor6 = create_text ("label 6", "#6fff"); + actor7 = create_text ("Align (center, center)", "#66ff"); + actor8 = create_text ("label 8", "#ffff"); + actor9 = create_text ("label 9", "#666f"); + actor10 = create_text ("label 10", "#aaaf"); + + clutter_table_layout_pack (CLUTTER_TABLE_LAYOUT (layout), actor1, 0, 0); + clutter_table_layout_pack (CLUTTER_TABLE_LAYOUT (layout), actor2, 1, 0); + clutter_table_layout_pack (CLUTTER_TABLE_LAYOUT (layout), actor3, 1, 1); + clutter_table_layout_pack (CLUTTER_TABLE_LAYOUT (layout), actor4, 0, 2); + clutter_table_layout_pack (CLUTTER_TABLE_LAYOUT (layout), actor5, 0, 3); + clutter_table_layout_pack (CLUTTER_TABLE_LAYOUT (layout), actor6, 1, 3); + clutter_table_layout_pack (CLUTTER_TABLE_LAYOUT (layout), actor7, 1, 4); + clutter_table_layout_pack (CLUTTER_TABLE_LAYOUT (layout), actor8, 0, 4); + clutter_table_layout_pack (CLUTTER_TABLE_LAYOUT (layout), actor9, 0, 5); + clutter_table_layout_pack (CLUTTER_TABLE_LAYOUT (layout), actor10, 0, -1); + clutter_table_layout_set_span (CLUTTER_TABLE_LAYOUT (layout), actor1, 1, 2); + clutter_table_layout_set_span (CLUTTER_TABLE_LAYOUT (layout), actor7, 1, 2); + clutter_table_layout_set_span (CLUTTER_TABLE_LAYOUT (layout), actor4, 2, 1); + + clutter_actor_set_size (actor1, 100, 100); + clutter_actor_set_width (actor4, 250); + + clutter_layout_manager_child_set (CLUTTER_LAYOUT_MANAGER (layout), + CLUTTER_CONTAINER (box), + actor1, + "x-expand", FALSE, "y-expand", FALSE, + NULL); + clutter_layout_manager_child_set (CLUTTER_LAYOUT_MANAGER (layout), + CLUTTER_CONTAINER (box), + actor4, + "x-expand", TRUE, "y-expand", TRUE, + "x-fill", TRUE, "y-fill", TRUE, + NULL); + clutter_layout_manager_child_set (CLUTTER_LAYOUT_MANAGER (layout), + CLUTTER_CONTAINER (box), + actor7, + "x-expand", TRUE, "y-expand", TRUE, + "x-fill", FALSE, "y-fill", FALSE, + NULL); + clutter_layout_manager_child_set (CLUTTER_LAYOUT_MANAGER (layout), + CLUTTER_CONTAINER (box), + actor8, + "x-expand", FALSE, "y-expand", FALSE, + NULL); + clutter_layout_manager_child_set (CLUTTER_LAYOUT_MANAGER (layout), + CLUTTER_CONTAINER (box), + actor9, + "x-expand", FALSE, "y-expand", FALSE, + NULL); + + clutter_layout_manager_child_set (CLUTTER_LAYOUT_MANAGER (layout), + CLUTTER_CONTAINER (box), + actor2, + "y-fill", FALSE, + "x-fill", FALSE, + NULL); + + clutter_actor_set_position (box, 5, 5); + + g_signal_connect (actor4, "button-release-event", G_CALLBACK (toggle_expand), box); + g_signal_connect (actor7, "button-release-event", G_CALLBACK (randomise_align), box); + g_signal_connect (actor10, "button-release-event", G_CALLBACK (toggle_visible), NULL); + + /* g_signal_connect (stage, "button-press-event", G_CALLBACK (button_press), */ + /* box); */ + /* g_signal_connect (stage, "motion-event", G_CALLBACK (motion_event), */ + /* box); */ + /* g_signal_connect (stage, "button-release-event", G_CALLBACK (button_release), */ + /* box); */ + + clutter_actor_show (stage); + + g_debug ("table row count = %d", + clutter_table_layout_get_row_count (CLUTTER_TABLE_LAYOUT (layout))); + g_debug ("table column count = %d", + clutter_table_layout_get_column_count (CLUTTER_TABLE_LAYOUT (layout))); + + clutter_main (); + + return EXIT_SUCCESS; +} + +G_MODULE_EXPORT const char * +test_table_layout_describe (void) +{ + return "TableLayout layout manager example."; +} diff --git a/clutter/tests/interactive/test-text-field.c b/clutter/tests/interactive/test-text-field.c new file mode 100644 index 0000000..18cdfcb --- /dev/null +++ b/clutter/tests/interactive/test-text-field.c @@ -0,0 +1,331 @@ +#include +#include +#include + +static void +on_entry_activate (ClutterText *text, + gpointer data) +{ + g_print ("Text activated: %s (cursor: %d, selection at: %d)\n", + clutter_text_get_text (text), + clutter_text_get_cursor_position (text), + clutter_text_get_selection_bound (text)); +} + +#define is_hex_digit(c) (((c) >= '0' && (c) <= '9') || \ + ((c) >= 'a' && (c) <= 'f') || \ + ((c) >= 'A' && (c) <= 'F')) +#define to_hex_digit(c) (((c) <= '9') ? (c) - '0' : ((c) & 7) + 9) + +static gboolean +on_captured_event (ClutterText *text, + ClutterEvent *event, + gpointer dummy G_GNUC_UNUSED) +{ + gboolean is_unicode_mode = FALSE; + gunichar c; + guint keyval; + + if (event->type != CLUTTER_KEY_PRESS) + return FALSE; + + is_unicode_mode = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (text), + "unicode-mode")); + + c = clutter_event_get_key_unicode (event); + keyval = clutter_event_get_key_symbol (event); + if (keyval == CLUTTER_KEY_U) + { + if (is_unicode_mode) + { + GString *str = g_object_get_data (G_OBJECT (text), "unicode-str"); + + clutter_text_set_preedit_string (text, NULL, NULL, 0); + + g_object_set_data (G_OBJECT (text), "unicode-mode", + GINT_TO_POINTER (FALSE)); + g_object_set_data (G_OBJECT (text), "unicode-str", + NULL); + + g_string_free (str, TRUE); + + return FALSE; + } + + if (clutter_event_has_control_modifier (event)) + { + PangoAttrList *attrs; + PangoAttribute *a; + GString *str = g_string_sized_new (5); + + g_string_append (str, "u"); + + g_object_set_data (G_OBJECT (text), + "unicode-mode", + GINT_TO_POINTER (TRUE)); + g_object_set_data (G_OBJECT (text), + "unicode-str", + str); + + attrs = pango_attr_list_new (); + + a = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); + a->start_index = 0; + a->end_index = str->len; + pango_attr_list_insert (attrs, a); + + clutter_text_set_preedit_string (text, str->str, attrs, str->len); + + pango_attr_list_unref (attrs); + + return TRUE; + } + + return FALSE; + } + else if (is_unicode_mode && is_hex_digit (c)) + { + GString *str = g_object_get_data (G_OBJECT (text), "unicode-str"); + PangoAttrList *attrs; + PangoAttribute *a; + gchar buf[8]; + gsize len; + + len = g_unichar_to_utf8 (c, buf); + buf[len] = '\0'; + + g_string_append (str, buf); + + g_print ("added '%s' to '%s' (len:%d)\n", + buf, + str->str, + (int) str->len); + + attrs = pango_attr_list_new (); + + a = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); + a->start_index = 0; + a->end_index = str->len; + pango_attr_list_insert (attrs, a); + + clutter_text_set_preedit_string (text, str->str, attrs, str->len); + + pango_attr_list_unref (attrs); + + return TRUE; + } + else if (is_unicode_mode && (keyval == CLUTTER_KEY_BackSpace)) + { + GString *str = g_object_get_data (G_OBJECT (text), "unicode-str"); + PangoAttrList *attrs; + PangoAttribute *a; + + g_string_truncate (str, str->len - 1); + + attrs = pango_attr_list_new (); + + a = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); + a->start_index = 0; + a->end_index = str->len; + pango_attr_list_insert (attrs, a); + + clutter_text_set_preedit_string (text, str->str, attrs, str->len); + + pango_attr_list_unref (attrs); + + return TRUE; + } + else if (is_unicode_mode && + (keyval == CLUTTER_KEY_Return || + keyval == CLUTTER_KEY_KP_Enter || + keyval == CLUTTER_KEY_ISO_Enter || + keyval == CLUTTER_KEY_KP_Space)) + { + GString *str = g_object_get_data (G_OBJECT (text), "unicode-str"); + const gchar *contents = clutter_text_get_text (text); + gunichar uchar = 0; + gchar ch; + gint i; + + clutter_text_set_preedit_string (text, NULL, NULL, 0); + + g_object_set_data (G_OBJECT (text), "unicode-mode", + GINT_TO_POINTER (FALSE)); + g_object_set_data (G_OBJECT (text), "unicode-str", + NULL); + + for (i = 0; i < str->len; i++) + { + ch = str->str[i]; + + if (is_hex_digit (ch)) + uchar += ((gunichar) to_hex_digit (ch) << ((4 - i) * 4)); + } + + g_assert (g_unichar_validate (uchar)); + + g_string_overwrite (str, 0, contents); + g_string_insert_unichar (str, + clutter_text_get_cursor_position (text), + uchar); + + i = clutter_text_get_cursor_position (text); + clutter_text_set_text (text, str->str); + + if (i >= 0) + i += 1; + else + i = -1; + + clutter_text_set_cursor_position (text, i); + clutter_text_set_selection_bound (text, i); + + g_string_free (str, TRUE); + + return TRUE; + } + else + return FALSE; +} + +static ClutterActor * +create_label (const ClutterColor *color, + const gchar *text) +{ + ClutterActor *retval = clutter_text_new (); + + clutter_text_set_color (CLUTTER_TEXT (retval), color); + clutter_text_set_markup (CLUTTER_TEXT (retval), text); + clutter_text_set_editable (CLUTTER_TEXT (retval), FALSE); + clutter_text_set_selectable (CLUTTER_TEXT (retval), FALSE); + clutter_text_set_single_line_mode (CLUTTER_TEXT (retval), TRUE); + clutter_text_set_ellipsize (CLUTTER_TEXT (retval), PANGO_ELLIPSIZE_END); + + return retval; +} + +static ClutterActor * +create_entry (const ClutterColor *color, + const gchar *text, + PangoAttrList *attrs, + gunichar password_char, + gint max_length) +{ + ClutterActor *retval = clutter_text_new_full (NULL, text, color); + ClutterColor selection = { 0, }; + ClutterColor selected_text = { 0x00, 0x00, 0xff, 0xff }; + + clutter_actor_set_reactive (retval, TRUE); + + clutter_color_darken (color, &selection); + + clutter_text_set_editable (CLUTTER_TEXT (retval), TRUE); + clutter_text_set_selectable (CLUTTER_TEXT (retval), TRUE); + clutter_text_set_activatable (CLUTTER_TEXT (retval), TRUE); + clutter_text_set_single_line_mode (CLUTTER_TEXT (retval), TRUE); + clutter_text_set_password_char (CLUTTER_TEXT (retval), password_char); + clutter_text_set_cursor_color (CLUTTER_TEXT (retval), &selection); + clutter_text_set_max_length (CLUTTER_TEXT (retval), max_length); + clutter_text_set_selected_text_color (CLUTTER_TEXT (retval), &selected_text); + clutter_actor_set_background_color (retval, CLUTTER_COLOR_LightGray); + if (attrs) + clutter_text_set_attributes (CLUTTER_TEXT (retval), attrs); + + g_signal_connect (retval, "activate", + G_CALLBACK (on_entry_activate), + NULL); + g_signal_connect (retval, "captured-event", + G_CALLBACK (on_captured_event), + NULL); + + return retval; +} + +G_MODULE_EXPORT gint +test_text_field_main (gint argc, + gchar **argv) +{ + ClutterActor *stage; + ClutterActor *box, *label, *entry; + ClutterLayoutManager *table; + PangoAttrList *entry_attrs; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return EXIT_FAILURE; + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Text Fields"); + clutter_actor_set_background_color (stage, CLUTTER_COLOR_Black); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + table = clutter_table_layout_new (); + clutter_table_layout_set_column_spacing (CLUTTER_TABLE_LAYOUT (table), 6); + clutter_table_layout_set_row_spacing (CLUTTER_TABLE_LAYOUT (table), 6); + + box = clutter_actor_new (); + clutter_actor_set_layout_manager (box, table); + clutter_actor_add_constraint (box, clutter_bind_constraint_new (stage, CLUTTER_BIND_WIDTH, -24.0)); + clutter_actor_add_constraint (box, clutter_bind_constraint_new (stage, CLUTTER_BIND_HEIGHT, -24.0)); + clutter_actor_set_position (box, 12, 12); + clutter_actor_add_child (stage, box); + + label = create_label (CLUTTER_COLOR_White, "Input field:"); + g_object_set (label, "min-width", 150.0, NULL); + clutter_actor_add_child (box, label); + clutter_layout_manager_child_set (table, CLUTTER_CONTAINER (box), label, + "row", 0, + "column", 0, + "x-expand", FALSE, + "y-expand", FALSE, + NULL); + + entry_attrs = pango_attr_list_new (); + pango_attr_list_insert (entry_attrs, pango_attr_underline_new (PANGO_UNDERLINE_ERROR)); + pango_attr_list_insert (entry_attrs, pango_attr_underline_color_new (65535, 0, 0)); + entry = create_entry (CLUTTER_COLOR_Black, "somme misspeeled textt", entry_attrs, 0, 0); + clutter_actor_add_child (box, entry); + clutter_layout_manager_child_set (table, CLUTTER_CONTAINER (box), entry, + "row", 0, + "column", 1, + "x-expand", TRUE, + "x-fill", TRUE, + "y-expand", FALSE, + NULL); + clutter_actor_grab_key_focus (entry); + + label = create_label (CLUTTER_COLOR_White, "A very long password field:"); + clutter_actor_add_child (box, label); + clutter_layout_manager_child_set (table, CLUTTER_CONTAINER (box), label, + "row", 1, + "column", 0, + "x-expand", FALSE, + "y-expand", FALSE, + NULL); + + entry = create_entry (CLUTTER_COLOR_Black, "password", NULL, '*', 8); + clutter_actor_add_child (box, entry); + clutter_layout_manager_child_set (table, CLUTTER_CONTAINER (box), entry, + "row", 1, + "column", 1, + "x-expand", TRUE, + "x-fill", TRUE, + "y-expand", FALSE, + NULL); + + clutter_actor_show (stage); + + clutter_main (); + + return EXIT_SUCCESS; +} + +G_MODULE_EXPORT const char * +test_text_field_describe (void) +{ + return +"Text actor single-line and password mode support\n" +"\n" +"This test checks the :single-line-mode and :password-char properties of\n" +"the ClutterText actor, plus the password hint feature and the :max-length\n" +"property."; +} diff --git a/clutter/tests/interactive/test-text.c b/clutter/tests/interactive/test-text.c new file mode 100644 index 0000000..37e45a7 --- /dev/null +++ b/clutter/tests/interactive/test-text.c @@ -0,0 +1,94 @@ +#include + +#include +#include + +#define FONT "Mono Bold 24px" + +static const gchar *runes = +"ᚠᛇᚻ᛫ᛒᛦᚦ᛫ᚠᚱᚩᚠᚢᚱ᛫ᚠᛁᚱᚪ᛫ᚷᛖᚻᚹᛦᛚᚳᚢᛗ\n" +"ᛋᚳᛖᚪᛚ᛫ᚦᛖᚪᚻ᛫ᛗᚪᚾᚾᚪ᛫ᚷᛖᚻᚹᛦᛚᚳ᛫ᛗᛁᚳᛚᚢᚾ᛫ᚻᛦᛏ᛫ᛞᚫᛚᚪᚾ\n" +"ᚷᛁᚠ᛫ᚻᛖ᛫ᚹᛁᛚᛖ᛫ᚠᚩᚱ᛫ᛞᚱᛁᚻᛏᚾᛖ᛫ᛞᚩᛗᛖᛋ᛫ᚻᛚᛇᛏᚪᚾ᛬\n"; + +G_MODULE_EXPORT gint +test_text_main (gint argc, + gchar **argv) +{ + ClutterActor *stage; + ClutterActor *text, *text2; + ClutterColor text_color = { 0x33, 0xff, 0x33, 0xff }; + ClutterColor cursor_color = { 0xff, 0x33, 0x33, 0xff }; + ClutterTextBuffer *buffer; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Text Editing"); + clutter_actor_set_background_color (stage, CLUTTER_COLOR_Black); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + buffer = clutter_text_buffer_new_with_text ("·", -1); + + text = clutter_text_new_with_buffer (buffer); + clutter_text_set_font_name (CLUTTER_TEXT (text), FONT); + clutter_text_set_color (CLUTTER_TEXT (text), &text_color); + + clutter_container_add (CLUTTER_CONTAINER (stage), text, NULL); + clutter_actor_set_position (text, 40, 30); + clutter_actor_set_width (text, 1024); + clutter_text_set_line_wrap (CLUTTER_TEXT (text), TRUE); + + clutter_actor_set_reactive (text, TRUE); + clutter_stage_set_key_focus (CLUTTER_STAGE (stage), text); + + clutter_text_set_editable (CLUTTER_TEXT (text), TRUE); + clutter_text_set_selectable (CLUTTER_TEXT (text), TRUE); + clutter_text_set_cursor_color (CLUTTER_TEXT (text), &cursor_color); + clutter_text_set_selected_text_color (CLUTTER_TEXT (text), CLUTTER_COLOR_Blue); + + text2 = clutter_text_new_with_buffer (buffer); + clutter_text_set_color (CLUTTER_TEXT (text2), &text_color); + clutter_container_add (CLUTTER_CONTAINER (stage), text2, NULL); + clutter_actor_set_position (text2, 40, 300); + clutter_actor_set_width (text2, 1024); + clutter_text_set_line_wrap (CLUTTER_TEXT (text2), TRUE); + + clutter_actor_set_reactive (text2, TRUE); + clutter_text_set_editable (CLUTTER_TEXT (text2), TRUE); + clutter_text_set_selectable (CLUTTER_TEXT (text2), TRUE); + clutter_text_set_cursor_color (CLUTTER_TEXT (text2), &cursor_color); + clutter_text_set_selected_text_color (CLUTTER_TEXT (text2), CLUTTER_COLOR_Green); + + if (argv[1]) + { + GError *error = NULL; + gchar *utf8; + + g_file_get_contents (argv[1], &utf8, NULL, &error); + if (error) + { + utf8 = g_strconcat ("Unable to open '", argv[1], "':\n", + error->message, + NULL); + g_error_free (error); + } + + clutter_text_set_text (CLUTTER_TEXT (text), utf8); + } + else + clutter_text_set_text (CLUTTER_TEXT (text), runes); + + clutter_actor_set_size (stage, 1024, 768); + clutter_actor_show (stage); + + clutter_main (); + + return EXIT_SUCCESS; +} + +G_MODULE_EXPORT const char * +test_text_describe (void) +{ + return "Multi-line text editing."; +} diff --git a/clutter/tests/interactive/test-texture-async.c b/clutter/tests/interactive/test-texture-async.c new file mode 100644 index 0000000..0437703 --- /dev/null +++ b/clutter/tests/interactive/test-texture-async.c @@ -0,0 +1,156 @@ +#include +#include +#include + +enum +{ + LOAD_SYNC, + LOAD_DATA_ASYNC, + LOAD_ASYNC +}; + +static ClutterActor *stage = NULL; + +static void +on_load_finished (ClutterTexture *texture, + const GError *error, + gpointer user_data) +{ + gint load_type = GPOINTER_TO_INT (user_data); + const gchar *load_str = NULL; + + switch (load_type) + { + case LOAD_SYNC: + load_str = "synchronous loading"; + break; + + case LOAD_DATA_ASYNC: + load_str = "asynchronous data loading"; + break; + + case LOAD_ASYNC: + load_str = "asynchronous loading"; + break; + } + + if (error != NULL) + g_print ("%s failed: %s\n", load_str, error->message); + else + g_print ("%s successful\n", load_str); +} + +static void +size_change_cb (ClutterTexture *texture, + gint width, + gint height, + gpointer user_data) +{ + clutter_actor_set_size (user_data, width, height); +} + +static +gboolean task (gpointer user_data) +{ + const gchar *path = user_data; + ClutterActor *image[3]; + ClutterActor *clone[3]; + gint i; + + image[0] = g_object_new (CLUTTER_TYPE_TEXTURE, NULL); + g_signal_connect (image[0], "load-finished", + G_CALLBACK (on_load_finished), + GINT_TO_POINTER (LOAD_SYNC)); + + image[1] = g_object_new (CLUTTER_TYPE_TEXTURE, + "load-data-async", TRUE, + NULL); + g_signal_connect (image[1], "load-finished", + G_CALLBACK (on_load_finished), + GINT_TO_POINTER (LOAD_DATA_ASYNC)); + image[2] = g_object_new (CLUTTER_TYPE_TEXTURE, + "load-async", TRUE, + NULL); + g_signal_connect (image[2], "load-finished", + G_CALLBACK (on_load_finished), + GINT_TO_POINTER (LOAD_ASYNC)); + + for (i = 0; i < 3; i++) + { + GError *error = NULL; + + clutter_texture_set_from_file (CLUTTER_TEXTURE (image[i]), path, &error); + if (error != NULL) + g_error ("Unable to load image at '%s': %s", + path != NULL ? path : "", + error->message); + } + + for (i = 0; i < 3; i++) + clutter_container_add_actor (CLUTTER_CONTAINER (stage), image[i]); + + for (i = 0; i < 3; i++) + { + clutter_actor_set_position (image[i], 50 + i * 100, 0 + i * 50); + clutter_actor_set_depth (image[i], -2500); + + clone[i] = clutter_clone_new (image[i]); + g_signal_connect (image[i], "size-change", + G_CALLBACK (size_change_cb), clone[i]); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), clone[i]); + clutter_actor_set_position (clone[i], 50 + i * 100, 150 + i * 50 + 100); + } + + for (i = 0; i < 3; i++) + { + clutter_actor_save_easing_state (image[i]); + clutter_actor_set_easing_duration (image[i], 5000); + clutter_actor_set_depth (image[i], 0); + clutter_actor_restore_easing_state (image[i]); + } + + return FALSE; +} + +static void +cleanup_task (gpointer data) +{ +} + +G_MODULE_EXPORT gint +test_texture_async_main (int argc, char *argv[]) +{ + gchar *path; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Asynchronous Texture Loading"); + clutter_actor_set_background_color (stage, CLUTTER_COLOR_LightSkyBlue); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + clutter_actor_show (stage); + + path = (argc > 1) + ? g_strdup (argv[1]) + : g_build_filename (TESTS_DATADIR, "redhand.png", NULL); + + clutter_threads_add_timeout_full (G_PRIORITY_DEFAULT, 500, + task, path, + cleanup_task); + + clutter_threads_enter (); + clutter_main (); + clutter_threads_leave (); + + g_free (path); + + return EXIT_SUCCESS; +} + +G_MODULE_EXPORT const char * +test_texture_async_describe (void) +{ + return "Texture asynchronous loading using threads"; +} diff --git a/clutter/tests/interactive/test-texture-material.c b/clutter/tests/interactive/test-texture-material.c new file mode 100644 index 0000000..4886ce0 --- /dev/null +++ b/clutter/tests/interactive/test-texture-material.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include + +G_MODULE_EXPORT int +test_texture_material_main (int argc, char *argv[]) +{ + ClutterActor *stage, *box; + ClutterLayoutManager *manager; + int i; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Texture Material"); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + manager = clutter_flow_layout_new (CLUTTER_FLOW_HORIZONTAL); + box = clutter_box_new (manager); + clutter_actor_add_constraint (box, clutter_bind_constraint_new (stage, CLUTTER_BIND_WIDTH, -25.0)); + clutter_actor_add_constraint (box, clutter_bind_constraint_new (stage, CLUTTER_BIND_HEIGHT, -25.0)); + clutter_actor_set_position (box, 25.0, 25.0); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), box); + + for (i = 0; i < 48; i++) + { + ClutterActor *texture = clutter_texture_new (); + + clutter_texture_set_load_data_async (CLUTTER_TEXTURE (texture), TRUE); + clutter_texture_set_keep_aspect_ratio (CLUTTER_TEXTURE (texture), TRUE); + clutter_texture_set_from_file (CLUTTER_TEXTURE (texture), + TESTS_DATADIR "/redhand.png", + NULL); + clutter_actor_set_width (texture, 96); + + clutter_container_add_actor (CLUTTER_CONTAINER (box), texture); + } + + clutter_actor_show (stage); + + clutter_main (); + + return EXIT_SUCCESS; +} diff --git a/clutter/tests/interactive/test-texture-quality.c b/clutter/tests/interactive/test-texture-quality.c new file mode 100644 index 0000000..8cb916a --- /dev/null +++ b/clutter/tests/interactive/test-texture-quality.c @@ -0,0 +1,116 @@ +#include +#include +#include + +/* each time the timeline animating the label completes, swap the direction */ +static void +timeline_completed (ClutterTimeline *timeline, + gpointer user_data) +{ + clutter_timeline_set_direction (timeline, + !clutter_timeline_get_direction (timeline)); + clutter_timeline_start (timeline); +} + +static gboolean +change_filter (gpointer actor) +{ + ClutterTextureQuality old_quality; + + old_quality = clutter_texture_get_filter_quality (actor); + switch (old_quality) + { + case CLUTTER_TEXTURE_QUALITY_LOW: + clutter_texture_set_filter_quality (actor, + CLUTTER_TEXTURE_QUALITY_MEDIUM); + g_print ("Setting texture rendering quality to medium\n"); + break; + case CLUTTER_TEXTURE_QUALITY_MEDIUM: + clutter_texture_set_filter_quality (actor, + CLUTTER_TEXTURE_QUALITY_HIGH); + g_print ("Setting texture rendering quality to high\n"); + break; + case CLUTTER_TEXTURE_QUALITY_HIGH: + clutter_texture_set_filter_quality (actor, + CLUTTER_TEXTURE_QUALITY_LOW); + g_print ("Setting texture rendering quality to low\n"); + break; + } + return TRUE; +} + +G_MODULE_EXPORT gint +test_texture_quality_main (int argc, char *argv[]) +{ + ClutterTimeline *timeline; + ClutterAlpha *alpha; + ClutterBehaviour *depth_behavior; + ClutterActor *stage; + ClutterActor *image; + ClutterColor stage_color = { 0x12, 0x34, 0x56, 0xff }; + ClutterFog stage_fog = { 10.0, -50.0 }; + GError *error; + gchar *file; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + clutter_actor_set_background_color (stage, &stage_color); + clutter_stage_set_use_fog (CLUTTER_STAGE (stage), TRUE); + clutter_stage_set_fog (CLUTTER_STAGE (stage), &stage_fog); + g_signal_connect (stage, + "destroy", G_CALLBACK (clutter_main_quit), + NULL); + g_signal_connect (stage, + "button-press-event", G_CALLBACK (clutter_main_quit), + NULL); + + if (argc < 2) + g_print ("Hint: the redhand.png isn't a good test image for this test.\n" + "This test can take any image file as an argument\n"); + + file = (argc > 1) + ? g_strdup (argv[1]) + : g_build_filename (TESTS_DATADIR, "redhand.png", NULL); + + error = NULL; + image = clutter_texture_new_from_file (file, &error); + if (error) + g_error ("Unable to load image: %s", error->message); + + g_free (file); + + /* center the image */ + clutter_actor_set_position (image, + (clutter_actor_get_width (stage) - clutter_actor_get_width (image))/2, + (clutter_actor_get_height (stage) - clutter_actor_get_height (image))/2); + clutter_container_add (CLUTTER_CONTAINER (stage), image, NULL); + + timeline = clutter_timeline_new (5000); + g_signal_connect (timeline, + "completed", G_CALLBACK (timeline_completed), + NULL); + + alpha = clutter_alpha_new_full (timeline, CLUTTER_LINEAR); + depth_behavior = clutter_behaviour_depth_new (alpha, -2500, 400); + clutter_behaviour_apply (depth_behavior, image); + + clutter_actor_show (stage); + clutter_timeline_start (timeline); + + clutter_threads_add_timeout (10000, change_filter, image); + + clutter_main (); + + g_object_unref (depth_behavior); + g_object_unref (timeline); + + return EXIT_SUCCESS; +} + +G_MODULE_EXPORT const char * +test_texture_quality_describe (void) +{ + return "Change the texture filtering quality."; +} diff --git a/clutter/tests/interactive/test-texture-slicing.c b/clutter/tests/interactive/test-texture-slicing.c new file mode 100644 index 0000000..94c6b41 --- /dev/null +++ b/clutter/tests/interactive/test-texture-slicing.c @@ -0,0 +1,125 @@ +#include +#include + +#include + +guchar* +make_rgba_data (int width, int height, int bpp, int has_alpha, int *rowstride_p) +{ +#define CHECK_SIZE 20 + + gint x,y, rowstride, i = 0; + guchar *pixels; + + g_assert(bpp == 4); + g_assert(has_alpha == TRUE); + + rowstride = width * bpp; + *rowstride_p = rowstride; + + pixels = g_try_malloc (height * rowstride); + if (!pixels) + return NULL; + + for (y = 0; y < height; y++) + { + i = 0; + for (x = 0; x < width; x++) + { + guchar *p; + + p = pixels + y * rowstride + x * bpp; + + p[0] = p[1] = p[2] = 0; p[3] = 0xff; + + if (x && y && y % CHECK_SIZE && x % CHECK_SIZE) + { + if (x % CHECK_SIZE == 1) + { + if (++i > 3) + i = 0; + } + p[i] = 0xff; + } + } + } + + return pixels; +} + +static void +exit_on_destroy (ClutterActor *actor) +{ + exit(EXIT_SUCCESS); +} + +#define SPIN() while (g_main_context_pending (NULL)) \ + g_main_context_iteration (NULL, FALSE); + +G_MODULE_EXPORT int +test_textures_main (int argc, char *argv[]) +{ + ClutterActor *texture; + ClutterActor *stage; + gint i, j; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + clutter_actor_show_all (CLUTTER_ACTOR (stage)); + g_signal_connect (stage, "destroy", G_CALLBACK (exit_on_destroy), NULL); + + SPIN(); + + for (i=100; i<=5000; i += 100) + for (j=0; j<4; j++) + { + const int width = i+j; + const int height = i+j; + const gboolean has_alpha = TRUE; + const int bpp = has_alpha ? 4 : 3; + int rowstride; + guchar *pixels; + + pixels = make_rgba_data (width, height, bpp, has_alpha, &rowstride); + if (!pixels) + g_error("No memory for %ix%i RGBA data failed", width, height); + + printf("o %ix%i texture... ", width, height); + + texture = clutter_texture_new (); + if (!clutter_texture_set_from_rgb_data (CLUTTER_TEXTURE (texture), + pixels, + has_alpha, + width, + height, + rowstride, + bpp, + 0, NULL)) + g_error("texture creation failed"); + g_free(pixels); + + printf("uploaded to texture...\n"); + + clutter_container_add (CLUTTER_CONTAINER (stage), texture, NULL); + clutter_actor_set_size (texture, 400, 400); + clutter_actor_show (texture); + + /* Hide & show to unreaise then realise the texture */ + clutter_actor_hide (texture); + clutter_actor_show (texture); + + SPIN(); + + clutter_container_remove (CLUTTER_CONTAINER (stage), texture, NULL); + } + + return EXIT_SUCCESS; +} + +G_MODULE_EXPORT const char * +test_texture_slicing_describe (void) +{ + return "Check texture slicing support in CoglTexture"; +} diff --git a/clutter/tests/interactive/test-touch-events.c b/clutter/tests/interactive/test-touch-events.c new file mode 100644 index 0000000..184924a --- /dev/null +++ b/clutter/tests/interactive/test-touch-events.c @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2012 Collabora Ltd. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * Boston, MA 02111-1307, USA. + * + */ +#include +#include +#include +#include +#include + +#define STAGE_WIDTH 800 +#define STAGE_HEIGHT 550 +#define NUM_COLORS 10 +#define NUM_ACTORS 10 + +static GQueue events = G_QUEUE_INIT; +static GQueue all_events = G_QUEUE_INIT; +static gboolean new_surface = TRUE; + +static const ClutterColor const static_colors[] = { + { 0xff, 0x00, 0x00, 0xff }, /* red */ + { 0x80, 0x00, 0x00, 0xff }, /* dark red */ + { 0x00, 0xff, 0x00, 0xff }, /* green */ + { 0x00, 0x80, 0x00, 0xff }, /* dark green */ + { 0x00, 0x00, 0xff, 0xff }, /* blue */ + { 0x00, 0x00, 0x80, 0xff }, /* dark blue */ + { 0x00, 0xff, 0xff, 0xff }, /* cyan */ + { 0x00, 0x80, 0x80, 0xff }, /* dark cyan */ + { 0xff, 0x00, 0xff, 0xff }, /* magenta */ + { 0xff, 0xff, 0x00, 0xff }, /* yellow */ +}; +static GHashTable *sequence_to_color = NULL; + +static void +canvas_paint (ClutterCairoTexture *canvas) +{ + clutter_cairo_texture_invalidate (canvas); +} + +static void +draw_touch (ClutterEvent *event, + cairo_t *cr) +{ + ClutterEventSequence *sequence = clutter_event_get_event_sequence (event); + const ClutterColor *color; + + color = g_hash_table_lookup (sequence_to_color, sequence); + if (color == NULL) + { + color = &static_colors[g_random_int_range (0, NUM_COLORS)]; + g_hash_table_insert (sequence_to_color, (gpointer) sequence, (gpointer) color); + } + + cairo_set_source_rgba (cr, color->red / 255, + color->green / 255, + color->blue / 255, + color->alpha / 255); + cairo_arc (cr, event->touch.x, event->touch.y, 5, 0, 2 * G_PI); + cairo_fill (cr); +} + +static gboolean +draw_touches (ClutterCairoTexture *canvas, + cairo_t *cr) +{ + g_queue_foreach (new_surface ? &all_events : &events, (GFunc) draw_touch, cr); + g_queue_clear (&events); + + new_surface = FALSE; + + return TRUE; +} + +static cairo_surface_t * +create_surface (ClutterCairoTexture *texture, + guint width, + guint height, + gpointer user_data) +{ + new_surface = TRUE; + + return NULL; +} + +static gboolean +event_cb (ClutterActor *actor, ClutterEvent *event, ClutterActor *canvas) +{ + ClutterEvent *copy; + + if (event->type != CLUTTER_TOUCH_UPDATE) + return FALSE; + + copy = clutter_event_copy (event); + g_queue_push_tail (&events, copy); + g_queue_push_tail (&all_events, copy); + clutter_actor_queue_redraw (canvas); + + return TRUE; +} + +static gboolean +rect_event_cb (ClutterActor *actor, ClutterEvent *event, gpointer data) +{ + ClutterColor color; + + if (event->type != CLUTTER_TOUCH_BEGIN) + return FALSE; + + color = static_colors[g_random_int_range (0, NUM_COLORS)]; + clutter_rectangle_set_color (CLUTTER_RECTANGLE (actor), &color); + + return TRUE; +} + +G_MODULE_EXPORT int +test_touch_events_main (int argc, char *argv[]) +{ + ClutterActor *stage, *canvas; + int i; + + /* initialize Clutter */ + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return EXIT_FAILURE; + + /* create a resizable stage */ + stage = clutter_stage_new (); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Touch events"); + clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); + clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT); + clutter_actor_set_reactive (stage, TRUE); + clutter_actor_show (stage); + + /* our 2D canvas, courtesy of Cairo */ + canvas = clutter_cairo_texture_new (1, 1); + g_signal_connect (canvas, "paint", G_CALLBACK (canvas_paint), NULL); + g_signal_connect (canvas, "draw", G_CALLBACK (draw_touches), NULL); + g_signal_connect (canvas, "create-surface", G_CALLBACK (create_surface), NULL); + clutter_cairo_texture_set_auto_resize (CLUTTER_CAIRO_TEXTURE (canvas), TRUE); + clutter_actor_add_constraint (canvas, + clutter_bind_constraint_new (stage, + CLUTTER_BIND_SIZE, + 0)); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), canvas); + + g_signal_connect (stage, "event", G_CALLBACK (event_cb), canvas); + + for (i = 0; i < NUM_ACTORS; i++) + { + gfloat size = STAGE_HEIGHT / NUM_ACTORS; + ClutterColor color = static_colors[i % NUM_COLORS]; + ClutterActor *rectangle = clutter_rectangle_new_with_color (&color); + + /* Test that event delivery to actors work */ + g_signal_connect (rectangle, "event", G_CALLBACK (rect_event_cb), NULL); + + clutter_container_add_actor (CLUTTER_CONTAINER (stage), rectangle); + clutter_actor_set_size (rectangle, size, size); + clutter_actor_set_position (rectangle, 0, i * size); + clutter_actor_set_reactive (rectangle, TRUE); + } + + sequence_to_color = g_hash_table_new (NULL, NULL); + + clutter_main (); + + g_queue_foreach (&all_events, (GFunc) clutter_event_free, NULL); + g_queue_clear (&events); + g_queue_clear (&all_events); + g_hash_table_destroy (sequence_to_color); + + return EXIT_SUCCESS; +} + +G_MODULE_EXPORT const char * +test_touch_events_describe (void) +{ + return "Draw shapes based on touch events"; +} diff --git a/clutter/tests/interactive/wrapper.sh.in b/clutter/tests/interactive/wrapper.sh.in new file mode 100755 index 0000000..90aa4e1 --- /dev/null +++ b/clutter/tests/interactive/wrapper.sh.in @@ -0,0 +1,15 @@ +#!/bin/sh + +UNIT_TEST=$1 + +shift + +echo "Running ./test-interactive $UNIT_TEST $@" +echo "" +echo "NOTE: For debugging purposes, you can run this single test as follows:" +echo "$ libtool --mode=execute \\" +echo " gdb --eval-command=\"b `echo $UNIT_TEST|tr '-' '_'`_main\" \\" +echo " --args ./test-interactive $UNIT_TEST" + +@abs_builddir@/test-interactive $UNIT_TEST "$@" + diff --git a/clutter/tests/micro-bench/Makefile.am b/clutter/tests/micro-bench/Makefile.am new file mode 100644 index 0000000..2731b9e --- /dev/null +++ b/clutter/tests/micro-bench/Makefile.am @@ -0,0 +1,34 @@ +common_ldadd = \ + $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la + + +check_PROGRAMS = \ + test-text \ + test-picking \ + test-text-perf \ + test-random-text \ + test-cogl-perf + +AM_CFLAGS = $(CLUTTER_CFLAGS) $(MAINTAINER_CFLAGS) + +AM_CPPFLAGS = \ + -DG_DISABLE_SINGLE_INCLUDES \ + -DGLIB_DISABLE_DEPRECATION_WARNINGS \ + -DCOGL_DISABLE_DEPRECATION_WARNINGS \ + -DCLUTTER_DISABLE_DEPRECATION_WARNINGS \ + -DTESTS_DATA_DIR=\""$(top_srcdir)/tests/data/"\" \ + -I$(top_srcdir)/../cogl \ + -I$(top_builddir)/../cogl \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + -I$(top_srcdir)/clutter \ + -I$(top_builddir)/clutter + +LDADD = $(common_ldadd) $(CLUTTER_LIBS) $(LIBM) + +test_text_SOURCES = test-text.c +test_picking_SOURCES = test-picking.c +test_text_perf_SOURCES = test-text-perf.c +test_random_text_SOURCES = test-random-text.c +test_cogl_perf_SOURCES = test-cogl-perf.c diff --git a/clutter/tests/micro-bench/Makefile.in b/clutter/tests/micro-bench/Makefile.in new file mode 100644 index 0000000..c3e7e65 --- /dev/null +++ b/clutter/tests/micro-bench/Makefile.in @@ -0,0 +1,731 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +check_PROGRAMS = test-text$(EXEEXT) test-picking$(EXEEXT) \ + test-text-perf$(EXEEXT) test-random-text$(EXEEXT) \ + test-cogl-perf$(EXEEXT) +subdir = tests/micro-bench +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/build/autotools/as-compiler-flag.m4 \ + $(top_srcdir)/build/autotools/glibtests.m4 \ + $(top_srcdir)/build/autotools/introspection.m4 \ + $(top_srcdir)/build/autotools/libtool.m4 \ + $(top_srcdir)/build/autotools/ltoptions.m4 \ + $(top_srcdir)/build/autotools/ltsugar.m4 \ + $(top_srcdir)/build/autotools/ltversion.m4 \ + $(top_srcdir)/build/autotools/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/clutter/clutter-build-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am_test_cogl_perf_OBJECTS = test-cogl-perf.$(OBJEXT) +test_cogl_perf_OBJECTS = $(am_test_cogl_perf_OBJECTS) +test_cogl_perf_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +test_cogl_perf_DEPENDENCIES = $(common_ldadd) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +am_test_picking_OBJECTS = test-picking.$(OBJEXT) +test_picking_OBJECTS = $(am_test_picking_OBJECTS) +test_picking_LDADD = $(LDADD) +test_picking_DEPENDENCIES = $(common_ldadd) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_test_random_text_OBJECTS = test-random-text.$(OBJEXT) +test_random_text_OBJECTS = $(am_test_random_text_OBJECTS) +test_random_text_LDADD = $(LDADD) +test_random_text_DEPENDENCIES = $(common_ldadd) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_test_text_OBJECTS = test-text.$(OBJEXT) +test_text_OBJECTS = $(am_test_text_OBJECTS) +test_text_LDADD = $(LDADD) +test_text_DEPENDENCIES = $(common_ldadd) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_test_text_perf_OBJECTS = test-text-perf.$(OBJEXT) +test_text_perf_OBJECTS = $(am_test_text_perf_OBJECTS) +test_text_perf_LDADD = $(LDADD) +test_text_perf_DEPENDENCIES = $(common_ldadd) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/clutter +depcomp = $(SHELL) $(top_srcdir)/build/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(test_cogl_perf_SOURCES) $(test_picking_SOURCES) \ + $(test_random_text_SOURCES) $(test_text_SOURCES) \ + $(test_text_perf_SOURCES) +DIST_SOURCES = $(test_cogl_perf_SOURCES) $(test_picking_SOURCES) \ + $(test_random_text_SOURCES) $(test_text_SOURCES) \ + $(test_text_perf_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/build/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ATK_REQ_VERSION = @ATK_REQ_VERSION@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_REQ_VERSION = @CAIRO_REQ_VERSION@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CLUTTER_API_VERSION = @CLUTTER_API_VERSION@ +CLUTTER_API_VERSION_AM = @CLUTTER_API_VERSION_AM@ +CLUTTER_BACKENDS = @CLUTTER_BACKENDS@ +CLUTTER_CFLAGS = @CLUTTER_CFLAGS@ +CLUTTER_COGL = @CLUTTER_COGL@ +CLUTTER_CONFIG_DEFINES = @CLUTTER_CONFIG_DEFINES@ +CLUTTER_DEBUG_CFLAGS = @CLUTTER_DEBUG_CFLAGS@ +CLUTTER_DEPRECATED_CFLAGS = @CLUTTER_DEPRECATED_CFLAGS@ +CLUTTER_DEPS_CFLAGS = @CLUTTER_DEPS_CFLAGS@ +CLUTTER_DEPS_LIBS = @CLUTTER_DEPS_LIBS@ +CLUTTER_DEPS_PRIVATE_CFLAGS = @CLUTTER_DEPS_PRIVATE_CFLAGS@ +CLUTTER_DEPS_PRIVATE_LIBS = @CLUTTER_DEPS_PRIVATE_LIBS@ +CLUTTER_FLAVOUR = @CLUTTER_FLAVOUR@ +CLUTTER_GCOV_CFLAGS = @CLUTTER_GCOV_CFLAGS@ +CLUTTER_GCOV_LDADD = @CLUTTER_GCOV_LDADD@ +CLUTTER_HIDDEN_VISIBILITY_CFLAGS = @CLUTTER_HIDDEN_VISIBILITY_CFLAGS@ +CLUTTER_INPUT_BACKENDS = @CLUTTER_INPUT_BACKENDS@ +CLUTTER_LIBS = @CLUTTER_LIBS@ +CLUTTER_LINK_FLAGS = @CLUTTER_LINK_FLAGS@ +CLUTTER_LT_CURRENT = @CLUTTER_LT_CURRENT@ +CLUTTER_LT_LDFLAGS = @CLUTTER_LT_LDFLAGS@ +CLUTTER_LT_REVISION = @CLUTTER_LT_REVISION@ +CLUTTER_LT_VERSION = @CLUTTER_LT_VERSION@ +CLUTTER_MAJOR_VERSION = @CLUTTER_MAJOR_VERSION@ +CLUTTER_MICRO_VERSION = @CLUTTER_MICRO_VERSION@ +CLUTTER_MINOR_VERSION = @CLUTTER_MINOR_VERSION@ +CLUTTER_RELEASE_STATUS = @CLUTTER_RELEASE_STATUS@ +CLUTTER_REQUIRES = @CLUTTER_REQUIRES@ +CLUTTER_REQUIRES_PRIVATE = @CLUTTER_REQUIRES_PRIVATE@ +CLUTTER_SONAME_INFIX = @CLUTTER_SONAME_INFIX@ +CLUTTER_STAGE_TYPE = @CLUTTER_STAGE_TYPE@ +CLUTTER_VERSION = @CLUTTER_VERSION@ +CLUTTER_WINSYS = @CLUTTER_WINSYS@ +CLUTTER_WINSYS_BASE = @CLUTTER_WINSYS_BASE@ +COGL_DRIVER = @COGL_DRIVER@ +COGL_REQ_VERSION = @COGL_REQ_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@ +GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@ +GDK_REQ_VERSION = @GDK_REQ_VERSION@ +GI_REQ_VERSION = @GI_REQ_VERSION@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQ_VERSION = @GLIB_REQ_VERSION@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +JSON_GLIB_REQ_VERSION = @JSON_GLIB_REQ_VERSION@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBINPUT_REQ_VERSION = @LIBINPUT_REQ_VERSION@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUDEV_REQ_VERSION = @LIBUDEV_REQ_VERSION@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTP = @LTP@ +LTP_GENHTML = @LTP_GENHTML@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINTAINER_CFLAGS = @MAINTAINER_CFLAGS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGO_REQ_VERSION = @PANGO_REQ_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SHTOOL = @SHTOOL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +XCOMPOSITE_REQ_VERSION = @XCOMPOSITE_REQ_VERSION@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +installed_test_metadir = @installed_test_metadir@ +installed_testdir = @installed_testdir@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +common_ldadd = \ + $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la \ + $(top_builddir)/../cogl/cogl/libmutter-cogl.la + +AM_CFLAGS = $(CLUTTER_CFLAGS) $(MAINTAINER_CFLAGS) +AM_CPPFLAGS = \ + -DG_DISABLE_SINGLE_INCLUDES \ + -DGLIB_DISABLE_DEPRECATION_WARNINGS \ + -DCOGL_DISABLE_DEPRECATION_WARNINGS \ + -DCLUTTER_DISABLE_DEPRECATION_WARNINGS \ + -DTESTS_DATA_DIR=\""$(top_srcdir)/tests/data/"\" \ + -I$(top_srcdir)/../cogl \ + -I$(top_builddir)/../cogl \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + -I$(top_srcdir)/clutter \ + -I$(top_builddir)/clutter + +LDADD = $(common_ldadd) $(CLUTTER_LIBS) $(LIBM) +test_text_SOURCES = test-text.c +test_picking_SOURCES = test-picking.c +test_text_perf_SOURCES = test-text-perf.c +test_random_text_SOURCES = test-random-text.c +test_cogl_perf_SOURCES = test-cogl-perf.c +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/micro-bench/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/micro-bench/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +test-cogl-perf$(EXEEXT): $(test_cogl_perf_OBJECTS) $(test_cogl_perf_DEPENDENCIES) $(EXTRA_test_cogl_perf_DEPENDENCIES) + @rm -f test-cogl-perf$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_cogl_perf_OBJECTS) $(test_cogl_perf_LDADD) $(LIBS) + +test-picking$(EXEEXT): $(test_picking_OBJECTS) $(test_picking_DEPENDENCIES) $(EXTRA_test_picking_DEPENDENCIES) + @rm -f test-picking$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_picking_OBJECTS) $(test_picking_LDADD) $(LIBS) + +test-random-text$(EXEEXT): $(test_random_text_OBJECTS) $(test_random_text_DEPENDENCIES) $(EXTRA_test_random_text_DEPENDENCIES) + @rm -f test-random-text$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_random_text_OBJECTS) $(test_random_text_LDADD) $(LIBS) + +test-text$(EXEEXT): $(test_text_OBJECTS) $(test_text_DEPENDENCIES) $(EXTRA_test_text_DEPENDENCIES) + @rm -f test-text$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_text_OBJECTS) $(test_text_LDADD) $(LIBS) + +test-text-perf$(EXEEXT): $(test_text_perf_OBJECTS) $(test_text_perf_DEPENDENCIES) $(EXTRA_test_text_perf_DEPENDENCIES) + @rm -f test-text-perf$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_text_perf_OBJECTS) $(test_text_perf_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-cogl-perf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-picking.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-random-text.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-text-perf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-text.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ + clean-checkPROGRAMS clean-generic clean-libtool cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/clutter/tests/micro-bench/test-cogl-perf.c b/clutter/tests/micro-bench/test-cogl-perf.c new file mode 100644 index 0000000..0b92219 --- /dev/null +++ b/clutter/tests/micro-bench/test-cogl-perf.c @@ -0,0 +1,158 @@ +#include +#include +#include +#include +#include +#include +#include + +#define STAGE_WIDTH 800 +#define STAGE_HEIGHT 600 + +gboolean run_all = FALSE; + +static GOptionEntry entries[] = { + { + "run-all", 'a', + 0, + G_OPTION_ARG_NONE, &run_all, + "Run all tests", "" + }, + { NULL } +}; + +typedef struct _TestState +{ + ClutterActor *stage; + int current_test; +} TestState; + +typedef void (*TestCallback) (TestState *state); + +static void +test_rectangles (TestState *state) +{ +#define RECT_WIDTH 5 +#define RECT_HEIGHT 5 + int x; + int y; + + /* Should the rectangles be randomly positioned/colored/rotated? + * + * It could be good to develop equivalent GL and Cairo tests so we can + * have a sanity check for our Cogl performance. + * + * The color should vary to check that we correctly batch color changes + * The use of alpha should vary so we have a variation of which rectangles + * require blending. + * Should this be a random variation? + * It could be good to experiment with focibly enabling blending for + * rectangles that don't technically need it for the sake of extending + * batching. E.g. if you a long run of interleved rectangles with every + * other rectangle needing blending then it may be worth enabling blending + * for all the rectangles to avoid the state changes. + * The modelview should change between rectangles to check the software + * transform codepath. + * Should we group some rectangles under the same modelview? Potentially + * we could avoid software transform for long runs of rectangles with the + * same modelview. + * + */ + + for (y = 0; y < STAGE_HEIGHT; y += RECT_HEIGHT) + { + for (x = 0; x < STAGE_WIDTH; x += RECT_WIDTH) + { + cogl_push_matrix (); + cogl_translate (x, y, 0); + cogl_rotate (45, 0, 0, 1); + cogl_set_source_color4f (1, + (1.0f/STAGE_WIDTH)*y, + (1.0f/STAGE_HEIGHT)*x, + 1); + cogl_rectangle (0, 0, RECT_WIDTH, RECT_HEIGHT); + cogl_pop_matrix (); + } + } + + for (y = 0; y < STAGE_HEIGHT; y += RECT_HEIGHT) + { + for (x = 0; x < STAGE_WIDTH; x += RECT_WIDTH) + { + cogl_push_matrix (); + cogl_translate (x, y, 0); + cogl_rotate (0, 0, 0, 1); + cogl_set_source_color4f (1, + (1.0f/STAGE_WIDTH)*x, + (1.0f/STAGE_HEIGHT)*y, + (1.0f/STAGE_WIDTH)*x); + cogl_rectangle (0, 0, RECT_WIDTH, RECT_HEIGHT); + cogl_pop_matrix (); + } + } +} + +TestCallback tests[] = +{ + test_rectangles +}; + +static void +on_paint (ClutterActor *actor, TestState *state) +{ + tests[state->current_test] (state); +} + +static gboolean +queue_redraw (gpointer stage) +{ + clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); + + return TRUE; +} + +int +main (int argc, char *argv[]) +{ + TestState state; + ClutterActor *stage; + GError *error = NULL; + + g_setenv ("CLUTTER_VBLANK", "none", FALSE); + g_setenv ("CLUTTER_SHOW_FPS", "1", FALSE); + + if (clutter_init_with_args (&argc, &argv, + NULL, + entries, + NULL, + &error) != CLUTTER_INIT_SUCCESS) + { + g_warning ("Unable to initialise Clutter:\n%s", + error->message); + g_error_free (error); + + return EXIT_FAILURE; + } + + state.current_test = 0; + + state.stage = stage = clutter_stage_new (); + + clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT); + clutter_stage_set_color (CLUTTER_STAGE (stage), CLUTTER_COLOR_White); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl Performance Test"); + + /* We want continuous redrawing of the stage... */ + clutter_threads_add_idle (queue_redraw, stage); + + g_signal_connect_after (stage, "paint", G_CALLBACK (on_paint), &state); + + clutter_actor_show (stage); + + clutter_main (); + + clutter_actor_destroy (stage); + + return 0; +} + diff --git a/clutter/tests/micro-bench/test-picking.c b/clutter/tests/micro-bench/test-picking.c new file mode 100644 index 0000000..845e600 --- /dev/null +++ b/clutter/tests/micro-bench/test-picking.c @@ -0,0 +1,140 @@ + +#include +#include +#include + +#define N_ACTORS 100 +#define N_EVENTS 5 + +static gint n_actors = N_ACTORS; +static gint n_events = N_EVENTS; + +static GOptionEntry entries[] = { + { + "num-actors", 'a', + 0, + G_OPTION_ARG_INT, &n_actors, + "Number of actors", "ACTORS" + }, + { + "num-events", 'e', + 0, + G_OPTION_ARG_INT, &n_events, + "Number of events", "EVENTS" + }, + { NULL } +}; + +static gboolean +motion_event_cb (ClutterActor *actor, ClutterEvent *event, gpointer user_data) +{ + return FALSE; +} + +static void +do_events (ClutterActor *stage) +{ + glong i; + static gdouble angle = 0; + + for (i = 0; i < n_events; i++) + { + angle += (2.0 * G_PI) / (gdouble)n_actors; + while (angle > G_PI * 2.0) + angle -= G_PI * 2.0; + + /* If we synthesized events, they would be motion compressed; + * calling get_actor_at_position() doesn't have that problem + */ + clutter_stage_get_actor_at_pos (CLUTTER_STAGE (stage), + CLUTTER_PICK_REACTIVE, + 256.0 + 206.0 * cos (angle), + 256.0 + 206.0 * sin (angle)); + } +} + +static void +on_paint (ClutterActor *stage, gconstpointer *data) +{ + do_events (stage); +} + +static gboolean +queue_redraw (gpointer stage) +{ + clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); + + return TRUE; +} + +int +main (int argc, char **argv) +{ + glong i; + gdouble angle; + ClutterColor color = { 0x00, 0x00, 0x00, 0xff }; + ClutterActor *stage, *rect; + GError *error = NULL; + + g_setenv ("CLUTTER_VBLANK", "none", FALSE); + g_setenv ("CLUTTER_DEFAULT_FPS", "1000", FALSE); + g_setenv ("CLUTTER_SHOW_FPS", "1", FALSE); + + if (clutter_init_with_args (&argc, &argv, + NULL, + entries, + NULL, + &error) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + clutter_actor_set_size (stage, 512, 512); + clutter_stage_set_color (CLUTTER_STAGE (stage), CLUTTER_COLOR_Black); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Picking"); + + printf ("Picking performance test with " + "%d actors and %d events per frame\n", + n_actors, + n_events); + + for (i = n_actors - 1; i >= 0; i--) + { + angle = ((2.0 * G_PI) / (gdouble) n_actors) * i; + + color.red = (1.0 - ABS ((MAX (0, MIN (n_actors/2.0 + 0, i))) / + (gdouble)(n_actors/4.0) - 1.0)) * 255.0; + color.green = (1.0 - ABS ((MAX (0, MIN (n_actors/2.0 + 0, + fmod (i + (n_actors/3.0)*2, n_actors)))) / + (gdouble)(n_actors/4) - 1.0)) * 255.0; + color.blue = (1.0 - ABS ((MAX (0, MIN (n_actors/2.0 + 0, + fmod ((i + (n_actors/3.0)), n_actors)))) / + (gdouble)(n_actors/4.0) - 1.0)) * 255.0; + + rect = clutter_rectangle_new_with_color (&color); + clutter_actor_set_size (rect, 100, 100); + clutter_actor_set_anchor_point_from_gravity (rect, + CLUTTER_GRAVITY_CENTER); + clutter_actor_set_position (rect, + 256 + 206 * cos (angle), + 256 + 206 * sin (angle)); + clutter_actor_set_reactive (rect, TRUE); + g_signal_connect (rect, "motion-event", + G_CALLBACK (motion_event_cb), NULL); + + clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); + } + + clutter_actor_show (stage); + + clutter_threads_add_idle (queue_redraw, stage); + + g_signal_connect (stage, "paint", G_CALLBACK (on_paint), NULL); + + clutter_main (); + + clutter_actor_destroy (stage); + + return 0; +} + + diff --git a/clutter/tests/micro-bench/test-random-text.c b/clutter/tests/micro-bench/test-random-text.c new file mode 100644 index 0000000..69eb6d0 --- /dev/null +++ b/clutter/tests/micro-bench/test-random-text.c @@ -0,0 +1,105 @@ +#include +#include +#include + +#define MAX_TEXT_LEN 10 +#define MIN_FONT_SIZE 10 +#define MAX_FONT_SIZE 30 + +static const char * const font_names[] = + { + "Sans", "Sans Italic", "Serif", "Serif Bold", "Times", "Monospace" + }; +#define FONT_NAME_COUNT 6 + +static gboolean +on_idle (gpointer data) +{ + ClutterActor *stage = CLUTTER_ACTOR (data); + int line_height = 0, xpos = 0, ypos = 0; + int stage_width = clutter_actor_get_width (stage); + int stage_height = clutter_actor_get_height (stage); + char text[MAX_TEXT_LEN + 1]; + char font_name[64]; + int i; + GList *children, *node; + static GTimer *timer = NULL; + static int frame_count = 0; + + /* Remove all of the children of the stage */ + children = clutter_container_get_children (CLUTTER_CONTAINER (stage)); + for (node = children; node; node = node->next) + clutter_container_remove_actor (CLUTTER_CONTAINER (stage), + CLUTTER_ACTOR (node->data)); + g_list_free (children); + + /* Fill the stage with new random labels */ + while (ypos < stage_height) + { + int text_len = rand () % MAX_TEXT_LEN + 1; + ClutterActor *label; + + for (i = 0; i < text_len; i++) + text[i] = rand () % (128 - 32) + 32; + text[text_len] = '\0'; + + sprintf (font_name, "%s %i", + font_names[rand () % FONT_NAME_COUNT], + rand () % (MAX_FONT_SIZE - MIN_FONT_SIZE) + MIN_FONT_SIZE); + + label = clutter_text_new_with_text (font_name, text); + + if (clutter_actor_get_height (label) > line_height) + line_height = clutter_actor_get_height (label); + + if (xpos + clutter_actor_get_width (label) > stage_width) + { + xpos = 0; + ypos += line_height; + line_height = 0; + } + + clutter_actor_set_position (label, xpos, ypos); + + clutter_container_add (CLUTTER_CONTAINER (stage), label, NULL); + + xpos += clutter_actor_get_width (label); + } + + if (timer == NULL) + timer = g_timer_new (); + else + { + if (++frame_count >= 10) + { + printf ("10 frames in %f seconds\n", + g_timer_elapsed (timer, NULL)); + g_timer_start (timer); + frame_count = 0; + } + } + + return TRUE; +} + +int +main (int argc, char *argv[]) +{ + ClutterActor *stage; + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Random Text"); + + clutter_actor_show (stage); + + clutter_threads_add_idle (on_idle, stage); + + clutter_main (); + + clutter_actor_destroy (stage); + + return 0; +} diff --git a/clutter/tests/micro-bench/test-text-perf.c b/clutter/tests/micro-bench/test-text-perf.c new file mode 100644 index 0000000..710c83e --- /dev/null +++ b/clutter/tests/micro-bench/test-text-perf.c @@ -0,0 +1,187 @@ +#include + +#include +#include + +#define STAGE_WIDTH 800 +#define STAGE_HEIGHT 600 + +static int font_size; +static int n_chars; +static int rows, cols; + +static void +on_paint (ClutterActor *actor, gconstpointer *data) +{ + static GTimer *timer = NULL; + static int fps = 0; + + if (!timer) + { + timer = g_timer_new (); + g_timer_start (timer); + } + + if (g_timer_elapsed (timer, NULL) >= 1) + { + printf ("fps=%d, strings/sec=%d, chars/sec=%d\n", + fps, + fps * rows * cols, + fps * rows * cols * n_chars); + g_timer_start (timer); + fps = 0; + } + + ++fps; +} + +static gboolean +queue_redraw (gpointer stage) +{ + clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); + + return G_SOURCE_CONTINUE; +} + +static gunichar +get_character (int ch) +{ + int total_letters = 0; + int i; + + static const struct + { + gunichar first_letter; + int n_letters; + } + ranges[] = + { + { 'a', 26 }, /* lower case letters */ + { 'A', 26 }, /* upper case letters */ + { '0', 10 }, /* digits */ + { 0x410, 0x40 }, /* cyrillic alphabet */ + { 0x3b1, 18 } /* greek alphabet */ + }; + + for (i = 0; i < G_N_ELEMENTS (ranges); i++) + total_letters += ranges[i].n_letters; + + ch %= total_letters; + + for (i = 0; i < G_N_ELEMENTS (ranges) - 1; i++) + if (ch < ranges[i].n_letters) + return ch + ranges[i].first_letter; + else + ch -= ranges[i].n_letters; + + return ch + ranges[i].first_letter; +} + +static ClutterActor * +create_label (void) +{ + ClutterColor label_color = { 0xff, 0xff, 0xff, 0xff }; + ClutterActor *label; + char *font_name; + GString *str; + int i; + + font_name = g_strdup_printf ("Monospace %dpx", font_size); + + str = g_string_new (NULL); + for (i = 0; i < n_chars; i++) + g_string_append_unichar (str, get_character (i)); + + label = clutter_text_new_with_text (font_name, str->str); + clutter_text_set_color (CLUTTER_TEXT (label), &label_color); + + g_free (font_name); + g_string_free (str, TRUE); + + return label; +} + +int +main (int argc, char *argv[]) +{ + ClutterActor *stage; + ClutterActor *label; + int w, h; + int row, col; + float scale = 1.0f; + + g_setenv ("CLUTTER_VBLANK", "none", FALSE); + g_setenv ("CLUTTER_DEFAULT_FPS", "1000", FALSE); + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + if (argc != 3) + { + g_printerr ("Usage test-text-perf FONT_SIZE N_CHARS\n"); + exit (1); + } + + font_size = atoi (argv[1]); + n_chars = atoi (argv[2]); + + g_print ("Monospace %dpx, string length = %d\n", font_size, n_chars); + + stage = clutter_stage_new (); + clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT); + clutter_stage_set_color (CLUTTER_STAGE (stage), CLUTTER_COLOR_Black); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Text Performance"); + + g_signal_connect (stage, "paint", G_CALLBACK (on_paint), NULL); + + label = create_label (); + w = clutter_actor_get_width (label); + h = clutter_actor_get_height (label); + + /* If the label is too big to fit on the stage then scale it so that + it will fit */ + if (w > STAGE_WIDTH || h > STAGE_HEIGHT) + { + float x_scale = STAGE_WIDTH / (float) w; + float y_scale = STAGE_HEIGHT / (float) h; + + if (x_scale < y_scale) + { + scale = x_scale; + cols = 1; + rows = STAGE_HEIGHT / (h * scale); + } + else + { + scale = y_scale; + cols = STAGE_WIDTH / (w * scale); + rows = 1; + } + + g_print ("Text scaled by %f to fit on the stage\n", scale); + } + else + { + cols = STAGE_WIDTH / w; + rows = STAGE_HEIGHT / h; + } + + clutter_actor_destroy (label); + + for (row=0; row + +#include +#include + +#define STAGE_WIDTH 640 +#define STAGE_HEIGHT 480 + +#define COLS 18 +#define ROWS 20 + +static void +on_paint (ClutterActor *actor, gconstpointer *data) +{ + static GTimer *timer = NULL; + static int fps = 0; + + if (!timer) + { + timer = g_timer_new (); + g_timer_start (timer); + } + + if (g_timer_elapsed (timer, NULL) >= 1) + { + printf ("fps: %d\n", fps); + g_timer_start (timer); + fps = 0; + } + + ++fps; +} + +static gboolean +queue_redraw (gpointer stage) +{ + clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); + + return G_SOURCE_CONTINUE; +} + +int +main (int argc, char *argv[]) +{ + ClutterActor *stage; + ClutterActor *group; + + g_setenv ("CLUTTER_VBLANK", "none", FALSE); + g_setenv ("CLUTTER_DEFAULT_FPS", "1000", FALSE); + + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return 1; + + stage = clutter_stage_new (); + clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT); + clutter_stage_set_color (CLUTTER_STAGE (stage), CLUTTER_COLOR_Black); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Text"); + + group = clutter_group_new (); + clutter_actor_set_size (group, STAGE_WIDTH, STAGE_WIDTH); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), group); + + clutter_threads_add_idle (queue_redraw, stage); + + g_signal_connect (group, "paint", G_CALLBACK (on_paint), NULL); + + { + gint row, col; + + for (row=0; row /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor || true' + #sudo sh -c 'echo performance > /sys/devices/system/cpu/cpu1/cpufreq/scaling_governor || true' + +reset: + rm -rf jobs jobs + # remove checkout dir to have a full reset on each invokation + rm -rf checkout + # create clone + git clone -s $(PROJECT_PATH) checkout + mkdir reports > /dev/null 2>&1 || true + make -f $(SELF) jobs + make -f $(SELF) prepare + +jobs: joblist + ./makejobs.rb joblist > jobs + +sequential: + for a in `cat jobs`;do make -f $(SELF) reports/$$a;done + +random: + for a in `cat jobs|sort`;do make -f $(SELF) reports/$$a;done + +reports/%: + # check out revision + (cd checkout; git checkout `echo $@|sed s:reports/::`) + # write header for report + git log -1 `echo $@|sed s:reports/::` > $@ || true + # clean previous build + rm -rf install; mkdir install + # build revision + (cd checkout; if [ ! -f Makefile ]; then CC=$(CC) ./autogen.sh --disable-introspection --prefix=`pwd`/../install; fi ; \ + make $(MAKE_FLAGS) ; make -k install ) > $@.log 2>&1 || true + # testing + make -f Makefile-tests clean;\ + make -f Makefile-tests; sync;\ + make -f Makefile-tests check >> $@ || true + # update report.pdf / report.png + ./create-report.rb + echo + +clean: + rm -rf reports jobs report.pdf report.png checkout install + make -f Makefile-tests clean diff --git a/clutter/tests/performance/Makefile-tests b/clutter/tests/performance/Makefile-tests new file mode 100644 index 0000000..3381a32 --- /dev/null +++ b/clutter/tests/performance/Makefile-tests @@ -0,0 +1,15 @@ +CFILES = $(wildcard *.c) +bins = $(subst ,,$(CFILES:.c=)) + +all: $(bins) + +%: %.c + PKG_CONFIG_PATH=install/lib/pkgconfig:$(PKG_CONFIG_PATH) $(CC) -DTESTS_DATA_DIR=\"../data/\" `pkg-config clutter-1.0 --cflags --libs` -Wall -O2 -o $@ $< + +check: $(bins) + for a in $(bins); do \ + LD_LIBRARY_PATH=install/lib:$(LD_LIBRARY_PATH) ./$$a;\ + done + +clean: + rm -f $(bins) diff --git a/clutter/tests/performance/Makefile.am b/clutter/tests/performance/Makefile.am new file mode 100644 index 0000000..2257959 --- /dev/null +++ b/clutter/tests/performance/Makefile.am @@ -0,0 +1,42 @@ +check_PROGRAMS = \ + test-picking \ + test-text-perf \ + test-state \ + test-state-interactive \ + test-state-hidden \ + test-state-mini \ + test-state-pick + +common_ldadd = $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la + +LDADD = $(common_ldadd) $(CLUTTER_LIBS) $(LIBM) + +AM_CFLAGS = $(CLUTTER_CFLAGS) + +AM_CPPFLAGS = \ + -DG_DISABLE_SINGLE_INCLUDES \ + -DGLIB_DISABLE_DEPRECATION_WARNINGS \ + -DCOGL_DISABLE_DEPRECATION_WARNINGS \ + -DCLUTTER_DISABLE_DEPRECATION_WARNINGS \ + -DTESTS_DATA_DIR=\""$(top_srcdir)/tests/data/"\" \ + -I$(top_srcdir)/../cogl \ + -I$(top_builddir)/../cogl \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + -I$(top_srcdir)/clutter \ + -I$(top_builddir)/clutter + +perf-report: check + +check: + for a in $(noinst_PROGRAMS);do ./$$a;done;true + +test_picking_SOURCES = test-picking.c +test_text_perf_SOURCES = test-text-perf.c +test_state_SOURCES = test-state.c +test_state_hidden_SOURCES = test-state-hidden.c +test_state_pick_SOURCES = test-state-pick.c +test_state_interactive_SOURCES = test-state-interactive.c +test_state_mini_SOURCES = test-state-mini.c + +EXTRA_DIST = Makefile-retrospect Makefile-tests create-report.rb test-common.h diff --git a/clutter/tests/performance/Makefile.in b/clutter/tests/performance/Makefile.in new file mode 100644 index 0000000..07b3ff0 --- /dev/null +++ b/clutter/tests/performance/Makefile.in @@ -0,0 +1,759 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +check_PROGRAMS = test-picking$(EXEEXT) test-text-perf$(EXEEXT) \ + test-state$(EXEEXT) test-state-interactive$(EXEEXT) \ + test-state-hidden$(EXEEXT) test-state-mini$(EXEEXT) \ + test-state-pick$(EXEEXT) +subdir = tests/performance +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/build/autotools/as-compiler-flag.m4 \ + $(top_srcdir)/build/autotools/glibtests.m4 \ + $(top_srcdir)/build/autotools/introspection.m4 \ + $(top_srcdir)/build/autotools/libtool.m4 \ + $(top_srcdir)/build/autotools/ltoptions.m4 \ + $(top_srcdir)/build/autotools/ltsugar.m4 \ + $(top_srcdir)/build/autotools/ltversion.m4 \ + $(top_srcdir)/build/autotools/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/clutter/clutter-build-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am_test_picking_OBJECTS = test-picking.$(OBJEXT) +test_picking_OBJECTS = $(am_test_picking_OBJECTS) +test_picking_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +test_picking_DEPENDENCIES = $(common_ldadd) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +am_test_state_OBJECTS = test-state.$(OBJEXT) +test_state_OBJECTS = $(am_test_state_OBJECTS) +test_state_LDADD = $(LDADD) +test_state_DEPENDENCIES = $(common_ldadd) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_test_state_hidden_OBJECTS = test-state-hidden.$(OBJEXT) +test_state_hidden_OBJECTS = $(am_test_state_hidden_OBJECTS) +test_state_hidden_LDADD = $(LDADD) +test_state_hidden_DEPENDENCIES = $(common_ldadd) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_test_state_interactive_OBJECTS = test-state-interactive.$(OBJEXT) +test_state_interactive_OBJECTS = $(am_test_state_interactive_OBJECTS) +test_state_interactive_LDADD = $(LDADD) +test_state_interactive_DEPENDENCIES = $(common_ldadd) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +am_test_state_mini_OBJECTS = test-state-mini.$(OBJEXT) +test_state_mini_OBJECTS = $(am_test_state_mini_OBJECTS) +test_state_mini_LDADD = $(LDADD) +test_state_mini_DEPENDENCIES = $(common_ldadd) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_test_state_pick_OBJECTS = test-state-pick.$(OBJEXT) +test_state_pick_OBJECTS = $(am_test_state_pick_OBJECTS) +test_state_pick_LDADD = $(LDADD) +test_state_pick_DEPENDENCIES = $(common_ldadd) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_test_text_perf_OBJECTS = test-text-perf.$(OBJEXT) +test_text_perf_OBJECTS = $(am_test_text_perf_OBJECTS) +test_text_perf_LDADD = $(LDADD) +test_text_perf_DEPENDENCIES = $(common_ldadd) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/clutter +depcomp = $(SHELL) $(top_srcdir)/build/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(test_picking_SOURCES) $(test_state_SOURCES) \ + $(test_state_hidden_SOURCES) $(test_state_interactive_SOURCES) \ + $(test_state_mini_SOURCES) $(test_state_pick_SOURCES) \ + $(test_text_perf_SOURCES) +DIST_SOURCES = $(test_picking_SOURCES) $(test_state_SOURCES) \ + $(test_state_hidden_SOURCES) $(test_state_interactive_SOURCES) \ + $(test_state_mini_SOURCES) $(test_state_pick_SOURCES) \ + $(test_text_perf_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/build/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ATK_REQ_VERSION = @ATK_REQ_VERSION@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_REQ_VERSION = @CAIRO_REQ_VERSION@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CLUTTER_API_VERSION = @CLUTTER_API_VERSION@ +CLUTTER_API_VERSION_AM = @CLUTTER_API_VERSION_AM@ +CLUTTER_BACKENDS = @CLUTTER_BACKENDS@ +CLUTTER_CFLAGS = @CLUTTER_CFLAGS@ +CLUTTER_COGL = @CLUTTER_COGL@ +CLUTTER_CONFIG_DEFINES = @CLUTTER_CONFIG_DEFINES@ +CLUTTER_DEBUG_CFLAGS = @CLUTTER_DEBUG_CFLAGS@ +CLUTTER_DEPRECATED_CFLAGS = @CLUTTER_DEPRECATED_CFLAGS@ +CLUTTER_DEPS_CFLAGS = @CLUTTER_DEPS_CFLAGS@ +CLUTTER_DEPS_LIBS = @CLUTTER_DEPS_LIBS@ +CLUTTER_DEPS_PRIVATE_CFLAGS = @CLUTTER_DEPS_PRIVATE_CFLAGS@ +CLUTTER_DEPS_PRIVATE_LIBS = @CLUTTER_DEPS_PRIVATE_LIBS@ +CLUTTER_FLAVOUR = @CLUTTER_FLAVOUR@ +CLUTTER_GCOV_CFLAGS = @CLUTTER_GCOV_CFLAGS@ +CLUTTER_GCOV_LDADD = @CLUTTER_GCOV_LDADD@ +CLUTTER_HIDDEN_VISIBILITY_CFLAGS = @CLUTTER_HIDDEN_VISIBILITY_CFLAGS@ +CLUTTER_INPUT_BACKENDS = @CLUTTER_INPUT_BACKENDS@ +CLUTTER_LIBS = @CLUTTER_LIBS@ +CLUTTER_LINK_FLAGS = @CLUTTER_LINK_FLAGS@ +CLUTTER_LT_CURRENT = @CLUTTER_LT_CURRENT@ +CLUTTER_LT_LDFLAGS = @CLUTTER_LT_LDFLAGS@ +CLUTTER_LT_REVISION = @CLUTTER_LT_REVISION@ +CLUTTER_LT_VERSION = @CLUTTER_LT_VERSION@ +CLUTTER_MAJOR_VERSION = @CLUTTER_MAJOR_VERSION@ +CLUTTER_MICRO_VERSION = @CLUTTER_MICRO_VERSION@ +CLUTTER_MINOR_VERSION = @CLUTTER_MINOR_VERSION@ +CLUTTER_RELEASE_STATUS = @CLUTTER_RELEASE_STATUS@ +CLUTTER_REQUIRES = @CLUTTER_REQUIRES@ +CLUTTER_REQUIRES_PRIVATE = @CLUTTER_REQUIRES_PRIVATE@ +CLUTTER_SONAME_INFIX = @CLUTTER_SONAME_INFIX@ +CLUTTER_STAGE_TYPE = @CLUTTER_STAGE_TYPE@ +CLUTTER_VERSION = @CLUTTER_VERSION@ +CLUTTER_WINSYS = @CLUTTER_WINSYS@ +CLUTTER_WINSYS_BASE = @CLUTTER_WINSYS_BASE@ +COGL_DRIVER = @COGL_DRIVER@ +COGL_REQ_VERSION = @COGL_REQ_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@ +GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@ +GDK_REQ_VERSION = @GDK_REQ_VERSION@ +GI_REQ_VERSION = @GI_REQ_VERSION@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQ_VERSION = @GLIB_REQ_VERSION@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +JSON_GLIB_REQ_VERSION = @JSON_GLIB_REQ_VERSION@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBINPUT_REQ_VERSION = @LIBINPUT_REQ_VERSION@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUDEV_REQ_VERSION = @LIBUDEV_REQ_VERSION@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTP = @LTP@ +LTP_GENHTML = @LTP_GENHTML@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINTAINER_CFLAGS = @MAINTAINER_CFLAGS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGO_REQ_VERSION = @PANGO_REQ_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SHTOOL = @SHTOOL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +XCOMPOSITE_REQ_VERSION = @XCOMPOSITE_REQ_VERSION@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +installed_test_metadir = @installed_test_metadir@ +installed_testdir = @installed_testdir@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +common_ldadd = $(top_builddir)/clutter/libmutter-clutter-@CLUTTER_API_VERSION@.la +LDADD = $(common_ldadd) $(CLUTTER_LIBS) $(LIBM) +AM_CFLAGS = $(CLUTTER_CFLAGS) +AM_CPPFLAGS = \ + -DG_DISABLE_SINGLE_INCLUDES \ + -DGLIB_DISABLE_DEPRECATION_WARNINGS \ + -DCOGL_DISABLE_DEPRECATION_WARNINGS \ + -DCLUTTER_DISABLE_DEPRECATION_WARNINGS \ + -DTESTS_DATA_DIR=\""$(top_srcdir)/tests/data/"\" \ + -I$(top_srcdir)/../cogl \ + -I$(top_builddir)/../cogl \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + -I$(top_srcdir)/clutter \ + -I$(top_builddir)/clutter + +test_picking_SOURCES = test-picking.c +test_text_perf_SOURCES = test-text-perf.c +test_state_SOURCES = test-state.c +test_state_hidden_SOURCES = test-state-hidden.c +test_state_pick_SOURCES = test-state-pick.c +test_state_interactive_SOURCES = test-state-interactive.c +test_state_mini_SOURCES = test-state-mini.c +EXTRA_DIST = Makefile-retrospect Makefile-tests create-report.rb test-common.h +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/performance/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/performance/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +test-picking$(EXEEXT): $(test_picking_OBJECTS) $(test_picking_DEPENDENCIES) $(EXTRA_test_picking_DEPENDENCIES) + @rm -f test-picking$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_picking_OBJECTS) $(test_picking_LDADD) $(LIBS) + +test-state$(EXEEXT): $(test_state_OBJECTS) $(test_state_DEPENDENCIES) $(EXTRA_test_state_DEPENDENCIES) + @rm -f test-state$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_state_OBJECTS) $(test_state_LDADD) $(LIBS) + +test-state-hidden$(EXEEXT): $(test_state_hidden_OBJECTS) $(test_state_hidden_DEPENDENCIES) $(EXTRA_test_state_hidden_DEPENDENCIES) + @rm -f test-state-hidden$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_state_hidden_OBJECTS) $(test_state_hidden_LDADD) $(LIBS) + +test-state-interactive$(EXEEXT): $(test_state_interactive_OBJECTS) $(test_state_interactive_DEPENDENCIES) $(EXTRA_test_state_interactive_DEPENDENCIES) + @rm -f test-state-interactive$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_state_interactive_OBJECTS) $(test_state_interactive_LDADD) $(LIBS) + +test-state-mini$(EXEEXT): $(test_state_mini_OBJECTS) $(test_state_mini_DEPENDENCIES) $(EXTRA_test_state_mini_DEPENDENCIES) + @rm -f test-state-mini$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_state_mini_OBJECTS) $(test_state_mini_LDADD) $(LIBS) + +test-state-pick$(EXEEXT): $(test_state_pick_OBJECTS) $(test_state_pick_DEPENDENCIES) $(EXTRA_test_state_pick_DEPENDENCIES) + @rm -f test-state-pick$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_state_pick_OBJECTS) $(test_state_pick_LDADD) $(LIBS) + +test-text-perf$(EXEEXT): $(test_text_perf_OBJECTS) $(test_text_perf_DEPENDENCIES) $(EXTRA_test_text_perf_DEPENDENCIES) + @rm -f test-text-perf$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_text_perf_OBJECTS) $(test_text_perf_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-picking.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-state-hidden.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-state-interactive.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-state-mini.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-state-pick.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-state.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-text-perf.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ + clean-checkPROGRAMS clean-generic clean-libtool cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +perf-report: check + +check: + for a in $(noinst_PROGRAMS);do ./$$a;done;true + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/clutter/tests/performance/create-report.rb b/clutter/tests/performance/create-report.rb new file mode 100755 index 0000000..43defc4 --- /dev/null +++ b/clutter/tests/performance/create-report.rb @@ -0,0 +1,179 @@ +#!/usr/bin/env ruby +# +# ruby program to generate a performance report in PDF/png over git revisions, based on work +# originally done for gegl by pippin@gimp.org, the original program is in the public domain. + +require 'cairo' + +def cairo_surface(w,h) + surface = Cairo::PDFSurface.new("report.pdf", w,h) + cr = Cairo::Context.new(surface) + yield(cr) +end + +class Database + + def initialize() + @vals = Hash.new + @runs = Array.new + @colors = [ + [0,1,0, 0.8], + [0,1,1, 0.8], + [1,0,0, 0.8], + [1,0,1, 0.8], + [1,1,0, 0.8], + #[0.5,0.5,0.5,0.8], + # gray doesnt have sufficient contrast against background + [0.5,0.5,1, 0.8], + [0.5,1,0.5, 0.8], + [0.5,1,1, 0.8], + [1,0.5,0.5, 0.8], + [1,0.5,1, 0.8], + [1,1,0.5, 0.8], + [1,1,1, 0.8], + ] + @width = 1800 + @height = 500 + + @marginlx = 10 + @marginrx = 180 + @rgap = 40 + @marginy = 10 + end + def val_max(key) + max=0 + @runs.each { |run| + val = @vals[key][run] + if val and val > max + max = val + end + } + max + end + def val_min(key) + min=9999990 + @runs.each { |run| + val = @vals[key][run] + min = val if val and val < min + } + #min + 0 # this shows the relative noise in measurements better + end + def add_run(run) + @runs = @runs + [run] + end + def add_entry(run, name, val) + if !@vals[name] + @vals[name]=Hash.new + end + # check if there is an existing value, + # and perhaps have different behaviors + # associated with + @vals[name][run] = val.to_f + end + + def drawbg cr + cr.set_source_rgba(0.2, 0.2, 0.2, 1) + cr.paint + + i=0 + @runs.each { |run| + if i % 2 == 1 + cr.move_to 1.0 * i / @runs.length * (@width - @marginlx-@marginrx) + @marginlx, 0 * (@height - @marginy*2) + @marginy + cr.line_to 1.0 * i / @runs.length * (@width - @marginlx-@marginrx) + @marginlx, 1.0 * (@height - @marginy*2) + @marginy + cr.rel_line_to(1.0 / @runs.length * (@width - @marginlx-@marginrx), 0) + cr.rel_line_to(0, -(@height - @marginy*2)) + + cr.set_source_rgba([0.25,0.25,0.25,1]) + cr.fill + end + i+=1 + } + end + + def drawtext cr + i = 0 + @runs.each { |run| + y = i * 10 + 20 + while y > @height - @marginy + y = y - @height + @marginy + 10 + end + cr.move_to 1.0 * i / @runs.length * (@width - @marginlx-@marginrx) + @marginlx, y + + cr.set_source_rgba(0.6,0.6,0.6,1) + cr.show_text(run[0..6]) + i+=1 + } + end + + def draw_limits cr, key + cr.move_to @width - @marginrx + @rgap, 20 + cr.set_source_rgba(1.0, 1.0, 1.0, 1.0) + cr.show_text(" #{val_max(key)} ") + cr.move_to @width - @marginrx + @rgap, @height - @marginy + cr.show_text(" #{val_min(key)} ") + end + + def draw_val cr, key, valno + min = val_min(key) + max = val_max(key) + + cr.set_source_rgba(@colors[valno]) + cr.move_to(@width - @marginrx + @rgap, valno * 14 + @marginy + 20) + cr.show_text(key) + + cr.line_width = 2 + cr.new_path + + i = 0 + @runs.each { |run| + val = @vals[key][run] + if val + cr.line_to 1.0 * (i+0.5) / @runs.length * (@width - @marginlx-@marginrx) + @marginlx, + (1.0 - ((val-min) * 1.0 / (max - min))) * (@height - @marginy*2) + @marginy + end + i = i + 1 + } + cr.stroke + end + + def create_report + cairo_surface(@width, @height) { |cr| + drawbg cr + valno = 0 + @vals.each { |key, value| + draw_val cr, key, valno + valno += 1 + } + drawtext cr + cr.target.write_to_png("report.png") + + valno = 0 + @vals.each { |key, value| + cr.show_page + drawbg cr + draw_val cr, key, valno + drawtext cr + draw_limits cr, key + valno += 1 + } + } + end +end + +generator = Database.new + +items = File.open('jobs').each { |rev| + rev.strip! + generator.add_run(rev) + filename = "reports/" + rev; + if File.exist?(filename) + File.open(filename).each { |line| + if line =~ /^@ (.*):(.*)/ + generator.add_entry(rev, $1, $2) + end + } + end +} + +generator.create_report diff --git a/clutter/tests/performance/test-common.h b/clutter/tests/performance/test-common.h new file mode 100644 index 0000000..b0bed10 --- /dev/null +++ b/clutter/tests/performance/test-common.h @@ -0,0 +1,130 @@ +#include +#include +#include + +static GTimer *testtimer = NULL; +static gint testframes = 0; +static float testmaxtime = 1.0; + +/* initialize environment to be suitable for fps testing */ +void clutter_perf_fps_init (void) +{ + /* Force not syncing to vblank, we want free-running maximum FPS */ + g_setenv ("vblank_mode", "0", FALSE); + g_setenv ("CLUTTER_VBLANK", "none", FALSE); + + /* also overrride internal default FPS */ + g_setenv ("CLUTTER_DEFAULT_FPS", "1000", FALSE); + + if (g_getenv ("CLUTTER_PERFORMANCE_TEST_DURATION")) + testmaxtime = atof(g_getenv("CLUTTER_PERFORMANCE_TEST_DURATION")); + else + testmaxtime = 10.0; + + g_random_set_seed (12345678); +} + +static void perf_stage_paint_cb (ClutterStage *stage, gpointer *data); +static gboolean perf_fake_mouse_cb (gpointer stage); + +void clutter_perf_fps_start (ClutterStage *stage) +{ + g_signal_connect (stage, "paint", G_CALLBACK (perf_stage_paint_cb), NULL); +} + +void clutter_perf_fake_mouse (ClutterStage *stage) +{ + clutter_threads_add_timeout (1000/60, perf_fake_mouse_cb, stage); +} + +void clutter_perf_fps_report (const gchar *id) +{ + g_print ("\n@ %s: %.2f fps \n", + id, testframes / g_timer_elapsed (testtimer, NULL)); +} + +static void perf_stage_paint_cb (ClutterStage *stage, gpointer *data) +{ + if (!testtimer) + testtimer = g_timer_new (); + testframes ++; + if (g_timer_elapsed (testtimer, NULL) > testmaxtime) + { + clutter_main_quit (); + } +} + +static void wrap (gfloat *value, gfloat min, gfloat max) +{ + if (*value > max) + *value = min; + else if (*value < min) + *value = max; +} + +static gboolean perf_fake_mouse_cb (gpointer stage) +{ + ClutterEvent *event = clutter_event_new (CLUTTER_MOTION); + static ClutterInputDevice *device = NULL; + int i; + static float x = 0.0; + static float y = 0.0; + static float xd = 0.0; + static float yd = 0.0; + static gboolean inited = FALSE; + + gfloat w, h; + + if (!inited) /* XXX: + force clutter to do handle our motion events, + by forcibly updating the input device's state + this shoudl be possible to do in a better + manner in the future, a versioning check + will have to be added when this is possible + without a hack... and the means to do the + hack is deprecated + */ + { + ClutterEvent *event2 = clutter_event_new (CLUTTER_ENTER); + device = clutter_device_manager_get_core_device (clutter_device_manager_get_default (), CLUTTER_POINTER_DEVICE); + + event2->crossing.stage = stage; + event2->crossing.source = stage; + event2->crossing.x = 10; + event2->crossing.y = 10; + event2->crossing.device = device; + event2->crossing.related = NULL; + + clutter_input_device_update_from_event (device, event2, TRUE); + + clutter_event_put (event2); + clutter_event_free (event2); + inited = TRUE; + } + + clutter_actor_get_size (stage, &w, &h); + event->motion.stage = stage; + event->motion.device = device; + + /* called about every 60fps, and do 10 picks per stage */ + for (i = 0; i < 10; i++) + { + event->motion.x = x; + event->motion.y = y; + + clutter_event_put (event); + + x += xd; + y += yd; + xd += g_random_double_range (-0.1, 0.1); + yd += g_random_double_range (-0.1, 0.1); + + wrap (&x, 0, w); + wrap (&y, 0, h); + + xd = CLAMP(xd, -1.3, 1.3); + yd = CLAMP(yd, -1.3, 1.3); + } + clutter_event_free (event); + return G_SOURCE_CONTINUE; +} diff --git a/clutter/tests/performance/test-picking.c b/clutter/tests/performance/test-picking.c new file mode 100644 index 0000000..af59600 --- /dev/null +++ b/clutter/tests/performance/test-picking.c @@ -0,0 +1,134 @@ + +#include +#include +#include +#include "test-common.h" + +#define N_ACTORS 100 +#define N_EVENTS 5 + +static gint n_actors = N_ACTORS; +static gint n_events = N_EVENTS; + +static GOptionEntry entries[] = { + { + "num-actors", 'a', + 0, + G_OPTION_ARG_INT, &n_actors, + "Number of actors", "ACTORS" + }, + { + "num-events", 'e', + 0, + G_OPTION_ARG_INT, &n_events, + "Number of events", "EVENTS" + }, + { NULL } +}; + +static gboolean +motion_event_cb (ClutterActor *actor, ClutterEvent *event, gpointer user_data) +{ + return FALSE; +} + +static void +do_events (ClutterActor *stage) +{ + glong i; + static gdouble angle = 0; + + for (i = 0; i < n_events; i++) + { + angle += (2.0 * G_PI) / (gdouble)n_actors; + while (angle > G_PI * 2.0) + angle -= G_PI * 2.0; + + /* If we synthesized events, they would be motion compressed; + * calling get_actor_at_position() doesn't have that problem + */ + clutter_stage_get_actor_at_pos (CLUTTER_STAGE (stage), + CLUTTER_PICK_REACTIVE, + 256.0 + 206.0 * cos (angle), + 256.0 + 206.0 * sin (angle)); + } +} + +static gboolean queue_redraw (gpointer data) +{ + ClutterActor *stage = CLUTTER_ACTOR (data); + clutter_actor_queue_redraw (stage); + do_events (stage); + return TRUE; +} + +int +main (int argc, char **argv) +{ + glong i; + gdouble angle; + ClutterColor color = { 0x00, 0x00, 0x00, 0xff }; + ClutterActor *stage, *rect; + + clutter_perf_fps_init (); + + if (CLUTTER_INIT_SUCCESS != + clutter_init_with_args (&argc, &argv, + NULL, + entries, + NULL, + NULL)) + { + g_warning ("Failed to initialize clutter"); + return -1; + } + + stage = clutter_stage_new (); + clutter_actor_set_size (stage, 512, 512); + clutter_stage_set_color (CLUTTER_STAGE (stage), CLUTTER_COLOR_Black); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Picking Performance"); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + printf ("Picking performance test with " + "%d actors and %d events per frame\n", + n_actors, + n_events); + + for (i = n_actors - 1; i >= 0; i--) + { + angle = ((2.0 * G_PI) / (gdouble) n_actors) * i; + + color.red = (1.0 - ABS ((MAX (0, MIN (n_actors/2.0 + 0, i))) / + (gdouble)(n_actors/4.0) - 1.0)) * 255.0; + color.green = (1.0 - ABS ((MAX (0, MIN (n_actors/2.0 + 0, + fmod (i + (n_actors/3.0)*2, n_actors)))) / + (gdouble)(n_actors/4) - 1.0)) * 255.0; + color.blue = (1.0 - ABS ((MAX (0, MIN (n_actors/2.0 + 0, + fmod ((i + (n_actors/3.0)), n_actors)))) / + (gdouble)(n_actors/4.0) - 1.0)) * 255.0; + + rect = clutter_rectangle_new_with_color (&color); + clutter_actor_set_size (rect, 100, 100); + clutter_actor_set_anchor_point_from_gravity (rect, + CLUTTER_GRAVITY_CENTER); + clutter_actor_set_position (rect, + 256 + 206 * cos (angle), + 256 + 206 * sin (angle)); + clutter_actor_set_reactive (rect, TRUE); + g_signal_connect (rect, "motion-event", + G_CALLBACK (motion_event_cb), NULL); + + clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); + } + + clutter_actor_show (stage); + + clutter_perf_fps_start (CLUTTER_STAGE (stage)); + clutter_threads_add_idle (queue_redraw, stage); + clutter_main (); + clutter_perf_fps_report ("test-picking"); + + return 0; +} + + diff --git a/clutter/tests/performance/test-state-hidden.c b/clutter/tests/performance/test-state-hidden.c new file mode 100644 index 0000000..64911b4 --- /dev/null +++ b/clutter/tests/performance/test-state-hidden.c @@ -0,0 +1,150 @@ +#include +#include +#include +#include +#include "test-common.h" + +#define STAGE_WIDTH 160 +#define STAGE_HEIGHT 120 + +#define ACTOR_WIDTH 8 +#define ACTOR_HEIGHT 8 + +#define COLS (STAGE_WIDTH/ACTOR_WIDTH) +#define ROWS (STAGE_HEIGHT/ACTOR_HEIGHT) +#define TOTAL (ROWS*COLS) + + +static void completed (ClutterState *state, + gpointer data) +{ + if (g_str_equal (clutter_state_get_state (state), "right")) + { + /* skip straight to left state when reaching right */ + clutter_state_warp_to_state (state, "left"); + } + else if (g_str_equal (clutter_state_get_state (state), "active")) + clutter_state_set_state (state, "right"); + else + { + clutter_state_set_state (state, "active"); + } +} + +static ClutterActor *new_rect (gint r, + gint g, + gint b, + gint a) +{ + ClutterColor *color = clutter_color_new (r, g, b, a); + ClutterActor *group = clutter_group_new (); + ClutterActor *rectangle = clutter_rectangle_new_with_color (color); + + gchar *file = g_build_filename (TESTS_DATA_DIR, "redhand.png", NULL); + + g_free (file); + clutter_actor_set_size (rectangle, ACTOR_WIDTH,ACTOR_HEIGHT); + clutter_color_free (color); + clutter_container_add (CLUTTER_CONTAINER (group), rectangle, NULL); + return group; +} + +gint +main (gint argc, + gchar **argv) +{ + ClutterActor *stage; + ClutterActor *group; + ClutterState *layout_state; + gint i; + + clutter_perf_fps_init (); + if (CLUTTER_INIT_SUCCESS != clutter_init (&argc, &argv)) + g_error ("Failed to initialize Clutter"); + + stage = clutter_stage_new (); + group = clutter_group_new (); + layout_state = clutter_state_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "State Performance [hidden]"); + clutter_stage_set_color (CLUTTER_STAGE (stage), CLUTTER_COLOR_Black); + clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + for (i=0; i +#include +#include +#include +#include "test-common.h" + +#define STAGE_WIDTH 800 +#define STAGE_HEIGHT 600 + +#define ACTOR_WIDTH 64 +#define ACTOR_HEIGHT 64 + +#define COLS (STAGE_WIDTH/ACTOR_WIDTH) +#define ROWS (STAGE_HEIGHT/ACTOR_HEIGHT) +#define TOTAL (ROWS*COLS) + + +static gboolean press_event (ClutterActor *actor, + ClutterEvent *event, + gpointer user_data) +{ + ClutterState *state = CLUTTER_STATE (user_data); + clutter_state_set_state (state, "right"); + return TRUE; +} + +static gboolean release_event (ClutterActor *actor, + ClutterEvent *event, + gpointer user_data) +{ + ClutterState *state = CLUTTER_STATE (user_data); + clutter_state_set_state (state, "active"); + return TRUE; +} + +static gboolean enter_event (ClutterActor *actor, + ClutterEvent *event, + gpointer user_data) +{ + ClutterState *state = CLUTTER_STATE (user_data); + clutter_state_set_state (state, "hover"); + return TRUE; +} + +static gboolean leave_event (ClutterActor *actor, + ClutterEvent *event, + gpointer user_data) +{ + ClutterState *state = CLUTTER_STATE (user_data); + clutter_state_set_state (state, "normal"); + return TRUE; +} + +static void completed (ClutterState *state, + gpointer data) +{ + g_print ("Completed transitioning to state: %s\n", + clutter_state_get_state (state)); + + if (g_str_equal (clutter_state_get_state (state), "right")) + { + /* skip straight to left state when reaching right */ + clutter_state_warp_to_state (state, "left"); + } +} + +static ClutterActor *new_rect (gint r, + gint g, + gint b, + gint a) +{ + GError *error = NULL; + ClutterColor *color = clutter_color_new (r, g, b, a); + ClutterActor *group = clutter_group_new (); + ClutterActor *rectangle = clutter_rectangle_new_with_color (color); + ClutterActor *hand = NULL; + + gchar *file = g_build_filename (TESTS_DATA_DIR, "redhand.png", NULL); + + hand = clutter_texture_new_from_file (file, &error); + if (rectangle == NULL) + g_error ("image load failed: %s", error->message); + g_free (file); + clutter_actor_set_size (hand, ACTOR_WIDTH,ACTOR_HEIGHT); + + clutter_actor_set_size (rectangle, ACTOR_WIDTH,ACTOR_HEIGHT); + clutter_color_free (color); + clutter_container_add (CLUTTER_CONTAINER (group), rectangle, hand, NULL); + return group; +} + +gint +main (gint argc, + gchar **argv) +{ + ClutterActor *stage; + ClutterState *layout_state; + gint i; + clutter_perf_fps_init (); + if (CLUTTER_INIT_SUCCESS != clutter_init (&argc, &argv)) + g_error ("Failed to initialize Clutter"); + + stage = clutter_stage_new (); + layout_state = clutter_state_new (); + clutter_stage_set_color (CLUTTER_STAGE (stage), CLUTTER_COLOR_Black); + clutter_stage_set_title (CLUTTER_STAGE (stage), "State Performance [interactive]"); + clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT); + + g_signal_connect (stage, "button-press-event", + G_CALLBACK (press_event), layout_state); + g_signal_connect (stage, "button-release-event", + G_CALLBACK (release_event), layout_state); + + for (i=0; i +#include +#include +#include +#include "test-common.h" + +#define STAGE_WIDTH 160 +#define STAGE_HEIGHT 120 + +#define ACTOR_WIDTH 8 +#define ACTOR_HEIGHT 8 + +#define COLS (STAGE_WIDTH/ACTOR_WIDTH) +#define ROWS (STAGE_HEIGHT/ACTOR_HEIGHT) +#define TOTAL (ROWS*COLS) + + +static void completed (ClutterState *state, + gpointer data) +{ + if (g_str_equal (clutter_state_get_state (state), "right")) + { + /* skip straight to left state when reaching right */ + clutter_state_warp_to_state (state, "left"); + } + else if (g_str_equal (clutter_state_get_state (state), "active")) + clutter_state_set_state (state, "right"); + else + { + clutter_state_set_state (state, "active"); + } +} + +static ClutterActor *new_rect (gint r, + gint g, + gint b, + gint a) +{ + GError *error = NULL; + ClutterColor *color = clutter_color_new (r, g, b, a); + ClutterActor *group = clutter_group_new (); + ClutterActor *rectangle = clutter_rectangle_new_with_color (color); + ClutterActor *hand = NULL; + + gchar *file = g_build_filename (TESTS_DATA_DIR, "redhand.png", NULL); + + hand = clutter_texture_new_from_file (file, &error); + if (rectangle == NULL) + g_error ("image load failed: %s", error->message); + g_free (file); + clutter_actor_set_size (hand, ACTOR_WIDTH,ACTOR_HEIGHT); + + clutter_actor_set_size (rectangle, ACTOR_WIDTH,ACTOR_HEIGHT); + clutter_color_free (color); + clutter_container_add (CLUTTER_CONTAINER (group), rectangle, hand, NULL); + return group; +} + +gint +main (gint argc, + gchar **argv) +{ + ClutterActor *stage; + ClutterState *layout_state; + gint i; + + clutter_perf_fps_init (); + if (CLUTTER_INIT_SUCCESS != clutter_init (&argc, &argv)) + g_error ("Failed to initialize Clutter"); + + stage = clutter_stage_new (); + layout_state = clutter_state_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "State Performance [mini]"); + clutter_stage_set_color (CLUTTER_STAGE (stage), CLUTTER_COLOR_Black); + clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + for (i=0; i +#include +#include +#include +#include "test-common.h" + +static gint times = 16; + +#define STAGE_WIDTH 800 +#define STAGE_HEIGHT 600 + +#define ACTOR_WIDTH 64 +#define ACTOR_HEIGHT 64 + +#define COLS (STAGE_WIDTH/ACTOR_WIDTH) +#define ROWS (STAGE_HEIGHT/ACTOR_HEIGHT) +#define TOTAL (ROWS*COLS) + + +static void completed (ClutterState *state, + gpointer data) +{ + if (g_str_equal (clutter_state_get_state (state), "right")) + { + /* skip straight to left state when reaching right */ + clutter_state_warp_to_state (state, "left"); + } + else if (g_str_equal (clutter_state_get_state (state), "active")) + clutter_state_set_state (state, "right"); + else + { + clutter_state_set_state (state, "active"); + } + times --; + if (times <=0) + clutter_main_quit (); +} + +static ClutterActor *new_rect (gint r, + gint g, + gint b, + gint a) +{ + GError *error = NULL; + ClutterColor *color = clutter_color_new (r, g, b, a); + ClutterActor *group = clutter_group_new (); + ClutterActor *rectangle = clutter_rectangle_new_with_color (color); + ClutterActor *hand = NULL; + + gchar *file = g_build_filename (TESTS_DATA_DIR, "redhand.png", NULL); + + hand = clutter_texture_new_from_file (file, &error); + if (rectangle == NULL) + g_error ("image load failed: %s", error->message); + g_free (file); + clutter_actor_set_size (hand, ACTOR_WIDTH,ACTOR_HEIGHT); + + clutter_actor_set_size (rectangle, ACTOR_WIDTH,ACTOR_HEIGHT); + clutter_color_free (color); + clutter_container_add (CLUTTER_CONTAINER (group), rectangle, hand, NULL); + return group; +} + +gint +main (gint argc, + gchar **argv) +{ + ClutterActor *stage; + ClutterState *layout_state; + gint i; + + clutter_perf_fps_init (); + if (CLUTTER_INIT_SUCCESS != clutter_init (&argc, &argv)) + g_error ("Failed to initialize Clutter"); + + stage = clutter_stage_new (); + layout_state = clutter_state_new (); + clutter_stage_set_color (CLUTTER_STAGE (stage), CLUTTER_COLOR_Black); + clutter_stage_set_title (CLUTTER_STAGE (stage), "State Performance [pick]"); + clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + for (i=0; i +#include +#include +#include +#include "test-common.h" + +static gint times = 16; + +#define STAGE_WIDTH 800 +#define STAGE_HEIGHT 600 + +#define ACTOR_WIDTH 64 +#define ACTOR_HEIGHT 64 + +#define COLS (STAGE_WIDTH/ACTOR_WIDTH) +#define ROWS (STAGE_HEIGHT/ACTOR_HEIGHT) +#define TOTAL (ROWS*COLS) + + +static void completed (ClutterState *state, + gpointer data) +{ + if (g_str_equal (clutter_state_get_state (state), "right")) + { + /* skip straight to left state when reaching right */ + clutter_state_warp_to_state (state, "left"); + } + else if (g_str_equal (clutter_state_get_state (state), "active")) + clutter_state_set_state (state, "right"); + else + { + clutter_state_set_state (state, "active"); + } + times --; + if (times <=0) + clutter_main_quit (); +} + +static ClutterActor *new_rect (gint r, + gint g, + gint b, + gint a) +{ + GError *error = NULL; + ClutterColor *color = clutter_color_new (r, g, b, a); + ClutterActor *group = clutter_group_new (); + ClutterActor *rectangle = clutter_rectangle_new_with_color (color); + ClutterActor *hand = NULL; + + gchar *file = g_build_filename (TESTS_DATA_DIR, "redhand.png", NULL); + + hand = clutter_texture_new_from_file (file, &error); + if (rectangle == NULL) + g_error ("image load failed: %s", error->message); + g_free (file); + clutter_actor_set_size (hand, ACTOR_WIDTH,ACTOR_HEIGHT); + + clutter_actor_set_size (rectangle, ACTOR_WIDTH,ACTOR_HEIGHT); + clutter_color_free (color); + clutter_container_add (CLUTTER_CONTAINER (group), rectangle, hand, NULL); + return group; +} + +gint +main (gint argc, + gchar **argv) +{ + ClutterActor *stage; + ClutterState *layout_state; + gint i; + + clutter_perf_fps_init (); + if (CLUTTER_INIT_SUCCESS != clutter_init (&argc, &argv)) + g_error ("Failed to initialize Clutter"); + + stage = clutter_stage_new (); + layout_state = clutter_state_new (); + clutter_stage_set_color (CLUTTER_STAGE (stage), CLUTTER_COLOR_Black); + clutter_stage_set_title (CLUTTER_STAGE (stage), "State Performance"); + clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + for (i=0; i + +#include +#include +#include "test-common.h" + +#define STAGE_WIDTH 800 +#define STAGE_HEIGHT 600 + +static int font_size; +static int n_chars; +static int rows, cols; + +static gboolean +queue_redraw (gpointer stage) +{ + clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); + + return G_SOURCE_CONTINUE; +} + +static gunichar +get_character (int ch) +{ + int total_letters = 0; + int i; + + static const struct + { + gunichar first_letter; + int n_letters; + } + ranges[] = + { + { 'a', 26 }, /* lower case letters */ + { 'A', 26 }, /* upper case letters */ + { '0', 10 }, /* digits */ + { 0x410, 0x40 }, /* cyrillic alphabet */ + { 0x3b1, 18 } /* greek alphabet */ + }; + + for (i = 0; i < G_N_ELEMENTS (ranges); i++) + total_letters += ranges[i].n_letters; + + ch %= total_letters; + + for (i = 0; i < G_N_ELEMENTS (ranges) - 1; i++) + if (ch < ranges[i].n_letters) + return ch + ranges[i].first_letter; + else + ch -= ranges[i].n_letters; + + return ch + ranges[i].first_letter; +} + +static ClutterActor * +create_label (void) +{ + ClutterColor label_color = { 0xff, 0xff, 0xff, 0xff }; + ClutterActor *label; + char *font_name; + GString *str; + int i; + + font_name = g_strdup_printf ("Monospace %dpx", font_size); + + str = g_string_new (NULL); + for (i = 0; i < n_chars; i++) + g_string_append_unichar (str, get_character (i)); + + label = clutter_text_new_with_text (font_name, str->str); + clutter_text_set_color (CLUTTER_TEXT (label), &label_color); + + g_free (font_name); + g_string_free (str, TRUE); + + return label; +} + +int +main (int argc, char *argv[]) +{ + ClutterActor *stage; + ClutterColor stage_color = { 0x00, 0x00, 0x00, 0xff }; + ClutterActor *label; + int w, h; + int row, col; + float scale = 1.0f; + + clutter_perf_fps_init (); + + if (CLUTTER_INIT_SUCCESS != clutter_init (&argc, &argv)) + g_error ("Failed to initialize Clutter"); + + if (argc != 3) + { + //g_printerr ("Usage test-text-perf FONT_SIZE N_CHARS\n"); + //exit (1); + font_size = 30; + n_chars = 400; + } + else + { + font_size = atoi (argv[1]); + n_chars = atoi (argv[2]); + } + + g_print ("Monospace %dpx, string length = %d\n", font_size, n_chars); + + stage = clutter_stage_new (); + clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT); + clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Text Performance"); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + label = create_label (); + w = clutter_actor_get_width (label); + h = clutter_actor_get_height (label); + + /* If the label is too big to fit on the stage then scale it so that + it will fit */ + if (w > STAGE_WIDTH || h > STAGE_HEIGHT) + { + float x_scale = STAGE_WIDTH / (float) w; + float y_scale = STAGE_HEIGHT / (float) h; + + if (x_scale < y_scale) + { + scale = x_scale; + cols = 1; + rows = STAGE_HEIGHT / (h * scale); + } + else + { + scale = y_scale; + cols = STAGE_WIDTH / (w * scale); + rows = 1; + } + + g_print ("Text scaled by %f to fit on the stage\n", scale); + } + else + { + cols = STAGE_WIDTH / w; + rows = STAGE_HEIGHT / h; + } + + clutter_actor_destroy (label); + + for (row=0; row&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@BUILD_COGL_PATH_TRUE@am__append_1 = cogl-path +@BUILD_COGL_PANGO_TRUE@am__append_2 = cogl-pango +@BUILD_COGL_GLES2_TRUE@am__append_3 = cogl-gles2 +subdir = . +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/build/autotools/as-compiler-flag.m4 \ + $(top_srcdir)/build/autotools/introspection.m4 \ + $(top_srcdir)/build/autotools/libtool.m4 \ + $(top_srcdir)/build/autotools/ltoptions.m4 \ + $(top_srcdir)/build/autotools/ltsugar.m4 \ + $(top_srcdir)/build/autotools/ltversion.m4 \ + $(top_srcdir)/build/autotools/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(am__DIST_COMMON) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = cogl-config.h cogl-mutter-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + cscope distdir dist dist-all distcheck +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ + $(LISP)cogl-config.h.in cogl-mutter-config.h.in +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +CSCOPE = cscope +DIST_SUBDIRS = test-fixtures cogl cogl-path cogl-pango cogl-gles2 \ + tests +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/cogl-config.h.in \ + $(srcdir)/cogl-mutter-config.h.in $(top_srcdir)/build/compile \ + $(top_srcdir)/build/config.guess \ + $(top_srcdir)/build/config.sub $(top_srcdir)/build/install-sh \ + $(top_srcdir)/build/ltmain.sh $(top_srcdir)/build/missing \ + build/compile build/config.guess build/config.sub \ + build/install-sh build/ltmain.sh build/missing +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +GZIP_ENV = --best +DIST_ARCHIVES = $(distdir).tar.xz +DIST_TARGETS = dist-xz +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_REQ_VERSION = @CAIRO_REQ_VERSION@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COGL_1_MICRO_VERSION = @COGL_1_MICRO_VERSION@ +COGL_1_MINOR_VERSION = @COGL_1_MINOR_VERSION@ +COGL_1_VERSION = @COGL_1_VERSION@ +COGL_API_VERSION = @COGL_API_VERSION@ +COGL_API_VERSION_AM = @COGL_API_VERSION_AM@ +COGL_DEBUG_CFLAGS = @COGL_DEBUG_CFLAGS@ +COGL_DEFAULT_DRIVER = @COGL_DEFAULT_DRIVER@ +COGL_DEP_CFLAGS = @COGL_DEP_CFLAGS@ +COGL_DEP_GL_CFLAGS = @COGL_DEP_GL_CFLAGS@ +COGL_DEP_GL_LIBS = @COGL_DEP_GL_LIBS@ +COGL_DEP_LIBS = @COGL_DEP_LIBS@ +COGL_EGL_INCLUDES = @COGL_EGL_INCLUDES@ +COGL_EXTRA_CFLAGS = @COGL_EXTRA_CFLAGS@ +COGL_EXTRA_LDFLAGS = @COGL_EXTRA_LDFLAGS@ +COGL_GLES1_LIBNAME = @COGL_GLES1_LIBNAME@ +COGL_GLES2_LIBNAME = @COGL_GLES2_LIBNAME@ +COGL_GL_LIBNAME = @COGL_GL_LIBNAME@ +COGL_GST_DEP_CFLAGS = @COGL_GST_DEP_CFLAGS@ +COGL_GST_DEP_LIBS = @COGL_GST_DEP_LIBS@ +COGL_LT_AGE = @COGL_LT_AGE@ +COGL_LT_CURRENT = @COGL_LT_CURRENT@ +COGL_LT_RELEASE = @COGL_LT_RELEASE@ +COGL_LT_REVISION = @COGL_LT_REVISION@ +COGL_MAJOR_VERSION = @COGL_MAJOR_VERSION@ +COGL_MICRO_VERSION = @COGL_MICRO_VERSION@ +COGL_MINOR_VERSION = @COGL_MINOR_VERSION@ +COGL_PANGO_DEP_CFLAGS = @COGL_PANGO_DEP_CFLAGS@ +COGL_PANGO_DEP_LIBS = @COGL_PANGO_DEP_LIBS@ +COGL_PANGO_PKG_REQUIRES = @COGL_PANGO_PKG_REQUIRES@ +COGL_PKG_REQUIRES = @COGL_PKG_REQUIRES@ +COGL_RELEASE_STATUS = @COGL_RELEASE_STATUS@ +COGL_VERSION = @COGL_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMMY_CFLAGS = @DUMMY_CFLAGS@ +DUMMY_LIBS = @DUMMY_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDKPIXBUF_PREFIX = @GDKPIXBUF_PREFIX@ +GDK_PIXBUF_REQ_VERSION = @GDK_PIXBUF_REQ_VERSION@ +GI_REQ_VERSION = @GI_REQ_VERSION@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ_VERSION = @GLIB_REQ_VERSION@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +HAVE_GL = @HAVE_GL@ +HAVE_GLES1 = @HAVE_GLES1@ +HAVE_GLES2 = @HAVE_GLES2@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINTAINER_CFLAGS = @MAINTAINER_CFLAGS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGOCAIRO_REQ_VERSION = @PANGOCAIRO_REQ_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +UPROF_REQ_VERSION = @UPROF_REQ_VERSION@ +VERSION = @VERSION@ +WAYLAND_SERVER_CFLAGS = @WAYLAND_SERVER_CFLAGS@ +WAYLAND_SERVER_LIBS = @WAYLAND_SERVER_LIBS@ +WAYLAND_SERVER_REQ_VERSION = @WAYLAND_SERVER_REQ_VERSION@ +XCOMPOSITE_REQ_VERSION = @XCOMPOSITE_REQ_VERSION@ +XFIXES_REQ_VERSION = @XFIXES_REQ_VERSION@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = test-fixtures cogl $(am__append_1) $(am__append_2) \ + $(am__append_3) tests +ACLOCAL_AMFLAGS = -I build/autotools ${ACLOCAL_FLAGS} +EXTRA_DIST = \ + config-custom.h + + +# .changelog expects these to be initializes +CLEANFILES = +DISTCLEANFILES = +DISTCHECK_CONFIGURE_FLAGS = \ + --enable-maintainer-flags \ + --enable-profile \ + --enable-gles2 \ + --enable-gl \ + --enable-xlib-egl-platform \ + --enable-wayland-egl-platform \ + --enable-glx \ + --enable-wayland-egl-server \ + --enable-cogl-gst + +all: cogl-config.h cogl-mutter-config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +cogl-config.h: stamp-h1 + @test -f $@ || rm -f stamp-h1 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 + +stamp-h1: $(srcdir)/cogl-config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status cogl-config.h +$(srcdir)/cogl-config.h.in: $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +cogl-mutter-config.h: stamp-h2 + @test -f $@ || rm -f stamp-h2 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h2 + +stamp-h2: $(srcdir)/cogl-mutter-config.h.in $(top_builddir)/config.status + @rm -f stamp-h2 + cd $(top_builddir) && $(SHELL) ./config.status cogl-mutter-config.h + +distclean-hdr: + -rm -f cogl-config.h stamp-h1 cogl-mutter-config.h stamp-h2 + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) +clean-cscope: + -rm -f cscope.files +cscope.files: clean-cscope cscopelist +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz + $(am__post_remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__post_remove_distdir) + +dist-tarZ: distdir + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__post_remove_distdir) + +dist-shar: distdir + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz + $(am__post_remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__post_remove_distdir) + +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + --srcdir=../.. --prefix="$$dc_install_base" \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__post_remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile cogl-config.h cogl-mutter-config.h +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-hdr \ + distclean-libtool distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) all install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--refresh check check-am clean clean-cscope clean-generic \ + clean-libtool cscope cscopelist-am ctags ctags-am dist \ + dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ + dist-xz dist-zip distcheck distclean distclean-generic \ + distclean-hdr distclean-libtool distclean-tags distcleancheck \ + distdir distuninstallcheck dvi dvi-am html html-am info \ + info-am install install-am install-data install-data-am \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cogl/aclocal.m4 b/cogl/aclocal.m4 new file mode 100644 index 0000000..6820bcb --- /dev/null +++ b/cogl/aclocal.m4 @@ -0,0 +1,1647 @@ +# generated automatically by aclocal 1.15 -*- Autoconf -*- + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. + +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, +[m4_warning([this file was generated for autoconf 2.69. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically 'autoreconf'.])]) + +dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +dnl serial 11 (pkg-config-0.29.1) +dnl +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29.1]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])dnl PKG_PROG_PKG_CONFIG + +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])dnl _PKG_CONFIG + +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])dnl _PKG_SHORT_ERRORS_SUPPORTED + + +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR + +# Configure paths for GLIB +# Owen Taylor 1997-2001 + +dnl AM_PATH_GLIB_2_0([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]]) +dnl Test for GLIB, and define GLIB_CFLAGS and GLIB_LIBS, if gmodule, gobject, +dnl gthread, or gio is specified in MODULES, pass to pkg-config +dnl +AC_DEFUN([AM_PATH_GLIB_2_0], +[dnl +dnl Get the cflags and libraries from pkg-config +dnl +AC_ARG_ENABLE(glibtest, [ --disable-glibtest do not try to compile and run a test GLIB program], + , enable_glibtest=yes) + + pkg_config_args=glib-2.0 + for module in . $4 + do + case "$module" in + gmodule) + pkg_config_args="$pkg_config_args gmodule-2.0" + ;; + gmodule-no-export) + pkg_config_args="$pkg_config_args gmodule-no-export-2.0" + ;; + gobject) + pkg_config_args="$pkg_config_args gobject-2.0" + ;; + gthread) + pkg_config_args="$pkg_config_args gthread-2.0" + ;; + gio*) + pkg_config_args="$pkg_config_args $module-2.0" + ;; + esac + done + + PKG_PROG_PKG_CONFIG([0.16]) + + no_glib="" + + if test "x$PKG_CONFIG" = x ; then + no_glib=yes + PKG_CONFIG=no + fi + + min_glib_version=ifelse([$1], ,2.0.0,$1) + AC_MSG_CHECKING(for GLIB - version >= $min_glib_version) + + if test x$PKG_CONFIG != xno ; then + ## don't try to run the test against uninstalled libtool libs + if $PKG_CONFIG --uninstalled $pkg_config_args; then + echo "Will use uninstalled version of GLib found in PKG_CONFIG_PATH" + enable_glibtest=no + fi + + if $PKG_CONFIG --atleast-version $min_glib_version $pkg_config_args; then + : + else + no_glib=yes + fi + fi + + if test x"$no_glib" = x ; then + GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0` + GOBJECT_QUERY=`$PKG_CONFIG --variable=gobject_query glib-2.0` + GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0` + GLIB_COMPILE_RESOURCES=`$PKG_CONFIG --variable=glib_compile_resources gio-2.0` + + GLIB_CFLAGS=`$PKG_CONFIG --cflags $pkg_config_args` + GLIB_LIBS=`$PKG_CONFIG --libs $pkg_config_args` + glib_config_major_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + glib_config_minor_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + glib_config_micro_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + if test "x$enable_glibtest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GLIB_CFLAGS" + LIBS="$GLIB_LIBS $LIBS" +dnl +dnl Now check if the installed GLIB is sufficiently new. (Also sanity +dnl checks the results of pkg-config to some extent) +dnl + rm -f conf.glibtest + AC_TRY_RUN([ +#include +#include +#include + +int +main () +{ + unsigned int major, minor, micro; + + fclose (fopen ("conf.glibtest", "w")); + + if (sscanf("$min_glib_version", "%u.%u.%u", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_glib_version"); + exit(1); + } + + if ((glib_major_version != $glib_config_major_version) || + (glib_minor_version != $glib_config_minor_version) || + (glib_micro_version != $glib_config_micro_version)) + { + printf("\n*** 'pkg-config --modversion glib-2.0' returned %d.%d.%d, but GLIB (%d.%d.%d)\n", + $glib_config_major_version, $glib_config_minor_version, $glib_config_micro_version, + glib_major_version, glib_minor_version, glib_micro_version); + printf ("*** was found! If pkg-config was correct, then it is best\n"); + printf ("*** to remove the old version of GLib. You may also be able to fix the error\n"); + printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); + printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); + printf("*** required on your system.\n"); + printf("*** If pkg-config was wrong, set the environment variable PKG_CONFIG_PATH\n"); + printf("*** to point to the correct configuration files\n"); + } + else if ((glib_major_version != GLIB_MAJOR_VERSION) || + (glib_minor_version != GLIB_MINOR_VERSION) || + (glib_micro_version != GLIB_MICRO_VERSION)) + { + printf("*** GLIB header files (version %d.%d.%d) do not match\n", + GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION); + printf("*** library (version %d.%d.%d)\n", + glib_major_version, glib_minor_version, glib_micro_version); + } + else + { + if ((glib_major_version > major) || + ((glib_major_version == major) && (glib_minor_version > minor)) || + ((glib_major_version == major) && (glib_minor_version == minor) && (glib_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** An old version of GLIB (%u.%u.%u) was found.\n", + glib_major_version, glib_minor_version, glib_micro_version); + printf("*** You need a version of GLIB newer than %u.%u.%u. The latest version of\n", + major, minor, micro); + printf("*** GLIB is always available from ftp://ftp.gtk.org.\n"); + printf("***\n"); + printf("*** If you have already installed a sufficiently new version, this error\n"); + printf("*** probably means that the wrong copy of the pkg-config shell script is\n"); + printf("*** being found. The easiest way to fix this is to remove the old version\n"); + printf("*** of GLIB, but you can also set the PKG_CONFIG environment to point to the\n"); + printf("*** correct copy of pkg-config. (In this case, you will have to\n"); + printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); + printf("*** so that the correct libraries are found at run-time))\n"); + } + } + return 1; +} +],, no_glib=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_glib" = x ; then + AC_MSG_RESULT(yes (version $glib_config_major_version.$glib_config_minor_version.$glib_config_micro_version)) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$PKG_CONFIG" = "no" ; then + echo "*** A new enough version of pkg-config was not found." + echo "*** See http://www.freedesktop.org/software/pkgconfig/" + else + if test -f conf.glibtest ; then + : + else + echo "*** Could not run GLIB test program, checking why..." + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GLIB_CFLAGS" + LIBS="$LIBS $GLIB_LIBS" + AC_TRY_LINK([ +#include +#include +], [ return ((glib_major_version) || (glib_minor_version) || (glib_micro_version)); ], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding GLIB or finding the wrong" + echo "*** version of GLIB. If it is not finding GLIB, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means GLIB is incorrectly installed."]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + GLIB_CFLAGS="" + GLIB_LIBS="" + GLIB_GENMARSHAL="" + GOBJECT_QUERY="" + GLIB_MKENUMS="" + GLIB_COMPILE_RESOURCES="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(GLIB_CFLAGS) + AC_SUBST(GLIB_LIBS) + AC_SUBST(GLIB_GENMARSHAL) + AC_SUBST(GOBJECT_QUERY) + AC_SUBST(GLIB_MKENUMS) + AC_SUBST(GLIB_COMPILE_RESOURCES) + rm -f conf.glibtest +]) + +# Copyright (C) 2002-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.15' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.15], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.15])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to +# '$srcdir', '$srcdir/..', or '$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is '.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ([2.52])dnl + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], + [$1], [CXX], [depcc="$CXX" am_compiler_list=], + [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], + [$1], [UPC], [depcc="$UPC" am_compiler_list=], + [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES. +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE([dependency-tracking], [dnl +AS_HELP_STRING( + [--enable-dependency-tracking], + [do not reject slow dependency extractors]) +AS_HELP_STRING( + [--disable-dependency-tracking], + [speeds up one-time build])]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "$am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each '.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. +m4_define([AC_PROG_CC], +m4_defn([AC_PROG_CC]) +[_AM_PROG_CC_C_O +]) + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.65])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[AC_DIAGNOSE([obsolete], + [$0: two- and three-arguments forms are deprecated.]) +m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if( + m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), + [ok:ok],, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) + AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) +AM_MISSING_PROG([AUTOCONF], [autoconf]) +AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) +AM_MISSING_PROG([AUTOHEADER], [autoheader]) +AM_MISSING_PROG([MAKEINFO], [makeinfo]) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +AC_SUBST([mkdir_p], ['$(MKDIR_P)']) +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES([CC])], + [m4_define([AC_PROG_CC], + m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES([CXX])], + [m4_define([AC_PROG_CXX], + m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES([OBJC])], + [m4_define([AC_PROG_OBJC], + m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], + [_AM_DEPENDENCIES([OBJCXX])], + [m4_define([AC_PROG_OBJCXX], + m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl +]) +AC_REQUIRE([AM_SILENT_RULES])dnl +dnl The testsuite driver may need to know about EXEEXT, so add the +dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This +dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) + fi +fi +dnl The trailing newline in this macro's definition is deliberate, for +dnl backward compatibility and to allow trailing 'dnl'-style comments +dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. +]) + +dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST([install_sh])]) + +# Copyright (C) 2003-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it is modern enough. +# If it is, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + AC_MSG_WARN(['missing' script is too old or missing]) +fi +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_CC_C_O +# --------------- +# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC +# to automatically call this. +AC_DEFUN([_AM_PROG_CC_C_O], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +AC_LANG_PUSH([C])dnl +AC_CACHE_CHECK( + [whether $CC understands -c and -o together], + [am_cv_prog_cc_c_o], + [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i]) +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +AC_LANG_POP([C])]) + +# For backward compatibility. +AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_RUN_LOG(COMMAND) +# ------------------- +# Run COMMAND, save the exit status in ac_status, and log it. +# (This has been adapted from Autoconf's _AC_RUN_LOG macro.) +AC_DEFUN([AM_RUN_LOG], +[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD + ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + (exit $ac_status); }]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken + alias in your environment]) + fi + if test "$[2]" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT([yes]) +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi +AC_CONFIG_COMMANDS_PRE( + [AC_MSG_CHECKING([that generated files are newer than configure]) + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + AC_MSG_RESULT([done])]) +rm -f conftest.file +]) + +# Copyright (C) 2009-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SILENT_RULES([DEFAULT]) +# -------------------------- +# Enable less verbose build rules; with the default set to DEFAULT +# ("yes" being less verbose, "no" or empty being verbose). +AC_DEFUN([AM_SILENT_RULES], +[AC_ARG_ENABLE([silent-rules], [dnl +AS_HELP_STRING( + [--enable-silent-rules], + [less verbose build output (undo: "make V=1")]) +AS_HELP_STRING( + [--disable-silent-rules], + [verbose build output (undo: "make V=0")])dnl +]) +case $enable_silent_rules in @%:@ ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; +esac +dnl +dnl A few 'make' implementations (e.g., NonStop OS and NextStep) +dnl do not support nested variable expansions. +dnl See automake bug#9928 and bug#10237. +am_make=${MAKE-make} +AC_CACHE_CHECK([whether $am_make supports nested variables], + [am_cv_make_support_nested_variables], + [if AS_ECHO([['TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi]) +if test $am_cv_make_support_nested_variables = yes; then + dnl Using '$V' instead of '$(V)' breaks IRIX make. + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AC_SUBST([AM_V])dnl +AM_SUBST_NOTMAKE([AM_V])dnl +AC_SUBST([AM_DEFAULT_V])dnl +AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl +AC_SUBST([AM_DEFAULT_VERBOSITY])dnl +AM_BACKSLASH='\' +AC_SUBST([AM_BACKSLASH])dnl +_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl +]) + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor 'install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in "make install-strip", and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of 'v7', 'ustar', or 'pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +# +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' + +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + + [m4_case([$1], + [ustar], + [# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) + if test $am_uid -le $am_max_uid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi + AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) + if test $am_gid -le $am_max_gid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi], + + [pax], + [], + + [m4_fatal([Unknown tar format])]) + + AC_MSG_CHECKING([how to create a $1 tar archive]) + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_$1-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi + done + rm -rf conftest.dir + + AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) + AC_MSG_RESULT([$am_cv_prog_tar_$1])]) + +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +m4_include([build/autotools/as-compiler-flag.m4]) +m4_include([build/autotools/introspection.m4]) +m4_include([build/autotools/libtool.m4]) +m4_include([build/autotools/ltoptions.m4]) +m4_include([build/autotools/ltsugar.m4]) +m4_include([build/autotools/ltversion.m4]) +m4_include([build/autotools/lt~obsolete.m4]) diff --git a/cogl/build/autotools/Makefile.am.enums b/cogl/build/autotools/Makefile.am.enums new file mode 100644 index 0000000..2fd69d5 --- /dev/null +++ b/cogl/build/autotools/Makefile.am.enums @@ -0,0 +1,52 @@ +# Rules for generating enumeration types using glib-mkenums +# +# Define: +# glib_enum_h = header template file +# glib_enum_c = source template file +# glib_enum_headers = list of headers to parse +# +# before including Makefile.am.enums. You will also need to have +# the following targets already defined: +# +# CLEANFILES +# DISTCLEANFILES +# BUILT_SOURCES +# EXTRA_DIST +# +# Author: Emmanuele Bassi + +# Basic sanity checks +$(if $(GLIB_MKENUMS),,$(error Need to define GLIB_MKENUMS)) + +$(if $(or $(glib_enum_h), \ + $(glib_enum_c)),, \ + $(error Need to define glib_enum_h and glib_enum_c)) + +$(if $(glib_enum_headers),,$(error Need to define glib_enum_headers)) + +enum_tmpl_h=$(addprefix $(srcdir)/, $(glib_enum_h:.h=.h.in)) +enum_tmpl_c=$(addprefix $(srcdir)/, $(glib_enum_c:.c=.c.in)) +enum_headers=$(addprefix $(srcdir)/, $(glib_enum_headers)) + +CLEANFILES += stamp-enum-types +DISTCLEANFILES += $(glib_enum_h) $(glib_enum_c) +BUILT_SOURCES += $(glib_enum_h) $(glib_enum_c) +EXTRA_DIST += $(enum_tmpl_h) $(enum_tmpl_c) + +stamp-enum-types: $(enum_headers) $(enum_tmpl_h) + $(AM_V_GEN)$(GLIB_MKENUMS) \ + --template $(enum_tmpl_h) \ + $(enum_headers) > xgen-eh \ + && (cmp -s xgen-eh $(glib_enum_h) || cp -f xgen-eh $(glib_enum_h)) \ + && rm -f xgen-eh \ + && echo timestamp > $(@F) + +$(glib_enum_h): stamp-enum-types + @true + +$(glib_enum_c): $(enum_headers) $(enum_tmpl_h) $(enum_tmpl_c) + $(AM_V_GEN)$(GLIB_MKENUMS) \ + --template $(enum_tmpl_c) \ + $(enum_headers) > xgen-ec \ + && cp -f xgen-ec $(glib_enum_c) \ + && rm -f xgen-ec diff --git a/cogl/build/autotools/as-compiler-flag.m4 b/cogl/build/autotools/as-compiler-flag.m4 new file mode 100644 index 0000000..0f660cf --- /dev/null +++ b/cogl/build/autotools/as-compiler-flag.m4 @@ -0,0 +1,62 @@ +dnl as-compiler-flag.m4 0.1.0 + +dnl autostars m4 macro for detection of compiler flags + +dnl David Schleef + +dnl $Id: as-compiler-flag.m4,v 1.1 2005/12/15 23:35:19 ds Exp $ + +dnl AS_COMPILER_FLAG(CFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED]) +dnl Tries to compile with the given CFLAGS. +dnl Runs ACTION-IF-ACCEPTED if the compiler can compile with the flags, +dnl and ACTION-IF-NOT-ACCEPTED otherwise. + +AC_DEFUN([AS_COMPILER_FLAG], +[ + AC_MSG_CHECKING([to see if compiler understands $1]) + + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $1" + + AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no]) + CFLAGS="$save_CFLAGS" + + if test "X$flag_ok" = Xyes ; then + m4_ifvaln([$2],[$2]) + true + else + m4_ifvaln([$3],[$3]) + true + fi + AC_MSG_RESULT([$flag_ok]) +]) + +dnl AS_COMPILER_FLAGS(VAR, FLAGS) +dnl Tries to compile with the given CFLAGS. + +AC_DEFUN([AS_COMPILER_FLAGS], +[ + list=$2 + flags_supported="" + flags_unsupported="" + AC_MSG_CHECKING([for supported compiler flags]) + for each in $list + do + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $each" + AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no]) + CFLAGS="$save_CFLAGS" + + if test "X$flag_ok" = Xyes ; then + flags_supported="$flags_supported $each" + else + flags_unsupported="$flags_unsupported $each" + fi + done + AC_MSG_RESULT([$flags_supported]) + if test "X$flags_unsupported" != X ; then + AC_MSG_WARN([unsupported compiler flags: $flags_unsupported]) + fi + $1="$$1 $flags_supported" +]) + diff --git a/cogl/build/autotools/introspection.m4 b/cogl/build/autotools/introspection.m4 new file mode 100644 index 0000000..589721c --- /dev/null +++ b/cogl/build/autotools/introspection.m4 @@ -0,0 +1,94 @@ +dnl -*- mode: autoconf -*- +dnl Copyright 2009 Johan Dahlin +dnl +dnl This file is free software; the author(s) gives unlimited +dnl permission to copy and/or distribute it, with or without +dnl modifications, as long as this notice is preserved. +dnl + +# serial 1 + +m4_define([_GOBJECT_INTROSPECTION_CHECK_INTERNAL], +[ + AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first + AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first + AC_BEFORE([LT_INIT],[$0])dnl setup libtool first + + dnl enable/disable introspection + m4_if([$2], [require], + [dnl + enable_introspection=yes + ],[dnl + AC_ARG_ENABLE(introspection, + AS_HELP_STRING([--enable-introspection[=@<:@no/auto/yes@:>@]], + [Enable introspection for this build]),, + [enable_introspection=auto]) + ])dnl + + AC_MSG_CHECKING([for gobject-introspection]) + + dnl presence/version checking + AS_CASE([$enable_introspection], + [no], [dnl + found_introspection="no (disabled, use --enable-introspection to enable)" + ],dnl + [yes],[dnl + PKG_CHECK_EXISTS([gobject-introspection-1.0],, + AC_MSG_ERROR([gobject-introspection-1.0 is not installed])) + PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], + found_introspection=yes, + AC_MSG_ERROR([You need to have gobject-introspection >= $1 installed to build AC_PACKAGE_NAME])) + ],dnl + [auto],[dnl + PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], found_introspection=yes, found_introspection=no) + ],dnl + [dnl + AC_MSG_ERROR([invalid argument passed to --enable-introspection, should be one of @<:@no/auto/yes@:>@]) + ])dnl + + AC_MSG_RESULT([$found_introspection]) + + INTROSPECTION_SCANNER= + INTROSPECTION_COMPILER= + INTROSPECTION_GENERATE= + INTROSPECTION_GIRDIR= + INTROSPECTION_TYPELIBDIR= + if test "x$found_introspection" = "xyes"; then + INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0` + INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0` + INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0` + INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0` + INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)" + INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0` + INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0` + INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection + fi + AC_SUBST(INTROSPECTION_SCANNER) + AC_SUBST(INTROSPECTION_COMPILER) + AC_SUBST(INTROSPECTION_GENERATE) + AC_SUBST(INTROSPECTION_GIRDIR) + AC_SUBST(INTROSPECTION_TYPELIBDIR) + AC_SUBST(INTROSPECTION_CFLAGS) + AC_SUBST(INTROSPECTION_LIBS) + AC_SUBST(INTROSPECTION_MAKEFILE) + + AM_CONDITIONAL(HAVE_INTROSPECTION, test "x$found_introspection" = "xyes") +]) + + +dnl Usage: +dnl GOBJECT_INTROSPECTION_CHECK([minimum-g-i-version]) + +AC_DEFUN([GOBJECT_INTROSPECTION_CHECK], +[ + _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1]) +]) + +dnl Usage: +dnl GOBJECT_INTROSPECTION_REQUIRE([minimum-g-i-version]) + + +AC_DEFUN([GOBJECT_INTROSPECTION_REQUIRE], +[ + _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1], [require]) +]) diff --git a/cogl/build/autotools/libtool.m4 b/cogl/build/autotools/libtool.m4 new file mode 100644 index 0000000..a644432 --- /dev/null +++ b/cogl/build/autotools/libtool.m4 @@ -0,0 +1,8372 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +# +# Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +m4_define([_LT_COPYING], [dnl +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +]) + +# serial 58 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_PREPARE_CC_BASENAME +# ----------------------- +m4_defun([_LT_PREPARE_CC_BASENAME], [ +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in @S|@*""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} +])# _LT_PREPARE_CC_BASENAME + + +# _LT_CC_BASENAME(CC) +# ------------------- +# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, +# but that macro is also expanded into generated libtool script, which +# arranges for $SED and $ECHO to be set by different means. +m4_defun([_LT_CC_BASENAME], +[m4_require([_LT_PREPARE_CC_BASENAME])dnl +AC_REQUIRE([_LT_DECL_SED])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl +func_cc_basename $1 +cc_basename=$func_cc_basename_result +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + +_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl +dnl +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_WITH_SYSROOT])dnl +m4_require([_LT_CMD_TRUNCATE])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from 'configure', and 'config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# 'config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain=$ac_aux_dir/ltmain.sh +])# _LT_PROG_LTMAIN + + +## ------------------------------------- ## +## Accumulate code for creating libtool. ## +## ------------------------------------- ## + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the 'libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + +## ------------------------ ## +## FIXME: Eliminate VARNAME ## +## ------------------------ ## + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to 'config.status' so that its +# declaration there will have the same value as in 'configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags='_LT_TAGS'dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into 'config.status', and then the shell code to quote escape them in +# for loops in 'config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +_LT_OUTPUT_LIBTOOL_INIT +]) + +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# '#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test 0 = "$lt_write_fail" && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), incase it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) + +cat >>"$CONFIG_LT" <<\_LTEOF +lt_cl_silent=false +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +'$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to ." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2011 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test 0 != $[#] +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try '$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try '$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +lt_cl_success=: +test yes = "$silent" && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +_LT_COPYING +_LT_LIBTOOL_TAGS + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +_LT_PREPARE_MUNGE_PATH_LIST +_LT_PREPARE_CC_BASENAME + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Go], [_LT_LANG(GO)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +m4_ifndef([AC_PROG_GO], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_GO. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +m4_defun([AC_PROG_GO], +[AC_LANG_PUSH(Go)dnl +AC_ARG_VAR([GOC], [Go compiler command])dnl +AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl +_AC_ARG_VAR_LDFLAGS()dnl +AC_CHECK_TOOL(GOC, gccgo) +if test -z "$GOC"; then + if test -n "$ac_tool_prefix"; then + AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) + fi +fi +if test -z "$GOC"; then + AC_CHECK_PROG(GOC, gccgo, gccgo, false) +fi +])#m4_defun +])#m4_ifndef + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([AC_PROG_GO], + [LT_LANG(GO)], + [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS=$save_LDFLAGS + ]) + + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[[012]][[,.]]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES([TAG]) +# --------------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + if test yes = "$lt_cv_ld_force_load"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], + [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + m4_if([$1], [CXX], +[ if test yes != "$lt_cv_apple_cc_single_mod"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) +# ---------------------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +# Store the results from the different compilers for each TAGNAME. +# Allow to override them for all tags through lt_cv_aix_libpath. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], + [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ + lt_aix_libpath_sed='[ + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }]' + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi],[]) + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib + fi + ]) + aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) +fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script that will find a shell with a builtin +# printf (that we can use as an echo command). +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +case $ECHO in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac + +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) + +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_WITH_SYSROOT +# ---------------- +AC_DEFUN([_LT_WITH_SYSROOT], +[AC_MSG_CHECKING([for sysroot]) +AC_ARG_WITH([sysroot], +[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], + [Search for dependent libraries within DIR (or the compiler's sysroot + if not specified).])], +[], [with_sysroot=no]) + +dnl lt_sysroot will always be passed unquoted. We quote it here +dnl in case the user passed a directory name. +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + AC_MSG_RESULT([$with_sysroot]) + AC_MSG_ERROR([The sysroot must be an absolute path.]) + ;; +esac + + AC_MSG_RESULT([${lt_sysroot:-no}]) +_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl +[dependent libraries, and where our libraries should be installed.])]) + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock +])# _LT_ENABLE_LOCK + + +# _LT_PROG_AR +# ----------- +m4_defun([_LT_PROG_AR], +[AC_CHECK_TOOLS(AR, [ar], false) +: ${AR=ar} +: ${AR_FLAGS=cru} +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], + [lt_cv_ar_at_file=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([lt_ar_try]) + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + AC_TRY_EVAL([lt_ar_try]) + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + ]) + ]) + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi +_LT_DECL([], [archiver_list_spec], [1], + [How to feed a file listing to the archiver]) +])# _LT_PROG_AR + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[_LT_PROG_AR + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test yes = "[$]$2"; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS +]) + +if test yes = "[$]$2"; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n "$lt_cv_sys_max_cmd_len"; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes = "$cross_compiling"; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen=shl_load], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen=dlopen], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links=nottested +if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test no = "$hard_links"; then + AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", + [Define to the sub-directory where libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then + + # We can hardcode non-existent directories. + if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && + test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || + test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_PREPARE_MUNGE_PATH_LIST +# --------------------------- +# Make sure func_munge_path_list() is defined correctly. +m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], +[[# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x@S|@2 in + x) + ;; + *:) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" + ;; + x:*) + eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" + ;; + *) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + esac +} +]])# _LT_PREPARE_PATH_LIST + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +AC_ARG_VAR([LT_SYS_LIBRARY_PATH], +[User-defined run-time library search path.]) + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[[4-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a[(]lib.so.V[)]' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[23]].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[[3-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Add ABI-specific directories to the system library path. + sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[List of archive names. First name is the real one, the rest are links. + The last name is the one that the linker finds with -lNAME]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], + [Detected run-time system search path for libraries]) +_LT_DECL([], [configure_time_lt_sys_library_path], [2], + [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program that can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$1"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac]) +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program that can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test no = "$withval" || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], +[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi]) +rm -f conftest.i conftest2.i conftest.out]) +])# _LT_PATH_DD + + +# _LT_CMD_TRUNCATE +# ---------------- +# find command to truncate a binary pipe +m4_defun([_LT_CMD_TRUNCATE], +[m4_require([_LT_PATH_DD]) +AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], +[printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) +_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], + [Command to truncate a binary pipe]) +])# _LT_CMD_TRUNCATE + + +# _LT_CHECK_MAGIC_METHOD +# ---------------------- +# how to check for library dependencies +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_MAGIC_METHOD], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +AC_CACHE_CHECK([how to recognize dependent libraries], +lt_cv_deplibs_check_method, +[lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[[4-9]]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[[45]]*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method = "file_magic"]) +_LT_DECL([], [file_magic_glob], [1], + [How to find potential files when deplibs_check_method = "file_magic"]) +_LT_DECL([], [want_nocaseglob], [1], + [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi]) +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + AC_SUBST([DUMPBIN]) + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + +# _LT_CHECK_SHAREDLIB_FROM_LINKLIB +# -------------------------------- +# how to determine the name of the shared library +# associated with a specific link library. +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +m4_require([_LT_DECL_DLLTOOL]) +AC_CACHE_CHECK([how to associate runtime and link libraries], +lt_cv_sharedlib_from_linklib_cmd, +[lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac +]) +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + +_LT_DECL([], [sharedlib_from_linklib_cmd], [1], + [Command to associate shared and link libraries]) +])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB + + +# _LT_PATH_MANIFEST_TOOL +# ---------------------- +# locate the manifest tool +m4_defun([_LT_PATH_MANIFEST_TOOL], +[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], + [lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&AS_MESSAGE_LOG_FD + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest*]) +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi +_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl +])# _LT_PATH_MANIFEST_TOOL + + +# _LT_DLL_DEF_P([FILE]) +# --------------------- +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with func_dll_def_p in the libtool script +AC_DEFUN([_LT_DLL_DEF_P], +[dnl + test DEF = "`$SED -n dnl + -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace + -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments + -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl + -e q dnl Only consider the first "real" line + $1`" dnl +])# _LT_DLL_DEF_P + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM=-lm) + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[[ABCDEGRST]]' + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT@&t@_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT@&t@_DLSYM_CONST +#else +# define LT@&t@_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT@&t@_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], + [Transform the output of nm into a list of symbols to manually relocate]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([nm_interface], [lt_cv_nm_interface], [1], + [The name lister interface]) +_LT_DECL([], [nm_file_list_spec], [1], + [Specify filename containing input files for $NM]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64, which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test yes = "$GCC"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + *Sun\ F* | *Sun*Fortran*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + *Intel*\ [[CF]]*Compiler*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + *Portland\ Group*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +AC_CACHE_CHECK([for $compiler option to produce PIC], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + case $host_os in + aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + ;; + esac + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + esac + + _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + esac + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + ;; + esac + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], + [lt_cv_irix_exported_symbol], + [save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + AC_LINK_IFELSE( + [AC_LANG_SOURCE( + [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], + [C++], [[int foo (void) { return 0; }]], + [Fortran 77], [[ + subroutine foo + end]], + [Fortran], [[ + subroutine foo + end]])])], + [lt_cv_irix_exported_symbol=yes], + [lt_cv_irix_exported_symbol=no]) + LDFLAGS=$save_LDFLAGS]) + if test yes = "$lt_cv_irix_exported_symbol"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(ld_shlibs, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + osf3*) + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $_LT_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting $shlibpath_var if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [postlink_cmds], [2], + [Commands necessary for finishing linking programs]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC=$CC +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report what library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC=$lt_save_CC +])# _LT_LANG_C_CONFIG + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +if test -n "$CXX" && ( test no != "$CXX" && + ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || + (test g++ != "$CXX"))); then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_caught_CXX_error"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test yes = "$GXX"; then + # Set up default GNU C++ configuration + + LT_PATH_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test yes = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='$wl' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GXX"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag=$shared_flag' $wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + # The "-G" linker flag allows undefined symbols. + _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared + # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd2.*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ + $RM $lib.exp' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require '-G' NOT '-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + + _LT_TAGVAR(GCC, $1)=$GXX + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test yes != "$_lt_caught_CXX_error" + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_FUNC_STRIPNAME_CNF +# ---------------------- +# func_stripname_cnf prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# +# This function is identical to the (non-XSI) version of func_stripname, +# except this one can be used by m4 code that may be executed by configure, +# rather than the libtool script. +m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl +AC_REQUIRE([_LT_DECL_SED]) +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) +func_stripname_cnf () +{ + case @S|@2 in + .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; + *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; + esac +} # func_stripname_cnf +])# _LT_FUNC_STRIPNAME_CNF + + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF +package foo +func foo() { +} +_LT_EOF +]) + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case $prev$p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test x-L = "$p" || + test x-R = "$p"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test no = "$pre_test_object_deps_done"; then + case $prev in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)=$prev$p + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test no = "$pre_test_object_deps_done"; then + if test -z "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)=$p + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)=$p + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test no = "$F77"; then + _lt_disable_F77=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_F77"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${F77-"f77"} + CFLAGS=$FFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$G77 + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_F77" + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test no = "$FC"; then + _lt_disable_FC=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_FC"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${FC-"f95"} + CFLAGS=$FCFLAGS + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_FC" + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +CFLAGS=$GCJFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_GO_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Go compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GO_CONFIG], +[AC_REQUIRE([LT_PROG_GO])dnl +AC_LANG_SAVE + +# Source file extension for Go test sources. +ac_ext=go + +# Object file extension for compiled Go test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="package main; func main() { }" + +# Code to be used in simple link tests +lt_simple_link_test_code='package main; func main() { }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GOC-"gccgo"} +CFLAGS=$GOFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# Go did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GO_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code=$lt_simple_compile_test_code + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +CFLAGS= +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_GO +# ---------- +AC_DEFUN([LT_PROG_GO], +[AC_CHECK_TOOL(GOC, gccgo,) +]) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + +# _LT_DECL_DLLTOOL +# ---------------- +# Ensure DLLTOOL variable is set. +m4_defun([_LT_DECL_DLLTOOL], +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) +AC_SUBST([DLLTOOL]) +]) + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f "$lt_ac_sed" && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test 10 -lt "$lt_ac_count" && break + lt_ac_count=`expr $lt_ac_count + 1` + if test "$lt_ac_count" -gt "$lt_ac_max"; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PATH_CONVERSION_FUNCTIONS +# ----------------------------- +# Determine what file name conversion functions should be used by +# func_to_host_file (and, implicitly, by func_to_host_path). These are needed +# for certain cross-compile configurations and native mingw. +m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_MSG_CHECKING([how to convert $build file names to $host format]) +AC_CACHE_VAL(lt_cv_to_host_file_cmd, +[case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac +]) +to_host_file_cmd=$lt_cv_to_host_file_cmd +AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) +_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], + [0], [convert $build file names to $host format])dnl + +AC_MSG_CHECKING([how to convert $build file names to toolchain format]) +AC_CACHE_VAL(lt_cv_to_tool_file_cmd, +[#assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac +]) +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) +_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], + [0], [convert $build files to toolchain format])dnl +])# _LT_PATH_CONVERSION_FUNCTIONS diff --git a/cogl/build/autotools/ltoptions.m4 b/cogl/build/autotools/ltoptions.m4 new file mode 100644 index 0000000..94b0829 --- /dev/null +++ b/cogl/build/autotools/ltoptions.m4 @@ -0,0 +1,437 @@ +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 8 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option '$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl 'shared' nor 'disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], + [_LT_WITH_AIX_SONAME([aix])]) + ]) +])# _LT_SET_OPTIONS + + +## --------------------------------- ## +## Macros to handle LT_INIT options. ## +## --------------------------------- ## + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [1], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the 'shared' and +# 'disable-shared' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the 'static' and +# 'disable-static' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the 'fast-install' +# and 'disable-fast-install' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_AIX_SONAME([DEFAULT]) +# ---------------------------------- +# implement the --with-aix-soname flag, and support the `aix-soname=aix' +# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT +# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. +m4_define([_LT_WITH_AIX_SONAME], +[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl +shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[[5-9]]*,yes) + AC_MSG_CHECKING([which variant of shared library versioning to provide]) + AC_ARG_WITH([aix-soname], + [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], + [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], + [case $withval in + aix|svr4|both) + ;; + *) + AC_MSG_ERROR([Unknown argument to --with-aix-soname]) + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname], + [AC_CACHE_VAL([lt_cv_with_aix_soname], + [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) + with_aix_soname=$lt_cv_with_aix_soname]) + AC_MSG_RESULT([$with_aix_soname]) + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + +_LT_DECL([], [shared_archive_member_spec], [0], + [Shared archive member basename, for filename based shared library versioning on AIX])dnl +])# _LT_WITH_AIX_SONAME + +LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the 'pic-only' and 'no-pic' +# LT_INIT options. +# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [pic_mode=m4_default([$1], [default])]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + +## ----------------- ## +## LTDL_INIT Options ## +## ----------------- ## + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) diff --git a/cogl/build/autotools/ltsugar.m4 b/cogl/build/autotools/ltsugar.m4 new file mode 100644 index 0000000..48bc934 --- /dev/null +++ b/cogl/build/autotools/ltsugar.m4 @@ -0,0 +1,124 @@ +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59, which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) diff --git a/cogl/build/autotools/ltversion.m4 b/cogl/build/autotools/ltversion.m4 new file mode 100644 index 0000000..fa04b52 --- /dev/null +++ b/cogl/build/autotools/ltversion.m4 @@ -0,0 +1,23 @@ +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# @configure_input@ + +# serial 4179 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.4.6]) +m4_define([LT_PACKAGE_REVISION], [2.4.6]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.4.6' +macro_revision='2.4.6' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) diff --git a/cogl/build/autotools/lt~obsolete.m4 b/cogl/build/autotools/lt~obsolete.m4 new file mode 100644 index 0000000..c6b26f8 --- /dev/null +++ b/cogl/build/autotools/lt~obsolete.m4 @@ -0,0 +1,99 @@ +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 5 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) diff --git a/cogl/build/compile b/cogl/build/compile new file mode 100755 index 0000000..a85b723 --- /dev/null +++ b/cogl/build/compile @@ -0,0 +1,347 @@ +#! /bin/sh +# Wrapper for compilers which do not understand '-c -o'. + +scriptversion=2012-10-14.11; # UTC + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Written by Tom Tromey . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +nl=' +' + +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent tools from complaining about whitespace usage. +IFS=" "" $nl" + +file_conv= + +# func_file_conv build_file lazy +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. If the determined conversion +# type is listed in (the comma separated) LAZY, no conversion will +# take place. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv/,$2, in + *,$file_conv,*) + ;; + mingw/*) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin/*) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine/*) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + if test -f "$dir/lib$lib.a"; then + found=yes + lib=$dir/lib$lib.a + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + +# func_cl_wrapper cl arg... +# Adjust compile command to suit cl +func_cl_wrapper () +{ + # Assume a capable shell + lib_path= + shared=: + linker_opts= + for arg + do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + eat=1 + case $2 in + *.o | *.[oO][bB][jJ]) + func_file_conv "$2" + set x "$@" -Fo"$file" + shift + ;; + *) + func_file_conv "$2" + set x "$@" -Fe"$file" + shift + ;; + esac + ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; + -I*) + func_file_conv "${1#-I}" mingw + set x "$@" -I"$file" + shift + ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; + -l*) + func_cl_dashl "${1#-l}" + set x "$@" "$lib" + shift + ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; + -L*) + func_cl_dashL "${1#-L}" + ;; + -static) + shared=false + ;; + -Wl,*) + arg=${1#-Wl,} + save_ifs="$IFS"; IFS=',' + for flag in $arg; do + IFS="$save_ifs" + linker_opts="$linker_opts $flag" + done + IFS="$save_ifs" + ;; + -Xlinker) + eat=1 + linker_opts="$linker_opts $2" + ;; + -*) + set x "$@" "$1" + shift + ;; + *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) + func_file_conv "$1" + set x "$@" -Tp"$file" + shift + ;; + *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) + func_file_conv "$1" mingw + set x "$@" "$file" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift + done + if test -n "$linker_opts"; then + linker_opts="-link$linker_opts" + fi + exec "$@" $linker_opts + exit 1 +} + +eat= + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand '-c -o'. +Remove '-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file 'INSTALL'. + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) + func_cl_wrapper "$@" # Doesn't return... + ;; +esac + +ofile= +cfile= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + # So we strip '-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no '-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # '.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use '[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/cogl/build/config.guess b/cogl/build/config.guess new file mode 100755 index 0000000..dbfb978 --- /dev/null +++ b/cogl/build/config.guess @@ -0,0 +1,1421 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2015 Free Software Foundation, Inc. + +timestamp='2015-01-01' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program 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 +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +# +# Please send patches to . + + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright 1992-2015 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +case "${UNAME_SYSTEM}" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval $set_cc_for_build + cat <<-EOF > $dummy.c + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + ;; +esac + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW64*:*) + echo ${UNAME_MACHINE}-pc-mingw64 + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + *:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="gnulibc1" ; fi + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + else + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-${LIBC} + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-${LIBC} + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; + PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; + *) echo hppa-unknown-linux-${LIBC} ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-${LIBC} + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-${LIBC} + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-${LIBC} + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-${LIBC} + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-${LIBC} + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + eval $set_cc_for_build + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + fi + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; +esac + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/cogl/build/config.sub b/cogl/build/config.sub new file mode 100755 index 0000000..6467c95 --- /dev/null +++ b/cogl/build/config.sub @@ -0,0 +1,1807 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright 1992-2015 Free Software Foundation, Inc. + +timestamp='2015-01-01' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program 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 +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + + +# Please send patches to . +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright 1992-2015 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze*) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | be32 | be64 \ + | bfin \ + | c4x | c8051 | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | epiphany \ + | fido | fr30 | frv | ft32 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ + | ns16k | ns32k \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | riscv32 | riscv64 \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | k1om-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | or1k*-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | visium-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + mingw32) + basic_machine=i686-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i686-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-* | ppc64p7-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* | -plan9* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/cogl/build/depcomp b/cogl/build/depcomp new file mode 100755 index 0000000..fc98710 --- /dev/null +++ b/cogl/build/depcomp @@ -0,0 +1,791 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2013-05-30.07; # UTC + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program 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 General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by 'PROGRAMS ARGS'. + object Object file output by 'PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputting dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +# Get the directory component of the given path, and save it in the +# global variables '$dir'. Note that this directory component will +# be either empty or ending with a '/' character. This is deliberate. +set_dir_from () +{ + case $1 in + */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; + *) dir=;; + esac +} + +# Get the suffix-stripped basename of the given path, and save it the +# global variable '$base'. +set_base_from () +{ + base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` +} + +# If no dependency file was actually created by the compiler invocation, +# we still have to create a dummy depfile, to avoid errors with the +# Makefile "include basename.Plo" scheme. +make_dummy_depfile () +{ + echo "#dummy" > "$depfile" +} + +# Factor out some common post-processing of the generated depfile. +# Requires the auxiliary global variable '$tmpdepfile' to be set. +aix_post_process_depfile () +{ + # If the compiler actually managed to produce a dependency file, + # post-process it. + if test -f "$tmpdepfile"; then + # Each line is of the form 'foo.o: dependency.h'. + # Do two passes, one to just change these to + # $object: dependency.h + # and one to simply output + # dependency.h: + # which is needed to avoid the deleted-header problem. + { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" + sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" + } > "$depfile" + rm -f "$tmpdepfile" + else + make_dummy_depfile + fi +} + +# A tabulation character. +tab=' ' +# A newline character. +nl=' +' +# Character ranges might be problematic outside the C locale. +# These definitions help. +upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ +lower=abcdefghijklmnopqrstuvwxyz +digits=0123456789 +alpha=${upper}${lower} + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Avoid interferences from the environment. +gccflag= dashmflag= + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvisualcpp +fi + +if test "$depmode" = msvc7msys; then + # This is just like msvc7 but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvc7 +fi + +if test "$depmode" = xlc; then + # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. + gccflag=-qmakedep=gcc,-MF + depmode=gcc +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. +## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. +## (see the conditional assignment to $gccflag above). +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). Also, it might not be +## supported by the other compilers which use the 'gcc' depmode. +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The second -e expression handles DOS-style file names with drive + # letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the "deleted header file" problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. +## Some versions of gcc put a space before the ':'. On the theory +## that the space means something, we add a space to the output as +## well. hp depmode also adds that space, but also prefixes the VPATH +## to the object. Take care to not repeat it in the output. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like '#:fec' to the end of the + # dependency line. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ + | tr "$nl" ' ' >> "$depfile" + echo >> "$depfile" + # The second pass generates a dummy entry for each header file. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" + ;; + +xlc) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts '$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + aix_post_process_depfile + ;; + +tcc) + # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 + # FIXME: That version still under development at the moment of writing. + # Make that this statement remains true also for stable, released + # versions. + # It will wrap lines (doesn't matter whether long or short) with a + # trailing '\', as in: + # + # foo.o : \ + # foo.c \ + # foo.h \ + # + # It will put a trailing '\' even on the last line, and will use leading + # spaces rather than leading tabs (at least since its commit 0394caf7 + # "Emit spaces for -MD"). + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. + # We have to change lines of the first kind to '$object: \'. + sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" + # And for each line of the second kind, we have to emit a 'dep.h:' + # dummy dependency, to avoid the deleted-header problem. + sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" + rm -f "$tmpdepfile" + ;; + +## The order of this option in the case statement is important, since the +## shell code in configure will try each of these formats in the order +## listed in this file. A plain '-MD' option would be understood by many +## compilers, so we must ensure this comes after the gcc and icc options. +pgcc) + # Portland's C compiler understands '-MD'. + # Will always output deps to 'file.d' where file is the root name of the + # source file under compilation, even if file resides in a subdirectory. + # The object file name does not affect the name of the '.d' file. + # pgcc 10.2 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using '\' : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + set_dir_from "$object" + # Use the source, not the object, to determine the base name, since + # that's sadly what pgcc will do too. + set_base_from "$source" + tmpdepfile=$base.d + + # For projects that build the same source file twice into different object + # files, the pgcc approach of using the *source* file root name can cause + # problems in parallel builds. Use a locking strategy to avoid stomping on + # the same $tmpdepfile. + lockdir=$base.d-lock + trap " + echo '$0: caught signal, cleaning up...' >&2 + rmdir '$lockdir' + exit 1 + " 1 2 13 15 + numtries=100 + i=$numtries + while test $i -gt 0; do + # mkdir is a portable test-and-set. + if mkdir "$lockdir" 2>/dev/null; then + # This process acquired the lock. + "$@" -MD + stat=$? + # Release the lock. + rmdir "$lockdir" + break + else + # If the lock is being held by a different process, wait + # until the winning process is done or we timeout. + while test -d "$lockdir" && test $i -gt 0; do + sleep 1 + i=`expr $i - 1` + done + fi + i=`expr $i - 1` + done + trap - 1 2 13 15 + if test $i -le 0; then + echo "$0: failed to acquire lock after $numtries attempts" >&2 + echo "$0: check lockdir '$lockdir'" >&2 + exit 1 + fi + + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" + # Add 'dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in 'foo.d' instead, so we check for that too. + # Subdirectories are respected. + set_dir_from "$object" + set_base_from "$object" + + if test "$libtool" = yes; then + # Libtool generates 2 separate objects for the 2 libraries. These + # two compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir$base.o.d # libtool 1.5 + tmpdepfile2=$dir.libs/$base.o.d # Likewise. + tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + # Same post-processing that is required for AIX mode. + aix_post_process_depfile + ;; + +msvc7) + if test "$libtool" = yes; then + showIncludes=-Wc,-showIncludes + else + showIncludes=-showIncludes + fi + "$@" $showIncludes > "$tmpdepfile" + stat=$? + grep -v '^Note: including file: ' "$tmpdepfile" + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The first sed program below extracts the file names and escapes + # backslashes for cygpath. The second sed program outputs the file + # name when reading, but also accumulates all include files in the + # hold buffer in order to output them again at the end. This only + # works with sed implementations that can handle large buffers. + sed < "$tmpdepfile" -n ' +/^Note: including file: *\(.*\)/ { + s//\1/ + s/\\/\\\\/g + p +}' | $cygpath_u | sort -u | sed -n ' +s/ /\\ /g +s/\(.*\)/'"$tab"'\1 \\/p +s/.\(.*\) \\/\1:/ +H +$ { + s/.*/'"$tab"'/ + G + p +}' >> "$depfile" + echo >> "$depfile" # make sure the fragment doesn't end with a backslash + rm -f "$tmpdepfile" + ;; + +msvc7msys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for ':' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. + "$@" $dashmflag | + sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this sed invocation + # correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + # makedepend may prepend the VPATH from the source file name to the object. + # No need to regex-escape $object, excess matching of '.' is harmless. + sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process the last invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed '1,2d' "$tmpdepfile" \ + | tr ' ' "$nl" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E \ + | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + | sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" + echo "$tab" >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/cogl/build/install-sh b/cogl/build/install-sh new file mode 100755 index 0000000..0b0fdcb --- /dev/null +++ b/cogl/build/install-sh @@ -0,0 +1,501 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2013-12-25.23; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# 'make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +tab=' ' +nl=' +' +IFS=" $tab$nl" + +# Set DOITPROG to "echo" to test this script. + +doit=${DOITPROG-} +doit_exec=${doit:-exec} + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +is_target_a_directory=possibly + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) is_target_a_directory=never;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi +fi + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + dstdir=`dirname "$dst"` + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + oIFS=$IFS + IFS=/ + set -f + set fnord $dstdir + shift + set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + set +f && + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/cogl/build/ltmain.sh b/cogl/build/ltmain.sh new file mode 100644 index 0000000..0f0a2da --- /dev/null +++ b/cogl/build/ltmain.sh @@ -0,0 +1,11147 @@ +#! /bin/sh +## DO NOT EDIT - This file generated from ./build-aux/ltmain.in +## by inline-source v2014-01-03.01 + +# libtool (GNU libtool) 2.4.6 +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool 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 +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +PROGRAM=libtool +PACKAGE=libtool +VERSION=2.4.6 +package_revision=2.4.6 + + +## ------ ## +## Usage. ## +## ------ ## + +# Run './libtool --help' for help with using this script from the +# command line. + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# After configure completes, it has a better idea of some of the +# shell tools we need than the defaults used by the functions shared +# with bootstrap, so set those here where they can still be over- +# ridden by the user, but otherwise take precedence. + +: ${AUTOCONF="autoconf"} +: ${AUTOMAKE="automake"} + + +## -------------------------- ## +## Source external libraries. ## +## -------------------------- ## + +# Much of our low-level functionality needs to be sourced from external +# libraries, which are installed to $pkgauxdir. + +# Set a version string for this script. +scriptversion=2015-01-20.17; # UTC + +# General shell script boiler plate, and helper functions. +# Written by Gary V. Vaughan, 2004 + +# Copyright (C) 2004-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# As a special exception to the GNU General Public License, if you distribute +# this file as part of a program or library that is built using GNU Libtool, +# you may include this file under the same distribution terms that you use +# for the rest of that program. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNES FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# Evaluate this file near the top of your script to gain access to +# the functions and variables defined here: +# +# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh +# +# If you need to override any of the default environment variable +# settings, do that before evaluating this file. + + +## -------------------- ## +## Shell normalisation. ## +## -------------------- ## + +# Some shells need a little help to be as Bourne compatible as possible. +# Before doing anything else, make sure all that help has been provided! + +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac +fi + +# NLS nuisances: We save the old values in case they are required later. +_G_user_locale= +_G_safe_locale= +for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test set = \"\${$_G_var+set}\"; then + save_$_G_var=\$$_G_var + $_G_var=C + export $_G_var + _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" + _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" + fi" +done + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Make sure IFS has a sensible default +sp=' ' +nl=' +' +IFS="$sp $nl" + +# There are apparently some retarded systems that use ';' as a PATH separator! +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + + +## ------------------------- ## +## Locate command utilities. ## +## ------------------------- ## + + +# func_executable_p FILE +# ---------------------- +# Check that FILE is an executable regular file. +func_executable_p () +{ + test -f "$1" && test -x "$1" +} + + +# func_path_progs PROGS_LIST CHECK_FUNC [PATH] +# -------------------------------------------- +# Search for either a program that responds to --version with output +# containing "GNU", or else returned by CHECK_FUNC otherwise, by +# trying all the directories in PATH with each of the elements of +# PROGS_LIST. +# +# CHECK_FUNC should accept the path to a candidate program, and +# set $func_check_prog_result if it truncates its output less than +# $_G_path_prog_max characters. +func_path_progs () +{ + _G_progs_list=$1 + _G_check_func=$2 + _G_PATH=${3-"$PATH"} + + _G_path_prog_max=0 + _G_path_prog_found=false + _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} + for _G_dir in $_G_PATH; do + IFS=$_G_save_IFS + test -z "$_G_dir" && _G_dir=. + for _G_prog_name in $_G_progs_list; do + for _exeext in '' .EXE; do + _G_path_prog=$_G_dir/$_G_prog_name$_exeext + func_executable_p "$_G_path_prog" || continue + case `"$_G_path_prog" --version 2>&1` in + *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; + *) $_G_check_func $_G_path_prog + func_path_progs_result=$func_check_prog_result + ;; + esac + $_G_path_prog_found && break 3 + done + done + done + IFS=$_G_save_IFS + test -z "$func_path_progs_result" && { + echo "no acceptable sed could be found in \$PATH" >&2 + exit 1 + } +} + + +# We want to be able to use the functions in this file before configure +# has figured out where the best binaries are kept, which means we have +# to search for them ourselves - except when the results are already set +# where we skip the searches. + +# Unless the user overrides by setting SED, search the path for either GNU +# sed, or the sed that truncates its output the least. +test -z "$SED" && { + _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for _G_i in 1 2 3 4 5 6 7; do + _G_sed_script=$_G_sed_script$nl$_G_sed_script + done + echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed + _G_sed_script= + + func_check_prog_sed () + { + _G_path_prog=$1 + + _G_count=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo '' >> conftest.nl + "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin + rm -f conftest.sed + SED=$func_path_progs_result +} + + +# Unless the user overrides by setting GREP, search the path for either GNU +# grep, or the grep that truncates its output the least. +test -z "$GREP" && { + func_check_prog_grep () + { + _G_path_prog=$1 + + _G_count=0 + _G_path_prog_max=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo 'GREP' >> conftest.nl + "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin + GREP=$func_path_progs_result +} + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# All uppercase variable names are used for environment variables. These +# variables can be overridden by the user before calling a script that +# uses them if a suitable command of that name is not already available +# in the command search PATH. + +: ${CP="cp -f"} +: ${ECHO="printf %s\n"} +: ${EGREP="$GREP -E"} +: ${FGREP="$GREP -F"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} + + +## -------------------- ## +## Useful sed snippets. ## +## -------------------- ## + +sed_dirname='s|/[^/]*$||' +sed_basename='s|^.*/||' + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Same as above, but do not quote variable references. +sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' + +# Sed substitution that converts a w32 file name or path +# that contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-'\' parameter expansions in output of sed_double_quote_subst that +# were '\'-ed in input to the same. If an odd number of '\' preceded a +# '$' in input to sed_double_quote_subst, that '$' was protected from +# expansion. Since each input '\' is now two '\'s, look for any number +# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. +_G_bs='\\' +_G_bs2='\\\\' +_G_bs4='\\\\\\\\' +_G_dollar='\$' +sed_double_backslash="\ + s/$_G_bs4/&\\ +/g + s/^$_G_bs2$_G_dollar/$_G_bs&/ + s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g + s/\n//g" + + +## ----------------- ## +## Global variables. ## +## ----------------- ## + +# Except for the global variables explicitly listed below, the following +# functions in the '^func_' namespace, and the '^require_' namespace +# variables initialised in the 'Resource management' section, sourcing +# this file will not pollute your global namespace with anything +# else. There's no portable way to scope variables in Bourne shell +# though, so actually running these functions will sometimes place +# results into a variable named after the function, and often use +# temporary variables in the '^_G_' namespace. If you are careful to +# avoid using those namespaces casually in your sourcing script, things +# should continue to work as you expect. And, of course, you can freely +# overwrite any of the functions or variables defined here before +# calling anything to customize them. + +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +# Allow overriding, eg assuming that you follow the convention of +# putting '$debug_cmd' at the start of all your functions, you can get +# bash to show function call trace with: +# +# debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name +debug_cmd=${debug_cmd-":"} +exit_cmd=: + +# By convention, finish your script with: +# +# exit $exit_status +# +# so that you can set exit_status to non-zero if you want to indicate +# something went wrong during execution without actually bailing out at +# the point of failure. +exit_status=$EXIT_SUCCESS + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath=$0 + +# The name of this program. +progname=`$ECHO "$progpath" |$SED "$sed_basename"` + +# Make sure we have an absolute progpath for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` + progdir=`cd "$progdir" && pwd` + progpath=$progdir/$progname + ;; + *) + _G_IFS=$IFS + IFS=${PATH_SEPARATOR-:} + for progdir in $PATH; do + IFS=$_G_IFS + test -x "$progdir/$progname" && break + done + IFS=$_G_IFS + test -n "$progdir" || progdir=`pwd` + progpath=$progdir/$progname + ;; +esac + + +## ----------------- ## +## Standard options. ## +## ----------------- ## + +# The following options affect the operation of the functions defined +# below, and should be set appropriately depending on run-time para- +# meters passed on the command line. + +opt_dry_run=false +opt_quiet=false +opt_verbose=false + +# Categories 'all' and 'none' are always available. Append any others +# you will pass as the first argument to func_warning from your own +# code. +warning_categories= + +# By default, display warnings according to 'opt_warning_types'. Set +# 'warning_func' to ':' to elide all warnings, or func_fatal_error to +# treat the next displayed warning as a fatal error. +warning_func=func_warn_and_continue + +# Set to 'all' to display all warnings, 'none' to suppress all +# warnings, or a space delimited list of some subset of +# 'warning_categories' to display only the listed warnings. +opt_warning_types=all + + +## -------------------- ## +## Resource management. ## +## -------------------- ## + +# This section contains definitions for functions that each ensure a +# particular resource (a file, or a non-empty configuration variable for +# example) is available, and if appropriate to extract default values +# from pertinent package files. Call them using their associated +# 'require_*' variable to ensure that they are executed, at most, once. +# +# It's entirely deliberate that calling these functions can set +# variables that don't obey the namespace limitations obeyed by the rest +# of this file, in order that that they be as useful as possible to +# callers. + + +# require_term_colors +# ------------------- +# Allow display of bold text on terminals that support it. +require_term_colors=func_require_term_colors +func_require_term_colors () +{ + $debug_cmd + + test -t 1 && { + # COLORTERM and USE_ANSI_COLORS environment variables take + # precedence, because most terminfo databases neglect to describe + # whether color sequences are supported. + test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} + + if test 1 = "$USE_ANSI_COLORS"; then + # Standard ANSI escape sequences + tc_reset='' + tc_bold=''; tc_standout='' + tc_red=''; tc_green='' + tc_blue=''; tc_cyan='' + else + # Otherwise trust the terminfo database after all. + test -n "`tput sgr0 2>/dev/null`" && { + tc_reset=`tput sgr0` + test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` + tc_standout=$tc_bold + test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` + test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` + test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` + test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` + test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` + } + fi + } + + require_term_colors=: +} + + +## ----------------- ## +## Function library. ## +## ----------------- ## + +# This section contains a variety of useful functions to call in your +# scripts. Take note of the portable wrappers for features provided by +# some modern shells, which will fall back to slower equivalents on +# less featureful shells. + + +# func_append VAR VALUE +# --------------------- +# Append VALUE onto the existing contents of VAR. + + # We should try to minimise forks, especially on Windows where they are + # unreasonably slow, so skip the feature probes when bash or zsh are + # being used: + if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then + : ${_G_HAVE_ARITH_OP="yes"} + : ${_G_HAVE_XSI_OPS="yes"} + # The += operator was introduced in bash 3.1 + case $BASH_VERSION in + [12].* | 3.0 | 3.0*) ;; + *) + : ${_G_HAVE_PLUSEQ_OP="yes"} + ;; + esac + fi + + # _G_HAVE_PLUSEQ_OP + # Can be empty, in which case the shell is probed, "yes" if += is + # useable or anything else if it does not work. + test -z "$_G_HAVE_PLUSEQ_OP" \ + && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ + && _G_HAVE_PLUSEQ_OP=yes + +if test yes = "$_G_HAVE_PLUSEQ_OP" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_append () + { + $debug_cmd + + eval "$1+=\$2" + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_append () + { + $debug_cmd + + eval "$1=\$$1\$2" + } +fi + + +# func_append_quoted VAR VALUE +# ---------------------------- +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +if test yes = "$_G_HAVE_PLUSEQ_OP"; then + eval 'func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1+=\\ \$func_quote_for_eval_result" + }' +else + func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1=\$$1\\ \$func_quote_for_eval_result" + } +fi + + +# func_append_uniq VAR VALUE +# -------------------------- +# Append unique VALUE onto the existing contents of VAR, assuming +# entries are delimited by the first character of VALUE. For example: +# +# func_append_uniq options " --another-option option-argument" +# +# will only append to $options if " --another-option option-argument " +# is not already present somewhere in $options already (note spaces at +# each end implied by leading space in second argument). +func_append_uniq () +{ + $debug_cmd + + eval _G_current_value='`$ECHO $'$1'`' + _G_delim=`expr "$2" : '\(.\)'` + + case $_G_delim$_G_current_value$_G_delim in + *"$2$_G_delim"*) ;; + *) func_append "$@" ;; + esac +} + + +# func_arith TERM... +# ------------------ +# Set func_arith_result to the result of evaluating TERMs. + test -z "$_G_HAVE_ARITH_OP" \ + && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ + && _G_HAVE_ARITH_OP=yes + +if test yes = "$_G_HAVE_ARITH_OP"; then + eval 'func_arith () + { + $debug_cmd + + func_arith_result=$(( $* )) + }' +else + func_arith () + { + $debug_cmd + + func_arith_result=`expr "$@"` + } +fi + + +# func_basename FILE +# ------------------ +# Set func_basename_result to FILE with everything up to and including +# the last / stripped. +if test yes = "$_G_HAVE_XSI_OPS"; then + # If this shell supports suffix pattern removal, then use it to avoid + # forking. Hide the definitions single quotes in case the shell chokes + # on unsupported syntax... + _b='func_basename_result=${1##*/}' + _d='case $1 in + */*) func_dirname_result=${1%/*}$2 ;; + * ) func_dirname_result=$3 ;; + esac' + +else + # ...otherwise fall back to using sed. + _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' + _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` + if test "X$func_dirname_result" = "X$1"; then + func_dirname_result=$3 + else + func_append func_dirname_result "$2" + fi' +fi + +eval 'func_basename () +{ + $debug_cmd + + '"$_b"' +}' + + +# func_dirname FILE APPEND NONDIR_REPLACEMENT +# ------------------------------------------- +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +eval 'func_dirname () +{ + $debug_cmd + + '"$_d"' +}' + + +# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT +# -------------------------------------------------------- +# Perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# For efficiency, we do not delegate to the functions above but instead +# duplicate the functionality here. +eval 'func_dirname_and_basename () +{ + $debug_cmd + + '"$_b"' + '"$_d"' +}' + + +# func_echo ARG... +# ---------------- +# Echo program name prefixed message. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_echo_all ARG... +# -------------------- +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + + +# func_echo_infix_1 INFIX ARG... +# ------------------------------ +# Echo program name, followed by INFIX on the first line, with any +# additional lines not showing INFIX. +func_echo_infix_1 () +{ + $debug_cmd + + $require_term_colors + + _G_infix=$1; shift + _G_indent=$_G_infix + _G_prefix="$progname: $_G_infix: " + _G_message=$* + + # Strip color escape sequences before counting printable length + for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" + do + test -n "$_G_tc" && { + _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` + _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` + } + done + _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes + + func_echo_infix_1_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_infix_1_IFS + $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 + _G_prefix=$_G_indent + done + IFS=$func_echo_infix_1_IFS +} + + +# func_error ARG... +# ----------------- +# Echo program name prefixed message to standard error. +func_error () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 +} + + +# func_fatal_error ARG... +# ----------------------- +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + $debug_cmd + + func_error "$*" + exit $EXIT_FAILURE +} + + +# func_grep EXPRESSION FILENAME +# ----------------------------- +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $debug_cmd + + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_len STRING +# --------------- +# Set func_len_result to the length of STRING. STRING may not +# start with a hyphen. + test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_len () + { + $debug_cmd + + func_len_result=${#1} + }' +else + func_len () + { + $debug_cmd + + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` + } +fi + + +# func_mkdir_p DIRECTORY-PATH +# --------------------------- +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + $debug_cmd + + _G_directory_path=$1 + _G_dir_list= + + if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then + + # Protect directory names starting with '-' + case $_G_directory_path in + -*) _G_directory_path=./$_G_directory_path ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$_G_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + _G_dir_list=$_G_directory_path:$_G_dir_list + + # If the last portion added has no slash in it, the list is done + case $_G_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` + done + _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` + + func_mkdir_p_IFS=$IFS; IFS=: + for _G_dir in $_G_dir_list; do + IFS=$func_mkdir_p_IFS + # mkdir can fail with a 'File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$_G_dir" 2>/dev/null || : + done + IFS=$func_mkdir_p_IFS + + # Bail out if we (or some other process) failed to create a directory. + test -d "$_G_directory_path" || \ + func_fatal_error "Failed to create '$1'" + fi +} + + +# func_mktempdir [BASENAME] +# ------------------------- +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, BASENAME is the basename for that directory. +func_mktempdir () +{ + $debug_cmd + + _G_template=${TMPDIR-/tmp}/${1-$progname} + + if test : = "$opt_dry_run"; then + # Return a directory name, but don't create it in dry-run mode + _G_tmpdir=$_G_template-$$ + else + + # If mktemp works, use that first and foremost + _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` + + if test ! -d "$_G_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + _G_tmpdir=$_G_template-${RANDOM-0}$$ + + func_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$_G_tmpdir" + umask $func_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$_G_tmpdir" || \ + func_fatal_error "cannot create temporary directory '$_G_tmpdir'" + fi + + $ECHO "$_G_tmpdir" +} + + +# func_normal_abspath PATH +# ------------------------ +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +func_normal_abspath () +{ + $debug_cmd + + # These SED scripts presuppose an absolute path with a trailing slash. + _G_pathcar='s|^/\([^/]*\).*$|\1|' + _G_pathcdr='s|^/[^/]*||' + _G_removedotparts=':dotsl + s|/\./|/|g + t dotsl + s|/\.$|/|' + _G_collapseslashes='s|/\{1,\}|/|g' + _G_finalslash='s|/*$|/|' + + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` + while :; do + # Processed it all yet? + if test / = "$func_normal_abspath_tpath"; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result"; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + + +# func_notquiet ARG... +# -------------------- +# Echo program name prefixed message only when not in quiet mode. +func_notquiet () +{ + $debug_cmd + + $opt_quiet || func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + + +# func_relative_path SRCDIR DSTDIR +# -------------------------------- +# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. +func_relative_path () +{ + $debug_cmd + + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=$func_dirname_result + if test -z "$func_relative_path_tlibdir"; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test -n "$func_stripname_result"; then + func_append func_relative_path_result "/$func_stripname_result" + fi + + # Normalisation. If bindir is libdir, return '.' else relative path. + if test -n "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + fi + + test -n "$func_relative_path_result" || func_relative_path_result=. + + : +} + + +# func_quote_for_eval ARG... +# -------------------------- +# Aesthetically quote ARGs to be evaled later. +# This function returns two values: +# i) func_quote_for_eval_result +# double-quoted, suitable for a subsequent eval +# ii) func_quote_for_eval_unquoted_result +# has all characters that are still active within double +# quotes backslashified. +func_quote_for_eval () +{ + $debug_cmd + + func_quote_for_eval_unquoted_result= + func_quote_for_eval_result= + while test 0 -lt $#; do + case $1 in + *[\\\`\"\$]*) + _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; + *) + _G_unquoted_arg=$1 ;; + esac + if test -n "$func_quote_for_eval_unquoted_result"; then + func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" + else + func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" + fi + + case $_G_unquoted_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and variable expansion + # for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_quoted_arg=\"$_G_unquoted_arg\" + ;; + *) + _G_quoted_arg=$_G_unquoted_arg + ;; + esac + + if test -n "$func_quote_for_eval_result"; then + func_append func_quote_for_eval_result " $_G_quoted_arg" + else + func_append func_quote_for_eval_result "$_G_quoted_arg" + fi + shift + done +} + + +# func_quote_for_expand ARG +# ------------------------- +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + $debug_cmd + + case $1 in + *[\\\`\"]*) + _G_arg=`$ECHO "$1" | $SED \ + -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; + *) + _G_arg=$1 ;; + esac + + case $_G_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_arg=\"$_G_arg\" + ;; + esac + + func_quote_for_expand_result=$_G_arg +} + + +# func_stripname PREFIX SUFFIX NAME +# --------------------------------- +# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_stripname () + { + $debug_cmd + + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary variable first. + func_stripname_result=$3 + func_stripname_result=${func_stripname_result#"$1"} + func_stripname_result=${func_stripname_result%"$2"} + }' +else + func_stripname () + { + $debug_cmd + + case $2 in + .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; + *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; + esac + } +fi + + +# func_show_eval CMD [FAIL_EXP] +# ----------------------------- +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + func_quote_for_expand "$_G_cmd" + eval "func_notquiet $func_quote_for_expand_result" + + $opt_dry_run || { + eval "$_G_cmd" + _G_status=$? + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_show_eval_locale CMD [FAIL_EXP] +# ------------------------------------ +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + $opt_quiet || { + func_quote_for_expand "$_G_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + $opt_dry_run || { + eval "$_G_user_locale + $_G_cmd" + _G_status=$? + eval "$_G_safe_locale" + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_tr_sh +# ---------- +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + $debug_cmd + + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_verbose ARG... +# ------------------- +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $debug_cmd + + $opt_verbose && func_echo "$*" + + : +} + + +# func_warn_and_continue ARG... +# ----------------------------- +# Echo program name prefixed warning message to standard error. +func_warn_and_continue () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 +} + + +# func_warning CATEGORY ARG... +# ---------------------------- +# Echo program name prefixed warning message to standard error. Warning +# messages can be filtered according to CATEGORY, where this function +# elides messages where CATEGORY is not listed in the global variable +# 'opt_warning_types'. +func_warning () +{ + $debug_cmd + + # CATEGORY must be in the warning_categories list! + case " $warning_categories " in + *" $1 "*) ;; + *) func_internal_error "invalid warning category '$1'" ;; + esac + + _G_category=$1 + shift + + case " $opt_warning_types " in + *" $_G_category "*) $warning_func ${1+"$@"} ;; + esac +} + + +# func_sort_ver VER1 VER2 +# ----------------------- +# 'sort -V' is not generally available. +# Note this deviates from the version comparison in automake +# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a +# but this should suffice as we won't be specifying old +# version formats or redundant trailing .0 in bootstrap.conf. +# If we did want full compatibility then we should probably +# use m4_version_compare from autoconf. +func_sort_ver () +{ + $debug_cmd + + printf '%s\n%s\n' "$1" "$2" \ + | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n +} + +# func_lt_ver PREV CURR +# --------------------- +# Return true if PREV and CURR are in the correct order according to +# func_sort_ver, otherwise false. Use it like this: +# +# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." +func_lt_ver () +{ + $debug_cmd + + test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: +#! /bin/sh + +# Set a version string for this script. +scriptversion=2014-01-07.03; # UTC + +# A portable, pluggable option parser for Bourne shell. +# Written by Gary V. Vaughan, 2010 + +# Copyright (C) 2010-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program 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 General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# This file is a library for parsing options in your shell scripts along +# with assorted other useful supporting features that you can make use +# of too. +# +# For the simplest scripts you might need only: +# +# #!/bin/sh +# . relative/path/to/funclib.sh +# . relative/path/to/options-parser +# scriptversion=1.0 +# func_options ${1+"$@"} +# eval set dummy "$func_options_result"; shift +# ...rest of your script... +# +# In order for the '--version' option to work, you will need to have a +# suitably formatted comment like the one at the top of this file +# starting with '# Written by ' and ending with '# warranty; '. +# +# For '-h' and '--help' to work, you will also need a one line +# description of your script's purpose in a comment directly above the +# '# Written by ' line, like the one at the top of this file. +# +# The default options also support '--debug', which will turn on shell +# execution tracing (see the comment above debug_cmd below for another +# use), and '--verbose' and the func_verbose function to allow your script +# to display verbose messages only when your user has specified +# '--verbose'. +# +# After sourcing this file, you can plug processing for additional +# options by amending the variables from the 'Configuration' section +# below, and following the instructions in the 'Option parsing' +# section further down. + +## -------------- ## +## Configuration. ## +## -------------- ## + +# You should override these variables in your script after sourcing this +# file so that they reflect the customisations you have added to the +# option parser. + +# The usage line for option parsing errors and the start of '-h' and +# '--help' output messages. You can embed shell variables for delayed +# expansion at the time the message is displayed, but you will need to +# quote other shell meta-characters carefully to prevent them being +# expanded when the contents are evaled. +usage='$progpath [OPTION]...' + +# Short help message in response to '-h' and '--help'. Add to this or +# override it after sourcing this library to reflect the full set of +# options your script accepts. +usage_message="\ + --debug enable verbose shell tracing + -W, --warnings=CATEGORY + report the warnings falling in CATEGORY [all] + -v, --verbose verbosely report processing + --version print version information and exit + -h, --help print short or long help message and exit +" + +# Additional text appended to 'usage_message' in response to '--help'. +long_help_message=" +Warning categories include: + 'all' show all warnings + 'none' turn off all the warnings + 'error' warnings are treated as fatal errors" + +# Help message printed before fatal option parsing errors. +fatal_help="Try '\$progname --help' for more information." + + + +## ------------------------- ## +## Hook function management. ## +## ------------------------- ## + +# This section contains functions for adding, removing, and running hooks +# to the main code. A hook is just a named list of of function, that can +# be run in order later on. + +# func_hookable FUNC_NAME +# ----------------------- +# Declare that FUNC_NAME will run hooks added with +# 'func_add_hook FUNC_NAME ...'. +func_hookable () +{ + $debug_cmd + + func_append hookable_fns " $1" +} + + +# func_add_hook FUNC_NAME HOOK_FUNC +# --------------------------------- +# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must +# first have been declared "hookable" by a call to 'func_hookable'. +func_add_hook () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not accept hook functions." ;; + esac + + eval func_append ${1}_hooks '" $2"' +} + + +# func_remove_hook FUNC_NAME HOOK_FUNC +# ------------------------------------ +# Remove HOOK_FUNC from the list of functions called by FUNC_NAME. +func_remove_hook () +{ + $debug_cmd + + eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' +} + + +# func_run_hooks FUNC_NAME [ARG]... +# --------------------------------- +# Run all hook functions registered to FUNC_NAME. +# It is assumed that the list of hook functions contains nothing more +# than a whitespace-delimited list of legal shell function names, and +# no effort is wasted trying to catch shell meta-characters or preserve +# whitespace. +func_run_hooks () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not support hook funcions.n" ;; + esac + + eval _G_hook_fns=\$$1_hooks; shift + + for _G_hook in $_G_hook_fns; do + eval $_G_hook '"$@"' + + # store returned options list back into positional + # parameters for next 'cmd' execution. + eval _G_hook_result=\$${_G_hook}_result + eval set dummy "$_G_hook_result"; shift + done + + func_quote_for_eval ${1+"$@"} + func_run_hooks_result=$func_quote_for_eval_result +} + + + +## --------------- ## +## Option parsing. ## +## --------------- ## + +# In order to add your own option parsing hooks, you must accept the +# full positional parameter list in your hook function, remove any +# options that you action, and then pass back the remaining unprocessed +# options in '_result', escaped suitably for +# 'eval'. Like this: +# +# my_options_prep () +# { +# $debug_cmd +# +# # Extend the existing usage message. +# usage_message=$usage_message' +# -s, --silent don'\''t print informational messages +# ' +# +# func_quote_for_eval ${1+"$@"} +# my_options_prep_result=$func_quote_for_eval_result +# } +# func_add_hook func_options_prep my_options_prep +# +# +# my_silent_option () +# { +# $debug_cmd +# +# # Note that for efficiency, we parse as many options as we can +# # recognise in a loop before passing the remainder back to the +# # caller on the first unrecognised argument we encounter. +# while test $# -gt 0; do +# opt=$1; shift +# case $opt in +# --silent|-s) opt_silent=: ;; +# # Separate non-argument short options: +# -s*) func_split_short_opt "$_G_opt" +# set dummy "$func_split_short_opt_name" \ +# "-$func_split_short_opt_arg" ${1+"$@"} +# shift +# ;; +# *) set dummy "$_G_opt" "$*"; shift; break ;; +# esac +# done +# +# func_quote_for_eval ${1+"$@"} +# my_silent_option_result=$func_quote_for_eval_result +# } +# func_add_hook func_parse_options my_silent_option +# +# +# my_option_validation () +# { +# $debug_cmd +# +# $opt_silent && $opt_verbose && func_fatal_help "\ +# '--silent' and '--verbose' options are mutually exclusive." +# +# func_quote_for_eval ${1+"$@"} +# my_option_validation_result=$func_quote_for_eval_result +# } +# func_add_hook func_validate_options my_option_validation +# +# You'll alse need to manually amend $usage_message to reflect the extra +# options you parse. It's preferable to append if you can, so that +# multiple option parsing hooks can be added safely. + + +# func_options [ARG]... +# --------------------- +# All the functions called inside func_options are hookable. See the +# individual implementations for details. +func_hookable func_options +func_options () +{ + $debug_cmd + + func_options_prep ${1+"$@"} + eval func_parse_options \ + ${func_options_prep_result+"$func_options_prep_result"} + eval func_validate_options \ + ${func_parse_options_result+"$func_parse_options_result"} + + eval func_run_hooks func_options \ + ${func_validate_options_result+"$func_validate_options_result"} + + # save modified positional parameters for caller + func_options_result=$func_run_hooks_result +} + + +# func_options_prep [ARG]... +# -------------------------- +# All initialisations required before starting the option parse loop. +# Note that when calling hook functions, we pass through the list of +# positional parameters. If a hook function modifies that list, and +# needs to propogate that back to rest of this script, then the complete +# modified list must be put in 'func_run_hooks_result' before +# returning. +func_hookable func_options_prep +func_options_prep () +{ + $debug_cmd + + # Option defaults: + opt_verbose=false + opt_warning_types= + + func_run_hooks func_options_prep ${1+"$@"} + + # save modified positional parameters for caller + func_options_prep_result=$func_run_hooks_result +} + + +# func_parse_options [ARG]... +# --------------------------- +# The main option parsing loop. +func_hookable func_parse_options +func_parse_options () +{ + $debug_cmd + + func_parse_options_result= + + # this just eases exit handling + while test $# -gt 0; do + # Defer to hook functions for initial option parsing, so they + # get priority in the event of reusing an option name. + func_run_hooks func_parse_options ${1+"$@"} + + # Adjust func_parse_options positional parameters to match + eval set dummy "$func_run_hooks_result"; shift + + # Break out of the loop if we already parsed every option. + test $# -gt 0 || break + + _G_opt=$1 + shift + case $_G_opt in + --debug|-x) debug_cmd='set -x' + func_echo "enabling shell trace mode" + $debug_cmd + ;; + + --no-warnings|--no-warning|--no-warn) + set dummy --warnings none ${1+"$@"} + shift + ;; + + --warnings|--warning|-W) + test $# = 0 && func_missing_arg $_G_opt && break + case " $warning_categories $1" in + *" $1 "*) + # trailing space prevents matching last $1 above + func_append_uniq opt_warning_types " $1" + ;; + *all) + opt_warning_types=$warning_categories + ;; + *none) + opt_warning_types=none + warning_func=: + ;; + *error) + opt_warning_types=$warning_categories + warning_func=func_fatal_error + ;; + *) + func_fatal_error \ + "unsupported warning category: '$1'" + ;; + esac + shift + ;; + + --verbose|-v) opt_verbose=: ;; + --version) func_version ;; + -\?|-h) func_usage ;; + --help) func_help ;; + + # Separate optargs to long options (plugins may need this): + --*=*) func_split_equals "$_G_opt" + set dummy "$func_split_equals_lhs" \ + "$func_split_equals_rhs" ${1+"$@"} + shift + ;; + + # Separate optargs to short options: + -W*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-v*|-x*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) break ;; + -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + esac + done + + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + func_parse_options_result=$func_quote_for_eval_result +} + + +# func_validate_options [ARG]... +# ------------------------------ +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +func_hookable func_validate_options +func_validate_options () +{ + $debug_cmd + + # Display all warnings if -W was not given. + test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" + + func_run_hooks func_validate_options ${1+"$@"} + + # Bail if the options were screwed! + $exit_cmd $EXIT_FAILURE + + # save modified positional parameters for caller + func_validate_options_result=$func_run_hooks_result +} + + + +## ----------------- ## +## Helper functions. ## +## ----------------- ## + +# This section contains the helper functions used by the rest of the +# hookable option parser framework in ascii-betical order. + + +# func_fatal_help ARG... +# ---------------------- +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + eval \$ECHO \""$fatal_help"\" + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + + +# func_help +# --------- +# Echo long help message to standard output and exit. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message" + exit 0 +} + + +# func_missing_arg ARGNAME +# ------------------------ +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $debug_cmd + + func_error "Missing argument for '$1'." + exit_cmd=exit +} + + +# func_split_equals STRING +# ------------------------ +# Set func_split_equals_lhs and func_split_equals_rhs shell variables after +# splitting STRING at the '=' sign. +test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=${1%%=*} + func_split_equals_rhs=${1#*=} + test "x$func_split_equals_lhs" = "x$1" \ + && func_split_equals_rhs= + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` + func_split_equals_rhs= + test "x$func_split_equals_lhs" = "x$1" \ + || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` + } +fi #func_split_equals + + +# func_split_short_opt SHORTOPT +# ----------------------------- +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"} + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` + func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` + } +fi #func_split_short_opt + + +# func_usage +# ---------- +# Echo short help message to standard output and exit. +func_usage () +{ + $debug_cmd + + func_usage_message + $ECHO "Run '$progname --help |${PAGER-more}' for full usage" + exit 0 +} + + +# func_usage_message +# ------------------ +# Echo short help message to standard output. +func_usage_message () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + echo + $SED -n 's|^# || + /^Written by/{ + x;p;x + } + h + /^Written by/q' < "$progpath" + echo + eval \$ECHO \""$usage_message"\" +} + + +# func_version +# ------------ +# Echo version message to standard output and exit. +func_version () +{ + $debug_cmd + + printf '%s\n' "$progname $scriptversion" + $SED -n ' + /(C)/!b go + :more + /\./!{ + N + s|\n# | | + b more + } + :go + /^# Written by /,/# warranty; / { + s|^# || + s|^# *$|| + s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| + p + } + /^# Written by / { + s|^# || + p + } + /^warranty; /q' < "$progpath" + + exit $? +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: + +# Set a version string. +scriptversion='(GNU libtool) 2.4.6' + + +# func_echo ARG... +# ---------------- +# Libtool also displays the current mode in messages, so override +# funclib.sh func_echo with this custom definition. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_warning ARG... +# ------------------- +# Libtool warnings are not categorized, so override funclib.sh +# func_warning with this simpler definition. +func_warning () +{ + $debug_cmd + + $warning_func ${1+"$@"} +} + + +## ---------------- ## +## Options parsing. ## +## ---------------- ## + +# Hook in the functions to make sure our own options are parsed during +# the option parsing loop. + +usage='$progpath [OPTION]... [MODE-ARG]...' + +# Short help message in response to '-h'. +usage_message="Options: + --config show all configuration variables + --debug enable verbose shell tracing + -n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --mode=MODE use operation mode MODE + --no-warnings equivalent to '-Wnone' + --preserve-dup-deps don't remove duplicate dependency libraries + --quiet, --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + -v, --verbose print more informational messages than default + --version print version information + -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] + -h, --help, --help-all print short, long, or detailed help message +" + +# Additional text appended to 'usage_message' in response to '--help'. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. When passed as first option, +'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. +Try '$progname --help --mode=MODE' for a more detailed description of MODE. + +When reporting a bug, please describe a test case to reproduce it and +include the following information: + + host-triplet: $host + shell: $SHELL + compiler: $LTCC + compiler flags: $LTCFLAGS + linker: $LD (gnu? $with_gnu_ld) + version: $progname (GNU libtool) 2.4.6 + automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` + autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` + +Report bugs to . +GNU libtool home page: . +General help using GNU software: ." + exit 0 +} + + +# func_lo2o OBJECT-NAME +# --------------------- +# Transform OBJECT-NAME from a '.lo' suffix to the platform specific +# object suffix. + +lo2o=s/\\.lo\$/.$objext/ +o2lo=s/\\.$objext\$/.lo/ + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_lo2o () + { + case $1 in + *.lo) func_lo2o_result=${1%.lo}.$objext ;; + * ) func_lo2o_result=$1 ;; + esac + }' + + # func_xform LIBOBJ-OR-SOURCE + # --------------------------- + # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) + # suffix to a '.lo' libtool-object suffix. + eval 'func_xform () + { + func_xform_result=${1%.*}.lo + }' +else + # ...otherwise fall back to using sed. + func_lo2o () + { + func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` + } + + func_xform () + { + func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` + } +fi + + +# func_fatal_configuration ARG... +# ------------------------------- +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func__fatal_error ${1+"$@"} \ + "See the $PACKAGE documentation for more information." \ + "Fatal configuration error." +} + + +# func_config +# ----------- +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + + +# func_features +# ------------- +# Display the features supported by this script. +func_features () +{ + echo "host: $host" + if test yes = "$build_libtool_libs"; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test yes = "$build_old_libs"; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + + exit $? +} + + +# func_enable_tag TAGNAME +# ----------------------- +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname=$1 + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf=/$re_begincf/,/$re_endcf/p + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + + +# func_check_version_match +# ------------------------ +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# libtool_options_prep [ARG]... +# ----------------------------- +# Preparation for options parsed by libtool. +libtool_options_prep () +{ + $debug_mode + + # Option defaults: + opt_config=false + opt_dlopen= + opt_dry_run=false + opt_help=false + opt_mode= + opt_preserve_dup_deps=false + opt_quiet=false + + nonopt= + preserve_args= + + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; + esac + + # Pass back the list of options. + func_quote_for_eval ${1+"$@"} + libtool_options_prep_result=$func_quote_for_eval_result +} +func_add_hook func_options_prep libtool_options_prep + + +# libtool_parse_options [ARG]... +# --------------------------------- +# Provide handling for libtool specific options. +libtool_parse_options () +{ + $debug_cmd + + # Perform our own loop to consume as many options as possible in + # each iteration. + while test $# -gt 0; do + _G_opt=$1 + shift + case $_G_opt in + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + + --config) func_config ;; + + --dlopen|-dlopen) + opt_dlopen="${opt_dlopen+$opt_dlopen +}$1" + shift + ;; + + --preserve-dup-deps) + opt_preserve_dup_deps=: ;; + + --features) func_features ;; + + --finish) set dummy --mode finish ${1+"$@"}; shift ;; + + --help) opt_help=: ;; + + --help-all) opt_help=': help-all' ;; + + --mode) test $# = 0 && func_missing_arg $_G_opt && break + opt_mode=$1 + case $1 in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $_G_opt" + exit_cmd=exit + break + ;; + esac + shift + ;; + + --no-silent|--no-quiet) + opt_quiet=false + func_append preserve_args " $_G_opt" + ;; + + --no-warnings|--no-warning|--no-warn) + opt_warning=false + func_append preserve_args " $_G_opt" + ;; + + --no-verbose) + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --silent|--quiet) + opt_quiet=: + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --tag) test $# = 0 && func_missing_arg $_G_opt && break + opt_tag=$1 + func_append preserve_args " $_G_opt $1" + func_enable_tag "$1" + shift + ;; + + --verbose|-v) opt_quiet=false + opt_verbose=: + func_append preserve_args " $_G_opt" + ;; + + # An option not handled by this hook function: + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + esac + done + + + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + libtool_parse_options_result=$func_quote_for_eval_result +} +func_add_hook func_parse_options libtool_parse_options + + + +# libtool_validate_options [ARG]... +# --------------------------------- +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +libtool_validate_options () +{ + # save first non-option argument + if test 0 -lt $#; then + nonopt=$1 + shift + fi + + # preserve --debug + test : = "$debug_cmd" || func_append preserve_args " --debug" + + case $host in + # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 + # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 + *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + test yes != "$build_libtool_libs" \ + && test yes != "$build_old_libs" \ + && func_fatal_configuration "not configured to build any kind of library" + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test execute != "$opt_mode"; then + func_error "unrecognized option '-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help=$help + help="Try '$progname --help --mode=$opt_mode' for more information." + } + + # Pass back the unparsed argument list + func_quote_for_eval ${1+"$@"} + libtool_validate_options_result=$func_quote_for_eval_result +} +func_add_hook func_validate_options libtool_validate_options + + +# Process options as early as possible so that --help and --version +# can return quickly. +func_options ${1+"$@"} +eval set dummy "$func_options_result"; shift + + + +## ----------- ## +## Main. ## +## ----------- ## + +magic='%%%MAGIC variable%%%' +magic_exe='%%%MAGIC EXE variable%%%' + +# Global variables. +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# func_generated_by_libtool +# True iff stdin has been generated by Libtool. This function is only +# a basic sanity check; it will hardly flush out determined imposters. +func_generated_by_libtool_p () +{ + $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if 'file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case $lalib_p_line in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test yes = "$lalib_p" +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + test -f "$1" && + $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $debug_cmd + + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# 'FILE.' does not work on cygwin managed mounts. +func_source () +{ + $debug_cmd + + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case $lt_sysroot:$1 in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result='='$func_stripname_result + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $debug_cmd + + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with '--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=$1 + if test yes = "$build_libtool_libs"; then + write_lobj=\'$2\' + else + write_lobj=none + fi + + if test yes = "$build_old_libs"; then + write_oldobj=\'$3\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T </dev/null` + if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $debug_cmd + + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result= + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result"; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $debug_cmd + + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $debug_cmd + + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $debug_cmd + + if test -z "$2" && test -n "$1"; then + func_error "Could not determine host file name corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result=$1 + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $debug_cmd + + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " '$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result=$3 + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $debug_cmd + + case $4 in + $1 ) func_to_host_path_result=$3$func_to_host_path_result + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via '$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $debug_cmd + + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $debug_cmd + + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result=$1 +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result=$func_convert_core_msys_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result=$func_convert_core_file_wine_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via '$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $debug_cmd + + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd=func_convert_path_$func_stripname_result + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $debug_cmd + + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result=$1 +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_msys_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_path_wine_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_dll_def_p FILE +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with _LT_DLL_DEF_P in libtool.m4 +func_dll_def_p () +{ + $debug_cmd + + func_dll_def_p_tmp=`$SED -n \ + -e 's/^[ ]*//' \ + -e '/^\(;.*\)*$/d' \ + -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ + -e q \ + "$1"` + test DEF = "$func_dll_def_p_tmp" +} + + +# func_mode_compile arg... +func_mode_compile () +{ + $debug_cmd + + # Get the compilation command and the source file. + base_compile= + srcfile=$nonopt # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg=$arg + arg_mode=normal + ;; + + target ) + libobj=$arg + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify '-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append later " $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs=$IFS; IFS=, + for arg in $args; do + IFS=$save_ifs + func_append_quoted lastarg "$arg" + done + IFS=$save_ifs + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append base_compile " $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg=$srcfile + srcfile=$arg + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with '-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj=$func_basename_result + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from '$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test yes = "$build_libtool_libs" \ + || func_fatal_configuration "cannot build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_for_eval "$libobj" + test "X$libobj" != "X$func_quote_for_eval_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name '$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname=$func_basename_result + xdir=$func_dirname_result + lobj=$xdir$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test yes = "$build_old_libs"; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test no = "$compiler_c_o"; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext + lockfile=$output_obj.lock + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test yes = "$need_locks"; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test warn = "$need_locks"; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test yes = "$build_libtool_libs"; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test no != "$pic_mode"; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test yes = "$suppress_opt"; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test yes = "$build_old_libs"; then + if test yes != "$pic_mode"; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test yes = "$compiler_c_o"; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test no != "$need_locks"; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test compile = "$opt_mode" && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a '.o' file suitable for static linking + -static only build a '.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +COMPILE-COMMAND is a command to be used in creating a 'standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix '.c' with the +library object suffix, '.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to '-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the '--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the 'install' or 'cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE use a list of object files found in FILE to specify objects + -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +All other options (arguments beginning with '-') are ignored. + +Every other argument is treated as a filename. Files ending in '.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in '.la', then a libtool library is created, +only library objects ('.lo' files) may be specified, and '-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created +using 'ar' and 'ranlib', or on Windows using 'lib'. + +If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode '$opt_mode'" + ;; + esac + + echo + $ECHO "Try '$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test : = "$opt_help"; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | $SED -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + $SED '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $debug_cmd + + # The first argument is the command name. + cmd=$nonopt + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "'$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "'$file' was not linked with '-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir=$func_dirname_result + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir=$func_dirname_result + ;; + + *) + func_warning "'-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir=$absdir + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic=$magic + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file=$progdir/$program + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file=$progdir/$program + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if $opt_dry_run; then + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + else + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd=\$cmd$args + fi +} + +test execute = "$opt_mode" && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $debug_cmd + + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "'$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument '$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and '=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_quiet && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the '-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the '$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the '$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the '$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" + fi + echo + + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test finish = "$opt_mode" && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $debug_cmd + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || + # Allow the use of GNU shtool's install command. + case $nonopt in *shtool*) :;; *) false;; esac + then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + func_append install_prog "$func_quote_for_eval_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=false + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=: ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test X-m = "X$prev" && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + func_append install_prog " $func_quote_for_eval_result" + if test -n "$arg2"; then + func_quote_for_eval "$arg2" + fi + func_append install_shared_prog " $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the '$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_for_eval "$install_override_mode" + func_append install_shared_prog " -m $func_quote_for_eval_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=: + if $isdir; then + destdir=$dest + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir=$func_dirname_result + destname=$func_basename_result + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "'$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "'$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir=$func_dirname_result + func_append dir "$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking '$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname=$1 + shift + + srcname=$realname + test -n "$relink_command" && srcname=${realname}T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme=$stripme + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme= + ;; + esac + ;; + os2*) + case $realname in + *_dll.a) + tstripme= + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try 'ln -sf' first, because the 'ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib=$destdir/$realname + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name=$func_basename_result + instname=$dir/${name}i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append staticlibs " $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest=$destfile + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to '$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test yes = "$build_old_libs"; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext= + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=.exe + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script '$wrapper'" + + finalize=: + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "'$lib' has not been installed in '$libdir'" + finalize=false + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test no = "$fast_install" && test -n "$relink_command"; then + $opt_dry_run || { + if $finalize; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file=$func_basename_result + outputname=$tmpdir/$file + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_quiet || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink '$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file=$outputname + else + func_warning "cannot relink '$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name=$func_basename_result + + # Set up the ranlib parameters. + oldlib=$destdir/$name + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $tool_oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run '$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test install = "$opt_mode" && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $debug_cmd + + my_outputname=$1 + my_originator=$2 + my_pic_p=${3-false} + my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms=${my_outputname}S.c + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist=$output_objdir/$my_outputname.nm + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* External symbol declarations for the compiler. */\ +" + + if test yes = "$dlself"; then + func_verbose "generating symbol list for '$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from '$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols=$output_objdir/$outputname.exp + $opt_dry_run || { + $RM $export_symbols + eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from '$dlprefile'" + func_basename "$dlprefile" + name=$func_basename_result + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename= + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname"; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename=$func_basename_result + else + # no lafile. user explicitly requested -dlpreopen . + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename"; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + func_show_eval '$RM "${nlist}I"' + if test -n "$global_symbol_to_import"; then + eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[];\ +" + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ +static void lt_syminit(void) +{ + LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; + for (; symbol->name; ++symbol) + {" + $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" + echo >> "$output_objdir/$my_dlsyms" "\ + } +}" + fi + echo >> "$output_objdir/$my_dlsyms" "\ +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{ {\"$my_originator\", (void *) 0}," + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ + {\"@INIT@\", (void *) <_syminit}," + fi + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + $my_pic_p && pic_flag_for_symtable=" $pic_flag" + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' + + # Transform the symbol file into the correct name. + symfileobj=$output_objdir/${my_outputname}S.$objext + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for '$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $debug_cmd + + win32_libid_type=unknown + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + case $nm_interface in + "MS dumpbin") + if func_cygming_ms_implib_p "$1" || + func_cygming_gnu_implib_p "$1" + then + win32_nmres=import + else + win32_nmres= + fi + ;; + *) + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' + 1,100{ + / I /{ + s|.*|import| + p + q + } + }'` + ;; + esac + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $debug_cmd + + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $debug_cmd + + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive that possess that section. Heuristic: eliminate + # all those that have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $debug_cmd + + if func_cygming_gnu_implib_p "$1"; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1"; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result= + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $debug_cmd + + f_ex_an_ar_dir=$1; shift + f_ex_an_ar_oldlib=$1 + if test yes = "$lock_old_archive_extraction"; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test yes = "$lock_old_archive_extraction"; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $debug_cmd + + my_gentop=$1; shift + my_oldlibs=${1+"$@"} + my_oldobjs= + my_xlib= + my_xabs= + my_xdir= + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib=$func_basename_result + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir=$my_gentop/$my_xlib_u + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + func_basename "$darwin_archive" + darwin_base_archive=$func_basename_result + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches; do + func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" + $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" + cd "unfat-$$/$darwin_base_archive-$darwin_arch" + func_extract_an_archive "`pwd`" "$darwin_base_archive" + cd "$darwin_curdir" + $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result=$my_oldobjs +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory where it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + file=\"\$0\"" + + qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=\"$qECHO\" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case \" \$* \" in + *\\ --lt-*) + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done ;; + esac + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test yes = "$fast_install"; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + \$ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +#else +# include +# include +# ifdef __CYGWIN__ +# include +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* declarations of non-ANSI functions */ +#if defined __MINGW32__ +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined __CYGWIN__ +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined other_platform || defined ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined _MSC_VER +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +#elif defined __MINGW32__ +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined __CYGWIN__ +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined other platforms ... */ +#endif + +#if defined PATH_MAX +# define LT_PATHMAX PATH_MAX +#elif defined MAXPATHLEN +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ + defined __OS2__ +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free (stale); stale = 0; } \ +} while (0) + +#if defined LT_DEBUGWRAPPER +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + size_t tmp_len; + char *concat_name; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined HAVE_DOS_BASED_FILE_SYSTEM + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined HAVE_DOS_BASED_FILE_SYSTEM + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = (size_t) (q - p); + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (STREQ (str, pat)) + *str = '\0'; + } + return str; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + size_t len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + size_t orig_value_len = strlen (orig_value); + size_t add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + size_t len = strlen (new_value); + while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[--len] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -n -e ' +s/^\(.\{79\}\)\(..*\)/\1\ +\2/ +h +s/\([\\"]\)/\\\1/g +s/$/\\n/ +s/\([^\n]*\).*/ fputs ("\1", f);/p +g +D' + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $debug_cmd + + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_suncc_cstd_abi +# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! +# Several compiler flags select an ABI that is incompatible with the +# Cstd library. Avoid specifying it if any are in CXXFLAGS. +func_suncc_cstd_abi () +{ + $debug_cmd + + case " $compile_command " in + *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) + suncc_use_cstd_abi=no + ;; + *) + suncc_use_cstd_abi=yes + ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $debug_cmd + + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # what system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll that has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + os2dllname= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=false + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module=$wl-single_module + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test yes != "$build_libtool_libs" \ + && func_fatal_configuration "cannot build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg=$1 + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir=$arg + prev= + continue + ;; + dlfiles|dlprefiles) + $preload || { + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=: + } + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test no = "$dlself"; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test dlprefiles = "$prev"; then + dlself=yes + elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test dlfiles = "$prev"; then + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols=$arg + test -f "$arg" \ + || func_fatal_error "symbol file '$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex=$arg + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir=$arg + prev= + continue + ;; + mllvm) + # Clang does not use LLVM to link, so we can simply discard any + # '-mllvm $arg' options when doing the link step. + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + if test none != "$pic_object"; then + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + fi + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file '$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + os2dllname) + os2dllname=$arg + prev= + continue + ;; + precious_regex) + precious_files_regex=$arg + prev= + continue + ;; + release) + release=-$arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test rpath = "$prev"; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds=$arg + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg=$arg + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "'-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test X-export-symbols = "X$arg"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between '-L' and '$1'" + else + func_fatal_error "need path for '-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of '$dir'" + dir=$absdir + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test X-lc = "X$arg" || test X-lm = "X$arg"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test X-lc = "X$arg" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc due to us having libc/libc_r. + test X-lc = "X$arg" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + func_append deplibs " System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test X-lc = "X$arg" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test X-lc = "X$arg" && continue + ;; + esac + elif test X-lc_r = "X$arg"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + func_append deplibs " $arg" + continue + ;; + + -mllvm) + prev=mllvm + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module=$wl-multi_module + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "'-no-install' is ignored for $host" + func_warning "assuming '-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -os2dllname) + prev=os2dllname + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $func_quote_for_eval_result" + func_append compiler_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $wl$func_quote_for_eval_result" + func_append compiler_flags " $wl$func_quote_for_eval_result" + func_append linker_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # -fstack-protector* stack protector flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -stdlib=* select c++ std lib with clang + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + -Z*) + if test os2 = "`expr $host : '.*\(os2\)'`"; then + # OS/2 uses -Zxxx to specify OS/2-specific options + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case $arg in + -Zlinker | -Zstack) + prev=xcompiler + ;; + esac + continue + else + # Otherwise treat like 'Some other compiler flag' below + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + fi + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + test none = "$pic_object" || { + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + } + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test dlfiles = "$prev"; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test dlprefiles = "$prev"; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the '$prevarg' option requires an argument" + + if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname=$func_basename_result + libobjs_save=$libobjs + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + # Definition is injected by LT_CONFIG during libtool generation. + func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" + + func_dirname "$output" "/" "" + output_objdir=$func_dirname_result$objdir + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_preserve_dup_deps; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append libs " $deplib" + done + + if test lib = "$linkmode"; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append pre_post_deps " $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=false + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test lib,link = "$linkmode,$pass"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs=$tmp_deplibs + fi + + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass"; then + libs=$deplibs + deplibs= + fi + if test prog = "$linkmode"; then + case $pass in + dlopen) libs=$dlfiles ;; + dlpreopen) libs=$dlprefiles ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + esac + fi + if test lib,dlpreopen = "$linkmode,$pass"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs=$dlprefiles + fi + if test dlopen = "$pass"; then + # Collect dlpreopened libraries + save_deplibs=$deplibs + deplibs= + fi + + for deplib in $libs; do + lib= + found=false + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test lib != "$linkmode" && test prog != "$linkmode"; then + func_warning "'-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test lib = "$linkmode"; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib=$searchdir/lib$name$search_ext + if test -f "$lib"; then + if test .la = "$search_ext"; then + found=: + else + found=false + fi + break 2 + fi + done + done + if $found; then + # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll=$l + done + if test "X$ll" = "X$old_library"; then # only static version available + found=false + func_dirname "$lib" "" "." + ladir=$func_dirname_result + lib=$ladir/$old_library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + else + # deplib doesn't seem to be a libtool library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + ;; # -l + *.ltframework) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test conv = "$pass" && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + prog) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + if test scan = "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "'-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test link = "$pass"; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=false + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=: + fi + ;; + pass_all) + valid_a_lib=: + ;; + esac + if $valid_a_lib; then + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + else + echo + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." + fi + ;; + esac + continue + ;; + prog) + if test link != "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + elif test prog = "$linkmode"; then + if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=: + continue + ;; + esac # case $deplib + + $found || test -f "$lib" \ + || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "'$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir=$func_dirname_result + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass" || + { test prog != "$linkmode" && test lib != "$linkmode"; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" + fi + + if test conv = "$pass"; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + elif test prog != "$linkmode" && test lib != "$linkmode"; then + func_fatal_error "'$lib' is not a convenience library" + fi + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test yes = "$prefer_static_libs" || + test built,no = "$prefer_static_libs,$installed"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib=$l + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + + # This library was specified with -dlopen. + if test dlopen = "$pass"; then + test -z "$libdir" \ + && func_fatal_error "cannot -dlopen a convenience library: '$lib'" + if test -z "$dlname" || + test yes != "$dlopen_support" || + test no = "$build_libtool_libs" + then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + func_append dlprefiles " $lib $dependency_libs" + else + func_append newdlfiles " $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of '$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir=$ladir + fi + ;; + esac + func_basename "$lib" + laname=$func_basename_result + + # Find the relevant object directory and library name. + if test yes = "$installed"; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library '$lib' was moved." + dir=$ladir + absdir=$abs_ladir + libdir=$abs_ladir + else + dir=$lt_sysroot$libdir + absdir=$lt_sysroot$libdir + fi + test yes = "$hardcode_automatic" && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir=$ladir + absdir=$abs_ladir + # Remove this search path later + func_append notinst_path " $abs_ladir" + else + dir=$ladir/$objdir + absdir=$abs_ladir/$objdir + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test dlpreopen = "$pass"; then + if test -z "$libdir" && test prog = "$linkmode"; then + func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" + fi + case $host in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test lib = "$linkmode"; then + deplibs="$dir/$old_library $deplibs" + elif test prog,link = "$linkmode,$pass"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test prog = "$linkmode" && test link != "$pass"; then + func_append newlib_search_path " $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=false + if test no != "$link_all_deplibs" || test -z "$library_names" || + test no = "$build_libtool_libs"; then + linkalldeplibs=: + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + esac + # Need to link against all dependency_libs? + if $linkalldeplibs; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test prog,link = "$linkmode,$pass"; then + if test -n "$library_names" && + { { test no = "$prefer_static_libs" || + test built,yes = "$prefer_static_libs,$installed"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then + # Make sure the rpath contains only unique directories. + case $temp_rpath: in + *"$absdir:"*) ;; + *) func_append temp_rpath "$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if $alldeplibs && + { test pass_all = "$deplibs_check_method" || + { test yes = "$build_libtool_libs" && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test built = "$use_static_libs" && test yes = "$installed"; then + use_static_libs=no + fi + if test -n "$library_names" && + { test no = "$use_static_libs" || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc* | *os2*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test no = "$installed"; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule= + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule=$dlpremoduletest + break + fi + done + if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then + echo + if test prog = "$linkmode"; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test lib = "$linkmode" && + test yes = "$hardcode_into_libs"; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname=$1 + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname=$dlname + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc* | *os2*) + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + esac + eval soname=\"$soname_spec\" + else + soname=$realname + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot=$soname + func_basename "$soroot" + soname=$func_basename_result + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from '$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for '$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test prog = "$linkmode" || test relink != "$opt_mode"; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test no = "$hardcode_direct"; then + add=$dir/$linklib + case $host in + *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; + *-*-sysv4*uw2*) add_dir=-L$dir ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir=-L$dir ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we cannot + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library"; then + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" + else + add=$dir/$old_library + fi + elif test -n "$old_library"; then + add=$dir/$old_library + fi + fi + esac + elif test no = "$hardcode_minus_L"; then + case $host in + *-*-sunos*) add_shlibpath=$dir ;; + esac + add_dir=-L$dir + add=-l$name + elif test no = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + relink) + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$dir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$absdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test yes != "$lib_linked"; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; + esac + fi + if test prog = "$linkmode"; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test yes != "$hardcode_direct" && + test yes != "$hardcode_minus_L" && + test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test prog = "$linkmode" || test relink = "$opt_mode"; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$libdir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$libdir + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + add=-l$name + elif test yes = "$hardcode_automatic"; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib"; then + add=$inst_prefix_dir$libdir/$linklib + else + add=$libdir/$linklib + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir=-L$libdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + fi + + if test prog = "$linkmode"; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test prog = "$linkmode"; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test unsupported != "$hardcode_direct"; then + test -n "$old_library" && linklib=$old_library + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test yes = "$build_libtool_libs"; then + # Not a shared library + if test pass_all != "$deplibs_check_method"; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + $ECHO "*** Warning: This system cannot link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test yes = "$module"; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test lib = "$linkmode"; then + if test -n "$dependency_libs" && + { test yes != "$hardcode_into_libs" || + test yes = "$build_old_libs" || + test yes = "$link_static"; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs=$temp_deplibs + fi + + func_append newlib_search_path " $absdir" + # Link against this library + test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test no != "$link_all_deplibs"; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path=$deplib ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of '$dir'" + absdir=$dir + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names"; then + for tmp in $deplibrary_names; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl"; then + depdepl=$absdir/$objdir/$depdepl + darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" + func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" + path= + fi + fi + ;; + *) + path=-L$absdir/$objdir + ;; + esac + else + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "'$deplib' seems to be moved" + + path=-L$absdir + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test link = "$pass"; then + if test prog = "$linkmode"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs=$newdependency_libs + if test dlpreopen = "$pass"; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test dlopen != "$pass"; then + test conv = "$pass" || { + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) func_append lib_search_path " $dir" ;; + esac + done + newlib_search_path= + } + + if test prog,link = "$linkmode,$pass"; then + vars="compile_deplibs finalize_deplibs" + else + vars=deplibs + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append tmp_libs " $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + + # Add Sun CC postdeps if required: + test CXX = "$tagname" && { + case $host_os in + linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C++ 5.9 + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + + solaris*) + func_cc_basename "$CC" + case $func_cc_basename_result in + CC* | sunCC*) + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + esac + } + + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i= + ;; + esac + if test -n "$i"; then + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test prog = "$linkmode"; then + dlfiles=$newdlfiles + fi + if test prog = "$linkmode" || test lib = "$linkmode"; then + dlprefiles=$newdlprefiles + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "'-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "'-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs=$output + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form 'libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test no = "$module" \ + && func_fatal_help "libtool library '$output' must begin with 'lib'" + + if test no != "$need_lib_prefix"; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test pass_all != "$deplibs_check_method"; then + func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test no = "$dlself" \ + || func_warning "'-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test 1 -lt "$#" \ + && func_warning "ignoring multiple '-rpath's for a libtool library" + + install_libdir=$1 + + oldlibs= + if test -z "$rpath"; then + if test yes = "$build_libtool_libs"; then + # Building a libtool convenience library. + # Some compilers have problems with a '.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "'-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs=$IFS; IFS=: + set dummy $vinfo 0 0 0 + shift + IFS=$save_ifs + + test -n "$7" && \ + func_fatal_help "too many parameters to '-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major=$1 + number_minor=$2 + number_revision=$3 + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # that has an extra 1 added just for fun + # + case $version_type in + # correct linux to gnu/linux during the next big refactor + darwin|freebsd-elf|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_revision + ;; + freebsd-aout|qnx|sunos) + current=$number_major + revision=$number_minor + age=0 + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_minor + lt_irix_increment=no + ;; + esac + ;; + no) + current=$1 + revision=$2 + age=$3 + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT '$current' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION '$revision' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE '$age' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE '$age' is greater than the current interface number '$current'" + func_fatal_error "'$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + # On Darwin other compilers + case $CC in + nagfor*) + verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + ;; + *) + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + esac + ;; + + freebsd-aout) + major=.$current + versuffix=.$current.$revision + ;; + + freebsd-elf) + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + irix | nonstopux) + if test no = "$lt_irix_increment"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring=$verstring_prefix$major.$revision + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test 0 -ne "$loop"; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring_prefix$major.$iface:$verstring + done + + # Before this point, $major must not contain '.'. + major=.$major + versuffix=$major.$revision + ;; + + linux) # correct to gnu/linux during the next big refactor + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=.$current.$age.$revision + verstring=$current.$age.$revision + + # Add in all the interfaces that we are compatible with. + loop=$age + while test 0 -ne "$loop"; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring:$iface.0 + done + + # Make executables depend on our current version. + func_append verstring ":$current.0" + ;; + + qnx) + major=.$current + versuffix=.$current + ;; + + sco) + major=.$current + versuffix=.$current + ;; + + sunos) + major=.$current + versuffix=.$current.$revision + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 file systems. + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + + *) + func_fatal_configuration "unknown library version type '$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring=0.0 + ;; + esac + if test no = "$need_version"; then + versuffix= + else + versuffix=.0.0 + fi + fi + + # Remove version info from name if versioning should be avoided + if test yes,no = "$avoid_version,$need_version"; then + major= + versuffix= + verstring= + fi + + # Check to see if the archive will have undefined symbols. + if test yes = "$allow_undefined"; then + if test unsupported = "$allow_undefined_flag"; then + if test yes = "$build_old_libs"; then + func_warning "undefined symbols not allowed in $host shared libraries; building static only" + build_libtool_libs=no + else + func_fatal_error "can't build $host shared library unless -no-undefined is specified" + fi + fi + else + # Don't allow undefined symbols. + allow_undefined_flag=$no_undefined_flag + fi + + fi + + func_generate_dlsyms "$libname" "$libname" : + func_append libobjs " $symfileobj" + test " " = "$libobjs" && libobjs= + + if test relink != "$opt_mode"; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) + if test -n "$precious_files_regex"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles=$dlfiles + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) func_append dlfiles " $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles=$dlprefiles + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test yes = "$build_libtool_libs"; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test yes = "$build_libtool_need_lc"; then + func_append deplibs " -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release= + versuffix= + major= + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib=$potent_lib + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | $SED 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; + *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib= + ;; + esac + fi + if test -n "$a_deplib"; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib=$potent_lib # see symlink-check above in file_magic test + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs= + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + for i in $predeps $postdeps; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + echo + if test none = "$deplibs_check_method"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + ;; + esac + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + if test yes = "$droppeddeps"; then + if test yes = "$module"; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test no = "$allow_undefined"; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + deplibs=$new_libs + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test yes = "$build_libtool_libs"; then + # Remove $wl instances when linking with ld. + # FIXME: should test the right _cmds variable. + case $archive_cmds in + *\$LD\ *) wl= ;; + esac + if test yes = "$hardcode_into_libs"; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath=$finalize_rpath + test relink = "$opt_mode" || rpath=$compile_rpath$rpath + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath=$finalize_shlibpath + test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname=$1 + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname=$realname + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib=$output_objdir/$realname + linknames= + for link + do + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols=$output_objdir/$libname.uexp + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + func_dll_def_p "$export_symbols" || { + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols=$export_symbols + export_symbols= + always_export_symbols=yes + } + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs=$IFS; IFS='~' + for cmd1 in $cmds; do + IFS=$save_ifs + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test yes = "$try_normal_branch" \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=$output_objdir/$output_la.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS=$save_ifs + if test -n "$export_symbols_regex" && test : != "$skipped_export"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test : != "$skipped_export" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs=$tmp_deplibs + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test yes = "$compiler_needs_object" && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test : != "$skipped_export" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then + output=$output_objdir/$output_la.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then + output=$output_objdir/$output_la.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test yes = "$compiler_needs_object"; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-$k.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test -z "$objlist" || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test 1 -eq "$k"; then + # The first file doesn't have a previous command to add. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-$k.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-$k.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + ${skipped_export-false} && { + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + } + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs=$IFS; IFS='~' + for cmd in $concat_cmds; do + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + ${skipped_export-false} && { + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + } + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs=$IFS; IFS='~' + for cmd in $cmds; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test yes = "$module" || test yes = "$export_dynamic"; then + # On all known operating systems, these are identical. + dlname=$soname + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "'-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object '$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj=$output + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # if reload_cmds runs $LD directly, get rid of -Wl from + # whole_archive_flag_spec and hope we can get by with turning comma + # into space. + case $reload_cmds in + *\$LD[\ \$]*) wl= ;; + esac + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags + else + gentop=$output_objdir/${obj}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test yes = "$build_libtool_libs" || libobjs=$non_pic_objects + + # Create the old-style object. + reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs + + output=$obj + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + test yes = "$build_libtool_libs" || { + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + } + + if test -n "$pic_flag" || test default != "$pic_mode"; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output=$libobj + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "'-release' is ignored for programs" + + $preload \ + && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ + && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test CXX = "$tagname"; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " $wl-bind_at_load" + func_append finalize_command " $wl-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs=$new_libs + + + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath=$rpath + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append finalize_perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath=$rpath + + if test -n "$libobjs" && test yes = "$build_old_libs"; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" false + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=: + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=false + ;; + *cygwin* | *mingw* ) + test yes = "$build_libtool_libs" || wrappers_required=false + ;; + *) + if test no = "$need_relink" || test yes != "$build_libtool_libs"; then + wrappers_required=false + fi + ;; + esac + $wrappers_required || { + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command=$compile_command$compile_rpath + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.$objext"; then + func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' + fi + + exit $exit_status + } + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + func_append rpath "$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test yes = "$no_install"; then + # We don't need to create a wrapper script. + link_command=$compile_var$compile_command$compile_rpath + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + exit $EXIT_SUCCESS + fi + + case $hardcode_action,$fast_install in + relink,*) + # Fast installation is not supported + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "'$output' will be relinked during installation" + ;; + *,yes) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + ;; + *,no) + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + ;; + *,needless) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command= + ;; + esac + + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource=$output_path/$objdir/lt-$output_name.c + cwrapper=$output_path/$output_name.exe + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host"; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + case $build_libtool_libs in + convenience) + oldobjs="$libobjs_save $symfileobj" + addlibs=$convenience + build_libtool_libs=no + ;; + module) + oldobjs=$libobjs_save + addlibs=$old_convenience + build_libtool_libs=no + ;; + *) + oldobjs="$old_deplibs $non_pic_objects" + $preload && test -f "$symfileobj" \ + && func_append oldobjs " $symfileobj" + addlibs=$old_convenience + ;; + esac + + if test -n "$addlibs"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append oldobjs " $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase=$func_basename_result + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj"; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test -z "$oldobjs"; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test yes = "$build_old_libs" && old_library=$libname.$libext + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + if test yes = "$hardcode_automatic"; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test yes = "$installed"; then + if test -z "$install_libdir"; then + break + fi + output=$output_objdir/${outputname}i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name=$func_basename_result + func_resolve_sysroot "$deplib" + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs=$newdependency_libs + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles=$newdlprefiles + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles=$newdlprefiles + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test -n "$bindir"; then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result/$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test no,yes = "$installed,$need_relink"; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +if test link = "$opt_mode" || test relink = "$opt_mode"; then + func_mode_link ${1+"$@"} +fi + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $debug_cmd + + RM=$nonopt + files= + rmforce=false + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + for arg + do + case $arg in + -f) func_append RM " $arg"; rmforce=: ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir=$func_dirname_result + if test . = "$dir"; then + odir=$objdir + else + odir=$dir/$objdir + fi + func_basename "$file" + name=$func_basename_result + test uninstall = "$opt_mode" && odir=$dir + + # Remember odir for removal later, being careful to avoid duplicates + if test clean = "$opt_mode"; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif $rmforce; then + continue + fi + + rmfiles=$file + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case $opt_mode in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && test none != "$pic_object"; then + func_append rmfiles " $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && test none != "$non_pic_object"; then + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test clean = "$opt_mode"; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.$objext" + if test yes = "$fast_install" && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name" + fi + if test "X$noexename" != "X$name"; then + func_append rmfiles " $odir/lt-$noexename.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the $objdir's in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then + func_mode_uninstall ${1+"$@"} +fi + +test -z "$opt_mode" && { + help=$generic_help + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode '$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# where we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/cogl/build/missing b/cogl/build/missing new file mode 100755 index 0000000..f62bbae --- /dev/null +++ b/cogl/build/missing @@ -0,0 +1,215 @@ +#! /bin/sh +# Common wrapper for a few potentially missing GNU programs. + +scriptversion=2013-10-28.13; # UTC + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Originally written by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program 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 General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try '$0 --help' for more information" + exit 1 +fi + +case $1 in + + --is-lightweight) + # Used by our autoconf macros to check whether the available missing + # script is modern enough. + exit 0 + ;; + + --run) + # Back-compat with the calling convention used by older automake. + shift + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due +to PROGRAM being missing or too old. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal autoconf autoheader autom4te automake makeinfo + bison yacc flex lex help2man + +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" + exit 1 + ;; + +esac + +# Run the given program, remember its exit status. +"$@"; st=$? + +# If it succeeded, we are done. +test $st -eq 0 && exit 0 + +# Also exit now if we it failed (or wasn't found), and '--version' was +# passed; such an option is passed most likely to detect whether the +# program is present and works. +case $2 in --version|--help) exit $st;; esac + +# Exit code 63 means version mismatch. This often happens when the user +# tries to use an ancient version of a tool on a file that requires a +# minimum version. +if test $st -eq 63; then + msg="probably too old" +elif test $st -eq 127; then + # Program was missing. + msg="missing on your system" +else + # Program was found and executed, but failed. Give up. + exit $st +fi + +perl_URL=http://www.perl.org/ +flex_URL=http://flex.sourceforge.net/ +gnu_software_URL=http://www.gnu.org/software + +program_details () +{ + case $1 in + aclocal|automake) + echo "The '$1' program is part of the GNU Automake package:" + echo "<$gnu_software_URL/automake>" + echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/autoconf>" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + autoconf|autom4te|autoheader) + echo "The '$1' program is part of the GNU Autoconf package:" + echo "<$gnu_software_URL/autoconf/>" + echo "It also requires GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + esac +} + +give_advice () +{ + # Normalize program name to check for. + normalized_program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + + printf '%s\n' "'$1' is $msg." + + configure_deps="'configure.ac' or m4 files included by 'configure.ac'" + case $normalized_program in + autoconf*) + echo "You should only need it if you modified 'configure.ac'," + echo "or m4 files included by it." + program_details 'autoconf' + ;; + autoheader*) + echo "You should only need it if you modified 'acconfig.h' or" + echo "$configure_deps." + program_details 'autoheader' + ;; + automake*) + echo "You should only need it if you modified 'Makefile.am' or" + echo "$configure_deps." + program_details 'automake' + ;; + aclocal*) + echo "You should only need it if you modified 'acinclude.m4' or" + echo "$configure_deps." + program_details 'aclocal' + ;; + autom4te*) + echo "You might have modified some maintainer files that require" + echo "the 'autom4te' program to be rebuilt." + program_details 'autom4te' + ;; + bison*|yacc*) + echo "You should only need it if you modified a '.y' file." + echo "You may want to install the GNU Bison package:" + echo "<$gnu_software_URL/bison/>" + ;; + lex*|flex*) + echo "You should only need it if you modified a '.l' file." + echo "You may want to install the Fast Lexical Analyzer package:" + echo "<$flex_URL>" + ;; + help2man*) + echo "You should only need it if you modified a dependency" \ + "of a man page." + echo "You may want to install the GNU Help2man package:" + echo "<$gnu_software_URL/help2man/>" + ;; + makeinfo*) + echo "You should only need it if you modified a '.texi' file, or" + echo "any other file indirectly affecting the aspect of the manual." + echo "You might want to install the Texinfo package:" + echo "<$gnu_software_URL/texinfo/>" + echo "The spurious makeinfo call might also be the consequence of" + echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" + echo "want to install GNU make:" + echo "<$gnu_software_URL/make/>" + ;; + *) + echo "You might have modified some files without having the proper" + echo "tools for further handling them. Check the 'README' file, it" + echo "often tells you about the needed prerequisites for installing" + echo "this package. You may also peek at any GNU archive site, in" + echo "case some other package contains this missing '$1' program." + ;; + esac +} + +give_advice "$1" | sed -e '1s/^/WARNING: /' \ + -e '2,$s/^/ /' >&2 + +# Propagate the correct exit status (expected to be 127 for a program +# not found, 63 for a program that failed due to version mismatch). +exit $st + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/cogl/cogl-config.h.in b/cogl/cogl-config.h.in new file mode 100644 index 0000000..af75f96 --- /dev/null +++ b/cogl/cogl-config.h.in @@ -0,0 +1,149 @@ +/* cogl-config.h.in. Generated from configure.ac by autoheader. */ + +/* The major version for libgbm */ +#undef COGL_GBM_MAJOR + +/* The micro version for libgbm */ +#undef COGL_GBM_MICRO + +/* The minor version for libgbm */ +#undef COGL_GBM_MINOR + +/* Whether to enable building unit tests */ +#undef ENABLE_UNIT_TESTS + +/* Whether we have cairo or not */ +#undef HAVE_CAIRO + +/* Have GL for rendering */ +#undef HAVE_COGL_GL + +/* Have GLES 1.1 for rendering */ +#undef HAVE_COGL_GLES + +/* Have GLES 2.0 for rendering */ +#undef HAVE_COGL_GLES2 + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_EGL_EGLEXT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_EGL_EGL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the `ffs' function. */ +#undef HAVE_FFS + +/* Has the __FLOAT_WORD_ORDER macro */ +#undef HAVE_FLOAT_WORD_ORDER + +/* Define to 1 if you have the header file. */ +#undef HAVE_GLES_EGL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `GL' library (-lGL). */ +#undef HAVE_LIBGL + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define to 1 if you have the `memmem' function. */ +#undef HAVE_MEMMEM + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `sincos' function. */ +#undef HAVE_SINCOS + +/* Whether _Static_assert can be used or not */ +#undef HAVE_STATIC_ASSERT + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#undef LT_OBJDIR + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# undef _POSIX_PTHREAD_SEMANTICS +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# undef _TANDEM_SOURCE +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# undef __EXTENSIONS__ +#endif + + +/* Define to 1 if on MINIX. */ +#undef _MINIX + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +#undef _POSIX_1_SOURCE + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +#undef _POSIX_SOURCE + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +#include "config-custom.h" diff --git a/cogl/cogl-gles2/GLES2/gl2.h b/cogl/cogl-gles2/GLES2/gl2.h new file mode 100644 index 0000000..718fb3b --- /dev/null +++ b/cogl/cogl-gles2/GLES2/gl2.h @@ -0,0 +1,169 @@ +#ifndef __gl2_h_ +#define __gl2_h_ + +/* $Revision: 16803 $ on $Date:: 2012-02-02 09:49:18 -0800 #$ */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This document is licensed under the SGI Free Software B License Version + * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ . + */ + +/*------------------------------------------------------------------------- + * GL core functions. + *-----------------------------------------------------------------------*/ + +GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture); +GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader); +GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar* name); +GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer); +GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer); +GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer); +GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture); +GL_APICALL void GL_APIENTRY glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +GL_APICALL void GL_APIENTRY glBlendEquation ( GLenum mode ); +GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha); +GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor); +GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage); +GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data); +GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target); +GL_APICALL void GL_APIENTRY glClear (GLbitfield mask); +GL_APICALL void GL_APIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +GL_APICALL void GL_APIENTRY glClearDepthf (GLclampf depth); +GL_APICALL void GL_APIENTRY glClearStencil (GLint s); +GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader); +GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data); +GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data); +GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL GLuint GL_APIENTRY glCreateProgram (void); +GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type); +GL_APICALL void GL_APIENTRY glCullFace (GLenum mode); +GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers); +GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers); +GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program); +GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers); +GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader); +GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint* textures); +GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func); +GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag); +GL_APICALL void GL_APIENTRY glDepthRangef (GLclampf zNear, GLclampf zFar); +GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader); +GL_APICALL void GL_APIENTRY glDisable (GLenum cap); +GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index); +GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count); +GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices); +GL_APICALL void GL_APIENTRY glEnable (GLenum cap); +GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index); +GL_APICALL void GL_APIENTRY glFinish (void); +GL_APICALL void GL_APIENTRY glFlush (void); +GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode); +GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers); +GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target); +GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers); +GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers); +GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint* textures); +GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name); +GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name); +GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders); +GL_APICALL int GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar* name); +GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params); +GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params); +GL_APICALL GLenum GL_APIENTRY glGetError (void); +GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat* params); +GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog); +GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog); +GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision); +GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source); +GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenum name); +GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params); +GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat* params); +GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint* params); +GL_APICALL int GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar* name); +GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params); +GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer); +GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode); +GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer); +GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap); +GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer); +GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program); +GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer); +GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader); +GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture); +GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width); +GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program); +GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param); +GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units); +GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels); +GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void); +GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glSampleCoverage (GLclampf value, GLboolean invert); +GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length); +GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length); +GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask); +GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask); +GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask); +GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask); +GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass); +GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass); +GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels); +GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param); +GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params); +GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); +GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint* params); +GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels); +GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat x); +GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat* v); +GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint x); +GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint* v); +GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat x, GLfloat y); +GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat* v); +GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint x, GLint y); +GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint* v); +GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z); +GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat* v); +GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint x, GLint y, GLint z); +GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint* v); +GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat* v); +GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w); +GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint* v); +GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glUseProgram (GLuint program); +GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program); +GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint indx, GLfloat x); +GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint indx, const GLfloat* values); +GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y); +GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint indx, const GLfloat* values); +GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z); +GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint indx, const GLfloat* values); +GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values); +GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr); +GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); + +#ifdef __cplusplus +} +#endif + +#endif /* __gl2_h_ */ diff --git a/cogl/cogl-gles2/GLES2/gl2ext.h b/cogl/cogl-gles2/GLES2/gl2ext.h new file mode 100644 index 0000000..e4016a5 --- /dev/null +++ b/cogl/cogl-gles2/GLES2/gl2ext.h @@ -0,0 +1,1498 @@ +#ifndef __gl2ext_h_ +#define __gl2ext_h_ + +/* $Revision: 16994 $ on $Date:: 2012-02-29 18:29:34 -0800 #$ */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This document is licensed under the SGI Free Software B License Version + * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ . + */ + +#ifndef GL_APIENTRYP +# define GL_APIENTRYP GL_APIENTRY* +#endif + +/*------------------------------------------------------------------------* + * OES extension tokens + *------------------------------------------------------------------------*/ + +/* GL_OES_compressed_ETC1_RGB8_texture */ +#ifndef GL_OES_compressed_ETC1_RGB8_texture +#define GL_ETC1_RGB8_OES 0x8D64 +#endif + +/* GL_OES_compressed_paletted_texture */ +#ifndef GL_OES_compressed_paletted_texture +#define GL_PALETTE4_RGB8_OES 0x8B90 +#define GL_PALETTE4_RGBA8_OES 0x8B91 +#define GL_PALETTE4_R5_G6_B5_OES 0x8B92 +#define GL_PALETTE4_RGBA4_OES 0x8B93 +#define GL_PALETTE4_RGB5_A1_OES 0x8B94 +#define GL_PALETTE8_RGB8_OES 0x8B95 +#define GL_PALETTE8_RGBA8_OES 0x8B96 +#define GL_PALETTE8_R5_G6_B5_OES 0x8B97 +#define GL_PALETTE8_RGBA4_OES 0x8B98 +#define GL_PALETTE8_RGB5_A1_OES 0x8B99 +#endif + +/* GL_OES_depth24 */ +#ifndef GL_OES_depth24 +#define GL_DEPTH_COMPONENT24_OES 0x81A6 +#endif + +/* GL_OES_depth32 */ +#ifndef GL_OES_depth32 +#define GL_DEPTH_COMPONENT32_OES 0x81A7 +#endif + +/* GL_OES_depth_texture */ +/* No new tokens introduced by this extension. */ + +/* GL_OES_EGL_image */ +#ifndef GL_OES_EGL_image +typedef void* GLeglImageOES; +#endif + +/* GL_OES_EGL_image_external */ +#ifndef GL_OES_EGL_image_external +/* GLeglImageOES defined in GL_OES_EGL_image already. */ +#define GL_TEXTURE_EXTERNAL_OES 0x8D65 +#define GL_SAMPLER_EXTERNAL_OES 0x8D66 +#define GL_TEXTURE_BINDING_EXTERNAL_OES 0x8D67 +#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES 0x8D68 +#endif + +/* GL_OES_element_index_uint */ +#ifndef GL_OES_element_index_uint +#define GL_UNSIGNED_INT 0x1405 +#endif + +/* GL_OES_get_program_binary */ +#ifndef GL_OES_get_program_binary +#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741 +#define GL_NUM_PROGRAM_BINARY_FORMATS_OES 0x87FE +#define GL_PROGRAM_BINARY_FORMATS_OES 0x87FF +#endif + +/* GL_OES_mapbuffer */ +#ifndef GL_OES_mapbuffer +#define GL_WRITE_ONLY_OES 0x88B9 +#define GL_BUFFER_ACCESS_OES 0x88BB +#define GL_BUFFER_MAPPED_OES 0x88BC +#define GL_BUFFER_MAP_POINTER_OES 0x88BD +#endif + +/* GL_OES_packed_depth_stencil */ +#ifndef GL_OES_packed_depth_stencil +#define GL_DEPTH_STENCIL_OES 0x84F9 +#define GL_UNSIGNED_INT_24_8_OES 0x84FA +#define GL_DEPTH24_STENCIL8_OES 0x88F0 +#endif + +/* GL_OES_rgb8_rgba8 */ +#ifndef GL_OES_rgb8_rgba8 +#define GL_RGB8_OES 0x8051 +#define GL_RGBA8_OES 0x8058 +#endif + +/* GL_OES_standard_derivatives */ +#ifndef GL_OES_standard_derivatives +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES 0x8B8B +#endif + +/* GL_OES_stencil1 */ +#ifndef GL_OES_stencil1 +#define GL_STENCIL_INDEX1_OES 0x8D46 +#endif + +/* GL_OES_stencil4 */ +#ifndef GL_OES_stencil4 +#define GL_STENCIL_INDEX4_OES 0x8D47 +#endif + +/* GL_OES_texture_3D */ +#ifndef GL_OES_texture_3D +#define GL_TEXTURE_WRAP_R_OES 0x8072 +#define GL_TEXTURE_3D_OES 0x806F +#define GL_TEXTURE_BINDING_3D_OES 0x806A +#define GL_MAX_3D_TEXTURE_SIZE_OES 0x8073 +#define GL_SAMPLER_3D_OES 0x8B5F +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES 0x8CD4 +#endif + +/* GL_OES_texture_float */ +/* No new tokens introduced by this extension. */ + +/* GL_OES_texture_float_linear */ +/* No new tokens introduced by this extension. */ + +/* GL_OES_texture_half_float */ +#ifndef GL_OES_texture_half_float +#define GL_HALF_FLOAT_OES 0x8D61 +#endif + +/* GL_OES_texture_half_float_linear */ +/* No new tokens introduced by this extension. */ + +/* GL_OES_texture_npot */ +/* No new tokens introduced by this extension. */ + +/* GL_OES_vertex_array_object */ +#ifndef GL_OES_vertex_array_object +#define GL_VERTEX_ARRAY_BINDING_OES 0x85B5 +#endif + +/* GL_OES_vertex_half_float */ +/* GL_HALF_FLOAT_OES defined in GL_OES_texture_half_float already. */ + +/* GL_OES_vertex_type_10_10_10_2 */ +#ifndef GL_OES_vertex_type_10_10_10_2 +#define GL_UNSIGNED_INT_10_10_10_2_OES 0x8DF6 +#define GL_INT_10_10_10_2_OES 0x8DF7 +#endif + +/*------------------------------------------------------------------------* + * AMD extension tokens + *------------------------------------------------------------------------*/ + +/* GL_AMD_compressed_3DC_texture */ +#ifndef GL_AMD_compressed_3DC_texture +#define GL_3DC_X_AMD 0x87F9 +#define GL_3DC_XY_AMD 0x87FA +#endif + +/* GL_AMD_compressed_ATC_texture */ +#ifndef GL_AMD_compressed_ATC_texture +#define GL_ATC_RGB_AMD 0x8C92 +#define GL_ATC_RGBA_EXPLICIT_ALPHA_AMD 0x8C93 +#define GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE +#endif + +/* GL_AMD_performance_monitor */ +#ifndef GL_AMD_performance_monitor +#define GL_COUNTER_TYPE_AMD 0x8BC0 +#define GL_COUNTER_RANGE_AMD 0x8BC1 +#define GL_UNSIGNED_INT64_AMD 0x8BC2 +#define GL_PERCENTAGE_AMD 0x8BC3 +#define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4 +#define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5 +#define GL_PERFMON_RESULT_AMD 0x8BC6 +#endif + +/* GL_AMD_program_binary_Z400 */ +#ifndef GL_AMD_program_binary_Z400 +#define GL_Z400_BINARY_AMD 0x8740 +#endif + +/*------------------------------------------------------------------------* + * ANGLE extension tokens + *------------------------------------------------------------------------*/ + +/* GL_ANGLE_framebuffer_blit */ +#ifndef GL_ANGLE_framebuffer_blit +#define GL_READ_FRAMEBUFFER_ANGLE 0x8CA8 +#define GL_DRAW_FRAMEBUFFER_ANGLE 0x8CA9 +#define GL_DRAW_FRAMEBUFFER_BINDING_ANGLE 0x8CA6 +#define GL_READ_FRAMEBUFFER_BINDING_ANGLE 0x8CAA +#endif + +/* GL_ANGLE_framebuffer_multisample */ +#ifndef GL_ANGLE_framebuffer_multisample +#define GL_RENDERBUFFER_SAMPLES_ANGLE 0x8CAB +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE 0x8D56 +#define GL_MAX_SAMPLES_ANGLE 0x8D57 +#endif + +/* GL_ANGLE_instanced_arrays */ +#ifndef GL_ANGLE_instanced_arrays +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE 0x88FE +#endif + +/* GL_ANGLE_pack_reverse_row_order */ +#ifndef GL_ANGLE_pack_reverse_row_order +#define GL_PACK_REVERSE_ROW_ORDER_ANGLE 0x93A4 +#endif + +/* GL_ANGLE_texture_compression_dxt3 */ +#ifndef GL_ANGLE_texture_compression_dxt3 +#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE 0x83F2 +#endif + +/* GL_ANGLE_texture_compression_dxt5 */ +#ifndef GL_ANGLE_texture_compression_dxt5 +#define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE 0x83F3 +#endif + +/* GL_ANGLE_texture_usage */ +#ifndef GL_ANGLE_texture_usage +#define GL_TEXTURE_USAGE_ANGLE 0x93A2 +#define GL_FRAMEBUFFER_ATTACHMENT_ANGLE 0x93A3 +#endif + +/* GL_ANGLE_translated_shader_source */ +#ifndef GL_ANGLE_translated_shader_source +#define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE 0x93A0 +#endif + +/*------------------------------------------------------------------------* + * APPLE extension tokens + *------------------------------------------------------------------------*/ + +/* GL_APPLE_rgb_422 */ +#ifndef GL_APPLE_rgb_422 +#define GL_RGB_422_APPLE 0x8A1F +#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA +#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB +#endif + +/* GL_APPLE_framebuffer_multisample */ +#ifndef GL_APPLE_framebuffer_multisample +#define GL_RENDERBUFFER_SAMPLES_APPLE 0x8CAB +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE 0x8D56 +#define GL_MAX_SAMPLES_APPLE 0x8D57 +#define GL_READ_FRAMEBUFFER_APPLE 0x8CA8 +#define GL_DRAW_FRAMEBUFFER_APPLE 0x8CA9 +#define GL_DRAW_FRAMEBUFFER_BINDING_APPLE 0x8CA6 +#define GL_READ_FRAMEBUFFER_BINDING_APPLE 0x8CAA +#endif + +/* GL_APPLE_texture_format_BGRA8888 */ +#ifndef GL_APPLE_texture_format_BGRA8888 +#define GL_BGRA_EXT 0x80E1 +#endif + +/* GL_APPLE_texture_max_level */ +#ifndef GL_APPLE_texture_max_level +#define GL_TEXTURE_MAX_LEVEL_APPLE 0x813D +#endif + +/*------------------------------------------------------------------------* + * ARM extension tokens + *------------------------------------------------------------------------*/ + +/* GL_ARM_mali_shader_binary */ +#ifndef GL_ARM_mali_shader_binary +#define GL_MALI_SHADER_BINARY_ARM 0x8F60 +#endif + +/* GL_ARM_rgba8 */ +/* No new tokens introduced by this extension. */ + +/*------------------------------------------------------------------------* + * EXT extension tokens + *------------------------------------------------------------------------*/ + +/* GL_EXT_blend_minmax */ +#ifndef GL_EXT_blend_minmax +#define GL_MIN_EXT 0x8007 +#define GL_MAX_EXT 0x8008 +#endif + +/* GL_EXT_color_buffer_half_float */ +#ifndef GL_EXT_color_buffer_half_float +#define GL_RGBA16F_EXT 0x881A +#define GL_RGB16F_EXT 0x881B +#define GL_RG16F_EXT 0x822F +#define GL_R16F_EXT 0x822D +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT 0x8211 +#define GL_UNSIGNED_NORMALIZED_EXT 0x8C17 +#endif + +/* GL_EXT_debug_label */ +#ifndef GL_EXT_debug_label +#define GL_PROGRAM_PIPELINE_OBJECT_EXT 0x8A4F +#define GL_PROGRAM_OBJECT_EXT 0x8B40 +#define GL_SHADER_OBJECT_EXT 0x8B48 +#define GL_BUFFER_OBJECT_EXT 0x9151 +#define GL_QUERY_OBJECT_EXT 0x9153 +#define GL_VERTEX_ARRAY_OBJECT_EXT 0x9154 +#endif + +/* GL_EXT_debug_marker */ +/* No new tokens introduced by this extension. */ + +/* GL_EXT_discard_framebuffer */ +#ifndef GL_EXT_discard_framebuffer +#define GL_COLOR_EXT 0x1800 +#define GL_DEPTH_EXT 0x1801 +#define GL_STENCIL_EXT 0x1802 +#endif + +/* GL_EXT_multisampled_render_to_texture */ +#ifndef GL_EXT_multisampled_render_to_texture +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT 0x8D6C +#define GL_RENDERBUFFER_SAMPLES_EXT 0x9133 +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x9134 +#define GL_MAX_SAMPLES_EXT 0x9135 +#endif + +/* GL_EXT_multi_draw_arrays */ +/* No new tokens introduced by this extension. */ + +/* GL_EXT_occlusion_query_boolean */ +#ifndef GL_EXT_occlusion_query_boolean +#define GL_ANY_SAMPLES_PASSED_EXT 0x8C2F +#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT 0x8D6A +#define GL_CURRENT_QUERY_EXT 0x8865 +#define GL_QUERY_RESULT_EXT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE_EXT 0x8867 +#endif + +/* GL_EXT_read_format_bgra */ +#ifndef GL_EXT_read_format_bgra +#define GL_BGRA_EXT 0x80E1 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT 0x8365 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT 0x8366 +#endif + +/* GL_EXT_robustness */ +#ifndef GL_EXT_robustness +/* reuse GL_NO_ERROR */ +#define GL_GUILTY_CONTEXT_RESET_EXT 0x8253 +#define GL_INNOCENT_CONTEXT_RESET_EXT 0x8254 +#define GL_UNKNOWN_CONTEXT_RESET_EXT 0x8255 +#define GL_CONTEXT_ROBUST_ACCESS_EXT 0x90F3 +#define GL_RESET_NOTIFICATION_STRATEGY_EXT 0x8256 +#define GL_LOSE_CONTEXT_ON_RESET_EXT 0x8252 +#define GL_NO_RESET_NOTIFICATION_EXT 0x8261 +#endif + +/* GL_EXT_separate_shader_objects */ +#ifndef GL_EXT_separate_shader_objects +#define GL_VERTEX_SHADER_BIT_EXT 0x00000001 +#define GL_FRAGMENT_SHADER_BIT_EXT 0x00000002 +#define GL_ALL_SHADER_BITS_EXT 0xFFFFFFFF +#define GL_PROGRAM_SEPARABLE_EXT 0x8258 +#define GL_ACTIVE_PROGRAM_EXT 0x8259 +#define GL_PROGRAM_PIPELINE_BINDING_EXT 0x825A +#endif + +/* GL_EXT_shader_texture_lod */ +/* No new tokens introduced by this extension. */ + +/* GL_EXT_shadow_samplers */ +#ifndef GL_EXT_shadow_samplers +#define GL_TEXTURE_COMPARE_MODE_EXT 0x884C +#define GL_TEXTURE_COMPARE_FUNC_EXT 0x884D +#define GL_COMPARE_REF_TO_TEXTURE_EXT 0x884E +#define GL_SAMPLER_2D_SHADOW_EXT 0x8B62 +#endif + +/* GL_EXT_sRGB */ +#ifndef GL_EXT_sRGB +#define GL_SRGB_EXT 0x8C40 +#define GL_SRGB_ALPHA_EXT 0x8C42 +#define GL_SRGB8_ALPHA8_EXT 0x8C43 +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT 0x8210 +#endif + +/* GL_EXT_texture_compression_dxt1 */ +#ifndef GL_EXT_texture_compression_dxt1 +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#endif + +/* GL_EXT_texture_filter_anisotropic */ +#ifndef GL_EXT_texture_filter_anisotropic +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF +#endif + +/* GL_EXT_texture_format_BGRA8888 */ +#ifndef GL_EXT_texture_format_BGRA8888 +#define GL_BGRA_EXT 0x80E1 +#endif + +/* GL_EXT_texture_rg */ +#ifndef GL_EXT_texture_rg +#define GL_RED_EXT 0x1903 +#define GL_RG_EXT 0x8227 +#define GL_R8_EXT 0x8229 +#define GL_RG8_EXT 0x822B +#endif + +/* GL_EXT_texture_storage */ +#ifndef GL_EXT_texture_storage +#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT 0x912F +#define GL_ALPHA8_EXT 0x803C +#define GL_LUMINANCE8_EXT 0x8040 +#define GL_LUMINANCE8_ALPHA8_EXT 0x8045 +#define GL_RGBA32F_EXT 0x8814 +#define GL_RGB32F_EXT 0x8815 +#define GL_ALPHA32F_EXT 0x8816 +#define GL_LUMINANCE32F_EXT 0x8818 +#define GL_LUMINANCE_ALPHA32F_EXT 0x8819 +/* reuse GL_RGBA16F_EXT */ +/* reuse GL_RGB16F_EXT */ +#define GL_ALPHA16F_EXT 0x881C +#define GL_LUMINANCE16F_EXT 0x881E +#define GL_LUMINANCE_ALPHA16F_EXT 0x881F +#define GL_RGB10_A2_EXT 0x8059 +#define GL_RGB10_EXT 0x8052 +#define GL_BGRA8_EXT 0x93A1 +#define GL_R8_EXT 0x8229 +#define GL_RG8_EXT 0x822B +#define GL_R32F_EXT 0x822E +#define GL_RG32F_EXT 0x8230 +#define GL_R16F_EXT 0x822D +#define GL_RG16F_EXT 0x822F +#endif + +/* GL_EXT_texture_type_2_10_10_10_REV */ +#ifndef GL_EXT_texture_type_2_10_10_10_REV +#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT 0x8368 +#endif + +/* GL_EXT_unpack_subimage */ +#ifndef GL_EXT_unpack_subimage +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#endif + +/*------------------------------------------------------------------------* + * DMP extension tokens + *------------------------------------------------------------------------*/ + +/* GL_DMP_shader_binary */ +#ifndef GL_DMP_shader_binary +#define GL_SHADER_BINARY_DMP 0x9250 +#endif + +/*------------------------------------------------------------------------* + * IMG extension tokens + *------------------------------------------------------------------------*/ + +/* GL_IMG_program_binary */ +#ifndef GL_IMG_program_binary +#define GL_SGX_PROGRAM_BINARY_IMG 0x9130 +#endif + +/* GL_IMG_read_format */ +#ifndef GL_IMG_read_format +#define GL_BGRA_IMG 0x80E1 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV_IMG 0x8365 +#endif + +/* GL_IMG_shader_binary */ +#ifndef GL_IMG_shader_binary +#define GL_SGX_BINARY_IMG 0x8C0A +#endif + +/* GL_IMG_texture_compression_pvrtc */ +#ifndef GL_IMG_texture_compression_pvrtc +#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00 +#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01 +#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02 +#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03 +#endif + +/* GL_IMG_multisampled_render_to_texture */ +#ifndef GL_IMG_multisampled_render_to_texture +#define GL_RENDERBUFFER_SAMPLES_IMG 0x9133 +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG 0x9134 +#define GL_MAX_SAMPLES_IMG 0x9135 +#define GL_TEXTURE_SAMPLES_IMG 0x9136 +#endif + +/*------------------------------------------------------------------------* + * NV extension tokens + *------------------------------------------------------------------------*/ + +/* GL_NV_coverage_sample */ +#ifndef GL_NV_coverage_sample +#define GL_COVERAGE_COMPONENT_NV 0x8ED0 +#define GL_COVERAGE_COMPONENT4_NV 0x8ED1 +#define GL_COVERAGE_ATTACHMENT_NV 0x8ED2 +#define GL_COVERAGE_BUFFERS_NV 0x8ED3 +#define GL_COVERAGE_SAMPLES_NV 0x8ED4 +#define GL_COVERAGE_ALL_FRAGMENTS_NV 0x8ED5 +#define GL_COVERAGE_EDGE_FRAGMENTS_NV 0x8ED6 +#define GL_COVERAGE_AUTOMATIC_NV 0x8ED7 +#define GL_COVERAGE_BUFFER_BIT_NV 0x8000 +#endif + +/* GL_NV_depth_nonlinear */ +#ifndef GL_NV_depth_nonlinear +#define GL_DEPTH_COMPONENT16_NONLINEAR_NV 0x8E2C +#endif + +/* GL_NV_draw_buffers */ +#ifndef GL_NV_draw_buffers +#define GL_MAX_DRAW_BUFFERS_NV 0x8824 +#define GL_DRAW_BUFFER0_NV 0x8825 +#define GL_DRAW_BUFFER1_NV 0x8826 +#define GL_DRAW_BUFFER2_NV 0x8827 +#define GL_DRAW_BUFFER3_NV 0x8828 +#define GL_DRAW_BUFFER4_NV 0x8829 +#define GL_DRAW_BUFFER5_NV 0x882A +#define GL_DRAW_BUFFER6_NV 0x882B +#define GL_DRAW_BUFFER7_NV 0x882C +#define GL_DRAW_BUFFER8_NV 0x882D +#define GL_DRAW_BUFFER9_NV 0x882E +#define GL_DRAW_BUFFER10_NV 0x882F +#define GL_DRAW_BUFFER11_NV 0x8830 +#define GL_DRAW_BUFFER12_NV 0x8831 +#define GL_DRAW_BUFFER13_NV 0x8832 +#define GL_DRAW_BUFFER14_NV 0x8833 +#define GL_DRAW_BUFFER15_NV 0x8834 +#define GL_COLOR_ATTACHMENT0_NV 0x8CE0 +#define GL_COLOR_ATTACHMENT1_NV 0x8CE1 +#define GL_COLOR_ATTACHMENT2_NV 0x8CE2 +#define GL_COLOR_ATTACHMENT3_NV 0x8CE3 +#define GL_COLOR_ATTACHMENT4_NV 0x8CE4 +#define GL_COLOR_ATTACHMENT5_NV 0x8CE5 +#define GL_COLOR_ATTACHMENT6_NV 0x8CE6 +#define GL_COLOR_ATTACHMENT7_NV 0x8CE7 +#define GL_COLOR_ATTACHMENT8_NV 0x8CE8 +#define GL_COLOR_ATTACHMENT9_NV 0x8CE9 +#define GL_COLOR_ATTACHMENT10_NV 0x8CEA +#define GL_COLOR_ATTACHMENT11_NV 0x8CEB +#define GL_COLOR_ATTACHMENT12_NV 0x8CEC +#define GL_COLOR_ATTACHMENT13_NV 0x8CED +#define GL_COLOR_ATTACHMENT14_NV 0x8CEE +#define GL_COLOR_ATTACHMENT15_NV 0x8CEF +#endif + +/* GL_NV_fbo_color_attachments */ +#ifndef GL_NV_fbo_color_attachments +#define GL_MAX_COLOR_ATTACHMENTS_NV 0x8CDF +/* GL_COLOR_ATTACHMENT{0-15}_NV defined in GL_NV_draw_buffers already. */ +#endif + +/* GL_NV_fence */ +#ifndef GL_NV_fence +#define GL_ALL_COMPLETED_NV 0x84F2 +#define GL_FENCE_STATUS_NV 0x84F3 +#define GL_FENCE_CONDITION_NV 0x84F4 +#endif + +/* GL_NV_read_buffer */ +#ifndef GL_NV_read_buffer +#define GL_READ_BUFFER_NV 0x0C02 +#endif + +/* GL_NV_read_buffer_front */ +/* No new tokens introduced by this extension. */ + +/* GL_NV_read_depth */ +/* No new tokens introduced by this extension. */ + +/* GL_NV_read_depth_stencil */ +/* No new tokens introduced by this extension. */ + +/* GL_NV_read_stencil */ +/* No new tokens introduced by this extension. */ + +/* GL_NV_texture_compression_s3tc_update */ +/* No new tokens introduced by this extension. */ + +/* GL_NV_texture_npot_2D_mipmap */ +/* No new tokens introduced by this extension. */ + +/*------------------------------------------------------------------------* + * QCOM extension tokens + *------------------------------------------------------------------------*/ + +/* GL_QCOM_alpha_test */ +#ifndef GL_QCOM_alpha_test +#define GL_ALPHA_TEST_QCOM 0x0BC0 +#define GL_ALPHA_TEST_FUNC_QCOM 0x0BC1 +#define GL_ALPHA_TEST_REF_QCOM 0x0BC2 +#endif + +/* GL_QCOM_driver_control */ +/* No new tokens introduced by this extension. */ + +/* GL_QCOM_extended_get */ +#ifndef GL_QCOM_extended_get +#define GL_TEXTURE_WIDTH_QCOM 0x8BD2 +#define GL_TEXTURE_HEIGHT_QCOM 0x8BD3 +#define GL_TEXTURE_DEPTH_QCOM 0x8BD4 +#define GL_TEXTURE_INTERNAL_FORMAT_QCOM 0x8BD5 +#define GL_TEXTURE_FORMAT_QCOM 0x8BD6 +#define GL_TEXTURE_TYPE_QCOM 0x8BD7 +#define GL_TEXTURE_IMAGE_VALID_QCOM 0x8BD8 +#define GL_TEXTURE_NUM_LEVELS_QCOM 0x8BD9 +#define GL_TEXTURE_TARGET_QCOM 0x8BDA +#define GL_TEXTURE_OBJECT_VALID_QCOM 0x8BDB +#define GL_STATE_RESTORE 0x8BDC +#endif + +/* GL_QCOM_extended_get2 */ +/* No new tokens introduced by this extension. */ + +/* GL_QCOM_perfmon_global_mode */ +#ifndef GL_QCOM_perfmon_global_mode +#define GL_PERFMON_GLOBAL_MODE_QCOM 0x8FA0 +#endif + +/* GL_QCOM_writeonly_rendering */ +#ifndef GL_QCOM_writeonly_rendering +#define GL_WRITEONLY_RENDERING_QCOM 0x8823 +#endif + +/* GL_QCOM_tiled_rendering */ +#ifndef GL_QCOM_tiled_rendering +#define GL_COLOR_BUFFER_BIT0_QCOM 0x00000001 +#define GL_COLOR_BUFFER_BIT1_QCOM 0x00000002 +#define GL_COLOR_BUFFER_BIT2_QCOM 0x00000004 +#define GL_COLOR_BUFFER_BIT3_QCOM 0x00000008 +#define GL_COLOR_BUFFER_BIT4_QCOM 0x00000010 +#define GL_COLOR_BUFFER_BIT5_QCOM 0x00000020 +#define GL_COLOR_BUFFER_BIT6_QCOM 0x00000040 +#define GL_COLOR_BUFFER_BIT7_QCOM 0x00000080 +#define GL_DEPTH_BUFFER_BIT0_QCOM 0x00000100 +#define GL_DEPTH_BUFFER_BIT1_QCOM 0x00000200 +#define GL_DEPTH_BUFFER_BIT2_QCOM 0x00000400 +#define GL_DEPTH_BUFFER_BIT3_QCOM 0x00000800 +#define GL_DEPTH_BUFFER_BIT4_QCOM 0x00001000 +#define GL_DEPTH_BUFFER_BIT5_QCOM 0x00002000 +#define GL_DEPTH_BUFFER_BIT6_QCOM 0x00004000 +#define GL_DEPTH_BUFFER_BIT7_QCOM 0x00008000 +#define GL_STENCIL_BUFFER_BIT0_QCOM 0x00010000 +#define GL_STENCIL_BUFFER_BIT1_QCOM 0x00020000 +#define GL_STENCIL_BUFFER_BIT2_QCOM 0x00040000 +#define GL_STENCIL_BUFFER_BIT3_QCOM 0x00080000 +#define GL_STENCIL_BUFFER_BIT4_QCOM 0x00100000 +#define GL_STENCIL_BUFFER_BIT5_QCOM 0x00200000 +#define GL_STENCIL_BUFFER_BIT6_QCOM 0x00400000 +#define GL_STENCIL_BUFFER_BIT7_QCOM 0x00800000 +#define GL_MULTISAMPLE_BUFFER_BIT0_QCOM 0x01000000 +#define GL_MULTISAMPLE_BUFFER_BIT1_QCOM 0x02000000 +#define GL_MULTISAMPLE_BUFFER_BIT2_QCOM 0x04000000 +#define GL_MULTISAMPLE_BUFFER_BIT3_QCOM 0x08000000 +#define GL_MULTISAMPLE_BUFFER_BIT4_QCOM 0x10000000 +#define GL_MULTISAMPLE_BUFFER_BIT5_QCOM 0x20000000 +#define GL_MULTISAMPLE_BUFFER_BIT6_QCOM 0x40000000 +#define GL_MULTISAMPLE_BUFFER_BIT7_QCOM 0x80000000 +#endif + +/*------------------------------------------------------------------------* + * VIV extension tokens + *------------------------------------------------------------------------*/ + +/* GL_VIV_shader_binary */ +#ifndef GL_VIV_shader_binary +#define GL_SHADER_BINARY_VIV 0x8FC4 +#endif + +/*------------------------------------------------------------------------* + * End of extension tokens, start of corresponding extension functions + *------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------* + * OES extension functions + *------------------------------------------------------------------------*/ + +/* GL_OES_compressed_ETC1_RGB8_texture */ +#ifndef GL_OES_compressed_ETC1_RGB8_texture +#define GL_OES_compressed_ETC1_RGB8_texture 1 +#endif + +/* GL_OES_compressed_paletted_texture */ +#ifndef GL_OES_compressed_paletted_texture +#define GL_OES_compressed_paletted_texture 1 +#endif + +/* GL_OES_depth24 */ +#ifndef GL_OES_depth24 +#define GL_OES_depth24 1 +#endif + +/* GL_OES_depth32 */ +#ifndef GL_OES_depth32 +#define GL_OES_depth32 1 +#endif + +/* GL_OES_depth_texture */ +#ifndef GL_OES_depth_texture +#define GL_OES_depth_texture 1 +#endif + +/* GL_OES_EGL_image */ +#ifndef GL_OES_EGL_image +#define GL_OES_EGL_image 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image); +GL_APICALL void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image); +#endif +typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image); +typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image); +#endif + +/* GL_OES_EGL_image_external */ +#ifndef GL_OES_EGL_image_external +#define GL_OES_EGL_image_external 1 +/* glEGLImageTargetTexture2DOES defined in GL_OES_EGL_image already. */ +#endif + +/* GL_OES_element_index_uint */ +#ifndef GL_OES_element_index_uint +#define GL_OES_element_index_uint 1 +#endif + +/* GL_OES_fbo_render_mipmap */ +#ifndef GL_OES_fbo_render_mipmap +#define GL_OES_fbo_render_mipmap 1 +#endif + +/* GL_OES_fragment_precision_high */ +#ifndef GL_OES_fragment_precision_high +#define GL_OES_fragment_precision_high 1 +#endif + +/* GL_OES_get_program_binary */ +#ifndef GL_OES_get_program_binary +#define GL_OES_get_program_binary 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glGetProgramBinaryOES (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary); +GL_APICALL void GL_APIENTRY glProgramBinaryOES (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length); +#endif +typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary); +typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length); +#endif + +/* GL_OES_mapbuffer */ +#ifndef GL_OES_mapbuffer +#define GL_OES_mapbuffer 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void* GL_APIENTRY glMapBufferOES (GLenum target, GLenum access); +GL_APICALL GLboolean GL_APIENTRY glUnmapBufferOES (GLenum target); +GL_APICALL void GL_APIENTRY glGetBufferPointervOES (GLenum target, GLenum pname, GLvoid** params); +#endif +typedef void* (GL_APIENTRYP PFNGLMAPBUFFEROESPROC) (GLenum target, GLenum access); +typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFEROESPROC) (GLenum target); +typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, GLvoid** params); +#endif + +/* GL_OES_packed_depth_stencil */ +#ifndef GL_OES_packed_depth_stencil +#define GL_OES_packed_depth_stencil 1 +#endif + +/* GL_OES_rgb8_rgba8 */ +#ifndef GL_OES_rgb8_rgba8 +#define GL_OES_rgb8_rgba8 1 +#endif + +/* GL_OES_standard_derivatives */ +#ifndef GL_OES_standard_derivatives +#define GL_OES_standard_derivatives 1 +#endif + +/* GL_OES_stencil1 */ +#ifndef GL_OES_stencil1 +#define GL_OES_stencil1 1 +#endif + +/* GL_OES_stencil4 */ +#ifndef GL_OES_stencil4 +#define GL_OES_stencil4 1 +#endif + +/* GL_OES_texture_3D */ +#ifndef GL_OES_texture_3D +#define GL_OES_texture_3D 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels); +GL_APICALL void GL_APIENTRY glTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels); +GL_APICALL void GL_APIENTRY glCopyTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glCompressedTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data); +GL_APICALL void GL_APIENTRY glCompressedTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data); +GL_APICALL void GL_APIENTRY glFramebufferTexture3DOES (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +#endif +typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels); +typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels); +typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data); +typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data); +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DOES) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +#endif + +/* GL_OES_texture_float */ +#ifndef GL_OES_texture_float +#define GL_OES_texture_float 1 +#endif + +/* GL_OES_texture_float_linear */ +#ifndef GL_OES_texture_float_linear +#define GL_OES_texture_float_linear 1 +#endif + +/* GL_OES_texture_half_float */ +#ifndef GL_OES_texture_half_float +#define GL_OES_texture_half_float 1 +#endif + +/* GL_OES_texture_half_float_linear */ +#ifndef GL_OES_texture_half_float_linear +#define GL_OES_texture_half_float_linear 1 +#endif + +/* GL_OES_texture_npot */ +#ifndef GL_OES_texture_npot +#define GL_OES_texture_npot 1 +#endif + +/* GL_OES_vertex_array_object */ +#ifndef GL_OES_vertex_array_object +#define GL_OES_vertex_array_object 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glBindVertexArrayOES (GLuint array); +GL_APICALL void GL_APIENTRY glDeleteVertexArraysOES (GLsizei n, const GLuint *arrays); +GL_APICALL void GL_APIENTRY glGenVertexArraysOES (GLsizei n, GLuint *arrays); +GL_APICALL GLboolean GL_APIENTRY glIsVertexArrayOES (GLuint array); +#endif +typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYOESPROC) (GLuint array); +typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSOESPROC) (GLsizei n, const GLuint *arrays); +typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint *arrays); +typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYOESPROC) (GLuint array); +#endif + +/* GL_OES_vertex_half_float */ +#ifndef GL_OES_vertex_half_float +#define GL_OES_vertex_half_float 1 +#endif + +/* GL_OES_vertex_type_10_10_10_2 */ +#ifndef GL_OES_vertex_type_10_10_10_2 +#define GL_OES_vertex_type_10_10_10_2 1 +#endif + +/*------------------------------------------------------------------------* + * AMD extension functions + *------------------------------------------------------------------------*/ + +/* GL_AMD_compressed_3DC_texture */ +#ifndef GL_AMD_compressed_3DC_texture +#define GL_AMD_compressed_3DC_texture 1 +#endif + +/* GL_AMD_compressed_ATC_texture */ +#ifndef GL_AMD_compressed_ATC_texture +#define GL_AMD_compressed_ATC_texture 1 +#endif + +/* AMD_performance_monitor */ +#ifndef GL_AMD_performance_monitor +#define GL_AMD_performance_monitor 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupsAMD (GLint *numGroups, GLsizei groupsSize, GLuint *groups); +GL_APICALL void GL_APIENTRY glGetPerfMonitorCountersAMD (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters); +GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupStringAMD (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString); +GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterStringAMD (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString); +GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, GLvoid *data); +GL_APICALL void GL_APIENTRY glGenPerfMonitorsAMD (GLsizei n, GLuint *monitors); +GL_APICALL void GL_APIENTRY glDeletePerfMonitorsAMD (GLsizei n, GLuint *monitors); +GL_APICALL void GL_APIENTRY glSelectPerfMonitorCountersAMD (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList); +GL_APICALL void GL_APIENTRY glBeginPerfMonitorAMD (GLuint monitor); +GL_APICALL void GL_APIENTRY glEndPerfMonitorAMD (GLuint monitor); +GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten); +#endif +typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups); +typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters); +typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString); +typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString); +typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, GLvoid *data); +typedef void (GL_APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors); +typedef void (GL_APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors); +typedef void (GL_APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList); +typedef void (GL_APIENTRYP PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor); +typedef void (GL_APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor); +typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten); +#endif + +/* GL_AMD_program_binary_Z400 */ +#ifndef GL_AMD_program_binary_Z400 +#define GL_AMD_program_binary_Z400 1 +#endif + +/*------------------------------------------------------------------------* + * ANGLE extension functions + *------------------------------------------------------------------------*/ + +/* GL_ANGLE_framebuffer_blit */ +#ifndef GL_ANGLE_framebuffer_blit +#define GL_ANGLE_framebuffer_blit 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glBlitFramebufferANGLE (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +#endif +typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERANGLEPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +#endif + +/* GL_ANGLE_framebuffer_multisample */ +#ifndef GL_ANGLE_framebuffer_multisample +#define GL_ANGLE_framebuffer_multisample 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleANGLE (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +#endif +typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +#endif + +#ifndef GL_ANGLE_instanced_arrays +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDrawArraysInstancedANGLE (GLenum mode, GLint first, GLsizei count, GLsizei primcount); +GL_APICALL void GL_APIENTRY glDrawElementsInstancedANGLE (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); +GL_APICALL void GL_APIENTRY glVertexAttribDivisorANGLE (GLuint index, GLuint divisor); +#endif +typedef void (GL_APIENTRYP PFLGLDRAWARRAYSINSTANCEDANGLEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); +typedef void (GL_APIENTRYP PFLGLDRAWELEMENTSINSTANCEDANGLEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); +typedef void (GL_APIENTRYP PFLGLVERTEXATTRIBDIVISORANGLEPROC) (GLuint index, GLuint divisor); +#endif + +/* GL_ANGLE_pack_reverse_row_order */ +#ifndef GL_ANGLE_pack_reverse_row_order +#define GL_ANGLE_pack_reverse_row_order 1 +#endif + +/* GL_ANGLE_texture_compression_dxt3 */ +#ifndef GL_ANGLE_texture_compression_dxt3 +#define GL_ANGLE_texture_compression_dxt3 1 +#endif + +/* GL_ANGLE_texture_compression_dxt5 */ +#ifndef GL_ANGLE_texture_compression_dxt5 +#define GL_ANGLE_texture_compression_dxt5 1 +#endif + +/* GL_ANGLE_texture_usage */ +#ifndef GL_ANGLE_texture_usage +#define GL_ANGLE_texture_usage 1 +#endif + +#ifndef GL_ANGLE_translated_shader_source +#define GL_ANGLE_translated_shader_source 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glGetTranslatedShaderSourceANGLE (GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source); +#endif +typedef void (GL_APIENTRYP PFLGLGETTRANSLATEDSHADERSOURCEANGLEPROC) (GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source); +#endif + +/*------------------------------------------------------------------------* + * APPLE extension functions + *------------------------------------------------------------------------*/ + +/* GL_APPLE_rgb_422 */ +#ifndef GL_APPLE_rgb_422 +#define GL_APPLE_rgb_422 1 +#endif + +/* GL_APPLE_framebuffer_multisample */ +#ifndef GL_APPLE_framebuffer_multisample +#define GL_APPLE_framebuffer_multisample 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleAPPLE (GLenum, GLsizei, GLenum, GLsizei, GLsizei); +GL_APICALL void GL_APIENTRY glResolveMultisampleFramebufferAPPLE (void); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEAPPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLRESOLVEMULTISAMPLEFRAMEBUFFERAPPLEPROC) (void); +#endif + +/* GL_APPLE_texture_format_BGRA8888 */ +#ifndef GL_APPLE_texture_format_BGRA8888 +#define GL_APPLE_texture_format_BGRA8888 1 +#endif + +/* GL_APPLE_texture_max_level */ +#ifndef GL_APPLE_texture_max_level +#define GL_APPLE_texture_max_level 1 +#endif + +/*------------------------------------------------------------------------* + * ARM extension functions + *------------------------------------------------------------------------*/ + +/* GL_ARM_mali_shader_binary */ +#ifndef GL_ARM_mali_shader_binary +#define GL_ARM_mali_shader_binary 1 +#endif + +/* GL_ARM_rgba8 */ +#ifndef GL_ARM_rgba8 +#define GL_ARM_rgba8 1 +#endif + +/*------------------------------------------------------------------------* + * EXT extension functions + *------------------------------------------------------------------------*/ + +/* GL_EXT_blend_minmax */ +#ifndef GL_EXT_blend_minmax +#define GL_EXT_blend_minmax 1 +#endif + +/* GL_EXT_color_buffer_half_float */ +#ifndef GL_EXT_color_buffer_half_float +#define GL_EXT_color_buffer_half_float 1 +#endif + +/* GL_EXT_debug_label */ +#ifndef GL_EXT_debug_label +#define GL_EXT_debug_label 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glLabelObjectEXT (GLenum type, GLuint object, GLsizei length, const GLchar *label); +GL_APICALL void GL_APIENTRY glGetObjectLabelEXT (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label); +#endif +typedef void (GL_APIENTRYP PFNGLLABELOBJECTEXTPROC) (GLenum type, GLuint object, GLsizei length, const GLchar *label); +typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label); +#endif + +/* GL_EXT_debug_marker */ +#ifndef GL_EXT_debug_marker +#define GL_EXT_debug_marker 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glInsertEventMarkerEXT (GLsizei length, const GLchar *marker); +GL_APICALL void GL_APIENTRY glPushGroupMarkerEXT (GLsizei length, const GLchar *marker); +GL_APICALL void GL_APIENTRY glPopGroupMarkerEXT (void); +#endif +typedef void (GL_APIENTRYP PFNGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const GLchar *marker); +typedef void (GL_APIENTRYP PFNGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const GLchar *marker); +typedef void (GL_APIENTRYP PFNGLPOPGROUPMARKEREXTPROC) (void); +#endif + +/* GL_EXT_discard_framebuffer */ +#ifndef GL_EXT_discard_framebuffer +#define GL_EXT_discard_framebuffer 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDiscardFramebufferEXT (GLenum target, GLsizei numAttachments, const GLenum *attachments); +#endif +typedef void (GL_APIENTRYP PFNGLDISCARDFRAMEBUFFEREXTPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments); +#endif + +/* GL_EXT_multisampled_render_to_texture */ +#ifndef GL_EXT_multisampled_render_to_texture +#define GL_EXT_multisampled_render_to_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleEXT (GLenum, GLsizei, GLenum, GLsizei, GLsizei); +GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleEXT (GLenum, GLenum, GLenum, GLuint, GLint, GLsizei); +#endif +typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples); +#endif + +#ifndef GL_EXT_multi_draw_arrays +#define GL_EXT_multi_draw_arrays 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glMultiDrawArraysEXT (GLenum, GLint *, GLsizei *, GLsizei); +GL_APICALL void GL_APIENTRY glMultiDrawElementsEXT (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); +typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount); +#endif + +/* GL_EXT_occlusion_query_boolean */ +#ifndef GL_EXT_occlusion_query_boolean +#define GL_EXT_occlusion_query_boolean 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glGenQueriesEXT (GLsizei n, GLuint *ids); +GL_APICALL void GL_APIENTRY glDeleteQueriesEXT (GLsizei n, const GLuint *ids); +GL_APICALL GLboolean GL_APIENTRY glIsQueryEXT (GLuint id); +GL_APICALL void GL_APIENTRY glBeginQueryEXT (GLenum target, GLuint id); +GL_APICALL void GL_APIENTRY glEndQueryEXT (GLenum target); +GL_APICALL void GL_APIENTRY glGetQueryivEXT (GLenum target, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetQueryObjectuivEXT (GLuint id, GLenum pname, GLuint *params); +#endif +typedef void (GL_APIENTRYP PFNGLGENQUERIESEXTPROC) (GLsizei n, GLuint *ids); +typedef void (GL_APIENTRYP PFNGLDELETEQUERIESEXTPROC) (GLsizei n, const GLuint *ids); +typedef GLboolean (GL_APIENTRYP PFNGLISQUERYEXTPROC) (GLuint id); +typedef void (GL_APIENTRYP PFNGLBEGINQUERYEXTPROC) (GLenum target, GLuint id); +typedef void (GL_APIENTRYP PFNGLENDQUERYEXTPROC) (GLenum target); +typedef void (GL_APIENTRYP PFNGLGETQUERYIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVEXTPROC) (GLuint id, GLenum pname, GLuint *params); +#endif + +/* GL_EXT_read_format_bgra */ +#ifndef GL_EXT_read_format_bgra +#define GL_EXT_read_format_bgra 1 +#endif + +/* GL_EXT_robustness */ +#ifndef GL_EXT_robustness +#define GL_EXT_robustness 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusEXT (void); +GL_APICALL void GL_APIENTRY glReadnPixelsEXT (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); +GL_APICALL void GL_APIENTRY glGetnUniformfvEXT (GLuint program, GLint location, GLsizei bufSize, float *params); +GL_APICALL void GL_APIENTRY glGetnUniformivEXT (GLuint program, GLint location, GLsizei bufSize, GLint *params); +#endif +typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSEXTPROC) (void); +typedef void (GL_APIENTRYP PFNGLREADNPIXELSEXTPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); +typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, float *params); +typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params); +#endif + +/* GL_EXT_separate_shader_objects */ +#ifndef GL_EXT_separate_shader_objects +#define GL_EXT_separate_shader_objects 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glUseProgramStagesEXT (GLuint pipeline, GLbitfield stages, GLuint program); +GL_APICALL void GL_APIENTRY glActiveShaderProgramEXT (GLuint pipeline, GLuint program); +GL_APICALL GLuint GL_APIENTRY glCreateShaderProgramvEXT (GLenum type, GLsizei count, const GLchar **strings); +GL_APICALL void GL_APIENTRY glBindProgramPipelineEXT (GLuint pipeline); +GL_APICALL void GL_APIENTRY glDeleteProgramPipelinesEXT (GLsizei n, const GLuint *pipelines); +GL_APICALL void GL_APIENTRY glGenProgramPipelinesEXT (GLsizei n, GLuint *pipelines); +GL_APICALL GLboolean GL_APIENTRY glIsProgramPipelineEXT (GLuint pipeline); +GL_APICALL void GL_APIENTRY glProgramParameteriEXT (GLuint program, GLenum pname, GLint value); +GL_APICALL void GL_APIENTRY glGetProgramPipelineivEXT (GLuint pipeline, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glProgramUniform1iEXT (GLuint program, GLint location, GLint x); +GL_APICALL void GL_APIENTRY glProgramUniform2iEXT (GLuint program, GLint location, GLint x, GLint y); +GL_APICALL void GL_APIENTRY glProgramUniform3iEXT (GLuint program, GLint location, GLint x, GLint y, GLint z); +GL_APICALL void GL_APIENTRY glProgramUniform4iEXT (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w); +GL_APICALL void GL_APIENTRY glProgramUniform1fEXT (GLuint program, GLint location, GLfloat x); +GL_APICALL void GL_APIENTRY glProgramUniform2fEXT (GLuint program, GLint location, GLfloat x, GLfloat y); +GL_APICALL void GL_APIENTRY glProgramUniform3fEXT (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z); +GL_APICALL void GL_APIENTRY glProgramUniform4fEXT (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GL_APICALL void GL_APIENTRY glProgramUniform1ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glProgramUniform2ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glProgramUniform3ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glProgramUniform4ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glProgramUniform1fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniform2fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniform3fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniform4fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glValidateProgramPipelineEXT (GLuint pipeline); +GL_APICALL void GL_APIENTRY glGetProgramPipelineInfoLogEXT (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +#endif +typedef void (GL_APIENTRYP PFNGLUSEPROGRAMSTAGESEXTPROC) (GLuint pipeline, GLbitfield stages, GLuint program); +typedef void (GL_APIENTRYP PFNGLACTIVESHADERPROGRAMEXTPROC) (GLuint pipeline, GLuint program); +typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROGRAMVEXTPROC) (GLenum type, GLsizei count, const GLchar **strings); +typedef void (GL_APIENTRYP PFNGLBINDPROGRAMPIPELINEEXTPROC) (GLuint pipeline); +typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPIPELINESEXTPROC) (GLsizei n, const GLuint *pipelines); +typedef void (GL_APIENTRYP PFNGLGENPROGRAMPIPELINESEXTPROC) (GLsizei n, GLuint *pipelines); +typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPIPELINEEXTPROC) (GLuint pipeline); +typedef void (GL_APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value); +typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEIVEXTPROC) (GLuint pipeline, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint x); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint x, GLint y); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat x); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEEXTPROC) (GLuint pipeline); +typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +#endif + +/* GL_EXT_shader_texture_lod */ +#ifndef GL_EXT_shader_texture_lod +#define GL_EXT_shader_texture_lod 1 +#endif + +/* GL_EXT_shadow_samplers */ +#ifndef GL_EXT_shadow_samplers +#define GL_EXT_shadow_samplers 1 +#endif + +/* GL_EXT_sRGB */ +#ifndef GL_EXT_sRGB +#define GL_EXT_sRGB 1 +#endif + +/* GL_EXT_texture_compression_dxt1 */ +#ifndef GL_EXT_texture_compression_dxt1 +#define GL_EXT_texture_compression_dxt1 1 +#endif + +/* GL_EXT_texture_filter_anisotropic */ +#ifndef GL_EXT_texture_filter_anisotropic +#define GL_EXT_texture_filter_anisotropic 1 +#endif + +/* GL_EXT_texture_format_BGRA8888 */ +#ifndef GL_EXT_texture_format_BGRA8888 +#define GL_EXT_texture_format_BGRA8888 1 +#endif + +/* GL_EXT_texture_rg */ +#ifndef GL_EXT_texture_rg +#define GL_EXT_texture_rg 1 +#endif + +/* GL_EXT_texture_storage */ +#ifndef GL_EXT_texture_storage +#define GL_EXT_texture_storage 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glTexStorage1DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +GL_APICALL void GL_APIENTRY glTexStorage2DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glTexStorage3DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +GL_APICALL void GL_APIENTRY glTextureStorage1DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +GL_APICALL void GL_APIENTRY glTextureStorage2DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glTextureStorage3DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +#endif +typedef void (GL_APIENTRYP PFNGLTEXSTORAGE1DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +#endif + +/* GL_EXT_texture_type_2_10_10_10_REV */ +#ifndef GL_EXT_texture_type_2_10_10_10_REV +#define GL_EXT_texture_type_2_10_10_10_REV 1 +#endif + +/* GL_EXT_unpack_subimage */ +#ifndef GL_EXT_unpack_subimage +#define GL_EXT_unpack_subimage 1 +#endif + +/*------------------------------------------------------------------------* + * DMP extension functions + *------------------------------------------------------------------------*/ + +/* GL_DMP_shader_binary */ +#ifndef GL_DMP_shader_binary +#define GL_DMP_shader_binary 1 +#endif + +/*------------------------------------------------------------------------* + * IMG extension functions + *------------------------------------------------------------------------*/ + +/* GL_IMG_program_binary */ +#ifndef GL_IMG_program_binary +#define GL_IMG_program_binary 1 +#endif + +/* GL_IMG_read_format */ +#ifndef GL_IMG_read_format +#define GL_IMG_read_format 1 +#endif + +/* GL_IMG_shader_binary */ +#ifndef GL_IMG_shader_binary +#define GL_IMG_shader_binary 1 +#endif + +/* GL_IMG_texture_compression_pvrtc */ +#ifndef GL_IMG_texture_compression_pvrtc +#define GL_IMG_texture_compression_pvrtc 1 +#endif + +/* GL_IMG_multisampled_render_to_texture */ +#ifndef GL_IMG_multisampled_render_to_texture +#define GL_IMG_multisampled_render_to_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleIMG (GLenum, GLsizei, GLenum, GLsizei, GLsizei); +GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleIMG (GLenum, GLenum, GLenum, GLuint, GLint, GLsizei); +#endif +typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMG) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMG) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples); +#endif + +/*------------------------------------------------------------------------* + * NV extension functions + *------------------------------------------------------------------------*/ + +/* GL_NV_coverage_sample */ +#ifndef GL_NV_coverage_sample +#define GL_NV_coverage_sample 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glCoverageMaskNV (GLboolean mask); +GL_APICALL void GL_APIENTRY glCoverageOperationNV (GLenum operation); +#endif +typedef void (GL_APIENTRYP PFNGLCOVERAGEMASKNVPROC) (GLboolean mask); +typedef void (GL_APIENTRYP PFNGLCOVERAGEOPERATIONNVPROC) (GLenum operation); +#endif + +/* GL_NV_depth_nonlinear */ +#ifndef GL_NV_depth_nonlinear +#define GL_NV_depth_nonlinear 1 +#endif + +/* GL_NV_draw_buffers */ +#ifndef GL_NV_draw_buffers +#define GL_NV_draw_buffers 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDrawBuffersNV (GLsizei n, const GLenum *bufs); +#endif +typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSNVPROC) (GLsizei n, const GLenum *bufs); +#endif + +/* GL_NV_fbo_color_attachments */ +#ifndef GL_NV_fbo_color_attachments +#define GL_NV_fbo_color_attachments 1 +#endif + +/* GL_NV_fence */ +#ifndef GL_NV_fence +#define GL_NV_fence 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDeleteFencesNV (GLsizei, const GLuint *); +GL_APICALL void GL_APIENTRY glGenFencesNV (GLsizei, GLuint *); +GL_APICALL GLboolean GL_APIENTRY glIsFenceNV (GLuint); +GL_APICALL GLboolean GL_APIENTRY glTestFenceNV (GLuint); +GL_APICALL void GL_APIENTRY glGetFenceivNV (GLuint, GLenum, GLint *); +GL_APICALL void GL_APIENTRY glFinishFenceNV (GLuint); +GL_APICALL void GL_APIENTRY glSetFenceNV (GLuint, GLenum); +#endif +typedef void (GL_APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences); +typedef void (GL_APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences); +typedef GLboolean (GL_APIENTRYP PFNGLISFENCENVPROC) (GLuint fence); +typedef GLboolean (GL_APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence); +typedef void (GL_APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence); +typedef void (GL_APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition); +#endif + +/* GL_NV_read_buffer */ +#ifndef GL_NV_read_buffer +#define GL_NV_read_buffer 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glReadBufferNV (GLenum mode); +#endif +typedef void (GL_APIENTRYP PFNGLREADBUFFERNVPROC) (GLenum mode); +#endif + +/* GL_NV_read_buffer_front */ +#ifndef GL_NV_read_buffer_front +#define GL_NV_read_buffer_front 1 +#endif + +/* GL_NV_read_depth */ +#ifndef GL_NV_read_depth +#define GL_NV_read_depth 1 +#endif + +/* GL_NV_read_depth_stencil */ +#ifndef GL_NV_read_depth_stencil +#define GL_NV_read_depth_stencil 1 +#endif + +/* GL_NV_read_stencil */ +#ifndef GL_NV_read_stencil +#define GL_NV_read_stencil 1 +#endif + +/* GL_NV_texture_compression_s3tc_update */ +#ifndef GL_NV_texture_compression_s3tc_update +#define GL_NV_texture_compression_s3tc_update 1 +#endif + +/* GL_NV_texture_npot_2D_mipmap */ +#ifndef GL_NV_texture_npot_2D_mipmap +#define GL_NV_texture_npot_2D_mipmap 1 +#endif + +/*------------------------------------------------------------------------* + * QCOM extension functions + *------------------------------------------------------------------------*/ + +/* GL_QCOM_alpha_test */ +#ifndef GL_QCOM_alpha_test +#define GL_QCOM_alpha_test 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glAlphaFuncQCOM (GLenum func, GLclampf ref); +#endif +typedef void (GL_APIENTRYP PFNGLALPHAFUNCQCOMPROC) (GLenum func, GLclampf ref); +#endif + +/* GL_QCOM_driver_control */ +#ifndef GL_QCOM_driver_control +#define GL_QCOM_driver_control 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glGetDriverControlsQCOM (GLint *num, GLsizei size, GLuint *driverControls); +GL_APICALL void GL_APIENTRY glGetDriverControlStringQCOM (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString); +GL_APICALL void GL_APIENTRY glEnableDriverControlQCOM (GLuint driverControl); +GL_APICALL void GL_APIENTRY glDisableDriverControlQCOM (GLuint driverControl); +#endif +typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSQCOMPROC) (GLint *num, GLsizei size, GLuint *driverControls); +typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSTRINGQCOMPROC) (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString); +typedef void (GL_APIENTRYP PFNGLENABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl); +typedef void (GL_APIENTRYP PFNGLDISABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl); +#endif + +/* GL_QCOM_extended_get */ +#ifndef GL_QCOM_extended_get +#define GL_QCOM_extended_get 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glExtGetTexturesQCOM (GLuint *textures, GLint maxTextures, GLint *numTextures); +GL_APICALL void GL_APIENTRY glExtGetBuffersQCOM (GLuint *buffers, GLint maxBuffers, GLint *numBuffers); +GL_APICALL void GL_APIENTRY glExtGetRenderbuffersQCOM (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers); +GL_APICALL void GL_APIENTRY glExtGetFramebuffersQCOM (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers); +GL_APICALL void GL_APIENTRY glExtGetTexLevelParameterivQCOM (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glExtTexObjectStateOverrideiQCOM (GLenum target, GLenum pname, GLint param); +GL_APICALL void GL_APIENTRY glExtGetTexSubImageQCOM (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels); +GL_APICALL void GL_APIENTRY glExtGetBufferPointervQCOM (GLenum target, GLvoid **params); +#endif +typedef void (GL_APIENTRYP PFNGLEXTGETTEXTURESQCOMPROC) (GLuint *textures, GLint maxTextures, GLint *numTextures); +typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERSQCOMPROC) (GLuint *buffers, GLint maxBuffers, GLint *numBuffers); +typedef void (GL_APIENTRYP PFNGLEXTGETRENDERBUFFERSQCOMPROC) (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers); +typedef void (GL_APIENTRYP PFNGLEXTGETFRAMEBUFFERSQCOMPROC) (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers); +typedef void (GL_APIENTRYP PFNGLEXTGETTEXLEVELPARAMETERIVQCOMPROC) (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLEXTTEXOBJECTSTATEOVERRIDEIQCOMPROC) (GLenum target, GLenum pname, GLint param); +typedef void (GL_APIENTRYP PFNGLEXTGETTEXSUBIMAGEQCOMPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels); +typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERPOINTERVQCOMPROC) (GLenum target, GLvoid **params); +#endif + +/* GL_QCOM_extended_get2 */ +#ifndef GL_QCOM_extended_get2 +#define GL_QCOM_extended_get2 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glExtGetShadersQCOM (GLuint *shaders, GLint maxShaders, GLint *numShaders); +GL_APICALL void GL_APIENTRY glExtGetProgramsQCOM (GLuint *programs, GLint maxPrograms, GLint *numPrograms); +GL_APICALL GLboolean GL_APIENTRY glExtIsProgramBinaryQCOM (GLuint program); +GL_APICALL void GL_APIENTRY glExtGetProgramBinarySourceQCOM (GLuint program, GLenum shadertype, GLchar *source, GLint *length); +#endif +typedef void (GL_APIENTRYP PFNGLEXTGETSHADERSQCOMPROC) (GLuint *shaders, GLint maxShaders, GLint *numShaders); +typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMSQCOMPROC) (GLuint *programs, GLint maxPrograms, GLint *numPrograms); +typedef GLboolean (GL_APIENTRYP PFNGLEXTISPROGRAMBINARYQCOMPROC) (GLuint program); +typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC) (GLuint program, GLenum shadertype, GLchar *source, GLint *length); +#endif + +/* GL_QCOM_perfmon_global_mode */ +#ifndef GL_QCOM_perfmon_global_mode +#define GL_QCOM_perfmon_global_mode 1 +#endif + +/* GL_QCOM_writeonly_rendering */ +#ifndef GL_QCOM_writeonly_rendering +#define GL_QCOM_writeonly_rendering 1 +#endif + +/* GL_QCOM_tiled_rendering */ +#ifndef GL_QCOM_tiled_rendering +#define GL_QCOM_tiled_rendering 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glStartTilingQCOM (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask); +GL_APICALL void GL_APIENTRY glEndTilingQCOM (GLbitfield preserveMask); +#endif +typedef void (GL_APIENTRYP PFNGLSTARTTILINGQCOMPROC) (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask); +typedef void (GL_APIENTRYP PFNGLENDTILINGQCOMPROC) (GLbitfield preserveMask); +#endif + +/*------------------------------------------------------------------------* + * VIV extension tokens + *------------------------------------------------------------------------*/ + +/* GL_VIV_shader_binary */ +#ifndef GL_VIV_shader_binary +#define GL_VIV_shader_binary 1 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __gl2ext_h_ */ diff --git a/cogl/cogl-gles2/GLES2/gl2platform.h b/cogl/cogl-gles2/GLES2/gl2platform.h new file mode 100644 index 0000000..8bc44b0 --- /dev/null +++ b/cogl/cogl-gles2/GLES2/gl2platform.h @@ -0,0 +1,28 @@ +#ifndef __gl2platform_h_ +#define __gl2platform_h_ + +/* $Revision: 10602 $ on $Date:: 2010-03-04 22:35:34 -0800 #$ */ + +/* + * This document is licensed under the SGI Free Software B License Version + * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ . + */ + +/* Platform-specific types and definitions for OpenGL ES 2.X gl2.h + * + * Adopters may modify khrplatform.h and this file to suit their platform. + * You are encouraged to submit all modifications to the Khronos group so that + * they can be included in future versions of this file. Please submit changes + * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla) + * by filing a bug against product "OpenGL-ES" component "Registry". + */ + +#ifndef GL_APICALL +#define GL_APICALL +#endif + +#ifndef GL_APIENTRY +#define GL_APIENTRY +#endif + +#endif /* __gl2platform_h_ */ diff --git a/cogl/cogl-gles2/Makefile.am b/cogl/cogl-gles2/Makefile.am new file mode 100644 index 0000000..d8650e5 --- /dev/null +++ b/cogl/cogl-gles2/Makefile.am @@ -0,0 +1,31 @@ +# preamble + +NULL = + +mutterlibdir = $(libdir)/mutter +mutterlib_LTLIBRARIES = libmutter-cogl-gles2.la + +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) + +AM_CFLAGS = $(COGL_DEP_CFLAGS) $(COGL_EXTRA_CFLAGS) $(MAINTAINER_CFLAGS) + +libmutter_cogl_gles2_la_SOURCES = cogl-gles2-api.c +libmutter_cogl_gles2_la_LDFLAGS = \ + -no-undefined \ + -rpath $(mutterlibdir) \ + -avoid-version \ + -export-dynamic \ + -export-symbols-regex "^gl*" + +coglgles2includedir = $(includedir)/mutter/cogl/cogl-gles2/GLES2 +coglgles2include_HEADERS = \ + GLES2/gl2.h \ + GLES2/gl2ext.h \ + GLES2/gl2platform.h + +pc_files = mutter-cogl-gles2-1.0.pc + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = $(pc_files) diff --git a/cogl/cogl-gles2/Makefile.in b/cogl/cogl-gles2/Makefile.in new file mode 100644 index 0000000..d2c2e8a --- /dev/null +++ b/cogl/cogl-gles2/Makefile.in @@ -0,0 +1,808 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# preamble + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = cogl-gles2 +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/build/autotools/as-compiler-flag.m4 \ + $(top_srcdir)/build/autotools/introspection.m4 \ + $(top_srcdir)/build/autotools/libtool.m4 \ + $(top_srcdir)/build/autotools/ltoptions.m4 \ + $(top_srcdir)/build/autotools/ltsugar.m4 \ + $(top_srcdir)/build/autotools/ltversion.m4 \ + $(top_srcdir)/build/autotools/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(coglgles2include_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/cogl-config.h \ + $(top_builddir)/cogl-mutter-config.h +CONFIG_CLEAN_FILES = mutter-cogl-gles2-1.0.pc +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(mutterlibdir)" \ + "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(coglgles2includedir)" +LTLIBRARIES = $(mutterlib_LTLIBRARIES) +libmutter_cogl_gles2_la_LIBADD = +am_libmutter_cogl_gles2_la_OBJECTS = cogl-gles2-api.lo +libmutter_cogl_gles2_la_OBJECTS = \ + $(am_libmutter_cogl_gles2_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libmutter_cogl_gles2_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libmutter_cogl_gles2_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libmutter_cogl_gles2_la_SOURCES) +DIST_SOURCES = $(libmutter_cogl_gles2_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(pkgconfig_DATA) +HEADERS = $(coglgles2include_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(srcdir)/mutter-cogl-gles2-1.0.pc.in \ + $(top_srcdir)/build/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_REQ_VERSION = @CAIRO_REQ_VERSION@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COGL_1_MICRO_VERSION = @COGL_1_MICRO_VERSION@ +COGL_1_MINOR_VERSION = @COGL_1_MINOR_VERSION@ +COGL_1_VERSION = @COGL_1_VERSION@ +COGL_API_VERSION = @COGL_API_VERSION@ +COGL_API_VERSION_AM = @COGL_API_VERSION_AM@ +COGL_DEBUG_CFLAGS = @COGL_DEBUG_CFLAGS@ +COGL_DEFAULT_DRIVER = @COGL_DEFAULT_DRIVER@ +COGL_DEP_CFLAGS = @COGL_DEP_CFLAGS@ +COGL_DEP_GL_CFLAGS = @COGL_DEP_GL_CFLAGS@ +COGL_DEP_GL_LIBS = @COGL_DEP_GL_LIBS@ +COGL_DEP_LIBS = @COGL_DEP_LIBS@ +COGL_EGL_INCLUDES = @COGL_EGL_INCLUDES@ +COGL_EXTRA_CFLAGS = @COGL_EXTRA_CFLAGS@ +COGL_EXTRA_LDFLAGS = @COGL_EXTRA_LDFLAGS@ +COGL_GLES1_LIBNAME = @COGL_GLES1_LIBNAME@ +COGL_GLES2_LIBNAME = @COGL_GLES2_LIBNAME@ +COGL_GL_LIBNAME = @COGL_GL_LIBNAME@ +COGL_GST_DEP_CFLAGS = @COGL_GST_DEP_CFLAGS@ +COGL_GST_DEP_LIBS = @COGL_GST_DEP_LIBS@ +COGL_LT_AGE = @COGL_LT_AGE@ +COGL_LT_CURRENT = @COGL_LT_CURRENT@ +COGL_LT_RELEASE = @COGL_LT_RELEASE@ +COGL_LT_REVISION = @COGL_LT_REVISION@ +COGL_MAJOR_VERSION = @COGL_MAJOR_VERSION@ +COGL_MICRO_VERSION = @COGL_MICRO_VERSION@ +COGL_MINOR_VERSION = @COGL_MINOR_VERSION@ +COGL_PANGO_DEP_CFLAGS = @COGL_PANGO_DEP_CFLAGS@ +COGL_PANGO_DEP_LIBS = @COGL_PANGO_DEP_LIBS@ +COGL_PANGO_PKG_REQUIRES = @COGL_PANGO_PKG_REQUIRES@ +COGL_PKG_REQUIRES = @COGL_PKG_REQUIRES@ +COGL_RELEASE_STATUS = @COGL_RELEASE_STATUS@ +COGL_VERSION = @COGL_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMMY_CFLAGS = @DUMMY_CFLAGS@ +DUMMY_LIBS = @DUMMY_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDKPIXBUF_PREFIX = @GDKPIXBUF_PREFIX@ +GDK_PIXBUF_REQ_VERSION = @GDK_PIXBUF_REQ_VERSION@ +GI_REQ_VERSION = @GI_REQ_VERSION@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ_VERSION = @GLIB_REQ_VERSION@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +HAVE_GL = @HAVE_GL@ +HAVE_GLES1 = @HAVE_GLES1@ +HAVE_GLES2 = @HAVE_GLES2@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINTAINER_CFLAGS = @MAINTAINER_CFLAGS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGOCAIRO_REQ_VERSION = @PANGOCAIRO_REQ_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +UPROF_REQ_VERSION = @UPROF_REQ_VERSION@ +VERSION = @VERSION@ +WAYLAND_SERVER_CFLAGS = @WAYLAND_SERVER_CFLAGS@ +WAYLAND_SERVER_LIBS = @WAYLAND_SERVER_LIBS@ +WAYLAND_SERVER_REQ_VERSION = @WAYLAND_SERVER_REQ_VERSION@ +XCOMPOSITE_REQ_VERSION = @XCOMPOSITE_REQ_VERSION@ +XFIXES_REQ_VERSION = @XFIXES_REQ_VERSION@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = +mutterlibdir = $(libdir)/mutter +mutterlib_LTLIBRARIES = libmutter-cogl-gles2.la +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) + +AM_CFLAGS = $(COGL_DEP_CFLAGS) $(COGL_EXTRA_CFLAGS) $(MAINTAINER_CFLAGS) +libmutter_cogl_gles2_la_SOURCES = cogl-gles2-api.c +libmutter_cogl_gles2_la_LDFLAGS = \ + -no-undefined \ + -rpath $(mutterlibdir) \ + -avoid-version \ + -export-dynamic \ + -export-symbols-regex "^gl*" + +coglgles2includedir = $(includedir)/mutter/cogl/cogl-gles2/GLES2 +coglgles2include_HEADERS = \ + GLES2/gl2.h \ + GLES2/gl2ext.h \ + GLES2/gl2platform.h + +pc_files = mutter-cogl-gles2-1.0.pc +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = $(pc_files) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign cogl-gles2/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign cogl-gles2/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +mutter-cogl-gles2-1.0.pc: $(top_builddir)/config.status $(srcdir)/mutter-cogl-gles2-1.0.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +install-mutterlibLTLIBRARIES: $(mutterlib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(mutterlib_LTLIBRARIES)'; test -n "$(mutterlibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(mutterlibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(mutterlibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(mutterlibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(mutterlibdir)"; \ + } + +uninstall-mutterlibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(mutterlib_LTLIBRARIES)'; test -n "$(mutterlibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(mutterlibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(mutterlibdir)/$$f"; \ + done + +clean-mutterlibLTLIBRARIES: + -test -z "$(mutterlib_LTLIBRARIES)" || rm -f $(mutterlib_LTLIBRARIES) + @list='$(mutterlib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libmutter-cogl-gles2.la: $(libmutter_cogl_gles2_la_OBJECTS) $(libmutter_cogl_gles2_la_DEPENDENCIES) $(EXTRA_libmutter_cogl_gles2_la_DEPENDENCIES) + $(AM_V_CCLD)$(libmutter_cogl_gles2_la_LINK) -rpath $(mutterlibdir) $(libmutter_cogl_gles2_la_OBJECTS) $(libmutter_cogl_gles2_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-gles2-api.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-pkgconfigDATA: $(pkgconfig_DATA) + @$(NORMAL_INSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ + done + +uninstall-pkgconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) +install-coglgles2includeHEADERS: $(coglgles2include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(coglgles2include_HEADERS)'; test -n "$(coglgles2includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(coglgles2includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(coglgles2includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(coglgles2includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(coglgles2includedir)" || exit $$?; \ + done + +uninstall-coglgles2includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(coglgles2include_HEADERS)'; test -n "$(coglgles2includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(coglgles2includedir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(mutterlibdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(coglgles2includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-mutterlibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-coglgles2includeHEADERS \ + install-mutterlibLTLIBRARIES install-pkgconfigDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-coglgles2includeHEADERS \ + uninstall-mutterlibLTLIBRARIES uninstall-pkgconfigDATA + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-mutterlibLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am \ + install-coglgles2includeHEADERS install-data install-data-am \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-mutterlibLTLIBRARIES install-pdf \ + install-pdf-am install-pkgconfigDATA install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-coglgles2includeHEADERS \ + uninstall-mutterlibLTLIBRARIES uninstall-pkgconfigDATA + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cogl/cogl-gles2/cogl-gles2-api.c b/cogl/cogl-gles2/cogl-gles2-api.c new file mode 100644 index 0000000..22ab2b7 --- /dev/null +++ b/cogl/cogl-gles2/cogl-gles2-api.c @@ -0,0 +1,1048 @@ + +#include + +#include + +void +glBindTexture (GLenum target, GLuint texture) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glBindTexture (target, texture); +} + +void +glBlendFunc (GLenum sfactor, GLenum dfactor) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glBlendFunc (sfactor, dfactor); +} + +void +glClear (GLbitfield mask) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glClear (mask); +} + +void +glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glClearColor (red, green, blue, alpha); +} + +void +glClearStencil (GLint s) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glClearStencil (s); +} + +void +glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glColorMask (red, green, blue, alpha); +} + +void +glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLint x, GLint y, GLsizei width, GLsizei height) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glCopyTexSubImage2D (target, level, xoffset, yoffset, x, y, width, + height); +} + +void +glDeleteTextures (GLsizei n, const GLuint * textures) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glDeleteTextures (n, textures); +} + +void +glDepthFunc (GLenum func) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glDepthFunc (func); +} + +void +glDepthMask (GLboolean flag) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glDepthMask (flag); +} + +void +glDisable (GLenum cap) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glDisable (cap); +} + +void +glDrawArrays (GLenum mode, GLint first, GLsizei count) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glDrawArrays (mode, first, count); +} + +void +glDrawElements (GLenum mode, GLsizei count, GLenum type, + const GLvoid * indices) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glDrawElements (mode, count, type, indices); +} + +void +glEnable (GLenum cap) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glEnable (cap); +} + +void +glFinish (void) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glFinish (); +} + +void +glFlush (void) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glFlush (); +} + +void +glFrontFace (GLenum mode) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glFrontFace (mode); +} + +void +glCullFace (GLenum mode) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glCullFace (mode); +} + +void +glGenTextures (GLsizei n, GLuint * textures) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGenTextures (n, textures); +} + +GLenum +glGetError (void) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + return vtable->glGetError (); +} + +void +glGetIntegerv (GLenum pname, GLint * params) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGetIntegerv (pname, params); +} + +void +glGetBooleanv (GLenum pname, GLboolean * params) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGetBooleanv (pname, params); +} + +void +glGetFloatv (GLenum pname, GLfloat * params) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGetFloatv (pname, params); +} + +const GLubyte * +glGetString (GLenum name) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + return vtable->glGetString (name); +} + +void +glHint (GLenum target, GLenum mode) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glHint (target, mode); +} + +GLboolean +glIsTexture (GLuint texture) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + return vtable->glIsTexture (texture); +} + +void +glPixelStorei (GLenum pname, GLint param) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glPixelStorei (pname, param); +} + +void +glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, + GLenum type, GLvoid * pixels) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glReadPixels (x, y, width, height, format, type, pixels); +} + +void +glScissor (GLint x, GLint y, GLsizei width, GLsizei height) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glScissor (x, y, width, height); +} + +void +glStencilFunc (GLenum func, GLint ref, GLuint mask) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glStencilFunc (func, ref, mask); +} + +void +glStencilMask (GLuint mask) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glStencilMask (mask); +} + +void +glStencilOp (GLenum fail, GLenum zfail, GLenum zpass) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glStencilOp (fail, zfail, zpass); +} + +void +glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, + GLsizei height, GLint border, GLenum format, GLenum type, + const GLvoid * pixels) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glTexImage2D (target, level, internalformat, width, height, border, + format, type, pixels); +} + +void +glTexParameterf (GLenum target, GLenum pname, GLfloat param) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glTexParameterf (target, pname, param); +} + +void +glTexParameterfv (GLenum target, GLenum pname, const GLfloat * params) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glTexParameterfv (target, pname, params); +} + +void +glTexParameteri (GLenum target, GLenum pname, GLint param) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glTexParameteri (target, pname, param); +} + +void +glTexParameteriv (GLenum target, GLenum pname, const GLint * params) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glTexParameteriv (target, pname, params); +} + +void +glGetTexParameterfv (GLenum target, GLenum pname, GLfloat * params) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGetTexParameterfv (target, pname, params); +} + +void +glGetTexParameteriv (GLenum target, GLenum pname, GLint * params) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGetTexParameteriv (target, pname, params); +} + +void +glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, GLenum format, GLenum type, + const GLvoid * pixels) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glTexSubImage2D (target, level, xoffset, yoffset, width, height, + format, type, pixels); +} + +void +glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, + GLint y, GLsizei width, GLsizei height, GLint border) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glCopyTexImage2D (target, level, internalformat, + x, y, width, height, border); +} + +void +glViewport (GLint x, GLint y, GLsizei width, GLsizei height) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glViewport (x, y, width, height); +} + +GLboolean +glIsEnabled (GLenum cap) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + return vtable->glIsEnabled (cap); +} + +void +glLineWidth (GLfloat width) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glLineWidth (width); +} + +void +glPolygonOffset (GLfloat factor, GLfloat units) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glPolygonOffset (factor, units); +} + +void +glDepthRangef (GLfloat near_val, GLfloat far_val) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glDepthRangef (near_val, far_val); +} + +void +glClearDepthf (GLclampf depth) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glClearDepthf (depth); +} + +void +glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, + GLsizei width, GLsizei height, GLint border, + GLsizei imageSize, const GLvoid * data) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glCompressedTexImage2D (target, level, internalformat, width, + height, border, imageSize, data); +} + +void +glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, + GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLsizei imageSize, + const GLvoid * data) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glCompressedTexSubImage2D (target, level, + xoffset, yoffset, width, height, + format, imageSize, data); +} + +void +glSampleCoverage (GLclampf value, GLboolean invert) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glSampleCoverage (value, invert); +} + +void +glGetBufferParameteriv (GLenum target, GLenum pname, GLint * params) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGetBufferParameteriv (target, pname, params); +} + +void +glGenBuffers (GLsizei n, GLuint * buffers) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGenBuffers (n, buffers); +} + +void +glBindBuffer (GLenum target, GLuint buffer) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glBindBuffer (target, buffer); +} + +void +glBufferData (GLenum target, GLsizeiptr size, const GLvoid * data, + GLenum usage) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glBufferData (target, size, data, usage); +} + +void +glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, + const GLvoid * data) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glBufferSubData (target, offset, size, data); +} + +void +glDeleteBuffers (GLsizei n, const GLuint * buffers) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glDeleteBuffers (n, buffers); +} + +GLboolean +glIsBuffer (GLuint buffer) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + return vtable->glIsBuffer (buffer); +} + +void +glActiveTexture (GLenum texture) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glActiveTexture (texture); +} + +void +glGenRenderbuffers (GLsizei n, GLuint * renderbuffers) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGenRenderbuffers (n, renderbuffers); +} + +void +glDeleteRenderbuffers (GLsizei n, const GLuint * renderbuffers) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glDeleteRenderbuffers (n, renderbuffers); +} + +void +glBindRenderbuffer (GLenum target, GLuint renderbuffer) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glBindRenderbuffer (target, renderbuffer); +} + +void +glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, + GLsizei height) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glRenderbufferStorage (target, internalformat, width, height); +} + +void +glGenFramebuffers (GLsizei n, GLuint * framebuffers) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGenFramebuffers (n, framebuffers); +} + +void +glBindFramebuffer (GLenum target, GLuint framebuffer) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glBindFramebuffer (target, framebuffer); +} + +void +glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, + GLuint texture, GLint level) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glFramebufferTexture2D (target, attachment, + textarget, texture, level); +} + +void +glFramebufferRenderbuffer (GLenum target, GLenum attachment, + GLenum renderbuffertarget, GLuint renderbuffer) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glFramebufferRenderbuffer (target, attachment, + renderbuffertarget, renderbuffer); +} + +GLboolean +glIsRenderbuffer (GLuint renderbuffer) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + return vtable->glIsRenderbuffer (renderbuffer); +} + +GLenum +glCheckFramebufferStatus (GLenum target) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + return vtable->glCheckFramebufferStatus (target); +} + +void +glDeleteFramebuffers (GLsizei n, const GLuint * framebuffers) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glDeleteFramebuffers (n, framebuffers); +} + +void +glGenerateMipmap (GLenum target) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGenerateMipmap (target); +} + +void +glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, + GLenum pname, GLint * params) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGetFramebufferAttachmentParameteriv (target, + attachment, pname, params); +} + +void +glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint * params) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGetRenderbufferParameteriv (target, pname, params); +} + +GLboolean +glIsFramebuffer (GLuint framebuffer) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + return vtable->glIsFramebuffer (framebuffer); +} + +void +glBlendEquation (GLenum mode) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glBlendEquation (mode); +} + +void +glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glBlendColor (red, green, blue, alpha); +} + +void +glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, + GLenum dstAlpha) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glBlendFuncSeparate (srcRGB, dstRGB, srcAlpha, dstAlpha); +} + +void +glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glBlendEquationSeparate (modeRGB, modeAlpha); +} + +void +glReleaseShaderCompiler (void) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glReleaseShaderCompiler (); +} + +void +glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, + GLint * range, GLint * precision) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGetShaderPrecisionFormat (shadertype, precisiontype, + range, precision); +} + +void +glShaderBinary (GLsizei n, const GLuint * shaders, GLenum binaryformat, + const GLvoid * binary, GLsizei length) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glShaderBinary (n, shaders, binaryformat, binary, length); +} + +void +glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glStencilFuncSeparate (face, func, ref, mask); +} + +void +glStencilMaskSeparate (GLenum face, GLuint mask) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glStencilMaskSeparate (face, mask); +} + +void +glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glStencilOpSeparate (face, fail, zfail, zpass); +} + +GLuint +glCreateProgram (void) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + return vtable->glCreateProgram (); +} + +GLuint +glCreateShader (GLenum shaderType) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + return vtable->glCreateShader (shaderType); +} + +void +glShaderSource (GLuint shader, GLsizei count, + const GLchar * const *string, const GLint * length) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glShaderSource (shader, count, string, length); +} + +void +glCompileShader (GLuint shader) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glCompileShader (shader); +} + +void +glDeleteShader (GLuint shader) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glDeleteShader (shader); +} + +void +glAttachShader (GLuint program, GLuint shader) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glAttachShader (program, shader); +} + +void +glLinkProgram (GLuint program) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glLinkProgram (program); +} + +void +glUseProgram (GLuint program) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glUseProgram (program); +} + +GLint +glGetUniformLocation (GLuint program, const char *name) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + return vtable->glGetUniformLocation (program, name); +} + +void +glDeleteProgram (GLuint program) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glDeleteProgram (program); +} + +void +glGetShaderInfoLog (GLuint shader, GLsizei maxLength, GLsizei * length, + char *infoLog) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGetShaderInfoLog (shader, maxLength, length, infoLog); +} + +void +glGetShaderiv (GLuint shader, GLenum pname, GLint * params) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGetShaderiv (shader, pname, params); +} + +void +glVertexAttribPointer (GLuint index, GLint size, GLenum type, + GLboolean normalized, GLsizei stride, + const GLvoid * pointer) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glVertexAttribPointer (index, size, type, normalized, stride, + pointer); +} + +void +glEnableVertexAttribArray (GLuint index) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glEnableVertexAttribArray (index); +} + +void +glDisableVertexAttribArray (GLuint index) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glDisableVertexAttribArray (index); +} + +void +glUniform1f (GLint location, GLfloat v0) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glUniform1f (location, v0); +} + +void +glUniform2f (GLint location, GLfloat v0, GLfloat v1) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glUniform2f (location, v0, v1); +} + +void +glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glUniform3f (location, v0, v1, v2); +} + +void +glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glUniform4f (location, v0, v1, v2, v3); +} + +void +glUniform1fv (GLint location, GLsizei count, const GLfloat * value) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glUniform1fv (location, count, value); +} + +void +glUniform2fv (GLint location, GLsizei count, const GLfloat * value) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glUniform2fv (location, count, value); +} + +void +glUniform3fv (GLint location, GLsizei count, const GLfloat * value) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glUniform3fv (location, count, value); +} + +void +glUniform4fv (GLint location, GLsizei count, const GLfloat * value) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glUniform4fv (location, count, value); +} + +void +glUniform1i (GLint location, GLint v0) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glUniform1i (location, v0); +} + +void +glUniform2i (GLint location, GLint v0, GLint v1) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glUniform2i (location, v0, v1); +} + +void +glUniform3i (GLint location, GLint v0, GLint v1, GLint v2) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glUniform3i (location, v0, v1, v2); +} + +void +glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glUniform4i (location, v0, v1, v2, v3); +} + +void +glUniform1iv (GLint location, GLsizei count, const GLint * value) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glUniform1iv (location, count, value); +} + +void +glUniform2iv (GLint location, GLsizei count, const GLint * value) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glUniform2iv (location, count, value); +} + +void +glUniform3iv (GLint location, GLsizei count, const GLint * value) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glUniform3iv (location, count, value); +} + +void +glUniform4iv (GLint location, GLsizei count, const GLint * value) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glUniform4iv (location, count, value); +} + +void +glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, + const GLfloat * value) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glUniformMatrix2fv (location, count, transpose, value); +} + +void +glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, + const GLfloat * value) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glUniformMatrix3fv (location, count, transpose, value); +} + +void +glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, + const GLfloat * value) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glUniformMatrix4fv (location, count, transpose, value); +} + +void +glGetUniformfv (GLuint program, GLint location, GLfloat * params) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGetUniformfv (program, location, params); +} + +void +glGetUniformiv (GLuint program, GLint location, GLint * params) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGetUniformiv (program, location, params); +} + +void +glGetProgramiv (GLuint program, GLenum pname, GLint * params) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGetProgramiv (program, pname, params); +} + +void +glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei * length, + char *infoLog) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGetProgramInfoLog (program, bufSize, length, infoLog); +} + +void +glVertexAttrib1f (GLuint indx, GLfloat x) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glVertexAttrib1f (indx, x); +} + +void +glVertexAttrib1fv (GLuint indx, const GLfloat * values) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glVertexAttrib1fv (indx, values); +} + +void +glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glVertexAttrib2f (indx, x, y); +} + +void +glVertexAttrib2fv (GLuint indx, const GLfloat * values) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glVertexAttrib2fv (indx, values); +} + +void +glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glVertexAttrib3f (indx, x, y, z); +} + +void +glVertexAttrib3fv (GLuint indx, const GLfloat * values) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glVertexAttrib3fv (indx, values); +} + +void +glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glVertexAttrib4f (index, x, y, z, w); +} + +void +glVertexAttrib4fv (GLuint indx, const GLfloat * values) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glVertexAttrib4fv (indx, values); +} + +void +glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat * params) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGetVertexAttribfv (index, pname, params); +} + +void +glGetVertexAttribiv (GLuint index, GLenum pname, GLint * params) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGetVertexAttribiv (index, pname, params); +} + +void +glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid ** pointer) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGetVertexAttribPointerv (index, pname, pointer); +} + +GLint +glGetAttribLocation (GLuint program, const char *name) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + return vtable->glGetAttribLocation (program, name); +} + +void +glBindAttribLocation (GLuint program, GLuint index, const GLchar * name) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glBindAttribLocation (program, index, name); +} + +void +glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, + GLsizei * length, GLint * size, GLenum * type, + GLchar * name) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGetActiveAttrib (program, index, bufsize, length, size, type, + name); +} + +void +glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, + GLsizei * length, GLint * size, GLenum * type, + GLchar * name) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGetActiveUniform (program, index, bufsize, length, size, type, + name); +} + +void +glDetachShader (GLuint program, GLuint shader) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glDetachShader (program, shader); +} + +void +glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei * count, + GLuint * shaders) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGetAttachedShaders (program, maxcount, count, shaders); +} + +void +glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei * length, + GLchar * source) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glGetShaderSource (shader, bufsize, length, source); +} + +GLboolean +glIsShader (GLuint shader) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + return vtable->glIsShader (shader); +} + +GLboolean +glIsProgram (GLuint program) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + return vtable->glIsProgram (program); +} + +void +glValidateProgram (GLuint program) +{ + CoglGLES2Vtable *vtable = cogl_gles2_get_current_vtable (); + vtable->glValidateProgram (program); +} diff --git a/cogl/cogl-gles2/mutter-cogl-gles2-1.0.pc.in b/cogl/cogl-gles2/mutter-cogl-gles2-1.0.pc.in new file mode 100644 index 0000000..a669353 --- /dev/null +++ b/cogl/cogl-gles2/mutter-cogl-gles2-1.0.pc.in @@ -0,0 +1,13 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@/mutter +includedir=@includedir@/mutter +apiversion=1.0 +requires=@COGL_PKG_REQUIRES@ mutter-cogl-1.0 + +Name: Cogl +Description: An object oriented GL/GLES Abstraction/Utility Layer +Version: @COGL_1_VERSION@ +Libs: -L${libdir} -lmutter-cogl-gles2 +Cflags: -I${includedir}/cogl +Requires: ${requires} diff --git a/cogl/cogl-mutter-config.h.in b/cogl/cogl-mutter-config.h.in new file mode 100644 index 0000000..bc7f146 --- /dev/null +++ b/cogl/cogl-mutter-config.h.in @@ -0,0 +1,17 @@ +/* Have GL for rendering */ +#undef HAVE_COGL_GL + +/* Have GLES 1.1 for rendering */ +#undef HAVE_COGL_GLES + +/* Have GLES 2.0 for rendering */ +#undef HAVE_COGL_GLES2 + +/* Define to 1 if you have the `ffs' function. */ +#undef HAVE_FFS + +/* Define to 1 if you have the `memmem' function. */ +#undef HAVE_MEMMEM + +/* Whether _Static_assert can be used or not */ +#undef HAVE_STATIC_ASSERT diff --git a/cogl/cogl-pango/Makefile.am b/cogl/cogl-pango/Makefile.am new file mode 100644 index 0000000..c9d5170 --- /dev/null +++ b/cogl/cogl-pango/Makefile.am @@ -0,0 +1,93 @@ +NULL = + +CLEANFILES = +DISTCLEANFILES = + +EXTRA_DIST = + +source_c = \ + cogl-pango-display-list.c \ + cogl-pango-fontmap.c \ + cogl-pango-render.c \ + cogl-pango-glyph-cache.c \ + cogl-pango-pipeline-cache.c \ + $(NULL) + +source_h = cogl-pango.h + +source_h_priv = \ + cogl-pango-display-list.h \ + cogl-pango-private.h \ + cogl-pango-glyph-cache.h \ + cogl-pango-pipeline-cache.h \ + $(NULL) + +mutterlibdir = $(libdir)/mutter +mutterlib_LTLIBRARIES = libmutter-cogl-pango.la + +libmutter_cogl_pango_la_SOURCES = $(source_c) $(source_h) $(source_h_priv) +libmutter_cogl_pango_la_CFLAGS = $(COGL_DEP_CFLAGS) $(COGL_PANGO_DEP_CFLAGS) $(COGL_EXTRA_CFLAGS) $(MAINTAINER_CFLAGS) +libmutter_cogl_pango_la_LIBADD = $(top_builddir)/cogl/libmutter-cogl.la +libmutter_cogl_pango_la_LIBADD += $(COGL_DEP_LIBS) $(COGL_PANGO_DEP_LIBS) $(COGL_EXTRA_LDFLAGS) +libmutter_cogl_pango_la_LDFLAGS = \ + -export-dynamic \ + -rpath $(mutterlibdir) \ + -export-symbols-regex "^cogl_pango_.*" \ + -no-undefined \ + -avoid-version + +AM_CPPFLAGS = \ + -DCOGL_COMPILATION \ + -DG_LOG_DOMAIN=\"CoglPango\" \ + -I$(top_srcdir)/cogl \ + -I$(top_builddir)/cogl \ + -I$(top_srcdir)/cogl/winsys \ + -I$(top_srcdir) \ + -I$(top_builddir) + +cogl_base_includedir = $(includedir)/mutter +cogl_pangoheadersdir = $(cogl_base_includedir)/cogl/cogl-pango +cogl_pangoheaders_HEADERS = $(source_h) + +pc_files = mutter-cogl-pango-1.0.pc + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = $(pc_files) + +DISTCLEANFILES += $(pc_files) + +EXTRA_DIST += cogl-pango.symbols + +-include $(INTROSPECTION_MAKEFILE) + +INTROSPECTION_GIRS = + +if HAVE_INTROSPECTION +INTROSPECTION_COMPILER_ARGS=--includedir=$(top_builddir)/cogl + +CoglPango-1.0.gir: libmutter-cogl-pango.la Makefile + +CoglPango_1_0_gir_NAMESPACE = CoglPango +CoglPango_1_0_gir_VERSION = 1.0 +CoglPango_1_0_gir_LIBS = $(top_builddir)/cogl/libmutter-cogl.la libmutter-cogl-pango.la +CoglPango_1_0_gir_FILES = $(source_h) $(source_c) +CoglPango_1_0_gir_CFLAGS = $(AM_CPPFLAGS) $(COGL_DEP_CFLAGS) $(COGL_PANGO_DEP_CFLAGS) +CoglPango_1_0_gir_INCLUDES = Pango-1.0 PangoCairo-1.0 +CoglPango_1_0_gir_EXPORT_PACKAGES = mutter-cogl-pango-1.0 +CoglPango_1_0_gir_SCANNERFLAGS = \ + --warn-all \ + --identifier-prefix=CoglPango \ + --symbol-prefix=cogl_pango \ + --c-include='cogl-pango/cogl-pango.h' \ + --include-uninstalled=$(top_builddir)/cogl/Cogl-1.0.gir + +INTROSPECTION_GIRS += CoglPango-1.0.gir + +girdir = $(mutterlibdir) +gir_DATA = $(INTROSPECTION_GIRS) + +typelibdir = $(mutterlibdir) +typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib) + +CLEANFILES += $(gir_DATA) $(typelib_DATA) +endif diff --git a/cogl/cogl-pango/Makefile.in b/cogl/cogl-pango/Makefile.in new file mode 100644 index 0000000..93c308f --- /dev/null +++ b/cogl/cogl-pango/Makefile.in @@ -0,0 +1,956 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@HAVE_INTROSPECTION_TRUE@am__append_1 = CoglPango-1.0.gir +@HAVE_INTROSPECTION_TRUE@am__append_2 = $(gir_DATA) $(typelib_DATA) +subdir = cogl-pango +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/build/autotools/as-compiler-flag.m4 \ + $(top_srcdir)/build/autotools/introspection.m4 \ + $(top_srcdir)/build/autotools/libtool.m4 \ + $(top_srcdir)/build/autotools/ltoptions.m4 \ + $(top_srcdir)/build/autotools/ltsugar.m4 \ + $(top_srcdir)/build/autotools/ltversion.m4 \ + $(top_srcdir)/build/autotools/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(cogl_pangoheaders_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/cogl-config.h \ + $(top_builddir)/cogl-mutter-config.h +CONFIG_CLEAN_FILES = mutter-cogl-pango-1.0.pc +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(mutterlibdir)" "$(DESTDIR)$(girdir)" \ + "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(typelibdir)" \ + "$(DESTDIR)$(cogl_pangoheadersdir)" +LTLIBRARIES = $(mutterlib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libmutter_cogl_pango_la_DEPENDENCIES = \ + $(top_builddir)/cogl/libmutter-cogl.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +am__objects_1 = +am__objects_2 = libmutter_cogl_pango_la-cogl-pango-display-list.lo \ + libmutter_cogl_pango_la-cogl-pango-fontmap.lo \ + libmutter_cogl_pango_la-cogl-pango-render.lo \ + libmutter_cogl_pango_la-cogl-pango-glyph-cache.lo \ + libmutter_cogl_pango_la-cogl-pango-pipeline-cache.lo \ + $(am__objects_1) +am__objects_3 = $(am__objects_1) +am_libmutter_cogl_pango_la_OBJECTS = $(am__objects_2) $(am__objects_1) \ + $(am__objects_3) +libmutter_cogl_pango_la_OBJECTS = \ + $(am_libmutter_cogl_pango_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libmutter_cogl_pango_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libmutter_cogl_pango_la_CFLAGS) $(CFLAGS) \ + $(libmutter_cogl_pango_la_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libmutter_cogl_pango_la_SOURCES) +DIST_SOURCES = $(libmutter_cogl_pango_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(gir_DATA) $(pkgconfig_DATA) $(typelib_DATA) +HEADERS = $(cogl_pangoheaders_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(srcdir)/mutter-cogl-pango-1.0.pc.in \ + $(top_srcdir)/build/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_REQ_VERSION = @CAIRO_REQ_VERSION@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COGL_1_MICRO_VERSION = @COGL_1_MICRO_VERSION@ +COGL_1_MINOR_VERSION = @COGL_1_MINOR_VERSION@ +COGL_1_VERSION = @COGL_1_VERSION@ +COGL_API_VERSION = @COGL_API_VERSION@ +COGL_API_VERSION_AM = @COGL_API_VERSION_AM@ +COGL_DEBUG_CFLAGS = @COGL_DEBUG_CFLAGS@ +COGL_DEFAULT_DRIVER = @COGL_DEFAULT_DRIVER@ +COGL_DEP_CFLAGS = @COGL_DEP_CFLAGS@ +COGL_DEP_GL_CFLAGS = @COGL_DEP_GL_CFLAGS@ +COGL_DEP_GL_LIBS = @COGL_DEP_GL_LIBS@ +COGL_DEP_LIBS = @COGL_DEP_LIBS@ +COGL_EGL_INCLUDES = @COGL_EGL_INCLUDES@ +COGL_EXTRA_CFLAGS = @COGL_EXTRA_CFLAGS@ +COGL_EXTRA_LDFLAGS = @COGL_EXTRA_LDFLAGS@ +COGL_GLES1_LIBNAME = @COGL_GLES1_LIBNAME@ +COGL_GLES2_LIBNAME = @COGL_GLES2_LIBNAME@ +COGL_GL_LIBNAME = @COGL_GL_LIBNAME@ +COGL_GST_DEP_CFLAGS = @COGL_GST_DEP_CFLAGS@ +COGL_GST_DEP_LIBS = @COGL_GST_DEP_LIBS@ +COGL_LT_AGE = @COGL_LT_AGE@ +COGL_LT_CURRENT = @COGL_LT_CURRENT@ +COGL_LT_RELEASE = @COGL_LT_RELEASE@ +COGL_LT_REVISION = @COGL_LT_REVISION@ +COGL_MAJOR_VERSION = @COGL_MAJOR_VERSION@ +COGL_MICRO_VERSION = @COGL_MICRO_VERSION@ +COGL_MINOR_VERSION = @COGL_MINOR_VERSION@ +COGL_PANGO_DEP_CFLAGS = @COGL_PANGO_DEP_CFLAGS@ +COGL_PANGO_DEP_LIBS = @COGL_PANGO_DEP_LIBS@ +COGL_PANGO_PKG_REQUIRES = @COGL_PANGO_PKG_REQUIRES@ +COGL_PKG_REQUIRES = @COGL_PKG_REQUIRES@ +COGL_RELEASE_STATUS = @COGL_RELEASE_STATUS@ +COGL_VERSION = @COGL_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMMY_CFLAGS = @DUMMY_CFLAGS@ +DUMMY_LIBS = @DUMMY_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDKPIXBUF_PREFIX = @GDKPIXBUF_PREFIX@ +GDK_PIXBUF_REQ_VERSION = @GDK_PIXBUF_REQ_VERSION@ +GI_REQ_VERSION = @GI_REQ_VERSION@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ_VERSION = @GLIB_REQ_VERSION@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +HAVE_GL = @HAVE_GL@ +HAVE_GLES1 = @HAVE_GLES1@ +HAVE_GLES2 = @HAVE_GLES2@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINTAINER_CFLAGS = @MAINTAINER_CFLAGS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGOCAIRO_REQ_VERSION = @PANGOCAIRO_REQ_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +UPROF_REQ_VERSION = @UPROF_REQ_VERSION@ +VERSION = @VERSION@ +WAYLAND_SERVER_CFLAGS = @WAYLAND_SERVER_CFLAGS@ +WAYLAND_SERVER_LIBS = @WAYLAND_SERVER_LIBS@ +WAYLAND_SERVER_REQ_VERSION = @WAYLAND_SERVER_REQ_VERSION@ +XCOMPOSITE_REQ_VERSION = @XCOMPOSITE_REQ_VERSION@ +XFIXES_REQ_VERSION = @XFIXES_REQ_VERSION@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = +CLEANFILES = $(am__append_2) +DISTCLEANFILES = $(pc_files) +EXTRA_DIST = cogl-pango.symbols +source_c = \ + cogl-pango-display-list.c \ + cogl-pango-fontmap.c \ + cogl-pango-render.c \ + cogl-pango-glyph-cache.c \ + cogl-pango-pipeline-cache.c \ + $(NULL) + +source_h = cogl-pango.h +source_h_priv = \ + cogl-pango-display-list.h \ + cogl-pango-private.h \ + cogl-pango-glyph-cache.h \ + cogl-pango-pipeline-cache.h \ + $(NULL) + +mutterlibdir = $(libdir)/mutter +mutterlib_LTLIBRARIES = libmutter-cogl-pango.la +libmutter_cogl_pango_la_SOURCES = $(source_c) $(source_h) $(source_h_priv) +libmutter_cogl_pango_la_CFLAGS = $(COGL_DEP_CFLAGS) $(COGL_PANGO_DEP_CFLAGS) $(COGL_EXTRA_CFLAGS) $(MAINTAINER_CFLAGS) +libmutter_cogl_pango_la_LIBADD = \ + $(top_builddir)/cogl/libmutter-cogl.la $(COGL_DEP_LIBS) \ + $(COGL_PANGO_DEP_LIBS) $(COGL_EXTRA_LDFLAGS) +libmutter_cogl_pango_la_LDFLAGS = \ + -export-dynamic \ + -rpath $(mutterlibdir) \ + -export-symbols-regex "^cogl_pango_.*" \ + -no-undefined \ + -avoid-version + +AM_CPPFLAGS = \ + -DCOGL_COMPILATION \ + -DG_LOG_DOMAIN=\"CoglPango\" \ + -I$(top_srcdir)/cogl \ + -I$(top_builddir)/cogl \ + -I$(top_srcdir)/cogl/winsys \ + -I$(top_srcdir) \ + -I$(top_builddir) + +cogl_base_includedir = $(includedir)/mutter +cogl_pangoheadersdir = $(cogl_base_includedir)/cogl/cogl-pango +cogl_pangoheaders_HEADERS = $(source_h) +pc_files = mutter-cogl-pango-1.0.pc +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = $(pc_files) +INTROSPECTION_GIRS = $(am__append_1) +@HAVE_INTROSPECTION_TRUE@INTROSPECTION_COMPILER_ARGS = --includedir=$(top_builddir)/cogl +@HAVE_INTROSPECTION_TRUE@CoglPango_1_0_gir_NAMESPACE = CoglPango +@HAVE_INTROSPECTION_TRUE@CoglPango_1_0_gir_VERSION = 1.0 +@HAVE_INTROSPECTION_TRUE@CoglPango_1_0_gir_LIBS = $(top_builddir)/cogl/libmutter-cogl.la libmutter-cogl-pango.la +@HAVE_INTROSPECTION_TRUE@CoglPango_1_0_gir_FILES = $(source_h) $(source_c) +@HAVE_INTROSPECTION_TRUE@CoglPango_1_0_gir_CFLAGS = $(AM_CPPFLAGS) $(COGL_DEP_CFLAGS) $(COGL_PANGO_DEP_CFLAGS) +@HAVE_INTROSPECTION_TRUE@CoglPango_1_0_gir_INCLUDES = Pango-1.0 PangoCairo-1.0 +@HAVE_INTROSPECTION_TRUE@CoglPango_1_0_gir_EXPORT_PACKAGES = mutter-cogl-pango-1.0 +@HAVE_INTROSPECTION_TRUE@CoglPango_1_0_gir_SCANNERFLAGS = \ +@HAVE_INTROSPECTION_TRUE@ --warn-all \ +@HAVE_INTROSPECTION_TRUE@ --identifier-prefix=CoglPango \ +@HAVE_INTROSPECTION_TRUE@ --symbol-prefix=cogl_pango \ +@HAVE_INTROSPECTION_TRUE@ --c-include='cogl-pango/cogl-pango.h' \ +@HAVE_INTROSPECTION_TRUE@ --include-uninstalled=$(top_builddir)/cogl/Cogl-1.0.gir + +@HAVE_INTROSPECTION_TRUE@girdir = $(mutterlibdir) +@HAVE_INTROSPECTION_TRUE@gir_DATA = $(INTROSPECTION_GIRS) +@HAVE_INTROSPECTION_TRUE@typelibdir = $(mutterlibdir) +@HAVE_INTROSPECTION_TRUE@typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign cogl-pango/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign cogl-pango/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +mutter-cogl-pango-1.0.pc: $(top_builddir)/config.status $(srcdir)/mutter-cogl-pango-1.0.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +install-mutterlibLTLIBRARIES: $(mutterlib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(mutterlib_LTLIBRARIES)'; test -n "$(mutterlibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(mutterlibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(mutterlibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(mutterlibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(mutterlibdir)"; \ + } + +uninstall-mutterlibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(mutterlib_LTLIBRARIES)'; test -n "$(mutterlibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(mutterlibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(mutterlibdir)/$$f"; \ + done + +clean-mutterlibLTLIBRARIES: + -test -z "$(mutterlib_LTLIBRARIES)" || rm -f $(mutterlib_LTLIBRARIES) + @list='$(mutterlib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libmutter-cogl-pango.la: $(libmutter_cogl_pango_la_OBJECTS) $(libmutter_cogl_pango_la_DEPENDENCIES) $(EXTRA_libmutter_cogl_pango_la_DEPENDENCIES) + $(AM_V_CCLD)$(libmutter_cogl_pango_la_LINK) -rpath $(mutterlibdir) $(libmutter_cogl_pango_la_OBJECTS) $(libmutter_cogl_pango_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmutter_cogl_pango_la-cogl-pango-display-list.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmutter_cogl_pango_la-cogl-pango-fontmap.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmutter_cogl_pango_la-cogl-pango-glyph-cache.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmutter_cogl_pango_la-cogl-pango-pipeline-cache.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmutter_cogl_pango_la-cogl-pango-render.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libmutter_cogl_pango_la-cogl-pango-display-list.lo: cogl-pango-display-list.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_pango_la_CFLAGS) $(CFLAGS) -MT libmutter_cogl_pango_la-cogl-pango-display-list.lo -MD -MP -MF $(DEPDIR)/libmutter_cogl_pango_la-cogl-pango-display-list.Tpo -c -o libmutter_cogl_pango_la-cogl-pango-display-list.lo `test -f 'cogl-pango-display-list.c' || echo '$(srcdir)/'`cogl-pango-display-list.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmutter_cogl_pango_la-cogl-pango-display-list.Tpo $(DEPDIR)/libmutter_cogl_pango_la-cogl-pango-display-list.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cogl-pango-display-list.c' object='libmutter_cogl_pango_la-cogl-pango-display-list.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_pango_la_CFLAGS) $(CFLAGS) -c -o libmutter_cogl_pango_la-cogl-pango-display-list.lo `test -f 'cogl-pango-display-list.c' || echo '$(srcdir)/'`cogl-pango-display-list.c + +libmutter_cogl_pango_la-cogl-pango-fontmap.lo: cogl-pango-fontmap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_pango_la_CFLAGS) $(CFLAGS) -MT libmutter_cogl_pango_la-cogl-pango-fontmap.lo -MD -MP -MF $(DEPDIR)/libmutter_cogl_pango_la-cogl-pango-fontmap.Tpo -c -o libmutter_cogl_pango_la-cogl-pango-fontmap.lo `test -f 'cogl-pango-fontmap.c' || echo '$(srcdir)/'`cogl-pango-fontmap.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmutter_cogl_pango_la-cogl-pango-fontmap.Tpo $(DEPDIR)/libmutter_cogl_pango_la-cogl-pango-fontmap.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cogl-pango-fontmap.c' object='libmutter_cogl_pango_la-cogl-pango-fontmap.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_pango_la_CFLAGS) $(CFLAGS) -c -o libmutter_cogl_pango_la-cogl-pango-fontmap.lo `test -f 'cogl-pango-fontmap.c' || echo '$(srcdir)/'`cogl-pango-fontmap.c + +libmutter_cogl_pango_la-cogl-pango-render.lo: cogl-pango-render.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_pango_la_CFLAGS) $(CFLAGS) -MT libmutter_cogl_pango_la-cogl-pango-render.lo -MD -MP -MF $(DEPDIR)/libmutter_cogl_pango_la-cogl-pango-render.Tpo -c -o libmutter_cogl_pango_la-cogl-pango-render.lo `test -f 'cogl-pango-render.c' || echo '$(srcdir)/'`cogl-pango-render.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmutter_cogl_pango_la-cogl-pango-render.Tpo $(DEPDIR)/libmutter_cogl_pango_la-cogl-pango-render.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cogl-pango-render.c' object='libmutter_cogl_pango_la-cogl-pango-render.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_pango_la_CFLAGS) $(CFLAGS) -c -o libmutter_cogl_pango_la-cogl-pango-render.lo `test -f 'cogl-pango-render.c' || echo '$(srcdir)/'`cogl-pango-render.c + +libmutter_cogl_pango_la-cogl-pango-glyph-cache.lo: cogl-pango-glyph-cache.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_pango_la_CFLAGS) $(CFLAGS) -MT libmutter_cogl_pango_la-cogl-pango-glyph-cache.lo -MD -MP -MF $(DEPDIR)/libmutter_cogl_pango_la-cogl-pango-glyph-cache.Tpo -c -o libmutter_cogl_pango_la-cogl-pango-glyph-cache.lo `test -f 'cogl-pango-glyph-cache.c' || echo '$(srcdir)/'`cogl-pango-glyph-cache.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmutter_cogl_pango_la-cogl-pango-glyph-cache.Tpo $(DEPDIR)/libmutter_cogl_pango_la-cogl-pango-glyph-cache.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cogl-pango-glyph-cache.c' object='libmutter_cogl_pango_la-cogl-pango-glyph-cache.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_pango_la_CFLAGS) $(CFLAGS) -c -o libmutter_cogl_pango_la-cogl-pango-glyph-cache.lo `test -f 'cogl-pango-glyph-cache.c' || echo '$(srcdir)/'`cogl-pango-glyph-cache.c + +libmutter_cogl_pango_la-cogl-pango-pipeline-cache.lo: cogl-pango-pipeline-cache.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_pango_la_CFLAGS) $(CFLAGS) -MT libmutter_cogl_pango_la-cogl-pango-pipeline-cache.lo -MD -MP -MF $(DEPDIR)/libmutter_cogl_pango_la-cogl-pango-pipeline-cache.Tpo -c -o libmutter_cogl_pango_la-cogl-pango-pipeline-cache.lo `test -f 'cogl-pango-pipeline-cache.c' || echo '$(srcdir)/'`cogl-pango-pipeline-cache.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmutter_cogl_pango_la-cogl-pango-pipeline-cache.Tpo $(DEPDIR)/libmutter_cogl_pango_la-cogl-pango-pipeline-cache.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cogl-pango-pipeline-cache.c' object='libmutter_cogl_pango_la-cogl-pango-pipeline-cache.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_pango_la_CFLAGS) $(CFLAGS) -c -o libmutter_cogl_pango_la-cogl-pango-pipeline-cache.lo `test -f 'cogl-pango-pipeline-cache.c' || echo '$(srcdir)/'`cogl-pango-pipeline-cache.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-girDATA: $(gir_DATA) + @$(NORMAL_INSTALL) + @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(girdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(girdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(girdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(girdir)" || exit $$?; \ + done + +uninstall-girDATA: + @$(NORMAL_UNINSTALL) + @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(girdir)'; $(am__uninstall_files_from_dir) +install-pkgconfigDATA: $(pkgconfig_DATA) + @$(NORMAL_INSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ + done + +uninstall-pkgconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) +install-typelibDATA: $(typelib_DATA) + @$(NORMAL_INSTALL) + @list='$(typelib_DATA)'; test -n "$(typelibdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(typelibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(typelibdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(typelibdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(typelibdir)" || exit $$?; \ + done + +uninstall-typelibDATA: + @$(NORMAL_UNINSTALL) + @list='$(typelib_DATA)'; test -n "$(typelibdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(typelibdir)'; $(am__uninstall_files_from_dir) +install-cogl_pangoheadersHEADERS: $(cogl_pangoheaders_HEADERS) + @$(NORMAL_INSTALL) + @list='$(cogl_pangoheaders_HEADERS)'; test -n "$(cogl_pangoheadersdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(cogl_pangoheadersdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(cogl_pangoheadersdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(cogl_pangoheadersdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(cogl_pangoheadersdir)" || exit $$?; \ + done + +uninstall-cogl_pangoheadersHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(cogl_pangoheaders_HEADERS)'; test -n "$(cogl_pangoheadersdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(cogl_pangoheadersdir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(mutterlibdir)" "$(DESTDIR)$(girdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(typelibdir)" "$(DESTDIR)$(cogl_pangoheadersdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-mutterlibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-cogl_pangoheadersHEADERS install-girDATA \ + install-mutterlibLTLIBRARIES install-pkgconfigDATA \ + install-typelibDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-cogl_pangoheadersHEADERS uninstall-girDATA \ + uninstall-mutterlibLTLIBRARIES uninstall-pkgconfigDATA \ + uninstall-typelibDATA + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-mutterlibLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am \ + install-cogl_pangoheadersHEADERS install-data install-data-am \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-girDATA install-html install-html-am install-info \ + install-info-am install-man install-mutterlibLTLIBRARIES \ + install-pdf install-pdf-am install-pkgconfigDATA install-ps \ + install-ps-am install-strip install-typelibDATA installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am \ + uninstall-cogl_pangoheadersHEADERS uninstall-girDATA \ + uninstall-mutterlibLTLIBRARIES uninstall-pkgconfigDATA \ + uninstall-typelibDATA + +.PRECIOUS: Makefile + + +-include $(INTROSPECTION_MAKEFILE) + +@HAVE_INTROSPECTION_TRUE@CoglPango-1.0.gir: libmutter-cogl-pango.la Makefile + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cogl/cogl-pango/cogl-pango-display-list.c b/cogl/cogl-pango/cogl-pango-display-list.c new file mode 100644 index 0000000..e8332b9 --- /dev/null +++ b/cogl/cogl-pango/cogl-pango-display-list.c @@ -0,0 +1,499 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include +#include + +#include "cogl-pango-display-list.h" +#include "cogl-pango-pipeline-cache.h" +#include "cogl/cogl-context-private.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 _CoglPangoDisplayListRectangle CoglPangoDisplayListRectangle; + +struct _CoglPangoDisplayList +{ + CoglBool color_override; + CoglColor color; + GSList *nodes; + GSList *last_node; + CoglPangoPipelineCache *pipeline_cache; +}; + +/* This matches the format expected by cogl_rectangles_with_texture_coords */ +struct _CoglPangoDisplayListRectangle +{ + float x_1, y_1, x_2, y_2; + float s_1, t_1, s_2, t_2; +}; + +struct _CoglPangoDisplayListNode +{ + CoglPangoDisplayListNodeType type; + + CoglBool color_override; + CoglColor color; + + CoglPipeline *pipeline; + + union + { + struct + { + /* The texture to render these coords from */ + CoglTexture *texture; + /* Array of rectangles in the format expected by + cogl_rectangles_with_texture_coords */ + GArray *rectangles; + /* A primitive representing those vertices */ + CoglPrimitive *primitive; + } texture; + + struct + { + float x_1, y_1; + float x_2, y_2; + } rectangle; + + struct + { + CoglPrimitive *primitive; + } trapezoid; + } d; +}; + +CoglPangoDisplayList * +_cogl_pango_display_list_new (CoglPangoPipelineCache *pipeline_cache) +{ + CoglPangoDisplayList *dl = g_slice_new0 (CoglPangoDisplayList); + + dl->pipeline_cache = pipeline_cache; + + return dl; +} + +static void +_cogl_pango_display_list_append_node (CoglPangoDisplayList *dl, + CoglPangoDisplayListNode *node) +{ + if (dl->last_node) + dl->last_node = dl->last_node->next = g_slist_prepend (NULL, node); + else + dl->last_node = dl->nodes = g_slist_prepend (NULL, node); +} + +void +_cogl_pango_display_list_set_color_override (CoglPangoDisplayList *dl, + const CoglColor *color) +{ + dl->color_override = TRUE; + dl->color = *color; +} + +void +_cogl_pango_display_list_remove_color_override (CoglPangoDisplayList *dl) +{ + dl->color_override = FALSE; +} + +void +_cogl_pango_display_list_add_texture (CoglPangoDisplayList *dl, + CoglTexture *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; + CoglPangoDisplayListRectangle *rectangle; + + /* Add to the last node if it is a texture node with the same + target texture */ + if (dl->last_node + && (node = dl->last_node->data)->type == COGL_PANGO_DISPLAY_LIST_TEXTURE + && node->d.texture.texture == texture + && (dl->color_override + ? (node->color_override && cogl_color_equal (&dl->color, &node->color)) + : !node->color_override)) + { + /* Get rid of the vertex buffer so that it will be recreated */ + if (node->d.texture.primitive != NULL) + { + cogl_object_unref (node->d.texture.primitive); + node->d.texture.primitive = NULL; + } + } + else + { + /* Otherwise create a new node */ + node = g_slice_new (CoglPangoDisplayListNode); + + node->type = COGL_PANGO_DISPLAY_LIST_TEXTURE; + node->color_override = dl->color_override; + node->color = dl->color; + node->pipeline = NULL; + node->d.texture.texture = cogl_object_ref (texture); + node->d.texture.rectangles + = g_array_new (FALSE, FALSE, sizeof (CoglPangoDisplayListRectangle)); + node->d.texture.primitive = NULL; + + _cogl_pango_display_list_append_node (dl, node); + } + + g_array_set_size (node->d.texture.rectangles, + node->d.texture.rectangles->len + 1); + rectangle = &g_array_index (node->d.texture.rectangles, + CoglPangoDisplayListRectangle, + node->d.texture.rectangles->len - 1); + rectangle->x_1 = x_1; + rectangle->y_1 = y_1; + rectangle->x_2 = x_2; + rectangle->y_2 = y_2; + rectangle->s_1 = tx_1; + rectangle->t_1 = ty_1; + rectangle->s_2 = tx_2; + rectangle->t_2 = ty_2; +} + +void +_cogl_pango_display_list_add_rectangle (CoglPangoDisplayList *dl, + float x_1, float y_1, + float x_2, float y_2) +{ + CoglPangoDisplayListNode *node = g_slice_new (CoglPangoDisplayListNode); + + node->type = COGL_PANGO_DISPLAY_LIST_RECTANGLE; + node->color_override = dl->color_override; + node->color = dl->color; + node->d.rectangle.x_1 = x_1; + node->d.rectangle.y_1 = y_1; + node->d.rectangle.x_2 = x_2; + node->d.rectangle.y_2 = y_2; + node->pipeline = NULL; + + _cogl_pango_display_list_append_node (dl, node); +} + +void +_cogl_pango_display_list_add_trapezoid (CoglPangoDisplayList *dl, + float y_1, + float x_11, + float x_21, + float y_2, + float x_12, + float x_22) +{ + CoglContext *ctx = dl->pipeline_cache->ctx; + CoglPangoDisplayListNode *node = g_slice_new (CoglPangoDisplayListNode); + CoglVertexP2 vertices[4] = { + { x_11, y_1 }, + { x_12, y_2 }, + { x_22, y_2 }, + { x_21, y_1 } + }; + + node->type = COGL_PANGO_DISPLAY_LIST_TRAPEZOID; + node->color_override = dl->color_override; + node->color = dl->color; + node->pipeline = NULL; + + node->d.trapezoid.primitive = + cogl_primitive_new_p2 (ctx, + COGL_VERTICES_MODE_TRIANGLE_FAN, + 4, + vertices); + + _cogl_pango_display_list_append_node (dl, node); +} + +static void +emit_rectangles_through_journal (CoglFramebuffer *fb, + CoglPipeline *pipeline, + CoglPangoDisplayListNode *node) +{ + const float *rectangles = (const float *)node->d.texture.rectangles->data; + + cogl_framebuffer_draw_textured_rectangles (fb, + pipeline, + rectangles, + node->d.texture.rectangles->len); +} + +static void +emit_vertex_buffer_geometry (CoglFramebuffer *fb, + CoglPipeline *pipeline, + CoglPangoDisplayListNode *node) +{ + CoglContext *ctx = fb->context; + + /* It's expensive to go through the Cogl journal for large runs + * of text in part because the journal transforms the quads in software + * to avoid changing the modelview matrix. So for larger runs of text + * we load the vertices into a VBO, and this has the added advantage + * that if the text doesn't change from frame to frame the VBO can + * be re-used avoiding the repeated cost of validating the data and + * mapping it into the GPU... */ + + if (node->d.texture.primitive == NULL) + { + CoglAttributeBuffer *buffer; + CoglVertexP2T2 *verts, *v; + int n_verts; + CoglBool allocated = FALSE; + CoglAttribute *attributes[2]; + CoglPrimitive *prim; + int i; + + n_verts = node->d.texture.rectangles->len * 4; + + buffer + = cogl_attribute_buffer_new_with_size (ctx, + n_verts * + sizeof (CoglVertexP2T2)); + + if ((verts = cogl_buffer_map (COGL_BUFFER (buffer), + COGL_BUFFER_ACCESS_WRITE, + COGL_BUFFER_MAP_HINT_DISCARD)) == NULL) + { + verts = g_new (CoglVertexP2T2, n_verts); + allocated = TRUE; + } + + v = verts; + + /* Copy the rectangles into the buffer and expand into four + vertices instead of just two */ + for (i = 0; i < node->d.texture.rectangles->len; i++) + { + const CoglPangoDisplayListRectangle *rectangle + = &g_array_index (node->d.texture.rectangles, + CoglPangoDisplayListRectangle, i); + + v->x = rectangle->x_1; + v->y = rectangle->y_1; + v->s = rectangle->s_1; + v->t = rectangle->t_1; + v++; + v->x = rectangle->x_1; + v->y = rectangle->y_2; + v->s = rectangle->s_1; + v->t = rectangle->t_2; + v++; + v->x = rectangle->x_2; + v->y = rectangle->y_2; + v->s = rectangle->s_2; + v->t = rectangle->t_2; + v++; + v->x = rectangle->x_2; + v->y = rectangle->y_1; + v->s = rectangle->s_2; + v->t = rectangle->t_1; + v++; + } + + if (allocated) + { + cogl_buffer_set_data (COGL_BUFFER (buffer), + 0, /* offset */ + verts, + sizeof (CoglVertexP2T2) * n_verts); + g_free (verts); + } + else + cogl_buffer_unmap (COGL_BUFFER (buffer)); + + attributes[0] = cogl_attribute_new (buffer, + "cogl_position_in", + sizeof (CoglVertexP2T2), + G_STRUCT_OFFSET (CoglVertexP2T2, x), + 2, /* n_components */ + COGL_ATTRIBUTE_TYPE_FLOAT); + attributes[1] = cogl_attribute_new (buffer, + "cogl_tex_coord0_in", + sizeof (CoglVertexP2T2), + G_STRUCT_OFFSET (CoglVertexP2T2, s), + 2, /* n_components */ + COGL_ATTRIBUTE_TYPE_FLOAT); + + prim = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, + n_verts, + attributes, + 2 /* n_attributes */); + +#ifdef CLUTTER_COGL_HAS_GL + if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_QUADS)) + cogl_primitive_set_mode (prim, GL_QUADS); + else +#endif + { + /* GLES doesn't support GL_QUADS so instead we use a VBO + with indexed vertices to generate GL_TRIANGLES from the + quads */ + + CoglIndices *indices = + cogl_get_rectangle_indices (ctx, node->d.texture.rectangles->len); + + cogl_primitive_set_indices (prim, indices, + node->d.texture.rectangles->len * 6); + } + + node->d.texture.primitive = prim; + + cogl_object_unref (buffer); + cogl_object_unref (attributes[0]); + cogl_object_unref (attributes[1]); + } + + cogl_primitive_draw (node->d.texture.primitive, + fb, + pipeline); +} + +static void +_cogl_framebuffer_draw_display_list_texture (CoglFramebuffer *fb, + CoglPipeline *pipeline, + CoglPangoDisplayListNode *node) +{ + /* For small runs of text like icon labels, we can get better performance + * going through the Cogl journal since text may then be batched together + * with other geometry. */ + /* FIXME: 25 is a number I plucked out of thin air; it would be good + * to determine this empirically! */ + if (node->d.texture.rectangles->len < 25) + emit_rectangles_through_journal (fb, pipeline, node); + else + emit_vertex_buffer_geometry (fb, pipeline, node); +} + +void +_cogl_pango_display_list_render (CoglFramebuffer *fb, + CoglPangoDisplayList *dl, + const CoglColor *color) +{ + GSList *l; + + for (l = dl->nodes; l; l = l->next) + { + CoglPangoDisplayListNode *node = l->data; + CoglColor draw_color; + + if (node->pipeline == NULL) + { + if (node->type == COGL_PANGO_DISPLAY_LIST_TEXTURE) + node->pipeline = + _cogl_pango_pipeline_cache_get (dl->pipeline_cache, + node->d.texture.texture); + else + node->pipeline = + _cogl_pango_pipeline_cache_get (dl->pipeline_cache, + NULL); + } + + if (node->color_override) + /* Use the override color but preserve the alpha from the + draw color */ + cogl_color_init_from_4ub (&draw_color, + cogl_color_get_red_byte (&node->color), + cogl_color_get_green_byte (&node->color), + cogl_color_get_blue_byte (&node->color), + cogl_color_get_alpha_byte (color)); + else + draw_color = *color; + cogl_color_premultiply (&draw_color); + + cogl_pipeline_set_color (node->pipeline, &draw_color); + + switch (node->type) + { + case COGL_PANGO_DISPLAY_LIST_TEXTURE: + _cogl_framebuffer_draw_display_list_texture (fb, node->pipeline, node); + break; + + case COGL_PANGO_DISPLAY_LIST_RECTANGLE: + cogl_framebuffer_draw_rectangle (fb, + node->pipeline, + 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: + cogl_framebuffer_draw_primitive (fb, node->pipeline, + node->d.trapezoid.primitive); + 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.rectangles, TRUE); + if (node->d.texture.texture != NULL) + cogl_object_unref (node->d.texture.texture); + if (node->d.texture.primitive != NULL) + cogl_object_unref (node->d.texture.primitive); + } + else if (node->type == COGL_PANGO_DISPLAY_LIST_TRAPEZOID) + cogl_object_unref (node->d.trapezoid.primitive); + + if (node->pipeline) + cogl_object_unref (node->pipeline); + + g_slice_free (CoglPangoDisplayListNode, node); +} + +void +_cogl_pango_display_list_clear (CoglPangoDisplayList *dl) +{ + g_slist_foreach (dl->nodes, (GFunc) _cogl_pango_display_list_node_free, NULL); + g_slist_free (dl->nodes); + dl->nodes = NULL; + dl->last_node = NULL; +} + +void +_cogl_pango_display_list_free (CoglPangoDisplayList *dl) +{ + _cogl_pango_display_list_clear (dl); + g_slice_free (CoglPangoDisplayList, dl); +} diff --git a/cogl/cogl-pango/cogl-pango-display-list.h b/cogl/cogl-pango/cogl-pango-display-list.h new file mode 100644 index 0000000..5dbc074 --- /dev/null +++ b/cogl/cogl-pango/cogl-pango-display-list.h @@ -0,0 +1,84 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __COGL_PANGO_DISPLAY_LIST_H__ +#define __COGL_PANGO_DISPLAY_LIST_H__ + +#include +#include "cogl-pango-pipeline-cache.h" + +COGL_BEGIN_DECLS + +typedef struct _CoglPangoDisplayList CoglPangoDisplayList; + +CoglPangoDisplayList * +_cogl_pango_display_list_new (CoglPangoPipelineCache *); + +void +_cogl_pango_display_list_set_color_override (CoglPangoDisplayList *dl, + const CoglColor *color); + +void +_cogl_pango_display_list_remove_color_override (CoglPangoDisplayList *dl); + +void +_cogl_pango_display_list_add_texture (CoglPangoDisplayList *dl, + CoglTexture *texture, + float x_1, float y_1, + float x_2, float y_2, + float tx_1, float ty_1, + float tx_2, float ty_2); + +void +_cogl_pango_display_list_add_rectangle (CoglPangoDisplayList *dl, + float x_1, float y_1, + float x_2, float y_2); + +void +_cogl_pango_display_list_add_trapezoid (CoglPangoDisplayList *dl, + float y_1, + float x_11, + float x_21, + float y_2, + float x_12, + float x_22); + +void +_cogl_pango_display_list_render (CoglFramebuffer *framebuffer, + CoglPangoDisplayList *dl, + const CoglColor *color); + +void +_cogl_pango_display_list_clear (CoglPangoDisplayList *dl); + +void +_cogl_pango_display_list_free (CoglPangoDisplayList *dl); + +COGL_END_DECLS + +#endif /* __COGL_PANGO_DISPLAY_LIST_H__ */ diff --git a/cogl/cogl-pango/cogl-pango-fontmap.c b/cogl/cogl-pango/cogl-pango-fontmap.c new file mode 100644 index 0000000..145f3b9 --- /dev/null +++ b/cogl/cogl-pango/cogl-pango-fontmap.c @@ -0,0 +1,184 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008 OpenedHand + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * SECTION:cogl-pango + * @short_description: COGL-based text rendering using Pango + * + * FIXME + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +/* This is needed to get the Pango headers to export stuff needed to + subclass */ +#ifndef PANGO_ENABLE_BACKEND +#define PANGO_ENABLE_BACKEND 1 +#endif + +#include +#include +#include + +#include "cogl-pango.h" +#include "cogl-pango-private.h" +#include "cogl-util.h" +#include "cogl/cogl-context-private.h" + +static GQuark cogl_pango_font_map_get_priv_key (void) G_GNUC_CONST; + +typedef struct _CoglPangoFontMapPriv +{ + CoglContext *ctx; + PangoRenderer *renderer; +} CoglPangoFontMapPriv; + +static void +free_priv (gpointer data) +{ + CoglPangoFontMapPriv *priv = data; + + cogl_object_unref (priv->ctx); + cogl_object_unref (priv->renderer); + + g_free (priv); +} + +PangoFontMap * +cogl_pango_font_map_new (void) +{ + PangoFontMap *fm = pango_cairo_font_map_new (); + CoglPangoFontMapPriv *priv = g_new0 (CoglPangoFontMapPriv, 1); + + _COGL_GET_CONTEXT (context, NULL); + + priv->ctx = cogl_object_ref (context); + + /* XXX: The public pango api doesn't let us sub-class + * PangoCairoFontMap so we attach our own private data using qdata + * for now. */ + g_object_set_qdata_full (G_OBJECT (fm), + cogl_pango_font_map_get_priv_key (), + priv, + free_priv); + + return fm; +} + +PangoContext * +cogl_pango_font_map_create_context (CoglPangoFontMap *fm) +{ + _COGL_RETURN_VAL_IF_FAIL (COGL_PANGO_IS_FONT_MAP (fm), NULL); + +#if PANGO_VERSION_CHECK (1, 22, 0) + /* We can just directly use the pango context from the Cairo font + map */ + return pango_font_map_create_context (PANGO_FONT_MAP (fm)); +#else + return pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fm)); +#endif +} + +static CoglPangoFontMapPriv * +_cogl_pango_font_map_get_priv (CoglPangoFontMap *fm) +{ + return g_object_get_qdata (G_OBJECT (fm), + cogl_pango_font_map_get_priv_key ()); +} + +PangoRenderer * +_cogl_pango_font_map_get_renderer (CoglPangoFontMap *fm) +{ + CoglPangoFontMapPriv *priv = _cogl_pango_font_map_get_priv (fm); + if (G_UNLIKELY (!priv->renderer)) + priv->renderer = _cogl_pango_renderer_new (priv->ctx); + return priv->renderer; +} + +PangoRenderer * +cogl_pango_font_map_get_renderer (CoglPangoFontMap *fm) +{ + return _cogl_pango_font_map_get_renderer (fm); +} + +CoglContext * +_cogl_pango_font_map_get_cogl_context (CoglPangoFontMap *fm) +{ + CoglPangoFontMapPriv *priv = _cogl_pango_font_map_get_priv (fm); + return priv->ctx; +} + +void +cogl_pango_font_map_set_resolution (CoglPangoFontMap *font_map, + double dpi) +{ + _COGL_RETURN_IF_FAIL (COGL_PANGO_IS_FONT_MAP (font_map)); + + pango_cairo_font_map_set_resolution (PANGO_CAIRO_FONT_MAP (font_map), dpi); +} + +void +cogl_pango_font_map_clear_glyph_cache (CoglPangoFontMap *fm) +{ + PangoRenderer *renderer = _cogl_pango_font_map_get_renderer (fm); + + _cogl_pango_renderer_clear_glyph_cache (COGL_PANGO_RENDERER (renderer)); +} + +void +cogl_pango_font_map_set_use_mipmapping (CoglPangoFontMap *fm, + CoglBool value) +{ + PangoRenderer *renderer = _cogl_pango_font_map_get_renderer (fm); + + _cogl_pango_renderer_set_use_mipmapping (COGL_PANGO_RENDERER (renderer), + value); +} + +CoglBool +cogl_pango_font_map_get_use_mipmapping (CoglPangoFontMap *fm) +{ + PangoRenderer *renderer = _cogl_pango_font_map_get_renderer (fm); + + return + _cogl_pango_renderer_get_use_mipmapping (COGL_PANGO_RENDERER (renderer)); +} + +static GQuark +cogl_pango_font_map_get_priv_key (void) +{ + static GQuark priv_key = 0; + + if (G_UNLIKELY (priv_key == 0)) + priv_key = g_quark_from_static_string ("CoglPangoFontMap"); + + return priv_key; +} diff --git a/cogl/cogl-pango/cogl-pango-glyph-cache.c b/cogl/cogl-pango/cogl-pango-glyph-cache.c new file mode 100644 index 0000000..038db7d --- /dev/null +++ b/cogl/cogl-pango/cogl-pango-glyph-cache.c @@ -0,0 +1,433 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008 OpenedHand + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include + +#include "cogl-pango-glyph-cache.h" +#include "cogl-pango-private.h" +#include "cogl/cogl-atlas.h" +#include "cogl/cogl-atlas-texture-private.h" + +typedef struct _CoglPangoGlyphCacheKey CoglPangoGlyphCacheKey; + +struct _CoglPangoGlyphCache +{ + CoglContext *ctx; + + /* Hash table to quickly check whether a particular glyph in a + particular font is already cached */ + GHashTable *hash_table; + + /* List of CoglAtlases */ + GSList *atlases; + + /* List of callbacks to invoke when an atlas is reorganized */ + GHookList reorganize_callbacks; + + /* TRUE if we've ever stored a texture in the global atlas. This is + used to make sure we only register one callback to listen for + global atlas reorganizations */ + CoglBool using_global_atlas; + + /* True if some of the glyphs are dirty. This is used as an + optimization in _cogl_pango_glyph_cache_set_dirty_glyphs to avoid + iterating the hash table if we know none of them are dirty */ + CoglBool has_dirty_glyphs; + + /* Whether mipmapping is being used for this cache. This only + affects whether we decide to put the glyph in the global atlas */ + CoglBool use_mipmapping; +}; + +struct _CoglPangoGlyphCacheKey +{ + PangoFont *font; + PangoGlyph glyph; +}; + +static void +cogl_pango_glyph_cache_value_free (CoglPangoGlyphCacheValue *value) +{ + if (value->texture) + cogl_object_unref (value->texture); + g_slice_free (CoglPangoGlyphCacheValue, value); +} + +static void +cogl_pango_glyph_cache_key_free (CoglPangoGlyphCacheKey *key) +{ + g_object_unref (key->font); + g_slice_free (CoglPangoGlyphCacheKey, key); +} + +static unsigned int +cogl_pango_glyph_cache_hash_func (const void *key) +{ + const CoglPangoGlyphCacheKey *cache_key + = (const CoglPangoGlyphCacheKey *) key; + + /* Generate a number affected by both the font and the glyph + number. We can safely directly compare the pointers because the + key holds a reference to the font so it is not possible that a + different font will have the same memory address */ + return GPOINTER_TO_UINT (cache_key->font) ^ cache_key->glyph; +} + +static CoglBool +cogl_pango_glyph_cache_equal_func (const void *a, const void *b) +{ + const CoglPangoGlyphCacheKey *key_a + = (const CoglPangoGlyphCacheKey *) a; + const CoglPangoGlyphCacheKey *key_b + = (const CoglPangoGlyphCacheKey *) b; + + /* We can safely directly compare the pointers for the fonts because + the key holds a reference to the font so it is not possible that + a different font will have the same memory address */ + return key_a->font == key_b->font + && key_a->glyph == key_b->glyph; +} + +CoglPangoGlyphCache * +cogl_pango_glyph_cache_new (CoglContext *ctx, + CoglBool use_mipmapping) +{ + CoglPangoGlyphCache *cache; + + cache = g_malloc (sizeof (CoglPangoGlyphCache)); + + /* Note: as a rule we don't take references to a CoglContext + * internally since */ + cache->ctx = ctx; + + cache->hash_table = g_hash_table_new_full + (cogl_pango_glyph_cache_hash_func, + cogl_pango_glyph_cache_equal_func, + (GDestroyNotify) cogl_pango_glyph_cache_key_free, + (GDestroyNotify) cogl_pango_glyph_cache_value_free); + + cache->atlases = NULL; + g_hook_list_init (&cache->reorganize_callbacks, sizeof (GHook)); + + cache->has_dirty_glyphs = FALSE; + + cache->using_global_atlas = FALSE; + + cache->use_mipmapping = use_mipmapping; + + return cache; +} + +static void +cogl_pango_glyph_cache_reorganize_cb (void *user_data) +{ + CoglPangoGlyphCache *cache = user_data; + + g_hook_list_invoke (&cache->reorganize_callbacks, FALSE); +} + +void +cogl_pango_glyph_cache_clear (CoglPangoGlyphCache *cache) +{ + g_slist_foreach (cache->atlases, (GFunc) cogl_object_unref, NULL); + g_slist_free (cache->atlases); + cache->atlases = NULL; + cache->has_dirty_glyphs = FALSE; + + g_hash_table_remove_all (cache->hash_table); +} + +void +cogl_pango_glyph_cache_free (CoglPangoGlyphCache *cache) +{ + if (cache->using_global_atlas) + { + _cogl_atlas_texture_remove_reorganize_callback ( + cache->ctx, + cogl_pango_glyph_cache_reorganize_cb, cache); + } + + cogl_pango_glyph_cache_clear (cache); + + g_hash_table_unref (cache->hash_table); + + g_hook_list_clear (&cache->reorganize_callbacks); + + g_free (cache); +} + +static void +cogl_pango_glyph_cache_update_position_cb (void *user_data, + CoglTexture *new_texture, + const CoglRectangleMapEntry *rect) +{ + CoglPangoGlyphCacheValue *value = user_data; + float tex_width, tex_height; + + if (value->texture) + cogl_object_unref (value->texture); + value->texture = cogl_object_ref (new_texture); + + tex_width = cogl_texture_get_width (new_texture); + tex_height = cogl_texture_get_height (new_texture); + + value->tx1 = rect->x / tex_width; + value->ty1 = rect->y / tex_height; + value->tx2 = (rect->x + value->draw_width) / tex_width; + value->ty2 = (rect->y + value->draw_height) / tex_height; + + value->tx_pixel = rect->x; + value->ty_pixel = rect->y; + + /* The glyph has changed position so it will need to be redrawn */ + value->dirty = TRUE; +} + +static CoglBool +cogl_pango_glyph_cache_add_to_global_atlas (CoglPangoGlyphCache *cache, + PangoFont *font, + PangoGlyph glyph, + CoglPangoGlyphCacheValue *value) +{ + CoglAtlasTexture *texture; + CoglError *ignore_error = NULL; + + if (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_SHARED_ATLAS)) + return FALSE; + + /* If the cache is using mipmapping then we can't use the global + atlas because it would just get migrated back out */ + if (cache->use_mipmapping) + return FALSE; + + texture = cogl_atlas_texture_new_with_size (cache->ctx, + value->draw_width, + value->draw_height); + if (!cogl_texture_allocate (COGL_TEXTURE (texture), &ignore_error)) + { + cogl_error_free (ignore_error); + return FALSE; + } + + value->texture = COGL_TEXTURE (texture); + value->tx1 = 0; + value->ty1 = 0; + value->tx2 = 1; + value->ty2 = 1; + value->tx_pixel = 0; + value->ty_pixel = 0; + + /* The first time we store a texture in the global atlas we'll + register for notifications when the global atlas is reorganized + so we can forward the notification on as a glyph + reorganization */ + if (!cache->using_global_atlas) + { + _cogl_atlas_texture_add_reorganize_callback + (cache->ctx, + cogl_pango_glyph_cache_reorganize_cb, cache); + cache->using_global_atlas = TRUE; + } + + return TRUE; +} + +static CoglBool +cogl_pango_glyph_cache_add_to_local_atlas (CoglPangoGlyphCache *cache, + PangoFont *font, + PangoGlyph glyph, + CoglPangoGlyphCacheValue *value) +{ + CoglAtlas *atlas = NULL; + GSList *l; + + /* Look for an atlas that can reserve the space */ + for (l = cache->atlases; l; l = l->next) + if (_cogl_atlas_reserve_space (l->data, + value->draw_width + 1, + value->draw_height + 1, + value)) + { + atlas = l->data; + break; + } + + /* If we couldn't find one then start a new atlas */ + if (atlas == NULL) + { + atlas = _cogl_atlas_new (COGL_PIXEL_FORMAT_A_8, + COGL_ATLAS_CLEAR_TEXTURE | + COGL_ATLAS_DISABLE_MIGRATION, + cogl_pango_glyph_cache_update_position_cb); + COGL_NOTE (ATLAS, "Created new atlas for glyphs: %p", atlas); + /* If we still can't reserve space then something has gone + seriously wrong so we'll just give up */ + if (!_cogl_atlas_reserve_space (atlas, + value->draw_width + 1, + value->draw_height + 1, + value)) + { + cogl_object_unref (atlas); + return FALSE; + } + + _cogl_atlas_add_reorganize_callback + (atlas, cogl_pango_glyph_cache_reorganize_cb, NULL, cache); + + cache->atlases = g_slist_prepend (cache->atlases, atlas); + } + + return TRUE; +} + +CoglPangoGlyphCacheValue * +cogl_pango_glyph_cache_lookup (CoglPangoGlyphCache *cache, + CoglBool create, + PangoFont *font, + PangoGlyph glyph) +{ + CoglPangoGlyphCacheKey lookup_key; + CoglPangoGlyphCacheValue *value; + + lookup_key.font = font; + lookup_key.glyph = glyph; + + value = g_hash_table_lookup (cache->hash_table, &lookup_key); + + if (create && value == NULL) + { + CoglPangoGlyphCacheKey *key; + PangoRectangle ink_rect; + + value = g_slice_new (CoglPangoGlyphCacheValue); + value->texture = NULL; + + pango_font_get_glyph_extents (font, glyph, &ink_rect, NULL); + pango_extents_to_pixels (&ink_rect, NULL); + + value->draw_x = ink_rect.x; + value->draw_y = ink_rect.y; + value->draw_width = ink_rect.width; + value->draw_height = ink_rect.height; + + /* If the glyph is zero-sized then we don't need to reserve any + space for it and we can just avoid painting anything */ + if (ink_rect.width < 1 || ink_rect.height < 1) + value->dirty = FALSE; + else + { + /* Try adding the glyph to the global atlas... */ + if (!cogl_pango_glyph_cache_add_to_global_atlas (cache, + font, + glyph, + value) && + /* If it fails try the local atlas */ + !cogl_pango_glyph_cache_add_to_local_atlas (cache, + font, + glyph, + value)) + { + cogl_pango_glyph_cache_value_free (value); + return NULL; + } + + value->dirty = TRUE; + cache->has_dirty_glyphs = TRUE; + } + + key = g_slice_new (CoglPangoGlyphCacheKey); + key->font = g_object_ref (font); + key->glyph = glyph; + + g_hash_table_insert (cache->hash_table, key, value); + } + + return value; +} + +static void +_cogl_pango_glyph_cache_set_dirty_glyphs_cb (void *key_ptr, + void *value_ptr, + void *user_data) +{ + CoglPangoGlyphCacheKey *key = key_ptr; + CoglPangoGlyphCacheValue *value = value_ptr; + CoglPangoGlyphCacheDirtyFunc func = user_data; + + if (value->dirty) + { + func (key->font, key->glyph, value); + + value->dirty = FALSE; + } +} + +void +_cogl_pango_glyph_cache_set_dirty_glyphs (CoglPangoGlyphCache *cache, + CoglPangoGlyphCacheDirtyFunc func) +{ + /* If we know that there are no dirty glyphs then we can shortcut + out early */ + if (!cache->has_dirty_glyphs) + return; + + g_hash_table_foreach (cache->hash_table, + _cogl_pango_glyph_cache_set_dirty_glyphs_cb, + func); + + cache->has_dirty_glyphs = FALSE; +} + +void +_cogl_pango_glyph_cache_add_reorganize_callback (CoglPangoGlyphCache *cache, + GHookFunc func, + void *user_data) +{ + GHook *hook = g_hook_alloc (&cache->reorganize_callbacks); + hook->func = func; + hook->data = user_data; + g_hook_prepend (&cache->reorganize_callbacks, hook); +} + +void +_cogl_pango_glyph_cache_remove_reorganize_callback (CoglPangoGlyphCache *cache, + GHookFunc func, + void *user_data) +{ + GHook *hook = g_hook_find_func_data (&cache->reorganize_callbacks, + FALSE, + func, + user_data); + + if (hook) + g_hook_destroy_link (&cache->reorganize_callbacks, hook); +} diff --git a/cogl/cogl-pango/cogl-pango-glyph-cache.h b/cogl/cogl-pango/cogl-pango-glyph-cache.h new file mode 100644 index 0000000..ca33203 --- /dev/null +++ b/cogl/cogl-pango/cogl-pango-glyph-cache.h @@ -0,0 +1,100 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008 OpenedHand + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __COGL_PANGO_GLYPH_CACHE_H__ +#define __COGL_PANGO_GLYPH_CACHE_H__ + +#include +#include + +#include "cogl/cogl-texture.h" + +COGL_BEGIN_DECLS + +typedef struct _CoglPangoGlyphCache CoglPangoGlyphCache; +typedef struct _CoglPangoGlyphCacheValue CoglPangoGlyphCacheValue; + +struct _CoglPangoGlyphCacheValue +{ + CoglTexture *texture; + + float tx1; + float ty1; + float tx2; + float ty2; + + int tx_pixel; + int ty_pixel; + + int draw_x; + int draw_y; + int draw_width; + int draw_height; + + /* This will be set to TRUE when the glyph atlas is reorganized + which means the glyph will need to be redrawn */ + CoglBool dirty; +}; + +typedef void (* CoglPangoGlyphCacheDirtyFunc) (PangoFont *font, + PangoGlyph glyph, + CoglPangoGlyphCacheValue *value); + +CoglPangoGlyphCache * +cogl_pango_glyph_cache_new (CoglContext *ctx, + CoglBool use_mipmapping); + +void +cogl_pango_glyph_cache_free (CoglPangoGlyphCache *cache); + +CoglPangoGlyphCacheValue * +cogl_pango_glyph_cache_lookup (CoglPangoGlyphCache *cache, + CoglBool create, + PangoFont *font, + PangoGlyph glyph); + +void +cogl_pango_glyph_cache_clear (CoglPangoGlyphCache *cache); + +void +_cogl_pango_glyph_cache_add_reorganize_callback (CoglPangoGlyphCache *cache, + GHookFunc func, + void *user_data); + +void +_cogl_pango_glyph_cache_remove_reorganize_callback (CoglPangoGlyphCache *cache, + GHookFunc func, + void *user_data); + +void +_cogl_pango_glyph_cache_set_dirty_glyphs (CoglPangoGlyphCache *cache, + CoglPangoGlyphCacheDirtyFunc func); + +COGL_END_DECLS + +#endif /* __COGL_PANGO_GLYPH_CACHE_H__ */ diff --git a/cogl/cogl-pango/cogl-pango-pipeline-cache.c b/cogl/cogl-pango/cogl-pango-pipeline-cache.c new file mode 100644 index 0000000..b084487 --- /dev/null +++ b/cogl/cogl-pango/cogl-pango-pipeline-cache.c @@ -0,0 +1,242 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Neil Roberts + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include +#include "cogl-pango-pipeline-cache.h" + +#include "cogl/cogl-context-private.h" +#include "cogl/cogl-texture-private.h" + +typedef struct _CoglPangoPipelineCacheEntry CoglPangoPipelineCacheEntry; + +struct _CoglPangoPipelineCacheEntry +{ + /* This will take a reference or it can be NULL to represent the + pipeline used to render colors */ + CoglTexture *texture; + + /* This will only take a weak reference */ + CoglPipeline *pipeline; +}; + +static void +_cogl_pango_pipeline_cache_key_destroy (void *data) +{ + if (data) + cogl_object_unref (data); +} + +static void +_cogl_pango_pipeline_cache_value_destroy (void *data) +{ + CoglPangoPipelineCacheEntry *cache_entry = data; + + if (cache_entry->texture) + cogl_object_unref (cache_entry->texture); + + /* We don't need to unref the pipeline because it only takes a weak + reference */ + + g_slice_free (CoglPangoPipelineCacheEntry, cache_entry); +} + +CoglPangoPipelineCache * +_cogl_pango_pipeline_cache_new (CoglContext *ctx, + CoglBool use_mipmapping) +{ + CoglPangoPipelineCache *cache = g_new (CoglPangoPipelineCache, 1); + + cache->ctx = cogl_object_ref (ctx); + + /* The key is the pipeline pointer. A reference is taken when the + pipeline is used as a key so we should unref it again in the + destroy function */ + cache->hash_table = + g_hash_table_new_full (g_direct_hash, + g_direct_equal, + _cogl_pango_pipeline_cache_key_destroy, + _cogl_pango_pipeline_cache_value_destroy); + + cache->base_texture_rgba_pipeline = NULL; + cache->base_texture_alpha_pipeline = NULL; + + cache->use_mipmapping = use_mipmapping; + + return cache; +} + +static CoglPipeline * +get_base_texture_rgba_pipeline (CoglPangoPipelineCache *cache) +{ + if (cache->base_texture_rgba_pipeline == NULL) + { + CoglPipeline *pipeline; + + pipeline = cache->base_texture_rgba_pipeline = + cogl_pipeline_new (cache->ctx); + + cogl_pipeline_set_layer_wrap_mode (pipeline, 0, + COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); + + if (cache->use_mipmapping) + cogl_pipeline_set_layer_filters + (pipeline, 0, + COGL_PIPELINE_FILTER_LINEAR_MIPMAP_LINEAR, + COGL_PIPELINE_FILTER_LINEAR); + } + + return cache->base_texture_rgba_pipeline; +} + +static CoglPipeline * +get_base_texture_alpha_pipeline (CoglPangoPipelineCache *cache) +{ + if (cache->base_texture_alpha_pipeline == NULL) + { + CoglPipeline *pipeline; + + pipeline = cogl_pipeline_copy (get_base_texture_rgba_pipeline (cache)); + cache->base_texture_alpha_pipeline = pipeline; + + /* The default combine mode of materials is to modulate (A x B) + * the texture RGBA channels with the RGBA channels of the + * previous layer (which in our case is just the font color) + * + * Since the RGB for an alpha texture is defined as 0, this gives us: + * + * result.rgb = color.rgb * 0 + * result.a = color.a * texture.a + * + * What we want is premultiplied rgba values: + * + * result.rgba = color.rgb * texture.a + * result.a = color.a * texture.a + */ + cogl_pipeline_set_layer_combine (pipeline, 0, /* layer */ + "RGBA = MODULATE (PREVIOUS, TEXTURE[A])", + NULL); + } + + return cache->base_texture_alpha_pipeline; +} + +typedef struct +{ + CoglPangoPipelineCache *cache; + CoglTexture *texture; +} PipelineDestroyNotifyData; + +static void +pipeline_destroy_notify_cb (void *user_data) +{ + PipelineDestroyNotifyData *data = user_data; + + g_hash_table_remove (data->cache->hash_table, data->texture); + g_slice_free (PipelineDestroyNotifyData, data); +} + +CoglPipeline * +_cogl_pango_pipeline_cache_get (CoglPangoPipelineCache *cache, + CoglTexture *texture) +{ + CoglPangoPipelineCacheEntry *entry; + PipelineDestroyNotifyData *destroy_data; + static CoglUserDataKey pipeline_destroy_notify_key; + + /* Look for an existing entry */ + entry = g_hash_table_lookup (cache->hash_table, texture); + + if (entry) + return cogl_object_ref (entry->pipeline); + + /* No existing pipeline was found so let's create another */ + entry = g_slice_new (CoglPangoPipelineCacheEntry); + + if (texture) + { + CoglPipeline *base; + + entry->texture = cogl_object_ref (texture); + + if (_cogl_texture_get_format (entry->texture) == COGL_PIXEL_FORMAT_A_8) + base = get_base_texture_alpha_pipeline (cache); + else + base = get_base_texture_rgba_pipeline (cache); + + entry->pipeline = cogl_pipeline_copy (base); + + cogl_pipeline_set_layer_texture (entry->pipeline, 0 /* layer */, texture); + } + else + { + entry->texture = NULL; + entry->pipeline = cogl_pipeline_new (cache->ctx); + } + + /* Add a weak reference to the pipeline so we can remove it from the + hash table when it is destroyed */ + destroy_data = g_slice_new (PipelineDestroyNotifyData); + destroy_data->cache = cache; + destroy_data->texture = texture; + cogl_object_set_user_data (COGL_OBJECT (entry->pipeline), + &pipeline_destroy_notify_key, + destroy_data, + pipeline_destroy_notify_cb); + + g_hash_table_insert (cache->hash_table, + texture ? cogl_object_ref (texture) : NULL, + entry); + + /* This doesn't take a reference on the pipeline so that it will use + the newly created reference */ + return entry->pipeline; +} + +void +_cogl_pango_pipeline_cache_free (CoglPangoPipelineCache *cache) +{ + if (cache->base_texture_rgba_pipeline) + cogl_object_unref (cache->base_texture_rgba_pipeline); + if (cache->base_texture_alpha_pipeline) + cogl_object_unref (cache->base_texture_alpha_pipeline); + + g_hash_table_destroy (cache->hash_table); + + cogl_object_unref (cache->ctx); + + g_free (cache); +} diff --git a/cogl/cogl-pango/cogl-pango-pipeline-cache.h b/cogl/cogl-pango/cogl-pango-pipeline-cache.h new file mode 100644 index 0000000..c8abe2c --- /dev/null +++ b/cogl/cogl-pango/cogl-pango-pipeline-cache.h @@ -0,0 +1,72 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Neil Roberts + */ + +#ifndef __COGL_PANGO_PIPELINE_CACHE_H__ +#define __COGL_PANGO_PIPELINE_CACHE_H__ + +#include + +#include "cogl/cogl-context-private.h" + +COGL_BEGIN_DECLS + +typedef struct _CoglPangoPipelineCache +{ + CoglContext *ctx; + + GHashTable *hash_table; + + CoglPipeline *base_texture_alpha_pipeline; + CoglPipeline *base_texture_rgba_pipeline; + + CoglBool use_mipmapping; +} CoglPangoPipelineCache; + + +CoglPangoPipelineCache * +_cogl_pango_pipeline_cache_new (CoglContext *ctx, + CoglBool use_mipmapping); + +/* Returns a pipeline that can be used to render glyphs in the given + texture. The pipeline has a new reference so it is up to the caller + to unref it */ +CoglPipeline * +_cogl_pango_pipeline_cache_get (CoglPangoPipelineCache *cache, + CoglTexture *texture); + +void +_cogl_pango_pipeline_cache_free (CoglPangoPipelineCache *cache); + +COGL_END_DECLS + +#endif /* __COGL_PANGO_PIPELINE_CACHE_H__ */ diff --git a/cogl/cogl-pango/cogl-pango-private.h b/cogl/cogl-pango/cogl-pango-private.h new file mode 100644 index 0000000..e0d1f51 --- /dev/null +++ b/cogl/cogl-pango/cogl-pango-private.h @@ -0,0 +1,65 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008 OpenedHand + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * Authors: + * Neil Roberts + * Robert Bragg + * Matthew Allum + */ + +#ifndef __COGL_PANGO_PRIVATE_H__ +#define __COGL_PANGO_PRIVATE_H__ + +#include "cogl-pango.h" + +COGL_BEGIN_DECLS + +PangoRenderer * +_cogl_pango_renderer_new (CoglContext *context); + +void +_cogl_pango_renderer_clear_glyph_cache (CoglPangoRenderer *renderer); + +void +_cogl_pango_renderer_set_use_mipmapping (CoglPangoRenderer *renderer, + CoglBool value); +CoglBool +_cogl_pango_renderer_get_use_mipmapping (CoglPangoRenderer *renderer); + + + +CoglContext * +_cogl_pango_font_map_get_cogl_context (CoglPangoFontMap *fm); + +PangoRenderer * +_cogl_pango_font_map_get_renderer (CoglPangoFontMap *fm); + +COGL_END_DECLS + +#endif /* __COGL_PANGO_PRIVATE_H__ */ diff --git a/cogl/cogl-pango/cogl-pango-render.c b/cogl/cogl-pango/cogl-pango-render.c new file mode 100644 index 0000000..d8cc713 --- /dev/null +++ b/cogl/cogl-pango/cogl-pango-render.c @@ -0,0 +1,929 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008 OpenedHand + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * Authors: + * Neil Roberts + * Robert Bragg + * Matthew Allum + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#ifndef PANGO_ENABLE_BACKEND +#define PANGO_ENABLE_BACKEND 1 +#endif + +#include +#include +#include +#include + +#include "cogl/cogl-debug.h" +#include "cogl/cogl-context-private.h" +#include "cogl/cogl-texture-private.h" +#include "cogl-pango-private.h" +#include "cogl-pango-glyph-cache.h" +#include "cogl-pango-display-list.h" + +enum +{ + PROP_0, + + PROP_COGL_CONTEXT, + PROP_LAST +}; + +typedef struct +{ + CoglPangoGlyphCache *glyph_cache; + CoglPangoPipelineCache *pipeline_cache; +} CoglPangoRendererCaches; + +struct _CoglPangoRenderer +{ + PangoRenderer parent_instance; + + CoglContext *ctx; + + /* Two caches of glyphs as textures and their corresponding pipeline + caches, one with mipmapped textures and one without */ + CoglPangoRendererCaches no_mipmap_caches; + CoglPangoRendererCaches mipmap_caches; + + CoglBool use_mipmapping; + + /* The current display list that is being built */ + CoglPangoDisplayList *display_list; +}; + +struct _CoglPangoRendererClass +{ + PangoRendererClass class_instance; +}; + +typedef struct _CoglPangoLayoutQdata CoglPangoLayoutQdata; + +/* An instance of this struct gets attached to each PangoLayout to + cache the VBO and to detect changes to the layout */ +struct _CoglPangoLayoutQdata +{ + CoglPangoRenderer *renderer; + /* The cache of the geometry for the layout */ + CoglPangoDisplayList *display_list; + /* A reference to the first line of the layout. This is just used to + detect changes */ + PangoLayoutLine *first_line; + /* Whether mipmapping was previously used to render this layout. We + need to regenerate the display list if the mipmapping value is + changed because it will be using a different set of textures */ + CoglBool mipmapping_used; +}; + +static void +_cogl_pango_ensure_glyph_cache_for_layout_line (PangoLayoutLine *line); + +typedef struct +{ + CoglPangoDisplayList *display_list; + float x1, y1, x2, y2; +} CoglPangoRendererSliceCbData; + +PangoRenderer * +_cogl_pango_renderer_new (CoglContext *context) +{ + return PANGO_RENDERER (g_object_new (COGL_PANGO_TYPE_RENDERER, + "context", context, NULL)); +} + +static void +cogl_pango_renderer_slice_cb (CoglTexture *texture, + const float *slice_coords, + const float *virtual_coords, + void *user_data) +{ + CoglPangoRendererSliceCbData *data = user_data; + + /* Note: this assumes that there is only one slice containing the + whole texture and it doesn't attempt to split up the vertex + coordinates based on the virtual_coords */ + + _cogl_pango_display_list_add_texture (data->display_list, + texture, + data->x1, + data->y1, + data->x2, + data->y2, + slice_coords[0], + slice_coords[1], + slice_coords[2], + slice_coords[3]); +} + +static void +cogl_pango_renderer_draw_glyph (CoglPangoRenderer *priv, + CoglPangoGlyphCacheValue *cache_value, + float x1, + float y1) +{ + CoglPangoRendererSliceCbData data; + + _COGL_RETURN_IF_FAIL (priv->display_list != NULL); + + data.display_list = priv->display_list; + data.x1 = x1; + data.y1 = y1; + data.x2 = x1 + (float) cache_value->draw_width; + data.y2 = y1 + (float) cache_value->draw_height; + + /* We iterate the internal sub textures of the texture so that we + can get a pointer to the base texture even if the texture is in + the global atlas. That way the display list can recognise that + the neighbouring glyphs are coming from the same atlas and bundle + them together into a single VBO */ + + cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (cache_value->texture), + cache_value->tx1, + cache_value->ty1, + cache_value->tx2, + cache_value->ty2, + COGL_PIPELINE_WRAP_MODE_REPEAT, + COGL_PIPELINE_WRAP_MODE_REPEAT, + cogl_pango_renderer_slice_cb, + &data); +} + +static void cogl_pango_renderer_dispose (GObject *object); +static void cogl_pango_renderer_finalize (GObject *object); +static void cogl_pango_renderer_draw_glyphs (PangoRenderer *renderer, + PangoFont *font, + PangoGlyphString *glyphs, + int x, + int y); +static void cogl_pango_renderer_draw_rectangle (PangoRenderer *renderer, + PangoRenderPart part, + int x, + int y, + int width, + int height); +static void cogl_pango_renderer_draw_trapezoid (PangoRenderer *renderer, + PangoRenderPart part, + double y1, + double x11, + double x21, + double y2, + double x12, + double x22); + +G_DEFINE_TYPE (CoglPangoRenderer, cogl_pango_renderer, PANGO_TYPE_RENDERER); + +static void +cogl_pango_renderer_init (CoglPangoRenderer *priv) +{ +} + +static void +_cogl_pango_renderer_constructed (GObject *gobject) +{ + CoglPangoRenderer *renderer = COGL_PANGO_RENDERER (gobject); + CoglContext *ctx = renderer->ctx; + + renderer->no_mipmap_caches.pipeline_cache = + _cogl_pango_pipeline_cache_new (ctx, FALSE); + renderer->mipmap_caches.pipeline_cache = + _cogl_pango_pipeline_cache_new (ctx, TRUE); + + renderer->no_mipmap_caches.glyph_cache = + cogl_pango_glyph_cache_new (ctx, FALSE); + renderer->mipmap_caches.glyph_cache = + cogl_pango_glyph_cache_new (ctx, TRUE); + + _cogl_pango_renderer_set_use_mipmapping (renderer, FALSE); + + if (G_OBJECT_CLASS (cogl_pango_renderer_parent_class)->constructed) + G_OBJECT_CLASS (cogl_pango_renderer_parent_class)->constructed (gobject); +} + +static void +cogl_pango_renderer_set_property (GObject *object, + unsigned int prop_id, + const GValue *value, + GParamSpec *pspec) +{ + CoglPangoRenderer *renderer = COGL_PANGO_RENDERER (object); + + switch (prop_id) + { + case PROP_COGL_CONTEXT: + renderer->ctx = g_value_get_pointer (value); + cogl_object_ref (renderer->ctx); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +cogl_pango_renderer_class_init (CoglPangoRendererClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass); + GParamSpec *pspec; + + object_class->set_property = cogl_pango_renderer_set_property; + object_class->constructed = _cogl_pango_renderer_constructed; + object_class->dispose = cogl_pango_renderer_dispose; + object_class->finalize = cogl_pango_renderer_finalize; + + pspec = g_param_spec_pointer ("context", + "Context", + "The Cogl Context", + G_PARAM_WRITABLE | + G_PARAM_STATIC_STRINGS | + G_PARAM_CONSTRUCT_ONLY); + + g_object_class_install_property (object_class, PROP_COGL_CONTEXT, pspec); + + renderer_class->draw_glyphs = cogl_pango_renderer_draw_glyphs; + renderer_class->draw_rectangle = cogl_pango_renderer_draw_rectangle; + renderer_class->draw_trapezoid = cogl_pango_renderer_draw_trapezoid; +} + +static void +cogl_pango_renderer_dispose (GObject *object) +{ + CoglPangoRenderer *priv = COGL_PANGO_RENDERER (object); + + if (priv->ctx) + { + cogl_object_unref (priv->ctx); + priv->ctx = NULL; + } +} + +static void +cogl_pango_renderer_finalize (GObject *object) +{ + CoglPangoRenderer *priv = COGL_PANGO_RENDERER (object); + + cogl_pango_glyph_cache_free (priv->no_mipmap_caches.glyph_cache); + cogl_pango_glyph_cache_free (priv->mipmap_caches.glyph_cache); + + _cogl_pango_pipeline_cache_free (priv->no_mipmap_caches.pipeline_cache); + _cogl_pango_pipeline_cache_free (priv->mipmap_caches.pipeline_cache); + + G_OBJECT_CLASS (cogl_pango_renderer_parent_class)->finalize (object); +} + +static CoglPangoRenderer * +cogl_pango_get_renderer_from_context (PangoContext *context) +{ + PangoFontMap *font_map; + CoglPangoFontMap *cogl_font_map; + PangoRenderer *renderer; + + font_map = pango_context_get_font_map (context); + g_return_val_if_fail (COGL_PANGO_IS_FONT_MAP (font_map), NULL); + + cogl_font_map = COGL_PANGO_FONT_MAP (font_map); + + renderer = _cogl_pango_font_map_get_renderer (cogl_font_map); + + g_return_val_if_fail (COGL_PANGO_IS_RENDERER (renderer), NULL); + + return COGL_PANGO_RENDERER (renderer); +} + +static GQuark +cogl_pango_layout_get_qdata_key (void) +{ + static GQuark key = 0; + + if (G_UNLIKELY (key == 0)) + key = g_quark_from_static_string ("CoglPangoDisplayList"); + + return key; +} + +static void +cogl_pango_layout_qdata_forget_display_list (CoglPangoLayoutQdata *qdata) +{ + if (qdata->display_list) + { + CoglPangoRendererCaches *caches = qdata->mipmapping_used ? + &qdata->renderer->mipmap_caches : + &qdata->renderer->no_mipmap_caches; + + _cogl_pango_glyph_cache_remove_reorganize_callback + (caches->glyph_cache, + (GHookFunc) cogl_pango_layout_qdata_forget_display_list, + qdata); + + _cogl_pango_display_list_free (qdata->display_list); + + qdata->display_list = NULL; + } +} + +static void +cogl_pango_render_qdata_destroy (CoglPangoLayoutQdata *qdata) +{ + cogl_pango_layout_qdata_forget_display_list (qdata); + if (qdata->first_line) + pango_layout_line_unref (qdata->first_line); + g_slice_free (CoglPangoLayoutQdata, qdata); +} + +void +cogl_pango_show_layout (CoglFramebuffer *fb, + PangoLayout *layout, + float x, + float y, + const CoglColor *color) +{ + PangoContext *context; + CoglPangoRenderer *priv; + CoglPangoLayoutQdata *qdata; + + context = pango_layout_get_context (layout); + priv = cogl_pango_get_renderer_from_context (context); + if (G_UNLIKELY (!priv)) + return; + + qdata = g_object_get_qdata (G_OBJECT (layout), + cogl_pango_layout_get_qdata_key ()); + + if (qdata == NULL) + { + qdata = g_slice_new0 (CoglPangoLayoutQdata); + qdata->renderer = priv; + g_object_set_qdata_full (G_OBJECT (layout), + cogl_pango_layout_get_qdata_key (), + qdata, + (GDestroyNotify) + cogl_pango_render_qdata_destroy); + } + + /* Check if the layout has changed since the last build of the + display list. This trick was suggested by Behdad Esfahbod here: + http://mail.gnome.org/archives/gtk-i18n-list/2009-May/msg00019.html */ + if (qdata->display_list && + ((qdata->first_line && + qdata->first_line->layout != layout) || + qdata->mipmapping_used != priv->use_mipmapping)) + cogl_pango_layout_qdata_forget_display_list (qdata); + + if (qdata->display_list == NULL) + { + CoglPangoRendererCaches *caches = priv->use_mipmapping ? + &priv->mipmap_caches : + &priv->no_mipmap_caches; + + cogl_pango_ensure_glyph_cache_for_layout (layout); + + qdata->display_list = + _cogl_pango_display_list_new (caches->pipeline_cache); + + /* Register for notification of when the glyph cache changes so + we can rebuild the display list */ + _cogl_pango_glyph_cache_add_reorganize_callback + (caches->glyph_cache, + (GHookFunc) cogl_pango_layout_qdata_forget_display_list, + qdata); + + priv->display_list = qdata->display_list; + pango_renderer_draw_layout (PANGO_RENDERER (priv), layout, 0, 0); + priv->display_list = NULL; + + qdata->mipmapping_used = priv->use_mipmapping; + } + + cogl_framebuffer_push_matrix (fb); + cogl_framebuffer_translate (fb, x, y, 0); + + _cogl_pango_display_list_render (fb, + qdata->display_list, + color); + + cogl_framebuffer_pop_matrix (fb); + + /* Keep a reference to the first line of the layout so we can detect + changes */ + if (qdata->first_line) + { + pango_layout_line_unref (qdata->first_line); + qdata->first_line = NULL; + } + if (pango_layout_get_line_count (layout) > 0) + { + qdata->first_line = pango_layout_get_line (layout, 0); + pango_layout_line_ref (qdata->first_line); + } +} + +void +cogl_pango_render_layout_subpixel (PangoLayout *layout, + int x, + int y, + const CoglColor *color, + int flags) +{ + cogl_pango_show_layout (cogl_get_draw_framebuffer (), + layout, + x / (float) PANGO_SCALE, + y / (float) PANGO_SCALE, + color); +} + +void +cogl_pango_render_layout (PangoLayout *layout, + int x, + int y, + const CoglColor *color, + int flags) +{ + cogl_pango_render_layout_subpixel (layout, + x * PANGO_SCALE, + y * PANGO_SCALE, + color, + flags); +} + +void +cogl_pango_show_layout_line (CoglFramebuffer *fb, + PangoLayoutLine *line, + float x, + float y, + const CoglColor *color) +{ + PangoContext *context; + CoglPangoRenderer *priv; + CoglPangoRendererCaches *caches; + int pango_x = x * PANGO_SCALE; + int pango_y = y * PANGO_SCALE; + + context = pango_layout_get_context (line->layout); + priv = cogl_pango_get_renderer_from_context (context); + if (G_UNLIKELY (!priv)) + return; + + caches = (priv->use_mipmapping ? + &priv->mipmap_caches : + &priv->no_mipmap_caches); + + priv->display_list = _cogl_pango_display_list_new (caches->pipeline_cache); + + _cogl_pango_ensure_glyph_cache_for_layout_line (line); + + pango_renderer_draw_layout_line (PANGO_RENDERER (priv), line, + pango_x, pango_y); + + _cogl_pango_display_list_render (fb, + priv->display_list, + color); + + _cogl_pango_display_list_free (priv->display_list); + priv->display_list = NULL; +} + +void +cogl_pango_render_layout_line (PangoLayoutLine *line, + int x, + int y, + const CoglColor *color) +{ + cogl_pango_show_layout_line (cogl_get_draw_framebuffer (), + line, + x / (float) PANGO_SCALE, + y / (float) PANGO_SCALE, + color); +} + +void +_cogl_pango_renderer_clear_glyph_cache (CoglPangoRenderer *renderer) +{ + cogl_pango_glyph_cache_clear (renderer->mipmap_caches.glyph_cache); + cogl_pango_glyph_cache_clear (renderer->no_mipmap_caches.glyph_cache); +} + +void +_cogl_pango_renderer_set_use_mipmapping (CoglPangoRenderer *renderer, + CoglBool value) +{ + renderer->use_mipmapping = value; +} + +CoglBool +_cogl_pango_renderer_get_use_mipmapping (CoglPangoRenderer *renderer) +{ + return renderer->use_mipmapping; +} + +static CoglPangoGlyphCacheValue * +cogl_pango_renderer_get_cached_glyph (PangoRenderer *renderer, + CoglBool create, + PangoFont *font, + PangoGlyph glyph) +{ + CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer); + CoglPangoRendererCaches *caches = (priv->use_mipmapping ? + &priv->mipmap_caches : + &priv->no_mipmap_caches); + + return cogl_pango_glyph_cache_lookup (caches->glyph_cache, + create, font, glyph); +} + +static void +cogl_pango_renderer_set_dirty_glyph (PangoFont *font, + PangoGlyph glyph, + CoglPangoGlyphCacheValue *value) +{ + cairo_surface_t *surface; + cairo_t *cr; + cairo_scaled_font_t *scaled_font; + cairo_glyph_t cairo_glyph; + cairo_format_t format_cairo; + CoglPixelFormat format_cogl; + + COGL_NOTE (PANGO, "redrawing glyph %i", glyph); + + /* Glyphs that don't take up any space will end up without a + texture. These should never become dirty so they shouldn't end up + here */ + _COGL_RETURN_IF_FAIL (value->texture != NULL); + + if (_cogl_texture_get_format (value->texture) == COGL_PIXEL_FORMAT_A_8) + { + format_cairo = CAIRO_FORMAT_A8; + format_cogl = COGL_PIXEL_FORMAT_A_8; + } + else + { + format_cairo = CAIRO_FORMAT_ARGB32; + + /* Cairo stores the data in native byte order as ARGB but Cogl's + pixel formats specify the actual byte order. Therefore we + need to use a different format depending on the + architecture */ +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + format_cogl = COGL_PIXEL_FORMAT_BGRA_8888_PRE; +#else + format_cogl = COGL_PIXEL_FORMAT_ARGB_8888_PRE; +#endif + } + + surface = cairo_image_surface_create (format_cairo, + value->draw_width, + value->draw_height); + cr = cairo_create (surface); + + scaled_font = pango_cairo_font_get_scaled_font (PANGO_CAIRO_FONT (font)); + cairo_set_scaled_font (cr, scaled_font); + + cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0); + + cairo_glyph.x = -value->draw_x; + cairo_glyph.y = -value->draw_y; + /* The PangoCairo glyph numbers directly map to Cairo glyph + numbers */ + cairo_glyph.index = glyph; + cairo_show_glyphs (cr, &cairo_glyph, 1); + + cairo_destroy (cr); + cairo_surface_flush (surface); + + /* Copy the glyph to the texture */ + cogl_texture_set_region (value->texture, + 0, /* src_x */ + 0, /* src_y */ + value->tx_pixel, /* dst_x */ + value->ty_pixel, /* dst_y */ + value->draw_width, /* dst_width */ + value->draw_height, /* dst_height */ + value->draw_width, /* width */ + value->draw_height, /* height */ + format_cogl, + cairo_image_surface_get_stride (surface), + cairo_image_surface_get_data (surface)); + + cairo_surface_destroy (surface); +} + +static void +_cogl_pango_ensure_glyph_cache_for_layout_line_internal (PangoLayoutLine *line) +{ + PangoContext *context; + PangoRenderer *renderer; + GSList *l; + + context = pango_layout_get_context (line->layout); + renderer = + PANGO_RENDERER (cogl_pango_get_renderer_from_context (context)); + + for (l = line->runs; l; l = l->next) + { + PangoLayoutRun *run = l->data; + PangoGlyphString *glyphs = run->glyphs; + int i; + + for (i = 0; i < glyphs->num_glyphs; i++) + { + PangoGlyphInfo *gi = &glyphs->glyphs[i]; + + /* If the glyph isn't cached then this will reserve + space for it now. We won't actually draw the glyph + yet because reserving space could cause all of the + other glyphs to be moved so we might as well redraw + them all later once we know that the position is + settled */ + cogl_pango_renderer_get_cached_glyph (renderer, TRUE, + run->item->analysis.font, + gi->glyph); + } + } +} + +static void +_cogl_pango_set_dirty_glyphs (CoglPangoRenderer *priv) +{ + _cogl_pango_glyph_cache_set_dirty_glyphs + (priv->mipmap_caches.glyph_cache, cogl_pango_renderer_set_dirty_glyph); + _cogl_pango_glyph_cache_set_dirty_glyphs + (priv->no_mipmap_caches.glyph_cache, cogl_pango_renderer_set_dirty_glyph); +} + +static void +_cogl_pango_ensure_glyph_cache_for_layout_line (PangoLayoutLine *line) +{ + PangoContext *context; + CoglPangoRenderer *priv; + + context = pango_layout_get_context (line->layout); + priv = cogl_pango_get_renderer_from_context (context); + + _cogl_pango_ensure_glyph_cache_for_layout_line_internal (line); + + /* Now that we know all of the positions are settled we'll fill in + any dirty glyphs */ + _cogl_pango_set_dirty_glyphs (priv); +} + +void +cogl_pango_ensure_glyph_cache_for_layout (PangoLayout *layout) +{ + PangoContext *context; + CoglPangoRenderer *priv; + PangoLayoutIter *iter; + + context = pango_layout_get_context (layout); + priv = cogl_pango_get_renderer_from_context (context); + + _COGL_RETURN_IF_FAIL (PANGO_IS_LAYOUT (layout)); + + if ((iter = pango_layout_get_iter (layout)) == NULL) + return; + + do + { + PangoLayoutLine *line; + + line = pango_layout_iter_get_line_readonly (iter); + + _cogl_pango_ensure_glyph_cache_for_layout_line_internal (line); + } + while (pango_layout_iter_next_line (iter)); + + pango_layout_iter_free (iter); + + /* Now that we know all of the positions are settled we'll fill in + any dirty glyphs */ + _cogl_pango_set_dirty_glyphs (priv); +} + +static void +cogl_pango_renderer_set_color_for_part (PangoRenderer *renderer, + PangoRenderPart part) +{ + PangoColor *pango_color = pango_renderer_get_color (renderer, part); + CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer); + + if (pango_color) + { + CoglColor color; + + cogl_color_init_from_4ub (&color, + pango_color->red >> 8, + pango_color->green >> 8, + pango_color->blue >> 8, + 0xff); + + _cogl_pango_display_list_set_color_override (priv->display_list, &color); + } + else + _cogl_pango_display_list_remove_color_override (priv->display_list); +} + +static void +cogl_pango_renderer_draw_box (PangoRenderer *renderer, + int x, + int y, + int width, + int height) +{ + CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer); + + _COGL_RETURN_IF_FAIL (priv->display_list != NULL); + + _cogl_pango_display_list_add_rectangle (priv->display_list, + x, + y - height, + x + width, + y); +} + +static void +cogl_pango_renderer_get_device_units (PangoRenderer *renderer, + int xin, + int yin, + float *xout, + float *yout) +{ + const PangoMatrix *matrix; + + if ((matrix = pango_renderer_get_matrix (renderer))) + { + /* Convert user-space coords to device coords */ + *xout = ((xin * matrix->xx + yin * matrix->xy) + / PANGO_SCALE + matrix->x0); + *yout = ((yin * matrix->yy + xin * matrix->yx) + / PANGO_SCALE + matrix->y0); + } + else + { + *xout = PANGO_PIXELS (xin); + *yout = PANGO_PIXELS (yin); + } +} + +static void +cogl_pango_renderer_draw_rectangle (PangoRenderer *renderer, + PangoRenderPart part, + int x, + int y, + int width, + int height) +{ + CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer); + float x1, x2, y1, y2; + + _COGL_RETURN_IF_FAIL (priv->display_list != NULL); + + cogl_pango_renderer_set_color_for_part (renderer, part); + + cogl_pango_renderer_get_device_units (renderer, + x, y, + &x1, &y1); + cogl_pango_renderer_get_device_units (renderer, + x + width, y + height, + &x2, &y2); + + _cogl_pango_display_list_add_rectangle (priv->display_list, + x1, y1, x2, y2); +} + +static void +cogl_pango_renderer_draw_trapezoid (PangoRenderer *renderer, + PangoRenderPart part, + double y1, + double x11, + double x21, + double y2, + double x12, + double x22) +{ + CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer); + + _COGL_RETURN_IF_FAIL (priv->display_list != NULL); + + cogl_pango_renderer_set_color_for_part (renderer, part); + + _cogl_pango_display_list_add_trapezoid (priv->display_list, + y1, + x11, + x21, + y2, + x12, + x22); +} + +static void +cogl_pango_renderer_draw_glyphs (PangoRenderer *renderer, + PangoFont *font, + PangoGlyphString *glyphs, + int xi, + int yi) +{ + CoglPangoRenderer *priv = (CoglPangoRenderer *) renderer; + CoglPangoGlyphCacheValue *cache_value; + int i; + + cogl_pango_renderer_set_color_for_part (renderer, + PANGO_RENDER_PART_FOREGROUND); + + for (i = 0; i < glyphs->num_glyphs; i++) + { + PangoGlyphInfo *gi = glyphs->glyphs + i; + float x, y; + + cogl_pango_renderer_get_device_units (renderer, + xi + gi->geometry.x_offset, + yi + gi->geometry.y_offset, + &x, &y); + + if ((gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG)) + { + if (font == NULL) + { + cogl_pango_renderer_draw_box (renderer, + x, + y, + PANGO_UNKNOWN_GLYPH_WIDTH, + PANGO_UNKNOWN_GLYPH_HEIGHT); + } + else + { + PangoRectangle ink_rect; + + pango_font_get_glyph_extents (font, gi->glyph, &ink_rect, NULL); + pango_extents_to_pixels (&ink_rect, NULL); + + cogl_pango_renderer_draw_box (renderer, + x + ink_rect.x, + y + ink_rect.y + ink_rect.height, + ink_rect.width, + ink_rect.height); + } + } + else + { + /* Get the texture containing the glyph */ + cache_value = + cogl_pango_renderer_get_cached_glyph (renderer, + FALSE, + font, + gi->glyph); + + /* cogl_pango_ensure_glyph_cache_for_layout should always be + called before rendering a layout so we should never have + a dirty glyph here */ + g_assert (cache_value == NULL || !cache_value->dirty); + + if (cache_value == NULL) + { + cogl_pango_renderer_draw_box (renderer, + x, + y, + PANGO_UNKNOWN_GLYPH_WIDTH, + PANGO_UNKNOWN_GLYPH_HEIGHT); + } + else if (cache_value->texture) + { + x += (float)(cache_value->draw_x); + y += (float)(cache_value->draw_y); + + cogl_pango_renderer_draw_glyph (priv, cache_value, x, y); + } + } + + xi += gi->geometry.width; + } +} diff --git a/cogl/cogl-pango/cogl-pango.h b/cogl/cogl-pango/cogl-pango.h new file mode 100644 index 0000000..787aaa8 --- /dev/null +++ b/cogl/cogl-pango/cogl-pango.h @@ -0,0 +1,299 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008 OpenedHand + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Neil Roberts + * Robert Bragg + * Matthew Allum + */ + +#ifndef __COGL_PANGO_H__ +#define __COGL_PANGO_H__ + +#include +#include +#include + +/* XXX: Currently this header may be included both as an internal + * header (within the cogl-pango implementation) and as a public + * header. + * + * Since should not be included for internal use we + * determine the current context and switch between including cogl.h + * or specific internal cogl headers here... + */ +#ifndef COGL_COMPILATION +#include +#else +#include "cogl/cogl-context.h" +#include "cogl/cogl-macros.h" +#endif + +COGL_BEGIN_DECLS + +/* It's too difficult to actually subclass the pango cairo font + * map. Instead we just make a fake set of macros that actually just + * directly use the original type + */ +#define COGL_PANGO_TYPE_FONT_MAP PANGO_TYPE_CAIRO_FONT_MAP +#define COGL_PANGO_FONT_MAP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), COGL_PANGO_TYPE_FONT_MAP, CoglPangoFontMap)) +#define COGL_PANGO_IS_FONT_MAP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), COGL_PANGO_TYPE_FONT_MAP)) + +typedef PangoCairoFontMap CoglPangoFontMap; + +/** + * cogl_pango_font_map_new: + * + * Creates a new font map. + * + * Return value: (transfer full): the newly created #PangoFontMap + * + * Since: 1.14 + */ +PangoFontMap * +cogl_pango_font_map_new (void); + +/** + * cogl_pango_font_map_create_context: + * @font_map: a #CoglPangoFontMap + * + * Create a #PangoContext for the given @font_map. + * + * Returns: (transfer full): the newly created context: free with g_object_unref(). + */ +PangoContext * +cogl_pango_font_map_create_context (CoglPangoFontMap *font_map); + +/** + * cogl_pango_font_map_set_resolution: + * @font_map: a #CoglPangoFontMap + * @dpi: The resolution in "dots per inch". (Physical inches aren't + * actually involved; the terminology is conventional.) + * + * Sets the resolution for the @font_map. This is a scale factor + * between points specified in a #PangoFontDescription and Cogl units. + * The default value is %96, meaning that a 10 point font will be 13 + * units high. (10 * 96. / 72. = 13.3). + * + * Since: 1.14 + */ +void +cogl_pango_font_map_set_resolution (CoglPangoFontMap *font_map, + double dpi); + +/** + * cogl_pango_font_map_clear_glyph_cache: + * @font_map: a #CoglPangoFontMap + * + * Clears the glyph cache for @font_map. + * + * Since: 1.0 + */ +void +cogl_pango_font_map_clear_glyph_cache (CoglPangoFontMap *font_map); + +/** + * cogl_pango_ensure_glyph_cache_for_layout: + * @layout: A #PangoLayout + * + * This updates any internal glyph cache textures as necessary to be + * able to render the given @layout. + * + * This api should be used to avoid mid-scene modifications of + * glyph-cache textures which can lead to undefined rendering results. + * + * Since: 1.0 + */ +void +cogl_pango_ensure_glyph_cache_for_layout (PangoLayout *layout); + +/** + * cogl_pango_font_map_set_use_mipmapping: + * @font_map: a #CoglPangoFontMap + * @value: %TRUE to enable the use of mipmapping + * + * Sets whether the renderer for the passed font map should use + * mipmapping when rendering a #PangoLayout. + * + * Since: 1.0 + */ +void +cogl_pango_font_map_set_use_mipmapping (CoglPangoFontMap *font_map, + CoglBool value); + +/** + * cogl_pango_font_map_get_use_mipmapping: + * @font_map: a #CoglPangoFontMap + * + * Retrieves whether the #CoglPangoRenderer used by @font_map will use + * mipmapping when rendering the glyphs. + * + * Return value: %TRUE if mipmapping is used, %FALSE otherwise. + * + * Since: 1.0 + */ +CoglBool +cogl_pango_font_map_get_use_mipmapping (CoglPangoFontMap *font_map); + +/** + * cogl_pango_font_map_get_renderer: + * @font_map: a #CoglPangoFontMap + * + * Retrieves the #CoglPangoRenderer for the passed @font_map. + * + * Return value: (transfer none): a #PangoRenderer + * + * Since: 1.0 + */ +PangoRenderer * +cogl_pango_font_map_get_renderer (CoglPangoFontMap *font_map); + +/** + * cogl_pango_show_layout: (skip) + * @framebuffer: A #CoglFramebuffer to draw too. + * @layout: a #PangoLayout + * @x: X coordinate to render the layout at + * @y: Y coordinate to render the layout at + * @color: color to use when rendering the layout + * + * Draws a solidly coloured @layout on the given @framebuffer at (@x, + * @y) within the @framebuffer's current model-view coordinate + * space. + * + * Since: 1.14 + */ +void +cogl_pango_show_layout (CoglFramebuffer *framebuffer, + PangoLayout *layout, + float x, + float y, + const CoglColor *color); + +/** + * cogl_pango_show_layout_line: (skip) + * @framebuffer: A #CoglFramebuffer to draw too. + * @line: a #PangoLayoutLine + * @x: X coordinate to render the line at + * @y: Y coordinate to render the line at + * @color: color to use when rendering the line + * + * Draws a solidly coloured @line on the given @framebuffer at (@x, + * @y) within the @framebuffer's current model-view coordinate + * space. + * + * Since: 1.14 + */ +void +cogl_pango_show_layout_line (CoglFramebuffer *framebuffer, + PangoLayoutLine *line, + float x, + float y, + const CoglColor *color); + + +#define COGL_PANGO_TYPE_RENDERER (cogl_pango_renderer_get_type ()) +#define COGL_PANGO_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), COGL_PANGO_TYPE_RENDERER, CoglPangoRenderer)) +#define COGL_PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), COGL_PANGO_TYPE_RENDERER, CoglPangoRendererClass)) +#define COGL_PANGO_IS_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), COGL_PANGO_TYPE_RENDERER)) +#define COGL_PANGO_IS_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), COGL_PANGO_TYPE_RENDERER)) +#define COGL_PANGO_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), COGL_PANGO_TYPE_RENDERER, CoglPangoRendererClass)) + +/* opaque types */ +typedef struct _CoglPangoRenderer CoglPangoRenderer; +typedef struct _CoglPangoRendererClass CoglPangoRendererClass; + +GType cogl_pango_renderer_get_type (void) G_GNUC_CONST; + +/** + * cogl_pango_render_layout_subpixel: + * @layout: a #PangoLayout + * @x: X coordinate (in Pango units) to render the layout at + * @y: Y coordinate (in Pango units) to render the layout at + * @color: color to use when rendering the layout + * @flags: + * + * Draws a solidly coloured @layout on the given @framebuffer at (@x, + * @y) within the @framebuffer's current model-view coordinate + * space. + * + * Since: 1.0 + * Deprecated: 1.16: Use cogl_pango_show_layout() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pango_show_layout) +void +cogl_pango_render_layout_subpixel (PangoLayout *layout, + int x, + int y, + const CoglColor *color, + int flags); + +/** + * cogl_pango_render_layout: + * @layout: a #PangoLayout + * @x: X coordinate to render the layout at + * @y: Y coordinate to render the layout at + * @color: color to use when rendering the layout + * @flags: + * + * Draws a solidly coloured @layout on the given @framebuffer at (@x, + * @y) within the @framebuffer's current model-view coordinate + * space. + * + * Since: 1.0 + * Deprecated: 1.16: Use cogl_pango_show_layout() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pango_show_layout) +void +cogl_pango_render_layout (PangoLayout *layout, + int x, + int y, + const CoglColor *color, + int flags); + +/** + * cogl_pango_render_layout_line: + * @line: a #PangoLayoutLine + * @x: X coordinate to render the line at + * @y: Y coordinate to render the line at + * @color: color to use when rendering the line + * + * Renders @line at the given coordinates using the given color. + * + * Since: 1.0 + * Deprecated: 1.16: Use cogl_pango_show_layout() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pango_show_layout_line) +void +cogl_pango_render_layout_line (PangoLayoutLine *line, + int x, + int y, + const CoglColor *color); + +COGL_END_DECLS + +#endif /* __COGL_PANGO_H__ */ diff --git a/cogl/cogl-pango/cogl-pango.symbols b/cogl/cogl-pango/cogl-pango.symbols new file mode 100644 index 0000000..b86c956 --- /dev/null +++ b/cogl/cogl-pango/cogl-pango.symbols @@ -0,0 +1,12 @@ +cogl_pango_ensure_glyph_cache_for_layout +cogl_pango_font_map_clear_glyph_cache +cogl_pango_font_map_create_context +cogl_pango_font_map_get_renderer +cogl_pango_font_map_get_use_mipmapping +cogl_pango_font_map_new +cogl_pango_font_map_set_resolution +cogl_pango_font_map_set_use_mipmapping +cogl_pango_renderer_get_type +cogl_pango_render_layout +cogl_pango_render_layout_line +cogl_pango_render_layout_subpixel diff --git a/cogl/cogl-pango/mutter-cogl-pango-1.0.pc.in b/cogl/cogl-pango/mutter-cogl-pango-1.0.pc.in new file mode 100644 index 0000000..64ab7b4 --- /dev/null +++ b/cogl/cogl-pango/mutter-cogl-pango-1.0.pc.in @@ -0,0 +1,13 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@/mutter +includedir=@includedir@/mutter +apiversion=1.0 +requires=@COGL_PKG_REQUIRES@ mutter-cogl-1.0 + +Name: Cogl +Description: An object oriented GL/GLES Abstraction/Utility Layer +Version: @COGL_1_VERSION@ +Libs: -L${libdir} -lmutter-cogl-pango +Cflags: -I${includedir}/cogl +Requires: ${requires} diff --git a/cogl/cogl-path/Makefile.am b/cogl/cogl-path/Makefile.am new file mode 100644 index 0000000..7827f92 --- /dev/null +++ b/cogl/cogl-path/Makefile.am @@ -0,0 +1,102 @@ +NULL = + +BUILT_SOURCES = + +CLEANFILES = +DISTCLEANFILES = + +EXTRA_DIST = + +# tesselator sources +cogl_tesselator_sources = \ + tesselator/dict-list.h \ + tesselator/dict.c \ + tesselator/dict.h \ + tesselator/geom.c \ + tesselator/geom.h \ + tesselator/gluos.h \ + tesselator/memalloc.h \ + tesselator/mesh.c \ + tesselator/mesh.h \ + tesselator/normal.c \ + tesselator/normal.h \ + tesselator/priorityq-heap.h \ + tesselator/priorityq-sort.h \ + tesselator/priorityq.c \ + tesselator/priorityq.h \ + tesselator/render.c \ + tesselator/render.h \ + tesselator/sweep.c \ + tesselator/sweep.h \ + tesselator/tess.c \ + tesselator/tess.h \ + tesselator/tesselator.h \ + tesselator/tessmono.c \ + tesselator/tessmono.h \ + tesselator/GL/glu.h \ + $(NULL) + +source_c = \ + $(cogl_tesselator_sources) \ + cogl-path-private.h \ + cogl-path.c \ + $(NULL) + +EXTRA_DIST += \ + tesselator/README \ + tesselator/priorityq-heap.c \ + cogl-path.symbols \ + $(NULL) + +source_1_x_h = \ + cogl-path-types.h \ + $(NULL) + +source_h = \ + cogl-path.h \ + $(source_1_x_h) \ + cogl-path-functions.h \ + $(NULL) + +# glib-mkenums rules +glib_enum_h = cogl-path-enum-types.h +glib_enum_c = cogl-path-enum-types.c +glib_enum_headers = $(source_1_x_h) +include $(top_srcdir)/build/autotools/Makefile.am.enums + +mutterlibdir = $(libdir)/mutter +mutterlib_LTLIBRARIES = libmutter-cogl-path.la + +libmutter_cogl_path_la_SOURCES = $(source_c) $(source_h) +nodist_libmutter_cogl_path_la_SOURCES = $(BUILT_SOURCES) +libmutter_cogl_path_la_CFLAGS = $(COGL_DEP_CFLAGS) $(COGL_EXTRA_CFLAGS) $(MAINTAINER_CFLAGS) +libmutter_cogl_path_la_LIBADD = $(top_builddir)/cogl/libmutter-cogl.la +libmutter_cogl_path_la_LIBADD += $(COGL_DEP_LIBS) $(COGL_EXTRA_LDFLAGS) +libmutter_cogl_path_la_LDFLAGS = \ + -export-dynamic \ + -export-symbols-regex "^(cogl|cogl2)_(framebuffer|path|is|clip|[sg]et)_.*" \ + -no-undefined \ + -avoid-version \ + -rpath $(mutterlibdir) + +AM_CPPFLAGS = \ + -DCOGL_COMPILATION \ + -DG_LOG_DOMAIN=\"CoglPath\" \ + -I$(srcdir)/tesselator \ + -I$(top_srcdir)/cogl \ + -I$(top_builddir)/cogl \ + -I$(top_srcdir)/cogl/winsys \ + -I$(top_srcdir) \ + -I$(top_builddir) + +cogl_base_includedir = $(includedir)/mutter +cogl_pathheadersdir = $(cogl_base_includedir)/cogl/cogl-path +cogl_pathheaders_HEADERS = $(source_h) +nodist_cogl_pathheaders_HEADERS = cogl-path-enum-types.h + +pc_files = mutter-cogl-path-1.0.pc + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = $(pc_files) + +DISTCLEANFILES += $(pc_files) diff --git a/cogl/cogl-path/Makefile.in b/cogl/cogl-path/Makefile.in new file mode 100644 index 0000000..027f77b --- /dev/null +++ b/cogl/cogl-path/Makefile.in @@ -0,0 +1,1097 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Rules for generating enumeration types using glib-mkenums +# +# Define: +# glib_enum_h = header template file +# glib_enum_c = source template file +# glib_enum_headers = list of headers to parse +# +# before including Makefile.am.enums. You will also need to have +# the following targets already defined: +# +# CLEANFILES +# DISTCLEANFILES +# BUILT_SOURCES +# EXTRA_DIST +# +# Author: Emmanuele Bassi + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = cogl-path +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/build/autotools/as-compiler-flag.m4 \ + $(top_srcdir)/build/autotools/introspection.m4 \ + $(top_srcdir)/build/autotools/libtool.m4 \ + $(top_srcdir)/build/autotools/ltoptions.m4 \ + $(top_srcdir)/build/autotools/ltsugar.m4 \ + $(top_srcdir)/build/autotools/ltversion.m4 \ + $(top_srcdir)/build/autotools/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(cogl_pathheaders_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/cogl-config.h \ + $(top_builddir)/cogl-mutter-config.h +CONFIG_CLEAN_FILES = mutter-cogl-path-1.0.pc +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(mutterlibdir)" \ + "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(cogl_pathheadersdir)" \ + "$(DESTDIR)$(cogl_pathheadersdir)" +LTLIBRARIES = $(mutterlib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libmutter_cogl_path_la_DEPENDENCIES = \ + $(top_builddir)/cogl/libmutter-cogl.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am__dirstamp = $(am__leading_dot)dirstamp +am__objects_1 = +am__objects_2 = tesselator/libmutter_cogl_path_la-dict.lo \ + tesselator/libmutter_cogl_path_la-geom.lo \ + tesselator/libmutter_cogl_path_la-mesh.lo \ + tesselator/libmutter_cogl_path_la-normal.lo \ + tesselator/libmutter_cogl_path_la-priorityq.lo \ + tesselator/libmutter_cogl_path_la-render.lo \ + tesselator/libmutter_cogl_path_la-sweep.lo \ + tesselator/libmutter_cogl_path_la-tess.lo \ + tesselator/libmutter_cogl_path_la-tessmono.lo $(am__objects_1) +am__objects_3 = $(am__objects_2) libmutter_cogl_path_la-cogl-path.lo \ + $(am__objects_1) +am__objects_4 = $(am__objects_1) +am__objects_5 = $(am__objects_4) $(am__objects_1) +am_libmutter_cogl_path_la_OBJECTS = $(am__objects_3) $(am__objects_5) +am__objects_6 = libmutter_cogl_path_la-cogl-path-enum-types.lo +am__objects_7 = $(am__objects_1) $(am__objects_6) +nodist_libmutter_cogl_path_la_OBJECTS = $(am__objects_7) +libmutter_cogl_path_la_OBJECTS = $(am_libmutter_cogl_path_la_OBJECTS) \ + $(nodist_libmutter_cogl_path_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libmutter_cogl_path_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libmutter_cogl_path_la_CFLAGS) $(CFLAGS) \ + $(libmutter_cogl_path_la_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libmutter_cogl_path_la_SOURCES) \ + $(nodist_libmutter_cogl_path_la_SOURCES) +DIST_SOURCES = $(libmutter_cogl_path_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(pkgconfig_DATA) +HEADERS = $(cogl_pathheaders_HEADERS) \ + $(nodist_cogl_pathheaders_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(srcdir)/mutter-cogl-path-1.0.pc.in \ + $(top_srcdir)/build/autotools/Makefile.am.enums \ + $(top_srcdir)/build/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_REQ_VERSION = @CAIRO_REQ_VERSION@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COGL_1_MICRO_VERSION = @COGL_1_MICRO_VERSION@ +COGL_1_MINOR_VERSION = @COGL_1_MINOR_VERSION@ +COGL_1_VERSION = @COGL_1_VERSION@ +COGL_API_VERSION = @COGL_API_VERSION@ +COGL_API_VERSION_AM = @COGL_API_VERSION_AM@ +COGL_DEBUG_CFLAGS = @COGL_DEBUG_CFLAGS@ +COGL_DEFAULT_DRIVER = @COGL_DEFAULT_DRIVER@ +COGL_DEP_CFLAGS = @COGL_DEP_CFLAGS@ +COGL_DEP_GL_CFLAGS = @COGL_DEP_GL_CFLAGS@ +COGL_DEP_GL_LIBS = @COGL_DEP_GL_LIBS@ +COGL_DEP_LIBS = @COGL_DEP_LIBS@ +COGL_EGL_INCLUDES = @COGL_EGL_INCLUDES@ +COGL_EXTRA_CFLAGS = @COGL_EXTRA_CFLAGS@ +COGL_EXTRA_LDFLAGS = @COGL_EXTRA_LDFLAGS@ +COGL_GLES1_LIBNAME = @COGL_GLES1_LIBNAME@ +COGL_GLES2_LIBNAME = @COGL_GLES2_LIBNAME@ +COGL_GL_LIBNAME = @COGL_GL_LIBNAME@ +COGL_GST_DEP_CFLAGS = @COGL_GST_DEP_CFLAGS@ +COGL_GST_DEP_LIBS = @COGL_GST_DEP_LIBS@ +COGL_LT_AGE = @COGL_LT_AGE@ +COGL_LT_CURRENT = @COGL_LT_CURRENT@ +COGL_LT_RELEASE = @COGL_LT_RELEASE@ +COGL_LT_REVISION = @COGL_LT_REVISION@ +COGL_MAJOR_VERSION = @COGL_MAJOR_VERSION@ +COGL_MICRO_VERSION = @COGL_MICRO_VERSION@ +COGL_MINOR_VERSION = @COGL_MINOR_VERSION@ +COGL_PANGO_DEP_CFLAGS = @COGL_PANGO_DEP_CFLAGS@ +COGL_PANGO_DEP_LIBS = @COGL_PANGO_DEP_LIBS@ +COGL_PANGO_PKG_REQUIRES = @COGL_PANGO_PKG_REQUIRES@ +COGL_PKG_REQUIRES = @COGL_PKG_REQUIRES@ +COGL_RELEASE_STATUS = @COGL_RELEASE_STATUS@ +COGL_VERSION = @COGL_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMMY_CFLAGS = @DUMMY_CFLAGS@ +DUMMY_LIBS = @DUMMY_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDKPIXBUF_PREFIX = @GDKPIXBUF_PREFIX@ +GDK_PIXBUF_REQ_VERSION = @GDK_PIXBUF_REQ_VERSION@ +GI_REQ_VERSION = @GI_REQ_VERSION@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ_VERSION = @GLIB_REQ_VERSION@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +HAVE_GL = @HAVE_GL@ +HAVE_GLES1 = @HAVE_GLES1@ +HAVE_GLES2 = @HAVE_GLES2@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINTAINER_CFLAGS = @MAINTAINER_CFLAGS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGOCAIRO_REQ_VERSION = @PANGOCAIRO_REQ_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +UPROF_REQ_VERSION = @UPROF_REQ_VERSION@ +VERSION = @VERSION@ +WAYLAND_SERVER_CFLAGS = @WAYLAND_SERVER_CFLAGS@ +WAYLAND_SERVER_LIBS = @WAYLAND_SERVER_LIBS@ +WAYLAND_SERVER_REQ_VERSION = @WAYLAND_SERVER_REQ_VERSION@ +XCOMPOSITE_REQ_VERSION = @XCOMPOSITE_REQ_VERSION@ +XFIXES_REQ_VERSION = @XFIXES_REQ_VERSION@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = +BUILT_SOURCES = $(glib_enum_h) $(glib_enum_c) +CLEANFILES = stamp-enum-types +DISTCLEANFILES = $(glib_enum_h) $(glib_enum_c) $(pc_files) +EXTRA_DIST = tesselator/README tesselator/priorityq-heap.c \ + cogl-path.symbols $(NULL) $(enum_tmpl_h) $(enum_tmpl_c) + +# tesselator sources +cogl_tesselator_sources = \ + tesselator/dict-list.h \ + tesselator/dict.c \ + tesselator/dict.h \ + tesselator/geom.c \ + tesselator/geom.h \ + tesselator/gluos.h \ + tesselator/memalloc.h \ + tesselator/mesh.c \ + tesselator/mesh.h \ + tesselator/normal.c \ + tesselator/normal.h \ + tesselator/priorityq-heap.h \ + tesselator/priorityq-sort.h \ + tesselator/priorityq.c \ + tesselator/priorityq.h \ + tesselator/render.c \ + tesselator/render.h \ + tesselator/sweep.c \ + tesselator/sweep.h \ + tesselator/tess.c \ + tesselator/tess.h \ + tesselator/tesselator.h \ + tesselator/tessmono.c \ + tesselator/tessmono.h \ + tesselator/GL/glu.h \ + $(NULL) + +source_c = \ + $(cogl_tesselator_sources) \ + cogl-path-private.h \ + cogl-path.c \ + $(NULL) + +source_1_x_h = \ + cogl-path-types.h \ + $(NULL) + +source_h = \ + cogl-path.h \ + $(source_1_x_h) \ + cogl-path-functions.h \ + $(NULL) + + +# glib-mkenums rules +glib_enum_h = cogl-path-enum-types.h +glib_enum_c = cogl-path-enum-types.c +glib_enum_headers = $(source_1_x_h) +enum_tmpl_h = $(addprefix $(srcdir)/, $(glib_enum_h:.h=.h.in)) +enum_tmpl_c = $(addprefix $(srcdir)/, $(glib_enum_c:.c=.c.in)) +enum_headers = $(addprefix $(srcdir)/, $(glib_enum_headers)) +mutterlibdir = $(libdir)/mutter +mutterlib_LTLIBRARIES = libmutter-cogl-path.la +libmutter_cogl_path_la_SOURCES = $(source_c) $(source_h) +nodist_libmutter_cogl_path_la_SOURCES = $(BUILT_SOURCES) +libmutter_cogl_path_la_CFLAGS = $(COGL_DEP_CFLAGS) $(COGL_EXTRA_CFLAGS) $(MAINTAINER_CFLAGS) +libmutter_cogl_path_la_LIBADD = \ + $(top_builddir)/cogl/libmutter-cogl.la $(COGL_DEP_LIBS) \ + $(COGL_EXTRA_LDFLAGS) +libmutter_cogl_path_la_LDFLAGS = \ + -export-dynamic \ + -export-symbols-regex "^(cogl|cogl2)_(framebuffer|path|is|clip|[sg]et)_.*" \ + -no-undefined \ + -avoid-version \ + -rpath $(mutterlibdir) + +AM_CPPFLAGS = \ + -DCOGL_COMPILATION \ + -DG_LOG_DOMAIN=\"CoglPath\" \ + -I$(srcdir)/tesselator \ + -I$(top_srcdir)/cogl \ + -I$(top_builddir)/cogl \ + -I$(top_srcdir)/cogl/winsys \ + -I$(top_srcdir) \ + -I$(top_builddir) + +cogl_base_includedir = $(includedir)/mutter +cogl_pathheadersdir = $(cogl_base_includedir)/cogl/cogl-path +cogl_pathheaders_HEADERS = $(source_h) +nodist_cogl_pathheaders_HEADERS = cogl-path-enum-types.h +pc_files = mutter-cogl-path-1.0.pc +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = $(pc_files) +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/build/autotools/Makefile.am.enums $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign cogl-path/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign cogl-path/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(top_srcdir)/build/autotools/Makefile.am.enums $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +mutter-cogl-path-1.0.pc: $(top_builddir)/config.status $(srcdir)/mutter-cogl-path-1.0.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +install-mutterlibLTLIBRARIES: $(mutterlib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(mutterlib_LTLIBRARIES)'; test -n "$(mutterlibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(mutterlibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(mutterlibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(mutterlibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(mutterlibdir)"; \ + } + +uninstall-mutterlibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(mutterlib_LTLIBRARIES)'; test -n "$(mutterlibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(mutterlibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(mutterlibdir)/$$f"; \ + done + +clean-mutterlibLTLIBRARIES: + -test -z "$(mutterlib_LTLIBRARIES)" || rm -f $(mutterlib_LTLIBRARIES) + @list='$(mutterlib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +tesselator/$(am__dirstamp): + @$(MKDIR_P) tesselator + @: > tesselator/$(am__dirstamp) +tesselator/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) tesselator/$(DEPDIR) + @: > tesselator/$(DEPDIR)/$(am__dirstamp) +tesselator/libmutter_cogl_path_la-dict.lo: tesselator/$(am__dirstamp) \ + tesselator/$(DEPDIR)/$(am__dirstamp) +tesselator/libmutter_cogl_path_la-geom.lo: tesselator/$(am__dirstamp) \ + tesselator/$(DEPDIR)/$(am__dirstamp) +tesselator/libmutter_cogl_path_la-mesh.lo: tesselator/$(am__dirstamp) \ + tesselator/$(DEPDIR)/$(am__dirstamp) +tesselator/libmutter_cogl_path_la-normal.lo: \ + tesselator/$(am__dirstamp) \ + tesselator/$(DEPDIR)/$(am__dirstamp) +tesselator/libmutter_cogl_path_la-priorityq.lo: \ + tesselator/$(am__dirstamp) \ + tesselator/$(DEPDIR)/$(am__dirstamp) +tesselator/libmutter_cogl_path_la-render.lo: \ + tesselator/$(am__dirstamp) \ + tesselator/$(DEPDIR)/$(am__dirstamp) +tesselator/libmutter_cogl_path_la-sweep.lo: \ + tesselator/$(am__dirstamp) \ + tesselator/$(DEPDIR)/$(am__dirstamp) +tesselator/libmutter_cogl_path_la-tess.lo: tesselator/$(am__dirstamp) \ + tesselator/$(DEPDIR)/$(am__dirstamp) +tesselator/libmutter_cogl_path_la-tessmono.lo: \ + tesselator/$(am__dirstamp) \ + tesselator/$(DEPDIR)/$(am__dirstamp) + +libmutter-cogl-path.la: $(libmutter_cogl_path_la_OBJECTS) $(libmutter_cogl_path_la_DEPENDENCIES) $(EXTRA_libmutter_cogl_path_la_DEPENDENCIES) + $(AM_V_CCLD)$(libmutter_cogl_path_la_LINK) -rpath $(mutterlibdir) $(libmutter_cogl_path_la_OBJECTS) $(libmutter_cogl_path_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f tesselator/*.$(OBJEXT) + -rm -f tesselator/*.lo + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmutter_cogl_path_la-cogl-path-enum-types.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmutter_cogl_path_la-cogl-path.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tesselator/$(DEPDIR)/libmutter_cogl_path_la-dict.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tesselator/$(DEPDIR)/libmutter_cogl_path_la-geom.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tesselator/$(DEPDIR)/libmutter_cogl_path_la-mesh.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tesselator/$(DEPDIR)/libmutter_cogl_path_la-normal.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tesselator/$(DEPDIR)/libmutter_cogl_path_la-priorityq.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tesselator/$(DEPDIR)/libmutter_cogl_path_la-render.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tesselator/$(DEPDIR)/libmutter_cogl_path_la-sweep.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tesselator/$(DEPDIR)/libmutter_cogl_path_la-tess.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tesselator/$(DEPDIR)/libmutter_cogl_path_la-tessmono.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +tesselator/libmutter_cogl_path_la-dict.lo: tesselator/dict.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_path_la_CFLAGS) $(CFLAGS) -MT tesselator/libmutter_cogl_path_la-dict.lo -MD -MP -MF tesselator/$(DEPDIR)/libmutter_cogl_path_la-dict.Tpo -c -o tesselator/libmutter_cogl_path_la-dict.lo `test -f 'tesselator/dict.c' || echo '$(srcdir)/'`tesselator/dict.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tesselator/$(DEPDIR)/libmutter_cogl_path_la-dict.Tpo tesselator/$(DEPDIR)/libmutter_cogl_path_la-dict.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tesselator/dict.c' object='tesselator/libmutter_cogl_path_la-dict.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_path_la_CFLAGS) $(CFLAGS) -c -o tesselator/libmutter_cogl_path_la-dict.lo `test -f 'tesselator/dict.c' || echo '$(srcdir)/'`tesselator/dict.c + +tesselator/libmutter_cogl_path_la-geom.lo: tesselator/geom.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_path_la_CFLAGS) $(CFLAGS) -MT tesselator/libmutter_cogl_path_la-geom.lo -MD -MP -MF tesselator/$(DEPDIR)/libmutter_cogl_path_la-geom.Tpo -c -o tesselator/libmutter_cogl_path_la-geom.lo `test -f 'tesselator/geom.c' || echo '$(srcdir)/'`tesselator/geom.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tesselator/$(DEPDIR)/libmutter_cogl_path_la-geom.Tpo tesselator/$(DEPDIR)/libmutter_cogl_path_la-geom.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tesselator/geom.c' object='tesselator/libmutter_cogl_path_la-geom.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_path_la_CFLAGS) $(CFLAGS) -c -o tesselator/libmutter_cogl_path_la-geom.lo `test -f 'tesselator/geom.c' || echo '$(srcdir)/'`tesselator/geom.c + +tesselator/libmutter_cogl_path_la-mesh.lo: tesselator/mesh.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_path_la_CFLAGS) $(CFLAGS) -MT tesselator/libmutter_cogl_path_la-mesh.lo -MD -MP -MF tesselator/$(DEPDIR)/libmutter_cogl_path_la-mesh.Tpo -c -o tesselator/libmutter_cogl_path_la-mesh.lo `test -f 'tesselator/mesh.c' || echo '$(srcdir)/'`tesselator/mesh.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tesselator/$(DEPDIR)/libmutter_cogl_path_la-mesh.Tpo tesselator/$(DEPDIR)/libmutter_cogl_path_la-mesh.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tesselator/mesh.c' object='tesselator/libmutter_cogl_path_la-mesh.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_path_la_CFLAGS) $(CFLAGS) -c -o tesselator/libmutter_cogl_path_la-mesh.lo `test -f 'tesselator/mesh.c' || echo '$(srcdir)/'`tesselator/mesh.c + +tesselator/libmutter_cogl_path_la-normal.lo: tesselator/normal.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_path_la_CFLAGS) $(CFLAGS) -MT tesselator/libmutter_cogl_path_la-normal.lo -MD -MP -MF tesselator/$(DEPDIR)/libmutter_cogl_path_la-normal.Tpo -c -o tesselator/libmutter_cogl_path_la-normal.lo `test -f 'tesselator/normal.c' || echo '$(srcdir)/'`tesselator/normal.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tesselator/$(DEPDIR)/libmutter_cogl_path_la-normal.Tpo tesselator/$(DEPDIR)/libmutter_cogl_path_la-normal.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tesselator/normal.c' object='tesselator/libmutter_cogl_path_la-normal.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_path_la_CFLAGS) $(CFLAGS) -c -o tesselator/libmutter_cogl_path_la-normal.lo `test -f 'tesselator/normal.c' || echo '$(srcdir)/'`tesselator/normal.c + +tesselator/libmutter_cogl_path_la-priorityq.lo: tesselator/priorityq.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_path_la_CFLAGS) $(CFLAGS) -MT tesselator/libmutter_cogl_path_la-priorityq.lo -MD -MP -MF tesselator/$(DEPDIR)/libmutter_cogl_path_la-priorityq.Tpo -c -o tesselator/libmutter_cogl_path_la-priorityq.lo `test -f 'tesselator/priorityq.c' || echo '$(srcdir)/'`tesselator/priorityq.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tesselator/$(DEPDIR)/libmutter_cogl_path_la-priorityq.Tpo tesselator/$(DEPDIR)/libmutter_cogl_path_la-priorityq.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tesselator/priorityq.c' object='tesselator/libmutter_cogl_path_la-priorityq.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_path_la_CFLAGS) $(CFLAGS) -c -o tesselator/libmutter_cogl_path_la-priorityq.lo `test -f 'tesselator/priorityq.c' || echo '$(srcdir)/'`tesselator/priorityq.c + +tesselator/libmutter_cogl_path_la-render.lo: tesselator/render.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_path_la_CFLAGS) $(CFLAGS) -MT tesselator/libmutter_cogl_path_la-render.lo -MD -MP -MF tesselator/$(DEPDIR)/libmutter_cogl_path_la-render.Tpo -c -o tesselator/libmutter_cogl_path_la-render.lo `test -f 'tesselator/render.c' || echo '$(srcdir)/'`tesselator/render.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tesselator/$(DEPDIR)/libmutter_cogl_path_la-render.Tpo tesselator/$(DEPDIR)/libmutter_cogl_path_la-render.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tesselator/render.c' object='tesselator/libmutter_cogl_path_la-render.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_path_la_CFLAGS) $(CFLAGS) -c -o tesselator/libmutter_cogl_path_la-render.lo `test -f 'tesselator/render.c' || echo '$(srcdir)/'`tesselator/render.c + +tesselator/libmutter_cogl_path_la-sweep.lo: tesselator/sweep.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_path_la_CFLAGS) $(CFLAGS) -MT tesselator/libmutter_cogl_path_la-sweep.lo -MD -MP -MF tesselator/$(DEPDIR)/libmutter_cogl_path_la-sweep.Tpo -c -o tesselator/libmutter_cogl_path_la-sweep.lo `test -f 'tesselator/sweep.c' || echo '$(srcdir)/'`tesselator/sweep.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tesselator/$(DEPDIR)/libmutter_cogl_path_la-sweep.Tpo tesselator/$(DEPDIR)/libmutter_cogl_path_la-sweep.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tesselator/sweep.c' object='tesselator/libmutter_cogl_path_la-sweep.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_path_la_CFLAGS) $(CFLAGS) -c -o tesselator/libmutter_cogl_path_la-sweep.lo `test -f 'tesselator/sweep.c' || echo '$(srcdir)/'`tesselator/sweep.c + +tesselator/libmutter_cogl_path_la-tess.lo: tesselator/tess.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_path_la_CFLAGS) $(CFLAGS) -MT tesselator/libmutter_cogl_path_la-tess.lo -MD -MP -MF tesselator/$(DEPDIR)/libmutter_cogl_path_la-tess.Tpo -c -o tesselator/libmutter_cogl_path_la-tess.lo `test -f 'tesselator/tess.c' || echo '$(srcdir)/'`tesselator/tess.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tesselator/$(DEPDIR)/libmutter_cogl_path_la-tess.Tpo tesselator/$(DEPDIR)/libmutter_cogl_path_la-tess.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tesselator/tess.c' object='tesselator/libmutter_cogl_path_la-tess.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_path_la_CFLAGS) $(CFLAGS) -c -o tesselator/libmutter_cogl_path_la-tess.lo `test -f 'tesselator/tess.c' || echo '$(srcdir)/'`tesselator/tess.c + +tesselator/libmutter_cogl_path_la-tessmono.lo: tesselator/tessmono.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_path_la_CFLAGS) $(CFLAGS) -MT tesselator/libmutter_cogl_path_la-tessmono.lo -MD -MP -MF tesselator/$(DEPDIR)/libmutter_cogl_path_la-tessmono.Tpo -c -o tesselator/libmutter_cogl_path_la-tessmono.lo `test -f 'tesselator/tessmono.c' || echo '$(srcdir)/'`tesselator/tessmono.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tesselator/$(DEPDIR)/libmutter_cogl_path_la-tessmono.Tpo tesselator/$(DEPDIR)/libmutter_cogl_path_la-tessmono.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tesselator/tessmono.c' object='tesselator/libmutter_cogl_path_la-tessmono.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_path_la_CFLAGS) $(CFLAGS) -c -o tesselator/libmutter_cogl_path_la-tessmono.lo `test -f 'tesselator/tessmono.c' || echo '$(srcdir)/'`tesselator/tessmono.c + +libmutter_cogl_path_la-cogl-path.lo: cogl-path.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_path_la_CFLAGS) $(CFLAGS) -MT libmutter_cogl_path_la-cogl-path.lo -MD -MP -MF $(DEPDIR)/libmutter_cogl_path_la-cogl-path.Tpo -c -o libmutter_cogl_path_la-cogl-path.lo `test -f 'cogl-path.c' || echo '$(srcdir)/'`cogl-path.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmutter_cogl_path_la-cogl-path.Tpo $(DEPDIR)/libmutter_cogl_path_la-cogl-path.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cogl-path.c' object='libmutter_cogl_path_la-cogl-path.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_path_la_CFLAGS) $(CFLAGS) -c -o libmutter_cogl_path_la-cogl-path.lo `test -f 'cogl-path.c' || echo '$(srcdir)/'`cogl-path.c + +libmutter_cogl_path_la-cogl-path-enum-types.lo: cogl-path-enum-types.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_path_la_CFLAGS) $(CFLAGS) -MT libmutter_cogl_path_la-cogl-path-enum-types.lo -MD -MP -MF $(DEPDIR)/libmutter_cogl_path_la-cogl-path-enum-types.Tpo -c -o libmutter_cogl_path_la-cogl-path-enum-types.lo `test -f 'cogl-path-enum-types.c' || echo '$(srcdir)/'`cogl-path-enum-types.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmutter_cogl_path_la-cogl-path-enum-types.Tpo $(DEPDIR)/libmutter_cogl_path_la-cogl-path-enum-types.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cogl-path-enum-types.c' object='libmutter_cogl_path_la-cogl-path-enum-types.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmutter_cogl_path_la_CFLAGS) $(CFLAGS) -c -o libmutter_cogl_path_la-cogl-path-enum-types.lo `test -f 'cogl-path-enum-types.c' || echo '$(srcdir)/'`cogl-path-enum-types.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + -rm -rf tesselator/.libs tesselator/_libs +install-pkgconfigDATA: $(pkgconfig_DATA) + @$(NORMAL_INSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ + done + +uninstall-pkgconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) +install-cogl_pathheadersHEADERS: $(cogl_pathheaders_HEADERS) + @$(NORMAL_INSTALL) + @list='$(cogl_pathheaders_HEADERS)'; test -n "$(cogl_pathheadersdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(cogl_pathheadersdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(cogl_pathheadersdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(cogl_pathheadersdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(cogl_pathheadersdir)" || exit $$?; \ + done + +uninstall-cogl_pathheadersHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(cogl_pathheaders_HEADERS)'; test -n "$(cogl_pathheadersdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(cogl_pathheadersdir)'; $(am__uninstall_files_from_dir) +install-nodist_cogl_pathheadersHEADERS: $(nodist_cogl_pathheaders_HEADERS) + @$(NORMAL_INSTALL) + @list='$(nodist_cogl_pathheaders_HEADERS)'; test -n "$(cogl_pathheadersdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(cogl_pathheadersdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(cogl_pathheadersdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(cogl_pathheadersdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(cogl_pathheadersdir)" || exit $$?; \ + done + +uninstall-nodist_cogl_pathheadersHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nodist_cogl_pathheaders_HEADERS)'; test -n "$(cogl_pathheadersdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(cogl_pathheadersdir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(mutterlibdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(cogl_pathheadersdir)" "$(DESTDIR)$(cogl_pathheadersdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f tesselator/$(DEPDIR)/$(am__dirstamp) + -rm -f tesselator/$(am__dirstamp) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-mutterlibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) tesselator/$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-cogl_pathheadersHEADERS \ + install-mutterlibLTLIBRARIES \ + install-nodist_cogl_pathheadersHEADERS install-pkgconfigDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) tesselator/$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-cogl_pathheadersHEADERS \ + uninstall-mutterlibLTLIBRARIES \ + uninstall-nodist_cogl_pathheadersHEADERS \ + uninstall-pkgconfigDATA + +.MAKE: all check install install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-mutterlibLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am \ + install-cogl_pathheadersHEADERS install-data install-data-am \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-mutterlibLTLIBRARIES \ + install-nodist_cogl_pathheadersHEADERS install-pdf \ + install-pdf-am install-pkgconfigDATA install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-cogl_pathheadersHEADERS \ + uninstall-mutterlibLTLIBRARIES \ + uninstall-nodist_cogl_pathheadersHEADERS \ + uninstall-pkgconfigDATA + +.PRECIOUS: Makefile + + +# Basic sanity checks +$(if $(GLIB_MKENUMS),,$(error Need to define GLIB_MKENUMS)) + +$(if $(or $(glib_enum_h), \ + $(glib_enum_c)),, \ + $(error Need to define glib_enum_h and glib_enum_c)) + +$(if $(glib_enum_headers),,$(error Need to define glib_enum_headers)) + +stamp-enum-types: $(enum_headers) $(enum_tmpl_h) + $(AM_V_GEN)$(GLIB_MKENUMS) \ + --template $(enum_tmpl_h) \ + $(enum_headers) > xgen-eh \ + && (cmp -s xgen-eh $(glib_enum_h) || cp -f xgen-eh $(glib_enum_h)) \ + && rm -f xgen-eh \ + && echo timestamp > $(@F) + +$(glib_enum_h): stamp-enum-types + @true + +$(glib_enum_c): $(enum_headers) $(enum_tmpl_h) $(enum_tmpl_c) + $(AM_V_GEN)$(GLIB_MKENUMS) \ + --template $(enum_tmpl_c) \ + $(enum_headers) > xgen-ec \ + && cp -f xgen-ec $(glib_enum_c) \ + && rm -f xgen-ec + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cogl/cogl-path/cogl-path-enum-types.c.in b/cogl/cogl-path/cogl-path-enum-types.c.in new file mode 100644 index 0000000..661e81c --- /dev/null +++ b/cogl/cogl-path/cogl-path-enum-types.c.in @@ -0,0 +1,50 @@ +/*** BEGIN file-header ***/ +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +/* We need to undefine this so that we will be sure to include + * cogl-path.h instead of cogl2-path.h when we include the framebuffer + * header. Otherwise it will include both headers and it won't + * compile. */ +#undef COGL_ENABLE_EXPERIMENTAL_2_0_API + +#include "cogl-path-enum-types.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 ***/ diff --git a/cogl/cogl-path/cogl-path-enum-types.h.in b/cogl/cogl-path/cogl-path-enum-types.h.in new file mode 100644 index 0000000..071686a --- /dev/null +++ b/cogl/cogl-path/cogl-path-enum-types.h.in @@ -0,0 +1,25 @@ +/*** BEGIN file-header ***/ +#ifndef __COGL_PATH_ENUM_TYPES_H__ +#define __COGL_PATH_ENUM_TYPES_H__ + +#include + +G_BEGIN_DECLS + +/*** END file-header ***/ + +/*** BEGIN file-production ***/ +/* enumerations from "@filename@" */ +/*** END file-production ***/ + +/*** BEGIN file-tail ***/ +G_END_DECLS + +#endif /* __COGL_PATH_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 ***/ diff --git a/cogl/cogl-path/cogl-path-functions.h b/cogl/cogl-path/cogl-path-functions.h new file mode 100644 index 0000000..489b25c --- /dev/null +++ b/cogl/cogl-path/cogl-path-functions.h @@ -0,0 +1,541 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009,2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_PATH_FUNCTIONS_H__ +#define __COGL_PATH_FUNCTIONS_H__ + +#include +#ifdef COGL_COMPILATION +#include "cogl-context.h" +#else +#include +#endif +#include + +COGL_BEGIN_DECLS + +/** + * cogl_path_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_path_get_gtype (void); + +#define cogl_path_new cogl2_path_new +/** + * cogl_path_new: + * + * Creates a new, empty path object. The default fill rule is + * %COGL_PATH_FILL_RULE_EVEN_ODD. + * + * Return value: A pointer to a newly allocated #CoglPath, which can + * be freed using cogl_object_unref(). + * + * Since: 2.0 + */ +CoglPath * +cogl_path_new (void); + +/** + * cogl_path_copy: + * @path: A #CoglPath object + * + * Returns a new copy of the path in @path. The new path has a + * reference count of 1 so you should unref it with + * cogl_object_unref() if you no longer need it. + * + * Internally the path will share the data until one of the paths is + * modified so copying paths should be relatively cheap. + * + * Return value: (transfer full): a copy of the path in @path. + * + * Since: 2.0 + */ +CoglPath * +cogl_path_copy (CoglPath *path); + +/** + * cogl_is_path: + * @object: A #CoglObject + * + * Gets whether the given object references an existing path object. + * + * Return value: %TRUE if the object references a #CoglPath, + * %FALSE otherwise. + * + * Since: 2.0 + */ +CoglBool +cogl_is_path (void *object); + +#define cogl_path_move_to cogl2_path_move_to +/** + * cogl_path_move_to: + * @x: X coordinate of the pen location to move to. + * @y: Y coordinate of the pen location to move to. + * + * Moves the pen to the given location. If there is an existing path + * this will start a new disjoint subpath. + * + * Since: 2.0 + */ +void +cogl_path_move_to (CoglPath *path, + float x, + float y); + +#define cogl_path_rel_move_to cogl2_path_rel_move_to +/** + * cogl_path_rel_move_to: + * @x: X offset from the current pen location to move the pen to. + * @y: Y offset from the current pen location to move the pen to. + * + * Moves the pen to the given offset relative to the current pen + * location. If there is an existing path this will start a new + * disjoint subpath. + * + * Since: 2.0 + */ +void +cogl_path_rel_move_to (CoglPath *path, + float x, + float y); + +#define cogl_path_line_to cogl2_path_line_to +/** + * cogl_path_line_to: + * @x: X coordinate of the end line vertex + * @y: Y coordinate of the end line vertex + * + * Adds a straight line segment to the current path that ends at the + * given coordinates. + * + * Since: 2.0 + */ +void +cogl_path_line_to (CoglPath *path, + float x, + float y); + +#define cogl_path_rel_line_to cogl2_path_rel_line_to +/** + * cogl_path_rel_line_to: + * @x: X offset from the current pen location of the end line vertex + * @y: Y offset from the current pen location of the end line vertex + * + * Adds a straight line segment to the current path that ends at the + * given coordinates relative to the current pen location. + * + * Since: 2.0 + */ +void +cogl_path_rel_line_to (CoglPath *path, + float x, + float y); + +#define cogl_path_arc cogl2_path_arc +/** + * cogl_path_arc: + * @center_x: X coordinate of the elliptical arc center + * @center_y: Y coordinate of the elliptical arc center + * @radius_x: X radius of the elliptical arc + * @radius_y: Y radius of the elliptical arc + * @angle_1: Angle in degrees at which the arc begin + * @angle_2: Angle in degrees at which the arc ends + * + * Adds an elliptical arc segment to the current path. A straight line + * segment will link the current pen location with the first vertex + * of the arc. If you perform a move_to to the arcs start just before + * drawing it you create a free standing arc. + * + * The angles are measured in degrees where 0° is in the direction of + * the positive X axis and 90° is in the direction of the positive Y + * axis. The angle of the arc begins at @angle_1 and heads towards + * @angle_2 (so if @angle_2 is less than @angle_1 it will decrease, + * otherwise it will increase). + * + * Since: 2.0 + */ +void +cogl_path_arc (CoglPath *path, + float center_x, + float center_y, + float radius_x, + float radius_y, + float angle_1, + float angle_2); + +#define cogl_path_curve_to cogl2_path_curve_to +/** + * cogl_path_curve_to: + * @x_1: X coordinate of the second bezier control point + * @y_1: Y coordinate of the second bezier control point + * @x_2: X coordinate of the third bezier control point + * @y_2: Y coordinate of the third bezier control point + * @x_3: X coordinate of the fourth bezier control point + * @y_3: Y coordinate of the fourth bezier control point + * + * Adds a cubic bezier curve segment to the current path with the given + * second, third and fourth control points and using current pen location + * as the first control point. + * + * Since: 2.0 + */ +void +cogl_path_curve_to (CoglPath *path, + float x_1, + float y_1, + float x_2, + float y_2, + float x_3, + float y_3); + +#define cogl_path_rel_curve_to cogl2_path_rel_curve_to +/** + * cogl_path_rel_curve_to: + * @x_1: X coordinate of the second bezier control point + * @y_1: Y coordinate of the second bezier control point + * @x_2: X coordinate of the third bezier control point + * @y_2: Y coordinate of the third bezier control point + * @x_3: X coordinate of the fourth bezier control point + * @y_3: Y coordinate of the fourth bezier control point + * + * Adds a cubic bezier curve segment to the current path with the given + * second, third and fourth control points and using current pen location + * as the first control point. The given coordinates are relative to the + * current pen location. + * + * Since: 2.0 + */ +void +cogl_path_rel_curve_to (CoglPath *path, + float x_1, + float y_1, + float x_2, + float y_2, + float x_3, + float y_3); + +#define cogl_path_close cogl2_path_close +/** + * cogl_path_close: + * + * Closes the path being constructed by adding a straight line segment + * to it that ends at the first vertex of the path. + * + * Since: 2.0 + */ +void +cogl_path_close (CoglPath *path); + +#define cogl_path_line cogl2_path_line +/** + * cogl_path_line: + * @x_1: X coordinate of the start line vertex + * @y_1: Y coordinate of the start line vertex + * @x_2: X coordinate of the end line vertex + * @y_2: Y coordinate of the end line vertex + * + * Constructs a straight line shape starting and ending at the given + * coordinates. If there is an existing path this will start a new + * disjoint sub-path. + * + * Since: 2.0 + */ +void +cogl_path_line (CoglPath *path, + float x_1, + float y_1, + float x_2, + float y_2); + +#define cogl_path_polyline cogl2_path_polyline +/** + * cogl_path_polyline: + * @coords: (in) (array) (transfer none): A pointer to the first element of an + * array of fixed-point values that specify the vertex coordinates. + * @num_points: The total number of vertices. + * + * Constructs a series of straight line segments, starting from the + * first given vertex coordinate. If there is an existing path this + * will start a new disjoint sub-path. Each subsequent segment starts + * where the previous one ended and ends at the next given vertex + * coordinate. + * + * The coords array must contain 2 * num_points values. The first value + * represents the X coordinate of the first vertex, the second value + * represents the Y coordinate of the first vertex, continuing in the same + * fashion for the rest of the vertices. (num_points - 1) segments will + * be constructed. + * + * Since: 2.0 + */ +void +cogl_path_polyline (CoglPath *path, + const float *coords, + int num_points); + +#define cogl_path_polygon cogl2_path_polygon +/** + * cogl_path_polygon: + * @coords: (in) (array) (transfer none): A pointer to the first element of + * an array of fixed-point values that specify the vertex coordinates. + * @num_points: The total number of vertices. + * + * Constructs a polygonal shape of the given number of vertices. If + * there is an existing path this will start a new disjoint sub-path. + * + * The coords array must contain 2 * num_points values. The first value + * represents the X coordinate of the first vertex, the second value + * represents the Y coordinate of the first vertex, continuing in the same + * fashion for the rest of the vertices. + * + * Since: 2.0 + */ +void +cogl_path_polygon (CoglPath *path, + const float *coords, + int num_points); + +#define cogl_path_rectangle cogl2_path_rectangle +/** + * cogl_path_rectangle: + * @x_1: X coordinate of the top-left corner. + * @y_1: Y coordinate of the top-left corner. + * @x_2: X coordinate of the bottom-right corner. + * @y_2: Y coordinate of the bottom-right corner. + * + * Constructs a rectangular shape at the given coordinates. If there + * is an existing path this will start a new disjoint sub-path. + * + * Since: 2.0 + */ +void +cogl_path_rectangle (CoglPath *path, + float x_1, + float y_1, + float x_2, + float y_2); + +#define cogl_path_ellipse cogl2_path_ellipse +/** + * cogl_path_ellipse: + * @center_x: X coordinate of the ellipse center + * @center_y: Y coordinate of the ellipse center + * @radius_x: X radius of the ellipse + * @radius_y: Y radius of the ellipse + * + * Constructs an ellipse shape. If there is an existing path this will + * start a new disjoint sub-path. + * + * Since: 2.0 + */ +void +cogl_path_ellipse (CoglPath *path, + float center_x, + float center_y, + float radius_x, + float radius_y); + +#define cogl_path_round_rectangle cogl2_path_round_rectangle +/** + * cogl_path_round_rectangle: + * @x_1: X coordinate of the top-left corner. + * @y_1: Y coordinate of the top-left corner. + * @x_2: X coordinate of the bottom-right corner. + * @y_2: Y coordinate of the bottom-right corner. + * @radius: Radius of the corner arcs. + * @arc_step: Angle increment resolution for subdivision of + * the corner arcs. + * + * Constructs a rectangular shape with rounded corners. If there is an + * existing path this will start a new disjoint sub-path. + * + * Since: 2.0 + */ +void +cogl_path_round_rectangle (CoglPath *path, + float x_1, + float y_1, + float x_2, + float y_2, + float radius, + float arc_step); + +#define cogl_path_set_fill_rule cogl2_path_set_fill_rule +/** + * cogl_path_set_fill_rule: + * @fill_rule: The new fill rule. + * + * Sets the fill rule of the current path to @fill_rule. This will + * affect how the path is filled when cogl_path_fill() is later + * called. Note that the fill rule state is attached to the path so + * calling cogl_get_path() will preserve the fill rule and calling + * cogl_path_new() will reset the fill rule back to the default. + * + * Since: 2.0 + */ +void +cogl_path_set_fill_rule (CoglPath *path, CoglPathFillRule fill_rule); + +#define cogl_path_get_fill_rule cogl2_path_get_fill_rule +/** + * cogl_path_get_fill_rule: + * + * Retrieves the fill rule set using cogl_path_set_fill_rule(). + * + * Return value: the fill rule that is used for the current path. + * + * Since: 2.0 + */ +CoglPathFillRule +cogl_path_get_fill_rule (CoglPath *path); + +#define cogl_path_fill cogl2_path_fill +/** + * cogl_path_fill: + * + * Fills the interior of the constructed shape using the current + * drawing color. + * + * The interior of the shape is determined using the fill rule of the + * path. See %CoglPathFillRule for details. + * + * The result of referencing sliced textures in your current + * pipeline when filling a path are undefined. You should pass + * the %COGL_TEXTURE_NO_SLICING flag when loading any texture you will + * use while filling a path. + * + * Since: 2.0 + */ +void +cogl_path_fill (CoglPath *path); + +/** + * cogl_framebuffer_fill_path: + * @framebuffer: A #CoglFramebuffer + * @pipeline: A #CoglPipeline to render with + * @path: The #CoglPath to fill + * + * Fills the interior of the path using the fragment operations + * defined by the pipeline. + * + * The interior of the shape is determined using the fill rule of the + * path. See %CoglPathFillRule for details. + * + * The result of referencing sliced textures in your current + * pipeline when filling a path are undefined. You should pass + * the %COGL_TEXTURE_NO_SLICING flag when loading any texture you will + * use while filling a path. + * + * Stability: unstable + * Deprecated: 1.16: Use cogl_path_fill() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_path_fill) +void +cogl_framebuffer_fill_path (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglPath *path); + +#define cogl_path_stroke cogl2_path_stroke +/** + * cogl_path_stroke: + * + * Strokes the constructed shape using the current drawing color and a + * width of 1 pixel (regardless of the current transformation + * matrix). + * + * Since: 2.0 + */ +void +cogl_path_stroke (CoglPath *path); + +/** + * cogl_framebuffer_stroke_path: + * @framebuffer: A #CoglFramebuffer + * @pipeline: A #CoglPipeline to render with + * @path: The #CoglPath to stroke + * + * Strokes the edge of the path using the fragment operations defined + * by the pipeline. The stroke line will have a width of 1 pixel + * regardless of the current transformation matrix. + * + * Stability: unstable + * Deprecated: 1.16: Use cogl_path_stroke() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_path_stroke) +void +cogl_framebuffer_stroke_path (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglPath *path); + +/** + * cogl_framebuffer_push_path_clip: + * @framebuffer: A #CoglFramebuffer pointer + * @path: The path to clip with. + * + * Sets a new clipping area using the silhouette of the specified, + * filled @path. The clipping area is intersected with the previous + * clipping area. To restore the previous clipping area, call + * cogl_framebuffer_pop_clip(). + * + * Since: 1.0 + * Stability: unstable + */ +void +cogl_framebuffer_push_path_clip (CoglFramebuffer *framebuffer, + CoglPath *path); + +#define cogl_clip_push_from_path cogl2_clip_push_from_path +/** + * cogl_clip_push_from_path: + * @path: The path to clip with. + * + * Sets a new clipping area using the silhouette of the specified, + * filled @path. The clipping area is intersected with the previous + * clipping area. To restore the previous clipping area, call + * call cogl_clip_pop(). + * + * Since: 1.8 + * Stability: Unstable + * Deprecated: 1.16: Use cogl_framebuffer_push_path_clip() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_framebuffer_push_path_clip) +void +cogl_clip_push_from_path (CoglPath *path); + +COGL_END_DECLS + +#endif /* __COGL_PATH_FUNCTIONS_H__ */ + diff --git a/cogl/cogl-path/cogl-path-private.h b/cogl/cogl-path/cogl-path-private.h new file mode 100644 index 0000000..078e58f --- /dev/null +++ b/cogl/cogl-path/cogl-path-private.h @@ -0,0 +1,126 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_PATH_PRIVATE_H +#define __COGL_PATH_PRIVATE_H + +#include "cogl-object.h" +#include "cogl-attribute-private.h" + +typedef struct _floatVec2 +{ + float x; + float y; +} floatVec2; + +typedef struct _CoglPathNode +{ + float x; + float y; + unsigned int path_size; +} CoglPathNode; + +typedef struct _CoglBezQuad +{ + floatVec2 p1; + floatVec2 p2; + floatVec2 p3; +} CoglBezQuad; + +typedef struct _CoglBezCubic +{ + floatVec2 p1; + floatVec2 p2; + floatVec2 p3; + floatVec2 p4; +} CoglBezCubic; + +typedef struct _CoglPathData CoglPathData; + +struct _CoglPath +{ + CoglObject _parent; + + CoglPathData *data; +}; + +#define COGL_PATH_N_ATTRIBUTES 2 + +struct _CoglPathData +{ + unsigned int ref_count; + + CoglContext *context; + + CoglPathFillRule fill_rule; + + GArray *path_nodes; + + floatVec2 path_start; + floatVec2 path_pen; + unsigned int last_path; + floatVec2 path_nodes_min; + floatVec2 path_nodes_max; + + CoglAttributeBuffer *fill_attribute_buffer; + CoglIndices *fill_vbo_indices; + unsigned int fill_vbo_n_indices; + CoglAttribute *fill_attributes[COGL_PATH_N_ATTRIBUTES + 1]; + CoglPrimitive *fill_primitive; + + CoglAttributeBuffer *stroke_attribute_buffer; + CoglAttribute **stroke_attributes; + unsigned int stroke_n_attributes; + + /* This is used as an optimisation for when the path contains a + single contour specified using cogl2_path_rectangle. Cogl is more + optimised to handle rectangles than paths so we can detect this + case and divert to the journal or a rectangle clip. If it is TRUE + then the entire path can be described by calling + _cogl_path_get_bounds */ + CoglBool is_rectangle; +}; + +void +_cogl_add_path_to_stencil_buffer (CoglPath *path, + CoglBool merge, + CoglBool need_clear); + +void +_cogl_path_get_bounds (CoglPath *path, + float *min_x, + float *min_y, + float *max_x, + float *max_y); + +CoglBool +_cogl_path_is_rectangle (CoglPath *path); + +#endif /* __COGL_PATH_PRIVATE_H */ diff --git a/cogl/cogl-path/cogl-path-types.h b/cogl/cogl-path/cogl-path-types.h new file mode 100644 index 0000000..53c06ee --- /dev/null +++ b/cogl/cogl-path/cogl-path-types.h @@ -0,0 +1,85 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009,2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_PATH_TYPES_H__ +#define __COGL_PATH_TYPES_H__ + +#include + +COGL_BEGIN_DECLS + +typedef struct _CoglPath CoglPath; + +/** + * CoglPathFillRule: + * @COGL_PATH_FILL_RULE_NON_ZERO: Each time the line crosses an edge of + * the path from left to right one is added to a counter and each time + * it crosses from right to left the counter is decremented. If the + * counter is non-zero then the point will be filled. See . + * @COGL_PATH_FILL_RULE_EVEN_ODD: If the line crosses an edge of the + * path an odd number of times then the point will filled, otherwise + * it won't. See . + * + * #CoglPathFillRule is used to determine how a path is filled. There + * are two options - 'non-zero' and 'even-odd'. To work out whether any + * point will be filled imagine drawing an infinetely long line in any + * direction from that point. The number of times and the direction + * that the edges of the path crosses this line determines whether the + * line is filled as described below. Any open sub paths are treated + * as if there was an extra line joining the first point and the last + * point. + * + * The default fill rule when creating a path is %COGL_PATH_FILL_RULE_EVEN_ODD. + * + *

+ * Example of filling various paths using the non-zero rule + * + *
+ * + *
+ * Example of filling various paths using the even-odd rule + * + *
+ * + * Since: 1.4 + */ +typedef enum { + COGL_PATH_FILL_RULE_NON_ZERO, + COGL_PATH_FILL_RULE_EVEN_ODD +} CoglPathFillRule; + +COGL_END_DECLS + +#endif /* __COGL_PATH_TYPES_H__ */ diff --git a/cogl/cogl-path/cogl-path.c b/cogl/cogl-path/cogl-path.c new file mode 100644 index 0000000..8adf542 --- /dev/null +++ b/cogl/cogl-path/cogl-path.c @@ -0,0 +1,1602 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2010,2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Ivan Leben + * Øyvind Kolås + * Neil Roberts + * Robert Bragg + */ + +#include "cogl-config.h" + +#include "cogl-util.h" +#include "cogl-object.h" +#include "cogl-context-private.h" +#include "cogl-journal-private.h" +#include "cogl-pipeline-private.h" +#include "cogl-framebuffer-private.h" +#include "cogl-primitive-private.h" +#include "cogl-texture-private.h" +#include "cogl-primitives-private.h" +#include "cogl-private.h" +#include "cogl-attribute-private.h" +#include "cogl1-context.h" +#include "tesselator/tesselator.h" + +#include "cogl-path/cogl-path.h" +#include "cogl-path-private.h" +#include "cogl-gtype-private.h" + +#include +#include + +#define _COGL_MAX_BEZ_RECURSE_DEPTH 16 + +static void _cogl_path_free (CoglPath *path); + +static void _cogl_path_build_fill_attribute_buffer (CoglPath *path); +static CoglPrimitive *_cogl_path_get_fill_primitive (CoglPath *path); +static void _cogl_path_build_stroke_attribute_buffer (CoglPath *path); + +COGL_OBJECT_DEFINE (Path, path); +COGL_GTYPE_DEFINE_CLASS (Path, path); + +static void +_cogl_path_data_clear_vbos (CoglPathData *data) +{ + int i; + + if (data->fill_attribute_buffer) + { + cogl_object_unref (data->fill_attribute_buffer); + cogl_object_unref (data->fill_vbo_indices); + + for (i = 0; i < COGL_PATH_N_ATTRIBUTES; i++) + cogl_object_unref (data->fill_attributes[i]); + + data->fill_attribute_buffer = NULL; + } + + if (data->fill_primitive) + { + cogl_object_unref (data->fill_primitive); + data->fill_primitive = NULL; + } + + if (data->stroke_attribute_buffer) + { + cogl_object_unref (data->stroke_attribute_buffer); + + for (i = 0; i < data->stroke_n_attributes; i++) + cogl_object_unref (data->stroke_attributes[i]); + + g_free (data->stroke_attributes); + + data->stroke_attribute_buffer = NULL; + } +} + +static void +_cogl_path_data_unref (CoglPathData *data) +{ + if (--data->ref_count <= 0) + { + _cogl_path_data_clear_vbos (data); + + g_array_free (data->path_nodes, TRUE); + + g_slice_free (CoglPathData, data); + } +} + +static void +_cogl_path_modify (CoglPath *path) +{ + /* This needs to be called whenever the path is about to be modified + to implement copy-on-write semantics */ + + /* If there is more than one path using the data then we need to + copy the data instead */ + if (path->data->ref_count != 1) + { + CoglPathData *old_data = path->data; + + path->data = g_slice_dup (CoglPathData, old_data); + path->data->path_nodes = g_array_new (FALSE, FALSE, + sizeof (CoglPathNode)); + g_array_append_vals (path->data->path_nodes, + old_data->path_nodes->data, + old_data->path_nodes->len); + + path->data->fill_attribute_buffer = NULL; + path->data->fill_primitive = NULL; + path->data->stroke_attribute_buffer = NULL; + path->data->ref_count = 1; + + _cogl_path_data_unref (old_data); + } + else + /* The path is altered so the vbos will now be invalid */ + _cogl_path_data_clear_vbos (path->data); +} + +void +cogl2_path_set_fill_rule (CoglPath *path, + CoglPathFillRule fill_rule) +{ + _COGL_RETURN_IF_FAIL (cogl_is_path (path)); + + if (path->data->fill_rule != fill_rule) + { + _cogl_path_modify (path); + + path->data->fill_rule = fill_rule; + } +} + +CoglPathFillRule +cogl2_path_get_fill_rule (CoglPath *path) +{ + _COGL_RETURN_VAL_IF_FAIL (cogl_is_path (path), COGL_PATH_FILL_RULE_NON_ZERO); + + return path->data->fill_rule; +} + +static void +_cogl_path_add_node (CoglPath *path, + CoglBool new_sub_path, + float x, + float y) +{ + CoglPathNode new_node; + CoglPathData *data; + + _cogl_path_modify (path); + + data = path->data; + + new_node.x = x; + new_node.y = y; + new_node.path_size = 0; + + if (new_sub_path || data->path_nodes->len == 0) + data->last_path = data->path_nodes->len; + + g_array_append_val (data->path_nodes, new_node); + + g_array_index (data->path_nodes, CoglPathNode, data->last_path).path_size++; + + if (data->path_nodes->len == 1) + { + data->path_nodes_min.x = data->path_nodes_max.x = x; + data->path_nodes_min.y = data->path_nodes_max.y = y; + } + else + { + if (x < data->path_nodes_min.x) + data->path_nodes_min.x = x; + if (x > data->path_nodes_max.x) + data->path_nodes_max.x = x; + if (y < data->path_nodes_min.y) + data->path_nodes_min.y = y; + if (y > data->path_nodes_max.y) + data->path_nodes_max.y = y; + } + + /* Once the path nodes have been modified then we'll assume it's no + longer a rectangle. cogl2_path_rectangle will set this back to + TRUE if this has been called from there */ + data->is_rectangle = FALSE; +} + +static void +_cogl_path_stroke_nodes (CoglPath *path, + CoglFramebuffer *framebuffer, + CoglPipeline *pipeline) +{ + CoglPathData *data; + CoglPipeline *copy = NULL; + unsigned int path_start; + int path_num = 0; + CoglPathNode *node; + + _COGL_RETURN_IF_FAIL (cogl_is_path (path)); + _COGL_RETURN_IF_FAIL (cogl_is_framebuffer (framebuffer)); + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + data = path->data; + + if (data->path_nodes->len == 0) + return; + + if (cogl_pipeline_get_n_layers (pipeline) != 0) + { + copy = cogl_pipeline_copy (pipeline); + _cogl_pipeline_prune_to_n_layers (copy, 0); + pipeline = copy; + } + + _cogl_path_build_stroke_attribute_buffer (path); + + for (path_start = 0; + path_start < data->path_nodes->len; + path_start += node->path_size) + { + CoglPrimitive *primitive; + + node = &g_array_index (data->path_nodes, CoglPathNode, path_start); + + primitive = + cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_LINE_STRIP, + node->path_size, + &data->stroke_attributes[path_num], + 1); + cogl_primitive_draw (primitive, framebuffer, pipeline); + cogl_object_unref (primitive); + + path_num++; + } + + if (copy) + cogl_object_unref (copy); +} + +void +_cogl_path_get_bounds (CoglPath *path, + float *min_x, + float *min_y, + float *max_x, + float *max_y) +{ + CoglPathData *data = path->data; + + if (data->path_nodes->len == 0) + { + *min_x = 0.0f; + *min_y = 0.0f; + *max_x = 0.0f; + *max_y = 0.0f; + } + else + { + *min_x = data->path_nodes_min.x; + *min_y = data->path_nodes_min.y; + *max_x = data->path_nodes_max.x; + *max_y = data->path_nodes_max.y; + } +} + +static void +_cogl_path_fill_nodes_with_clipped_rectangle (CoglPath *path, + CoglFramebuffer *framebuffer, + CoglPipeline *pipeline) +{ + /* We need at least three stencil bits to combine clips */ + if (_cogl_framebuffer_get_stencil_bits (framebuffer) >= 3) + { + static CoglBool seen_warning = FALSE; + + if (!seen_warning) + { + g_warning ("Paths can not be filled using materials with " + "sliced textures unless there is a stencil " + "buffer"); + seen_warning = TRUE; + } + } + + cogl_framebuffer_push_path_clip (framebuffer, path); + cogl_framebuffer_draw_rectangle (framebuffer, + pipeline, + path->data->path_nodes_min.x, + path->data->path_nodes_min.y, + path->data->path_nodes_max.x, + path->data->path_nodes_max.y); + cogl_framebuffer_pop_clip (framebuffer); +} + +static CoglBool +validate_layer_cb (CoglPipelineLayer *layer, void *user_data) +{ + CoglBool *needs_fallback = user_data; + CoglTexture *texture = _cogl_pipeline_layer_get_texture (layer); + + /* If any of the layers of the current pipeline contain sliced + * textures or textures with waste then it won't work to draw the + * path directly. Instead we fallback to pushing the path as a clip + * on the clip-stack and drawing the path's bounding rectangle + * instead. + */ + + if (texture != NULL && (cogl_texture_is_sliced (texture) || + !_cogl_texture_can_hardware_repeat (texture))) + *needs_fallback = TRUE; + + return !*needs_fallback; +} + +static void +_cogl_path_fill_nodes (CoglPath *path, + CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglDrawFlags flags) +{ + if (path->data->path_nodes->len == 0) + return; + + /* If the path is a simple rectangle then we can divert to using + cogl_framebuffer_draw_rectangle which should be faster because it + can go through the journal instead of uploading the geometry just + for two triangles */ + if (path->data->is_rectangle && flags == 0) + { + float x_1, y_1, x_2, y_2; + + _cogl_path_get_bounds (path, &x_1, &y_1, &x_2, &y_2); + cogl_framebuffer_draw_rectangle (framebuffer, + pipeline, + x_1, y_1, + x_2, y_2); + } + else + { + CoglBool needs_fallback = FALSE; + CoglPrimitive *primitive; + + _cogl_pipeline_foreach_layer_internal (pipeline, + validate_layer_cb, + &needs_fallback); + if (needs_fallback) + { + _cogl_path_fill_nodes_with_clipped_rectangle (path, + framebuffer, + pipeline); + return; + } + + primitive = _cogl_path_get_fill_primitive (path); + + _cogl_primitive_draw (primitive, framebuffer, pipeline, flags); + } +} + +/* TODO: Update to the protoype used in the Cogl master branch. + * This is experimental API but not in sync with the cogl_path_fill() + * api in Cogl master which takes explicit framebuffer and pipeline + * arguments */ +void +cogl2_path_fill (CoglPath *path) +{ + _COGL_RETURN_IF_FAIL (cogl_is_path (path)); + + _cogl_path_fill_nodes (path, + cogl_get_draw_framebuffer (), + cogl_get_source (), + 0 /* flags */); +} + +/* TODO: Update to the protoype used in the Cogl master branch. + * This is experimental API but not in sync with the cogl_path_fill() + * api in Cogl master which takes explicit framebuffer and pipeline + * arguments */ +void +cogl2_path_stroke (CoglPath *path) +{ + _COGL_RETURN_IF_FAIL (cogl_is_path (path)); + + if (path->data->path_nodes->len == 0) + return; + + _cogl_path_stroke_nodes (path, + cogl_get_draw_framebuffer (), + cogl_get_source ()); +} + +void +cogl2_path_move_to (CoglPath *path, + float x, + float y) +{ + CoglPathData *data; + + _COGL_RETURN_IF_FAIL (cogl_is_path (path)); + + _cogl_path_add_node (path, TRUE, x, y); + + data = path->data; + + data->path_start.x = x; + data->path_start.y = y; + + data->path_pen = data->path_start; +} + +void +cogl2_path_rel_move_to (CoglPath *path, + float x, + float y) +{ + CoglPathData *data; + + _COGL_RETURN_IF_FAIL (cogl_is_path (path)); + + data = path->data; + + cogl2_path_move_to (path, + data->path_pen.x + x, + data->path_pen.y + y); +} + +void +cogl2_path_line_to (CoglPath *path, + float x, + float y) +{ + CoglPathData *data; + + _COGL_RETURN_IF_FAIL (cogl_is_path (path)); + + _cogl_path_add_node (path, FALSE, x, y); + + data = path->data; + + data->path_pen.x = x; + data->path_pen.y = y; +} + +void +cogl2_path_rel_line_to (CoglPath *path, + float x, + float y) +{ + CoglPathData *data; + + _COGL_RETURN_IF_FAIL (cogl_is_path (path)); + + data = path->data; + + cogl2_path_line_to (path, + data->path_pen.x + x, + data->path_pen.y + y); +} + +void +cogl2_path_close (CoglPath *path) +{ + _COGL_RETURN_IF_FAIL (cogl_is_path (path)); + + _cogl_path_add_node (path, FALSE, path->data->path_start.x, + path->data->path_start.y); + + path->data->path_pen = path->data->path_start; +} + +void +cogl2_path_line (CoglPath *path, + float x_1, + float y_1, + float x_2, + float y_2) +{ + cogl2_path_move_to (path, x_1, y_1); + cogl2_path_line_to (path, x_2, y_2); +} + +void +cogl2_path_polyline (CoglPath *path, + const float *coords, + int num_points) +{ + int c = 0; + + _COGL_RETURN_IF_FAIL (cogl_is_path (path)); + + cogl2_path_move_to (path, coords[0], coords[1]); + + for (c = 1; c < num_points; ++c) + cogl2_path_line_to (path, coords[2*c], coords[2*c+1]); +} + +void +cogl2_path_polygon (CoglPath *path, + const float *coords, + int num_points) +{ + cogl2_path_polyline (path, coords, num_points); + cogl2_path_close (path); +} + +void +cogl2_path_rectangle (CoglPath *path, + float x_1, + float y_1, + float x_2, + float y_2) +{ + CoglBool is_rectangle; + + /* If the path was previously empty and the rectangle isn't mirrored + then we'll record that this is a simple rectangle path so that we + can optimise it */ + is_rectangle = (path->data->path_nodes->len == 0 && + x_2 >= x_1 && + y_2 >= y_1); + + cogl2_path_move_to (path, x_1, y_1); + cogl2_path_line_to (path, x_2, y_1); + cogl2_path_line_to (path, x_2, y_2); + cogl2_path_line_to (path, x_1, y_2); + cogl2_path_close (path); + + path->data->is_rectangle = is_rectangle; +} + +CoglBool +_cogl_path_is_rectangle (CoglPath *path) +{ + return path->data->is_rectangle; +} + +static void +_cogl_path_arc (CoglPath *path, + float center_x, + float center_y, + float radius_x, + float radius_y, + float angle_1, + float angle_2, + float angle_step, + unsigned int move_first) +{ + float a = 0x0; + float cosa = 0x0; + float sina = 0x0; + float px = 0x0; + float py = 0x0; + + /* Fix invalid angles */ + + if (angle_1 == angle_2 || angle_step == 0x0) + return; + + if (angle_step < 0x0) + angle_step = -angle_step; + + /* Walk the arc by given step */ + + a = angle_1; + while (a != angle_2) + { + cosa = cosf (a * (G_PI/180.0)); + sina = sinf (a * (G_PI/180.0)); + + px = center_x + (cosa * radius_x); + py = center_y + (sina * radius_y); + + if (a == angle_1 && move_first) + cogl2_path_move_to (path, px, py); + else + cogl2_path_line_to (path, px, py); + + if (G_LIKELY (angle_2 > angle_1)) + { + a += angle_step; + if (a > angle_2) + a = angle_2; + } + else + { + a -= angle_step; + if (a < angle_2) + a = angle_2; + } + } + + /* Make sure the final point is drawn */ + + cosa = cosf (angle_2 * (G_PI/180.0)); + sina = sinf (angle_2 * (G_PI/180.0)); + + px = center_x + (cosa * radius_x); + py = center_y + (sina * radius_y); + + cogl2_path_line_to (path, px, py); +} + +void +cogl2_path_arc (CoglPath *path, + float center_x, + float center_y, + float radius_x, + float radius_y, + float angle_1, + float angle_2) +{ + float angle_step = 10; + + _COGL_RETURN_IF_FAIL (cogl_is_path (path)); + + /* it is documented that a move to is needed to create a freestanding + * arc + */ + _cogl_path_arc (path, + center_x, center_y, + radius_x, radius_y, + angle_1, angle_2, + angle_step, 0 /* no move */); +} + + +static void +_cogl_path_rel_arc (CoglPath *path, + float center_x, + float center_y, + float radius_x, + float radius_y, + float angle_1, + float angle_2, + float angle_step) +{ + CoglPathData *data; + + data = path->data; + + _cogl_path_arc (path, + data->path_pen.x + center_x, + data->path_pen.y + center_y, + radius_x, radius_y, + angle_1, angle_2, + angle_step, 0 /* no move */); +} + +void +cogl2_path_ellipse (CoglPath *path, + float center_x, + float center_y, + float radius_x, + float radius_y) +{ + float angle_step = 10; + + _COGL_RETURN_IF_FAIL (cogl_is_path (path)); + + /* FIXME: if shows to be slow might be optimized + * by mirroring just a quarter of it */ + + _cogl_path_arc (path, + center_x, center_y, + radius_x, radius_y, + 0, 360, + angle_step, 1 /* move first */); + + cogl2_path_close (path); +} + +void +cogl2_path_round_rectangle (CoglPath *path, + float x_1, + float y_1, + float x_2, + float y_2, + float radius, + float arc_step) +{ + float inner_width = x_2 - x_1 - radius * 2; + float inner_height = y_2 - y_1 - radius * 2; + + _COGL_RETURN_IF_FAIL (cogl_is_path (path)); + + cogl2_path_move_to (path, x_1, y_1 + radius); + _cogl_path_rel_arc (path, + radius, 0, + radius, radius, + 180, + 270, + arc_step); + + cogl2_path_line_to (path, + path->data->path_pen.x + inner_width, + path->data->path_pen.y); + _cogl_path_rel_arc (path, + 0, radius, + radius, radius, + -90, + 0, + arc_step); + + cogl2_path_line_to (path, + path->data->path_pen.x, + path->data->path_pen.y + inner_height); + + _cogl_path_rel_arc (path, + -radius, 0, + radius, radius, + 0, + 90, + arc_step); + + cogl2_path_line_to (path, + path->data->path_pen.x - inner_width, + path->data->path_pen.y); + _cogl_path_rel_arc (path, + 0, -radius, + radius, radius, + 90, + 180, + arc_step); + + cogl2_path_close (path); +} + +static void +_cogl_path_bezier3_sub (CoglPath *path, + CoglBezCubic *cubic) +{ + CoglBezCubic cubics[_COGL_MAX_BEZ_RECURSE_DEPTH]; + CoglBezCubic *cleft; + CoglBezCubic *cright; + CoglBezCubic *c; + floatVec2 dif1; + floatVec2 dif2; + floatVec2 mm; + floatVec2 c1; + floatVec2 c2; + floatVec2 c3; + floatVec2 c4; + floatVec2 c5; + int cindex; + + /* Put first curve on stack */ + cubics[0] = *cubic; + cindex = 0; + + while (cindex >= 0) + { + c = &cubics[cindex]; + + + /* Calculate distance of control points from their + * counterparts on the line between end points */ + dif1.x = (c->p2.x * 3) - (c->p1.x * 2) - c->p4.x; + dif1.y = (c->p2.y * 3) - (c->p1.y * 2) - c->p4.y; + dif2.x = (c->p3.x * 3) - (c->p4.x * 2) - c->p1.x; + dif2.y = (c->p3.y * 3) - (c->p4.y * 2) - c->p1.y; + + if (dif1.x < 0) + dif1.x = -dif1.x; + if (dif1.y < 0) + dif1.y = -dif1.y; + if (dif2.x < 0) + dif2.x = -dif2.x; + if (dif2.y < 0) + dif2.y = -dif2.y; + + + /* Pick the greatest of two distances */ + if (dif1.x < dif2.x) dif1.x = dif2.x; + if (dif1.y < dif2.y) dif1.y = dif2.y; + + /* Cancel if the curve is flat enough */ + if (dif1.x + dif1.y <= 1.0 || + cindex == _COGL_MAX_BEZ_RECURSE_DEPTH-1) + { + /* Add subdivision point (skip last) */ + if (cindex == 0) + return; + + _cogl_path_add_node (path, FALSE, c->p4.x, c->p4.y); + + --cindex; + + continue; + } + + /* Left recursion goes on top of stack! */ + cright = c; cleft = &cubics[++cindex]; + + /* Subdivide into 2 sub-curves */ + c1.x = ((c->p1.x + c->p2.x) / 2); + c1.y = ((c->p1.y + c->p2.y) / 2); + mm.x = ((c->p2.x + c->p3.x) / 2); + mm.y = ((c->p2.y + c->p3.y) / 2); + c5.x = ((c->p3.x + c->p4.x) / 2); + c5.y = ((c->p3.y + c->p4.y) / 2); + + c2.x = ((c1.x + mm.x) / 2); + c2.y = ((c1.y + mm.y) / 2); + c4.x = ((mm.x + c5.x) / 2); + c4.y = ((mm.y + c5.y) / 2); + + c3.x = ((c2.x + c4.x) / 2); + c3.y = ((c2.y + c4.y) / 2); + + /* Add left recursion to stack */ + cleft->p1 = c->p1; + cleft->p2 = c1; + cleft->p3 = c2; + cleft->p4 = c3; + + /* Add right recursion to stack */ + cright->p1 = c3; + cright->p2 = c4; + cright->p3 = c5; + cright->p4 = c->p4; + } +} + +void +cogl2_path_curve_to (CoglPath *path, + float x_1, + float y_1, + float x_2, + float y_2, + float x_3, + float y_3) +{ + CoglBezCubic cubic; + + _COGL_RETURN_IF_FAIL (cogl_is_path (path)); + + /* Prepare cubic curve */ + cubic.p1 = path->data->path_pen; + cubic.p2.x = x_1; + cubic.p2.y = y_1; + cubic.p3.x = x_2; + cubic.p3.y = y_2; + cubic.p4.x = x_3; + cubic.p4.y = y_3; + + /* Run subdivision */ + _cogl_path_bezier3_sub (path, &cubic); + + /* Add last point */ + _cogl_path_add_node (path, FALSE, cubic.p4.x, cubic.p4.y); + path->data->path_pen = cubic.p4; +} + +void +cogl2_path_rel_curve_to (CoglPath *path, + float x_1, + float y_1, + float x_2, + float y_2, + float x_3, + float y_3) +{ + CoglPathData *data; + + _COGL_RETURN_IF_FAIL (cogl_is_path (path)); + + data = path->data; + + cogl2_path_curve_to (path, + data->path_pen.x + x_1, + data->path_pen.y + y_1, + data->path_pen.x + x_2, + data->path_pen.y + y_2, + data->path_pen.x + x_3, + data->path_pen.y + y_3); +} + +CoglPath * +cogl2_path_new (void) +{ + CoglPath *path; + CoglPathData *data; + + _COGL_GET_CONTEXT (ctx, NULL); + + path = g_slice_new (CoglPath); + data = path->data = g_slice_new (CoglPathData); + + data->ref_count = 1; + data->context = ctx; + data->fill_rule = COGL_PATH_FILL_RULE_EVEN_ODD; + data->path_nodes = g_array_new (FALSE, FALSE, sizeof (CoglPathNode)); + data->last_path = 0; + data->fill_attribute_buffer = NULL; + data->stroke_attribute_buffer = NULL; + data->fill_primitive = NULL; + data->is_rectangle = FALSE; + + return _cogl_path_object_new (path); +} + +CoglPath * +cogl_path_copy (CoglPath *old_path) +{ + CoglPath *new_path; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_path (old_path), NULL); + + new_path = g_slice_new (CoglPath); + new_path->data = old_path->data; + new_path->data->ref_count++; + + return _cogl_path_object_new (new_path); +} + +static void +_cogl_path_free (CoglPath *path) +{ + _cogl_path_data_unref (path->data); + g_slice_free (CoglPath, path); +} + +/* If second order beziers were needed the following code could + * be re-enabled: + */ +#if 0 + +static void +_cogl_path_bezier2_sub (CoglPath *path, + CoglBezQuad *quad) +{ + CoglBezQuad quads[_COGL_MAX_BEZ_RECURSE_DEPTH]; + CoglBezQuad *qleft; + CoglBezQuad *qright; + CoglBezQuad *q; + floatVec2 mid; + floatVec2 dif; + floatVec2 c1; + floatVec2 c2; + floatVec2 c3; + int qindex; + + /* Put first curve on stack */ + quads[0] = *quad; + qindex = 0; + + /* While stack is not empty */ + while (qindex >= 0) + { + + q = &quads[qindex]; + + /* Calculate distance of control point from its + * counterpart on the line between end points */ + mid.x = ((q->p1.x + q->p3.x) / 2); + mid.y = ((q->p1.y + q->p3.y) / 2); + dif.x = (q->p2.x - mid.x); + dif.y = (q->p2.y - mid.y); + if (dif.x < 0) dif.x = -dif.x; + if (dif.y < 0) dif.y = -dif.y; + + /* Cancel if the curve is flat enough */ + if (dif.x + dif.y <= 1.0 || + qindex == _COGL_MAX_BEZ_RECURSE_DEPTH - 1) + { + /* Add subdivision point (skip last) */ + if (qindex == 0) return; + _cogl_path_add_node (path, FALSE, q->p3.x, q->p3.y); + --qindex; continue; + } + + /* Left recursion goes on top of stack! */ + qright = q; qleft = &quads[++qindex]; + + /* Subdivide into 2 sub-curves */ + c1.x = ((q->p1.x + q->p2.x) / 2); + c1.y = ((q->p1.y + q->p2.y) / 2); + c3.x = ((q->p2.x + q->p3.x) / 2); + c3.y = ((q->p2.y + q->p3.y) / 2); + c2.x = ((c1.x + c3.x) / 2); + c2.y = ((c1.y + c3.y) / 2); + + /* Add left recursion onto stack */ + qleft->p1 = q->p1; + qleft->p2 = c1; + qleft->p3 = c2; + + /* Add right recursion onto stack */ + qright->p1 = c2; + qright->p2 = c3; + qright->p3 = q->p3; + } +} + +void +cogl_path_curve2_to (CoglPath *path, + float x_1, + float y_1, + float x_2, + float y_2) +{ + CoglBezQuad quad; + + /* Prepare quadratic curve */ + quad.p1 = path->data->path_pen; + quad.p2.x = x_1; + quad.p2.y = y_1; + quad.p3.x = x_2; + quad.p3.y = y_2; + + /* Run subdivision */ + _cogl_path_bezier2_sub (&quad); + + /* Add last point */ + _cogl_path_add_node (FALSE, quad.p3.x, quad.p3.y); + path->data->path_pen = quad.p3; +} + +void +cogl_rel_curve2_to (CoglPath *path, + float x_1, + float y_1, + float x_2, + float y_2) +{ + CoglPathData *data; + + _COGL_RETURN_IF_FAIL (cogl_is_path (path)); + + data = path->data; + + cogl_path_curve2_to (data->path_pen.x + x_1, + data->path_pen.y + y_1, + data->path_pen.x + x_2, + data->path_pen.y + y_2); +} + +#endif + +typedef struct _CoglPathTesselator CoglPathTesselator; +typedef struct _CoglPathTesselatorVertex CoglPathTesselatorVertex; + +struct _CoglPathTesselator +{ + GLUtesselator *glu_tess; + GLenum primitive_type; + int vertex_number; + /* Array of CoglPathTesselatorVertex. This needs to grow when the + combine callback is called */ + GArray *vertices; + /* Array of integers for the indices into the vertices array. Each + element will either be uint8_t, uint16_t or uint32_t depending on + the number of vertices */ + GArray *indices; + CoglIndicesType indices_type; + /* Indices used to split fans and strips */ + int index_a, index_b; +}; + +struct _CoglPathTesselatorVertex +{ + float x, y, s, t; +}; + +static void +_cogl_path_tesselator_begin (GLenum type, + CoglPathTesselator *tess) +{ + g_assert (type == GL_TRIANGLES || + type == GL_TRIANGLE_FAN || + type == GL_TRIANGLE_STRIP); + + tess->primitive_type = type; + tess->vertex_number = 0; +} + +static CoglIndicesType +_cogl_path_tesselator_get_indices_type_for_size (int n_vertices) +{ + if (n_vertices <= 256) + return COGL_INDICES_TYPE_UNSIGNED_BYTE; + else if (n_vertices <= 65536) + return COGL_INDICES_TYPE_UNSIGNED_SHORT; + else + return COGL_INDICES_TYPE_UNSIGNED_INT; +} + +static void +_cogl_path_tesselator_allocate_indices_array (CoglPathTesselator *tess) +{ + switch (tess->indices_type) + { + case COGL_INDICES_TYPE_UNSIGNED_BYTE: + tess->indices = g_array_new (FALSE, FALSE, sizeof (uint8_t)); + break; + + case COGL_INDICES_TYPE_UNSIGNED_SHORT: + tess->indices = g_array_new (FALSE, FALSE, sizeof (uint16_t)); + break; + + case COGL_INDICES_TYPE_UNSIGNED_INT: + tess->indices = g_array_new (FALSE, FALSE, sizeof (uint32_t)); + break; + } +} + +static void +_cogl_path_tesselator_add_index (CoglPathTesselator *tess, int vertex_index) +{ + switch (tess->indices_type) + { + case COGL_INDICES_TYPE_UNSIGNED_BYTE: + { + uint8_t val = vertex_index; + g_array_append_val (tess->indices, val); + } + break; + + case COGL_INDICES_TYPE_UNSIGNED_SHORT: + { + uint16_t val = vertex_index; + g_array_append_val (tess->indices, val); + } + break; + + case COGL_INDICES_TYPE_UNSIGNED_INT: + { + uint32_t val = vertex_index; + g_array_append_val (tess->indices, val); + } + break; + } +} + +static void +_cogl_path_tesselator_vertex (void *vertex_data, + CoglPathTesselator *tess) +{ + int vertex_index; + + vertex_index = GPOINTER_TO_INT (vertex_data); + + /* This tries to convert all of the primitives into GL_TRIANGLES + with indices to share vertices */ + switch (tess->primitive_type) + { + case GL_TRIANGLES: + /* Directly use the vertex */ + _cogl_path_tesselator_add_index (tess, vertex_index); + break; + + case GL_TRIANGLE_FAN: + if (tess->vertex_number == 0) + tess->index_a = vertex_index; + else if (tess->vertex_number == 1) + tess->index_b = vertex_index; + else + { + /* Create a triangle with the first vertex, the previous + vertex and this vertex */ + _cogl_path_tesselator_add_index (tess, tess->index_a); + _cogl_path_tesselator_add_index (tess, tess->index_b); + _cogl_path_tesselator_add_index (tess, vertex_index); + /* Next time we will use this vertex as the previous + vertex */ + tess->index_b = vertex_index; + } + break; + + case GL_TRIANGLE_STRIP: + if (tess->vertex_number == 0) + tess->index_a = vertex_index; + else if (tess->vertex_number == 1) + tess->index_b = vertex_index; + else + { + _cogl_path_tesselator_add_index (tess, tess->index_a); + _cogl_path_tesselator_add_index (tess, tess->index_b); + _cogl_path_tesselator_add_index (tess, vertex_index); + if (tess->vertex_number & 1) + tess->index_b = vertex_index; + else + tess->index_a = vertex_index; + } + break; + + default: + g_assert_not_reached (); + } + + tess->vertex_number++; +} + +static void +_cogl_path_tesselator_end (CoglPathTesselator *tess) +{ + tess->primitive_type = GL_FALSE; +} + +static void +_cogl_path_tesselator_combine (double coords[3], + void *vertex_data[4], + float weight[4], + void **out_data, + CoglPathTesselator *tess) +{ + CoglPathTesselatorVertex *vertex; + CoglIndicesType new_indices_type; + int i; + + /* Add a new vertex to the array */ + g_array_set_size (tess->vertices, tess->vertices->len + 1); + vertex = &g_array_index (tess->vertices, + CoglPathTesselatorVertex, + tess->vertices->len - 1); + /* The data is just the index to the vertex */ + *out_data = GINT_TO_POINTER (tess->vertices->len - 1); + /* Set the coordinates of the new vertex */ + vertex->x = coords[0]; + vertex->y = coords[1]; + /* Generate the texture coordinates as the weighted average of the + four incoming coordinates */ + vertex->s = 0.0f; + vertex->t = 0.0f; + for (i = 0; i < 4; i++) + { + CoglPathTesselatorVertex *old_vertex = + &g_array_index (tess->vertices, CoglPathTesselatorVertex, + GPOINTER_TO_INT (vertex_data[i])); + vertex->s += old_vertex->s * weight[i]; + vertex->t += old_vertex->t * weight[i]; + } + + /* Check if we've reached the limit for the data type of our indices */ + new_indices_type = + _cogl_path_tesselator_get_indices_type_for_size (tess->vertices->len); + if (new_indices_type != tess->indices_type) + { + CoglIndicesType old_indices_type = new_indices_type; + GArray *old_vertices = tess->indices; + + /* Copy the indices to an array of the new type */ + tess->indices_type = new_indices_type; + _cogl_path_tesselator_allocate_indices_array (tess); + + switch (old_indices_type) + { + case COGL_INDICES_TYPE_UNSIGNED_BYTE: + for (i = 0; i < old_vertices->len; i++) + _cogl_path_tesselator_add_index (tess, + g_array_index (old_vertices, + uint8_t, i)); + break; + + case COGL_INDICES_TYPE_UNSIGNED_SHORT: + for (i = 0; i < old_vertices->len; i++) + _cogl_path_tesselator_add_index (tess, + g_array_index (old_vertices, + uint16_t, i)); + break; + + case COGL_INDICES_TYPE_UNSIGNED_INT: + for (i = 0; i < old_vertices->len; i++) + _cogl_path_tesselator_add_index (tess, + g_array_index (old_vertices, + uint32_t, i)); + break; + } + + g_array_free (old_vertices, TRUE); + } +} + +static void +_cogl_path_build_fill_attribute_buffer (CoglPath *path) +{ + CoglPathTesselator tess; + unsigned int path_start = 0; + CoglPathData *data = path->data; + int i; + + /* If we've already got a vbo then we don't need to do anything */ + if (data->fill_attribute_buffer) + return; + + tess.primitive_type = FALSE; + + /* Generate a vertex for each point on the path */ + tess.vertices = g_array_new (FALSE, FALSE, sizeof (CoglPathTesselatorVertex)); + g_array_set_size (tess.vertices, data->path_nodes->len); + for (i = 0; i < data->path_nodes->len; i++) + { + CoglPathNode *node = + &g_array_index (data->path_nodes, CoglPathNode, i); + CoglPathTesselatorVertex *vertex = + &g_array_index (tess.vertices, CoglPathTesselatorVertex, i); + + vertex->x = node->x; + vertex->y = node->y; + + /* Add texture coordinates so that a texture would be drawn to + fit the bounding box of the path and then cropped by the + path */ + if (data->path_nodes_min.x == data->path_nodes_max.x) + vertex->s = 0.0f; + else + vertex->s = ((node->x - data->path_nodes_min.x) + / (data->path_nodes_max.x - data->path_nodes_min.x)); + if (data->path_nodes_min.y == data->path_nodes_max.y) + vertex->t = 0.0f; + else + vertex->t = ((node->y - data->path_nodes_min.y) + / (data->path_nodes_max.y - data->path_nodes_min.y)); + } + + tess.indices_type = + _cogl_path_tesselator_get_indices_type_for_size (data->path_nodes->len); + _cogl_path_tesselator_allocate_indices_array (&tess); + + tess.glu_tess = gluNewTess (); + + if (data->fill_rule == COGL_PATH_FILL_RULE_EVEN_ODD) + gluTessProperty (tess.glu_tess, GLU_TESS_WINDING_RULE, + GLU_TESS_WINDING_ODD); + else + gluTessProperty (tess.glu_tess, GLU_TESS_WINDING_RULE, + GLU_TESS_WINDING_NONZERO); + + /* All vertices are on the xy-plane */ + gluTessNormal (tess.glu_tess, 0.0, 0.0, 1.0); + + gluTessCallback (tess.glu_tess, GLU_TESS_BEGIN_DATA, + _cogl_path_tesselator_begin); + gluTessCallback (tess.glu_tess, GLU_TESS_VERTEX_DATA, + _cogl_path_tesselator_vertex); + gluTessCallback (tess.glu_tess, GLU_TESS_END_DATA, + _cogl_path_tesselator_end); + gluTessCallback (tess.glu_tess, GLU_TESS_COMBINE_DATA, + _cogl_path_tesselator_combine); + + gluTessBeginPolygon (tess.glu_tess, &tess); + + while (path_start < data->path_nodes->len) + { + CoglPathNode *node = + &g_array_index (data->path_nodes, CoglPathNode, path_start); + + gluTessBeginContour (tess.glu_tess); + + for (i = 0; i < node->path_size; i++) + { + double vertex[3] = { node[i].x, node[i].y, 0.0 }; + gluTessVertex (tess.glu_tess, vertex, + GINT_TO_POINTER (i + path_start)); + } + + gluTessEndContour (tess.glu_tess); + + path_start += node->path_size; + } + + gluTessEndPolygon (tess.glu_tess); + + gluDeleteTess (tess.glu_tess); + + data->fill_attribute_buffer = + cogl_attribute_buffer_new (data->context, + sizeof (CoglPathTesselatorVertex) * + tess.vertices->len, + tess.vertices->data); + g_array_free (tess.vertices, TRUE); + + data->fill_attributes[0] = + cogl_attribute_new (data->fill_attribute_buffer, + "cogl_position_in", + sizeof (CoglPathTesselatorVertex), + G_STRUCT_OFFSET (CoglPathTesselatorVertex, x), + 2, /* n_components */ + COGL_ATTRIBUTE_TYPE_FLOAT); + data->fill_attributes[1] = + cogl_attribute_new (data->fill_attribute_buffer, + "cogl_tex_coord0_in", + sizeof (CoglPathTesselatorVertex), + G_STRUCT_OFFSET (CoglPathTesselatorVertex, s), + 2, /* n_components */ + COGL_ATTRIBUTE_TYPE_FLOAT); + + data->fill_vbo_indices = cogl_indices_new (data->context, + tess.indices_type, + tess.indices->data, + tess.indices->len); + data->fill_vbo_n_indices = tess.indices->len; + g_array_free (tess.indices, TRUE); +} + +static CoglPrimitive * +_cogl_path_get_fill_primitive (CoglPath *path) +{ + if (path->data->fill_primitive) + return path->data->fill_primitive; + + _cogl_path_build_fill_attribute_buffer (path); + + path->data->fill_primitive = + cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, + path->data->fill_vbo_n_indices, + path->data->fill_attributes, + COGL_PATH_N_ATTRIBUTES); + cogl_primitive_set_indices (path->data->fill_primitive, + path->data->fill_vbo_indices, + path->data->fill_vbo_n_indices); + + return path->data->fill_primitive; +} + +static CoglClipStack * +_cogl_clip_stack_push_from_path (CoglClipStack *stack, + CoglPath *path, + CoglMatrixEntry *modelview_entry, + CoglMatrixEntry *projection_entry, + const float *viewport) +{ + float x_1, y_1, x_2, y_2; + + _cogl_path_get_bounds (path, &x_1, &y_1, &x_2, &y_2); + + /* If the path is a simple rectangle then we can divert to pushing a + rectangle clip instead which usually won't involve the stencil + buffer */ + if (_cogl_path_is_rectangle (path)) + return _cogl_clip_stack_push_rectangle (stack, + x_1, y_1, + x_2, y_2, + modelview_entry, + projection_entry, + viewport); + else + { + CoglPrimitive *primitive = _cogl_path_get_fill_primitive (path); + + return _cogl_clip_stack_push_primitive (stack, + primitive, + x_1, y_1, x_2, y_2, + modelview_entry, + projection_entry, + viewport); + } +} + +void +cogl_framebuffer_push_path_clip (CoglFramebuffer *framebuffer, + CoglPath *path) +{ + CoglMatrixEntry *modelview_entry = + _cogl_framebuffer_get_modelview_entry (framebuffer); + CoglMatrixEntry *projection_entry = + _cogl_framebuffer_get_projection_entry (framebuffer); + /* XXX: It would be nicer if we stored the private viewport as a + * vec4 so we could avoid this redundant copy. */ + float viewport[] = { + framebuffer->viewport_x, + framebuffer->viewport_y, + framebuffer->viewport_width, + framebuffer->viewport_height + }; + + framebuffer->clip_stack = + _cogl_clip_stack_push_from_path (framebuffer->clip_stack, + path, + modelview_entry, + projection_entry, + viewport); + + if (framebuffer->context->current_draw_buffer == framebuffer) + framebuffer->context->current_draw_buffer_changes |= + COGL_FRAMEBUFFER_STATE_CLIP; +} + +/* XXX: deprecated */ +void +cogl_clip_push_from_path (CoglPath *path) +{ + cogl_framebuffer_push_path_clip (cogl_get_draw_framebuffer (), path); +} + +static void +_cogl_path_build_stroke_attribute_buffer (CoglPath *path) +{ + CoglPathData *data = path->data; + CoglBuffer *buffer; + unsigned int n_attributes = 0; + unsigned int path_start; + CoglPathNode *node; + floatVec2 *buffer_p; + unsigned int i; + + /* If we've already got a cached vbo then we don't need to do anything */ + if (data->stroke_attribute_buffer) + return; + + data->stroke_attribute_buffer = + cogl_attribute_buffer_new_with_size (data->context, + data->path_nodes->len * + sizeof (floatVec2)); + + buffer = COGL_BUFFER (data->stroke_attribute_buffer); + buffer_p = _cogl_buffer_map_for_fill_or_fallback (buffer); + + /* Copy the vertices in and count the number of sub paths. Each sub + path will form a separate attribute so we can paint the disjoint + line strips */ + for (path_start = 0; + path_start < data->path_nodes->len; + path_start += node->path_size) + { + node = &g_array_index (data->path_nodes, CoglPathNode, path_start); + + for (i = 0; i < node->path_size; i++) + { + buffer_p[path_start + i].x = node[i].x; + buffer_p[path_start + i].y = node[i].y; + } + + n_attributes++; + } + + _cogl_buffer_unmap_for_fill_or_fallback (buffer); + + data->stroke_attributes = g_new (CoglAttribute *, n_attributes); + + /* Now we can loop the sub paths again to create the attributes */ + for (i = 0, path_start = 0; + path_start < data->path_nodes->len; + i++, path_start += node->path_size) + { + node = &g_array_index (data->path_nodes, CoglPathNode, path_start); + + data->stroke_attributes[i] = + cogl_attribute_new (data->stroke_attribute_buffer, + "cogl_position_in", + sizeof (floatVec2), + path_start * sizeof (floatVec2), + 2, /* n_components */ + COGL_ATTRIBUTE_TYPE_FLOAT); + } + + data->stroke_n_attributes = n_attributes; +} + +/* XXX: deprecated */ +void +cogl_framebuffer_fill_path (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglPath *path) +{ + _COGL_RETURN_IF_FAIL (cogl_is_framebuffer (framebuffer)); + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + _COGL_RETURN_IF_FAIL (cogl_is_path (path)); + + _cogl_path_fill_nodes (path, framebuffer, pipeline, 0 /* flags */); +} + +/* XXX: deprecated */ +void +cogl_framebuffer_stroke_path (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglPath *path) +{ + _COGL_RETURN_IF_FAIL (cogl_is_framebuffer (framebuffer)); + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + _COGL_RETURN_IF_FAIL (cogl_is_path (path)); + + _cogl_path_stroke_nodes (path, framebuffer, pipeline); +} diff --git a/cogl/cogl-path/cogl-path.h b/cogl/cogl-path/cogl-path.h new file mode 100644 index 0000000..0a2eb05 --- /dev/null +++ b/cogl/cogl-path/cogl-path.h @@ -0,0 +1,60 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009,2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_PATH_H__ +#define __COGL_PATH_H__ + +/** + * SECTION:cogl-paths + * @short_description: Functions for constructing and drawing 2D paths. + * + * There are two levels on which drawing with cogl-paths can be used. + * The highest level functions construct various simple primitive + * shapes to be either filled or stroked. Using a lower-level set of + * functions more complex and arbitrary paths can be constructed by + * concatenating straight line, bezier curve and arc segments. + * + * When constructing arbitrary paths, the current pen location is + * initialized using the move_to command. The subsequent path segments + * implicitly use the last pen location as their first vertex and move + * the pen location to the last vertex they produce at the end. Also + * there are special versions of functions that allow specifying the + * vertices of the path segments relative to the last pen location + * rather then in the absolute coordinates. + */ + +#include + +#include +#include +#include + +#endif /* __COGL_PATH_H__ */ + diff --git a/cogl/cogl-path/cogl-path.symbols b/cogl/cogl-path/cogl-path.symbols new file mode 100644 index 0000000..b643ec0 --- /dev/null +++ b/cogl/cogl-path/cogl-path.symbols @@ -0,0 +1,59 @@ +/* cogl1-path-functions.h */ +cogl_clip_push_from_path +cogl_clip_push_from_path_preserve +cogl_get_path +cogl_is_path +cogl_path_arc +cogl_path_close +cogl_path_copy +cogl_path_curve_to +cogl_path_ellipse +cogl_path_fill +cogl_path_fill_preserve +cogl_path_get_fill_rule +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_path_get_gtype +#endif +cogl_path_line +cogl_path_line_to +cogl_path_move_to +cogl_path_new +cogl_path_polygon +cogl_path_polyline +cogl_path_rectangle +cogl_path_rel_curve_to +cogl_path_rel_line_to +cogl_path_rel_move_to +cogl_path_round_rectangle +cogl_path_set_fill_rule +cogl_path_stroke +cogl_path_stroke_preserve +cogl_set_path + +/* cogl2-path-functions.h */ +cogl_framebuffer_fill_path +cogl_framebuffer_push_path_clip +cogl_framebuffer_stroke_path +cogl2_clip_push_from_path +cogl2_path_arc +cogl2_path_close +cogl2_path_curve_to +cogl2_path_ellipse +cogl2_path_fill +cogl2_path_get_fill_rule +cogl2_path_line +cogl2_path_line_to +cogl2_path_move_to +cogl2_path_new +cogl2_path_polygon +cogl2_path_polyline +cogl2_path_rectangle +cogl2_path_rel_curve_to +cogl2_path_rel_line_to +cogl2_path_rel_move_to +cogl2_path_round_rectangle +cogl2_path_set_fill_rule +cogl2_path_stroke + +/* cogl-path-enums.h-contents may change as header is generated */ +cogl_path_fill_rule_get_type diff --git a/cogl/cogl-path/mutter-cogl-path-1.0.pc.in b/cogl/cogl-path/mutter-cogl-path-1.0.pc.in new file mode 100644 index 0000000..959b772 --- /dev/null +++ b/cogl/cogl-path/mutter-cogl-path-1.0.pc.in @@ -0,0 +1,13 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@/mutter +includedir=@includedir@/mutter +apiversion=1.0 +requires=@COGL_PKG_REQUIRES@ mutter-cogl-1.0 + +Name: Cogl +Description: A 2D path drawing library for Cogl +Version: @COGL_1_VERSION@ +Libs: -L${libdir} -lmutter-cogl-path +Cflags: -I${includedir}/cogl +Requires: ${requires} diff --git a/cogl/cogl-path/tesselator/GL/glu.h b/cogl/cogl-path/tesselator/GL/glu.h new file mode 100644 index 0000000..18c4024 --- /dev/null +++ b/cogl/cogl-path/tesselator/GL/glu.h @@ -0,0 +1,47 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +/* This is just a wrapper to use our simplified version of glu.h so + that the tesselator code can still #include */ + +#include "../tesselator.h" + +/* These aren't defined on GLES and we don't really want the + tesselator code to use them but we're also trying to avoid + modifying the C files so we just force them to be empty here */ + +#undef GLAPI +#define GLAPI + +#undef GLAPIENTRY +#define GLAPIENTRY + +/* GLES doesn't define a GLdouble type so lets just force it to a + regular double */ +#define GLdouble double diff --git a/cogl/cogl-path/tesselator/README b/cogl/cogl-path/tesselator/README new file mode 100644 index 0000000..66a6011 --- /dev/null +++ b/cogl/cogl-path/tesselator/README @@ -0,0 +1,446 @@ +/* +*/ + +General Polygon Tesselation +--------------------------- + + This note describes a tesselator for polygons consisting of one or + more closed contours. It is backward-compatible with the current + OpenGL Utilities tesselator, and is intended to replace it. Here is + a summary of the major differences: + + - input contours can be intersecting, self-intersecting, or degenerate. + + - supports a choice of several winding rules for determining which parts + of the polygon are on the "interior". This makes it possible to do + CSG operations on polygons. + + - boundary extraction: instead of tesselating the polygon, returns a + set of closed contours which separate the interior from the exterior. + + - returns the output as a small number of triangle fans and strips, + rather than a list of independent triangles (when possible). + + - output is available as an explicit mesh (a quad-edge structure), + in addition to the normal callback interface. + + - the algorithm used is extremely robust. + + +The interface +------------- + + The tesselator state is maintained in a "tesselator object". + These are allocated and destroyed using + + GLUtesselator *gluNewTess( void ); + void gluDeleteTess( GLUtesselator *tess ); + + Several tesselator objects may be used simultaneously. + + Inputs + ------ + + The input contours are specified with the following routines: + + void gluTessBeginPolygon( GLUtesselator *tess ); + void gluTessBeginContour( GLUtesselator *tess ); + void gluTessVertex( GLUtesselator *tess, GLUcoord coords[3], void *data ); + void gluTessEndContour( GLUtesselator *tess ); + void gluTessEndPolygon( GLUtesselator *tess ); + + Within each BeginPolygon/EndPolygon pair, there can be zero or more + calls to BeginContour/EndContour. Within each contour, there are zero + or more calls to gluTessVertex(). The vertices specify a closed + contour (the last vertex of each contour is automatically linked to + the first). + + "coords" give the coordinates of the vertex in 3-space. For useful + results, all vertices should lie in some plane, since the vertices + are projected onto a plane before tesselation. "data" is a pointer + to a user-defined vertex structure, which typically contains other + information such as color, texture coordinates, normal, etc. It is + used to refer to the vertex during rendering. + + The library can be compiled in single- or double-precision; the type + GLUcoord represents either "float" or "double" accordingly. The GLU + version will be available in double-precision only. Compile with + GLU_TESS_API_FLOAT defined to get the single-precision version. + + When EndPolygon is called, the tesselation algorithm determines + which regions are interior to the given contours, according to one + of several "winding rules" described below. The interior regions + are then tesselated, and the output is provided as callbacks. + + + Rendering Callbacks + ------------------- + + Callbacks are specified by the client using + + void gluTessCallback( GLUtesselator *tess, GLenum which, void (*fn)()); + + If "fn" is NULL, any previously defined callback is discarded. + + The callbacks used to provide output are: /* which == */ + + void begin( GLenum type ); /* GLU_TESS_BEGIN */ + void edgeFlag( GLboolean flag ); /* GLU_TESS_EDGE_FLAG */ + void vertex( void *data ); /* GLU_TESS_VERTEX */ + void end( void ); /* GLU_TESS_END */ + + Any of the callbacks may be left undefined; if so, the corresponding + information will not be supplied during rendering. + + The "begin" callback indicates the start of a primitive; type is one + of GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, or GL_TRIANGLES (but see the + notes on "boundary extraction" below). + + It is followed by any number of "vertex" callbacks, which supply the + vertices in the same order as expected by the corresponding glBegin() + call. After the last vertex of a given primitive, there is a callback + to "end". + + If the "edgeFlag" callback is provided, no triangle fans or strips + will be used. When edgeFlag is called, if "flag" is GL_TRUE then each + vertex which follows begins an edge which lies on the polygon boundary + (ie. an edge which separates an interior region from an exterior one). + If "flag" is GL_FALSE, each vertex which follows begins an edge which lies + in the polygon interior. "edgeFlag" will be called before the first + call to "vertex". + + Other Callbacks + --------------- + + void mesh( GLUmesh *mesh ); /* GLU_TESS_MESH */ + + - Returns an explicit mesh, represented using the quad-edge structure + (Guibas/Stolfi '85). Other implementations of this interface might + use a different mesh structure, so this is available only only as an + SGI extension. When the mesh is no longer needed, it should be freed + using + + void gluDeleteMesh( GLUmesh *mesh ); + + There is a brief description of this data structure in the include + file "mesh.h". For the full details, see L. Guibas and J. Stolfi, + Primitives for the manipulation of general subdivisions and the + computation of Voronoi diagrams, ACM Transactions on Graphics, + 4(2):74-123, April 1985. For an introduction, see the course notes + for CS348a, "Mathematical Foundations of Computer Graphics", + available at the Stanford bookstore (and taught during the fall + quarter). + + void error( GLenum errno ); /* GLU_TESS_ERROR */ + + - errno is one of GLU_TESS_MISSING_BEGIN_POLYGON, + GLU_TESS_MISSING_END_POLYGON, + GLU_TESS_MISSING_BEGIN_CONTOUR, + GLU_TESS_MISSING_END_CONTOUR, + GLU_TESS_COORD_TOO_LARGE, + GLU_TESS_NEED_COMBINE_CALLBACK + + The first four are obvious. The interface recovers from these + errors by inserting the missing call(s). + + GLU_TESS_COORD_TOO_LARGE says that some vertex coordinate exceeded + the predefined constant GLU_TESS_MAX_COORD in absolute value, and + that the value has been clamped. (Coordinate values must be small + enough so that two can be multiplied together without overflow.) + + GLU_TESS_NEED_COMBINE_CALLBACK says that the algorithm detected an + intersection between two edges in the input data, and the "combine" + callback (below) was not provided. No output will be generated. + + + void combine( GLUcoord coords[3], void *data[4], /* GLU_TESS_COMBINE */ + GLUcoord weight[4], void **outData ); + + - When the algorithm detects an intersection, or wishes to merge + features, it needs to create a new vertex. The vertex is defined + as a linear combination of up to 4 existing vertices, referenced + by data[0..3]. The coefficients of the linear combination are + given by weight[0..3]; these weights always sum to 1.0. All vertex + pointers are valid even when some of the weights are zero. + "coords" gives the location of the new vertex. + + The user must allocate another vertex, interpolate parameters + using "data" and "weights", and return the new vertex pointer in + "outData". This handle is supplied during rendering callbacks. + For example, if the polygon lies in an arbitrary plane in 3-space, + and we associate a color with each vertex, the combine callback might + look like this: + + void myCombine( GLUcoord coords[3], VERTEX *d[4], + GLUcoord w[4], VERTEX **dataOut ) + { + VERTEX *new = new_vertex(); + + new->x = coords[0]; + new->y = coords[1]; + new->z = coords[2]; + new->r = w[0]*d[0]->r + w[1]*d[1]->r + w[2]*d[2]->r + w[3]*d[3]->r; + new->g = w[0]*d[0]->g + w[1]*d[1]->g + w[2]*d[2]->g + w[3]*d[3]->g; + new->b = w[0]*d[0]->b + w[1]*d[1]->b + w[2]*d[2]->b + w[3]*d[3]->b; + new->a = w[0]*d[0]->a + w[1]*d[1]->a + w[2]*d[2]->a + w[3]*d[3]->a; + *dataOut = new; + } + + If the algorithm detects an intersection, then the "combine" callback + must be defined, and must write a non-NULL pointer into "dataOut". + Otherwise the GLU_TESS_NEED_COMBINE_CALLBACK error occurs, and no + output is generated. This is the only error that can occur during + tesselation and rendering. + + + Control over Tesselation + ------------------------ + + void gluTessProperty( GLUtesselator *tess, GLenum which, GLUcoord value ); + + Properties defined: + + - GLU_TESS_WINDING_RULE. Possible values: + + GLU_TESS_WINDING_ODD + GLU_TESS_WINDING_NONZERO + GLU_TESS_WINDING_POSITIVE + GLU_TESS_WINDING_NEGATIVE + GLU_TESS_WINDING_ABS_GEQ_TWO + + The input contours parition the plane into regions. A winding + rule determines which of these regions are inside the polygon. + + For a single contour C, the winding number of a point x is simply + the signed number of revolutions we make around x as we travel + once around C (where CCW is positive). When there are several + contours, the individual winding numbers are summed. This + procedure associates a signed integer value with each point x in + the plane. Note that the winding number is the same for all + points in a single region. + + The winding rule classifies a region as "inside" if its winding + number belongs to the chosen category (odd, nonzero, positive, + negative, or absolute value of at least two). The current GLU + tesselator implements the "odd" rule. The "nonzero" rule is another + common way to define the interior. The other three rules are + useful for polygon CSG operations (see below). + + - GLU_TESS_BOUNDARY_ONLY. Values: TRUE (non-zero) or FALSE (zero). + + If TRUE, returns a set of closed contours which separate the + polygon interior and exterior (rather than a tesselation). + Exterior contours are oriented CCW with respect to the normal, + interior contours are oriented CW. The GLU_TESS_BEGIN callback + uses the type GL_LINE_LOOP for each contour. + + - GLU_TESS_TOLERANCE. Value: a real number between 0.0 and 1.0. + + This specifies a tolerance for merging features to reduce the size + of the output. For example, two vertices which are very close to + each other might be replaced by a single vertex. The tolerance + is multiplied by the largest coordinate magnitude of any input vertex; + this specifies the maximum distance that any feature can move as the + result of a single merge operation. If a single feature takes part + in several merge operations, the total distance moved could be larger. + + Feature merging is completely optional; the tolerance is only a hint. + The implementation is free to merge in some cases and not in others, + or to never merge features at all. The default tolerance is zero. + + The current implementation merges vertices only if they are exactly + coincident, regardless of the current tolerance. A vertex is + spliced into an edge only if the implementation is unable to + distinguish which side of the edge the vertex lies on. + Two edges are merged only when both endpoints are identical. + + + void gluTessNormal( GLUtesselator *tess, + GLUcoord x, GLUcoord y, GLUcoord z ) + + - Lets the user supply the polygon normal, if known. All input data + is projected into a plane perpendicular to the normal before + tesselation. All output triangles are oriented CCW with + respect to the normal (CW orientation can be obtained by + reversing the sign of the supplied normal). For example, if + you know that all polygons lie in the x-y plane, call + "gluTessNormal(tess, 0.0, 0.0, 1.0)" before rendering any polygons. + + - If the supplied normal is (0,0,0) (the default value), the + normal is determined as follows. The direction of the normal, + up to its sign, is found by fitting a plane to the vertices, + without regard to how the vertices are connected. It is + expected that the input data lies approximately in plane; + otherwise projection perpendicular to the computed normal may + substantially change the geometry. The sign of the normal is + chosen so that the sum of the signed areas of all input contours + is non-negative (where a CCW contour has positive area). + + - The supplied normal persists until it is changed by another + call to gluTessNormal. + + + Backward compatibility with the GLU tesselator + ---------------------------------------------- + + The preferred interface is the one described above. The following + routines are obsolete, and are provided only for backward compatibility: + + typedef GLUtesselator GLUtriangulatorObj; /* obsolete name */ + + void gluBeginPolygon( GLUtesselator *tess ); + void gluNextContour( GLUtesselator *tess, GLenum type ); + void gluEndPolygon( GLUtesselator *tess ); + + "type" is one of GLU_EXTERIOR, GLU_INTERIOR, GLU_CCW, GLU_CW, or + GLU_UNKNOWN. It is ignored by the current GLU tesselator. + + GLU_BEGIN, GLU_VERTEX, GLU_END, GLU_ERROR, and GLU_EDGE_FLAG are defined + as synonyms for GLU_TESS_BEGIN, GLU_TESS_VERTEX, GLU_TESS_END, + GLU_TESS_ERROR, and GLU_TESS_EDGE_FLAG. + + +Polygon CSG operations +---------------------- + + The features of the tesselator make it easy to find the union, difference, + or intersection of several polygons. + + First, assume that each polygon is defined so that the winding number + is 0 for each exterior region, and 1 for each interior region. Under + this model, CCW contours define the outer boundary of the polygon, and + CW contours define holes. Contours may be nested, but a nested + contour must be oriented oppositely from the contour that contains it. + + If the original polygons do not satisfy this description, they can be + converted to this form by first running the tesselator with the + GLU_TESS_BOUNDARY_ONLY property turned on. This returns a list of + contours satisfying the restriction above. By allocating two + tesselator objects, the callbacks from one tesselator can be fed + directly to the input of another. + + Given two or more polygons of the form above, CSG operations can be + implemented as follows: + + Union + Draw all the input contours as a single polygon. The winding number + of each resulting region is the number of original polygons + which cover it. The union can be extracted using the + GLU_TESS_WINDING_NONZERO or GLU_TESS_WINDING_POSITIVE winding rules. + Note that with the nonzero rule, we would get the same result if + all contour orientations were reversed. + + Intersection (two polygons at a time only) + Draw a single polygon using the contours from both input polygons. + Extract the result using GLU_TESS_WINDING_ABS_GEQ_TWO. (Since this + winding rule looks at the absolute value, reversing all contour + orientations does not change the result.) + + Difference + + Suppose we want to compute A \ (B union C union D). Draw a single + polygon consisting of the unmodified contours from A, followed by + the contours of B,C,D with the vertex order reversed (this changes + the winding number of the interior regions to -1). To extract the + result, use the GLU_TESS_WINDING_POSITIVE rule. + + If B,C,D are the result of a GLU_TESS_BOUNDARY_ONLY call, an + alternative to reversing the vertex order is to reverse the sign of + the supplied normal. For example in the x-y plane, call + gluTessNormal( tess, 0.0, 0.0, -1.0 ). + + +Performance +----------- + + The tesselator is not intended for immediate-mode rendering; when + possible the output should be cached in a user structure or display + list. General polygon tesselation is an inherently difficult problem, + especially given the goal of extreme robustness. + + The implementation makes an effort to output a small number of fans + and strips; this should improve the rendering performance when the + output is used in a display list. + + Single-contour input polygons are first tested to see whether they can + be rendered as a triangle fan with respect to the first vertex (to + avoid running the full decomposition algorithm on convex polygons). + Non-convex polygons may be rendered by this "fast path" as well, if + the algorithm gets lucky in its choice of a starting vertex. + + For best performance follow these guidelines: + + - supply the polygon normal, if available, using gluTessNormal(). + This represents about 10% of the computation time. For example, + if all polygons lie in the x-y plane, use gluTessNormal(tess,0,0,1). + + - render many polygons using the same tesselator object, rather than + allocating a new tesselator for each one. (In a multi-threaded, + multi-processor environment you may get better performance using + several tesselators.) + + +Comparison with the GLU tesselator +---------------------------------- + + On polygons which make it through the "fast path", the tesselator is + 3 to 5 times faster than the GLU tesselator. + + On polygons which don't make it through the fast path (but which don't + have self-intersections or degeneracies), it is about 2 times slower. + + On polygons with self-intersections or degeneraces, there is nothing + to compare against. + + The new tesselator generates many more fans and strips, reducing the + number of vertices that need to be sent to the hardware. + + Key to the statistics: + + vert number of input vertices on all contours + cntr number of input contours + tri number of triangles in all output primitives + strip number of triangle strips + fan number of triangle fans + ind number of independent triangles + ms number of milliseconds for tesselation + (on a 150MHz R4400 Indy) + + Convex polygon examples: + +New: 3 vert, 1 cntr, 1 tri, 0 strip, 0 fan, 1 ind, 0.0459 ms +Old: 3 vert, 1 cntr, 1 tri, 0 strip, 0 fan, 1 ind, 0.149 ms +New: 4 vert, 1 cntr, 2 tri, 0 strip, 1 fan, 0 ind, 0.0459 ms +Old: 4 vert, 1 cntr, 2 tri, 0 strip, 0 fan, 2 ind, 0.161 ms +New: 36 vert, 1 cntr, 34 tri, 0 strip, 1 fan, 0 ind, 0.153 ms +Old: 36 vert, 1 cntr, 34 tri, 0 strip, 0 fan, 34 ind, 0.621 ms + + Concave single-contour polygons: + +New: 5 vert, 1 cntr, 3 tri, 0 strip, 1 fan, 0 ind, 0.052 ms +Old: 5 vert, 1 cntr, 3 tri, 0 strip, 0 fan, 3 ind, 0.252 ms +New: 19 vert, 1 cntr, 17 tri, 2 strip, 2 fan, 1 ind, 0.911 ms +Old: 19 vert, 1 cntr, 17 tri, 0 strip, 0 fan, 17 ind, 0.529 ms +New: 151 vert, 1 cntr, 149 tri, 13 strip, 18 fan, 3 ind, 6.82 ms +Old: 151 vert, 1 cntr, 149 tri, 0 strip, 3 fan, 143 ind, 2.7 ms +New: 574 vert, 1 cntr, 572 tri, 59 strip, 54 fan, 11 ind, 26.6 ms +Old: 574 vert, 1 cntr, 572 tri, 0 strip, 31 fan, 499 ind, 12.4 ms + + Multiple contours, but no intersections: + +New: 7 vert, 2 cntr, 7 tri, 1 strip, 0 fan, 0 ind, 0.527 ms +Old: 7 vert, 2 cntr, 7 tri, 0 strip, 0 fan, 7 ind, 0.274 ms +New: 81 vert, 6 cntr, 89 tri, 9 strip, 7 fan, 6 ind, 3.88 ms +Old: 81 vert, 6 cntr, 89 tri, 0 strip, 13 fan, 61 ind, 2.2 ms +New: 391 vert, 19 cntr, 413 tri, 37 strip, 32 fan, 26 ind, 20.2 ms +Old: 391 vert, 19 cntr, 413 tri, 0 strip, 25 fan, 363 ind, 8.68 ms + + Self-intersecting and degenerate examples: + +Bowtie: 4 vert, 1 cntr, 2 tri, 0 strip, 0 fan, 2 ind, 0.483 ms +Star: 5 vert, 1 cntr, 5 tri, 0 strip, 0 fan, 5 ind, 0.91 ms +Random: 24 vert, 7 cntr, 46 tri, 2 strip, 12 fan, 7 ind, 5.32 ms +Font: 333 vert, 2 cntr, 331 tri, 32 strip, 16 fan, 3 ind, 14.1 ms +: 167 vert, 35 cntr, 254 tri, 8 strip, 56 fan, 52 ind, 46.3 ms +: 78 vert, 1 cntr, 2675 tri, 148 strip, 207 fan, 180 ind, 243 ms +: 12480 vert, 2 cntr, 12478 tri, 736 strip,1275 fan, 5 ind, 1010 ms diff --git a/cogl/cogl-path/tesselator/dict-list.h b/cogl/cogl-path/tesselator/dict-list.h new file mode 100644 index 0000000..11331a7 --- /dev/null +++ b/cogl/cogl-path/tesselator/dict-list.h @@ -0,0 +1,100 @@ +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ +/* +** Author: Eric Veach, July 1994. +** +*/ + +#ifndef __dict_list_h_ +#define __dict_list_h_ + +/* Use #define's so that another heap implementation can use this one */ + +#define DictKey DictListKey +#define Dict DictList +#define DictNode DictListNode + +#define dictNewDict(frame,leq) __gl_dictListNewDict(frame,leq) +#define dictDeleteDict(dict) __gl_dictListDeleteDict(dict) + +#define dictSearch(dict,key) __gl_dictListSearch(dict,key) +#define dictInsert(dict,key) __gl_dictListInsert(dict,key) +#define dictInsertBefore(dict,node,key) __gl_dictListInsertBefore(dict,node,key) +#define dictDelete(dict,node) __gl_dictListDelete(dict,node) + +#define dictKey(n) __gl_dictListKey(n) +#define dictSucc(n) __gl_dictListSucc(n) +#define dictPred(n) __gl_dictListPred(n) +#define dictMin(d) __gl_dictListMin(d) +#define dictMax(d) __gl_dictListMax(d) + + + +typedef void *DictKey; +typedef struct Dict Dict; +typedef struct DictNode DictNode; + +Dict *dictNewDict( + void *frame, + int (*leq)(void *frame, DictKey key1, DictKey key2) ); + +void dictDeleteDict( Dict *dict ); + +/* Search returns the node with the smallest key greater than or equal + * to the given key. If there is no such key, returns a node whose + * key is NULL. Similarly, Succ(Max(d)) has a NULL key, etc. + */ +DictNode *dictSearch( Dict *dict, DictKey key ); +DictNode *dictInsertBefore( Dict *dict, DictNode *node, DictKey key ); +void dictDelete( Dict *dict, DictNode *node ); + +#define __gl_dictListKey(n) ((n)->key) +#define __gl_dictListSucc(n) ((n)->next) +#define __gl_dictListPred(n) ((n)->prev) +#define __gl_dictListMin(d) ((d)->head.next) +#define __gl_dictListMax(d) ((d)->head.prev) +#define __gl_dictListInsert(d,k) (dictInsertBefore((d),&(d)->head,(k))) + + +/*** Private data structures ***/ + +struct DictNode { + DictKey key; + DictNode *next; + DictNode *prev; +}; + +struct Dict { + DictNode head; + void *frame; + int (*leq)(void *frame, DictKey key1, DictKey key2); +}; + +#endif diff --git a/cogl/cogl-path/tesselator/dict.c b/cogl/cogl-path/tesselator/dict.c new file mode 100644 index 0000000..49d4f75 --- /dev/null +++ b/cogl/cogl-path/tesselator/dict.c @@ -0,0 +1,111 @@ +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ +/* +** Author: Eric Veach, July 1994. +** +*/ + +#include +#include "dict-list.h" +#include "memalloc.h" + +/* really __gl_dictListNewDict */ +Dict *dictNewDict( void *frame, + int (*leq)(void *frame, DictKey key1, DictKey key2) ) +{ + Dict *dict = (Dict *) memAlloc( sizeof( Dict )); + DictNode *head; + + if (dict == NULL) return NULL; + + head = &dict->head; + + head->key = NULL; + head->next = head; + head->prev = head; + + dict->frame = frame; + dict->leq = leq; + + return dict; +} + +/* really __gl_dictListDeleteDict */ +void dictDeleteDict( Dict *dict ) +{ + DictNode *node, *next; + + for( node = dict->head.next; node != &dict->head; node = next ) { + next = node->next; + memFree( node ); + } + memFree( dict ); +} + +/* really __gl_dictListInsertBefore */ +DictNode *dictInsertBefore( Dict *dict, DictNode *node, DictKey key ) +{ + DictNode *newNode; + + do { + node = node->prev; + } while( node->key != NULL && ! (*dict->leq)(dict->frame, node->key, key)); + + newNode = (DictNode *) memAlloc( sizeof( DictNode )); + if (newNode == NULL) return NULL; + + newNode->key = key; + newNode->next = node->next; + node->next->prev = newNode; + newNode->prev = node; + node->next = newNode; + + return newNode; +} + +/* really __gl_dictListDelete */ +void dictDelete( Dict *dict, DictNode *node ) /*ARGSUSED*/ +{ + node->next->prev = node->prev; + node->prev->next = node->next; + memFree( node ); +} + +/* really __gl_dictListSearch */ +DictNode *dictSearch( Dict *dict, DictKey key ) +{ + DictNode *node = &dict->head; + + do { + node = node->next; + } while( node->key != NULL && ! (*dict->leq)(dict->frame, key, node->key)); + + return node; +} diff --git a/cogl/cogl-path/tesselator/dict.h b/cogl/cogl-path/tesselator/dict.h new file mode 100644 index 0000000..11331a7 --- /dev/null +++ b/cogl/cogl-path/tesselator/dict.h @@ -0,0 +1,100 @@ +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ +/* +** Author: Eric Veach, July 1994. +** +*/ + +#ifndef __dict_list_h_ +#define __dict_list_h_ + +/* Use #define's so that another heap implementation can use this one */ + +#define DictKey DictListKey +#define Dict DictList +#define DictNode DictListNode + +#define dictNewDict(frame,leq) __gl_dictListNewDict(frame,leq) +#define dictDeleteDict(dict) __gl_dictListDeleteDict(dict) + +#define dictSearch(dict,key) __gl_dictListSearch(dict,key) +#define dictInsert(dict,key) __gl_dictListInsert(dict,key) +#define dictInsertBefore(dict,node,key) __gl_dictListInsertBefore(dict,node,key) +#define dictDelete(dict,node) __gl_dictListDelete(dict,node) + +#define dictKey(n) __gl_dictListKey(n) +#define dictSucc(n) __gl_dictListSucc(n) +#define dictPred(n) __gl_dictListPred(n) +#define dictMin(d) __gl_dictListMin(d) +#define dictMax(d) __gl_dictListMax(d) + + + +typedef void *DictKey; +typedef struct Dict Dict; +typedef struct DictNode DictNode; + +Dict *dictNewDict( + void *frame, + int (*leq)(void *frame, DictKey key1, DictKey key2) ); + +void dictDeleteDict( Dict *dict ); + +/* Search returns the node with the smallest key greater than or equal + * to the given key. If there is no such key, returns a node whose + * key is NULL. Similarly, Succ(Max(d)) has a NULL key, etc. + */ +DictNode *dictSearch( Dict *dict, DictKey key ); +DictNode *dictInsertBefore( Dict *dict, DictNode *node, DictKey key ); +void dictDelete( Dict *dict, DictNode *node ); + +#define __gl_dictListKey(n) ((n)->key) +#define __gl_dictListSucc(n) ((n)->next) +#define __gl_dictListPred(n) ((n)->prev) +#define __gl_dictListMin(d) ((d)->head.next) +#define __gl_dictListMax(d) ((d)->head.prev) +#define __gl_dictListInsert(d,k) (dictInsertBefore((d),&(d)->head,(k))) + + +/*** Private data structures ***/ + +struct DictNode { + DictKey key; + DictNode *next; + DictNode *prev; +}; + +struct Dict { + DictNode head; + void *frame; + int (*leq)(void *frame, DictKey key1, DictKey key2); +}; + +#endif diff --git a/cogl/cogl-path/tesselator/geom.c b/cogl/cogl-path/tesselator/geom.c new file mode 100644 index 0000000..35b36a3 --- /dev/null +++ b/cogl/cogl-path/tesselator/geom.c @@ -0,0 +1,264 @@ +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ +/* +** Author: Eric Veach, July 1994. +** +*/ + +#include "gluos.h" +#include +#include "mesh.h" +#include "geom.h" + +int __gl_vertLeq( GLUvertex *u, GLUvertex *v ) +{ + /* Returns TRUE if u is lexicographically <= v. */ + + return VertLeq( u, v ); +} + +GLdouble __gl_edgeEval( GLUvertex *u, GLUvertex *v, GLUvertex *w ) +{ + /* Given three vertices u,v,w such that VertLeq(u,v) && VertLeq(v,w), + * evaluates the t-coord of the edge uw at the s-coord of the vertex v. + * Returns v->t - (uw)(v->s), ie. the signed distance from uw to v. + * If uw is vertical (and thus passes thru v), the result is zero. + * + * The calculation is extremely accurate and stable, even when v + * is very close to u or w. In particular if we set v->t = 0 and + * let r be the negated result (this evaluates (uw)(v->s)), then + * r is guaranteed to satisfy MIN(u->t,w->t) <= r <= MAX(u->t,w->t). + */ + GLdouble gapL, gapR; + + assert( VertLeq( u, v ) && VertLeq( v, w )); + + gapL = v->s - u->s; + gapR = w->s - v->s; + + if( gapL + gapR > 0 ) { + if( gapL < gapR ) { + return (v->t - u->t) + (u->t - w->t) * (gapL / (gapL + gapR)); + } else { + return (v->t - w->t) + (w->t - u->t) * (gapR / (gapL + gapR)); + } + } + /* vertical line */ + return 0; +} + +GLdouble __gl_edgeSign( GLUvertex *u, GLUvertex *v, GLUvertex *w ) +{ + /* Returns a number whose sign matches EdgeEval(u,v,w) but which + * is cheaper to evaluate. Returns > 0, == 0 , or < 0 + * as v is above, on, or below the edge uw. + */ + GLdouble gapL, gapR; + + assert( VertLeq( u, v ) && VertLeq( v, w )); + + gapL = v->s - u->s; + gapR = w->s - v->s; + + if( gapL + gapR > 0 ) { + return (v->t - w->t) * gapL + (v->t - u->t) * gapR; + } + /* vertical line */ + return 0; +} + + +/*********************************************************************** + * Define versions of EdgeSign, EdgeEval with s and t transposed. + */ + +GLdouble __gl_transEval( GLUvertex *u, GLUvertex *v, GLUvertex *w ) +{ + /* Given three vertices u,v,w such that TransLeq(u,v) && TransLeq(v,w), + * evaluates the t-coord of the edge uw at the s-coord of the vertex v. + * Returns v->s - (uw)(v->t), ie. the signed distance from uw to v. + * If uw is vertical (and thus passes thru v), the result is zero. + * + * The calculation is extremely accurate and stable, even when v + * is very close to u or w. In particular if we set v->s = 0 and + * let r be the negated result (this evaluates (uw)(v->t)), then + * r is guaranteed to satisfy MIN(u->s,w->s) <= r <= MAX(u->s,w->s). + */ + GLdouble gapL, gapR; + + assert( TransLeq( u, v ) && TransLeq( v, w )); + + gapL = v->t - u->t; + gapR = w->t - v->t; + + if( gapL + gapR > 0 ) { + if( gapL < gapR ) { + return (v->s - u->s) + (u->s - w->s) * (gapL / (gapL + gapR)); + } else { + return (v->s - w->s) + (w->s - u->s) * (gapR / (gapL + gapR)); + } + } + /* vertical line */ + return 0; +} + +GLdouble __gl_transSign( GLUvertex *u, GLUvertex *v, GLUvertex *w ) +{ + /* Returns a number whose sign matches TransEval(u,v,w) but which + * is cheaper to evaluate. Returns > 0, == 0 , or < 0 + * as v is above, on, or below the edge uw. + */ + GLdouble gapL, gapR; + + assert( TransLeq( u, v ) && TransLeq( v, w )); + + gapL = v->t - u->t; + gapR = w->t - v->t; + + if( gapL + gapR > 0 ) { + return (v->s - w->s) * gapL + (v->s - u->s) * gapR; + } + /* vertical line */ + return 0; +} + + +int __gl_vertCCW( GLUvertex *u, GLUvertex *v, GLUvertex *w ) +{ + /* For almost-degenerate situations, the results are not reliable. + * Unless the floating-point arithmetic can be performed without + * rounding errors, *any* implementation will give incorrect results + * on some degenerate inputs, so the client must have some way to + * handle this situation. + */ + return (u->s*(v->t - w->t) + v->s*(w->t - u->t) + w->s*(u->t - v->t)) >= 0; +} + +/* Given parameters a,x,b,y returns the value (b*x+a*y)/(a+b), + * or (x+y)/2 if a==b==0. It requires that a,b >= 0, and enforces + * this in the rare case that one argument is slightly negative. + * The implementation is extremely stable numerically. + * In particular it guarantees that the result r satisfies + * MIN(x,y) <= r <= MAX(x,y), and the results are very accurate + * even when a and b differ greatly in magnitude. + */ +#define RealInterpolate(a,x,b,y) \ + (a = (a < 0) ? 0 : a, b = (b < 0) ? 0 : b, \ + ((a <= b) ? ((b == 0) ? ((x+y) / 2) \ + : (x + (y-x) * (a/(a+b)))) \ + : (y + (x-y) * (b/(a+b))))) + +#ifndef FOR_TRITE_TEST_PROGRAM +#define Interpolate(a,x,b,y) RealInterpolate(a,x,b,y) +#else + +/* Claim: the ONLY property the sweep algorithm relies on is that + * MIN(x,y) <= r <= MAX(x,y). This is a nasty way to test that. + */ +#include +extern int RandomInterpolate; + +GLdouble Interpolate( GLdouble a, GLdouble x, GLdouble b, GLdouble y) +{ +printf("*********************%d\n",RandomInterpolate); + if( RandomInterpolate ) { + a = 1.2 * drand48() - 0.1; + a = (a < 0) ? 0 : ((a > 1) ? 1 : a); + b = 1.0 - a; + } + return RealInterpolate(a,x,b,y); +} + +#endif + +#define Swap(a,b) do { GLUvertex *t = a; a = b; b = t; } while (0) + +void __gl_edgeIntersect( GLUvertex *o1, GLUvertex *d1, + GLUvertex *o2, GLUvertex *d2, + GLUvertex *v ) +/* Given edges (o1,d1) and (o2,d2), compute their point of intersection. + * The computed point is guaranteed to lie in the intersection of the + * bounding rectangles defined by each edge. + */ +{ + GLdouble z1, z2; + + /* This is certainly not the most efficient way to find the intersection + * of two line segments, but it is very numerically stable. + * + * Strategy: find the two middle vertices in the VertLeq ordering, + * and interpolate the intersection s-value from these. Then repeat + * using the TransLeq ordering to find the intersection t-value. + */ + + if( ! VertLeq( o1, d1 )) { Swap( o1, d1 ); } + if( ! VertLeq( o2, d2 )) { Swap( o2, d2 ); } + if( ! VertLeq( o1, o2 )) { Swap( o1, o2 ); Swap( d1, d2 ); } + + if( ! VertLeq( o2, d1 )) { + /* Technically, no intersection -- do our best */ + v->s = (o2->s + d1->s) / 2; + } else if( VertLeq( d1, d2 )) { + /* Interpolate between o2 and d1 */ + z1 = EdgeEval( o1, o2, d1 ); + z2 = EdgeEval( o2, d1, d2 ); + if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; } + v->s = Interpolate( z1, o2->s, z2, d1->s ); + } else { + /* Interpolate between o2 and d2 */ + z1 = EdgeSign( o1, o2, d1 ); + z2 = -EdgeSign( o1, d2, d1 ); + if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; } + v->s = Interpolate( z1, o2->s, z2, d2->s ); + } + + /* Now repeat the process for t */ + + if( ! TransLeq( o1, d1 )) { Swap( o1, d1 ); } + if( ! TransLeq( o2, d2 )) { Swap( o2, d2 ); } + if( ! TransLeq( o1, o2 )) { Swap( o1, o2 ); Swap( d1, d2 ); } + + if( ! TransLeq( o2, d1 )) { + /* Technically, no intersection -- do our best */ + v->t = (o2->t + d1->t) / 2; + } else if( TransLeq( d1, d2 )) { + /* Interpolate between o2 and d1 */ + z1 = TransEval( o1, o2, d1 ); + z2 = TransEval( o2, d1, d2 ); + if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; } + v->t = Interpolate( z1, o2->t, z2, d1->t ); + } else { + /* Interpolate between o2 and d2 */ + z1 = TransSign( o1, o2, d1 ); + z2 = -TransSign( o1, d2, d1 ); + if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; } + v->t = Interpolate( z1, o2->t, z2, d2->t ); + } +} diff --git a/cogl/cogl-path/tesselator/geom.h b/cogl/cogl-path/tesselator/geom.h new file mode 100644 index 0000000..5cb76c7 --- /dev/null +++ b/cogl/cogl-path/tesselator/geom.h @@ -0,0 +1,84 @@ +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ +/* +** Author: Eric Veach, July 1994. +** +*/ + +#ifndef __geom_h_ +#define __geom_h_ + +#include "mesh.h" + +#ifdef NO_BRANCH_CONDITIONS +/* MIPS architecture has special instructions to evaluate boolean + * conditions -- more efficient than branching, IF you can get the + * compiler to generate the right instructions (SGI compiler doesn't) + */ +#define VertEq(u,v) (((u)->s == (v)->s) & ((u)->t == (v)->t)) +#define VertLeq(u,v) (((u)->s < (v)->s) | \ + ((u)->s == (v)->s & (u)->t <= (v)->t)) +#else +#define VertEq(u,v) ((u)->s == (v)->s && (u)->t == (v)->t) +#define VertLeq(u,v) (((u)->s < (v)->s) || \ + ((u)->s == (v)->s && (u)->t <= (v)->t)) +#endif + +#define EdgeEval(u,v,w) __gl_edgeEval(u,v,w) +#define EdgeSign(u,v,w) __gl_edgeSign(u,v,w) + +/* Versions of VertLeq, EdgeSign, EdgeEval with s and t transposed. */ + +#define TransLeq(u,v) (((u)->t < (v)->t) || \ + ((u)->t == (v)->t && (u)->s <= (v)->s)) +#define TransEval(u,v,w) __gl_transEval(u,v,w) +#define TransSign(u,v,w) __gl_transSign(u,v,w) + + +#define EdgeGoesLeft(e) VertLeq( (e)->Dst, (e)->Org ) +#define EdgeGoesRight(e) VertLeq( (e)->Org, (e)->Dst ) + +#undef ABS +#define ABS(x) ((x) < 0 ? -(x) : (x)) +#define VertL1dist(u,v) (ABS(u->s - v->s) + ABS(u->t - v->t)) + +#define VertCCW(u,v,w) __gl_vertCCW(u,v,w) + +int __gl_vertLeq( GLUvertex *u, GLUvertex *v ); +GLdouble __gl_edgeEval( GLUvertex *u, GLUvertex *v, GLUvertex *w ); +GLdouble __gl_edgeSign( GLUvertex *u, GLUvertex *v, GLUvertex *w ); +GLdouble __gl_transEval( GLUvertex *u, GLUvertex *v, GLUvertex *w ); +GLdouble __gl_transSign( GLUvertex *u, GLUvertex *v, GLUvertex *w ); +int __gl_vertCCW( GLUvertex *u, GLUvertex *v, GLUvertex *w ); +void __gl_edgeIntersect( GLUvertex *o1, GLUvertex *d1, + GLUvertex *o2, GLUvertex *d2, + GLUvertex *v ); + +#endif diff --git a/cogl/cogl-path/tesselator/gluos.h b/cogl/cogl-path/tesselator/gluos.h new file mode 100644 index 0000000..d6c3ae9 --- /dev/null +++ b/cogl/cogl-path/tesselator/gluos.h @@ -0,0 +1 @@ +/* This is a stub header to avoid having to change tess.c */ diff --git a/cogl/cogl-path/tesselator/memalloc.h b/cogl/cogl-path/tesselator/memalloc.h new file mode 100644 index 0000000..a094b6c --- /dev/null +++ b/cogl/cogl-path/tesselator/memalloc.h @@ -0,0 +1,49 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +/* This is a simple replacement for memalloc from the SGI tesselator + code to force it to use glib's allocation instead */ + +#ifndef __MEMALLOC_H__ +#define __MEMALLOC_H__ + +#include + +#define memRealloc g_realloc +#define memAlloc g_malloc +#define memFree g_free +#define memInit(x) 1 + +/* tess.c defines TRUE and FALSE itself unconditionally so we need to + undefine it from the glib headers */ +#undef TRUE +#undef FALSE + +#endif /* __MEMALLOC_H__ */ diff --git a/cogl/cogl-path/tesselator/mesh.c b/cogl/cogl-path/tesselator/mesh.c new file mode 100644 index 0000000..36cb3a7 --- /dev/null +++ b/cogl/cogl-path/tesselator/mesh.c @@ -0,0 +1,798 @@ +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ +/* +** Author: Eric Veach, July 1994. +** +*/ + +#include "gluos.h" +#include +#include +#include "mesh.h" +#include "memalloc.h" + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +static GLUvertex *allocVertex() +{ + return (GLUvertex *)memAlloc( sizeof( GLUvertex )); +} + +static GLUface *allocFace() +{ + return (GLUface *)memAlloc( sizeof( GLUface )); +} + +/************************ Utility Routines ************************/ + +/* Allocate and free half-edges in pairs for efficiency. + * The *only* place that should use this fact is allocation/free. + */ +typedef struct { GLUhalfEdge e, eSym; } EdgePair; + +/* MakeEdge creates a new pair of half-edges which form their own loop. + * No vertex or face structures are allocated, but these must be assigned + * before the current edge operation is completed. + */ +static GLUhalfEdge *MakeEdge( GLUhalfEdge *eNext ) +{ + GLUhalfEdge *e; + GLUhalfEdge *eSym; + GLUhalfEdge *ePrev; + EdgePair *pair = (EdgePair *)memAlloc( sizeof( EdgePair )); + if (pair == NULL) return NULL; + + e = &pair->e; + eSym = &pair->eSym; + + /* Make sure eNext points to the first edge of the edge pair */ + if( eNext->Sym < eNext ) { eNext = eNext->Sym; } + + /* Insert in circular doubly-linked list before eNext. + * Note that the prev pointer is stored in Sym->next. + */ + ePrev = eNext->Sym->next; + eSym->next = ePrev; + ePrev->Sym->next = e; + e->next = eNext; + eNext->Sym->next = eSym; + + e->Sym = eSym; + e->Onext = e; + e->Lnext = eSym; + e->Org = NULL; + e->Lface = NULL; + e->winding = 0; + e->activeRegion = NULL; + + eSym->Sym = e; + eSym->Onext = eSym; + eSym->Lnext = e; + eSym->Org = NULL; + eSym->Lface = NULL; + eSym->winding = 0; + eSym->activeRegion = NULL; + + return e; +} + +/* Splice( a, b ) is best described by the Guibas/Stolfi paper or the + * CS348a notes (see mesh.h). Basically it modifies the mesh so that + * a->Onext and b->Onext are exchanged. This can have various effects + * depending on whether a and b belong to different face or vertex rings. + * For more explanation see __gl_meshSplice() below. + */ +static void Splice( GLUhalfEdge *a, GLUhalfEdge *b ) +{ + GLUhalfEdge *aOnext = a->Onext; + GLUhalfEdge *bOnext = b->Onext; + + aOnext->Sym->Lnext = b; + bOnext->Sym->Lnext = a; + a->Onext = bOnext; + b->Onext = aOnext; +} + +/* MakeVertex( newVertex, eOrig, vNext ) attaches a new vertex and makes it the + * origin of all edges in the vertex loop to which eOrig belongs. "vNext" gives + * a place to insert the new vertex in the global vertex list. We insert + * the new vertex *before* vNext so that algorithms which walk the vertex + * list will not see the newly created vertices. + */ +static void MakeVertex( GLUvertex *newVertex, + GLUhalfEdge *eOrig, GLUvertex *vNext ) +{ + GLUhalfEdge *e; + GLUvertex *vPrev; + GLUvertex *vNew = newVertex; + + assert(vNew != NULL); + + /* insert in circular doubly-linked list before vNext */ + vPrev = vNext->prev; + vNew->prev = vPrev; + vPrev->next = vNew; + vNew->next = vNext; + vNext->prev = vNew; + + vNew->anEdge = eOrig; + vNew->data = NULL; + /* leave coords, s, t undefined */ + + /* fix other edges on this vertex loop */ + e = eOrig; + do { + e->Org = vNew; + e = e->Onext; + } while( e != eOrig ); +} + +/* MakeFace( newFace, eOrig, fNext ) attaches a new face and makes it the left + * face of all edges in the face loop to which eOrig belongs. "fNext" gives + * a place to insert the new face in the global face list. We insert + * the new face *before* fNext so that algorithms which walk the face + * list will not see the newly created faces. + */ +static void MakeFace( GLUface *newFace, GLUhalfEdge *eOrig, GLUface *fNext ) +{ + GLUhalfEdge *e; + GLUface *fPrev; + GLUface *fNew = newFace; + + assert(fNew != NULL); + + /* insert in circular doubly-linked list before fNext */ + fPrev = fNext->prev; + fNew->prev = fPrev; + fPrev->next = fNew; + fNew->next = fNext; + fNext->prev = fNew; + + fNew->anEdge = eOrig; + fNew->data = NULL; + fNew->trail = NULL; + fNew->marked = FALSE; + + /* The new face is marked "inside" if the old one was. This is a + * convenience for the common case where a face has been split in two. + */ + fNew->inside = fNext->inside; + + /* fix other edges on this face loop */ + e = eOrig; + do { + e->Lface = fNew; + e = e->Lnext; + } while( e != eOrig ); +} + +/* KillEdge( eDel ) destroys an edge (the half-edges eDel and eDel->Sym), + * and removes from the global edge list. + */ +static void KillEdge( GLUhalfEdge *eDel ) +{ + GLUhalfEdge *ePrev, *eNext; + + /* Half-edges are allocated in pairs, see EdgePair above */ + if( eDel->Sym < eDel ) { eDel = eDel->Sym; } + + /* delete from circular doubly-linked list */ + eNext = eDel->next; + ePrev = eDel->Sym->next; + eNext->Sym->next = ePrev; + ePrev->Sym->next = eNext; + + memFree( eDel ); +} + + +/* KillVertex( vDel ) destroys a vertex and removes it from the global + * vertex list. It updates the vertex loop to point to a given new vertex. + */ +static void KillVertex( GLUvertex *vDel, GLUvertex *newOrg ) +{ + GLUhalfEdge *e, *eStart = vDel->anEdge; + GLUvertex *vPrev, *vNext; + + /* change the origin of all affected edges */ + e = eStart; + do { + e->Org = newOrg; + e = e->Onext; + } while( e != eStart ); + + /* delete from circular doubly-linked list */ + vPrev = vDel->prev; + vNext = vDel->next; + vNext->prev = vPrev; + vPrev->next = vNext; + + memFree( vDel ); +} + +/* KillFace( fDel ) destroys a face and removes it from the global face + * list. It updates the face loop to point to a given new face. + */ +static void KillFace( GLUface *fDel, GLUface *newLface ) +{ + GLUhalfEdge *e, *eStart = fDel->anEdge; + GLUface *fPrev, *fNext; + + /* change the left face of all affected edges */ + e = eStart; + do { + e->Lface = newLface; + e = e->Lnext; + } while( e != eStart ); + + /* delete from circular doubly-linked list */ + fPrev = fDel->prev; + fNext = fDel->next; + fNext->prev = fPrev; + fPrev->next = fNext; + + memFree( fDel ); +} + + +/****************** Basic Edge Operations **********************/ + +/* __gl_meshMakeEdge creates one edge, two vertices, and a loop (face). + * The loop consists of the two new half-edges. + */ +GLUhalfEdge *__gl_meshMakeEdge( GLUmesh *mesh ) +{ + GLUvertex *newVertex1= allocVertex(); + GLUvertex *newVertex2= allocVertex(); + GLUface *newFace= allocFace(); + GLUhalfEdge *e; + + /* if any one is null then all get freed */ + if (newVertex1 == NULL || newVertex2 == NULL || newFace == NULL) { + if (newVertex1 != NULL) memFree(newVertex1); + if (newVertex2 != NULL) memFree(newVertex2); + if (newFace != NULL) memFree(newFace); + return NULL; + } + + e = MakeEdge( &mesh->eHead ); + if (e == NULL) { + memFree(newVertex1); + memFree(newVertex2); + memFree(newFace); + return NULL; + } + + MakeVertex( newVertex1, e, &mesh->vHead ); + MakeVertex( newVertex2, e->Sym, &mesh->vHead ); + MakeFace( newFace, e, &mesh->fHead ); + return e; +} + + +/* __gl_meshSplice( eOrg, eDst ) is the basic operation for changing the + * mesh connectivity and topology. It changes the mesh so that + * eOrg->Onext <- OLD( eDst->Onext ) + * eDst->Onext <- OLD( eOrg->Onext ) + * where OLD(...) means the value before the meshSplice operation. + * + * This can have two effects on the vertex structure: + * - if eOrg->Org != eDst->Org, the two vertices are merged together + * - if eOrg->Org == eDst->Org, the origin is split into two vertices + * In both cases, eDst->Org is changed and eOrg->Org is untouched. + * + * Similarly (and independently) for the face structure, + * - if eOrg->Lface == eDst->Lface, one loop is split into two + * - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one + * In both cases, eDst->Lface is changed and eOrg->Lface is unaffected. + * + * Some special cases: + * If eDst == eOrg, the operation has no effect. + * If eDst == eOrg->Lnext, the new face will have a single edge. + * If eDst == eOrg->Lprev, the old face will have a single edge. + * If eDst == eOrg->Onext, the new vertex will have a single edge. + * If eDst == eOrg->Oprev, the old vertex will have a single edge. + */ +int __gl_meshSplice( GLUhalfEdge *eOrg, GLUhalfEdge *eDst ) +{ + int joiningLoops = FALSE; + int joiningVertices = FALSE; + + if( eOrg == eDst ) return 1; + + if( eDst->Org != eOrg->Org ) { + /* We are merging two disjoint vertices -- destroy eDst->Org */ + joiningVertices = TRUE; + KillVertex( eDst->Org, eOrg->Org ); + } + if( eDst->Lface != eOrg->Lface ) { + /* We are connecting two disjoint loops -- destroy eDst->Lface */ + joiningLoops = TRUE; + KillFace( eDst->Lface, eOrg->Lface ); + } + + /* Change the edge structure */ + Splice( eDst, eOrg ); + + if( ! joiningVertices ) { + GLUvertex *newVertex= allocVertex(); + if (newVertex == NULL) return 0; + + /* We split one vertex into two -- the new vertex is eDst->Org. + * Make sure the old vertex points to a valid half-edge. + */ + MakeVertex( newVertex, eDst, eOrg->Org ); + eOrg->Org->anEdge = eOrg; + } + if( ! joiningLoops ) { + GLUface *newFace= allocFace(); + if (newFace == NULL) return 0; + + /* We split one loop into two -- the new loop is eDst->Lface. + * Make sure the old face points to a valid half-edge. + */ + MakeFace( newFace, eDst, eOrg->Lface ); + eOrg->Lface->anEdge = eOrg; + } + + return 1; +} + + +/* __gl_meshDelete( eDel ) removes the edge eDel. There are several cases: + * if (eDel->Lface != eDel->Rface), we join two loops into one; the loop + * eDel->Lface is deleted. Otherwise, we are splitting one loop into two; + * the newly created loop will contain eDel->Dst. If the deletion of eDel + * would create isolated vertices, those are deleted as well. + * + * This function could be implemented as two calls to __gl_meshSplice + * plus a few calls to memFree, but this would allocate and delete + * unnecessary vertices and faces. + */ +int __gl_meshDelete( GLUhalfEdge *eDel ) +{ + GLUhalfEdge *eDelSym = eDel->Sym; + int joiningLoops = FALSE; + + /* First step: disconnect the origin vertex eDel->Org. We make all + * changes to get a consistent mesh in this "intermediate" state. + */ + if( eDel->Lface != eDel->Rface ) { + /* We are joining two loops into one -- remove the left face */ + joiningLoops = TRUE; + KillFace( eDel->Lface, eDel->Rface ); + } + + if( eDel->Onext == eDel ) { + KillVertex( eDel->Org, NULL ); + } else { + /* Make sure that eDel->Org and eDel->Rface point to valid half-edges */ + eDel->Rface->anEdge = eDel->Oprev; + eDel->Org->anEdge = eDel->Onext; + + Splice( eDel, eDel->Oprev ); + if( ! joiningLoops ) { + GLUface *newFace= allocFace(); + if (newFace == NULL) return 0; + + /* We are splitting one loop into two -- create a new loop for eDel. */ + MakeFace( newFace, eDel, eDel->Lface ); + } + } + + /* Claim: the mesh is now in a consistent state, except that eDel->Org + * may have been deleted. Now we disconnect eDel->Dst. + */ + if( eDelSym->Onext == eDelSym ) { + KillVertex( eDelSym->Org, NULL ); + KillFace( eDelSym->Lface, NULL ); + } else { + /* Make sure that eDel->Dst and eDel->Lface point to valid half-edges */ + eDel->Lface->anEdge = eDelSym->Oprev; + eDelSym->Org->anEdge = eDelSym->Onext; + Splice( eDelSym, eDelSym->Oprev ); + } + + /* Any isolated vertices or faces have already been freed. */ + KillEdge( eDel ); + + return 1; +} + + +/******************** Other Edge Operations **********************/ + +/* All these routines can be implemented with the basic edge + * operations above. They are provided for convenience and efficiency. + */ + + +/* __gl_meshAddEdgeVertex( eOrg ) creates a new edge eNew such that + * eNew == eOrg->Lnext, and eNew->Dst is a newly created vertex. + * eOrg and eNew will have the same left face. + */ +GLUhalfEdge *__gl_meshAddEdgeVertex( GLUhalfEdge *eOrg ) +{ + GLUhalfEdge *eNewSym; + GLUhalfEdge *eNew = MakeEdge( eOrg ); + if (eNew == NULL) return NULL; + + eNewSym = eNew->Sym; + + /* Connect the new edge appropriately */ + Splice( eNew, eOrg->Lnext ); + + /* Set the vertex and face information */ + eNew->Org = eOrg->Dst; + { + GLUvertex *newVertex= allocVertex(); + if (newVertex == NULL) return NULL; + + MakeVertex( newVertex, eNewSym, eNew->Org ); + } + eNew->Lface = eNewSym->Lface = eOrg->Lface; + + return eNew; +} + + +/* __gl_meshSplitEdge( eOrg ) splits eOrg into two edges eOrg and eNew, + * such that eNew == eOrg->Lnext. The new vertex is eOrg->Dst == eNew->Org. + * eOrg and eNew will have the same left face. + */ +GLUhalfEdge *__gl_meshSplitEdge( GLUhalfEdge *eOrg ) +{ + GLUhalfEdge *eNew; + GLUhalfEdge *tempHalfEdge= __gl_meshAddEdgeVertex( eOrg ); + if (tempHalfEdge == NULL) return NULL; + + eNew = tempHalfEdge->Sym; + + /* Disconnect eOrg from eOrg->Dst and connect it to eNew->Org */ + Splice( eOrg->Sym, eOrg->Sym->Oprev ); + Splice( eOrg->Sym, eNew ); + + /* Set the vertex and face information */ + eOrg->Dst = eNew->Org; + eNew->Dst->anEdge = eNew->Sym; /* may have pointed to eOrg->Sym */ + eNew->Rface = eOrg->Rface; + eNew->winding = eOrg->winding; /* copy old winding information */ + eNew->Sym->winding = eOrg->Sym->winding; + + return eNew; +} + + +/* __gl_meshConnect( eOrg, eDst ) creates a new edge from eOrg->Dst + * to eDst->Org, and returns the corresponding half-edge eNew. + * If eOrg->Lface == eDst->Lface, this splits one loop into two, + * and the newly created loop is eNew->Lface. Otherwise, two disjoint + * loops are merged into one, and the loop eDst->Lface is destroyed. + * + * If (eOrg == eDst), the new face will have only two edges. + * If (eOrg->Lnext == eDst), the old face is reduced to a single edge. + * If (eOrg->Lnext->Lnext == eDst), the old face is reduced to two edges. + */ +GLUhalfEdge *__gl_meshConnect( GLUhalfEdge *eOrg, GLUhalfEdge *eDst ) +{ + GLUhalfEdge *eNewSym; + int joiningLoops = FALSE; + GLUhalfEdge *eNew = MakeEdge( eOrg ); + if (eNew == NULL) return NULL; + + eNewSym = eNew->Sym; + + if( eDst->Lface != eOrg->Lface ) { + /* We are connecting two disjoint loops -- destroy eDst->Lface */ + joiningLoops = TRUE; + KillFace( eDst->Lface, eOrg->Lface ); + } + + /* Connect the new edge appropriately */ + Splice( eNew, eOrg->Lnext ); + Splice( eNewSym, eDst ); + + /* Set the vertex and face information */ + eNew->Org = eOrg->Dst; + eNewSym->Org = eDst->Org; + eNew->Lface = eNewSym->Lface = eOrg->Lface; + + /* Make sure the old face points to a valid half-edge */ + eOrg->Lface->anEdge = eNewSym; + + if( ! joiningLoops ) { + GLUface *newFace= allocFace(); + if (newFace == NULL) return NULL; + + /* We split one loop into two -- the new loop is eNew->Lface */ + MakeFace( newFace, eNew, eOrg->Lface ); + } + return eNew; +} + + +/******************** Other Operations **********************/ + +/* __gl_meshZapFace( fZap ) destroys a face and removes it from the + * global face list. All edges of fZap will have a NULL pointer as their + * left face. Any edges which also have a NULL pointer as their right face + * are deleted entirely (along with any isolated vertices this produces). + * An entire mesh can be deleted by zapping its faces, one at a time, + * in any order. Zapped faces cannot be used in further mesh operations! + */ +void __gl_meshZapFace( GLUface *fZap ) +{ + GLUhalfEdge *eStart = fZap->anEdge; + GLUhalfEdge *e, *eNext, *eSym; + GLUface *fPrev, *fNext; + + /* walk around face, deleting edges whose right face is also NULL */ + eNext = eStart->Lnext; + do { + e = eNext; + eNext = e->Lnext; + + e->Lface = NULL; + if( e->Rface == NULL ) { + /* delete the edge -- see __gl_MeshDelete above */ + + if( e->Onext == e ) { + KillVertex( e->Org, NULL ); + } else { + /* Make sure that e->Org points to a valid half-edge */ + e->Org->anEdge = e->Onext; + Splice( e, e->Oprev ); + } + eSym = e->Sym; + if( eSym->Onext == eSym ) { + KillVertex( eSym->Org, NULL ); + } else { + /* Make sure that eSym->Org points to a valid half-edge */ + eSym->Org->anEdge = eSym->Onext; + Splice( eSym, eSym->Oprev ); + } + KillEdge( e ); + } + } while( e != eStart ); + + /* delete from circular doubly-linked list */ + fPrev = fZap->prev; + fNext = fZap->next; + fNext->prev = fPrev; + fPrev->next = fNext; + + memFree( fZap ); +} + + +/* __gl_meshNewMesh() creates a new mesh with no edges, no vertices, + * and no loops (what we usually call a "face"). + */ +GLUmesh *__gl_meshNewMesh( void ) +{ + GLUvertex *v; + GLUface *f; + GLUhalfEdge *e; + GLUhalfEdge *eSym; + GLUmesh *mesh = (GLUmesh *)memAlloc( sizeof( GLUmesh )); + if (mesh == NULL) { + return NULL; + } + + v = &mesh->vHead; + f = &mesh->fHead; + e = &mesh->eHead; + eSym = &mesh->eHeadSym; + + v->next = v->prev = v; + v->anEdge = NULL; + v->data = NULL; + + f->next = f->prev = f; + f->anEdge = NULL; + f->data = NULL; + f->trail = NULL; + f->marked = FALSE; + f->inside = FALSE; + + e->next = e; + e->Sym = eSym; + e->Onext = NULL; + e->Lnext = NULL; + e->Org = NULL; + e->Lface = NULL; + e->winding = 0; + e->activeRegion = NULL; + + eSym->next = eSym; + eSym->Sym = e; + eSym->Onext = NULL; + eSym->Lnext = NULL; + eSym->Org = NULL; + eSym->Lface = NULL; + eSym->winding = 0; + eSym->activeRegion = NULL; + + return mesh; +} + + +/* __gl_meshUnion( mesh1, mesh2 ) forms the union of all structures in + * both meshes, and returns the new mesh (the old meshes are destroyed). + */ +GLUmesh *__gl_meshUnion( GLUmesh *mesh1, GLUmesh *mesh2 ) +{ + GLUface *f1 = &mesh1->fHead; + GLUvertex *v1 = &mesh1->vHead; + GLUhalfEdge *e1 = &mesh1->eHead; + GLUface *f2 = &mesh2->fHead; + GLUvertex *v2 = &mesh2->vHead; + GLUhalfEdge *e2 = &mesh2->eHead; + + /* Add the faces, vertices, and edges of mesh2 to those of mesh1 */ + if( f2->next != f2 ) { + f1->prev->next = f2->next; + f2->next->prev = f1->prev; + f2->prev->next = f1; + f1->prev = f2->prev; + } + + if( v2->next != v2 ) { + v1->prev->next = v2->next; + v2->next->prev = v1->prev; + v2->prev->next = v1; + v1->prev = v2->prev; + } + + if( e2->next != e2 ) { + e1->Sym->next->Sym->next = e2->next; + e2->next->Sym->next = e1->Sym->next; + e2->Sym->next->Sym->next = e1; + e1->Sym->next = e2->Sym->next; + } + + memFree( mesh2 ); + return mesh1; +} + + +#ifdef DELETE_BY_ZAPPING + +/* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh. + */ +void __gl_meshDeleteMesh( GLUmesh *mesh ) +{ + GLUface *fHead = &mesh->fHead; + + while( fHead->next != fHead ) { + __gl_meshZapFace( fHead->next ); + } + assert( mesh->vHead.next == &mesh->vHead ); + + memFree( mesh ); +} + +#else + +/* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh. + */ +void __gl_meshDeleteMesh( GLUmesh *mesh ) +{ + GLUface *f, *fNext; + GLUvertex *v, *vNext; + GLUhalfEdge *e, *eNext; + + for( f = mesh->fHead.next; f != &mesh->fHead; f = fNext ) { + fNext = f->next; + memFree( f ); + } + + for( v = mesh->vHead.next; v != &mesh->vHead; v = vNext ) { + vNext = v->next; + memFree( v ); + } + + for( e = mesh->eHead.next; e != &mesh->eHead; e = eNext ) { + /* One call frees both e and e->Sym (see EdgePair above) */ + eNext = e->next; + memFree( e ); + } + + memFree( mesh ); +} + +#endif + +#ifndef NDEBUG + +/* __gl_meshCheckMesh( mesh ) checks a mesh for self-consistency. + */ +void __gl_meshCheckMesh( GLUmesh *mesh ) +{ + GLUface *fHead = &mesh->fHead; + GLUvertex *vHead = &mesh->vHead; + GLUhalfEdge *eHead = &mesh->eHead; + GLUface *f, *fPrev; + GLUvertex *v, *vPrev; + GLUhalfEdge *e, *ePrev; + + fPrev = fHead; + for( fPrev = fHead ; (f = fPrev->next) != fHead; fPrev = f) { + assert( f->prev == fPrev ); + e = f->anEdge; + do { + assert( e->Sym != e ); + assert( e->Sym->Sym == e ); + assert( e->Lnext->Onext->Sym == e ); + assert( e->Onext->Sym->Lnext == e ); + assert( e->Lface == f ); + e = e->Lnext; + } while( e != f->anEdge ); + } + assert( f->prev == fPrev && f->anEdge == NULL && f->data == NULL ); + + vPrev = vHead; + for( vPrev = vHead ; (v = vPrev->next) != vHead; vPrev = v) { + assert( v->prev == vPrev ); + e = v->anEdge; + do { + assert( e->Sym != e ); + assert( e->Sym->Sym == e ); + assert( e->Lnext->Onext->Sym == e ); + assert( e->Onext->Sym->Lnext == e ); + assert( e->Org == v ); + e = e->Onext; + } while( e != v->anEdge ); + } + assert( v->prev == vPrev && v->anEdge == NULL && v->data == NULL ); + + ePrev = eHead; + for( ePrev = eHead ; (e = ePrev->next) != eHead; ePrev = e) { + assert( e->Sym->next == ePrev->Sym ); + assert( e->Sym != e ); + assert( e->Sym->Sym == e ); + assert( e->Org != NULL ); + assert( e->Dst != NULL ); + assert( e->Lnext->Onext->Sym == e ); + assert( e->Onext->Sym->Lnext == e ); + } + assert( e->Sym->next == ePrev->Sym + && e->Sym == &mesh->eHeadSym + && e->Sym->Sym == e + && e->Org == NULL && e->Dst == NULL + && e->Lface == NULL && e->Rface == NULL ); +} + +#endif diff --git a/cogl/cogl-path/tesselator/mesh.h b/cogl/cogl-path/tesselator/mesh.h new file mode 100644 index 0000000..690c5f2 --- /dev/null +++ b/cogl/cogl-path/tesselator/mesh.h @@ -0,0 +1,266 @@ +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ +/* +** Author: Eric Veach, July 1994. +** +*/ + +#ifndef __mesh_h_ +#define __mesh_h_ + +#include + +typedef struct GLUmesh GLUmesh; + +typedef struct GLUvertex GLUvertex; +typedef struct GLUface GLUface; +typedef struct GLUhalfEdge GLUhalfEdge; + +typedef struct ActiveRegion ActiveRegion; /* Internal data */ + +/* The mesh structure is similar in spirit, notation, and operations + * to the "quad-edge" structure (see L. Guibas and J. Stolfi, Primitives + * for the manipulation of general subdivisions and the computation of + * Voronoi diagrams, ACM Transactions on Graphics, 4(2):74-123, April 1985). + * For a simplified description, see the course notes for CS348a, + * "Mathematical Foundations of Computer Graphics", available at the + * Stanford bookstore (and taught during the fall quarter). + * The implementation also borrows a tiny subset of the graph-based approach + * use in Mantyla's Geometric Work Bench (see M. Mantyla, An Introduction + * to Sold Modeling, Computer Science Press, Rockville, Maryland, 1988). + * + * The fundamental data structure is the "half-edge". Two half-edges + * go together to make an edge, but they point in opposite directions. + * Each half-edge has a pointer to its mate (the "symmetric" half-edge Sym), + * its origin vertex (Org), the face on its left side (Lface), and the + * adjacent half-edges in the CCW direction around the origin vertex + * (Onext) and around the left face (Lnext). There is also a "next" + * pointer for the global edge list (see below). + * + * The notation used for mesh navigation: + * Sym = the mate of a half-edge (same edge, but opposite direction) + * Onext = edge CCW around origin vertex (keep same origin) + * Dnext = edge CCW around destination vertex (keep same dest) + * Lnext = edge CCW around left face (dest becomes new origin) + * Rnext = edge CCW around right face (origin becomes new dest) + * + * "prev" means to substitute CW for CCW in the definitions above. + * + * The mesh keeps global lists of all vertices, faces, and edges, + * stored as doubly-linked circular lists with a dummy header node. + * The mesh stores pointers to these dummy headers (vHead, fHead, eHead). + * + * The circular edge list is special; since half-edges always occur + * in pairs (e and e->Sym), each half-edge stores a pointer in only + * one direction. Starting at eHead and following the e->next pointers + * will visit each *edge* once (ie. e or e->Sym, but not both). + * e->Sym stores a pointer in the opposite direction, thus it is + * always true that e->Sym->next->Sym->next == e. + * + * Each vertex has a pointer to next and previous vertices in the + * circular list, and a pointer to a half-edge with this vertex as + * the origin (NULL if this is the dummy header). There is also a + * field "data" for client data. + * + * Each face has a pointer to the next and previous faces in the + * circular list, and a pointer to a half-edge with this face as + * the left face (NULL if this is the dummy header). There is also + * a field "data" for client data. + * + * Note that what we call a "face" is really a loop; faces may consist + * of more than one loop (ie. not simply connected), but there is no + * record of this in the data structure. The mesh may consist of + * several disconnected regions, so it may not be possible to visit + * the entire mesh by starting at a half-edge and traversing the edge + * structure. + * + * The mesh does NOT support isolated vertices; a vertex is deleted along + * with its last edge. Similarly when two faces are merged, one of the + * faces is deleted (see __gl_meshDelete below). For mesh operations, + * all face (loop) and vertex pointers must not be NULL. However, once + * mesh manipulation is finished, __gl_MeshZapFace can be used to delete + * faces of the mesh, one at a time. All external faces can be "zapped" + * before the mesh is returned to the client; then a NULL face indicates + * a region which is not part of the output polygon. + */ + +struct GLUvertex { + GLUvertex *next; /* next vertex (never NULL) */ + GLUvertex *prev; /* previous vertex (never NULL) */ + GLUhalfEdge *anEdge; /* a half-edge with this origin */ + void *data; /* client's data */ + + /* Internal data (keep hidden) */ + GLdouble coords[3]; /* vertex location in 3D */ + GLdouble s, t; /* projection onto the sweep plane */ + long pqHandle; /* to allow deletion from priority queue */ +}; + +struct GLUface { + GLUface *next; /* next face (never NULL) */ + GLUface *prev; /* previous face (never NULL) */ + GLUhalfEdge *anEdge; /* a half edge with this left face */ + void *data; /* room for client's data */ + + /* Internal data (keep hidden) */ + GLUface *trail; /* "stack" for conversion to strips */ + GLboolean marked; /* flag for conversion to strips */ + GLboolean inside; /* this face is in the polygon interior */ +}; + +struct GLUhalfEdge { + GLUhalfEdge *next; /* doubly-linked list (prev==Sym->next) */ + GLUhalfEdge *Sym; /* same edge, opposite direction */ + GLUhalfEdge *Onext; /* next edge CCW around origin */ + GLUhalfEdge *Lnext; /* next edge CCW around left face */ + GLUvertex *Org; /* origin vertex (Overtex too long) */ + GLUface *Lface; /* left face */ + + /* Internal data (keep hidden) */ + ActiveRegion *activeRegion; /* a region with this upper edge (sweep.c) */ + int winding; /* change in winding number when crossing + from the right face to the left face */ +}; + +#define Rface Sym->Lface +#define Dst Sym->Org + +#define Oprev Sym->Lnext +#define Lprev Onext->Sym +#define Dprev Lnext->Sym +#define Rprev Sym->Onext +#define Dnext Rprev->Sym /* 3 pointers */ +#define Rnext Oprev->Sym /* 3 pointers */ + + +struct GLUmesh { + GLUvertex vHead; /* dummy header for vertex list */ + GLUface fHead; /* dummy header for face list */ + GLUhalfEdge eHead; /* dummy header for edge list */ + GLUhalfEdge eHeadSym; /* and its symmetric counterpart */ +}; + +/* The mesh operations below have three motivations: completeness, + * convenience, and efficiency. The basic mesh operations are MakeEdge, + * Splice, and Delete. All the other edge operations can be implemented + * in terms of these. The other operations are provided for convenience + * and/or efficiency. + * + * When a face is split or a vertex is added, they are inserted into the + * global list *before* the existing vertex or face (ie. e->Org or e->Lface). + * This makes it easier to process all vertices or faces in the global lists + * without worrying about processing the same data twice. As a convenience, + * when a face is split, the "inside" flag is copied from the old face. + * Other internal data (v->data, v->activeRegion, f->data, f->marked, + * f->trail, e->winding) is set to zero. + * + * ********************** Basic Edge Operations ************************** + * + * __gl_meshMakeEdge( mesh ) creates one edge, two vertices, and a loop. + * The loop (face) consists of the two new half-edges. + * + * __gl_meshSplice( eOrg, eDst ) is the basic operation for changing the + * mesh connectivity and topology. It changes the mesh so that + * eOrg->Onext <- OLD( eDst->Onext ) + * eDst->Onext <- OLD( eOrg->Onext ) + * where OLD(...) means the value before the meshSplice operation. + * + * This can have two effects on the vertex structure: + * - if eOrg->Org != eDst->Org, the two vertices are merged together + * - if eOrg->Org == eDst->Org, the origin is split into two vertices + * In both cases, eDst->Org is changed and eOrg->Org is untouched. + * + * Similarly (and independently) for the face structure, + * - if eOrg->Lface == eDst->Lface, one loop is split into two + * - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one + * In both cases, eDst->Lface is changed and eOrg->Lface is unaffected. + * + * __gl_meshDelete( eDel ) removes the edge eDel. There are several cases: + * if (eDel->Lface != eDel->Rface), we join two loops into one; the loop + * eDel->Lface is deleted. Otherwise, we are splitting one loop into two; + * the newly created loop will contain eDel->Dst. If the deletion of eDel + * would create isolated vertices, those are deleted as well. + * + * ********************** Other Edge Operations ************************** + * + * __gl_meshAddEdgeVertex( eOrg ) creates a new edge eNew such that + * eNew == eOrg->Lnext, and eNew->Dst is a newly created vertex. + * eOrg and eNew will have the same left face. + * + * __gl_meshSplitEdge( eOrg ) splits eOrg into two edges eOrg and eNew, + * such that eNew == eOrg->Lnext. The new vertex is eOrg->Dst == eNew->Org. + * eOrg and eNew will have the same left face. + * + * __gl_meshConnect( eOrg, eDst ) creates a new edge from eOrg->Dst + * to eDst->Org, and returns the corresponding half-edge eNew. + * If eOrg->Lface == eDst->Lface, this splits one loop into two, + * and the newly created loop is eNew->Lface. Otherwise, two disjoint + * loops are merged into one, and the loop eDst->Lface is destroyed. + * + * ************************ Other Operations ***************************** + * + * __gl_meshNewMesh() creates a new mesh with no edges, no vertices, + * and no loops (what we usually call a "face"). + * + * __gl_meshUnion( mesh1, mesh2 ) forms the union of all structures in + * both meshes, and returns the new mesh (the old meshes are destroyed). + * + * __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh. + * + * __gl_meshZapFace( fZap ) destroys a face and removes it from the + * global face list. All edges of fZap will have a NULL pointer as their + * left face. Any edges which also have a NULL pointer as their right face + * are deleted entirely (along with any isolated vertices this produces). + * An entire mesh can be deleted by zapping its faces, one at a time, + * in any order. Zapped faces cannot be used in further mesh operations! + * + * __gl_meshCheckMesh( mesh ) checks a mesh for self-consistency. + */ + +GLUhalfEdge *__gl_meshMakeEdge( GLUmesh *mesh ); +int __gl_meshSplice( GLUhalfEdge *eOrg, GLUhalfEdge *eDst ); +int __gl_meshDelete( GLUhalfEdge *eDel ); + +GLUhalfEdge *__gl_meshAddEdgeVertex( GLUhalfEdge *eOrg ); +GLUhalfEdge *__gl_meshSplitEdge( GLUhalfEdge *eOrg ); +GLUhalfEdge *__gl_meshConnect( GLUhalfEdge *eOrg, GLUhalfEdge *eDst ); + +GLUmesh *__gl_meshNewMesh( void ); +GLUmesh *__gl_meshUnion( GLUmesh *mesh1, GLUmesh *mesh2 ); +void __gl_meshDeleteMesh( GLUmesh *mesh ); +void __gl_meshZapFace( GLUface *fZap ); + +#ifdef NDEBUG +#define __gl_meshCheckMesh( mesh ) +#else +void __gl_meshCheckMesh( GLUmesh *mesh ); +#endif + +#endif diff --git a/cogl/cogl-path/tesselator/normal.c b/cogl/cogl-path/tesselator/normal.c new file mode 100644 index 0000000..9a3bd43 --- /dev/null +++ b/cogl/cogl-path/tesselator/normal.c @@ -0,0 +1,257 @@ +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ +/* +** Author: Eric Veach, July 1994. +** +*/ + +#include "gluos.h" +#include "mesh.h" +#include "tess.h" +#include "normal.h" +#include +#include + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#define Dot(u,v) (u[0]*v[0] + u[1]*v[1] + u[2]*v[2]) + +#if 0 +static void Normalize( GLdouble v[3] ) +{ + GLdouble len = v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; + + assert( len > 0 ); + len = sqrt( len ); + v[0] /= len; + v[1] /= len; + v[2] /= len; +} +#endif + +#undef ABS +#define ABS(x) ((x) < 0 ? -(x) : (x)) + +static int LongAxis( GLdouble v[3] ) +{ + int i = 0; + + if( ABS(v[1]) > ABS(v[0]) ) { i = 1; } + if( ABS(v[2]) > ABS(v[i]) ) { i = 2; } + return i; +} + +static void ComputeNormal( GLUtesselator *tess, GLdouble norm[3] ) +{ + GLUvertex *v, *v1, *v2; + GLdouble c, tLen2, maxLen2; + GLdouble maxVal[3], minVal[3], d1[3], d2[3], tNorm[3]; + GLUvertex *maxVert[3], *minVert[3]; + GLUvertex *vHead = &tess->mesh->vHead; + int i; + + maxVal[0] = maxVal[1] = maxVal[2] = -2 * GLU_TESS_MAX_COORD; + minVal[0] = minVal[1] = minVal[2] = 2 * GLU_TESS_MAX_COORD; + + for( v = vHead->next; v != vHead; v = v->next ) { + for( i = 0; i < 3; ++i ) { + c = v->coords[i]; + if( c < minVal[i] ) { minVal[i] = c; minVert[i] = v; } + if( c > maxVal[i] ) { maxVal[i] = c; maxVert[i] = v; } + } + } + + /* Find two vertices separated by at least 1/sqrt(3) of the maximum + * distance between any two vertices + */ + i = 0; + if( maxVal[1] - minVal[1] > maxVal[0] - minVal[0] ) { i = 1; } + if( maxVal[2] - minVal[2] > maxVal[i] - minVal[i] ) { i = 2; } + if( minVal[i] >= maxVal[i] ) { + /* All vertices are the same -- normal doesn't matter */ + norm[0] = 0; norm[1] = 0; norm[2] = 1; + return; + } + + /* Look for a third vertex which forms the triangle with maximum area + * (Length of normal == twice the triangle area) + */ + maxLen2 = 0; + v1 = minVert[i]; + v2 = maxVert[i]; + d1[0] = v1->coords[0] - v2->coords[0]; + d1[1] = v1->coords[1] - v2->coords[1]; + d1[2] = v1->coords[2] - v2->coords[2]; + for( v = vHead->next; v != vHead; v = v->next ) { + d2[0] = v->coords[0] - v2->coords[0]; + d2[1] = v->coords[1] - v2->coords[1]; + d2[2] = v->coords[2] - v2->coords[2]; + tNorm[0] = d1[1]*d2[2] - d1[2]*d2[1]; + tNorm[1] = d1[2]*d2[0] - d1[0]*d2[2]; + tNorm[2] = d1[0]*d2[1] - d1[1]*d2[0]; + tLen2 = tNorm[0]*tNorm[0] + tNorm[1]*tNorm[1] + tNorm[2]*tNorm[2]; + if( tLen2 > maxLen2 ) { + maxLen2 = tLen2; + norm[0] = tNorm[0]; + norm[1] = tNorm[1]; + norm[2] = tNorm[2]; + } + } + + if( maxLen2 <= 0 ) { + /* All points lie on a single line -- any decent normal will do */ + norm[0] = norm[1] = norm[2] = 0; + norm[LongAxis(d1)] = 1; + } +} + + +static void CheckOrientation( GLUtesselator *tess ) +{ + GLdouble area; + GLUface *f, *fHead = &tess->mesh->fHead; + GLUvertex *v, *vHead = &tess->mesh->vHead; + GLUhalfEdge *e; + + /* When we compute the normal automatically, we choose the orientation + * so that the sum of the signed areas of all contours is non-negative. + */ + area = 0; + for( f = fHead->next; f != fHead; f = f->next ) { + e = f->anEdge; + if( e->winding <= 0 ) continue; + do { + area += (e->Org->s - e->Dst->s) * (e->Org->t + e->Dst->t); + e = e->Lnext; + } while( e != f->anEdge ); + } + if( area < 0 ) { + /* Reverse the orientation by flipping all the t-coordinates */ + for( v = vHead->next; v != vHead; v = v->next ) { + v->t = - v->t; + } + tess->tUnit[0] = - tess->tUnit[0]; + tess->tUnit[1] = - tess->tUnit[1]; + tess->tUnit[2] = - tess->tUnit[2]; + } +} + +#ifdef FOR_TRITE_TEST_PROGRAM +#include +extern int RandomSweep; +#define S_UNIT_X (RandomSweep ? (2*drand48()-1) : 1.0) +#define S_UNIT_Y (RandomSweep ? (2*drand48()-1) : 0.0) +#else +#if defined(SLANTED_SWEEP) +/* The "feature merging" is not intended to be complete. There are + * special cases where edges are nearly parallel to the sweep line + * which are not implemented. The algorithm should still behave + * robustly (ie. produce a reasonable tesselation) in the presence + * of such edges, however it may miss features which could have been + * merged. We could minimize this effect by choosing the sweep line + * direction to be something unusual (ie. not parallel to one of the + * coordinate axes). + */ +#define S_UNIT_X 0.50941539564955385 /* Pre-normalized */ +#define S_UNIT_Y 0.86052074622010633 +#else +#define S_UNIT_X 1.0 +#define S_UNIT_Y 0.0 +#endif +#endif + +/* Determine the polygon normal and project vertices onto the plane + * of the polygon. + */ +void __gl_projectPolygon( GLUtesselator *tess ) +{ + GLUvertex *v, *vHead = &tess->mesh->vHead; + GLdouble norm[3]; + GLdouble *sUnit, *tUnit; + int i, computedNormal = FALSE; + + norm[0] = tess->normal[0]; + norm[1] = tess->normal[1]; + norm[2] = tess->normal[2]; + if( norm[0] == 0 && norm[1] == 0 && norm[2] == 0 ) { + ComputeNormal( tess, norm ); + computedNormal = TRUE; + } + sUnit = tess->sUnit; + tUnit = tess->tUnit; + i = LongAxis( norm ); + +#if defined(FOR_TRITE_TEST_PROGRAM) || defined(TRUE_PROJECT) + /* Choose the initial sUnit vector to be approximately perpendicular + * to the normal. + */ + Normalize( norm ); + + sUnit[i] = 0; + sUnit[(i+1)%3] = S_UNIT_X; + sUnit[(i+2)%3] = S_UNIT_Y; + + /* Now make it exactly perpendicular */ + w = Dot( sUnit, norm ); + sUnit[0] -= w * norm[0]; + sUnit[1] -= w * norm[1]; + sUnit[2] -= w * norm[2]; + Normalize( sUnit ); + + /* Choose tUnit so that (sUnit,tUnit,norm) form a right-handed frame */ + tUnit[0] = norm[1]*sUnit[2] - norm[2]*sUnit[1]; + tUnit[1] = norm[2]*sUnit[0] - norm[0]*sUnit[2]; + tUnit[2] = norm[0]*sUnit[1] - norm[1]*sUnit[0]; + Normalize( tUnit ); +#else + /* Project perpendicular to a coordinate axis -- better numerically */ + sUnit[i] = 0; + sUnit[(i+1)%3] = S_UNIT_X; + sUnit[(i+2)%3] = S_UNIT_Y; + + tUnit[i] = 0; + tUnit[(i+1)%3] = (norm[i] > 0) ? -S_UNIT_Y : S_UNIT_Y; + tUnit[(i+2)%3] = (norm[i] > 0) ? S_UNIT_X : -S_UNIT_X; +#endif + + /* Project the vertices onto the sweep plane */ + for( v = vHead->next; v != vHead; v = v->next ) { + v->s = Dot( v->coords, sUnit ); + v->t = Dot( v->coords, tUnit ); + } + if( computedNormal ) { + CheckOrientation( tess ); + } +} diff --git a/cogl/cogl-path/tesselator/normal.h b/cogl/cogl-path/tesselator/normal.h new file mode 100644 index 0000000..c376ca4 --- /dev/null +++ b/cogl/cogl-path/tesselator/normal.h @@ -0,0 +1,45 @@ +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ +/* +** Author: Eric Veach, July 1994. +** +*/ + +#ifndef __normal_h_ +#define __normal_h_ + +#include "tess.h" + +/* __gl_projectPolygon( tess ) determines the polygon normal + * and project vertices onto the plane of the polygon. + */ +void __gl_projectPolygon( GLUtesselator *tess ); + +#endif diff --git a/cogl/cogl-path/tesselator/priorityq-heap.c b/cogl/cogl-path/tesselator/priorityq-heap.c new file mode 100644 index 0000000..52698b5 --- /dev/null +++ b/cogl/cogl-path/tesselator/priorityq-heap.c @@ -0,0 +1,256 @@ +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ +/* +** Author: Eric Veach, July 1994. +** +*/ + +#include +#include +#include "priorityq-heap.h" +#include "memalloc.h" + +#define INIT_SIZE 32 + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#ifdef FOR_TRITE_TEST_PROGRAM +#define LEQ(x,y) (*pq->leq)(x,y) +#else +/* Violates modularity, but a little faster */ +#include "geom.h" +#define LEQ(x,y) VertLeq((GLUvertex *)x, (GLUvertex *)y) +#endif + +/* really __gl_pqHeapNewPriorityQ */ +PriorityQ *pqNewPriorityQ( int (*leq)(PQkey key1, PQkey key2) ) +{ + PriorityQ *pq = (PriorityQ *)memAlloc( sizeof( PriorityQ )); + if (pq == NULL) return NULL; + + pq->size = 0; + pq->max = INIT_SIZE; + pq->nodes = (PQnode *)memAlloc( (INIT_SIZE + 1) * sizeof(pq->nodes[0]) ); + if (pq->nodes == NULL) { + memFree(pq); + return NULL; + } + + pq->handles = (PQhandleElem *)memAlloc( (INIT_SIZE + 1) * sizeof(pq->handles[0]) ); + if (pq->handles == NULL) { + memFree(pq->nodes); + memFree(pq); + return NULL; + } + + pq->initialized = FALSE; + pq->freeList = 0; + pq->leq = leq; + + pq->nodes[1].handle = 1; /* so that Minimum() returns NULL */ + pq->handles[1].key = NULL; + return pq; +} + +/* really __gl_pqHeapDeletePriorityQ */ +void pqDeletePriorityQ( PriorityQ *pq ) +{ + memFree( pq->handles ); + memFree( pq->nodes ); + memFree( pq ); +} + + +static void FloatDown( PriorityQ *pq, long curr ) +{ + PQnode *n = pq->nodes; + PQhandleElem *h = pq->handles; + PQhandle hCurr, hChild; + long child; + + hCurr = n[curr].handle; + for( ;; ) { + child = curr << 1; + if( child < pq->size && LEQ( h[n[child+1].handle].key, + h[n[child].handle].key )) { + ++child; + } + + assert(child <= pq->max); + + hChild = n[child].handle; + if( child > pq->size || LEQ( h[hCurr].key, h[hChild].key )) { + n[curr].handle = hCurr; + h[hCurr].node = curr; + break; + } + n[curr].handle = hChild; + h[hChild].node = curr; + curr = child; + } +} + + +static void FloatUp( PriorityQ *pq, long curr ) +{ + PQnode *n = pq->nodes; + PQhandleElem *h = pq->handles; + PQhandle hCurr, hParent; + long parent; + + hCurr = n[curr].handle; + for( ;; ) { + parent = curr >> 1; + hParent = n[parent].handle; + if( parent == 0 || LEQ( h[hParent].key, h[hCurr].key )) { + n[curr].handle = hCurr; + h[hCurr].node = curr; + break; + } + n[curr].handle = hParent; + h[hParent].node = curr; + curr = parent; + } +} + +/* really __gl_pqHeapInit */ +void pqInit( PriorityQ *pq ) +{ + long i; + + /* This method of building a heap is O(n), rather than O(n lg n). */ + + for( i = pq->size; i >= 1; --i ) { + FloatDown( pq, i ); + } + pq->initialized = TRUE; +} + +/* really __gl_pqHeapInsert */ +/* returns LONG_MAX iff out of memory */ +PQhandle pqInsert( PriorityQ *pq, PQkey keyNew ) +{ + long curr; + PQhandle free_handle; + + curr = ++ pq->size; + if( (curr*2) > pq->max ) { + PQnode *saveNodes= pq->nodes; + PQhandleElem *saveHandles= pq->handles; + + /* If the heap overflows, double its size. */ + pq->max <<= 1; + pq->nodes = (PQnode *)memRealloc( pq->nodes, + (size_t) + ((pq->max + 1) * sizeof( pq->nodes[0] ))); + if (pq->nodes == NULL) { + pq->nodes = saveNodes; /* restore ptr to free upon return */ + return LONG_MAX; + } + pq->handles = (PQhandleElem *)memRealloc( pq->handles, + (size_t) + ((pq->max + 1) * + sizeof( pq->handles[0] ))); + if (pq->handles == NULL) { + pq->handles = saveHandles; /* restore ptr to free upon return */ + return LONG_MAX; + } + } + + if( pq->freeList == 0 ) { + free_handle = curr; + } else { + free_handle = pq->freeList; + pq->freeList = pq->handles[free_handle].node; + } + + pq->nodes[curr].handle = free_handle; + pq->handles[free_handle].node = curr; + pq->handles[free_handle].key = keyNew; + + if( pq->initialized ) { + FloatUp( pq, curr ); + } + assert(free_handle != LONG_MAX); + return free_handle; +} + +/* really __gl_pqHeapExtractMin */ +PQkey pqExtractMin( PriorityQ *pq ) +{ + PQnode *n = pq->nodes; + PQhandleElem *h = pq->handles; + PQhandle hMin = n[1].handle; + PQkey min = h[hMin].key; + + if( pq->size > 0 ) { + n[1].handle = n[pq->size].handle; + h[n[1].handle].node = 1; + + h[hMin].key = NULL; + h[hMin].node = pq->freeList; + pq->freeList = hMin; + + if( -- pq->size > 0 ) { + FloatDown( pq, 1 ); + } + } + return min; +} + +/* really __gl_pqHeapDelete */ +void pqDelete( PriorityQ *pq, PQhandle hCurr ) +{ + PQnode *n = pq->nodes; + PQhandleElem *h = pq->handles; + long curr; + + assert( hCurr >= 1 && hCurr <= pq->max && h[hCurr].key != NULL ); + + curr = h[hCurr].node; + n[curr].handle = n[pq->size].handle; + h[n[curr].handle].node = curr; + + if( curr <= -- pq->size ) { + if( curr <= 1 || LEQ( h[n[curr>>1].handle].key, h[n[curr].handle].key )) { + FloatDown( pq, curr ); + } else { + FloatUp( pq, curr ); + } + } + h[hCurr].key = NULL; + h[hCurr].node = pq->freeList; + pq->freeList = hCurr; +} diff --git a/cogl/cogl-path/tesselator/priorityq-heap.h b/cogl/cogl-path/tesselator/priorityq-heap.h new file mode 100644 index 0000000..dc9aaef --- /dev/null +++ b/cogl/cogl-path/tesselator/priorityq-heap.h @@ -0,0 +1,107 @@ +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ +/* +** Author: Eric Veach, July 1994. +** +*/ + +#ifndef __priorityq_heap_h_ +#define __priorityq_heap_h_ + +/* Use #define's so that another heap implementation can use this one */ + +#define PQkey PQHeapKey +#define PQhandle PQHeapHandle +#define PriorityQ PriorityQHeap + +#define pqNewPriorityQ(leq) __gl_pqHeapNewPriorityQ(leq) +#define pqDeletePriorityQ(pq) __gl_pqHeapDeletePriorityQ(pq) + +/* The basic operations are insertion of a new key (pqInsert), + * and examination/extraction of a key whose value is minimum + * (pqMinimum/pqExtractMin). Deletion is also allowed (pqDelete); + * for this purpose pqInsert returns a "handle" which is supplied + * as the argument. + * + * An initial heap may be created efficiently by calling pqInsert + * repeatedly, then calling pqInit. In any case pqInit must be called + * before any operations other than pqInsert are used. + * + * If the heap is empty, pqMinimum/pqExtractMin will return a NULL key. + * This may also be tested with pqIsEmpty. + */ +#define pqInit(pq) __gl_pqHeapInit(pq) +#define pqInsert(pq,key) __gl_pqHeapInsert(pq,key) +#define pqMinimum(pq) __gl_pqHeapMinimum(pq) +#define pqExtractMin(pq) __gl_pqHeapExtractMin(pq) +#define pqDelete(pq,handle) __gl_pqHeapDelete(pq,handle) +#define pqIsEmpty(pq) __gl_pqHeapIsEmpty(pq) + + +/* Since we support deletion the data structure is a little more + * complicated than an ordinary heap. "nodes" is the heap itself; + * active nodes are stored in the range 1..pq->size. When the + * heap exceeds its allocated size (pq->max), its size doubles. + * The children of node i are nodes 2i and 2i+1. + * + * Each node stores an index into an array "handles". Each handle + * stores a key, plus a pointer back to the node which currently + * represents that key (ie. nodes[handles[i].node].handle == i). + */ + +typedef void *PQkey; +typedef long PQhandle; +typedef struct PriorityQ PriorityQ; + +typedef struct { PQhandle handle; } PQnode; +typedef struct { PQkey key; PQhandle node; } PQhandleElem; + +struct PriorityQ { + PQnode *nodes; + PQhandleElem *handles; + long size, max; + PQhandle freeList; + int initialized; + int (*leq)(PQkey key1, PQkey key2); +}; + +PriorityQ *pqNewPriorityQ( int (*leq)(PQkey key1, PQkey key2) ); +void pqDeletePriorityQ( PriorityQ *pq ); + +void pqInit( PriorityQ *pq ); +PQhandle pqInsert( PriorityQ *pq, PQkey key ); +PQkey pqExtractMin( PriorityQ *pq ); +void pqDelete( PriorityQ *pq, PQhandle handle ); + + +#define __gl_pqHeapMinimum(pq) ((pq)->handles[(pq)->nodes[1].handle].key) +#define __gl_pqHeapIsEmpty(pq) ((pq)->size == 0) + +#endif diff --git a/cogl/cogl-path/tesselator/priorityq-sort.h b/cogl/cogl-path/tesselator/priorityq-sort.h new file mode 100644 index 0000000..746cf5f --- /dev/null +++ b/cogl/cogl-path/tesselator/priorityq-sort.h @@ -0,0 +1,117 @@ +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ +/* +** Author: Eric Veach, July 1994. +** +*/ + +#ifndef __priorityq_sort_h_ +#define __priorityq_sort_h_ + +#include "priorityq-heap.h" + +#undef PQkey +#undef PQhandle +#undef PriorityQ +#undef pqNewPriorityQ +#undef pqDeletePriorityQ +#undef pqInit +#undef pqInsert +#undef pqMinimum +#undef pqExtractMin +#undef pqDelete +#undef pqIsEmpty + +/* Use #define's so that another heap implementation can use this one */ + +#define PQkey PQSortKey +#define PQhandle PQSortHandle +#define PriorityQ PriorityQSort + +#define pqNewPriorityQ(leq) __gl_pqSortNewPriorityQ(leq) +#define pqDeletePriorityQ(pq) __gl_pqSortDeletePriorityQ(pq) + +/* The basic operations are insertion of a new key (pqInsert), + * and examination/extraction of a key whose value is minimum + * (pqMinimum/pqExtractMin). Deletion is also allowed (pqDelete); + * for this purpose pqInsert returns a "handle" which is supplied + * as the argument. + * + * An initial heap may be created efficiently by calling pqInsert + * repeatedly, then calling pqInit. In any case pqInit must be called + * before any operations other than pqInsert are used. + * + * If the heap is empty, pqMinimum/pqExtractMin will return a NULL key. + * This may also be tested with pqIsEmpty. + */ +#define pqInit(pq) __gl_pqSortInit(pq) +#define pqInsert(pq,key) __gl_pqSortInsert(pq,key) +#define pqMinimum(pq) __gl_pqSortMinimum(pq) +#define pqExtractMin(pq) __gl_pqSortExtractMin(pq) +#define pqDelete(pq,handle) __gl_pqSortDelete(pq,handle) +#define pqIsEmpty(pq) __gl_pqSortIsEmpty(pq) + + +/* Since we support deletion the data structure is a little more + * complicated than an ordinary heap. "nodes" is the heap itself; + * active nodes are stored in the range 1..pq->size. When the + * heap exceeds its allocated size (pq->max), its size doubles. + * The children of node i are nodes 2i and 2i+1. + * + * Each node stores an index into an array "handles". Each handle + * stores a key, plus a pointer back to the node which currently + * represents that key (ie. nodes[handles[i].node].handle == i). + */ + +typedef PQHeapKey PQkey; +typedef PQHeapHandle PQhandle; +typedef struct PriorityQ PriorityQ; + +struct PriorityQ { + PriorityQHeap *heap; + PQkey *keys; + PQkey **order; + PQhandle size, max; + int initialized; + int (*leq)(PQkey key1, PQkey key2); +}; + +PriorityQ *pqNewPriorityQ( int (*leq)(PQkey key1, PQkey key2) ); +void pqDeletePriorityQ( PriorityQ *pq ); + +int pqInit( PriorityQ *pq ); +PQhandle pqInsert( PriorityQ *pq, PQkey key ); +PQkey pqExtractMin( PriorityQ *pq ); +void pqDelete( PriorityQ *pq, PQhandle handle ); + +PQkey pqMinimum( PriorityQ *pq ); +int pqIsEmpty( PriorityQ *pq ); + +#endif diff --git a/cogl/cogl-path/tesselator/priorityq.c b/cogl/cogl-path/tesselator/priorityq.c new file mode 100644 index 0000000..db7cd59 --- /dev/null +++ b/cogl/cogl-path/tesselator/priorityq.c @@ -0,0 +1,261 @@ +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ +/* +** Author: Eric Veach, July 1994. +** +*/ + +#include "gluos.h" +#include +#include +#include /* LONG_MAX */ +#include "memalloc.h" + +/* Include all the code for the regular heap-based queue here. */ + +#include "priorityq-heap.c" + +/* Now redefine all the function names to map to their "Sort" versions. */ + +#include "priorityq-sort.h" + +/* really __gl_pqSortNewPriorityQ */ +PriorityQ *pqNewPriorityQ( int (*leq)(PQkey key1, PQkey key2) ) +{ + PriorityQ *pq = (PriorityQ *)memAlloc( sizeof( PriorityQ )); + if (pq == NULL) return NULL; + + pq->heap = __gl_pqHeapNewPriorityQ( leq ); + if (pq->heap == NULL) { + memFree(pq); + return NULL; + } + + pq->keys = (PQHeapKey *)memAlloc( INIT_SIZE * sizeof(pq->keys[0]) ); + if (pq->keys == NULL) { + __gl_pqHeapDeletePriorityQ(pq->heap); + memFree(pq); + return NULL; + } + + pq->order = NULL; + pq->size = 0; + pq->max = INIT_SIZE; + pq->initialized = FALSE; + pq->leq = leq; + return pq; +} + +/* really __gl_pqSortDeletePriorityQ */ +void pqDeletePriorityQ( PriorityQ *pq ) +{ + assert(pq != NULL); + if (pq->heap != NULL) __gl_pqHeapDeletePriorityQ( pq->heap ); + if (pq->order != NULL) memFree( pq->order ); + if (pq->keys != NULL) memFree( pq->keys ); + memFree( pq ); +} + + +#define LT(x,y) (! LEQ(y,x)) +#define GT(x,y) (! LEQ(x,y)) +#define Swap(a,b) do{PQkey *tmp = *a; *a = *b; *b = tmp;}while(0) + +/* really __gl_pqSortInit */ +int pqInit( PriorityQ *pq ) +{ + PQkey **p, **r, **i, **j, *piv; + struct { PQkey **p, **r; } Stack[50], *top = Stack; + unsigned long seed = 2016473283; + + /* Create an array of indirect pointers to the keys, so that we + * the handles we have returned are still valid. + */ +/* + pq->order = (PQHeapKey **)memAlloc( (size_t) + (pq->size * sizeof(pq->order[0])) ); +*/ + pq->order = (PQHeapKey **)memAlloc( (size_t) + ((pq->size+1) * sizeof(pq->order[0])) ); +/* the previous line is a patch to compensate for the fact that IBM */ +/* machines return a null on a malloc of zero bytes (unlike SGI), */ +/* so we have to put in this defense to guard against a memory */ +/* fault four lines down. from fossum@austin.ibm.com. */ + if (pq->order == NULL) return 0; + + p = pq->order; + r = p + pq->size - 1; + for( piv = pq->keys, i = p; i <= r; ++piv, ++i ) { + *i = piv; + } + + /* Sort the indirect pointers in descending order, + * using randomized Quicksort + */ + top->p = p; top->r = r; ++top; + while( --top >= Stack ) { + p = top->p; + r = top->r; + while( r > p + 10 ) { + seed = seed * 1539415821 + 1; + i = p + seed % (r - p + 1); + piv = *i; + *i = *p; + *p = piv; + i = p - 1; + j = r + 1; + do { + do { ++i; } while( GT( **i, *piv )); + do { --j; } while( LT( **j, *piv )); + Swap( i, j ); + } while( i < j ); + Swap( i, j ); /* Undo last swap */ + if( i - p < r - j ) { + top->p = j+1; top->r = r; ++top; + r = i-1; + } else { + top->p = p; top->r = i-1; ++top; + p = j+1; + } + } + /* Insertion sort small lists */ + for( i = p+1; i <= r; ++i ) { + piv = *i; + for( j = i; j > p && LT( **(j-1), *piv ); --j ) { + *j = *(j-1); + } + *j = piv; + } + } + pq->max = pq->size; + pq->initialized = TRUE; + __gl_pqHeapInit( pq->heap ); /* always succeeds */ + +#ifndef NDEBUG + p = pq->order; + r = p + pq->size - 1; + for( i = p; i < r; ++i ) { + assert( LEQ( **(i+1), **i )); + } +#endif + + return 1; +} + +/* really __gl_pqSortInsert */ +/* returns LONG_MAX iff out of memory */ +PQhandle pqInsert( PriorityQ *pq, PQkey keyNew ) +{ + long curr; + + if( pq->initialized ) { + return __gl_pqHeapInsert( pq->heap, keyNew ); + } + curr = pq->size; + if( ++ pq->size >= pq->max ) { + PQkey *saveKey= pq->keys; + + /* If the heap overflows, double its size. */ + pq->max <<= 1; + pq->keys = (PQHeapKey *)memRealloc( pq->keys, + (size_t) + (pq->max * sizeof( pq->keys[0] ))); + if (pq->keys == NULL) { + pq->keys = saveKey; /* restore ptr to free upon return */ + return LONG_MAX; + } + } + assert(curr != LONG_MAX); + pq->keys[curr] = keyNew; + + /* Negative handles index the sorted array. */ + return -(curr+1); +} + +/* really __gl_pqSortExtractMin */ +PQkey pqExtractMin( PriorityQ *pq ) +{ + PQkey sortMin, heapMin; + + if( pq->size == 0 ) { + return __gl_pqHeapExtractMin( pq->heap ); + } + sortMin = *(pq->order[pq->size-1]); + if( ! __gl_pqHeapIsEmpty( pq->heap )) { + heapMin = __gl_pqHeapMinimum( pq->heap ); + if( LEQ( heapMin, sortMin )) { + return __gl_pqHeapExtractMin( pq->heap ); + } + } + do { + -- pq->size; + } while( pq->size > 0 && *(pq->order[pq->size-1]) == NULL ); + return sortMin; +} + +/* really __gl_pqSortMinimum */ +PQkey pqMinimum( PriorityQ *pq ) +{ + PQkey sortMin, heapMin; + + if( pq->size == 0 ) { + return __gl_pqHeapMinimum( pq->heap ); + } + sortMin = *(pq->order[pq->size-1]); + if( ! __gl_pqHeapIsEmpty( pq->heap )) { + heapMin = __gl_pqHeapMinimum( pq->heap ); + if( LEQ( heapMin, sortMin )) { + return heapMin; + } + } + return sortMin; +} + +/* really __gl_pqSortIsEmpty */ +int pqIsEmpty( PriorityQ *pq ) +{ + return (pq->size == 0) && __gl_pqHeapIsEmpty( pq->heap ); +} + +/* really __gl_pqSortDelete */ +void pqDelete( PriorityQ *pq, PQhandle curr ) +{ + if( curr >= 0 ) { + __gl_pqHeapDelete( pq->heap, curr ); + return; + } + curr = -(curr+1); + assert( curr < pq->max && pq->keys[curr] != NULL ); + + pq->keys[curr] = NULL; + while( pq->size > 0 && *(pq->order[pq->size-1]) == NULL ) { + -- pq->size; + } +} diff --git a/cogl/cogl-path/tesselator/priorityq.h b/cogl/cogl-path/tesselator/priorityq.h new file mode 100644 index 0000000..746cf5f --- /dev/null +++ b/cogl/cogl-path/tesselator/priorityq.h @@ -0,0 +1,117 @@ +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ +/* +** Author: Eric Veach, July 1994. +** +*/ + +#ifndef __priorityq_sort_h_ +#define __priorityq_sort_h_ + +#include "priorityq-heap.h" + +#undef PQkey +#undef PQhandle +#undef PriorityQ +#undef pqNewPriorityQ +#undef pqDeletePriorityQ +#undef pqInit +#undef pqInsert +#undef pqMinimum +#undef pqExtractMin +#undef pqDelete +#undef pqIsEmpty + +/* Use #define's so that another heap implementation can use this one */ + +#define PQkey PQSortKey +#define PQhandle PQSortHandle +#define PriorityQ PriorityQSort + +#define pqNewPriorityQ(leq) __gl_pqSortNewPriorityQ(leq) +#define pqDeletePriorityQ(pq) __gl_pqSortDeletePriorityQ(pq) + +/* The basic operations are insertion of a new key (pqInsert), + * and examination/extraction of a key whose value is minimum + * (pqMinimum/pqExtractMin). Deletion is also allowed (pqDelete); + * for this purpose pqInsert returns a "handle" which is supplied + * as the argument. + * + * An initial heap may be created efficiently by calling pqInsert + * repeatedly, then calling pqInit. In any case pqInit must be called + * before any operations other than pqInsert are used. + * + * If the heap is empty, pqMinimum/pqExtractMin will return a NULL key. + * This may also be tested with pqIsEmpty. + */ +#define pqInit(pq) __gl_pqSortInit(pq) +#define pqInsert(pq,key) __gl_pqSortInsert(pq,key) +#define pqMinimum(pq) __gl_pqSortMinimum(pq) +#define pqExtractMin(pq) __gl_pqSortExtractMin(pq) +#define pqDelete(pq,handle) __gl_pqSortDelete(pq,handle) +#define pqIsEmpty(pq) __gl_pqSortIsEmpty(pq) + + +/* Since we support deletion the data structure is a little more + * complicated than an ordinary heap. "nodes" is the heap itself; + * active nodes are stored in the range 1..pq->size. When the + * heap exceeds its allocated size (pq->max), its size doubles. + * The children of node i are nodes 2i and 2i+1. + * + * Each node stores an index into an array "handles". Each handle + * stores a key, plus a pointer back to the node which currently + * represents that key (ie. nodes[handles[i].node].handle == i). + */ + +typedef PQHeapKey PQkey; +typedef PQHeapHandle PQhandle; +typedef struct PriorityQ PriorityQ; + +struct PriorityQ { + PriorityQHeap *heap; + PQkey *keys; + PQkey **order; + PQhandle size, max; + int initialized; + int (*leq)(PQkey key1, PQkey key2); +}; + +PriorityQ *pqNewPriorityQ( int (*leq)(PQkey key1, PQkey key2) ); +void pqDeletePriorityQ( PriorityQ *pq ); + +int pqInit( PriorityQ *pq ); +PQhandle pqInsert( PriorityQ *pq, PQkey key ); +PQkey pqExtractMin( PriorityQ *pq ); +void pqDelete( PriorityQ *pq, PQhandle handle ); + +PQkey pqMinimum( PriorityQ *pq ); +int pqIsEmpty( PriorityQ *pq ); + +#endif diff --git a/cogl/cogl-path/tesselator/render.c b/cogl/cogl-path/tesselator/render.c new file mode 100644 index 0000000..bca836f --- /dev/null +++ b/cogl/cogl-path/tesselator/render.c @@ -0,0 +1,502 @@ +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ +/* +** Author: Eric Veach, July 1994. +** +*/ + +#include "gluos.h" +#include +#include +#include "mesh.h" +#include "tess.h" +#include "render.h" + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +/* This structure remembers the information we need about a primitive + * to be able to render it later, once we have determined which + * primitive is able to use the most triangles. + */ +struct FaceCount { + long size; /* number of triangles used */ + GLUhalfEdge *eStart; /* edge where this primitive starts */ + void (*render)(GLUtesselator *, GLUhalfEdge *, long); + /* routine to render this primitive */ +}; + +static struct FaceCount MaximumFan( GLUhalfEdge *eOrig ); +static struct FaceCount MaximumStrip( GLUhalfEdge *eOrig ); + +static void RenderFan( GLUtesselator *tess, GLUhalfEdge *eStart, long size ); +static void RenderStrip( GLUtesselator *tess, GLUhalfEdge *eStart, long size ); +static void RenderTriangle( GLUtesselator *tess, GLUhalfEdge *eStart, + long size ); + +static void RenderMaximumFaceGroup( GLUtesselator *tess, GLUface *fOrig ); +static void RenderLonelyTriangles( GLUtesselator *tess, GLUface *head ); + + + +/************************ Strips and Fans decomposition ******************/ + +/* __gl_renderMesh( tess, mesh ) takes a mesh and breaks it into triangle + * fans, strips, and separate triangles. A substantial effort is made + * to use as few rendering primitives as possible (ie. to make the fans + * and strips as large as possible). + * + * The rendering output is provided as callbacks (see the api). + */ +void __gl_renderMesh( GLUtesselator *tess, GLUmesh *mesh ) +{ + GLUface *f; + + /* Make a list of separate triangles so we can render them all at once */ + tess->lonelyTriList = NULL; + + for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) { + f->marked = FALSE; + } + for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) { + + /* We examine all faces in an arbitrary order. Whenever we find + * an unprocessed face F, we output a group of faces including F + * whose size is maximum. + */ + if( f->inside && ! f->marked ) { + RenderMaximumFaceGroup( tess, f ); + assert( f->marked ); + } + } + if( tess->lonelyTriList != NULL ) { + RenderLonelyTriangles( tess, tess->lonelyTriList ); + tess->lonelyTriList = NULL; + } +} + + +static void RenderMaximumFaceGroup( GLUtesselator *tess, GLUface *fOrig ) +{ + /* We want to find the largest triangle fan or strip of unmarked faces + * which includes the given face fOrig. There are 3 possible fans + * passing through fOrig (one centered at each vertex), and 3 possible + * strips (one for each CCW permutation of the vertices). Our strategy + * is to try all of these, and take the primitive which uses the most + * triangles (a greedy approach). + */ + GLUhalfEdge *e = fOrig->anEdge; + struct FaceCount max, newFace; + + max.size = 1; + max.eStart = e; + max.render = &RenderTriangle; + + if( ! tess->flagBoundary ) { + newFace = MaximumFan( e ); if( newFace.size > max.size ) { max = newFace; } + newFace = MaximumFan( e->Lnext ); if( newFace.size > max.size ) { max = newFace; } + newFace = MaximumFan( e->Lprev ); if( newFace.size > max.size ) { max = newFace; } + + newFace = MaximumStrip( e ); if( newFace.size > max.size ) { max = newFace; } + newFace = MaximumStrip( e->Lnext ); if( newFace.size > max.size ) { max = newFace; } + newFace = MaximumStrip( e->Lprev ); if( newFace.size > max.size ) { max = newFace; } + } + (*(max.render))( tess, max.eStart, max.size ); +} + + +/* Macros which keep track of faces we have marked temporarily, and allow + * us to backtrack when necessary. With triangle fans, this is not + * really necessary, since the only awkward case is a loop of triangles + * around a single origin vertex. However with strips the situation is + * more complicated, and we need a general tracking method like the + * one here. + */ +#define Marked(f) (! (f)->inside || (f)->marked) + +#define AddToTrail(f,t) ((f)->trail = (t), (t) = (f), (f)->marked = TRUE) + +#define FreeTrail(t) do { \ + while( (t) != NULL ) { \ + (t)->marked = FALSE; t = (t)->trail; \ + } \ + } while(0) /* absorb trailing semicolon */ + + + +static struct FaceCount MaximumFan( GLUhalfEdge *eOrig ) +{ + /* eOrig->Lface is the face we want to render. We want to find the size + * of a maximal fan around eOrig->Org. To do this we just walk around + * the origin vertex as far as possible in both directions. + */ + struct FaceCount newFace = { 0, NULL, &RenderFan }; + GLUface *trail = NULL; + GLUhalfEdge *e; + + for( e = eOrig; ! Marked( e->Lface ); e = e->Onext ) { + AddToTrail( e->Lface, trail ); + ++newFace.size; + } + for( e = eOrig; ! Marked( e->Rface ); e = e->Oprev ) { + AddToTrail( e->Rface, trail ); + ++newFace.size; + } + newFace.eStart = e; + /*LINTED*/ + FreeTrail( trail ); + return newFace; +} + + +#define IsEven(n) (((n) & 1) == 0) + +static struct FaceCount MaximumStrip( GLUhalfEdge *eOrig ) +{ + /* Here we are looking for a maximal strip that contains the vertices + * eOrig->Org, eOrig->Dst, eOrig->Lnext->Dst (in that order or the + * reverse, such that all triangles are oriented CCW). + * + * Again we walk forward and backward as far as possible. However for + * strips there is a twist: to get CCW orientations, there must be + * an *even* number of triangles in the strip on one side of eOrig. + * We walk the strip starting on a side with an even number of triangles; + * if both side have an odd number, we are forced to shorten one side. + */ + struct FaceCount newFace = { 0, NULL, &RenderStrip }; + long headSize = 0, tailSize = 0; + GLUface *trail = NULL; + GLUhalfEdge *e, *eTail, *eHead; + + for( e = eOrig; ! Marked( e->Lface ); ++tailSize, e = e->Onext ) { + AddToTrail( e->Lface, trail ); + ++tailSize; + e = e->Dprev; + if( Marked( e->Lface )) break; + AddToTrail( e->Lface, trail ); + } + eTail = e; + + for( e = eOrig; ! Marked( e->Rface ); ++headSize, e = e->Dnext ) { + AddToTrail( e->Rface, trail ); + ++headSize; + e = e->Oprev; + if( Marked( e->Rface )) break; + AddToTrail( e->Rface, trail ); + } + eHead = e; + + newFace.size = tailSize + headSize; + if( IsEven( tailSize )) { + newFace.eStart = eTail->Sym; + } else if( IsEven( headSize )) { + newFace.eStart = eHead; + } else { + /* Both sides have odd length, we must shorten one of them. In fact, + * we must start from eHead to guarantee inclusion of eOrig->Lface. + */ + --newFace.size; + newFace.eStart = eHead->Onext; + } + /*LINTED*/ + FreeTrail( trail ); + return newFace; +} + + +static void RenderTriangle( GLUtesselator *tess, GLUhalfEdge *e, long size ) +{ + /* Just add the triangle to a triangle list, so we can render all + * the separate triangles at once. + */ + assert( size == 1 ); + AddToTrail( e->Lface, tess->lonelyTriList ); +} + + +static void RenderLonelyTriangles( GLUtesselator *tess, GLUface *f ) +{ + /* Now we render all the separate triangles which could not be + * grouped into a triangle fan or strip. + */ + GLUhalfEdge *e; + int newState; + int edgeState = -1; /* force edge state output for first vertex */ + + CALL_BEGIN_OR_BEGIN_DATA( GL_TRIANGLES ); + + for( ; f != NULL; f = f->trail ) { + /* Loop once for each edge (there will always be 3 edges) */ + + e = f->anEdge; + do { + if( tess->flagBoundary ) { + /* Set the "edge state" to TRUE just before we output the + * first vertex of each edge on the polygon boundary. + */ + newState = ! e->Rface->inside; + if( edgeState != newState ) { + edgeState = newState; + CALL_EDGE_FLAG_OR_EDGE_FLAG_DATA( edgeState ); + } + } + CALL_VERTEX_OR_VERTEX_DATA( e->Org->data ); + + e = e->Lnext; + } while( e != f->anEdge ); + } + CALL_END_OR_END_DATA(); +} + + +static void RenderFan( GLUtesselator *tess, GLUhalfEdge *e, long size ) +{ + /* Render as many CCW triangles as possible in a fan starting from + * edge "e". The fan *should* contain exactly "size" triangles + * (otherwise we've goofed up somewhere). + */ + CALL_BEGIN_OR_BEGIN_DATA( GL_TRIANGLE_FAN ); + CALL_VERTEX_OR_VERTEX_DATA( e->Org->data ); + CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data ); + + while( ! Marked( e->Lface )) { + e->Lface->marked = TRUE; + --size; + e = e->Onext; + CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data ); + } + + assert( size == 0 ); + CALL_END_OR_END_DATA(); +} + + +static void RenderStrip( GLUtesselator *tess, GLUhalfEdge *e, long size ) +{ + /* Render as many CCW triangles as possible in a strip starting from + * edge "e". The strip *should* contain exactly "size" triangles + * (otherwise we've goofed up somewhere). + */ + CALL_BEGIN_OR_BEGIN_DATA( GL_TRIANGLE_STRIP ); + CALL_VERTEX_OR_VERTEX_DATA( e->Org->data ); + CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data ); + + while( ! Marked( e->Lface )) { + e->Lface->marked = TRUE; + --size; + e = e->Dprev; + CALL_VERTEX_OR_VERTEX_DATA( e->Org->data ); + if( Marked( e->Lface )) break; + + e->Lface->marked = TRUE; + --size; + e = e->Onext; + CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data ); + } + + assert( size == 0 ); + CALL_END_OR_END_DATA(); +} + + +/************************ Boundary contour decomposition ******************/ + +/* __gl_renderBoundary( tess, mesh ) takes a mesh, and outputs one + * contour for each face marked "inside". The rendering output is + * provided as callbacks (see the api). + */ +void __gl_renderBoundary( GLUtesselator *tess, GLUmesh *mesh ) +{ + GLUface *f; + GLUhalfEdge *e; + + for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) { + if( f->inside ) { + CALL_BEGIN_OR_BEGIN_DATA( GL_LINE_LOOP ); + e = f->anEdge; + do { + CALL_VERTEX_OR_VERTEX_DATA( e->Org->data ); + e = e->Lnext; + } while( e != f->anEdge ); + CALL_END_OR_END_DATA(); + } + } +} + + +/************************ Quick-and-dirty decomposition ******************/ + +#define SIGN_INCONSISTENT 2 + +static int ComputeNormal( GLUtesselator *tess, GLdouble norm[3], int check ) +/* + * If check==FALSE, we compute the polygon normal and place it in norm[]. + * If check==TRUE, we check that each triangle in the fan from v0 has a + * consistent orientation with respect to norm[]. If triangles are + * consistently oriented CCW, return 1; if CW, return -1; if all triangles + * are degenerate return 0; otherwise (no consistent orientation) return + * SIGN_INCONSISTENT. + */ +{ + CachedVertex *v0 = tess->cache; + CachedVertex *vn = v0 + tess->cacheCount; + CachedVertex *vc; + GLdouble dot, xc, yc, zc, xp, yp, zp, n[3]; + int sign = 0; + + /* Find the polygon normal. It is important to get a reasonable + * normal even when the polygon is self-intersecting (eg. a bowtie). + * Otherwise, the computed normal could be very tiny, but perpendicular + * to the true plane of the polygon due to numerical noise. Then all + * the triangles would appear to be degenerate and we would incorrectly + * decompose the polygon as a fan (or simply not render it at all). + * + * We use a sum-of-triangles normal algorithm rather than the more + * efficient sum-of-trapezoids method (used in CheckOrientation() + * in normal.c). This lets us explicitly reverse the signed area + * of some triangles to get a reasonable normal in the self-intersecting + * case. + */ + if( ! check ) { + norm[0] = norm[1] = norm[2] = 0.0; + } + + vc = v0 + 1; + xc = vc->coords[0] - v0->coords[0]; + yc = vc->coords[1] - v0->coords[1]; + zc = vc->coords[2] - v0->coords[2]; + while( ++vc < vn ) { + xp = xc; yp = yc; zp = zc; + xc = vc->coords[0] - v0->coords[0]; + yc = vc->coords[1] - v0->coords[1]; + zc = vc->coords[2] - v0->coords[2]; + + /* Compute (vp - v0) cross (vc - v0) */ + n[0] = yp*zc - zp*yc; + n[1] = zp*xc - xp*zc; + n[2] = xp*yc - yp*xc; + + dot = n[0]*norm[0] + n[1]*norm[1] + n[2]*norm[2]; + if( ! check ) { + /* Reverse the contribution of back-facing triangles to get + * a reasonable normal for self-intersecting polygons (see above) + */ + if( dot >= 0 ) { + norm[0] += n[0]; norm[1] += n[1]; norm[2] += n[2]; + } else { + norm[0] -= n[0]; norm[1] -= n[1]; norm[2] -= n[2]; + } + } else if( dot != 0 ) { + /* Check the new orientation for consistency with previous triangles */ + if( dot > 0 ) { + if( sign < 0 ) return SIGN_INCONSISTENT; + sign = 1; + } else { + if( sign > 0 ) return SIGN_INCONSISTENT; + sign = -1; + } + } + } + return sign; +} + +/* __gl_renderCache( tess ) takes a single contour and tries to render it + * as a triangle fan. This handles convex polygons, as well as some + * non-convex polygons if we get lucky. + * + * Returns TRUE if the polygon was successfully rendered. The rendering + * output is provided as callbacks (see the api). + */ +GLboolean __gl_renderCache( GLUtesselator *tess ) +{ + CachedVertex *v0 = tess->cache; + CachedVertex *vn = v0 + tess->cacheCount; + CachedVertex *vc; + GLdouble norm[3]; + int sign; + + if( tess->cacheCount < 3 ) { + /* Degenerate contour -- no output */ + return TRUE; + } + + norm[0] = tess->normal[0]; + norm[1] = tess->normal[1]; + norm[2] = tess->normal[2]; + if( norm[0] == 0 && norm[1] == 0 && norm[2] == 0 ) { + ComputeNormal( tess, norm, FALSE ); + } + + sign = ComputeNormal( tess, norm, TRUE ); + if( sign == SIGN_INCONSISTENT ) { + /* Fan triangles did not have a consistent orientation */ + return FALSE; + } + if( sign == 0 ) { + /* All triangles were degenerate */ + return TRUE; + } + + /* Make sure we do the right thing for each winding rule */ + switch( tess->windingRule ) { + case GLU_TESS_WINDING_ODD: + case GLU_TESS_WINDING_NONZERO: + break; + case GLU_TESS_WINDING_POSITIVE: + if( sign < 0 ) return TRUE; + break; + case GLU_TESS_WINDING_NEGATIVE: + if( sign > 0 ) return TRUE; + break; + case GLU_TESS_WINDING_ABS_GEQ_TWO: + return TRUE; + } + + CALL_BEGIN_OR_BEGIN_DATA( tess->boundaryOnly ? GL_LINE_LOOP + : (tess->cacheCount > 3) ? GL_TRIANGLE_FAN + : GL_TRIANGLES ); + + CALL_VERTEX_OR_VERTEX_DATA( v0->data ); + if( sign > 0 ) { + for( vc = v0+1; vc < vn; ++vc ) { + CALL_VERTEX_OR_VERTEX_DATA( vc->data ); + } + } else { + for( vc = vn-1; vc > v0; --vc ) { + CALL_VERTEX_OR_VERTEX_DATA( vc->data ); + } + } + CALL_END_OR_END_DATA(); + return TRUE; +} diff --git a/cogl/cogl-path/tesselator/render.h b/cogl/cogl-path/tesselator/render.h new file mode 100644 index 0000000..a298c9a --- /dev/null +++ b/cogl/cogl-path/tesselator/render.h @@ -0,0 +1,52 @@ +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ +/* +** Author: Eric Veach, July 1994. +** +*/ + +#ifndef __render_h_ +#define __render_h_ + +#include "mesh.h" + +/* __gl_renderMesh( tess, mesh ) takes a mesh and breaks it into triangle + * fans, strips, and separate triangles. A substantial effort is made + * to use as few rendering primitives as possible (ie. to make the fans + * and strips as large as possible). + * + * The rendering output is provided as callbacks (see the api). + */ +void __gl_renderMesh( GLUtesselator *tess, GLUmesh *mesh ); +void __gl_renderBoundary( GLUtesselator *tess, GLUmesh *mesh ); + +GLboolean __gl_renderCache( GLUtesselator *tess ); + +#endif diff --git a/cogl/cogl-path/tesselator/sweep.c b/cogl/cogl-path/tesselator/sweep.c new file mode 100644 index 0000000..eca828f --- /dev/null +++ b/cogl/cogl-path/tesselator/sweep.c @@ -0,0 +1,1361 @@ +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ +/* +** Author: Eric Veach, July 1994. +** +*/ + +#include "gluos.h" +#include +#include +#include /* longjmp */ +#include /* LONG_MAX */ + +#include "mesh.h" +#include "geom.h" +#include "tess.h" +#include "dict.h" +#include "priorityq.h" +#include "memalloc.h" +#include "sweep.h" + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#ifdef FOR_TRITE_TEST_PROGRAM +extern void DebugEvent( GLUtesselator *tess ); +#else +#define DebugEvent( tess ) +#endif + +/* + * Invariants for the Edge Dictionary. + * - each pair of adjacent edges e2=Succ(e1) satisfies EdgeLeq(e1,e2) + * at any valid location of the sweep event + * - if EdgeLeq(e2,e1) as well (at any valid sweep event), then e1 and e2 + * share a common endpoint + * - for each e, e->Dst has been processed, but not e->Org + * - each edge e satisfies VertLeq(e->Dst,event) && VertLeq(event,e->Org) + * where "event" is the current sweep line event. + * - no edge e has zero length + * + * Invariants for the Mesh (the processed portion). + * - the portion of the mesh left of the sweep line is a planar graph, + * ie. there is *some* way to embed it in the plane + * - no processed edge has zero length + * - no two processed vertices have identical coordinates + * - each "inside" region is monotone, ie. can be broken into two chains + * of monotonically increasing vertices according to VertLeq(v1,v2) + * - a non-invariant: these chains may intersect (very slightly) + * + * Invariants for the Sweep. + * - if none of the edges incident to the event vertex have an activeRegion + * (ie. none of these edges are in the edge dictionary), then the vertex + * has only right-going edges. + * - if an edge is marked "fixUpperEdge" (it is a temporary edge introduced + * by ConnectRightVertex), then it is the only right-going edge from + * its associated vertex. (This says that these edges exist only + * when it is necessary.) + */ + +#undef MAX +#undef MIN +#define MAX(x,y) ((x) >= (y) ? (x) : (y)) +#define MIN(x,y) ((x) <= (y) ? (x) : (y)) + +/* When we merge two edges into one, we need to compute the combined + * winding of the new edge. + */ +#define AddWinding(eDst,eSrc) (eDst->winding += eSrc->winding, \ + eDst->Sym->winding += eSrc->Sym->winding) + +static void SweepEvent( GLUtesselator *tess, GLUvertex *vEvent ); +static void WalkDirtyRegions( GLUtesselator *tess, ActiveRegion *regUp ); +static int CheckForRightSplice( GLUtesselator *tess, ActiveRegion *regUp ); + +static int EdgeLeq( GLUtesselator *tess, ActiveRegion *reg1, + ActiveRegion *reg2 ) +/* + * Both edges must be directed from right to left (this is the canonical + * direction for the upper edge of each region). + * + * The strategy is to evaluate a "t" value for each edge at the + * current sweep line position, given by tess->event. The calculations + * are designed to be very stable, but of course they are not perfect. + * + * Special case: if both edge destinations are at the sweep event, + * we sort the edges by slope (they would otherwise compare equally). + */ +{ + GLUvertex *event = tess->event; + GLUhalfEdge *e1, *e2; + GLdouble t1, t2; + + e1 = reg1->eUp; + e2 = reg2->eUp; + + if( e1->Dst == event ) { + if( e2->Dst == event ) { + /* Two edges right of the sweep line which meet at the sweep event. + * Sort them by slope. + */ + if( VertLeq( e1->Org, e2->Org )) { + return EdgeSign( e2->Dst, e1->Org, e2->Org ) <= 0; + } + return EdgeSign( e1->Dst, e2->Org, e1->Org ) >= 0; + } + return EdgeSign( e2->Dst, event, e2->Org ) <= 0; + } + if( e2->Dst == event ) { + return EdgeSign( e1->Dst, event, e1->Org ) >= 0; + } + + /* General case - compute signed distance *from* e1, e2 to event */ + t1 = EdgeEval( e1->Dst, event, e1->Org ); + t2 = EdgeEval( e2->Dst, event, e2->Org ); + return (t1 >= t2); +} + + +static void DeleteRegion( GLUtesselator *tess, ActiveRegion *reg ) +{ + if( reg->fixUpperEdge ) { + /* It was created with zero winding number, so it better be + * deleted with zero winding number (ie. it better not get merged + * with a real edge). + */ + assert( reg->eUp->winding == 0 ); + } + reg->eUp->activeRegion = NULL; + dictDelete( tess->dict, reg->nodeUp ); /* __gl_dictListDelete */ + memFree( reg ); +} + + +static int FixUpperEdge( ActiveRegion *reg, GLUhalfEdge *newEdge ) +/* + * Replace an upper edge which needs fixing (see ConnectRightVertex). + */ +{ + assert( reg->fixUpperEdge ); + if ( !__gl_meshDelete( reg->eUp ) ) return 0; + reg->fixUpperEdge = FALSE; + reg->eUp = newEdge; + newEdge->activeRegion = reg; + + return 1; +} + +static ActiveRegion *TopLeftRegion( ActiveRegion *reg ) +{ + GLUvertex *org = reg->eUp->Org; + GLUhalfEdge *e; + + /* Find the region above the uppermost edge with the same origin */ + do { + reg = RegionAbove( reg ); + } while( reg->eUp->Org == org ); + + /* If the edge above was a temporary edge introduced by ConnectRightVertex, + * now is the time to fix it. + */ + if( reg->fixUpperEdge ) { + e = __gl_meshConnect( RegionBelow(reg)->eUp->Sym, reg->eUp->Lnext ); + if (e == NULL) return NULL; + if ( !FixUpperEdge( reg, e ) ) return NULL; + reg = RegionAbove( reg ); + } + return reg; +} + +static ActiveRegion *TopRightRegion( ActiveRegion *reg ) +{ + GLUvertex *dst = reg->eUp->Dst; + + /* Find the region above the uppermost edge with the same destination */ + do { + reg = RegionAbove( reg ); + } while( reg->eUp->Dst == dst ); + return reg; +} + +static ActiveRegion *AddRegionBelow( GLUtesselator *tess, + ActiveRegion *regAbove, + GLUhalfEdge *eNewUp ) +/* + * Add a new active region to the sweep line, *somewhere* below "regAbove" + * (according to where the new edge belongs in the sweep-line dictionary). + * The upper edge of the new region will be "eNewUp". + * Winding number and "inside" flag are not updated. + */ +{ + ActiveRegion *regNew = (ActiveRegion *)memAlloc( sizeof( ActiveRegion )); + if (regNew == NULL) longjmp(tess->env,1); + + regNew->eUp = eNewUp; + /* __gl_dictListInsertBefore */ + regNew->nodeUp = dictInsertBefore( tess->dict, regAbove->nodeUp, regNew ); + if (regNew->nodeUp == NULL) longjmp(tess->env,1); + regNew->fixUpperEdge = FALSE; + regNew->sentinel = FALSE; + regNew->dirty = FALSE; + + eNewUp->activeRegion = regNew; + return regNew; +} + +static GLboolean IsWindingInside( GLUtesselator *tess, int n ) +{ + switch( tess->windingRule ) { + case GLU_TESS_WINDING_ODD: + return (n & 1); + case GLU_TESS_WINDING_NONZERO: + return (n != 0); + case GLU_TESS_WINDING_POSITIVE: + return (n > 0); + case GLU_TESS_WINDING_NEGATIVE: + return (n < 0); + case GLU_TESS_WINDING_ABS_GEQ_TWO: + return (n >= 2) || (n <= -2); + } + /*LINTED*/ + assert( FALSE ); + /*NOTREACHED*/ + return GL_FALSE; /* avoid compiler complaints */ +} + + +static void ComputeWinding( GLUtesselator *tess, ActiveRegion *reg ) +{ + reg->windingNumber = RegionAbove(reg)->windingNumber + reg->eUp->winding; + reg->inside = IsWindingInside( tess, reg->windingNumber ); +} + + +static void FinishRegion( GLUtesselator *tess, ActiveRegion *reg ) +/* + * Delete a region from the sweep line. This happens when the upper + * and lower chains of a region meet (at a vertex on the sweep line). + * The "inside" flag is copied to the appropriate mesh face (we could + * not do this before -- since the structure of the mesh is always + * changing, this face may not have even existed until now). + */ +{ + GLUhalfEdge *e = reg->eUp; + GLUface *f = e->Lface; + + f->inside = reg->inside; + f->anEdge = e; /* optimization for __gl_meshTessellateMonoRegion() */ + DeleteRegion( tess, reg ); +} + + +static GLUhalfEdge *FinishLeftRegions( GLUtesselator *tess, + ActiveRegion *regFirst, ActiveRegion *regLast ) +/* + * We are given a vertex with one or more left-going edges. All affected + * edges should be in the edge dictionary. Starting at regFirst->eUp, + * we walk down deleting all regions where both edges have the same + * origin vOrg. At the same time we copy the "inside" flag from the + * active region to the face, since at this point each face will belong + * to at most one region (this was not necessarily true until this point + * in the sweep). The walk stops at the region above regLast; if regLast + * is NULL we walk as far as possible. At the same time we relink the + * mesh if necessary, so that the ordering of edges around vOrg is the + * same as in the dictionary. + */ +{ + ActiveRegion *reg, *regPrev; + GLUhalfEdge *e, *ePrev; + + regPrev = regFirst; + ePrev = regFirst->eUp; + while( regPrev != regLast ) { + regPrev->fixUpperEdge = FALSE; /* placement was OK */ + reg = RegionBelow( regPrev ); + e = reg->eUp; + if( e->Org != ePrev->Org ) { + if( ! reg->fixUpperEdge ) { + /* Remove the last left-going edge. Even though there are no further + * edges in the dictionary with this origin, there may be further + * such edges in the mesh (if we are adding left edges to a vertex + * that has already been processed). Thus it is important to call + * FinishRegion rather than just DeleteRegion. + */ + FinishRegion( tess, regPrev ); + break; + } + /* If the edge below was a temporary edge introduced by + * ConnectRightVertex, now is the time to fix it. + */ + e = __gl_meshConnect( ePrev->Lprev, e->Sym ); + if (e == NULL) longjmp(tess->env,1); + if ( !FixUpperEdge( reg, e ) ) longjmp(tess->env,1); + } + + /* Relink edges so that ePrev->Onext == e */ + if( ePrev->Onext != e ) { + if ( !__gl_meshSplice( e->Oprev, e ) ) longjmp(tess->env,1); + if ( !__gl_meshSplice( ePrev, e ) ) longjmp(tess->env,1); + } + FinishRegion( tess, regPrev ); /* may change reg->eUp */ + ePrev = reg->eUp; + regPrev = reg; + } + return ePrev; +} + + +static void AddRightEdges( GLUtesselator *tess, ActiveRegion *regUp, + GLUhalfEdge *eFirst, GLUhalfEdge *eLast, GLUhalfEdge *eTopLeft, + GLboolean cleanUp ) +/* + * Purpose: insert right-going edges into the edge dictionary, and update + * winding numbers and mesh connectivity appropriately. All right-going + * edges share a common origin vOrg. Edges are inserted CCW starting at + * eFirst; the last edge inserted is eLast->Oprev. If vOrg has any + * left-going edges already processed, then eTopLeft must be the edge + * such that an imaginary upward vertical segment from vOrg would be + * contained between eTopLeft->Oprev and eTopLeft; otherwise eTopLeft + * should be NULL. + */ +{ + ActiveRegion *reg, *regPrev; + GLUhalfEdge *e, *ePrev; + int firstTime = TRUE; + + /* Insert the new right-going edges in the dictionary */ + e = eFirst; + do { + assert( VertLeq( e->Org, e->Dst )); + AddRegionBelow( tess, regUp, e->Sym ); + e = e->Onext; + } while ( e != eLast ); + + /* Walk *all* right-going edges from e->Org, in the dictionary order, + * updating the winding numbers of each region, and re-linking the mesh + * edges to match the dictionary ordering (if necessary). + */ + if( eTopLeft == NULL ) { + eTopLeft = RegionBelow( regUp )->eUp->Rprev; + } + regPrev = regUp; + ePrev = eTopLeft; + for( ;; ) { + reg = RegionBelow( regPrev ); + e = reg->eUp->Sym; + if( e->Org != ePrev->Org ) break; + + if( e->Onext != ePrev ) { + /* Unlink e from its current position, and relink below ePrev */ + if ( !__gl_meshSplice( e->Oprev, e ) ) longjmp(tess->env,1); + if ( !__gl_meshSplice( ePrev->Oprev, e ) ) longjmp(tess->env,1); + } + /* Compute the winding number and "inside" flag for the new regions */ + reg->windingNumber = regPrev->windingNumber - e->winding; + reg->inside = IsWindingInside( tess, reg->windingNumber ); + + /* Check for two outgoing edges with same slope -- process these + * before any intersection tests (see example in __gl_computeInterior). + */ + regPrev->dirty = TRUE; + if( ! firstTime && CheckForRightSplice( tess, regPrev )) { + AddWinding( e, ePrev ); + DeleteRegion( tess, regPrev ); + if ( !__gl_meshDelete( ePrev ) ) longjmp(tess->env,1); + } + firstTime = FALSE; + regPrev = reg; + ePrev = e; + } + regPrev->dirty = TRUE; + assert( regPrev->windingNumber - e->winding == reg->windingNumber ); + + if( cleanUp ) { + /* Check for intersections between newly adjacent edges. */ + WalkDirtyRegions( tess, regPrev ); + } +} + + +static void CallCombine( GLUtesselator *tess, GLUvertex *isect, + void *data[4], GLfloat weights[4], int needed ) +{ + GLdouble coords[3]; + + /* Copy coord data in case the callback changes it. */ + coords[0] = isect->coords[0]; + coords[1] = isect->coords[1]; + coords[2] = isect->coords[2]; + + isect->data = NULL; + CALL_COMBINE_OR_COMBINE_DATA( coords, data, weights, &isect->data ); + if( isect->data == NULL ) { + if( ! needed ) { + isect->data = data[0]; + } else if( ! tess->fatalError ) { + /* The only way fatal error is when two edges are found to intersect, + * but the user has not provided the callback necessary to handle + * generated intersection points. + */ + CALL_ERROR_OR_ERROR_DATA( GLU_TESS_NEED_COMBINE_CALLBACK ); + tess->fatalError = TRUE; + } + } +} + +static void SpliceMergeVertices( GLUtesselator *tess, GLUhalfEdge *e1, + GLUhalfEdge *e2 ) +/* + * Two vertices with idential coordinates are combined into one. + * e1->Org is kept, while e2->Org is discarded. + */ +{ + void *data[4] = { NULL, NULL, NULL, NULL }; + GLfloat weights[4] = { 0.5, 0.5, 0.0, 0.0 }; + + data[0] = e1->Org->data; + data[1] = e2->Org->data; + CallCombine( tess, e1->Org, data, weights, FALSE ); + if ( !__gl_meshSplice( e1, e2 ) ) longjmp(tess->env,1); +} + +static void VertexWeights( GLUvertex *isect, GLUvertex *org, GLUvertex *dst, + GLfloat *weights ) +/* + * Find some weights which describe how the intersection vertex is + * a linear combination of "org" and "dest". Each of the two edges + * which generated "isect" is allocated 50% of the weight; each edge + * splits the weight between its org and dst according to the + * relative distance to "isect". + */ +{ + GLdouble t1 = VertL1dist( org, isect ); + GLdouble t2 = VertL1dist( dst, isect ); + + weights[0] = 0.5 * t2 / (t1 + t2); + weights[1] = 0.5 * t1 / (t1 + t2); + isect->coords[0] += weights[0]*org->coords[0] + weights[1]*dst->coords[0]; + isect->coords[1] += weights[0]*org->coords[1] + weights[1]*dst->coords[1]; + isect->coords[2] += weights[0]*org->coords[2] + weights[1]*dst->coords[2]; +} + + +static void GetIntersectData( GLUtesselator *tess, GLUvertex *isect, + GLUvertex *orgUp, GLUvertex *dstUp, + GLUvertex *orgLo, GLUvertex *dstLo ) +/* + * We've computed a new intersection point, now we need a "data" pointer + * from the user so that we can refer to this new vertex in the + * rendering callbacks. + */ +{ + void *data[4]; + GLfloat weights[4]; + + data[0] = orgUp->data; + data[1] = dstUp->data; + data[2] = orgLo->data; + data[3] = dstLo->data; + + isect->coords[0] = isect->coords[1] = isect->coords[2] = 0; + VertexWeights( isect, orgUp, dstUp, &weights[0] ); + VertexWeights( isect, orgLo, dstLo, &weights[2] ); + + CallCombine( tess, isect, data, weights, TRUE ); +} + +static int CheckForRightSplice( GLUtesselator *tess, ActiveRegion *regUp ) +/* + * Check the upper and lower edge of "regUp", to make sure that the + * eUp->Org is above eLo, or eLo->Org is below eUp (depending on which + * origin is leftmost). + * + * The main purpose is to splice right-going edges with the same + * dest vertex and nearly identical slopes (ie. we can't distinguish + * the slopes numerically). However the splicing can also help us + * to recover from numerical errors. For example, suppose at one + * point we checked eUp and eLo, and decided that eUp->Org is barely + * above eLo. Then later, we split eLo into two edges (eg. from + * a splice operation like this one). This can change the result of + * our test so that now eUp->Org is incident to eLo, or barely below it. + * We must correct this condition to maintain the dictionary invariants. + * + * One possibility is to check these edges for intersection again + * (ie. CheckForIntersect). This is what we do if possible. However + * CheckForIntersect requires that tess->event lies between eUp and eLo, + * so that it has something to fall back on when the intersection + * calculation gives us an unusable answer. So, for those cases where + * we can't check for intersection, this routine fixes the problem + * by just splicing the offending vertex into the other edge. + * This is a guaranteed solution, no matter how degenerate things get. + * Basically this is a combinatorial solution to a numerical problem. + */ +{ + ActiveRegion *regLo = RegionBelow(regUp); + GLUhalfEdge *eUp = regUp->eUp; + GLUhalfEdge *eLo = regLo->eUp; + + if( VertLeq( eUp->Org, eLo->Org )) { + if( EdgeSign( eLo->Dst, eUp->Org, eLo->Org ) > 0 ) return FALSE; + + /* eUp->Org appears to be below eLo */ + if( ! VertEq( eUp->Org, eLo->Org )) { + /* Splice eUp->Org into eLo */ + if ( __gl_meshSplitEdge( eLo->Sym ) == NULL) longjmp(tess->env,1); + if ( !__gl_meshSplice( eUp, eLo->Oprev ) ) longjmp(tess->env,1); + regUp->dirty = regLo->dirty = TRUE; + + } else if( eUp->Org != eLo->Org ) { + /* merge the two vertices, discarding eUp->Org */ + pqDelete( tess->pq, eUp->Org->pqHandle ); /* __gl_pqSortDelete */ + SpliceMergeVertices( tess, eLo->Oprev, eUp ); + } + } else { + if( EdgeSign( eUp->Dst, eLo->Org, eUp->Org ) < 0 ) return FALSE; + + /* eLo->Org appears to be above eUp, so splice eLo->Org into eUp */ + RegionAbove(regUp)->dirty = regUp->dirty = TRUE; + if (__gl_meshSplitEdge( eUp->Sym ) == NULL) longjmp(tess->env,1); + if ( !__gl_meshSplice( eLo->Oprev, eUp ) ) longjmp(tess->env,1); + } + return TRUE; +} + +static int CheckForLeftSplice( GLUtesselator *tess, ActiveRegion *regUp ) +/* + * Check the upper and lower edge of "regUp", to make sure that the + * eUp->Dst is above eLo, or eLo->Dst is below eUp (depending on which + * destination is rightmost). + * + * Theoretically, this should always be true. However, splitting an edge + * into two pieces can change the results of previous tests. For example, + * suppose at one point we checked eUp and eLo, and decided that eUp->Dst + * is barely above eLo. Then later, we split eLo into two edges (eg. from + * a splice operation like this one). This can change the result of + * the test so that now eUp->Dst is incident to eLo, or barely below it. + * We must correct this condition to maintain the dictionary invariants + * (otherwise new edges might get inserted in the wrong place in the + * dictionary, and bad stuff will happen). + * + * We fix the problem by just splicing the offending vertex into the + * other edge. + */ +{ + ActiveRegion *regLo = RegionBelow(regUp); + GLUhalfEdge *eUp = regUp->eUp; + GLUhalfEdge *eLo = regLo->eUp; + GLUhalfEdge *e; + + assert( ! VertEq( eUp->Dst, eLo->Dst )); + + if( VertLeq( eUp->Dst, eLo->Dst )) { + if( EdgeSign( eUp->Dst, eLo->Dst, eUp->Org ) < 0 ) return FALSE; + + /* eLo->Dst is above eUp, so splice eLo->Dst into eUp */ + RegionAbove(regUp)->dirty = regUp->dirty = TRUE; + e = __gl_meshSplitEdge( eUp ); + if (e == NULL) longjmp(tess->env,1); + if ( !__gl_meshSplice( eLo->Sym, e ) ) longjmp(tess->env,1); + e->Lface->inside = regUp->inside; + } else { + if( EdgeSign( eLo->Dst, eUp->Dst, eLo->Org ) > 0 ) return FALSE; + + /* eUp->Dst is below eLo, so splice eUp->Dst into eLo */ + regUp->dirty = regLo->dirty = TRUE; + e = __gl_meshSplitEdge( eLo ); + if (e == NULL) longjmp(tess->env,1); + if ( !__gl_meshSplice( eUp->Lnext, eLo->Sym ) ) longjmp(tess->env,1); + e->Rface->inside = regUp->inside; + } + return TRUE; +} + + +static int CheckForIntersect( GLUtesselator *tess, ActiveRegion *regUp ) +/* + * Check the upper and lower edges of the given region to see if + * they intersect. If so, create the intersection and add it + * to the data structures. + * + * Returns TRUE if adding the new intersection resulted in a recursive + * call to AddRightEdges(); in this case all "dirty" regions have been + * checked for intersections, and possibly regUp has been deleted. + */ +{ + ActiveRegion *regLo = RegionBelow(regUp); + GLUhalfEdge *eUp = regUp->eUp; + GLUhalfEdge *eLo = regLo->eUp; + GLUvertex *orgUp = eUp->Org; + GLUvertex *orgLo = eLo->Org; + GLUvertex *dstUp = eUp->Dst; + GLUvertex *dstLo = eLo->Dst; + GLdouble tMinUp, tMaxLo; + GLUvertex isect, *orgMin; + GLUhalfEdge *e; + + assert( ! VertEq( dstLo, dstUp )); + assert( EdgeSign( dstUp, tess->event, orgUp ) <= 0 ); + assert( EdgeSign( dstLo, tess->event, orgLo ) >= 0 ); + assert( orgUp != tess->event && orgLo != tess->event ); + assert( ! regUp->fixUpperEdge && ! regLo->fixUpperEdge ); + + if( orgUp == orgLo ) return FALSE; /* right endpoints are the same */ + + tMinUp = MIN( orgUp->t, dstUp->t ); + tMaxLo = MAX( orgLo->t, dstLo->t ); + if( tMinUp > tMaxLo ) return FALSE; /* t ranges do not overlap */ + + if( VertLeq( orgUp, orgLo )) { + if( EdgeSign( dstLo, orgUp, orgLo ) > 0 ) return FALSE; + } else { + if( EdgeSign( dstUp, orgLo, orgUp ) < 0 ) return FALSE; + } + + /* At this point the edges intersect, at least marginally */ + DebugEvent( tess ); + + __gl_edgeIntersect( dstUp, orgUp, dstLo, orgLo, &isect ); + /* The following properties are guaranteed: */ + assert( MIN( orgUp->t, dstUp->t ) <= isect.t ); + assert( isect.t <= MAX( orgLo->t, dstLo->t )); + assert( MIN( dstLo->s, dstUp->s ) <= isect.s ); + assert( isect.s <= MAX( orgLo->s, orgUp->s )); + + if( VertLeq( &isect, tess->event )) { + /* The intersection point lies slightly to the left of the sweep line, + * so move it until it''s slightly to the right of the sweep line. + * (If we had perfect numerical precision, this would never happen + * in the first place). The easiest and safest thing to do is + * replace the intersection by tess->event. + */ + isect.s = tess->event->s; + isect.t = tess->event->t; + } + /* Similarly, if the computed intersection lies to the right of the + * rightmost origin (which should rarely happen), it can cause + * unbelievable inefficiency on sufficiently degenerate inputs. + * (If you have the test program, try running test54.d with the + * "X zoom" option turned on). + */ + orgMin = VertLeq( orgUp, orgLo ) ? orgUp : orgLo; + if( VertLeq( orgMin, &isect )) { + isect.s = orgMin->s; + isect.t = orgMin->t; + } + + if( VertEq( &isect, orgUp ) || VertEq( &isect, orgLo )) { + /* Easy case -- intersection at one of the right endpoints */ + (void) CheckForRightSplice( tess, regUp ); + return FALSE; + } + + if( (! VertEq( dstUp, tess->event ) + && EdgeSign( dstUp, tess->event, &isect ) >= 0) + || (! VertEq( dstLo, tess->event ) + && EdgeSign( dstLo, tess->event, &isect ) <= 0 )) + { + /* Very unusual -- the new upper or lower edge would pass on the + * wrong side of the sweep event, or through it. This can happen + * due to very small numerical errors in the intersection calculation. + */ + if( dstLo == tess->event ) { + /* Splice dstLo into eUp, and process the new region(s) */ + if (__gl_meshSplitEdge( eUp->Sym ) == NULL) longjmp(tess->env,1); + if ( !__gl_meshSplice( eLo->Sym, eUp ) ) longjmp(tess->env,1); + regUp = TopLeftRegion( regUp ); + if (regUp == NULL) longjmp(tess->env,1); + eUp = RegionBelow(regUp)->eUp; + FinishLeftRegions( tess, RegionBelow(regUp), regLo ); + AddRightEdges( tess, regUp, eUp->Oprev, eUp, eUp, TRUE ); + return TRUE; + } + if( dstUp == tess->event ) { + /* Splice dstUp into eLo, and process the new region(s) */ + if (__gl_meshSplitEdge( eLo->Sym ) == NULL) longjmp(tess->env,1); + if ( !__gl_meshSplice( eUp->Lnext, eLo->Oprev ) ) longjmp(tess->env,1); + regLo = regUp; + regUp = TopRightRegion( regUp ); + e = RegionBelow(regUp)->eUp->Rprev; + regLo->eUp = eLo->Oprev; + eLo = FinishLeftRegions( tess, regLo, NULL ); + AddRightEdges( tess, regUp, eLo->Onext, eUp->Rprev, e, TRUE ); + return TRUE; + } + /* Special case: called from ConnectRightVertex. If either + * edge passes on the wrong side of tess->event, split it + * (and wait for ConnectRightVertex to splice it appropriately). + */ + if( EdgeSign( dstUp, tess->event, &isect ) >= 0 ) { + RegionAbove(regUp)->dirty = regUp->dirty = TRUE; + if (__gl_meshSplitEdge( eUp->Sym ) == NULL) longjmp(tess->env,1); + eUp->Org->s = tess->event->s; + eUp->Org->t = tess->event->t; + } + if( EdgeSign( dstLo, tess->event, &isect ) <= 0 ) { + regUp->dirty = regLo->dirty = TRUE; + if (__gl_meshSplitEdge( eLo->Sym ) == NULL) longjmp(tess->env,1); + eLo->Org->s = tess->event->s; + eLo->Org->t = tess->event->t; + } + /* leave the rest for ConnectRightVertex */ + return FALSE; + } + + /* General case -- split both edges, splice into new vertex. + * When we do the splice operation, the order of the arguments is + * arbitrary as far as correctness goes. However, when the operation + * creates a new face, the work done is proportional to the size of + * the new face. We expect the faces in the processed part of + * the mesh (ie. eUp->Lface) to be smaller than the faces in the + * unprocessed original contours (which will be eLo->Oprev->Lface). + */ + if (__gl_meshSplitEdge( eUp->Sym ) == NULL) longjmp(tess->env,1); + if (__gl_meshSplitEdge( eLo->Sym ) == NULL) longjmp(tess->env,1); + if ( !__gl_meshSplice( eLo->Oprev, eUp ) ) longjmp(tess->env,1); + eUp->Org->s = isect.s; + eUp->Org->t = isect.t; + eUp->Org->pqHandle = pqInsert( tess->pq, eUp->Org ); /* __gl_pqSortInsert */ + if (eUp->Org->pqHandle == LONG_MAX) { + pqDeletePriorityQ(tess->pq); /* __gl_pqSortDeletePriorityQ */ + tess->pq = NULL; + longjmp(tess->env,1); + } + GetIntersectData( tess, eUp->Org, orgUp, dstUp, orgLo, dstLo ); + RegionAbove(regUp)->dirty = regUp->dirty = regLo->dirty = TRUE; + return FALSE; +} + +static void WalkDirtyRegions( GLUtesselator *tess, ActiveRegion *regUp ) +/* + * When the upper or lower edge of any region changes, the region is + * marked "dirty". This routine walks through all the dirty regions + * and makes sure that the dictionary invariants are satisfied + * (see the comments at the beginning of this file). Of course + * new dirty regions can be created as we make changes to restore + * the invariants. + */ +{ + ActiveRegion *regLo = RegionBelow(regUp); + GLUhalfEdge *eUp, *eLo; + + for( ;; ) { + /* Find the lowest dirty region (we walk from the bottom up). */ + while( regLo->dirty ) { + regUp = regLo; + regLo = RegionBelow(regLo); + } + if( ! regUp->dirty ) { + regLo = regUp; + regUp = RegionAbove( regUp ); + if( regUp == NULL || ! regUp->dirty ) { + /* We've walked all the dirty regions */ + return; + } + } + regUp->dirty = FALSE; + eUp = regUp->eUp; + eLo = regLo->eUp; + + if( eUp->Dst != eLo->Dst ) { + /* Check that the edge ordering is obeyed at the Dst vertices. */ + if( CheckForLeftSplice( tess, regUp )) { + + /* If the upper or lower edge was marked fixUpperEdge, then + * we no longer need it (since these edges are needed only for + * vertices which otherwise have no right-going edges). + */ + if( regLo->fixUpperEdge ) { + DeleteRegion( tess, regLo ); + if ( !__gl_meshDelete( eLo ) ) longjmp(tess->env,1); + regLo = RegionBelow( regUp ); + eLo = regLo->eUp; + } else if( regUp->fixUpperEdge ) { + DeleteRegion( tess, regUp ); + if ( !__gl_meshDelete( eUp ) ) longjmp(tess->env,1); + regUp = RegionAbove( regLo ); + eUp = regUp->eUp; + } + } + } + if( eUp->Org != eLo->Org ) { + if( eUp->Dst != eLo->Dst + && ! regUp->fixUpperEdge && ! regLo->fixUpperEdge + && (eUp->Dst == tess->event || eLo->Dst == tess->event) ) + { + /* When all else fails in CheckForIntersect(), it uses tess->event + * as the intersection location. To make this possible, it requires + * that tess->event lie between the upper and lower edges, and also + * that neither of these is marked fixUpperEdge (since in the worst + * case it might splice one of these edges into tess->event, and + * violate the invariant that fixable edges are the only right-going + * edge from their associated vertex). + */ + if( CheckForIntersect( tess, regUp )) { + /* WalkDirtyRegions() was called recursively; we're done */ + return; + } + } else { + /* Even though we can't use CheckForIntersect(), the Org vertices + * may violate the dictionary edge ordering. Check and correct this. + */ + (void) CheckForRightSplice( tess, regUp ); + } + } + if( eUp->Org == eLo->Org && eUp->Dst == eLo->Dst ) { + /* A degenerate loop consisting of only two edges -- delete it. */ + AddWinding( eLo, eUp ); + DeleteRegion( tess, regUp ); + if ( !__gl_meshDelete( eUp ) ) longjmp(tess->env,1); + regUp = RegionAbove( regLo ); + } + } +} + + +static void ConnectRightVertex( GLUtesselator *tess, ActiveRegion *regUp, + GLUhalfEdge *eBottomLeft ) +/* + * Purpose: connect a "right" vertex vEvent (one where all edges go left) + * to the unprocessed portion of the mesh. Since there are no right-going + * edges, two regions (one above vEvent and one below) are being merged + * into one. "regUp" is the upper of these two regions. + * + * There are two reasons for doing this (adding a right-going edge): + * - if the two regions being merged are "inside", we must add an edge + * to keep them separated (the combined region would not be monotone). + * - in any case, we must leave some record of vEvent in the dictionary, + * so that we can merge vEvent with features that we have not seen yet. + * For example, maybe there is a vertical edge which passes just to + * the right of vEvent; we would like to splice vEvent into this edge. + * + * However, we don't want to connect vEvent to just any vertex. We don''t + * want the new edge to cross any other edges; otherwise we will create + * intersection vertices even when the input data had no self-intersections. + * (This is a bad thing; if the user's input data has no intersections, + * we don't want to generate any false intersections ourselves.) + * + * Our eventual goal is to connect vEvent to the leftmost unprocessed + * vertex of the combined region (the union of regUp and regLo). + * But because of unseen vertices with all right-going edges, and also + * new vertices which may be created by edge intersections, we don''t + * know where that leftmost unprocessed vertex is. In the meantime, we + * connect vEvent to the closest vertex of either chain, and mark the region + * as "fixUpperEdge". This flag says to delete and reconnect this edge + * to the next processed vertex on the boundary of the combined region. + * Quite possibly the vertex we connected to will turn out to be the + * closest one, in which case we won''t need to make any changes. + */ +{ + GLUhalfEdge *eNew; + GLUhalfEdge *eTopLeft = eBottomLeft->Onext; + ActiveRegion *regLo = RegionBelow(regUp); + GLUhalfEdge *eUp = regUp->eUp; + GLUhalfEdge *eLo = regLo->eUp; + int degenerate = FALSE; + + if( eUp->Dst != eLo->Dst ) { + (void) CheckForIntersect( tess, regUp ); + } + + /* Possible new degeneracies: upper or lower edge of regUp may pass + * through vEvent, or may coincide with new intersection vertex + */ + if( VertEq( eUp->Org, tess->event )) { + if ( !__gl_meshSplice( eTopLeft->Oprev, eUp ) ) longjmp(tess->env,1); + regUp = TopLeftRegion( regUp ); + if (regUp == NULL) longjmp(tess->env,1); + eTopLeft = RegionBelow( regUp )->eUp; + FinishLeftRegions( tess, RegionBelow(regUp), regLo ); + degenerate = TRUE; + } + if( VertEq( eLo->Org, tess->event )) { + if ( !__gl_meshSplice( eBottomLeft, eLo->Oprev ) ) longjmp(tess->env,1); + eBottomLeft = FinishLeftRegions( tess, regLo, NULL ); + degenerate = TRUE; + } + if( degenerate ) { + AddRightEdges( tess, regUp, eBottomLeft->Onext, eTopLeft, eTopLeft, TRUE ); + return; + } + + /* Non-degenerate situation -- need to add a temporary, fixable edge. + * Connect to the closer of eLo->Org, eUp->Org. + */ + if( VertLeq( eLo->Org, eUp->Org )) { + eNew = eLo->Oprev; + } else { + eNew = eUp; + } + eNew = __gl_meshConnect( eBottomLeft->Lprev, eNew ); + if (eNew == NULL) longjmp(tess->env,1); + + /* Prevent cleanup, otherwise eNew might disappear before we've even + * had a chance to mark it as a temporary edge. + */ + AddRightEdges( tess, regUp, eNew, eNew->Onext, eNew->Onext, FALSE ); + eNew->Sym->activeRegion->fixUpperEdge = TRUE; + WalkDirtyRegions( tess, regUp ); +} + +/* Because vertices at exactly the same location are merged together + * before we process the sweep event, some degenerate cases can't occur. + * However if someone eventually makes the modifications required to + * merge features which are close together, the cases below marked + * TOLERANCE_NONZERO will be useful. They were debugged before the + * code to merge identical vertices in the main loop was added. + */ +#define TOLERANCE_NONZERO FALSE + +static void ConnectLeftDegenerate( GLUtesselator *tess, + ActiveRegion *regUp, GLUvertex *vEvent ) +/* + * The event vertex lies exacty on an already-processed edge or vertex. + * Adding the new vertex involves splicing it into the already-processed + * part of the mesh. + */ +{ + GLUhalfEdge *e, *eTopLeft, *eTopRight, *eLast; + ActiveRegion *reg; + + e = regUp->eUp; + if( VertEq( e->Org, vEvent )) { + /* e->Org is an unprocessed vertex - just combine them, and wait + * for e->Org to be pulled from the queue + */ + assert( TOLERANCE_NONZERO ); + SpliceMergeVertices( tess, e, vEvent->anEdge ); + return; + } + + if( ! VertEq( e->Dst, vEvent )) { + /* General case -- splice vEvent into edge e which passes through it */ + if (__gl_meshSplitEdge( e->Sym ) == NULL) longjmp(tess->env,1); + if( regUp->fixUpperEdge ) { + /* This edge was fixable -- delete unused portion of original edge */ + if ( !__gl_meshDelete( e->Onext ) ) longjmp(tess->env,1); + regUp->fixUpperEdge = FALSE; + } + if ( !__gl_meshSplice( vEvent->anEdge, e ) ) longjmp(tess->env,1); + SweepEvent( tess, vEvent ); /* recurse */ + return; + } + + /* vEvent coincides with e->Dst, which has already been processed. + * Splice in the additional right-going edges. + */ + assert( TOLERANCE_NONZERO ); + regUp = TopRightRegion( regUp ); + reg = RegionBelow( regUp ); + eTopRight = reg->eUp->Sym; + eTopLeft = eLast = eTopRight->Onext; + if( reg->fixUpperEdge ) { + /* Here e->Dst has only a single fixable edge going right. + * We can delete it since now we have some real right-going edges. + */ + assert( eTopLeft != eTopRight ); /* there are some left edges too */ + DeleteRegion( tess, reg ); + if ( !__gl_meshDelete( eTopRight ) ) longjmp(tess->env,1); + eTopRight = eTopLeft->Oprev; + } + if ( !__gl_meshSplice( vEvent->anEdge, eTopRight ) ) longjmp(tess->env,1); + if( ! EdgeGoesLeft( eTopLeft )) { + /* e->Dst had no left-going edges -- indicate this to AddRightEdges() */ + eTopLeft = NULL; + } + AddRightEdges( tess, regUp, eTopRight->Onext, eLast, eTopLeft, TRUE ); +} + + +static void ConnectLeftVertex( GLUtesselator *tess, GLUvertex *vEvent ) +/* + * Purpose: connect a "left" vertex (one where both edges go right) + * to the processed portion of the mesh. Let R be the active region + * containing vEvent, and let U and L be the upper and lower edge + * chains of R. There are two possibilities: + * + * - the normal case: split R into two regions, by connecting vEvent to + * the rightmost vertex of U or L lying to the left of the sweep line + * + * - the degenerate case: if vEvent is close enough to U or L, we + * merge vEvent into that edge chain. The subcases are: + * - merging with the rightmost vertex of U or L + * - merging with the active edge of U or L + * - merging with an already-processed portion of U or L + */ +{ + ActiveRegion *regUp, *regLo, *reg; + GLUhalfEdge *eUp, *eLo, *eNew; + ActiveRegion tmp; + + /* assert( vEvent->anEdge->Onext->Onext == vEvent->anEdge ); */ + + /* Get a pointer to the active region containing vEvent */ + tmp.eUp = vEvent->anEdge->Sym; + /* __GL_DICTLISTKEY */ /* __gl_dictListSearch */ + regUp = (ActiveRegion *)dictKey( dictSearch( tess->dict, &tmp )); + regLo = RegionBelow( regUp ); + eUp = regUp->eUp; + eLo = regLo->eUp; + + /* Try merging with U or L first */ + if( EdgeSign( eUp->Dst, vEvent, eUp->Org ) == 0 ) { + ConnectLeftDegenerate( tess, regUp, vEvent ); + return; + } + + /* Connect vEvent to rightmost processed vertex of either chain. + * e->Dst is the vertex that we will connect to vEvent. + */ + reg = VertLeq( eLo->Dst, eUp->Dst ) ? regUp : regLo; + + if( regUp->inside || reg->fixUpperEdge) { + if( reg == regUp ) { + eNew = __gl_meshConnect( vEvent->anEdge->Sym, eUp->Lnext ); + if (eNew == NULL) longjmp(tess->env,1); + } else { + GLUhalfEdge *tempHalfEdge= __gl_meshConnect( eLo->Dnext, vEvent->anEdge); + if (tempHalfEdge == NULL) longjmp(tess->env,1); + + eNew = tempHalfEdge->Sym; + } + if( reg->fixUpperEdge ) { + if ( !FixUpperEdge( reg, eNew ) ) longjmp(tess->env,1); + } else { + ComputeWinding( tess, AddRegionBelow( tess, regUp, eNew )); + } + SweepEvent( tess, vEvent ); + } else { + /* The new vertex is in a region which does not belong to the polygon. + * We don''t need to connect this vertex to the rest of the mesh. + */ + AddRightEdges( tess, regUp, vEvent->anEdge, vEvent->anEdge, NULL, TRUE ); + } +} + + +static void SweepEvent( GLUtesselator *tess, GLUvertex *vEvent ) +/* + * Does everything necessary when the sweep line crosses a vertex. + * Updates the mesh and the edge dictionary. + */ +{ + ActiveRegion *regUp, *reg; + GLUhalfEdge *e, *eTopLeft, *eBottomLeft; + + tess->event = vEvent; /* for access in EdgeLeq() */ + DebugEvent( tess ); + + /* Check if this vertex is the right endpoint of an edge that is + * already in the dictionary. In this case we don't need to waste + * time searching for the location to insert new edges. + */ + e = vEvent->anEdge; + while( e->activeRegion == NULL ) { + e = e->Onext; + if( e == vEvent->anEdge ) { + /* All edges go right -- not incident to any processed edges */ + ConnectLeftVertex( tess, vEvent ); + return; + } + } + + /* Processing consists of two phases: first we "finish" all the + * active regions where both the upper and lower edges terminate + * at vEvent (ie. vEvent is closing off these regions). + * We mark these faces "inside" or "outside" the polygon according + * to their winding number, and delete the edges from the dictionary. + * This takes care of all the left-going edges from vEvent. + */ + regUp = TopLeftRegion( e->activeRegion ); + if (regUp == NULL) longjmp(tess->env,1); + reg = RegionBelow( regUp ); + eTopLeft = reg->eUp; + eBottomLeft = FinishLeftRegions( tess, reg, NULL ); + + /* Next we process all the right-going edges from vEvent. This + * involves adding the edges to the dictionary, and creating the + * associated "active regions" which record information about the + * regions between adjacent dictionary edges. + */ + if( eBottomLeft->Onext == eTopLeft ) { + /* No right-going edges -- add a temporary "fixable" edge */ + ConnectRightVertex( tess, regUp, eBottomLeft ); + } else { + AddRightEdges( tess, regUp, eBottomLeft->Onext, eTopLeft, eTopLeft, TRUE ); + } +} + + +/* Make the sentinel coordinates big enough that they will never be + * merged with real input features. (Even with the largest possible + * input contour and the maximum tolerance of 1.0, no merging will be + * done with coordinates larger than 3 * GLU_TESS_MAX_COORD). + */ +#define SENTINEL_COORD (4 * GLU_TESS_MAX_COORD) + +static void AddSentinel( GLUtesselator *tess, GLdouble t ) +/* + * We add two sentinel edges above and below all other edges, + * to avoid special cases at the top and bottom. + */ +{ + GLUhalfEdge *e; + ActiveRegion *reg = (ActiveRegion *)memAlloc( sizeof( ActiveRegion )); + if (reg == NULL) longjmp(tess->env,1); + + e = __gl_meshMakeEdge( tess->mesh ); + if (e == NULL) longjmp(tess->env,1); + + e->Org->s = SENTINEL_COORD; + e->Org->t = t; + e->Dst->s = -SENTINEL_COORD; + e->Dst->t = t; + tess->event = e->Dst; /* initialize it */ + + reg->eUp = e; + reg->windingNumber = 0; + reg->inside = FALSE; + reg->fixUpperEdge = FALSE; + reg->sentinel = TRUE; + reg->dirty = FALSE; + reg->nodeUp = dictInsert( tess->dict, reg ); /* __gl_dictListInsertBefore */ + if (reg->nodeUp == NULL) longjmp(tess->env,1); +} + + +static void InitEdgeDict( GLUtesselator *tess ) +/* + * We maintain an ordering of edge intersections with the sweep line. + * This order is maintained in a dynamic dictionary. + */ +{ + /* __gl_dictListNewDict */ + tess->dict = dictNewDict( tess, (int (*)(void *, DictKey, DictKey)) EdgeLeq ); + if (tess->dict == NULL) longjmp(tess->env,1); + + AddSentinel( tess, -SENTINEL_COORD ); + AddSentinel( tess, SENTINEL_COORD ); +} + + +static void DoneEdgeDict( GLUtesselator *tess ) +{ + ActiveRegion *reg; +#ifndef NDEBUG + int fixedEdges = 0; +#endif + + /* __GL_DICTLISTKEY */ /* __GL_DICTLISTMIN */ + while( (reg = (ActiveRegion *)dictKey( dictMin( tess->dict ))) != NULL ) { + /* + * At the end of all processing, the dictionary should contain + * only the two sentinel edges, plus at most one "fixable" edge + * created by ConnectRightVertex(). + */ + if( ! reg->sentinel ) { + assert( reg->fixUpperEdge ); + assert( ++fixedEdges == 1 ); + } + assert( reg->windingNumber == 0 ); + DeleteRegion( tess, reg ); +/* __gl_meshDelete( reg->eUp );*/ + } + dictDeleteDict( tess->dict ); /* __gl_dictListDeleteDict */ +} + + +static void RemoveDegenerateEdges( GLUtesselator *tess ) +/* + * Remove zero-length edges, and contours with fewer than 3 vertices. + */ +{ + GLUhalfEdge *e, *eNext, *eLnext; + GLUhalfEdge *eHead = &tess->mesh->eHead; + + /*LINTED*/ + for( e = eHead->next; e != eHead; e = eNext ) { + eNext = e->next; + eLnext = e->Lnext; + + if( VertEq( e->Org, e->Dst ) && e->Lnext->Lnext != e ) { + /* Zero-length edge, contour has at least 3 edges */ + + SpliceMergeVertices( tess, eLnext, e ); /* deletes e->Org */ + if ( !__gl_meshDelete( e ) ) longjmp(tess->env,1); /* e is a self-loop */ + e = eLnext; + eLnext = e->Lnext; + } + if( eLnext->Lnext == e ) { + /* Degenerate contour (one or two edges) */ + + if( eLnext != e ) { + if( eLnext == eNext || eLnext == eNext->Sym ) { eNext = eNext->next; } + if ( !__gl_meshDelete( eLnext ) ) longjmp(tess->env,1); + } + if( e == eNext || e == eNext->Sym ) { eNext = eNext->next; } + if ( !__gl_meshDelete( e ) ) longjmp(tess->env,1); + } + } +} + +static int InitPriorityQ( GLUtesselator *tess ) +/* + * Insert all vertices into the priority queue which determines the + * order in which vertices cross the sweep line. + */ +{ + PriorityQ *pq; + GLUvertex *v, *vHead; + + /* __gl_pqSortNewPriorityQ */ + pq = tess->pq = pqNewPriorityQ( (int (*)(PQkey, PQkey)) __gl_vertLeq ); + if (pq == NULL) return 0; + + vHead = &tess->mesh->vHead; + for( v = vHead->next; v != vHead; v = v->next ) { + v->pqHandle = pqInsert( pq, v ); /* __gl_pqSortInsert */ + if (v->pqHandle == LONG_MAX) break; + } + if (v != vHead || !pqInit( pq ) ) { /* __gl_pqSortInit */ + pqDeletePriorityQ(tess->pq); /* __gl_pqSortDeletePriorityQ */ + tess->pq = NULL; + return 0; + } + + return 1; +} + + +static void DonePriorityQ( GLUtesselator *tess ) +{ + pqDeletePriorityQ( tess->pq ); /* __gl_pqSortDeletePriorityQ */ +} + + +static int RemoveDegenerateFaces( GLUmesh *mesh ) +/* + * Delete any degenerate faces with only two edges. WalkDirtyRegions() + * will catch almost all of these, but it won't catch degenerate faces + * produced by splice operations on already-processed edges. + * The two places this can happen are in FinishLeftRegions(), when + * we splice in a "temporary" edge produced by ConnectRightVertex(), + * and in CheckForLeftSplice(), where we splice already-processed + * edges to ensure that our dictionary invariants are not violated + * by numerical errors. + * + * In both these cases it is *very* dangerous to delete the offending + * edge at the time, since one of the routines further up the stack + * will sometimes be keeping a pointer to that edge. + */ +{ + GLUface *f, *fNext; + GLUhalfEdge *e; + + /*LINTED*/ + for( f = mesh->fHead.next; f != &mesh->fHead; f = fNext ) { + fNext = f->next; + e = f->anEdge; + assert( e->Lnext != e ); + + if( e->Lnext->Lnext == e ) { + /* A face with only two edges */ + AddWinding( e->Onext, e ); + if ( !__gl_meshDelete( e ) ) return 0; + } + } + return 1; +} + +int __gl_computeInterior( GLUtesselator *tess ) +/* + * __gl_computeInterior( tess ) computes the planar arrangement specified + * by the given contours, and further subdivides this arrangement + * into regions. Each region is marked "inside" if it belongs + * to the polygon, according to the rule given by tess->windingRule. + * Each interior region is guaranteed be monotone. + */ +{ + GLUvertex *v, *vNext; + + tess->fatalError = FALSE; + + /* Each vertex defines an event for our sweep line. Start by inserting + * all the vertices in a priority queue. Events are processed in + * lexicographic order, ie. + * + * e1 < e2 iff e1.x < e2.x || (e1.x == e2.x && e1.y < e2.y) + */ + RemoveDegenerateEdges( tess ); + if ( !InitPriorityQ( tess ) ) return 0; /* if error */ + InitEdgeDict( tess ); + + /* __gl_pqSortExtractMin */ + while( (v = (GLUvertex *)pqExtractMin( tess->pq )) != NULL ) { + for( ;; ) { + vNext = (GLUvertex *)pqMinimum( tess->pq ); /* __gl_pqSortMinimum */ + if( vNext == NULL || ! VertEq( vNext, v )) break; + + /* Merge together all vertices at exactly the same location. + * This is more efficient than processing them one at a time, + * simplifies the code (see ConnectLeftDegenerate), and is also + * important for correct handling of certain degenerate cases. + * For example, suppose there are two identical edges A and B + * that belong to different contours (so without this code they would + * be processed by separate sweep events). Suppose another edge C + * crosses A and B from above. When A is processed, we split it + * at its intersection point with C. However this also splits C, + * so when we insert B we may compute a slightly different + * intersection point. This might leave two edges with a small + * gap between them. This kind of error is especially obvious + * when using boundary extraction (GLU_TESS_BOUNDARY_ONLY). + */ + vNext = (GLUvertex *)pqExtractMin( tess->pq ); /* __gl_pqSortExtractMin*/ + SpliceMergeVertices( tess, v->anEdge, vNext->anEdge ); + } + SweepEvent( tess, v ); + } + + /* Set tess->event for debugging purposes */ + /* __GL_DICTLISTKEY */ /* __GL_DICTLISTMIN */ + tess->event = ((ActiveRegion *) dictKey( dictMin( tess->dict )))->eUp->Org; + DebugEvent( tess ); + DoneEdgeDict( tess ); + DonePriorityQ( tess ); + + if ( !RemoveDegenerateFaces( tess->mesh ) ) return 0; + __gl_meshCheckMesh( tess->mesh ); + + return 1; +} diff --git a/cogl/cogl-path/tesselator/sweep.h b/cogl/cogl-path/tesselator/sweep.h new file mode 100644 index 0000000..feb68b0 --- /dev/null +++ b/cogl/cogl-path/tesselator/sweep.h @@ -0,0 +1,77 @@ +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ +/* +** Author: Eric Veach, July 1994. +** +*/ + +#ifndef __sweep_h_ +#define __sweep_h_ + +#include "mesh.h" + +/* __gl_computeInterior( tess ) computes the planar arrangement specified + * by the given contours, and further subdivides this arrangement + * into regions. Each region is marked "inside" if it belongs + * to the polygon, according to the rule given by tess->windingRule. + * Each interior region is guaranteed be monotone. + */ +int __gl_computeInterior( GLUtesselator *tess ); + + +/* The following is here *only* for access by debugging routines */ + +#include "dict.h" + +/* For each pair of adjacent edges crossing the sweep line, there is + * an ActiveRegion to represent the region between them. The active + * regions are kept in sorted order in a dynamic dictionary. As the + * sweep line crosses each vertex, we update the affected regions. + */ + +struct ActiveRegion { + GLUhalfEdge *eUp; /* upper edge, directed right to left */ + DictNode *nodeUp; /* dictionary node corresponding to eUp */ + int windingNumber; /* used to determine which regions are + * inside the polygon */ + GLboolean inside; /* is this region inside the polygon? */ + GLboolean sentinel; /* marks fake edges at t = +/-infinity */ + GLboolean dirty; /* marks regions where the upper or lower + * edge has changed, but we haven't checked + * whether they intersect yet */ + GLboolean fixUpperEdge; /* marks temporary edges introduced when + * we process a "right vertex" (one without + * any edges leaving to the right) */ +}; + +#define RegionBelow(r) ((ActiveRegion *) dictKey(dictPred((r)->nodeUp))) +#define RegionAbove(r) ((ActiveRegion *) dictKey(dictSucc((r)->nodeUp))) + +#endif diff --git a/cogl/cogl-path/tesselator/tess.c b/cogl/cogl-path/tesselator/tess.c new file mode 100644 index 0000000..4a0e8de --- /dev/null +++ b/cogl/cogl-path/tesselator/tess.c @@ -0,0 +1,632 @@ +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ +/* +** Author: Eric Veach, July 1994. +** +*/ + +#include "gluos.h" +#include +#include +#include +#include "memalloc.h" +#include "tess.h" +#include "mesh.h" +#include "normal.h" +#include "sweep.h" +#include "tessmono.h" +#include "render.h" + +#define GLU_TESS_DEFAULT_TOLERANCE 0.0 +#define GLU_TESS_MESH 100112 /* void (*)(GLUmesh *mesh) */ + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +/*ARGSUSED*/ static void GLAPIENTRY noBegin( GLenum type ) {} +/*ARGSUSED*/ static void GLAPIENTRY noEdgeFlag( GLboolean boundaryEdge ) {} +/*ARGSUSED*/ static void GLAPIENTRY noVertex( void *data ) {} +/*ARGSUSED*/ static void GLAPIENTRY noEnd( void ) {} +/*ARGSUSED*/ static void GLAPIENTRY noError( GLenum errnum ) {} +/*ARGSUSED*/ static void GLAPIENTRY noCombine( GLdouble coords[3], void *data[4], + GLfloat weight[4], void **dataOut ) {} +/*ARGSUSED*/ static void GLAPIENTRY noMesh( GLUmesh *mesh ) {} + + +/*ARGSUSED*/ void GLAPIENTRY __gl_noBeginData( GLenum type, + void *polygonData ) {} +/*ARGSUSED*/ void GLAPIENTRY __gl_noEdgeFlagData( GLboolean boundaryEdge, + void *polygonData ) {} +/*ARGSUSED*/ void GLAPIENTRY __gl_noVertexData( void *data, + void *polygonData ) {} +/*ARGSUSED*/ void GLAPIENTRY __gl_noEndData( void *polygonData ) {} +/*ARGSUSED*/ void GLAPIENTRY __gl_noErrorData( GLenum errnum, + void *polygonData ) {} +/*ARGSUSED*/ void GLAPIENTRY __gl_noCombineData( GLdouble coords[3], + void *data[4], + GLfloat weight[4], + void **outData, + void *polygonData ) {} + +/* Half-edges are allocated in pairs (see mesh.c) */ +typedef struct { GLUhalfEdge e, eSym; } EdgePair; + +#undef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#define MAX_FAST_ALLOC (MAX(sizeof(EdgePair), \ + MAX(sizeof(GLUvertex),sizeof(GLUface)))) + + +GLUtesselator * GLAPIENTRY +gluNewTess( void ) +{ + GLUtesselator *tess; + + /* Only initialize fields which can be changed by the api. Other fields + * are initialized where they are used. + */ + + if (memInit( MAX_FAST_ALLOC ) == 0) { + return 0; /* out of memory */ + } + tess = (GLUtesselator *)memAlloc( sizeof( GLUtesselator )); + if (tess == NULL) { + return 0; /* out of memory */ + } + + tess->state = T_DORMANT; + + tess->normal[0] = 0; + tess->normal[1] = 0; + tess->normal[2] = 0; + + tess->relTolerance = GLU_TESS_DEFAULT_TOLERANCE; + tess->windingRule = GLU_TESS_WINDING_ODD; + tess->flagBoundary = FALSE; + tess->boundaryOnly = FALSE; + + tess->callBegin = &noBegin; + tess->callEdgeFlag = &noEdgeFlag; + tess->callVertex = &noVertex; + tess->callEnd = &noEnd; + + tess->callError = &noError; + tess->callCombine = &noCombine; + tess->callMesh = &noMesh; + + tess->callBeginData= &__gl_noBeginData; + tess->callEdgeFlagData= &__gl_noEdgeFlagData; + tess->callVertexData= &__gl_noVertexData; + tess->callEndData= &__gl_noEndData; + tess->callErrorData= &__gl_noErrorData; + tess->callCombineData= &__gl_noCombineData; + + tess->polygonData= NULL; + + return tess; +} + +static void MakeDormant( GLUtesselator *tess ) +{ + /* Return the tessellator to its original dormant state. */ + + if( tess->mesh != NULL ) { + __gl_meshDeleteMesh( tess->mesh ); + } + tess->state = T_DORMANT; + tess->lastEdge = NULL; + tess->mesh = NULL; +} + +#define RequireState( tess, s ) if( tess->state != s ) GotoState(tess,s) + +static void GotoState( GLUtesselator *tess, enum TessState newState ) +{ + while( tess->state != newState ) { + /* We change the current state one level at a time, to get to + * the desired state. + */ + if( tess->state < newState ) { + switch( tess->state ) { + case T_DORMANT: + CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_BEGIN_POLYGON ); + gluTessBeginPolygon( tess, NULL ); + break; + case T_IN_POLYGON: + CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_BEGIN_CONTOUR ); + gluTessBeginContour( tess ); + break; + default: + ; + } + } else { + switch( tess->state ) { + case T_IN_CONTOUR: + CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_END_CONTOUR ); + gluTessEndContour( tess ); + break; + case T_IN_POLYGON: + CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_END_POLYGON ); + /* gluTessEndPolygon( tess ) is too much work! */ + MakeDormant( tess ); + break; + default: + ; + } + } + } +} + + +void GLAPIENTRY +gluDeleteTess( GLUtesselator *tess ) +{ + RequireState( tess, T_DORMANT ); + memFree( tess ); +} + + +void GLAPIENTRY +gluTessProperty( GLUtesselator *tess, GLenum which, GLdouble value ) +{ + GLenum windingRule; + + switch( which ) { + case GLU_TESS_TOLERANCE: + if( value < 0.0 || value > 1.0 ) break; + tess->relTolerance = value; + return; + + case GLU_TESS_WINDING_RULE: + windingRule = (GLenum) value; + if( windingRule != value ) break; /* not an integer */ + + switch( windingRule ) { + case GLU_TESS_WINDING_ODD: + case GLU_TESS_WINDING_NONZERO: + case GLU_TESS_WINDING_POSITIVE: + case GLU_TESS_WINDING_NEGATIVE: + case GLU_TESS_WINDING_ABS_GEQ_TWO: + tess->windingRule = windingRule; + return; + default: + break; + } + + case GLU_TESS_BOUNDARY_ONLY: + tess->boundaryOnly = (value != 0); + return; + + default: + CALL_ERROR_OR_ERROR_DATA( GLU_INVALID_ENUM ); + return; + } + CALL_ERROR_OR_ERROR_DATA( GLU_INVALID_VALUE ); +} + +/* Returns tessellator property */ +void GLAPIENTRY +gluGetTessProperty( GLUtesselator *tess, GLenum which, GLdouble *value ) +{ + switch (which) { + case GLU_TESS_TOLERANCE: + /* tolerance should be in range [0..1] */ + assert(0.0 <= tess->relTolerance && tess->relTolerance <= 1.0); + *value= tess->relTolerance; + break; + case GLU_TESS_WINDING_RULE: + assert(tess->windingRule == GLU_TESS_WINDING_ODD || + tess->windingRule == GLU_TESS_WINDING_NONZERO || + tess->windingRule == GLU_TESS_WINDING_POSITIVE || + tess->windingRule == GLU_TESS_WINDING_NEGATIVE || + tess->windingRule == GLU_TESS_WINDING_ABS_GEQ_TWO); + *value= tess->windingRule; + break; + case GLU_TESS_BOUNDARY_ONLY: + assert(tess->boundaryOnly == TRUE || tess->boundaryOnly == FALSE); + *value= tess->boundaryOnly; + break; + default: + *value= 0.0; + CALL_ERROR_OR_ERROR_DATA( GLU_INVALID_ENUM ); + break; + } +} /* gluGetTessProperty() */ + +void GLAPIENTRY +gluTessNormal( GLUtesselator *tess, GLdouble x, GLdouble y, GLdouble z ) +{ + tess->normal[0] = x; + tess->normal[1] = y; + tess->normal[2] = z; +} + +void GLAPIENTRY +gluTessCallback( GLUtesselator *tess, GLenum which, _GLUfuncptr fn) +{ + switch( which ) { + case GLU_TESS_BEGIN: + tess->callBegin = (fn == NULL) ? &noBegin : (void (GLAPIENTRY *)(GLenum)) fn; + return; + case GLU_TESS_BEGIN_DATA: + tess->callBeginData = (fn == NULL) ? + &__gl_noBeginData : (void (GLAPIENTRY *)(GLenum, void *)) fn; + return; + case GLU_TESS_EDGE_FLAG: + tess->callEdgeFlag = (fn == NULL) ? &noEdgeFlag : + (void (GLAPIENTRY *)(GLboolean)) fn; + /* If the client wants boundary edges to be flagged, + * we render everything as separate triangles (no strips or fans). + */ + tess->flagBoundary = (fn != NULL); + return; + case GLU_TESS_EDGE_FLAG_DATA: + tess->callEdgeFlagData= (fn == NULL) ? + &__gl_noEdgeFlagData : (void (GLAPIENTRY *)(GLboolean, void *)) fn; + /* If the client wants boundary edges to be flagged, + * we render everything as separate triangles (no strips or fans). + */ + tess->flagBoundary = (fn != NULL); + return; + case GLU_TESS_VERTEX: + tess->callVertex = (fn == NULL) ? &noVertex : + (void (GLAPIENTRY *)(void *)) fn; + return; + case GLU_TESS_VERTEX_DATA: + tess->callVertexData = (fn == NULL) ? + &__gl_noVertexData : (void (GLAPIENTRY *)(void *, void *)) fn; + return; + case GLU_TESS_END: + tess->callEnd = (fn == NULL) ? &noEnd : (void (GLAPIENTRY *)(void)) fn; + return; + case GLU_TESS_END_DATA: + tess->callEndData = (fn == NULL) ? &__gl_noEndData : + (void (GLAPIENTRY *)(void *)) fn; + return; + case GLU_TESS_ERROR: + tess->callError = (fn == NULL) ? &noError : (void (GLAPIENTRY *)(GLenum)) fn; + return; + case GLU_TESS_ERROR_DATA: + tess->callErrorData = (fn == NULL) ? + &__gl_noErrorData : (void (GLAPIENTRY *)(GLenum, void *)) fn; + return; + case GLU_TESS_COMBINE: + tess->callCombine = (fn == NULL) ? &noCombine : + (void (GLAPIENTRY *)(GLdouble [3],void *[4], GLfloat [4], void ** )) fn; + return; + case GLU_TESS_COMBINE_DATA: + tess->callCombineData = (fn == NULL) ? &__gl_noCombineData : + (void (GLAPIENTRY *)(GLdouble [3], + void *[4], + GLfloat [4], + void **, + void *)) fn; + return; + case GLU_TESS_MESH: + tess->callMesh = (fn == NULL) ? &noMesh : (void (GLAPIENTRY *)(GLUmesh *)) fn; + return; + default: + CALL_ERROR_OR_ERROR_DATA( GLU_INVALID_ENUM ); + return; + } +} + +static int AddVertex( GLUtesselator *tess, GLdouble coords[3], void *data ) +{ + GLUhalfEdge *e; + + e = tess->lastEdge; + if( e == NULL ) { + /* Make a self-loop (one vertex, one edge). */ + + e = __gl_meshMakeEdge( tess->mesh ); + if (e == NULL) return 0; + if ( !__gl_meshSplice( e, e->Sym ) ) return 0; + } else { + /* Create a new vertex and edge which immediately follow e + * in the ordering around the left face. + */ + if (__gl_meshSplitEdge( e ) == NULL) return 0; + e = e->Lnext; + } + + /* The new vertex is now e->Org. */ + e->Org->data = data; + e->Org->coords[0] = coords[0]; + e->Org->coords[1] = coords[1]; + e->Org->coords[2] = coords[2]; + + /* The winding of an edge says how the winding number changes as we + * cross from the edge''s right face to its left face. We add the + * vertices in such an order that a CCW contour will add +1 to + * the winding number of the region inside the contour. + */ + e->winding = 1; + e->Sym->winding = -1; + + tess->lastEdge = e; + + return 1; +} + + +static void CacheVertex( GLUtesselator *tess, GLdouble coords[3], void *data ) +{ + CachedVertex *v = &tess->cache[tess->cacheCount]; + + v->data = data; + v->coords[0] = coords[0]; + v->coords[1] = coords[1]; + v->coords[2] = coords[2]; + ++tess->cacheCount; +} + + +static int EmptyCache( GLUtesselator *tess ) +{ + CachedVertex *v = tess->cache; + CachedVertex *vLast; + + tess->mesh = __gl_meshNewMesh(); + if (tess->mesh == NULL) return 0; + + for( vLast = v + tess->cacheCount; v < vLast; ++v ) { + if ( !AddVertex( tess, v->coords, v->data ) ) return 0; + } + tess->cacheCount = 0; + tess->emptyCache = FALSE; + + return 1; +} + + +void GLAPIENTRY +gluTessVertex( GLUtesselator *tess, GLdouble coords[3], void *data ) +{ + int i, tooLarge = FALSE; + GLdouble x, clamped[3]; + + RequireState( tess, T_IN_CONTOUR ); + + if( tess->emptyCache ) { + if ( !EmptyCache( tess ) ) { + CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY ); + return; + } + tess->lastEdge = NULL; + } + for( i = 0; i < 3; ++i ) { + x = coords[i]; + if( x < - GLU_TESS_MAX_COORD ) { + x = - GLU_TESS_MAX_COORD; + tooLarge = TRUE; + } + if( x > GLU_TESS_MAX_COORD ) { + x = GLU_TESS_MAX_COORD; + tooLarge = TRUE; + } + clamped[i] = x; + } + if( tooLarge ) { + CALL_ERROR_OR_ERROR_DATA( GLU_TESS_COORD_TOO_LARGE ); + } + + if( tess->mesh == NULL ) { + if( tess->cacheCount < TESS_MAX_CACHE ) { + CacheVertex( tess, clamped, data ); + return; + } + if ( !EmptyCache( tess ) ) { + CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY ); + return; + } + } + if ( !AddVertex( tess, clamped, data ) ) { + CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY ); + } +} + + +void GLAPIENTRY +gluTessBeginPolygon( GLUtesselator *tess, void *data ) +{ + RequireState( tess, T_DORMANT ); + + tess->state = T_IN_POLYGON; + tess->cacheCount = 0; + tess->emptyCache = FALSE; + tess->mesh = NULL; + + tess->polygonData= data; +} + + +void GLAPIENTRY +gluTessBeginContour( GLUtesselator *tess ) +{ + RequireState( tess, T_IN_POLYGON ); + + tess->state = T_IN_CONTOUR; + tess->lastEdge = NULL; + if( tess->cacheCount > 0 ) { + /* Just set a flag so we don't get confused by empty contours + * -- these can be generated accidentally with the obsolete + * NextContour() interface. + */ + tess->emptyCache = TRUE; + } +} + + +void GLAPIENTRY +gluTessEndContour( GLUtesselator *tess ) +{ + RequireState( tess, T_IN_CONTOUR ); + tess->state = T_IN_POLYGON; +} + +void GLAPIENTRY +gluTessEndPolygon( GLUtesselator *tess ) +{ + GLUmesh *mesh; + + if (setjmp(tess->env) != 0) { + /* come back here if out of memory */ + CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY ); + return; + } + + RequireState( tess, T_IN_POLYGON ); + tess->state = T_DORMANT; + + if( tess->mesh == NULL ) { + if( ! tess->flagBoundary && tess->callMesh == &noMesh ) { + + /* Try some special code to make the easy cases go quickly + * (eg. convex polygons). This code does NOT handle multiple contours, + * intersections, edge flags, and of course it does not generate + * an explicit mesh either. + */ + if( __gl_renderCache( tess )) { + tess->polygonData= NULL; + return; + } + } + if ( !EmptyCache( tess ) ) longjmp(tess->env,1); /* could've used a label*/ + } + + /* Determine the polygon normal and project vertices onto the plane + * of the polygon. + */ + __gl_projectPolygon( tess ); + + /* __gl_computeInterior( tess ) computes the planar arrangement specified + * by the given contours, and further subdivides this arrangement + * into regions. Each region is marked "inside" if it belongs + * to the polygon, according to the rule given by tess->windingRule. + * Each interior region is guaranteed be monotone. + */ + if ( !__gl_computeInterior( tess ) ) { + longjmp(tess->env,1); /* could've used a label */ + } + + mesh = tess->mesh; + if( ! tess->fatalError ) { + int rc = 1; + + /* If the user wants only the boundary contours, we throw away all edges + * except those which separate the interior from the exterior. + * Otherwise we tessellate all the regions marked "inside". + */ + if( tess->boundaryOnly ) { + rc = __gl_meshSetWindingNumber( mesh, 1, TRUE ); + } else { + rc = __gl_meshTessellateInterior( mesh ); + } + if (rc == 0) longjmp(tess->env,1); /* could've used a label */ + + __gl_meshCheckMesh( mesh ); + + if( tess->callBegin != &noBegin || tess->callEnd != &noEnd + || tess->callVertex != &noVertex || tess->callEdgeFlag != &noEdgeFlag + || tess->callBeginData != &__gl_noBeginData + || tess->callEndData != &__gl_noEndData + || tess->callVertexData != &__gl_noVertexData + || tess->callEdgeFlagData != &__gl_noEdgeFlagData ) + { + if( tess->boundaryOnly ) { + __gl_renderBoundary( tess, mesh ); /* output boundary contours */ + } else { + __gl_renderMesh( tess, mesh ); /* output strips and fans */ + } + } + if( tess->callMesh != &noMesh ) { + + /* Throw away the exterior faces, so that all faces are interior. + * This way the user doesn't have to check the "inside" flag, + * and we don't need to even reveal its existence. It also leaves + * the freedom for an implementation to not generate the exterior + * faces in the first place. + */ + __gl_meshDiscardExterior( mesh ); + (*tess->callMesh)( mesh ); /* user wants the mesh itself */ + tess->mesh = NULL; + tess->polygonData= NULL; + return; + } + } + __gl_meshDeleteMesh( mesh ); + tess->polygonData= NULL; + tess->mesh = NULL; +} + + +/*XXXblythe unused function*/ +#if 0 +void GLAPIENTRY +gluDeleteMesh( GLUmesh *mesh ) +{ + __gl_meshDeleteMesh( mesh ); +} +#endif + + + +/*******************************************************/ + +/* Obsolete calls -- for backward compatibility */ + +void GLAPIENTRY +gluBeginPolygon( GLUtesselator *tess ) +{ + gluTessBeginPolygon( tess, NULL ); + gluTessBeginContour( tess ); +} + + +/*ARGSUSED*/ +void GLAPIENTRY +gluNextContour( GLUtesselator *tess, GLenum type ) +{ + gluTessEndContour( tess ); + gluTessBeginContour( tess ); +} + + +void GLAPIENTRY +gluEndPolygon( GLUtesselator *tess ) +{ + gluTessEndContour( tess ); + gluTessEndPolygon( tess ); +} diff --git a/cogl/cogl-path/tesselator/tess.h b/cogl/cogl-path/tesselator/tess.h new file mode 100644 index 0000000..1624960 --- /dev/null +++ b/cogl/cogl-path/tesselator/tess.h @@ -0,0 +1,165 @@ +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ +/* +** Author: Eric Veach, July 1994. +** +*/ + +#ifndef __tess_h_ +#define __tess_h_ + +#include +#include +#include "mesh.h" +#include "dict.h" +#include "priorityq.h" + +/* The begin/end calls must be properly nested. We keep track of + * the current state to enforce the ordering. + */ +enum TessState { T_DORMANT, T_IN_POLYGON, T_IN_CONTOUR }; + +/* We cache vertex data for single-contour polygons so that we can + * try a quick-and-dirty decomposition first. + */ +#define TESS_MAX_CACHE 100 + +typedef struct CachedVertex { + GLdouble coords[3]; + void *data; +} CachedVertex; + +struct GLUtesselator { + + /*** state needed for collecting the input data ***/ + + enum TessState state; /* what begin/end calls have we seen? */ + + GLUhalfEdge *lastEdge; /* lastEdge->Org is the most recent vertex */ + GLUmesh *mesh; /* stores the input contours, and eventually + the tessellation itself */ + + void (GLAPIENTRY *callError)( GLenum errnum ); + + /*** state needed for projecting onto the sweep plane ***/ + + GLdouble normal[3]; /* user-specified normal (if provided) */ + GLdouble sUnit[3]; /* unit vector in s-direction (debugging) */ + GLdouble tUnit[3]; /* unit vector in t-direction (debugging) */ + + /*** state needed for the line sweep ***/ + + GLdouble relTolerance; /* tolerance for merging features */ + GLenum windingRule; /* rule for determining polygon interior */ + GLboolean fatalError; /* fatal error: needed combine callback */ + + Dict *dict; /* edge dictionary for sweep line */ + PriorityQ *pq; /* priority queue of vertex events */ + GLUvertex *event; /* current sweep event being processed */ + + void (GLAPIENTRY *callCombine)( GLdouble coords[3], void *data[4], + GLfloat weight[4], void **outData ); + + /*** state needed for rendering callbacks (see render.c) ***/ + + GLboolean flagBoundary; /* mark boundary edges (use EdgeFlag) */ + GLboolean boundaryOnly; /* Extract contours, not triangles */ + GLUface *lonelyTriList; + /* list of triangles which could not be rendered as strips or fans */ + + void (GLAPIENTRY *callBegin)( GLenum type ); + void (GLAPIENTRY *callEdgeFlag)( GLboolean boundaryEdge ); + void (GLAPIENTRY *callVertex)( void *data ); + void (GLAPIENTRY *callEnd)( void ); + void (GLAPIENTRY *callMesh)( GLUmesh *mesh ); + + + /*** state needed to cache single-contour polygons for renderCache() */ + + GLboolean emptyCache; /* empty cache on next vertex() call */ + int cacheCount; /* number of cached vertices */ + CachedVertex cache[TESS_MAX_CACHE]; /* the vertex data */ + + /*** rendering callbacks that also pass polygon data ***/ + void (GLAPIENTRY *callBeginData)( GLenum type, void *polygonData ); + void (GLAPIENTRY *callEdgeFlagData)( GLboolean boundaryEdge, + void *polygonData ); + void (GLAPIENTRY *callVertexData)( void *data, void *polygonData ); + void (GLAPIENTRY *callEndData)( void *polygonData ); + void (GLAPIENTRY *callErrorData)( GLenum errnum, void *polygonData ); + void (GLAPIENTRY *callCombineData)( GLdouble coords[3], void *data[4], + GLfloat weight[4], void **outData, + void *polygonData ); + + jmp_buf env; /* place to jump to when memAllocs fail */ + + void *polygonData; /* client data for current polygon */ +}; + +void GLAPIENTRY __gl_noBeginData( GLenum type, void *polygonData ); +void GLAPIENTRY __gl_noEdgeFlagData( GLboolean boundaryEdge, void *polygonData ); +void GLAPIENTRY __gl_noVertexData( void *data, void *polygonData ); +void GLAPIENTRY __gl_noEndData( void *polygonData ); +void GLAPIENTRY __gl_noErrorData( GLenum errnum, void *polygonData ); +void GLAPIENTRY __gl_noCombineData( GLdouble coords[3], void *data[4], + GLfloat weight[4], void **outData, + void *polygonData ); + +#define CALL_BEGIN_OR_BEGIN_DATA(a) \ + if (tess->callBeginData != &__gl_noBeginData) \ + (*tess->callBeginData)((a),tess->polygonData); \ + else (*tess->callBegin)((a)); + +#define CALL_VERTEX_OR_VERTEX_DATA(a) \ + if (tess->callVertexData != &__gl_noVertexData) \ + (*tess->callVertexData)((a),tess->polygonData); \ + else (*tess->callVertex)((a)); + +#define CALL_EDGE_FLAG_OR_EDGE_FLAG_DATA(a) \ + if (tess->callEdgeFlagData != &__gl_noEdgeFlagData) \ + (*tess->callEdgeFlagData)((a),tess->polygonData); \ + else (*tess->callEdgeFlag)((a)); + +#define CALL_END_OR_END_DATA() \ + if (tess->callEndData != &__gl_noEndData) \ + (*tess->callEndData)(tess->polygonData); \ + else (*tess->callEnd)(); + +#define CALL_COMBINE_OR_COMBINE_DATA(a,b,c,d) \ + if (tess->callCombineData != &__gl_noCombineData) \ + (*tess->callCombineData)((a),(b),(c),(d),tess->polygonData); \ + else (*tess->callCombine)((a),(b),(c),(d)); + +#define CALL_ERROR_OR_ERROR_DATA(a) \ + if (tess->callErrorData != &__gl_noErrorData) \ + (*tess->callErrorData)((a),tess->polygonData); \ + else (*tess->callError)((a)); + +#endif diff --git a/cogl/cogl-path/tesselator/tesselator.h b/cogl/cogl-path/tesselator/tesselator.h new file mode 100644 index 0000000..5b651be --- /dev/null +++ b/cogl/cogl-path/tesselator/tesselator.h @@ -0,0 +1,122 @@ +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (C) 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ + +#ifndef __TESSELATOR_H__ +#define __TESSELATOR_H__ + +/* This just includes the defines needed by the tesselator code */ + +#include "cogl/cogl-defines.h" +#include "cogl/cogl-gl-header.h" + +typedef struct GLUtesselator GLUtesselator; + +#define GLU_TESS_MAX_COORD 1.0e150 + +void gluBeginPolygon (GLUtesselator* tess); +void gluDeleteTess (GLUtesselator* tess); +void gluEndPolygon (GLUtesselator* tess); + +typedef void (_GLUfuncptr)(); + +void gluGetTessProperty (GLUtesselator* tess, GLenum which, double* data); + +GLUtesselator *gluNewTess (void); +void gluNextContour (GLUtesselator* tess, GLenum type); + +void gluTessBeginContour (GLUtesselator* tess); +void gluTessBeginPolygon (GLUtesselator* tess, GLvoid* data); +void gluTessCallback (GLUtesselator* tess, GLenum which, _GLUfuncptr CallBackFunc); +void gluTessEndContour (GLUtesselator* tess); +void gluTessEndPolygon (GLUtesselator* tess); +void gluTessNormal (GLUtesselator* tess, double valueX, double valueY, double valueZ); +void gluTessProperty (GLUtesselator* tess, GLenum which, double data); +void gluTessVertex (GLUtesselator* tess, double *location, GLvoid* data); + +/* ErrorCode */ +#define GLU_INVALID_ENUM 100900 +#define GLU_INVALID_VALUE 100901 +#define GLU_OUT_OF_MEMORY 100902 + +/* TessCallback */ +#define GLU_TESS_BEGIN 100100 +#define GLU_BEGIN 100100 +#define GLU_TESS_VERTEX 100101 +#define GLU_VERTEX 100101 +#define GLU_TESS_END 100102 +#define GLU_END 100102 +#define GLU_TESS_ERROR 100103 +#define GLU_TESS_EDGE_FLAG 100104 +#define GLU_EDGE_FLAG 100104 +#define GLU_TESS_COMBINE 100105 +#define GLU_TESS_BEGIN_DATA 100106 +#define GLU_TESS_VERTEX_DATA 100107 +#define GLU_TESS_END_DATA 100108 +#define GLU_TESS_ERROR_DATA 100109 +#define GLU_TESS_EDGE_FLAG_DATA 100110 +#define GLU_TESS_COMBINE_DATA 100111 + +/* TessContour */ +#define GLU_CW 100120 +#define GLU_CCW 100121 +#define GLU_INTERIOR 100122 +#define GLU_EXTERIOR 100123 +#define GLU_UNKNOWN 100124 + +/* TessProperty */ +#define GLU_TESS_WINDING_RULE 100140 +#define GLU_TESS_BOUNDARY_ONLY 100141 +#define GLU_TESS_TOLERANCE 100142 + +/* TessError */ +#define GLU_TESS_ERROR1 100151 +#define GLU_TESS_ERROR2 100152 +#define GLU_TESS_ERROR3 100153 +#define GLU_TESS_ERROR4 100154 +#define GLU_TESS_ERROR5 100155 +#define GLU_TESS_ERROR6 100156 +#define GLU_TESS_ERROR7 100157 +#define GLU_TESS_ERROR8 100158 +#define GLU_TESS_MISSING_BEGIN_POLYGON 100151 +#define GLU_TESS_MISSING_BEGIN_CONTOUR 100152 +#define GLU_TESS_MISSING_END_POLYGON 100153 +#define GLU_TESS_MISSING_END_CONTOUR 100154 +#define GLU_TESS_COORD_TOO_LARGE 100155 +#define GLU_TESS_NEED_COMBINE_CALLBACK 100156 + +/* TessWinding */ +#define GLU_TESS_WINDING_ODD 100130 +#define GLU_TESS_WINDING_NONZERO 100131 +#define GLU_TESS_WINDING_POSITIVE 100132 +#define GLU_TESS_WINDING_NEGATIVE 100133 +#define GLU_TESS_WINDING_ABS_GEQ_TWO 100134 + +#endif /* __TESSELATOR_H__ */ diff --git a/cogl/cogl-path/tesselator/tessmono.c b/cogl/cogl-path/tesselator/tessmono.c new file mode 100644 index 0000000..4d08440 --- /dev/null +++ b/cogl/cogl-path/tesselator/tessmono.c @@ -0,0 +1,201 @@ +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ +/* +** Author: Eric Veach, July 1994. +** +*/ + +#include "gluos.h" +#include +#include "geom.h" +#include "mesh.h" +#include "tessmono.h" +#include + +#define AddWinding(eDst,eSrc) (eDst->winding += eSrc->winding, \ + eDst->Sym->winding += eSrc->Sym->winding) + +/* __gl_meshTessellateMonoRegion( face ) tessellates a monotone region + * (what else would it do??) The region must consist of a single + * loop of half-edges (see mesh.h) oriented CCW. "Monotone" in this + * case means that any vertical line intersects the interior of the + * region in a single interval. + * + * Tessellation consists of adding interior edges (actually pairs of + * half-edges), to split the region into non-overlapping triangles. + * + * The basic idea is explained in Preparata and Shamos (which I don''t + * have handy right now), although their implementation is more + * complicated than this one. The are two edge chains, an upper chain + * and a lower chain. We process all vertices from both chains in order, + * from right to left. + * + * The algorithm ensures that the following invariant holds after each + * vertex is processed: the untessellated region consists of two + * chains, where one chain (say the upper) is a single edge, and + * the other chain is concave. The left vertex of the single edge + * is always to the left of all vertices in the concave chain. + * + * Each step consists of adding the rightmost unprocessed vertex to one + * of the two chains, and forming a fan of triangles from the rightmost + * of two chain endpoints. Determining whether we can add each triangle + * to the fan is a simple orientation test. By making the fan as large + * as possible, we restore the invariant (check it yourself). + */ +int __gl_meshTessellateMonoRegion( GLUface *face ) +{ + GLUhalfEdge *up, *lo; + + /* All edges are oriented CCW around the boundary of the region. + * First, find the half-edge whose origin vertex is rightmost. + * Since the sweep goes from left to right, face->anEdge should + * be close to the edge we want. + */ + up = face->anEdge; + assert( up->Lnext != up && up->Lnext->Lnext != up ); + + for( ; VertLeq( up->Dst, up->Org ); up = up->Lprev ) + ; + for( ; VertLeq( up->Org, up->Dst ); up = up->Lnext ) + ; + lo = up->Lprev; + + while( up->Lnext != lo ) { + if( VertLeq( up->Dst, lo->Org )) { + /* up->Dst is on the left. It is safe to form triangles from lo->Org. + * The EdgeGoesLeft test guarantees progress even when some triangles + * are CW, given that the upper and lower chains are truly monotone. + */ + while( lo->Lnext != up && (EdgeGoesLeft( lo->Lnext ) + || EdgeSign( lo->Org, lo->Dst, lo->Lnext->Dst ) <= 0 )) { + GLUhalfEdge *tempHalfEdge= __gl_meshConnect( lo->Lnext, lo ); + if (tempHalfEdge == NULL) return 0; + lo = tempHalfEdge->Sym; + } + lo = lo->Lprev; + } else { + /* lo->Org is on the left. We can make CCW triangles from up->Dst. */ + while( lo->Lnext != up && (EdgeGoesRight( up->Lprev ) + || EdgeSign( up->Dst, up->Org, up->Lprev->Org ) >= 0 )) { + GLUhalfEdge *tempHalfEdge= __gl_meshConnect( up, up->Lprev ); + if (tempHalfEdge == NULL) return 0; + up = tempHalfEdge->Sym; + } + up = up->Lnext; + } + } + + /* Now lo->Org == up->Dst == the leftmost vertex. The remaining region + * can be tessellated in a fan from this leftmost vertex. + */ + assert( lo->Lnext != up ); + while( lo->Lnext->Lnext != up ) { + GLUhalfEdge *tempHalfEdge= __gl_meshConnect( lo->Lnext, lo ); + if (tempHalfEdge == NULL) return 0; + lo = tempHalfEdge->Sym; + } + + return 1; +} + + +/* __gl_meshTessellateInterior( mesh ) tessellates each region of + * the mesh which is marked "inside" the polygon. Each such region + * must be monotone. + */ +int __gl_meshTessellateInterior( GLUmesh *mesh ) +{ + GLUface *f, *next; + + /*LINTED*/ + for( f = mesh->fHead.next; f != &mesh->fHead; f = next ) { + /* Make sure we don''t try to tessellate the new triangles. */ + next = f->next; + if( f->inside ) { + if ( !__gl_meshTessellateMonoRegion( f ) ) return 0; + } + } + + return 1; +} + + +/* __gl_meshDiscardExterior( mesh ) zaps (ie. sets to NULL) all faces + * which are not marked "inside" the polygon. Since further mesh operations + * on NULL faces are not allowed, the main purpose is to clean up the + * mesh so that exterior loops are not represented in the data structure. + */ +void __gl_meshDiscardExterior( GLUmesh *mesh ) +{ + GLUface *f, *next; + + /*LINTED*/ + for( f = mesh->fHead.next; f != &mesh->fHead; f = next ) { + /* Since f will be destroyed, save its next pointer. */ + next = f->next; + if( ! f->inside ) { + __gl_meshZapFace( f ); + } + } +} + +#define MARKED_FOR_DELETION 0x7fffffff + +/* __gl_meshSetWindingNumber( mesh, value, keepOnlyBoundary ) resets the + * winding numbers on all edges so that regions marked "inside" the + * polygon have a winding number of "value", and regions outside + * have a winding number of 0. + * + * If keepOnlyBoundary is TRUE, it also deletes all edges which do not + * separate an interior region from an exterior one. + */ +int __gl_meshSetWindingNumber( GLUmesh *mesh, int value, + GLboolean keepOnlyBoundary ) +{ + GLUhalfEdge *e, *eNext; + + for( e = mesh->eHead.next; e != &mesh->eHead; e = eNext ) { + eNext = e->next; + if( e->Rface->inside != e->Lface->inside ) { + + /* This is a boundary edge (one side is interior, one is exterior). */ + e->winding = (e->Lface->inside) ? value : -value; + } else { + + /* Both regions are interior, or both are exterior. */ + if( ! keepOnlyBoundary ) { + e->winding = 0; + } else { + if ( !__gl_meshDelete( e ) ) return 0; + } + } + } + return 1; +} diff --git a/cogl/cogl-path/tesselator/tessmono.h b/cogl/cogl-path/tesselator/tessmono.h new file mode 100644 index 0000000..8ee1b2f --- /dev/null +++ b/cogl/cogl-path/tesselator/tessmono.h @@ -0,0 +1,71 @@ +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ +/* +** Author: Eric Veach, July 1994. +** +*/ + +#ifndef __tessmono_h_ +#define __tessmono_h_ + +/* __gl_meshTessellateMonoRegion( face ) tessellates a monotone region + * (what else would it do??) The region must consist of a single + * loop of half-edges (see mesh.h) oriented CCW. "Monotone" in this + * case means that any vertical line intersects the interior of the + * region in a single interval. + * + * Tessellation consists of adding interior edges (actually pairs of + * half-edges), to split the region into non-overlapping triangles. + * + * __gl_meshTessellateInterior( mesh ) tessellates each region of + * the mesh which is marked "inside" the polygon. Each such region + * must be monotone. + * + * __gl_meshDiscardExterior( mesh ) zaps (ie. sets to NULL) all faces + * which are not marked "inside" the polygon. Since further mesh operations + * on NULL faces are not allowed, the main purpose is to clean up the + * mesh so that exterior loops are not represented in the data structure. + * + * __gl_meshSetWindingNumber( mesh, value, keepOnlyBoundary ) resets the + * winding numbers on all edges so that regions marked "inside" the + * polygon have a winding number of "value", and regions outside + * have a winding number of 0. + * + * If keepOnlyBoundary is TRUE, it also deletes all edges which do not + * separate an interior region from an exterior one. + */ + +int __gl_meshTessellateMonoRegion( GLUface *face ); +int __gl_meshTessellateInterior( GLUmesh *mesh ); +void __gl_meshDiscardExterior( GLUmesh *mesh ); +int __gl_meshSetWindingNumber( GLUmesh *mesh, int value, + GLboolean keepOnlyBoundary ); + +#endif diff --git a/cogl/cogl/Makefile.am b/cogl/cogl/Makefile.am new file mode 100644 index 0000000..fef656a --- /dev/null +++ b/cogl/cogl/Makefile.am @@ -0,0 +1,510 @@ +# preamble + +NULL = + +SUBDIRS = + +BUILT_SOURCES = + +EXTRA_DIST = +CLEANFILES = +DISTCLEANFILES = + +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + -I$(srcdir)/deprecated \ + -I$(srcdir)/winsys \ + -I$(srcdir)/driver/gl \ + -I$(srcdir)/driver/gl/gl \ + -I$(srcdir)/driver/gl/gles \ + $(NULL) + +AM_CPPFLAGS += \ + -DG_LOG_DOMAIN=\"Cogl\" \ + -DCOGL_COMPILATION \ + -DCOGL_GL_LIBNAME=\"$(COGL_GL_LIBNAME)\" \ + -DCOGL_GLES1_LIBNAME=\"$(COGL_GLES1_LIBNAME)\" \ + -DCOGL_GLES2_LIBNAME=\"$(COGL_GLES2_LIBNAME)\" \ + -DCOGL_LOCALEDIR=\""$(localedir)"\" \ + $(NULL) + +if HAVE_COGL_DEFAULT_DRIVER +AM_CPPFLAGS += \ + -DCOGL_DEFAULT_DRIVER=\"$(COGL_DEFAULT_DRIVER)\" +endif + + +AM_CFLAGS = $(COGL_DEP_CFLAGS) $(COGL_EXTRA_CFLAGS) $(MAINTAINER_CFLAGS) + +BUILT_SOURCES += cogl-defines.h cogl-egl-defines.h cogl-gl-header.h +DISTCLEANFILES += cogl-defines.h cogl-egl-defines.h cogl-gl-header.h +EXTRA_DIST += cogl-defines.h.in cogl-egl-defines.h.in cogl-gl-header.h.in + +pc_files = mutter-cogl-1.0.pc + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = $(pc_files) + +DISTCLEANFILES += $(pc_files) + +cogl_deprecated_h = \ + deprecated/cogl-material-compat.h \ + deprecated/cogl-vertex-buffer.h \ + deprecated/cogl-shader.h \ + deprecated/cogl-clutter.h \ + deprecated/cogl-type-casts.h \ + deprecated/cogl-auto-texture.h \ + $(NULL) + +cogl_deprecated_nonintrospected_h = \ + deprecated/cogl-framebuffer-deprecated.h \ + $(NULL) + +# public 1.x api headers +cogl_1_public_h = \ + $(cogl_deprecated_h) \ + cogl1-context.h \ + cogl-bitmap.h \ + cogl-color.h \ + cogl-matrix.h \ + cogl-offscreen.h \ + cogl-primitives.h \ + cogl-texture.h \ + cogl-types.h \ + cogl.h \ + $(NULL) + +cogl_nonintrospected_h = \ + cogl-object.h \ + cogl-renderer.h \ + cogl-swap-chain.h \ + cogl-onscreen-template.h \ + cogl-display.h \ + cogl-context.h \ + cogl-pipeline.h \ + cogl-pipeline-state.h \ + cogl-pipeline-layer-state.h \ + cogl-snippet.h \ + cogl-gles2.h \ + cogl-gles2-types.h \ + cogl-index-buffer.h \ + cogl-attribute-buffer.h \ + cogl-indices.h \ + cogl-attribute.h \ + cogl-primitive.h \ + cogl-framebuffer.h \ + cogl-onscreen.h \ + cogl-frame-info.h \ + cogl-vector.h \ + cogl-euler.h \ + cogl-output.h \ + cogl-quaternion.h \ + cogl-matrix-stack.h \ + cogl-poll.h \ + cogl-texture-3d.h \ + cogl-texture-2d.h \ + cogl-texture-2d-gl.h \ + cogl-texture-rectangle.h \ + cogl-texture-2d-sliced.h \ + cogl-sub-texture.h \ + cogl-atlas-texture.h \ + cogl-meta-texture.h \ + cogl-primitive-texture.h \ + cogl-depth-state.h \ + cogl-buffer.h \ + cogl-pixel-buffer.h \ + cogl-macros.h \ + cogl-fence.h \ + cogl-version.h \ + cogl-error.h \ + cogl-bitmap.h \ + cogl-color.h \ + cogl-matrix.h \ + cogl-texture.h \ + cogl-types.h \ + cogl-gtype-private.h \ + cogl-mutter.h \ + $(NULL) + +cogl_nodist_h = \ + $(NULL) + +# nop driver +cogl_driver_sources = \ + driver/nop/cogl-driver-nop.c \ + driver/nop/cogl-framebuffer-nop-private.h \ + driver/nop/cogl-framebuffer-nop.c \ + driver/nop/cogl-attribute-nop-private.h \ + driver/nop/cogl-attribute-nop.c \ + driver/nop/cogl-clip-stack-nop-private.h \ + driver/nop/cogl-clip-stack-nop.c \ + driver/nop/cogl-texture-2d-nop-private.h \ + driver/nop/cogl-texture-2d-nop.c \ + $(NULL) + +# gl driver sources +cogl_gl_prototypes_h = \ + gl-prototypes/cogl-gles2-functions.h \ + gl-prototypes/cogl-core-functions.h \ + gl-prototypes/cogl-in-gles-core-functions.h \ + gl-prototypes/cogl-in-gles2-core-functions.h \ + gl-prototypes/cogl-glsl-functions.h \ + $(NULL) + +cogl_driver_sources += \ + driver/gl/cogl-util-gl-private.h \ + driver/gl/cogl-util-gl.c \ + driver/gl/cogl-framebuffer-gl-private.h \ + driver/gl/cogl-framebuffer-gl.c \ + driver/gl/cogl-texture-gl-private.h \ + driver/gl/cogl-texture-gl.c \ + driver/gl/cogl-texture-2d-gl-private.h \ + driver/gl/cogl-texture-2d-gl.c \ + driver/gl/cogl-attribute-gl-private.h \ + driver/gl/cogl-attribute-gl.c \ + driver/gl/cogl-clip-stack-gl-private.h \ + driver/gl/cogl-clip-stack-gl.c \ + driver/gl/cogl-buffer-gl-private.h \ + driver/gl/cogl-buffer-gl.c \ + driver/gl/cogl-pipeline-opengl.c \ + driver/gl/cogl-pipeline-opengl-private.h \ + driver/gl/cogl-pipeline-fragend-glsl.c \ + driver/gl/cogl-pipeline-fragend-glsl-private.h \ + driver/gl/gl/cogl-pipeline-fragend-arbfp.c \ + driver/gl/gl/cogl-pipeline-fragend-arbfp-private.h \ + driver/gl/gl/cogl-pipeline-progend-fixed-arbfp.c \ + driver/gl/gl/cogl-pipeline-progend-fixed-arbfp-private.h \ + driver/gl/cogl-pipeline-fragend-fixed.c \ + driver/gl/cogl-pipeline-fragend-fixed-private.h \ + driver/gl/cogl-pipeline-vertend-glsl.c \ + driver/gl/cogl-pipeline-vertend-glsl-private.h \ + driver/gl/cogl-pipeline-vertend-fixed.c \ + driver/gl/cogl-pipeline-vertend-fixed-private.h \ + driver/gl/cogl-pipeline-progend-fixed.c \ + driver/gl/cogl-pipeline-progend-fixed-private.h \ + driver/gl/cogl-pipeline-progend-glsl.c \ + driver/gl/cogl-pipeline-progend-glsl-private.h \ + $(NULL) + +if COGL_DRIVER_GL_SUPPORTED +cogl_driver_sources += \ + driver/gl/gl/cogl-driver-gl.c \ + driver/gl/gl/cogl-texture-driver-gl.c \ + $(NULL) +endif + +if COGL_DRIVER_GLES_SUPPORTED +cogl_driver_sources += \ + driver/gl/gles/cogl-driver-gles.c \ + driver/gl/gles/cogl-texture-driver-gles.c \ + $(NULL) +endif + +# winsys sources, common to all backends +cogl_winsys_common_sources = \ + winsys/cogl-winsys-private.h \ + winsys/cogl-winsys.c \ + $(NULL) + +# sources +cogl_sources_c = \ + $(cogl_driver_sources) \ + $(cogl_winsys_common_sources) \ + cogl-private.h \ + cogl-i18n-private.h \ + cogl-debug.h \ + cogl-debug-options.h \ + cogl-gpu-info.c \ + cogl-gpu-info-private.h \ + cogl-context-private.h \ + cogl-context.c \ + cogl-renderer-private.h \ + cogl-renderer.h \ + cogl-renderer.c \ + cogl-swap-chain-private.h \ + cogl-swap-chain.h \ + cogl-swap-chain.c \ + cogl-onscreen-template-private.h \ + cogl-onscreen-template.h \ + cogl-onscreen-template.c \ + cogl-display-private.h \ + cogl-display.h \ + cogl-display.c \ + cogl-driver.h \ + cogl.c \ + cogl-object-private.h \ + cogl-object.h \ + cogl-object.c \ + cogl-util.h \ + cogl-util.c \ + cogl-bitmap-private.h \ + cogl-bitmap.c \ + cogl-bitmap-conversion.c \ + cogl-bitmap-packing.h \ + cogl-primitives-private.h \ + cogl-primitives.h \ + cogl-primitives.c \ + cogl-bitmap-pixbuf.c \ + cogl-clip-stack.h \ + cogl-clip-stack.c \ + cogl-feature-private.h \ + cogl-feature-private.c \ + cogl-color-private.h \ + cogl-color.c \ + cogl-buffer-private.h \ + cogl-buffer.c \ + cogl-pixel-buffer-private.h \ + cogl-pixel-buffer.c \ + cogl-index-buffer-private.h \ + cogl-index-buffer.c \ + cogl-attribute-buffer-private.h \ + cogl-attribute-buffer.c \ + cogl-indices-private.h \ + cogl-indices.c \ + cogl-attribute-private.h \ + cogl-attribute.c \ + cogl-primitive-private.h \ + cogl-primitive.c \ + cogl-matrix.c \ + cogl-vector.c \ + cogl-euler.c \ + cogl-quaternion-private.h \ + cogl-quaternion.c \ + cogl-matrix-private.h \ + cogl-matrix-stack.c \ + cogl-matrix-stack-private.h \ + cogl-depth-state.c \ + cogl-depth-state-private.h \ + cogl-node.c \ + cogl-node-private.h \ + cogl-pipeline.c \ + cogl-pipeline-private.h \ + cogl-pipeline-layer.c \ + cogl-pipeline-layer-private.h \ + cogl-pipeline-state.c \ + cogl-pipeline-layer-state-private.h \ + cogl-pipeline-layer-state.c \ + cogl-pipeline-state-private.h \ + cogl-pipeline-debug.c \ + cogl-glsl-shader.c \ + cogl-glsl-shader-private.h \ + cogl-glsl-shader-boilerplate.h \ + cogl-pipeline-snippet-private.h \ + cogl-pipeline-snippet.c \ + cogl-pipeline-cache.h \ + cogl-pipeline-cache.c \ + cogl-pipeline-hash-table.h \ + cogl-pipeline-hash-table.c \ + cogl-sampler-cache.c \ + cogl-sampler-cache-private.h \ + cogl-blend-string.c \ + cogl-blend-string.h \ + cogl-debug.c \ + cogl-sub-texture-private.h \ + cogl-texture-private.h \ + cogl-texture-2d-private.h \ + cogl-texture-2d-sliced-private.h \ + cogl-texture-3d-private.h \ + cogl-texture-driver.h \ + cogl-sub-texture.c \ + cogl-texture.c \ + cogl-texture-2d.c \ + cogl-texture-2d-sliced.c \ + cogl-texture-3d.c \ + cogl-texture-rectangle-private.h \ + cogl-texture-rectangle.c \ + cogl-rectangle-map.h \ + cogl-rectangle-map.c \ + cogl-atlas.h \ + cogl-atlas.c \ + cogl-atlas-texture-private.h \ + cogl-atlas-texture.c \ + cogl-meta-texture.c \ + cogl-primitive-texture.c \ + cogl-blit.h \ + cogl-blit.c \ + cogl-spans.h \ + cogl-spans.c \ + cogl-journal-private.h \ + cogl-journal.c \ + cogl-frame-info-private.h \ + cogl-frame-info.c \ + cogl-framebuffer-private.h \ + cogl-framebuffer.c \ + cogl-onscreen-private.h \ + cogl-onscreen.c \ + cogl-output-private.h \ + cogl-output.c \ + cogl-profile.h \ + cogl-profile.c \ + cogl-flags.h \ + cogl-bitmask.h \ + cogl-bitmask.c \ + cogl-gtype.c \ + cogl-gtype-private.h \ + cogl-point-in-poly-private.h \ + cogl-point-in-poly.c \ + cogl-list.c \ + cogl-list.h \ + winsys/cogl-winsys-stub-private.h \ + winsys/cogl-winsys-stub.c \ + cogl-config-private.h \ + cogl-config.c \ + cogl-boxed-value.h \ + cogl-boxed-value.c \ + cogl-snippet-private.h \ + cogl-snippet.c \ + cogl-poll-private.h \ + cogl-poll.c \ + gl-prototypes/cogl-all-functions.h \ + gl-prototypes/cogl-gles1-functions.h \ + gl-prototypes/cogl-gles2-functions.h \ + gl-prototypes/cogl-core-functions.h \ + gl-prototypes/cogl-in-gles-core-functions.h \ + gl-prototypes/cogl-in-gles1-core-functions.h \ + gl-prototypes/cogl-in-gles2-core-functions.h \ + gl-prototypes/cogl-fixed-functions.h \ + gl-prototypes/cogl-glsl-functions.h \ + cogl-memory-stack-private.h \ + cogl-memory-stack.c \ + cogl-magazine-private.h \ + cogl-magazine.c \ + cogl-gles2-context-private.h \ + cogl-gles2-context.c \ + cogl-error-private.h \ + cogl-error.c \ + cogl-closure-list-private.h \ + cogl-closure-list.c \ + cogl-fence.c \ + cogl-fence-private.h \ + deprecated/cogl-vertex-buffer-private.h \ + deprecated/cogl-vertex-buffer.c \ + deprecated/cogl-material-compat.c \ + deprecated/cogl-program.c \ + deprecated/cogl-program-private.h \ + deprecated/cogl-auto-texture.c \ + deprecated/cogl-shader-private.h \ + deprecated/cogl-shader.c \ + deprecated/cogl-clutter.c \ + deprecated/cogl-framebuffer-deprecated.c \ + $(NULL) + +cogl_nonintrospected_h += cogl-glib-source.h +cogl_sources_c += cogl-glib-source.c + +if SUPPORT_XLIB +cogl_deprecated_nonintrospected_h += deprecated/cogl-clutter-xlib.h +cogl_1_public_h += cogl-xlib-renderer.h + +cogl_nonintrospected_h += \ + winsys/cogl-texture-pixmap-x11.h \ + cogl-xlib.h + +cogl_sources_c += \ + cogl-x11-renderer-private.h \ + cogl-xlib-renderer-private.h \ + cogl-xlib-renderer.c \ + cogl-xlib.c \ + cogl-xlib-private.h \ + winsys/cogl-texture-pixmap-x11.c \ + winsys/cogl-texture-pixmap-x11-private.h +endif +if SUPPORT_GLX +cogl_nonintrospected_h += cogl-glx.h +cogl_sources_c += \ + cogl-glx-renderer-private.h \ + cogl-glx-display-private.h \ + winsys/cogl-winsys-glx-feature-functions.h \ + winsys/cogl-winsys-glx-private.h \ + winsys/cogl-winsys-glx.c +endif +if SUPPORT_WAYLAND_EGL_SERVER +cogl_nonintrospected_h += cogl-wayland-server.h +endif +if SUPPORT_EGL_PLATFORM_XLIB +cogl_sources_c += \ + winsys/cogl-winsys-egl-x11.c \ + winsys/cogl-winsys-egl-x11-private.h +endif +if SUPPORT_EGL +cogl_nonintrospected_h += cogl-egl.h +cogl_nodist_h += cogl-egl-defines.h + +cogl_sources_c += \ + cogl-egl-private.h \ + winsys/cogl-winsys-egl.c \ + winsys/cogl-winsys-egl-feature-functions.h \ + winsys/cogl-winsys-egl-private.h +endif + +mutterlibdir = $(libdir)/mutter +mutterlib_LTLIBRARIES = libmutter-cogl.la + +libmutter_cogl_la_LIBADD = $(LIBM) $(COGL_DEP_LIBS) $(COGL_EXTRA_LDFLAGS) +if UNIT_TESTS +libmutter_cogl_la_LIBADD += $(top_builddir)/test-fixtures/libtest-fixtures.la +endif +# XXX: The aim is to eventually get rid of all private API exports +# for cogl-pango. +libmutter_cogl_la_LDFLAGS = \ + -no-undefined \ + -avoid-version \ + -export-dynamic \ + -rpath $(mutterlibdir) \ + -export-symbols-regex "^(cogl|_cogl_debug_flags|_cogl_atlas_new|_cogl_atlas_add_reorganize_callback|_cogl_atlas_reserve_space|_cogl_callback|_cogl_util_get_eye_planes_for_screen_poly|_cogl_atlas_texture_remove_reorganize_callback|_cogl_atlas_texture_add_reorganize_callback|_cogl_texture_get_format|_cogl_texture_foreach_sub_texture_in_region|_cogl_profile_trace_message|_cogl_context_get_default|_cogl_framebuffer_get_stencil_bits|_cogl_clip_stack_push_rectangle|_cogl_framebuffer_get_modelview_stack|_cogl_object_default_unref|_cogl_pipeline_foreach_layer_internal|_cogl_clip_stack_push_primitive|_cogl_buffer_unmap_for_fill_or_fallback|_cogl_framebuffer_draw_primitive|_cogl_debug_instances|_cogl_framebuffer_get_projection_stack|_cogl_pipeline_layer_get_texture|_cogl_buffer_map_for_fill_or_fallback|_cogl_texture_can_hardware_repeat|_cogl_pipeline_prune_to_n_layers|_cogl_primitive_draw|test_|unit_test_|_cogl_winsys_glx_get_vtable|_cogl_winsys_egl_xlib_get_vtable|_cogl_winsys_egl_get_vtable|_cogl_closure_disconnect|_cogl_onscreen_notify_complete|_cogl_onscreen_notify_frame_sync|_cogl_winsys_egl_renderer_connect_common|_cogl_winsys_error_quark|_cogl_set_error|_cogl_poll_renderer_add_fd|_cogl_poll_renderer_add_idle|_cogl_framebuffer_winsys_update_size|_cogl_winsys_egl_make_current).*" + +libmutter_cogl_la_SOURCES = $(cogl_sources_c) +nodist_libmutter_cogl_la_SOURCES = $(BUILT_SOURCES) + +# Cogl installed headers +cogl_headers = \ + $(cogl_1_public_h) \ + cogl-deprecated.h \ + cogl-pango.h \ + $(NULL) + +cogl_base_includedir = $(includedir)/mutter +cogldeprecatedincludedir = $(cogl_base_includedir)/cogl/cogl/deprecated +cogldeprecatedinclude_HEADERS = $(cogl_deprecated_h) $(cogl_deprecated_nonintrospected_h) + +coglincludedir = $(cogl_base_includedir)/cogl/cogl +coglinclude_HEADERS = $(cogl_headers) $(cogl_nonintrospected_h) +nodist_coglinclude_HEADERS = $(cogl_nodist_h) cogl-defines.h + +cogl_proto_includedir = $(cogl_base_includedir)/cogl/cogl/gl-prototypes +cogl_proto_include_HEADERS = $(cogl_gl_prototypes_h) + +EXTRA_DIST += \ + cogl.symbols + +-include $(INTROSPECTION_MAKEFILE) + +INTROSPECTION_GIRS = + +if HAVE_INTROSPECTION +Cogl-1.0.gir: libmutter-cogl.la Makefile + +Cogl_1_0_gir_NAMESPACE = Cogl +Cogl_1_0_gir_VERSION = 1.0 +Cogl_1_0_gir_LIBS = libmutter-cogl.la +if UNIT_TESTS +Cogl_1_0_gir_LIBS += $(top_builddir)/test-fixtures/libtest-fixtures.la +endif +Cogl_1_0_gir_FILES = $(cogl_1_public_h) + +Cogl_1_0_gir_CFLAGS = $(AM_CPPFLAGS) $(COGL_DEP_CFLAGS) -UCOGL_COMPILATION -D__COGL_H_INSIDE__ -D__COGL_XLIB_H_INSIDE__ -D__COGL_EGL_H_INSIDE__ -D__COGL_GLX_H_INSIDE__ -DCOGL_GIR_SCANNING +Cogl_1_0_gir_INCLUDES = GL-1.0 GObject-2.0 +Cogl_1_0_gir_EXPORT_PACKAGES = mutter-cogl-1.0 +Cogl_1_0_gir_SCANNERFLAGS = --warn-all --c-include='cogl/cogl.h' + +INTROSPECTION_GIRS += Cogl-1.0.gir + +girdir = $(mutterlibdir) +gir_DATA = $(INTROSPECTION_GIRS) + +typelibdir = $(mutterlibdir) +typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib) + +CLEANFILES += $(gir_DATA) $(typelib_DATA) +endif diff --git a/cogl/cogl/Makefile.in b/cogl/cogl/Makefile.in new file mode 100644 index 0000000..c6f1043 --- /dev/null +++ b/cogl/cogl/Makefile.in @@ -0,0 +1,1837 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# preamble + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@HAVE_COGL_DEFAULT_DRIVER_TRUE@am__append_1 = \ +@HAVE_COGL_DEFAULT_DRIVER_TRUE@ -DCOGL_DEFAULT_DRIVER=\"$(COGL_DEFAULT_DRIVER)\" + +@COGL_DRIVER_GL_SUPPORTED_TRUE@am__append_2 = \ +@COGL_DRIVER_GL_SUPPORTED_TRUE@ driver/gl/gl/cogl-driver-gl.c \ +@COGL_DRIVER_GL_SUPPORTED_TRUE@ driver/gl/gl/cogl-texture-driver-gl.c \ +@COGL_DRIVER_GL_SUPPORTED_TRUE@ $(NULL) + +@COGL_DRIVER_GLES_SUPPORTED_TRUE@am__append_3 = \ +@COGL_DRIVER_GLES_SUPPORTED_TRUE@ driver/gl/gles/cogl-driver-gles.c \ +@COGL_DRIVER_GLES_SUPPORTED_TRUE@ driver/gl/gles/cogl-texture-driver-gles.c \ +@COGL_DRIVER_GLES_SUPPORTED_TRUE@ $(NULL) + +@SUPPORT_XLIB_TRUE@am__append_4 = deprecated/cogl-clutter-xlib.h +@SUPPORT_XLIB_TRUE@am__append_5 = cogl-xlib-renderer.h +@SUPPORT_XLIB_TRUE@am__append_6 = \ +@SUPPORT_XLIB_TRUE@ winsys/cogl-texture-pixmap-x11.h \ +@SUPPORT_XLIB_TRUE@ cogl-xlib.h + +@SUPPORT_XLIB_TRUE@am__append_7 = \ +@SUPPORT_XLIB_TRUE@ cogl-x11-renderer-private.h \ +@SUPPORT_XLIB_TRUE@ cogl-xlib-renderer-private.h \ +@SUPPORT_XLIB_TRUE@ cogl-xlib-renderer.c \ +@SUPPORT_XLIB_TRUE@ cogl-xlib.c \ +@SUPPORT_XLIB_TRUE@ cogl-xlib-private.h \ +@SUPPORT_XLIB_TRUE@ winsys/cogl-texture-pixmap-x11.c \ +@SUPPORT_XLIB_TRUE@ winsys/cogl-texture-pixmap-x11-private.h + +@SUPPORT_GLX_TRUE@am__append_8 = cogl-glx.h +@SUPPORT_GLX_TRUE@am__append_9 = \ +@SUPPORT_GLX_TRUE@ cogl-glx-renderer-private.h \ +@SUPPORT_GLX_TRUE@ cogl-glx-display-private.h \ +@SUPPORT_GLX_TRUE@ winsys/cogl-winsys-glx-feature-functions.h \ +@SUPPORT_GLX_TRUE@ winsys/cogl-winsys-glx-private.h \ +@SUPPORT_GLX_TRUE@ winsys/cogl-winsys-glx.c + +@SUPPORT_WAYLAND_EGL_SERVER_TRUE@am__append_10 = cogl-wayland-server.h +@SUPPORT_EGL_PLATFORM_XLIB_TRUE@am__append_11 = \ +@SUPPORT_EGL_PLATFORM_XLIB_TRUE@ winsys/cogl-winsys-egl-x11.c \ +@SUPPORT_EGL_PLATFORM_XLIB_TRUE@ winsys/cogl-winsys-egl-x11-private.h + +@SUPPORT_EGL_TRUE@am__append_12 = cogl-egl.h +@SUPPORT_EGL_TRUE@am__append_13 = cogl-egl-defines.h +@SUPPORT_EGL_TRUE@am__append_14 = \ +@SUPPORT_EGL_TRUE@ cogl-egl-private.h \ +@SUPPORT_EGL_TRUE@ winsys/cogl-winsys-egl.c \ +@SUPPORT_EGL_TRUE@ winsys/cogl-winsys-egl-feature-functions.h \ +@SUPPORT_EGL_TRUE@ winsys/cogl-winsys-egl-private.h + +@UNIT_TESTS_TRUE@am__append_15 = $(top_builddir)/test-fixtures/libtest-fixtures.la +@HAVE_INTROSPECTION_TRUE@@UNIT_TESTS_TRUE@am__append_16 = $(top_builddir)/test-fixtures/libtest-fixtures.la +@HAVE_INTROSPECTION_TRUE@am__append_17 = Cogl-1.0.gir +@HAVE_INTROSPECTION_TRUE@am__append_18 = $(gir_DATA) $(typelib_DATA) +subdir = cogl +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/build/autotools/as-compiler-flag.m4 \ + $(top_srcdir)/build/autotools/introspection.m4 \ + $(top_srcdir)/build/autotools/libtool.m4 \ + $(top_srcdir)/build/autotools/ltoptions.m4 \ + $(top_srcdir)/build/autotools/ltsugar.m4 \ + $(top_srcdir)/build/autotools/ltversion.m4 \ + $(top_srcdir)/build/autotools/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(cogl_proto_include_HEADERS) \ + $(am__cogldeprecatedinclude_HEADERS_DIST) \ + $(am__coglinclude_HEADERS_DIST) $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/cogl-config.h \ + $(top_builddir)/cogl-mutter-config.h +CONFIG_CLEAN_FILES = mutter-cogl-1.0.pc cogl-defines.h \ + cogl-gl-header.h cogl-egl-defines.h +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(mutterlibdir)" "$(DESTDIR)$(girdir)" \ + "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(typelibdir)" \ + "$(DESTDIR)$(cogl_proto_includedir)" \ + "$(DESTDIR)$(cogldeprecatedincludedir)" \ + "$(DESTDIR)$(coglincludedir)" "$(DESTDIR)$(coglincludedir)" +LTLIBRARIES = $(mutterlib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libmutter_cogl_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) $(am__append_15) +am__libmutter_cogl_la_SOURCES_DIST = driver/nop/cogl-driver-nop.c \ + driver/nop/cogl-framebuffer-nop-private.h \ + driver/nop/cogl-framebuffer-nop.c \ + driver/nop/cogl-attribute-nop-private.h \ + driver/nop/cogl-attribute-nop.c \ + driver/nop/cogl-clip-stack-nop-private.h \ + driver/nop/cogl-clip-stack-nop.c \ + driver/nop/cogl-texture-2d-nop-private.h \ + driver/nop/cogl-texture-2d-nop.c \ + driver/gl/cogl-util-gl-private.h driver/gl/cogl-util-gl.c \ + driver/gl/cogl-framebuffer-gl-private.h \ + driver/gl/cogl-framebuffer-gl.c \ + driver/gl/cogl-texture-gl-private.h \ + driver/gl/cogl-texture-gl.c \ + driver/gl/cogl-texture-2d-gl-private.h \ + driver/gl/cogl-texture-2d-gl.c \ + driver/gl/cogl-attribute-gl-private.h \ + driver/gl/cogl-attribute-gl.c \ + driver/gl/cogl-clip-stack-gl-private.h \ + driver/gl/cogl-clip-stack-gl.c \ + driver/gl/cogl-buffer-gl-private.h driver/gl/cogl-buffer-gl.c \ + driver/gl/cogl-pipeline-opengl.c \ + driver/gl/cogl-pipeline-opengl-private.h \ + driver/gl/cogl-pipeline-fragend-glsl.c \ + driver/gl/cogl-pipeline-fragend-glsl-private.h \ + driver/gl/gl/cogl-pipeline-fragend-arbfp.c \ + driver/gl/gl/cogl-pipeline-fragend-arbfp-private.h \ + driver/gl/gl/cogl-pipeline-progend-fixed-arbfp.c \ + driver/gl/gl/cogl-pipeline-progend-fixed-arbfp-private.h \ + driver/gl/cogl-pipeline-fragend-fixed.c \ + driver/gl/cogl-pipeline-fragend-fixed-private.h \ + driver/gl/cogl-pipeline-vertend-glsl.c \ + driver/gl/cogl-pipeline-vertend-glsl-private.h \ + driver/gl/cogl-pipeline-vertend-fixed.c \ + driver/gl/cogl-pipeline-vertend-fixed-private.h \ + driver/gl/cogl-pipeline-progend-fixed.c \ + driver/gl/cogl-pipeline-progend-fixed-private.h \ + driver/gl/cogl-pipeline-progend-glsl.c \ + driver/gl/cogl-pipeline-progend-glsl-private.h \ + driver/gl/gl/cogl-driver-gl.c \ + driver/gl/gl/cogl-texture-driver-gl.c \ + driver/gl/gles/cogl-driver-gles.c \ + driver/gl/gles/cogl-texture-driver-gles.c \ + winsys/cogl-winsys-private.h winsys/cogl-winsys.c \ + cogl-private.h cogl-i18n-private.h cogl-debug.h \ + cogl-debug-options.h cogl-gpu-info.c cogl-gpu-info-private.h \ + cogl-context-private.h cogl-context.c cogl-renderer-private.h \ + cogl-renderer.h cogl-renderer.c cogl-swap-chain-private.h \ + cogl-swap-chain.h cogl-swap-chain.c \ + cogl-onscreen-template-private.h cogl-onscreen-template.h \ + cogl-onscreen-template.c cogl-display-private.h cogl-display.h \ + cogl-display.c cogl-driver.h cogl.c cogl-object-private.h \ + cogl-object.h cogl-object.c cogl-util.h cogl-util.c \ + cogl-bitmap-private.h cogl-bitmap.c cogl-bitmap-conversion.c \ + cogl-bitmap-packing.h cogl-primitives-private.h \ + cogl-primitives.h cogl-primitives.c cogl-bitmap-pixbuf.c \ + cogl-clip-stack.h cogl-clip-stack.c cogl-feature-private.h \ + cogl-feature-private.c cogl-color-private.h cogl-color.c \ + cogl-buffer-private.h cogl-buffer.c \ + cogl-pixel-buffer-private.h cogl-pixel-buffer.c \ + cogl-index-buffer-private.h cogl-index-buffer.c \ + cogl-attribute-buffer-private.h cogl-attribute-buffer.c \ + cogl-indices-private.h cogl-indices.c cogl-attribute-private.h \ + cogl-attribute.c cogl-primitive-private.h cogl-primitive.c \ + cogl-matrix.c cogl-vector.c cogl-euler.c \ + cogl-quaternion-private.h cogl-quaternion.c \ + cogl-matrix-private.h cogl-matrix-stack.c \ + cogl-matrix-stack-private.h cogl-depth-state.c \ + cogl-depth-state-private.h cogl-node.c cogl-node-private.h \ + cogl-pipeline.c cogl-pipeline-private.h cogl-pipeline-layer.c \ + cogl-pipeline-layer-private.h cogl-pipeline-state.c \ + cogl-pipeline-layer-state-private.h \ + cogl-pipeline-layer-state.c cogl-pipeline-state-private.h \ + cogl-pipeline-debug.c cogl-glsl-shader.c \ + cogl-glsl-shader-private.h cogl-glsl-shader-boilerplate.h \ + cogl-pipeline-snippet-private.h cogl-pipeline-snippet.c \ + cogl-pipeline-cache.h cogl-pipeline-cache.c \ + cogl-pipeline-hash-table.h cogl-pipeline-hash-table.c \ + cogl-sampler-cache.c cogl-sampler-cache-private.h \ + cogl-blend-string.c cogl-blend-string.h cogl-debug.c \ + cogl-sub-texture-private.h cogl-texture-private.h \ + cogl-texture-2d-private.h cogl-texture-2d-sliced-private.h \ + cogl-texture-3d-private.h cogl-texture-driver.h \ + cogl-sub-texture.c cogl-texture.c cogl-texture-2d.c \ + cogl-texture-2d-sliced.c cogl-texture-3d.c \ + cogl-texture-rectangle-private.h cogl-texture-rectangle.c \ + cogl-rectangle-map.h cogl-rectangle-map.c cogl-atlas.h \ + cogl-atlas.c cogl-atlas-texture-private.h cogl-atlas-texture.c \ + cogl-meta-texture.c cogl-primitive-texture.c cogl-blit.h \ + cogl-blit.c cogl-spans.h cogl-spans.c cogl-journal-private.h \ + cogl-journal.c cogl-frame-info-private.h cogl-frame-info.c \ + cogl-framebuffer-private.h cogl-framebuffer.c \ + cogl-onscreen-private.h cogl-onscreen.c cogl-output-private.h \ + cogl-output.c cogl-profile.h cogl-profile.c cogl-flags.h \ + cogl-bitmask.h cogl-bitmask.c cogl-gtype.c \ + cogl-gtype-private.h cogl-point-in-poly-private.h \ + cogl-point-in-poly.c cogl-list.c cogl-list.h \ + winsys/cogl-winsys-stub-private.h winsys/cogl-winsys-stub.c \ + cogl-config-private.h cogl-config.c cogl-boxed-value.h \ + cogl-boxed-value.c cogl-snippet-private.h cogl-snippet.c \ + cogl-poll-private.h cogl-poll.c \ + gl-prototypes/cogl-all-functions.h \ + gl-prototypes/cogl-gles1-functions.h \ + gl-prototypes/cogl-gles2-functions.h \ + gl-prototypes/cogl-core-functions.h \ + gl-prototypes/cogl-in-gles-core-functions.h \ + gl-prototypes/cogl-in-gles1-core-functions.h \ + gl-prototypes/cogl-in-gles2-core-functions.h \ + gl-prototypes/cogl-fixed-functions.h \ + gl-prototypes/cogl-glsl-functions.h \ + cogl-memory-stack-private.h cogl-memory-stack.c \ + cogl-magazine-private.h cogl-magazine.c \ + cogl-gles2-context-private.h cogl-gles2-context.c \ + cogl-error-private.h cogl-error.c cogl-closure-list-private.h \ + cogl-closure-list.c cogl-fence.c cogl-fence-private.h \ + deprecated/cogl-vertex-buffer-private.h \ + deprecated/cogl-vertex-buffer.c \ + deprecated/cogl-material-compat.c deprecated/cogl-program.c \ + deprecated/cogl-program-private.h \ + deprecated/cogl-auto-texture.c \ + deprecated/cogl-shader-private.h deprecated/cogl-shader.c \ + deprecated/cogl-clutter.c \ + deprecated/cogl-framebuffer-deprecated.c cogl-glib-source.c \ + cogl-x11-renderer-private.h cogl-xlib-renderer-private.h \ + cogl-xlib-renderer.c cogl-xlib.c cogl-xlib-private.h \ + winsys/cogl-texture-pixmap-x11.c \ + winsys/cogl-texture-pixmap-x11-private.h \ + cogl-glx-renderer-private.h cogl-glx-display-private.h \ + winsys/cogl-winsys-glx-feature-functions.h \ + winsys/cogl-winsys-glx-private.h winsys/cogl-winsys-glx.c \ + winsys/cogl-winsys-egl-x11.c \ + winsys/cogl-winsys-egl-x11-private.h cogl-egl-private.h \ + winsys/cogl-winsys-egl.c \ + winsys/cogl-winsys-egl-feature-functions.h \ + winsys/cogl-winsys-egl-private.h +am__dirstamp = $(am__leading_dot)dirstamp +am__objects_1 = +@COGL_DRIVER_GL_SUPPORTED_TRUE@am__objects_2 = \ +@COGL_DRIVER_GL_SUPPORTED_TRUE@ driver/gl/gl/cogl-driver-gl.lo \ +@COGL_DRIVER_GL_SUPPORTED_TRUE@ driver/gl/gl/cogl-texture-driver-gl.lo \ +@COGL_DRIVER_GL_SUPPORTED_TRUE@ $(am__objects_1) +@COGL_DRIVER_GLES_SUPPORTED_TRUE@am__objects_3 = driver/gl/gles/cogl-driver-gles.lo \ +@COGL_DRIVER_GLES_SUPPORTED_TRUE@ driver/gl/gles/cogl-texture-driver-gles.lo \ +@COGL_DRIVER_GLES_SUPPORTED_TRUE@ $(am__objects_1) +am__objects_4 = driver/nop/cogl-driver-nop.lo \ + driver/nop/cogl-framebuffer-nop.lo \ + driver/nop/cogl-attribute-nop.lo \ + driver/nop/cogl-clip-stack-nop.lo \ + driver/nop/cogl-texture-2d-nop.lo $(am__objects_1) \ + driver/gl/cogl-util-gl.lo driver/gl/cogl-framebuffer-gl.lo \ + driver/gl/cogl-texture-gl.lo driver/gl/cogl-texture-2d-gl.lo \ + driver/gl/cogl-attribute-gl.lo driver/gl/cogl-clip-stack-gl.lo \ + driver/gl/cogl-buffer-gl.lo driver/gl/cogl-pipeline-opengl.lo \ + driver/gl/cogl-pipeline-fragend-glsl.lo \ + driver/gl/gl/cogl-pipeline-fragend-arbfp.lo \ + driver/gl/gl/cogl-pipeline-progend-fixed-arbfp.lo \ + driver/gl/cogl-pipeline-fragend-fixed.lo \ + driver/gl/cogl-pipeline-vertend-glsl.lo \ + driver/gl/cogl-pipeline-vertend-fixed.lo \ + driver/gl/cogl-pipeline-progend-fixed.lo \ + driver/gl/cogl-pipeline-progend-glsl.lo $(am__objects_1) \ + $(am__objects_2) $(am__objects_3) +am__objects_5 = winsys/cogl-winsys.lo $(am__objects_1) +@SUPPORT_XLIB_TRUE@am__objects_6 = cogl-xlib-renderer.lo cogl-xlib.lo \ +@SUPPORT_XLIB_TRUE@ winsys/cogl-texture-pixmap-x11.lo +@SUPPORT_GLX_TRUE@am__objects_7 = winsys/cogl-winsys-glx.lo +@SUPPORT_EGL_PLATFORM_XLIB_TRUE@am__objects_8 = \ +@SUPPORT_EGL_PLATFORM_XLIB_TRUE@ winsys/cogl-winsys-egl-x11.lo +@SUPPORT_EGL_TRUE@am__objects_9 = winsys/cogl-winsys-egl.lo +am__objects_10 = $(am__objects_4) $(am__objects_5) cogl-gpu-info.lo \ + cogl-context.lo cogl-renderer.lo cogl-swap-chain.lo \ + cogl-onscreen-template.lo cogl-display.lo cogl.lo \ + cogl-object.lo cogl-util.lo cogl-bitmap.lo \ + cogl-bitmap-conversion.lo cogl-primitives.lo \ + cogl-bitmap-pixbuf.lo cogl-clip-stack.lo \ + cogl-feature-private.lo cogl-color.lo cogl-buffer.lo \ + cogl-pixel-buffer.lo cogl-index-buffer.lo \ + cogl-attribute-buffer.lo cogl-indices.lo cogl-attribute.lo \ + cogl-primitive.lo cogl-matrix.lo cogl-vector.lo cogl-euler.lo \ + cogl-quaternion.lo cogl-matrix-stack.lo cogl-depth-state.lo \ + cogl-node.lo cogl-pipeline.lo cogl-pipeline-layer.lo \ + cogl-pipeline-state.lo cogl-pipeline-layer-state.lo \ + cogl-pipeline-debug.lo cogl-glsl-shader.lo \ + cogl-pipeline-snippet.lo cogl-pipeline-cache.lo \ + cogl-pipeline-hash-table.lo cogl-sampler-cache.lo \ + cogl-blend-string.lo cogl-debug.lo cogl-sub-texture.lo \ + cogl-texture.lo cogl-texture-2d.lo cogl-texture-2d-sliced.lo \ + cogl-texture-3d.lo cogl-texture-rectangle.lo \ + cogl-rectangle-map.lo cogl-atlas.lo cogl-atlas-texture.lo \ + cogl-meta-texture.lo cogl-primitive-texture.lo cogl-blit.lo \ + cogl-spans.lo cogl-journal.lo cogl-frame-info.lo \ + cogl-framebuffer.lo cogl-onscreen.lo cogl-output.lo \ + cogl-profile.lo cogl-bitmask.lo cogl-gtype.lo \ + cogl-point-in-poly.lo cogl-list.lo winsys/cogl-winsys-stub.lo \ + cogl-config.lo cogl-boxed-value.lo cogl-snippet.lo \ + cogl-poll.lo cogl-memory-stack.lo cogl-magazine.lo \ + cogl-gles2-context.lo cogl-error.lo cogl-closure-list.lo \ + cogl-fence.lo deprecated/cogl-vertex-buffer.lo \ + deprecated/cogl-material-compat.lo deprecated/cogl-program.lo \ + deprecated/cogl-auto-texture.lo deprecated/cogl-shader.lo \ + deprecated/cogl-clutter.lo \ + deprecated/cogl-framebuffer-deprecated.lo $(am__objects_1) \ + cogl-glib-source.lo $(am__objects_6) $(am__objects_7) \ + $(am__objects_8) $(am__objects_9) +am_libmutter_cogl_la_OBJECTS = $(am__objects_10) +nodist_libmutter_cogl_la_OBJECTS = $(am__objects_1) +libmutter_cogl_la_OBJECTS = $(am_libmutter_cogl_la_OBJECTS) \ + $(nodist_libmutter_cogl_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libmutter_cogl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libmutter_cogl_la_LDFLAGS) $(LDFLAGS) \ + -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libmutter_cogl_la_SOURCES) \ + $(nodist_libmutter_cogl_la_SOURCES) +DIST_SOURCES = $(am__libmutter_cogl_la_SOURCES_DIST) +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(gir_DATA) $(pkgconfig_DATA) $(typelib_DATA) +am__cogldeprecatedinclude_HEADERS_DIST = \ + deprecated/cogl-material-compat.h \ + deprecated/cogl-vertex-buffer.h deprecated/cogl-shader.h \ + deprecated/cogl-clutter.h deprecated/cogl-type-casts.h \ + deprecated/cogl-auto-texture.h \ + deprecated/cogl-framebuffer-deprecated.h \ + deprecated/cogl-clutter-xlib.h +am__coglinclude_HEADERS_DIST = deprecated/cogl-material-compat.h \ + deprecated/cogl-vertex-buffer.h deprecated/cogl-shader.h \ + deprecated/cogl-clutter.h deprecated/cogl-type-casts.h \ + deprecated/cogl-auto-texture.h cogl1-context.h cogl-bitmap.h \ + cogl-color.h cogl-matrix.h cogl-offscreen.h cogl-primitives.h \ + cogl-texture.h cogl-types.h cogl.h cogl-xlib-renderer.h \ + cogl-deprecated.h cogl-pango.h cogl-object.h cogl-renderer.h \ + cogl-swap-chain.h cogl-onscreen-template.h cogl-display.h \ + cogl-context.h cogl-pipeline.h cogl-pipeline-state.h \ + cogl-pipeline-layer-state.h cogl-snippet.h cogl-gles2.h \ + cogl-gles2-types.h cogl-index-buffer.h cogl-attribute-buffer.h \ + cogl-indices.h cogl-attribute.h cogl-primitive.h \ + cogl-framebuffer.h cogl-onscreen.h cogl-frame-info.h \ + cogl-vector.h cogl-euler.h cogl-output.h cogl-quaternion.h \ + cogl-matrix-stack.h cogl-poll.h cogl-texture-3d.h \ + cogl-texture-2d.h cogl-texture-2d-gl.h \ + cogl-texture-rectangle.h cogl-texture-2d-sliced.h \ + cogl-sub-texture.h cogl-atlas-texture.h cogl-meta-texture.h \ + cogl-primitive-texture.h cogl-depth-state.h cogl-buffer.h \ + cogl-pixel-buffer.h cogl-macros.h cogl-fence.h cogl-version.h \ + cogl-error.h cogl-gtype-private.h cogl-mutter.h \ + cogl-glib-source.h winsys/cogl-texture-pixmap-x11.h \ + cogl-xlib.h cogl-glx.h cogl-wayland-server.h cogl-egl.h +HEADERS = $(cogl_proto_include_HEADERS) \ + $(cogldeprecatedinclude_HEADERS) $(coglinclude_HEADERS) \ + $(nodist_coglinclude_HEADERS) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/cogl-defines.h.in \ + $(srcdir)/cogl-egl-defines.h.in $(srcdir)/cogl-gl-header.h.in \ + $(srcdir)/mutter-cogl-1.0.pc.in $(top_srcdir)/build/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_REQ_VERSION = @CAIRO_REQ_VERSION@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COGL_1_MICRO_VERSION = @COGL_1_MICRO_VERSION@ +COGL_1_MINOR_VERSION = @COGL_1_MINOR_VERSION@ +COGL_1_VERSION = @COGL_1_VERSION@ +COGL_API_VERSION = @COGL_API_VERSION@ +COGL_API_VERSION_AM = @COGL_API_VERSION_AM@ +COGL_DEBUG_CFLAGS = @COGL_DEBUG_CFLAGS@ +COGL_DEFAULT_DRIVER = @COGL_DEFAULT_DRIVER@ +COGL_DEP_CFLAGS = @COGL_DEP_CFLAGS@ +COGL_DEP_GL_CFLAGS = @COGL_DEP_GL_CFLAGS@ +COGL_DEP_GL_LIBS = @COGL_DEP_GL_LIBS@ +COGL_DEP_LIBS = @COGL_DEP_LIBS@ +COGL_EGL_INCLUDES = @COGL_EGL_INCLUDES@ +COGL_EXTRA_CFLAGS = @COGL_EXTRA_CFLAGS@ +COGL_EXTRA_LDFLAGS = @COGL_EXTRA_LDFLAGS@ +COGL_GLES1_LIBNAME = @COGL_GLES1_LIBNAME@ +COGL_GLES2_LIBNAME = @COGL_GLES2_LIBNAME@ +COGL_GL_LIBNAME = @COGL_GL_LIBNAME@ +COGL_GST_DEP_CFLAGS = @COGL_GST_DEP_CFLAGS@ +COGL_GST_DEP_LIBS = @COGL_GST_DEP_LIBS@ +COGL_LT_AGE = @COGL_LT_AGE@ +COGL_LT_CURRENT = @COGL_LT_CURRENT@ +COGL_LT_RELEASE = @COGL_LT_RELEASE@ +COGL_LT_REVISION = @COGL_LT_REVISION@ +COGL_MAJOR_VERSION = @COGL_MAJOR_VERSION@ +COGL_MICRO_VERSION = @COGL_MICRO_VERSION@ +COGL_MINOR_VERSION = @COGL_MINOR_VERSION@ +COGL_PANGO_DEP_CFLAGS = @COGL_PANGO_DEP_CFLAGS@ +COGL_PANGO_DEP_LIBS = @COGL_PANGO_DEP_LIBS@ +COGL_PANGO_PKG_REQUIRES = @COGL_PANGO_PKG_REQUIRES@ +COGL_PKG_REQUIRES = @COGL_PKG_REQUIRES@ +COGL_RELEASE_STATUS = @COGL_RELEASE_STATUS@ +COGL_VERSION = @COGL_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMMY_CFLAGS = @DUMMY_CFLAGS@ +DUMMY_LIBS = @DUMMY_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDKPIXBUF_PREFIX = @GDKPIXBUF_PREFIX@ +GDK_PIXBUF_REQ_VERSION = @GDK_PIXBUF_REQ_VERSION@ +GI_REQ_VERSION = @GI_REQ_VERSION@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ_VERSION = @GLIB_REQ_VERSION@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +HAVE_GL = @HAVE_GL@ +HAVE_GLES1 = @HAVE_GLES1@ +HAVE_GLES2 = @HAVE_GLES2@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINTAINER_CFLAGS = @MAINTAINER_CFLAGS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGOCAIRO_REQ_VERSION = @PANGOCAIRO_REQ_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +UPROF_REQ_VERSION = @UPROF_REQ_VERSION@ +VERSION = @VERSION@ +WAYLAND_SERVER_CFLAGS = @WAYLAND_SERVER_CFLAGS@ +WAYLAND_SERVER_LIBS = @WAYLAND_SERVER_LIBS@ +WAYLAND_SERVER_REQ_VERSION = @WAYLAND_SERVER_REQ_VERSION@ +XCOMPOSITE_REQ_VERSION = @XCOMPOSITE_REQ_VERSION@ +XFIXES_REQ_VERSION = @XFIXES_REQ_VERSION@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = +SUBDIRS = +BUILT_SOURCES = cogl-defines.h cogl-egl-defines.h cogl-gl-header.h +EXTRA_DIST = cogl-defines.h.in cogl-egl-defines.h.in \ + cogl-gl-header.h.in cogl.symbols +CLEANFILES = $(am__append_18) +DISTCLEANFILES = cogl-defines.h cogl-egl-defines.h cogl-gl-header.h \ + $(pc_files) +AM_CPPFLAGS = -I$(top_srcdir) -I$(top_builddir) -I$(srcdir)/deprecated \ + -I$(srcdir)/winsys -I$(srcdir)/driver/gl \ + -I$(srcdir)/driver/gl/gl -I$(srcdir)/driver/gl/gles $(NULL) \ + -DG_LOG_DOMAIN=\"Cogl\" -DCOGL_COMPILATION \ + -DCOGL_GL_LIBNAME=\"$(COGL_GL_LIBNAME)\" \ + -DCOGL_GLES1_LIBNAME=\"$(COGL_GLES1_LIBNAME)\" \ + -DCOGL_GLES2_LIBNAME=\"$(COGL_GLES2_LIBNAME)\" \ + -DCOGL_LOCALEDIR=\""$(localedir)"\" $(NULL) $(am__append_1) +AM_CFLAGS = $(COGL_DEP_CFLAGS) $(COGL_EXTRA_CFLAGS) $(MAINTAINER_CFLAGS) +pc_files = mutter-cogl-1.0.pc +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = $(pc_files) +cogl_deprecated_h = \ + deprecated/cogl-material-compat.h \ + deprecated/cogl-vertex-buffer.h \ + deprecated/cogl-shader.h \ + deprecated/cogl-clutter.h \ + deprecated/cogl-type-casts.h \ + deprecated/cogl-auto-texture.h \ + $(NULL) + +cogl_deprecated_nonintrospected_h = \ + deprecated/cogl-framebuffer-deprecated.h $(NULL) \ + $(am__append_4) + +# public 1.x api headers +cogl_1_public_h = $(cogl_deprecated_h) cogl1-context.h cogl-bitmap.h \ + cogl-color.h cogl-matrix.h cogl-offscreen.h cogl-primitives.h \ + cogl-texture.h cogl-types.h cogl.h $(NULL) $(am__append_5) +cogl_nonintrospected_h = cogl-object.h cogl-renderer.h \ + cogl-swap-chain.h cogl-onscreen-template.h cogl-display.h \ + cogl-context.h cogl-pipeline.h cogl-pipeline-state.h \ + cogl-pipeline-layer-state.h cogl-snippet.h cogl-gles2.h \ + cogl-gles2-types.h cogl-index-buffer.h cogl-attribute-buffer.h \ + cogl-indices.h cogl-attribute.h cogl-primitive.h \ + cogl-framebuffer.h cogl-onscreen.h cogl-frame-info.h \ + cogl-vector.h cogl-euler.h cogl-output.h cogl-quaternion.h \ + cogl-matrix-stack.h cogl-poll.h cogl-texture-3d.h \ + cogl-texture-2d.h cogl-texture-2d-gl.h \ + cogl-texture-rectangle.h cogl-texture-2d-sliced.h \ + cogl-sub-texture.h cogl-atlas-texture.h cogl-meta-texture.h \ + cogl-primitive-texture.h cogl-depth-state.h cogl-buffer.h \ + cogl-pixel-buffer.h cogl-macros.h cogl-fence.h cogl-version.h \ + cogl-error.h cogl-bitmap.h cogl-color.h cogl-matrix.h \ + cogl-texture.h cogl-types.h cogl-gtype-private.h cogl-mutter.h \ + $(NULL) cogl-glib-source.h $(am__append_6) $(am__append_8) \ + $(am__append_10) $(am__append_12) +cogl_nodist_h = $(NULL) $(am__append_13) + +# nop driver +cogl_driver_sources = driver/nop/cogl-driver-nop.c \ + driver/nop/cogl-framebuffer-nop-private.h \ + driver/nop/cogl-framebuffer-nop.c \ + driver/nop/cogl-attribute-nop-private.h \ + driver/nop/cogl-attribute-nop.c \ + driver/nop/cogl-clip-stack-nop-private.h \ + driver/nop/cogl-clip-stack-nop.c \ + driver/nop/cogl-texture-2d-nop-private.h \ + driver/nop/cogl-texture-2d-nop.c $(NULL) \ + driver/gl/cogl-util-gl-private.h driver/gl/cogl-util-gl.c \ + driver/gl/cogl-framebuffer-gl-private.h \ + driver/gl/cogl-framebuffer-gl.c \ + driver/gl/cogl-texture-gl-private.h \ + driver/gl/cogl-texture-gl.c \ + driver/gl/cogl-texture-2d-gl-private.h \ + driver/gl/cogl-texture-2d-gl.c \ + driver/gl/cogl-attribute-gl-private.h \ + driver/gl/cogl-attribute-gl.c \ + driver/gl/cogl-clip-stack-gl-private.h \ + driver/gl/cogl-clip-stack-gl.c \ + driver/gl/cogl-buffer-gl-private.h driver/gl/cogl-buffer-gl.c \ + driver/gl/cogl-pipeline-opengl.c \ + driver/gl/cogl-pipeline-opengl-private.h \ + driver/gl/cogl-pipeline-fragend-glsl.c \ + driver/gl/cogl-pipeline-fragend-glsl-private.h \ + driver/gl/gl/cogl-pipeline-fragend-arbfp.c \ + driver/gl/gl/cogl-pipeline-fragend-arbfp-private.h \ + driver/gl/gl/cogl-pipeline-progend-fixed-arbfp.c \ + driver/gl/gl/cogl-pipeline-progend-fixed-arbfp-private.h \ + driver/gl/cogl-pipeline-fragend-fixed.c \ + driver/gl/cogl-pipeline-fragend-fixed-private.h \ + driver/gl/cogl-pipeline-vertend-glsl.c \ + driver/gl/cogl-pipeline-vertend-glsl-private.h \ + driver/gl/cogl-pipeline-vertend-fixed.c \ + driver/gl/cogl-pipeline-vertend-fixed-private.h \ + driver/gl/cogl-pipeline-progend-fixed.c \ + driver/gl/cogl-pipeline-progend-fixed-private.h \ + driver/gl/cogl-pipeline-progend-glsl.c \ + driver/gl/cogl-pipeline-progend-glsl-private.h $(NULL) \ + $(am__append_2) $(am__append_3) + +# gl driver sources +cogl_gl_prototypes_h = \ + gl-prototypes/cogl-gles2-functions.h \ + gl-prototypes/cogl-core-functions.h \ + gl-prototypes/cogl-in-gles-core-functions.h \ + gl-prototypes/cogl-in-gles2-core-functions.h \ + gl-prototypes/cogl-glsl-functions.h \ + $(NULL) + + +# winsys sources, common to all backends +cogl_winsys_common_sources = \ + winsys/cogl-winsys-private.h \ + winsys/cogl-winsys.c \ + $(NULL) + + +# sources +cogl_sources_c = $(cogl_driver_sources) $(cogl_winsys_common_sources) \ + cogl-private.h cogl-i18n-private.h cogl-debug.h \ + cogl-debug-options.h cogl-gpu-info.c cogl-gpu-info-private.h \ + cogl-context-private.h cogl-context.c cogl-renderer-private.h \ + cogl-renderer.h cogl-renderer.c cogl-swap-chain-private.h \ + cogl-swap-chain.h cogl-swap-chain.c \ + cogl-onscreen-template-private.h cogl-onscreen-template.h \ + cogl-onscreen-template.c cogl-display-private.h cogl-display.h \ + cogl-display.c cogl-driver.h cogl.c cogl-object-private.h \ + cogl-object.h cogl-object.c cogl-util.h cogl-util.c \ + cogl-bitmap-private.h cogl-bitmap.c cogl-bitmap-conversion.c \ + cogl-bitmap-packing.h cogl-primitives-private.h \ + cogl-primitives.h cogl-primitives.c cogl-bitmap-pixbuf.c \ + cogl-clip-stack.h cogl-clip-stack.c cogl-feature-private.h \ + cogl-feature-private.c cogl-color-private.h cogl-color.c \ + cogl-buffer-private.h cogl-buffer.c \ + cogl-pixel-buffer-private.h cogl-pixel-buffer.c \ + cogl-index-buffer-private.h cogl-index-buffer.c \ + cogl-attribute-buffer-private.h cogl-attribute-buffer.c \ + cogl-indices-private.h cogl-indices.c cogl-attribute-private.h \ + cogl-attribute.c cogl-primitive-private.h cogl-primitive.c \ + cogl-matrix.c cogl-vector.c cogl-euler.c \ + cogl-quaternion-private.h cogl-quaternion.c \ + cogl-matrix-private.h cogl-matrix-stack.c \ + cogl-matrix-stack-private.h cogl-depth-state.c \ + cogl-depth-state-private.h cogl-node.c cogl-node-private.h \ + cogl-pipeline.c cogl-pipeline-private.h cogl-pipeline-layer.c \ + cogl-pipeline-layer-private.h cogl-pipeline-state.c \ + cogl-pipeline-layer-state-private.h \ + cogl-pipeline-layer-state.c cogl-pipeline-state-private.h \ + cogl-pipeline-debug.c cogl-glsl-shader.c \ + cogl-glsl-shader-private.h cogl-glsl-shader-boilerplate.h \ + cogl-pipeline-snippet-private.h cogl-pipeline-snippet.c \ + cogl-pipeline-cache.h cogl-pipeline-cache.c \ + cogl-pipeline-hash-table.h cogl-pipeline-hash-table.c \ + cogl-sampler-cache.c cogl-sampler-cache-private.h \ + cogl-blend-string.c cogl-blend-string.h cogl-debug.c \ + cogl-sub-texture-private.h cogl-texture-private.h \ + cogl-texture-2d-private.h cogl-texture-2d-sliced-private.h \ + cogl-texture-3d-private.h cogl-texture-driver.h \ + cogl-sub-texture.c cogl-texture.c cogl-texture-2d.c \ + cogl-texture-2d-sliced.c cogl-texture-3d.c \ + cogl-texture-rectangle-private.h cogl-texture-rectangle.c \ + cogl-rectangle-map.h cogl-rectangle-map.c cogl-atlas.h \ + cogl-atlas.c cogl-atlas-texture-private.h cogl-atlas-texture.c \ + cogl-meta-texture.c cogl-primitive-texture.c cogl-blit.h \ + cogl-blit.c cogl-spans.h cogl-spans.c cogl-journal-private.h \ + cogl-journal.c cogl-frame-info-private.h cogl-frame-info.c \ + cogl-framebuffer-private.h cogl-framebuffer.c \ + cogl-onscreen-private.h cogl-onscreen.c cogl-output-private.h \ + cogl-output.c cogl-profile.h cogl-profile.c cogl-flags.h \ + cogl-bitmask.h cogl-bitmask.c cogl-gtype.c \ + cogl-gtype-private.h cogl-point-in-poly-private.h \ + cogl-point-in-poly.c cogl-list.c cogl-list.h \ + winsys/cogl-winsys-stub-private.h winsys/cogl-winsys-stub.c \ + cogl-config-private.h cogl-config.c cogl-boxed-value.h \ + cogl-boxed-value.c cogl-snippet-private.h cogl-snippet.c \ + cogl-poll-private.h cogl-poll.c \ + gl-prototypes/cogl-all-functions.h \ + gl-prototypes/cogl-gles1-functions.h \ + gl-prototypes/cogl-gles2-functions.h \ + gl-prototypes/cogl-core-functions.h \ + gl-prototypes/cogl-in-gles-core-functions.h \ + gl-prototypes/cogl-in-gles1-core-functions.h \ + gl-prototypes/cogl-in-gles2-core-functions.h \ + gl-prototypes/cogl-fixed-functions.h \ + gl-prototypes/cogl-glsl-functions.h \ + cogl-memory-stack-private.h cogl-memory-stack.c \ + cogl-magazine-private.h cogl-magazine.c \ + cogl-gles2-context-private.h cogl-gles2-context.c \ + cogl-error-private.h cogl-error.c cogl-closure-list-private.h \ + cogl-closure-list.c cogl-fence.c cogl-fence-private.h \ + deprecated/cogl-vertex-buffer-private.h \ + deprecated/cogl-vertex-buffer.c \ + deprecated/cogl-material-compat.c deprecated/cogl-program.c \ + deprecated/cogl-program-private.h \ + deprecated/cogl-auto-texture.c \ + deprecated/cogl-shader-private.h deprecated/cogl-shader.c \ + deprecated/cogl-clutter.c \ + deprecated/cogl-framebuffer-deprecated.c $(NULL) \ + cogl-glib-source.c $(am__append_7) $(am__append_9) \ + $(am__append_11) $(am__append_14) +mutterlibdir = $(libdir)/mutter +mutterlib_LTLIBRARIES = libmutter-cogl.la +libmutter_cogl_la_LIBADD = $(LIBM) $(COGL_DEP_LIBS) \ + $(COGL_EXTRA_LDFLAGS) $(am__append_15) +# XXX: The aim is to eventually get rid of all private API exports +# for cogl-pango. +libmutter_cogl_la_LDFLAGS = \ + -no-undefined \ + -avoid-version \ + -export-dynamic \ + -rpath $(mutterlibdir) \ + -export-symbols-regex "^(cogl|_cogl_debug_flags|_cogl_atlas_new|_cogl_atlas_add_reorganize_callback|_cogl_atlas_reserve_space|_cogl_callback|_cogl_util_get_eye_planes_for_screen_poly|_cogl_atlas_texture_remove_reorganize_callback|_cogl_atlas_texture_add_reorganize_callback|_cogl_texture_get_format|_cogl_texture_foreach_sub_texture_in_region|_cogl_profile_trace_message|_cogl_context_get_default|_cogl_framebuffer_get_stencil_bits|_cogl_clip_stack_push_rectangle|_cogl_framebuffer_get_modelview_stack|_cogl_object_default_unref|_cogl_pipeline_foreach_layer_internal|_cogl_clip_stack_push_primitive|_cogl_buffer_unmap_for_fill_or_fallback|_cogl_framebuffer_draw_primitive|_cogl_debug_instances|_cogl_framebuffer_get_projection_stack|_cogl_pipeline_layer_get_texture|_cogl_buffer_map_for_fill_or_fallback|_cogl_texture_can_hardware_repeat|_cogl_pipeline_prune_to_n_layers|_cogl_primitive_draw|test_|unit_test_|_cogl_winsys_glx_get_vtable|_cogl_winsys_egl_xlib_get_vtable|_cogl_winsys_egl_get_vtable|_cogl_closure_disconnect|_cogl_onscreen_notify_complete|_cogl_onscreen_notify_frame_sync|_cogl_winsys_egl_renderer_connect_common|_cogl_winsys_error_quark|_cogl_set_error|_cogl_poll_renderer_add_fd|_cogl_poll_renderer_add_idle|_cogl_framebuffer_winsys_update_size|_cogl_winsys_egl_make_current).*" + +libmutter_cogl_la_SOURCES = $(cogl_sources_c) +nodist_libmutter_cogl_la_SOURCES = $(BUILT_SOURCES) + +# Cogl installed headers +cogl_headers = \ + $(cogl_1_public_h) \ + cogl-deprecated.h \ + cogl-pango.h \ + $(NULL) + +cogl_base_includedir = $(includedir)/mutter +cogldeprecatedincludedir = $(cogl_base_includedir)/cogl/cogl/deprecated +cogldeprecatedinclude_HEADERS = $(cogl_deprecated_h) $(cogl_deprecated_nonintrospected_h) +coglincludedir = $(cogl_base_includedir)/cogl/cogl +coglinclude_HEADERS = $(cogl_headers) $(cogl_nonintrospected_h) +nodist_coglinclude_HEADERS = $(cogl_nodist_h) cogl-defines.h +cogl_proto_includedir = $(cogl_base_includedir)/cogl/cogl/gl-prototypes +cogl_proto_include_HEADERS = $(cogl_gl_prototypes_h) +INTROSPECTION_GIRS = $(am__append_17) +@HAVE_INTROSPECTION_TRUE@Cogl_1_0_gir_NAMESPACE = Cogl +@HAVE_INTROSPECTION_TRUE@Cogl_1_0_gir_VERSION = 1.0 +@HAVE_INTROSPECTION_TRUE@Cogl_1_0_gir_LIBS = libmutter-cogl.la \ +@HAVE_INTROSPECTION_TRUE@ $(am__append_16) +@HAVE_INTROSPECTION_TRUE@Cogl_1_0_gir_FILES = $(cogl_1_public_h) +@HAVE_INTROSPECTION_TRUE@Cogl_1_0_gir_CFLAGS = $(AM_CPPFLAGS) $(COGL_DEP_CFLAGS) -UCOGL_COMPILATION -D__COGL_H_INSIDE__ -D__COGL_XLIB_H_INSIDE__ -D__COGL_EGL_H_INSIDE__ -D__COGL_GLX_H_INSIDE__ -DCOGL_GIR_SCANNING +@HAVE_INTROSPECTION_TRUE@Cogl_1_0_gir_INCLUDES = GL-1.0 GObject-2.0 +@HAVE_INTROSPECTION_TRUE@Cogl_1_0_gir_EXPORT_PACKAGES = mutter-cogl-1.0 +@HAVE_INTROSPECTION_TRUE@Cogl_1_0_gir_SCANNERFLAGS = --warn-all --c-include='cogl/cogl.h' +@HAVE_INTROSPECTION_TRUE@girdir = $(mutterlibdir) +@HAVE_INTROSPECTION_TRUE@gir_DATA = $(INTROSPECTION_GIRS) +@HAVE_INTROSPECTION_TRUE@typelibdir = $(mutterlibdir) +@HAVE_INTROSPECTION_TRUE@typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib) +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign cogl/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign cogl/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +mutter-cogl-1.0.pc: $(top_builddir)/config.status $(srcdir)/mutter-cogl-1.0.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +cogl-defines.h: $(top_builddir)/config.status $(srcdir)/cogl-defines.h.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +cogl-gl-header.h: $(top_builddir)/config.status $(srcdir)/cogl-gl-header.h.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +cogl-egl-defines.h: $(top_builddir)/config.status $(srcdir)/cogl-egl-defines.h.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +install-mutterlibLTLIBRARIES: $(mutterlib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(mutterlib_LTLIBRARIES)'; test -n "$(mutterlibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(mutterlibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(mutterlibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(mutterlibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(mutterlibdir)"; \ + } + +uninstall-mutterlibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(mutterlib_LTLIBRARIES)'; test -n "$(mutterlibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(mutterlibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(mutterlibdir)/$$f"; \ + done + +clean-mutterlibLTLIBRARIES: + -test -z "$(mutterlib_LTLIBRARIES)" || rm -f $(mutterlib_LTLIBRARIES) + @list='$(mutterlib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +driver/nop/$(am__dirstamp): + @$(MKDIR_P) driver/nop + @: > driver/nop/$(am__dirstamp) +driver/nop/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) driver/nop/$(DEPDIR) + @: > driver/nop/$(DEPDIR)/$(am__dirstamp) +driver/nop/cogl-driver-nop.lo: driver/nop/$(am__dirstamp) \ + driver/nop/$(DEPDIR)/$(am__dirstamp) +driver/nop/cogl-framebuffer-nop.lo: driver/nop/$(am__dirstamp) \ + driver/nop/$(DEPDIR)/$(am__dirstamp) +driver/nop/cogl-attribute-nop.lo: driver/nop/$(am__dirstamp) \ + driver/nop/$(DEPDIR)/$(am__dirstamp) +driver/nop/cogl-clip-stack-nop.lo: driver/nop/$(am__dirstamp) \ + driver/nop/$(DEPDIR)/$(am__dirstamp) +driver/nop/cogl-texture-2d-nop.lo: driver/nop/$(am__dirstamp) \ + driver/nop/$(DEPDIR)/$(am__dirstamp) +driver/gl/$(am__dirstamp): + @$(MKDIR_P) driver/gl + @: > driver/gl/$(am__dirstamp) +driver/gl/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) driver/gl/$(DEPDIR) + @: > driver/gl/$(DEPDIR)/$(am__dirstamp) +driver/gl/cogl-util-gl.lo: driver/gl/$(am__dirstamp) \ + driver/gl/$(DEPDIR)/$(am__dirstamp) +driver/gl/cogl-framebuffer-gl.lo: driver/gl/$(am__dirstamp) \ + driver/gl/$(DEPDIR)/$(am__dirstamp) +driver/gl/cogl-texture-gl.lo: driver/gl/$(am__dirstamp) \ + driver/gl/$(DEPDIR)/$(am__dirstamp) +driver/gl/cogl-texture-2d-gl.lo: driver/gl/$(am__dirstamp) \ + driver/gl/$(DEPDIR)/$(am__dirstamp) +driver/gl/cogl-attribute-gl.lo: driver/gl/$(am__dirstamp) \ + driver/gl/$(DEPDIR)/$(am__dirstamp) +driver/gl/cogl-clip-stack-gl.lo: driver/gl/$(am__dirstamp) \ + driver/gl/$(DEPDIR)/$(am__dirstamp) +driver/gl/cogl-buffer-gl.lo: driver/gl/$(am__dirstamp) \ + driver/gl/$(DEPDIR)/$(am__dirstamp) +driver/gl/cogl-pipeline-opengl.lo: driver/gl/$(am__dirstamp) \ + driver/gl/$(DEPDIR)/$(am__dirstamp) +driver/gl/cogl-pipeline-fragend-glsl.lo: driver/gl/$(am__dirstamp) \ + driver/gl/$(DEPDIR)/$(am__dirstamp) +driver/gl/gl/$(am__dirstamp): + @$(MKDIR_P) driver/gl/gl + @: > driver/gl/gl/$(am__dirstamp) +driver/gl/gl/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) driver/gl/gl/$(DEPDIR) + @: > driver/gl/gl/$(DEPDIR)/$(am__dirstamp) +driver/gl/gl/cogl-pipeline-fragend-arbfp.lo: \ + driver/gl/gl/$(am__dirstamp) \ + driver/gl/gl/$(DEPDIR)/$(am__dirstamp) +driver/gl/gl/cogl-pipeline-progend-fixed-arbfp.lo: \ + driver/gl/gl/$(am__dirstamp) \ + driver/gl/gl/$(DEPDIR)/$(am__dirstamp) +driver/gl/cogl-pipeline-fragend-fixed.lo: driver/gl/$(am__dirstamp) \ + driver/gl/$(DEPDIR)/$(am__dirstamp) +driver/gl/cogl-pipeline-vertend-glsl.lo: driver/gl/$(am__dirstamp) \ + driver/gl/$(DEPDIR)/$(am__dirstamp) +driver/gl/cogl-pipeline-vertend-fixed.lo: driver/gl/$(am__dirstamp) \ + driver/gl/$(DEPDIR)/$(am__dirstamp) +driver/gl/cogl-pipeline-progend-fixed.lo: driver/gl/$(am__dirstamp) \ + driver/gl/$(DEPDIR)/$(am__dirstamp) +driver/gl/cogl-pipeline-progend-glsl.lo: driver/gl/$(am__dirstamp) \ + driver/gl/$(DEPDIR)/$(am__dirstamp) +driver/gl/gl/cogl-driver-gl.lo: driver/gl/gl/$(am__dirstamp) \ + driver/gl/gl/$(DEPDIR)/$(am__dirstamp) +driver/gl/gl/cogl-texture-driver-gl.lo: driver/gl/gl/$(am__dirstamp) \ + driver/gl/gl/$(DEPDIR)/$(am__dirstamp) +driver/gl/gles/$(am__dirstamp): + @$(MKDIR_P) driver/gl/gles + @: > driver/gl/gles/$(am__dirstamp) +driver/gl/gles/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) driver/gl/gles/$(DEPDIR) + @: > driver/gl/gles/$(DEPDIR)/$(am__dirstamp) +driver/gl/gles/cogl-driver-gles.lo: driver/gl/gles/$(am__dirstamp) \ + driver/gl/gles/$(DEPDIR)/$(am__dirstamp) +driver/gl/gles/cogl-texture-driver-gles.lo: \ + driver/gl/gles/$(am__dirstamp) \ + driver/gl/gles/$(DEPDIR)/$(am__dirstamp) +winsys/$(am__dirstamp): + @$(MKDIR_P) winsys + @: > winsys/$(am__dirstamp) +winsys/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) winsys/$(DEPDIR) + @: > winsys/$(DEPDIR)/$(am__dirstamp) +winsys/cogl-winsys.lo: winsys/$(am__dirstamp) \ + winsys/$(DEPDIR)/$(am__dirstamp) +winsys/cogl-winsys-stub.lo: winsys/$(am__dirstamp) \ + winsys/$(DEPDIR)/$(am__dirstamp) +deprecated/$(am__dirstamp): + @$(MKDIR_P) deprecated + @: > deprecated/$(am__dirstamp) +deprecated/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) deprecated/$(DEPDIR) + @: > deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/cogl-vertex-buffer.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/cogl-material-compat.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/cogl-program.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/cogl-auto-texture.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/cogl-shader.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/cogl-clutter.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +deprecated/cogl-framebuffer-deprecated.lo: deprecated/$(am__dirstamp) \ + deprecated/$(DEPDIR)/$(am__dirstamp) +winsys/cogl-texture-pixmap-x11.lo: winsys/$(am__dirstamp) \ + winsys/$(DEPDIR)/$(am__dirstamp) +winsys/cogl-winsys-glx.lo: winsys/$(am__dirstamp) \ + winsys/$(DEPDIR)/$(am__dirstamp) +winsys/cogl-winsys-egl-x11.lo: winsys/$(am__dirstamp) \ + winsys/$(DEPDIR)/$(am__dirstamp) +winsys/cogl-winsys-egl.lo: winsys/$(am__dirstamp) \ + winsys/$(DEPDIR)/$(am__dirstamp) + +libmutter-cogl.la: $(libmutter_cogl_la_OBJECTS) $(libmutter_cogl_la_DEPENDENCIES) $(EXTRA_libmutter_cogl_la_DEPENDENCIES) + $(AM_V_CCLD)$(libmutter_cogl_la_LINK) -rpath $(mutterlibdir) $(libmutter_cogl_la_OBJECTS) $(libmutter_cogl_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f deprecated/*.$(OBJEXT) + -rm -f deprecated/*.lo + -rm -f driver/gl/*.$(OBJEXT) + -rm -f driver/gl/*.lo + -rm -f driver/gl/gl/*.$(OBJEXT) + -rm -f driver/gl/gl/*.lo + -rm -f driver/gl/gles/*.$(OBJEXT) + -rm -f driver/gl/gles/*.lo + -rm -f driver/nop/*.$(OBJEXT) + -rm -f driver/nop/*.lo + -rm -f winsys/*.$(OBJEXT) + -rm -f winsys/*.lo + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-atlas-texture.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-atlas.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-attribute-buffer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-attribute.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-bitmap-conversion.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-bitmap-pixbuf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-bitmap.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-bitmask.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-blend-string.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-blit.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-boxed-value.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-buffer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-clip-stack.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-closure-list.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-color.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-config.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-context.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-debug.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-depth-state.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-display.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-error.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-euler.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-feature-private.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-fence.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-frame-info.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-framebuffer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-gles2-context.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-glib-source.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-glsl-shader.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-gpu-info.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-gtype.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-index-buffer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-indices.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-journal.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-list.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-magazine.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-matrix-stack.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-matrix.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-memory-stack.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-meta-texture.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-node.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-object.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-onscreen-template.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-onscreen.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-output.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-pipeline-cache.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-pipeline-debug.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-pipeline-hash-table.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-pipeline-layer-state.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-pipeline-layer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-pipeline-snippet.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-pipeline-state.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-pipeline.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-pixel-buffer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-point-in-poly.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-poll.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-primitive-texture.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-primitive.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-primitives.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-profile.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-quaternion.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-rectangle-map.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-renderer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-sampler-cache.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-snippet.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-spans.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-sub-texture.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-swap-chain.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-texture-2d-sliced.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-texture-2d.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-texture-3d.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-texture-rectangle.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-texture.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-util.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-vector.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-xlib-renderer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl-xlib.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cogl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/cogl-auto-texture.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/cogl-clutter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/cogl-framebuffer-deprecated.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/cogl-material-compat.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/cogl-program.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/cogl-shader.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@deprecated/$(DEPDIR)/cogl-vertex-buffer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@driver/gl/$(DEPDIR)/cogl-attribute-gl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@driver/gl/$(DEPDIR)/cogl-buffer-gl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@driver/gl/$(DEPDIR)/cogl-clip-stack-gl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@driver/gl/$(DEPDIR)/cogl-framebuffer-gl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@driver/gl/$(DEPDIR)/cogl-pipeline-fragend-fixed.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@driver/gl/$(DEPDIR)/cogl-pipeline-fragend-glsl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@driver/gl/$(DEPDIR)/cogl-pipeline-opengl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@driver/gl/$(DEPDIR)/cogl-pipeline-progend-fixed.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@driver/gl/$(DEPDIR)/cogl-pipeline-progend-glsl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@driver/gl/$(DEPDIR)/cogl-pipeline-vertend-fixed.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@driver/gl/$(DEPDIR)/cogl-pipeline-vertend-glsl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@driver/gl/$(DEPDIR)/cogl-texture-2d-gl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@driver/gl/$(DEPDIR)/cogl-texture-gl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@driver/gl/$(DEPDIR)/cogl-util-gl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@driver/gl/gl/$(DEPDIR)/cogl-driver-gl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@driver/gl/gl/$(DEPDIR)/cogl-pipeline-fragend-arbfp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@driver/gl/gl/$(DEPDIR)/cogl-pipeline-progend-fixed-arbfp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@driver/gl/gl/$(DEPDIR)/cogl-texture-driver-gl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@driver/gl/gles/$(DEPDIR)/cogl-driver-gles.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@driver/gl/gles/$(DEPDIR)/cogl-texture-driver-gles.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@driver/nop/$(DEPDIR)/cogl-attribute-nop.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@driver/nop/$(DEPDIR)/cogl-clip-stack-nop.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@driver/nop/$(DEPDIR)/cogl-driver-nop.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@driver/nop/$(DEPDIR)/cogl-framebuffer-nop.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@driver/nop/$(DEPDIR)/cogl-texture-2d-nop.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@winsys/$(DEPDIR)/cogl-texture-pixmap-x11.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@winsys/$(DEPDIR)/cogl-winsys-egl-x11.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@winsys/$(DEPDIR)/cogl-winsys-egl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@winsys/$(DEPDIR)/cogl-winsys-glx.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@winsys/$(DEPDIR)/cogl-winsys-stub.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@winsys/$(DEPDIR)/cogl-winsys.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + -rm -rf deprecated/.libs deprecated/_libs + -rm -rf driver/gl/.libs driver/gl/_libs + -rm -rf driver/gl/gl/.libs driver/gl/gl/_libs + -rm -rf driver/gl/gles/.libs driver/gl/gles/_libs + -rm -rf driver/nop/.libs driver/nop/_libs + -rm -rf winsys/.libs winsys/_libs +install-girDATA: $(gir_DATA) + @$(NORMAL_INSTALL) + @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(girdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(girdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(girdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(girdir)" || exit $$?; \ + done + +uninstall-girDATA: + @$(NORMAL_UNINSTALL) + @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(girdir)'; $(am__uninstall_files_from_dir) +install-pkgconfigDATA: $(pkgconfig_DATA) + @$(NORMAL_INSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ + done + +uninstall-pkgconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) +install-typelibDATA: $(typelib_DATA) + @$(NORMAL_INSTALL) + @list='$(typelib_DATA)'; test -n "$(typelibdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(typelibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(typelibdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(typelibdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(typelibdir)" || exit $$?; \ + done + +uninstall-typelibDATA: + @$(NORMAL_UNINSTALL) + @list='$(typelib_DATA)'; test -n "$(typelibdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(typelibdir)'; $(am__uninstall_files_from_dir) +install-cogl_proto_includeHEADERS: $(cogl_proto_include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(cogl_proto_include_HEADERS)'; test -n "$(cogl_proto_includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(cogl_proto_includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(cogl_proto_includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(cogl_proto_includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(cogl_proto_includedir)" || exit $$?; \ + done + +uninstall-cogl_proto_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(cogl_proto_include_HEADERS)'; test -n "$(cogl_proto_includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(cogl_proto_includedir)'; $(am__uninstall_files_from_dir) +install-cogldeprecatedincludeHEADERS: $(cogldeprecatedinclude_HEADERS) + @$(NORMAL_INSTALL) + @list='$(cogldeprecatedinclude_HEADERS)'; test -n "$(cogldeprecatedincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(cogldeprecatedincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(cogldeprecatedincludedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(cogldeprecatedincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(cogldeprecatedincludedir)" || exit $$?; \ + done + +uninstall-cogldeprecatedincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(cogldeprecatedinclude_HEADERS)'; test -n "$(cogldeprecatedincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(cogldeprecatedincludedir)'; $(am__uninstall_files_from_dir) +install-coglincludeHEADERS: $(coglinclude_HEADERS) + @$(NORMAL_INSTALL) + @list='$(coglinclude_HEADERS)'; test -n "$(coglincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(coglincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(coglincludedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(coglincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(coglincludedir)" || exit $$?; \ + done + +uninstall-coglincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(coglinclude_HEADERS)'; test -n "$(coglincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(coglincludedir)'; $(am__uninstall_files_from_dir) +install-nodist_coglincludeHEADERS: $(nodist_coglinclude_HEADERS) + @$(NORMAL_INSTALL) + @list='$(nodist_coglinclude_HEADERS)'; test -n "$(coglincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(coglincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(coglincludedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(coglincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(coglincludedir)" || exit $$?; \ + done + +uninstall-nodist_coglincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nodist_coglinclude_HEADERS)'; test -n "$(coglincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(coglincludedir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-recursive +all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(mutterlibdir)" "$(DESTDIR)$(girdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(typelibdir)" "$(DESTDIR)$(cogl_proto_includedir)" "$(DESTDIR)$(cogldeprecatedincludedir)" "$(DESTDIR)$(coglincludedir)" "$(DESTDIR)$(coglincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f deprecated/$(DEPDIR)/$(am__dirstamp) + -rm -f deprecated/$(am__dirstamp) + -rm -f driver/gl/$(DEPDIR)/$(am__dirstamp) + -rm -f driver/gl/$(am__dirstamp) + -rm -f driver/gl/gl/$(DEPDIR)/$(am__dirstamp) + -rm -f driver/gl/gl/$(am__dirstamp) + -rm -f driver/gl/gles/$(DEPDIR)/$(am__dirstamp) + -rm -f driver/gl/gles/$(am__dirstamp) + -rm -f driver/nop/$(DEPDIR)/$(am__dirstamp) + -rm -f driver/nop/$(am__dirstamp) + -rm -f winsys/$(DEPDIR)/$(am__dirstamp) + -rm -f winsys/$(am__dirstamp) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-recursive + +clean-am: clean-generic clean-libtool clean-mutterlibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-recursive + -rm -rf ./$(DEPDIR) deprecated/$(DEPDIR) driver/gl/$(DEPDIR) driver/gl/gl/$(DEPDIR) driver/gl/gles/$(DEPDIR) driver/nop/$(DEPDIR) winsys/$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-cogl_proto_includeHEADERS \ + install-cogldeprecatedincludeHEADERS \ + install-coglincludeHEADERS install-girDATA \ + install-mutterlibLTLIBRARIES install-nodist_coglincludeHEADERS \ + install-pkgconfigDATA install-typelibDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -rf ./$(DEPDIR) deprecated/$(DEPDIR) driver/gl/$(DEPDIR) driver/gl/gl/$(DEPDIR) driver/gl/gles/$(DEPDIR) driver/nop/$(DEPDIR) winsys/$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-cogl_proto_includeHEADERS \ + uninstall-cogldeprecatedincludeHEADERS \ + uninstall-coglincludeHEADERS uninstall-girDATA \ + uninstall-mutterlibLTLIBRARIES \ + uninstall-nodist_coglincludeHEADERS uninstall-pkgconfigDATA \ + uninstall-typelibDATA + +.MAKE: $(am__recursive_targets) all check install install-am \ + install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool \ + clean-mutterlibLTLIBRARIES cscopelist-am ctags ctags-am \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am \ + install-cogl_proto_includeHEADERS \ + install-cogldeprecatedincludeHEADERS \ + install-coglincludeHEADERS install-data install-data-am \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-girDATA install-html install-html-am install-info \ + install-info-am install-man install-mutterlibLTLIBRARIES \ + install-nodist_coglincludeHEADERS install-pdf install-pdf-am \ + install-pkgconfigDATA install-ps install-ps-am install-strip \ + install-typelibDATA installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-cogl_proto_includeHEADERS \ + uninstall-cogldeprecatedincludeHEADERS \ + uninstall-coglincludeHEADERS uninstall-girDATA \ + uninstall-mutterlibLTLIBRARIES \ + uninstall-nodist_coglincludeHEADERS uninstall-pkgconfigDATA \ + uninstall-typelibDATA + +.PRECIOUS: Makefile + + +-include $(INTROSPECTION_MAKEFILE) + +@HAVE_INTROSPECTION_TRUE@Cogl-1.0.gir: libmutter-cogl.la Makefile + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cogl/cogl/cogl-atlas-texture-private.h b/cogl/cogl/cogl-atlas-texture-private.h new file mode 100644 index 0000000..ba83bf9 --- /dev/null +++ b/cogl/cogl/cogl-atlas-texture-private.h @@ -0,0 +1,81 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef _COGL_ATLAS_TEXTURE_PRIVATE_H_ +#define _COGL_ATLAS_TEXTURE_PRIVATE_H_ + +#include "cogl-object-private.h" +#include "cogl-texture-private.h" +#include "cogl-rectangle-map.h" +#include "cogl-atlas.h" +#include "cogl-atlas-texture.h" + +struct _CoglAtlasTexture +{ + CoglTexture _parent; + + /* The format that the texture is in. This isn't necessarily the + same format as the atlas texture because we can store + pre-multiplied and non-pre-multiplied textures together */ + CoglPixelFormat internal_format; + + /* The rectangle that was used to add this texture to the + atlas. This includes the 1-pixel border */ + CoglRectangleMapEntry rectangle; + + /* The atlas that this texture is in. If the texture is no longer in + an atlas then this will be NULL. A reference is taken on the + atlas by the texture (but not vice versa so there is no cycle) */ + CoglAtlas *atlas; + + /* Either a CoglSubTexture representing the atlas region for easy + * rendering or if the texture has been migrated out of the atlas it + * may be some other texture type such as CoglTexture2D */ + CoglTexture *sub_texture; +}; + +CoglAtlasTexture * +_cogl_atlas_texture_new_from_bitmap (CoglBitmap *bmp, + CoglBool can_convert_in_place); + +void +_cogl_atlas_texture_add_reorganize_callback (CoglContext *ctx, + GHookFunc callback, + void *user_data); + +void +_cogl_atlas_texture_remove_reorganize_callback (CoglContext *ctx, + GHookFunc callback, + void *user_data); + +CoglBool +_cogl_is_atlas_texture (void *object); + +#endif /* _COGL_ATLAS_TEXTURE_PRIVATE_H_ */ diff --git a/cogl/cogl/cogl-atlas-texture.c b/cogl/cogl/cogl-atlas-texture.c new file mode 100644 index 0000000..97bb84a --- /dev/null +++ b/cogl/cogl/cogl-atlas-texture.c @@ -0,0 +1,1047 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009,2010,2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Neil Roberts + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-debug.h" +#include "cogl-util.h" +#include "cogl-texture-private.h" +#include "cogl-atlas-texture-private.h" +#include "cogl-texture-2d-private.h" +#include "cogl-sub-texture-private.h" +#include "cogl-context-private.h" +#include "cogl-object-private.h" +#include "cogl-texture-driver.h" +#include "cogl-rectangle-map.h" +#include "cogl-journal-private.h" +#include "cogl-pipeline-opengl-private.h" +#include "cogl-atlas.h" +#include "cogl1-context.h" +#include "cogl-sub-texture.h" +#include "cogl-error-private.h" +#include "cogl-texture-gl-private.h" +#include "cogl-gtype-private.h" + +#include + +static void _cogl_atlas_texture_free (CoglAtlasTexture *sub_tex); + +COGL_TEXTURE_DEFINE (AtlasTexture, atlas_texture); +COGL_GTYPE_DEFINE_CLASS (AtlasTexture, atlas_texture); + +static const CoglTextureVtable cogl_atlas_texture_vtable; + +static CoglSubTexture * +_cogl_atlas_texture_create_sub_texture (CoglTexture *full_texture, + const CoglRectangleMapEntry *rectangle) +{ + CoglContext *ctx = full_texture->context; + /* Create a subtexture for the given rectangle not including the + 1-pixel border */ + return cogl_sub_texture_new (ctx, + full_texture, + rectangle->x + 1, + rectangle->y + 1, + rectangle->width - 2, + rectangle->height - 2); +} + +static void +_cogl_atlas_texture_update_position_cb (void *user_data, + CoglTexture *new_texture, + const CoglRectangleMapEntry *rectangle) +{ + CoglAtlasTexture *atlas_tex = user_data; + + /* Update the sub texture */ + if (atlas_tex->sub_texture) + cogl_object_unref (atlas_tex->sub_texture); + atlas_tex->sub_texture = COGL_TEXTURE ( + _cogl_atlas_texture_create_sub_texture (new_texture, rectangle)); + + /* Update the position */ + atlas_tex->rectangle = *rectangle; +} + +static void +_cogl_atlas_texture_pre_reorganize_foreach_cb + (const CoglRectangleMapEntry *entry, + void *rectangle_data, + void *user_data) +{ + CoglAtlasTexture *atlas_tex = rectangle_data; + + /* Keep a reference to the texture because we don't want it to be + destroyed during the reorganization */ + cogl_object_ref (atlas_tex); + + /* Notify cogl-pipeline.c that the texture's underlying GL texture + * storage is changing so it knows it may need to bind a new texture + * if the CoglTexture is reused with the same texture unit. */ + _cogl_pipeline_texture_storage_change_notify (COGL_TEXTURE (atlas_tex)); +} + +static void +_cogl_atlas_texture_pre_reorganize_cb (void *data) +{ + CoglAtlas *atlas = data; + + /* We don't know if any journal entries currently depend on OpenGL + * texture coordinates that would be invalidated by reorganizing + * this atlas so we flush all journals before migrating. + * + * We are assuming that texture atlas migration never happens + * during a flush so we don't have to consider recursion here. + */ + cogl_flush (); + + if (atlas->map) + _cogl_rectangle_map_foreach (atlas->map, + _cogl_atlas_texture_pre_reorganize_foreach_cb, + NULL); +} + +typedef struct +{ + CoglAtlasTexture **textures; + /* Number of textures found so far */ + unsigned int n_textures; +} CoglAtlasTextureGetRectanglesData; + +static void +_cogl_atlas_texture_get_rectangles_cb (const CoglRectangleMapEntry *entry, + void *rectangle_data, + void *user_data) +{ + CoglAtlasTextureGetRectanglesData *data = user_data; + + data->textures[data->n_textures++] = rectangle_data; +} + +static void +_cogl_atlas_texture_post_reorganize_cb (void *user_data) +{ + CoglAtlas *atlas = user_data; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (atlas->map) + { + CoglAtlasTextureGetRectanglesData data; + unsigned int i; + + data.textures = g_new (CoglAtlasTexture *, + _cogl_rectangle_map_get_n_rectangles (atlas->map)); + data.n_textures = 0; + + /* We need to remove all of the references that we took during + the preorganize callback. We have to get a separate array of + the textures because CoglRectangleMap doesn't support + removing rectangles during iteration */ + _cogl_rectangle_map_foreach (atlas->map, + _cogl_atlas_texture_get_rectangles_cb, + &data); + + for (i = 0; i < data.n_textures; i++) + { + /* Ignore textures that don't have an atlas yet. This will + happen when a new texture is added because we allocate + the structure for the texture so that it can get stored + in the atlas but it isn't a valid object yet */ + if (data.textures[i]->atlas) + cogl_object_unref (data.textures[i]); + } + + g_free (data.textures); + } + + /* Notify any listeners that an atlas has changed */ + g_hook_list_invoke (&ctx->atlas_reorganize_callbacks, FALSE); +} + +static void +_cogl_atlas_texture_atlas_destroyed_cb (void *user_data) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + /* Remove the atlas from the global list */ + ctx->atlases = g_slist_remove (ctx->atlases, user_data); +} + +static CoglAtlas * +_cogl_atlas_texture_create_atlas (CoglContext *ctx) +{ + static CoglUserDataKey atlas_private_key; + + CoglAtlas *atlas = _cogl_atlas_new (COGL_PIXEL_FORMAT_RGBA_8888, + 0, + _cogl_atlas_texture_update_position_cb); + + _cogl_atlas_add_reorganize_callback (atlas, + _cogl_atlas_texture_pre_reorganize_cb, + _cogl_atlas_texture_post_reorganize_cb, + atlas); + + ctx->atlases = g_slist_prepend (ctx->atlases, atlas); + + /* Set some data on the atlas so we can get notification when it is + destroyed in order to remove it from the list. ctx->atlases + effectively holds a weak reference. We don't need a strong + reference because the atlas textures take a reference on the + atlas so it will stay alive */ + cogl_object_set_user_data (COGL_OBJECT (atlas), &atlas_private_key, atlas, + _cogl_atlas_texture_atlas_destroyed_cb); + + return atlas; +} + +static void +_cogl_atlas_texture_foreach_sub_texture_in_region ( + CoglTexture *tex, + float virtual_tx_1, + float virtual_ty_1, + float virtual_tx_2, + float virtual_ty_2, + CoglMetaTextureCallback callback, + void *user_data) +{ + CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex); + CoglMetaTexture *meta_texture = COGL_META_TEXTURE (atlas_tex->sub_texture); + + /* Forward on to the sub texture */ + cogl_meta_texture_foreach_in_region (meta_texture, + virtual_tx_1, + virtual_ty_1, + virtual_tx_2, + virtual_ty_2, + COGL_PIPELINE_WRAP_MODE_REPEAT, + COGL_PIPELINE_WRAP_MODE_REPEAT, + callback, + user_data); +} + +static void +_cogl_atlas_texture_gl_flush_legacy_texobj_wrap_modes (CoglTexture *tex, + GLenum wrap_mode_s, + GLenum wrap_mode_t, + GLenum wrap_mode_p) +{ + CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex); + + /* Forward on to the sub texture */ + _cogl_texture_gl_flush_legacy_texobj_wrap_modes (atlas_tex->sub_texture, + wrap_mode_s, + wrap_mode_t, + wrap_mode_p); +} + +static void +_cogl_atlas_texture_remove_from_atlas (CoglAtlasTexture *atlas_tex) +{ + if (atlas_tex->atlas) + { + _cogl_atlas_remove (atlas_tex->atlas, + &atlas_tex->rectangle); + + cogl_object_unref (atlas_tex->atlas); + atlas_tex->atlas = NULL; + } +} + +static void +_cogl_atlas_texture_free (CoglAtlasTexture *atlas_tex) +{ + _cogl_atlas_texture_remove_from_atlas (atlas_tex); + + if (atlas_tex->sub_texture) + cogl_object_unref (atlas_tex->sub_texture); + + /* Chain up */ + _cogl_texture_free (COGL_TEXTURE (atlas_tex)); +} + +static int +_cogl_atlas_texture_get_max_waste (CoglTexture *tex) +{ + CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex); + + /* Forward on to the sub texture */ + return cogl_texture_get_max_waste (atlas_tex->sub_texture); +} + +static CoglBool +_cogl_atlas_texture_is_sliced (CoglTexture *tex) +{ + CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex); + + /* Forward on to the sub texture */ + return cogl_texture_is_sliced (atlas_tex->sub_texture); +} + +static CoglBool +_cogl_atlas_texture_can_hardware_repeat (CoglTexture *tex) +{ + CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex); + + /* Forward on to the sub texture */ + return _cogl_texture_can_hardware_repeat (atlas_tex->sub_texture); +} + +static void +_cogl_atlas_texture_transform_coords_to_gl (CoglTexture *tex, + float *s, + float *t) +{ + CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex); + + /* Forward on to the sub texture */ + _cogl_texture_transform_coords_to_gl (atlas_tex->sub_texture, s, t); +} + +static CoglTransformResult +_cogl_atlas_texture_transform_quad_coords_to_gl (CoglTexture *tex, + float *coords) +{ + CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex); + + /* Forward on to the sub texture */ + return _cogl_texture_transform_quad_coords_to_gl (atlas_tex->sub_texture, + coords); +} + +static CoglBool +_cogl_atlas_texture_get_gl_texture (CoglTexture *tex, + GLuint *out_gl_handle, + GLenum *out_gl_target) +{ + CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex); + + /* Forward on to the sub texture */ + return cogl_texture_get_gl_texture (atlas_tex->sub_texture, + out_gl_handle, + out_gl_target); +} + +static void +_cogl_atlas_texture_gl_flush_legacy_texobj_filters (CoglTexture *tex, + GLenum min_filter, + GLenum mag_filter) +{ + CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex); + + /* Forward on to the sub texture */ + _cogl_texture_gl_flush_legacy_texobj_filters (atlas_tex->sub_texture, + min_filter, mag_filter); +} + +static void +_cogl_atlas_texture_migrate_out_of_atlas (CoglAtlasTexture *atlas_tex) +{ + CoglTexture *standalone_tex; + + /* Make sure this texture is not in the atlas */ + if (!atlas_tex->atlas) + return; + + COGL_NOTE (ATLAS, "Migrating texture out of the atlas"); + + /* We don't know if any journal entries currently depend on + * OpenGL texture coordinates that would be invalidated by + * migrating textures in this atlas so we flush all journals + * before migrating. + * + * We are assuming that texture atlas migration never happens + * during a flush so we don't have to consider recursion here. + */ + cogl_flush (); + + standalone_tex = + _cogl_atlas_copy_rectangle (atlas_tex->atlas, + atlas_tex->rectangle.x + 1, + atlas_tex->rectangle.y + 1, + atlas_tex->rectangle.width - 2, + atlas_tex->rectangle.height - 2, + atlas_tex->internal_format); + /* Note: we simply silently ignore failures to migrate a texture + * out (most likely due to lack of memory) and hope for the + * best. + * + * Maybe we should find a way to report the problem back to the + * app. + */ + if (!standalone_tex) + return; + + /* Notify cogl-pipeline.c that the texture's underlying GL texture + * storage is changing so it knows it may need to bind a new texture + * if the CoglTexture is reused with the same texture unit. */ + _cogl_pipeline_texture_storage_change_notify (COGL_TEXTURE (atlas_tex)); + + /* We need to unref the sub texture after doing the copy because + the copy can involve rendering which might cause the texture + to be used if it is used from a layer that is left in a + texture unit */ + cogl_object_unref (atlas_tex->sub_texture); + atlas_tex->sub_texture = standalone_tex; + + _cogl_atlas_texture_remove_from_atlas (atlas_tex); +} + +static void +_cogl_atlas_texture_pre_paint (CoglTexture *tex, CoglTexturePrePaintFlags flags) +{ + CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex); + + if ((flags & COGL_TEXTURE_NEEDS_MIPMAP)) + /* Mipmaps do not work well with the current atlas so instead + we'll just migrate the texture out and use a regular texture */ + _cogl_atlas_texture_migrate_out_of_atlas (atlas_tex); + + /* Forward on to the sub texture */ + _cogl_texture_pre_paint (atlas_tex->sub_texture, flags); +} + +static void +_cogl_atlas_texture_ensure_non_quad_rendering (CoglTexture *tex) +{ + CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex); + + /* Sub textures can't support non-quad rendering so we'll just + migrate the texture out */ + _cogl_atlas_texture_migrate_out_of_atlas (atlas_tex); + + /* Forward on to the sub texture */ + _cogl_texture_ensure_non_quad_rendering (atlas_tex->sub_texture); +} + +static CoglBool +_cogl_atlas_texture_set_region_with_border (CoglAtlasTexture *atlas_tex, + int src_x, + int src_y, + int dst_x, + int dst_y, + int dst_width, + int dst_height, + CoglBitmap *bmp, + CoglError **error) +{ + CoglAtlas *atlas = atlas_tex->atlas; + + /* Copy the central data */ + if (!_cogl_texture_set_region_from_bitmap (atlas->texture, + src_x, src_y, + dst_width, + dst_height, + bmp, + dst_x + atlas_tex->rectangle.x + 1, + dst_y + atlas_tex->rectangle.y + 1, + 0, /* level 0 */ + error)) + return FALSE; + + /* Update the left edge pixels */ + if (dst_x == 0 && + !_cogl_texture_set_region_from_bitmap (atlas->texture, + src_x, src_y, + 1, dst_height, + bmp, + atlas_tex->rectangle.x, + dst_y + atlas_tex->rectangle.y + 1, + 0, /* level 0 */ + error)) + return FALSE; + /* Update the right edge pixels */ + if (dst_x + dst_width == atlas_tex->rectangle.width - 2 && + !_cogl_texture_set_region_from_bitmap (atlas->texture, + src_x + dst_width - 1, src_y, + 1, dst_height, + bmp, + atlas_tex->rectangle.x + + atlas_tex->rectangle.width - 1, + dst_y + atlas_tex->rectangle.y + 1, + 0, /* level 0 */ + error)) + return FALSE; + /* Update the top edge pixels */ + if (dst_y == 0 && + !_cogl_texture_set_region_from_bitmap (atlas->texture, + src_x, src_y, + dst_width, 1, + bmp, + dst_x + atlas_tex->rectangle.x + 1, + atlas_tex->rectangle.y, + 0, /* level 0 */ + error)) + return FALSE; + /* Update the bottom edge pixels */ + if (dst_y + dst_height == atlas_tex->rectangle.height - 2 && + !_cogl_texture_set_region_from_bitmap (atlas->texture, + src_x, src_y + dst_height - 1, + dst_width, 1, + bmp, + dst_x + atlas_tex->rectangle.x + 1, + atlas_tex->rectangle.y + + atlas_tex->rectangle.height - 1, + 0, /* level 0 */ + error)) + return FALSE; + + return TRUE; +} + +static CoglBitmap * +_cogl_atlas_texture_convert_bitmap_for_upload (CoglAtlasTexture *atlas_tex, + CoglBitmap *bmp, + CoglPixelFormat internal_format, + CoglBool can_convert_in_place, + CoglError **error) +{ + CoglBitmap *upload_bmp; + CoglBitmap *override_bmp; + + /* We'll prepare to upload using the format of the actual texture of + the atlas texture instead of the format reported by + _cogl_texture_get_format which would be the original internal + format specified when the texture was created. However we'll + preserve the premult status of the internal format because the + images are all stored in the original premult format of the + orignal format so we do need to trigger the conversion */ + + internal_format = (COGL_PIXEL_FORMAT_RGBA_8888 | + (internal_format & COGL_PREMULT_BIT)); + + upload_bmp = _cogl_bitmap_convert_for_upload (bmp, + internal_format, + can_convert_in_place, + error); + if (upload_bmp == NULL) + return NULL; + + /* We'll create another bitmap which uses the same data but + overrides the format to remove the premult flag so that uploads + to the atlas texture won't trigger the conversion again */ + + override_bmp = + _cogl_bitmap_new_shared (upload_bmp, + cogl_bitmap_get_format (upload_bmp) & + ~COGL_PREMULT_BIT, + cogl_bitmap_get_width (upload_bmp), + cogl_bitmap_get_height (upload_bmp), + cogl_bitmap_get_rowstride (upload_bmp)); + + cogl_object_unref (upload_bmp); + + return override_bmp; +} + +static CoglBool +_cogl_atlas_texture_set_region (CoglTexture *tex, + int src_x, + int src_y, + int dst_x, + int dst_y, + int dst_width, + int dst_height, + int level, + CoglBitmap *bmp, + CoglError **error) +{ + CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex); + + if (level != 0 && atlas_tex->atlas) + _cogl_atlas_texture_migrate_out_of_atlas (atlas_tex); + + /* If the texture is in the atlas then we need to copy the edge + pixels to the border */ + if (atlas_tex->atlas) + { + CoglBool ret; + CoglBitmap *upload_bmp = + _cogl_atlas_texture_convert_bitmap_for_upload (atlas_tex, + bmp, + atlas_tex->internal_format, + FALSE, /* can't convert + in place */ + error); + if (!upload_bmp) + return FALSE; + + /* Upload the data ignoring the premult bit */ + ret = _cogl_atlas_texture_set_region_with_border (atlas_tex, + src_x, src_y, + dst_x, dst_y, + dst_width, dst_height, + upload_bmp, + error); + + cogl_object_unref (upload_bmp); + + return ret; + } + else + /* Otherwise we can just forward on to the sub texture */ + return _cogl_texture_set_region_from_bitmap (atlas_tex->sub_texture, + src_x, src_y, + dst_width, dst_height, + bmp, + dst_x, dst_y, + level, + error); +} + +static CoglPixelFormat +_cogl_atlas_texture_get_format (CoglTexture *tex) +{ + CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex); + + /* We don't want to forward this on the sub-texture because it isn't + the necessarily the same format. This will happen if the texture + isn't pre-multiplied */ + return atlas_tex->internal_format; +} + +static GLenum +_cogl_atlas_texture_get_gl_format (CoglTexture *tex) +{ + CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex); + + /* Forward on to the sub texture */ + return _cogl_texture_gl_get_format (atlas_tex->sub_texture); +} + +static CoglBool +_cogl_atlas_texture_can_use_format (CoglPixelFormat format) +{ + /* We don't care about the ordering or the premult status and we can + accept RGBA or RGB textures. Although we could also accept + luminance and alpha only textures or 16-bit formats it seems that + if the application is explicitly using these formats then they've + got a reason to want the lower memory requirements so putting + them in the atlas might not be a good idea */ + format &= ~(COGL_PREMULT_BIT | COGL_BGR_BIT | COGL_AFIRST_BIT); + return (format == COGL_PIXEL_FORMAT_RGB_888 || + format == COGL_PIXEL_FORMAT_RGBA_8888); +} + +static CoglAtlasTexture * +_cogl_atlas_texture_create_base (CoglContext *ctx, + int width, + int height, + CoglPixelFormat internal_format, + CoglTextureLoader *loader) +{ + CoglAtlasTexture *atlas_tex; + + COGL_NOTE (ATLAS, "Adding texture of size %ix%i", width, height); + + /* We need to allocate the texture now because we need the pointer + to set as the data for the rectangle in the atlas */ + atlas_tex = g_new0 (CoglAtlasTexture, 1); + /* Mark it as having no atlas so we don't try to unref it in + _cogl_atlas_texture_post_reorganize_cb */ + atlas_tex->atlas = NULL; + + _cogl_texture_init (COGL_TEXTURE (atlas_tex), + ctx, + width, height, + internal_format, + loader, + &cogl_atlas_texture_vtable); + + atlas_tex->sub_texture = NULL; + + atlas_tex->atlas = NULL; + + return _cogl_atlas_texture_object_new (atlas_tex); +} + +CoglAtlasTexture * +cogl_atlas_texture_new_with_size (CoglContext *ctx, + int width, + int height) +{ + CoglTextureLoader *loader; + + /* We can't atlas zero-sized textures because it breaks the atlas + * data structure */ + _COGL_RETURN_VAL_IF_FAIL (width > 0 && height > 0, NULL); + + loader = _cogl_texture_create_loader (); + loader->src_type = COGL_TEXTURE_SOURCE_TYPE_SIZED; + loader->src.sized.width = width; + loader->src.sized.height = height; + + return _cogl_atlas_texture_create_base (ctx, width, height, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + loader); +} + +static CoglBool +allocate_space (CoglAtlasTexture *atlas_tex, + int width, + int height, + CoglPixelFormat internal_format, + CoglError **error) +{ + CoglTexture *tex = COGL_TEXTURE (atlas_tex); + CoglContext *ctx = tex->context; + CoglAtlas *atlas; + GSList *l; + + /* If the texture is in a strange format then we won't use it */ + if (!_cogl_atlas_texture_can_use_format (internal_format)) + { + COGL_NOTE (ATLAS, "Texture can not be added because the " + "format is unsupported"); + _cogl_set_error (error, + COGL_TEXTURE_ERROR, + COGL_TEXTURE_ERROR_FORMAT, + "Texture format unsuitable for atlasing"); + return FALSE; + } + + /* If we can't use FBOs then it will be too slow to migrate textures + and we shouldn't use the atlas */ + if (!cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN)) + { + _cogl_set_error (error, + COGL_SYSTEM_ERROR, + COGL_SYSTEM_ERROR_UNSUPPORTED, + "Atlasing disabled because migrations " + "would be too slow"); + return FALSE; + } + + /* Look for an existing atlas that can hold the texture */ + for (l = ctx->atlases; l; l = l->next) + { + /* We need to take a reference on the atlas before trying to + * reserve space because in some circumstances atlas migration + * can cause the atlas to be freed */ + atlas = cogl_object_ref (l->data); + /* Try to make some space in the atlas for the texture */ + if (_cogl_atlas_reserve_space (atlas, + /* Add two pixels for the border */ + width + 2, height + 2, + atlas_tex)) + { + /* keep the atlas reference */ + break; + } + else + { + cogl_object_unref (atlas); + } + } + + /* If we couldn't find a suitable atlas then start another */ + if (l == NULL) + { + atlas = _cogl_atlas_texture_create_atlas (ctx); + COGL_NOTE (ATLAS, "Created new atlas for textures: %p", atlas); + if (!_cogl_atlas_reserve_space (atlas, + /* Add two pixels for the border */ + width + 2, height + 2, + atlas_tex)) + { + /* Ok, this means we really can't add it to the atlas */ + cogl_object_unref (atlas); + + _cogl_set_error (error, + COGL_SYSTEM_ERROR, + COGL_SYSTEM_ERROR_NO_MEMORY, + "Not enough memory to atlas texture"); + return FALSE; + } + } + + atlas_tex->internal_format = internal_format; + + atlas_tex->atlas = atlas; + + return TRUE; +} + +static CoglBool +allocate_with_size (CoglAtlasTexture *atlas_tex, + CoglTextureLoader *loader, + CoglError **error) +{ + CoglTexture *tex = COGL_TEXTURE (atlas_tex); + CoglPixelFormat internal_format = + _cogl_texture_determine_internal_format (tex, COGL_PIXEL_FORMAT_ANY); + + if (allocate_space (atlas_tex, + loader->src.sized.width, + loader->src.sized.height, + internal_format, + error)) + { + _cogl_texture_set_allocated (COGL_TEXTURE (atlas_tex), + internal_format, + loader->src.sized.width, + loader->src.sized.height); + return TRUE; + } + else + return FALSE; +} + +static CoglBool +allocate_from_bitmap (CoglAtlasTexture *atlas_tex, + CoglTextureLoader *loader, + CoglError **error) +{ + CoglTexture *tex = COGL_TEXTURE (atlas_tex); + CoglBitmap *bmp = loader->src.bitmap.bitmap; + CoglPixelFormat bmp_format = cogl_bitmap_get_format (bmp); + int width = cogl_bitmap_get_width (bmp); + int height = cogl_bitmap_get_height (bmp); + CoglBool can_convert_in_place = loader->src.bitmap.can_convert_in_place; + CoglPixelFormat internal_format; + CoglBitmap *upload_bmp; + + _COGL_RETURN_VAL_IF_FAIL (atlas_tex->atlas == NULL, FALSE); + + internal_format = _cogl_texture_determine_internal_format (tex, bmp_format); + + upload_bmp = + _cogl_atlas_texture_convert_bitmap_for_upload (atlas_tex, + bmp, + internal_format, + can_convert_in_place, + error); + if (upload_bmp == NULL) + return FALSE; + + if (!allocate_space (atlas_tex, + width, + height, + internal_format, + error)) + { + cogl_object_unref (upload_bmp); + return FALSE; + } + + /* Defer to set_region so that we can share the code for copying the + edge pixels to the border. */ + if (!_cogl_atlas_texture_set_region_with_border (atlas_tex, + 0, /* src_x */ + 0, /* src_y */ + 0, /* dst_x */ + 0, /* dst_y */ + width, /* dst_width */ + height, /* dst_height */ + upload_bmp, + error)) + { + _cogl_atlas_texture_remove_from_atlas (atlas_tex); + cogl_object_unref (upload_bmp); + return FALSE; + } + + cogl_object_unref (upload_bmp); + + _cogl_texture_set_allocated (tex, internal_format, width, height); + + return TRUE; +} + +static CoglBool +_cogl_atlas_texture_allocate (CoglTexture *tex, + CoglError **error) +{ + CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex); + CoglTextureLoader *loader = tex->loader; + + _COGL_RETURN_VAL_IF_FAIL (loader, FALSE); + + switch (loader->src_type) + { + case COGL_TEXTURE_SOURCE_TYPE_SIZED: + return allocate_with_size (atlas_tex, loader, error); + case COGL_TEXTURE_SOURCE_TYPE_BITMAP: + return allocate_from_bitmap (atlas_tex, loader, error); + default: + break; + } + + g_return_val_if_reached (FALSE); +} + +CoglAtlasTexture * +_cogl_atlas_texture_new_from_bitmap (CoglBitmap *bmp, + CoglBool can_convert_in_place) +{ + CoglTextureLoader *loader; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_bitmap (bmp), NULL); + + loader = _cogl_texture_create_loader (); + loader->src_type = COGL_TEXTURE_SOURCE_TYPE_BITMAP; + loader->src.bitmap.bitmap = cogl_object_ref (bmp); + loader->src.bitmap.can_convert_in_place = can_convert_in_place; + + return _cogl_atlas_texture_create_base (_cogl_bitmap_get_context (bmp), + cogl_bitmap_get_width (bmp), + cogl_bitmap_get_height (bmp), + cogl_bitmap_get_format (bmp), + loader); +} + +CoglAtlasTexture * +cogl_atlas_texture_new_from_bitmap (CoglBitmap *bmp) +{ + return _cogl_atlas_texture_new_from_bitmap (bmp, FALSE); +} + +CoglAtlasTexture * +cogl_atlas_texture_new_from_data (CoglContext *ctx, + int width, + int height, + CoglPixelFormat format, + int rowstride, + const uint8_t *data, + CoglError **error) +{ + CoglBitmap *bmp; + CoglAtlasTexture *atlas_tex; + + _COGL_RETURN_VAL_IF_FAIL (format != COGL_PIXEL_FORMAT_ANY, NULL); + _COGL_RETURN_VAL_IF_FAIL (data != NULL, NULL); + + /* Rowstride from width if not given */ + if (rowstride == 0) + rowstride = width * _cogl_pixel_format_get_bytes_per_pixel (format); + + /* Wrap the data into a bitmap */ + bmp = cogl_bitmap_new_for_data (ctx, + width, height, + format, + rowstride, + (uint8_t *) data); + + atlas_tex = cogl_atlas_texture_new_from_bitmap (bmp); + + cogl_object_unref (bmp); + + if (atlas_tex && + !cogl_texture_allocate (COGL_TEXTURE (atlas_tex), error)) + { + cogl_object_unref (atlas_tex); + return NULL; + } + + return atlas_tex; +} + +CoglAtlasTexture * +cogl_atlas_texture_new_from_file (CoglContext *ctx, + const char *filename, + CoglError **error) +{ + CoglBitmap *bmp; + CoglAtlasTexture *atlas_tex = NULL; + + _COGL_RETURN_VAL_IF_FAIL (error == NULL || *error == NULL, NULL); + + bmp = cogl_bitmap_new_from_file (filename, error); + if (bmp == NULL) + return NULL; + + atlas_tex = _cogl_atlas_texture_new_from_bitmap (bmp, + TRUE); /* convert in-place */ + + cogl_object_unref (bmp); + + return atlas_tex; +} + +void +_cogl_atlas_texture_add_reorganize_callback (CoglContext *ctx, + GHookFunc callback, + void *user_data) +{ + GHook *hook = g_hook_alloc (&ctx->atlas_reorganize_callbacks); + hook->func = callback; + hook->data = user_data; + g_hook_prepend (&ctx->atlas_reorganize_callbacks, hook); +} + +void +_cogl_atlas_texture_remove_reorganize_callback (CoglContext *ctx, + GHookFunc callback, + void *user_data) +{ + GHook *hook = g_hook_find_func_data (&ctx->atlas_reorganize_callbacks, + FALSE, + callback, + user_data); + + if (hook) + g_hook_destroy_link (&ctx->atlas_reorganize_callbacks, hook); +} + +static CoglTextureType +_cogl_atlas_texture_get_type (CoglTexture *tex) +{ + return COGL_TEXTURE_TYPE_2D; +} + +static const CoglTextureVtable +cogl_atlas_texture_vtable = + { + FALSE, /* not primitive */ + _cogl_atlas_texture_allocate, + _cogl_atlas_texture_set_region, + NULL, /* get_data */ + _cogl_atlas_texture_foreach_sub_texture_in_region, + _cogl_atlas_texture_get_max_waste, + _cogl_atlas_texture_is_sliced, + _cogl_atlas_texture_can_hardware_repeat, + _cogl_atlas_texture_transform_coords_to_gl, + _cogl_atlas_texture_transform_quad_coords_to_gl, + _cogl_atlas_texture_get_gl_texture, + _cogl_atlas_texture_gl_flush_legacy_texobj_filters, + _cogl_atlas_texture_pre_paint, + _cogl_atlas_texture_ensure_non_quad_rendering, + _cogl_atlas_texture_gl_flush_legacy_texobj_wrap_modes, + _cogl_atlas_texture_get_format, + _cogl_atlas_texture_get_gl_format, + _cogl_atlas_texture_get_type, + NULL, /* is_foreign */ + NULL /* set_auto_mipmap */ + }; diff --git a/cogl/cogl/cogl-atlas-texture.h b/cogl/cogl/cogl-atlas-texture.h new file mode 100644 index 0000000..37b7b8f --- /dev/null +++ b/cogl/cogl/cogl-atlas-texture.h @@ -0,0 +1,254 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef _COGL_ATLAS_TEXTURE_H_ +#define _COGL_ATLAS_TEXTURE_H_ + +#include + +#include + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-atlas-texture + * @short_description: Functions for managing textures in Cogl's global + * set of texture atlases + * + * A texture atlas is a texture that contains many smaller images that + * an application is interested in. These are packed together as a way + * of optimizing drawing with those images by avoiding the costs of + * repeatedly telling the hardware to change what texture it should + * sample from. This can enable more geometry to be batched together + * into few draw calls. + * + * Each #CoglContext has an shared, pool of texture atlases that are + * are managed by Cogl. + * + * This api lets applications upload texture data into one of Cogl's + * shared texture atlases using a high-level #CoglAtlasTexture which + * represents a sub-region of one of these atlases. + * + * A #CoglAtlasTexture is a high-level meta texture which has + * some limitations to be aware of. Please see the documentation for + * #CoglMetaTexture for more details. + */ + + +typedef struct _CoglAtlasTexture CoglAtlasTexture; +#define COGL_ATLAS_TEXTURE(tex) ((CoglAtlasTexture *) tex) + +/** + * cogl_atlas_texture_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_atlas_texture_get_gtype (void); + +/** + * cogl_atlas_texture_new_with_size: + * @ctx: A #CoglContext + * @width: The width of your atlased texture. + * @height: The height of your atlased texture. + * + * Creates a #CoglAtlasTexture with a given @width and @height. A + * #CoglAtlasTexture represents a sub-region within one of Cogl's + * shared texture atlases. + * + * The storage for the texture is not allocated before this function + * returns. You can call cogl_texture_allocate() to explicitly + * allocate the underlying storage or let Cogl automatically allocate + * storage lazily. + * + * The texture is still configurable until it has been allocated so + * for example you can influence the internal format of the texture + * using cogl_texture_set_components() and + * cogl_texture_set_premultiplied(). + * + * Allocate call can fail if Cogl considers the internal + * format to be incompatible with the format of its internal + * atlases. + * + * The returned #CoglAtlasTexture is a high-level meta-texture + * with some limitations. See the documentation for #CoglMetaTexture + * for more details. + * + * Returns: (transfer full): A new #CoglAtlasTexture object. + * Since: 1.16 + * Stability: unstable + */ +CoglAtlasTexture * +cogl_atlas_texture_new_with_size (CoglContext *ctx, + int width, + int height); + +/** + * cogl_atlas_texture_new_from_file: + * @ctx: A #CoglContext + * @filename: the file to load + * @error: A #CoglError to catch exceptional errors or %NULL + * + * Creates a #CoglAtlasTexture from an image file. A #CoglAtlasTexture + * represents a sub-region within one of Cogl's shared texture + * atlases. + * + * The storage for the texture is not allocated before this function + * returns. You can call cogl_texture_allocate() to explicitly + * allocate the underlying storage or let Cogl automatically allocate + * storage lazily. + * + * The texture is still configurable until it has been allocated so + * for example you can influence the internal format of the texture + * using cogl_texture_set_components() and + * cogl_texture_set_premultiplied(). + * + * Allocate call can fail if Cogl considers the internal + * format to be incompatible with the format of its internal + * atlases. + * + * The returned #CoglAtlasTexture is a high-level meta-texture + * with some limitations. See the documentation for #CoglMetaTexture + * for more details. + * + * Return value: (transfer full): A new #CoglAtlasTexture object or + * %NULL on failure and @error will be updated. + * Since: 1.16 + * Stability: unstable + */ +CoglAtlasTexture * +cogl_atlas_texture_new_from_file (CoglContext *ctx, + const char *filename, + CoglError **error); + +/** + * cogl_atlas_texture_new_from_data: + * @ctx: A #CoglContext + * @width: width of texture in pixels + * @height: height of texture in pixels + * @format: the #CoglPixelFormat the buffer is stored in in RAM + * @rowstride: the memory offset in bytes between the start of each + * row in @data. A value of 0 will make Cogl automatically + * calculate @rowstride from @width and @format. + * @data: pointer to the memory region where the source buffer resides + * @error: A #CoglError to catch exceptional errors or %NULL + * + * Creates a new #CoglAtlasTexture texture based on data residing in + * memory. A #CoglAtlasTexture represents a sub-region within one of + * Cogl's shared texture atlases. + * + * This api will always immediately allocate GPU memory for the + * texture and upload the given data so that the @data pointer does + * not need to remain valid once this function returns. This means it + * is not possible to configure the texture before it is allocated. If + * you do need to configure the texture before allocation (to specify + * constraints on the internal format for example) then you can + * instead create a #CoglBitmap for your data and use + * cogl_atlas_texture_new_from_bitmap() or use + * cogl_atlas_texture_new_with_size() and then upload data using + * cogl_texture_set_data() + * + * Allocate call can fail if Cogl considers the internal + * format to be incompatible with the format of its internal + * atlases. + * + * The returned #CoglAtlasTexture is a high-level + * meta-texture with some limitations. See the documentation for + * #CoglMetaTexture for more details. + * + * Return value: (transfer full): A new #CoglAtlasTexture object or + * %NULL on failure and @error will be updated. + * Since: 1.16 + * Stability: unstable + */ +CoglAtlasTexture * +cogl_atlas_texture_new_from_data (CoglContext *ctx, + int width, + int height, + CoglPixelFormat format, + int rowstride, + const uint8_t *data, + CoglError **error); + +/** + * cogl_atlas_texture_new_from_bitmap: + * @bitmap: A #CoglBitmap + * + * Creates a new #CoglAtlasTexture texture based on data residing in a + * @bitmap. A #CoglAtlasTexture represents a sub-region within one of + * Cogl's shared texture atlases. + * + * The storage for the texture is not allocated before this function + * returns. You can call cogl_texture_allocate() to explicitly + * allocate the underlying storage or preferably let Cogl + * automatically allocate storage lazily when it may know more about + * how the texture is being used and can optimize how it is allocated. + * + * The texture is still configurable until it has been allocated so + * for example you can influence the internal format of the texture + * using cogl_texture_set_components() and + * cogl_texture_set_premultiplied(). + * + * Allocate call can fail if Cogl considers the internal + * format to be incompatible with the format of its internal + * atlases. + * + * The returned #CoglAtlasTexture is a high-level meta-texture + * with some limitations. See the documentation for #CoglMetaTexture + * for more details. + * + * Returns: (transfer full): A new #CoglAtlasTexture object. + * Since: 1.16 + * Stability: unstable + */ +CoglAtlasTexture * +cogl_atlas_texture_new_from_bitmap (CoglBitmap *bmp); + +/** + * cogl_is_atlas_texture: + * @object: a #CoglObject + * + * Checks whether the given object references a #CoglAtlasTexture + * + * Return value: %TRUE if the passed object represents an atlas + * texture and %FALSE otherwise + * + * Since: 1.16 + * Stability: Unstable + */ +CoglBool +cogl_is_atlas_texture (void *object); + +COGL_END_DECLS + +#endif /* _COGL_ATLAS_TEXTURE_H_ */ diff --git a/cogl/cogl/cogl-atlas.c b/cogl/cogl/cogl-atlas.c new file mode 100644 index 0000000..023dff8 --- /dev/null +++ b/cogl/cogl/cogl-atlas.c @@ -0,0 +1,690 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010,2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Neil Roberts + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-atlas.h" +#include "cogl-rectangle-map.h" +#include "cogl-context-private.h" +#include "cogl-texture-private.h" +#include "cogl-texture-2d-private.h" +#include "cogl-texture-2d-sliced.h" +#include "cogl-texture-driver.h" +#include "cogl-pipeline-opengl-private.h" +#include "cogl-debug.h" +#include "cogl-framebuffer-private.h" +#include "cogl-blit.h" +#include "cogl-private.h" + +#include + +static void _cogl_atlas_free (CoglAtlas *atlas); + +COGL_OBJECT_INTERNAL_DEFINE (Atlas, atlas); + +CoglAtlas * +_cogl_atlas_new (CoglPixelFormat texture_format, + CoglAtlasFlags flags, + CoglAtlasUpdatePositionCallback update_position_cb) +{ + CoglAtlas *atlas = g_new (CoglAtlas, 1); + + atlas->update_position_cb = update_position_cb; + atlas->map = NULL; + atlas->texture = NULL; + atlas->flags = flags; + atlas->texture_format = texture_format; + g_hook_list_init (&atlas->pre_reorganize_callbacks, sizeof (GHook)); + g_hook_list_init (&atlas->post_reorganize_callbacks, sizeof (GHook)); + + return _cogl_atlas_object_new (atlas); +} + +static void +_cogl_atlas_free (CoglAtlas *atlas) +{ + COGL_NOTE (ATLAS, "%p: Atlas destroyed", atlas); + + if (atlas->texture) + cogl_object_unref (atlas->texture); + if (atlas->map) + _cogl_rectangle_map_free (atlas->map); + + g_hook_list_clear (&atlas->pre_reorganize_callbacks); + g_hook_list_clear (&atlas->post_reorganize_callbacks); + + g_free (atlas); +} + +typedef struct _CoglAtlasRepositionData +{ + /* The current user data for this texture */ + void *user_data; + /* The old and new positions of the texture */ + CoglRectangleMapEntry old_position; + CoglRectangleMapEntry new_position; +} CoglAtlasRepositionData; + +static void +_cogl_atlas_migrate (CoglAtlas *atlas, + unsigned int n_textures, + CoglAtlasRepositionData *textures, + CoglTexture *old_texture, + CoglTexture *new_texture, + void *skip_user_data) +{ + unsigned int i; + CoglBlitData blit_data; + + /* If the 'disable migrate' flag is set then we won't actually copy + the textures to their new location. Instead we'll just invoke the + callback to update the position */ + if ((atlas->flags & COGL_ATLAS_DISABLE_MIGRATION)) + for (i = 0; i < n_textures; i++) + /* Update the texture position */ + atlas->update_position_cb (textures[i].user_data, + new_texture, + &textures[i].new_position); + else + { + _cogl_blit_begin (&blit_data, new_texture, old_texture); + + for (i = 0; i < n_textures; i++) + { + /* Skip the texture that is being added because it doesn't contain + any data yet */ + if (textures[i].user_data != skip_user_data) + _cogl_blit (&blit_data, + textures[i].old_position.x, + textures[i].old_position.y, + textures[i].new_position.x, + textures[i].new_position.y, + textures[i].new_position.width, + textures[i].new_position.height); + + /* Update the texture position */ + atlas->update_position_cb (textures[i].user_data, + new_texture, + &textures[i].new_position); + } + + _cogl_blit_end (&blit_data); + } +} + +typedef struct _CoglAtlasGetRectanglesData +{ + CoglAtlasRepositionData *textures; + /* Number of textures found so far */ + unsigned int n_textures; +} CoglAtlasGetRectanglesData; + +static void +_cogl_atlas_get_rectangles_cb (const CoglRectangleMapEntry *rectangle, + void *rect_data, + void *user_data) +{ + CoglAtlasGetRectanglesData *data = user_data; + + data->textures[data->n_textures].old_position = *rectangle; + data->textures[data->n_textures++].user_data = rect_data; +} + +static void +_cogl_atlas_get_next_size (unsigned int *map_width, + unsigned int *map_height) +{ + /* Double the size of the texture by increasing whichever dimension + is smaller */ + if (*map_width < *map_height) + *map_width <<= 1; + else + *map_height <<= 1; +} + +static void +_cogl_atlas_get_initial_size (CoglPixelFormat format, + unsigned int *map_width, + unsigned int *map_height) +{ + unsigned int size; + GLenum gl_intformat; + GLenum gl_format; + GLenum gl_type; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + ctx->driver_vtable->pixel_format_to_gl (ctx, + format, + &gl_intformat, + &gl_format, + &gl_type); + + /* At least on Intel hardware, the texture size will be rounded up + to at least 1MB so we might as well try to aim for that as an + initial minimum size. If the format is only 1 byte per pixel we + can use 1024x1024, otherwise we'll assume it will take 4 bytes + per pixel and use 512x512. */ + if (_cogl_pixel_format_get_bytes_per_pixel (format) == 1) + size = 1024; + else + size = 512; + + /* Some platforms might not support this large size so we'll + decrease the size until it can */ + while (size > 1 && + !ctx->texture_driver->size_supported (ctx, + GL_TEXTURE_2D, + gl_intformat, + gl_format, + gl_type, + size, size)) + size >>= 1; + + *map_width = size; + *map_height = size; +} + +static CoglRectangleMap * +_cogl_atlas_create_map (CoglPixelFormat format, + unsigned int map_width, + unsigned int map_height, + unsigned int n_textures, + CoglAtlasRepositionData *textures) +{ + GLenum gl_intformat; + GLenum gl_format; + GLenum gl_type; + + _COGL_GET_CONTEXT (ctx, NULL); + + ctx->driver_vtable->pixel_format_to_gl (ctx, + format, + &gl_intformat, + &gl_format, + &gl_type); + + /* Keep trying increasingly larger atlases until we can fit all of + the textures */ + while (ctx->texture_driver->size_supported (ctx, + GL_TEXTURE_2D, + gl_intformat, + gl_format, + gl_type, + map_width, map_height)) + { + CoglRectangleMap *new_atlas = _cogl_rectangle_map_new (map_width, + map_height, + NULL); + unsigned int i; + + COGL_NOTE (ATLAS, "Trying to resize the atlas to %ux%u", + map_width, map_height); + + /* Add all of the textures and keep track of the new position */ + for (i = 0; i < n_textures; i++) + if (!_cogl_rectangle_map_add (new_atlas, + textures[i].old_position.width, + textures[i].old_position.height, + textures[i].user_data, + &textures[i].new_position)) + break; + + /* If the atlas can contain all of the textures then we have a + winner */ + if (i >= n_textures) + return new_atlas; + else + COGL_NOTE (ATLAS, "Atlas size abandoned after trying " + "%u out of %u textures", + i, n_textures); + + _cogl_rectangle_map_free (new_atlas); + _cogl_atlas_get_next_size (&map_width, &map_height); + } + + /* If we get here then there's no atlas that can accommodate all of + the rectangles */ + + return NULL; +} + +static CoglTexture2D * +_cogl_atlas_create_texture (CoglAtlas *atlas, + int width, + int height) +{ + CoglTexture2D *tex; + CoglError *ignore_error = NULL; + + _COGL_GET_CONTEXT (ctx, NULL); + + if ((atlas->flags & COGL_ATLAS_CLEAR_TEXTURE)) + { + uint8_t *clear_data; + CoglBitmap *clear_bmp; + int bpp = _cogl_pixel_format_get_bytes_per_pixel (atlas->texture_format); + + /* Create a buffer of zeroes to initially clear the texture */ + clear_data = g_malloc0 (width * height * bpp); + clear_bmp = cogl_bitmap_new_for_data (ctx, + width, + height, + atlas->texture_format, + width * bpp, + clear_data); + + tex = cogl_texture_2d_new_from_bitmap (clear_bmp); + + _cogl_texture_set_internal_format (COGL_TEXTURE (tex), + atlas->texture_format); + + if (!cogl_texture_allocate (COGL_TEXTURE (tex), &ignore_error)) + { + cogl_error_free (ignore_error); + cogl_object_unref (tex); + tex = NULL; + } + + cogl_object_unref (clear_bmp); + + g_free (clear_data); + } + else + { + tex = cogl_texture_2d_new_with_size (ctx, width, height); + + _cogl_texture_set_internal_format (COGL_TEXTURE (tex), + atlas->texture_format); + + if (!cogl_texture_allocate (COGL_TEXTURE (tex), &ignore_error)) + { + cogl_error_free (ignore_error); + cogl_object_unref (tex); + tex = NULL; + } + } + + return tex; +} + +static int +_cogl_atlas_compare_size_cb (const void *a, + const void *b) +{ + const CoglAtlasRepositionData *ta = a; + const CoglAtlasRepositionData *tb = b; + unsigned int a_size, b_size; + + a_size = ta->old_position.width * ta->old_position.height; + b_size = tb->old_position.width * tb->old_position.height; + + return a_size < b_size ? 1 : a_size > b_size ? -1 : 0; +} + +static void +_cogl_atlas_notify_pre_reorganize (CoglAtlas *atlas) +{ + g_hook_list_invoke (&atlas->pre_reorganize_callbacks, FALSE); +} + +static void +_cogl_atlas_notify_post_reorganize (CoglAtlas *atlas) +{ + g_hook_list_invoke (&atlas->post_reorganize_callbacks, FALSE); +} + +CoglBool +_cogl_atlas_reserve_space (CoglAtlas *atlas, + unsigned int width, + unsigned int height, + void *user_data) +{ + CoglAtlasGetRectanglesData data; + CoglRectangleMap *new_map; + CoglTexture2D *new_tex; + unsigned int map_width = 0, map_height = 0; + CoglBool ret; + CoglRectangleMapEntry new_position; + + /* Check if we can fit the rectangle into the existing map */ + if (atlas->map && + _cogl_rectangle_map_add (atlas->map, width, height, + user_data, + &new_position)) + { + COGL_NOTE (ATLAS, "%p: Atlas is %ix%i, has %i textures and is %i%% waste", + atlas, + _cogl_rectangle_map_get_width (atlas->map), + _cogl_rectangle_map_get_height (atlas->map), + _cogl_rectangle_map_get_n_rectangles (atlas->map), + /* waste as a percentage */ + _cogl_rectangle_map_get_remaining_space (atlas->map) * + 100 / (_cogl_rectangle_map_get_width (atlas->map) * + _cogl_rectangle_map_get_height (atlas->map))); + + atlas->update_position_cb (user_data, + atlas->texture, + &new_position); + + return TRUE; + } + + /* If we make it here then we need to reorganize the atlas. First + we'll notify any users of the atlas that this is going to happen + so that for example in CoglAtlasTexture it can notify that the + storage has changed and cause a flush */ + _cogl_atlas_notify_pre_reorganize (atlas); + + /* Get an array of all the textures currently in the atlas. */ + data.n_textures = 0; + if (atlas->map == NULL) + data.textures = g_malloc (sizeof (CoglAtlasRepositionData)); + else + { + unsigned int n_rectangles = + _cogl_rectangle_map_get_n_rectangles (atlas->map); + data.textures = g_malloc (sizeof (CoglAtlasRepositionData) * + (n_rectangles + 1)); + _cogl_rectangle_map_foreach (atlas->map, + _cogl_atlas_get_rectangles_cb, + &data); + } + + /* Add the new rectangle as a dummy texture so that it can be + positioned with the rest */ + data.textures[data.n_textures].old_position.x = 0; + data.textures[data.n_textures].old_position.y = 0; + data.textures[data.n_textures].old_position.width = width; + data.textures[data.n_textures].old_position.height = height; + data.textures[data.n_textures++].user_data = user_data; + + /* The atlasing algorithm works a lot better if the rectangles are + added in decreasing order of size so we'll first sort the + array */ + qsort (data.textures, data.n_textures, + sizeof (CoglAtlasRepositionData), + _cogl_atlas_compare_size_cb); + + /* Try to create a new atlas that can contain all of the textures */ + if (atlas->map) + { + map_width = _cogl_rectangle_map_get_width (atlas->map); + map_height = _cogl_rectangle_map_get_height (atlas->map); + + /* If there is enough space in for the new rectangle in the + existing atlas with at least 6% waste we'll start with the + same size, otherwise we'll immediately double it */ + if ((map_width * map_height - + _cogl_rectangle_map_get_remaining_space (atlas->map) + + width * height) * 53 / 50 > + map_width * map_height) + _cogl_atlas_get_next_size (&map_width, &map_height); + } + else + _cogl_atlas_get_initial_size (atlas->texture_format, + &map_width, &map_height); + + new_map = _cogl_atlas_create_map (atlas->texture_format, + map_width, map_height, + data.n_textures, data.textures); + + /* If we can't create a map with the texture then give up */ + if (new_map == NULL) + { + COGL_NOTE (ATLAS, "%p: Could not fit texture in the atlas", atlas); + ret = FALSE; + } + /* We need to migrate the existing textures into a new texture */ + else if ((new_tex = _cogl_atlas_create_texture + (atlas, + _cogl_rectangle_map_get_width (new_map), + _cogl_rectangle_map_get_height (new_map))) == NULL) + { + COGL_NOTE (ATLAS, "%p: Could not create a CoglTexture2D", atlas); + _cogl_rectangle_map_free (new_map); + ret = FALSE; + } + else + { + int waste; + + COGL_NOTE (ATLAS, + "%p: Atlas %s with size %ix%i", + atlas, + atlas->map == NULL || + _cogl_rectangle_map_get_width (atlas->map) != + _cogl_rectangle_map_get_width (new_map) || + _cogl_rectangle_map_get_height (atlas->map) != + _cogl_rectangle_map_get_height (new_map) ? + "resized" : "reorganized", + _cogl_rectangle_map_get_width (new_map), + _cogl_rectangle_map_get_height (new_map)); + + if (atlas->map) + { + /* Move all the textures to the right position in the new + texture. This will also update the texture's rectangle */ + _cogl_atlas_migrate (atlas, + data.n_textures, + data.textures, + atlas->texture, + COGL_TEXTURE (new_tex), + user_data); + _cogl_rectangle_map_free (atlas->map); + cogl_object_unref (atlas->texture); + } + else + /* We know there's only one texture so we can just directly + update the rectangle from its new position */ + atlas->update_position_cb (data.textures[0].user_data, + COGL_TEXTURE (new_tex), + &data.textures[0].new_position); + + atlas->map = new_map; + atlas->texture = COGL_TEXTURE (new_tex); + + waste = (_cogl_rectangle_map_get_remaining_space (atlas->map) * + 100 / (_cogl_rectangle_map_get_width (atlas->map) * + _cogl_rectangle_map_get_height (atlas->map))); + + COGL_NOTE (ATLAS, "%p: Atlas is %ix%i, has %i textures and is %i%% waste", + atlas, + _cogl_rectangle_map_get_width (atlas->map), + _cogl_rectangle_map_get_height (atlas->map), + _cogl_rectangle_map_get_n_rectangles (atlas->map), + waste); + + ret = TRUE; + } + + g_free (data.textures); + + _cogl_atlas_notify_post_reorganize (atlas); + + return ret; +} + +void +_cogl_atlas_remove (CoglAtlas *atlas, + const CoglRectangleMapEntry *rectangle) +{ + _cogl_rectangle_map_remove (atlas->map, rectangle); + + COGL_NOTE (ATLAS, "%p: Removed rectangle sized %ix%i", + atlas, + rectangle->width, + rectangle->height); + COGL_NOTE (ATLAS, "%p: Atlas is %ix%i, has %i textures and is %i%% waste", + atlas, + _cogl_rectangle_map_get_width (atlas->map), + _cogl_rectangle_map_get_height (atlas->map), + _cogl_rectangle_map_get_n_rectangles (atlas->map), + _cogl_rectangle_map_get_remaining_space (atlas->map) * + 100 / (_cogl_rectangle_map_get_width (atlas->map) * + _cogl_rectangle_map_get_height (atlas->map))); +}; + +static CoglTexture * +create_migration_texture (CoglContext *ctx, + int width, + int height, + CoglPixelFormat internal_format) +{ + CoglTexture *tex; + CoglError *skip_error = NULL; + + if ((_cogl_util_is_pot (width) && _cogl_util_is_pot (height)) || + (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC) && + cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP))) + { + /* First try creating a fast-path non-sliced texture */ + tex = COGL_TEXTURE (cogl_texture_2d_new_with_size (ctx, + width, height)); + + _cogl_texture_set_internal_format (tex, internal_format); + + /* TODO: instead of allocating storage here it would be better + * if we had some api that let us just check that the size is + * supported by the hardware so storage could be allocated + * lazily when uploading data. */ + if (!cogl_texture_allocate (tex, &skip_error)) + { + cogl_error_free (skip_error); + cogl_object_unref (tex); + tex = NULL; + } + } + else + tex = NULL; + + if (!tex) + { + CoglTexture2DSliced *tex_2ds = + cogl_texture_2d_sliced_new_with_size (ctx, + width, + height, + COGL_TEXTURE_MAX_WASTE); + + _cogl_texture_set_internal_format (COGL_TEXTURE (tex_2ds), + internal_format); + + tex = COGL_TEXTURE (tex_2ds); + } + + return tex; +} + +CoglTexture * +_cogl_atlas_copy_rectangle (CoglAtlas *atlas, + int x, + int y, + int width, + int height, + CoglPixelFormat internal_format) +{ + CoglTexture *tex; + CoglBlitData blit_data; + CoglError *ignore_error = NULL; + + _COGL_GET_CONTEXT (ctx, NULL); + + /* Create a new texture at the right size */ + tex = create_migration_texture (ctx, width, height, internal_format); + if (!cogl_texture_allocate (tex, &ignore_error)) + { + cogl_error_free (ignore_error); + cogl_object_unref (tex); + return NULL; + } + + /* Blit the data out of the atlas to the new texture. If FBOs + aren't available this will end up having to copy the entire + atlas texture */ + _cogl_blit_begin (&blit_data, tex, atlas->texture); + _cogl_blit (&blit_data, + x, y, + 0, 0, + width, height); + _cogl_blit_end (&blit_data); + + return tex; +} + +void +_cogl_atlas_add_reorganize_callback (CoglAtlas *atlas, + GHookFunc pre_callback, + GHookFunc post_callback, + void *user_data) +{ + if (pre_callback) + { + GHook *hook = g_hook_alloc (&atlas->post_reorganize_callbacks); + hook->func = pre_callback; + hook->data = user_data; + g_hook_prepend (&atlas->pre_reorganize_callbacks, hook); + } + if (post_callback) + { + GHook *hook = g_hook_alloc (&atlas->pre_reorganize_callbacks); + hook->func = post_callback; + hook->data = user_data; + g_hook_prepend (&atlas->post_reorganize_callbacks, hook); + } +} + +void +_cogl_atlas_remove_reorganize_callback (CoglAtlas *atlas, + GHookFunc pre_callback, + GHookFunc post_callback, + void *user_data) +{ + if (pre_callback) + { + GHook *hook = g_hook_find_func_data (&atlas->pre_reorganize_callbacks, + FALSE, + pre_callback, + user_data); + if (hook) + g_hook_destroy_link (&atlas->pre_reorganize_callbacks, hook); + } + if (post_callback) + { + GHook *hook = g_hook_find_func_data (&atlas->post_reorganize_callbacks, + FALSE, + post_callback, + user_data); + if (hook) + g_hook_destroy_link (&atlas->post_reorganize_callbacks, hook); + } +} diff --git a/cogl/cogl/cogl-atlas.h b/cogl/cogl/cogl-atlas.h new file mode 100644 index 0000000..e9b3fb0 --- /dev/null +++ b/cogl/cogl/cogl-atlas.h @@ -0,0 +1,105 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010,2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __COGL_ATLAS_H +#define __COGL_ATLAS_H + +#include "cogl-rectangle-map.h" +#include "cogl-object-private.h" +#include "cogl-texture.h" + +typedef void +(* CoglAtlasUpdatePositionCallback) (void *user_data, + CoglTexture *new_texture, + const CoglRectangleMapEntry *rect); + +typedef enum +{ + COGL_ATLAS_CLEAR_TEXTURE = (1 << 0), + COGL_ATLAS_DISABLE_MIGRATION = (1 << 1) +} CoglAtlasFlags; + +typedef struct _CoglAtlas CoglAtlas; + +#define COGL_ATLAS(object) ((CoglAtlas *) object) + +struct _CoglAtlas +{ + CoglObject _parent; + + CoglRectangleMap *map; + + CoglTexture *texture; + CoglPixelFormat texture_format; + CoglAtlasFlags flags; + + CoglAtlasUpdatePositionCallback update_position_cb; + + GHookList pre_reorganize_callbacks; + GHookList post_reorganize_callbacks; +}; + +CoglAtlas * +_cogl_atlas_new (CoglPixelFormat texture_format, + CoglAtlasFlags flags, + CoglAtlasUpdatePositionCallback update_position_cb); + +CoglBool +_cogl_atlas_reserve_space (CoglAtlas *atlas, + unsigned int width, + unsigned int height, + void *user_data); + +void +_cogl_atlas_remove (CoglAtlas *atlas, + const CoglRectangleMapEntry *rectangle); + +CoglTexture * +_cogl_atlas_copy_rectangle (CoglAtlas *atlas, + int x, + int y, + int width, + int height, + CoglPixelFormat format); + +void +_cogl_atlas_add_reorganize_callback (CoglAtlas *atlas, + GHookFunc pre_callback, + GHookFunc post_callback, + void *user_data); + +void +_cogl_atlas_remove_reorganize_callback (CoglAtlas *atlas, + GHookFunc pre_callback, + GHookFunc post_callback, + void *user_data); + +CoglBool +_cogl_is_atlas (void *object); + +#endif /* __COGL_ATLAS_H */ diff --git a/cogl/cogl/cogl-attribute-buffer-private.h b/cogl/cogl/cogl-attribute-buffer-private.h new file mode 100644 index 0000000..c5e8a27 --- /dev/null +++ b/cogl/cogl/cogl-attribute-buffer-private.h @@ -0,0 +1,44 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_ATTRIBUTE_BUFFER_PRIVATE_H +#define __COGL_ATTRIBUTE_BUFFER_PRIVATE_H + +#include "cogl-buffer-private.h" + +struct _CoglAttributeBuffer +{ + CoglBuffer _parent; +}; + +#endif /* __COGL_ATTRIBUTE_BUFFER_PRIVATE_H */ diff --git a/cogl/cogl/cogl-attribute-buffer.c b/cogl/cogl/cogl-attribute-buffer.c new file mode 100644 index 0000000..dfc8e89 --- /dev/null +++ b/cogl/cogl/cogl-attribute-buffer.c @@ -0,0 +1,104 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-object-private.h" +#include "cogl-attribute-buffer.h" +#include "cogl-attribute-buffer-private.h" +#include "cogl-context-private.h" +#include "cogl-gtype-private.h" + +static void _cogl_attribute_buffer_free (CoglAttributeBuffer *array); + +COGL_BUFFER_DEFINE (AttributeBuffer, attribute_buffer); +COGL_GTYPE_DEFINE_CLASS (AttributeBuffer, attribute_buffer); + +CoglAttributeBuffer * +cogl_attribute_buffer_new_with_size (CoglContext *context, + size_t bytes) +{ + CoglAttributeBuffer *buffer = g_slice_new (CoglAttributeBuffer); + + /* parent's constructor */ + _cogl_buffer_initialize (COGL_BUFFER (buffer), + context, + bytes, + COGL_BUFFER_BIND_TARGET_ATTRIBUTE_BUFFER, + COGL_BUFFER_USAGE_HINT_ATTRIBUTE_BUFFER, + COGL_BUFFER_UPDATE_HINT_STATIC); + + return _cogl_attribute_buffer_object_new (buffer); +} + +CoglAttributeBuffer * +cogl_attribute_buffer_new (CoglContext *context, + size_t bytes, + const void *data) +{ + CoglAttributeBuffer *buffer; + + buffer = cogl_attribute_buffer_new_with_size (context, bytes); + + /* Note: to keep the common cases simple this API doesn't throw + * CoglErrors, so developers can assume this function never returns + * NULL and we will simply abort on error. + * + * Developers wanting to catch errors can use + * cogl_attribute_buffer_new_with_size() and catch errors when later + * calling cogl_buffer_set_data() or cogl_buffer_map(). + */ + + /* XXX: NB: for Cogl 2.0 we don't allow NULL data here but we can't + * break the api for 1.x and so we keep the check for now. */ + if (data) + _cogl_buffer_set_data (COGL_BUFFER (buffer), + 0, + data, + bytes, + NULL); + + return buffer; +} + +static void +_cogl_attribute_buffer_free (CoglAttributeBuffer *array) +{ + /* parent's destructor */ + _cogl_buffer_fini (COGL_BUFFER (array)); + + g_slice_free (CoglAttributeBuffer, array); +} + diff --git a/cogl/cogl/cogl-attribute-buffer.h b/cogl/cogl/cogl-attribute-buffer.h new file mode 100644 index 0000000..9c72df4 --- /dev/null +++ b/cogl/cogl/cogl-attribute-buffer.h @@ -0,0 +1,148 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_ATTRIBUTE_BUFFER_H__ +#define __COGL_ATTRIBUTE_BUFFER_H__ + +/* We forward declare the CoglAttributeBuffer type here to avoid some circular + * dependency issues with the following headers. + */ +typedef struct _CoglAttributeBuffer CoglAttributeBuffer; + +#include + +#include + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-attribute-buffer + * @short_description: Functions for creating and manipulating attribute + * buffers + * + * FIXME + */ + +#define COGL_ATTRIBUTE_BUFFER(buffer) ((CoglAttributeBuffer *)(buffer)) + +/** + * cogl_attribute_buffer_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_attribute_buffer_get_gtype (void); + +/** + * cogl_attribute_buffer_new_with_size: + * @context: A #CoglContext + * @bytes: The number of bytes to allocate for vertex attribute data. + * + * Describes a new #CoglAttributeBuffer of @size bytes to contain + * arrays of vertex attribute data. Afterwards data can be set using + * cogl_buffer_set_data() or by mapping it into the application's + * address space using cogl_buffer_map(). + * + * The underlying storage of this buffer isn't allocated by this + * function so that you have an opportunity to use the + * cogl_buffer_set_update_hint() and cogl_buffer_set_usage_hint() + * functions which may influence how the storage is allocated. The + * storage will be allocated once you upload data to the buffer. + * + * Note: You can assume this function always succeeds and won't return + * %NULL + * + * Return value: (transfer full): A newly allocated #CoglAttributeBuffer. Never %NULL. + * + * Stability: Unstable + */ +CoglAttributeBuffer * +cogl_attribute_buffer_new_with_size (CoglContext *context, + size_t bytes); + +/** + * cogl_attribute_buffer_new: + * @context: A #CoglContext + * @bytes: The number of bytes to allocate for vertex attribute data. + * @data: (array length=bytes): An optional pointer to vertex data to + * upload immediately. + * + * Describes a new #CoglAttributeBuffer of @size bytes to contain + * arrays of vertex attribute data and also uploads @size bytes read + * from @data to the new buffer. + * + * You should never pass a %NULL data pointer. + * + * This function does not report out-of-memory errors back to + * the caller by returning %NULL and so you can assume this function + * always succeeds. + * + * In the unlikely case that there is an out of memory problem + * then Cogl will abort the application with a message. If your + * application needs to gracefully handle out-of-memory errors then + * you can use cogl_attribute_buffer_new_with_size() and then + * explicitly catch errors with cogl_buffer_set_data() or + * cogl_buffer_map(). + * + * Return value: (transfer full): A newly allocated #CoglAttributeBuffer (never %NULL) + * + * Since: 1.4 + * Stability: Unstable + */ +CoglAttributeBuffer * +cogl_attribute_buffer_new (CoglContext *context, + size_t bytes, + const void *data); + +/** + * cogl_is_attribute_buffer: + * @object: A #CoglObject + * + * Gets whether the given object references a #CoglAttributeBuffer. + * + * Returns: %TRUE if @object references a #CoglAttributeBuffer, + * %FALSE otherwise + * + * Since: 1.4 + * Stability: Unstable + */ +CoglBool +cogl_is_attribute_buffer (void *object); + +COGL_END_DECLS + +#endif /* __COGL_ATTRIBUTE_BUFFER_H__ */ + diff --git a/cogl/cogl/cogl-attribute-private.h b/cogl/cogl/cogl-attribute-private.h new file mode 100644 index 0000000..aac4a88 --- /dev/null +++ b/cogl/cogl/cogl-attribute-private.h @@ -0,0 +1,140 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_ATTRIBUTE_PRIVATE_H +#define __COGL_ATTRIBUTE_PRIVATE_H + +#include "cogl-object-private.h" +#include "cogl-attribute.h" +#include "cogl-framebuffer.h" +#include "cogl-pipeline-private.h" +#include "cogl-boxed-value.h" + +typedef enum +{ + COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY, + COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY, + COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY, + COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY, + COGL_ATTRIBUTE_NAME_ID_POINT_SIZE_ARRAY, + COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY +} CoglAttributeNameID; + +typedef struct _CoglAttributeNameState +{ + char *name; + CoglAttributeNameID name_id; + int name_index; + CoglBool normalized_default; + int layer_number; +} CoglAttributeNameState; + +struct _CoglAttribute +{ + CoglObject _parent; + + const CoglAttributeNameState *name_state; + CoglBool normalized; + + CoglBool is_buffered; + + union { + struct { + CoglAttributeBuffer *attribute_buffer; + size_t stride; + size_t offset; + int n_components; + CoglAttributeType type; + } buffered; + struct { + CoglContext *context; + CoglBoxedValue boxed; + } constant; + } d; + + int immutable_ref; +}; + +typedef enum +{ + COGL_DRAW_SKIP_JOURNAL_FLUSH = 1 << 0, + COGL_DRAW_SKIP_PIPELINE_VALIDATION = 1 << 1, + COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH = 1 << 2, + COGL_DRAW_SKIP_LEGACY_STATE = 1 << 3, + /* By default the vertex attribute drawing code will assume that if + there is a color attribute array enabled then we can't determine + if the colors will be opaque so we need to enabling + blending. However when drawing from the journal we know what the + contents of the color array is so we can override this by passing + this flag. */ + COGL_DRAW_COLOR_ATTRIBUTE_IS_OPAQUE = 1 << 4, + /* This forcibly disables the debug option to divert all drawing to + * wireframes */ + COGL_DRAW_SKIP_DEBUG_WIREFRAME = 1 << 5 +} CoglDrawFlags; + +/* During CoglContext initialization we register the "cogl_color_in" + * attribute name so it gets a global name_index of 0. We need to know + * the name_index for "cogl_color_in" in + * _cogl_pipeline_flush_gl_state() */ +#define COGL_ATTRIBUTE_COLOR_NAME_INDEX 0 + +CoglAttributeNameState * +_cogl_attribute_register_attribute_name (CoglContext *context, + const char *name); + +CoglAttribute * +_cogl_attribute_immutable_ref (CoglAttribute *attribute); + +void +_cogl_attribute_immutable_unref (CoglAttribute *attribute); + +typedef struct +{ + int unit; + CoglPipelineFlushOptions options; + uint32_t fallback_layers; +} CoglFlushLayerState; + +void +_cogl_flush_attributes_state (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglDrawFlags flags, + CoglAttribute **attributes, + int n_attributes); + +int +_cogl_attribute_get_n_components (CoglAttribute *attribute); + +#endif /* __COGL_ATTRIBUTE_PRIVATE_H */ + diff --git a/cogl/cogl/cogl-attribute.c b/cogl/cogl/cogl-attribute.c new file mode 100644 index 0000000..73fb07a --- /dev/null +++ b/cogl/cogl/cogl-attribute.c @@ -0,0 +1,687 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-util.h" +#include "cogl-context-private.h" +#include "cogl-object-private.h" +#include "cogl-journal-private.h" +#include "cogl-attribute.h" +#include "cogl-attribute-private.h" +#include "cogl-pipeline.h" +#include "cogl-pipeline-private.h" +#include "cogl-pipeline-opengl-private.h" +#include "cogl-texture-private.h" +#include "cogl-framebuffer-private.h" +#include "cogl-indices-private.h" +#ifdef COGL_PIPELINE_PROGEND_GLSL +#include "cogl-pipeline-progend-glsl-private.h" +#endif +#include "cogl-private.h" +#include "cogl-gtype-private.h" + +#include +#include +#include + +/* This isn't defined in the GLES headers */ +#ifndef GL_UNSIGNED_INT +#define GL_UNSIGNED_INT 0x1405 +#endif + +static void _cogl_attribute_free (CoglAttribute *attribute); + +COGL_OBJECT_DEFINE (Attribute, attribute); +COGL_GTYPE_DEFINE_CLASS (Attribute, attribute); + +static CoglBool +validate_cogl_attribute_name (const char *name, + char **real_attribute_name, + CoglAttributeNameID *name_id, + CoglBool *normalized, + int *layer_number) +{ + name = name + 5; /* skip "cogl_" */ + + *normalized = FALSE; + *layer_number = 0; + + if (strcmp (name, "position_in") == 0) + *name_id = COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY; + else if (strcmp (name, "color_in") == 0) + { + *name_id = COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY; + *normalized = TRUE; + } + else if (strcmp (name, "tex_coord_in") == 0) + { + *real_attribute_name = "cogl_tex_coord0_in"; + *name_id = COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY; + } + else if (strncmp (name, "tex_coord", strlen ("tex_coord")) == 0) + { + char *endptr; + *layer_number = strtoul (name + 9, &endptr, 10); + if (strcmp (endptr, "_in") != 0) + { + g_warning ("Texture coordinate attributes should either be named " + "\"cogl_tex_coord_in\" or named with a texture unit index " + "like \"cogl_tex_coord2_in\"\n"); + return FALSE; + } + *name_id = COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY; + } + else if (strcmp (name, "normal_in") == 0) + { + *name_id = COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY; + *normalized = TRUE; + } + else if (strcmp (name, "point_size_in") == 0) + *name_id = COGL_ATTRIBUTE_NAME_ID_POINT_SIZE_ARRAY; + else + { + g_warning ("Unknown cogl_* attribute name cogl_%s\n", name); + return FALSE; + } + + return TRUE; +} + +CoglAttributeNameState * +_cogl_attribute_register_attribute_name (CoglContext *context, + const char *name) +{ + CoglAttributeNameState *name_state = g_new (CoglAttributeNameState, 1); + int name_index = context->n_attribute_names++; + char *name_copy = g_strdup (name); + + name_state->name = NULL; + name_state->name_index = name_index; + if (strncmp (name, "cogl_", 5) == 0) + { + if (!validate_cogl_attribute_name (name, + &name_state->name, + &name_state->name_id, + &name_state->normalized_default, + &name_state->layer_number)) + goto error; + } + else + { + name_state->name_id = COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY; + name_state->normalized_default = FALSE; + name_state->layer_number = 0; + } + + if (name_state->name == NULL) + name_state->name = name_copy; + + g_hash_table_insert (context->attribute_name_states_hash, + name_copy, name_state); + + if (G_UNLIKELY (context->attribute_name_index_map == NULL)) + context->attribute_name_index_map = + g_array_new (FALSE, FALSE, sizeof (void *)); + + g_array_set_size (context->attribute_name_index_map, name_index + 1); + + g_array_index (context->attribute_name_index_map, + CoglAttributeNameState *, name_index) = name_state; + + return name_state; + +error: + g_free (name_state); + return NULL; +} + +static CoglBool +validate_n_components (const CoglAttributeNameState *name_state, + int n_components) +{ + switch (name_state->name_id) + { + case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY: + if (G_UNLIKELY (n_components == 1)) + { + g_critical ("glVertexPointer doesn't allow 1 component vertex " + "positions so we currently only support \"cogl_vertex\" " + "attributes where n_components == 2, 3 or 4"); + return FALSE; + } + break; + case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY: + if (G_UNLIKELY (n_components != 3 && n_components != 4)) + { + g_critical ("glColorPointer expects 3 or 4 component colors so we " + "currently only support \"cogl_color\" attributes where " + "n_components == 3 or 4"); + return FALSE; + } + break; + case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY: + break; + case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY: + if (G_UNLIKELY (n_components != 3)) + { + g_critical ("glNormalPointer expects 3 component normals so we " + "currently only support \"cogl_normal\" attributes " + "where n_components == 3"); + return FALSE; + } + break; + case COGL_ATTRIBUTE_NAME_ID_POINT_SIZE_ARRAY: + if (G_UNLIKELY (n_components != 1)) + { + g_critical ("The point size attribute can only have one " + "component"); + return FALSE; + } + break; + case COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY: + return TRUE; + } + + return TRUE; +} + +CoglAttribute * +cogl_attribute_new (CoglAttributeBuffer *attribute_buffer, + const char *name, + size_t stride, + size_t offset, + int n_components, + CoglAttributeType type) +{ + CoglAttribute *attribute = g_slice_new (CoglAttribute); + CoglBuffer *buffer = COGL_BUFFER (attribute_buffer); + CoglContext *ctx = buffer->context; + + attribute->is_buffered = TRUE; + + attribute->name_state = + g_hash_table_lookup (ctx->attribute_name_states_hash, name); + if (!attribute->name_state) + { + CoglAttributeNameState *name_state = + _cogl_attribute_register_attribute_name (ctx, name); + if (!name_state) + goto error; + attribute->name_state = name_state; + } + + attribute->d.buffered.attribute_buffer = cogl_object_ref (attribute_buffer); + attribute->d.buffered.stride = stride; + attribute->d.buffered.offset = offset; + attribute->d.buffered.n_components = n_components; + attribute->d.buffered.type = type; + + attribute->immutable_ref = 0; + + if (attribute->name_state->name_id != COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY) + { + if (!validate_n_components (attribute->name_state, n_components)) + return NULL; + attribute->normalized = + attribute->name_state->normalized_default; + } + else + attribute->normalized = FALSE; + + return _cogl_attribute_object_new (attribute); + +error: + _cogl_attribute_free (attribute); + return NULL; +} + +static CoglAttribute * +_cogl_attribute_new_const (CoglContext *context, + const char *name, + int n_components, + int n_columns, + CoglBool transpose, + const float *value) +{ + CoglAttribute *attribute = g_slice_new (CoglAttribute); + + attribute->name_state = + g_hash_table_lookup (context->attribute_name_states_hash, name); + if (!attribute->name_state) + { + CoglAttributeNameState *name_state = + _cogl_attribute_register_attribute_name (context, name); + if (!name_state) + goto error; + attribute->name_state = name_state; + } + + if (!validate_n_components (attribute->name_state, n_components)) + goto error; + + attribute->is_buffered = FALSE; + attribute->normalized = FALSE; + + attribute->d.constant.context = cogl_object_ref (context); + + attribute->d.constant.boxed.v.array = NULL; + + if (n_columns == 1) + { + _cogl_boxed_value_set_float (&attribute->d.constant.boxed, + n_components, + 1, + value); + } + else + { + /* FIXME: Up until GL[ES] 3 only square matrices were supported + * and we don't currently expose non-square matrices in Cogl. + */ + _COGL_RETURN_VAL_IF_FAIL (n_columns == n_components, NULL); + _cogl_boxed_value_set_matrix (&attribute->d.constant.boxed, + n_columns, + 1, + transpose, + value); + } + + return _cogl_attribute_object_new (attribute); + +error: + _cogl_attribute_free (attribute); + return NULL; +} + +CoglAttribute * +cogl_attribute_new_const_1f (CoglContext *context, + const char *name, + float value) +{ + return _cogl_attribute_new_const (context, + name, + 1, /* n_components */ + 1, /* 1 column vector */ + FALSE, /* no transpose */ + &value); +} + +CoglAttribute * +cogl_attribute_new_const_2fv (CoglContext *context, + const char *name, + const float *value) +{ + return _cogl_attribute_new_const (context, + name, + 2, /* n_components */ + 1, /* 1 column vector */ + FALSE, /* no transpose */ + value); +} + +CoglAttribute * +cogl_attribute_new_const_3fv (CoglContext *context, + const char *name, + const float *value) +{ + return _cogl_attribute_new_const (context, + name, + 3, /* n_components */ + 1, /* 1 column vector */ + FALSE, /* no transpose */ + value); +} + +CoglAttribute * +cogl_attribute_new_const_4fv (CoglContext *context, + const char *name, + const float *value) +{ + return _cogl_attribute_new_const (context, + name, + 4, /* n_components */ + 1, /* 1 column vector */ + FALSE, /* no transpose */ + value); +} + +CoglAttribute * +cogl_attribute_new_const_2f (CoglContext *context, + const char *name, + float component0, + float component1) +{ + float vec2[2] = { component0, component1 }; + return _cogl_attribute_new_const (context, + name, + 2, /* n_components */ + 1, /* 1 column vector */ + FALSE, /* no transpose */ + vec2); +} + +CoglAttribute * +cogl_attribute_new_const_3f (CoglContext *context, + const char *name, + float component0, + float component1, + float component2) +{ + float vec3[3] = { component0, component1, component2 }; + return _cogl_attribute_new_const (context, + name, + 3, /* n_components */ + 1, /* 1 column vector */ + FALSE, /* no transpose */ + vec3); +} + +CoglAttribute * +cogl_attribute_new_const_4f (CoglContext *context, + const char *name, + float component0, + float component1, + float component2, + float component3) +{ + float vec4[4] = { component0, component1, component2, component3 }; + return _cogl_attribute_new_const (context, + name, + 4, /* n_components */ + 1, /* 1 column vector */ + FALSE, /* no transpose */ + vec4); +} + +CoglAttribute * +cogl_attribute_new_const_2x2fv (CoglContext *context, + const char *name, + const float *matrix2x2, + CoglBool transpose) +{ + return _cogl_attribute_new_const (context, + name, + 2, /* n_components */ + 2, /* 2 column vector */ + FALSE, /* no transpose */ + matrix2x2); +} + +CoglAttribute * +cogl_attribute_new_const_3x3fv (CoglContext *context, + const char *name, + const float *matrix3x3, + CoglBool transpose) +{ + return _cogl_attribute_new_const (context, + name, + 3, /* n_components */ + 3, /* 3 column vector */ + FALSE, /* no transpose */ + matrix3x3); +} + +CoglAttribute * +cogl_attribute_new_const_4x4fv (CoglContext *context, + const char *name, + const float *matrix4x4, + CoglBool transpose) +{ + return _cogl_attribute_new_const (context, + name, + 4, /* n_components */ + 4, /* 4 column vector */ + FALSE, /* no transpose */ + matrix4x4); +} + +CoglBool +cogl_attribute_get_normalized (CoglAttribute *attribute) +{ + _COGL_RETURN_VAL_IF_FAIL (cogl_is_attribute (attribute), FALSE); + + return attribute->normalized; +} + +static void +warn_about_midscene_changes (void) +{ + static CoglBool seen = FALSE; + if (!seen) + { + g_warning ("Mid-scene modification of attributes has " + "undefined results\n"); + seen = TRUE; + } +} + +void +cogl_attribute_set_normalized (CoglAttribute *attribute, + CoglBool normalized) +{ + _COGL_RETURN_IF_FAIL (cogl_is_attribute (attribute)); + + if (G_UNLIKELY (attribute->immutable_ref)) + warn_about_midscene_changes (); + + attribute->normalized = normalized; +} + +CoglAttributeBuffer * +cogl_attribute_get_buffer (CoglAttribute *attribute) +{ + _COGL_RETURN_VAL_IF_FAIL (cogl_is_attribute (attribute), NULL); + _COGL_RETURN_VAL_IF_FAIL (attribute->is_buffered, NULL); + + return attribute->d.buffered.attribute_buffer; +} + +void +cogl_attribute_set_buffer (CoglAttribute *attribute, + CoglAttributeBuffer *attribute_buffer) +{ + _COGL_RETURN_IF_FAIL (cogl_is_attribute (attribute)); + _COGL_RETURN_IF_FAIL (attribute->is_buffered); + + if (G_UNLIKELY (attribute->immutable_ref)) + warn_about_midscene_changes (); + + cogl_object_ref (attribute_buffer); + + cogl_object_unref (attribute->d.buffered.attribute_buffer); + attribute->d.buffered.attribute_buffer = attribute_buffer; +} + +CoglAttribute * +_cogl_attribute_immutable_ref (CoglAttribute *attribute) +{ + CoglBuffer *buffer = COGL_BUFFER (attribute->d.buffered.attribute_buffer); + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_attribute (attribute), NULL); + + attribute->immutable_ref++; + _cogl_buffer_immutable_ref (buffer); + return attribute; +} + +void +_cogl_attribute_immutable_unref (CoglAttribute *attribute) +{ + CoglBuffer *buffer = COGL_BUFFER (attribute->d.buffered.attribute_buffer); + + _COGL_RETURN_IF_FAIL (cogl_is_attribute (attribute)); + _COGL_RETURN_IF_FAIL (attribute->immutable_ref > 0); + + attribute->immutable_ref--; + _cogl_buffer_immutable_unref (buffer); +} + +static void +_cogl_attribute_free (CoglAttribute *attribute) +{ + if (attribute->is_buffered) + cogl_object_unref (attribute->d.buffered.attribute_buffer); + else + _cogl_boxed_value_destroy (&attribute->d.constant.boxed); + + g_slice_free (CoglAttribute, attribute); +} + +static CoglBool +validate_layer_cb (CoglPipeline *pipeline, + int layer_index, + void *user_data) +{ + CoglTexture *texture = + cogl_pipeline_get_layer_texture (pipeline, layer_index); + CoglFlushLayerState *state = user_data; + CoglBool status = TRUE; + + /* invalid textures will be handled correctly in + * _cogl_pipeline_flush_layers_gl_state */ + if (texture == NULL) + goto validated; + + _cogl_texture_flush_journal_rendering (texture); + + /* Give the texture a chance to know that we're rendering + non-quad shaped primitives. If the texture is in an atlas it + will be migrated */ + _cogl_texture_ensure_non_quad_rendering (texture); + + /* We need to ensure the mipmaps are ready before deciding + * anything else about the texture because the texture storate + * could completely change if it needs to be migrated out of the + * atlas and will affect how we validate the layer. + */ + _cogl_pipeline_pre_paint_for_layer (pipeline, layer_index); + + if (!_cogl_texture_can_hardware_repeat (texture)) + { + g_warning ("Disabling layer %d of the current source material, " + "because texturing with the vertex buffer API is not " + "currently supported using sliced textures, or textures " + "with waste\n", layer_index); + + /* XXX: maybe we can add a mechanism for users to forcibly use + * textures with waste where it would be their responsability to use + * texture coords in the range [0,1] such that sampling outside isn't + * required. We can then use a texture matrix (or a modification of + * the users own matrix) to map 1 to the edge of the texture data. + * + * Potentially, given the same guarantee as above we could also + * support a single sliced layer too. We would have to redraw the + * vertices once for each layer, each time with a fiddled texture + * matrix. + */ + state->fallback_layers |= (1 << state->unit); + state->options.flags |= COGL_PIPELINE_FLUSH_FALLBACK_MASK; + } + +validated: + state->unit++; + return status; +} + +void +_cogl_flush_attributes_state (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglDrawFlags flags, + CoglAttribute **attributes, + int n_attributes) +{ + CoglContext *ctx = framebuffer->context; + CoglFlushLayerState layers_state; + CoglPipeline *copy = NULL; + + if (!(flags & COGL_DRAW_SKIP_JOURNAL_FLUSH)) + _cogl_journal_flush (framebuffer->journal); + + layers_state.unit = 0; + layers_state.options.flags = 0; + layers_state.fallback_layers = 0; + + if (!(flags & COGL_DRAW_SKIP_PIPELINE_VALIDATION)) + cogl_pipeline_foreach_layer (pipeline, + validate_layer_cb, + &layers_state); + + /* NB: _cogl_framebuffer_flush_state may disrupt various state (such + * as the pipeline state) when flushing the clip stack, so should + * always be done first when preparing to draw. We need to do this + * before setting up the array pointers because setting up the clip + * stack can cause some drawing which would change the array + * pointers. */ + if (!(flags & COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH)) + _cogl_framebuffer_flush_state (framebuffer, + framebuffer, + COGL_FRAMEBUFFER_STATE_ALL); + + /* In cogl_read_pixels we have a fast-path when reading a single + * pixel and the scene is just comprised of simple rectangles still + * in the journal. For this optimization to work we need to track + * when the framebuffer really does get drawn to. */ + _cogl_framebuffer_mark_mid_scene (framebuffer); + _cogl_framebuffer_mark_clear_clip_dirty (framebuffer); + + if (G_UNLIKELY (!(flags & COGL_DRAW_SKIP_LEGACY_STATE)) && + G_UNLIKELY (ctx->legacy_state_set) && + _cogl_get_enable_legacy_state ()) + { + copy = cogl_pipeline_copy (pipeline); + pipeline = copy; + _cogl_pipeline_apply_legacy_state (pipeline); + } + + ctx->driver_vtable->flush_attributes_state (framebuffer, + pipeline, + &layers_state, + flags, + attributes, + n_attributes); + + if (copy) + cogl_object_unref (copy); +} + +int +_cogl_attribute_get_n_components (CoglAttribute *attribute) +{ + if (attribute->is_buffered) + return attribute->d.buffered.n_components; + else + return attribute->d.constant.boxed.size; +} diff --git a/cogl/cogl/cogl-attribute.h b/cogl/cogl/cogl-attribute.h new file mode 100644 index 0000000..801412c --- /dev/null +++ b/cogl/cogl/cogl-attribute.h @@ -0,0 +1,554 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_ATTRIBUTE_H__ +#define __COGL_ATTRIBUTE_H__ + +/* We forward declare the CoglAttribute type here to avoid some circular + * dependency issues with the following headers. + */ +typedef struct _CoglAttribute CoglAttribute; + +#include +#include + +#include + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-attribute + * @short_description: Functions for declaring and drawing vertex + * attributes + * + * FIXME + */ + +/** + * cogl_attribute_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_attribute_get_gtype (void); + +/** + * cogl_attribute_new: (constructor) + * @attribute_buffer: The #CoglAttributeBuffer containing the actual + * attribute data + * @name: The name of the attribute (used to reference it from GLSL) + * @stride: The number of bytes to jump to get to the next attribute + * value for the next vertex. (Usually + * sizeof (MyVertex)) + * @offset: The byte offset from the start of @attribute_buffer for + * the first attribute value. (Usually + * offsetof (MyVertex, component0) + * @components: The number of components (e.g. 4 for an rgba color or + * 3 for and (x,y,z) position) + * @type: FIXME + * + * Describes the layout for a list of vertex attribute values (For + * example, a list of texture coordinates or colors). + * + * The @name is used to access the attribute inside a GLSL vertex + * shader and there are some special names you should use if they are + * applicable: + * + * "cogl_position_in" (used for vertex positions) + * "cogl_color_in" (used for vertex colors) + * "cogl_tex_coord0_in", "cogl_tex_coord1", ... + * (used for vertex texture coordinates) + * "cogl_normal_in" (used for vertex normals) + * "cogl_point_size_in" (used to set the size of points + * per-vertex. Note this can only be used if + * %COGL_FEATURE_ID_POINT_SIZE_ATTRIBUTE is advertised and + * cogl_pipeline_set_per_vertex_point_size() is called on the pipeline. + * + * + * + * The attribute values corresponding to different vertices can either + * be tightly packed or interleaved with other attribute values. For + * example it's common to define a structure for a single vertex like: + * |[ + * typedef struct + * { + * float x, y, z; /* position attribute */ + * float s, t; /* texture coordinate attribute */ + * } MyVertex; + * ]| + * + * And then create an array of vertex data something like: + * |[ + * MyVertex vertices[100] = { .... } + * ]| + * + * In this case, to describe either the position or texture coordinate + * attribute you have to move sizeof (MyVertex) bytes to + * move from one vertex to the next. This is called the attribute + * @stride. If you weren't interleving attributes and you instead had + * a packed array of float x, y pairs then the attribute stride would + * be (2 * sizeof (float)). So the @stride is the number of + * bytes to move to find the attribute value of the next vertex. + * + * Normally a list of attributes starts at the beginning of an array. + * So for the MyVertex example above the @offset is the + * offset inside the MyVertex structure to the first + * component of the attribute. For the texture coordinate attribute + * the offset would be offsetof (MyVertex, s) or instead of + * using the offsetof macro you could use sizeof (float) * + * 3. If you've divided your @array into blocks of non-interleved + * attributes then you will need to calculate the @offset as the number of + * bytes in blocks preceding the attribute you're describing. + * + * An attribute often has more than one component. For example a color + * is often comprised of 4 red, green, blue and alpha @components, and a + * position may be comprised of 2 x and y @components. You should aim + * to keep the number of components to a minimum as more components + * means more data needs to be mapped into the GPU which can be a + * bottlneck when dealing with a large number of vertices. + * + * Finally you need to specify the component data type. Here you + * should aim to use the smallest type that meets your precision + * requirements. Again the larger the type then more data needs to be + * mapped into the GPU which can be a bottlneck when dealing with + * a large number of vertices. + * + * Return value: (transfer full): A newly allocated #CoglAttribute + * describing the layout for a list of attribute values + * stored in @array. + * + * Since: 1.4 + * Stability: Unstable + */ +/* XXX: look for a precedent to see if the stride/offset args should + * have a different order. */ +CoglAttribute * +cogl_attribute_new (CoglAttributeBuffer *attribute_buffer, + const char *name, + size_t stride, + size_t offset, + int components, + CoglAttributeType type); + +/** + * cogl_attribute_new_const_1f: + * @context: A #CoglContext + * @name: The name of the attribute (used to reference it from GLSL) + * @value: The constant value for the attribute + * + * Creates a new, single component, attribute whose value remains + * constant across all the vertices of a primitive without needing to + * duplicate the value for each vertex. + * + * The constant @value is a single precision floating point scalar + * which should have a corresponding declaration in GLSL code like: + * + * [| + * attribute float name; + * |] + * + * Return value: (transfer full): A newly allocated #CoglAttribute + * representing the given constant @value. + */ +CoglAttribute * +cogl_attribute_new_const_1f (CoglContext *context, + const char *name, + float value); + +/** + * cogl_attribute_new_const_2f: + * @context: A #CoglContext + * @name: The name of the attribute (used to reference it from GLSL) + * @component0: The first component of a 2 component vector + * @component1: The second component of a 2 component vector + * + * Creates a new, 2 component, attribute whose value remains + * constant across all the vertices of a primitive without needing to + * duplicate the value for each vertex. + * + * The constants (@component0, @component1) represent a 2 component + * float vector which should have a corresponding declaration in GLSL + * code like: + * + * [| + * attribute vec2 name; + * |] + * + * Return value: (transfer full): A newly allocated #CoglAttribute + * representing the given constant vector. + */ +CoglAttribute * +cogl_attribute_new_const_2f (CoglContext *context, + const char *name, + float component0, + float component1); + +/** + * cogl_attribute_new_const_3f: + * @context: A #CoglContext + * @name: The name of the attribute (used to reference it from GLSL) + * @component0: The first component of a 3 component vector + * @component1: The second component of a 3 component vector + * @component2: The third component of a 3 component vector + * + * Creates a new, 3 component, attribute whose value remains + * constant across all the vertices of a primitive without needing to + * duplicate the value for each vertex. + * + * The constants (@component0, @component1, @component2) represent a 3 + * component float vector which should have a corresponding + * declaration in GLSL code like: + * + * [| + * attribute vec3 name; + * |] + * + * unless the built in name "cogl_normal_in" is being used where no + * explicit GLSL declaration need be made. + * + * Return value: (transfer full): A newly allocated #CoglAttribute + * representing the given constant vector. + */ +CoglAttribute * +cogl_attribute_new_const_3f (CoglContext *context, + const char *name, + float component0, + float component1, + float component2); + +/** + * cogl_attribute_new_const_4f: + * @context: A #CoglContext + * @name: The name of the attribute (used to reference it from GLSL) + * @component0: The first component of a 4 component vector + * @component1: The second component of a 4 component vector + * @component2: The third component of a 4 component vector + * @component3: The fourth component of a 4 component vector + * + * Creates a new, 4 component, attribute whose value remains + * constant across all the vertices of a primitive without needing to + * duplicate the value for each vertex. + * + * The constants (@component0, @component1, @component2, @constant3) + * represent a 4 component float vector which should have a + * corresponding declaration in GLSL code like: + * + * [| + * attribute vec4 name; + * |] + * + * unless one of the built in names "cogl_color_in", + * "cogl_tex_coord0_in or "cogl_tex_coord1_in" etc is being used where + * no explicit GLSL declaration need be made. + * + * Return value: (transfer full): A newly allocated #CoglAttribute + * representing the given constant vector. + */ +CoglAttribute * +cogl_attribute_new_const_4f (CoglContext *context, + const char *name, + float component0, + float component1, + float component2, + float component3); + +/** + * cogl_attribute_new_const_2fv: + * @context: A #CoglContext + * @name: The name of the attribute (used to reference it from GLSL) + * @value: A pointer to a 2 component float vector + * + * Creates a new, 2 component, attribute whose value remains + * constant across all the vertices of a primitive without needing to + * duplicate the value for each vertex. + * + * The constants (value[0], value[1]) represent a 2 component float + * vector which should have a corresponding declaration in GLSL code + * like: + * + * [| + * attribute vec2 name; + * |] + * + * Return value: (transfer full): A newly allocated #CoglAttribute + * representing the given constant vector. + */ +CoglAttribute * +cogl_attribute_new_const_2fv (CoglContext *context, + const char *name, + const float *value); + +/** + * cogl_attribute_new_const_3fv: + * @context: A #CoglContext + * @name: The name of the attribute (used to reference it from GLSL) + * @value: A pointer to a 3 component float vector + * + * Creates a new, 3 component, attribute whose value remains + * constant across all the vertices of a primitive without needing to + * duplicate the value for each vertex. + * + * The constants (value[0], value[1], value[2]) represent a 3 + * component float vector which should have a corresponding + * declaration in GLSL code like: + * + * [| + * attribute vec3 name; + * |] + * + * unless the built in name "cogl_normal_in" is being used where no + * explicit GLSL declaration need be made. + * + * Return value: (transfer full): A newly allocated #CoglAttribute + * representing the given constant vector. + */ +CoglAttribute * +cogl_attribute_new_const_3fv (CoglContext *context, + const char *name, + const float *value); + +/** + * cogl_attribute_new_const_4fv: + * @context: A #CoglContext + * @name: The name of the attribute (used to reference it from GLSL) + * @value: A pointer to a 4 component float vector + * + * Creates a new, 4 component, attribute whose value remains + * constant across all the vertices of a primitive without needing to + * duplicate the value for each vertex. + * + * The constants (value[0], value[1], value[2], value[3]) represent a + * 4 component float vector which should have a corresponding + * declaration in GLSL code like: + * + * [| + * attribute vec4 name; + * |] + * + * unless one of the built in names "cogl_color_in", + * "cogl_tex_coord0_in or "cogl_tex_coord1_in" etc is being used where + * no explicit GLSL declaration need be made. + * + * Return value: (transfer full): A newly allocated #CoglAttribute + * representing the given constant vector. + */ +CoglAttribute * +cogl_attribute_new_const_4fv (CoglContext *context, + const char *name, + const float *value); + +/** + * cogl_attribute_new_const_2x2fv: + * @context: A #CoglContext + * @name: The name of the attribute (used to reference it from GLSL) + * @matrix2x2: A pointer to a 2 by 2 matrix + * @transpose: Whether the matrix should be transposed on upload or + * not + * + * Creates a new matrix attribute whose value remains constant + * across all the vertices of a primitive without needing to duplicate + * the value for each vertex. + * + * @matrix2x2 represent a square 2 by 2 matrix specified in + * column-major order (each pair of consecutive numbers represents a + * column) which should have a corresponding declaration in GLSL code + * like: + * + * [| + * attribute mat2 name; + * |] + * + * If @transpose is %TRUE then all matrix components are rotated + * around the diagonal of the matrix such that the first column + * becomes the first row and the second column becomes the second row. + * + * Return value: (transfer full): A newly allocated #CoglAttribute + * representing the given constant matrix. + */ +CoglAttribute * +cogl_attribute_new_const_2x2fv (CoglContext *context, + const char *name, + const float *matrix2x2, + CoglBool transpose); + +/** + * cogl_attribute_new_const_3x3fv: + * @context: A #CoglContext + * @name: The name of the attribute (used to reference it from GLSL) + * @matrix3x3: A pointer to a 3 by 3 matrix + * @transpose: Whether the matrix should be transposed on upload or + * not + * + * Creates a new matrix attribute whose value remains constant + * across all the vertices of a primitive without needing to duplicate + * the value for each vertex. + * + * @matrix3x3 represent a square 3 by 3 matrix specified in + * column-major order (each triple of consecutive numbers represents a + * column) which should have a corresponding declaration in GLSL code + * like: + * + * [| + * attribute mat3 name; + * |] + * + * If @transpose is %TRUE then all matrix components are rotated + * around the diagonal of the matrix such that the first column + * becomes the first row and the second column becomes the second row + * etc. + * + * Return value: (transfer full): A newly allocated #CoglAttribute + * representing the given constant matrix. + */ +CoglAttribute * +cogl_attribute_new_const_3x3fv (CoglContext *context, + const char *name, + const float *matrix3x3, + CoglBool transpose); + +/** + * cogl_attribute_new_const_4x4fv: + * @context: A #CoglContext + * @name: The name of the attribute (used to reference it from GLSL) + * @matrix4x4: A pointer to a 4 by 4 matrix + * @transpose: Whether the matrix should be transposed on upload or + * not + * + * Creates a new matrix attribute whose value remains constant + * across all the vertices of a primitive without needing to duplicate + * the value for each vertex. + * + * @matrix4x4 represent a square 4 by 4 matrix specified in + * column-major order (each 4-tuple of consecutive numbers represents a + * column) which should have a corresponding declaration in GLSL code + * like: + * + * [| + * attribute mat4 name; + * |] + * + * If @transpose is %TRUE then all matrix components are rotated + * around the diagonal of the matrix such that the first column + * becomes the first row and the second column becomes the second row + * etc. + * + * Return value: (transfer full): A newly allocated #CoglAttribute + * representing the given constant matrix. + */ +CoglAttribute * +cogl_attribute_new_const_4x4fv (CoglContext *context, + const char *name, + const float *matrix4x4, + CoglBool transpose); + +/** + * cogl_attribute_set_normalized: + * @attribute: A #CoglAttribute + * @normalized: The new value for the normalized property. + * + * Sets whether fixed point attribute types are mapped to the range + * 0→1. For example when this property is TRUE and a + * %COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE type is used then the value 255 + * will be mapped to 1.0. + * + * The default value of this property depends on the name of the + * attribute. For the builtin properties cogl_color_in and + * cogl_normal_in it will default to TRUE and for all other names it + * will default to FALSE. + * + * Stability: unstable + * Since: 1.10 + */ +void +cogl_attribute_set_normalized (CoglAttribute *attribute, + CoglBool normalized); + +/** + * cogl_attribute_get_normalized: + * @attribute: A #CoglAttribute + * + * Return value: the value of the normalized property set with + * cogl_attribute_set_normalized(). + * + * Stability: unstable + * Since: 1.10 + */ +CoglBool +cogl_attribute_get_normalized (CoglAttribute *attribute); + +/** + * cogl_attribute_get_buffer: + * @attribute: A #CoglAttribute + * + * Return value: (transfer none): the #CoglAttributeBuffer that was + * set with cogl_attribute_set_buffer() or cogl_attribute_new(). + * + * Stability: unstable + * Since: 1.10 + */ +CoglAttributeBuffer * +cogl_attribute_get_buffer (CoglAttribute *attribute); + +/** + * cogl_attribute_set_buffer: + * @attribute: A #CoglAttribute + * @attribute_buffer: A #CoglAttributeBuffer + * + * Sets a new #CoglAttributeBuffer for the attribute. + * + * Stability: unstable + * Since: 1.10 + */ +void +cogl_attribute_set_buffer (CoglAttribute *attribute, + CoglAttributeBuffer *attribute_buffer); + +/** + * cogl_is_attribute: + * @object: A #CoglObject + * + * Gets whether the given object references a #CoglAttribute. + * + * Return value: %TRUE if the @object references a #CoglAttribute, + * %FALSE otherwise + */ +CoglBool +cogl_is_attribute (void *object); + +COGL_END_DECLS + +#endif /* __COGL_ATTRIBUTE_H__ */ + diff --git a/cogl/cogl/cogl-bitmap-conversion.c b/cogl/cogl/cogl-bitmap-conversion.c new file mode 100644 index 0000000..9748aca --- /dev/null +++ b/cogl/cogl/cogl-bitmap-conversion.c @@ -0,0 +1,748 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-private.h" +#include "cogl-bitmap-private.h" +#include "cogl-context-private.h" +#include "cogl-texture-private.h" + +#include + +#define component_type uint8_t +#define component_size 8 +/* We want to specially optimise the packing when we are converting + to/from an 8-bit type so that it won't do anything. That way for + example if we are just doing a swizzle conversion then the inner + loop for the conversion will be really simple */ +#define UNPACK_BYTE(b) (b) +#define PACK_BYTE(b) (b) +#include "cogl-bitmap-packing.h" +#undef PACK_BYTE +#undef UNPACK_BYTE +#undef component_type +#undef component_size + +#define component_type uint16_t +#define component_size 16 +#define UNPACK_BYTE(b) (((b) * 65535 + 127) / 255) +#define PACK_BYTE(b) (((b) * 255 + 32767) / 65535) +#include "cogl-bitmap-packing.h" +#undef PACK_BYTE +#undef UNPACK_BYTE +#undef component_type +#undef component_size + +/* (Un)Premultiplication */ + +inline static void +_cogl_unpremult_alpha_0 (uint8_t *dst) +{ + dst[0] = 0; + dst[1] = 0; + dst[2] = 0; + dst[3] = 0; +} + +inline static void +_cogl_unpremult_alpha_last (uint8_t *dst) +{ + uint8_t alpha = dst[3]; + + dst[0] = (dst[0] * 255) / alpha; + dst[1] = (dst[1] * 255) / alpha; + dst[2] = (dst[2] * 255) / alpha; +} + +inline static void +_cogl_unpremult_alpha_first (uint8_t *dst) +{ + uint8_t alpha = dst[0]; + + dst[1] = (dst[1] * 255) / alpha; + dst[2] = (dst[2] * 255) / alpha; + dst[3] = (dst[3] * 255) / alpha; +} + +/* No division form of floor((c*a + 128)/255) (I first encountered + * this in the RENDER implementation in the X server.) Being exact + * is important for a == 255 - we want to get exactly c. + */ +#define MULT(d,a,t) \ + G_STMT_START { \ + t = d * a + 128; \ + d = ((t >> 8) + t) >> 8; \ + } G_STMT_END + +inline static void +_cogl_premult_alpha_last (uint8_t *dst) +{ + uint8_t alpha = dst[3]; + /* Using a separate temporary per component has given slightly better + * code generation with GCC in the past; it shouldn't do any worse in + * any case. + */ + unsigned int t1, t2, t3; + MULT(dst[0], alpha, t1); + MULT(dst[1], alpha, t2); + MULT(dst[2], alpha, t3); +} + +inline static void +_cogl_premult_alpha_first (uint8_t *dst) +{ + uint8_t alpha = dst[0]; + unsigned int t1, t2, t3; + + MULT(dst[1], alpha, t1); + MULT(dst[2], alpha, t2); + MULT(dst[3], alpha, t3); +} + +#undef MULT + +/* Use the SSE optimized version to premult four pixels at once when + it is available. The same assembler code works for x86 and x86-64 + because it doesn't refer to any non-SSE registers directly */ +#if defined(__SSE2__) && defined(__GNUC__) \ + && (defined(__x86_64) || defined(__i386)) +#define COGL_USE_PREMULT_SSE2 +#endif + +#ifdef COGL_USE_PREMULT_SSE2 + +inline static void +_cogl_premult_alpha_last_four_pixels_sse2 (uint8_t *p) +{ + /* 8 copies of 128 used below */ + static const int16_t eight_halves[8] __attribute__ ((aligned (16))) = + { 128, 128, 128, 128, 128, 128, 128, 128 }; + /* Mask of the rgb components of the four pixels */ + static const int8_t just_rgb[16] __attribute__ ((aligned (16))) = + { 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00 }; + /* Each SSE register only holds two pixels because we need to work + with 16-bit intermediate values. We still do four pixels by + interleaving two registers in the hope that it will pipeline + better */ + asm (/* Load eight_halves into xmm5 for later */ + "movdqa (%1), %%xmm5\n" + /* Clear xmm3 */ + "pxor %%xmm3, %%xmm3\n" + /* Load two pixels from p into the low half of xmm0 */ + "movlps (%0), %%xmm0\n" + /* Load the next set of two pixels from p into the low half of xmm1 */ + "movlps 8(%0), %%xmm1\n" + /* Unpack 8 bytes from the low quad-words in each register to 8 + 16-bit values */ + "punpcklbw %%xmm3, %%xmm0\n" + "punpcklbw %%xmm3, %%xmm1\n" + /* Copy alpha values of the first pixel in xmm0 to all + components of the first pixel in xmm2 */ + "pshuflw $255, %%xmm0, %%xmm2\n" + /* same for xmm1 and xmm3 */ + "pshuflw $255, %%xmm1, %%xmm3\n" + /* The above also copies the second pixel directly so we now + want to replace the RGB components with copies of the alpha + components */ + "pshufhw $255, %%xmm2, %%xmm2\n" + "pshufhw $255, %%xmm3, %%xmm3\n" + /* Multiply the rgb components by the alpha */ + "pmullw %%xmm2, %%xmm0\n" + "pmullw %%xmm3, %%xmm1\n" + /* Add 128 to each component */ + "paddw %%xmm5, %%xmm0\n" + "paddw %%xmm5, %%xmm1\n" + /* Copy the results to temporary registers xmm4 and xmm5 */ + "movdqa %%xmm0, %%xmm4\n" + "movdqa %%xmm1, %%xmm5\n" + /* Divide the results by 256 */ + "psrlw $8, %%xmm0\n" + "psrlw $8, %%xmm1\n" + /* Add the temporaries back in */ + "paddw %%xmm4, %%xmm0\n" + "paddw %%xmm5, %%xmm1\n" + /* Divide again */ + "psrlw $8, %%xmm0\n" + "psrlw $8, %%xmm1\n" + /* Pack the results back as bytes */ + "packuswb %%xmm1, %%xmm0\n" + /* Load just_rgb into xmm3 for later */ + "movdqa (%2), %%xmm3\n" + /* Reload all four pixels into xmm2 */ + "movups (%0), %%xmm2\n" + /* Mask out the alpha from the results */ + "andps %%xmm3, %%xmm0\n" + /* Mask out the RGB from the original four pixels */ + "andnps %%xmm2, %%xmm3\n" + /* Combine the two to get the right alpha values */ + "orps %%xmm3, %%xmm0\n" + /* Write to memory */ + "movdqu %%xmm0, (%0)\n" + : /* no outputs */ + : "r" (p), "r" (eight_halves), "r" (just_rgb) + : "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"); +} + +#endif /* COGL_USE_PREMULT_SSE2 */ + +static void +_cogl_bitmap_premult_unpacked_span_8 (uint8_t *data, + int width) +{ +#ifdef COGL_USE_PREMULT_SSE2 + + /* Process 4 pixels at a time */ + while (width >= 4) + { + _cogl_premult_alpha_last_four_pixels_sse2 (data); + data += 4 * 4; + width -= 4; + } + + /* If there are any pixels left we will fall through and + handle them below */ + +#endif /* COGL_USE_PREMULT_SSE2 */ + + while (width-- > 0) + { + _cogl_premult_alpha_last (data); + data += 4; + } +} + +static void +_cogl_bitmap_unpremult_unpacked_span_8 (uint8_t *data, + int width) +{ + int x; + + for (x = 0; x < width; x++) + { + if (data[3] == 0) + _cogl_unpremult_alpha_0 (data); + else + _cogl_unpremult_alpha_last (data); + data += 4; + } +} + +static void +_cogl_bitmap_unpremult_unpacked_span_16 (uint16_t *data, + int width) +{ + while (width-- > 0) + { + uint16_t alpha = data[3]; + + if (alpha == 0) + memset (data, 0, sizeof (uint16_t) * 3); + else + { + data[0] = (data[0] * 65535) / alpha; + data[1] = (data[1] * 65535) / alpha; + data[2] = (data[2] * 65535) / alpha; + } + } +} + +static void +_cogl_bitmap_premult_unpacked_span_16 (uint16_t *data, + int width) +{ + while (width-- > 0) + { + uint16_t alpha = data[3]; + + data[0] = (data[0] * alpha) / 65535; + data[1] = (data[1] * alpha) / 65535; + data[2] = (data[2] * alpha) / 65535; + } +} + +static CoglBool +_cogl_bitmap_can_fast_premult (CoglPixelFormat format) +{ + switch (format & ~COGL_PREMULT_BIT) + { + case COGL_PIXEL_FORMAT_RGBA_8888: + case COGL_PIXEL_FORMAT_BGRA_8888: + case COGL_PIXEL_FORMAT_ARGB_8888: + case COGL_PIXEL_FORMAT_ABGR_8888: + return TRUE; + + default: + return FALSE; + } +} + +static CoglBool +_cogl_bitmap_needs_short_temp_buffer (CoglPixelFormat format) +{ + /* If the format is using more than 8 bits per component then we'll + unpack into a 16-bit per component buffer instead of 8-bit so we + won't lose as much precision. If we ever add support for formats + with more than 16 bits for at least one of the components then we + should probably do something else here, maybe convert to + floats */ + switch (format) + { + case COGL_PIXEL_FORMAT_DEPTH_16: + case COGL_PIXEL_FORMAT_DEPTH_32: + case COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8: + case COGL_PIXEL_FORMAT_ANY: + case COGL_PIXEL_FORMAT_YUV: + g_assert_not_reached (); + + case COGL_PIXEL_FORMAT_A_8: + case COGL_PIXEL_FORMAT_RG_88: + case COGL_PIXEL_FORMAT_RGB_565: + case COGL_PIXEL_FORMAT_RGBA_4444: + case COGL_PIXEL_FORMAT_RGBA_5551: + case COGL_PIXEL_FORMAT_G_8: + case COGL_PIXEL_FORMAT_RGB_888: + case COGL_PIXEL_FORMAT_BGR_888: + case COGL_PIXEL_FORMAT_RGBA_8888: + case COGL_PIXEL_FORMAT_BGRA_8888: + case COGL_PIXEL_FORMAT_ARGB_8888: + case COGL_PIXEL_FORMAT_ABGR_8888: + case COGL_PIXEL_FORMAT_RGBA_8888_PRE: + case COGL_PIXEL_FORMAT_BGRA_8888_PRE: + case COGL_PIXEL_FORMAT_ARGB_8888_PRE: + case COGL_PIXEL_FORMAT_ABGR_8888_PRE: + case COGL_PIXEL_FORMAT_RGBA_4444_PRE: + case COGL_PIXEL_FORMAT_RGBA_5551_PRE: + return FALSE; + + case COGL_PIXEL_FORMAT_RGBA_1010102: + case COGL_PIXEL_FORMAT_BGRA_1010102: + case COGL_PIXEL_FORMAT_ARGB_2101010: + case COGL_PIXEL_FORMAT_ABGR_2101010: + case COGL_PIXEL_FORMAT_RGBA_1010102_PRE: + case COGL_PIXEL_FORMAT_BGRA_1010102_PRE: + case COGL_PIXEL_FORMAT_ARGB_2101010_PRE: + case COGL_PIXEL_FORMAT_ABGR_2101010_PRE: + return TRUE; + } + + g_assert_not_reached (); +} + +CoglBool +_cogl_bitmap_convert_into_bitmap (CoglBitmap *src_bmp, + CoglBitmap *dst_bmp, + CoglError **error) +{ + uint8_t *src_data; + uint8_t *dst_data; + uint8_t *src; + uint8_t *dst; + void *tmp_row; + int src_rowstride; + int dst_rowstride; + int y; + int width, height; + CoglPixelFormat src_format; + CoglPixelFormat dst_format; + CoglBool use_16; + CoglBool need_premult; + + src_format = cogl_bitmap_get_format (src_bmp); + src_rowstride = cogl_bitmap_get_rowstride (src_bmp); + dst_format = cogl_bitmap_get_format (dst_bmp); + dst_rowstride = cogl_bitmap_get_rowstride (dst_bmp); + width = cogl_bitmap_get_width (src_bmp); + height = cogl_bitmap_get_height (src_bmp); + + _COGL_RETURN_VAL_IF_FAIL (width == cogl_bitmap_get_width (dst_bmp), FALSE); + _COGL_RETURN_VAL_IF_FAIL (height == cogl_bitmap_get_height (dst_bmp), FALSE); + + need_premult + = ((src_format & COGL_PREMULT_BIT) != (dst_format & COGL_PREMULT_BIT) && + src_format != COGL_PIXEL_FORMAT_A_8 && + dst_format != COGL_PIXEL_FORMAT_A_8 && + (src_format & dst_format & COGL_A_BIT)); + + /* If the base format is the same then we can just copy the bitmap + instead */ + if ((src_format & ~COGL_PREMULT_BIT) == (dst_format & ~COGL_PREMULT_BIT) && + (!need_premult || _cogl_bitmap_can_fast_premult (dst_format))) + { + if (!_cogl_bitmap_copy_subregion (src_bmp, dst_bmp, + 0, 0, /* src_x / src_y */ + 0, 0, /* dst_x / dst_y */ + width, height, + error)) + return FALSE; + + if (need_premult) + { + if ((dst_format & COGL_PREMULT_BIT)) + { + if (!_cogl_bitmap_premult (dst_bmp, error)) + return FALSE; + } + else + { + if (!_cogl_bitmap_unpremult (dst_bmp, error)) + return FALSE; + } + } + + return TRUE; + } + + src_data = _cogl_bitmap_map (src_bmp, COGL_BUFFER_ACCESS_READ, 0, error); + if (src_data == NULL) + return FALSE; + dst_data = _cogl_bitmap_map (dst_bmp, + COGL_BUFFER_ACCESS_WRITE, + COGL_BUFFER_MAP_HINT_DISCARD, + error); + if (dst_data == NULL) + { + _cogl_bitmap_unmap (src_bmp); + return FALSE; + } + + use_16 = _cogl_bitmap_needs_short_temp_buffer (dst_format); + + /* Allocate a buffer to hold a temporary RGBA row */ + tmp_row = g_malloc (width * + (use_16 ? sizeof (uint16_t) : sizeof (uint8_t)) * 4); + + /* FIXME: Optimize */ + for (y = 0; y < height; y++) + { + src = src_data + y * src_rowstride; + dst = dst_data + y * dst_rowstride; + + if (use_16) + _cogl_unpack_16 (src_format, src, tmp_row, width); + else + _cogl_unpack_8 (src_format, src, tmp_row, width); + + /* Handle premultiplication */ + if (need_premult) + { + if (dst_format & COGL_PREMULT_BIT) + { + if (use_16) + _cogl_bitmap_premult_unpacked_span_16 (tmp_row, width); + else + _cogl_bitmap_premult_unpacked_span_8 (tmp_row, width); + } + else + { + if (use_16) + _cogl_bitmap_unpremult_unpacked_span_16 (tmp_row, width); + else + _cogl_bitmap_unpremult_unpacked_span_8 (tmp_row, width); + } + } + + if (use_16) + _cogl_pack_16 (dst_format, tmp_row, dst, width); + else + _cogl_pack_8 (dst_format, tmp_row, dst, width); + } + + _cogl_bitmap_unmap (src_bmp); + _cogl_bitmap_unmap (dst_bmp); + + g_free (tmp_row); + + return TRUE; +} + +CoglBitmap * +_cogl_bitmap_convert (CoglBitmap *src_bmp, + CoglPixelFormat dst_format, + CoglError **error) +{ + CoglBitmap *dst_bmp; + int width, height; + + _COGL_GET_CONTEXT (ctx, NULL); + + width = cogl_bitmap_get_width (src_bmp); + height = cogl_bitmap_get_height (src_bmp); + + dst_bmp = _cogl_bitmap_new_with_malloc_buffer (ctx, + width, height, + dst_format, + error); + if (!dst_bmp) + return NULL; + + if (!_cogl_bitmap_convert_into_bitmap (src_bmp, dst_bmp, error)) + { + cogl_object_unref (dst_bmp); + return NULL; + } + + return dst_bmp; +} + +static CoglBool +driver_can_convert (CoglContext *ctx, + CoglPixelFormat src_format, + CoglPixelFormat internal_format) +{ + if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_FORMAT_CONVERSION)) + return FALSE; + + if (src_format == internal_format) + return TRUE; + + /* If the driver doesn't natively support alpha textures then it + * won't work correctly to convert to/from component-alpha + * textures */ + if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_ALPHA_TEXTURES) && + (src_format == COGL_PIXEL_FORMAT_A_8 || + internal_format == COGL_PIXEL_FORMAT_A_8)) + return FALSE; + + /* Same for red-green textures. If red-green textures aren't + * supported then the internal format should never be RG_88 but we + * should still be able to convert from an RG source image */ + if (!cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_RG) && + src_format == COGL_PIXEL_FORMAT_RG_88) + return FALSE; + + return TRUE; +} + +CoglBitmap * +_cogl_bitmap_convert_for_upload (CoglBitmap *src_bmp, + CoglPixelFormat internal_format, + CoglBool can_convert_in_place, + CoglError **error) +{ + CoglContext *ctx = _cogl_bitmap_get_context (src_bmp); + CoglPixelFormat src_format = cogl_bitmap_get_format (src_bmp); + CoglBitmap *dst_bmp; + + _COGL_RETURN_VAL_IF_FAIL (internal_format != COGL_PIXEL_FORMAT_ANY, NULL); + + /* OpenGL supports specifying a different format for the internal + format when uploading texture data. We should use this to convert + formats because it is likely to be faster and support more types + than the Cogl bitmap code. However under GLES the internal format + must be the same as the bitmap format and it only supports a + limited number of formats so we must convert using the Cogl + bitmap code instead */ + + if (driver_can_convert (ctx, src_format, internal_format)) + { + /* If the source format does not have the same premult flag as the + internal_format then we need to copy and convert it */ + if (_cogl_texture_needs_premult_conversion (src_format, + internal_format)) + { + if (can_convert_in_place) + { + if (_cogl_bitmap_convert_premult_status (src_bmp, + (src_format ^ + COGL_PREMULT_BIT), + error)) + { + dst_bmp = cogl_object_ref (src_bmp); + } + else + return NULL; + } + else + { + dst_bmp = _cogl_bitmap_convert (src_bmp, + src_format ^ COGL_PREMULT_BIT, + error); + if (dst_bmp == NULL) + return NULL; + } + } + else + dst_bmp = cogl_object_ref (src_bmp); + } + else + { + CoglPixelFormat closest_format; + + closest_format = + ctx->driver_vtable->pixel_format_to_gl (ctx, + internal_format, + NULL, /* ignore gl intformat */ + NULL, /* ignore gl format */ + NULL); /* ignore gl type */ + + if (closest_format != src_format) + dst_bmp = _cogl_bitmap_convert (src_bmp, closest_format, error); + else + dst_bmp = cogl_object_ref (src_bmp); + } + + return dst_bmp; +} + +CoglBool +_cogl_bitmap_unpremult (CoglBitmap *bmp, + CoglError **error) +{ + uint8_t *p, *data; + uint16_t *tmp_row; + int x,y; + CoglPixelFormat format; + int width, height; + int rowstride; + + format = cogl_bitmap_get_format (bmp); + width = cogl_bitmap_get_width (bmp); + height = cogl_bitmap_get_height (bmp); + rowstride = cogl_bitmap_get_rowstride (bmp); + + if ((data = _cogl_bitmap_map (bmp, + COGL_BUFFER_ACCESS_READ | + COGL_BUFFER_ACCESS_WRITE, + 0, + error)) == NULL) + return FALSE; + + /* If we can't directly unpremult the data inline then we'll + allocate a temporary row and unpack the data. This assumes if we + can fast premult then we can also fast unpremult */ + if (_cogl_bitmap_can_fast_premult (format)) + tmp_row = NULL; + else + tmp_row = g_malloc (sizeof (uint16_t) * 4 * width); + + for (y = 0; y < height; y++) + { + p = (uint8_t*) data + y * rowstride; + + if (tmp_row) + { + _cogl_unpack_16 (format, p, tmp_row, width); + _cogl_bitmap_unpremult_unpacked_span_16 (tmp_row, width); + _cogl_pack_16 (format, tmp_row, p, width); + } + else + { + if (format & COGL_AFIRST_BIT) + { + for (x = 0; x < width; x++) + { + if (p[0] == 0) + _cogl_unpremult_alpha_0 (p); + else + _cogl_unpremult_alpha_first (p); + p += 4; + } + } + else + _cogl_bitmap_unpremult_unpacked_span_8 (p, width); + } + } + + g_free (tmp_row); + + _cogl_bitmap_unmap (bmp); + + _cogl_bitmap_set_format (bmp, format & ~COGL_PREMULT_BIT); + + return TRUE; +} + +CoglBool +_cogl_bitmap_premult (CoglBitmap *bmp, + CoglError **error) +{ + uint8_t *p, *data; + uint16_t *tmp_row; + int x,y; + CoglPixelFormat format; + int width, height; + int rowstride; + + format = cogl_bitmap_get_format (bmp); + width = cogl_bitmap_get_width (bmp); + height = cogl_bitmap_get_height (bmp); + rowstride = cogl_bitmap_get_rowstride (bmp); + + if ((data = _cogl_bitmap_map (bmp, + COGL_BUFFER_ACCESS_READ | + COGL_BUFFER_ACCESS_WRITE, + 0, + error)) == NULL) + return FALSE; + + /* If we can't directly premult the data inline then we'll allocate + a temporary row and unpack the data. */ + if (_cogl_bitmap_can_fast_premult (format)) + tmp_row = NULL; + else + tmp_row = g_malloc (sizeof (uint16_t) * 4 * width); + + for (y = 0; y < height; y++) + { + p = (uint8_t*) data + y * rowstride; + + if (tmp_row) + { + _cogl_unpack_16 (format, p, tmp_row, width); + _cogl_bitmap_premult_unpacked_span_16 (tmp_row, width); + _cogl_pack_16 (format, tmp_row, p, width); + } + else + { + if (format & COGL_AFIRST_BIT) + { + for (x = 0; x < width; x++) + { + _cogl_premult_alpha_first (p); + p += 4; + } + } + else + _cogl_bitmap_premult_unpacked_span_8 (p, width); + } + } + + g_free (tmp_row); + + _cogl_bitmap_unmap (bmp); + + _cogl_bitmap_set_format (bmp, format | COGL_PREMULT_BIT); + + return TRUE; +} diff --git a/cogl/cogl/cogl-bitmap-packing.h b/cogl/cogl/cogl-bitmap-packing.h new file mode 100644 index 0000000..1b8e140 --- /dev/null +++ b/cogl/cogl/cogl-bitmap-packing.h @@ -0,0 +1,767 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +/* This file is included multiple times with different definitions for + the component_type type (either uint8_t or uint16_t). The code ends + up exactly the same for both but we only want to end up hitting the + 16-bit path when one of the types in the conversion is > 8 bits per + component. */ + +/* Unpacking to RGBA */ + +#define UNPACK_1(b) ((b) * ((1 << (sizeof (component_type) * 8)) - 1)) +#define UNPACK_2(b) (((b) * ((1 << (sizeof (component_type) * 8)) - 1) + \ + 1) / 3) +#define UNPACK_4(b) (((b) * ((1 << (sizeof (component_type) * 8)) - 1) + \ + 7) / 15) +#define UNPACK_5(b) (((b) * ((1 << (sizeof (component_type) * 8)) - 1) + \ + 15) / 31) +#define UNPACK_6(b) (((b) * ((1 << (sizeof (component_type) * 8)) - 1) + \ + 31) / 63) +#define UNPACK_10(b) (((b) * ((1 << (sizeof (component_type) * 8)) - 1) + \ + 511) / 1023) + +inline static void +G_PASTE (_cogl_unpack_a_8_, component_size) (const uint8_t *src, + component_type *dst, + int width) +{ + while (width-- > 0) + { + dst[0] = 0; + dst[1] = 0; + dst[2] = 0; + dst[3] = UNPACK_BYTE (*src); + dst += 4; + src++; + } +} + +inline static void +G_PASTE (_cogl_unpack_g_8_, component_size) (const uint8_t *src, + component_type *dst, + int width) +{ + /* FIXME: I'm not sure if this is right. It looks like Nvidia and + Mesa handle luminance textures differently. Maybe we should + consider just removing luminance textures for Cogl 2.0 because + they have been removed in GL 3.0 */ + while (width-- > 0) + { + component_type v = UNPACK_BYTE (src[0]); + dst[0] = v; + dst[1] = v; + dst[2] = v; + dst[3] = UNPACK_BYTE (255); + dst += 4; + src++; + } +} + +inline static void +G_PASTE (_cogl_unpack_rg_88_, component_size) (const uint8_t *src, + component_type *dst, + int width) +{ + while (width-- > 0) + { + dst[0] = UNPACK_BYTE (src[0]); + dst[1] = UNPACK_BYTE (src[1]); + dst[2] = 0; + dst[3] = UNPACK_BYTE (255); + dst += 4; + src += 2; + } +} + +inline static void +G_PASTE (_cogl_unpack_rgb_888_, component_size) (const uint8_t *src, + component_type *dst, + int width) +{ + while (width-- > 0) + { + dst[0] = UNPACK_BYTE (src[0]); + dst[1] = UNPACK_BYTE (src[1]); + dst[2] = UNPACK_BYTE (src[2]); + dst[3] = UNPACK_BYTE (255); + dst += 4; + src += 3; + } +} + +inline static void +G_PASTE (_cogl_unpack_bgr_888_, component_size) (const uint8_t *src, + component_type *dst, + int width) +{ + while (width-- > 0) + { + dst[0] = UNPACK_BYTE (src[2]); + dst[1] = UNPACK_BYTE (src[1]); + dst[2] = UNPACK_BYTE (src[0]); + dst[3] = UNPACK_BYTE (255); + dst += 4; + src += 3; + } +} + +inline static void +G_PASTE (_cogl_unpack_bgra_8888_, component_size) (const uint8_t *src, + component_type *dst, + int width) +{ + while (width-- > 0) + { + dst[0] = UNPACK_BYTE (src[2]); + dst[1] = UNPACK_BYTE (src[1]); + dst[2] = UNPACK_BYTE (src[0]); + dst[3] = UNPACK_BYTE (src[3]); + dst += 4; + src += 4; + } +} + +inline static void +G_PASTE (_cogl_unpack_argb_8888_, component_size) (const uint8_t *src, + component_type *dst, + int width) +{ + while (width-- > 0) + { + dst[0] = UNPACK_BYTE (src[1]); + dst[1] = UNPACK_BYTE (src[2]); + dst[2] = UNPACK_BYTE (src[3]); + dst[3] = UNPACK_BYTE (src[0]); + dst += 4; + src += 4; + } +} + +inline static void +G_PASTE (_cogl_unpack_abgr_8888_, component_size) (const uint8_t *src, + component_type *dst, + int width) +{ + while (width-- > 0) + { + dst[0] = UNPACK_BYTE (src[3]); + dst[1] = UNPACK_BYTE (src[2]); + dst[2] = UNPACK_BYTE (src[1]); + dst[3] = UNPACK_BYTE (src[0]); + dst += 4; + src += 4; + } +} + +inline static void +G_PASTE (_cogl_unpack_rgba_8888_, component_size) (const uint8_t *src, + component_type *dst, + int width) +{ + while (width-- > 0) + { + dst[0] = UNPACK_BYTE (src[0]); + dst[1] = UNPACK_BYTE (src[1]); + dst[2] = UNPACK_BYTE (src[2]); + dst[3] = UNPACK_BYTE (src[3]); + dst += 4; + src += 4; + } +} + +inline static void +G_PASTE (_cogl_unpack_rgb_565_, component_size) (const uint8_t *src, + component_type *dst, + int width) +{ + while (width-- > 0) + { + uint16_t v = *(const uint16_t *) src; + + dst[0] = UNPACK_5 (v >> 11); + dst[1] = UNPACK_6 ((v >> 5) & 63); + dst[2] = UNPACK_5 (v & 31); + dst[3] = UNPACK_BYTE (255); + dst += 4; + src += 2; + } +} + +inline static void +G_PASTE (_cogl_unpack_rgba_4444_, component_size) (const uint8_t *src, + component_type *dst, + int width) +{ + while (width-- > 0) + { + uint16_t v = *(const uint16_t *) src; + + dst[0] = UNPACK_4 (v >> 12); + dst[1] = UNPACK_4 ((v >> 8) & 15); + dst[2] = UNPACK_4 ((v >> 4) & 15); + dst[3] = UNPACK_4 (v & 15); + dst += 4; + src += 2; + } +} + +inline static void +G_PASTE (_cogl_unpack_rgba_5551_, component_size) (const uint8_t *src, + component_type *dst, + int width) +{ + while (width-- > 0) + { + uint16_t v = *(const uint16_t *) src; + + dst[0] = UNPACK_5 (v >> 11); + dst[1] = UNPACK_5 ((v >> 6) & 31); + dst[2] = UNPACK_5 ((v >> 1) & 31); + dst[3] = UNPACK_1 (v & 1); + dst += 4; + src += 2; + } +} + +inline static void +G_PASTE (_cogl_unpack_rgba_1010102_, component_size) (const uint8_t *src, + component_type *dst, + int width) +{ + while (width-- > 0) + { + uint32_t v = *(const uint32_t *) src; + + dst[0] = UNPACK_10 (v >> 22); + dst[1] = UNPACK_10 ((v >> 12) & 1023); + dst[2] = UNPACK_10 ((v >> 2) & 1023); + dst[3] = UNPACK_2 (v & 3); + dst += 4; + src += 2; + } +} + +inline static void +G_PASTE (_cogl_unpack_bgra_1010102_, component_size) (const uint8_t *src, + component_type *dst, + int width) +{ + while (width-- > 0) + { + uint32_t v = *(const uint32_t *) src; + + dst[2] = UNPACK_10 (v >> 22); + dst[1] = UNPACK_10 ((v >> 12) & 1023); + dst[0] = UNPACK_10 ((v >> 2) & 1023); + dst[3] = UNPACK_2 (v & 3); + dst += 4; + src += 2; + } +} + +inline static void +G_PASTE (_cogl_unpack_argb_2101010_, component_size) (const uint8_t *src, + component_type *dst, + int width) +{ + while (width-- > 0) + { + uint32_t v = *(const uint32_t *) src; + + dst[3] = UNPACK_2 (v >> 30); + dst[0] = UNPACK_10 ((v >> 20) & 1023); + dst[1] = UNPACK_10 ((v >> 10) & 1023); + dst[2] = UNPACK_10 (v & 1023); + dst += 4; + src += 2; + } +} + +inline static void +G_PASTE (_cogl_unpack_abgr_2101010_, component_size) (const uint8_t *src, + component_type *dst, + int width) +{ + while (width-- > 0) + { + uint32_t v = *(const uint32_t *) src; + + dst[3] = UNPACK_2 (v >> 30); + dst[2] = UNPACK_10 ((v >> 20) & 1023); + dst[1] = UNPACK_10 ((v >> 10) & 1023); + dst[0] = UNPACK_10 (v & 1023); + dst += 4; + src += 2; + } +} + +#undef UNPACK_1 +#undef UNPACK_2 +#undef UNPACK_4 +#undef UNPACK_5 +#undef UNPACK_6 +#undef UNPACK_10 + +inline static void +G_PASTE (_cogl_unpack_, component_size) (CoglPixelFormat format, + const uint8_t *src, + component_type *dst, + int width) +{ + switch (format) + { + case COGL_PIXEL_FORMAT_A_8: + G_PASTE (_cogl_unpack_a_8_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_G_8: + G_PASTE (_cogl_unpack_g_8_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_RG_88: + G_PASTE (_cogl_unpack_rg_88_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_RGB_888: + G_PASTE (_cogl_unpack_rgb_888_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_BGR_888: + G_PASTE (_cogl_unpack_bgr_888_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_RGBA_8888: + case COGL_PIXEL_FORMAT_RGBA_8888_PRE: + G_PASTE (_cogl_unpack_rgba_8888_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_BGRA_8888: + case COGL_PIXEL_FORMAT_BGRA_8888_PRE: + G_PASTE (_cogl_unpack_bgra_8888_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_ARGB_8888: + case COGL_PIXEL_FORMAT_ARGB_8888_PRE: + G_PASTE (_cogl_unpack_argb_8888_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_ABGR_8888: + case COGL_PIXEL_FORMAT_ABGR_8888_PRE: + G_PASTE (_cogl_unpack_abgr_8888_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_RGB_565: + G_PASTE (_cogl_unpack_rgb_565_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_RGBA_4444: + case COGL_PIXEL_FORMAT_RGBA_4444_PRE: + G_PASTE (_cogl_unpack_rgba_4444_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_RGBA_5551: + case COGL_PIXEL_FORMAT_RGBA_5551_PRE: + G_PASTE (_cogl_unpack_rgba_5551_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_RGBA_1010102: + case COGL_PIXEL_FORMAT_RGBA_1010102_PRE: + G_PASTE (_cogl_unpack_rgba_1010102_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_BGRA_1010102: + case COGL_PIXEL_FORMAT_BGRA_1010102_PRE: + G_PASTE (_cogl_unpack_bgra_1010102_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_ARGB_2101010: + case COGL_PIXEL_FORMAT_ARGB_2101010_PRE: + G_PASTE (_cogl_unpack_argb_2101010_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_ABGR_2101010: + case COGL_PIXEL_FORMAT_ABGR_2101010_PRE: + G_PASTE (_cogl_unpack_abgr_2101010_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_DEPTH_16: + case COGL_PIXEL_FORMAT_DEPTH_32: + case COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8: + case COGL_PIXEL_FORMAT_ANY: + case COGL_PIXEL_FORMAT_YUV: + g_assert_not_reached (); + } +} + +/* Packing from RGBA */ + +/* Pack and round to nearest */ +#define PACK_SIZE(b, max) \ + (((b) * (max) + (1 << (sizeof (component_type) * 8 - 1)) - 1) / \ + ((1 << (sizeof (component_type) * 8)) - 1)) + +#define PACK_1(b) PACK_SIZE (b, 1) +#define PACK_2(b) PACK_SIZE (b, 3) +#define PACK_4(b) PACK_SIZE (b, 15) +#define PACK_5(b) PACK_SIZE (b, 31) +#define PACK_6(b) PACK_SIZE (b, 63) +#define PACK_10(b) PACK_SIZE (b, 1023) + +inline static void +G_PASTE (_cogl_pack_a_8_, component_size) (const component_type *src, + uint8_t *dst, + int width) +{ + while (width-- > 0) + { + *dst = PACK_BYTE (src[3]); + src += 4; + dst++; + } +} + +inline static void +G_PASTE (_cogl_pack_g_8_, component_size) (const component_type *src, + uint8_t *dst, + int width) +{ + /* FIXME: I'm not sure if this is right. It looks like Nvidia and + Mesa handle luminance textures differently. Maybe we should + consider just removing luminance textures for Cogl 2.0 because + they have been removed in GL 3.0 */ + while (width-- > 0) + { + component_type v = (src[0] + src[1] + src[2]) / 3; + *dst = PACK_BYTE (v); + src += 4; + dst++; + } +} + +inline static void +G_PASTE (_cogl_pack_rg_88_, component_size) (const component_type *src, + uint8_t *dst, + int width) +{ + while (width-- > 0) + { + dst[0] = PACK_BYTE (src[0]); + dst[1] = PACK_BYTE (src[1]); + src += 4; + dst += 2; + } +} + +inline static void +G_PASTE (_cogl_pack_rgb_888_, component_size) (const component_type *src, + uint8_t *dst, + int width) +{ + while (width-- > 0) + { + dst[0] = PACK_BYTE (src[0]); + dst[1] = PACK_BYTE (src[1]); + dst[2] = PACK_BYTE (src[2]); + src += 4; + dst += 3; + } +} + +inline static void +G_PASTE (_cogl_pack_bgr_888_, component_size) (const component_type *src, + uint8_t *dst, + int width) +{ + while (width-- > 0) + { + dst[2] = PACK_BYTE (src[0]); + dst[1] = PACK_BYTE (src[1]); + dst[0] = PACK_BYTE (src[2]); + src += 4; + dst += 3; + } +} + +inline static void +G_PASTE (_cogl_pack_bgra_8888_, component_size) (const component_type *src, + uint8_t *dst, + int width) +{ + while (width-- > 0) + { + dst[2] = PACK_BYTE (src[0]); + dst[1] = PACK_BYTE (src[1]); + dst[0] = PACK_BYTE (src[2]); + dst[3] = PACK_BYTE (src[3]); + src += 4; + dst += 4; + } +} + +inline static void +G_PASTE (_cogl_pack_argb_8888_, component_size) (const component_type *src, + uint8_t *dst, + int width) +{ + while (width-- > 0) + { + dst[1] = PACK_BYTE (src[0]); + dst[2] = PACK_BYTE (src[1]); + dst[3] = PACK_BYTE (src[2]); + dst[0] = PACK_BYTE (src[3]); + src += 4; + dst += 4; + } +} + +inline static void +G_PASTE (_cogl_pack_abgr_8888_, component_size) (const component_type *src, + uint8_t *dst, + int width) +{ + while (width-- > 0) + { + dst[3] = PACK_BYTE (src[0]); + dst[2] = PACK_BYTE (src[1]); + dst[1] = PACK_BYTE (src[2]); + dst[0] = PACK_BYTE (src[3]); + src += 4; + dst += 4; + } +} + +inline static void +G_PASTE (_cogl_pack_rgba_8888_, component_size) (const component_type *src, + uint8_t *dst, + int width) +{ + while (width-- > 0) + { + dst[0] = PACK_BYTE (src[0]); + dst[1] = PACK_BYTE (src[1]); + dst[2] = PACK_BYTE (src[2]); + dst[3] = PACK_BYTE (src[3]); + src += 4; + dst += 4; + } +} + +inline static void +G_PASTE (_cogl_pack_rgb_565_, component_size) (const component_type *src, + uint8_t *dst, + int width) +{ + while (width-- > 0) + { + uint16_t *v = (uint16_t *) dst; + + *v = ((PACK_5 (src[0]) << 11) | + (PACK_6 (src[1]) << 5) | + PACK_5 (src[2])); + src += 4; + dst += 2; + } +} + +inline static void +G_PASTE (_cogl_pack_rgba_4444_, component_size) (const component_type *src, + uint8_t *dst, + int width) +{ + while (width-- > 0) + { + uint16_t *v = (uint16_t *) dst; + + *v = ((PACK_4 (src[0]) << 12) | + (PACK_4 (src[1]) << 8) | + (PACK_4 (src[2]) << 4) | + PACK_4 (src[3])); + src += 4; + dst += 2; + } +} + +inline static void +G_PASTE (_cogl_pack_rgba_5551_, component_size) (const component_type *src, + uint8_t *dst, + int width) +{ + while (width-- > 0) + { + uint16_t *v = (uint16_t *) dst; + + *v = ((PACK_5 (src[0]) << 11) | + (PACK_5 (src[1]) << 6) | + (PACK_5 (src[2]) << 1) | + PACK_1 (src[3])); + src += 4; + dst += 2; + } +} + +inline static void +G_PASTE (_cogl_pack_rgba_1010102_, component_size) (const component_type *src, + uint8_t *dst, + int width) +{ + while (width-- > 0) + { + uint32_t *v = (uint32_t *) dst; + + *v = ((PACK_10 (src[0]) << 22) | + (PACK_10 (src[1]) << 12) | + (PACK_10 (src[2]) << 2) | + PACK_2 (src[3])); + src += 4; + dst += 4; + } +} + +inline static void +G_PASTE (_cogl_pack_bgra_1010102_, component_size) (const component_type *src, + uint8_t *dst, + int width) +{ + while (width-- > 0) + { + uint32_t *v = (uint32_t *) dst; + + *v = ((PACK_10 (src[2]) << 22) | + (PACK_10 (src[1]) << 12) | + (PACK_10 (src[0]) << 2) | + PACK_2 (src[3])); + src += 4; + dst += 4; + } +} + +inline static void +G_PASTE (_cogl_pack_argb_2101010_, component_size) (const component_type *src, + uint8_t *dst, + int width) +{ + while (width-- > 0) + { + uint32_t *v = (uint32_t *) dst; + + *v = ((PACK_2 (src[3]) << 30) | + (PACK_10 (src[0]) << 20) | + (PACK_10 (src[1]) << 10) | + PACK_10 (src[2])); + src += 4; + dst += 4; + } +} + +inline static void +G_PASTE (_cogl_pack_abgr_2101010_, component_size) (const component_type *src, + uint8_t *dst, + int width) +{ + while (width-- > 0) + { + uint32_t *v = (uint32_t *) dst; + + *v = ((PACK_2 (src[3]) << 30) | + (PACK_10 (src[2]) << 20) | + (PACK_10 (src[1]) << 10) | + PACK_10 (src[0])); + src += 4; + dst += 4; + } +} + +#undef PACK_SIZE +#undef PACK_1 +#undef PACK_2 +#undef PACK_4 +#undef PACK_5 +#undef PACK_6 +#undef PACK_10 + +inline static void +G_PASTE (_cogl_pack_, component_size) (CoglPixelFormat format, + const component_type *src, + uint8_t *dst, + int width) +{ + switch (format) + { + case COGL_PIXEL_FORMAT_A_8: + G_PASTE (_cogl_pack_a_8_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_G_8: + G_PASTE (_cogl_pack_g_8_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_RG_88: + G_PASTE (_cogl_pack_rg_88_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_RGB_888: + G_PASTE (_cogl_pack_rgb_888_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_BGR_888: + G_PASTE (_cogl_pack_bgr_888_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_RGBA_8888: + case COGL_PIXEL_FORMAT_RGBA_8888_PRE: + G_PASTE (_cogl_pack_rgba_8888_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_BGRA_8888: + case COGL_PIXEL_FORMAT_BGRA_8888_PRE: + G_PASTE (_cogl_pack_bgra_8888_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_ARGB_8888: + case COGL_PIXEL_FORMAT_ARGB_8888_PRE: + G_PASTE (_cogl_pack_argb_8888_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_ABGR_8888: + case COGL_PIXEL_FORMAT_ABGR_8888_PRE: + G_PASTE (_cogl_pack_abgr_8888_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_RGB_565: + G_PASTE (_cogl_pack_rgb_565_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_RGBA_4444: + case COGL_PIXEL_FORMAT_RGBA_4444_PRE: + G_PASTE (_cogl_pack_rgba_4444_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_RGBA_5551: + case COGL_PIXEL_FORMAT_RGBA_5551_PRE: + G_PASTE (_cogl_pack_rgba_5551_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_RGBA_1010102: + case COGL_PIXEL_FORMAT_RGBA_1010102_PRE: + G_PASTE (_cogl_pack_rgba_1010102_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_BGRA_1010102: + case COGL_PIXEL_FORMAT_BGRA_1010102_PRE: + G_PASTE (_cogl_pack_bgra_1010102_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_ARGB_2101010: + case COGL_PIXEL_FORMAT_ARGB_2101010_PRE: + G_PASTE (_cogl_pack_argb_2101010_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_ABGR_2101010: + case COGL_PIXEL_FORMAT_ABGR_2101010_PRE: + G_PASTE (_cogl_pack_abgr_2101010_, component_size) (src, dst, width); + break; + case COGL_PIXEL_FORMAT_DEPTH_16: + case COGL_PIXEL_FORMAT_DEPTH_32: + case COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8: + case COGL_PIXEL_FORMAT_ANY: + case COGL_PIXEL_FORMAT_YUV: + g_assert_not_reached (); + } +} diff --git a/cogl/cogl/cogl-bitmap-pixbuf.c b/cogl/cogl/cogl-bitmap-pixbuf.c new file mode 100644 index 0000000..21b6fb4 --- /dev/null +++ b/cogl/cogl/cogl-bitmap-pixbuf.c @@ -0,0 +1,136 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-util.h" +#include "cogl-bitmap-private.h" +#include "cogl-context-private.h" +#include "cogl-private.h" +#include "cogl-error-private.h" + +#include + +#include + +CoglBool +_cogl_bitmap_get_size_from_file (const char *filename, + int *width, + int *height) +{ + _COGL_RETURN_VAL_IF_FAIL (filename != NULL, FALSE); + + if (gdk_pixbuf_get_file_info (filename, width, height) != NULL) + return TRUE; + + return FALSE; +} + +CoglBitmap * +_cogl_bitmap_from_file (CoglContext *ctx, + const char *filename, + CoglError **error) +{ + static CoglUserDataKey pixbuf_key; + GdkPixbuf *pixbuf; + CoglBool has_alpha; + GdkColorspace color_space; + CoglPixelFormat pixel_format; + int width; + int height; + int rowstride; + int bits_per_sample; + int n_channels; + CoglBitmap *bmp; + GError *glib_error = NULL; + + /* Load from file using GdkPixbuf */ + pixbuf = gdk_pixbuf_new_from_file (filename, &glib_error); + if (pixbuf == NULL) + { + _cogl_propagate_gerror (error, glib_error); + return FALSE; + } + + /* Get pixbuf properties */ + has_alpha = gdk_pixbuf_get_has_alpha (pixbuf); + color_space = gdk_pixbuf_get_colorspace (pixbuf); + width = gdk_pixbuf_get_width (pixbuf); + height = gdk_pixbuf_get_height (pixbuf); + rowstride = gdk_pixbuf_get_rowstride (pixbuf); + bits_per_sample = gdk_pixbuf_get_bits_per_sample (pixbuf); + n_channels = gdk_pixbuf_get_n_channels (pixbuf); + + /* According to current docs this should be true and so + * the translation to cogl pixel format below valid */ + g_assert (bits_per_sample == 8); + + if (has_alpha) + g_assert (n_channels == 4); + else + g_assert (n_channels == 3); + + /* Translate to cogl pixel format */ + switch (color_space) + { + case GDK_COLORSPACE_RGB: + /* The only format supported by GdkPixbuf so far */ + pixel_format = has_alpha ? + COGL_PIXEL_FORMAT_RGBA_8888 : + COGL_PIXEL_FORMAT_RGB_888; + break; + + default: + /* Ouch, spec changed! */ + g_object_unref (pixbuf); + return FALSE; + } + + /* We just use the data directly from the pixbuf so that we don't + have to copy to a seperate buffer. Note that Cogl is expected not + to read past the end of bpp*width on the last row even if the + rowstride is much larger so we don't need to worry about + GdkPixbuf's semantics that it may under-allocate the buffer. */ + bmp = cogl_bitmap_new_for_data (ctx, + width, + height, + pixel_format, + rowstride, + gdk_pixbuf_get_pixels (pixbuf)); + + cogl_object_set_user_data (COGL_OBJECT (bmp), + &pixbuf_key, + pixbuf, + g_object_unref); + + return bmp; +} diff --git a/cogl/cogl/cogl-bitmap-private.h b/cogl/cogl/cogl-bitmap-private.h new file mode 100644 index 0000000..676729d --- /dev/null +++ b/cogl/cogl/cogl-bitmap-private.h @@ -0,0 +1,201 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007 OpenedHand + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_BITMAP_H +#define __COGL_BITMAP_H + +#include + +#include "cogl-object-private.h" +#include "cogl-buffer.h" +#include "cogl-bitmap.h" + +struct _CoglBitmap +{ + CoglObject _parent; + + /* Pointer back to the context that this bitmap was created with */ + CoglContext *context; + + CoglPixelFormat format; + int width; + int height; + int rowstride; + + uint8_t *data; + + CoglBool mapped; + CoglBool bound; + + /* If this is non-null then 'data' is ignored and instead it is + fetched from this shared bitmap. */ + CoglBitmap *shared_bmp; + + /* If this is non-null then 'data' is treated as an offset into the + buffer and map will divert to mapping the buffer */ + CoglBuffer *buffer; +}; + + +/* + * _cogl_bitmap_new_with_malloc_buffer: + * @context: A #CoglContext + * @width: width of the bitmap in pixels + * @height: height of the bitmap in pixels + * @format: the format of the pixels the array will store + * @error: A #CoglError for catching exceptional errors or %NULL + * + * This is equivalent to cogl_bitmap_new_with_size() except that it + * allocated the buffer using g_malloc() instead of creating a + * #CoglPixelBuffer. The buffer will be automatically destroyed when + * the bitmap is freed. + * + * Return value: a #CoglPixelBuffer representing the newly created array + * + * Since: 1.10 + * Stability: Unstable + */ +CoglBitmap * +_cogl_bitmap_new_with_malloc_buffer (CoglContext *context, + unsigned int width, + unsigned int height, + CoglPixelFormat format, + CoglError **error); + +/* The idea of this function is that it will create a bitmap that + shares the actual data with another bitmap. This is needed for the + atlas texture backend because it needs upload a bitmap to a sub + texture but override the format so that it ignores the premult + flag. */ +CoglBitmap * +_cogl_bitmap_new_shared (CoglBitmap *shared_bmp, + CoglPixelFormat format, + int width, + int height, + int rowstride); + +CoglBitmap * +_cogl_bitmap_convert (CoglBitmap *bmp, + CoglPixelFormat dst_format, + CoglError **error); + +CoglBitmap * +_cogl_bitmap_convert_for_upload (CoglBitmap *src_bmp, + CoglPixelFormat internal_format, + CoglBool can_convert_in_place, + CoglError **error); + +CoglBool +_cogl_bitmap_convert_into_bitmap (CoglBitmap *src_bmp, + CoglBitmap *dst_bmp, + CoglError **error); + +CoglBitmap * +_cogl_bitmap_from_file (CoglContext *ctx, + const char *filename, + CoglError **error); + +CoglBool +_cogl_bitmap_unpremult (CoglBitmap *dst_bmp, + CoglError **error); + +CoglBool +_cogl_bitmap_premult (CoglBitmap *dst_bmp, + CoglError **error); + +CoglBool +_cogl_bitmap_convert_premult_status (CoglBitmap *bmp, + CoglPixelFormat dst_format, + CoglError **error); + +CoglBool +_cogl_bitmap_copy_subregion (CoglBitmap *src, + CoglBitmap *dst, + int src_x, + int src_y, + int dst_x, + int dst_y, + int width, + int height, + CoglError **error); + +/* Creates a deep copy of the source bitmap */ +CoglBitmap * +_cogl_bitmap_copy (CoglBitmap *src_bmp, + CoglError **error); + +CoglBool +_cogl_bitmap_get_size_from_file (const char *filename, + int *width, + int *height); + +void +_cogl_bitmap_set_format (CoglBitmap *bitmap, + CoglPixelFormat format); + +/* Maps the bitmap so that the pixels can be accessed directly or if + the bitmap is just a memory bitmap then it just returns the pointer + to memory. Note that the bitmap isn't guaranteed to allocated to + the full size of rowstride*height so it is not safe to read up to + the rowstride of the last row. This will be the case if the user + uploads data using gdk_pixbuf_new_subpixbuf with a sub region + containing the last row of the pixbuf because in that case the + rowstride can be much larger than the width of the image */ +uint8_t * +_cogl_bitmap_map (CoglBitmap *bitmap, + CoglBufferAccess access, + CoglBufferMapHint hints, + CoglError **error); + +void +_cogl_bitmap_unmap (CoglBitmap *bitmap); + +/* These two are replacements for map and unmap that should used when + * the pointer is going to be passed to GL for pixel packing or + * unpacking. The address might not be valid for reading if the bitmap + * was created with new_from_buffer but it will however be good to + * pass to glTexImage2D for example. The access should be READ for + * unpacking and WRITE for packing. It can not be both + * + * TODO: split this bind/unbind functions out into a GL specific file + */ +uint8_t * +_cogl_bitmap_gl_bind (CoglBitmap *bitmap, + CoglBufferAccess access, + CoglBufferMapHint hints, + CoglError **error); + +void +_cogl_bitmap_gl_unbind (CoglBitmap *bitmap); + +CoglContext * +_cogl_bitmap_get_context (CoglBitmap *bitmap); + +#endif /* __COGL_BITMAP_H */ diff --git a/cogl/cogl/cogl-bitmap.c b/cogl/cogl/cogl-bitmap.c new file mode 100644 index 0000000..b395c42 --- /dev/null +++ b/cogl/cogl/cogl-bitmap.c @@ -0,0 +1,522 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-util.h" +#include "cogl-debug.h" +#include "cogl-private.h" +#include "cogl-bitmap-private.h" +#include "cogl-buffer-private.h" +#include "cogl-pixel-buffer.h" +#include "cogl-context-private.h" +#include "cogl-buffer-gl-private.h" +#include "cogl-error-private.h" +#include "cogl-gtype-private.h" + +#include + +static void _cogl_bitmap_free (CoglBitmap *bmp); + +COGL_OBJECT_DEFINE (Bitmap, bitmap); +COGL_GTYPE_DEFINE_CLASS (Bitmap, bitmap); + +static void +_cogl_bitmap_free (CoglBitmap *bmp) +{ + g_assert (!bmp->mapped); + g_assert (!bmp->bound); + + if (bmp->shared_bmp) + cogl_object_unref (bmp->shared_bmp); + + if (bmp->buffer) + cogl_object_unref (bmp->buffer); + + g_slice_free (CoglBitmap, bmp); +} + +CoglBool +_cogl_bitmap_convert_premult_status (CoglBitmap *bmp, + CoglPixelFormat dst_format, + CoglError **error) +{ + /* Do we need to unpremultiply? */ + if ((bmp->format & COGL_PREMULT_BIT) > 0 && + (dst_format & COGL_PREMULT_BIT) == 0 && + COGL_PIXEL_FORMAT_CAN_HAVE_PREMULT (dst_format)) + return _cogl_bitmap_unpremult (bmp, error); + + /* Do we need to premultiply? */ + if ((bmp->format & COGL_PREMULT_BIT) == 0 && + COGL_PIXEL_FORMAT_CAN_HAVE_PREMULT (bmp->format) && + (dst_format & COGL_PREMULT_BIT) > 0) + /* Try premultiplying using imaging library */ + return _cogl_bitmap_premult (bmp, error); + + return TRUE; +} + +CoglBitmap * +_cogl_bitmap_copy (CoglBitmap *src_bmp, + CoglError **error) +{ + CoglBitmap *dst_bmp; + CoglPixelFormat src_format = cogl_bitmap_get_format (src_bmp); + int width = cogl_bitmap_get_width (src_bmp); + int height = cogl_bitmap_get_height (src_bmp); + + dst_bmp = + _cogl_bitmap_new_with_malloc_buffer (src_bmp->context, + width, height, + src_format, + error); + if (!dst_bmp) + return NULL; + + if (!_cogl_bitmap_copy_subregion (src_bmp, + dst_bmp, + 0, 0, /* src_x/y */ + 0, 0, /* dst_x/y */ + width, height, + error)) + { + cogl_object_unref (dst_bmp); + return NULL; + } + + return dst_bmp; +} + +CoglBool +_cogl_bitmap_copy_subregion (CoglBitmap *src, + CoglBitmap *dst, + int src_x, + int src_y, + int dst_x, + int dst_y, + int width, + int height, + CoglError **error) +{ + uint8_t *srcdata; + uint8_t *dstdata; + int bpp; + int line; + CoglBool succeeded = FALSE; + + /* Intended only for fast copies when format is equal! */ + _COGL_RETURN_VAL_IF_FAIL ((src->format & ~COGL_PREMULT_BIT) == + (dst->format & ~COGL_PREMULT_BIT), + FALSE); + + bpp = _cogl_pixel_format_get_bytes_per_pixel (src->format); + + if ((srcdata = _cogl_bitmap_map (src, COGL_BUFFER_ACCESS_READ, 0, error))) + { + if ((dstdata = + _cogl_bitmap_map (dst, COGL_BUFFER_ACCESS_WRITE, 0, error))) + { + srcdata += src_y * src->rowstride + src_x * bpp; + dstdata += dst_y * dst->rowstride + dst_x * bpp; + + for (line = 0; line < height; ++line) + { + memcpy (dstdata, srcdata, width * bpp); + srcdata += src->rowstride; + dstdata += dst->rowstride; + } + + succeeded = TRUE; + + _cogl_bitmap_unmap (dst); + } + + _cogl_bitmap_unmap (src); + } + + return succeeded; +} + +CoglBool +cogl_bitmap_get_size_from_file (const char *filename, + int *width, + int *height) +{ + return _cogl_bitmap_get_size_from_file (filename, width, height); +} + +CoglBitmap * +cogl_bitmap_new_for_data (CoglContext *context, + int width, + int height, + CoglPixelFormat format, + int rowstride, + uint8_t *data) +{ + CoglBitmap *bmp; + + g_return_val_if_fail (cogl_is_context (context), NULL); + + /* Rowstride from width if not given */ + if (rowstride == 0) + rowstride = width * _cogl_pixel_format_get_bytes_per_pixel (format); + + bmp = g_slice_new (CoglBitmap); + bmp->context = context; + bmp->format = format; + bmp->width = width; + bmp->height = height; + bmp->rowstride = rowstride; + bmp->data = data; + bmp->mapped = FALSE; + bmp->bound = FALSE; + bmp->shared_bmp = NULL; + bmp->buffer = NULL; + + return _cogl_bitmap_object_new (bmp); +} + +CoglBitmap * +_cogl_bitmap_new_with_malloc_buffer (CoglContext *context, + unsigned int width, + unsigned int height, + CoglPixelFormat format, + CoglError **error) +{ + static CoglUserDataKey bitmap_free_key; + int bpp = _cogl_pixel_format_get_bytes_per_pixel (format); + int rowstride = ((width * bpp) + 3) & ~3; + uint8_t *data = g_try_malloc (rowstride * height); + CoglBitmap *bitmap; + + if (!data) + { + _cogl_set_error (error, + COGL_SYSTEM_ERROR, + COGL_SYSTEM_ERROR_NO_MEMORY, + "Failed to allocate memory for bitmap"); + return NULL; + } + + bitmap = cogl_bitmap_new_for_data (context, + width, height, + format, + rowstride, + data); + cogl_object_set_user_data (COGL_OBJECT (bitmap), + &bitmap_free_key, + data, + g_free); + + return bitmap; +} + +CoglBitmap * +_cogl_bitmap_new_shared (CoglBitmap *shared_bmp, + CoglPixelFormat format, + int width, + int height, + int rowstride) +{ + CoglBitmap *bmp; + + bmp = cogl_bitmap_new_for_data (shared_bmp->context, + width, height, + format, + rowstride, + NULL /* data */); + + bmp->shared_bmp = cogl_object_ref (shared_bmp); + + return bmp; +} + +CoglBitmap * +cogl_bitmap_new_from_file (const char *filename, + CoglError **error) +{ + _COGL_GET_CONTEXT (ctx, NULL); + + _COGL_RETURN_VAL_IF_FAIL (filename != NULL, NULL); + _COGL_RETURN_VAL_IF_FAIL (error == NULL || *error == NULL, NULL); + + return _cogl_bitmap_from_file (ctx, filename, error); +} + +CoglBitmap * +cogl_bitmap_new_from_buffer (CoglBuffer *buffer, + CoglPixelFormat format, + int width, + int height, + int rowstride, + int offset) +{ + CoglBitmap *bmp; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_buffer (buffer), NULL); + + bmp = cogl_bitmap_new_for_data (buffer->context, + width, height, + format, + rowstride, + NULL /* data */); + + bmp->buffer = cogl_object_ref (buffer); + bmp->data = GINT_TO_POINTER (offset); + + return bmp; +} + +CoglBitmap * +cogl_bitmap_new_with_size (CoglContext *context, + unsigned int width, + unsigned int height, + CoglPixelFormat format) +{ + CoglPixelBuffer *pixel_buffer; + CoglBitmap *bitmap; + unsigned int rowstride; + + /* creating a buffer to store "any" format does not make sense */ + _COGL_RETURN_VAL_IF_FAIL (format != COGL_PIXEL_FORMAT_ANY, NULL); + + /* for now we fallback to cogl_pixel_buffer_new, later, we could ask + * libdrm a tiled buffer for instance */ + rowstride = width * _cogl_pixel_format_get_bytes_per_pixel (format); + + pixel_buffer = + cogl_pixel_buffer_new (context, + height * rowstride, + NULL); /* data */ + + _COGL_RETURN_VAL_IF_FAIL (pixel_buffer != NULL, NULL); + + bitmap = cogl_bitmap_new_from_buffer (COGL_BUFFER (pixel_buffer), + format, + width, height, + rowstride, + 0 /* offset */); + + cogl_object_unref (pixel_buffer); + + return bitmap; +} + +CoglPixelFormat +cogl_bitmap_get_format (CoglBitmap *bitmap) +{ + return bitmap->format; +} + +void +_cogl_bitmap_set_format (CoglBitmap *bitmap, + CoglPixelFormat format) +{ + bitmap->format = format; +} + +int +cogl_bitmap_get_width (CoglBitmap *bitmap) +{ + return bitmap->width; +} + +int +cogl_bitmap_get_height (CoglBitmap *bitmap) +{ + return bitmap->height; +} + +int +cogl_bitmap_get_rowstride (CoglBitmap *bitmap) +{ + return bitmap->rowstride; +} + +CoglPixelBuffer * +cogl_bitmap_get_buffer (CoglBitmap *bitmap) +{ + while (bitmap->shared_bmp) + bitmap = bitmap->shared_bmp; + + return COGL_PIXEL_BUFFER (bitmap->buffer); +} + +uint32_t +cogl_bitmap_error_quark (void) +{ + return g_quark_from_static_string ("cogl-bitmap-error-quark"); +} + +uint8_t * +_cogl_bitmap_map (CoglBitmap *bitmap, + CoglBufferAccess access, + CoglBufferMapHint hints, + CoglError **error) +{ + /* Divert to another bitmap if this data is shared */ + if (bitmap->shared_bmp) + return _cogl_bitmap_map (bitmap->shared_bmp, access, hints, error); + + g_assert (!bitmap->mapped); + + if (bitmap->buffer) + { + uint8_t *data = _cogl_buffer_map (bitmap->buffer, + access, + hints, + error); + + COGL_NOTE (BITMAP, "A pixel array is being mapped from a bitmap. This " + "usually means that some conversion on the pixel array is " + "needed so a sub-optimal format is being used."); + + if (data) + { + bitmap->mapped = TRUE; + + return data + GPOINTER_TO_INT (bitmap->data); + } + else + return NULL; + } + else + { + bitmap->mapped = TRUE; + + return bitmap->data; + } +} + +void +_cogl_bitmap_unmap (CoglBitmap *bitmap) +{ + /* Divert to another bitmap if this data is shared */ + if (bitmap->shared_bmp) + { + _cogl_bitmap_unmap (bitmap->shared_bmp); + return; + } + + g_assert (bitmap->mapped); + bitmap->mapped = FALSE; + + if (bitmap->buffer) + cogl_buffer_unmap (bitmap->buffer); +} + +uint8_t * +_cogl_bitmap_gl_bind (CoglBitmap *bitmap, + CoglBufferAccess access, + CoglBufferMapHint hints, + CoglError **error) +{ + uint8_t *ptr; + CoglError *internal_error = NULL; + + g_return_val_if_fail (access & (COGL_BUFFER_ACCESS_READ | + COGL_BUFFER_ACCESS_WRITE), + NULL); + + /* Divert to another bitmap if this data is shared */ + if (bitmap->shared_bmp) + return _cogl_bitmap_gl_bind (bitmap->shared_bmp, access, hints, error); + + _COGL_RETURN_VAL_IF_FAIL (!bitmap->bound, NULL); + + /* If the bitmap wasn't created from a buffer then the + implementation of bind is the same as map */ + if (bitmap->buffer == NULL) + { + uint8_t *data = _cogl_bitmap_map (bitmap, access, hints, error); + if (data) + bitmap->bound = TRUE; + return data; + } + + if (access == COGL_BUFFER_ACCESS_READ) + ptr = _cogl_buffer_gl_bind (bitmap->buffer, + COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK, + &internal_error); + else if (access == COGL_BUFFER_ACCESS_WRITE) + ptr = _cogl_buffer_gl_bind (bitmap->buffer, + COGL_BUFFER_BIND_TARGET_PIXEL_PACK, + &internal_error); + else + { + ptr = NULL; + g_assert_not_reached (); + return NULL; + } + + /* NB: _cogl_buffer_gl_bind() may return NULL in non-error + * conditions so we have to explicitly check internal_error to see + * if an exception was thrown */ + if (internal_error) + { + _cogl_propagate_error (error, internal_error); + return NULL; + } + + bitmap->bound = TRUE; + + /* The data pointer actually stores the offset */ + return ptr + GPOINTER_TO_INT (bitmap->data); +} + +void +_cogl_bitmap_gl_unbind (CoglBitmap *bitmap) +{ + /* Divert to another bitmap if this data is shared */ + if (bitmap->shared_bmp) + { + _cogl_bitmap_gl_unbind (bitmap->shared_bmp); + return; + } + + g_assert (bitmap->bound); + bitmap->bound = FALSE; + + /* If the bitmap wasn't created from a pixel array then the + implementation of unbind is the same as unmap */ + if (bitmap->buffer) + _cogl_buffer_gl_unbind (bitmap->buffer); + else + _cogl_bitmap_unmap (bitmap); +} + +CoglContext * +_cogl_bitmap_get_context (CoglBitmap *bitmap) +{ + return bitmap->context; +} diff --git a/cogl/cogl/cogl-bitmap.h b/cogl/cogl/cogl-bitmap.h new file mode 100644 index 0000000..723f8d0 --- /dev/null +++ b/cogl/cogl/cogl-bitmap.h @@ -0,0 +1,302 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_BITMAP_H__ +#define __COGL_BITMAP_H__ + +/* XXX: We forward declare CoglBitmap here to allow for circular + * dependencies between some headers */ +typedef struct _CoglBitmap CoglBitmap; + +#include +#include +#include +#include + +#include + +COGL_BEGIN_DECLS + +/** + * cogl_bitmap_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_bitmap_get_gtype (void); + +/** + * SECTION:cogl-bitmap + * @short_description: Functions for loading images + * + * Cogl allows loading image data into memory as CoglBitmaps without + * loading them immediately into GPU textures. + * + * #CoglBitmap is available since Cogl 1.0 + */ + + +/** + * cogl_bitmap_new_from_file: + * @filename: the file to load. + * @error: a #CoglError or %NULL. + * + * Loads an image file from disk. This function can be safely called from + * within a thread. + * + * Return value: (transfer full): a #CoglBitmap to the new loaded + * image data, or %NULL if loading the image failed. + * + * Since: 1.0 + */ +CoglBitmap * +cogl_bitmap_new_from_file (const char *filename, + CoglError **error); + +/** + * cogl_bitmap_new_from_buffer: (skip) + * @buffer: A #CoglBuffer containing image data + * @format: The #CoglPixelFormat defining the format of the image data + * in the given @buffer. + * @width: The width of the image data in the given @buffer. + * @height: The height of the image data in the given @buffer. + * @rowstride: The rowstride in bytes of the image data in the given @buffer. + * @offset: The offset into the given @buffer to the first pixel that + * should be considered part of the #CoglBitmap. + * + * Wraps some image data that has been uploaded into a #CoglBuffer as + * a #CoglBitmap. The data is not copied in this process. + * + * Return value: (transfer full): a #CoglBitmap encapsulating the given @buffer. + * + * Since: 1.8 + * Stability: unstable + */ +CoglBitmap * +cogl_bitmap_new_from_buffer (CoglBuffer *buffer, + CoglPixelFormat format, + int width, + int height, + int rowstride, + int offset); + +/** + * cogl_bitmap_new_with_size: (skip) + * @context: A #CoglContext + * @width: width of the bitmap in pixels + * @height: height of the bitmap in pixels + * @format: the format of the pixels the array will store + * + * Creates a new #CoglBitmap with the given width, height and format. + * The initial contents of the bitmap are undefined. + * + * The data for the bitmap will be stored in a newly created + * #CoglPixelBuffer. You can get a pointer to the pixel buffer using + * cogl_bitmap_get_buffer(). The #CoglBuffer API can then be + * used to fill the bitmap with data. + * + * Cogl will try its best to provide a hardware array you can + * map, write into and effectively do a zero copy upload when creating + * a texture from it with cogl_texture_new_from_bitmap(). For various + * reasons, such arrays are likely to have a stride larger than width + * * bytes_per_pixel. The user must take the stride into account when + * writing into it. The stride can be retrieved with + * cogl_bitmap_get_rowstride(). + * + * Return value: (transfer full): a #CoglPixelBuffer representing the + * newly created array or %NULL on failure + * + * Since: 1.10 + * Stability: Unstable + */ +CoglBitmap * +cogl_bitmap_new_with_size (CoglContext *context, + unsigned int width, + unsigned int height, + CoglPixelFormat format); + +/** + * cogl_bitmap_new_for_data: (skip) + * @context: A #CoglContext + * @width: The width of the bitmap. + * @height: The height of the bitmap. + * @format: The format of the pixel data. + * @rowstride: The rowstride of the bitmap (the number of bytes from + * the start of one row of the bitmap to the next). + * @data: A pointer to the data. The bitmap will take ownership of this data. + * + * Creates a bitmap using some existing data. The data is not copied + * so the application must keep the buffer alive for the lifetime of + * the #CoglBitmap. This can be used for example with + * cogl_framebuffer_read_pixels_into_bitmap() to read data directly + * into an application buffer with the specified rowstride. + * + * Return value: (transfer full): A new #CoglBitmap. + * Since: 1.10 + * Stability: unstable + */ +CoglBitmap * +cogl_bitmap_new_for_data (CoglContext *context, + int width, + int height, + CoglPixelFormat format, + int rowstride, + uint8_t *data); + +/** + * cogl_bitmap_get_format: + * @bitmap: A #CoglBitmap + * + * Return value: the #CoglPixelFormat that the data for the bitmap is in. + * Since: 1.10 + * Stability: unstable + */ +CoglPixelFormat +cogl_bitmap_get_format (CoglBitmap *bitmap); + +/** + * cogl_bitmap_get_width: + * @bitmap: A #CoglBitmap + * + * Return value: the width of the bitmap + * Since: 1.10 + * Stability: unstable + */ +int +cogl_bitmap_get_width (CoglBitmap *bitmap); + +/** + * cogl_bitmap_get_height: + * @bitmap: A #CoglBitmap + * + * Return value: the height of the bitmap + * Since: 1.10 + * Stability: unstable + */ +int +cogl_bitmap_get_height (CoglBitmap *bitmap); + +/** + * cogl_bitmap_get_rowstride: + * @bitmap: A #CoglBitmap + * + * Return value: the rowstride of the bitmap. This is the number of + * bytes between the address of start of one row to the address of the + * next row in the image. + * Since: 1.10 + * Stability: unstable + */ +int +cogl_bitmap_get_rowstride (CoglBitmap *bitmap); + +/** + * cogl_bitmap_get_buffer: (skip) + * @bitmap: A #CoglBitmap + * + * Return value: (transfer none): the #CoglPixelBuffer that this + * buffer uses for storage. Note that if the bitmap was created with + * cogl_bitmap_new_from_file() then it will not actually be using a + * pixel buffer and this function will return %NULL. + * Stability: unstable + * Since: 1.10 + */ +CoglPixelBuffer * +cogl_bitmap_get_buffer (CoglBitmap *bitmap); + +/** + * cogl_bitmap_get_size_from_file: + * @filename: the file to check + * @width: (out): return location for the bitmap width, or %NULL + * @height: (out): return location for the bitmap height, or %NULL + * + * Parses an image file enough to extract the width and height + * of the bitmap. + * + * Return value: %TRUE if the image was successfully parsed + * + * Since: 1.0 + */ +CoglBool +cogl_bitmap_get_size_from_file (const char *filename, + int *width, + int *height); + +/** + * cogl_is_bitmap: + * @object: a #CoglObject pointer + * + * Checks whether @object is a #CoglBitmap + * + * Return value: %TRUE if the passed @object represents a bitmap, + * and %FALSE otherwise + * + * Since: 1.0 + */ +CoglBool +cogl_is_bitmap (void *object); + +/** + * COGL_BITMAP_ERROR: + * + * #CoglError domain for bitmap errors. + * + * Since: 1.4 + */ +#define COGL_BITMAP_ERROR (cogl_bitmap_error_quark ()) + +/** + * CoglBitmapError: + * @COGL_BITMAP_ERROR_FAILED: Generic failure code, something went + * wrong. + * @COGL_BITMAP_ERROR_UNKNOWN_TYPE: Unknown image type. + * @COGL_BITMAP_ERROR_CORRUPT_IMAGE: An image file was broken somehow. + * + * Error codes that can be thrown when performing bitmap + * operations. Note that gdk_pixbuf_new_from_file() can also throw + * errors directly from the underlying image loading library. For + * example, if GdkPixbuf is used then errors #GdkPixbufErrors + * will be used directly. + * + * Since: 1.4 + */ +typedef enum { + COGL_BITMAP_ERROR_FAILED, + COGL_BITMAP_ERROR_UNKNOWN_TYPE, + COGL_BITMAP_ERROR_CORRUPT_IMAGE +} CoglBitmapError; + +uint32_t cogl_bitmap_error_quark (void); + +COGL_END_DECLS + +#endif /* __COGL_BITMAP_H__ */ diff --git a/cogl/cogl/cogl-bitmask.c b/cogl/cogl/cogl-bitmask.c new file mode 100644 index 0000000..7ec84b5 --- /dev/null +++ b/cogl/cogl/cogl-bitmask.c @@ -0,0 +1,489 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Neil Roberts + */ + +#include "cogl-config.h" + +#include +#include + +#include + +#include "cogl-bitmask.h" +#include "cogl-util.h" +#include "cogl-flags.h" + +/* This code assumes that we can cast an unsigned long to a pointer + and back without losing any data */ +_COGL_STATIC_ASSERT (sizeof (unsigned long) <= sizeof (void *), + "This toolchain breaks Cogl's assumption that it can " + "safely cast an unsigned long to a pointer without " + "loosing data"); + +#define ARRAY_INDEX(bit_num) \ + ((bit_num) / (sizeof (unsigned long) * 8)) +#define BIT_INDEX(bit_num) \ + ((bit_num) & (sizeof (unsigned long) * 8 - 1)) +#define BIT_MASK(bit_num) \ + (1UL << BIT_INDEX (bit_num)) + +CoglBool +_cogl_bitmask_get_from_array (const CoglBitmask *bitmask, + unsigned int bit_num) +{ + GArray *array = (GArray *) *bitmask; + + /* If the index is off the end of the array then assume the bit is + not set */ + if (bit_num >= sizeof (unsigned long) * 8 * array->len) + return FALSE; + else + return !!(g_array_index (array, unsigned long, ARRAY_INDEX (bit_num)) & + BIT_MASK (bit_num)); +} + +static void +_cogl_bitmask_convert_to_array (CoglBitmask *bitmask) +{ + GArray *array; + /* Fetch the old values */ + unsigned long old_values = _cogl_bitmask_to_bits (bitmask); + + array = g_array_new (FALSE, /* not zero-terminated */ + TRUE, /* do clear new entries */ + sizeof (unsigned long)); + /* Copy the old values back in */ + g_array_append_val (array, old_values); + + *bitmask = (struct _CoglBitmaskImaginaryType *) array; +} + +void +_cogl_bitmask_set_in_array (CoglBitmask *bitmask, + unsigned int bit_num, + CoglBool value) +{ + GArray *array; + unsigned int array_index; + unsigned long new_value_mask; + + /* If the bitmask is not already an array then we need to allocate one */ + if (!_cogl_bitmask_has_array (bitmask)) + _cogl_bitmask_convert_to_array (bitmask); + + array = (GArray *) *bitmask; + + array_index = ARRAY_INDEX (bit_num); + /* Grow the array if necessary. This will clear the new data */ + if (array_index >= array->len) + g_array_set_size (array, array_index + 1); + + new_value_mask = BIT_MASK (bit_num); + + if (value) + g_array_index (array, unsigned long, array_index) |= new_value_mask; + else + g_array_index (array, unsigned long, array_index) &= ~new_value_mask; +} + +void +_cogl_bitmask_set_bits (CoglBitmask *dst, + const CoglBitmask *src) +{ + if (_cogl_bitmask_has_array (src)) + { + GArray *src_array, *dst_array; + int i; + + if (!_cogl_bitmask_has_array (dst)) + _cogl_bitmask_convert_to_array (dst); + + dst_array = (GArray *) *dst; + src_array = (GArray *) *src; + + if (dst_array->len < src_array->len) + g_array_set_size (dst_array, src_array->len); + + for (i = 0; i < src_array->len; i++) + g_array_index (dst_array, unsigned long, i) |= + g_array_index (src_array, unsigned long, i); + } + else if (_cogl_bitmask_has_array (dst)) + { + GArray *dst_array; + + dst_array = (GArray *) *dst; + + g_array_index (dst_array, unsigned long, 0) |= + _cogl_bitmask_to_bits (src); + } + else + *dst = _cogl_bitmask_from_bits (_cogl_bitmask_to_bits (dst) | + _cogl_bitmask_to_bits (src)); +} + +void +_cogl_bitmask_set_range_in_array (CoglBitmask *bitmask, + unsigned int n_bits, + CoglBool value) +{ + GArray *array; + unsigned int array_index, bit_index; + + if (n_bits == 0) + return; + + /* If the bitmask is not already an array then we need to allocate one */ + if (!_cogl_bitmask_has_array (bitmask)) + _cogl_bitmask_convert_to_array (bitmask); + + array = (GArray *) *bitmask; + + /* Get the array index of the top most value that will be touched */ + array_index = ARRAY_INDEX (n_bits - 1); + /* Get the bit index of the top most value */ + bit_index = BIT_INDEX (n_bits - 1); + /* Grow the array if necessary. This will clear the new data */ + if (array_index >= array->len) + g_array_set_size (array, array_index + 1); + + if (value) + { + /* Set the bits that are touching this index */ + g_array_index (array, unsigned long, array_index) |= + ~0UL >> (sizeof (unsigned long) * 8 - 1 - bit_index); + + /* Set all of the bits in any lesser indices */ + memset (array->data, 0xff, sizeof (unsigned long) * array_index); + } + else + { + /* Clear the bits that are touching this index */ + g_array_index (array, unsigned long, array_index) &= ~1UL << bit_index; + + /* Clear all of the bits in any lesser indices */ + memset (array->data, 0x00, sizeof (unsigned long) * array_index); + } +} + +void +_cogl_bitmask_xor_bits (CoglBitmask *dst, + const CoglBitmask *src) +{ + if (_cogl_bitmask_has_array (src)) + { + GArray *src_array, *dst_array; + int i; + + if (!_cogl_bitmask_has_array (dst)) + _cogl_bitmask_convert_to_array (dst); + + dst_array = (GArray *) *dst; + src_array = (GArray *) *src; + + if (dst_array->len < src_array->len) + g_array_set_size (dst_array, src_array->len); + + for (i = 0; i < src_array->len; i++) + g_array_index (dst_array, unsigned long, i) ^= + g_array_index (src_array, unsigned long, i); + } + else if (_cogl_bitmask_has_array (dst)) + { + GArray *dst_array; + + dst_array = (GArray *) *dst; + + g_array_index (dst_array, unsigned long, 0) ^= + _cogl_bitmask_to_bits (src); + } + else + *dst = _cogl_bitmask_from_bits (_cogl_bitmask_to_bits (dst) ^ + _cogl_bitmask_to_bits (src)); +} + +void +_cogl_bitmask_clear_all_in_array (CoglBitmask *bitmask) +{ + GArray *array = (GArray *) *bitmask; + + memset (array->data, 0, sizeof (unsigned long) * array->len); +} + +void +_cogl_bitmask_foreach (const CoglBitmask *bitmask, + CoglBitmaskForeachFunc func, + void *user_data) +{ + if (_cogl_bitmask_has_array (bitmask)) + { + GArray *array = (GArray *) *bitmask; + const unsigned long *values = &g_array_index (array, unsigned long, 0); + int bit_num; + + COGL_FLAGS_FOREACH_START (values, array->len, bit_num) + { + if (!func (bit_num, user_data)) + return; + } + COGL_FLAGS_FOREACH_END; + } + else + { + unsigned long mask = _cogl_bitmask_to_bits (bitmask); + int bit_num; + + COGL_FLAGS_FOREACH_START (&mask, 1, bit_num) + { + if (!func (bit_num, user_data)) + return; + } + COGL_FLAGS_FOREACH_END; + } +} + +void +_cogl_bitmask_set_flags_array (const CoglBitmask *bitmask, + unsigned long *flags) +{ + const GArray *array = (const GArray *) *bitmask; + int i; + + for (i = 0; i < array->len; i++) + flags[i] |= g_array_index (array, unsigned long, i); +} + +int +_cogl_bitmask_popcount_in_array (const CoglBitmask *bitmask) +{ + const GArray *array = (const GArray *) *bitmask; + int pop = 0; + int i; + + for (i = 0; i < array->len; i++) + pop += _cogl_util_popcountl (g_array_index (array, unsigned long, i)); + + return pop; +} + +int +_cogl_bitmask_popcount_upto_in_array (const CoglBitmask *bitmask, + int upto) +{ + const GArray *array = (const GArray *) *bitmask; + + if (upto >= array->len * sizeof (unsigned long) * 8) + return _cogl_bitmask_popcount_in_array (bitmask); + else + { + unsigned long top_mask; + int array_index = ARRAY_INDEX (upto); + int bit_index = BIT_INDEX (upto); + int pop = 0; + int i; + + for (i = 0; i < array_index; i++) + pop += _cogl_util_popcountl (g_array_index (array, unsigned long, i)); + + top_mask = g_array_index (array, unsigned long, array_index); + + return pop + _cogl_util_popcountl (top_mask & ((1UL << bit_index) - 1)); + } +} + +typedef struct +{ + int n_bits; + int *bits; +} CheckData; + +static CoglBool +check_bit (int bit_num, void *user_data) +{ + CheckData *data = user_data; + int i; + + for (i = 0; i < data->n_bits; i++) + if (data->bits[i] == bit_num) + { + data->bits[i] = -1; + return TRUE; + } + + g_assert_not_reached (); + + return TRUE; +} + +static void +verify_bits (const CoglBitmask *bitmask, + ...) +{ + CheckData data; + va_list ap, ap_copy; + int i; + + va_start (ap, bitmask); + G_VA_COPY (ap_copy, ap); + + for (data.n_bits = 0; va_arg (ap, int) != -1; data.n_bits++); + + data.bits = alloca (data.n_bits * (sizeof (int))); + + G_VA_COPY (ap, ap_copy); + + for (i = 0; i < data.n_bits; i++) + data.bits[i] = va_arg (ap, int); + + _cogl_bitmask_foreach (bitmask, check_bit, &data); + + for (i = 0; i < data.n_bits; i++) + g_assert_cmpint (data.bits[i], ==, -1); + + g_assert_cmpint (_cogl_bitmask_popcount (bitmask), ==, data.n_bits); + + for (i = 0; i < 1024; i++) + { + int upto_popcount = 0; + int j; + + G_VA_COPY (ap, ap_copy); + + for (j = 0; j < data.n_bits; j++) + if (va_arg (ap, int) < i) + upto_popcount++; + + g_assert_cmpint (_cogl_bitmask_popcount_upto (bitmask, i), + ==, + upto_popcount); + + G_VA_COPY (ap, ap_copy); + + for (j = 0; j < data.n_bits; j++) + if (va_arg (ap, int) == i) + break; + + g_assert_cmpint (_cogl_bitmask_get (bitmask, i), ==, (j < data.n_bits)); + } +} + +UNIT_TEST (check_bitmask_api, + 0 /* no requirements */, + 0 /* no failure cases */) +{ + CoglBitmask bitmask; + CoglBitmask other_bitmask; + /* A dummy bit to make it use arrays sometimes */ + int dummy_bit; + int i; + + for (dummy_bit = -1; dummy_bit < 256; dummy_bit += 40) + { + _cogl_bitmask_init (&bitmask); + _cogl_bitmask_init (&other_bitmask); + + if (dummy_bit != -1) + _cogl_bitmask_set (&bitmask, dummy_bit, TRUE); + + verify_bits (&bitmask, dummy_bit, -1); + + _cogl_bitmask_set (&bitmask, 1, TRUE); + _cogl_bitmask_set (&bitmask, 4, TRUE); + _cogl_bitmask_set (&bitmask, 5, TRUE); + + verify_bits (&bitmask, 1, 4, 5, dummy_bit, -1); + + _cogl_bitmask_set (&bitmask, 4, FALSE); + + verify_bits (&bitmask, 1, 5, dummy_bit, -1); + + _cogl_bitmask_clear_all (&bitmask); + + verify_bits (&bitmask, -1); + + if (dummy_bit != -1) + _cogl_bitmask_set (&bitmask, dummy_bit, TRUE); + + verify_bits (&bitmask, dummy_bit, -1); + + _cogl_bitmask_set (&bitmask, 1, TRUE); + _cogl_bitmask_set (&bitmask, 4, TRUE); + _cogl_bitmask_set (&bitmask, 5, TRUE); + _cogl_bitmask_set (&other_bitmask, 5, TRUE); + _cogl_bitmask_set (&other_bitmask, 6, TRUE); + + _cogl_bitmask_set_bits (&bitmask, &other_bitmask); + + verify_bits (&bitmask, 1, 4, 5, 6, dummy_bit, -1); + verify_bits (&other_bitmask, 5, 6, -1); + + _cogl_bitmask_set (&bitmask, 6, FALSE); + + verify_bits (&bitmask, 1, 4, 5, dummy_bit, -1); + + _cogl_bitmask_xor_bits (&bitmask, &other_bitmask); + + verify_bits (&bitmask, 1, 4, 6, dummy_bit, -1); + verify_bits (&other_bitmask, 5, 6, -1); + + _cogl_bitmask_set_range (&bitmask, 5, TRUE); + + verify_bits (&bitmask, 0, 1, 2, 3, 4, 6, dummy_bit, -1); + + _cogl_bitmask_set_range (&bitmask, 4, FALSE); + + verify_bits (&bitmask, 4, 6, dummy_bit, -1); + + _cogl_bitmask_destroy (&other_bitmask); + _cogl_bitmask_destroy (&bitmask); + } + + /* Extra tests for really long bitmasks */ + _cogl_bitmask_init (&bitmask); + _cogl_bitmask_set_range (&bitmask, 400, TRUE); + _cogl_bitmask_init (&other_bitmask); + _cogl_bitmask_set (&other_bitmask, 5, TRUE); + _cogl_bitmask_xor_bits (&bitmask, &other_bitmask); + + for (i = 0; i < 1024; i++) + g_assert_cmpint (_cogl_bitmask_get (&bitmask, i), + ==, + (i == 5 ? FALSE : + i < 400 ? TRUE : + FALSE)); + + _cogl_bitmask_set_range (&other_bitmask, 500, TRUE); + _cogl_bitmask_set_bits (&bitmask, &other_bitmask); + + for (i = 0; i < 1024; i++) + g_assert_cmpint (_cogl_bitmask_get (&bitmask, i), ==, (i < 500)); +} diff --git a/cogl/cogl/cogl-bitmask.h b/cogl/cogl/cogl-bitmask.h new file mode 100644 index 0000000..35fc441 --- /dev/null +++ b/cogl/cogl/cogl-bitmask.h @@ -0,0 +1,312 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Neil Roberts + */ + +#ifndef __COGL_BITMASK_H +#define __COGL_BITMASK_H + +#include +#include "cogl-util.h" + +COGL_BEGIN_DECLS + +/* + * CoglBitmask implements a growable array of bits. A CoglBitmask can + * be allocated on the stack but it must be initialised with + * _cogl_bitmask_init() before use and then destroyed with + * _cogl_bitmask_destroy(). A CoglBitmask will try to avoid allocating + * any memory unless more than the number of bits in a long - 1 bits + * are needed. + * + * Internally a CoglBitmask is a pointer. If the least significant bit + * of the pointer is 1 then the rest of the bits are directly used as + * part of the bitmask, otherwise it is a pointer to a GArray of + * unsigned ints. This relies on the fact the g_malloc will return a + * pointer aligned to at least two bytes (so that the least + * significant bit of the address is always 0). It also assumes that + * the size of a pointer is always greater than or equal to the size + * of a long (although there is a compile time assert to verify this). + * + * If the maximum possible bit number in the set is known at compile + * time, it may make more sense to use the macros in cogl-flags.h + * instead of this type. + */ + +typedef struct _CoglBitmaskImaginaryType *CoglBitmask; + +/* These are internal helper macros */ +#define _cogl_bitmask_to_number(bitmask) \ + ((unsigned long) (*bitmask)) +#define _cogl_bitmask_to_bits(bitmask) \ + (_cogl_bitmask_to_number (bitmask) >> 1UL) +/* The least significant bit is set to mark that no array has been + allocated yet */ +#define _cogl_bitmask_from_bits(bits) \ + ((void *) ((((unsigned long) (bits)) << 1UL) | 1UL)) + +/* Internal helper macro to determine whether this bitmask has a + GArray allocated or whether the pointer is just used directly */ +#define _cogl_bitmask_has_array(bitmask) \ + (!(_cogl_bitmask_to_number (bitmask) & 1UL)) + +/* Number of bits we can use before needing to allocate an array */ +#define COGL_BITMASK_MAX_DIRECT_BITS (sizeof (unsigned long) * 8 - 1) + +/* + * _cogl_bitmask_init: + * @bitmask: A pointer to a bitmask + * + * Initialises the cogl bitmask. This must be called before any other + * bitmask functions are called. Initially all of the values are + * zero + */ +#define _cogl_bitmask_init(bitmask) \ + G_STMT_START { *(bitmask) = _cogl_bitmask_from_bits (0); } G_STMT_END + +CoglBool +_cogl_bitmask_get_from_array (const CoglBitmask *bitmask, + unsigned int bit_num); + +void +_cogl_bitmask_set_in_array (CoglBitmask *bitmask, + unsigned int bit_num, + CoglBool value); + +void +_cogl_bitmask_set_range_in_array (CoglBitmask *bitmask, + unsigned int n_bits, + CoglBool value); + +void +_cogl_bitmask_clear_all_in_array (CoglBitmask *bitmask); + +void +_cogl_bitmask_set_flags_array (const CoglBitmask *bitmask, + unsigned long *flags); + +int +_cogl_bitmask_popcount_in_array (const CoglBitmask *bitmask); + +int +_cogl_bitmask_popcount_upto_in_array (const CoglBitmask *bitmask, + int upto); + +/* + * cogl_bitmask_set_bits: + * @dst: The bitmask to modify + * @src: The bitmask to copy bits from + * + * This makes sure that all of the bits that are set in @src are also + * set in @dst. Any unset bits in @src are left alone in @dst. + */ +void +_cogl_bitmask_set_bits (CoglBitmask *dst, + const CoglBitmask *src); + +/* + * cogl_bitmask_xor_bits: + * @dst: The bitmask to modify + * @src: The bitmask to copy bits from + * + * For every bit that is set in src, the corresponding bit in dst is + * inverted. + */ +void +_cogl_bitmask_xor_bits (CoglBitmask *dst, + const CoglBitmask *src); + +/* The foreach function can return FALSE to stop iteration */ +typedef CoglBool (* CoglBitmaskForeachFunc) (int bit_num, void *user_data); + +/* + * cogl_bitmask_foreach: + * @bitmask: A pointer to a bitmask + * @func: A callback function + * @user_data: A pointer to pass to the callback + * + * This calls @func for each bit that is set in @bitmask. + */ +void +_cogl_bitmask_foreach (const CoglBitmask *bitmask, + CoglBitmaskForeachFunc func, + void *user_data); + +/* + * _cogl_bitmask_get: + * @bitmask: A pointer to a bitmask + * @bit_num: A bit number + * + * Return value: whether bit number @bit_num is set in @bitmask + */ +static inline CoglBool +_cogl_bitmask_get (const CoglBitmask *bitmask, unsigned int bit_num) +{ + if (_cogl_bitmask_has_array (bitmask)) + return _cogl_bitmask_get_from_array (bitmask, bit_num); + else if (bit_num >= COGL_BITMASK_MAX_DIRECT_BITS) + return FALSE; + else + return !!(_cogl_bitmask_to_bits (bitmask) & (1UL << bit_num)); +} + +/* + * _cogl_bitmask_set: + * @bitmask: A pointer to a bitmask + * @bit_num: A bit number + * @value: The new value + * + * Sets or resets a bit number @bit_num in @bitmask according to @value. + */ +static inline void +_cogl_bitmask_set (CoglBitmask *bitmask, unsigned int bit_num, CoglBool value) +{ + if (_cogl_bitmask_has_array (bitmask) || + bit_num >= COGL_BITMASK_MAX_DIRECT_BITS) + _cogl_bitmask_set_in_array (bitmask, bit_num, value); + else if (value) + *bitmask = _cogl_bitmask_from_bits (_cogl_bitmask_to_bits (bitmask) | + (1UL << bit_num)); + else + *bitmask = _cogl_bitmask_from_bits (_cogl_bitmask_to_bits (bitmask) & + ~(1UL << bit_num)); +} + +/* + * _cogl_bitmask_set_range: + * @bitmask: A pointer to a bitmask + * @n_bits: The number of bits to set + * @value: The value to set + * + * Sets the first @n_bits in @bitmask to @value. + */ +static inline void +_cogl_bitmask_set_range (CoglBitmask *bitmask, + unsigned int n_bits, + CoglBool value) +{ + if (_cogl_bitmask_has_array (bitmask) || + n_bits > COGL_BITMASK_MAX_DIRECT_BITS) + _cogl_bitmask_set_range_in_array (bitmask, n_bits, value); + else if (value) + *bitmask = _cogl_bitmask_from_bits (_cogl_bitmask_to_bits (bitmask) | + ~(~0UL << n_bits)); + else + *bitmask = _cogl_bitmask_from_bits (_cogl_bitmask_to_bits (bitmask) & + (~0UL << n_bits)); +} + +/* + * _cogl_bitmask_destroy: + * @bitmask: A pointer to a bitmask + * + * Destroys any resources allocated by the bitmask + */ +static inline void +_cogl_bitmask_destroy (CoglBitmask *bitmask) +{ + if (_cogl_bitmask_has_array (bitmask)) + g_array_free ((GArray *) *bitmask, TRUE); +} + +/* + * _cogl_bitmask_clear_all: + * @bitmask: A pointer to a bitmask + * + * Clears all the bits in a bitmask without destroying any resources. + */ +static inline void +_cogl_bitmask_clear_all (CoglBitmask *bitmask) +{ + if (_cogl_bitmask_has_array (bitmask)) + _cogl_bitmask_clear_all_in_array (bitmask); + else + *bitmask = _cogl_bitmask_from_bits (0); +} + +/* + * _cogl_bitmask_set_flags: + * @bitmask: A pointer to a bitmask + * @flags: An array of flags + * + * Bitwise or's the bits from @bitmask into the flags array (see + * cogl-flags) pointed to by @flags. + */ +static inline void +_cogl_bitmask_set_flags (const CoglBitmask *bitmask, + unsigned long *flags) +{ + if (_cogl_bitmask_has_array (bitmask)) + _cogl_bitmask_set_flags_array (bitmask, flags); + else + flags[0] |= _cogl_bitmask_to_bits (bitmask); +} + +/* + * _cogl_bitmask_popcount: + * @bitmask: A pointer to a bitmask + * + * Counts the number of bits that are set in the bitmask. + * + * Return value: the number of bits set in @bitmask. + */ +static inline int +_cogl_bitmask_popcount (const CoglBitmask *bitmask) +{ + return (_cogl_bitmask_has_array (bitmask) ? + _cogl_bitmask_popcount_in_array (bitmask) : + _cogl_util_popcountl (_cogl_bitmask_to_bits (bitmask))); +} + +/* + * _cogl_bitmask_popcount: + * @Bitmask: A pointer to a bitmask + * @upto: The maximum bit index to consider + * + * Counts the number of bits that are set and have an index which is + * less than @upto. + * + * Return value: the number of bits set in @bitmask that are less than @upto. + */ +static inline int +_cogl_bitmask_popcount_upto (const CoglBitmask *bitmask, + int upto) +{ + if (_cogl_bitmask_has_array (bitmask)) + return _cogl_bitmask_popcount_upto_in_array (bitmask, upto); + else if (upto >= (int) COGL_BITMASK_MAX_DIRECT_BITS) + return _cogl_util_popcountl (_cogl_bitmask_to_bits (bitmask)); + else + return _cogl_util_popcountl (_cogl_bitmask_to_bits (bitmask) & + ((1UL << upto) - 1)); +} + +COGL_END_DECLS + +#endif /* __COGL_BITMASK_H */ diff --git a/cogl/cogl/cogl-blend-string.c b/cogl/cogl/cogl-blend-string.c new file mode 100644 index 0000000..659152d --- /dev/null +++ b/cogl/cogl/cogl-blend-string.c @@ -0,0 +1,1003 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include +#include + +#include + +#include "cogl-context-private.h" +#include "cogl-debug.h" +#include "cogl-blend-string.h" +#include "cogl-error-private.h" + +typedef enum _ParserState +{ + PARSER_STATE_EXPECT_DEST_CHANNELS, + PARSER_STATE_SCRAPING_DEST_CHANNELS, + PARSER_STATE_EXPECT_FUNCTION_NAME, + PARSER_STATE_SCRAPING_FUNCTION_NAME, + PARSER_STATE_EXPECT_ARG_START, + PARSER_STATE_EXPECT_STATEMENT_END +} ParserState; + +typedef enum _ParserArgState +{ + PARSER_ARG_STATE_START, + PARSER_ARG_STATE_EXPECT_MINUS, + PARSER_ARG_STATE_EXPECT_COLOR_SRC_NAME, + PARSER_ARG_STATE_SCRAPING_COLOR_SRC_NAME, + PARSER_ARG_STATE_MAYBE_COLOR_MASK, + PARSER_ARG_STATE_SCRAPING_MASK, + PARSER_ARG_STATE_MAYBE_MULT, + PARSER_ARG_STATE_EXPECT_OPEN_PAREN, + PARSER_ARG_STATE_EXPECT_FACTOR, + PARSER_ARG_STATE_MAYBE_SRC_ALPHA_SATURATE, + PARSER_ARG_STATE_MAYBE_MINUS, + PARSER_ARG_STATE_EXPECT_CLOSE_PAREN, + PARSER_ARG_STATE_EXPECT_END +} ParserArgState; + + +#define DEFINE_COLOR_SOURCE(NAME, NAME_LEN) \ + {/*.type = */COGL_BLEND_STRING_COLOR_SOURCE_ ## NAME, \ + /*.name = */#NAME, \ + /*.name_len = */NAME_LEN} + +static CoglBlendStringColorSourceInfo blending_color_sources[] = { + DEFINE_COLOR_SOURCE (SRC_COLOR, 9), + DEFINE_COLOR_SOURCE (DST_COLOR, 9), + DEFINE_COLOR_SOURCE (CONSTANT, 8) +}; + +static CoglBlendStringColorSourceInfo tex_combine_color_sources[] = { + DEFINE_COLOR_SOURCE (TEXTURE, 7), + /* DEFINE_COLOR_SOURCE (TEXTURE_N, *) - handled manually */ + DEFINE_COLOR_SOURCE (PRIMARY, 7), + DEFINE_COLOR_SOURCE (CONSTANT, 8), + DEFINE_COLOR_SOURCE (PREVIOUS, 8) +}; + +static CoglBlendStringColorSourceInfo tex_combine_texture_n_color_source = { + /*.type = */COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE_N, + /*.name = */"TEXTURE_N", + /*.name_len = */0 +}; + +#undef DEFINE_COLOR_SOURCE + +#define DEFINE_FUNCTION(NAME, NAME_LEN, ARGC) \ + { /*.type = */COGL_BLEND_STRING_FUNCTION_ ## NAME, \ + /*.name = */#NAME, \ + /*.name_len = */NAME_LEN, \ + /*.argc = */ARGC } + +/* NB: These must be sorted so any name that's a subset of another + * comes later than the longer name. */ +static CoglBlendStringFunctionInfo tex_combine_functions[] = { + DEFINE_FUNCTION (REPLACE, 7, 1), + DEFINE_FUNCTION (MODULATE, 8, 2), + DEFINE_FUNCTION (ADD_SIGNED, 10, 2), + DEFINE_FUNCTION (ADD, 3, 2), + DEFINE_FUNCTION (INTERPOLATE, 11, 3), + DEFINE_FUNCTION (SUBTRACT, 8, 2), + DEFINE_FUNCTION (DOT3_RGBA, 9, 2), + DEFINE_FUNCTION (DOT3_RGB, 8, 2) +}; + +static CoglBlendStringFunctionInfo blend_functions[] = { + DEFINE_FUNCTION (ADD, 3, 2) +}; + +#undef DEFINE_FUNCTION + +uint32_t +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 CoglBool +validate_tex_combine_statements (CoglBlendStringStatement *statements, + int n_statements, + CoglError **error) +{ + int i, j; + const char *error_string; + CoglBlendStringError detail = COGL_BLEND_STRING_ERROR_INVALID_ERROR; + + for (i = 0; i < n_statements; i++) + { + for (j = 0; j < statements[i].function->argc; j++) + { + CoglBlendStringArgument *arg = &statements[i].args[j]; + if (arg->source.is_zero) + { + error_string = "You can't use the constant '0' as a texture " + "combine argument"; + goto error; + } + if (!arg->factor.is_one) + { + error_string = "Argument factors are only relevant to blending " + "not texture combining"; + goto error; + } + } + } + + return TRUE; + +error: + _cogl_set_error (error, + COGL_BLEND_STRING_ERROR, + detail, + "Invalid texture combine string: %s", + error_string); + + if (COGL_DEBUG_ENABLED (COGL_DEBUG_BLEND_STRINGS)) + { + g_debug ("Invalid texture combine string: %s", + error_string); + } + return FALSE; +} + +static CoglBool +validate_blend_statements (CoglBlendStringStatement *statements, + int n_statements, + CoglError **error) +{ + int i, j; + const char *error_string; + CoglBlendStringError detail = COGL_BLEND_STRING_ERROR_INVALID_ERROR; + + _COGL_GET_CONTEXT (ctx, 0); + + if (n_statements == 2 && + !ctx->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; + } + + 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; + } + + if (!_cogl_has_private_feature (ctx, + COGL_PRIVATE_FEATURE_BLEND_CONSTANT) && + arg->factor.is_color && + (arg->factor.source.info->type == + COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT)) + { + error_string = "Driver doesn't support constant blend factors"; + detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR; + goto error; + } + } + + return TRUE; + +error: + _cogl_set_error (error, + COGL_BLEND_STRING_ERROR, + detail, + "Invalid blend string: %s", + error_string); + return FALSE; +} + +static CoglBool +validate_statements_for_context (CoglBlendStringStatement *statements, + int n_statements, + CoglBlendStringContext context, + CoglError **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: + _cogl_set_error (error, + COGL_BLEND_STRING_ERROR, + COGL_BLEND_STRING_ERROR_INVALID_ERROR, + "Invalid %s string: %s", + context == COGL_BLEND_STRING_CONTEXT_BLENDING ? + "blend" : "texture combine", + error_string); + + if (COGL_DEBUG_ENABLED (COGL_DEBUG_BLEND_STRINGS)) + { + g_debug ("Invalid %s string: %s", + context == COGL_BLEND_STRING_CONTEXT_BLENDING ? + "blend" : "texture combine", + error_string); + } + + return FALSE; +} + +static void +print_argument (CoglBlendStringArgument *arg) +{ + const char *mask_names[] = { + "RGB", + "A", + "RGBA" + }; + + g_print (" Arg:\n"); + g_print (" is zero = %s\n", arg->source.is_zero ? "yes" : "no"); + if (!arg->source.is_zero) + { + g_print (" color source = %s\n", arg->source.info->name); + g_print (" one minus = %s\n", arg->source.one_minus ? "yes" : "no"); + g_print (" mask = %s\n", mask_names[arg->source.mask]); + g_print (" texture = %d\n", arg->source.texture); + g_print ("\n"); + g_print (" factor is_one = %s\n", arg->factor.is_one ? "yes" : "no"); + g_print (" factor is_src_alpha_saturate = %s\n", + arg->factor.is_src_alpha_saturate ? "yes" : "no"); + g_print (" factor is_color = %s\n", arg->factor.is_color ? "yes" : "no"); + if (arg->factor.is_color) + { + g_print (" factor color:is zero = %s\n", + arg->factor.source.is_zero ? "yes" : "no"); + g_print (" factor color:color source = %s\n", + arg->factor.source.info->name); + g_print (" factor color:one minus = %s\n", + arg->factor.source.one_minus ? "yes" : "no"); + g_print (" factor color:mask = %s\n", + mask_names[arg->factor.source.mask]); + g_print (" factor color:texture = %d\n", + arg->factor.source.texture); + } + } +} + +static void +print_statement (int num, CoglBlendStringStatement *statement) +{ + const char *mask_names[] = { + "RGB", + "A", + "RGBA" + }; + int i; + g_print ("Statement %d:\n", num); + g_print (" Destination channel mask = %s\n", + mask_names[statement->mask]); + g_print (" Function = %s\n", statement->function->name); + for (i = 0; i < statement->function->argc; i++) + print_argument (&statement->args[i]); +} + +static const CoglBlendStringFunctionInfo * +get_function_info (const char *mark, + const char *p, + CoglBlendStringContext context) +{ + 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); + } + + if (len >= 8 && + strncmp (mark, "TEXTURE_", 8) == 0 && + g_ascii_isdigit (mark[8])) + { + return &tex_combine_texture_n_color_source; + } + + 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]; + } + + return NULL; +} + +static CoglBool +is_symbol_char (const char c) +{ + return (g_ascii_isalpha (c) || c == '_') ? TRUE : FALSE; +} + +static CoglBool +is_alphanum_char (const char c) +{ + return (g_ascii_isalnum (c) || c == '_') ? TRUE : FALSE; +} + +static CoglBool +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, + CoglError **error) +{ + const char *p = *ret_p; + const char *mark = NULL; + const char *error_string = NULL; + ParserArgState state = PARSER_ARG_STATE_START; + CoglBool parsing_factor = FALSE; + CoglBool implicit_factor_brace = 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 != '(') + { + if (is_alphanum_char (*p)) + { + p--; /* compensate for implicit brace and ensure this + * char gets considered part of the blend factor */ + implicit_factor_brace = TRUE; + } + else + { + error_string = "Expected '(' around blend factor or alpha " + "numeric character for blend factor name"; + goto error; + } + } + else + implicit_factor_brace = FALSE; + 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 == '-') + { + if (implicit_factor_brace) + { + error_string = "Expected ( ) braces around blend factor with " + "a subtraction"; + goto error; + } + 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 (implicit_factor_brace) + { + p--; + state = PARSER_ARG_STATE_EXPECT_END; + continue; + } + 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; + _cogl_set_error (error, + COGL_BLEND_STRING_ERROR, + COGL_BLEND_STRING_ERROR_ARGUMENT_PARSE_ERROR, + "Syntax error for argument %d at offset %d: %s", + current_arg, + offset, + error_string); + + if (COGL_DEBUG_ENABLED (COGL_DEBUG_BLEND_STRINGS)) + { + g_debug ("Syntax error for argument %d at offset %d: %s", + current_arg, offset, error_string); + } + return FALSE; + } +} + +int +_cogl_blend_string_compile (const char *string, + CoglBlendStringContext context, + CoglBlendStringStatement *statements, + CoglError **error) +{ + const char *p = string; + const char *mark = NULL; + const char *error_string; + ParserState state = PARSER_STATE_EXPECT_DEST_CHANNELS; + CoglBlendStringStatement *statement = statements; + int current_statement = 0; + int current_arg = 0; + int remaining_argc = 0; + +#if 0 + COGL_DEBUG_SET_FLAG (COGL_DEBUG_BLEND_STRINGS); +#endif + + if (COGL_DEBUG_ENABLED (COGL_DEBUG_BLEND_STRINGS)) + { + COGL_NOTE (BLEND_STRINGS, "Compiling %s string:\n%s\n", + context == COGL_BLEND_STRING_CONTEXT_BLENDING ? + "blend" : "texture combine", + string); + } + + do + { + if (g_ascii_isspace (*p)) + continue; + + if (*p == '\0') + { + switch (state) + { + case PARSER_STATE_EXPECT_DEST_CHANNELS: + if (current_statement != 0) + goto finished; + error_string = "Empty statement"; + goto error; + case PARSER_STATE_SCRAPING_DEST_CHANNELS: + error_string = "Expected an '=' following the destination " + "channel mask"; + goto error; + case PARSER_STATE_EXPECT_FUNCTION_NAME: + error_string = "Expected a function name"; + goto error; + case PARSER_STATE_SCRAPING_FUNCTION_NAME: + error_string = "Expected parenthesis after the function name"; + goto error; + case PARSER_STATE_EXPECT_ARG_START: + error_string = "Expected to find the start of an argument"; + goto error; + case PARSER_STATE_EXPECT_STATEMENT_END: + error_string = "Expected closing parenthesis for statement"; + goto error; + } + } + + switch (state) + { + case PARSER_STATE_EXPECT_DEST_CHANNELS: + mark = p; + state = PARSER_STATE_SCRAPING_DEST_CHANNELS; + + /* fall through */ + case PARSER_STATE_SCRAPING_DEST_CHANNELS: + if (*p != '=') + continue; + if (strncmp (mark, "RGBA", 4) == 0) + statement->mask = COGL_BLEND_STRING_CHANNEL_MASK_RGBA; + else if (strncmp (mark, "RGB", 3) == 0) + statement->mask = COGL_BLEND_STRING_CHANNEL_MASK_RGB; + else if (strncmp (mark, "A", 1) == 0) + statement->mask = COGL_BLEND_STRING_CHANNEL_MASK_ALPHA; + else + { + error_string = "Unknown destination channel mask; " + "expected RGBA=, RGB= or A="; + goto error; + } + state = PARSER_STATE_EXPECT_FUNCTION_NAME; + continue; + + case PARSER_STATE_EXPECT_FUNCTION_NAME: + mark = p; + state = PARSER_STATE_SCRAPING_FUNCTION_NAME; + + /* fall through */ + case PARSER_STATE_SCRAPING_FUNCTION_NAME: + if (*p != '(') + { + if (!is_alphanum_char (*p)) + { + error_string = "non alpha numeric character in function" + "name"; + goto error; + } + continue; + } + statement->function = get_function_info (mark, p, context); + if (!statement->function) + { + error_string = "Unknown function name"; + goto error; + } + remaining_argc = statement->function->argc; + current_arg = 0; + state = PARSER_STATE_EXPECT_ARG_START; + + /* fall through */ + case PARSER_STATE_EXPECT_ARG_START: + if (*p != '(' && *p != ',') + continue; + if (remaining_argc) + { + p++; /* parse_argument expects to see the first char of the arg */ + if (!parse_argument (string, &p, statement, + current_arg, &statement->args[current_arg], + context, error)) + return 0; + current_arg++; + remaining_argc--; + } + if (!remaining_argc) + state = PARSER_STATE_EXPECT_STATEMENT_END; + continue; + + case PARSER_STATE_EXPECT_STATEMENT_END: + if (*p != ')') + { + error_string = "Expected end of statement"; + goto error; + } + state = PARSER_STATE_EXPECT_DEST_CHANNELS; + if (current_statement++ == 1) + goto finished; + statement = &statements[current_statement]; + } + } + while (p++); + +finished: + + if (COGL_DEBUG_ENABLED (COGL_DEBUG_BLEND_STRINGS)) + { + if (current_statement > 0) + print_statement (0, &statements[0]); + if (current_statement > 1) + print_statement (1, &statements[1]); + } + + if (!validate_statements_for_context (statements, + current_statement, + context, + error)) + return 0; + + return current_statement; + +error: + { + int offset = p - string; + _cogl_set_error (error, + COGL_BLEND_STRING_ERROR, + COGL_BLEND_STRING_ERROR_PARSE_ERROR, + "Syntax error at offset %d: %s", + offset, + error_string); + + if (COGL_DEBUG_ENABLED (COGL_DEBUG_BLEND_STRINGS)) + { + g_debug ("Syntax error at offset %d: %s", + offset, error_string); + } + return 0; + } +} + +/* + * INTERNAL TESTING CODE ... + */ + +struct _TestString +{ + const char *string; + CoglBlendStringContext context; +}; + +/* FIXME: this should probably be moved to a unit test */ +int +_cogl_blend_string_test (void); + +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; + + CoglError *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); + cogl_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; +} + diff --git a/cogl/cogl/cogl-blend-string.h b/cogl/cogl/cogl-blend-string.h new file mode 100644 index 0000000..355338c --- /dev/null +++ b/cogl/cogl/cogl-blend-string.h @@ -0,0 +1,144 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef COGL_BLEND_STRING_H +#define COGL_BLEND_STRING_H + +#include +#include + +typedef enum _CoglBlendStringContext +{ + COGL_BLEND_STRING_CONTEXT_BLENDING, + COGL_BLEND_STRING_CONTEXT_TEXTURE_COMBINE +} CoglBlendStringContext; + +/* NB: debug stringify code will get upset if these + * are re-ordered */ +typedef enum _CoglBlendStringChannelMask +{ + COGL_BLEND_STRING_CHANNEL_MASK_RGB, + COGL_BLEND_STRING_CHANNEL_MASK_ALPHA, + COGL_BLEND_STRING_CHANNEL_MASK_RGBA +} CoglBlendStringChannelMask; + +typedef enum _CoglBlendStringColorSourceType +{ + /* blending */ + COGL_BLEND_STRING_COLOR_SOURCE_SRC_COLOR, + COGL_BLEND_STRING_COLOR_SOURCE_DST_COLOR, + + /* shared */ + COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT, + + /* texture combining */ + COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE, + COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE_N, + COGL_BLEND_STRING_COLOR_SOURCE_PRIMARY, + COGL_BLEND_STRING_COLOR_SOURCE_PREVIOUS +} CoglBlendStringColorSourceType; + +typedef struct _CoglBlendStringColorSourceInfo +{ + CoglBlendStringColorSourceType type; + const char *name; + size_t name_len; +} CoglBlendStringColorSourceInfo; + +typedef struct _CoglBlendStringColorSource +{ + CoglBool is_zero; + const CoglBlendStringColorSourceInfo *info; + int texture; /* for the TEXTURE_N color source */ + CoglBool one_minus; + CoglBlendStringChannelMask mask; +} CoglBlendStringColorSource; + +typedef struct _CoglBlendStringFactor +{ + CoglBool is_one; + CoglBool is_src_alpha_saturate; + CoglBool is_color; + CoglBlendStringColorSource source; +} CoglBlendStringFactor; + +typedef struct _CoglBlendStringArgument +{ + CoglBlendStringColorSource source; + CoglBlendStringFactor factor; +} CoglBlendStringArgument; + +typedef enum _CoglBlendStringFunctionType +{ + /* shared */ + COGL_BLEND_STRING_FUNCTION_ADD, + + /* texture combine only */ + COGL_BLEND_STRING_FUNCTION_REPLACE, + COGL_BLEND_STRING_FUNCTION_MODULATE, + COGL_BLEND_STRING_FUNCTION_ADD_SIGNED, + COGL_BLEND_STRING_FUNCTION_INTERPOLATE, + COGL_BLEND_STRING_FUNCTION_SUBTRACT, + COGL_BLEND_STRING_FUNCTION_DOT3_RGB, + COGL_BLEND_STRING_FUNCTION_DOT3_RGBA +} CoglBlendStringFunctionType; + +typedef struct _CoglBlendStringFunctionInfo +{ + enum _CoglBlendStringFunctionType type; + const char *name; + size_t name_len; + int argc; +} CoglBlendStringFunctionInfo; + +typedef struct _CoglBlendStringStatement +{ + CoglBlendStringChannelMask mask; + const CoglBlendStringFunctionInfo *function; + CoglBlendStringArgument args[3]; +} CoglBlendStringStatement; + + +CoglBool +_cogl_blend_string_compile (const char *string, + CoglBlendStringContext context, + CoglBlendStringStatement *statements, + CoglError **error); + +void +_cogl_blend_string_split_rgba_statement (CoglBlendStringStatement *statement, + CoglBlendStringStatement *rgb, + CoglBlendStringStatement *a); + +#endif /* COGL_BLEND_STRING_H */ + diff --git a/cogl/cogl/cogl-blit.c b/cogl/cogl/cogl-blit.c new file mode 100644 index 0000000..af78e21 --- /dev/null +++ b/cogl/cogl/cogl-blit.c @@ -0,0 +1,438 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Neil Roberts + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include + +#include "cogl-util.h" +#include "cogl-blit.h" +#include "cogl-context-private.h" +#include "cogl-framebuffer-private.h" +#include "cogl-texture-private.h" +#include "cogl-texture-2d-private.h" +#include "cogl-private.h" +#include "cogl1-context.h" + +static const CoglBlitMode *_cogl_blit_default_mode = NULL; + +static CoglBool +_cogl_blit_texture_render_begin (CoglBlitData *data) +{ + CoglContext *ctx = data->src_tex->context; + CoglOffscreen *offscreen; + CoglFramebuffer *fb; + CoglPipeline *pipeline; + unsigned int dst_width, dst_height; + CoglError *ignore_error = NULL; + + offscreen = _cogl_offscreen_new_with_texture_full + (data->dst_tex, COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL, 0 /* level */); + + fb = COGL_FRAMEBUFFER (offscreen); + if (!cogl_framebuffer_allocate (fb, &ignore_error)) + { + cogl_error_free (ignore_error); + cogl_object_unref (fb); + return FALSE; + } + + data->dest_fb = fb; + + dst_width = cogl_texture_get_width (data->dst_tex); + dst_height = cogl_texture_get_height (data->dst_tex); + + /* Set up an orthographic projection so we can use pixel + coordinates to render to the texture */ + cogl_framebuffer_orthographic (fb, + 0, 0, dst_width, dst_height, + -1 /* near */, 1 /* far */); + + /* We cache a pipeline used for migrating on to the context so + that it doesn't have to continuously regenerate a shader + program */ + if (ctx->blit_texture_pipeline == NULL) + { + ctx->blit_texture_pipeline = cogl_pipeline_new (ctx); + + cogl_pipeline_set_layer_filters (ctx->blit_texture_pipeline, 0, + COGL_PIPELINE_FILTER_NEAREST, + COGL_PIPELINE_FILTER_NEAREST); + + /* Disable blending by just directly taking the contents of the + source texture */ + cogl_pipeline_set_blend (ctx->blit_texture_pipeline, + "RGBA = ADD(SRC_COLOR, 0)", + NULL); + } + + pipeline = ctx->blit_texture_pipeline; + + cogl_pipeline_set_layer_texture (pipeline, 0, data->src_tex); + + data->pipeline = pipeline; + + return TRUE; +} + +static void +_cogl_blit_texture_render_blit (CoglBlitData *data, + int src_x, + int src_y, + int dst_x, + int dst_y, + int width, + int height) +{ + cogl_framebuffer_draw_textured_rectangle (data->dest_fb, + data->pipeline, + dst_x, dst_y, + dst_x + width, + dst_y + height, + src_x / (float) data->src_width, + src_y / (float) data->src_height, + (src_x + width) / + (float) data->src_width, + (src_y + height) / + (float) data->src_height); +} + +static void +_cogl_blit_texture_render_end (CoglBlitData *data) +{ + CoglContext *ctx = data->src_tex->context; + + /* Attach the target texture to the texture render pipeline so that + we don't keep a reference to the source texture forever. This is + assuming that the destination texture will live for a long time + which is currently the case when cogl_blit_* is used from the + atlas code. It may be better in future to keep around a set of + dummy 1x1 textures for each texture target that we could bind + instead. This would also be useful when using a pipeline as a + hash table key such as for the ARBfp program cache. */ + cogl_pipeline_set_layer_texture (ctx->blit_texture_pipeline, 0, + data->dst_tex); + + cogl_object_unref (data->dest_fb); +} + +static CoglBool +_cogl_blit_framebuffer_begin (CoglBlitData *data) +{ + CoglContext *ctx = data->src_tex->context; + CoglOffscreen *dst_offscreen = NULL, *src_offscreen = NULL; + CoglFramebuffer *dst_fb, *src_fb; + CoglError *ignore_error = NULL; + + /* We can only blit between FBOs if both textures are the same + format and the blit framebuffer extension is supported */ + if ((_cogl_texture_get_format (data->src_tex) & ~COGL_A_BIT) != + (_cogl_texture_get_format (data->dst_tex) & ~COGL_A_BIT) || + !_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT)) + return FALSE; + + dst_offscreen = _cogl_offscreen_new_with_texture_full + (data->dst_tex, COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL, 0 /* level */); + + dst_fb = COGL_FRAMEBUFFER (dst_offscreen); + if (!cogl_framebuffer_allocate (dst_fb, &ignore_error)) + { + cogl_error_free (ignore_error); + goto error; + } + + src_offscreen= _cogl_offscreen_new_with_texture_full + (data->src_tex, + COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL, + 0 /* level */); + + src_fb = COGL_FRAMEBUFFER (src_offscreen); + if (!cogl_framebuffer_allocate (src_fb, &ignore_error)) + { + cogl_error_free (ignore_error); + goto error; + } + + data->src_fb = src_fb; + data->dest_fb = dst_fb; + + return TRUE; + +error: + + if (dst_offscreen) + cogl_object_unref (dst_offscreen); + if (src_offscreen) + cogl_object_unref (src_offscreen); + + return FALSE; +} + +static void +_cogl_blit_framebuffer_blit (CoglBlitData *data, + int src_x, + int src_y, + int dst_x, + int dst_y, + int width, + int height) +{ + _cogl_blit_framebuffer (data->src_fb, + data->dest_fb, + src_x, src_y, + dst_x, dst_y, + width, height); +} + +static void +_cogl_blit_framebuffer_end (CoglBlitData *data) +{ + cogl_object_unref (data->src_fb); + cogl_object_unref (data->dest_fb); +} + +static CoglBool +_cogl_blit_copy_tex_sub_image_begin (CoglBlitData *data) +{ + CoglOffscreen *offscreen; + CoglFramebuffer *fb; + CoglError *ignore_error = NULL; + + /* This will only work if the target texture is a CoglTexture2D */ + if (!cogl_is_texture_2d (data->dst_tex)) + return FALSE; + + offscreen = _cogl_offscreen_new_with_texture_full + (data->src_tex, COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL, 0 /* level */); + + fb = COGL_FRAMEBUFFER (offscreen); + if (!cogl_framebuffer_allocate (fb, &ignore_error)) + { + cogl_error_free (ignore_error); + cogl_object_unref (fb); + return FALSE; + } + + data->src_fb = fb; + + return TRUE; +} + +static void +_cogl_blit_copy_tex_sub_image_blit (CoglBlitData *data, + int src_x, + int src_y, + int dst_x, + int dst_y, + int width, + int height) +{ + _cogl_texture_2d_copy_from_framebuffer (COGL_TEXTURE_2D (data->dst_tex), + src_x, src_y, + width, height, + data->src_fb, + dst_x, dst_y, + 0); /* level */ +} + +static void +_cogl_blit_copy_tex_sub_image_end (CoglBlitData *data) +{ + cogl_object_unref (data->src_fb); +} + +static CoglBool +_cogl_blit_get_tex_data_begin (CoglBlitData *data) +{ + data->format = _cogl_texture_get_format (data->src_tex); + data->bpp = _cogl_pixel_format_get_bytes_per_pixel (data->format); + + data->image_data = g_malloc (data->bpp * data->src_width * + data->src_height); + cogl_texture_get_data (data->src_tex, data->format, + data->src_width * data->bpp, data->image_data); + + return TRUE; +} + +static void +_cogl_blit_get_tex_data_blit (CoglBlitData *data, + int src_x, + int src_y, + int dst_x, + int dst_y, + int width, + int height) +{ + CoglError *ignore = NULL; + int rowstride = data->src_width * data->bpp; + int offset = rowstride * src_y + src_x * data->bpp; + + _cogl_texture_set_region (data->dst_tex, + width, height, + data->format, + rowstride, + data->image_data + offset, + dst_x, dst_y, + 0, /* level */ + &ignore); + /* TODO: support chaining up errors during the blit */ +} + +static void +_cogl_blit_get_tex_data_end (CoglBlitData *data) +{ + g_free (data->image_data); +} + +/* These should be specified in order of preference */ +static const CoglBlitMode +_cogl_blit_modes[] = + { + { + "texture-render", + _cogl_blit_texture_render_begin, + _cogl_blit_texture_render_blit, + _cogl_blit_texture_render_end + }, + { + "framebuffer", + _cogl_blit_framebuffer_begin, + _cogl_blit_framebuffer_blit, + _cogl_blit_framebuffer_end + }, + { + "copy-tex-sub-image", + _cogl_blit_copy_tex_sub_image_begin, + _cogl_blit_copy_tex_sub_image_blit, + _cogl_blit_copy_tex_sub_image_end + }, + { + "get-tex-data", + _cogl_blit_get_tex_data_begin, + _cogl_blit_get_tex_data_blit, + _cogl_blit_get_tex_data_end + } + }; + +void +_cogl_blit_begin (CoglBlitData *data, + CoglTexture *dst_tex, + CoglTexture *src_tex) +{ + int i; + + if (_cogl_blit_default_mode == NULL) + { + const char *default_mode_string; + + /* Allow the default to be specified with an environment + variable. For the time being these functions are only used + when blitting between atlas textures so the environment + variable is named to be specific to the atlas code. If we + want to use the code in other places we should create another + environment variable for each specific use case */ + if ((default_mode_string = g_getenv ("COGL_ATLAS_DEFAULT_BLIT_MODE"))) + { + for (i = 0; i < G_N_ELEMENTS (_cogl_blit_modes); i++) + if (!strcmp (_cogl_blit_modes[i].name, default_mode_string)) + { + _cogl_blit_default_mode = _cogl_blit_modes + i; + break; + } + + if (i >= G_N_ELEMENTS (_cogl_blit_modes)) + { + g_warning ("Unknown blit mode %s", default_mode_string); + _cogl_blit_default_mode = _cogl_blit_modes; + } + } + else + /* Default to the first blit mode */ + _cogl_blit_default_mode = _cogl_blit_modes; + } + + memset (data, 0, sizeof (CoglBlitData)); + + data->dst_tex = dst_tex; + data->src_tex = src_tex; + + data->src_width = cogl_texture_get_width (src_tex); + data->src_height = cogl_texture_get_height (src_tex); + + /* Try the default blit mode first */ + if (!_cogl_blit_default_mode->begin_func (data)) + { + COGL_NOTE (ATLAS, "Failed to set up blit mode %s", + _cogl_blit_default_mode->name); + + /* Try all of the other modes in order */ + for (i = 0; i < G_N_ELEMENTS (_cogl_blit_modes); i++) + if (_cogl_blit_modes + i != _cogl_blit_default_mode && + _cogl_blit_modes[i].begin_func (data)) + { + /* Use this mode as the default from now on */ + _cogl_blit_default_mode = _cogl_blit_modes + i; + break; + } + else + COGL_NOTE (ATLAS, + "Failed to set up blit mode %s", + _cogl_blit_modes[i].name); + + /* The last blit mode can't fail so this should never happen */ + _COGL_RETURN_IF_FAIL (i < G_N_ELEMENTS (_cogl_blit_modes)); + } + + data->blit_mode = _cogl_blit_default_mode; + + COGL_NOTE (ATLAS, "Setup blit using %s", _cogl_blit_default_mode->name); +} + +void +_cogl_blit (CoglBlitData *data, + int src_x, + int src_y, + int dst_x, + int dst_y, + int width, + int height) +{ + data->blit_mode->blit_func (data, src_x, src_y, dst_x, dst_y, width, height); +} + +void +_cogl_blit_end (CoglBlitData *data) +{ + data->blit_mode->end_func (data); +} diff --git a/cogl/cogl/cogl-blit.h b/cogl/cogl/cogl-blit.h new file mode 100644 index 0000000..f4e25e7 --- /dev/null +++ b/cogl/cogl/cogl-blit.h @@ -0,0 +1,101 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __COGL_BLIT_H +#define __COGL_BLIT_H + +#include +#include "cogl-object-private.h" +#include "cogl-texture.h" +#include "cogl-framebuffer.h" + +/* This structures and functions are used when a series of blits needs + to be performed between two textures. In this case there are + multiple methods we can use, most of which involve transferring + between an FBO bound to the texture. */ + +typedef struct _CoglBlitData CoglBlitData; + +typedef CoglBool (* CoglBlitBeginFunc) (CoglBlitData *data); +typedef void (* CoglBlitEndFunc) (CoglBlitData *data); + +typedef void (* CoglBlitFunc) (CoglBlitData *data, + int src_x, + int src_y, + int dst_x, + int dst_y, + int width, + int height); + +typedef struct +{ + const char *name; + CoglBlitBeginFunc begin_func; + CoglBlitFunc blit_func; + CoglBlitEndFunc end_func; +} CoglBlitMode; + +struct _CoglBlitData +{ + CoglTexture *src_tex, *dst_tex; + + unsigned int src_width; + unsigned int src_height; + + const CoglBlitMode *blit_mode; + + /* If we're not using an FBO then we g_malloc a buffer and copy the + complete texture data in */ + unsigned char *image_data; + CoglPixelFormat format; + + int bpp; + + CoglFramebuffer *src_fb; + CoglFramebuffer *dest_fb; + CoglPipeline *pipeline; +}; + +void +_cogl_blit_begin (CoglBlitData *data, + CoglTexture *dst_tex, + CoglTexture *src_tex); + +void +_cogl_blit (CoglBlitData *data, + int src_x, + int src_y, + int dst_x, + int dst_y, + int width, + int height); + +void +_cogl_blit_end (CoglBlitData *data); + +#endif /* __COGL_BLIT_H */ diff --git a/cogl/cogl/cogl-boxed-value.c b/cogl/cogl/cogl-boxed-value.c new file mode 100644 index 0000000..fb8f27b --- /dev/null +++ b/cogl/cogl/cogl-boxed-value.c @@ -0,0 +1,377 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include + +#include "cogl-boxed-value.h" +#include "cogl-context-private.h" +#include "cogl-util-gl-private.h" + +CoglBool +_cogl_boxed_value_equal (const CoglBoxedValue *bva, + const CoglBoxedValue *bvb) +{ + const void *pa, *pb; + + if (bva->type != bvb->type) + return FALSE; + + switch (bva->type) + { + case COGL_BOXED_NONE: + return TRUE; + + case COGL_BOXED_INT: + if (bva->size != bvb->size || bva->count != bvb->count) + return FALSE; + + if (bva->count == 1) + { + pa = bva->v.int_value; + pb = bvb->v.int_value; + } + else + { + pa = bva->v.int_array; + pb = bvb->v.int_array; + } + + return !memcmp (pa, pb, sizeof (int) * bva->size * bva->count); + + case COGL_BOXED_FLOAT: + if (bva->size != bvb->size || bva->count != bvb->count) + return FALSE; + + if (bva->count == 1) + { + pa = bva->v.float_value; + pb = bvb->v.float_value; + } + else + { + pa = bva->v.float_array; + pb = bvb->v.float_array; + } + + return !memcmp (pa, pb, sizeof (float) * bva->size * bva->count); + + case COGL_BOXED_MATRIX: + if (bva->size != bvb->size || + bva->count != bvb->count) + return FALSE; + + if (bva->count == 1) + { + pa = bva->v.matrix; + pb = bvb->v.matrix; + } + else + { + pa = bva->v.array; + pb = bvb->v.array; + } + + return !memcmp (pa, pb, + sizeof (float) * bva->size * bva->size * bva->count); + } + + g_warn_if_reached (); + + return FALSE; +} + +static void +_cogl_boxed_value_tranpose (float *dst, + int size, + const float *src) +{ + int y, x; + + /* If the value is transposed we'll just transpose it now as it + * is copied into the boxed value instead of passing TRUE to + * glUniformMatrix because that is not supported on GLES and it + * doesn't seem like the GL driver would be able to do anything + * much smarter than this anyway */ + + for (y = 0; y < size; y++) + for (x = 0; x < size; x++) + *(dst++) = src[y + x * size]; +} + +static void +_cogl_boxed_value_set_x (CoglBoxedValue *bv, + int size, + int count, + CoglBoxedType type, + size_t value_size, + const void *value, + CoglBool transpose) +{ + if (count == 1) + { + if (bv->count > 1) + g_free (bv->v.array); + + if (transpose) + _cogl_boxed_value_tranpose (bv->v.float_value, + size, + value); + else + memcpy (bv->v.float_value, value, value_size); + } + else + { + if (bv->count > 1) + { + if (bv->count != count || + bv->size != size || + bv->type != type) + { + g_free (bv->v.array); + bv->v.array = g_malloc (count * value_size); + } + } + else + bv->v.array = g_malloc (count * value_size); + + if (transpose) + { + int value_num; + + for (value_num = 0; value_num < count; value_num++) + _cogl_boxed_value_tranpose (bv->v.float_array + + value_num * size * size, + size, + (const float *) value + + value_num * size * size); + } + else + memcpy (bv->v.array, value, count * value_size); + } + + bv->type = type; + bv->size = size; + bv->count = count; +} + +void +_cogl_boxed_value_set_1f (CoglBoxedValue *bv, + float value) +{ + _cogl_boxed_value_set_x (bv, + 1, 1, COGL_BOXED_FLOAT, + sizeof (float), &value, FALSE); +} + +void +_cogl_boxed_value_set_1i (CoglBoxedValue *bv, + int value) +{ + _cogl_boxed_value_set_x (bv, + 1, 1, COGL_BOXED_INT, + sizeof (int), &value, FALSE); +} + +void +_cogl_boxed_value_set_float (CoglBoxedValue *bv, + int n_components, + int count, + const float *value) +{ + _cogl_boxed_value_set_x (bv, + n_components, count, + COGL_BOXED_FLOAT, + sizeof (float) * n_components, value, FALSE); +} + +void +_cogl_boxed_value_set_int (CoglBoxedValue *bv, + int n_components, + int count, + const int *value) +{ + _cogl_boxed_value_set_x (bv, + n_components, count, + COGL_BOXED_INT, + sizeof (int) * n_components, value, FALSE); +} + +void +_cogl_boxed_value_set_matrix (CoglBoxedValue *bv, + int dimensions, + int count, + CoglBool transpose, + const float *value) +{ + _cogl_boxed_value_set_x (bv, + dimensions, count, + COGL_BOXED_MATRIX, + sizeof (float) * dimensions * dimensions, + value, + transpose); +} + +void +_cogl_boxed_value_copy (CoglBoxedValue *dst, + const CoglBoxedValue *src) +{ + *dst = *src; + + if (src->count > 1) + { + switch (src->type) + { + case COGL_BOXED_NONE: + break; + + case COGL_BOXED_INT: + dst->v.int_array = g_memdup (src->v.int_array, + src->size * src->count * sizeof (int)); + break; + + case COGL_BOXED_FLOAT: + dst->v.float_array = g_memdup (src->v.float_array, + src->size * + src->count * + sizeof (float)); + break; + + case COGL_BOXED_MATRIX: + dst->v.float_array = g_memdup (src->v.float_array, + src->size * src->size * + src->count * sizeof (float)); + break; + } + } +} + +void +_cogl_boxed_value_destroy (CoglBoxedValue *bv) +{ + if (bv->count > 1) + g_free (bv->v.array); +} + +void +_cogl_boxed_value_set_uniform (CoglContext *ctx, + GLint location, + const CoglBoxedValue *value) +{ + switch (value->type) + { + case COGL_BOXED_NONE: + break; + + case COGL_BOXED_INT: + { + const int *ptr; + + if (value->count == 1) + ptr = value->v.int_value; + else + ptr = value->v.int_array; + + switch (value->size) + { + case 1: + GE( ctx, glUniform1iv (location, value->count, ptr) ); + break; + case 2: + GE( ctx, glUniform2iv (location, value->count, ptr) ); + break; + case 3: + GE( ctx, glUniform3iv (location, value->count, ptr) ); + break; + case 4: + GE( ctx, glUniform4iv (location, value->count, ptr) ); + break; + } + } + break; + + case COGL_BOXED_FLOAT: + { + const float *ptr; + + if (value->count == 1) + ptr = value->v.float_value; + else + ptr = value->v.float_array; + + switch (value->size) + { + case 1: + GE( ctx, glUniform1fv (location, value->count, ptr) ); + break; + case 2: + GE( ctx, glUniform2fv (location, value->count, ptr) ); + break; + case 3: + GE( ctx, glUniform3fv (location, value->count, ptr) ); + break; + case 4: + GE( ctx, glUniform4fv (location, value->count, ptr) ); + break; + } + } + break; + + case COGL_BOXED_MATRIX: + { + const float *ptr; + + if (value->count == 1) + ptr = value->v.matrix; + else + ptr = value->v.float_array; + + switch (value->size) + { + case 2: + GE( ctx, glUniformMatrix2fv (location, value->count, + FALSE, ptr) ); + break; + case 3: + GE( ctx, glUniformMatrix3fv (location, value->count, + FALSE, ptr) ); + break; + case 4: + GE( ctx, glUniformMatrix4fv (location, value->count, + FALSE, ptr) ); + break; + } + } + break; + } +} diff --git a/cogl/cogl/cogl-boxed-value.h b/cogl/cogl/cogl-boxed-value.h new file mode 100644 index 0000000..c8eda44 --- /dev/null +++ b/cogl/cogl/cogl-boxed-value.h @@ -0,0 +1,117 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_BOXED_VALUE_H +#define __COGL_BOXED_VALUE_H + +#include + +#include "cogl-context.h" + +typedef enum { + COGL_BOXED_NONE, + COGL_BOXED_INT, + COGL_BOXED_FLOAT, + COGL_BOXED_MATRIX +} CoglBoxedType; + +typedef struct _CoglBoxedValue +{ + CoglBoxedType type; + int size, count; + + union { + float float_value[4]; + int int_value[4]; + float matrix[16]; + float *float_array; + int *int_array; + void *array; + } v; +} CoglBoxedValue; + +#define _cogl_boxed_value_init(bv) \ + G_STMT_START { \ + CoglBoxedValue *_bv = (bv); \ + _bv->type = COGL_BOXED_NONE; \ + _bv->count = 1; \ + } G_STMT_END + +CoglBool +_cogl_boxed_value_equal (const CoglBoxedValue *bva, + const CoglBoxedValue *bvb); + +void +_cogl_boxed_value_set_1f (CoglBoxedValue *bv, + float value); + +void +_cogl_boxed_value_set_1i (CoglBoxedValue *bv, + int value); + +void +_cogl_boxed_value_set_float (CoglBoxedValue *bv, + int n_components, + int count, + const float *value); + +void +_cogl_boxed_value_set_int (CoglBoxedValue *bv, + int n_components, + int count, + const int *value); + +void +_cogl_boxed_value_set_matrix (CoglBoxedValue *bv, + int dimensions, + int count, + CoglBool transpose, + const float *value); + +/* + * _cogl_boxed_value_copy: + * @dst: The destination boxed value + * @src: The source boxed value + * + * This copies @src to @dst. It is assumed that @dst is initialised. + */ +void +_cogl_boxed_value_copy (CoglBoxedValue *dst, + const CoglBoxedValue *src); + +void +_cogl_boxed_value_destroy (CoglBoxedValue *bv); + +void +_cogl_boxed_value_set_uniform (CoglContext *ctx, + int location, + const CoglBoxedValue *value); + +#endif /* __COGL_BOXED_VALUE_H */ diff --git a/cogl/cogl/cogl-buffer-private.h b/cogl/cogl/cogl-buffer-private.h new file mode 100644 index 0000000..eab81fd --- /dev/null +++ b/cogl/cogl/cogl-buffer-private.h @@ -0,0 +1,180 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Damien Lespiau + * Robert Bragg + */ + +#ifndef __COGL_BUFFER_PRIVATE_H__ +#define __COGL_BUFFER_PRIVATE_H__ + +#include + +#include "cogl-object-private.h" +#include "cogl-buffer.h" +#include "cogl-context.h" +#include "cogl-gl-header.h" + +COGL_BEGIN_DECLS + +typedef struct _CoglBufferVtable CoglBufferVtable; + +struct _CoglBufferVtable +{ + void * (* map_range) (CoglBuffer *buffer, + size_t offset, + size_t size, + CoglBufferAccess access, + CoglBufferMapHint hints, + CoglError **error); + + void (* unmap) (CoglBuffer *buffer); + + CoglBool (* set_data) (CoglBuffer *buffer, + unsigned int offset, + const void *data, + unsigned int size, + CoglError **error); +}; + +typedef enum _CoglBufferFlags +{ + COGL_BUFFER_FLAG_NONE = 0, + COGL_BUFFER_FLAG_BUFFER_OBJECT = 1UL << 0, /* real openGL buffer object */ + COGL_BUFFER_FLAG_MAPPED = 1UL << 1, + COGL_BUFFER_FLAG_MAPPED_FALLBACK = 1UL << 2 +} CoglBufferFlags; + +typedef enum { + COGL_BUFFER_USAGE_HINT_TEXTURE, + COGL_BUFFER_USAGE_HINT_ATTRIBUTE_BUFFER, + COGL_BUFFER_USAGE_HINT_INDEX_BUFFER +} CoglBufferUsageHint; + +typedef enum { + COGL_BUFFER_BIND_TARGET_PIXEL_PACK, + COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK, + COGL_BUFFER_BIND_TARGET_ATTRIBUTE_BUFFER, + COGL_BUFFER_BIND_TARGET_INDEX_BUFFER, + + COGL_BUFFER_BIND_TARGET_COUNT +} CoglBufferBindTarget; + +struct _CoglBuffer +{ + CoglObject _parent; + + CoglContext *context; + + CoglBufferVtable vtable; + + CoglBufferBindTarget last_target; + + CoglBufferFlags flags; + + GLuint gl_handle; /* OpenGL handle */ + unsigned int size; /* size of the buffer, in bytes */ + CoglBufferUsageHint usage_hint; + CoglBufferUpdateHint update_hint; + + /* points to the mapped memory when the CoglBuffer is a VBO, PBO, + * ... or points to allocated memory in the fallback paths */ + uint8_t *data; + + int immutable_ref; + + unsigned int store_created:1; +}; + +/* This is used to register a type to the list of handle types that + will be considered a texture in cogl_is_texture() */ +void +_cogl_buffer_register_buffer_type (const CoglObjectClass *klass); + +#define COGL_BUFFER_DEFINE(TypeName, type_name) \ + COGL_OBJECT_DEFINE_WITH_CODE \ + (TypeName, type_name, \ + _cogl_buffer_register_buffer_type (&_cogl_##type_name##_class)) + +void +_cogl_buffer_initialize (CoglBuffer *buffer, + CoglContext *context, + size_t size, + CoglBufferBindTarget default_target, + CoglBufferUsageHint usage_hint, + CoglBufferUpdateHint update_hint); + +void +_cogl_buffer_fini (CoglBuffer *buffer); + +CoglBufferUsageHint +_cogl_buffer_get_usage_hint (CoglBuffer *buffer); + +GLenum +_cogl_buffer_access_to_gl_enum (CoglBufferAccess access); + +CoglBuffer * +_cogl_buffer_immutable_ref (CoglBuffer *buffer); + +void +_cogl_buffer_immutable_unref (CoglBuffer *buffer); + +CoglBool +_cogl_buffer_set_data (CoglBuffer *buffer, + size_t offset, + const void *data, + size_t size, + CoglError **error); + +void * +_cogl_buffer_map (CoglBuffer *buffer, + CoglBufferAccess access, + CoglBufferMapHint hints, + CoglError **error); + +/* This is a wrapper around cogl_buffer_map_range for internal use + when we want to map the buffer for write only to replace the entire + contents. If the map fails then it will fallback to writing to a + temporary buffer. When _cogl_buffer_unmap_for_fill_or_fallback is + called the temporary buffer will be copied into the array. Note + that these calls share a global array so they can not be nested. */ +void * +_cogl_buffer_map_range_for_fill_or_fallback (CoglBuffer *buffer, + size_t offset, + size_t size); +void * +_cogl_buffer_map_for_fill_or_fallback (CoglBuffer *buffer); + +void +_cogl_buffer_unmap_for_fill_or_fallback (CoglBuffer *buffer); + +COGL_END_DECLS + +#endif /* __COGL_BUFFER_PRIVATE_H__ */ diff --git a/cogl/cogl/cogl-buffer.c b/cogl/cogl/cogl-buffer.c new file mode 100644 index 0000000..18a6a4b --- /dev/null +++ b/cogl/cogl/cogl-buffer.c @@ -0,0 +1,411 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Damien Lespiau + * Robert Bragg + */ + +/* For an overview of the functionality implemented here, please see + * cogl-buffer.h, which contains the gtk-doc section overview for the + * Pixel Buffers API. + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include +#include +#include + +#include "cogl-util.h" +#include "cogl-context-private.h" +#include "cogl-object-private.h" +#include "cogl-pixel-buffer-private.h" + +/* XXX: + * The CoglObject macros don't support any form of inheritance, so for + * now we implement the CoglObject support for the CoglBuffer + * abstract class manually. + */ + +static GSList *_cogl_buffer_types; + +void +_cogl_buffer_register_buffer_type (const CoglObjectClass *klass) +{ + _cogl_buffer_types = g_slist_prepend (_cogl_buffer_types, (void *) klass); +} + +CoglBool +cogl_is_buffer (void *object) +{ + const CoglObject *obj = object; + GSList *l; + + if (object == NULL) + return FALSE; + + for (l = _cogl_buffer_types; l; l = l->next) + if (l->data == obj->klass) + return TRUE; + + return FALSE; +} + +/* + * Fallback path, buffer->data points to a malloc'ed buffer. + */ + +static void * +malloc_map_range (CoglBuffer *buffer, + size_t offset, + size_t size, + CoglBufferAccess access, + CoglBufferMapHint hints, + CoglError **error) +{ + buffer->flags |= COGL_BUFFER_FLAG_MAPPED; + return buffer->data + offset; +} + +static void +malloc_unmap (CoglBuffer *buffer) +{ + buffer->flags &= ~COGL_BUFFER_FLAG_MAPPED; +} + +static CoglBool +malloc_set_data (CoglBuffer *buffer, + unsigned int offset, + const void *data, + unsigned int size, + CoglError **error) +{ + memcpy (buffer->data + offset, data, size); + return TRUE; +} + +void +_cogl_buffer_initialize (CoglBuffer *buffer, + CoglContext *ctx, + size_t size, + CoglBufferBindTarget default_target, + CoglBufferUsageHint usage_hint, + CoglBufferUpdateHint update_hint) +{ + CoglBool use_malloc = FALSE; + + buffer->context = ctx; + buffer->flags = COGL_BUFFER_FLAG_NONE; + buffer->store_created = FALSE; + buffer->size = size; + buffer->last_target = default_target; + buffer->usage_hint = usage_hint; + buffer->update_hint = update_hint; + buffer->data = NULL; + buffer->immutable_ref = 0; + + if (default_target == COGL_BUFFER_BIND_TARGET_PIXEL_PACK || + default_target == COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK) + { + if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_PBOS)) + use_malloc = TRUE; + } + else if (default_target == COGL_BUFFER_BIND_TARGET_ATTRIBUTE_BUFFER || + default_target == COGL_BUFFER_BIND_TARGET_INDEX_BUFFER) + { + if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_VBOS)) + use_malloc = TRUE; + } + + if (use_malloc) + { + buffer->vtable.map_range = malloc_map_range; + buffer->vtable.unmap = malloc_unmap; + buffer->vtable.set_data = malloc_set_data; + + buffer->data = g_malloc (size); + } + else + { + buffer->vtable.map_range = ctx->driver_vtable->buffer_map_range; + buffer->vtable.unmap = ctx->driver_vtable->buffer_unmap; + buffer->vtable.set_data = ctx->driver_vtable->buffer_set_data; + + ctx->driver_vtable->buffer_create (buffer); + + buffer->flags |= COGL_BUFFER_FLAG_BUFFER_OBJECT; + } +} + +void +_cogl_buffer_fini (CoglBuffer *buffer) +{ + _COGL_RETURN_IF_FAIL (!(buffer->flags & COGL_BUFFER_FLAG_MAPPED)); + _COGL_RETURN_IF_FAIL (buffer->immutable_ref == 0); + + if (buffer->flags & COGL_BUFFER_FLAG_BUFFER_OBJECT) + buffer->context->driver_vtable->buffer_destroy (buffer); + else + g_free (buffer->data); +} + +unsigned int +cogl_buffer_get_size (CoglBuffer *buffer) +{ + if (!cogl_is_buffer (buffer)) + return 0; + + return COGL_BUFFER (buffer)->size; +} + +void +cogl_buffer_set_update_hint (CoglBuffer *buffer, + CoglBufferUpdateHint hint) +{ + if (!cogl_is_buffer (buffer)) + return; + + if (G_UNLIKELY (hint > COGL_BUFFER_UPDATE_HINT_STREAM)) + hint = COGL_BUFFER_UPDATE_HINT_STATIC; + + buffer->update_hint = hint; +} + +CoglBufferUpdateHint +cogl_buffer_get_update_hint (CoglBuffer *buffer) +{ + if (!cogl_is_buffer (buffer)) + return FALSE; + + return buffer->update_hint; +} + +static void +warn_about_midscene_changes (void) +{ + static CoglBool seen = FALSE; + if (!seen) + { + g_warning ("Mid-scene modification of buffers has " + "undefined results\n"); + seen = TRUE; + } +} + +void * +_cogl_buffer_map (CoglBuffer *buffer, + CoglBufferAccess access, + CoglBufferMapHint hints, + CoglError **error) +{ + _COGL_RETURN_VAL_IF_FAIL (cogl_is_buffer (buffer), NULL); + + return cogl_buffer_map_range (buffer, 0, buffer->size, access, hints, error); +} + +void * +cogl_buffer_map (CoglBuffer *buffer, + CoglBufferAccess access, + CoglBufferMapHint hints) +{ + CoglError *ignore_error = NULL; + void *ptr = + cogl_buffer_map_range (buffer, 0, buffer->size, access, hints, + &ignore_error); + if (!ptr) + cogl_error_free (ignore_error); + return ptr; +} + +void * +cogl_buffer_map_range (CoglBuffer *buffer, + size_t offset, + size_t size, + CoglBufferAccess access, + CoglBufferMapHint hints, + CoglError **error) +{ + _COGL_RETURN_VAL_IF_FAIL (cogl_is_buffer (buffer), NULL); + _COGL_RETURN_VAL_IF_FAIL (!(buffer->flags & COGL_BUFFER_FLAG_MAPPED), NULL); + + if (G_UNLIKELY (buffer->immutable_ref)) + warn_about_midscene_changes (); + + buffer->data = buffer->vtable.map_range (buffer, + offset, + size, + access, + hints, + error); + + return buffer->data; +} + +void +cogl_buffer_unmap (CoglBuffer *buffer) +{ + if (!cogl_is_buffer (buffer)) + return; + + if (!(buffer->flags & COGL_BUFFER_FLAG_MAPPED)) + return; + + buffer->vtable.unmap (buffer); +} + +void * +_cogl_buffer_map_for_fill_or_fallback (CoglBuffer *buffer) +{ + return _cogl_buffer_map_range_for_fill_or_fallback (buffer, 0, buffer->size); +} + +void * +_cogl_buffer_map_range_for_fill_or_fallback (CoglBuffer *buffer, + size_t offset, + size_t size) +{ + CoglContext *ctx = buffer->context; + void *ret; + CoglError *ignore_error = NULL; + + _COGL_RETURN_VAL_IF_FAIL (!ctx->buffer_map_fallback_in_use, NULL); + + ctx->buffer_map_fallback_in_use = TRUE; + + ret = cogl_buffer_map_range (buffer, + offset, + size, + COGL_BUFFER_ACCESS_WRITE, + COGL_BUFFER_MAP_HINT_DISCARD, + &ignore_error); + + if (ret) + return ret; + + cogl_error_free (ignore_error); + + /* If the map fails then we'll use a temporary buffer to fill + the data and then upload it using cogl_buffer_set_data when + the buffer is unmapped. The temporary buffer is shared to + avoid reallocating it every time */ + g_byte_array_set_size (ctx->buffer_map_fallback_array, size); + ctx->buffer_map_fallback_offset = offset; + + buffer->flags |= COGL_BUFFER_FLAG_MAPPED_FALLBACK; + + return ctx->buffer_map_fallback_array->data; +} + +void +_cogl_buffer_unmap_for_fill_or_fallback (CoglBuffer *buffer) +{ + CoglContext *ctx = buffer->context; + + _COGL_RETURN_IF_FAIL (ctx->buffer_map_fallback_in_use); + + ctx->buffer_map_fallback_in_use = FALSE; + + if ((buffer->flags & COGL_BUFFER_FLAG_MAPPED_FALLBACK)) + { + /* Note: don't try to catch OOM errors here since the use cases + * we currently have for this api (the journal and path stroke + * tesselator) don't have anything particularly sensible they + * can do in response to a failure anyway so it seems better to + * simply abort instead. + * + * If we find this is a problem for real world applications + * then in the path tesselation case we could potentially add an + * explicit cogl_path_tesselate_stroke() api that can throw an + * error for the app to cache. For the journal we could + * potentially flush the journal in smaller batches so we use + * smaller buffers, though that would probably not help for + * deferred renderers. + */ + _cogl_buffer_set_data (buffer, + ctx->buffer_map_fallback_offset, + ctx->buffer_map_fallback_array->data, + ctx->buffer_map_fallback_array->len, + NULL); + buffer->flags &= ~COGL_BUFFER_FLAG_MAPPED_FALLBACK; + } + else + cogl_buffer_unmap (buffer); +} + +CoglBool +_cogl_buffer_set_data (CoglBuffer *buffer, + size_t offset, + const void *data, + size_t size, + CoglError **error) +{ + _COGL_RETURN_VAL_IF_FAIL (cogl_is_buffer (buffer), FALSE); + _COGL_RETURN_VAL_IF_FAIL ((offset + size) <= buffer->size, FALSE); + + if (G_UNLIKELY (buffer->immutable_ref)) + warn_about_midscene_changes (); + + return buffer->vtable.set_data (buffer, offset, data, size, error); +} + +CoglBool +cogl_buffer_set_data (CoglBuffer *buffer, + size_t offset, + const void *data, + size_t size) +{ + CoglError *ignore_error = NULL; + CoglBool status = + _cogl_buffer_set_data (buffer, offset, data, size, &ignore_error); + if (!status) + cogl_error_free (ignore_error); + return status; +} + +CoglBuffer * +_cogl_buffer_immutable_ref (CoglBuffer *buffer) +{ + _COGL_RETURN_VAL_IF_FAIL (cogl_is_buffer (buffer), NULL); + + buffer->immutable_ref++; + return buffer; +} + +void +_cogl_buffer_immutable_unref (CoglBuffer *buffer) +{ + _COGL_RETURN_IF_FAIL (cogl_is_buffer (buffer)); + _COGL_RETURN_IF_FAIL (buffer->immutable_ref > 0); + + buffer->immutable_ref--; +} + diff --git a/cogl/cogl/cogl-buffer.h b/cogl/cogl/cogl-buffer.h new file mode 100644 index 0000000..68fec49 --- /dev/null +++ b/cogl/cogl/cogl-buffer.h @@ -0,0 +1,325 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C)2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Damien Lespiau + * Robert Bragg + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_BUFFER_H__ +#define __COGL_BUFFER_H__ + +#include +#include + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-buffer + * @short_description: Common buffer functions, including data upload APIs + * @stability: unstable + * + * The CoglBuffer API provides a common interface to manipulate + * buffers that have been allocated either via cogl_pixel_buffer_new() + * or cogl_attribute_buffer_new(). The API allows you to upload data + * to these buffers and define usage hints that help Cogl manage your + * buffer optimally. + * + * Data can either be uploaded by supplying a pointer and size so Cogl + * can copy your data, or you can mmap() a CoglBuffer and then you can + * copy data to the buffer directly. + * + * One of the most common uses for CoglBuffers is to upload texture + * data asynchronously since the ability to mmap the buffers into + * the CPU makes it possible for another thread to handle the IO + * of loading an image file and unpacking it into the mapped buffer + * without blocking other Cogl operations. + */ + +#if defined(__COGL_H_INSIDE__) && !defined(COGL_ENABLE_MUTTER_API) && \ + !defined(COGL_GIR_SCANNING) +/* For the public C api we typedef interface types as void to avoid needing + * lots of casting in code and instead we will rely on runtime type checking + * for these objects. */ +typedef void CoglBuffer; +#else +typedef struct _CoglBuffer CoglBuffer; +#define COGL_BUFFER(buffer) ((CoglBuffer *)(buffer)) +#endif + +#define COGL_BUFFER_ERROR (_cogl_buffer_error_domain ()) + +/** + * CoglBufferError: + * @COGL_BUFFER_ERROR_MAP: A buffer could not be mapped either + * because the feature isn't supported or because a system + * limitation was hit. + * + * Error enumeration for #CoglBuffer + * + * Stability: unstable + */ +typedef enum { /*< prefix=COGL_BUFFER_ERROR >*/ + COGL_BUFFER_ERROR_MAP +} CoglBufferError; + +uint32_t +_cogl_buffer_error_domain (void); + +/** + * cogl_is_buffer: + * @object: a buffer object + * + * Checks whether @buffer is a buffer object. + * + * Return value: %TRUE if the handle is a CoglBuffer, and %FALSE otherwise + * + * Since: 1.2 + * Stability: unstable + */ +CoglBool +cogl_is_buffer (void *object); + +/** + * cogl_buffer_get_size: + * @buffer: a buffer object + * + * Retrieves the size of buffer + * + * Return value: the size of the buffer in bytes + * + * Since: 1.2 + * Stability: unstable + */ +unsigned int +cogl_buffer_get_size (CoglBuffer *buffer); + +/** + * CoglBufferUpdateHint: + * @COGL_BUFFER_UPDATE_HINT_STATIC: the buffer will not change over time + * @COGL_BUFFER_UPDATE_HINT_DYNAMIC: the buffer will change from time to time + * @COGL_BUFFER_UPDATE_HINT_STREAM: the buffer will be used once or a couple of + * times + * + * The update hint on a buffer allows the user to give some detail on how often + * the buffer data is going to be updated. + * + * Since: 1.2 + * Stability: unstable + */ +typedef enum { /*< prefix=COGL_BUFFER_UPDATE_HINT >*/ + COGL_BUFFER_UPDATE_HINT_STATIC, + COGL_BUFFER_UPDATE_HINT_DYNAMIC, + COGL_BUFFER_UPDATE_HINT_STREAM +} CoglBufferUpdateHint; + +/** + * cogl_buffer_set_update_hint: + * @buffer: a buffer object + * @hint: the new hint + * + * Sets the update hint on a buffer. See #CoglBufferUpdateHint for a description + * of the available hints. + * + * Since: 1.2 + * Stability: unstable + */ +void +cogl_buffer_set_update_hint (CoglBuffer *buffer, + CoglBufferUpdateHint hint); + +/** + * cogl_buffer_get_update_hint: + * @buffer: a buffer object + * + * Retrieves the update hints set using cogl_buffer_set_update_hint() + * + * Return value: the #CoglBufferUpdateHint currently used by the buffer + * + * Since: 1.2 + * Stability: unstable + */ +CoglBufferUpdateHint +cogl_buffer_get_update_hint (CoglBuffer *buffer); + +/** + * CoglBufferAccess: + * @COGL_BUFFER_ACCESS_READ: the buffer will be read + * @COGL_BUFFER_ACCESS_WRITE: the buffer will written to + * @COGL_BUFFER_ACCESS_READ_WRITE: the buffer will be used for both reading and + * writing + * + * The access hints for cogl_buffer_set_update_hint() + * + * Since: 1.2 + * Stability: unstable + */ +typedef enum { /*< prefix=COGL_BUFFER_ACCESS >*/ + COGL_BUFFER_ACCESS_READ = 1 << 0, + COGL_BUFFER_ACCESS_WRITE = 1 << 1, + COGL_BUFFER_ACCESS_READ_WRITE = COGL_BUFFER_ACCESS_READ | COGL_BUFFER_ACCESS_WRITE +} CoglBufferAccess; + + +/** + * CoglBufferMapHint: + * @COGL_BUFFER_MAP_HINT_DISCARD: Tells Cogl that you plan to replace + * all the buffer's contents. When this flag is used to map a + * buffer, the entire contents of the buffer become undefined, even + * if only a subregion of the buffer is mapped. + * @COGL_BUFFER_MAP_HINT_DISCARD_RANGE: Tells Cogl that you plan to + * replace all the contents of the mapped region. The contents of + * the region specified are undefined after this flag is used to + * map a buffer. + * + * Hints to Cogl about how you are planning to modify the data once it + * is mapped. + * + * Since: 1.4 + * Stability: unstable + */ +typedef enum { /*< prefix=COGL_BUFFER_MAP_HINT >*/ + COGL_BUFFER_MAP_HINT_DISCARD = 1 << 0, + COGL_BUFFER_MAP_HINT_DISCARD_RANGE = 1 << 1 +} CoglBufferMapHint; + +/** + * cogl_buffer_map: + * @buffer: a buffer object + * @access: how the mapped buffer will be used by the application + * @hints: A mask of #CoglBufferMapHints that tell Cogl how + * the data will be modified once mapped. + * + * Maps the buffer into the application address space for direct + * access. This is equivalent to calling cogl_buffer_map_range() with + * zero as the offset and the size of the entire buffer as the size. + * + * It is strongly recommended that you pass + * %COGL_BUFFER_MAP_HINT_DISCARD as a hint if you are going to replace + * all the buffer's data. This way if the buffer is currently being + * used by the GPU then the driver won't have to stall the CPU and + * wait for the hardware to finish because it can instead allocate a + * new buffer to map. + * + * The behaviour is undefined if you access the buffer in a way + * conflicting with the @access mask you pass. It is also an error to + * release your last reference while the buffer is mapped. + * + * Return value: (transfer none): A pointer to the mapped memory or + * %NULL is the call fails + * + * Since: 1.2 + * Stability: unstable + */ +void * +cogl_buffer_map (CoglBuffer *buffer, + CoglBufferAccess access, + CoglBufferMapHint hints); + +/** + * cogl_buffer_map_range: + * @buffer: a buffer object + * @offset: Offset within the buffer to start the mapping + * @size: The size of data to map + * @access: how the mapped buffer will be used by the application + * @hints: A mask of #CoglBufferMapHints that tell Cogl how + * the data will be modified once mapped. + * @error: A #CoglError for catching exceptional errors + * + * Maps a sub-region of the buffer into the application's address space + * for direct access. + * + * It is strongly recommended that you pass + * %COGL_BUFFER_MAP_HINT_DISCARD as a hint if you are going to replace + * all the buffer's data. This way if the buffer is currently being + * used by the GPU then the driver won't have to stall the CPU and + * wait for the hardware to finish because it can instead allocate a + * new buffer to map. You can pass + * %COGL_BUFFER_MAP_HINT_DISCARD_RANGE instead if you want the + * regions outside of the mapping to be retained. + * + * The behaviour is undefined if you access the buffer in a way + * conflicting with the @access mask you pass. It is also an error to + * release your last reference while the buffer is mapped. + * + * Return value: (transfer none): A pointer to the mapped memory or + * %NULL is the call fails + * + * Since: 2.0 + * Stability: unstable + */ +void * +cogl_buffer_map_range (CoglBuffer *buffer, + size_t offset, + size_t size, + CoglBufferAccess access, + CoglBufferMapHint hints, + CoglError **error); + +/** + * cogl_buffer_unmap: + * @buffer: a buffer object + * + * Unmaps a buffer previously mapped by cogl_buffer_map(). + * + * Since: 1.2 + * Stability: unstable + */ +void +cogl_buffer_unmap (CoglBuffer *buffer); + +/** + * cogl_buffer_set_data: + * @buffer: a buffer object + * @offset: destination offset (in bytes) in the buffer + * @data: a pointer to the data to be copied into the buffer + * @size: number of bytes to copy + * + * Updates part of the buffer with new data from @data. Where to put this new + * data is controlled by @offset and @offset + @data should be less than the + * buffer size. + * + * Return value: %TRUE is the operation succeeded, %FALSE otherwise + * + * Since: 1.2 + * Stability: unstable + */ +CoglBool +cogl_buffer_set_data (CoglBuffer *buffer, + size_t offset, + const void *data, + size_t size); + +COGL_END_DECLS + +#endif /* __COGL_BUFFER_H__ */ diff --git a/cogl/cogl/cogl-clip-stack.c b/cogl/cogl/cogl-clip-stack.c new file mode 100644 index 0000000..128b1bc --- /dev/null +++ b/cogl/cogl/cogl-clip-stack.c @@ -0,0 +1,412 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include +#include + +#include + +#include "cogl-clip-stack.h" +#include "cogl-primitives.h" +#include "cogl-context-private.h" +#include "cogl-framebuffer-private.h" +#include "cogl-journal-private.h" +#include "cogl-util.h" +#include "cogl-matrix-private.h" +#include "cogl-primitives-private.h" +#include "cogl-private.h" +#include "cogl-pipeline-opengl-private.h" +#include "cogl-attribute-private.h" +#include "cogl-primitive-private.h" +#include "cogl1-context.h" +#include "cogl-offscreen.h" +#include "cogl-matrix-stack.h" + + + +static void * +_cogl_clip_stack_push_entry (CoglClipStack *clip_stack, + size_t size, + CoglClipStackType type) +{ + CoglClipStack *entry = g_slice_alloc (size); + + /* The new entry starts with a ref count of 1 because the stack + holds a reference to it as it is the top entry */ + entry->ref_count = 1; + entry->type = type; + entry->parent = clip_stack; + + /* We don't need to take a reference to the parent from the entry + because the we are stealing the ref in the new stack top */ + + return entry; +} + +static void +get_transformed_corners (float x_1, + float y_1, + float x_2, + float y_2, + CoglMatrix *modelview, + CoglMatrix *projection, + const float *viewport, + float *transformed_corners) +{ + int i; + + transformed_corners[0] = x_1; + transformed_corners[1] = y_1; + transformed_corners[2] = x_2; + transformed_corners[3] = y_1; + transformed_corners[4] = x_2; + transformed_corners[5] = y_2; + transformed_corners[6] = x_1; + transformed_corners[7] = y_2; + + + /* Project the coordinates to window space coordinates */ + for (i = 0; i < 4; i++) + { + float *v = transformed_corners + i * 2; + _cogl_transform_point (modelview, projection, viewport, v, v + 1); + } +} + +/* Sets the window-space bounds of the entry based on the projected + coordinates of the given rectangle */ +static void +_cogl_clip_stack_entry_set_bounds (CoglClipStack *entry, + float *transformed_corners) +{ + float min_x = G_MAXFLOAT, min_y = G_MAXFLOAT; + float max_x = -G_MAXFLOAT, max_y = -G_MAXFLOAT; + int i; + + for (i = 0; i < 4; i++) + { + float *v = transformed_corners + i * 2; + + if (v[0] > max_x) + max_x = v[0]; + if (v[0] < min_x) + min_x = v[0]; + if (v[1] > max_y) + max_y = v[1]; + if (v[1] < min_y) + min_y = v[1]; + } + + entry->bounds_x0 = floorf (min_x); + entry->bounds_x1 = ceilf (max_x); + entry->bounds_y0 = floorf (min_y); + entry->bounds_y1 = ceilf (max_y); +} + +CoglClipStack * +_cogl_clip_stack_push_window_rectangle (CoglClipStack *stack, + int x_offset, + int y_offset, + int width, + int height) +{ + CoglClipStack *entry; + + entry = _cogl_clip_stack_push_entry (stack, + sizeof (CoglClipStackWindowRect), + COGL_CLIP_STACK_WINDOW_RECT); + + entry->bounds_x0 = x_offset; + entry->bounds_x1 = x_offset + width; + entry->bounds_y0 = y_offset; + entry->bounds_y1 = y_offset + height; + + return entry; +} + +CoglClipStack * +_cogl_clip_stack_push_rectangle (CoglClipStack *stack, + float x_1, + float y_1, + float x_2, + float y_2, + CoglMatrixEntry *modelview_entry, + CoglMatrixEntry *projection_entry, + const float *viewport) +{ + CoglClipStackRect *entry; + CoglMatrix modelview; + CoglMatrix projection; + CoglMatrix modelview_projection; + + /* Corners of the given rectangle in an clockwise order: + * (0, 1) (2, 3) + * + * + * + * (6, 7) (4, 5) + */ + float rect[] = { + x_1, y_1, + x_2, y_1, + x_2, y_2, + x_1, y_2 + }; + + /* Make a new entry */ + entry = _cogl_clip_stack_push_entry (stack, + sizeof (CoglClipStackRect), + COGL_CLIP_STACK_RECT); + + entry->x0 = x_1; + entry->y0 = y_1; + entry->x1 = x_2; + entry->y1 = y_2; + + entry->matrix_entry = cogl_matrix_entry_ref (modelview_entry); + + cogl_matrix_entry_get (modelview_entry, &modelview); + cogl_matrix_entry_get (projection_entry, &projection); + + cogl_matrix_multiply (&modelview_projection, + &projection, + &modelview); + + /* Technically we could avoid the viewport transform at this point + * if we want to make this a bit faster. */ + _cogl_transform_point (&modelview, &projection, viewport, &rect[0], &rect[1]); + _cogl_transform_point (&modelview, &projection, viewport, &rect[2], &rect[3]); + _cogl_transform_point (&modelview, &projection, viewport, &rect[4], &rect[5]); + _cogl_transform_point (&modelview, &projection, viewport, &rect[6], &rect[7]); + + /* If the fully transformed rectangle isn't still axis aligned we + * can't handle it using a scissor. + * + * We don't use an epsilon here since we only really aim to catch + * simple cases where the transform doesn't leave the rectangle screen + * aligned and don't mind some false positives. + */ + if (rect[0] != rect[6] || + rect[1] != rect[3] || + rect[2] != rect[4] || + rect[7] != rect[5]) + { + entry->can_be_scissor = FALSE; + + _cogl_clip_stack_entry_set_bounds ((CoglClipStack *) entry, + rect); + } + else + { + CoglClipStack *base_entry = (CoglClipStack *) entry; + x_1 = rect[0]; + y_1 = rect[1]; + x_2 = rect[4]; + y_2 = rect[5]; + + /* Consider that the modelview matrix may flip the rectangle + * along the x or y axis... */ +#define SWAP(A,B) do { float tmp = B; B = A; A = tmp; } while (0) + if (x_1 > x_2) + SWAP (x_1, x_2); + if (y_1 > y_2) + SWAP (y_1, y_2); +#undef SWAP + + base_entry->bounds_x0 = COGL_UTIL_NEARBYINT (x_1); + base_entry->bounds_y0 = COGL_UTIL_NEARBYINT (y_1); + base_entry->bounds_x1 = COGL_UTIL_NEARBYINT (x_2); + base_entry->bounds_y1 = COGL_UTIL_NEARBYINT (y_2); + entry->can_be_scissor = TRUE; + } + + return (CoglClipStack *) entry; +} + +CoglClipStack * +_cogl_clip_stack_push_primitive (CoglClipStack *stack, + CoglPrimitive *primitive, + float bounds_x1, + float bounds_y1, + float bounds_x2, + float bounds_y2, + CoglMatrixEntry *modelview_entry, + CoglMatrixEntry *projection_entry, + const float *viewport) +{ + CoglClipStackPrimitive *entry; + CoglMatrix modelview; + CoglMatrix projection; + float transformed_corners[8]; + + entry = _cogl_clip_stack_push_entry (stack, + sizeof (CoglClipStackPrimitive), + COGL_CLIP_STACK_PRIMITIVE); + + entry->primitive = cogl_object_ref (primitive); + + entry->matrix_entry = cogl_matrix_entry_ref (modelview_entry); + + entry->bounds_x1 = bounds_x1; + entry->bounds_y1 = bounds_y1; + entry->bounds_x2 = bounds_x2; + entry->bounds_y2 = bounds_y2; + + cogl_matrix_entry_get (modelview_entry, &modelview); + cogl_matrix_entry_get (projection_entry, &projection); + + get_transformed_corners (bounds_x1, bounds_y1, bounds_x2, bounds_y2, + &modelview, + &projection, + viewport, + transformed_corners); + + /* NB: this is referring to the bounds in window coordinates as opposed + * to the bounds above in primitive local coordinates. */ + _cogl_clip_stack_entry_set_bounds ((CoglClipStack *) entry, + transformed_corners); + + return (CoglClipStack *) entry; +} + +CoglClipStack * +_cogl_clip_stack_ref (CoglClipStack *entry) +{ + /* A NULL pointer is considered a valid stack so we should accept + that as an argument */ + if (entry) + entry->ref_count++; + + return entry; +} + +void +_cogl_clip_stack_unref (CoglClipStack *entry) +{ + /* Unref all of the entries until we hit the root of the list or the + entry still has a remaining reference */ + while (entry && --entry->ref_count <= 0) + { + CoglClipStack *parent = entry->parent; + + switch (entry->type) + { + case COGL_CLIP_STACK_RECT: + { + CoglClipStackRect *rect = (CoglClipStackRect *) entry; + cogl_matrix_entry_unref (rect->matrix_entry); + g_slice_free1 (sizeof (CoglClipStackRect), entry); + break; + } + case COGL_CLIP_STACK_WINDOW_RECT: + g_slice_free1 (sizeof (CoglClipStackWindowRect), entry); + break; + case COGL_CLIP_STACK_PRIMITIVE: + { + CoglClipStackPrimitive *primitive_entry = + (CoglClipStackPrimitive *) entry; + cogl_matrix_entry_unref (primitive_entry->matrix_entry); + cogl_object_unref (primitive_entry->primitive); + g_slice_free1 (sizeof (CoglClipStackPrimitive), entry); + break; + } + default: + g_assert_not_reached (); + } + + entry = parent; + } +} + +CoglClipStack * +_cogl_clip_stack_pop (CoglClipStack *stack) +{ + CoglClipStack *new_top; + + _COGL_RETURN_VAL_IF_FAIL (stack != NULL, NULL); + + /* To pop we are moving the top of the stack to the old top's parent + node. The stack always needs to have a reference to the top entry + so we must take a reference to the new top. The stack would have + previously had a reference to the old top so we need to decrease + the ref count on that. We need to ref the new head first in case + this stack was the only thing referencing the old top. In that + case the call to _cogl_clip_stack_entry_unref will unref the + parent. */ + new_top = stack->parent; + + _cogl_clip_stack_ref (new_top); + + _cogl_clip_stack_unref (stack); + + return new_top; +} + +void +_cogl_clip_stack_get_bounds (CoglClipStack *stack, + int *scissor_x0, + int *scissor_y0, + int *scissor_x1, + int *scissor_y1) +{ + CoglClipStack *entry; + + *scissor_x0 = 0; + *scissor_y0 = 0; + *scissor_x1 = G_MAXINT; + *scissor_y1 = G_MAXINT; + + for (entry = stack; entry; entry = entry->parent) + { + /* Get the intersection of the current scissor and the bounding + box of this clip */ + _cogl_util_scissor_intersect (entry->bounds_x0, + entry->bounds_y0, + entry->bounds_x1, + entry->bounds_y1, + scissor_x0, + scissor_y0, + scissor_x1, + scissor_y1); + } +} + +void +_cogl_clip_stack_flush (CoglClipStack *stack, + CoglFramebuffer *framebuffer) +{ + CoglContext *ctx = framebuffer->context; + + ctx->driver_vtable->clip_stack_flush (stack, framebuffer); +} diff --git a/cogl/cogl/cogl-clip-stack.h b/cogl/cogl/cogl-clip-stack.h new file mode 100644 index 0000000..56bc3f8 --- /dev/null +++ b/cogl/cogl/cogl-clip-stack.h @@ -0,0 +1,213 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_CLIP_STACK_H +#define __COGL_CLIP_STACK_H + +#include "cogl-matrix.h" +#include "cogl-primitive.h" +#include "cogl-framebuffer.h" +#include "cogl-matrix-stack.h" + +/* The clip stack works like a GSList where only a pointer to the top + of the stack is stored. The empty clip stack is represented simply + by the NULL pointer. When an entry is added to or removed from the + stack the new top of the stack is returned. When an entry is pushed + a new clip stack entry is created which effectively takes ownership + of the reference on the old entry. Therefore unrefing the top entry + effectively loses ownership of all entries in the stack */ + +typedef struct _CoglClipStack CoglClipStack; +typedef struct _CoglClipStackRect CoglClipStackRect; +typedef struct _CoglClipStackWindowRect CoglClipStackWindowRect; +typedef struct _CoglClipStackPrimitive CoglClipStackPrimitive; + +typedef enum + { + COGL_CLIP_STACK_RECT, + COGL_CLIP_STACK_WINDOW_RECT, + COGL_CLIP_STACK_PRIMITIVE + } CoglClipStackType; + +/* A clip stack consists a list of entries. Each entry has a reference + * count and a link to its parent node. The child takes a reference on + * the parent and the CoglClipStack holds a reference to the top of + * the stack. There are no links back from the parent to the + * children. This allows stacks that have common ancestry to share the + * entries. + * + * For example, the following sequence of operations would generate + * the tree below: + * + * CoglClipStack *stack_a = NULL; + * stack_a = _cogl_clip_stack_push_rectangle (stack_a, ...); + * stack_a = _cogl_clip_stack_push_rectangle (stack_a, ...); + * stack_a = _cogl_clip_stack_push_primitive (stack_a, ...); + * CoglClipStack *stack_b = NULL; + * stack_b = cogl_clip_stack_push_window_rectangle (stack_b, ...); + * + * stack_a + * \ holds a ref to + * +-----------+ + * | prim node | + * |ref count 1| + * +-----------+ + * \ + * +-----------+ +-----------+ + * both tops hold | rect node | | rect node | + * a ref to the |ref count 2|--|ref count 1| + * same rect node +-----------+ +-----------+ + * / + * +-----------+ + * | win. rect | + * |ref count 1| + * +-----------+ + * / holds a ref to + * stack_b + * + */ + +struct _CoglClipStack +{ + /* This will be null if there is no parent. If it is not null then + this node must be holding a reference to the parent */ + CoglClipStack *parent; + + CoglClipStackType type; + + /* All clip entries have a window-space bounding box which we can + use to calculate a scissor. The scissor limits the clip so that + we don't need to do a full stencil clear if the stencil buffer is + needed. This is stored in Cogl's coordinate space (ie, 0,0 is the + top left) */ + int bounds_x0; + int bounds_y0; + int bounds_x1; + int bounds_y1; + + unsigned int ref_count; +}; + +struct _CoglClipStackRect +{ + CoglClipStack _parent_data; + + /* The rectangle for this clip */ + float x0; + float y0; + float x1; + float y1; + + /* The matrix that was current when the clip was set */ + CoglMatrixEntry *matrix_entry; + + /* If this is true then the clip for this rectangle is entirely + described by the scissor bounds. This implies that the rectangle + is screen aligned and we don't need to use the stencil buffer to + set the clip. We keep the entry as a rect entry rather than a + window rect entry so that it will be easier to detect if the + modelview matrix is that same as when a rectangle is added to the + journal. In that case we can use the original clip coordinates + and modify the rectangle instead. */ + CoglBool can_be_scissor; +}; + +struct _CoglClipStackWindowRect +{ + CoglClipStack _parent_data; + + /* The window rect clip doesn't need any specific data because it + just adds to the scissor clip */ +}; + +struct _CoglClipStackPrimitive +{ + CoglClipStack _parent_data; + + /* The matrix that was current when the clip was set */ + CoglMatrixEntry *matrix_entry; + + CoglPrimitive *primitive; + + float bounds_x1; + float bounds_y1; + float bounds_x2; + float bounds_y2; +}; + +CoglClipStack * +_cogl_clip_stack_push_window_rectangle (CoglClipStack *stack, + int x_offset, + int y_offset, + int width, + int height); + +CoglClipStack * +_cogl_clip_stack_push_rectangle (CoglClipStack *stack, + float x_1, + float y_1, + float x_2, + float y_2, + CoglMatrixEntry *modelview_entry, + CoglMatrixEntry *projection_entry, + const float *viewport); + +CoglClipStack * +_cogl_clip_stack_push_primitive (CoglClipStack *stack, + CoglPrimitive *primitive, + float bounds_x1, + float bounds_y1, + float bounds_x2, + float bounds_y2, + CoglMatrixEntry *modelview_entry, + CoglMatrixEntry *projection_entry, + const float *viewport); + +CoglClipStack * +_cogl_clip_stack_pop (CoglClipStack *stack); + +void +_cogl_clip_stack_get_bounds (CoglClipStack *stack, + int *scissor_x0, + int *scissor_y0, + int *scissor_x1, + int *scissor_y1); + +void +_cogl_clip_stack_flush (CoglClipStack *stack, + CoglFramebuffer *framebuffer); + +CoglClipStack * +_cogl_clip_stack_ref (CoglClipStack *stack); + +void +_cogl_clip_stack_unref (CoglClipStack *stack); + +#endif /* __COGL_CLIP_STACK_H */ diff --git a/cogl/cogl/cogl-closure-list-private.h b/cogl/cogl/cogl-closure-list-private.h new file mode 100644 index 0000000..5446cb2 --- /dev/null +++ b/cogl/cogl/cogl-closure-list-private.h @@ -0,0 +1,118 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012,2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef _COGL_CLOSURE_LIST_PRIVATE_H_ +#define _COGL_CLOSURE_LIST_PRIVATE_H_ + +#include "cogl-object.h" +#include "cogl-list.h" + +/* + * This implements a list of callbacks that can be used a bit like + * signals in GObject, but that don't have any marshalling overhead. + * + * The idea is that any Cogl code that wants to provide a callback + * point will provide api to add a callback for that particular point. + * The function can take a function pointer with the correct + * signature. Internally the Cogl code can use _cogl_closure_list_add, + * _cogl_closure_disconnect and _cogl_closure_list_disconnect_all + * + * In the future we could consider exposing the CoglClosure type which + * would allow applications to use _cogl_closure_disconnect() directly + * so we don't need to expose new disconnect apis for each callback + * point. + */ + +typedef struct _CoglClosure +{ + CoglList link; + + void *function; + void *user_data; + CoglUserDataDestroyCallback destroy_cb; +} CoglClosure; + +/* + * _cogl_closure_disconnect: + * @closure: A closure connected to a Cogl closure list + * + * Removes the given closure from the callback list it is connected to + * and destroys it. If the closure was created with a destroy function + * then it will be invoked. */ +void +_cogl_closure_disconnect (CoglClosure *closure); + +void +_cogl_closure_list_disconnect_all (CoglList *list); + +CoglClosure * +_cogl_closure_list_add (CoglList *list, + void *function, + void *user_data, + CoglUserDataDestroyCallback destroy_cb); + +/* + * _cogl_closure_list_invoke: + * @list: A pointer to a CoglList containing CoglClosures + * @cb_type: The name of a typedef for the closure callback function signature + * @...: The the arguments to pass to the callback + * + * A convenience macro to invoke a closure list with a variable number + * of arguments that will be passed to the closure callback functions. + * + * Note that the arguments will be evaluated multiple times so it is + * not safe to pass expressions that have side-effects. + * + * Note also that this function ignores the return value from the + * callbacks. If you want to handle the return value you should + * manually iterate the list and invoke the callbacks yourself. + */ +#define _cogl_closure_list_invoke(list, cb_type, ...) \ + G_STMT_START { \ + CoglClosure *_c, *_tmp; \ + \ + _cogl_list_for_each_safe (_c, _tmp, (list), link) \ + { \ + cb_type _cb = _c->function; \ + _cb (__VA_ARGS__, _c->user_data); \ + } \ + } G_STMT_END + +#define _cogl_closure_list_invoke_no_args(list) \ + G_STMT_START { \ + CoglClosure *_c, *_tmp; \ + \ + _cogl_list_for_each_safe (_c, _tmp, (list), link) \ + { \ + void (*_cb)(void *) = _c->function; \ + _cb (_c->user_data); \ + } \ + } G_STMT_END + +#endif /* _COGL_CLOSURE_LIST_PRIVATE_H_ */ diff --git a/cogl/cogl/cogl-closure-list.c b/cogl/cogl/cogl-closure-list.c new file mode 100644 index 0000000..a2e82e7 --- /dev/null +++ b/cogl/cogl/cogl-closure-list.c @@ -0,0 +1,71 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012,2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#include "cogl-config.h" + +#include + +#include "cogl-closure-list-private.h" + +void +_cogl_closure_disconnect (CoglClosure *closure) +{ + _cogl_list_remove (&closure->link); + + if (closure->destroy_cb) + closure->destroy_cb (closure->user_data); + + g_slice_free (CoglClosure, closure); +} + +void +_cogl_closure_list_disconnect_all (CoglList *list) +{ + CoglClosure *closure, *next; + + _cogl_list_for_each_safe (closure, next, list, link) + _cogl_closure_disconnect (closure); +} + +CoglClosure * +_cogl_closure_list_add (CoglList *list, + void *function, + void *user_data, + CoglUserDataDestroyCallback destroy_cb) +{ + CoglClosure *closure = g_slice_new (CoglClosure); + + closure->function = function; + closure->user_data = user_data; + closure->destroy_cb = destroy_cb; + + _cogl_list_insert (list, &closure->link); + + return closure; +} diff --git a/cogl/cogl/cogl-color-private.h b/cogl/cogl/cogl-color-private.h new file mode 100644 index 0000000..bb1a58e --- /dev/null +++ b/cogl/cogl/cogl-color-private.h @@ -0,0 +1,51 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_COLOR_PRIVATE_PRIVATE_H +#define __COGL_COLOR_PRIVATE_PRIVATE_H + +#include "cogl-color.h" + +#include + +/* cogl-pipeline.c wants to be able to hash CoglColor data so it needs + * the exact data size to be able to avoid reading the padding bytes. + */ +#define _COGL_COLOR_DATA_SIZE 4 + +void +_cogl_color_get_rgba_4ubv (const CoglColor *color, + uint8_t *dest); + +#endif /* __COGL_COLOR_PRIVATE_PRIVATE_H */ + diff --git a/cogl/cogl/cogl-color.c b/cogl/cogl/cogl-color.c new file mode 100644 index 0000000..631ec4a --- /dev/null +++ b/cogl/cogl/cogl-color.c @@ -0,0 +1,448 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include + +#include "cogl-util.h" +#include "cogl-color.h" +#include "cogl-color-private.h" +#include "cogl-gtype-private.h" + +COGL_GTYPE_DEFINE_BOXED (Color, color, cogl_color_copy, cogl_color_free); + +CoglColor * +cogl_color_new (void) +{ + return g_slice_new (CoglColor); +} + +CoglColor * +cogl_color_copy (const CoglColor *color) +{ + if (G_LIKELY (color)) + return g_slice_dup (CoglColor, color); + + return NULL; +} + +void +cogl_color_free (CoglColor *color) +{ + if (G_LIKELY (color)) + g_slice_free (CoglColor, color); +} + +void +cogl_color_init_from_4ub (CoglColor *color, + uint8_t red, + uint8_t green, + uint8_t blue, + uint8_t alpha) +{ + _COGL_RETURN_IF_FAIL (color != NULL); + + color->red = red; + color->green = green; + color->blue = blue; + color->alpha = alpha; +} + +/* XXX: deprecated, use cogl_color_init_from_4ub */ +void +cogl_color_set_from_4ub (CoglColor *dest, + uint8_t red, + uint8_t green, + uint8_t blue, + uint8_t alpha) +{ + cogl_color_init_from_4ub (dest, red, green, blue, alpha); +} + +void +cogl_color_init_from_4f (CoglColor *color, + float red, + float green, + float blue, + float alpha) +{ + _COGL_RETURN_IF_FAIL (color != NULL); + + color->red = (red * 255); + color->green = (green * 255); + color->blue = (blue * 255); + color->alpha = (alpha * 255); +} + +/* XXX: deprecated, use cogl_color_init_from_4f */ +void +cogl_color_set_from_4f (CoglColor *color, + float red, + float green, + float blue, + float alpha) +{ + cogl_color_init_from_4f (color, red, green, blue, alpha); +} + +void +cogl_color_init_from_4fv (CoglColor *color, + const float *color_array) +{ + _COGL_RETURN_IF_FAIL (color != NULL); + + color->red = (color_array[0] * 255); + color->green = (color_array[1] * 255); + color->blue = (color_array[2] * 255); + color->alpha = (color_array[3] * 255); +} + +unsigned char +cogl_color_get_red_byte (const CoglColor *color) +{ + return color->red; +} + +float +cogl_color_get_red_float (const CoglColor *color) +{ + return (float) color->red / 255.0; +} + +float +cogl_color_get_red (const CoglColor *color) +{ + return ((float) color->red / 255.0); +} + +unsigned char +cogl_color_get_green_byte (const CoglColor *color) +{ + return color->green; +} + +float +cogl_color_get_green_float (const CoglColor *color) +{ + return (float) color->green / 255.0; +} + +float +cogl_color_get_green (const CoglColor *color) +{ + return ((float) color->green / 255.0); +} + +unsigned char +cogl_color_get_blue_byte (const CoglColor *color) +{ + return color->blue; +} + +float +cogl_color_get_blue_float (const CoglColor *color) +{ + return (float) color->blue / 255.0; +} + +float +cogl_color_get_blue (const CoglColor *color) +{ + return ((float) color->blue / 255.0); +} + +unsigned char +cogl_color_get_alpha_byte (const CoglColor *color) +{ + return color->alpha; +} + +float +cogl_color_get_alpha_float (const CoglColor *color) +{ + return (float) color->alpha / 255.0; +} + +float +cogl_color_get_alpha (const CoglColor *color) +{ + return ((float) color->alpha / 255.0); +} + +void +cogl_color_set_red_byte (CoglColor *color, + unsigned char red) +{ + color->red = red; +} + +void +cogl_color_set_red_float (CoglColor *color, + float red) +{ + color->red = red * 255.0; +} + +void +cogl_color_set_red (CoglColor *color, + float red) +{ + color->red = red * 255.0; +} + +void +cogl_color_set_green_byte (CoglColor *color, + unsigned char green) +{ + color->green = green; +} + +void +cogl_color_set_green_float (CoglColor *color, + float green) +{ + color->green = green * 255.0; +} + +void +cogl_color_set_green (CoglColor *color, + float green) +{ + color->green = green * 255.0; +} + +void +cogl_color_set_blue_byte (CoglColor *color, + unsigned char blue) +{ + color->blue = blue; +} + +void +cogl_color_set_blue_float (CoglColor *color, + float blue) +{ + color->blue = blue * 255.0; +} + +void +cogl_color_set_blue (CoglColor *color, + float blue) +{ + color->blue = blue * 255.0; +} + +void +cogl_color_set_alpha_byte (CoglColor *color, + unsigned char alpha) +{ + color->alpha = alpha; +} + +void +cogl_color_set_alpha_float (CoglColor *color, + float alpha) +{ + color->alpha = alpha * 255.0; +} + +void +cogl_color_set_alpha (CoglColor *color, + float alpha) +{ + color->alpha = alpha * 255.0; +} + +void +cogl_color_premultiply (CoglColor *color) +{ + color->red = (color->red * color->alpha + 128) / 255; + color->green = (color->green * color->alpha + 128) / 255; + color->blue = (color->blue * color->alpha + 128) / 255; +} + +void +cogl_color_unpremultiply (CoglColor *color) +{ + if (color->alpha != 0) + { + color->red = (color->red * 255) / color->alpha; + color->green = (color->green * 255) / color->alpha; + color->blue = (color->blue * 255) / color->alpha; + } +} + +CoglBool +cogl_color_equal (const void *v1, const void *v2) +{ + const uint32_t *c1 = v1, *c2 = v2; + + _COGL_RETURN_VAL_IF_FAIL (v1 != NULL, FALSE); + _COGL_RETURN_VAL_IF_FAIL (v2 != NULL, FALSE); + + /* XXX: We don't compare the padding */ + return *c1 == *c2 ? TRUE : FALSE; +} + +void +_cogl_color_get_rgba_4ubv (const CoglColor *color, + uint8_t *dest) +{ + memcpy (dest, color, 4); +} + +void +cogl_color_to_hsl (const CoglColor *color, + float *hue, + float *saturation, + float *luminance) +{ + float red, green, blue; + float min, max, delta; + float h, l, s; + + red = color->red / 255.0; + green = color->green / 255.0; + blue = color->blue / 255.0; + + if (red > green) + { + if (red > blue) + max = red; + else + max = blue; + + if (green < blue) + min = green; + else + min = blue; + } + else + { + if (green > blue) + max = green; + else + max = blue; + + if (red < blue) + min = red; + else + min = blue; + } + + l = (max + min) / 2; + s = 0; + h = 0; + + if (max != min) + { + if (l <= 0.5) + s = (max - min) / (max + min); + else + s = (max - min) / (2.0 - max - min); + + delta = max - min; + + if (red == max) + h = (green - blue) / delta; + else if (green == max) + h = 2.0 + (blue - red) / delta; + else if (blue == max) + h = 4.0 + (red - green) / delta; + + h *= 60; + + if (h < 0) + h += 360.0; + } + + if (hue) + *hue = h; + + if (luminance) + *luminance = l; + + if (saturation) + *saturation = s; +} + +void +cogl_color_init_from_hsl (CoglColor *color, + float hue, + float saturation, + float luminance) +{ + float tmp1, tmp2; + float tmp3[3]; + float clr[3]; + int i; + + hue /= 360.0; + + if (saturation == 0) + { + cogl_color_init_from_4f (color, luminance, luminance, luminance, 1.0f); + return; + } + + if (luminance <= 0.5) + tmp2 = luminance * (1.0 + saturation); + else + tmp2 = luminance + saturation - (luminance * saturation); + + tmp1 = 2.0 * luminance - tmp2; + + tmp3[0] = hue + 1.0 / 3.0; + tmp3[1] = hue; + tmp3[2] = hue - 1.0 / 3.0; + + for (i = 0; i < 3; i++) + { + if (tmp3[i] < 0) + tmp3[i] += 1.0; + + if (tmp3[i] > 1) + tmp3[i] -= 1.0; + + if (6.0 * tmp3[i] < 1.0) + clr[i] = tmp1 + (tmp2 - tmp1) * tmp3[i] * 6.0; + else if (2.0 * tmp3[i] < 1.0) + clr[i] = tmp2; + else if (3.0 * tmp3[i] < 2.0) + clr[i] = (tmp1 + (tmp2 - tmp1) * ((2.0 / 3.0) - tmp3[i]) * 6.0); + else + clr[i] = tmp1; + } + + cogl_color_init_from_4f (color, clr[0], clr[1], clr[2], 1.0f); +} diff --git a/cogl/cogl/cogl-color.h b/cogl/cogl/cogl-color.h new file mode 100644 index 0000000..42fe525 --- /dev/null +++ b/cogl/cogl/cogl-color.h @@ -0,0 +1,600 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_COLOR_H__ +#define __COGL_COLOR_H__ + +/** + * SECTION:cogl-color + * @short_description: A generic color definition + * + * #CoglColor is a simple structure holding the definition of a color such + * that it can be efficiently used by GL + * + * Since: 1.0 + */ + +#include +#include + +#include + +COGL_BEGIN_DECLS + +/** + * cogl_color_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_color_get_gtype (void); + +/** + * cogl_color_new: + * + * Creates a new (empty) color + * + * Return value: a newly-allocated #CoglColor. Use cogl_color_free() + * to free the allocated resources + * + * Since: 1.0 + */ +CoglColor * +cogl_color_new (void); + +/** + * cogl_color_copy: + * @color: the color to copy + * + * Creates a copy of @color + * + * Return value: a newly-allocated #CoglColor. Use cogl_color_free() + * to free the allocate resources + * + * Since: 1.0 + */ +CoglColor * +cogl_color_copy (const CoglColor *color); + +/** + * cogl_color_free: + * @color: the color to free + * + * Frees the resources allocated by cogl_color_new() and cogl_color_copy() + * + * Since: 1.0 + */ +void +cogl_color_free (CoglColor *color); + +/** + * cogl_color_init_from_4ub: + * @color: A pointer to a #CoglColor to initialize + * @red: value of the red channel, between 0 and 255 + * @green: value of the green channel, between 0 and 255 + * @blue: value of the blue channel, between 0 and 255 + * @alpha: value of the alpha channel, between 0 and 255 + * + * Sets the values of the passed channels into a #CoglColor. + * + * Since: 1.4 + */ +void +cogl_color_init_from_4ub (CoglColor *color, + uint8_t red, + uint8_t green, + uint8_t blue, + uint8_t alpha); + +/** + * cogl_color_set_from_4ub: + * @color: A pointer to a #CoglColor to initialize + * @red: value of the red channel, between 0 and 255 + * @green: value of the green channel, between 0 and 255 + * @blue: value of the blue channel, between 0 and 255 + * @alpha: value of the alpha channel, between 0 and 255 + * + * Sets the values of the passed channels into a #CoglColor. + * + * Since: 1.0 + * Deprecated: 1.4: Use cogl_color_init_from_4ub instead. + */ +COGL_DEPRECATED_IN_1_4_FOR (cogl_color_init_from_4ub) +void +cogl_color_set_from_4ub (CoglColor *color, + uint8_t red, + uint8_t green, + uint8_t blue, + uint8_t alpha); + +/** + * cogl_color_init_from_4f: + * @color: A pointer to a #CoglColor to initialize + * @red: value of the red channel, between 0 and 1.0 + * @green: value of the green channel, between 0 and 1.0 + * @blue: value of the blue channel, between 0 and 1.0 + * @alpha: value of the alpha channel, between 0 and 1.0 + * + * Sets the values of the passed channels into a #CoglColor + * + * Since: 1.4 + */ +void +cogl_color_init_from_4f (CoglColor *color, + float red, + float green, + float blue, + float alpha); + +/** + * cogl_color_set_from_4f: + * @color: A pointer to a #CoglColor to initialize + * @red: value of the red channel, between 0 and %1.0 + * @green: value of the green channel, between 0 and %1.0 + * @blue: value of the blue channel, between 0 and %1.0 + * @alpha: value of the alpha channel, between 0 and %1.0 + * + * Sets the values of the passed channels into a #CoglColor + * + * Since: 1.0 + * Deprecated: 1.4: Use cogl_color_init_from_4f instead. + */ +COGL_DEPRECATED_IN_1_4_FOR (cogl_color_init_from_4f) +void +cogl_color_set_from_4f (CoglColor *color, + float red, + float green, + float blue, + float alpha); + +/** + * cogl_color_init_from_4fv: + * @color: A pointer to a #CoglColor to initialize + * @color_array: a pointer to an array of 4 float color components + * + * Sets the values of the passed channels into a #CoglColor + * + * Since: 1.4 + */ +void +cogl_color_init_from_4fv (CoglColor *color, + const float *color_array); + +/** + * cogl_color_get_red_byte: + * @color: a #CoglColor + * + * Retrieves the red channel of @color as a byte value + * between 0 and 255 + * + * Return value: the red channel of the passed color + * + * Since: 1.0 + */ +unsigned char +cogl_color_get_red_byte (const CoglColor *color); + +/** + * cogl_color_get_green_byte: + * @color: a #CoglColor + * + * Retrieves the green channel of @color as a byte value + * between 0 and 255 + * + * Return value: the green channel of the passed color + * + * Since: 1.0 + */ +unsigned char +cogl_color_get_green_byte (const CoglColor *color); + +/** + * cogl_color_get_blue_byte: + * @color: a #CoglColor + * + * Retrieves the blue channel of @color as a byte value + * between 0 and 255 + * + * Return value: the blue channel of the passed color + * + * Since: 1.0 + */ +unsigned char +cogl_color_get_blue_byte (const CoglColor *color); + +/** + * cogl_color_get_alpha_byte: + * @color: a #CoglColor + * + * Retrieves the alpha channel of @color as a byte value + * between 0 and 255 + * + * Return value: the alpha channel of the passed color + * + * Since: 1.0 + */ +unsigned char +cogl_color_get_alpha_byte (const CoglColor *color); + +/** + * cogl_color_get_red_float: + * @color: a #CoglColor + * + * Retrieves the red channel of @color as a floating point + * value between 0.0 and 1.0 + * + * Return value: the red channel of the passed color + * + * Since: 1.0 + */ +float +cogl_color_get_red_float (const CoglColor *color); + +/** + * cogl_color_get_green_float: + * @color: a #CoglColor + * + * Retrieves the green channel of @color as a floating point + * value between 0.0 and 1.0 + * + * Return value: the green channel of the passed color + * + * Since: 1.0 + */ +float +cogl_color_get_green_float (const CoglColor *color); + +/** + * cogl_color_get_blue_float: + * @color: a #CoglColor + * + * Retrieves the blue channel of @color as a floating point + * value between 0.0 and 1.0 + * + * Return value: the blue channel of the passed color + * + * Since: 1.0 + */ +float +cogl_color_get_blue_float (const CoglColor *color); + +/** + * cogl_color_get_alpha_float: + * @color: a #CoglColor + * + * Retrieves the alpha channel of @color as a floating point + * value between 0.0 and 1.0 + * + * Return value: the alpha channel of the passed color + * + * Since: 1.0 + */ +float +cogl_color_get_alpha_float (const CoglColor *color); + +/** + * cogl_color_get_red: + * @color: a #CoglColor + * + * Retrieves the red channel of @color as a fixed point + * value between 0 and 1.0. + * + * Return value: the red channel of the passed color + * + * Since: 1.0 + */ +float +cogl_color_get_red (const CoglColor *color); + +/** + * cogl_color_get_green: + * @color: a #CoglColor + * + * Retrieves the green channel of @color as a fixed point + * value between 0 and 1.0. + * + * Return value: the green channel of the passed color + * + * Since: 1.0 + */ +float +cogl_color_get_green (const CoglColor *color); + +/** + * cogl_color_get_blue: + * @color: a #CoglColor + * + * Retrieves the blue channel of @color as a fixed point + * value between 0 and 1.0. + * + * Return value: the blue channel of the passed color + * + * Since: 1.0 + */ +float +cogl_color_get_blue (const CoglColor *color); + +/** + * cogl_color_get_alpha: + * @color: a #CoglColor + * + * Retrieves the alpha channel of @color as a fixed point + * value between 0 and 1.0. + * + * Return value: the alpha channel of the passed color + * + * Since: 1.0 + */ +float +cogl_color_get_alpha (const CoglColor *color); + +/** + * cogl_color_set_red_byte: + * @color: a #CoglColor + * @red: a byte value between 0 and 255 + * + * Sets the red channel of @color to @red. + * + * Since: 1.4 + */ +void +cogl_color_set_red_byte (CoglColor *color, + unsigned char red); + +/** + * cogl_color_set_green_byte: + * @color: a #CoglColor + * @green: a byte value between 0 and 255 + * + * Sets the green channel of @color to @green. + * + * Since: 1.4 + */ +void +cogl_color_set_green_byte (CoglColor *color, + unsigned char green); + +/** + * cogl_color_set_blue_byte: + * @color: a #CoglColor + * @blue: a byte value between 0 and 255 + * + * Sets the blue channel of @color to @blue. + * + * Since: 1.4 + */ +void +cogl_color_set_blue_byte (CoglColor *color, + unsigned char blue); + +/** + * cogl_color_set_alpha_byte: + * @color: a #CoglColor + * @alpha: a byte value between 0 and 255 + * + * Sets the alpha channel of @color to @alpha. + * + * Since: 1.4 + */ +void +cogl_color_set_alpha_byte (CoglColor *color, + unsigned char alpha); + +/** + * cogl_color_set_red_float: + * @color: a #CoglColor + * @red: a float value between 0.0f and 1.0f + * + * Sets the red channel of @color to @red. + * + * since: 1.4 + */ +void +cogl_color_set_red_float (CoglColor *color, + float red); + +/** + * cogl_color_set_green_float: + * @color: a #CoglColor + * @green: a float value between 0.0f and 1.0f + * + * Sets the green channel of @color to @green. + * + * since: 1.4 + */ +void +cogl_color_set_green_float (CoglColor *color, + float green); + +/** + * cogl_color_set_blue_float: + * @color: a #CoglColor + * @blue: a float value between 0.0f and 1.0f + * + * Sets the blue channel of @color to @blue. + * + * since: 1.4 + */ +void +cogl_color_set_blue_float (CoglColor *color, + float blue); + +/** + * cogl_color_set_alpha_float: + * @color: a #CoglColor + * @alpha: a float value between 0.0f and 1.0f + * + * Sets the alpha channel of @color to @alpha. + * + * since: 1.4 + */ +void +cogl_color_set_alpha_float (CoglColor *color, + float alpha); + +/** + * cogl_color_set_red: + * @color: a #CoglColor + * @red: a float value between 0.0f and 1.0f + * + * Sets the red channel of @color to @red. + * + * Since: 1.4 + */ +void +cogl_color_set_red (CoglColor *color, + float red); + +/** + * cogl_color_set_green: + * @color: a #CoglColor + * @green: a float value between 0.0f and 1.0f + * + * Sets the green channel of @color to @green. + * + * Since: 1.4 + */ +void +cogl_color_set_green (CoglColor *color, + float green); + +/** + * cogl_color_set_blue: + * @color: a #CoglColor + * @blue: a float value between 0.0f and 1.0f + * + * Sets the blue channel of @color to @blue. + * + * Since: 1.4 + */ +void +cogl_color_set_blue (CoglColor *color, + float blue); + +/** + * cogl_color_set_alpha: + * @color: a #CoglColor + * @alpha: a float value between 0.0f and 1.0f + * + * Sets the alpha channel of @color to @alpha. + * + * Since: 1.4 + */ +void +cogl_color_set_alpha (CoglColor *color, + float alpha); + +/** + * cogl_color_premultiply: + * @color: the color to premultiply + * + * Converts a non-premultiplied color to a pre-multiplied color. For + * example, semi-transparent red is (1.0, 0, 0, 0.5) when non-premultiplied + * and (0.5, 0, 0, 0.5) when premultiplied. + * + * Since: 1.0 + */ +void +cogl_color_premultiply (CoglColor *color); + +/** + * cogl_color_unpremultiply: + * @color: the color to unpremultiply + * + * Converts a pre-multiplied color to a non-premultiplied color. For + * example, semi-transparent red is (0.5, 0, 0, 0.5) when premultiplied + * and (1.0, 0, 0, 0.5) when non-premultiplied. + * + * Since: 1.4 + */ +void +cogl_color_unpremultiply (CoglColor *color); + +/** + * cogl_color_equal: + * @v1: a #CoglColor + * @v2: a #CoglColor + * + * Compares two #CoglColors and checks if they are the same. + * + * This function can be passed to g_hash_table_new() as the @key_equal_func + * parameter, when using #CoglColors as keys in a #GHashTable. + * + * Return value: %TRUE if the two colors are the same. + * + * Since: 1.0 + */ +CoglBool +cogl_color_equal (const void *v1, const void *v2); + +/** + * cogl_color_to_hsl: + * @color: a #CoglColor + * @hue: (out): return location for the hue value or %NULL + * @saturation: (out): return location for the saturation value or %NULL + * @luminance: (out): return location for the luminance value or %NULL + * + * Converts @color to the HLS format. + * + * The @hue value is in the 0 .. 360 range. The @luminance and + * @saturation values are in the 0 .. 1 range. + * + * Since: 1.16 + */ +void +cogl_color_to_hsl (const CoglColor *color, + float *hue, + float *saturation, + float *luminance); + +/** + * cogl_color_init_from_hsl: + * @color: (out): return location for a #CoglColor + * @hue: hue value, in the 0 .. 360 range + * @saturation: saturation value, in the 0 .. 1 range + * @luminance: luminance value, in the 0 .. 1 range + * + * Converts a color expressed in HLS (hue, luminance and saturation) + * values into a #CoglColor. + * + * Since: 1.16 + */ +void +cogl_color_init_from_hsl (CoglColor *color, + float hue, + float saturation, + float luminance); + +COGL_END_DECLS + +#endif /* __COGL_COLOR_H__ */ diff --git a/cogl/cogl/cogl-config-private.h b/cogl/cogl/cogl-config-private.h new file mode 100644 index 0000000..93ff943 --- /dev/null +++ b/cogl/cogl/cogl-config-private.h @@ -0,0 +1,45 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_CONFIG_PRIVATE_H +#define __COGL_CONFIG_PRIVATE_H + +void +_cogl_config_read (void); + +extern char *_cogl_config_driver; +extern char *_cogl_config_renderer; +extern char *_cogl_config_disable_gl_extensions; +extern char *_cogl_config_override_gl_version; + +#endif /* __COGL_CONFIG_PRIVATE_H */ diff --git a/cogl/cogl/cogl-config.c b/cogl/cogl/cogl-config.c new file mode 100644 index 0000000..032dc37 --- /dev/null +++ b/cogl/cogl/cogl-config.c @@ -0,0 +1,135 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-debug.h" +#include "cogl-config-private.h" + +#include + +char *_cogl_config_driver; +char *_cogl_config_renderer; +char *_cogl_config_disable_gl_extensions; +char *_cogl_config_override_gl_version; + +/* Array of config options that just set a global string */ +static const struct +{ + const char *conf_name; + char **variable; +} cogl_config_string_options[] = + { + { "COGL_DRIVER", &_cogl_config_driver }, + { "COGL_RENDERER", &_cogl_config_renderer }, + { "COGL_DISABLE_GL_EXTENSIONS", &_cogl_config_disable_gl_extensions }, + { "COGL_OVERRIDE_GL_VERSION", &_cogl_config_override_gl_version } + }; + +static void +_cogl_config_process (GKeyFile *key_file) +{ + char *value; + int i; + + value = g_key_file_get_string (key_file, "global", "COGL_DEBUG", NULL); + if (value) + { + _cogl_parse_debug_string (value, + TRUE /* enable the flags */, + TRUE /* ignore help option */); + g_free (value); + } + + value = g_key_file_get_string (key_file, "global", "COGL_NO_DEBUG", NULL); + if (value) + { + _cogl_parse_debug_string (value, + FALSE /* disable the flags */, + TRUE /* ignore help option */); + g_free (value); + } + + for (i = 0; i < G_N_ELEMENTS (cogl_config_string_options); i++) + { + const char *conf_name = cogl_config_string_options[i].conf_name; + char **variable = cogl_config_string_options[i].variable; + + value = g_key_file_get_string (key_file, "global", conf_name, NULL); + if (value) + { + g_free (*variable); + *variable = value; + } + } +} + +void +_cogl_config_read (void) +{ + GKeyFile *key_file = g_key_file_new (); + const char * const *system_dirs = g_get_system_config_dirs (); + char *filename; + CoglBool status = FALSE; + int i; + + for (i = 0; system_dirs[i]; i++) + { + filename = g_build_filename (system_dirs[i], "cogl", "cogl.conf", NULL); + status = g_key_file_load_from_file (key_file, + filename, + 0, + NULL); + g_free (filename); + if (status) + { + _cogl_config_process (key_file); + g_key_file_free (key_file); + key_file = g_key_file_new (); + break; + } + } + + filename = g_build_filename (g_get_user_config_dir (), "cogl", "cogl.conf", NULL); + status = g_key_file_load_from_file (key_file, + filename, + 0, + NULL); + g_free (filename); + + if (status) + _cogl_config_process (key_file); + + g_key_file_free (key_file); +} diff --git a/cogl/cogl/cogl-context-private.h b/cogl/cogl/cogl-context-private.h new file mode 100644 index 0000000..9e66207 --- /dev/null +++ b/cogl/cogl/cogl-context-private.h @@ -0,0 +1,407 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_CONTEXT_PRIVATE_H +#define __COGL_CONTEXT_PRIVATE_H + +#include "cogl-context.h" +#include "cogl-winsys-private.h" +#include "cogl-flags.h" + +#ifdef COGL_HAS_XLIB_SUPPORT +#include "cogl-xlib-private.h" +#endif + +#include "cogl-display-private.h" +#include "cogl-primitives.h" +#include "cogl-clip-stack.h" +#include "cogl-matrix-stack.h" +#include "cogl-pipeline-private.h" +#include "cogl-buffer-private.h" +#include "cogl-bitmask.h" +#include "cogl-atlas.h" +#include "cogl-driver.h" +#include "cogl-texture-driver.h" +#include "cogl-pipeline-cache.h" +#include "cogl-texture-2d.h" +#include "cogl-texture-3d.h" +#include "cogl-texture-rectangle.h" +#include "cogl-sampler-cache-private.h" +#include "cogl-gpu-info-private.h" +#include "cogl-gl-header.h" +#include "cogl-framebuffer-private.h" +#include "cogl-onscreen-private.h" +#include "cogl-fence-private.h" +#include "cogl-poll-private.h" +#include "cogl-path/cogl-path-types.h" +#include "cogl-private.h" + +typedef struct +{ + GLfloat v[3]; + GLfloat t[2]; + GLubyte c[4]; +} CoglTextureGLVertex; + +struct _CoglContext +{ + CoglObject _parent; + + CoglDisplay *display; + + CoglDriver driver; + + /* Information about the GPU and driver which we can use to + determine certain workarounds */ + CoglGpuInfo gpu; + + /* vtables for the driver functions */ + const CoglDriverVtable *driver_vtable; + const CoglTextureDriver *texture_driver; + + int glsl_major; + int glsl_minor; + + /* This is the GLSL version that we will claim that snippets are + * written against using the #version pragma. This will be the + * largest version that is less than or equal to the version + * provided by the driver without massively altering the syntax. Eg, + * we wouldn't use version 1.3 even if it is available because that + * removes the ‘attribute’ and ‘varying’ keywords. */ + int glsl_version_to_use; + + /* Features cache */ + unsigned long features[COGL_FLAGS_N_LONGS_FOR_SIZE (_COGL_N_FEATURE_IDS)]; + CoglFeatureFlags feature_flags; /* legacy/deprecated feature flags */ + unsigned long private_features + [COGL_FLAGS_N_LONGS_FOR_SIZE (COGL_N_PRIVATE_FEATURES)]; + + CoglBool needs_viewport_scissor_workaround; + CoglFramebuffer *viewport_scissor_workaround_framebuffer; + + CoglPipeline *default_pipeline; + CoglPipelineLayer *default_layer_0; + CoglPipelineLayer *default_layer_n; + CoglPipelineLayer *dummy_layer_dependant; + + GHashTable *attribute_name_states_hash; + GArray *attribute_name_index_map; + int n_attribute_names; + + CoglBitmask enabled_builtin_attributes; + CoglBitmask enabled_texcoord_attributes; + CoglBitmask enabled_custom_attributes; + + /* These are temporary bitmasks that are used when disabling + * builtin,texcoord and custom attribute arrays. They are here just + * to avoid allocating new ones each time */ + CoglBitmask enable_builtin_attributes_tmp; + CoglBitmask enable_texcoord_attributes_tmp; + CoglBitmask enable_custom_attributes_tmp; + CoglBitmask changed_bits_tmp; + + CoglBool legacy_backface_culling_enabled; + + /* A few handy matrix constants */ + CoglMatrix identity_matrix; + CoglMatrix y_flip_matrix; + + /* Value that was last used when calling glMatrixMode to avoid + calling it multiple times */ + CoglMatrixMode flushed_matrix_mode; + + /* The matrix stack entries that should be flushed during the next + * pipeline state flush */ + CoglMatrixEntry *current_projection_entry; + CoglMatrixEntry *current_modelview_entry; + + CoglMatrixEntry identity_entry; + + /* A cache of the last (immutable) matrix stack entries that were + * flushed to the GL matrix builtins */ + CoglMatrixEntryCache builtin_flushed_projection; + CoglMatrixEntryCache builtin_flushed_modelview; + + GArray *texture_units; + int active_texture_unit; + + CoglPipelineFogState legacy_fog_state; + + /* Pipelines */ + CoglPipeline *opaque_color_pipeline; /* used for set_source_color */ + CoglPipeline *blended_color_pipeline; /* used for set_source_color */ + CoglPipeline *texture_pipeline; /* used for set_source_texture */ + GString *codegen_header_buffer; + GString *codegen_source_buffer; + GString *codegen_boilerplate_buffer; + GList *source_stack; + + int legacy_state_set; + + CoglPipelineCache *pipeline_cache; + + /* Textures */ + CoglTexture2D *default_gl_texture_2d_tex; + CoglTexture3D *default_gl_texture_3d_tex; + CoglTextureRectangle *default_gl_texture_rect_tex; + + /* Central list of all framebuffers so all journals can be flushed + * at any time. */ + GList *framebuffers; + + /* Global journal buffers */ + GArray *journal_flush_attributes_array; + GArray *journal_clip_bounds; + + GArray *polygon_vertices; + + /* Some simple caching, to minimize state changes... */ + CoglPipeline *current_pipeline; + unsigned long current_pipeline_changes_since_flush; + CoglBool current_pipeline_with_color_attrib; + CoglBool current_pipeline_unknown_color_alpha; + unsigned long current_pipeline_age; + + CoglBool gl_blend_enable_cache; + + CoglBool depth_test_enabled_cache; + CoglDepthTestFunction depth_test_function_cache; + CoglBool depth_writing_enabled_cache; + float depth_range_near_cache; + float depth_range_far_cache; + + CoglBool legacy_depth_test_enabled; + + CoglBuffer *current_buffer[COGL_BUFFER_BIND_TARGET_COUNT]; + + /* Framebuffers */ + GSList *framebuffer_stack; + CoglFramebuffer *window_buffer; + unsigned long current_draw_buffer_state_flushed; + unsigned long current_draw_buffer_changes; + CoglFramebuffer *current_draw_buffer; + CoglFramebuffer *current_read_buffer; + + gboolean have_last_offscreen_allocate_flags; + CoglOffscreenAllocateFlags last_offscreen_allocate_flags; + + GHashTable *swap_callback_closures; + int next_swap_callback_id; + + CoglList onscreen_events_queue; + CoglList onscreen_dirty_queue; + CoglClosure *onscreen_dispatch_idle; + + CoglGLES2Context *current_gles2_context; + GQueue gles2_context_stack; + + /* This becomes TRUE the first time the context is bound to an + * onscreen buffer. This is used by cogl-framebuffer-gl to determine + * when to initialise the glDrawBuffer state */ + CoglBool was_bound_to_onscreen; + + /* Primitives */ + CoglPath *current_path; + CoglPipeline *stencil_pipeline; + + /* Pre-generated VBOs containing indices to generate GL_TRIANGLES + out of a vertex array of quads */ + CoglIndices *quad_buffer_indices_byte; + unsigned int quad_buffer_indices_len; + CoglIndices *quad_buffer_indices; + + CoglIndices *rectangle_byte_indices; + CoglIndices *rectangle_short_indices; + int rectangle_short_indices_len; + + CoglBool in_begin_gl_block; + + CoglPipeline *texture_download_pipeline; + CoglPipeline *blit_texture_pipeline; + + GSList *atlases; + GHookList atlas_reorganize_callbacks; + + /* This debugging variable is used to pick a colour for visually + displaying the quad batches. It needs to be global so that it can + be reset by cogl_clear. It needs to be reset to increase the + chances of getting the same colour during an animation */ + uint8_t journal_rectangles_color; + + /* Cached values for GL_MAX_TEXTURE_[IMAGE_]UNITS to avoid calling + glGetInteger too often */ + GLint max_texture_units; + GLint max_texture_image_units; + GLint max_activateable_texture_units; + + /* Fragment processing programs */ + CoglHandle current_program; + + CoglPipelineProgramType current_fragment_program_type; + CoglPipelineProgramType current_vertex_program_type; + GLuint current_gl_program; + + CoglBool current_gl_dither_enabled; + CoglColorMask current_gl_color_mask; + GLenum current_gl_draw_buffer; + + /* Clipping */ + /* TRUE if we have a valid clipping stack flushed. In that case + current_clip_stack will describe what the current state is. If + this is FALSE then the current clip stack is completely unknown + so it will need to be reflushed. In that case current_clip_stack + doesn't need to be a valid pointer. We can't just use NULL in + current_clip_stack to mark a dirty state because NULL is a valid + stack (meaning no clipping) */ + CoglBool current_clip_stack_valid; + /* The clip state that was flushed. This isn't intended to be used + as a stack to push and pop new entries. Instead the current stack + that the user wants is part of the framebuffer state. This is + just used to record the flush state so we can avoid flushing the + same state multiple times. When the clip state is flushed this + will hold a reference */ + CoglClipStack *current_clip_stack; + /* Whether the stencil buffer was used as part of the current clip + state. If TRUE then any further use of the stencil buffer (such + as for drawing paths) would need to be merged with the existing + stencil buffer */ + CoglBool current_clip_stack_uses_stencil; + + /* This is used as a temporary buffer to fill a CoglBuffer when + cogl_buffer_map fails and we only want to map to fill it with new + data */ + GByteArray *buffer_map_fallback_array; + CoglBool buffer_map_fallback_in_use; + size_t buffer_map_fallback_offset; + + CoglWinsysRectangleState rectangle_state; + + CoglSamplerCache *sampler_cache; + + /* FIXME: remove these when we remove the last xlib based clutter + * backend. they should be tracked as part of the renderer but e.g. + * the eglx backend doesn't yet have a corresponding Cogl winsys + * and so we wont have a renderer in that case. */ +#ifdef COGL_HAS_XLIB_SUPPORT + int damage_base; + /* List of callback functions that will be given every Xlib event */ + GSList *event_filters; + /* Current top of the XError trap state stack. The actual memory for + these is expected to be allocated on the stack by the caller */ + CoglXlibTrapState *trap_state; +#endif + + unsigned long winsys_features + [COGL_FLAGS_N_LONGS_FOR_SIZE (COGL_WINSYS_FEATURE_N_FEATURES)]; + void *winsys; + + /* Array of names of uniforms. These are used like quarks to give a + unique number to each uniform name except that we ensure that + they increase sequentially so that we can use the id as an index + into a bitfield representing the uniforms that a pipeline + overrides from its parent. */ + GPtrArray *uniform_names; + /* A hash table to quickly get an index given an existing name. The + name strings are owned by the uniform_names array. The values are + the uniform location cast to a pointer. */ + GHashTable *uniform_name_hash; + int n_uniform_names; + + CoglPollSource *fences_poll_source; + CoglList fences; + + /* This defines a list of function pointers that Cogl uses from + either GL or GLES. All functions are accessed indirectly through + these pointers rather than linking to them directly */ +#ifndef APIENTRY +#define APIENTRY +#endif + +#define COGL_EXT_BEGIN(name, \ + min_gl_major, min_gl_minor, \ + gles_availability, \ + extension_suffixes, extension_names) +#define COGL_EXT_FUNCTION(ret, name, args) \ + ret (APIENTRY * name) args; +#define COGL_EXT_END() + +#include "gl-prototypes/cogl-all-functions.h" + +#undef COGL_EXT_BEGIN +#undef COGL_EXT_FUNCTION +#undef COGL_EXT_END +}; + +CoglContext * +_cogl_context_get_default (); + +const CoglWinsysVtable * +_cogl_context_get_winsys (CoglContext *context); + +/* Query the GL extensions and lookup the corresponding function + * pointers. Theoretically the list of extensions can change for + * different GL contexts so it is the winsys backend's responsiblity + * to know when to re-query the GL extensions. The backend should also + * check whether the GL context is supported by Cogl. If not it should + * return FALSE and set @error */ +CoglBool +_cogl_context_update_features (CoglContext *context, + CoglError **error); + +/* Obtains the context and returns retval if NULL */ +#define _COGL_GET_CONTEXT(ctxvar, retval) \ +CoglContext *ctxvar = _cogl_context_get_default (); \ +if (ctxvar == NULL) return retval; + +#define NO_RETVAL + +void +_cogl_context_set_current_projection_entry (CoglContext *context, + CoglMatrixEntry *entry); + +void +_cogl_context_set_current_modelview_entry (CoglContext *context, + CoglMatrixEntry *entry); + +/* + * _cogl_context_get_gl_extensions: + * @context: A CoglContext + * + * Return value: a NULL-terminated array of strings representing the + * supported extensions by the current driver. This array is owned + * by the caller and should be freed with g_strfreev(). + */ +char ** +_cogl_context_get_gl_extensions (CoglContext *context); + +const char * +_cogl_context_get_gl_version (CoglContext *context); + +#endif /* __COGL_CONTEXT_PRIVATE_H */ diff --git a/cogl/cogl/cogl-context.c b/cogl/cogl/cogl-context.c new file mode 100644 index 0000000..c45c9b4 --- /dev/null +++ b/cogl/cogl/cogl-context.c @@ -0,0 +1,816 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-object.h" +#include "cogl-private.h" +#include "cogl-winsys-private.h" +#include "winsys/cogl-winsys-stub-private.h" +#include "cogl-profile.h" +#include "cogl-util.h" +#include "cogl-context-private.h" +#include "cogl-util-gl-private.h" +#include "cogl-display-private.h" +#include "cogl-renderer-private.h" +#include "cogl-journal-private.h" +#include "cogl-texture-private.h" +#include "cogl-texture-2d-private.h" +#include "cogl-texture-3d-private.h" +#include "cogl-texture-rectangle-private.h" +#include "cogl-pipeline-private.h" +#include "cogl-pipeline-opengl-private.h" +#include "cogl-framebuffer-private.h" +#include "cogl-onscreen-private.h" +#include "cogl-attribute-private.h" +#include "cogl1-context.h" +#include "cogl-gpu-info-private.h" +#include "cogl-config-private.h" +#include "cogl-error-private.h" +#include "cogl-gtype-private.h" + +#include "cogl/deprecated/cogl-framebuffer-deprecated.h" + +#include +#include + +#ifdef HAVE_COGL_GL +#include "cogl-pipeline-fragend-arbfp-private.h" +#endif + +/* These aren't defined in the GLES headers */ +#ifndef GL_POINT_SPRITE +#define GL_POINT_SPRITE 0x8861 +#endif + +#ifndef GL_NUM_EXTENSIONS +#define GL_NUM_EXTENSIONS 0x821D +#endif + +/* This is a relatively new extension */ +#ifndef GL_PURGED_CONTEXT_RESET_NV +#define GL_PURGED_CONTEXT_RESET_NV 0x92BB +#endif + +static void _cogl_context_free (CoglContext *context); + +COGL_OBJECT_DEFINE (Context, context); +COGL_GTYPE_DEFINE_CLASS (Context, context); + +extern void +_cogl_create_context_driver (CoglContext *context); + +static CoglContext *_cogl_context = NULL; + +static void +_cogl_init_feature_overrides (CoglContext *ctx) +{ + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_VBOS))) + COGL_FLAGS_SET (ctx->private_features, COGL_PRIVATE_FEATURE_VBOS, FALSE); + + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_PBOS))) + COGL_FLAGS_SET (ctx->private_features, COGL_PRIVATE_FEATURE_PBOS, FALSE); + + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_ARBFP))) + { + ctx->feature_flags &= ~COGL_FEATURE_SHADERS_ARBFP; + COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_ARBFP, FALSE); + } + + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_GLSL))) + { + ctx->feature_flags &= ~COGL_FEATURE_SHADERS_GLSL; + COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_GLSL, FALSE); + COGL_FLAGS_SET (ctx->features, + COGL_FEATURE_ID_PER_VERTEX_POINT_SIZE, + FALSE); + } + + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_NPOT_TEXTURES))) + { + ctx->feature_flags &= ~(COGL_FEATURE_TEXTURE_NPOT | + COGL_FEATURE_TEXTURE_NPOT_BASIC | + COGL_FEATURE_TEXTURE_NPOT_MIPMAP | + COGL_FEATURE_TEXTURE_NPOT_REPEAT); + COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_TEXTURE_NPOT, FALSE); + COGL_FLAGS_SET (ctx->features, + COGL_FEATURE_ID_TEXTURE_NPOT_BASIC, FALSE); + COGL_FLAGS_SET (ctx->features, + COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP, FALSE); + COGL_FLAGS_SET (ctx->features, + COGL_FEATURE_ID_TEXTURE_NPOT_REPEAT, FALSE); + } +} + +const CoglWinsysVtable * +_cogl_context_get_winsys (CoglContext *context) +{ + return context->display->renderer->winsys_vtable; +} + +/* For reference: There was some deliberation over whether to have a + * constructor that could throw an exception but looking at standard + * practices with several high level OO languages including python, C++, + * C# Java and Ruby they all support exceptions in constructors and the + * general consensus appears to be that throwing an exception is neater + * than successfully constructing with an internal error status that + * would then have to be explicitly checked via some form of ::is_ok() + * method. + */ +CoglContext * +cogl_context_new (CoglDisplay *display, + CoglError **error) +{ + CoglContext *context; + uint8_t white_pixel[] = { 0xff, 0xff, 0xff, 0xff }; + CoglBitmap *white_pixel_bitmap; + const CoglWinsysVtable *winsys; + int i; + CoglError *internal_error = NULL; + + _cogl_init (); + +#ifdef COGL_ENABLE_PROFILE + /* We need to be absolutely sure that uprof has been initialized + * before calling _cogl_uprof_init. uprof_init (NULL, NULL) + * will be a NOP if it has been initialized but it will also + * mean subsequent parsing of the UProf GOptionGroup will have no + * affect. + * + * Sadly GOptionGroup based library initialization is extremely + * fragile by design because GOptionGroups have no notion of + * dependencies and so the order things are initialized isn't + * currently under tight control. + */ + uprof_init (NULL, NULL); + _cogl_uprof_init (); +#endif + + /* Allocate context memory */ + context = g_malloc0 (sizeof (CoglContext)); + + /* Convert the context into an object immediately in case any of the + code below wants to verify that the context pointer is a valid + object */ + _cogl_context_object_new (context); + + /* XXX: Gross hack! + * Currently everything in Cogl just assumes there is a default + * context which it can access via _COGL_GET_CONTEXT() including + * code used to construct a CoglContext. Until all of that code + * has been updated to take an explicit context argument we have + * to immediately make our pointer the default context. + */ + _cogl_context = context; + + /* Init default values */ + memset (context->features, 0, sizeof (context->features)); + context->feature_flags = 0; + memset (context->private_features, 0, sizeof (context->private_features)); + + context->rectangle_state = COGL_WINSYS_RECTANGLE_STATE_UNKNOWN; + + memset (context->winsys_features, 0, sizeof (context->winsys_features)); + + if (!display) + { + CoglRenderer *renderer = cogl_renderer_new (); + if (!cogl_renderer_connect (renderer, error)) + { + g_free (context); + return NULL; + } + + display = cogl_display_new (renderer, NULL); + cogl_object_unref(renderer); + } + else + cogl_object_ref (display); + + if (!cogl_display_setup (display, error)) + { + cogl_object_unref (display); + g_free (context); + return NULL; + } + + context->display = display; + + /* This is duplicated data, but it's much more convenient to have + the driver attached to the context and the value is accessed a + lot throughout Cogl */ + context->driver = display->renderer->driver; + + /* Again this is duplicated data, but it convenient to be able + * access these from the context. */ + context->driver_vtable = display->renderer->driver_vtable; + context->texture_driver = display->renderer->texture_driver; + + for (i = 0; i < G_N_ELEMENTS (context->private_features); i++) + context->private_features[i] |= display->renderer->private_features[i]; + + winsys = _cogl_context_get_winsys (context); + if (!winsys->context_init (context, error)) + { + cogl_object_unref (display); + g_free (context); + return NULL; + } + + context->attribute_name_states_hash = + g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + context->attribute_name_index_map = NULL; + context->n_attribute_names = 0; + + /* The "cogl_color_in" attribute needs a deterministic name_index + * so we make sure it's the first attribute name we register */ + _cogl_attribute_register_attribute_name (context, "cogl_color_in"); + + + context->uniform_names = + g_ptr_array_new_with_free_func ((GDestroyNotify) g_free); + context->uniform_name_hash = g_hash_table_new (g_str_hash, g_str_equal); + context->n_uniform_names = 0; + + /* Initialise the driver specific state */ + _cogl_init_feature_overrides (context); + + /* XXX: ONGOING BUG: Intel viewport scissor + * + * Intel gen6 drivers don't currently correctly handle offset + * viewports, since primitives aren't clipped within the bounds of + * the viewport. To workaround this we push our own clip for the + * viewport that will use scissoring to ensure we clip as expected. + * + * TODO: file a bug upstream! + */ + if (context->gpu.driver_package == COGL_GPU_INFO_DRIVER_PACKAGE_MESA && + context->gpu.architecture == COGL_GPU_INFO_ARCHITECTURE_SANDYBRIDGE && + !getenv ("COGL_DISABLE_INTEL_VIEWPORT_SCISSORT_WORKAROUND")) + context->needs_viewport_scissor_workaround = TRUE; + else + context->needs_viewport_scissor_workaround = FALSE; + + context->sampler_cache = _cogl_sampler_cache_new (context); + + _cogl_pipeline_init_default_pipeline (); + _cogl_pipeline_init_default_layers (); + _cogl_pipeline_init_state_hash_functions (); + _cogl_pipeline_init_layer_state_hash_functions (); + + context->current_clip_stack_valid = FALSE; + context->current_clip_stack = NULL; + + context->legacy_backface_culling_enabled = FALSE; + + cogl_matrix_init_identity (&context->identity_matrix); + cogl_matrix_init_identity (&context->y_flip_matrix); + cogl_matrix_scale (&context->y_flip_matrix, 1, -1, 1); + + context->flushed_matrix_mode = COGL_MATRIX_MODELVIEW; + + context->texture_units = + g_array_new (FALSE, FALSE, sizeof (CoglTextureUnit)); + + if (_cogl_has_private_feature (context, COGL_PRIVATE_FEATURE_ANY_GL)) + { + /* See cogl-pipeline.c for more details about why we leave texture unit 1 + * active by default... */ + context->active_texture_unit = 1; + GE (context, glActiveTexture (GL_TEXTURE1)); + } + + context->legacy_fog_state.enabled = FALSE; + + context->opaque_color_pipeline = cogl_pipeline_new (context); + context->blended_color_pipeline = cogl_pipeline_new (context); + context->texture_pipeline = cogl_pipeline_new (context); + context->codegen_header_buffer = g_string_new (""); + context->codegen_source_buffer = g_string_new (""); + context->codegen_boilerplate_buffer = g_string_new (""); + context->source_stack = NULL; + + context->legacy_state_set = 0; + + context->default_gl_texture_2d_tex = NULL; + context->default_gl_texture_3d_tex = NULL; + context->default_gl_texture_rect_tex = NULL; + + context->framebuffers = NULL; + context->current_draw_buffer = NULL; + context->current_read_buffer = NULL; + context->current_draw_buffer_state_flushed = 0; + context->current_draw_buffer_changes = COGL_FRAMEBUFFER_STATE_ALL; + + context->swap_callback_closures = + g_hash_table_new (g_direct_hash, g_direct_equal); + + _cogl_list_init (&context->onscreen_events_queue); + _cogl_list_init (&context->onscreen_dirty_queue); + + g_queue_init (&context->gles2_context_stack); + + context->journal_flush_attributes_array = + g_array_new (TRUE, FALSE, sizeof (CoglAttribute *)); + context->journal_clip_bounds = NULL; + + context->polygon_vertices = g_array_new (FALSE, FALSE, sizeof (float)); + + context->current_pipeline = NULL; + context->current_pipeline_changes_since_flush = 0; + context->current_pipeline_with_color_attrib = FALSE; + + _cogl_bitmask_init (&context->enabled_builtin_attributes); + _cogl_bitmask_init (&context->enable_builtin_attributes_tmp); + _cogl_bitmask_init (&context->enabled_texcoord_attributes); + _cogl_bitmask_init (&context->enable_texcoord_attributes_tmp); + _cogl_bitmask_init (&context->enabled_custom_attributes); + _cogl_bitmask_init (&context->enable_custom_attributes_tmp); + _cogl_bitmask_init (&context->changed_bits_tmp); + + context->max_texture_units = -1; + context->max_activateable_texture_units = -1; + + context->current_fragment_program_type = COGL_PIPELINE_PROGRAM_TYPE_FIXED; + context->current_vertex_program_type = COGL_PIPELINE_PROGRAM_TYPE_FIXED; + context->current_gl_program = 0; + + context->current_gl_dither_enabled = TRUE; + context->current_gl_color_mask = COGL_COLOR_MASK_ALL; + + context->gl_blend_enable_cache = FALSE; + + context->depth_test_enabled_cache = FALSE; + context->depth_test_function_cache = COGL_DEPTH_TEST_FUNCTION_LESS; + context->depth_writing_enabled_cache = TRUE; + context->depth_range_near_cache = 0; + context->depth_range_far_cache = 1; + + context->legacy_depth_test_enabled = FALSE; + + context->pipeline_cache = _cogl_pipeline_cache_new (); + + for (i = 0; i < COGL_BUFFER_BIND_TARGET_COUNT; i++) + context->current_buffer[i] = NULL; + + context->window_buffer = NULL; + context->framebuffer_stack = _cogl_create_framebuffer_stack (); + + /* XXX: In this case the Clutter backend is still responsible for + * the OpenGL binding API and for creating onscreen framebuffers and + * so we have to add a dummy framebuffer to represent the backend + * owned window... */ + if (_cogl_context_get_winsys (context) == _cogl_winsys_stub_get_vtable ()) + { + CoglOnscreen *window = _cogl_onscreen_new (); + cogl_set_framebuffer (COGL_FRAMEBUFFER (window)); + cogl_object_unref (COGL_FRAMEBUFFER (window)); + } + + context->current_path = NULL; + context->stencil_pipeline = cogl_pipeline_new (context); + + context->in_begin_gl_block = FALSE; + + context->quad_buffer_indices_byte = NULL; + context->quad_buffer_indices = NULL; + context->quad_buffer_indices_len = 0; + + context->rectangle_byte_indices = NULL; + context->rectangle_short_indices = NULL; + context->rectangle_short_indices_len = 0; + + context->texture_download_pipeline = NULL; + context->blit_texture_pipeline = NULL; + +#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) + if (_cogl_has_private_feature (context, COGL_PRIVATE_FEATURE_ALPHA_TEST)) + /* The default for GL_ALPHA_TEST is to always pass which is equivalent to + * the test being disabled therefore we assume that for all drivers there + * will be no performance impact if we always leave the test enabled which + * makes things a bit simpler for us. Under GLES2 the alpha test is + * implemented in the fragment shader so there is no enable for it + */ + GE (context, glEnable (GL_ALPHA_TEST)); +#endif + +#if defined (HAVE_COGL_GL) + if ((context->driver == COGL_DRIVER_GL3)) + { + GLuint vertex_array; + + /* In a forward compatible context, GL 3 doesn't support rendering + * using the default vertex array object. Cogl doesn't use vertex + * array objects yet so for now we just create a dummy array + * object that we will use as our own default object. Eventually + * it could be good to attach the vertex array objects to + * CoglPrimitives */ + context->glGenVertexArrays (1, &vertex_array); + context->glBindVertexArray (vertex_array); + } +#endif + + context->current_modelview_entry = NULL; + context->current_projection_entry = NULL; + _cogl_matrix_entry_identity_init (&context->identity_entry); + _cogl_matrix_entry_cache_init (&context->builtin_flushed_projection); + _cogl_matrix_entry_cache_init (&context->builtin_flushed_modelview); + + /* Create default textures used for fall backs */ + context->default_gl_texture_2d_tex = + cogl_texture_2d_new_from_data (context, + 1, 1, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + 0, /* rowstride */ + white_pixel, + NULL); /* abort on error */ + + /* If 3D or rectangle textures aren't supported then these will + * return errors that we can simply ignore. */ + internal_error = NULL; + context->default_gl_texture_3d_tex = + cogl_texture_3d_new_from_data (context, + 1, 1, 1, /* width, height, depth */ + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + 0, /* rowstride */ + 0, /* image stride */ + white_pixel, + &internal_error); + if (internal_error) + cogl_error_free (internal_error); + + /* TODO: add cogl_texture_rectangle_new_from_data() */ + white_pixel_bitmap = + cogl_bitmap_new_for_data (context, + 1, 1, /* width/height */ + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + 4, /* rowstride */ + white_pixel); + + internal_error = NULL; + context->default_gl_texture_rect_tex = + cogl_texture_rectangle_new_from_bitmap (white_pixel_bitmap); + + /* XXX: we need to allocate the texture now because the white_pixel + * data is on the stack */ + cogl_texture_allocate (COGL_TEXTURE (context->default_gl_texture_rect_tex), + &internal_error); + if (internal_error) + cogl_error_free (internal_error); + + cogl_object_unref (white_pixel_bitmap); + + cogl_push_source (context->opaque_color_pipeline); + + context->atlases = NULL; + g_hook_list_init (&context->atlas_reorganize_callbacks, sizeof (GHook)); + + context->buffer_map_fallback_array = g_byte_array_new (); + context->buffer_map_fallback_in_use = FALSE; + + /* As far as I can tell, GL_POINT_SPRITE doesn't have any effect + unless GL_COORD_REPLACE is enabled for an individual layer. + Therefore it seems like it should be ok to just leave it enabled + all the time instead of having to have a set property on each + pipeline to track whether any layers have point sprite coords + enabled. We don't need to do this for GL3 or GLES2 because point + sprites are handled using a builtin varying in the shader. */ + if (_cogl_has_private_feature (context, COGL_PRIVATE_FEATURE_GL_FIXED) && + cogl_has_feature (context, COGL_FEATURE_ID_POINT_SPRITE)) + GE (context, glEnable (GL_POINT_SPRITE)); + + _cogl_list_init (&context->fences); + + return context; +} + +static void +_cogl_context_free (CoglContext *context) +{ + const CoglWinsysVtable *winsys = _cogl_context_get_winsys (context); + + winsys->context_deinit (context); + + _cogl_free_framebuffer_stack (context->framebuffer_stack); + + if (context->current_path) + cogl_handle_unref (context->current_path); + + if (context->default_gl_texture_2d_tex) + cogl_object_unref (context->default_gl_texture_2d_tex); + if (context->default_gl_texture_3d_tex) + cogl_object_unref (context->default_gl_texture_3d_tex); + if (context->default_gl_texture_rect_tex) + cogl_object_unref (context->default_gl_texture_rect_tex); + + if (context->opaque_color_pipeline) + cogl_object_unref (context->opaque_color_pipeline); + if (context->blended_color_pipeline) + cogl_object_unref (context->blended_color_pipeline); + if (context->texture_pipeline) + cogl_object_unref (context->texture_pipeline); + + if (context->blit_texture_pipeline) + cogl_object_unref (context->blit_texture_pipeline); + + if (context->swap_callback_closures) + g_hash_table_destroy (context->swap_callback_closures); + + g_warn_if_fail (context->gles2_context_stack.length == 0); + + if (context->journal_flush_attributes_array) + g_array_free (context->journal_flush_attributes_array, TRUE); + if (context->journal_clip_bounds) + g_array_free (context->journal_clip_bounds, TRUE); + + if (context->polygon_vertices) + g_array_free (context->polygon_vertices, TRUE); + + if (context->quad_buffer_indices_byte) + cogl_object_unref (context->quad_buffer_indices_byte); + if (context->quad_buffer_indices) + cogl_object_unref (context->quad_buffer_indices); + + if (context->rectangle_byte_indices) + cogl_object_unref (context->rectangle_byte_indices); + if (context->rectangle_short_indices) + cogl_object_unref (context->rectangle_short_indices); + + if (context->default_pipeline) + cogl_object_unref (context->default_pipeline); + + if (context->dummy_layer_dependant) + cogl_object_unref (context->dummy_layer_dependant); + if (context->default_layer_n) + cogl_object_unref (context->default_layer_n); + if (context->default_layer_0) + cogl_object_unref (context->default_layer_0); + + if (context->current_clip_stack_valid) + _cogl_clip_stack_unref (context->current_clip_stack); + + g_slist_free (context->atlases); + g_hook_list_clear (&context->atlas_reorganize_callbacks); + + _cogl_bitmask_destroy (&context->enabled_builtin_attributes); + _cogl_bitmask_destroy (&context->enable_builtin_attributes_tmp); + _cogl_bitmask_destroy (&context->enabled_texcoord_attributes); + _cogl_bitmask_destroy (&context->enable_texcoord_attributes_tmp); + _cogl_bitmask_destroy (&context->enabled_custom_attributes); + _cogl_bitmask_destroy (&context->enable_custom_attributes_tmp); + _cogl_bitmask_destroy (&context->changed_bits_tmp); + + if (context->current_modelview_entry) + cogl_matrix_entry_unref (context->current_modelview_entry); + if (context->current_projection_entry) + cogl_matrix_entry_unref (context->current_projection_entry); + _cogl_matrix_entry_cache_destroy (&context->builtin_flushed_projection); + _cogl_matrix_entry_cache_destroy (&context->builtin_flushed_modelview); + + _cogl_pipeline_cache_free (context->pipeline_cache); + + _cogl_sampler_cache_free (context->sampler_cache); + + _cogl_destroy_texture_units (); + + g_ptr_array_free (context->uniform_names, TRUE); + g_hash_table_destroy (context->uniform_name_hash); + + g_hash_table_destroy (context->attribute_name_states_hash); + g_array_free (context->attribute_name_index_map, TRUE); + + g_byte_array_free (context->buffer_map_fallback_array, TRUE); + + cogl_object_unref (context->display); + + g_free (context); +} + +CoglContext * +_cogl_context_get_default (void) +{ + CoglError *error = NULL; + /* Create if doesn't exist yet */ + if (_cogl_context == NULL) + { + _cogl_context = cogl_context_new (NULL, &error); + if (!_cogl_context) + { + g_warning ("Failed to create default context: %s", + error->message); + cogl_error_free (error); + } + } + + return _cogl_context; +} + +CoglDisplay * +cogl_context_get_display (CoglContext *context) +{ + return context->display; +} + +CoglRenderer * +cogl_context_get_renderer (CoglContext *context) +{ + return context->display->renderer; +} + +CoglBool +_cogl_context_update_features (CoglContext *context, + CoglError **error) +{ + return context->driver_vtable->update_features (context, error); +} + +void +_cogl_context_set_current_projection_entry (CoglContext *context, + CoglMatrixEntry *entry) +{ + cogl_matrix_entry_ref (entry); + if (context->current_projection_entry) + cogl_matrix_entry_unref (context->current_projection_entry); + context->current_projection_entry = entry; +} + +void +_cogl_context_set_current_modelview_entry (CoglContext *context, + CoglMatrixEntry *entry) +{ + cogl_matrix_entry_ref (entry); + if (context->current_modelview_entry) + cogl_matrix_entry_unref (context->current_modelview_entry); + context->current_modelview_entry = entry; +} + +char ** +_cogl_context_get_gl_extensions (CoglContext *context) +{ + const char *env_disabled_extensions; + char **ret; + + /* In GL 3, querying GL_EXTENSIONS is deprecated so we have to build + * the array using glGetStringi instead */ +#ifdef HAVE_COGL_GL + if (context->driver == COGL_DRIVER_GL3) + { + int num_extensions, i; + + context->glGetIntegerv (GL_NUM_EXTENSIONS, &num_extensions); + + ret = g_malloc (sizeof (char *) * (num_extensions + 1)); + + for (i = 0; i < num_extensions; i++) + { + const char *ext = + (const char *) context->glGetStringi (GL_EXTENSIONS, i); + ret[i] = g_strdup (ext); + } + + ret[num_extensions] = NULL; + } + else +#endif + { + const char *all_extensions = + (const char *) context->glGetString (GL_EXTENSIONS); + + ret = g_strsplit (all_extensions, " ", 0 /* max tokens */); + } + + if ((env_disabled_extensions = g_getenv ("COGL_DISABLE_GL_EXTENSIONS")) + || _cogl_config_disable_gl_extensions) + { + char **split_env_disabled_extensions; + char **split_conf_disabled_extensions; + char **src, **dst; + + if (env_disabled_extensions) + split_env_disabled_extensions = + g_strsplit (env_disabled_extensions, + ",", + 0 /* no max tokens */); + else + split_env_disabled_extensions = NULL; + + if (_cogl_config_disable_gl_extensions) + split_conf_disabled_extensions = + g_strsplit (_cogl_config_disable_gl_extensions, + ",", + 0 /* no max tokens */); + else + split_conf_disabled_extensions = NULL; + + for (dst = ret, src = ret; + *src; + src++) + { + char **d; + + if (split_env_disabled_extensions) + for (d = split_env_disabled_extensions; *d; d++) + if (!strcmp (*src, *d)) + goto disabled; + if (split_conf_disabled_extensions) + for (d = split_conf_disabled_extensions; *d; d++) + if (!strcmp (*src, *d)) + goto disabled; + + *(dst++) = *src; + continue; + + disabled: + g_free (*src); + continue; + } + + *dst = NULL; + + if (split_env_disabled_extensions) + g_strfreev (split_env_disabled_extensions); + if (split_conf_disabled_extensions) + g_strfreev (split_conf_disabled_extensions); + } + + return ret; +} + +const char * +_cogl_context_get_gl_version (CoglContext *context) +{ + const char *version_override; + + if ((version_override = g_getenv ("COGL_OVERRIDE_GL_VERSION"))) + return version_override; + else if (_cogl_config_override_gl_version) + return _cogl_config_override_gl_version; + else + return (const char *) context->glGetString (GL_VERSION); + +} + +int64_t +cogl_get_clock_time (CoglContext *context) +{ + const CoglWinsysVtable *winsys = _cogl_context_get_winsys (context); + + if (winsys->context_get_clock_time) + return winsys->context_get_clock_time (context); + else + return 0; +} + +CoglGraphicsResetStatus +cogl_get_graphics_reset_status (CoglContext *context) +{ + if (!context->glGetGraphicsResetStatus) + return COGL_GRAPHICS_RESET_STATUS_NO_ERROR; + + switch (context->glGetGraphicsResetStatus ()) + { + case GL_GUILTY_CONTEXT_RESET_ARB: + return COGL_GRAPHICS_RESET_STATUS_GUILTY_CONTEXT_RESET; + + case GL_INNOCENT_CONTEXT_RESET_ARB: + return COGL_GRAPHICS_RESET_STATUS_INNOCENT_CONTEXT_RESET; + + case GL_UNKNOWN_CONTEXT_RESET_ARB: + return COGL_GRAPHICS_RESET_STATUS_UNKNOWN_CONTEXT_RESET; + + case GL_PURGED_CONTEXT_RESET_NV: + return COGL_GRAPHICS_RESET_STATUS_PURGED_CONTEXT_RESET; + + default: + return COGL_GRAPHICS_RESET_STATUS_NO_ERROR; + } +} diff --git a/cogl/cogl/cogl-context.h b/cogl/cogl/cogl-context.h new file mode 100644 index 0000000..978c3fc --- /dev/null +++ b/cogl/cogl/cogl-context.h @@ -0,0 +1,411 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Robert Bragg + * + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_CONTEXT_H__ +#define __COGL_CONTEXT_H__ + +/* We forward declare the CoglContext type here to avoid some circular + * dependency issues with the following headers. + */ +typedef struct _CoglContext CoglContext; + +#include +#include +#include + +#include + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-context + * @short_description: The top level application context. + * + * A #CoglContext is the top most sandbox of Cogl state for an + * application or toolkit. Its main purpose is to act as a sandbox + * for the memory management of state objects. Normally an application + * will only create a single context since there is no way to share + * resources between contexts. + * + * For those familiar with OpenGL or perhaps Cairo it should be + * understood that unlike these APIs a Cogl context isn't a rendering + * context as such. In other words Cogl doesn't aim to provide a state + * machine style model for configuring rendering parameters. Most + * rendering state in Cogl is directly associated with user managed + * objects called pipelines and geometry is drawn with a specific + * pipeline object to a framebuffer object and those 3 things fully + * define the state for drawing. This is an important part of Cogl's + * design since it helps you write orthogonal rendering components + * that can all access the same GPU without having to worry about + * what state other components have left you with. + * + * Cogl does not maintain internal references to the context for + * resources that depend on the context so applications. This is to + * help applications control the lifetime a context without us needing to + * introduce special api to handle the breakup of internal circular + * references due to internal resources and caches associated with the + * context. + * + * One a context has been destroyed then all directly or indirectly + * dependant resources will be in an inconsistent state and should not + * be manipulated or queried in any way. + * + * For applications that rely on the operating system to clean up + * resources this policy shouldn't affect them, but for applications + * that need to carefully destroy and re-create Cogl contexts multiple + * times throughout their lifetime (such as Android applications) they + * should be careful to destroy all context dependant resources, such as + * framebuffers or textures etc before unrefing and destroying the + * context. + */ + +#define COGL_CONTEXT(OBJECT) ((CoglContext *)OBJECT) + +/** + * cogl_context_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_context_get_gtype (void); + +/** + * cogl_context_new: (constructor) + * @display: (allow-none): A #CoglDisplay pointer + * @error: A CoglError return location. + * + * Creates a new #CoglContext which acts as an application sandbox + * for any state objects that are allocated. + * + * Return value: (transfer full): A newly allocated #CoglContext + * Since: 1.8 + * Stability: unstable + */ +CoglContext * +cogl_context_new (CoglDisplay *display, + CoglError **error); + +/** + * cogl_context_get_display: + * @context: A #CoglContext pointer + * + * Retrieves the #CoglDisplay that is internally associated with the + * given @context. This will return the same #CoglDisplay that was + * passed to cogl_context_new() or if %NULL was passed to + * cogl_context_new() then this function returns a pointer to the + * display that was automatically setup internally. + * + * Return value: (transfer none): The #CoglDisplay associated with the + * given @context. + * Since: 1.8 + * Stability: unstable + */ +CoglDisplay * +cogl_context_get_display (CoglContext *context); + +/** + * cogl_context_get_renderer: + * @context: A #CoglContext pointer + * + * Retrieves the #CoglRenderer that is internally associated with the + * given @context. This will return the same #CoglRenderer that was + * passed to cogl_display_new() or if %NULL was passed to + * cogl_display_new() or cogl_context_new() then this function returns + * a pointer to the renderer that was automatically connected + * internally. + * + * Return value: (transfer none): The #CoglRenderer associated with the + * given @context. + * Since: 1.16 + * Stability: unstable + */ +CoglRenderer * +cogl_context_get_renderer (CoglContext *context); + +/** + * cogl_is_context: + * @object: An object or %NULL + * + * Gets whether the given object references an existing context object. + * + * Return value: %TRUE if the @object references a #CoglContext, + * %FALSE otherwise + * + * Since: 1.10 + * Stability: Unstable + */ +CoglBool +cogl_is_context (void *object); + +/* XXX: not guarded by the EXPERIMENTAL_API defines to avoid + * upsetting glib-mkenums, but this can still be considered implicitly + * experimental since it's only useable with experimental API... */ +/** + * CoglFeatureID: + * @COGL_FEATURE_ID_TEXTURE_NPOT_BASIC: The hardware supports non power + * of two textures, but you also need to check the + * %COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP and %COGL_FEATURE_ID_TEXTURE_NPOT_REPEAT + * features to know if the hardware supports npot texture mipmaps + * or repeat modes other than + * %COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE respectively. + * @COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP: Mipmapping is supported in + * conjuntion with non power of two textures. + * @COGL_FEATURE_ID_TEXTURE_NPOT_REPEAT: Repeat modes other than + * %COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE are supported by the + * hardware. + * @COGL_FEATURE_ID_TEXTURE_NPOT: Non power of two textures are supported + * by the hardware. This is a equivalent to the + * %COGL_FEATURE_ID_TEXTURE_NPOT_BASIC, %COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP + * and %COGL_FEATURE_ID_TEXTURE_NPOT_REPEAT features combined. + * @COGL_FEATURE_ID_TEXTURE_RECTANGLE: Support for rectangular + * textures with non-normalized texture coordinates. + * @COGL_FEATURE_ID_TEXTURE_RG: Support for + * %COGL_TEXTURE_COMPONENTS_RG as the internal components of a + * texture. + * @COGL_FEATURE_ID_TEXTURE_3D: 3D texture support + * @COGL_FEATURE_ID_OFFSCREEN: Offscreen rendering support + * @COGL_FEATURE_ID_OFFSCREEN_MULTISAMPLE: Multisample support for + * offscreen framebuffers + * @COGL_FEATURE_ID_ONSCREEN_MULTIPLE: Multiple onscreen framebuffers + * supported. + * @COGL_FEATURE_ID_GLSL: GLSL support + * @COGL_FEATURE_ID_ARBFP: ARBFP support + * @COGL_FEATURE_ID_UNSIGNED_INT_INDICES: Set if + * %COGL_INDICES_TYPE_UNSIGNED_INT is supported in + * cogl_indices_new(). + * @COGL_FEATURE_ID_DEPTH_RANGE: cogl_pipeline_set_depth_range() support + * @COGL_FEATURE_ID_POINT_SPRITE: Whether + * cogl_pipeline_set_layer_point_sprite_coords_enabled() is supported. + * @COGL_FEATURE_ID_PER_VERTEX_POINT_SIZE: Whether cogl_point_size_in + * can be used as an attribute to set a per-vertex point size. + * @COGL_FEATURE_ID_MAP_BUFFER_FOR_READ: Whether cogl_buffer_map() is + * supported with CoglBufferAccess including read support. + * @COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE: Whether cogl_buffer_map() is + * supported with CoglBufferAccess including write support. + * @COGL_FEATURE_ID_MIRRORED_REPEAT: Whether + * %COGL_PIPELINE_WRAP_MODE_MIRRORED_REPEAT is supported. + * @COGL_FEATURE_ID_SWAP_BUFFERS_EVENT: + * Available if the window system supports reporting an event + * for swap buffer completions. + * @COGL_FEATURE_ID_BUFFER_AGE: Available if the age of #CoglOnscreen back + * buffers are tracked and so cogl_onscreen_get_buffer_age() can be + * expected to return age values other than 0. + * @COGL_FEATURE_ID_GLES2_CONTEXT: Whether creating new GLES2 contexts is + * suported. + * @COGL_FEATURE_ID_DEPTH_TEXTURE: Whether #CoglFramebuffer support rendering + * the depth buffer to a texture. + * @COGL_FEATURE_ID_PRESENTATION_TIME: Whether frame presentation + * time stamps will be recorded in #CoglFrameInfo objects. + * + * All the capabilities that can vary between different GPUs supported + * by Cogl. Applications that depend on any of these features should explicitly + * check for them using cogl_has_feature() or cogl_has_features(). + * + * Since: 1.10 + */ +typedef enum _CoglFeatureID +{ + COGL_FEATURE_ID_TEXTURE_NPOT_BASIC = 1, + COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP, + COGL_FEATURE_ID_TEXTURE_NPOT_REPEAT, + COGL_FEATURE_ID_TEXTURE_NPOT, + COGL_FEATURE_ID_TEXTURE_RECTANGLE, + COGL_FEATURE_ID_TEXTURE_3D, + COGL_FEATURE_ID_GLSL, + COGL_FEATURE_ID_ARBFP, + COGL_FEATURE_ID_OFFSCREEN, + COGL_FEATURE_ID_OFFSCREEN_MULTISAMPLE, + COGL_FEATURE_ID_ONSCREEN_MULTIPLE, + COGL_FEATURE_ID_UNSIGNED_INT_INDICES, + COGL_FEATURE_ID_DEPTH_RANGE, + COGL_FEATURE_ID_POINT_SPRITE, + COGL_FEATURE_ID_MAP_BUFFER_FOR_READ, + COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE, + COGL_FEATURE_ID_MIRRORED_REPEAT, + COGL_FEATURE_ID_SWAP_BUFFERS_EVENT, + COGL_FEATURE_ID_GLES2_CONTEXT, + COGL_FEATURE_ID_DEPTH_TEXTURE, + COGL_FEATURE_ID_PRESENTATION_TIME, + COGL_FEATURE_ID_FENCE, + COGL_FEATURE_ID_PER_VERTEX_POINT_SIZE, + COGL_FEATURE_ID_TEXTURE_RG, + COGL_FEATURE_ID_BUFFER_AGE, + + /*< private >*/ + _COGL_N_FEATURE_IDS /*< skip >*/ +} CoglFeatureID; + + +/** + * cogl_has_feature: + * @context: A #CoglContext pointer + * @feature: A #CoglFeatureID + * + * Checks if a given @feature is currently available + * + * Cogl does not aim to be a lowest common denominator API, it aims to + * expose all the interesting features of GPUs to application which + * means applications have some responsibility to explicitly check + * that certain features are available before depending on them. + * + * Returns: %TRUE if the @feature is currently supported or %FALSE if + * not. + * + * Since: 1.10 + * Stability: unstable + */ +CoglBool +cogl_has_feature (CoglContext *context, CoglFeatureID feature); + +/** + * cogl_has_features: + * @context: A #CoglContext pointer + * @...: A 0 terminated list of CoglFeatureIDs + * + * Checks if a list of features are all currently available. + * + * This checks all of the listed features using cogl_has_feature() and + * returns %TRUE if all the features are available or %FALSE + * otherwise. + * + * Return value: %TRUE if all the features are available, %FALSE + * otherwise. + * + * Since: 1.10 + * Stability: unstable + */ +CoglBool +cogl_has_features (CoglContext *context, ...); + +/** + * CoglFeatureCallback: + * @feature: A single feature currently supported by Cogl + * @user_data: A private pointer passed to cogl_foreach_feature(). + * + * A callback used with cogl_foreach_feature() for enumerating all + * context level features supported by Cogl. + * + * Since: 0.10 + * Stability: unstable + */ +typedef void (*CoglFeatureCallback) (CoglFeatureID feature, void *user_data); + +/** + * cogl_foreach_feature: + * @context: A #CoglContext pointer + * @callback: (scope call): A #CoglFeatureCallback called for each + * supported feature + * @user_data: (closure): Private data to pass to the callback + * + * Iterates through all the context level features currently supported + * for a given @context and for each feature @callback is called. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_foreach_feature (CoglContext *context, + CoglFeatureCallback callback, + void *user_data); + +/** + * cogl_get_clock_time: + * @context: a #CoglContext pointer + * + * Returns the current time value from Cogl's internal clock. This + * clock is used for measuring times such as the presentation time + * in a #CoglFrameInfo. + * + * This method is meant for converting timestamps retrieved from Cogl + * to other time systems, and is not meant to be used as a standalone + * timing system. For that reason, if this function is called without + * having retrieved a valid (non-zero) timestamp from Cogl first, it + * may return 0 to indicate that Cogl has no active internal clock. + * + * Return value: the time value for the Cogl clock, in nanoseconds + * from an arbitrary point in time, or 0 if Cogl doesn't have an + * active internal clock. + * Since: 1.14 + * Stability: unstable + */ +int64_t +cogl_get_clock_time (CoglContext *context); + +/** + * CoglGraphicsResetStatus: + * @COGL_GRAPHICS_RESET_STATUS_NO_ERROR: + * @COGL_GRAPHICS_RESET_STATUS_GUILTY_CONTEXT_RESET: + * @COGL_GRAPHICS_RESET_STATUS_INNOCENT_CONTEXT_RESET: + * @COGL_GRAPHICS_RESET_STATUS_UNKNOWN_CONTEXT_RESET: + * @COGL_GRAPHICS_RESET_STATUS_PURGED_CONTEXT_RESET: + * + * All the error values that might be returned by + * cogl_get_graphics_reset_status(). Each value's meaning corresponds + * to the similarly named value defined in the ARB_robustness and + * NV_robustness_video_memory_purge extensions. + */ +typedef enum _CoglGraphicsResetStatus +{ + COGL_GRAPHICS_RESET_STATUS_NO_ERROR, + COGL_GRAPHICS_RESET_STATUS_GUILTY_CONTEXT_RESET, + COGL_GRAPHICS_RESET_STATUS_INNOCENT_CONTEXT_RESET, + COGL_GRAPHICS_RESET_STATUS_UNKNOWN_CONTEXT_RESET, + COGL_GRAPHICS_RESET_STATUS_PURGED_CONTEXT_RESET, +} CoglGraphicsResetStatus; + +/** + * cogl_get_graphics_reset_status: + * @context: a #CoglContext pointer + * + * Returns the graphics reset status as reported by + * GetGraphicsResetStatusARB defined in the ARB_robustness extension. + * + * Note that Cogl doesn't normally enable the ARB_robustness + * extension in which case this will only ever return + * #COGL_GRAPHICS_RESET_STATUS_NO_ERROR. + * + * Applications must explicitly use a backend specific method to + * request that errors get reported such as X11's + * cogl_xlib_renderer_request_reset_on_video_memory_purge(). + * + * Return value: a #CoglGraphicsResetStatus + */ +CoglGraphicsResetStatus +cogl_get_graphics_reset_status (CoglContext *context); + +COGL_END_DECLS + +#endif /* __COGL_CONTEXT_H__ */ + diff --git a/cogl/cogl/cogl-debug-options.h b/cogl/cogl/cogl-debug-options.h new file mode 100644 index 0000000..0f3b307 --- /dev/null +++ b/cogl/cogl/cogl-debug-options.h @@ -0,0 +1,199 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +OPT (OBJECT, + N_("Cogl Tracing"), + "ref-counts", + N_("CoglObject references"), + N_("Debug ref counting issues for CoglObjects")) +OPT (SLICING, + N_("Cogl Tracing"), + "slicing", + N_("Trace Texture Slicing"), + N_("debug the creation of texture slices")) +OPT (ATLAS, + N_("Cogl Tracing"), + "atlas", + N_("Trace Atlas Textures"), + N_("Debug texture atlas management")) +OPT (BLEND_STRINGS, + N_("Cogl Tracing"), + "blend-strings", + N_("Trace Blend Strings"), + N_("Debug CoglBlendString parsing")) +OPT (JOURNAL, + N_("Cogl Tracing"), + "journal", + N_("Trace Journal"), + N_("View all the geometry passing through the journal")) +OPT (BATCHING, + N_("Cogl Tracing"), + "batching", + N_("Trace Batching"), + N_("Show how geometry is being batched in the journal")) +OPT (MATRICES, + N_("Cogl Tracing"), + "matrices", + N_("Trace matrices"), + N_("Trace all matrix manipulation")) +/* XXX we should replace the "draw" option its very hand wavy... */ +OPT (DRAW, + N_("Cogl Tracing"), + "draw", + N_("Trace Misc Drawing"), + N_("Trace some misc drawing operations")) +OPT (PANGO, + N_("Cogl Tracing"), + "pango", + N_("Trace Pango Renderer"), + N_("Trace the Cogl Pango renderer")) +OPT (TEXTURE_PIXMAP, + N_("Cogl Tracing"), + "texture-pixmap", + N_("Trace CoglTexturePixmap backend"), + N_("Trace the Cogl texture pixmap backend")) +OPT (RECTANGLES, + N_("Visualize"), + "rectangles", + N_("Outline rectangles"), + N_("Add wire outlines for all rectangular geometry")) +OPT (WIREFRAME, + N_("Visualize"), + "wireframe", + N_("Show wireframes"), + N_("Add wire outlines for all geometry")) +OPT (DISABLE_BATCHING, + N_("Root Cause"), + "disable-batching", + N_("Disable Journal batching"), + N_("Disable batching of geometry in the Cogl Journal.")) +OPT (DISABLE_VBOS, + N_("Root Cause"), + "disable-vbos", + N_("Disable GL Vertex Buffers"), + N_("Disable use of OpenGL vertex buffer objects")) +OPT (DISABLE_PBOS, + N_("Root Cause"), + "disable-pbos", + N_("Disable GL Pixel Buffers"), + N_("Disable use of OpenGL pixel buffer objects")) +OPT (DISABLE_SOFTWARE_TRANSFORM, + N_("Root Cause"), + "disable-software-transform", + N_("Disable software rect transform"), + N_("Use the GPU to transform rectangular geometry")) +OPT (DUMP_ATLAS_IMAGE, + N_("Cogl Specialist"), + "dump-atlas-image", + N_("Dump atlas images"), + N_("Dump texture atlas changes to an image file")) +OPT (DISABLE_ATLAS, + N_("Root Cause"), + "disable-atlas", + N_("Disable texture atlasing"), + N_("Disable use of texture atlasing")) +OPT (DISABLE_SHARED_ATLAS, + N_("Root Cause"), + "disable-shared-atlas", + N_("Disable sharing the texture atlas between text and images"), + N_("When this is set the glyph cache will always use a separate texture " + "for its atlas. Otherwise it will try to share the atlas with images.")) +OPT (DISABLE_TEXTURING, + N_("Root Cause"), + "disable-texturing", + N_("Disable texturing"), + N_("Disable texturing any primitives")) +OPT (DISABLE_ARBFP, + N_("Root Cause"), + "disable-arbfp", + N_("Disable arbfp"), + N_("Disable use of ARB fragment programs")) +OPT (DISABLE_FIXED, + N_("Root Cause"), + "disable-fixed", + N_("Disable fixed"), + N_("Disable use of the fixed function pipeline backend")) +OPT (DISABLE_GLSL, + N_("Root Cause"), + "disable-glsl", + N_("Disable GLSL"), + N_("Disable use of GLSL")) +OPT (DISABLE_BLENDING, + N_("Root Cause"), + "disable-blending", + N_("Disable blending"), + N_("Disable use of blending")) +OPT (DISABLE_NPOT_TEXTURES, + N_("Root Cause"), + "disable-npot-textures", + N_("Disable non-power-of-two textures"), + N_("Makes Cogl think that the GL driver doesn't support NPOT textures " + "so that it will create sliced textures or textures with waste instead.")) +OPT (DISABLE_SOFTWARE_CLIP, + N_("Root Cause"), + "disable-software-clip", + N_("Disable software clipping"), + N_("Disables Cogl's attempts to clip some rectangles in software.")) +OPT (SHOW_SOURCE, + N_("Cogl Tracing"), + "show-source", + N_("Show source"), + N_("Show generated ARBfp/GLSL source code")) +OPT (OPENGL, + N_("Cogl Tracing"), + "opengl", + N_("Trace some OpenGL"), + N_("Traces some select OpenGL calls")) +OPT (OFFSCREEN, + N_("Cogl Tracing"), + "offscreen", + N_("Trace offscreen support"), + N_("Debug offscreen support")) +OPT (DISABLE_BLENDING, + N_("Root Cause"), + "disable-program-caches", + N_("Disable program caches"), + N_("Disable fallback caches for arbfp and glsl programs")) +OPT (DISABLE_FAST_READ_PIXEL, + N_("Root Cause"), + "disable-fast-read-pixel", + N_("Disable read pixel optimization"), + N_("Disable optimization for reading 1px for simple " + "scenes of opaque rectangles")) +OPT (CLIPPING, + N_("Cogl Tracing"), + "clipping", + N_("Trace clipping"), + N_("Logs information about how Cogl is implementing clipping")) +OPT (PERFORMANCE, + N_("Cogl Tracing"), + "performance", + N_("Trace performance concerns"), + N_("Tries to highlight sub-optimal Cogl usage.")) diff --git a/cogl/cogl/cogl-debug.c b/cogl/cogl/cogl-debug.c new file mode 100644 index 0000000..1ef2fd0 --- /dev/null +++ b/cogl/cogl/cogl-debug.c @@ -0,0 +1,302 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include + +#include "cogl-i18n-private.h" +#include "cogl-private.h" +#include "cogl-debug.h" +#include "cogl1-context.h" + +/* XXX: If you add a debug option, please also add an option + * definition to cogl-debug-options.h. This will enable us - for + * example - to emit a "help" description for the option. + */ + +/* NB: Only these options get enabled if COGL_DEBUG=all is + * used since they don't affect the behaviour of Cogl they + * simply print out verbose information */ +static const GDebugKey cogl_log_debug_keys[] = { + { "object", COGL_DEBUG_OBJECT }, + { "slicing", COGL_DEBUG_SLICING }, + { "atlas", COGL_DEBUG_ATLAS }, + { "blend-strings", COGL_DEBUG_BLEND_STRINGS }, + { "journal", COGL_DEBUG_JOURNAL }, + { "batching", COGL_DEBUG_BATCHING }, + { "matrices", COGL_DEBUG_MATRICES }, + { "draw", COGL_DEBUG_DRAW }, + { "opengl", COGL_DEBUG_OPENGL }, + { "pango", COGL_DEBUG_PANGO }, + { "show-source", COGL_DEBUG_SHOW_SOURCE}, + { "offscreen", COGL_DEBUG_OFFSCREEN }, + { "texture-pixmap", COGL_DEBUG_TEXTURE_PIXMAP }, + { "bitmap", COGL_DEBUG_BITMAP }, + { "clipping", COGL_DEBUG_CLIPPING }, + { "winsys", COGL_DEBUG_WINSYS }, + { "performance", COGL_DEBUG_PERFORMANCE } +}; +static const int n_cogl_log_debug_keys = + G_N_ELEMENTS (cogl_log_debug_keys); + +static const GDebugKey cogl_behavioural_debug_keys[] = { + { "rectangles", COGL_DEBUG_RECTANGLES }, + { "disable-batching", COGL_DEBUG_DISABLE_BATCHING }, + { "disable-vbos", COGL_DEBUG_DISABLE_VBOS }, + { "disable-pbos", COGL_DEBUG_DISABLE_PBOS }, + { "disable-software-transform", COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM }, + { "dump-atlas-image", COGL_DEBUG_DUMP_ATLAS_IMAGE }, + { "disable-atlas", COGL_DEBUG_DISABLE_ATLAS }, + { "disable-shared-atlas", COGL_DEBUG_DISABLE_SHARED_ATLAS }, + { "disable-texturing", COGL_DEBUG_DISABLE_TEXTURING}, + { "disable-arbfp", COGL_DEBUG_DISABLE_ARBFP}, + { "disable-fixed", COGL_DEBUG_DISABLE_FIXED}, + { "disable-glsl", COGL_DEBUG_DISABLE_GLSL}, + { "disable-blending", COGL_DEBUG_DISABLE_BLENDING}, + { "disable-npot-textures", COGL_DEBUG_DISABLE_NPOT_TEXTURES}, + { "wireframe", COGL_DEBUG_WIREFRAME}, + { "disable-software-clip", COGL_DEBUG_DISABLE_SOFTWARE_CLIP}, + { "disable-program-caches", COGL_DEBUG_DISABLE_PROGRAM_CACHES}, + { "disable-fast-read-pixel", COGL_DEBUG_DISABLE_FAST_READ_PIXEL} +}; +static const int n_cogl_behavioural_debug_keys = + G_N_ELEMENTS (cogl_behavioural_debug_keys); + +unsigned long _cogl_debug_flags[COGL_DEBUG_N_LONGS]; +GHashTable *_cogl_debug_instances; + +static void +_cogl_parse_debug_string_for_keys (const char *value, + CoglBool enable, + const GDebugKey *keys, + unsigned int nkeys) +{ + int long_num, key_num; + + /* g_parse_debug_string expects the value field in GDebugKey to be a + mask in an unsigned int but the flags are stored in an array of + multiple longs so we need to build a separate array for each + possible unsigned int */ + + for (long_num = 0; long_num < COGL_DEBUG_N_LONGS; long_num++) + { + int int_num; + + for (int_num = 0; + int_num < sizeof (unsigned long) / sizeof (unsigned int); + int_num++) + { + GDebugKey keys_for_int[sizeof (unsigned int) * 8]; + int nkeys_for_int = 0; + + for (key_num = 0; key_num < nkeys; key_num++) + { + int long_index = COGL_FLAGS_GET_INDEX (keys[key_num].value); + int int_index = (keys[key_num].value % + (sizeof (unsigned long) * 8) / + (sizeof (unsigned int) * 8)); + + if (long_index == long_num && int_index == int_num) + { + keys_for_int[nkeys_for_int] = keys[key_num]; + keys_for_int[nkeys_for_int].value = + COGL_FLAGS_GET_MASK (keys[key_num].value) >> + (int_num * sizeof (unsigned int) * 8); + nkeys_for_int++; + } + } + + if (nkeys_for_int > 0) + { + unsigned long mask = + ((unsigned long) g_parse_debug_string (value, + keys_for_int, + nkeys_for_int)) << + (int_num * sizeof (unsigned int) * 8); + + if (enable) + _cogl_debug_flags[long_num] |= mask; + else + _cogl_debug_flags[long_num] &= ~mask; + } + } + } +} + +void +_cogl_parse_debug_string (const char *value, + CoglBool enable, + CoglBool ignore_help) +{ + if (ignore_help && strcmp (value, "help") == 0) + return; + + /* We don't want to let g_parse_debug_string handle "all" because + * literally enabling all the debug options wouldn't be useful to + * anyone; instead the all option enables all non behavioural + * options. + */ + if (strcmp (value, "all") == 0 || + strcmp (value, "verbose") == 0) + { + int i; + for (i = 0; i < n_cogl_log_debug_keys; i++) + if (enable) + COGL_DEBUG_SET_FLAG (cogl_log_debug_keys[i].value); + else + COGL_DEBUG_CLEAR_FLAG (cogl_log_debug_keys[i].value); + } + else if (g_ascii_strcasecmp (value, "help") == 0) + { + g_printerr ("\n\n%28s\n", _("Supported debug values:")); +#define OPT(MASK_NAME, GROUP, NAME, NAME_FORMATTED, DESCRIPTION) \ + g_printerr ("%28s %s\n", NAME ":", DESCRIPTION); +#include "cogl-debug-options.h" + g_printerr ("\n%28s\n", _("Special debug values:")); + OPT (IGNORED, "ignored", "all", "ignored", \ + N_("Enables all non-behavioural debug options")); + OPT (IGNORED, "ignored", "verbose", "ignored", \ + N_("Enables all non-behavioural debug options")); +#undef OPT + + g_printerr ("\n" + "%28s\n" + " COGL_DISABLE_GL_EXTENSIONS: %s\n" + " COGL_OVERRIDE_GL_VERSION: %s\n", + _("Additional environment variables:"), + _("Comma-separated list of GL extensions to pretend are " + "disabled"), + _("Override the GL version that Cogl will assume the driver " + "supports")); + exit (1); + } + else + { + _cogl_parse_debug_string_for_keys (value, + enable, + cogl_log_debug_keys, + n_cogl_log_debug_keys); + _cogl_parse_debug_string_for_keys (value, + enable, + cogl_behavioural_debug_keys, + n_cogl_behavioural_debug_keys); + } +} + +#ifdef COGL_ENABLE_DEBUG +static CoglBool +cogl_arg_debug_cb (const char *key, + const char *value, + void *user_data) +{ + _cogl_parse_debug_string (value, + TRUE /* enable the flags */, + FALSE /* don't ignore help */); + return TRUE; +} + +static CoglBool +cogl_arg_no_debug_cb (const char *key, + const char *value, + void *user_data) +{ + _cogl_parse_debug_string (value, + FALSE, /* disable the flags */ + TRUE /* ignore help */); + return TRUE; +} +#endif /* COGL_ENABLE_DEBUG */ + +static GOptionEntry cogl_args[] = { +#ifdef COGL_ENABLE_DEBUG + { "cogl-debug", 0, 0, G_OPTION_ARG_CALLBACK, cogl_arg_debug_cb, + N_("Cogl debugging flags to set"), "FLAGS" }, + { "cogl-no-debug", 0, 0, G_OPTION_ARG_CALLBACK, cogl_arg_no_debug_cb, + N_("Cogl debugging flags to unset"), "FLAGS" }, +#endif /* COGL_ENABLE_DEBUG */ + { NULL, }, +}; + +void +_cogl_debug_check_environment (void) +{ + const char *env_string; + + env_string = g_getenv ("COGL_DEBUG"); + if (env_string != NULL) + { + _cogl_parse_debug_string (env_string, + TRUE /* enable the flags */, + FALSE /* don't ignore help */); + env_string = NULL; + } + + env_string = g_getenv ("COGL_NO_DEBUG"); + if (env_string != NULL) + { + _cogl_parse_debug_string (env_string, + FALSE /* disable the flags */, + FALSE /* don't ignore help */); + env_string = NULL; + } +} + +static CoglBool +pre_parse_hook (GOptionContext *context, + GOptionGroup *group, + void *data, + GError **error) +{ + _cogl_init (); + + return TRUE; +} + +/* XXX: GOption based library initialization is not reliable because the + * GOption API has no way to represent dependencies between libraries. + */ +GOptionGroup * +cogl_get_option_group (void) +{ + GOptionGroup *group; + + group = g_option_group_new ("cogl", + _("Cogl Options"), + _("Show Cogl options"), + NULL, NULL); + + g_option_group_set_parse_hooks (group, pre_parse_hook, NULL); + g_option_group_add_entries (group, cogl_args); + + return group; +} diff --git a/cogl/cogl/cogl-debug.h b/cogl/cogl/cogl-debug.h new file mode 100644 index 0000000..ae116a2 --- /dev/null +++ b/cogl/cogl/cogl-debug.h @@ -0,0 +1,123 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_DEBUG_H__ +#define __COGL_DEBUG_H__ + +#include "cogl-profile.h" +#include "cogl-flags.h" +#include "cogl-util.h" + +#include + +COGL_BEGIN_DECLS + +typedef enum { + COGL_DEBUG_SLICING, + COGL_DEBUG_OFFSCREEN, + COGL_DEBUG_DRAW, + COGL_DEBUG_PANGO, + COGL_DEBUG_RECTANGLES, + COGL_DEBUG_OBJECT, + COGL_DEBUG_BLEND_STRINGS, + COGL_DEBUG_DISABLE_BATCHING, + COGL_DEBUG_DISABLE_VBOS, + COGL_DEBUG_DISABLE_PBOS, + COGL_DEBUG_JOURNAL, + COGL_DEBUG_BATCHING, + COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM, + COGL_DEBUG_MATRICES, + COGL_DEBUG_ATLAS, + COGL_DEBUG_DUMP_ATLAS_IMAGE, + COGL_DEBUG_DISABLE_ATLAS, + COGL_DEBUG_DISABLE_SHARED_ATLAS, + COGL_DEBUG_OPENGL, + COGL_DEBUG_DISABLE_TEXTURING, + COGL_DEBUG_DISABLE_ARBFP, + COGL_DEBUG_DISABLE_FIXED, + COGL_DEBUG_DISABLE_GLSL, + COGL_DEBUG_SHOW_SOURCE, + COGL_DEBUG_DISABLE_BLENDING, + COGL_DEBUG_TEXTURE_PIXMAP, + COGL_DEBUG_BITMAP, + COGL_DEBUG_DISABLE_NPOT_TEXTURES, + COGL_DEBUG_WIREFRAME, + COGL_DEBUG_DISABLE_SOFTWARE_CLIP, + COGL_DEBUG_DISABLE_PROGRAM_CACHES, + COGL_DEBUG_DISABLE_FAST_READ_PIXEL, + COGL_DEBUG_CLIPPING, + COGL_DEBUG_WINSYS, + COGL_DEBUG_PERFORMANCE, + + COGL_DEBUG_N_FLAGS +} CoglDebugFlags; + +extern GHashTable *_cogl_debug_instances; +#define COGL_DEBUG_N_LONGS COGL_FLAGS_N_LONGS_FOR_SIZE (COGL_DEBUG_N_FLAGS) + +extern unsigned long _cogl_debug_flags[COGL_DEBUG_N_LONGS]; + +#define COGL_DEBUG_ENABLED(flag) \ + COGL_FLAGS_GET (_cogl_debug_flags, flag) + +#define COGL_DEBUG_SET_FLAG(flag) \ + COGL_FLAGS_SET (_cogl_debug_flags, flag, TRUE) + +#define COGL_DEBUG_CLEAR_FLAG(flag) \ + COGL_FLAGS_SET (_cogl_debug_flags, flag, FALSE) + +#ifdef __GNUC__ +#define COGL_NOTE(type,x,a...) G_STMT_START { \ + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_##type))) { \ + _cogl_profile_trace_message ("[" #type "] " G_STRLOC " & " x, ##a); \ + } } G_STMT_END + +#else +#define COGL_NOTE(type,...) G_STMT_START { \ + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_##type))) { \ + char *_fmt = g_strdup_printf (__VA_ARGS__); \ + _cogl_profile_trace_message ("[" #type "] " G_STRLOC " & %s", _fmt);\ + g_free (_fmt); \ + } } G_STMT_END + +#endif /* __GNUC__ */ + +void +_cogl_debug_check_environment (void); + +void +_cogl_parse_debug_string (const char *value, + CoglBool enable, + CoglBool ignore_help); + +COGL_END_DECLS + +#endif /* __COGL_DEBUG_H__ */ + diff --git a/cogl/cogl/cogl-defines.h.in b/cogl/cogl/cogl-defines.h.in new file mode 100644 index 0000000..eb3ad92 --- /dev/null +++ b/cogl/cogl/cogl-defines.h.in @@ -0,0 +1,45 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_DEFINES_H__ +#define __COGL_DEFINES_H__ + +@COGL_DEFINES@ + +#define COGL_VERSION_MAJOR_INTERNAL 1 +#define COGL_VERSION_MINOR_INTERNAL @COGL_1_MINOR_VERSION@ +#define COGL_VERSION_MICRO_INTERNAL @COGL_1_MICRO_VERSION@ +#define COGL_VERSION_STRING_INTERNAL "@COGL_1_VERSION@" + +#endif diff --git a/cogl/cogl/cogl-deprecated.h b/cogl/cogl/cogl-deprecated.h new file mode 100644 index 0000000..ca56fa1 --- /dev/null +++ b/cogl/cogl/cogl-deprecated.h @@ -0,0 +1,43 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef COGL_DEPRECATED_H + +#define cogl_color cogl_color_REPLACED_BY_cogl_set_source_color +#define cogl_enable_depth_test cogl_enable_depth_test_RENAMED_TO_cogl_set_depth_test_enabled +#define cogl_enable_backface_culling cogl_enable_backface_culling_RENAMED_TO_cogl_set_backface_culling_enabled + +#define cogl_texture_rectangle cogl_texture_rectangle_REPLACE_BY_cogl_set_source_texture_AND_cogl_rectangle_with_texture_coords + +#define cogl_texture_multiple_rectangles cogl_texture_multiple_rectangles_REPLACED_BY_cogl_set_source_texture_AND_cogl_rectangles_with_texture_coords + +#define cogl_texture_polygon cogl_texture_polygon_REPLACED_BY_cogl_set_source_texture_AND_cogl_polygon + +#endif diff --git a/cogl/cogl/cogl-depth-state-private.h b/cogl/cogl/cogl-depth-state-private.h new file mode 100644 index 0000000..6c14bb9 --- /dev/null +++ b/cogl/cogl/cogl-depth-state-private.h @@ -0,0 +1,38 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_DEPTH_STATE_PRIVATE_H +#define __COGL_DEPTH_STATE_PRIVATE_H + + +#define COGL_DEPTH_STATE_MAGIC 0xDEADBEEF + +#endif /* __COGL_DEPTH_STATE_PRIVATE_H */ diff --git a/cogl/cogl/cogl-depth-state.c b/cogl/cogl/cogl-depth-state.c new file mode 100644 index 0000000..8346d4c --- /dev/null +++ b/cogl/cogl/cogl-depth-state.c @@ -0,0 +1,116 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-util.h" +#include "cogl-depth-state-private.h" +#include "cogl-depth-state.h" + +void +cogl_depth_state_init (CoglDepthState *state) +{ + state->magic = COGL_DEPTH_STATE_MAGIC; + + /* The same as the GL defaults */ + state->test_enabled = FALSE; + state->write_enabled = TRUE; + state->test_function = COGL_DEPTH_TEST_FUNCTION_LESS; + state->range_near = 0; + state->range_far = 1; +} + +void +cogl_depth_state_set_test_enabled (CoglDepthState *state, + CoglBool enabled) +{ + _COGL_RETURN_IF_FAIL (state->magic == COGL_DEPTH_STATE_MAGIC); + state->test_enabled = enabled; +} + +CoglBool +cogl_depth_state_get_test_enabled (CoglDepthState *state) +{ + _COGL_RETURN_VAL_IF_FAIL (state->magic == COGL_DEPTH_STATE_MAGIC, FALSE); + return state->test_enabled; +} + +void +cogl_depth_state_set_write_enabled (CoglDepthState *state, + CoglBool enabled) +{ + _COGL_RETURN_IF_FAIL (state->magic == COGL_DEPTH_STATE_MAGIC); + state->write_enabled = enabled; +} + +CoglBool +cogl_depth_state_get_write_enabled (CoglDepthState *state) +{ + _COGL_RETURN_VAL_IF_FAIL (state->magic == COGL_DEPTH_STATE_MAGIC, FALSE); + return state->write_enabled; +} + +void +cogl_depth_state_set_test_function (CoglDepthState *state, + CoglDepthTestFunction function) +{ + _COGL_RETURN_IF_FAIL (state->magic == COGL_DEPTH_STATE_MAGIC); + state->test_function = function; +} + +CoglDepthTestFunction +cogl_depth_state_get_test_function (CoglDepthState *state) +{ + _COGL_RETURN_VAL_IF_FAIL (state->magic == COGL_DEPTH_STATE_MAGIC, FALSE); + return state->test_function; +} + +void +cogl_depth_state_set_range (CoglDepthState *state, + float near, + float far) +{ + _COGL_RETURN_IF_FAIL (state->magic == COGL_DEPTH_STATE_MAGIC); + state->range_near = near; + state->range_far = far; +} + +void +cogl_depth_state_get_range (CoglDepthState *state, + float *near_out, + float *far_out) +{ + _COGL_RETURN_IF_FAIL (state->magic == COGL_DEPTH_STATE_MAGIC); + *near_out = state->range_near; + *far_out = state->range_far; +} diff --git a/cogl/cogl/cogl-depth-state.h b/cogl/cogl/cogl-depth-state.h new file mode 100644 index 0000000..581b961 --- /dev/null +++ b/cogl/cogl/cogl-depth-state.h @@ -0,0 +1,270 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Robert Bragg + * + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_DEPTH_STATE_H__ +#define __COGL_DEPTH_STATE_H__ + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-depth-state + * @short_description: Functions for describing the depth testing + * state of your GPU. + */ + +/** + * CoglDepthState: + * + * Since: 2.0 + */ +typedef struct { + /*< private >*/ + uint32_t COGL_PRIVATE (magic); + + CoglBool COGL_PRIVATE (test_enabled); + CoglDepthTestFunction COGL_PRIVATE (test_function); + CoglBool COGL_PRIVATE (write_enabled); + float COGL_PRIVATE (range_near); + float COGL_PRIVATE (range_far); + + uint32_t COGL_PRIVATE (padding0); + uint32_t COGL_PRIVATE (padding1); + uint32_t COGL_PRIVATE (padding2); + uint32_t COGL_PRIVATE (padding3); + uint32_t COGL_PRIVATE (padding4); + uint32_t COGL_PRIVATE (padding5); + uint32_t COGL_PRIVATE (padding6); + uint32_t COGL_PRIVATE (padding7); + uint32_t COGL_PRIVATE (padding8); + uint32_t COGL_PRIVATE (padding9); +} CoglDepthState; + +/** + * cogl_depth_state_init: + * @state: A #CoglDepthState struct + * + * Initializes the members of @state to their default values. + * + * You should never pass an un initialized #CoglDepthState structure + * to cogl_pipeline_set_depth_state(). + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_depth_state_init (CoglDepthState *state); + +/** + * cogl_depth_state_set_test_enabled: + * @state: A #CoglDepthState struct + * @enable: The enable state you want + * + * Enables or disables depth testing according to the value of + * @enable. + * + * If depth testing is enable then the #CoglDepthTestFunction set + * using cogl_depth_state_set_test_function() us used to evaluate + * the depth value of incoming fragments against the corresponding + * value stored in the current depth buffer, and if the test passes + * then the fragments depth value is used to update the depth buffer. + * (unless you have disabled depth writing via + * cogl_depth_state_set_write_enabled()) + * + * By default depth testing is disabled. + * + * NB: this won't directly affect the state of the GPU. You have + * to then set the state on a #CoglPipeline using + * cogl_pipeline_set_depth_state() + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_depth_state_set_test_enabled (CoglDepthState *state, + CoglBool enable); + +/** + * cogl_depth_state_get_test_enabled: + * @state: A #CoglDepthState struct + * + * Gets the current depth test enabled state as previously set by + * cogl_depth_state_set_test_enabled(). + * + * Returns: The pipeline's current depth test enabled state. + * Since: 2.0 + * Stability: Unstable + */ +CoglBool +cogl_depth_state_get_test_enabled (CoglDepthState *state); + +/** + * cogl_depth_state_set_write_enabled: + * @state: A #CoglDepthState struct + * @enable: The enable state you want + * + * Enables or disables depth buffer writing according to the value of + * @enable. Normally when depth testing is enabled and the comparison + * between a fragment's depth value and the corresponding depth buffer + * value passes then the fragment's depth is written to the depth + * buffer unless writing is disabled here. + * + * By default depth writing is enabled + * + * NB: this won't directly affect the state of the GPU. You have + * to then set the state on a #CoglPipeline using + * cogl_pipeline_set_depth_state() + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_depth_state_set_write_enabled (CoglDepthState *state, + CoglBool enable); + +/** + * cogl_depth_state_get_write_enabled: + * @state: A #CoglDepthState struct + * + * Gets the depth writing enable state as set by the corresponding + * cogl_depth_state_set_write_enabled(). + * + * Returns: The current depth writing enable state + * Since: 2.0 + * Stability: Unstable + */ +CoglBool +cogl_depth_state_get_write_enabled (CoglDepthState *state); + +/** + * cogl_depth_state_set_test_function: + * @state: A #CoglDepthState struct + * @function: The #CoglDepthTestFunction to set + * + * Sets the #CoglDepthTestFunction used to compare the depth value of + * an incoming fragment against the corresponding value in the current + * depth buffer. + * + * By default the depth test function is %COGL_DEPTH_TEST_FUNCTION_LESS + * + * NB: this won't directly affect the state of the GPU. You have + * to then set the state on a #CoglPipeline using + * cogl_pipeline_set_depth_state() + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_depth_state_set_test_function (CoglDepthState *state, + CoglDepthTestFunction function); + +/** + * cogl_depth_state_get_test_function: + * @state: A #CoglDepthState struct + * + * Gets the current depth test enable state as previously set via + * cogl_depth_state_set_test_enabled(). + * + * Returns: The current depth test enable state. + * Since: 2.0 + * Stability: Unstable + */ +CoglDepthTestFunction +cogl_depth_state_get_test_function (CoglDepthState *state); + +/** + * cogl_depth_state_set_range: + * @state: A #CoglDepthState object + * @near_val: The near component of the desired depth range which will be + * clamped to the range [0, 1] + * @far_val: The far component of the desired depth range which will be + * clamped to the range [0, 1] + * + * Sets the range to map depth values in normalized device coordinates + * to before writing out to a depth buffer. + * + * After your geometry has be transformed, clipped and had perspective + * division applied placing it in normalized device + * coordinates all depth values between the near and far z clipping + * planes are in the range -1 to 1. Before writing any depth value to + * the depth buffer though the value is mapped into the range [0, 1]. + * + * With this function you can change the range which depth values are + * mapped too although the range must still lye within the range [0, + * 1]. + * + * If your driver does not support this feature (for example you are + * using GLES 1 drivers) then if you don't use the default range + * values you will get an error reported when calling + * cogl_pipeline_set_depth_state (). You can check ahead of time for + * the %COGL_FEATURE_ID_DEPTH_RANGE feature with + * cogl_has_feature() to know if this function will succeed. + * + * By default normalized device coordinate depth values are mapped to + * the full range of depth buffer values, [0, 1]. + * + * NB: this won't directly affect the state of the GPU. You have + * to then set the state on a #CoglPipeline using + * cogl_pipeline_set_depth_state(). + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_depth_state_set_range (CoglDepthState *state, + float near_val, + float far_val); + +/** + * cogl_depth_state_get_range: + * @state: A #CoglDepthState object + * @near_val: A pointer to store the near component of the depth range + * @far_val: A pointer to store the far component of the depth range + * + * Gets the current range to which normalized depth values are mapped + * before writing to the depth buffer. This corresponds to the range + * set with cogl_depth_state_set_range(). + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_depth_state_get_range (CoglDepthState *state, + float *near_val, + float *far_val); + +COGL_END_DECLS + +#endif /* __COGL_DEPTH_STATE_H__ */ diff --git a/cogl/cogl/cogl-display-private.h b/cogl/cogl/cogl-display-private.h new file mode 100644 index 0000000..9788435 --- /dev/null +++ b/cogl/cogl/cogl-display-private.h @@ -0,0 +1,54 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_DISPLAY_PRIVATE_H +#define __COGL_DISPLAY_PRIVATE_H + +#include "cogl-object-private.h" +#include "cogl-display.h" +#include "cogl-renderer.h" +#include "cogl-onscreen-template.h" + +struct _CoglDisplay +{ + CoglObject _parent; + + CoglBool setup; + CoglRenderer *renderer; + CoglOnscreenTemplate *onscreen_template; + +#ifdef COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT + struct wl_display *wayland_compositor_display; +#endif + + void *winsys; +}; + +#endif /* __COGL_DISPLAY_PRIVATE_H */ diff --git a/cogl/cogl/cogl-display.c b/cogl/cogl/cogl-display.c new file mode 100644 index 0000000..81d3d84 --- /dev/null +++ b/cogl/cogl/cogl-display.c @@ -0,0 +1,167 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include + +#include "cogl-private.h" +#include "cogl-object.h" + +#include "cogl-display-private.h" +#include "cogl-renderer-private.h" +#include "cogl-winsys-private.h" +#ifdef COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT +#include "cogl-wayland-server.h" +#endif +#include "cogl-gtype-private.h" + +static void _cogl_display_free (CoglDisplay *display); + +COGL_OBJECT_DEFINE (Display, display); +COGL_GTYPE_DEFINE_CLASS (Display, display); + +static const CoglWinsysVtable * +_cogl_display_get_winsys (CoglDisplay *display) +{ + return display->renderer->winsys_vtable; +} + +static void +_cogl_display_free (CoglDisplay *display) +{ + const CoglWinsysVtable *winsys; + + if (display->setup) + { + winsys = _cogl_display_get_winsys (display); + winsys->display_destroy (display); + display->setup = FALSE; + } + + if (display->renderer) + { + cogl_object_unref (display->renderer); + display->renderer = NULL; + } + + if (display->onscreen_template) + { + cogl_object_unref (display->onscreen_template); + display->onscreen_template = NULL; + } + + g_slice_free (CoglDisplay, display); +} + +CoglDisplay * +cogl_display_new (CoglRenderer *renderer, + CoglOnscreenTemplate *onscreen_template) +{ + CoglDisplay *display = g_slice_new0 (CoglDisplay); + CoglError *error = NULL; + + _cogl_init (); + + display->renderer = renderer; + if (renderer) + cogl_object_ref (renderer); + else + display->renderer = cogl_renderer_new (); + + if (!cogl_renderer_connect (display->renderer, &error)) + g_error ("Failed to connect to renderer: %s\n", error->message); + + display->setup = FALSE; + + display = _cogl_display_object_new (display); + + cogl_display_set_onscreen_template (display, onscreen_template); + + return display; +} + +CoglRenderer * +cogl_display_get_renderer (CoglDisplay *display) +{ + return display->renderer; +} + +void +cogl_display_set_onscreen_template (CoglDisplay *display, + CoglOnscreenTemplate *onscreen_template) +{ + _COGL_RETURN_IF_FAIL (display->setup == FALSE); + + if (onscreen_template) + cogl_object_ref (onscreen_template); + + if (display->onscreen_template) + cogl_object_unref (display->onscreen_template); + + display->onscreen_template = onscreen_template; + + /* NB: we want to maintain the invariable that there is always an + * onscreen template associated with a CoglDisplay... */ + if (!onscreen_template) + display->onscreen_template = cogl_onscreen_template_new (NULL); +} + +CoglBool +cogl_display_setup (CoglDisplay *display, + CoglError **error) +{ + const CoglWinsysVtable *winsys; + + if (display->setup) + return TRUE; + + winsys = _cogl_display_get_winsys (display); + if (!winsys->display_setup (display, error)) + return FALSE; + + display->setup = TRUE; + + return TRUE; +} + +#ifdef COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT +void +cogl_wayland_display_set_compositor_display (CoglDisplay *display, + struct wl_display *wayland_display) +{ + _COGL_RETURN_IF_FAIL (display->setup == FALSE); + + display->wayland_compositor_display = wayland_display; +} +#endif diff --git a/cogl/cogl/cogl-display.h b/cogl/cogl/cogl-display.h new file mode 100644 index 0000000..4c15dcc --- /dev/null +++ b/cogl/cogl/cogl-display.h @@ -0,0 +1,210 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Robert Bragg + * + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_DISPLAY_H__ +#define __COGL_DISPLAY_H__ + +#include +#include + +#include + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-display + * @short_description: Common aspects of a display pipeline + * + * The basic intention for this object is to let the application + * configure common display preferences before creating a context, and + * there are a few different aspects to this... + * + * Firstly there are options directly relating to the physical display + * pipeline that is currently being used including the digital to + * analogue conversion hardware and the screens the user sees. + * + * Another aspect is that display options may constrain or affect how + * onscreen framebuffers should later be configured. The original + * rationale for the display object in fact was to let us handle GLX + * and EGLs requirements that framebuffers must be "compatible" with + * the config associated with the current context meaning we have to + * force the user to describe how they would like to create their + * onscreen windows before we can choose a suitable fbconfig and + * create a GLContext. + */ + +typedef struct _CoglDisplay CoglDisplay; + +#define COGL_DISPLAY(OBJECT) ((CoglDisplay *)OBJECT) + +/** + * cogl_display_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_display_get_gtype (void); + +/** + * cogl_display_new: + * @renderer: A #CoglRenderer + * @onscreen_template: A #CoglOnscreenTemplate + * + * Explicitly allocates a new #CoglDisplay object to encapsulate the + * common state of the display pipeline that applies to the whole + * application. + * + * Many applications don't need to explicitly use + * cogl_display_new() and can just jump straight to cogl_context_new() + * and pass a %NULL display argument so Cogl will automatically + * connect and setup a renderer and display. + * + * A @display can only be made for a specific choice of renderer which + * is why this takes the @renderer argument. + * + * A common use for explicitly allocating a display object is to + * define a template for allocating onscreen framebuffers which is + * what the @onscreen_template argument is for, or alternatively + * you can use cogl_display_set_onscreen_template(). + * + * When a display is first allocated via cogl_display_new() it is in a + * mutable configuration mode. It's designed this way so we can + * extend the apis available for configuring a display without + * requiring huge numbers of constructor arguments. + * + * When you have finished configuring a display object you can + * optionally call cogl_display_setup() to explicitly apply the + * configuration and check for errors. Alternaitvely you can pass the + * display to cogl_context_new() and Cogl will implicitly apply your + * configuration but if there are errors then the application will + * abort with a message. For simple applications with no fallback + * options then relying on the implicit setup can be fine. + * + * Return value: (transfer full): A newly allocated #CoglDisplay + * object in a mutable configuration mode. + * Since: 1.10 + * Stability: unstable + */ +CoglDisplay * +cogl_display_new (CoglRenderer *renderer, + CoglOnscreenTemplate *onscreen_template); + +/** + * cogl_display_get_renderer: + * @display: a #CoglDisplay + * + * Queries the #CoglRenderer associated with the given @display. + * + * Return value: (transfer none): The associated #CoglRenderer + * + * Since: 1.10 + * Stability: unstable + */ +CoglRenderer * +cogl_display_get_renderer (CoglDisplay *display); + +/** + * cogl_display_set_onscreen_template: + * @display: a #CoglDisplay + * @onscreen_template: A template for creating #CoglOnscreen framebuffers + * + * Specifies a template for creating #CoglOnscreen framebuffers. + * + * Depending on the system, the constraints for creating #CoglOnscreen + * framebuffers need to be known before setting up a #CoglDisplay because the + * final setup of the display may constrain how onscreen framebuffers may be + * allocated. If Cogl knows how an application wants to allocate onscreen + * framebuffers then it can try to make sure to setup the display accordingly. + * + * Since: 1.16 + * Stability: unstable + */ +void +cogl_display_set_onscreen_template (CoglDisplay *display, + CoglOnscreenTemplate *onscreen_template); + +/** + * cogl_display_setup: + * @display: a #CoglDisplay + * @error: return location for a #CoglError + * + * Explicitly sets up the given @display object. Use of this api is + * optional since Cogl will internally setup the display if not done + * explicitly. + * + * When a display is first allocated via cogl_display_new() it is in a + * mutable configuration mode. This allows us to extend the apis + * available for configuring a display without requiring huge numbers + * of constructor arguments. + * + * Its possible to request a configuration that might not be + * supportable on the current system and so this api provides a means + * to apply the configuration explicitly but if it fails then an + * exception will be returned so you can handle the error gracefully + * and perhaps fall back to an alternative configuration. + * + * If you instead rely on Cogl implicitly calling cogl_display_setup() + * for you then if there is an error with the configuration you won't + * get an opportunity to handle that and the application may abort + * with a message. For simple applications that don't have any + * fallback options this behaviour may be fine. + * + * Return value: Returns %TRUE if there was no error, else it returns + * %FALSE and returns an exception via @error. + * Since: 1.10 + * Stability: unstable + */ +CoglBool +cogl_display_setup (CoglDisplay *display, + CoglError **error); + +/** + * cogl_is_display: + * @object: A #CoglObject pointer + * + * Gets whether the given object references a #CoglDisplay. + * + * Return value: %TRUE if the object references a #CoglDisplay + * and %FALSE otherwise. + * Since: 1.10 + * Stability: unstable + */ +CoglBool +cogl_is_display (void *object); + +COGL_END_DECLS + +#endif /* __COGL_DISPLAY_H__ */ + diff --git a/cogl/cogl/cogl-driver.h b/cogl/cogl/cogl-driver.h new file mode 100644 index 0000000..648228c --- /dev/null +++ b/cogl/cogl/cogl-driver.h @@ -0,0 +1,268 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_DRIVER_H +#define __COGL_DRIVER_H + +#include "cogl-context.h" +#include "cogl-offscreen.h" +#include "cogl-framebuffer-private.h" +#include "cogl-attribute-private.h" + +typedef struct _CoglDriverVtable CoglDriverVtable; + +struct _CoglDriverVtable +{ + /* TODO: factor this out since this is OpenGL specific and + * so can be ignored by non-OpenGL drivers. */ + CoglBool + (* pixel_format_from_gl_internal) (CoglContext *context, + GLenum gl_int_format, + CoglPixelFormat *out_format); + + /* TODO: factor this out since this is OpenGL specific and + * so can be ignored by non-OpenGL drivers. */ + CoglPixelFormat + (* pixel_format_to_gl) (CoglContext *context, + CoglPixelFormat format, + GLenum *out_glintformat, + GLenum *out_glformat, + GLenum *out_gltype); + + CoglBool + (* update_features) (CoglContext *context, + CoglError **error); + + CoglBool + (* offscreen_allocate) (CoglOffscreen *offscreen, + CoglError **error); + + void + (* offscreen_free) (CoglOffscreen *offscreen); + + void + (* framebuffer_flush_state) (CoglFramebuffer *draw_buffer, + CoglFramebuffer *read_buffer, + CoglFramebufferState state); + + void + (* framebuffer_clear) (CoglFramebuffer *framebuffer, + unsigned long buffers, + float red, + float green, + float blue, + float alpha); + + void + (* framebuffer_query_bits) (CoglFramebuffer *framebuffer, + CoglFramebufferBits *bits); + + void + (* framebuffer_finish) (CoglFramebuffer *framebuffer); + + void + (* framebuffer_discard_buffers) (CoglFramebuffer *framebuffer, + unsigned long buffers); + + void + (* framebuffer_draw_attributes) (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglVerticesMode mode, + int first_vertex, + int n_vertices, + CoglAttribute **attributes, + int n_attributes, + CoglDrawFlags flags); + + void + (* framebuffer_draw_indexed_attributes) (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglVerticesMode mode, + int first_vertex, + int n_vertices, + CoglIndices *indices, + CoglAttribute **attributes, + int n_attributes, + CoglDrawFlags flags); + + CoglBool + (* framebuffer_read_pixels_into_bitmap) (CoglFramebuffer *framebuffer, + int x, + int y, + CoglReadPixelsFlags source, + CoglBitmap *bitmap, + CoglError **error); + + /* Destroys any driver specific resources associated with the given + * 2D texture. */ + void + (* texture_2d_free) (CoglTexture2D *tex_2d); + + /* Returns TRUE if the driver can support creating a 2D texture with + * the given geometry and specified internal format. + */ + CoglBool + (* texture_2d_can_create) (CoglContext *ctx, + int width, + int height, + CoglPixelFormat internal_format); + + /* Initializes driver private state before allocating any specific + * storage for a 2D texture, where base texture and texture 2D + * members will already be initialized before passing control to + * the driver. + */ + void + (* texture_2d_init) (CoglTexture2D *tex_2d); + + /* Allocates (uninitialized) storage for the given texture according + * to the configured size and format of the texture */ + CoglBool + (* texture_2d_allocate) (CoglTexture *tex, + CoglError **error); + + /* Initialize the specified region of storage of the given texture + * with the contents of the specified framebuffer region + */ + void + (* texture_2d_copy_from_framebuffer) (CoglTexture2D *tex_2d, + int src_x, + int src_y, + int width, + int height, + CoglFramebuffer *src_fb, + int dst_x, + int dst_y, + int level); + + /* If the given texture has a corresponding OpenGL texture handle + * then return that. + * + * This is optional + */ + unsigned int + (* texture_2d_get_gl_handle) (CoglTexture2D *tex_2d); + + /* Update all mipmap levels > 0 */ + void + (* texture_2d_generate_mipmap) (CoglTexture2D *tex_2d); + + /* Initialize the specified region of storage of the given texture + * with the contents of the specified bitmap region + * + * Since this may need to create the underlying storage first + * it may throw a NO_MEMORY error. + */ + CoglBool + (* texture_2d_copy_from_bitmap) (CoglTexture2D *tex_2d, + int src_x, + int src_y, + int width, + int height, + CoglBitmap *bitmap, + int dst_x, + int dst_y, + int level, + CoglError **error); + + /* Reads back the full contents of the given texture and write it to + * @data in the given @format and with the given @rowstride. + * + * This is optional + */ + void + (* texture_2d_get_data) (CoglTexture2D *tex_2d, + CoglPixelFormat format, + int rowstride, + uint8_t *data); + + /* Prepares for drawing by flushing the journal, framebuffer state, + * pipeline state and attribute state. + */ + void + (* flush_attributes_state) (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglFlushLayerState *layer_state, + CoglDrawFlags flags, + CoglAttribute **attributes, + int n_attributes); + + /* Flushes the clip stack to the GPU using a combination of the + * stencil buffer, scissor and clip plane state. + */ + void + (* clip_stack_flush) (CoglClipStack *stack, CoglFramebuffer *framebuffer); + + /* Enables the driver to create some meta data to represent a buffer + * but with no corresponding storage allocated yet. + */ + void + (* buffer_create) (CoglBuffer *buffer); + + void + (* buffer_destroy) (CoglBuffer *buffer); + + /* Maps a buffer into the CPU */ + void * + (* buffer_map_range) (CoglBuffer *buffer, + size_t offset, + size_t size, + CoglBufferAccess access, + CoglBufferMapHint hints, + CoglError **error); + + /* Unmaps a buffer */ + void + (* buffer_unmap) (CoglBuffer *buffer); + + /* Uploads data to the buffer without needing to map it necessarily + */ + CoglBool + (* buffer_set_data) (CoglBuffer *buffer, + unsigned int offset, + const void *data, + unsigned int size, + CoglError **error); +}; + +#define COGL_DRIVER_ERROR (_cogl_driver_error_quark ()) + +typedef enum { /*< prefix=COGL_DRIVER_ERROR >*/ + COGL_DRIVER_ERROR_UNKNOWN_VERSION, + COGL_DRIVER_ERROR_INVALID_VERSION, + COGL_DRIVER_ERROR_NO_SUITABLE_DRIVER_FOUND, + COGL_DRIVER_ERROR_FAILED_TO_LOAD_LIBRARY +} CoglDriverError; + +uint32_t +_cogl_driver_error_quark (void); + +#endif /* __COGL_DRIVER_H */ + diff --git a/cogl/cogl/cogl-egl-defines.h.in b/cogl/cogl/cogl-egl-defines.h.in new file mode 100644 index 0000000..648a62d --- /dev/null +++ b/cogl/cogl/cogl-egl-defines.h.in @@ -0,0 +1,40 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_EGL_DEFINES_H__ +#define __COGL_EGL_DEFINES_H__ + +#ifdef COGL_HAS_EGL_SUPPORT + +@COGL_EGL_INCLUDES@ + +#endif /* COGL_HAS_EGL_SUPPORT */ + +#endif diff --git a/cogl/cogl/cogl-egl-private.h b/cogl/cogl/cogl-egl-private.h new file mode 100644 index 0000000..0af8518 --- /dev/null +++ b/cogl/cogl/cogl-egl-private.h @@ -0,0 +1,40 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_EGL_PRIVATE_H__ +#define __COGL_EGL_PRIVATE_H__ + +#include "cogl-egl-defines.h" + +#if defined(GL_OES_EGL_image) && !defined(GLeglImageOES) +#define GLeglImageOES void * +#endif + +#endif /* __COGL_EGL_PRIVATE_H__ */ diff --git a/cogl/cogl/cogl-egl.h b/cogl/cogl/cogl-egl.h new file mode 100644 index 0000000..787feab --- /dev/null +++ b/cogl/cogl/cogl-egl.h @@ -0,0 +1,118 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_EGL_H__ +#define __COGL_EGL_H__ + +/* NB: this is a top-level header that can be included directly but we + * want to be careful not to define __COGL_H_INSIDE__ when this is + * included internally while building Cogl itself since + * __COGL_H_INSIDE__ is used in headers to guard public vs private api + * definitions + */ +#ifndef COGL_COMPILATION + +/* Note: When building Cogl .gir we explicitly define + * __COGL_EGL_H_INSIDE__ */ +#ifndef __COGL_EGL_H_INSIDE__ +#define __COGL_EGL_H_INSIDE__ +#endif + +/* Note: When building Cogl .gir we explicitly define + * __COGL_H_INSIDE__ */ +#ifndef __COGL_H_INSIDE__ +#define __COGL_H_INSIDE__ +#define __COGL_MUST_UNDEF_COGL_H_INSIDE_COGL_EGL__ +#endif + +#endif /* COGL_COMPILATION */ + + +#include +#include + +COGL_BEGIN_DECLS + +/** + * cogl_egl_context_get_egl_display: + * @context: A #CoglContext pointer + * + * If you have done a runtime check to determine that Cogl is using + * EGL internally then this API can be used to retrieve the EGLDisplay + * handle that was setup internally. The result is undefined if Cogl + * is not using EGL. + * + * Note: The current window system backend can be checked using + * cogl_renderer_get_winsys_id(). + * + * Return value: The internally setup EGLDisplay handle. + * Since: 1.8 + * Stability: unstable + */ +EGLDisplay +cogl_egl_context_get_egl_display (CoglContext *context); + +/** + * cogl_egl_context_get_egl_context: + * @context: A #CoglContext pointer + * + * If you have done a runtime check to determine that Cogl is using + * EGL internally then this API can be used to retrieve the EGLContext + * handle that was setup internally. The result is undefined if Cogl + * is not using EGL. + * + * Note: The current window system backend can be checked using + * cogl_renderer_get_winsys_id(). + * + * Return value: The internally setup EGLDisplay handle. + * Since: 1.18 + * Stability: unstable + */ +EGLContext +cogl_egl_context_get_egl_context (CoglContext *context); + + +COGL_END_DECLS + +/* The gobject introspection scanner seems to parse public headers in + * isolation which means we need to be extra careful about how we + * define and undefine __COGL_H_INSIDE__ used to detect when internal + * headers are incorrectly included by developers. In the gobject + * introspection case we have to manually define __COGL_H_INSIDE__ as + * a commandline argument for the scanner which means we must be + * careful not to undefine it in a header... + */ +#ifdef __COGL_MUST_UNDEF_COGL_H_INSIDE_COGL_EGL__ +#undef __COGL_H_INSIDE__ +#undef __COGL_EGL_H_INSIDE__ +#undef __COGL_MUST_UNDEF_COGL_H_INSIDE_COGL_EGL__ +#endif + +#endif /* __COGL_EGL_H__ */ diff --git a/cogl/cogl/cogl-error-private.h b/cogl/cogl/cogl-error-private.h new file mode 100644 index 0000000..382fc44 --- /dev/null +++ b/cogl/cogl/cogl-error-private.h @@ -0,0 +1,57 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __COGL_ERROR_PRIVATE_H__ +#define __COGL_ERROR_PRIVATE_H__ + +#include "cogl-error.h" + +void +_cogl_set_error (CoglError **error, + uint32_t domain, + int code, + const char *format, + ...) G_GNUC_PRINTF (4, 5); + +void +_cogl_set_error_literal (CoglError **error, + uint32_t domain, + int code, + const char *message); + +void +_cogl_propagate_error (CoglError **dest, + CoglError *src); + +void +_cogl_propagate_gerror (CoglError **dest, + GError *src); + +#define _cogl_clear_error(X) g_clear_error ((GError **)X) + +#endif /* __COGL_ERROR_PRIVATE_H__ */ diff --git a/cogl/cogl/cogl-error.c b/cogl/cogl/cogl-error.c new file mode 100644 index 0000000..623ab1b --- /dev/null +++ b/cogl/cogl/cogl-error.c @@ -0,0 +1,128 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-types.h" +#include "cogl-util.h" +#include "cogl-error-private.h" + +#include + +void +cogl_error_free (CoglError *error) +{ + g_error_free ((GError *)error); +} + +CoglError * +cogl_error_copy (CoglError *error) +{ + return (CoglError *)g_error_copy ((GError *)error); +} + +CoglBool +cogl_error_matches (CoglError *error, + uint32_t domain, + int code) +{ + return g_error_matches ((GError *)error, domain, code); +} + +#define ERROR_OVERWRITTEN_WARNING \ + "CoglError set over the top of a previous CoglError or " \ + "uninitialized memory.\nThis indicates a bug in someone's " \ + "code. You must ensure an error is NULL before it's set.\n" \ + "The overwriting error message was: %s" + +void +_cogl_set_error (CoglError **error, + uint32_t domain, + int code, + const char *format, + ...) +{ + GError *new; + + va_list args; + + va_start (args, format); + + if (error == NULL) + { + g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, format, args); + va_end (args); + return; + } + + new = g_error_new_valist (domain, code, format, args); + va_end (args); + + if (*error == NULL) + *error = (CoglError *)new; + else + g_warning (ERROR_OVERWRITTEN_WARNING, new->message); +} + +void +_cogl_set_error_literal (CoglError **error, + uint32_t domain, + int code, + const char *message) +{ + _cogl_set_error (error, domain, code, "%s", message); +} + +void +_cogl_propagate_error (CoglError **dest, + CoglError *src) +{ + _COGL_RETURN_IF_FAIL (src != NULL); + + if (dest == NULL) + { + g_log (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, "%s", src->message); + cogl_error_free (src); + } + else if (*dest) + g_warning (ERROR_OVERWRITTEN_WARNING, src->message); + else + *dest = src; +} + +void +_cogl_propagate_gerror (CoglError **dest, + GError *src) +{ + _cogl_propagate_error (dest, (CoglError *) src); +} diff --git a/cogl/cogl/cogl-error.h b/cogl/cogl/cogl-error.h new file mode 100644 index 0000000..eddec35 --- /dev/null +++ b/cogl/cogl/cogl-error.h @@ -0,0 +1,169 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_ERROR_H__ +#define __COGL_ERROR_H__ + +#include "cogl-types.h" + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-error + * @short_description: A way for Cogl to throw exceptions + * + * As a general rule Cogl shields non-recoverable errors from + * developers, such as most heap allocation failures (unless for + * exceptionally large resources which we might reasonably expect to + * fail) and this reduces the burden on developers. + * + * There are some Cogl apis though that can fail for exceptional + * reasons that can also potentially be recovered from at runtime + * and for these apis we use a standard convention for reporting + * runtime recoverable errors. + * + * As an example if we look at the cogl_context_new() api which + * takes an error argument: + * |[ + * CoglContext * + * cogl_context_new (CoglDisplay *display, CoglError **error); + * ]| + * + * A caller interested in catching any runtime error when creating a + * new #CoglContext would pass the address of a #CoglError pointer + * that has first been initialized to %NULL as follows: + * + * |[ + * CoglError *error = NULL; + * CoglContext *context; + * + * context = cogl_context_new (NULL, &error); + * ]| + * + * The return status should usually be enough to determine if there + * was an error set (in this example we can check if context == %NULL) + * but if it's not possible to tell from the function's return status + * you can instead look directly at the error pointer which you + * initialized to %NULL. In this example we now check the error, + * report any error to the user, free the error and then simply + * abort without attempting to recover. + * + * |[ + * if (context == NULL) + * { + * fprintf (stderr, "Failed to create a Cogl context: %s\n", + * error->message); + * cogl_error_free (error); + * abort (); + * } + * ]| + * + * All Cogl APIs that accept an error argument can also be passed a + * %NULL pointer. In this case if an exceptional error condition is hit + * then Cogl will simply log the error message and abort the + * application. This can be compared to language execeptions where the + * developer has not attempted to catch the exception. This means the + * above example is essentially redundant because it's what Cogl would + * have done automatically and so, similarly, if your application has + * no way to recover from a particular error you might just as well + * pass a %NULL #CoglError pointer to save a bit of typing. + * + * If you are used to using the GLib API you will probably + * recognize that #CoglError is just like a #GError. In fact if Cogl + * has been built with --enable-glib then it is safe to cast a + * #CoglError to a #GError. + * + * An important detail to be aware of if you are used to using + * GLib's GError API is that Cogl deviates from the GLib GError + * conventions in one noteable way which is that a %NULL error pointer + * does not mean you want to ignore the details of an error, it means + * you are not trying to catch any exceptional errors the function might + * throw which will result in the program aborting with a log message + * if an error is thrown. + */ + +#define CoglError GError + +/** + * cogl_error_free: + * @error: A #CoglError thrown by the Cogl api + * + * Frees a #CoglError and associated resources. + */ +void +cogl_error_free (CoglError *error); + +/** + * cogl_error_copy: + * @error: A #CoglError thrown by the Cogl api + * + * Makes a copy of @error which can later be freed using + * cogl_error_free(). + * + * Return value: A newly allocated #CoglError initialized to match the + * contents of @error. + */ +CoglError * +cogl_error_copy (CoglError *error); + +/** + * cogl_error_matches: + * @error: A #CoglError thrown by the Cogl api or %NULL + * @domain: The error domain + * @code: The error code + * + * Returns %TRUE if error matches @domain and @code, %FALSE otherwise. + * In particular, when error is %NULL, FALSE will be returned. + * + * Return value: whether the @error corresponds to the given @domain + * and @code. + */ +CoglBool +cogl_error_matches (CoglError *error, + uint32_t domain, + int code); + +/** + * COGL_GLIB_ERROR: + * @COGL_ERROR: A #CoglError thrown by the Cogl api or %NULL + * + * Simply casts a #CoglError to a #CoglError + * + * If Cogl is built with GLib support then it can safely be assumed + * that a CoglError is a GError and can be used directly with the + * GError api. + */ +#define COGL_GLIB_ERROR(COGL_ERROR) ((CoglError *)COGL_ERROR) + +COGL_END_DECLS + +#endif /* __COGL_ERROR_H__ */ diff --git a/cogl/cogl/cogl-euler.c b/cogl/cogl/cogl-euler.c new file mode 100644 index 0000000..7af6ea0 --- /dev/null +++ b/cogl/cogl/cogl-euler.c @@ -0,0 +1,198 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include +#include +#include +#include "cogl-gtype-private.h" + +#include +#include + +COGL_GTYPE_DEFINE_BOXED (Euler, euler, + cogl_euler_copy, + cogl_euler_free); + +void +cogl_euler_init (CoglEuler *euler, + float heading, + float pitch, + float roll) +{ + euler->heading = heading; + euler->pitch = pitch; + euler->roll = roll; +} + +void +cogl_euler_init_from_matrix (CoglEuler *euler, + const CoglMatrix *matrix) +{ + /* + * Extracting a canonical Euler angle from a matrix: + * (where it is assumed the matrix contains no scaling, mirroring or + * skewing) + * + * A Euler angle is a combination of three rotations around mutually + * perpendicular axis. For this algorithm they are: + * + * Heading: A rotation about the Y axis by an angle H: + * | cosH 0 sinH| + * | 0 1 0| + * |-sinH 0 cosH| + * + * Pitch: A rotation around the X axis by an angle P: + * |1 0 0| + * |0 cosP -sinP| + * |0 sinP cosP| + * + * Roll: A rotation about the Z axis by an angle R: + * |cosR -sinR 0| + * |sinR cosR 0| + * | 0 0 1| + * + * When multiplied as matrices this gives: + * | cosHcosR+sinHsinPsinR sinRcosP -sinHcosR+cosHsinPsinR| + * M = |-cosHsinR+sinHsinPcosR cosRcosP sinRsinH+cosHsinPcosB| + * | sinHcosP -sinP cosHcosP | + * + * Given that there are an infinite number of ways to represent + * a given orientation, the "canonical" Euler angle is any such that: + * -180 < H < 180, + * -180 < R < 180 and + * -90 < P < 90 + * + * M[3][2] = -sinP lets us immediately solve for P = asin(-M[3][2]) + * (Note: asin has a range of +-90) + * This gives cosP + * This means we can use M[3][1] to calculate sinH: + * sinH = M[3][1]/cosP + * And use M[3][3] to calculate cosH: + * cosH = M[3][3]/cosP + * This lets us calculate H = atan2(sinH,cosH), but we optimise this: + * 1st note: atan2(x, y) does: atan(x/y) and uses the sign of x and y to + * determine the quadrant of the final angle. + * 2nd note: we know cosP is > 0 (ignoring cosP == 0) + * Therefore H = atan2((M[3][1]/cosP) / (M[3][3]/cosP)) can be simplified + * by skipping the division by cosP since it won't change the x/y ratio + * nor will it change their sign. This gives: + * H = atan2(M[3][1], M[3][3]) + * R is computed in the same way as H from M[1][2] and M[2][2] so: + * R = atan2(M[1][2], M[2][2]) + * Note: If cosP were == 0 then H and R could not be calculated as above + * because all the necessary matrix values would == 0. In other words we are + * pitched vertically and so H and R would now effectively rotate around the + * same axis - known as "Gimbal lock". In this situation we will set all the + * rotation on H and set R = 0. + * So with P = R = 0 we have cosP = 0, sinR = 0 and cosR = 1 + * We can substitute those into the above equation for M giving: + * | cosH 0 -sinH| + * |sinHsinP 0 cosHsinP| + * | 0 -sinP 0| + * And calculate H as atan2 (-M[3][2], M[1][1]) + */ + + float sinP; + float H; /* heading */ + float P; /* pitch */ + float R; /* roll */ + + /* NB: CoglMatrix provides struct members named according to the + * [row][column] indexed. So matrix->zx is row 3 column 1. */ + sinP = -matrix->zy; + + /* Determine the Pitch, avoiding domain errors with asin () which + * might occur due to previous imprecision in manipulating the + * matrix. */ + if (sinP <= -1.0f) + P = -G_PI_2; + else if (sinP >= 1.0f) + P = G_PI_2; + else + P = asinf (sinP); + + /* If P is too close to 0 then we have hit Gimbal lock */ + if (sinP > 0.999f) + { + H = atan2f (-matrix->zy, matrix->xx); + R = 0; + } + else + { + H = atan2f (matrix->zx, matrix->zz); + R = atan2f (matrix->xy, matrix->yy); + } + + euler->heading = H; + euler->pitch = P; + euler->roll = R; +} + +CoglBool +cogl_euler_equal (const void *v1, const void *v2) +{ + const CoglEuler *a = v1; + const CoglEuler *b = v2; + + _COGL_RETURN_VAL_IF_FAIL (v1 != NULL, FALSE); + _COGL_RETURN_VAL_IF_FAIL (v2 != NULL, FALSE); + + if (v1 == v2) + return TRUE; + + return (a->heading == b->heading && + a->pitch == b->pitch && + a->roll == b->roll); +} + +CoglEuler * +cogl_euler_copy (const CoglEuler *src) +{ + if (G_LIKELY (src)) + { + CoglEuler *new = g_slice_new (CoglEuler); + memcpy (new, src, sizeof (float) * 3); + return new; + } + else + return NULL; +} + +void +cogl_euler_free (CoglEuler *euler) +{ + g_slice_free (CoglEuler, euler); +} + diff --git a/cogl/cogl/cogl-euler.h b/cogl/cogl/cogl-euler.h new file mode 100644 index 0000000..39b06de --- /dev/null +++ b/cogl/cogl/cogl-euler.h @@ -0,0 +1,265 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Robert Bragg + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_EULER_H +#define __COGL_EULER_H + +#include + +#include + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-euler + * @short_description: Functions for initializing and manipulating + * euler angles. + * + * Euler angles are a simple representation of a 3 dimensional + * rotation; comprised of 3 ordered heading, pitch and roll rotations. + * An important thing to understand is that the axis of rotation + * belong to the object being rotated and so they also rotate as each + * of the heading, pitch and roll rotations are applied. + * + * One way to consider euler angles is to imagine controlling an + * aeroplane, where you first choose a heading (Such as flying south + * east), then you set the pitch (such as 30 degrees to take off) and + * then you might set a roll, by dipping the left, wing as you prepare + * to turn. + * + * They have some advantages and limitations that it helps to be + * aware of: + * + * Advantages: + * + * + * Easy to understand and use, compared to quaternions and matrices, + * so may be a good choice for a user interface. + * + * + * Efficient storage, needing only 3 components any rotation can be + * represented. + * Actually the #CoglEuler type isn't optimized for size because + * we may cache the equivalent #CoglQuaternion along with a euler + * rotation, but it would be trivial for an application to track the + * components of euler rotations in a packed float array if optimizing + * for size was important. The values could be passed to Cogl only when + * manipulation is necessary. + * + * + * + * Disadvantages: + * + * + * Aliasing: it's possible to represent some rotations with multiple + * different heading, pitch and roll rotations. + * + * + * They can suffer from a problem called Gimbal Lock. A good + * explanation of this can be seen on wikipedia here: + * http://en.wikipedia.org/wiki/Gimbal_lock but basically two + * of the axis of rotation may become aligned and so you loose a + * degree of freedom. For example a pitch of +-90° would mean that + * heading and bank rotate around the same axis. + * + * + * If you use euler angles to orient something in 3D space and try to + * transition between orientations by interpolating the component + * angles you probably wont get the transitions you expect as they may + * not follow the shortest path between the two orientations. + * + * + * There's no standard to what order the component axis rotations are + * applied. The most common convention seems to be what we do in Cogl + * with heading (y-axis), pitch (x-axis) and then roll (z-axis), but + * other software might apply x-axis, y-axis then z-axis or any other + * order so you need to consider this if you are accepting euler + * rotations from some other software. Other software may also use + * slightly different aeronautical terms, such as "yaw" instead of + * "heading" or "bank" instead of "roll". + * + * + * + * To minimize the aliasing issue we may refer to "Canonical Euler" + * angles where heading and roll are restricted to +- 180° and pitch is + * restricted to +- 90°. If pitch is +- 90° bank is set to 0°. + * + * Quaternions don't suffer from Gimbal Lock and they can be nicely + * interpolated between, their disadvantage is that they don't have an + * intuitive representation. + * + * A common practice is to accept angles in the intuitive Euler form + * and convert them to quaternions internally to avoid Gimbal Lock and + * handle interpolations. See cogl_quaternion_init_from_euler(). + */ + +/** + * CoglEuler: + * @heading: Angle to rotate around an object's y axis + * @pitch: Angle to rotate around an object's x axis + * @roll: Angle to rotate around an object's z axis + * + * Represents an ordered rotation first of @heading degrees around an + * object's y axis, then @pitch degrees around an object's x axis and + * finally @roll degrees around an object's z axis. + * + * It's important to understand the that axis are associated + * with the object being rotated, so the axis also rotate in sequence + * with the rotations being applied. + * + * The members of a #CoglEuler can be initialized, for example, with + * cogl_euler_init() and cogl_euler_init_from_quaternion (). + * + * You may also want to look at cogl_quaternion_init_from_euler() if + * you want to do interpolation between 3d rotations. + * + * Since: 2.0 + */ +struct _CoglEuler +{ + /*< public > */ + float heading; + float pitch; + float roll; + + /*< private > */ + /* May cached a quaternion here in the future */ + float padding0; + float padding1; + float padding2; + float padding3; + float padding4; +}; +COGL_STRUCT_SIZE_ASSERT (CoglEuler, 32); + +/** + * cogl_euler_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_euler_get_gtype (void); + +/** + * cogl_euler_init: + * @euler: The #CoglEuler angle to initialize + * @heading: Angle to rotate around an object's y axis + * @pitch: Angle to rotate around an object's x axis + * @roll: Angle to rotate around an object's z axis + * + * Initializes @euler to represent a rotation of @x_angle degrees + * around the x axis, then @y_angle degrees around the y_axis and + * @z_angle degrees around the z axis. + * + * Since: 2.0 + */ +void +cogl_euler_init (CoglEuler *euler, + float heading, + float pitch, + float roll); + +/** + * cogl_euler_init_from_matrix: + * @euler: The #CoglEuler angle to initialize + * @matrix: A #CoglMatrix containing a rotation, but no scaling, + * mirroring or skewing. + * + * Extracts a euler rotation from the given @matrix and + * initializses @euler with the component x, y and z rotation angles. + */ +void +cogl_euler_init_from_matrix (CoglEuler *euler, + const CoglMatrix *matrix); + +/** + * cogl_euler_init_from_quaternion: + * @euler: The #CoglEuler angle to initialize + * @quaternion: A #CoglEuler with the rotation to initialize with + * + * Initializes a @euler rotation with the equivalent rotation + * represented by the given @quaternion. + */ +void +cogl_euler_init_from_quaternion (CoglEuler *euler, + const CoglQuaternion *quaternion); + +/** + * cogl_euler_equal: + * @v1: The first euler angle to compare + * @v2: The second euler angle to compare + * + * Compares the two given euler angles @v1 and @v1 and it they are + * equal returns %TRUE else %FALSE. + * + * This function only checks that all three components rotations + * are numerically equal, it does not consider that some rotations + * can be represented with different component rotations + * + * Returns: %TRUE if @v1 and @v2 are equal else %FALSE. + * Since: 2.0 + */ +CoglBool +cogl_euler_equal (const void *v1, const void *v2); + +/** + * cogl_euler_copy: + * @src: A #CoglEuler to copy + * + * Allocates a new #CoglEuler and initilizes it with the component + * angles of @src. The newly allocated euler should be freed using + * cogl_euler_free(). + * + * Returns: A newly allocated #CoglEuler + * Since: 2.0 + */ +CoglEuler * +cogl_euler_copy (const CoglEuler *src); + +/** + * cogl_euler_free: + * @euler: A #CoglEuler allocated via cogl_euler_copy() + * + * Frees a #CoglEuler that was previously allocated using + * cogl_euler_copy(). + * + * Since: 2.0 + */ +void +cogl_euler_free (CoglEuler *euler); + +COGL_END_DECLS + +#endif /* __COGL_EULER_H */ + diff --git a/cogl/cogl/cogl-feature-private.c b/cogl/cogl/cogl-feature-private.c new file mode 100644 index 0000000..31b421b --- /dev/null +++ b/cogl/cogl/cogl-feature-private.c @@ -0,0 +1,234 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include + +#include "cogl-context-private.h" + +#include "cogl-feature-private.h" +#include "cogl-renderer-private.h" +#include "cogl-private.h" + +CoglBool +_cogl_feature_check (CoglRenderer *renderer, + const char *driver_prefix, + const CoglFeatureData *data, + int gl_major, + int gl_minor, + CoglDriver driver, + char * const *extensions, + void *function_table) + +{ + const char *suffix = NULL; + int func_num; + CoglExtGlesAvailability gles_availability = 0; + CoglBool in_core; + + switch (driver) + { + case COGL_DRIVER_GLES1: + gles_availability = COGL_EXT_IN_GLES; + break; + case COGL_DRIVER_GLES2: + gles_availability = COGL_EXT_IN_GLES2; + + if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 3, 0)) + gles_availability |= COGL_EXT_IN_GLES3; + break; + case COGL_DRIVER_ANY: + g_assert_not_reached (); + case COGL_DRIVER_WEBGL: + /* FIXME: WebGL should probably have its own COGL_EXT_IN_WEBGL flag */ + break; + case COGL_DRIVER_NOP: + case COGL_DRIVER_GL: + case COGL_DRIVER_GL3: + break; + } + + /* First check whether the functions should be directly provided by + GL */ + if (((driver == COGL_DRIVER_GL || + driver == COGL_DRIVER_GL3) && + COGL_CHECK_GL_VERSION (gl_major, gl_minor, + data->min_gl_major, data->min_gl_minor)) || + (data->gles_availability & gles_availability)) + { + suffix = ""; + in_core = TRUE; + } + else + { + /* Otherwise try all of the extensions */ + const char *namespace, *namespace_suffix; + unsigned int namespace_len; + + for (namespace = data->namespaces; + *namespace; + namespace += strlen (namespace) + 1) + { + const char *extension; + GString *full_extension_name = g_string_new (""); + + /* If the namespace part contains a ':' then the suffix for + the function names is different from the name space */ + if ((namespace_suffix = strchr (namespace, ':'))) + { + namespace_len = namespace_suffix - namespace; + namespace_suffix++; + } + else + { + namespace_len = strlen (namespace); + namespace_suffix = namespace; + } + + for (extension = data->extension_names; + *extension; + extension += strlen (extension) + 1) + { + g_string_assign (full_extension_name, driver_prefix); + g_string_append_c (full_extension_name, '_'); + g_string_append_len (full_extension_name, + namespace, namespace_len); + g_string_append_c (full_extension_name, '_'); + g_string_append (full_extension_name, extension); + if (_cogl_check_extension (full_extension_name->str, + extensions)) + break; + } + + g_string_free (full_extension_name, TRUE); + + /* If we found an extension with this namespace then use it + as the suffix */ + if (*extension) + { + suffix = namespace_suffix; + break; + } + } + + in_core = FALSE; + } + + /* If we couldn't find anything that provides the functions then + give up */ + if (suffix == NULL) + goto error; + + /* Try to get all of the entry points */ + for (func_num = 0; data->functions[func_num].name; func_num++) + { + void *func; + char *full_function_name; + + full_function_name = g_strconcat (data->functions[func_num].name, + suffix, NULL); + func = _cogl_renderer_get_proc_address (renderer, + full_function_name, + in_core); + g_free (full_function_name); + + if (func == NULL) + goto error; + + /* Set the function pointer in the context */ + *(void **) ((uint8_t *) function_table + + data->functions[func_num].pointer_offset) = func; + } + + return TRUE; + + /* If the extension isn't found or one of the functions wasn't found + * then set all of the functions pointers to NULL so Cogl can safely + * do feature testing by just looking at the function pointers */ +error: + for (func_num = 0; data->functions[func_num].name; func_num++) + *(void **) ((uint8_t *) function_table + + data->functions[func_num].pointer_offset) = NULL; + + return FALSE; +} + +/* Define a set of arrays containing the functions required from GL + for each feature */ +#define COGL_EXT_BEGIN(name, \ + min_gl_major, min_gl_minor, \ + gles_availability, \ + namespaces, extension_names) \ + static const CoglFeatureFunction cogl_ext_ ## name ## _funcs[] = { +#define COGL_EXT_FUNCTION(ret, name, args) \ + { G_STRINGIFY (name), G_STRUCT_OFFSET (CoglContext, name) }, +#define COGL_EXT_END() \ + { NULL, 0 }, \ + }; +#include "gl-prototypes/cogl-all-functions.h" + +/* Define an array of features */ +#undef COGL_EXT_BEGIN +#define COGL_EXT_BEGIN(name, \ + min_gl_major, min_gl_minor, \ + gles_availability, \ + namespaces, extension_names) \ + { min_gl_major, min_gl_minor, gles_availability, namespaces, \ + extension_names, 0, 0, 0, \ + cogl_ext_ ## name ## _funcs }, +#undef COGL_EXT_FUNCTION +#define COGL_EXT_FUNCTION(ret, name, args) +#undef COGL_EXT_END +#define COGL_EXT_END() + +static const CoglFeatureData +cogl_feature_ext_functions_data[] = + { +#include "gl-prototypes/cogl-all-functions.h" + }; + +void +_cogl_feature_check_ext_functions (CoglContext *context, + int gl_major, + int gl_minor, + char * const *gl_extensions) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS (cogl_feature_ext_functions_data); i++) + _cogl_feature_check (context->display->renderer, + "GL", cogl_feature_ext_functions_data + i, + gl_major, gl_minor, context->driver, + gl_extensions, + context); +} diff --git a/cogl/cogl/cogl-feature-private.h b/cogl/cogl/cogl-feature-private.h new file mode 100644 index 0000000..a342d23 --- /dev/null +++ b/cogl/cogl/cogl-feature-private.h @@ -0,0 +1,106 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_FEATURE_PRIVATE_H +#define __COGL_FEATURE_PRIVATE_H + +#include + + +#define COGL_CHECK_GL_VERSION(driver_major, driver_minor, \ + target_major, target_minor) \ + ((driver_major) > (target_major) || \ + ((driver_major) == (target_major) && (driver_minor) >= (target_minor))) + +typedef enum +{ + COGL_EXT_IN_GLES = (1 << 0), + COGL_EXT_IN_GLES2 = (1 << 1), + COGL_EXT_IN_GLES3 = (1 << 2) +} CoglExtGlesAvailability; + +typedef struct _CoglFeatureFunction CoglFeatureFunction; + +struct _CoglFeatureFunction +{ + /* The name of the function without the "EXT" or "ARB" suffix */ + const char *name; + /* The offset in the context of where to store the function pointer */ + unsigned int pointer_offset; +}; + +typedef struct _CoglFeatureData CoglFeatureData; + +struct _CoglFeatureData +{ + /* A minimum GL version which the functions should be defined in + without needing an extension. Set to 255,255 if it's only + provided in an extension */ + int min_gl_major, min_gl_minor; + /* Flags specifying which versions of GLES the feature is available + in core in */ + CoglExtGlesAvailability gles_availability; + /* \0 separated list of namespaces to try. Eg "EXT\0ARB\0" */ + const char *namespaces; + /* \0 separated list of required extension names without the GL_EXT + or GL_ARB prefix. Any of the extensions must be available for the + feature to be considered available. If the suffix for an + extension is different from the namespace, you can specify it + with a ':' after the namespace */ + const char *extension_names; + /* A set of feature flags to enable if the extension is available */ + CoglFeatureFlags feature_flags; + /* A set of private feature flags to enable if the extension is + * available */ + int feature_flags_private; + /* An optional corresponding winsys feature. */ + CoglWinsysFeature winsys_feature; + /* A list of functions required for this feature. Terminated with a + NULL name */ + const CoglFeatureFunction *functions; +}; + +CoglBool +_cogl_feature_check (CoglRenderer *renderer, + const char *driver_prefix, + const CoglFeatureData *data, + int gl_major, + int gl_minor, + CoglDriver driver, + char * const *extensions, + void *function_table); + +void +_cogl_feature_check_ext_functions (CoglContext *context, + int gl_major, + int gl_minor, + char * const *gl_extensions); + +#endif /* __COGL_FEATURE_PRIVATE_H */ diff --git a/cogl/cogl/cogl-fence-private.h b/cogl/cogl/cogl-fence-private.h new file mode 100644 index 0000000..abbf51f --- /dev/null +++ b/cogl/cogl/cogl-fence-private.h @@ -0,0 +1,66 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Collabora Ltd. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_FENCE_PRIVATE_H__ +#define __COGL_FENCE_PRIVATE_H__ + +#include "cogl-fence.h" +#include "cogl-list.h" +#include "cogl-winsys-private.h" + +typedef enum +{ + FENCE_TYPE_PENDING, +#ifdef GL_ARB_sync + FENCE_TYPE_GL_ARB, +#endif + FENCE_TYPE_WINSYS, + FENCE_TYPE_ERROR +} CoglFenceType; + +struct _CoglFenceClosure +{ + CoglList link; + CoglFramebuffer *framebuffer; + + CoglFenceType type; + void *fence_obj; + + CoglFenceCallback callback; + void *user_data; +}; + +void +_cogl_fence_submit (CoglFenceClosure *fence); + +void +_cogl_fence_cancel_fences_for_framebuffer (CoglFramebuffer *framebuffer); + +#endif /* __COGL_FENCE_PRIVATE_H__ */ diff --git a/cogl/cogl/cogl-fence.c b/cogl/cogl/cogl-fence.c new file mode 100644 index 0000000..f1209be --- /dev/null +++ b/cogl/cogl/cogl-fence.c @@ -0,0 +1,236 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Collabora Ltd. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-fence.h" +#include "cogl-fence-private.h" +#include "cogl-context-private.h" +#include "cogl-winsys-private.h" + +#define FENCE_CHECK_TIMEOUT 5000 /* microseconds */ + +void * +cogl_fence_closure_get_user_data (CoglFenceClosure *closure) +{ + return closure->user_data; +} + +static void +_cogl_fence_check (CoglFenceClosure *fence) +{ + CoglContext *context = fence->framebuffer->context; + + if (fence->type == FENCE_TYPE_WINSYS) + { + const CoglWinsysVtable *winsys = _cogl_context_get_winsys (context); + CoglBool ret; + + ret = winsys->fence_is_complete (context, fence->fence_obj); + if (!ret) + return; + } +#ifdef GL_ARB_sync + else if (fence->type == FENCE_TYPE_GL_ARB) + { + GLenum arb; + + arb = context->glClientWaitSync (fence->fence_obj, + GL_SYNC_FLUSH_COMMANDS_BIT, + 0); + if (arb != GL_ALREADY_SIGNALED && arb != GL_CONDITION_SATISFIED) + return; + } +#endif + + fence->callback (NULL, /* dummy CoglFence object */ + fence->user_data); + cogl_framebuffer_cancel_fence_callback (fence->framebuffer, fence); +} + +static void +_cogl_fence_poll_dispatch (void *source, int revents) +{ + CoglContext *context = source; + CoglFenceClosure *fence, *tmp; + + _cogl_list_for_each_safe (fence, tmp, &context->fences, link) + _cogl_fence_check (fence); +} + +static int64_t +_cogl_fence_poll_prepare (void *source) +{ + CoglContext *context = source; + GList *l; + + /* If there are any pending fences in any of the journals then we + * need to flush the journal otherwise the fence will never be + * hit and the main loop might block forever */ + for (l = context->framebuffers; l; l = l->next) + { + CoglFramebuffer *fb = l->data; + + if (!_cogl_list_empty (&fb->journal->pending_fences)) + _cogl_framebuffer_flush_journal (fb); + } + + if (!_cogl_list_empty (&context->fences)) + return FENCE_CHECK_TIMEOUT; + else + return -1; +} + +void +_cogl_fence_submit (CoglFenceClosure *fence) +{ + CoglContext *context = fence->framebuffer->context; + const CoglWinsysVtable *winsys = _cogl_context_get_winsys (context); + + fence->type = FENCE_TYPE_ERROR; + + if (winsys->fence_add) + { + fence->fence_obj = winsys->fence_add (context); + if (fence->fence_obj) + { + fence->type = FENCE_TYPE_WINSYS; + goto done; + } + } + +#ifdef GL_ARB_sync + if (context->glFenceSync) + { + fence->fence_obj = context->glFenceSync (GL_SYNC_GPU_COMMANDS_COMPLETE, + 0); + if (fence->fence_obj) + { + fence->type = FENCE_TYPE_GL_ARB; + goto done; + } + } +#endif + + done: + _cogl_list_insert (context->fences.prev, &fence->link); + + if (!context->fences_poll_source) + { + context->fences_poll_source = + _cogl_poll_renderer_add_source (context->display->renderer, + _cogl_fence_poll_prepare, + _cogl_fence_poll_dispatch, + context); + } +} + +CoglFenceClosure * +cogl_framebuffer_add_fence_callback (CoglFramebuffer *framebuffer, + CoglFenceCallback callback, + void *user_data) +{ + CoglContext *context = framebuffer->context; + CoglJournal *journal = framebuffer->journal; + CoglFenceClosure *fence; + + if (!COGL_FLAGS_GET (context->features, COGL_FEATURE_ID_FENCE)) + return NULL; + + fence = g_slice_new (CoglFenceClosure); + fence->framebuffer = framebuffer; + fence->callback = callback; + fence->user_data = user_data; + fence->fence_obj = NULL; + + if (journal->entries->len) + { + _cogl_list_insert (journal->pending_fences.prev, &fence->link); + fence->type = FENCE_TYPE_PENDING; + } + else + _cogl_fence_submit (fence); + + return fence; +} + +void +cogl_framebuffer_cancel_fence_callback (CoglFramebuffer *framebuffer, + CoglFenceClosure *fence) +{ + CoglContext *context = framebuffer->context; + + if (fence->type == FENCE_TYPE_PENDING) + { + _cogl_list_remove (&fence->link); + } + else + { + _cogl_list_remove (&fence->link); + + if (fence->type == FENCE_TYPE_WINSYS) + { + const CoglWinsysVtable *winsys = _cogl_context_get_winsys (context); + + winsys->fence_destroy (context, fence->fence_obj); + } +#ifdef GL_ARB_sync + else if (fence->type == FENCE_TYPE_GL_ARB) + { + context->glDeleteSync (fence->fence_obj); + } +#endif + } + + g_slice_free (CoglFenceClosure, fence); +} + +void +_cogl_fence_cancel_fences_for_framebuffer (CoglFramebuffer *framebuffer) +{ + CoglJournal *journal = framebuffer->journal; + CoglContext *context = framebuffer->context; + CoglFenceClosure *fence, *tmp; + + while (!_cogl_list_empty (&journal->pending_fences)) + { + fence = _cogl_container_of (journal->pending_fences.next, + CoglFenceClosure, + link); + cogl_framebuffer_cancel_fence_callback (framebuffer, fence); + } + + _cogl_list_for_each_safe (fence, tmp, &context->fences, link) + { + if (fence->framebuffer == framebuffer) + cogl_framebuffer_cancel_fence_callback (framebuffer, fence); + } +} diff --git a/cogl/cogl/cogl-fence.h b/cogl/cogl/cogl-fence.h new file mode 100644 index 0000000..e268f8f --- /dev/null +++ b/cogl/cogl/cogl-fence.h @@ -0,0 +1,143 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Collabora Ltd. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_FENCE_H__ +#define __COGL_FENCE_H__ + +#include +#include + +/** + * SECTION:cogl-fence + * @short_description: Functions for notification of command completion + * + * Cogl allows notification of GPU command completion; users may mark + * points in the GPU command stream and receive notification when the GPU + * has executed to that point. + */ + +/** + * CoglFence: + * + * An opaque object representing a fence. This type is currently + * unused but in the future may be used to pass extra information + * about the fence completion. + * + * Since: 2.0 + * Stability: Unstable + */ +typedef struct _CoglFence CoglFence; + +/** + * CoglFenceCallback: + * @fence: Unused. In the future this parameter may be used to pass + * extra information about the fence completion but for now it + * should be ignored. + * @user_data: The private data passed to cogl_framebuffer_add_fence_callback() + * + * The callback prototype used with + * cogl_framebuffer_add_fence_callback() for notification of GPU + * command completion. + * + * Since: 2.0 + * Stability: Unstable + */ +typedef void (* CoglFenceCallback) (CoglFence *fence, + void *user_data); + +/** + * CoglFenceClosure: + * + * An opaque type representing one future callback to be made when the + * GPU command stream has passed a certain point. + * + * Since: 2.0 + * Stability: Unstable + */ +typedef struct _CoglFenceClosure CoglFenceClosure; + +/** + * cogl_frame_closure_get_user_data: + * @closure: A #CoglFenceClosure returned from cogl_framebuffer_add_fence() + * + * Returns the user_data submitted to cogl_framebuffer_add_fence() which + * returned a given #CoglFenceClosure. + * + * Since: 2.0 + * Stability: Unstable + */ +void * +cogl_fence_closure_get_user_data (CoglFenceClosure *closure); + +/** + * cogl_framebuffer_add_fence_callback: + * @framebuffer: The #CoglFramebuffer the commands have been submitted to + * @callback: (scope notified): A #CoglFenceCallback to be called when + * all commands submitted to Cogl have been executed + * @user_data: (closure): Private data that will be passed to the callback + * + * Calls the provided callback when all previously-submitted commands have + * been executed by the GPU. + * + * Returns non-NULL if the fence succeeded, or %NULL if it was unable to + * be inserted and the callback will never be called. The user does not + * need to free the closure; it will be freed automatically when the + * callback is called, or cancelled. + * + * Since: 2.0 + * Stability: Unstable + */ +CoglFenceClosure * +cogl_framebuffer_add_fence_callback (CoglFramebuffer *framebuffer, + CoglFenceCallback callback, + void *user_data); + +/** + * cogl_framebuffer_cancel_fence_callback: + * @framebuffer: The #CoglFramebuffer the commands were submitted to + * @closure: The #CoglFenceClosure returned from + * cogl_framebuffer_add_fence_callback() + * + * Removes a fence previously submitted with + * cogl_framebuffer_add_fence_callback(); the callback will not be + * called. + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_framebuffer_cancel_fence_callback (CoglFramebuffer *framebuffer, + CoglFenceClosure *closure); + +#endif /* __COGL_FENCE_H__ */ diff --git a/cogl/cogl/cogl-flags.h b/cogl/cogl/cogl-flags.h new file mode 100644 index 0000000..33633f0 --- /dev/null +++ b/cogl/cogl/cogl-flags.h @@ -0,0 +1,130 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Neil Roberts + */ + +#ifndef __COGL_FLAGS_H +#define __COGL_FLAGS_H + +#include + +#include "cogl-util.h" + +COGL_BEGIN_DECLS + +/* These are macros used to implement a fixed-size array of bits. This + should be used instead of CoglBitmask when the maximum bit number + that will be set is known at compile time, for example when setting + for recording a set of known available features */ + +/* The bits are stored in an array of unsigned longs. To use these + macros, you would typically have an enum defining the available + bits with an extra last enum to define the maximum value. Then to + store the flags you would declare an array of unsigned longs sized + using COGL_FLAGS_N_LONGS_FOR_SIZE, eg: + + typedef enum { FEATURE_A, FEATURE_B, FEATURE_C, N_FEATURES } Features; + + unsigned long feature_flags[COGL_FLAGS_N_LONGS_FOR_SIZE (N_FEATURES)]; +*/ + +#define COGL_FLAGS_N_LONGS_FOR_SIZE(size) \ + (((size) + \ + (sizeof (unsigned long) * 8 - 1)) \ + / (sizeof (unsigned long) * 8)) + +/* @flag is expected to be constant so these should result in a + constant expression. This means that setting a flag is equivalent + to just setting in a bit in a global variable at a known + location */ +#define COGL_FLAGS_GET_INDEX(flag) \ + ((flag) / (sizeof (unsigned long) * 8)) +#define COGL_FLAGS_GET_MASK(flag) \ + (1UL << ((unsigned long) (flag) & \ + (sizeof (unsigned long) * 8 - 1))) + +#define COGL_FLAGS_GET(array, flag) \ + (!!((array)[COGL_FLAGS_GET_INDEX (flag)] & \ + COGL_FLAGS_GET_MASK (flag))) + +/* The expectation here is that @value will be constant so the if + statement will be optimised out */ +#define COGL_FLAGS_SET(array, flag, value) \ + G_STMT_START { \ + if (value) \ + ((array)[COGL_FLAGS_GET_INDEX (flag)] |= \ + COGL_FLAGS_GET_MASK (flag)); \ + else \ + ((array)[COGL_FLAGS_GET_INDEX (flag)] &= \ + ~COGL_FLAGS_GET_MASK (flag)); \ + } G_STMT_END + +/* Macros to help iterate an array of flags. It should be used like + * this: + * + * int n_longs = COGL_FLAGS_N_LONGS_FOR_SIZE (...); + * unsigned long flags[n_longs]; + * int bit_num; + * + * COGL_FLAGS_FOREACH_START (flags, n_longs, bit_num) + * { + * do_something_with_the_bit (bit_num); + * } + * COGL_FLAGS_FOREACH_END; + */ +#define COGL_FLAGS_FOREACH_START(array, n_longs, bit) \ + G_STMT_START { \ + const unsigned long *_p = (array); \ + int _n_longs = (n_longs); \ + int _i; \ + \ + for (_i = 0; _i < _n_longs; _i++) \ + { \ + unsigned long _mask = *(_p++); \ + \ + (bit) = _i * sizeof (unsigned long) * 8 - 1; \ + \ + while (_mask) \ + { \ + int _next_bit = _cogl_util_ffsl (_mask); \ + (bit) += _next_bit; \ + /* This odd two-part shift is to avoid */ \ + /* shifting by sizeof (long)*8 which has */ \ + /* undefined results according to the */ \ + /* C spec (and seems to be a no-op in */ \ + /* practice) */ \ + _mask = (_mask >> (_next_bit - 1)) >> 1; \ + +#define COGL_FLAGS_FOREACH_END \ + } } } G_STMT_END + +COGL_END_DECLS + +#endif /* __COGL_FLAGS_H */ + diff --git a/cogl/cogl/cogl-frame-info-private.h b/cogl/cogl/cogl-frame-info-private.h new file mode 100644 index 0000000..16d393e --- /dev/null +++ b/cogl/cogl/cogl-frame-info-private.h @@ -0,0 +1,52 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_FRAME_INFO_PRIVATE_H +#define __COGL_FRAME_INFO_PRIVATE_H + +#include "cogl-frame-info.h" +#include "cogl-object-private.h" + +struct _CoglFrameInfo +{ + CoglObject _parent; + + int64_t frame_counter; + int64_t presentation_time; + float refresh_rate; + + int64_t global_frame_counter; + + CoglOutput *output; +}; + +CoglFrameInfo *_cogl_frame_info_new (void); + +#endif /* __COGL_FRAME_INFO_PRIVATE_H */ diff --git a/cogl/cogl/cogl-frame-info.c b/cogl/cogl/cogl-frame-info.c new file mode 100644 index 0000000..4e7ac3a --- /dev/null +++ b/cogl/cogl/cogl-frame-info.c @@ -0,0 +1,87 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-frame-info-private.h" +#include "cogl-gtype-private.h" + +static void _cogl_frame_info_free (CoglFrameInfo *info); + +COGL_OBJECT_DEFINE (FrameInfo, frame_info); +COGL_GTYPE_DEFINE_CLASS (FrameInfo, frame_info); + +CoglFrameInfo * +_cogl_frame_info_new (void) +{ + CoglFrameInfo *info; + + info = g_slice_new0 (CoglFrameInfo); + + return _cogl_frame_info_object_new (info); +} + +static void +_cogl_frame_info_free (CoglFrameInfo *info) +{ + g_slice_free (CoglFrameInfo, info); +} + +int64_t +cogl_frame_info_get_frame_counter (CoglFrameInfo *info) +{ + return info->frame_counter; +} + +int64_t +cogl_frame_info_get_presentation_time (CoglFrameInfo *info) +{ + return info->presentation_time; +} + +float +cogl_frame_info_get_refresh_rate (CoglFrameInfo *info) +{ + return info->refresh_rate; +} + +CoglOutput * +cogl_frame_info_get_output (CoglFrameInfo *info) +{ + return info->output; +} + +int64_t +cogl_frame_info_get_global_frame_counter (CoglFrameInfo *info) +{ + return info->global_frame_counter; +} diff --git a/cogl/cogl/cogl-frame-info.h b/cogl/cogl/cogl-frame-info.h new file mode 100644 index 0000000..a87f7e1 --- /dev/null +++ b/cogl/cogl/cogl-frame-info.h @@ -0,0 +1,149 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Owen Taylor + */ +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_FRAME_INFO_H +#define __COGL_FRAME_INFO_H + +#include +#include + +#include +#include + +G_BEGIN_DECLS + +typedef struct _CoglFrameInfo CoglFrameInfo; +#define COGL_FRAME_INFO(X) ((CoglFrameInfo *)(X)) + +/** + * cogl_frame_info_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_frame_info_get_gtype (void); + +/** + * cogl_is_frame_info: + * @object: A #CoglObject pointer + * + * Gets whether the given object references a #CoglFrameInfo. + * + * Return value: %TRUE if the object references a #CoglFrameInfo + * and %FALSE otherwise. + * Since: 2.0 + * Stability: unstable + */ +CoglBool +cogl_is_frame_info (void *object); + +/** + * cogl_frame_info_get_frame_counter: + * @info: a #CoglFrameInfo object + * + * Gets the frame counter for the #CoglOnscreen that corresponds + * to this frame. + * + * Return value: The frame counter value + * Since: 1.14 + * Stability: unstable + */ +int64_t cogl_frame_info_get_frame_counter (CoglFrameInfo *info); + +/** + * cogl_frame_info_get_presentation_time: + * @info: a #CoglFrameInfo object + * + * Gets the presentation time for the frame. This is the time at which + * the frame became visible to the user. + * + * The presentation time measured in nanoseconds is based on a + * monotonic time source. The time source is not necessarily + * correlated with system/wall clock time and may represent the time + * elapsed since some undefined system event such as when the system + * last booted. + * + * Linux kernel version less that 3.8 can result in + * non-monotonic timestamps being reported when using a drm based + * OpenGL driver. Also some buggy Mesa drivers up to 9.0.1 may also + * incorrectly report non-monotonic timestamps. + * + * Return value: the presentation time for the frame + * Since: 1.14 + * Stability: unstable + */ +int64_t cogl_frame_info_get_presentation_time (CoglFrameInfo *info); + +/** + * cogl_frame_info_get_refresh_rate: + * @info: a #CoglFrameInfo object + * + * Gets the refresh rate in Hertz for the output that the frame was on + * at the time the frame was presented. + * + * Some platforms can't associate a #CoglOutput with a + * #CoglFrameInfo object but are able to report a refresh rate via + * this api. Therefore if you need this information then this api is + * more reliable than using cogl_frame_info_get_output() followed by + * cogl_output_get_refresh_rate(). + * + * Return value: the refresh rate in Hertz + * Since: 1.14 + * Stability: unstable + */ +float cogl_frame_info_get_refresh_rate (CoglFrameInfo *info); + +/** + * cogl_frame_info_get_output: + * @info: a #CoglFrameInfo object + * + * Gets the #CoglOutput that the swapped frame was presented to. + * + * Return value: (transfer none): The #CoglOutput that the frame was + * presented to, or %NULL if this could not be determined. + * Since: 1.14 + * Stability: unstable + */ +CoglOutput * +cogl_frame_info_get_output (CoglFrameInfo *info); + +/** + * cogl_frame_info_get_global_frame_counter: (skip) + */ +int64_t cogl_frame_info_get_global_frame_counter (CoglFrameInfo *info); + +G_END_DECLS + +#endif /* __COGL_FRAME_INFO_H */ diff --git a/cogl/cogl/cogl-framebuffer-private.h b/cogl/cogl/cogl-framebuffer-private.h new file mode 100644 index 0000000..99ac2fb --- /dev/null +++ b/cogl/cogl/cogl-framebuffer-private.h @@ -0,0 +1,514 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_FRAMEBUFFER_PRIVATE_H +#define __COGL_FRAMEBUFFER_PRIVATE_H + +#include "cogl-object-private.h" +#include "cogl-matrix-stack-private.h" +#include "cogl-journal-private.h" +#include "cogl-winsys-private.h" +#include "cogl-attribute-private.h" +#include "cogl-offscreen.h" +#include "cogl-gl-header.h" +#include "cogl-clip-stack.h" + +#ifdef COGL_HAS_XLIB_SUPPORT +#include +#endif + +#ifdef COGL_HAS_GLX_SUPPORT +#include +#include +#endif + +typedef enum _CoglFramebufferType { + COGL_FRAMEBUFFER_TYPE_ONSCREEN, + COGL_FRAMEBUFFER_TYPE_OFFSCREEN +} CoglFramebufferType; + +typedef struct +{ + CoglSwapChain *swap_chain; + CoglBool need_stencil; + int samples_per_pixel; + CoglBool swap_throttled; + CoglBool depth_texture_enabled; + CoglBool stereo_enabled; +} CoglFramebufferConfig; + +/* Flags to pass to _cogl_offscreen_new_with_texture_full */ +typedef enum +{ + COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL = 1 +} CoglOffscreenFlags; + +/* XXX: The order of these indices determines the order they are + * flushed. + * + * Flushing clip state may trash the modelview and projection matrices + * so we must do it before flushing the matrices. + */ +typedef enum _CoglFramebufferStateIndex +{ + COGL_FRAMEBUFFER_STATE_INDEX_BIND = 0, + COGL_FRAMEBUFFER_STATE_INDEX_VIEWPORT = 1, + COGL_FRAMEBUFFER_STATE_INDEX_CLIP = 2, + COGL_FRAMEBUFFER_STATE_INDEX_DITHER = 3, + COGL_FRAMEBUFFER_STATE_INDEX_MODELVIEW = 4, + COGL_FRAMEBUFFER_STATE_INDEX_PROJECTION = 5, + COGL_FRAMEBUFFER_STATE_INDEX_COLOR_MASK = 6, + COGL_FRAMEBUFFER_STATE_INDEX_FRONT_FACE_WINDING = 7, + COGL_FRAMEBUFFER_STATE_INDEX_DEPTH_WRITE = 8, + COGL_FRAMEBUFFER_STATE_INDEX_STEREO_MODE = 9, + COGL_FRAMEBUFFER_STATE_INDEX_MAX = 10 +} CoglFramebufferStateIndex; + +typedef enum _CoglFramebufferState +{ + COGL_FRAMEBUFFER_STATE_BIND = 1<<0, + COGL_FRAMEBUFFER_STATE_VIEWPORT = 1<<1, + COGL_FRAMEBUFFER_STATE_CLIP = 1<<2, + COGL_FRAMEBUFFER_STATE_DITHER = 1<<3, + COGL_FRAMEBUFFER_STATE_MODELVIEW = 1<<4, + COGL_FRAMEBUFFER_STATE_PROJECTION = 1<<5, + COGL_FRAMEBUFFER_STATE_COLOR_MASK = 1<<6, + COGL_FRAMEBUFFER_STATE_FRONT_FACE_WINDING = 1<<7, + COGL_FRAMEBUFFER_STATE_DEPTH_WRITE = 1<<8, + COGL_FRAMEBUFFER_STATE_STEREO_MODE = 1<<9 +} CoglFramebufferState; + +#define COGL_FRAMEBUFFER_STATE_ALL ((1<config to configure if we want a depth or stencil buffer so + * we can get rid of these flags */ + CoglOffscreenFlags create_flags; +}; + +void +_cogl_framebuffer_init (CoglFramebuffer *framebuffer, + CoglContext *ctx, + CoglFramebufferType type, + int width, + int height); + +/* XXX: For a public api we might instead want a way to explicitly + * set the _premult status of a framebuffer or what components we + * care about instead of exposing the CoglPixelFormat + * internal_format. + * + * The current use case for this api is where we create an offscreen + * framebuffer for a shared atlas texture that has a format of + * RGBA_8888 disregarding the premultiplied alpha status for + * individual atlased textures or whether the alpha component is being + * discarded. We want to overried the internal_format that will be + * derived from the texture. + */ +void +_cogl_framebuffer_set_internal_format (CoglFramebuffer *framebuffer, + CoglPixelFormat internal_format); + +void _cogl_framebuffer_free (CoglFramebuffer *framebuffer); + +const CoglWinsysVtable * +_cogl_framebuffer_get_winsys (CoglFramebuffer *framebuffer); + +void +_cogl_framebuffer_clear_without_flush4f (CoglFramebuffer *framebuffer, + unsigned long buffers, + float red, + float green, + float blue, + float alpha); + +void +_cogl_framebuffer_mark_clear_clip_dirty (CoglFramebuffer *framebuffer); + +void +_cogl_framebuffer_mark_mid_scene (CoglFramebuffer *framebuffer); + +/* + * _cogl_framebuffer_get_clip_stack: + * @framebuffer: A #CoglFramebuffer + * + * Gets a pointer to the current clip stack. This can be used to later + * return to the same clip stack state with + * _cogl_framebuffer_set_clip_stack(). A reference is not taken on the + * stack so if you want to keep it you should call + * _cogl_clip_stack_ref(). + * + * Return value: a pointer to the @framebuffer clip stack. + */ +CoglClipStack * +_cogl_framebuffer_get_clip_stack (CoglFramebuffer *framebuffer); + +/* + * _cogl_framebuffer_set_clip_stack: + * @framebuffer: A #CoglFramebuffer + * @stack: a pointer to the replacement clip stack + * + * Replaces the @framebuffer clip stack with @stack. + */ +void +_cogl_framebuffer_set_clip_stack (CoglFramebuffer *framebuffer, + CoglClipStack *stack); + +CoglMatrixStack * +_cogl_framebuffer_get_modelview_stack (CoglFramebuffer *framebuffer); + +CoglMatrixStack * +_cogl_framebuffer_get_projection_stack (CoglFramebuffer *framebuffer); + +void +_cogl_framebuffer_add_dependency (CoglFramebuffer *framebuffer, + CoglFramebuffer *dependency); + +void +_cogl_framebuffer_remove_all_dependencies (CoglFramebuffer *framebuffer); + +void +_cogl_framebuffer_flush_journal (CoglFramebuffer *framebuffer); + +void +_cogl_framebuffer_flush_dependency_journals (CoglFramebuffer *framebuffer); + +void +_cogl_framebuffer_flush_state (CoglFramebuffer *draw_buffer, + CoglFramebuffer *read_buffer, + CoglFramebufferState state); + +CoglFramebuffer * +_cogl_get_read_framebuffer (void); + +GSList * +_cogl_create_framebuffer_stack (void); + +void +_cogl_free_framebuffer_stack (GSList *stack); + +/* + * _cogl_offscreen_new_with_texture_full: + * @texture: A #CoglTexture pointer + * @create_flags: Flags specifying how to create the FBO + * @level: The mipmap level within the texture to target + * + * Creates a new offscreen buffer which will target the given + * texture. By default the buffer will have a depth and stencil + * buffer. This can be disabled by passing + * %COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL in @create_flags. + * + * Return value: the new CoglOffscreen object. + */ +CoglOffscreen * +_cogl_offscreen_new_with_texture_full (CoglTexture *texture, + CoglOffscreenFlags create_flags, + int level); + +/* + * _cogl_push_framebuffers: + * @draw_buffer: A pointer to the buffer used for drawing + * @read_buffer: A pointer to the buffer used for reading back pixels + * + * Redirects drawing and reading to the specified framebuffers as in + * cogl_push_framebuffer() except that it allows the draw and read + * buffer to be different. The buffers are pushed as a pair so that + * they can later both be restored with a single call to + * cogl_pop_framebuffer(). + */ +void +_cogl_push_framebuffers (CoglFramebuffer *draw_buffer, + CoglFramebuffer *read_buffer); + +/* + * _cogl_blit_framebuffer: + * @src: The source #CoglFramebuffer + * @dest: The destination #CoglFramebuffer + * @src_x: Source x position + * @src_y: Source y position + * @dst_x: Destination x position + * @dst_y: Destination y position + * @width: Width of region to copy + * @height: Height of region to copy + * + * This blits a region of the color buffer of the current draw buffer + * to the current read buffer. The draw and read buffers can be set up + * using _cogl_push_framebuffers(). This function should only be + * called if the COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT feature is + * advertised. The two buffers must both be offscreen and have the + * same format. + * + * Note that this function differs a lot from the glBlitFramebuffer + * function provided by the GL_EXT_framebuffer_blit extension. Notably + * it doesn't support having different sizes for the source and + * destination rectangle. This isn't supported by the corresponding + * GL_ANGLE_framebuffer_blit extension on GLES2.0 and it doesn't seem + * like a particularly useful feature. If the application wanted to + * scale the results it may make more sense to draw a primitive + * instead. + * + * We can only really support blitting between two offscreen buffers + * for this function on GLES2.0. This is because we effectively render + * upside down to offscreen buffers to maintain Cogl's representation + * of the texture coordinate system where 0,0 is the top left of the + * texture. If we were to blit from an offscreen to an onscreen buffer + * then we would need to mirror the blit along the x-axis but the GLES + * extension does not support this. + * + * The GL function is documented to be affected by the scissor. This + * function therefore ensure that an empty clip stack is flushed + * before performing the blit which means the scissor is effectively + * ignored. + * + * The function also doesn't support specifying the buffers to copy + * and instead only the color buffer is copied. When copying the depth + * or stencil buffers the extension on GLES2.0 only supports copying + * the full buffer which would be awkward to document with this + * API. If we wanted to support that feature it may be better to have + * a separate function to copy the entire buffer for a given mask. + */ +void +_cogl_blit_framebuffer (CoglFramebuffer *src, + CoglFramebuffer *dest, + int src_x, + int src_y, + int dst_x, + int dst_y, + int width, + int height); + +void +_cogl_framebuffer_push_projection (CoglFramebuffer *framebuffer); + +void +_cogl_framebuffer_pop_projection (CoglFramebuffer *framebuffer); + +void +_cogl_framebuffer_save_clip_stack (CoglFramebuffer *framebuffer); + +void +_cogl_framebuffer_restore_clip_stack (CoglFramebuffer *framebuffer); + +void +_cogl_framebuffer_unref (CoglFramebuffer *framebuffer); + +/* This can be called directly by the CoglJournal to draw attributes + * skipping the implicit journal flush, the framebuffer flush and + * pipeline validation. */ +void +_cogl_framebuffer_draw_attributes (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglVerticesMode mode, + int first_vertex, + int n_vertices, + CoglAttribute **attributes, + int n_attributes, + CoglDrawFlags flags); + +void +_cogl_framebuffer_draw_indexed_attributes (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglVerticesMode mode, + int first_vertex, + int n_vertices, + CoglIndices *indices, + CoglAttribute **attributes, + int n_attributes, + CoglDrawFlags flags); + +gboolean +_cogl_framebuffer_try_creating_gl_fbo (CoglContext *ctx, + CoglTexture *texture, + int texture_level, + int texture_level_width, + int texture_level_height, + CoglTexture *depth_texture, + CoglFramebufferConfig *config, + CoglOffscreenAllocateFlags flags, + CoglGLFramebuffer *gl_framebuffer); + +unsigned long +_cogl_framebuffer_compare (CoglFramebuffer *a, + CoglFramebuffer *b, + unsigned long state); + +static inline CoglMatrixEntry * +_cogl_framebuffer_get_modelview_entry (CoglFramebuffer *framebuffer) +{ + CoglMatrixStack *modelview_stack = + _cogl_framebuffer_get_modelview_stack (framebuffer); + return modelview_stack->last_entry; +} + +static inline CoglMatrixEntry * +_cogl_framebuffer_get_projection_entry (CoglFramebuffer *framebuffer) +{ + CoglMatrixStack *projection_stack = + _cogl_framebuffer_get_projection_stack (framebuffer); + return projection_stack->last_entry; +} + +CoglBool +_cogl_framebuffer_read_pixels_into_bitmap (CoglFramebuffer *framebuffer, + int x, + int y, + CoglReadPixelsFlags source, + CoglBitmap *bitmap, + CoglError **error); + +/* + * _cogl_framebuffer_get_stencil_bits: + * @framebuffer: a pointer to a #CoglFramebuffer + * + * Retrieves the number of stencil bits of @framebuffer + * + * Return value: the number of bits + * + * Since: 2.0 + * Stability: unstable + */ +int +_cogl_framebuffer_get_stencil_bits (CoglFramebuffer *framebuffer); + +#endif /* __COGL_FRAMEBUFFER_PRIVATE_H */ diff --git a/cogl/cogl/cogl-framebuffer.c b/cogl/cogl/cogl-framebuffer.c new file mode 100644 index 0000000..55b9e37 --- /dev/null +++ b/cogl/cogl/cogl-framebuffer.c @@ -0,0 +1,2550 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include + +#include "cogl-debug.h" +#include "cogl-context-private.h" +#include "cogl-display-private.h" +#include "cogl-renderer-private.h" +#include "cogl-object-private.h" +#include "cogl-util.h" +#include "cogl-texture-private.h" +#include "cogl-framebuffer-private.h" +#include "cogl-onscreen-template-private.h" +#include "cogl-clip-stack.h" +#include "cogl-journal-private.h" +#include "cogl-winsys-private.h" +#include "cogl-pipeline-state-private.h" +#include "cogl-matrix-private.h" +#include "cogl-primitive-private.h" +#include "cogl-offscreen.h" +#include "cogl1-context.h" +#include "cogl-private.h" +#include "cogl-primitives-private.h" +#include "cogl-error-private.h" +#include "cogl-texture-gl-private.h" +#include "cogl-gtype-private.h" + +extern CoglObjectClass _cogl_onscreen_class; + +#ifdef COGL_ENABLE_DEBUG +static CoglUserDataKey wire_pipeline_key; +#endif + +static void _cogl_offscreen_free (CoglOffscreen *offscreen); + +COGL_OBJECT_DEFINE_WITH_CODE_GTYPE (Offscreen, offscreen, + _cogl_offscreen_class.virt_unref = + _cogl_framebuffer_unref); +COGL_GTYPE_DEFINE_CLASS (Offscreen, offscreen); +COGL_OBJECT_DEFINE_DEPRECATED_REF_COUNTING (offscreen); +COGL_GTYPE_DEFINE_INTERFACE (Framebuffer, framebuffer); + +/* XXX: + * The CoglObject macros don't support any form of inheritance, so for + * now we implement the CoglObject support for the CoglFramebuffer + * abstract class manually. + */ + +uint32_t +cogl_framebuffer_error_quark (void) +{ + return g_quark_from_static_string ("cogl-framebuffer-error-quark"); +} + +CoglBool +cogl_is_framebuffer (void *object) +{ + CoglObject *obj = object; + + if (obj == NULL) + return FALSE; + + return (obj->klass == &_cogl_onscreen_class || + obj->klass == &_cogl_offscreen_class); +} + +void +_cogl_framebuffer_init (CoglFramebuffer *framebuffer, + CoglContext *ctx, + CoglFramebufferType type, + int width, + int height) +{ + framebuffer->context = ctx; + + framebuffer->type = type; + framebuffer->width = width; + framebuffer->height = height; + framebuffer->internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE; + framebuffer->viewport_x = 0; + framebuffer->viewport_y = 0; + framebuffer->viewport_width = width; + framebuffer->viewport_height = height; + framebuffer->viewport_age = 0; + framebuffer->viewport_age_for_scissor_workaround = -1; + framebuffer->dither_enabled = TRUE; + framebuffer->depth_writing_enabled = TRUE; + + framebuffer->modelview_stack = cogl_matrix_stack_new (ctx); + framebuffer->projection_stack = cogl_matrix_stack_new (ctx); + + framebuffer->dirty_bitmasks = TRUE; + + framebuffer->color_mask = COGL_COLOR_MASK_ALL; + + framebuffer->samples_per_pixel = 0; + + framebuffer->clip_stack = NULL; + + framebuffer->journal = _cogl_journal_new (framebuffer); + + /* Ensure we know the framebuffer->clear_color* members can't be + * referenced for our fast-path read-pixel optimization (see + * _cogl_journal_try_read_pixel()) until some region of the + * framebuffer is initialized. + */ + framebuffer->clear_clip_dirty = TRUE; + + /* XXX: We have to maintain a central list of all framebuffers + * because at times we need to be able to flush all known journals. + * + * Examples where we need to flush all journals are: + * - because journal entries can reference OpenGL texture + * coordinates that may not survive texture-atlas reorganization + * so we need the ability to flush those entries. + * - because although we generally advise against modifying + * pipelines after construction we have to handle that possibility + * and since pipelines may be referenced in journal entries we + * need to be able to flush them before allowing the pipelines to + * be changed. + * + * Note we don't maintain a list of journals and associate + * framebuffers with journals by e.g. having a journal->framebuffer + * reference since that would introduce a circular reference. + * + * Note: As a future change to try and remove the need to index all + * journals it might be possible to defer resolving of OpenGL + * texture coordinates for rectangle primitives until we come to + * flush a journal. This would mean for instance that a single + * rectangle entry in a journal could later be expanded into + * multiple quad primitives to handle sliced textures but would mean + * we don't have to worry about retaining references to OpenGL + * texture coordinates that may later become invalid. + */ + ctx->framebuffers = g_list_prepend (ctx->framebuffers, framebuffer); +} + +void +_cogl_framebuffer_set_internal_format (CoglFramebuffer *framebuffer, + CoglPixelFormat internal_format) +{ + framebuffer->internal_format = internal_format; +} + +void +_cogl_framebuffer_free (CoglFramebuffer *framebuffer) +{ + CoglContext *ctx = framebuffer->context; + + _cogl_fence_cancel_fences_for_framebuffer (framebuffer); + + _cogl_clip_stack_unref (framebuffer->clip_stack); + + cogl_object_unref (framebuffer->modelview_stack); + framebuffer->modelview_stack = NULL; + + cogl_object_unref (framebuffer->projection_stack); + framebuffer->projection_stack = NULL; + + cogl_object_unref (framebuffer->journal); + + if (ctx->viewport_scissor_workaround_framebuffer == framebuffer) + ctx->viewport_scissor_workaround_framebuffer = NULL; + + ctx->framebuffers = g_list_remove (ctx->framebuffers, framebuffer); + + if (ctx->current_draw_buffer == framebuffer) + ctx->current_draw_buffer = NULL; + if (ctx->current_read_buffer == framebuffer) + ctx->current_read_buffer = NULL; +} + +const CoglWinsysVtable * +_cogl_framebuffer_get_winsys (CoglFramebuffer *framebuffer) +{ + return framebuffer->context->display->renderer->winsys_vtable; +} + +/* This version of cogl_clear can be used internally as an alternative + * to avoid flushing the journal or the framebuffer state. This is + * needed when doing operations that may be called whiling flushing + * the journal */ +void +_cogl_framebuffer_clear_without_flush4f (CoglFramebuffer *framebuffer, + unsigned long buffers, + float red, + float green, + float blue, + float alpha) +{ + CoglContext *ctx = framebuffer->context; + + if (!buffers) + { + static CoglBool shown = FALSE; + + if (!shown) + { + g_warning ("You should specify at least one auxiliary buffer " + "when calling cogl_framebuffer_clear"); + } + + return; + } + + ctx->driver_vtable->framebuffer_clear (framebuffer, + buffers, + red, green, blue, alpha); +} + +void +_cogl_framebuffer_mark_clear_clip_dirty (CoglFramebuffer *framebuffer) +{ + framebuffer->clear_clip_dirty = TRUE; +} + +void +_cogl_framebuffer_mark_mid_scene (CoglFramebuffer *framebuffer) +{ + framebuffer->mid_scene = TRUE; +} + +void +cogl_framebuffer_clear4f (CoglFramebuffer *framebuffer, + unsigned long buffers, + float red, + float green, + float blue, + float alpha) +{ + CoglContext *ctx = framebuffer->context; + CoglClipStack *clip_stack = _cogl_framebuffer_get_clip_stack (framebuffer); + int scissor_x0; + int scissor_y0; + int scissor_x1; + int scissor_y1; + CoglBool saved_viewport_scissor_workaround; + + _cogl_clip_stack_get_bounds (clip_stack, + &scissor_x0, &scissor_y0, + &scissor_x1, &scissor_y1); + + /* NB: the previous clear could have had an arbitrary clip. + * NB: everything for the last frame might still be in the journal + * but we can't assume anything about how each entry was + * clipped. + * NB: Clutter will scissor its pick renders which would mean all + * journal entries have a common ClipStack entry, but without + * a layering violation Cogl has to explicitly walk the journal + * entries to determine if this is the case. + * NB: We have a software only read-pixel optimization in the + * journal that determines the color at a given framebuffer + * coordinate for simple scenes without rendering with the GPU. + * When Clutter is hitting this fast-path we can expect to + * receive calls to clear the framebuffer with an un-flushed + * journal. + * NB: To fully support software based picking for Clutter we + * need to be able to reliably detect when the contents of a + * journal can be discarded and when we can skip the call to + * glClear because it matches the previous clear request. + */ + + /* Note: we don't check for the stencil buffer being cleared here + * since there isn't any public cogl api to manipulate the stencil + * buffer. + * + * Note: we check for an exact clip match here because + * 1) a smaller clip could mean existing journal entries may + * need to contribute to regions outside the new clear-clip + * 2) a larger clip would mean we need to issue a real + * glClear and we only care about cases avoiding a + * glClear. + * + * Note: Comparing without an epsilon is considered + * appropriate here. + */ + if (buffers & COGL_BUFFER_BIT_COLOR && + buffers & COGL_BUFFER_BIT_DEPTH && + !framebuffer->clear_clip_dirty && + framebuffer->clear_color_red == red && + framebuffer->clear_color_green == green && + framebuffer->clear_color_blue == blue && + framebuffer->clear_color_alpha == alpha && + scissor_x0 == framebuffer->clear_clip_x0 && + scissor_y0 == framebuffer->clear_clip_y0 && + scissor_x1 == framebuffer->clear_clip_x1 && + scissor_y1 == framebuffer->clear_clip_y1) + { + /* NB: We only have to consider the clip state of journal + * entries if the current clear is clipped since otherwise we + * know every pixel of the framebuffer is affected by the clear + * and so all journal entries become redundant and can simply be + * discarded. + */ + if (clip_stack) + { + /* + * Note: the function for checking the journal entries is + * quite strict. It avoids detailed checking of all entry + * clip_stacks by only checking the details of the first + * entry and then it only verifies that the remaining + * entries share the same clip_stack ancestry. This means + * it's possible for some false negatives here but that will + * just result in us falling back to a real clear. + */ + if (_cogl_journal_all_entries_within_bounds (framebuffer->journal, + scissor_x0, scissor_y0, + scissor_x1, scissor_y1)) + { + _cogl_journal_discard (framebuffer->journal); + goto cleared; + } + } + else + { + _cogl_journal_discard (framebuffer->journal); + goto cleared; + } + } + + COGL_NOTE (DRAW, "Clear begin"); + + _cogl_framebuffer_flush_journal (framebuffer); + + /* XXX: ONGOING BUG: Intel viewport scissor + * + * The semantics of cogl_framebuffer_clear() are that it should not + * be affected by the current viewport and so if we are currently + * applying a workaround for viewport scissoring we need to + * temporarily disable the workaround before clearing so any + * special scissoring for the workaround will be removed first. + * + * Note: we only need to disable the workaround if the current + * viewport doesn't match the framebuffer's size since otherwise + * the workaround wont affect clearing anyway. + */ + if (ctx->needs_viewport_scissor_workaround && + (framebuffer->viewport_x != 0 || + framebuffer->viewport_y != 0 || + framebuffer->viewport_width != framebuffer->width || + framebuffer->viewport_height != framebuffer->height)) + { + saved_viewport_scissor_workaround = TRUE; + ctx->needs_viewport_scissor_workaround = FALSE; + ctx->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_CLIP; + } + else + saved_viewport_scissor_workaround = FALSE; + + /* NB: _cogl_framebuffer_flush_state may disrupt various state (such + * as the pipeline state) when flushing the clip stack, so should + * always be done first when preparing to draw. */ + _cogl_framebuffer_flush_state (framebuffer, framebuffer, + COGL_FRAMEBUFFER_STATE_ALL); + + _cogl_framebuffer_clear_without_flush4f (framebuffer, buffers, + red, green, blue, alpha); + + /* XXX: ONGOING BUG: Intel viewport scissor + * + * See comment about temporarily disabling this workaround above + */ + if (saved_viewport_scissor_workaround) + { + ctx->needs_viewport_scissor_workaround = TRUE; + ctx->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_CLIP; + } + + /* This is a debugging variable used to visually display the quad + * batches from the journal. It is reset here to increase the + * chances of getting the same colours for each frame during an + * animation */ + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_RECTANGLES)) && + buffers & COGL_BUFFER_BIT_COLOR) + { + framebuffer->context->journal_rectangles_color = 1; + } + + COGL_NOTE (DRAW, "Clear end"); + +cleared: + + _cogl_framebuffer_mark_mid_scene (framebuffer); + _cogl_framebuffer_mark_clear_clip_dirty (framebuffer); + + if (buffers & COGL_BUFFER_BIT_COLOR && buffers & COGL_BUFFER_BIT_DEPTH) + { + /* For our fast-path for reading back a single pixel of simple + * scenes where the whole frame is in the journal we need to + * track the cleared color of the framebuffer in case the point + * read doesn't intersect any of the journal rectangles. */ + framebuffer->clear_clip_dirty = FALSE; + framebuffer->clear_color_red = red; + framebuffer->clear_color_green = green; + framebuffer->clear_color_blue = blue; + framebuffer->clear_color_alpha = alpha; + + /* NB: A clear may be scissored so we need to track the extents + * that the clear is applicable too... */ + if (clip_stack) + { + _cogl_clip_stack_get_bounds (clip_stack, + &framebuffer->clear_clip_x0, + &framebuffer->clear_clip_y0, + &framebuffer->clear_clip_x1, + &framebuffer->clear_clip_y1); + } + else + { + /* FIXME: set degenerate clip */ + } + } +} + +/* Note: the 'buffers' and 'color' arguments were switched around on + * purpose compared to the original cogl_clear API since it was odd + * that you would be expected to specify a color before even + * necessarily choosing to clear the color buffer. + */ +void +cogl_framebuffer_clear (CoglFramebuffer *framebuffer, + unsigned long buffers, + const CoglColor *color) +{ + cogl_framebuffer_clear4f (framebuffer, buffers, + cogl_color_get_red_float (color), + cogl_color_get_green_float (color), + cogl_color_get_blue_float (color), + cogl_color_get_alpha_float (color)); +} + +/* We will lazily allocate framebuffers if necessary when querying + * their size/viewport but note we need to be careful in the case of + * onscreen framebuffers that are instantiated with an initial request + * size that we don't trigger an allocation when this is queried since + * that would lead to a recursion when the winsys backend queries this + * requested size during allocation. */ +static void +ensure_size_initialized (CoglFramebuffer *framebuffer) +{ + /* In the case of offscreen framebuffers backed by a texture then + * until that texture has been allocated we might not know the size + * of the framebuffer */ + if (framebuffer->width < 0) + { + /* Currently we assume the size is always initialized for + * onscreen framebuffers. */ + _COGL_RETURN_IF_FAIL (cogl_is_offscreen (framebuffer)); + + /* We also assume the size would have been initialized if the + * framebuffer were allocated. */ + _COGL_RETURN_IF_FAIL (!framebuffer->allocated); + + cogl_framebuffer_allocate (framebuffer, NULL); + } +} + +int +cogl_framebuffer_get_width (CoglFramebuffer *framebuffer) +{ + ensure_size_initialized (framebuffer); + return framebuffer->width; +} + +int +cogl_framebuffer_get_height (CoglFramebuffer *framebuffer) +{ + ensure_size_initialized (framebuffer); + return framebuffer->height; +} + +CoglClipStack * +_cogl_framebuffer_get_clip_stack (CoglFramebuffer *framebuffer) +{ + return framebuffer->clip_stack; +} + +void +_cogl_framebuffer_set_clip_stack (CoglFramebuffer *framebuffer, + CoglClipStack *stack) +{ + _cogl_clip_stack_ref (stack); + _cogl_clip_stack_unref (framebuffer->clip_stack); + framebuffer->clip_stack = stack; +} + +void +cogl_framebuffer_set_viewport (CoglFramebuffer *framebuffer, + float x, + float y, + float width, + float height) +{ + CoglContext *context = framebuffer->context; + + _COGL_RETURN_IF_FAIL (width > 0 && height > 0); + + if (framebuffer->viewport_x == x && + framebuffer->viewport_y == y && + framebuffer->viewport_width == width && + framebuffer->viewport_height == height) + return; + + _cogl_framebuffer_flush_journal (framebuffer); + + framebuffer->viewport_x = x; + framebuffer->viewport_y = y; + framebuffer->viewport_width = width; + framebuffer->viewport_height = height; + framebuffer->viewport_age++; + + if (context->current_draw_buffer == framebuffer) + { + context->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_VIEWPORT; + + if (context->needs_viewport_scissor_workaround) + context->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_CLIP; + } +} + +float +cogl_framebuffer_get_viewport_x (CoglFramebuffer *framebuffer) +{ + return framebuffer->viewport_x; +} + +float +cogl_framebuffer_get_viewport_y (CoglFramebuffer *framebuffer) +{ + return framebuffer->viewport_y; +} + +float +cogl_framebuffer_get_viewport_width (CoglFramebuffer *framebuffer) +{ + ensure_size_initialized (framebuffer); + return framebuffer->viewport_width; +} + +float +cogl_framebuffer_get_viewport_height (CoglFramebuffer *framebuffer) +{ + ensure_size_initialized (framebuffer); + return framebuffer->viewport_height; +} + +void +cogl_framebuffer_get_viewport4fv (CoglFramebuffer *framebuffer, + float *viewport) +{ + ensure_size_initialized (framebuffer); + + viewport[0] = framebuffer->viewport_x; + viewport[1] = framebuffer->viewport_y; + viewport[2] = framebuffer->viewport_width; + viewport[3] = framebuffer->viewport_height; +} + +CoglMatrixStack * +_cogl_framebuffer_get_modelview_stack (CoglFramebuffer *framebuffer) +{ + return framebuffer->modelview_stack; +} + +CoglMatrixStack * +_cogl_framebuffer_get_projection_stack (CoglFramebuffer *framebuffer) +{ + return framebuffer->projection_stack; +} + +void +_cogl_framebuffer_add_dependency (CoglFramebuffer *framebuffer, + CoglFramebuffer *dependency) +{ + GList *l; + + for (l = framebuffer->deps; l; l = l->next) + { + CoglFramebuffer *existing_dep = l->data; + if (existing_dep == dependency) + return; + } + + /* TODO: generalize the primed-array type structure we e.g. use for + * cogl_object_set_user_data or for pipeline children as a way to + * avoid quite a lot of mid-scene micro allocations here... */ + framebuffer->deps = + g_list_prepend (framebuffer->deps, cogl_object_ref (dependency)); +} + +void +_cogl_framebuffer_remove_all_dependencies (CoglFramebuffer *framebuffer) +{ + GList *l; + for (l = framebuffer->deps; l; l = l->next) + cogl_object_unref (l->data); + g_list_free (framebuffer->deps); + framebuffer->deps = NULL; +} + +void +_cogl_framebuffer_flush_journal (CoglFramebuffer *framebuffer) +{ + _cogl_journal_flush (framebuffer->journal); +} + +void +_cogl_framebuffer_flush_dependency_journals (CoglFramebuffer *framebuffer) +{ + GList *l; + for (l = framebuffer->deps; l; l = l->next) + _cogl_framebuffer_flush_journal (l->data); + _cogl_framebuffer_remove_all_dependencies (framebuffer); +} + +CoglOffscreen * +_cogl_offscreen_new_with_texture_full (CoglTexture *texture, + CoglOffscreenFlags create_flags, + int level) +{ + CoglContext *ctx = texture->context; + CoglOffscreen *offscreen; + CoglFramebuffer *fb; + CoglOffscreen *ret; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_texture (texture), NULL); + + offscreen = g_new0 (CoglOffscreen, 1); + offscreen->texture = cogl_object_ref (texture); + offscreen->texture_level = level; + offscreen->create_flags = create_flags; + + fb = COGL_FRAMEBUFFER (offscreen); + + /* NB: we can't assume we can query the texture's width yet, since + * it might not have been allocated yet and for example if the + * texture is being loaded from a file then the file might not + * have been read yet. */ + + _cogl_framebuffer_init (fb, + ctx, + COGL_FRAMEBUFFER_TYPE_OFFSCREEN, + -1, /* unknown width, until allocation */ + -1); /* unknown height until allocation */ + + ret = _cogl_offscreen_object_new (offscreen); + + _cogl_texture_associate_framebuffer (texture, fb); + + return ret; +} + +/* XXX: deprecated api */ +CoglOffscreen * +cogl_offscreen_new_to_texture (CoglTexture *texture) +{ + CoglOffscreen *ret = _cogl_offscreen_new_with_texture_full (texture, 0, 0); + CoglError *error = NULL; + + if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (ret), &error)) + { + cogl_object_unref (ret); + cogl_error_free (error); + ret = NULL; + } + + return ret; +} + +CoglOffscreen * +cogl_offscreen_new_with_texture (CoglTexture *texture) +{ + return _cogl_offscreen_new_with_texture_full (texture, 0, 0); +} + +CoglTexture * +cogl_offscreen_get_texture (CoglOffscreen *offscreen) +{ + return offscreen->texture; +} + +static void +_cogl_offscreen_free (CoglOffscreen *offscreen) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (offscreen); + CoglContext *ctx = framebuffer->context; + + ctx->driver_vtable->offscreen_free (offscreen); + + /* Chain up to parent */ + _cogl_framebuffer_free (framebuffer); + + if (offscreen->texture != NULL) + cogl_object_unref (offscreen->texture); + + if (offscreen->depth_texture != NULL) + cogl_object_unref (offscreen->depth_texture); + + g_free (offscreen); +} + +CoglBool +cogl_framebuffer_allocate (CoglFramebuffer *framebuffer, + CoglError **error) +{ + CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); + const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer); + CoglContext *ctx = framebuffer->context; + + if (framebuffer->allocated) + return TRUE; + + if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN) + { + if (framebuffer->config.depth_texture_enabled) + { + _cogl_set_error (error, COGL_FRAMEBUFFER_ERROR, + COGL_FRAMEBUFFER_ERROR_ALLOCATE, + "Can't allocate onscreen framebuffer with a " + "texture based depth buffer"); + return FALSE; + } + + if (!winsys->onscreen_init (onscreen, error)) + return FALSE; + + /* If the winsys doesn't support dirty events then we'll report + * one on allocation so that if the application only paints in + * response to dirty events then it will at least paint once to + * start */ + if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_DIRTY_EVENTS)) + _cogl_onscreen_queue_full_dirty (onscreen); + } + else + { + CoglOffscreen *offscreen = COGL_OFFSCREEN (framebuffer); + + if (!cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN)) + { + _cogl_set_error (error, COGL_SYSTEM_ERROR, + COGL_SYSTEM_ERROR_UNSUPPORTED, + "Offscreen framebuffers not supported by system"); + return FALSE; + } + + if (!cogl_texture_allocate (offscreen->texture, error)) + return FALSE; + + /* NB: it's only after allocating the texture that we will + * determine whether a texture needs slicing... */ + if (cogl_texture_is_sliced (offscreen->texture)) + { + _cogl_set_error (error, COGL_SYSTEM_ERROR, + COGL_SYSTEM_ERROR_UNSUPPORTED, + "Can't create offscreen framebuffer from " + "sliced texture"); + return FALSE; + } + + /* Now that the texture has been allocated we can determine a + * size for the framebuffer... */ + framebuffer->width = cogl_texture_get_width (offscreen->texture); + framebuffer->height = cogl_texture_get_height (offscreen->texture); + framebuffer->viewport_width = framebuffer->width; + framebuffer->viewport_height = framebuffer->height; + + /* Forward the texture format as the internal format of the + * framebuffer */ + framebuffer->internal_format = + _cogl_texture_get_format (offscreen->texture); + + if (!ctx->driver_vtable->offscreen_allocate (offscreen, error)) + return FALSE; + } + + framebuffer->allocated = TRUE; + + return TRUE; +} + +static unsigned long +_cogl_framebuffer_compare_viewport_state (CoglFramebuffer *a, + CoglFramebuffer *b) +{ + if (a->viewport_x != b->viewport_x || + a->viewport_y != b->viewport_y || + a->viewport_width != b->viewport_width || + a->viewport_height != b->viewport_height || + /* NB: we render upside down to offscreen framebuffers and that + * can affect how we setup the GL viewport... */ + a->type != b->type) + { + unsigned long differences = COGL_FRAMEBUFFER_STATE_VIEWPORT; + CoglContext *context = a->context; + + /* XXX: ONGOING BUG: Intel viewport scissor + * + * Intel gen6 drivers don't currently correctly handle offset + * viewports, since primitives aren't clipped within the bounds of + * the viewport. To workaround this we push our own clip for the + * viewport that will use scissoring to ensure we clip as expected. + * + * This workaround implies that a change in viewport state is + * effectively also a change in the clipping state. + * + * TODO: file a bug upstream! + */ + if (G_UNLIKELY (context->needs_viewport_scissor_workaround)) + differences |= COGL_FRAMEBUFFER_STATE_CLIP; + + return differences; + } + else + return 0; +} + +static unsigned long +_cogl_framebuffer_compare_clip_state (CoglFramebuffer *a, + CoglFramebuffer *b) +{ + if (a->clip_stack != b->clip_stack) + return COGL_FRAMEBUFFER_STATE_CLIP; + else + return 0; +} + +static unsigned long +_cogl_framebuffer_compare_dither_state (CoglFramebuffer *a, + CoglFramebuffer *b) +{ + return a->dither_enabled != b->dither_enabled ? + COGL_FRAMEBUFFER_STATE_DITHER : 0; +} + +static unsigned long +_cogl_framebuffer_compare_modelview_state (CoglFramebuffer *a, + CoglFramebuffer *b) +{ + /* We always want to flush the modelview state. All this does is set + the current modelview stack on the context to the framebuffer's + stack. */ + return COGL_FRAMEBUFFER_STATE_MODELVIEW; +} + +static unsigned long +_cogl_framebuffer_compare_projection_state (CoglFramebuffer *a, + CoglFramebuffer *b) +{ + /* We always want to flush the projection state. All this does is + set the current projection stack on the context to the + framebuffer's stack. */ + return COGL_FRAMEBUFFER_STATE_PROJECTION; +} + +static unsigned long +_cogl_framebuffer_compare_color_mask_state (CoglFramebuffer *a, + CoglFramebuffer *b) +{ + if (cogl_framebuffer_get_color_mask (a) != + cogl_framebuffer_get_color_mask (b)) + return COGL_FRAMEBUFFER_STATE_COLOR_MASK; + else + return 0; +} + +static unsigned long +_cogl_framebuffer_compare_front_face_winding_state (CoglFramebuffer *a, + CoglFramebuffer *b) +{ + if (a->type != b->type) + return COGL_FRAMEBUFFER_STATE_FRONT_FACE_WINDING; + else + return 0; +} + +static unsigned long +_cogl_framebuffer_compare_depth_write_state (CoglFramebuffer *a, + CoglFramebuffer *b) +{ + return a->depth_writing_enabled != b->depth_writing_enabled ? + COGL_FRAMEBUFFER_STATE_DEPTH_WRITE : 0; +} + +static unsigned long +_cogl_framebuffer_compare_stereo_mode (CoglFramebuffer *a, + CoglFramebuffer *b) +{ + return a->stereo_mode != b->stereo_mode ? + COGL_FRAMEBUFFER_STATE_STEREO_MODE : 0; +} + +unsigned long +_cogl_framebuffer_compare (CoglFramebuffer *a, + CoglFramebuffer *b, + unsigned long state) +{ + unsigned long differences = 0; + int bit; + + if (state & COGL_FRAMEBUFFER_STATE_BIND) + { + differences |= COGL_FRAMEBUFFER_STATE_BIND; + state &= ~COGL_FRAMEBUFFER_STATE_BIND; + } + + COGL_FLAGS_FOREACH_START (&state, 1, bit) + { + /* XXX: We considered having an array of callbacks for each state index + * that we'd call here but decided that this way the compiler is more + * likely going to be able to in-line the comparison functions and use + * the index to jump straight to the required code. */ + switch (bit) + { + case COGL_FRAMEBUFFER_STATE_INDEX_VIEWPORT: + differences |= + _cogl_framebuffer_compare_viewport_state (a, b); + break; + case COGL_FRAMEBUFFER_STATE_INDEX_CLIP: + differences |= _cogl_framebuffer_compare_clip_state (a, b); + break; + case COGL_FRAMEBUFFER_STATE_INDEX_DITHER: + differences |= _cogl_framebuffer_compare_dither_state (a, b); + break; + case COGL_FRAMEBUFFER_STATE_INDEX_MODELVIEW: + differences |= + _cogl_framebuffer_compare_modelview_state (a, b); + break; + case COGL_FRAMEBUFFER_STATE_INDEX_PROJECTION: + differences |= + _cogl_framebuffer_compare_projection_state (a, b); + break; + case COGL_FRAMEBUFFER_STATE_INDEX_COLOR_MASK: + differences |= + _cogl_framebuffer_compare_color_mask_state (a, b); + break; + case COGL_FRAMEBUFFER_STATE_INDEX_FRONT_FACE_WINDING: + differences |= + _cogl_framebuffer_compare_front_face_winding_state (a, b); + break; + case COGL_FRAMEBUFFER_STATE_INDEX_DEPTH_WRITE: + differences |= + _cogl_framebuffer_compare_depth_write_state (a, b); + break; + case COGL_FRAMEBUFFER_STATE_INDEX_STEREO_MODE: + differences |= + _cogl_framebuffer_compare_stereo_mode (a, b); + break; + default: + g_warn_if_reached (); + } + } + COGL_FLAGS_FOREACH_END; + + return differences; +} + +void +_cogl_framebuffer_flush_state (CoglFramebuffer *draw_buffer, + CoglFramebuffer *read_buffer, + CoglFramebufferState state) +{ + CoglContext *ctx = draw_buffer->context; + + ctx->driver_vtable->framebuffer_flush_state (draw_buffer, + read_buffer, + state); +} + +int +cogl_framebuffer_get_red_bits (CoglFramebuffer *framebuffer) +{ + CoglContext *ctx = framebuffer->context; + CoglFramebufferBits bits; + + ctx->driver_vtable->framebuffer_query_bits (framebuffer, &bits); + + return bits.red; +} + +int +cogl_framebuffer_get_green_bits (CoglFramebuffer *framebuffer) +{ + CoglContext *ctx = framebuffer->context; + CoglFramebufferBits bits; + + ctx->driver_vtable->framebuffer_query_bits (framebuffer, &bits); + + return bits.green; +} + +int +cogl_framebuffer_get_blue_bits (CoglFramebuffer *framebuffer) +{ + CoglContext *ctx = framebuffer->context; + CoglFramebufferBits bits; + + ctx->driver_vtable->framebuffer_query_bits (framebuffer, &bits); + + return bits.blue; +} + +int +cogl_framebuffer_get_alpha_bits (CoglFramebuffer *framebuffer) +{ + CoglContext *ctx = framebuffer->context; + CoglFramebufferBits bits; + + ctx->driver_vtable->framebuffer_query_bits (framebuffer, &bits); + + return bits.alpha; +} + +int +cogl_framebuffer_get_depth_bits (CoglFramebuffer *framebuffer) +{ + CoglContext *ctx = framebuffer->context; + CoglFramebufferBits bits; + + ctx->driver_vtable->framebuffer_query_bits (framebuffer, &bits); + + return bits.depth; +} + +int +_cogl_framebuffer_get_stencil_bits (CoglFramebuffer *framebuffer) +{ + CoglContext *ctx = framebuffer->context; + CoglFramebufferBits bits; + + ctx->driver_vtable->framebuffer_query_bits (framebuffer, &bits); + + return bits.stencil; +} + +gboolean +cogl_framebuffer_get_is_stereo (CoglFramebuffer *framebuffer) +{ + return framebuffer->config.stereo_enabled; +} + +CoglColorMask +cogl_framebuffer_get_color_mask (CoglFramebuffer *framebuffer) +{ + return framebuffer->color_mask; +} + +void +cogl_framebuffer_set_color_mask (CoglFramebuffer *framebuffer, + CoglColorMask color_mask) +{ + if (framebuffer->color_mask == color_mask) + return; + + /* XXX: Currently color mask changes don't go through the journal */ + _cogl_framebuffer_flush_journal (framebuffer); + + framebuffer->color_mask = color_mask; + + if (framebuffer->context->current_draw_buffer == framebuffer) + framebuffer->context->current_draw_buffer_changes |= + COGL_FRAMEBUFFER_STATE_COLOR_MASK; +} + +CoglStereoMode +cogl_framebuffer_get_stereo_mode (CoglFramebuffer *framebuffer) +{ + return framebuffer->stereo_mode; +} + +void +cogl_framebuffer_set_stereo_mode (CoglFramebuffer *framebuffer, + CoglStereoMode stereo_mode) +{ + if (framebuffer->stereo_mode == stereo_mode) + return; + + /* Stereo mode changes don't go through the journal */ + _cogl_framebuffer_flush_journal (framebuffer); + + framebuffer->stereo_mode = stereo_mode; + + if (framebuffer->context->current_draw_buffer == framebuffer) + framebuffer->context->current_draw_buffer_changes |= + COGL_FRAMEBUFFER_STATE_STEREO_MODE; +} + +CoglBool +cogl_framebuffer_get_depth_write_enabled (CoglFramebuffer *framebuffer) +{ + return framebuffer->depth_writing_enabled; +} + +void +cogl_framebuffer_set_depth_write_enabled (CoglFramebuffer *framebuffer, + CoglBool depth_write_enabled) +{ + if (framebuffer->depth_writing_enabled == depth_write_enabled) + return; + + /* XXX: Currently depth write changes don't go through the journal */ + _cogl_framebuffer_flush_journal (framebuffer); + + framebuffer->depth_writing_enabled = depth_write_enabled; + + if (framebuffer->context->current_draw_buffer == framebuffer) + framebuffer->context->current_draw_buffer_changes |= + COGL_FRAMEBUFFER_STATE_DEPTH_WRITE; +} + +CoglBool +cogl_framebuffer_get_dither_enabled (CoglFramebuffer *framebuffer) +{ + return framebuffer->dither_enabled; +} + +void +cogl_framebuffer_set_dither_enabled (CoglFramebuffer *framebuffer, + CoglBool dither_enabled) +{ + if (framebuffer->dither_enabled == dither_enabled) + return; + + cogl_flush (); /* Currently dithering changes aren't tracked in the journal */ + framebuffer->dither_enabled = dither_enabled; + + if (framebuffer->context->current_draw_buffer == framebuffer) + framebuffer->context->current_draw_buffer_changes |= + COGL_FRAMEBUFFER_STATE_DITHER; +} + +void +cogl_framebuffer_set_depth_texture_enabled (CoglFramebuffer *framebuffer, + CoglBool enabled) +{ + _COGL_RETURN_IF_FAIL (!framebuffer->allocated); + + framebuffer->config.depth_texture_enabled = enabled; +} + +CoglBool +cogl_framebuffer_get_depth_texture_enabled (CoglFramebuffer *framebuffer) +{ + return framebuffer->config.depth_texture_enabled; +} + +CoglTexture * +cogl_framebuffer_get_depth_texture (CoglFramebuffer *framebuffer) +{ + /* lazily allocate the framebuffer... */ + if (!cogl_framebuffer_allocate (framebuffer, NULL)) + return NULL; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_offscreen (framebuffer), NULL); + return COGL_OFFSCREEN(framebuffer)->depth_texture; +} + +int +cogl_framebuffer_get_samples_per_pixel (CoglFramebuffer *framebuffer) +{ + if (framebuffer->allocated) + return framebuffer->samples_per_pixel; + else + return framebuffer->config.samples_per_pixel; +} + +void +cogl_framebuffer_set_samples_per_pixel (CoglFramebuffer *framebuffer, + int samples_per_pixel) +{ + _COGL_RETURN_IF_FAIL (!framebuffer->allocated); + + framebuffer->config.samples_per_pixel = samples_per_pixel; +} + +void +cogl_framebuffer_resolve_samples (CoglFramebuffer *framebuffer) +{ + cogl_framebuffer_resolve_samples_region (framebuffer, + 0, 0, + framebuffer->width, + framebuffer->height); + + /* TODO: Make this happen implicitly when the resolve texture next gets used + * as a source, either via cogl_texture_get_data(), via cogl_read_pixels() or + * if used as a source for rendering. We would also implicitly resolve if + * necessary before freeing a CoglFramebuffer. + * + * This API should still be kept but it is optional, only necessary + * if the user wants to explicitly control when the resolve happens e.g. + * to ensure it's done in advance of it being used as a source. + * + * Every texture should have a CoglFramebuffer *needs_resolve member + * internally. When the texture gets validated before being used as a source + * we should first check the needs_resolve pointer and if set we'll + * automatically call cogl_framebuffer_resolve_samples (). + * + * Calling cogl_framebuffer_resolve_samples() or + * cogl_framebuffer_resolve_samples_region() should reset the textures + * needs_resolve pointer to NULL. + * + * Rendering anything to a framebuffer will cause the corresponding + * texture's ->needs_resolve pointer to be set. + * + * XXX: Note: we only need to address this TODO item when adding support for + * EXT_framebuffer_multisample because currently we only support hardware + * that resolves implicitly anyway. + */ +} + +void +cogl_framebuffer_resolve_samples_region (CoglFramebuffer *framebuffer, + int x, + int y, + int width, + int height) +{ + /* NOP for now since we don't support EXT_framebuffer_multisample yet which + * requires an explicit resolve. */ +} + +CoglContext * +cogl_framebuffer_get_context (CoglFramebuffer *framebuffer) +{ + _COGL_RETURN_VAL_IF_FAIL (framebuffer != NULL, NULL); + + return framebuffer->context; +} + +static CoglBool +_cogl_framebuffer_try_fast_read_pixel (CoglFramebuffer *framebuffer, + int x, + int y, + CoglReadPixelsFlags source, + CoglBitmap *bitmap) +{ + CoglBool found_intersection; + CoglPixelFormat format; + + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_FAST_READ_PIXEL))) + return FALSE; + + if (source != COGL_READ_PIXELS_COLOR_BUFFER) + return FALSE; + + format = cogl_bitmap_get_format (bitmap); + + if (format != COGL_PIXEL_FORMAT_RGBA_8888_PRE && + format != COGL_PIXEL_FORMAT_RGBA_8888) + return FALSE; + + if (!_cogl_journal_try_read_pixel (framebuffer->journal, + x, y, bitmap, + &found_intersection)) + return FALSE; + + /* If we can't determine the color from the primitives in the + * journal then see if we can use the last recorded clear color + */ + + /* If _cogl_journal_try_read_pixel() failed even though there was an + * intersection of the given point with a primitive in the journal + * then we can't fallback to the framebuffer's last clear color... + * */ + if (found_intersection) + return TRUE; + + /* If the framebuffer has been rendered too since it was last + * cleared then we can't return the last known clear color. */ + if (framebuffer->clear_clip_dirty) + return FALSE; + + if (x >= framebuffer->clear_clip_x0 && + x < framebuffer->clear_clip_x1 && + y >= framebuffer->clear_clip_y0 && + y < framebuffer->clear_clip_y1) + { + uint8_t *pixel; + CoglError *ignore_error = NULL; + + /* we currently only care about cases where the premultiplied or + * unpremultipled colors are equivalent... */ + if (framebuffer->clear_color_alpha != 1.0) + return FALSE; + + pixel = _cogl_bitmap_map (bitmap, + COGL_BUFFER_ACCESS_WRITE, + COGL_BUFFER_MAP_HINT_DISCARD, + &ignore_error); + if (pixel == NULL) + { + cogl_error_free (ignore_error); + return FALSE; + } + + pixel[0] = framebuffer->clear_color_red * 255.0; + pixel[1] = framebuffer->clear_color_green * 255.0; + pixel[2] = framebuffer->clear_color_blue * 255.0; + pixel[3] = framebuffer->clear_color_alpha * 255.0; + + _cogl_bitmap_unmap (bitmap); + + return TRUE; + } + + return FALSE; +} + +CoglBool +_cogl_framebuffer_read_pixels_into_bitmap (CoglFramebuffer *framebuffer, + int x, + int y, + CoglReadPixelsFlags source, + CoglBitmap *bitmap, + CoglError **error) +{ + CoglContext *ctx; + int width; + int height; + + _COGL_RETURN_VAL_IF_FAIL (source & COGL_READ_PIXELS_COLOR_BUFFER, FALSE); + _COGL_RETURN_VAL_IF_FAIL (cogl_is_framebuffer (framebuffer), FALSE); + + if (!cogl_framebuffer_allocate (framebuffer, error)) + return FALSE; + + width = cogl_bitmap_get_width (bitmap); + height = cogl_bitmap_get_height (bitmap); + + if (width == 1 && height == 1 && !framebuffer->clear_clip_dirty) + { + /* If everything drawn so far for this frame is still in the + * Journal then if all of the rectangles only have a flat + * opaque color we have a fast-path for reading a single pixel + * that avoids the relatively high cost of flushing primitives + * to be drawn on the GPU (considering how simple the geometry + * is in this case) and then blocking on the long GPU pipelines + * for the result. + */ + if (_cogl_framebuffer_try_fast_read_pixel (framebuffer, + x, y, source, bitmap)) + return TRUE; + } + + ctx = cogl_framebuffer_get_context (framebuffer); + + /* make sure any batched primitives get emitted to the driver + * before issuing our read pixels... + */ + _cogl_framebuffer_flush_journal (framebuffer); + + return ctx->driver_vtable->framebuffer_read_pixels_into_bitmap (framebuffer, + x, y, + source, + bitmap, + error); +} + +CoglBool +cogl_framebuffer_read_pixels_into_bitmap (CoglFramebuffer *framebuffer, + int x, + int y, + CoglReadPixelsFlags source, + CoglBitmap *bitmap) +{ + CoglError *ignore_error = NULL; + CoglBool status = + _cogl_framebuffer_read_pixels_into_bitmap (framebuffer, + x, y, source, bitmap, + &ignore_error); + if (!status) + cogl_error_free (ignore_error); + return status; +} + +CoglBool +cogl_framebuffer_read_pixels (CoglFramebuffer *framebuffer, + int x, + int y, + int width, + int height, + CoglPixelFormat format, + uint8_t *pixels) +{ + int bpp = _cogl_pixel_format_get_bytes_per_pixel (format); + CoglBitmap *bitmap; + CoglBool ret; + + bitmap = cogl_bitmap_new_for_data (framebuffer->context, + width, height, + format, + bpp * width, /* rowstride */ + pixels); + + /* Note: we don't try and catch errors here since we created the + * bitmap storage up-front and can assume we wont hit an + * out-of-memory error which should be the only exception + * this api throws. + */ + ret = _cogl_framebuffer_read_pixels_into_bitmap (framebuffer, + x, y, + COGL_READ_PIXELS_COLOR_BUFFER, + bitmap, + NULL); + cogl_object_unref (bitmap); + + return ret; +} + +void +_cogl_blit_framebuffer (CoglFramebuffer *src, + CoglFramebuffer *dest, + int src_x, + int src_y, + int dst_x, + int dst_y, + int width, + int height) +{ + CoglContext *ctx = src->context; + + _COGL_RETURN_IF_FAIL (_cogl_has_private_feature + (ctx, COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT)); + + /* We can only support blitting between offscreen buffers because + otherwise we would need to mirror the image and GLES2.0 doesn't + support this */ + _COGL_RETURN_IF_FAIL (cogl_is_offscreen (src)); + _COGL_RETURN_IF_FAIL (cogl_is_offscreen (dest)); + /* The buffers must be the same format */ + _COGL_RETURN_IF_FAIL (src->internal_format == dest->internal_format); + + /* Make sure the current framebuffers are bound. We explicitly avoid + flushing the clip state so we can bind our own empty state */ + _cogl_framebuffer_flush_state (dest, + src, + COGL_FRAMEBUFFER_STATE_ALL & + ~COGL_FRAMEBUFFER_STATE_CLIP); + + /* Flush any empty clip stack because glBlitFramebuffer is affected + by the scissor and we want to hide this feature for the Cogl API + because it's not obvious to an app how the clip state will affect + the scissor */ + _cogl_clip_stack_flush (NULL, dest); + + /* XXX: Because we are manually flushing clip state here we need to + * make sure that the clip state gets updated the next time we flush + * framebuffer state by marking the current framebuffer's clip state + * as changed */ + ctx->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_CLIP; + + ctx->glBlitFramebuffer (src_x, src_y, + src_x + width, src_y + height, + dst_x, dst_y, + dst_x + width, dst_y + height, + GL_COLOR_BUFFER_BIT, + GL_NEAREST); +} + +void +cogl_framebuffer_discard_buffers (CoglFramebuffer *framebuffer, + unsigned long buffers) +{ + CoglContext *ctx = framebuffer->context; + + _COGL_RETURN_IF_FAIL (buffers & COGL_BUFFER_BIT_COLOR); + + ctx->driver_vtable->framebuffer_discard_buffers (framebuffer, buffers); +} + +void +cogl_framebuffer_finish (CoglFramebuffer *framebuffer) +{ + CoglContext *ctx = framebuffer->context; + + _cogl_framebuffer_flush_journal (framebuffer); + + ctx->driver_vtable->framebuffer_finish (framebuffer); +} + +void +cogl_framebuffer_push_matrix (CoglFramebuffer *framebuffer) +{ + CoglMatrixStack *modelview_stack = + _cogl_framebuffer_get_modelview_stack (framebuffer); + cogl_matrix_stack_push (modelview_stack); + + if (framebuffer->context->current_draw_buffer == framebuffer) + framebuffer->context->current_draw_buffer_changes |= + COGL_FRAMEBUFFER_STATE_MODELVIEW; +} + +void +cogl_framebuffer_pop_matrix (CoglFramebuffer *framebuffer) +{ + CoglMatrixStack *modelview_stack = + _cogl_framebuffer_get_modelview_stack (framebuffer); + cogl_matrix_stack_pop (modelview_stack); + + if (framebuffer->context->current_draw_buffer == framebuffer) + framebuffer->context->current_draw_buffer_changes |= + COGL_FRAMEBUFFER_STATE_MODELVIEW; +} + +void +cogl_framebuffer_identity_matrix (CoglFramebuffer *framebuffer) +{ + CoglMatrixStack *modelview_stack = + _cogl_framebuffer_get_modelview_stack (framebuffer); + cogl_matrix_stack_load_identity (modelview_stack); + + if (framebuffer->context->current_draw_buffer == framebuffer) + framebuffer->context->current_draw_buffer_changes |= + COGL_FRAMEBUFFER_STATE_MODELVIEW; +} + +void +cogl_framebuffer_scale (CoglFramebuffer *framebuffer, + float x, + float y, + float z) +{ + CoglMatrixStack *modelview_stack = + _cogl_framebuffer_get_modelview_stack (framebuffer); + cogl_matrix_stack_scale (modelview_stack, x, y, z); + + if (framebuffer->context->current_draw_buffer == framebuffer) + framebuffer->context->current_draw_buffer_changes |= + COGL_FRAMEBUFFER_STATE_MODELVIEW; +} + +void +cogl_framebuffer_translate (CoglFramebuffer *framebuffer, + float x, + float y, + float z) +{ + CoglMatrixStack *modelview_stack = + _cogl_framebuffer_get_modelview_stack (framebuffer); + cogl_matrix_stack_translate (modelview_stack, x, y, z); + + if (framebuffer->context->current_draw_buffer == framebuffer) + framebuffer->context->current_draw_buffer_changes |= + COGL_FRAMEBUFFER_STATE_MODELVIEW; +} + +void +cogl_framebuffer_rotate (CoglFramebuffer *framebuffer, + float angle, + float x, + float y, + float z) +{ + CoglMatrixStack *modelview_stack = + _cogl_framebuffer_get_modelview_stack (framebuffer); + cogl_matrix_stack_rotate (modelview_stack, angle, x, y, z); + + if (framebuffer->context->current_draw_buffer == framebuffer) + framebuffer->context->current_draw_buffer_changes |= + COGL_FRAMEBUFFER_STATE_MODELVIEW; +} + +void +cogl_framebuffer_rotate_quaternion (CoglFramebuffer *framebuffer, + const CoglQuaternion *quaternion) +{ + CoglMatrixStack *modelview_stack = + _cogl_framebuffer_get_modelview_stack (framebuffer); + cogl_matrix_stack_rotate_quaternion (modelview_stack, quaternion); + + if (framebuffer->context->current_draw_buffer == framebuffer) + framebuffer->context->current_draw_buffer_changes |= + COGL_FRAMEBUFFER_STATE_MODELVIEW; +} + +void +cogl_framebuffer_rotate_euler (CoglFramebuffer *framebuffer, + const CoglEuler *euler) +{ + CoglMatrixStack *modelview_stack = + _cogl_framebuffer_get_modelview_stack (framebuffer); + cogl_matrix_stack_rotate_euler (modelview_stack, euler); + + if (framebuffer->context->current_draw_buffer == framebuffer) + framebuffer->context->current_draw_buffer_changes |= + COGL_FRAMEBUFFER_STATE_MODELVIEW; +} + +void +cogl_framebuffer_transform (CoglFramebuffer *framebuffer, + const CoglMatrix *matrix) +{ + CoglMatrixStack *modelview_stack = + _cogl_framebuffer_get_modelview_stack (framebuffer); + cogl_matrix_stack_multiply (modelview_stack, matrix); + + if (framebuffer->context->current_draw_buffer == framebuffer) + framebuffer->context->current_draw_buffer_changes |= + COGL_FRAMEBUFFER_STATE_MODELVIEW; +} + +void +cogl_framebuffer_perspective (CoglFramebuffer *framebuffer, + float fov_y, + float aspect, + float z_near, + float z_far) +{ + float ymax = z_near * tanf (fov_y * G_PI / 360.0); + + cogl_framebuffer_frustum (framebuffer, + -ymax * aspect, /* left */ + ymax * aspect, /* right */ + -ymax, /* bottom */ + ymax, /* top */ + z_near, + z_far); + + if (framebuffer->context->current_draw_buffer == framebuffer) + framebuffer->context->current_draw_buffer_changes |= + COGL_FRAMEBUFFER_STATE_PROJECTION; +} + +void +cogl_framebuffer_frustum (CoglFramebuffer *framebuffer, + float left, + float right, + float bottom, + float top, + float z_near, + float z_far) +{ + CoglMatrixStack *projection_stack = + _cogl_framebuffer_get_projection_stack (framebuffer); + + /* XXX: The projection matrix isn't currently tracked in the journal + * so we need to flush all journaled primitives first... */ + _cogl_framebuffer_flush_journal (framebuffer); + + cogl_matrix_stack_load_identity (projection_stack); + + cogl_matrix_stack_frustum (projection_stack, + left, + right, + bottom, + top, + z_near, + z_far); + + if (framebuffer->context->current_draw_buffer == framebuffer) + framebuffer->context->current_draw_buffer_changes |= + COGL_FRAMEBUFFER_STATE_PROJECTION; +} + +void +cogl_framebuffer_orthographic (CoglFramebuffer *framebuffer, + float x_1, + float y_1, + float x_2, + float y_2, + float near, + float far) +{ + CoglMatrix ortho; + CoglMatrixStack *projection_stack = + _cogl_framebuffer_get_projection_stack (framebuffer); + + /* XXX: The projection matrix isn't currently tracked in the journal + * so we need to flush all journaled primitives first... */ + _cogl_framebuffer_flush_journal (framebuffer); + + cogl_matrix_init_identity (&ortho); + cogl_matrix_orthographic (&ortho, x_1, y_1, x_2, y_2, near, far); + cogl_matrix_stack_set (projection_stack, &ortho); + + if (framebuffer->context->current_draw_buffer == framebuffer) + framebuffer->context->current_draw_buffer_changes |= + COGL_FRAMEBUFFER_STATE_PROJECTION; +} + +void +_cogl_framebuffer_push_projection (CoglFramebuffer *framebuffer) +{ + CoglMatrixStack *projection_stack = + _cogl_framebuffer_get_projection_stack (framebuffer); + cogl_matrix_stack_push (projection_stack); + + if (framebuffer->context->current_draw_buffer == framebuffer) + framebuffer->context->current_draw_buffer_changes |= + COGL_FRAMEBUFFER_STATE_PROJECTION; +} + +void +_cogl_framebuffer_pop_projection (CoglFramebuffer *framebuffer) +{ + CoglMatrixStack *projection_stack = + _cogl_framebuffer_get_projection_stack (framebuffer); + cogl_matrix_stack_pop (projection_stack); + + if (framebuffer->context->current_draw_buffer == framebuffer) + framebuffer->context->current_draw_buffer_changes |= + COGL_FRAMEBUFFER_STATE_PROJECTION; +} + +void +cogl_framebuffer_get_modelview_matrix (CoglFramebuffer *framebuffer, + CoglMatrix *matrix) +{ + CoglMatrixEntry *modelview_entry = + _cogl_framebuffer_get_modelview_entry (framebuffer); + cogl_matrix_entry_get (modelview_entry, matrix); + _COGL_MATRIX_DEBUG_PRINT (matrix); +} + +void +cogl_framebuffer_set_modelview_matrix (CoglFramebuffer *framebuffer, + const CoglMatrix *matrix) +{ + CoglMatrixStack *modelview_stack = + _cogl_framebuffer_get_modelview_stack (framebuffer); + cogl_matrix_stack_set (modelview_stack, matrix); + + if (framebuffer->context->current_draw_buffer == framebuffer) + framebuffer->context->current_draw_buffer_changes |= + COGL_FRAMEBUFFER_STATE_MODELVIEW; + + _COGL_MATRIX_DEBUG_PRINT (matrix); +} + +void +cogl_framebuffer_get_projection_matrix (CoglFramebuffer *framebuffer, + CoglMatrix *matrix) +{ + CoglMatrixEntry *projection_entry = + _cogl_framebuffer_get_projection_entry (framebuffer); + cogl_matrix_entry_get (projection_entry, matrix); + _COGL_MATRIX_DEBUG_PRINT (matrix); +} + +void +cogl_framebuffer_set_projection_matrix (CoglFramebuffer *framebuffer, + const CoglMatrix *matrix) +{ + CoglMatrixStack *projection_stack = + _cogl_framebuffer_get_projection_stack (framebuffer); + + /* XXX: The projection matrix isn't currently tracked in the journal + * so we need to flush all journaled primitives first... */ + _cogl_framebuffer_flush_journal (framebuffer); + + cogl_matrix_stack_set (projection_stack, matrix); + + if (framebuffer->context->current_draw_buffer == framebuffer) + framebuffer->context->current_draw_buffer_changes |= + COGL_FRAMEBUFFER_STATE_PROJECTION; + + _COGL_MATRIX_DEBUG_PRINT (matrix); +} + +void +cogl_framebuffer_push_scissor_clip (CoglFramebuffer *framebuffer, + int x, + int y, + int width, + int height) +{ + framebuffer->clip_stack = + _cogl_clip_stack_push_window_rectangle (framebuffer->clip_stack, + x, y, width, height); + + if (framebuffer->context->current_draw_buffer == framebuffer) + framebuffer->context->current_draw_buffer_changes |= + COGL_FRAMEBUFFER_STATE_CLIP; +} + +void +cogl_framebuffer_push_rectangle_clip (CoglFramebuffer *framebuffer, + float x_1, + float y_1, + float x_2, + float y_2) +{ + CoglMatrixEntry *modelview_entry = + _cogl_framebuffer_get_modelview_entry (framebuffer); + CoglMatrixEntry *projection_entry = + _cogl_framebuffer_get_projection_entry (framebuffer); + /* XXX: It would be nicer if we stored the private viewport as a + * vec4 so we could avoid this redundant copy. */ + float viewport[] = { + framebuffer->viewport_x, + framebuffer->viewport_y, + framebuffer->viewport_width, + framebuffer->viewport_height + }; + + framebuffer->clip_stack = + _cogl_clip_stack_push_rectangle (framebuffer->clip_stack, + x_1, y_1, x_2, y_2, + modelview_entry, + projection_entry, + viewport); + + if (framebuffer->context->current_draw_buffer == framebuffer) + framebuffer->context->current_draw_buffer_changes |= + COGL_FRAMEBUFFER_STATE_CLIP; +} + +void +cogl_framebuffer_push_primitive_clip (CoglFramebuffer *framebuffer, + CoglPrimitive *primitive, + float bounds_x1, + float bounds_y1, + float bounds_x2, + float bounds_y2) +{ + CoglMatrixEntry *modelview_entry = + _cogl_framebuffer_get_modelview_entry (framebuffer); + CoglMatrixEntry *projection_entry = + _cogl_framebuffer_get_projection_entry (framebuffer); + /* XXX: It would be nicer if we stored the private viewport as a + * vec4 so we could avoid this redundant copy. */ + float viewport[] = { + framebuffer->viewport_x, + framebuffer->viewport_y, + framebuffer->viewport_width, + framebuffer->viewport_height + }; + + framebuffer->clip_stack = + _cogl_clip_stack_push_primitive (framebuffer->clip_stack, + primitive, + bounds_x1, bounds_y1, + bounds_x2, bounds_y2, + modelview_entry, + projection_entry, + viewport); + + if (framebuffer->context->current_draw_buffer == framebuffer) + framebuffer->context->current_draw_buffer_changes |= + COGL_FRAMEBUFFER_STATE_CLIP; +} + +void +cogl_framebuffer_pop_clip (CoglFramebuffer *framebuffer) +{ + framebuffer->clip_stack = _cogl_clip_stack_pop (framebuffer->clip_stack); + + if (framebuffer->context->current_draw_buffer == framebuffer) + framebuffer->context->current_draw_buffer_changes |= + COGL_FRAMEBUFFER_STATE_CLIP; +} + +void +_cogl_framebuffer_unref (CoglFramebuffer *framebuffer) +{ + /* The journal holds a reference to the framebuffer whenever it is + non-empty. Therefore if the journal is non-empty and we will have + exactly one reference then we know the journal is the only thing + keeping the framebuffer alive. In that case we want to flush the + journal and let the framebuffer die. It is fine at this point if + flushing the journal causes something else to take a reference to + it and it comes back to life */ + if (framebuffer->journal->entries->len > 0) + { + unsigned int ref_count = ((CoglObject *) framebuffer)->ref_count; + + /* There should be at least two references - the one we are + about to drop and the one held by the journal */ + if (ref_count < 2) + g_warning ("Inconsistent ref count on a framebuffer with journal " + "entries."); + + if (ref_count == 2) + _cogl_framebuffer_flush_journal (framebuffer); + } + + /* Chain-up */ + _cogl_object_default_unref (framebuffer); +} + +#ifdef COGL_ENABLE_DEBUG +static int +get_index (void *indices, + CoglIndicesType type, + int _index) +{ + if (!indices) + return _index; + + switch (type) + { + case COGL_INDICES_TYPE_UNSIGNED_BYTE: + return ((uint8_t *)indices)[_index]; + case COGL_INDICES_TYPE_UNSIGNED_SHORT: + return ((uint16_t *)indices)[_index]; + case COGL_INDICES_TYPE_UNSIGNED_INT: + return ((uint32_t *)indices)[_index]; + } + + g_return_val_if_reached (0); +} + +static void +add_line (uint32_t *line_indices, + int base, + void *user_indices, + CoglIndicesType user_indices_type, + int index0, + int index1, + int *pos) +{ + index0 = get_index (user_indices, user_indices_type, index0); + index1 = get_index (user_indices, user_indices_type, index1); + + line_indices[(*pos)++] = base + index0; + line_indices[(*pos)++] = base + index1; +} + +static int +get_line_count (CoglVerticesMode mode, int n_vertices) +{ + if (mode == COGL_VERTICES_MODE_TRIANGLES && + (n_vertices % 3) == 0) + { + return n_vertices; + } + else if (mode == COGL_VERTICES_MODE_TRIANGLE_FAN && + n_vertices >= 3) + { + return 2 * n_vertices - 3; + } + else if (mode == COGL_VERTICES_MODE_TRIANGLE_STRIP && + n_vertices >= 3) + { + return 2 * n_vertices - 3; + } + /* In the journal we are a bit sneaky and actually use GL_QUADS + * which isn't actually a valid CoglVerticesMode! */ +#ifdef HAVE_COGL_GL + else if (mode == GL_QUADS && (n_vertices % 4) == 0) + { + return n_vertices; + } +#endif + + g_return_val_if_reached (0); +} + +static CoglIndices * +get_wire_line_indices (CoglContext *ctx, + CoglVerticesMode mode, + int first_vertex, + int n_vertices_in, + CoglIndices *user_indices, + int *n_indices) +{ + int n_lines; + uint32_t *line_indices; + CoglIndexBuffer *index_buffer; + void *indices; + CoglIndicesType indices_type; + int base = first_vertex; + int pos; + int i; + CoglIndices *ret; + + if (user_indices) + { + index_buffer = cogl_indices_get_buffer (user_indices); + indices = _cogl_buffer_map (COGL_BUFFER (index_buffer), + COGL_BUFFER_ACCESS_READ, 0, + NULL); + indices_type = cogl_indices_get_type (user_indices); + } + else + { + index_buffer = NULL; + indices = NULL; + indices_type = COGL_INDICES_TYPE_UNSIGNED_BYTE; + } + + n_lines = get_line_count (mode, n_vertices_in); + + /* Note: we are using COGL_INDICES_TYPE_UNSIGNED_INT so 4 bytes per index. */ + line_indices = g_malloc (4 * n_lines * 2); + + pos = 0; + + if (mode == COGL_VERTICES_MODE_TRIANGLES && + (n_vertices_in % 3) == 0) + { + for (i = 0; i < n_vertices_in; i += 3) + { + add_line (line_indices, base, indices, indices_type, i, i+1, &pos); + add_line (line_indices, base, indices, indices_type, i+1, i+2, &pos); + add_line (line_indices, base, indices, indices_type, i+2, i, &pos); + } + } + else if (mode == COGL_VERTICES_MODE_TRIANGLE_FAN && + n_vertices_in >= 3) + { + add_line (line_indices, base, indices, indices_type, 0, 1, &pos); + add_line (line_indices, base, indices, indices_type, 1, 2, &pos); + add_line (line_indices, base, indices, indices_type, 0, 2, &pos); + + for (i = 3; i < n_vertices_in; i++) + { + add_line (line_indices, base, indices, indices_type, i - 1, i, &pos); + add_line (line_indices, base, indices, indices_type, 0, i, &pos); + } + } + else if (mode == COGL_VERTICES_MODE_TRIANGLE_STRIP && + n_vertices_in >= 3) + { + add_line (line_indices, base, indices, indices_type, 0, 1, &pos); + add_line (line_indices, base, indices, indices_type, 1, 2, &pos); + add_line (line_indices, base, indices, indices_type, 0, 2, &pos); + + for (i = 3; i < n_vertices_in; i++) + { + add_line (line_indices, base, indices, indices_type, i - 1, i, &pos); + add_line (line_indices, base, indices, indices_type, i - 2, i, &pos); + } + } + /* In the journal we are a bit sneaky and actually use GL_QUADS + * which isn't actually a valid CoglVerticesMode! */ +#ifdef HAVE_COGL_GL + else if (mode == GL_QUADS && (n_vertices_in % 4) == 0) + { + for (i = 0; i < n_vertices_in; i += 4) + { + add_line (line_indices, + base, indices, indices_type, i, i + 1, &pos); + add_line (line_indices, + base, indices, indices_type, i + 1, i + 2, &pos); + add_line (line_indices, + base, indices, indices_type, i + 2, i + 3, &pos); + add_line (line_indices, + base, indices, indices_type, i + 3, i, &pos); + } + } +#endif + + if (user_indices) + cogl_buffer_unmap (COGL_BUFFER (index_buffer)); + + *n_indices = n_lines * 2; + + ret = cogl_indices_new (ctx, + COGL_INDICES_TYPE_UNSIGNED_INT, + line_indices, + *n_indices); + + g_free (line_indices); + + return ret; +} + +static CoglBool +remove_layer_cb (CoglPipeline *pipeline, + int layer_index, + void *user_data) +{ + cogl_pipeline_remove_layer (pipeline, layer_index); + return TRUE; +} + +static void +pipeline_destroyed_cb (CoglPipeline *weak_pipeline, void *user_data) +{ + CoglPipeline *original_pipeline = user_data; + + /* XXX: I think we probably need to provide a custom unref function for + * CoglPipeline because it's possible that we will reach this callback + * because original_pipeline is being freed which means cogl_object_unref + * will have already freed any associated user data. + * + * Setting more user data here will *probably* succeed but that may allocate + * a new user-data array which could be leaked. + * + * Potentially we could have a _cogl_object_free_user_data function so + * that a custom unref function could be written that can destroy weak + * pipeline children before removing user data. + */ + cogl_object_set_user_data (COGL_OBJECT (original_pipeline), + &wire_pipeline_key, NULL, NULL); + + cogl_object_unref (weak_pipeline); +} + +static void +draw_wireframe (CoglContext *ctx, + CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglVerticesMode mode, + int first_vertex, + int n_vertices, + CoglAttribute **attributes, + int n_attributes, + CoglIndices *indices, + CoglDrawFlags flags) +{ + CoglIndices *wire_indices; + CoglPipeline *wire_pipeline; + int n_indices; + + wire_indices = get_wire_line_indices (ctx, + mode, + first_vertex, + n_vertices, + indices, + &n_indices); + + wire_pipeline = cogl_object_get_user_data (COGL_OBJECT (pipeline), + &wire_pipeline_key); + + if (!wire_pipeline) + { + wire_pipeline = + _cogl_pipeline_weak_copy (pipeline, pipeline_destroyed_cb, NULL); + + cogl_object_set_user_data (COGL_OBJECT (pipeline), + &wire_pipeline_key, wire_pipeline, + NULL); + + /* If we have glsl then the pipeline may have an associated + * vertex program and since we'd like to see the results of the + * vertex program in the wireframe we just add a final clobber + * of the wire color leaving the rest of the state untouched. */ + if (cogl_has_feature (framebuffer->context, COGL_FEATURE_ID_GLSL)) + { + static CoglSnippet *snippet = NULL; + + /* The snippet is cached so that it will reuse the program + * from the pipeline cache if possible */ + if (snippet == NULL) + { + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, + NULL, + NULL); + cogl_snippet_set_replace (snippet, + "cogl_color_out = " + "vec4 (0.0, 1.0, 0.0, 1.0);\n"); + } + + cogl_pipeline_add_snippet (wire_pipeline, snippet); + } + else + { + cogl_pipeline_foreach_layer (wire_pipeline, remove_layer_cb, NULL); + cogl_pipeline_set_color4f (wire_pipeline, 0, 1, 0, 1); + } + } + + /* temporarily disable the wireframe to avoid recursion! */ + flags |= COGL_DRAW_SKIP_DEBUG_WIREFRAME; + _cogl_framebuffer_draw_indexed_attributes ( + framebuffer, + wire_pipeline, + COGL_VERTICES_MODE_LINES, + 0, + n_indices, + wire_indices, + attributes, + n_attributes, + flags); + COGL_DEBUG_SET_FLAG (COGL_DEBUG_WIREFRAME); + + cogl_object_unref (wire_indices); +} +#endif + +/* This can be called directly by the CoglJournal to draw attributes + * skipping the implicit journal flush, the framebuffer flush and + * pipeline validation. */ +void +_cogl_framebuffer_draw_attributes (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglVerticesMode mode, + int first_vertex, + int n_vertices, + CoglAttribute **attributes, + int n_attributes, + CoglDrawFlags flags) +{ +#ifdef COGL_ENABLE_DEBUG + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_WIREFRAME) && + (flags & COGL_DRAW_SKIP_DEBUG_WIREFRAME) == 0) && + mode != COGL_VERTICES_MODE_LINES && + mode != COGL_VERTICES_MODE_LINE_LOOP && + mode != COGL_VERTICES_MODE_LINE_STRIP) + draw_wireframe (framebuffer->context, + framebuffer, pipeline, + mode, first_vertex, n_vertices, + attributes, n_attributes, NULL, + flags); + else +#endif + { + CoglContext *ctx = framebuffer->context; + + ctx->driver_vtable->framebuffer_draw_attributes (framebuffer, + pipeline, + mode, + first_vertex, + n_vertices, + attributes, + n_attributes, + flags); + } +} + +/* XXX: deprecated */ +void +cogl_framebuffer_draw_attributes (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglVerticesMode mode, + int first_vertex, + int n_vertices, + CoglAttribute **attributes, + int n_attributes) +{ + _cogl_framebuffer_draw_attributes (framebuffer, + pipeline, + mode, + first_vertex, + n_vertices, + attributes, n_attributes, + COGL_DRAW_SKIP_LEGACY_STATE); +} + +/* XXX: deprecated */ +void +cogl_framebuffer_vdraw_attributes (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglVerticesMode mode, + int first_vertex, + int n_vertices, + ...) +{ + va_list ap; + int n_attributes; + CoglAttribute *attribute; + CoglAttribute **attributes; + int i; + + va_start (ap, n_vertices); + for (n_attributes = 0; va_arg (ap, CoglAttribute *); n_attributes++) + ; + va_end (ap); + + attributes = g_alloca (sizeof (CoglAttribute *) * n_attributes); + + va_start (ap, n_vertices); + for (i = 0; (attribute = va_arg (ap, CoglAttribute *)); i++) + attributes[i] = attribute; + va_end (ap); + + _cogl_framebuffer_draw_attributes (framebuffer, + pipeline, + mode, first_vertex, n_vertices, + attributes, n_attributes, + COGL_DRAW_SKIP_LEGACY_STATE); +} + +void +_cogl_framebuffer_draw_indexed_attributes (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglVerticesMode mode, + int first_vertex, + int n_vertices, + CoglIndices *indices, + CoglAttribute **attributes, + int n_attributes, + CoglDrawFlags flags) +{ +#ifdef COGL_ENABLE_DEBUG + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_WIREFRAME) && + (flags & COGL_DRAW_SKIP_DEBUG_WIREFRAME) == 0) && + mode != COGL_VERTICES_MODE_LINES && + mode != COGL_VERTICES_MODE_LINE_LOOP && + mode != COGL_VERTICES_MODE_LINE_STRIP) + draw_wireframe (framebuffer->context, + framebuffer, pipeline, + mode, first_vertex, n_vertices, + attributes, n_attributes, indices, + flags); + else +#endif + { + CoglContext *ctx = framebuffer->context; + + ctx->driver_vtable->framebuffer_draw_indexed_attributes (framebuffer, + pipeline, + mode, + first_vertex, + n_vertices, + indices, + attributes, + n_attributes, + flags); + } +} + +/* XXX: deprecated */ +void +cogl_framebuffer_draw_indexed_attributes (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglVerticesMode mode, + int first_vertex, + int n_vertices, + CoglIndices *indices, + CoglAttribute **attributes, + int n_attributes) +{ + _cogl_framebuffer_draw_indexed_attributes (framebuffer, + pipeline, + mode, first_vertex, + n_vertices, indices, + attributes, n_attributes, + COGL_DRAW_SKIP_LEGACY_STATE); +} + +/* XXX: deprecated */ +void +cogl_framebuffer_vdraw_indexed_attributes (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglVerticesMode mode, + int first_vertex, + int n_vertices, + CoglIndices *indices, + ...) + +{ + va_list ap; + int n_attributes; + CoglAttribute **attributes; + int i; + CoglAttribute *attribute; + + va_start (ap, indices); + for (n_attributes = 0; va_arg (ap, CoglAttribute *); n_attributes++) + ; + va_end (ap); + + attributes = g_alloca (sizeof (CoglAttribute *) * n_attributes); + + va_start (ap, indices); + for (i = 0; (attribute = va_arg (ap, CoglAttribute *)); i++) + attributes[i] = attribute; + va_end (ap); + + _cogl_framebuffer_draw_indexed_attributes (framebuffer, + pipeline, + mode, + first_vertex, + n_vertices, + indices, + attributes, + n_attributes, + COGL_DRAW_SKIP_LEGACY_STATE); +} + +void +cogl_framebuffer_draw_primitive (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglPrimitive *primitive) +{ + _cogl_primitive_draw (primitive, framebuffer, pipeline, + COGL_DRAW_SKIP_LEGACY_STATE); +} + +void +cogl_framebuffer_draw_rectangle (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + float x_1, + float y_1, + float x_2, + float y_2) +{ + const float position[4] = {x_1, y_1, x_2, y_2}; + CoglMultiTexturedRect rect; + + /* XXX: All the _*_rectangle* APIs normalize their input into an array of + * _CoglMultiTexturedRect rectangles and pass these on to our work horse; + * _cogl_framebuffer_draw_multitextured_rectangles. + */ + + rect.position = position; + rect.tex_coords = NULL; + rect.tex_coords_len = 0; + + _cogl_framebuffer_draw_multitextured_rectangles (framebuffer, + pipeline, + &rect, + 1, + TRUE); +} + +void +cogl_framebuffer_draw_textured_rectangle (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + float x_1, + float y_1, + float x_2, + float y_2, + float s_1, + float t_1, + float s_2, + float t_2) +{ + const float position[4] = {x_1, y_1, x_2, y_2}; + const float tex_coords[4] = {s_1, t_1, s_2, t_2}; + CoglMultiTexturedRect rect; + + /* XXX: All the _*_rectangle* APIs normalize their input into an array of + * CoglMultiTexturedRect rectangles and pass these on to our work horse; + * _cogl_framebuffer_draw_multitextured_rectangles. + */ + + rect.position = position; + rect.tex_coords = tex_coords; + rect.tex_coords_len = 4; + + _cogl_framebuffer_draw_multitextured_rectangles (framebuffer, + pipeline, + &rect, + 1, + TRUE); +} + +void +cogl_framebuffer_draw_multitextured_rectangle (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + float x_1, + float y_1, + float x_2, + float y_2, + const float *tex_coords, + int tex_coords_len) +{ + const float position[4] = {x_1, y_1, x_2, y_2}; + CoglMultiTexturedRect rect; + + /* XXX: All the _*_rectangle* APIs normalize their input into an array of + * CoglMultiTexturedRect rectangles and pass these on to our work horse; + * _cogl_framebuffer_draw_multitextured_rectangles. + */ + + rect.position = position; + rect.tex_coords = tex_coords; + rect.tex_coords_len = tex_coords_len; + + _cogl_framebuffer_draw_multitextured_rectangles (framebuffer, + pipeline, + &rect, + 1, + TRUE); +} + +void +cogl_framebuffer_draw_rectangles (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + const float *coordinates, + unsigned int n_rectangles) +{ + CoglMultiTexturedRect *rects; + int i; + + /* XXX: All the _*_rectangle* APIs normalize their input into an array of + * CoglMultiTexturedRect rectangles and pass these on to our work horse; + * _cogl_framebuffer_draw_multitextured_rectangles. + */ + + rects = g_alloca (n_rectangles * sizeof (CoglMultiTexturedRect)); + + for (i = 0; i < n_rectangles; i++) + { + rects[i].position = &coordinates[i * 4]; + rects[i].tex_coords = NULL; + rects[i].tex_coords_len = 0; + } + + _cogl_framebuffer_draw_multitextured_rectangles (framebuffer, + pipeline, + rects, + n_rectangles, + TRUE); +} + +void +cogl_framebuffer_draw_textured_rectangles (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + const float *coordinates, + unsigned int n_rectangles) +{ + CoglMultiTexturedRect *rects; + int i; + + /* XXX: All the _*_rectangle* APIs normalize their input into an array of + * _CoglMultiTexturedRect rectangles and pass these on to our work horse; + * _cogl_framebuffer_draw_multitextured_rectangles. + */ + + rects = g_alloca (n_rectangles * sizeof (CoglMultiTexturedRect)); + + for (i = 0; i < n_rectangles; i++) + { + rects[i].position = &coordinates[i * 8]; + rects[i].tex_coords = &coordinates[i * 8 + 4]; + rects[i].tex_coords_len = 4; + } + + _cogl_framebuffer_draw_multitextured_rectangles (framebuffer, + pipeline, + rects, + n_rectangles, + TRUE); +} diff --git a/cogl/cogl/cogl-framebuffer.h b/cogl/cogl/cogl-framebuffer.h new file mode 100644 index 0000000..d47a78e --- /dev/null +++ b/cogl/cogl/cogl-framebuffer.h @@ -0,0 +1,1850 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_FRAMEBUFFER_H +#define __COGL_FRAMEBUFFER_H + +/* We forward declare the CoglFramebuffer type here to avoid some circular + * dependency issues with the following headers. + */ +#if defined(__COGL_H_INSIDE__) && !defined(COGL_ENABLE_MUTTER_API) && \ + !defined(COGL_GIR_SCANNING) +/* For the public C api we typedef interface types as void to avoid needing + * lots of casting in code and instead we will rely on runtime type checking + * for these objects. */ +typedef void CoglFramebuffer; +#else +typedef struct _CoglFramebuffer CoglFramebuffer; +#define COGL_FRAMEBUFFER(X) ((CoglFramebuffer *)(X)) +#endif + +#include +#include +#include +#include +#include +#include +#include + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-framebuffer + * @short_description: A common interface for manipulating framebuffers + * + * Framebuffers are a collection of buffers that can be rendered too. + * A framebuffer may be comprised of one or more color buffers, an + * optional depth buffer and an optional stencil buffer. Other + * configuration parameters are associated with framebuffers too such + * as whether the framebuffer supports multi-sampling (an anti-aliasing + * technique) or dithering. + * + * There are two kinds of framebuffer in Cogl, #CoglOnscreen + * framebuffers and #CoglOffscreen framebuffers. As the names imply + * offscreen framebuffers are for rendering something offscreen + * (perhaps to a texture which is bound as one of the color buffers). + * The exact semantics of onscreen framebuffers depends on the window + * system backend that you are using, but typically you can expect + * rendering to a #CoglOnscreen framebuffer will be immediately + * visible to the user. + * + * If you want to create a new framebuffer then you should start by + * looking at the #CoglOnscreen and #CoglOffscreen constructor + * functions, such as cogl_offscreen_new_with_texture() or + * cogl_onscreen_new(). The #CoglFramebuffer interface deals with + * all aspects that are common between those two types of framebuffer. + * + * Setup of a new CoglFramebuffer happens in two stages. There is a + * configuration stage where you specify all the options and ancillary + * buffers you want associated with your framebuffer and then when you + * are happy with the configuration you can "allocate" the framebuffer + * using cogl_framebuffer_allocate(). Technically explicitly calling + * cogl_framebuffer_allocate() is optional for convenience and the + * framebuffer will automatically be allocated when you first try to + * draw to it, but if you do the allocation manually then you can + * also catch any possible errors that may arise from your + * configuration. + */ + +/** + * cogl_framebuffer_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_framebuffer_get_gtype (void); + +/** + * cogl_framebuffer_allocate: + * @framebuffer: A #CoglFramebuffer + * @error: A pointer to a #CoglError for returning exceptions. + * + * Explicitly allocates a configured #CoglFramebuffer allowing developers to + * check and handle any errors that might arise from an unsupported + * configuration so that fallback configurations may be tried. + * + * Many applications don't support any fallback options at least when + * they are initially developed and in that case the don't need to use this API + * since Cogl will automatically allocate a framebuffer when it first gets + * used. The disadvantage of relying on automatic allocation is that the + * program will abort with an error message if there is an error during + * automatic allocation. + * + * Return value: %TRUE if there were no error allocating the framebuffer, else %FALSE. + * Since: 1.8 + * Stability: unstable + */ +CoglBool +cogl_framebuffer_allocate (CoglFramebuffer *framebuffer, + CoglError **error); + +/** + * cogl_framebuffer_get_width: + * @framebuffer: A #CoglFramebuffer + * + * Queries the current width of the given @framebuffer. + * + * Return value: The width of @framebuffer. + * Since: 1.8 + * Stability: unstable + */ +int +cogl_framebuffer_get_width (CoglFramebuffer *framebuffer); + +/** + * cogl_framebuffer_get_height: + * @framebuffer: A #CoglFramebuffer + * + * Queries the current height of the given @framebuffer. + * + * Return value: The height of @framebuffer. + * Since: 1.8 + * Stability: unstable + */ +int +cogl_framebuffer_get_height (CoglFramebuffer *framebuffer); + +/** + * cogl_framebuffer_set_viewport: + * @framebuffer: A #CoglFramebuffer + * @x: The top-left x coordinate of the viewport origin (only integers + * supported currently) + * @y: The top-left y coordinate of the viewport origin (only integers + * supported currently) + * @width: The width of the viewport (only integers supported currently) + * @height: The height of the viewport (only integers supported currently) + * + * Defines a scale and offset for everything rendered relative to the + * top-left of the destination framebuffer. + * + * By default the viewport has an origin of (0,0) and width and height + * that match the framebuffer's size. Assuming a default projection and + * modelview matrix then you could translate the contents of a window + * down and right by leaving the viewport size unchanged by moving the + * offset to (10,10). The viewport coordinates are measured in pixels. + * If you left the x and y origin as (0,0) you could scale the windows + * contents down by specify and width and height that's half the real + * size of the framebuffer. + * + * Although the function takes floating point arguments, existing + * drivers only allow the use of integer values. In the future floating + * point values will be exposed via a checkable feature. + * + * Since: 1.8 + * Stability: unstable + */ +void +cogl_framebuffer_set_viewport (CoglFramebuffer *framebuffer, + float x, + float y, + float width, + float height); + +/** + * cogl_framebuffer_get_viewport_x: + * @framebuffer: A #CoglFramebuffer + * + * Queries the x coordinate of the viewport origin as set using cogl_framebuffer_set_viewport() + * or the default value which is 0. + * + * Return value: The x coordinate of the viewport origin. + * Since: 1.8 + * Stability: unstable + */ +float +cogl_framebuffer_get_viewport_x (CoglFramebuffer *framebuffer); + +/** + * cogl_framebuffer_get_viewport_y: + * @framebuffer: A #CoglFramebuffer + * + * Queries the y coordinate of the viewport origin as set using cogl_framebuffer_set_viewport() + * or the default value which is 0. + * + * Return value: The y coordinate of the viewport origin. + * Since: 1.8 + * Stability: unstable + */ +float +cogl_framebuffer_get_viewport_y (CoglFramebuffer *framebuffer); + +/** + * cogl_framebuffer_get_viewport_width: + * @framebuffer: A #CoglFramebuffer + * + * Queries the width of the viewport as set using cogl_framebuffer_set_viewport() + * or the default value which is the width of the framebuffer. + * + * Return value: The width of the viewport. + * Since: 1.8 + * Stability: unstable + */ +float +cogl_framebuffer_get_viewport_width (CoglFramebuffer *framebuffer); + +/** + * cogl_framebuffer_get_viewport_height: + * @framebuffer: A #CoglFramebuffer + * + * Queries the height of the viewport as set using cogl_framebuffer_set_viewport() + * or the default value which is the height of the framebuffer. + * + * Return value: The height of the viewport. + * Since: 1.8 + * Stability: unstable + */ +float +cogl_framebuffer_get_viewport_height (CoglFramebuffer *framebuffer); + +/** + * cogl_framebuffer_get_viewport4fv: + * @framebuffer: A #CoglFramebuffer + * @viewport: (out caller-allocates) (array fixed-size=4): A pointer to an + * array of 4 floats to receive the (x, y, width, height) + * components of the current viewport. + * + * Queries the x, y, width and height components of the current viewport as set + * using cogl_framebuffer_set_viewport() or the default values which are 0, 0, + * framebuffer_width and framebuffer_height. The values are written into the + * given @viewport array. + * + * Since: 1.8 + * Stability: unstable + */ +void +cogl_framebuffer_get_viewport4fv (CoglFramebuffer *framebuffer, + float *viewport); + +/** + * cogl_framebuffer_push_matrix: + * @framebuffer: A #CoglFramebuffer pointer + * + * Copies the current model-view matrix onto the matrix stack. The matrix + * can later be restored with cogl_framebuffer_pop_matrix(). + * + * Since: 1.10 + */ +void +cogl_framebuffer_push_matrix (CoglFramebuffer *framebuffer); + +/** + * cogl_framebuffer_pop_matrix: + * @framebuffer: A #CoglFramebuffer pointer + * + * Restores the model-view matrix on the top of the matrix stack. + * + * Since: 1.10 + */ +void +cogl_framebuffer_pop_matrix (CoglFramebuffer *framebuffer); + +/** + * cogl_framebuffer_identity_matrix: + * @framebuffer: A #CoglFramebuffer pointer + * + * Resets the current model-view matrix to the identity matrix. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_framebuffer_identity_matrix (CoglFramebuffer *framebuffer); + +/** + * cogl_framebuffer_scale: + * @framebuffer: A #CoglFramebuffer pointer + * @x: Amount to scale along the x-axis + * @y: Amount to scale along the y-axis + * @z: Amount to scale along the z-axis + * + * Multiplies the current model-view matrix by one that scales the x, + * y and z axes by the given values. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_framebuffer_scale (CoglFramebuffer *framebuffer, + float x, + float y, + float z); + +/** + * cogl_framebuffer_translate: + * @framebuffer: A #CoglFramebuffer pointer + * @x: Distance to translate along the x-axis + * @y: Distance to translate along the y-axis + * @z: Distance to translate along the z-axis + * + * Multiplies the current model-view matrix by one that translates the + * model along all three axes according to the given values. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_framebuffer_translate (CoglFramebuffer *framebuffer, + float x, + float y, + float z); + +/** + * cogl_framebuffer_rotate: + * @framebuffer: A #CoglFramebuffer pointer + * @angle: Angle in degrees to rotate. + * @x: X-component of vertex to rotate around. + * @y: Y-component of vertex to rotate around. + * @z: Z-component of vertex to rotate around. + * + * Multiplies the current model-view matrix by one that rotates the + * model around the axis-vector specified by @x, @y and @z. The + * rotation follows the right-hand thumb rule so for example rotating + * by 10 degrees about the axis-vector (0, 0, 1) causes a small + * counter-clockwise rotation. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_framebuffer_rotate (CoglFramebuffer *framebuffer, + float angle, + float x, + float y, + float z); + +/** + * cogl_framebuffer_rotate_quaternion: + * @framebuffer: A #CoglFramebuffer pointer + * @quaternion: A #CoglQuaternion + * + * Multiplies the current model-view matrix by one that rotates + * according to the rotation described by @quaternion. + * + * Since: 2.0 + * Stability: unstable + */ +void +cogl_framebuffer_rotate_quaternion (CoglFramebuffer *framebuffer, + const CoglQuaternion *quaternion); + +/** + * cogl_framebuffer_rotate_euler: + * @framebuffer: A #CoglFramebuffer pointer + * @euler: A #CoglEuler + * + * Multiplies the current model-view matrix by one that rotates + * according to the rotation described by @euler. + * + * Since: 2.0 + * Stability: unstable + */ +void +cogl_framebuffer_rotate_euler (CoglFramebuffer *framebuffer, + const CoglEuler *euler); + +/** + * cogl_framebuffer_transform: + * @framebuffer: A #CoglFramebuffer pointer + * @matrix: the matrix to multiply with the current model-view + * + * Multiplies the current model-view matrix by the given matrix. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_framebuffer_transform (CoglFramebuffer *framebuffer, + const CoglMatrix *matrix); + +/** + * cogl_framebuffer_get_modelview_matrix: + * @framebuffer: A #CoglFramebuffer pointer + * @matrix: (out): return location for the model-view matrix + * + * Stores the current model-view matrix in @matrix. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_framebuffer_get_modelview_matrix (CoglFramebuffer *framebuffer, + CoglMatrix *matrix); + +/** + * cogl_framebuffer_set_modelview_matrix: + * @framebuffer: A #CoglFramebuffer pointer + * @matrix: the new model-view matrix + * + * Sets @matrix as the new model-view matrix. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_framebuffer_set_modelview_matrix (CoglFramebuffer *framebuffer, + const CoglMatrix *matrix); + +/** + * cogl_framebuffer_perspective: + * @framebuffer: A #CoglFramebuffer pointer + * @fov_y: Vertical field of view angle in degrees. + * @aspect: The (width over height) aspect ratio for display + * @z_near: The distance to the near clipping plane (Must be positive, + * and must not be 0) + * @z_far: The distance to the far clipping plane (Must be positive) + * + * Replaces the current projection matrix with a perspective matrix + * based on the provided values. + * + * 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. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_framebuffer_perspective (CoglFramebuffer *framebuffer, + float fov_y, + float aspect, + float z_near, + float z_far); + +/** + * cogl_framebuffer_frustum: + * @framebuffer: A #CoglFramebuffer pointer + * @left: X position of the left clipping plane where it + * intersects the near clipping plane + * @right: X position of the right clipping plane where it + * intersects the near clipping plane + * @bottom: Y position of the bottom clipping plane where it + * intersects the near clipping plane + * @top: Y position of the top clipping plane where it intersects + * the near clipping plane + * @z_near: The distance to the near clipping plane (Must be positive) + * @z_far: The distance to the far clipping plane (Must be positive) + * + * Replaces the current projection matrix with a perspective matrix + * for a given viewing frustum defined by 4 side clip planes that + * all cross through the origin and 2 near and far clip planes. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_framebuffer_frustum (CoglFramebuffer *framebuffer, + float left, + float right, + float bottom, + float top, + float z_near, + float z_far); + +/** + * cogl_framebuffer_orthographic: + * @framebuffer: A #CoglFramebuffer pointer + * @x_1: The x coordinate for the first vertical clipping plane + * @y_1: The y coordinate for the first horizontal clipping plane + * @x_2: The x coordinate for the second vertical clipping plane + * @y_2: The y coordinate for the second horizontal clipping plane + * @near: The distance to the near clipping + * plane (will be negative if the plane is + * behind the viewer) + * @far: The distance to the far clipping + * plane (will be negative if the plane is + * behind the viewer) + * + * Replaces the current projection matrix with an orthographic projection + * matrix. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_framebuffer_orthographic (CoglFramebuffer *framebuffer, + float x_1, + float y_1, + float x_2, + float y_2, + float near, + float far); + +/** + * cogl_framebuffer_get_projection_matrix: + * @framebuffer: A #CoglFramebuffer pointer + * @matrix: (out): return location for the projection matrix + * + * Stores the current projection matrix in @matrix. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_framebuffer_get_projection_matrix (CoglFramebuffer *framebuffer, + CoglMatrix *matrix); + +/** + * cogl_framebuffer_set_projection_matrix: + * @framebuffer: A #CoglFramebuffer pointer + * @matrix: the new projection matrix + * + * Sets @matrix as the new projection matrix. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_framebuffer_set_projection_matrix (CoglFramebuffer *framebuffer, + const CoglMatrix *matrix); + +/** + * cogl_framebuffer_push_scissor_clip: + * @framebuffer: A #CoglFramebuffer pointer + * @x: left edge of the clip rectangle in window coordinates + * @y: top edge of the clip rectangle in window coordinates + * @width: width of the clip rectangle + * @height: height of the clip rectangle + * + * Specifies a rectangular clipping area for all subsequent drawing + * operations. Any drawing commands that extend outside the rectangle + * will be clipped so that only the portion inside the rectangle will + * be displayed. The rectangle dimensions are not transformed by the + * current model-view matrix. + * + * The rectangle is intersected with the current clip region. To undo + * the effect of this function, call cogl_framebuffer_pop_clip(). + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_framebuffer_push_scissor_clip (CoglFramebuffer *framebuffer, + int x, + int y, + int width, + int height); + +/** + * cogl_framebuffer_push_rectangle_clip: + * @framebuffer: A #CoglFramebuffer pointer + * @x_1: x coordinate for top left corner of the clip rectangle + * @y_1: y coordinate for top left corner of the clip rectangle + * @x_2: x coordinate for bottom right corner of the clip rectangle + * @y_2: y coordinate for bottom right corner of the clip rectangle + * + * Specifies a modelview transformed rectangular clipping area for all + * subsequent drawing operations. Any drawing commands that extend + * outside the rectangle will be clipped so that only the portion + * inside the rectangle will be displayed. The rectangle dimensions + * are transformed by the current model-view matrix. + * + * The rectangle is intersected with the current clip region. To undo + * the effect of this function, call cogl_framebuffer_pop_clip(). + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_framebuffer_push_rectangle_clip (CoglFramebuffer *framebuffer, + float x_1, + float y_1, + float x_2, + float y_2); + +/** + * cogl_framebuffer_push_primitive_clip: + * @framebuffer: A #CoglFramebuffer pointer + * @primitive: A #CoglPrimitive describing a flat 2D shape + * @bounds_x1: x coordinate for the top-left corner of the primitives + * bounds + * @bounds_y1: y coordinate for the top-left corner of the primitives + * bounds + * @bounds_x2: x coordinate for the bottom-right corner of the + * primitives bounds. + * @bounds_y2: y coordinate for the bottom-right corner of the + * primitives bounds. + * + * Sets a new clipping area using a 2D shaped described with a + * #CoglPrimitive. The shape must not contain self overlapping + * geometry and must lie on a single 2D plane. A bounding box of the + * 2D shape in local coordinates (the same coordinates used to + * describe the shape) must be given. It is acceptable for the bounds + * to be larger than the true bounds but behaviour is undefined if the + * bounds are smaller than the true bounds. + * + * The primitive is transformed by the current model-view matrix and + * the silhouette is intersected with the previous clipping area. To + * restore the previous clipping area, call + * cogl_framebuffer_pop_clip(). + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_framebuffer_push_primitive_clip (CoglFramebuffer *framebuffer, + CoglPrimitive *primitive, + float bounds_x1, + float bounds_y1, + float bounds_x2, + float bounds_y2); + +/** + * cogl_framebuffer_pop_clip: + * @framebuffer: A #CoglFramebuffer pointer + * + * Reverts the clipping region to the state before the last call to + * cogl_framebuffer_push_scissor_clip(), cogl_framebuffer_push_rectangle_clip() + * cogl_framebuffer_push_path_clip(), or cogl_framebuffer_push_primitive_clip(). + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_framebuffer_pop_clip (CoglFramebuffer *framebuffer); + +/** + * cogl_framebuffer_get_red_bits: + * @framebuffer: a pointer to a #CoglFramebuffer + * + * Retrieves the number of red bits of @framebuffer + * + * Return value: the number of bits + * + * Since: 1.8 + * Stability: unstable + */ +int +cogl_framebuffer_get_red_bits (CoglFramebuffer *framebuffer); + +/** + * cogl_framebuffer_get_green_bits: + * @framebuffer: a pointer to a #CoglFramebuffer + * + * Retrieves the number of green bits of @framebuffer + * + * Return value: the number of bits + * + * Since: 1.8 + * Stability: unstable + */ +int +cogl_framebuffer_get_green_bits (CoglFramebuffer *framebuffer); + +/** + * cogl_framebuffer_get_blue_bits: + * @framebuffer: a pointer to a #CoglFramebuffer + * + * Retrieves the number of blue bits of @framebuffer + * + * Return value: the number of bits + * + * Since: 1.8 + * Stability: unstable + */ +int +cogl_framebuffer_get_blue_bits (CoglFramebuffer *framebuffer); + +/** + * cogl_framebuffer_get_alpha_bits: + * @framebuffer: a pointer to a #CoglFramebuffer + * + * Retrieves the number of alpha bits of @framebuffer + * + * Return value: the number of bits + * + * Since: 1.8 + * Stability: unstable + */ +int +cogl_framebuffer_get_alpha_bits (CoglFramebuffer *framebuffer); + +/** + * cogl_framebuffer_get_depth_bits: + * @framebuffer: a pointer to a #CoglFramebuffer + * + * Retrieves the number of depth bits of @framebuffer + * + * Return value: the number of bits + * + * Since: 2.0 + * Stability: unstable + */ +int +cogl_framebuffer_get_depth_bits (CoglFramebuffer *framebuffer); + +/* + * cogl_framebuffer_get_is_stereo: + * @framebuffer: a pointer to a #CoglFramebuffer + * + * Retrieves whether @framebuffer has separate left and right + * buffers for use with stereo drawing. See + * cogl_framebuffer_set_stereo_mode(). + * + * Return value: %TRUE if @framebuffer has separate left and + * right buffers. + * + * Since: 1.20 + * Stability: unstable + */ +CoglBool +cogl_framebuffer_get_is_stereo (CoglFramebuffer *framebuffer); + +/** + * cogl_framebuffer_get_dither_enabled: + * @framebuffer: a pointer to a #CoglFramebuffer + * + * Returns whether dithering has been requested for the given @framebuffer. + * See cogl_framebuffer_set_dither_enabled() for more details about dithering. + * + * This may return %TRUE even when the underlying @framebuffer + * display pipeline does not support dithering. This value only represents + * the user's request for dithering. + * + * Return value: %TRUE if dithering has been requested or %FALSE if not. + * Since: 1.8 + * Stability: unstable + */ +CoglBool +cogl_framebuffer_get_dither_enabled (CoglFramebuffer *framebuffer); + +/** + * cogl_framebuffer_set_dither_enabled: + * @framebuffer: a pointer to a #CoglFramebuffer + * @dither_enabled: %TRUE to enable dithering or %FALSE to disable + * + * Enables or disabled dithering if supported by the hardware. + * + * Dithering is a hardware dependent technique to increase the visible + * color resolution beyond what the underlying hardware supports by playing + * tricks with the colors placed into the framebuffer to give the illusion + * of other colors. (For example this can be compared to half-toning used + * by some news papers to show varying levels of grey even though their may + * only be black and white are available). + * + * If the current display pipeline for @framebuffer does not support dithering + * then this has no affect. + * + * Dithering is enabled by default. + * + * Since: 1.8 + * Stability: unstable + */ +void +cogl_framebuffer_set_dither_enabled (CoglFramebuffer *framebuffer, + CoglBool dither_enabled); + +/** + * cogl_framebuffer_get_depth_write_enabled: + * @framebuffer: a pointer to a #CoglFramebuffer + * + * Queries whether depth buffer writing is enabled for @framebuffer. This + * can be controlled via cogl_framebuffer_set_depth_write_enabled(). + * + * Return value: %TRUE if depth writing is enabled or %FALSE if not. + * Since: 1.18 + * Stability: unstable + */ +CoglBool +cogl_framebuffer_get_depth_write_enabled (CoglFramebuffer *framebuffer); + +/** + * cogl_framebuffer_set_depth_write_enabled: + * @framebuffer: a pointer to a #CoglFramebuffer + * @depth_write_enabled: %TRUE to enable depth writing or %FALSE to disable + * + * Enables or disables depth buffer writing when rendering to @framebuffer. + * If depth writing is enabled for both the framebuffer and the rendering + * pipeline, and the framebuffer has an associated depth buffer, depth + * information will be written to this buffer during rendering. + * + * Depth buffer writing is enabled by default. + * + * Since: 1.18 + * Stability: unstable + */ +void +cogl_framebuffer_set_depth_write_enabled (CoglFramebuffer *framebuffer, + CoglBool depth_write_enabled); + +/** + * cogl_framebuffer_get_color_mask: + * @framebuffer: a pointer to a #CoglFramebuffer + * + * Gets the current #CoglColorMask of which channels would be written to the + * current framebuffer. Each bit set in the mask means that the + * corresponding color would be written. + * + * Returns: A #CoglColorMask + * Since: 1.8 + * Stability: unstable + */ +CoglColorMask +cogl_framebuffer_get_color_mask (CoglFramebuffer *framebuffer); + +/** + * cogl_framebuffer_set_color_mask: + * @framebuffer: a pointer to a #CoglFramebuffer + * @color_mask: A #CoglColorMask of which color channels to write to + * the current framebuffer. + * + * Defines a bit mask of which color channels should be written to the + * given @framebuffer. If a bit is set in @color_mask that means that + * color will be written. + * + * Since: 1.8 + * Stability: unstable + */ +void +cogl_framebuffer_set_color_mask (CoglFramebuffer *framebuffer, + CoglColorMask color_mask); + +/** + * cogl_framebuffer_get_stereo_mode: + * @framebuffer: a pointer to a #CoglFramebuffer + * + * Gets the current #CoglStereoMode, which defines which stereo buffers + * should be drawn to. See cogl_framebuffer_set_stereo_mode(). + * + * Returns: A #CoglStereoMode + * Since: 1.20 + * Stability: unstable + */ +CoglStereoMode +cogl_framebuffer_get_stereo_mode (CoglFramebuffer *framebuffer); + +/** + * cogl_framebuffer_set_stereo_mode: + * @framebuffer: a pointer to a #CoglFramebuffer + * @stereo_mode: A #CoglStereoMode specifying which stereo buffers + * should be drawn tow. + * + * Sets which stereo buffers should be drawn to. The default + * is %COGL_STEREO_BOTH, which means that both the left and + * right buffers will be affected by drawing. For this to have + * an effect, the display system must support stereo drawables, + * and the framebuffer must have been created with stereo + * enabled. (See cogl_onscreen_template_set_stereo_enabled(), + * cogl_framebuffer_get_is_stereo().) + * + * Since: 1.20 + * Stability: unstable + */ +void +cogl_framebuffer_set_stereo_mode (CoglFramebuffer *framebuffer, + CoglStereoMode stereo_mode); + +/** + * cogl_framebuffer_set_depth_texture_enabled: + * @framebuffer: A #CoglFramebuffer + * @enabled: TRUE or FALSE + * + * If @enabled is #TRUE, the depth buffer used when rendering to @framebuffer + * is available as a texture. You can retrieve the texture with + * cogl_framebuffer_get_depth_texture(). + * + * It's possible that your GPU does not support depth textures. You + * should check the %COGL_FEATURE_ID_DEPTH_TEXTURE feature before using this + * function. + * It's not valid to call this function after the framebuffer has been + * allocated as the creation of the depth texture is done at allocation time. + * + * + * Since: 1.14 + * Stability: unstable + */ +void +cogl_framebuffer_set_depth_texture_enabled (CoglFramebuffer *framebuffer, + CoglBool enabled); + +/** + * cogl_framebuffer_get_depth_texture_enabled: + * @framebuffer: A #CoglFramebuffer + * + * Queries whether texture based depth buffer has been enabled via + * cogl_framebuffer_set_depth_texture_enabled(). + * + * Return value: %TRUE if a depth texture has been enabled, else + * %FALSE. + * + * Since: 1.14 + * Stability: unstable + */ +CoglBool +cogl_framebuffer_get_depth_texture_enabled (CoglFramebuffer *framebuffer); + +/** + * cogl_framebuffer_get_depth_texture: + * @framebuffer: A #CoglFramebuffer + * + * Retrieves the depth buffer of @framebuffer as a #CoglTexture. You need to + * call cogl_framebuffer_get_depth_texture(fb, TRUE); before using this + * function. + * + * Calling this function implicitely allocates the framebuffer. + * The texture returned stays valid as long as the framebuffer stays + * valid. + * + * Returns: (transfer none): the depth texture + * + * Since: 1.14 + * Stability: unstable + */ +CoglTexture * +cogl_framebuffer_get_depth_texture (CoglFramebuffer *framebuffer); + +/** + * cogl_framebuffer_set_samples_per_pixel: + * @framebuffer: A #CoglFramebuffer framebuffer + * @samples_per_pixel: The minimum number of samples per pixel + * + * Requires that when rendering to @framebuffer then @n point samples + * should be made per pixel which will all contribute to the final + * resolved color for that pixel. The idea is that the hardware aims + * to get quality similar to what you would get if you rendered + * everything twice as big (for 4 samples per pixel) and then scaled + * that image back down with filtering. It can effectively remove the + * jagged edges of polygons and should be more efficient than if you + * were to manually render at a higher resolution and downscale + * because the hardware is often able to take some shortcuts. For + * example the GPU may only calculate a single texture sample for all + * points of a single pixel, and for tile based architectures all the + * extra sample data (such as depth and stencil samples) may be + * handled on-chip and so avoid increased demand on system memory + * bandwidth. + * + * By default this value is usually set to 0 and that is referred to + * as "single-sample" rendering. A value of 1 or greater is referred + * to as "multisample" rendering. + * + * There are some semantic differences between single-sample + * rendering and multisampling with just 1 point sample such as it + * being redundant to use the cogl_framebuffer_resolve_samples() and + * cogl_framebuffer_resolve_samples_region() apis with single-sample + * rendering. + * + * It's recommended that + * cogl_framebuffer_resolve_samples_region() be explicitly used at the + * end of rendering to a point sample buffer to minimize the number of + * samples that get resolved. By default Cogl will implicitly resolve + * all framebuffer samples but if only a small region of a + * framebuffer has changed this can lead to redundant work being + * done. + * + * Since: 1.8 + * Stability: unstable + */ +void +cogl_framebuffer_set_samples_per_pixel (CoglFramebuffer *framebuffer, + int samples_per_pixel); + +/** + * cogl_framebuffer_get_samples_per_pixel: + * @framebuffer: A #CoglFramebuffer framebuffer + * + * Gets the number of points that are sampled per-pixel when + * rasterizing geometry. Usually by default this will return 0 which + * means that single-sample not multisample rendering has been chosen. + * When using a GPU supporting multisample rendering it's possible to + * increase the number of samples per pixel using + * cogl_framebuffer_set_samples_per_pixel(). + * + * Calling cogl_framebuffer_get_samples_per_pixel() before the + * framebuffer has been allocated will simply return the value set + * using cogl_framebuffer_set_samples_per_pixel(). After the + * framebuffer has been allocated the value will reflect the actual + * number of samples that will be made by the GPU. + * + * Returns: The number of point samples made per pixel when + * rasterizing geometry or 0 if single-sample rendering + * has been chosen. + * + * Since: 1.10 + * Stability: unstable + */ +int +cogl_framebuffer_get_samples_per_pixel (CoglFramebuffer *framebuffer); + + +/** + * cogl_framebuffer_resolve_samples: + * @framebuffer: A #CoglFramebuffer framebuffer + * + * When point sample rendering (also known as multisample rendering) + * has been enabled via cogl_framebuffer_set_samples_per_pixel() + * then you can optionally call this function (or + * cogl_framebuffer_resolve_samples_region()) to explicitly resolve + * the point samples into values for the final color buffer. + * + * Some GPUs will implicitly resolve the point samples during + * rendering and so this function is effectively a nop, but with other + * architectures it is desirable to defer the resolve step until the + * end of the frame. + * + * Since Cogl will automatically ensure samples are resolved if the + * target color buffer is used as a source this API only needs to be + * used if explicit control is desired - perhaps because you want to + * ensure that the resolve is completed in advance to avoid later + * having to wait for the resolve to complete. + * + * If you are performing incremental updates to a framebuffer you + * should consider using cogl_framebuffer_resolve_samples_region() + * instead to avoid resolving redundant pixels. + * + * Since: 1.8 + * Stability: unstable + */ +void +cogl_framebuffer_resolve_samples (CoglFramebuffer *framebuffer); + +/** + * cogl_framebuffer_resolve_samples_region: + * @framebuffer: A #CoglFramebuffer framebuffer + * @x: top-left x coordinate of region to resolve + * @y: top-left y coordinate of region to resolve + * @width: width of region to resolve + * @height: height of region to resolve + * + * When point sample rendering (also known as multisample rendering) + * has been enabled via cogl_framebuffer_set_samples_per_pixel() + * then you can optionally call this function (or + * cogl_framebuffer_resolve_samples()) to explicitly resolve the point + * samples into values for the final color buffer. + * + * Some GPUs will implicitly resolve the point samples during + * rendering and so this function is effectively a nop, but with other + * architectures it is desirable to defer the resolve step until the + * end of the frame. + * + * Use of this API is recommended if incremental, small updates to + * a framebuffer are being made because by default Cogl will + * implicitly resolve all the point samples of the framebuffer which + * can result in redundant work if only a small number of samples have + * changed. + * + * Because some GPUs implicitly resolve point samples this function + * only guarantees that at-least the region specified will be resolved + * and if you have rendered to a larger region then it's possible that + * other samples may be implicitly resolved. + * + * Since: 1.8 + * Stability: unstable + */ +void +cogl_framebuffer_resolve_samples_region (CoglFramebuffer *framebuffer, + int x, + int y, + int width, + int height); + +/** + * cogl_framebuffer_get_context: + * @framebuffer: A #CoglFramebuffer + * + * Can be used to query the #CoglContext a given @framebuffer was + * instantiated within. This is the #CoglContext that was passed to + * cogl_onscreen_new() for example. + * + * Return value: (transfer none): The #CoglContext that the given + * @framebuffer was instantiated within. + * Since: 1.8 + * Stability: unstable + */ +CoglContext * +cogl_framebuffer_get_context (CoglFramebuffer *framebuffer); + +/** + * cogl_framebuffer_clear: + * @framebuffer: A #CoglFramebuffer + * @buffers: A mask of #CoglBufferBit's identifying which auxiliary + * buffers to clear + * @color: The color to clear the color buffer too if specified in + * @buffers. + * + * Clears all the auxiliary buffers identified in the @buffers mask, and if + * that includes the color buffer then the specified @color is used. + * + * Since: 1.8 + * Stability: unstable + */ +void +cogl_framebuffer_clear (CoglFramebuffer *framebuffer, + unsigned long buffers, + const CoglColor *color); + +/** + * cogl_framebuffer_clear4f: + * @framebuffer: A #CoglFramebuffer + * @buffers: A mask of #CoglBufferBit's identifying which auxiliary + * buffers to clear + * @red: The red component of color to clear the color buffer too if + * specified in @buffers. + * @green: The green component of color to clear the color buffer too if + * specified in @buffers. + * @blue: The blue component of color to clear the color buffer too if + * specified in @buffers. + * @alpha: The alpha component of color to clear the color buffer too if + * specified in @buffers. + * + * Clears all the auxiliary buffers identified in the @buffers mask, and if + * that includes the color buffer then the specified @color is used. + * + * Since: 1.8 + * Stability: unstable + */ +void +cogl_framebuffer_clear4f (CoglFramebuffer *framebuffer, + unsigned long buffers, + float red, + float green, + float blue, + float alpha); + +/** + * cogl_framebuffer_draw_primitive: + * @framebuffer: A destination #CoglFramebuffer + * @pipeline: A #CoglPipeline state object + * @primitive: A #CoglPrimitive geometry object + * + * Draws the given @primitive geometry to the specified destination + * @framebuffer using the graphics processing state described by @pipeline. + * + * This drawing api doesn't support high-level meta texture types such + * as #CoglTexture2DSliced so it is the user's responsibility to + * ensure that only low-level textures that can be directly sampled by + * a GPU such as #CoglTexture2D, #CoglTextureRectangle or #CoglTexture3D + * are associated with layers of the given @pipeline. + * + * This api doesn't support any of the legacy global state options such + * as cogl_set_depth_test_enabled(), cogl_set_backface_culling_enabled() or + * cogl_program_use() + * + * Stability: unstable + * Since: 1.10 + * Deprecated: 1.16: Use #CoglPrimitives and + * cogl_primitive_draw() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_primitive_draw) +void +cogl_framebuffer_draw_primitive (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglPrimitive *primitive); + +/** + * cogl_framebuffer_vdraw_attributes: + * @framebuffer: A destination #CoglFramebuffer + * @pipeline: A #CoglPipeline state object + * @mode: The #CoglVerticesMode defining the topology of vertices + * @first_vertex: The vertex offset within the given attributes to draw from + * @n_vertices: The number of vertices to draw from the given attributes + * @...: A set of vertex #CoglAttributes defining vertex geometry + * + * First defines a geometry primitive by grouping a set of vertex attributes; + * specifying a @first_vertex; a number of vertices (@n_vertices) and + * specifying what kind of topology the vertices have via @mode. + * + * Then the function draws the given @primitive geometry to the specified + * destination @framebuffer using the graphics processing pipeline described by + * @pipeline. + * + * The list of #CoglAttributes define the attributes of the vertices to + * be drawn, such as positions, colors and normals and should be %NULL + * terminated. + * + * This drawing api doesn't support high-level meta texture types such + * as #CoglTexture2DSliced so it is the user's responsibility to + * ensure that only low-level textures that can be directly sampled by + * a GPU such as #CoglTexture2D, #CoglTextureRectangle or #CoglTexture3D + * are associated with layers of the given @pipeline. + * + * Stability: unstable + * Since: 1.10 + * Deprecated: 1.16: Use #CoglPrimitives and + * cogl_primitive_draw() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_primitive_draw) +void +cogl_framebuffer_vdraw_attributes (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglVerticesMode mode, + int first_vertex, + int n_vertices, + ...) COGL_GNUC_NULL_TERMINATED; + +/** + * cogl_framebuffer_draw_attributes: + * @framebuffer: A destination #CoglFramebuffer + * @pipeline: A #CoglPipeline state object + * @mode: The #CoglVerticesMode defining the topology of vertices + * @first_vertex: The vertex offset within the given attributes to draw from + * @n_vertices: The number of vertices to draw from the given attributes + * @attributes: An array of pointers to #CoglAttribute<-- -->s defining vertex + * geometry + * @n_attributes: The number of attributes in the @attributes array. + * + * First defines a geometry primitive by grouping a set of vertex @attributes; + * specifying a @first_vertex; a number of vertices (@n_vertices) and + * specifying what kind of topology the vertices have via @mode. + * + * Then the function draws the given @primitive geometry to the specified + * destination @framebuffer using the graphics processing pipeline described by + * @pipeline. + * + * The list of #CoglAttributes define the attributes of the vertices to + * be drawn, such as positions, colors and normals and the number of attributes + * is given as @n_attributes. + * + * This drawing api doesn't support high-level meta texture types such + * as #CoglTexture2DSliced so it is the user's responsibility to + * ensure that only low-level textures that can be directly sampled by + * a GPU such as #CoglTexture2D, #CoglTextureRectangle or #CoglTexture3D + * are associated with layers of the given @pipeline. + * + * This api doesn't support any of the legacy global state options such + * as cogl_set_depth_test_enabled(), cogl_set_backface_culling_enabled() or + * cogl_program_use() + * + * Stability: unstable + * Since: 1.10 + * Deprecated: 1.16: Use #CoglPrimitives and + * cogl_primitive_draw() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_primitive_draw) +void +cogl_framebuffer_draw_attributes (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglVerticesMode mode, + int first_vertex, + int n_vertices, + CoglAttribute **attributes, + int n_attributes); + +/** + * cogl_framebuffer_vdraw_indexed_attributes: + * @framebuffer: A destination #CoglFramebuffer + * @pipeline: A #CoglPipeline state object + * @mode: The #CoglVerticesMode defining the topology of vertices + * @first_vertex: The vertex offset within the given attributes to draw from + * @n_vertices: The number of vertices to draw from the given attributes + * @indices: The array of indices used by the GPU to lookup attribute + * data for each vertex. + * @...: A set of vertex #CoglAttributes defining vertex geometry + * + * Behaves the same as cogl_framebuffer_vdraw_attributes() except that + * instead of reading vertex data sequentially from the specified + * attributes the @indices provide an indirection for how the data + * should be indexed allowing a random access order to be + * specified. + * + * For example an indices array of [0, 1, 2, 0, 2, 3] could be used + * used to draw two triangles (@mode = %COGL_VERTICES_MODE_TRIANGLES + + * @n_vertices = 6) but only provide attribute data for the 4 corners + * of a rectangle. When the GPU needs to read in each of the 6 + * vertices it will read the @indices array for each vertex in + * sequence and use the index to look up the vertex attribute data. So + * here you can see that first and fourth vertex will point to the + * same data and third and fifth vertex will also point to shared + * data. + * + * Drawing with indices can be a good way of minimizing the size of a + * mesh by allowing you to avoid data for duplicate vertices because + * multiple entries in the index array can refer back to a single + * shared vertex. + * + * The @indices array must be at least as long as @first_vertex + * + @n_vertices otherwise the GPU will overrun the indices array when + * looking up vertex data. + * + * Since it's very common to want to draw a run of rectangles using + * indices to avoid duplicating vertex data you can use + * cogl_get_rectangle_indices() to get a set of indices that can be + * shared. + * + * This drawing api doesn't support high-level meta texture types such + * as #CoglTexture2DSliced so it is the user's responsibility to + * ensure that only low-level textures that can be directly sampled by + * a GPU such as #CoglTexture2D, #CoglTextureRectangle or + * #CoglTexture3D are associated with layers of the given @pipeline. + * + * This api doesn't support any of the legacy global state + * options such as cogl_set_depth_test_enabled(), + * cogl_set_backface_culling_enabled() or cogl_program_use() + * + * Stability: unstable + * Since: 1.10 + * Deprecated: 1.16: Use #CoglPrimitives and + * cogl_primitive_draw() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_primitive_draw) +void +cogl_framebuffer_vdraw_indexed_attributes (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglVerticesMode mode, + int first_vertex, + int n_vertices, + CoglIndices *indices, + ...) COGL_GNUC_NULL_TERMINATED; + +/** + * cogl_framebuffer_draw_indexed_attributes: + * @framebuffer: A destination #CoglFramebuffer + * @pipeline: A #CoglPipeline state object + * @mode: The #CoglVerticesMode defining the topology of vertices + * @first_vertex: The vertex offset within the given attributes to draw from + * @n_vertices: The number of vertices to draw from the given attributes + * @indices: The array of indices used by the GPU to lookup attribute + * data for each vertex. + * @attributes: An array of pointers to #CoglAttribute<-- -->s defining vertex + * geometry + * @n_attributes: The number of attributes in the @attributes array. + * + * Behaves the same as cogl_framebuffer_draw_attributes() except that + * instead of reading vertex data sequentially from the specified + * @attributes the @indices provide an indirection for how the data + * should be indexed allowing a random access order to be + * specified. + * + * For example an indices array of [0, 1, 2, 0, 2, 3] could be used + * used to draw two triangles (@mode = %COGL_VERTICES_MODE_TRIANGLES + + * @n_vertices = 6) but only provide attribute data for the 4 corners + * of a rectangle. When the GPU needs to read in each of the 6 + * vertices it will read the @indices array for each vertex in + * sequence and use the index to look up the vertex attribute data. So + * here you can see that first and fourth vertex will point to the + * same data and third and fifth vertex will also point to shared + * data. + * + * Drawing with indices can be a good way of minimizing the size of a + * mesh by allowing you to avoid data for duplicate vertices because + * multiple entries in the index array can refer back to a single + * shared vertex. + * + * The @indices array must be at least as long as @first_vertex + * + @n_vertices otherwise the GPU will overrun the indices array when + * looking up vertex data. + * + * Since it's very common to want to draw a run of rectangles using + * indices to avoid duplicating vertex data you can use + * cogl_get_rectangle_indices() to get a set of indices that can be + * shared. + * + * This drawing api doesn't support high-level meta texture types such + * as #CoglTexture2DSliced so it is the user's responsibility to + * ensure that only low-level textures that can be directly sampled by + * a GPU such as #CoglTexture2D, #CoglTextureRectangle or + * #CoglTexture3D are associated with layers of the given @pipeline. + * + * This api doesn't support any of the legacy global state + * options such as cogl_set_depth_test_enabled(), + * cogl_set_backface_culling_enabled() or cogl_program_use() + * + * Stability: unstable + * Since: 1.10 + * Deprecated: 1.16: Use #CoglPrimitives and + * cogl_primitive_draw() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_primitive_draw) +void +cogl_framebuffer_draw_indexed_attributes (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglVerticesMode mode, + int first_vertex, + int n_vertices, + CoglIndices *indices, + CoglAttribute **attributes, + int n_attributes); + +/** + * cogl_framebuffer_draw_rectangle: + * @framebuffer: A destination #CoglFramebuffer + * @pipeline: A #CoglPipeline state object + * @x_1: X coordinate of the top-left corner + * @y_1: Y coordinate of the top-left corner + * @x_2: X coordinate of the bottom-right corner + * @y_2: Y coordinate of the bottom-right corner + * + * Draws a rectangle to @framebuffer with the given @pipeline state + * and with the top left corner positioned at (@x_1, @y_1) and the + * bottom right corner positioned at (@x_2, @y_2). + * + * The position is the position before the rectangle has been + * transformed by the model-view matrix and the projection + * matrix. + * + * If you want to describe a rectangle with a texture mapped on + * it then you can use + * cogl_framebuffer_draw_textured_rectangle(). + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_framebuffer_draw_rectangle (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + float x_1, + float y_1, + float x_2, + float y_2); + +/** + * cogl_framebuffer_draw_textured_rectangle: + * @framebuffer: A destination #CoglFramebuffer + * @pipeline: A #CoglPipeline state object + * @x_1: x coordinate upper left on screen. + * @y_1: y coordinate upper left on screen. + * @x_2: x coordinate lower right on screen. + * @y_2: y coordinate lower right on screen. + * @s_1: S texture coordinate of the top-left coorner + * @t_1: T texture coordinate of the top-left coorner + * @s_2: S texture coordinate of the bottom-right coorner + * @t_2: T texture coordinate of the bottom-right coorner + * + * Draws a textured rectangle to @framebuffer using the given + * @pipeline state with the top left corner positioned at (@x_1, @y_1) + * and the bottom right corner positioned at (@x_2, @y_2). The top + * left corner will have texture coordinates of (@s_1, @t_1) and the + * bottom right corner will have texture coordinates of (@s_2, @t_2). + * + * The position is the position before the rectangle has been + * transformed by the model-view matrix and the projection + * matrix. + * + * This is a high level drawing api that can handle any kind of + * #CoglMetaTexture texture such as #CoglTexture2DSliced textures + * which may internally be comprised of multiple low-level textures. + * This is unlike low-level drawing apis such as cogl_primitive_draw() + * which only support low level texture types that are directly + * supported by GPUs such as #CoglTexture2D. + * + * The given texture coordinates will only be used for the first + * texture layer of the pipeline and if your pipeline has more than + * one layer then all other layers will have default texture + * coordinates of @s_1=0.0 @t_1=0.0 @s_2=1.0 @t_2=1.0 + * + * The given texture coordinates should always be normalized such that + * (0, 0) corresponds to the top left and (1, 1) corresponds to the + * bottom right. To map an entire texture across the rectangle pass + * in @s_1=0, @t_1=0, @s_2=1, @t_2=1. + * + * Even if you have associated a #CoglTextureRectangle texture + * with one of your @pipeline layers which normally implies working + * with non-normalized texture coordinates this api should still be + * passed normalized texture coordinates. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_framebuffer_draw_textured_rectangle (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + float x_1, + float y_1, + float x_2, + float y_2, + float s_1, + float t_1, + float s_2, + float t_2); + +/** + * cogl_framebuffer_draw_multitextured_rectangle: + * @framebuffer: A destination #CoglFramebuffer + * @pipeline: A #CoglPipeline state object + * @x_1: x coordinate upper left on screen. + * @y_1: y coordinate upper left on screen. + * @x_2: x coordinate lower right on screen. + * @y_2: y coordinate lower right on screen. + * @tex_coords: (in) (array) (transfer none): An array containing groups of + * 4 float values: [s_1, t_1, s_2, t_2] that are interpreted as two texture + * coordinates; one for the top left texel, and one for the bottom right + * texel. Each value should be between 0.0 and 1.0, where the coordinate + * (0.0, 0.0) represents the top left of the texture, and (1.0, 1.0) the + * bottom right. + * @tex_coords_len: The length of the @tex_coords array. (For one layer + * and one group of texture coordinates, this would be 4) + * + * Draws a textured rectangle to @framebuffer with the given @pipeline + * state with the top left corner positioned at (@x_1, @y_1) and the + * bottom right corner positioned at (@x_2, @y_2). As a pipeline may + * contain multiple texture layers this interface lets you supply + * texture coordinates for each layer of the pipeline. + * + * The position is the position before the rectangle has been + * transformed by the model-view matrix and the projection + * matrix. + * + * This is a high level drawing api that can handle any kind of + * #CoglMetaTexture texture for the first layer such as + * #CoglTexture2DSliced textures which may internally be comprised of + * multiple low-level textures. This is unlike low-level drawing apis + * such as cogl_primitive_draw() which only support low level texture + * types that are directly supported by GPUs such as #CoglTexture2D. + * + * This api can not currently handle multiple high-level meta + * texture layers. The first layer may be a high level meta texture + * such as #CoglTexture2DSliced but all other layers much be low + * level textures such as #CoglTexture2D and additionally they + * should be textures that can be sampled using normalized coordinates + * (so not #CoglTextureRectangle textures). + * + * The top left texture coordinate for layer 0 of any pipeline will be + * (tex_coords[0], tex_coords[1]) and the bottom right coordinate will + * be (tex_coords[2], tex_coords[3]). The coordinates for layer 1 + * would be (tex_coords[4], tex_coords[5]) (tex_coords[6], + * tex_coords[7]) and so on... + * + * The given texture coordinates should always be normalized such that + * (0, 0) corresponds to the top left and (1, 1) corresponds to the + * bottom right. To map an entire texture across the rectangle pass + * in tex_coords[0]=0, tex_coords[1]=0, tex_coords[2]=1, + * tex_coords[3]=1. + * + * Even if you have associated a #CoglTextureRectangle texture + * which normally implies working with non-normalized texture + * coordinates this api should still be passed normalized texture + * coordinates. + * + * The first pair of coordinates are for the first layer (with the + * smallest layer index) and if you supply less texture coordinates + * than there are layers in the current source material then default + * texture coordinates (0.0, 0.0, 1.0, 1.0) are generated. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_framebuffer_draw_multitextured_rectangle (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + float x_1, + float y_1, + float x_2, + float y_2, + const float *tex_coords, + int tex_coords_len); + +/** + * cogl_framebuffer_draw_rectangles: + * @framebuffer: A destination #CoglFramebuffer + * @pipeline: A #CoglPipeline state object + * @coordinates: (in) (array) (transfer none): an array of coordinates + * containing groups of 4 float values: [x_1, y_1, x_2, y_2] that are + * interpreted as two position coordinates; one for the top left of + * the rectangle (x1, y1), and one for the bottom right of the + * rectangle (x2, y2). + * @n_rectangles: number of rectangles defined in @coordinates. + * + * Draws a series of rectangles to @framebuffer with the given + * @pipeline state in the same way that + * cogl_framebuffer_draw_rectangle() does. + * + * The top left corner of the first rectangle is positioned at + * (coordinates[0], coordinates[1]) and the bottom right corner is + * positioned at (coordinates[2], coordinates[3]). The positions for + * the second rectangle are (coordinates[4], coordinates[5]) and + * (coordinates[6], coordinates[7]) and so on... + * + * The position is the position before the rectangle has been + * transformed by the model-view matrix and the projection + * matrix. + * + * As a general rule for better performance its recommended to use + * this this API instead of calling + * cogl_framebuffer_draw_textured_rectangle() separately for multiple + * rectangles if all of the rectangles will be drawn together with the + * same @pipeline state. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_framebuffer_draw_rectangles (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + const float *coordinates, + unsigned int n_rectangles); + +/** + * cogl_framebuffer_draw_textured_rectangles: + * @framebuffer: A destination #CoglFramebuffer + * @pipeline: A #CoglPipeline state object + * @coordinates: (in) (array) (transfer none): an array containing + * groups of 8 float values: [x_1, y_1, x_2, y_2, s_1, t_1, s_2, t_2] + * that have the same meaning as the arguments for + * cogl_framebuffer_draw_textured_rectangle(). + * @n_rectangles: number of rectangles to @coordinates to draw + * + * Draws a series of rectangles to @framebuffer with the given + * @pipeline state in the same way that + * cogl_framebuffer_draw_textured_rectangle() does. + * + * The position is the position before the rectangle has been + * transformed by the model-view matrix and the projection + * matrix. + * + * This is a high level drawing api that can handle any kind of + * #CoglMetaTexture texture such as #CoglTexture2DSliced textures + * which may internally be comprised of multiple low-level textures. + * This is unlike low-level drawing apis such as cogl_primitive_draw() + * which only support low level texture types that are directly + * supported by GPUs such as #CoglTexture2D. + * + * The top left corner of the first rectangle is positioned at + * (coordinates[0], coordinates[1]) and the bottom right corner is + * positioned at (coordinates[2], coordinates[3]). The top left + * texture coordinate is (coordinates[4], coordinates[5]) and the + * bottom right texture coordinate is (coordinates[6], + * coordinates[7]). The coordinates for subsequent rectangles + * are defined similarly by the subsequent coordinates. + * + * As a general rule for better performance its recommended to use + * this this API instead of calling + * cogl_framebuffer_draw_textured_rectangle() separately for multiple + * rectangles if all of the rectangles will be drawn together with the + * same @pipeline state. + * + * The given texture coordinates should always be normalized such that + * (0, 0) corresponds to the top left and (1, 1) corresponds to the + * bottom right. To map an entire texture across the rectangle pass + * in tex_coords[0]=0, tex_coords[1]=0, tex_coords[2]=1, + * tex_coords[3]=1. + * + * Even if you have associated a #CoglTextureRectangle texture + * which normally implies working with non-normalized texture + * coordinates this api should still be passed normalized texture + * coordinates. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_framebuffer_draw_textured_rectangles (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + const float *coordinates, + unsigned int n_rectangles); + +/* XXX: Should we take an n_buffers + buffer id array instead of using + * the CoglBufferBits type which doesn't seem future proof? */ +/** + * cogl_framebuffer_discard_buffers: + * @framebuffer: A #CoglFramebuffer + * @buffers: A #CoglBufferBit mask of which ancillary buffers you want + * to discard. + * + * Declares that the specified @buffers no longer need to be referenced + * by any further rendering commands. This can be an important + * optimization to avoid subsequent frames of rendering depending on + * the results of a previous frame. + * + * For example; some tile-based rendering GPUs are able to avoid allocating and + * accessing system memory for the depth and stencil buffer so long as these + * buffers are not required as input for subsequent frames and that can save a + * significant amount of memory bandwidth used to save and restore their + * contents to system memory between frames. + * + * It is currently considered an error to try and explicitly discard the color + * buffer by passing %COGL_BUFFER_BIT_COLOR. This is because the color buffer is + * already implicitly discard when you finish rendering to a #CoglOnscreen + * framebuffer, and it's not meaningful to try and discard the color buffer of + * a #CoglOffscreen framebuffer since they are single-buffered. + * + * + * Since: 1.8 + * Stability: unstable + */ +void +cogl_framebuffer_discard_buffers (CoglFramebuffer *framebuffer, + unsigned long buffers); + +/** + * cogl_framebuffer_finish: + * @framebuffer: A #CoglFramebuffer pointer + * + * This blocks the CPU until all pending rendering associated with the + * specified framebuffer has completed. It's very rare that developers should + * ever need this level of synchronization with the GPU and should never be + * used unless you clearly understand why you need to explicitly force + * synchronization. + * + * One example might be for benchmarking purposes to be sure timing + * measurements reflect the time that the GPU is busy for not just the time it + * takes to queue rendering commands. + * + * Stability: unstable + * Since: 1.10 + */ +void +cogl_framebuffer_finish (CoglFramebuffer *framebuffer); + +/** + * cogl_framebuffer_read_pixels_into_bitmap: + * @framebuffer: A #CoglFramebuffer + * @x: The x position to read from + * @y: The y position to read from + * @source: Identifies which auxillary buffer you want to read + * (only COGL_READ_PIXELS_COLOR_BUFFER supported currently) + * @bitmap: The bitmap to store the results in. + * + * This reads a rectangle of pixels from the given framebuffer where + * position (0, 0) is the top left. The pixel at (x, y) is the first + * read, and a rectangle of pixels with the same size as the bitmap is + * read right and downwards from that point. + * + * Currently Cogl assumes that the framebuffer is in a premultiplied + * format so if the format of @bitmap is non-premultiplied it will + * convert it. To read the pixel values without any conversion you + * should either specify a format that doesn't use an alpha channel or + * use one of the formats ending in PRE. + * + * Return value: %TRUE if the read succeeded or %FALSE otherwise. The + * function is only likely to fail if the bitmap points to a pixel + * buffer and it could not be mapped. + * Since: 1.10 + * Stability: unstable + */ +CoglBool +cogl_framebuffer_read_pixels_into_bitmap (CoglFramebuffer *framebuffer, + int x, + int y, + CoglReadPixelsFlags source, + CoglBitmap *bitmap); + +/** + * cogl_framebuffer_read_pixels: + * @framebuffer: A #CoglFramebuffer + * @x: The x position to read from + * @y: The y position to read from + * @width: The width of the region of rectangles to read + * @height: The height of the region of rectangles to read + * @format: The pixel format to store the data in + * @pixels: The address of the buffer to store the data in + * + * This is a convenience wrapper around + * cogl_framebuffer_read_pixels_into_bitmap() which allocates a + * temporary #CoglBitmap to read pixel data directly into the given + * buffer. The rowstride of the buffer is assumed to be the width of + * the region times the bytes per pixel of the format. The source for + * the data is always taken from the color buffer. If you want to use + * any other rowstride or source, please use the + * cogl_framebuffer_read_pixels_into_bitmap() function directly. + * + * The implementation of the function looks like this: + * + * |[ + * bitmap = cogl_bitmap_new_for_data (context, + * width, height, + * format, + * /* rowstride */ + * bpp * width, + * pixels); + * cogl_framebuffer_read_pixels_into_bitmap (framebuffer, + * x, y, + * COGL_READ_PIXELS_COLOR_BUFFER, + * bitmap); + * cogl_object_unref (bitmap); + * ]| + * + * Return value: %TRUE if the read succeeded or %FALSE otherwise. + * Since: 1.10 + * Stability: unstable + */ +CoglBool +cogl_framebuffer_read_pixels (CoglFramebuffer *framebuffer, + int x, + int y, + int width, + int height, + CoglPixelFormat format, + uint8_t *pixels); + +/** + * cogl_get_draw_framebuffer: + * + * Gets the current #CoglFramebuffer as set using + * cogl_push_framebuffer() + * + * Return value: (transfer none): The current #CoglFramebuffer + * Stability: unstable + * Since: 1.8 + */ +CoglFramebuffer * +cogl_get_draw_framebuffer (void); + +uint32_t +cogl_framebuffer_error_quark (void); + +/** + * COGL_FRAMEBUFFER_ERROR: + * + * An error domain for reporting #CoglFramebuffer exceptions + */ +#define COGL_FRAMEBUFFER_ERROR (cogl_framebuffer_error_quark ()) + +typedef enum { /*< prefix=COGL_FRAMEBUFFER_ERROR >*/ + COGL_FRAMEBUFFER_ERROR_ALLOCATE +} CoglFramebufferError; + +/** + * cogl_is_framebuffer: + * @object: A #CoglObject pointer + * + * Gets whether the given object references a #CoglFramebuffer. + * + * Return value: %TRUE if the object references a #CoglFramebuffer + * and %FALSE otherwise. + * Since: 1.10 + * Stability: unstable + */ +CoglBool +cogl_is_framebuffer (void *object); + +COGL_END_DECLS + +#endif /* __COGL_FRAMEBUFFER_H */ diff --git a/cogl/cogl/cogl-gl-header.h.in b/cogl/cogl/cogl-gl-header.h.in new file mode 100644 index 0000000..a6659e9 --- /dev/null +++ b/cogl/cogl/cogl-gl-header.h.in @@ -0,0 +1,46 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#if !defined(COGL_COMPILATION) && !defined(COGL_ENABLE_MUTTER_API) +#error "cogl-gl-header.h should only be included when compiling Cogl" +#endif + +#ifndef __COGL_GL_HEADER_H__ +#define __COGL_GL_HEADER_H__ + +#include "cogl-defines.h" + +@COGL_GL_HEADER_INCLUDES@ + +#ifndef GL_OES_EGL_image +#define GLeglImageOES void * +#endif + +#endif /* __COGL_GL_HEADER_H__ */ diff --git a/cogl/cogl/cogl-gles2-context-private.h b/cogl/cogl/cogl-gles2-context-private.h new file mode 100644 index 0000000..805b064 --- /dev/null +++ b/cogl/cogl/cogl-gles2-context-private.h @@ -0,0 +1,201 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Collabora Ltd. + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Tomeu Vizoso + * Robert Bragg + * + */ + +#ifndef __COGL_GLES2_CONTEXT_PRIVATE_H +#define __COGL_GLES2_CONTEXT_PRIVATE_H + +#include + +#include "cogl-object-private.h" +#include "cogl-framebuffer-private.h" +#include "cogl-list.h" + +typedef struct _CoglGLES2Offscreen +{ + CoglList link; + CoglOffscreen *original_offscreen; + CoglGLFramebuffer gl_framebuffer; +} CoglGLES2Offscreen; + +typedef struct +{ + /* GL's ID for the shader */ + GLuint object_id; + /* Shader type */ + GLenum type; + + /* Number of references to this shader. The shader will have one + * reference when it is created. This reference will be removed when + * glDeleteShader is called. An additional reference will be taken + * whenever the shader is attached to a program. This is necessary + * to correctly detect when a shader is destroyed because + * glDeleteShader doesn't actually delete the object if it is + * attached to a program */ + int ref_count; + + /* Set once this object has had glDeleteShader called on it. We need + * to keep track of this so we don't deref the data twice if the + * application calls glDeleteShader multiple times */ + CoglBool deleted; +} CoglGLES2ShaderData; + +typedef enum +{ + COGL_GLES2_FLIP_STATE_UNKNOWN, + COGL_GLES2_FLIP_STATE_NORMAL, + COGL_GLES2_FLIP_STATE_FLIPPED +} CoglGLES2FlipState; + +typedef struct +{ + /* GL's ID for the program */ + GLuint object_id; + + /* List of shaders attached to this program */ + GList *attached_shaders; + + /* Reference count. There can be up to two references. One of these + * will exist between glCreateProgram and glDeleteShader, the other + * will exist while the program is made current. This is necessary + * to correctly detect when the program is deleted because + * glDeleteShader will delay the deletion if the program is + * current */ + int ref_count; + + /* Set once this object has had glDeleteProgram called on it. We need + * to keep track of this so we don't deref the data twice if the + * application calls glDeleteProgram multiple times */ + CoglBool deleted; + + GLuint flip_vector_location; + + /* A cache of what value we've put in the flip vector uniform so + * that we don't flush unless it's changed */ + CoglGLES2FlipState flip_vector_state; + + CoglGLES2Context *context; +} CoglGLES2ProgramData; + +/* State tracked for each texture unit */ +typedef struct +{ + /* The currently bound texture for the GL_TEXTURE_2D */ + GLuint current_texture_2d; +} CoglGLES2TextureUnitData; + +/* State tracked for each texture object */ +typedef struct +{ + /* GL's ID for this object */ + GLuint object_id; + + GLenum target; + + /* The details for texture when it has a 2D target */ + int width, height; + GLenum format; +} CoglGLES2TextureObjectData; + +struct _CoglGLES2Context +{ + CoglObject _parent; + + CoglContext *context; + + /* This is set to FALSE until the first time the GLES2 context is + * bound to something. We need to keep track of this so we can set + * the viewport and scissor the first time it is bound. */ + CoglBool has_been_bound; + + CoglFramebuffer *read_buffer; + CoglGLES2Offscreen *gles2_read_buffer; + CoglFramebuffer *write_buffer; + CoglGLES2Offscreen *gles2_write_buffer; + + GLuint current_fbo_handle; + + CoglList foreign_offscreens; + + CoglGLES2Vtable *vtable; + + /* Hash table mapping GL's IDs for shaders and objects to ShaderData + * and ProgramData so that we can maintain extra data for these + * objects. Although technically the IDs will end up global across + * all GLES2 contexts because they will all be in the same share + * list, we don't really want to expose this outside of the Cogl API + * so we will assume it is undefined behaviour if an application + * relies on this. */ + GHashTable *shader_map; + GHashTable *program_map; + + /* Currently in use program. We need to keep track of this so that + * we can keep a reference to the data for the program while it is + * current */ + CoglGLES2ProgramData *current_program; + + /* Whether the currently bound framebuffer needs flipping. This is + * used to check for changes so that we can dirty the following + * state flags */ + CoglGLES2FlipState current_flip_state; + + /* The following state is tracked separately from the GL context + * because we need to modify it depending on whether we are flipping + * the geometry. */ + CoglBool viewport_dirty; + int viewport[4]; + CoglBool scissor_dirty; + int scissor[4]; + CoglBool front_face_dirty; + GLenum front_face; + + /* We need to keep track of the pack alignment so we can flip the + * results of glReadPixels read from a CoglOffscreen */ + int pack_alignment; + + /* A hash table of CoglGLES2TextureObjects indexed by the texture + * object ID so that we can track some state */ + GHashTable *texture_object_map; + + /* Array of CoglGLES2TextureUnits to keep track of state for each + * texture unit */ + GArray *texture_units; + + /* The currently active texture unit indexed from 0 (not from + * GL_TEXTURE0) */ + int current_texture_unit; + + void *winsys; +}; + +#endif /* __COGL_GLES2_CONTEXT_PRIVATE_H */ diff --git a/cogl/cogl/cogl-gles2-context.c b/cogl/cogl/cogl-gles2-context.c new file mode 100644 index 0000000..78d423f --- /dev/null +++ b/cogl/cogl/cogl-gles2-context.c @@ -0,0 +1,1966 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Collabora Ltd. + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Tomeu Vizoso + * Robert Bragg + * Neil Roberts + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include + +#include "cogl-gles2.h" +#include "cogl-gles2-context-private.h" + +#include "cogl-context-private.h" +#include "cogl-display-private.h" +#include "cogl-framebuffer-private.h" +#include "cogl-framebuffer-gl-private.h" +#include "cogl-onscreen-template-private.h" +#include "cogl-renderer-private.h" +#include "cogl-swap-chain-private.h" +#include "cogl-texture-2d-gl.h" +#include "cogl-texture-2d-private.h" +#include "cogl-pipeline-opengl-private.h" +#include "cogl-error-private.h" +#include "cogl-gtype-private.h" + +static void _cogl_gles2_context_free (CoglGLES2Context *gles2_context); + +COGL_OBJECT_DEFINE (GLES2Context, gles2_context); +COGL_GTYPE_DEFINE_CLASS (GLES2Context, gles2_context); + +static CoglGLES2Context *current_gles2_context; + +static CoglUserDataKey offscreen_wrapper_key; + +/* The application's main function is renamed to this so that we can + * provide an alternative main function */ +#define MAIN_WRAPPER_REPLACEMENT_NAME "_c31" +/* This uniform is used to flip the rendering or not depending on + * whether we are rendering to an offscreen buffer or not */ +#define MAIN_WRAPPER_FLIP_UNIFORM "_cogl_flip_vector" +/* These comments are used to delimit the added wrapper snippet so + * that we can remove it again when the shader source is requested via + * glGetShaderSource */ +#define MAIN_WRAPPER_BEGIN "/*_COGL_WRAPPER_BEGIN*/" +#define MAIN_WRAPPER_END "/*_COGL_WRAPPER_END*/" + +/* This wrapper function around 'main' is appended to every vertex shader + * so that we can add some extra code to flip the rendering when + * rendering to an offscreen buffer */ +static const char +main_wrapper_function[] = + MAIN_WRAPPER_BEGIN "\n" + "uniform vec4 " MAIN_WRAPPER_FLIP_UNIFORM ";\n" + "\n" + "void\n" + "main ()\n" + "{\n" + " " MAIN_WRAPPER_REPLACEMENT_NAME " ();\n" + " gl_Position *= " MAIN_WRAPPER_FLIP_UNIFORM ";\n" + "}\n" + MAIN_WRAPPER_END; + +enum { + RESTORE_FB_NONE, + RESTORE_FB_FROM_OFFSCREEN, + RESTORE_FB_FROM_ONSCREEN, +}; + +uint32_t +_cogl_gles2_context_error_quark (void) +{ + return g_quark_from_static_string ("cogl-gles2-context-error-quark"); +} + +static void +shader_data_unref (CoglGLES2Context *context, + CoglGLES2ShaderData *shader_data) +{ + if (--shader_data->ref_count < 1) + /* Removing the hash table entry should also destroy the data */ + g_hash_table_remove (context->shader_map, + GINT_TO_POINTER (shader_data->object_id)); +} + +static void +program_data_unref (CoglGLES2ProgramData *program_data) +{ + if (--program_data->ref_count < 1) + /* Removing the hash table entry should also destroy the data */ + g_hash_table_remove (program_data->context->program_map, + GINT_TO_POINTER (program_data->object_id)); +} + +static void +detach_shader (CoglGLES2ProgramData *program_data, + CoglGLES2ShaderData *shader_data) +{ + GList *l; + + for (l = program_data->attached_shaders; l; l = l->next) + { + if (l->data == shader_data) + { + shader_data_unref (program_data->context, shader_data); + program_data->attached_shaders = + g_list_delete_link (program_data->attached_shaders, l); + break; + } + } +} + +static CoglBool +is_symbol_character (char ch) +{ + return g_ascii_isalnum (ch) || ch == '_'; +} + +static void +replace_token (char *string, + const char *token, + const char *replacement, + int length) +{ + char *token_pos; + char *last_pos = string; + char *end = string + length; + int token_length = strlen (token); + + /* NOTE: this assumes token and replacement are the same length */ + + while ((token_pos = _cogl_util_memmem (last_pos, + end - last_pos, + token, + token_length))) + { + /* Make sure this isn't in the middle of some longer token */ + if ((token_pos <= string || + !is_symbol_character (token_pos[-1])) && + (token_pos + token_length == end || + !is_symbol_character (token_pos[token_length]))) + memcpy (token_pos, replacement, token_length); + + last_pos = token_pos + token_length; + } +} + +static void +update_current_flip_state (CoglGLES2Context *gles2_ctx) +{ + CoglGLES2FlipState new_flip_state; + + if (gles2_ctx->current_fbo_handle == 0 && + cogl_is_offscreen (gles2_ctx->write_buffer)) + new_flip_state = COGL_GLES2_FLIP_STATE_FLIPPED; + else + new_flip_state = COGL_GLES2_FLIP_STATE_NORMAL; + + /* If the flip state has changed then we need to reflush all of the + * dependent state */ + if (new_flip_state != gles2_ctx->current_flip_state) + { + gles2_ctx->viewport_dirty = TRUE; + gles2_ctx->scissor_dirty = TRUE; + gles2_ctx->front_face_dirty = TRUE; + gles2_ctx->current_flip_state = new_flip_state; + } +} + +static GLuint +get_current_texture_2d_object (CoglGLES2Context *gles2_ctx) +{ + return g_array_index (gles2_ctx->texture_units, + CoglGLES2TextureUnitData, + gles2_ctx->current_texture_unit).current_texture_2d; +} + +static void +set_texture_object_data (CoglGLES2Context *gles2_ctx, + GLenum target, + GLint level, + GLenum internal_format, + GLsizei width, + GLsizei height) +{ + GLuint texture_id = get_current_texture_2d_object (gles2_ctx); + CoglGLES2TextureObjectData *texture_object; + + /* We want to keep track of all texture objects where the data is + * created by this context so that we can delete them later */ + texture_object = g_hash_table_lookup (gles2_ctx->texture_object_map, + GUINT_TO_POINTER (texture_id)); + if (texture_object == NULL) + { + texture_object = g_slice_new0 (CoglGLES2TextureObjectData); + texture_object->object_id = texture_id; + + g_hash_table_insert (gles2_ctx->texture_object_map, + GUINT_TO_POINTER (texture_id), + texture_object); + } + + switch (target) + { + case GL_TEXTURE_2D: + texture_object->target = GL_TEXTURE_2D; + + /* We want to keep track of the dimensions of any texture object + * setting the GL_TEXTURE_2D target */ + if (level == 0) + { + texture_object->width = width; + texture_object->height = height; + texture_object->format = internal_format; + } + break; + + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + texture_object->target = GL_TEXTURE_CUBE_MAP; + break; + } +} + +static void +copy_flipped_texture (CoglGLES2Context *gles2_ctx, + int level, + int src_x, + int src_y, + int dst_x, + int dst_y, + int width, + int height) +{ + GLuint tex_id = get_current_texture_2d_object (gles2_ctx); + CoglGLES2TextureObjectData *tex_object_data; + CoglContext *ctx; + const CoglWinsysVtable *winsys; + CoglTexture2D *dst_texture; + CoglPixelFormat internal_format; + + tex_object_data = g_hash_table_lookup (gles2_ctx->texture_object_map, + GUINT_TO_POINTER (tex_id)); + + /* We can't do anything if the application hasn't set a level 0 + * image on this texture object */ + if (tex_object_data == NULL || + tex_object_data->target != GL_TEXTURE_2D || + tex_object_data->width <= 0 || + tex_object_data->height <= 0) + return; + + switch (tex_object_data->format) + { + case GL_RGB: + internal_format = COGL_PIXEL_FORMAT_RGB_888; + break; + + case GL_RGBA: + internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE; + break; + + case GL_ALPHA: + internal_format = COGL_PIXEL_FORMAT_A_8; + break; + + case GL_LUMINANCE: + internal_format = COGL_PIXEL_FORMAT_G_8; + break; + + default: + /* We can't handle this format so just give up */ + return; + } + + ctx = gles2_ctx->context; + winsys = ctx->display->renderer->winsys_vtable; + + /* We need to make sure the rendering on the GLES2 context is + * complete before the blit will be ready in the GLES2 context */ + ctx->glFinish (); + /* We need to force Cogl to rebind the texture because according to + * the GL spec a shared texture isn't guaranteed to be updated until + * is rebound */ + _cogl_get_texture_unit (0)->dirty_gl_texture = TRUE; + + /* Temporarily switch back to the Cogl context */ + winsys->restore_context (ctx); + + dst_texture = + cogl_gles2_texture_2d_new_from_handle (gles2_ctx->context, + gles2_ctx, + tex_id, + tex_object_data->width, + tex_object_data->height, + internal_format); + + if (dst_texture) + { + CoglTexture *src_texture = + COGL_OFFSCREEN (gles2_ctx->read_buffer)->texture; + CoglPipeline *pipeline = cogl_pipeline_new (ctx); + const CoglOffscreenFlags flags = COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL; + CoglOffscreen *offscreen = + _cogl_offscreen_new_with_texture_full (COGL_TEXTURE (dst_texture), + flags, level); + int src_width = cogl_texture_get_width (src_texture); + int src_height = cogl_texture_get_height (src_texture); + /* The framebuffer size might be different from the texture size + * if a level > 0 is used */ + int dst_width = + cogl_framebuffer_get_width (COGL_FRAMEBUFFER (offscreen)); + int dst_height = + cogl_framebuffer_get_height (COGL_FRAMEBUFFER (offscreen)); + float x_1, y_1, x_2, y_2, s_1, t_1, s_2, t_2; + + cogl_pipeline_set_layer_texture (pipeline, 0, src_texture); + cogl_pipeline_set_blend (pipeline, + "RGBA = ADD(SRC_COLOR, 0)", + NULL); + cogl_pipeline_set_layer_filters (pipeline, + 0, /* layer_num */ + COGL_PIPELINE_FILTER_NEAREST, + COGL_PIPELINE_FILTER_NEAREST); + + x_1 = dst_x * 2.0f / dst_width - 1.0f; + y_1 = dst_y * 2.0f / dst_height - 1.0f; + x_2 = x_1 + width * 2.0f / dst_width; + y_2 = y_1 + height * 2.0f / dst_height; + + s_1 = src_x / (float) src_width; + t_1 = 1.0f - src_y / (float) src_height; + s_2 = (src_x + width) / (float) src_width; + t_2 = 1.0f - (src_y + height) / (float) src_height; + + cogl_framebuffer_draw_textured_rectangle (COGL_FRAMEBUFFER (offscreen), + pipeline, + x_1, y_1, + x_2, y_2, + s_1, t_1, + s_2, t_2); + + _cogl_framebuffer_flush_journal (COGL_FRAMEBUFFER (offscreen)); + + /* We need to make sure the rendering is complete before the + * blit will be ready in the GLES2 context */ + ctx->glFinish (); + + cogl_object_unref (pipeline); + cogl_object_unref (dst_texture); + cogl_object_unref (offscreen); + } + + winsys->set_gles2_context (gles2_ctx, NULL); + + /* From what I understand of the GL spec, changes to a shared object + * are not guaranteed to be propagated to another context until that + * object is rebound in that context so we can just rebind it + * here */ + gles2_ctx->vtable->glBindTexture (GL_TEXTURE_2D, tex_id); +} + +/* We wrap glBindFramebuffer so that when framebuffer 0 is bound + * we can instead bind the write_framebuffer passed to + * cogl_push_gles2_context(). + */ +static void +gl_bind_framebuffer_wrapper (GLenum target, GLuint framebuffer) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + + gles2_ctx->current_fbo_handle = framebuffer; + + if (framebuffer == 0 && cogl_is_offscreen (gles2_ctx->write_buffer)) + { + CoglGLES2Offscreen *write = gles2_ctx->gles2_write_buffer; + framebuffer = write->gl_framebuffer.fbo_handle; + } + + gles2_ctx->context->glBindFramebuffer (target, framebuffer); + + update_current_flip_state (gles2_ctx); +} + +static int +transient_bind_read_buffer (CoglGLES2Context *gles2_ctx) +{ + if (gles2_ctx->current_fbo_handle == 0) + { + if (cogl_is_offscreen (gles2_ctx->read_buffer)) + { + CoglGLES2Offscreen *read = gles2_ctx->gles2_read_buffer; + GLuint read_fbo_handle = read->gl_framebuffer.fbo_handle; + + gles2_ctx->context->glBindFramebuffer (GL_FRAMEBUFFER, + read_fbo_handle); + + return RESTORE_FB_FROM_OFFSCREEN; + } + else + { + _cogl_framebuffer_gl_bind (gles2_ctx->read_buffer, + 0 /* target ignored */); + + return RESTORE_FB_FROM_ONSCREEN; + } + } + else + return RESTORE_FB_NONE; +} + +static void +restore_write_buffer (CoglGLES2Context *gles2_ctx, + int restore_mode) +{ + switch (restore_mode) + { + case RESTORE_FB_FROM_OFFSCREEN: + + gl_bind_framebuffer_wrapper (GL_FRAMEBUFFER, 0); + + break; + case RESTORE_FB_FROM_ONSCREEN: + + /* Note: we can't restore the original write buffer using + * _cogl_framebuffer_gl_bind() if it's an offscreen + * framebuffer because _cogl_framebuffer_gl_bind() doesn't + * know about the fbo handle owned by the gles2 context. + */ + if (cogl_is_offscreen (gles2_ctx->write_buffer)) + gl_bind_framebuffer_wrapper (GL_FRAMEBUFFER, 0); + else + _cogl_framebuffer_gl_bind (gles2_ctx->write_buffer, GL_FRAMEBUFFER); + + break; + case RESTORE_FB_NONE: + break; + } +} + +/* We wrap glReadPixels so when framebuffer 0 is bound then we can + * read from the read_framebuffer passed to cogl_push_gles2_context(). + */ +static void +gl_read_pixels_wrapper (GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + GLvoid *pixels) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + int restore_mode = transient_bind_read_buffer (gles2_ctx); + + gles2_ctx->context->glReadPixels (x, y, width, height, format, type, pixels); + + restore_write_buffer (gles2_ctx, restore_mode); + + /* If the read buffer is a CoglOffscreen then the data will be + * upside down compared to what GL expects so we need to flip it */ + if (gles2_ctx->current_fbo_handle == 0 && + cogl_is_offscreen (gles2_ctx->read_buffer)) + { + int bpp, bytes_per_row, stride, y; + uint8_t *bytes = pixels; + uint8_t *temprow; + + /* Try to determine the bytes per pixel for the given + * format/type combination. If there's a format which doesn't + * make sense then we'll just give up because GL will probably + * have just thrown an error */ + switch (format) + { + case GL_RGB: + switch (type) + { + case GL_UNSIGNED_BYTE: + bpp = 3; + break; + + case GL_UNSIGNED_SHORT_5_6_5: + bpp = 2; + break; + + default: + return; + } + break; + + case GL_RGBA: + switch (type) + { + case GL_UNSIGNED_BYTE: + bpp = 4; + break; + + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_5_5_5_1: + bpp = 2; + break; + + default: + return; + } + break; + + case GL_ALPHA: + switch (type) + { + case GL_UNSIGNED_BYTE: + bpp = 1; + break; + + default: + return; + } + break; + + default: + return; + } + + bytes_per_row = bpp * width; + stride = ((bytes_per_row + gles2_ctx->pack_alignment - 1) & + ~(gles2_ctx->pack_alignment - 1)); + temprow = g_alloca (bytes_per_row); + + /* vertically flip the buffer in-place */ + for (y = 0; y < height / 2; y++) + { + if (y != height - y - 1) /* skip center row */ + { + memcpy (temprow, + bytes + y * stride, + bytes_per_row); + memcpy (bytes + y * stride, + bytes + (height - y - 1) * stride, + bytes_per_row); + memcpy (bytes + (height - y - 1) * stride, + temprow, + bytes_per_row); + } + } + } +} + +static void +gl_copy_tex_image_2d_wrapper (GLenum target, + GLint level, + GLenum internal_format, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLint border) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + + /* If we are reading from a CoglOffscreen buffer then the image will + * be upside down with respect to what GL expects so we can't use + * glCopyTexImage2D. Instead we we'll try to use the Cogl API to + * flip it */ + if (gles2_ctx->current_fbo_handle == 0 && + cogl_is_offscreen (gles2_ctx->read_buffer)) + { + /* This will only work with the GL_TEXTURE_2D target. FIXME: + * GLES2 also supports setting cube map textures with + * glTexImage2D so we need to handle that too */ + if (target != GL_TEXTURE_2D) + return; + + /* Create an empty texture to hold the data */ + gles2_ctx->vtable->glTexImage2D (target, + level, + internal_format, + width, height, + border, + internal_format, /* format */ + GL_UNSIGNED_BYTE, /* type */ + NULL /* data */); + + copy_flipped_texture (gles2_ctx, + level, + x, y, /* src_x/src_y */ + 0, 0, /* dst_x/dst_y */ + width, height); + } + else + { + int restore_mode = transient_bind_read_buffer (gles2_ctx); + + gles2_ctx->context->glCopyTexImage2D (target, level, internal_format, + x, y, width, height, border); + + restore_write_buffer (gles2_ctx, restore_mode); + + set_texture_object_data (gles2_ctx, + target, + level, + internal_format, + width, height); + } +} + +static void +gl_copy_tex_sub_image_2d_wrapper (GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + + /* If we are reading from a CoglOffscreen buffer then the image will + * be upside down with respect to what GL expects so we can't use + * glCopyTexSubImage2D. Instead we we'll try to use the Cogl API to + * flip it */ + if (gles2_ctx->current_fbo_handle == 0 && + cogl_is_offscreen (gles2_ctx->read_buffer)) + { + /* This will only work with the GL_TEXTURE_2D target. FIXME: + * GLES2 also supports setting cube map textures with + * glTexImage2D so we need to handle that too */ + if (target != GL_TEXTURE_2D) + return; + + copy_flipped_texture (gles2_ctx, + level, + x, y, /* src_x/src_y */ + xoffset, yoffset, /* dst_x/dst_y */ + width, height); + } + else + { + int restore_mode = transient_bind_read_buffer (gles2_ctx); + + gles2_ctx->context->glCopyTexSubImage2D (target, level, + xoffset, yoffset, + x, y, width, height); + + restore_write_buffer (gles2_ctx, restore_mode); + } +} + +static GLuint +gl_create_shader_wrapper (GLenum type) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + GLuint id; + + id = gles2_ctx->context->glCreateShader (type); + + if (id != 0) + { + CoglGLES2ShaderData *data = g_slice_new (CoglGLES2ShaderData); + + data->object_id = id; + data->type = type; + data->ref_count = 1; + data->deleted = FALSE; + + g_hash_table_insert (gles2_ctx->shader_map, + GINT_TO_POINTER (id), + data); + } + + return id; +} + +static void +gl_delete_shader_wrapper (GLuint shader) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + CoglGLES2ShaderData *shader_data; + + if ((shader_data = g_hash_table_lookup (gles2_ctx->shader_map, + GINT_TO_POINTER (shader))) && + !shader_data->deleted) + { + shader_data->deleted = TRUE; + shader_data_unref (gles2_ctx, shader_data); + } + + gles2_ctx->context->glDeleteShader (shader); +} + +static GLuint +gl_create_program_wrapper (void) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + GLuint id; + + id = gles2_ctx->context->glCreateProgram (); + + if (id != 0) + { + CoglGLES2ProgramData *data = g_slice_new (CoglGLES2ProgramData); + + data->object_id = id; + data->attached_shaders = NULL; + data->ref_count = 1; + data->deleted = FALSE; + data->context = gles2_ctx; + data->flip_vector_location = 0; + data->flip_vector_state = COGL_GLES2_FLIP_STATE_UNKNOWN; + + g_hash_table_insert (gles2_ctx->program_map, + GINT_TO_POINTER (id), + data); + } + + return id; +} + +static void +gl_delete_program_wrapper (GLuint program) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + CoglGLES2ProgramData *program_data; + + if ((program_data = g_hash_table_lookup (gles2_ctx->program_map, + GINT_TO_POINTER (program))) && + !program_data->deleted) + { + program_data->deleted = TRUE; + program_data_unref (program_data); + } + + gles2_ctx->context->glDeleteProgram (program); +} + +static void +gl_use_program_wrapper (GLuint program) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + CoglGLES2ProgramData *program_data; + + program_data = g_hash_table_lookup (gles2_ctx->program_map, + GINT_TO_POINTER (program)); + + if (program_data) + program_data->ref_count++; + if (gles2_ctx->current_program) + program_data_unref (gles2_ctx->current_program); + + gles2_ctx->current_program = program_data; + + gles2_ctx->context->glUseProgram (program); +} + +static void +gl_attach_shader_wrapper (GLuint program, + GLuint shader) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + CoglGLES2ProgramData *program_data; + CoglGLES2ShaderData *shader_data; + + if ((program_data = g_hash_table_lookup (gles2_ctx->program_map, + GINT_TO_POINTER (program))) && + (shader_data = g_hash_table_lookup (gles2_ctx->shader_map, + GINT_TO_POINTER (shader))) && + /* Ignore attempts to attach a shader that is already attached */ + g_list_find (program_data->attached_shaders, shader_data) == NULL) + { + shader_data->ref_count++; + program_data->attached_shaders = + g_list_prepend (program_data->attached_shaders, shader_data); + } + + gles2_ctx->context->glAttachShader (program, shader); +} + +static void +gl_detach_shader_wrapper (GLuint program, + GLuint shader) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + CoglGLES2ProgramData *program_data; + CoglGLES2ShaderData *shader_data; + + if ((program_data = g_hash_table_lookup (gles2_ctx->program_map, + GINT_TO_POINTER (program))) && + (shader_data = g_hash_table_lookup (gles2_ctx->shader_map, + GINT_TO_POINTER (shader)))) + detach_shader (program_data, shader_data); + + gles2_ctx->context->glDetachShader (program, shader); +} + +static void +gl_shader_source_wrapper (GLuint shader, + GLsizei count, + const char *const *string, + const GLint *length) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + CoglGLES2ShaderData *shader_data; + + if ((shader_data = g_hash_table_lookup (gles2_ctx->shader_map, + GINT_TO_POINTER (shader))) && + shader_data->type == GL_VERTEX_SHADER) + { + char **string_copy = g_alloca ((count + 1) * sizeof (char *)); + int *length_copy = g_alloca ((count + 1) * sizeof (int)); + int i; + + /* Replace any occurences of the symbol 'main' with a different + * symbol so that we can provide our own wrapper main + * function */ + + for (i = 0; i < count; i++) + { + int string_length; + + if (length == NULL || length[i] < 0) + string_length = strlen (string[i]); + else + string_length = length[i]; + + string_copy[i] = g_memdup (string[i], string_length); + + replace_token (string_copy[i], + "main", + MAIN_WRAPPER_REPLACEMENT_NAME, + string_length); + + length_copy[i] = string_length; + } + + string_copy[count] = (char *) main_wrapper_function; + length_copy[count] = sizeof (main_wrapper_function) - 1; + + gles2_ctx->context->glShaderSource (shader, + count + 1, + (const char *const *) string_copy, + length_copy); + + /* Note: we don't need to free the last entry in string_copy[] + * because it is our static wrapper string... */ + for (i = 0; i < count; i++) + g_free (string_copy[i]); + } + else + gles2_ctx->context->glShaderSource (shader, count, string, length); +} + +static void +gl_get_shader_source_wrapper (GLuint shader, + GLsizei buf_size, + GLsizei *length_out, + GLchar *source) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + CoglGLES2ShaderData *shader_data; + GLsizei length; + + gles2_ctx->context->glGetShaderSource (shader, + buf_size, + &length, + source); + + if ((shader_data = g_hash_table_lookup (gles2_ctx->shader_map, + GINT_TO_POINTER (shader))) && + shader_data->type == GL_VERTEX_SHADER) + { + GLsizei copy_length = MIN (length, buf_size - 1); + static const char wrapper_marker[] = MAIN_WRAPPER_BEGIN; + char *wrapper_start; + + /* Strip out the wrapper snippet we added when the source was + * specified */ + wrapper_start = _cogl_util_memmem (source, + copy_length, + wrapper_marker, + sizeof (wrapper_marker) - 1); + if (wrapper_start) + { + length = wrapper_start - source; + copy_length = length; + *wrapper_start = '\0'; + } + + /* Correct the name of the main function back to its original */ + replace_token (source, + MAIN_WRAPPER_REPLACEMENT_NAME, + "main", + copy_length); + } + + if (length_out) + *length_out = length; +} + +static void +gl_link_program_wrapper (GLuint program) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + CoglGLES2ProgramData *program_data; + + gles2_ctx->context->glLinkProgram (program); + + program_data = g_hash_table_lookup (gles2_ctx->program_map, + GINT_TO_POINTER (program)); + + if (program_data) + { + GLint status; + + gles2_ctx->context->glGetProgramiv (program, GL_LINK_STATUS, &status); + + if (status) + program_data->flip_vector_location = + gles2_ctx->context->glGetUniformLocation (program, + MAIN_WRAPPER_FLIP_UNIFORM); + } +} + +static void +gl_get_program_iv_wrapper (GLuint program, + GLenum pname, + GLint *params) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + + gles2_ctx->context->glGetProgramiv (program, pname, params); + + switch (pname) + { + case GL_ATTACHED_SHADERS: + /* Decrease the number of shaders to try and hide the shader + * wrapper we added */ + if (*params > 1) + (*params)--; + break; + } +} + +static void +flush_viewport_state (CoglGLES2Context *gles2_ctx) +{ + if (gles2_ctx->viewport_dirty) + { + int y; + + if (gles2_ctx->current_flip_state == COGL_GLES2_FLIP_STATE_FLIPPED) + { + /* We need to know the height of the current framebuffer in + * order to flip the viewport. Fortunately we don't need to + * track the height of the FBOs created within the GLES2 + * context because we would never be flipping if they are + * bound so we can just assume Cogl's framebuffer is bound + * when we are flipping */ + int fb_height = cogl_framebuffer_get_height (gles2_ctx->write_buffer); + y = fb_height - (gles2_ctx->viewport[1] + gles2_ctx->viewport[3]); + } + else + y = gles2_ctx->viewport[1]; + + gles2_ctx->context->glViewport (gles2_ctx->viewport[0], + y, + gles2_ctx->viewport[2], + gles2_ctx->viewport[3]); + + gles2_ctx->viewport_dirty = FALSE; + } +} + +static void +flush_scissor_state (CoglGLES2Context *gles2_ctx) +{ + if (gles2_ctx->scissor_dirty) + { + int y; + + if (gles2_ctx->current_flip_state == COGL_GLES2_FLIP_STATE_FLIPPED) + { + /* See comment above about the viewport flipping */ + int fb_height = cogl_framebuffer_get_height (gles2_ctx->write_buffer); + y = fb_height - (gles2_ctx->scissor[1] + gles2_ctx->scissor[3]); + } + else + y = gles2_ctx->scissor[1]; + + gles2_ctx->context->glScissor (gles2_ctx->scissor[0], + y, + gles2_ctx->scissor[2], + gles2_ctx->scissor[3]); + + gles2_ctx->scissor_dirty = FALSE; + } +} + +static void +flush_front_face_state (CoglGLES2Context *gles2_ctx) +{ + if (gles2_ctx->front_face_dirty) + { + GLenum front_face; + + if (gles2_ctx->current_flip_state == COGL_GLES2_FLIP_STATE_FLIPPED) + { + if (gles2_ctx->front_face == GL_CW) + front_face = GL_CCW; + else + front_face = GL_CW; + } + else + front_face = gles2_ctx->front_face; + + gles2_ctx->context->glFrontFace (front_face); + + gles2_ctx->front_face_dirty = FALSE; + } +} + +static void +pre_draw_wrapper (CoglGLES2Context *gles2_ctx) +{ + /* If there's no current program then we'll just let GL report an + * error */ + if (gles2_ctx->current_program == NULL) + return; + + flush_viewport_state (gles2_ctx); + flush_scissor_state (gles2_ctx); + flush_front_face_state (gles2_ctx); + + /* We want to flip rendering when the application is rendering to a + * Cogl offscreen buffer in order to maintain the flipped texture + * coordinate origin */ + if (gles2_ctx->current_flip_state != + gles2_ctx->current_program->flip_vector_state) + { + GLuint location = + gles2_ctx->current_program->flip_vector_location; + float value[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + + if (gles2_ctx->current_flip_state == COGL_GLES2_FLIP_STATE_FLIPPED) + value[1] = -1.0f; + + gles2_ctx->context->glUniform4fv (location, 1, value); + + gles2_ctx->current_program->flip_vector_state = + gles2_ctx->current_flip_state; + } +} + +static void +gl_clear_wrapper (GLbitfield mask) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + + /* Clearing is affected by the scissor state so we need to ensure + * that's flushed */ + flush_scissor_state (gles2_ctx); + + gles2_ctx->context->glClear (mask); +} + +static void +gl_draw_elements_wrapper (GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + + pre_draw_wrapper (gles2_ctx); + + gles2_ctx->context->glDrawElements (mode, count, type, indices); +} + +static void +gl_draw_arrays_wrapper (GLenum mode, + GLint first, + GLsizei count) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + + pre_draw_wrapper (gles2_ctx); + + gles2_ctx->context->glDrawArrays (mode, first, count); +} + +static void +gl_get_program_info_log_wrapper (GLuint program, + GLsizei buf_size, + GLsizei *length_out, + GLchar *info_log) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + GLsizei length; + + gles2_ctx->context->glGetProgramInfoLog (program, + buf_size, + &length, + info_log); + + replace_token (info_log, + MAIN_WRAPPER_REPLACEMENT_NAME, + "main", + MIN (length, buf_size)); + + if (length_out) + *length_out = length; +} + +static void +gl_get_shader_info_log_wrapper (GLuint shader, + GLsizei buf_size, + GLsizei *length_out, + GLchar *info_log) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + GLsizei length; + + gles2_ctx->context->glGetShaderInfoLog (shader, + buf_size, + &length, + info_log); + + replace_token (info_log, + MAIN_WRAPPER_REPLACEMENT_NAME, + "main", + MIN (length, buf_size)); + + if (length_out) + *length_out = length; +} + +static void +gl_front_face_wrapper (GLenum mode) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + + /* If the mode doesn't make any sense then we'll just let the + * context deal with it directly so that it will throw an error */ + if (mode != GL_CW && mode != GL_CCW) + gles2_ctx->context->glFrontFace (mode); + else + { + gles2_ctx->front_face = mode; + gles2_ctx->front_face_dirty = TRUE; + } +} + +static void +gl_viewport_wrapper (GLint x, + GLint y, + GLsizei width, + GLsizei height) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + + /* If the viewport is invalid then we'll just let the context deal + * with it directly so that it will throw an error */ + if (width < 0 || height < 0) + gles2_ctx->context->glViewport (x, y, width, height); + else + { + gles2_ctx->viewport[0] = x; + gles2_ctx->viewport[1] = y; + gles2_ctx->viewport[2] = width; + gles2_ctx->viewport[3] = height; + gles2_ctx->viewport_dirty = TRUE; + } +} + +static void +gl_scissor_wrapper (GLint x, + GLint y, + GLsizei width, + GLsizei height) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + + /* If the scissor is invalid then we'll just let the context deal + * with it directly so that it will throw an error */ + if (width < 0 || height < 0) + gles2_ctx->context->glScissor (x, y, width, height); + else + { + gles2_ctx->scissor[0] = x; + gles2_ctx->scissor[1] = y; + gles2_ctx->scissor[2] = width; + gles2_ctx->scissor[3] = height; + gles2_ctx->scissor_dirty = TRUE; + } +} + +static void +gl_get_boolean_v_wrapper (GLenum pname, + GLboolean *params) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + + switch (pname) + { + case GL_VIEWPORT: + { + int i; + + for (i = 0; i < 4; i++) + params[i] = !!gles2_ctx->viewport[i]; + } + break; + + case GL_SCISSOR_BOX: + { + int i; + + for (i = 0; i < 4; i++) + params[i] = !!gles2_ctx->scissor[i]; + } + break; + + default: + gles2_ctx->context->glGetBooleanv (pname, params); + } +} + +static void +gl_get_integer_v_wrapper (GLenum pname, + GLint *params) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + + switch (pname) + { + case GL_VIEWPORT: + { + int i; + + for (i = 0; i < 4; i++) + params[i] = gles2_ctx->viewport[i]; + } + break; + + case GL_SCISSOR_BOX: + { + int i; + + for (i = 0; i < 4; i++) + params[i] = gles2_ctx->scissor[i]; + } + break; + + case GL_FRONT_FACE: + params[0] = gles2_ctx->front_face; + break; + + default: + gles2_ctx->context->glGetIntegerv (pname, params); + } +} + +static void +gl_get_float_v_wrapper (GLenum pname, + GLfloat *params) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + + switch (pname) + { + case GL_VIEWPORT: + { + int i; + + for (i = 0; i < 4; i++) + params[i] = gles2_ctx->viewport[i]; + } + break; + + case GL_SCISSOR_BOX: + { + int i; + + for (i = 0; i < 4; i++) + params[i] = gles2_ctx->scissor[i]; + } + break; + + case GL_FRONT_FACE: + params[0] = gles2_ctx->front_face; + break; + + default: + gles2_ctx->context->glGetFloatv (pname, params); + } +} + +static void +gl_pixel_store_i_wrapper (GLenum pname, GLint param) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + + gles2_ctx->context->glPixelStorei (pname, param); + + if (pname == GL_PACK_ALIGNMENT && + (param == 1 || param == 2 || param == 4 || param == 8)) + gles2_ctx->pack_alignment = param; +} + +static void +gl_active_texture_wrapper (GLenum texture) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + int texture_unit; + + gles2_ctx->context->glActiveTexture (texture); + + texture_unit = texture - GL_TEXTURE0; + + /* If the application is binding some odd looking texture unit + * numbers then we'll just ignore it and hope that GL has generated + * an error */ + if (texture_unit >= 0 && texture_unit < 512) + { + gles2_ctx->current_texture_unit = texture_unit; + g_array_set_size (gles2_ctx->texture_units, + MAX (texture_unit, gles2_ctx->texture_units->len)); + } +} + +static void +gl_delete_textures_wrapper (GLsizei n, + const GLuint *textures) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + int texture_index; + int texture_unit; + + gles2_ctx->context->glDeleteTextures (n, textures); + + for (texture_index = 0; texture_index < n; texture_index++) + { + /* Reset any texture units that have any of these textures bound */ + for (texture_unit = 0; + texture_unit < gles2_ctx->texture_units->len; + texture_unit++) + { + CoglGLES2TextureUnitData *unit = + &g_array_index (gles2_ctx->texture_units, + CoglGLES2TextureUnitData, + texture_unit); + + if (unit->current_texture_2d == textures[texture_index]) + unit->current_texture_2d = 0; + } + + /* Remove the binding. We can do this immediately because unlike + * shader objects the deletion isn't delayed until the object is + * unbound */ + g_hash_table_remove (gles2_ctx->texture_object_map, + GUINT_TO_POINTER (textures[texture_index])); + } +} + +static void +gl_bind_texture_wrapper (GLenum target, + GLuint texture) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + + gles2_ctx->context->glBindTexture (target, texture); + + if (target == GL_TEXTURE_2D) + { + CoglGLES2TextureUnitData *unit = + &g_array_index (gles2_ctx->texture_units, + CoglGLES2TextureUnitData, + gles2_ctx->current_texture_unit); + unit->current_texture_2d = texture; + } +} + +static void +gl_tex_image_2d_wrapper (GLenum target, + GLint level, + GLint internal_format, + GLsizei width, + GLsizei height, + GLint border, + GLenum format, + GLenum type, + const GLvoid *pixels) +{ + CoglGLES2Context *gles2_ctx = current_gles2_context; + + gles2_ctx->context->glTexImage2D (target, + level, + internal_format, + width, height, + border, + format, + type, + pixels); + + set_texture_object_data (gles2_ctx, + target, + level, + internal_format, + width, height); +} + +static void +_cogl_gles2_offscreen_free (CoglGLES2Offscreen *gles2_offscreen) +{ + _cogl_list_remove (&gles2_offscreen->link); + g_slice_free (CoglGLES2Offscreen, gles2_offscreen); +} + +static void +force_delete_program_object (CoglGLES2Context *context, + CoglGLES2ProgramData *program_data) +{ + if (!program_data->deleted) + { + context->context->glDeleteProgram (program_data->object_id); + program_data->deleted = TRUE; + program_data_unref (program_data); + } +} + +static void +force_delete_shader_object (CoglGLES2Context *context, + CoglGLES2ShaderData *shader_data) +{ + if (!shader_data->deleted) + { + context->context->glDeleteShader (shader_data->object_id); + shader_data->deleted = TRUE; + shader_data_unref (context, shader_data); + } +} + +static void +force_delete_texture_object (CoglGLES2Context *context, + CoglGLES2TextureObjectData *texture_data) +{ + context->context->glDeleteTextures (1, &texture_data->object_id); +} + +static void +_cogl_gles2_context_free (CoglGLES2Context *gles2_context) +{ + CoglContext *ctx = gles2_context->context; + const CoglWinsysVtable *winsys; + GList *objects, *l; + + if (gles2_context->current_program) + program_data_unref (gles2_context->current_program); + + /* Try to forcibly delete any shaders, programs and textures so that + * they won't get leaked. Because all GLES2 contexts are in the same + * share list as Cogl's context these won't get deleted by default. + * FIXME: we should do this for all of the other resources too, like + * textures */ + objects = g_hash_table_get_values (gles2_context->program_map); + for (l = objects; l; l = l->next) + force_delete_program_object (gles2_context, l->data); + g_list_free (objects); + objects = g_hash_table_get_values (gles2_context->shader_map); + for (l = objects; l; l = l->next) + force_delete_shader_object (gles2_context, l->data); + g_list_free (objects); + objects = g_hash_table_get_values (gles2_context->texture_object_map); + for (l = objects; l; l = l->next) + force_delete_texture_object (gles2_context, l->data); + g_list_free (objects); + + /* All of the program and shader objects should now be destroyed */ + if (g_hash_table_size (gles2_context->program_map) > 0) + g_warning ("Program objects have been leaked from a CoglGLES2Context"); + if (g_hash_table_size (gles2_context->shader_map) > 0) + g_warning ("Shader objects have been leaked from a CoglGLES2Context"); + + g_hash_table_destroy (gles2_context->program_map); + g_hash_table_destroy (gles2_context->shader_map); + + g_hash_table_destroy (gles2_context->texture_object_map); + g_array_free (gles2_context->texture_units, TRUE); + + winsys = ctx->display->renderer->winsys_vtable; + winsys->destroy_gles2_context (gles2_context); + + while (!_cogl_list_empty (&gles2_context->foreign_offscreens)) + { + CoglGLES2Offscreen *gles2_offscreen = + _cogl_container_of (gles2_context->foreign_offscreens.next, + CoglGLES2Offscreen, + link); + + /* Note: this will also indirectly free the gles2_offscreen by + * calling the destroy notify for the _user_data */ + cogl_object_set_user_data (COGL_OBJECT (gles2_offscreen->original_offscreen), + &offscreen_wrapper_key, + NULL, + NULL); + } + + g_free (gles2_context->vtable); + + g_free (gles2_context); +} + +static void +free_shader_data (CoglGLES2ShaderData *data) +{ + g_slice_free (CoglGLES2ShaderData, data); +} + +static void +free_program_data (CoglGLES2ProgramData *data) +{ + while (data->attached_shaders) + detach_shader (data, + data->attached_shaders->data); + + g_slice_free (CoglGLES2ProgramData, data); +} + +static void +free_texture_object_data (CoglGLES2TextureObjectData *data) +{ + g_slice_free (CoglGLES2TextureObjectData, data); +} + +CoglGLES2Context * +cogl_gles2_context_new (CoglContext *ctx, CoglError **error) +{ + CoglGLES2Context *gles2_ctx; + const CoglWinsysVtable *winsys; + + if (!cogl_has_feature (ctx, COGL_FEATURE_ID_GLES2_CONTEXT)) + { + _cogl_set_error (error, COGL_GLES2_CONTEXT_ERROR, + COGL_GLES2_CONTEXT_ERROR_UNSUPPORTED, + "Backend doesn't support creating GLES2 contexts"); + + return NULL; + } + + gles2_ctx = g_malloc0 (sizeof (CoglGLES2Context)); + + gles2_ctx->context = ctx; + + _cogl_list_init (&gles2_ctx->foreign_offscreens); + + winsys = ctx->display->renderer->winsys_vtable; + gles2_ctx->winsys = winsys->context_create_gles2_context (ctx, error); + if (gles2_ctx->winsys == NULL) + { + g_free (gles2_ctx); + return NULL; + } + + gles2_ctx->current_flip_state = COGL_GLES2_FLIP_STATE_UNKNOWN; + gles2_ctx->viewport_dirty = TRUE; + gles2_ctx->scissor_dirty = TRUE; + gles2_ctx->front_face_dirty = TRUE; + gles2_ctx->front_face = GL_CCW; + gles2_ctx->pack_alignment = 4; + + gles2_ctx->vtable = g_malloc0 (sizeof (CoglGLES2Vtable)); +#define COGL_EXT_BEGIN(name, \ + min_gl_major, min_gl_minor, \ + gles_availability, \ + extension_suffixes, extension_names) + +#define COGL_EXT_FUNCTION(ret, name, args) \ + gles2_ctx->vtable->name = (void *) ctx->name; + +#define COGL_EXT_END() + +#include "gl-prototypes/cogl-gles2-functions.h" + +#undef COGL_EXT_BEGIN +#undef COGL_EXT_FUNCTION +#undef COGL_EXT_END + + gles2_ctx->vtable->glBindFramebuffer = + (void *) gl_bind_framebuffer_wrapper; + gles2_ctx->vtable->glReadPixels = + (void *) gl_read_pixels_wrapper; + gles2_ctx->vtable->glCopyTexImage2D = + (void *) gl_copy_tex_image_2d_wrapper; + gles2_ctx->vtable->glCopyTexSubImage2D = + (void *) gl_copy_tex_sub_image_2d_wrapper; + + gles2_ctx->vtable->glCreateShader = gl_create_shader_wrapper; + gles2_ctx->vtable->glDeleteShader = gl_delete_shader_wrapper; + gles2_ctx->vtable->glCreateProgram = gl_create_program_wrapper; + gles2_ctx->vtable->glDeleteProgram = gl_delete_program_wrapper; + gles2_ctx->vtable->glUseProgram = gl_use_program_wrapper; + gles2_ctx->vtable->glAttachShader = gl_attach_shader_wrapper; + gles2_ctx->vtable->glDetachShader = gl_detach_shader_wrapper; + gles2_ctx->vtable->glShaderSource = gl_shader_source_wrapper; + gles2_ctx->vtable->glGetShaderSource = gl_get_shader_source_wrapper; + gles2_ctx->vtable->glLinkProgram = gl_link_program_wrapper; + gles2_ctx->vtable->glGetProgramiv = gl_get_program_iv_wrapper; + gles2_ctx->vtable->glGetProgramInfoLog = gl_get_program_info_log_wrapper; + gles2_ctx->vtable->glGetShaderInfoLog = gl_get_shader_info_log_wrapper; + gles2_ctx->vtable->glClear = gl_clear_wrapper; + gles2_ctx->vtable->glDrawElements = gl_draw_elements_wrapper; + gles2_ctx->vtable->glDrawArrays = gl_draw_arrays_wrapper; + gles2_ctx->vtable->glFrontFace = gl_front_face_wrapper; + gles2_ctx->vtable->glViewport = gl_viewport_wrapper; + gles2_ctx->vtable->glScissor = gl_scissor_wrapper; + gles2_ctx->vtable->glGetBooleanv = gl_get_boolean_v_wrapper; + gles2_ctx->vtable->glGetIntegerv = gl_get_integer_v_wrapper; + gles2_ctx->vtable->glGetFloatv = gl_get_float_v_wrapper; + gles2_ctx->vtable->glPixelStorei = gl_pixel_store_i_wrapper; + gles2_ctx->vtable->glActiveTexture = gl_active_texture_wrapper; + gles2_ctx->vtable->glDeleteTextures = gl_delete_textures_wrapper; + gles2_ctx->vtable->glBindTexture = gl_bind_texture_wrapper; + gles2_ctx->vtable->glTexImage2D = gl_tex_image_2d_wrapper; + + gles2_ctx->shader_map = + g_hash_table_new_full (g_direct_hash, + g_direct_equal, + NULL, /* key_destroy */ + (GDestroyNotify) free_shader_data); + gles2_ctx->program_map = + g_hash_table_new_full (g_direct_hash, + g_direct_equal, + NULL, /* key_destroy */ + (GDestroyNotify) free_program_data); + + gles2_ctx->texture_object_map = + g_hash_table_new_full (g_direct_hash, + g_direct_equal, + NULL, /* key_destroy */ + (GDestroyNotify) free_texture_object_data); + + gles2_ctx->texture_units = g_array_new (FALSE, /* not zero terminated */ + TRUE, /* clear */ + sizeof (CoglGLES2TextureUnitData)); + gles2_ctx->current_texture_unit = 0; + g_array_set_size (gles2_ctx->texture_units, 1); + + return _cogl_gles2_context_object_new (gles2_ctx); +} + +const CoglGLES2Vtable * +cogl_gles2_context_get_vtable (CoglGLES2Context *gles2_ctx) +{ + return gles2_ctx->vtable; +} + +/* When drawing to a CoglFramebuffer from a separate context we have + * to be able to allocate ancillary buffers for that context... + */ +static CoglGLES2Offscreen * +_cogl_gles2_offscreen_allocate (CoglOffscreen *offscreen, + CoglGLES2Context *gles2_context, + CoglError **error) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (offscreen); + const CoglWinsysVtable *winsys; + CoglError *internal_error = NULL; + CoglGLES2Offscreen *gles2_offscreen; + int level_width; + int level_height; + + if (!framebuffer->allocated && + !cogl_framebuffer_allocate (framebuffer, error)) + { + return NULL; + } + + _cogl_list_for_each (gles2_offscreen, + &gles2_context->foreign_offscreens, + link) + { + if (gles2_offscreen->original_offscreen == offscreen) + return gles2_offscreen; + } + + winsys = _cogl_framebuffer_get_winsys (framebuffer); + winsys->save_context (framebuffer->context); + if (!winsys->set_gles2_context (gles2_context, &internal_error)) + { + winsys->restore_context (framebuffer->context); + + cogl_error_free (internal_error); + _cogl_set_error (error, COGL_FRAMEBUFFER_ERROR, + COGL_FRAMEBUFFER_ERROR_ALLOCATE, + "Failed to bind gles2 context to create framebuffer"); + return NULL; + } + + gles2_offscreen = g_slice_new0 (CoglGLES2Offscreen); + + _cogl_texture_get_level_size (offscreen->texture, + offscreen->texture_level, + &level_width, + &level_height, + NULL); + + if (!_cogl_framebuffer_try_creating_gl_fbo (gles2_context->context, + offscreen->texture, + offscreen->texture_level, + level_width, + level_height, + offscreen->depth_texture, + &COGL_FRAMEBUFFER (offscreen)->config, + offscreen->allocation_flags, + &gles2_offscreen->gl_framebuffer)) + { + winsys->restore_context (framebuffer->context); + + g_slice_free (CoglGLES2Offscreen, gles2_offscreen); + + _cogl_set_error (error, COGL_FRAMEBUFFER_ERROR, + COGL_FRAMEBUFFER_ERROR_ALLOCATE, + "Failed to create an OpenGL framebuffer object"); + return NULL; + } + + winsys->restore_context (framebuffer->context); + + gles2_offscreen->original_offscreen = offscreen; + + _cogl_list_insert (&gles2_context->foreign_offscreens, + &gles2_offscreen->link); + + /* So we avoid building up an ever growing collection of ancillary + * buffers for wrapped framebuffers, we make sure that the wrappers + * get freed when the original offscreen framebuffer is freed. */ + cogl_object_set_user_data (COGL_OBJECT (framebuffer), + &offscreen_wrapper_key, + gles2_offscreen, + (CoglUserDataDestroyCallback) + _cogl_gles2_offscreen_free); + + return gles2_offscreen; +} + +CoglBool +cogl_push_gles2_context (CoglContext *ctx, + CoglGLES2Context *gles2_ctx, + CoglFramebuffer *read_buffer, + CoglFramebuffer *write_buffer, + CoglError **error) +{ + const CoglWinsysVtable *winsys = ctx->display->renderer->winsys_vtable; + CoglError *internal_error = NULL; + + _COGL_RETURN_VAL_IF_FAIL (gles2_ctx != NULL, FALSE); + + /* The read/write buffers are properties of the gles2 context and we + * don't currently track the read/write buffers as part of the stack + * entries so we explicitly don't allow the same context to be + * pushed multiple times. */ + if (g_queue_find (&ctx->gles2_context_stack, gles2_ctx)) + { + g_critical ("Pushing the same GLES2 context multiple times isn't " + "supported"); + return FALSE; + } + + if (ctx->gles2_context_stack.length == 0) + { + _cogl_journal_flush (read_buffer->journal); + if (write_buffer != read_buffer) + _cogl_journal_flush (write_buffer->journal); + winsys->save_context (ctx); + } + else + gles2_ctx->vtable->glFlush (); + + if (gles2_ctx->read_buffer != read_buffer) + { + if (cogl_is_offscreen (read_buffer)) + { + gles2_ctx->gles2_read_buffer = + _cogl_gles2_offscreen_allocate (COGL_OFFSCREEN (read_buffer), + gles2_ctx, + error); + /* XXX: what consistency guarantees should this api have? + * + * It should be safe to return at this point but we provide + * no guarantee to the caller whether their given buffers + * may be referenced and old buffers unreferenced even + * if the _push fails. */ + if (!gles2_ctx->gles2_read_buffer) + return FALSE; + } + else + gles2_ctx->gles2_read_buffer = NULL; + if (gles2_ctx->read_buffer) + cogl_object_unref (gles2_ctx->read_buffer); + gles2_ctx->read_buffer = cogl_object_ref (read_buffer); + } + + if (gles2_ctx->write_buffer != write_buffer) + { + if (cogl_is_offscreen (write_buffer)) + { + gles2_ctx->gles2_write_buffer = + _cogl_gles2_offscreen_allocate (COGL_OFFSCREEN (write_buffer), + gles2_ctx, + error); + /* XXX: what consistency guarantees should this api have? + * + * It should be safe to return at this point but we provide + * no guarantee to the caller whether their given buffers + * may be referenced and old buffers unreferenced even + * if the _push fails. */ + if (!gles2_ctx->gles2_write_buffer) + return FALSE; + } + else + gles2_ctx->gles2_write_buffer = NULL; + if (gles2_ctx->write_buffer) + cogl_object_unref (gles2_ctx->write_buffer); + gles2_ctx->write_buffer = cogl_object_ref (write_buffer); + + update_current_flip_state (gles2_ctx); + } + + if (!winsys->set_gles2_context (gles2_ctx, &internal_error)) + { + winsys->restore_context (ctx); + + cogl_error_free (internal_error); + _cogl_set_error (error, COGL_GLES2_CONTEXT_ERROR, + COGL_GLES2_CONTEXT_ERROR_DRIVER, + "Driver failed to make GLES2 context current"); + return FALSE; + } + + g_queue_push_tail (&ctx->gles2_context_stack, gles2_ctx); + + /* The last time this context was pushed may have been with a + * different offscreen draw framebuffer and so if GL framebuffer 0 + * is bound for this GLES2 context we may need to bind a new, + * corresponding, window system framebuffer... */ + if (gles2_ctx->current_fbo_handle == 0) + { + if (cogl_is_offscreen (gles2_ctx->write_buffer)) + { + CoglGLES2Offscreen *write = gles2_ctx->gles2_write_buffer; + GLuint handle = write->gl_framebuffer.fbo_handle; + gles2_ctx->context->glBindFramebuffer (GL_FRAMEBUFFER, handle); + } + } + + current_gles2_context = gles2_ctx; + + /* If this is the first time this gles2 context has been used then + * we'll force the viewport and scissor to the right size. GL has + * the semantics that the viewport and scissor default to the size + * of the first surface the context is used with. If the first + * CoglFramebuffer that this context is used with is an offscreen, + * then the surface from GL's point of view will be the 1x1 dummy + * surface so the viewport will be wrong. Therefore we just override + * the default viewport and scissor here */ + if (!gles2_ctx->has_been_bound) + { + int fb_width = cogl_framebuffer_get_width (write_buffer); + int fb_height = cogl_framebuffer_get_height (write_buffer); + + gles2_ctx->vtable->glViewport (0, 0, /* x/y */ + fb_width, fb_height); + gles2_ctx->vtable->glScissor (0, 0, /* x/y */ + fb_width, fb_height); + gles2_ctx->has_been_bound = TRUE; + } + + return TRUE; +} + +CoglGLES2Vtable * +cogl_gles2_get_current_vtable (void) +{ + return current_gles2_context ? current_gles2_context->vtable : NULL; +} + +void +cogl_pop_gles2_context (CoglContext *ctx) +{ + CoglGLES2Context *gles2_ctx; + const CoglWinsysVtable *winsys = ctx->display->renderer->winsys_vtable; + + _COGL_RETURN_IF_FAIL (ctx->gles2_context_stack.length > 0); + + g_queue_pop_tail (&ctx->gles2_context_stack); + + gles2_ctx = g_queue_peek_tail (&ctx->gles2_context_stack); + + if (gles2_ctx) + { + winsys->set_gles2_context (gles2_ctx, NULL); + current_gles2_context = gles2_ctx; + } + else + { + winsys->restore_context (ctx); + current_gles2_context = NULL; + } +} + +CoglTexture2D * +cogl_gles2_texture_2d_new_from_handle (CoglContext *ctx, + CoglGLES2Context *gles2_ctx, + unsigned int handle, + int width, + int height, + CoglPixelFormat format) +{ + return cogl_texture_2d_gl_new_from_foreign (ctx, + handle, + width, + height, + format); +} + +CoglBool +cogl_gles2_texture_get_handle (CoglTexture *texture, + unsigned int *handle, + unsigned int *target) +{ + return cogl_texture_get_gl_texture (texture, handle, target); +} diff --git a/cogl/cogl/cogl-gles2-types.h b/cogl/cogl/cogl-gles2-types.h new file mode 100644 index 0000000..8f41bf8 --- /dev/null +++ b/cogl/cogl/cogl-gles2-types.h @@ -0,0 +1,474 @@ +#ifndef __COGL_GLES2_TYPES_H_ +#define __COGL_GLES2_TYPES_H_ + +/* $Revision: 16803 $ on $Date:: 2012-02-02 09:49:18 -0800 #$ */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This document is licensed under the SGI Free Software B License Version + * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ . + */ + +/*------------------------------------------------------------------------- + * Data type definitions + *-----------------------------------------------------------------------*/ + +typedef void GLvoid; +typedef char GLchar; +typedef unsigned int GLenum; +typedef unsigned char GLboolean; +typedef unsigned int GLbitfield; +typedef int8_t GLbyte; +typedef short GLshort; +typedef int GLint; +typedef int GLsizei; +typedef uint8_t GLubyte; +typedef unsigned short GLushort; +typedef unsigned int GLuint; +typedef float GLfloat; +typedef float GLclampf; +typedef int32_t GLfixed; + +/* GL types for handling large vertex buffer objects */ +typedef signed long int GLintptr; +typedef long GLsizeiptr; + +/* OpenGL ES core versions */ +#define GL_ES_VERSION_2_0 1 + +/* ClearBufferMask */ +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_COLOR_BUFFER_BIT 0x00004000 + +/* Boolean */ +#define GL_FALSE 0 +#define GL_TRUE 1 + +/* BeginMode */ +#define GL_POINTS 0x0000 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_STRIP 0x0003 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_FAN 0x0006 + +/* AlphaFunction (not supported in ES20) */ +/* GL_NEVER */ +/* GL_LESS */ +/* GL_EQUAL */ +/* GL_LEQUAL */ +/* GL_GREATER */ +/* GL_NOTEQUAL */ +/* GL_GEQUAL */ +/* GL_ALWAYS */ + +/* BlendingFactorDest */ +#define GL_ZERO 0 +#define GL_ONE 1 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 + +/* BlendingFactorSrc */ +/* GL_ZERO */ +/* GL_ONE */ +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 +/* GL_SRC_ALPHA */ +/* GL_ONE_MINUS_SRC_ALPHA */ +/* GL_DST_ALPHA */ +/* GL_ONE_MINUS_DST_ALPHA */ + +/* BlendEquationSeparate */ +#define GL_FUNC_ADD 0x8006 +#define GL_BLEND_EQUATION 0x8009 +#define GL_BLEND_EQUATION_RGB 0x8009 /* same as BLEND_EQUATION */ +#define GL_BLEND_EQUATION_ALPHA 0x883D + +/* BlendSubtract */ +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B + +/* Separate Blend Functions */ +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_BLEND_COLOR 0x8005 + +/* Buffer Objects */ +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 + +#define GL_STREAM_DRAW 0x88E0 +#define GL_STATIC_DRAW 0x88E4 +#define GL_DYNAMIC_DRAW 0x88E8 + +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 + +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 + +/* CullFaceMode */ +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_FRONT_AND_BACK 0x0408 + +/* DepthFunction */ +/* GL_NEVER */ +/* GL_LESS */ +/* GL_EQUAL */ +/* GL_LEQUAL */ +/* GL_GREATER */ +/* GL_NOTEQUAL */ +/* GL_GEQUAL */ +/* GL_ALWAYS */ + +/* EnableCap */ +#define GL_TEXTURE_2D 0x0DE1 +#define GL_CULL_FACE 0x0B44 +#define GL_BLEND 0x0BE2 +#define GL_DITHER 0x0BD0 +#define GL_STENCIL_TEST 0x0B90 +#define GL_DEPTH_TEST 0x0B71 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_COVERAGE 0x80A0 + +/* ErrorCode */ +#define GL_NO_ERROR 0 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_OUT_OF_MEMORY 0x0505 + +/* FrontFaceDirection */ +#define GL_CW 0x0900 +#define GL_CCW 0x0901 + +/* GetPName */ +#define GL_LINE_WIDTH 0x0B21 +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_FRONT_FACE 0x0B46 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 +#define GL_VIEWPORT 0x0BA2 +#define GL_SCISSOR_BOX 0x0C10 +/* GL_SCISSOR_TEST */ +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_RED_BITS 0x0D52 +#define GL_GREEN_BITS 0x0D53 +#define GL_BLUE_BITS 0x0D54 +#define GL_ALPHA_BITS 0x0D55 +#define GL_DEPTH_BITS 0x0D56 +#define GL_STENCIL_BITS 0x0D57 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +/* GL_POLYGON_OFFSET_FILL */ +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB + +/* GetTextureParameter */ +/* GL_TEXTURE_MAG_FILTER */ +/* GL_TEXTURE_MIN_FILTER */ +/* GL_TEXTURE_WRAP_S */ +/* GL_TEXTURE_WRAP_T */ + +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 + +/* HintMode */ +#define GL_DONT_CARE 0x1100 +#define GL_FASTEST 0x1101 +#define GL_NICEST 0x1102 + +/* HintTarget */ +#define GL_GENERATE_MIPMAP_HINT 0x8192 + +/* DataType */ +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_INT 0x1404 +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_FIXED 0x140C + +/* PixelFormat */ +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_ALPHA 0x1906 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_LUMINANCE 0x1909 +#define GL_LUMINANCE_ALPHA 0x190A + +/* PixelType */ +/* GL_UNSIGNED_BYTE */ +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 + +/* Shaders */ +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB +#define GL_MAX_VARYING_VECTORS 0x8DFC +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD +#define GL_SHADER_TYPE 0x8B4F +#define GL_DELETE_STATUS 0x8B80 +#define GL_LINK_STATUS 0x8B82 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_CURRENT_PROGRAM 0x8B8D + +/* StencilFunction */ +#define GL_NEVER 0x0200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 + +/* StencilOp */ +/* GL_ZERO */ +#define GL_KEEP 0x1E00 +#define GL_REPLACE 0x1E01 +#define GL_INCR 0x1E02 +#define GL_DECR 0x1E03 +#define GL_INVERT 0x150A +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 + +/* StringName */ +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 +#define GL_EXTENSIONS 0x1F03 + +/* TextureMagFilter */ +#define GL_NEAREST 0x2600 +#define GL_LINEAR 0x2601 + +/* TextureMinFilter */ +/* GL_NEAREST */ +/* GL_LINEAR */ +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 + +/* TextureParameterName */ +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 + +/* TextureTarget */ +/* GL_TEXTURE_2D */ +#define GL_TEXTURE 0x1702 + +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C + +/* TextureUnit */ +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 + +/* TextureWrapMode */ +#define GL_REPEAT 0x2901 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_MIRRORED_REPEAT 0x8370 + +/* Uniform Types */ +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_CUBE 0x8B60 + +/* Vertex Arrays */ +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F + +/* Read Format */ +#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B + +/* Shader Source */ +#define GL_COMPILE_STATUS 0x8B81 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_SHADER_COMPILER 0x8DFA + +/* Shader Binary */ +#define GL_SHADER_BINARY_FORMATS 0x8DF8 +#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 + +/* Shader Precision-Specified Types */ +#define GL_LOW_FLOAT 0x8DF0 +#define GL_MEDIUM_FLOAT 0x8DF1 +#define GL_HIGH_FLOAT 0x8DF2 +#define GL_LOW_INT 0x8DF3 +#define GL_MEDIUM_INT 0x8DF4 +#define GL_HIGH_INT 0x8DF5 + +/* Framebuffer Object. */ +#define GL_FRAMEBUFFER 0x8D40 +#define GL_RENDERBUFFER 0x8D41 + +#define GL_RGBA4 0x8056 +#define GL_RGB5_A1 0x8057 +#define GL_RGB565 0x8D62 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_STENCIL_INDEX8 0x8D48 + +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 + +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 + +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_STENCIL_ATTACHMENT 0x8D20 + +#define GL_NONE 0 + +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD + +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 + +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 + + +#ifdef __cplusplus +} +#endif + +#endif /* __COGL_GLES2_TYPES_H_ */ diff --git a/cogl/cogl/cogl-gles2.h b/cogl/cogl/cogl-gles2.h new file mode 100644 index 0000000..87a06f1 --- /dev/null +++ b/cogl/cogl/cogl-gles2.h @@ -0,0 +1,416 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Collabora Ltd. + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Tomeu Vizoso + * Robert Bragg + * + */ + +#ifndef __COGL_GLES2_H__ +#define __COGL_GLES2_H__ + +/* NB: cogl-gles2.h is a top-level header that can be included directly + * but we want to be careful not to define __COGL_H_INSIDE__ when this + * is included internally while building Cogl itself since + * __COGL_H_INSIDE__ is used in headers to guard public vs private + * api definitions + */ +#ifndef COGL_COMPILATION + +/* Note: When building Cogl .gir we explicitly define + * __COGL_H_INSIDE__ */ +#ifndef __COGL_H_INSIDE__ +#define __COGL_H_INSIDE__ +#define __COGL_MUST_UNDEF_COGL_H_INSIDE_COGL_GLES2__ +#endif + +#endif /* COGL_COMPILATION */ + +#include +#include +#include +#include +#include + +/* CoglGLES2Vtable depends on GLES 2.0 typedefs being available but we + * want to be careful that the public api doesn't expose arbitrary + * system GL headers as part of the Cogl API so although when building + * internally we consistently refer to the system headers to avoid + * conflicts we only expose the minimal set of GLES 2.0 types and enums + * publicly. + */ +#if defined(COGL_COMPILATION) || defined(COGL_ENABLE_MUTTER_API) +#include "cogl-gl-header.h" +#else +#include +#endif + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-gles2 + * @short_description: A portable api to access OpenGLES 2.0 + * + * Cogl provides portable access to the OpenGLES api through a single + * library that is able to smooth over inconsistencies between the + * different vendor drivers for OpenGLES in a single place. + * + * The api is designed to allow Cogl to transparently implement the + * api on top of other drivers, such as OpenGL, D3D or on Cogl's own + * drawing api so even if your platform doesn't come with an + * OpenGLES 2.0 api Cogl may still be able to expose the api to your + * application. + * + * Since Cogl is a library and not an api specification it is possible + * to add OpenGLES 2.0 api features to Cogl which can immidiately + * benefit developers regardless of what platform they are running on. + * + * With this api it's possible to re-use existing OpenGLES 2.0 code + * within applications that are rendering with the Cogl API and also + * it's possible for applications that render using OpenGLES 2.0 to + * incorporate content rendered with Cogl. + * + * Applications can check for OpenGLES 2.0 api support by checking for + * %COGL_FEATURE_ID_GLES2_CONTEXT support with cogl_has_feature(). + * + * Since: 1.12 + * Stability: unstable + */ + +/** + * CoglGLES2Context: + * + * Represents an OpenGLES 2.0 api context used as a sandbox for + * OpenGLES 2.0 state. This is comparable to an EGLContext for those + * who have used OpenGLES 2.0 with EGL before. + * + * Since: 1.12 + * Stability: unstable + */ +typedef struct _CoglGLES2Context CoglGLES2Context; + +/** + * CoglGLES2Vtable: + * + * Provides function pointers for the full OpenGLES 2.0 api. The + * api must be accessed this way and not by directly calling + * symbols of any system OpenGLES 2.0 api. + * + * Since: 1.12 + * Stability: unstable + */ +typedef struct _CoglGLES2Vtable CoglGLES2Vtable; + +struct _CoglGLES2Vtable +{ + /*< private >*/ +#define COGL_EXT_BEGIN(name, \ + min_gl_major, min_gl_minor, \ + gles_availability, \ + extension_suffixes, extension_names) + +#define COGL_EXT_FUNCTION(ret, name, args) \ + ret (* name) args; + +#define COGL_EXT_END() + +#include + +#include + +#undef COGL_EXT_BEGIN +#undef COGL_EXT_FUNCTION +#undef COGL_EXT_END +}; + +/** + * cogl_gles2_context_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_gles2_context_get_gtype (void); + +uint32_t +_cogl_gles2_context_error_quark (void); + +/** + * COGL_GLES2_CONTEXT_ERROR: + * + * An error domain for runtime exceptions relating to the + * cogl_gles2_context api. + * + * Since: 2.0 + * Stability: unstable + */ +#define COGL_GLES2_CONTEXT_ERROR (_cogl_gles2_context_error_quark ()) + +/** + * CoglGLES2ContextError: + * @COGL_GLES2_CONTEXT_ERROR_UNSUPPORTED: Creating GLES2 contexts + * isn't supported. Applications should use cogl_has_feature() to + * check for the %COGL_FEATURE_ID_GLES2_CONTEXT. + * @COGL_GLES2_CONTEXT_ERROR_DRIVER: An underlying driver error + * occured. + * + * Error codes that relate to the cogl_gles2_context api. + */ +typedef enum { /*< prefix=COGL_GLES2_CONTEXT_ERROR >*/ + COGL_GLES2_CONTEXT_ERROR_UNSUPPORTED, + COGL_GLES2_CONTEXT_ERROR_DRIVER +} CoglGLES2ContextError; + +/** + * cogl_gles2_context_new: + * @ctx: A #CoglContext + * @error: A pointer to a #CoglError for returning exceptions + * + * Allocates a new OpenGLES 2.0 context that can be used to render to + * #CoglOffscreen framebuffers (Rendering to #CoglOnscreen + * framebuffers is not currently supported). + * + * To actually access the OpenGLES 2.0 api itself you need to use + * cogl_gles2_context_get_vtable(). You should not try to directly link + * to and use the symbols provided by the a system OpenGLES 2.0 + * driver. + * + * Once you have allocated an OpenGLES 2.0 context you can make it + * current using cogl_push_gles2_context(). For those familiar with + * using the EGL api, this serves a similar purpose to eglMakeCurrent. + * + * Before using this api applications can check for OpenGLES 2.0 + * api support by checking for %COGL_FEATURE_ID_GLES2_CONTEXT support + * with cogl_has_feature(). This function will return %FALSE and + * return an %COGL_GLES2_CONTEXT_ERROR_UNSUPPORTED error if the + * feature isn't available. + * + * Since: 2.0 + * Return value: A newly allocated #CoglGLES2Context or %NULL if there + * was an error and @error will be updated in that case. + * Stability: unstable + */ +CoglGLES2Context * +cogl_gles2_context_new (CoglContext *ctx, CoglError **error); + +/** + * cogl_gles2_context_get_vtable: + * @gles2_ctx: A #CoglGLES2Context allocated with + * cogl_gles2_context_new() + * + * Queries the OpenGLES 2.0 api function pointers that should be + * used for rendering with the given @gles2_ctx. + * + * You should not try to directly link to and use the symbols + * provided by any system OpenGLES 2.0 driver. + * + * Since: 2.0 + * Return value: A pointer to a #CoglGLES2Vtable providing pointers + * to functions for the full OpenGLES 2.0 api. + * Stability: unstable + */ +const CoglGLES2Vtable * +cogl_gles2_context_get_vtable (CoglGLES2Context *gles2_ctx); + +/** + * cogl_push_gles2_context: + * @ctx: A #CoglContext + * @gles2_ctx: A #CoglGLES2Context allocated with + * cogl_gles2_context_new() + * @read_buffer: A #CoglFramebuffer to access to read operations + * such as glReadPixels. (must be a #CoglOffscreen + * framebuffer currently) + * @write_buffer: A #CoglFramebuffer to access for drawing operations + * such as glDrawArrays. (must be a #CoglOffscreen + * framebuffer currently) + * @error: A pointer to a #CoglError for returning exceptions + * + * Pushes the given @gles2_ctx onto a stack associated with @ctx so + * that the OpenGLES 2.0 api can be used instead of the Cogl + * rendering apis to read and write to the specified framebuffers. + * + * Usage of the api available through a #CoglGLES2Vtable is only + * allowed between cogl_push_gles2_context() and + * cogl_pop_gles2_context() calls. + * + * If there is a runtime problem with switching over to the given + * @gles2_ctx then this function will return %FALSE and return + * an error through @error. + * + * Since: 2.0 + * Return value: %TRUE if operation was successfull or %FALSE + * otherwise and @error will be updated. + * Stability: unstable + */ +CoglBool +cogl_push_gles2_context (CoglContext *ctx, + CoglGLES2Context *gles2_ctx, + CoglFramebuffer *read_buffer, + CoglFramebuffer *write_buffer, + CoglError **error); + +/** + * cogl_pop_gles2_context: + * @ctx: A #CoglContext + * + * Restores the previously active #CoglGLES2Context if there + * were nested calls to cogl_push_gles2_context() or otherwise + * restores the ability to render with the Cogl api instead + * of OpenGLES 2.0. + * + * The behaviour is undefined if calls to cogl_pop_gles2_context() + * are not balenced with the number of corresponding calls to + * cogl_push_gles2_context(). + * + * Since: 2.0 + * Stability: unstable + */ +void +cogl_pop_gles2_context (CoglContext *ctx); + +/** + * cogl_gles2_get_current_vtable: + * + * Returns the OpenGL ES 2.0 api vtable for the currently pushed + * #CoglGLES2Context (last pushed with cogl_push_gles2_context()) or + * %NULL if no #CoglGLES2Context has been pushed. + * + * Return value: The #CoglGLES2Vtable for the currently pushed + * #CoglGLES2Context or %NULL if none has been pushed. + * Since: 2.0 + * Stability: unstable + */ +CoglGLES2Vtable * +cogl_gles2_get_current_vtable (void); + +/** + * cogl_gles2_texture_2d_new_from_handle: + * @ctx: A #CoglContext + * @gles2_ctx: A #CoglGLES2Context allocated with + * cogl_gles2_context_new() + * @handle: An OpenGL ES 2.0 texture handle created with + * glGenTextures() + * @width: Width of the texture to allocate + * @height: Height of the texture to allocate + * @format: The format of the texture + * + * Creates a #CoglTexture2D from an OpenGL ES 2.0 texture handle that + * was created within the given @gles2_ctx via glGenTextures(). The + * texture needs to have been associated with the GL_TEXTURE_2D target. + * + * This interface is only intended for sharing textures to read + * from. The behaviour is undefined if the texture is modified using + * the Cogl api. + * + * Applications should only pass this function handles that were + * created via a #CoglGLES2Vtable or via libcogl-gles2 and not pass + * handles created directly using the system's native libGLESv2 + * api. + * + * Since: 2.0 + * Stability: unstable + */ +CoglTexture2D * +cogl_gles2_texture_2d_new_from_handle (CoglContext *ctx, + CoglGLES2Context *gles2_ctx, + unsigned int handle, + int width, + int height, + CoglPixelFormat format); + +/** + * cogl_gles2_texture_get_handle: + * @texture: A #CoglTexture + * @handle: A return location for an OpenGL ES 2.0 texture handle + * @target: A return location for an OpenGL ES 2.0 texture target + * + * Gets an OpenGL ES 2.0 texture handle for a #CoglTexture that can + * then be referenced by a #CoglGLES2Context. As well as returning + * a texture handle the texture's target (such as GL_TEXTURE_2D) is + * also returned. + * + * If the #CoglTexture can not be shared with a #CoglGLES2Context then + * this function will return %FALSE. + * + * This api does not affect the lifetime of the CoglTexture and you + * must take care not to reference the returned handle after the + * original texture has been freed. + * + * This interface is only intended for sharing textures to read + * from. The behaviour is undefined if the texture is modified by a + * GLES2 context. + * + * This function will only return %TRUE for low-level + * #CoglTextures such as #CoglTexture2D or #CoglTexture3D but + * not for high level meta textures such as + * #CoglTexture2DSliced + * + * The handle returned should not be passed directly to a system + * OpenGL ES 2.0 library, the handle is only intended to be used via + * a #CoglGLES2Vtable or via libcogl-gles2. + * + * Return value: %TRUE if a handle and target could be returned + * otherwise %FALSE is returned. + * Since: 2.0 + * Stability: unstable + */ +CoglBool +cogl_gles2_texture_get_handle (CoglTexture *texture, + unsigned int *handle, + unsigned int *target); + +/** + * cogl_is_gles2_context: + * @object: A #CoglObject pointer + * + * Gets whether the given object references a #CoglGLES2Context. + * + * Return value: %TRUE if the object references a #CoglGLES2Context + * and %FALSE otherwise. + * Since: 2.0 + * Stability: unstable + */ +CoglBool +cogl_is_gles2_context (void *object); + +COGL_END_DECLS + +/* The gobject introspection scanner seems to parse public headers in + * isolation which means we need to be extra careful about how we + * define and undefine __COGL_H_INSIDE__ used to detect when internal + * headers are incorrectly included by developers. In the gobject + * introspection case we have to manually define __COGL_H_INSIDE__ as + * a commandline argument for the scanner which means we must be + * careful not to undefine it in a header... + */ +#ifdef __COGL_MUST_UNDEF_COGL_H_INSIDE_COGL_GLES2__ +#undef __COGL_H_INSIDE__ +#undef __COGL_MUST_UNDEF_COGL_H_INSIDE_COGL_GLES2__ +#endif + +#endif /* __COGL_GLES2_H__ */ + diff --git a/cogl/cogl/cogl-glib-source.c b/cogl/cogl/cogl-glib-source.c new file mode 100644 index 0000000..b0b0ac5 --- /dev/null +++ b/cogl/cogl/cogl-glib-source.c @@ -0,0 +1,195 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-glib-source.h" +#include "cogl-poll.h" + +typedef struct _CoglGLibSource +{ + GSource source; + + CoglRenderer *renderer; + + GArray *poll_fds; + int poll_fds_age; + + int64_t expiration_time; +} CoglGLibSource; + +static CoglBool +cogl_glib_source_prepare (GSource *source, int *timeout) +{ + CoglGLibSource *cogl_source = (CoglGLibSource *) source; + CoglPollFD *poll_fds; + int n_poll_fds; + int64_t cogl_timeout; + int age; + int i; + + age = cogl_poll_renderer_get_info (cogl_source->renderer, + &poll_fds, + &n_poll_fds, + &cogl_timeout); + + /* We have to be careful not to call g_source_add/remove_poll unless + * the FDs have changed because it will cause the main loop to + * immediately wake up. If we call it every time the source is + * prepared it will effectively never go idle. */ + if (age != cogl_source->poll_fds_age) + { + /* Remove any existing polls before adding the new ones */ + for (i = 0; i < cogl_source->poll_fds->len; i++) + { + GPollFD *poll_fd = &g_array_index (cogl_source->poll_fds, GPollFD, i); + g_source_remove_poll (source, poll_fd); + } + + g_array_set_size (cogl_source->poll_fds, n_poll_fds); + + for (i = 0; i < n_poll_fds; i++) + { + GPollFD *poll_fd = &g_array_index (cogl_source->poll_fds, GPollFD, i); + poll_fd->fd = poll_fds[i].fd; + g_source_add_poll (source, poll_fd); + } + } + + cogl_source->poll_fds_age = age; + + /* Update the events */ + for (i = 0; i < n_poll_fds; i++) + { + GPollFD *poll_fd = &g_array_index (cogl_source->poll_fds, GPollFD, i); + poll_fd->events = poll_fds[i].events; + poll_fd->revents = 0; + } + + if (cogl_timeout == -1) + { + *timeout = -1; + cogl_source->expiration_time = -1; + } + else + { + /* Round up to ensure that we don't try again too early */ + *timeout = (cogl_timeout + 999) / 1000; + cogl_source->expiration_time = (g_source_get_time (source) + + cogl_timeout); + } + + return *timeout == 0; +} + +static CoglBool +cogl_glib_source_check (GSource *source) +{ + CoglGLibSource *cogl_source = (CoglGLibSource *) source; + int i; + + if (cogl_source->expiration_time >= 0 && + g_source_get_time (source) >= cogl_source->expiration_time) + return TRUE; + + for (i = 0; i < cogl_source->poll_fds->len; i++) + { + GPollFD *poll_fd = &g_array_index (cogl_source->poll_fds, GPollFD, i); + if (poll_fd->revents != 0) + return TRUE; + } + + return FALSE; +} + +static CoglBool +cogl_glib_source_dispatch (GSource *source, + GSourceFunc callback, + void *user_data) +{ + CoglGLibSource *cogl_source = (CoglGLibSource *) source; + CoglPollFD *poll_fds = + (CoglPollFD *) &g_array_index (cogl_source->poll_fds, GPollFD, 0); + + cogl_poll_renderer_dispatch (cogl_source->renderer, + poll_fds, + cogl_source->poll_fds->len); + + return TRUE; +} + +static void +cogl_glib_source_finalize (GSource *source) +{ + CoglGLibSource *cogl_source = (CoglGLibSource *) source; + + g_array_free (cogl_source->poll_fds, TRUE); +} + +static GSourceFuncs +cogl_glib_source_funcs = + { + cogl_glib_source_prepare, + cogl_glib_source_check, + cogl_glib_source_dispatch, + cogl_glib_source_finalize + }; + +GSource * +cogl_glib_renderer_source_new (CoglRenderer *renderer, + int priority) +{ + GSource *source; + CoglGLibSource *cogl_source; + + source = g_source_new (&cogl_glib_source_funcs, + sizeof (CoglGLibSource)); + cogl_source = (CoglGLibSource *) source; + + cogl_source->renderer = renderer; + cogl_source->poll_fds = g_array_new (FALSE, FALSE, sizeof (GPollFD)); + + if (priority != G_PRIORITY_DEFAULT) + g_source_set_priority (source, priority); + + return source; +} + +GSource * +cogl_glib_source_new (CoglContext *context, + int priority) +{ + return cogl_glib_renderer_source_new (cogl_context_get_renderer (context), + priority); +} + + diff --git a/cogl/cogl/cogl-glib-source.h b/cogl/cogl/cogl-glib-source.h new file mode 100644 index 0000000..ddb7f99 --- /dev/null +++ b/cogl/cogl/cogl-glib-source.h @@ -0,0 +1,97 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_GSOURCE_H__ +#define __COGL_GSOURCE_H__ + +#include +#include + +G_BEGIN_DECLS + +/** + * cogl_glib_source_new: + * @context: A #CoglContext + * @priority: The priority of the #GSource + * + * Creates a #GSource which handles Cogl's internal system event + * processing. This can be used as a convenience instead of + * cogl_poll_renderer_get_info() and cogl_poll_renderer_dispatch() in + * applications that are already using the GLib main loop. After this + * is called the #GSource should be attached to the main loop using + * g_source_attach(). + * + * Applications that manually connect to a #CoglRenderer before they + * create a #CoglContext should instead use + * cogl_glib_renderer_source_new() so that events may be dispatched + * before a context has been created. In that case you don't need to + * use this api in addition later, it is simply enough to use + * cogl_glib_renderer_source_new() instead. + * + * This api is actually just a thin convenience wrapper around + * cogl_glib_renderer_source_new() + * + * Return value: a new #GSource + * + * Stability: unstable + * Since: 1.10 + */ +GSource * +cogl_glib_source_new (CoglContext *context, + int priority); + +/** + * cogl_glib_renderer_source_new: + * @renderer: A #CoglRenderer + * @priority: The priority of the #GSource + * + * Creates a #GSource which handles Cogl's internal system event + * processing. This can be used as a convenience instead of + * cogl_poll_renderer_get_info() and cogl_poll_renderer_dispatch() in + * applications that are already using the GLib main loop. After this + * is called the #GSource should be attached to the main loop using + * g_source_attach(). + * + * Return value: a new #GSource + * + * Stability: unstable + * Since: 1.16 + */ +GSource * +cogl_glib_renderer_source_new (CoglRenderer *renderer, + int priority); + +G_END_DECLS + +#endif /* __COGL_GSOURCE_H__ */ diff --git a/cogl/cogl/cogl-glsl-shader-boilerplate.h b/cogl/cogl/cogl-glsl-shader-boilerplate.h new file mode 100644 index 0000000..6d882da --- /dev/null +++ b/cogl/cogl/cogl-glsl-shader-boilerplate.h @@ -0,0 +1,86 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_SHADER_BOILERPLATE_H +#define __COGL_SHADER_BOILERPLATE_H + +#define _COGL_COMMON_SHADER_BOILERPLATE \ + "#define COGL_VERSION 100\n" \ + "\n" \ + "uniform mat4 cogl_modelview_matrix;\n" \ + "uniform mat4 cogl_modelview_projection_matrix;\n" \ + "uniform mat4 cogl_projection_matrix;\n" + +/* This declares all of the variables that we might need. This is + * working on the assumption that the compiler will optimise them out + * if they are not actually used. The GLSL spec at least implies that + * this will happen for varyings but it doesn't explicitly so for + * attributes */ +#define _COGL_VERTEX_SHADER_BOILERPLATE \ + _COGL_COMMON_SHADER_BOILERPLATE \ + "#define cogl_color_out _cogl_color\n" \ + "varying vec4 _cogl_color;\n" \ + "#define cogl_tex_coord_out _cogl_tex_coord\n" \ + "#define cogl_position_out gl_Position\n" \ + "#define cogl_point_size_out gl_PointSize\n" \ + "\n" \ + "attribute vec4 cogl_color_in;\n" \ + "attribute vec4 cogl_position_in;\n" \ + "#define cogl_tex_coord_in cogl_tex_coord0_in;\n" \ + "attribute vec3 cogl_normal_in;\n" + +#define _COGL_FRAGMENT_SHADER_BOILERPLATE \ + "#ifdef GL_ES\n" \ + "precision highp float;\n" \ + "#endif\n" \ + _COGL_COMMON_SHADER_BOILERPLATE \ + "\n" \ + "varying vec4 _cogl_color;\n" \ + "\n" \ + "#define cogl_color_in _cogl_color\n" \ + "#define cogl_tex_coord_in _cogl_tex_coord\n" \ + "\n" \ + "#define cogl_color_out gl_FragColor\n" \ + "#define cogl_depth_out gl_FragDepth\n" \ + "\n" \ + "#define cogl_front_facing gl_FrontFacing\n" \ + "\n" \ + "#define cogl_point_coord gl_PointCoord\n" +#if 0 + /* GLSL 1.2 has a bottom left origin, though later versions + * allow use of an origin_upper_left keyword which would be + * more appropriate for Cogl. */ + "#define coglFragCoord gl_FragCoord\n" +#endif + +#endif /* __COGL_SHADER_BOILERPLATE_H */ + diff --git a/cogl/cogl/cogl-glsl-shader-private.h b/cogl/cogl/cogl-glsl-shader-private.h new file mode 100644 index 0000000..9899c12 --- /dev/null +++ b/cogl/cogl/cogl-glsl-shader-private.h @@ -0,0 +1,41 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _COGL_GLSL_SHADER_PRIVATE_H_ +#define _COGL_GLSL_SHADER_PRIVATE_H_ + +void +_cogl_glsl_shader_set_source_with_boilerplate (CoglContext *ctx, + GLuint shader_gl_handle, + GLenum shader_gl_type, + CoglPipeline *pipeline, + GLsizei count_in, + const char **strings_in, + const GLint *lengths_in); + +#endif /* _COGL_GLSL_SHADER_PRIVATE_H_ */ diff --git a/cogl/cogl/cogl-glsl-shader.c b/cogl/cogl/cogl-glsl-shader.c new file mode 100644 index 0000000..5aadd10 --- /dev/null +++ b/cogl/cogl/cogl-glsl-shader.c @@ -0,0 +1,192 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + * Neil Roberts + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-context-private.h" +#include "cogl-util-gl-private.h" +#include "cogl-glsl-shader-private.h" +#include "cogl-glsl-shader-boilerplate.h" + +#include + +#include + +static CoglBool +add_layer_vertex_boilerplate_cb (CoglPipelineLayer *layer, + void *user_data) +{ + GString *layer_declarations = user_data; + int unit_index = _cogl_pipeline_layer_get_unit_index (layer); + g_string_append_printf (layer_declarations, + "attribute vec4 cogl_tex_coord%d_in;\n" + "#define cogl_texture_matrix%i cogl_texture_matrix[%i]\n" + "#define cogl_tex_coord%i_out _cogl_tex_coord[%i]\n", + layer->index, + layer->index, + unit_index, + layer->index, + unit_index); + return TRUE; +} + +static CoglBool +add_layer_fragment_boilerplate_cb (CoglPipelineLayer *layer, + void *user_data) +{ + GString *layer_declarations = user_data; + g_string_append_printf (layer_declarations, + "#define cogl_tex_coord%i_in _cogl_tex_coord[%i]\n", + layer->index, + _cogl_pipeline_layer_get_unit_index (layer)); + return TRUE; +} + +void +_cogl_glsl_shader_set_source_with_boilerplate (CoglContext *ctx, + GLuint shader_gl_handle, + GLenum shader_gl_type, + CoglPipeline *pipeline, + GLsizei count_in, + const char **strings_in, + const GLint *lengths_in) +{ + const char *vertex_boilerplate; + const char *fragment_boilerplate; + + const char **strings = g_alloca (sizeof (char *) * (count_in + 4)); + GLint *lengths = g_alloca (sizeof (GLint) * (count_in + 4)); + char *version_string; + int count = 0; + + int n_layers; + + vertex_boilerplate = _COGL_VERTEX_SHADER_BOILERPLATE; + fragment_boilerplate = _COGL_FRAGMENT_SHADER_BOILERPLATE; + + version_string = g_strdup_printf ("#version %i\n\n", + ctx->glsl_version_to_use); + strings[count] = version_string; + lengths[count++] = -1; + + if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_GL_EMBEDDED) && + cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_3D)) + { + static const char texture_3d_extension[] = + "#extension GL_OES_texture_3D : enable\n"; + strings[count] = texture_3d_extension; + lengths[count++] = sizeof (texture_3d_extension) - 1; + } + + if (shader_gl_type == GL_VERTEX_SHADER) + { + strings[count] = vertex_boilerplate; + lengths[count++] = strlen (vertex_boilerplate); + } + else if (shader_gl_type == GL_FRAGMENT_SHADER) + { + strings[count] = fragment_boilerplate; + lengths[count++] = strlen (fragment_boilerplate); + } + + n_layers = cogl_pipeline_get_n_layers (pipeline); + if (n_layers) + { + GString *layer_declarations = ctx->codegen_boilerplate_buffer; + g_string_set_size (layer_declarations, 0); + + g_string_append_printf (layer_declarations, + "varying vec4 _cogl_tex_coord[%d];\n", + n_layers); + + if (shader_gl_type == GL_VERTEX_SHADER) + { + g_string_append_printf (layer_declarations, + "uniform mat4 cogl_texture_matrix[%d];\n", + n_layers); + + _cogl_pipeline_foreach_layer_internal (pipeline, + add_layer_vertex_boilerplate_cb, + layer_declarations); + } + else if (shader_gl_type == GL_FRAGMENT_SHADER) + { + _cogl_pipeline_foreach_layer_internal (pipeline, + add_layer_fragment_boilerplate_cb, + layer_declarations); + } + + strings[count] = layer_declarations->str; + lengths[count++] = -1; /* null terminated */ + } + + memcpy (strings + count, strings_in, sizeof (char *) * count_in); + if (lengths_in) + memcpy (lengths + count, lengths_in, sizeof (GLint) * count_in); + else + { + int i; + + for (i = 0; i < count_in; i++) + lengths[count + i] = -1; /* null terminated */ + } + count += count_in; + + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SHOW_SOURCE))) + { + GString *buf = g_string_new (NULL); + int i; + + g_string_append_printf (buf, + "%s shader:\n", + shader_gl_type == GL_VERTEX_SHADER ? + "vertex" : "fragment"); + for (i = 0; i < count; i++) + if (lengths[i] != -1) + g_string_append_len (buf, strings[i], lengths[i]); + else + g_string_append (buf, strings[i]); + + g_message ("%s", buf->str); + + g_string_free (buf, TRUE); + } + + GE( ctx, glShaderSource (shader_gl_handle, count, + (const char **) strings, lengths) ); + + g_free (version_string); +} diff --git a/cogl/cogl/cogl-glx-display-private.h b/cogl/cogl/cogl-glx-display-private.h new file mode 100644 index 0000000..133c118 --- /dev/null +++ b/cogl/cogl/cogl-glx-display-private.h @@ -0,0 +1,62 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_DISPLAY_GLX_PRIVATE_H +#define __COGL_DISPLAY_GLX_PRIVATE_H + +#include "cogl-object-private.h" + +typedef struct _CoglGLXCachedConfig +{ + /* This will be -1 if there is no cached config in this slot */ + int depth; + CoglBool found; + GLXFBConfig fb_config; + CoglBool stereo; + CoglBool can_mipmap; +} CoglGLXCachedConfig; + +#define COGL_GLX_N_CACHED_CONFIGS 6 + +typedef struct _CoglGLXDisplay +{ + CoglGLXCachedConfig glx_cached_configs[COGL_GLX_N_CACHED_CONFIGS]; + + CoglBool found_fbconfig; + CoglBool fbconfig_has_rgba_visual; + GLXFBConfig fbconfig; + + /* Single context for all wins */ + GLXContext glx_context; + GLXWindow dummy_glxwin; + Window dummy_xwin; +} CoglGLXDisplay; + +#endif /* __COGL_DISPLAY_GLX_PRIVATE_H */ diff --git a/cogl/cogl/cogl-glx-renderer-private.h b/cogl/cogl/cogl-glx-renderer-private.h new file mode 100644 index 0000000..cb8ff97 --- /dev/null +++ b/cogl/cogl/cogl-glx-renderer-private.h @@ -0,0 +1,108 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_RENDERER_GLX_PRIVATE_H +#define __COGL_RENDERER_GLX_PRIVATE_H + +#include +#include "cogl-object-private.h" +#include "cogl-xlib-renderer-private.h" + +typedef struct _CoglGLXRenderer +{ + int glx_major; + int glx_minor; + + int glx_error_base; + int glx_event_base; + + CoglBool is_direct; + + /* Vblank stuff */ + int dri_fd; + + /* enumeration with relatioship between OML_sync_control + * UST (unadjusted-system-time) and the system clock */ + enum { + COGL_GLX_UST_IS_UNKNOWN, + COGL_GLX_UST_IS_GETTIMEOFDAY, + COGL_GLX_UST_IS_MONOTONIC_TIME, + COGL_GLX_UST_IS_OTHER + } ust_type; + + /* GModule pointing to libGL which we use to get glX functions out of */ + GModule *libgl_module; + + CoglClosure *flush_notifications_idle; + + /* Copy of the winsys features that are based purely on the + * information we can get without using a GL context. We want to + * determine this before we have a context so that we can use the + * function pointers from the extensions earlier. This is necessary + * to use the glXCreateContextAttribs function. */ + unsigned long base_winsys_features + [COGL_FLAGS_N_LONGS_FOR_SIZE (COGL_WINSYS_FEATURE_N_FEATURES)]; + + CoglFeatureFlags legacy_feature_flags; + + /* Function pointers for core GLX functionality. We can't just link + against these directly because we need to conditionally load + libGL when we are using GLX so that it won't conflict with a GLES + library if we are using EGL + GLES. These are just the functions + that we want to use before calling glXGetProcAddress */ + Bool + (* glXQueryExtension) (Display *dpy, int *errorb, int *event); + const char * + (* glXQueryExtensionsString) (Display *dpy, int screen); + Bool + (* glXQueryVersion) (Display *dpy, int *maj, int *min); + void * + (* glXGetProcAddress) (const GLubyte *procName); + + int + (* glXQueryDrawable) (Display *dpy, GLXDrawable drawable, + int attribute, unsigned int *value); + + /* Function pointers for GLX specific extensions */ +#define COGL_WINSYS_FEATURE_BEGIN(a, b, c, d, e, f, g) + +#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args) \ + ret (APIENTRY * name) args; + +#define COGL_WINSYS_FEATURE_END() + +#include "cogl-winsys-glx-feature-functions.h" + +#undef COGL_WINSYS_FEATURE_BEGIN +#undef COGL_WINSYS_FEATURE_FUNCTION +#undef COGL_WINSYS_FEATURE_END +} CoglGLXRenderer; + +#endif /* __COGL_RENDERER_GLX_PRIVATE_H */ diff --git a/cogl/cogl/cogl-glx.h b/cogl/cogl/cogl-glx.h new file mode 100644 index 0000000..69963d7 --- /dev/null +++ b/cogl/cogl/cogl-glx.h @@ -0,0 +1,96 @@ +/* + * Cogl + * + * A Low-Level GPU Graphics and Utilities API + * + * Copyright (C) 2014 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_GLX_H__ +#define __COGL_GLX_H__ + +/* NB: this is a top-level header that can be included directly but we + * want to be careful not to define __COGL_H_INSIDE__ when this is + * included internally while building Cogl itself since + * __COGL_H_INSIDE__ is used in headers to guard public vs private api + * definitions + */ +#ifndef COGL_COMPILATION + +/* Note: When building Cogl .gir we explicitly define + * __COGL_GLX_H_INSIDE__ */ +#ifndef __COGL_GLX_H_INSIDE__ +#define __COGL_GLX_H_INSIDE__ +#endif + +/* Note: When building Cogl .gir we explicitly define + * __COGL_H_INSIDE__ */ +#ifndef __COGL_H_INSIDE__ +#define __COGL_H_INSIDE__ +#define __COGL_MUST_UNDEF_COGL_H_INSIDE_COGL_GLX_ +#endif + +#endif /* COGL_COMPILATION */ + + +#include +#include + +COGL_BEGIN_DECLS + +/** + * cogl_glx_context_get_glx_context: + * @context: A #CoglContext pointer + * + * If you have done a runtime check to determine that Cogl is using + * GLX internally then this API can be used to retrieve the GLXContext + * handle that was setup internally. The result is undefined if Cogl + * is not using GLX. + * + * Return value: The internally setup GLXContext handle. + * Since: 1.18 + * Stability: unstable + */ +GLXContext +cogl_glx_context_get_glx_context (CoglContext *context); + +COGL_END_DECLS + +/* The gobject introspection scanner seems to parse public headers in + * isolation which means we need to be extra careful about how we + * define and undefine __COGL_H_INSIDE__ used to detect when internal + * headers are incorrectly included by developers. In the gobject + * introspection case we have to manually define __COGL_H_INSIDE__ as + * a commandline argument for the scanner which means we must be + * careful not to undefine it in a header... + */ +#ifdef __COGL_MUST_UNDEF_COGL_H_INSIDE_COGL_GLX_ +#warning +#undef __COGL_H_INSIDE__ +#undef __COGL_GLX_H_INSIDE__ +#undef __COGL_MUST_UNDEF_COGL_H_INSIDE_COGL_GLX_ +#endif + +#endif /* __COGL_GLX_H__ */ diff --git a/cogl/cogl/cogl-gpu-info-private.h b/cogl/cogl/cogl-gpu-info-private.h new file mode 100644 index 0000000..e532cdd --- /dev/null +++ b/cogl/cogl/cogl-gpu-info-private.h @@ -0,0 +1,117 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_GPU_INFO_PRIVATE_H +#define __COGL_GPU_INFO_PRIVATE_H + +#include "cogl-context.h" + +typedef enum _CoglGpuInfoArchitectureFlag +{ + COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE, + COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_TILED, + COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_SOFTWARE, + COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE, + COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_DEFERRED, + COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_SOFTWARE +} CoglGpuInfoArchitectureFlag; + +typedef enum _CoglGpuInfoArchitecture +{ + COGL_GPU_INFO_ARCHITECTURE_UNKNOWN, + COGL_GPU_INFO_ARCHITECTURE_SANDYBRIDGE, + COGL_GPU_INFO_ARCHITECTURE_SGX, + COGL_GPU_INFO_ARCHITECTURE_MALI, + COGL_GPU_INFO_ARCHITECTURE_LLVMPIPE, + COGL_GPU_INFO_ARCHITECTURE_SOFTPIPE, + COGL_GPU_INFO_ARCHITECTURE_SWRAST +} CoglGpuInfoArchitecture; + +typedef enum +{ + COGL_GPU_INFO_VENDOR_UNKNOWN, + COGL_GPU_INFO_VENDOR_INTEL, + COGL_GPU_INFO_VENDOR_IMAGINATION_TECHNOLOGIES, + COGL_GPU_INFO_VENDOR_ARM, + COGL_GPU_INFO_VENDOR_QUALCOMM, + COGL_GPU_INFO_VENDOR_NVIDIA, + COGL_GPU_INFO_VENDOR_ATI, + COGL_GPU_INFO_VENDOR_MESA +} CoglGpuInfoVendor; + +typedef enum +{ + COGL_GPU_INFO_DRIVER_PACKAGE_UNKNOWN, + COGL_GPU_INFO_DRIVER_PACKAGE_MESA +} CoglGpuInfoDriverPackage; + +typedef enum +{ + /* If this bug is present then it is faster to read pixels into a + * PBO and then memcpy out of the PBO into system memory rather than + * directly read into system memory. + * https://bugs.freedesktop.org/show_bug.cgi?id=46631 + */ + COGL_GPU_INFO_DRIVER_BUG_MESA_46631_SLOW_READ_PIXELS = 1 << 0 +} CoglGpuInfoDriverBug; + +typedef struct _CoglGpuInfoVersion CoglGpuInfoVersion; + +typedef struct _CoglGpuInfo CoglGpuInfo; + +struct _CoglGpuInfo +{ + CoglGpuInfoVendor vendor; + const char *vendor_name; + + CoglGpuInfoDriverPackage driver_package; + const char *driver_package_name; + int driver_package_version; + + CoglGpuInfoArchitecture architecture; + const char *architecture_name; + CoglGpuInfoArchitectureFlag architecture_flags; + + CoglGpuInfoDriverBug driver_bugs; +}; + +/* + * _cogl_gpu_info_init: + * @ctx: A #CoglContext + * @gpu: A return location for the GPU information + * + * Determines information about the GPU and driver from the given + * context. + */ +void +_cogl_gpu_info_init (CoglContext *ctx, + CoglGpuInfo *gpu); + +#endif /* __COGL_GPU_INFO_PRIVATE_H */ diff --git a/cogl/cogl/cogl-gpu-info.c b/cogl/cogl/cogl-gpu-info.c new file mode 100644 index 0000000..8453828 --- /dev/null +++ b/cogl/cogl/cogl-gpu-info.c @@ -0,0 +1,581 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include +#include + +#include + +#include "cogl-gpu-info-private.h" +#include "cogl-context-private.h" +#include "cogl-version.h" + +typedef struct +{ + const char *renderer_string; + const char *version_string; + const char *vendor_string; +} CoglGpuInfoStrings; + +typedef struct CoglGpuInfoArchitectureDescription +{ + CoglGpuInfoArchitecture architecture; + const char *name; + CoglGpuInfoArchitectureFlag flags; + CoglBool (* check_function) (const CoglGpuInfoStrings *strings); + +} CoglGpuInfoArchitectureDescription; + +typedef struct +{ + CoglGpuInfoVendor vendor; + const char *name; + CoglBool (* check_function) (const CoglGpuInfoStrings *strings); + const CoglGpuInfoArchitectureDescription *architectures; + +} CoglGpuInfoVendorDescription; + +typedef struct +{ + CoglGpuInfoDriverPackage driver_package; + const char *name; + CoglBool (* check_function) (const CoglGpuInfoStrings *strings, + int *version_out); +} CoglGpuInfoDriverPackageDescription; + +static CoglBool +_cogl_gpu_info_parse_version_string (const char *version_string, + int n_components, + const char **tail, + int *version_ret) +{ + int version = 0; + uint64_t part; + int i; + + for (i = 0; ; i++) + { + errno = 0; + part = g_ascii_strtoull (version_string, + (char **) &version_string, + 10); + + if (errno || part > COGL_VERSION_MAX_COMPONENT_VALUE) + return FALSE; + + version |= part << ((2 - i) * COGL_VERSION_COMPONENT_BITS); + + if (i + 1 >= n_components) + break; + + if (*version_string != '.') + return FALSE; + + version_string++; + } + + if (version_ret) + *version_ret = version; + if (tail) + *tail = version_string; + + return TRUE; +} + +static CoglBool +match_phrase (const char *string, const char *phrase) +{ + const char *part = strstr (string, phrase); + int len; + + if (part == NULL) + return FALSE; + + /* The match must either be at the beginning of the string or + preceded by a space. */ + if (part > string && part[-1] != ' ') + return FALSE; + + /* Also match must either be at end of string or followed by a + * space. */ + len = strlen (phrase); + if (part[len] != '\0' && part[len] != ' ') + return FALSE; + + return TRUE; +} + +static CoglBool +check_intel_vendor (const CoglGpuInfoStrings *strings) +{ + return match_phrase (strings->renderer_string, "Intel(R)"); +} + +static CoglBool +check_imagination_technologies_vendor (const CoglGpuInfoStrings *strings) +{ + if (strcmp (strings->vendor_string, "Imagination Technologies") != 0) + return FALSE; + return TRUE; +} + +static CoglBool +check_arm_vendor (const CoglGpuInfoStrings *strings) +{ + if (strcmp (strings->vendor_string, "ARM") != 0) + return FALSE; + return TRUE; +} + +static CoglBool +check_qualcomm_vendor (const CoglGpuInfoStrings *strings) +{ + if (strcmp (strings->vendor_string, "Qualcomm") != 0) + return FALSE; + return TRUE; +} + +static CoglBool +check_nvidia_vendor (const CoglGpuInfoStrings *strings) +{ + if (strcmp (strings->vendor_string, "NVIDIA") != 0) + return FALSE; + + return TRUE; +} + +static CoglBool +check_ati_vendor (const CoglGpuInfoStrings *strings) +{ + if (strcmp (strings->vendor_string, "ATI") != 0) + return FALSE; + + return TRUE; +} + +static CoglBool +check_mesa_vendor (const CoglGpuInfoStrings *strings) +{ + if (strcmp (strings->vendor_string, "Tungsten Graphics, Inc") == 0) + return TRUE; + else if (strcmp (strings->vendor_string, "VMware, Inc.") == 0) + return TRUE; + else if (strcmp (strings->vendor_string, "Mesa Project") == 0) + return TRUE; + + return FALSE; +} + +static CoglBool +check_true (const CoglGpuInfoStrings *strings) +{ + /* This is a last resort so it always matches */ + return TRUE; +} + +static CoglBool +check_sandybridge_architecture (const CoglGpuInfoStrings *strings) +{ + return match_phrase (strings->renderer_string, "Sandybridge"); +} + +static CoglBool +check_llvmpipe_architecture (const CoglGpuInfoStrings *strings) +{ + return match_phrase (strings->renderer_string, "llvmpipe"); +} + +static CoglBool +check_softpipe_architecture (const CoglGpuInfoStrings *strings) +{ + return match_phrase (strings->renderer_string, "softpipe"); +} + +static CoglBool +check_swrast_architecture (const CoglGpuInfoStrings *strings) +{ + return match_phrase (strings->renderer_string, "software rasterizer") || + match_phrase (strings->renderer_string, "Software Rasterizer"); +} + +static CoglBool +check_sgx_architecture (const CoglGpuInfoStrings *strings) +{ + if (strncmp (strings->renderer_string, "PowerVR SGX", 12) != 0) + return FALSE; + + return TRUE; +} + +static CoglBool +check_mali_architecture (const CoglGpuInfoStrings *strings) +{ + if (strncmp (strings->renderer_string, "Mali-", 5) != 0) + return FALSE; + + return TRUE; +} + +static const CoglGpuInfoArchitectureDescription +intel_architectures[] = + { + { + COGL_GPU_INFO_ARCHITECTURE_SANDYBRIDGE, + "Sandybridge", + COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE | + COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE, + check_sandybridge_architecture + }, + { + COGL_GPU_INFO_ARCHITECTURE_UNKNOWN, + "Unknown", + COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE | + COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE, + check_true + } + }; + +static const CoglGpuInfoArchitectureDescription +powervr_architectures[] = + { + { + COGL_GPU_INFO_ARCHITECTURE_SGX, + "SGX", + COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_TILED | + COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_DEFERRED, + check_sgx_architecture + }, + { + COGL_GPU_INFO_ARCHITECTURE_UNKNOWN, + "Unknown", + COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_TILED | + COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_TILED, + check_true + } + }; + +static const CoglGpuInfoArchitectureDescription +arm_architectures[] = + { + { + COGL_GPU_INFO_ARCHITECTURE_MALI, + "Mali", + COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_TILED | + COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE, + check_mali_architecture + }, + { + COGL_GPU_INFO_ARCHITECTURE_UNKNOWN, + "Unknown", + COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_TILED | + COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE, + check_true + } + }; + +static const CoglGpuInfoArchitectureDescription +mesa_architectures[] = + { + { + COGL_GPU_INFO_ARCHITECTURE_LLVMPIPE, + "LLVM Pipe", + COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE | + COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_SOFTWARE | + COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE | + COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_SOFTWARE, + check_llvmpipe_architecture + }, + { + COGL_GPU_INFO_ARCHITECTURE_SOFTPIPE, + "Softpipe", + COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE | + COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_SOFTWARE | + COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE | + COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_SOFTWARE, + check_softpipe_architecture + }, + { + COGL_GPU_INFO_ARCHITECTURE_SWRAST, + "SWRast", + COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE | + COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_SOFTWARE | + COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE | + COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_SOFTWARE, + check_swrast_architecture + }, + { + COGL_GPU_INFO_ARCHITECTURE_UNKNOWN, + "Unknown", + COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE | + COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE, + check_true + } + }; + +static const CoglGpuInfoArchitectureDescription +unknown_architectures[] = + { + { + COGL_GPU_INFO_ARCHITECTURE_UNKNOWN, + "Unknown", + COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE | + COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE, + check_true + } + }; + +static const CoglGpuInfoVendorDescription +_cogl_gpu_info_vendors[] = + { + { + COGL_GPU_INFO_VENDOR_INTEL, + "Intel", + check_intel_vendor, + intel_architectures + }, + { + COGL_GPU_INFO_VENDOR_IMAGINATION_TECHNOLOGIES, + "Imagination Technologies", + check_imagination_technologies_vendor, + powervr_architectures + }, + { + COGL_GPU_INFO_VENDOR_ARM, + "ARM", + check_arm_vendor, + arm_architectures + }, + { + COGL_GPU_INFO_VENDOR_QUALCOMM, + "Qualcomm", + check_qualcomm_vendor, + unknown_architectures + }, + { + COGL_GPU_INFO_VENDOR_NVIDIA, + "Nvidia", + check_nvidia_vendor, + unknown_architectures + }, + { + COGL_GPU_INFO_VENDOR_ATI, + "ATI", + check_ati_vendor, + unknown_architectures + }, + /* Must be last */ + { + COGL_GPU_INFO_VENDOR_MESA, + "Mesa", + check_mesa_vendor, + mesa_architectures + }, + { + COGL_GPU_INFO_VENDOR_UNKNOWN, + "Unknown", + check_true, + unknown_architectures + } + }; + +static CoglBool +check_mesa_driver_package (const CoglGpuInfoStrings *strings, + int *version_ret) +{ + uint64_t micro_part; + const char *v; + + /* The version string should always begin a two-part GL version + number */ + if (!_cogl_gpu_info_parse_version_string (strings->version_string, + 2, /* n_components */ + &v, /* tail */ + NULL /* version_ret */)) + return FALSE; + + /* In mesa this will be followed optionally by "(Core Profile)" and + * then "Mesa" */ + v = strstr (v, " Mesa "); + if (!v) + return FALSE; + + v += 6; + + /* Next there will be a version string that is at least two + components. On a git devel build the version will be something + like "-devel" instead */ + if (!_cogl_gpu_info_parse_version_string (v, + 2, /* n_components */ + &v, /* tail */ + version_ret)) + return FALSE; + + /* If it is a development build then we'll just leave the micro + number as 0 */ + if (g_str_has_prefix (v, "-devel")) + return TRUE; + + /* Otherwise there should be a micro version number */ + if (*v != '.') + return FALSE; + + errno = 0; + micro_part = g_ascii_strtoull (v + 1, NULL /* endptr */, 10 /* base */); + if (errno || micro_part > COGL_VERSION_MAX_COMPONENT_VALUE) + return FALSE; + + *version_ret = COGL_VERSION_ENCODE (COGL_VERSION_GET_MAJOR (*version_ret), + COGL_VERSION_GET_MINOR (*version_ret), + micro_part); + + return TRUE; +} + +UNIT_TEST (check_mesa_driver_package_parser, + 0, /* no requirements */ + 0 /* no failure cases */) +{ + /* renderer_string, version_string, vendor_string;*/ + const CoglGpuInfoStrings test_strings[2] = { + { NULL, "3.1 Mesa 9.2-devel15436ad", NULL }, + { NULL, "3.1 (Core Profile) Mesa 9.2.0-devel (git-15436ad)", NULL } + }; + int i; + int version; + + for (i = 0; i < G_N_ELEMENTS (test_strings); i++) + { + g_assert (check_mesa_driver_package (&test_strings[i], &version)); + g_assert_cmpint (version, ==, COGL_VERSION_ENCODE (9, 2, 0)); + } +} + +static CoglBool +check_unknown_driver_package (const CoglGpuInfoStrings *strings, + int *version_out) +{ + *version_out = 0; + + /* This is a last resort so it always matches */ + return TRUE; +} + +static const CoglGpuInfoDriverPackageDescription +_cogl_gpu_info_driver_packages[] = + { + { + COGL_GPU_INFO_DRIVER_PACKAGE_MESA, + "Mesa", + check_mesa_driver_package + }, + /* Must be last */ + { + COGL_GPU_INFO_DRIVER_PACKAGE_UNKNOWN, + "Unknown", + check_unknown_driver_package + } + }; + +void +_cogl_gpu_info_init (CoglContext *ctx, + CoglGpuInfo *gpu) +{ + CoglGpuInfoStrings strings; + int i; + + strings.renderer_string = (const char *) ctx->glGetString (GL_RENDERER); + strings.version_string = _cogl_context_get_gl_version (ctx); + strings.vendor_string = (const char *) ctx->glGetString (GL_VENDOR); + + /* Determine the driver package */ + for (i = 0; ; i++) + { + const CoglGpuInfoDriverPackageDescription *description = + _cogl_gpu_info_driver_packages + i; + + if (description->check_function (&strings, &gpu->driver_package_version)) + { + gpu->driver_package = description->driver_package; + gpu->driver_package_name = description->name; + break; + } + } + + /* Determine the GPU vendor */ + for (i = 0; ; i++) + { + const CoglGpuInfoVendorDescription *description = + _cogl_gpu_info_vendors + i; + + if (description->check_function (&strings)) + { + int j; + + gpu->vendor = description->vendor; + gpu->vendor_name = description->name; + + for (j = 0; ; j++) + { + const CoglGpuInfoArchitectureDescription *architecture = + description->architectures + j; + + if (architecture->check_function (&strings)) + { + gpu->architecture = architecture->architecture; + gpu->architecture_name = architecture->name; + gpu->architecture_flags = architecture->flags; + goto probed; + } + } + } + } + +probed: + + COGL_NOTE (WINSYS, "Driver package = %s, vendor = %s, architecture = %s\n", + gpu->driver_package_name, + gpu->vendor_name, + gpu->architecture_name); + + /* Determine the driver bugs */ + + /* In Mesa the glReadPixels implementation is really slow + when using the Intel driver. The Intel + driver has a fast blit path when reading into a PBO. Reading into + a temporary PBO and then memcpying back out to the application's + memory is faster than a regular glReadPixels in this case */ + if (gpu->vendor == COGL_GPU_INFO_VENDOR_INTEL && + gpu->driver_package == COGL_GPU_INFO_DRIVER_PACKAGE_MESA) + gpu->driver_bugs |= COGL_GPU_INFO_DRIVER_BUG_MESA_46631_SLOW_READ_PIXELS; +} diff --git a/cogl/cogl/cogl-gtype-private.h b/cogl/cogl/cogl-gtype-private.h new file mode 100644 index 0000000..e750526 --- /dev/null +++ b/cogl/cogl/cogl-gtype-private.h @@ -0,0 +1,278 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_GTYPE_PRIVATE_H__ +#define __COGL_GTYPE_PRIVATE_H__ + +#include "cogl-config.h" + +#include +#include + +#include "cogl-object-private.h" + +/* Move this to public headers? */ +typedef struct _CoglGtypeObject CoglGtypeObject; +typedef struct _CoglGtypeClass CoglGtypeClass; + +struct _CoglGtypeObject +{ + GTypeInstance parent_instance; + + guint dummy; +}; + +struct _CoglGtypeClass +{ + GTypeClass base_class; + + guint dummy; +}; + +#define I_(str) (g_intern_static_string ((str))) + +/**/ + +#define COGL_GTYPE_DEFINE_BOXED(Name,underscore_name,copy_func,free_func) \ +GType \ +cogl_##underscore_name##_get_gtype (void) \ +{ \ + static volatile size_t type_volatile = 0; \ + if (g_once_init_enter (&type_volatile)) \ + { \ + GType type = \ + g_boxed_type_register_static (g_intern_static_string (I_("Cogl" # Name)), \ + (GBoxedCopyFunc)copy_func, \ + (GBoxedFreeFunc)free_func); \ + g_once_init_leave (&type_volatile, type); \ + } \ + return type_volatile; \ +} + +#define COGL_GTYPE_IMPLEMENT_INTERFACE(name) { \ + const GInterfaceInfo g_implement_interface_info = { \ + (GInterfaceInitFunc) _cogl_gtype_dummy_iface_init, NULL, NULL \ + }; \ + g_type_add_interface_static (fundamental_type_id, \ + cogl_##name##_get_gtype(), \ + &g_implement_interface_info); \ + } + +#define _COGL_GTYPE_DEFINE_BASE_CLASS_BEGIN(Name,name) \ +GType \ +cogl_##name##_get_gtype (void) \ +{ \ + static volatile gsize type_id__volatile = 0; \ + if (g_once_init_enter (&type_id__volatile)) \ + { \ + static const GTypeFundamentalInfo finfo = { \ + (G_TYPE_FLAG_CLASSED | \ + G_TYPE_FLAG_INSTANTIATABLE | \ + G_TYPE_FLAG_DERIVABLE | \ + G_TYPE_FLAG_DEEP_DERIVABLE), \ + }; \ + static const GTypeValueTable value_table = { \ + _cogl_gtype_object_init_value, \ + _cogl_gtype_object_free_value, \ + _cogl_gtype_object_copy_value, \ + _cogl_gtype_object_peek_pointer, \ + "p", \ + _cogl_gtype_object_collect_value, \ + "p", \ + _cogl_gtype_object_lcopy_value, \ + }; \ + const GTypeInfo node_info = { \ + sizeof (CoglObjectClass), \ + (GBaseInitFunc) _cogl_gtype_object_class_base_init, \ + (GBaseFinalizeFunc) _cogl_gtype_object_class_base_finalize, \ + (GClassInitFunc) _cogl_gtype_object_class_init, \ + (GClassFinalizeFunc) NULL, \ + NULL, \ + sizeof (CoglObject), \ + 0, \ + (GInstanceInitFunc) _cogl_gtype_object_init, \ + &value_table, \ + }; \ + GType fundamental_type_id = \ + g_type_register_fundamental (g_type_fundamental_next (), \ + I_("Cogl" # Name), \ + &node_info, &finfo, \ + G_TYPE_FLAG_ABSTRACT); \ + g_once_init_leave (&type_id__volatile, \ + fundamental_type_id); + +#define _COGL_GTYPE_DEFINE_BASE_CLASS_END() \ + } \ + return type_id__volatile; \ + } + +#define COGL_GTYPE_DEFINE_BASE_CLASS(Name,name,...) \ + _COGL_GTYPE_DEFINE_BASE_CLASS_BEGIN(Name,name) \ + {__VA_ARGS__;} \ + _COGL_GTYPE_DEFINE_BASE_CLASS_END() + +#define _COGL_GTYPE_DEFINE_INTERFACE_EXTENDED_BEGIN(Name,name) \ + \ + static void name##_default_init (Name##Interface *klass); \ + GType \ + name##_get_gtype (void) \ + { \ + static volatile gsize type_id__volatile = 0; \ + if (g_once_init_enter (&type_id__volatile)) \ + { \ + GType fundamental_type_id = \ + g_type_register_static_simple (G_TYPE_INTERFACE, \ + g_intern_static_string (#Name), \ + sizeof (Name##Interface), \ + (GClassInitFunc)name##_default_init, \ + 0, \ + (GInstanceInitFunc)NULL, \ + (GTypeFlags) 0); \ + g_type_interface_add_prerequisite (fundamental_type_id, \ + cogl_object_get_gtype()); \ + { /* custom code follows */ + +#define _COGL_GTYPE_DEFINE_INTERFACE_EXTENDED_END() \ + /* following custom code */ \ + } \ + g_once_init_leave (&type_id__volatile, \ + fundamental_type_id); \ + } \ + return type_id__volatile; \ + } /* closes name##_get_type() */ + + +#define COGL_GTYPE_DEFINE_INTERFACE(Name,name) \ + typedef struct _Cogl##Name##Iface Cogl##Name##Iface; \ + typedef Cogl##Name##Iface Cogl##Name##Interface; \ + struct _Cogl##Name##Iface \ + { \ + /*< private >*/ \ + GTypeInterface g_iface; \ + }; \ + _COGL_GTYPE_DEFINE_INTERFACE_EXTENDED_BEGIN (Cogl##Name, cogl_##name) \ + _COGL_GTYPE_DEFINE_INTERFACE_EXTENDED_END () \ + static void \ + cogl_##name##_default_init (Cogl##Name##Interface *iface) \ + { \ + } + +#define _COGL_GTYPE_DEFINE_TYPE_EXTENDED_BEGIN(Name,name,parent,flags) \ + \ + static void name##_init (Name *self); \ + static void name##_class_init (Name##Class *klass); \ + static gpointer name##_parent_class = NULL; \ + static gint Name##_private_offset; \ + \ + static void \ + name##_class_intern_init (gpointer klass) \ + { \ + name##_parent_class = g_type_class_peek_parent (klass); \ + name##_class_init ((Name##Class*) klass); \ + } \ + \ + static inline gpointer \ + name##_get_instance_private (Name *self) \ + { \ + return (G_STRUCT_MEMBER_P (self, Name ##_private_offset)); \ + } \ + \ + GType \ + name##_get_gtype (void) \ + { \ + static volatile gsize type_id__volatile = 0; \ + if (g_once_init_enter (&type_id__volatile)) \ + { \ + GType fundamental_type_id = \ + g_type_register_static_simple (parent, \ + g_intern_static_string (#Name), \ + sizeof (Name##Class), \ + (GClassInitFunc) name##_class_intern_init, \ + sizeof (Name), \ + (GInstanceInitFunc) name##_init, \ + (GTypeFlags) flags); \ + { /* custom code follows */ + +#define _COGL_GTYPE_DEFINE_TYPE_EXTENDED_END() \ + /* following custom code */ \ + } \ + g_once_init_leave (&type_id__volatile, \ + fundamental_type_id); \ + } \ + return type_id__volatile; \ + } /* closes name##_get_type() */ + + +#define COGL_GTYPE_DEFINE_CLASS(Name,name,...) \ + typedef struct _Cogl##Name##Class Cogl##Name##Class; \ + struct _Cogl##Name##Class { \ + CoglObjectClass parent_class; \ + }; \ + _COGL_GTYPE_DEFINE_TYPE_EXTENDED_BEGIN(Cogl##Name, \ + cogl_##name, \ + cogl_object_get_gtype(), \ + 0) \ + {__VA_ARGS__;} \ + _COGL_GTYPE_DEFINE_TYPE_EXTENDED_END() \ + static void \ + cogl_##name##_init (Cogl##Name *instance) \ + { \ + } \ + static void \ + cogl_##name##_class_init (Cogl##Name##Class *klass) \ + { \ + } + +void _cogl_gtype_object_init_value (GValue *value); +void _cogl_gtype_object_free_value (GValue *value); +void _cogl_gtype_object_copy_value (const GValue *src, + GValue *dst); +gpointer _cogl_gtype_object_peek_pointer (const GValue *value); +gchar *_cogl_gtype_object_collect_value (GValue *value, + guint n_collect_values, + GTypeCValue *collect_values, + guint collect_flags); +gchar *_cogl_gtype_object_lcopy_value (const GValue *value, + guint n_collect_values, + GTypeCValue *collect_values, + guint collect_flags); + +void _cogl_gtype_object_class_base_init (CoglObjectClass *klass); +void _cogl_gtype_object_class_base_finalize (CoglObjectClass *klass); +void _cogl_gtype_object_class_init (CoglObjectClass *klass); +void _cogl_gtype_object_init (CoglObject *object); + +void cogl_object_value_set_object (GValue *value, + gpointer object); +gpointer cogl_object_value_get_object (const GValue *value); + +void _cogl_gtype_dummy_iface_init (gpointer iface); + +#endif /* __COGL_GTYPE_PRIVATE_H__ */ diff --git a/cogl/cogl/cogl-gtype.c b/cogl/cogl/cogl-gtype.c new file mode 100644 index 0000000..314d8e4 --- /dev/null +++ b/cogl/cogl/cogl-gtype.c @@ -0,0 +1,153 @@ +#include "cogl-gtype-private.h" + +#include + +void +_cogl_gtype_object_init_value (GValue *value) +{ + value->data[0].v_pointer = NULL; +} + +void +_cogl_gtype_object_free_value (GValue *value) +{ + if (value->data[0].v_pointer != NULL) + cogl_object_unref (value->data[0].v_pointer); +} + +void +_cogl_gtype_object_copy_value (const GValue *src, + GValue *dst) +{ + if (src->data[0].v_pointer != NULL) + dst->data[0].v_pointer = cogl_object_ref (src->data[0].v_pointer); + else + dst->data[0].v_pointer = NULL; +} + +gpointer +_cogl_gtype_object_peek_pointer (const GValue *value) +{ + return value->data[0].v_pointer; +} + +gchar * +_cogl_gtype_object_collect_value (GValue *value, + guint n_collect_values, + GTypeCValue *collect_values, + guint collect_flags) +{ + CoglObject *object; + + object = collect_values[0].v_pointer; + + if (object == NULL) + { + value->data[0].v_pointer = NULL; + return NULL; + } + + if (object->klass == NULL) + return g_strconcat ("invalid unclassed CoglObject pointer for " + "value type '", + G_VALUE_TYPE_NAME (value), + "'", + NULL); + + value->data[0].v_pointer = cogl_object_ref (object); + + return NULL; +} + +gchar * +_cogl_gtype_object_lcopy_value (const GValue *value, + guint n_collect_values, + GTypeCValue *collect_values, + guint collect_flags) +{ + CoglObject **object_p = collect_values[0].v_pointer; + + if (object_p == NULL) + return g_strconcat ("value location for '", + G_VALUE_TYPE_NAME (value), + "' passed as NULL", + NULL); + + if (value->data[0].v_pointer == NULL) + *object_p = NULL; + else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) + *object_p = value->data[0].v_pointer; + else + *object_p = cogl_object_ref (value->data[0].v_pointer); + + return NULL; +} + +void +_cogl_gtype_object_class_base_init (CoglObjectClass *klass) +{ +} + +void +_cogl_gtype_object_class_base_finalize (CoglObjectClass *klass) +{ +} + +void +_cogl_gtype_object_class_init (CoglObjectClass *klass) +{ +} + +void +_cogl_gtype_object_init (CoglObject *object) +{ +} + +void +_cogl_gtype_dummy_iface_init (gpointer iface) +{ +} + +/** + * cogl_object_value_set_object: + * @value: a #GValue initialized with %COGL_GTYPE_TYPE_OBJECT + * @object: (type Cogl.GtypeObject) (allow-none): a #CoglGtypeObject, or %NULL + * + * Sets the contents of a #GValue initialized with %COGL_GTYPE_TYPE_OBJECT. + * + */ +void +cogl_object_value_set_object (GValue *value, + gpointer object) +{ + CoglObject *old_object; + + old_object = value->data[0].v_pointer; + + if (object != NULL) + { + /* take over ownership */ + value->data[0].v_pointer = object; + } + else + value->data[0].v_pointer = NULL; + + if (old_object != NULL) + cogl_object_unref (old_object); +} + +/** + * cogl_object_value_get_object: + * @value: a #GValue initialized with %COGL_GTYPE_TYPE_OBJECT + * + * Retrieves a pointer to the #CoglGtypeObject contained inside + * the passed #GValue. + * + * Return value: (transfer none) (type Cogl.GtypeObject): a pointer to + * a #CoglGtypeObject, or %NULL + */ +gpointer +cogl_object_value_get_object (const GValue *value) +{ + return value->data[0].v_pointer; +} diff --git a/cogl/cogl/cogl-i18n-private.h b/cogl/cogl/cogl-i18n-private.h new file mode 100644 index 0000000..94202f7 --- /dev/null +++ b/cogl/cogl/cogl-i18n-private.h @@ -0,0 +1,39 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef _COGL_I18N_PRIVATE_H_ +#define _COGL_I18N_PRIVATE_H_ + +#include + +#define _(X) X +#define N_(X) X + +#endif /* _COGL_I18N_PRIVATE_H_ */ diff --git a/cogl/cogl/cogl-index-buffer-private.h b/cogl/cogl/cogl-index-buffer-private.h new file mode 100644 index 0000000..d9596cd --- /dev/null +++ b/cogl/cogl/cogl-index-buffer-private.h @@ -0,0 +1,44 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_INDEX_BUFFER_PRIVATE_H +#define __COGL_INDEX_BUFFER_PRIVATE_H + +#include "cogl-buffer-private.h" + +struct _CoglIndexBuffer +{ + CoglBuffer _parent; +}; + +#endif /* __COGL_INDEX_BUFFER_PRIVATE_H */ diff --git a/cogl/cogl/cogl-index-buffer.c b/cogl/cogl/cogl-index-buffer.c new file mode 100644 index 0000000..1f9b59d --- /dev/null +++ b/cogl/cogl/cogl-index-buffer.c @@ -0,0 +1,112 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-object-private.h" +#include "cogl-indices.h" +#include "cogl-indices-private.h" +#include "cogl-context-private.h" +#include "cogl-gtype-private.h" + +static void _cogl_index_buffer_free (CoglIndexBuffer *indices); + +COGL_BUFFER_DEFINE (IndexBuffer, index_buffer); +COGL_GTYPE_DEFINE_CLASS (IndexBuffer, index_buffer); + +/* XXX: Unlike the wiki design this just takes a size. A single + * indices buffer should be able to contain multiple ranges of indices + * which the wiki design doesn't currently consider. */ +CoglIndexBuffer * +cogl_index_buffer_new (CoglContext *context, size_t bytes) +{ + CoglIndexBuffer *indices = g_slice_new (CoglIndexBuffer); + + /* parent's constructor */ + _cogl_buffer_initialize (COGL_BUFFER (indices), + context, + bytes, + COGL_BUFFER_BIND_TARGET_INDEX_BUFFER, + COGL_BUFFER_USAGE_HINT_INDEX_BUFFER, + COGL_BUFFER_UPDATE_HINT_STATIC); + + return _cogl_index_buffer_object_new (indices); +} + +static void +_cogl_index_buffer_free (CoglIndexBuffer *indices) +{ + /* parent's destructor */ + _cogl_buffer_fini (COGL_BUFFER (indices)); + + g_slice_free (CoglIndexBuffer, indices); +} + +/* XXX: do we want a convenience function like this as an alternative + * to using cogl_buffer_set_data? The advantage of this is that we can + * track meta data such as the indices type and max_index_value for a + * range as part of the indices buffer. If we just leave people to use + * cogl_buffer_set_data then we either need a way to specify the type + * and max index value at draw time or we'll want a separate way to + * declare the type and max value for a range after uploading the + * data. + * + * XXX: I think in the end it'll be that CoglIndices are to + * CoglIndexBuffers as CoglAttributes are to CoglAttributeBuffers. I.e + * a CoglIndexBuffer is a lite subclass of CoglBuffer that simply + * implies that the buffer will later be bound as indices but doesn't + * track more detailed meta data. CoglIndices build on a + * CoglIndexBuffer and define the type and max_index_value for some + * sub-range of a CoglIndexBuffer. + */ +#if 0 +void +cogl_index_buffer_set_data (CoglIndexBuffer *indices, + CoglIndicesType type, + int max_index_value, + size_t write_offset, + void *user_indices, + int n_indices) +{ + GList *l; + + for (l = indices->ranges; l; l = l->next) + { + + } + cogl_buffer_set +} +#endif + diff --git a/cogl/cogl/cogl-index-buffer.h b/cogl/cogl/cogl-index-buffer.h new file mode 100644 index 0000000..94d2c8d --- /dev/null +++ b/cogl/cogl/cogl-index-buffer.h @@ -0,0 +1,103 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_INDEX_BUFFER_H__ +#define __COGL_INDEX_BUFFER_H__ + +#include + +#include + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-index-buffer + * @short_description: Functions for creating and manipulating vertex + * indices. + * + * FIXME + */ + +#define COGL_INDEX_BUFFER(buffer) ((CoglIndexBuffer*) buffer) + +typedef struct _CoglIndexBuffer CoglIndexBuffer; + +/** + * cogl_index_buffer_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_index_buffer_get_gtype (void); + +/** + * cogl_index_buffer_new: + * @context: A #CoglContext + * @bytes: The number of bytes to allocate for vertex attribute data. + * + * Declares a new #CoglIndexBuffer of @size bytes to contain vertex + * indices. Once declared, data can be set using + * cogl_buffer_set_data() or by mapping it into the application's + * address space using cogl_buffer_map(). + * + * Return value: (transfer full): A newly allocated #CoglIndexBuffer + * + * Since: 1.4 + * Stability: Unstable + */ +CoglIndexBuffer * +cogl_index_buffer_new (CoglContext *context, + size_t bytes); + +/** + * cogl_is_index_buffer: + * @object: A #CoglObject + * + * Gets whether the given object references a #CoglIndexBuffer. + * + * Returns: %TRUE if the @object references a #CoglIndexBuffer, + * %FALSE otherwise + * + * Since: 1.4 + * Stability: Unstable + */ +CoglBool +cogl_is_index_buffer (void *object); + +COGL_END_DECLS + +#endif /* __COGL_INDEX_BUFFER_H__ */ + diff --git a/cogl/cogl/cogl-indices-private.h b/cogl/cogl/cogl-indices-private.h new file mode 100644 index 0000000..3d58916 --- /dev/null +++ b/cogl/cogl/cogl-indices-private.h @@ -0,0 +1,60 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_INDICES_PRIVATE_H +#define __COGL_INDICES_PRIVATE_H + +#include "cogl-object-private.h" +#include "cogl-index-buffer-private.h" +#include "cogl-types.h" + +struct _CoglIndices +{ + CoglObject _parent; + + CoglIndexBuffer *buffer; + size_t offset; + + CoglIndicesType type; + + int immutable_ref; +}; + +CoglIndices * +_cogl_indices_immutable_ref (CoglIndices *indices); + +void +_cogl_indices_immutable_unref (CoglIndices *indices); + +#endif /* __COGL_INDICES_PRIVATE_H */ + diff --git a/cogl/cogl/cogl-indices.c b/cogl/cogl/cogl-indices.c new file mode 100644 index 0000000..8ffcdc6 --- /dev/null +++ b/cogl/cogl/cogl-indices.c @@ -0,0 +1,271 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + * Neil Roberts + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-util.h" +#include "cogl-object-private.h" +#include "cogl-context-private.h" +#include "cogl-indices.h" +#include "cogl-indices-private.h" +#include "cogl-index-buffer.h" +#include "cogl-gtype-private.h" + +#include + +static void _cogl_indices_free (CoglIndices *indices); + +COGL_OBJECT_DEFINE (Indices, indices); +COGL_GTYPE_DEFINE_CLASS (Indices, indices); + +static size_t +sizeof_indices_type (CoglIndicesType type) +{ + switch (type) + { + case COGL_INDICES_TYPE_UNSIGNED_BYTE: + return 1; + case COGL_INDICES_TYPE_UNSIGNED_SHORT: + return 2; + case COGL_INDICES_TYPE_UNSIGNED_INT: + return 4; + } + g_return_val_if_reached (0); +} + +CoglIndices * +cogl_indices_new_for_buffer (CoglIndicesType type, + CoglIndexBuffer *buffer, + size_t offset) +{ + CoglIndices *indices = g_slice_new (CoglIndices); + + indices->buffer = cogl_object_ref (buffer); + indices->offset = offset; + + indices->type = type; + + indices->immutable_ref = 0; + + return _cogl_indices_object_new (indices); +} + +CoglIndices * +cogl_indices_new (CoglContext *context, + CoglIndicesType type, + const void *indices_data, + int n_indices) +{ + size_t buffer_bytes = sizeof_indices_type (type) * n_indices; + CoglIndexBuffer *index_buffer = cogl_index_buffer_new (context, buffer_bytes); + CoglBuffer *buffer = COGL_BUFFER (index_buffer); + CoglIndices *indices; + CoglError *ignore_error = NULL; + + _cogl_buffer_set_data (buffer, + 0, + indices_data, + buffer_bytes, + &ignore_error); + if (ignore_error) + { + cogl_error_free (ignore_error); + cogl_object_unref (index_buffer); + return NULL; + } + + indices = cogl_indices_new_for_buffer (type, index_buffer, 0); + cogl_object_unref (index_buffer); + + return indices; +} + +CoglIndexBuffer * +cogl_indices_get_buffer (CoglIndices *indices) +{ + return indices->buffer; +} + +CoglIndicesType +cogl_indices_get_type (CoglIndices *indices) +{ + _COGL_RETURN_VAL_IF_FAIL (cogl_is_indices (indices), + COGL_INDICES_TYPE_UNSIGNED_BYTE); + return indices->type; +} + +size_t +cogl_indices_get_offset (CoglIndices *indices) +{ + _COGL_RETURN_VAL_IF_FAIL (cogl_is_indices (indices), 0); + + return indices->offset; +} + +static void +warn_about_midscene_changes (void) +{ + static CoglBool seen = FALSE; + if (!seen) + { + g_warning ("Mid-scene modification of indices has " + "undefined results\n"); + seen = TRUE; + } +} + +void +cogl_indices_set_offset (CoglIndices *indices, + size_t offset) +{ + _COGL_RETURN_IF_FAIL (cogl_is_indices (indices)); + + if (G_UNLIKELY (indices->immutable_ref)) + warn_about_midscene_changes (); + + indices->offset = offset; +} + +static void +_cogl_indices_free (CoglIndices *indices) +{ + cogl_object_unref (indices->buffer); + g_slice_free (CoglIndices, indices); +} + +CoglIndices * +_cogl_indices_immutable_ref (CoglIndices *indices) +{ + _COGL_RETURN_VAL_IF_FAIL (cogl_is_indices (indices), NULL); + + indices->immutable_ref++; + _cogl_buffer_immutable_ref (COGL_BUFFER (indices->buffer)); + return indices; +} + +void +_cogl_indices_immutable_unref (CoglIndices *indices) +{ + _COGL_RETURN_IF_FAIL (cogl_is_indices (indices)); + _COGL_RETURN_IF_FAIL (indices->immutable_ref > 0); + + indices->immutable_ref--; + _cogl_buffer_immutable_unref (COGL_BUFFER (indices->buffer)); +} + +CoglIndices * +cogl_get_rectangle_indices (CoglContext *ctx, int n_rectangles) +{ + int n_indices = n_rectangles * 6; + + /* Check if the largest index required will fit in a byte array... */ + if (n_indices <= 256 / 4 * 6) + { + /* Generate the byte array if we haven't already */ + if (ctx->rectangle_byte_indices == NULL) + { + uint8_t *byte_array = g_malloc (256 / 4 * 6 * sizeof (uint8_t)); + uint8_t *p = byte_array; + int i, vert_num = 0; + + for (i = 0; i < 256 / 4; i++) + { + *(p++) = vert_num + 0; + *(p++) = vert_num + 1; + *(p++) = vert_num + 2; + *(p++) = vert_num + 0; + *(p++) = vert_num + 2; + *(p++) = vert_num + 3; + vert_num += 4; + } + + ctx->rectangle_byte_indices + = cogl_indices_new (ctx, + COGL_INDICES_TYPE_UNSIGNED_BYTE, + byte_array, + 256 / 4 * 6); + + g_free (byte_array); + } + + return ctx->rectangle_byte_indices; + } + else + { + if (ctx->rectangle_short_indices_len < n_indices) + { + uint16_t *short_array; + uint16_t *p; + int i, vert_num = 0; + + if (ctx->rectangle_short_indices != NULL) + cogl_object_unref (ctx->rectangle_short_indices); + /* Pick a power of two >= MAX (512, n_indices) */ + if (ctx->rectangle_short_indices_len == 0) + ctx->rectangle_short_indices_len = 512; + while (ctx->rectangle_short_indices_len < n_indices) + ctx->rectangle_short_indices_len *= 2; + + /* Over-allocate to generate a whole number of quads */ + p = short_array = g_malloc ((ctx->rectangle_short_indices_len + + 5) / 6 * 6 + * sizeof (uint16_t)); + + /* Fill in the complete quads */ + for (i = 0; i < ctx->rectangle_short_indices_len; i += 6) + { + *(p++) = vert_num + 0; + *(p++) = vert_num + 1; + *(p++) = vert_num + 2; + *(p++) = vert_num + 0; + *(p++) = vert_num + 2; + *(p++) = vert_num + 3; + vert_num += 4; + } + + ctx->rectangle_short_indices + = cogl_indices_new (ctx, + COGL_INDICES_TYPE_UNSIGNED_SHORT, + short_array, + ctx->rectangle_short_indices_len); + + g_free (short_array); + } + + return ctx->rectangle_short_indices; + } +} + diff --git a/cogl/cogl/cogl-indices.h b/cogl/cogl/cogl-indices.h new file mode 100644 index 0000000..9247f40 --- /dev/null +++ b/cogl/cogl/cogl-indices.h @@ -0,0 +1,161 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_INDICES_H__ +#define __COGL_INDICES_H__ + +/* We forward declare the CoglIndices type here to avoid some circular + * dependency issues with the following headers. + */ +typedef struct _CoglIndices CoglIndices; + +#include + +#include + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-indices + * @short_description: Describe vertex indices stored in a #CoglIndexBuffer. + * + * Indices allow you to avoid duplicating vertices in your vertex data + * by virtualizing your data and instead providing a sequence of index + * values that tell the GPU which data should be used for each vertex. + * + * If the GPU is given a sequence of indices it doesn't simply walk + * through each vertex of your data in order it will instead walk + * through the indices which can provide random access to the + * underlying data. + * + * Since it's very common to have duplicate vertices when describing a + * shape as a list of triangles it can often be a significant space + * saving to describe geometry using indices. Reducing the size of + * your models can make it cheaper to map them into the GPU by + * reducing the demand on memory bandwidth and may help to make better + * use of your GPUs internal vertex caching. + * + * For example, to describe a quadrilateral as 2 triangles for the GPU + * you could either provide data with 6 vertices or instead with + * indices you can provide vertex data for just 4 vertices and an + * index buffer that specfies the 6 vertices by indexing the shared + * vertices multiple times. + * + * |[ + * CoglVertex2f quad_vertices[] = { + * {x0, y0}, //0 = top left + * {x1, y1}, //1 = bottom left + * {x2, y2}, //2 = bottom right + * {x3, y3}, //3 = top right + * }; + * //tell the gpu how to interpret the quad as 2 triangles... + * unsigned char indices[] = {0, 1, 2, 0, 2, 3}; + * ]| + * + * Even in the above illustration we see a saving of 10bytes for one + * quad compared to having data for 6 vertices and no indices but if + * you need to draw 100s or 1000s of quads then its really quite + * significant. + * + * Something else to consider is that often indices can be defined + * once and remain static while the vertex data may change for + * animations perhaps. That means you may be able to ignore the + * negligable cost of mapping your indices into the GPU if they don't + * ever change. + * + * The above illustration is actually a good example of static indices + * because it's really common that developers have quad mesh data that + * they need to display and we know exactly what that indices array + * needs to look like depending on the number of quads that need to be + * drawn. It doesn't matter how the quads might be animated and + * changed the indices will remain the same. Cogl even has a utility + * (cogl_get_rectangle_indices()) to get access to re-useable indices + * for drawing quads as above. + */ + +/** + * cogl_indices_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_indices_get_gtype (void); + +CoglIndices * +cogl_indices_new (CoglContext *context, + CoglIndicesType type, + const void *indices_data, + int n_indices); + +CoglIndices * +cogl_indices_new_for_buffer (CoglIndicesType type, + CoglIndexBuffer *buffer, + size_t offset); + +CoglIndexBuffer * +cogl_indices_get_buffer (CoglIndices *indices); + +CoglIndicesType +cogl_indices_get_type (CoglIndices *indices); + +size_t +cogl_indices_get_offset (CoglIndices *indices); + +void +cogl_indices_set_offset (CoglIndices *indices, + size_t offset); + +CoglIndices * +cogl_get_rectangle_indices (CoglContext *context, int n_rectangles); + +/** + * cogl_is_indices: + * @object: A #CoglObject pointer + * + * Gets whether the given object references a #CoglIndices. + * + * Return value: %TRUE if the object references a #CoglIndices + * and %FALSE otherwise. + * Since: 1.10 + * Stability: unstable + */ +CoglBool +cogl_is_indices (void *object); + +COGL_END_DECLS + +#endif /* __COGL_INDICES_H__ */ + diff --git a/cogl/cogl/cogl-journal-private.h b/cogl/cogl/cogl-journal-private.h new file mode 100644 index 0000000..8211359 --- /dev/null +++ b/cogl/cogl/cogl-journal-private.h @@ -0,0 +1,121 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_JOURNAL_PRIVATE_H +#define __COGL_JOURNAL_PRIVATE_H + +#include "cogl-texture.h" +#include "cogl-object-private.h" +#include "cogl-clip-stack.h" +#include "cogl-fence-private.h" + +#define COGL_JOURNAL_VBO_POOL_SIZE 8 + +typedef struct _CoglJournal +{ + CoglObject _parent; + + /* A pointer the framebuffer that is using this journal. This is + only valid when the journal is not empty. It *does* take a + reference on the framebuffer. Although this creates a circular + reference, the framebuffer has special code to handle the case + where the journal is the only thing holding a reference and it + will cause the journal to flush */ + CoglFramebuffer *framebuffer; + + GArray *entries; + GArray *vertices; + size_t needed_vbo_len; + + /* A pool of attribute buffers is used so that we can avoid repeatedly + reallocating buffers. Only one of these buffers at a time will be + used by Cogl but we keep more than one alive anyway in case the + GL driver is internally using the buffer and it would have to + allocate a new one when we start writing to it */ + CoglAttributeBuffer *vbo_pool[COGL_JOURNAL_VBO_POOL_SIZE]; + /* The next vbo to use from the pool. We just cycle through them in + order */ + unsigned int next_vbo_in_pool; + + int fast_read_pixel_count; + + CoglList pending_fences; + +} CoglJournal; + +/* To improve batching of geometry when submitting vertices to OpenGL we + * log the texture rectangles we want to draw to a journal, so when we + * later flush the journal we aim to batch data, and gl draw calls. */ +typedef struct _CoglJournalEntry +{ + CoglPipeline *pipeline; + CoglMatrixEntry *modelview_entry; + CoglClipStack *clip_stack; + /* Offset into ctx->logged_vertices */ + size_t array_offset; + int n_layers; +} CoglJournalEntry; + +CoglJournal * +_cogl_journal_new (CoglFramebuffer *framebuffer); + +void +_cogl_journal_log_quad (CoglJournal *journal, + const float *position, + CoglPipeline *pipeline, + int n_layers, + CoglTexture *layer0_override_texture, + const float *tex_coords, + unsigned int tex_coords_len); + +void +_cogl_journal_flush (CoglJournal *journal); + +void +_cogl_journal_discard (CoglJournal *journal); + +CoglBool +_cogl_journal_all_entries_within_bounds (CoglJournal *journal, + float clip_x0, + float clip_y0, + float clip_x1, + float clip_y1); + +CoglBool +_cogl_journal_try_read_pixel (CoglJournal *journal, + int x, + int y, + CoglBitmap *bitmap, + CoglBool *found_intersection); + +CoglBool +_cogl_is_journal (void *object); + +#endif /* __COGL_JOURNAL_PRIVATE_H */ diff --git a/cogl/cogl/cogl-journal.c b/cogl/cogl/cogl-journal.c new file mode 100644 index 0000000..9f11e8b --- /dev/null +++ b/cogl/cogl/cogl-journal.c @@ -0,0 +1,1853 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-debug.h" +#include "cogl-context-private.h" +#include "cogl-journal-private.h" +#include "cogl-texture-private.h" +#include "cogl-pipeline-private.h" +#include "cogl-pipeline-opengl-private.h" +#include "cogl-vertex-buffer-private.h" +#include "cogl-framebuffer-private.h" +#include "cogl-profile.h" +#include "cogl-attribute-private.h" +#include "cogl-point-in-poly-private.h" +#include "cogl-private.h" +#include "cogl1-context.h" + +#include +#include +#include + +/* XXX NB: + * The data logged in logged_vertices is formatted as follows: + * + * Per entry: + * 4 RGBA GLubytes for the color + * 2 floats for the top left position + * 2 * n_layers floats for the top left texture coordinates + * 2 floats for the bottom right position + * 2 * n_layers floats for the bottom right texture coordinates + */ +#define GET_JOURNAL_ARRAY_STRIDE_FOR_N_LAYERS(N_LAYERS) \ + (N_LAYERS * 2 + 2) + +/* XXX NB: + * Once in the vertex array, the journal's vertex data is arranged as follows: + * 4 vertices per quad: + * 2 or 3 GLfloats per position (3 when doing software transforms) + * 4 RGBA GLubytes, + * 2 GLfloats per tex coord * n_layers + * + * Where n_layers corresponds to the number of pipeline layers enabled + * + * To avoid frequent changes in the stride of our vertex data we always pad + * n_layers to be >= 2 + * + * There will be four vertices per quad in the vertex array + * + * When we are transforming quads in software we need to also track the z + * coordinate of transformed vertices. + * + * So for a given number of layers this gets the stride in 32bit words: + */ +#define SW_TRANSFORM (!(COGL_DEBUG_ENABLED \ + (COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM))) +#define POS_STRIDE (SW_TRANSFORM ? 3 : 2) /* number of 32bit words */ +#define N_POS_COMPONENTS POS_STRIDE +#define COLOR_STRIDE 1 /* number of 32bit words */ +#define TEX_STRIDE 2 /* number of 32bit words */ +#define MIN_LAYER_PADING 2 +#define GET_JOURNAL_VB_STRIDE_FOR_N_LAYERS(N_LAYERS) \ + (POS_STRIDE + COLOR_STRIDE + \ + TEX_STRIDE * (N_LAYERS < MIN_LAYER_PADING ? MIN_LAYER_PADING : N_LAYERS)) + +/* If a batch is longer than this threshold then we'll assume it's not + worth doing software clipping and it's cheaper to program the GPU + to do the clip */ +#define COGL_JOURNAL_HARDWARE_CLIP_THRESHOLD 8 + +typedef struct _CoglJournalFlushState +{ + CoglContext *ctx; + + CoglJournal *journal; + + CoglAttributeBuffer *attribute_buffer; + GArray *attributes; + int current_attribute; + + size_t stride; + size_t array_offset; + GLuint current_vertex; + + CoglIndices *indices; + size_t indices_type_size; + + CoglPipeline *pipeline; +} CoglJournalFlushState; + +typedef void (*CoglJournalBatchCallback) (CoglJournalEntry *start, + int n_entries, + void *data); +typedef CoglBool (*CoglJournalBatchTest) (CoglJournalEntry *entry0, + CoglJournalEntry *entry1); + +static void _cogl_journal_free (CoglJournal *journal); + +COGL_OBJECT_INTERNAL_DEFINE (Journal, journal); + +static void +_cogl_journal_free (CoglJournal *journal) +{ + int i; + + if (journal->entries) + g_array_free (journal->entries, TRUE); + if (journal->vertices) + g_array_free (journal->vertices, TRUE); + + for (i = 0; i < COGL_JOURNAL_VBO_POOL_SIZE; i++) + if (journal->vbo_pool[i]) + cogl_object_unref (journal->vbo_pool[i]); + + g_slice_free (CoglJournal, journal); +} + +CoglJournal * +_cogl_journal_new (CoglFramebuffer *framebuffer) +{ + CoglJournal *journal = g_slice_new0 (CoglJournal); + + /* The journal keeps a pointer back to the framebuffer because there + is effectively a 1:1 mapping between journals and framebuffers. + However, to avoid a circular reference the journal doesn't take a + reference unless it is non-empty. The framebuffer has a special + unref implementation to ensure that the journal is flushed when + the journal is the only thing keeping it alive */ + journal->framebuffer = framebuffer; + + journal->entries = g_array_new (FALSE, FALSE, sizeof (CoglJournalEntry)); + journal->vertices = g_array_new (FALSE, FALSE, sizeof (float)); + + _cogl_list_init (&journal->pending_fences); + + return _cogl_journal_object_new (journal); +} + +static void +_cogl_journal_dump_logged_quad (uint8_t *data, int n_layers) +{ + size_t stride = GET_JOURNAL_ARRAY_STRIDE_FOR_N_LAYERS (n_layers); + int i; + + g_print ("n_layers = %d; rgba=0x%02X%02X%02X%02X\n", + n_layers, data[0], data[1], data[2], data[3]); + + data += 4; + + for (i = 0; i < 2; i++) + { + float *v = (float *)data + (i * stride); + int j; + + g_print ("v%d: x = %f, y = %f", i, v[0], v[1]); + + for (j = 0; j < n_layers; j++) + { + float *t = v + 2 + TEX_STRIDE * j; + g_print (", tx%d = %f, ty%d = %f", j, t[0], j, t[1]); + } + g_print ("\n"); + } +} + +static void +_cogl_journal_dump_quad_vertices (uint8_t *data, int n_layers) +{ + size_t stride = GET_JOURNAL_VB_STRIDE_FOR_N_LAYERS (n_layers); + int i; + + g_print ("n_layers = %d; stride = %d; pos stride = %d; color stride = %d; " + "tex stride = %d; stride in bytes = %d\n", + n_layers, (int)stride, POS_STRIDE, COLOR_STRIDE, + TEX_STRIDE, (int)stride * 4); + + for (i = 0; i < 4; i++) + { + float *v = (float *)data + (i * stride); + uint8_t *c = data + (POS_STRIDE * 4) + (i * stride * 4); + int j; + + if (G_UNLIKELY (COGL_DEBUG_ENABLED + (COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM))) + g_print ("v%d: x = %f, y = %f, rgba=0x%02X%02X%02X%02X", + i, v[0], v[1], c[0], c[1], c[2], c[3]); + else + g_print ("v%d: x = %f, y = %f, z = %f, rgba=0x%02X%02X%02X%02X", + i, v[0], v[1], v[2], c[0], c[1], c[2], c[3]); + for (j = 0; j < n_layers; j++) + { + float *t = v + POS_STRIDE + COLOR_STRIDE + TEX_STRIDE * j; + g_print (", tx%d = %f, ty%d = %f", j, t[0], j, t[1]); + } + g_print ("\n"); + } +} + +static void +_cogl_journal_dump_quad_batch (uint8_t *data, int n_layers, int n_quads) +{ + size_t byte_stride = GET_JOURNAL_VB_STRIDE_FOR_N_LAYERS (n_layers) * 4; + int i; + + g_print ("_cogl_journal_dump_quad_batch: n_layers = %d, n_quads = %d\n", + n_layers, n_quads); + for (i = 0; i < n_quads; i++) + _cogl_journal_dump_quad_vertices (data + byte_stride * 2 * i, n_layers); +} + +static void +batch_and_call (CoglJournalEntry *entries, + int n_entries, + CoglJournalBatchTest can_batch_callback, + CoglJournalBatchCallback batch_callback, + void *data) +{ + int i; + int batch_len = 1; + CoglJournalEntry *batch_start = entries; + + if (n_entries < 1) + return; + + for (i = 1; i < n_entries; i++) + { + CoglJournalEntry *entry0 = &entries[i - 1]; + CoglJournalEntry *entry1 = entry0 + 1; + + if (can_batch_callback (entry0, entry1)) + { + batch_len++; + continue; + } + + batch_callback (batch_start, batch_len, data); + + batch_start = entry1; + batch_len = 1; + } + + /* The last batch... */ + batch_callback (batch_start, batch_len, data); +} + +static void +_cogl_journal_flush_modelview_and_entries (CoglJournalEntry *batch_start, + int batch_len, + void *data) +{ + CoglJournalFlushState *state = data; + CoglContext *ctx = state->ctx; + CoglFramebuffer *framebuffer = state->journal->framebuffer; + CoglAttribute **attributes; + CoglDrawFlags draw_flags = (COGL_DRAW_SKIP_JOURNAL_FLUSH | + COGL_DRAW_SKIP_PIPELINE_VALIDATION | + COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH | + COGL_DRAW_SKIP_LEGACY_STATE); + + COGL_STATIC_TIMER (time_flush_modelview_and_entries, + "flush: pipeline+entries", /* parent */ + "flush: modelview+entries", + "The time spent flushing modelview + entries", + 0 /* no application private data */); + + COGL_TIMER_START (_cogl_uprof_context, time_flush_modelview_and_entries); + + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_BATCHING))) + g_print ("BATCHING: modelview batch len = %d\n", batch_len); + + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM))) + _cogl_context_set_current_modelview_entry (ctx, + batch_start->modelview_entry); + + attributes = (CoglAttribute **)state->attributes->data; + + if (!_cogl_pipeline_get_real_blend_enabled (state->pipeline)) + draw_flags |= COGL_DRAW_COLOR_ATTRIBUTE_IS_OPAQUE; + +#ifdef HAVE_COGL_GL + if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_QUADS)) + { + /* XXX: it's rather evil that we sneak in the GL_QUADS enum here... */ + _cogl_framebuffer_draw_attributes (framebuffer, + state->pipeline, + GL_QUADS, + state->current_vertex, batch_len * 4, + attributes, + state->attributes->len, + draw_flags); + } + else +#endif /* HAVE_COGL_GL */ + { + if (batch_len > 1) + { + CoglVerticesMode mode = COGL_VERTICES_MODE_TRIANGLES; + int first_vertex = state->current_vertex * 6 / 4; + _cogl_framebuffer_draw_indexed_attributes (framebuffer, + state->pipeline, + mode, + first_vertex, + batch_len * 6, + state->indices, + attributes, + state->attributes->len, + draw_flags); + } + else + { + _cogl_framebuffer_draw_attributes (framebuffer, + state->pipeline, + COGL_VERTICES_MODE_TRIANGLE_FAN, + state->current_vertex, 4, + attributes, + state->attributes->len, + draw_flags); + } + } + + /* DEBUGGING CODE XXX: This path will cause all rectangles to be + * drawn with a coloured outline. Each batch will be rendered with + * the same color. This may e.g. help with debugging texture slicing + * issues, visually seeing what is batched and debugging blending + * issues, plus it looks quite cool. + */ + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_RECTANGLES))) + { + static CoglPipeline *outline = NULL; + uint8_t color_intensity; + int i; + CoglAttribute *loop_attributes[1]; + + if (outline == NULL) + outline = cogl_pipeline_new (ctx); + + /* The least significant three bits represent the three + components so that the order of colours goes red, green, + yellow, blue, magenta, cyan. Black and white are skipped. The + next two bits give four scales of intensity for those colours + in the order 0xff, 0xcc, 0x99, and 0x66. This gives a total + of 24 colours. If there are more than 24 batches on the stage + then it will wrap around */ + color_intensity = 0xff - 0x33 * (ctx->journal_rectangles_color >> 3); + cogl_pipeline_set_color4ub (outline, + (ctx->journal_rectangles_color & 1) ? + color_intensity : 0, + (ctx->journal_rectangles_color & 2) ? + color_intensity : 0, + (ctx->journal_rectangles_color & 4) ? + color_intensity : 0, + 0xff); + + loop_attributes[0] = attributes[0]; /* we just want the position */ + for (i = 0; i < batch_len; i++) + _cogl_framebuffer_draw_attributes (framebuffer, + outline, + COGL_VERTICES_MODE_LINE_LOOP, + 4 * i + state->current_vertex, 4, + loop_attributes, + 1, + draw_flags); + + /* Go to the next color */ + do + ctx->journal_rectangles_color = ((ctx->journal_rectangles_color + 1) & + ((1 << 5) - 1)); + /* We don't want to use black or white */ + while ((ctx->journal_rectangles_color & 0x07) == 0 + || (ctx->journal_rectangles_color & 0x07) == 0x07); + } + + state->current_vertex += (4 * batch_len); + + COGL_TIMER_STOP (_cogl_uprof_context, time_flush_modelview_and_entries); +} + +static CoglBool +compare_entry_modelviews (CoglJournalEntry *entry0, + CoglJournalEntry *entry1) +{ + /* Batch together quads with the same model view matrix */ + return entry0->modelview_entry == entry1->modelview_entry; +} + +/* At this point we have a run of quads that we know have compatible + * pipelines, but they may not all have the same modelview matrix */ +static void +_cogl_journal_flush_pipeline_and_entries (CoglJournalEntry *batch_start, + int batch_len, + void *data) +{ + CoglJournalFlushState *state = data; + COGL_STATIC_TIMER (time_flush_pipeline_entries, + "flush: texcoords+pipeline+entries", /* parent */ + "flush: pipeline+entries", + "The time spent flushing pipeline + entries", + 0 /* no application private data */); + + COGL_TIMER_START (_cogl_uprof_context, time_flush_pipeline_entries); + + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_BATCHING))) + g_print ("BATCHING: pipeline batch len = %d\n", batch_len); + + state->pipeline = batch_start->pipeline; + + /* If we haven't transformed the quads in software then we need to also break + * up batches according to changes in the modelview matrix... */ + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM))) + { + batch_and_call (batch_start, + batch_len, + compare_entry_modelviews, + _cogl_journal_flush_modelview_and_entries, + data); + } + else + _cogl_journal_flush_modelview_and_entries (batch_start, batch_len, data); + + COGL_TIMER_STOP (_cogl_uprof_context, time_flush_pipeline_entries); +} + +static CoglBool +compare_entry_pipelines (CoglJournalEntry *entry0, CoglJournalEntry *entry1) +{ + /* batch rectangles using compatible pipelines */ + + if (_cogl_pipeline_equal (entry0->pipeline, + entry1->pipeline, + (COGL_PIPELINE_STATE_ALL & + ~COGL_PIPELINE_STATE_COLOR), + COGL_PIPELINE_LAYER_STATE_ALL, + 0)) + return TRUE; + else + return FALSE; +} + +typedef struct _CreateAttributeState +{ + int current; + CoglJournalFlushState *flush_state; +} CreateAttributeState; + +static CoglBool +create_attribute_cb (CoglPipeline *pipeline, + int layer_number, + void *user_data) +{ + CreateAttributeState *state = user_data; + CoglJournalFlushState *flush_state = state->flush_state; + CoglAttribute **attribute_entry = + &g_array_index (flush_state->attributes, + CoglAttribute *, + state->current + 2); + const char *names[] = { + "cogl_tex_coord0_in", + "cogl_tex_coord1_in", + "cogl_tex_coord2_in", + "cogl_tex_coord3_in", + "cogl_tex_coord4_in", + "cogl_tex_coord5_in", + "cogl_tex_coord6_in", + "cogl_tex_coord7_in" + }; + char *name; + + /* XXX NB: + * Our journal's vertex data is arranged as follows: + * 4 vertices per quad: + * 2 or 3 floats per position (3 when doing software transforms) + * 4 RGBA bytes, + * 2 floats per tex coord * n_layers + * (though n_layers may be padded; see definition of + * GET_JOURNAL_VB_STRIDE_FOR_N_LAYERS for details) + */ + name = layer_number < 8 ? (char *)names[layer_number] : + g_strdup_printf ("cogl_tex_coord%d_in", layer_number); + + /* XXX: it may be worth having some form of static initializer for + * attributes... */ + *attribute_entry = + cogl_attribute_new (flush_state->attribute_buffer, + name, + flush_state->stride, + flush_state->array_offset + + (POS_STRIDE + COLOR_STRIDE) * 4 + + TEX_STRIDE * 4 * state->current, + 2, + COGL_ATTRIBUTE_TYPE_FLOAT); + + if (layer_number >= 8) + g_free (name); + + state->current++; + + return TRUE; +} + +/* Since the stride may not reflect the number of texture layers in use + * (due to padding) we deal with texture coordinate offsets separately + * from vertex and color offsets... */ +static void +_cogl_journal_flush_texcoord_vbo_offsets_and_entries ( + CoglJournalEntry *batch_start, + int batch_len, + void *data) +{ + CoglJournalFlushState *state = data; + CreateAttributeState create_attrib_state; + int i; + COGL_STATIC_TIMER (time_flush_texcoord_pipeline_entries, + "flush: vbo+texcoords+pipeline+entries", /* parent */ + "flush: texcoords+pipeline+entries", + "The time spent flushing texcoord offsets + pipeline " + "+ entries", + 0 /* no application private data */); + + COGL_TIMER_START (_cogl_uprof_context, time_flush_texcoord_pipeline_entries); + + /* NB: attributes 0 and 1 are position and color */ + + for (i = 2; i < state->attributes->len; i++) + cogl_object_unref (g_array_index (state->attributes, CoglAttribute *, i)); + + g_array_set_size (state->attributes, batch_start->n_layers + 2); + + create_attrib_state.current = 0; + create_attrib_state.flush_state = state; + + cogl_pipeline_foreach_layer (batch_start->pipeline, + create_attribute_cb, + &create_attrib_state); + + batch_and_call (batch_start, + batch_len, + compare_entry_pipelines, + _cogl_journal_flush_pipeline_and_entries, + data); + COGL_TIMER_STOP (_cogl_uprof_context, time_flush_texcoord_pipeline_entries); +} + +static CoglBool +compare_entry_layer_numbers (CoglJournalEntry *entry0, CoglJournalEntry *entry1) +{ + if (_cogl_pipeline_layer_numbers_equal (entry0->pipeline, entry1->pipeline)) + return TRUE; + else + return FALSE; +} + +/* At this point we know the stride has changed from the previous batch + * of journal entries */ +static void +_cogl_journal_flush_vbo_offsets_and_entries (CoglJournalEntry *batch_start, + int batch_len, + void *data) +{ + CoglJournalFlushState *state = data; + CoglContext *ctx = state->journal->framebuffer->context; + size_t stride; + int i; + CoglAttribute **attribute_entry; + COGL_STATIC_TIMER (time_flush_vbo_texcoord_pipeline_entries, + "flush: clip+vbo+texcoords+pipeline+entries", /* parent */ + "flush: vbo+texcoords+pipeline+entries", + "The time spent flushing vbo + texcoord offsets + " + "pipeline + entries", + 0 /* no application private data */); + + COGL_TIMER_START (_cogl_uprof_context, + time_flush_vbo_texcoord_pipeline_entries); + + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_BATCHING))) + g_print ("BATCHING: vbo offset batch len = %d\n", batch_len); + + /* XXX NB: + * Our journal's vertex data is arranged as follows: + * 4 vertices per quad: + * 2 or 3 GLfloats per position (3 when doing software transforms) + * 4 RGBA GLubytes, + * 2 GLfloats per tex coord * n_layers + * (though n_layers may be padded; see definition of + * GET_JOURNAL_VB_STRIDE_FOR_N_LAYERS for details) + */ + stride = GET_JOURNAL_VB_STRIDE_FOR_N_LAYERS (batch_start->n_layers); + stride *= sizeof (float); + state->stride = stride; + + for (i = 0; i < state->attributes->len; i++) + cogl_object_unref (g_array_index (state->attributes, CoglAttribute *, i)); + + g_array_set_size (state->attributes, 2); + + attribute_entry = &g_array_index (state->attributes, CoglAttribute *, 0); + *attribute_entry = cogl_attribute_new (state->attribute_buffer, + "cogl_position_in", + stride, + state->array_offset, + N_POS_COMPONENTS, + COGL_ATTRIBUTE_TYPE_FLOAT); + + attribute_entry = &g_array_index (state->attributes, CoglAttribute *, 1); + *attribute_entry = + cogl_attribute_new (state->attribute_buffer, + "cogl_color_in", + stride, + state->array_offset + (POS_STRIDE * 4), + 4, + COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE); + + if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_QUADS)) + state->indices = cogl_get_rectangle_indices (ctx, batch_len); + + /* We only create new Attributes when the stride within the + * AttributeBuffer changes. (due to a change in the number of pipeline + * layers) While the stride remains constant we walk forward through + * the above AttributeBuffer using a vertex offset passed to + * cogl_draw_attributes + */ + state->current_vertex = 0; + + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_JOURNAL)) && + cogl_has_feature (ctx, COGL_FEATURE_ID_MAP_BUFFER_FOR_READ)) + { + uint8_t *verts; + + /* Mapping a buffer for read is probably a really bad thing to + do but this will only happen during debugging so it probably + doesn't matter */ + verts = ((uint8_t *)_cogl_buffer_map (COGL_BUFFER (state->attribute_buffer), + COGL_BUFFER_ACCESS_READ, 0, + NULL) + + state->array_offset); + + _cogl_journal_dump_quad_batch (verts, + batch_start->n_layers, + batch_len); + + cogl_buffer_unmap (COGL_BUFFER (state->attribute_buffer)); + } + + batch_and_call (batch_start, + batch_len, + compare_entry_layer_numbers, + _cogl_journal_flush_texcoord_vbo_offsets_and_entries, + data); + + /* progress forward through the VBO containing all our vertices */ + state->array_offset += (stride * 4 * batch_len); + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_JOURNAL))) + g_print ("new vbo offset = %lu\n", (unsigned long)state->array_offset); + + COGL_TIMER_STOP (_cogl_uprof_context, + time_flush_vbo_texcoord_pipeline_entries); +} + +static CoglBool +compare_entry_strides (CoglJournalEntry *entry0, CoglJournalEntry *entry1) +{ + /* Currently the only thing that affects the stride for our vertex arrays + * is the number of pipeline layers. We need to update our VBO offsets + * whenever the stride changes. */ + /* TODO: We should be padding the n_layers == 1 case as if it were + * n_layers == 2 so we can reduce the need to split batches. */ + if (entry0->n_layers == entry1->n_layers || + (entry0->n_layers <= MIN_LAYER_PADING && + entry1->n_layers <= MIN_LAYER_PADING)) + return TRUE; + else + return FALSE; +} + +/* At this point we know the batch has a unique clip stack */ +static void +_cogl_journal_flush_clip_stacks_and_entries (CoglJournalEntry *batch_start, + int batch_len, + void *data) +{ + CoglJournalFlushState *state = data; + CoglFramebuffer *framebuffer = state->journal->framebuffer; + CoglContext *ctx = framebuffer->context; + CoglMatrixStack *projection_stack; + + COGL_STATIC_TIMER (time_flush_clip_stack_pipeline_entries, + "Journal Flush", /* parent */ + "flush: clip+vbo+texcoords+pipeline+entries", + "The time spent flushing clip + vbo + texcoord offsets + " + "pipeline + entries", + 0 /* no application private data */); + + COGL_TIMER_START (_cogl_uprof_context, + time_flush_clip_stack_pipeline_entries); + + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_BATCHING))) + g_print ("BATCHING: clip stack batch len = %d\n", batch_len); + + _cogl_clip_stack_flush (batch_start->clip_stack, framebuffer); + + /* XXX: Because we are manually flushing clip state here we need to + * make sure that the clip state gets updated the next time we flush + * framebuffer state by marking the current framebuffer's clip state + * as changed. */ + ctx->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_CLIP; + + /* If we have transformed all our quads at log time then we ensure + * no further model transform is applied by loading the identity + * matrix here. We need to do this after flushing the clip stack + * because the clip stack flushing code can modify the current + * modelview matrix entry */ + if (G_LIKELY (!(COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM)))) + _cogl_context_set_current_modelview_entry (ctx, &ctx->identity_entry); + + /* Setting up the clip state can sometimes also update the current + * projection matrix entry so we should update it again. This will have + * no affect if the clip code didn't modify the projection */ + projection_stack = + _cogl_framebuffer_get_projection_stack (framebuffer); + _cogl_context_set_current_projection_entry (ctx, + projection_stack->last_entry); + + batch_and_call (batch_start, + batch_len, + compare_entry_strides, + _cogl_journal_flush_vbo_offsets_and_entries, /* callback */ + data); + + COGL_TIMER_STOP (_cogl_uprof_context, + time_flush_clip_stack_pipeline_entries); +} + +typedef struct +{ + float x_1, y_1; + float x_2, y_2; +} ClipBounds; + +static CoglBool +can_software_clip_entry (CoglJournalEntry *journal_entry, + CoglJournalEntry *prev_journal_entry, + CoglClipStack *clip_stack, + ClipBounds *clip_bounds_out) +{ + CoglPipeline *pipeline = journal_entry->pipeline; + CoglClipStack *clip_entry; + int layer_num; + + clip_bounds_out->x_1 = -G_MAXFLOAT; + clip_bounds_out->y_1 = -G_MAXFLOAT; + clip_bounds_out->x_2 = G_MAXFLOAT; + clip_bounds_out->y_2 = G_MAXFLOAT; + + /* Check the pipeline is usable. We can short-cut here for + entries using the same pipeline as the previous entry */ + if (prev_journal_entry == NULL || pipeline != prev_journal_entry->pipeline) + { + /* If the pipeline has a user program then we can't reliably modify + the texture coordinates */ + if (cogl_pipeline_get_user_program (pipeline)) + return FALSE; + + /* If any of the pipeline layers have a texture matrix then we can't + reliably modify the texture coordinates */ + for (layer_num = cogl_pipeline_get_n_layers (pipeline) - 1; + layer_num >= 0; + layer_num--) + if (_cogl_pipeline_layer_has_user_matrix (pipeline, layer_num)) + return FALSE; + } + + /* Now we need to verify that each clip entry's matrix is just a + translation of the journal entry's modelview matrix. We can + also work out the bounds of the clip in modelview space using + this translation */ + for (clip_entry = clip_stack; clip_entry; clip_entry = clip_entry->parent) + { + float rect_x1, rect_y1, rect_x2, rect_y2; + CoglClipStackRect *clip_rect; + float tx, ty, tz; + CoglMatrixEntry *modelview_entry; + + clip_rect = (CoglClipStackRect *) clip_entry; + + modelview_entry = journal_entry->modelview_entry; + if (!cogl_matrix_entry_calculate_translation (clip_rect->matrix_entry, + modelview_entry, + &tx, &ty, &tz)) + return FALSE; + + if (clip_rect->x0 < clip_rect->x1) + { + rect_x1 = clip_rect->x0; + rect_x2 = clip_rect->x1; + } + else + { + rect_x1 = clip_rect->x1; + rect_x2 = clip_rect->x0; + } + if (clip_rect->y0 < clip_rect->y1) + { + rect_y1 = clip_rect->y0; + rect_y2 = clip_rect->y1; + } + else + { + rect_y1 = clip_rect->y1; + rect_y2 = clip_rect->y0; + } + + clip_bounds_out->x_1 = MAX (clip_bounds_out->x_1, rect_x1 - tx); + clip_bounds_out->y_1 = MAX (clip_bounds_out->y_1, rect_y1 - ty); + clip_bounds_out->x_2 = MIN (clip_bounds_out->x_2, rect_x2 - tx); + clip_bounds_out->y_2 = MIN (clip_bounds_out->y_2, rect_y2 - ty); + } + + if (clip_bounds_out->x_2 <= clip_bounds_out->x_1 || + clip_bounds_out->y_2 <= clip_bounds_out->y_1) + memset (clip_bounds_out, 0, sizeof (ClipBounds)); + + return TRUE; +} + +static void +software_clip_entry (CoglJournalEntry *journal_entry, + float *verts, + ClipBounds *clip_bounds) +{ + size_t stride = + GET_JOURNAL_ARRAY_STRIDE_FOR_N_LAYERS (journal_entry->n_layers); + float rx1, ry1, rx2, ry2; + float vx1, vy1, vx2, vy2; + int layer_num; + + /* Remove the clip on the entry */ + _cogl_clip_stack_unref (journal_entry->clip_stack); + journal_entry->clip_stack = NULL; + + vx1 = verts[0]; + vy1 = verts[1]; + vx2 = verts[stride]; + vy2 = verts[stride + 1]; + + if (vx1 < vx2) + { + rx1 = vx1; + rx2 = vx2; + } + else + { + rx1 = vx2; + rx2 = vx1; + } + if (vy1 < vy2) + { + ry1 = vy1; + ry2 = vy2; + } + else + { + ry1 = vy2; + ry2 = vy1; + } + + rx1 = CLAMP (rx1, clip_bounds->x_1, clip_bounds->x_2); + ry1 = CLAMP (ry1, clip_bounds->y_1, clip_bounds->y_2); + rx2 = CLAMP (rx2, clip_bounds->x_1, clip_bounds->x_2); + ry2 = CLAMP (ry2, clip_bounds->y_1, clip_bounds->y_2); + + /* Check if the rectangle intersects the clip at all */ + if (rx1 == rx2 || ry1 == ry2) + /* Will set all of the vertex data to 0 in the hope that this + will create a degenerate rectangle and the GL driver will + be able to clip it quickly */ + memset (verts, 0, sizeof (float) * stride * 2); + else + { + if (vx1 > vx2) + { + float t = rx1; + rx1 = rx2; + rx2 = t; + } + if (vy1 > vy2) + { + float t = ry1; + ry1 = ry2; + ry2 = t; + } + + verts[0] = rx1; + verts[1] = ry1; + verts[stride] = rx2; + verts[stride + 1] = ry2; + + /* Convert the rectangle coordinates to a fraction of the original + rectangle */ + rx1 = (rx1 - vx1) / (vx2 - vx1); + ry1 = (ry1 - vy1) / (vy2 - vy1); + rx2 = (rx2 - vx1) / (vx2 - vx1); + ry2 = (ry2 - vy1) / (vy2 - vy1); + + for (layer_num = 0; layer_num < journal_entry->n_layers; layer_num++) + { + float *t = verts + 2 + 2 * layer_num; + float tx1 = t[0], ty1 = t[1]; + float tx2 = t[stride], ty2 = t[stride + 1]; + t[0] = rx1 * (tx2 - tx1) + tx1; + t[1] = ry1 * (ty2 - ty1) + ty1; + t[stride] = rx2 * (tx2 - tx1) + tx1; + t[stride + 1] = ry2 * (ty2 - ty1) + ty1; + } + } +} + +static void +maybe_software_clip_entries (CoglJournalEntry *batch_start, + int batch_len, + CoglJournalFlushState *state) +{ + CoglContext *ctx; + CoglJournal *journal; + CoglClipStack *clip_stack, *clip_entry; + int entry_num; + + /* This tries to find cases where the entry is logged with a clip + but it would be faster to modify the vertex and texture + coordinates rather than flush the clip so that it can batch + better */ + + /* If the batch is reasonably long then it's worthwhile programming + the GPU to do the clip */ + if (batch_len >= COGL_JOURNAL_HARDWARE_CLIP_THRESHOLD) + return; + + clip_stack = batch_start->clip_stack; + + if (clip_stack == NULL) + return; + + /* Verify that all of the clip stack entries are a simple rectangle + clip */ + for (clip_entry = clip_stack; clip_entry; clip_entry = clip_entry->parent) + if (clip_entry->type != COGL_CLIP_STACK_RECT) + return; + + ctx = state->ctx; + journal = state->journal; + + /* This scratch buffer is used to store the translation for each + entry in the journal. We store it in a separate buffer because + it's expensive to calculate but at this point we still don't know + whether we can clip all of the entries so we don't want to do the + rest of the dependant calculations until we're sure we can. */ + if (ctx->journal_clip_bounds == NULL) + ctx->journal_clip_bounds = g_array_new (FALSE, FALSE, sizeof (ClipBounds)); + g_array_set_size (ctx->journal_clip_bounds, batch_len); + + for (entry_num = 0; entry_num < batch_len; entry_num++) + { + CoglJournalEntry *journal_entry = batch_start + entry_num; + CoglJournalEntry *prev_journal_entry = + entry_num ? batch_start + (entry_num - 1) : NULL; + ClipBounds *clip_bounds = &g_array_index (ctx->journal_clip_bounds, + ClipBounds, entry_num); + + if (!can_software_clip_entry (journal_entry, prev_journal_entry, + clip_stack, + clip_bounds)) + return; + } + + /* If we make it here then we know we can software clip the entire batch */ + + COGL_NOTE (CLIPPING, "Software clipping a batch of length %i", batch_len); + + for (entry_num = 0; entry_num < batch_len; entry_num++) + { + CoglJournalEntry *journal_entry = batch_start + entry_num; + float *verts = &g_array_index (journal->vertices, float, + journal_entry->array_offset + 1); + ClipBounds *clip_bounds = &g_array_index (ctx->journal_clip_bounds, + ClipBounds, entry_num); + + software_clip_entry (journal_entry, verts, clip_bounds); + } + + return; +} + +static void +_cogl_journal_maybe_software_clip_entries (CoglJournalEntry *batch_start, + int batch_len, + void *data) +{ + CoglJournalFlushState *state = data; + + COGL_STATIC_TIMER (time_check_software_clip, + "Journal Flush", /* parent */ + "flush: software clipping", + "Time spent software clipping", + 0 /* no application private data */); + + COGL_TIMER_START (_cogl_uprof_context, + time_check_software_clip); + + maybe_software_clip_entries (batch_start, batch_len, state); + + COGL_TIMER_STOP (_cogl_uprof_context, + time_check_software_clip); +} + +static CoglBool +compare_entry_clip_stacks (CoglJournalEntry *entry0, CoglJournalEntry *entry1) +{ + return entry0->clip_stack == entry1->clip_stack; +} + +/* Gets a new vertex array from the pool. A reference is taken on the + array so it can be treated as if it was just newly allocated */ +static CoglAttributeBuffer * +create_attribute_buffer (CoglJournal *journal, + size_t n_bytes) +{ + CoglAttributeBuffer *vbo; + CoglContext *ctx = journal->framebuffer->context; + + /* If CoglBuffers are being emulated with malloc then there's not + really any point in using the pool so we'll just allocate the + buffer directly */ + if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_VBOS)) + return cogl_attribute_buffer_new_with_size (ctx, n_bytes); + + vbo = journal->vbo_pool[journal->next_vbo_in_pool]; + + if (vbo == NULL) + { + vbo = cogl_attribute_buffer_new_with_size (ctx, n_bytes); + journal->vbo_pool[journal->next_vbo_in_pool] = vbo; + } + else if (cogl_buffer_get_size (COGL_BUFFER (vbo)) < n_bytes) + { + /* If the buffer is too small then we'll just recreate it */ + cogl_object_unref (vbo); + vbo = cogl_attribute_buffer_new_with_size (ctx, n_bytes); + journal->vbo_pool[journal->next_vbo_in_pool] = vbo; + } + + journal->next_vbo_in_pool = ((journal->next_vbo_in_pool + 1) % + COGL_JOURNAL_VBO_POOL_SIZE); + + return cogl_object_ref (vbo); +} + +static CoglAttributeBuffer * +upload_vertices (CoglJournal *journal, + const CoglJournalEntry *entries, + int n_entries, + size_t needed_vbo_len, + GArray *vertices) +{ + CoglAttributeBuffer *attribute_buffer; + CoglBuffer *buffer; + const float *vin; + float *vout; + int entry_num; + int i; + CoglMatrixEntry *last_modelview_entry = NULL; + CoglMatrix modelview; + + g_assert (needed_vbo_len); + + attribute_buffer = create_attribute_buffer (journal, needed_vbo_len * 4); + buffer = COGL_BUFFER (attribute_buffer); + cogl_buffer_set_update_hint (buffer, COGL_BUFFER_UPDATE_HINT_STATIC); + + vout = _cogl_buffer_map_range_for_fill_or_fallback (buffer, + 0, /* offset */ + needed_vbo_len * 4); + vin = &g_array_index (vertices, float, 0); + + /* Expand the number of vertices from 2 to 4 while uploading */ + for (entry_num = 0; entry_num < n_entries; entry_num++) + { + const CoglJournalEntry *entry = entries + entry_num; + size_t vb_stride = GET_JOURNAL_VB_STRIDE_FOR_N_LAYERS (entry->n_layers); + size_t array_stride = + GET_JOURNAL_ARRAY_STRIDE_FOR_N_LAYERS (entry->n_layers); + + /* Copy the color to all four of the vertices */ + for (i = 0; i < 4; i++) + memcpy (vout + vb_stride * i + POS_STRIDE, vin, 4); + vin++; + + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM))) + { + vout[vb_stride * 0] = vin[0]; + vout[vb_stride * 0 + 1] = vin[1]; + vout[vb_stride * 1] = vin[0]; + vout[vb_stride * 1 + 1] = vin[array_stride + 1]; + vout[vb_stride * 2] = vin[array_stride]; + vout[vb_stride * 2 + 1] = vin[array_stride + 1]; + vout[vb_stride * 3] = vin[array_stride]; + vout[vb_stride * 3 + 1] = vin[1]; + } + else + { + float v[8]; + + v[0] = vin[0]; + v[1] = vin[1]; + v[2] = vin[0]; + v[3] = vin[array_stride + 1]; + v[4] = vin[array_stride]; + v[5] = vin[array_stride + 1]; + v[6] = vin[array_stride]; + v[7] = vin[1]; + + if (entry->modelview_entry != last_modelview_entry) + cogl_matrix_entry_get (entry->modelview_entry, &modelview); + cogl_matrix_transform_points (&modelview, + 2, /* n_components */ + sizeof (float) * 2, /* stride_in */ + v, /* points_in */ + /* strideout */ + vb_stride * sizeof (float), + vout, /* points_out */ + 4 /* n_points */); + } + + for (i = 0; i < entry->n_layers; i++) + { + const float *tin = vin + 2; + float *tout = vout + POS_STRIDE + COLOR_STRIDE; + + tout[vb_stride * 0 + i * 2] = tin[i * 2]; + tout[vb_stride * 0 + 1 + i * 2] = tin[i * 2 + 1]; + tout[vb_stride * 1 + i * 2] = tin[i * 2]; + tout[vb_stride * 1 + 1 + i * 2] = tin[array_stride + i * 2 + 1]; + tout[vb_stride * 2 + i * 2] = tin[array_stride + i * 2]; + tout[vb_stride * 2 + 1 + i * 2] = tin[array_stride + i * 2 + 1]; + tout[vb_stride * 3 + i * 2] = tin[array_stride + i * 2]; + tout[vb_stride * 3 + 1 + i * 2] = tin[i * 2 + 1]; + } + + vin += array_stride * 2; + vout += vb_stride * 4; + } + + _cogl_buffer_unmap_for_fill_or_fallback (buffer); + + return attribute_buffer; +} + +void +_cogl_journal_discard (CoglJournal *journal) +{ + int i; + + if (journal->entries->len <= 0) + return; + + for (i = 0; i < journal->entries->len; i++) + { + CoglJournalEntry *entry = + &g_array_index (journal->entries, CoglJournalEntry, i); + _cogl_pipeline_journal_unref (entry->pipeline); + cogl_matrix_entry_unref (entry->modelview_entry); + _cogl_clip_stack_unref (entry->clip_stack); + } + + g_array_set_size (journal->entries, 0); + g_array_set_size (journal->vertices, 0); + journal->needed_vbo_len = 0; + journal->fast_read_pixel_count = 0; + + /* The journal only holds a reference to the framebuffer while the + journal is not empty */ + cogl_object_unref (journal->framebuffer); +} + +/* Note: A return value of FALSE doesn't mean 'no' it means + * 'unknown' */ +CoglBool +_cogl_journal_all_entries_within_bounds (CoglJournal *journal, + float clip_x0, + float clip_y0, + float clip_x1, + float clip_y1) +{ + CoglJournalEntry *entry = (CoglJournalEntry *)journal->entries->data; + CoglClipStack *clip_entry; + CoglClipStack *reference = NULL; + int bounds_x0; + int bounds_y0; + int bounds_x1; + int bounds_y1; + int i; + + if (journal->entries->len == 0) + return TRUE; + + /* Find the shortest clip_stack ancestry that leaves us in the + * required bounds */ + for (clip_entry = entry->clip_stack; + clip_entry; + clip_entry = clip_entry->parent) + { + _cogl_clip_stack_get_bounds (clip_entry, + &bounds_x0, &bounds_y0, + &bounds_x1, &bounds_y1); + + if (bounds_x0 >= clip_x0 && bounds_y0 >= clip_y0 && + bounds_x1 <= clip_x1 && bounds_y1 <= clip_y1) + reference = clip_entry; + else + break; + } + + if (!reference) + return FALSE; + + /* For the remaining journal entries we will only verify they share + * 'reference' as an ancestor in their clip stack since that's + * enough to know that they would be within the required bounds. + */ + for (i = 1; i < journal->entries->len; i++) + { + CoglBool found_reference = FALSE; + entry = &g_array_index (journal->entries, CoglJournalEntry, i); + + for (clip_entry = entry->clip_stack; + clip_entry; + clip_entry = clip_entry->parent) + { + if (clip_entry == reference) + { + found_reference = TRUE; + break; + } + } + + if (!found_reference) + return FALSE; + } + + return TRUE; +} + +static void +post_fences (CoglJournal *journal) +{ + CoglFenceClosure *fence, *tmp; + + _cogl_list_for_each_safe (fence, tmp, &journal->pending_fences, link) + { + _cogl_list_remove (&fence->link); + _cogl_fence_submit (fence); + } +} + +/* XXX NB: When _cogl_journal_flush() returns all state relating + * to pipelines, all glEnable flags and current matrix state + * is undefined. + */ +void +_cogl_journal_flush (CoglJournal *journal) +{ + CoglFramebuffer *framebuffer; + CoglContext *ctx; + CoglJournalFlushState state; + int i; + COGL_STATIC_TIMER (flush_timer, + "Mainloop", /* parent */ + "Journal Flush", + "The time spent flushing the Cogl journal", + 0 /* no application private data */); + COGL_STATIC_TIMER (discard_timer, + "Journal Flush", /* parent */ + "flush: discard", + "The time spent discarding the Cogl journal after a flush", + 0 /* no application private data */); + + if (journal->entries->len == 0) + { + post_fences (journal); + return; + } + + framebuffer = journal->framebuffer; + ctx = framebuffer->context; + + /* The entries in this journal may depend on images in other + * framebuffers which may require that we flush the journals + * associated with those framebuffers before we can flush + * this journal... */ + _cogl_framebuffer_flush_dependency_journals (framebuffer); + + /* Note: we start the timer after flushing dependency journals so + * that the timer isn't started recursively. */ + COGL_TIMER_START (_cogl_uprof_context, flush_timer); + + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_BATCHING))) + g_print ("BATCHING: journal len = %d\n", journal->entries->len); + + /* NB: the journal deals with flushing the modelview stack and clip + state manually */ + _cogl_framebuffer_flush_state (framebuffer, + framebuffer, + COGL_FRAMEBUFFER_STATE_ALL & + ~(COGL_FRAMEBUFFER_STATE_MODELVIEW | + COGL_FRAMEBUFFER_STATE_CLIP)); + + /* We need to mark the current modelview state of the framebuffer as + * dirty because we are going to manually replace it */ + ctx->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_MODELVIEW; + + state.ctx = ctx; + state.journal = journal; + + state.attributes = ctx->journal_flush_attributes_array; + + if (G_UNLIKELY ((COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_SOFTWARE_CLIP)) == 0)) + { + /* We do an initial walk of the journal to analyse the clip stack + batches to see if we can do software clipping. We do this as a + separate walk of the journal because we can modify entries and + this may end up joining together clip stack batches in the next + iteration. */ + batch_and_call ((CoglJournalEntry *)journal->entries->data, /* first entry */ + journal->entries->len, /* max number of entries to consider */ + compare_entry_clip_stacks, + _cogl_journal_maybe_software_clip_entries, /* callback */ + &state); /* data */ + } + + /* We upload the vertices after the clip stack pass in case it + modifies the entries */ + state.attribute_buffer = + upload_vertices (journal, + &g_array_index (journal->entries, CoglJournalEntry, 0), + journal->entries->len, + journal->needed_vbo_len, + journal->vertices); + state.array_offset = 0; + + /* batch_and_call() batches a list of journal entries according to some + * given criteria and calls a callback once for each determined batch. + * + * The process of flushing the journal is staggered to reduce the amount + * of driver/GPU state changes necessary: + * 1) We split the entries according to the clip state. + * 2) We split the entries according to the stride of the vertices: + * Each time the stride of our vertex data changes we need to call + * gl{Vertex,Color}Pointer to inform GL of new VBO offsets. + * Currently the only thing that affects the stride of our vertex data + * is the number of pipeline layers. + * 3) We split the entries explicitly by the number of pipeline layers: + * We pad our vertex data when the number of layers is < 2 so that we + * can minimize changes in stride. Each time the number of layers + * changes we need to call glTexCoordPointer to inform GL of new VBO + * offsets. + * 4) We then split according to compatible Cogl pipelines: + * This is where we flush pipeline state + * 5) Finally we split according to modelview matrix changes: + * This is when we finally tell GL to draw something. + * Note: Splitting by modelview changes is skipped when are doing the + * vertex transformation in software at log time. + */ + batch_and_call ((CoglJournalEntry *)journal->entries->data, /* first entry */ + journal->entries->len, /* max number of entries to consider */ + compare_entry_clip_stacks, + _cogl_journal_flush_clip_stacks_and_entries, /* callback */ + &state); /* data */ + + for (i = 0; i < state.attributes->len; i++) + cogl_object_unref (g_array_index (state.attributes, CoglAttribute *, i)); + g_array_set_size (state.attributes, 0); + + cogl_object_unref (state.attribute_buffer); + + COGL_TIMER_START (_cogl_uprof_context, discard_timer); + _cogl_journal_discard (journal); + COGL_TIMER_STOP (_cogl_uprof_context, discard_timer); + + post_fences (journal); + + COGL_TIMER_STOP (_cogl_uprof_context, flush_timer); +} + +static CoglBool +add_framebuffer_deps_cb (CoglPipelineLayer *layer, void *user_data) +{ + CoglFramebuffer *framebuffer = user_data; + CoglTexture *texture = _cogl_pipeline_layer_get_texture_real (layer); + const GList *l; + + if (!texture) + return TRUE; + + for (l = _cogl_texture_get_associated_framebuffers (texture); l; l = l->next) + _cogl_framebuffer_add_dependency (framebuffer, l->data); + + return TRUE; +} + +void +_cogl_journal_log_quad (CoglJournal *journal, + const float *position, + CoglPipeline *pipeline, + int n_layers, + CoglTexture *layer0_override_texture, + const float *tex_coords, + unsigned int tex_coords_len) +{ + CoglFramebuffer *framebuffer = journal->framebuffer; + size_t stride; + int next_vert; + float *v; + int i; + int next_entry; + uint32_t disable_layers; + CoglJournalEntry *entry; + CoglPipeline *final_pipeline; + CoglClipStack *clip_stack; + CoglPipelineFlushOptions flush_options; + CoglMatrixStack *modelview_stack; + COGL_STATIC_TIMER (log_timer, + "Mainloop", /* parent */ + "Journal Log", + "The time spent logging in the Cogl journal", + 0 /* no application private data */); + + COGL_TIMER_START (_cogl_uprof_context, log_timer); + + /* Adding something to the journal should mean that we are in the + * middle of the scene. Although this will also end up being set + * when the journal is actually flushed, we set it here explicitly + * so that we will know sooner */ + _cogl_framebuffer_mark_mid_scene (framebuffer); + + /* If the framebuffer was previously empty then we'll take a + reference to the current framebuffer. This reference will be + removed when the journal is flushed */ + if (journal->vertices->len == 0) + cogl_object_ref (framebuffer); + + /* The vertex data is logged into a separate array. The data needs + to be copied into a vertex array before it's given to GL so we + only store two vertices per quad and expand it to four while + uploading. */ + + /* XXX: See definition of GET_JOURNAL_ARRAY_STRIDE_FOR_N_LAYERS for details + * about how we pack our vertex data */ + stride = GET_JOURNAL_ARRAY_STRIDE_FOR_N_LAYERS (n_layers); + + next_vert = journal->vertices->len; + g_array_set_size (journal->vertices, next_vert + 2 * stride + 1); + v = &g_array_index (journal->vertices, float, next_vert); + + /* We calculate the needed size of the vbo as we go because it + depends on the number of layers in each entry and it's not easy + calculate based on the length of the logged vertices array */ + journal->needed_vbo_len += GET_JOURNAL_VB_STRIDE_FOR_N_LAYERS (n_layers) * 4; + + /* XXX: All the jumping around to fill in this strided buffer doesn't + * seem ideal. */ + + /* FIXME: This is a hacky optimization, since it will break if we + * change the definition of CoglColor: */ + _cogl_pipeline_get_colorubv (pipeline, (uint8_t *) v); + v++; + + memcpy (v, position, sizeof (float) * 2); + memcpy (v + stride, position + 2, sizeof (float) * 2); + + for (i = 0; i < n_layers; i++) + { + /* XXX: See definition of GET_JOURNAL_ARRAY_STRIDE_FOR_N_LAYERS + * for details about how we pack our vertex data */ + GLfloat *t = v + 2 + i * 2; + + memcpy (t, tex_coords + i * 4, sizeof (float) * 2); + memcpy (t + stride, tex_coords + i * 4 + 2, sizeof (float) * 2); + } + + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_JOURNAL))) + { + g_print ("Logged new quad:\n"); + v = &g_array_index (journal->vertices, float, next_vert); + _cogl_journal_dump_logged_quad ((uint8_t *)v, n_layers); + } + + next_entry = journal->entries->len; + g_array_set_size (journal->entries, next_entry + 1); + entry = &g_array_index (journal->entries, CoglJournalEntry, next_entry); + + entry->n_layers = n_layers; + entry->array_offset = next_vert; + + final_pipeline = pipeline; + + flush_options.flags = 0; + if (G_UNLIKELY (cogl_pipeline_get_n_layers (pipeline) != n_layers)) + { + disable_layers = (1 << n_layers) - 1; + disable_layers = ~disable_layers; + flush_options.disable_layers = disable_layers; + flush_options.flags |= COGL_PIPELINE_FLUSH_DISABLE_MASK; + } + if (G_UNLIKELY (layer0_override_texture)) + { + flush_options.flags |= COGL_PIPELINE_FLUSH_LAYER0_OVERRIDE; + flush_options.layer0_override_texture = layer0_override_texture; + } + + if (G_UNLIKELY (flush_options.flags)) + { + final_pipeline = cogl_pipeline_copy (pipeline); + _cogl_pipeline_apply_overrides (final_pipeline, &flush_options); + } + + entry->pipeline = _cogl_pipeline_journal_ref (final_pipeline); + + clip_stack = _cogl_framebuffer_get_clip_stack (framebuffer); + entry->clip_stack = _cogl_clip_stack_ref (clip_stack); + + if (G_UNLIKELY (final_pipeline != pipeline)) + cogl_object_unref (final_pipeline); + + modelview_stack = + _cogl_framebuffer_get_modelview_stack (framebuffer); + entry->modelview_entry = cogl_matrix_entry_ref (modelview_stack->last_entry); + + _cogl_pipeline_foreach_layer_internal (pipeline, + add_framebuffer_deps_cb, + framebuffer); + + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_BATCHING))) + _cogl_journal_flush (journal); + + COGL_TIMER_STOP (_cogl_uprof_context, log_timer); +} + +static void +entry_to_screen_polygon (CoglFramebuffer *framebuffer, + const CoglJournalEntry *entry, + float *vertices, + float *poly) +{ + size_t array_stride = + GET_JOURNAL_ARRAY_STRIDE_FOR_N_LAYERS (entry->n_layers); + CoglMatrixStack *projection_stack; + CoglMatrix projection; + CoglMatrix modelview; + int i; + float viewport[4]; + + poly[0] = vertices[0]; + poly[1] = vertices[1]; + poly[2] = 0; + poly[3] = 1; + + poly[4] = vertices[0]; + poly[5] = vertices[array_stride + 1]; + poly[6] = 0; + poly[7] = 1; + + poly[8] = vertices[array_stride]; + poly[9] = vertices[array_stride + 1]; + poly[10] = 0; + poly[11] = 1; + + poly[12] = vertices[array_stride]; + poly[13] = vertices[1]; + poly[14] = 0; + poly[15] = 1; + + /* TODO: perhaps split the following out into a more generalized + * _cogl_transform_points utility... + */ + + cogl_matrix_entry_get (entry->modelview_entry, &modelview); + cogl_matrix_transform_points (&modelview, + 2, /* n_components */ + sizeof (float) * 4, /* stride_in */ + poly, /* points_in */ + /* strideout */ + sizeof (float) * 4, + poly, /* points_out */ + 4 /* n_points */); + + projection_stack = + _cogl_framebuffer_get_projection_stack (framebuffer); + cogl_matrix_stack_get (projection_stack, &projection); + + cogl_matrix_project_points (&projection, + 3, /* n_components */ + sizeof (float) * 4, /* stride_in */ + poly, /* points_in */ + /* strideout */ + sizeof (float) * 4, + poly, /* points_out */ + 4 /* n_points */); + + cogl_framebuffer_get_viewport4fv (framebuffer, viewport); + +/* Scale from OpenGL normalized device coordinates (ranging from -1 to 1) + * to Cogl window/framebuffer coordinates (ranging from 0 to buffer-size) with + * (0,0) being top left. */ +#define VIEWPORT_TRANSFORM_X(x, vp_origin_x, vp_width) \ + ( ( ((x) + 1.0) * ((vp_width) / 2.0) ) + (vp_origin_x) ) +/* Note: for Y we first flip all coordinates around the X axis while in + * normalized device coodinates */ +#define VIEWPORT_TRANSFORM_Y(y, vp_origin_y, vp_height) \ + ( ( ((-(y)) + 1.0) * ((vp_height) / 2.0) ) + (vp_origin_y) ) + + /* Scale from normalized device coordinates (in range [-1,1]) to + * window coordinates ranging [0,window-size] ... */ + for (i = 0; i < 4; i++) + { + float w = poly[4 * i + 3]; + + /* Perform perspective division */ + poly[4 * i] /= w; + poly[4 * i + 1] /= w; + + /* Apply viewport transform */ + poly[4 * i] = VIEWPORT_TRANSFORM_X (poly[4 * i], + viewport[0], viewport[2]); + poly[4 * i + 1] = VIEWPORT_TRANSFORM_Y (poly[4 * i + 1], + viewport[1], viewport[3]); + } + +#undef VIEWPORT_TRANSFORM_X +#undef VIEWPORT_TRANSFORM_Y +} + +static CoglBool +try_checking_point_hits_entry_after_clipping (CoglFramebuffer *framebuffer, + CoglJournalEntry *entry, + float *vertices, + float x, + float y, + CoglBool *hit) +{ + CoglBool can_software_clip = TRUE; + CoglBool needs_software_clip = FALSE; + CoglClipStack *clip_entry; + + *hit = TRUE; + + /* Verify that all of the clip stack entries are simple rectangle + * clips */ + for (clip_entry = entry->clip_stack; + clip_entry; + clip_entry = clip_entry->parent) + { + if (x < clip_entry->bounds_x0 || + x >= clip_entry->bounds_x1 || + y < clip_entry->bounds_y0 || + y >= clip_entry->bounds_y1) + { + *hit = FALSE; + return TRUE; + } + + if (clip_entry->type == COGL_CLIP_STACK_WINDOW_RECT) + { + /* XXX: technically we could still run the software clip in + * this case because for our purposes we know this clip + * can be ignored now, but [can_]sofware_clip_entry() doesn't + * know this and will bail out. */ + can_software_clip = FALSE; + } + else if (clip_entry->type == COGL_CLIP_STACK_RECT) + { + CoglClipStackRect *rect_entry = (CoglClipStackRect *)entry; + + if (rect_entry->can_be_scissor == FALSE) + needs_software_clip = TRUE; + /* If can_be_scissor is TRUE then we know it's screen + * aligned and the hit test we did above has determined + * that we are inside this clip. */ + } + else + return FALSE; + } + + if (needs_software_clip) + { + ClipBounds clip_bounds; + float poly[16]; + + if (!can_software_clip) + return FALSE; + + if (!can_software_clip_entry (entry, NULL, + entry->clip_stack, &clip_bounds)) + return FALSE; + + software_clip_entry (entry, vertices, &clip_bounds); + entry_to_screen_polygon (framebuffer, entry, vertices, poly); + + *hit = _cogl_util_point_in_screen_poly (x, y, poly, sizeof (float) * 4, 4); + return TRUE; + } + + return TRUE; +} + +CoglBool +_cogl_journal_try_read_pixel (CoglJournal *journal, + int x, + int y, + CoglBitmap *bitmap, + CoglBool *found_intersection) +{ + CoglContext *ctx; + CoglPixelFormat format; + int i; + + /* XXX: this number has been plucked out of thin air, but the idea + * is that if so many pixels are being read from the same un-changed + * journal than we expect that it will be more efficient to fail + * here so we end up flushing and rendering the journal so that + * further reads can directly read from the framebuffer. There will + * be a bit more lag to flush the render but if there are going to + * continue being lots of arbitrary single pixel reads they will end + * up faster in the end. */ + if (journal->fast_read_pixel_count > 50) + return FALSE; + + format = cogl_bitmap_get_format (bitmap); + + if (format != COGL_PIXEL_FORMAT_RGBA_8888_PRE && + format != COGL_PIXEL_FORMAT_RGBA_8888) + return FALSE; + + ctx = _cogl_bitmap_get_context (bitmap); + + *found_intersection = FALSE; + + /* NB: The most recently added journal entry is the last entry, and + * assuming this is a simple scene only comprised of opaque coloured + * rectangles with no special pipelines involved (e.g. enabling + * depth testing) then we can assume painter's algorithm for the + * entries and so our fast read-pixel just needs to walk backwards + * through the journal entries trying to intersect each entry with + * the given point of interest. */ + for (i = journal->entries->len - 1; i >= 0; i--) + { + CoglJournalEntry *entry = + &g_array_index (journal->entries, CoglJournalEntry, i); + uint8_t *color = (uint8_t *)&g_array_index (journal->vertices, float, + entry->array_offset); + float *vertices = (float *)color + 1; + float poly[16]; + CoglFramebuffer *framebuffer = journal->framebuffer; + uint8_t *pixel; + CoglError *ignore_error; + + entry_to_screen_polygon (framebuffer, entry, vertices, poly); + + if (!_cogl_util_point_in_screen_poly (x, y, poly, sizeof (float) * 4, 4)) + continue; + + if (entry->clip_stack) + { + CoglBool hit; + + if (!try_checking_point_hits_entry_after_clipping (framebuffer, + entry, + vertices, + x, y, &hit)) + return FALSE; /* hit couldn't be determined */ + + if (!hit) + continue; + } + + *found_intersection = TRUE; + + /* If we find that the rectangle the point of interest + * intersects has any state more complex than a constant opaque + * color then we bail out. */ + if (!_cogl_pipeline_equal (ctx->opaque_color_pipeline, entry->pipeline, + (COGL_PIPELINE_STATE_ALL & + ~COGL_PIPELINE_STATE_COLOR), + COGL_PIPELINE_LAYER_STATE_ALL, + 0)) + return FALSE; + + + /* we currently only care about cases where the premultiplied or + * unpremultipled colors are equivalent... */ + if (color[3] != 0xff) + return FALSE; + + pixel = _cogl_bitmap_map (bitmap, + COGL_BUFFER_ACCESS_WRITE, + COGL_BUFFER_MAP_HINT_DISCARD, + &ignore_error); + if (pixel == NULL) + { + cogl_error_free (ignore_error); + return FALSE; + } + + pixel[0] = color[0]; + pixel[1] = color[1]; + pixel[2] = color[2]; + pixel[3] = color[3]; + + _cogl_bitmap_unmap (bitmap); + + goto success; + } + +success: + journal->fast_read_pixel_count++; + return TRUE; +} diff --git a/cogl/cogl/cogl-list.c b/cogl/cogl/cogl-list.c new file mode 100644 index 0000000..08e6a24 --- /dev/null +++ b/cogl/cogl/cogl-list.c @@ -0,0 +1,94 @@ +/* + * Copyright © 2008-2011 Kristian Høgsberg + * Copyright © 2011, 2012 Intel Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* This list implementation is based on the Wayland source code */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include +#include + +#include "cogl-list.h" + +void +_cogl_list_init (CoglList *list) +{ + list->prev = list; + list->next = list; +} + +void +_cogl_list_insert (CoglList *list, CoglList *elm) +{ + elm->prev = list; + elm->next = list->next; + list->next = elm; + elm->next->prev = elm; +} + +void +_cogl_list_remove (CoglList *elm) +{ + elm->prev->next = elm->next; + elm->next->prev = elm->prev; + elm->next = NULL; + elm->prev = NULL; +} + +int +_cogl_list_length (CoglList *list) +{ + CoglList *e; + int count; + + count = 0; + e = list->next; + while (e != list) + { + e = e->next; + count++; + } + + return count; +} + +int +_cogl_list_empty (CoglList *list) +{ + return list->next == list; +} + +void +_cogl_list_insert_list (CoglList *list, + CoglList *other) +{ + if (_cogl_list_empty (other)) + return; + + other->next->prev = list; + other->prev->next = list->next; + list->next->prev = other->prev; + list->next = other->next; +} diff --git a/cogl/cogl/cogl-list.h b/cogl/cogl/cogl-list.h new file mode 100644 index 0000000..20cbec8 --- /dev/null +++ b/cogl/cogl/cogl-list.h @@ -0,0 +1,129 @@ +/* + * Copyright © 2008 Kristian Høgsberg + * Copyright © 2012, 2013 Intel Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* This list implementation is based on the Wayland source code */ + +#ifndef COGL_LIST_H +#define COGL_LIST_H + +#include + +/** + * CoglList - linked list + * + * The list head is of "CoglList" type, and must be initialized + * using cogl_list_init(). All entries in the list must be of the same + * type. The item type must have a "CoglList" member. This + * member will be initialized by cogl_list_insert(). There is no need to + * call cogl_list_init() on the individual item. To query if the list is + * empty in O(1), use cogl_list_empty(). + * + * Let's call the list reference "CoglList foo_list", the item type as + * "item_t", and the item member as "CoglList link". The following code + * + * The following code will initialize a list: + * + * cogl_list_init (foo_list); + * cogl_list_insert (foo_list, item1); Pushes item1 at the head + * cogl_list_insert (foo_list, item2); Pushes item2 at the head + * cogl_list_insert (item2, item3); Pushes item3 after item2 + * + * The list now looks like [item2, item3, item1] + * + * Will iterate the list in ascending order: + * + * item_t *item; + * cogl_list_for_each(item, foo_list, link) { + * Do_something_with_item(item); + * } + */ + +typedef struct _CoglList CoglList; + +struct _CoglList +{ + CoglList *prev; + CoglList *next; +}; + +void +_cogl_list_init (CoglList *list); + +void +_cogl_list_insert (CoglList *list, + CoglList *elm); + +void +_cogl_list_remove (CoglList *elm); + +int +_cogl_list_length (CoglList *list); + +int +_cogl_list_empty (CoglList *list); + +void +_cogl_list_insert_list (CoglList *list, + CoglList *other); + +/* This assigns to iterator first so that taking a reference to it + * later in the second step won't be an undefined operation. It + * assigns the value of list_node rather than 0 so that it is possible + * have list_node be based on the previous value of iterator. In that + * respect iterator is just used as a convenient temporary variable. + * The compiler optimises all of this down to a single subtraction by + * a constant */ +#define _cogl_list_set_iterator(list_node, iterator, member) \ + ((iterator) = (void *) (list_node), \ + (iterator) = (void *) ((char *) (iterator) - \ + (((char *) &(iterator)->member) - \ + (char *) (iterator)))) + +#define _cogl_container_of(ptr, type, member) \ + (type *) ((char *) (ptr) - offsetof (type, member)) + +#define _cogl_list_for_each(pos, head, member) \ + for (_cogl_list_set_iterator ((head)->next, pos, member); \ + &pos->member != (head); \ + _cogl_list_set_iterator (pos->member.next, pos, member)) + +#define _cogl_list_for_each_safe(pos, tmp, head, member) \ + for (_cogl_list_set_iterator ((head)->next, pos, member), \ + _cogl_list_set_iterator ((pos)->member.next, tmp, member); \ + &pos->member != (head); \ + pos = tmp, \ + _cogl_list_set_iterator (pos->member.next, tmp, member)) + +#define _cogl_list_for_each_reverse(pos, head, member) \ + for (_cogl_list_set_iterator ((head)->prev, pos, member); \ + &pos->member != (head); \ + _cogl_list_set_iterator (pos->member.prev, pos, member)) + +#define _cogl_list_for_each_reverse_safe(pos, tmp, head, member) \ + for (_cogl_list_set_iterator ((head)->prev, pos, member), \ + _cogl_list_set_iterator ((pos)->member.prev, tmp, member); \ + &pos->member != (head); \ + pos = tmp, \ + _cogl_list_set_iterator (pos->member.prev, tmp, member)) + +#endif /* COGL_LIST_H */ diff --git a/cogl/cogl/cogl-macros.h b/cogl/cogl/cogl-macros.h new file mode 100644 index 0000000..96c0659 --- /dev/null +++ b/cogl/cogl/cogl-macros.h @@ -0,0 +1,287 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_MACROS_H__ +#define __COGL_MACROS_H__ + +#include + +/* These macros are used to mark deprecated functions, and thus have + * to be exposed in a public header. + * + * They are only intended for internal use and should not be used by + * other projects. + */ +#if defined(COGL_DISABLE_DEPRECATION_WARNINGS) || defined(COGL_COMPILATION) + +#define COGL_DEPRECATED +#define COGL_DEPRECATED_FOR(f) +#define COGL_UNAVAILABLE(maj,min) + +#else /* COGL_DISABLE_DEPRECATION_WARNINGS */ + +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) +#define COGL_DEPRECATED __attribute__((__deprecated__)) +#elif defined(_MSC_VER) && (_MSC_VER >= 1300) +#define COGL_DEPRECATED __declspec(deprecated) +#else +#define COGL_DEPRECATED +#endif + +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) +#define COGL_DEPRECATED_FOR(f) __attribute__((__deprecated__("Use '" #f "' instead"))) +#elif defined(_MSC_FULL_VER) && (_MSC_FULL_VER > 140050320) +#define COGL_DEPRECATED_FOR(f) __declspec(deprecated("is deprecated. Use '" #f "' instead")) +#else +#define COGL_DEPRECATED_FOR(f) G_DEPRECATED +#endif + +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) +#define COGL_UNAVAILABLE(maj,min) __attribute__((deprecated("Not available before " #maj "." #min))) +#elif defined(_MSC_FULL_VER) && (_MSC_FULL_VER > 140050320) +#define COGL_UNAVAILABLE(maj,min) __declspec(deprecated("is not available before " #maj "." #min)) +#else +#define COGL_UNAVAILABLE(maj,min) +#endif + +#endif /* COGL_DISABLE_DEPRECATION_WARNINGS */ + +/** + * COGL_VERSION_MIN_REQUIRED: + * + * A macro that should be defined by the user prior to including the + * cogl.h header. + * + * The definition should be one of the predefined Cogl version macros, + * such as: %COGL_VERSION_1_8, %COGL_VERSION_1_10, ... + * + * This macro defines the lower bound for the Cogl API to be used. + * + * If a function has been deprecated in a newer version of Cogl, it + * is possible to use this symbol to avoid the compiler warnings without + * disabling warnings for every deprecated function. + * + * Since: 1.16 + */ +#ifndef COGL_VERSION_MIN_REQUIRED +# define COGL_VERSION_MIN_REQUIRED (COGL_VERSION_CURRENT_STABLE) +#endif + +/** + * COGL_VERSION_MAX_ALLOWED: + * + * A macro that should be define by the user prior to including the + * cogl.h header. + * + * The definition should be one of the predefined Cogl version macros, + * such as: %COGL_VERSION_1_0, %COGL_VERSION_1_2, ... + * + * This macro defines the upper bound for the Cogl API to be used. + * + * If a function has been introduced in a newer version of Cogl, it + * is possible to use this symbol to get compiler warnings when trying + * to use that function. + * + * Since: 1.16 + */ +#ifndef COGL_VERSION_MAX_ALLOWED +# if COGL_VERSION_MIN_REQUIRED > COGL_VERSION_PREVIOUS_STABLE +# define COGL_VERSION_MAX_ALLOWED COGL_VERSION_MIN_REQUIRED +# else +# define COGL_VERSION_MAX_ALLOWED COGL_VERSION_CURRENT_STABLE +# endif +#endif + +/* sanity checks */ +#if COGL_VERSION_MAX_ALLOWED < COGL_VERSION_MIN_REQUIRED +# error "COGL_VERSION_MAX_ALLOWED must be >= COGL_VERSION_MIN_REQUIRED" +#endif +#if COGL_VERSION_MIN_REQUIRED < COGL_VERSION_1_0 +# error "COGL_VERSION_MIN_REQUIRED must be >= COGL_VERSION_1_0" +#endif + +/* XXX: Every new stable minor release should add a set of macros here */ +#if COGL_VERSION_MIN_REQUIRED >= COGL_VERSION_1_0 +# define COGL_DEPRECATED_IN_1_0 COGL_DEPRECATED +# define COGL_DEPRECATED_IN_1_0_FOR(f) COGL_DEPRECATED_FOR(f) +#else +# define COGL_DEPRECATED_IN_1_0 +# define COGL_DEPRECATED_IN_1_0_FOR(f) +#endif + +#if COGL_VERSION_MAX_ALLOWED < COGL_VERSION_1_0 +# define COGL_AVAILABLE_IN_1_0 COGL_UNAVAILABLE(1, 0) +#else +# define COGL_AVAILABLE_IN_1_0 +#endif + +#if COGL_VERSION_MIN_REQUIRED >= COGL_VERSION_1_2 +# define COGL_DEPRECATED_IN_1_2 COGL_DEPRECATED +# define COGL_DEPRECATED_IN_1_2_FOR(f) COGL_DEPRECATED_FOR(f) +#else +# define COGL_DEPRECATED_IN_1_2 +# define COGL_DEPRECATED_IN_1_2_FOR(f) +#endif + +#if COGL_VERSION_MAX_ALLOWED < COGL_VERSION_1_2 +# define COGL_AVAILABLE_IN_1_2 COGL_UNAVAILABLE(1, 2) +#else +# define COGL_AVAILABLE_IN_1_2 +#endif + +#if COGL_VERSION_MIN_REQUIRED >= COGL_VERSION_1_4 +# define COGL_DEPRECATED_IN_1_4 COGL_DEPRECATED +# define COGL_DEPRECATED_IN_1_4_FOR(f) COGL_DEPRECATED_FOR(f) +#else +# define COGL_DEPRECATED_IN_1_4 +# define COGL_DEPRECATED_IN_1_4_FOR(f) +#endif + +#if COGL_VERSION_MAX_ALLOWED < COGL_VERSION_1_4 +# define COGL_AVAILABLE_IN_1_4 COGL_UNAVAILABLE(1, 4) +#else +# define COGL_AVAILABLE_IN_1_4 +#endif + +#if COGL_VERSION_MIN_REQUIRED >= COGL_VERSION_1_6 +# define COGL_DEPRECATED_IN_1_6 COGL_DEPRECATED +# define COGL_DEPRECATED_IN_1_6_FOR(f) COGL_DEPRECATED_FOR(f) +#else +# define COGL_DEPRECATED_IN_1_6 +# define COGL_DEPRECATED_IN_1_6_FOR(f) +#endif + +#if COGL_VERSION_MAX_ALLOWED < COGL_VERSION_1_6 +# define COGL_AVAILABLE_IN_1_6 COGL_UNAVAILABLE(1, 6) +#else +# define COGL_AVAILABLE_IN_1_6 +#endif + +#if COGL_VERSION_MIN_REQUIRED >= COGL_VERSION_1_8 +# define COGL_DEPRECATED_IN_1_8 COGL_DEPRECATED +# define COGL_DEPRECATED_IN_1_8_FOR(f) COGL_DEPRECATED_FOR(f) +#else +# define COGL_DEPRECATED_IN_1_8 +# define COGL_DEPRECATED_IN_1_8_FOR(f) +#endif + +#if COGL_VERSION_MAX_ALLOWED < COGL_VERSION_1_8 +# define COGL_AVAILABLE_IN_1_8 COGL_UNAVAILABLE(1, 8) +#else +# define COGL_AVAILABLE_IN_1_8 +#endif + +#if COGL_VERSION_MIN_REQUIRED >= COGL_VERSION_1_10 +# define COGL_DEPRECATED_IN_1_10 COGL_DEPRECATED +# define COGL_DEPRECATED_IN_1_10_FOR(f) COGL_DEPRECATED_FOR(f) +#else +# define COGL_DEPRECATED_IN_1_10 +# define COGL_DEPRECATED_IN_1_10_FOR(f) +#endif + +#if COGL_VERSION_MAX_ALLOWED < COGL_VERSION_1_10 +# define COGL_AVAILABLE_IN_1_10 COGL_UNAVAILABLE(1, 10) +#else +# define COGL_AVAILABLE_IN_1_10 +#endif + +#if COGL_VERSION_MIN_REQUIRED >= COGL_VERSION_1_12 +# define COGL_DEPRECATED_IN_1_12 COGL_DEPRECATED +# define COGL_DEPRECATED_IN_1_12_FOR(f) COGL_DEPRECATED_FOR(f) +#else +# define COGL_DEPRECATED_IN_1_12 +# define COGL_DEPRECATED_IN_1_12_FOR(f) +#endif + +#if COGL_VERSION_MAX_ALLOWED < COGL_VERSION_1_12 +# define COGL_AVAILABLE_IN_1_12 COGL_UNAVAILABLE(1, 12) +#else +# define COGL_AVAILABLE_IN_1_12 +#endif + +#if COGL_VERSION_MIN_REQUIRED >= COGL_VERSION_1_14 +# define COGL_DEPRECATED_IN_1_14 COGL_DEPRECATED +# define COGL_DEPRECATED_IN_1_14_FOR(f) COGL_DEPRECATED_FOR(f) +#else +# define COGL_DEPRECATED_IN_1_14 +# define COGL_DEPRECATED_IN_1_14_FOR(f) +#endif + +#if COGL_VERSION_MAX_ALLOWED < COGL_VERSION_1_14 +# define COGL_AVAILABLE_IN_1_14 COGL_UNAVAILABLE(1, 14) +#else +# define COGL_AVAILABLE_IN_1_14 +#endif + +#if COGL_VERSION_MIN_REQUIRED >= COGL_VERSION_1_16 +# define COGL_DEPRECATED_IN_1_16 COGL_DEPRECATED +# define COGL_DEPRECATED_IN_1_16_FOR(f) COGL_DEPRECATED_FOR(f) +#else +# define COGL_DEPRECATED_IN_1_16 +# define COGL_DEPRECATED_IN_1_16_FOR(f) +#endif + +#if COGL_VERSION_MAX_ALLOWED < COGL_VERSION_1_16 +# define COGL_AVAILABLE_IN_1_16 COGL_UNAVAILABLE(1, 16) +#else +# define COGL_AVAILABLE_IN_1_16 +#endif + +#if COGL_VERSION_MIN_REQUIRED >= COGL_VERSION_1_18 +# define COGL_DEPRECATED_IN_1_18 COGL_DEPRECATED +# define COGL_DEPRECATED_IN_1_18_FOR(f) COGL_DEPRECATED_FOR(f) +#else +# define COGL_DEPRECATED_IN_1_18 +# define COGL_DEPRECATED_IN_1_18_FOR(f) +#endif + +#if COGL_VERSION_MAX_ALLOWED < COGL_VERSION_1_18 +# define COGL_AVAILABLE_IN_1_18 COGL_UNAVAILABLE(1, 18) +#else +# define COGL_AVAILABLE_IN_1_18 +#endif + +#if COGL_VERSION_MIN_REQUIRED >= COGL_VERSION_1_20 +# define COGL_DEPRECATED_IN_1_20 COGL_DEPRECATED +# define COGL_DEPRECATED_IN_1_20_FOR(f) COGL_DEPRECATED_FOR(f) +#else +# define COGL_DEPRECATED_IN_1_20 +# define COGL_DEPRECATED_IN_1_20_FOR(f) +#endif + +#if COGL_VERSION_MAX_ALLOWED < COGL_VERSION_1_20 +# define COGL_AVAILABLE_IN_1_20 COGL_UNAVAILABLE(1, 18) +#else +# define COGL_AVAILABLE_IN_1_20 +#endif + +#endif /* __COGL_MACROS_H__ */ diff --git a/cogl/cogl/cogl-magazine-private.h b/cogl/cogl/cogl-magazine-private.h new file mode 100644 index 0000000..091801b --- /dev/null +++ b/cogl/cogl/cogl-magazine-private.h @@ -0,0 +1,81 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_MAGAZINE_PRIVATE_H__ +#define __COGL_MAGAZINE_PRIVATE_H__ + +#include + +#include "cogl-memory-stack-private.h" + +typedef struct _CoglMagazineChunk CoglMagazineChunk; + +struct _CoglMagazineChunk +{ + CoglMagazineChunk *next; +}; + +typedef struct _CoglMagazine +{ + size_t chunk_size; + + CoglMemoryStack *stack; + CoglMagazineChunk *head; +} CoglMagazine; + +CoglMagazine * +_cogl_magazine_new (size_t chunk_size, int initial_chunk_count); + +static inline void * +_cogl_magazine_chunk_alloc (CoglMagazine *magazine) +{ + if (G_LIKELY (magazine->head)) + { + CoglMagazineChunk *chunk = magazine->head; + magazine->head = chunk->next; + return chunk; + } + else + return _cogl_memory_stack_alloc (magazine->stack, magazine->chunk_size); +} + +static inline void +_cogl_magazine_chunk_free (CoglMagazine *magazine, void *data) +{ + CoglMagazineChunk *chunk = data; + + chunk->next = magazine->head; + magazine->head = chunk; +} + +void +_cogl_magazine_free (CoglMagazine *magazine); + +#endif /* __COGL_MAGAZINE_PRIVATE_H__ */ diff --git a/cogl/cogl/cogl-magazine.c b/cogl/cogl/cogl-magazine.c new file mode 100644 index 0000000..89c9122 --- /dev/null +++ b/cogl/cogl/cogl-magazine.c @@ -0,0 +1,84 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * CoglMagazine provides a really light weight allocator for chunks + * of memory with a pre-determined size. + * + * This allocator builds on CoglMemoryStack for making all initial + * allocations but never frees memory back to the stack. + * + * Memory chunks that haven't been allocated yet are stored in a + * singly linked, fifo, list. + * + * Allocating from a magazine is simply a question of popping an entry + * from the head of the fifo list. If no entries are available then + * instead allocate from the memory stack instead. + * + * When an entry is freed, it is put back into the fifo list for + * re-use. + * + * No attempt is ever made to shrink the amount of memory associated + * with a CoglMagazine. + * + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-memory-stack-private.h" +#include "cogl-magazine-private.h" +#include + +#define ROUND_UP_8(X) ((X + (8 - 1)) & ~(8 - 1)) + +CoglMagazine * +_cogl_magazine_new (size_t chunk_size, int initial_chunk_count) +{ + CoglMagazine *magazine = g_new0 (CoglMagazine, 1); + + chunk_size = MAX (chunk_size, sizeof (CoglMagazineChunk)); + chunk_size = ROUND_UP_8 (chunk_size); + + magazine->chunk_size = chunk_size; + magazine->stack = _cogl_memory_stack_new (chunk_size * initial_chunk_count); + magazine->head = NULL; + + return magazine; +} + +void +_cogl_magazine_free (CoglMagazine *magazine) +{ + _cogl_memory_stack_free (magazine->stack); + g_free (magazine); +} diff --git a/cogl/cogl/cogl-matrix-private.h b/cogl/cogl/cogl-matrix-private.h new file mode 100644 index 0000000..d9fc98e --- /dev/null +++ b/cogl/cogl/cogl-matrix-private.h @@ -0,0 +1,58 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_MATRIX_PRIVATE_H +#define __COGL_MATRIX_PRIVATE_H + +#include + +COGL_BEGIN_DECLS + +#define _COGL_MATRIX_DEBUG_PRINT(MATRIX) \ + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_MATRICES))) \ + { \ + g_print ("%s:\n", G_STRFUNC); \ + cogl_debug_matrix_print (MATRIX); \ + } + +void +_cogl_matrix_prefix_print (const char *prefix, const CoglMatrix *matrix); + +void +_cogl_matrix_init_from_matrix_without_inverse (CoglMatrix *matrix, + const CoglMatrix *src); + +COGL_END_DECLS + +#endif /* __COGL_MATRIX_PRIVATE_H */ + diff --git a/cogl/cogl/cogl-matrix-stack-private.h b/cogl/cogl/cogl-matrix-stack-private.h new file mode 100644 index 0000000..0d5caf8 --- /dev/null +++ b/cogl/cogl/cogl-matrix-stack-private.h @@ -0,0 +1,200 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009,2010,2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Havoc Pennington for litl + * Robert Bragg + */ + +#ifndef _COGL_MATRIX_STACK_PRIVATE_H_ +#define _COGL_MATRIX_STACK_PRIVATE_H_ + +#include "cogl-object-private.h" +#include "cogl-matrix-stack.h" +#include "cogl-context.h" +#include "cogl-framebuffer.h" + +typedef enum _CoglMatrixOp +{ + COGL_MATRIX_OP_LOAD_IDENTITY, + COGL_MATRIX_OP_TRANSLATE, + COGL_MATRIX_OP_ROTATE, + COGL_MATRIX_OP_ROTATE_QUATERNION, + COGL_MATRIX_OP_ROTATE_EULER, + COGL_MATRIX_OP_SCALE, + COGL_MATRIX_OP_MULTIPLY, + COGL_MATRIX_OP_LOAD, + COGL_MATRIX_OP_SAVE, +} CoglMatrixOp; + +struct _CoglMatrixEntry +{ + CoglMatrixEntry *parent; + CoglMatrixOp op; + unsigned int ref_count; + +#ifdef COGL_DEBUG_ENABLED + /* used for performance tracing */ + int composite_gets; +#endif +}; + +typedef struct _CoglMatrixEntryTranslate +{ + CoglMatrixEntry _parent_data; + + float x; + float y; + float z; + +} CoglMatrixEntryTranslate; + +typedef struct _CoglMatrixEntryRotate +{ + CoglMatrixEntry _parent_data; + + float angle; + float x; + float y; + float z; + +} CoglMatrixEntryRotate; + +typedef struct _CoglMatrixEntryRotateEuler +{ + CoglMatrixEntry _parent_data; + + /* This doesn't store an actual CoglEuler in order to avoid the + * padding */ + float heading; + float pitch; + float roll; +} CoglMatrixEntryRotateEuler; + +typedef struct _CoglMatrixEntryRotateQuaternion +{ + CoglMatrixEntry _parent_data; + + /* This doesn't store an actual CoglQuaternion in order to avoid the + * padding */ + float values[4]; +} CoglMatrixEntryRotateQuaternion; + +typedef struct _CoglMatrixEntryScale +{ + CoglMatrixEntry _parent_data; + + float x; + float y; + float z; + +} CoglMatrixEntryScale; + +typedef struct _CoglMatrixEntryMultiply +{ + CoglMatrixEntry _parent_data; + + CoglMatrix *matrix; + +} CoglMatrixEntryMultiply; + +typedef struct _CoglMatrixEntryLoad +{ + CoglMatrixEntry _parent_data; + + CoglMatrix *matrix; + +} CoglMatrixEntryLoad; + +typedef struct _CoglMatrixEntrySave +{ + CoglMatrixEntry _parent_data; + + CoglMatrix *cache; + CoglBool cache_valid; + +} CoglMatrixEntrySave; + +typedef union _CoglMatrixEntryFull +{ + CoglMatrixEntry any; + CoglMatrixEntryTranslate translate; + CoglMatrixEntryRotate rotate; + CoglMatrixEntryRotateEuler rotate_euler; + CoglMatrixEntryRotateQuaternion rotate_quaternion; + CoglMatrixEntryScale scale; + CoglMatrixEntryMultiply multiply; + CoglMatrixEntryLoad load; + CoglMatrixEntrySave save; +} CoglMatrixEntryFull; + +struct _CoglMatrixStack +{ + CoglObject _parent; + + CoglContext *context; + + CoglMatrixEntry *last_entry; +}; + +typedef struct _CoglMatrixEntryCache +{ + CoglMatrixEntry *entry; + CoglBool flushed_identity; + CoglBool flipped; +} CoglMatrixEntryCache; + +void +_cogl_matrix_entry_identity_init (CoglMatrixEntry *entry); + +typedef enum { + COGL_MATRIX_MODELVIEW, + COGL_MATRIX_PROJECTION, + COGL_MATRIX_TEXTURE +} CoglMatrixMode; + +void +_cogl_matrix_entry_flush_to_gl_builtins (CoglContext *ctx, + CoglMatrixEntry *entry, + CoglMatrixMode mode, + CoglFramebuffer *framebuffer, + CoglBool disable_flip); + +void +_cogl_matrix_entry_cache_init (CoglMatrixEntryCache *cache); + +CoglBool +_cogl_matrix_entry_cache_maybe_update (CoglMatrixEntryCache *cache, + CoglMatrixEntry *entry, + CoglBool flip); + +void +_cogl_matrix_entry_cache_destroy (CoglMatrixEntryCache *cache); + +#endif /* _COGL_MATRIX_STACK_PRIVATE_H_ */ diff --git a/cogl/cogl/cogl-matrix-stack.c b/cogl/cogl/cogl-matrix-stack.c new file mode 100644 index 0000000..d426e1f --- /dev/null +++ b/cogl/cogl/cogl-matrix-stack.c @@ -0,0 +1,1211 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009,2010,2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Havoc Pennington for litl + * Robert Bragg + * Neil Roberts + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-context-private.h" +#include "cogl-util-gl-private.h" +#include "cogl-matrix-stack.h" +#include "cogl-framebuffer-private.h" +#include "cogl-object-private.h" +#include "cogl-offscreen.h" +#include "cogl-matrix-private.h" +#include "cogl-magazine-private.h" +#include "cogl-gtype-private.h" + +static void _cogl_matrix_stack_free (CoglMatrixStack *stack); + +COGL_OBJECT_DEFINE (MatrixStack, matrix_stack); +COGL_GTYPE_DEFINE_CLASS (MatrixStack, matrix_stack); +COGL_GTYPE_DEFINE_BOXED (MatrixEntry, matrix_entry, + cogl_matrix_entry_ref, + cogl_matrix_entry_unref); + +static CoglMagazine *cogl_matrix_stack_magazine; +static CoglMagazine *cogl_matrix_stack_matrices_magazine; + +/* XXX: Note: this leaves entry->parent uninitialized! */ +static CoglMatrixEntry * +_cogl_matrix_entry_new (CoglMatrixOp operation) +{ + CoglMatrixEntry *entry = + _cogl_magazine_chunk_alloc (cogl_matrix_stack_magazine); + + entry->ref_count = 1; + entry->op = operation; + +#ifdef COGL_DEBUG_ENABLED + entry->composite_gets = 0; +#endif + + return entry; +} + +static void * +_cogl_matrix_stack_push_entry (CoglMatrixStack *stack, + CoglMatrixEntry *entry) +{ + /* NB: The initial reference of the entry is transferred to the + * stack here. + * + * The stack only maintains a reference to the top of the stack (the + * last entry pushed) and each entry in-turn maintains a reference + * to its parent. + * + * We don't need to take a reference to the parent from the entry + * here because the we are stealing the reference that was held by + * the stack while that parent was previously the top of the stack. + */ + entry->parent = stack->last_entry; + stack->last_entry = entry; + + return entry; +} + +static void * +_cogl_matrix_stack_push_operation (CoglMatrixStack *stack, + CoglMatrixOp operation) +{ + CoglMatrixEntry *entry = _cogl_matrix_entry_new (operation); + + _cogl_matrix_stack_push_entry (stack, entry); + + return entry; +} + +static void * +_cogl_matrix_stack_push_replacement_entry (CoglMatrixStack *stack, + CoglMatrixOp operation) +{ + CoglMatrixEntry *old_top = stack->last_entry; + CoglMatrixEntry *new_top; + + /* This would only be called for operations that completely replace + * the matrix. In that case we don't need to keep a reference to + * anything up to the last save entry. This optimisation could be + * important for applications that aren't using the stack but + * instead just perform their own matrix manipulations and load a + * new stack every frame. If this optimisation isn't done then the + * stack would just grow endlessly. See the comments + * cogl_matrix_stack_pop for a description of how popping works. */ + for (new_top = old_top; + new_top->op != COGL_MATRIX_OP_SAVE && new_top->parent; + new_top = new_top->parent) + ; + + cogl_matrix_entry_ref (new_top); + cogl_matrix_entry_unref (old_top); + stack->last_entry = new_top; + + return _cogl_matrix_stack_push_operation (stack, operation); +} + +void +_cogl_matrix_entry_identity_init (CoglMatrixEntry *entry) +{ + entry->ref_count = 1; + entry->op = COGL_MATRIX_OP_LOAD_IDENTITY; + entry->parent = NULL; +#ifdef COGL_DEBUG_ENABLED + entry->composite_gets = 0; +#endif +} + +void +cogl_matrix_stack_load_identity (CoglMatrixStack *stack) +{ + _cogl_matrix_stack_push_replacement_entry (stack, + COGL_MATRIX_OP_LOAD_IDENTITY); +} + +void +cogl_matrix_stack_translate (CoglMatrixStack *stack, + float x, + float y, + float z) +{ + CoglMatrixEntryTranslate *entry; + + entry = _cogl_matrix_stack_push_operation (stack, COGL_MATRIX_OP_TRANSLATE); + + entry->x = x; + entry->y = y; + entry->z = z; +} + +void +cogl_matrix_stack_rotate (CoglMatrixStack *stack, + float angle, + float x, + float y, + float z) +{ + CoglMatrixEntryRotate *entry; + + entry = _cogl_matrix_stack_push_operation (stack, COGL_MATRIX_OP_ROTATE); + + entry->angle = angle; + entry->x = x; + entry->y = y; + entry->z = z; +} + +void +cogl_matrix_stack_rotate_quaternion (CoglMatrixStack *stack, + const CoglQuaternion *quaternion) +{ + CoglMatrixEntryRotateQuaternion *entry; + + entry = _cogl_matrix_stack_push_operation (stack, + COGL_MATRIX_OP_ROTATE_QUATERNION); + + entry->values[0] = quaternion->w; + entry->values[1] = quaternion->x; + entry->values[2] = quaternion->y; + entry->values[3] = quaternion->z; +} + +void +cogl_matrix_stack_rotate_euler (CoglMatrixStack *stack, + const CoglEuler *euler) +{ + CoglMatrixEntryRotateEuler *entry; + + entry = _cogl_matrix_stack_push_operation (stack, + COGL_MATRIX_OP_ROTATE_EULER); + + entry->heading = euler->heading; + entry->pitch = euler->pitch; + entry->roll = euler->roll; +} + +void +cogl_matrix_stack_scale (CoglMatrixStack *stack, + float x, + float y, + float z) +{ + CoglMatrixEntryScale *entry; + + entry = _cogl_matrix_stack_push_operation (stack, COGL_MATRIX_OP_SCALE); + + entry->x = x; + entry->y = y; + entry->z = z; +} + +void +cogl_matrix_stack_multiply (CoglMatrixStack *stack, + const CoglMatrix *matrix) +{ + CoglMatrixEntryMultiply *entry; + + entry = _cogl_matrix_stack_push_operation (stack, COGL_MATRIX_OP_MULTIPLY); + + entry->matrix = + _cogl_magazine_chunk_alloc (cogl_matrix_stack_matrices_magazine); + + cogl_matrix_init_from_array (entry->matrix, (float *)matrix); +} + +void +cogl_matrix_stack_set (CoglMatrixStack *stack, + const CoglMatrix *matrix) +{ + CoglMatrixEntryLoad *entry; + + entry = + _cogl_matrix_stack_push_replacement_entry (stack, + COGL_MATRIX_OP_LOAD); + + entry->matrix = + _cogl_magazine_chunk_alloc (cogl_matrix_stack_matrices_magazine); + + cogl_matrix_init_from_array (entry->matrix, (float *)matrix); +} + +void +cogl_matrix_stack_frustum (CoglMatrixStack *stack, + float left, + float right, + float bottom, + float top, + float z_near, + float z_far) +{ + CoglMatrixEntryLoad *entry; + + entry = + _cogl_matrix_stack_push_replacement_entry (stack, + COGL_MATRIX_OP_LOAD); + + entry->matrix = + _cogl_magazine_chunk_alloc (cogl_matrix_stack_matrices_magazine); + + cogl_matrix_init_identity (entry->matrix); + cogl_matrix_frustum (entry->matrix, + left, right, bottom, top, + z_near, z_far); +} + +void +cogl_matrix_stack_perspective (CoglMatrixStack *stack, + float fov_y, + float aspect, + float z_near, + float z_far) +{ + CoglMatrixEntryLoad *entry; + + entry = + _cogl_matrix_stack_push_replacement_entry (stack, + COGL_MATRIX_OP_LOAD); + + entry->matrix = + _cogl_magazine_chunk_alloc (cogl_matrix_stack_matrices_magazine); + + cogl_matrix_init_identity (entry->matrix); + cogl_matrix_perspective (entry->matrix, + fov_y, aspect, z_near, z_far); +} + +void +cogl_matrix_stack_orthographic (CoglMatrixStack *stack, + float x_1, + float y_1, + float x_2, + float y_2, + float near, + float far) +{ + CoglMatrixEntryLoad *entry; + + entry = + _cogl_matrix_stack_push_replacement_entry (stack, + COGL_MATRIX_OP_LOAD); + + entry->matrix = + _cogl_magazine_chunk_alloc (cogl_matrix_stack_matrices_magazine); + + cogl_matrix_init_identity (entry->matrix); + cogl_matrix_orthographic (entry->matrix, + x_1, y_1, x_2, y_2, near, far); +} + +void +cogl_matrix_stack_push (CoglMatrixStack *stack) +{ + CoglMatrixEntrySave *entry; + + entry = _cogl_matrix_stack_push_operation (stack, COGL_MATRIX_OP_SAVE); + + entry->cache_valid = FALSE; +} + +CoglMatrixEntry * +cogl_matrix_entry_ref (CoglMatrixEntry *entry) +{ + /* A NULL pointer is considered a valid stack so we should accept + that as an argument */ + if (entry) + entry->ref_count++; + + return entry; +} + +void +cogl_matrix_entry_unref (CoglMatrixEntry *entry) +{ + CoglMatrixEntry *parent; + + for (; entry && --entry->ref_count <= 0; entry = parent) + { + parent = entry->parent; + + switch (entry->op) + { + case COGL_MATRIX_OP_LOAD_IDENTITY: + case COGL_MATRIX_OP_TRANSLATE: + case COGL_MATRIX_OP_ROTATE: + case COGL_MATRIX_OP_ROTATE_QUATERNION: + case COGL_MATRIX_OP_ROTATE_EULER: + case COGL_MATRIX_OP_SCALE: + break; + case COGL_MATRIX_OP_MULTIPLY: + { + CoglMatrixEntryMultiply *multiply = + (CoglMatrixEntryMultiply *)entry; + _cogl_magazine_chunk_free (cogl_matrix_stack_matrices_magazine, + multiply->matrix); + break; + } + case COGL_MATRIX_OP_LOAD: + { + CoglMatrixEntryLoad *load = (CoglMatrixEntryLoad *)entry; + _cogl_magazine_chunk_free (cogl_matrix_stack_matrices_magazine, + load->matrix); + break; + } + case COGL_MATRIX_OP_SAVE: + { + CoglMatrixEntrySave *save = (CoglMatrixEntrySave *)entry; + if (save->cache_valid) + _cogl_magazine_chunk_free (cogl_matrix_stack_matrices_magazine, + save->cache); + break; + } + } + + _cogl_magazine_chunk_free (cogl_matrix_stack_magazine, entry); + } +} + +void +cogl_matrix_stack_pop (CoglMatrixStack *stack) +{ + CoglMatrixEntry *old_top; + CoglMatrixEntry *new_top; + + _COGL_RETURN_IF_FAIL (stack != NULL); + + old_top = stack->last_entry; + _COGL_RETURN_IF_FAIL (old_top != NULL); + + /* To pop we are moving the top of the stack to the old top's parent + * node. The stack always needs to have a reference to the top entry + * so we must take a reference to the new top. The stack would have + * previously had a reference to the old top so we need to decrease + * the ref count on that. We need to ref the new head first in case + * this stack was the only thing referencing the old top. In that + * case the call to cogl_matrix_entry_unref will unref the parent. + */ + + /* Find the last save operation and remove it */ + + /* XXX: it would be an error to pop to the very beginning of the + * stack so we don't need to check for NULL pointer dereferencing. */ + for (new_top = old_top; + new_top->op != COGL_MATRIX_OP_SAVE; + new_top = new_top->parent) + ; + + new_top = new_top->parent; + cogl_matrix_entry_ref (new_top); + + cogl_matrix_entry_unref (old_top); + + stack->last_entry = new_top; +} + +CoglBool +cogl_matrix_stack_get_inverse (CoglMatrixStack *stack, + CoglMatrix *inverse) +{ + CoglMatrix matrix; + CoglMatrix *internal = cogl_matrix_stack_get (stack, &matrix); + + if (internal) + return cogl_matrix_get_inverse (internal, inverse); + else + return cogl_matrix_get_inverse (&matrix, inverse); +} + +/* In addition to writing the stack matrix into the give @matrix + * argument this function *may* sometimes also return a pointer + * to a matrix too so if we are querying the inverse matrix we + * should query from the return matrix so that the result can + * be cached within the stack. */ +CoglMatrix * +cogl_matrix_entry_get (CoglMatrixEntry *entry, + CoglMatrix *matrix) +{ + int depth; + CoglMatrixEntry *current; + CoglMatrixEntry **children; + int i; + + for (depth = 0, current = entry; + current; + current = current->parent, depth++) + { + switch (current->op) + { + case COGL_MATRIX_OP_LOAD_IDENTITY: + cogl_matrix_init_identity (matrix); + goto initialized; + case COGL_MATRIX_OP_LOAD: + { + CoglMatrixEntryLoad *load = (CoglMatrixEntryLoad *)current; + _cogl_matrix_init_from_matrix_without_inverse (matrix, + load->matrix); + goto initialized; + } + case COGL_MATRIX_OP_SAVE: + { + CoglMatrixEntrySave *save = (CoglMatrixEntrySave *)current; + if (!save->cache_valid) + { + CoglMagazine *matrices_magazine = + cogl_matrix_stack_matrices_magazine; + save->cache = _cogl_magazine_chunk_alloc (matrices_magazine); + cogl_matrix_entry_get (current->parent, save->cache); + save->cache_valid = TRUE; + } + _cogl_matrix_init_from_matrix_without_inverse (matrix, save->cache); + goto initialized; + } + default: + continue; + } + } + +initialized: + + if (depth == 0) + { + switch (entry->op) + { + case COGL_MATRIX_OP_LOAD_IDENTITY: + case COGL_MATRIX_OP_TRANSLATE: + case COGL_MATRIX_OP_ROTATE: + case COGL_MATRIX_OP_ROTATE_QUATERNION: + case COGL_MATRIX_OP_ROTATE_EULER: + case COGL_MATRIX_OP_SCALE: + case COGL_MATRIX_OP_MULTIPLY: + return NULL; + + case COGL_MATRIX_OP_LOAD: + { + CoglMatrixEntryLoad *load = (CoglMatrixEntryLoad *)entry; + return load->matrix; + } + case COGL_MATRIX_OP_SAVE: + { + CoglMatrixEntrySave *save = (CoglMatrixEntrySave *)entry; + return save->cache; + } + } + g_warn_if_reached (); + return NULL; + } + +#ifdef COGL_ENABLE_DEBUG + if (!current) + { + g_warning ("Inconsistent matrix stack"); + return NULL; + } + + entry->composite_gets++; +#endif + + children = g_alloca (sizeof (CoglMatrixEntry) * depth); + + /* We need walk the list of entries from the init/load/save entry + * back towards the leaf node but the nodes don't link to their + * children so we need to re-walk them here to add to a separate + * array. */ + for (i = depth - 1, current = entry; + i >= 0 && current; + i--, current = current->parent) + { + children[i] = current; + } + +#ifdef COGL_ENABLE_DEBUG + if (COGL_DEBUG_ENABLED (COGL_DEBUG_PERFORMANCE) && + entry->composite_gets >= 2) + { + COGL_NOTE (PERFORMANCE, + "Re-composing a matrix stack entry multiple times"); + } +#endif + + for (i = 0; i < depth; i++) + { + switch (children[i]->op) + { + case COGL_MATRIX_OP_TRANSLATE: + { + CoglMatrixEntryTranslate *translate = + (CoglMatrixEntryTranslate *)children[i]; + cogl_matrix_translate (matrix, + translate->x, + translate->y, + translate->z); + continue; + } + case COGL_MATRIX_OP_ROTATE: + { + CoglMatrixEntryRotate *rotate= + (CoglMatrixEntryRotate *)children[i]; + cogl_matrix_rotate (matrix, + rotate->angle, + rotate->x, + rotate->y, + rotate->z); + continue; + } + case COGL_MATRIX_OP_ROTATE_EULER: + { + CoglMatrixEntryRotateEuler *rotate = + (CoglMatrixEntryRotateEuler *)children[i]; + CoglEuler euler; + cogl_euler_init (&euler, + rotate->heading, + rotate->pitch, + rotate->roll); + cogl_matrix_rotate_euler (matrix, + &euler); + continue; + } + case COGL_MATRIX_OP_ROTATE_QUATERNION: + { + CoglMatrixEntryRotateQuaternion *rotate = + (CoglMatrixEntryRotateQuaternion *)children[i]; + CoglQuaternion quaternion; + cogl_quaternion_init_from_array (&quaternion, rotate->values); + cogl_matrix_rotate_quaternion (matrix, &quaternion); + continue; + } + case COGL_MATRIX_OP_SCALE: + { + CoglMatrixEntryScale *scale = + (CoglMatrixEntryScale *)children[i]; + cogl_matrix_scale (matrix, + scale->x, + scale->y, + scale->z); + continue; + } + case COGL_MATRIX_OP_MULTIPLY: + { + CoglMatrixEntryMultiply *multiply = + (CoglMatrixEntryMultiply *)children[i]; + cogl_matrix_multiply (matrix, matrix, multiply->matrix); + continue; + } + + case COGL_MATRIX_OP_LOAD_IDENTITY: + case COGL_MATRIX_OP_LOAD: + case COGL_MATRIX_OP_SAVE: + g_warn_if_reached (); + continue; + } + } + + return NULL; +} + +CoglMatrixEntry * +cogl_matrix_stack_get_entry (CoglMatrixStack *stack) +{ + return stack->last_entry; +} + +/* In addition to writing the stack matrix into the give @matrix + * argument this function *may* sometimes also return a pointer + * to a matrix too so if we are querying the inverse matrix we + * should query from the return matrix so that the result can + * be cached within the stack. */ +CoglMatrix * +cogl_matrix_stack_get (CoglMatrixStack *stack, + CoglMatrix *matrix) +{ + return cogl_matrix_entry_get (stack->last_entry, matrix); +} + +static void +_cogl_matrix_stack_free (CoglMatrixStack *stack) +{ + cogl_matrix_entry_unref (stack->last_entry); + g_slice_free (CoglMatrixStack, stack); +} + +CoglMatrixStack * +cogl_matrix_stack_new (CoglContext *ctx) +{ + CoglMatrixStack *stack = g_slice_new (CoglMatrixStack); + + if (G_UNLIKELY (cogl_matrix_stack_magazine == NULL)) + { + cogl_matrix_stack_magazine = + _cogl_magazine_new (sizeof (CoglMatrixEntryFull), 20); + cogl_matrix_stack_matrices_magazine = + _cogl_magazine_new (sizeof (CoglMatrix), 20); + } + + stack->context = ctx; + stack->last_entry = NULL; + + cogl_matrix_entry_ref (&ctx->identity_entry); + _cogl_matrix_stack_push_entry (stack, &ctx->identity_entry); + + return _cogl_matrix_stack_object_new (stack); +} + +static CoglMatrixEntry * +_cogl_matrix_entry_skip_saves (CoglMatrixEntry *entry) +{ + /* We currently assume that every stack starts with an + * _OP_LOAD_IDENTITY so we don't need to worry about + * NULL pointer dereferencing here. */ + while (entry->op == COGL_MATRIX_OP_SAVE) + entry = entry->parent; + + return entry; +} + +CoglBool +cogl_matrix_entry_calculate_translation (CoglMatrixEntry *entry0, + CoglMatrixEntry *entry1, + float *x, + float *y, + float *z) +{ + GSList *head0 = NULL; + GSList *head1 = NULL; + CoglMatrixEntry *node0; + CoglMatrixEntry *node1; + int len0 = 0; + int len1 = 0; + int count; + GSList *common_ancestor0; + GSList *common_ancestor1; + + /* Algorithm: + * + * 1) Ignoring _OP_SAVE entries walk the ancestors of each entry to + * the root node or any non-translation node, adding a pointer to + * each ancestor node to two linked lists. + * + * 2) Compare the lists to find the nodes where they start to + * differ marking the common_ancestor node for each list. + * + * 3) For the list corresponding to entry0, start iterating after + * the common ancestor applying the negative of all translations + * to x, y and z. + * + * 4) For the list corresponding to entry1, start iterating after + * the common ancestor applying the positive of all translations + * to x, y and z. + * + * If we come across any non-translation operations during 3) or 4) + * then bail out returning FALSE. + */ + + for (node0 = entry0; node0; node0 = node0->parent) + { + GSList *link; + + if (node0->op == COGL_MATRIX_OP_SAVE) + continue; + + link = alloca (sizeof (GSList)); + link->next = head0; + link->data = node0; + head0 = link; + len0++; + + if (node0->op != COGL_MATRIX_OP_TRANSLATE) + break; + } + for (node1 = entry1; node1; node1 = node1->parent) + { + GSList *link; + + if (node1->op == COGL_MATRIX_OP_SAVE) + continue; + + link = alloca (sizeof (GSList)); + link->next = head1; + link->data = node1; + head1 = link; + len1++; + + if (node1->op != COGL_MATRIX_OP_TRANSLATE) + break; + } + + if (head0->data != head1->data) + return FALSE; + + common_ancestor0 = head0; + common_ancestor1 = head1; + head0 = head0->next; + head1 = head1->next; + count = MIN (len0, len1) - 1; + while (count--) + { + if (head0->data != head1->data) + break; + common_ancestor0 = head0; + common_ancestor1 = head1; + head0 = head0->next; + head1 = head1->next; + } + + *x = 0; + *y = 0; + *z = 0; + + for (head0 = common_ancestor0->next; head0; head0 = head0->next) + { + CoglMatrixEntryTranslate *translate; + + node0 = head0->data; + + if (node0->op != COGL_MATRIX_OP_TRANSLATE) + return FALSE; + + translate = (CoglMatrixEntryTranslate *)node0; + + *x = *x - translate->x; + *y = *y - translate->y; + *z = *z - translate->z; + } + for (head1 = common_ancestor1->next; head1; head1 = head1->next) + { + CoglMatrixEntryTranslate *translate; + + node1 = head1->data; + + if (node1->op != COGL_MATRIX_OP_TRANSLATE) + return FALSE; + + translate = (CoglMatrixEntryTranslate *)node1; + + *x = *x + translate->x; + *y = *y + translate->y; + *z = *z + translate->z; + } + + return TRUE; +} + +CoglBool +cogl_matrix_entry_is_identity (CoglMatrixEntry *entry) +{ + return entry ? entry->op == COGL_MATRIX_OP_LOAD_IDENTITY : FALSE; +} + +static void +_cogl_matrix_flush_to_gl_builtin (CoglContext *ctx, + CoglBool is_identity, + CoglMatrix *matrix, + CoglMatrixMode mode) +{ + g_assert (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_GL_FIXED)); + +#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) + if (ctx->flushed_matrix_mode != mode) + { + GLenum gl_mode = 0; + + switch (mode) + { + case COGL_MATRIX_MODELVIEW: + gl_mode = GL_MODELVIEW; + break; + + case COGL_MATRIX_PROJECTION: + gl_mode = GL_PROJECTION; + break; + + case COGL_MATRIX_TEXTURE: + gl_mode = GL_TEXTURE; + break; + } + + GE (ctx, glMatrixMode (gl_mode)); + ctx->flushed_matrix_mode = mode; + } + + if (is_identity) + GE (ctx, glLoadIdentity ()); + else + GE (ctx, glLoadMatrixf (cogl_matrix_get_array (matrix))); +#endif +} + +void +_cogl_matrix_entry_flush_to_gl_builtins (CoglContext *ctx, + CoglMatrixEntry *entry, + CoglMatrixMode mode, + CoglFramebuffer *framebuffer, + CoglBool disable_flip) +{ + g_assert (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_GL_FIXED)); + +#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) + { + CoglBool needs_flip; + CoglMatrixEntryCache *cache; + + if (mode == COGL_MATRIX_PROJECTION) + { + /* Because Cogl defines texture coordinates to have a top left + * origin and because offscreen framebuffers may be used for + * rendering to textures we always render upside down to + * offscreen buffers. Also for some backends we need to render + * onscreen buffers upside-down too. + */ + if (disable_flip) + needs_flip = FALSE; + else + needs_flip = cogl_is_offscreen (framebuffer); + + cache = &ctx->builtin_flushed_projection; + } + else + { + needs_flip = FALSE; + + if (mode == COGL_MATRIX_MODELVIEW) + cache = &ctx->builtin_flushed_modelview; + else + cache = NULL; + } + + /* We don't need to do anything if the state is the same */ + if (!cache || + _cogl_matrix_entry_cache_maybe_update (cache, entry, needs_flip)) + { + CoglBool is_identity; + CoglMatrix matrix; + + if (entry->op == COGL_MATRIX_OP_LOAD_IDENTITY) + is_identity = TRUE; + else + { + is_identity = FALSE; + cogl_matrix_entry_get (entry, &matrix); + } + + if (needs_flip) + { + CoglMatrix flipped_matrix; + + cogl_matrix_multiply (&flipped_matrix, + &ctx->y_flip_matrix, + is_identity ? + &ctx->identity_matrix : + &matrix); + + _cogl_matrix_flush_to_gl_builtin (ctx, + /* not identity */ + FALSE, + &flipped_matrix, + mode); + } + else + { + _cogl_matrix_flush_to_gl_builtin (ctx, + is_identity, + &matrix, + mode); + } + } + } +#endif +} + +CoglBool +cogl_matrix_entry_equal (CoglMatrixEntry *entry0, + CoglMatrixEntry *entry1) +{ + for (; + entry0 && entry1; + entry0 = entry0->parent, entry1 = entry1->parent) + { + entry0 = _cogl_matrix_entry_skip_saves (entry0); + entry1 = _cogl_matrix_entry_skip_saves (entry1); + + if (entry0 == entry1) + return TRUE; + + if (entry0->op != entry1->op) + return FALSE; + + switch (entry0->op) + { + case COGL_MATRIX_OP_LOAD_IDENTITY: + return TRUE; + case COGL_MATRIX_OP_TRANSLATE: + { + CoglMatrixEntryTranslate *translate0 = + (CoglMatrixEntryTranslate *)entry0; + CoglMatrixEntryTranslate *translate1 = + (CoglMatrixEntryTranslate *)entry1; + /* We could perhaps use an epsilon to compare here? + * I expect the false negatives are probaly never going to + * be a problem and this is a bit cheaper. */ + if (translate0->x != translate1->x || + translate0->y != translate1->y || + translate0->z != translate1->z) + return FALSE; + } + break; + case COGL_MATRIX_OP_ROTATE: + { + CoglMatrixEntryRotate *rotate0 = + (CoglMatrixEntryRotate *)entry0; + CoglMatrixEntryRotate *rotate1 = + (CoglMatrixEntryRotate *)entry1; + if (rotate0->angle != rotate1->angle || + rotate0->x != rotate1->x || + rotate0->y != rotate1->y || + rotate0->z != rotate1->z) + return FALSE; + } + break; + case COGL_MATRIX_OP_ROTATE_QUATERNION: + { + CoglMatrixEntryRotateQuaternion *rotate0 = + (CoglMatrixEntryRotateQuaternion *)entry0; + CoglMatrixEntryRotateQuaternion *rotate1 = + (CoglMatrixEntryRotateQuaternion *)entry1; + int i; + for (i = 0; i < 4; i++) + if (rotate0->values[i] != rotate1->values[i]) + return FALSE; + } + break; + case COGL_MATRIX_OP_ROTATE_EULER: + { + CoglMatrixEntryRotateEuler *rotate0 = + (CoglMatrixEntryRotateEuler *)entry0; + CoglMatrixEntryRotateEuler *rotate1 = + (CoglMatrixEntryRotateEuler *)entry1; + + if (rotate0->heading != rotate1->heading || + rotate0->pitch != rotate1->pitch || + rotate0->roll != rotate1->roll) + return FALSE; + } + break; + case COGL_MATRIX_OP_SCALE: + { + CoglMatrixEntryScale *scale0 = (CoglMatrixEntryScale *)entry0; + CoglMatrixEntryScale *scale1 = (CoglMatrixEntryScale *)entry1; + if (scale0->x != scale1->x || + scale0->y != scale1->y || + scale0->z != scale1->z) + return FALSE; + } + break; + case COGL_MATRIX_OP_MULTIPLY: + { + CoglMatrixEntryMultiply *mult0 = (CoglMatrixEntryMultiply *)entry0; + CoglMatrixEntryMultiply *mult1 = (CoglMatrixEntryMultiply *)entry1; + if (!cogl_matrix_equal (mult0->matrix, mult1->matrix)) + return FALSE; + } + break; + case COGL_MATRIX_OP_LOAD: + { + CoglMatrixEntryLoad *load0 = (CoglMatrixEntryLoad *)entry0; + CoglMatrixEntryLoad *load1 = (CoglMatrixEntryLoad *)entry1; + /* There's no need to check any further since an + * _OP_LOAD makes all the ancestors redundant as far as + * the final matrix value is concerned. */ + return cogl_matrix_equal (load0->matrix, load1->matrix); + } + case COGL_MATRIX_OP_SAVE: + /* We skip over saves above so we shouldn't see save entries */ + g_warn_if_reached (); + } + } + + return FALSE; +} + +void +cogl_debug_matrix_entry_print (CoglMatrixEntry *entry) +{ + int depth; + CoglMatrixEntry *e; + CoglMatrixEntry **children; + int i; + + for (depth = 0, e = entry; e; e = e->parent) + depth++; + + children = g_alloca (sizeof (CoglMatrixEntry) * depth); + + for (i = depth - 1, e = entry; + i >= 0 && e; + i--, e = e->parent) + { + children[i] = e; + } + + g_print ("MatrixEntry %p =\n", entry); + + for (i = 0; i < depth; i++) + { + entry = children[i]; + + switch (entry->op) + { + case COGL_MATRIX_OP_LOAD_IDENTITY: + g_print (" LOAD IDENTITY\n"); + continue; + case COGL_MATRIX_OP_TRANSLATE: + { + CoglMatrixEntryTranslate *translate = + (CoglMatrixEntryTranslate *)entry; + g_print (" TRANSLATE X=%f Y=%f Z=%f\n", + translate->x, + translate->y, + translate->z); + continue; + } + case COGL_MATRIX_OP_ROTATE: + { + CoglMatrixEntryRotate *rotate = + (CoglMatrixEntryRotate *)entry; + g_print (" ROTATE ANGLE=%f X=%f Y=%f Z=%f\n", + rotate->angle, + rotate->x, + rotate->y, + rotate->z); + continue; + } + case COGL_MATRIX_OP_ROTATE_QUATERNION: + { + CoglMatrixEntryRotateQuaternion *rotate = + (CoglMatrixEntryRotateQuaternion *)entry; + g_print (" ROTATE QUATERNION w=%f x=%f y=%f z=%f\n", + rotate->values[0], + rotate->values[1], + rotate->values[2], + rotate->values[3]); + continue; + } + case COGL_MATRIX_OP_ROTATE_EULER: + { + CoglMatrixEntryRotateEuler *rotate = + (CoglMatrixEntryRotateEuler *)entry; + g_print (" ROTATE EULER heading=%f pitch=%f roll=%f\n", + rotate->heading, + rotate->pitch, + rotate->roll); + continue; + } + case COGL_MATRIX_OP_SCALE: + { + CoglMatrixEntryScale *scale = (CoglMatrixEntryScale *)entry; + g_print (" SCALE X=%f Y=%f Z=%f\n", + scale->x, + scale->y, + scale->z); + continue; + } + case COGL_MATRIX_OP_MULTIPLY: + { + CoglMatrixEntryMultiply *mult = (CoglMatrixEntryMultiply *)entry; + g_print (" MULT:\n"); + _cogl_matrix_prefix_print (" ", mult->matrix); + continue; + } + case COGL_MATRIX_OP_LOAD: + { + CoglMatrixEntryLoad *load = (CoglMatrixEntryLoad *)entry; + g_print (" LOAD:\n"); + _cogl_matrix_prefix_print (" ", load->matrix); + continue; + } + case COGL_MATRIX_OP_SAVE: + g_print (" SAVE\n"); + } + } +} + +void +_cogl_matrix_entry_cache_init (CoglMatrixEntryCache *cache) +{ + cache->entry = NULL; + cache->flushed_identity = FALSE; + cache->flipped = FALSE; +} + +/* NB: This function can report false negatives since it never does a + * deep comparison of the stack matrices. */ +CoglBool +_cogl_matrix_entry_cache_maybe_update (CoglMatrixEntryCache *cache, + CoglMatrixEntry *entry, + CoglBool flip) +{ + CoglBool is_identity; + CoglBool updated = FALSE; + + if (cache->flipped != flip) + { + cache->flipped = flip; + updated = TRUE; + } + + is_identity = (entry->op == COGL_MATRIX_OP_LOAD_IDENTITY); + if (cache->flushed_identity != is_identity) + { + cache->flushed_identity = is_identity; + updated = TRUE; + } + + if (cache->entry != entry) + { + cogl_matrix_entry_ref (entry); + if (cache->entry) + cogl_matrix_entry_unref (cache->entry); + cache->entry = entry; + + /* We want to make sure here that if the cache->entry and the + * given @entry are both identity matrices then even though they + * are different entries we don't want to consider this an + * update... + */ + updated |= !is_identity; + } + + return updated; +} + +void +_cogl_matrix_entry_cache_destroy (CoglMatrixEntryCache *cache) +{ + if (cache->entry) + cogl_matrix_entry_unref (cache->entry); +} diff --git a/cogl/cogl/cogl-matrix-stack.h b/cogl/cogl/cogl-matrix-stack.h new file mode 100644 index 0000000..8d936b2 --- /dev/null +++ b/cogl/cogl/cogl-matrix-stack.h @@ -0,0 +1,641 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009,2010,2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Havoc Pennington for litl + * Robert Bragg + */ + +#ifndef _COGL_MATRIX_STACK_H_ +#define _COGL_MATRIX_STACK_H_ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#include "cogl-matrix.h" +#include "cogl-context.h" + + +/** + * SECTION:cogl-matrix-stack + * @short_description: Functions for efficiently tracking many + * related transformations + * + * Matrices can be used (for example) to describe the model-view + * transforms of objects, texture transforms, and projective + * transforms. + * + * The #CoglMatrix api provides a good way to manipulate individual + * matrices representing a single transformation but if you need to + * track many-many such transformations for many objects that are + * organized in a scenegraph for example then using a separate + * #CoglMatrix for each object may not be the most efficient way. + * + * A #CoglMatrixStack enables applications to track lots of + * transformations that are related to each other in some kind of + * hierarchy. In a scenegraph for example if you want to know how to + * transform a particular node then you usually have to walk up + * through the ancestors and accumulate their transforms before + * finally applying the transform of the node itself. In this model + * things are grouped together spatially according to their ancestry + * and all siblings with the same parent share the same initial + * transformation. The #CoglMatrixStack API is suited to tracking lots + * of transformations that fit this kind of model. + * + * Compared to using the #CoglMatrix api directly to track many + * related transforms, these can be some advantages to using a + * #CoglMatrixStack: + * + * Faster equality comparisons of transformations + * Efficient comparisons of the differences between arbitrary + * transformations + * Avoid redundant arithmetic related to common transforms + * + * Can be more space efficient (not always though) + * + * + * For reference (to give an idea of when a #CoglMatrixStack can + * provide a space saving) a #CoglMatrix can be expected to take 72 + * bytes whereas a single #CoglMatrixEntry in a #CoglMatrixStack is + * currently around 32 bytes on a 32bit CPU or 36 bytes on a 64bit + * CPU. An entry is needed for each individual operation applied to + * the stack (such as rotate, scale, translate) so if most of your + * leaf node transformations only need one or two simple operations + * relative to their parent then a matrix stack will likely take less + * space than having a #CoglMatrix for each node. + * + * Even without any space saving though the ability to perform fast + * comparisons and avoid redundant arithmetic (especially sine and + * cosine calculations for rotations) can make using a matrix stack + * worthwhile. + */ + +/** + * CoglMatrixStack: + * + * Tracks your current position within a hierarchy and lets you build + * up a graph of transformations as you traverse through a hierarchy + * such as a scenegraph. + * + * A #CoglMatrixStack always maintains a reference to a single + * transformation at any point in time, representing the + * transformation at the current position in the hierarchy. You can + * get a reference to the current transformation by calling + * cogl_matrix_stack_get_entry(). + * + * When a #CoglMatrixStack is first created with + * cogl_matrix_stack_new() then it is conceptually positioned at the + * root of your hierarchy and the current transformation simply + * represents an identity transformation. + * + * As you traverse your object hierarchy (your scenegraph) then you + * should call cogl_matrix_stack_push() whenever you move down one + * level and call cogl_matrix_stack_pop() whenever you move back up + * one level towards the root. + * + * At any time you can apply a set of operations, such as "rotate", + * "scale", "translate" on top of the current transformation of a + * #CoglMatrixStack using functions such as + * cogl_matrix_stack_rotate(), cogl_matrix_stack_scale() and + * cogl_matrix_stack_translate(). These operations will derive a new + * current transformation and will never affect a transformation + * that you have referenced using cogl_matrix_stack_get_entry(). + * + * Internally applying operations to a #CoglMatrixStack builds up a + * graph of #CoglMatrixEntry structures which each represent a single + * immutable transform. + */ +typedef struct _CoglMatrixStack CoglMatrixStack; + +/** + * cogl_matrix_stack_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_matrix_stack_get_gtype (void); + +/** + * CoglMatrixEntry: + * + * Represents a single immutable transformation that was retrieved + * from a #CoglMatrixStack using cogl_matrix_stack_get_entry(). + * + * Internally a #CoglMatrixEntry represents a single matrix + * operation (such as "rotate", "scale", "translate") which is applied + * to the transform of a single parent entry. + * + * Using the #CoglMatrixStack api effectively builds up a graph of + * these immutable #CoglMatrixEntry structures whereby operations + * that can be shared between multiple transformations will result + * in shared #CoglMatrixEntry nodes in the graph. + * + * When a #CoglMatrixStack is first created it references one + * #CoglMatrixEntry that represents a single "load identity" + * operation. This serves as the root entry and all operations + * that are then applied to the stack will extend the graph + * starting from this root "load identity" entry. + * + * Given the typical usage model for a #CoglMatrixStack and the way + * the entries are built up while traversing a scenegraph then in most + * cases where an application is interested in comparing two + * transformations for equality then it is enough to simply compare + * two #CoglMatrixEntry pointers directly. Technically this can lead + * to false negatives that could be identified with a deeper + * comparison but often these false negatives are unlikely and + * don't matter anyway so this enables extremely cheap comparisons. + * + * #CoglMatrixEntrys are reference counted using + * cogl_matrix_entry_ref() and cogl_matrix_entry_unref() not with + * cogl_object_ref() and cogl_object_unref(). + */ +typedef struct _CoglMatrixEntry CoglMatrixEntry; + +/** + * cogl_matrix_entry_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_matrix_entry_get_gtype (void); + + +/** + * cogl_matrix_stack_new: + * @ctx: A #CoglContext + * + * Allocates a new #CoglMatrixStack that can be used to build up + * transformations relating to objects in a scenegraph like hierarchy. + * (See the description of #CoglMatrixStack and #CoglMatrixEntry for + * more details of what a matrix stack is best suited for) + * + * When a #CoglMatrixStack is first allocated it is conceptually + * positioned at the root of your scenegraph hierarchy. As you + * traverse your scenegraph then you should call + * cogl_matrix_stack_push() whenever you move down a level and + * cogl_matrix_stack_pop() whenever you move back up a level towards + * the root. + * + * Once you have allocated a #CoglMatrixStack you can get a reference + * to the current transformation for the current position in the + * hierarchy by calling cogl_matrix_stack_get_entry(). + * + * Once you have allocated a #CoglMatrixStack you can apply operations + * such as rotate, scale and translate to modify the current transform + * for the current position in the hierarchy by calling + * cogl_matrix_stack_rotate(), cogl_matrix_stack_scale() and + * cogl_matrix_stack_translate(). + * + * Return value: (transfer full): A newly allocated #CoglMatrixStack + */ +CoglMatrixStack * +cogl_matrix_stack_new (CoglContext *ctx); + +/** + * cogl_matrix_stack_push: + * @stack: A #CoglMatrixStack + * + * Saves the current transform and starts a new transform that derives + * from the current transform. + * + * This is usually called while traversing a scenegraph whenever you + * traverse one level deeper. cogl_matrix_stack_pop() can then be + * called when going back up one layer to restore the previous + * transform of an ancestor. + */ +void +cogl_matrix_stack_push (CoglMatrixStack *stack); + +/** + * cogl_matrix_stack_pop: + * @stack: A #CoglMatrixStack + * + * Restores the previous transform that was last saved by calling + * cogl_matrix_stack_push(). + * + * This is usually called while traversing a scenegraph whenever you + * return up one level in the graph towards the root node. + */ +void +cogl_matrix_stack_pop (CoglMatrixStack *stack); + +/** + * cogl_matrix_stack_load_identity: + * @stack: A #CoglMatrixStack + * + * Resets the current matrix to the identity matrix. + */ +void +cogl_matrix_stack_load_identity (CoglMatrixStack *stack); + +/** + * cogl_matrix_stack_scale: + * @stack: A #CoglMatrixStack + * @x: Amount to scale along the x-axis + * @y: Amount to scale along the y-axis + * @z: Amount to scale along the z-axis + * + * Multiplies the current matrix by one that scales the x, y and z + * axes by the given values. + */ +void +cogl_matrix_stack_scale (CoglMatrixStack *stack, + float x, + float y, + float z); + +/** + * cogl_matrix_stack_translate: + * @stack: A #CoglMatrixStack + * @x: Distance to translate along the x-axis + * @y: Distance to translate along the y-axis + * @z: Distance to translate along the z-axis + * + * Multiplies the current matrix by one that translates along all + * three axes according to the given values. + */ +void +cogl_matrix_stack_translate (CoglMatrixStack *stack, + float x, + float y, + float z); + +/** + * cogl_matrix_stack_rotate: + * @stack: A #CoglMatrixStack + * @angle: Angle in degrees to rotate. + * @x: X-component of vertex to rotate around. + * @y: Y-component of vertex to rotate around. + * @z: Z-component of vertex to rotate around. + * + * Multiplies the current matrix by one that rotates the around the + * axis-vector specified by @x, @y and @z. The rotation follows the + * right-hand thumb rule so for example rotating by 10 degrees about + * the axis-vector (0, 0, 1) causes a small counter-clockwise + * rotation. + */ +void +cogl_matrix_stack_rotate (CoglMatrixStack *stack, + float angle, + float x, + float y, + float z); + +/** + * cogl_matrix_stack_rotate_quaternion: + * @stack: A #CoglMatrixStack + * @quaternion: A #CoglQuaternion + * + * Multiplies the current matrix by one that rotates according to the + * rotation described by @quaternion. + */ +void +cogl_matrix_stack_rotate_quaternion (CoglMatrixStack *stack, + const CoglQuaternion *quaternion); + +/** + * cogl_matrix_stack_rotate_euler: + * @stack: A #CoglMatrixStack + * @euler: A #CoglEuler + * + * Multiplies the current matrix by one that rotates according to the + * rotation described by @euler. + */ +void +cogl_matrix_stack_rotate_euler (CoglMatrixStack *stack, + const CoglEuler *euler); + +/** + * cogl_matrix_stack_multiply: + * @stack: A #CoglMatrixStack + * @matrix: the matrix to multiply with the current model-view + * + * Multiplies the current matrix by the given matrix. + */ +void +cogl_matrix_stack_multiply (CoglMatrixStack *stack, + const CoglMatrix *matrix); + +/** + * cogl_matrix_stack_frustum: + * @stack: A #CoglMatrixStack + * @left: X position of the left clipping plane where it + * intersects the near clipping plane + * @right: X position of the right clipping plane where it + * intersects the near clipping plane + * @bottom: Y position of the bottom clipping plane where it + * intersects the near clipping plane + * @top: Y position of the top clipping plane where it intersects + * the near clipping plane + * @z_near: The distance to the near clipping plane (Must be positive) + * @z_far: The distance to the far clipping plane (Must be positive) + * + * Replaces the current matrix with a perspective matrix for a given + * viewing frustum defined by 4 side clip planes that all cross + * through the origin and 2 near and far clip planes. + */ +void +cogl_matrix_stack_frustum (CoglMatrixStack *stack, + float left, + float right, + float bottom, + float top, + float z_near, + float z_far); + +/** + * cogl_matrix_stack_perspective: + * @stack: A #CoglMatrixStack + * @fov_y: Vertical field of view angle in degrees. + * @aspect: The (width over height) aspect ratio for display + * @z_near: The distance to the near clipping plane (Must be positive, + * and must not be 0) + * @z_far: The distance to the far clipping plane (Must be positive) + * + * Replaces the current matrix with a perspective matrix based on the + * provided values. + * + * You should be careful not to have too 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_stack_perspective (CoglMatrixStack *stack, + float fov_y, + float aspect, + float z_near, + float z_far); + +/** + * cogl_matrix_stack_orthographic: + * @stack: A #CoglMatrixStack + * @x_1: The x coordinate for the first vertical clipping plane + * @y_1: The y coordinate for the first horizontal clipping plane + * @x_2: The x coordinate for the second vertical clipping plane + * @y_2: The y coordinate for the second horizontal clipping plane + * @near: The distance to the near clipping + * plane (will be negative if the plane is + * behind the viewer) + * @far: The distance to the far clipping + * plane (will be negative if the plane is + * behind the viewer) + * + * Replaces the current matrix with an orthographic projection matrix. + */ +void +cogl_matrix_stack_orthographic (CoglMatrixStack *stack, + float x_1, + float y_1, + float x_2, + float y_2, + float near, + float far); + +/** + * cogl_matrix_stack_get_inverse: + * @stack: A #CoglMatrixStack + * @inverse: (out): The destination for a 4x4 inverse transformation matrix + * + * Gets the inverse transform of the current matrix and uses it to + * initialize a new #CoglMatrix. + * + * Return value: %TRUE if the inverse was successfully calculated or %FALSE + * for degenerate transformations that can't be inverted (in this case the + * @inverse matrix will simply be initialized with the identity matrix) + */ +CoglBool +cogl_matrix_stack_get_inverse (CoglMatrixStack *stack, + CoglMatrix *inverse); + +/** + * cogl_matrix_stack_get_entry: + * @stack: A #CoglMatrixStack + * + * Gets a reference to the current transform represented by a + * #CoglMatrixEntry pointer. + * + * The transform represented by a #CoglMatrixEntry is + * immutable. + * + * #CoglMatrixEntrys are reference counted using + * cogl_matrix_entry_ref() and cogl_matrix_entry_unref() and you + * should call cogl_matrix_entry_unref() when you are finished with + * and entry you get via cogl_matrix_stack_get_entry(). + * + * Return value: (transfer none): A pointer to the #CoglMatrixEntry + * representing the current matrix stack transform. + */ +CoglMatrixEntry * +cogl_matrix_stack_get_entry (CoglMatrixStack *stack); + +/** + * cogl_matrix_stack_get: + * @stack: A #CoglMatrixStack + * @matrix: (out): The potential destination for the current matrix + * + * Resolves the current @stack transform into a #CoglMatrix by + * combining the operations that have been applied to build up the + * current transform. + * + * There are two possible ways that this function may return its + * result depending on whether the stack is able to directly point + * to an internal #CoglMatrix or whether the result needs to be + * composed of multiple operations. + * + * If an internal matrix contains the required result then this + * function will directly return a pointer to that matrix, otherwise + * if the function returns %NULL then @matrix will be initialized + * to match the current transform of @stack. + * + * @matrix will be left untouched if a direct pointer is + * returned. + * + * Return value: A direct pointer to the current transform or %NULL + * and in that case @matrix will be initialized with + * the value of the current transform. + */ +CoglMatrix * +cogl_matrix_stack_get (CoglMatrixStack *stack, + CoglMatrix *matrix); + +/** + * cogl_matrix_entry_get: + * @entry: A #CoglMatrixEntry + * @matrix: (out): The potential destination for the transform as + * a matrix + * + * Resolves the current @entry transform into a #CoglMatrix by + * combining the sequence of operations that have been applied to + * build up the current transform. + * + * There are two possible ways that this function may return its + * result depending on whether it's possible to directly point + * to an internal #CoglMatrix or whether the result needs to be + * composed of multiple operations. + * + * If an internal matrix contains the required result then this + * function will directly return a pointer to that matrix, otherwise + * if the function returns %NULL then @matrix will be initialized + * to match the transform of @entry. + * + * @matrix will be left untouched if a direct pointer is + * returned. + * + * Return value: A direct pointer to a #CoglMatrix transform or %NULL + * and in that case @matrix will be initialized with + * the effective transform represented by @entry. + */ +CoglMatrix * +cogl_matrix_entry_get (CoglMatrixEntry *entry, + CoglMatrix *matrix); + +/** + * cogl_matrix_stack_set: + * @stack: A #CoglMatrixStack + * @matrix: A #CoglMatrix replace the current matrix value with + * + * Replaces the current @stack matrix value with the value of @matrix. + * This effectively discards any other operations that were applied + * since the last time cogl_matrix_stack_push() was called or since + * the stack was initialized. + */ +void +cogl_matrix_stack_set (CoglMatrixStack *stack, + const CoglMatrix *matrix); + +/** + * cogl_is_matrix_stack: + * @object: a #CoglObject + * + * Determines if the given #CoglObject refers to a #CoglMatrixStack. + * + * Return value: %TRUE if @object is a #CoglMatrixStack, otherwise + * %FALSE. + */ +CoglBool +cogl_is_matrix_stack (void *object); + +/** + * cogl_matrix_entry_calculate_translation: + * @entry0: The first reference transform + * @entry1: A second reference transform + * @x: (out): The destination for the x-component of the translation + * @y: (out): The destination for the y-component of the translation + * @z: (out): The destination for the z-component of the translation + * + * Determines if the only difference between two transforms is a + * translation and if so returns what the @x, @y, and @z components of + * the translation are. + * + * If the difference between the two translations involves anything + * other than a translation then the function returns %FALSE. + * + * Return value: %TRUE if the only difference between the transform of + * @entry0 and the transform of @entry1 is a translation, + * otherwise %FALSE. + */ +CoglBool +cogl_matrix_entry_calculate_translation (CoglMatrixEntry *entry0, + CoglMatrixEntry *entry1, + float *x, + float *y, + float *z); + +/** + * cogl_matrix_entry_is_identity: + * @entry: A #CoglMatrixEntry + * + * Determines whether @entry is known to represent an identity + * transform. + * + * If this returns %TRUE then the entry is definitely the identity + * matrix. If it returns %FALSE it may or may not be the identity + * matrix but no expensive comparison is performed to verify it. + * + * Return value: %TRUE if @entry is definitely an identity transform, + * otherwise %FALSE. + */ +CoglBool +cogl_matrix_entry_is_identity (CoglMatrixEntry *entry); + +/** + * cogl_matrix_entry_equal: + * @entry0: The first #CoglMatrixEntry to compare + * @entry1: A second #CoglMatrixEntry to compare + * + * Compares two arbitrary #CoglMatrixEntry transforms for equality + * returning %TRUE if they are equal or %FALSE otherwise. + * + * In many cases it is unnecessary to use this api and instead + * direct pointer comparisons of entries are good enough and much + * cheaper too. + * + * Return value: %TRUE if @entry0 represents the same transform as + * @entry1, otherwise %FALSE. + */ +CoglBool +cogl_matrix_entry_equal (CoglMatrixEntry *entry0, + CoglMatrixEntry *entry1); + +/** + * cogl_debug_matrix_entry_print: + * @entry: A #CoglMatrixEntry + * + * Allows visualizing the operations that build up the given @entry + * for debugging purposes by printing to stdout. + */ +void +cogl_debug_matrix_entry_print (CoglMatrixEntry *entry); + +/** + * cogl_matrix_entry_ref: + * @entry: A #CoglMatrixEntry + * + * Takes a reference on the given @entry to ensure the @entry stays + * alive and remains valid. When you are finished with the @entry then + * you should call cogl_matrix_entry_unref(). + * + * It is an error to pass an @entry pointer to cogl_object_ref() and + * cogl_object_unref() + */ +CoglMatrixEntry * +cogl_matrix_entry_ref (CoglMatrixEntry *entry); + +/** + * cogl_matrix_entry_unref: + * @entry: A #CoglMatrixEntry + * + * Releases a reference on @entry either taken by calling + * cogl_matrix_entry_unref() or to release the reference given when + * calling cogl_matrix_stack_get_entry(). + */ +void +cogl_matrix_entry_unref (CoglMatrixEntry *entry); + +#endif /* _COGL_MATRIX_STACK_H_ */ diff --git a/cogl/cogl/cogl-matrix.c b/cogl/cogl/cogl-matrix.c new file mode 100644 index 0000000..7c01a0b --- /dev/null +++ b/cogl/cogl/cogl-matrix.c @@ -0,0 +1,2311 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009,2010,2011 Intel Corporation. + * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Robert Bragg + */ +/* + * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Note: a lot of this code is based on code that was taken from Mesa. + * + * Changes compared to the original code from Mesa: + * + * - instead of allocating matrix->m and matrix->inv using malloc, our + * public CoglMatrix typedef is large enough to directly contain the + * matrix, its inverse, a type and a set of flags. + * - instead of having a _cogl_matrix_analyse which updates the type, + * flags and inverse, we have _cogl_matrix_update_inverse which + * essentially does the same thing (internally making use of + * _cogl_matrix_update_type_and_flags()) but with additional guards in + * place to bail out when the inverse matrix is still valid. + * - when initializing a matrix with the identity matrix we don't + * immediately initialize the inverse matrix; rather we just set the + * dirty flag for the inverse (since it's likely the user won't request + * the inverse of the identity matrix) + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +COGL_GTYPE_DEFINE_BOXED (Matrix, matrix, + cogl_matrix_copy, + cogl_matrix_free); + +/* + * Symbolic names to some of the entries in the matrix + * + * These are handy for the viewport mapping, which is expressed as a matrix. + */ +#define MAT_SX 0 +#define MAT_SY 5 +#define MAT_SZ 10 +#define MAT_TX 12 +#define MAT_TY 13 +#define MAT_TZ 14 + +/* + * These identify different kinds of 4x4 transformation matrices and we use + * this information to find fast-paths when available. + */ +enum CoglMatrixType { + COGL_MATRIX_TYPE_GENERAL, /**< general 4x4 matrix */ + COGL_MATRIX_TYPE_IDENTITY, /**< identity matrix */ + COGL_MATRIX_TYPE_3D_NO_ROT, /**< orthogonal projection and others... */ + COGL_MATRIX_TYPE_PERSPECTIVE, /**< perspective projection matrix */ + COGL_MATRIX_TYPE_2D, /**< 2-D transformation */ + COGL_MATRIX_TYPE_2D_NO_ROT, /**< 2-D scale & translate only */ + COGL_MATRIX_TYPE_3D, /**< 3-D transformation */ + COGL_MATRIX_N_TYPES +} ; + +#define DEG2RAD (G_PI/180.0) + +/* Dot product of two 2-element vectors */ +#define DOT2(A,B) ( (A)[0]*(B)[0] + (A)[1]*(B)[1] ) + +/* Dot product of two 3-element vectors */ +#define DOT3(A,B) ( (A)[0]*(B)[0] + (A)[1]*(B)[1] + (A)[2]*(B)[2] ) + +#define CROSS3(N, U, V) \ +do { \ + (N)[0] = (U)[1]*(V)[2] - (U)[2]*(V)[1]; \ + (N)[1] = (U)[2]*(V)[0] - (U)[0]*(V)[2]; \ + (N)[2] = (U)[0]*(V)[1] - (U)[1]*(V)[0]; \ +} while (0) + +#define SUB_3V(DST, SRCA, SRCB) \ +do { \ + (DST)[0] = (SRCA)[0] - (SRCB)[0]; \ + (DST)[1] = (SRCA)[1] - (SRCB)[1]; \ + (DST)[2] = (SRCA)[2] - (SRCB)[2]; \ +} while (0) + +#define LEN_SQUARED_3FV( V ) ((V)[0]*(V)[0]+(V)[1]*(V)[1]+(V)[2]*(V)[2]) + +/* + * \defgroup MatFlags MAT_FLAG_XXX-flags + * + * Bitmasks to indicate different kinds of 4x4 matrices in CoglMatrix::flags + */ +#define MAT_FLAG_IDENTITY 0 /*< is an identity matrix flag. + * (Not actually used - the identity + * matrix is identified by the absense + * of all other flags.) + */ +#define MAT_FLAG_GENERAL 0x1 /*< is a general matrix flag */ +#define MAT_FLAG_ROTATION 0x2 /*< is a rotation matrix flag */ +#define MAT_FLAG_TRANSLATION 0x4 /*< is a translation matrix flag */ +#define MAT_FLAG_UNIFORM_SCALE 0x8 /*< is an uniform scaling matrix flag */ +#define MAT_FLAG_GENERAL_SCALE 0x10 /*< is a general scaling matrix flag */ +#define MAT_FLAG_GENERAL_3D 0x20 /*< general 3D matrix flag */ +#define MAT_FLAG_PERSPECTIVE 0x40 /*< is a perspective proj matrix flag */ +#define MAT_FLAG_SINGULAR 0x80 /*< is a singular matrix flag */ +#define MAT_DIRTY_TYPE 0x100 /*< matrix type is dirty */ +#define MAT_DIRTY_FLAGS 0x200 /*< matrix flags are dirty */ +#define MAT_DIRTY_INVERSE 0x400 /*< matrix inverse is dirty */ + +/* angle preserving matrix flags mask */ +#define MAT_FLAGS_ANGLE_PRESERVING (MAT_FLAG_ROTATION | \ + MAT_FLAG_TRANSLATION | \ + MAT_FLAG_UNIFORM_SCALE) + +/* geometry related matrix flags mask */ +#define MAT_FLAGS_GEOMETRY (MAT_FLAG_GENERAL | \ + MAT_FLAG_ROTATION | \ + MAT_FLAG_TRANSLATION | \ + MAT_FLAG_UNIFORM_SCALE | \ + MAT_FLAG_GENERAL_SCALE | \ + MAT_FLAG_GENERAL_3D | \ + MAT_FLAG_PERSPECTIVE | \ + MAT_FLAG_SINGULAR) + +/* length preserving matrix flags mask */ +#define MAT_FLAGS_LENGTH_PRESERVING (MAT_FLAG_ROTATION | \ + MAT_FLAG_TRANSLATION) + + +/* 3D (non-perspective) matrix flags mask */ +#define MAT_FLAGS_3D (MAT_FLAG_ROTATION | \ + MAT_FLAG_TRANSLATION | \ + MAT_FLAG_UNIFORM_SCALE | \ + MAT_FLAG_GENERAL_SCALE | \ + MAT_FLAG_GENERAL_3D) + +/* dirty matrix flags mask */ +#define MAT_DIRTY_ALL (MAT_DIRTY_TYPE | \ + MAT_DIRTY_FLAGS | \ + MAT_DIRTY_INVERSE) + + +/* + * Test geometry related matrix flags. + * + * @mat a pointer to a CoglMatrix structure. + * @a flags mask. + * + * Returns: non-zero if all geometry related matrix flags are contained within + * the mask, or zero otherwise. + */ +#define TEST_MAT_FLAGS(mat, a) \ + ((MAT_FLAGS_GEOMETRY & (~(a)) & ((mat)->flags) ) == 0) + + + +/* + * Names of the corresponding CoglMatrixType values. + */ +static const char *types[] = { + "COGL_MATRIX_TYPE_GENERAL", + "COGL_MATRIX_TYPE_IDENTITY", + "COGL_MATRIX_TYPE_3D_NO_ROT", + "COGL_MATRIX_TYPE_PERSPECTIVE", + "COGL_MATRIX_TYPE_2D", + "COGL_MATRIX_TYPE_2D_NO_ROT", + "COGL_MATRIX_TYPE_3D" +}; + + +/* + * Identity matrix. + */ +static float identity[16] = { + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0 +}; + + +#define A(row,col) a[(col<<2)+row] +#define B(row,col) b[(col<<2)+row] +#define R(row,col) result[(col<<2)+row] + +/* + * Perform a full 4x4 matrix multiplication. + * + * It's assumed that @result != @b. @product == @a is allowed. + * + * KW: 4*16 = 64 multiplications + */ +static void +matrix_multiply4x4 (float *result, const float *a, const float *b) +{ + int i; + for (i = 0; i < 4; i++) + { + const float ai0 = A(i,0), ai1=A(i,1), ai2=A(i,2), ai3=A(i,3); + R(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0); + R(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1); + R(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2); + R(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3); + } +} + +/* + * Multiply two matrices known to occupy only the top three rows, such + * as typical model matrices, and orthogonal matrices. + * + * @a matrix. + * @b matrix. + * @product will receive the product of \p a and \p b. + */ +static void +matrix_multiply3x4 (float *result, const float *a, const float *b) +{ + int i; + for (i = 0; i < 3; i++) + { + const float ai0 = A(i,0), ai1 = A(i,1), ai2 = A(i,2), ai3 = A(i,3); + R(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0); + R(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1); + R(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2); + R(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3; + } + R(3,0) = 0; + R(3,1) = 0; + R(3,2) = 0; + R(3,3) = 1; +} + +#undef A +#undef B +#undef R + +/* + * Multiply a matrix by an array of floats with known properties. + * + * @mat pointer to a CoglMatrix structure containing the left multiplication + * matrix, and that will receive the product result. + * @m right multiplication matrix array. + * @flags flags of the matrix \p m. + * + * Joins both flags and marks the type and inverse as dirty. Calls + * matrix_multiply3x4() if both matrices are 3D, or matrix_multiply4x4() + * otherwise. + */ +static void +matrix_multiply_array_with_flags (CoglMatrix *result, + const float *array, + unsigned int flags) +{ + result->flags |= (flags | MAT_DIRTY_TYPE | MAT_DIRTY_INVERSE); + + if (TEST_MAT_FLAGS (result, MAT_FLAGS_3D)) + matrix_multiply3x4 ((float *)result, (float *)result, array); + else + matrix_multiply4x4 ((float *)result, (float *)result, array); +} + +/* Joins both flags and marks the type and inverse as dirty. Calls + * matrix_multiply3x4() if both matrices are 3D, or matrix_multiply4x4() + * otherwise. + */ +static void +_cogl_matrix_multiply (CoglMatrix *result, + const CoglMatrix *a, + const CoglMatrix *b) +{ + result->flags = (a->flags | + b->flags | + MAT_DIRTY_TYPE | + MAT_DIRTY_INVERSE); + + if (TEST_MAT_FLAGS(result, MAT_FLAGS_3D)) + matrix_multiply3x4 ((float *)result, (float *)a, (float *)b); + else + matrix_multiply4x4 ((float *)result, (float *)a, (float *)b); +} + +void +cogl_matrix_multiply (CoglMatrix *result, + const CoglMatrix *a, + const CoglMatrix *b) +{ + _cogl_matrix_multiply (result, a, b); + _COGL_MATRIX_DEBUG_PRINT (result); +} + +#if 0 +/* Marks the matrix flags with general flag, and type and inverse dirty flags. + * Calls matrix_multiply4x4() for the multiplication. + */ +static void +_cogl_matrix_multiply_array (CoglMatrix *result, const float *array) +{ + result->flags |= (MAT_FLAG_GENERAL | + MAT_DIRTY_TYPE | + MAT_DIRTY_INVERSE | + MAT_DIRTY_FLAGS); + + matrix_multiply4x4 ((float *)result, (float *)result, (float *)array); +} +#endif + +/* + * Print a matrix array. + * + * Called by _cogl_matrix_print() to print a matrix or its inverse. + */ +static void +print_matrix_floats (const char *prefix, const float m[16]) +{ + int i; + for (i = 0;i < 4; i++) + g_print ("%s\t%f %f %f %f\n", prefix, m[i], m[4+i], m[8+i], m[12+i] ); +} + +void +_cogl_matrix_prefix_print (const char *prefix, const CoglMatrix *matrix) +{ + if (!(matrix->flags & MAT_DIRTY_TYPE)) + { + _COGL_RETURN_IF_FAIL (matrix->type < COGL_MATRIX_N_TYPES); + g_print ("%sMatrix type: %s, flags: %x\n", + prefix, types[matrix->type], (int)matrix->flags); + } + else + g_print ("%sMatrix type: DIRTY, flags: %x\n", + prefix, (int)matrix->flags); + + print_matrix_floats (prefix, (float *)matrix); + g_print ("%sInverse: \n", prefix); + if (!(matrix->flags & MAT_DIRTY_INVERSE)) + { + float prod[16]; + print_matrix_floats (prefix, matrix->inv); + matrix_multiply4x4 (prod, (float *)matrix, matrix->inv); + g_print ("%sMat * Inverse:\n", prefix); + print_matrix_floats (prefix, prod); + } + else + g_print ("%s - not available\n", prefix); +} + +/* + * Dumps the contents of a CoglMatrix structure. + */ +void +cogl_debug_matrix_print (const CoglMatrix *matrix) +{ + _cogl_matrix_prefix_print ("", matrix); +} + +/* + * References an element of 4x4 matrix. + * + * @m matrix array. + * @c column of the desired element. + * @r row of the desired element. + * + * Returns: value of the desired element. + * + * Calculate the linear storage index of the element and references it. + */ +#define MAT(m,r,c) (m)[(c)*4+(r)] + +/* + * Swaps the values of two floating pointer variables. + * + * Used by invert_matrix_general() to swap the row pointers. + */ +#define SWAP_ROWS(a, b) { float *_tmp = a; (a)=(b); (b)=_tmp; } + +/* + * Compute inverse of 4x4 transformation matrix. + * + * @mat pointer to a CoglMatrix structure. The matrix inverse will be + * stored in the CoglMatrix::inv attribute. + * + * Returns: %TRUE for success, %FALSE for failure (\p singular matrix). + * + * \author + * Code contributed by Jacques Leroy jle@star.be + * + * Calculates the inverse matrix by performing the gaussian matrix reduction + * with partial pivoting followed by back/substitution with the loops manually + * unrolled. + */ +static CoglBool +invert_matrix_general (CoglMatrix *matrix) +{ + const float *m = (float *)matrix; + float *out = matrix->inv; + float wtmp[4][8]; + float m0, m1, m2, m3, s; + float *r0, *r1, *r2, *r3; + + r0 = wtmp[0], r1 = wtmp[1], r2 = wtmp[2], r3 = wtmp[3]; + + r0[0] = MAT (m, 0, 0), r0[1] = MAT (m, 0, 1), + r0[2] = MAT (m, 0, 2), r0[3] = MAT (m, 0, 3), + r0[4] = 1.0, r0[5] = r0[6] = r0[7] = 0.0, + + r1[0] = MAT (m, 1, 0), r1[1] = MAT (m, 1, 1), + r1[2] = MAT (m, 1, 2), r1[3] = MAT (m, 1, 3), + r1[5] = 1.0, r1[4] = r1[6] = r1[7] = 0.0, + + r2[0] = MAT (m, 2, 0), r2[1] = MAT (m, 2, 1), + r2[2] = MAT (m, 2, 2), r2[3] = MAT (m, 2, 3), + r2[6] = 1.0, r2[4] = r2[5] = r2[7] = 0.0, + + r3[0] = MAT (m, 3, 0), r3[1] = MAT (m, 3, 1), + r3[2] = MAT (m, 3, 2), r3[3] = MAT (m, 3, 3), + r3[7] = 1.0, r3[4] = r3[5] = r3[6] = 0.0; + + /* choose pivot - or die */ + if (fabsf (r3[0]) > fabsf (r2[0])) + SWAP_ROWS (r3, r2); + if (fabsf (r2[0]) > fabsf (r1[0])) + SWAP_ROWS (r2, r1); + if (fabsf (r1[0]) > fabsf (r0[0])) + SWAP_ROWS (r1, r0); + if (0.0 == r0[0]) + return FALSE; + + /* eliminate first variable */ + m1 = r1[0]/r0[0]; m2 = r2[0]/r0[0]; m3 = r3[0]/r0[0]; + s = r0[1]; r1[1] -= m1 * s; r2[1] -= m2 * s; r3[1] -= m3 * s; + s = r0[2]; r1[2] -= m1 * s; r2[2] -= m2 * s; r3[2] -= m3 * s; + s = r0[3]; r1[3] -= m1 * s; r2[3] -= m2 * s; r3[3] -= m3 * s; + s = r0[4]; + if (s != 0.0) { r1[4] -= m1 * s; r2[4] -= m2 * s; r3[4] -= m3 * s; } + s = r0[5]; + if (s != 0.0) { r1[5] -= m1 * s; r2[5] -= m2 * s; r3[5] -= m3 * s; } + s = r0[6]; + if (s != 0.0) { r1[6] -= m1 * s; r2[6] -= m2 * s; r3[6] -= m3 * s; } + s = r0[7]; + if (s != 0.0) { r1[7] -= m1 * s; r2[7] -= m2 * s; r3[7] -= m3 * s; } + + /* choose pivot - or die */ + if (fabsf (r3[1]) > fabsf (r2[1])) + SWAP_ROWS (r3, r2); + if (fabsf (r2[1]) > fabsf (r1[1])) + SWAP_ROWS (r2, r1); + if (0.0 == r1[1]) + return FALSE; + + /* eliminate second variable */ + m2 = r2[1] / r1[1]; m3 = r3[1] / r1[1]; + r2[2] -= m2 * r1[2]; r3[2] -= m3 * r1[2]; + r2[3] -= m2 * r1[3]; r3[3] -= m3 * r1[3]; + s = r1[4]; if (0.0 != s) { r2[4] -= m2 * s; r3[4] -= m3 * s; } + s = r1[5]; if (0.0 != s) { r2[5] -= m2 * s; r3[5] -= m3 * s; } + s = r1[6]; if (0.0 != s) { r2[6] -= m2 * s; r3[6] -= m3 * s; } + s = r1[7]; if (0.0 != s) { r2[7] -= m2 * s; r3[7] -= m3 * s; } + + /* choose pivot - or die */ + if (fabsf (r3[2]) > fabsf (r2[2])) + SWAP_ROWS (r3, r2); + if (0.0 == r2[2]) + return FALSE; + + /* eliminate third variable */ + m3 = r3[2] / r2[2]; + r3[3] -= m3 * r2[3], r3[4] -= m3 * r2[4], + r3[5] -= m3 * r2[5], r3[6] -= m3 * r2[6], + r3[7] -= m3 * r2[7]; + + /* last check */ + if (0.0 == r3[3]) + return FALSE; + + s = 1.0f / r3[3]; /* now back substitute row 3 */ + r3[4] *= s; r3[5] *= s; r3[6] *= s; r3[7] *= s; + + m2 = r2[3]; /* now back substitute row 2 */ + s = 1.0f / r2[2]; + r2[4] = s * (r2[4] - r3[4] * m2), r2[5] = s * (r2[5] - r3[5] * m2), + r2[6] = s * (r2[6] - r3[6] * m2), r2[7] = s * (r2[7] - r3[7] * m2); + m1 = r1[3]; + r1[4] -= r3[4] * m1, r1[5] -= r3[5] * m1, + r1[6] -= r3[6] * m1, r1[7] -= r3[7] * m1; + m0 = r0[3]; + r0[4] -= r3[4] * m0, r0[5] -= r3[5] * m0, + r0[6] -= r3[6] * m0, r0[7] -= r3[7] * m0; + + m1 = r1[2]; /* now back substitute row 1 */ + s = 1.0f / r1[1]; + r1[4] = s * (r1[4] - r2[4] * m1), r1[5] = s * (r1[5] - r2[5] * m1), + r1[6] = s * (r1[6] - r2[6] * m1), r1[7] = s * (r1[7] - r2[7] * m1); + m0 = r0[2]; + r0[4] -= r2[4] * m0, r0[5] -= r2[5] * m0, + r0[6] -= r2[6] * m0, r0[7] -= r2[7] * m0; + + m0 = r0[1]; /* now back substitute row 0 */ + s = 1.0f / r0[0]; + r0[4] = s * (r0[4] - r1[4] * m0), r0[5] = s * (r0[5] - r1[5] * m0), + r0[6] = s * (r0[6] - r1[6] * m0), r0[7] = s * (r0[7] - r1[7] * m0); + + MAT (out, 0, 0) = r0[4]; MAT (out, 0, 1) = r0[5], + MAT (out, 0, 2) = r0[6]; MAT (out, 0, 3) = r0[7], + MAT (out, 1, 0) = r1[4]; MAT (out, 1, 1) = r1[5], + MAT (out, 1, 2) = r1[6]; MAT (out, 1, 3) = r1[7], + MAT (out, 2, 0) = r2[4]; MAT (out, 2, 1) = r2[5], + MAT (out, 2, 2) = r2[6]; MAT (out, 2, 3) = r2[7], + MAT (out, 3, 0) = r3[4]; MAT (out, 3, 1) = r3[5], + MAT (out, 3, 2) = r3[6]; MAT (out, 3, 3) = r3[7]; + + return TRUE; +} +#undef SWAP_ROWS + +/* + * Compute inverse of a general 3d transformation matrix. + * + * @mat pointer to a CoglMatrix structure. The matrix inverse will be + * stored in the CoglMatrix::inv attribute. + * + * Returns: %TRUE for success, %FALSE for failure (\p singular matrix). + * + * \author Adapted from graphics gems II. + * + * Calculates the inverse of the upper left by first calculating its + * determinant and multiplying it to the symmetric adjust matrix of each + * element. Finally deals with the translation part by transforming the + * original translation vector using by the calculated submatrix inverse. + */ +static CoglBool +invert_matrix_3d_general (CoglMatrix *matrix) +{ + const float *in = (float *)matrix; + float *out = matrix->inv; + float pos, neg, t; + float det; + + /* Calculate the determinant of upper left 3x3 submatrix and + * determine if the matrix is singular. + */ + pos = neg = 0.0; + t = MAT (in,0,0) * MAT (in,1,1) * MAT (in,2,2); + if (t >= 0.0) pos += t; else neg += t; + + t = MAT (in,1,0) * MAT (in,2,1) * MAT (in,0,2); + if (t >= 0.0) pos += t; else neg += t; + + t = MAT (in,2,0) * MAT (in,0,1) * MAT (in,1,2); + if (t >= 0.0) pos += t; else neg += t; + + t = -MAT (in,2,0) * MAT (in,1,1) * MAT (in,0,2); + if (t >= 0.0) pos += t; else neg += t; + + t = -MAT (in,1,0) * MAT (in,0,1) * MAT (in,2,2); + if (t >= 0.0) pos += t; else neg += t; + + t = -MAT (in,0,0) * MAT (in,2,1) * MAT (in,1,2); + if (t >= 0.0) pos += t; else neg += t; + + det = pos + neg; + + if (det*det < 1e-25) + return FALSE; + + det = 1.0f / det; + MAT (out,0,0) = + ( (MAT (in, 1, 1)*MAT (in, 2, 2) - MAT (in, 2, 1)*MAT (in, 1, 2) )*det); + MAT (out,0,1) = + (- (MAT (in, 0, 1)*MAT (in, 2, 2) - MAT (in, 2, 1)*MAT (in, 0, 2) )*det); + MAT (out,0,2) = + ( (MAT (in, 0, 1)*MAT (in, 1, 2) - MAT (in, 1, 1)*MAT (in, 0, 2) )*det); + MAT (out,1,0) = + (- (MAT (in,1,0)*MAT (in,2,2) - MAT (in,2,0)*MAT (in,1,2) )*det); + MAT (out,1,1) = + ( (MAT (in,0,0)*MAT (in,2,2) - MAT (in,2,0)*MAT (in,0,2) )*det); + MAT (out,1,2) = + (- (MAT (in,0,0)*MAT (in,1,2) - MAT (in,1,0)*MAT (in,0,2) )*det); + MAT (out,2,0) = + ( (MAT (in,1,0)*MAT (in,2,1) - MAT (in,2,0)*MAT (in,1,1) )*det); + MAT (out,2,1) = + (- (MAT (in,0,0)*MAT (in,2,1) - MAT (in,2,0)*MAT (in,0,1) )*det); + MAT (out,2,2) = + ( (MAT (in,0,0)*MAT (in,1,1) - MAT (in,1,0)*MAT (in,0,1) )*det); + + /* Do the translation part */ + MAT (out,0,3) = - (MAT (in, 0, 3) * MAT (out, 0, 0) + + MAT (in, 1, 3) * MAT (out, 0, 1) + + MAT (in, 2, 3) * MAT (out, 0, 2) ); + MAT (out,1,3) = - (MAT (in, 0, 3) * MAT (out, 1, 0) + + MAT (in, 1, 3) * MAT (out, 1, 1) + + MAT (in, 2, 3) * MAT (out, 1, 2) ); + MAT (out,2,3) = - (MAT (in, 0, 3) * MAT (out, 2 ,0) + + MAT (in, 1, 3) * MAT (out, 2, 1) + + MAT (in, 2, 3) * MAT (out, 2, 2) ); + + return TRUE; +} + +/* + * Compute inverse of a 3d transformation matrix. + * + * @mat pointer to a CoglMatrix structure. The matrix inverse will be + * stored in the CoglMatrix::inv attribute. + * + * Returns: %TRUE for success, %FALSE for failure (\p singular matrix). + * + * If the matrix is not an angle preserving matrix then calls + * invert_matrix_3d_general for the actual calculation. Otherwise calculates + * the inverse matrix analyzing and inverting each of the scaling, rotation and + * translation parts. + */ +static CoglBool +invert_matrix_3d (CoglMatrix *matrix) +{ + const float *in = (float *)matrix; + float *out = matrix->inv; + + memcpy (out, identity, 16 * sizeof (float)); + + if (!TEST_MAT_FLAGS(matrix, MAT_FLAGS_ANGLE_PRESERVING)) + return invert_matrix_3d_general (matrix); + + if (matrix->flags & MAT_FLAG_UNIFORM_SCALE) + { + float scale = (MAT (in, 0, 0) * MAT (in, 0, 0) + + MAT (in, 0, 1) * MAT (in, 0, 1) + + MAT (in, 0, 2) * MAT (in, 0, 2)); + + if (scale == 0.0) + return FALSE; + + scale = 1.0f / scale; + + /* Transpose and scale the 3 by 3 upper-left submatrix. */ + MAT (out, 0, 0) = scale * MAT (in, 0, 0); + MAT (out, 1, 0) = scale * MAT (in, 0, 1); + MAT (out, 2, 0) = scale * MAT (in, 0, 2); + MAT (out, 0, 1) = scale * MAT (in, 1, 0); + MAT (out, 1, 1) = scale * MAT (in, 1, 1); + MAT (out, 2, 1) = scale * MAT (in, 1, 2); + MAT (out, 0, 2) = scale * MAT (in, 2, 0); + MAT (out, 1, 2) = scale * MAT (in, 2, 1); + MAT (out, 2, 2) = scale * MAT (in, 2, 2); + } + else if (matrix->flags & MAT_FLAG_ROTATION) + { + /* Transpose the 3 by 3 upper-left submatrix. */ + MAT (out, 0, 0) = MAT (in, 0, 0); + MAT (out, 1, 0) = MAT (in, 0, 1); + MAT (out, 2, 0) = MAT (in, 0, 2); + MAT (out, 0, 1) = MAT (in, 1, 0); + MAT (out, 1, 1) = MAT (in, 1, 1); + MAT (out, 2, 1) = MAT (in, 1, 2); + MAT (out, 0, 2) = MAT (in, 2, 0); + MAT (out, 1, 2) = MAT (in, 2, 1); + MAT (out, 2, 2) = MAT (in, 2, 2); + } + else + { + /* pure translation */ + memcpy (out, identity, 16 * sizeof (float)); + MAT (out, 0, 3) = - MAT (in, 0, 3); + MAT (out, 1, 3) = - MAT (in, 1, 3); + MAT (out, 2, 3) = - MAT (in, 2, 3); + return TRUE; + } + + if (matrix->flags & MAT_FLAG_TRANSLATION) + { + /* Do the translation part */ + MAT (out,0,3) = - (MAT (in, 0, 3) * MAT (out, 0, 0) + + MAT (in, 1, 3) * MAT (out, 0, 1) + + MAT (in, 2, 3) * MAT (out, 0, 2) ); + MAT (out,1,3) = - (MAT (in, 0, 3) * MAT (out, 1, 0) + + MAT (in, 1, 3) * MAT (out, 1, 1) + + MAT (in, 2, 3) * MAT (out, 1, 2) ); + MAT (out,2,3) = - (MAT (in, 0, 3) * MAT (out, 2, 0) + + MAT (in, 1, 3) * MAT (out, 2, 1) + + MAT (in, 2, 3) * MAT (out, 2, 2) ); + } + else + MAT (out, 0, 3) = MAT (out, 1, 3) = MAT (out, 2, 3) = 0.0; + + return TRUE; +} + +/* + * Compute inverse of an identity transformation matrix. + * + * @mat pointer to a CoglMatrix structure. The matrix inverse will be + * stored in the CoglMatrix::inv attribute. + * + * Returns: always %TRUE. + * + * Simply copies identity into CoglMatrix::inv. + */ +static CoglBool +invert_matrix_identity (CoglMatrix *matrix) +{ + memcpy (matrix->inv, identity, 16 * sizeof (float)); + return TRUE; +} + +/* + * Compute inverse of a no-rotation 3d transformation matrix. + * + * @mat pointer to a CoglMatrix structure. The matrix inverse will be + * stored in the CoglMatrix::inv attribute. + * + * Returns: %TRUE for success, %FALSE for failure (\p singular matrix). + * + * Calculates the + */ +static CoglBool +invert_matrix_3d_no_rotation (CoglMatrix *matrix) +{ + const float *in = (float *)matrix; + float *out = matrix->inv; + + if (MAT (in,0,0) == 0 || MAT (in,1,1) == 0 || MAT (in,2,2) == 0) + return FALSE; + + memcpy (out, identity, 16 * sizeof (float)); + MAT (out,0,0) = 1.0f / MAT (in,0,0); + MAT (out,1,1) = 1.0f / MAT (in,1,1); + MAT (out,2,2) = 1.0f / MAT (in,2,2); + + if (matrix->flags & MAT_FLAG_TRANSLATION) + { + MAT (out,0,3) = - (MAT (in,0,3) * MAT (out,0,0)); + MAT (out,1,3) = - (MAT (in,1,3) * MAT (out,1,1)); + MAT (out,2,3) = - (MAT (in,2,3) * MAT (out,2,2)); + } + + return TRUE; +} + +/* + * Compute inverse of a no-rotation 2d transformation matrix. + * + * @mat pointer to a CoglMatrix structure. The matrix inverse will be + * stored in the CoglMatrix::inv attribute. + * + * Returns: %TRUE for success, %FALSE for failure (\p singular matrix). + * + * Calculates the inverse matrix by applying the inverse scaling and + * translation to the identity matrix. + */ +static CoglBool +invert_matrix_2d_no_rotation (CoglMatrix *matrix) +{ + const float *in = (float *)matrix; + float *out = matrix->inv; + + if (MAT (in, 0, 0) == 0 || MAT (in, 1, 1) == 0) + return FALSE; + + memcpy (out, identity, 16 * sizeof (float)); + MAT (out, 0, 0) = 1.0f / MAT (in, 0, 0); + MAT (out, 1, 1) = 1.0f / MAT (in, 1, 1); + + if (matrix->flags & MAT_FLAG_TRANSLATION) + { + MAT (out, 0, 3) = - (MAT (in, 0, 3) * MAT (out, 0, 0)); + MAT (out, 1, 3) = - (MAT (in, 1, 3) * MAT (out, 1, 1)); + } + + return TRUE; +} + +#if 0 +/* broken */ +static CoglBool +invert_matrix_perspective (CoglMatrix *matrix) +{ + const float *in = matrix; + float *out = matrix->inv; + + if (MAT (in,2,3) == 0) + return FALSE; + + memcpy( out, identity, 16 * sizeof(float) ); + + MAT (out, 0, 0) = 1.0f / MAT (in, 0, 0); + MAT (out, 1, 1) = 1.0f / MAT (in, 1, 1); + + MAT (out, 0, 3) = MAT (in, 0, 2); + MAT (out, 1, 3) = MAT (in, 1, 2); + + MAT (out,2,2) = 0; + MAT (out,2,3) = -1; + + MAT (out,3,2) = 1.0f / MAT (in,2,3); + MAT (out,3,3) = MAT (in,2,2) * MAT (out,3,2); + + return TRUE; +} +#endif + +/* + * Matrix inversion function pointer type. + */ +typedef CoglBool (*inv_mat_func)(CoglMatrix *matrix); + +/* + * Table of the matrix inversion functions according to the matrix type. + */ +static inv_mat_func inv_mat_tab[7] = { + invert_matrix_general, + invert_matrix_identity, + invert_matrix_3d_no_rotation, +#if 0 + /* Don't use this function for now - it fails when the projection matrix + * is premultiplied by a translation (ala Chromium's tilesort SPU). + */ + invert_matrix_perspective, +#else + invert_matrix_general, +#endif + invert_matrix_3d, /* lazy! */ + invert_matrix_2d_no_rotation, + invert_matrix_3d +}; + +#define ZERO(x) (1<flags &= ~MAT_FLAGS_GEOMETRY; + + /* Check for translation - no-one really cares + */ + if ((mask & MASK_NO_TRX) != MASK_NO_TRX) + matrix->flags |= MAT_FLAG_TRANSLATION; + + /* Do the real work + */ + if (mask == (unsigned int) MASK_IDENTITY) + matrix->type = COGL_MATRIX_TYPE_IDENTITY; + else if ((mask & MASK_2D_NO_ROT) == (unsigned int) MASK_2D_NO_ROT) + { + matrix->type = COGL_MATRIX_TYPE_2D_NO_ROT; + + if ((mask & MASK_NO_2D_SCALE) != MASK_NO_2D_SCALE) + matrix->flags |= MAT_FLAG_GENERAL_SCALE; + } + else if ((mask & MASK_2D) == (unsigned int) MASK_2D) + { + float mm = DOT2 (m, m); + float m4m4 = DOT2 (m+4,m+4); + float mm4 = DOT2 (m,m+4); + + matrix->type = COGL_MATRIX_TYPE_2D; + + /* Check for scale */ + if (SQ (mm-1) > SQ (1e-6) || + SQ (m4m4-1) > SQ (1e-6)) + matrix->flags |= MAT_FLAG_GENERAL_SCALE; + + /* Check for rotation */ + if (SQ (mm4) > SQ (1e-6)) + matrix->flags |= MAT_FLAG_GENERAL_3D; + else + matrix->flags |= MAT_FLAG_ROTATION; + + } + else if ((mask & MASK_3D_NO_ROT) == (unsigned int) MASK_3D_NO_ROT) + { + matrix->type = COGL_MATRIX_TYPE_3D_NO_ROT; + + /* Check for scale */ + if (SQ (m[0]-m[5]) < SQ (1e-6) && + SQ (m[0]-m[10]) < SQ (1e-6)) + { + if (SQ (m[0]-1.0) > SQ (1e-6)) + matrix->flags |= MAT_FLAG_UNIFORM_SCALE; + } + else + matrix->flags |= MAT_FLAG_GENERAL_SCALE; + } + else if ((mask & MASK_3D) == (unsigned int) MASK_3D) + { + float c1 = DOT3 (m,m); + float c2 = DOT3 (m+4,m+4); + float c3 = DOT3 (m+8,m+8); + float d1 = DOT3 (m, m+4); + float cp[3]; + + matrix->type = COGL_MATRIX_TYPE_3D; + + /* Check for scale */ + if (SQ (c1-c2) < SQ (1e-6) && SQ (c1-c3) < SQ (1e-6)) + { + if (SQ (c1-1.0) > SQ (1e-6)) + matrix->flags |= MAT_FLAG_UNIFORM_SCALE; + /* else no scale at all */ + } + else + matrix->flags |= MAT_FLAG_GENERAL_SCALE; + + /* Check for rotation */ + if (SQ (d1) < SQ (1e-6)) + { + CROSS3 ( cp, m, m+4); + SUB_3V ( cp, cp, (m+8)); + if (LEN_SQUARED_3FV(cp) < SQ(1e-6)) + matrix->flags |= MAT_FLAG_ROTATION; + else + matrix->flags |= MAT_FLAG_GENERAL_3D; + } + else + matrix->flags |= MAT_FLAG_GENERAL_3D; /* shear, etc */ + } + else if ((mask & MASK_PERSPECTIVE) == MASK_PERSPECTIVE && m[11]==-1.0f) + { + matrix->type = COGL_MATRIX_TYPE_PERSPECTIVE; + matrix->flags |= MAT_FLAG_GENERAL; + } + else + { + matrix->type = COGL_MATRIX_TYPE_GENERAL; + matrix->flags |= MAT_FLAG_GENERAL; + } +} + +/* + * Analyze a matrix given that its flags are accurate. + * + * This is the more common operation, hopefully. + */ +static void +analyse_from_flags (CoglMatrix *matrix) +{ + const float *m = (float *)matrix; + + if (TEST_MAT_FLAGS(matrix, 0)) + matrix->type = COGL_MATRIX_TYPE_IDENTITY; + else if (TEST_MAT_FLAGS(matrix, (MAT_FLAG_TRANSLATION | + MAT_FLAG_UNIFORM_SCALE | + MAT_FLAG_GENERAL_SCALE))) + { + if ( m[10] == 1.0f && m[14] == 0.0f ) + matrix->type = COGL_MATRIX_TYPE_2D_NO_ROT; + else + matrix->type = COGL_MATRIX_TYPE_3D_NO_ROT; + } + else if (TEST_MAT_FLAGS (matrix, MAT_FLAGS_3D)) + { + if ( m[ 8]==0.0f + && m[ 9]==0.0f + && m[2]==0.0f && m[6]==0.0f && m[10]==1.0f && m[14]==0.0f) + { + matrix->type = COGL_MATRIX_TYPE_2D; + } + else + matrix->type = COGL_MATRIX_TYPE_3D; + } + else if ( m[4]==0.0f && m[12]==0.0f + && m[1]==0.0f && m[13]==0.0f + && m[2]==0.0f && m[6]==0.0f + && m[3]==0.0f && m[7]==0.0f && m[11]==-1.0f && m[15]==0.0f) + { + matrix->type = COGL_MATRIX_TYPE_PERSPECTIVE; + } + else + matrix->type = COGL_MATRIX_TYPE_GENERAL; +} + +/* + * Analyze and update the type and flags of a matrix. + * + * If the matrix type is dirty then calls either analyse_from_scratch() or + * analyse_from_flags() to determine its type, according to whether the flags + * are dirty or not, respectively. If the matrix has an inverse and it's dirty + * then calls matrix_invert(). Finally clears the dirty flags. + */ +static void +_cogl_matrix_update_type_and_flags (CoglMatrix *matrix) +{ + if (matrix->flags & MAT_DIRTY_TYPE) + { + if (matrix->flags & MAT_DIRTY_FLAGS) + analyse_from_scratch (matrix); + else + analyse_from_flags (matrix); + } + + matrix->flags &= ~(MAT_DIRTY_FLAGS | MAT_DIRTY_TYPE); +} + +/* + * Compute inverse of a transformation matrix. + * + * @mat pointer to a CoglMatrix structure. The matrix inverse will be + * stored in the CoglMatrix::inv attribute. + * + * Returns: %TRUE for success, %FALSE for failure (\p singular matrix). + * + * Calls the matrix inversion function in inv_mat_tab corresponding to the + * given matrix type. In case of failure, updates the MAT_FLAG_SINGULAR flag, + * and copies the identity matrix into CoglMatrix::inv. + */ +static CoglBool +_cogl_matrix_update_inverse (CoglMatrix *matrix) +{ + if (matrix->flags & MAT_DIRTY_FLAGS || + matrix->flags & MAT_DIRTY_INVERSE) + { + _cogl_matrix_update_type_and_flags (matrix); + + if (inv_mat_tab[matrix->type](matrix)) + matrix->flags &= ~MAT_FLAG_SINGULAR; + else + { + matrix->flags |= MAT_FLAG_SINGULAR; + memcpy (matrix->inv, identity, 16 * sizeof (float)); + } + + matrix->flags &= ~MAT_DIRTY_INVERSE; + } + + if (matrix->flags & MAT_FLAG_SINGULAR) + return FALSE; + else + return TRUE; +} + +CoglBool +cogl_matrix_get_inverse (const CoglMatrix *matrix, CoglMatrix *inverse) +{ + if (_cogl_matrix_update_inverse ((CoglMatrix *)matrix)) + { + cogl_matrix_init_from_array (inverse, matrix->inv); + return TRUE; + } + else + { + cogl_matrix_init_identity (inverse); + return FALSE; + } +} + +/* + * Generate a 4x4 transformation matrix from glRotate parameters, and + * post-multiply the input matrix by it. + * + * \author + * This function was contributed by Erich Boleyn (erich@uruk.org). + * Optimizations contributed by Rudolf Opalla (rudi@khm.de). + */ +static void +_cogl_matrix_rotate (CoglMatrix *matrix, + float angle, + float x, + float y, + float z) +{ + float xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c, s, c; + float m[16]; + CoglBool optimized; + + s = sinf (angle * DEG2RAD); + c = cosf (angle * DEG2RAD); + + memcpy (m, identity, 16 * sizeof (float)); + optimized = FALSE; + +#define M(row,col) m[col*4+row] + + if (x == 0.0f) + { + if (y == 0.0f) + { + if (z != 0.0f) + { + optimized = TRUE; + /* rotate only around z-axis */ + M (0,0) = c; + M (1,1) = c; + if (z < 0.0f) + { + M (0,1) = s; + M (1,0) = -s; + } + else + { + M (0,1) = -s; + M (1,0) = s; + } + } + } + else if (z == 0.0f) + { + optimized = TRUE; + /* rotate only around y-axis */ + M (0,0) = c; + M (2,2) = c; + if (y < 0.0f) + { + M (0,2) = -s; + M (2,0) = s; + } + else + { + M (0,2) = s; + M (2,0) = -s; + } + } + } + else if (y == 0.0f) + { + if (z == 0.0f) + { + optimized = TRUE; + /* rotate only around x-axis */ + M (1,1) = c; + M (2,2) = c; + if (x < 0.0f) + { + M (1,2) = s; + M (2,1) = -s; + } + else + { + M (1,2) = -s; + M (2,1) = s; + } + } + } + + if (!optimized) + { + const float mag = sqrtf (x * x + y * y + z * z); + + if (mag <= 1.0e-4) + { + /* no rotation, leave mat as-is */ + return; + } + + x /= mag; + y /= mag; + z /= mag; + + + /* + * Arbitrary axis rotation matrix. + * + * This is composed of 5 matrices, Rz, Ry, T, Ry', Rz', multiplied + * like so: Rz * Ry * T * Ry' * Rz'. T is the final rotation + * (which is about the X-axis), and the two composite transforms + * Ry' * Rz' and Rz * Ry are (respectively) the rotations necessary + * from the arbitrary axis to the X-axis then back. They are + * all elementary rotations. + * + * Rz' is a rotation about the Z-axis, to bring the axis vector + * into the x-z plane. Then Ry' is applied, rotating about the + * Y-axis to bring the axis vector parallel with the X-axis. The + * rotation about the X-axis is then performed. Ry and Rz are + * simply the respective inverse transforms to bring the arbitrary + * axis back to it's original orientation. The first transforms + * Rz' and Ry' are considered inverses, since the data from the + * arbitrary axis gives you info on how to get to it, not how + * to get away from it, and an inverse must be applied. + * + * The basic calculation used is to recognize that the arbitrary + * axis vector (x, y, z), since it is of unit length, actually + * represents the sines and cosines of the angles to rotate the + * X-axis to the same orientation, with theta being the angle about + * Z and phi the angle about Y (in the order described above) + * as follows: + * + * cos ( theta ) = x / sqrt ( 1 - z^2 ) + * sin ( theta ) = y / sqrt ( 1 - z^2 ) + * + * cos ( phi ) = sqrt ( 1 - z^2 ) + * sin ( phi ) = z + * + * Note that cos ( phi ) can further be inserted to the above + * formulas: + * + * cos ( theta ) = x / cos ( phi ) + * sin ( theta ) = y / sin ( phi ) + * + * ...etc. Because of those relations and the standard trigonometric + * relations, it is pssible to reduce the transforms down to what + * is used below. It may be that any primary axis chosen will give the + * same results (modulo a sign convention) using thie method. + * + * Particularly nice is to notice that all divisions that might + * have caused trouble when parallel to certain planes or + * axis go away with care paid to reducing the expressions. + * After checking, it does perform correctly under all cases, since + * in all the cases of division where the denominator would have + * been zero, the numerator would have been zero as well, giving + * the expected result. + */ + + xx = x * x; + yy = y * y; + zz = z * z; + xy = x * y; + yz = y * z; + zx = z * x; + xs = x * s; + ys = y * s; + zs = z * s; + one_c = 1.0f - c; + + /* We already hold the identity-matrix so we can skip some statements */ + M (0,0) = (one_c * xx) + c; + M (0,1) = (one_c * xy) - zs; + M (0,2) = (one_c * zx) + ys; + /* M (0,3) = 0.0f; */ + + M (1,0) = (one_c * xy) + zs; + M (1,1) = (one_c * yy) + c; + M (1,2) = (one_c * yz) - xs; + /* M (1,3) = 0.0f; */ + + M (2,0) = (one_c * zx) - ys; + M (2,1) = (one_c * yz) + xs; + M (2,2) = (one_c * zz) + c; + /* M (2,3) = 0.0f; */ + + /* + M (3,0) = 0.0f; + M (3,1) = 0.0f; + M (3,2) = 0.0f; + M (3,3) = 1.0f; + */ + } +#undef M + + matrix_multiply_array_with_flags (matrix, m, MAT_FLAG_ROTATION); +} + +void +cogl_matrix_rotate (CoglMatrix *matrix, + float angle, + float x, + float y, + float z) +{ + _cogl_matrix_rotate (matrix, angle, x, y, z); + _COGL_MATRIX_DEBUG_PRINT (matrix); +} + +void +cogl_matrix_rotate_quaternion (CoglMatrix *matrix, + const CoglQuaternion *quaternion) +{ + CoglMatrix rotation_transform; + + cogl_matrix_init_from_quaternion (&rotation_transform, quaternion); + cogl_matrix_multiply (matrix, matrix, &rotation_transform); +} + +void +cogl_matrix_rotate_euler (CoglMatrix *matrix, + const CoglEuler *euler) +{ + CoglMatrix rotation_transform; + + cogl_matrix_init_from_euler (&rotation_transform, euler); + cogl_matrix_multiply (matrix, matrix, &rotation_transform); +} + +/* + * Apply a perspective projection matrix. + * + * Creates the projection matrix and multiplies it with matrix, marking the + * MAT_FLAG_PERSPECTIVE flag. + */ +static void +_cogl_matrix_frustum (CoglMatrix *matrix, + float left, + float right, + float bottom, + float top, + float nearval, + float farval) +{ + float x, y, a, b, c, d; + float m[16]; + + x = (2.0f * nearval) / (right - left); + y = (2.0f * nearval) / (top - bottom); + a = (right + left) / (right - left); + b = (top + bottom) / (top - bottom); + c = -(farval + nearval) / ( farval - nearval); + d = -(2.0f * farval * nearval) / (farval - nearval); /* error? */ + +#define M(row,col) m[col*4+row] + M (0,0) = x; M (0,1) = 0.0f; M (0,2) = a; M (0,3) = 0.0f; + M (1,0) = 0.0f; M (1,1) = y; M (1,2) = b; M (1,3) = 0.0f; + M (2,0) = 0.0f; M (2,1) = 0.0f; M (2,2) = c; M (2,3) = d; + M (3,0) = 0.0f; M (3,1) = 0.0f; M (3,2) = -1.0f; M (3,3) = 0.0f; +#undef M + + matrix_multiply_array_with_flags (matrix, m, MAT_FLAG_PERSPECTIVE); +} + +void +cogl_matrix_frustum (CoglMatrix *matrix, + float left, + float right, + float bottom, + float top, + float z_near, + float z_far) +{ + _cogl_matrix_frustum (matrix, left, right, bottom, top, z_near, z_far); + _COGL_MATRIX_DEBUG_PRINT (matrix); +} + +void +cogl_matrix_perspective (CoglMatrix *matrix, + float fov_y, + float aspect, + float z_near, + float z_far) +{ + float ymax = z_near * tan (fov_y * G_PI / 360.0); + + cogl_matrix_frustum (matrix, + -ymax * aspect, /* left */ + ymax * aspect, /* right */ + -ymax, /* bottom */ + ymax, /* top */ + z_near, + z_far); + _COGL_MATRIX_DEBUG_PRINT (matrix); +} + +/* + * Apply an orthographic projection matrix. + * + * Creates the projection matrix and multiplies it with matrix, marking the + * MAT_FLAG_GENERAL_SCALE and MAT_FLAG_TRANSLATION flags. + */ +static void +_cogl_matrix_orthographic (CoglMatrix *matrix, + float x_1, + float y_1, + float x_2, + float y_2, + float nearval, + float farval) +{ + float m[16]; + +#define M(row, col) m[col * 4 + row] + M (0,0) = 2.0f / (x_2 - x_1); + M (0,1) = 0.0f; + M (0,2) = 0.0f; + M (0,3) = -(x_2 + x_1) / (x_2 - x_1); + + M (1,0) = 0.0f; + M (1,1) = 2.0f / (y_1 - y_2); + M (1,2) = 0.0f; + M (1,3) = -(y_1 + y_2) / (y_1 - y_2); + + M (2,0) = 0.0f; + M (2,1) = 0.0f; + M (2,2) = -2.0f / (farval - nearval); + M (2,3) = -(farval + nearval) / (farval - nearval); + + M (3,0) = 0.0f; + M (3,1) = 0.0f; + M (3,2) = 0.0f; + M (3,3) = 1.0f; +#undef M + + matrix_multiply_array_with_flags (matrix, m, + (MAT_FLAG_GENERAL_SCALE | + MAT_FLAG_TRANSLATION)); +} + +void +cogl_matrix_ortho (CoglMatrix *matrix, + float left, + float right, + float bottom, + float top, + float near, + float far) +{ + _cogl_matrix_orthographic (matrix, left, top, right, bottom, near, far); + _COGL_MATRIX_DEBUG_PRINT (matrix); +} + +void +cogl_matrix_orthographic (CoglMatrix *matrix, + float x_1, + float y_1, + float x_2, + float y_2, + float near, + float far) +{ + _cogl_matrix_orthographic (matrix, x_1, y_1, x_2, y_2, near, far); + _COGL_MATRIX_DEBUG_PRINT (matrix); +} + +/* + * Multiply a matrix with a general scaling matrix. + * + * Multiplies in-place the elements of matrix by the scale factors. Checks if + * the scales factors are roughly the same, marking the MAT_FLAG_UNIFORM_SCALE + * flag, or MAT_FLAG_GENERAL_SCALE. Marks the MAT_DIRTY_TYPE and + * MAT_DIRTY_INVERSE dirty flags. + */ +static void +_cogl_matrix_scale (CoglMatrix *matrix, float x, float y, float z) +{ + float *m = (float *)matrix; + m[0] *= x; m[4] *= y; m[8] *= z; + m[1] *= x; m[5] *= y; m[9] *= z; + m[2] *= x; m[6] *= y; m[10] *= z; + m[3] *= x; m[7] *= y; m[11] *= z; + + if (fabsf (x - y) < 1e-8 && fabsf (x - z) < 1e-8) + matrix->flags |= MAT_FLAG_UNIFORM_SCALE; + else + matrix->flags |= MAT_FLAG_GENERAL_SCALE; + + matrix->flags |= (MAT_DIRTY_TYPE | MAT_DIRTY_INVERSE); +} + +void +cogl_matrix_scale (CoglMatrix *matrix, + float sx, + float sy, + float sz) +{ + _cogl_matrix_scale (matrix, sx, sy, sz); + _COGL_MATRIX_DEBUG_PRINT (matrix); +} + +/* + * Multiply a matrix with a translation matrix. + * + * Adds the translation coordinates to the elements of matrix in-place. Marks + * the MAT_FLAG_TRANSLATION flag, and the MAT_DIRTY_TYPE and MAT_DIRTY_INVERSE + * dirty flags. + */ +static void +_cogl_matrix_translate (CoglMatrix *matrix, float x, float y, float z) +{ + float *m = (float *)matrix; + m[12] = m[0] * x + m[4] * y + m[8] * z + m[12]; + m[13] = m[1] * x + m[5] * y + m[9] * z + m[13]; + m[14] = m[2] * x + m[6] * y + m[10] * z + m[14]; + m[15] = m[3] * x + m[7] * y + m[11] * z + m[15]; + + matrix->flags |= (MAT_FLAG_TRANSLATION | + MAT_DIRTY_TYPE | + MAT_DIRTY_INVERSE); +} + +void +cogl_matrix_translate (CoglMatrix *matrix, + float x, + float y, + float z) +{ + _cogl_matrix_translate (matrix, x, y, z); + _COGL_MATRIX_DEBUG_PRINT (matrix); +} + +#if 0 +/* + * Set matrix to do viewport and depthrange mapping. + * Transforms Normalized Device Coords to window/Z values. + */ +static void +_cogl_matrix_viewport (CoglMatrix *matrix, + float x, float y, + float width, float height, + float zNear, float zFar, float depthMax) +{ + float *m = (float *)matrix; + m[MAT_SX] = width / 2.0f; + m[MAT_TX] = m[MAT_SX] + x; + m[MAT_SY] = height / 2.0f; + m[MAT_TY] = m[MAT_SY] + y; + m[MAT_SZ] = depthMax * ((zFar - zNear) / 2.0f); + m[MAT_TZ] = depthMax * ((zFar - zNear) / 2.0f + zNear); + matrix->flags = MAT_FLAG_GENERAL_SCALE | MAT_FLAG_TRANSLATION; + matrix->type = COGL_MATRIX_TYPE_3D_NO_ROT; +} +#endif + +/* + * Set a matrix to the identity matrix. + * + * @mat matrix. + * + * Copies ::identity into \p CoglMatrix::m, and into CoglMatrix::inv if + * not NULL. Sets the matrix type to identity, resets the flags. It + * doesn't initialize the inverse matrix, it just marks it dirty. + */ +static void +_cogl_matrix_init_identity (CoglMatrix *matrix) +{ + memcpy (matrix, identity, 16 * sizeof (float)); + + matrix->type = COGL_MATRIX_TYPE_IDENTITY; + matrix->flags = MAT_DIRTY_INVERSE; +} + +void +cogl_matrix_init_identity (CoglMatrix *matrix) +{ + _cogl_matrix_init_identity (matrix); + _COGL_MATRIX_DEBUG_PRINT (matrix); +} + +/* + * Set a matrix to the (tx, ty, tz) translation matrix. + * + * @matix matrix. + * @tx x coordinate of the translation vector + * @ty y coordinate of the translation vector + * @tz z coordinate of the translation vector + */ +static void +_cogl_matrix_init_translation (CoglMatrix *matrix, + float tx, + float ty, + float tz) +{ + memcpy (matrix, identity, 16 * sizeof (float)); + + matrix->xw = tx; + matrix->yw = ty; + matrix->zw = tz; + + matrix->type = COGL_MATRIX_TYPE_3D; + matrix->flags = MAT_FLAG_TRANSLATION | MAT_DIRTY_INVERSE; +} + +void +cogl_matrix_init_translation (CoglMatrix *matrix, + float tx, + float ty, + float tz) +{ + _cogl_matrix_init_translation (matrix, tx, ty, tz); + _COGL_MATRIX_DEBUG_PRINT (matrix); +} + +#if 0 +/* + * Test if the given matrix preserves vector lengths. + */ +static CoglBool +_cogl_matrix_is_length_preserving (const CoglMatrix *m) +{ + return TEST_MAT_FLAGS (m, MAT_FLAGS_LENGTH_PRESERVING); +} + +/* + * Test if the given matrix does any rotation. + * (or perhaps if the upper-left 3x3 is non-identity) + */ +static CoglBool +_cogl_matrix_has_rotation (const CoglMatrix *matrix) +{ + if (matrix->flags & (MAT_FLAG_GENERAL | + MAT_FLAG_ROTATION | + MAT_FLAG_GENERAL_3D | + MAT_FLAG_PERSPECTIVE)) + return TRUE; + else + return FALSE; +} + +static CoglBool +_cogl_matrix_is_general_scale (const CoglMatrix *matrix) +{ + return (matrix->flags & MAT_FLAG_GENERAL_SCALE) ? TRUE : FALSE; +} + +static CoglBool +_cogl_matrix_is_dirty (const CoglMatrix *matrix) +{ + return (matrix->flags & MAT_DIRTY_ALL) ? TRUE : FALSE; +} +#endif + +/* + * Loads a matrix array into CoglMatrix. + * + * @m matrix array. + * @mat matrix. + * + * Copies \p m into CoglMatrix::m and marks the MAT_FLAG_GENERAL and + * MAT_DIRTY_ALL + * flags. + */ +static void +_cogl_matrix_init_from_array (CoglMatrix *matrix, const float *array) +{ + memcpy (matrix, array, 16 * sizeof (float)); + matrix->flags = (MAT_FLAG_GENERAL | MAT_DIRTY_ALL); +} + +void +cogl_matrix_init_from_array (CoglMatrix *matrix, const float *array) +{ + _cogl_matrix_init_from_array (matrix, array); + _COGL_MATRIX_DEBUG_PRINT (matrix); +} + +void +_cogl_matrix_init_from_matrix_without_inverse (CoglMatrix *matrix, + const CoglMatrix *src) +{ + memcpy (matrix, src, 16 * sizeof (float)); + matrix->type = src->type; + matrix->flags = src->flags | MAT_DIRTY_INVERSE; +} + +static void +_cogl_matrix_init_from_quaternion (CoglMatrix *matrix, + const CoglQuaternion *quaternion) +{ + float qnorm = _COGL_QUATERNION_NORM (quaternion); + float s = (qnorm > 0.0f) ? (2.0f / qnorm) : 0.0f; + float xs = quaternion->x * s; + float ys = quaternion->y * s; + float zs = quaternion->z * s; + float wx = quaternion->w * xs; + float wy = quaternion->w * ys; + float wz = quaternion->w * zs; + float xx = quaternion->x * xs; + float xy = quaternion->x * ys; + float xz = quaternion->x * zs; + float yy = quaternion->y * ys; + float yz = quaternion->y * zs; + float zz = quaternion->z * zs; + + matrix->xx = 1.0f - (yy + zz); + matrix->yx = xy + wz; + matrix->zx = xz - wy; + matrix->xy = xy - wz; + matrix->yy = 1.0f - (xx + zz); + matrix->zy = yz + wx; + matrix->xz = xz + wy; + matrix->yz = yz - wx; + matrix->zz = 1.0f - (xx + yy); + matrix->xw = matrix->yw = matrix->zw = 0.0f; + matrix->wx = matrix->wy = matrix->wz = 0.0f; + matrix->ww = 1.0f; + + matrix->flags = (MAT_FLAG_GENERAL | MAT_DIRTY_ALL); +} + +void +cogl_matrix_init_from_quaternion (CoglMatrix *matrix, + const CoglQuaternion *quaternion) +{ + _cogl_matrix_init_from_quaternion (matrix, quaternion); +} + +void +cogl_matrix_init_from_euler (CoglMatrix *matrix, + const CoglEuler *euler) +{ + /* Convert angles to radians */ + float heading_rad = euler->heading / 180.0f * G_PI; + float pitch_rad = euler->pitch / 180.0f * G_PI; + float roll_rad = euler->roll / 180.0f * G_PI; + /* Pre-calculate the sin and cos */ + float sin_heading = sinf (heading_rad); + float cos_heading = cosf (heading_rad); + float sin_pitch = sinf (pitch_rad); + float cos_pitch = cosf (pitch_rad); + float sin_roll = sinf (roll_rad); + float cos_roll = cosf (roll_rad); + + /* These calculations are based on the following website but they + * use a different order for the rotations so it has been modified + * slightly. + * http://www.euclideanspace.com/maths/geometry/ + * rotations/conversions/eulerToMatrix/index.htm + */ + + /* Heading rotation x=0, y=1, z=0 gives: + * + * [ ch 0 sh 0 ] + * [ 0 1 0 0 ] + * [ -sh 0 ch 0 ] + * [ 0 0 0 1 ] + * + * Pitch rotation x=1, y=0, z=0 gives: + * [ 1 0 0 0 ] + * [ 0 cp -sp 0 ] + * [ 0 sp cp 0 ] + * [ 0 0 0 1 ] + * + * Roll rotation x=0, y=0, z=1 gives: + * [ cr -sr 0 0 ] + * [ sr cr 0 0 ] + * [ 0 0 1 0 ] + * [ 0 0 0 1 ] + * + * Heading matrix * pitch matrix = + * [ ch sh*sp cp*sh 0 ] + * [ 0 cp -sp 0 ] + * [ -sh ch*sp ch*cp 0 ] + * [ 0 0 0 1 ] + * + * That matrix * roll matrix = + * [ ch*cr + sh*sp*sr sh*sp*cr - ch*sr sh*cp 0 ] + * [ cp*sr cp*cr -sp 0 ] + * [ ch*sp*sr - sh*cr sh*sr + ch*sp*cr ch*cp 0 ] + * [ 0 0 0 1 ] + */ + + matrix->xx = cos_heading * cos_roll + sin_heading * sin_pitch * sin_roll; + matrix->yx = cos_pitch * sin_roll; + matrix->zx = cos_heading * sin_pitch * sin_roll - sin_heading * cos_roll; + matrix->wx = 0.0f; + + matrix->xy = sin_heading * sin_pitch * cos_roll - cos_heading * sin_roll; + matrix->yy = cos_pitch * cos_roll; + matrix->zy = sin_heading * sin_roll + cos_heading * sin_pitch * cos_roll; + matrix->wy = 0.0f; + + matrix->xz = sin_heading * cos_pitch; + matrix->yz = -sin_pitch; + matrix->zz = cos_heading * cos_pitch; + matrix->wz = 0; + + matrix->xw = 0; + matrix->yw = 0; + matrix->zw = 0; + matrix->ww = 1; + + matrix->flags = (MAT_FLAG_GENERAL | MAT_DIRTY_ALL); +} + +/* + * Transpose a float matrix. + */ +static void +_cogl_matrix_util_transposef (float to[16], const float from[16]) +{ + to[0] = from[0]; + to[1] = from[4]; + to[2] = from[8]; + to[3] = from[12]; + to[4] = from[1]; + to[5] = from[5]; + to[6] = from[9]; + to[7] = from[13]; + to[8] = from[2]; + to[9] = from[6]; + to[10] = from[10]; + to[11] = from[14]; + to[12] = from[3]; + to[13] = from[7]; + to[14] = from[11]; + to[15] = from[15]; +} + +void +cogl_matrix_view_2d_in_frustum (CoglMatrix *matrix, + float left, + float right, + float bottom, + float top, + float z_near, + float z_2d, + float width_2d, + float height_2d) +{ + float left_2d_plane = left / z_near * z_2d; + float right_2d_plane = right / z_near * z_2d; + float bottom_2d_plane = bottom / z_near * z_2d; + float top_2d_plane = top / z_near * z_2d; + + float width_2d_start = right_2d_plane - left_2d_plane; + float height_2d_start = top_2d_plane - bottom_2d_plane; + + /* Factors to scale from framebuffer geometry to frustum + * cross-section geometry. */ + float width_scale = width_2d_start / width_2d; + float height_scale = height_2d_start / height_2d; + + cogl_matrix_translate (matrix, + left_2d_plane, top_2d_plane, -z_2d); + + cogl_matrix_scale (matrix, width_scale, -height_scale, width_scale); +} + +/* Assuming a symmetric perspective matrix is being used for your + * projective transform this convenience function lets you compose a + * view transform such that geometry on the z=0 plane will map to + * screen coordinates with a top left origin of (0,0) and with the + * given width and height. + */ +void +cogl_matrix_view_2d_in_perspective (CoglMatrix *matrix, + float fov_y, + float aspect, + float z_near, + float z_2d, + float width_2d, + float height_2d) +{ + float top = z_near * tan (fov_y * G_PI / 360.0); + cogl_matrix_view_2d_in_frustum (matrix, + -top * aspect, + top * aspect, + -top, + top, + z_near, + z_2d, + width_2d, + height_2d); +} + +CoglBool +cogl_matrix_equal (const void *v1, const void *v2) +{ + const CoglMatrix *a = v1; + const CoglMatrix *b = v2; + + _COGL_RETURN_VAL_IF_FAIL (v1 != NULL, FALSE); + _COGL_RETURN_VAL_IF_FAIL (v2 != NULL, FALSE); + + /* We want to avoid having a fuzzy _equal() function (e.g. that uses + * an arbitrary epsilon value) since this function noteably conforms + * to the prototype suitable for use with g_hash_table_new() and a + * fuzzy hash function isn't really appropriate for comparing hash + * table keys since it's possible that you could end up fetching + * different values if you end up with multiple similar keys in use + * at the same time. If you consider that fuzzyness allows cases + * such as A == B == C but A != C then you could also end up loosing + * values in a hash table. + * + * We do at least use the == operator to compare values though so + * that -0 is considered equal to 0. + */ + + /* XXX: We don't compare the flags, inverse matrix or padding */ + if (a->xx == b->xx && + a->xy == b->xy && + a->xz == b->xz && + a->xw == b->xw && + a->yx == b->yx && + a->yy == b->yy && + a->yz == b->yz && + a->yw == b->yw && + a->zx == b->zx && + a->zy == b->zy && + a->zz == b->zz && + a->zw == b->zw && + a->wx == b->wx && + a->wy == b->wy && + a->wz == b->wz && + a->ww == b->ww) + return TRUE; + else + return FALSE; +} + +CoglMatrix * +cogl_matrix_copy (const CoglMatrix *matrix) +{ + if (G_LIKELY (matrix)) + return g_slice_dup (CoglMatrix, matrix); + + return NULL; +} + +void +cogl_matrix_free (CoglMatrix *matrix) +{ + g_slice_free (CoglMatrix, matrix); +} + +const float * +cogl_matrix_get_array (const CoglMatrix *matrix) +{ + return (float *)matrix; +} + +void +cogl_matrix_transform_point (const CoglMatrix *matrix, + float *x, + float *y, + float *z, + float *w) +{ + float _x = *x, _y = *y, _z = *z, _w = *w; + + *x = matrix->xx * _x + matrix->xy * _y + matrix->xz * _z + matrix->xw * _w; + *y = matrix->yx * _x + matrix->yy * _y + matrix->yz * _z + matrix->yw * _w; + *z = matrix->zx * _x + matrix->zy * _y + matrix->zz * _z + matrix->zw * _w; + *w = matrix->wx * _x + matrix->wy * _y + matrix->wz * _z + matrix->ww * _w; +} + +typedef struct _Point2f +{ + float x; + float y; +} Point2f; + +typedef struct _Point3f +{ + float x; + float y; + float z; +} Point3f; + +typedef struct _Point4f +{ + float x; + float y; + float z; + float w; +} Point4f; + +static void +_cogl_matrix_transform_points_f2 (const CoglMatrix *matrix, + size_t stride_in, + const void *points_in, + size_t stride_out, + void *points_out, + int n_points) +{ + int i; + + for (i = 0; i < n_points; i++) + { + Point2f p = *(Point2f *)((uint8_t *)points_in + i * stride_in); + Point3f *o = (Point3f *)((uint8_t *)points_out + i * stride_out); + + o->x = matrix->xx * p.x + matrix->xy * p.y + matrix->xw; + o->y = matrix->yx * p.x + matrix->yy * p.y + matrix->yw; + o->z = matrix->zx * p.x + matrix->zy * p.y + matrix->zw; + } +} + +static void +_cogl_matrix_project_points_f2 (const CoglMatrix *matrix, + size_t stride_in, + const void *points_in, + size_t stride_out, + void *points_out, + int n_points) +{ + int i; + + for (i = 0; i < n_points; i++) + { + Point2f p = *(Point2f *)((uint8_t *)points_in + i * stride_in); + Point4f *o = (Point4f *)((uint8_t *)points_out + i * stride_out); + + o->x = matrix->xx * p.x + matrix->xy * p.y + matrix->xw; + o->y = matrix->yx * p.x + matrix->yy * p.y + matrix->yw; + o->z = matrix->zx * p.x + matrix->zy * p.y + matrix->zw; + o->w = matrix->wx * p.x + matrix->wy * p.y + matrix->ww; + } +} + +static void +_cogl_matrix_transform_points_f3 (const CoglMatrix *matrix, + size_t stride_in, + const void *points_in, + size_t stride_out, + void *points_out, + int n_points) +{ + int i; + + for (i = 0; i < n_points; i++) + { + Point3f p = *(Point3f *)((uint8_t *)points_in + i * stride_in); + Point3f *o = (Point3f *)((uint8_t *)points_out + i * stride_out); + + o->x = matrix->xx * p.x + matrix->xy * p.y + + matrix->xz * p.z + matrix->xw; + o->y = matrix->yx * p.x + matrix->yy * p.y + + matrix->yz * p.z + matrix->yw; + o->z = matrix->zx * p.x + matrix->zy * p.y + + matrix->zz * p.z + matrix->zw; + } +} + +static void +_cogl_matrix_project_points_f3 (const CoglMatrix *matrix, + size_t stride_in, + const void *points_in, + size_t stride_out, + void *points_out, + int n_points) +{ + int i; + + for (i = 0; i < n_points; i++) + { + Point3f p = *(Point3f *)((uint8_t *)points_in + i * stride_in); + Point4f *o = (Point4f *)((uint8_t *)points_out + i * stride_out); + + o->x = matrix->xx * p.x + matrix->xy * p.y + + matrix->xz * p.z + matrix->xw; + o->y = matrix->yx * p.x + matrix->yy * p.y + + matrix->yz * p.z + matrix->yw; + o->z = matrix->zx * p.x + matrix->zy * p.y + + matrix->zz * p.z + matrix->zw; + o->w = matrix->wx * p.x + matrix->wy * p.y + + matrix->wz * p.z + matrix->ww; + } +} + +static void +_cogl_matrix_project_points_f4 (const CoglMatrix *matrix, + size_t stride_in, + const void *points_in, + size_t stride_out, + void *points_out, + int n_points) +{ + int i; + + for (i = 0; i < n_points; i++) + { + Point4f p = *(Point4f *)((uint8_t *)points_in + i * stride_in); + Point4f *o = (Point4f *)((uint8_t *)points_out + i * stride_out); + + o->x = matrix->xx * p.x + matrix->xy * p.y + + matrix->xz * p.z + matrix->xw * p.w; + o->y = matrix->yx * p.x + matrix->yy * p.y + + matrix->yz * p.z + matrix->yw * p.w; + o->z = matrix->zx * p.x + matrix->zy * p.y + + matrix->zz * p.z + matrix->zw * p.w; + o->w = matrix->wx * p.x + matrix->wy * p.y + + matrix->wz * p.z + matrix->ww * p.w; + } +} + +void +cogl_matrix_transform_points (const CoglMatrix *matrix, + int n_components, + size_t stride_in, + const void *points_in, + size_t stride_out, + void *points_out, + int n_points) +{ + /* The results of transforming always have three components... */ + _COGL_RETURN_IF_FAIL (stride_out >= sizeof (Point3f)); + + if (n_components == 2) + _cogl_matrix_transform_points_f2 (matrix, + stride_in, points_in, + stride_out, points_out, + n_points); + else + { + _COGL_RETURN_IF_FAIL (n_components == 3); + + _cogl_matrix_transform_points_f3 (matrix, + stride_in, points_in, + stride_out, points_out, + n_points); + } +} + +void +cogl_matrix_project_points (const CoglMatrix *matrix, + int n_components, + size_t stride_in, + const void *points_in, + size_t stride_out, + void *points_out, + int n_points) +{ + if (n_components == 2) + _cogl_matrix_project_points_f2 (matrix, + stride_in, points_in, + stride_out, points_out, + n_points); + else if (n_components == 3) + _cogl_matrix_project_points_f3 (matrix, + stride_in, points_in, + stride_out, points_out, + n_points); + else + { + _COGL_RETURN_IF_FAIL (n_components == 4); + + _cogl_matrix_project_points_f4 (matrix, + stride_in, points_in, + stride_out, points_out, + n_points); + } +} + +CoglBool +cogl_matrix_is_identity (const CoglMatrix *matrix) +{ + if (!(matrix->flags & MAT_DIRTY_TYPE) && + matrix->type == COGL_MATRIX_TYPE_IDENTITY) + return TRUE; + else + return memcmp (matrix, identity, sizeof (float) * 16) == 0; +} + +void +cogl_matrix_look_at (CoglMatrix *matrix, + float eye_position_x, + float eye_position_y, + float eye_position_z, + float object_x, + float object_y, + float object_z, + float world_up_x, + float world_up_y, + float world_up_z) +{ + CoglMatrix tmp; + float forward[3]; + float side[3]; + float up[3]; + + /* Get a unit viewing direction vector */ + cogl_vector3_init (forward, + object_x - eye_position_x, + object_y - eye_position_y, + object_z - eye_position_z); + cogl_vector3_normalize (forward); + + cogl_vector3_init (up, world_up_x, world_up_y, world_up_z); + + /* Take the sideways direction as being perpendicular to the viewing + * direction and the word up vector. */ + cogl_vector3_cross_product (side, forward, up); + cogl_vector3_normalize (side); + + /* Now we have unit sideways and forward-direction vectors calculate + * a new mutually perpendicular up vector. */ + cogl_vector3_cross_product (up, side, forward); + + tmp.xx = side[0]; + tmp.yx = side[1]; + tmp.zx = side[2]; + tmp.wx = 0; + + tmp.xy = up[0]; + tmp.yy = up[1]; + tmp.zy = up[2]; + tmp.wy = 0; + + tmp.xz = -forward[0]; + tmp.yz = -forward[1]; + tmp.zz = -forward[2]; + tmp.wz = 0; + + tmp.xw = 0; + tmp.yw = 0; + tmp.zw = 0; + tmp.ww = 1; + + tmp.flags = (MAT_FLAG_GENERAL_3D | MAT_DIRTY_TYPE | MAT_DIRTY_INVERSE); + + cogl_matrix_translate (&tmp, -eye_position_x, -eye_position_y, -eye_position_z); + + cogl_matrix_multiply (matrix, matrix, &tmp); +} + +void +cogl_matrix_transpose (CoglMatrix *matrix) +{ + float new_values[16]; + + /* We don't need to do anything if the matrix is the identity matrix */ + if (!(matrix->flags & MAT_DIRTY_TYPE) && + matrix->type == COGL_MATRIX_TYPE_IDENTITY) + return; + + _cogl_matrix_util_transposef (new_values, cogl_matrix_get_array (matrix)); + + cogl_matrix_init_from_array (matrix, new_values); +} + +GType +cogl_gtype_matrix_get_type (void) +{ + return cogl_matrix_get_gtype (); +} diff --git a/cogl/cogl/cogl-matrix.h b/cogl/cogl/cogl-matrix.h new file mode 100644 index 0000000..43adfd9 --- /dev/null +++ b/cogl/cogl/cogl-matrix.h @@ -0,0 +1,799 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_MATRIX_H +#define __COGL_MATRIX_H + +#include + +#include + +#include +#include + +#include +#include + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-matrix + * @short_description: Functions for initializing and manipulating 4x4 matrices + * + * Matrices are used in Cogl to describe affine model-view transforms, texture + * transforms, and projective transforms. This exposes a utility API that can + * be used for direct manipulation of these matrices. + */ + +/** + * CoglMatrix: + * + * A CoglMatrix holds a 4x4 transform matrix. This is a single precision, + * column-major matrix which means it is compatible with what OpenGL expects. + * + * A CoglMatrix can represent transforms such as, rotations, scaling, + * translation, sheering, and linear projections. You can combine these + * transforms by multiplying multiple matrices in the order you want them + * applied. + * + * The transformation of a vertex (x, y, z, w) by a CoglMatrix is given by: + * + * |[ + * x_new = xx * x + xy * y + xz * z + xw * w + * y_new = yx * x + yy * y + yz * z + yw * w + * z_new = zx * x + zy * y + zz * z + zw * w + * w_new = wx * x + wy * y + wz * z + ww * w + * ]| + * + * Where w is normally 1 + * + * You must consider the members of the CoglMatrix structure read only, + * and all matrix modifications must be done via the cogl_matrix API. This + * allows Cogl to annotate the matrices internally. Violation of this will give + * undefined results. If you need to initialize a matrix with a constant other + * than the identity matrix you can use cogl_matrix_init_from_array(). + */ +struct _CoglMatrix +{ + /* column 0 */ + float xx; + float yx; + float zx; + float wx; + + /* column 1 */ + float xy; + float yy; + float zy; + float wy; + + /* column 2 */ + float xz; + float yz; + float zz; + float wz; + + /* column 3 */ + float xw; + float yw; + float zw; + float ww; + + /*< private >*/ + + /* Note: we may want to extend this later with private flags + * and a cache of the inverse transform matrix. */ + float COGL_PRIVATE (inv)[16]; + unsigned long COGL_PRIVATE (type); + unsigned long COGL_PRIVATE (flags); + unsigned long COGL_PRIVATE (_padding3); +}; +COGL_STRUCT_SIZE_ASSERT (CoglMatrix, 128 + sizeof (unsigned long) * 3); + + +/** + * cogl_matrix_init_identity: + * @matrix: A 4x4 transformation matrix + * + * Resets matrix to the identity matrix: + * + * |[ + * .xx=1; .xy=0; .xz=0; .xw=0; + * .yx=0; .yy=1; .yz=0; .yw=0; + * .zx=0; .zy=0; .zz=1; .zw=0; + * .wx=0; .wy=0; .wz=0; .ww=1; + * ]| + */ +void +cogl_matrix_init_identity (CoglMatrix *matrix); + +/** + * cogl_matrix_init_translation: + * @matrix: A 4x4 transformation matrix + * @tx: x coordinate of the translation vector + * @ty: y coordinate of the translation vector + * @tz: z coordinate of the translation vector + * + * Resets matrix to the (tx, ty, tz) translation matrix: + * + * |[ + * .xx=1; .xy=0; .xz=0; .xw=tx; + * .yx=0; .yy=1; .yz=0; .yw=ty; + * .zx=0; .zy=0; .zz=1; .zw=tz; + * .wx=0; .wy=0; .wz=0; .ww=1; + * ]| + * + * Since: 2.0 + */ +void +cogl_matrix_init_translation (CoglMatrix *matrix, + float tx, + float ty, + float tz); + +/** + * cogl_matrix_multiply: + * @result: The address of a 4x4 matrix to store the result in + * @a: A 4x4 transformation matrix + * @b: A 4x4 transformation matrix + * + * Multiplies the two supplied matrices together and stores + * the resulting matrix inside @result. + * + * It is possible to multiply the @a matrix in-place, so + * @result can be equal to @a but can't be equal to @b. + */ +void +cogl_matrix_multiply (CoglMatrix *result, + const CoglMatrix *a, + const CoglMatrix *b); + +/** + * cogl_matrix_rotate: + * @matrix: A 4x4 transformation matrix + * @angle: The angle you want to rotate in degrees + * @x: X component of your rotation vector + * @y: Y component of your rotation vector + * @z: Z component of your rotation vector + * + * Multiplies @matrix with a rotation matrix that applies a rotation + * of @angle degrees around the specified 3D vector. + */ +void +cogl_matrix_rotate (CoglMatrix *matrix, + float angle, + float x, + float y, + float z); + +/** + * cogl_matrix_rotate_quaternion: + * @matrix: A 4x4 transformation matrix + * @quaternion: A quaternion describing a rotation + * + * Multiplies @matrix with a rotation transformation described by the + * given #CoglQuaternion. + * + * Since: 2.0 + */ +void +cogl_matrix_rotate_quaternion (CoglMatrix *matrix, + const CoglQuaternion *quaternion); + +/** + * cogl_matrix_rotate_euler: + * @matrix: A 4x4 transformation matrix + * @euler: A euler describing a rotation + * + * Multiplies @matrix with a rotation transformation described by the + * given #CoglEuler. + * + * Since: 2.0 + */ +void +cogl_matrix_rotate_euler (CoglMatrix *matrix, + const CoglEuler *euler); + +/** + * cogl_matrix_translate: + * @matrix: A 4x4 transformation matrix + * @x: The X translation you want to apply + * @y: The Y translation you want to apply + * @z: The Z translation you want to apply + * + * Multiplies @matrix with a transform matrix that translates along + * the X, Y and Z axis. + */ +void +cogl_matrix_translate (CoglMatrix *matrix, + float x, + float y, + float z); + +/** + * cogl_matrix_scale: + * @matrix: A 4x4 transformation matrix + * @sx: The X scale factor + * @sy: The Y scale factor + * @sz: The Z scale factor + * + * Multiplies @matrix with a transform matrix that scales along the X, + * Y and Z axis. + */ +void +cogl_matrix_scale (CoglMatrix *matrix, + float sx, + float sy, + float sz); + +/** + * cogl_matrix_look_at: + * @matrix: A 4x4 transformation matrix + * @eye_position_x: The X coordinate to look from + * @eye_position_y: The Y coordinate to look from + * @eye_position_z: The Z coordinate to look from + * @object_x: The X coordinate of the object to look at + * @object_y: The Y coordinate of the object to look at + * @object_z: The Z coordinate of the object to look at + * @world_up_x: The X component of the world's up direction vector + * @world_up_y: The Y component of the world's up direction vector + * @world_up_z: The Z component of the world's up direction vector + * + * Applies a view transform @matrix that positions the camera at + * the coordinate (@eye_position_x, @eye_position_y, @eye_position_z) + * looking towards an object at the coordinate (@object_x, @object_y, + * @object_z). The top of the camera is aligned to the given world up + * vector, which is normally simply (0, 1, 0) to map up to the + * positive direction of the y axis. + * + * Because there is a lot of missleading documentation online for + * gluLookAt regarding the up vector we want to try and be a bit + * clearer here. + * + * The up vector should simply be relative to your world coordinates + * and does not need to change as you move the eye and object + * positions. Many online sources may claim that the up vector needs + * to be perpendicular to the vector between the eye and object + * position (partly because the man page is somewhat missleading) but + * that is not necessary for this function. + * + * You should never look directly along the world-up + * vector. + * + * It is assumed you are using a typical projection matrix where + * your origin maps to the center of your viewport. + * + * Almost always when you use this function it should be the first + * transform applied to a new modelview transform + * + * Since: 1.8 + * Stability: unstable + */ +void +cogl_matrix_look_at (CoglMatrix *matrix, + float eye_position_x, + float eye_position_y, + float eye_position_z, + float object_x, + float object_y, + float object_z, + float world_up_x, + float world_up_y, + float world_up_z); + +/** + * cogl_matrix_frustum: + * @matrix: A 4x4 transformation matrix + * @left: X position of the left clipping plane where it + * intersects the near clipping plane + * @right: X position of the right clipping plane where it + * intersects the near clipping plane + * @bottom: Y position of the bottom clipping plane where it + * intersects the near clipping plane + * @top: Y position of the top clipping plane where it intersects + * the near clipping plane + * @z_near: The distance to the near clipping plane (Must be positive) + * @z_far: The distance to the far clipping plane (Must be positive) + * + * Multiplies @matrix by the given frustum perspective matrix. + */ +void +cogl_matrix_frustum (CoglMatrix *matrix, + float left, + float right, + float bottom, + float top, + float z_near, + float z_far); + +/** + * cogl_matrix_perspective: + * @matrix: A 4x4 transformation matrix + * @fov_y: Vertical field of view angle in degrees. + * @aspect: The (width over height) aspect ratio for display + * @z_near: The distance to the near clipping plane (Must be positive, + * and must not be 0) + * @z_far: The distance to the far clipping plane (Must be positive) + * + * Multiplies @matrix by the described perspective matrix + * + * 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_perspective (CoglMatrix *matrix, + float fov_y, + float aspect, + float z_near, + float z_far); + +/** + * cogl_matrix_orthographic: + * @matrix: A 4x4 transformation matrix + * @x_1: The x coordinate for the first vertical clipping plane + * @y_1: The y coordinate for the first horizontal clipping plane + * @x_2: The x coordinate for the second vertical clipping plane + * @y_2: The y coordinate for the second horizontal clipping plane + * @near: The distance to the near clipping + * plane (will be negative if the plane is + * behind the viewer) + * @far: The distance to the far clipping + * plane (will be negative if the plane is + * behind the viewer) + * + * Multiplies @matrix by a parallel projection matrix. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_matrix_orthographic (CoglMatrix *matrix, + float x_1, + float y_1, + float x_2, + float y_2, + float near, + float 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 + * @near: The distance to the near clipping + * plane (will be negative if the plane is + * behind the viewer) + * @far: The distance to the far clipping + * plane (will be negative if the plane is + * behind the viewer) + * + * Multiplies @matrix by a parallel projection matrix. + * + * Deprecated: 1.10: Use cogl_matrix_orthographic() + */ +COGL_DEPRECATED_IN_1_10_FOR (cogl_matrix_orthographic) +void +cogl_matrix_ortho (CoglMatrix *matrix, + float left, + float right, + float bottom, + float top, + float near, + float far); + +/** + * cogl_matrix_view_2d_in_frustum: + * @matrix: A 4x4 transformation matrix + * @left: coord of left vertical clipping plane + * @right: coord of right vertical clipping plane + * @bottom: coord of bottom horizontal clipping plane + * @top: coord of top horizontal clipping plane + * @z_near: The distance to the near clip plane. Never pass 0 and always pass + * a positive number. + * @z_2d: The distance to the 2D plane. (Should always be positive and + * be between @z_near and the z_far value that was passed to + * cogl_matrix_frustum()) + * @width_2d: The width of the 2D coordinate system + * @height_2d: The height of the 2D coordinate system + * + * Multiplies @matrix by a view transform that maps the 2D coordinates + * (0,0) top left and (@width_2d,@height_2d) bottom right the full viewport + * size. Geometry at a depth of 0 will now lie on this 2D plane. + * + * Note: this doesn't multiply the matrix by any projection matrix, + * but it assumes you have a perspective projection as defined by + * passing the corresponding arguments to cogl_matrix_frustum(). + + * Toolkits such as Clutter that mix 2D and 3D drawing can use this to + * create a 2D coordinate system within a 3D perspective projected + * view frustum. + * + * Since: 1.8 + * Stability: unstable + */ +void +cogl_matrix_view_2d_in_frustum (CoglMatrix *matrix, + float left, + float right, + float bottom, + float top, + float z_near, + float z_2d, + float width_2d, + float height_2d); + +/** + * cogl_matrix_view_2d_in_perspective: + * @fov_y: A field of view angle for the Y axis + * @aspect: The ratio of width to height determining the field of view angle + * for the x axis. + * @z_near: The distance to the near clip plane. Never pass 0 and always pass + * a positive number. + * @z_2d: The distance to the 2D plane. (Should always be positive and + * be between @z_near and the z_far value that was passed to + * cogl_matrix_frustum()) + * @width_2d: The width of the 2D coordinate system + * @height_2d: The height of the 2D coordinate system + * + * Multiplies @matrix by a view transform that maps the 2D coordinates + * (0,0) top left and (@width_2d,@height_2d) bottom right the full viewport + * size. Geometry at a depth of 0 will now lie on this 2D plane. + * + * Note: this doesn't multiply the matrix by any projection matrix, + * but it assumes you have a perspective projection as defined by + * passing the corresponding arguments to cogl_matrix_perspective(). + * + * Toolkits such as Clutter that mix 2D and 3D drawing can use this to + * create a 2D coordinate system within a 3D perspective projected + * view frustum. + * + * Since: 1.8 + * Stability: unstable + */ +void +cogl_matrix_view_2d_in_perspective (CoglMatrix *matrix, + float fov_y, + float aspect, + float z_near, + float z_2d, + float width_2d, + float height_2d); + +/** + * cogl_matrix_init_from_array: + * @matrix: A 4x4 transformation matrix + * @array: A linear array of 16 floats (column-major order) + * + * Initializes @matrix with the contents of @array + */ +void +cogl_matrix_init_from_array (CoglMatrix *matrix, + const float *array); + +/** + * cogl_matrix_get_array: + * @matrix: A 4x4 transformation matrix + * + * Casts @matrix to a float array which can be directly passed to OpenGL. + * + * Return value: a pointer to the float array + */ +const float * +cogl_matrix_get_array (const CoglMatrix *matrix); + +/** + * cogl_matrix_init_from_quaternion: + * @matrix: A 4x4 transformation matrix + * @quaternion: A #CoglQuaternion + * + * Initializes @matrix from a #CoglQuaternion rotation. + */ +void +cogl_matrix_init_from_quaternion (CoglMatrix *matrix, + const CoglQuaternion *quaternion); + +/** + * cogl_matrix_init_from_euler: + * @matrix: A 4x4 transformation matrix + * @euler: A #CoglEuler + * + * Initializes @matrix from a #CoglEuler rotation. + */ +void +cogl_matrix_init_from_euler (CoglMatrix *matrix, + const CoglEuler *euler); + +/** + * cogl_matrix_equal: + * @v1: A 4x4 transformation matrix + * @v2: A 4x4 transformation matrix + * + * Compares two matrices to see if they represent the same + * transformation. Although internally the matrices may have different + * annotations associated with them and may potentially have a cached + * inverse matrix these are not considered in the comparison. + * + * Since: 1.4 + */ +CoglBool +cogl_matrix_equal (const void *v1, const void *v2); + +/** + * cogl_matrix_copy: + * @matrix: A 4x4 transformation matrix you want to copy + * + * Allocates a new #CoglMatrix on the heap and initializes it with + * the same values as @matrix. + * + * Return value: (transfer full): A newly allocated #CoglMatrix which + * should be freed using cogl_matrix_free() + * + * Since: 1.6 + */ +CoglMatrix * +cogl_matrix_copy (const CoglMatrix *matrix); + +/** + * cogl_matrix_free: + * @matrix: A 4x4 transformation matrix you want to free + * + * Frees a #CoglMatrix that was previously allocated via a call to + * cogl_matrix_copy(). + * + * Since: 1.6 + */ +void +cogl_matrix_free (CoglMatrix *matrix); + +/** + * cogl_matrix_get_inverse: + * @matrix: A 4x4 transformation matrix + * @inverse: (out): The destination for a 4x4 inverse transformation matrix + * + * Gets the inverse transform of a given matrix and uses it to initialize + * a new #CoglMatrix. + * + * Although the first parameter is annotated as const to indicate + * that the transform it represents isn't modified this function may + * technically save a copy of the inverse transform within the given + * #CoglMatrix so that subsequent requests for the inverse transform may + * avoid costly inversion calculations. + * + * Return value: %TRUE if the inverse was successfully calculated or %FALSE + * for degenerate transformations that can't be inverted (in this case the + * @inverse matrix will simply be initialized with the identity matrix) + * + * Since: 1.2 + */ +CoglBool +cogl_matrix_get_inverse (const CoglMatrix *matrix, + CoglMatrix *inverse); + +/* FIXME: to be consistent with cogl_matrix_{transform,project}_points + * this could be renamed to cogl_matrix_project_point for Cogl 2.0... + */ + +/** + * cogl_matrix_transform_point: + * @matrix: A 4x4 transformation matrix + * @x: (inout): The X component of your points position + * @y: (inout): The Y component of your points position + * @z: (inout): The Z component of your points position + * @w: (inout): The W component of your points position + * + * Transforms a point whos position is given and returned as four float + * components. + */ +void +cogl_matrix_transform_point (const CoglMatrix *matrix, + float *x, + float *y, + float *z, + float *w); + +/** + * cogl_matrix_transform_points: + * @matrix: A transformation matrix + * @n_components: The number of position components for each input point. + * (either 2 or 3) + * @stride_in: The stride in bytes between input points. + * @points_in: A pointer to the first component of the first input point. + * @stride_out: The stride in bytes between output points. + * @points_out: A pointer to the first component of the first output point. + * @n_points: The number of points to transform. + * + * Transforms an array of input points and writes the result to + * another array of output points. The input points can either have 2 + * or 3 components each. The output points always have 3 components. + * The output array can simply point to the input array to do the + * transform in-place. + * + * If you need to transform 4 component points see + * cogl_matrix_project_points(). + * + * Here's an example with differing input/output strides: + * |[ + * typedef struct { + * float x,y; + * uint8_t r,g,b,a; + * float s,t,p; + * } MyInVertex; + * typedef struct { + * uint8_t r,g,b,a; + * float x,y,z; + * } MyOutVertex; + * MyInVertex vertices[N_VERTICES]; + * MyOutVertex results[N_VERTICES]; + * CoglMatrix matrix; + * + * my_load_vertices (vertices); + * my_get_matrix (&matrix); + * + * cogl_matrix_transform_points (&matrix, + * 2, + * sizeof (MyInVertex), + * &vertices[0].x, + * sizeof (MyOutVertex), + * &results[0].x, + * N_VERTICES); + * ]| + * + * Stability: unstable + */ +void +cogl_matrix_transform_points (const CoglMatrix *matrix, + int n_components, + size_t stride_in, + const void *points_in, + size_t stride_out, + void *points_out, + int n_points); + +/** + * cogl_matrix_project_points: + * @matrix: A projection matrix + * @n_components: The number of position components for each input point. + * (either 2, 3 or 4) + * @stride_in: The stride in bytes between input points. + * @points_in: A pointer to the first component of the first input point. + * @stride_out: The stride in bytes between output points. + * @points_out: A pointer to the first component of the first output point. + * @n_points: The number of points to transform. + * + * Projects an array of input points and writes the result to another + * array of output points. The input points can either have 2, 3 or 4 + * components each. The output points always have 4 components (known + * as homogenous coordinates). The output array can simply point to + * the input array to do the transform in-place. + * + * Here's an example with differing input/output strides: + * |[ + * typedef struct { + * float x,y; + * uint8_t r,g,b,a; + * float s,t,p; + * } MyInVertex; + * typedef struct { + * uint8_t r,g,b,a; + * float x,y,z; + * } MyOutVertex; + * MyInVertex vertices[N_VERTICES]; + * MyOutVertex results[N_VERTICES]; + * CoglMatrix matrix; + * + * my_load_vertices (vertices); + * my_get_matrix (&matrix); + * + * cogl_matrix_project_points (&matrix, + * 2, + * sizeof (MyInVertex), + * &vertices[0].x, + * sizeof (MyOutVertex), + * &results[0].x, + * N_VERTICES); + * ]| + * + * Stability: unstable + */ +void +cogl_matrix_project_points (const CoglMatrix *matrix, + int n_components, + size_t stride_in, + const void *points_in, + size_t stride_out, + void *points_out, + int n_points); + +/** + * cogl_matrix_is_identity: + * @matrix: A #CoglMatrix + * + * Determines if the given matrix is an identity matrix. + * + * Returns: %TRUE if @matrix is an identity matrix else %FALSE + * Since: 1.8 + */ +CoglBool +cogl_matrix_is_identity (const CoglMatrix *matrix); + +/** + * cogl_matrix_transpose: + * @matrix: A #CoglMatrix + * + * Replaces @matrix with its transpose. Ie, every element (i,j) in the + * new matrix is taken from element (j,i) in the old matrix. + * + * Since: 1.10 + */ +void +cogl_matrix_transpose (CoglMatrix *matrix); + +/** + * cogl_debug_matrix_print: + * @matrix: A #CoglMatrix + * + * Prints the contents of a #CoglMatrix to stdout. + * + * Since: 2.0 + */ +void +cogl_debug_matrix_print (const CoglMatrix *matrix); + +#define COGL_GTYPE_TYPE_MATRIX (cogl_matrix_get_gtype ()) + +/** + * cogl_matrix_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_matrix_get_gtype (void); + +/** + * cogl_gtype_matrix_get_type: + * + * Returns: the GType for the registered "CoglMatrix" boxed type. This + * can be used for example to define GObject properties that accept a + * #CoglMatrix value. + * + * Deprecated: 1.18: Use cogl_matrix_get_gtype() instead. + */ +GType +cogl_gtype_matrix_get_type (void); + +COGL_END_DECLS + +#endif /* __COGL_MATRIX_H */ diff --git a/cogl/cogl/cogl-memory-stack-private.h b/cogl/cogl/cogl-memory-stack-private.h new file mode 100644 index 0000000..2b6ee82 --- /dev/null +++ b/cogl/cogl/cogl-memory-stack-private.h @@ -0,0 +1,50 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_MEMORY_STACK__ +#define __COGL_MEMORY_STACK__ + +#include + +typedef struct _CoglMemoryStack CoglMemoryStack; + +CoglMemoryStack * +_cogl_memory_stack_new (size_t initial_size_bytes); + +void * +_cogl_memory_stack_alloc (CoglMemoryStack *stack, size_t bytes); + +void +_cogl_memory_stack_rewind (CoglMemoryStack *stack); + +void +_cogl_memory_stack_free (CoglMemoryStack *stack); + +#endif /* __COGL_MEMORY_STACK__ */ diff --git a/cogl/cogl/cogl-memory-stack.c b/cogl/cogl/cogl-memory-stack.c new file mode 100644 index 0000000..a7c3ee3 --- /dev/null +++ b/cogl/cogl/cogl-memory-stack.c @@ -0,0 +1,196 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * CoglMemoryStack provides a really simple, but lightning fast + * memory stack allocation strategy: + * + * - The underlying pool of memory is grow-only. + * - The pool is considered to be a stack which may be comprised + * of multiple smaller stacks. Allocation is done as follows: + * - If there's enough memory in the current sub-stack then the + * stack-pointer will be returned as the allocation and the + * stack-pointer will be incremented by the allocation size. + * - If there isn't enough memory in the current sub-stack + * then a new sub-stack is allocated twice as big as the current + * sub-stack or twice as big as the requested allocation size if + * that's bigger and the stack-pointer is set to the start of the + * new sub-stack. + * - Allocations can't be freed in a random-order, you can only + * rewind the entire stack back to the start. There is no + * the concept of stack frames to allow partial rewinds. + * + * For example; we plan to use this in our tesselator which has to + * allocate lots of small vertex, edge and face structures because + * when tesselation has been finished we just want to free the whole + * lot in one go. + * + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-memory-stack-private.h" +#include "cogl-list.h" + +#include + +#include + +typedef struct _CoglMemorySubStack +{ + CoglList link; + size_t bytes; + uint8_t *data; +} CoglMemorySubStack; + +struct _CoglMemoryStack +{ + CoglList sub_stacks; + + CoglMemorySubStack *sub_stack; + size_t sub_stack_offset; +}; + +static CoglMemorySubStack * +_cogl_memory_sub_stack_alloc (size_t bytes) +{ + CoglMemorySubStack *sub_stack = g_slice_new (CoglMemorySubStack); + sub_stack->bytes = bytes; + sub_stack->data = g_malloc (bytes); + return sub_stack; +} + +static void +_cogl_memory_stack_add_sub_stack (CoglMemoryStack *stack, + size_t sub_stack_bytes) +{ + CoglMemorySubStack *sub_stack = + _cogl_memory_sub_stack_alloc (sub_stack_bytes); + _cogl_list_insert (stack->sub_stacks.prev, &sub_stack->link); + stack->sub_stack = sub_stack; + stack->sub_stack_offset = 0; +} + +CoglMemoryStack * +_cogl_memory_stack_new (size_t initial_size_bytes) +{ + CoglMemoryStack *stack = g_slice_new0 (CoglMemoryStack); + + _cogl_list_init (&stack->sub_stacks); + + _cogl_memory_stack_add_sub_stack (stack, initial_size_bytes); + + return stack; +} + +void * +_cogl_memory_stack_alloc (CoglMemoryStack *stack, size_t bytes) +{ + CoglMemorySubStack *sub_stack; + void *ret; + + sub_stack = stack->sub_stack; + if (G_LIKELY (sub_stack->bytes - stack->sub_stack_offset >= bytes)) + { + ret = sub_stack->data + stack->sub_stack_offset; + stack->sub_stack_offset += bytes; + return ret; + } + + /* If the stack has been rewound and then a large initial allocation + * is made then we may need to skip over one or more of the + * sub-stacks that are too small for the requested allocation + * size... */ + for (_cogl_list_set_iterator (sub_stack->link.next, sub_stack, link); + &sub_stack->link != &stack->sub_stacks; + _cogl_list_set_iterator (sub_stack->link.next, sub_stack, link)) + { + if (sub_stack->bytes >= bytes) + { + ret = sub_stack->data; + stack->sub_stack = sub_stack; + stack->sub_stack_offset = bytes; + return ret; + } + } + + /* Finally if we couldn't find a free sub-stack with enough space + * for the requested allocation we allocate another sub-stack that's + * twice as big as the last sub-stack or twice as big as the + * requested allocation if that's bigger. + */ + + sub_stack = _cogl_container_of (stack->sub_stacks.prev, + CoglMemorySubStack, + link); + + _cogl_memory_stack_add_sub_stack (stack, MAX (sub_stack->bytes, bytes) * 2); + + sub_stack = _cogl_container_of (stack->sub_stacks.prev, + CoglMemorySubStack, + link); + + stack->sub_stack_offset += bytes; + + return sub_stack->data; +} + +void +_cogl_memory_stack_rewind (CoglMemoryStack *stack) +{ + stack->sub_stack = _cogl_container_of (stack->sub_stacks.next, + CoglMemorySubStack, + link); + stack->sub_stack_offset = 0; +} + +static void +_cogl_memory_sub_stack_free (CoglMemorySubStack *sub_stack) +{ + g_free (sub_stack->data); + g_slice_free (CoglMemorySubStack, sub_stack); +} + +void +_cogl_memory_stack_free (CoglMemoryStack *stack) +{ + + while (!_cogl_list_empty (&stack->sub_stacks)) + { + CoglMemorySubStack *sub_stack = + _cogl_container_of (stack->sub_stacks.next, CoglMemorySubStack, link); + _cogl_list_remove (&sub_stack->link); + _cogl_memory_sub_stack_free (sub_stack); + } + + g_slice_free (CoglMemoryStack, stack); +} diff --git a/cogl/cogl/cogl-meta-texture.c b/cogl/cogl/cogl-meta-texture.c new file mode 100644 index 0000000..ed12269 --- /dev/null +++ b/cogl/cogl/cogl-meta-texture.c @@ -0,0 +1,642 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-texture.h" +#include "cogl-matrix.h" +#include "cogl-spans.h" +#include "cogl-meta-texture.h" +#include "cogl-texture-rectangle-private.h" + +#include +#include + +typedef struct _ForeachData +{ + float meta_region_coords[4]; + CoglPipelineWrapMode wrap_s; + CoglPipelineWrapMode wrap_t; + CoglMetaTextureCallback callback; + void *user_data; + + int width; + int height; + + CoglTexture *padded_textures[9]; + const float *grid_slice_texture_coords; + float slice_offset_s; + float slice_offset_t; + float slice_range_s; + float slice_range_t; +} ForeachData; + +static void +padded_grid_repeat_cb (CoglTexture *slice_texture, + const float *slice_texture_coords, + const float *meta_coords, + void *user_data) +{ + ForeachData *data; + float mapped_coords[4]; + + /* Ignore padding slices for the current grid */ + if (!slice_texture) + return; + + data = user_data; + + /* NB: the slice_texture_coords[] we get here will always be + * normalized. + * + * We now need to map the normalized slice_texture_coords[] we have + * here back to the real slice coordinates we saved in the previous + * stage... + */ + mapped_coords[0] = + slice_texture_coords[0] * data->slice_range_s + data->slice_offset_s; + mapped_coords[1] = + slice_texture_coords[1] * data->slice_range_t + data->slice_offset_t; + mapped_coords[2] = + slice_texture_coords[2] * data->slice_range_s + data->slice_offset_s; + mapped_coords[3] = + slice_texture_coords[3] * data->slice_range_t + data->slice_offset_t; + + data->callback (slice_texture, + mapped_coords, meta_coords, data->user_data); +} + +static int +setup_padded_spans (CoglSpan *spans, + float start, + float end, + float range, + int *real_index) +{ + int span_index = 0; + + if (start > 0) + { + spans[0].start = 0; + spans[0].size = start; + spans[0].waste = 0; + span_index++; + spans[1].start = spans[0].size; + } + else + spans[span_index].start = 0; + + spans[span_index].size = end - start; + spans[span_index].waste = 0; + *real_index = span_index; + span_index++; + + if (end < range) + { + spans[span_index].start = + spans[span_index - 1].start + spans[span_index - 1].size; + spans[span_index].size = range - end; + spans[span_index].waste = 0; + span_index++; + } + + return span_index; +} + +/* This handles each sub-texture within the range [0,1] of our + * original meta texture and repeats each one separately across the + * users requested virtual texture coordinates. + * + * A notable advantage of this approach is that we will batch + * together callbacks corresponding to the same underlying slice + * together. + */ +static void +create_grid_and_repeat_cb (CoglTexture *slice_texture, + const float *slice_texture_coords, + const float *meta_coords, + void *user_data) +{ + ForeachData *data = user_data; + CoglSpan x_spans[3]; + int n_x_spans; + int x_real_index; + CoglSpan y_spans[3]; + int n_y_spans; + int y_real_index; + + /* NB: This callback is called for each slice of the meta-texture + * in the range [0,1]. + * + * We define a "padded grid" for each slice of the meta-texture in + * the range [0,1]. The x axis and y axis grid lines are defined + * using CoglSpans. + * + * The padded grid maps over the meta-texture coordinates in the + * range [0,1] but only contains one valid cell that corresponds to + * current slice being iterated and all the surrounding cells just + * provide padding. + * + * Once we've defined our padded grid we then repeat that across + * the user's original region, calling their callback whenever + * we see our current slice - ignoring padding. + * + * NB: we can assume meta_coords[] are normalized at this point + * since TextureRectangles aren't iterated with this code-path. + * + * NB: spans are always defined using non-normalized coordinates + */ + n_x_spans = setup_padded_spans (x_spans, + meta_coords[0] * data->width, + meta_coords[2] * data->width, + data->width, + &x_real_index); + n_y_spans = setup_padded_spans (y_spans, + meta_coords[1] * data->height, + meta_coords[3] * data->height, + data->height, + &y_real_index); + + data->padded_textures[n_x_spans * y_real_index + x_real_index] = + slice_texture; + + /* Our callback is going to be passed normalized slice texture + * coordinates, and we will need to map the range [0,1] to the real + * slice_texture_coords we have here... */ + data->grid_slice_texture_coords = slice_texture_coords; + data->slice_range_s = fabs (data->grid_slice_texture_coords[2] - + data->grid_slice_texture_coords[0]); + data->slice_range_t = fabs (data->grid_slice_texture_coords[3] - + data->grid_slice_texture_coords[1]); + data->slice_offset_s = MIN (data->grid_slice_texture_coords[0], + data->grid_slice_texture_coords[2]); + data->slice_offset_t = MIN (data->grid_slice_texture_coords[1], + data->grid_slice_texture_coords[3]); + + /* Now actually iterate the region the user originally requested + * using the current padded grid */ + _cogl_texture_spans_foreach_in_region (x_spans, + n_x_spans, + y_spans, + n_y_spans, + data->padded_textures, + data->meta_region_coords, + data->width, + data->height, + data->wrap_s, + data->wrap_t, + padded_grid_repeat_cb, + data); + + /* Clear the padded_textures ready for the next iteration */ + data->padded_textures[n_x_spans * y_real_index + x_real_index] = NULL; +} + +#define SWAP(A,B) do { float tmp = B; B = A; A = tmp; } while (0) + +typedef struct _ClampData +{ + float start; + float end; + CoglBool s_flipped; + CoglBool t_flipped; + CoglMetaTextureCallback callback; + void *user_data; +} ClampData; + +static void +clamp_s_cb (CoglTexture *sub_texture, + const float *sub_texture_coords, + const float *meta_coords, + void *user_data) +{ + ClampData *clamp_data = user_data; + float mapped_meta_coords[4] = { + clamp_data->start, + meta_coords[1], + clamp_data->end, + meta_coords[3] + }; + if (clamp_data->s_flipped) + SWAP (mapped_meta_coords[0], mapped_meta_coords[2]); + /* NB: we never need to flip the t coords when dealing with + * s-axis clamping so no need to check if ->t_flipped */ + clamp_data->callback (sub_texture, + sub_texture_coords, mapped_meta_coords, + clamp_data->user_data); +} + +static void +clamp_t_cb (CoglTexture *sub_texture, + const float *sub_texture_coords, + const float *meta_coords, + void *user_data) +{ + ClampData *clamp_data = user_data; + float mapped_meta_coords[4] = { + meta_coords[0], + clamp_data->start, + meta_coords[2], + clamp_data->end, + }; + if (clamp_data->s_flipped) + SWAP (mapped_meta_coords[0], mapped_meta_coords[2]); + if (clamp_data->t_flipped) + SWAP (mapped_meta_coords[1], mapped_meta_coords[3]); + clamp_data->callback (sub_texture, + sub_texture_coords, mapped_meta_coords, + clamp_data->user_data); +} + +static CoglBool +foreach_clamped_region (CoglMetaTexture *meta_texture, + float *tx_1, + float *ty_1, + float *tx_2, + float *ty_2, + CoglPipelineWrapMode wrap_s, + CoglPipelineWrapMode wrap_t, + CoglMetaTextureCallback callback, + void *user_data) +{ + float width = cogl_texture_get_width (COGL_TEXTURE (meta_texture)); + ClampData clamp_data; + + /* Consider that *tx_1 may be > *tx_2 and to simplify things + * we just flip them around if that's the case and keep a note + * of the fact that they are flipped. */ + if (*tx_1 > *tx_2) + { + SWAP (*tx_1, *tx_2); + clamp_data.s_flipped = TRUE; + } + else + clamp_data.s_flipped = FALSE; + + /* The same goes for ty_1 and ty_2... */ + if (*ty_1 > *ty_2) + { + SWAP (*ty_1, *ty_2); + clamp_data.t_flipped = TRUE; + } + else + clamp_data.t_flipped = FALSE; + + clamp_data.callback = callback; + clamp_data.user_data = user_data; + + if (wrap_s == COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE) + { + float max_s_coord; + float half_texel_width; + + /* Consider that rectangle textures have non-normalized + * coordinates... */ + if (cogl_is_texture_rectangle (meta_texture)) + max_s_coord = width; + else + max_s_coord = 1.0; + + half_texel_width = max_s_coord / (width * 2); + + /* Handle any left clamped region */ + if (*tx_1 < 0) + { + clamp_data.start = *tx_1; + clamp_data.end = MIN (0, *tx_2);; + cogl_meta_texture_foreach_in_region (meta_texture, + half_texel_width, *ty_1, + half_texel_width, *ty_2, + COGL_PIPELINE_WRAP_MODE_REPEAT, + wrap_t, + clamp_s_cb, + &clamp_data); + /* Have we handled everything? */ + if (*tx_2 <= 0) + return TRUE; + + /* clamp tx_1 since we've handled everything with x < 0 */ + *tx_1 = 0; + } + + /* Handle any right clamped region - including the corners */ + if (*tx_2 > max_s_coord) + { + clamp_data.start = MAX (max_s_coord, *tx_1); + clamp_data.end = *tx_2; + cogl_meta_texture_foreach_in_region (meta_texture, + max_s_coord - half_texel_width, + *ty_1, + max_s_coord - half_texel_width, + *ty_2, + COGL_PIPELINE_WRAP_MODE_REPEAT, + wrap_t, + clamp_s_cb, + &clamp_data); + /* Have we handled everything? */ + if (*tx_1 >= max_s_coord) + return TRUE; + + /* clamp tx_2 since we've handled everything with x > + * max_s_coord */ + *tx_2 = max_s_coord; + } + } + + if (wrap_t == COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE) + { + float height = cogl_texture_get_height (COGL_TEXTURE (meta_texture)); + float max_t_coord; + float half_texel_height; + + /* Consider that rectangle textures have non-normalized + * coordinates... */ + if (cogl_is_texture_rectangle (meta_texture)) + max_t_coord = height; + else + max_t_coord = 1.0; + + half_texel_height = max_t_coord / (height * 2); + + /* Handle any top clamped region */ + if (*ty_1 < 0) + { + clamp_data.start = *ty_1; + clamp_data.end = MIN (0, *ty_2);; + cogl_meta_texture_foreach_in_region (meta_texture, + *tx_1, half_texel_height, + *tx_2, half_texel_height, + wrap_s, + COGL_PIPELINE_WRAP_MODE_REPEAT, + clamp_t_cb, + &clamp_data); + /* Have we handled everything? */ + if (*tx_2 <= 0) + return TRUE; + + /* clamp ty_1 since we've handled everything with y < 0 */ + *ty_1 = 0; + } + + /* Handle any bottom clamped region */ + if (*ty_2 > max_t_coord) + { + clamp_data.start = MAX (max_t_coord, *ty_1);; + clamp_data.end = *ty_2; + cogl_meta_texture_foreach_in_region (meta_texture, + *tx_1, + max_t_coord - half_texel_height, + *tx_2, + max_t_coord - half_texel_height, + wrap_s, + COGL_PIPELINE_WRAP_MODE_REPEAT, + clamp_t_cb, + &clamp_data); + /* Have we handled everything? */ + if (*ty_1 >= max_t_coord) + return TRUE; + + /* clamp ty_2 since we've handled everything with y > + * max_t_coord */ + *ty_2 = max_t_coord; + } + } + + if (clamp_data.s_flipped) + SWAP (*tx_1, *tx_2); + if (clamp_data.t_flipped) + SWAP (*ty_1, *ty_2); + + return FALSE; +} + +typedef struct _NormalizeData +{ + CoglMetaTextureCallback callback; + void *user_data; + float s_normalize_factor; + float t_normalize_factor; +} NormalizeData; + +static void +normalize_meta_coords_cb (CoglTexture *slice_texture, + const float *slice_coords, + const float *meta_coords, + void *user_data) +{ + NormalizeData *data = user_data; + float normalized_meta_coords[4] = { + meta_coords[0] * data->s_normalize_factor, + meta_coords[1] * data->t_normalize_factor, + meta_coords[2] * data->s_normalize_factor, + meta_coords[3] * data->t_normalize_factor + }; + + data->callback (slice_texture, + slice_coords, normalized_meta_coords, + data->user_data); +} + +typedef struct _UnNormalizeData +{ + CoglMetaTextureCallback callback; + void *user_data; + float width; + float height; +} UnNormalizeData; + +static void +un_normalize_slice_coords_cb (CoglTexture *slice_texture, + const float *slice_coords, + const float *meta_coords, + void *user_data) +{ + UnNormalizeData *data = user_data; + float un_normalized_slice_coords[4] = { + slice_coords[0] * data->width, + slice_coords[1] * data->height, + slice_coords[2] * data->width, + slice_coords[3] * data->height + }; + + data->callback (slice_texture, + un_normalized_slice_coords, meta_coords, + data->user_data); +} + +void +cogl_meta_texture_foreach_in_region (CoglMetaTexture *meta_texture, + float tx_1, + float ty_1, + float tx_2, + float ty_2, + CoglPipelineWrapMode wrap_s, + CoglPipelineWrapMode wrap_t, + CoglMetaTextureCallback callback, + void *user_data) +{ + CoglTexture *texture = COGL_TEXTURE (meta_texture); + float width = cogl_texture_get_width (texture); + float height = cogl_texture_get_height (texture); + NormalizeData normalize_data; + + if (wrap_s == COGL_PIPELINE_WRAP_MODE_AUTOMATIC) + wrap_s = COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE; + if (wrap_t == COGL_PIPELINE_WRAP_MODE_AUTOMATIC) + wrap_t = COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE; + + if (wrap_s == COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE || + wrap_t == COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE) + { + CoglBool finished = foreach_clamped_region (meta_texture, + &tx_1, &ty_1, &tx_2, &ty_2, + wrap_s, wrap_t, + callback, + user_data); + if (finished) + return; + + /* Since clamping has been handled we now want to normalize our + * wrap modes we se can assume from this point on we don't + * need to consider CLAMP_TO_EDGE. (NB: The spans code will + * assert that CLAMP_TO_EDGE isn't requested) */ + if (wrap_s == COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE) + wrap_s = COGL_PIPELINE_WRAP_MODE_REPEAT; + if (wrap_t == COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE) + wrap_t = COGL_PIPELINE_WRAP_MODE_REPEAT; + } + + /* It makes things simpler to deal with non-normalized region + * coordinates beyond this point and only re-normalize just before + * calling the user's callback... */ + + if (!cogl_is_texture_rectangle (COGL_TEXTURE (meta_texture))) + { + normalize_data.callback = callback; + normalize_data.user_data = user_data; + normalize_data.s_normalize_factor = 1.0f / width; + normalize_data.t_normalize_factor = 1.0f / height; + callback = normalize_meta_coords_cb; + user_data = &normalize_data; + tx_1 *= width; + ty_1 *= height; + tx_2 *= width; + ty_2 *= height; + } + + /* XXX: at some point this wont be routed through the CoglTexture + * vtable, instead there will be a separate CoglMetaTexture + * interface vtable. */ + + if (texture->vtable->foreach_sub_texture_in_region) + { + ForeachData data; + + data.meta_region_coords[0] = tx_1; + data.meta_region_coords[1] = ty_1; + data.meta_region_coords[2] = tx_2; + data.meta_region_coords[3] = ty_2; + data.wrap_s = wrap_s; + data.wrap_t = wrap_t; + data.callback = callback; + data.user_data = user_data; + + data.width = width; + data.height = height; + + memset (data.padded_textures, 0, sizeof (data.padded_textures)); + + /* + * 1) We iterate all the slices of the meta-texture only within + * the range [0,1]. + * + * 2) We define a "padded grid" for each slice of the + * meta-texture in the range [0,1]. + * + * The padded grid maps over the meta-texture coordinates in + * the range [0,1] but only contains one valid cell that + * corresponds to current slice being iterated and all the + * surrounding cells just provide padding. + * + * 3) Once we've defined our padded grid we then repeat that + * across the user's original region, calling their callback + * whenever we see our current slice - ignoring padding. + * + * A notable benefit of this design is that repeating a texture + * made of multiple slices will result in us repeating each + * slice in-turn so the user gets repeat callbacks for the same + * texture batched together. For manual emulation of texture + * repeats done by drawing geometry this makes it more likely + * that we can batch geometry. + */ + + texture->vtable->foreach_sub_texture_in_region (texture, + 0, 0, 1, 1, + create_grid_and_repeat_cb, + &data); + } + else + { + CoglSpan x_span = { 0, width, 0 }; + CoglSpan y_span = { 0, height, 0 }; + float meta_region_coords[4] = { tx_1, ty_1, tx_2, ty_2 }; + UnNormalizeData un_normalize_data; + + /* If we are dealing with a CoglTextureRectangle then we need a shim + * callback that un_normalizes the slice coordinates we get from + * _cogl_texture_spans_foreach_in_region before passing them to + * the user's callback. */ + if (cogl_is_texture_rectangle (meta_texture)) + { + un_normalize_data.callback = callback; + un_normalize_data.user_data = user_data; + un_normalize_data.width = width; + un_normalize_data.height = height; + callback = un_normalize_slice_coords_cb; + user_data = &un_normalize_data; + } + + _cogl_texture_spans_foreach_in_region (&x_span, 1, + &y_span, 1, + &texture, + meta_region_coords, + width, + height, + wrap_s, + wrap_t, + callback, + user_data); + } +} +#undef SWAP diff --git a/cogl/cogl/cogl-meta-texture.h b/cogl/cogl/cogl-meta-texture.h new file mode 100644 index 0000000..c347881 --- /dev/null +++ b/cogl/cogl/cogl-meta-texture.h @@ -0,0 +1,195 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_META_TEXTURE_H__ +#define __COGL_META_TEXTURE_H__ + +#include + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-meta-texture + * @short_description: Interface for high-level textures built from + * low-level textures like #CoglTexture2D and + * #CoglTexture3D. + * + * Cogl helps to make it easy to deal with high level textures such + * as #CoglAtlasTextures, #CoglSubTextures, + * #CoglTexturePixmapX11 textures and #CoglTexture2DSliced textures + * consistently. + * + * A #CoglMetaTexture is a texture that might internally be + * represented by one or more low-level #CoglTextures + * such as #CoglTexture2D or #CoglTexture3D. These low-level textures + * are the only ones that a GPU really understands but because + * applications often want more high-level texture abstractions + * (such as storing multiple textures inside one larger "atlas" + * texture) it's desirable to be able to deal with these + * using a common interface. + * + * For example the GPU is not able to automatically handle repeating a + * texture that is part of a larger atlas texture but if you use + * %COGL_PIPELINE_WRAP_MODE_REPEAT with an atlas texture when drawing + * with cogl_rectangle() you should see that it "Just Works™" - at + * least if you don't use multi-texturing. The reason this works is + * because cogl_rectangle() internally understands the #CoglMetaTexture + * interface and is able to manually resolve the low-level textures + * using this interface and by making multiple draw calls it can + * emulate the texture repeat modes. + * + * Cogl doesn't aim to pretend that meta-textures are just like real + * textures because it would get extremely complex to try and emulate + * low-level GPU semantics transparently for these textures. The low + * level drawing APIs of Cogl, such as cogl_primitive_draw() don't + * actually know anything about the #CoglMetaTexture interface and its + * the developer's responsibility to resolve all textures referenced + * by a #CoglPipeline to low-level textures before drawing. + * + * If you want to develop custom primitive APIs like + * cogl_framebuffer_draw_rectangle() and you want to support drawing + * with #CoglAtlasTextures or #CoglSubTextures for + * example, then you will need to use this #CoglMetaTexture interface + * to be able to resolve high-level textures into low-level textures + * before drawing with Cogl's low-level drawing APIs such as + * cogl_primitive_draw(). + * + * Most developers won't need to use this interface directly + * but still it is worth understanding the distinction between + * low-level and meta textures because you may find other references + * in the documentation that detail limitations of using + * meta-textures. + */ + +#if defined(__COGL_H_INSIDE__) && !defined(COGL_ENABLE_MUTTER_API) && \ + !defined(COGL_GIR_SCANNING) +/* For the public C api we typedef interface types as void to avoid needing + * lots of casting in code and instead we will rely on runtime type checking + * for these objects. */ +typedef void CoglMetaTexture; +#else +typedef struct _CoglMetaTexture CoglMetaTexture; +#define COGL_META_TEXTURE(X) ((CoglMetaTexture *)X) +#endif + +/** + * CoglMetaTextureCallback: + * @sub_texture: A low-level #CoglTexture making up part of a + * #CoglMetaTexture. + * @sub_texture_coords: A float 4-tuple ordered like + * (tx1,ty1,tx2,ty2) defining what region of the + * current @sub_texture maps to a sub-region of a + * #CoglMetaTexture. (tx1,ty1) is the top-left + * sub-region coordinate and (tx2,ty2) is the + * bottom-right. These are low-level texture + * coordinates. + * @meta_coords: A float 4-tuple ordered like (tx1,ty1,tx2,ty2) + * defining what sub-region of a #CoglMetaTexture this + * low-level @sub_texture maps too. (tx1,ty1) is + * the top-left sub-region coordinate and (tx2,ty2) is + * the bottom-right. These are high-level meta-texture + * coordinates. + * @user_data: A private pointer passed to + * cogl_meta_texture_foreach_in_region(). + * + * A callback used with cogl_meta_texture_foreach_in_region() to + * retrieve details of all the low-level #CoglTextures that + * make up a given #CoglMetaTexture. + * + * Since: 1.10 + * Stability: unstable + */ +typedef void (*CoglMetaTextureCallback) (CoglTexture *sub_texture, + const float *sub_texture_coords, + const float *meta_coords, + void *user_data); + +/** + * cogl_meta_texture_foreach_in_region: + * @meta_texture: An object implementing the #CoglMetaTexture + * interface. + * @tx_1: The top-left x coordinate of the region to iterate + * @ty_1: The top-left y coordinate of the region to iterate + * @tx_2: The bottom-right x coordinate of the region to iterate + * @ty_2: The bottom-right y coordinate of the region to iterate + * @wrap_s: The wrap mode for the x-axis + * @wrap_t: The wrap mode for the y-axis + * @callback: A #CoglMetaTextureCallback pointer to be called + * for each low-level texture within the specified region. + * @user_data: A private pointer that is passed to @callback. + * + * Allows you to manually iterate the low-level textures that define a + * given region of a high-level #CoglMetaTexture. + * + * For example cogl_texture_2d_sliced_new_with_size() can be used to + * create a meta texture that may slice a large image into multiple, + * smaller power-of-two sized textures. These high level textures are + * not directly understood by a GPU and so this API must be used to + * manually resolve the underlying textures for drawing. + * + * All high level textures (#CoglAtlasTexture, #CoglSubTexture, + * #CoglTexturePixmapX11, and #CoglTexture2DSliced) can be handled + * consistently using this interface which greately simplifies + * implementing primitives that support all texture types. + * + * For example if you use the cogl_rectangle() API then Cogl will + * internally use this API to resolve the low level textures of any + * meta textures you have associated with CoglPipeline layers. + * + * The low level drawing APIs such as cogl_primitive_draw() + * don't understand the #CoglMetaTexture interface and so it is your + * responsibility to use this API to resolve all CoglPipeline textures + * into low-level textures before drawing. + * + * For each low-level texture that makes up part of the given region + * of the @meta_texture, @callback is called specifying how the + * low-level texture maps to the original region. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_meta_texture_foreach_in_region (CoglMetaTexture *meta_texture, + float tx_1, + float ty_1, + float tx_2, + float ty_2, + CoglPipelineWrapMode wrap_s, + CoglPipelineWrapMode wrap_t, + CoglMetaTextureCallback callback, + void *user_data); + +COGL_END_DECLS + +#endif /* __COGL_META_TEXTURE_H__ */ diff --git a/cogl/cogl/cogl-mutter.h b/cogl/cogl/cogl-mutter.h new file mode 100644 index 0000000..4bfac07 --- /dev/null +++ b/cogl/cogl/cogl-mutter.h @@ -0,0 +1,48 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2016 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_MUTTER_H___ +#define __COGL_MUTTER_H___ + +#include "cogl-mutter-config.h" +#include "cogl-defines.h" + +#include +#include +#include +#include +#include +#include +#include + +void cogl_renderer_set_custom_winsys (CoglRenderer *renderer, + CoglWinsysVtableGetter winsys_vtable_getter); + +#endif /* __COGL_MUTTER_H___ */ diff --git a/cogl/cogl/cogl-node-private.h b/cogl/cogl/cogl-node-private.h new file mode 100644 index 0000000..8fe2477 --- /dev/null +++ b/cogl/cogl/cogl-node-private.h @@ -0,0 +1,89 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_NODE_PRIVATE_H +#define __COGL_NODE_PRIVATE_H + +#include "cogl-object-private.h" +#include "cogl-list.h" + +typedef struct _CoglNode CoglNode; + +/* Pipelines and layers represent their state in a tree structure where + * some of the state relating to a given pipeline or layer may actually + * be owned by one if is ancestors in the tree. We have a common data + * type to track the tree heirachy so we can share code... */ +struct _CoglNode +{ + /* the parent in terms of class hierarchy, so anything inheriting + * from CoglNode also inherits from CoglObject. */ + CoglObject _parent; + + /* The parent pipeline/layer */ + CoglNode *parent; + + /* The list entry here contains pointers to the node's siblings */ + CoglList link; + + /* List of children */ + CoglList children; + + /* TRUE if the node took a strong reference on its parent. Weak + * pipelines for instance don't take a reference on their parent. */ + CoglBool has_parent_reference; +}; + +#define COGL_NODE(X) ((CoglNode *)(X)) + +void +_cogl_pipeline_node_init (CoglNode *node); + +typedef void (*CoglNodeUnparentVFunc) (CoglNode *node); + +void +_cogl_pipeline_node_set_parent_real (CoglNode *node, + CoglNode *parent, + CoglNodeUnparentVFunc unparent, + CoglBool take_strong_reference); + +void +_cogl_pipeline_node_unparent_real (CoglNode *node); + +typedef CoglBool (*CoglNodeChildCallback) (CoglNode *child, void *user_data); + +void +_cogl_pipeline_node_foreach_child (CoglNode *node, + CoglNodeChildCallback callback, + void *user_data); + +#endif /* __COGL_NODE_PRIVATE_H */ diff --git a/cogl/cogl/cogl-node.c b/cogl/cogl/cogl-node.c new file mode 100644 index 0000000..dcec3cc --- /dev/null +++ b/cogl/cogl/cogl-node.c @@ -0,0 +1,110 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-util.h" +#include "cogl-node-private.h" + +void +_cogl_pipeline_node_init (CoglNode *node) +{ + node->parent = NULL; + _cogl_list_init (&node->children); +} + +void +_cogl_pipeline_node_set_parent_real (CoglNode *node, + CoglNode *parent, + CoglNodeUnparentVFunc unparent, + CoglBool take_strong_reference) +{ + /* NB: the old parent may indirectly be keeping the new parent alive + * so we have to ref the new parent before unrefing the old. + * + * Note: we take a reference here regardless of + * take_strong_reference because weak children may need special + * handling when the parent disposes itself which relies on a + * consistent link to all weak nodes. Once the node is linked to its + * parent then we remove the reference at the end if + * take_strong_reference == FALSE. */ + cogl_object_ref (parent); + + if (node->parent) + unparent (node); + + _cogl_list_insert (&parent->children, &node->link); + + node->parent = parent; + node->has_parent_reference = take_strong_reference; + + /* Now that there is a consistent parent->child link we can remove + * the parent reference if no reference was requested. If it turns + * out that the new parent was only being kept alive by the old + * parent then it will be disposed of here. */ + if (!take_strong_reference) + cogl_object_unref (parent); +} + +void +_cogl_pipeline_node_unparent_real (CoglNode *node) +{ + CoglNode *parent = node->parent; + + if (parent == NULL) + return; + + _COGL_RETURN_IF_FAIL (!_cogl_list_empty (&parent->children)); + + _cogl_list_remove (&node->link); + + if (node->has_parent_reference) + cogl_object_unref (parent); + + node->parent = NULL; +} + +void +_cogl_pipeline_node_foreach_child (CoglNode *node, + CoglNodeChildCallback callback, + void *user_data) +{ + CoglNode *child, *next; + + _cogl_list_for_each_safe (child, next, &node->children, link) + callback (child, user_data); +} + + diff --git a/cogl/cogl/cogl-object-private.h b/cogl/cogl/cogl-object-private.h new file mode 100644 index 0000000..c63e323 --- /dev/null +++ b/cogl/cogl/cogl-object-private.h @@ -0,0 +1,317 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_OBJECT_PRIVATE_H +#define __COGL_OBJECT_PRIVATE_H + +#include + +#include "cogl-types.h" +#include "cogl-object.h" +#include "cogl-debug.h" + +/* For compatability until all components have been converted */ +typedef struct _CoglObjectClass CoglHandleClass; +typedef struct _CoglObject CoglHandleObject; + +/* XXX: sadly we didn't fully consider when we copied the cairo API + * for _set_user_data that the callback doesn't get a pointer to the + * instance which is desired in most cases. This means you tend to end + * up creating micro allocations for the private data just so you can + * pair up the data of interest with the original instance for + * identification when it is later destroyed. + * + * Internally we use a small hack to avoid needing these micro + * allocations by actually passing the instance as a second argument + * to the callback */ +typedef void (*CoglUserDataDestroyInternalCallback) (void *user_data, + void *instance); + +typedef struct _CoglObjectClass +{ + GTypeClass base_class; + const char *name; + void *virt_free; + void *virt_unref; +} CoglObjectClass; + +#define COGL_OBJECT_N_PRE_ALLOCATED_USER_DATA_ENTRIES 2 + +typedef struct +{ + CoglUserDataKey *key; + void *user_data; + CoglUserDataDestroyInternalCallback destroy; +} CoglUserDataEntry; + +/* All Cogl objects inherit from this base object by adding a member: + * + * CoglObject _parent; + * + * at the top of its main structure. This structure is initialized + * when you call _cogl_#type_name#_object_new (new_object); + */ +struct _CoglObject +{ + CoglObjectClass *klass; /* equivalent to GTypeInstance */ + + CoglUserDataEntry user_data_entry[ + COGL_OBJECT_N_PRE_ALLOCATED_USER_DATA_ENTRIES]; + GArray *user_data_array; + int n_user_data_entries; + + unsigned int ref_count; +}; + +/* Helper macro to encapsulate the common code for COGL reference + counted objects */ + +#ifdef COGL_OBJECT_DEBUG + +#define _COGL_OBJECT_DEBUG_NEW(type_name, obj) \ + COGL_NOTE (OBJECT, "COGL " G_STRINGIFY (type_name) " NEW %p %i", \ + (obj), (obj)->ref_count) + +#define _COGL_OBJECT_DEBUG_REF(type_name, object) G_STMT_START { \ + CoglObject *__obj = (CoglObject *)object; \ + COGL_NOTE (OBJECT, "COGL %s REF %p %i", \ + (__obj)->klass->name, \ + (__obj), (__obj)->ref_count); } G_STMT_END + +#define _COGL_OBJECT_DEBUG_UNREF(type_name, object) G_STMT_START { \ + CoglObject *__obj = (CoglObject *)object; \ + COGL_NOTE (OBJECT, "COGL %s UNREF %p %i", \ + (__obj)->klass->name, \ + (__obj), (__obj)->ref_count - 1); } G_STMT_END + +#define COGL_OBJECT_DEBUG_FREE(obj) \ + COGL_NOTE (OBJECT, "COGL %s FREE %p", \ + (obj)->klass->name, (obj)) + +#else /* !COGL_OBJECT_DEBUG */ + +#define _COGL_OBJECT_DEBUG_NEW(type_name, obj) +#define _COGL_OBJECT_DEBUG_REF(type_name, obj) +#define _COGL_OBJECT_DEBUG_UNREF(type_name, obj) +#define COGL_OBJECT_DEBUG_FREE(obj) + +#endif /* COGL_OBJECT_DEBUG */ + +#define _COGL_GTYPE_INIT_CLASS(type_name) do { \ + _cogl_##type_name##_class.base_class.g_type = cogl_##type_name##_get_gtype (); \ +} while (0) + +#define COGL_OBJECT_COMMON_DEFINE_WITH_CODE(TypeName, type_name, code) \ + \ +CoglObjectClass _cogl_##type_name##_class; \ +static unsigned long _cogl_object_##type_name##_count; \ + \ +static inline void \ +_cogl_object_##type_name##_inc (void) \ +{ \ + _cogl_object_##type_name##_count++; \ +} \ + \ +static inline void \ +_cogl_object_##type_name##_dec (void) \ +{ \ + _cogl_object_##type_name##_count--; \ +} \ + \ +static void \ +_cogl_object_##type_name##_indirect_free (CoglObject *obj) \ +{ \ + _cogl_##type_name##_free ((Cogl##TypeName *) obj); \ + _cogl_object_##type_name##_dec (); \ +} \ + \ +static void \ +_cogl_object_##type_name##_class_init (void) \ +{ \ + _cogl_object_##type_name##_count = 0; \ + \ + if (_cogl_debug_instances == NULL) \ + _cogl_debug_instances = \ + g_hash_table_new (g_str_hash, g_str_equal); \ + \ + _cogl_##type_name##_class.virt_free = \ + _cogl_object_##type_name##_indirect_free; \ + _cogl_##type_name##_class.virt_unref = \ + _cogl_object_default_unref; \ + _cogl_##type_name##_class.name = "Cogl"#TypeName; \ + \ + g_hash_table_insert (_cogl_debug_instances, \ + (void *) _cogl_##type_name##_class.name, \ + &_cogl_object_##type_name##_count); \ + \ + { code; } \ +} \ + \ +static Cogl##TypeName * \ +_cogl_##type_name##_object_new (Cogl##TypeName *new_obj) \ +{ \ + CoglObject *obj = (CoglObject *)&new_obj->_parent; \ + obj->ref_count = 0; \ + cogl_object_ref (obj); \ + obj->n_user_data_entries = 0; \ + obj->user_data_array = NULL; \ + \ + obj->klass = &_cogl_##type_name##_class; \ + if (!obj->klass->virt_free) \ + { \ + _cogl_object_##type_name##_class_init (); \ + } \ + \ + _cogl_object_##type_name##_inc (); \ + _COGL_OBJECT_DEBUG_NEW (TypeName, obj); \ + return new_obj; \ +} + +#define COGL_OBJECT_DEFINE_WITH_CODE_GTYPE(TypeName, type_name, code) \ + \ +COGL_OBJECT_COMMON_DEFINE_WITH_CODE(TypeName, \ + type_name, \ + do { code; } while (0); \ + _COGL_GTYPE_INIT_CLASS (type_name)) \ + \ +CoglBool \ +cogl_is_##type_name (void *object) \ +{ \ + CoglObject *obj = object; \ + \ + if (object == NULL) \ + return FALSE; \ + \ + return obj->klass == &_cogl_##type_name##_class; \ +} + +#define COGL_OBJECT_DEFINE_WITH_CODE(TypeName, type_name, code) \ + \ +COGL_OBJECT_COMMON_DEFINE_WITH_CODE(TypeName, type_name, code) \ + \ +CoglBool \ +cogl_is_##type_name (void *object) \ +{ \ + CoglObject *obj = object; \ + \ + if (object == NULL) \ + return FALSE; \ + \ + return obj->klass == &_cogl_##type_name##_class; \ +} + +#define COGL_OBJECT_INTERNAL_DEFINE_WITH_CODE(TypeName, type_name, code) \ + \ +COGL_OBJECT_COMMON_DEFINE_WITH_CODE(TypeName, type_name, code) \ + \ +CoglBool \ +_cogl_is_##type_name (void *object) \ +{ \ + CoglObject *obj = object; \ + \ + if (object == NULL) \ + return FALSE; \ + \ + return obj->klass == &_cogl_##type_name##_class; \ +} + +#define COGL_OBJECT_DEFINE_DEPRECATED_REF_COUNTING(type_name) \ + \ +void * G_GNUC_DEPRECATED \ +cogl_##type_name##_ref (void *object) \ +{ \ + if (!cogl_is_##type_name (object)) \ + return NULL; \ + \ + _COGL_OBJECT_DEBUG_REF (TypeName, object); \ + \ + cogl_handle_ref (object); \ + \ + return object; \ +} \ + \ +void G_GNUC_DEPRECATED \ +cogl_##type_name##_unref (void *object) \ +{ \ + if (!cogl_is_##type_name (object)) \ + { \ + g_warning (G_STRINGIFY (cogl_##type_name##_unref) \ + ": Ignoring unref of Cogl handle " \ + "due to type mismatch"); \ + return; \ + } \ + \ + _COGL_OBJECT_DEBUG_UNREF (TypeName, object); \ + \ + cogl_handle_unref (object); \ +} + +#define COGL_OBJECT_DEFINE(TypeName, type_name) \ + COGL_OBJECT_DEFINE_WITH_CODE_GTYPE (TypeName, type_name, (void) 0) + +#define COGL_OBJECT_INTERNAL_DEFINE(TypeName, type_name) \ + COGL_OBJECT_INTERNAL_DEFINE_WITH_CODE (TypeName, type_name, (void) 0) + +/* For temporary compatability */ +#define COGL_HANDLE_INTERNAL_DEFINE_WITH_CODE(TypeName, type_name, code) \ + \ +COGL_OBJECT_INTERNAL_DEFINE_WITH_CODE (TypeName, type_name, code) \ + \ +static Cogl##TypeName * \ +_cogl_##type_name##_handle_new (CoglHandle handle) \ +{ \ + return _cogl_##type_name##_object_new (handle); \ +} + +#define COGL_HANDLE_DEFINE_WITH_CODE(TypeName, type_name, code) \ + \ +COGL_OBJECT_DEFINE_WITH_CODE (TypeName, type_name, code) \ + \ +static Cogl##TypeName * \ +_cogl_##type_name##_handle_new (CoglHandle handle) \ +{ \ + return _cogl_##type_name##_object_new (handle); \ +} + +#define COGL_HANDLE_DEFINE(TypeName, type_name) \ + COGL_HANDLE_DEFINE_WITH_CODE (TypeName, type_name, (void) 0) + +void +_cogl_object_set_user_data (CoglObject *object, + CoglUserDataKey *key, + void *user_data, + CoglUserDataDestroyInternalCallback destroy); + +void +_cogl_object_default_unref (void *obj); + +#endif /* __COGL_OBJECT_PRIVATE_H */ + diff --git a/cogl/cogl/cogl-object.c b/cogl/cogl/cogl-object.c new file mode 100644 index 0000000..1b849d5 --- /dev/null +++ b/cogl/cogl/cogl-object.c @@ -0,0 +1,304 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include +#include + +#include "cogl-util.h" +#include "cogl-types.h" +#include "cogl-object-private.h" +#include "cogl-gtype-private.h" + +COGL_GTYPE_DEFINE_BASE_CLASS (Object, object); + +void * +cogl_object_ref (void *object) +{ + CoglObject *obj = object; + + _COGL_RETURN_VAL_IF_FAIL (object != NULL, NULL); + + obj->ref_count++; + return object; +} + +CoglHandle +cogl_handle_ref (CoglHandle handle) +{ + return cogl_object_ref (handle); +} + +void +_cogl_object_default_unref (void *object) +{ + CoglObject *obj = object; + + _COGL_RETURN_IF_FAIL (object != NULL); + _COGL_RETURN_IF_FAIL (obj->ref_count > 0); + + if (--obj->ref_count < 1) + { + void (*free_func)(void *obj); + + if (obj->n_user_data_entries) + { + int i; + int count = MIN (obj->n_user_data_entries, + COGL_OBJECT_N_PRE_ALLOCATED_USER_DATA_ENTRIES); + + for (i = 0; i < count; i++) + { + CoglUserDataEntry *entry = &obj->user_data_entry[i]; + if (entry->destroy) + entry->destroy (entry->user_data, obj); + } + + if (obj->user_data_array != NULL) + { + for (i = 0; i < obj->user_data_array->len; i++) + { + CoglUserDataEntry *entry = + &g_array_index (obj->user_data_array, + CoglUserDataEntry, i); + + if (entry->destroy) + entry->destroy (entry->user_data, obj); + } + g_array_free (obj->user_data_array, TRUE); + } + } + + COGL_OBJECT_DEBUG_FREE (obj); + free_func = obj->klass->virt_free; + free_func (obj); + } +} + +void +cogl_object_unref (void *obj) +{ + void (* unref_func) (void *) = ((CoglObject *) obj)->klass->virt_unref; + unref_func (obj); +} + +void +cogl_handle_unref (CoglHandle handle) +{ + cogl_object_unref (handle); +} + +GType +cogl_handle_get_type (void) +{ + static GType our_type = 0; + + /* XXX: We are keeping the "CoglHandle" name for now incase it would + * break bindings to change to "CoglObject" */ + if (G_UNLIKELY (our_type == 0)) + our_type = g_boxed_type_register_static (g_intern_static_string ("CoglHandle"), + (GBoxedCopyFunc) cogl_object_ref, + (GBoxedFreeFunc) cogl_object_unref); + + return our_type; +} + +/* XXX: Unlike for cogl_object_get_user_data this code will return + * an empty entry if available and no entry for the given key can be + * found. */ +static CoglUserDataEntry * +_cogl_object_find_entry (CoglObject *object, CoglUserDataKey *key) +{ + CoglUserDataEntry *entry = NULL; + int count; + int i; + + count = MIN (object->n_user_data_entries, + COGL_OBJECT_N_PRE_ALLOCATED_USER_DATA_ENTRIES); + + for (i = 0; i < count; i++) + { + CoglUserDataEntry *current = &object->user_data_entry[i]; + if (current->key == key) + return current; + if (current->user_data == NULL) + entry = current; + } + + if (G_UNLIKELY (object->user_data_array != NULL)) + { + for (i = 0; i < object->user_data_array->len; i++) + { + CoglUserDataEntry *current = + &g_array_index (object->user_data_array, CoglUserDataEntry, i); + + if (current->key == key) + return current; + if (current->user_data == NULL) + entry = current; + } + } + + return entry; +} + +void +_cogl_object_set_user_data (CoglObject *object, + CoglUserDataKey *key, + void *user_data, + CoglUserDataDestroyInternalCallback destroy) +{ + CoglUserDataEntry new_entry; + CoglUserDataEntry *entry; + + if (user_data) + { + new_entry.key = key; + new_entry.user_data = user_data; + new_entry.destroy = destroy; + } + else + memset (&new_entry, 0, sizeof (new_entry)); + + entry = _cogl_object_find_entry (object, key); + if (entry) + { + if (G_LIKELY (entry->destroy)) + entry->destroy (entry->user_data, object); + } + else + { + /* NB: Setting a value of NULL is documented to delete the + * corresponding entry so we can return immediately in this + * case. */ + if (user_data == NULL) + return; + + if (G_LIKELY (object->n_user_data_entries < + COGL_OBJECT_N_PRE_ALLOCATED_USER_DATA_ENTRIES)) + entry = &object->user_data_entry[object->n_user_data_entries++]; + else + { + if (G_UNLIKELY (object->user_data_array == NULL)) + { + object->user_data_array = + g_array_new (FALSE, FALSE, sizeof (CoglUserDataEntry)); + } + + g_array_set_size (object->user_data_array, + object->user_data_array->len + 1); + entry = + &g_array_index (object->user_data_array, CoglUserDataEntry, + object->user_data_array->len - 1); + + object->n_user_data_entries++; + } + } + + *entry = new_entry; +} + +void +cogl_object_set_user_data (CoglObject *object, + CoglUserDataKey *key, + void *user_data, + CoglUserDataDestroyCallback destroy) +{ + _cogl_object_set_user_data (object, key, user_data, + (CoglUserDataDestroyInternalCallback)destroy); +} + +void * +cogl_object_get_user_data (CoglObject *object, CoglUserDataKey *key) +{ + int count; + int i; + + count = MIN (object->n_user_data_entries, + COGL_OBJECT_N_PRE_ALLOCATED_USER_DATA_ENTRIES); + + for (i = 0; i < count; i++) + { + CoglUserDataEntry *entry = &object->user_data_entry[i]; + if (entry->key == key) + return entry->user_data; + } + + if (object->user_data_array != NULL) + { + for (i = 0; i < object->user_data_array->len; i++) + { + CoglUserDataEntry *entry = + &g_array_index (object->user_data_array, CoglUserDataEntry, i); + + if (entry->key == key) + return entry->user_data; + } + } + + return NULL; +} + +void +cogl_debug_object_foreach_type (CoglDebugObjectForeachTypeCallback func, + void *user_data) +{ + GHashTableIter iter; + unsigned long *instance_count; + CoglDebugObjectTypeInfo info; + + g_hash_table_iter_init (&iter, _cogl_debug_instances); + while (g_hash_table_iter_next (&iter, + (void *) &info.name, + (void *) &instance_count)) + { + info.instance_count = *instance_count; + func (&info, user_data); + } +} + +static void +print_instances_cb (const CoglDebugObjectTypeInfo *info, + void *user_data) +{ + g_print ("\t%s: %lu\n", info->name, info->instance_count); +} + +void +cogl_debug_object_print_instances (void) +{ + g_print ("Cogl instances:\n"); + + cogl_debug_object_foreach_type (print_instances_cb, NULL); +} diff --git a/cogl/cogl/cogl-object.h b/cogl/cogl/cogl-object.h new file mode 100644 index 0000000..fa52958 --- /dev/null +++ b/cogl/cogl/cogl-object.h @@ -0,0 +1,236 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_OBJECT_H +#define __COGL_OBJECT_H + +#include + +#include + +COGL_BEGIN_DECLS + +typedef struct _CoglObject CoglObject; + +#define COGL_OBJECT(X) ((CoglObject *)X) + +/** + * CoglObject: (ref-func cogl_object_ref) (unref-func cogl_object_unref) + * (set-value-func cogl_object_value_set_object) + * (get-value-func cogl_object_get_object) + */ + +/** + * cogl_object_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_object_get_gtype (void); + +/** + * cogl_object_ref: (skip) + * @object: a #CoglObject + * + * Increases the reference count of @object by 1 + * + * Returns: the @object, with its reference count increased + */ +void * +cogl_object_ref (void *object); + +/** + * cogl_object_unref: (skip) + * @object: a #CoglObject + * + * Drecreases the reference count of @object by 1; if the reference + * count reaches 0, the resources allocated by @object will be freed + */ +void +cogl_object_unref (void *object); + +/** + * CoglUserDataKey: + * @unused: ignored. + * + * A #CoglUserDataKey is used to declare a key for attaching data to a + * #CoglObject using cogl_object_set_user_data. The typedef only exists as a + * formality to make code self documenting since only the unique address of a + * #CoglUserDataKey is used. + * + * Typically you would declare a static #CoglUserDataKey and set private data + * on an object something like this: + * + * |[ + * static CoglUserDataKey path_private_key; + * + * static void + * destroy_path_private_cb (void *data) + * { + * g_free (data); + * } + * + * static void + * my_path_set_data (CoglPath *path, void *data) + * { + * cogl_object_set_user_data (COGL_OBJECT (path), + * &private_key, + * data, + * destroy_path_private_cb); + * } + * ]| + * + * Since: 1.4 + */ +typedef struct { + int unused; +} CoglUserDataKey; + +/** + * CoglUserDataDestroyCallback: + * @user_data: The data whos association with a #CoglObject has been + * destoyed. + * + * When associating private data with a #CoglObject a callback can be + * given which will be called either if the object is destroyed or if + * cogl_object_set_user_data() is called with NULL user_data for the + * same key. + * + * Since: 1.4 + */ +typedef GDestroyNotify CoglUserDataDestroyCallback; + +/** + * CoglDebugObjectTypeInfo: + * @name: A human readable name for the type. + * @instance_count: The number of objects of this type that are + * currently in use + * + * This struct is used to pass information to the callback when + * cogl_debug_object_foreach_type() is called. + * + * Since: 1.8 + * Stability: unstable + */ +typedef struct { + const char *name; + unsigned long instance_count; +} CoglDebugObjectTypeInfo; + +/** + * CoglDebugObjectForeachTypeCallback: + * @info: A pointer to a struct containing information about the type. + * + * A callback function to use for cogl_debug_object_foreach_type(). + * + * Since: 1.8 + * Stability: unstable + */ +typedef void +(* CoglDebugObjectForeachTypeCallback) (const CoglDebugObjectTypeInfo *info, + void *user_data); + +/** + * cogl_object_set_user_data: (skip) + * @object: The object to associate private data with + * @key: The address of a #CoglUserDataKey which provides a unique value + * with which to index the private data. + * @user_data: The data to associate with the given object, + * or %NULL to remove a previous association. + * @destroy: A #CoglUserDataDestroyCallback to call if the object is + * destroyed or if the association is removed by later setting + * %NULL data for the same key. + * + * Associates some private @user_data with a given #CoglObject. To + * later remove the association call cogl_object_set_user_data() with + * the same @key but NULL for the @user_data. + * + * Since: 1.4 + */ +void +cogl_object_set_user_data (CoglObject *object, + CoglUserDataKey *key, + void *user_data, + CoglUserDataDestroyCallback destroy); + +/** + * cogl_object_get_user_data: (skip) + * @object: The object with associated private data to query + * @key: The address of a #CoglUserDataKey which provides a unique value + * with which to index the private data. + * + * Finds the user data previously associated with @object using + * the given @key. If no user data has been associated with @object + * for the given @key this function returns NULL. + * + * Returns: (transfer none): The user data previously associated + * with @object using the given @key; or %NULL if no associated + * data is found. + * + * Since: 1.4 + */ +void * +cogl_object_get_user_data (CoglObject *object, + CoglUserDataKey *key); + +/** + * cogl_debug_object_foreach_type: + * @func: (scope call): A callback function for each type + * @user_data: (closure): A pointer to pass to @func + * + * Invokes @func once for each type of object that Cogl uses and + * passes a count of the number of objects for that type. This is + * intended to be used solely for debugging purposes to track down + * issues with objects leaking. + * + * Since: 1.8 + * Stability: unstable + */ +void +cogl_debug_object_foreach_type (CoglDebugObjectForeachTypeCallback func, + void *user_data); + +/** + * cogl_debug_object_print_instances: + * + * Prints a list of all the object types that Cogl uses along with the + * number of objects of that type that are currently in use. This is + * intended to be used solely for debugging purposes to track down + * issues with objects leaking. + * + * Since: 1.8 + * Stability: unstable + */ +void +cogl_debug_object_print_instances (void); + +COGL_END_DECLS + +#endif /* __COGL_OBJECT_H */ + diff --git a/cogl/cogl/cogl-offscreen.h b/cogl/cogl/cogl-offscreen.h new file mode 100644 index 0000000..5c26370 --- /dev/null +++ b/cogl/cogl/cogl-offscreen.h @@ -0,0 +1,174 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_OFFSCREEN_H__ +#define __COGL_OFFSCREEN_H__ + +#include +#include + +#include + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-offscreen + * @short_description: Functions for creating and manipulating offscreen + * framebuffers. + * + * Cogl allows creating and operating on offscreen framebuffers. + */ + +typedef struct _CoglOffscreen CoglOffscreen; + +#define COGL_OFFSCREEN(X) ((CoglOffscreen *)X) + +/** + * cogl_offscreen_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_offscreen_get_gtype (void); + +/* Offscreen api */ + +/** + * cogl_offscreen_new_with_texture: + * @texture: A #CoglTexture pointer + * + * This creates an offscreen framebuffer object using the given + * @texture as the primary color buffer. It doesn't just initialize + * the contents of the offscreen buffer with the @texture; they are + * tightly bound so that drawing to the offscreen buffer effectively + * updates the contents of the given texture. You don't need to + * destroy the offscreen buffer before you can use the @texture again. + * + * This api only works with low-level #CoglTexture types such as + * #CoglTexture2D, #CoglTexture3D and #CoglTextureRectangle, and not + * with meta-texture types such as #CoglTexture2DSliced. + * + * The storage for the framebuffer is actually allocated lazily + * so this function will never return %NULL to indicate a runtime + * error. This means it is still possible to configure the framebuffer + * before it is really allocated. + * + * Simple applications without full error handling can simply rely on + * Cogl to lazily allocate the storage of framebuffers but you should + * be aware that if Cogl encounters an error (such as running out of + * GPU memory) then your application will simply abort with an error + * message. If you need to be able to catch such exceptions at runtime + * then you can explicitly allocate your framebuffer when you have + * finished configuring it by calling cogl_framebuffer_allocate() and + * passing in a #CoglError argument to catch any exceptions. + * + * Return value: (transfer full): a newly instantiated #CoglOffscreen + * framebuffer. + */ +CoglOffscreen * +cogl_offscreen_new_with_texture (CoglTexture *texture); + +/** + * cogl_offscreen_new_to_texture: + * @texture: A #CoglTexture pointer + * + * This creates an offscreen buffer object using the given @texture as the + * primary color buffer. It doesn't just initialize the contents of the + * offscreen buffer with the @texture; they are tightly bound so that + * drawing to the offscreen buffer effectivly updates the contents of the + * given texture. You don't need to destroy the offscreen buffer before + * you can use the @texture again. + * + * This only works with low-level #CoglTexture types such as + * #CoglTexture2D, #CoglTexture3D and #CoglTextureRectangle, and not + * with meta-texture types such as #CoglTexture2DSliced. + * + * Return value: (transfer full): a newly instantiated #CoglOffscreen + * framebuffer or %NULL if it wasn't possible to create the + * buffer. + * Deprecated: 1.16: Use cogl_offscreen_new_with_texture instead. + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_offscreen_new_with_texture) +CoglOffscreen * +cogl_offscreen_new_to_texture (CoglTexture *texture); + +/** + * cogl_is_offscreen: + * @object: A pointer to a #CoglObject + * + * Determines whether the given #CoglObject references an offscreen + * framebuffer object. + * + * Returns: %TRUE if @object is a #CoglOffscreen framebuffer, + * %FALSE otherwise + */ +CoglBool +cogl_is_offscreen (void *object); + +/** + * cogl_offscreen_ref: + * @offscreen: A pointer to a #CoglOffscreen framebuffer + * + * Increments the reference count on the @offscreen framebuffer. + * + * Return value: (transfer none): For convenience it returns the + * given @offscreen + * + * Deprecated: 1.2: cogl_object_ref() should be used in new code. + */ +COGL_DEPRECATED_FOR (cogl_object_ref) +void * +cogl_offscreen_ref (void *offscreen); + +/** + * cogl_offscreen_unref: + * @offscreen: A pointer to a #CoglOffscreen framebuffer + * + * Decreases the reference count for the @offscreen buffer and frees it when + * the count reaches 0. + * + * Deprecated: 1.2: cogl_object_unref() should be used in new code. + */ +COGL_DEPRECATED_FOR (cogl_object_unref) +void +cogl_offscreen_unref (void *offscreen); + +/** + * cogl_offscreen_get_texture: (skip) + */ +CoglTexture * +cogl_offscreen_get_texture (CoglOffscreen *offscreen); + +COGL_END_DECLS + +#endif /* __COGL_OFFSCREEN_H__ */ diff --git a/cogl/cogl/cogl-onscreen-private.h b/cogl/cogl/cogl-onscreen-private.h new file mode 100644 index 0000000..0a67832 --- /dev/null +++ b/cogl/cogl/cogl-onscreen-private.h @@ -0,0 +1,115 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011,2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_ONSCREEN_PRIVATE_H +#define __COGL_ONSCREEN_PRIVATE_H + +#include "cogl-onscreen.h" +#include "cogl-framebuffer-private.h" +#include "cogl-closure-list-private.h" +#include "cogl-list.h" + +#include + +typedef struct _CoglOnscreenEvent +{ + CoglList link; + + CoglOnscreen *onscreen; + CoglFrameInfo *info; + CoglFrameEvent type; +} CoglOnscreenEvent; + +typedef struct _CoglOnscreenQueuedDirty +{ + CoglList link; + + CoglOnscreen *onscreen; + CoglOnscreenDirtyInfo info; +} CoglOnscreenQueuedDirty; + +struct _CoglOnscreen +{ + CoglFramebuffer _parent; + +#ifdef COGL_HAS_X11_SUPPORT + uint32_t foreign_xid; + CoglOnscreenX11MaskCallback foreign_update_mask_callback; + void *foreign_update_mask_data; +#endif + + CoglBool swap_throttled; + + CoglList frame_closures; + + CoglBool resizable; + CoglList resize_closures; + + CoglList dirty_closures; + + int64_t frame_counter; + int64_t swap_frame_counter; /* frame counter at last all to + * cogl_onscreen_swap_region() or + * cogl_onscreen_swap_buffers() */ + GQueue pending_frame_infos; + + void *winsys; +}; + +CoglOnscreen * +_cogl_onscreen_new (void); + +void +_cogl_framebuffer_winsys_update_size (CoglFramebuffer *framebuffer, + int width, int height); + +void +_cogl_onscreen_queue_event (CoglOnscreen *onscreen, + CoglFrameEvent type, + CoglFrameInfo *info); + +void +_cogl_onscreen_notify_frame_sync (CoglOnscreen *onscreen, CoglFrameInfo *info); + +void +_cogl_onscreen_notify_complete (CoglOnscreen *onscreen, CoglFrameInfo *info); + +void +_cogl_onscreen_notify_resize (CoglOnscreen *onscreen); + +void +_cogl_onscreen_queue_dirty (CoglOnscreen *onscreen, + const CoglOnscreenDirtyInfo *info); + + +void +_cogl_onscreen_queue_full_dirty (CoglOnscreen *onscreen); + +#endif /* __COGL_ONSCREEN_PRIVATE_H */ diff --git a/cogl/cogl/cogl-onscreen-template-private.h b/cogl/cogl/cogl-onscreen-template-private.h new file mode 100644 index 0000000..1b19d35 --- /dev/null +++ b/cogl/cogl/cogl-onscreen-template-private.h @@ -0,0 +1,45 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_ONSCREEN_TEMPLATE_PRIVATE_H +#define __COGL_ONSCREEN_TEMPLATE_PRIVATE_H + +#include "cogl-object-private.h" +#include "cogl-swap-chain.h" +#include "cogl-framebuffer-private.h" + +struct _CoglOnscreenTemplate +{ + CoglObject _parent; + + CoglFramebufferConfig config; +}; + +#endif /* __COGL_ONSCREEN_TEMPLATE_PRIVATE_H */ diff --git a/cogl/cogl/cogl-onscreen-template.c b/cogl/cogl/cogl-onscreen-template.c new file mode 100644 index 0000000..1adbf41 --- /dev/null +++ b/cogl/cogl/cogl-onscreen-template.c @@ -0,0 +1,105 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-object.h" + +#include "cogl-framebuffer-private.h" +#include "cogl-onscreen-template-private.h" +#include "cogl-gtype-private.h" + +#include + +static void _cogl_onscreen_template_free (CoglOnscreenTemplate *onscreen_template); + +COGL_OBJECT_DEFINE (OnscreenTemplate, onscreen_template); +COGL_GTYPE_DEFINE_CLASS (OnscreenTemplate, onscreen_template); + +static void +_cogl_onscreen_template_free (CoglOnscreenTemplate *onscreen_template) +{ + g_slice_free (CoglOnscreenTemplate, onscreen_template); +} + +CoglOnscreenTemplate * +cogl_onscreen_template_new (CoglSwapChain *swap_chain) +{ + CoglOnscreenTemplate *onscreen_template = g_slice_new0 (CoglOnscreenTemplate); + char *user_config; + + onscreen_template->config.swap_chain = swap_chain; + if (swap_chain) + cogl_object_ref (swap_chain); + else + onscreen_template->config.swap_chain = cogl_swap_chain_new (); + + onscreen_template->config.swap_throttled = TRUE; + onscreen_template->config.need_stencil = TRUE; + onscreen_template->config.samples_per_pixel = 0; + + user_config = getenv ("COGL_POINT_SAMPLES_PER_PIXEL"); + if (user_config) + { + unsigned long samples_per_pixel = strtoul (user_config, NULL, 10); + if (samples_per_pixel != ULONG_MAX) + onscreen_template->config.samples_per_pixel = + samples_per_pixel; + } + + return _cogl_onscreen_template_object_new (onscreen_template); +} + +void +cogl_onscreen_template_set_samples_per_pixel ( + CoglOnscreenTemplate *onscreen_template, + int samples_per_pixel) +{ + onscreen_template->config.samples_per_pixel = samples_per_pixel; +} + +void +cogl_onscreen_template_set_swap_throttled ( + CoglOnscreenTemplate *onscreen_template, + CoglBool throttled) +{ + onscreen_template->config.swap_throttled = throttled; +} + +void +cogl_onscreen_template_set_stereo_enabled ( + CoglOnscreenTemplate *onscreen_template, + CoglBool enabled) +{ + onscreen_template->config.stereo_enabled = enabled; +} diff --git a/cogl/cogl/cogl-onscreen-template.h b/cogl/cogl/cogl-onscreen-template.h new file mode 100644 index 0000000..2dd737b --- /dev/null +++ b/cogl/cogl/cogl-onscreen-template.h @@ -0,0 +1,139 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Robert Bragg + * + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_ONSCREEN_TEMPLATE_H__ +#define __COGL_ONSCREEN_TEMPLATE_H__ + +#include + +#include + +COGL_BEGIN_DECLS + +typedef struct _CoglOnscreenTemplate CoglOnscreenTemplate; + +#define COGL_ONSCREEN_TEMPLATE(OBJECT) ((CoglOnscreenTemplate *)OBJECT) + +/** + * cogl_onscreen_template_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_onscreen_template_get_gtype (void); + +CoglOnscreenTemplate * +cogl_onscreen_template_new (CoglSwapChain *swap_chain); + +/** + * cogl_onscreen_template_set_samples_per_pixel: + * @onscreen_template: A #CoglOnscreenTemplate template framebuffer + * @n: The minimum number of samples per pixel + * + * Requires that any future CoglOnscreen framebuffers derived from + * this template must support making at least @n samples per pixel + * which will all contribute to the final resolved color for that + * pixel. + * + * By default this value is usually set to 0 and that is referred to + * as "single-sample" rendering. A value of 1 or greater is referred + * to as "multisample" rendering. + * + * There are some semantic differences between single-sample + * rendering and multisampling with just 1 point sample such as it + * being redundant to use the cogl_framebuffer_resolve_samples() and + * cogl_framebuffer_resolve_samples_region() apis with single-sample + * rendering. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_onscreen_template_set_samples_per_pixel ( + CoglOnscreenTemplate *onscreen_template, + int n); + +/** + * cogl_onscreen_template_set_swap_throttled: + * @onscreen_template: A #CoglOnscreenTemplate template framebuffer + * @throttled: Whether throttling should be enabled + * + * Requests that any future #CoglOnscreen framebuffers derived from this + * template should enable or disable swap throttling according to the given + * @throttled argument. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_onscreen_template_set_swap_throttled ( + CoglOnscreenTemplate *onscreen_template, + CoglBool throttled); + +/** + * cogl_onscreen_template_set_stereo_enabled: + * @onscreen_template: A #CoglOnscreenTemplate template framebuffer + * @enabled: Whether framebuffers are created with stereo buffers + * + * Sets whether future #CoglOnscreen framebuffers derived from this + * template are attempted to be created with both left and right + * buffers, for use with stereo display. If the display system + * does not support stereo, then creation of the framebuffer will + * fail. + * + * Since: 1.20 + * Stability: unstable + */ +void +cogl_onscreen_template_set_stereo_enabled ( + CoglOnscreenTemplate *onscreen_template, + CoglBool enabled); +/** + * cogl_is_onscreen_template: + * @object: A #CoglObject pointer + * + * Gets whether the given object references a #CoglOnscreenTemplate. + * + * Return value: %TRUE if the object references a #CoglOnscreenTemplate + * and %FALSE otherwise. + * Since: 1.10 + * Stability: unstable + */ +CoglBool +cogl_is_onscreen_template (void *object); + +COGL_END_DECLS + +#endif /* __COGL_ONSCREEN_TEMPLATE_H__ */ diff --git a/cogl/cogl/cogl-onscreen.c b/cogl/cogl/cogl-onscreen.c new file mode 100644 index 0000000..e766e59 --- /dev/null +++ b/cogl/cogl/cogl-onscreen.c @@ -0,0 +1,720 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011, 2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-util.h" +#include "cogl-onscreen-private.h" +#include "cogl-frame-info-private.h" +#include "cogl-framebuffer-private.h" +#include "cogl-onscreen-template-private.h" +#include "cogl-context-private.h" +#include "cogl-object-private.h" +#include "cogl1-context.h" +#include "cogl-closure-list-private.h" +#include "cogl-poll-private.h" +#include "cogl-gtype-private.h" + +#ifdef COGL_HAS_X11_SUPPORT +#include "cogl-xlib-renderer.h" +#endif + +static void _cogl_onscreen_free (CoglOnscreen *onscreen); + +COGL_OBJECT_DEFINE_WITH_CODE_GTYPE (Onscreen, onscreen, + _cogl_onscreen_class.virt_unref = + _cogl_framebuffer_unref); +COGL_GTYPE_DEFINE_CLASS (Onscreen, onscreen, + COGL_GTYPE_IMPLEMENT_INTERFACE (framebuffer)); + +static gpointer +cogl_dummy_copy (gpointer data) +{ + return data; +} + +static void +cogl_dummy_free (gpointer data) +{ +} + +COGL_GTYPE_DEFINE_BOXED (FrameClosure, frame_closure, + cogl_dummy_copy, + cogl_dummy_free); +COGL_GTYPE_DEFINE_BOXED (OnscreenResizeClosure, + onscreen_resize_closure, + cogl_dummy_copy, + cogl_dummy_free); +COGL_GTYPE_DEFINE_BOXED (OnscreenDirtyClosure, + onscreen_dirty_closure, + cogl_dummy_copy, + cogl_dummy_free); + +static void +_cogl_onscreen_init_from_template (CoglOnscreen *onscreen, + CoglOnscreenTemplate *onscreen_template) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + + _cogl_list_init (&onscreen->frame_closures); + _cogl_list_init (&onscreen->resize_closures); + _cogl_list_init (&onscreen->dirty_closures); + + framebuffer->config = onscreen_template->config; + cogl_object_ref (framebuffer->config.swap_chain); +} + +/* XXX: While we still have backend in Clutter we need a dummy object + * to represent the CoglOnscreen framebuffer that the backend + * creates... */ +CoglOnscreen * +_cogl_onscreen_new (void) +{ + CoglOnscreen *onscreen = g_new0 (CoglOnscreen, 1); + + _COGL_GET_CONTEXT (ctx, NULL); + + _cogl_framebuffer_init (COGL_FRAMEBUFFER (onscreen), + ctx, + COGL_FRAMEBUFFER_TYPE_ONSCREEN, + 0x1eadbeef, /* width */ + 0x1eadbeef); /* height */ + /* NB: make sure to pass positive width/height numbers here + * because otherwise we'll hit input validation assertions!*/ + + _cogl_onscreen_init_from_template (onscreen, ctx->display->onscreen_template); + + COGL_FRAMEBUFFER (onscreen)->allocated = TRUE; + + /* XXX: Note we don't initialize onscreen->winsys in this case. */ + + return _cogl_onscreen_object_new (onscreen); +} + +CoglOnscreen * +cogl_onscreen_new (CoglContext *ctx, int width, int height) +{ + CoglOnscreen *onscreen; + + /* FIXME: We are assuming onscreen buffers will always be + premultiplied so we'll set the premult flag on the bitmap + format. This will usually be correct because the result of the + default blending operations for Cogl ends up with premultiplied + data in the framebuffer. However it is possible for the + framebuffer to be in whatever format depending on what + CoglPipeline is used to render to it. Eventually we may want to + add a way for an application to inform Cogl that the framebuffer + is not premultiplied in case it is being used for some special + purpose. */ + + onscreen = g_new0 (CoglOnscreen, 1); + _cogl_framebuffer_init (COGL_FRAMEBUFFER (onscreen), + ctx, + COGL_FRAMEBUFFER_TYPE_ONSCREEN, + width, /* width */ + height); /* height */ + + _cogl_onscreen_init_from_template (onscreen, ctx->display->onscreen_template); + + return _cogl_onscreen_object_new (onscreen); +} + +static void +_cogl_onscreen_free (CoglOnscreen *onscreen) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer); + CoglFrameInfo *frame_info; + + _cogl_closure_list_disconnect_all (&onscreen->resize_closures); + _cogl_closure_list_disconnect_all (&onscreen->frame_closures); + _cogl_closure_list_disconnect_all (&onscreen->dirty_closures); + + while ((frame_info = g_queue_pop_tail (&onscreen->pending_frame_infos))) + cogl_object_unref (frame_info); + g_queue_clear (&onscreen->pending_frame_infos); + + if (framebuffer->context->window_buffer == COGL_FRAMEBUFFER (onscreen)) + framebuffer->context->window_buffer = NULL; + + winsys->onscreen_deinit (onscreen); + _COGL_RETURN_IF_FAIL (onscreen->winsys == NULL); + + /* Chain up to parent */ + _cogl_framebuffer_free (framebuffer); + + g_free (onscreen); +} + +static void +notify_event (CoglOnscreen *onscreen, + CoglFrameEvent event, + CoglFrameInfo *info) +{ + _cogl_closure_list_invoke (&onscreen->frame_closures, + CoglFrameCallback, + onscreen, event, info); +} + +static void +_cogl_dispatch_onscreen_cb (CoglContext *context) +{ + CoglOnscreenEvent *event, *tmp; + CoglList queue; + + /* Dispatching the event callback may cause another frame to be + * drawn which in may cause another event to be queued immediately. + * To make sure this loop will only dispatch one set of events we'll + * steal the queue and iterate that separately */ + _cogl_list_init (&queue); + _cogl_list_insert_list (&queue, &context->onscreen_events_queue); + _cogl_list_init (&context->onscreen_events_queue); + + _cogl_closure_disconnect (context->onscreen_dispatch_idle); + context->onscreen_dispatch_idle = NULL; + + _cogl_list_for_each_safe (event, tmp, &queue, link) + { + CoglOnscreen *onscreen = event->onscreen; + CoglFrameInfo *info = event->info; + + notify_event (onscreen, event->type, info); + + cogl_object_unref (onscreen); + cogl_object_unref (info); + + g_slice_free (CoglOnscreenEvent, event); + } + + while (!_cogl_list_empty (&context->onscreen_dirty_queue)) + { + CoglOnscreenQueuedDirty *qe = + _cogl_container_of (context->onscreen_dirty_queue.next, + CoglOnscreenQueuedDirty, + link); + + _cogl_list_remove (&qe->link); + + _cogl_closure_list_invoke (&qe->onscreen->dirty_closures, + CoglOnscreenDirtyCallback, + qe->onscreen, + &qe->info); + + cogl_object_unref (qe->onscreen); + + g_slice_free (CoglOnscreenQueuedDirty, qe); + } +} + +static void +_cogl_onscreen_queue_dispatch_idle (CoglOnscreen *onscreen) +{ + CoglContext *ctx = COGL_FRAMEBUFFER (onscreen)->context; + + if (!ctx->onscreen_dispatch_idle) + { + ctx->onscreen_dispatch_idle = + _cogl_poll_renderer_add_idle (ctx->display->renderer, + (CoglIdleCallback) + _cogl_dispatch_onscreen_cb, + ctx, + NULL); + } +} + +void +_cogl_onscreen_queue_dirty (CoglOnscreen *onscreen, + const CoglOnscreenDirtyInfo *info) +{ + CoglContext *ctx = COGL_FRAMEBUFFER (onscreen)->context; + CoglOnscreenQueuedDirty *qe = g_slice_new (CoglOnscreenQueuedDirty); + + qe->onscreen = cogl_object_ref (onscreen); + qe->info = *info; + _cogl_list_insert (ctx->onscreen_dirty_queue.prev, &qe->link); + + _cogl_onscreen_queue_dispatch_idle (onscreen); +} + +void +_cogl_onscreen_queue_full_dirty (CoglOnscreen *onscreen) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + CoglOnscreenDirtyInfo info; + + info.x = 0; + info.y = 0; + info.width = framebuffer->width; + info.height = framebuffer->height; + + _cogl_onscreen_queue_dirty (onscreen, &info); +} + +void +_cogl_onscreen_queue_event (CoglOnscreen *onscreen, + CoglFrameEvent type, + CoglFrameInfo *info) +{ + CoglContext *ctx = COGL_FRAMEBUFFER (onscreen)->context; + + CoglOnscreenEvent *event = g_slice_new (CoglOnscreenEvent); + + event->onscreen = cogl_object_ref (onscreen); + event->info = cogl_object_ref (info); + event->type = type; + + _cogl_list_insert (ctx->onscreen_events_queue.prev, &event->link); + + _cogl_onscreen_queue_dispatch_idle (onscreen); +} + +void +cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen, + const int *rectangles, + int n_rectangles) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + const CoglWinsysVtable *winsys; + CoglFrameInfo *info; + + _COGL_RETURN_IF_FAIL (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN); + + info = _cogl_frame_info_new (); + info->frame_counter = onscreen->frame_counter; + g_queue_push_tail (&onscreen->pending_frame_infos, info); + + /* FIXME: we shouldn't need to flush *all* journals here! */ + cogl_flush (); + + winsys = _cogl_framebuffer_get_winsys (framebuffer); + winsys->onscreen_swap_buffers_with_damage (onscreen, + rectangles, n_rectangles); + cogl_framebuffer_discard_buffers (framebuffer, + COGL_BUFFER_BIT_COLOR | + COGL_BUFFER_BIT_DEPTH | + COGL_BUFFER_BIT_STENCIL); + + if (!_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT)) + { + CoglFrameInfo *info; + + g_warn_if_fail (onscreen->pending_frame_infos.length == 1); + + info = g_queue_pop_tail (&onscreen->pending_frame_infos); + + _cogl_onscreen_queue_event (onscreen, COGL_FRAME_EVENT_SYNC, info); + _cogl_onscreen_queue_event (onscreen, COGL_FRAME_EVENT_COMPLETE, info); + + cogl_object_unref (info); + } + + onscreen->frame_counter++; + framebuffer->mid_scene = FALSE; +} + +void +cogl_onscreen_swap_buffers (CoglOnscreen *onscreen) +{ + cogl_onscreen_swap_buffers_with_damage (onscreen, NULL, 0); +} + +void +cogl_onscreen_swap_region (CoglOnscreen *onscreen, + const int *rectangles, + int n_rectangles) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + const CoglWinsysVtable *winsys; + CoglFrameInfo *info; + + _COGL_RETURN_IF_FAIL (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN); + + info = _cogl_frame_info_new (); + info->frame_counter = onscreen->frame_counter; + g_queue_push_tail (&onscreen->pending_frame_infos, info); + + /* FIXME: we shouldn't need to flush *all* journals here! */ + cogl_flush (); + + winsys = _cogl_framebuffer_get_winsys (framebuffer); + + /* This should only be called if the winsys advertises + COGL_WINSYS_FEATURE_SWAP_REGION */ + _COGL_RETURN_IF_FAIL (winsys->onscreen_swap_region != NULL); + + winsys->onscreen_swap_region (COGL_ONSCREEN (framebuffer), + rectangles, + n_rectangles); + + cogl_framebuffer_discard_buffers (framebuffer, + COGL_BUFFER_BIT_COLOR | + COGL_BUFFER_BIT_DEPTH | + COGL_BUFFER_BIT_STENCIL); + + if (!_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT)) + { + CoglFrameInfo *info; + + g_warn_if_fail (onscreen->pending_frame_infos.length == 1); + + info = g_queue_pop_tail (&onscreen->pending_frame_infos); + + _cogl_onscreen_queue_event (onscreen, COGL_FRAME_EVENT_SYNC, info); + _cogl_onscreen_queue_event (onscreen, COGL_FRAME_EVENT_COMPLETE, info); + + cogl_object_unref (info); + } + + onscreen->frame_counter++; + framebuffer->mid_scene = FALSE; +} + +int +cogl_onscreen_get_buffer_age (CoglOnscreen *onscreen) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + const CoglWinsysVtable *winsys; + + _COGL_RETURN_VAL_IF_FAIL (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN, 0); + + winsys = _cogl_framebuffer_get_winsys (framebuffer); + + if (!winsys->onscreen_get_buffer_age) + return 0; + + return winsys->onscreen_get_buffer_age (onscreen); +} + +#ifdef COGL_HAS_X11_SUPPORT +void +cogl_x11_onscreen_set_foreign_window_xid (CoglOnscreen *onscreen, + uint32_t xid, + CoglOnscreenX11MaskCallback update, + void *user_data) +{ + /* We don't wan't applications to get away with being lazy here and not + * passing an update callback... */ + _COGL_RETURN_IF_FAIL (update); + + onscreen->foreign_xid = xid; + onscreen->foreign_update_mask_callback = update; + onscreen->foreign_update_mask_data = user_data; +} + +uint32_t +cogl_x11_onscreen_get_window_xid (CoglOnscreen *onscreen) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + + if (onscreen->foreign_xid) + return onscreen->foreign_xid; + else + { + const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer); + + /* This should only be called for x11 onscreens */ + _COGL_RETURN_VAL_IF_FAIL (winsys->onscreen_x11_get_window_xid != NULL, 0); + + return winsys->onscreen_x11_get_window_xid (onscreen); + } +} + +uint32_t +cogl_x11_onscreen_get_visual_xid (CoglOnscreen *onscreen) +{ + CoglContext *ctx = COGL_FRAMEBUFFER (onscreen)->context; + XVisualInfo *visinfo; + uint32_t id; + + /* This should only be called for xlib based onscreens */ + visinfo = cogl_xlib_renderer_get_visual_info (ctx->display->renderer); + if (visinfo == NULL) + return 0; + + id = (uint32_t)visinfo->visualid; + + return id; +} +#endif /* COGL_HAS_X11_SUPPORT */ + +CoglFrameClosure * +cogl_onscreen_add_frame_callback (CoglOnscreen *onscreen, + CoglFrameCallback callback, + void *user_data, + CoglUserDataDestroyCallback destroy) +{ + return _cogl_closure_list_add (&onscreen->frame_closures, + callback, + user_data, + destroy); +} + +void +cogl_onscreen_remove_frame_callback (CoglOnscreen *onscreen, + CoglFrameClosure *closure) +{ + _COGL_RETURN_IF_FAIL (closure); + + _cogl_closure_disconnect (closure); +} + +typedef struct _SwapBufferCallbackState +{ + CoglSwapBuffersNotify callback; + void *user_data; +} SwapBufferCallbackState; + +static void +destroy_swap_buffers_callback_state (void *user_data) +{ + g_slice_free (SwapBufferCallbackState, user_data); +} + +static void +shim_swap_buffers_callback (CoglOnscreen *onscreen, + CoglFrameEvent event, + CoglFrameInfo *info, + void *user_data) +{ + SwapBufferCallbackState *state = user_data; + + /* XXX: Note that technically it is a change in semantics for this + * interface to forward _SYNC events here and also makes the api + * name somewhat missleading. + * + * In practice though this interface is currently used by + * applications for throttling, not because they are strictly + * interested in knowing when a frame has been presented and so + * forwarding _SYNC events should serve them better. + */ + if (event == COGL_FRAME_EVENT_SYNC) + state->callback (COGL_FRAMEBUFFER (onscreen), state->user_data); +} + +unsigned int +cogl_onscreen_add_swap_buffers_callback (CoglOnscreen *onscreen, + CoglSwapBuffersNotify callback, + void *user_data) +{ + CoglContext *ctx = COGL_FRAMEBUFFER (onscreen)->context; + SwapBufferCallbackState *state = g_slice_new (SwapBufferCallbackState); + CoglFrameClosure *closure; + unsigned int id = ctx->next_swap_callback_id++; + + state->callback = callback; + state->user_data = user_data; + + closure = + cogl_onscreen_add_frame_callback (onscreen, + shim_swap_buffers_callback, + state, + destroy_swap_buffers_callback_state); + + g_hash_table_insert (ctx->swap_callback_closures, + GINT_TO_POINTER (id), + closure); + + return id; +} + +void +cogl_onscreen_remove_swap_buffers_callback (CoglOnscreen *onscreen, + unsigned int id) +{ + CoglContext *ctx = COGL_FRAMEBUFFER (onscreen)->context; + CoglFrameClosure *closure = g_hash_table_lookup (ctx->swap_callback_closures, + GINT_TO_POINTER (id)); + + _COGL_RETURN_IF_FAIL (closure); + + cogl_onscreen_remove_frame_callback (onscreen, closure); +} + +void +cogl_onscreen_set_swap_throttled (CoglOnscreen *onscreen, + CoglBool throttled) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + framebuffer->config.swap_throttled = throttled; + if (framebuffer->allocated) + { + const CoglWinsysVtable *winsys = + _cogl_framebuffer_get_winsys (framebuffer); + winsys->onscreen_update_swap_throttled (onscreen); + } +} + +void +cogl_onscreen_show (CoglOnscreen *onscreen) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + const CoglWinsysVtable *winsys; + + if (!framebuffer->allocated) + { + if (!cogl_framebuffer_allocate (framebuffer, NULL)) + return; + } + + winsys = _cogl_framebuffer_get_winsys (framebuffer); + if (winsys->onscreen_set_visibility) + winsys->onscreen_set_visibility (onscreen, TRUE); +} + +void +cogl_onscreen_hide (CoglOnscreen *onscreen) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + + if (framebuffer->allocated) + { + const CoglWinsysVtable *winsys = + _cogl_framebuffer_get_winsys (framebuffer); + if (winsys->onscreen_set_visibility) + winsys->onscreen_set_visibility (onscreen, FALSE); + } +} + +void +_cogl_onscreen_notify_frame_sync (CoglOnscreen *onscreen, CoglFrameInfo *info) +{ + notify_event (onscreen, COGL_FRAME_EVENT_SYNC, info); +} + +void +_cogl_onscreen_notify_complete (CoglOnscreen *onscreen, CoglFrameInfo *info) +{ + notify_event (onscreen, COGL_FRAME_EVENT_COMPLETE, info); +} + +void +_cogl_onscreen_notify_resize (CoglOnscreen *onscreen) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + + _cogl_closure_list_invoke (&onscreen->resize_closures, + CoglOnscreenResizeCallback, + onscreen, + framebuffer->width, + framebuffer->height); +} + +void +_cogl_framebuffer_winsys_update_size (CoglFramebuffer *framebuffer, + int width, int height) +{ + if (framebuffer->width == width && framebuffer->height == height) + return; + + framebuffer->width = width; + framebuffer->height = height; + + cogl_framebuffer_set_viewport (framebuffer, 0, 0, width, height); + + if (!_cogl_has_private_feature (framebuffer->context, + COGL_PRIVATE_FEATURE_DIRTY_EVENTS)) + _cogl_onscreen_queue_full_dirty (COGL_ONSCREEN (framebuffer)); +} + +void +cogl_onscreen_set_resizable (CoglOnscreen *onscreen, + CoglBool resizable) +{ + CoglFramebuffer *framebuffer; + const CoglWinsysVtable *winsys; + + if (onscreen->resizable == resizable) + return; + + onscreen->resizable = resizable; + + framebuffer = COGL_FRAMEBUFFER (onscreen); + if (framebuffer->allocated) + { + winsys = _cogl_framebuffer_get_winsys (COGL_FRAMEBUFFER (onscreen)); + + if (winsys->onscreen_set_resizable) + winsys->onscreen_set_resizable (onscreen, resizable); + } +} + +CoglBool +cogl_onscreen_get_resizable (CoglOnscreen *onscreen) +{ + return onscreen->resizable; +} + +CoglOnscreenResizeClosure * +cogl_onscreen_add_resize_callback (CoglOnscreen *onscreen, + CoglOnscreenResizeCallback callback, + void *user_data, + CoglUserDataDestroyCallback destroy) +{ + return _cogl_closure_list_add (&onscreen->resize_closures, + callback, + user_data, + destroy); +} + +void +cogl_onscreen_remove_resize_callback (CoglOnscreen *onscreen, + CoglOnscreenResizeClosure *closure) +{ + _cogl_closure_disconnect (closure); +} + +CoglOnscreenDirtyClosure * +cogl_onscreen_add_dirty_callback (CoglOnscreen *onscreen, + CoglOnscreenDirtyCallback callback, + void *user_data, + CoglUserDataDestroyCallback destroy) +{ + return _cogl_closure_list_add (&onscreen->dirty_closures, + callback, + user_data, + destroy); +} + +void +cogl_onscreen_remove_dirty_callback (CoglOnscreen *onscreen, + CoglOnscreenDirtyClosure *closure) +{ + _COGL_RETURN_IF_FAIL (closure); + + _cogl_closure_disconnect (closure); +} + +int64_t +cogl_onscreen_get_frame_counter (CoglOnscreen *onscreen) +{ + return onscreen->frame_counter; +} diff --git a/cogl/cogl/cogl-onscreen.h b/cogl/cogl/cogl-onscreen.h new file mode 100644 index 0000000..bf36bfb --- /dev/null +++ b/cogl/cogl/cogl-onscreen.h @@ -0,0 +1,901 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011,2012,2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_ONSCREEN_H +#define __COGL_ONSCREEN_H + +#include +#include +#include +#include + +#include + +COGL_BEGIN_DECLS + +typedef struct _CoglOnscreen CoglOnscreen; +#define COGL_ONSCREEN(X) ((CoglOnscreen *)(X)) + +/** + * cogl_onscreen_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_onscreen_get_gtype (void); + +/** + * cogl_onscreen_new: (constructor) + * @context: A #CoglContext + * @width: The desired framebuffer width + * @height: The desired framebuffer height + * + * Instantiates an "unallocated" #CoglOnscreen framebuffer that may be + * configured before later being allocated, either implicitly when + * it is first used or explicitly via cogl_framebuffer_allocate(). + * + * Return value: (transfer full): A newly instantiated #CoglOnscreen framebuffer + * Since: 1.8 + * Stability: unstable + */ +CoglOnscreen * +cogl_onscreen_new (CoglContext *context, int width, int height); + +#ifdef COGL_HAS_X11 +typedef void (*CoglOnscreenX11MaskCallback) (CoglOnscreen *onscreen, + uint32_t event_mask, + void *user_data); + +/** + * cogl_x11_onscreen_set_foreign_window_xid: + * @onscreen: The unallocated framebuffer to associated with an X + * window. + * @xid: The XID of an existing X window + * @update: A callback that notifies of updates to what Cogl requires + * to be in the core X protocol event mask. + * @user_data: user data passed to @update + * + * Ideally we would recommend that you let Cogl be responsible for + * creating any X window required to back an onscreen framebuffer but + * if you really need to target a window created manually this + * function can be called before @onscreen has been allocated to set a + * foreign XID for your existing X window. + * + * Since Cogl needs, for example, to track changes to the size of an X + * window it requires that certain events be selected for via the core + * X protocol. This requirement may also be changed asynchronously so + * you must pass in an @update callback to inform you of Cogl's + * required event mask. + * + * For example if you are using Xlib you could use this API roughly + * as follows: + * [{ + * static void + * my_update_cogl_x11_event_mask (CoglOnscreen *onscreen, + * uint32_t event_mask, + * void *user_data) + * { + * XSetWindowAttributes attrs; + * MyData *data = user_data; + * attrs.event_mask = event_mask | data->my_event_mask; + * XChangeWindowAttributes (data->xdpy, + * data->xwin, + * CWEventMask, + * &attrs); + * } + * + * { + * *snip* + * cogl_x11_onscreen_set_foreign_window_xid (onscreen, + * data->xwin, + * my_update_cogl_x11_event_mask, + * data); + * *snip* + * } + * }] + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_x11_onscreen_set_foreign_window_xid (CoglOnscreen *onscreen, + uint32_t xid, + CoglOnscreenX11MaskCallback update, + void *user_data); + +/** + * cogl_x11_onscreen_get_window_xid: + * @onscreen: A #CoglOnscreen framebuffer + * + * Assuming you know the given @onscreen framebuffer is based on an x11 window + * this queries the XID of that window. If + * cogl_x11_onscreen_set_foreign_window_xid() was previously called then it + * will return that same XID otherwise it will be the XID of a window Cogl + * created internally. If the window has not been allocated yet and a foreign + * xid has not been set then it's undefined what value will be returned. + * + * It's undefined what this function does if called when not using an x11 based + * renderer. + * + * Since: 1.10 + * Stability: unstable + */ +uint32_t +cogl_x11_onscreen_get_window_xid (CoglOnscreen *onscreen); + +/* XXX: we should maybe remove this, since nothing currently uses + * it and the current implementation looks dubious. */ +uint32_t +cogl_x11_onscreen_get_visual_xid (CoglOnscreen *onscreen); +#endif /* COGL_HAS_X11 */ + +/** + * cogl_onscreen_set_swap_throttled: + * @onscreen: A #CoglOnscreen framebuffer + * @throttled: Whether swap throttling is wanted or not. + * + * Requests that the given @onscreen framebuffer should have swap buffer + * requests (made using cogl_onscreen_swap_buffers()) throttled either by a + * displays vblank period or perhaps some other mechanism in a composited + * environment. + * + * Since: 1.8 + * Stability: unstable + */ +void +cogl_onscreen_set_swap_throttled (CoglOnscreen *onscreen, + CoglBool throttled); + +/** + * cogl_onscreen_show: + * @onscreen: The onscreen framebuffer to make visible + * + * This requests to make @onscreen visible to the user. + * + * Actually the precise semantics of this function depend on the + * window system currently in use, and if you don't have a + * multi-windowining system this function may in-fact do nothing. + * + * This function will implicitly allocate the given @onscreen + * framebuffer before showing it if it hasn't already been allocated. + * + * When using the Wayland winsys calling this will set the surface to + * a toplevel type which will make it appear. If the application wants + * to set a different type for the surface, it can avoid calling + * cogl_onscreen_show() and set its own type directly with the Wayland + * client API via cogl_wayland_onscreen_get_surface(). + * + * Since Cogl doesn't explicitly track the visibility status of + * onscreen framebuffers it wont try to avoid redundant window system + * requests e.g. to show an already visible window. This also means + * that it's acceptable to alternatively use native APIs to show and + * hide windows without confusing Cogl. + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_onscreen_show (CoglOnscreen *onscreen); + +/** + * cogl_onscreen_hide: + * @onscreen: The onscreen framebuffer to make invisible + * + * This requests to make @onscreen invisible to the user. + * + * Actually the precise semantics of this function depend on the + * window system currently in use, and if you don't have a + * multi-windowining system this function may in-fact do nothing. + * + * This function does not implicitly allocate the given @onscreen + * framebuffer before hiding it. + * + * Since Cogl doesn't explicitly track the visibility status of + * onscreen framebuffers it wont try to avoid redundant window system + * requests e.g. to show an already visible window. This also means + * that it's acceptable to alternatively use native APIs to show and + * hide windows without confusing Cogl. + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_onscreen_hide (CoglOnscreen *onscreen); + +/** + * cogl_onscreen_swap_buffers: + * @onscreen: A #CoglOnscreen framebuffer + * + * Swaps the current back buffer being rendered too, to the front for display. + * + * This function also implicitly discards the contents of the color, depth and + * stencil buffers as if cogl_framebuffer_discard_buffers() were used. The + * significance of the discard is that you should not expect to be able to + * start a new frame that incrementally builds on the contents of the previous + * frame. + * + * It is highly recommended that applications use + * cogl_onscreen_swap_buffers_with_damage() instead whenever possible + * and also use the cogl_onscreen_get_buffer_age() api so they can + * perform incremental updates to older buffers instead of having to + * render a full buffer for every frame. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_onscreen_swap_buffers (CoglOnscreen *onscreen); + + +/** + * cogl_onscreen_get_buffer_age: + * @onscreen: A #CoglOnscreen framebuffer + * + * Gets the current age of the buffer contents. + * + * This function allows applications to query the age of the current + * back buffer contents for a #CoglOnscreen as the number of frames + * elapsed since the contents were most recently defined. + * + * These age values exposes enough information to applications about + * how Cogl internally manages back buffers to allow applications to + * re-use the contents of old frames and minimize how much must be + * redrawn for the next frame. + * + * The back buffer contents can either be reported as invalid (has an + * age of 0) or it may be reported to be the same contents as from n + * frames prior to the current frame. + * + * The queried value remains valid until the next buffer swap. + * + * One caveat is that under X11 the buffer age does not reflect + * changes to buffer contents caused by the window systems. X11 + * applications must track Expose events to determine what buffer + * regions need to additionally be repaired each frame. + * + * The recommended way to take advantage of this buffer age api is to + * build up a circular buffer of length 3 for tracking damage regions + * over the last 3 frames and when starting a new frame look at the + * age of the buffer and combine the damage regions for the current + * frame with the damage regions of previous @age frames so you know + * everything that must be redrawn to update the old contents for the + * new frame. + * + * If the system doesn't not support being able to track the age + * of back buffers then this function will always return 0 which + * implies that the contents are undefined. + * + * The %COGL_FEATURE_ID_BUFFER_AGE feature can optionally be + * explicitly checked to determine if Cogl is currently tracking the + * age of #CoglOnscreen back buffer contents. If this feature is + * missing then this function will always return 0. + * + * Return value: The age of the buffer contents or 0 when the buffer + * contents are undefined. + * + * Since: 1.14 + * Stability: stable + */ +int +cogl_onscreen_get_buffer_age (CoglOnscreen *onscreen); + +/** + * cogl_onscreen_swap_buffers_with_damage: + * @onscreen: A #CoglOnscreen framebuffer + * @rectangles: An array of integer 4-tuples representing damaged + * rectangles as (x, y, width, height) tuples. + * @n_rectangles: The number of 4-tuples to be read from @rectangles + * + * Swaps the current back buffer being rendered too, to the front for + * display and provides information to any system compositor about + * what regions of the buffer have changed (damage) with respect to + * the last swapped buffer. + * + * This function has the same semantics as + * cogl_framebuffer_swap_buffers() except that it additionally allows + * applications to pass a list of damaged rectangles which may be + * passed on to a compositor so that it can minimize how much of the + * screen is redrawn in response to this applications newly swapped + * front buffer. + * + * For example if your application is only animating a small object in + * the corner of the screen and everything else is remaining static + * then it can help the compositor to know that only the bottom right + * corner of your newly swapped buffer has really changed with respect + * to your previously swapped front buffer. + * + * If @n_rectangles is 0 then the whole buffer will implicitly be + * reported as damaged as if cogl_onscreen_swap_buffers() had been + * called. + * + * This function also implicitly discards the contents of the color, + * depth and stencil buffers as if cogl_framebuffer_discard_buffers() + * were used. The significance of the discard is that you should not + * expect to be able to start a new frame that incrementally builds on + * the contents of the previous frame. If you want to perform + * incremental updates to older back buffers then please refer to the + * cogl_onscreen_get_buffer_age() api. + * + * Whenever possible it is recommended that applications use this + * function instead of cogl_onscreen_swap_buffers() to improve + * performance when running under a compositor. + * + * It is highly recommended to use this API in conjunction with + * the cogl_onscreen_get_buffer_age() api so that your application can + * perform incremental rendering based on old back buffers. + * + * Since: 1.16 + * Stability: unstable + */ +void +cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen, + const int *rectangles, + int n_rectangles); + +/** + * cogl_onscreen_swap_region: + * @onscreen: A #CoglOnscreen framebuffer + * @rectangles: An array of integer 4-tuples representing rectangles as + * (x, y, width, height) tuples. + * @n_rectangles: The number of 4-tuples to be read from @rectangles + * + * Swaps a region of the back buffer being rendered too, to the front for + * display. @rectangles represents the region as array of @n_rectangles each + * defined by 4 sequential (x, y, width, height) integers. + * + * This function also implicitly discards the contents of the color, depth and + * stencil buffers as if cogl_framebuffer_discard_buffers() were used. The + * significance of the discard is that you should not expect to be able to + * start a new frame that incrementally builds on the contents of the previous + * frame. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_onscreen_swap_region (CoglOnscreen *onscreen, + const int *rectangles, + int n_rectangles); + +/** + * CoglFrameEvent: + * @COGL_FRAME_EVENT_SYNC: Notifies that the system compositor has + * acknowledged a frame and is ready for a + * new frame to be created. + * @COGL_FRAME_EVENT_COMPLETE: Notifies that a frame has ended. This + * is a good time for applications to + * collect statistics about the frame + * since the #CoglFrameInfo should hold + * the most data at this point. No other + * events should be expected after a + * @COGL_FRAME_EVENT_COMPLETE event. + * + * Identifiers that are passed to #CoglFrameCallback functions + * (registered using cogl_onscreen_add_frame_callback()) that + * mark the progression of a frame in some way which usually + * means that new information will have been accumulated in the + * frame's corresponding #CoglFrameInfo object. + * + * The last event that will be sent for a frame will be a + * @COGL_FRAME_EVENT_COMPLETE event and so these are a good + * opportunity to collect statistics about a frame since the + * #CoglFrameInfo should hold the most data at this point. + * + * A frame may not be completed before the next frame can start + * so applications should avoid needing to collect all statistics for + * a particular frame before they can start a new frame. + * + * Since: 1.14 + * Stability: unstable + */ +typedef enum _CoglFrameEvent +{ + COGL_FRAME_EVENT_SYNC = 1, + COGL_FRAME_EVENT_COMPLETE +} CoglFrameEvent; + +/** + * CoglFrameCallback: + * @onscreen: The onscreen that the frame is associated with + * @event: A #CoglFrameEvent notifying how the frame has progressed + * @info: The meta information, such as timing information, about + * the frame that has progressed. + * @user_data: The user pointer passed to + * cogl_onscreen_add_frame_callback() + * + * Is a callback that can be registered via + * cogl_onscreen_add_frame_callback() to be called when a frame + * progresses in some notable way. + * + * Please see the documentation for #CoglFrameEvent and + * cogl_onscreen_add_frame_callback() for more details about what + * events can be notified. + * + * Since: 1.14 + * Stability: unstable + */ +typedef void (*CoglFrameCallback) (CoglOnscreen *onscreen, + CoglFrameEvent event, + CoglFrameInfo *info, + void *user_data); + +/** + * CoglFrameClosure: + * + * An opaque type that tracks a #CoglFrameCallback and associated user + * data. A #CoglFrameClosure pointer will be returned from + * cogl_onscreen_add_frame_callback() and it allows you to remove a + * callback later using cogl_onscreen_remove_frame_callback(). + * + * Since: 1.14 + * Stability: unstable + */ +typedef struct _CoglClosure CoglFrameClosure; + +/** + * cogl_frame_closure_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_frame_closure_get_gtype (void); + +/** + * cogl_onscreen_add_frame_callback: + * @onscreen: A #CoglOnscreen framebuffer + * @callback: (scope notified): A callback function to call for frame events + * @user_data: (closure): A private pointer to be passed to @callback + * @destroy: (allow-none): An optional callback to destroy @user_data + * when the @callback is removed or @onscreen is freed. + * + * Installs a @callback function that will be called for significant + * events relating to the given @onscreen framebuffer. + * + * The @callback will be used to notify when the system compositor is + * ready for this application to render a new frame. In this case + * %COGL_FRAME_EVENT_SYNC will be passed as the event argument to the + * given @callback in addition to the #CoglFrameInfo corresponding to + * the frame beeing acknowledged by the compositor. + * + * The @callback will also be called to notify when the frame has + * ended. In this case %COGL_FRAME_EVENT_COMPLETE will be passed as + * the event argument to the given @callback in addition to the + * #CoglFrameInfo corresponding to the newly presented frame. The + * meaning of "ended" here simply means that no more timing + * information will be collected within the corresponding + * #CoglFrameInfo and so this is a good opportunity to analyse the + * given info. It does not necessarily mean that the GPU has finished + * rendering the corresponding frame. + * + * We highly recommend throttling your application according to + * %COGL_FRAME_EVENT_SYNC events so that your application can avoid + * wasting resources, drawing more frames than your system compositor + * can display. + * + * Return value: a #CoglFrameClosure pointer that can be used to + * remove the callback and associated @user_data later. + * Since: 1.14 + * Stability: unstable + */ +CoglFrameClosure * +cogl_onscreen_add_frame_callback (CoglOnscreen *onscreen, + CoglFrameCallback callback, + void *user_data, + CoglUserDataDestroyCallback destroy); + +/** + * cogl_onscreen_remove_frame_callback: + * @onscreen: A #CoglOnscreen + * @closure: A #CoglFrameClosure returned from + * cogl_onscreen_add_frame_callback() + * + * Removes a callback and associated user data that were previously + * registered using cogl_onscreen_add_frame_callback(). + * + * If a destroy callback was passed to + * cogl_onscreen_add_frame_callback() to destroy the user data then + * this will get called. + * + * Since: 1.14 + * Stability: unstable + */ +void +cogl_onscreen_remove_frame_callback (CoglOnscreen *onscreen, + CoglFrameClosure *closure); + +typedef void (*CoglSwapBuffersNotify) (CoglFramebuffer *framebuffer, + void *user_data); + +/** + * cogl_onscreen_add_swap_buffers_callback: + * @onscreen: A #CoglOnscreen framebuffer + * @callback: (scope notified): A callback function to call when a swap + * has completed + * @user_data: (closure): A private pointer to be passed to @callback + * + * Installs a @callback function that should be called whenever a swap buffers + * request (made using cogl_onscreen_swap_buffers()) for the given + * @onscreen completes. + * + * Applications should check for the %COGL_FEATURE_ID_SWAP_BUFFERS_EVENT + * feature before using this API. It's currently undefined when and if + * registered callbacks will be called if this feature is not supported. + * + * We recommend using this mechanism when available to manually throttle your + * applications (in conjunction with cogl_onscreen_set_swap_throttled()) so + * your application will be able to avoid long blocks in the driver caused by + * throttling when you request to swap buffers too quickly. + * + * Return value: a unique identifier that can be used to remove to remove + * the callback later. + * Since: 1.10 + * Stability: unstable + * Deprecated: 1.14: Use cogl_onscreen_add_frame_callback() instead + */ +COGL_DEPRECATED_IN_1_14_FOR (cogl_onscreen_add_frame_callback) +unsigned int +cogl_onscreen_add_swap_buffers_callback (CoglOnscreen *onscreen, + CoglSwapBuffersNotify callback, + void *user_data); + +/** + * cogl_onscreen_remove_swap_buffers_callback: + * @onscreen: A #CoglOnscreen framebuffer + * @id: An identifier returned from cogl_onscreen_add_swap_buffers_callback() + * + * Removes a callback that was previously registered + * using cogl_onscreen_add_swap_buffers_callback(). + * + * Since: 1.10 + * Stability: unstable + * Deprecated: 1.14: Use cogl_onscreen_remove_frame_callback() instead + */ + +COGL_DEPRECATED_IN_1_14_FOR (cogl_onscreen_remove_frame_callback) +void +cogl_onscreen_remove_swap_buffers_callback (CoglOnscreen *onscreen, + unsigned int id); + +/** + * cogl_onscreen_set_resizable: + * @onscreen: A #CoglOnscreen framebuffer + * + * Lets you request Cogl to mark an @onscreen framebuffer as + * resizable or not. + * + * By default, if possible, a @onscreen will be created by Cogl + * as non resizable, but it is not guaranteed that this is always + * possible for all window systems. + * + * Cogl does not know whether marking the @onscreen framebuffer + * is truly meaningful for your current window system (consider + * applications being run fullscreen on a phone or TV) so this + * function may not have any useful effect. If you are running on a + * multi windowing system such as X11 or Win32 or OSX then Cogl will + * request to the window system that users be allowed to resize the + * @onscreen, although it's still possible that some other window + * management policy will block this possibility. + * + * Whenever an @onscreen framebuffer is resized the viewport + * will be automatically updated to match the new size of the + * framebuffer with an origin of (0,0). If your application needs more + * specialized control of the viewport it will need to register a + * resize handler using cogl_onscreen_add_resize_callback() so that it + * can track when the viewport has been changed automatically. + * + * Since: 2.0 + */ +void +cogl_onscreen_set_resizable (CoglOnscreen *onscreen, + CoglBool resizable); + +/** + * cogl_onscreen_get_resizable: + * @onscreen: A #CoglOnscreen framebuffer + * + * Lets you query whether @onscreen has been marked as resizable via + * the cogl_onscreen_set_resizable() api. + * + * By default, if possible, a @onscreen will be created by Cogl + * as non resizable, but it is not guaranteed that this is always + * possible for all window systems. + * + * If cogl_onscreen_set_resizable(@onscreen, %TRUE) has been + * previously called then this function will return %TRUE, but it's + * possible that the current windowing system being used does not + * support window resizing (consider fullscreen windows on a phone or + * a TV). This function is not aware of whether resizing is truly + * meaningful with your window system, only whether the @onscreen has + * been marked as resizable. + * + * Return value: Returns whether @onscreen has been marked as + * resizable or not. + * Since: 2.0 + */ +CoglBool +cogl_onscreen_get_resizable (CoglOnscreen *onscreen); + +/** + * CoglOnscreenResizeCallback: + * @onscreen: A #CoglOnscreen framebuffer that was resized + * @width: The new width of @onscreen + * @height: The new height of @onscreen + * @user_data: The private passed to + * cogl_onscreen_add_resize_callback() + * + * Is a callback type used with the + * cogl_onscreen_add_resize_callback() allowing applications to be + * notified whenever an @onscreen framebuffer is resized. + * + * Cogl automatically updates the viewport of an @onscreen + * framebuffer that is resized so this callback is also an indication + * that the viewport has been modified too + * + * A resize callback will only ever be called while dispatching + * Cogl events from the system mainloop; so for example during + * cogl_poll_renderer_dispatch(). This is so that callbacks shouldn't + * occur while an application might have arbitrary locks held for + * example. + * + * Since: 2.0 + */ +typedef void (*CoglOnscreenResizeCallback) (CoglOnscreen *onscreen, + int width, + int height, + void *user_data); + +/** + * CoglOnscreenResizeClosure: + * + * An opaque type that tracks a #CoglOnscreenResizeCallback and + * associated user data. A #CoglOnscreenResizeClosure pointer will be + * returned from cogl_onscreen_add_resize_callback() and it allows you + * to remove a callback later using + * cogl_onscreen_remove_resize_callback(). + * + * Since: 2.0 + * Stability: unstable + */ +typedef struct _CoglClosure CoglOnscreenResizeClosure; + +/** + * cogl_onscreen_resize_closure_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_onscreen_resize_closure_get_gtype (void); + +/** + * cogl_onscreen_add_resize_callback: + * @onscreen: A #CoglOnscreen framebuffer + * @callback: (scope notified): A #CoglOnscreenResizeCallback to call when + * the @onscreen changes size. + * @user_data: (closure): Private data to be passed to @callback. + * @destroy: (allow-none): An optional callback to destroy @user_data + * when the @callback is removed or @onscreen is freed. + * + * Registers a @callback with @onscreen that will be called whenever + * the @onscreen framebuffer changes size. + * + * The @callback can be removed using + * cogl_onscreen_remove_resize_callback() passing the returned closure + * pointer. + * + * Since Cogl automatically updates the viewport of an @onscreen + * framebuffer that is resized, a resize callback can also be used to + * track when the viewport has been changed automatically by Cogl in + * case your application needs more specialized control over the + * viewport. + * + * A resize callback will only ever be called while dispatching + * Cogl events from the system mainloop; so for example during + * cogl_poll_renderer_dispatch(). This is so that callbacks shouldn't + * occur while an application might have arbitrary locks held for + * example. + * + * Return value: a #CoglOnscreenResizeClosure pointer that can be used to + * remove the callback and associated @user_data later. + * Since: 2.0 + */ +CoglOnscreenResizeClosure * +cogl_onscreen_add_resize_callback (CoglOnscreen *onscreen, + CoglOnscreenResizeCallback callback, + void *user_data, + CoglUserDataDestroyCallback destroy); + +/** + * cogl_onscreen_remove_resize_callback: + * @onscreen: A #CoglOnscreen framebuffer + * @closure: An identifier returned from cogl_onscreen_add_resize_callback() + * + * Removes a resize @callback and @user_data pair that were previously + * associated with @onscreen via cogl_onscreen_add_resize_callback(). + * + * Since: 2.0 + */ +void +cogl_onscreen_remove_resize_callback (CoglOnscreen *onscreen, + CoglOnscreenResizeClosure *closure); + +/** + * CoglOnscreenDirtyInfo: + * @x: Left edge of the dirty rectangle + * @y: Top edge of the dirty rectangle, measured from the top of the window + * @width: Width of the dirty rectangle + * @height: Height of the dirty rectangle + * + * A structure passed to callbacks registered using + * cogl_onscreen_add_dirty_callback(). The members describe a + * rectangle within the onscreen buffer that should be redrawn. + * + * Since: 1.16 + * Stability: unstable + */ +typedef struct _CoglOnscreenDirtyInfo CoglOnscreenDirtyInfo; + +struct _CoglOnscreenDirtyInfo +{ + int x, y; + int width, height; +}; + +/** + * CoglOnscreenDirtyCallback: + * @onscreen: The onscreen that the frame is associated with + * @info: A #CoglOnscreenDirtyInfo struct containing the details of the + * dirty area + * @user_data: The user pointer passed to + * cogl_onscreen_add_frame_callback() + * + * Is a callback that can be registered via + * cogl_onscreen_add_dirty_callback() to be called when the windowing + * system determines that a region of the onscreen window has been + * lost and the application should redraw it. + * + * Since: 1.16 + * Stability: unstable + */ +typedef void (*CoglOnscreenDirtyCallback) (CoglOnscreen *onscreen, + const CoglOnscreenDirtyInfo *info, + void *user_data); + +/** + * CoglOnscreenDirtyClosure: + * + * An opaque type that tracks a #CoglOnscreenDirtyCallback and associated + * user data. A #CoglOnscreenDirtyClosure pointer will be returned from + * cogl_onscreen_add_dirty_callback() and it allows you to remove a + * callback later using cogl_onscreen_remove_dirty_callback(). + * + * Since: 1.16 + * Stability: unstable + */ +typedef struct _CoglClosure CoglOnscreenDirtyClosure; + +/** + * cogl_onscreen_dirty_closure_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_onscreen_dirty_closure_get_gtype (void); + +/** + * cogl_onscreen_add_dirty_callback: + * @onscreen: A #CoglOnscreen framebuffer + * @callback: (scope notified): A callback function to call for dirty events + * @user_data: (closure): A private pointer to be passed to @callback + * @destroy: (allow-none): An optional callback to destroy @user_data when the + * @callback is removed or @onscreen is freed. + * + * Installs a @callback function that will be called whenever the + * window system has lost the contents of a region of the onscreen + * buffer and the application should redraw it to repair the buffer. + * For example this may happen in a window system without a compositor + * if a window that was previously covering up the onscreen window has + * been moved causing a region of the onscreen to be exposed. + * + * The @callback will be passed a #CoglOnscreenDirtyInfo struct which + * decribes a rectangle containing the newly dirtied region. Note that + * this may be called multiple times to describe a non-rectangular + * region composed of multiple smaller rectangles. + * + * The dirty events are separate from %COGL_FRAME_EVENT_SYNC events so + * the application should also listen for this event before rendering + * the dirty region to ensure that the framebuffer is actually ready + * for rendering. + * + * Return value: a #CoglOnscreenDirtyClosure pointer that can be used to + * remove the callback and associated @user_data later. + * Since: 1.16 + * Stability: unstable + */ +CoglOnscreenDirtyClosure * +cogl_onscreen_add_dirty_callback (CoglOnscreen *onscreen, + CoglOnscreenDirtyCallback callback, + void *user_data, + CoglUserDataDestroyCallback destroy); + +/** + * cogl_onscreen_remove_dirty_callback: + * @onscreen: A #CoglOnscreen + * @closure: A #CoglOnscreenDirtyClosure returned from + * cogl_onscreen_add_dirty_callback() + * + * Removes a callback and associated user data that were previously + * registered using cogl_onscreen_add_dirty_callback(). + * + * If a destroy callback was passed to + * cogl_onscreen_add_dirty_callback() to destroy the user data then + * this will also get called. + * + * Since: 1.16 + * Stability: unstable + */ +void +cogl_onscreen_remove_dirty_callback (CoglOnscreen *onscreen, + CoglOnscreenDirtyClosure *closure); + +/** + * cogl_is_onscreen: + * @object: A #CoglObject pointer + * + * Gets whether the given object references a #CoglOnscreen. + * + * Return value: %TRUE if the object references a #CoglOnscreen + * and %FALSE otherwise. + * Since: 1.10 + * Stability: unstable + */ +CoglBool +cogl_is_onscreen (void *object); + +/** + * cogl_onscreen_get_frame_counter: + * + * Gets the value of the framebuffers frame counter. This is + * a counter that increases by one each time + * cogl_onscreen_swap_buffers() or cogl_onscreen_swap_region() + * is called. + * + * Return value: the current frame counter value + * Since: 1.14 + * Stability: unstable + */ +int64_t +cogl_onscreen_get_frame_counter (CoglOnscreen *onscreen); + +COGL_END_DECLS + +#endif /* __COGL_ONSCREEN_H */ diff --git a/cogl/cogl/cogl-output-private.h b/cogl/cogl/cogl-output-private.h new file mode 100644 index 0000000..d264d48 --- /dev/null +++ b/cogl/cogl/cogl-output-private.h @@ -0,0 +1,57 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_OUTPUT_PRIVATE_H +#define __COGL_OUTPUT_PRIVATE_H + +#include "cogl-output.h" +#include "cogl-object-private.h" + +struct _CoglOutput +{ + CoglObject _parent; + + char *name; + + int x; /* Must be first field for _cogl_output_values_equal() */ + int y; + int width; + int height; + int mm_width; + int mm_height; + float refresh_rate; + CoglSubpixelOrder subpixel_order; +}; + +CoglOutput *_cogl_output_new (const char *name); +CoglBool _cogl_output_values_equal (CoglOutput *output, + CoglOutput *other); + +#endif /* __COGL_OUTPUT_PRIVATE_H */ diff --git a/cogl/cogl/cogl-output.c b/cogl/cogl/cogl-output.c new file mode 100644 index 0000000..573e8dc --- /dev/null +++ b/cogl/cogl/cogl-output.c @@ -0,0 +1,119 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-output-private.h" +#include "cogl-gtype-private.h" + +#include + +static void _cogl_output_free (CoglOutput *output); + +COGL_OBJECT_DEFINE (Output, output); +COGL_GTYPE_DEFINE_CLASS (Output, output); + +CoglOutput * +_cogl_output_new (const char *name) +{ + CoglOutput *output; + + output = g_slice_new0 (CoglOutput); + output->name = g_strdup (name); + + return _cogl_output_object_new (output); +} + +static void +_cogl_output_free (CoglOutput *output) +{ + g_free (output->name); + + g_slice_free (CoglOutput, output); +} + +gboolean +_cogl_output_values_equal (CoglOutput *output, + CoglOutput *other) +{ + return memcmp ((const char *)output + G_STRUCT_OFFSET (CoglOutput, x), + (const char *)other + G_STRUCT_OFFSET (CoglOutput, x), + sizeof (CoglOutput) - G_STRUCT_OFFSET (CoglOutput, x)) == 0; +} + +int +cogl_output_get_x (CoglOutput *output) +{ + return output->x; +} + +int +cogl_output_get_y (CoglOutput *output) +{ + return output->y; +} + +int +cogl_output_get_width (CoglOutput *output) +{ + return output->width; +} + +int +cogl_output_get_height (CoglOutput *output) +{ + return output->height; +} + +int +cogl_output_get_mm_width (CoglOutput *output) +{ + return output->mm_width; +} + +int +cogl_output_get_mm_height (CoglOutput *output) +{ + return output->mm_height; +} + +CoglSubpixelOrder +cogl_output_get_subpixel_order (CoglOutput *output) +{ + return output->subpixel_order; +} + +float +cogl_output_get_refresh_rate (CoglOutput *output) +{ + return output->refresh_rate; +} diff --git a/cogl/cogl/cogl-output.h b/cogl/cogl/cogl-output.h new file mode 100644 index 0000000..15df92c --- /dev/null +++ b/cogl/cogl/cogl-output.h @@ -0,0 +1,257 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Owen Taylor + */ +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_OUTPUT_H +#define __COGL_OUTPUT_H + +#include + +#include + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-output + * @short_description: information about an output device + * + * The #CoglOutput object holds information about an output device + * such as a monitor or laptop display. It can be queried to find + * out the position of the output with respect to the screen + * coordinate system and other information such as the resolution + * and refresh rate of the device. + * + * There can be any number of outputs which may overlap: the + * same area of the screen may be displayed by multiple output + * devices. + * + * XXX: though it's possible to query the position of the output + * with respect to screen coordinates, there is currently no way + * of finding out the position of a #CoglOnscreen in screen + * coordinates, at least without using windowing-system specific + * API's, so it's not easy to get the output positions relative + * to the #CoglOnscreen. + */ + +typedef struct _CoglOutput CoglOutput; +#define COGL_OUTPUT(X) ((CoglOutput *)(X)) + +/** + * cogl_output_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_output_get_gtype (void); + +/** + * CoglSubpixelOrder: + * @COGL_SUBPIXEL_ORDER_UNKNOWN: the layout of subpixel + * components for the device is unknown. + * @COGL_SUBPIXEL_ORDER_NONE: the device displays colors + * without geometrically-separated subpixel components, + * or the positioning or colors of the components do not + * match any of the values in the enumeration. + * @COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB: the device has + * horizontally arranged components in the order + * red-green-blue from left to right. + * @COGL_SUBPIXEL_ORDER_HORIZONTAL_BGR: the device has + * horizontally arranged components in the order + * blue-green-red from left to right. + * @COGL_SUBPIXEL_ORDER_VERTICAL_RGB: the device has + * vertically arranged components in the order + * red-green-blue from top to bottom. + * @COGL_SUBPIXEL_ORDER_VERTICAL_BGR: the device has + * vertically arranged components in the order + * blue-green-red from top to bottom. + * + * Some output devices (such as LCD panels) display colors + * by making each pixel consist of smaller "subpixels" + * that each have a particular color. By using knowledge + * of the layout of this subpixel components, it is possible + * to create image content with higher resolution than the + * pixel grid. + * + * Since: 1.14 + * Stability: unstable + */ +typedef enum { + COGL_SUBPIXEL_ORDER_UNKNOWN, + COGL_SUBPIXEL_ORDER_NONE, + COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB, + COGL_SUBPIXEL_ORDER_HORIZONTAL_BGR, + COGL_SUBPIXEL_ORDER_VERTICAL_RGB, + COGL_SUBPIXEL_ORDER_VERTICAL_BGR +} CoglSubpixelOrder; + +/** + * cogl_is_output: + * @object: A #CoglObject pointer + * + * Gets whether the given object references a #CoglOutput. + * + * Return value: %TRUE if the object references a #CoglOutput + * and %FALSE otherwise. + * Since: 1.14 + * Stability: unstable + */ +CoglBool +cogl_is_output (void *object); + +/** + * cogl_output_get_x: + * @output: a #CoglOutput + * + * Gets the X position of the output with respect to the coordinate + * system of the screen. + * + * Return value: the X position of the output as a pixel offset + * from the left side of the screen coordinate space + * Since: 1.14 + * Stability: unstable + */ +int +cogl_output_get_x (CoglOutput *output); + +/** + * cogl_output_get_y: + * @output: a #CoglOutput + * + * Gets the Y position of the output with respect to the coordinate + * system of the screen. + * + * Return value: the Y position of the output as a pixel offset + * from the top side of the screen coordinate space + * Since: 1.14 + * Stability: unstable + */ +int +cogl_output_get_y (CoglOutput *output); + +/** + * cogl_output_get_width: + * @output: a #CoglOutput + * + * Gets the width of the output in pixels. + * + * Return value: the width of the output in pixels + * Since: 1.14 + * Stability: unstable + */ +int +cogl_output_get_width (CoglOutput *output); + +/** + * cogl_output_get_height: + * @output: a #CoglOutput + * + * Gets the height of the output in pixels. + * + * Return value: the height of the output in pixels + * Since: 1.14 + * Stability: unstable + */ +int +cogl_output_get_height (CoglOutput *output); + +/** + * cogl_output_get_mm_width: + * @output: a #CoglOutput + * + * Gets the physical width of the output. In some cases (such as + * as a projector), the value returned here might correspond to + * nominal resolution rather than the actual physical size of the + * output device. + * + * Return value: the height of the output in millimeters. A value + * of 0 indicates the width is unknown + * Since: 1.14 + * Stability: unstable + */ +int +cogl_output_get_mm_width (CoglOutput *output); + +/** + * cogl_output_get_mm_height: + * @output: a #CoglOutput + * + * Gets the physical height of the output. In some cases (such as + * as a projector), the value returned here might correspond to + * nominal resolution rather than the actual physical size of the + * output device. + * + * Return value: the height of the output in millimeters. A value + * of 0 indicates that the height is unknown + * Since: 1.14 + * Stability: unstable + */ +int +cogl_output_get_mm_height (CoglOutput *output); + +/** + * cogl_output_get_subpixel_order: + * @output: a #CoglOutput + * + * For an output device where each pixel is made up of smaller components + * with different colors, returns the layout of the subpixel + * components. + * + * Return value: the order of subpixel components for the output device + * Since: 1.14 + * Stability: unstable + */ +CoglSubpixelOrder +cogl_output_get_subpixel_order (CoglOutput *output); + +/** + * cogl_output_get_refresh_rate: + * @output: a #CoglOutput + * + * Gets the number of times per second that the output device refreshes + * the display contents. + * + * Return value: the refresh rate of the output device. A value of zero + * indicates that the refresh rate is unknown. + * Since: 1.14 + * Stability: unstable + */ +float +cogl_output_get_refresh_rate (CoglOutput *output); + +COGL_END_DECLS + +#endif /* __COGL_OUTPUT_H */ + + + diff --git a/cogl/cogl/cogl-pango.h b/cogl/cogl/cogl-pango.h new file mode 100644 index 0000000..8082c56 --- /dev/null +++ b/cogl/cogl/cogl-pango.h @@ -0,0 +1,36 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ +#ifndef __COGL_PANGO_H_COMPAT__ +#define __COGL_PANGO_H_COMPAT__ + +#warning "#include is deprecated; please #include " +#include + +#endif /* __COGL_PANGO_H_COMPAT__ */ diff --git a/cogl/cogl/cogl-pipeline-cache.c b/cogl/cogl/cogl-pipeline-cache.c new file mode 100644 index 0000000..62b3724 --- /dev/null +++ b/cogl/cogl/cogl-pipeline-cache.c @@ -0,0 +1,216 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011, 2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * Authors: + * Neil Roberts + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include + +#include "cogl-context-private.h" +#include "cogl-pipeline-private.h" +#include "cogl-pipeline-cache.h" +#include "cogl-pipeline-hash-table.h" + +struct _CoglPipelineCache +{ + CoglPipelineHashTable fragment_hash; + CoglPipelineHashTable vertex_hash; + CoglPipelineHashTable combined_hash; +}; + +CoglPipelineCache * +_cogl_pipeline_cache_new (void) +{ + CoglPipelineCache *cache = g_new (CoglPipelineCache, 1); + unsigned long vertex_state; + unsigned long layer_vertex_state; + unsigned int fragment_state; + unsigned int layer_fragment_state; + + _COGL_GET_CONTEXT (ctx, 0); + + vertex_state = + _cogl_pipeline_get_state_for_vertex_codegen (ctx); + layer_vertex_state = + COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN; + fragment_state = + _cogl_pipeline_get_state_for_fragment_codegen (ctx); + layer_fragment_state = + _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx); + + _cogl_pipeline_hash_table_init (&cache->vertex_hash, + vertex_state, + layer_vertex_state, + "vertex shaders"); + _cogl_pipeline_hash_table_init (&cache->fragment_hash, + fragment_state, + layer_fragment_state, + "fragment shaders"); + _cogl_pipeline_hash_table_init (&cache->combined_hash, + vertex_state | fragment_state, + layer_vertex_state | layer_fragment_state, + "programs"); + + return cache; +} + +void +_cogl_pipeline_cache_free (CoglPipelineCache *cache) +{ + _cogl_pipeline_hash_table_destroy (&cache->fragment_hash); + _cogl_pipeline_hash_table_destroy (&cache->vertex_hash); + _cogl_pipeline_hash_table_destroy (&cache->combined_hash); + g_free (cache); +} + +CoglPipelineCacheEntry * +_cogl_pipeline_cache_get_fragment_template (CoglPipelineCache *cache, + CoglPipeline *key_pipeline) +{ + return _cogl_pipeline_hash_table_get (&cache->fragment_hash, + key_pipeline); +} + +CoglPipelineCacheEntry * +_cogl_pipeline_cache_get_vertex_template (CoglPipelineCache *cache, + CoglPipeline *key_pipeline) +{ + return _cogl_pipeline_hash_table_get (&cache->vertex_hash, + key_pipeline); +} + +CoglPipelineCacheEntry * +_cogl_pipeline_cache_get_combined_template (CoglPipelineCache *cache, + CoglPipeline *key_pipeline) +{ + return _cogl_pipeline_hash_table_get (&cache->combined_hash, + key_pipeline); +} + +#ifdef ENABLE_UNIT_TESTS + +static void +create_pipelines (CoglPipeline **pipelines, + int n_pipelines) +{ + int i; + + for (i = 0; i < n_pipelines; i++) + { + char *source = g_strdup_printf (" cogl_color_out = " + "vec4 (%f, 0.0, 0.0, 1.0);\n", + i / 255.0f); + CoglSnippet *snippet = + cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, + NULL, /* declarations */ + source); + + g_free (source); + + pipelines[i] = cogl_pipeline_new (test_ctx); + cogl_pipeline_add_snippet (pipelines[i], snippet); + cogl_object_unref (snippet); + } + + /* Test that drawing with them works. This should create the entries + * in the cache */ + for (i = 0; i < n_pipelines; i++) + { + cogl_framebuffer_draw_rectangle (test_fb, + pipelines[i], + i, 0, + i + 1, 1); + test_utils_check_pixel_rgb (test_fb, i, 0, i, 0, 0); + } + +} + +UNIT_TEST (check_pipeline_pruning, + TEST_REQUIREMENT_GLSL, /* requirements */ + 0 /* no failure cases */) +{ + CoglPipeline *pipelines[18]; + int fb_width, fb_height; + CoglPipelineHashTable *fragment_hash = + &test_ctx->pipeline_cache->fragment_hash; + CoglPipelineHashTable *combined_hash = + &test_ctx->pipeline_cache->combined_hash; + int i; + + fb_width = cogl_framebuffer_get_width (test_fb); + fb_height = cogl_framebuffer_get_height (test_fb); + + cogl_framebuffer_orthographic (test_fb, + 0, 0, + fb_width, + fb_height, + -1, + 100); + + /* Create 18 unique pipelines. This should end up being more than + * the initial expected minimum size so it will trigger the garbage + * collection. However all of the pipelines will be in use so they + * won't be collected */ + create_pipelines (pipelines, 18); + + /* These pipelines should all have unique entries in the cache. We + * should have run the garbage collection once and at that point the + * expected minimum size would have been 17 */ + g_assert_cmpint (g_hash_table_size (fragment_hash->table), ==, 18); + g_assert_cmpint (g_hash_table_size (combined_hash->table), ==, 18); + g_assert_cmpint (fragment_hash->expected_min_size, ==, 17); + g_assert_cmpint (combined_hash->expected_min_size, ==, 17); + + /* Destroy the original pipelines and create some new ones. This + * should run the garbage collector again but this time the + * pipelines won't be in use so it should free some of them */ + for (i = 0; i < 18; i++) + cogl_object_unref (pipelines[i]); + + create_pipelines (pipelines, 18); + + /* The garbage collection should have freed half of the original 18 + * pipelines which means there should now be 18*1.5 = 27 */ + g_assert_cmpint (g_hash_table_size (fragment_hash->table), ==, 27); + g_assert_cmpint (g_hash_table_size (combined_hash->table), ==, 27); + /* The 35th pipeline would have caused the garbage collection. At + * that point there would be 35-18=17 used unique pipelines. */ + g_assert_cmpint (fragment_hash->expected_min_size, ==, 17); + g_assert_cmpint (combined_hash->expected_min_size, ==, 17); + + for (i = 0; i < 18; i++) + cogl_object_unref (pipelines[i]); +} + +#endif /* ENABLE_UNIT_TESTS */ diff --git a/cogl/cogl/cogl-pipeline-cache.h b/cogl/cogl/cogl-pipeline-cache.h new file mode 100644 index 0000000..bd5862e --- /dev/null +++ b/cogl/cogl/cogl-pipeline-cache.h @@ -0,0 +1,93 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_PIPELINE_CACHE_H__ +#define __COGL_PIPELINE_CACHE_H__ + +#include "cogl-pipeline.h" + +typedef struct _CoglPipelineCache CoglPipelineCache; + +typedef struct +{ + CoglPipeline *pipeline; + + /* Number of usages of this template. If this drops to zero then it + * will be a candidate for removal from the cache */ + int usage_count; +} CoglPipelineCacheEntry; + +CoglPipelineCache * +_cogl_pipeline_cache_new (void); + +void +_cogl_pipeline_cache_free (CoglPipelineCache *cache); + +/* + * Gets a pipeline from the cache that has the same state as + * @key_pipeline for the state in + * COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN. If there is no + * matching pipline already then a copy of key_pipeline is stored in + * the cache so that it will be used next time the function is called + * with a similar pipeline. In that case the copy itself will be + * returned + */ +CoglPipelineCacheEntry * +_cogl_pipeline_cache_get_fragment_template (CoglPipelineCache *cache, + CoglPipeline *key_pipeline); + +/* + * Gets a pipeline from the cache that has the same state as + * @key_pipeline for the state in + * COGL_PIPELINE_STATE_AFFECTS_VERTEX_CODEGEN. If there is no + * matching pipline already then a copy of key_pipeline is stored in + * the cache so that it will be used next time the function is called + * with a similar pipeline. In that case the copy itself will be + * returned + */ +CoglPipelineCacheEntry * +_cogl_pipeline_cache_get_vertex_template (CoglPipelineCache *cache, + CoglPipeline *key_pipeline); + +/* + * Gets a pipeline from the cache that has the same state as + * @key_pipeline for the combination of the state state in + * COGL_PIPELINE_STATE_AFFECTS_VERTEX_CODEGEN and + * COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN. If there is no + * matching pipline already then a copy of key_pipeline is stored in + * the cache so that it will be used next time the function is called + * with a similar pipeline. In that case the copy itself will be + * returned + */ +CoglPipelineCacheEntry * +_cogl_pipeline_cache_get_combined_template (CoglPipelineCache *cache, + CoglPipeline *key_pipeline); + +#endif /* __COGL_PIPELINE_CACHE_H__ */ diff --git a/cogl/cogl/cogl-pipeline-debug.c b/cogl/cogl/cogl-pipeline-debug.c new file mode 100644 index 0000000..0e4f6cd --- /dev/null +++ b/cogl/cogl/cogl-pipeline-debug.c @@ -0,0 +1,301 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009,2010,2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-context-private.h" +#include "cogl-pipeline-private.h" +#include "cogl-pipeline-layer-private.h" +#include "cogl-node-private.h" + +#include + +typedef struct +{ + int parent_id; + int *node_id_ptr; + GString *graph; + int indent; +} PrintDebugState; + +static CoglBool +dump_layer_cb (CoglNode *node, void *user_data) +{ + CoglPipelineLayer *layer = COGL_PIPELINE_LAYER (node); + PrintDebugState *state = user_data; + int layer_id = *state->node_id_ptr; + PrintDebugState state_out; + GString *changes_label; + CoglBool changes = FALSE; + + if (state->parent_id >= 0) + g_string_append_printf (state->graph, "%*slayer%p -> layer%p;\n", + state->indent, "", + layer->_parent.parent, + layer); + + g_string_append_printf (state->graph, + "%*slayer%p [label=\"layer=0x%p\\n" + "ref count=%d\" " + "color=\"blue\"];\n", + state->indent, "", + layer, + layer, + COGL_OBJECT (layer)->ref_count); + + changes_label = g_string_new (""); + g_string_append_printf (changes_label, + "%*slayer%p -> layer_state%d [weight=100];\n" + "%*slayer_state%d [shape=box label=\"", + state->indent, "", + layer, + layer_id, + state->indent, "", + layer_id); + + if (layer->differences & COGL_PIPELINE_LAYER_STATE_UNIT) + { + changes = TRUE; + g_string_append_printf (changes_label, + "\\lunit=%u\\n", + layer->unit_index); + } + + if (layer->differences & COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA) + { + changes = TRUE; + g_string_append_printf (changes_label, + "\\ltexture=%p\\n", + layer->texture); + } + + if (changes) + { + g_string_append_printf (changes_label, "\"];\n"); + g_string_append (state->graph, changes_label->str); + g_string_free (changes_label, TRUE); + } + + state_out.parent_id = layer_id; + + state_out.node_id_ptr = state->node_id_ptr; + (*state_out.node_id_ptr)++; + + state_out.graph = state->graph; + state_out.indent = state->indent + 2; + + _cogl_pipeline_node_foreach_child (COGL_NODE (layer), + dump_layer_cb, + &state_out); + + return TRUE; +} + +static CoglBool +dump_layer_ref_cb (CoglPipelineLayer *layer, void *data) +{ + PrintDebugState *state = data; + int pipeline_id = *state->node_id_ptr; + + g_string_append_printf (state->graph, + "%*spipeline_state%d -> layer%p;\n", + state->indent, "", + pipeline_id, + layer); + + return TRUE; +} + +static CoglBool +dump_pipeline_cb (CoglNode *node, void *user_data) +{ + CoglPipeline *pipeline = COGL_PIPELINE (node); + PrintDebugState *state = user_data; + int pipeline_id = *state->node_id_ptr; + PrintDebugState state_out; + GString *changes_label; + CoglBool changes = FALSE; + CoglBool layers = FALSE; + + if (state->parent_id >= 0) + g_string_append_printf (state->graph, "%*spipeline%d -> pipeline%d;\n", + state->indent, "", + state->parent_id, + pipeline_id); + + g_string_append_printf (state->graph, + "%*spipeline%d [label=\"pipeline=0x%p\\n" + "ref count=%d\\n" + "breadcrumb=\\\"%s\\\"\" color=\"red\"];\n", + state->indent, "", + pipeline_id, + pipeline, + COGL_OBJECT (pipeline)->ref_count, + pipeline->has_static_breadcrumb ? +#ifdef COGL_DEBUG_ENABLED + pipeline->static_breadcrumb : "NULL" +#else + "NULL" +#endif + ); + + changes_label = g_string_new (""); + g_string_append_printf (changes_label, + "%*spipeline%d -> pipeline_state%d [weight=100];\n" + "%*spipeline_state%d [shape=box label=\"", + state->indent, "", + pipeline_id, + pipeline_id, + state->indent, "", + pipeline_id); + + + if (pipeline->differences & COGL_PIPELINE_STATE_COLOR) + { + changes = TRUE; + g_string_append_printf (changes_label, + "\\lcolor=0x%02X%02X%02X%02X\\n", + cogl_color_get_red_byte (&pipeline->color), + cogl_color_get_green_byte (&pipeline->color), + cogl_color_get_blue_byte (&pipeline->color), + cogl_color_get_alpha_byte (&pipeline->color)); + } + + if (pipeline->differences & COGL_PIPELINE_STATE_BLEND) + { + const char *blend_enable_name; + + changes = TRUE; + + switch (pipeline->blend_enable) + { + case COGL_PIPELINE_BLEND_ENABLE_AUTOMATIC: + blend_enable_name = "AUTO"; + break; + case COGL_PIPELINE_BLEND_ENABLE_ENABLED: + blend_enable_name = "ENABLED"; + break; + case COGL_PIPELINE_BLEND_ENABLE_DISABLED: + blend_enable_name = "DISABLED"; + break; + default: + blend_enable_name = "UNKNOWN"; + } + g_string_append_printf (changes_label, + "\\lblend=%s\\n", + blend_enable_name); + } + + if (pipeline->differences & COGL_PIPELINE_STATE_LAYERS) + { + changes = TRUE; + layers = TRUE; + g_string_append_printf (changes_label, "\\ln_layers=%d\\n", + pipeline->n_layers); + } + + if (changes) + { + g_string_append_printf (changes_label, "\"];\n"); + g_string_append (state->graph, changes_label->str); + g_string_free (changes_label, TRUE); + } + + if (layers) + { + g_list_foreach (pipeline->layer_differences, + (GFunc)dump_layer_ref_cb, + state); + } + + state_out.parent_id = pipeline_id; + + state_out.node_id_ptr = state->node_id_ptr; + (*state_out.node_id_ptr)++; + + state_out.graph = state->graph; + state_out.indent = state->indent + 2; + + _cogl_pipeline_node_foreach_child (COGL_NODE (pipeline), + dump_pipeline_cb, + &state_out); + + return TRUE; +} + +/* This function is just here to be called from GDB so we don't really + want to put a declaration in a header and we just add it here to + avoid a warning */ +void +_cogl_debug_dump_pipelines_dot_file (const char *filename); + +void +_cogl_debug_dump_pipelines_dot_file (const char *filename) +{ + GString *graph; + PrintDebugState layer_state; + PrintDebugState pipeline_state; + int layer_id = 0; + int pipeline_id = 0; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (!ctx->default_pipeline) + return; + + graph = g_string_new (""); + g_string_append_printf (graph, "digraph {\n"); + + layer_state.graph = graph; + layer_state.parent_id = -1; + layer_state.node_id_ptr = &layer_id; + layer_state.indent = 0; + dump_layer_cb ((CoglNode *)ctx->default_layer_0, &layer_state); + + pipeline_state.graph = graph; + pipeline_state.parent_id = -1; + pipeline_state.node_id_ptr = &pipeline_id; + pipeline_state.indent = 0; + dump_pipeline_cb ((CoglNode *)ctx->default_pipeline, &pipeline_state); + + g_string_append_printf (graph, "}\n"); + + if (filename) + g_file_set_contents (filename, graph->str, -1, NULL); + else + g_print ("%s", graph->str); + + g_string_free (graph, TRUE); +} diff --git a/cogl/cogl/cogl-pipeline-hash-table.c b/cogl/cogl/cogl-pipeline-hash-table.c new file mode 100644 index 0000000..8f961b0 --- /dev/null +++ b/cogl/cogl/cogl-pipeline-hash-table.c @@ -0,0 +1,233 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * Authors: + * Neil Roberts + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-context-private.h" +#include "cogl-pipeline-private.h" +#include "cogl-pipeline-hash-table.h" +#include "cogl-pipeline-cache.h" + +typedef struct +{ + CoglPipelineCacheEntry parent; + + /* Calculating the hash is a little bit expensive for pipelines so + * we don't want to do it repeatedly for entries that are already in + * the hash table. Instead we cache the value here and calculate it + * outside of the GHashTable. */ + unsigned int hash_value; + + /* GHashTable annoyingly doesn't let us pass a user data pointer to + * the hash and equal functions so to work around it we have to + * store the pointer in every hash table entry. We will use this + * entry as both the key and the value */ + CoglPipelineHashTable *hash; + + /* The number of unique pipelines that had been created when this + * pipeline was last accessed */ + int age; +} CoglPipelineHashTableEntry; + +static void +value_destroy_cb (void *value) +{ + CoglPipelineHashTableEntry *entry = value; + + cogl_object_unref (entry->parent.pipeline); + + g_slice_free (CoglPipelineHashTableEntry, entry); +} + +static unsigned int +entry_hash (const void *data) +{ + const CoglPipelineHashTableEntry *entry = data; + + return entry->hash_value; +} + +static CoglBool +entry_equal (const void *a, + const void *b) +{ + const CoglPipelineHashTableEntry *entry_a = a; + const CoglPipelineHashTableEntry *entry_b = b; + const CoglPipelineHashTable *hash = entry_a->hash; + + return _cogl_pipeline_equal (entry_a->parent.pipeline, + entry_b->parent.pipeline, + hash->main_state, + hash->layer_state, + 0); +} + +void +_cogl_pipeline_hash_table_init (CoglPipelineHashTable *hash, + unsigned int main_state, + unsigned int layer_state, + const char *debug_string) +{ + hash->n_unique_pipelines = 0; + hash->debug_string = debug_string; + hash->main_state = main_state; + hash->layer_state = layer_state; + /* We'll only start pruning once we get to 16 unique pipelines */ + hash->expected_min_size = 8; + hash->table = g_hash_table_new_full (entry_hash, + entry_equal, + NULL, /* key destroy */ + value_destroy_cb); +} + +void +_cogl_pipeline_hash_table_destroy (CoglPipelineHashTable *hash) +{ + g_hash_table_destroy (hash->table); +} + +static void +collect_prunable_entries_cb (void *key, + void *value, + void *user_data) +{ + GQueue *entries = user_data; + CoglPipelineCacheEntry *entry = value; + + if (entry->usage_count == 0) + g_queue_push_tail (entries, entry); +} + +static int +compare_pipeline_age_cb (const void *a, + const void *b) +{ + const CoglPipelineHashTableEntry *ae = a; + const CoglPipelineHashTableEntry *be = b; + + return be->age - ae->age; +} + +static void +prune_old_pipelines (CoglPipelineHashTable *hash) +{ + GQueue entries; + GList *l; + int i; + + /* Collect all of the prunable entries into a GQueue */ + g_queue_init (&entries); + g_hash_table_foreach (hash->table, + collect_prunable_entries_cb, + &entries); + + /* Sort the entries by increasing order of age */ + entries.head = g_list_sort (entries.head, compare_pipeline_age_cb); + + /* The +1 is to include the pipeline that we're about to add */ + hash->expected_min_size = (g_hash_table_size (hash->table) - + entries.length + + 1); + + /* Remove oldest half of the prunable pipelines. We still want to + * keep some of the prunable entries that are recently used because + * it's not unlikely that the application will recreate the same + * pipeline */ + for (l = entries.head, i = 0; i < entries.length / 2; l = l->next, i++) + { + CoglPipelineCacheEntry *entry = l->data; + + g_hash_table_remove (hash->table, entry); + } + + g_list_free (entries.head); +} + +CoglPipelineCacheEntry * +_cogl_pipeline_hash_table_get (CoglPipelineHashTable *hash, + CoglPipeline *key_pipeline) +{ + CoglPipelineHashTableEntry dummy_entry; + CoglPipelineHashTableEntry *entry; + unsigned int copy_state; + + dummy_entry.parent.pipeline = key_pipeline; + dummy_entry.hash = hash; + dummy_entry.hash_value = _cogl_pipeline_hash (key_pipeline, + hash->main_state, + hash->layer_state, + 0); + entry = g_hash_table_lookup (hash->table, &dummy_entry); + + if (entry) + { + entry->age = hash->n_unique_pipelines; + return &entry->parent; + } + + if (hash->n_unique_pipelines == 50) + g_warning ("Over 50 separate %s have been generated which is very " + "unusual, so something is probably wrong!\n", + hash->debug_string); + + /* If we are going to have more than twice the expected minimum + * number of pipelines in the hash then we'll try pruning and update + * the minimum */ + if (g_hash_table_size (hash->table) >= hash->expected_min_size * 2) + prune_old_pipelines (hash); + + entry = g_slice_new (CoglPipelineHashTableEntry); + entry->parent.usage_count = 0; + entry->hash = hash; + entry->hash_value = dummy_entry.hash_value; + entry->age = hash->n_unique_pipelines; + + copy_state = hash->main_state; + if (hash->layer_state) + copy_state |= COGL_PIPELINE_STATE_LAYERS; + + /* Create a new pipeline that is a child of the root pipeline + * instead of a normal copy so that the template pipeline won't hold + * a reference to the original pipeline */ + entry->parent.pipeline = _cogl_pipeline_deep_copy (key_pipeline, + copy_state, + hash->layer_state); + + g_hash_table_insert (hash->table, entry, entry); + + hash->n_unique_pipelines++; + + return &entry->parent; +} diff --git a/cogl/cogl/cogl-pipeline-hash-table.h b/cogl/cogl/cogl-pipeline-hash-table.h new file mode 100644 index 0000000..035e8df --- /dev/null +++ b/cogl/cogl/cogl-pipeline-hash-table.h @@ -0,0 +1,81 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_PIPELINE_HASH_H__ +#define __COGL_PIPELINE_HASH_H__ + +#include "cogl-pipeline-cache.h" + +typedef struct +{ + /* Total number of pipelines that were ever added to the hash. This + * is not decremented when a pipeline is removed. It is only used to + * generate a warning if an unusually high number of pipelines are + * generated */ + int n_unique_pipelines; + + /* This is the expected minimum size we could prune the hash table + * to if we were to remove all pipelines that are not in use. This + * is only updated after we prune the table */ + int expected_min_size; + + /* String that will be used to describe the usage of this hash table + * in the debug warning when too many pipelines are generated. This + * must be a static string because it won't be copied or freed */ + const char *debug_string; + + unsigned int main_state; + unsigned int layer_state; + + GHashTable *table; +} CoglPipelineHashTable; + +void +_cogl_pipeline_hash_table_init (CoglPipelineHashTable *hash, + unsigned int main_state, + unsigned int layer_state, + const char *debug_string); + +void +_cogl_pipeline_hash_table_destroy (CoglPipelineHashTable *hash); + +/* + * Gets a pipeline from the hash that has the same state as + * @key_pipeline according to the limited state bits passed to + * _cogl_pipeline_hash_table_init(). If there is no matching pipelines + * already then a copy of key_pipeline is stored in the hash so that + * it will be used next time the function is called with a similar + * pipeline. In that case the copy itself will be returned + */ +CoglPipelineCacheEntry * +_cogl_pipeline_hash_table_get (CoglPipelineHashTable *hash, + CoglPipeline *key_pipeline); + +#endif /* __COGL_PIPELINE_HASH_H__ */ diff --git a/cogl/cogl/cogl-pipeline-layer-private.h b/cogl/cogl/cogl-pipeline-layer-private.h new file mode 100644 index 0000000..38cd3b5 --- /dev/null +++ b/cogl/cogl/cogl-pipeline-layer-private.h @@ -0,0 +1,390 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009,2010,2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_PIPELINE_LAYER_PRIVATE_H +#define __COGL_PIPELINE_LAYER_PRIVATE_H + +#include "cogl-private.h" +#include "cogl-pipeline.h" +#include "cogl-node-private.h" +#include "cogl-texture.h" +#include "cogl-matrix.h" +#include "cogl-pipeline-layer-state.h" +#include "cogl-pipeline-snippet-private.h" +#include "cogl-sampler-cache-private.h" + +#include + +typedef struct _CoglPipelineLayer CoglPipelineLayer; +#define COGL_PIPELINE_LAYER(OBJECT) ((CoglPipelineLayer *)OBJECT) + +/* XXX: should I rename these as + * COGL_PIPELINE_LAYER_STATE_INDEX_XYZ... ? + */ +typedef enum +{ + /* sparse state */ + COGL_PIPELINE_LAYER_STATE_UNIT_INDEX, + COGL_PIPELINE_LAYER_STATE_TEXTURE_TYPE_INDEX, + COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA_INDEX, + COGL_PIPELINE_LAYER_STATE_SAMPLER_INDEX, + COGL_PIPELINE_LAYER_STATE_COMBINE_INDEX, + COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT_INDEX, + COGL_PIPELINE_LAYER_STATE_USER_MATRIX_INDEX, + COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS_INDEX, + COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS_INDEX, + COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS_INDEX, + + /* note: layers don't currently have any non-sparse state */ + + COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT, + COGL_PIPELINE_LAYER_STATE_COUNT = COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT +} CoglPipelineLayerStateIndex; + +/* XXX: If you add or remove state groups here you may need to update + * some of the state masks following this enum too! + * + * FIXME: perhaps it would be better to rename this enum to + * CoglPipelineLayerStateGroup to better convey the fact that a single + * enum here can map to multiple properties. + */ +typedef enum +{ + COGL_PIPELINE_LAYER_STATE_UNIT = + 1L< TEXTURE0 to store + very large layer numbers */ + COGL_PIPELINE_COMBINE_SOURCE_TEXTURE, + COGL_PIPELINE_COMBINE_SOURCE_CONSTANT, + COGL_PIPELINE_COMBINE_SOURCE_PRIMARY_COLOR, + COGL_PIPELINE_COMBINE_SOURCE_PREVIOUS, + COGL_PIPELINE_COMBINE_SOURCE_TEXTURE0 +} CoglPipelineCombineSource; + +typedef enum +{ + /* These are the same values as GL */ + COGL_PIPELINE_COMBINE_OP_SRC_COLOR = 0x0300, + COGL_PIPELINE_COMBINE_OP_ONE_MINUS_SRC_COLOR = 0x0301, + COGL_PIPELINE_COMBINE_OP_SRC_ALPHA = 0x0302, + COGL_PIPELINE_COMBINE_OP_ONE_MINUS_SRC_ALPHA = 0x0303 +} CoglPipelineCombineOp; + +typedef struct +{ + /* The texture combine state determines how the color of individual + * texture fragments are calculated. */ + CoglPipelineCombineFunc texture_combine_rgb_func; + CoglPipelineCombineSource texture_combine_rgb_src[3]; + CoglPipelineCombineOp texture_combine_rgb_op[3]; + + CoglPipelineCombineFunc texture_combine_alpha_func; + CoglPipelineCombineSource texture_combine_alpha_src[3]; + CoglPipelineCombineOp texture_combine_alpha_op[3]; + + float texture_combine_constant[4]; + + /* The texture matrix dscribes how to transform texture coordinates */ + CoglMatrix matrix; + + CoglPipelineSnippetList vertex_snippets; + CoglPipelineSnippetList fragment_snippets; + + CoglBool point_sprite_coords; +} CoglPipelineLayerBigState; + +struct _CoglPipelineLayer +{ + /* XXX: Please think twice about adding members that *have* be + * initialized during a _cogl_pipeline_layer_copy. We are aiming + * to have copies be as cheap as possible and copies may be + * done by the primitives APIs which means they may happen + * in performance critical code paths. + * + * XXX: If you are extending the state we track please consider if + * the state is expected to vary frequently across many pipelines or + * if the state can be shared among many derived pipelines instead. + * This will determine if the state should be added directly to this + * structure which will increase the memory overhead for *all* + * layers or if instead it can go under ->big_state. + */ + + /* Layers represent their state in a tree structure where some of + * the state relating to a given pipeline or layer may actually be + * owned by one if is ancestors in the tree. We have a common data + * type to track the tree heirachy so we can share code... */ + CoglNode _parent; + + /* Some layers have a pipeline owner, which is to say that the layer + * is referenced in that pipelines->layer_differences list. A layer + * doesn't always have an owner and may simply be an ancestor for + * other layers that keeps track of some shared state. */ + CoglPipeline *owner; + + /* The lowest index is blended first then others on top */ + int index; + + /* A mask of which state groups are different in this layer + * in comparison to its parent. */ + unsigned int differences; + + /* Common differences + * + * As a basic way to reduce memory usage we divide the layer + * state into two groups; the minimal state modified in 90% of + * all layers and the rest, so that the second group can + * be allocated dynamically when required. + */ + + /* Each layer is directly associated with a single texture unit */ + int unit_index; + + /* The type of the texture. This is always set even if the texture + is NULL and it will be used to determine what type of texture + lookups to use in any shaders generated by the pipeline + backends. */ + CoglTextureType texture_type; + /* The texture for this layer, or NULL for an empty + * layer */ + CoglTexture *texture; + + const CoglSamplerCacheEntry *sampler_cache_entry; + + /* Infrequent differences aren't currently tracked in + * a separate, dynamically allocated structure as they are + * for pipelines... */ + CoglPipelineLayerBigState *big_state; + + /* bitfields */ + + /* Determines if layer->big_state is valid */ + unsigned int has_big_state:1; + +}; + +typedef CoglBool +(*CoglPipelineLayerStateComparitor) (CoglPipelineLayer *authority0, + CoglPipelineLayer *authority1); + + + +void +_cogl_pipeline_init_default_layers (void); + +static inline CoglPipelineLayer * +_cogl_pipeline_layer_get_parent (CoglPipelineLayer *layer) +{ + CoglNode *parent_node = COGL_NODE (layer)->parent; + return COGL_PIPELINE_LAYER (parent_node); +} + +CoglPipelineLayer * +_cogl_pipeline_layer_copy (CoglPipelineLayer *layer); + +void +_cogl_pipeline_layer_resolve_authorities (CoglPipelineLayer *layer, + unsigned long differences, + CoglPipelineLayer **authorities); + +CoglBool +_cogl_pipeline_layer_equal (CoglPipelineLayer *layer0, + CoglPipelineLayer *layer1, + unsigned long differences_mask, + CoglPipelineEvalFlags flags); + +CoglPipelineLayer * +_cogl_pipeline_layer_pre_change_notify (CoglPipeline *required_owner, + CoglPipelineLayer *layer, + CoglPipelineLayerState change); + +void +_cogl_pipeline_layer_prune_redundant_ancestry (CoglPipelineLayer *layer); + +CoglBool +_cogl_pipeline_layer_has_alpha (CoglPipelineLayer *layer); + +CoglBool +_cogl_pipeline_layer_has_user_matrix (CoglPipeline *pipeline, + int layer_index); + +/* + * Calls the pre_paint method on the layer texture if there is + * one. This will determine whether mipmaps are needed based on the + * filter settings. + */ +void +_cogl_pipeline_layer_pre_paint (CoglPipelineLayer *layerr); + +void +_cogl_pipeline_layer_get_wrap_modes (CoglPipelineLayer *layer, + CoglSamplerCacheWrapMode *wrap_mode_s, + CoglSamplerCacheWrapMode *wrap_mode_t, + CoglSamplerCacheWrapMode *wrap_mode_r); + +void +_cogl_pipeline_layer_get_filters (CoglPipelineLayer *layer, + CoglPipelineFilter *min_filter, + CoglPipelineFilter *mag_filter); + +const CoglSamplerCacheEntry * +_cogl_pipeline_layer_get_sampler_state (CoglPipelineLayer *layer); + +void +_cogl_pipeline_get_layer_filters (CoglPipeline *pipeline, + int layer_index, + CoglPipelineFilter *min_filter, + CoglPipelineFilter *mag_filter); + +typedef enum { + COGL_PIPELINE_LAYER_TYPE_TEXTURE +} CoglPipelineLayerType; + +CoglPipelineLayerType +_cogl_pipeline_layer_get_type (CoglPipelineLayer *layer); + +CoglTexture * +_cogl_pipeline_layer_get_texture (CoglPipelineLayer *layer); + +CoglTexture * +_cogl_pipeline_layer_get_texture_real (CoglPipelineLayer *layer); + +CoglTextureType +_cogl_pipeline_layer_get_texture_type (CoglPipelineLayer *layer); + +CoglPipelineFilter +_cogl_pipeline_layer_get_min_filter (CoglPipelineLayer *layer); + +CoglPipelineFilter +_cogl_pipeline_layer_get_mag_filter (CoglPipelineLayer *layer); + +CoglPipelineWrapMode +_cogl_pipeline_layer_get_wrap_mode_s (CoglPipelineLayer *layer); + +CoglPipelineWrapMode +_cogl_pipeline_layer_get_wrap_mode_t (CoglPipelineLayer *layer); + +CoglPipelineWrapMode +_cogl_pipeline_layer_get_wrap_mode_p (CoglPipelineLayer *layer); + +void +_cogl_pipeline_layer_copy_differences (CoglPipelineLayer *dest, + CoglPipelineLayer *src, + unsigned long differences); + +unsigned long +_cogl_pipeline_layer_compare_differences (CoglPipelineLayer *layer0, + CoglPipelineLayer *layer1); + +CoglPipelineLayer * +_cogl_pipeline_layer_get_authority (CoglPipelineLayer *layer, + unsigned long difference); + +CoglTexture * +_cogl_pipeline_layer_get_texture (CoglPipelineLayer *layer); + +int +_cogl_pipeline_layer_get_unit_index (CoglPipelineLayer *layer); + +CoglBool +_cogl_pipeline_layer_needs_combine_separate + (CoglPipelineLayer *combine_authority); + +#endif /* __COGL_PIPELINE_LAYER_PRIVATE_H */ diff --git a/cogl/cogl/cogl-pipeline-layer-state-private.h b/cogl/cogl/cogl-pipeline-layer-state-private.h new file mode 100644 index 0000000..64e70cf --- /dev/null +++ b/cogl/cogl/cogl-pipeline-layer-state-private.h @@ -0,0 +1,141 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_PIPELINE_LAYER_STATE_PRIVATE_H +#define __COGL_PIPELINE_LAYER_STATE_PRIVATE_H + +#include "cogl-pipeline-layer-state.h" +#include "cogl-pipeline-private.h" + +CoglPipelineLayer * +_cogl_pipeline_set_layer_unit (CoglPipeline *required_owner, + CoglPipelineLayer *layer, + int unit_index); + +CoglPipelineFilter +_cogl_pipeline_get_layer_min_filter (CoglPipeline *pipeline, + int layer_index); + +CoglPipelineFilter +_cogl_pipeline_get_layer_mag_filter (CoglPipeline *pipeline, + int layer_index); + +CoglBool +_cogl_pipeline_layer_texture_type_equal (CoglPipelineLayer *authority0, + CoglPipelineLayer *authority1, + CoglPipelineEvalFlags flags); + +CoglBool +_cogl_pipeline_layer_texture_data_equal (CoglPipelineLayer *authority0, + CoglPipelineLayer *authority1, + CoglPipelineEvalFlags flags); + +CoglBool +_cogl_pipeline_layer_combine_state_equal (CoglPipelineLayer *authority0, + CoglPipelineLayer *authority1); + +CoglBool +_cogl_pipeline_layer_combine_constant_equal (CoglPipelineLayer *authority0, + CoglPipelineLayer *authority1); + +CoglBool +_cogl_pipeline_layer_sampler_equal (CoglPipelineLayer *authority0, + CoglPipelineLayer *authority1); + +CoglBool +_cogl_pipeline_layer_user_matrix_equal (CoglPipelineLayer *authority0, + CoglPipelineLayer *authority1); + +CoglBool +_cogl_pipeline_layer_point_sprite_coords_equal (CoglPipelineLayer *authority0, + CoglPipelineLayer *authority1); + +CoglBool +_cogl_pipeline_layer_vertex_snippets_equal (CoglPipelineLayer *authority0, + CoglPipelineLayer *authority1); + +CoglBool +_cogl_pipeline_layer_fragment_snippets_equal (CoglPipelineLayer *authority0, + CoglPipelineLayer *authority1); + +void +_cogl_pipeline_layer_hash_unit_state (CoglPipelineLayer *authority, + CoglPipelineLayer **authorities, + CoglPipelineHashState *state); + +void +_cogl_pipeline_layer_hash_texture_type_state (CoglPipelineLayer *authority, + CoglPipelineLayer **authorities, + CoglPipelineHashState *state); + +void +_cogl_pipeline_layer_hash_texture_data_state (CoglPipelineLayer *authority, + CoglPipelineLayer **authorities, + CoglPipelineHashState *state); + +void +_cogl_pipeline_layer_hash_sampler_state (CoglPipelineLayer *authority, + CoglPipelineLayer **authorities, + CoglPipelineHashState *state); + +void +_cogl_pipeline_layer_hash_combine_state (CoglPipelineLayer *authority, + CoglPipelineLayer **authorities, + CoglPipelineHashState *state); + +void +_cogl_pipeline_layer_hash_combine_constant_state (CoglPipelineLayer *authority, + CoglPipelineLayer **authorities, + CoglPipelineHashState *state); + +void +_cogl_pipeline_layer_hash_user_matrix_state (CoglPipelineLayer *authority, + CoglPipelineLayer **authorities, + CoglPipelineHashState *state); + +void +_cogl_pipeline_layer_hash_point_sprite_state (CoglPipelineLayer *authority, + CoglPipelineLayer **authorities, + CoglPipelineHashState *state); + +void +_cogl_pipeline_layer_hash_vertex_snippets_state (CoglPipelineLayer *authority, + CoglPipelineLayer **authorities, + CoglPipelineHashState *state); + +void +_cogl_pipeline_layer_hash_fragment_snippets_state (CoglPipelineLayer *authority, + CoglPipelineLayer **authorities, + CoglPipelineHashState *state); + +#endif /* __COGL_PIPELINE_LAYER_STATE_PRIVATE_H */ diff --git a/cogl/cogl/cogl-pipeline-layer-state.c b/cogl/cogl/cogl-pipeline-layer-state.c new file mode 100644 index 0000000..c30fae9 --- /dev/null +++ b/cogl/cogl/cogl-pipeline-layer-state.c @@ -0,0 +1,1814 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-context-private.h" +#include "cogl-pipeline-private.h" +#include "cogl-blend-string.h" +#include "cogl-util.h" +#include "cogl-matrix.h" +#include "cogl-snippet-private.h" +#include "cogl-texture-private.h" +#include "cogl-pipeline-layer-state-private.h" +#include "cogl-error-private.h" + +#include "string.h" +#if 0 +#include "cogl-context-private.h" +#include "cogl-color-private.h" + +#endif + +/* + * XXX: consider special casing layer->unit_index so it's not a sparse + * property so instead we can assume it's valid for all layer + * instances. + * - We would need to initialize ->unit_index in + * _cogl_pipeline_layer_copy (). + * + * XXX: If you use this API you should consider that the given layer + * might not be writeable and so a new derived layer will be allocated + * and modified instead. The layer modified will be returned so you + * can identify when this happens. + */ +CoglPipelineLayer * +_cogl_pipeline_set_layer_unit (CoglPipeline *required_owner, + CoglPipelineLayer *layer, + int unit_index) +{ + CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_UNIT; + CoglPipelineLayer *authority = + _cogl_pipeline_layer_get_authority (layer, change); + CoglPipelineLayer *new; + + if (authority->unit_index == unit_index) + return layer; + + new = + _cogl_pipeline_layer_pre_change_notify (required_owner, + layer, + change); + if (new != layer) + layer = new; + else + { + /* If the layer we found is currently the authority on the state + * we are changing see if we can revert to one of our ancestors + * being the authority. */ + if (layer == authority && + _cogl_pipeline_layer_get_parent (authority) != NULL) + { + CoglPipelineLayer *parent = + _cogl_pipeline_layer_get_parent (authority); + CoglPipelineLayer *old_authority = + _cogl_pipeline_layer_get_authority (parent, change); + + if (old_authority->unit_index == unit_index) + { + layer->differences &= ~change; + return layer; + } + } + } + + layer->unit_index = unit_index; + + /* If we weren't previously the authority on this state then we need + * to extended our differences mask and so it's possible that some + * of our ancestry will now become redundant, so we aim to reparent + * ourselves if that's true... */ + if (layer != authority) + { + layer->differences |= change; + _cogl_pipeline_layer_prune_redundant_ancestry (layer); + } + + return layer; +} + +CoglTexture * +_cogl_pipeline_layer_get_texture_real (CoglPipelineLayer *layer) +{ + CoglPipelineLayer *authority = + _cogl_pipeline_layer_get_authority (layer, + COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA); + + return authority->texture; +} + +CoglTexture * +cogl_pipeline_get_layer_texture (CoglPipeline *pipeline, + int layer_index) +{ + CoglPipelineLayer *layer = + _cogl_pipeline_get_layer (pipeline, layer_index); + return _cogl_pipeline_layer_get_texture (layer); +} + +CoglTextureType +_cogl_pipeline_layer_get_texture_type (CoglPipelineLayer *layer) +{ + CoglPipelineLayer *authority = + _cogl_pipeline_layer_get_authority (layer, + COGL_PIPELINE_LAYER_STATE_TEXTURE_TYPE); + + return authority->texture_type; +} + +static void +_cogl_pipeline_set_layer_texture_type (CoglPipeline *pipeline, + int layer_index, + CoglTextureType texture_type) +{ + CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_TEXTURE_TYPE; + CoglPipelineLayer *layer; + CoglPipelineLayer *authority; + CoglPipelineLayer *new; + + /* Note: this will ensure that the layer exists, creating one if it + * doesn't already. + * + * Note: If the layer already existed it's possibly owned by another + * pipeline. If the layer is created then it will be owned by + * pipeline. */ + layer = _cogl_pipeline_get_layer (pipeline, layer_index); + + /* Now find the ancestor of the layer that is the authority for the + * state we want to change */ + authority = _cogl_pipeline_layer_get_authority (layer, change); + + if (texture_type == authority->texture_type) + return; + + new = _cogl_pipeline_layer_pre_change_notify (pipeline, layer, change); + if (new != layer) + layer = new; + else + { + /* If the original layer we found is currently the authority on + * the state we are changing see if we can revert to one of our + * ancestors being the authority. */ + if (layer == authority && + _cogl_pipeline_layer_get_parent (authority) != NULL) + { + CoglPipelineLayer *parent = + _cogl_pipeline_layer_get_parent (authority); + CoglPipelineLayer *old_authority = + _cogl_pipeline_layer_get_authority (parent, change); + + if (old_authority->texture_type == texture_type) + { + layer->differences &= ~change; + + g_assert (layer->owner == pipeline); + if (layer->differences == 0) + _cogl_pipeline_prune_empty_layer_difference (pipeline, + layer); + goto changed; + } + } + } + + layer->texture_type = texture_type; + + /* If we weren't previously the authority on this state then we need + * to extended our differences mask and so it's possible that some + * of our ancestry will now become redundant, so we aim to reparent + * ourselves if that's true... */ + if (layer != authority) + { + layer->differences |= change; + _cogl_pipeline_layer_prune_redundant_ancestry (layer); + } + +changed: + + pipeline->dirty_real_blend_enable = TRUE; +} + +static void +_cogl_pipeline_set_layer_texture_data (CoglPipeline *pipeline, + int layer_index, + CoglTexture *texture) +{ + CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA; + CoglPipelineLayer *layer; + CoglPipelineLayer *authority; + CoglPipelineLayer *new; + + /* Note: this will ensure that the layer exists, creating one if it + * doesn't already. + * + * Note: If the layer already existed it's possibly owned by another + * pipeline. If the layer is created then it will be owned by + * pipeline. */ + layer = _cogl_pipeline_get_layer (pipeline, layer_index); + + /* Now find the ancestor of the layer that is the authority for the + * state we want to change */ + authority = _cogl_pipeline_layer_get_authority (layer, change); + + if (authority->texture == texture) + return; + + new = _cogl_pipeline_layer_pre_change_notify (pipeline, layer, change); + if (new != layer) + layer = new; + else + { + /* If the original layer we found is currently the authority on + * the state we are changing see if we can revert to one of our + * ancestors being the authority. */ + if (layer == authority && + _cogl_pipeline_layer_get_parent (authority) != NULL) + { + CoglPipelineLayer *parent = + _cogl_pipeline_layer_get_parent (authority); + CoglPipelineLayer *old_authority = + _cogl_pipeline_layer_get_authority (parent, change); + + if (old_authority->texture == texture) + { + layer->differences &= ~change; + + if (layer->texture != NULL) + cogl_object_unref (layer->texture); + + g_assert (layer->owner == pipeline); + if (layer->differences == 0) + _cogl_pipeline_prune_empty_layer_difference (pipeline, + layer); + goto changed; + } + } + } + + if (texture != NULL) + cogl_object_ref (texture); + if (layer == authority && + layer->texture != NULL) + cogl_object_unref (layer->texture); + layer->texture = texture; + + /* If we weren't previously the authority on this state then we need + * to extended our differences mask and so it's possible that some + * of our ancestry will now become redundant, so we aim to reparent + * ourselves if that's true... */ + if (layer != authority) + { + layer->differences |= change; + _cogl_pipeline_layer_prune_redundant_ancestry (layer); + } + +changed: + + pipeline->dirty_real_blend_enable = TRUE; +} + +void +cogl_pipeline_set_layer_texture (CoglPipeline *pipeline, + int layer_index, + CoglTexture *texture) +{ + /* For the convenience of fragend code we separate texture state + * into the "type" and the "data", and setting a layer texture + * updates both of these properties. + * + * One example for why this is helpful is that the fragends may + * cache programs they generate and want to re-use those programs + * with all pipelines having equivalent fragment processing state. + * For the sake of determining if pipelines have equivalent fragment + * processing state we don't need to compare that the same + * underlying texture objects are referenced by the pipelines but we + * do need to see if they use the same texture types. Making this + * distinction is much simpler if they are in different state + * groups. + * + * Note: if a NULL texture is set then we leave the type unchanged + * so we can avoid needlessly invalidating any associated fragment + * program. + */ + if (texture) + { + CoglTextureType texture_type = + _cogl_texture_get_type (texture); + _cogl_pipeline_set_layer_texture_type (pipeline, + layer_index, + texture_type); + } + _cogl_pipeline_set_layer_texture_data (pipeline, layer_index, texture); +} + +void +cogl_pipeline_set_layer_null_texture (CoglPipeline *pipeline, + int layer_index, + CoglTextureType texture_type) +{ + CoglContext *ctx = _cogl_context_get_default (); + + /* Disallow setting texture types that aren't supported */ + switch (texture_type) + { + case COGL_TEXTURE_TYPE_2D: + break; + + case COGL_TEXTURE_TYPE_3D: + if (ctx->default_gl_texture_3d_tex == NULL) + { + g_warning ("The default 3D texture was set on a pipeline but " + "3D textures are not supported"); + texture_type = COGL_TEXTURE_TYPE_2D; + return; + } + break; + + case COGL_TEXTURE_TYPE_RECTANGLE: + if (ctx->default_gl_texture_rect_tex == NULL) + { + g_warning ("The default rectangle texture was set on a pipeline but " + "rectangle textures are not supported"); + texture_type = COGL_TEXTURE_TYPE_2D; + } + break; + } + + _cogl_pipeline_set_layer_texture_type (pipeline, layer_index, texture_type); + _cogl_pipeline_set_layer_texture_data (pipeline, layer_index, NULL); +} + +static void +_cogl_pipeline_set_layer_sampler_state (CoglPipeline *pipeline, + CoglPipelineLayer *layer, + CoglPipelineLayer *authority, + const CoglSamplerCacheEntry *state) +{ + CoglPipelineLayer *new; + CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_SAMPLER; + + if (authority->sampler_cache_entry == state) + return; + + new = _cogl_pipeline_layer_pre_change_notify (pipeline, layer, change); + if (new != layer) + layer = new; + else + { + /* If the original layer we found is currently the authority on + * the state we are changing see if we can revert to one of our + * ancestors being the authority. */ + if (layer == authority && + _cogl_pipeline_layer_get_parent (authority) != NULL) + { + CoglPipelineLayer *parent = + _cogl_pipeline_layer_get_parent (authority); + CoglPipelineLayer *old_authority = + _cogl_pipeline_layer_get_authority (parent, change); + + if (old_authority->sampler_cache_entry == state) + { + layer->differences &= ~change; + + g_assert (layer->owner == pipeline); + if (layer->differences == 0) + _cogl_pipeline_prune_empty_layer_difference (pipeline, + layer); + return; + } + } + } + + layer->sampler_cache_entry = state; + + /* If we weren't previously the authority on this state then we need + * to extended our differences mask and so it's possible that some + * of our ancestry will now become redundant, so we aim to reparent + * ourselves if that's true... */ + if (layer != authority) + { + layer->differences |= change; + _cogl_pipeline_layer_prune_redundant_ancestry (layer); + } +} + +static CoglSamplerCacheWrapMode +public_to_internal_wrap_mode (CoglPipelineWrapMode mode) +{ + return (CoglSamplerCacheWrapMode)mode; +} + +static CoglPipelineWrapMode +internal_to_public_wrap_mode (CoglSamplerCacheWrapMode internal_mode) +{ + _COGL_RETURN_VAL_IF_FAIL (internal_mode != + COGL_SAMPLER_CACHE_WRAP_MODE_CLAMP_TO_BORDER, + COGL_PIPELINE_WRAP_MODE_AUTOMATIC); + return (CoglPipelineWrapMode)internal_mode; +} + +void +cogl_pipeline_set_layer_wrap_mode_s (CoglPipeline *pipeline, + int layer_index, + CoglPipelineWrapMode mode) +{ + CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_SAMPLER; + CoglPipelineLayer *layer; + CoglPipelineLayer *authority; + CoglSamplerCacheWrapMode internal_mode = + public_to_internal_wrap_mode (mode); + const CoglSamplerCacheEntry *sampler_state; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + /* Note: this will ensure that the layer exists, creating one if it + * doesn't already. + * + * Note: If the layer already existed it's possibly owned by another + * pipeline. If the layer is created then it will be owned by + * pipeline. */ + layer = _cogl_pipeline_get_layer (pipeline, layer_index); + + /* Now find the ancestor of the layer that is the authority for the + * state we want to change */ + authority = _cogl_pipeline_layer_get_authority (layer, change); + + sampler_state = + _cogl_sampler_cache_update_wrap_modes (ctx->sampler_cache, + authority->sampler_cache_entry, + internal_mode, + authority->sampler_cache_entry-> + wrap_mode_t, + authority->sampler_cache_entry-> + wrap_mode_p); + _cogl_pipeline_set_layer_sampler_state (pipeline, + layer, + authority, + sampler_state); +} + +void +cogl_pipeline_set_layer_wrap_mode_t (CoglPipeline *pipeline, + int layer_index, + CoglPipelineWrapMode mode) +{ + CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_SAMPLER; + CoglPipelineLayer *layer; + CoglPipelineLayer *authority; + CoglSamplerCacheWrapMode internal_mode = + public_to_internal_wrap_mode (mode); + const CoglSamplerCacheEntry *sampler_state; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + /* Note: this will ensure that the layer exists, creating one if it + * doesn't already. + * + * Note: If the layer already existed it's possibly owned by another + * pipeline. If the layer is created then it will be owned by + * pipeline. */ + layer = _cogl_pipeline_get_layer (pipeline, layer_index); + + /* Now find the ancestor of the layer that is the authority for the + * state we want to change */ + authority = _cogl_pipeline_layer_get_authority (layer, change); + + sampler_state = + _cogl_sampler_cache_update_wrap_modes (ctx->sampler_cache, + authority->sampler_cache_entry, + authority->sampler_cache_entry-> + wrap_mode_s, + internal_mode, + authority->sampler_cache_entry-> + wrap_mode_p); + _cogl_pipeline_set_layer_sampler_state (pipeline, + layer, + authority, + sampler_state); +} + +/* The rationale for naming the third texture coordinate 'p' instead + of OpenGL's usual 'r' is that 'r' conflicts with the usual naming + of the 'red' component when treating a vector as a color. Under + GLSL this is awkward because the texture swizzling for a vector + uses a single letter for each component and the names for colors, + textures and positions are synonymous. GLSL works around this by + naming the components of the texture s, t, p and q. Cogl already + effectively already exposes this naming because it exposes GLSL so + it makes sense to use that naming consistently. Another alternative + could be u, v and w. This is what Blender and Direct3D use. However + the w component conflicts with the w component of a position + vertex. */ +void +cogl_pipeline_set_layer_wrap_mode_p (CoglPipeline *pipeline, + int layer_index, + CoglPipelineWrapMode mode) +{ + CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_SAMPLER; + CoglPipelineLayer *layer; + CoglPipelineLayer *authority; + CoglSamplerCacheWrapMode internal_mode = + public_to_internal_wrap_mode (mode); + const CoglSamplerCacheEntry *sampler_state; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + /* Note: this will ensure that the layer exists, creating one if it + * doesn't already. + * + * Note: If the layer already existed it's possibly owned by another + * pipeline. If the layer is created then it will be owned by + * pipeline. */ + layer = _cogl_pipeline_get_layer (pipeline, layer_index); + + /* Now find the ancestor of the layer that is the authority for the + * state we want to change */ + authority = _cogl_pipeline_layer_get_authority (layer, change); + + sampler_state = + _cogl_sampler_cache_update_wrap_modes (ctx->sampler_cache, + authority->sampler_cache_entry, + authority->sampler_cache_entry-> + wrap_mode_s, + authority->sampler_cache_entry-> + wrap_mode_t, + internal_mode); + _cogl_pipeline_set_layer_sampler_state (pipeline, + layer, + authority, + sampler_state); +} + +void +cogl_pipeline_set_layer_wrap_mode (CoglPipeline *pipeline, + int layer_index, + CoglPipelineWrapMode mode) +{ + CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_SAMPLER; + CoglPipelineLayer *layer; + CoglPipelineLayer *authority; + CoglSamplerCacheWrapMode internal_mode = + public_to_internal_wrap_mode (mode); + const CoglSamplerCacheEntry *sampler_state; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + /* Note: this will ensure that the layer exists, creating one if it + * doesn't already. + * + * Note: If the layer already existed it's possibly owned by another + * pipeline. If the layer is created then it will be owned by + * pipeline. */ + layer = _cogl_pipeline_get_layer (pipeline, layer_index); + + /* Now find the ancestor of the layer that is the authority for the + * state we want to change */ + authority = _cogl_pipeline_layer_get_authority (layer, change); + + sampler_state = + _cogl_sampler_cache_update_wrap_modes (ctx->sampler_cache, + authority->sampler_cache_entry, + internal_mode, + internal_mode, + internal_mode); + _cogl_pipeline_set_layer_sampler_state (pipeline, + layer, + authority, + sampler_state); + /* XXX: I wonder if we should really be duplicating the mode into + * the 'p' wrap mode too? */ +} + +/* FIXME: deprecate this API */ +CoglPipelineWrapMode +_cogl_pipeline_layer_get_wrap_mode_s (CoglPipelineLayer *layer) +{ + CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_SAMPLER; + CoglPipelineLayer *authority; + const CoglSamplerCacheEntry *sampler_state; + + _COGL_RETURN_VAL_IF_FAIL (_cogl_is_pipeline_layer (layer), FALSE); + + /* Now find the ancestor of the layer that is the authority for the + * state we want to change */ + authority = _cogl_pipeline_layer_get_authority (layer, change); + + sampler_state = authority->sampler_cache_entry; + return internal_to_public_wrap_mode (sampler_state->wrap_mode_s); +} + +CoglPipelineWrapMode +cogl_pipeline_get_layer_wrap_mode_s (CoglPipeline *pipeline, int layer_index) +{ + CoglPipelineLayer *layer; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), FALSE); + + /* Note: this will ensure that the layer exists, creating one if it + * doesn't already. + * + * Note: If the layer already existed it's possibly owned by another + * pipeline. If the layer is created then it will be owned by + * pipeline. */ + layer = _cogl_pipeline_get_layer (pipeline, layer_index); + /* FIXME: we shouldn't ever construct a layer in a getter function */ + + return _cogl_pipeline_layer_get_wrap_mode_s (layer); +} + +/* FIXME: deprecate this API */ +CoglPipelineWrapMode +_cogl_pipeline_layer_get_wrap_mode_t (CoglPipelineLayer *layer) +{ + CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_SAMPLER; + CoglPipelineLayer *authority; + const CoglSamplerCacheEntry *sampler_state; + + _COGL_RETURN_VAL_IF_FAIL (_cogl_is_pipeline_layer (layer), FALSE); + + /* Now find the ancestor of the layer that is the authority for the + * state we want to change */ + authority = _cogl_pipeline_layer_get_authority (layer, change); + + sampler_state = authority->sampler_cache_entry; + return internal_to_public_wrap_mode (sampler_state->wrap_mode_t); +} + +CoglPipelineWrapMode +cogl_pipeline_get_layer_wrap_mode_t (CoglPipeline *pipeline, int layer_index) +{ + CoglPipelineLayer *layer; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), FALSE); + + /* Note: this will ensure that the layer exists, creating one if it + * doesn't already. + * + * Note: If the layer already existed it's possibly owned by another + * pipeline. If the layer is created then it will be owned by + * pipeline. */ + layer = _cogl_pipeline_get_layer (pipeline, layer_index); + /* FIXME: we shouldn't ever construct a layer in a getter function */ + + return _cogl_pipeline_layer_get_wrap_mode_t (layer); +} + +CoglPipelineWrapMode +_cogl_pipeline_layer_get_wrap_mode_p (CoglPipelineLayer *layer) +{ + CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_SAMPLER; + CoglPipelineLayer *authority = + _cogl_pipeline_layer_get_authority (layer, change); + const CoglSamplerCacheEntry *sampler_state; + + sampler_state = authority->sampler_cache_entry; + return internal_to_public_wrap_mode (sampler_state->wrap_mode_p); +} + +CoglPipelineWrapMode +cogl_pipeline_get_layer_wrap_mode_p (CoglPipeline *pipeline, int layer_index) +{ + CoglPipelineLayer *layer; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), FALSE); + + /* Note: this will ensure that the layer exists, creating one if it + * doesn't already. + * + * Note: If the layer already existed it's possibly owned by another + * pipeline. If the layer is created then it will be owned by + * pipeline. */ + layer = _cogl_pipeline_get_layer (pipeline, layer_index); + + return _cogl_pipeline_layer_get_wrap_mode_p (layer); +} + +void +_cogl_pipeline_layer_get_wrap_modes (CoglPipelineLayer *layer, + CoglSamplerCacheWrapMode *wrap_mode_s, + CoglSamplerCacheWrapMode *wrap_mode_t, + CoglSamplerCacheWrapMode *wrap_mode_p) +{ + CoglPipelineLayer *authority = + _cogl_pipeline_layer_get_authority (layer, + COGL_PIPELINE_LAYER_STATE_SAMPLER); + + *wrap_mode_s = authority->sampler_cache_entry->wrap_mode_s; + *wrap_mode_t = authority->sampler_cache_entry->wrap_mode_t; + *wrap_mode_p = authority->sampler_cache_entry->wrap_mode_p; +} + +CoglBool +cogl_pipeline_set_layer_point_sprite_coords_enabled (CoglPipeline *pipeline, + int layer_index, + CoglBool enable, + CoglError **error) +{ + CoglPipelineLayerState change = + COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS; + CoglPipelineLayer *layer; + CoglPipelineLayer *new; + CoglPipelineLayer *authority; + + _COGL_GET_CONTEXT (ctx, FALSE); + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), FALSE); + + /* Don't allow point sprite coordinates to be enabled if the driver + doesn't support it */ + if (enable && !cogl_has_feature (ctx, COGL_FEATURE_ID_POINT_SPRITE)) + { + if (error) + { + _cogl_set_error (error, + COGL_SYSTEM_ERROR, + COGL_SYSTEM_ERROR_UNSUPPORTED, + "Point sprite texture coordinates are enabled for " + "a layer but the GL driver does not support it."); + } + else + { + static CoglBool warning_seen = FALSE; + if (!warning_seen) + g_warning ("Point sprite texture coordinates are enabled " + "for a layer but the GL driver does not support it."); + warning_seen = TRUE; + } + + return FALSE; + } + + /* Note: this will ensure that the layer exists, creating one if it + * doesn't already. + * + * Note: If the layer already existed it's possibly owned by another + * pipeline. If the layer is created then it will be owned by + * pipeline. */ + layer = _cogl_pipeline_get_layer (pipeline, layer_index); + + /* Now find the ancestor of the layer that is the authority for the + * state we want to change */ + authority = _cogl_pipeline_layer_get_authority (layer, change); + + if (authority->big_state->point_sprite_coords == enable) + return TRUE; + + new = _cogl_pipeline_layer_pre_change_notify (pipeline, layer, change); + if (new != layer) + layer = new; + else + { + /* If the original layer we found is currently the authority on + * the state we are changing see if we can revert to one of our + * ancestors being the authority. */ + if (layer == authority && + _cogl_pipeline_layer_get_parent (authority) != NULL) + { + CoglPipelineLayer *parent = + _cogl_pipeline_layer_get_parent (authority); + CoglPipelineLayer *old_authority = + _cogl_pipeline_layer_get_authority (parent, change); + + if (old_authority->big_state->point_sprite_coords == enable) + { + layer->differences &= ~change; + + g_assert (layer->owner == pipeline); + if (layer->differences == 0) + _cogl_pipeline_prune_empty_layer_difference (pipeline, + layer); + return TRUE; + } + } + } + + layer->big_state->point_sprite_coords = enable; + + /* If we weren't previously the authority on this state then we need + * to extended our differences mask and so it's possible that some + * of our ancestry will now become redundant, so we aim to reparent + * ourselves if that's true... */ + if (layer != authority) + { + layer->differences |= change; + _cogl_pipeline_layer_prune_redundant_ancestry (layer); + } + + return TRUE; +} + +CoglBool +cogl_pipeline_get_layer_point_sprite_coords_enabled (CoglPipeline *pipeline, + int layer_index) +{ + CoglPipelineLayerState change = + COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS; + CoglPipelineLayer *layer; + CoglPipelineLayer *authority; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), FALSE); + + /* Note: this will ensure that the layer exists, creating one if it + * doesn't already. + * + * Note: If the layer already existed it's possibly owned by another + * pipeline. If the layer is created then it will be owned by + * pipeline. */ + layer = _cogl_pipeline_get_layer (pipeline, layer_index); + /* FIXME: we shouldn't ever construct a layer in a getter function */ + + authority = _cogl_pipeline_layer_get_authority (layer, change); + + return authority->big_state->point_sprite_coords; +} + +static void +_cogl_pipeline_layer_add_vertex_snippet (CoglPipeline *pipeline, + int layer_index, + CoglSnippet *snippet) +{ + CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS; + CoglPipelineLayer *layer, *authority; + + /* Note: this will ensure that the layer exists, creating one if it + * doesn't already. + * + * Note: If the layer already existed it's possibly owned by another + * pipeline. If the layer is created then it will be owned by + * pipeline. */ + layer = _cogl_pipeline_get_layer (pipeline, layer_index); + + /* Now find the ancestor of the layer that is the authority for the + * state we want to change */ + authority = _cogl_pipeline_layer_get_authority (layer, change); + + layer = _cogl_pipeline_layer_pre_change_notify (pipeline, layer, change); + + _cogl_pipeline_snippet_list_add (&layer->big_state->vertex_snippets, + snippet); + + /* If we weren't previously the authority on this state then we need + * to extended our differences mask and so it's possible that some + * of our ancestry will now become redundant, so we aim to reparent + * ourselves if that's true... */ + if (layer != authority) + { + layer->differences |= change; + _cogl_pipeline_layer_prune_redundant_ancestry (layer); + } +} + +static void +_cogl_pipeline_layer_add_fragment_snippet (CoglPipeline *pipeline, + int layer_index, + CoglSnippet *snippet) +{ + CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS; + CoglPipelineLayer *layer, *authority; + + /* Note: this will ensure that the layer exists, creating one if it + * doesn't already. + * + * Note: If the layer already existed it's possibly owned by another + * pipeline. If the layer is created then it will be owned by + * pipeline. */ + layer = _cogl_pipeline_get_layer (pipeline, layer_index); + + /* Now find the ancestor of the layer that is the authority for the + * state we want to change */ + authority = _cogl_pipeline_layer_get_authority (layer, change); + + layer = _cogl_pipeline_layer_pre_change_notify (pipeline, layer, change); + + _cogl_pipeline_snippet_list_add (&layer->big_state->fragment_snippets, + snippet); + + /* If we weren't previously the authority on this state then we need + * to extended our differences mask and so it's possible that some + * of our ancestry will now become redundant, so we aim to reparent + * ourselves if that's true... */ + if (layer != authority) + { + layer->differences |= change; + _cogl_pipeline_layer_prune_redundant_ancestry (layer); + } +} + +void +cogl_pipeline_add_layer_snippet (CoglPipeline *pipeline, + int layer_index, + CoglSnippet *snippet) +{ + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + _COGL_RETURN_IF_FAIL (cogl_is_snippet (snippet)); + _COGL_RETURN_IF_FAIL (snippet->hook >= COGL_SNIPPET_FIRST_LAYER_HOOK); + + if (snippet->hook < COGL_SNIPPET_FIRST_LAYER_FRAGMENT_HOOK) + _cogl_pipeline_layer_add_vertex_snippet (pipeline, + layer_index, + snippet); + else + _cogl_pipeline_layer_add_fragment_snippet (pipeline, + layer_index, + snippet); +} + +CoglBool +_cogl_pipeline_layer_texture_type_equal (CoglPipelineLayer *authority0, + CoglPipelineLayer *authority1, + CoglPipelineEvalFlags flags) +{ + return authority0->texture_type == authority1->texture_type; +} + +CoglBool +_cogl_pipeline_layer_texture_data_equal (CoglPipelineLayer *authority0, + CoglPipelineLayer *authority1, + CoglPipelineEvalFlags flags) +{ + if (authority0->texture == NULL) + { + if (authority1->texture == NULL) + return (_cogl_pipeline_layer_get_texture_type (authority0) == + _cogl_pipeline_layer_get_texture_type (authority1)); + else + return FALSE; + } + else if (authority1->texture == NULL) + return FALSE; + else + { + GLuint gl_handle0, gl_handle1; + + cogl_texture_get_gl_texture (authority0->texture, &gl_handle0, NULL); + cogl_texture_get_gl_texture (authority1->texture, &gl_handle1, NULL); + + return gl_handle0 == gl_handle1; + } +} + +CoglBool +_cogl_pipeline_layer_combine_state_equal (CoglPipelineLayer *authority0, + CoglPipelineLayer *authority1) +{ + CoglPipelineLayerBigState *big_state0 = authority0->big_state; + CoglPipelineLayerBigState *big_state1 = authority1->big_state; + int n_args; + int i; + + if (big_state0->texture_combine_rgb_func != + big_state1->texture_combine_rgb_func) + return FALSE; + + if (big_state0->texture_combine_alpha_func != + big_state1->texture_combine_alpha_func) + return FALSE; + + n_args = + _cogl_get_n_args_for_combine_func (big_state0->texture_combine_rgb_func); + for (i = 0; i < n_args; i++) + { + if ((big_state0->texture_combine_rgb_src[i] != + big_state1->texture_combine_rgb_src[i]) || + (big_state0->texture_combine_rgb_op[i] != + big_state1->texture_combine_rgb_op[i])) + return FALSE; + } + + n_args = + _cogl_get_n_args_for_combine_func (big_state0->texture_combine_alpha_func); + for (i = 0; i < n_args; i++) + { + if ((big_state0->texture_combine_alpha_src[i] != + big_state1->texture_combine_alpha_src[i]) || + (big_state0->texture_combine_alpha_op[i] != + big_state1->texture_combine_alpha_op[i])) + return FALSE; + } + + return TRUE; +} + +CoglBool +_cogl_pipeline_layer_combine_constant_equal (CoglPipelineLayer *authority0, + CoglPipelineLayer *authority1) +{ + return memcmp (authority0->big_state->texture_combine_constant, + authority1->big_state->texture_combine_constant, + sizeof (float) * 4) == 0 ? TRUE : FALSE; +} + +CoglBool +_cogl_pipeline_layer_sampler_equal (CoglPipelineLayer *authority0, + CoglPipelineLayer *authority1) +{ + /* We compare the actual sampler objects rather than just the entry + pointers because two states with different values can lead to the + same state in GL terms when AUTOMATIC is used as a wrap mode */ + return (authority0->sampler_cache_entry->sampler_object == + authority1->sampler_cache_entry->sampler_object); +} + +CoglBool +_cogl_pipeline_layer_user_matrix_equal (CoglPipelineLayer *authority0, + CoglPipelineLayer *authority1) +{ + CoglPipelineLayerBigState *big_state0 = authority0->big_state; + CoglPipelineLayerBigState *big_state1 = authority1->big_state; + + if (!cogl_matrix_equal (&big_state0->matrix, &big_state1->matrix)) + return FALSE; + + return TRUE; +} + +CoglBool +_cogl_pipeline_layer_point_sprite_coords_equal (CoglPipelineLayer *authority0, + CoglPipelineLayer *authority1) +{ + CoglPipelineLayerBigState *big_state0 = authority0->big_state; + CoglPipelineLayerBigState *big_state1 = authority1->big_state; + + return big_state0->point_sprite_coords == big_state1->point_sprite_coords; +} + +CoglBool +_cogl_pipeline_layer_vertex_snippets_equal (CoglPipelineLayer *authority0, + CoglPipelineLayer *authority1) +{ + return _cogl_pipeline_snippet_list_equal (&authority0->big_state-> + vertex_snippets, + &authority1->big_state-> + vertex_snippets); +} + +CoglBool +_cogl_pipeline_layer_fragment_snippets_equal (CoglPipelineLayer *authority0, + CoglPipelineLayer *authority1) +{ + return _cogl_pipeline_snippet_list_equal (&authority0->big_state-> + fragment_snippets, + &authority1->big_state-> + fragment_snippets); +} + +static void +setup_texture_combine_state (CoglBlendStringStatement *statement, + CoglPipelineCombineFunc *texture_combine_func, + CoglPipelineCombineSource *texture_combine_src, + CoglPipelineCombineOp *texture_combine_op) +{ + int i; + + switch (statement->function->type) + { + case COGL_BLEND_STRING_FUNCTION_REPLACE: + *texture_combine_func = COGL_PIPELINE_COMBINE_FUNC_REPLACE; + break; + case COGL_BLEND_STRING_FUNCTION_MODULATE: + *texture_combine_func = COGL_PIPELINE_COMBINE_FUNC_MODULATE; + break; + case COGL_BLEND_STRING_FUNCTION_ADD: + *texture_combine_func = COGL_PIPELINE_COMBINE_FUNC_ADD; + break; + case COGL_BLEND_STRING_FUNCTION_ADD_SIGNED: + *texture_combine_func = COGL_PIPELINE_COMBINE_FUNC_ADD_SIGNED; + break; + case COGL_BLEND_STRING_FUNCTION_INTERPOLATE: + *texture_combine_func = COGL_PIPELINE_COMBINE_FUNC_INTERPOLATE; + break; + case COGL_BLEND_STRING_FUNCTION_SUBTRACT: + *texture_combine_func = COGL_PIPELINE_COMBINE_FUNC_SUBTRACT; + break; + case COGL_BLEND_STRING_FUNCTION_DOT3_RGB: + *texture_combine_func = COGL_PIPELINE_COMBINE_FUNC_DOT3_RGB; + break; + case COGL_BLEND_STRING_FUNCTION_DOT3_RGBA: + *texture_combine_func = COGL_PIPELINE_COMBINE_FUNC_DOT3_RGBA; + break; + } + + for (i = 0; i < statement->function->argc; i++) + { + CoglBlendStringArgument *arg = &statement->args[i]; + + switch (arg->source.info->type) + { + case COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT: + texture_combine_src[i] = COGL_PIPELINE_COMBINE_SOURCE_CONSTANT; + break; + case COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE: + texture_combine_src[i] = COGL_PIPELINE_COMBINE_SOURCE_TEXTURE; + break; + case COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE_N: + texture_combine_src[i] = + COGL_PIPELINE_COMBINE_SOURCE_TEXTURE0 + arg->source.texture; + break; + case COGL_BLEND_STRING_COLOR_SOURCE_PRIMARY: + texture_combine_src[i] = COGL_PIPELINE_COMBINE_SOURCE_PRIMARY_COLOR; + break; + case COGL_BLEND_STRING_COLOR_SOURCE_PREVIOUS: + texture_combine_src[i] = COGL_PIPELINE_COMBINE_SOURCE_PREVIOUS; + break; + default: + g_warning ("Unexpected texture combine source"); + texture_combine_src[i] = COGL_PIPELINE_COMBINE_SOURCE_TEXTURE; + } + + if (arg->source.mask == COGL_BLEND_STRING_CHANNEL_MASK_RGB) + { + if (statement->args[i].source.one_minus) + texture_combine_op[i] = + COGL_PIPELINE_COMBINE_OP_ONE_MINUS_SRC_COLOR; + else + texture_combine_op[i] = COGL_PIPELINE_COMBINE_OP_SRC_COLOR; + } + else + { + if (statement->args[i].source.one_minus) + texture_combine_op[i] = + COGL_PIPELINE_COMBINE_OP_ONE_MINUS_SRC_ALPHA; + else + texture_combine_op[i] = COGL_PIPELINE_COMBINE_OP_SRC_ALPHA; + } + } +} + +CoglBool +cogl_pipeline_set_layer_combine (CoglPipeline *pipeline, + int layer_index, + const char *combine_description, + CoglError **error) +{ + CoglPipelineLayerState state = COGL_PIPELINE_LAYER_STATE_COMBINE; + CoglPipelineLayer *authority; + CoglPipelineLayer *layer; + CoglBlendStringStatement statements[2]; + CoglBlendStringStatement split[2]; + CoglBlendStringStatement *rgb; + CoglBlendStringStatement *a; + int count; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), FALSE); + + /* Note: this will ensure that the layer exists, creating one if it + * doesn't already. + * + * Note: If the layer already existed it's possibly owned by another + * pipeline. If the layer is created then it will be owned by + * pipeline. */ + layer = _cogl_pipeline_get_layer (pipeline, layer_index); + + /* Now find the ancestor of the layer that is the authority for the + * state we want to change */ + authority = _cogl_pipeline_layer_get_authority (layer, state); + + count = + _cogl_blend_string_compile (combine_description, + COGL_BLEND_STRING_CONTEXT_TEXTURE_COMBINE, + statements, + 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]; + } + + /* FIXME: compare the new state with the current state! */ + + /* possibly flush primitives referencing the current state... */ + layer = _cogl_pipeline_layer_pre_change_notify (pipeline, layer, state); + + setup_texture_combine_state (rgb, + &layer->big_state->texture_combine_rgb_func, + layer->big_state->texture_combine_rgb_src, + layer->big_state->texture_combine_rgb_op); + + setup_texture_combine_state (a, + &layer->big_state->texture_combine_alpha_func, + layer->big_state->texture_combine_alpha_src, + layer->big_state->texture_combine_alpha_op); + + /* If the original layer we found is currently the authority on + * the state we are changing see if we can revert to one of our + * ancestors being the authority. */ + if (layer == authority && + _cogl_pipeline_layer_get_parent (authority) != NULL) + { + CoglPipelineLayer *parent = _cogl_pipeline_layer_get_parent (authority); + CoglPipelineLayer *old_authority = + _cogl_pipeline_layer_get_authority (parent, state); + + if (_cogl_pipeline_layer_combine_state_equal (authority, + old_authority)) + { + layer->differences &= ~state; + + g_assert (layer->owner == pipeline); + if (layer->differences == 0) + _cogl_pipeline_prune_empty_layer_difference (pipeline, + layer); + goto changed; + } + } + + /* If we weren't previously the authority on this state then we need + * to extended our differences mask and so it's possible that some + * of our ancestry will now become redundant, so we aim to reparent + * ourselves if that's true... */ + if (layer != authority) + { + layer->differences |= state; + _cogl_pipeline_layer_prune_redundant_ancestry (layer); + } + +changed: + + pipeline->dirty_real_blend_enable = TRUE; + return TRUE; +} + +void +cogl_pipeline_set_layer_combine_constant (CoglPipeline *pipeline, + int layer_index, + const CoglColor *constant_color) +{ + CoglPipelineLayerState state = COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT; + CoglPipelineLayer *layer; + CoglPipelineLayer *authority; + CoglPipelineLayer *new; + float color_as_floats[4]; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + /* Note: this will ensure that the layer exists, creating one if it + * doesn't already. + * + * Note: If the layer already existed it's possibly owned by another + * pipeline. If the layer is created then it will be owned by + * pipeline. */ + layer = _cogl_pipeline_get_layer (pipeline, layer_index); + + /* Now find the ancestor of the layer that is the authority for the + * state we want to change */ + authority = _cogl_pipeline_layer_get_authority (layer, state); + + color_as_floats[0] = cogl_color_get_red_float (constant_color); + color_as_floats[1] = cogl_color_get_green_float (constant_color); + color_as_floats[2] = cogl_color_get_blue_float (constant_color); + color_as_floats[3] = cogl_color_get_alpha_float (constant_color); + + if (memcmp (authority->big_state->texture_combine_constant, + color_as_floats, sizeof (float) * 4) == 0) + return; + + new = _cogl_pipeline_layer_pre_change_notify (pipeline, layer, state); + if (new != layer) + layer = new; + else + { + /* If the original layer we found is currently the authority on + * the state we are changing see if we can revert to one of our + * ancestors being the authority. */ + if (layer == authority && + _cogl_pipeline_layer_get_parent (authority) != NULL) + { + CoglPipelineLayer *parent = + _cogl_pipeline_layer_get_parent (authority); + CoglPipelineLayer *old_authority = + _cogl_pipeline_layer_get_authority (parent, state); + CoglPipelineLayerBigState *old_big_state = old_authority->big_state; + + if (memcmp (old_big_state->texture_combine_constant, + color_as_floats, sizeof (float) * 4) == 0) + { + layer->differences &= ~state; + + g_assert (layer->owner == pipeline); + if (layer->differences == 0) + _cogl_pipeline_prune_empty_layer_difference (pipeline, + layer); + goto changed; + } + } + } + + memcpy (layer->big_state->texture_combine_constant, + color_as_floats, + sizeof (color_as_floats)); + + /* If we weren't previously the authority on this state then we need + * to extended our differences mask and so it's possible that some + * of our ancestry will now become redundant, so we aim to reparent + * ourselves if that's true... */ + if (layer != authority) + { + layer->differences |= state; + _cogl_pipeline_layer_prune_redundant_ancestry (layer); + } + +changed: + + pipeline->dirty_real_blend_enable = TRUE; +} + +void +_cogl_pipeline_get_layer_combine_constant (CoglPipeline *pipeline, + int layer_index, + float *constant) +{ + CoglPipelineLayerState change = + COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT; + CoglPipelineLayer *layer; + CoglPipelineLayer *authority; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + /* Note: this will ensure that the layer exists, creating one if it + * doesn't already. + * + * Note: If the layer already existed it's possibly owned by another + * pipeline. If the layer is created then it will be owned by + * pipeline. */ + layer = _cogl_pipeline_get_layer (pipeline, layer_index); + /* FIXME: we shouldn't ever construct a layer in a getter function */ + + authority = _cogl_pipeline_layer_get_authority (layer, change); + memcpy (constant, authority->big_state->texture_combine_constant, + sizeof (float) * 4); +} + +/* We should probably make a public API version of this that has a + matrix out-param. For an internal API it's good to be able to avoid + copying the matrix */ +const CoglMatrix * +_cogl_pipeline_get_layer_matrix (CoglPipeline *pipeline, int layer_index) +{ + CoglPipelineLayerState change = + COGL_PIPELINE_LAYER_STATE_USER_MATRIX; + CoglPipelineLayer *layer; + CoglPipelineLayer *authority; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), NULL); + + layer = _cogl_pipeline_get_layer (pipeline, layer_index); + + authority = _cogl_pipeline_layer_get_authority (layer, change); + return &authority->big_state->matrix; +} + +void +cogl_pipeline_set_layer_matrix (CoglPipeline *pipeline, + int layer_index, + const CoglMatrix *matrix) +{ + CoglPipelineLayerState state = COGL_PIPELINE_LAYER_STATE_USER_MATRIX; + CoglPipelineLayer *layer; + CoglPipelineLayer *authority; + CoglPipelineLayer *new; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + /* Note: this will ensure that the layer exists, creating one if it + * doesn't already. + * + * Note: If the layer already existed it's possibly owned by another + * pipeline. If the layer is created then it will be owned by + * pipeline. */ + layer = _cogl_pipeline_get_layer (pipeline, layer_index); + + /* Now find the ancestor of the layer that is the authority for the + * state we want to change */ + authority = _cogl_pipeline_layer_get_authority (layer, state); + + if (cogl_matrix_equal (matrix, &authority->big_state->matrix)) + return; + + new = _cogl_pipeline_layer_pre_change_notify (pipeline, layer, state); + if (new != layer) + layer = new; + else + { + /* If the original layer we found is currently the authority on + * the state we are changing see if we can revert to one of our + * ancestors being the authority. */ + if (layer == authority && + _cogl_pipeline_layer_get_parent (authority) != NULL) + { + CoglPipelineLayer *parent = + _cogl_pipeline_layer_get_parent (authority); + CoglPipelineLayer *old_authority = + _cogl_pipeline_layer_get_authority (parent, state); + + if (cogl_matrix_equal (matrix, &old_authority->big_state->matrix)) + { + layer->differences &= ~state; + + g_assert (layer->owner == pipeline); + if (layer->differences == 0) + _cogl_pipeline_prune_empty_layer_difference (pipeline, + layer); + return; + } + } + } + + layer->big_state->matrix = *matrix; + + /* If we weren't previously the authority on this state then we need + * to extended our differences mask and so it's possible that some + * of our ancestry will now become redundant, so we aim to reparent + * ourselves if that's true... */ + if (layer != authority) + { + layer->differences |= state; + _cogl_pipeline_layer_prune_redundant_ancestry (layer); + } +} + +CoglTexture * +_cogl_pipeline_layer_get_texture (CoglPipelineLayer *layer) +{ + _COGL_RETURN_VAL_IF_FAIL (_cogl_is_pipeline_layer (layer), NULL); + + return _cogl_pipeline_layer_get_texture_real (layer); +} + +CoglBool +_cogl_pipeline_layer_has_user_matrix (CoglPipeline *pipeline, + int layer_index) +{ + CoglPipelineLayer *layer; + CoglPipelineLayer *authority; + + layer = _cogl_pipeline_get_layer (pipeline, layer_index); + + authority = + _cogl_pipeline_layer_get_authority (layer, + COGL_PIPELINE_LAYER_STATE_USER_MATRIX); + + /* If the authority is the default pipeline then no, otherwise yes */ + return _cogl_pipeline_layer_get_parent (authority) ? TRUE : FALSE; +} + +void +_cogl_pipeline_layer_get_filters (CoglPipelineLayer *layer, + CoglPipelineFilter *min_filter, + CoglPipelineFilter *mag_filter) +{ + CoglPipelineLayer *authority = + _cogl_pipeline_layer_get_authority (layer, + COGL_PIPELINE_LAYER_STATE_SAMPLER); + + *min_filter = authority->sampler_cache_entry->min_filter; + *mag_filter = authority->sampler_cache_entry->mag_filter; +} + +void +_cogl_pipeline_get_layer_filters (CoglPipeline *pipeline, + int layer_index, + CoglPipelineFilter *min_filter, + CoglPipelineFilter *mag_filter) +{ + CoglPipelineLayer *layer; + CoglPipelineLayer *authority; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + layer = _cogl_pipeline_get_layer (pipeline, layer_index); + + authority = + _cogl_pipeline_layer_get_authority (layer, + COGL_PIPELINE_LAYER_STATE_SAMPLER); + + *min_filter = authority->sampler_cache_entry->min_filter; + *mag_filter = authority->sampler_cache_entry->mag_filter; +} + +CoglPipelineFilter +cogl_pipeline_get_layer_min_filter (CoglPipeline *pipeline, + int layer_index) +{ + CoglPipelineFilter min_filter; + CoglPipelineFilter mag_filter; + + _cogl_pipeline_get_layer_filters (pipeline, layer_index, + &min_filter, &mag_filter); + return min_filter; +} + +CoglPipelineFilter +cogl_pipeline_get_layer_mag_filter (CoglPipeline *pipeline, + int layer_index) +{ + CoglPipelineFilter min_filter; + CoglPipelineFilter mag_filter; + + _cogl_pipeline_get_layer_filters (pipeline, layer_index, + &min_filter, &mag_filter); + return mag_filter; +} + +CoglPipelineFilter +_cogl_pipeline_layer_get_min_filter (CoglPipelineLayer *layer) +{ + CoglPipelineLayer *authority; + + _COGL_RETURN_VAL_IF_FAIL (_cogl_is_pipeline_layer (layer), 0); + + authority = + _cogl_pipeline_layer_get_authority (layer, + COGL_PIPELINE_LAYER_STATE_SAMPLER); + + return authority->sampler_cache_entry->min_filter; +} + +CoglPipelineFilter +_cogl_pipeline_layer_get_mag_filter (CoglPipelineLayer *layer) +{ + CoglPipelineLayer *authority; + + _COGL_RETURN_VAL_IF_FAIL (_cogl_is_pipeline_layer (layer), 0); + + authority = + _cogl_pipeline_layer_get_authority (layer, + COGL_PIPELINE_LAYER_STATE_SAMPLER); + + return authority->sampler_cache_entry->mag_filter; +} + +void +cogl_pipeline_set_layer_filters (CoglPipeline *pipeline, + int layer_index, + CoglPipelineFilter min_filter, + CoglPipelineFilter mag_filter) +{ + CoglPipelineLayerState state = COGL_PIPELINE_LAYER_STATE_SAMPLER; + CoglPipelineLayer *layer; + CoglPipelineLayer *authority; + const CoglSamplerCacheEntry *sampler_state; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + _COGL_RETURN_IF_FAIL (mag_filter == COGL_PIPELINE_FILTER_NEAREST || + mag_filter == COGL_PIPELINE_FILTER_LINEAR); + + /* Note: this will ensure that the layer exists, creating one if it + * doesn't already. + * + * Note: If the layer already existed it's possibly owned by another + * pipeline. If the layer is created then it will be owned by + * pipeline. */ + layer = _cogl_pipeline_get_layer (pipeline, layer_index); + + /* Now find the ancestor of the layer that is the authority for the + * state we want to change */ + authority = _cogl_pipeline_layer_get_authority (layer, state); + + sampler_state = + _cogl_sampler_cache_update_filters (ctx->sampler_cache, + authority->sampler_cache_entry, + min_filter, + mag_filter); + _cogl_pipeline_set_layer_sampler_state (pipeline, + layer, + authority, + sampler_state); +} + +const CoglSamplerCacheEntry * +_cogl_pipeline_layer_get_sampler_state (CoglPipelineLayer *layer) +{ + CoglPipelineLayer *authority; + + authority = + _cogl_pipeline_layer_get_authority (layer, + COGL_PIPELINE_LAYER_STATE_SAMPLER); + + return authority->sampler_cache_entry; +} + +void +_cogl_pipeline_layer_hash_unit_state (CoglPipelineLayer *authority, + CoglPipelineLayer **authorities, + CoglPipelineHashState *state) +{ + int unit = authority->unit_index; + state->hash = + _cogl_util_one_at_a_time_hash (state->hash, &unit, sizeof (unit)); +} + +void +_cogl_pipeline_layer_hash_texture_type_state (CoglPipelineLayer *authority, + CoglPipelineLayer **authorities, + CoglPipelineHashState *state) +{ + CoglTextureType texture_type = authority->texture_type; + + state->hash = _cogl_util_one_at_a_time_hash (state->hash, + &texture_type, + sizeof (texture_type)); +} + +void +_cogl_pipeline_layer_hash_texture_data_state (CoglPipelineLayer *authority, + CoglPipelineLayer **authorities, + CoglPipelineHashState *state) +{ + GLuint gl_handle; + + cogl_texture_get_gl_texture (authority->texture, &gl_handle, NULL); + + state->hash = + _cogl_util_one_at_a_time_hash (state->hash, &gl_handle, sizeof (gl_handle)); +} + +void +_cogl_pipeline_layer_hash_sampler_state (CoglPipelineLayer *authority, + CoglPipelineLayer **authorities, + CoglPipelineHashState *state) +{ + state->hash = + _cogl_util_one_at_a_time_hash (state->hash, + &authority->sampler_cache_entry, + sizeof (authority->sampler_cache_entry)); +} + +void +_cogl_pipeline_layer_hash_combine_state (CoglPipelineLayer *authority, + CoglPipelineLayer **authorities, + CoglPipelineHashState *state) +{ + unsigned int hash = state->hash; + CoglPipelineLayerBigState *b = authority->big_state; + int n_args; + int i; + + hash = _cogl_util_one_at_a_time_hash (hash, &b->texture_combine_rgb_func, + sizeof (b->texture_combine_rgb_func)); + n_args = _cogl_get_n_args_for_combine_func (b->texture_combine_rgb_func); + for (i = 0; i < n_args; i++) + { + hash = + _cogl_util_one_at_a_time_hash (hash, &b->texture_combine_rgb_src[i], + sizeof (b->texture_combine_rgb_src[i])); + hash = + _cogl_util_one_at_a_time_hash (hash, &b->texture_combine_rgb_op[i], + sizeof (b->texture_combine_rgb_op[i])); + } + + hash = _cogl_util_one_at_a_time_hash (hash, &b->texture_combine_alpha_func, + sizeof (b->texture_combine_alpha_func)); + n_args = _cogl_get_n_args_for_combine_func (b->texture_combine_alpha_func); + for (i = 0; i < n_args; i++) + { + hash = + _cogl_util_one_at_a_time_hash (hash, &b->texture_combine_alpha_src[i], + sizeof (b->texture_combine_alpha_src[i])); + hash = + _cogl_util_one_at_a_time_hash (hash, &b->texture_combine_alpha_op[i], + sizeof (b->texture_combine_alpha_op[i])); + } + + state->hash = hash; +} + +void +_cogl_pipeline_layer_hash_combine_constant_state (CoglPipelineLayer *authority, + CoglPipelineLayer **authorities, + CoglPipelineHashState *state) +{ + CoglPipelineLayerBigState *b = authority->big_state; + CoglBool need_hash = FALSE; + int n_args; + int i; + + /* XXX: If the user also asked to hash the ALPHA_FUNC_STATE then it + * would be nice if we could combine the n_args loops in this + * function and _cogl_pipeline_layer_hash_combine_state. + */ + + n_args = _cogl_get_n_args_for_combine_func (b->texture_combine_rgb_func); + for (i = 0; i < n_args; i++) + { + if (b->texture_combine_rgb_src[i] == + COGL_PIPELINE_COMBINE_SOURCE_CONSTANT) + { + /* XXX: should we be careful to only hash the alpha + * component in the COGL_PIPELINE_COMBINE_OP_SRC_ALPHA case? */ + need_hash = TRUE; + goto done; + } + } + + n_args = _cogl_get_n_args_for_combine_func (b->texture_combine_alpha_func); + for (i = 0; i < n_args; i++) + { + if (b->texture_combine_alpha_src[i] == + COGL_PIPELINE_COMBINE_SOURCE_CONSTANT) + { + /* XXX: should we be careful to only hash the alpha + * component in the COGL_PIPELINE_COMBINE_OP_SRC_ALPHA case? */ + need_hash = TRUE; + goto done; + } + } + +done: + if (need_hash) + { + float *constant = b->texture_combine_constant; + state->hash = _cogl_util_one_at_a_time_hash (state->hash, constant, + sizeof (float) * 4); + } +} + +void +_cogl_pipeline_layer_hash_user_matrix_state (CoglPipelineLayer *authority, + CoglPipelineLayer **authorities, + CoglPipelineHashState *state) +{ + CoglPipelineLayerBigState *big_state = authority->big_state; + state->hash = _cogl_util_one_at_a_time_hash (state->hash, &big_state->matrix, + sizeof (float) * 16); +} + +void +_cogl_pipeline_layer_hash_point_sprite_state (CoglPipelineLayer *authority, + CoglPipelineLayer **authorities, + CoglPipelineHashState *state) +{ + CoglPipelineLayerBigState *big_state = authority->big_state; + state->hash = + _cogl_util_one_at_a_time_hash (state->hash, &big_state->point_sprite_coords, + sizeof (big_state->point_sprite_coords)); +} + +void +_cogl_pipeline_layer_hash_vertex_snippets_state (CoglPipelineLayer *authority, + CoglPipelineLayer **authorities, + CoglPipelineHashState *state) +{ + _cogl_pipeline_snippet_list_hash (&authority->big_state->vertex_snippets, + &state->hash); +} + +void +_cogl_pipeline_layer_hash_fragment_snippets_state (CoglPipelineLayer *authority, + CoglPipelineLayer **authorities, + CoglPipelineHashState *state) +{ + _cogl_pipeline_snippet_list_hash (&authority->big_state->fragment_snippets, + &state->hash); +} diff --git a/cogl/cogl/cogl-pipeline-layer-state.h b/cogl/cogl/cogl-pipeline-layer-state.h new file mode 100644 index 0000000..96ae1b4 --- /dev/null +++ b/cogl/cogl/cogl-pipeline-layer-state.h @@ -0,0 +1,616 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_PIPELINE_LAYER_STATE_H__ +#define __COGL_PIPELINE_LAYER_STATE_H__ + +#include +#include +#include +#include + +COGL_BEGIN_DECLS + +/** + * CoglPipelineFilter: + * @COGL_PIPELINE_FILTER_NEAREST: Measuring in manhatten distance from the, + * current pixel center, use the nearest texture texel + * @COGL_PIPELINE_FILTER_LINEAR: Use the weighted average of the 4 texels + * nearest the current pixel center + * @COGL_PIPELINE_FILTER_NEAREST_MIPMAP_NEAREST: Select the mimap level whose + * texel size most closely matches the current pixel, and use the + * %COGL_PIPELINE_FILTER_NEAREST criterion + * @COGL_PIPELINE_FILTER_LINEAR_MIPMAP_NEAREST: Select the mimap level whose + * texel size most closely matches the current pixel, and use the + * %COGL_PIPELINE_FILTER_LINEAR criterion + * @COGL_PIPELINE_FILTER_NEAREST_MIPMAP_LINEAR: Select the two mimap levels + * whose texel size most closely matches the current pixel, use + * the %COGL_PIPELINE_FILTER_NEAREST criterion on each one and take + * their weighted average + * @COGL_PIPELINE_FILTER_LINEAR_MIPMAP_LINEAR: Select the two mimap levels + * whose texel size most closely matches the current pixel, use + * the %COGL_PIPELINE_FILTER_LINEAR criterion on each one and take + * their weighted average + * + * Texture filtering is used whenever the current pixel maps either to more + * than one texture element (texel) or less than one. These filter enums + * correspond to different strategies used to come up with a pixel color, by + * possibly referring to multiple neighbouring texels and taking a weighted + * average or simply using the nearest texel. + */ +typedef enum { + COGL_PIPELINE_FILTER_NEAREST = 0x2600, + COGL_PIPELINE_FILTER_LINEAR = 0x2601, + COGL_PIPELINE_FILTER_NEAREST_MIPMAP_NEAREST = 0x2700, + COGL_PIPELINE_FILTER_LINEAR_MIPMAP_NEAREST = 0x2701, + COGL_PIPELINE_FILTER_NEAREST_MIPMAP_LINEAR = 0x2702, + COGL_PIPELINE_FILTER_LINEAR_MIPMAP_LINEAR = 0x2703 +} CoglPipelineFilter; +/* NB: these values come from the equivalents in gl.h */ + +/** + * CoglPipelineWrapMode: + * @COGL_PIPELINE_WRAP_MODE_REPEAT: The texture will be repeated. This + * is useful for example to draw a tiled background. + * @COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE: The coordinates outside the + * range 0→1 will sample copies of the edge pixels of the + * texture. This is useful to avoid artifacts if only one copy of + * the texture is being rendered. + * @COGL_PIPELINE_WRAP_MODE_AUTOMATIC: Cogl will try to automatically + * decide which of the above two to use. For cogl_rectangle(), it + * will use repeat mode if any of the texture coordinates are + * outside the range 0→1, otherwise it will use clamp to edge. For + * cogl_polygon() it will always use repeat mode. For + * cogl_vertex_buffer_draw() it will use repeat mode except for + * layers that have point sprite coordinate generation enabled. This + * is the default value. + * + * The wrap mode specifies what happens when texture coordinates + * outside the range 0→1 are used. Note that if the filter mode is + * anything but %COGL_PIPELINE_FILTER_NEAREST then texels outside the + * range 0→1 might be used even when the coordinate is exactly 0 or 1 + * because OpenGL will try to sample neighbouring pixels. For example + * if you are trying to render the full texture then you may get + * artifacts around the edges when the pixels from the other side are + * merged in if the wrap mode is set to repeat. + * + * Since: 2.0 + */ +/* GL_ALWAYS is just used here as a value that is known not to clash + * with any valid GL wrap modes + * + * XXX: keep the values in sync with the CoglPipelineWrapModeInternal + * enum so no conversion is actually needed. + */ +typedef enum { + COGL_PIPELINE_WRAP_MODE_REPEAT = 0x2901, + COGL_PIPELINE_WRAP_MODE_MIRRORED_REPEAT = 0x8370, + COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE = 0x812F, + COGL_PIPELINE_WRAP_MODE_AUTOMATIC = 0x0207 /* GL_ALWAYS */ +} CoglPipelineWrapMode; +/* NB: these values come from the equivalents in gl.h */ + +/** + * cogl_pipeline_set_layer: + * @pipeline: A #CoglPipeline object + * @layer_index: the index of the layer + * @texture: a #CoglTexture for the layer object + * + * In addition to the standard OpenGL lighting model a Cogl pipeline may have + * one or more layers comprised of textures that can be blended together in + * order, with a number of different texture combine modes. This function + * defines a new texture layer. + * + * The index values of multiple layers do not have to be consecutive; it is + * only their relative order that is important. + * + * The @texture parameter can also be %NULL in which case the pipeline + * will use a default white texture. The type of the default texture + * will be the same as whatever texture was last used for the pipeline + * or %COGL_TEXTURE_TYPE_2D if none has been specified yet. To + * explicitly specify the type of default texture required, use + * cogl_pipeline_set_layer_null_texture() instead. + * + * In the future, we may define other types of pipeline layers, such + * as purely GLSL based layers. + * + * Since: 2.0 + * Stability: unstable + */ +void +cogl_pipeline_set_layer_texture (CoglPipeline *pipeline, + int layer_index, + CoglTexture *texture); + +/** + * cogl_pipeline_set_layer_null_texture: + * @pipeline: A #CoglPipeline + * @layer_index: The layer number to modify + * @texture_type: The type of the default texture to use + * + * Sets the texture for this layer to be the default texture for the + * given type. This is equivalent to calling + * cogl_pipeline_set_layer_texture() with %NULL for the texture + * argument except that you can also specify the type of default + * texture to use. The default texture is a 1x1 pixel white texture. + * + * This function is mostly useful if you want to create a base + * pipeline that you want to create multiple copies from using + * cogl_pipeline_copy(). In that case this function can be used to + * specify the texture type so that any pipeline copies can share the + * internal texture type state for efficiency. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_pipeline_set_layer_null_texture (CoglPipeline *pipeline, + int layer_index, + CoglTextureType texture_type); + +/** + * cogl_pipeline_get_layer_texture: + * @pipeline: A #CoglPipeline object + * @layer_index: the index of the layer + * + * Return value: (transfer none): the texture that was set for the + * given layer of the pipeline or %NULL if no texture was set. + * Stability: unstable + * Since: 1.10 + */ +CoglTexture * +cogl_pipeline_get_layer_texture (CoglPipeline *pipeline, + int layer_index); + +/** + * cogl_pipeline_remove_layer: + * @pipeline: A #CoglPipeline object + * @layer_index: Specifies the layer you want to remove + * + * This function removes a layer from your pipeline + * Since: 1.10 + * Stability: unstable + */ +void +cogl_pipeline_remove_layer (CoglPipeline *pipeline, + int layer_index); + +/** + * cogl_pipeline_set_layer_combine: + * @pipeline: A #CoglPipeline object + * @layer_index: Specifies the layer you want define a combine function for + * @blend_string: A Cogl blend string + * describing the desired texture combine function. + * @error: A #CoglError that may report parse errors or lack of GPU/driver + * support. May be %NULL, in which case a warning will be printed out if an + * error is encountered. + * + * If not already familiar; you can refer + * here for an overview of what blend + * strings are and there syntax. + * + * These are all the functions available for texture combining: + * + * REPLACE(arg0) = arg0 + * MODULATE(arg0, arg1) = arg0 x arg1 + * ADD(arg0, arg1) = arg0 + arg1 + * ADD_SIGNED(arg0, arg1) = arg0 + arg1 - 0.5 + * INTERPOLATE(arg0, arg1, arg2) = arg0 x arg2 + arg1 x (1 - arg2) + * SUBTRACT(arg0, arg1) = arg0 - arg1 + * + * + * DOT3_RGB(arg0, arg1) = 4 x ((arg0[R] - 0.5)) * (arg1[R] - 0.5) + + * (arg0[G] - 0.5)) * (arg1[G] - 0.5) + + * (arg0[B] - 0.5)) * (arg1[B] - 0.5)) + * + * + * + * + * DOT3_RGBA(arg0, arg1) = 4 x ((arg0[R] - 0.5)) * (arg1[R] - 0.5) + + * (arg0[G] - 0.5)) * (arg1[G] - 0.5) + + * (arg0[B] - 0.5)) * (arg1[B] - 0.5)) + * + * + * + * + * Refer to the + * color-source syntax for + * describing the arguments. The valid source names for texture combining + * are: + * + * + * TEXTURE + * Use the color from the current texture layer + * + * + * TEXTURE_0, TEXTURE_1, etc + * Use the color from the specified texture layer + * + * + * CONSTANT + * Use the color from the constant given with + * cogl_pipeline_set_layer_combine_constant() + * + * + * PRIMARY + * Use the color of the pipeline as set with + * cogl_pipeline_set_color() + * + * + * PREVIOUS + * Either use the texture color from the previous layer, or + * if this is layer 0, use the color of the pipeline as set with + * cogl_pipeline_set_color() + * + * + * + * + * Layer Combine Examples + * This is effectively what the default blending is: + * + * RGBA = MODULATE (PREVIOUS, TEXTURE) + * + * This could be used to cross-fade between two images, using + * the alpha component of a constant as the interpolator. The constant + * color is given by calling + * cogl_pipeline_set_layer_combine_constant(). + * + * RGBA = INTERPOLATE (PREVIOUS, TEXTURE, CONSTANT[A]) + * + * + * + * You can't give a multiplication factor for arguments as you can + * with blending. + * + * Return value: %TRUE if the blend string was successfully parsed, and the + * described texture combining is supported by the underlying driver and + * or hardware. On failure, %FALSE is returned and @error is set + * + * Since: 2.0 + * Stability: unstable + */ +CoglBool +cogl_pipeline_set_layer_combine (CoglPipeline *pipeline, + int layer_index, + const char *blend_string, + CoglError **error); + +/** + * cogl_pipeline_set_layer_combine_constant: + * @pipeline: A #CoglPipeline object + * @layer_index: Specifies the layer you want to specify a constant used + * for texture combining + * @constant: The constant color you want + * + * When you are using the 'CONSTANT' color source in a layer combine + * description then you can use this function to define its value. + * + * Since: 2.0 + * Stability: unstable + */ +void +cogl_pipeline_set_layer_combine_constant (CoglPipeline *pipeline, + int layer_index, + const CoglColor *constant); + +/** + * cogl_pipeline_set_layer_matrix: + * @pipeline: A #CoglPipeline object + * @layer_index: the index for the layer inside @pipeline + * @matrix: the transformation matrix for the layer + * + * This function lets you set a matrix that can be used to e.g. translate + * and rotate a single layer of a pipeline used to fill your geometry. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_pipeline_set_layer_matrix (CoglPipeline *pipeline, + int layer_index, + const CoglMatrix *matrix); + +/** + * cogl_pipeline_get_n_layers: + * @pipeline: A #CoglPipeline object + * + * Retrieves the number of layers defined for the given @pipeline + * + * Return value: the number of layers + * + * Since: 2.0 + * Stability: unstable + */ +int +cogl_pipeline_get_n_layers (CoglPipeline *pipeline); + +/** + * cogl_pipeline_set_layer_filters: + * @pipeline: A #CoglPipeline object + * @layer_index: the layer number to change. + * @min_filter: the filter used when scaling a texture down. + * @mag_filter: the filter used when magnifying a texture. + * + * Changes the decimation and interpolation filters used when a texture is + * drawn at other scales than 100%. + * + * It is an error to pass anything other than + * %COGL_PIPELINE_FILTER_NEAREST or %COGL_PIPELINE_FILTER_LINEAR as + * magnification filters since magnification doesn't ever need to + * reference values stored in the mipmap chain. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_pipeline_set_layer_filters (CoglPipeline *pipeline, + int layer_index, + CoglPipelineFilter min_filter, + CoglPipelineFilter mag_filter); + +/** + * cogl_pipeline_get_layer_min_filter: + * @pipeline: A #CoglPipeline object + * @layer_index: the layer number to change. + * + * Retrieves the currently set minification #CoglPipelineFilter set on + * the specified layer. The miniifcation filter determines how the + * layer should be sampled when down-scaled. + * + * The default filter is %COGL_PIPELINE_FILTER_LINEAR but this can be + * changed using cogl_pipeline_set_layer_filters(). + * + * Return value: The minification #CoglPipelineFilter for the + * specified layer. + * Since: 1.10 + * Stability: unstable + */ +CoglPipelineFilter +cogl_pipeline_get_layer_min_filter (CoglPipeline *pipeline, + int layer_index); + +/** + * cogl_pipeline_get_layer_mag_filter: + * @pipeline: A #CoglPipeline object + * @layer_index: the layer number to change. + * + * Retrieves the currently set magnification #CoglPipelineFilter set on + * the specified layer. The magnification filter determines how the + * layer should be sampled when up-scaled. + * + * The default filter is %COGL_PIPELINE_FILTER_LINEAR but this can be + * changed using cogl_pipeline_set_layer_filters(). + * + * Return value: The magnification #CoglPipelineFilter for the + * specified layer. + * Since: 1.10 + * Stability: unstable + */ +CoglPipelineFilter +cogl_pipeline_get_layer_mag_filter (CoglPipeline *pipeline, + int layer_index); + +/** + * cogl_pipeline_set_layer_point_sprite_coords_enabled: + * @pipeline: A #CoglPipeline object + * @layer_index: the layer number to change. + * @enable: whether to enable point sprite coord generation. + * @error: A return location for a CoglError, or NULL to ignore errors. + * + * When rendering points, if @enable is %TRUE then the texture + * coordinates for this layer will be replaced with coordinates that + * vary from 0.0 to 1.0 across the primitive. The top left of the + * point will have the coordinates 0.0,0.0 and the bottom right will + * have 1.0,1.0. If @enable is %FALSE then the coordinates will be + * fixed for the entire point. + * + * This function will only work if %COGL_FEATURE_ID_POINT_SPRITE is + * available. If the feature is not available then the function will + * return %FALSE and set @error. + * + * Return value: %TRUE if the function succeeds, %FALSE otherwise. + * Since: 2.0 + * Stability: unstable + */ +CoglBool +cogl_pipeline_set_layer_point_sprite_coords_enabled (CoglPipeline *pipeline, + int layer_index, + CoglBool enable, + CoglError **error); + +/** + * cogl_pipeline_get_layer_point_sprite_coords_enabled: + * @pipeline: A #CoglPipeline object + * @layer_index: the layer number to check. + * + * Gets whether point sprite coordinate generation is enabled for this + * texture layer. + * + * Return value: whether the texture coordinates will be replaced with + * point sprite coordinates. + * + * Since: 2.0 + * Stability: unstable + */ +CoglBool +cogl_pipeline_get_layer_point_sprite_coords_enabled (CoglPipeline *pipeline, + int layer_index); + +/** + * cogl_pipeline_get_layer_wrap_mode_s: + * @pipeline: A #CoglPipeline object + * @layer_index: the layer number to change. + * + * Returns the wrap mode for the 's' coordinate of texture lookups on this + * layer. + * + * Return value: the wrap mode for the 's' coordinate of texture lookups on + * this layer. + * + * Since: 1.6 + * Stability: unstable + */ +CoglPipelineWrapMode +cogl_pipeline_get_layer_wrap_mode_s (CoglPipeline *pipeline, + int layer_index); + +/** + * cogl_pipeline_set_layer_wrap_mode_s: + * @pipeline: A #CoglPipeline object + * @layer_index: the layer number to change. + * @mode: the new wrap mode + * + * Sets the wrap mode for the 's' coordinate of texture lookups on this layer. + * + * Since: 2.0 + * Stability: unstable + */ +void +cogl_pipeline_set_layer_wrap_mode_s (CoglPipeline *pipeline, + int layer_index, + CoglPipelineWrapMode mode); + +/** + * cogl_pipeline_get_layer_wrap_mode_t: + * @pipeline: A #CoglPipeline object + * @layer_index: the layer number to change. + * + * Returns the wrap mode for the 't' coordinate of texture lookups on this + * layer. + * + * Return value: the wrap mode for the 't' coordinate of texture lookups on + * this layer. + * + * Since: 1.6 + * Stability: unstable + */ +CoglPipelineWrapMode +cogl_pipeline_get_layer_wrap_mode_t (CoglPipeline *pipeline, + int layer_index); + + +/** + * cogl_pipeline_set_layer_wrap_mode_t: + * @pipeline: A #CoglPipeline object + * @layer_index: the layer number to change. + * @mode: the new wrap mode + * + * Sets the wrap mode for the 't' coordinate of texture lookups on this layer. + * + * Since: 2.0 + * Stability: unstable + */ +void +cogl_pipeline_set_layer_wrap_mode_t (CoglPipeline *pipeline, + int layer_index, + CoglPipelineWrapMode mode); + +/** + * cogl_pipeline_get_layer_wrap_mode_p: + * @pipeline: A #CoglPipeline object + * @layer_index: the layer number to change. + * + * Returns the wrap mode for the 'p' coordinate of texture lookups on this + * layer. + * + * Return value: the wrap mode for the 'p' coordinate of texture lookups on + * this layer. + * + * Since: 1.6 + * Stability: unstable + */ +CoglPipelineWrapMode +cogl_pipeline_get_layer_wrap_mode_p (CoglPipeline *pipeline, + int layer_index); + +/** + * cogl_pipeline_set_layer_wrap_mode_p: + * @pipeline: A #CoglPipeline object + * @layer_index: the layer number to change. + * @mode: the new wrap mode + * + * Sets the wrap mode for the 'p' coordinate of texture lookups on + * this layer. 'p' is the third coordinate. + * + * Since: 2.0 + * Stability: unstable + */ +void +cogl_pipeline_set_layer_wrap_mode_p (CoglPipeline *pipeline, + int layer_index, + CoglPipelineWrapMode mode); + +/** + * cogl_pipeline_set_layer_wrap_mode: + * @pipeline: A #CoglPipeline object + * @layer_index: the layer number to change. + * @mode: the new wrap mode + * + * Sets the wrap mode for all three coordinates of texture lookups on + * this layer. This is equivalent to calling + * cogl_pipeline_set_layer_wrap_mode_s(), + * cogl_pipeline_set_layer_wrap_mode_t() and + * cogl_pipeline_set_layer_wrap_mode_p() separately. + * + * Since: 2.0 + * Stability: unstable + */ +void +cogl_pipeline_set_layer_wrap_mode (CoglPipeline *pipeline, + int layer_index, + CoglPipelineWrapMode mode); + +/** + * cogl_pipeline_add_layer_snippet: + * @pipeline: A #CoglPipeline + * @layer: The layer to hook the snippet to + * @snippet: A #CoglSnippet + * + * Adds a shader snippet that will hook on to the given layer of the + * pipeline. The exact part of the pipeline that the snippet wraps + * around depends on the hook that is given to + * cogl_snippet_new(). Note that some hooks can't be used with a layer + * and need to be added with cogl_pipeline_add_snippet() instead. + * + * Since: 1.10 + * Stability: Unstable + */ +void +cogl_pipeline_add_layer_snippet (CoglPipeline *pipeline, + int layer, + CoglSnippet *snippet); + +COGL_END_DECLS + +#endif /* __COGL_PIPELINE_LAYER_STATE_H__ */ diff --git a/cogl/cogl/cogl-pipeline-layer.c b/cogl/cogl/cogl-pipeline-layer.c new file mode 100644 index 0000000..c7a3d5e --- /dev/null +++ b/cogl/cogl/cogl-pipeline-layer.c @@ -0,0 +1,942 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-util.h" +#include "cogl-context-private.h" +#include "cogl-texture-private.h" + +#include "cogl-pipeline.h" +#include "cogl-pipeline-layer-private.h" +#include "cogl-pipeline-layer-state-private.h" +#include "cogl-pipeline-layer-state.h" +#include "cogl-node-private.h" +#include "cogl-pipeline-opengl-private.h" +#include "cogl-context-private.h" +#include "cogl-texture-private.h" + +#include + +static void +_cogl_pipeline_layer_free (CoglPipelineLayer *layer); + +/* This type was made deprecated before the cogl_is_pipeline_layer + function was ever exposed in the public headers so there's no need + to make the cogl_is_pipeline_layer function public. We use INTERNAL + so that the cogl_is_* function won't get defined */ +COGL_OBJECT_INTERNAL_DEFINE (PipelineLayer, pipeline_layer); + + +CoglPipelineLayer * +_cogl_pipeline_layer_get_authority (CoglPipelineLayer *layer, + unsigned long difference) +{ + CoglPipelineLayer *authority = layer; + while (!(authority->differences & difference)) + authority = _cogl_pipeline_layer_get_parent (authority); + return authority; +} + +int +_cogl_pipeline_layer_get_unit_index (CoglPipelineLayer *layer) +{ + CoglPipelineLayer *authority = + _cogl_pipeline_layer_get_authority (layer, COGL_PIPELINE_LAYER_STATE_UNIT); + return authority->unit_index; +} + +CoglBool +_cogl_pipeline_layer_has_alpha (CoglPipelineLayer *layer) +{ + CoglPipelineLayer *combine_authority = + _cogl_pipeline_layer_get_authority (layer, + COGL_PIPELINE_LAYER_STATE_COMBINE); + CoglPipelineLayerBigState *big_state = combine_authority->big_state; + CoglPipelineLayer *tex_authority; + CoglPipelineLayer *snippets_authority; + + /* has_alpha maintains the alpha status for the GL_PREVIOUS layer */ + + /* For anything but the default texture combine we currently just + * assume it may result in an alpha value < 1 + * + * FIXME: we could do better than this. */ + if (big_state->texture_combine_alpha_func != + COGL_PIPELINE_COMBINE_FUNC_MODULATE || + big_state->texture_combine_alpha_src[0] != + COGL_PIPELINE_COMBINE_SOURCE_PREVIOUS || + big_state->texture_combine_alpha_op[0] != + COGL_PIPELINE_COMBINE_OP_SRC_ALPHA || + big_state->texture_combine_alpha_src[1] != + COGL_PIPELINE_COMBINE_SOURCE_TEXTURE || + big_state->texture_combine_alpha_op[1] != + COGL_PIPELINE_COMBINE_OP_SRC_ALPHA) + { + return TRUE; + } + + /* NB: A layer may have a combine mode set on it but not yet + * have an associated texture which would mean we'd fallback + * to the default texture which doesn't have an alpha component + */ + tex_authority = + _cogl_pipeline_layer_get_authority (layer, + COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA); + if (tex_authority->texture && + _cogl_texture_get_format (tex_authority->texture) & COGL_A_BIT) + { + return TRUE; + } + + /* All bets are off if the layer contains any snippets */ + snippets_authority = _cogl_pipeline_layer_get_authority + (layer, COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS); + if (snippets_authority->big_state->vertex_snippets.entries != NULL) + return TRUE; + snippets_authority = _cogl_pipeline_layer_get_authority + (layer, COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS); + if (snippets_authority->big_state->fragment_snippets.entries != NULL) + return TRUE; + + return FALSE; +} + +unsigned int +_cogl_get_n_args_for_combine_func (CoglPipelineCombineFunc func) +{ + switch (func) + { + case COGL_PIPELINE_COMBINE_FUNC_REPLACE: + return 1; + case COGL_PIPELINE_COMBINE_FUNC_MODULATE: + case COGL_PIPELINE_COMBINE_FUNC_ADD: + case COGL_PIPELINE_COMBINE_FUNC_ADD_SIGNED: + case COGL_PIPELINE_COMBINE_FUNC_SUBTRACT: + case COGL_PIPELINE_COMBINE_FUNC_DOT3_RGB: + case COGL_PIPELINE_COMBINE_FUNC_DOT3_RGBA: + return 2; + case COGL_PIPELINE_COMBINE_FUNC_INTERPOLATE: + return 3; + } + return 0; +} + +void +_cogl_pipeline_layer_copy_differences (CoglPipelineLayer *dest, + CoglPipelineLayer *src, + unsigned long differences) +{ + CoglPipelineLayerBigState *big_dest, *big_src; + + if ((differences & COGL_PIPELINE_LAYER_STATE_NEEDS_BIG_STATE) && + !dest->has_big_state) + { + dest->big_state = g_slice_new (CoglPipelineLayerBigState); + dest->has_big_state = TRUE; + } + + big_dest = dest->big_state; + big_src = src->big_state; + + dest->differences |= differences; + + while (differences) + { + int index = _cogl_util_ffs (differences) - 1; + + differences &= ~(1 << index); + + /* This convoluted switch statement is just here so that we'll + * get a warning if a new state is added without handling it + * here */ + switch (index) + { + case COGL_PIPELINE_LAYER_STATE_COUNT: + case COGL_PIPELINE_LAYER_STATE_UNIT_INDEX: + g_warn_if_reached (); + break; + + case COGL_PIPELINE_LAYER_STATE_TEXTURE_TYPE_INDEX: + dest->texture_type = src->texture_type; + break; + + case COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA_INDEX: + dest->texture = src->texture; + if (dest->texture) + cogl_object_ref (dest->texture); + break; + + case COGL_PIPELINE_LAYER_STATE_SAMPLER_INDEX: + dest->sampler_cache_entry = src->sampler_cache_entry; + break; + + case COGL_PIPELINE_LAYER_STATE_COMBINE_INDEX: + { + CoglPipelineCombineFunc func; + int n_args, i; + + func = big_src->texture_combine_rgb_func; + big_dest->texture_combine_rgb_func = func; + n_args = _cogl_get_n_args_for_combine_func (func); + for (i = 0; i < n_args; i++) + { + big_dest->texture_combine_rgb_src[i] = + big_src->texture_combine_rgb_src[i]; + big_dest->texture_combine_rgb_op[i] = + big_src->texture_combine_rgb_op[i]; + } + + func = big_src->texture_combine_alpha_func; + big_dest->texture_combine_alpha_func = func; + n_args = _cogl_get_n_args_for_combine_func (func); + for (i = 0; i < n_args; i++) + { + big_dest->texture_combine_alpha_src[i] = + big_src->texture_combine_alpha_src[i]; + big_dest->texture_combine_alpha_op[i] = + big_src->texture_combine_alpha_op[i]; + } + } + break; + + case COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT_INDEX: + memcpy (big_dest->texture_combine_constant, + big_src->texture_combine_constant, + sizeof (big_dest->texture_combine_constant)); + break; + + case COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS_INDEX: + big_dest->point_sprite_coords = big_src->point_sprite_coords; + break; + + case COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS_INDEX: + _cogl_pipeline_snippet_list_copy (&big_dest->vertex_snippets, + &big_src->vertex_snippets); + break; + + case COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS_INDEX: + _cogl_pipeline_snippet_list_copy (&big_dest->fragment_snippets, + &big_src->fragment_snippets); + break; + } + } +} + +static void +_cogl_pipeline_layer_init_multi_property_sparse_state ( + CoglPipelineLayer *layer, + CoglPipelineLayerState change) +{ + CoglPipelineLayer *authority; + + /* Nothing to initialize in these cases since they are all comprised + * of one member which we expect to immediately be overwritten. */ + if (!(change & COGL_PIPELINE_LAYER_STATE_MULTI_PROPERTY)) + return; + + authority = _cogl_pipeline_layer_get_authority (layer, change); + + switch (change) + { + /* XXX: avoid using a default: label so we get a warning if we + * don't explicitly handle a newly defined state-group here. */ + case COGL_PIPELINE_LAYER_STATE_UNIT: + case COGL_PIPELINE_LAYER_STATE_TEXTURE_TYPE: + case COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA: + case COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS: + case COGL_PIPELINE_LAYER_STATE_USER_MATRIX: + case COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT: + case COGL_PIPELINE_LAYER_STATE_SAMPLER: + g_return_if_reached (); + + /* XXX: technically we could probably even consider these as + * single property state-groups from the pov that currently the + * corresponding property setters always update all of the values + * at the same time. */ + case COGL_PIPELINE_LAYER_STATE_COMBINE: + { + int n_args; + int i; + CoglPipelineLayerBigState *src_big_state = authority->big_state; + CoglPipelineLayerBigState *dest_big_state = layer->big_state; + GLint func = src_big_state->texture_combine_rgb_func; + + dest_big_state->texture_combine_rgb_func = func; + n_args = _cogl_get_n_args_for_combine_func (func); + for (i = 0; i < n_args; i++) + { + dest_big_state->texture_combine_rgb_src[i] = + src_big_state->texture_combine_rgb_src[i]; + dest_big_state->texture_combine_rgb_op[i] = + src_big_state->texture_combine_rgb_op[i]; + } + + func = src_big_state->texture_combine_alpha_func; + dest_big_state->texture_combine_alpha_func = func; + n_args = _cogl_get_n_args_for_combine_func (func); + for (i = 0; i < n_args; i++) + { + dest_big_state->texture_combine_alpha_src[i] = + src_big_state->texture_combine_alpha_src[i]; + dest_big_state->texture_combine_alpha_op[i] = + src_big_state->texture_combine_alpha_op[i]; + } + break; + } + case COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS: + _cogl_pipeline_snippet_list_copy (&layer->big_state->vertex_snippets, + &authority->big_state-> + vertex_snippets); + break; + case COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS: + _cogl_pipeline_snippet_list_copy (&layer->big_state->fragment_snippets, + &authority->big_state-> + fragment_snippets); + break; + } +} + +/* NB: If a layer has descendants we can't modify the layer + * NB: If the layer is owned and the owner has descendants we can't + * modify the layer. + * + * This function will allocate a new derived layer if you are trying + * to change the state of a layer with dependants (as described above) + * so you must always check the return value. + * + * If a new layer is returned it will be owned by required_owner. + * (NB: a layer is always modified with respect to a pipeline - the + * "required_owner") + * + * required_owner can only by NULL for new, currently unowned layers + * with no dependants. + */ +CoglPipelineLayer * +_cogl_pipeline_layer_pre_change_notify (CoglPipeline *required_owner, + CoglPipelineLayer *layer, + CoglPipelineLayerState change) +{ + CoglTextureUnit *unit; + + /* Identify the case where the layer is new with no owner or + * dependants and so we don't need to do anything. */ + if (_cogl_list_empty (&COGL_NODE (layer)->children) && + layer->owner == NULL) + goto init_layer_state; + + /* We only allow a NULL required_owner for new layers */ + _COGL_RETURN_VAL_IF_FAIL (required_owner != NULL, layer); + + /* Chain up: + * A modification of a layer is indirectly also a modification of + * its owner so first make sure to flush the journal of any + * references to the current owner state and if necessary perform + * a copy-on-write for the required_owner if it has dependants. + */ + _cogl_pipeline_pre_change_notify (required_owner, + COGL_PIPELINE_STATE_LAYERS, + NULL, + TRUE); + + /* Unlike pipelines; layers are simply considered immutable once + * they have dependants - either direct children, or another + * pipeline as an owner. + */ + if (!_cogl_list_empty (&COGL_NODE (layer)->children) || + layer->owner != required_owner) + { + CoglPipelineLayer *new = _cogl_pipeline_layer_copy (layer); + if (layer->owner == required_owner) + _cogl_pipeline_remove_layer_difference (required_owner, layer, FALSE); + _cogl_pipeline_add_layer_difference (required_owner, new, FALSE); + cogl_object_unref (new); + layer = new; + goto init_layer_state; + } + + /* Note: At this point we know there is only one pipeline dependant on + * this layer (required_owner), and there are no other layers + * dependant on this layer so it's ok to modify it. */ + + /* NB: Although layers can have private state associated with them + * by multiple backends we know that a layer can't be *changed* if + * it has multiple dependants so if we reach here we know we only + * have a single owner and can only be associated with a single + * backend that needs to be notified of the layer change... + */ + if (required_owner->progend != COGL_PIPELINE_PROGEND_UNDEFINED) + { + const CoglPipelineProgend *progend = + _cogl_pipeline_progends[required_owner->progend]; + const CoglPipelineFragend *fragend = + _cogl_pipeline_fragends[progend->fragend]; + const CoglPipelineVertend *vertend = + _cogl_pipeline_vertends[progend->vertend]; + + if (fragend->layer_pre_change_notify) + fragend->layer_pre_change_notify (required_owner, layer, change); + if (vertend->layer_pre_change_notify) + vertend->layer_pre_change_notify (required_owner, layer, change); + if (progend->layer_pre_change_notify) + progend->layer_pre_change_notify (required_owner, layer, change); + } + + /* If the layer being changed is the same as the last layer we + * flushed to the corresponding texture unit then we keep a track of + * the changes so we can try to minimize redundant OpenGL calls if + * the same layer is flushed again. + */ + unit = _cogl_get_texture_unit (_cogl_pipeline_layer_get_unit_index (layer)); + if (unit->layer == layer) + unit->layer_changes_since_flush |= change; + +init_layer_state: + + if (required_owner) + required_owner->age++; + + if (change & COGL_PIPELINE_LAYER_STATE_NEEDS_BIG_STATE && + !layer->has_big_state) + { + layer->big_state = g_slice_new (CoglPipelineLayerBigState); + layer->has_big_state = TRUE; + } + + /* Note: conceptually we have just been notified that a single + * property value is about to change, but since some state-groups + * contain multiple properties and 'layer' is about to take over + * being the authority for the property's corresponding state-group + * we need to maintain the integrity of the other property values + * too. + * + * To ensure this we handle multi-property state-groups by copying + * all the values from the old-authority to the new... + * + * We don't have to worry about non-sparse property groups since + * we never take over being an authority for such properties so + * they automatically maintain integrity. + */ + if (change & COGL_PIPELINE_LAYER_STATE_ALL_SPARSE && + !(layer->differences & change)) + { + _cogl_pipeline_layer_init_multi_property_sparse_state (layer, change); + layer->differences |= change; + } + + return layer; +} + +static void +_cogl_pipeline_layer_unparent (CoglNode *layer) +{ + /* Chain up */ + _cogl_pipeline_node_unparent_real (layer); +} + +static void +_cogl_pipeline_layer_set_parent (CoglPipelineLayer *layer, + CoglPipelineLayer *parent) +{ + /* Chain up */ + _cogl_pipeline_node_set_parent_real (COGL_NODE (layer), + COGL_NODE (parent), + _cogl_pipeline_layer_unparent, + TRUE); +} + +CoglPipelineLayer * +_cogl_pipeline_layer_copy (CoglPipelineLayer *src) +{ + CoglPipelineLayer *layer = g_slice_new (CoglPipelineLayer); + + _cogl_pipeline_node_init (COGL_NODE (layer)); + + layer->owner = NULL; + layer->index = src->index; + layer->differences = 0; + layer->has_big_state = FALSE; + + _cogl_pipeline_layer_set_parent (layer, src); + + return _cogl_pipeline_layer_object_new (layer); +} + +/* XXX: This is duplicated logic; the same as for + * _cogl_pipeline_prune_redundant_ancestry it would be nice to find a + * way to consolidate these functions! */ +void +_cogl_pipeline_layer_prune_redundant_ancestry (CoglPipelineLayer *layer) +{ + CoglPipelineLayer *new_parent = _cogl_pipeline_layer_get_parent (layer); + + /* walk up past ancestors that are now redundant and potentially + * reparent the layer. */ + while (_cogl_pipeline_layer_get_parent (new_parent) && + (new_parent->differences | layer->differences) == + layer->differences) + new_parent = _cogl_pipeline_layer_get_parent (new_parent); + + _cogl_pipeline_layer_set_parent (layer, new_parent); +} + +/* Determine the mask of differences between two layers. + * + * XXX: If layers and pipelines could both be cast to a common Tree + * type of some kind then we could have a unified + * compare_differences() function. + */ +unsigned long +_cogl_pipeline_layer_compare_differences (CoglPipelineLayer *layer0, + CoglPipelineLayer *layer1) +{ + GSList *head0 = NULL; + GSList *head1 = NULL; + CoglPipelineLayer *node0; + CoglPipelineLayer *node1; + int len0 = 0; + int len1 = 0; + int count; + GSList *common_ancestor0; + GSList *common_ancestor1; + unsigned long layers_difference = 0; + + /* Algorithm: + * + * 1) Walk the ancestors of each layer to the root node, adding a + * pointer to each ancester node to two linked lists + * + * 2) Compare the lists to find the nodes where they start to + * differ marking the common_ancestor node for each list. + * + * 3) For each list now iterate starting after the common_ancestor + * nodes ORing each nodes ->difference mask into the final + * differences mask. + */ + + for (node0 = layer0; node0; node0 = _cogl_pipeline_layer_get_parent (node0)) + { + GSList *link = alloca (sizeof (GSList)); + link->next = head0; + link->data = node0; + head0 = link; + len0++; + } + for (node1 = layer1; node1; node1 = _cogl_pipeline_layer_get_parent (node1)) + { + GSList *link = alloca (sizeof (GSList)); + link->next = head1; + link->data = node1; + head1 = link; + len1++; + } + + /* NB: There's no point looking at the head entries since we know both layers + * must have the same default layer as their root node. */ + common_ancestor0 = head0; + common_ancestor1 = head1; + head0 = head0->next; + head1 = head1->next; + count = MIN (len0, len1) - 1; + while (count--) + { + if (head0->data != head1->data) + break; + common_ancestor0 = head0; + common_ancestor1 = head1; + head0 = head0->next; + head1 = head1->next; + } + + for (head0 = common_ancestor0->next; head0; head0 = head0->next) + { + node0 = head0->data; + layers_difference |= node0->differences; + } + for (head1 = common_ancestor1->next; head1; head1 = head1->next) + { + node1 = head1->data; + layers_difference |= node1->differences; + } + + return layers_difference; +} + +static CoglBool +layer_state_equal (CoglPipelineLayerStateIndex state_index, + CoglPipelineLayer **authorities0, + CoglPipelineLayer **authorities1, + CoglPipelineLayerStateComparitor comparitor) +{ + return comparitor (authorities0[state_index], authorities1[state_index]); +} + +void +_cogl_pipeline_layer_resolve_authorities (CoglPipelineLayer *layer, + unsigned long differences, + CoglPipelineLayer **authorities) +{ + unsigned long remaining = differences; + CoglPipelineLayer *authority = layer; + + do + { + unsigned long found = authority->differences & remaining; + int i; + + if (found == 0) + continue; + + for (i = 0; TRUE; i++) + { + unsigned long state = (1L< found) + break; + } + + remaining &= ~found; + if (remaining == 0) + return; + } + while ((authority = _cogl_pipeline_layer_get_parent (authority))); + + g_assert (remaining == 0); +} + +CoglBool +_cogl_pipeline_layer_equal (CoglPipelineLayer *layer0, + CoglPipelineLayer *layer1, + unsigned long differences_mask, + CoglPipelineEvalFlags flags) +{ + unsigned long layers_difference; + CoglPipelineLayer *authorities0[COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT]; + CoglPipelineLayer *authorities1[COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT]; + + if (layer0 == layer1) + return TRUE; + + layers_difference = + _cogl_pipeline_layer_compare_differences (layer0, layer1); + + /* Only compare the sparse state groups requested by the caller... */ + layers_difference &= differences_mask; + + _cogl_pipeline_layer_resolve_authorities (layer0, + layers_difference, + authorities0); + _cogl_pipeline_layer_resolve_authorities (layer1, + layers_difference, + authorities1); + + if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE_TYPE) + { + CoglPipelineLayerStateIndex state_index = + COGL_PIPELINE_LAYER_STATE_TEXTURE_TYPE_INDEX; + if (!_cogl_pipeline_layer_texture_type_equal (authorities0[state_index], + authorities1[state_index], + flags)) + return FALSE; + } + + if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA) + { + CoglPipelineLayerStateIndex state_index = + COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA_INDEX; + if (!_cogl_pipeline_layer_texture_data_equal (authorities0[state_index], + authorities1[state_index], + flags)) + return FALSE; + } + + if (layers_difference & COGL_PIPELINE_LAYER_STATE_COMBINE && + !layer_state_equal (COGL_PIPELINE_LAYER_STATE_COMBINE_INDEX, + authorities0, authorities1, + _cogl_pipeline_layer_combine_state_equal)) + return FALSE; + + if (layers_difference & COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT && + !layer_state_equal (COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT_INDEX, + authorities0, authorities1, + _cogl_pipeline_layer_combine_constant_equal)) + return FALSE; + + if (layers_difference & COGL_PIPELINE_LAYER_STATE_SAMPLER && + !layer_state_equal (COGL_PIPELINE_LAYER_STATE_SAMPLER_INDEX, + authorities0, authorities1, + _cogl_pipeline_layer_sampler_equal)) + return FALSE; + + if (layers_difference & COGL_PIPELINE_LAYER_STATE_USER_MATRIX && + !layer_state_equal (COGL_PIPELINE_LAYER_STATE_USER_MATRIX_INDEX, + authorities0, authorities1, + _cogl_pipeline_layer_user_matrix_equal)) + return FALSE; + + if (layers_difference & COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS && + !layer_state_equal (COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS_INDEX, + authorities0, authorities1, + _cogl_pipeline_layer_point_sprite_coords_equal)) + return FALSE; + + if (layers_difference & COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS && + !layer_state_equal (COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS_INDEX, + authorities0, authorities1, + _cogl_pipeline_layer_vertex_snippets_equal)) + return FALSE; + + if (layers_difference & COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS && + !layer_state_equal (COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS_INDEX, + authorities0, authorities1, + _cogl_pipeline_layer_fragment_snippets_equal)) + return FALSE; + + return TRUE; +} + +static void +_cogl_pipeline_layer_free (CoglPipelineLayer *layer) +{ + _cogl_pipeline_layer_unparent (COGL_NODE (layer)); + + if (layer->differences & COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA && + layer->texture != NULL) + cogl_object_unref (layer->texture); + + if (layer->differences & COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS) + _cogl_pipeline_snippet_list_free (&layer->big_state->vertex_snippets); + + if (layer->differences & COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS) + _cogl_pipeline_snippet_list_free (&layer->big_state->fragment_snippets); + + if (layer->differences & COGL_PIPELINE_LAYER_STATE_NEEDS_BIG_STATE) + g_slice_free (CoglPipelineLayerBigState, layer->big_state); + + g_slice_free (CoglPipelineLayer, layer); +} + +void +_cogl_pipeline_init_default_layers (void) +{ + CoglPipelineLayer *layer = g_slice_new0 (CoglPipelineLayer); + CoglPipelineLayerBigState *big_state = + g_slice_new0 (CoglPipelineLayerBigState); + CoglPipelineLayer *new; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + _cogl_pipeline_node_init (COGL_NODE (layer)); + + layer->index = 0; + + layer->differences = COGL_PIPELINE_LAYER_STATE_ALL_SPARSE; + + layer->unit_index = 0; + + layer->texture = NULL; + layer->texture_type = COGL_TEXTURE_TYPE_2D; + + layer->sampler_cache_entry = + _cogl_sampler_cache_get_default_entry (ctx->sampler_cache); + + layer->big_state = big_state; + layer->has_big_state = TRUE; + + /* Choose the same default combine mode as OpenGL: + * RGBA = MODULATE(PREVIOUS[RGBA],TEXTURE[RGBA]) */ + big_state->texture_combine_rgb_func = + COGL_PIPELINE_COMBINE_FUNC_MODULATE; + big_state->texture_combine_rgb_src[0] = + COGL_PIPELINE_COMBINE_SOURCE_PREVIOUS; + big_state->texture_combine_rgb_src[1] = + COGL_PIPELINE_COMBINE_SOURCE_TEXTURE; + big_state->texture_combine_rgb_op[0] = + COGL_PIPELINE_COMBINE_OP_SRC_COLOR; + big_state->texture_combine_rgb_op[1] = + COGL_PIPELINE_COMBINE_OP_SRC_COLOR; + big_state->texture_combine_alpha_func = + COGL_PIPELINE_COMBINE_FUNC_MODULATE; + big_state->texture_combine_alpha_src[0] = + COGL_PIPELINE_COMBINE_SOURCE_PREVIOUS; + big_state->texture_combine_alpha_src[1] = + COGL_PIPELINE_COMBINE_SOURCE_TEXTURE; + big_state->texture_combine_alpha_op[0] = + COGL_PIPELINE_COMBINE_OP_SRC_ALPHA; + big_state->texture_combine_alpha_op[1] = + COGL_PIPELINE_COMBINE_OP_SRC_ALPHA; + + big_state->point_sprite_coords = FALSE; + + cogl_matrix_init_identity (&big_state->matrix); + + ctx->default_layer_0 = _cogl_pipeline_layer_object_new (layer); + + /* TODO: we should make default_layer_n comprise of two + * descendants of default_layer_0: + * - the first descendant should change the texture combine + * to what we expect is most commonly used for multitexturing + * - the second should revert the above change. + * + * why? the documentation for how a new layer is initialized + * doesn't say that layers > 0 have different defaults so unless + * we change the documentation we can't use different defaults, + * but if the user does what we expect and changes the + * texture combine then we can revert the authority to the + * first descendant which means we can maximize the number + * of layers with a common ancestor. + * + * The main problem will be that we'll need to disable the + * optimizations for flattening the ancestry when we make + * the second descendant which reverts the state. + */ + ctx->default_layer_n = _cogl_pipeline_layer_copy (layer); + new = _cogl_pipeline_set_layer_unit (NULL, ctx->default_layer_n, 1); + g_assert (new == ctx->default_layer_n); + /* Since we passed a newly allocated layer we don't expect that + * _set_layer_unit() will have to allocate *another* layer. */ + + /* Finally we create a dummy dependant for ->default_layer_n which + * effectively ensures that ->default_layer_n and ->default_layer_0 + * remain immutable. + */ + ctx->dummy_layer_dependant = + _cogl_pipeline_layer_copy (ctx->default_layer_n); +} + +void +_cogl_pipeline_layer_pre_paint (CoglPipelineLayer *layer) +{ + CoglPipelineLayer *texture_authority; + + texture_authority = + _cogl_pipeline_layer_get_authority (layer, + COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA); + + if (texture_authority->texture != NULL) + { + CoglTexturePrePaintFlags flags = 0; + CoglPipelineFilter min_filter; + CoglPipelineFilter mag_filter; + + _cogl_pipeline_layer_get_filters (layer, &min_filter, &mag_filter); + + if (min_filter == COGL_PIPELINE_FILTER_NEAREST_MIPMAP_NEAREST + || min_filter == COGL_PIPELINE_FILTER_LINEAR_MIPMAP_NEAREST + || min_filter == COGL_PIPELINE_FILTER_NEAREST_MIPMAP_LINEAR + || min_filter == COGL_PIPELINE_FILTER_LINEAR_MIPMAP_LINEAR) + flags |= COGL_TEXTURE_NEEDS_MIPMAP; + + _cogl_texture_pre_paint (texture_authority->texture, flags); + } +} + +/* Determines if we need to handle the RGB and A texture combining + * separately or is the same function used for both channel masks and + * with the same arguments... + */ +CoglBool +_cogl_pipeline_layer_needs_combine_separate + (CoglPipelineLayer *combine_authority) +{ + CoglPipelineLayerBigState *big_state = combine_authority->big_state; + int n_args; + int i; + + if (big_state->texture_combine_rgb_func != + big_state->texture_combine_alpha_func) + return TRUE; + + n_args = _cogl_get_n_args_for_combine_func (big_state->texture_combine_rgb_func); + + for (i = 0; i < n_args; i++) + { + if (big_state->texture_combine_rgb_src[i] != + big_state->texture_combine_alpha_src[i]) + return TRUE; + + /* + * We can allow some variation of the source operands without + * needing a separation... + * + * "A = REPLACE (CONSTANT[A])" + either of the following... + * "RGB = REPLACE (CONSTANT[RGB])" + * "RGB = REPLACE (CONSTANT[A])" + * + * can be combined as: + * "RGBA = REPLACE (CONSTANT)" or + * "RGBA = REPLACE (CONSTANT[A])" or + * + * And "A = REPLACE (1-CONSTANT[A])" + either of the following... + * "RGB = REPLACE (1-CONSTANT)" or + * "RGB = REPLACE (1-CONSTANT[A])" + * + * can be combined as: + * "RGBA = REPLACE (1-CONSTANT)" or + * "RGBA = REPLACE (1-CONSTANT[A])" + */ + switch (big_state->texture_combine_alpha_op[i]) + { + case GL_SRC_ALPHA: + switch (big_state->texture_combine_rgb_op[i]) + { + case GL_SRC_COLOR: + case GL_SRC_ALPHA: + break; + default: + return FALSE; + } + break; + case GL_ONE_MINUS_SRC_ALPHA: + switch (big_state->texture_combine_rgb_op[i]) + { + case GL_ONE_MINUS_SRC_COLOR: + case GL_ONE_MINUS_SRC_ALPHA: + break; + default: + return FALSE; + } + break; + default: + return FALSE; /* impossible */ + } + } + + return FALSE; +} + + diff --git a/cogl/cogl/cogl-pipeline-private.h b/cogl/cogl/cogl-pipeline-private.h new file mode 100644 index 0000000..845fdd8 --- /dev/null +++ b/cogl/cogl/cogl-pipeline-private.h @@ -0,0 +1,998 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009,2010,2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_PIPELINE_PRIVATE_H +#define __COGL_PIPELINE_PRIVATE_H + +#include "cogl-node-private.h" +#include "cogl-pipeline-layer-private.h" +#include "cogl-pipeline.h" +#include "cogl-matrix.h" +#include "cogl-object-private.h" +#include "cogl-profile.h" +#include "cogl-list.h" +#include "cogl-boxed-value.h" +#include "cogl-pipeline-snippet-private.h" +#include "cogl-pipeline-state.h" +#include "cogl-framebuffer.h" +#include "cogl-bitmask.h" + +#include + +#ifdef HAVE_COGL_GL + +#define COGL_PIPELINE_PROGEND_FIXED_ARBFP 0 +#define COGL_PIPELINE_PROGEND_FIXED 1 +#define COGL_PIPELINE_PROGEND_GLSL 2 +#define COGL_PIPELINE_N_PROGENDS 3 + +#define COGL_PIPELINE_VERTEND_FIXED 0 +#define COGL_PIPELINE_VERTEND_GLSL 1 +#define COGL_PIPELINE_N_VERTENDS 2 + +#define COGL_PIPELINE_FRAGEND_ARBFP 0 +#define COGL_PIPELINE_FRAGEND_FIXED 1 +#define COGL_PIPELINE_FRAGEND_GLSL 2 +#define COGL_PIPELINE_N_FRAGENDS 3 + +#else /* HAVE_COGL_GL */ + +#ifdef HAVE_COGL_GLES2 + +#define COGL_PIPELINE_PROGEND_GLSL 0 +#define COGL_PIPELINE_VERTEND_GLSL 0 +#define COGL_PIPELINE_FRAGEND_GLSL 0 + +#ifdef HAVE_COGL_GLES +#define COGL_PIPELINE_PROGEND_FIXED 1 +#define COGL_PIPELINE_VERTEND_FIXED 1 +#define COGL_PIPELINE_FRAGEND_FIXED 1 + +#define COGL_PIPELINE_N_PROGENDS 2 +#define COGL_PIPELINE_N_VERTENDS 2 +#define COGL_PIPELINE_N_FRAGENDS 2 +#else +#define COGL_PIPELINE_N_PROGENDS 1 +#define COGL_PIPELINE_N_VERTENDS 1 +#define COGL_PIPELINE_N_FRAGENDS 1 +#endif + +#else /* HAVE_COGL_GLES2 */ + +#ifdef HAVE_COGL_GLES +#define COGL_PIPELINE_PROGEND_FIXED 0 +#define COGL_PIPELINE_VERTEND_FIXED 0 +#define COGL_PIPELINE_FRAGEND_FIXED 0 +#define COGL_PIPELINE_N_PROGENDS 1 +#define COGL_PIPELINE_N_VERTENDS 1 +#define COGL_PIPELINE_N_FRAGENDS 1 +#else +#error No drivers defined +#endif + +#endif /* HAVE_COGL_GLES2 */ + +#endif /* HAVE_COGL_GL */ + +#define COGL_PIPELINE_PROGEND_DEFAULT 0 +#define COGL_PIPELINE_PROGEND_UNDEFINED 3 + +/* XXX: should I rename these as + * COGL_PIPELINE_STATE_INDEX_XYZ... ? + */ +typedef enum +{ + /* sparse state */ + COGL_PIPELINE_STATE_COLOR_INDEX, + COGL_PIPELINE_STATE_BLEND_ENABLE_INDEX, + COGL_PIPELINE_STATE_LAYERS_INDEX, + COGL_PIPELINE_STATE_LIGHTING_INDEX, + COGL_PIPELINE_STATE_ALPHA_FUNC_INDEX, + COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE_INDEX, + COGL_PIPELINE_STATE_BLEND_INDEX, + COGL_PIPELINE_STATE_USER_SHADER_INDEX, + COGL_PIPELINE_STATE_DEPTH_INDEX, + COGL_PIPELINE_STATE_FOG_INDEX, + COGL_PIPELINE_STATE_NON_ZERO_POINT_SIZE_INDEX, + COGL_PIPELINE_STATE_POINT_SIZE_INDEX, + COGL_PIPELINE_STATE_PER_VERTEX_POINT_SIZE_INDEX, + COGL_PIPELINE_STATE_LOGIC_OPS_INDEX, + COGL_PIPELINE_STATE_CULL_FACE_INDEX, + COGL_PIPELINE_STATE_UNIFORMS_INDEX, + COGL_PIPELINE_STATE_VERTEX_SNIPPETS_INDEX, + COGL_PIPELINE_STATE_FRAGMENT_SNIPPETS_INDEX, + + /* non-sparse */ + COGL_PIPELINE_STATE_REAL_BLEND_ENABLE_INDEX, + + COGL_PIPELINE_STATE_COUNT +} CoglPipelineStateIndex; + +#define COGL_PIPELINE_STATE_SPARSE_COUNT (COGL_PIPELINE_STATE_COUNT - 1) + +/* Used in pipeline->differences masks and for notifying pipeline + * state changes. + * + * XXX: If you add or remove state groups here you may need to update + * some of the state masks following this enum too! + * + * FIXME: perhaps it would be better to rename this enum to + * CoglPipelineStateGroup to better convey the fact that a single enum + * here can map to multiple properties. + */ +typedef enum _CoglPipelineState +{ + COGL_PIPELINE_STATE_COLOR = + 1L<big_state. + */ + + /* Layers represent their state in a tree structure where some of + * the state relating to a given pipeline or layer may actually be + * owned by one if is ancestors in the tree. We have a common data + * type to track the tree heirachy so we can share code... */ + CoglNode _parent; + + /* When weak pipelines are destroyed the user is notified via this + * callback */ + CoglPipelineDestroyCallback destroy_callback; + + /* When notifying that a weak pipeline has been destroyed this + * private data is passed to the above callback */ + void *destroy_data; + + /* We need to track if a pipeline is referenced in the journal + * because we can't allow modification to these pipelines without + * flushing the journal first */ + unsigned int journal_ref_count; + + /* A mask of which sparse state groups are different in this + * pipeline in comparison to its parent. */ + unsigned int differences; + + /* Whenever a pipeline is modified we increment the age. There's no + * guarantee that it won't wrap but it can nevertheless be a + * convenient mechanism to determine when a pipeline has been + * changed to you can invalidate some some associated cache that + * depends on the old state. */ + unsigned int age; + + /* This is the primary color of the pipeline. + * + * This is a sparse property, ref COGL_PIPELINE_STATE_COLOR */ + CoglColor color; + + /* A pipeline may be made up with multiple layers used to combine + * textures together. + * + * This is sparse state, ref COGL_PIPELINE_STATE_LAYERS */ + unsigned int n_layers; + GList *layer_differences; + + /* As a basic way to reduce memory usage we divide the pipeline + * state into two groups; the minimal state modified in 90% of + * all pipelines and the rest, so that the second group can + * be allocated dynamically when required... */ + CoglPipelineBigState *big_state; + +#ifdef COGL_DEBUG_ENABLED + /* For debugging purposes it's possible to associate a static const + * string with a pipeline which can be an aid when trying to trace + * where the pipeline originates from */ + const char *static_breadcrumb; +#endif + + /* Cached state... */ + + /* A cached, complete list of the layers this pipeline depends + * on sorted by layer->unit_index. */ + CoglPipelineLayer **layers_cache; + /* To avoid a separate ->layers_cache allocation for common + * pipelines with only a few layers... */ + CoglPipelineLayer *short_layers_cache[3]; + + /* The deprecated cogl_pipeline_get_layers() API returns a + * const GList of layers, which we track here... */ + GList *deprecated_get_layers_list; + + /* XXX: consider adding an authorities cache to speed up sparse + * property value lookups: + * CoglPipeline *authorities_cache[COGL_PIPELINE_N_SPARSE_PROPERTIES]; + * and corresponding authorities_cache_dirty:1 bitfield + */ + + /* bitfields */ + + /* Weak pipelines don't count as dependants on their parents which + * means that the parent pipeline can be modified without + * considering how the modifications may affect the weak pipeline. + */ + unsigned int is_weak:1; + + /* Determines if pipeline->big_state is valid */ + unsigned int has_big_state:1; + + /* By default blending is enabled automatically depending on the + * unlit color, the lighting colors or the texture format. The user + * can override this to explicitly enable or disable blending. + * + * This is a sparse property */ + unsigned int blend_enable:3; + + /* There are many factors that can determine if we need to enable + * blending, this holds our final decision */ + unsigned int real_blend_enable:1; + + /* Since the code for deciding if blending really needs to be + * enabled for a particular pipeline is quite expensive we update + * the real_blend_enable flag lazily when flushing a pipeline if + * this dirty flag has been set. */ + unsigned int dirty_real_blend_enable:1; + + /* Whenever a pipeline is flushed we keep track of whether the + * pipeline was used with a color attribute where we don't know + * whether the colors are opaque. The real_blend_enable state + * depends on this, and must be updated whenever this changes (even + * if dirty_real_blend_enable isn't set) */ + unsigned int unknown_color_alpha:1; + + unsigned int layers_cache_dirty:1; + unsigned int deprecated_get_layers_list_dirty:1; + +#ifdef COGL_DEBUG_ENABLED + /* For debugging purposes it's possible to associate a static const + * string with a pipeline which can be an aid when trying to trace + * where the pipeline originates from */ + unsigned int has_static_breadcrumb:1; +#endif + + /* There are multiple fragment and vertex processing backends for + * CoglPipeline, glsl, arbfp and fixed that are bundled under a + * "progend". This identifies the backend being used for the + * pipeline. */ + unsigned int progend:3; +}; + +typedef struct _CoglPipelineFragend +{ + void (*start) (CoglPipeline *pipeline, + int n_layers, + unsigned long pipelines_difference); + CoglBool (*add_layer) (CoglPipeline *pipeline, + CoglPipelineLayer *layer, + unsigned long layers_difference); + CoglBool (*passthrough) (CoglPipeline *pipeline); + CoglBool (*end) (CoglPipeline *pipeline, + unsigned long pipelines_difference); + + void (*pipeline_pre_change_notify) (CoglPipeline *pipeline, + CoglPipelineState change, + const CoglColor *new_color); + void (*pipeline_set_parent_notify) (CoglPipeline *pipeline); + void (*layer_pre_change_notify) (CoglPipeline *owner, + CoglPipelineLayer *layer, + CoglPipelineLayerState change); +} CoglPipelineFragend; + +typedef struct _CoglPipelineVertend +{ + void (*start) (CoglPipeline *pipeline, + int n_layers, + unsigned long pipelines_difference); + CoglBool (*add_layer) (CoglPipeline *pipeline, + CoglPipelineLayer *layer, + unsigned long layers_difference, + CoglFramebuffer *framebuffer); + CoglBool (*end) (CoglPipeline *pipeline, + unsigned long pipelines_difference); + + void (*pipeline_pre_change_notify) (CoglPipeline *pipeline, + CoglPipelineState change, + const CoglColor *new_color); + void (*layer_pre_change_notify) (CoglPipeline *owner, + CoglPipelineLayer *layer, + CoglPipelineLayerState change); +} CoglPipelineVertend; + +typedef struct +{ + int vertend; + int fragend; + CoglBool (*start) (CoglPipeline *pipeline); + void (*end) (CoglPipeline *pipeline, + unsigned long pipelines_difference); + void (*pipeline_pre_change_notify) (CoglPipeline *pipeline, + CoglPipelineState change, + const CoglColor *new_color); + void (*layer_pre_change_notify) (CoglPipeline *owner, + CoglPipelineLayer *layer, + CoglPipelineLayerState change); + /* This is called after all of the other functions whenever the + pipeline is flushed, even if the pipeline hasn't changed since + the last flush */ + void (* pre_paint) (CoglPipeline *pipeline, CoglFramebuffer *framebuffer); +} CoglPipelineProgend; + +typedef enum +{ + COGL_PIPELINE_PROGRAM_TYPE_GLSL = 1, + COGL_PIPELINE_PROGRAM_TYPE_ARBFP, + COGL_PIPELINE_PROGRAM_TYPE_FIXED +} CoglPipelineProgramType; + +extern const CoglPipelineFragend * +_cogl_pipeline_fragends[COGL_PIPELINE_N_FRAGENDS]; +extern const CoglPipelineVertend * +_cogl_pipeline_vertends[COGL_PIPELINE_N_VERTENDS]; +extern const CoglPipelineProgend * +_cogl_pipeline_progends[]; + +void +_cogl_pipeline_init_default_pipeline (void); + +static inline CoglPipeline * +_cogl_pipeline_get_parent (CoglPipeline *pipeline) +{ + CoglNode *parent_node = COGL_NODE (pipeline)->parent; + return COGL_PIPELINE (parent_node); +} + +static inline CoglPipeline * +_cogl_pipeline_get_authority (CoglPipeline *pipeline, + unsigned long difference) +{ + CoglPipeline *authority = pipeline; + while (!(authority->differences & difference)) + authority = _cogl_pipeline_get_parent (authority); + return authority; +} + +typedef CoglBool (*CoglPipelineStateComparitor) (CoglPipeline *authority0, + CoglPipeline *authority1); + +void +_cogl_pipeline_update_authority (CoglPipeline *pipeline, + CoglPipeline *authority, + CoglPipelineState state, + CoglPipelineStateComparitor comparitor); + +void +_cogl_pipeline_pre_change_notify (CoglPipeline *pipeline, + CoglPipelineState change, + const CoglColor *new_color, + CoglBool from_layer_change); + +void +_cogl_pipeline_prune_redundant_ancestry (CoglPipeline *pipeline); + +void +_cogl_pipeline_update_real_blend_enable (CoglPipeline *pipeline, + CoglBool unknown_color_alpha); + +typedef enum +{ + COGL_PIPELINE_GET_LAYER_NO_CREATE = 1<<0 +} CoglPipelineGetLayerFlags; + +CoglPipelineLayer * +_cogl_pipeline_get_layer_with_flags (CoglPipeline *pipeline, + int layer_index, + CoglPipelineGetLayerFlags flags); + +#define _cogl_pipeline_get_layer(p, l) \ + _cogl_pipeline_get_layer_with_flags (p, l, 0) + +CoglBool +_cogl_is_pipeline_layer (void *object); + +void +_cogl_pipeline_prune_empty_layer_difference (CoglPipeline *layers_authority, + CoglPipelineLayer *layer); + +/* + * SECTION:cogl-pipeline-internals + * @short_description: Functions for creating custom primitives that make use + * of Cogl pipelines for filling. + * + * Normally you shouldn't need to use this API directly, but if you need to + * developing a custom/specialised primitive - probably using raw OpenGL - then + * this API aims to expose enough of the pipeline internals to support being + * able to fill your geometry according to a given Cogl pipeline. + */ + +CoglBool +_cogl_pipeline_get_real_blend_enabled (CoglPipeline *pipeline); + +/* + * Calls the pre_paint method on the layer texture if there is + * one. This will determine whether mipmaps are needed based on the + * filter settings. + */ +void +_cogl_pipeline_pre_paint_for_layer (CoglPipeline *pipeline, + int layer_id); + +/* + * CoglPipelineFlushFlag: + * @COGL_PIPELINE_FLUSH_FALLBACK_MASK: The fallback_layers member is set to + * a uint32_t mask of the layers that can't be supported with the user + * supplied texture and need to be replaced with fallback textures. (1 = + * fallback, and the least significant bit = layer 0) + * @COGL_PIPELINE_FLUSH_DISABLE_MASK: The disable_layers member is set to + * a uint32_t mask of the layers that you want to completly disable + * texturing for (1 = fallback, and the least significant bit = layer 0) + * @COGL_PIPELINE_FLUSH_LAYER0_OVERRIDE: The layer0_override_texture member is + * set to a GLuint OpenGL texture name to override the texture used for + * layer 0 of the pipeline. This is intended for dealing with sliced + * textures where you will need to point to each of the texture slices in + * turn when drawing your geometry. Passing a value of 0 is the same as + * not passing the option at all. + * @COGL_PIPELINE_FLUSH_SKIP_GL_COLOR: When flushing the GL state for the + * pipeline don't call glColor. + */ +typedef enum _CoglPipelineFlushFlag +{ + COGL_PIPELINE_FLUSH_FALLBACK_MASK = 1L<<0, + COGL_PIPELINE_FLUSH_DISABLE_MASK = 1L<<1, + COGL_PIPELINE_FLUSH_LAYER0_OVERRIDE = 1L<<2, + COGL_PIPELINE_FLUSH_SKIP_GL_COLOR = 1L<<3 +} CoglPipelineFlushFlag; + +/* + * CoglPipelineFlushOptions: + * + */ +typedef struct _CoglPipelineFlushOptions +{ + CoglPipelineFlushFlag flags; + + uint32_t fallback_layers; + uint32_t disable_layers; + CoglTexture *layer0_override_texture; +} CoglPipelineFlushOptions; + +void +_cogl_use_fragment_program (GLuint gl_program, CoglPipelineProgramType type); + +void +_cogl_use_vertex_program (GLuint gl_program, CoglPipelineProgramType type); + +unsigned int +_cogl_get_n_args_for_combine_func (CoglPipelineCombineFunc func); + +/* + * _cogl_pipeline_weak_copy: + * @pipeline: A #CoglPipeline object + * @callback: A callback to notify when your weak pipeline is destroyed + * @user_data: Private data to pass to your given callback. + * + * Returns a weak copy of the given source @pipeline. Unlike a normal + * copy no internal reference is taken on the source @pipeline and you + * can expect that later modifications of the source pipeline (or in + * fact any other pipeline) can result in the weak pipeline being + * destroyed. + * + * To understand this better its good to know a bit about the internal + * design of #CoglPipeline... + * + * Internally #CoglPipelines are represented as a graph of + * property diff's, where each node is a diff of properties that gets + * applied on top of its parent. Copying a pipeline creates an empty + * diff and a child->parent relationship between the empty diff and + * the source @pipeline, parent. + * + * Because of this internal graph design a single #CoglPipeline may + * indirectly depend on a chain of ancestors to fully define all of + * its properties. Because a node depends on its ancestors it normally + * owns a reference to its parent to stop it from being freed. Also if + * you try to modify a pipeline with children we internally use a + * copy-on-write mechanism to ensure that you don't indirectly change + * the properties those children. + * + * Weak pipelines avoid the use of copy-on-write to preserve the + * integrity of weak dependants and instead weak dependants are + * simply destroyed allowing the parent to be modified directly. Also + * because weak pipelines don't own a reference to their parent they + * won't stop the source @pipeline from being freed when the user + * releases their reference on it. + * + * Because weak pipelines don't own a reference on their parent they + * are the recommended mechanism for creating derived pipelines that you + * want to cache as a private property of the original pipeline + * because they won't result in a circular dependency. + * + * An example use case: + * + * Consider for example you are implementing a custom primitive that is + * not compatible with certain source pipelines. To handle this you + * implement a validation stage that given an arbitrary pipeline as + * input will create a derived pipeline that is suitable for drawing + * your primitive. + * + * Because you don't want to have to repeat this validation every time + * the same incompatible pipeline is given as input you want to cache + * the result as a private property of the original pipeline. If the + * derived pipeline were created using cogl_pipeline_copy that would + * create a circular dependency so the original pipeline can never be + * freed. + * + * If you instead create a weak copy you won't stop the original pipeline + * from being freed if it's no longer needed, and you will instead simply + * be notified that your weak pipeline has been destroyed. + * + * This is the recommended coding pattern for validating an input + * pipeline and caching a derived result: + * |[ + * static CoglUserDataKey _cogl_my_cache_key; + * + * typedef struct { + * CoglPipeline *validated_source; + * } MyValidatedMaterialCache; + * + * static void + * destroy_cache_cb (CoglObject *object, void *user_data) + * { + * g_slice_free (MyValidatedMaterialCache, user_data); + * } + * + * static void + * invalidate_cache_cb (CoglPipeline *destroyed, void *user_data) + * { + * MyValidatedMaterialCache *cache = user_data; + * cogl_object_unref (cache->validated_source); + * cache->validated_source = NULL; + * } + * + * static CoglPipeline * + * get_validated_pipeline (CoglPipeline *source) + * { + * MyValidatedMaterialCache *cache = + * cogl_object_get_user_data (COGL_OBJECT (source), + * &_cogl_my_cache_key); + * if (G_UNLIKELY (cache == NULL)) + * { + * cache = g_slice_new (MyValidatedMaterialCache); + * cogl_object_set_user_data (COGL_OBJECT (source), + * &_cogl_my_cache_key, + * cache, destroy_cache_cb); + * cache->validated_source = source; + * } + * + * if (G_UNLIKELY (cache->validated_source == NULL)) + * { + * cache->validated_source = source; + * + * / * Start validating source... * / + * + * / * If you find you need to change something... * / + * if (cache->validated_source == source) + * cache->validated_source = + * cogl_pipeline_weak_copy (source, + * invalidate_cache_cb, + * cache); + * + * / * Modify cache->validated_source * / + * } + * + * return cache->validated_source; + * } + * ]| + */ +CoglPipeline * +_cogl_pipeline_weak_copy (CoglPipeline *pipeline, + CoglPipelineDestroyCallback callback, + void *user_data); + +void +_cogl_pipeline_set_progend (CoglPipeline *pipeline, int progend); + +CoglPipeline * +_cogl_pipeline_get_parent (CoglPipeline *pipeline); + +void +_cogl_pipeline_get_colorubv (CoglPipeline *pipeline, + uint8_t *color); + +/* XXX: At some point it could be good for this to accept a mask of + * the state groups we are interested in comparing since we can + * probably use that information in a number situations to reduce + * the work we do. */ +unsigned long +_cogl_pipeline_compare_differences (CoglPipeline *pipeline0, + CoglPipeline *pipeline1); + +CoglBool +_cogl_pipeline_equal (CoglPipeline *pipeline0, + CoglPipeline *pipeline1, + unsigned int differences, + unsigned long layer_differences, + CoglPipelineEvalFlags flags); + +unsigned int +_cogl_pipeline_hash (CoglPipeline *pipeline, + unsigned int differences, + unsigned long layer_differences, + CoglPipelineEvalFlags flags); + +/* Makes a copy of the given pipeline that is a child of the root + * pipeline rather than a child of the source pipeline. That way the + * new pipeline won't hold a reference to the source pipeline. The + * differences specified in @differences and @layer_differences are + * copied across and all other state is left with the default + * values. */ +CoglPipeline * +_cogl_pipeline_deep_copy (CoglPipeline *pipeline, + unsigned long differences, + unsigned long layer_differences); + +CoglPipeline * +_cogl_pipeline_journal_ref (CoglPipeline *pipeline); + +void +_cogl_pipeline_journal_unref (CoglPipeline *pipeline); + +const CoglMatrix * +_cogl_pipeline_get_layer_matrix (CoglPipeline *pipeline, + int layer_index); + +void +_cogl_pipeline_texture_storage_change_notify (CoglTexture *texture); + +void +_cogl_pipeline_apply_legacy_state (CoglPipeline *pipeline); + +void +_cogl_pipeline_apply_overrides (CoglPipeline *pipeline, + CoglPipelineFlushOptions *options); + +CoglPipelineBlendEnable +_cogl_pipeline_get_blend_enabled (CoglPipeline *pipeline); + +void +_cogl_pipeline_set_blend_enabled (CoglPipeline *pipeline, + CoglPipelineBlendEnable enable); + +CoglBool +_cogl_pipeline_get_fog_enabled (CoglPipeline *pipeline); + +#ifdef COGL_DEBUG_ENABLED +void +_cogl_pipeline_set_static_breadcrumb (CoglPipeline *pipeline, + const char *breadcrumb); +#endif + +unsigned long +_cogl_pipeline_get_age (CoglPipeline *pipeline); + +CoglPipeline * +_cogl_pipeline_get_authority (CoglPipeline *pipeline, + unsigned long difference); + +void +_cogl_pipeline_add_layer_difference (CoglPipeline *pipeline, + CoglPipelineLayer *layer, + CoglBool inc_n_layers); + +void +_cogl_pipeline_remove_layer_difference (CoglPipeline *pipeline, + CoglPipelineLayer *layer, + CoglBool dec_n_layers); + +CoglPipeline * +_cogl_pipeline_find_equivalent_parent (CoglPipeline *pipeline, + CoglPipelineState pipeline_state, + CoglPipelineLayerState layer_state); + +void +_cogl_pipeline_get_layer_combine_constant (CoglPipeline *pipeline, + int layer_index, + float *constant); + +void +_cogl_pipeline_prune_to_n_layers (CoglPipeline *pipeline, int n); + + +/* + * API to support the deprecate cogl_pipeline_layer_xyz functions... + */ + +const GList * +_cogl_pipeline_get_layers (CoglPipeline *pipeline); + +typedef CoglBool (*CoglPipelineInternalLayerCallback) (CoglPipelineLayer *layer, + void *user_data); + +void +_cogl_pipeline_foreach_layer_internal (CoglPipeline *pipeline, + CoglPipelineInternalLayerCallback callback, + void *user_data); + +CoglBool +_cogl_pipeline_layer_numbers_equal (CoglPipeline *pipeline0, + CoglPipeline *pipeline1); + +CoglBool +_cogl_pipeline_layer_and_unit_numbers_equal (CoglPipeline *pipeline0, + CoglPipeline *pipeline1); + +CoglBool +_cogl_pipeline_need_texture_combine_separate + (CoglPipelineLayer *combine_authority); + +void +_cogl_pipeline_init_state_hash_functions (void); + +void +_cogl_pipeline_init_layer_state_hash_functions (void); + +CoglPipelineState +_cogl_pipeline_get_state_for_vertex_codegen (CoglContext *context); + +CoglPipelineLayerState +_cogl_pipeline_get_layer_state_for_fragment_codegen (CoglContext *context); + +CoglPipelineState +_cogl_pipeline_get_state_for_fragment_codegen (CoglContext *context); + +#endif /* __COGL_PIPELINE_PRIVATE_H */ + diff --git a/cogl/cogl/cogl-pipeline-snippet-private.h b/cogl/cogl/cogl-pipeline-snippet-private.h new file mode 100644 index 0000000..7a9d233 --- /dev/null +++ b/cogl/cogl/cogl-pipeline-snippet-private.h @@ -0,0 +1,116 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011, 2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Neil Roberts + */ + +#ifndef __COGL_PIPELINE_SNIPPET_PRIVATE_H +#define __COGL_PIPELINE_SNIPPET_PRIVATE_H + +#include + +#include "cogl-snippet.h" + +typedef struct +{ + GList *entries; +} CoglPipelineSnippetList; + +/* Arguments to pass to _cogl_pipeline_snippet_generate_code() */ +typedef struct +{ + CoglPipelineSnippetList *snippets; + + /* Only snippets at this hook point will be used */ + CoglSnippetHook hook; + + /* The final function to chain on to after all of the snippets code + has been run */ + const char *chain_function; + + /* The name of the final generated function */ + const char *final_name; + + /* A prefix to insert before each generate function name */ + const char *function_prefix; + + /* The return type of all of the functions, or NULL to use void */ + const char *return_type; + + /* A variable to return from the functions. The snippets are + expected to modify this variable. Ignored if return_type is + NULL */ + const char *return_variable; + + /* If this is TRUE then it won't allocate a separate variable for + the return value. Instead it is expected that the snippet will + modify one of the argument variables directly and that will be + returned */ + CoglBool return_variable_is_argument; + + /* The argument names or NULL if there are none */ + const char *arguments; + + /* The argument types or NULL */ + const char *argument_declarations; + + /* The string to generate the source into */ + GString *source_buf; +} CoglPipelineSnippetData; + +void +_cogl_pipeline_snippet_generate_code (const CoglPipelineSnippetData *data); + +void +_cogl_pipeline_snippet_generate_declarations (GString *declarations_buf, + CoglSnippetHook hook, + CoglPipelineSnippetList *list); + +void +_cogl_pipeline_snippet_list_free (CoglPipelineSnippetList *list); + +void +_cogl_pipeline_snippet_list_add (CoglPipelineSnippetList *list, + CoglSnippet *snippet); + +void +_cogl_pipeline_snippet_list_copy (CoglPipelineSnippetList *dst, + const CoglPipelineSnippetList *src); + +void +_cogl_pipeline_snippet_list_hash (CoglPipelineSnippetList *list, + unsigned int *hash); + +CoglBool +_cogl_pipeline_snippet_list_equal (CoglPipelineSnippetList *list0, + CoglPipelineSnippetList *list1); + +#endif /* __COGL_PIPELINE_SNIPPET_PRIVATE_H */ + diff --git a/cogl/cogl/cogl-pipeline-snippet.c b/cogl/cogl/cogl-pipeline-snippet.c new file mode 100644 index 0000000..18aefc7 --- /dev/null +++ b/cogl/cogl/cogl-pipeline-snippet.c @@ -0,0 +1,286 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011, 2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Neil Roberts + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include + +#include "cogl-types.h" +#include "cogl-pipeline-snippet-private.h" +#include "cogl-snippet-private.h" +#include "cogl-util.h" + +/* Helper functions that are used by both GLSL pipeline backends */ + +void +_cogl_pipeline_snippet_generate_code (const CoglPipelineSnippetData *data) +{ + GList *first_snippet, *l; + CoglSnippet *snippet; + int snippet_num = 0; + int n_snippets = 0; + + first_snippet = data->snippets->entries; + + /* First count the number of snippets so we can easily tell when + we're at the last one */ + for (l = data->snippets->entries; l; l = l->next) + { + snippet = l->data; + + if (snippet->hook == data->hook) + { + /* Don't bother processing any previous snippets if we reach + one that has a replacement */ + if (snippet->replace) + { + n_snippets = 1; + first_snippet = l; + } + else + n_snippets++; + } + } + + /* If there weren't any snippets then generate a stub function with + the final name */ + if (n_snippets == 0) + { + if (data->return_type) + g_string_append_printf (data->source_buf, + "\n" + "%s\n" + "%s (%s)\n" + "{\n" + " return %s (%s);\n" + "}\n", + data->return_type, + data->final_name, + data->argument_declarations ? + data->argument_declarations : "", + data->chain_function, + data->arguments ? data->arguments : ""); + else + g_string_append_printf (data->source_buf, + "\n" + "void\n" + "%s (%s)\n" + "{\n" + " %s (%s);\n" + "}\n", + data->final_name, + data->argument_declarations ? + data->argument_declarations : "", + data->chain_function, + data->arguments ? data->arguments : ""); + + return; + } + + for (l = first_snippet; snippet_num < n_snippets; l = l->next) + { + snippet = l->data; + + if (snippet->hook == data->hook) + { + const char *source; + + if ((source = cogl_snippet_get_declarations (snippet))) + g_string_append (data->source_buf, source); + + g_string_append_printf (data->source_buf, + "\n" + "%s\n", + data->return_type ? + data->return_type : + "void"); + + if (snippet_num + 1 < n_snippets) + g_string_append_printf (data->source_buf, + "%s_%i", + data->function_prefix, + snippet_num); + else + g_string_append (data->source_buf, data->final_name); + + g_string_append (data->source_buf, " ("); + + if (data->argument_declarations) + g_string_append (data->source_buf, data->argument_declarations); + + g_string_append (data->source_buf, + ")\n" + "{\n"); + + if (data->return_type && !data->return_variable_is_argument) + g_string_append_printf (data->source_buf, + " %s %s;\n" + "\n", + data->return_type, + data->return_variable); + + if ((source = cogl_snippet_get_pre (snippet))) + g_string_append (data->source_buf, source); + + /* Chain on to the next function, or bypass it if there is + a replace string */ + if ((source = cogl_snippet_get_replace (snippet))) + g_string_append (data->source_buf, source); + else + { + g_string_append (data->source_buf, " "); + + if (data->return_type) + g_string_append_printf (data->source_buf, + "%s = ", + data->return_variable); + + if (snippet_num > 0) + g_string_append_printf (data->source_buf, + "%s_%i", + data->function_prefix, + snippet_num - 1); + else + g_string_append (data->source_buf, data->chain_function); + + g_string_append (data->source_buf, " ("); + + if (data->arguments) + g_string_append (data->source_buf, data->arguments); + + g_string_append (data->source_buf, ");\n"); + } + + if ((source = cogl_snippet_get_post (snippet))) + g_string_append (data->source_buf, source); + + if (data->return_type) + g_string_append_printf (data->source_buf, + " return %s;\n", + data->return_variable); + + g_string_append (data->source_buf, "}\n"); + snippet_num++; + } + } +} + +void +_cogl_pipeline_snippet_generate_declarations (GString *declarations_buf, + CoglSnippetHook hook, + CoglPipelineSnippetList *snippets) +{ + GList *l; + + for (l = snippets->entries; l; l = l->next) + { + CoglSnippet *snippet = l->data; + + if (snippet->hook == hook) + { + const char *source; + + if ((source = cogl_snippet_get_declarations (snippet))) + g_string_append (declarations_buf, source); + } + } +} + +void +_cogl_pipeline_snippet_list_free (CoglPipelineSnippetList *list) +{ + GList *l, *tmp; + + for (l = list->entries; l; l = tmp) + { + tmp = l->next; + + cogl_object_unref (l->data); + g_list_free_1 (l); + } +} + +void +_cogl_pipeline_snippet_list_add (CoglPipelineSnippetList *list, + CoglSnippet *snippet) +{ + list->entries = g_list_append (list->entries, cogl_object_ref (snippet)); + + _cogl_snippet_make_immutable (snippet); +} + +void +_cogl_pipeline_snippet_list_copy (CoglPipelineSnippetList *dst, + const CoglPipelineSnippetList *src) +{ + GQueue queue = G_QUEUE_INIT; + const GList *l; + + for (l = src->entries; l; l = l->next) + g_queue_push_tail (&queue, cogl_object_ref (l->data)); + + dst->entries = queue.head; +} + +void +_cogl_pipeline_snippet_list_hash (CoglPipelineSnippetList *list, + unsigned int *hash) +{ + GList *l; + + for (l = list->entries; l; l = l->next) + { + CoglSnippet *snippet = l->data; + + *hash = _cogl_util_one_at_a_time_hash (*hash, + &snippet, + sizeof (CoglSnippet *)); + } +} + +CoglBool +_cogl_pipeline_snippet_list_equal (CoglPipelineSnippetList *list0, + CoglPipelineSnippetList *list1) +{ + GList *l0, *l1; + + for (l0 = list0->entries, l1 = list1->entries; + l0 && l1; + l0 = l0->next, l1 = l1->next) + if (l0->data != l1->data) + return FALSE; + + return l0 == NULL && l1 == NULL; +} diff --git a/cogl/cogl/cogl-pipeline-state-private.h b/cogl/cogl/cogl-pipeline-state-private.h new file mode 100644 index 0000000..366683e --- /dev/null +++ b/cogl/cogl/cogl-pipeline-state-private.h @@ -0,0 +1,196 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_PIPELINE_STATE_PRIVATE_H +#define __COGL_PIPELINE_STATE_PRIVATE_H + +CoglPipeline * +_cogl_pipeline_get_user_program (CoglPipeline *pipeline); + +CoglBool +_cogl_pipeline_has_vertex_snippets (CoglPipeline *pipeline); + +CoglBool +_cogl_pipeline_has_fragment_snippets (CoglPipeline *pipeline); + +CoglBool +_cogl_pipeline_has_non_layer_vertex_snippets (CoglPipeline *pipeline); + +CoglBool +_cogl_pipeline_has_non_layer_fragment_snippets (CoglPipeline *pipeline); + +void +_cogl_pipeline_set_fog_state (CoglPipeline *pipeline, + const CoglPipelineFogState *fog_state); + +CoglBool +_cogl_pipeline_color_equal (CoglPipeline *authority0, + CoglPipeline *authority1); + +CoglBool +_cogl_pipeline_lighting_state_equal (CoglPipeline *authority0, + CoglPipeline *authority1); + +CoglBool +_cogl_pipeline_alpha_func_state_equal (CoglPipeline *authority0, + CoglPipeline *authority1); + +CoglBool +_cogl_pipeline_alpha_func_reference_state_equal (CoglPipeline *authority0, + CoglPipeline *authority1); + +CoglBool +_cogl_pipeline_blend_state_equal (CoglPipeline *authority0, + CoglPipeline *authority1); + +CoglBool +_cogl_pipeline_depth_state_equal (CoglPipeline *authority0, + CoglPipeline *authority1); + +CoglBool +_cogl_pipeline_fog_state_equal (CoglPipeline *authority0, + CoglPipeline *authority1); + +CoglBool +_cogl_pipeline_non_zero_point_size_equal (CoglPipeline *authority0, + CoglPipeline *authority1); + +CoglBool +_cogl_pipeline_point_size_equal (CoglPipeline *authority0, + CoglPipeline *authority1); +CoglBool +_cogl_pipeline_per_vertex_point_size_equal (CoglPipeline *authority0, + CoglPipeline *authority1); + +CoglBool +_cogl_pipeline_logic_ops_state_equal (CoglPipeline *authority0, + CoglPipeline *authority1); + +CoglBool +_cogl_pipeline_user_shader_equal (CoglPipeline *authority0, + CoglPipeline *authority1); + +CoglBool +_cogl_pipeline_cull_face_state_equal (CoglPipeline *authority0, + CoglPipeline *authority1); + +CoglBool +_cogl_pipeline_uniforms_state_equal (CoglPipeline *authority0, + CoglPipeline *authority1); + +CoglBool +_cogl_pipeline_vertex_snippets_state_equal (CoglPipeline *authority0, + CoglPipeline *authority1); + +CoglBool +_cogl_pipeline_fragment_snippets_state_equal (CoglPipeline *authority0, + CoglPipeline *authority1); + +void +_cogl_pipeline_hash_color_state (CoglPipeline *authority, + CoglPipelineHashState *state); + +void +_cogl_pipeline_hash_blend_enable_state (CoglPipeline *authority, + CoglPipelineHashState *state); + +void +_cogl_pipeline_hash_layers_state (CoglPipeline *authority, + CoglPipelineHashState *state); + +void +_cogl_pipeline_hash_lighting_state (CoglPipeline *authority, + CoglPipelineHashState *state); + +void +_cogl_pipeline_hash_alpha_func_state (CoglPipeline *authority, + CoglPipelineHashState *state); + +void +_cogl_pipeline_hash_alpha_func_reference_state (CoglPipeline *authority, + CoglPipelineHashState *state); + +void +_cogl_pipeline_hash_blend_state (CoglPipeline *authority, + CoglPipelineHashState *state); + +void +_cogl_pipeline_hash_user_shader_state (CoglPipeline *authority, + CoglPipelineHashState *state); + +void +_cogl_pipeline_hash_depth_state (CoglPipeline *authority, + CoglPipelineHashState *state); + +void +_cogl_pipeline_hash_fog_state (CoglPipeline *authority, + CoglPipelineHashState *state); + +void +_cogl_pipeline_hash_non_zero_point_size_state (CoglPipeline *authority, + CoglPipelineHashState *state); + +void +_cogl_pipeline_hash_point_size_state (CoglPipeline *authority, + CoglPipelineHashState *state); + +void +_cogl_pipeline_hash_per_vertex_point_size_state (CoglPipeline *authority, + CoglPipelineHashState *state); + +void +_cogl_pipeline_hash_logic_ops_state (CoglPipeline *authority, + CoglPipelineHashState *state); + +void +_cogl_pipeline_hash_cull_face_state (CoglPipeline *authority, + CoglPipelineHashState *state); + +void +_cogl_pipeline_hash_uniforms_state (CoglPipeline *authority, + CoglPipelineHashState *state); + +void +_cogl_pipeline_hash_vertex_snippets_state (CoglPipeline *authority, + CoglPipelineHashState *state); + +void +_cogl_pipeline_hash_fragment_snippets_state (CoglPipeline *authority, + CoglPipelineHashState *state); + +void +_cogl_pipeline_compare_uniform_differences (unsigned long *differences, + CoglPipeline *pipeline0, + CoglPipeline *pipeline1); + +#endif /* __COGL_PIPELINE_STATE_PRIVATE_H */ diff --git a/cogl/cogl/cogl-pipeline-state.c b/cogl/cogl/cogl-pipeline-state.c new file mode 100644 index 0000000..57eaf57 --- /dev/null +++ b/cogl/cogl/cogl-pipeline-state.c @@ -0,0 +1,2171 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-context-private.h" +#include "cogl-color-private.h" +#include "cogl-blend-string.h" +#include "cogl-util.h" +#include "cogl-depth-state-private.h" +#include "cogl-pipeline-state-private.h" +#include "cogl-snippet-private.h" +#include "cogl-error-private.h" + +#include + +#include "string.h" + +#ifndef GL_FUNC_ADD +#define GL_FUNC_ADD 0x8006 +#endif + +CoglPipeline * +_cogl_pipeline_get_user_program (CoglPipeline *pipeline) +{ + CoglPipeline *authority; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), NULL); + + authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_USER_SHADER); + + return authority->big_state->user_program; +} + +CoglBool +_cogl_pipeline_color_equal (CoglPipeline *authority0, + CoglPipeline *authority1) +{ + return cogl_color_equal (&authority0->color, &authority1->color); +} + +CoglBool +_cogl_pipeline_lighting_state_equal (CoglPipeline *authority0, + CoglPipeline *authority1) +{ + CoglPipelineLightingState *state0 = &authority0->big_state->lighting_state; + CoglPipelineLightingState *state1 = &authority1->big_state->lighting_state; + + if (memcmp (state0->ambient, state1->ambient, sizeof (float) * 4) != 0) + return FALSE; + if (memcmp (state0->diffuse, state1->diffuse, sizeof (float) * 4) != 0) + return FALSE; + if (memcmp (state0->specular, state1->specular, sizeof (float) * 4) != 0) + return FALSE; + if (memcmp (state0->emission, state1->emission, sizeof (float) * 4) != 0) + return FALSE; + if (state0->shininess != state1->shininess) + return FALSE; + + return TRUE; +} + +CoglBool +_cogl_pipeline_alpha_func_state_equal (CoglPipeline *authority0, + CoglPipeline *authority1) +{ + CoglPipelineAlphaFuncState *alpha_state0 = + &authority0->big_state->alpha_state; + CoglPipelineAlphaFuncState *alpha_state1 = + &authority1->big_state->alpha_state; + + return alpha_state0->alpha_func == alpha_state1->alpha_func; +} + +CoglBool +_cogl_pipeline_alpha_func_reference_state_equal (CoglPipeline *authority0, + CoglPipeline *authority1) +{ + CoglPipelineAlphaFuncState *alpha_state0 = + &authority0->big_state->alpha_state; + CoglPipelineAlphaFuncState *alpha_state1 = + &authority1->big_state->alpha_state; + + return (alpha_state0->alpha_func_reference == + alpha_state1->alpha_func_reference); +} + +CoglBool +_cogl_pipeline_blend_state_equal (CoglPipeline *authority0, + CoglPipeline *authority1) +{ + CoglPipelineBlendState *blend_state0 = &authority0->big_state->blend_state; + CoglPipelineBlendState *blend_state1 = &authority1->big_state->blend_state; + + _COGL_GET_CONTEXT (ctx, FALSE); + + if (blend_state0->blend_equation_rgb != blend_state1->blend_equation_rgb) + return FALSE; + + if (blend_state0->blend_equation_alpha != + blend_state1->blend_equation_alpha) + return FALSE; + if (blend_state0->blend_src_factor_alpha != + blend_state1->blend_src_factor_alpha) + return FALSE; + if (blend_state0->blend_dst_factor_alpha != + blend_state1->blend_dst_factor_alpha) + return FALSE; + + if (blend_state0->blend_src_factor_rgb != + blend_state1->blend_src_factor_rgb) + return FALSE; + if (blend_state0->blend_dst_factor_rgb != + blend_state1->blend_dst_factor_rgb) + return FALSE; + + if (blend_state0->blend_src_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR || + blend_state0->blend_src_factor_rgb == GL_CONSTANT_COLOR || + blend_state0->blend_dst_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR || + blend_state0->blend_dst_factor_rgb == GL_CONSTANT_COLOR) + { + if (!cogl_color_equal (&blend_state0->blend_constant, + &blend_state1->blend_constant)) + return FALSE; + } + + return TRUE; +} + +CoglBool +_cogl_pipeline_depth_state_equal (CoglPipeline *authority0, + CoglPipeline *authority1) +{ + if (authority0->big_state->depth_state.test_enabled == FALSE && + authority1->big_state->depth_state.test_enabled == FALSE) + return TRUE; + else + { + CoglDepthState *s0 = &authority0->big_state->depth_state; + CoglDepthState *s1 = &authority1->big_state->depth_state; + return s0->test_enabled == s1->test_enabled && + s0->test_function == s1->test_function && + s0->write_enabled == s1->write_enabled && + s0->range_near == s1->range_near && + s0->range_far == s1->range_far; + } +} + +CoglBool +_cogl_pipeline_fog_state_equal (CoglPipeline *authority0, + CoglPipeline *authority1) +{ + CoglPipelineFogState *fog_state0 = &authority0->big_state->fog_state; + CoglPipelineFogState *fog_state1 = &authority1->big_state->fog_state; + + if (fog_state0->enabled == fog_state1->enabled && + cogl_color_equal (&fog_state0->color, &fog_state1->color) && + fog_state0->mode == fog_state1->mode && + fog_state0->density == fog_state1->density && + fog_state0->z_near == fog_state1->z_near && + fog_state0->z_far == fog_state1->z_far) + return TRUE; + else + return FALSE; +} + +CoglBool +_cogl_pipeline_non_zero_point_size_equal (CoglPipeline *authority0, + CoglPipeline *authority1) +{ + return (authority0->big_state->non_zero_point_size == + authority1->big_state->non_zero_point_size); +} + +CoglBool +_cogl_pipeline_point_size_equal (CoglPipeline *authority0, + CoglPipeline *authority1) +{ + return authority0->big_state->point_size == authority1->big_state->point_size; +} + +CoglBool +_cogl_pipeline_per_vertex_point_size_equal (CoglPipeline *authority0, + CoglPipeline *authority1) +{ + return (authority0->big_state->per_vertex_point_size == + authority1->big_state->per_vertex_point_size); +} + +CoglBool +_cogl_pipeline_logic_ops_state_equal (CoglPipeline *authority0, + CoglPipeline *authority1) +{ + CoglPipelineLogicOpsState *logic_ops_state0 = &authority0->big_state->logic_ops_state; + CoglPipelineLogicOpsState *logic_ops_state1 = &authority1->big_state->logic_ops_state; + + return logic_ops_state0->color_mask == logic_ops_state1->color_mask; +} + +CoglBool +_cogl_pipeline_cull_face_state_equal (CoglPipeline *authority0, + CoglPipeline *authority1) +{ + CoglPipelineCullFaceState *cull_face_state0 + = &authority0->big_state->cull_face_state; + CoglPipelineCullFaceState *cull_face_state1 + = &authority1->big_state->cull_face_state; + + /* The cull face state is considered equal if two pipelines are both + set to no culling. If the front winding property is ever used for + anything else or the comparison is used not just for drawing then + this would have to change */ + + if (cull_face_state0->mode == COGL_PIPELINE_CULL_FACE_MODE_NONE) + return cull_face_state1->mode == COGL_PIPELINE_CULL_FACE_MODE_NONE; + + return (cull_face_state0->mode == cull_face_state1->mode && + cull_face_state0->front_winding == cull_face_state1->front_winding); +} + +CoglBool +_cogl_pipeline_user_shader_equal (CoglPipeline *authority0, + CoglPipeline *authority1) +{ + return (authority0->big_state->user_program == + authority1->big_state->user_program); +} + +typedef struct +{ + const CoglBoxedValue **dst_values; + const CoglBoxedValue *src_values; + int override_count; +} GetUniformsClosure; + +static CoglBool +get_uniforms_cb (int uniform_num, void *user_data) +{ + GetUniformsClosure *data = user_data; + + if (data->dst_values[uniform_num] == NULL) + data->dst_values[uniform_num] = data->src_values + data->override_count; + + data->override_count++; + + return TRUE; +} + +static void +_cogl_pipeline_get_all_uniform_values (CoglPipeline *pipeline, + const CoglBoxedValue **values) +{ + GetUniformsClosure data; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + memset (values, 0, + sizeof (const CoglBoxedValue *) * ctx->n_uniform_names); + + data.dst_values = values; + + do + { + if ((pipeline->differences & COGL_PIPELINE_STATE_UNIFORMS)) + { + const CoglPipelineUniformsState *uniforms_state = + &pipeline->big_state->uniforms_state; + + data.override_count = 0; + data.src_values = uniforms_state->override_values; + + _cogl_bitmask_foreach (&uniforms_state->override_mask, + get_uniforms_cb, + &data); + } + pipeline = _cogl_pipeline_get_parent (pipeline); + } + while (pipeline); +} + +CoglBool +_cogl_pipeline_uniforms_state_equal (CoglPipeline *authority0, + CoglPipeline *authority1) +{ + unsigned long *differences; + const CoglBoxedValue **values0, **values1; + int n_longs; + int i; + + _COGL_GET_CONTEXT (ctx, FALSE); + + if (authority0 == authority1) + return TRUE; + + values0 = g_alloca (sizeof (const CoglBoxedValue *) * ctx->n_uniform_names); + values1 = g_alloca (sizeof (const CoglBoxedValue *) * ctx->n_uniform_names); + + n_longs = COGL_FLAGS_N_LONGS_FOR_SIZE (ctx->n_uniform_names); + differences = g_alloca (n_longs * sizeof (unsigned long)); + memset (differences, 0, sizeof (unsigned long) * n_longs); + _cogl_pipeline_compare_uniform_differences (differences, + authority0, + authority1); + + _cogl_pipeline_get_all_uniform_values (authority0, values0); + _cogl_pipeline_get_all_uniform_values (authority1, values1); + + COGL_FLAGS_FOREACH_START (differences, n_longs, i) + { + const CoglBoxedValue *value0 = values0[i]; + const CoglBoxedValue *value1 = values1[i]; + + if (value0 == NULL) + { + if (value1 != NULL && value1->type != COGL_BOXED_NONE) + return FALSE; + } + else if (value1 == NULL) + { + if (value0 != NULL && value0->type != COGL_BOXED_NONE) + return FALSE; + } + else if (!_cogl_boxed_value_equal (value0, value1)) + return FALSE; + } + COGL_FLAGS_FOREACH_END; + + return TRUE; +} + +CoglBool +_cogl_pipeline_vertex_snippets_state_equal (CoglPipeline *authority0, + CoglPipeline *authority1) +{ + return _cogl_pipeline_snippet_list_equal (&authority0->big_state-> + vertex_snippets, + &authority1->big_state-> + vertex_snippets); +} + +CoglBool +_cogl_pipeline_fragment_snippets_state_equal (CoglPipeline *authority0, + CoglPipeline *authority1) +{ + return _cogl_pipeline_snippet_list_equal (&authority0->big_state-> + fragment_snippets, + &authority1->big_state-> + fragment_snippets); +} + +void +cogl_pipeline_get_color (CoglPipeline *pipeline, + CoglColor *color) +{ + CoglPipeline *authority; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_COLOR); + + *color = authority->color; +} + +/* This is used heavily by the cogl journal when logging quads */ +void +_cogl_pipeline_get_colorubv (CoglPipeline *pipeline, + uint8_t *color) +{ + CoglPipeline *authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_COLOR); + + _cogl_color_get_rgba_4ubv (&authority->color, color); +} + +void +cogl_pipeline_set_color (CoglPipeline *pipeline, + const CoglColor *color) +{ + CoglPipelineState state = COGL_PIPELINE_STATE_COLOR; + CoglPipeline *authority; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + authority = _cogl_pipeline_get_authority (pipeline, state); + + if (cogl_color_equal (color, &authority->color)) + return; + + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_pipeline_pre_change_notify (pipeline, state, color, FALSE); + + pipeline->color = *color; + + _cogl_pipeline_update_authority (pipeline, authority, state, + _cogl_pipeline_color_equal); + + pipeline->dirty_real_blend_enable = TRUE; +} + +void +cogl_pipeline_set_color4ub (CoglPipeline *pipeline, + uint8_t red, + uint8_t green, + uint8_t blue, + uint8_t alpha) +{ + CoglColor color; + cogl_color_init_from_4ub (&color, red, green, blue, alpha); + cogl_pipeline_set_color (pipeline, &color); +} + +void +cogl_pipeline_set_color4f (CoglPipeline *pipeline, + float red, + float green, + float blue, + float alpha) +{ + CoglColor color; + cogl_color_init_from_4f (&color, red, green, blue, alpha); + cogl_pipeline_set_color (pipeline, &color); +} + +CoglPipelineBlendEnable +_cogl_pipeline_get_blend_enabled (CoglPipeline *pipeline) +{ + CoglPipeline *authority; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), FALSE); + + authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_BLEND_ENABLE); + return authority->blend_enable; +} + +static CoglBool +_cogl_pipeline_blend_enable_equal (CoglPipeline *authority0, + CoglPipeline *authority1) +{ + return authority0->blend_enable == authority1->blend_enable ? TRUE : FALSE; +} + +void +_cogl_pipeline_set_blend_enabled (CoglPipeline *pipeline, + CoglPipelineBlendEnable enable) +{ + CoglPipelineState state = COGL_PIPELINE_STATE_BLEND_ENABLE; + CoglPipeline *authority; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + _COGL_RETURN_IF_FAIL (enable > 1 && + "don't pass TRUE or FALSE to _set_blend_enabled!"); + + authority = _cogl_pipeline_get_authority (pipeline, state); + + if (authority->blend_enable == enable) + return; + + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); + + pipeline->blend_enable = enable; + + _cogl_pipeline_update_authority (pipeline, authority, state, + _cogl_pipeline_blend_enable_equal); + + pipeline->dirty_real_blend_enable = TRUE; +} + +void +cogl_pipeline_get_ambient (CoglPipeline *pipeline, + CoglColor *ambient) +{ + CoglPipeline *authority; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LIGHTING); + + cogl_color_init_from_4fv (ambient, + authority->big_state->lighting_state.ambient); +} + +void +cogl_pipeline_set_ambient (CoglPipeline *pipeline, + const CoglColor *ambient) +{ + CoglPipelineState state = COGL_PIPELINE_STATE_LIGHTING; + CoglPipeline *authority; + CoglPipelineLightingState *lighting_state; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + authority = _cogl_pipeline_get_authority (pipeline, state); + + lighting_state = &authority->big_state->lighting_state; + if (cogl_color_equal (ambient, &lighting_state->ambient)) + return; + + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); + + lighting_state = &pipeline->big_state->lighting_state; + lighting_state->ambient[0] = cogl_color_get_red_float (ambient); + lighting_state->ambient[1] = cogl_color_get_green_float (ambient); + lighting_state->ambient[2] = cogl_color_get_blue_float (ambient); + lighting_state->ambient[3] = cogl_color_get_alpha_float (ambient); + + _cogl_pipeline_update_authority (pipeline, authority, state, + _cogl_pipeline_lighting_state_equal); + + pipeline->dirty_real_blend_enable = TRUE; +} + +void +cogl_pipeline_get_diffuse (CoglPipeline *pipeline, + CoglColor *diffuse) +{ + CoglPipeline *authority; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LIGHTING); + + cogl_color_init_from_4fv (diffuse, + authority->big_state->lighting_state.diffuse); +} + +void +cogl_pipeline_set_diffuse (CoglPipeline *pipeline, + const CoglColor *diffuse) +{ + CoglPipelineState state = COGL_PIPELINE_STATE_LIGHTING; + CoglPipeline *authority; + CoglPipelineLightingState *lighting_state; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + authority = _cogl_pipeline_get_authority (pipeline, state); + + lighting_state = &authority->big_state->lighting_state; + if (cogl_color_equal (diffuse, &lighting_state->diffuse)) + return; + + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); + + lighting_state = &pipeline->big_state->lighting_state; + lighting_state->diffuse[0] = cogl_color_get_red_float (diffuse); + lighting_state->diffuse[1] = cogl_color_get_green_float (diffuse); + lighting_state->diffuse[2] = cogl_color_get_blue_float (diffuse); + lighting_state->diffuse[3] = cogl_color_get_alpha_float (diffuse); + + + _cogl_pipeline_update_authority (pipeline, authority, state, + _cogl_pipeline_lighting_state_equal); + + pipeline->dirty_real_blend_enable = TRUE; +} + +void +cogl_pipeline_set_ambient_and_diffuse (CoglPipeline *pipeline, + const CoglColor *color) +{ + cogl_pipeline_set_ambient (pipeline, color); + cogl_pipeline_set_diffuse (pipeline, color); +} + +void +cogl_pipeline_get_specular (CoglPipeline *pipeline, + CoglColor *specular) +{ + CoglPipeline *authority; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LIGHTING); + + cogl_color_init_from_4fv (specular, + authority->big_state->lighting_state.specular); +} + +void +cogl_pipeline_set_specular (CoglPipeline *pipeline, const CoglColor *specular) +{ + CoglPipeline *authority; + CoglPipelineState state = COGL_PIPELINE_STATE_LIGHTING; + CoglPipelineLightingState *lighting_state; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + authority = _cogl_pipeline_get_authority (pipeline, state); + + lighting_state = &authority->big_state->lighting_state; + if (cogl_color_equal (specular, &lighting_state->specular)) + return; + + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); + + lighting_state = &pipeline->big_state->lighting_state; + lighting_state->specular[0] = cogl_color_get_red_float (specular); + lighting_state->specular[1] = cogl_color_get_green_float (specular); + lighting_state->specular[2] = cogl_color_get_blue_float (specular); + lighting_state->specular[3] = cogl_color_get_alpha_float (specular); + + _cogl_pipeline_update_authority (pipeline, authority, state, + _cogl_pipeline_lighting_state_equal); + + pipeline->dirty_real_blend_enable = TRUE; +} + +float +cogl_pipeline_get_shininess (CoglPipeline *pipeline) +{ + CoglPipeline *authority; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), 0); + + authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LIGHTING); + + return authority->big_state->lighting_state.shininess; +} + +void +cogl_pipeline_set_shininess (CoglPipeline *pipeline, + float shininess) +{ + CoglPipeline *authority; + CoglPipelineState state = COGL_PIPELINE_STATE_LIGHTING; + CoglPipelineLightingState *lighting_state; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + if (shininess < 0.0) + { + g_warning ("Out of range shininess %f supplied for pipeline\n", + shininess); + return; + } + + authority = _cogl_pipeline_get_authority (pipeline, state); + + lighting_state = &authority->big_state->lighting_state; + + if (lighting_state->shininess == shininess) + return; + + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); + + lighting_state = &pipeline->big_state->lighting_state; + lighting_state->shininess = shininess; + + _cogl_pipeline_update_authority (pipeline, authority, state, + _cogl_pipeline_lighting_state_equal); +} + +void +cogl_pipeline_get_emission (CoglPipeline *pipeline, + CoglColor *emission) +{ + CoglPipeline *authority; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LIGHTING); + + cogl_color_init_from_4fv (emission, + authority->big_state->lighting_state.emission); +} + +void +cogl_pipeline_set_emission (CoglPipeline *pipeline, const CoglColor *emission) +{ + CoglPipeline *authority; + CoglPipelineState state = COGL_PIPELINE_STATE_LIGHTING; + CoglPipelineLightingState *lighting_state; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + authority = _cogl_pipeline_get_authority (pipeline, state); + + lighting_state = &authority->big_state->lighting_state; + if (cogl_color_equal (emission, &lighting_state->emission)) + return; + + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); + + lighting_state = &pipeline->big_state->lighting_state; + lighting_state->emission[0] = cogl_color_get_red_float (emission); + lighting_state->emission[1] = cogl_color_get_green_float (emission); + lighting_state->emission[2] = cogl_color_get_blue_float (emission); + lighting_state->emission[3] = cogl_color_get_alpha_float (emission); + + _cogl_pipeline_update_authority (pipeline, authority, state, + _cogl_pipeline_lighting_state_equal); + + pipeline->dirty_real_blend_enable = TRUE; +} + +static void +_cogl_pipeline_set_alpha_test_function (CoglPipeline *pipeline, + CoglPipelineAlphaFunc alpha_func) +{ + CoglPipelineState state = COGL_PIPELINE_STATE_ALPHA_FUNC; + CoglPipeline *authority; + CoglPipelineAlphaFuncState *alpha_state; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + authority = _cogl_pipeline_get_authority (pipeline, state); + + alpha_state = &authority->big_state->alpha_state; + if (alpha_state->alpha_func == alpha_func) + return; + + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); + + alpha_state = &pipeline->big_state->alpha_state; + alpha_state->alpha_func = alpha_func; + + _cogl_pipeline_update_authority (pipeline, authority, state, + _cogl_pipeline_alpha_func_state_equal); +} + +static void +_cogl_pipeline_set_alpha_test_function_reference (CoglPipeline *pipeline, + float alpha_reference) +{ + CoglPipelineState state = COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE; + CoglPipeline *authority; + CoglPipelineAlphaFuncState *alpha_state; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + authority = _cogl_pipeline_get_authority (pipeline, state); + + alpha_state = &authority->big_state->alpha_state; + if (alpha_state->alpha_func_reference == alpha_reference) + return; + + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); + + alpha_state = &pipeline->big_state->alpha_state; + alpha_state->alpha_func_reference = alpha_reference; + + _cogl_pipeline_update_authority + (pipeline, authority, state, + _cogl_pipeline_alpha_func_reference_state_equal); +} + +void +cogl_pipeline_set_alpha_test_function (CoglPipeline *pipeline, + CoglPipelineAlphaFunc alpha_func, + float alpha_reference) +{ + _cogl_pipeline_set_alpha_test_function (pipeline, alpha_func); + _cogl_pipeline_set_alpha_test_function_reference (pipeline, alpha_reference); +} + +CoglPipelineAlphaFunc +cogl_pipeline_get_alpha_test_function (CoglPipeline *pipeline) +{ + CoglPipeline *authority; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), 0); + + authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_ALPHA_FUNC); + + return authority->big_state->alpha_state.alpha_func; +} + +float +cogl_pipeline_get_alpha_test_reference (CoglPipeline *pipeline) +{ + CoglPipeline *authority; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), 0.0f); + + authority = + _cogl_pipeline_get_authority (pipeline, + COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE); + + return authority->big_state->alpha_state.alpha_func_reference; +} + +static GLenum +arg_to_gl_blend_factor (CoglBlendStringArgument *arg) +{ + if (arg->source.is_zero) + return GL_ZERO; + if (arg->factor.is_one) + return GL_ONE; + else if (arg->factor.is_src_alpha_saturate) + return GL_SRC_ALPHA_SATURATE; + else if (arg->factor.source.info->type == + COGL_BLEND_STRING_COLOR_SOURCE_SRC_COLOR) + { + if (arg->factor.source.mask != COGL_BLEND_STRING_CHANNEL_MASK_ALPHA) + { + if (arg->factor.source.one_minus) + return GL_ONE_MINUS_SRC_COLOR; + else + return GL_SRC_COLOR; + } + else + { + if (arg->factor.source.one_minus) + return GL_ONE_MINUS_SRC_ALPHA; + else + return GL_SRC_ALPHA; + } + } + else if (arg->factor.source.info->type == + COGL_BLEND_STRING_COLOR_SOURCE_DST_COLOR) + { + if (arg->factor.source.mask != COGL_BLEND_STRING_CHANNEL_MASK_ALPHA) + { + if (arg->factor.source.one_minus) + return GL_ONE_MINUS_DST_COLOR; + else + return GL_DST_COLOR; + } + else + { + if (arg->factor.source.one_minus) + return GL_ONE_MINUS_DST_ALPHA; + else + return GL_DST_ALPHA; + } + } +#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL) + else if (arg->factor.source.info->type == + COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT) + { + if (arg->factor.source.mask != COGL_BLEND_STRING_CHANNEL_MASK_ALPHA) + { + if (arg->factor.source.one_minus) + return GL_ONE_MINUS_CONSTANT_COLOR; + else + return GL_CONSTANT_COLOR; + } + else + { + if (arg->factor.source.one_minus) + return GL_ONE_MINUS_CONSTANT_ALPHA; + else + return GL_CONSTANT_ALPHA; + } + } +#endif + + g_warning ("Unable to determine valid blend factor from blend string\n"); + return GL_ONE; +} + +static void +setup_blend_state (CoglBlendStringStatement *statement, + GLenum *blend_equation, + GLint *blend_src_factor, + GLint *blend_dst_factor) +{ + 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; + } + + *blend_src_factor = arg_to_gl_blend_factor (&statement->args[0]); + *blend_dst_factor = arg_to_gl_blend_factor (&statement->args[1]); +} + +CoglBool +cogl_pipeline_set_blend (CoglPipeline *pipeline, + const char *blend_description, + CoglError **error) +{ + CoglPipelineState state = COGL_PIPELINE_STATE_BLEND; + CoglPipeline *authority; + CoglBlendStringStatement statements[2]; + CoglBlendStringStatement *rgb; + CoglBlendStringStatement *a; + int count; + CoglPipelineBlendState *blend_state; + + _COGL_GET_CONTEXT (ctx, FALSE); + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), FALSE); + + count = + _cogl_blend_string_compile (blend_description, + COGL_BLEND_STRING_CONTEXT_BLENDING, + statements, + error); + if (!count) + return FALSE; + + if (count == 1) + rgb = a = statements; + else + { + rgb = &statements[0]; + a = &statements[1]; + } + + authority = + _cogl_pipeline_get_authority (pipeline, state); + + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); + + blend_state = &pipeline->big_state->blend_state; + + setup_blend_state (rgb, + &blend_state->blend_equation_rgb, + &blend_state->blend_src_factor_rgb, + &blend_state->blend_dst_factor_rgb); + setup_blend_state (a, + &blend_state->blend_equation_alpha, + &blend_state->blend_src_factor_alpha, + &blend_state->blend_dst_factor_alpha); + + /* If we are the current authority see if we can revert to one of our + * ancestors being the authority */ + if (pipeline == authority && + _cogl_pipeline_get_parent (authority) != NULL) + { + CoglPipeline *parent = _cogl_pipeline_get_parent (authority); + CoglPipeline *old_authority = + _cogl_pipeline_get_authority (parent, state); + + if (_cogl_pipeline_blend_state_equal (authority, old_authority)) + pipeline->differences &= ~state; + } + + /* If we weren't previously the authority on this state then we need + * to extended our differences mask and so it's possible that some + * of our ancestry will now become redundant, so we aim to reparent + * ourselves if that's true... */ + if (pipeline != authority) + { + pipeline->differences |= state; + _cogl_pipeline_prune_redundant_ancestry (pipeline); + } + + pipeline->dirty_real_blend_enable = TRUE; + + return TRUE; +} + +void +cogl_pipeline_set_blend_constant (CoglPipeline *pipeline, + const CoglColor *constant_color) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_BLEND_CONSTANT)) + return; + +#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL) + { + CoglPipelineState state = COGL_PIPELINE_STATE_BLEND; + CoglPipeline *authority; + CoglPipelineBlendState *blend_state; + + authority = _cogl_pipeline_get_authority (pipeline, state); + + blend_state = &authority->big_state->blend_state; + if (cogl_color_equal (constant_color, &blend_state->blend_constant)) + return; + + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); + + blend_state = &pipeline->big_state->blend_state; + blend_state->blend_constant = *constant_color; + + _cogl_pipeline_update_authority (pipeline, authority, state, + _cogl_pipeline_blend_state_equal); + + pipeline->dirty_real_blend_enable = TRUE; + } +#endif +} + +CoglHandle +cogl_pipeline_get_user_program (CoglPipeline *pipeline) +{ + CoglPipeline *authority; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), COGL_INVALID_HANDLE); + + authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_USER_SHADER); + + return authority->big_state->user_program; +} + +/* XXX: for now we don't mind if the program has vertex shaders + * attached but if we ever make a similar API public we should only + * allow attaching of programs containing fragment shaders. Eventually + * we will have a CoglPipeline abstraction to also cover vertex + * processing. + */ +void +cogl_pipeline_set_user_program (CoglPipeline *pipeline, + CoglHandle program) +{ + CoglPipelineState state = COGL_PIPELINE_STATE_USER_SHADER; + CoglPipeline *authority; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + authority = _cogl_pipeline_get_authority (pipeline, state); + + if (authority->big_state->user_program == program) + return; + + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); + + if (program != COGL_INVALID_HANDLE) + _cogl_pipeline_set_progend (pipeline, COGL_PIPELINE_PROGEND_UNDEFINED); + + /* If we are the current authority see if we can revert to one of our + * ancestors being the authority */ + if (pipeline == authority && + _cogl_pipeline_get_parent (authority) != NULL) + { + CoglPipeline *parent = _cogl_pipeline_get_parent (authority); + CoglPipeline *old_authority = + _cogl_pipeline_get_authority (parent, state); + + if (old_authority->big_state->user_program == program) + pipeline->differences &= ~state; + } + else if (pipeline != authority) + { + /* If we weren't previously the authority on this state then we + * need to extended our differences mask and so it's possible + * that some of our ancestry will now become redundant, so we + * aim to reparent ourselves if that's true... */ + pipeline->differences |= state; + _cogl_pipeline_prune_redundant_ancestry (pipeline); + } + + if (program != COGL_INVALID_HANDLE) + cogl_handle_ref (program); + if (authority == pipeline && + pipeline->big_state->user_program != COGL_INVALID_HANDLE) + cogl_handle_unref (pipeline->big_state->user_program); + pipeline->big_state->user_program = program; + + pipeline->dirty_real_blend_enable = TRUE; +} + +CoglBool +cogl_pipeline_set_depth_state (CoglPipeline *pipeline, + const CoglDepthState *depth_state, + CoglError **error) +{ + CoglPipelineState state = COGL_PIPELINE_STATE_DEPTH; + CoglPipeline *authority; + CoglDepthState *orig_state; + + _COGL_GET_CONTEXT (ctx, FALSE); + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), FALSE); + _COGL_RETURN_VAL_IF_FAIL (depth_state->magic == COGL_DEPTH_STATE_MAGIC, FALSE); + + authority = _cogl_pipeline_get_authority (pipeline, state); + + orig_state = &authority->big_state->depth_state; + if (orig_state->test_enabled == depth_state->test_enabled && + orig_state->write_enabled == depth_state->write_enabled && + orig_state->test_function == depth_state->test_function && + orig_state->range_near == depth_state->range_near && + orig_state->range_far == depth_state->range_far) + return TRUE; + + if (ctx->driver == COGL_DRIVER_GLES1 && + (depth_state->range_near != 0 || + depth_state->range_far != 1)) + { + _cogl_set_error (error, + COGL_SYSTEM_ERROR, + COGL_SYSTEM_ERROR_UNSUPPORTED, + "glDepthRange not available on GLES 1"); + return FALSE; + } + + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); + + pipeline->big_state->depth_state = *depth_state; + + _cogl_pipeline_update_authority (pipeline, authority, state, + _cogl_pipeline_depth_state_equal); + + return TRUE; +} + +void +cogl_pipeline_get_depth_state (CoglPipeline *pipeline, + CoglDepthState *state) +{ + CoglPipeline *authority; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_DEPTH); + *state = authority->big_state->depth_state; +} + +CoglColorMask +cogl_pipeline_get_color_mask (CoglPipeline *pipeline) +{ + CoglPipeline *authority; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), 0); + + authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LOGIC_OPS); + + return authority->big_state->logic_ops_state.color_mask; +} + +void +cogl_pipeline_set_color_mask (CoglPipeline *pipeline, + CoglColorMask color_mask) +{ + CoglPipelineState state = COGL_PIPELINE_STATE_LOGIC_OPS; + CoglPipeline *authority; + CoglPipelineLogicOpsState *logic_ops_state; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + authority = _cogl_pipeline_get_authority (pipeline, state); + + logic_ops_state = &authority->big_state->logic_ops_state; + if (logic_ops_state->color_mask == color_mask) + return; + + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); + + logic_ops_state = &pipeline->big_state->logic_ops_state; + logic_ops_state->color_mask = color_mask; + + _cogl_pipeline_update_authority (pipeline, authority, state, + _cogl_pipeline_logic_ops_state_equal); +} + +void +_cogl_pipeline_set_fog_state (CoglPipeline *pipeline, + const CoglPipelineFogState *fog_state) +{ + CoglPipelineState state = COGL_PIPELINE_STATE_FOG; + CoglPipeline *authority; + CoglPipelineFogState *current_fog_state; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + authority = _cogl_pipeline_get_authority (pipeline, state); + + current_fog_state = &authority->big_state->fog_state; + + if (current_fog_state->enabled == fog_state->enabled && + cogl_color_equal (¤t_fog_state->color, &fog_state->color) && + current_fog_state->mode == fog_state->mode && + current_fog_state->density == fog_state->density && + current_fog_state->z_near == fog_state->z_near && + current_fog_state->z_far == fog_state->z_far) + return; + + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); + + pipeline->big_state->fog_state = *fog_state; + + _cogl_pipeline_update_authority (pipeline, authority, state, + _cogl_pipeline_fog_state_equal); +} + +void +cogl_pipeline_set_cull_face_mode (CoglPipeline *pipeline, + CoglPipelineCullFaceMode cull_face_mode) +{ + CoglPipelineState state = COGL_PIPELINE_STATE_CULL_FACE; + CoglPipeline *authority; + CoglPipelineCullFaceState *cull_face_state; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + authority = _cogl_pipeline_get_authority (pipeline, state); + + cull_face_state = &authority->big_state->cull_face_state; + + if (cull_face_state->mode == cull_face_mode) + return; + + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); + + pipeline->big_state->cull_face_state.mode = cull_face_mode; + + _cogl_pipeline_update_authority (pipeline, authority, state, + _cogl_pipeline_cull_face_state_equal); +} + +void +cogl_pipeline_set_front_face_winding (CoglPipeline *pipeline, + CoglWinding front_winding) +{ + CoglPipelineState state = COGL_PIPELINE_STATE_CULL_FACE; + CoglPipeline *authority; + CoglPipelineCullFaceState *cull_face_state; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + authority = _cogl_pipeline_get_authority (pipeline, state); + + cull_face_state = &authority->big_state->cull_face_state; + + if (cull_face_state->front_winding == front_winding) + return; + + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); + + pipeline->big_state->cull_face_state.front_winding = front_winding; + + _cogl_pipeline_update_authority (pipeline, authority, state, + _cogl_pipeline_cull_face_state_equal); +} + +CoglPipelineCullFaceMode +cogl_pipeline_get_cull_face_mode (CoglPipeline *pipeline) +{ + CoglPipelineState state = COGL_PIPELINE_STATE_CULL_FACE; + CoglPipeline *authority; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), + COGL_PIPELINE_CULL_FACE_MODE_NONE); + + authority = _cogl_pipeline_get_authority (pipeline, state); + + return authority->big_state->cull_face_state.mode; +} + +CoglWinding +cogl_pipeline_get_front_face_winding (CoglPipeline *pipeline) +{ + CoglPipelineState state = COGL_PIPELINE_STATE_CULL_FACE; + CoglPipeline *authority; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), + COGL_PIPELINE_CULL_FACE_MODE_NONE); + + authority = _cogl_pipeline_get_authority (pipeline, state); + + return authority->big_state->cull_face_state.front_winding; +} + +float +cogl_pipeline_get_point_size (CoglPipeline *pipeline) +{ + CoglPipeline *authority; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), FALSE); + + authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_POINT_SIZE); + + return authority->big_state->point_size; +} + +static void +_cogl_pipeline_set_non_zero_point_size (CoglPipeline *pipeline, + CoglBool value) +{ + CoglPipelineState state = COGL_PIPELINE_STATE_NON_ZERO_POINT_SIZE; + CoglPipeline *authority; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + authority = _cogl_pipeline_get_authority (pipeline, state); + + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); + + pipeline->big_state->non_zero_point_size = !!value; + + _cogl_pipeline_update_authority (pipeline, authority, state, + _cogl_pipeline_non_zero_point_size_equal); +} + +void +cogl_pipeline_set_point_size (CoglPipeline *pipeline, + float point_size) +{ + CoglPipelineState state = COGL_PIPELINE_STATE_POINT_SIZE; + CoglPipeline *authority; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + authority = _cogl_pipeline_get_authority (pipeline, state); + + if (authority->big_state->point_size == point_size) + return; + + /* Changing the point size may additionally modify + * COGL_PIPELINE_STATE_NON_ZERO_POINT_SIZE. */ + + if ((authority->big_state->point_size > 0.0f) != (point_size > 0.0f)) + _cogl_pipeline_set_non_zero_point_size (pipeline, point_size > 0.0f); + + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); + + pipeline->big_state->point_size = point_size; + + _cogl_pipeline_update_authority (pipeline, authority, state, + _cogl_pipeline_point_size_equal); +} + +CoglBool +cogl_pipeline_set_per_vertex_point_size (CoglPipeline *pipeline, + CoglBool enable, + CoglError **error) +{ + CoglPipelineState state = COGL_PIPELINE_STATE_PER_VERTEX_POINT_SIZE; + CoglPipeline *authority; + + _COGL_GET_CONTEXT (ctx, FALSE); + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), FALSE); + + authority = _cogl_pipeline_get_authority (pipeline, state); + + enable = !!enable; + + if (authority->big_state->per_vertex_point_size == enable) + return TRUE; + + if (enable && !cogl_has_feature (ctx, COGL_FEATURE_ID_PER_VERTEX_POINT_SIZE)) + { + _cogl_set_error (error, + COGL_SYSTEM_ERROR, + COGL_SYSTEM_ERROR_UNSUPPORTED, + "Per-vertex point size is not supported"); + + return FALSE; + } + + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); + + pipeline->big_state->per_vertex_point_size = enable; + + _cogl_pipeline_update_authority (pipeline, authority, state, + _cogl_pipeline_point_size_equal); + + return TRUE; +} + +CoglBool +cogl_pipeline_get_per_vertex_point_size (CoglPipeline *pipeline) +{ + CoglPipeline *authority; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), FALSE); + + authority = + _cogl_pipeline_get_authority (pipeline, + COGL_PIPELINE_STATE_PER_VERTEX_POINT_SIZE); + + return authority->big_state->per_vertex_point_size; +} + +static CoglBoxedValue * +_cogl_pipeline_override_uniform (CoglPipeline *pipeline, + int location) +{ + CoglPipelineState state = COGL_PIPELINE_STATE_UNIFORMS; + CoglPipelineUniformsState *uniforms_state; + int override_index; + + _COGL_GET_CONTEXT (ctx, NULL); + + g_return_val_if_fail (cogl_is_pipeline (pipeline), NULL); + g_return_val_if_fail (location >= 0, NULL); + g_return_val_if_fail (location < ctx->n_uniform_names, NULL); + + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); + + uniforms_state = &pipeline->big_state->uniforms_state; + + /* Count the number of bits that are set below this location. That + should give us the position where our new value should lie */ + override_index = _cogl_bitmask_popcount_upto (&uniforms_state->override_mask, + location); + + _cogl_bitmask_set (&uniforms_state->changed_mask, location, TRUE); + + /* If this pipeline already has an override for this value then we + can just use it directly */ + if (_cogl_bitmask_get (&uniforms_state->override_mask, location)) + return uniforms_state->override_values + override_index; + + /* We need to create a new override value in the right position + within the array. This is pretty inefficient but the hope is that + it will be much more common to modify an existing uniform rather + than modify a new one so it is more important to optimise the + former case. */ + + if (uniforms_state->override_values == NULL) + { + g_assert (override_index == 0); + uniforms_state->override_values = g_new (CoglBoxedValue, 1); + } + else + { + /* We need to grow the array and copy in the old values */ + CoglBoxedValue *old_values = uniforms_state->override_values; + int old_size = _cogl_bitmask_popcount (&uniforms_state->override_mask); + + uniforms_state->override_values = g_new (CoglBoxedValue, old_size + 1); + + /* Copy in the old values leaving a gap for the new value */ + memcpy (uniforms_state->override_values, + old_values, + sizeof (CoglBoxedValue) * override_index); + memcpy (uniforms_state->override_values + override_index + 1, + old_values + override_index, + sizeof (CoglBoxedValue) * (old_size - override_index)); + + g_free (old_values); + } + + _cogl_boxed_value_init (uniforms_state->override_values + override_index); + + _cogl_bitmask_set (&uniforms_state->override_mask, location, TRUE); + + return uniforms_state->override_values + override_index; +} + +void +cogl_pipeline_set_uniform_1f (CoglPipeline *pipeline, + int uniform_location, + float value) +{ + CoglBoxedValue *boxed_value; + + boxed_value = _cogl_pipeline_override_uniform (pipeline, uniform_location); + + _cogl_boxed_value_set_1f (boxed_value, value); +} + +void +cogl_pipeline_set_uniform_1i (CoglPipeline *pipeline, + int uniform_location, + int value) +{ + CoglBoxedValue *boxed_value; + + boxed_value = _cogl_pipeline_override_uniform (pipeline, uniform_location); + + _cogl_boxed_value_set_1i (boxed_value, value); +} + +void +cogl_pipeline_set_uniform_float (CoglPipeline *pipeline, + int uniform_location, + int n_components, + int count, + const float *value) +{ + CoglBoxedValue *boxed_value; + + boxed_value = _cogl_pipeline_override_uniform (pipeline, uniform_location); + + _cogl_boxed_value_set_float (boxed_value, n_components, count, value); +} + +void +cogl_pipeline_set_uniform_int (CoglPipeline *pipeline, + int uniform_location, + int n_components, + int count, + const int *value) +{ + CoglBoxedValue *boxed_value; + + boxed_value = _cogl_pipeline_override_uniform (pipeline, uniform_location); + + _cogl_boxed_value_set_int (boxed_value, n_components, count, value); +} + +void +cogl_pipeline_set_uniform_matrix (CoglPipeline *pipeline, + int uniform_location, + int dimensions, + int count, + CoglBool transpose, + const float *value) +{ + CoglBoxedValue *boxed_value; + + boxed_value = _cogl_pipeline_override_uniform (pipeline, uniform_location); + + _cogl_boxed_value_set_matrix (boxed_value, + dimensions, + count, + transpose, + value); +} + +static void +_cogl_pipeline_add_vertex_snippet (CoglPipeline *pipeline, + CoglSnippet *snippet) +{ + CoglPipelineState state = COGL_PIPELINE_STATE_VERTEX_SNIPPETS; + + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); + + _cogl_pipeline_snippet_list_add (&pipeline->big_state->vertex_snippets, + snippet); +} + +static void +_cogl_pipeline_add_fragment_snippet (CoglPipeline *pipeline, + CoglSnippet *snippet) +{ + CoglPipelineState state = COGL_PIPELINE_STATE_FRAGMENT_SNIPPETS; + + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); + + _cogl_pipeline_snippet_list_add (&pipeline->big_state->fragment_snippets, + snippet); +} + +void +cogl_pipeline_add_snippet (CoglPipeline *pipeline, + CoglSnippet *snippet) +{ + g_return_if_fail (cogl_is_pipeline (pipeline)); + g_return_if_fail (cogl_is_snippet (snippet)); + g_return_if_fail (snippet->hook < COGL_SNIPPET_FIRST_LAYER_HOOK); + + if (snippet->hook < COGL_SNIPPET_FIRST_PIPELINE_FRAGMENT_HOOK) + _cogl_pipeline_add_vertex_snippet (pipeline, snippet); + else + _cogl_pipeline_add_fragment_snippet (pipeline, snippet); +} + +CoglBool +_cogl_pipeline_has_non_layer_vertex_snippets (CoglPipeline *pipeline) +{ + CoglPipeline *authority = + _cogl_pipeline_get_authority (pipeline, + COGL_PIPELINE_STATE_VERTEX_SNIPPETS); + + return authority->big_state->vertex_snippets.entries != NULL; +} + +static CoglBool +check_layer_has_vertex_snippet (CoglPipelineLayer *layer, + void *user_data) +{ + unsigned long state = COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS; + CoglPipelineLayer *authority = + _cogl_pipeline_layer_get_authority (layer, state); + CoglBool *found_vertex_snippet = user_data; + + if (authority->big_state->vertex_snippets.entries) + { + *found_vertex_snippet = TRUE; + return FALSE; + } + + return TRUE; +} + +CoglBool +_cogl_pipeline_has_vertex_snippets (CoglPipeline *pipeline) +{ + CoglBool found_vertex_snippet = FALSE; + + if (_cogl_pipeline_has_non_layer_vertex_snippets (pipeline)) + return TRUE; + + _cogl_pipeline_foreach_layer_internal (pipeline, + check_layer_has_vertex_snippet, + &found_vertex_snippet); + + return found_vertex_snippet; +} + +CoglBool +_cogl_pipeline_has_non_layer_fragment_snippets (CoglPipeline *pipeline) +{ + CoglPipeline *authority = + _cogl_pipeline_get_authority (pipeline, + COGL_PIPELINE_STATE_FRAGMENT_SNIPPETS); + + return authority->big_state->fragment_snippets.entries != NULL; +} + +static CoglBool +check_layer_has_fragment_snippet (CoglPipelineLayer *layer, + void *user_data) +{ + unsigned long state = COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS; + CoglPipelineLayer *authority = + _cogl_pipeline_layer_get_authority (layer, state); + CoglBool *found_fragment_snippet = user_data; + + if (authority->big_state->fragment_snippets.entries) + { + *found_fragment_snippet = TRUE; + return FALSE; + } + + return TRUE; +} + +CoglBool +_cogl_pipeline_has_fragment_snippets (CoglPipeline *pipeline) +{ + CoglBool found_fragment_snippet = FALSE; + + if (_cogl_pipeline_has_non_layer_fragment_snippets (pipeline)) + return TRUE; + + _cogl_pipeline_foreach_layer_internal (pipeline, + check_layer_has_fragment_snippet, + &found_fragment_snippet); + + return found_fragment_snippet; +} + +void +_cogl_pipeline_hash_color_state (CoglPipeline *authority, + CoglPipelineHashState *state) +{ + state->hash = _cogl_util_one_at_a_time_hash (state->hash, &authority->color, + _COGL_COLOR_DATA_SIZE); +} + +void +_cogl_pipeline_hash_blend_enable_state (CoglPipeline *authority, + CoglPipelineHashState *state) +{ + uint8_t blend_enable = authority->blend_enable; + state->hash = _cogl_util_one_at_a_time_hash (state->hash, &blend_enable, 1); +} + +void +_cogl_pipeline_hash_lighting_state (CoglPipeline *authority, + CoglPipelineHashState *state) +{ + CoglPipelineLightingState *lighting_state = + &authority->big_state->lighting_state; + state->hash = + _cogl_util_one_at_a_time_hash (state->hash, lighting_state, + sizeof (CoglPipelineLightingState)); +} + +void +_cogl_pipeline_hash_alpha_func_state (CoglPipeline *authority, + CoglPipelineHashState *state) +{ + CoglPipelineAlphaFuncState *alpha_state = &authority->big_state->alpha_state; + state->hash = + _cogl_util_one_at_a_time_hash (state->hash, &alpha_state->alpha_func, + sizeof (alpha_state->alpha_func)); +} + +void +_cogl_pipeline_hash_alpha_func_reference_state (CoglPipeline *authority, + CoglPipelineHashState *state) +{ + CoglPipelineAlphaFuncState *alpha_state = &authority->big_state->alpha_state; + float ref = alpha_state->alpha_func_reference; + state->hash = + _cogl_util_one_at_a_time_hash (state->hash, &ref, sizeof (float)); +} + +void +_cogl_pipeline_hash_blend_state (CoglPipeline *authority, + CoglPipelineHashState *state) +{ + CoglPipelineBlendState *blend_state = &authority->big_state->blend_state; + unsigned int hash; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (!authority->real_blend_enable) + return; + + hash = state->hash; + + hash = + _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_equation_rgb, + sizeof (blend_state->blend_equation_rgb)); + hash = + _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_equation_alpha, + sizeof (blend_state->blend_equation_alpha)); + hash = + _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_src_factor_alpha, + sizeof (blend_state->blend_src_factor_alpha)); + hash = + _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_dst_factor_alpha, + sizeof (blend_state->blend_dst_factor_alpha)); + + if (blend_state->blend_src_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR || + blend_state->blend_src_factor_rgb == GL_CONSTANT_COLOR || + blend_state->blend_dst_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR || + blend_state->blend_dst_factor_rgb == GL_CONSTANT_COLOR) + { + hash = + _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_constant, + sizeof (blend_state->blend_constant)); + } + + hash = + _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_src_factor_rgb, + sizeof (blend_state->blend_src_factor_rgb)); + hash = + _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_dst_factor_rgb, + sizeof (blend_state->blend_dst_factor_rgb)); + + state->hash = hash; +} + +void +_cogl_pipeline_hash_user_shader_state (CoglPipeline *authority, + CoglPipelineHashState *state) +{ + CoglHandle user_program = authority->big_state->user_program; + state->hash = _cogl_util_one_at_a_time_hash (state->hash, &user_program, + sizeof (user_program)); +} + +void +_cogl_pipeline_hash_depth_state (CoglPipeline *authority, + CoglPipelineHashState *state) +{ + CoglDepthState *depth_state = &authority->big_state->depth_state; + unsigned int hash = state->hash; + + if (depth_state->test_enabled) + { + uint8_t enabled = depth_state->test_enabled; + CoglDepthTestFunction function = depth_state->test_function; + hash = _cogl_util_one_at_a_time_hash (hash, &enabled, sizeof (enabled)); + hash = _cogl_util_one_at_a_time_hash (hash, &function, sizeof (function)); + } + + if (depth_state->write_enabled) + { + uint8_t enabled = depth_state->write_enabled; + float near_val = depth_state->range_near; + float far_val = depth_state->range_far; + hash = _cogl_util_one_at_a_time_hash (hash, &enabled, sizeof (enabled)); + hash = _cogl_util_one_at_a_time_hash (hash, &near_val, sizeof (near_val)); + hash = _cogl_util_one_at_a_time_hash (hash, &far_val, sizeof (far_val)); + } + + state->hash = hash; +} + +void +_cogl_pipeline_hash_fog_state (CoglPipeline *authority, + CoglPipelineHashState *state) +{ + CoglPipelineFogState *fog_state = &authority->big_state->fog_state; + unsigned long hash = state->hash; + + if (!fog_state->enabled) + hash = _cogl_util_one_at_a_time_hash (hash, &fog_state->enabled, + sizeof (fog_state->enabled)); + else + hash = _cogl_util_one_at_a_time_hash (hash, &fog_state, + sizeof (CoglPipelineFogState)); + + state->hash = hash; +} + +void +_cogl_pipeline_hash_non_zero_point_size_state (CoglPipeline *authority, + CoglPipelineHashState *state) +{ + CoglBool non_zero_point_size = authority->big_state->non_zero_point_size; + + state->hash = _cogl_util_one_at_a_time_hash (state->hash, + &non_zero_point_size, + sizeof (non_zero_point_size)); +} + +void +_cogl_pipeline_hash_point_size_state (CoglPipeline *authority, + CoglPipelineHashState *state) +{ + float point_size = authority->big_state->point_size; + state->hash = _cogl_util_one_at_a_time_hash (state->hash, &point_size, + sizeof (point_size)); +} + +void +_cogl_pipeline_hash_per_vertex_point_size_state (CoglPipeline *authority, + CoglPipelineHashState *state) +{ + CoglBool per_vertex_point_size = authority->big_state->per_vertex_point_size; + state->hash = _cogl_util_one_at_a_time_hash (state->hash, + &per_vertex_point_size, + sizeof (per_vertex_point_size)); +} + +void +_cogl_pipeline_hash_logic_ops_state (CoglPipeline *authority, + CoglPipelineHashState *state) +{ + CoglPipelineLogicOpsState *logic_ops_state = &authority->big_state->logic_ops_state; + state->hash = _cogl_util_one_at_a_time_hash (state->hash, &logic_ops_state->color_mask, + sizeof (CoglColorMask)); +} + +void +_cogl_pipeline_hash_cull_face_state (CoglPipeline *authority, + CoglPipelineHashState *state) +{ + CoglPipelineCullFaceState *cull_face_state + = &authority->big_state->cull_face_state; + + /* The cull face state is considered equal if two pipelines are both + set to no culling. If the front winding property is ever used for + anything else or the hashing is used not just for drawing then + this would have to change */ + if (cull_face_state->mode == COGL_PIPELINE_CULL_FACE_MODE_NONE) + state->hash = + _cogl_util_one_at_a_time_hash (state->hash, + &cull_face_state->mode, + sizeof (CoglPipelineCullFaceMode)); + else + state->hash = + _cogl_util_one_at_a_time_hash (state->hash, + cull_face_state, + sizeof (CoglPipelineCullFaceState)); +} + +void +_cogl_pipeline_hash_uniforms_state (CoglPipeline *authority, + CoglPipelineHashState *state) +{ + /* This isn't used anywhere yet because the uniform state doesn't + affect program generation. It's quite a hassle to implement so + let's just leave it until something actually needs it */ + g_warn_if_reached (); +} + +void +_cogl_pipeline_compare_uniform_differences (unsigned long *differences, + CoglPipeline *pipeline0, + CoglPipeline *pipeline1) +{ + GSList *head0 = NULL; + GSList *head1 = NULL; + CoglPipeline *node0; + CoglPipeline *node1; + int len0 = 0; + int len1 = 0; + int count; + GSList *common_ancestor0; + GSList *common_ancestor1; + + /* This algorithm is copied from + _cogl_pipeline_compare_differences(). It might be nice to share + the code more */ + + for (node0 = pipeline0; node0; node0 = _cogl_pipeline_get_parent (node0)) + { + GSList *link = alloca (sizeof (GSList)); + link->next = head0; + link->data = node0; + head0 = link; + len0++; + } + for (node1 = pipeline1; node1; node1 = _cogl_pipeline_get_parent (node1)) + { + GSList *link = alloca (sizeof (GSList)); + link->next = head1; + link->data = node1; + head1 = link; + len1++; + } + + /* NB: There's no point looking at the head entries since we know both + * pipelines must have the same default pipeline as their root node. */ + common_ancestor0 = head0; + common_ancestor1 = head1; + head0 = head0->next; + head1 = head1->next; + count = MIN (len0, len1) - 1; + while (count--) + { + if (head0->data != head1->data) + break; + common_ancestor0 = head0; + common_ancestor1 = head1; + head0 = head0->next; + head1 = head1->next; + } + + for (head0 = common_ancestor0->next; head0; head0 = head0->next) + { + node0 = head0->data; + if ((node0->differences & COGL_PIPELINE_STATE_UNIFORMS)) + { + const CoglPipelineUniformsState *uniforms_state = + &node0->big_state->uniforms_state; + _cogl_bitmask_set_flags (&uniforms_state->override_mask, + differences); + } + } + for (head1 = common_ancestor1->next; head1; head1 = head1->next) + { + node1 = head1->data; + if ((node1->differences & COGL_PIPELINE_STATE_UNIFORMS)) + { + const CoglPipelineUniformsState *uniforms_state = + &node1->big_state->uniforms_state; + _cogl_bitmask_set_flags (&uniforms_state->override_mask, + differences); + } + } +} + +void +_cogl_pipeline_hash_vertex_snippets_state (CoglPipeline *authority, + CoglPipelineHashState *state) +{ + _cogl_pipeline_snippet_list_hash (&authority->big_state->vertex_snippets, + &state->hash); +} + +void +_cogl_pipeline_hash_fragment_snippets_state (CoglPipeline *authority, + CoglPipelineHashState *state) +{ + _cogl_pipeline_snippet_list_hash (&authority->big_state->fragment_snippets, + &state->hash); +} + +UNIT_TEST (check_blend_constant_ancestry, + 0 /* no requirements */, + 0 /* no known failures */) +{ + CoglPipeline *pipeline = cogl_pipeline_new (test_ctx); + CoglNode *node; + int pipeline_length = 0; + int i; + + /* Repeatedly making a copy of a pipeline and changing the same + * state (in this case the blend constant) shouldn't cause a long + * chain of pipelines to be created because the redundant ancestry + * should be pruned. */ + + for (i = 0; i < 20; i++) + { + CoglColor color; + CoglPipeline *tmp_pipeline; + + cogl_color_init_from_4f (&color, i / 20.0f, 0.0f, 0.0f, 1.0f); + + tmp_pipeline = cogl_pipeline_copy (pipeline); + cogl_object_unref (pipeline); + pipeline = tmp_pipeline; + + cogl_pipeline_set_blend_constant (pipeline, &color); + } + + for (node = (CoglNode *) pipeline; node; node = node->parent) + pipeline_length++; + + g_assert_cmpint (pipeline_length, <=, 2); + + cogl_object_unref (pipeline); +} + +UNIT_TEST (check_uniform_ancestry, + 0 /* no requirements */, + TEST_KNOWN_FAILURE) +{ + CoglPipeline *pipeline = cogl_pipeline_new (test_ctx); + CoglNode *node; + int pipeline_length = 0; + int i; + + /* Repeatedly making a copy of a pipeline and changing a uniform + * shouldn't cause a long chain of pipelines to be created */ + + for (i = 0; i < 20; i++) + { + CoglPipeline *tmp_pipeline; + int uniform_location; + + tmp_pipeline = cogl_pipeline_copy (pipeline); + cogl_object_unref (pipeline); + pipeline = tmp_pipeline; + + uniform_location = + cogl_pipeline_get_uniform_location (pipeline, "a_uniform"); + + cogl_pipeline_set_uniform_1i (pipeline, uniform_location, i); + } + + for (node = (CoglNode *) pipeline; node; node = node->parent) + pipeline_length++; + + g_assert_cmpint (pipeline_length, <=, 2); + + cogl_object_unref (pipeline); +} diff --git a/cogl/cogl/cogl-pipeline-state.h b/cogl/cogl/cogl-pipeline-state.h new file mode 100644 index 0000000..67e6ef8 --- /dev/null +++ b/cogl/cogl/cogl-pipeline-state.h @@ -0,0 +1,976 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_PIPELINE_STATE_H__ +#define __COGL_PIPELINE_STATE_H__ + +#include +#include +#include + +COGL_BEGIN_DECLS + +/** + * cogl_pipeline_set_color: + * @pipeline: A #CoglPipeline object + * @color: The components of the color + * + * Sets the basic color of the pipeline, used when no lighting is enabled. + * + * Note that if you don't add any layers to the pipeline then the color + * will be blended unmodified with the destination; the default blend + * expects premultiplied colors: for example, use (0.5, 0.0, 0.0, 0.5) for + * semi-transparent red. See cogl_color_premultiply(). + * + * The default value is (1.0, 1.0, 1.0, 1.0) + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_pipeline_set_color (CoglPipeline *pipeline, + const CoglColor *color); + +/** + * cogl_pipeline_set_color4ub: + * @pipeline: A #CoglPipeline object + * @red: The red component + * @green: The green component + * @blue: The blue component + * @alpha: The alpha component + * + * Sets the basic color of the pipeline, used when no lighting is enabled. + * + * The default value is (0xff, 0xff, 0xff, 0xff) + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_pipeline_set_color4ub (CoglPipeline *pipeline, + uint8_t red, + uint8_t green, + uint8_t blue, + uint8_t alpha); + +/** + * cogl_pipeline_set_color4f: + * @pipeline: A #CoglPipeline object + * @red: The red component + * @green: The green component + * @blue: The blue component + * @alpha: The alpha component + * + * Sets the basic color of the pipeline, used when no lighting is enabled. + * + * The default value is (1.0, 1.0, 1.0, 1.0) + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_pipeline_set_color4f (CoglPipeline *pipeline, + float red, + float green, + float blue, + float alpha); + +/** + * cogl_pipeline_get_color: + * @pipeline: A #CoglPipeline object + * @color: (out): The location to store the color + * + * Retrieves the current pipeline color. + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_pipeline_get_color (CoglPipeline *pipeline, + CoglColor *color); + +/** + * cogl_pipeline_set_ambient: + * @pipeline: A #CoglPipeline object + * @ambient: The components of the desired ambient color + * + * Sets the pipeline's ambient color, in the standard OpenGL lighting + * model. The ambient color affects the overall color of the object. + * + * Since the diffuse color will be intense when the light hits the surface + * directly, the ambient will be most apparent where the light hits at a + * slant. + * + * The default value is (0.2, 0.2, 0.2, 1.0) + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_pipeline_set_ambient (CoglPipeline *pipeline, + const CoglColor *ambient); + +/** + * cogl_pipeline_get_ambient: + * @pipeline: A #CoglPipeline object + * @ambient: The location to store the ambient color + * + * Retrieves the current ambient color for @pipeline + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_pipeline_get_ambient (CoglPipeline *pipeline, + CoglColor *ambient); + +/** + * cogl_pipeline_set_diffuse: + * @pipeline: A #CoglPipeline object + * @diffuse: The components of the desired diffuse color + * + * Sets the pipeline's diffuse color, in the standard OpenGL lighting + * model. The diffuse color is most intense where the light hits the + * surface directly - perpendicular to the surface. + * + * The default value is (0.8, 0.8, 0.8, 1.0) + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_pipeline_set_diffuse (CoglPipeline *pipeline, + const CoglColor *diffuse); + +/** + * cogl_pipeline_get_diffuse: + * @pipeline: A #CoglPipeline object + * @diffuse: The location to store the diffuse color + * + * Retrieves the current diffuse color for @pipeline + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_pipeline_get_diffuse (CoglPipeline *pipeline, + CoglColor *diffuse); + +/** + * cogl_pipeline_set_ambient_and_diffuse: + * @pipeline: A #CoglPipeline object + * @color: The components of the desired ambient and diffuse colors + * + * Conveniently sets the diffuse and ambient color of @pipeline at the same + * time. See cogl_pipeline_set_ambient() and cogl_pipeline_set_diffuse(). + * + * The default ambient color is (0.2, 0.2, 0.2, 1.0) + * + * The default diffuse color is (0.8, 0.8, 0.8, 1.0) + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_pipeline_set_ambient_and_diffuse (CoglPipeline *pipeline, + const CoglColor *color); + +/** + * cogl_pipeline_set_specular: + * @pipeline: A #CoglPipeline object + * @specular: The components of the desired specular color + * + * Sets the pipeline's specular color, in the standard OpenGL lighting + * model. The intensity of the specular color depends on the viewport + * position, and is brightest along the lines of reflection. + * + * The default value is (0.0, 0.0, 0.0, 1.0) + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_pipeline_set_specular (CoglPipeline *pipeline, + const CoglColor *specular); + +/** + * cogl_pipeline_get_specular: + * @pipeline: A #CoglPipeline object + * @specular: The location to store the specular color + * + * Retrieves the pipelines current specular color. + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_pipeline_get_specular (CoglPipeline *pipeline, + CoglColor *specular); + +/** + * cogl_pipeline_set_shininess: + * @pipeline: A #CoglPipeline object + * @shininess: The desired shininess; must be >= 0.0 + * + * Sets the shininess of the pipeline, in the standard OpenGL lighting + * model, which determines the size of the specular highlights. A + * higher @shininess will produce smaller highlights which makes the + * object appear more shiny. + * + * The default value is 0.0 + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_pipeline_set_shininess (CoglPipeline *pipeline, + float shininess); + +/** + * cogl_pipeline_get_shininess: + * @pipeline: A #CoglPipeline object + * + * Retrieves the pipelines current emission color. + * + * Return value: The pipelines current shininess value + * + * Since: 2.0 + * Stability: Unstable + */ +float +cogl_pipeline_get_shininess (CoglPipeline *pipeline); + +/** + * cogl_pipeline_set_emission: + * @pipeline: A #CoglPipeline object + * @emission: The components of the desired emissive color + * + * Sets the pipeline's emissive color, in the standard OpenGL lighting + * model. It will look like the surface is a light source emitting this + * color. + * + * The default value is (0.0, 0.0, 0.0, 1.0) + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_pipeline_set_emission (CoglPipeline *pipeline, + const CoglColor *emission); + +/** + * cogl_pipeline_get_emission: + * @pipeline: A #CoglPipeline object + * @emission: The location to store the emission color + * + * Retrieves the pipelines current emission color. + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_pipeline_get_emission (CoglPipeline *pipeline, + CoglColor *emission); + +/** + * CoglPipelineAlphaFunc: + * @COGL_PIPELINE_ALPHA_FUNC_NEVER: Never let the fragment through. + * @COGL_PIPELINE_ALPHA_FUNC_LESS: Let the fragment through if the incoming + * alpha value is less than the reference alpha value + * @COGL_PIPELINE_ALPHA_FUNC_EQUAL: Let the fragment through if the incoming + * alpha value equals the reference alpha value + * @COGL_PIPELINE_ALPHA_FUNC_LEQUAL: Let the fragment through if the incoming + * alpha value is less than or equal to the reference alpha value + * @COGL_PIPELINE_ALPHA_FUNC_GREATER: Let the fragment through if the incoming + * alpha value is greater than the reference alpha value + * @COGL_PIPELINE_ALPHA_FUNC_NOTEQUAL: Let the fragment through if the incoming + * alpha value does not equal the reference alpha value + * @COGL_PIPELINE_ALPHA_FUNC_GEQUAL: Let the fragment through if the incoming + * alpha value is greater than or equal to the reference alpha value. + * @COGL_PIPELINE_ALPHA_FUNC_ALWAYS: Always let the fragment through. + * + * Alpha testing happens before blending primitives with the framebuffer and + * gives an opportunity to discard fragments based on a comparison with the + * incoming alpha value and a reference alpha value. The #CoglPipelineAlphaFunc + * determines how the comparison is done. + */ +typedef enum { + COGL_PIPELINE_ALPHA_FUNC_NEVER = 0x0200, + COGL_PIPELINE_ALPHA_FUNC_LESS = 0x0201, + COGL_PIPELINE_ALPHA_FUNC_EQUAL = 0x0202, + COGL_PIPELINE_ALPHA_FUNC_LEQUAL = 0x0203, + COGL_PIPELINE_ALPHA_FUNC_GREATER = 0x0204, + COGL_PIPELINE_ALPHA_FUNC_NOTEQUAL = 0x0205, + COGL_PIPELINE_ALPHA_FUNC_GEQUAL = 0x0206, + COGL_PIPELINE_ALPHA_FUNC_ALWAYS = 0x0207 +} CoglPipelineAlphaFunc; +/* NB: these values come from the equivalents in gl.h */ + +/** + * cogl_pipeline_set_alpha_test_function: + * @pipeline: A #CoglPipeline object + * @alpha_func: A @CoglPipelineAlphaFunc constant + * @alpha_reference: A reference point that the chosen alpha function uses + * to compare incoming fragments to. + * + * Before a primitive is blended with the framebuffer, it goes through an + * alpha test stage which lets you discard fragments based on the current + * alpha value. This function lets you change the function used to evaluate + * the alpha channel, and thus determine which fragments are discarded + * and which continue on to the blending stage. + * + * The default is %COGL_PIPELINE_ALPHA_FUNC_ALWAYS + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_pipeline_set_alpha_test_function (CoglPipeline *pipeline, + CoglPipelineAlphaFunc alpha_func, + float alpha_reference); + +/** + * cogl_pipeline_get_alpha_test_function: + * @pipeline: A #CoglPipeline object + * + * Return value: The alpha test function of @pipeline. + * + * Since: 2.0 + * Stability: Unstable + */ +CoglPipelineAlphaFunc +cogl_pipeline_get_alpha_test_function (CoglPipeline *pipeline); + +/** + * cogl_pipeline_get_alpha_test_reference: + * @pipeline: A #CoglPipeline object + * + * Return value: The alpha test reference value of @pipeline. + * + * Since: 2.0 + * Stability: Unstable + */ +float +cogl_pipeline_get_alpha_test_reference (CoglPipeline *pipeline); + +/** + * cogl_pipeline_set_blend: + * @pipeline: A #CoglPipeline object + * @blend_string: A Cogl blend string + * describing the desired blend function. + * @error: return location for a #CoglError that may report lack of driver + * support if you give separate blend string statements for the alpha + * channel and RGB channels since some drivers, or backends such as + * GLES 1.1, don't support this feature. May be %NULL, in which case a + * warning will be printed out using GLib's logging facilities if an + * error is encountered. + * + * If not already familiar; please refer here + * for an overview of what blend strings are, and their syntax. + * + * Blending occurs after the alpha test function, and combines fragments with + * the framebuffer. + + * Currently the only blend function Cogl exposes is ADD(). So any valid + * blend statements will be of the form: + * + * |[ + * <channel-mask>=ADD(SRC_COLOR*(<factor>), DST_COLOR*(<factor>)) + * ]| + * + * This is the list of source-names usable as blend factors: + * + * SRC_COLOR: The color of the in comming fragment + * DST_COLOR: The color of the framebuffer + * CONSTANT: The constant set via cogl_pipeline_set_blend_constant() + * + * + * The source names can be used according to the + * color-source and factor syntax, + * so for example "(1-SRC_COLOR[A])" would be a valid factor, as would + * "(CONSTANT[RGB])" + * + * These can also be used as factors: + * + * 0: (0, 0, 0, 0) + * 1: (1, 1, 1, 1) + * SRC_ALPHA_SATURATE_FACTOR: (f,f,f,1) where f = MIN(SRC_COLOR[A],1-DST_COLOR[A]) + * + * + * Remember; all color components are normalized to the range [0, 1] + * before computing the result of blending. + * + * + * Blend Strings/1 + * Blend a non-premultiplied source over a destination with + * premultiplied alpha: + * + * "RGB = ADD(SRC_COLOR*(SRC_COLOR[A]), DST_COLOR*(1-SRC_COLOR[A]))" + * "A = ADD(SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))" + * + * + * + * + * Blend Strings/2 + * Blend a premultiplied source over a destination with + * premultiplied alpha + * + * "RGBA = ADD(SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))" + * + * + * + * The default blend string is: + * |[ + * RGBA = ADD (SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A])) + * ]| + * + * That gives normal alpha-blending when the calculated color for the pipeline + * is in premultiplied form. + * + * Return value: %TRUE if the blend string was successfully parsed, and the + * described blending is supported by the underlying driver/hardware. If + * there was an error, %FALSE is returned and @error is set accordingly (if + * present). + * + * Since: 2.0 + * Stability: Unstable + */ +CoglBool +cogl_pipeline_set_blend (CoglPipeline *pipeline, + const char *blend_string, + CoglError **error); + +/** + * cogl_pipeline_set_blend_constant: + * @pipeline: A #CoglPipeline object + * @constant_color: The constant color you want + * + * When blending is setup to reference a CONSTANT blend factor then + * blending will depend on the constant set with this function. + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_pipeline_set_blend_constant (CoglPipeline *pipeline, + const CoglColor *constant_color); + +/** + * cogl_pipeline_set_point_size: + * @pipeline: a #CoglPipeline pointer + * @point_size: the new point size. + * + * Changes the size of points drawn when %COGL_VERTICES_MODE_POINTS is + * used with the attribute buffer API. Note that typically the GPU + * will only support a limited minimum and maximum range of point + * sizes. If the chosen point size is outside that range then the + * nearest value within that range will be used instead. The size of a + * point is in screen space so it will be the same regardless of any + * transformations. + * + * If the point size is set to 0.0 then drawing points with the + * pipeline will have undefined results. This is the default value so + * if an application wants to draw points it must make sure to use a + * pipeline that has an explicit point size set on it. + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_pipeline_set_point_size (CoglPipeline *pipeline, + float point_size); + +/** + * cogl_pipeline_get_point_size: + * @pipeline: a #CoglPipeline pointer + * + * Get the size of points drawn when %COGL_VERTICES_MODE_POINTS is + * used with the vertex buffer API. + * + * Return value: the point size of the @pipeline. + * + * Since: 2.0 + * Stability: Unstable + */ +float +cogl_pipeline_get_point_size (CoglPipeline *pipeline); + +/** + * cogl_pipeline_set_per_vertex_point_size: + * @pipeline: a #CoglPipeline pointer + * @enable: whether to enable per-vertex point size + * @error: a location to store a #CoglError if the change failed + * + * Sets whether to use a per-vertex point size or to use the value set + * by cogl_pipeline_set_point_size(). If per-vertex point size is + * enabled then the point size can be set for an individual point + * either by drawing with a #CoglAttribute with the name + * ‘cogl_point_size_in’ or by writing to the GLSL builtin + * ‘cogl_point_size_out’ from a vertex shader snippet. + * + * If per-vertex point size is enabled and this attribute is not used + * and cogl_point_size_out is not written to then the results are + * undefined. + * + * Note that enabling this will only work if the + * %COGL_FEATURE_ID_PER_VERTEX_POINT_SIZE feature is available. If + * this is not available then the function will return %FALSE and set + * a #CoglError. + * + * Since: 2.0 + * Stability: Unstable + * Return value: %TRUE if the change suceeded or %FALSE otherwise + */ +CoglBool +cogl_pipeline_set_per_vertex_point_size (CoglPipeline *pipeline, + CoglBool enable, + CoglError **error); + +/** + * cogl_pipeline_get_per_vertex_point_size: + * @pipeline: a #CoglPipeline pointer + * + * Since: 2.0 + * Stability: Unstable + * Return value: %TRUE if the pipeline has per-vertex point size + * enabled or %FALSE otherwise. The per-vertex point size can be + * enabled with cogl_pipeline_set_per_vertex_point_size(). + */ +CoglBool +cogl_pipeline_get_per_vertex_point_size (CoglPipeline *pipeline); + +/** + * cogl_pipeline_get_color_mask: + * @pipeline: a #CoglPipeline object. + * + * Gets the current #CoglColorMask of which channels would be written to the + * current framebuffer. Each bit set in the mask means that the + * corresponding color would be written. + * + * Returns: A #CoglColorMask + * Since: 1.8 + * Stability: unstable + */ +CoglColorMask +cogl_pipeline_get_color_mask (CoglPipeline *pipeline); + +/** + * cogl_pipeline_set_color_mask: + * @pipeline: a #CoglPipeline object. + * @color_mask: A #CoglColorMask of which color channels to write to + * the current framebuffer. + * + * Defines a bit mask of which color channels should be written to the + * current framebuffer. If a bit is set in @color_mask that means that + * color will be written. + * + * Since: 1.8 + * Stability: unstable + */ +void +cogl_pipeline_set_color_mask (CoglPipeline *pipeline, + CoglColorMask color_mask); + +/** + * cogl_pipeline_get_user_program: + * @pipeline: a #CoglPipeline object. + * + * Queries what user program has been associated with the given + * @pipeline using cogl_pipeline_set_user_program(). + * + * Return value: (transfer none): The current user program or %COGL_INVALID_HANDLE. + * + * Since: 2.0 + * Stability: Unstable + */ +CoglHandle +cogl_pipeline_get_user_program (CoglPipeline *pipeline); + +/** + * cogl_pipeline_set_user_program: + * @pipeline: a #CoglPipeline object. + * @program: A #CoglHandle to a linked CoglProgram + * + * Associates a linked CoglProgram with the given pipeline so that the + * program can take full control of vertex and/or fragment processing. + * + * This is an example of how it can be used to associate an ARBfp + * program with a #CoglPipeline: + * |[ + * CoglHandle shader; + * CoglHandle program; + * CoglPipeline *pipeline; + * + * shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT); + * cogl_shader_source (shader, + * "!!ARBfp1.0\n" + * "MOV result.color,fragment.color;\n" + * "END\n"); + * cogl_shader_compile (shader); + * + * program = cogl_create_program (); + * cogl_program_attach_shader (program, shader); + * cogl_program_link (program); + * + * pipeline = cogl_pipeline_new (); + * cogl_pipeline_set_user_program (pipeline, program); + * + * cogl_set_source_color4ub (0xff, 0x00, 0x00, 0xff); + * cogl_rectangle (0, 0, 100, 100); + * ]| + * + * It is possibly worth keeping in mind that this API is not part of + * the long term design for how we want to expose shaders to Cogl + * developers (We are planning on deprecating the cogl_program and + * cogl_shader APIs in favour of a "snippet" framework) but in the + * meantime we hope this will handle most practical GLSL and ARBfp + * requirements. + * + * Also remember you need to check for either the + * %COGL_FEATURE_SHADERS_GLSL or %COGL_FEATURE_SHADERS_ARBFP before + * using the cogl_program or cogl_shader API. + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_pipeline_set_user_program (CoglPipeline *pipeline, + CoglHandle program); + +/** + * cogl_pipeline_set_depth_state: + * @pipeline: A #CoglPipeline object + * @state: A #CoglDepthState struct + * @error: A #CoglError to report failures to setup the given @state. + * + * This commits all the depth state configured in @state struct to the + * given @pipeline. The configuration values are copied into the + * pipeline so there is no requirement to keep the #CoglDepthState + * struct around if you don't need it any more. + * + * Note: Since some platforms do not support the depth range feature + * it is possible for this function to fail and report an @error. + * + * Returns: TRUE if the GPU supports all the given @state else %FALSE + * and returns an @error. + * + * Since: 2.0 + * Stability: Unstable + */ +CoglBool +cogl_pipeline_set_depth_state (CoglPipeline *pipeline, + const CoglDepthState *state, + CoglError **error); + +/** + * cogl_pipeline_get_depth_state: + * @pipeline: A #CoglPipeline object + * @state_out: (out): A destination #CoglDepthState struct + * + * Retrieves the current depth state configuration for the given + * @pipeline as previously set using cogl_pipeline_set_depth_state(). + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_pipeline_get_depth_state (CoglPipeline *pipeline, + CoglDepthState *state_out); + +/** + * CoglPipelineCullFaceMode: + * @COGL_PIPELINE_CULL_FACE_MODE_NONE: Neither face will be + * culled. This is the default. + * @COGL_PIPELINE_CULL_FACE_MODE_FRONT: Front faces will be culled. + * @COGL_PIPELINE_CULL_FACE_MODE_BACK: Back faces will be culled. + * @COGL_PIPELINE_CULL_FACE_MODE_BOTH: All faces will be culled. + * + * Specifies which faces should be culled. This can be set on a + * pipeline using cogl_pipeline_set_cull_face_mode(). + */ +typedef enum +{ + COGL_PIPELINE_CULL_FACE_MODE_NONE, + COGL_PIPELINE_CULL_FACE_MODE_FRONT, + COGL_PIPELINE_CULL_FACE_MODE_BACK, + COGL_PIPELINE_CULL_FACE_MODE_BOTH +} CoglPipelineCullFaceMode; + +/** + * cogl_pipeline_set_cull_face_mode: + * @pipeline: A #CoglPipeline + * @cull_face_mode: The new mode to set + * + * Sets which faces will be culled when drawing. Face culling can be + * used to increase efficiency by avoiding drawing faces that would + * get overridden. For example, if a model has gaps so that it is + * impossible to see the inside then faces which are facing away from + * the screen will never be seen so there is no point in drawing + * them. This can be acheived by setting the cull face mode to + * %COGL_PIPELINE_CULL_FACE_MODE_BACK. + * + * Face culling relies on the primitives being drawn with a specific + * order to represent which faces are facing inside and outside the + * model. This order can be specified by calling + * cogl_pipeline_set_front_face_winding(). + * + * Status: Unstable + * Since: 2.0 + */ +void +cogl_pipeline_set_cull_face_mode (CoglPipeline *pipeline, + CoglPipelineCullFaceMode cull_face_mode); + +/** + * cogl_pipeline_get_cull_face_mode: + * + * Return value: the cull face mode that was previously set with + * cogl_pipeline_set_cull_face_mode(). + * + * Status: Unstable + * Since: 2.0 + */ +CoglPipelineCullFaceMode +cogl_pipeline_get_cull_face_mode (CoglPipeline *pipeline); + +/** + * cogl_pipeline_set_front_face_winding: + * @pipeline: a #CoglPipeline + * @front_winding: the winding order + * + * The order of the vertices within a primitive specifies whether it + * is considered to be front or back facing. This function specifies + * which order is considered to be the front + * faces. %COGL_WINDING_COUNTER_CLOCKWISE sets the front faces to + * primitives with vertices in a counter-clockwise order and + * %COGL_WINDING_CLOCKWISE sets them to be clockwise. The default is + * %COGL_WINDING_COUNTER_CLOCKWISE. + * + * Status: Unstable + * Since: 2.0 + */ +void +cogl_pipeline_set_front_face_winding (CoglPipeline *pipeline, + CoglWinding front_winding); + +/** + * cogl_pipeline_get_front_face_winding: + * @pipeline: a #CoglPipeline + * + * The order of the vertices within a primitive specifies whether it + * is considered to be front or back facing. This function specifies + * which order is considered to be the front + * faces. %COGL_WINDING_COUNTER_CLOCKWISE sets the front faces to + * primitives with vertices in a counter-clockwise order and + * %COGL_WINDING_CLOCKWISE sets them to be clockwise. The default is + * %COGL_WINDING_COUNTER_CLOCKWISE. + * + * Returns: The @pipeline front face winding + * + * Status: Unstable + * Since: 2.0 + */ +CoglWinding +cogl_pipeline_get_front_face_winding (CoglPipeline *pipeline); + +/** + * cogl_pipeline_set_uniform_1f: + * @pipeline: A #CoglPipeline object + * @uniform_location: The uniform's location identifier + * @value: The new value for the uniform + * + * Sets a new value for the uniform at @uniform_location. If this + * pipeline has a user program attached and is later used as a source + * for drawing, the given value will be assigned to the uniform which + * can be accessed from the shader's source. The value for + * @uniform_location should be retrieved from the string name of the + * uniform by calling cogl_pipeline_get_uniform_location(). + * + * This function should be used to set uniforms that are of type + * float. It can also be used to set a single member of a float array + * uniform. + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_pipeline_set_uniform_1f (CoglPipeline *pipeline, + int uniform_location, + float value); + +/** + * cogl_pipeline_set_uniform_1i: + * @pipeline: A #CoglPipeline object + * @uniform_location: The uniform's location identifier + * @value: The new value for the uniform + * + * Sets a new value for the uniform at @uniform_location. If this + * pipeline has a user program attached and is later used as a source + * for drawing, the given value will be assigned to the uniform which + * can be accessed from the shader's source. The value for + * @uniform_location should be retrieved from the string name of the + * uniform by calling cogl_pipeline_get_uniform_location(). + * + * This function should be used to set uniforms that are of type + * int. It can also be used to set a single member of a int array + * uniform or a sampler uniform. + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_pipeline_set_uniform_1i (CoglPipeline *pipeline, + int uniform_location, + int value); + +/** + * cogl_pipeline_set_uniform_float: + * @pipeline: A #CoglPipeline object + * @uniform_location: The uniform's location identifier + * @n_components: The number of components in the corresponding uniform's type + * @count: The number of values to set + * @value: Pointer to the new values to set + * + * Sets new values for the uniform at @uniform_location. If this + * pipeline has a user program attached and is later used as a source + * for drawing, the given values will be assigned to the uniform which + * can be accessed from the shader's source. The value for + * @uniform_location should be retrieved from the string name of the + * uniform by calling cogl_pipeline_get_uniform_location(). + * + * This function can be used to set any floating point type uniform, + * including float arrays and float vectors. For example, to set a + * single vec4 uniform you would use 4 for @n_components and 1 for + * @count. To set an array of 8 float values, you could use 1 for + * @n_components and 8 for @count. + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_pipeline_set_uniform_float (CoglPipeline *pipeline, + int uniform_location, + int n_components, + int count, + const float *value); + +/** + * cogl_pipeline_set_uniform_int: + * @pipeline: A #CoglPipeline object + * @uniform_location: The uniform's location identifier + * @n_components: The number of components in the corresponding uniform's type + * @count: The number of values to set + * @value: Pointer to the new values to set + * + * Sets new values for the uniform at @uniform_location. If this + * pipeline has a user program attached and is later used as a source + * for drawing, the given values will be assigned to the uniform which + * can be accessed from the shader's source. The value for + * @uniform_location should be retrieved from the string name of the + * uniform by calling cogl_pipeline_get_uniform_location(). + * + * This function can be used to set any integer type uniform, + * including int arrays and int vectors. For example, to set a single + * ivec4 uniform you would use 4 for @n_components and 1 for + * @count. To set an array of 8 int values, you could use 1 for + * @n_components and 8 for @count. + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_pipeline_set_uniform_int (CoglPipeline *pipeline, + int uniform_location, + int n_components, + int count, + const int *value); + +/** + * cogl_pipeline_set_uniform_matrix: + * @pipeline: A #CoglPipeline object + * @uniform_location: The uniform's location identifier + * @dimensions: The size of the matrix + * @count: The number of values to set + * @transpose: Whether to transpose the matrix + * @value: Pointer to the new values to set + * + * Sets new values for the uniform at @uniform_location. If this + * pipeline has a user program attached and is later used as a source + * for drawing, the given values will be assigned to the uniform which + * can be accessed from the shader's source. The value for + * @uniform_location should be retrieved from the string name of the + * uniform by calling cogl_pipeline_get_uniform_location(). + * + * This function can be used to set any matrix type uniform, including + * matrix arrays. For example, to set a single mat4 uniform you would + * use 4 for @dimensions and 1 for @count. To set an array of 8 + * mat3 values, you could use 3 for @dimensions and 8 for @count. + * + * If @transpose is %FALSE then the matrix is expected to be in + * column-major order or if it is %TRUE then the matrix is in + * row-major order. You can pass a #CoglMatrix by calling by passing + * the result of cogl_matrix_get_array() in @value and setting + * @transpose to %FALSE. + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_pipeline_set_uniform_matrix (CoglPipeline *pipeline, + int uniform_location, + int dimensions, + int count, + CoglBool transpose, + const float *value); + +/** + * cogl_pipeline_add_snippet: + * @pipeline: A #CoglPipeline + * @snippet: The #CoglSnippet to add to the vertex processing hook + * + * Adds a shader snippet to @pipeline. The snippet will wrap around or + * replace some part of the pipeline as defined by the hook point in + * @snippet. Note that some hook points are specific to a layer and + * must be added with cogl_pipeline_add_layer_snippet() instead. + * + * Since: 1.10 + * Stability: Unstable + */ +void +cogl_pipeline_add_snippet (CoglPipeline *pipeline, + CoglSnippet *snippet); + +COGL_END_DECLS + +#endif /* __COGL_PIPELINE_STATE_H__ */ diff --git a/cogl/cogl/cogl-pipeline.c b/cogl/cogl/cogl-pipeline.c new file mode 100644 index 0000000..da2d2ce --- /dev/null +++ b/cogl/cogl/cogl-pipeline.c @@ -0,0 +1,3174 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009,2010,2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-debug.h" +#include "cogl-context-private.h" +#include "cogl-object.h" + +#include "cogl-pipeline-private.h" +#include "cogl-pipeline-opengl-private.h" +#include "cogl-pipeline-state-private.h" +#include "cogl-pipeline-layer-state-private.h" +#include "cogl-texture-private.h" +#include "cogl-blend-string.h" +#include "cogl-journal-private.h" +#include "cogl-color-private.h" +#include "cogl-util.h" +#include "cogl-profile.h" +#include "cogl-depth-state-private.h" +#include "cogl1-context.h" +#include "cogl-gtype-private.h" + +#include +#include +#include + +static void _cogl_pipeline_free (CoglPipeline *tex); +static void recursively_free_layer_caches (CoglPipeline *pipeline); +static CoglBool _cogl_pipeline_is_weak (CoglPipeline *pipeline); + +const CoglPipelineFragend *_cogl_pipeline_fragends[COGL_PIPELINE_N_FRAGENDS]; +const CoglPipelineVertend *_cogl_pipeline_vertends[COGL_PIPELINE_N_VERTENDS]; +/* The 'MAX' here is so that we don't define an empty array when there + are no progends */ +const CoglPipelineProgend * +_cogl_pipeline_progends[MAX (COGL_PIPELINE_N_PROGENDS, 1)]; + +#ifdef COGL_PIPELINE_FRAGEND_GLSL +#include "cogl-pipeline-fragend-glsl-private.h" +#endif +#ifdef COGL_PIPELINE_FRAGEND_ARBFP +#include "cogl-pipeline-fragend-arbfp-private.h" +#endif +#ifdef COGL_PIPELINE_FRAGEND_FIXED +#include "cogl-pipeline-fragend-fixed-private.h" +#endif + +#ifdef COGL_PIPELINE_VERTEND_GLSL +#include "cogl-pipeline-vertend-glsl-private.h" +#endif +#ifdef COGL_PIPELINE_VERTEND_FIXED +#include "cogl-pipeline-vertend-fixed-private.h" +#endif + +#ifdef COGL_PIPELINE_PROGEND_FIXED_ARBFP +#include "cogl-pipeline-progend-fixed-arbfp-private.h" +#endif +#ifdef COGL_PIPELINE_PROGEND_FIXED +#include "cogl-pipeline-progend-fixed-private.h" +#endif +#ifdef COGL_PIPELINE_PROGEND_GLSL +#include "cogl-pipeline-progend-glsl-private.h" +#endif + +COGL_OBJECT_DEFINE (Pipeline, pipeline); +COGL_GTYPE_DEFINE_CLASS (Pipeline, pipeline); + +/* + * This initializes the first pipeline owned by the Cogl context. All + * subsequently instantiated pipelines created via the cogl_pipeline_new() + * API will initially be a copy of this pipeline. + * + * The default pipeline is the topmost ancester for all pipelines. + */ +void +_cogl_pipeline_init_default_pipeline (void) +{ + /* Create new - blank - pipeline */ + CoglPipeline *pipeline = g_slice_new0 (CoglPipeline); + /* XXX: NB: It's important that we zero this to avoid polluting + * pipeline hash values with un-initialized data */ + CoglPipelineBigState *big_state = g_slice_new0 (CoglPipelineBigState); + CoglPipelineLightingState *lighting_state = &big_state->lighting_state; + CoglPipelineAlphaFuncState *alpha_state = &big_state->alpha_state; + CoglPipelineBlendState *blend_state = &big_state->blend_state; + CoglPipelineLogicOpsState *logic_ops_state = &big_state->logic_ops_state; + CoglPipelineCullFaceState *cull_face_state = &big_state->cull_face_state; + CoglPipelineUniformsState *uniforms_state = &big_state->uniforms_state; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + /* Take this opportunity to setup the backends... */ +#ifdef COGL_PIPELINE_FRAGEND_GLSL + _cogl_pipeline_fragends[COGL_PIPELINE_FRAGEND_GLSL] = + &_cogl_pipeline_glsl_fragend; +#endif +#ifdef COGL_PIPELINE_FRAGEND_ARBFP + _cogl_pipeline_fragends[COGL_PIPELINE_FRAGEND_ARBFP] = + &_cogl_pipeline_arbfp_fragend; +#endif +#ifdef COGL_PIPELINE_FRAGEND_FIXED + _cogl_pipeline_fragends[COGL_PIPELINE_FRAGEND_FIXED] = + &_cogl_pipeline_fixed_fragend; +#endif +#ifdef COGL_PIPELINE_PROGEND_FIXED + _cogl_pipeline_progends[COGL_PIPELINE_PROGEND_FIXED_ARBFP] = + &_cogl_pipeline_fixed_arbfp_progend; +#endif +#ifdef COGL_PIPELINE_PROGEND_FIXED + _cogl_pipeline_progends[COGL_PIPELINE_PROGEND_FIXED] = + &_cogl_pipeline_fixed_progend; +#endif +#ifdef COGL_PIPELINE_PROGEND_GLSL + _cogl_pipeline_progends[COGL_PIPELINE_PROGEND_GLSL] = + &_cogl_pipeline_glsl_progend; +#endif + +#ifdef COGL_PIPELINE_VERTEND_GLSL + _cogl_pipeline_vertends[COGL_PIPELINE_VERTEND_GLSL] = + &_cogl_pipeline_glsl_vertend; +#endif +#ifdef COGL_PIPELINE_VERTEND_FIXED + _cogl_pipeline_vertends[COGL_PIPELINE_VERTEND_FIXED] = + &_cogl_pipeline_fixed_vertend; +#endif + + _cogl_pipeline_node_init (COGL_NODE (pipeline)); + + pipeline->is_weak = FALSE; + pipeline->journal_ref_count = 0; + pipeline->progend = COGL_PIPELINE_PROGEND_UNDEFINED; + pipeline->differences = COGL_PIPELINE_STATE_ALL_SPARSE; + + pipeline->real_blend_enable = FALSE; + + pipeline->blend_enable = COGL_PIPELINE_BLEND_ENABLE_AUTOMATIC; + pipeline->layer_differences = NULL; + pipeline->n_layers = 0; + + pipeline->big_state = big_state; + pipeline->has_big_state = TRUE; + + pipeline->static_breadcrumb = "default pipeline"; + pipeline->has_static_breadcrumb = TRUE; + + pipeline->age = 0; + + /* Use the same defaults as the GL spec... */ + cogl_color_init_from_4ub (&pipeline->color, 0xff, 0xff, 0xff, 0xff); + + /* Use the same defaults as the GL spec... */ + lighting_state->ambient[0] = 0.2; + lighting_state->ambient[1] = 0.2; + lighting_state->ambient[2] = 0.2; + lighting_state->ambient[3] = 1.0; + + lighting_state->diffuse[0] = 0.8; + lighting_state->diffuse[1] = 0.8; + lighting_state->diffuse[2] = 0.8; + lighting_state->diffuse[3] = 1.0; + + lighting_state->specular[0] = 0; + lighting_state->specular[1] = 0; + lighting_state->specular[2] = 0; + lighting_state->specular[3] = 1.0; + + lighting_state->emission[0] = 0; + lighting_state->emission[1] = 0; + lighting_state->emission[2] = 0; + lighting_state->emission[3] = 1.0; + + lighting_state->shininess = 0.0f; + + /* Use the same defaults as the GL spec... */ + alpha_state->alpha_func = COGL_PIPELINE_ALPHA_FUNC_ALWAYS; + alpha_state->alpha_func_reference = 0.0; + + /* Not the same as the GL default, but seems saner... */ +#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL) + blend_state->blend_equation_rgb = GL_FUNC_ADD; + blend_state->blend_equation_alpha = GL_FUNC_ADD; + blend_state->blend_src_factor_alpha = GL_ONE; + blend_state->blend_dst_factor_alpha = GL_ONE_MINUS_SRC_ALPHA; + cogl_color_init_from_4ub (&blend_state->blend_constant, + 0x00, 0x00, 0x00, 0x00); +#endif + blend_state->blend_src_factor_rgb = GL_ONE; + blend_state->blend_dst_factor_rgb = GL_ONE_MINUS_SRC_ALPHA; + + big_state->user_program = COGL_INVALID_HANDLE; + + cogl_depth_state_init (&big_state->depth_state); + + big_state->point_size = 0.0f; + + logic_ops_state->color_mask = COGL_COLOR_MASK_ALL; + + cull_face_state->mode = COGL_PIPELINE_CULL_FACE_MODE_NONE; + cull_face_state->front_winding = COGL_WINDING_COUNTER_CLOCKWISE; + + _cogl_bitmask_init (&uniforms_state->override_mask); + _cogl_bitmask_init (&uniforms_state->changed_mask); + uniforms_state->override_values = NULL; + + ctx->default_pipeline = _cogl_pipeline_object_new (pipeline); +} + +static void +_cogl_pipeline_unparent (CoglNode *pipeline) +{ + /* Chain up */ + _cogl_pipeline_node_unparent_real (pipeline); +} + +static CoglBool +recursively_free_layer_caches_cb (CoglNode *node, + void *user_data) +{ + recursively_free_layer_caches (COGL_PIPELINE (node)); + return TRUE; +} + +/* This recursively frees the layers_cache of a pipeline and all of + * its descendants. + * + * For instance if we change a pipelines ->layer_differences list + * then that pipeline and all of its descendants may now have + * incorrect layer caches. */ +static void +recursively_free_layer_caches (CoglPipeline *pipeline) +{ + /* Note: we maintain the invariable that if a pipeline already has a + * dirty layers_cache then so do all of its descendants. */ + if (pipeline->layers_cache_dirty) + return; + + if (G_UNLIKELY (pipeline->layers_cache != pipeline->short_layers_cache)) + g_slice_free1 (sizeof (CoglPipelineLayer *) * pipeline->n_layers, + pipeline->layers_cache); + pipeline->layers_cache_dirty = TRUE; + + _cogl_pipeline_node_foreach_child (COGL_NODE (pipeline), + recursively_free_layer_caches_cb, + NULL); +} + +static void +_cogl_pipeline_set_parent (CoglPipeline *pipeline, + CoglPipeline *parent, + CoglBool take_strong_reference) +{ + /* Chain up */ + _cogl_pipeline_node_set_parent_real (COGL_NODE (pipeline), + COGL_NODE (parent), + _cogl_pipeline_unparent, + take_strong_reference); + + /* Since we just changed the ancestry of the pipeline its cache of + * layers could now be invalid so free it... */ + if (pipeline->differences & COGL_PIPELINE_STATE_LAYERS) + recursively_free_layer_caches (pipeline); + + /* If the backends are also caching state along with the pipeline + * that depends on the pipeline's ancestry then it may be notified + * here... + */ + if (pipeline->progend != COGL_PIPELINE_PROGEND_UNDEFINED) + { + const CoglPipelineProgend *progend = + _cogl_pipeline_progends[pipeline->progend]; + const CoglPipelineFragend *fragend = + _cogl_pipeline_fragends[progend->fragend]; + + /* Currently only the fragends ever care about reparenting of + * pipelines... */ + if (fragend->pipeline_set_parent_notify) + fragend->pipeline_set_parent_notify (pipeline); + } +} + +static void +_cogl_pipeline_promote_weak_ancestors (CoglPipeline *strong) +{ + CoglNode *n; + + _COGL_RETURN_IF_FAIL (!strong->is_weak); + + /* If the parent of strong is weak, then we want to promote it by + taking a reference on strong's grandparent. We don't need to take + a reference on strong's direct parent */ + + if (COGL_NODE (strong)->parent == NULL) + return; + + for (n = COGL_NODE (strong)->parent; + /* We can assume that all weak pipelines have a parent */ + COGL_PIPELINE (n)->is_weak; + n = n->parent) + /* 'n' is weak so we take a reference on its parent */ + cogl_object_ref (n->parent); +} + +static void +_cogl_pipeline_revert_weak_ancestors (CoglPipeline *strong) +{ + CoglNode *n; + + _COGL_RETURN_IF_FAIL (!strong->is_weak); + + /* This reverts the effect of calling + _cogl_pipeline_promote_weak_ancestors */ + + if (COGL_NODE (strong)->parent == NULL) + return; + + for (n = COGL_NODE (strong)->parent; + /* We can assume that all weak pipelines have a parent */ + COGL_PIPELINE (n)->is_weak; + n = n->parent) + /* 'n' is weak so we unref its parent */ + cogl_object_unref (n->parent); +} + +/* XXX: Always have an eye out for opportunities to lower the cost of + * cogl_pipeline_copy. */ +static CoglPipeline * +_cogl_pipeline_copy (CoglPipeline *src, CoglBool is_weak) +{ + CoglPipeline *pipeline = g_slice_new (CoglPipeline); + + _cogl_pipeline_node_init (COGL_NODE (pipeline)); + + pipeline->is_weak = is_weak; + + pipeline->journal_ref_count = 0; + + pipeline->differences = 0; + + pipeline->has_big_state = FALSE; + + /* NB: real_blend_enable isn't a sparse property, it's valid for + * every pipeline node so we have fast access to it. */ + pipeline->real_blend_enable = src->real_blend_enable; + pipeline->dirty_real_blend_enable = src->dirty_real_blend_enable; + pipeline->unknown_color_alpha = src->unknown_color_alpha; + + /* XXX: + * consider generalizing the idea of "cached" properties. These + * would still have an authority like other sparse properties but + * you wouldn't have to walk up the ancestry to find the authority + * because the value would be cached directly in each pipeline. + */ + + pipeline->layers_cache_dirty = TRUE; + pipeline->deprecated_get_layers_list = NULL; + pipeline->deprecated_get_layers_list_dirty = TRUE; + + pipeline->progend = src->progend; + + pipeline->has_static_breadcrumb = FALSE; + + pipeline->age = 0; + + _cogl_pipeline_set_parent (pipeline, src, !is_weak); + + /* The semantics for copying a weak pipeline are that we promote all + * weak ancestors to temporarily become strong pipelines until the + * copy is freed. */ + if (!is_weak) + _cogl_pipeline_promote_weak_ancestors (pipeline); + + return _cogl_pipeline_object_new (pipeline); +} + +CoglPipeline * +cogl_pipeline_copy (CoglPipeline *src) +{ + return _cogl_pipeline_copy (src, FALSE); +} + +CoglPipeline * +_cogl_pipeline_weak_copy (CoglPipeline *pipeline, + CoglPipelineDestroyCallback callback, + void *user_data) +{ + CoglPipeline *copy; + CoglPipeline *copy_pipeline; + + copy = _cogl_pipeline_copy (pipeline, TRUE); + copy_pipeline = COGL_PIPELINE (copy); + copy_pipeline->destroy_callback = callback; + copy_pipeline->destroy_data = user_data; + + return copy; +} + +CoglPipeline * +cogl_pipeline_new (CoglContext *context) +{ + CoglPipeline *new; + + new = cogl_pipeline_copy (context->default_pipeline); +#ifdef COGL_DEBUG_ENABLED + _cogl_pipeline_set_static_breadcrumb (new, "new"); +#endif + return new; +} + +static CoglBool +destroy_weak_children_cb (CoglNode *node, + void *user_data) +{ + CoglPipeline *pipeline = COGL_PIPELINE (node); + + if (_cogl_pipeline_is_weak (pipeline)) + { + _cogl_pipeline_node_foreach_child (COGL_NODE (pipeline), + destroy_weak_children_cb, + NULL); + + pipeline->destroy_callback (pipeline, pipeline->destroy_data); + _cogl_pipeline_unparent (COGL_NODE (pipeline)); + } + + return TRUE; +} + +static void +_cogl_pipeline_free (CoglPipeline *pipeline) +{ + if (!pipeline->is_weak) + _cogl_pipeline_revert_weak_ancestors (pipeline); + + /* Weak pipelines don't take a reference on their parent */ + _cogl_pipeline_node_foreach_child (COGL_NODE (pipeline), + destroy_weak_children_cb, + NULL); + + g_assert (_cogl_list_empty (&COGL_NODE (pipeline)->children)); + + _cogl_pipeline_unparent (COGL_NODE (pipeline)); + + if (pipeline->differences & COGL_PIPELINE_STATE_USER_SHADER && + pipeline->big_state->user_program) + cogl_handle_unref (pipeline->big_state->user_program); + + if (pipeline->differences & COGL_PIPELINE_STATE_UNIFORMS) + { + CoglPipelineUniformsState *uniforms_state + = &pipeline->big_state->uniforms_state; + int n_overrides = _cogl_bitmask_popcount (&uniforms_state->override_mask); + int i; + + for (i = 0; i < n_overrides; i++) + _cogl_boxed_value_destroy (uniforms_state->override_values + i); + g_free (uniforms_state->override_values); + + _cogl_bitmask_destroy (&uniforms_state->override_mask); + _cogl_bitmask_destroy (&uniforms_state->changed_mask); + } + + if (pipeline->differences & COGL_PIPELINE_STATE_NEEDS_BIG_STATE) + g_slice_free (CoglPipelineBigState, pipeline->big_state); + + if (pipeline->differences & COGL_PIPELINE_STATE_LAYERS) + { + g_list_foreach (pipeline->layer_differences, + (GFunc)cogl_object_unref, NULL); + g_list_free (pipeline->layer_differences); + } + + if (pipeline->differences & COGL_PIPELINE_STATE_VERTEX_SNIPPETS) + _cogl_pipeline_snippet_list_free (&pipeline->big_state->vertex_snippets); + + if (pipeline->differences & COGL_PIPELINE_STATE_FRAGMENT_SNIPPETS) + _cogl_pipeline_snippet_list_free (&pipeline->big_state->fragment_snippets); + + g_list_free (pipeline->deprecated_get_layers_list); + + recursively_free_layer_caches (pipeline); + + g_slice_free (CoglPipeline, pipeline); +} + +CoglBool +_cogl_pipeline_get_real_blend_enabled (CoglPipeline *pipeline) +{ + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), FALSE); + + return pipeline->real_blend_enable; +} + +static void +_cogl_pipeline_update_layers_cache (CoglPipeline *pipeline) +{ + /* Note: we assume this pipeline is a _LAYERS authority */ + int n_layers; + CoglPipeline *current; + int layers_found; + + if (G_LIKELY (!pipeline->layers_cache_dirty) || + pipeline->n_layers == 0) + return; + + pipeline->layers_cache_dirty = FALSE; + + n_layers = pipeline->n_layers; + if (G_LIKELY (n_layers < G_N_ELEMENTS (pipeline->short_layers_cache))) + { + pipeline->layers_cache = pipeline->short_layers_cache; + memset (pipeline->layers_cache, 0, + sizeof (CoglPipelineLayer *) * + G_N_ELEMENTS (pipeline->short_layers_cache)); + } + else + { + pipeline->layers_cache = + g_slice_alloc0 (sizeof (CoglPipelineLayer *) * n_layers); + } + + /* Notes: + * + * Each pipeline doesn't have to contain a complete list of the layers + * it depends on, some of them are indirectly referenced through the + * pipeline's ancestors. + * + * pipeline->layer_differences only contains a list of layers that + * have changed in relation to its parent. + * + * pipeline->layer_differences is not maintained sorted, but it + * won't contain multiple layers corresponding to a particular + * ->unit_index. + * + * Some of the ancestor pipelines may reference layers with + * ->unit_index values >= n_layers so we ignore them. + * + * As we ascend through the ancestors we are searching for any + * CoglPipelineLayers corresponding to the texture ->unit_index + * values in the range [0,n_layers-1]. As soon as a pointer is found + * we ignore layers of further ancestors with the same ->unit_index + * values. + */ + + layers_found = 0; + for (current = pipeline; + _cogl_pipeline_get_parent (current); + current = _cogl_pipeline_get_parent (current)) + { + GList *l; + + if (!(current->differences & COGL_PIPELINE_STATE_LAYERS)) + continue; + + for (l = current->layer_differences; l; l = l->next) + { + CoglPipelineLayer *layer = l->data; + int unit_index = _cogl_pipeline_layer_get_unit_index (layer); + + if (unit_index < n_layers && !pipeline->layers_cache[unit_index]) + { + pipeline->layers_cache[unit_index] = layer; + layers_found++; + if (layers_found == n_layers) + return; + } + } + } + + g_warn_if_reached (); +} + +/* XXX: Be carefull when using this API that the callback given doesn't result + * in the layer cache being invalidated during the iteration! */ +void +_cogl_pipeline_foreach_layer_internal (CoglPipeline *pipeline, + CoglPipelineInternalLayerCallback callback, + void *user_data) +{ + CoglPipeline *authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LAYERS); + int n_layers; + int i; + CoglBool cont; + + n_layers = authority->n_layers; + if (n_layers == 0) + return; + + _cogl_pipeline_update_layers_cache (authority); + + for (i = 0, cont = TRUE; i < n_layers && cont == TRUE; i++) + { + _COGL_RETURN_IF_FAIL (authority->layers_cache_dirty == FALSE); + cont = callback (authority->layers_cache[i], user_data); + } +} + +CoglBool +_cogl_pipeline_layer_numbers_equal (CoglPipeline *pipeline0, + CoglPipeline *pipeline1) +{ + CoglPipeline *authority0 = + _cogl_pipeline_get_authority (pipeline0, COGL_PIPELINE_STATE_LAYERS); + CoglPipeline *authority1 = + _cogl_pipeline_get_authority (pipeline1, COGL_PIPELINE_STATE_LAYERS); + int n_layers = authority0->n_layers; + int i; + + if (authority1->n_layers != n_layers) + return FALSE; + + _cogl_pipeline_update_layers_cache (authority0); + _cogl_pipeline_update_layers_cache (authority1); + + for (i = 0; i < n_layers; i++) + { + CoglPipelineLayer *layer0 = authority0->layers_cache[i]; + CoglPipelineLayer *layer1 = authority1->layers_cache[i]; + + if (layer0->index != layer1->index) + return FALSE; + } + + return TRUE; +} + +CoglBool +_cogl_pipeline_layer_and_unit_numbers_equal (CoglPipeline *pipeline0, + CoglPipeline *pipeline1) +{ + CoglPipeline *authority0 = + _cogl_pipeline_get_authority (pipeline0, COGL_PIPELINE_STATE_LAYERS); + CoglPipeline *authority1 = + _cogl_pipeline_get_authority (pipeline1, COGL_PIPELINE_STATE_LAYERS); + int n_layers = authority0->n_layers; + int i; + + if (authority1->n_layers != n_layers) + return FALSE; + + _cogl_pipeline_update_layers_cache (authority0); + _cogl_pipeline_update_layers_cache (authority1); + + for (i = 0; i < n_layers; i++) + { + CoglPipelineLayer *layer0 = authority0->layers_cache[i]; + CoglPipelineLayer *layer1 = authority1->layers_cache[i]; + int unit0, unit1; + + if (layer0->index != layer1->index) + return FALSE; + + unit0 = _cogl_pipeline_layer_get_unit_index (layer0); + unit1 = _cogl_pipeline_layer_get_unit_index (layer1); + if (unit0 != unit1) + return FALSE; + } + + return TRUE; +} + +typedef struct +{ + int i; + int *indices; +} AppendLayerIndexState; + +static CoglBool +append_layer_index_cb (CoglPipelineLayer *layer, + void *user_data) +{ + AppendLayerIndexState *state = user_data; + state->indices[state->i++] = layer->index; + return TRUE; +} + +void +cogl_pipeline_foreach_layer (CoglPipeline *pipeline, + CoglPipelineLayerCallback callback, + void *user_data) +{ + CoglPipeline *authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LAYERS); + AppendLayerIndexState state; + CoglBool cont; + int i; + + /* XXX: We don't know what the user is going to want to do to the layers + * but any modification of layers can result in the layer graph changing + * which could confuse _cogl_pipeline_foreach_layer_internal(). We first + * get a list of layer indices which will remain valid so long as the + * user doesn't remove layers. */ + + state.i = 0; + state.indices = g_alloca (authority->n_layers * sizeof (int)); + + _cogl_pipeline_foreach_layer_internal (pipeline, + append_layer_index_cb, + &state); + + for (i = 0, cont = TRUE; i < authority->n_layers && cont; i++) + cont = callback (pipeline, state.indices[i], user_data); +} + +static CoglBool +layer_has_alpha_cb (CoglPipelineLayer *layer, void *data) +{ + CoglBool *has_alpha = data; + *has_alpha = _cogl_pipeline_layer_has_alpha (layer); + + /* return FALSE to stop iterating layers if we find any layer + * has alpha ... + * + * FIXME: actually we should never be bailing out because it's + * always possible that a later layer could discard any previous + * alpha! + */ + + return !(*has_alpha); +} + +/* NB: If this pipeline returns FALSE that doesn't mean that the + * pipeline is definitely opaque, it just means that that the + * given changes dont imply transparency. + * + * If you want to find out of the pipeline is opaque then assuming + * this returns FALSE for a set of changes then you can follow + * up + */ +static CoglBool +_cogl_pipeline_change_implies_transparency (CoglPipeline *pipeline, + unsigned int changes, + const CoglColor *override_color, + CoglBool unknown_color_alpha) +{ + /* In the case of a layer state change we need to check everything + * else first since they contribute to the has_alpha status of the + * "PREVIOUS" layer. */ + if (changes & COGL_PIPELINE_STATE_LAYERS) + changes = COGL_PIPELINE_STATE_AFFECTS_BLENDING; + + if (unknown_color_alpha) + return TRUE; + + if ((override_color && cogl_color_get_alpha_byte (override_color) != 0xff)) + return TRUE; + + if (changes & COGL_PIPELINE_STATE_COLOR) + { + CoglColor tmp; + cogl_pipeline_get_color (pipeline, &tmp); + if (cogl_color_get_alpha_byte (&tmp) != 0xff) + return TRUE; + } + + if (changes & COGL_PIPELINE_STATE_USER_SHADER) + { + /* We can't make any assumptions about the alpha channel if the user + * is using an unknown fragment shader. + * + * TODO: check that it isn't just a vertex shader! + */ + if (_cogl_pipeline_get_user_program (pipeline) != COGL_INVALID_HANDLE) + return TRUE; + } + + if (changes & COGL_PIPELINE_STATE_FRAGMENT_SNIPPETS) + { + if (_cogl_pipeline_has_non_layer_fragment_snippets (pipeline)) + return TRUE; + } + + if (changes & COGL_PIPELINE_STATE_VERTEX_SNIPPETS) + { + if (_cogl_pipeline_has_non_layer_vertex_snippets (pipeline)) + return TRUE; + } + + /* XXX: we should only need to look at these if lighting is enabled + */ + if (changes & COGL_PIPELINE_STATE_LIGHTING) + { + /* XXX: This stuff is showing up in sysprof reports which is + * silly because lighting isn't currently actually supported + * by Cogl except for these token properties. When we actually + * expose lighting support we can avoid these checks when + * lighting is disabled. */ +#if 0 + CoglColor tmp; + cogl_pipeline_get_ambient (pipeline, &tmp); + if (cogl_color_get_alpha_byte (&tmp) != 0xff) + return TRUE; + cogl_pipeline_get_diffuse (pipeline, &tmp); + if (cogl_color_get_alpha_byte (&tmp) != 0xff) + return TRUE; + cogl_pipeline_get_specular (pipeline, &tmp); + if (cogl_color_get_alpha_byte (&tmp) != 0xff) + return TRUE; + cogl_pipeline_get_emission (pipeline, &tmp); + if (cogl_color_get_alpha_byte (&tmp) != 0xff) + return TRUE; +#endif + } + + if (changes & COGL_PIPELINE_STATE_LAYERS) + { + /* has_alpha tracks the alpha status of the GL_PREVIOUS layer. + * To start with that's defined by the pipeline color which + * must be fully opaque if we got this far. */ + CoglBool has_alpha = FALSE; + _cogl_pipeline_foreach_layer_internal (pipeline, + layer_has_alpha_cb, + &has_alpha); + if (has_alpha) + return TRUE; + } + + return FALSE; +} + +static CoglBool +_cogl_pipeline_needs_blending_enabled (CoglPipeline *pipeline, + unsigned int changes, + const CoglColor *override_color, + CoglBool unknown_color_alpha) +{ + CoglPipeline *enable_authority; + CoglPipeline *blend_authority; + CoglPipelineBlendState *blend_state; + CoglPipelineBlendEnable enabled; + + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_BLENDING))) + return FALSE; + + /* We unconditionally check the _BLEND_ENABLE state first because + * all the other changes are irrelevent if blend_enable != _AUTOMATIC + */ + enable_authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_BLEND_ENABLE); + + enabled = enable_authority->blend_enable; + if (enabled != COGL_PIPELINE_BLEND_ENABLE_AUTOMATIC) + return enabled == COGL_PIPELINE_BLEND_ENABLE_ENABLED ? TRUE : FALSE; + + blend_authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_BLEND); + + blend_state = &blend_authority->big_state->blend_state; + + /* We are trying to identify some cases that are equivalent to + * blending being disable, where the output is simply GL_SRC_COLOR. + * + * Note: we currently only consider a few cases that can be + * optimized but there could be opportunities to special case more + * blend functions later. + */ + + /* As the most common way that we currently use to effectively + * disable blending is to use an equation of + * "RGBA=ADD(SRC_COLOR, 0)" that's the first thing we check + * for... */ + if (blend_state->blend_equation_rgb == GL_FUNC_ADD && + blend_state->blend_equation_alpha == GL_FUNC_ADD && + blend_state->blend_src_factor_alpha == GL_ONE && + blend_state->blend_dst_factor_alpha == GL_ZERO) + { + return FALSE; + } + + /* NB: The default blending equation for Cogl is + * "RGBA=ADD(SRC_COLOR, DST_COLOR * (1-SRC_COLOR[A]))" + * + * Next we check if the default blending equation is being used. If + * so then we follow that by looking for cases where SRC_COLOR[A] == + * 1 since that simplifies "DST_COLOR * (1-SRC_COLOR[A])" to 0 which + * also effectively requires no blending. + */ + + if (blend_state->blend_equation_rgb != GL_FUNC_ADD || + blend_state->blend_equation_alpha != GL_FUNC_ADD) + return TRUE; + + if (blend_state->blend_src_factor_alpha != GL_ONE || + blend_state->blend_dst_factor_alpha != GL_ONE_MINUS_SRC_ALPHA) + return TRUE; + + if (blend_state->blend_src_factor_rgb != GL_ONE || + blend_state->blend_dst_factor_rgb != GL_ONE_MINUS_SRC_ALPHA) + return TRUE; + + /* Given the above constraints, it's now a case of finding any + * SRC_ALPHA that != 1 */ + + if (_cogl_pipeline_change_implies_transparency (pipeline, changes, + override_color, + unknown_color_alpha)) + return TRUE; + + /* At this point, considering just the state that has changed it + * looks like blending isn't needed. If blending was previously + * enabled though it could be that some other state still requires + * that we have blending enabled because it implies transparency. + * In this case we still need to go and check the other state... + * + * XXX: We could explicitly keep track of the mask of state groups + * that are currently causing blending to be enabled so that we + * never have to resort to checking *all* the state and can instead + * always limit the check to those in the mask. + */ + if (pipeline->real_blend_enable) + { + unsigned int other_state = + COGL_PIPELINE_STATE_AFFECTS_BLENDING & ~changes; + if (other_state && + _cogl_pipeline_change_implies_transparency (pipeline, other_state, NULL, FALSE)) + return TRUE; + } + + return FALSE; +} + +void +_cogl_pipeline_set_progend (CoglPipeline *pipeline, int progend) +{ + pipeline->progend = progend; +} + +static void +_cogl_pipeline_copy_differences (CoglPipeline *dest, + CoglPipeline *src, + unsigned long differences) +{ + CoglPipelineBigState *big_state; + + if (differences & COGL_PIPELINE_STATE_COLOR) + dest->color = src->color; + + if (differences & COGL_PIPELINE_STATE_BLEND_ENABLE) + dest->blend_enable = src->blend_enable; + + if (differences & COGL_PIPELINE_STATE_LAYERS) + { + GList *l; + + if (dest->differences & COGL_PIPELINE_STATE_LAYERS && + dest->layer_differences) + { + g_list_foreach (dest->layer_differences, + (GFunc)cogl_object_unref, + NULL); + g_list_free (dest->layer_differences); + } + + for (l = src->layer_differences; l; l = l->next) + { + /* NB: a layer can't have more than one ->owner so we can't + * simply take a references on each of the original + * layer_differences, we have to derive new layers from the + * originals instead. */ + CoglPipelineLayer *copy = _cogl_pipeline_layer_copy (l->data); + _cogl_pipeline_add_layer_difference (dest, copy, FALSE); + cogl_object_unref (copy); + } + + /* Note: we initialize n_layers after adding the layer differences + * since the act of adding the layers will initialize n_layers to 0 + * because dest isn't initially a STATE_LAYERS authority. */ + dest->n_layers = src->n_layers; + } + + if (differences & COGL_PIPELINE_STATE_NEEDS_BIG_STATE) + { + if (!dest->has_big_state) + { + dest->big_state = g_slice_new (CoglPipelineBigState); + dest->has_big_state = TRUE; + } + big_state = dest->big_state; + } + else + goto check_for_blending_change; + + if (differences & COGL_PIPELINE_STATE_LIGHTING) + { + memcpy (&big_state->lighting_state, + &src->big_state->lighting_state, + sizeof (CoglPipelineLightingState)); + } + + if (differences & COGL_PIPELINE_STATE_ALPHA_FUNC) + big_state->alpha_state.alpha_func = + src->big_state->alpha_state.alpha_func; + + if (differences & COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE) + big_state->alpha_state.alpha_func_reference = + src->big_state->alpha_state.alpha_func_reference; + + if (differences & COGL_PIPELINE_STATE_BLEND) + { + memcpy (&big_state->blend_state, + &src->big_state->blend_state, + sizeof (CoglPipelineBlendState)); + } + + if (differences & COGL_PIPELINE_STATE_USER_SHADER) + { + if (src->big_state->user_program) + big_state->user_program = + cogl_handle_ref (src->big_state->user_program); + else + big_state->user_program = COGL_INVALID_HANDLE; + } + + if (differences & COGL_PIPELINE_STATE_DEPTH) + { + memcpy (&big_state->depth_state, + &src->big_state->depth_state, + sizeof (CoglDepthState)); + } + + if (differences & COGL_PIPELINE_STATE_FOG) + { + memcpy (&big_state->fog_state, + &src->big_state->fog_state, + sizeof (CoglPipelineFogState)); + } + + if (differences & COGL_PIPELINE_STATE_NON_ZERO_POINT_SIZE) + big_state->non_zero_point_size = src->big_state->non_zero_point_size; + + if (differences & COGL_PIPELINE_STATE_POINT_SIZE) + big_state->point_size = src->big_state->point_size; + + if (differences & COGL_PIPELINE_STATE_PER_VERTEX_POINT_SIZE) + big_state->per_vertex_point_size = src->big_state->per_vertex_point_size; + + if (differences & COGL_PIPELINE_STATE_LOGIC_OPS) + { + memcpy (&big_state->logic_ops_state, + &src->big_state->logic_ops_state, + sizeof (CoglPipelineLogicOpsState)); + } + + if (differences & COGL_PIPELINE_STATE_CULL_FACE) + { + memcpy (&big_state->cull_face_state, + &src->big_state->cull_face_state, + sizeof (CoglPipelineCullFaceState)); + } + + if (differences & COGL_PIPELINE_STATE_UNIFORMS) + { + int n_overrides = + _cogl_bitmask_popcount (&src->big_state->uniforms_state.override_mask); + int i; + + big_state->uniforms_state.override_values = + g_malloc (n_overrides * sizeof (CoglBoxedValue)); + + for (i = 0; i < n_overrides; i++) + { + CoglBoxedValue *dst_bv = + big_state->uniforms_state.override_values + i; + const CoglBoxedValue *src_bv = + src->big_state->uniforms_state.override_values + i; + + _cogl_boxed_value_copy (dst_bv, src_bv); + } + + _cogl_bitmask_init (&big_state->uniforms_state.override_mask); + _cogl_bitmask_set_bits (&big_state->uniforms_state.override_mask, + &src->big_state->uniforms_state.override_mask); + + _cogl_bitmask_init (&big_state->uniforms_state.changed_mask); + } + + if (differences & COGL_PIPELINE_STATE_VERTEX_SNIPPETS) + _cogl_pipeline_snippet_list_copy (&big_state->vertex_snippets, + &src->big_state->vertex_snippets); + + if (differences & COGL_PIPELINE_STATE_FRAGMENT_SNIPPETS) + _cogl_pipeline_snippet_list_copy (&big_state->fragment_snippets, + &src->big_state->fragment_snippets); + + /* XXX: we shouldn't bother doing this in most cases since + * _copy_differences is typically used to initialize pipeline state + * by copying it from the current authority, so it's not actually + * *changing* anything. + */ +check_for_blending_change: + if (differences & COGL_PIPELINE_STATE_AFFECTS_BLENDING) + dest->dirty_real_blend_enable = TRUE; + + dest->differences |= differences; +} + +static void +_cogl_pipeline_init_multi_property_sparse_state (CoglPipeline *pipeline, + CoglPipelineState change) +{ + CoglPipeline *authority; + + _COGL_RETURN_IF_FAIL (change & COGL_PIPELINE_STATE_ALL_SPARSE); + + if (!(change & COGL_PIPELINE_STATE_MULTI_PROPERTY)) + return; + + authority = _cogl_pipeline_get_authority (pipeline, change); + + switch (change) + { + /* XXX: avoid using a default: label so we get a warning if we + * don't explicitly handle a newly defined state-group here. */ + case COGL_PIPELINE_STATE_COLOR: + case COGL_PIPELINE_STATE_BLEND_ENABLE: + case COGL_PIPELINE_STATE_ALPHA_FUNC: + case COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE: + case COGL_PIPELINE_STATE_NON_ZERO_POINT_SIZE: + case COGL_PIPELINE_STATE_POINT_SIZE: + case COGL_PIPELINE_STATE_USER_SHADER: + case COGL_PIPELINE_STATE_PER_VERTEX_POINT_SIZE: + case COGL_PIPELINE_STATE_REAL_BLEND_ENABLE: + g_return_if_reached (); + + case COGL_PIPELINE_STATE_LAYERS: + pipeline->n_layers = authority->n_layers; + pipeline->layer_differences = NULL; + break; + case COGL_PIPELINE_STATE_LIGHTING: + { + memcpy (&pipeline->big_state->lighting_state, + &authority->big_state->lighting_state, + sizeof (CoglPipelineLightingState)); + break; + } + case COGL_PIPELINE_STATE_BLEND: + { + memcpy (&pipeline->big_state->blend_state, + &authority->big_state->blend_state, + sizeof (CoglPipelineBlendState)); + break; + } + case COGL_PIPELINE_STATE_DEPTH: + { + memcpy (&pipeline->big_state->depth_state, + &authority->big_state->depth_state, + sizeof (CoglDepthState)); + break; + } + case COGL_PIPELINE_STATE_FOG: + { + memcpy (&pipeline->big_state->fog_state, + &authority->big_state->fog_state, + sizeof (CoglPipelineFogState)); + break; + } + case COGL_PIPELINE_STATE_LOGIC_OPS: + { + memcpy (&pipeline->big_state->logic_ops_state, + &authority->big_state->logic_ops_state, + sizeof (CoglPipelineLogicOpsState)); + break; + } + case COGL_PIPELINE_STATE_CULL_FACE: + { + memcpy (&pipeline->big_state->cull_face_state, + &authority->big_state->cull_face_state, + sizeof (CoglPipelineCullFaceState)); + break; + } + case COGL_PIPELINE_STATE_UNIFORMS: + { + CoglPipelineUniformsState *uniforms_state = + &pipeline->big_state->uniforms_state; + _cogl_bitmask_init (&uniforms_state->override_mask); + _cogl_bitmask_init (&uniforms_state->changed_mask); + uniforms_state->override_values = NULL; + break; + } + case COGL_PIPELINE_STATE_VERTEX_SNIPPETS: + _cogl_pipeline_snippet_list_copy (&pipeline->big_state->vertex_snippets, + &authority->big_state->vertex_snippets); + break; + + case COGL_PIPELINE_STATE_FRAGMENT_SNIPPETS: + _cogl_pipeline_snippet_list_copy (&pipeline->big_state->fragment_snippets, + &authority->big_state-> + fragment_snippets); + break; + } +} + +static CoglBool +check_if_strong_cb (CoglNode *node, void *user_data) +{ + CoglPipeline *pipeline = COGL_PIPELINE (node); + CoglBool *has_strong_child = user_data; + + if (!_cogl_pipeline_is_weak (pipeline)) + { + *has_strong_child = TRUE; + return FALSE; + } + + return TRUE; +} + +static CoglBool +has_strong_children (CoglPipeline *pipeline) +{ + CoglBool has_strong_child = FALSE; + _cogl_pipeline_node_foreach_child (COGL_NODE (pipeline), + check_if_strong_cb, + &has_strong_child); + return has_strong_child; +} + +static CoglBool +_cogl_pipeline_is_weak (CoglPipeline *pipeline) +{ + if (pipeline->is_weak && !has_strong_children (pipeline)) + return TRUE; + else + return FALSE; +} + +static CoglBool +reparent_children_cb (CoglNode *node, + void *user_data) +{ + CoglPipeline *pipeline = COGL_PIPELINE (node); + CoglPipeline *parent = user_data; + + _cogl_pipeline_set_parent (pipeline, parent, TRUE); + + return TRUE; +} + +void +_cogl_pipeline_pre_change_notify (CoglPipeline *pipeline, + CoglPipelineState change, + const CoglColor *new_color, + CoglBool from_layer_change) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + /* If primitives have been logged in the journal referencing the + * current state of this pipeline we need to flush the journal + * before we can modify it... */ + if (pipeline->journal_ref_count) + { + CoglBool skip_journal_flush = FALSE; + + /* XXX: We don't usually need to flush the journal just due to + * color changes since pipeline colors are logged in the + * journal's vertex buffer. The exception is when the change in + * color enables or disables the need for blending. */ + if (change == COGL_PIPELINE_STATE_COLOR) + { + CoglBool will_need_blending = + _cogl_pipeline_needs_blending_enabled (pipeline, + change, + new_color, + FALSE); + CoglBool blend_enable = pipeline->real_blend_enable ? TRUE : FALSE; + + if (will_need_blending == blend_enable) + skip_journal_flush = TRUE; + } + + if (!skip_journal_flush) + { + /* XXX: note we use cogl_flush() not _cogl_flush_journal() so + * we will flush *all* known journals that might reference the + * current pipeline. */ + cogl_flush (); + } + } + + /* XXX: + * To simplify things for the vertex, fragment and program backends + * we are careful about how we report STATE_LAYERS changes. + * + * All STATE_LAYERS change notifications with the exception of + * ->n_layers will also result in layer_pre_change_notifications. + * + * For backends that perform code generation for fragment processing + * they typically need to understand the details of how layers get + * changed to determine if they need to repeat codegen. It doesn't + * help them to report a pipeline STATE_LAYERS change for all layer + * changes since it's so broad, they really need to wait for the + * specific layer change to be notified. What does help though is + * to report a STATE_LAYERS change for a change in ->n_layers + * because they typically do need to repeat codegen in that case. + * + * Here we ensure that change notifications against a pipeline or + * against a layer are mutually exclusive as far as fragment, vertex + * and program backends are concerned. + * + * NB: A pipeline can potentially have private state from multiple + * backends associated with it because descendants may cache state + * with an ancestor to maximize the chance that it can later be + * re-used by other descendants and a descendent can require a + * different backend to an ancestor. + */ + if (!from_layer_change) + { + int i; + + for (i = 0; i < COGL_PIPELINE_N_PROGENDS; i++) + { + const CoglPipelineProgend *progend = _cogl_pipeline_progends[i]; + const CoglPipelineVertend *vertend = + _cogl_pipeline_vertends[progend->vertend]; + const CoglPipelineFragend *fragend = + _cogl_pipeline_fragends[progend->fragend]; + + if (vertend->pipeline_pre_change_notify) + vertend->pipeline_pre_change_notify (pipeline, change, new_color); + + /* TODO: make the vertend and fragend implementation details + * of the progend */ + + if (fragend->pipeline_pre_change_notify) + fragend->pipeline_pre_change_notify (pipeline, change, new_color); + + if (progend->pipeline_pre_change_notify) + progend->pipeline_pre_change_notify (pipeline, change, new_color); + } + } + + /* There may be an arbitrary tree of descendants of this pipeline; + * any of which may indirectly depend on this pipeline as the + * authority for some set of properties. (Meaning for example that + * one of its descendants derives its color or blending state from + * this pipeline.) + * + * We can't modify any property that this pipeline is the authority + * for unless we create another pipeline to take its place first and + * make sure descendants reference this new pipeline instead. + */ + + /* The simplest descendants to handle are weak pipelines; we simply + * destroy them if we are modifying a pipeline they depend on. This + * means weak pipelines never cause us to do a copy-on-write. */ + _cogl_pipeline_node_foreach_child (COGL_NODE (pipeline), + destroy_weak_children_cb, + NULL); + + /* If there are still children remaining though we'll need to + * perform a copy-on-write and reparent the dependants as children + * of the copy. */ + if (!_cogl_list_empty (&COGL_NODE (pipeline)->children)) + { + CoglPipeline *new_authority; + + COGL_STATIC_COUNTER (pipeline_copy_on_write_counter, + "pipeline copy on write counter", + "Increments each time a pipeline " + "must be copied to allow modification", + 0 /* no application private data */); + + COGL_COUNTER_INC (_cogl_uprof_context, pipeline_copy_on_write_counter); + + new_authority = + cogl_pipeline_copy (_cogl_pipeline_get_parent (pipeline)); +#ifdef COGL_DEBUG_ENABLED + _cogl_pipeline_set_static_breadcrumb (new_authority, + "pre_change_notify:copy-on-write"); +#endif + + /* We could explicitly walk the descendants, OR together the set + * of differences that we determine this pipeline is the + * authority on and only copy those differences copied across. + * + * Or, if we don't explicitly walk the descendants we at least + * know that pipeline->differences represents the largest set of + * differences that this pipeline could possibly be an authority + * on. + * + * We do the later just because it's simplest, but we might need + * to come back to this later... + */ + _cogl_pipeline_copy_differences (new_authority, pipeline, + pipeline->differences); + + /* Reparent the dependants of pipeline to be children of + * new_authority instead... */ + _cogl_pipeline_node_foreach_child (COGL_NODE (pipeline), + reparent_children_cb, + new_authority); + + /* The children will keep the new authority alive so drop the + * reference we got when copying... */ + cogl_object_unref (new_authority); + } + + /* At this point we know we have a pipeline with no strong + * dependants (though we may have some weak children) so we are now + * free to modify the pipeline. */ + + pipeline->age++; + + if (change & COGL_PIPELINE_STATE_NEEDS_BIG_STATE && + !pipeline->has_big_state) + { + pipeline->big_state = g_slice_new (CoglPipelineBigState); + pipeline->has_big_state = TRUE; + } + + /* Note: conceptually we have just been notified that a single + * property value is about to change, but since some state-groups + * contain multiple properties and 'pipeline' is about to take over + * being the authority for the property's corresponding state-group + * we need to maintain the integrity of the other property values + * too. + * + * To ensure this we handle multi-property state-groups by copying + * all the values from the old-authority to the new... + * + * We don't have to worry about non-sparse property groups since + * we never take over being an authority for such properties so + * they automatically maintain integrity. + */ + if (change & COGL_PIPELINE_STATE_ALL_SPARSE && + !(pipeline->differences & change)) + { + _cogl_pipeline_init_multi_property_sparse_state (pipeline, change); + pipeline->differences |= change; + } + + /* Each pipeline has a sorted cache of the layers it depends on + * which will need updating via _cogl_pipeline_update_layers_cache + * if a pipeline's layers are changed. */ + if (change == COGL_PIPELINE_STATE_LAYERS) + recursively_free_layer_caches (pipeline); + + /* If the pipeline being changed is the same as the last pipeline we + * flushed then we keep a track of the changes so we can try to + * minimize redundant OpenGL calls if the same pipeline is flushed + * again. + */ + if (ctx->current_pipeline == pipeline) + ctx->current_pipeline_changes_since_flush |= change; +} + + +void +_cogl_pipeline_add_layer_difference (CoglPipeline *pipeline, + CoglPipelineLayer *layer, + CoglBool inc_n_layers) +{ + _COGL_RETURN_IF_FAIL (layer->owner == NULL); + + layer->owner = pipeline; + cogl_object_ref (layer); + + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + /* Note: the last argument to _cogl_pipeline_pre_change_notify is + * needed to differentiate STATE_LAYER changes which don't affect + * the number of layers from those that do. NB: Layer change + * notifications that don't change the number of layers don't get + * forwarded to the fragend. */ + _cogl_pipeline_pre_change_notify (pipeline, + COGL_PIPELINE_STATE_LAYERS, + NULL, + !inc_n_layers); + + pipeline->differences |= COGL_PIPELINE_STATE_LAYERS; + + pipeline->layer_differences = + g_list_prepend (pipeline->layer_differences, layer); + + if (inc_n_layers) + pipeline->n_layers++; + + /* Adding a layer difference may mean this pipeline now overrides + * all of the layers of its parent which might make the parent + * redundant so we should try to prune the hierarchy */ + _cogl_pipeline_prune_redundant_ancestry (pipeline); +} + +void +_cogl_pipeline_remove_layer_difference (CoglPipeline *pipeline, + CoglPipelineLayer *layer, + CoglBool dec_n_layers) +{ + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + /* Note: the last argument to _cogl_pipeline_pre_change_notify is + * needed to differentiate STATE_LAYER changes which don't affect + * the number of layers from those that do. NB: Layer change + * notifications that don't change the number of layers don't get + * forwarded to the fragend. */ + _cogl_pipeline_pre_change_notify (pipeline, + COGL_PIPELINE_STATE_LAYERS, + NULL, + !dec_n_layers); + + /* We only need to remove the layer difference if the pipeline is + * currently the owner. If it is not the owner then one of two + * things will happen to make sure this layer is replaced. If it is + * the last layer being removed then decrementing n_layers will + * ensure that the last layer is skipped. If it is any other layer + * then the subsequent layers will have been shifted down and cause + * it be replaced */ + if (layer->owner == pipeline) + { + layer->owner = NULL; + cogl_object_unref (layer); + + pipeline->layer_differences = + g_list_remove (pipeline->layer_differences, layer); + } + + pipeline->differences |= COGL_PIPELINE_STATE_LAYERS; + + if (dec_n_layers) + pipeline->n_layers--; +} + +static void +_cogl_pipeline_try_reverting_layers_authority (CoglPipeline *authority, + CoglPipeline *old_authority) +{ + if (authority->layer_differences == NULL && + _cogl_pipeline_get_parent (authority)) + { + /* If the previous _STATE_LAYERS authority has the same + * ->n_layers then we can revert to that being the authority + * again. */ + if (!old_authority) + { + old_authority = + _cogl_pipeline_get_authority (_cogl_pipeline_get_parent (authority), + COGL_PIPELINE_STATE_LAYERS); + } + + if (old_authority->n_layers == authority->n_layers) + authority->differences &= ~COGL_PIPELINE_STATE_LAYERS; + } +} + +void +_cogl_pipeline_update_real_blend_enable (CoglPipeline *pipeline, + CoglBool unknown_color_alpha) +{ + CoglPipeline *parent; + unsigned int differences; + + if (pipeline->dirty_real_blend_enable == FALSE && + pipeline->unknown_color_alpha == unknown_color_alpha) + return; + + if (pipeline->dirty_real_blend_enable) + { + differences = pipeline->differences; + + parent = _cogl_pipeline_get_parent (pipeline); + while (parent->dirty_real_blend_enable) + { + differences |= parent->differences; + parent = _cogl_pipeline_get_parent (parent); + } + + /* We initialize the pipeline's real_blend_enable with a known + * reference value from its nearest ancestor with clean state so + * we can then potentially reduce the work involved in checking + * if the pipeline really needs blending itself because we can + * just look at the things that differ between the ancestor and + * this pipeline. + */ + pipeline->real_blend_enable = parent->real_blend_enable; + } + else /* pipeline->unknown_color_alpha != unknown_color_alpha */ + differences = 0; + + /* Note we don't call _cogl_pipeline_pre_change_notify() for this + * state change because ->real_blend_enable is lazily derived from + * other state while flushing the pipeline and we'd need to avoid + * recursion problems in cases where _pre_change_notify() flushes + * the journal if the pipeline is referenced by a journal. + */ + pipeline->real_blend_enable = + _cogl_pipeline_needs_blending_enabled (pipeline, differences, + NULL, unknown_color_alpha); + pipeline->dirty_real_blend_enable = FALSE; + pipeline->unknown_color_alpha = unknown_color_alpha; +} + +typedef struct +{ + int keep_n; + int current_pos; + int first_index_to_prune; +} CoglPipelinePruneLayersInfo; + +static CoglBool +update_prune_layers_info_cb (CoglPipelineLayer *layer, void *user_data) +{ + CoglPipelinePruneLayersInfo *state = user_data; + + if (state->current_pos == state->keep_n) + { + state->first_index_to_prune = layer->index; + return FALSE; + } + state->current_pos++; + return TRUE; +} + +void +_cogl_pipeline_prune_to_n_layers (CoglPipeline *pipeline, int n) +{ + CoglPipeline *authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LAYERS); + CoglPipelinePruneLayersInfo state; + GList *l; + GList *next; + + if (authority->n_layers <= n) + return; + + /* This call to foreach_layer_internal needs to be done before + * calling pre_change_notify because it recreates the layer cache. + * We are relying on pre_change_notify to clear the layer cache + * before we change the number of layers */ + state.keep_n = n; + state.current_pos = 0; + _cogl_pipeline_foreach_layer_internal (pipeline, + update_prune_layers_info_cb, + &state); + + _cogl_pipeline_pre_change_notify (pipeline, + COGL_PIPELINE_STATE_LAYERS, + NULL, + FALSE); + + pipeline->differences |= COGL_PIPELINE_STATE_LAYERS; + pipeline->n_layers = n; + + /* It's possible that this pipeline owns some of the layers being + * discarded, so we'll need to unlink them... */ + for (l = pipeline->layer_differences; l; l = next) + { + CoglPipelineLayer *layer = l->data; + next = l->next; /* we're modifying the list we're iterating */ + + if (layer->index >= state.first_index_to_prune) + _cogl_pipeline_remove_layer_difference (pipeline, layer, FALSE); + } + + pipeline->differences |= COGL_PIPELINE_STATE_LAYERS; +} + +typedef struct +{ + /* The layer we are trying to find */ + int layer_index; + + /* The layer we find or untouched if not found */ + CoglPipelineLayer *layer; + + /* If the layer can't be found then a new layer should be + * inserted after this texture unit index... */ + int insert_after; + + /* When adding a layer we need the list of layers to shift up + * to a new texture unit. When removing we need the list of + * layers to shift down. + * + * Note: the list isn't sorted */ + CoglPipelineLayer **layers_to_shift; + int n_layers_to_shift; + + /* When adding a layer we don't need a complete list of + * layers_to_shift if we find a layer already corresponding to the + * layer_index. */ + CoglBool ignore_shift_layers_if_found; + +} CoglPipelineLayerInfo; + +/* Returns TRUE once we know there is nothing more to update */ +static CoglBool +update_layer_info (CoglPipelineLayer *layer, + CoglPipelineLayerInfo *layer_info) +{ + if (layer->index == layer_info->layer_index) + { + layer_info->layer = layer; + if (layer_info->ignore_shift_layers_if_found) + return TRUE; + } + else if (layer->index < layer_info->layer_index) + { + int unit_index = _cogl_pipeline_layer_get_unit_index (layer); + layer_info->insert_after = unit_index; + } + else + layer_info->layers_to_shift[layer_info->n_layers_to_shift++] = + layer; + + return FALSE; +} + +/* Returns FALSE to break out of a _foreach_layer () iteration */ +static CoglBool +update_layer_info_cb (CoglPipelineLayer *layer, + void *user_data) +{ + CoglPipelineLayerInfo *layer_info = user_data; + + if (update_layer_info (layer, layer_info)) + return FALSE; /* break */ + else + return TRUE; /* continue */ +} + +static void +_cogl_pipeline_get_layer_info (CoglPipeline *pipeline, + CoglPipelineLayerInfo *layer_info) +{ + /* Note: we are assuming this pipeline is a _STATE_LAYERS authority */ + int n_layers = pipeline->n_layers; + int i; + + /* FIXME: _cogl_pipeline_foreach_layer_internal now calls + * _cogl_pipeline_update_layers_cache anyway so this codepath is + * pointless! */ + if (layer_info->ignore_shift_layers_if_found && + pipeline->layers_cache_dirty) + { + /* The expectation is that callers of + * _cogl_pipeline_get_layer_info are likely to be modifying the + * list of layers associated with a pipeline so in this case + * where we don't have a cache of the layers and we don't + * necessarily have to iterate all the layers of the pipeline we + * use a foreach_layer callback instead of updating the cache + * and iterating that as below. */ + _cogl_pipeline_foreach_layer_internal (pipeline, + update_layer_info_cb, + layer_info); + return; + } + + _cogl_pipeline_update_layers_cache (pipeline); + for (i = 0; i < n_layers; i++) + { + CoglPipelineLayer *layer = pipeline->layers_cache[i]; + + if (update_layer_info (layer, layer_info)) + return; + } +} + +CoglPipelineLayer * +_cogl_pipeline_get_layer_with_flags (CoglPipeline *pipeline, + int layer_index, + CoglPipelineGetLayerFlags flags) +{ + CoglPipeline *authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LAYERS); + CoglPipelineLayerInfo layer_info; + CoglPipelineLayer *layer; + int unit_index; + int i; + CoglContext *ctx; + + /* The layer index of the layer we want info about */ + layer_info.layer_index = layer_index; + + /* If a layer already exists with the given index this will be + * updated. */ + layer_info.layer = NULL; + + /* If a layer isn't found for the given index we'll need to know + * where to insert a new layer. */ + layer_info.insert_after = -1; + + /* If a layer can't be found then we'll need to insert a new layer + * and bump up the texture unit for all layers with an index + * > layer_index. */ + layer_info.layers_to_shift = + g_alloca (sizeof (CoglPipelineLayer *) * authority->n_layers); + layer_info.n_layers_to_shift = 0; + + /* If an exact match is found though we don't need a complete + * list of layers with indices > layer_index... */ + layer_info.ignore_shift_layers_if_found = TRUE; + + _cogl_pipeline_get_layer_info (authority, &layer_info); + + if (layer_info.layer || (flags & COGL_PIPELINE_GET_LAYER_NO_CREATE)) + return layer_info.layer; + + ctx = _cogl_context_get_default (); + + unit_index = layer_info.insert_after + 1; + if (unit_index == 0) + layer = _cogl_pipeline_layer_copy (ctx->default_layer_0); + else + { + CoglPipelineLayer *new; + layer = _cogl_pipeline_layer_copy (ctx->default_layer_n); + new = _cogl_pipeline_set_layer_unit (NULL, layer, unit_index); + /* Since we passed a newly allocated layer we wouldn't expect + * _set_layer_unit() to have to allocate *another* layer. */ + g_assert (new == layer); + } + layer->index = layer_index; + + for (i = 0; i < layer_info.n_layers_to_shift; i++) + { + CoglPipelineLayer *shift_layer = layer_info.layers_to_shift[i]; + + unit_index = _cogl_pipeline_layer_get_unit_index (shift_layer); + _cogl_pipeline_set_layer_unit (pipeline, shift_layer, unit_index + 1); + /* NB: shift_layer may not be writeable so _set_layer_unit() + * will allocate a derived layer internally which will become + * owned by pipeline. Check the return value if we need to do + * anything else with this layer. */ + } + + _cogl_pipeline_add_layer_difference (pipeline, layer, TRUE); + + cogl_object_unref (layer); + + return layer; +} + +void +_cogl_pipeline_prune_empty_layer_difference (CoglPipeline *layers_authority, + CoglPipelineLayer *layer) +{ + /* Find the GList link that references the empty layer */ + GList *link = g_list_find (layers_authority->layer_differences, layer); + /* No pipeline directly owns the root node layer so this is safe... */ + CoglPipelineLayer *layer_parent = _cogl_pipeline_layer_get_parent (layer); + CoglPipelineLayerInfo layer_info; + CoglPipeline *old_layers_authority; + + _COGL_RETURN_IF_FAIL (link != NULL); + + /* If the layer's parent doesn't have an owner then we can simply + * take ownership ourselves and drop our reference on the empty + * layer. We don't want to take ownership of the root node layer so + * we also need to verify that the parent has a parent + */ + if (layer_parent->index == layer->index && layer_parent->owner == NULL && + _cogl_pipeline_layer_get_parent (layer_parent) != NULL) + { + cogl_object_ref (layer_parent); + layer_parent->owner = layers_authority; + link->data = layer_parent; + cogl_object_unref (layer); + recursively_free_layer_caches (layers_authority); + return; + } + + /* Now we want to find the layer that would become the authority for + * layer->index if we were to remove layer from + * layers_authority->layer_differences + */ + + /* The layer index of the layer we want info about */ + layer_info.layer_index = layer->index; + + /* If a layer already exists with the given index this will be + * updated. */ + layer_info.layer = NULL; + + /* If a layer can't be found then we'll need to insert a new layer + * and bump up the texture unit for all layers with an index + * > layer_index. */ + layer_info.layers_to_shift = + g_alloca (sizeof (CoglPipelineLayer *) * layers_authority->n_layers); + layer_info.n_layers_to_shift = 0; + + /* If an exact match is found though we don't need a complete + * list of layers with indices > layer_index... */ + layer_info.ignore_shift_layers_if_found = TRUE; + + /* We know the default/root pipeline isn't a LAYERS authority so it's + * safe to use the result of _cogl_pipeline_get_parent (layers_authority) + * without checking it. + */ + old_layers_authority = + _cogl_pipeline_get_authority (_cogl_pipeline_get_parent (layers_authority), + COGL_PIPELINE_STATE_LAYERS); + + _cogl_pipeline_get_layer_info (old_layers_authority, &layer_info); + + /* If layer is the defining layer for the corresponding ->index then + * we can't get rid of it. */ + if (!layer_info.layer) + return; + + /* If the layer that would become the authority for layer->index is + * _cogl_pipeline_layer_get_parent (layer) then we can simply remove the + * layer difference. */ + if (layer_info.layer == _cogl_pipeline_layer_get_parent (layer)) + { + _cogl_pipeline_remove_layer_difference (layers_authority, layer, FALSE); + _cogl_pipeline_try_reverting_layers_authority (layers_authority, + old_layers_authority); + } +} + +typedef struct +{ + int i; + CoglPipeline *pipeline; + unsigned long fallback_layers; +} CoglPipelineFallbackState; + +static CoglBool +fallback_layer_cb (CoglPipelineLayer *layer, void *user_data) +{ + CoglPipelineFallbackState *state = user_data; + CoglPipeline *pipeline = state->pipeline; + CoglTextureType texture_type = _cogl_pipeline_layer_get_texture_type (layer); + CoglTexture *texture = NULL; + COGL_STATIC_COUNTER (layer_fallback_counter, + "layer fallback counter", + "Increments each time a layer's texture is " + "forced to a fallback texture", + 0 /* no application private data */); + + _COGL_GET_CONTEXT (ctx, FALSE); + + if (!(state->fallback_layers & 1<i)) + return TRUE; + + COGL_COUNTER_INC (_cogl_uprof_context, layer_fallback_counter); + + switch (texture_type) + { + case COGL_TEXTURE_TYPE_2D: + texture = COGL_TEXTURE (ctx->default_gl_texture_2d_tex); + break; + + case COGL_TEXTURE_TYPE_3D: + texture = COGL_TEXTURE (ctx->default_gl_texture_3d_tex); + break; + + case COGL_TEXTURE_TYPE_RECTANGLE: + texture = COGL_TEXTURE (ctx->default_gl_texture_rect_tex); + break; + } + + if (texture == NULL) + { + g_warning ("We don't have a fallback texture we can use to fill " + "in for an invalid pipeline layer, since it was " + "using an unsupported texture target "); + /* might get away with this... */ + texture = COGL_TEXTURE (ctx->default_gl_texture_2d_tex); + } + + cogl_pipeline_set_layer_texture (pipeline, layer->index, texture); + + state->i++; + + return TRUE; +} + +typedef struct +{ + CoglPipeline *pipeline; + CoglTexture *texture; +} CoglPipelineOverrideLayerState; + +static CoglBool +override_layer_texture_cb (CoglPipelineLayer *layer, void *user_data) +{ + CoglPipelineOverrideLayerState *state = user_data; + + cogl_pipeline_set_layer_texture (state->pipeline, + layer->index, + state->texture); + + return TRUE; +} + +void +_cogl_pipeline_apply_overrides (CoglPipeline *pipeline, + CoglPipelineFlushOptions *options) +{ + COGL_STATIC_COUNTER (apply_overrides_counter, + "pipeline overrides counter", + "Increments each time we have to apply " + "override options to a pipeline", + 0 /* no application private data */); + + COGL_COUNTER_INC (_cogl_uprof_context, apply_overrides_counter); + + if (options->flags & COGL_PIPELINE_FLUSH_DISABLE_MASK) + { + int i; + + /* NB: we can assume that once we see one bit to disable + * a layer, all subsequent layers are also disabled. */ + for (i = 0; i < 32 && options->disable_layers & (1<flags & COGL_PIPELINE_FLUSH_FALLBACK_MASK) + { + CoglPipelineFallbackState state; + + state.i = 0; + state.pipeline = pipeline; + state.fallback_layers = options->fallback_layers; + + _cogl_pipeline_foreach_layer_internal (pipeline, + fallback_layer_cb, + &state); + } + + if (options->flags & COGL_PIPELINE_FLUSH_LAYER0_OVERRIDE) + { + CoglPipelineOverrideLayerState state; + + _cogl_pipeline_prune_to_n_layers (pipeline, 1); + + /* NB: we are overriding the first layer, but we don't know + * the user's given layer_index, which is why we use + * _cogl_pipeline_foreach_layer_internal() here even though we know + * there's only one layer. */ + state.pipeline = pipeline; + state.texture = options->layer0_override_texture; + _cogl_pipeline_foreach_layer_internal (pipeline, + override_layer_texture_cb, + &state); + } +} + +static CoglBool +_cogl_pipeline_layers_equal (CoglPipeline *authority0, + CoglPipeline *authority1, + unsigned long differences, + CoglPipelineEvalFlags flags) +{ + int i; + + if (authority0->n_layers != authority1->n_layers) + return FALSE; + + _cogl_pipeline_update_layers_cache (authority0); + _cogl_pipeline_update_layers_cache (authority1); + + for (i = 0; i < authority0->n_layers; i++) + { + if (!_cogl_pipeline_layer_equal (authority0->layers_cache[i], + authority1->layers_cache[i], + differences, + flags)) + return FALSE; + } + return TRUE; +} + +/* Determine the mask of differences between two pipelines */ +unsigned long +_cogl_pipeline_compare_differences (CoglPipeline *pipeline0, + CoglPipeline *pipeline1) +{ + GSList *head0 = NULL; + GSList *head1 = NULL; + CoglPipeline *node0; + CoglPipeline *node1; + int len0 = 0; + int len1 = 0; + int count; + GSList *common_ancestor0; + GSList *common_ancestor1; + unsigned long pipelines_difference = 0; + + /* Algorithm: + * + * 1) Walk the ancestors of each pipeline to the root node, adding a + * pointer to each ancester node to two linked lists + * + * 2) Compare the lists to find the nodes where they start to + * differ marking the common_ancestor node for each list. + * + * 3) For each list now iterate starting after the common_ancestor + * nodes ORing each nodes ->difference mask into the final + * differences mask. + */ + + for (node0 = pipeline0; node0; node0 = _cogl_pipeline_get_parent (node0)) + { + GSList *link = alloca (sizeof (GSList)); + link->next = head0; + link->data = node0; + head0 = link; + len0++; + } + for (node1 = pipeline1; node1; node1 = _cogl_pipeline_get_parent (node1)) + { + GSList *link = alloca (sizeof (GSList)); + link->next = head1; + link->data = node1; + head1 = link; + len1++; + } + + /* NB: There's no point looking at the head entries since we know both + * pipelines must have the same default pipeline as their root node. */ + common_ancestor0 = head0; + common_ancestor1 = head1; + head0 = head0->next; + head1 = head1->next; + count = MIN (len0, len1) - 1; + while (count--) + { + if (head0->data != head1->data) + break; + common_ancestor0 = head0; + common_ancestor1 = head1; + head0 = head0->next; + head1 = head1->next; + } + + for (head0 = common_ancestor0->next; head0; head0 = head0->next) + { + node0 = head0->data; + pipelines_difference |= node0->differences; + } + for (head1 = common_ancestor1->next; head1; head1 = head1->next) + { + node1 = head1->data; + pipelines_difference |= node1->differences; + } + + return pipelines_difference; +} + +static void +_cogl_pipeline_resolve_authorities (CoglPipeline *pipeline, + unsigned long differences, + CoglPipeline **authorities) +{ + unsigned long remaining = differences; + CoglPipeline *authority = pipeline; + + do + { + unsigned long found = authority->differences & remaining; + int i; + + if (found == 0) + continue; + + for (i = 0; TRUE; i++) + { + unsigned long state = (1L< found) + break; + } + + remaining &= ~found; + if (remaining == 0) + return; + } + while ((authority = _cogl_pipeline_get_parent (authority))); + + g_assert (remaining == 0); +} + +/* Comparison of two arbitrary pipelines is done by: + * 1) walking up the parents of each pipeline until a common + * ancestor is found, and at each step ORing together the + * difference masks. + * + * 2) using the final difference mask to determine which state + * groups to compare. + * + * This is used, for example, by the Cogl journal to compare pipelines so that + * it can split up geometry that needs different OpenGL state. + * + * XXX: When comparing texture layers, _cogl_pipeline_equal will actually + * compare the underlying GL texture handle that the Cogl texture uses so that + * atlas textures and sub textures will be considered equal if they point to + * the same texture. This is useful for comparing pipelines in the journal but + * it means that _cogl_pipeline_equal doesn't strictly compare whether the + * pipelines are the same. If we needed those semantics we could perhaps add + * another function or some flags to control the behaviour. + * + * XXX: Similarly when comparing the wrap modes, + * COGL_PIPELINE_WRAP_MODE_AUTOMATIC is considered to be the same as + * COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE because once they get to the + * journal stage they act exactly the same. + */ +CoglBool +_cogl_pipeline_equal (CoglPipeline *pipeline0, + CoglPipeline *pipeline1, + unsigned int differences, + unsigned long layer_differences, + CoglPipelineEvalFlags flags) +{ + unsigned long pipelines_difference; + CoglPipeline *authorities0[COGL_PIPELINE_STATE_SPARSE_COUNT]; + CoglPipeline *authorities1[COGL_PIPELINE_STATE_SPARSE_COUNT]; + int bit; + CoglBool ret; + + COGL_STATIC_TIMER (pipeline_equal_timer, + "Mainloop", /* parent */ + "_cogl_pipeline_equal", + "The time spent comparing cogl pipelines", + 0 /* no application private data */); + + COGL_TIMER_START (_cogl_uprof_context, pipeline_equal_timer); + + if (pipeline0 == pipeline1) + { + ret = TRUE; + goto done; + } + + ret = FALSE; + + _cogl_pipeline_update_real_blend_enable (pipeline0, FALSE); + _cogl_pipeline_update_real_blend_enable (pipeline1, FALSE); + + /* First check non-sparse properties */ + + if (differences & COGL_PIPELINE_STATE_REAL_BLEND_ENABLE && + pipeline0->real_blend_enable != pipeline1->real_blend_enable) + goto done; + + /* Then check sparse properties */ + + pipelines_difference = + _cogl_pipeline_compare_differences (pipeline0, pipeline1); + + /* Only compare the sparse state groups requested by the caller... */ + pipelines_difference &= differences; + + _cogl_pipeline_resolve_authorities (pipeline0, + pipelines_difference, + authorities0); + _cogl_pipeline_resolve_authorities (pipeline1, + pipelines_difference, + authorities1); + + COGL_FLAGS_FOREACH_START (&pipelines_difference, 1, bit) + { + /* XXX: We considered having an array of callbacks for each state index + * that we'd call here but decided that this way the compiler is more + * likely going to be able to in-line the comparison functions and use + * the index to jump straight to the required code. */ + switch ((CoglPipelineStateIndex)bit) + { + case COGL_PIPELINE_STATE_COLOR_INDEX: + if (!cogl_color_equal (&authorities0[bit]->color, + &authorities1[bit]->color)) + goto done; + break; + case COGL_PIPELINE_STATE_LIGHTING_INDEX: + if (!_cogl_pipeline_lighting_state_equal (authorities0[bit], + authorities1[bit])) + goto done; + break; + case COGL_PIPELINE_STATE_ALPHA_FUNC_INDEX: + if (!_cogl_pipeline_alpha_func_state_equal (authorities0[bit], + authorities1[bit])) + goto done; + break; + case COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE_INDEX: + if (!_cogl_pipeline_alpha_func_reference_state_equal ( + authorities0[bit], + authorities1[bit])) + goto done; + break; + case COGL_PIPELINE_STATE_BLEND_INDEX: + /* We don't need to compare the detailed blending state if we know + * blending is disabled for both pipelines. */ + if (pipeline0->real_blend_enable) + { + if (!_cogl_pipeline_blend_state_equal (authorities0[bit], + authorities1[bit])) + goto done; + } + break; + case COGL_PIPELINE_STATE_DEPTH_INDEX: + if (!_cogl_pipeline_depth_state_equal (authorities0[bit], + authorities1[bit])) + goto done; + break; + case COGL_PIPELINE_STATE_FOG_INDEX: + if (!_cogl_pipeline_fog_state_equal (authorities0[bit], + authorities1[bit])) + goto done; + break; + case COGL_PIPELINE_STATE_CULL_FACE_INDEX: + if (!_cogl_pipeline_cull_face_state_equal (authorities0[bit], + authorities1[bit])) + goto done; + break; + case COGL_PIPELINE_STATE_NON_ZERO_POINT_SIZE_INDEX: + if (!_cogl_pipeline_non_zero_point_size_equal (authorities0[bit], + authorities1[bit])) + goto done; + break; + case COGL_PIPELINE_STATE_POINT_SIZE_INDEX: + if (!_cogl_pipeline_point_size_equal (authorities0[bit], + authorities1[bit])) + goto done; + break; + case COGL_PIPELINE_STATE_PER_VERTEX_POINT_SIZE_INDEX: + if (!_cogl_pipeline_per_vertex_point_size_equal (authorities0[bit], + authorities1[bit])) + goto done; + break; + case COGL_PIPELINE_STATE_LOGIC_OPS_INDEX: + if (!_cogl_pipeline_logic_ops_state_equal (authorities0[bit], + authorities1[bit])) + goto done; + break; + case COGL_PIPELINE_STATE_USER_SHADER_INDEX: + if (!_cogl_pipeline_user_shader_equal (authorities0[bit], + authorities1[bit])) + goto done; + break; + case COGL_PIPELINE_STATE_UNIFORMS_INDEX: + if (!_cogl_pipeline_uniforms_state_equal (authorities0[bit], + authorities1[bit])) + goto done; + break; + case COGL_PIPELINE_STATE_VERTEX_SNIPPETS_INDEX: + if (!_cogl_pipeline_vertex_snippets_state_equal (authorities0[bit], + authorities1[bit])) + goto done; + break; + case COGL_PIPELINE_STATE_FRAGMENT_SNIPPETS_INDEX: + if (!_cogl_pipeline_fragment_snippets_state_equal (authorities0[bit], + authorities1[bit])) + goto done; + break; + case COGL_PIPELINE_STATE_LAYERS_INDEX: + { + if (!_cogl_pipeline_layers_equal (authorities0[bit], + authorities1[bit], + layer_differences, + flags)) + goto done; + break; + } + + case COGL_PIPELINE_STATE_BLEND_ENABLE_INDEX: + case COGL_PIPELINE_STATE_REAL_BLEND_ENABLE_INDEX: + case COGL_PIPELINE_STATE_COUNT: + g_warn_if_reached (); + } + } + COGL_FLAGS_FOREACH_END; + + ret = TRUE; +done: + COGL_TIMER_STOP (_cogl_uprof_context, pipeline_equal_timer); + return ret; +} + +void +_cogl_pipeline_prune_redundant_ancestry (CoglPipeline *pipeline) +{ + CoglPipeline *new_parent = _cogl_pipeline_get_parent (pipeline); + + /* Before considering pruning redundant ancestry we check if this + * pipeline is an authority for layer state and if so only consider + * reparenting if it *owns* all the layers it depends on. NB: A + * pipeline can be be a STATE_LAYERS authority but it may still + * defer to its ancestors to define the state for some of its + * layers. + * + * For example a pipeline that derives from a parent with 5 layers + * can become a STATE_LAYERS authority by simply changing it's + * ->n_layers count to 4 and in that case it can still defer to its + * ancestors to define the state of those 4 layers. + * + * If a pipeline depends on any ancestors for layer state then we + * immediatly bail out. + */ + if (pipeline->differences & COGL_PIPELINE_STATE_LAYERS) + { + if (pipeline->n_layers != g_list_length (pipeline->layer_differences)) + return; + } + + /* walk up past ancestors that are now redundant and potentially + * reparent the pipeline. */ + while (_cogl_pipeline_get_parent (new_parent) && + (new_parent->differences | pipeline->differences) == + pipeline->differences) + new_parent = _cogl_pipeline_get_parent (new_parent); + + if (new_parent != _cogl_pipeline_get_parent (pipeline)) + { + CoglBool is_weak = _cogl_pipeline_is_weak (pipeline); + _cogl_pipeline_set_parent (pipeline, new_parent, is_weak ? FALSE : TRUE); + } +} + +void +_cogl_pipeline_update_authority (CoglPipeline *pipeline, + CoglPipeline *authority, + CoglPipelineState state, + CoglPipelineStateComparitor comparitor) +{ + /* If we are the current authority see if we can revert to one of + * our ancestors being the authority */ + if (pipeline == authority && + _cogl_pipeline_get_parent (authority) != NULL) + { + CoglPipeline *parent = _cogl_pipeline_get_parent (authority); + CoglPipeline *old_authority = + _cogl_pipeline_get_authority (parent, state); + + if (comparitor (authority, old_authority)) + pipeline->differences &= ~state; + } + else if (pipeline != authority) + { + /* If we weren't previously the authority on this state then we + * need to extended our differences mask and so it's possible + * that some of our ancestry will now become redundant, so we + * aim to reparent ourselves if that's true... */ + pipeline->differences |= state; + _cogl_pipeline_prune_redundant_ancestry (pipeline); + } +} + +CoglBool +_cogl_pipeline_get_fog_enabled (CoglPipeline *pipeline) +{ + CoglPipeline *authority; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), FALSE); + + authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_FOG); + return authority->big_state->fog_state.enabled; +} + +unsigned long +_cogl_pipeline_get_age (CoglPipeline *pipeline) +{ + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), 0); + + return pipeline->age; +} + +void +cogl_pipeline_remove_layer (CoglPipeline *pipeline, int layer_index) +{ + CoglPipeline *authority; + CoglPipelineLayerInfo layer_info; + int i; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LAYERS); + + /* The layer index of the layer we want info about */ + layer_info.layer_index = layer_index; + + /* This will be updated with a reference to the layer being removed + * if it can be found. */ + layer_info.layer = NULL; + + /* This will be filled in with a list of layers that need to be + * dropped down to a lower texture unit to fill the gap of the + * removed layer. */ + layer_info.layers_to_shift = + g_alloca (sizeof (CoglPipelineLayer *) * authority->n_layers); + layer_info.n_layers_to_shift = 0; + + /* Unlike when we query layer info when adding a layer we must + * always have a complete layers_to_shift list... */ + layer_info.ignore_shift_layers_if_found = FALSE; + + _cogl_pipeline_get_layer_info (authority, &layer_info); + + if (layer_info.layer == NULL) + return; + + for (i = 0; i < layer_info.n_layers_to_shift; i++) + { + CoglPipelineLayer *shift_layer = layer_info.layers_to_shift[i]; + int unit_index = _cogl_pipeline_layer_get_unit_index (shift_layer); + _cogl_pipeline_set_layer_unit (pipeline, shift_layer, unit_index - 1); + /* NB: shift_layer may not be writeable so _set_layer_unit() + * will allocate a derived layer internally which will become + * owned by pipeline. Check the return value if we need to do + * anything else with this layer. */ + } + + _cogl_pipeline_remove_layer_difference (pipeline, layer_info.layer, TRUE); + _cogl_pipeline_try_reverting_layers_authority (pipeline, NULL); + + pipeline->dirty_real_blend_enable = TRUE; +} + +static CoglBool +prepend_layer_to_list_cb (CoglPipelineLayer *layer, + void *user_data) +{ + GList **layers = user_data; + + *layers = g_list_prepend (*layers, layer); + return TRUE; +} + +/* TODO: deprecate this API and replace it with + * cogl_pipeline_foreach_layer + * TODO: update the docs to note that if the user modifies any layers + * then the list may become invalid. + */ +const GList * +_cogl_pipeline_get_layers (CoglPipeline *pipeline) +{ + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), NULL); + + if (!pipeline->deprecated_get_layers_list_dirty) + g_list_free (pipeline->deprecated_get_layers_list); + + pipeline->deprecated_get_layers_list = NULL; + + _cogl_pipeline_foreach_layer_internal (pipeline, + prepend_layer_to_list_cb, + &pipeline->deprecated_get_layers_list); + pipeline->deprecated_get_layers_list = + g_list_reverse (pipeline->deprecated_get_layers_list); + + pipeline->deprecated_get_layers_list_dirty = 0; + + return pipeline->deprecated_get_layers_list; +} + +int +cogl_pipeline_get_n_layers (CoglPipeline *pipeline) +{ + CoglPipeline *authority; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), 0); + + authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LAYERS); + + return authority->n_layers; +} + +void +_cogl_pipeline_pre_paint_for_layer (CoglPipeline *pipeline, + int layer_id) +{ + CoglPipelineLayer *layer = _cogl_pipeline_get_layer (pipeline, layer_id); + _cogl_pipeline_layer_pre_paint (layer); +} + +/* While a pipeline is referenced by the Cogl journal we can not allow + * modifications, so this gives us a mechanism to track journal + * references separately */ +CoglPipeline * +_cogl_pipeline_journal_ref (CoglPipeline *pipeline) +{ + pipeline->journal_ref_count++; + return cogl_object_ref (pipeline); +} + +void +_cogl_pipeline_journal_unref (CoglPipeline *pipeline) +{ + pipeline->journal_ref_count--; + cogl_object_unref (pipeline); +} + +#ifdef COGL_DEBUG_ENABLED +void +_cogl_pipeline_apply_legacy_state (CoglPipeline *pipeline) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + /* It was a mistake that we ever copied the OpenGL style API for + * associating these things directly with the context when we + * originally wrote Cogl. Until the corresponding deprecated APIs + * can be removed though we now shoehorn the state changes through + * the cogl_pipeline API instead. + */ + + /* A program explicitly set on the pipeline has higher precedence than + * one associated with the context using cogl_program_use() */ + if (ctx->current_program && + cogl_pipeline_get_user_program (pipeline) == COGL_INVALID_HANDLE) + cogl_pipeline_set_user_program (pipeline, ctx->current_program); + + if (ctx->legacy_depth_test_enabled) + { + CoglDepthState depth_state; + cogl_depth_state_init (&depth_state); + cogl_depth_state_set_test_enabled (&depth_state, TRUE); + cogl_pipeline_set_depth_state (pipeline, &depth_state, NULL); + } + + if (ctx->legacy_fog_state.enabled) + _cogl_pipeline_set_fog_state (pipeline, &ctx->legacy_fog_state); + + if (ctx->legacy_backface_culling_enabled) + cogl_pipeline_set_cull_face_mode (pipeline, + COGL_PIPELINE_CULL_FACE_MODE_BACK); +} + +void +_cogl_pipeline_set_static_breadcrumb (CoglPipeline *pipeline, + const char *breadcrumb) +{ + pipeline->has_static_breadcrumb = TRUE; + pipeline->static_breadcrumb = breadcrumb; +} +#endif + +typedef void (*LayerStateHashFunction) (CoglPipelineLayer *authority, + CoglPipelineLayer **authorities, + CoglPipelineHashState *state); + +static LayerStateHashFunction +layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT]; + +/* XXX: We don't statically initialize the array of hash functions, so + * we won't get caught out by later re-indexing the groups for some + * reason. */ +void +_cogl_pipeline_init_layer_state_hash_functions (void) +{ + CoglPipelineLayerStateIndex _index; + layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_UNIT_INDEX] = + _cogl_pipeline_layer_hash_unit_state; + layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_TEXTURE_TYPE_INDEX] = + _cogl_pipeline_layer_hash_texture_type_state; + layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA_INDEX] = + _cogl_pipeline_layer_hash_texture_data_state; + layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_SAMPLER_INDEX] = + _cogl_pipeline_layer_hash_sampler_state; + layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_COMBINE_INDEX] = + _cogl_pipeline_layer_hash_combine_state; + layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT_INDEX] = + _cogl_pipeline_layer_hash_combine_constant_state; + layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_USER_MATRIX_INDEX] = + _cogl_pipeline_layer_hash_user_matrix_state; + _index = COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS_INDEX; + layer_state_hash_functions[_index] = + _cogl_pipeline_layer_hash_point_sprite_state; + _index = COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS_INDEX; + layer_state_hash_functions[_index] = + _cogl_pipeline_layer_hash_point_sprite_state; + _index = COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS_INDEX; + layer_state_hash_functions[_index] = + _cogl_pipeline_layer_hash_fragment_snippets_state; + + { + /* So we get a big error if we forget to update this code! */ + _COGL_STATIC_ASSERT (COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT == 10, + "Don't forget to install a hash function for new " + "pipeline state and update assert at end of " + "_cogl_pipeline_init_state_hash_functions"); + } +} + +static CoglBool +_cogl_pipeline_hash_layer_cb (CoglPipelineLayer *layer, + void *user_data) +{ + CoglPipelineHashState *state = user_data; + unsigned long differences = state->layer_differences; + CoglPipelineLayer *authorities[COGL_PIPELINE_LAYER_STATE_COUNT]; + unsigned long mask; + int i; + + /* Theoretically we would hash non-sparse layer state here but + * currently layers don't have any. */ + + /* XXX: we resolve all the authorities here - not just those + * corresponding to hash_state->layer_differences - because + * the hashing of some state groups actually depends on the values + * in other groups. For example we don't hash layer combine + * constants if they are aren't referenced by the current layer + * combine function. + */ + mask = COGL_PIPELINE_LAYER_STATE_ALL_SPARSE; + _cogl_pipeline_layer_resolve_authorities (layer, + mask, + authorities); + + /* So we go right ahead and hash the sparse state... */ + for (i = 0; i < COGL_PIPELINE_LAYER_STATE_COUNT; i++) + { + unsigned long current_state = (1L< differences) + break; + } + + return TRUE; +} + +void +_cogl_pipeline_hash_layers_state (CoglPipeline *authority, + CoglPipelineHashState *state) +{ + state->hash = + _cogl_util_one_at_a_time_hash (state->hash, &authority->n_layers, + sizeof (authority->n_layers)); + _cogl_pipeline_foreach_layer_internal (authority, + _cogl_pipeline_hash_layer_cb, + state); +} + +typedef void (*StateHashFunction) (CoglPipeline *authority, CoglPipelineHashState *state); + +static StateHashFunction +state_hash_functions[COGL_PIPELINE_STATE_SPARSE_COUNT]; + +/* We don't statically initialize the array of hash functions + * so we won't get caught out by later re-indexing the groups for + * some reason. */ +void +_cogl_pipeline_init_state_hash_functions (void) +{ + state_hash_functions[COGL_PIPELINE_STATE_COLOR_INDEX] = + _cogl_pipeline_hash_color_state; + state_hash_functions[COGL_PIPELINE_STATE_BLEND_ENABLE_INDEX] = + _cogl_pipeline_hash_blend_enable_state; + state_hash_functions[COGL_PIPELINE_STATE_LAYERS_INDEX] = + _cogl_pipeline_hash_layers_state; + state_hash_functions[COGL_PIPELINE_STATE_LIGHTING_INDEX] = + _cogl_pipeline_hash_lighting_state; + state_hash_functions[COGL_PIPELINE_STATE_ALPHA_FUNC_INDEX] = + _cogl_pipeline_hash_alpha_func_state; + state_hash_functions[COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE_INDEX] = + _cogl_pipeline_hash_alpha_func_reference_state; + state_hash_functions[COGL_PIPELINE_STATE_BLEND_INDEX] = + _cogl_pipeline_hash_blend_state; + state_hash_functions[COGL_PIPELINE_STATE_USER_SHADER_INDEX] = + _cogl_pipeline_hash_user_shader_state; + state_hash_functions[COGL_PIPELINE_STATE_DEPTH_INDEX] = + _cogl_pipeline_hash_depth_state; + state_hash_functions[COGL_PIPELINE_STATE_FOG_INDEX] = + _cogl_pipeline_hash_fog_state; + state_hash_functions[COGL_PIPELINE_STATE_CULL_FACE_INDEX] = + _cogl_pipeline_hash_cull_face_state; + state_hash_functions[COGL_PIPELINE_STATE_NON_ZERO_POINT_SIZE_INDEX] = + _cogl_pipeline_hash_non_zero_point_size_state; + state_hash_functions[COGL_PIPELINE_STATE_POINT_SIZE_INDEX] = + _cogl_pipeline_hash_point_size_state; + state_hash_functions[COGL_PIPELINE_STATE_PER_VERTEX_POINT_SIZE_INDEX] = + _cogl_pipeline_hash_per_vertex_point_size_state; + state_hash_functions[COGL_PIPELINE_STATE_LOGIC_OPS_INDEX] = + _cogl_pipeline_hash_logic_ops_state; + state_hash_functions[COGL_PIPELINE_STATE_UNIFORMS_INDEX] = + _cogl_pipeline_hash_uniforms_state; + state_hash_functions[COGL_PIPELINE_STATE_VERTEX_SNIPPETS_INDEX] = + _cogl_pipeline_hash_vertex_snippets_state; + state_hash_functions[COGL_PIPELINE_STATE_FRAGMENT_SNIPPETS_INDEX] = + _cogl_pipeline_hash_fragment_snippets_state; + + { + /* So we get a big error if we forget to update this code! */ + _COGL_STATIC_ASSERT (COGL_PIPELINE_STATE_SPARSE_COUNT == 18, + "Make sure to install a hash function for " + "newly added pipeline state and update assert " + "in _cogl_pipeline_init_state_hash_functions"); + } +} + +unsigned int +_cogl_pipeline_hash (CoglPipeline *pipeline, + unsigned int differences, + unsigned long layer_differences, + CoglPipelineEvalFlags flags) +{ + CoglPipeline *authorities[COGL_PIPELINE_STATE_SPARSE_COUNT]; + unsigned int mask; + int i; + CoglPipelineHashState state; + unsigned int final_hash = 0; + + state.hash = 0; + state.layer_differences = layer_differences; + state.flags = flags; + + _cogl_pipeline_update_real_blend_enable (pipeline, FALSE); + + /* hash non-sparse state */ + + if (differences & COGL_PIPELINE_STATE_REAL_BLEND_ENABLE) + { + CoglBool enable = pipeline->real_blend_enable; + state.hash = + _cogl_util_one_at_a_time_hash (state.hash, &enable, sizeof (enable)); + } + + /* hash sparse state */ + + mask = differences & COGL_PIPELINE_STATE_ALL_SPARSE; + _cogl_pipeline_resolve_authorities (pipeline, mask, authorities); + + for (i = 0; i < COGL_PIPELINE_STATE_SPARSE_COUNT; i++) + { + unsigned int current_state = (1< differences) + break; + } + + return _cogl_util_one_at_a_time_mix (final_hash); +} + +typedef struct +{ + CoglContext *context; + CoglPipeline *src_pipeline; + CoglPipeline *dst_pipeline; + unsigned int layer_differences; +} DeepCopyData; + +static CoglBool +deep_copy_layer_cb (CoglPipelineLayer *src_layer, + void *user_data) +{ + DeepCopyData *data = user_data; + CoglPipelineLayer *dst_layer; + unsigned int differences = data->layer_differences; + + dst_layer = _cogl_pipeline_get_layer (data->dst_pipeline, src_layer->index); + + while (src_layer != data->context->default_layer_n && + src_layer != data->context->default_layer_0 && + differences) + { + unsigned long to_copy = differences & src_layer->differences; + + if (to_copy) + { + _cogl_pipeline_layer_copy_differences (dst_layer, src_layer, to_copy); + differences ^= to_copy; + } + + src_layer = COGL_PIPELINE_LAYER (COGL_NODE (src_layer)->parent); + } + + return TRUE; +} + +CoglPipeline * +_cogl_pipeline_deep_copy (CoglPipeline *pipeline, + unsigned long differences, + unsigned long layer_differences) +{ + CoglPipeline *new, *authority; + CoglBool copy_layer_state; + + _COGL_GET_CONTEXT (ctx, NULL); + + if ((differences & COGL_PIPELINE_STATE_LAYERS)) + { + copy_layer_state = TRUE; + differences &= ~COGL_PIPELINE_STATE_LAYERS; + } + else + copy_layer_state = FALSE; + + new = cogl_pipeline_new (ctx); + + for (authority = pipeline; + authority != ctx->default_pipeline && differences; + authority = COGL_PIPELINE (COGL_NODE (authority)->parent)) + { + unsigned long to_copy = differences & authority->differences; + + if (to_copy) + { + _cogl_pipeline_copy_differences (new, authority, to_copy); + differences ^= to_copy; + } + } + + if (copy_layer_state) + { + DeepCopyData data; + + /* The unit index doesn't need to be copied because it should + * end up with the same values anyway because the new pipeline + * will have the same indices as the source pipeline */ + layer_differences &= ~COGL_PIPELINE_LAYER_STATE_UNIT; + + data.context = ctx; + data.src_pipeline = pipeline; + data.dst_pipeline = new; + data.layer_differences = layer_differences; + + _cogl_pipeline_foreach_layer_internal (pipeline, + deep_copy_layer_cb, + &data); + } + + return new; +} + +typedef struct +{ + int i; + CoglPipelineLayer **layers; +} AddLayersToArrayState; + +static CoglBool +add_layer_to_array_cb (CoglPipelineLayer *layer, + void *user_data) +{ + AddLayersToArrayState *state = user_data; + state->layers[state->i++] = layer; + return TRUE; +} + +/* This tries to find the oldest ancestor whose pipeline and layer + state matches the given flags. This is mostly used to detect code + gen authorities so that we can reduce the numer of programs + generated */ +CoglPipeline * +_cogl_pipeline_find_equivalent_parent (CoglPipeline *pipeline, + CoglPipelineState pipeline_state, + CoglPipelineLayerState layer_state) +{ + CoglPipeline *authority0; + CoglPipeline *authority1; + int n_layers; + CoglPipelineLayer **authority0_layers; + CoglPipelineLayer **authority1_layers; + + /* Find the first pipeline that modifies state that affects the + * state or any layer state... */ + authority0 = _cogl_pipeline_get_authority (pipeline, + pipeline_state | + COGL_PIPELINE_STATE_LAYERS); + + /* Find the next ancestor after that, that also modifies the + * state... */ + if (_cogl_pipeline_get_parent (authority0)) + { + authority1 = + _cogl_pipeline_get_authority (_cogl_pipeline_get_parent (authority0), + pipeline_state | + COGL_PIPELINE_STATE_LAYERS); + } + else + return authority0; + + n_layers = cogl_pipeline_get_n_layers (authority0); + + for (;;) + { + AddLayersToArrayState state; + int i; + + if (n_layers != cogl_pipeline_get_n_layers (authority1)) + return authority0; + + /* If the programs differ by anything that isn't part of the + layer state then we can't continue */ + if (pipeline_state && + (_cogl_pipeline_compare_differences (authority0, authority1) & + pipeline_state)) + return authority0; + + authority0_layers = + g_alloca (sizeof (CoglPipelineLayer *) * n_layers); + state.i = 0; + state.layers = authority0_layers; + _cogl_pipeline_foreach_layer_internal (authority0, + add_layer_to_array_cb, + &state); + + authority1_layers = + g_alloca (sizeof (CoglPipelineLayer *) * n_layers); + state.i = 0; + state.layers = authority1_layers; + _cogl_pipeline_foreach_layer_internal (authority1, + add_layer_to_array_cb, + &state); + + for (i = 0; i < n_layers; i++) + { + unsigned long layer_differences; + + if (authority0_layers[i] == authority1_layers[i]) + continue; + + layer_differences = + _cogl_pipeline_layer_compare_differences (authority0_layers[i], + authority1_layers[i]); + + if (layer_differences & layer_state) + return authority0; + } + + /* Find the next ancestor after that, that also modifies state + * affecting codegen... */ + + if (!_cogl_pipeline_get_parent (authority1)) + break; + + authority0 = authority1; + authority1 = + _cogl_pipeline_get_authority (_cogl_pipeline_get_parent (authority1), + pipeline_state | + COGL_PIPELINE_STATE_LAYERS); + if (authority1 == authority0) + break; + } + + return authority1; +} + +CoglPipelineState +_cogl_pipeline_get_state_for_vertex_codegen (CoglContext *context) +{ + CoglPipelineState state = (COGL_PIPELINE_STATE_LAYERS | + COGL_PIPELINE_STATE_USER_SHADER | + COGL_PIPELINE_STATE_PER_VERTEX_POINT_SIZE | + COGL_PIPELINE_STATE_VERTEX_SNIPPETS); + + /* If we don't have the builtin point size uniform then we'll add + * one in the GLSL but we'll only do this if the point size is + * non-zero. Whether or not the point size is zero is represented by + * COGL_PIPELINE_STATE_NON_ZERO_POINT_SIZE */ + if (!_cogl_has_private_feature + (context, COGL_PRIVATE_FEATURE_BUILTIN_POINT_SIZE_UNIFORM)) + state |= COGL_PIPELINE_STATE_NON_ZERO_POINT_SIZE; + + return state; +} + +CoglPipelineLayerState +_cogl_pipeline_get_layer_state_for_fragment_codegen (CoglContext *context) +{ + CoglPipelineLayerState state = + (COGL_PIPELINE_LAYER_STATE_COMBINE | + COGL_PIPELINE_LAYER_STATE_TEXTURE_TYPE | + COGL_PIPELINE_LAYER_STATE_UNIT | + COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS); + + /* If the driver supports GLSL then we might be using gl_PointCoord + * to implement the sprite coords. In that case the generated code + * depends on the point sprite state */ + if (cogl_has_feature (context, COGL_FEATURE_ID_GLSL)) + state |= COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS; + + return state; +} + +CoglPipelineState +_cogl_pipeline_get_state_for_fragment_codegen (CoglContext *context) +{ + CoglPipelineState state = (COGL_PIPELINE_STATE_LAYERS | + COGL_PIPELINE_STATE_USER_SHADER | + COGL_PIPELINE_STATE_FRAGMENT_SNIPPETS); + + if (!_cogl_has_private_feature (context, COGL_PRIVATE_FEATURE_ALPHA_TEST)) + state |= COGL_PIPELINE_STATE_ALPHA_FUNC; + + return state; +} + +int +cogl_pipeline_get_uniform_location (CoglPipeline *pipeline, + const char *uniform_name) +{ + void *location_ptr; + char *uniform_name_copy; + + _COGL_GET_CONTEXT (ctx, -1); + + /* This API is designed as if the uniform locations are specific to + a pipeline but they are actually unique across a whole + CoglContext. Potentially this could just be + cogl_context_get_uniform_location but it seems to make sense to + keep the API this way so that we can change the internals if need + be. */ + + /* Look for an existing uniform with this name */ + if (g_hash_table_lookup_extended (ctx->uniform_name_hash, + uniform_name, + NULL, + &location_ptr)) + return GPOINTER_TO_INT (location_ptr); + + uniform_name_copy = g_strdup (uniform_name); + g_ptr_array_add (ctx->uniform_names, uniform_name_copy); + g_hash_table_insert (ctx->uniform_name_hash, + uniform_name_copy, + GINT_TO_POINTER (ctx->n_uniform_names)); + + return ctx->n_uniform_names++; +} diff --git a/cogl/cogl/cogl-pipeline.h b/cogl/cogl/cogl-pipeline.h new file mode 100644 index 0000000..6558735 --- /dev/null +++ b/cogl/cogl/cogl-pipeline.h @@ -0,0 +1,185 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_PIPELINE_H__ +#define __COGL_PIPELINE_H__ + +/* We forward declare the CoglPipeline type here to avoid some circular + * dependency issues with the following headers. + */ +typedef struct _CoglPipeline CoglPipeline; + +#include +#include +#include + +#include + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-pipeline + * @short_description: Functions for creating and manipulating the GPU + * pipeline + * + * Cogl allows creating and manipulating objects representing the full + * configuration of the GPU pipeline. In simplified terms the GPU + * pipeline takes primitive geometry as the input, it first performs + * vertex processing, allowing you to deform your geometry, then + * rasterizes that (turning it from pure geometry into fragments) then + * performs fragment processing including depth testing and texture + * mapping. Finally it blends the result with the framebuffer. + */ + +#define COGL_PIPELINE(OBJECT) ((CoglPipeline *)OBJECT) + +/** + * cogl_pipeline_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_pipeline_get_gtype (void); + +/** + * cogl_pipeline_new: + * @context: a #CoglContext + * + * Allocates and initializes a default simple pipeline that will color + * a primitive white. + * + * Return value: (transfer full): a pointer to a new #CoglPipeline + * + * Since: 2.0 + * Stability: Unstable + */ +CoglPipeline * +cogl_pipeline_new (CoglContext *context); + +/** + * cogl_pipeline_copy: + * @source: a #CoglPipeline object to copy + * + * Creates a new pipeline with the configuration copied from the + * source pipeline. + * + * We would strongly advise developers to always aim to use + * cogl_pipeline_copy() instead of cogl_pipeline_new() whenever there will + * be any similarity between two pipelines. Copying a pipeline helps Cogl + * keep track of a pipelines ancestry which we may use to help minimize GPU + * state changes. + * + * Return value: (transfer full): a pointer to the newly allocated #CoglPipeline + * + * Since: 2.0 + * Stability: Unstable + */ +CoglPipeline * +cogl_pipeline_copy (CoglPipeline *source); + +/** + * cogl_is_pipeline: + * @object: A #CoglObject + * + * Gets whether the given @object references an existing pipeline object. + * + * Return value: %TRUE if the @object references a #CoglPipeline, + * %FALSE otherwise + * + * Since: 2.0 + * Stability: Unstable + */ +CoglBool +cogl_is_pipeline (void *object); + +/** + * CoglPipelineLayerCallback: + * @pipeline: The #CoglPipeline whos layers are being iterated + * @layer_index: The current layer index + * @user_data: The private data passed to cogl_pipeline_foreach_layer() + * + * The callback prototype used with cogl_pipeline_foreach_layer() for + * iterating all the layers of a @pipeline. + * + * Since: 2.0 + * Stability: Unstable + */ +typedef CoglBool (*CoglPipelineLayerCallback) (CoglPipeline *pipeline, + int layer_index, + void *user_data); + +/** + * cogl_pipeline_foreach_layer: + * @pipeline: A #CoglPipeline object + * @callback: (scope call): A #CoglPipelineLayerCallback to be + * called for each layer index + * @user_data: (closure): Private data that will be passed to the + * callback + * + * Iterates all the layer indices of the given @pipeline. + * + * Since: 2.0 + * Stability: Unstable + */ +void +cogl_pipeline_foreach_layer (CoglPipeline *pipeline, + CoglPipelineLayerCallback callback, + void *user_data); + +/** + * cogl_pipeline_get_uniform_location: + * @pipeline: A #CoglPipeline object + * @uniform_name: The name of a uniform + * + * This is used to get an integer representing the uniform with the + * name @uniform_name. The integer can be passed to functions such as + * cogl_pipeline_set_uniform_1f() to set the value of a uniform. + * + * This function will always return a valid integer. Ie, unlike + * OpenGL, it does not return -1 if the uniform is not available in + * this pipeline so it can not be used to test whether uniforms are + * present. It is not necessary to set the program on the pipeline + * before calling this function. + * + * Return value: A integer representing the location of the given uniform. + * + * Since: 2.0 + * Stability: Unstable + */ +int +cogl_pipeline_get_uniform_location (CoglPipeline *pipeline, + const char *uniform_name); + +COGL_END_DECLS + +#endif /* __COGL_PIPELINE_H__ */ diff --git a/cogl/cogl/cogl-pixel-buffer-private.h b/cogl/cogl/cogl-pixel-buffer-private.h new file mode 100644 index 0000000..2735277 --- /dev/null +++ b/cogl/cogl/cogl-pixel-buffer-private.h @@ -0,0 +1,52 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Damien Lespiau + * Robert Bragg + */ + +#ifndef __COGL_PIXEL_BUFFER_PRIVATE_H__ +#define __COGL_PIXEL_BUFFER_PRIVATE_H__ + +#include "cogl-object-private.h" +#include "cogl-buffer-private.h" + +#include + +COGL_BEGIN_DECLS + +struct _CoglPixelBuffer +{ + CoglBuffer _parent; +}; + +COGL_END_DECLS + +#endif /* __COGL_PIXEL_BUFFER_PRIVATE_H__ */ diff --git a/cogl/cogl/cogl-pixel-buffer.c b/cogl/cogl/cogl-pixel-buffer.c new file mode 100644 index 0000000..348f74a --- /dev/null +++ b/cogl/cogl/cogl-pixel-buffer.c @@ -0,0 +1,134 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Damien Lespiau + * Robert Bragg + */ + +/* For an overview of the functionality implemented here, please see + * cogl-buffer-array.h, which contains the gtk-doc section overview for the + * Pixel Buffers API. + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include +#include +#include + +#include "cogl-private.h" +#include "cogl-util.h" +#include "cogl-context-private.h" +#include "cogl-object.h" +#include "cogl-pixel-buffer-private.h" +#include "cogl-pixel-buffer.h" +#include "cogl-gtype-private.h" + +/* + * GL/GLES compatibility defines for the buffer API: + */ + +#if defined (HAVE_COGL_GL) + +#ifndef GL_PIXEL_UNPACK_BUFFER +#define GL_PIXEL_UNPACK_BUFFER GL_PIXEL_UNPACK_BUFFER_ARB +#endif + +#ifndef GL_PIXEL_PACK_BUFFER +#define GL_PIXEL_PACK_BUFFER GL_PIXEL_PACK_BUFFER_ARB +#endif + +#endif + +static void +_cogl_pixel_buffer_free (CoglPixelBuffer *buffer); + +COGL_BUFFER_DEFINE (PixelBuffer, pixel_buffer) +COGL_GTYPE_DEFINE_CLASS (PixelBuffer, pixel_buffer) + +static CoglPixelBuffer * +_cogl_pixel_buffer_new (CoglContext *context, + size_t size, + const void *data, + CoglError **error) +{ + CoglPixelBuffer *pixel_buffer = g_slice_new0 (CoglPixelBuffer); + CoglBuffer *buffer = COGL_BUFFER (pixel_buffer); + + /* parent's constructor */ + _cogl_buffer_initialize (buffer, + context, + size, + COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK, + COGL_BUFFER_USAGE_HINT_TEXTURE, + COGL_BUFFER_UPDATE_HINT_STATIC); + + _cogl_pixel_buffer_object_new (pixel_buffer); + + if (data) + { + if (!_cogl_buffer_set_data (COGL_BUFFER (pixel_buffer), + 0, + data, + size, + error)) + { + cogl_object_unref (pixel_buffer); + return NULL; + } + } + + return pixel_buffer; +} + +CoglPixelBuffer * +cogl_pixel_buffer_new (CoglContext *context, + size_t size, + const void *data) +{ + CoglError *ignore_error = NULL; + CoglPixelBuffer *buffer = + _cogl_pixel_buffer_new (context, size, data, &ignore_error); + if (!buffer) + cogl_error_free (ignore_error); + return buffer; +} + +static void +_cogl_pixel_buffer_free (CoglPixelBuffer *buffer) +{ + /* parent's destructor */ + _cogl_buffer_fini (COGL_BUFFER (buffer)); + + g_slice_free (CoglPixelBuffer, buffer); +} + diff --git a/cogl/cogl/cogl-pixel-buffer.h b/cogl/cogl/cogl-pixel-buffer.h new file mode 100644 index 0000000..473b5ed --- /dev/null +++ b/cogl/cogl/cogl-pixel-buffer.h @@ -0,0 +1,138 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Damien Lespiau + * Robert Bragg + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_PIXEL_BUFFER_H__ +#define __COGL_PIXEL_BUFFER_H__ + +/* XXX: We forward declare CoglPixelBuffer here to allow for circular + * dependencies between some headers */ +typedef struct _CoglPixelBuffer CoglPixelBuffer; + +#include +#include + +#include + +COGL_BEGIN_DECLS + +#define COGL_PIXEL_BUFFER(buffer) ((CoglPixelBuffer *)(buffer)) + +/** + * CoglPixelBuffer: (skip) + */ + +/** + * cogl_pixel_buffer_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_pixel_buffer_get_gtype (void); + +/** + * cogl_pixel_buffer_new: + * @context: A #CoglContext + * @size: The number of bytes to allocate for the pixel data. + * @data: An optional pointer to vertex data to upload immediately + * + * Declares a new #CoglPixelBuffer of @size bytes to contain arrays of + * pixels. Once declared, data can be set using cogl_buffer_set_data() + * or by mapping it into the application's address space using + * cogl_buffer_map(). + * + * If @data isn't %NULL then @size bytes will be read from @data and + * immediately copied into the new buffer. + * + * Return value: (transfer full): a newly allocated #CoglPixelBuffer + * + * Since: 1.10 + * Stability: unstable + */ +CoglPixelBuffer * +cogl_pixel_buffer_new (CoglContext *context, + size_t size, + const void *data); + +/** + * cogl_is_pixel_buffer: + * @object: a #CoglObject to test + * + * Checks whether @object is a pixel buffer. + * + * Return value: %TRUE if the @object is a pixel buffer, and %FALSE + * otherwise + * + * Since: 1.2 + * Stability: Unstable + */ +CoglBool +cogl_is_pixel_buffer (void *object); + +#if 0 +/* + * cogl_pixel_buffer_set_region: + * @buffer: A #CoglPixelBuffer object + * @data: pixel data to upload to @array + * @src_width: width in pixels of the region to update + * @src_height: height in pixels of the region to update + * @src_rowstride: row stride in bytes of the source array + * @dst_x: upper left destination horizontal coordinate + * @dst_y: upper left destination vertical coordinate + * + * Uploads new data into a pixel array. The source data pointed by @data can + * have a different stride than @array in which case the function will do the + * right thing for you. For performance reasons, it is recommended for the + * source data to have the same stride than @array. + * + * Return value: %TRUE if the upload succeeded, %FALSE otherwise + * + * Since: 1.2 + * Stability: Unstable + */ +CoglBool +cogl_pixel_buffer_set_region (CoglPixelBuffer *buffer, + uint8_t *data, + unsigned int src_width, + unsigned int src_height, + unsigned int src_rowstride, + unsigned int dst_x, + unsigned int dst_y); +#endif + +COGL_END_DECLS + +#endif /* __COGL_PIXEL_BUFFER_H__ */ diff --git a/cogl/cogl/cogl-point-in-poly-private.h b/cogl/cogl/cogl-point-in-poly-private.h new file mode 100644 index 0000000..1f3f701 --- /dev/null +++ b/cogl/cogl/cogl-point-in-poly-private.h @@ -0,0 +1,46 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __COGL_POINT_INT_POLYGON_PRIVATE_H +#define __COGL_POINT_INT_POLYGON_PRIVATE_H + +#include + +COGL_BEGIN_DECLS + +int +_cogl_util_point_in_screen_poly (float point_x, + float point_y, + void *vertices, + size_t stride, + int n_vertices); + +COGL_END_DECLS + +#endif /* __COGL_POINT_INT_POLYGON_PRIVATE_H */ + diff --git a/cogl/cogl/cogl-point-in-poly.c b/cogl/cogl/cogl-point-in-poly.c new file mode 100644 index 0000000..64bbd30 --- /dev/null +++ b/cogl/cogl/cogl-point-in-poly.c @@ -0,0 +1,101 @@ +/* + * Point Inclusion in Polygon Test + * + * Copyright (c) 1970-2003, Wm. Randolph Franklin + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimers. + * 2. Redistributions in binary form must reproduce the above + * copyright notice in the documentation and/or other materials + * provided with the distribution. + * 3. The name of W. Randolph Franklin may not be used to endorse or + * promote products derived from this Software without specific + * prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Note: + * The algorithm for this point_in_poly() function was learnt from: + * http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-util.h" +#include "cogl-point-in-poly-private.h" + +#include + +/* We've made a notable change to the original algorithm referenced + * above to make sure we have reliable results for screen aligned + * rectangles even though there may be some numerical in-precision in + * how the vertices of the polygon were calculated. + * + * We've avoided introducing an epsilon factor to the comparisons + * since we feel there's a risk of changing some semantics in ways that + * might not be desirable. One of those is that if you transform two + * polygons which share an edge and test a point close to that edge + * then this algorithm will currently give a positive result for only + * one polygon. + * + * Another concern is the way this algorithm resolves the corner case + * where the horizontal ray being cast to count edge crossings may + * cross directly through a vertex. The solution is based on the "idea + * of Simulation of Simplicity" and "pretends to shift the ray + * infinitesimally down so that it either clearly intersects, or + * clearly doesn't touch". I'm not familiar with the idea myself so I + * expect a misplaced epsilon is likely to break that aspect of the + * algorithm. + * + * The simple solution we've gone for is to pixel align the polygon + * vertices which should eradicate most noise due to in-precision. + */ +int +_cogl_util_point_in_screen_poly (float point_x, + float point_y, + void *vertices, + size_t stride, + int n_vertices) +{ + int i, j, c = 0; + + for (i = 0, j = n_vertices - 1; i < n_vertices; j = i++) + { + float vert_xi = *(float *)((uint8_t *)vertices + i * stride); + float vert_xj = *(float *)((uint8_t *)vertices + j * stride); + float vert_yi = *(float *)((uint8_t *)vertices + i * stride + + sizeof (float)); + float vert_yj = *(float *)((uint8_t *)vertices + j * stride + + sizeof (float)); + + vert_xi = COGL_UTIL_NEARBYINT (vert_xi); + vert_xj = COGL_UTIL_NEARBYINT (vert_xj); + vert_yi = COGL_UTIL_NEARBYINT (vert_yi); + vert_yj = COGL_UTIL_NEARBYINT (vert_yj); + + if (((vert_yi > point_y) != (vert_yj > point_y)) && + (point_x < (vert_xj - vert_xi) * (point_y - vert_yi) / + (vert_yj - vert_yi) + vert_xi) ) + c = !c; + } + + return c; +} + diff --git a/cogl/cogl/cogl-poll-private.h b/cogl/cogl/cogl-poll-private.h new file mode 100644 index 0000000..bdc9e6d --- /dev/null +++ b/cogl/cogl/cogl-poll-private.h @@ -0,0 +1,77 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_POLL_PRIVATE_H__ +#define __COGL_POLL_PRIVATE_H__ + +#include "cogl-poll.h" +#include "cogl-renderer.h" +#include "cogl-closure-list-private.h" + +void +_cogl_poll_renderer_remove_fd (CoglRenderer *renderer, int fd); + +typedef int64_t (*CoglPollPrepareCallback) (void *user_data); +typedef void (*CoglPollDispatchCallback) (void *user_data, int revents); + +void +_cogl_poll_renderer_add_fd (CoglRenderer *renderer, + int fd, + CoglPollFDEvent events, + CoglPollPrepareCallback prepare, + CoglPollDispatchCallback dispatch, + void *user_data); + +void +_cogl_poll_renderer_modify_fd (CoglRenderer *renderer, + int fd, + CoglPollFDEvent events); + +typedef struct _CoglPollSource CoglPollSource; + +CoglPollSource * +_cogl_poll_renderer_add_source (CoglRenderer *renderer, + CoglPollPrepareCallback prepare, + CoglPollDispatchCallback dispatch, + void *user_data); + +void +_cogl_poll_renderer_remove_source (CoglRenderer *renderer, + CoglPollSource *source); + +typedef void (*CoglIdleCallback) (void *user_data); + +CoglClosure * +_cogl_poll_renderer_add_idle (CoglRenderer *renderer, + CoglIdleCallback idle_cb, + void *user_data, + CoglUserDataDestroyCallback destroy_cb); + +#endif /* __COGL_POLL_PRIVATE_H__ */ diff --git a/cogl/cogl/cogl-poll.c b/cogl/cogl/cogl-poll.c new file mode 100644 index 0000000..d0926e3 --- /dev/null +++ b/cogl/cogl/cogl-poll.c @@ -0,0 +1,267 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * Authors: + * Neil Roberts + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-poll.h" +#include "cogl-poll-private.h" +#include "cogl-winsys-private.h" +#include "cogl-renderer-private.h" + +struct _CoglPollSource +{ + int fd; + CoglPollPrepareCallback prepare; + CoglPollDispatchCallback dispatch; + void *user_data; +}; + +int +cogl_poll_renderer_get_info (CoglRenderer *renderer, + CoglPollFD **poll_fds, + int *n_poll_fds, + int64_t *timeout) +{ + GList *l, *next; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_renderer (renderer), 0); + _COGL_RETURN_VAL_IF_FAIL (poll_fds != NULL, 0); + _COGL_RETURN_VAL_IF_FAIL (n_poll_fds != NULL, 0); + _COGL_RETURN_VAL_IF_FAIL (timeout != NULL, 0); + + *timeout = -1; + + if (!_cogl_list_empty (&renderer->idle_closures)) + *timeout = 0; + + /* This loop needs to cope with the prepare callback removing its + * own fd */ + for (l = renderer->poll_sources; l; l = next) + { + CoglPollSource *source = l->data; + + next = l->next; + + if (source->prepare) + { + int64_t source_timeout = source->prepare (source->user_data); + if (source_timeout >= 0 && + (*timeout == -1 || *timeout > source_timeout)) + *timeout = source_timeout; + } + } + + /* This is deliberately set after calling the prepare callbacks in + * case one of them removes its fd */ + *poll_fds = (void *)renderer->poll_fds->data; + *n_poll_fds = renderer->poll_fds->len; + + return renderer->poll_fds_age; +} + +void +cogl_poll_renderer_dispatch (CoglRenderer *renderer, + const CoglPollFD *poll_fds, + int n_poll_fds) +{ + GList *l, *next; + + _COGL_RETURN_IF_FAIL (cogl_is_renderer (renderer)); + + _cogl_closure_list_invoke_no_args (&renderer->idle_closures); + + /* This loop needs to cope with the dispatch callback removing its + * own fd */ + for (l = renderer->poll_sources; l; l = next) + { + CoglPollSource *source = l->data; + int i; + + next = l->next; + + if (source->fd == -1) + { + source->dispatch (source->user_data, 0); + continue; + } + + for (i = 0; i < n_poll_fds; i++) + { + const CoglPollFD *pollfd = &poll_fds[i]; + + if (pollfd->fd == source->fd) + { + source->dispatch (source->user_data, pollfd->revents); + break; + } + } + } +} + +static int +find_pollfd (CoglRenderer *renderer, int fd) +{ + int i; + + for (i = 0; i < renderer->poll_fds->len; i++) + { + CoglPollFD *pollfd = &g_array_index (renderer->poll_fds, CoglPollFD, i); + + if (pollfd->fd == fd) + return i; + } + + return -1; +} + +void +_cogl_poll_renderer_remove_fd (CoglRenderer *renderer, int fd) +{ + int i = find_pollfd (renderer, fd); + GList *l; + + if (i < 0) + return; + + g_array_remove_index_fast (renderer->poll_fds, i); + renderer->poll_fds_age++; + + for (l = renderer->poll_sources; l; l = l->next) + { + CoglPollSource *source = l->data; + if (source->fd == fd) + { + renderer->poll_sources = + g_list_delete_link (renderer->poll_sources, l); + g_slice_free (CoglPollSource, source); + break; + } + } +} + +void +_cogl_poll_renderer_modify_fd (CoglRenderer *renderer, + int fd, + CoglPollFDEvent events) +{ + int fd_index = find_pollfd (renderer, fd); + + if (fd_index == -1) + g_warn_if_reached (); + else + { + CoglPollFD *pollfd = + &g_array_index (renderer->poll_sources, CoglPollFD, fd_index); + + pollfd->events = events; + renderer->poll_fds_age++; + } +} + +void +_cogl_poll_renderer_add_fd (CoglRenderer *renderer, + int fd, + CoglPollFDEvent events, + CoglPollPrepareCallback prepare, + CoglPollDispatchCallback dispatch, + void *user_data) +{ + CoglPollFD pollfd = { + fd, + events + }; + CoglPollSource *source; + + _cogl_poll_renderer_remove_fd (renderer, fd); + + source = g_slice_new0 (CoglPollSource); + source->fd = fd; + source->prepare = prepare; + source->dispatch = dispatch; + source->user_data = user_data; + + renderer->poll_sources = g_list_prepend (renderer->poll_sources, source); + + g_array_append_val (renderer->poll_fds, pollfd); + renderer->poll_fds_age++; +} + +CoglPollSource * +_cogl_poll_renderer_add_source (CoglRenderer *renderer, + CoglPollPrepareCallback prepare, + CoglPollDispatchCallback dispatch, + void *user_data) +{ + CoglPollSource *source; + + source = g_slice_new0 (CoglPollSource); + source->fd = -1; + source->prepare = prepare; + source->dispatch = dispatch; + source->user_data = user_data; + + renderer->poll_sources = g_list_prepend (renderer->poll_sources, source); + + return source; +} + +void +_cogl_poll_renderer_remove_source (CoglRenderer *renderer, + CoglPollSource *source) +{ + GList *l; + + for (l = renderer->poll_sources; l; l = l->next) + { + if (l->data == source) + { + renderer->poll_sources = + g_list_delete_link (renderer->poll_sources, l); + g_slice_free (CoglPollSource, source); + break; + } + } +} + +CoglClosure * +_cogl_poll_renderer_add_idle (CoglRenderer *renderer, + CoglIdleCallback idle_cb, + void *user_data, + CoglUserDataDestroyCallback destroy_cb) +{ + return _cogl_closure_list_add (&renderer->idle_closures, + idle_cb, + user_data, + destroy_cb); +} diff --git a/cogl/cogl/cogl-poll.h b/cogl/cogl/cogl-poll.h new file mode 100644 index 0000000..849e95c --- /dev/null +++ b/cogl/cogl/cogl-poll.h @@ -0,0 +1,195 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * Authors: + * Neil Roberts + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_POLL_H__ +#define __COGL_POLL_H__ + +#include +#include + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-poll + * @short_description: Functions for integrating Cogl with an + * application's main loop + * + * Cogl needs to integrate with the application's main loop so that it + * can internally handle some events from the driver. All Cogl + * applications must use these functions. They provide enough + * information to describe the state that Cogl will need to wake up + * on. An application using the GLib main loop can instead use + * cogl_glib_source_new() which provides a #GSource ready to be added + * to the main loop. + */ + +/** + * CoglPollFDEvent: + * @COGL_POLL_FD_EVENT_IN: there is data to read + * @COGL_POLL_FD_EVENT_PRI: data can be written (without blocking) + * @COGL_POLL_FD_EVENT_OUT: there is urgent data to read. + * @COGL_POLL_FD_EVENT_ERR: error condition + * @COGL_POLL_FD_EVENT_HUP: hung up (the connection has been broken, usually + * for pipes and sockets). + * @COGL_POLL_FD_EVENT_NVAL: invalid request. The file descriptor is not open. + * + * A bitmask of events that Cogl may need to wake on for a file + * descriptor. Note that these all have the same values as the + * corresponding defines for the poll function call on Unix so they + * may be directly passed to poll. + * + * Since: 1.10 + * Stability: unstable + */ +typedef enum +{ + COGL_POLL_FD_EVENT_IN = COGL_SYSDEF_POLLIN, + COGL_POLL_FD_EVENT_PRI = COGL_SYSDEF_POLLPRI, + COGL_POLL_FD_EVENT_OUT = COGL_SYSDEF_POLLOUT, + COGL_POLL_FD_EVENT_ERR = COGL_SYSDEF_POLLERR, + COGL_POLL_FD_EVENT_HUP = COGL_SYSDEF_POLLHUP, + COGL_POLL_FD_EVENT_NVAL = COGL_SYSDEF_POLLNVAL +} CoglPollFDEvent; + +/** + * CoglPollFD: + * @fd: The file descriptor to block on + * @events: A bitmask of events to block on + * @revents: A bitmask of returned events + * + * A struct for describing the state of a file descriptor that Cogl + * needs to block on. The @events field contains a bitmask of + * #CoglPollFDEvents that should cause the application to wake + * up. After the application is woken up from idle it should pass back + * an array of #CoglPollFDs to Cogl and update the @revents + * mask to the actual events that occurred on the file descriptor. + * + * Note that CoglPollFD is deliberately exactly the same as struct + * pollfd on Unix so that it can simply be cast when calling poll. + * + * Since: 1.10 + * Stability: unstable + */ +typedef struct { + int fd; + short int events; + short int revents; +} CoglPollFD; + +/** + * cogl_poll_renderer_get_info: + * @renderer: A #CoglRenderer + * @poll_fds: A return location for a pointer to an array + * of #CoglPollFDs + * @n_poll_fds: A return location for the number of entries in *@poll_fds + * @timeout: A return location for the maximum length of time to wait + * in microseconds, or -1 to wait indefinitely. + * + * Is used to integrate Cogl with an application mainloop that is based + * on the unix poll(2) api (or select() or something equivalent). This + * api should be called whenever an application is about to go idle so + * that Cogl has a chance to describe what file descriptor events it + * needs to be woken up for. + * + * If your application is using the Glib mainloop then you + * should jump to the cogl_glib_source_new() api as a more convenient + * way of integrating Cogl with the mainloop. + * + * After the function is called *@poll_fds will contain a pointer to + * an array of #CoglPollFD structs describing the file descriptors + * that Cogl expects. The fd and events members will be updated + * accordingly. After the application has completed its idle it is + * expected to either update the revents members directly in this + * array or to create a copy of the array and update them + * there. + * + * When the application mainloop returns from calling poll(2) (or its + * equivalent) then it should call cogl_poll_renderer_dispatch() + * passing a pointer the array of CoglPollFDs with updated + * revent values. + * + * @timeout will contain a maximum amount of time to wait in + * microseconds before the application should wake up or -1 if the + * application should wait indefinitely. This can also be 0 if + * Cogl needs to be woken up immediately. + * + * Return value: A "poll fd state age" that changes whenever the set + * of poll_fds has changed. If this API is being used to + * integrate with another system mainloop api then + * knowing if the set of file descriptors and events has + * really changed can help avoid redundant work + * depending the api. The age isn't guaranteed to change + * when the timeout changes. + * + * Stability: unstable + * Since: 1.16 + */ +int +cogl_poll_renderer_get_info (CoglRenderer *renderer, + CoglPollFD **poll_fds, + int *n_poll_fds, + int64_t *timeout); + +/** + * cogl_poll_renderer_dispatch: + * @renderer: A #CoglRenderer + * @poll_fds: An array of #CoglPollFDs describing the events + * that have occurred since the application went idle. + * @n_poll_fds: The length of the @poll_fds array. + * + * This should be called whenever an application is woken up from + * going idle in its main loop. The @poll_fds array should contain a + * list of file descriptors matched with the events that occurred in + * revents. The events field is ignored. It is safe to pass in extra + * file descriptors that Cogl didn't request when calling + * cogl_poll_renderer_get_info() or a shorter array missing some file + * descriptors that Cogl requested. + * + * If your application didn't originally create a #CoglRenderer + * manually then you can easily get a #CoglRenderer pointer by calling + * cogl_get_renderer(). + * + * Stability: unstable + * Since: 1.16 + */ +void +cogl_poll_renderer_dispatch (CoglRenderer *renderer, + const CoglPollFD *poll_fds, + int n_poll_fds); + +COGL_END_DECLS + +#endif /* __COGL_POLL_H__ */ diff --git a/cogl/cogl/cogl-primitive-private.h b/cogl/cogl/cogl-primitive-private.h new file mode 100644 index 0000000..7862729 --- /dev/null +++ b/cogl/cogl/cogl-primitive-private.h @@ -0,0 +1,73 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_PRIMITIVE_PRIVATE_H +#define __COGL_PRIMITIVE_PRIVATE_H + +#include "cogl-object-private.h" +#include "cogl-attribute-buffer-private.h" +#include "cogl-attribute-private.h" +#include "cogl-framebuffer.h" + +struct _CoglPrimitive +{ + CoglObject _parent; + + CoglIndices *indices; + CoglVerticesMode mode; + int first_vertex; + int n_vertices; + + int immutable_ref; + + CoglAttribute **attributes; + int n_attributes; + + int n_embedded_attributes; + CoglAttribute *embedded_attribute; +}; + +CoglPrimitive * +_cogl_primitive_immutable_ref (CoglPrimitive *primitive); + +void +_cogl_primitive_immutable_unref (CoglPrimitive *primitive); + +void +_cogl_primitive_draw (CoglPrimitive *primitive, + CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglDrawFlags flags); + +#endif /* __COGL_PRIMITIVE_PRIVATE_H */ + diff --git a/cogl/cogl/cogl-primitive-texture.c b/cogl/cogl/cogl-primitive-texture.c new file mode 100644 index 0000000..ae913d1 --- /dev/null +++ b/cogl/cogl/cogl-primitive-texture.c @@ -0,0 +1,60 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * Authors: + * Neil Roberts + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-primitive-texture.h" +#include "cogl-texture-private.h" + +CoglBool +cogl_is_primitive_texture (void *object) +{ + return (cogl_is_texture (object) && + COGL_TEXTURE (object)->vtable->is_primitive); +} + +void +cogl_primitive_texture_set_auto_mipmap (CoglPrimitiveTexture *primitive_texture, + CoglBool value) +{ + CoglTexture *texture; + + _COGL_RETURN_IF_FAIL (cogl_is_primitive_texture (primitive_texture)); + + texture = COGL_TEXTURE (primitive_texture); + + g_assert (texture->vtable->set_auto_mipmap != NULL); + + texture->vtable->set_auto_mipmap (texture, value); +} diff --git a/cogl/cogl/cogl-primitive-texture.h b/cogl/cogl/cogl-primitive-texture.h new file mode 100644 index 0000000..a810257 --- /dev/null +++ b/cogl/cogl/cogl-primitive-texture.h @@ -0,0 +1,112 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_PRIMITIVE_TEXTURE_H__ +#define __COGL_PRIMITIVE_TEXTURE_H__ + +#include "cogl-types.h" + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-primitive-texture + * @short_description: Interface for low-level textures like + * #CoglTexture2D and #CoglTexture3D. + * + * A #CoglPrimitiveTexture is a texture that is directly represented + * by a single texture on the GPU. For example these could be a + * #CoglTexture2D, #CoglTexture3D or #CoglTextureRectangle. This is + * opposed to high level meta textures which may be composed of + * multiple primitive textures or a sub-region of another texture such + * as #CoglAtlasTexture and #CoglTexture2DSliced. + * + * A texture that implements this interface can be directly used with + * the low level cogl_primitive_draw() API. Other types of textures + * need to be first resolved to primitive textures using the + * #CoglMetaTexture interface. + * + * Most developers won't need to use this interface directly but + * still it is worth understanding the distinction between high-level + * and primitive textures because you may find other references in the + * documentation that detail limitations of using + * primitive textures. + */ + +#if defined(__COGL_H_INSIDE__) && !defined(COGL_ENABLE_MUTTER_API) && \ + !defined(COGL_GIR_SCANNING) +/* For the public C api we typedef interface types as void to avoid needing + * lots of casting in code and instead we will rely on runtime type checking + * for these objects. */ +typedef void CoglPrimitiveTexture; +#else +typedef struct _CoglPrimitiveTexture CoglPrimitiveTexture; +#define COGL_PRIMITIVE_TEXTURE(X) ((CoglPrimitiveTexture *)X) +#endif + +/** + * cogl_is_primitive_texture: + * @object: A #CoglObject pointer + * + * Gets whether the given object references a primitive texture object. + * + * Return value: %TRUE if the pointer references a primitive texture, and + * %FALSE otherwise + * Since: 2.0 + * Stability: unstable + */ +CoglBool +cogl_is_primitive_texture (void *object); + +/** + * cogl_primitive_texture_set_auto_mipmap: + * @primitive_texture: A #CoglPrimitiveTexture + * @value: The new value for whether to auto mipmap + * + * Sets whether the texture will automatically update the smaller + * mipmap levels after any part of level 0 is updated. The update will + * only occur whenever the texture is used for drawing with a texture + * filter that requires the lower mipmap levels. An application should + * disable this if it wants to upload its own data for the other + * levels. By default auto mipmapping is enabled. + * + * Since: 2.0 + * Stability: unstable + */ +void +cogl_primitive_texture_set_auto_mipmap (CoglPrimitiveTexture *primitive_texture, + CoglBool value); + +COGL_END_DECLS + +#endif /* __COGL_PRIMITIVE_TEXTURE_H__ */ diff --git a/cogl/cogl/cogl-primitive.c b/cogl/cogl/cogl-primitive.c new file mode 100644 index 0000000..728d94f --- /dev/null +++ b/cogl/cogl/cogl-primitive.c @@ -0,0 +1,645 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-util.h" +#include "cogl-object-private.h" +#include "cogl-primitive.h" +#include "cogl-primitive-private.h" +#include "cogl-attribute-private.h" +#include "cogl-framebuffer-private.h" +#include "cogl-gtype-private.h" + +#include +#include + +static void _cogl_primitive_free (CoglPrimitive *primitive); + +COGL_OBJECT_DEFINE (Primitive, primitive); +COGL_GTYPE_DEFINE_CLASS (Primitive, primitive); + +CoglPrimitive * +cogl_primitive_new_with_attributes (CoglVerticesMode mode, + int n_vertices, + CoglAttribute **attributes, + int n_attributes) +{ + CoglPrimitive *primitive; + int i; + + primitive = g_slice_alloc (sizeof (CoglPrimitive) + + sizeof (CoglAttribute *) * (n_attributes - 1)); + primitive->mode = mode; + primitive->first_vertex = 0; + primitive->n_vertices = n_vertices; + primitive->indices = NULL; + primitive->immutable_ref = 0; + + primitive->n_attributes = n_attributes; + primitive->n_embedded_attributes = n_attributes; + primitive->attributes = &primitive->embedded_attribute; + for (i = 0; i < n_attributes; i++) + { + CoglAttribute *attribute = attributes[i]; + cogl_object_ref (attribute); + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_attribute (attribute), NULL); + + primitive->attributes[i] = attribute; + } + + return _cogl_primitive_object_new (primitive); +} + +/* This is just an internal convenience wrapper around + new_with_attributes that also unrefs the attributes. It is just + used for the builtin struct constructors */ +static CoglPrimitive * +_cogl_primitive_new_with_attributes_unref (CoglVerticesMode mode, + int n_vertices, + CoglAttribute **attributes, + int n_attributes) +{ + CoglPrimitive *primitive; + int i; + + primitive = cogl_primitive_new_with_attributes (mode, + n_vertices, + attributes, + n_attributes); + + for (i = 0; i < n_attributes; i++) + cogl_object_unref (attributes[i]); + + return primitive; +} + +CoglPrimitive * +cogl_primitive_new (CoglVerticesMode mode, + int n_vertices, + ...) +{ + va_list ap; + int n_attributes; + CoglAttribute **attributes; + int i; + CoglAttribute *attribute; + + va_start (ap, n_vertices); + for (n_attributes = 0; va_arg (ap, CoglAttribute *); n_attributes++) + ; + va_end (ap); + + attributes = g_alloca (sizeof (CoglAttribute *) * n_attributes); + + va_start (ap, n_vertices); + for (i = 0; (attribute = va_arg (ap, CoglAttribute *)); i++) + attributes[i] = attribute; + va_end (ap); + + return cogl_primitive_new_with_attributes (mode, n_vertices, + attributes, + i); +} + +CoglPrimitive * +cogl_primitive_new_p2 (CoglContext *ctx, + CoglVerticesMode mode, + int n_vertices, + const CoglVertexP2 *data) +{ + CoglAttributeBuffer *attribute_buffer = + cogl_attribute_buffer_new (ctx, n_vertices * sizeof (CoglVertexP2), data); + CoglAttribute *attributes[1]; + + attributes[0] = cogl_attribute_new (attribute_buffer, + "cogl_position_in", + sizeof (CoglVertexP2), + offsetof (CoglVertexP2, x), + 2, + COGL_ATTRIBUTE_TYPE_FLOAT); + + cogl_object_unref (attribute_buffer); + + return _cogl_primitive_new_with_attributes_unref (mode, n_vertices, + attributes, + 1); +} + +CoglPrimitive * +cogl_primitive_new_p3 (CoglContext *ctx, + CoglVerticesMode mode, + int n_vertices, + const CoglVertexP3 *data) +{ + CoglAttributeBuffer *attribute_buffer = + cogl_attribute_buffer_new (ctx, n_vertices * sizeof (CoglVertexP3), data); + CoglAttribute *attributes[1]; + + attributes[0] = cogl_attribute_new (attribute_buffer, + "cogl_position_in", + sizeof (CoglVertexP3), + offsetof (CoglVertexP3, x), + 3, + COGL_ATTRIBUTE_TYPE_FLOAT); + + cogl_object_unref (attribute_buffer); + + return _cogl_primitive_new_with_attributes_unref (mode, n_vertices, + attributes, + 1); +} + +CoglPrimitive * +cogl_primitive_new_p2c4 (CoglContext *ctx, + CoglVerticesMode mode, + int n_vertices, + const CoglVertexP2C4 *data) +{ + CoglAttributeBuffer *attribute_buffer = + cogl_attribute_buffer_new (ctx, n_vertices * sizeof (CoglVertexP2C4), data); + CoglAttribute *attributes[2]; + + attributes[0] = cogl_attribute_new (attribute_buffer, + "cogl_position_in", + sizeof (CoglVertexP2C4), + offsetof (CoglVertexP2C4, x), + 2, + COGL_ATTRIBUTE_TYPE_FLOAT); + attributes[1] = cogl_attribute_new (attribute_buffer, + "cogl_color_in", + sizeof (CoglVertexP2C4), + offsetof (CoglVertexP2C4, r), + 4, + COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE); + + cogl_object_unref (attribute_buffer); + + return _cogl_primitive_new_with_attributes_unref (mode, n_vertices, + attributes, + 2); +} + +CoglPrimitive * +cogl_primitive_new_p3c4 (CoglContext *ctx, + CoglVerticesMode mode, + int n_vertices, + const CoglVertexP3C4 *data) +{ + CoglAttributeBuffer *attribute_buffer = + cogl_attribute_buffer_new (ctx, n_vertices * sizeof (CoglVertexP3C4), data); + CoglAttribute *attributes[2]; + + attributes[0] = cogl_attribute_new (attribute_buffer, + "cogl_position_in", + sizeof (CoglVertexP3C4), + offsetof (CoglVertexP3C4, x), + 3, + COGL_ATTRIBUTE_TYPE_FLOAT); + attributes[1] = cogl_attribute_new (attribute_buffer, + "cogl_color_in", + sizeof (CoglVertexP3C4), + offsetof (CoglVertexP3C4, r), + 4, + COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE); + + cogl_object_unref (attribute_buffer); + + return _cogl_primitive_new_with_attributes_unref (mode, n_vertices, + attributes, + 2); +} + +CoglPrimitive * +cogl_primitive_new_p2t2 (CoglContext *ctx, + CoglVerticesMode mode, + int n_vertices, + const CoglVertexP2T2 *data) +{ + CoglAttributeBuffer *attribute_buffer = + cogl_attribute_buffer_new (ctx, n_vertices * sizeof (CoglVertexP2T2), data); + CoglAttribute *attributes[2]; + + attributes[0] = cogl_attribute_new (attribute_buffer, + "cogl_position_in", + sizeof (CoglVertexP2T2), + offsetof (CoglVertexP2T2, x), + 2, + COGL_ATTRIBUTE_TYPE_FLOAT); + attributes[1] = cogl_attribute_new (attribute_buffer, + "cogl_tex_coord0_in", + sizeof (CoglVertexP2T2), + offsetof (CoglVertexP2T2, s), + 2, + COGL_ATTRIBUTE_TYPE_FLOAT); + + cogl_object_unref (attribute_buffer); + + return _cogl_primitive_new_with_attributes_unref (mode, n_vertices, + attributes, + 2); +} + +CoglPrimitive * +cogl_primitive_new_p3t2 (CoglContext *ctx, + CoglVerticesMode mode, + int n_vertices, + const CoglVertexP3T2 *data) +{ + CoglAttributeBuffer *attribute_buffer = + cogl_attribute_buffer_new (ctx, n_vertices * sizeof (CoglVertexP3T2), data); + CoglAttribute *attributes[2]; + + attributes[0] = cogl_attribute_new (attribute_buffer, + "cogl_position_in", + sizeof (CoglVertexP3T2), + offsetof (CoglVertexP3T2, x), + 3, + COGL_ATTRIBUTE_TYPE_FLOAT); + attributes[1] = cogl_attribute_new (attribute_buffer, + "cogl_tex_coord0_in", + sizeof (CoglVertexP3T2), + offsetof (CoglVertexP3T2, s), + 2, + COGL_ATTRIBUTE_TYPE_FLOAT); + + cogl_object_unref (attribute_buffer); + + return _cogl_primitive_new_with_attributes_unref (mode, n_vertices, + attributes, + 2); +} + +CoglPrimitive * +cogl_primitive_new_p2t2c4 (CoglContext *ctx, + CoglVerticesMode mode, + int n_vertices, + const CoglVertexP2T2C4 *data) +{ + CoglAttributeBuffer *attribute_buffer = + cogl_attribute_buffer_new (ctx, + n_vertices * sizeof (CoglVertexP2T2C4), data); + CoglAttribute *attributes[3]; + + attributes[0] = cogl_attribute_new (attribute_buffer, + "cogl_position_in", + sizeof (CoglVertexP2T2C4), + offsetof (CoglVertexP2T2C4, x), + 2, + COGL_ATTRIBUTE_TYPE_FLOAT); + attributes[1] = cogl_attribute_new (attribute_buffer, + "cogl_tex_coord0_in", + sizeof (CoglVertexP2T2C4), + offsetof (CoglVertexP2T2C4, s), + 2, + COGL_ATTRIBUTE_TYPE_FLOAT); + attributes[2] = cogl_attribute_new (attribute_buffer, + "cogl_color_in", + sizeof (CoglVertexP2T2C4), + offsetof (CoglVertexP2T2C4, r), + 4, + COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE); + + cogl_object_unref (attribute_buffer); + + return _cogl_primitive_new_with_attributes_unref (mode, n_vertices, + attributes, + 3); +} + +CoglPrimitive * +cogl_primitive_new_p3t2c4 (CoglContext *ctx, + CoglVerticesMode mode, + int n_vertices, + const CoglVertexP3T2C4 *data) +{ + CoglAttributeBuffer *attribute_buffer = + cogl_attribute_buffer_new (ctx, + n_vertices * sizeof (CoglVertexP3T2C4), data); + CoglAttribute *attributes[3]; + + attributes[0] = cogl_attribute_new (attribute_buffer, + "cogl_position_in", + sizeof (CoglVertexP3T2C4), + offsetof (CoglVertexP3T2C4, x), + 3, + COGL_ATTRIBUTE_TYPE_FLOAT); + attributes[1] = cogl_attribute_new (attribute_buffer, + "cogl_tex_coord0_in", + sizeof (CoglVertexP3T2C4), + offsetof (CoglVertexP3T2C4, s), + 2, + COGL_ATTRIBUTE_TYPE_FLOAT); + attributes[2] = cogl_attribute_new (attribute_buffer, + "cogl_color_in", + sizeof (CoglVertexP3T2C4), + offsetof (CoglVertexP3T2C4, r), + 4, + COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE); + + cogl_object_unref (attribute_buffer); + + return _cogl_primitive_new_with_attributes_unref (mode, n_vertices, + attributes, + 3); +} + +static void +_cogl_primitive_free (CoglPrimitive *primitive) +{ + int i; + + for (i = 0; i < primitive->n_attributes; i++) + cogl_object_unref (primitive->attributes[i]); + + if (primitive->attributes != &primitive->embedded_attribute) + g_slice_free1 (sizeof (CoglAttribute *) * primitive->n_attributes, + primitive->attributes); + + if (primitive->indices) + cogl_object_unref (primitive->indices); + + g_slice_free1 (sizeof (CoglPrimitive) + + sizeof (CoglAttribute *) * + (primitive->n_embedded_attributes - 1), primitive); +} + +static void +warn_about_midscene_changes (void) +{ + static CoglBool seen = FALSE; + if (!seen) + { + g_warning ("Mid-scene modification of primitives has " + "undefined results\n"); + seen = TRUE; + } +} + +void +cogl_primitive_set_attributes (CoglPrimitive *primitive, + CoglAttribute **attributes, + int n_attributes) +{ + int i; + + _COGL_RETURN_IF_FAIL (cogl_is_primitive (primitive)); + + if (G_UNLIKELY (primitive->immutable_ref)) + { + warn_about_midscene_changes (); + return; + } + + /* NB: we don't unref the previous attributes before refing the new + * in case we would end up releasing the last reference for an + * attribute thats actually in the new list too. */ + for (i = 0; i < n_attributes; i++) + { + _COGL_RETURN_IF_FAIL (cogl_is_attribute (attributes[i])); + cogl_object_ref (attributes[i]); + } + + for (i = 0; i < primitive->n_attributes; i++) + cogl_object_unref (primitive->attributes[i]); + + /* First try to use the embedded storage assocated with the + * primitive, else fallback to slice allocating separate storage for + * the attribute pointers... */ + + if (n_attributes <= primitive->n_embedded_attributes) + { + if (primitive->attributes != &primitive->embedded_attribute) + g_slice_free1 (sizeof (CoglAttribute *) * primitive->n_attributes, + primitive->attributes); + primitive->attributes = &primitive->embedded_attribute; + } + else + { + if (primitive->attributes != &primitive->embedded_attribute) + g_slice_free1 (sizeof (CoglAttribute *) * primitive->n_attributes, + primitive->attributes); + primitive->attributes = + g_slice_alloc (sizeof (CoglAttribute *) * n_attributes); + } + + memcpy (primitive->attributes, attributes, + sizeof (CoglAttribute *) * n_attributes); + + primitive->n_attributes = n_attributes; +} + +int +cogl_primitive_get_first_vertex (CoglPrimitive *primitive) +{ + _COGL_RETURN_VAL_IF_FAIL (cogl_is_primitive (primitive), 0); + + return primitive->first_vertex; +} + +void +cogl_primitive_set_first_vertex (CoglPrimitive *primitive, + int first_vertex) +{ + _COGL_RETURN_IF_FAIL (cogl_is_primitive (primitive)); + + if (G_UNLIKELY (primitive->immutable_ref)) + { + warn_about_midscene_changes (); + return; + } + + primitive->first_vertex = first_vertex; +} + +int +cogl_primitive_get_n_vertices (CoglPrimitive *primitive) +{ + _COGL_RETURN_VAL_IF_FAIL (cogl_is_primitive (primitive), 0); + + return primitive->n_vertices; +} + +void +cogl_primitive_set_n_vertices (CoglPrimitive *primitive, + int n_vertices) +{ + _COGL_RETURN_IF_FAIL (cogl_is_primitive (primitive)); + + primitive->n_vertices = n_vertices; +} + +CoglVerticesMode +cogl_primitive_get_mode (CoglPrimitive *primitive) +{ + _COGL_RETURN_VAL_IF_FAIL (cogl_is_primitive (primitive), 0); + + return primitive->mode; +} + +void +cogl_primitive_set_mode (CoglPrimitive *primitive, + CoglVerticesMode mode) +{ + _COGL_RETURN_IF_FAIL (cogl_is_primitive (primitive)); + + if (G_UNLIKELY (primitive->immutable_ref)) + { + warn_about_midscene_changes (); + return; + } + + primitive->mode = mode; +} + +void +cogl_primitive_set_indices (CoglPrimitive *primitive, + CoglIndices *indices, + int n_indices) +{ + _COGL_RETURN_IF_FAIL (cogl_is_primitive (primitive)); + + if (G_UNLIKELY (primitive->immutable_ref)) + { + warn_about_midscene_changes (); + return; + } + + if (indices) + cogl_object_ref (indices); + if (primitive->indices) + cogl_object_unref (primitive->indices); + primitive->indices = indices; + primitive->n_vertices = n_indices; +} + +CoglIndices * +cogl_primitive_get_indices (CoglPrimitive *primitive) +{ + return primitive->indices; +} + +CoglPrimitive * +cogl_primitive_copy (CoglPrimitive *primitive) +{ + CoglPrimitive *copy; + + copy = cogl_primitive_new_with_attributes (primitive->mode, + primitive->n_vertices, + primitive->attributes, + primitive->n_attributes); + + cogl_primitive_set_indices (copy, primitive->indices, primitive->n_vertices); + cogl_primitive_set_first_vertex (copy, primitive->first_vertex); + + return copy; +} + +CoglPrimitive * +_cogl_primitive_immutable_ref (CoglPrimitive *primitive) +{ + int i; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_primitive (primitive), NULL); + + primitive->immutable_ref++; + + for (i = 0; i < primitive->n_attributes; i++) + _cogl_attribute_immutable_ref (primitive->attributes[i]); + + return primitive; +} + +void +_cogl_primitive_immutable_unref (CoglPrimitive *primitive) +{ + int i; + + _COGL_RETURN_IF_FAIL (cogl_is_primitive (primitive)); + _COGL_RETURN_IF_FAIL (primitive->immutable_ref > 0); + + primitive->immutable_ref--; + + for (i = 0; i < primitive->n_attributes; i++) + _cogl_attribute_immutable_unref (primitive->attributes[i]); +} + +void +cogl_primitive_foreach_attribute (CoglPrimitive *primitive, + CoglPrimitiveAttributeCallback callback, + void *user_data) +{ + int i; + + for (i = 0; i < primitive->n_attributes; i++) + if (!callback (primitive, primitive->attributes[i], user_data)) + break; +} + +void +_cogl_primitive_draw (CoglPrimitive *primitive, + CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglDrawFlags flags) +{ + if (primitive->indices) + _cogl_framebuffer_draw_indexed_attributes (framebuffer, + pipeline, + primitive->mode, + primitive->first_vertex, + primitive->n_vertices, + primitive->indices, + primitive->attributes, + primitive->n_attributes, + flags); + else + _cogl_framebuffer_draw_attributes (framebuffer, + pipeline, + primitive->mode, + primitive->first_vertex, + primitive->n_vertices, + primitive->attributes, + primitive->n_attributes, + flags); +} + +void +cogl_primitive_draw (CoglPrimitive *primitive, + CoglFramebuffer *framebuffer, + CoglPipeline *pipeline) +{ + _cogl_primitive_draw (primitive, framebuffer, pipeline, 0 /* flags */); +} diff --git a/cogl/cogl/cogl-primitive.h b/cogl/cogl/cogl-primitive.h new file mode 100644 index 0000000..708c06b --- /dev/null +++ b/cogl/cogl/cogl-primitive.h @@ -0,0 +1,944 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_PRIMITIVE_H__ +#define __COGL_PRIMITIVE_H__ + +/* We forward declare the CoglPrimitive type here to avoid some circular + * dependency issues with the following headers. + */ +typedef struct _CoglPrimitive CoglPrimitive; + +#include /* for CoglVerticesMode */ +#include +#include + +#include + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-primitive + * @short_description: Functions for creating, manipulating and drawing + * primitives + * + * FIXME + */ + +/** + * CoglPrimitive: (ref-func cogl_object_ref) (unref-func cogl_object_unref) + * (set-value-func cogl_object_value_set_object) + * (get-value-func cogl_object_get_object) + */ + +/** + * cogl_primitive_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_primitive_get_gtype (void); + +/** + * CoglVertexP2: + * @x: The x component of a position attribute + * @y: The y component of a position attribute + * + * A convenience vertex definition that can be used with + * cogl_primitive_new_p2(). + * + * Since: 1.6 + * Stability: Unstable + */ +typedef struct { + float x, y; +} CoglVertexP2; + +/** + * CoglVertexP3: + * @x: The x component of a position attribute + * @y: The y component of a position attribute + * @z: The z component of a position attribute + * + * A convenience vertex definition that can be used with + * cogl_primitive_new_p3(). + * + * Since: 1.6 + * Stability: Unstable + */ +typedef struct { + float x, y, z; +} CoglVertexP3; + +/** + * CoglVertexP2C4: + * @x: The x component of a position attribute + * @y: The y component of a position attribute + * @r: The red component of a color attribute + * @b: The green component of a color attribute + * @g: The blue component of a color attribute + * @a: The alpha component of a color attribute + * + * A convenience vertex definition that can be used with + * cogl_primitive_new_p2c4(). + * + * Since: 1.6 + * Stability: Unstable + */ +typedef struct { + float x, y; + uint8_t r, g, b, a; +} CoglVertexP2C4; + +/** + * CoglVertexP3C4: + * @x: The x component of a position attribute + * @y: The y component of a position attribute + * @z: The z component of a position attribute + * @r: The red component of a color attribute + * @b: The green component of a color attribute + * @g: The blue component of a color attribute + * @a: The alpha component of a color attribute + * + * A convenience vertex definition that can be used with + * cogl_primitive_new_p3c4(). + * + * Since: 1.6 + * Stability: Unstable + */ +typedef struct { + float x, y, z; + uint8_t r, g, b, a; +} CoglVertexP3C4; + +/** + * CoglVertexP2T2: + * @x: The x component of a position attribute + * @y: The y component of a position attribute + * @s: The s component of a texture coordinate attribute + * @t: The t component of a texture coordinate attribute + * + * A convenience vertex definition that can be used with + * cogl_primitive_new_p2t2(). + * + * Since: 1.6 + * Stability: Unstable + */ +typedef struct { + float x, y; + float s, t; +} CoglVertexP2T2; + +/** + * CoglVertexP3T2: + * @x: The x component of a position attribute + * @y: The y component of a position attribute + * @z: The z component of a position attribute + * @s: The s component of a texture coordinate attribute + * @t: The t component of a texture coordinate attribute + * + * A convenience vertex definition that can be used with + * cogl_primitive_new_p3t2(). + * + * Since: 1.6 + * Stability: Unstable + */ +typedef struct { + float x, y, z; + float s, t; +} CoglVertexP3T2; + + +/** + * CoglVertexP2T2C4: + * @x: The x component of a position attribute + * @y: The y component of a position attribute + * @s: The s component of a texture coordinate attribute + * @t: The t component of a texture coordinate attribute + * @r: The red component of a color attribute + * @b: The green component of a color attribute + * @g: The blue component of a color attribute + * @a: The alpha component of a color attribute + * + * A convenience vertex definition that can be used with + * cogl_primitive_new_p3t2c4(). + * + * Since: 1.6 + * Stability: Unstable + */ +typedef struct { + float x, y; + float s, t; + uint8_t r, g, b, a; +} CoglVertexP2T2C4; + +/** + * CoglVertexP3T2C4: + * @x: The x component of a position attribute + * @y: The y component of a position attribute + * @z: The z component of a position attribute + * @s: The s component of a texture coordinate attribute + * @t: The t component of a texture coordinate attribute + * @r: The red component of a color attribute + * @b: The green component of a color attribute + * @g: The blue component of a color attribute + * @a: The alpha component of a color attribute + * + * A convenience vertex definition that can be used with + * cogl_primitive_new_p3t2c4(). + * + * Since: 1.6 + * Stability: Unstable + */ +typedef struct { + float x, y, z; + float s, t; + uint8_t r, g, b, a; +} CoglVertexP3T2C4; + +/** + * cogl_primitive_new: + * @mode: A #CoglVerticesMode defining how to draw the vertices + * @n_vertices: The number of vertices to process when drawing + * @...: A %NULL terminated list of attributes + * + * Combines a set of #CoglAttributes with a specific draw @mode + * and defines a vertex count so a #CoglPrimitive object can be retained and + * drawn later with no addition information required. + * + * The value passed as @n_vertices will simply update the + * #CoglPrimitive n_vertices property as if + * cogl_primitive_set_n_vertices() were called. This property defines + * the number of vertices to read when drawing. + * + * Return value: (transfer full): A newly allocated #CoglPrimitive object + * + * Since: 1.6 + * Stability: Unstable + */ +CoglPrimitive * +cogl_primitive_new (CoglVerticesMode mode, + int n_vertices, + ...); + +/** + * cogl_primitive_new_with_attributes: (skip) + * @mode: A #CoglVerticesMode defining how to draw the vertices + * @n_vertices: The number of vertices to process when drawing + * @attributes: An array of CoglAttribute + * @n_attributes: The number of attributes + * + * Combines a set of #CoglAttributes with a specific draw @mode + * and defines a vertex count so a #CoglPrimitive object can be retained and + * drawn later with no addition information required. + * + * The value passed as @n_vertices will simply update the + * #CoglPrimitive n_vertices property as if + * cogl_primitive_set_n_vertices() were called. This property defines + * the number of vertices to read when drawing. + * + * Return value: (transfer full): A newly allocated #CoglPrimitive object + * + * Since: 1.6 + * Stability: Unstable + */ +CoglPrimitive * +cogl_primitive_new_with_attributes (CoglVerticesMode mode, + int n_vertices, + CoglAttribute **attributes, + int n_attributes); + +/** + * cogl_primitive_new_p2: (skip) + * @context: A #CoglContext + * @mode: A #CoglVerticesMode defining how to draw the vertices + * @n_vertices: The number of vertices to read from @data and also + * the number of vertices to read when later drawing. + * @data: (array length=n_vertices): (type Cogl.VertexP2): An array + * of #CoglVertexP2 vertices + * + * Provides a convenient way to describe a primitive, such as a single + * triangle strip or a triangle fan, that will internally allocate the + * necessary #CoglAttributeBuffer storage, describe the position + * attribute with a #CoglAttribute and upload your data. + * + * For example to draw a convex polygon you can do: + * |[ + * CoglVertexP2 triangle[] = + * { + * { 0, 300 }, + * { 150, 0, }, + * { 300, 300 } + * }; + * prim = cogl_primitive_new_p2 (COGL_VERTICES_MODE_TRIANGLE_FAN, + * 3, triangle); + * cogl_primitive_draw (prim); + * ]| + * + * The value passed as @n_vertices is initially used to determine how + * much can be read from @data but it will also be used to update the + * #CoglPrimitive n_vertices property as if + * cogl_primitive_set_n_vertices() were called. This property defines + * the number of vertices to read when drawing. + + * The primitive API doesn't support drawing with sliced + * textures (since switching between slices implies changing state and + * so that implies multiple primitives need to be submitted). You + * should pass the %COGL_TEXTURE_NO_SLICING flag to all textures that + * might be used while drawing with this API. If your hardware doesn't + * support non-power of two textures (For example you are using GLES + * 1.1) then you will need to make sure your assets are resized to a + * power-of-two size (though they don't have to be square) + * + * Return value: (transfer full): A newly allocated #CoglPrimitive + * with a reference of 1. This can be freed using cogl_object_unref(). + * + * Since: 1.6 + * Stability: Unstable + */ +CoglPrimitive * +cogl_primitive_new_p2 (CoglContext *context, + CoglVerticesMode mode, + int n_vertices, + const CoglVertexP2 *data); + +/** + * cogl_primitive_new_p3: (skip) + * @context: A #CoglContext + * @mode: A #CoglVerticesMode defining how to draw the vertices + * @n_vertices: The number of vertices to read from @data and also + * the number of vertices to read when later drawing. + * @data: (array length=n_vertices): (type Cogl.VertexP3): An array of + * #CoglVertexP3 vertices + * + * Provides a convenient way to describe a primitive, such as a single + * triangle strip or a triangle fan, that will internally allocate the + * necessary #CoglAttributeBuffer storage, describe the position + * attribute with a #CoglAttribute and upload your data. + * + * For example to draw a convex polygon you can do: + * |[ + * CoglVertexP3 triangle[] = + * { + * { 0, 300, 0 }, + * { 150, 0, 0 }, + * { 300, 300, 0 } + * }; + * prim = cogl_primitive_new_p3 (COGL_VERTICES_MODE_TRIANGLE_FAN, + * 3, triangle); + * cogl_primitive_draw (prim); + * ]| + * + * The value passed as @n_vertices is initially used to determine how + * much can be read from @data but it will also be used to update the + * #CoglPrimitive n_vertices property as if + * cogl_primitive_set_n_vertices() were called. This property defines + * the number of vertices to read when drawing. + + * The primitive API doesn't support drawing with sliced + * textures (since switching between slices implies changing state and + * so that implies multiple primitives need to be submitted). You + * should pass the %COGL_TEXTURE_NO_SLICING flag to all textures that + * might be used while drawing with this API. If your hardware doesn't + * support non-power of two textures (For example you are using GLES + * 1.1) then you will need to make sure your assets are resized to a + * power-of-two size (though they don't have to be square) + * + * Return value: (transfer full): A newly allocated #CoglPrimitive + * with a reference of 1. This can be freed using cogl_object_unref(). + * + * Since: 1.6 + * Stability: Unstable + */ +CoglPrimitive * +cogl_primitive_new_p3 (CoglContext *context, + CoglVerticesMode mode, + int n_vertices, + const CoglVertexP3 *data); + +/** + * cogl_primitive_new_p2c4: (skip) + * @context: A #CoglContext + * @mode: A #CoglVerticesMode defining how to draw the vertices + * @n_vertices: The number of vertices to read from @data and also + * the number of vertices to read when later drawing. + * @data: (array length=n_vertices): (type Cogl.VertexP2C4): An array + * of #CoglVertexP2C4 vertices + * + * Provides a convenient way to describe a primitive, such as a single + * triangle strip or a triangle fan, that will internally allocate the + * necessary #CoglAttributeBuffer storage, describe the position + * and color attributes with #CoglAttributes and upload + * your data. + * + * For example to draw a convex polygon with a linear gradient you + * can do: + * |[ + * CoglVertexP2C4 triangle[] = + * { + * { 0, 300, 0xff, 0x00, 0x00, 0xff }, + * { 150, 0, 0x00, 0xff, 0x00, 0xff }, + * { 300, 300, 0xff, 0x00, 0x00, 0xff } + * }; + * prim = cogl_primitive_new_p2c4 (COGL_VERTICES_MODE_TRIANGLE_FAN, + * 3, triangle); + * cogl_primitive_draw (prim); + * ]| + * + * The value passed as @n_vertices is initially used to determine how + * much can be read from @data but it will also be used to update the + * #CoglPrimitive n_vertices property as if + * cogl_primitive_set_n_vertices() were called. This property defines + * the number of vertices to read when drawing. + + * The primitive API doesn't support drawing with sliced + * textures (since switching between slices implies changing state and + * so that implies multiple primitives need to be submitted). You + * should pass the %COGL_TEXTURE_NO_SLICING flag to all textures that + * might be used while drawing with this API. If your hardware doesn't + * support non-power of two textures (For example you are using GLES + * 1.1) then you will need to make sure your assets are resized to a + * power-of-two size (though they don't have to be square) + * + * Return value: (transfer full): A newly allocated #CoglPrimitive + * with a reference of 1. This can be freed using cogl_object_unref(). + * + * Since: 1.6 + * Stability: Unstable + */ +CoglPrimitive * +cogl_primitive_new_p2c4 (CoglContext *context, + CoglVerticesMode mode, + int n_vertices, + const CoglVertexP2C4 *data); + +/** + * cogl_primitive_new_p3c4: (skip) + * @context: A #CoglContext + * @mode: A #CoglVerticesMode defining how to draw the vertices + * @n_vertices: The number of vertices to read from @data and also + * the number of vertices to read when later drawing. + * @data: (array length=n_vertices): (type Cogl.VertexP3C4): An array + * of #CoglVertexP3C4 vertices + * + * Provides a convenient way to describe a primitive, such as a single + * triangle strip or a triangle fan, that will internally allocate the + * necessary #CoglAttributeBuffer storage, describe the position + * and color attributes with #CoglAttributes and upload + * your data. + * + * For example to draw a convex polygon with a linear gradient you + * can do: + * |[ + * CoglVertexP3C4 triangle[] = + * { + * { 0, 300, 0, 0xff, 0x00, 0x00, 0xff }, + * { 150, 0, 0, 0x00, 0xff, 0x00, 0xff }, + * { 300, 300, 0, 0xff, 0x00, 0x00, 0xff } + * }; + * prim = cogl_primitive_new_p3c4 (COGL_VERTICES_MODE_TRIANGLE_FAN, + * 3, triangle); + * cogl_primitive_draw (prim); + * ]| + * + * The value passed as @n_vertices is initially used to determine how + * much can be read from @data but it will also be used to update the + * #CoglPrimitive n_vertices property as if + * cogl_primitive_set_n_vertices() were called. This property defines + * the number of vertices to read when drawing. + + * The primitive API doesn't support drawing with sliced + * textures (since switching between slices implies changing state and + * so that implies multiple primitives need to be submitted). You + * should pass the %COGL_TEXTURE_NO_SLICING flag to all textures that + * might be used while drawing with this API. If your hardware doesn't + * support non-power of two textures (For example you are using GLES + * 1.1) then you will need to make sure your assets are resized to a + * power-of-two size (though they don't have to be square) + * + * Return value: (transfer full): A newly allocated #CoglPrimitive + * with a reference of 1. This can be freed using cogl_object_unref(). + * + * Since: 1.6 + * Stability: Unstable + */ +CoglPrimitive * +cogl_primitive_new_p3c4 (CoglContext *context, + CoglVerticesMode mode, + int n_vertices, + const CoglVertexP3C4 *data); + +/** + * cogl_primitive_new_p2t2: (skip) + * @context: A #CoglContext + * @mode: A #CoglVerticesMode defining how to draw the vertices + * @n_vertices: The number of vertices to read from @data and also + * the number of vertices to read when later drawing. + * @data: (array length=n_vertices): (type Cogl.VertexP2T2): An array + * of #CoglVertexP2T2 vertices + * + * Provides a convenient way to describe a primitive, such as a single + * triangle strip or a triangle fan, that will internally allocate the + * necessary #CoglAttributeBuffer storage, describe the position and + * texture coordinate attributes with #CoglAttributes and + * upload your data. + * + * For example to draw a convex polygon with texture mapping you can + * do: + * |[ + * CoglVertexP2T2 triangle[] = + * { + * { 0, 300, 0.0, 1.0}, + * { 150, 0, 0.5, 0.0}, + * { 300, 300, 1.0, 1.0} + * }; + * prim = cogl_primitive_new_p2t2 (COGL_VERTICES_MODE_TRIANGLE_FAN, + * 3, triangle); + * cogl_primitive_draw (prim); + * ]| + * + * The value passed as @n_vertices is initially used to determine how + * much can be read from @data but it will also be used to update the + * #CoglPrimitive n_vertices property as if + * cogl_primitive_set_n_vertices() were called. This property defines + * the number of vertices to read when drawing. + + * The primitive API doesn't support drawing with sliced + * textures (since switching between slices implies changing state and + * so that implies multiple primitives need to be submitted). You + * should pass the %COGL_TEXTURE_NO_SLICING flag to all textures that + * might be used while drawing with this API. If your hardware doesn't + * support non-power of two textures (For example you are using GLES + * 1.1) then you will need to make sure your assets are resized to a + * power-of-two size (though they don't have to be square) + * + * Return value: (transfer full): A newly allocated #CoglPrimitive + * with a reference of 1. This can be freed using cogl_object_unref(). + * + * Since: 1.6 + * Stability: Unstable + */ +CoglPrimitive * +cogl_primitive_new_p2t2 (CoglContext *context, + CoglVerticesMode mode, + int n_vertices, + const CoglVertexP2T2 *data); + +/** + * cogl_primitive_new_p3t2: (skip) + * @context: A #CoglContext + * @mode: A #CoglVerticesMode defining how to draw the vertices + * @n_vertices: The number of vertices to read from @data and also + * the number of vertices to read when later drawing. + * @data: (array length=n_vertices): (type Cogl.VertexP3T2): An array + * of #CoglVertexP3T2 vertices + * + * Provides a convenient way to describe a primitive, such as a single + * triangle strip or a triangle fan, that will internally allocate the + * necessary #CoglAttributeBuffer storage, describe the position and + * texture coordinate attributes with #CoglAttributes and + * upload your data. + * + * For example to draw a convex polygon with texture mapping you can + * do: + * |[ + * CoglVertexP3T2 triangle[] = + * { + * { 0, 300, 0, 0.0, 1.0}, + * { 150, 0, 0, 0.5, 0.0}, + * { 300, 300, 0, 1.0, 1.0} + * }; + * prim = cogl_primitive_new_p3t2 (COGL_VERTICES_MODE_TRIANGLE_FAN, + * 3, triangle); + * cogl_primitive_draw (prim); + * ]| + * + * The value passed as @n_vertices is initially used to determine how + * much can be read from @data but it will also be used to update the + * #CoglPrimitive n_vertices property as if + * cogl_primitive_set_n_vertices() were called. This property defines + * the number of vertices to read when drawing. + + * The primitive API doesn't support drawing with sliced + * textures (since switching between slices implies changing state and + * so that implies multiple primitives need to be submitted). You + * should pass the %COGL_TEXTURE_NO_SLICING flag to all textures that + * might be used while drawing with this API. If your hardware doesn't + * support non-power of two textures (For example you are using GLES + * 1.1) then you will need to make sure your assets are resized to a + * power-of-two size (though they don't have to be square) + * + * Return value: (transfer full): A newly allocated #CoglPrimitive + * with a reference of 1. This can be freed using cogl_object_unref(). + * + * Since: 1.6 + * Stability: Unstable + */ +CoglPrimitive * +cogl_primitive_new_p3t2 (CoglContext *context, + CoglVerticesMode mode, + int n_vertices, + const CoglVertexP3T2 *data); + +/** + * cogl_primitive_new_p2t2c4: (skip) + * @context: A #CoglContext + * @mode: A #CoglVerticesMode defining how to draw the vertices + * @n_vertices: The number of vertices to read from @data and also + * the number of vertices to read when later drawing. + * @data: (array length=n_vertices): (type Cogl.VertexP2T2C4): An + * array of #CoglVertexP2T2C4 vertices + * + * Provides a convenient way to describe a primitive, such as a single + * triangle strip or a triangle fan, that will internally allocate the + * necessary #CoglAttributeBuffer storage, describe the position, texture + * coordinate and color attributes with #CoglAttributes and + * upload your data. + * + * For example to draw a convex polygon with texture mapping and a + * linear gradient you can do: + * |[ + * CoglVertexP2T2C4 triangle[] = + * { + * { 0, 300, 0.0, 1.0, 0xff, 0x00, 0x00, 0xff}, + * { 150, 0, 0.5, 0.0, 0x00, 0xff, 0x00, 0xff}, + * { 300, 300, 1.0, 1.0, 0xff, 0x00, 0x00, 0xff} + * }; + * prim = cogl_primitive_new_p2t2c4 (COGL_VERTICES_MODE_TRIANGLE_FAN, + * 3, triangle); + * cogl_primitive_draw (prim); + * ]| + * + * The value passed as @n_vertices is initially used to determine how + * much can be read from @data but it will also be used to update the + * #CoglPrimitive n_vertices property as if + * cogl_primitive_set_n_vertices() were called. This property defines + * the number of vertices to read when drawing. + + * The primitive API doesn't support drawing with sliced + * textures (since switching between slices implies changing state and + * so that implies multiple primitives need to be submitted). You + * should pass the %COGL_TEXTURE_NO_SLICING flag to all textures that + * might be used while drawing with this API. If your hardware doesn't + * support non-power of two textures (For example you are using GLES + * 1.1) then you will need to make sure your assets are resized to a + * power-of-two size (though they don't have to be square) + * + * Return value: (transfer full): A newly allocated #CoglPrimitive + * with a reference of 1. This can be freed using cogl_object_unref(). + * + * Since: 1.6 + * Stability: Unstable + */ +CoglPrimitive * +cogl_primitive_new_p2t2c4 (CoglContext *context, + CoglVerticesMode mode, + int n_vertices, + const CoglVertexP2T2C4 *data); + +/** + * cogl_primitive_new_p3t2c4: (skip) + * @context: A #CoglContext + * @mode: A #CoglVerticesMode defining how to draw the vertices + * @n_vertices: The number of vertices to read from @data and also + * the number of vertices to read when later drawing. + * @data: (array length=n_vertices): (type Cogl.VertexP3T2C4): An + * array of #CoglVertexP3T2C4 vertices + * + * Provides a convenient way to describe a primitive, such as a single + * triangle strip or a triangle fan, that will internally allocate the + * necessary #CoglAttributeBuffer storage, describe the position, texture + * coordinate and color attributes with #CoglAttributes and + * upload your data. + * + * For example to draw a convex polygon with texture mapping and a + * linear gradient you can do: + * |[ + * CoglVertexP3T2C4 triangle[] = + * { + * { 0, 300, 0, 0.0, 1.0, 0xff, 0x00, 0x00, 0xff}, + * { 150, 0, 0, 0.5, 0.0, 0x00, 0xff, 0x00, 0xff}, + * { 300, 300, 0, 1.0, 1.0, 0xff, 0x00, 0x00, 0xff} + * }; + * prim = cogl_primitive_new_p3t2c4 (COGL_VERTICES_MODE_TRIANGLE_FAN, + * 3, triangle); + * cogl_primitive_draw (prim); + * ]| + * + * The value passed as @n_vertices is initially used to determine how + * much can be read from @data but it will also be used to update the + * #CoglPrimitive n_vertices property as if + * cogl_primitive_set_n_vertices() were called. This property defines + * the number of vertices to read when drawing. + + * The primitive API doesn't support drawing with sliced + * textures (since switching between slices implies changing state and + * so that implies multiple primitives need to be submitted). You + * should pass the %COGL_TEXTURE_NO_SLICING flag to all textures that + * might be used while drawing with this API. If your hardware doesn't + * support non-power of two textures (For example you are using GLES + * 1.1) then you will need to make sure your assets are resized to a + * power-of-two size (though they don't have to be square) + * + * Return value: (transfer full): A newly allocated #CoglPrimitive + * with a reference of 1. This can be freed using cogl_object_unref(). + * + * Since: 1.6 + * Stability: Unstable + */ +CoglPrimitive * +cogl_primitive_new_p3t2c4 (CoglContext *context, + CoglVerticesMode mode, + int n_vertices, + const CoglVertexP3T2C4 *data); +int +cogl_primitive_get_first_vertex (CoglPrimitive *primitive); + +void +cogl_primitive_set_first_vertex (CoglPrimitive *primitive, + int first_vertex); + +/** + * cogl_primitive_get_n_vertices: + * @primitive: A #CoglPrimitive object + * + * Queries the number of vertices to read when drawing the given + * @primitive. Usually this value is implicitly set when associating + * vertex data or indices with a #CoglPrimitive. + * + * If cogl_primitive_set_indices() has been used to associate a + * sequence of #CoglIndices with the given @primitive then the + * number of vertices to read can also be phrased as the number + * of indices to read. + * + * To be clear; it doesn't refer to the number of vertices - in + * terms of data - associated with the primitive it's just the number + * of vertices to read and draw. + * + * Returns: The number of vertices to read when drawing. + * + * Since: 1.8 + * Stability: unstable + */ +int +cogl_primitive_get_n_vertices (CoglPrimitive *primitive); + +/** + * cogl_primitive_set_n_vertices: + * @primitive: A #CoglPrimitive object + * @n_vertices: The number of vertices to read when drawing. + * + * Specifies how many vertices should be read when drawing the given + * @primitive. + * + * Usually this value is set implicitly when associating vertex data + * or indices with a #CoglPrimitive. + * + * To be clear; it doesn't refer to the number of vertices - in + * terms of data - associated with the primitive it's just the number + * of vertices to read and draw. + * + * Since: 1.8 + * Stability: unstable + */ +void +cogl_primitive_set_n_vertices (CoglPrimitive *primitive, + int n_vertices); + +CoglVerticesMode +cogl_primitive_get_mode (CoglPrimitive *primitive); + +void +cogl_primitive_set_mode (CoglPrimitive *primitive, + CoglVerticesMode mode); + +/** + * cogl_primitive_set_attributes: (skip) + * @primitive: A #CoglPrimitive object + * @attributes: an array of #CoglAttribute pointers + * @n_attributes: the number of elements in @attributes + * + * Replaces all the attributes of the given #CoglPrimitive object. + * + * Since: 1.6 + * Stability: Unstable + */ +void +cogl_primitive_set_attributes (CoglPrimitive *primitive, + CoglAttribute **attributes, + int n_attributes); + +/** + * cogl_primitive_set_indices: (skip) + * @primitive: A #CoglPrimitive + * @indices: A #CoglIndices array + * @n_indices: The number of indices to reference when drawing + * + * Associates a sequence of #CoglIndices with the given @primitive. + * + * #CoglIndices provide a way to virtualize your real vertex data by + * providing a sequence of indices that index into your real vertex + * data. The GPU will walk though the index values to indirectly + * lookup the data for each vertex instead of sequentially walking + * through the data directly. This lets you save memory by indexing + * shared data multiple times instead of duplicating the data. + * + * The value passed as @n_indices will simply update the + * #CoglPrimitive n_vertices property as if + * cogl_primitive_set_n_vertices() were called. This property defines + * the number of vertices to draw or, put another way, how many + * indices should be read from @indices when drawing. + * + * The #CoglPrimitive first_vertex property + * also affects drawing with indices by defining the first entry of the + * indices to start drawing from. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_primitive_set_indices (CoglPrimitive *primitive, + CoglIndices *indices, + int n_indices); + +/** + * cogl_primitive_get_indices: (skip) + * @primitive: A #CoglPrimitive + * + * Return value: (transfer none): the indices that were set with + * cogl_primitive_set_indices() or %NULL if no indices were set. + * + * Since: 1.10 + * Stability: unstable + */ +CoglIndices * +cogl_primitive_get_indices (CoglPrimitive *primitive); + +/** + * cogl_primitive_copy: + * @primitive: A primitive copy + * + * Makes a copy of an existing #CoglPrimitive. Note that the primitive + * is a shallow copy which means it will use the same attributes and + * attribute buffers as the original primitive. + * + * Return value: (transfer full): the new primitive + * Since: 1.10 + * Stability: unstable + */ +CoglPrimitive * +cogl_primitive_copy (CoglPrimitive *primitive); + +/** + * cogl_is_primitive: + * @object: A #CoglObject + * + * Gets whether the given object references a #CoglPrimitive. + * + * Returns: %TRUE if the @object references a #CoglPrimitive, + * %FALSE otherwise + * + * Since: 1.6 + * Stability: Unstable + */ +CoglBool +cogl_is_primitive (void *object); + +/** + * CoglPrimitiveAttributeCallback: + * @primitive: The #CoglPrimitive whose attributes are being iterated + * @attribute: The #CoglAttribute + * @user_data: The private data passed to cogl_primitive_foreach_attribute() + * + * The callback prototype used with cogl_primitive_foreach_attribute() + * for iterating all the attributes of a #CoglPrimitive. + * + * The function should return TRUE to continue iteration or FALSE to + * stop. + * + * Since: 1.10 + * Stability: Unstable + */ +typedef CoglBool (* CoglPrimitiveAttributeCallback) (CoglPrimitive *primitive, + CoglAttribute *attribute, + void *user_data); + +/** + * cogl_primitive_foreach_attribute: + * @primitive: A #CoglPrimitive object + * @callback: (scope call): A #CoglPrimitiveAttributeCallback to be + * called for each attribute + * @user_data: (closure): Private data that will be passed to the + * callback + * + * Iterates all the attributes of the given #CoglPrimitive. + * + * Since: 1.10 + * Stability: Unstable + */ +void +cogl_primitive_foreach_attribute (CoglPrimitive *primitive, + CoglPrimitiveAttributeCallback callback, + void *user_data); + +/** + * cogl_primitive_draw: (skip) + * @primitive: A #CoglPrimitive geometry object + * @framebuffer: A destination #CoglFramebuffer + * @pipeline: A #CoglPipeline state object + * + * Draws the given @primitive geometry to the specified destination + * @framebuffer using the graphics processing state described by @pipeline. + * + * This drawing api doesn't support high-level meta texture types such + * as #CoglTexture2DSliced so it is the user's responsibility to + * ensure that only low-level textures that can be directly sampled by + * a GPU such as #CoglTexture2D, #CoglTextureRectangle or #CoglTexture3D + * are associated with layers of the given @pipeline. + * + * Stability: unstable + * Since: 1.16 + */ +void +cogl_primitive_draw (CoglPrimitive *primitive, + CoglFramebuffer *framebuffer, + CoglPipeline *pipeline); + + +COGL_END_DECLS + +#endif /* __COGL_PRIMITIVE_H__ */ + diff --git a/cogl/cogl/cogl-primitives-private.h b/cogl/cogl/cogl-primitives-private.h new file mode 100644 index 0000000..10db869 --- /dev/null +++ b/cogl/cogl/cogl-primitives-private.h @@ -0,0 +1,67 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_PRIMITIVES_PRIVATE_H +#define __COGL_PRIMITIVES_PRIVATE_H + +#include + +COGL_BEGIN_DECLS + +/* Draws a rectangle without going through the journal so that it will + be flushed immediately. This should only be used in situations + where the code may be called while the journal is already being + flushed. In that case using the journal would go wrong */ +void +_cogl_rectangle_immediate (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + float x_1, + float y_1, + float x_2, + float y_2); + +typedef struct _CoglMultiTexturedRect +{ + const float *position; /* x0,y0,x1,y1 */ + const float *tex_coords; /* (tx0,ty0,tx1,ty1)(tx0,ty0,tx1,ty1)(... */ + int tex_coords_len; /* number of floats in tex_coords? */ +} CoglMultiTexturedRect; + +void +_cogl_framebuffer_draw_multitextured_rectangles ( + CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglMultiTexturedRect *rects, + int n_rects, + CoglBool disable_legacy_state); + +COGL_END_DECLS + +#endif /* __COGL_PRIMITIVES_PRIVATE_H */ diff --git a/cogl/cogl/cogl-primitives.c b/cogl/cogl/cogl-primitives.c new file mode 100644 index 0000000..07ef412 --- /dev/null +++ b/cogl/cogl/cogl-primitives.c @@ -0,0 +1,1148 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-debug.h" +#include "cogl-context-private.h" +#include "cogl-journal-private.h" +#include "cogl-texture-private.h" +#include "cogl-pipeline-private.h" +#include "cogl-pipeline-opengl-private.h" +#include "cogl-vertex-buffer-private.h" +#include "cogl-framebuffer-private.h" +#include "cogl-attribute-private.h" +#include "cogl-private.h" +#include "cogl-meta-texture.h" +#include "cogl-framebuffer-private.h" +#include "cogl1-context.h" +#include "cogl-primitives-private.h" + +#include +#include + +#define _COGL_MAX_BEZ_RECURSE_DEPTH 16 + +typedef struct _TextureSlicedQuadState +{ + CoglFramebuffer *framebuffer; + CoglPipeline *pipeline; + CoglTexture *main_texture; + float tex_virtual_origin_x; + float tex_virtual_origin_y; + float quad_origin_x; + float quad_origin_y; + float v_to_q_scale_x; + float v_to_q_scale_y; + float quad_len_x; + float quad_len_y; + CoglBool flipped_x; + CoglBool flipped_y; +} TextureSlicedQuadState; + +typedef struct _TextureSlicedPolygonState +{ + const CoglTextureVertex *vertices; + int n_vertices; + int stride; + CoglAttribute **attributes; +} TextureSlicedPolygonState; + +static void +log_quad_sub_textures_cb (CoglTexture *texture, + const float *subtexture_coords, + const float *virtual_coords, + void *user_data) +{ + TextureSlicedQuadState *state = user_data; + CoglFramebuffer *framebuffer = state->framebuffer; + CoglTexture *texture_override; + float quad_coords[4]; + +#define TEX_VIRTUAL_TO_QUAD(V, Q, AXIS) \ + do { \ + Q = V - state->tex_virtual_origin_##AXIS; \ + Q *= state->v_to_q_scale_##AXIS; \ + if (state->flipped_##AXIS) \ + Q = state->quad_len_##AXIS - Q; \ + Q += state->quad_origin_##AXIS; \ + } while (0); + + TEX_VIRTUAL_TO_QUAD (virtual_coords[0], quad_coords[0], x); + TEX_VIRTUAL_TO_QUAD (virtual_coords[1], quad_coords[1], y); + + TEX_VIRTUAL_TO_QUAD (virtual_coords[2], quad_coords[2], x); + TEX_VIRTUAL_TO_QUAD (virtual_coords[3], quad_coords[3], y); + +#undef TEX_VIRTUAL_TO_QUAD + + COGL_NOTE (DRAW, + "~~~~~ slice\n" + "qx1: %f\t" + "qy1: %f\n" + "qx2: %f\t" + "qy2: %f\n" + "tx1: %f\t" + "ty1: %f\n" + "tx2: %f\t" + "ty2: %f\n", + quad_coords[0], quad_coords[1], + quad_coords[2], quad_coords[3], + subtexture_coords[0], subtexture_coords[1], + subtexture_coords[2], subtexture_coords[3]); + + /* We only need to override the texture if it's different from the + main texture */ + if (texture == state->main_texture) + texture_override = NULL; + else + texture_override = texture; + + _cogl_journal_log_quad (framebuffer->journal, + quad_coords, + state->pipeline, + 1, /* one layer */ + texture_override, /* replace the layer0 texture */ + subtexture_coords, + 4); +} + +typedef struct _ValidateFirstLayerState +{ + CoglPipeline *override_pipeline; +} ValidateFirstLayerState; + +static CoglBool +validate_first_layer_cb (CoglPipeline *pipeline, + int layer_index, + void *user_data) +{ + ValidateFirstLayerState *state = user_data; + CoglPipelineWrapMode clamp_to_edge = + COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE; + CoglPipelineWrapMode wrap_s; + CoglPipelineWrapMode wrap_t; + + /* We can't use hardware repeat so we need to set clamp to edge + * otherwise it might pull in edge pixels from the other side. By + * default WRAP_MODE_AUTOMATIC becomes CLAMP_TO_EDGE so we only need + * to override if the wrap mode isn't already automatic or + * clamp_to_edge. + */ + wrap_s = cogl_pipeline_get_layer_wrap_mode_s (pipeline, layer_index); + if (wrap_s != COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE && + wrap_s != COGL_PIPELINE_WRAP_MODE_AUTOMATIC) + { + if (!state->override_pipeline) + state->override_pipeline = cogl_pipeline_copy (pipeline); + cogl_pipeline_set_layer_wrap_mode_s (state->override_pipeline, + layer_index, clamp_to_edge); + } + + wrap_t = cogl_pipeline_get_layer_wrap_mode_t (pipeline, layer_index); + if (wrap_t != COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE && + wrap_t != COGL_PIPELINE_WRAP_MODE_AUTOMATIC) + { + if (!state->override_pipeline) + state->override_pipeline = cogl_pipeline_copy (pipeline); + cogl_pipeline_set_layer_wrap_mode_t (state->override_pipeline, + layer_index, clamp_to_edge); + } + + return FALSE; +} + +/* This path doesn't currently support multitexturing but is used for + * CoglTextures that don't support repeating using the GPU so we need to + * manually emit extra geometry to fake the repeating. This includes: + * + * - CoglTexture2DSliced: when made of > 1 slice or if the users given + * texture coordinates require repeating, + * - CoglTexture2DAtlas: if the users given texture coordinates require + * repeating, + * - CoglTextureRectangle: if the users given texture coordinates require + * repeating, + * - CoglTexturePixmap: if the users given texture coordinates require + * repeating + */ +/* TODO: support multitexturing */ +static void +_cogl_texture_quad_multiple_primitives (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglTexture *texture, + int layer_index, + const float *position, + float tx_1, + float ty_1, + float tx_2, + float ty_2) +{ + TextureSlicedQuadState state; + CoglBool tex_virtual_flipped_x; + CoglBool tex_virtual_flipped_y; + CoglBool quad_flipped_x; + CoglBool quad_flipped_y; + ValidateFirstLayerState validate_first_layer_state; + CoglPipelineWrapMode wrap_s, wrap_t; + + wrap_s = cogl_pipeline_get_layer_wrap_mode_s (pipeline, layer_index); + wrap_t = cogl_pipeline_get_layer_wrap_mode_t (pipeline, layer_index); + + validate_first_layer_state.override_pipeline = NULL; + cogl_pipeline_foreach_layer (pipeline, + validate_first_layer_cb, + &validate_first_layer_state); + + state.framebuffer = framebuffer; + state.main_texture = texture; + + if (validate_first_layer_state.override_pipeline) + state.pipeline = validate_first_layer_state.override_pipeline; + else + state.pipeline = pipeline; + + /* Get together the data we need to transform the virtual texture + * coordinates of each slice into quad coordinates... + * + * NB: We need to consider that the quad coordinates and the texture + * coordinates may be inverted along the x or y axis, and must preserve the + * inversions when we emit the final geometry. + */ + +#define X0 0 +#define Y0 1 +#define X1 2 +#define Y1 3 + + tex_virtual_flipped_x = (tx_1 > tx_2) ? TRUE : FALSE; + tex_virtual_flipped_y = (ty_1 > ty_2) ? TRUE : FALSE; + state.tex_virtual_origin_x = tex_virtual_flipped_x ? tx_2 : tx_1; + state.tex_virtual_origin_y = tex_virtual_flipped_y ? ty_2 : ty_1; + + quad_flipped_x = (position[X0] > position[X1]) ? TRUE : FALSE; + quad_flipped_y = (position[Y0] > position[Y1]) ? TRUE : FALSE; + state.quad_origin_x = quad_flipped_x ? position[X1] : position[X0]; + state.quad_origin_y = quad_flipped_y ? position[Y1] : position[Y0]; + + /* flatten the two forms of coordinate inversion into one... */ + state.flipped_x = tex_virtual_flipped_x ^ quad_flipped_x; + state.flipped_y = tex_virtual_flipped_y ^ quad_flipped_y; + + /* We use the _len_AXIS naming here instead of _width and _height because + * log_quad_slice_cb uses a macro with symbol concatenation to handle both + * axis, so this is more convenient... */ + state.quad_len_x = fabs (position[X1] - position[X0]); + state.quad_len_y = fabs (position[Y1] - position[Y0]); + +#undef X0 +#undef Y0 +#undef X1 +#undef Y1 + + state.v_to_q_scale_x = fabs (state.quad_len_x / (tx_2 - tx_1)); + state.v_to_q_scale_y = fabs (state.quad_len_y / (ty_2 - ty_1)); + + /* For backwards compatablity the default wrap mode for cogl_rectangle() is + * _REPEAT... */ + if (wrap_s == COGL_PIPELINE_WRAP_MODE_AUTOMATIC) + wrap_s = COGL_PIPELINE_WRAP_MODE_REPEAT; + if (wrap_t == COGL_PIPELINE_WRAP_MODE_AUTOMATIC) + wrap_t = COGL_PIPELINE_WRAP_MODE_REPEAT; + + cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (texture), + tx_1, ty_1, tx_2, ty_2, + wrap_s, + wrap_t, + log_quad_sub_textures_cb, + &state); + + if (validate_first_layer_state.override_pipeline) + cogl_object_unref (validate_first_layer_state.override_pipeline); +} + +typedef struct _ValidateTexCoordsState +{ + int i; + int n_layers; + const float *user_tex_coords; + int user_tex_coords_len; + float *final_tex_coords; + CoglPipeline *override_pipeline; + CoglBool needs_multiple_primitives; +} ValidateTexCoordsState; + +/* + * Validate the texture coordinates for this rectangle. + */ +static CoglBool +validate_tex_coords_cb (CoglPipeline *pipeline, + int layer_index, + void *user_data) +{ + ValidateTexCoordsState *state = user_data; + CoglTexture *texture; + const float *in_tex_coords; + float *out_tex_coords; + float default_tex_coords[4] = {0.0, 0.0, 1.0, 1.0}; + CoglTransformResult transform_result; + + state->i++; + + /* FIXME: we should be able to avoid this copying when no + * transform is required by the texture backend and the user + * has supplied enough coordinates for all the layers. + */ + + /* If the user didn't supply texture coordinates for this layer + then use the default coords */ + if (state->i >= state->user_tex_coords_len / 4) + in_tex_coords = default_tex_coords; + else + in_tex_coords = &state->user_tex_coords[state->i * 4]; + + out_tex_coords = &state->final_tex_coords[state->i * 4]; + + memcpy (out_tex_coords, in_tex_coords, sizeof (float) * 4); + + texture = cogl_pipeline_get_layer_texture (pipeline, layer_index); + + /* NB: NULL textures are handled by _cogl_pipeline_flush_gl_state */ + if (!texture) + return TRUE; + + /* Convert the texture coordinates to GL. + */ + transform_result = + _cogl_texture_transform_quad_coords_to_gl (texture, + out_tex_coords); + /* If the texture has waste or we are using GL_TEXTURE_RECT we + * can't handle texture repeating so we can't use the layer if + * repeating is required. + * + * NB: We already know that no texture matrix is being used if the + * texture doesn't support hardware repeat. + */ + if (transform_result == COGL_TRANSFORM_SOFTWARE_REPEAT) + { + if (state->i == 0) + { + if (state->n_layers > 1) + { + static CoglBool warning_seen = FALSE; + if (!warning_seen) + g_warning ("Skipping layers 1..n of your material since " + "the first layer doesn't support hardware " + "repeat (e.g. because of waste or use of " + "GL_TEXTURE_RECTANGLE_ARB) and you supplied " + "texture coordinates outside the range [0,1]." + "Falling back to software repeat assuming " + "layer 0 is the most important one keep"); + warning_seen = TRUE; + } + + if (state->override_pipeline) + cogl_object_unref (state->override_pipeline); + state->needs_multiple_primitives = TRUE; + return FALSE; + } + else + { + static CoglBool warning_seen = FALSE; + if (!warning_seen) + g_warning ("Skipping layer %d of your material " + "since you have supplied texture coords " + "outside the range [0,1] but the texture " + "doesn't support hardware repeat (e.g. " + "because of waste or use of " + "GL_TEXTURE_RECTANGLE_ARB). This isn't " + "supported with multi-texturing.", state->i); + warning_seen = TRUE; + + cogl_pipeline_set_layer_texture (pipeline, layer_index, NULL); + } + } + + /* By default WRAP_MODE_AUTOMATIC becomes to CLAMP_TO_EDGE. If + the texture coordinates need repeating then we'll override + this to GL_REPEAT. Otherwise we'll leave it at CLAMP_TO_EDGE + so that it won't blend in pixels from the opposite side when + the full texture is drawn with GL_LINEAR filter mode */ + if (transform_result == COGL_TRANSFORM_HARDWARE_REPEAT) + { + if (cogl_pipeline_get_layer_wrap_mode_s (pipeline, layer_index) == + COGL_PIPELINE_WRAP_MODE_AUTOMATIC) + { + if (!state->override_pipeline) + state->override_pipeline = cogl_pipeline_copy (pipeline); + cogl_pipeline_set_layer_wrap_mode_s (state->override_pipeline, + layer_index, + COGL_PIPELINE_WRAP_MODE_REPEAT); + } + if (cogl_pipeline_get_layer_wrap_mode_t (pipeline, layer_index) == + COGL_PIPELINE_WRAP_MODE_AUTOMATIC) + { + if (!state->override_pipeline) + state->override_pipeline = cogl_pipeline_copy (pipeline); + cogl_pipeline_set_layer_wrap_mode_t (state->override_pipeline, + layer_index, + COGL_PIPELINE_WRAP_MODE_REPEAT); + } + } + + return TRUE; +} + +/* This path supports multitexturing but only when each of the layers is + * handled with a single GL texture. Also if repeating is necessary then + * _cogl_texture_can_hardware_repeat() must return TRUE. + * This includes layers made from: + * + * - CoglTexture2DSliced: if only comprised of a single slice with optional + * waste, assuming the users given texture coordinates don't require + * repeating. + * - CoglTexture{1D,2D,3D}: always. + * - CoglTexture2DAtlas: assuming the users given texture coordinates don't + * require repeating. + * - CoglTextureRectangle: assuming the users given texture coordinates don't + * require repeating. + * - CoglTexturePixmap: assuming the users given texture coordinates don't + * require repeating. + */ +static CoglBool +_cogl_multitexture_quad_single_primitive (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + const float *position, + const float *user_tex_coords, + int user_tex_coords_len) +{ + int n_layers = cogl_pipeline_get_n_layers (pipeline); + ValidateTexCoordsState state; + float *final_tex_coords = alloca (sizeof (float) * 4 * n_layers); + + state.i = -1; + state.n_layers = n_layers; + state.user_tex_coords = user_tex_coords; + state.user_tex_coords_len = user_tex_coords_len; + state.final_tex_coords = final_tex_coords; + state.override_pipeline = NULL; + state.needs_multiple_primitives = FALSE; + + cogl_pipeline_foreach_layer (pipeline, + validate_tex_coords_cb, + &state); + + if (state.needs_multiple_primitives) + return FALSE; + + if (state.override_pipeline) + pipeline = state.override_pipeline; + + _cogl_journal_log_quad (framebuffer->journal, + position, + pipeline, + n_layers, + NULL, /* no texture override */ + final_tex_coords, + n_layers * 4); + + if (state.override_pipeline) + cogl_object_unref (state.override_pipeline); + + return TRUE; +} + +typedef struct _ValidateLayerState +{ + CoglContext *ctx; + int i; + int first_layer; + CoglPipeline *override_source; + CoglBool all_use_sliced_quad_fallback; +} ValidateLayerState; + +static CoglBool +_cogl_rectangles_validate_layer_cb (CoglPipeline *pipeline, + int layer_index, + void *user_data) +{ + ValidateLayerState *state = user_data; + CoglTexture *texture; + + state->i++; + + /* We need to ensure the mipmaps are ready before deciding + * anything else about the texture because the texture storage + * could completely change if it needs to be migrated out of the + * atlas and will affect how we validate the layer. + * + * FIXME: this needs to be generalized. There could be any + * number of things that might require a shuffling of the + * underlying texture storage. We could add two mechanisms to + * generalize this a bit... + * + * 1) add a _cogl_pipeline_layer_update_storage() function that + * would for instance consider if mipmapping is necessary and + * potentially migrate the texture from an atlas. + * + * 2) allow setting of transient primitive-flags on a pipeline + * that may affect the outcome of _update_storage(). One flag + * could indicate that we expect to sample beyond the bounds of + * the texture border. + * + * flags = COGL_PIPELINE_PRIMITIVE_FLAG_VALID_BORDERS; + * _cogl_pipeline_layer_assert_primitive_flags (layer, flags) + * _cogl_pipeline_layer_update_storage (layer) + * enqueue primitive in journal + * + * when the primitive is dequeued and drawn we should: + * _cogl_pipeline_flush_gl_state (pipeline) + * draw primitive + * _cogl_pipeline_unassert_primitive_flags (layer, flags); + * + * _cogl_pipeline_layer_update_storage should take into + * consideration all the asserted primitive requirements. (E.g. + * there could be multiple primitives in the journal - or in a + * renderlist in the future - that need mipmaps or that need + * valid contents beyond their borders (for cogl_polygon) + * meaning they can't work with textures in an atas, so + * _cogl_pipeline_layer_update_storage would pass on these + * requirements to the texture atlas backend which would make + * sure the referenced texture is migrated out of the atlas and + * mipmaps are generated.) + */ + _cogl_pipeline_pre_paint_for_layer (pipeline, layer_index); + + texture = cogl_pipeline_get_layer_texture (pipeline, layer_index); + + /* NULL textures are handled by + * _cogl_pipeline_flush_gl_state */ + if (texture == NULL) + return TRUE; + + if (state->i == 0) + state->first_layer = layer_index; + + /* XXX: + * For now, if the first layer is sliced then all other layers are + * ignored since we currently don't support multi-texturing with + * sliced textures. If the first layer is not sliced then any other + * layers found to be sliced will be skipped. (with a warning) + * + * TODO: Add support for multi-texturing rectangles with sliced + * textures if no texture matrices are in use. + */ + if (cogl_texture_is_sliced (texture)) + { + if (state->i == 0) + { + if (cogl_pipeline_get_n_layers (pipeline) > 1) + { + static CoglBool warning_seen = FALSE; + + if (!state->override_source) + state->override_source = cogl_pipeline_copy (pipeline); + _cogl_pipeline_prune_to_n_layers (state->override_source, 1); + + if (!warning_seen) + g_warning ("Skipping layers 1..n of your pipeline since " + "the first layer is sliced. We don't currently " + "support any multi-texturing with sliced " + "textures but assume layer 0 is the most " + "important to keep"); + warning_seen = TRUE; + } + + state->all_use_sliced_quad_fallback = TRUE; + + return FALSE; + } + else + { + static CoglBool warning_seen = FALSE; + CoglTexture2D *tex_2d; + + if (!warning_seen) + g_warning ("Skipping layer %d of your pipeline consisting of " + "a sliced texture (unsuported for multi texturing)", + state->i); + warning_seen = TRUE; + + /* Note: currently only 2D textures can be sliced. */ + tex_2d = state->ctx->default_gl_texture_2d_tex; + cogl_pipeline_set_layer_texture (pipeline, layer_index, + COGL_TEXTURE (tex_2d)); + return TRUE; + } + } + +#ifdef COGL_ENABLE_DEBUG + /* If the texture can't be repeated with the GPU (e.g. because it has + * waste or if using GL_TEXTURE_RECTANGLE_ARB) then if a texture matrix + * is also in use we don't know if the result will end up trying + * to texture from the waste area. + * + * Note: we check can_hardware_repeat() first since it's cheaper. + * + * Note: cases where the texture coordinates will require repeating + * will be caught by later validation. + */ + if (!_cogl_texture_can_hardware_repeat (texture) && + _cogl_pipeline_layer_has_user_matrix (pipeline, layer_index)) + { + static CoglBool warning_seen = FALSE; + if (!warning_seen) + g_warning ("layer %d of your pipeline uses a custom " + "texture matrix but because the texture doesn't " + "support hardware repeating you may see artefacts " + "due to sampling beyond the texture's bounds.", + state->i); + warning_seen = TRUE; + } +#endif + + return TRUE; +} + +void +_cogl_framebuffer_draw_multitextured_rectangles ( + CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglMultiTexturedRect *rects, + int n_rects, + CoglBool disable_legacy_state) +{ + CoglContext *ctx = framebuffer->context; + CoglPipeline *original_pipeline; + ValidateLayerState state; + int i; + + original_pipeline = pipeline; + + /* + * Validate all the layers of the current source pipeline... + */ + state.ctx = ctx; + state.i = -1; + state.first_layer = 0; + state.override_source = NULL; + state.all_use_sliced_quad_fallback = FALSE; + cogl_pipeline_foreach_layer (pipeline, + _cogl_rectangles_validate_layer_cb, + &state); + + if (state.override_source) + pipeline = state.override_source; + + if (!disable_legacy_state) + { + if (G_UNLIKELY (ctx->legacy_state_set) && + _cogl_get_enable_legacy_state ()) + { + /* If we haven't already made a pipeline copy */ + if (pipeline == original_pipeline) + pipeline = cogl_pipeline_copy (pipeline); + _cogl_pipeline_apply_legacy_state (pipeline); + } + } + + /* + * Emit geometry for each of the rectangles... + */ + + for (i = 0; i < n_rects; i++) + { + CoglTexture *texture; + const float default_tex_coords[4] = {0.0, 0.0, 1.0, 1.0}; + const float *tex_coords; + + if (!state.all_use_sliced_quad_fallback) + { + CoglBool success = + _cogl_multitexture_quad_single_primitive (framebuffer, + pipeline, + rects[i].position, + rects[i].tex_coords, + rects[i].tex_coords_len); + + /* NB: If _cogl_multitexture_quad_single_primitive fails then it + * means the user tried to use texture repeat with a texture that + * can't be repeated by the GPU (e.g. due to waste or use of + * GL_TEXTURE_RECTANGLE_ARB) */ + if (success) + continue; + } + + /* If multitexturing failed or we are drawing with a sliced texture + * then we only support a single layer so we pluck out the texture + * from the first pipeline layer... */ + texture = cogl_pipeline_get_layer_texture (pipeline, state.first_layer); + + if (rects[i].tex_coords) + tex_coords = rects[i].tex_coords; + else + tex_coords = default_tex_coords; + + COGL_NOTE (DRAW, "Drawing Tex Quad (Multi-Prim Mode)"); + + _cogl_texture_quad_multiple_primitives (framebuffer, + pipeline, + texture, + state.first_layer, + rects[i].position, + tex_coords[0], + tex_coords[1], + tex_coords[2], + tex_coords[3]); + } + + if (pipeline != original_pipeline) + cogl_object_unref (pipeline); +} + +static void +_cogl_rectangles_with_multitexture_coords ( + CoglMultiTexturedRect *rects, + int n_rects) +{ + _cogl_framebuffer_draw_multitextured_rectangles (cogl_get_draw_framebuffer (), + cogl_get_source (), + rects, + n_rects, + FALSE); +} + +void +cogl_rectangles (const float *verts, + unsigned int n_rects) +{ + CoglMultiTexturedRect *rects; + int i; + + /* XXX: All the cogl_rectangle* APIs normalize their input into an array of + * CoglMultiTexturedRect rectangles and pass these on to our work horse; + * _cogl_rectangles_with_multitexture_coords. + */ + + rects = g_alloca (n_rects * sizeof (CoglMultiTexturedRect)); + + for (i = 0; i < n_rects; i++) + { + rects[i].position = &verts[i * 4]; + rects[i].tex_coords = NULL; + rects[i].tex_coords_len = 0; + } + + _cogl_rectangles_with_multitexture_coords (rects, n_rects); +} + +void +cogl_rectangles_with_texture_coords (const float *verts, + unsigned int n_rects) +{ + CoglMultiTexturedRect *rects; + int i; + + /* XXX: All the cogl_rectangle* APIs normalize their input into an array of + * CoglMultiTexturedRect rectangles and pass these on to our work horse; + * _cogl_rectangles_with_multitexture_coords. + */ + + rects = g_alloca (n_rects * sizeof (CoglMultiTexturedRect)); + + for (i = 0; i < n_rects; i++) + { + rects[i].position = &verts[i * 8]; + rects[i].tex_coords = &verts[i * 8 + 4]; + rects[i].tex_coords_len = 4; + } + + _cogl_rectangles_with_multitexture_coords (rects, n_rects); +} + +void +cogl_rectangle_with_texture_coords (float x_1, + float y_1, + float x_2, + float y_2, + float tx_1, + float ty_1, + float tx_2, + float ty_2) +{ + const float position[4] = {x_1, y_1, x_2, y_2}; + const float tex_coords[4] = {tx_1, ty_1, tx_2, ty_2}; + CoglMultiTexturedRect rect; + + /* XXX: All the cogl_rectangle* APIs normalize their input into an array of + * CoglMultiTexturedRect rectangles and pass these on to our work horse; + * _cogl_rectangles_with_multitexture_coords. + */ + + rect.position = position; + rect.tex_coords = tex_coords; + rect.tex_coords_len = 4; + + _cogl_rectangles_with_multitexture_coords (&rect, 1); +} + +void +cogl_rectangle_with_multitexture_coords (float x_1, + float y_1, + float x_2, + float y_2, + const float *user_tex_coords, + int user_tex_coords_len) +{ + const float position[4] = {x_1, y_1, x_2, y_2}; + CoglMultiTexturedRect rect; + + /* XXX: All the cogl_rectangle* APIs normalize their input into an array of + * CoglMultiTexturedRect rectangles and pass these on to our work horse; + * _cogl_rectangles_with_multitexture_coords. + */ + + rect.position = position; + rect.tex_coords = user_tex_coords; + rect.tex_coords_len = user_tex_coords_len; + + _cogl_rectangles_with_multitexture_coords (&rect, 1); +} + +void +cogl_rectangle (float x_1, + float y_1, + float x_2, + float y_2) +{ + const float position[4] = {x_1, y_1, x_2, y_2}; + CoglMultiTexturedRect rect; + + /* XXX: All the cogl_rectangle* APIs normalize their input into an array of + * CoglMultiTexturedRect rectangles and pass these on to our work horse; + * _cogl_rectangles_with_multitexture_coords. + */ + + rect.position = position; + rect.tex_coords = NULL; + rect.tex_coords_len = 0; + + _cogl_rectangles_with_multitexture_coords (&rect, 1); +} + +void +_cogl_rectangle_immediate (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + float x_1, + float y_1, + float x_2, + float y_2) +{ + /* Draw a rectangle using the vertex array API to avoid going + through the journal. This should only be used in cases where the + code might be called while the journal is already being flushed + such as when flushing the clip state */ + CoglContext *ctx = framebuffer->context; + float vertices[8] = + { + x_1, y_1, + x_1, y_2, + x_2, y_1, + x_2, y_2 + }; + CoglAttributeBuffer *attribute_buffer; + CoglAttribute *attributes[1]; + + attribute_buffer = + cogl_attribute_buffer_new (ctx, sizeof (vertices), vertices); + attributes[0] = cogl_attribute_new (attribute_buffer, + "cogl_position_in", + sizeof (float) * 2, /* stride */ + 0, /* offset */ + 2, /* n_components */ + COGL_ATTRIBUTE_TYPE_FLOAT); + + _cogl_framebuffer_draw_attributes (framebuffer, + pipeline, + COGL_VERTICES_MODE_TRIANGLE_STRIP, + 0, /* first_index */ + 4, /* n_vertices */ + attributes, + 1, + COGL_DRAW_SKIP_JOURNAL_FLUSH | + COGL_DRAW_SKIP_PIPELINE_VALIDATION | + COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH | + COGL_DRAW_SKIP_LEGACY_STATE); + + + cogl_object_unref (attributes[0]); + cogl_object_unref (attribute_buffer); +} + +typedef struct _AppendTexCoordsState +{ + const CoglTextureVertex *vertices_in; + int vertex; + int layer; + float *vertices_out; +} AppendTexCoordsState; + +static CoglBool +append_tex_coord_attributes_cb (CoglPipeline *pipeline, + int layer_index, + void *user_data) +{ + AppendTexCoordsState *state = user_data; + CoglTexture *texture; + float tx, ty; + float *t; + + tx = state->vertices_in[state->vertex].tx; + ty = state->vertices_in[state->vertex].ty; + + /* NULL textures will be handled in + * _cogl_pipeline_flush_layers_gl_state but there is no need to worry + * about scaling texture coordinates in this case */ + texture = cogl_pipeline_get_layer_texture (pipeline, layer_index); + if (texture != NULL) + _cogl_texture_transform_coords_to_gl (texture, &tx, &ty); + + /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */ + t = state->vertices_out + 3 + 2 * state->layer; + t[0] = tx; + t[1] = ty; + + state->layer++; + + return TRUE; +} + +typedef struct _ValidateState +{ + CoglPipeline *original_pipeline; + CoglPipeline *pipeline; +} ValidateState; + +static CoglBool +_cogl_polygon_validate_layer_cb (CoglPipeline *pipeline, + int layer_index, + void *user_data) +{ + ValidateState *state = user_data; + + /* By default COGL_PIPELINE_WRAP_MODE_AUTOMATIC becomes + * GL_CLAMP_TO_EDGE but we want the polygon API to use GL_REPEAT to + * maintain compatibility with previous releases + */ + + if (cogl_pipeline_get_layer_wrap_mode_s (pipeline, layer_index) == + COGL_PIPELINE_WRAP_MODE_AUTOMATIC) + { + if (state->original_pipeline == state->pipeline) + state->pipeline = cogl_pipeline_copy (pipeline); + + cogl_pipeline_set_layer_wrap_mode_s (state->pipeline, layer_index, + COGL_PIPELINE_WRAP_MODE_REPEAT); + } + + if (cogl_pipeline_get_layer_wrap_mode_t (pipeline, layer_index) == + COGL_PIPELINE_WRAP_MODE_AUTOMATIC) + { + if (state->original_pipeline == state->pipeline) + state->pipeline = cogl_pipeline_copy (pipeline); + + cogl_pipeline_set_layer_wrap_mode_t (state->pipeline, layer_index, + COGL_PIPELINE_WRAP_MODE_REPEAT); + } + + return TRUE; +} + +void +cogl_polygon (const CoglTextureVertex *vertices, + unsigned int n_vertices, + CoglBool use_color) +{ + CoglPipeline *pipeline; + ValidateState validate_state; + int n_layers; + int n_attributes; + CoglAttribute **attributes; + int i; + unsigned int stride; + size_t stride_bytes; + CoglAttributeBuffer *attribute_buffer; + float *v; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + pipeline = cogl_get_source (); + + validate_state.original_pipeline = pipeline; + validate_state.pipeline = pipeline; + cogl_pipeline_foreach_layer (pipeline, + _cogl_polygon_validate_layer_cb, + &validate_state); + pipeline = validate_state.pipeline; + + n_layers = cogl_pipeline_get_n_layers (pipeline); + + n_attributes = 1 + n_layers + (use_color ? 1 : 0); + attributes = g_alloca (sizeof (CoglAttribute *) * n_attributes); + + /* Our data is arranged like: + * [X, Y, Z, TX0, TY0, TX1, TY1..., R, G, B, A,...] */ + stride = 3 + (2 * n_layers) + (use_color ? 1 : 0); + stride_bytes = stride * sizeof (float); + + /* Make sure there is enough space in the global vertex array. This + * is used so we can render the polygon with a single call to OpenGL + * but still support any number of vertices */ + g_array_set_size (ctx->polygon_vertices, n_vertices * stride); + + attribute_buffer = + cogl_attribute_buffer_new (ctx, n_vertices * stride_bytes, NULL); + + attributes[0] = cogl_attribute_new (attribute_buffer, + "cogl_position_in", + stride_bytes, + 0, + 3, + COGL_ATTRIBUTE_TYPE_FLOAT); + + for (i = 0; i < n_layers; i++) + { + static const char *names[] = { + "cogl_tex_coord0_in", + "cogl_tex_coord1_in", + "cogl_tex_coord2_in", + "cogl_tex_coord3_in", + "cogl_tex_coord4_in", + "cogl_tex_coord5_in", + "cogl_tex_coord6_in", + "cogl_tex_coord7_in" + }; + char *allocated_name = NULL; + const char *name; + + if (i < 8) + name = names[i]; + else + name = allocated_name = g_strdup_printf ("cogl_tex_coord%d_in", i); + + attributes[i + 1] = cogl_attribute_new (attribute_buffer, + name, + stride_bytes, + /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */ + 12 + 8 * i, + 2, + COGL_ATTRIBUTE_TYPE_FLOAT); + + g_free (allocated_name); + } + + if (use_color) + { + attributes[n_attributes - 1] = + cogl_attribute_new (attribute_buffer, + "cogl_color_in", + stride_bytes, + /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */ + 12 + 8 * n_layers, + 4, + COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE); + } + + /* Convert the vertices into an array of float vertex attributes */ + v = (float *)ctx->polygon_vertices->data; + for (i = 0; i < n_vertices; i++) + { + AppendTexCoordsState append_tex_coords_state; + uint8_t *c; + + /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */ + v[0] = vertices[i].x; + v[1] = vertices[i].y; + v[2] = vertices[i].z; + + append_tex_coords_state.vertices_in = vertices; + append_tex_coords_state.vertex = i; + append_tex_coords_state.layer = 0; + append_tex_coords_state.vertices_out = v; + cogl_pipeline_foreach_layer (pipeline, + append_tex_coord_attributes_cb, + &append_tex_coords_state); + + if (use_color) + { + /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */ + c = (uint8_t *) (v + 3 + 2 * n_layers); + c[0] = cogl_color_get_red_byte (&vertices[i].color); + c[1] = cogl_color_get_green_byte (&vertices[i].color); + c[2] = cogl_color_get_blue_byte (&vertices[i].color); + c[3] = cogl_color_get_alpha_byte (&vertices[i].color); + } + + v += stride; + } + + v = (float *)ctx->polygon_vertices->data; + cogl_buffer_set_data (COGL_BUFFER (attribute_buffer), + 0, + v, + ctx->polygon_vertices->len * sizeof (float)); + + /* XXX: although this may seem redundant, we need to do this since + * cogl_polygon() can be used with legacy state and its the source stack + * which track whether legacy state is enabled. + * + * (We only have a CoglDrawFlag to disable legacy state not one + * to enable it) */ + cogl_push_source (pipeline); + + _cogl_framebuffer_draw_attributes (cogl_get_draw_framebuffer (), + pipeline, + COGL_VERTICES_MODE_TRIANGLE_FAN, + 0, n_vertices, + attributes, + n_attributes, + 0 /* no draw flags */); + + cogl_pop_source (); + + if (pipeline != validate_state.original_pipeline) + cogl_object_unref (pipeline); + + cogl_object_unref (attribute_buffer); + + for (i = 0; i < n_attributes; i++) + cogl_object_unref (attributes[i]); +} diff --git a/cogl/cogl/cogl-primitives.h b/cogl/cogl/cogl-primitives.h new file mode 100644 index 0000000..0c9211e --- /dev/null +++ b/cogl/cogl/cogl-primitives.h @@ -0,0 +1,197 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_PRIMITIVES_H +#define __COGL_PRIMITIVES_H + +#include + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-primitives + * @short_description: Functions that draw various primitive 3D shapes + * + * The primitives API provides utilities for drawing some + * common 3D shapes in a more convenient way than the CoglVertexBuffer + * API provides. + */ + +/** + * cogl_rectangle: + * @x_1: X coordinate of the top-left corner + * @y_1: Y coordinate of the top-left corner + * @x_2: X coordinate of the bottom-right corner + * @y_2: Y coordinate of the bottom-right corner + * + * Fills a rectangle at the given coordinates with the current source material + **/ +void +cogl_rectangle (float x_1, + float y_1, + float x_2, + float y_2); + +/** + * cogl_rectangle_with_texture_coords: + * @x1: x coordinate upper left on screen. + * @y1: y coordinate upper left on screen. + * @x2: x coordinate lower right on screen. + * @y2: y coordinate lower right on screen. + * @tx1: x part of texture coordinate to use for upper left pixel + * @ty1: y part of texture coordinate to use for upper left pixel + * @tx2: x part of texture coordinate to use for lower right pixel + * @ty2: y part of texture coordinate to use for left pixel + * + * Draw a rectangle using the current material and supply texture coordinates + * to be used for the first texture layer of the material. To draw the entire + * texture pass in @tx1=0.0 @ty1=0.0 @tx2=1.0 @ty2=1.0. + * + * Since: 1.0 + */ +void +cogl_rectangle_with_texture_coords (float x1, + float y1, + float x2, + float y2, + float tx1, + float ty1, + float tx2, + float ty2); + +/** + * cogl_rectangle_with_multitexture_coords: + * @x1: x coordinate upper left on screen. + * @y1: y coordinate upper left on screen. + * @x2: x coordinate lower right on screen. + * @y2: y coordinate lower right on screen. + * @tex_coords: (in) (array) (transfer none): An array containing groups of + * 4 float values: [tx1, ty1, tx2, ty2] that are interpreted as two texture + * coordinates; one for the upper left texel, and one for the lower right + * texel. Each value should be between 0.0 and 1.0, where the coordinate + * (0.0, 0.0) represents the top left of the texture, and (1.0, 1.0) the + * bottom right. + * @tex_coords_len: The length of the tex_coords array. (e.g. for one layer + * and one group of texture coordinates, this would be 4) + * + * This function draws a rectangle using the current source material to + * texture or fill with. As a material may contain multiple texture layers + * this interface lets you supply texture coordinates for each layer of the + * material. + * + * The first pair of coordinates are for the first layer (with the smallest + * layer index) and if you supply less texture coordinates than there are + * layers in the current source material then default texture coordinates + * (0.0, 0.0, 1.0, 1.0) are generated. + * + * Since: 1.0 + */ +void +cogl_rectangle_with_multitexture_coords (float x1, + float y1, + float x2, + float y2, + const float *tex_coords, + int tex_coords_len); + +/** + * cogl_rectangles_with_texture_coords: + * @verts: (in) (array) (transfer none): an array of vertices + * @n_rects: number of rectangles to draw + * + * Draws a series of rectangles in the same way that + * cogl_rectangle_with_texture_coords() does. In some situations it can give a + * significant performance boost to use this function rather than + * calling cogl_rectangle_with_texture_coords() separately for each rectangle. + * + * @verts should point to an array of #floats with + * @n_rects * 8 elements. Each group of 8 values corresponds to the + * parameters x1, y1, x2, y2, tx1, ty1, tx2 and ty2 and have the same + * meaning as in cogl_rectangle_with_texture_coords(). + * + * Since: 0.8.6 + */ +void +cogl_rectangles_with_texture_coords (const float *verts, + unsigned int n_rects); + +/** + * cogl_rectangles: + * @verts: (in) (array) (transfer none): an array of vertices + * @n_rects: number of rectangles to draw + * + * Draws a series of rectangles in the same way that + * cogl_rectangle() does. In some situations it can give a + * significant performance boost to use this function rather than + * calling cogl_rectangle() separately for each rectangle. + * + * @verts should point to an array of #floats with + * @n_rects * 4 elements. Each group of 4 values corresponds to the + * parameters x1, y1, x2, and y2, and have the same + * meaning as in cogl_rectangle(). + * + * Since: 1.0 + */ +void +cogl_rectangles (const float *verts, + unsigned int n_rects); + +/** + * cogl_polygon: + * @vertices: An array of #CoglTextureVertex structs + * @n_vertices: The length of the vertices array + * @use_color: %TRUE if the color member of #CoglTextureVertex should be used + * + * Draws a convex polygon using the current source material to fill / texture + * with according to the texture coordinates passed. + * + * If @use_color is %TRUE then the color will be changed for each vertex using + * the value specified in the color member of #CoglTextureVertex. This can be + * used for example to make the texture fade out by setting the alpha value of + * the color. + * + * All of the texture coordinates must be in the range [0,1] and repeating the + * texture is not supported. + * + * Because of the way this function is implemented it will currently + * only work if either the texture is not sliced or the backend is not + * OpenGL ES and the minifying and magnifying functions are both set + * to COGL_MATERIAL_FILTER_NEAREST. + * + * Since: 1.0 + */ +void +cogl_polygon (const CoglTextureVertex *vertices, + unsigned int n_vertices, + CoglBool use_color); + +COGL_END_DECLS + +#endif /* __COGL_PRIMITIVES_H */ diff --git a/cogl/cogl/cogl-private.h b/cogl/cogl/cogl-private.h new file mode 100644 index 0000000..333955c --- /dev/null +++ b/cogl/cogl/cogl-private.h @@ -0,0 +1,170 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010,2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_PRIVATE_H__ +#define __COGL_PRIVATE_H__ + +#include + +#include "cogl-context.h" +#include "cogl-flags.h" + +COGL_BEGIN_DECLS + +typedef enum +{ + COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE, + COGL_PRIVATE_FEATURE_MESA_PACK_INVERT, + COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT, + COGL_PRIVATE_FEATURE_FOUR_CLIP_PLANES, + COGL_PRIVATE_FEATURE_PBOS, + COGL_PRIVATE_FEATURE_VBOS, + COGL_PRIVATE_FEATURE_EXT_PACKED_DEPTH_STENCIL, + COGL_PRIVATE_FEATURE_OES_PACKED_DEPTH_STENCIL, + COGL_PRIVATE_FEATURE_TEXTURE_FORMAT_BGRA8888, + COGL_PRIVATE_FEATURE_UNPACK_SUBIMAGE, + COGL_PRIVATE_FEATURE_SAMPLER_OBJECTS, + COGL_PRIVATE_FEATURE_READ_PIXELS_ANY_FORMAT, + COGL_PRIVATE_FEATURE_ALPHA_TEST, + COGL_PRIVATE_FEATURE_FORMAT_CONVERSION, + COGL_PRIVATE_FEATURE_QUADS, + COGL_PRIVATE_FEATURE_BLEND_CONSTANT, + COGL_PRIVATE_FEATURE_QUERY_FRAMEBUFFER_BITS, + COGL_PRIVATE_FEATURE_BUILTIN_POINT_SIZE_UNIFORM, + COGL_PRIVATE_FEATURE_QUERY_TEXTURE_PARAMETERS, + COGL_PRIVATE_FEATURE_ALPHA_TEXTURES, + COGL_PRIVATE_FEATURE_TEXTURE_SWIZZLE, + COGL_PRIVATE_FEATURE_TEXTURE_MAX_LEVEL, + COGL_PRIVATE_FEATURE_ARBFP, + COGL_PRIVATE_FEATURE_OES_EGL_SYNC, + /* If this is set then the winsys is responsible for queueing dirty + * events. Otherwise a dirty event will be queued when the onscreen + * is first allocated or when it is shown or resized */ + COGL_PRIVATE_FEATURE_DIRTY_EVENTS, + COGL_PRIVATE_FEATURE_ENABLE_PROGRAM_POINT_SIZE, + /* These features let us avoid conditioning code based on the exact + * driver being used and instead check for broad opengl feature + * sets that can be shared by several GL apis */ + COGL_PRIVATE_FEATURE_ANY_GL, + COGL_PRIVATE_FEATURE_GL_FIXED, + COGL_PRIVATE_FEATURE_GL_PROGRAMMABLE, + COGL_PRIVATE_FEATURE_GL_EMBEDDED, + COGL_PRIVATE_FEATURE_GL_WEB, + + COGL_N_PRIVATE_FEATURES +} CoglPrivateFeature; + +/* Sometimes when evaluating pipelines, either during comparisons or + * if calculating a hash value we need to tweak the evaluation + * semantics */ +typedef enum _CoglPipelineEvalFlags +{ + COGL_PIPELINE_EVAL_FLAG_NONE = 0 +} CoglPipelineEvalFlags; + +void +_cogl_transform_point (const CoglMatrix *matrix_mv, + const CoglMatrix *matrix_p, + const float *viewport, + float *x, + float *y); + +CoglBool +_cogl_check_extension (const char *name, char * const *ext); + +void +_cogl_clear (const CoglColor *color, unsigned long buffers); + +void +_cogl_init (void); + +void +_cogl_push_source (CoglPipeline *pipeline, CoglBool enable_legacy); + +CoglBool +_cogl_get_enable_legacy_state (void); + +#define _cogl_has_private_feature(ctx, feature) \ + COGL_FLAGS_GET ((ctx)->private_features, (feature)) + +/* + * _cogl_pixel_format_get_bytes_per_pixel: + * @format: a #CoglPixelFormat + * + * Queries how many bytes a pixel of the given @format takes. + * + * Return value: The number of bytes taken for a pixel of the given + * @format. + */ +int +_cogl_pixel_format_get_bytes_per_pixel (CoglPixelFormat format); + +/* + * _cogl_pixel_format_has_aligned_components: + * @format: a #CoglPixelFormat + * + * Queries whether the ordering of the components for the given + * @format depend on the endianness of the host CPU or if the + * components can be accessed using bit shifting and bitmasking by + * loading a whole pixel into a word. + * + * XXX: If we ever consider making something like this public we + * should really try to think of a better name and come up with + * much clearer documentation since it really depends on what + * point of view you consider this from whether a format like + * COGL_PIXEL_FORMAT_RGBA_8888 is endian dependent. E.g. If you + * read an RGBA_8888 pixel into a uint32 + * it's endian dependent how you mask out the different channels. + * But If you already have separate color components and you want + * to write them to an RGBA_8888 pixel then the bytes can be + * written sequentially regardless of the endianness. + * + * Return value: %TRUE if you need to consider the host CPU + * endianness when dealing with the given @format + * else %FALSE. + */ +CoglBool +_cogl_pixel_format_is_endian_dependant (CoglPixelFormat format); + +/* + * COGL_PIXEL_FORMAT_CAN_HAVE_PREMULT(format): + * @format: a #CoglPixelFormat + * + * Returns TRUE if the pixel format can take a premult bit. This is + * currently true for all formats that have an alpha channel except + * COGL_PIXEL_FORMAT_A_8 (because that doesn't have any other + * components to multiply by the alpha). + */ +#define COGL_PIXEL_FORMAT_CAN_HAVE_PREMULT(format) \ + (((format) & COGL_A_BIT) && (format) != COGL_PIXEL_FORMAT_A_8) + +COGL_END_DECLS + +#endif /* __COGL_PRIVATE_H__ */ diff --git a/cogl/cogl/cogl-profile.c b/cogl/cogl/cogl-profile.c new file mode 100644 index 0000000..d5bca6a --- /dev/null +++ b/cogl/cogl/cogl-profile.c @@ -0,0 +1,124 @@ +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#ifdef COGL_ENABLE_PROFILE + +#include "cogl-profile.h" +#include "cogl-debug.h" +#include "cogl-i18n-private.h" + +#include + +UProfContext *_cogl_uprof_context; + +static CoglBool +debug_option_getter (void *user_data) +{ + unsigned int shift = GPOINTER_TO_UINT (user_data); + return COGL_DEBUG_ENABLED (shift); +} + +static void +debug_option_setter (CoglBool value, void *user_data) +{ + unsigned int shift = GPOINTER_TO_UINT (user_data); + + if (value) + COGL_DEBUG_SET_FLAG (shift); + else + COGL_DEBUG_CLEAR_FLAG (shift); +} + +static void +print_exit_report (void) +{ + if (getenv ("COGL_PROFILE_OUTPUT_REPORT")) + { + UProfContext *mainloop_context; + UProfTimerResult *mainloop_timer; + UProfReport *report; + + /* NB: uprof provides a shared context for mainloop statistics + * which needs to be setup by the application which controls the + * mainloop. + * + * If no "Mainloop" timer has been setup then we print a warning + * since we can't provide a meaningful Cogl report without one. + */ + mainloop_context = uprof_get_mainloop_context (); + mainloop_timer = uprof_context_get_timer_result (mainloop_context, + "Mainloop"); + /* just bail out if the mainloop timer wasn't hit */ + if (!mainloop_timer) + { + g_warning ("\n\n" + "No UProf \"Mainloop\" timer was setup by the " + "application therefore we\ncan't provide a meaningful " + "profile report.\n" + "\n" + "This should be done automatically if you are using Clutter " + "(if\nbuilt with --enable-profile)\n" + "\n" + "If you aren't using Clutter then you can declare a " + "\"Mainloop\" UProf\ntimer in your application like this:\n\n" + " UPROF_STATIC_TIMER (mainloop_timer, \n" + " NULL,\n" + " \"Mainloop\",\n" + " \"Time in glib mainloop\",\n" + " 0);\n" + "\n" + "And start/stop it around your mainloop like this:\n" + "\n" + " UPROF_TIMER_START (uprof_get_mainloop_context (), mainloop_timer);\n" + " g_main_loop_run (loop);\n" + " UPROF_TIMER_STOP (uprof_get_mainloop_context (), mainloop_timer);\n"); + return; + } + + report = uprof_report_new ("Cogl report"); + uprof_report_add_context (report, _cogl_uprof_context); + uprof_report_print (report); + uprof_report_unref (report); + } + uprof_context_unref (_cogl_uprof_context); +} + +void +_cogl_uprof_init (void) +{ + _cogl_uprof_context = uprof_context_new ("Cogl"); + uprof_context_link (_cogl_uprof_context, uprof_get_mainloop_context ()); +#define OPT(MASK_NAME, GROUP, NAME, NAME_FORMATTED, DESCRIPTION) \ + G_STMT_START { \ + int shift = COGL_DEBUG_ ## MASK_NAME; \ + uprof_context_add_boolean_option (_cogl_uprof_context, \ + GROUP, \ + NAME, \ + NAME_FORMATTED, \ + DESCRIPTION, \ + debug_option_getter, \ + debug_option_setter, \ + GUINT_TO_POINTER (shift)); \ + } G_STMT_END; + +#include "cogl-debug-options.h" +#undef OPT + + atexit (print_exit_report); +} + +void +_cogl_profile_trace_message (const char *format, ...) +{ + va_list ap; + + va_start (ap, format); + g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, format, ap); + va_end (ap); + + if (_cogl_uprof_context) + uprof_context_vtrace_message (_cogl_uprof_context, format, ap); +} + +#endif diff --git a/cogl/cogl/cogl-profile.h b/cogl/cogl/cogl-profile.h new file mode 100644 index 0000000..db95647 --- /dev/null +++ b/cogl/cogl/cogl-profile.h @@ -0,0 +1,68 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_PROFILE_H__ +#define __COGL_PROFILE_H__ + + +#ifdef COGL_ENABLE_PROFILE + +#include + +extern UProfContext *_cogl_uprof_context; + +#define COGL_STATIC_TIMER UPROF_STATIC_TIMER +#define COGL_STATIC_COUNTER UPROF_STATIC_COUNTER +#define COGL_COUNTER_INC UPROF_COUNTER_INC +#define COGL_COUNTER_DEC UPROF_COUNTER_DEC +#define COGL_TIMER_START UPROF_TIMER_START +#define COGL_TIMER_STOP UPROF_TIMER_STOP + +void +_cogl_uprof_init (void); + +void +_cogl_profile_trace_message (const char *format, ...); + +#else + +#define COGL_STATIC_TIMER(A,B,C,D,E) extern void _cogl_dummy_decl (void) +#define COGL_STATIC_COUNTER(A,B,C,D) extern void _cogl_dummy_decl (void) +#define COGL_COUNTER_INC(A,B) G_STMT_START{ (void)0; }G_STMT_END +#define COGL_COUNTER_DEC(A,B) G_STMT_START{ (void)0; }G_STMT_END +#define COGL_TIMER_START(A,B) G_STMT_START{ (void)0; }G_STMT_END +#define COGL_TIMER_STOP(A,B) G_STMT_START{ (void)0; }G_STMT_END + +#define _cogl_profile_trace_message g_message + +#endif + +#endif /* __COGL_PROFILE_H__ */ + diff --git a/cogl/cogl/cogl-quaternion-private.h b/cogl/cogl/cogl-quaternion-private.h new file mode 100644 index 0000000..eda672e --- /dev/null +++ b/cogl/cogl/cogl-quaternion-private.h @@ -0,0 +1,44 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_QUATERNION_PRIVATE_H__ +#define __COGL_QUATERNION_PRIVATE_H__ + +#include + +/* squared length */ +#define _COGL_QUATERNION_NORM(Q) \ + ((Q)->x*(Q)->x + (Q)->y*(Q)->y + (Q)->z*(Q)->z + (Q)->w*(Q)->w) + +#define _COGL_QUATERNION_DEGREES_TO_RADIANS (G_PI / 180.0f) +#define _COGL_QUATERNION_RADIANS_TO_DEGREES (180.0f / G_PI) + +#endif /* __COGL_QUATERNION_PRIVATE_H__ */ diff --git a/cogl/cogl/cogl-quaternion.c b/cogl/cogl/cogl-quaternion.c new file mode 100644 index 0000000..d380cec --- /dev/null +++ b/cogl/cogl/cogl-quaternion.c @@ -0,0 +1,673 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Robert Bragg + * + * Various references relating to quaternions: + * + * http://www.cs.caltech.edu/courses/cs171/quatut.pdf + * http://mathworld.wolfram.com/Quaternion.html + * http://www.gamedev.net/reference/articles/article1095.asp + * http://www.cprogramming.com/tutorial/3d/quaternions.html + * http://www.isner.com/tutorials/quatSpells/quaternion_spells_12.htm + * http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q56 + * 3D Maths Primer for Graphics and Game Development ISBN-10: 1556229119 + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include "cogl-gtype-private.h" + +#include +#include + +#define FLOAT_EPSILON 1e-03 + +COGL_GTYPE_DEFINE_BOXED (Quaternion, quaternion, + cogl_quaternion_copy, + cogl_quaternion_free); + +static CoglQuaternion zero_quaternion = +{ + 0.0, 0.0, 0.0, 0.0, +}; + +static CoglQuaternion identity_quaternion = +{ + 1.0, 0.0, 0.0, 0.0, +}; + +/* This function is just here to be called from GDB so we don't really + want to put a declaration in a header and we just add it here to + avoid a warning */ +void +_cogl_quaternion_print (CoglQuaternion *quarternion); + +void +_cogl_quaternion_print (CoglQuaternion *quaternion) +{ + g_print ("[ %6.4f (%6.4f, %6.4f, %6.4f)]\n", + quaternion->w, + quaternion->x, + quaternion->y, + quaternion->z); +} + +void +cogl_quaternion_init (CoglQuaternion *quaternion, + float angle, + float x, + float y, + float z) +{ + float axis[3] = { x, y, z}; + cogl_quaternion_init_from_angle_vector (quaternion, angle, axis); +} + +void +cogl_quaternion_init_from_angle_vector (CoglQuaternion *quaternion, + float angle, + const float *axis3f_in) +{ + /* NB: We are using quaternions to represent an axis (a), angle (𝜃) pair + * in this form: + * [w=cos(𝜃/2) ( x=sin(𝜃/2)*a.x, y=sin(𝜃/2)*a.y, z=sin(𝜃/2)*a.x )] + */ + float axis[3]; + float half_angle; + float sin_half_angle; + + /* XXX: Should we make cogl_vector3_normalize have separate in and + * out args? */ + axis[0] = axis3f_in[0]; + axis[1] = axis3f_in[1]; + axis[2] = axis3f_in[2]; + cogl_vector3_normalize (axis); + + half_angle = angle * _COGL_QUATERNION_DEGREES_TO_RADIANS * 0.5f; + sin_half_angle = sinf (half_angle); + + quaternion->w = cosf (half_angle); + + quaternion->x = axis[0] * sin_half_angle; + quaternion->y = axis[1] * sin_half_angle; + quaternion->z = axis[2] * sin_half_angle; + + cogl_quaternion_normalize (quaternion); +} + +void +cogl_quaternion_init_identity (CoglQuaternion *quaternion) +{ + quaternion->w = 1.0; + + quaternion->x = 0.0; + quaternion->y = 0.0; + quaternion->z = 0.0; +} + +void +cogl_quaternion_init_from_array (CoglQuaternion *quaternion, + const float *array) +{ + quaternion->w = array[0]; + quaternion->x = array[1]; + quaternion->y = array[2]; + quaternion->z = array[3]; +} + +void +cogl_quaternion_init_from_x_rotation (CoglQuaternion *quaternion, + float angle) +{ + /* NB: We are using quaternions to represent an axis (a), angle (𝜃) pair + * in this form: + * [w=cos(𝜃/2) ( x=sin(𝜃/2)*a.x, y=sin(𝜃/2)*a.y, z=sin(𝜃/2)*a.x )] + */ + float half_angle = angle * _COGL_QUATERNION_DEGREES_TO_RADIANS * 0.5f; + + quaternion->w = cosf (half_angle); + + quaternion->x = sinf (half_angle); + quaternion->y = 0.0f; + quaternion->z = 0.0f; +} + +void +cogl_quaternion_init_from_y_rotation (CoglQuaternion *quaternion, + float angle) +{ + /* NB: We are using quaternions to represent an axis (a), angle (𝜃) pair + * in this form: + * [w=cos(𝜃/2) ( x=sin(𝜃/2)*a.x, y=sin(𝜃/2)*a.y, z=sin(𝜃/2)*a.x )] + */ + float half_angle = angle * _COGL_QUATERNION_DEGREES_TO_RADIANS * 0.5f; + + quaternion->w = cosf (half_angle); + + quaternion->x = 0.0f; + quaternion->y = sinf (half_angle); + quaternion->z = 0.0f; +} + +void +cogl_quaternion_init_from_z_rotation (CoglQuaternion *quaternion, + float angle) +{ + /* NB: We are using quaternions to represent an axis (a), angle (𝜃) pair + * in this form: + * [w=cos(𝜃/2) ( x=sin(𝜃/2)*a.x, y=sin(𝜃/2)*a.y, z=sin(𝜃/2)*a.x )] + */ + float half_angle = angle * _COGL_QUATERNION_DEGREES_TO_RADIANS * 0.5f; + + quaternion->w = cosf (half_angle); + + quaternion->x = 0.0f; + quaternion->y = 0.0f; + quaternion->z = sinf (half_angle); +} + +void +cogl_quaternion_init_from_euler (CoglQuaternion *quaternion, + const CoglEuler *euler) +{ + /* NB: We are using quaternions to represent an axis (a), angle (𝜃) pair + * in this form: + * [w=cos(𝜃/2) ( x=sin(𝜃/2)*a.x, y=sin(𝜃/2)*a.y, z=sin(𝜃/2)*a.x )] + */ + float sin_heading = + sinf (euler->heading * _COGL_QUATERNION_DEGREES_TO_RADIANS * 0.5f); + float sin_pitch = + sinf (euler->pitch * _COGL_QUATERNION_DEGREES_TO_RADIANS * 0.5f); + float sin_roll = + sinf (euler->roll * _COGL_QUATERNION_DEGREES_TO_RADIANS * 0.5f); + float cos_heading = + cosf (euler->heading * _COGL_QUATERNION_DEGREES_TO_RADIANS * 0.5f); + float cos_pitch = + cosf (euler->pitch * _COGL_QUATERNION_DEGREES_TO_RADIANS * 0.5f); + float cos_roll = + cosf (euler->roll * _COGL_QUATERNION_DEGREES_TO_RADIANS * 0.5f); + + quaternion->w = + cos_heading * cos_pitch * cos_roll + + sin_heading * sin_pitch * sin_roll; + + quaternion->x = + cos_heading * sin_pitch * cos_roll + + sin_heading * cos_pitch * sin_roll; + quaternion->y = + sin_heading * cos_pitch * cos_roll - + cos_heading * sin_pitch * sin_roll; + quaternion->z = + cos_heading * cos_pitch * sin_roll - + sin_heading * sin_pitch * cos_roll; +} + +void +cogl_quaternion_init_from_quaternion (CoglQuaternion *quaternion, + CoglQuaternion *src) +{ + memcpy (quaternion, src, sizeof (float) * 4); +} + +/* XXX: it could be nice to make something like this public... */ +/* + * COGL_MATRIX_READ: + * @MATRIX: A 4x4 transformation matrix + * @ROW: The row of the value you want to read + * @COLUMN: The column of the value you want to read + * + * Reads a value from the given matrix using integers to index + * into the matrix. + */ +#define COGL_MATRIX_READ(MATRIX, ROW, COLUMN) \ + (((const float *)matrix)[COLUMN * 4 + ROW]) + +void +cogl_quaternion_init_from_matrix (CoglQuaternion *quaternion, + const CoglMatrix *matrix) +{ + /* Algorithm devised by Ken Shoemake, Ref: + * http://campar.in.tum.de/twiki/pub/Chair/DwarfTutorial/quatut.pdf + */ + + /* 3D maths literature refers to the diagonal of a matrix as the + * "trace" of a matrix... */ + float trace = matrix->xx + matrix->yy + matrix->zz; + float root; + + if (trace > 0.0f) + { + root = sqrtf (trace + 1); + quaternion->w = root * 0.5f; + root = 0.5f / root; + quaternion->x = (matrix->zy - matrix->yz) * root; + quaternion->y = (matrix->xz - matrix->zx) * root; + quaternion->z = (matrix->yx - matrix->xy) * root; + } + else + { +#define X 0 +#define Y 1 +#define Z 2 +#define W 3 + int h = X; + if (matrix->yy > matrix->xx) + h = Y; + if (matrix->zz > COGL_MATRIX_READ (matrix, h, h)) + h = Z; + switch (h) + { +#define CASE_MACRO(i, j, k, I, J, K) \ + case I: \ + root = sqrtf ((COGL_MATRIX_READ (matrix, I, I) - \ + (COGL_MATRIX_READ (matrix, J, J) + \ + COGL_MATRIX_READ (matrix, K, K))) + \ + COGL_MATRIX_READ (matrix, W, W)); \ + quaternion->i = root * 0.5f;\ + root = 0.5f / root;\ + quaternion->j = (COGL_MATRIX_READ (matrix, I, J) + \ + COGL_MATRIX_READ (matrix, J, I)) * root; \ + quaternion->k = (COGL_MATRIX_READ (matrix, K, I) + \ + COGL_MATRIX_READ (matrix, I, K)) * root; \ + quaternion->w = (COGL_MATRIX_READ (matrix, K, J) - \ + COGL_MATRIX_READ (matrix, J, K)) * root;\ + break + CASE_MACRO (x, y, z, X, Y, Z); + CASE_MACRO (y, z, x, Y, Z, X); + CASE_MACRO (z, x, y, Z, X, Y); +#undef CASE_MACRO +#undef X +#undef Y +#undef Z + } + } + + if (matrix->ww != 1.0f) + { + float s = 1.0 / sqrtf (matrix->ww); + quaternion->w *= s; + quaternion->x *= s; + quaternion->y *= s; + quaternion->z *= s; + } +} + +CoglBool +cogl_quaternion_equal (const void *v1, const void *v2) +{ + const CoglQuaternion *a = v1; + const CoglQuaternion *b = v2; + + _COGL_RETURN_VAL_IF_FAIL (v1 != NULL, FALSE); + _COGL_RETURN_VAL_IF_FAIL (v2 != NULL, FALSE); + + if (v1 == v2) + return TRUE; + + return (a->w == b->w && + a->x == b->x && + a->y == b->y && + a->z == b->z); +} + +CoglQuaternion * +cogl_quaternion_copy (const CoglQuaternion *src) +{ + if (G_LIKELY (src)) + { + CoglQuaternion *new = g_slice_new (CoglQuaternion); + memcpy (new, src, sizeof (float) * 4); + return new; + } + else + return NULL; +} + +void +cogl_quaternion_free (CoglQuaternion *quaternion) +{ + g_slice_free (CoglQuaternion, quaternion); +} + +float +cogl_quaternion_get_rotation_angle (const CoglQuaternion *quaternion) +{ + /* NB: We are using quaternions to represent an axis (a), angle (𝜃) pair + * in this form: + * [w=cos(𝜃/2) ( x=sin(𝜃/2)*a.x, y=sin(𝜃/2)*a.y, z=sin(𝜃/2)*a.x )] + */ + + /* FIXME: clamp [-1, 1] */ + return 2.0f * acosf (quaternion->w) * _COGL_QUATERNION_RADIANS_TO_DEGREES; +} + +void +cogl_quaternion_get_rotation_axis (const CoglQuaternion *quaternion, + float *vector3) +{ + float sin_half_angle_sqr; + float one_over_sin_angle_over_2; + + /* NB: We are using quaternions to represent an axis (a), angle (𝜃) pair + * in this form: + * [w=cos(𝜃/2) ( x=sin(𝜃/2)*a.x, y=sin(𝜃/2)*a.y, z=sin(𝜃/2)*a.x )] + */ + + /* NB: sin²(𝜃) + cos²(𝜃) = 1 */ + + sin_half_angle_sqr = 1.0f - quaternion->w * quaternion->w; + + if (sin_half_angle_sqr <= 0.0f) + { + /* Either an identity quaternion or numerical imprecision. + * Either way we return an arbitrary vector. */ + vector3[0] = 1; + vector3[1] = 0; + vector3[2] = 0; + return; + } + + /* Calculate 1 / sin(𝜃/2) */ + one_over_sin_angle_over_2 = 1.0f / sqrtf (sin_half_angle_sqr); + + vector3[0] = quaternion->x * one_over_sin_angle_over_2; + vector3[1] = quaternion->y * one_over_sin_angle_over_2; + vector3[2] = quaternion->z * one_over_sin_angle_over_2; +} + +void +cogl_quaternion_normalize (CoglQuaternion *quaternion) +{ + float slen = _COGL_QUATERNION_NORM (quaternion); + float factor = 1.0f / sqrtf (slen); + + quaternion->x *= factor; + quaternion->y *= factor; + quaternion->z *= factor; + + quaternion->w *= factor; + + return; +} + +float +cogl_quaternion_dot_product (const CoglQuaternion *a, + const CoglQuaternion *b) +{ + return a->w * b->w + a->x * b->x + a->y * b->y + a->z * b->z; +} + +void +cogl_quaternion_invert (CoglQuaternion *quaternion) +{ + quaternion->x = -quaternion->x; + quaternion->y = -quaternion->y; + quaternion->z = -quaternion->z; +} + +void +cogl_quaternion_multiply (CoglQuaternion *result, + const CoglQuaternion *a, + const CoglQuaternion *b) +{ + float w = a->w; + float x = a->x; + float y = a->y; + float z = a->z; + + _COGL_RETURN_IF_FAIL (b != result); + + result->w = w * b->w - x * b->x - y * b->y - z * b->z; + + result->x = w * b->x + x * b->w + y * b->z - z * b->y; + result->y = w * b->y + y * b->w + z * b->x - x * b->z; + result->z = w * b->z + z * b->w + x * b->y - y * b->x; +} + +void +cogl_quaternion_pow (CoglQuaternion *quaternion, float exponent) +{ + float half_angle; + float new_half_angle; + float factor; + + /* Try and identify and nop identity quaternions to avoid + * dividing by zero */ + if (fabs (quaternion->w) > 0.9999f) + return; + + /* NB: We are using quaternions to represent an axis (a), angle (𝜃) pair + * in this form: + * [w=cos(𝜃/2) ( x=sin(𝜃/2)*a.x, y=sin(𝜃/2)*a.y, z=sin(𝜃/2)*a.x )] + */ + + /* FIXME: clamp [-1, 1] */ + /* Extract 𝜃/2 from w */ + half_angle = acosf (quaternion->w); + + /* Compute the new 𝜃/2 */ + new_half_angle = half_angle * exponent; + + /* Compute the new w value */ + quaternion->w = cosf (new_half_angle); + + /* And new xyz values */ + factor = sinf (new_half_angle) / sinf (half_angle); + quaternion->x *= factor; + quaternion->y *= factor; + quaternion->z *= factor; +} + +void +cogl_quaternion_slerp (CoglQuaternion *result, + const CoglQuaternion *a, + const CoglQuaternion *b, + float t) +{ + float cos_difference; + float qb_w; + float qb_x; + float qb_y; + float qb_z; + float fa; + float fb; + + _COGL_RETURN_IF_FAIL (t >=0 && t <= 1.0f); + + if (t == 0) + { + *result = *a; + return; + } + else if (t == 1) + { + *result = *b; + return; + } + + /* compute the cosine of the angle between the two given quaternions */ + cos_difference = cogl_quaternion_dot_product (a, b); + + /* If negative, use -b. Two quaternions q and -q represent the same angle but + * may produce a different slerp. We choose b or -b to rotate using the acute + * angle. + */ + if (cos_difference < 0.0f) + { + qb_w = -b->w; + qb_x = -b->x; + qb_y = -b->y; + qb_z = -b->z; + cos_difference = -cos_difference; + } + else + { + qb_w = b->w; + qb_x = b->x; + qb_y = b->y; + qb_z = b->z; + } + + /* If we have two unit quaternions the dot should be <= 1.0 */ + g_assert (cos_difference < 1.1f); + + + /* Determine the interpolation factors for each quaternion, simply using + * linear interpolation for quaternions that are nearly exactly the same. + * (this will avoid divisions by zero) + */ + + if (cos_difference > 0.9999f) + { + fa = 1.0f - t; + fb = t; + + /* XXX: should we also normalize() at the end in this case? */ + } + else + { + /* Calculate the sin of the angle between the two quaternions using the + * trig identity: sin²(𝜃) + cos²(𝜃) = 1 + */ + float sin_difference = sqrtf (1.0f - cos_difference * cos_difference); + + float difference = atan2f (sin_difference, cos_difference); + float one_over_sin_difference = 1.0f / sin_difference; + fa = sinf ((1.0f - t) * difference) * one_over_sin_difference; + fb = sinf (t * difference) * one_over_sin_difference; + } + + /* Finally interpolate the two quaternions */ + + result->x = fa * a->x + fb * qb_x; + result->y = fa * a->y + fb * qb_y; + result->z = fa * a->z + fb * qb_z; + result->w = fa * a->w + fb * qb_w; +} + +void +cogl_quaternion_nlerp (CoglQuaternion *result, + const CoglQuaternion *a, + const CoglQuaternion *b, + float t) +{ + float cos_difference; + float qb_w; + float qb_x; + float qb_y; + float qb_z; + float fa; + float fb; + + _COGL_RETURN_IF_FAIL (t >=0 && t <= 1.0f); + + if (t == 0) + { + *result = *a; + return; + } + else if (t == 1) + { + *result = *b; + return; + } + + /* compute the cosine of the angle between the two given quaternions */ + cos_difference = cogl_quaternion_dot_product (a, b); + + /* If negative, use -b. Two quaternions q and -q represent the same angle but + * may produce a different slerp. We choose b or -b to rotate using the acute + * angle. + */ + if (cos_difference < 0.0f) + { + qb_w = -b->w; + qb_x = -b->x; + qb_y = -b->y; + qb_z = -b->z; + cos_difference = -cos_difference; + } + else + { + qb_w = b->w; + qb_x = b->x; + qb_y = b->y; + qb_z = b->z; + } + + /* If we have two unit quaternions the dot should be <= 1.0 */ + g_assert (cos_difference < 1.1f); + + fa = 1.0f - t; + fb = t; + + result->x = fa * a->x + fb * qb_x; + result->y = fa * a->y + fb * qb_y; + result->z = fa * a->z + fb * qb_z; + result->w = fa * a->w + fb * qb_w; + + cogl_quaternion_normalize (result); +} + +void +cogl_quaternion_squad (CoglQuaternion *result, + const CoglQuaternion *prev, + const CoglQuaternion *a, + const CoglQuaternion *b, + const CoglQuaternion *next, + float t) +{ + CoglQuaternion slerp0; + CoglQuaternion slerp1; + + cogl_quaternion_slerp (&slerp0, a, b, t); + cogl_quaternion_slerp (&slerp1, prev, next, t); + cogl_quaternion_slerp (result, &slerp0, &slerp1, 2.0f * t * (1.0f - t)); +} + +const CoglQuaternion * +cogl_get_static_identity_quaternion (void) +{ + return &identity_quaternion; +} + +const CoglQuaternion * +cogl_get_static_zero_quaternion (void) +{ + return &zero_quaternion; +} + diff --git a/cogl/cogl/cogl-quaternion.h b/cogl/cogl/cogl-quaternion.h new file mode 100644 index 0000000..0660f7e --- /dev/null +++ b/cogl/cogl/cogl-quaternion.h @@ -0,0 +1,560 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Robert Bragg + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_QUATERNION_H__ +#define __COGL_QUATERNION_H__ + +#include +#include + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-quaternion + * @short_description: Functions for initializing and manipulating + * quaternions. + * + * Quaternions have become a standard form for representing 3D + * rotations and have some nice properties when compared with other + * representation such as (roll,pitch,yaw) Euler angles. They can be + * used to interpolate between different rotations and they don't + * suffer from a problem called + * "Gimbal lock" + * where two of the axis of rotation may become aligned and you loose a + * degree of freedom. + * . + */ +#include +#include + +#include + +/** + * CoglQuaternion: + * @w: based on the angle of rotation it is cos(𝜃/2) + * @x: based on the angle of rotation and x component of the axis of + * rotation it is sin(𝜃/2)*axis.x + * @y: based on the angle of rotation and y component of the axis of + * rotation it is sin(𝜃/2)*axis.y + * @z: based on the angle of rotation and z component of the axis of + * rotation it is sin(𝜃/2)*axis.z + * + * A quaternion is comprised of a scalar component and a 3D vector + * component. The scalar component is normally referred to as w and the + * vector might either be referred to as v or a (for axis) or expanded + * with the individual components: (x, y, z) A full quaternion would + * then be written as [w (x, y, z)]. + * + * Quaternions can be considered to represent an axis and angle + * pair although sadly these numbers are buried somewhat under some + * maths... + * + * For the curious you can see here that a given axis (a) and angle (𝜃) + * pair are represented in a quaternion as follows: + * |[ + * [w=cos(𝜃/2) ( x=sin(𝜃/2)*a.x, y=sin(𝜃/2)*a.y, z=sin(𝜃/2)*a.x )] + * ]| + * + * Unit Quaternions: + * When using Quaternions to represent spatial orientations for 3D + * graphics it's always assumed you have a unit quaternion. The + * magnitude of a quaternion is defined as: + * |[ + * sqrt (w² + x² + y² + z²) + * ]| + * and a unit quaternion satisfies this equation: + * |[ + * w² + x² + y² + z² = 1 + * ]| + * + * Thankfully most of the time we don't actually have to worry about + * the maths that goes on behind the scenes but if you are curious to + * learn more here are some external references: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * 3D Maths Primer for Graphics and Game Development ISBN-10: 1556229119 + * + * + * + * + * + * + * + * + * + */ +struct _CoglQuaternion +{ + /*< public >*/ + float w; + + float x; + float y; + float z; + + /*< private >*/ + float padding0; + float padding1; + float padding2; + float padding3; +}; +COGL_STRUCT_SIZE_ASSERT (CoglQuaternion, 32); + +/** + * cogl_quaternion_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_quaternion_get_gtype (void); + +/** + * cogl_quaternion_init: + * @quaternion: An uninitialized #CoglQuaternion + * @angle: The angle you want to rotate around the given axis + * @x: The x component of your axis vector about which you want to + * rotate. + * @y: The y component of your axis vector about which you want to + * rotate. + * @z: The z component of your axis vector about which you want to + * rotate. + * + * Initializes a quaternion that rotates @angle degrees around the + * axis vector (@x, @y, @z). The axis vector does not need to be + * normalized. + * + * Returns: A normalized, unit quaternion representing an orientation + * rotated @angle degrees around the axis vector (@x, @y, @z) + * + * Since: 2.0 + */ +void +cogl_quaternion_init (CoglQuaternion *quaternion, + float angle, + float x, + float y, + float z); + +/** + * cogl_quaternion_init_from_angle_vector: + * @quaternion: An uninitialized #CoglQuaternion + * @angle: The angle to rotate around @axis3f + * @axis3f: your 3 component axis vector about which you want to rotate. + * + * Initializes a quaternion that rotates @angle degrees around the + * given @axis vector. The axis vector does not need to be + * normalized. + * + * Returns: A normalized, unit quaternion representing an orientation + * rotated @angle degrees around the given @axis vector. + * + * Since: 2.0 + */ +void +cogl_quaternion_init_from_angle_vector (CoglQuaternion *quaternion, + float angle, + const float *axis3f); + +/** + * cogl_quaternion_init_identity: + * @quaternion: An uninitialized #CoglQuaternion + * + * Initializes the quaternion with the canonical quaternion identity + * [1 (0, 0, 0)] which represents no rotation. Multiplying a + * quaternion with this identity leaves the quaternion unchanged. + * + * You might also want to consider using + * cogl_get_static_identity_quaternion(). + * + * Since: 2.0 + */ +void +cogl_quaternion_init_identity (CoglQuaternion *quaternion); + +/** + * cogl_quaternion_init_from_array: + * @quaternion: A #CoglQuaternion + * @array: An array of 4 floats w,(x,y,z) + * + * Initializes a [w (x, y,z)] quaternion directly from an array of 4 + * floats: [w,x,y,z]. + * + * Since: 2.0 + */ +void +cogl_quaternion_init_from_array (CoglQuaternion *quaternion, + const float *array); + +/** + * cogl_quaternion_init_from_x_rotation: + * @quaternion: An uninitialized #CoglQuaternion + * @angle: The angle to rotate around the x axis + * + * XXX: check which direction this rotates + * + * Since: 2.0 + */ +void +cogl_quaternion_init_from_x_rotation (CoglQuaternion *quaternion, + float angle); + +/** + * cogl_quaternion_init_from_y_rotation: + * @quaternion: An uninitialized #CoglQuaternion + * @angle: The angle to rotate around the y axis + * + * + * Since: 2.0 + */ +void +cogl_quaternion_init_from_y_rotation (CoglQuaternion *quaternion, + float angle); + +/** + * cogl_quaternion_init_from_z_rotation: + * @quaternion: An uninitialized #CoglQuaternion + * @angle: The angle to rotate around the z axis + * + * + * Since: 2.0 + */ +void +cogl_quaternion_init_from_z_rotation (CoglQuaternion *quaternion, + float angle); + +/** + * cogl_quaternion_init_from_euler: + * @quaternion: A #CoglQuaternion + * @euler: A #CoglEuler with which to initialize the quaternion + * + * Since: 2.0 + */ +void +cogl_quaternion_init_from_euler (CoglQuaternion *quaternion, + const CoglEuler *euler); + +/** + * cogl_quaternion_init_from_quaternion: + * @quaternion: A #CoglQuaternion + * @src: A #CoglQuaternion with which to initialize @quaternion + * + * Since: 2.0 + */ +void +cogl_quaternion_init_from_quaternion (CoglQuaternion *quaternion, + CoglQuaternion *src); + +/** + * cogl_quaternion_init_from_matrix: + * @quaternion: A Cogl Quaternion + * @matrix: A rotation matrix with which to initialize the quaternion + * + * Initializes a quaternion from a rotation matrix. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_quaternion_init_from_matrix (CoglQuaternion *quaternion, + const CoglMatrix *matrix); + +/** + * cogl_quaternion_equal: + * @v1: A #CoglQuaternion + * @v2: A #CoglQuaternion + * + * Compares that all the components of quaternions @a and @b are + * equal. + * + * An epsilon value is not used to compare the float components, but + * the == operator is at least used so that 0 and -0 are considered + * equal. + * + * Returns: %TRUE if the quaternions are equal else %FALSE. + * + * Since: 2.0 + */ +CoglBool +cogl_quaternion_equal (const void *v1, const void *v2); + +/** + * cogl_quaternion_copy: + * @src: A #CoglQuaternion + * + * Allocates a new #CoglQuaternion on the stack and initializes it with + * the same values as @src. + * + * Returns: A newly allocated #CoglQuaternion which should be freed + * using cogl_quaternion_free() + * + * Since: 2.0 + */ +CoglQuaternion * +cogl_quaternion_copy (const CoglQuaternion *src); + +/** + * cogl_quaternion_free: + * @quaternion: A #CoglQuaternion + * + * Frees a #CoglQuaternion that was previously allocated via + * cogl_quaternion_copy(). + * + * Since: 2.0 + */ +void +cogl_quaternion_free (CoglQuaternion *quaternion); + +/** + * cogl_quaternion_get_rotation_angle: + * @quaternion: A #CoglQuaternion + * + * + * Since: 2.0 + */ +float +cogl_quaternion_get_rotation_angle (const CoglQuaternion *quaternion); + +/** + * cogl_quaternion_get_rotation_axis: + * @quaternion: A #CoglQuaternion + * @vector3: (out): an allocated 3-float array + * + * Since: 2.0 + */ +void +cogl_quaternion_get_rotation_axis (const CoglQuaternion *quaternion, + float *vector3); + +/** + * cogl_quaternion_normalize: + * @quaternion: A #CoglQuaternion + * + * + * Since: 2.0 + */ +void +cogl_quaternion_normalize (CoglQuaternion *quaternion); + +/** + * cogl_quaternion_dot_product: + * @a: A #CoglQuaternion + * @b: A #CoglQuaternion + * + * Since: 2.0 + */ +float +cogl_quaternion_dot_product (const CoglQuaternion *a, + const CoglQuaternion *b); + +/** + * cogl_quaternion_invert: + * @quaternion: A #CoglQuaternion + * + * + * Since: 2.0 + */ +void +cogl_quaternion_invert (CoglQuaternion *quaternion); + +/** + * cogl_quaternion_multiply: + * @result: The destination #CoglQuaternion + * @left: The second #CoglQuaternion rotation to apply + * @right: The first #CoglQuaternion rotation to apply + * + * This combines the rotations of two quaternions into @result. The + * operation is not commutative so the order is important because AxB + * != BxA. Cogl follows the standard convention for quaternions here + * so the rotations are applied @right to @left. This is similar to the + * combining of matrices. + * + * It is possible to multiply the @a quaternion in-place, so + * @result can be equal to @a but can't be equal to @b. + * + * Since: 2.0 + */ +void +cogl_quaternion_multiply (CoglQuaternion *result, + const CoglQuaternion *left, + const CoglQuaternion *right); + +/** + * cogl_quaternion_pow: + * @quaternion: A #CoglQuaternion + * @exponent: the exponent + * + * + * Since: 2.0 + */ +void +cogl_quaternion_pow (CoglQuaternion *quaternion, float exponent); + +/** + * cogl_quaternion_slerp: + * @result: The destination #CoglQuaternion + * @a: The first #CoglQuaternion + * @b: The second #CoglQuaternion + * @t: The factor in the range [0,1] used to interpolate between + * quaternion @a and @b. + * + * Performs a spherical linear interpolation between two quaternions. + * + * Noteable properties: + * + * + * commutative: No + * + * + * constant velocity: Yes + * + * + * torque minimal (travels along the surface of the 4-sphere): Yes + * + * + * more expensive than cogl_quaternion_nlerp() + * + * + */ +void +cogl_quaternion_slerp (CoglQuaternion *result, + const CoglQuaternion *a, + const CoglQuaternion *b, + float t); + +/** + * cogl_quaternion_nlerp: + * @result: The destination #CoglQuaternion + * @a: The first #CoglQuaternion + * @b: The second #CoglQuaternion + * @t: The factor in the range [0,1] used to interpolate between + * quaterion @a and @b. + * + * Performs a normalized linear interpolation between two quaternions. + * That is it does a linear interpolation of the quaternion components + * and then normalizes the result. This will follow the shortest arc + * between the two orientations (just like the slerp() function) but + * will not progress at a constant speed. Unlike slerp() nlerp is + * commutative which is useful if you are blending animations + * together. (I.e. nlerp (tmp, a, b) followed by nlerp (result, tmp, + * d) is the same as nlerp (tmp, a, d) followed by nlerp (result, tmp, + * b)). Finally nlerp is cheaper than slerp so it can be a good choice + * if you don't need the constant speed property of the slerp() function. + * + * Notable properties: + * + * + * commutative: Yes + * + * + * constant velocity: No + * + * + * torque minimal (travels along the surface of the 4-sphere): Yes + * + * + * faster than cogl_quaternion_slerp() + * + * + */ +void +cogl_quaternion_nlerp (CoglQuaternion *result, + const CoglQuaternion *a, + const CoglQuaternion *b, + float t); +/** + * cogl_quaternion_squad: + * @result: The destination #CoglQuaternion + * @prev: A #CoglQuaternion used before @a + * @a: The first #CoglQuaternion + * @b: The second #CoglQuaternion + * @next: A #CoglQuaternion that will be used after @b + * @t: The factor in the range [0,1] used to interpolate between + * quaternion @a and @b. + * + * + * Since: 2.0 + */ +void +cogl_quaternion_squad (CoglQuaternion *result, + const CoglQuaternion *prev, + const CoglQuaternion *a, + const CoglQuaternion *b, + const CoglQuaternion *next, + float t); + +/** + * cogl_get_static_identity_quaternion: + * + * Returns a pointer to a singleton quaternion constant describing the + * canonical identity [1 (0, 0, 0)] which represents no rotation. + * + * If you multiply a quaternion with the identity quaternion you will + * get back the same value as the original quaternion. + * + * Returns: A pointer to an identity quaternion + * + * Since: 2.0 + */ +const CoglQuaternion * +cogl_get_static_identity_quaternion (void); + +/** + * cogl_get_static_zero_quaternion: + * + * Returns: a pointer to a singleton quaternion constant describing a + * rotation of 180 degrees around a degenerate axis: + * [0 (0, 0, 0)] + * + * Since: 2.0 + */ +const CoglQuaternion * +cogl_get_static_zero_quaternion (void); + +COGL_END_DECLS + +#endif /* __COGL_QUATERNION_H__ */ + diff --git a/cogl/cogl/cogl-rectangle-map.c b/cogl/cogl/cogl-rectangle-map.c new file mode 100644 index 0000000..ef6b421 --- /dev/null +++ b/cogl/cogl/cogl-rectangle-map.c @@ -0,0 +1,764 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Neil Roberts + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include + +#include "cogl-util.h" +#include "cogl-rectangle-map.h" +#include "cogl-debug.h" + +/* Implements a data structure which keeps track of unused + sub-rectangles within a larger rectangle using a binary tree + structure. The algorithm for this is based on the description here: + + http://www.blackpawn.com/texts/lightmaps/default.html +*/ + +#if defined (COGL_ENABLE_DEBUG) && defined (HAVE_CAIRO) + +/* The cairo header is only used for debugging to generate an image of + the atlas */ +#include + +static void _cogl_rectangle_map_dump_image (CoglRectangleMap *map); + +#endif /* COGL_ENABLE_DEBUG && HAVE_CAIRO */ + +typedef struct _CoglRectangleMapNode CoglRectangleMapNode; +typedef struct _CoglRectangleMapStackEntry CoglRectangleMapStackEntry; + +typedef void (* CoglRectangleMapInternalForeachCb) (CoglRectangleMapNode *node, + void *data); + +typedef enum +{ + COGL_RECTANGLE_MAP_BRANCH, + COGL_RECTANGLE_MAP_FILLED_LEAF, + COGL_RECTANGLE_MAP_EMPTY_LEAF +} CoglRectangleMapNodeType; + +struct _CoglRectangleMap +{ + CoglRectangleMapNode *root; + + unsigned int n_rectangles; + + unsigned int space_remaining; + + GDestroyNotify value_destroy_func; + + /* Stack used for walking the structure. This is only used during + the lifetime of a single function call but it is kept here as an + optimisation to avoid reallocating it every time it is needed */ + GArray *stack; +}; + +struct _CoglRectangleMapNode +{ + CoglRectangleMapNodeType type; + + CoglRectangleMapEntry rectangle; + + unsigned int largest_gap; + + CoglRectangleMapNode *parent; + + union + { + /* Fields used when this is a branch */ + struct + { + CoglRectangleMapNode *left; + CoglRectangleMapNode *right; + } branch; + + /* Field used when this is a filled leaf */ + void *data; + } d; +}; + +struct _CoglRectangleMapStackEntry +{ + /* The node to search */ + CoglRectangleMapNode *node; + /* Index of next branch of this node to explore. Basically either 0 + to go left or 1 to go right */ + CoglBool next_index; +}; + +static CoglRectangleMapNode * +_cogl_rectangle_map_node_new (void) +{ + return g_slice_new (CoglRectangleMapNode); +} + +static void +_cogl_rectangle_map_node_free (CoglRectangleMapNode *node) +{ + g_slice_free (CoglRectangleMapNode, node); +} + +CoglRectangleMap * +_cogl_rectangle_map_new (unsigned int width, + unsigned int height, + GDestroyNotify value_destroy_func) +{ + CoglRectangleMap *map = g_new (CoglRectangleMap, 1); + CoglRectangleMapNode *root = _cogl_rectangle_map_node_new (); + + root->type = COGL_RECTANGLE_MAP_EMPTY_LEAF; + root->parent = NULL; + root->rectangle.x = 0; + root->rectangle.y = 0; + root->rectangle.width = width; + root->rectangle.height = height; + root->largest_gap = width * height; + + map->root = root; + map->n_rectangles = 0; + map->value_destroy_func = value_destroy_func; + map->space_remaining = width * height; + + map->stack = g_array_new (FALSE, FALSE, sizeof (CoglRectangleMapStackEntry)); + + return map; +} + +static void +_cogl_rectangle_map_stack_push (GArray *stack, + CoglRectangleMapNode *node, + CoglBool next_index) +{ + CoglRectangleMapStackEntry *new_entry; + + g_array_set_size (stack, stack->len + 1); + + new_entry = &g_array_index (stack, CoglRectangleMapStackEntry, + stack->len - 1); + + new_entry->node = node; + new_entry->next_index = next_index; +} + +static void +_cogl_rectangle_map_stack_pop (GArray *stack) +{ + g_array_set_size (stack, stack->len - 1); +} + +static CoglRectangleMapStackEntry * +_cogl_rectangle_map_stack_get_top (GArray *stack) +{ + return &g_array_index (stack, CoglRectangleMapStackEntry, + stack->len - 1); +} + +static CoglRectangleMapNode * +_cogl_rectangle_map_node_split_horizontally (CoglRectangleMapNode *node, + unsigned int left_width) +{ + /* Splits the node horizontally (according to emacs' definition, not + vim) by converting it to a branch and adding two new leaf + nodes. The leftmost branch will have the width left_width and + will be returned. If the node is already just the right size it + won't do anything */ + + CoglRectangleMapNode *left_node, *right_node; + + if (node->rectangle.width == left_width) + return node; + + left_node = _cogl_rectangle_map_node_new (); + left_node->type = COGL_RECTANGLE_MAP_EMPTY_LEAF; + left_node->parent = node; + left_node->rectangle.x = node->rectangle.x; + left_node->rectangle.y = node->rectangle.y; + left_node->rectangle.width = left_width; + left_node->rectangle.height = node->rectangle.height; + left_node->largest_gap = (left_node->rectangle.width * + left_node->rectangle.height); + node->d.branch.left = left_node; + + right_node = _cogl_rectangle_map_node_new (); + right_node->type = COGL_RECTANGLE_MAP_EMPTY_LEAF; + right_node->parent = node; + right_node->rectangle.x = node->rectangle.x + left_width; + right_node->rectangle.y = node->rectangle.y; + right_node->rectangle.width = node->rectangle.width - left_width; + right_node->rectangle.height = node->rectangle.height; + right_node->largest_gap = (right_node->rectangle.width * + right_node->rectangle.height); + node->d.branch.right = right_node; + + node->type = COGL_RECTANGLE_MAP_BRANCH; + + return left_node; +} + +static CoglRectangleMapNode * +_cogl_rectangle_map_node_split_vertically (CoglRectangleMapNode *node, + unsigned int top_height) +{ + /* Splits the node vertically (according to emacs' definition, not + vim) by converting it to a branch and adding two new leaf + nodes. The topmost branch will have the height top_height and + will be returned. If the node is already just the right size it + won't do anything */ + + CoglRectangleMapNode *top_node, *bottom_node; + + if (node->rectangle.height == top_height) + return node; + + top_node = _cogl_rectangle_map_node_new (); + top_node->type = COGL_RECTANGLE_MAP_EMPTY_LEAF; + top_node->parent = node; + top_node->rectangle.x = node->rectangle.x; + top_node->rectangle.y = node->rectangle.y; + top_node->rectangle.width = node->rectangle.width; + top_node->rectangle.height = top_height; + top_node->largest_gap = (top_node->rectangle.width * + top_node->rectangle.height); + node->d.branch.left = top_node; + + bottom_node = _cogl_rectangle_map_node_new (); + bottom_node->type = COGL_RECTANGLE_MAP_EMPTY_LEAF; + bottom_node->parent = node; + bottom_node->rectangle.x = node->rectangle.x; + bottom_node->rectangle.y = node->rectangle.y + top_height; + bottom_node->rectangle.width = node->rectangle.width; + bottom_node->rectangle.height = node->rectangle.height - top_height; + bottom_node->largest_gap = (bottom_node->rectangle.width * + bottom_node->rectangle.height); + node->d.branch.right = bottom_node; + + node->type = COGL_RECTANGLE_MAP_BRANCH; + + return top_node; +} + +#ifdef COGL_ENABLE_DEBUG + +static unsigned int +_cogl_rectangle_map_verify_recursive (CoglRectangleMapNode *node) +{ + /* This is just used for debugging the data structure. It + recursively walks the tree to verify that the largest gap values + all add up */ + + switch (node->type) + { + case COGL_RECTANGLE_MAP_BRANCH: + { + int sum = + _cogl_rectangle_map_verify_recursive (node->d.branch.left) + + _cogl_rectangle_map_verify_recursive (node->d.branch.right); + g_assert (node->largest_gap == + MAX (node->d.branch.left->largest_gap, + node->d.branch.right->largest_gap)); + return sum; + } + + case COGL_RECTANGLE_MAP_EMPTY_LEAF: + g_assert (node->largest_gap == + node->rectangle.width * node->rectangle.height); + return 0; + + case COGL_RECTANGLE_MAP_FILLED_LEAF: + g_assert (node->largest_gap == 0); + return 1; + } + + return 0; +} + +static unsigned int +_cogl_rectangle_map_get_space_remaining_recursive (CoglRectangleMapNode *node) +{ + /* This is just used for debugging the data structure. It + recursively walks the tree to verify that the remaining space + value adds up */ + + switch (node->type) + { + case COGL_RECTANGLE_MAP_BRANCH: + { + CoglRectangleMapNode *l = node->d.branch.left; + CoglRectangleMapNode *r = node->d.branch.right; + + return (_cogl_rectangle_map_get_space_remaining_recursive (l) + + _cogl_rectangle_map_get_space_remaining_recursive (r)); + } + + case COGL_RECTANGLE_MAP_EMPTY_LEAF: + return node->rectangle.width * node->rectangle.height; + + case COGL_RECTANGLE_MAP_FILLED_LEAF: + return 0; + } + + return 0; +} + +static void +_cogl_rectangle_map_verify (CoglRectangleMap *map) +{ + unsigned int actual_n_rectangles = + _cogl_rectangle_map_verify_recursive (map->root); + unsigned int actual_space_remaining = + _cogl_rectangle_map_get_space_remaining_recursive (map->root); + + g_assert_cmpuint (actual_n_rectangles, ==, map->n_rectangles); + g_assert_cmpuint (actual_space_remaining, ==, map->space_remaining); +} + +#endif /* COGL_ENABLE_DEBUG */ + +CoglBool +_cogl_rectangle_map_add (CoglRectangleMap *map, + unsigned int width, + unsigned int height, + void *data, + CoglRectangleMapEntry *rectangle) +{ + unsigned int rectangle_size = width * height; + /* Stack of nodes to search in */ + GArray *stack = map->stack; + CoglRectangleMapNode *found_node = NULL; + + /* Zero-sized rectangles break the algorithm for removing rectangles + so we'll disallow them */ + _COGL_RETURN_VAL_IF_FAIL (width > 0 && height > 0, FALSE); + + /* Start with the root node */ + g_array_set_size (stack, 0); + _cogl_rectangle_map_stack_push (stack, map->root, FALSE); + + /* Depth-first search for an empty node that is big enough */ + while (stack->len > 0) + { + CoglRectangleMapStackEntry *stack_top; + CoglRectangleMapNode *node; + int next_index; + + /* Pop an entry off the stack */ + stack_top = _cogl_rectangle_map_stack_get_top (stack); + node = stack_top->node; + next_index = stack_top->next_index; + _cogl_rectangle_map_stack_pop (stack); + + /* Regardless of the type of the node, there's no point + descending any further if the new rectangle won't fit within + it */ + if (node->rectangle.width >= width && + node->rectangle.height >= height && + node->largest_gap >= rectangle_size) + { + if (node->type == COGL_RECTANGLE_MAP_EMPTY_LEAF) + { + /* We've found a node we can use */ + found_node = node; + break; + } + else if (node->type == COGL_RECTANGLE_MAP_BRANCH) + { + if (next_index) + /* Try the right branch */ + _cogl_rectangle_map_stack_push (stack, + node->d.branch.right, + 0); + else + { + /* Make sure we remember to try the right branch once + we've finished descending the left branch */ + _cogl_rectangle_map_stack_push (stack, + node, + 1); + /* Try the left branch */ + _cogl_rectangle_map_stack_push (stack, + node->d.branch.left, + 0); + } + } + } + } + + if (found_node) + { + CoglRectangleMapNode *node; + + /* Split according to whichever axis will leave us with the + largest space */ + if (found_node->rectangle.width - width > + found_node->rectangle.height - height) + { + found_node = + _cogl_rectangle_map_node_split_horizontally (found_node, width); + found_node = + _cogl_rectangle_map_node_split_vertically (found_node, height); + } + else + { + found_node = + _cogl_rectangle_map_node_split_vertically (found_node, height); + found_node = + _cogl_rectangle_map_node_split_horizontally (found_node, width); + } + + found_node->type = COGL_RECTANGLE_MAP_FILLED_LEAF; + found_node->d.data = data; + found_node->largest_gap = 0; + if (rectangle) + *rectangle = found_node->rectangle; + + /* Walk back up the tree and update the stored largest gap for + the node's sub tree */ + for (node = found_node->parent; node; node = node->parent) + { + /* This node is a parent so it should always be a branch */ + g_assert (node->type == COGL_RECTANGLE_MAP_BRANCH); + + node->largest_gap = MAX (node->d.branch.left->largest_gap, + node->d.branch.right->largest_gap); + } + + /* There is now an extra rectangle in the map */ + map->n_rectangles++; + /* and less space */ + map->space_remaining -= rectangle_size; + +#ifdef COGL_ENABLE_DEBUG + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DUMP_ATLAS_IMAGE))) + { +#ifdef HAVE_CAIRO + _cogl_rectangle_map_dump_image (map); +#endif + /* Dumping the rectangle map is really slow so we might as well + verify the space remaining here as it is also quite slow */ + _cogl_rectangle_map_verify (map); + } +#endif + + return TRUE; + } + else + return FALSE; +} + +void +_cogl_rectangle_map_remove (CoglRectangleMap *map, + const CoglRectangleMapEntry *rectangle) +{ + CoglRectangleMapNode *node = map->root; + unsigned int rectangle_size = rectangle->width * rectangle->height; + + /* We can do a binary-chop down the search tree to find the rectangle */ + while (node->type == COGL_RECTANGLE_MAP_BRANCH) + { + CoglRectangleMapNode *left_node = node->d.branch.left; + + /* If and only if the rectangle is in the left node then the x,y + position of the rectangle will be within the node's + rectangle */ + if (rectangle->x < left_node->rectangle.x + left_node->rectangle.width && + rectangle->y < left_node->rectangle.y + left_node->rectangle.height) + /* Go left */ + node = left_node; + else + /* Go right */ + node = node->d.branch.right; + } + + /* Make sure we found the right node */ + if (node->type != COGL_RECTANGLE_MAP_FILLED_LEAF || + node->rectangle.x != rectangle->x || + node->rectangle.y != rectangle->y || + node->rectangle.width != rectangle->width || + node->rectangle.height != rectangle->height) + /* This should only happen if someone tried to remove a rectangle + that was not in the map so something has gone wrong */ + g_return_if_reached (); + else + { + /* Convert the node back to an empty node */ + if (map->value_destroy_func) + map->value_destroy_func (node->d.data); + node->type = COGL_RECTANGLE_MAP_EMPTY_LEAF; + node->largest_gap = rectangle_size; + + /* Walk back up the tree combining branch nodes that have two + empty leaves back into a single empty leaf */ + for (node = node->parent; node; node = node->parent) + { + /* This node is a parent so it should always be a branch */ + g_assert (node->type == COGL_RECTANGLE_MAP_BRANCH); + + if (node->d.branch.left->type == COGL_RECTANGLE_MAP_EMPTY_LEAF && + node->d.branch.right->type == COGL_RECTANGLE_MAP_EMPTY_LEAF) + { + _cogl_rectangle_map_node_free (node->d.branch.left); + _cogl_rectangle_map_node_free (node->d.branch.right); + node->type = COGL_RECTANGLE_MAP_EMPTY_LEAF; + + node->largest_gap = (node->rectangle.width * + node->rectangle.height); + } + else + break; + } + + /* Reduce the amount of space remaining in all of the parents + further up the chain */ + for (; node; node = node->parent) + node->largest_gap = MAX (node->d.branch.left->largest_gap, + node->d.branch.right->largest_gap); + + /* There is now one less rectangle */ + g_assert (map->n_rectangles > 0); + map->n_rectangles--; + /* and more space */ + map->space_remaining += rectangle_size; + } + +#ifdef COGL_ENABLE_DEBUG + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DUMP_ATLAS_IMAGE))) + { +#ifdef HAVE_CAIRO + _cogl_rectangle_map_dump_image (map); +#endif + /* Dumping the rectangle map is really slow so we might as well + verify the space remaining here as it is also quite slow */ + _cogl_rectangle_map_verify (map); + } +#endif +} + +unsigned int +_cogl_rectangle_map_get_width (CoglRectangleMap *map) +{ + return map->root->rectangle.width; +} + +unsigned int +_cogl_rectangle_map_get_height (CoglRectangleMap *map) +{ + return map->root->rectangle.height; +} + +unsigned int +_cogl_rectangle_map_get_remaining_space (CoglRectangleMap *map) +{ + return map->space_remaining; +} + +unsigned int +_cogl_rectangle_map_get_n_rectangles (CoglRectangleMap *map) +{ + return map->n_rectangles; +} + +static void +_cogl_rectangle_map_internal_foreach (CoglRectangleMap *map, + CoglRectangleMapInternalForeachCb func, + void *data) +{ + /* Stack of nodes to search in */ + GArray *stack = map->stack; + + /* Start with the root node */ + g_array_set_size (stack, 0); + _cogl_rectangle_map_stack_push (stack, map->root, 0); + + /* Iterate all nodes depth-first */ + while (stack->len > 0) + { + CoglRectangleMapStackEntry *stack_top = + _cogl_rectangle_map_stack_get_top (stack); + CoglRectangleMapNode *node = stack_top->node; + + switch (node->type) + { + case COGL_RECTANGLE_MAP_BRANCH: + if (stack_top->next_index == 0) + { + /* Next time we come back to this node, go to the right */ + stack_top->next_index = 1; + + /* Explore the left branch next */ + _cogl_rectangle_map_stack_push (stack, + node->d.branch.left, + 0); + } + else if (stack_top->next_index == 1) + { + /* Next time we come back to this node, stop processing it */ + stack_top->next_index = 2; + + /* Explore the right branch next */ + _cogl_rectangle_map_stack_push (stack, + node->d.branch.right, + 0); + } + else + { + /* We're finished with this node so we can call the callback */ + func (node, data); + _cogl_rectangle_map_stack_pop (stack); + } + break; + + default: + /* Some sort of leaf node, just call the callback */ + func (node, data); + _cogl_rectangle_map_stack_pop (stack); + break; + } + } + + /* The stack should now be empty */ + g_assert (stack->len == 0); +} + +typedef struct _CoglRectangleMapForeachClosure +{ + CoglRectangleMapCallback callback; + void *data; +} CoglRectangleMapForeachClosure; + +static void +_cogl_rectangle_map_foreach_cb (CoglRectangleMapNode *node, void *data) +{ + CoglRectangleMapForeachClosure *closure = data; + + if (node->type == COGL_RECTANGLE_MAP_FILLED_LEAF) + closure->callback (&node->rectangle, node->d.data, closure->data); +} + +void +_cogl_rectangle_map_foreach (CoglRectangleMap *map, + CoglRectangleMapCallback callback, + void *data) +{ + CoglRectangleMapForeachClosure closure; + + closure.callback = callback; + closure.data = data; + + _cogl_rectangle_map_internal_foreach (map, + _cogl_rectangle_map_foreach_cb, + &closure); +} + +static void +_cogl_rectangle_map_free_cb (CoglRectangleMapNode *node, void *data) +{ + CoglRectangleMap *map = data; + + if (node->type == COGL_RECTANGLE_MAP_FILLED_LEAF && map->value_destroy_func) + map->value_destroy_func (node->d.data); + + _cogl_rectangle_map_node_free (node); +} + +void +_cogl_rectangle_map_free (CoglRectangleMap *map) +{ + _cogl_rectangle_map_internal_foreach (map, + _cogl_rectangle_map_free_cb, + map); + + g_array_free (map->stack, TRUE); + + g_free (map); +} + +#if defined (COGL_ENABLE_DEBUG) && defined (HAVE_CAIRO) + +static void +_cogl_rectangle_map_dump_image_cb (CoglRectangleMapNode *node, void *data) +{ + cairo_t *cr = data; + + if (node->type == COGL_RECTANGLE_MAP_FILLED_LEAF || + node->type == COGL_RECTANGLE_MAP_EMPTY_LEAF) + { + /* Fill the rectangle using a different colour depending on + whether the rectangle is used */ + if (node->type == COGL_RECTANGLE_MAP_FILLED_LEAF) + cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); + else + cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); + + cairo_rectangle (cr, + node->rectangle.x, + node->rectangle.y, + node->rectangle.width, + node->rectangle.height); + + cairo_fill_preserve (cr); + + /* Draw a white outline around the rectangle */ + cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); + cairo_stroke (cr); + } +} + +static void +_cogl_rectangle_map_dump_image (CoglRectangleMap *map) +{ + /* This dumps a png to help visualize the map. Each leaf rectangle + is drawn with a white outline. Unused leaves are filled in black + and used leaves are blue */ + + cairo_surface_t *surface = + cairo_image_surface_create (CAIRO_FORMAT_RGB24, + _cogl_rectangle_map_get_width (map), + _cogl_rectangle_map_get_height (map)); + cairo_t *cr = cairo_create (surface); + + _cogl_rectangle_map_internal_foreach (map, + _cogl_rectangle_map_dump_image_cb, + cr); + + cairo_destroy (cr); + + cairo_surface_write_to_png (surface, "cogl-rectangle-map-dump.png"); + + cairo_surface_destroy (surface); +} + +#endif /* COGL_ENABLE_DEBUG && HAVE_CAIRO */ diff --git a/cogl/cogl/cogl-rectangle-map.h b/cogl/cogl/cogl-rectangle-map.h new file mode 100644 index 0000000..1dd50fd --- /dev/null +++ b/cogl/cogl/cogl-rectangle-map.h @@ -0,0 +1,84 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __COGL_RECTANGLE_MAP_H +#define __COGL_RECTANGLE_MAP_H + +#include +#include "cogl-types.h" + +typedef struct _CoglRectangleMap CoglRectangleMap; +typedef struct _CoglRectangleMapEntry CoglRectangleMapEntry; + +typedef void (* CoglRectangleMapCallback) (const CoglRectangleMapEntry *entry, + void *rectangle_data, + void *user_data); + +struct _CoglRectangleMapEntry +{ + unsigned int x, y; + unsigned int width, height; +}; + +CoglRectangleMap * +_cogl_rectangle_map_new (unsigned int width, + unsigned int height, + GDestroyNotify value_destroy_func); + +CoglBool +_cogl_rectangle_map_add (CoglRectangleMap *map, + unsigned int width, + unsigned int height, + void *data, + CoglRectangleMapEntry *rectangle); + +void +_cogl_rectangle_map_remove (CoglRectangleMap *map, + const CoglRectangleMapEntry *rectangle); + +unsigned int +_cogl_rectangle_map_get_width (CoglRectangleMap *map); + +unsigned int +_cogl_rectangle_map_get_height (CoglRectangleMap *map); + +unsigned int +_cogl_rectangle_map_get_remaining_space (CoglRectangleMap *map); + +unsigned int +_cogl_rectangle_map_get_n_rectangles (CoglRectangleMap *map); + +void +_cogl_rectangle_map_foreach (CoglRectangleMap *map, + CoglRectangleMapCallback callback, + void *data); + +void +_cogl_rectangle_map_free (CoglRectangleMap *map); + +#endif /* __COGL_RECTANGLE_MAP_H */ diff --git a/cogl/cogl/cogl-renderer-private.h b/cogl/cogl/cogl-renderer-private.h new file mode 100644 index 0000000..8627b6c --- /dev/null +++ b/cogl/cogl/cogl-renderer-private.h @@ -0,0 +1,111 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_RENDERER_PRIVATE_H +#define __COGL_RENDERER_PRIVATE_H + +#include + +#include "cogl-object-private.h" +#include "cogl-winsys-private.h" +#include "cogl-driver.h" +#include "cogl-texture-driver.h" +#include "cogl-context.h" +#include "cogl-closure-list-private.h" +#include "cogl-mutter.h" + +#ifdef COGL_HAS_XLIB_SUPPORT +#include +#endif + +struct _CoglRenderer +{ + CoglObject _parent; + CoglBool connected; + CoglDriver driver_override; + const CoglDriverVtable *driver_vtable; + const CoglTextureDriver *texture_driver; + const CoglWinsysVtable *winsys_vtable; + CoglWinsysVtableGetter custom_winsys_vtable_getter; + CoglWinsysID winsys_id_override; + GList *constraints; + + GArray *poll_fds; + int poll_fds_age; + GList *poll_sources; + + CoglList idle_closures; + + GList *outputs; + +#ifdef COGL_HAS_XLIB_SUPPORT + Display *foreign_xdpy; + CoglBool xlib_enable_event_retrieval; + CoglBool xlib_want_reset_on_video_memory_purge; +#endif + + CoglDriver driver; + unsigned long private_features + [COGL_FLAGS_N_LONGS_FOR_SIZE (COGL_N_PRIVATE_FEATURES)]; + GModule *libgl_module; + + /* List of callback functions that will be given every native event */ + GSList *event_filters; + void *winsys; +}; + +/* Mask of constraints that effect driver selection. All of the other + * constraints effect only the winsys selection */ +#define COGL_RENDERER_DRIVER_CONSTRAINTS \ + COGL_RENDERER_CONSTRAINT_SUPPORTS_COGL_GLES2 + +typedef CoglFilterReturn (* CoglNativeFilterFunc) (void *native_event, + void *data); + +CoglFilterReturn +_cogl_renderer_handle_native_event (CoglRenderer *renderer, + void *event); + +void +_cogl_renderer_add_native_filter (CoglRenderer *renderer, + CoglNativeFilterFunc func, + void *data); + +void +_cogl_renderer_remove_native_filter (CoglRenderer *renderer, + CoglNativeFilterFunc func, + void *data); + +void * +_cogl_renderer_get_proc_address (CoglRenderer *renderer, + const char *name, + CoglBool in_core); + +#endif /* __COGL_RENDERER_PRIVATE_H */ diff --git a/cogl/cogl/cogl-renderer.c b/cogl/cogl/cogl-renderer.c new file mode 100644 index 0000000..51a04ff --- /dev/null +++ b/cogl/cogl/cogl-renderer.c @@ -0,0 +1,846 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include +#include + +#include "cogl-util.h" +#include "cogl-private.h" +#include "cogl-object.h" +#include "cogl-context-private.h" +#include "cogl-util-gl-private.h" +#include "cogl-mutter.h" + +#include "cogl-renderer.h" +#include "cogl-renderer-private.h" +#include "cogl-display-private.h" +#include "cogl-winsys-private.h" +#include "cogl-winsys-stub-private.h" +#include "cogl-config-private.h" +#include "cogl-error-private.h" +#include "cogl-gtype-private.h" + +#ifdef COGL_HAS_EGL_PLATFORM_XLIB_SUPPORT +#include "cogl-winsys-egl-x11-private.h" +#endif +#ifdef COGL_HAS_GLX_SUPPORT +#include "cogl-winsys-glx-private.h" +#endif + +#ifdef COGL_HAS_XLIB_SUPPORT +#include "cogl-xlib-renderer.h" +#endif + +#ifdef HAVE_COGL_GL +extern const CoglTextureDriver _cogl_texture_driver_gl; +extern const CoglDriverVtable _cogl_driver_gl; +#endif +#if defined (HAVE_COGL_GLES) || defined (HAVE_COGL_GLES2) +extern const CoglTextureDriver _cogl_texture_driver_gles; +extern const CoglDriverVtable _cogl_driver_gles; +#endif + +extern const CoglDriverVtable _cogl_driver_nop; + +typedef struct _CoglDriverDescription +{ + CoglDriver id; + const char *name; + CoglRendererConstraint constraints; + /* It would be nice to make this a pointer and then use a compound + * literal from C99 to initialise it but we probably can't get away + * with using C99 here. Instead we'll just use a fixed-size array. + * GCC should complain if someone adds an 8th feature to a + * driver. */ + const CoglPrivateFeature private_features[8]; + const CoglDriverVtable *vtable; + const CoglTextureDriver *texture_driver; + const char *libgl_name; +} CoglDriverDescription; + +static CoglDriverDescription _cogl_drivers[] = +{ +#ifdef HAVE_COGL_GL + { + COGL_DRIVER_GL, + "gl", + 0, + { COGL_PRIVATE_FEATURE_ANY_GL, + COGL_PRIVATE_FEATURE_GL_FIXED, + COGL_PRIVATE_FEATURE_GL_PROGRAMMABLE, + -1 }, + &_cogl_driver_gl, + &_cogl_texture_driver_gl, + COGL_GL_LIBNAME, + }, + { + COGL_DRIVER_GL3, + "gl3", + 0, + { COGL_PRIVATE_FEATURE_ANY_GL, + COGL_PRIVATE_FEATURE_GL_PROGRAMMABLE, + -1 }, + &_cogl_driver_gl, + &_cogl_texture_driver_gl, + COGL_GL_LIBNAME, + }, +#endif +#ifdef HAVE_COGL_GLES2 + { + COGL_DRIVER_GLES2, + "gles2", + COGL_RENDERER_CONSTRAINT_SUPPORTS_COGL_GLES2, + { COGL_PRIVATE_FEATURE_ANY_GL, + COGL_PRIVATE_FEATURE_GL_EMBEDDED, + COGL_PRIVATE_FEATURE_GL_PROGRAMMABLE, + -1 }, + &_cogl_driver_gles, + &_cogl_texture_driver_gles, + COGL_GLES2_LIBNAME, + }, +#endif +#ifdef HAVE_COGL_GLES + { + COGL_DRIVER_GLES1, + "gles1", + 0, + { COGL_PRIVATE_FEATURE_ANY_GL, + COGL_PRIVATE_FEATURE_GL_EMBEDDED, + COGL_PRIVATE_FEATURE_GL_FIXED, + -1 }, + &_cogl_driver_gles, + &_cogl_texture_driver_gles, + COGL_GLES1_LIBNAME, + }, +#endif + { + COGL_DRIVER_NOP, + "nop", + 0, /* constraints satisfied */ + { -1 }, + &_cogl_driver_nop, + NULL, /* texture driver */ + NULL /* libgl_name */ + } +}; + +static CoglWinsysVtableGetter _cogl_winsys_vtable_getters[] = +{ +#ifdef COGL_HAS_GLX_SUPPORT + _cogl_winsys_glx_get_vtable, +#endif +#ifdef COGL_HAS_EGL_PLATFORM_XLIB_SUPPORT + _cogl_winsys_egl_xlib_get_vtable, +#endif + _cogl_winsys_stub_get_vtable, +}; + +static void _cogl_renderer_free (CoglRenderer *renderer); + +COGL_OBJECT_DEFINE (Renderer, renderer); +COGL_GTYPE_DEFINE_CLASS (Renderer, renderer); + +typedef struct _CoglNativeFilterClosure +{ + CoglNativeFilterFunc func; + void *data; +} CoglNativeFilterClosure; + +uint32_t +cogl_renderer_error_quark (void) +{ + return g_quark_from_static_string ("cogl-renderer-error-quark"); +} + +static const CoglWinsysVtable * +_cogl_renderer_get_winsys (CoglRenderer *renderer) +{ + return renderer->winsys_vtable; +} + +static void +native_filter_closure_free (CoglNativeFilterClosure *closure) +{ + g_slice_free (CoglNativeFilterClosure, closure); +} + +static void +_cogl_renderer_free (CoglRenderer *renderer) +{ + const CoglWinsysVtable *winsys = _cogl_renderer_get_winsys (renderer); + + _cogl_closure_list_disconnect_all (&renderer->idle_closures); + + if (winsys) + winsys->renderer_disconnect (renderer); + + if (renderer->libgl_module) + g_module_close (renderer->libgl_module); + + g_slist_foreach (renderer->event_filters, + (GFunc) native_filter_closure_free, + NULL); + g_slist_free (renderer->event_filters); + + g_array_free (renderer->poll_fds, TRUE); + + g_free (renderer); +} + +CoglRenderer * +cogl_renderer_new (void) +{ + CoglRenderer *renderer = g_new0 (CoglRenderer, 1); + + _cogl_init (); + + renderer->connected = FALSE; + renderer->event_filters = NULL; + + renderer->poll_fds = g_array_new (FALSE, TRUE, sizeof (CoglPollFD)); + + _cogl_list_init (&renderer->idle_closures); + +#ifdef COGL_HAS_XLIB_SUPPORT + renderer->xlib_enable_event_retrieval = TRUE; +#endif + + return _cogl_renderer_object_new (renderer); +} + +#ifdef COGL_HAS_XLIB_SUPPORT +void +cogl_xlib_renderer_set_foreign_display (CoglRenderer *renderer, + Display *xdisplay) +{ + _COGL_RETURN_IF_FAIL (cogl_is_renderer (renderer)); + + /* NB: Renderers are considered immutable once connected */ + _COGL_RETURN_IF_FAIL (!renderer->connected); + + renderer->foreign_xdpy = xdisplay; + + /* If the application is using a foreign display then we can assume + it will also do its own event retrieval */ + cogl_xlib_renderer_set_event_retrieval_enabled (renderer, FALSE); +} + +Display * +cogl_xlib_renderer_get_foreign_display (CoglRenderer *renderer) +{ + _COGL_RETURN_VAL_IF_FAIL (cogl_is_renderer (renderer), NULL); + + return renderer->foreign_xdpy; +} + +void +cogl_xlib_renderer_set_event_retrieval_enabled (CoglRenderer *renderer, + CoglBool enable) +{ + _COGL_RETURN_IF_FAIL (cogl_is_renderer (renderer)); + /* NB: Renderers are considered immutable once connected */ + _COGL_RETURN_IF_FAIL (!renderer->connected); + + renderer->xlib_enable_event_retrieval = enable; +} + +void +cogl_xlib_renderer_request_reset_on_video_memory_purge (CoglRenderer *renderer, + CoglBool enable) +{ + _COGL_RETURN_IF_FAIL (cogl_is_renderer (renderer)); + _COGL_RETURN_IF_FAIL (!renderer->connected); + + renderer->xlib_want_reset_on_video_memory_purge = enable; +} +#endif /* COGL_HAS_XLIB_SUPPORT */ + +CoglBool +cogl_renderer_check_onscreen_template (CoglRenderer *renderer, + CoglOnscreenTemplate *onscreen_template, + CoglError **error) +{ + CoglDisplay *display; + + if (!cogl_renderer_connect (renderer, error)) + return FALSE; + + display = cogl_display_new (renderer, onscreen_template); + if (!cogl_display_setup (display, error)) + { + cogl_object_unref (display); + return FALSE; + } + + cogl_object_unref (display); + + return TRUE; +} + +typedef CoglBool (*CoglDriverCallback) (CoglDriverDescription *description, + void *user_data); + +static void +foreach_driver_description (CoglDriver driver_override, + CoglDriverCallback callback, + void *user_data) +{ +#ifdef COGL_DEFAULT_DRIVER + const CoglDriverDescription *default_driver = NULL; +#endif + int i; + + if (driver_override != COGL_DRIVER_ANY) + { + for (i = 0; i < G_N_ELEMENTS (_cogl_drivers); i++) + { + if (_cogl_drivers[i].id == driver_override) + { + callback (&_cogl_drivers[i], user_data); + return; + } + } + + g_warn_if_reached (); + return; + } + +#ifdef COGL_DEFAULT_DRIVER + for (i = 0; i < G_N_ELEMENTS (_cogl_drivers); i++) + { + const CoglDriverDescription *desc = &_cogl_drivers[i]; + if (g_ascii_strcasecmp (desc->name, COGL_DEFAULT_DRIVER) == 0) + { + default_driver = desc; + break; + } + } + + if (default_driver) + { + if (!callback (default_driver, user_data)) + return; + } +#endif + + for (i = 0; i < G_N_ELEMENTS (_cogl_drivers); i++) + { +#ifdef COGL_DEFAULT_DRIVER + if (&_cogl_drivers[i] == default_driver) + continue; +#endif + + if (!callback (&_cogl_drivers[i], user_data)) + return; + } +} + +static CoglDriver +driver_name_to_id (const char *name) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS (_cogl_drivers); i++) + { + if (g_ascii_strcasecmp (_cogl_drivers[i].name, name) == 0) + return _cogl_drivers[i].id; + } + + return COGL_DRIVER_ANY; +} + +static const char * +driver_id_to_name (CoglDriver id) +{ + switch (id) + { + case COGL_DRIVER_GL: + return "gl"; + case COGL_DRIVER_GL3: + return "gl3"; + case COGL_DRIVER_GLES1: + return "gles1"; + case COGL_DRIVER_GLES2: + return "gles2"; + case COGL_DRIVER_WEBGL: + return "webgl"; + case COGL_DRIVER_NOP: + return "nop"; + case COGL_DRIVER_ANY: + g_warn_if_reached (); + return "any"; + } + + g_warn_if_reached (); + return "unknown"; +} + +typedef struct _SatisfyConstraintsState +{ + GList *constraints; + const CoglDriverDescription *driver_description; +} SatisfyConstraintsState; + +static CoglBool +satisfy_constraints (CoglDriverDescription *description, + void *user_data) +{ + SatisfyConstraintsState *state = user_data; + GList *l; + + for (l = state->constraints; l; l = l->next) + { + CoglRendererConstraint constraint = GPOINTER_TO_UINT (l->data); + + /* Most of the constraints only affect the winsys selection so + * we'll filter them out */ + if (!(constraint & COGL_RENDERER_DRIVER_CONSTRAINTS)) + continue; + + /* If the driver doesn't satisfy any constraint then continue + * to the next driver description */ + if (!(constraint & description->constraints)) + return TRUE; + } + + state->driver_description = description; + + return FALSE; +} + +static CoglBool +_cogl_renderer_choose_driver (CoglRenderer *renderer, + CoglError **error) +{ + const char *driver_name = g_getenv ("COGL_DRIVER"); + CoglDriver driver_override = COGL_DRIVER_ANY; + const char *invalid_override = NULL; + const char *libgl_name; + SatisfyConstraintsState state; + const CoglDriverDescription *desc; + int i; + + if (!driver_name) + driver_name = _cogl_config_driver; + + if (driver_name) + { + driver_override = driver_name_to_id (driver_name); + if (driver_override == COGL_DRIVER_ANY) + invalid_override = driver_name; + } + + if (renderer->driver_override != COGL_DRIVER_ANY) + { + if (driver_override != COGL_DRIVER_ANY && + renderer->driver_override != driver_override) + { + _cogl_set_error (error, + COGL_RENDERER_ERROR, + COGL_RENDERER_ERROR_BAD_CONSTRAINT, + "Application driver selection conflicts with driver " + "specified in configuration"); + return FALSE; + } + + driver_override = renderer->driver_override; + } + + if (driver_override != COGL_DRIVER_ANY) + { + CoglBool found = FALSE; + int i; + + for (i = 0; i < G_N_ELEMENTS (_cogl_drivers); i++) + { + if (_cogl_drivers[i].id == driver_override) + { + found = TRUE; + break; + } + } + if (!found) + invalid_override = driver_id_to_name (driver_override); + } + + if (invalid_override) + { + _cogl_set_error (error, + COGL_RENDERER_ERROR, + COGL_RENDERER_ERROR_BAD_CONSTRAINT, + "Driver \"%s\" is not available", + invalid_override); + return FALSE; + } + + state.driver_description = NULL; + state.constraints = renderer->constraints; + + foreach_driver_description (driver_override, + satisfy_constraints, + &state); + + if (!state.driver_description) + { + _cogl_set_error (error, + COGL_RENDERER_ERROR, + COGL_RENDERER_ERROR_BAD_CONSTRAINT, + "No suitable driver found"); + return FALSE; + } + + desc = state.driver_description; + renderer->driver = desc->id; + renderer->driver_vtable = desc->vtable; + renderer->texture_driver = desc->texture_driver; + libgl_name = desc->libgl_name; + + memset(renderer->private_features, 0, sizeof (renderer->private_features)); + for (i = 0; desc->private_features[i] != -1; i++) + COGL_FLAGS_SET (renderer->private_features, + desc->private_features[i], TRUE); + + if (COGL_FLAGS_GET (renderer->private_features, + COGL_PRIVATE_FEATURE_ANY_GL)) + { + renderer->libgl_module = g_module_open (libgl_name, + G_MODULE_BIND_LAZY); + + if (renderer->libgl_module == NULL) + { + _cogl_set_error (error, COGL_DRIVER_ERROR, + COGL_DRIVER_ERROR_FAILED_TO_LOAD_LIBRARY, + "Failed to dynamically open the GL library \"%s\"", + libgl_name); + return FALSE; + } + } + + return TRUE; +} + +/* Final connection API */ + +void +cogl_renderer_set_custom_winsys (CoglRenderer *renderer, + CoglWinsysVtableGetter winsys_vtable_getter) +{ + renderer->custom_winsys_vtable_getter = winsys_vtable_getter; +} + +static CoglBool +connect_custom_winsys (CoglRenderer *renderer, + CoglError **error) +{ + const CoglWinsysVtable *winsys = renderer->custom_winsys_vtable_getter(); + CoglError *tmp_error = NULL; + GString *error_message; + + renderer->winsys_vtable = winsys; + + error_message = g_string_new (""); + if (!winsys->renderer_connect (renderer, &tmp_error)) + { + g_string_append_c (error_message, '\n'); + g_string_append (error_message, tmp_error->message); + cogl_error_free (tmp_error); + } + else + { + renderer->connected = TRUE; + g_string_free (error_message, TRUE); + return TRUE; + } + + renderer->winsys_vtable = NULL; + _cogl_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_INIT, + "Failed to connected to any renderer: %s", + error_message->str); + g_string_free (error_message, TRUE); + return FALSE; +} + +CoglBool +cogl_renderer_connect (CoglRenderer *renderer, CoglError **error) +{ + int i; + GString *error_message; + CoglBool constraints_failed = FALSE; + + if (renderer->connected) + return TRUE; + + /* The driver needs to be chosen before connecting the renderer + because eglInitialize requires the library containing the GL API + to be loaded before its called */ + if (!_cogl_renderer_choose_driver (renderer, error)) + return FALSE; + + if (renderer->custom_winsys_vtable_getter) + return connect_custom_winsys (renderer, error); + + error_message = g_string_new (""); + for (i = 0; i < G_N_ELEMENTS (_cogl_winsys_vtable_getters); i++) + { + const CoglWinsysVtable *winsys = _cogl_winsys_vtable_getters[i](); + CoglError *tmp_error = NULL; + GList *l; + CoglBool skip_due_to_constraints = FALSE; + + if (renderer->winsys_id_override != COGL_WINSYS_ID_ANY) + { + if (renderer->winsys_id_override != winsys->id) + continue; + } + else + { + char *user_choice = getenv ("COGL_RENDERER"); + if (!user_choice) + user_choice = _cogl_config_renderer; + if (user_choice && + g_ascii_strcasecmp (winsys->name, user_choice) != 0) + continue; + } + + for (l = renderer->constraints; l; l = l->next) + { + CoglRendererConstraint constraint = GPOINTER_TO_UINT (l->data); + if (!(winsys->constraints & constraint)) + { + skip_due_to_constraints = TRUE; + break; + } + } + if (skip_due_to_constraints) + { + constraints_failed |= TRUE; + continue; + } + + /* At least temporarily we will associate this winsys with + * the renderer in-case ->renderer_connect calls API that + * wants to query the current winsys... */ + renderer->winsys_vtable = winsys; + + if (!winsys->renderer_connect (renderer, &tmp_error)) + { + g_string_append_c (error_message, '\n'); + g_string_append (error_message, tmp_error->message); + cogl_error_free (tmp_error); + } + else + { + renderer->connected = TRUE; + g_string_free (error_message, TRUE); + return TRUE; + } + } + + if (!renderer->connected) + { + if (constraints_failed) + { + _cogl_set_error (error, COGL_RENDERER_ERROR, + COGL_RENDERER_ERROR_BAD_CONSTRAINT, + "Failed to connected to any renderer due to constraints"); + return FALSE; + } + + renderer->winsys_vtable = NULL; + _cogl_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_INIT, + "Failed to connected to any renderer: %s", + error_message->str); + g_string_free (error_message, TRUE); + return FALSE; + } + + return TRUE; +} + +CoglFilterReturn +_cogl_renderer_handle_native_event (CoglRenderer *renderer, + void *event) +{ + GSList *l, *next; + + /* Pass the event on to all of the registered filters in turn */ + for (l = renderer->event_filters; l; l = next) + { + CoglNativeFilterClosure *closure = l->data; + + /* The next pointer is taken now so that we can handle the + closure being removed during emission */ + next = l->next; + + if (closure->func (event, closure->data) == COGL_FILTER_REMOVE) + return COGL_FILTER_REMOVE; + } + + /* If the backend for the renderer also wants to see the events, it + should just register its own filter */ + + return COGL_FILTER_CONTINUE; +} + +void +_cogl_renderer_add_native_filter (CoglRenderer *renderer, + CoglNativeFilterFunc func, + void *data) +{ + CoglNativeFilterClosure *closure; + + closure = g_slice_new (CoglNativeFilterClosure); + closure->func = func; + closure->data = data; + + renderer->event_filters = g_slist_prepend (renderer->event_filters, closure); +} + +void +_cogl_renderer_remove_native_filter (CoglRenderer *renderer, + CoglNativeFilterFunc func, + void *data) +{ + GSList *l, *prev = NULL; + + for (l = renderer->event_filters; l; prev = l, l = l->next) + { + CoglNativeFilterClosure *closure = l->data; + + if (closure->func == func && closure->data == data) + { + native_filter_closure_free (closure); + if (prev) + prev->next = g_slist_delete_link (prev->next, l); + else + renderer->event_filters = + g_slist_delete_link (renderer->event_filters, l); + break; + } + } +} + +void +cogl_renderer_set_winsys_id (CoglRenderer *renderer, + CoglWinsysID winsys_id) +{ + _COGL_RETURN_IF_FAIL (!renderer->connected); + + renderer->winsys_id_override = winsys_id; +} + +CoglWinsysID +cogl_renderer_get_winsys_id (CoglRenderer *renderer) +{ + _COGL_RETURN_VAL_IF_FAIL (renderer->connected, 0); + + return renderer->winsys_vtable->id; +} + +void * +_cogl_renderer_get_proc_address (CoglRenderer *renderer, + const char *name, + CoglBool in_core) +{ + const CoglWinsysVtable *winsys = _cogl_renderer_get_winsys (renderer); + + return winsys->renderer_get_proc_address (renderer, name, in_core); +} + +int +cogl_renderer_get_n_fragment_texture_units (CoglRenderer *renderer) +{ + int n = 0; + + _COGL_GET_CONTEXT (ctx, 0); + +#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES2) + if (cogl_has_feature (ctx, COGL_FEATURE_ID_GLSL) || + cogl_has_feature (ctx, COGL_FEATURE_ID_ARBFP)) + GE (ctx, glGetIntegerv (GL_MAX_TEXTURE_IMAGE_UNITS, &n)); +#endif + + return n; +} + +void +cogl_renderer_add_constraint (CoglRenderer *renderer, + CoglRendererConstraint constraint) +{ + g_return_if_fail (!renderer->connected); + renderer->constraints = g_list_prepend (renderer->constraints, + GUINT_TO_POINTER (constraint)); +} + +void +cogl_renderer_remove_constraint (CoglRenderer *renderer, + CoglRendererConstraint constraint) +{ + g_return_if_fail (!renderer->connected); + renderer->constraints = g_list_remove (renderer->constraints, + GUINT_TO_POINTER (constraint)); +} + +void +cogl_renderer_set_driver (CoglRenderer *renderer, + CoglDriver driver) +{ + _COGL_RETURN_IF_FAIL (!renderer->connected); + renderer->driver_override = driver; +} + +CoglDriver +cogl_renderer_get_driver (CoglRenderer *renderer) +{ + _COGL_RETURN_VAL_IF_FAIL (renderer->connected, 0); + + return renderer->driver; +} + +void +cogl_renderer_foreach_output (CoglRenderer *renderer, + CoglOutputCallback callback, + void *user_data) +{ + GList *l; + + _COGL_RETURN_IF_FAIL (renderer->connected); + _COGL_RETURN_IF_FAIL (callback != NULL); + + for (l = renderer->outputs; l; l = l->next) + callback (l->data, user_data); +} diff --git a/cogl/cogl/cogl-renderer.h b/cogl/cogl/cogl-renderer.h new file mode 100644 index 0000000..8dbf199 --- /dev/null +++ b/cogl/cogl/cogl-renderer.h @@ -0,0 +1,427 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_RENDERER_H__ +#define __COGL_RENDERER_H__ + +#include +#include +#include +#include + +#include + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-renderer + * @short_description: Choosing a means to render + * + * A #CoglRenderer represents a means to render. It encapsulates the + * selection of an underlying driver, such as OpenGL or OpenGL-ES and + * a selection of a window system binding API such as GLX or EGL. + * + * A #CoglRenderer has two states, "unconnected" and "connected". When + * a renderer is first instantiated using cogl_renderer_new() it is + * unconnected so that it can be configured and constraints can be + * specified for how the backend driver and window system should be + * chosen. + * + * After configuration a #CoglRenderer can (optionally) be explicitly + * connected using cogl_renderer_connect() which allows for the + * handling of connection errors so that fallback configurations can + * be tried if necessary. Applications that don't support any + * fallbacks though can skip using cogl_renderer_connect() and leave + * Cogl to automatically connect the renderer. + * + * Once you have a configured #CoglRenderer it can be used to create a + * #CoglDisplay object using cogl_display_new(). + * + * Many applications don't need to explicitly use + * cogl_renderer_new() or cogl_display_new() and can just jump + * straight to cogl_context_new() and pass a %NULL display argument so + * Cogl will automatically connect and setup a renderer and + * display. + */ + + +/** + * COGL_RENDERER_ERROR: + * + * An error domain for exceptions reported by Cogl + */ +#define COGL_RENDERER_ERROR cogl_renderer_error_quark () + +uint32_t +cogl_renderer_error_quark (void); + +typedef struct _CoglRenderer CoglRenderer; + +/** + * cogl_renderer_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_renderer_get_gtype (void); + +/** + * cogl_is_renderer: + * @object: A #CoglObject pointer + * + * Determines if the given @object is a #CoglRenderer + * + * Return value: %TRUE if @object is a #CoglRenderer, else %FALSE. + * Since: 1.10 + * Stability: unstable + */ +CoglBool +cogl_is_renderer (void *object); + +/** + * cogl_renderer_new: + * + * Instantiates a new (unconnected) #CoglRenderer object. A + * #CoglRenderer represents a means to render. It encapsulates the + * selection of an underlying driver, such as OpenGL or OpenGL-ES and + * a selection of a window system binding API such as GLX or EGL. + * + * While the renderer is unconnected it can be configured so that + * applications may specify backend constraints, such as "must use + * x11" for example via cogl_renderer_add_constraint(). + * + * There are also some platform specific configuration apis such + * as cogl_xlib_renderer_set_foreign_display() that may also be + * used while the renderer is unconnected. + * + * Once the renderer has been configured, then it may (optionally) be + * explicitly connected using cogl_renderer_connect() which allows + * errors to be handled gracefully and potentially fallback + * configurations can be tried out if there are initial failures. + * + * If a renderer is not explicitly connected then cogl_display_new() + * will automatically connect the renderer for you. If you don't + * have any code to deal with error/fallback situations then its fine + * to just let Cogl do the connection for you. + * + * Once you have setup your renderer then the next step is to create a + * #CoglDisplay using cogl_display_new(). + * + * Many applications don't need to explicitly use + * cogl_renderer_new() or cogl_display_new() and can just jump + * straight to cogl_context_new() and pass a %NULL display argument + * so Cogl will automatically connect and setup a renderer and + * display. + * + * Return value: (transfer full): A newly created #CoglRenderer. + * + * Since: 1.10 + * Stability: unstable + */ +CoglRenderer * +cogl_renderer_new (void); + +/* optional configuration APIs */ + +/** + * CoglWinsysID: + * @COGL_WINSYS_ID_ANY: Implies no preference for which backend is used + * @COGL_WINSYS_ID_STUB: Use the no-op stub backend + * @COGL_WINSYS_ID_GLX: Use the GLX window system binding API + * @COGL_WINSYS_ID_EGL_XLIB: Use EGL with the X window system via XLib + * + * Identifies specific window system backends that Cogl supports. + * + * These can be used to query what backend Cogl is using or to try and + * explicitly select a backend to use. + */ +typedef enum +{ + COGL_WINSYS_ID_ANY, + COGL_WINSYS_ID_STUB, + COGL_WINSYS_ID_GLX, + COGL_WINSYS_ID_EGL_XLIB, + COGL_WINSYS_ID_CUSTOM, +} CoglWinsysID; + +/** + * cogl_renderer_set_winsys_id: + * @renderer: A #CoglRenderer + * @winsys_id: An ID of the winsys you explicitly want to use. + * + * This allows you to explicitly select a winsys backend to use instead + * of letting Cogl automatically select a backend. + * + * if you select an unsupported backend then cogl_renderer_connect() + * will fail and report an error. + * + * This may only be called on an un-connected #CoglRenderer. + */ +void +cogl_renderer_set_winsys_id (CoglRenderer *renderer, + CoglWinsysID winsys_id); + +/** + * cogl_renderer_get_winsys_id: + * @renderer: A #CoglRenderer + * + * Queries which window system backend Cogl has chosen to use. + * + * This may only be called on a connected #CoglRenderer. + * + * Returns: The #CoglWinsysID corresponding to the chosen window + * system backend. + */ +CoglWinsysID +cogl_renderer_get_winsys_id (CoglRenderer *renderer); + +/** + * cogl_renderer_get_n_fragment_texture_units: + * @renderer: A #CoglRenderer + * + * Queries how many texture units can be used from fragment programs + * + * Returns: the number of texture image units. + * + * Since: 1.8 + * Stability: Unstable + */ +int +cogl_renderer_get_n_fragment_texture_units (CoglRenderer *renderer); + +/** + * cogl_renderer_check_onscreen_template: (skip) + * @renderer: A #CoglRenderer + * @onscreen_template: A #CoglOnscreenTemplate + * @error: A pointer to a #CoglError for reporting exceptions + * + * Tests if a given @onscreen_template can be supported with the given + * @renderer. + * + * Return value: %TRUE if the @onscreen_template can be supported, + * else %FALSE. + * Since: 1.10 + * Stability: unstable + */ +CoglBool +cogl_renderer_check_onscreen_template (CoglRenderer *renderer, + CoglOnscreenTemplate *onscreen_template, + CoglError **error); + +/* Final connection API */ + +/** + * cogl_renderer_connect: + * @renderer: An unconnected #CoglRenderer + * @error: a pointer to a #CoglError for reporting exceptions + * + * Connects the configured @renderer. Renderer connection isn't a + * very active process, it basically just means validating that + * any given constraint criteria can be satisfied and that a + * usable driver and window system backend can be found. + * + * Return value: %TRUE if there was no error while connecting the + * given @renderer. %FALSE if there was an error. + * Since: 1.10 + * Stability: unstable + */ +CoglBool +cogl_renderer_connect (CoglRenderer *renderer, CoglError **error); + +/** + * CoglRendererConstraint: + * @COGL_RENDERER_CONSTRAINT_USES_X11: Require the renderer to be X11 based + * @COGL_RENDERER_CONSTRAINT_USES_XLIB: Require the renderer to be X11 + * based and use Xlib + * @COGL_RENDERER_CONSTRAINT_USES_EGL: Require the renderer to be EGL based + * @COGL_RENDERER_CONSTRAINT_SUPPORTS_COGL_GLES2: Require that the + * renderer supports creating a #CoglGLES2Context via + * cogl_gles2_context_new(). This can be used to integrate GLES 2.0 + * code into Cogl based applications. + * + * These constraint flags are hard-coded features of the different renderer + * backends. Sometimes a platform may support multiple rendering options which + * Cogl will usually choose from automatically. Some of these features are + * important to higher level applications and frameworks though, such as + * whether a renderer is X11 based because an application might only support + * X11 based input handling. An application might also need to ensure EGL is + * used internally too if they depend on access to an EGLDisplay for some + * purpose. + * + * Applications should ideally minimize how many of these constraints + * they depend on to ensure maximum portability. + * + * Since: 1.10 + * Stability: unstable + */ +typedef enum +{ + COGL_RENDERER_CONSTRAINT_USES_X11 = (1 << 0), + COGL_RENDERER_CONSTRAINT_USES_XLIB = (1 << 1), + COGL_RENDERER_CONSTRAINT_USES_EGL = (1 << 2), + COGL_RENDERER_CONSTRAINT_SUPPORTS_COGL_GLES2 = (1 << 3) +} CoglRendererConstraint; + + +/** + * cogl_renderer_add_constraint: + * @renderer: An unconnected #CoglRenderer + * @constraint: A #CoglRendererConstraint to add + * + * This adds a renderer selection @constraint. + * + * Applications should ideally minimize how many of these constraints they + * depend on to ensure maximum portability. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_renderer_add_constraint (CoglRenderer *renderer, + CoglRendererConstraint constraint); + +/** + * cogl_renderer_remove_constraint: + * @renderer: An unconnected #CoglRenderer + * @constraint: A #CoglRendererConstraint to remove + * + * This removes a renderer selection @constraint. + * + * Applications should ideally minimize how many of these constraints they + * depend on to ensure maximum portability. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_renderer_remove_constraint (CoglRenderer *renderer, + CoglRendererConstraint constraint); + +/** + * CoglDriver: + * @COGL_DRIVER_ANY: Implies no preference for which driver is used + * @COGL_DRIVER_NOP: A No-Op driver. + * @COGL_DRIVER_GL: An OpenGL driver. + * @COGL_DRIVER_GL3: An OpenGL driver using the core GL 3.1 profile + * @COGL_DRIVER_GLES1: An OpenGL ES 1.1 driver. + * @COGL_DRIVER_GLES2: An OpenGL ES 2.0 driver. + * @COGL_DRIVER_WEBGL: A WebGL driver. + * + * Identifiers for underlying hardware drivers that may be used by + * Cogl for rendering. + * + * Since: 1.10 + * Stability: unstable + */ +typedef enum +{ + COGL_DRIVER_ANY, + COGL_DRIVER_NOP, + COGL_DRIVER_GL, + COGL_DRIVER_GL3, + COGL_DRIVER_GLES1, + COGL_DRIVER_GLES2, + COGL_DRIVER_WEBGL +} CoglDriver; + +/** + * cogl_renderer_set_driver: + * @renderer: An unconnected #CoglRenderer + * + * Requests that Cogl should try to use a specific underlying driver + * for rendering. + * + * If you select an unsupported driver then cogl_renderer_connect() + * will fail and report an error. Most applications should not + * explicitly select a driver and should rely on Cogl automatically + * choosing the driver. + * + * This may only be called on an un-connected #CoglRenderer. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_renderer_set_driver (CoglRenderer *renderer, + CoglDriver driver); + +/** + * cogl_renderer_get_driver: + * @renderer: A connected #CoglRenderer + * + * Queries what underlying driver is being used by Cogl. + * + * This may only be called on a connected #CoglRenderer. + * + * Since: 1.10 + * Stability: unstable + */ +CoglDriver +cogl_renderer_get_driver (CoglRenderer *renderer); + +/** + * CoglOutputCallback: + * @output: The current display output being iterated + * @user_data: The user pointer passed to + * cogl_renderer_foreach_output() + * + * A callback type that can be passed to + * cogl_renderer_foreach_output() for iterating display outputs for a + * given renderer. + * + * Since: 1.14 + * Stability: Unstable + */ +typedef void (*CoglOutputCallback) (CoglOutput *output, void *user_data); + +/** + * cogl_renderer_foreach_output: + * @renderer: A connected #CoglRenderer + * @callback: (scope call): A #CoglOutputCallback to be called for + * each display output + * @user_data: A user pointer to be passed to @callback + * + * Iterates all known display outputs for the given @renderer and + * passes a corresponding #CoglOutput pointer to the given @callback + * for each one, along with the given @user_data. + * + * Since: 1.14 + * Stability: Unstable + */ +void +cogl_renderer_foreach_output (CoglRenderer *renderer, + CoglOutputCallback callback, + void *user_data); + +COGL_END_DECLS + +#endif /* __COGL_RENDERER_H__ */ + diff --git a/cogl/cogl/cogl-sampler-cache-private.h b/cogl/cogl/cogl-sampler-cache-private.h new file mode 100644 index 0000000..5688eff --- /dev/null +++ b/cogl/cogl/cogl-sampler-cache-private.h @@ -0,0 +1,96 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_SAMPLER_CACHE_PRIVATE_H +#define __COGL_SAMPLER_CACHE_PRIVATE_H + +#include "cogl-context.h" +#include "cogl-gl-header.h" + +/* These aren't defined in the GLES headers */ +#ifndef GL_CLAMP_TO_BORDER +#define GL_CLAMP_TO_BORDER 0x812d +#endif +#ifndef GL_MIRRORED_REPEAT +#define GL_MIRRORED_REPEAT 0x8370 +#endif + +/* GL_ALWAYS is just used here as a value that is known not to clash + * with any valid GL wrap modes. + * + * XXX: keep the values in sync with the CoglPipelineWrapMode enum + * so no conversion is actually needed. + */ +typedef enum _CoglSamplerCacheWrapMode +{ + COGL_SAMPLER_CACHE_WRAP_MODE_REPEAT = GL_REPEAT, + COGL_SAMPLER_CACHE_WRAP_MODE_MIRRORED_REPEAT = GL_MIRRORED_REPEAT, + COGL_SAMPLER_CACHE_WRAP_MODE_CLAMP_TO_EDGE = GL_CLAMP_TO_EDGE, + COGL_SAMPLER_CACHE_WRAP_MODE_CLAMP_TO_BORDER = GL_CLAMP_TO_BORDER, + COGL_SAMPLER_CACHE_WRAP_MODE_AUTOMATIC = GL_ALWAYS +} CoglSamplerCacheWrapMode; + +typedef struct _CoglSamplerCache CoglSamplerCache; + +typedef struct _CoglSamplerCacheEntry +{ + GLuint sampler_object; + + GLenum min_filter; + GLenum mag_filter; + + CoglSamplerCacheWrapMode wrap_mode_s; + CoglSamplerCacheWrapMode wrap_mode_t; + CoglSamplerCacheWrapMode wrap_mode_p; +} CoglSamplerCacheEntry; + +CoglSamplerCache * +_cogl_sampler_cache_new (CoglContext *context); + +const CoglSamplerCacheEntry * +_cogl_sampler_cache_get_default_entry (CoglSamplerCache *cache); + +const CoglSamplerCacheEntry * +_cogl_sampler_cache_update_wrap_modes (CoglSamplerCache *cache, + const CoglSamplerCacheEntry *old_entry, + CoglSamplerCacheWrapMode wrap_mode_s, + CoglSamplerCacheWrapMode wrap_mode_t, + CoglSamplerCacheWrapMode wrap_mode_p); + +const CoglSamplerCacheEntry * +_cogl_sampler_cache_update_filters (CoglSamplerCache *cache, + const CoglSamplerCacheEntry *old_entry, + GLenum min_filter, + GLenum mag_filter); + +void +_cogl_sampler_cache_free (CoglSamplerCache *cache); + +#endif /* __COGL_SAMPLER_CACHE_PRIVATE_H */ diff --git a/cogl/cogl/cogl-sampler-cache.c b/cogl/cogl/cogl-sampler-cache.c new file mode 100644 index 0000000..1f92120 --- /dev/null +++ b/cogl/cogl/cogl-sampler-cache.c @@ -0,0 +1,371 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * Authors: + * Neil Roberts + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-sampler-cache-private.h" +#include "cogl-context-private.h" +#include "cogl-util-gl-private.h" + +#ifndef GL_TEXTURE_WRAP_R +#define GL_TEXTURE_WRAP_R 0x8072 +#endif + +struct _CoglSamplerCache +{ + CoglContext *context; + + /* The samplers are hashed in two tables. One is using the enum + values that Cogl exposes (so it can include the 'automatic' wrap + mode) and the other is using the converted values that will be + given to GL. The first is used to get a unique pointer for the + sampler state so that pipelines only need to store a single + pointer instead of the whole state and the second is used so that + only a single GL sampler object will be created for each unique + GL state. */ + GHashTable *hash_table_cogl; + GHashTable *hash_table_gl; + + /* This is used for generated fake unique sampler object numbers + when the sampler object extension is not supported */ + GLuint next_fake_sampler_object_number; +}; + +static CoglSamplerCacheWrapMode +get_real_wrap_mode (CoglSamplerCacheWrapMode wrap_mode) +{ + if (wrap_mode == COGL_SAMPLER_CACHE_WRAP_MODE_AUTOMATIC) + return COGL_SAMPLER_CACHE_WRAP_MODE_CLAMP_TO_EDGE; + + return wrap_mode; +} + +static void +canonicalize_key (CoglSamplerCacheEntry *key) +{ + /* This converts the wrap modes to the enums that will actually be + given to GL so that it can be used as a key to get a unique GL + sampler object for the state */ + key->wrap_mode_s = get_real_wrap_mode (key->wrap_mode_s); + key->wrap_mode_t = get_real_wrap_mode (key->wrap_mode_t); + key->wrap_mode_p = get_real_wrap_mode (key->wrap_mode_p); +} + +static CoglBool +wrap_mode_equal_gl (CoglSamplerCacheWrapMode wrap_mode0, + CoglSamplerCacheWrapMode wrap_mode1) +{ + /* We want to compare the actual GLenum that will be used so that if + two different wrap_modes actually use the same GL state we'll + still use the same sampler object */ + return get_real_wrap_mode (wrap_mode0) == get_real_wrap_mode (wrap_mode1); +} + +static CoglBool +sampler_state_equal_gl (const void *value0, + const void *value1) +{ + const CoglSamplerCacheEntry *state0 = value0; + const CoglSamplerCacheEntry *state1 = value1; + + return (state0->mag_filter == state1->mag_filter && + state0->min_filter == state1->min_filter && + wrap_mode_equal_gl (state0->wrap_mode_s, state1->wrap_mode_s) && + wrap_mode_equal_gl (state0->wrap_mode_t, state1->wrap_mode_t) && + wrap_mode_equal_gl (state0->wrap_mode_p, state1->wrap_mode_p)); +} + +static unsigned int +hash_wrap_mode_gl (unsigned int hash, + CoglSamplerCacheWrapMode wrap_mode) +{ + /* We want to hash the actual GLenum that will be used so that if + two different wrap_modes actually use the same GL state we'll + still use the same sampler object */ + GLenum real_wrap_mode = get_real_wrap_mode (wrap_mode); + + return _cogl_util_one_at_a_time_hash (hash, + &real_wrap_mode, + sizeof (real_wrap_mode)); +} + +static unsigned int +hash_sampler_state_gl (const void *key) +{ + const CoglSamplerCacheEntry *entry = key; + unsigned int hash = 0; + + hash = _cogl_util_one_at_a_time_hash (hash, &entry->mag_filter, + sizeof (entry->mag_filter)); + hash = _cogl_util_one_at_a_time_hash (hash, &entry->min_filter, + sizeof (entry->min_filter)); + hash = hash_wrap_mode_gl (hash, entry->wrap_mode_s); + hash = hash_wrap_mode_gl (hash, entry->wrap_mode_t); + hash = hash_wrap_mode_gl (hash, entry->wrap_mode_p); + + return _cogl_util_one_at_a_time_mix (hash); +} + +static CoglBool +sampler_state_equal_cogl (const void *value0, + const void *value1) +{ + const CoglSamplerCacheEntry *state0 = value0; + const CoglSamplerCacheEntry *state1 = value1; + + return (state0->mag_filter == state1->mag_filter && + state0->min_filter == state1->min_filter && + state0->wrap_mode_s == state1->wrap_mode_s && + state0->wrap_mode_t == state1->wrap_mode_t && + state0->wrap_mode_p == state1->wrap_mode_p); +} + +static unsigned int +hash_sampler_state_cogl (const void *key) +{ + const CoglSamplerCacheEntry *entry = key; + unsigned int hash = 0; + + hash = _cogl_util_one_at_a_time_hash (hash, &entry->mag_filter, + sizeof (entry->mag_filter)); + hash = _cogl_util_one_at_a_time_hash (hash, &entry->min_filter, + sizeof (entry->min_filter)); + hash = _cogl_util_one_at_a_time_hash (hash, &entry->wrap_mode_s, + sizeof (entry->wrap_mode_s)); + hash = _cogl_util_one_at_a_time_hash (hash, &entry->wrap_mode_t, + sizeof (entry->wrap_mode_t)); + hash = _cogl_util_one_at_a_time_hash (hash, &entry->wrap_mode_p, + sizeof (entry->wrap_mode_p)); + + return _cogl_util_one_at_a_time_mix (hash); +} + +CoglSamplerCache * +_cogl_sampler_cache_new (CoglContext *context) +{ + CoglSamplerCache *cache = g_new (CoglSamplerCache, 1); + + /* No reference is taken on the context because it would create a + circular reference */ + cache->context = context; + + cache->hash_table_gl = g_hash_table_new (hash_sampler_state_gl, + sampler_state_equal_gl); + cache->hash_table_cogl = g_hash_table_new (hash_sampler_state_cogl, + sampler_state_equal_cogl); + cache->next_fake_sampler_object_number = 1; + + return cache; +} + +static void +set_wrap_mode (CoglContext *context, + GLuint sampler_object, + GLenum param, + CoglSamplerCacheWrapMode wrap_mode) +{ + GE( context, glSamplerParameteri (sampler_object, + param, + wrap_mode) ); +} + +static CoglSamplerCacheEntry * +_cogl_sampler_cache_get_entry_gl (CoglSamplerCache *cache, + const CoglSamplerCacheEntry *key) +{ + CoglSamplerCacheEntry *entry; + + entry = g_hash_table_lookup (cache->hash_table_gl, key); + + if (entry == NULL) + { + CoglContext *context = cache->context; + + entry = g_slice_dup (CoglSamplerCacheEntry, key); + + if (_cogl_has_private_feature (context, + COGL_PRIVATE_FEATURE_SAMPLER_OBJECTS)) + { + GE( context, glGenSamplers (1, &entry->sampler_object) ); + + GE( context, glSamplerParameteri (entry->sampler_object, + GL_TEXTURE_MIN_FILTER, + entry->min_filter) ); + GE( context, glSamplerParameteri (entry->sampler_object, + GL_TEXTURE_MAG_FILTER, + entry->mag_filter) ); + + set_wrap_mode (context, + entry->sampler_object, + GL_TEXTURE_WRAP_S, + entry->wrap_mode_s); + set_wrap_mode (context, + entry->sampler_object, + GL_TEXTURE_WRAP_T, + entry->wrap_mode_t); + set_wrap_mode (context, + entry->sampler_object, + GL_TEXTURE_WRAP_R, + entry->wrap_mode_p); + } + else + { + /* If sampler objects aren't supported then we'll invent a + unique number so that pipelines can still compare the + unique state just by comparing the sampler object + numbers */ + entry->sampler_object = cache->next_fake_sampler_object_number++; + } + + g_hash_table_insert (cache->hash_table_gl, entry, entry); + } + + return entry; +} + +static CoglSamplerCacheEntry * +_cogl_sampler_cache_get_entry_cogl (CoglSamplerCache *cache, + const CoglSamplerCacheEntry *key) +{ + CoglSamplerCacheEntry *entry; + + entry = g_hash_table_lookup (cache->hash_table_cogl, key); + + if (entry == NULL) + { + CoglSamplerCacheEntry canonical_key; + CoglSamplerCacheEntry *gl_entry; + + entry = g_slice_dup (CoglSamplerCacheEntry, key); + + /* Get the sampler object number from the canonical GL version + of the sampler state cache */ + canonical_key = *key; + canonicalize_key (&canonical_key); + gl_entry = _cogl_sampler_cache_get_entry_gl (cache, &canonical_key); + entry->sampler_object = gl_entry->sampler_object; + + g_hash_table_insert (cache->hash_table_cogl, entry, entry); + } + + return entry; +} + +const CoglSamplerCacheEntry * +_cogl_sampler_cache_get_default_entry (CoglSamplerCache *cache) +{ + CoglSamplerCacheEntry key; + + key.wrap_mode_s = COGL_SAMPLER_CACHE_WRAP_MODE_AUTOMATIC; + key.wrap_mode_t = COGL_SAMPLER_CACHE_WRAP_MODE_AUTOMATIC; + key.wrap_mode_p = COGL_SAMPLER_CACHE_WRAP_MODE_AUTOMATIC; + + key.min_filter = GL_LINEAR; + key.mag_filter = GL_LINEAR; + + return _cogl_sampler_cache_get_entry_cogl (cache, &key); +} + +const CoglSamplerCacheEntry * +_cogl_sampler_cache_update_wrap_modes (CoglSamplerCache *cache, + const CoglSamplerCacheEntry *old_entry, + CoglSamplerCacheWrapMode wrap_mode_s, + CoglSamplerCacheWrapMode wrap_mode_t, + CoglSamplerCacheWrapMode wrap_mode_p) +{ + CoglSamplerCacheEntry key = *old_entry; + + key.wrap_mode_s = wrap_mode_s; + key.wrap_mode_t = wrap_mode_t; + key.wrap_mode_p = wrap_mode_p; + + return _cogl_sampler_cache_get_entry_cogl (cache, &key); +} + +const CoglSamplerCacheEntry * +_cogl_sampler_cache_update_filters (CoglSamplerCache *cache, + const CoglSamplerCacheEntry *old_entry, + GLenum min_filter, + GLenum mag_filter) +{ + CoglSamplerCacheEntry key = *old_entry; + + key.min_filter = min_filter; + key.mag_filter = mag_filter; + + return _cogl_sampler_cache_get_entry_cogl (cache, &key); +} + +static void +hash_table_free_gl_cb (void *key, + void *value, + void *user_data) +{ + CoglContext *context = user_data; + CoglSamplerCacheEntry *entry = value; + + if (_cogl_has_private_feature (context, + COGL_PRIVATE_FEATURE_SAMPLER_OBJECTS)) + GE( context, glDeleteSamplers (1, &entry->sampler_object) ); + + g_slice_free (CoglSamplerCacheEntry, entry); +} + +static void +hash_table_free_cogl_cb (void *key, + void *value, + void *user_data) +{ + CoglSamplerCacheEntry *entry = value; + + g_slice_free (CoglSamplerCacheEntry, entry); +} + +void +_cogl_sampler_cache_free (CoglSamplerCache *cache) +{ + g_hash_table_foreach (cache->hash_table_gl, + hash_table_free_gl_cb, + cache->context); + + g_hash_table_destroy (cache->hash_table_gl); + + g_hash_table_foreach (cache->hash_table_cogl, + hash_table_free_cogl_cb, + cache->context); + + g_hash_table_destroy (cache->hash_table_cogl); + + g_free (cache); +} diff --git a/cogl/cogl/cogl-snippet-private.h b/cogl/cogl/cogl-snippet-private.h new file mode 100644 index 0000000..e3269f2 --- /dev/null +++ b/cogl/cogl/cogl-snippet-private.h @@ -0,0 +1,77 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Neil Roberts + */ + +#ifndef __COGL_SNIPPET_PRIVATE_H +#define __COGL_SNIPPET_PRIVATE_H + +#include + +#include "cogl-snippet.h" +#include "cogl-object-private.h" + +/* These values are also used in the enum for CoglSnippetHook. They + are copied here because we don't really want these names to be part + of the public API */ +#define COGL_SNIPPET_HOOK_BAND_SIZE 2048 +#define COGL_SNIPPET_FIRST_PIPELINE_HOOK 0 +#define COGL_SNIPPET_FIRST_PIPELINE_VERTEX_HOOK \ + COGL_SNIPPET_FIRST_PIPELINE_HOOK +#define COGL_SNIPPET_FIRST_PIPELINE_FRAGMENT_HOOK \ + (COGL_SNIPPET_FIRST_PIPELINE_VERTEX_HOOK + COGL_SNIPPET_HOOK_BAND_SIZE) +#define COGL_SNIPPET_FIRST_LAYER_HOOK (COGL_SNIPPET_HOOK_BAND_SIZE * 2) +#define COGL_SNIPPET_FIRST_LAYER_VERTEX_HOOK COGL_SNIPPET_FIRST_LAYER_HOOK +#define COGL_SNIPPET_FIRST_LAYER_FRAGMENT_HOOK \ + (COGL_SNIPPET_FIRST_LAYER_VERTEX_HOOK + COGL_SNIPPET_HOOK_BAND_SIZE) + +struct _CoglSnippet +{ + CoglObject _parent; + + CoglSnippetHook hook; + + /* This is set to TRUE the first time the snippet is attached to the + pipeline. After that any attempts to modify the snippet will be + ignored. */ + CoglBool immutable; + + char *declarations; + char *pre; + char *replace; + char *post; +}; + +void +_cogl_snippet_make_immutable (CoglSnippet *snippet); + +#endif /* __COGL_SNIPPET_PRIVATE_H */ + diff --git a/cogl/cogl/cogl-snippet.c b/cogl/cogl/cogl-snippet.c new file mode 100644 index 0000000..c5a7940 --- /dev/null +++ b/cogl/cogl/cogl-snippet.c @@ -0,0 +1,187 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Neil Roberts + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-types.h" +#include "cogl-snippet-private.h" +#include "cogl-util.h" +#include "cogl-gtype-private.h" + +static void +_cogl_snippet_free (CoglSnippet *snippet); + +COGL_OBJECT_DEFINE (Snippet, snippet); +COGL_GTYPE_DEFINE_CLASS (Snippet, snippet); + +CoglSnippet * +cogl_snippet_new (CoglSnippetHook hook, + const char *declarations, + const char *post) +{ + CoglSnippet *snippet = g_slice_new0 (CoglSnippet); + + _cogl_snippet_object_new (snippet); + + snippet->hook = hook; + + cogl_snippet_set_declarations (snippet, declarations); + cogl_snippet_set_post (snippet, post); + + return snippet; +} + +CoglSnippetHook +cogl_snippet_get_hook (CoglSnippet *snippet) +{ + _COGL_RETURN_VAL_IF_FAIL (cogl_is_snippet (snippet), 0); + + return snippet->hook; +} + +static CoglBool +_cogl_snippet_modify (CoglSnippet *snippet) +{ + if (snippet->immutable) + { + g_warning ("A CoglSnippet should not be modified once it has been " + "attached to a pipeline. Any modifications after that point " + "will be ignored."); + + return FALSE; + } + + return TRUE; +} + +void +cogl_snippet_set_declarations (CoglSnippet *snippet, + const char *declarations) +{ + _COGL_RETURN_IF_FAIL (cogl_is_snippet (snippet)); + + if (!_cogl_snippet_modify (snippet)) + return; + + g_free (snippet->declarations); + snippet->declarations = declarations ? g_strdup (declarations) : NULL; +} + +const char * +cogl_snippet_get_declarations (CoglSnippet *snippet) +{ + _COGL_RETURN_VAL_IF_FAIL (cogl_is_snippet (snippet), NULL); + + return snippet->declarations; +} + +void +cogl_snippet_set_pre (CoglSnippet *snippet, + const char *pre) +{ + _COGL_RETURN_IF_FAIL (cogl_is_snippet (snippet)); + + if (!_cogl_snippet_modify (snippet)) + return; + + g_free (snippet->pre); + snippet->pre = pre ? g_strdup (pre) : NULL; +} + +const char * +cogl_snippet_get_pre (CoglSnippet *snippet) +{ + _COGL_RETURN_VAL_IF_FAIL (cogl_is_snippet (snippet), NULL); + + return snippet->pre; +} + +void +cogl_snippet_set_replace (CoglSnippet *snippet, + const char *replace) +{ + _COGL_RETURN_IF_FAIL (cogl_is_snippet (snippet)); + + if (!_cogl_snippet_modify (snippet)) + return; + + g_free (snippet->replace); + snippet->replace = replace ? g_strdup (replace) : NULL; +} + +const char * +cogl_snippet_get_replace (CoglSnippet *snippet) +{ + _COGL_RETURN_VAL_IF_FAIL (cogl_is_snippet (snippet), NULL); + + return snippet->replace; +} + +void +cogl_snippet_set_post (CoglSnippet *snippet, + const char *post) +{ + _COGL_RETURN_IF_FAIL (cogl_is_snippet (snippet)); + + if (!_cogl_snippet_modify (snippet)) + return; + + g_free (snippet->post); + snippet->post = post ? g_strdup (post) : NULL; +} + +const char * +cogl_snippet_get_post (CoglSnippet *snippet) +{ + _COGL_RETURN_VAL_IF_FAIL (cogl_is_snippet (snippet), NULL); + + return snippet->post; +} + +void +_cogl_snippet_make_immutable (CoglSnippet *snippet) +{ + snippet->immutable = TRUE; +} + +static void +_cogl_snippet_free (CoglSnippet *snippet) +{ + g_free (snippet->declarations); + g_free (snippet->pre); + g_free (snippet->replace); + g_free (snippet->post); + g_slice_free (CoglSnippet, snippet); +} diff --git a/cogl/cogl/cogl-snippet.h b/cogl/cogl/cogl-snippet.h new file mode 100644 index 0000000..a4a77ed --- /dev/null +++ b/cogl/cogl/cogl-snippet.h @@ -0,0 +1,864 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011, 2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Neil Roberts + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_SNIPPET_H__ +#define __COGL_SNIPPET_H__ + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-snippet + * @short_description: Functions for creating and manipulating shader snippets + * + * #CoglSnippets are used to modify or replace parts of a + * #CoglPipeline using GLSL. GLSL is a programming language supported + * by OpenGL on programmable hardware to provide a more flexible + * description of what should be rendered. A description of GLSL + * itself is outside the scope of this documentation but any good + * OpenGL book should help to describe it. + * + * Unlike in OpenGL, when using GLSL with Cogl it is possible to write + * short snippets to replace small sections of the pipeline instead of + * having to replace the whole of either the vertex or fragment + * pipelines. Of course it is also possible to replace the whole of + * the pipeline if needed. + * + * Each snippet is a standalone chunk of code which would attach to + * the pipeline at a particular point. The code is split into four + * separate strings (all of which are optional): + * + * + * + * declarations + * + * The code in this string will be inserted outside of any function in + * the global scope of the shader. This can be used to declare + * uniforms, attributes, varyings and functions to be used by the + * snippet. + * + * + * + * pre + * + * The code in this string will be inserted before the hook point. + * + * + * + * post + * + * The code in this string will be inserted after the hook point. This + * can be used to modify the results of the builtin generated code for + * that hook point. + * + * + * + * replace + * + * If present the code in this string will replace the generated code + * for the hook point. + * + * + * + * + * All of the strings apart from the declarations string of a pipeline + * are generated in a single function so they can share variables + * declared from one string in another. The scope of the code is + * limited to each snippet so local variables declared in the snippet + * will not collide with variables declared in another + * snippet. However, code in the 'declarations' string is global to + * the shader so it is the application's responsibility to ensure that + * variables declared here will not collide with those from other + * snippets. + * + * The snippets can be added to a pipeline with + * cogl_pipeline_add_snippet() or + * cogl_pipeline_add_layer_snippet(). Which function to use depends on + * which hook the snippet is targetting. The snippets are all + * generated in the order they are added to the pipeline. That is, the + * post strings are executed in the order they are added to the + * pipeline and the pre strings are executed in reverse order. If any + * replace strings are given for a snippet then any other snippets + * with the same hook added before that snippet will be ignored. The + * different hooks are documented under #CoglSnippetHook. + * + * For portability with GLES2, it is recommended not to use the GLSL + * builtin names such as gl_FragColor. Instead there are replacement + * names under the cogl_* namespace which can be used instead. These + * are: + * + * + * + * uniform mat4 + * cogl_modelview_matrix + * + * The current modelview matrix. This is equivalent to + * #gl_ModelViewMatrix. + * + * + * + * uniform mat4 + * cogl_projection_matrix + * + * The current projection matrix. This is equivalent to + * #gl_ProjectionMatrix. + * + * + * + * uniform mat4 + * cogl_modelview_projection_matrix + * + * The combined modelview and projection matrix. A vertex shader + * would typically use this to transform the incoming vertex + * position. The separate modelview and projection matrices are + * usually only needed for lighting calculations. This is + * equivalent to #gl_ModelViewProjectionMatrix. + * + * + * + * uniform mat4 + * cogl_texture_matrix[] + * + * An array of matrices for transforming the texture + * coordinates. This is equivalent to #gl_TextureMatrix. + * + * + * + * + * In a vertex shader, the following are also available: + * + * + * + * attribute vec4 + * cogl_position_in + * + * The incoming vertex position. This is equivalent to #gl_Vertex. + * + * + * + * attribute vec4 + * cogl_color_in + * + * The incoming vertex color. This is equivalent to #gl_Color. + * + * + * + * attribute vec4 + * cogl_tex_coord_in + * + * The texture coordinate for layer 0. This is an alternative name + * for #cogl_tex_coord0_in. + * + * + * + * attribute vec4 + * cogl_tex_coord0_in + * + * The texture coordinate for the layer 0. This is equivalent to + * #gl_MultiTexCoord0. There will also be #cogl_tex_coord1_in and + * so on if more layers are added to the pipeline. + * + * + * + * attribute vec3 + * cogl_normal_in + * + * The normal of the vertex. This is equivalent to #gl_Normal. + * + * + * + * vec4 + * cogl_position_out + * + * The calculated position of the vertex. This must be written to + * in all vertex shaders. This is equivalent to #gl_Position. + * + * + * + * float + * cogl_point_size_in + * + * The incoming point size from the cogl_point_size_in attribute. + * This is only available if + * cogl_pipeline_set_per_vertex_point_size() is set on the + * pipeline. + * + * + * + * float + * cogl_point_size_out + * + * The calculated size of a point. This is equivalent to #gl_PointSize. + * + * + * + * varying vec4 + * cogl_color_out + * + * The calculated color of a vertex. This is equivalent to #gl_FrontColor. + * + * + * + * varying vec4 + * cogl_tex_coord0_out + * + * The calculated texture coordinate for layer 0 of the pipeline. + * This is equivalent to #gl_TexCoord[0]. There will also be + * #cogl_tex_coord1_out and so on if more layers are added to the + * pipeline. In the fragment shader, this varying is called + * #cogl_tex_coord0_in. + * + * + * + * + * In a fragment shader, the following are also available: + * + * + * + * varying vec4 cogl_color_in + * + * The calculated color of a vertex. This is equivalent to #gl_FrontColor. + * + * + * + * varying vec4 + * cogl_tex_coord0_in + * + * The texture coordinate for layer 0. This is equivalent to + * #gl_TexCoord[0]. There will also be #cogl_tex_coord1_in and so + * on if more layers are added to the pipeline. + * + * + * + * vec4 cogl_color_out + * + * The final calculated color of the fragment. All fragment shaders + * must write to this variable. This is equivalent to + * #gl_FrontColor. + * + * + * + * float cogl_depth_out + * + * An optional output variable specifying the depth value to use + * for this fragment. This is equivalent to #gl_FragDepth. + * + * + * + * bool cogl_front_facing + * + * A readonly variable that will be true if the current primitive + * is front facing. This can be used to implement two-sided + * coloring algorithms. This is equivalent to #gl_FrontFacing. + * + * + * + * vec2 cogl_point_coord + * + * When rendering points, this will contain a vec2 which represents + * the position within the point of the current fragment. + * vec2(0.0,0.0) will be the topleft of the point and vec2(1.0,1.0) + * will be the bottom right. Note that there is currently a bug in + * Cogl where when rendering to an offscreen buffer these + * coordinates will be upside-down. The value is undefined when not + * rendering points. This builtin can only be used if the + * %COGL_FEATURE_ID_POINT_SPRITE feature is available. + * + * + * + * + * Here is an example of using a snippet to add a desaturate effect to the + * generated color on a pipeline. + * + * + * CoglPipeline *pipeline = cogl_pipeline_new (); + * + * /* Set up the pipeline here, ie by adding a texture or other + * layers */ + * + * /* Create the snippet. The first string is the declarations which + * we will use to add a uniform. The second is the 'post' string which + * will contain the code to perform the desaturation. */ + * CoglSnippet *snippet = + * cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, + * "uniform float factor;", + * "float gray = dot (vec3 (0.299, 0.587, 0.114), " + * " cogl_color_out.rgb);" + * "cogl_color_out.rgb = mix (vec3 (gray)," + * " cogl_color_out.rgb," + * " factor);"); + * + * /* Add it to the pipeline */ + * cogl_pipeline_add_snippet (pipeline, snippet); + * /* The pipeline keeps a reference to the snippet + * so we don't need to */ + * cogl_object_unref (snippet); + * + * /* Update the custom uniform on the pipeline */ + * int location = cogl_pipeline_get_uniform_location (pipeline, "factor"); + * cogl_pipeline_set_uniform_1f (pipeline, location, 0.5f); + * + * /* Now we can render with the snippet as usual */ + * cogl_push_source (pipeline); + * cogl_rectangle (0, 0, 10, 10); + * cogl_pop_source (); + * + */ +typedef struct _CoglSnippet CoglSnippet; + +#define COGL_SNIPPET(OBJECT) ((CoglSnippet *)OBJECT) + +/** + * cogl_snippet_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_snippet_get_gtype (void); + +/* Enumeration of all the hook points that a snippet can be attached + to within a pipeline. */ +/** + * CoglSnippetHook: + * @COGL_SNIPPET_HOOK_VERTEX_GLOBALS: A hook for declaring global data + * that can be shared with all other snippets that are on a vertex + * hook. + * @COGL_SNIPPET_HOOK_FRAGMENT_GLOBALS: A hook for declaring global + * data wthat can be shared with all other snippets that are on a + * fragment hook. + * @COGL_SNIPPET_HOOK_VERTEX: A hook for the entire vertex processing + * stage of the pipeline. + * @COGL_SNIPPET_HOOK_VERTEX_TRANSFORM: A hook for the vertex transformation. + * @COGL_SNIPPET_HOOK_POINT_SIZE: A hook for manipulating the point + * size of a vertex. This is only used if + * cogl_pipeline_set_per_vertex_point_size() is enabled on the + * pipeline. + * @COGL_SNIPPET_HOOK_FRAGMENT: A hook for the entire fragment + * processing stage of the pipeline. + * @COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM: A hook for applying the + * layer matrix to a texture coordinate for a layer. + * @COGL_SNIPPET_HOOK_LAYER_FRAGMENT: A hook for the fragment + * processing of a particular layer. + * @COGL_SNIPPET_HOOK_TEXTURE_LOOKUP: A hook for the texture lookup + * stage of a given layer in a pipeline. + * + * #CoglSnippetHook is used to specify a location within a + * #CoglPipeline where the code of the snippet should be used when it + * is attached to a pipeline. + * + * + * + * %COGL_SNIPPET_HOOK_VERTEX_GLOBALS + * + * + * Adds a shader snippet at the beginning of the global section of the + * shader for the vertex processing. Any declarations here can be + * shared with all other snippets that are attached to a vertex hook. + * Only the ‘declarations’ string is used and the other strings are + * ignored. + * + * + * + * + * %COGL_SNIPPET_HOOK_FRAGMENT_GLOBALS + * + * + * Adds a shader snippet at the beginning of the global section of the + * shader for the fragment processing. Any declarations here can be + * shared with all other snippets that are attached to a fragment + * hook. Only the ‘declarations’ string is used and the other strings + * are ignored. + * + * + * + * + * %COGL_SNIPPET_HOOK_VERTEX + * + * + * Adds a shader snippet that will hook on to the vertex processing + * stage of the pipeline. This gives a chance for the application to + * modify the vertex attributes generated by the shader. Typically the + * snippet will modify cogl_color_out or cogl_position_out builtins. + * + * + * The ‘declarations’ string in @snippet will be inserted in the + * global scope of the shader. Use this to declare any uniforms, + * attributes or functions that the snippet requires. + * + * + * The ‘pre’ string in @snippet will be inserted at the top of the + * main() function before any vertex processing is done. + * + * + * The ‘replace’ string in @snippet will be used instead of the + * generated vertex processing if it is present. This can be used if + * the application wants to provide a complete vertex shader and + * doesn't need the generated output from Cogl. + * + * + * The ‘post’ string in @snippet will be inserted after all of the + * standard vertex processing is done. This can be used to modify the + * outputs. + * + * + * + * + * %COGL_SNIPPET_HOOK_VERTEX_TRANSFORM + * + * + * Adds a shader snippet that will hook on to the vertex transform stage. + * Typically the snippet will use the cogl_modelview_matrix, + * cogl_projection_matrix and cogl_modelview_projection_matrix matrices and the + * cogl_position_in attribute. The hook must write to cogl_position_out. + * The default processing for this hook will multiply cogl_position_in by + * the combined modelview-projection matrix and store it on cogl_position_out. + * + * + * The ‘declarations’ string in @snippet will be inserted in the + * global scope of the shader. Use this to declare any uniforms, + * attributes or functions that the snippet requires. + * + * + * The ‘pre’ string in @snippet will be inserted at the top of the + * main() function before the vertex transform is done. + * + * + * The ‘replace’ string in @snippet will be used instead of the + * generated vertex transform if it is present. + * + * + * The ‘post’ string in @snippet will be inserted after all of the + * standard vertex transformation is done. This can be used to modify the + * cogl_position_out in addition to the default processing. + * + * + * + * + * %COGL_SNIPPET_HOOK_POINT_SIZE + * + * + * Adds a shader snippet that will hook on to the point size + * calculation step within the vertex shader stage. The snippet should + * write to the builtin cogl_point_size_out with the new point size. + * The snippet can either read cogl_point_size_in directly and write a + * new value or first read an existing value in cogl_point_size_out + * that would be set by a previous snippet. Note that this hook is + * only used if cogl_pipeline_set_per_vertex_point_size() is enabled + * on the pipeline. + * + * + * The ‘declarations’ string in @snippet will be inserted in the + * global scope of the shader. Use this to declare any uniforms, + * attributes or functions that the snippet requires. + * + * + * The ‘pre’ string in @snippet will be inserted just before + * calculating the point size. + * + * + * The ‘replace’ string in @snippet will be used instead of the + * generated point size calculation if it is present. + * + * + * The ‘post’ string in @snippet will be inserted after the + * standard point size calculation is done. This can be used to modify + * cogl_point_size_out in addition to the default processing. + * + * + * + * + * %COGL_SNIPPET_HOOK_FRAGMENT + * + * + * Adds a shader snippet that will hook on to the fragment processing + * stage of the pipeline. This gives a chance for the application to + * modify the fragment color generated by the shader. Typically the + * snippet will modify cogl_color_out. + * + * + * The ‘declarations’ string in @snippet will be inserted in the + * global scope of the shader. Use this to declare any uniforms, + * attributes or functions that the snippet requires. + * + * + * The ‘pre’ string in @snippet will be inserted at the top of the + * main() function before any fragment processing is done. + * + * + * The ‘replace’ string in @snippet will be used instead of the + * generated fragment processing if it is present. This can be used if + * the application wants to provide a complete fragment shader and + * doesn't need the generated output from Cogl. + * + * + * The ‘post’ string in @snippet will be inserted after all of the + * standard fragment processing is done. At this point the generated + * value for the rest of the pipeline state will already be in + * cogl_color_out so the application can modify the result by altering + * this variable. + * + * + * + * + * %COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM + * + * + * Adds a shader snippet that will hook on to the texture coordinate + * transformation of a particular layer. This can be used to replace + * the processing for a layer or to modify the results. + * + * + * Within the snippet code for this hook there are two extra + * variables. The first is a mat4 called cogl_matrix which represents + * the user matrix for this layer. The second is called cogl_tex_coord + * and represents the incoming and outgoing texture coordinate. On + * entry to the hook, cogl_tex_coord contains the value of the + * corresponding texture coordinate attribute for this layer. The hook + * is expected to modify this variable. The output will be passed as a + * varying to the fragment processing stage. The default code will + * just multiply cogl_matrix by cogl_tex_coord and store the result in + * cogl_tex_coord. + * + * + * The ‘declarations’ string in @snippet will be inserted in the + * global scope of the shader. Use this to declare any uniforms, + * attributes or functions that the snippet requires. + * + * + * The ‘pre’ string in @snippet will be inserted just before the + * fragment processing for this layer. At this point cogl_tex_coord + * still contains the value of the texture coordinate attribute. + * + * + * If a ‘replace’ string is given then this will be used instead of + * the default fragment processing for this layer. The snippet can + * modify cogl_tex_coord or leave it as is to apply no transformation. + * + * + * The ‘post’ string in @snippet will be inserted just after the + * transformation. At this point cogl_tex_coord will contain the + * results of the transformation but it can be further modified by the + * snippet. + * + * + * + * + * %COGL_SNIPPET_HOOK_LAYER_FRAGMENT + * + * + * Adds a shader snippet that will hook on to the fragment processing + * of a particular layer. This can be used to replace the processing + * for a layer or to modify the results. + * + * + * Within the snippet code for this hook there is an extra vec4 + * variable called ‘cogl_layer’. This contains the resulting color + * that will be used for the layer. This can be modified in the ‘post’ + * section or it the default processing can be replaced entirely using + * the ‘replace’ section. + * + * + * The ‘declarations’ string in @snippet will be inserted in the + * global scope of the shader. Use this to declare any uniforms, + * attributes or functions that the snippet requires. + * + * + * The ‘pre’ string in @snippet will be inserted just before the + * fragment processing for this layer. + * + * + * If a ‘replace’ string is given then this will be used instead of + * the default fragment processing for this layer. The snippet must write to + * the ‘cogl_layer’ variable in that case. + * + * + * The ‘post’ string in @snippet will be inserted just after the + * fragment processing for the layer. The results can be modified by changing + * the value of the ‘cogl_layer’ variable. + * + * + * + * + * %COGL_SNIPPET_HOOK_TEXTURE_LOOKUP + * + * + * Adds a shader snippet that will hook on to the texture lookup part + * of a given layer. This gives a chance for the application to modify + * the coordinates that will be used for the texture lookup or to + * alter the returned texel. + * + * + * Within the snippet code for this hook there are three extra + * variables available. ‘cogl_sampler’ is a sampler object + * representing the sampler for the layer where the snippet is + * attached. ‘cogl_tex_coord’ is a vec4 which contains the texture + * coordinates that will be used for the texture lookup. This can be + * modified. ‘cogl_texel’ will contain the result of the texture + * lookup. This can also be modified. + * + * + * The ‘declarations’ string in @snippet will be inserted in the + * global scope of the shader. Use this to declare any uniforms, + * attributes or functions that the snippet requires. + * + * + * The ‘pre’ string in @snippet will be inserted at the top of the + * main() function before any fragment processing is done. This is a + * good place to modify the cogl_tex_coord variable. + * + * + * If a ‘replace’ string is given then this will be used instead of a + * the default texture lookup. The snippet would typically use its own + * sampler in this case. + * + * + * The ‘post’ string in @snippet will be inserted after texture lookup + * has been preformed. Here the snippet can modify the cogl_texel + * variable to alter the returned texel. + * + * + * + * + * + * Since: 1.10 + * Stability: Unstable + */ +typedef enum { + /* Per pipeline vertex hooks */ + COGL_SNIPPET_HOOK_VERTEX = 0, + COGL_SNIPPET_HOOK_VERTEX_TRANSFORM, + COGL_SNIPPET_HOOK_VERTEX_GLOBALS, + COGL_SNIPPET_HOOK_POINT_SIZE, + + /* Per pipeline fragment hooks */ + COGL_SNIPPET_HOOK_FRAGMENT = 2048, + COGL_SNIPPET_HOOK_FRAGMENT_GLOBALS, + + /* Per layer vertex hooks */ + COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM = 4096, + + /* Per layer fragment hooks */ + COGL_SNIPPET_HOOK_LAYER_FRAGMENT = 6144, + COGL_SNIPPET_HOOK_TEXTURE_LOOKUP +} CoglSnippetHook; + +/** + * cogl_snippet_new: + * @hook: The point in the pipeline that this snippet will wrap around + * or replace. + * @declarations: The source code for the declarations for this + * snippet or %NULL. See cogl_snippet_set_declarations(). + * @post: The source code to run after the hook point where this + * shader snippet is attached or %NULL. See cogl_snippet_set_post(). + * + * Allocates and initializes a new snippet with the given source strings. + * + * Return value: a pointer to a new #CoglSnippet + * + * Since: 1.10 + * Stability: Unstable + */ +CoglSnippet * +cogl_snippet_new (CoglSnippetHook hook, + const char *declarations, + const char *post); + +/** + * cogl_snippet_get_hook: + * @snippet: A #CoglSnippet + * + * Return value: the hook that was set when cogl_snippet_new() was + * called. + * Since: 1.10 + * Stability: Unstable + */ +CoglSnippetHook +cogl_snippet_get_hook (CoglSnippet *snippet); + +/** + * cogl_is_snippet: + * @object: A #CoglObject pointer + * + * Gets whether the given @object references an existing snippet object. + * + * Return value: %TRUE if the @object references a #CoglSnippet, + * %FALSE otherwise + * + * Since: 1.10 + * Stability: Unstable + */ +CoglBool +cogl_is_snippet (void *object); + +/** + * cogl_snippet_set_declarations: + * @snippet: A #CoglSnippet + * @declarations: The new source string for the declarations section + * of this snippet. + * + * Sets a source string that will be inserted in the global scope of + * the generated shader when this snippet is used on a pipeline. This + * string is typically used to declare uniforms, attributes or + * functions that will be used by the other parts of the snippets. + * + * This function should only be called before the snippet is attached + * to its first pipeline. After that the snippet should be considered + * immutable. + * + * Since: 1.10 + * Stability: Unstable + */ +void +cogl_snippet_set_declarations (CoglSnippet *snippet, + const char *declarations); + +/** + * cogl_snippet_get_declarations: + * @snippet: A #CoglSnippet + * + * Return value: the source string that was set with + * cogl_snippet_set_declarations() or %NULL if none was set. + * + * Since: 1.10 + * Stability: Unstable + */ +const char * +cogl_snippet_get_declarations (CoglSnippet *snippet); + +/** + * cogl_snippet_set_pre: + * @snippet: A #CoglSnippet + * @pre: The new source string for the pre section of this snippet. + * + * Sets a source string that will be inserted before the hook point in + * the generated shader for the pipeline that this snippet is attached + * to. Please see the documentation of each hook point in + * #CoglPipeline for a description of how this string should be used. + * + * This function should only be called before the snippet is attached + * to its first pipeline. After that the snippet should be considered + * immutable. + * + * Since: 1.10 + * Stability: Unstable + */ +void +cogl_snippet_set_pre (CoglSnippet *snippet, + const char *pre); + +/** + * cogl_snippet_get_pre: + * @snippet: A #CoglSnippet + * + * Return value: the source string that was set with + * cogl_snippet_set_pre() or %NULL if none was set. + * + * Since: 1.10 + * Stability: Unstable + */ +const char * +cogl_snippet_get_pre (CoglSnippet *snippet); + +/** + * cogl_snippet_set_replace: + * @snippet: A #CoglSnippet + * @replace: The new source string for the replace section of this snippet. + * + * Sets a source string that will be used instead of any generated + * source code or any previous snippets for this hook point. Please + * see the documentation of each hook point in #CoglPipeline for a + * description of how this string should be used. + * + * This function should only be called before the snippet is attached + * to its first pipeline. After that the snippet should be considered + * immutable. + * + * Since: 1.10 + * Stability: Unstable + */ +void +cogl_snippet_set_replace (CoglSnippet *snippet, + const char *replace); + +/** + * cogl_snippet_get_replace: + * @snippet: A #CoglSnippet + * + * Return value: the source string that was set with + * cogl_snippet_set_replace() or %NULL if none was set. + * + * Since: 1.10 + * Stability: Unstable + */ +const char * +cogl_snippet_get_replace (CoglSnippet *snippet); + +/** + * cogl_snippet_set_post: + * @snippet: A #CoglSnippet + * @post: The new source string for the post section of this snippet. + * + * Sets a source string that will be inserted after the hook point in + * the generated shader for the pipeline that this snippet is attached + * to. Please see the documentation of each hook point in + * #CoglPipeline for a description of how this string should be used. + * + * This function should only be called before the snippet is attached + * to its first pipeline. After that the snippet should be considered + * immutable. + * + * Since: 1.10 + * Stability: Unstable + */ +void +cogl_snippet_set_post (CoglSnippet *snippet, + const char *post); + +/** + * cogl_snippet_get_post: + * @snippet: A #CoglSnippet + * + * Return value: the source string that was set with + * cogl_snippet_set_post() or %NULL if none was set. + * + * Since: 1.10 + * Stability: Unstable + */ +const char * +cogl_snippet_get_post (CoglSnippet *snippet); + +COGL_END_DECLS + +#endif /* __COGL_SNIPPET_H__ */ diff --git a/cogl/cogl/cogl-spans.c b/cogl/cogl/cogl-spans.c new file mode 100644 index 0000000..85f8e01 --- /dev/null +++ b/cogl/cogl/cogl-spans.c @@ -0,0 +1,183 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "math.h" + +#include "cogl-util.h" +#include "cogl-spans.h" + +void +_cogl_span_iter_update (CoglSpanIter *iter) +{ + /* Pick current span */ + iter->span = &iter->spans[iter->index]; + + /* Offset next position by span size */ + iter->next_pos = iter->pos + iter->span->size - iter->span->waste; + + /* Check if span intersects the area to cover */ + if (iter->next_pos <= iter->cover_start || + iter->pos >= iter->cover_end) + { + /* Intersection undefined */ + iter->intersects = FALSE; + return; + } + + iter->intersects = TRUE; + + /* Clip start position to coverage area */ + if (iter->pos < iter->cover_start) + iter->intersect_start = iter->cover_start; + else + iter->intersect_start = iter->pos; + + /* Clip end position to coverage area */ + if (iter->next_pos > iter->cover_end) + iter->intersect_end = iter->cover_end; + else + iter->intersect_end = iter->next_pos; +} + +void +_cogl_span_iter_begin (CoglSpanIter *iter, + const CoglSpan *spans, + int n_spans, + float normalize_factor, + float cover_start, + float cover_end, + CoglPipelineWrapMode wrap_mode) +{ + /* XXX: If CLAMP_TO_EDGE needs to be emulated then it needs to be + * done at a higher level than here... */ + _COGL_RETURN_IF_FAIL (wrap_mode == COGL_PIPELINE_WRAP_MODE_REPEAT || + wrap_mode == COGL_PIPELINE_WRAP_MODE_MIRRORED_REPEAT); + + iter->span = NULL; + + iter->spans = spans; + iter->n_spans = n_spans; + + /* We always iterate in a positive direction from the origin. If + * iter->flipped == TRUE that means whoever is using this API should + * interpreted the current span as extending in the opposite direction. I.e. + * it extends to the left if iterating the X axis, or up if the Y axis. */ + if (cover_start > cover_end) + { + float tmp = cover_start; + cover_start = cover_end; + cover_end = tmp; + iter->flipped = TRUE; + } + else + iter->flipped = FALSE; + + /* The texture spans cover the normalized texture coordinate space ranging + * from [0,1] but to help support repeating of sliced textures we allow + * iteration of any range so we need to relate the start of the range to the + * nearest point equivalent to 0. + */ + if (normalize_factor != 1.0) + { + float cover_start_normalized = cover_start / normalize_factor; + iter->origin = floorf (cover_start_normalized) * normalize_factor; + } + else + iter->origin = floorf (cover_start); + + iter->wrap_mode = wrap_mode; + + if (wrap_mode == COGL_PIPELINE_WRAP_MODE_REPEAT) + iter->index = 0; + else if (wrap_mode == COGL_PIPELINE_WRAP_MODE_MIRRORED_REPEAT) + { + if ((int)iter->origin % 2) + { + iter->index = iter->n_spans - 1; + iter->mirror_direction = -1; + iter->flipped = !iter->flipped; + } + else + { + iter->index = 0; + iter->mirror_direction = 1; + } + } + else + g_warn_if_reached (); + + iter->cover_start = cover_start; + iter->cover_end = cover_end; + iter->pos = iter->origin; + + /* Update intersection */ + _cogl_span_iter_update (iter); + + while (iter->next_pos <= iter->cover_start) + _cogl_span_iter_next (iter); +} + +void +_cogl_span_iter_next (CoglSpanIter *iter) +{ + /* Move current position */ + iter->pos = iter->next_pos; + + if (iter->wrap_mode == COGL_PIPELINE_WRAP_MODE_REPEAT) + iter->index = (iter->index + 1) % iter->n_spans; + else if (iter->wrap_mode == COGL_PIPELINE_WRAP_MODE_MIRRORED_REPEAT) + { + iter->index += iter->mirror_direction; + if (iter->index == iter->n_spans || iter->index == -1) + { + iter->mirror_direction = -iter->mirror_direction; + iter->index += iter->mirror_direction; + iter->flipped = !iter->flipped; + } + } + else + g_warn_if_reached (); + + /* Update intersection */ + _cogl_span_iter_update (iter); +} + +CoglBool +_cogl_span_iter_end (CoglSpanIter *iter) +{ + /* End reached when whole area covered */ + return iter->pos >= iter->cover_end; +} + + diff --git a/cogl/cogl/cogl-spans.h b/cogl/cogl/cogl-spans.h new file mode 100644 index 0000000..a236784 --- /dev/null +++ b/cogl/cogl/cogl-spans.h @@ -0,0 +1,81 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_SPANS_PRIVATE_H +#define __COGL_SPANS_PRIVATE_H + +#include "cogl-object-private.h" +#include "cogl-pipeline-layer-state.h" + +typedef struct _CoglSpan +{ + float start; + float size; + float waste; +} CoglSpan; + +typedef struct _CoglSpanIter +{ + int index; + const CoglSpan *spans; + int n_spans; + const CoglSpan *span; + float pos; + float next_pos; + float origin; + float cover_start; + float cover_end; + float intersect_start; + float intersect_end; + CoglBool intersects; + CoglBool flipped; + CoglPipelineWrapMode wrap_mode; + int mirror_direction; +} CoglSpanIter; + +void +_cogl_span_iter_update (CoglSpanIter *iter); + +void +_cogl_span_iter_begin (CoglSpanIter *iter, + const CoglSpan *spans, + int n_spans, + float normalize_factor, + float cover_start, + float cover_end, + CoglPipelineWrapMode wrap_mode); + +void +_cogl_span_iter_next (CoglSpanIter *iter); + +CoglBool +_cogl_span_iter_end (CoglSpanIter *iter); + +#endif /* __COGL_SPANS_PRIVATE_H */ diff --git a/cogl/cogl/cogl-sub-texture-private.h b/cogl/cogl/cogl-sub-texture-private.h new file mode 100644 index 0000000..75c476d --- /dev/null +++ b/cogl/cogl/cogl-sub-texture-private.h @@ -0,0 +1,62 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_SUB_TEXTURE_PRIVATE_H +#define __COGL_SUB_TEXTURE_PRIVATE_H + +#include "cogl-texture-private.h" + +#include + +struct _CoglSubTexture +{ + CoglTexture _parent; + + /* This is the texture that was passed in to + _cogl_sub_texture_new. If this is also a sub texture then we will + use the full texture from that to render instead of making a + chain. However we want to preserve the next texture in case the + user is expecting us to keep a reference and also so that we can + later add a cogl_sub_texture_get_parent_texture() function. */ + CoglTexture *next_texture; + /* This is the texture that will actually be used to draw. It will + point to the end of the chain if a sub texture of a sub texture + is created */ + CoglTexture *full_texture; + + /* The offset of the region represented by this sub-texture. This is + * the offset in full_texture which won't necessarily be the same as + * the offset passed to _cogl_sub_texture_new if next_texture is + * actually already a sub texture */ + int sub_x; + int sub_y; +}; + +#endif /* __COGL_SUB_TEXTURE_PRIVATE_H */ diff --git a/cogl/cogl/cogl-sub-texture.c b/cogl/cogl/cogl-sub-texture.c new file mode 100644 index 0000000..9d7abea --- /dev/null +++ b/cogl/cogl/cogl-sub-texture.c @@ -0,0 +1,480 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009,2010,2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Neil Roberts + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-util.h" +#include "cogl-texture-private.h" +#include "cogl-sub-texture-private.h" +#include "cogl-sub-texture.h" +#include "cogl-context-private.h" +#include "cogl-object.h" +#include "cogl-texture-driver.h" +#include "cogl-texture-rectangle-private.h" +#include "cogl-texture-2d.h" +#include "cogl-texture-gl-private.h" +#include "cogl-gtype-private.h" + +#include +#include + +static void _cogl_sub_texture_free (CoglSubTexture *sub_tex); + +COGL_TEXTURE_DEFINE (SubTexture, sub_texture); +COGL_GTYPE_DEFINE_CLASS (SubTexture, sub_texture); + +static const CoglTextureVtable cogl_sub_texture_vtable; + +static void +_cogl_sub_texture_unmap_quad (CoglSubTexture *sub_tex, + float *coords) +{ + CoglTexture *tex = COGL_TEXTURE (sub_tex); + + /* NB: coords[] come in as non-normalized if sub_tex->full_texture + * is a CoglTextureRectangle otherwhise they are normalized. The + * coordinates we write out though must always be normalized. + * + * NB: sub_tex->sub_x/y/width/height are in non-normalized + * coordinates. + */ + if (cogl_is_texture_rectangle (sub_tex->full_texture)) + { + coords[0] = (coords[0] - sub_tex->sub_x) / tex->width; + coords[1] = (coords[1] - sub_tex->sub_y) / tex->height; + coords[2] = (coords[2] - sub_tex->sub_x) / tex->width; + coords[3] = (coords[3] - sub_tex->sub_y) / tex->height; + } + else + { + float width = cogl_texture_get_width (sub_tex->full_texture); + float height = cogl_texture_get_height (sub_tex->full_texture); + coords[0] = (coords[0] * width - sub_tex->sub_x) / tex->width; + coords[1] = (coords[1] * height - sub_tex->sub_y) / tex->height; + coords[2] = (coords[2] * width - sub_tex->sub_x) / tex->width; + coords[3] = (coords[3] * height - sub_tex->sub_y) / tex->height; + } +} + +static void +_cogl_sub_texture_map_quad (CoglSubTexture *sub_tex, + float *coords) +{ + CoglTexture *tex = COGL_TEXTURE (sub_tex); + + /* NB: coords[] always come in as normalized coordinates but may go + * out as non-normalized if sub_tex->full_texture is a + * CoglTextureRectangle. + * + * NB: sub_tex->sub_x/y/width/height are in non-normalized + * coordinates. + */ + + if (cogl_is_texture_rectangle (sub_tex->full_texture)) + { + coords[0] = coords[0] * tex->width + sub_tex->sub_x; + coords[1] = coords[1] * tex->height + sub_tex->sub_y; + coords[2] = coords[2] * tex->width + sub_tex->sub_x; + coords[3] = coords[3] * tex->height + sub_tex->sub_y; + } + else + { + float width = cogl_texture_get_width (sub_tex->full_texture); + float height = cogl_texture_get_height (sub_tex->full_texture); + coords[0] = (coords[0] * tex->width + sub_tex->sub_x) / width; + coords[1] = (coords[1] * tex->height + sub_tex->sub_y) / height; + coords[2] = (coords[2] * tex->width + sub_tex->sub_x) / width; + coords[3] = (coords[3] * tex->height + sub_tex->sub_y) / height; + } +} + +typedef struct _CoglSubTextureForeachData +{ + CoglSubTexture *sub_tex; + CoglMetaTextureCallback callback; + void *user_data; +} CoglSubTextureForeachData; + +static void +unmap_coords_cb (CoglTexture *slice_texture, + const float *slice_texture_coords, + const float *meta_coords, + void *user_data) +{ + CoglSubTextureForeachData *data = user_data; + float unmapped_coords[4]; + + memcpy (unmapped_coords, meta_coords, sizeof (unmapped_coords)); + + _cogl_sub_texture_unmap_quad (data->sub_tex, unmapped_coords); + + data->callback (slice_texture, + slice_texture_coords, + unmapped_coords, + data->user_data); +} + +static void +_cogl_sub_texture_foreach_sub_texture_in_region ( + CoglTexture *tex, + float virtual_tx_1, + float virtual_ty_1, + float virtual_tx_2, + float virtual_ty_2, + CoglMetaTextureCallback callback, + void *user_data) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + CoglTexture *full_texture = sub_tex->full_texture; + float mapped_coords[4] = + { virtual_tx_1, virtual_ty_1, virtual_tx_2, virtual_ty_2}; + float virtual_coords[4] = + { virtual_tx_1, virtual_ty_1, virtual_tx_2, virtual_ty_2}; + + /* map the virtual coordinates to ->full_texture coordinates */ + _cogl_sub_texture_map_quad (sub_tex, mapped_coords); + + /* TODO: Add something like cogl_is_low_level_texture() */ + if (cogl_is_texture_2d (full_texture) || + cogl_is_texture_rectangle (full_texture)) + { + callback (sub_tex->full_texture, + mapped_coords, + virtual_coords, + user_data); + } + else + { + CoglSubTextureForeachData data; + + data.sub_tex = sub_tex; + data.callback = callback; + data.user_data = user_data; + + cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (full_texture), + mapped_coords[0], + mapped_coords[1], + mapped_coords[2], + mapped_coords[3], + COGL_PIPELINE_WRAP_MODE_REPEAT, + COGL_PIPELINE_WRAP_MODE_REPEAT, + unmap_coords_cb, + &data); + } +} + +static void +_cogl_sub_texture_gl_flush_legacy_texobj_wrap_modes (CoglTexture *tex, + GLenum wrap_mode_s, + GLenum wrap_mode_t, + GLenum wrap_mode_p) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + + _cogl_texture_gl_flush_legacy_texobj_wrap_modes (sub_tex->full_texture, + wrap_mode_s, + wrap_mode_t, + wrap_mode_p); +} + +static void +_cogl_sub_texture_free (CoglSubTexture *sub_tex) +{ + cogl_object_unref (sub_tex->next_texture); + cogl_object_unref (sub_tex->full_texture); + + /* Chain up */ + _cogl_texture_free (COGL_TEXTURE (sub_tex)); +} + +CoglSubTexture * +cogl_sub_texture_new (CoglContext *ctx, + CoglTexture *next_texture, + int sub_x, int sub_y, + int sub_width, int sub_height) +{ + CoglTexture *full_texture; + CoglSubTexture *sub_tex; + CoglTexture *tex; + unsigned int next_width, next_height; + + next_width = cogl_texture_get_width (next_texture); + next_height = cogl_texture_get_height (next_texture); + + /* The region must specify a non-zero subset of the full texture */ + _COGL_RETURN_VAL_IF_FAIL (sub_x >= 0 && sub_y >= 0, NULL); + _COGL_RETURN_VAL_IF_FAIL (sub_width > 0 && sub_height > 0, NULL); + _COGL_RETURN_VAL_IF_FAIL (sub_x + sub_width <= next_width, NULL); + _COGL_RETURN_VAL_IF_FAIL (sub_y + sub_height <= next_height, NULL); + + sub_tex = g_new (CoglSubTexture, 1); + + tex = COGL_TEXTURE (sub_tex); + + _cogl_texture_init (tex, ctx, sub_width, sub_height, + _cogl_texture_get_format (next_texture), + NULL, /* no loader */ + &cogl_sub_texture_vtable); + + /* If the next texture is also a sub texture we can avoid one level + of indirection by referencing the full texture of that texture + instead. */ + if (cogl_is_sub_texture (next_texture)) + { + CoglSubTexture *other_sub_tex = COGL_SUB_TEXTURE (next_texture); + full_texture = other_sub_tex->full_texture; + sub_x += other_sub_tex->sub_x; + sub_y += other_sub_tex->sub_y; + } + else + full_texture = next_texture; + + sub_tex->next_texture = cogl_object_ref (next_texture); + sub_tex->full_texture = cogl_object_ref (full_texture); + + sub_tex->sub_x = sub_x; + sub_tex->sub_y = sub_y; + + return _cogl_sub_texture_object_new (sub_tex); +} + +static CoglBool +_cogl_sub_texture_allocate (CoglTexture *tex, + CoglError **error) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + CoglBool status = cogl_texture_allocate (sub_tex->full_texture, error); + + _cogl_texture_set_allocated (tex, + _cogl_texture_get_format (sub_tex->full_texture), + tex->width, tex->height); + + return status; +} + +CoglTexture * +cogl_sub_texture_get_parent (CoglSubTexture *sub_texture) +{ + return sub_texture->next_texture; +} + +static int +_cogl_sub_texture_get_max_waste (CoglTexture *tex) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + + return cogl_texture_get_max_waste (sub_tex->full_texture); +} + +static CoglBool +_cogl_sub_texture_is_sliced (CoglTexture *tex) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + + return cogl_texture_is_sliced (sub_tex->full_texture); +} + +static CoglBool +_cogl_sub_texture_can_hardware_repeat (CoglTexture *tex) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + + /* We can hardware repeat if the subtexture actually represents all of the + of the full texture */ + return (tex->width == + cogl_texture_get_width (sub_tex->full_texture) && + tex->height == + cogl_texture_get_height (sub_tex->full_texture) && + _cogl_texture_can_hardware_repeat (sub_tex->full_texture)); +} + +static void +_cogl_sub_texture_transform_coords_to_gl (CoglTexture *tex, + float *s, + float *t) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + + /* This won't work if the sub texture is not the size of the full + texture and the coordinates are outside the range [0,1] */ + *s = ((*s * tex->width + sub_tex->sub_x) / + cogl_texture_get_width (sub_tex->full_texture)); + *t = ((*t * tex->height + sub_tex->sub_y) / + cogl_texture_get_height (sub_tex->full_texture)); + + _cogl_texture_transform_coords_to_gl (sub_tex->full_texture, s, t); +} + +static CoglTransformResult +_cogl_sub_texture_transform_quad_coords_to_gl (CoglTexture *tex, + float *coords) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + int i; + + /* We can't support repeating with this method. In this case + cogl-primitives will resort to manual repeating */ + for (i = 0; i < 4; i++) + if (coords[i] < 0.0f || coords[i] > 1.0f) + return COGL_TRANSFORM_SOFTWARE_REPEAT; + + _cogl_sub_texture_map_quad (sub_tex, coords); + + return _cogl_texture_transform_quad_coords_to_gl (sub_tex->full_texture, + coords); +} + +static CoglBool +_cogl_sub_texture_get_gl_texture (CoglTexture *tex, + GLuint *out_gl_handle, + GLenum *out_gl_target) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + + return cogl_texture_get_gl_texture (sub_tex->full_texture, + out_gl_handle, + out_gl_target); +} + +static void +_cogl_sub_texture_gl_flush_legacy_texobj_filters (CoglTexture *tex, + GLenum min_filter, + GLenum mag_filter) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + + _cogl_texture_gl_flush_legacy_texobj_filters (sub_tex->full_texture, + min_filter, mag_filter); +} + +static void +_cogl_sub_texture_pre_paint (CoglTexture *tex, + CoglTexturePrePaintFlags flags) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + + _cogl_texture_pre_paint (sub_tex->full_texture, flags); +} + +static void +_cogl_sub_texture_ensure_non_quad_rendering (CoglTexture *tex) +{ +} + +static CoglBool +_cogl_sub_texture_set_region (CoglTexture *tex, + int src_x, + int src_y, + int dst_x, + int dst_y, + int dst_width, + int dst_height, + int level, + CoglBitmap *bmp, + CoglError **error) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + + if (level != 0) + { + int full_width = cogl_texture_get_width (sub_tex->full_texture); + int full_height = cogl_texture_get_width (sub_tex->full_texture); + + _COGL_RETURN_VAL_IF_FAIL (sub_tex->sub_x == 0 && + cogl_texture_get_width (tex) == full_width, + FALSE); + _COGL_RETURN_VAL_IF_FAIL (sub_tex->sub_y == 0 && + cogl_texture_get_height (tex) == full_height, + FALSE); + } + + return _cogl_texture_set_region_from_bitmap (sub_tex->full_texture, + src_x, src_y, + dst_width, dst_height, + bmp, + dst_x + sub_tex->sub_x, + dst_y + sub_tex->sub_y, + level, + error); +} + +static CoglPixelFormat +_cogl_sub_texture_get_format (CoglTexture *tex) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + + return _cogl_texture_get_format (sub_tex->full_texture); +} + +static GLenum +_cogl_sub_texture_get_gl_format (CoglTexture *tex) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + + return _cogl_texture_gl_get_format (sub_tex->full_texture); +} + +static CoglTextureType +_cogl_sub_texture_get_type (CoglTexture *tex) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + + return _cogl_texture_get_type (sub_tex->full_texture); +} + +static const CoglTextureVtable +cogl_sub_texture_vtable = + { + FALSE, /* not primitive */ + _cogl_sub_texture_allocate, + _cogl_sub_texture_set_region, + NULL, /* get_data */ + _cogl_sub_texture_foreach_sub_texture_in_region, + _cogl_sub_texture_get_max_waste, + _cogl_sub_texture_is_sliced, + _cogl_sub_texture_can_hardware_repeat, + _cogl_sub_texture_transform_coords_to_gl, + _cogl_sub_texture_transform_quad_coords_to_gl, + _cogl_sub_texture_get_gl_texture, + _cogl_sub_texture_gl_flush_legacy_texobj_filters, + _cogl_sub_texture_pre_paint, + _cogl_sub_texture_ensure_non_quad_rendering, + _cogl_sub_texture_gl_flush_legacy_texobj_wrap_modes, + _cogl_sub_texture_get_format, + _cogl_sub_texture_get_gl_format, + _cogl_sub_texture_get_type, + NULL, /* is_foreign */ + NULL /* set_auto_mipmap */ + }; diff --git a/cogl/cogl/cogl-sub-texture.h b/cogl/cogl/cogl-sub-texture.h new file mode 100644 index 0000000..7b89bb7 --- /dev/null +++ b/cogl/cogl/cogl-sub-texture.h @@ -0,0 +1,134 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Neil Roberts + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_SUB_TEXTURE_H +#define __COGL_SUB_TEXTURE_H + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-sub-texture + * @short_description: Functions for creating and manipulating + * sub-textures. + * + * These functions allow high-level textures to be created that + * represent a sub-region of another texture. For example these + * can be used to implement custom texture atlasing schemes. + */ + + +#define COGL_SUB_TEXTURE(tex) ((CoglSubTexture *) tex) +typedef struct _CoglSubTexture CoglSubTexture; + +/** + * cogl_sub_texture_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_sub_texture_get_gtype (void); + +/** + * cogl_sub_texture_new: + * @ctx: A #CoglContext pointer + * @parent_texture: The full texture containing a sub-region you want + * to make a #CoglSubTexture from. + * @sub_x: The top-left x coordinate of the parent region to make + * a texture from. + * @sub_y: The top-left y coordinate of the parent region to make + * a texture from. + * @sub_width: The width of the parent region to make a texture from. + * @sub_height: The height of the parent region to make a texture + * from. + * + * Creates a high-level #CoglSubTexture representing a sub-region of + * any other #CoglTexture. The sub-region must strictly lye within the + * bounds of the @parent_texture. The returned texture implements the + * #CoglMetaTexture interface because it's not a low level texture + * that hardware can understand natively. + * + * Remember: Unless you are using high level drawing APIs such + * as cogl_rectangle() or other APIs documented to understand the + * #CoglMetaTexture interface then you need to use the + * #CoglMetaTexture interface to resolve a #CoglSubTexture into a + * low-level texture before drawing. + * + * Return value: (transfer full): A newly allocated #CoglSubTexture + * representing a sub-region of @parent_texture. + * + * Since: 1.10 + * Stability: unstable + */ +CoglSubTexture * +cogl_sub_texture_new (CoglContext *ctx, + CoglTexture *parent_texture, + int sub_x, + int sub_y, + int sub_width, + int sub_height); + +/** + * cogl_sub_texture_get_parent: + * @sub_texture: A pointer to a #CoglSubTexture + * + * Retrieves the parent texture that @sub_texture derives its content + * from. This is the texture that was passed to + * cogl_sub_texture_new() as the parent_texture argument. + * + * Return value: (transfer none): The parent texture that @sub_texture + * derives its content from. + * Since: 1.10 + * Stability: unstable + */ +CoglTexture * +cogl_sub_texture_get_parent (CoglSubTexture *sub_texture); + +/** + * cogl_is_sub_texture: + * @object: a #CoglObject + * + * Checks whether @object is a #CoglSubTexture. + * + * Return value: %TRUE if the passed @object represents a + * #CoglSubTexture and %FALSE otherwise. + * + * Since: 1.10 + * Stability: unstable + */ +CoglBool +cogl_is_sub_texture (void *object); + +COGL_END_DECLS + +#endif /* __COGL_SUB_TEXTURE_H */ diff --git a/cogl/cogl/cogl-swap-chain-private.h b/cogl/cogl/cogl-swap-chain-private.h new file mode 100644 index 0000000..c67e6f0 --- /dev/null +++ b/cogl/cogl/cogl-swap-chain-private.h @@ -0,0 +1,45 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_SWAP_CHAIN_PRIVATE_H +#define __COGL_SWAP_CHAIN_PRIVATE_H + +#include "cogl-object-private.h" + +struct _CoglSwapChain +{ + CoglObject _parent; + + CoglBool has_alpha; + + int length; +}; + +#endif /* __COGL_SWAP_CHAIN_PRIVATE_H */ diff --git a/cogl/cogl/cogl-swap-chain.c b/cogl/cogl/cogl-swap-chain.c new file mode 100644 index 0000000..558dad2 --- /dev/null +++ b/cogl/cogl/cogl-swap-chain.c @@ -0,0 +1,76 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-object.h" + +#include "cogl-swap-chain-private.h" +#include "cogl-swap-chain.h" +#include "cogl-gtype-private.h" + +static void _cogl_swap_chain_free (CoglSwapChain *swap_chain); + +COGL_OBJECT_DEFINE (SwapChain, swap_chain); +COGL_GTYPE_DEFINE_CLASS (SwapChain, swap_chain); + + +static void +_cogl_swap_chain_free (CoglSwapChain *swap_chain) +{ + g_slice_free (CoglSwapChain, swap_chain); +} + +CoglSwapChain * +cogl_swap_chain_new (void) +{ + CoglSwapChain *swap_chain = g_slice_new0 (CoglSwapChain); + + swap_chain->length = -1; /* no preference */ + + return _cogl_swap_chain_object_new (swap_chain); +} + +void +cogl_swap_chain_set_has_alpha (CoglSwapChain *swap_chain, + CoglBool has_alpha) +{ + swap_chain->has_alpha = has_alpha; +} + +void +cogl_swap_chain_set_length (CoglSwapChain *swap_chain, + int length) +{ + swap_chain->length = length; +} diff --git a/cogl/cogl/cogl-swap-chain.h b/cogl/cogl/cogl-swap-chain.h new file mode 100644 index 0000000..dd854bc --- /dev/null +++ b/cogl/cogl/cogl-swap-chain.h @@ -0,0 +1,67 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_SWAP_CHAIN_H__ +#define __COGL_SWAP_CHAIN_H__ + +#include + +#include + +COGL_BEGIN_DECLS + +typedef struct _CoglSwapChain CoglSwapChain; + +/** + * cogl_swap_chain_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_swap_chain_get_gtype (void); + +CoglSwapChain * +cogl_swap_chain_new (void); + +void +cogl_swap_chain_set_has_alpha (CoglSwapChain *swap_chain, + CoglBool has_alpha); + +void +cogl_swap_chain_set_length (CoglSwapChain *swap_chain, + int length); + +CoglBool +cogl_is_swap_chain (void *object); + +COGL_END_DECLS + +#endif /* __COGL_SWAP_CHAIN_H__ */ diff --git a/cogl/cogl/cogl-texture-2d-gl.h b/cogl/cogl/cogl-texture-2d-gl.h new file mode 100644 index 0000000..e7b22df --- /dev/null +++ b/cogl/cogl/cogl-texture-2d-gl.h @@ -0,0 +1,78 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * Authors: + * Robert Bragg + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef _COGL_TEXTURE_2D_GL_H_ +#define _COGL_TEXTURE_2D_GL_H_ + +#include "cogl-context.h" +#include "cogl-texture-2d.h" + +COGL_BEGIN_DECLS + +/** + * cogl_texture_2d_gl_new_from_foreign: + * @ctx: A #CoglContext + * @gl_handle: A GL handle for a GL_TEXTURE_2D texture object + * @width: Width of the foreign GL texture + * @height: Height of the foreign GL texture + * @format: The format of the texture + * + * Wraps an existing GL_TEXTURE_2D texture object as a #CoglTexture2D. + * This can be used for integrating Cogl with software using OpenGL + * directly. + * + * The texture is still configurable until it has been allocated so + * for example you can declare whether the texture is premultiplied + * with cogl_texture_set_premultiplied(). + * + * The results are undefined for passing an invalid @gl_handle + * or if @width or @height don't have the correct texture + * geometry. + * + * Returns: (transfer full): A newly allocated #CoglTexture2D + * + * Since: 2.0 + */ +CoglTexture2D * +cogl_texture_2d_gl_new_from_foreign (CoglContext *ctx, + unsigned int gl_handle, + int width, + int height, + CoglPixelFormat format); + +COGL_END_DECLS + +#endif /* _COGL_TEXTURE_2D_GL_H_ */ diff --git a/cogl/cogl/cogl-texture-2d-private.h b/cogl/cogl/cogl-texture-2d-private.h new file mode 100644 index 0000000..27847af --- /dev/null +++ b/cogl/cogl/cogl-texture-2d-private.h @@ -0,0 +1,134 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_TEXTURE_2D_PRIVATE_H +#define __COGL_TEXTURE_2D_PRIVATE_H + +#include "cogl-object-private.h" +#include "cogl-pipeline-private.h" +#include "cogl-texture-private.h" +#include "cogl-texture-2d.h" + +#ifdef COGL_HAS_EGL_SUPPORT +#include "cogl-egl-defines.h" +#endif + +struct _CoglTexture2D +{ + CoglTexture _parent; + + /* The internal format of the GL texture represented as a + CoglPixelFormat */ + CoglPixelFormat internal_format; + + CoglBool auto_mipmap; + CoglBool mipmaps_dirty; + CoglBool is_foreign; + + /* TODO: factor out these OpenGL specific members into some form + * of driver private state. */ + + /* The internal format of the GL texture represented as a GL enum */ + GLenum gl_internal_format; + /* The texture object number */ + GLuint gl_texture; + GLenum gl_legacy_texobj_min_filter; + GLenum gl_legacy_texobj_mag_filter; + GLint gl_legacy_texobj_wrap_mode_s; + GLint gl_legacy_texobj_wrap_mode_t; + CoglTexturePixel first_pixel; +}; + +CoglTexture2D * +_cogl_texture_2d_new_from_bitmap (CoglBitmap *bmp, + CoglBool can_convert_in_place); + +#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base) +/* NB: The reason we require the width, height and format to be passed + * even though they may seem redundant is because GLES 1/2 don't + * provide a way to query these properties. */ +CoglTexture2D * +_cogl_egl_texture_2d_new_from_image (CoglContext *ctx, + int width, + int height, + CoglPixelFormat format, + EGLImageKHR image, + CoglError **error); +#endif + +CoglTexture2D * +_cogl_texture_2d_create_base (CoglContext *ctx, + int width, + int height, + CoglPixelFormat internal_format, + CoglTextureLoader *loader); + +void +_cogl_texture_2d_set_auto_mipmap (CoglTexture *tex, + CoglBool value); + +/* + * _cogl_texture_2d_externally_modified: + * @texture: A #CoglTexture2D object + * + * This should be called whenever the texture is modified other than + * by using cogl_texture_set_region. It will cause the mipmaps to be + * invalidated + */ +void +_cogl_texture_2d_externally_modified (CoglTexture *texture); + +/* + * _cogl_texture_2d_copy_from_framebuffer: + * @texture: A #CoglTexture2D pointer + * @src_x: X-position to within the framebuffer to read from + * @src_y: Y-position to within the framebuffer to read from + * @width: width of the rectangle to copy + * @height: height of the rectangle to copy + * @src_fb: A source #CoglFramebuffer to copy from + * @dst_x: X-position to store the image within the texture + * @dst_y: Y-position to store the image within the texture + * @level: The mipmap level of @texture to copy too + * + * This copies a portion of the given @src_fb into the + * texture. + */ +void +_cogl_texture_2d_copy_from_framebuffer (CoglTexture2D *texture, + int src_x, + int src_y, + int width, + int height, + CoglFramebuffer *src_fb, + int dst_x, + int dst_y, + int level); + +#endif /* __COGL_TEXTURE_2D_PRIVATE_H */ diff --git a/cogl/cogl/cogl-texture-2d-sliced-private.h b/cogl/cogl/cogl-texture-2d-sliced-private.h new file mode 100644 index 0000000..e827923 --- /dev/null +++ b/cogl/cogl/cogl-texture-2d-sliced-private.h @@ -0,0 +1,67 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_TEXTURE_2D_SLICED_PRIVATE_H +#define __COGL_TEXTURE_2D_SLICED_PRIVATE_H + +#include "cogl-bitmap-private.h" +#include "cogl-pipeline-private.h" +#include "cogl-texture-private.h" +#include "cogl-texture-2d-sliced.h" + +#include + +struct _CoglTexture2DSliced +{ + CoglTexture _parent; + + GArray *slice_x_spans; + GArray *slice_y_spans; + GArray *slice_textures; + int max_waste; + CoglPixelFormat internal_format; +}; + +CoglTexture2DSliced * +_cogl_texture_2d_sliced_new_from_foreign (CoglContext *context, + unsigned int gl_handle, + unsigned int gl_target, + int width, + int height, + int x_pot_waste, + int y_pot_waste, + CoglPixelFormat format); + +CoglTexture2DSliced * +_cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp, + int max_waste, + CoglBool can_convert_in_place); + +#endif /* __COGL_TEXTURE_2D_SLICED_PRIVATE_H */ diff --git a/cogl/cogl/cogl-texture-2d-sliced.c b/cogl/cogl/cogl-texture-2d-sliced.c new file mode 100644 index 0000000..4f586cd --- /dev/null +++ b/cogl/cogl/cogl-texture-2d-sliced.c @@ -0,0 +1,1546 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Matthew Allum + * Neil Roberts + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-debug.h" +#include "cogl-private.h" +#include "cogl-util.h" +#include "cogl-bitmap.h" +#include "cogl-bitmap-private.h" +#include "cogl-texture-private.h" +#include "cogl-texture-2d-gl.h" +#include "cogl-texture-2d-private.h" +#include "cogl-texture-2d-sliced-private.h" +#include "cogl-texture-gl-private.h" +#include "cogl-texture-driver.h" +#include "cogl-context-private.h" +#include "cogl-object-private.h" +#include "cogl-spans.h" +#include "cogl-journal-private.h" +#include "cogl-pipeline-opengl-private.h" +#include "cogl-primitive-texture.h" +#include "cogl-error-private.h" +#include "cogl-texture-gl-private.h" +#include "cogl-gtype-private.h" + +#include +#include +#include + +static void _cogl_texture_2d_sliced_free (CoglTexture2DSliced *tex_2ds); + +COGL_TEXTURE_DEFINE (Texture2DSliced, texture_2d_sliced); +COGL_GTYPE_DEFINE_CLASS (Texture2DSliced, texture_2d_sliced, + COGL_GTYPE_IMPLEMENT_INTERFACE (texture)); + +static const CoglTextureVtable cogl_texture_2d_sliced_vtable; + +typedef struct _ForeachData +{ + CoglMetaTextureCallback callback; + void *user_data; + float x_normalize_factor; + float y_normalize_factor; +} ForeachData; + +static void +re_normalize_sub_texture_coords_cb (CoglTexture *sub_texture, + const float *sub_texture_coords, + const float *meta_coords, + void *user_data) +{ + ForeachData *data = user_data; + /* The coordinates passed to the span iterating code were + * un-normalized so we need to renormalize them before passing them + * on */ + float re_normalized_coords[4] = + { + meta_coords[0] * data->x_normalize_factor, + meta_coords[1] * data->y_normalize_factor, + meta_coords[2] * data->x_normalize_factor, + meta_coords[3] * data->y_normalize_factor + }; + + data->callback (sub_texture, sub_texture_coords, re_normalized_coords, + data->user_data); +} + +static void +_cogl_texture_2d_sliced_foreach_sub_texture_in_region ( + CoglTexture *tex, + float virtual_tx_1, + float virtual_ty_1, + float virtual_tx_2, + float virtual_ty_2, + CoglMetaTextureCallback callback, + void *user_data) +{ + CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); + CoglSpan *x_spans = (CoglSpan *)tex_2ds->slice_x_spans->data; + CoglSpan *y_spans = (CoglSpan *)tex_2ds->slice_y_spans->data; + CoglTexture **textures = (CoglTexture **)tex_2ds->slice_textures->data; + float un_normalized_coords[4]; + ForeachData data; + + /* NB: its convenient for us to store non-normalized coordinates in + * our CoglSpans but that means we need to un-normalize the incoming + * virtual coordinates and make sure we re-normalize the coordinates + * before calling the given callback. + */ + + data.callback = callback; + data.user_data = user_data; + data.x_normalize_factor = 1.0f / tex->width; + data.y_normalize_factor = 1.0f / tex->height; + + un_normalized_coords[0] = virtual_tx_1 * tex->width; + un_normalized_coords[1] = virtual_ty_1 * tex->height; + un_normalized_coords[2] = virtual_tx_2 * tex->width; + un_normalized_coords[3] = virtual_ty_2 * tex->height; + + /* Note that the normalize factors passed here are the reciprocal of + * the factors calculated above because the span iterating code + * normalizes by dividing by the factor instead of multiplying */ + _cogl_texture_spans_foreach_in_region (x_spans, + tex_2ds->slice_x_spans->len, + y_spans, + tex_2ds->slice_y_spans->len, + textures, + un_normalized_coords, + tex->width, + tex->height, + COGL_PIPELINE_WRAP_MODE_REPEAT, + COGL_PIPELINE_WRAP_MODE_REPEAT, + re_normalize_sub_texture_coords_cb, + &data); +} + +static uint8_t * +_cogl_texture_2d_sliced_allocate_waste_buffer (CoglTexture2DSliced *tex_2ds, + CoglPixelFormat format) +{ + CoglSpan *last_x_span; + CoglSpan *last_y_span; + uint8_t *waste_buf = NULL; + + /* If the texture has any waste then allocate a buffer big enough to + fill the gaps */ + last_x_span = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, + tex_2ds->slice_x_spans->len - 1); + last_y_span = &g_array_index (tex_2ds->slice_y_spans, CoglSpan, + tex_2ds->slice_y_spans->len - 1); + if (last_x_span->waste > 0 || last_y_span->waste > 0) + { + int bpp = _cogl_pixel_format_get_bytes_per_pixel (format); + CoglSpan *first_x_span + = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, 0); + CoglSpan *first_y_span + = &g_array_index (tex_2ds->slice_y_spans, CoglSpan, 0); + unsigned int right_size = first_y_span->size * last_x_span->waste; + unsigned int bottom_size = first_x_span->size * last_y_span->waste; + + waste_buf = g_malloc (MAX (right_size, bottom_size) * bpp); + } + + return waste_buf; +} + +static CoglBool +_cogl_texture_2d_sliced_set_waste (CoglTexture2DSliced *tex_2ds, + CoglBitmap *source_bmp, + CoglTexture2D *slice_tex, + uint8_t *waste_buf, + CoglSpan *x_span, + CoglSpan *y_span, + CoglSpanIter *x_iter, + CoglSpanIter *y_iter, + int src_x, + int src_y, + int dst_x, + int dst_y, + CoglError **error) +{ + CoglBool need_x, need_y; + CoglContext *ctx = COGL_TEXTURE (tex_2ds)->context; + + /* If the x_span is sliced and the upload touches the + rightmost pixels then fill the waste with copies of the + pixels */ + need_x = x_span->waste > 0 && + x_iter->intersect_end - x_iter->pos >= x_span->size - x_span->waste; + + /* same for the bottom-most pixels */ + need_y = y_span->waste > 0 && + y_iter->intersect_end - y_iter->pos >= y_span->size - y_span->waste; + + if (need_x || need_y) + { + int bmp_rowstride = cogl_bitmap_get_rowstride (source_bmp); + CoglPixelFormat source_format = cogl_bitmap_get_format (source_bmp); + int bpp = _cogl_pixel_format_get_bytes_per_pixel (source_format); + uint8_t *bmp_data; + const uint8_t *src; + uint8_t *dst; + unsigned int wy, wx; + CoglBitmap *waste_bmp; + + bmp_data = _cogl_bitmap_map (source_bmp, COGL_BUFFER_ACCESS_READ, 0, error); + if (bmp_data == NULL) + return FALSE; + + if (need_x) + { + src = (bmp_data + ((src_y + (int) y_iter->intersect_start - dst_y) * + bmp_rowstride) + + (src_x + (int)x_span->start + (int)x_span->size - + (int)x_span->waste - dst_x - 1) * bpp); + + dst = waste_buf; + + for (wy = 0; + wy < y_iter->intersect_end - y_iter->intersect_start; + wy++) + { + for (wx = 0; wx < x_span->waste; wx++) + { + memcpy (dst, src, bpp); + dst += bpp; + } + src += bmp_rowstride; + } + + waste_bmp = cogl_bitmap_new_for_data (ctx, + x_span->waste, + y_iter->intersect_end - + y_iter->intersect_start, + source_format, + x_span->waste * bpp, + waste_buf); + + if (!_cogl_texture_set_region_from_bitmap (COGL_TEXTURE (slice_tex), + 0, /* src_x */ + 0, /* src_y */ + x_span->waste, /* width */ + /* height */ + y_iter->intersect_end - + y_iter->intersect_start, + waste_bmp, + /* dst_x */ + x_span->size - x_span->waste, + y_iter->intersect_start - + y_span->start, /* dst_y */ + 0, /* level */ + error)) + { + cogl_object_unref (waste_bmp); + _cogl_bitmap_unmap (source_bmp); + return FALSE; + } + + cogl_object_unref (waste_bmp); + } + + if (need_y) + { + unsigned int copy_width, intersect_width; + + src = (bmp_data + ((src_x + (int) x_iter->intersect_start - dst_x) * + bpp) + + (src_y + (int)y_span->start + (int)y_span->size - + (int)y_span->waste - dst_y - 1) * bmp_rowstride); + + dst = waste_buf; + + if (x_iter->intersect_end - x_iter->pos + >= x_span->size - x_span->waste) + copy_width = x_span->size + x_iter->pos - x_iter->intersect_start; + else + copy_width = x_iter->intersect_end - x_iter->intersect_start; + + intersect_width = x_iter->intersect_end - x_iter->intersect_start; + + for (wy = 0; wy < y_span->waste; wy++) + { + memcpy (dst, src, intersect_width * bpp); + dst += intersect_width * bpp; + + for (wx = intersect_width; wx < copy_width; wx++) + { + memcpy (dst, dst - bpp, bpp); + dst += bpp; + } + } + + waste_bmp = cogl_bitmap_new_for_data (ctx, + copy_width, + y_span->waste, + source_format, + copy_width * bpp, + waste_buf); + + if (!_cogl_texture_set_region_from_bitmap (COGL_TEXTURE (slice_tex), + 0, /* src_x */ + 0, /* src_y */ + copy_width, /* width */ + y_span->waste, /* height */ + waste_bmp, + /* dst_x */ + x_iter->intersect_start - + x_iter->pos, + /* dst_y */ + y_span->size - y_span->waste, + 0, /* level */ + error)) + { + cogl_object_unref (waste_bmp); + _cogl_bitmap_unmap (source_bmp); + return FALSE; + } + + cogl_object_unref (waste_bmp); + } + + _cogl_bitmap_unmap (source_bmp); + } + + return TRUE; +} + +static CoglBool +_cogl_texture_2d_sliced_upload_bitmap (CoglTexture2DSliced *tex_2ds, + CoglBitmap *bmp, + CoglError **error) +{ + CoglSpan *x_span; + CoglSpan *y_span; + CoglTexture2D *slice_tex; + int x, y; + uint8_t *waste_buf; + CoglPixelFormat bmp_format; + + bmp_format = cogl_bitmap_get_format (bmp); + + waste_buf = _cogl_texture_2d_sliced_allocate_waste_buffer (tex_2ds, + bmp_format); + + /* Iterate vertical slices */ + for (y = 0; y < tex_2ds->slice_y_spans->len; ++y) + { + y_span = &g_array_index (tex_2ds->slice_y_spans, CoglSpan, y); + + /* Iterate horizontal slices */ + for (x = 0; x < tex_2ds->slice_x_spans->len; ++x) + { + int slice_num = y * tex_2ds->slice_x_spans->len + x; + CoglSpanIter x_iter, y_iter; + + x_span = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, x); + + /* Pick the gl texture object handle */ + slice_tex = g_array_index (tex_2ds->slice_textures, + CoglTexture2D *, slice_num); + + if (!_cogl_texture_set_region_from_bitmap (COGL_TEXTURE (slice_tex), + x_span->start, /* src x */ + y_span->start, /* src y */ + x_span->size - + x_span->waste, /* width */ + y_span->size - + y_span->waste, /* height */ + bmp, + 0, /* dst x */ + 0, /* dst y */ + 0, /* level */ + error)) + { + if (waste_buf) + g_free (waste_buf); + return FALSE; + } + + /* Set up a fake iterator that covers the whole slice */ + x_iter.intersect_start = x_span->start; + x_iter.intersect_end = (x_span->start + + x_span->size - + x_span->waste); + x_iter.pos = x_span->start; + + y_iter.intersect_start = y_span->start; + y_iter.intersect_end = (y_span->start + + y_span->size - + y_span->waste); + y_iter.pos = y_span->start; + + if (!_cogl_texture_2d_sliced_set_waste (tex_2ds, + bmp, + slice_tex, + waste_buf, + x_span, y_span, + &x_iter, &y_iter, + 0, /* src_x */ + 0, /* src_y */ + 0, /* dst_x */ + 0, + error)) /* dst_y */ + { + if (waste_buf) + g_free (waste_buf); + return FALSE; + } + } + } + + if (waste_buf) + g_free (waste_buf); + + return TRUE; +} + +static CoglBool +_cogl_texture_2d_sliced_upload_subregion (CoglTexture2DSliced *tex_2ds, + int src_x, + int src_y, + int dst_x, + int dst_y, + int width, + int height, + CoglBitmap *source_bmp, + CoglError **error) +{ + CoglTexture *tex = COGL_TEXTURE (tex_2ds); + CoglSpan *x_span; + CoglSpan *y_span; + CoglSpanIter x_iter; + CoglSpanIter y_iter; + CoglTexture2D *slice_tex; + int source_x = 0, source_y = 0; + int inter_w = 0, inter_h = 0; + int local_x = 0, local_y = 0; + uint8_t *waste_buf; + CoglPixelFormat source_format; + + source_format = cogl_bitmap_get_format (source_bmp); + + waste_buf = + _cogl_texture_2d_sliced_allocate_waste_buffer (tex_2ds, source_format); + + /* Iterate vertical spans */ + for (source_y = src_y, + _cogl_span_iter_begin (&y_iter, + (CoglSpan *)tex_2ds->slice_y_spans->data, + tex_2ds->slice_y_spans->len, + tex->height, + dst_y, + dst_y + height, + COGL_PIPELINE_WRAP_MODE_REPEAT); + + !_cogl_span_iter_end (&y_iter); + + _cogl_span_iter_next (&y_iter), + source_y += inter_h ) + { + y_span = &g_array_index (tex_2ds->slice_y_spans, CoglSpan, + y_iter.index); + + /* Iterate horizontal spans */ + for (source_x = src_x, + _cogl_span_iter_begin (&x_iter, + (CoglSpan *)tex_2ds->slice_x_spans->data, + tex_2ds->slice_x_spans->len, + tex->width, + dst_x, + dst_x + width, + COGL_PIPELINE_WRAP_MODE_REPEAT); + + !_cogl_span_iter_end (&x_iter); + + _cogl_span_iter_next (&x_iter), + source_x += inter_w ) + { + int slice_num; + + x_span = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, + x_iter.index); + + /* Pick intersection width and height */ + inter_w = (x_iter.intersect_end - x_iter.intersect_start); + inter_h = (y_iter.intersect_end - y_iter.intersect_start); + + /* Localize intersection top-left corner to slice*/ + local_x = (x_iter.intersect_start - x_iter.pos); + local_y = (y_iter.intersect_start - y_iter.pos); + + slice_num = y_iter.index * tex_2ds->slice_x_spans->len + x_iter.index; + + /* Pick slice texture */ + slice_tex = g_array_index (tex_2ds->slice_textures, + CoglTexture2D *, slice_num); + + if (!_cogl_texture_set_region_from_bitmap (COGL_TEXTURE (slice_tex), + source_x, + source_y, + inter_w, /* width */ + inter_h, /* height */ + source_bmp, + local_x, /* dst x */ + local_y, /* dst y */ + 0, /* level */ + error)) + { + if (waste_buf) + g_free (waste_buf); + return FALSE; + } + + if (!_cogl_texture_2d_sliced_set_waste (tex_2ds, + source_bmp, + slice_tex, + waste_buf, + x_span, y_span, + &x_iter, &y_iter, + src_x, src_y, + dst_x, dst_y, + error)) + { + if (waste_buf) + g_free (waste_buf); + return FALSE; + } + } + } + + if (waste_buf) + g_free (waste_buf); + + return TRUE; +} + +static int +_cogl_rect_slices_for_size (int size_to_fill, + int max_span_size, + int max_waste, + GArray *out_spans) +{ + int n_spans = 0; + CoglSpan span; + + /* Init first slice span */ + span.start = 0; + span.size = max_span_size; + span.waste = 0; + + /* Repeat until whole area covered */ + while (size_to_fill >= span.size) + { + /* Add another slice span of same size */ + if (out_spans) + g_array_append_val (out_spans, span); + span.start += span.size; + size_to_fill -= span.size; + n_spans++; + } + + /* Add one last smaller slice span */ + if (size_to_fill > 0) + { + span.size = size_to_fill; + if (out_spans) + g_array_append_val (out_spans, span); + n_spans++; + } + + return n_spans; +} + +static int +_cogl_pot_slices_for_size (int size_to_fill, + int max_span_size, + int max_waste, + GArray *out_spans) +{ + int n_spans = 0; + CoglSpan span; + + /* Init first slice span */ + span.start = 0; + span.size = max_span_size; + span.waste = 0; + + /* Fix invalid max_waste */ + if (max_waste < 0) + max_waste = 0; + + while (TRUE) + { + /* Is the whole area covered? */ + if (size_to_fill > span.size) + { + /* Not yet - add a span of this size */ + if (out_spans) + g_array_append_val (out_spans, span); + + span.start += span.size; + size_to_fill -= span.size; + n_spans++; + } + else if (span.size - size_to_fill <= max_waste) + { + /* Yes and waste is small enough */ + /* Pick the next power of two up from size_to_fill. This can + sometimes be less than the span.size that would be chosen + otherwise */ + span.size = _cogl_util_next_p2 (size_to_fill); + span.waste = span.size - size_to_fill; + if (out_spans) + g_array_append_val (out_spans, span); + + return ++n_spans; + } + else + { + /* Yes but waste is too large */ + while (span.size - size_to_fill > max_waste) + { + span.size /= 2; + g_assert (span.size > 0); + } + } + } + + /* Can't get here */ + return 0; +} + +static void +_cogl_texture_2d_sliced_gl_flush_legacy_texobj_wrap_modes (CoglTexture *tex, + GLenum wrap_mode_s, + GLenum wrap_mode_t, + GLenum wrap_mode_p) +{ + CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); + int i; + + /* Pass the set wrap mode on to all of the child textures */ + for (i = 0; i < tex_2ds->slice_textures->len; i++) + { + CoglTexture2D *slice_tex = g_array_index (tex_2ds->slice_textures, + CoglTexture2D *, + i); + + _cogl_texture_gl_flush_legacy_texobj_wrap_modes (COGL_TEXTURE (slice_tex), + wrap_mode_s, + wrap_mode_t, + wrap_mode_p); + } +} + +static void +free_spans (CoglTexture2DSliced *tex_2ds) +{ + if (tex_2ds->slice_x_spans != NULL) + { + g_array_free (tex_2ds->slice_x_spans, TRUE); + tex_2ds->slice_x_spans = NULL; + } + + if (tex_2ds->slice_y_spans != NULL) + { + g_array_free (tex_2ds->slice_y_spans, TRUE); + tex_2ds->slice_y_spans = NULL; + } +} + +static CoglBool +setup_spans (CoglContext *ctx, + CoglTexture2DSliced *tex_2ds, + int width, + int height, + int max_waste, + CoglPixelFormat internal_format, + CoglError **error) +{ + int max_width; + int max_height; + int n_x_slices; + int n_y_slices; + + int (*slices_for_size) (int, int, int, GArray*); + + /* Initialize size of largest slice according to supported features */ + if (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT)) + { + max_width = width; + max_height = height; + slices_for_size = _cogl_rect_slices_for_size; + } + else + { + max_width = _cogl_util_next_p2 (width); + max_height = _cogl_util_next_p2 (height); + slices_for_size = _cogl_pot_slices_for_size; + } + + /* Negative number means no slicing forced by the user */ + if (max_waste <= -1) + { + CoglSpan span; + + /* Check if size supported else bail out */ + if (!ctx->driver_vtable->texture_2d_can_create (ctx, + max_width, + max_height, + internal_format)) + { + _cogl_set_error (error, + COGL_TEXTURE_ERROR, + COGL_TEXTURE_ERROR_SIZE, + "Sliced texture size of %d x %d not possible " + "with max waste set to -1", + width, + height); + return FALSE; + } + + n_x_slices = 1; + n_y_slices = 1; + + /* Init span arrays */ + tex_2ds->slice_x_spans = g_array_sized_new (FALSE, FALSE, + sizeof (CoglSpan), + 1); + + tex_2ds->slice_y_spans = g_array_sized_new (FALSE, FALSE, + sizeof (CoglSpan), + 1); + + /* Add a single span for width and height */ + span.start = 0; + span.size = max_width; + span.waste = max_width - width; + g_array_append_val (tex_2ds->slice_x_spans, span); + + span.size = max_height; + span.waste = max_height - height; + g_array_append_val (tex_2ds->slice_y_spans, span); + } + else + { + /* Decrease the size of largest slice until supported by GL */ + while (!ctx->driver_vtable->texture_2d_can_create (ctx, + max_width, + max_height, + internal_format)) + { + /* Alternate between width and height */ + if (max_width > max_height) + max_width /= 2; + else + max_height /= 2; + + if (max_width == 0 || max_height == 0) + { + /* Maybe it would be ok to just g_warn_if_reached() for this + * codepath */ + _cogl_set_error (error, + COGL_TEXTURE_ERROR, + COGL_TEXTURE_ERROR_SIZE, + "No suitable slice geometry found"); + free_spans (tex_2ds); + return FALSE; + } + } + + /* Determine the slices required to cover the bitmap area */ + n_x_slices = slices_for_size (width, + max_width, max_waste, + NULL); + + n_y_slices = slices_for_size (height, + max_height, max_waste, + NULL); + + /* Init span arrays with reserved size */ + tex_2ds->slice_x_spans = g_array_sized_new (FALSE, FALSE, + sizeof (CoglSpan), + n_x_slices); + + tex_2ds->slice_y_spans = g_array_sized_new (FALSE, FALSE, + sizeof (CoglSpan), + n_y_slices); + + /* Fill span arrays with info */ + slices_for_size (width, + max_width, max_waste, + tex_2ds->slice_x_spans); + + slices_for_size (height, + max_height, max_waste, + tex_2ds->slice_y_spans); + } + + return TRUE; +} + +static void +free_slices (CoglTexture2DSliced *tex_2ds) +{ + if (tex_2ds->slice_textures != NULL) + { + int i; + + for (i = 0; i < tex_2ds->slice_textures->len; i++) + { + CoglTexture2D *slice_tex = + g_array_index (tex_2ds->slice_textures, CoglTexture2D *, i); + cogl_object_unref (slice_tex); + } + + g_array_free (tex_2ds->slice_textures, TRUE); + } + + free_spans (tex_2ds); +} + +static CoglBool +allocate_slices (CoglTexture2DSliced *tex_2ds, + int width, + int height, + int max_waste, + CoglPixelFormat internal_format, + CoglError **error) +{ + CoglTexture *tex = COGL_TEXTURE (tex_2ds); + CoglContext *ctx = tex->context; + int n_x_slices; + int n_y_slices; + int n_slices; + int x, y; + CoglSpan *x_span; + CoglSpan *y_span; + + tex_2ds->internal_format = internal_format; + + if (!setup_spans (ctx, tex_2ds, + width, + height, + max_waste, + internal_format, + error)) + { + return FALSE; + } + + n_x_slices = tex_2ds->slice_x_spans->len; + n_y_slices = tex_2ds->slice_y_spans->len; + n_slices = n_x_slices * n_y_slices; + + tex_2ds->slice_textures = g_array_sized_new (FALSE, FALSE, + sizeof (CoglTexture2D *), + n_slices); + + /* Allocate each slice */ + for (y = 0; y < n_y_slices; ++y) + { + y_span = &g_array_index (tex_2ds->slice_y_spans, CoglSpan, y); + + for (x = 0; x < n_x_slices; ++x) + { + CoglTexture *slice; + + x_span = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, x); + + COGL_NOTE (SLICING, "CREATE SLICE (%d,%d)\tsize (%d,%d)", + x, y, + (int)(x_span->size - x_span->waste), + (int)(y_span->size - y_span->waste)); + + slice = COGL_TEXTURE ( + cogl_texture_2d_new_with_size (ctx, + x_span->size, y_span->size)); + + _cogl_texture_copy_internal_format (tex, slice); + + g_array_append_val (tex_2ds->slice_textures, slice); + if (!cogl_texture_allocate (slice, error)) + { + free_slices (tex_2ds); + return FALSE; + } + } + } + + return TRUE; +} + +static void +_cogl_texture_2d_sliced_free (CoglTexture2DSliced *tex_2ds) +{ + free_slices (tex_2ds); + + /* Chain up */ + _cogl_texture_free (COGL_TEXTURE (tex_2ds)); +} + +static CoglTexture2DSliced * +_cogl_texture_2d_sliced_create_base (CoglContext *ctx, + int width, + int height, + int max_waste, + CoglPixelFormat internal_format, + CoglTextureLoader *loader) +{ + CoglTexture2DSliced *tex_2ds = g_new0 (CoglTexture2DSliced, 1); + + _cogl_texture_init (COGL_TEXTURE (tex_2ds), ctx, width, height, + internal_format, loader, + &cogl_texture_2d_sliced_vtable); + + tex_2ds->max_waste = max_waste; + + return _cogl_texture_2d_sliced_object_new (tex_2ds); +} + +CoglTexture2DSliced * +cogl_texture_2d_sliced_new_with_size (CoglContext *ctx, + int width, + int height, + int max_waste) +{ + CoglTextureLoader *loader = _cogl_texture_create_loader (); + loader->src_type = COGL_TEXTURE_SOURCE_TYPE_SIZED; + loader->src.sized.width = width; + loader->src.sized.height = height; + + return _cogl_texture_2d_sliced_create_base (ctx, + width, + height, + max_waste, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + loader); +} + +CoglTexture2DSliced * +_cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp, + int max_waste, + CoglBool can_convert_in_place) +{ + CoglTextureLoader *loader; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_bitmap (bmp), NULL); + + loader = _cogl_texture_create_loader (); + loader->src_type = COGL_TEXTURE_SOURCE_TYPE_BITMAP; + loader->src.bitmap.bitmap = cogl_object_ref (bmp); + loader->src.bitmap.can_convert_in_place = can_convert_in_place; + + return _cogl_texture_2d_sliced_create_base (_cogl_bitmap_get_context (bmp), + cogl_bitmap_get_width (bmp), + cogl_bitmap_get_height (bmp), + max_waste, + cogl_bitmap_get_format (bmp), + loader); +} + +CoglTexture2DSliced * +cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp, + int max_waste) +{ + return _cogl_texture_2d_sliced_new_from_bitmap (bmp, + max_waste, + FALSE); +} + +CoglTexture2DSliced * +_cogl_texture_2d_sliced_new_from_foreign (CoglContext *ctx, + unsigned int gl_handle, + unsigned int gl_target, + int width, + int height, + int x_pot_waste, + int y_pot_waste, + CoglPixelFormat format) +{ + CoglTextureLoader *loader; + + /* NOTE: width, height and internal format are not queriable + * in GLES, hence such a function prototype. + */ + + /* This should only be called when the texture target is 2D. If a + rectangle texture is used then _cogl_texture_new_from_foreign + will create a cogl_texture_rectangle instead */ + _COGL_RETURN_VAL_IF_FAIL (gl_target == GL_TEXTURE_2D, NULL); + + /* Assert it is a valid GL texture object */ + _COGL_RETURN_VAL_IF_FAIL (ctx->glIsTexture (gl_handle), FALSE); + + /* Validate width and height */ + _COGL_RETURN_VAL_IF_FAIL (width > 0 && height > 0, NULL); + + /* Validate pot waste */ + _COGL_RETURN_VAL_IF_FAIL (x_pot_waste >= 0 && x_pot_waste < width && + y_pot_waste >= 0 && y_pot_waste < height, + NULL); + + loader = _cogl_texture_create_loader (); + loader->src_type = COGL_TEXTURE_SOURCE_TYPE_GL_FOREIGN; + loader->src.gl_foreign.gl_handle = gl_handle; + loader->src.gl_foreign.width = width + x_pot_waste; + loader->src.gl_foreign.height = height + y_pot_waste; + loader->src.gl_foreign.format = format; + + return _cogl_texture_2d_sliced_create_base (ctx, + width, + height, + 0, /* max waste */ + format, loader); +} + +CoglTexture2DSliced * +cogl_texture_2d_sliced_new_from_data (CoglContext *ctx, + int width, + int height, + int max_waste, + CoglPixelFormat format, + int rowstride, + const uint8_t *data, + CoglError **error) +{ + CoglBitmap *bmp; + CoglTexture2DSliced *tex_2ds; + + _COGL_RETURN_VAL_IF_FAIL (format != COGL_PIXEL_FORMAT_ANY, NULL); + _COGL_RETURN_VAL_IF_FAIL (data != NULL, NULL); + + /* Rowstride from width if not given */ + if (rowstride == 0) + rowstride = width * _cogl_pixel_format_get_bytes_per_pixel (format); + + /* Wrap the data into a bitmap */ + bmp = cogl_bitmap_new_for_data (ctx, + width, height, + format, + rowstride, + (uint8_t *) data); + + tex_2ds = cogl_texture_2d_sliced_new_from_bitmap (bmp, max_waste); + + cogl_object_unref (bmp); + + if (tex_2ds && + !cogl_texture_allocate (COGL_TEXTURE (tex_2ds), error)) + { + cogl_object_unref (tex_2ds); + return NULL; + } + + return tex_2ds; +} + +CoglTexture2DSliced * +cogl_texture_2d_sliced_new_from_file (CoglContext *ctx, + const char *filename, + int max_waste, + CoglError **error) +{ + CoglBitmap *bmp; + CoglTexture2DSliced *tex_2ds = NULL; + + _COGL_RETURN_VAL_IF_FAIL (error == NULL || *error == NULL, NULL); + + bmp = _cogl_bitmap_from_file (ctx, filename, error); + if (bmp == NULL) + return NULL; + + tex_2ds = _cogl_texture_2d_sliced_new_from_bitmap (bmp, + max_waste, + TRUE); /* can convert in-place */ + + cogl_object_unref (bmp); + + return tex_2ds; +} + +static CoglBool +allocate_with_size (CoglTexture2DSliced *tex_2ds, + CoglTextureLoader *loader, + CoglError **error) +{ + CoglTexture *tex = COGL_TEXTURE (tex_2ds); + CoglPixelFormat internal_format = + _cogl_texture_determine_internal_format (tex, COGL_PIXEL_FORMAT_ANY); + + if (allocate_slices (tex_2ds, + loader->src.sized.width, + loader->src.sized.height, + tex_2ds->max_waste, + internal_format, + error)) + { + _cogl_texture_set_allocated (COGL_TEXTURE (tex_2ds), + internal_format, + loader->src.sized.width, + loader->src.sized.height); + return TRUE; + } + else + return FALSE; +} + +static CoglBool +allocate_from_bitmap (CoglTexture2DSliced *tex_2ds, + CoglTextureLoader *loader, + CoglError **error) +{ + CoglTexture *tex = COGL_TEXTURE (tex_2ds); + CoglBitmap *bmp = loader->src.bitmap.bitmap; + int width = cogl_bitmap_get_width (bmp); + int height = cogl_bitmap_get_height (bmp); + CoglBool can_convert_in_place = loader->src.bitmap.can_convert_in_place; + CoglPixelFormat internal_format; + CoglBitmap *upload_bmp; + + _COGL_RETURN_VAL_IF_FAIL (tex_2ds->slice_textures == NULL, FALSE); + + internal_format = + _cogl_texture_determine_internal_format (tex, + cogl_bitmap_get_format (bmp)); + + upload_bmp = _cogl_bitmap_convert_for_upload (bmp, + internal_format, + can_convert_in_place, + error); + if (upload_bmp == NULL) + return FALSE; + + if (!allocate_slices (tex_2ds, + width, + height, + tex_2ds->max_waste, + internal_format, + error)) + { + cogl_object_unref (upload_bmp); + return FALSE; + } + + if (!_cogl_texture_2d_sliced_upload_bitmap (tex_2ds, + upload_bmp, + error)) + { + free_slices (tex_2ds); + cogl_object_unref (upload_bmp); + return FALSE; + } + + cogl_object_unref (upload_bmp); + + _cogl_texture_set_allocated (tex, internal_format, width, height); + + return TRUE; +} + +static CoglBool +allocate_from_gl_foreign (CoglTexture2DSliced *tex_2ds, + CoglTextureLoader *loader, + CoglError **error) +{ + CoglTexture *tex = COGL_TEXTURE (tex_2ds); + CoglContext *ctx = tex->context; + CoglPixelFormat format = loader->src.gl_foreign.format; + int gl_width = loader->src.gl_foreign.width; + int gl_height = loader->src.gl_foreign.height; + int x_pot_waste = gl_width - tex->width; + int y_pot_waste = gl_height - tex->height; + CoglSpan x_span; + CoglSpan y_span; + CoglTexture2D *tex_2d = + cogl_texture_2d_gl_new_from_foreign (ctx, + loader->src.gl_foreign.gl_handle, + gl_width, + gl_height, + format); + + if (!cogl_texture_allocate (COGL_TEXTURE (tex_2d), error)) + { + cogl_object_unref (tex_2d); + return FALSE; + } + + /* The texture 2d backend may use a different pixel format if it + queries the actual texture so we'll refetch the format it + actually used */ + format = _cogl_texture_get_format (tex); + + tex_2ds->internal_format = format; + + /* Create slice arrays */ + tex_2ds->slice_x_spans = + g_array_sized_new (FALSE, FALSE, sizeof (CoglSpan), 1); + + tex_2ds->slice_y_spans = + g_array_sized_new (FALSE, FALSE, sizeof (CoglSpan), 1); + + tex_2ds->slice_textures = + g_array_sized_new (FALSE, FALSE, sizeof (CoglTexture2D *), 1); + + /* Store info for a single slice */ + x_span.start = 0; + x_span.size = gl_width; + x_span.waste = x_pot_waste; + g_array_append_val (tex_2ds->slice_x_spans, x_span); + + y_span.start = 0; + y_span.size = gl_height; + y_span.waste = y_pot_waste; + g_array_append_val (tex_2ds->slice_y_spans, y_span); + + g_array_append_val (tex_2ds->slice_textures, tex_2d); + + _cogl_texture_set_allocated (tex, + format, + tex->width, + tex->height); + + return TRUE; +} + +static CoglBool +_cogl_texture_2d_sliced_allocate (CoglTexture *tex, + CoglError **error) +{ + CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); + CoglTextureLoader *loader = tex->loader; + + _COGL_RETURN_VAL_IF_FAIL (loader, FALSE); + + switch (loader->src_type) + { + case COGL_TEXTURE_SOURCE_TYPE_SIZED: + return allocate_with_size (tex_2ds, loader, error); + case COGL_TEXTURE_SOURCE_TYPE_BITMAP: + return allocate_from_bitmap (tex_2ds, loader, error); + case COGL_TEXTURE_SOURCE_TYPE_GL_FOREIGN: + return allocate_from_gl_foreign (tex_2ds, loader, error); + default: + break; + } + + g_return_val_if_reached (FALSE); +} + +static CoglBool +_cogl_texture_2d_sliced_is_foreign (CoglTexture *tex) +{ + CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); + CoglTexture2D *slice_tex; + + /* Make sure slices were created */ + if (tex_2ds->slice_textures == NULL) + return FALSE; + + /* Pass the call on to the first slice */ + slice_tex = g_array_index (tex_2ds->slice_textures, CoglTexture2D *, 0); + return _cogl_texture_is_foreign (COGL_TEXTURE (slice_tex)); +} + +static int +_cogl_texture_2d_sliced_get_max_waste (CoglTexture *tex) +{ + CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); + + return tex_2ds->max_waste; +} + +static CoglBool +_cogl_texture_2d_sliced_is_sliced (CoglTexture *tex) +{ + CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); + + /* It's only after allocating a sliced texture that we will know + * whether it really needed to be sliced... */ + if (!tex->allocated) + cogl_texture_allocate (tex, NULL); + + if (tex_2ds->slice_x_spans->len != 1 || + tex_2ds->slice_y_spans->len != 1) + return TRUE; + else + return FALSE; +} + +static CoglBool +_cogl_texture_2d_sliced_can_hardware_repeat (CoglTexture *tex) +{ + CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); + CoglTexture2D *slice_tex; + CoglSpan *x_span; + CoglSpan *y_span; + + /* If there's more than one texture then we can't hardware repeat */ + if (tex_2ds->slice_textures->len != 1) + return FALSE; + + /* If there's any waste then we can't hardware repeat */ + x_span = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, 0); + y_span = &g_array_index (tex_2ds->slice_y_spans, CoglSpan, 0); + if (x_span->waste > 0 || y_span->waste > 0) + return FALSE; + + /* Otherwise pass the query on to the single slice texture */ + slice_tex = g_array_index (tex_2ds->slice_textures, CoglTexture2D *, 0); + return _cogl_texture_can_hardware_repeat (COGL_TEXTURE (slice_tex)); +} + +static void +_cogl_texture_2d_sliced_transform_coords_to_gl (CoglTexture *tex, + float *s, + float *t) +{ + CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); + CoglSpan *x_span; + CoglSpan *y_span; + CoglTexture2D *slice_tex; + + g_assert (!_cogl_texture_2d_sliced_is_sliced (tex)); + + /* Don't include the waste in the texture coordinates */ + x_span = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, 0); + y_span = &g_array_index (tex_2ds->slice_y_spans, CoglSpan, 0); + + *s *= tex->width / (float)x_span->size; + *t *= tex->height / (float)y_span->size; + + /* Let the child texture further transform the coords */ + slice_tex = g_array_index (tex_2ds->slice_textures, CoglTexture2D *, 0); + _cogl_texture_transform_coords_to_gl (COGL_TEXTURE (slice_tex), s, t); +} + +static CoglTransformResult +_cogl_texture_2d_sliced_transform_quad_coords_to_gl (CoglTexture *tex, + float *coords) +{ + CoglBool need_repeat = FALSE; + int i; + + /* This is a bit lazy - in the case where the quad lies entirely + * within a single slice we could avoid the fallback. But that + * could likely lead to visual inconsistency if the fallback involves + * dropping layers, so this might be the right thing to do anyways. + */ + if (_cogl_texture_2d_sliced_is_sliced (tex)) + return COGL_TRANSFORM_SOFTWARE_REPEAT; + + for (i = 0; i < 4; i++) + if (coords[i] < 0.0f || coords[i] > 1.0f) + need_repeat = TRUE; + + if (need_repeat && !_cogl_texture_2d_sliced_can_hardware_repeat (tex)) + return COGL_TRANSFORM_SOFTWARE_REPEAT; + + _cogl_texture_2d_sliced_transform_coords_to_gl (tex, coords + 0, coords + 1); + _cogl_texture_2d_sliced_transform_coords_to_gl (tex, coords + 2, coords + 3); + + return (need_repeat + ? COGL_TRANSFORM_HARDWARE_REPEAT : COGL_TRANSFORM_NO_REPEAT); +} + +static CoglBool +_cogl_texture_2d_sliced_get_gl_texture (CoglTexture *tex, + GLuint *out_gl_handle, + GLenum *out_gl_target) +{ + CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); + CoglTexture2D *slice_tex; + + if (tex_2ds->slice_textures == NULL) + return FALSE; + + if (tex_2ds->slice_textures->len < 1) + return FALSE; + + slice_tex = g_array_index (tex_2ds->slice_textures, CoglTexture2D *, 0); + + return cogl_texture_get_gl_texture (COGL_TEXTURE (slice_tex), + out_gl_handle, out_gl_target); +} + +static void +_cogl_texture_2d_sliced_gl_flush_legacy_texobj_filters (CoglTexture *tex, + GLenum min_filter, + GLenum mag_filter) +{ + CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); + CoglTexture2D *slice_tex; + int i; + + _COGL_RETURN_IF_FAIL (tex_2ds->slice_textures != NULL); + + /* Apply new filters to every slice. The slice texture itself should + cache the value and avoid resubmitting the same filter value to + GL */ + for (i = 0; i < tex_2ds->slice_textures->len; i++) + { + slice_tex = g_array_index (tex_2ds->slice_textures, CoglTexture2D *, i); + _cogl_texture_gl_flush_legacy_texobj_filters (COGL_TEXTURE (slice_tex), + min_filter, mag_filter); + } +} + +static void +_cogl_texture_2d_sliced_pre_paint (CoglTexture *tex, + CoglTexturePrePaintFlags flags) +{ + CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); + int i; + + _COGL_RETURN_IF_FAIL (tex_2ds->slice_textures != NULL); + + /* Pass the pre-paint on to every slice */ + for (i = 0; i < tex_2ds->slice_textures->len; i++) + { + CoglTexture2D *slice_tex = g_array_index (tex_2ds->slice_textures, + CoglTexture2D *, i); + _cogl_texture_pre_paint (COGL_TEXTURE (slice_tex), flags); + } +} + +static void +_cogl_texture_2d_sliced_ensure_non_quad_rendering (CoglTexture *tex) +{ + CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); + int i; + + _COGL_RETURN_IF_FAIL (tex_2ds->slice_textures != NULL); + + /* Pass the call on to every slice */ + for (i = 0; i < tex_2ds->slice_textures->len; i++) + { + CoglTexture2D *slice_tex = g_array_index (tex_2ds->slice_textures, + CoglTexture2D *, i); + _cogl_texture_ensure_non_quad_rendering (COGL_TEXTURE (slice_tex)); + } +} + +static CoglBool +_cogl_texture_2d_sliced_set_region (CoglTexture *tex, + int src_x, + int src_y, + int dst_x, + int dst_y, + int dst_width, + int dst_height, + int level, + CoglBitmap *bmp, + CoglError **error) +{ + CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); + CoglBitmap *upload_bmp; + CoglBool status; + + upload_bmp = _cogl_bitmap_convert_for_upload (bmp, + _cogl_texture_get_format (tex), + FALSE, /* can't convert in + place */ + error); + if (!upload_bmp) + return FALSE; + + status = _cogl_texture_2d_sliced_upload_subregion (tex_2ds, + src_x, src_y, + dst_x, dst_y, + dst_width, dst_height, + upload_bmp, + error); + cogl_object_unref (upload_bmp); + + return status; +} + +static CoglPixelFormat +_cogl_texture_2d_sliced_get_format (CoglTexture *tex) +{ + CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); + + return tex_2ds->internal_format; +} + +static GLenum +_cogl_texture_2d_sliced_get_gl_format (CoglTexture *tex) +{ + CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); + CoglTexture2D *slice_tex; + + /* Assert that we've allocated our slices at this point */ + cogl_texture_allocate (tex, NULL); /* (abort on error) */ + + /* Pass the call on to the first slice */ + slice_tex = g_array_index (tex_2ds->slice_textures, CoglTexture2D *, 0); + return _cogl_texture_gl_get_format (COGL_TEXTURE (slice_tex)); +} + +static CoglTextureType +_cogl_texture_2d_sliced_get_type (CoglTexture *tex) +{ + return COGL_TEXTURE_TYPE_2D; +} + +static const CoglTextureVtable +cogl_texture_2d_sliced_vtable = + { + FALSE, /* not primitive */ + _cogl_texture_2d_sliced_allocate, + _cogl_texture_2d_sliced_set_region, + NULL, /* get_data */ + _cogl_texture_2d_sliced_foreach_sub_texture_in_region, + _cogl_texture_2d_sliced_get_max_waste, + _cogl_texture_2d_sliced_is_sliced, + _cogl_texture_2d_sliced_can_hardware_repeat, + _cogl_texture_2d_sliced_transform_coords_to_gl, + _cogl_texture_2d_sliced_transform_quad_coords_to_gl, + _cogl_texture_2d_sliced_get_gl_texture, + _cogl_texture_2d_sliced_gl_flush_legacy_texobj_filters, + _cogl_texture_2d_sliced_pre_paint, + _cogl_texture_2d_sliced_ensure_non_quad_rendering, + _cogl_texture_2d_sliced_gl_flush_legacy_texobj_wrap_modes, + _cogl_texture_2d_sliced_get_format, + _cogl_texture_2d_sliced_get_gl_format, + _cogl_texture_2d_sliced_get_type, + _cogl_texture_2d_sliced_is_foreign, + NULL /* set_auto_mipmap */ + }; diff --git a/cogl/cogl/cogl-texture-2d-sliced.h b/cogl/cogl/cogl-texture-2d-sliced.h new file mode 100644 index 0000000..7208ef4 --- /dev/null +++ b/cogl/cogl/cogl-texture-2d-sliced.h @@ -0,0 +1,299 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_TEXURE_2D_SLICED_H +#define __COGL_TEXURE_2D_SLICED_H + +#include "cogl-context.h" +#include "cogl-types.h" + +/** + * SECTION:cogl-texture-2d-sliced + * @short_description: Functions for creating and manipulating 2D meta + * textures that may internally be comprised of + * multiple 2D textures with power-of-two sizes. + * + * These functions allow high-level meta textures (See the + * #CoglMetaTexture interface) to be allocated that may internally be + * comprised of multiple 2D texture "slices" with power-of-two sizes. + * + * This API can be useful when working with GPUs that don't have + * native support for non-power-of-two textures or if you want to load + * a texture that is larger than the GPUs maximum texture size limits. + * + * The algorithm for slicing works by first trying to map a virtual + * size to the next larger power-of-two size and then seeing how many + * wasted pixels that would result in. For example if you have a + * virtual texture that's 259 texels wide, the next pot size = 512 and + * the amount of waste would be 253 texels. If the amount of waste is + * above a max-waste threshold then we would next slice that texture + * into one that's 256 texels and then looking at how many more texels + * remain unallocated after that we choose the next power-of-two size. + * For the example of a 259 texel image that would mean having a 256 + * texel wide texture, leaving 3 texels unallocated so we'd then + * create a 4 texel wide texture - now there is only one texel of + * waste. The algorithm continues to slice the right most textures + * until the amount of waste is less than or equal to a specfied + * max-waste threshold. The same logic for slicing from left to right + * is also applied from top to bottom. + */ + +typedef struct _CoglTexture2DSliced CoglTexture2DSliced; +#define COGL_TEXTURE_2D_SLICED(X) ((CoglTexture2DSliced *)X) + +/** + * cogl_texture_2d_sliced_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_texture_2d_sliced_get_gtype (void); + +/** + * cogl_texture_2d_sliced_new_with_size: + * @ctx: A #CoglContext + * @width: The virtual width of your sliced texture. + * @height: The virtual height of your sliced texture. + * @max_waste: The threshold of how wide a strip of wasted texels + * are allowed along the right and bottom textures before + * they must be sliced to reduce the amount of waste. A + * negative can be passed to disable slicing. + * + * Creates a #CoglTexture2DSliced that may internally be comprised of + * 1 or more #CoglTexture2D textures depending on GPU limitations. + * For example if the GPU only supports power-of-two sized textures + * then a sliced texture will turn a non-power-of-two size into a + * combination of smaller power-of-two sized textures. If the + * requested texture size is larger than is supported by the hardware + * then the texture will be sliced into smaller textures that can be + * accessed by the hardware. + * + * @max_waste is used as a threshold for recursively slicing the + * right-most or bottom-most slices into smaller sizes until the + * wasted padding at the bottom and right of the textures is less than + * specified. A negative @max_waste will disable slicing. + * + * The storage for the texture is not allocated before this function + * returns. You can call cogl_texture_allocate() to explicitly + * allocate the underlying storage or let Cogl automatically allocate + * storage lazily. + * + * It's possible for the allocation of a sliced texture to fail + * later due to impossible slicing constraints if a negative + * @max_waste value is given. If the given virtual texture size size + * is larger than is supported by the hardware but slicing is disabled + * the texture size would be too large to handle. + * + * Returns: (transfer full): A new #CoglTexture2DSliced object with no storage + * allocated yet. + * + * Since: 1.10 + * Stability: unstable + */ +CoglTexture2DSliced * +cogl_texture_2d_sliced_new_with_size (CoglContext *ctx, + int width, + int height, + int max_waste); + +/** + * cogl_texture_2d_sliced_new_from_file: + * @ctx: A #CoglContext + * @filename: the file to load + * @max_waste: The threshold of how wide a strip of wasted texels + * are allowed along the right and bottom textures before + * they must be sliced to reduce the amount of waste. A + * negative can be passed to disable slicing. + * @error: A #CoglError to catch exceptional errors or %NULL + * + * Creates a #CoglTexture2DSliced from an image file. + * + * A #CoglTexture2DSliced may internally be comprised of 1 or more + * #CoglTexture2D textures depending on GPU limitations. For example + * if the GPU only supports power-of-two sized textures then a sliced + * texture will turn a non-power-of-two size into a combination of + * smaller power-of-two sized textures. If the requested texture size + * is larger than is supported by the hardware then the texture will + * be sliced into smaller textures that can be accessed by the + * hardware. + * + * @max_waste is used as a threshold for recursively slicing the + * right-most or bottom-most slices into smaller sizes until the + * wasted padding at the bottom and right of the textures is less than + * specified. A negative @max_waste will disable slicing. + * + * The storage for the texture is not allocated before this function + * returns. You can call cogl_texture_allocate() to explicitly + * allocate the underlying storage or let Cogl automatically allocate + * storage lazily. + * + * It's possible for the allocation of a sliced texture to fail + * later due to impossible slicing constraints if a negative + * @max_waste value is given. If the given virtual texture size is + * larger than is supported by the hardware but slicing is disabled + * the texture size would be too large to handle. + * + * Return value: (transfer full): A newly created #CoglTexture2DSliced + * or %NULL on failure and @error will be updated. + * + * Since: 1.16 + */ +CoglTexture2DSliced * +cogl_texture_2d_sliced_new_from_file (CoglContext *ctx, + const char *filename, + int max_waste, + CoglError **error); + +/** + * cogl_texture_2d_sliced_new_from_data: + * @ctx: A #CoglContext + * @width: width of texture in pixels + * @height: height of texture in pixels + * @format: the #CoglPixelFormat the buffer is stored in in RAM + * @max_waste: The threshold of how wide a strip of wasted texels + * are allowed along the right and bottom textures before + * they must be sliced to reduce the amount of waste. A + * negative can be passed to disable slicing. + * @rowstride: the memory offset in bytes between the start of each + * row in @data. A value of 0 will make Cogl automatically + * calculate @rowstride from @width and @format. + * @data: pointer the memory region where the source buffer resides + * @error: A #CoglError to catch exceptional errors or %NULL + * + * Creates a new #CoglTexture2DSliced texture based on data residing + * in memory. + * + * A #CoglTexture2DSliced may internally be comprised of 1 or more + * #CoglTexture2D textures depending on GPU limitations. For example + * if the GPU only supports power-of-two sized textures then a sliced + * texture will turn a non-power-of-two size into a combination of + * smaller power-of-two sized textures. If the requested texture size + * is larger than is supported by the hardware then the texture will + * be sliced into smaller textures that can be accessed by the + * hardware. + * + * @max_waste is used as a threshold for recursively slicing the + * right-most or bottom-most slices into smaller sizes until the + * wasted padding at the bottom and right of the textures is less than + * specified. A negative @max_waste will disable slicing. + * + * This api will always immediately allocate GPU memory for all + * the required texture slices and upload the given data so that the + * @data pointer does not need to remain valid once this function + * returns. This means it is not possible to configure the texture + * before it is allocated. If you do need to configure the texture + * before allocation (to specify constraints on the internal format + * for example) then you can instead create a #CoglBitmap for your + * data and use cogl_texture_2d_sliced_new_from_bitmap() or use + * cogl_texture_2d_sliced_new_with_size() and then upload data using + * cogl_texture_set_data() + * + * It's possible for the allocation of a sliced texture to fail + * due to impossible slicing constraints if a negative @max_waste + * value is given. If the given virtual texture size is larger than is + * supported by the hardware but slicing is disabled the texture size + * would be too large to handle. + * + * Return value: (transfer full): A newly created #CoglTexture2DSliced + * or %NULL on failure and @error will be updated. + * + * Since: 1.16 + */ +CoglTexture2DSliced * +cogl_texture_2d_sliced_new_from_data (CoglContext *ctx, + int width, + int height, + int max_waste, + CoglPixelFormat format, + int rowstride, + const uint8_t *data, + CoglError **error); + +/** + * cogl_texture_2d_sliced_new_from_bitmap: + * @bmp: A #CoglBitmap + * @max_waste: The threshold of how wide a strip of wasted texels + * are allowed along the right and bottom textures before + * they must be sliced to reduce the amount of waste. A + * negative can be passed to disable slicing. + * + * Creates a new #CoglTexture2DSliced texture based on data residing + * in a bitmap. + * + * A #CoglTexture2DSliced may internally be comprised of 1 or more + * #CoglTexture2D textures depending on GPU limitations. For example + * if the GPU only supports power-of-two sized textures then a sliced + * texture will turn a non-power-of-two size into a combination of + * smaller power-of-two sized textures. If the requested texture size + * is larger than is supported by the hardware then the texture will + * be sliced into smaller textures that can be accessed by the + * hardware. + * + * @max_waste is used as a threshold for recursively slicing the + * right-most or bottom-most slices into smaller sizes until the + * wasted padding at the bottom and right of the textures is less than + * specified. A negative @max_waste will disable slicing. + * + * The storage for the texture is not allocated before this function + * returns. You can call cogl_texture_allocate() to explicitly + * allocate the underlying storage or let Cogl automatically allocate + * storage lazily. + * + * It's possible for the allocation of a sliced texture to fail + * later due to impossible slicing constraints if a negative + * @max_waste value is given. If the given virtual texture size is + * larger than is supported by the hardware but slicing is disabled + * the texture size would be too large to handle. + * + * Return value: (transfer full): A newly created #CoglTexture2DSliced + * or %NULL on failure and @error will be updated. + * + * Since: 1.16 + */ +CoglTexture2DSliced * +cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp, + int max_waste); + +/** + * cogl_is_texture_2d_sliced: + * @object: A #CoglObject pointer + * + * Gets whether the given object references a #CoglTexture2DSliced. + * + * Return value: %TRUE if the object references a #CoglTexture2DSliced + * and %FALSE otherwise. + * Since: 1.10 + * Stability: unstable + */ +CoglBool +cogl_is_texture_2d_sliced (void *object); + +#endif /* __COGL_TEXURE_2D_SLICED_H */ diff --git a/cogl/cogl/cogl-texture-2d.c b/cogl/cogl/cogl-texture-2d.c new file mode 100644 index 0000000..447d33b --- /dev/null +++ b/cogl/cogl/cogl-texture-2d.c @@ -0,0 +1,695 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Neil Roberts + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-private.h" +#include "cogl-util.h" +#include "cogl-texture-private.h" +#include "cogl-texture-2d-private.h" +#include "cogl-texture-2d-gl-private.h" +#include "cogl-texture-driver.h" +#include "cogl-context-private.h" +#include "cogl-object-private.h" +#include "cogl-journal-private.h" +#include "cogl-pipeline-opengl-private.h" +#include "cogl-framebuffer-private.h" +#include "cogl-error-private.h" +#ifdef COGL_HAS_EGL_SUPPORT +#include "cogl-winsys-egl-private.h" +#endif +#include "cogl-gtype-private.h" + +#include +#include + +#ifdef COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT +#include "cogl-wayland-server.h" +#endif + +static void _cogl_texture_2d_free (CoglTexture2D *tex_2d); + +COGL_TEXTURE_DEFINE (Texture2D, texture_2d); +COGL_GTYPE_DEFINE_CLASS (Texture2D, texture_2d, + COGL_GTYPE_IMPLEMENT_INTERFACE (texture)); + +static const CoglTextureVtable cogl_texture_2d_vtable; + +typedef struct _CoglTexture2DManualRepeatData +{ + CoglTexture2D *tex_2d; + CoglMetaTextureCallback callback; + void *user_data; +} CoglTexture2DManualRepeatData; + +static void +_cogl_texture_2d_free (CoglTexture2D *tex_2d) +{ + CoglContext *ctx = COGL_TEXTURE (tex_2d)->context; + + ctx->driver_vtable->texture_2d_free (tex_2d); + + /* Chain up */ + _cogl_texture_free (COGL_TEXTURE (tex_2d)); +} + +void +_cogl_texture_2d_set_auto_mipmap (CoglTexture *tex, + CoglBool value) +{ + CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex); + + tex_2d->auto_mipmap = value; +} + +CoglTexture2D * +_cogl_texture_2d_create_base (CoglContext *ctx, + int width, + int height, + CoglPixelFormat internal_format, + CoglTextureLoader *loader) +{ + CoglTexture2D *tex_2d = g_new (CoglTexture2D, 1); + CoglTexture *tex = COGL_TEXTURE (tex_2d); + + _cogl_texture_init (tex, ctx, width, height, internal_format, loader, + &cogl_texture_2d_vtable); + + tex_2d->mipmaps_dirty = TRUE; + tex_2d->auto_mipmap = TRUE; + + tex_2d->is_foreign = FALSE; + + ctx->driver_vtable->texture_2d_init (tex_2d); + + return _cogl_texture_2d_object_new (tex_2d); +} + +CoglTexture2D * +cogl_texture_2d_new_with_size (CoglContext *ctx, + int width, + int height) +{ + CoglTextureLoader *loader; + + loader = _cogl_texture_create_loader (); + loader->src_type = COGL_TEXTURE_SOURCE_TYPE_SIZED; + loader->src.sized.width = width; + loader->src.sized.height = height; + + return _cogl_texture_2d_create_base (ctx, width, height, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, loader); +} + +static CoglBool +_cogl_texture_2d_allocate (CoglTexture *tex, + CoglError **error) +{ + CoglContext *ctx = tex->context; + + return ctx->driver_vtable->texture_2d_allocate (tex, error); +} + +CoglTexture2D * +_cogl_texture_2d_new_from_bitmap (CoglBitmap *bmp, + CoglBool can_convert_in_place) +{ + CoglTextureLoader *loader; + + _COGL_RETURN_VAL_IF_FAIL (bmp != NULL, NULL); + + loader = _cogl_texture_create_loader (); + loader->src_type = COGL_TEXTURE_SOURCE_TYPE_BITMAP; + loader->src.bitmap.bitmap = cogl_object_ref (bmp); + loader->src.bitmap.can_convert_in_place = can_convert_in_place; + + return _cogl_texture_2d_create_base (_cogl_bitmap_get_context (bmp), + cogl_bitmap_get_width (bmp), + cogl_bitmap_get_height (bmp), + cogl_bitmap_get_format (bmp), + loader); +} + +CoglTexture2D * +cogl_texture_2d_new_from_bitmap (CoglBitmap *bmp) +{ + return _cogl_texture_2d_new_from_bitmap (bmp, + FALSE); /* can't convert in place */ +} + +CoglTexture2D * +cogl_texture_2d_new_from_file (CoglContext *ctx, + const char *filename, + CoglError **error) +{ + CoglBitmap *bmp; + CoglTexture2D *tex_2d = NULL; + + _COGL_RETURN_VAL_IF_FAIL (error == NULL || *error == NULL, NULL); + + bmp = _cogl_bitmap_from_file (ctx, filename, error); + if (bmp == NULL) + return NULL; + + tex_2d = _cogl_texture_2d_new_from_bitmap (bmp, + TRUE); /* can convert in-place */ + + cogl_object_unref (bmp); + + return tex_2d; +} + +CoglTexture2D * +cogl_texture_2d_new_from_data (CoglContext *ctx, + int width, + int height, + CoglPixelFormat format, + int rowstride, + const uint8_t *data, + CoglError **error) +{ + CoglBitmap *bmp; + CoglTexture2D *tex_2d; + + _COGL_RETURN_VAL_IF_FAIL (format != COGL_PIXEL_FORMAT_ANY, NULL); + _COGL_RETURN_VAL_IF_FAIL (data != NULL, NULL); + + /* Rowstride from width if not given */ + if (rowstride == 0) + rowstride = width * _cogl_pixel_format_get_bytes_per_pixel (format); + + /* Wrap the data into a bitmap */ + bmp = cogl_bitmap_new_for_data (ctx, + width, height, + format, + rowstride, + (uint8_t *) data); + + tex_2d = cogl_texture_2d_new_from_bitmap (bmp); + + cogl_object_unref (bmp); + + if (tex_2d && + !cogl_texture_allocate (COGL_TEXTURE (tex_2d), error)) + { + cogl_object_unref (tex_2d); + return NULL; + } + + return tex_2d; +} + +#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base) +/* NB: The reason we require the width, height and format to be passed + * even though they may seem redundant is because GLES 1/2 don't + * provide a way to query these properties. */ +CoglTexture2D * +_cogl_egl_texture_2d_new_from_image (CoglContext *ctx, + int width, + int height, + CoglPixelFormat format, + EGLImageKHR image, + CoglError **error) +{ + CoglTextureLoader *loader; + CoglTexture2D *tex; + + _COGL_RETURN_VAL_IF_FAIL (_cogl_context_get_winsys (ctx)->constraints & + COGL_RENDERER_CONSTRAINT_USES_EGL, + NULL); + + _COGL_RETURN_VAL_IF_FAIL (_cogl_has_private_feature + (ctx, + COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE), + NULL); + + loader = _cogl_texture_create_loader (); + loader->src_type = COGL_TEXTURE_SOURCE_TYPE_EGL_IMAGE; + loader->src.egl_image.image = image; + loader->src.egl_image.width = width; + loader->src.egl_image.height = height; + loader->src.egl_image.format = format; + + tex = _cogl_texture_2d_create_base (ctx, width, height, format, loader); + + if (!cogl_texture_allocate (COGL_TEXTURE (tex), error)) + { + cogl_object_unref (tex); + return NULL; + } + + return tex; +} +#endif /* defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base) */ + +#ifdef COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT +static void +shm_buffer_get_cogl_pixel_format (struct wl_shm_buffer *shm_buffer, + CoglPixelFormat *format_out, + CoglTextureComponents *components_out) +{ + CoglPixelFormat format; + CoglTextureComponents components = COGL_TEXTURE_COMPONENTS_RGBA; + + switch (wl_shm_buffer_get_format (shm_buffer)) + { +#if G_BYTE_ORDER == G_BIG_ENDIAN + case WL_SHM_FORMAT_ARGB8888: + format = COGL_PIXEL_FORMAT_ARGB_8888_PRE; + break; + case WL_SHM_FORMAT_XRGB8888: + format = COGL_PIXEL_FORMAT_ARGB_8888; + components = COGL_TEXTURE_COMPONENTS_RGB; + break; +#elif G_BYTE_ORDER == G_LITTLE_ENDIAN + case WL_SHM_FORMAT_ARGB8888: + format = COGL_PIXEL_FORMAT_BGRA_8888_PRE; + break; + case WL_SHM_FORMAT_XRGB8888: + format = COGL_PIXEL_FORMAT_BGRA_8888; + components = COGL_TEXTURE_COMPONENTS_RGB; + break; +#endif + default: + g_warn_if_reached (); + format = COGL_PIXEL_FORMAT_ARGB_8888; + } + + if (format_out) + *format_out = format; + if (components_out) + *components_out = components; +} + +CoglBool +cogl_wayland_texture_set_region_from_shm_buffer (CoglTexture *texture, + int src_x, + int src_y, + int width, + int height, + struct wl_shm_buffer * + shm_buffer, + int dst_x, + int dst_y, + int level, + CoglError **error) +{ + const uint8_t *data = wl_shm_buffer_get_data (shm_buffer); + int32_t stride = wl_shm_buffer_get_stride (shm_buffer); + CoglPixelFormat format; + int bpp; + + shm_buffer_get_cogl_pixel_format (shm_buffer, &format, NULL); + bpp = _cogl_pixel_format_get_bytes_per_pixel (format); + + return _cogl_texture_set_region (COGL_TEXTURE (texture), + width, height, + format, + stride, + data + src_x * bpp + src_y * stride, + dst_x, dst_y, + level, + error); +} + +CoglTexture2D * +cogl_wayland_texture_2d_new_from_buffer (CoglContext *ctx, + struct wl_resource *buffer, + CoglError **error) +{ + struct wl_shm_buffer *shm_buffer; + CoglTexture2D *tex = NULL; + + shm_buffer = wl_shm_buffer_get (buffer); + + if (shm_buffer) + { + int stride = wl_shm_buffer_get_stride (shm_buffer); + int width = wl_shm_buffer_get_width (shm_buffer); + int height = wl_shm_buffer_get_height (shm_buffer); + CoglPixelFormat format; + CoglTextureComponents components; + CoglBitmap *bmp; + + shm_buffer_get_cogl_pixel_format (shm_buffer, &format, &components); + + bmp = cogl_bitmap_new_for_data (ctx, + width, height, + format, + stride, + wl_shm_buffer_get_data (shm_buffer)); + + tex = cogl_texture_2d_new_from_bitmap (bmp); + + cogl_texture_set_components (COGL_TEXTURE (tex), components); + + cogl_object_unref (bmp); + + if (!cogl_texture_allocate (COGL_TEXTURE (tex), error)) + { + cogl_object_unref (tex); + return NULL; + } + else + return tex; + } + else + { + int format, width, height; + + if (_cogl_egl_query_wayland_buffer (ctx, + buffer, + EGL_TEXTURE_FORMAT, + &format) && + _cogl_egl_query_wayland_buffer (ctx, + buffer, + EGL_WIDTH, + &width) && + _cogl_egl_query_wayland_buffer (ctx, + buffer, + EGL_HEIGHT, + &height)) + { + EGLImageKHR image; + CoglPixelFormat internal_format; + + _COGL_RETURN_VAL_IF_FAIL (_cogl_context_get_winsys (ctx)->constraints & + COGL_RENDERER_CONSTRAINT_USES_EGL, + NULL); + + switch (format) + { + case EGL_TEXTURE_RGB: + internal_format = COGL_PIXEL_FORMAT_RGB_888; + break; + case EGL_TEXTURE_RGBA: + internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE; + break; + default: + _cogl_set_error (error, + COGL_SYSTEM_ERROR, + COGL_SYSTEM_ERROR_UNSUPPORTED, + "Can't create texture from unknown " + "wayland buffer format %d\n", format); + return NULL; + } + + image = _cogl_egl_create_image (ctx, + EGL_WAYLAND_BUFFER_WL, + buffer, + NULL); + tex = _cogl_egl_texture_2d_new_from_image (ctx, + width, height, + internal_format, + image, + error); + _cogl_egl_destroy_image (ctx, image); + return tex; + } + } + + _cogl_set_error (error, + COGL_SYSTEM_ERROR, + COGL_SYSTEM_ERROR_UNSUPPORTED, + "Can't create texture from unknown " + "wayland buffer type\n"); + return NULL; +} +#endif /* COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT */ + +void +_cogl_texture_2d_externally_modified (CoglTexture *texture) +{ + if (!cogl_is_texture_2d (texture)) + return; + + COGL_TEXTURE_2D (texture)->mipmaps_dirty = TRUE; +} + +void +_cogl_texture_2d_copy_from_framebuffer (CoglTexture2D *tex_2d, + int src_x, + int src_y, + int width, + int height, + CoglFramebuffer *src_fb, + int dst_x, + int dst_y, + int level) +{ + CoglTexture *tex = COGL_TEXTURE (tex_2d); + CoglContext *ctx = tex->context; + + /* Assert that the storage for this texture has been allocated */ + cogl_texture_allocate (tex, NULL); /* (abort on error) */ + + ctx->driver_vtable->texture_2d_copy_from_framebuffer (tex_2d, + src_x, + src_y, + width, + height, + src_fb, + dst_x, + dst_y, + level); + + tex_2d->mipmaps_dirty = TRUE; +} + +static int +_cogl_texture_2d_get_max_waste (CoglTexture *tex) +{ + return -1; +} + +static CoglBool +_cogl_texture_2d_is_sliced (CoglTexture *tex) +{ + return FALSE; +} + +static CoglBool +_cogl_texture_2d_can_hardware_repeat (CoglTexture *tex) +{ + CoglContext *ctx = tex->context; + + if (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_REPEAT) || + (_cogl_util_is_pot (tex->width) && + _cogl_util_is_pot (tex->height))) + return TRUE; + else + return FALSE; +} + +static void +_cogl_texture_2d_transform_coords_to_gl (CoglTexture *tex, + float *s, + float *t) +{ + /* The texture coordinates map directly so we don't need to do + anything */ +} + +static CoglTransformResult +_cogl_texture_2d_transform_quad_coords_to_gl (CoglTexture *tex, + float *coords) +{ + /* The texture coordinates map directly so we don't need to do + anything other than check for repeats */ + + int i; + + for (i = 0; i < 4; i++) + if (coords[i] < 0.0f || coords[i] > 1.0f) + { + /* Repeat is needed */ + return (_cogl_texture_2d_can_hardware_repeat (tex) ? + COGL_TRANSFORM_HARDWARE_REPEAT : + COGL_TRANSFORM_SOFTWARE_REPEAT); + } + + /* No repeat is needed */ + return COGL_TRANSFORM_NO_REPEAT; +} + +static CoglBool +_cogl_texture_2d_get_gl_texture (CoglTexture *tex, + GLuint *out_gl_handle, + GLenum *out_gl_target) +{ + CoglContext *ctx = tex->context; + CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex); + + if (ctx->driver_vtable->texture_2d_get_gl_handle) + { + GLuint handle; + + if (out_gl_target) + *out_gl_target = GL_TEXTURE_2D; + + handle = ctx->driver_vtable->texture_2d_get_gl_handle (tex_2d); + + if (out_gl_handle) + *out_gl_handle = handle; + + return handle ? TRUE : FALSE; + } + else + return FALSE; +} + +static void +_cogl_texture_2d_pre_paint (CoglTexture *tex, CoglTexturePrePaintFlags flags) +{ + CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex); + + /* Only update if the mipmaps are dirty */ + if ((flags & COGL_TEXTURE_NEEDS_MIPMAP) && + tex_2d->auto_mipmap && tex_2d->mipmaps_dirty) + { + CoglContext *ctx = tex->context; + + ctx->driver_vtable->texture_2d_generate_mipmap (tex_2d); + + tex_2d->mipmaps_dirty = FALSE; + } +} + +static void +_cogl_texture_2d_ensure_non_quad_rendering (CoglTexture *tex) +{ + /* Nothing needs to be done */ +} + +static CoglBool +_cogl_texture_2d_set_region (CoglTexture *tex, + int src_x, + int src_y, + int dst_x, + int dst_y, + int width, + int height, + int level, + CoglBitmap *bmp, + CoglError **error) +{ + CoglContext *ctx = tex->context; + CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex); + + if (!ctx->driver_vtable->texture_2d_copy_from_bitmap (tex_2d, + src_x, + src_y, + width, + height, + bmp, + dst_x, + dst_y, + level, + error)) + { + return FALSE; + } + + tex_2d->mipmaps_dirty = TRUE; + + return TRUE; +} + +static CoglBool +_cogl_texture_2d_get_data (CoglTexture *tex, + CoglPixelFormat format, + int rowstride, + uint8_t *data) +{ + CoglContext *ctx = tex->context; + + if (ctx->driver_vtable->texture_2d_get_data) + { + CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex); + ctx->driver_vtable->texture_2d_get_data (tex_2d, format, rowstride, data); + return TRUE; + } + else + return FALSE; +} + +static CoglPixelFormat +_cogl_texture_2d_get_format (CoglTexture *tex) +{ + return COGL_TEXTURE_2D (tex)->internal_format; +} + +static GLenum +_cogl_texture_2d_get_gl_format (CoglTexture *tex) +{ + return COGL_TEXTURE_2D (tex)->gl_internal_format; +} + +static CoglBool +_cogl_texture_2d_is_foreign (CoglTexture *tex) +{ + return COGL_TEXTURE_2D (tex)->is_foreign; +} + +static CoglTextureType +_cogl_texture_2d_get_type (CoglTexture *tex) +{ + return COGL_TEXTURE_TYPE_2D; +} + +static const CoglTextureVtable +cogl_texture_2d_vtable = + { + TRUE, /* primitive */ + _cogl_texture_2d_allocate, + _cogl_texture_2d_set_region, + _cogl_texture_2d_get_data, + NULL, /* foreach_sub_texture_in_region */ + _cogl_texture_2d_get_max_waste, + _cogl_texture_2d_is_sliced, + _cogl_texture_2d_can_hardware_repeat, + _cogl_texture_2d_transform_coords_to_gl, + _cogl_texture_2d_transform_quad_coords_to_gl, + _cogl_texture_2d_get_gl_texture, + _cogl_texture_2d_gl_flush_legacy_texobj_filters, + _cogl_texture_2d_pre_paint, + _cogl_texture_2d_ensure_non_quad_rendering, + _cogl_texture_2d_gl_flush_legacy_texobj_wrap_modes, + _cogl_texture_2d_get_format, + _cogl_texture_2d_get_gl_format, + _cogl_texture_2d_get_type, + _cogl_texture_2d_is_foreign, + _cogl_texture_2d_set_auto_mipmap + }; diff --git a/cogl/cogl/cogl-texture-2d.h b/cogl/cogl/cogl-texture-2d.h new file mode 100644 index 0000000..ee6c9d7 --- /dev/null +++ b/cogl/cogl/cogl-texture-2d.h @@ -0,0 +1,232 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011,2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * Authors: + * Robert Bragg + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_TEXTURE_2D_H +#define __COGL_TEXTURE_2D_H + +#include "cogl-context.h" +#include "cogl-bitmap.h" + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-texture-2d + * @short_description: Functions for creating and manipulating 2D textures + * + * These functions allow low-level 2D textures to be allocated. These + * differ from sliced textures for example which may internally be + * made up of multiple 2D textures, or atlas textures where Cogl must + * internally modify user texture coordinates before they can be used + * by the GPU. + * + * You should be aware that many GPUs only support power of two sizes + * for #CoglTexture2D textures. You can check support for non power of + * two textures by checking for the %COGL_FEATURE_ID_TEXTURE_NPOT feature + * via cogl_has_feature(). + */ + +typedef struct _CoglTexture2D CoglTexture2D; +#define COGL_TEXTURE_2D(X) ((CoglTexture2D *)X) + +/** + * cogl_texture_2d_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_texture_2d_get_gtype (void); + +/** + * cogl_is_texture_2d: + * @object: A #CoglObject + * + * Gets whether the given object references an existing #CoglTexture2D + * object. + * + * Return value: %TRUE if the object references a #CoglTexture2D, + * %FALSE otherwise + */ +CoglBool +cogl_is_texture_2d (void *object); + +/** + * cogl_texture_2d_new_with_size: + * @ctx: A #CoglContext + * @width: Width of the texture to allocate + * @height: Height of the texture to allocate + * + * Creates a low-level #CoglTexture2D texture with a given @width and + * @height that your GPU can texture from directly. + * + * The storage for the texture is not allocated before this function + * returns. You can call cogl_texture_allocate() to explicitly + * allocate the underlying storage or preferably let Cogl + * automatically allocate storage lazily when it may know more about + * how the texture is being used and can optimize how it is allocated. + * + * The texture is still configurable until it has been allocated so + * for example you can influence the internal format of the texture + * using cogl_texture_set_components() and + * cogl_texture_set_premultiplied(). + * + * Many GPUs only support power of two sizes for #CoglTexture2D + * textures. You can check support for non power of two textures by + * checking for the %COGL_FEATURE_ID_TEXTURE_NPOT feature via + * cogl_has_feature(). + * + * Returns: (transfer full): A new #CoglTexture2D object with no storage yet allocated. + * + * Since: 2.0 + */ +CoglTexture2D * +cogl_texture_2d_new_with_size (CoglContext *ctx, + int width, + int height); + +/** + * cogl_texture_2d_new_from_file: + * @ctx: A #CoglContext + * @filename: the file to load + * @error: A #CoglError to catch exceptional errors or %NULL + * + * Creates a low-level #CoglTexture2D texture from an image file. + * + * The storage for the texture is not allocated before this function + * returns. You can call cogl_texture_allocate() to explicitly + * allocate the underlying storage or preferably let Cogl + * automatically allocate storage lazily when it may know more about + * how the texture is being used and can optimize how it is allocated. + * + * The texture is still configurable until it has been allocated so + * for example you can influence the internal format of the texture + * using cogl_texture_set_components() and + * cogl_texture_set_premultiplied(). + * + * Many GPUs only support power of two sizes for #CoglTexture2D + * textures. You can check support for non power of two textures by + * checking for the %COGL_FEATURE_ID_TEXTURE_NPOT feature via + * cogl_has_feature(). + * + * Return value: (transfer full): A newly created #CoglTexture2D or %NULL on failure + * and @error will be updated. + * + * Since: 1.16 + */ +CoglTexture2D * +cogl_texture_2d_new_from_file (CoglContext *ctx, + const char *filename, + CoglError **error); + +/** + * cogl_texture_2d_new_from_data: + * @ctx: A #CoglContext + * @width: width of texture in pixels + * @height: height of texture in pixels + * @format: the #CoglPixelFormat the buffer is stored in in RAM + * @rowstride: the memory offset in bytes between the starts of + * scanlines in @data. A value of 0 will make Cogl automatically + * calculate @rowstride from @width and @format. + * @data: pointer the memory region where the source buffer resides + * @error: A #CoglError for exceptions + * + * Creates a low-level #CoglTexture2D texture based on data residing + * in memory. + * + * This api will always immediately allocate GPU memory for the + * texture and upload the given data so that the @data pointer does + * not need to remain valid once this function returns. This means it + * is not possible to configure the texture before it is allocated. If + * you do need to configure the texture before allocation (to specify + * constraints on the internal format for example) then you can + * instead create a #CoglBitmap for your data and use + * cogl_texture_2d_new_from_bitmap() or use + * cogl_texture_2d_new_with_size() and then upload data using + * cogl_texture_set_data() + * + * Many GPUs only support power of two sizes for #CoglTexture2D + * textures. You can check support for non power of two textures by + * checking for the %COGL_FEATURE_ID_TEXTURE_NPOT feature via + * cogl_has_feature(). + * + * Returns: (transfer full): A newly allocated #CoglTexture2D, or if + * the size is not supported (because it is too large or a + * non-power-of-two size that the hardware doesn't support) + * it will return %NULL and set @error. + * + * Since: 2.0 + */ +CoglTexture2D * +cogl_texture_2d_new_from_data (CoglContext *ctx, + int width, + int height, + CoglPixelFormat format, + int rowstride, + const uint8_t *data, + CoglError **error); + +/** + * cogl_texture_2d_new_from_bitmap: + * @bitmap: A #CoglBitmap + * + * Creates a low-level #CoglTexture2D texture based on data residing + * in a #CoglBitmap. + * + * The storage for the texture is not allocated before this function + * returns. You can call cogl_texture_allocate() to explicitly + * allocate the underlying storage or preferably let Cogl + * automatically allocate storage lazily when it may know more about + * how the texture is being used and can optimize how it is allocated. + * + * The texture is still configurable until it has been allocated so + * for example you can influence the internal format of the texture + * using cogl_texture_set_components() and + * cogl_texture_set_premultiplied(). + * + * Many GPUs only support power of two sizes for #CoglTexture2D + * textures. You can check support for non power of two textures by + * checking for the %COGL_FEATURE_ID_TEXTURE_NPOT feature via + * cogl_has_feature(). + * + * Returns: (transfer full): A newly allocated #CoglTexture2D + * + * Since: 2.0 + * Stability: unstable + */ +CoglTexture2D * +cogl_texture_2d_new_from_bitmap (CoglBitmap *bitmap); + +COGL_END_DECLS + +#endif /* __COGL_TEXTURE_2D_H */ diff --git a/cogl/cogl/cogl-texture-3d-private.h b/cogl/cogl/cogl-texture-3d-private.h new file mode 100644 index 0000000..b6e0066 --- /dev/null +++ b/cogl/cogl/cogl-texture-3d-private.h @@ -0,0 +1,66 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Neil Roberts + */ + +#ifndef __COGL_TEXTURE_3D_PRIVATE_H +#define __COGL_TEXTURE_3D_PRIVATE_H + +#include "cogl-object-private.h" +#include "cogl-pipeline-private.h" +#include "cogl-texture-private.h" +#include "cogl-texture-3d.h" + +struct _CoglTexture3D +{ + CoglTexture _parent; + + /* The internal format of the texture represented as a + CoglPixelFormat */ + CoglPixelFormat internal_format; + int depth; + CoglBool auto_mipmap; + CoglBool mipmaps_dirty; + + /* TODO: factor out these OpenGL specific members into some form + * of driver private state. */ + + /* The internal format of the GL texture represented as a GL enum */ + GLenum gl_format; + /* The texture object number */ + GLuint gl_texture; + GLenum gl_legacy_texobj_min_filter; + GLenum gl_legacy_texobj_mag_filter; + GLint gl_legacy_texobj_wrap_mode_s; + GLint gl_legacy_texobj_wrap_mode_t; + GLint gl_legacy_texobj_wrap_mode_p; + CoglTexturePixel first_pixel; +}; + +#endif /* __COGL_TEXTURE_3D_PRIVATE_H */ diff --git a/cogl/cogl/cogl-texture-3d.c b/cogl/cogl/cogl-texture-3d.c new file mode 100644 index 0000000..5644119 --- /dev/null +++ b/cogl/cogl/cogl-texture-3d.c @@ -0,0 +1,759 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Neil Roberts + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-private.h" +#include "cogl-util.h" +#include "cogl-texture-private.h" +#include "cogl-texture-3d-private.h" +#include "cogl-texture-3d.h" +#include "cogl-texture-gl-private.h" +#include "cogl-texture-driver.h" +#include "cogl-context-private.h" +#include "cogl-object-private.h" +#include "cogl-journal-private.h" +#include "cogl-pipeline-private.h" +#include "cogl-pipeline-opengl-private.h" +#include "cogl-error-private.h" +#include "cogl-util-gl-private.h" +#include "cogl-gtype-private.h" + +#include +#include + +/* These might not be defined on GLES */ +#ifndef GL_TEXTURE_3D +#define GL_TEXTURE_3D 0x806F +#endif +#ifndef GL_TEXTURE_WRAP_R +#define GL_TEXTURE_WRAP_R 0x8072 +#endif + +static void _cogl_texture_3d_free (CoglTexture3D *tex_3d); + +COGL_TEXTURE_DEFINE (Texture3D, texture_3d); +COGL_GTYPE_DEFINE_CLASS (Texture3D, texture_3d, + COGL_GTYPE_IMPLEMENT_INTERFACE (texture)); + +static const CoglTextureVtable cogl_texture_3d_vtable; + +static void +_cogl_texture_3d_gl_flush_legacy_texobj_wrap_modes (CoglTexture *tex, + GLenum wrap_mode_s, + GLenum wrap_mode_t, + GLenum wrap_mode_p) +{ + CoglTexture3D *tex_3d = COGL_TEXTURE_3D (tex); + CoglContext *ctx = tex->context; + + /* Only set the wrap mode if it's different from the current value + to avoid too many GL calls. */ + if (tex_3d->gl_legacy_texobj_wrap_mode_s != wrap_mode_s || + tex_3d->gl_legacy_texobj_wrap_mode_t != wrap_mode_t || + tex_3d->gl_legacy_texobj_wrap_mode_p != wrap_mode_p) + { + _cogl_bind_gl_texture_transient (GL_TEXTURE_3D, + tex_3d->gl_texture, + FALSE); + GE( ctx, glTexParameteri (GL_TEXTURE_3D, + GL_TEXTURE_WRAP_S, + wrap_mode_s) ); + GE( ctx, glTexParameteri (GL_TEXTURE_3D, + GL_TEXTURE_WRAP_T, + wrap_mode_t) ); + GE( ctx, glTexParameteri (GL_TEXTURE_3D, + GL_TEXTURE_WRAP_R, + wrap_mode_p) ); + + tex_3d->gl_legacy_texobj_wrap_mode_s = wrap_mode_s; + tex_3d->gl_legacy_texobj_wrap_mode_t = wrap_mode_t; + tex_3d->gl_legacy_texobj_wrap_mode_p = wrap_mode_p; + } +} + +static void +_cogl_texture_3d_free (CoglTexture3D *tex_3d) +{ + if (tex_3d->gl_texture) + _cogl_delete_gl_texture (tex_3d->gl_texture); + + /* Chain up */ + _cogl_texture_free (COGL_TEXTURE (tex_3d)); +} + +static void +_cogl_texture_3d_set_auto_mipmap (CoglTexture *tex, + CoglBool value) +{ + CoglTexture3D *tex_3d = COGL_TEXTURE_3D (tex); + + tex_3d->auto_mipmap = value; +} + +static CoglTexture3D * +_cogl_texture_3d_create_base (CoglContext *ctx, + int width, + int height, + int depth, + CoglPixelFormat internal_format, + CoglTextureLoader *loader) +{ + CoglTexture3D *tex_3d = g_new (CoglTexture3D, 1); + CoglTexture *tex = COGL_TEXTURE (tex_3d); + + _cogl_texture_init (tex, ctx, width, height, + internal_format, loader, &cogl_texture_3d_vtable); + + tex_3d->gl_texture = 0; + + tex_3d->depth = depth; + tex_3d->mipmaps_dirty = TRUE; + tex_3d->auto_mipmap = TRUE; + + /* We default to GL_LINEAR for both filters */ + tex_3d->gl_legacy_texobj_min_filter = GL_LINEAR; + tex_3d->gl_legacy_texobj_mag_filter = GL_LINEAR; + + /* Wrap mode not yet set */ + tex_3d->gl_legacy_texobj_wrap_mode_s = GL_FALSE; + tex_3d->gl_legacy_texobj_wrap_mode_t = GL_FALSE; + tex_3d->gl_legacy_texobj_wrap_mode_p = GL_FALSE; + + return _cogl_texture_3d_object_new (tex_3d); +} + +CoglTexture3D * +cogl_texture_3d_new_with_size (CoglContext *ctx, + int width, + int height, + int depth) +{ + CoglTextureLoader *loader = _cogl_texture_create_loader (); + loader->src_type = COGL_TEXTURE_SOURCE_TYPE_SIZED; + loader->src.sized.width = width; + loader->src.sized.height = height; + loader->src.sized.depth = depth; + + return _cogl_texture_3d_create_base (ctx, width, height, depth, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + loader); +} + +CoglTexture3D * +cogl_texture_3d_new_from_bitmap (CoglBitmap *bmp, + int height, + int depth) +{ + CoglTextureLoader *loader; + + _COGL_RETURN_VAL_IF_FAIL (bmp, NULL); + + loader = _cogl_texture_create_loader (); + loader->src_type = COGL_TEXTURE_SOURCE_TYPE_BITMAP; + loader->src.bitmap.bitmap = cogl_object_ref (bmp); + loader->src.bitmap.height = height; + loader->src.bitmap.depth = depth; + loader->src.bitmap.can_convert_in_place = FALSE; /* TODO add api for this */ + + return _cogl_texture_3d_create_base (_cogl_bitmap_get_context (bmp), + cogl_bitmap_get_width (bmp), + height, + depth, + cogl_bitmap_get_format (bmp), + loader); +} + +CoglTexture3D * +cogl_texture_3d_new_from_data (CoglContext *context, + int width, + int height, + int depth, + CoglPixelFormat format, + int rowstride, + int image_stride, + const uint8_t *data, + CoglError **error) +{ + CoglBitmap *bitmap; + CoglTexture3D *ret; + + _COGL_RETURN_VAL_IF_FAIL (data, NULL); + _COGL_RETURN_VAL_IF_FAIL (format != COGL_PIXEL_FORMAT_ANY, NULL); + + /* Rowstride from width if not given */ + if (rowstride == 0) + rowstride = width * _cogl_pixel_format_get_bytes_per_pixel (format); + /* Image stride from height and rowstride if not given */ + if (image_stride == 0) + image_stride = height * rowstride; + + if (image_stride < rowstride * height) + return NULL; + + /* GL doesn't support uploading when the image_stride isn't a + multiple of the rowstride. If this happens we'll just pack the + image into a new bitmap. The documentation for this function + recommends avoiding this situation. */ + if (image_stride % rowstride != 0) + { + uint8_t *bmp_data; + int bmp_rowstride; + int z, y; + + bitmap = _cogl_bitmap_new_with_malloc_buffer (context, + width, + depth * height, + format, + error); + if (!bitmap) + return NULL; + + bmp_data = _cogl_bitmap_map (bitmap, + COGL_BUFFER_ACCESS_WRITE, + COGL_BUFFER_MAP_HINT_DISCARD, + error); + + if (bmp_data == NULL) + { + cogl_object_unref (bitmap); + return NULL; + } + + bmp_rowstride = cogl_bitmap_get_rowstride (bitmap); + + /* Copy all of the images in */ + for (z = 0; z < depth; z++) + for (y = 0; y < height; y++) + memcpy (bmp_data + (z * bmp_rowstride * height + + bmp_rowstride * y), + data + z * image_stride + rowstride * y, + bmp_rowstride); + + _cogl_bitmap_unmap (bitmap); + } + else + bitmap = cogl_bitmap_new_for_data (context, + width, + image_stride / rowstride * depth, + format, + rowstride, + (uint8_t *) data); + + ret = cogl_texture_3d_new_from_bitmap (bitmap, + height, + depth); + + cogl_object_unref (bitmap); + + if (ret && + !cogl_texture_allocate (COGL_TEXTURE (ret), error)) + { + cogl_object_unref (ret); + return NULL; + } + + return ret; +} + +static CoglBool +_cogl_texture_3d_can_create (CoglContext *ctx, + int width, + int height, + int depth, + CoglPixelFormat internal_format, + CoglError **error) +{ + GLenum gl_intformat; + GLenum gl_type; + + /* This should only happen on GLES */ + if (!cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_3D)) + { + _cogl_set_error (error, + COGL_SYSTEM_ERROR, + COGL_SYSTEM_ERROR_UNSUPPORTED, + "3D textures are not supported by the GPU"); + return FALSE; + } + + /* If NPOT textures aren't supported then the size must be a power + of two */ + if (!cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT) && + (!_cogl_util_is_pot (width) || + !_cogl_util_is_pot (height) || + !_cogl_util_is_pot (depth))) + { + _cogl_set_error (error, + COGL_SYSTEM_ERROR, + COGL_SYSTEM_ERROR_UNSUPPORTED, + "A non-power-of-two size was requested but this is not " + "supported by the GPU"); + return FALSE; + } + + ctx->driver_vtable->pixel_format_to_gl (ctx, + internal_format, + &gl_intformat, + NULL, + &gl_type); + + /* Check that the driver can create a texture with that size */ + if (!ctx->texture_driver->size_supported_3d (ctx, + GL_TEXTURE_3D, + gl_intformat, + gl_type, + width, + height, + depth)) + { + _cogl_set_error (error, + COGL_SYSTEM_ERROR, + COGL_SYSTEM_ERROR_UNSUPPORTED, + "The requested dimensions are not supported by the GPU"); + return FALSE; + } + + return TRUE; +} + +static CoglBool +allocate_with_size (CoglTexture3D *tex_3d, + CoglTextureLoader *loader, + CoglError **error) +{ + CoglTexture *tex = COGL_TEXTURE (tex_3d); + CoglContext *ctx = tex->context; + CoglPixelFormat internal_format; + int width = loader->src.sized.width; + int height = loader->src.sized.height; + int depth = loader->src.sized.depth; + GLenum gl_intformat; + GLenum gl_format; + GLenum gl_type; + GLenum gl_texture; + + internal_format = + _cogl_texture_determine_internal_format (tex, COGL_PIXEL_FORMAT_ANY); + + if (!_cogl_texture_3d_can_create (ctx, + width, + height, + depth, + internal_format, + error)) + return FALSE; + + ctx->driver_vtable->pixel_format_to_gl (ctx, + internal_format, + &gl_intformat, + &gl_format, + &gl_type); + + gl_texture = + ctx->texture_driver->gen (ctx, GL_TEXTURE_3D, internal_format); + _cogl_bind_gl_texture_transient (GL_TEXTURE_3D, + gl_texture, + FALSE); + /* Clear any GL errors */ + _cogl_gl_util_clear_gl_errors (ctx); + + ctx->glTexImage3D (GL_TEXTURE_3D, 0, gl_intformat, + width, height, depth, + 0, gl_format, gl_type, NULL); + + if (_cogl_gl_util_catch_out_of_memory (ctx, error)) + { + GE( ctx, glDeleteTextures (1, &gl_texture) ); + return FALSE; + } + + tex_3d->gl_texture = gl_texture; + tex_3d->gl_format = gl_intformat; + + tex_3d->depth = depth; + + tex_3d->internal_format = internal_format; + + _cogl_texture_set_allocated (tex, internal_format, width, height); + + return TRUE; +} + +static CoglBool +allocate_from_bitmap (CoglTexture3D *tex_3d, + CoglTextureLoader *loader, + CoglError **error) +{ + CoglTexture *tex = COGL_TEXTURE (tex_3d); + CoglContext *ctx = tex->context; + CoglPixelFormat internal_format; + CoglBitmap *bmp = loader->src.bitmap.bitmap; + int bmp_width = cogl_bitmap_get_width (bmp); + int height = loader->src.bitmap.height; + int depth = loader->src.bitmap.depth; + CoglPixelFormat bmp_format = cogl_bitmap_get_format (bmp); + CoglBool can_convert_in_place = loader->src.bitmap.can_convert_in_place; + CoglBitmap *upload_bmp; + CoglPixelFormat upload_format; + GLenum gl_intformat; + GLenum gl_format; + GLenum gl_type; + + internal_format = _cogl_texture_determine_internal_format (tex, bmp_format); + + if (!_cogl_texture_3d_can_create (ctx, + bmp_width, height, depth, + internal_format, + error)) + return FALSE; + + upload_bmp = _cogl_bitmap_convert_for_upload (bmp, + internal_format, + can_convert_in_place, + error); + if (upload_bmp == NULL) + return FALSE; + + upload_format = cogl_bitmap_get_format (upload_bmp); + + ctx->driver_vtable->pixel_format_to_gl (ctx, + upload_format, + NULL, /* internal format */ + &gl_format, + &gl_type); + ctx->driver_vtable->pixel_format_to_gl (ctx, + internal_format, + &gl_intformat, + NULL, + NULL); + + /* Keep a copy of the first pixel so that if glGenerateMipmap isn't + supported we can fallback to using GL_GENERATE_MIPMAP */ + if (!cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN)) + { + CoglError *ignore = NULL; + uint8_t *data = _cogl_bitmap_map (upload_bmp, + COGL_BUFFER_ACCESS_READ, 0, + &ignore); + + tex_3d->first_pixel.gl_format = gl_format; + tex_3d->first_pixel.gl_type = gl_type; + + if (data) + { + memcpy (tex_3d->first_pixel.data, data, + _cogl_pixel_format_get_bytes_per_pixel (upload_format)); + _cogl_bitmap_unmap (upload_bmp); + } + else + { + g_warning ("Failed to read first pixel of bitmap for " + "glGenerateMipmap fallback"); + cogl_error_free (ignore); + memset (tex_3d->first_pixel.data, 0, + _cogl_pixel_format_get_bytes_per_pixel (upload_format)); + } + } + + tex_3d->gl_texture = + ctx->texture_driver->gen (ctx, GL_TEXTURE_3D, internal_format); + + if (!ctx->texture_driver->upload_to_gl_3d (ctx, + GL_TEXTURE_3D, + tex_3d->gl_texture, + FALSE, /* is_foreign */ + height, + depth, + upload_bmp, + gl_intformat, + gl_format, + gl_type, + error)) + { + cogl_object_unref (upload_bmp); + return FALSE; + } + + tex_3d->gl_format = gl_intformat; + + cogl_object_unref (upload_bmp); + + tex_3d->depth = loader->src.bitmap.depth; + + tex_3d->internal_format = internal_format; + + _cogl_texture_set_allocated (tex, internal_format, + bmp_width, loader->src.bitmap.height); + + return TRUE; +} + +static CoglBool +_cogl_texture_3d_allocate (CoglTexture *tex, + CoglError **error) +{ + CoglTexture3D *tex_3d = COGL_TEXTURE_3D (tex); + CoglTextureLoader *loader = tex->loader; + + _COGL_RETURN_VAL_IF_FAIL (loader, FALSE); + + switch (loader->src_type) + { + case COGL_TEXTURE_SOURCE_TYPE_SIZED: + return allocate_with_size (tex_3d, loader, error); + case COGL_TEXTURE_SOURCE_TYPE_BITMAP: + return allocate_from_bitmap (tex_3d, loader, error); + default: + break; + } + + g_return_val_if_reached (FALSE); +} + +static int +_cogl_texture_3d_get_max_waste (CoglTexture *tex) +{ + return -1; +} + +static CoglBool +_cogl_texture_3d_is_sliced (CoglTexture *tex) +{ + return FALSE; +} + +static CoglBool +_cogl_texture_3d_can_hardware_repeat (CoglTexture *tex) +{ + return TRUE; +} + +static void +_cogl_texture_3d_transform_coords_to_gl (CoglTexture *tex, + float *s, + float *t) +{ + /* The texture coordinates map directly so we don't need to do + anything */ +} + +static CoglTransformResult +_cogl_texture_3d_transform_quad_coords_to_gl (CoglTexture *tex, + float *coords) +{ + /* The texture coordinates map directly so we don't need to do + anything other than check for repeats */ + + CoglBool need_repeat = FALSE; + int i; + + for (i = 0; i < 4; i++) + if (coords[i] < 0.0f || coords[i] > 1.0f) + need_repeat = TRUE; + + return (need_repeat ? COGL_TRANSFORM_HARDWARE_REPEAT + : COGL_TRANSFORM_NO_REPEAT); +} + +static CoglBool +_cogl_texture_3d_get_gl_texture (CoglTexture *tex, + GLuint *out_gl_handle, + GLenum *out_gl_target) +{ + CoglTexture3D *tex_3d = COGL_TEXTURE_3D (tex); + + if (out_gl_handle) + *out_gl_handle = tex_3d->gl_texture; + + if (out_gl_target) + *out_gl_target = GL_TEXTURE_3D; + + return TRUE; +} + +static void +_cogl_texture_3d_gl_flush_legacy_texobj_filters (CoglTexture *tex, + GLenum min_filter, + GLenum mag_filter) +{ + CoglTexture3D *tex_3d = COGL_TEXTURE_3D (tex); + CoglContext *ctx = tex->context; + + if (min_filter == tex_3d->gl_legacy_texobj_min_filter + && mag_filter == tex_3d->gl_legacy_texobj_mag_filter) + return; + + /* Store new values */ + tex_3d->gl_legacy_texobj_min_filter = min_filter; + tex_3d->gl_legacy_texobj_mag_filter = mag_filter; + + /* Apply new filters to the texture */ + _cogl_bind_gl_texture_transient (GL_TEXTURE_3D, + tex_3d->gl_texture, + FALSE); + GE( ctx, glTexParameteri (GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, mag_filter) ); + GE( ctx, glTexParameteri (GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, min_filter) ); +} + +static void +_cogl_texture_3d_pre_paint (CoglTexture *tex, CoglTexturePrePaintFlags flags) +{ + CoglTexture3D *tex_3d = COGL_TEXTURE_3D (tex); + CoglContext *ctx = tex->context; + + /* Only update if the mipmaps are dirty */ + if ((flags & COGL_TEXTURE_NEEDS_MIPMAP) && + tex_3d->auto_mipmap && tex_3d->mipmaps_dirty) + { + /* glGenerateMipmap is defined in the FBO extension. If it's not + available we'll fallback to temporarily enabling + GL_GENERATE_MIPMAP and reuploading the first pixel */ + if (cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN)) + _cogl_texture_gl_generate_mipmaps (tex); +#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) + else if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_GL_FIXED)) + { + _cogl_bind_gl_texture_transient (GL_TEXTURE_3D, + tex_3d->gl_texture, + FALSE); + + GE( ctx, glTexParameteri (GL_TEXTURE_3D, + GL_GENERATE_MIPMAP, + GL_TRUE) ); + GE( ctx, glTexSubImage3D (GL_TEXTURE_3D, + 0, /* level */ + 0, /* xoffset */ + 0, /* yoffset */ + 0, /* zoffset */ + 1, /* width */ + 1, /* height */ + 1, /* depth */ + tex_3d->first_pixel.gl_format, + tex_3d->first_pixel.gl_type, + tex_3d->first_pixel.data) ); + GE( ctx, glTexParameteri (GL_TEXTURE_3D, + GL_GENERATE_MIPMAP, + GL_FALSE) ); + } +#endif + + tex_3d->mipmaps_dirty = FALSE; + } +} + +static void +_cogl_texture_3d_ensure_non_quad_rendering (CoglTexture *tex) +{ + /* Nothing needs to be done */ +} + +static CoglBool +_cogl_texture_3d_set_region (CoglTexture *tex, + int src_x, + int src_y, + int dst_x, + int dst_y, + int dst_width, + int dst_height, + int level, + CoglBitmap *bmp, + CoglError **error) +{ + /* This function doesn't really make sense for 3D textures because + it can't specify which image to upload to */ + _cogl_set_error (error, + COGL_SYSTEM_ERROR, + COGL_SYSTEM_ERROR_UNSUPPORTED, + "Setting a 2D region on a 3D texture isn't " + "currently supported"); + + return FALSE; +} + +static int +_cogl_texture_3d_get_data (CoglTexture *tex, + CoglPixelFormat format, + int rowstride, + uint8_t *data) +{ + /* FIXME: we could probably implement this by assuming the data is + big enough to hold all of the images and that there is no stride + between the images. However it would be better to have an API + that can provide an image stride and this function probably isn't + particularly useful anyway so for now it just reports failure */ + return 0; +} + +static CoglPixelFormat +_cogl_texture_3d_get_format (CoglTexture *tex) +{ + return COGL_TEXTURE_3D (tex)->internal_format; +} + +static GLenum +_cogl_texture_3d_get_gl_format (CoglTexture *tex) +{ + return COGL_TEXTURE_3D (tex)->gl_format; +} + +static CoglTextureType +_cogl_texture_3d_get_type (CoglTexture *tex) +{ + return COGL_TEXTURE_TYPE_3D; +} + +static const CoglTextureVtable +cogl_texture_3d_vtable = + { + TRUE, /* primitive */ + _cogl_texture_3d_allocate, + _cogl_texture_3d_set_region, + _cogl_texture_3d_get_data, + NULL, /* foreach_sub_texture_in_region */ + _cogl_texture_3d_get_max_waste, + _cogl_texture_3d_is_sliced, + _cogl_texture_3d_can_hardware_repeat, + _cogl_texture_3d_transform_coords_to_gl, + _cogl_texture_3d_transform_quad_coords_to_gl, + _cogl_texture_3d_get_gl_texture, + _cogl_texture_3d_gl_flush_legacy_texobj_filters, + _cogl_texture_3d_pre_paint, + _cogl_texture_3d_ensure_non_quad_rendering, + _cogl_texture_3d_gl_flush_legacy_texobj_wrap_modes, + _cogl_texture_3d_get_format, + _cogl_texture_3d_get_gl_format, + _cogl_texture_3d_get_type, + NULL, /* is_foreign */ + _cogl_texture_3d_set_auto_mipmap + }; diff --git a/cogl/cogl/cogl-texture-3d.h b/cogl/cogl/cogl-texture-3d.h new file mode 100644 index 0000000..238adfe --- /dev/null +++ b/cogl/cogl/cogl-texture-3d.h @@ -0,0 +1,202 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Neil Roberts + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_TEXTURE_3D_H +#define __COGL_TEXTURE_3D_H + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-texture-3d + * @short_description: Functions for creating and manipulating 3D textures + * + * These functions allow 3D textures to be used. 3D textures can be + * thought of as layers of 2D images arranged into a cuboid + * shape. When choosing a texel from the texture, Cogl will take into + * account the 'r' texture coordinate to select one of the images. + */ + +typedef struct _CoglTexture3D CoglTexture3D; + +#define COGL_TEXTURE_3D(X) ((CoglTexture3D *)X) + +/** + * cogl_texture_3d_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_texture_3d_get_gtype (void); + +/** + * cogl_texture_3d_new_with_size: + * @context: a #CoglContext + * @width: width of the texture in pixels. + * @height: height of the texture in pixels. + * @depth: depth of the texture in pixels. + * + * Creates a low-level #CoglTexture3D texture with the specified + * dimensions and pixel format. + * + * The storage for the texture is not allocated before this function + * returns. You can call cogl_texture_allocate() to explicitly + * allocate the underlying storage or preferably let Cogl + * automatically allocate storage lazily when it may know more about + * how the texture is going to be used and can optimize how it is + * allocated. + * + * The texture is still configurable until it has been allocated so + * for example you can influence the internal format of the texture + * using cogl_texture_set_components() and + * cogl_texture_set_premultiplied(). + * + * This texture will fail to allocate later if + * %COGL_FEATURE_ID_TEXTURE_3D is not advertised. Allocation can also + * fail if the requested dimensions are not supported by the + * GPU. + * + * Returns: (transfer full): A new #CoglTexture3D object with no storage yet allocated. + * Since: 1.10 + * Stability: Unstable + */ +CoglTexture3D * +cogl_texture_3d_new_with_size (CoglContext *context, + int width, + int height, + int depth); + +/** + * cogl_texture_3d_new_from_data: + * @context: a #CoglContext + * @width: width of the texture in pixels. + * @height: height of the texture in pixels. + * @depth: depth of the texture in pixels. + * @format: the #CoglPixelFormat the buffer is stored in in RAM + * @rowstride: the memory offset in bytes between the starts of + * scanlines in @data or 0 to infer it from the width and format + * @image_stride: the number of bytes from one image to the next. This + * can be used to add padding between the images in a similar way + * that the rowstride can be used to add padding between + * rows. Alternatively 0 can be passed to infer the @image_stride + * from the @height. + * @data: pointer the memory region where the source buffer resides + * @error: A CoglError return location. + * + * Creates a low-level 3D texture and initializes it with @data. The + * data is assumed to be packed array of @depth images. There can be + * padding between the images using @image_stride. + * + * This api will always immediately allocate GPU memory for the + * texture and upload the given data so that the @data pointer does + * not need to remain valid once this function returns. This means it + * is not possible to configure the texture before it is allocated. If + * you do need to configure the texture before allocation (to specify + * constraints on the internal format for example) then you can + * instead create a #CoglBitmap for your data and use + * cogl_texture_3d_new_from_bitmap(). + * + * Return value: (transfer full): the newly created #CoglTexture3D or + * %NULL if there was an error and an exception will be + * returned through @error. + * Since: 1.10 + * Stability: Unstable + */ +CoglTexture3D * +cogl_texture_3d_new_from_data (CoglContext *context, + int width, + int height, + int depth, + CoglPixelFormat format, + int rowstride, + int image_stride, + const uint8_t *data, + CoglError **error); + +/** + * cogl_texture_3d_new_from_bitmap: + * @bitmap: A #CoglBitmap object. + * @height: height of the texture in pixels. + * @depth: depth of the texture in pixels. + * + * Creates a low-level 3D texture and initializes it with the images + * in @bitmap. The images are assumed to be packed together after one + * another in the increasing y axis. The height of individual image is + * given as @height and the number of images is given in @depth. The + * actual height of the bitmap can be larger than @height × @depth. In + * this case it assumes there is padding between the images. + * + * The storage for the texture is not allocated before this function + * returns. You can call cogl_texture_allocate() to explicitly + * allocate the underlying storage or preferably let Cogl + * automatically allocate storage lazily when it may know more about + * how the texture is going to be used and can optimize how it is + * allocated. + * + * The texture is still configurable until it has been allocated so + * for example you can influence the internal format of the texture + * using cogl_texture_set_components() and + * cogl_texture_set_premultiplied(). + * + * This texture will fail to allocate later if + * %COGL_FEATURE_ID_TEXTURE_3D is not advertised. Allocation can also + * fail if the requested dimensions are not supported by the + * GPU. + * + * Return value: (transfer full): a newly created #CoglTexture3D + * Since: 2.0 + * Stability: unstable + */ +CoglTexture3D * +cogl_texture_3d_new_from_bitmap (CoglBitmap *bitmap, + int height, + int depth); + +/** + * cogl_is_texture_3d: + * @object: a #CoglObject + * + * Checks whether the given object references a #CoglTexture3D + * + * Return value: %TRUE if the passed object represents a 3D texture + * and %FALSE otherwise + * + * Since: 1.4 + * Stability: Unstable + */ +CoglBool +cogl_is_texture_3d (void *object); + +COGL_END_DECLS + +#endif /* __COGL_TEXTURE_3D_H */ diff --git a/cogl/cogl/cogl-texture-driver.h b/cogl/cogl/cogl-texture-driver.h new file mode 100644 index 0000000..3ab86ed --- /dev/null +++ b/cogl/cogl/cogl-texture-driver.h @@ -0,0 +1,206 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_TEXTURE_DRIVER_H +#define __COGL_TEXTURE_DRIVER_H + +typedef struct _CoglTextureDriver CoglTextureDriver; + +struct _CoglTextureDriver +{ + /* + * A very small wrapper around glGenTextures() that ensures we default to + * non-mipmap filters when creating textures. This is to save some memory as + * the driver will not allocate room for the mipmap tree. + */ + GLuint + (* gen) (CoglContext *ctx, + GLenum gl_target, + CoglPixelFormat internal_format); + + /* + * This sets up the glPixelStore state for an upload to a destination with + * the same size, and with no offset. + */ + /* NB: GLES can't upload a sub region of pixel data from a larger source + * buffer which is why this interface is limited. The GL driver has a more + * flexible version of this function that is uses internally */ + void + (* prep_gl_for_pixels_upload) (CoglContext *ctx, + int pixels_rowstride, + int pixels_bpp); + + /* + * This uploads a sub-region from source_bmp to a single GL texture + * handle (i.e a single CoglTexture slice) + * + * It also updates the array of tex->first_pixels[slice_index] if + * dst_{x,y} == 0 + * + * The driver abstraction is in place because GLES doesn't support the pixel + * store options required to source from a subregion, so for GLES we have + * to manually create a transient source bitmap. + * + * XXX: sorry for the ridiculous number of arguments :-( + */ + CoglBool + (* upload_subregion_to_gl) (CoglContext *ctx, + CoglTexture *texture, + CoglBool is_foreign, + int src_x, + int src_y, + int dst_x, + int dst_y, + int width, + int height, + int level, + CoglBitmap *source_bmp, + GLuint source_gl_format, + GLuint source_gl_type, + CoglError **error); + + /* + * Replaces the contents of the GL texture with the entire bitmap. On + * GL this just directly calls glTexImage2D, but under GLES it needs + * to copy the bitmap if the rowstride is not a multiple of a possible + * alignment value because there is no GL_UNPACK_ROW_LENGTH + */ + CoglBool + (* upload_to_gl) (CoglContext *ctx, + GLenum gl_target, + GLuint gl_handle, + CoglBool is_foreign, + CoglBitmap *source_bmp, + GLint internal_gl_format, + GLuint source_gl_format, + GLuint source_gl_type, + CoglError **error); + + /* + * Replaces the contents of the GL texture with the entire bitmap. The + * width of the texture is inferred from the bitmap. The height and + * depth of the texture is given directly. The 'image_height' (which + * is the number of rows between images) is inferred by dividing the + * height of the bitmap by the depth. + */ + CoglBool + (* upload_to_gl_3d) (CoglContext *ctx, + GLenum gl_target, + GLuint gl_handle, + CoglBool is_foreign, + GLint height, + GLint depth, + CoglBitmap *source_bmp, + GLint internal_gl_format, + GLuint source_gl_format, + GLuint source_gl_type, + CoglError **error); + + /* + * This sets up the glPixelStore state for an download to a destination with + * the same size, and with no offset. + */ + /* NB: GLES can't download pixel data into a sub region of a larger + * destination buffer, the GL driver has a more flexible version of + * this function that it uses internally. */ + void + (* prep_gl_for_pixels_download) (CoglContext *ctx, + int image_width, + int pixels_rowstride, + int pixels_bpp); + + /* + * This driver abstraction is needed because GLES doesn't support + * glGetTexImage (). On GLES this currently just returns FALSE which + * will lead to a generic fallback path being used that simply + * renders the texture and reads it back from the framebuffer. (See + * _cogl_texture_draw_and_read () ) + */ + CoglBool + (* gl_get_tex_image) (CoglContext *ctx, + GLenum gl_target, + GLenum dest_gl_format, + GLenum dest_gl_type, + uint8_t *dest); + + /* + * It may depend on the driver as to what texture sizes are supported... + */ + CoglBool + (* size_supported) (CoglContext *ctx, + GLenum gl_target, + GLenum gl_intformat, + GLenum gl_format, + GLenum gl_type, + int width, + int height); + + CoglBool + (* size_supported_3d) (CoglContext *ctx, + GLenum gl_target, + GLenum gl_format, + GLenum gl_type, + int width, + int height, + int depth); + + /* + * This driver abstraction is needed because GLES doesn't support setting + * a texture border color. + */ + void + (* try_setting_gl_border_color) (CoglContext *ctx, + GLuint gl_target, + const GLfloat *transparent_color); + + /* + * It may depend on the driver as to what texture targets may be used when + * creating a foreign texture. E.g. OpenGL supports ARB_texture_rectangle + * but GLES doesn't + */ + CoglBool + (* allows_foreign_gl_target) (CoglContext *ctx, + GLenum gl_target); + + /* + * The driver may impose constraints on what formats can be used to store + * texture data read from textures. For example GLES currently only supports + * RGBA_8888, and so we need to manually convert the data if the final + * destination has another format. + */ + CoglPixelFormat + (* find_best_gl_get_data_format) (CoglContext *context, + CoglPixelFormat format, + GLenum *closest_gl_format, + GLenum *closest_gl_type); +}; + +#endif /* __COGL_TEXTURE_DRIVER_H */ + diff --git a/cogl/cogl/cogl-texture-private.h b/cogl/cogl/cogl-texture-private.h new file mode 100644 index 0000000..472c41d --- /dev/null +++ b/cogl/cogl/cogl-texture-private.h @@ -0,0 +1,409 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_TEXTURE_PRIVATE_H +#define __COGL_TEXTURE_PRIVATE_H + +#include "cogl-bitmap-private.h" +#include "cogl-object-private.h" +#include "cogl-pipeline-private.h" +#include "cogl-spans.h" +#include "cogl-meta-texture.h" +#include "cogl-framebuffer.h" + +#ifdef COGL_HAS_EGL_SUPPORT +#include "cogl-egl-defines.h" +#endif + +typedef struct _CoglTextureVtable CoglTextureVtable; + +/* Encodes three possibiloities result of transforming a quad */ +typedef enum { + /* quad doesn't cross the boundaries of a texture */ + COGL_TRANSFORM_NO_REPEAT, + /* quad crosses boundaries, hardware wrap mode can handle */ + COGL_TRANSFORM_HARDWARE_REPEAT, + /* quad crosses boundaries, needs software fallback; + * for a sliced texture, this might not actually involve + * repeating, just a quad crossing multiple slices */ + COGL_TRANSFORM_SOFTWARE_REPEAT, +} CoglTransformResult; + +/* Flags given to the pre_paint method */ +typedef enum { + /* The texture is going to be used with filters that require + mipmapping. This gives the texture the opportunity to + automatically update the mipmap tree */ + COGL_TEXTURE_NEEDS_MIPMAP = 1 +} CoglTexturePrePaintFlags; + +struct _CoglTextureVtable +{ + /* Virtual functions that must be implemented for a texture + backend */ + + CoglBool is_primitive; + + CoglBool (* allocate) (CoglTexture *tex, + CoglError **error); + + /* This should update the specified sub region of the texture with a + sub region of the given bitmap. The bitmap is not converted + before being set so the caller is expected to have called + _cogl_bitmap_convert_for_upload with a suitable internal_format + before passing here */ + CoglBool (* set_region) (CoglTexture *tex, + int src_x, + int src_y, + int dst_x, + int dst_y, + int dst_width, + int dst_height, + int level, + CoglBitmap *bitmap, + CoglError **error); + + /* This should copy the image data of the texture into @data. The + requested format will have been first passed through + ctx->texture_driver->find_best_gl_get_data_format so it should + always be a format that is valid for GL (ie, no conversion should + be necessary). */ + CoglBool (* get_data) (CoglTexture *tex, + CoglPixelFormat format, + int rowstride, + uint8_t *data); + + void (* foreach_sub_texture_in_region) (CoglTexture *tex, + float virtual_tx_1, + float virtual_ty_1, + float virtual_tx_2, + float virtual_ty_2, + CoglMetaTextureCallback callback, + void *user_data); + + int (* get_max_waste) (CoglTexture *tex); + + CoglBool (* is_sliced) (CoglTexture *tex); + + CoglBool (* can_hardware_repeat) (CoglTexture *tex); + + void (* transform_coords_to_gl) (CoglTexture *tex, + float *s, + float *t); + CoglTransformResult (* transform_quad_coords_to_gl) (CoglTexture *tex, + float *coords); + + CoglBool (* get_gl_texture) (CoglTexture *tex, + GLuint *out_gl_handle, + GLenum *out_gl_target); + + /* OpenGL driver specific virtual function */ + void (* gl_flush_legacy_texobj_filters) (CoglTexture *tex, + GLenum min_filter, + GLenum mag_filter); + + void (* pre_paint) (CoglTexture *tex, CoglTexturePrePaintFlags flags); + void (* ensure_non_quad_rendering) (CoglTexture *tex); + + /* OpenGL driver specific virtual function */ + void (* gl_flush_legacy_texobj_wrap_modes) (CoglTexture *tex, + GLenum wrap_mode_s, + GLenum wrap_mode_t, + GLenum wrap_mode_p); + + CoglPixelFormat (* get_format) (CoglTexture *tex); + GLenum (* get_gl_format) (CoglTexture *tex); + + CoglTextureType (* get_type) (CoglTexture *tex); + + CoglBool (* is_foreign) (CoglTexture *tex); + + /* Only needs to be implemented if is_primitive == TRUE */ + void (* set_auto_mipmap) (CoglTexture *texture, + CoglBool value); +}; + +typedef enum _CoglTextureSoureType { + COGL_TEXTURE_SOURCE_TYPE_SIZED = 1, + COGL_TEXTURE_SOURCE_TYPE_BITMAP, + COGL_TEXTURE_SOURCE_TYPE_EGL_IMAGE, + COGL_TEXTURE_SOURCE_TYPE_GL_FOREIGN +} CoglTextureSourceType; + +typedef struct _CoglTextureLoader +{ + CoglTextureSourceType src_type; + union { + struct { + int width; + int height; + int depth; /* for 3d textures */ + } sized; + struct { + CoglBitmap *bitmap; + int height; /* for 3d textures */ + int depth; /* for 3d textures */ + CoglBool can_convert_in_place; + } bitmap; +#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base) + struct { + EGLImageKHR image; + int width; + int height; + CoglPixelFormat format; + } egl_image; +#endif + struct { + int width; + int height; + unsigned int gl_handle; + CoglPixelFormat format; + } gl_foreign; + } src; +} CoglTextureLoader; + +struct _CoglTexture +{ + CoglObject _parent; + CoglContext *context; + CoglTextureLoader *loader; + GList *framebuffers; + int max_level; + int width; + int height; + CoglBool allocated; + + /* + * Internal format + */ + CoglTextureComponents components; + unsigned int premultiplied:1; + + const CoglTextureVtable *vtable; +}; + +typedef enum _CoglTextureChangeFlags +{ + /* Whenever the internals of a texture are changed such that the + * underlying GL textures that represent the CoglTexture change then + * we notify cogl-material.c via + * _cogl_pipeline_texture_pre_change_notify + */ + COGL_TEXTURE_CHANGE_GL_TEXTURES + +} CoglTextureChangeFlags; + +typedef struct _CoglTexturePixel CoglTexturePixel; + +/* This is used by the texture backends to store the first pixel of + each GL texture. This is only used when glGenerateMipmap is not + available so that we can temporarily set GL_GENERATE_MIPMAP and + reupload a pixel */ +struct _CoglTexturePixel +{ + /* We need to store the format of the pixel because we store the + data in the source format which might end up being different for + each slice if a subregion is updated with a different format */ + GLenum gl_format; + GLenum gl_type; + uint8_t data[4]; +}; + +void +_cogl_texture_init (CoglTexture *texture, + CoglContext *ctx, + int width, + int height, + CoglPixelFormat src_format, + CoglTextureLoader *loader, + const CoglTextureVtable *vtable); + +void +_cogl_texture_free (CoglTexture *texture); + +/* This is used to register a type to the list of handle types that + will be considered a texture in cogl_is_texture() */ +void +_cogl_texture_register_texture_type (const CoglObjectClass *klass); + +#define COGL_TEXTURE_DEFINE(TypeName, type_name) \ + COGL_OBJECT_DEFINE_WITH_CODE_GTYPE \ + (TypeName, type_name, \ + _cogl_texture_register_texture_type (&_cogl_##type_name##_class)) + +#define COGL_TEXTURE_INTERNAL_DEFINE(TypeName, type_name) \ + COGL_OBJECT_INTERNAL_DEFINE_WITH_CODE \ + (TypeName, type_name, \ + _cogl_texture_register_texture_type (&_cogl_##type_name##_class)) + +CoglBool +_cogl_texture_can_hardware_repeat (CoglTexture *texture); + +void +_cogl_texture_transform_coords_to_gl (CoglTexture *texture, + float *s, + float *t); +CoglTransformResult +_cogl_texture_transform_quad_coords_to_gl (CoglTexture *texture, + float *coords); + +void +_cogl_texture_pre_paint (CoglTexture *texture, CoglTexturePrePaintFlags flags); + +void +_cogl_texture_ensure_non_quad_rendering (CoglTexture *texture); + +/* + * This determines a CoglPixelFormat according to texture::components + * and texture::premultiplied (i.e. the user required components and + * whether the texture should be considered premultiplied) + * + * A reference/source format can be given (or COGL_PIXEL_FORMAT_ANY) + * and wherever possible this function tries to simply return the + * given source format if its compatible with the required components. + * + * Texture backends can call this when allocating a texture to know + * how to convert a source image in preparation for uploading. + */ +CoglPixelFormat +_cogl_texture_determine_internal_format (CoglTexture *texture, + CoglPixelFormat src_format); + +/* This is called by texture backends when they have successfully + * allocated a texture. + * + * Most texture backends currently track the internal layout of + * textures using a CoglPixelFormat which will be finalized when a + * texture is allocated. At this point we need to update + * texture::components and texture::premultiplied according to the + * determined layout. + * + * XXX: Going forward we should probably aim to stop using + * CoglPixelFormat at all for tracking the internal layout of + * textures. + */ +void +_cogl_texture_set_internal_format (CoglTexture *texture, + CoglPixelFormat internal_format); + +CoglBool +_cogl_texture_is_foreign (CoglTexture *texture); + +void +_cogl_texture_associate_framebuffer (CoglTexture *texture, + CoglFramebuffer *framebuffer); + +const GList * +_cogl_texture_get_associated_framebuffers (CoglTexture *texture); + +void +_cogl_texture_flush_journal_rendering (CoglTexture *texture); + +void +_cogl_texture_spans_foreach_in_region (CoglSpan *x_spans, + int n_x_spans, + CoglSpan *y_spans, + int n_y_spans, + CoglTexture **textures, + float *virtual_coords, + float x_normalize_factor, + float y_normalize_factor, + CoglPipelineWrapMode wrap_x, + CoglPipelineWrapMode wrap_y, + CoglMetaTextureCallback callback, + void *user_data); + +/* + * _cogl_texture_get_type: + * @texture: a #CoglTexture pointer + * + * Retrieves the texture type of the underlying hardware texture that + * this #CoglTexture will use. + * + * Return value: The type of the hardware texture. + */ +CoglTextureType +_cogl_texture_get_type (CoglTexture *texture); + +CoglBool +_cogl_texture_set_region (CoglTexture *texture, + int width, + int height, + CoglPixelFormat format, + int rowstride, + const uint8_t *data, + int dst_x, + int dst_y, + int level, + CoglError **error); + +CoglBool +_cogl_texture_set_region_from_bitmap (CoglTexture *texture, + int src_x, + int src_y, + int width, + int height, + CoglBitmap *bmp, + int dst_x, + int dst_y, + int level, + CoglError **error); + +CoglBool +_cogl_texture_needs_premult_conversion (CoglPixelFormat src_format, + CoglPixelFormat dst_format); + +int +_cogl_texture_get_n_levels (CoglTexture *texture); + +void +_cogl_texture_get_level_size (CoglTexture *texture, + int level, + int *width, + int *height, + int *depth); + +void +_cogl_texture_set_allocated (CoglTexture *texture, + CoglPixelFormat internal_format, + int width, + int height); + +CoglPixelFormat +_cogl_texture_get_format (CoglTexture *texture); + +CoglTextureLoader * +_cogl_texture_create_loader (void); + +void +_cogl_texture_copy_internal_format (CoglTexture *src, + CoglTexture *dest); + +#endif /* __COGL_TEXTURE_PRIVATE_H */ diff --git a/cogl/cogl/cogl-texture-rectangle-private.h b/cogl/cogl/cogl-texture-rectangle-private.h new file mode 100644 index 0000000..75029e7 --- /dev/null +++ b/cogl/cogl/cogl-texture-rectangle-private.h @@ -0,0 +1,66 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_TEXTURE_RECTANGLE_H +#define __COGL_TEXTURE_RECTANGLE_H + +#include "cogl-pipeline-private.h" +#include "cogl-texture-private.h" +#include "cogl-texture-rectangle.h" + +struct _CoglTextureRectangle +{ + CoglTexture _parent; + + /* The internal format of the texture represented as a + CoglPixelFormat */ + CoglPixelFormat internal_format; + + /* TODO: factor out these OpenGL specific members into some form + * of driver private state. */ + + /* The internal format of the GL texture represented as a GL enum */ + GLenum gl_format; + /* The texture object number */ + GLuint gl_texture; + GLenum gl_legacy_texobj_min_filter; + GLenum gl_legacy_texobj_mag_filter; + GLint gl_legacy_texobj_wrap_mode_s; + GLint gl_legacy_texobj_wrap_mode_t; + CoglBool is_foreign; +}; + +CoglTextureRectangle * +_cogl_texture_rectangle_new_from_foreign (GLuint gl_handle, + GLuint width, + GLuint height, + CoglPixelFormat format); + +#endif /* __COGL_TEXTURE_RECTANGLE_H */ diff --git a/cogl/cogl/cogl-texture-rectangle.c b/cogl/cogl/cogl-texture-rectangle.c new file mode 100644 index 0000000..cc2e642 --- /dev/null +++ b/cogl/cogl/cogl-texture-rectangle.c @@ -0,0 +1,777 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Neil Roberts + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-private.h" +#include "cogl-util.h" +#include "cogl-texture-private.h" +#include "cogl-texture-rectangle-private.h" +#include "cogl-texture-driver.h" +#include "cogl-context-private.h" +#include "cogl-object-private.h" +#include "cogl-journal-private.h" +#include "cogl-pipeline-opengl-private.h" +#include "cogl-error-private.h" +#include "cogl-util-gl-private.h" +#include "cogl-gtype-private.h" + +#include +#include + +/* These aren't defined under GLES */ +#ifndef GL_TEXTURE_RECTANGLE_ARB +#define GL_TEXTURE_RECTANGLE_ARB 0x84F5 +#endif +#ifndef GL_CLAMP +#define GL_CLAMP 0x2900 +#endif +#ifndef GL_CLAMP_TO_BORDER +#define GL_CLAMP_TO_BORDER 0x812D +#endif + +static void _cogl_texture_rectangle_free (CoglTextureRectangle *tex_rect); + +COGL_TEXTURE_DEFINE (TextureRectangle, texture_rectangle); +COGL_GTYPE_DEFINE_CLASS (TextureRectangle, texture_rectangle, + COGL_GTYPE_IMPLEMENT_INTERFACE (texture)); + +static const CoglTextureVtable cogl_texture_rectangle_vtable; + +static CoglBool +can_use_wrap_mode (GLenum wrap_mode) +{ + return (wrap_mode == GL_CLAMP || + wrap_mode == GL_CLAMP_TO_EDGE || + wrap_mode == GL_CLAMP_TO_BORDER); +} + +static void +_cogl_texture_rectangle_gl_flush_legacy_texobj_wrap_modes (CoglTexture *tex, + GLenum wrap_mode_s, + GLenum wrap_mode_t, + GLenum wrap_mode_p) +{ + CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex); + CoglContext *ctx = tex->context; + + /* Only set the wrap mode if it's different from the current value + to avoid too many GL calls. Texture rectangle doesn't make use of + the r coordinate so we can ignore its wrap mode */ + if (tex_rect->gl_legacy_texobj_wrap_mode_s != wrap_mode_s || + tex_rect->gl_legacy_texobj_wrap_mode_t != wrap_mode_t) + { + g_assert (can_use_wrap_mode (wrap_mode_s)); + g_assert (can_use_wrap_mode (wrap_mode_t)); + + _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB, + tex_rect->gl_texture, + tex_rect->is_foreign); + GE( ctx, glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, + GL_TEXTURE_WRAP_S, wrap_mode_s) ); + GE( ctx, glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, + GL_TEXTURE_WRAP_T, wrap_mode_t) ); + + tex_rect->gl_legacy_texobj_wrap_mode_s = wrap_mode_s; + tex_rect->gl_legacy_texobj_wrap_mode_t = wrap_mode_t; + } +} + +static void +_cogl_texture_rectangle_free (CoglTextureRectangle *tex_rect) +{ + if (!tex_rect->is_foreign && tex_rect->gl_texture) + _cogl_delete_gl_texture (tex_rect->gl_texture); + + /* Chain up */ + _cogl_texture_free (COGL_TEXTURE (tex_rect)); +} + +static CoglBool +_cogl_texture_rectangle_can_create (CoglContext *ctx, + unsigned int width, + unsigned int height, + CoglPixelFormat internal_format, + CoglError **error) +{ + GLenum gl_intformat; + GLenum gl_format; + GLenum gl_type; + + if (!cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_RECTANGLE)) + { + _cogl_set_error (error, + COGL_TEXTURE_ERROR, + COGL_TEXTURE_ERROR_TYPE, + "The CoglTextureRectangle feature isn't available"); + return FALSE; + } + + ctx->driver_vtable->pixel_format_to_gl (ctx, + internal_format, + &gl_intformat, + &gl_format, + &gl_type); + + /* Check that the driver can create a texture with that size */ + if (!ctx->texture_driver->size_supported (ctx, + GL_TEXTURE_RECTANGLE_ARB, + gl_intformat, + gl_format, + gl_type, + width, + height)) + { + _cogl_set_error (error, + COGL_TEXTURE_ERROR, + COGL_TEXTURE_ERROR_SIZE, + "The requested texture size + format is unsupported"); + return FALSE; + } + + return TRUE; +} + +static void +_cogl_texture_rectangle_set_auto_mipmap (CoglTexture *tex, + CoglBool value) +{ + /* Rectangle textures currently never support mipmapping so there's + no point in doing anything here */ +} + +static CoglTextureRectangle * +_cogl_texture_rectangle_create_base (CoglContext *ctx, + int width, + int height, + CoglPixelFormat internal_format, + CoglTextureLoader *loader) +{ + CoglTextureRectangle *tex_rect = g_new (CoglTextureRectangle, 1); + CoglTexture *tex = COGL_TEXTURE (tex_rect); + + _cogl_texture_init (tex, ctx, width, height, + internal_format, loader, + &cogl_texture_rectangle_vtable); + + tex_rect->gl_texture = 0; + tex_rect->is_foreign = FALSE; + + /* We default to GL_LINEAR for both filters */ + tex_rect->gl_legacy_texobj_min_filter = GL_LINEAR; + tex_rect->gl_legacy_texobj_mag_filter = GL_LINEAR; + + /* Wrap mode not yet set */ + tex_rect->gl_legacy_texobj_wrap_mode_s = GL_FALSE; + tex_rect->gl_legacy_texobj_wrap_mode_t = GL_FALSE; + + return _cogl_texture_rectangle_object_new (tex_rect); +} + +CoglTextureRectangle * +cogl_texture_rectangle_new_with_size (CoglContext *ctx, + int width, + int height) +{ + CoglTextureLoader *loader = _cogl_texture_create_loader (); + loader->src_type = COGL_TEXTURE_SOURCE_TYPE_SIZED; + loader->src.sized.width = width; + loader->src.sized.height = height; + + return _cogl_texture_rectangle_create_base (ctx, width, height, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + loader); +} + +static CoglBool +allocate_with_size (CoglTextureRectangle *tex_rect, + CoglTextureLoader *loader, + CoglError **error) +{ + CoglTexture *tex = COGL_TEXTURE (tex_rect); + CoglContext *ctx = tex->context; + CoglPixelFormat internal_format; + int width = loader->src.sized.width; + int height = loader->src.sized.height; + GLenum gl_intformat; + GLenum gl_format; + GLenum gl_type; + GLenum gl_texture; + + internal_format = + _cogl_texture_determine_internal_format (tex, COGL_PIXEL_FORMAT_ANY); + + if (!_cogl_texture_rectangle_can_create (ctx, + width, + height, + internal_format, + error)) + return FALSE; + + ctx->driver_vtable->pixel_format_to_gl (ctx, + internal_format, + &gl_intformat, + &gl_format, + &gl_type); + + gl_texture = + ctx->texture_driver->gen (ctx, + GL_TEXTURE_RECTANGLE_ARB, + internal_format); + _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB, + gl_texture, + tex_rect->is_foreign); + + /* Clear any GL errors */ + _cogl_gl_util_clear_gl_errors (ctx); + + ctx->glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, gl_intformat, + width, height, 0, gl_format, gl_type, NULL); + + if (_cogl_gl_util_catch_out_of_memory (ctx, error)) + { + GE( ctx, glDeleteTextures (1, &gl_texture) ); + return FALSE; + } + + tex_rect->internal_format = internal_format; + + tex_rect->gl_texture = gl_texture; + tex_rect->gl_format = gl_intformat; + + _cogl_texture_set_allocated (COGL_TEXTURE (tex_rect), + internal_format, width, height); + + return TRUE; +} + +static CoglBool +allocate_from_bitmap (CoglTextureRectangle *tex_rect, + CoglTextureLoader *loader, + CoglError **error) +{ + CoglTexture *tex = COGL_TEXTURE (tex_rect); + CoglContext *ctx = tex->context; + CoglPixelFormat internal_format; + CoglBitmap *bmp = loader->src.bitmap.bitmap; + int width = cogl_bitmap_get_width (bmp); + int height = cogl_bitmap_get_height (bmp); + CoglBool can_convert_in_place = loader->src.bitmap.can_convert_in_place; + CoglBitmap *upload_bmp; + GLenum gl_intformat; + GLenum gl_format; + GLenum gl_type; + + internal_format = + _cogl_texture_determine_internal_format (tex, cogl_bitmap_get_format (bmp)); + + if (!_cogl_texture_rectangle_can_create (ctx, + width, + height, + internal_format, + error)) + return FALSE; + + upload_bmp = _cogl_bitmap_convert_for_upload (bmp, + internal_format, + can_convert_in_place, + error); + if (upload_bmp == NULL) + return FALSE; + + ctx->driver_vtable->pixel_format_to_gl (ctx, + cogl_bitmap_get_format (upload_bmp), + NULL, /* internal format */ + &gl_format, + &gl_type); + ctx->driver_vtable->pixel_format_to_gl (ctx, + internal_format, + &gl_intformat, + NULL, + NULL); + + tex_rect->gl_texture = + ctx->texture_driver->gen (ctx, + GL_TEXTURE_RECTANGLE_ARB, + internal_format); + if (!ctx->texture_driver->upload_to_gl (ctx, + GL_TEXTURE_RECTANGLE_ARB, + tex_rect->gl_texture, + FALSE, + upload_bmp, + gl_intformat, + gl_format, + gl_type, + error)) + { + cogl_object_unref (upload_bmp); + return FALSE; + } + + tex_rect->gl_format = gl_intformat; + tex_rect->internal_format = internal_format; + + cogl_object_unref (upload_bmp); + + _cogl_texture_set_allocated (COGL_TEXTURE (tex_rect), + internal_format, width, height); + + return TRUE; +} + +static CoglBool +allocate_from_gl_foreign (CoglTextureRectangle *tex_rect, + CoglTextureLoader *loader, + CoglError **error) +{ + CoglTexture *tex = COGL_TEXTURE (tex_rect); + CoglContext *ctx = tex->context; + CoglPixelFormat format = loader->src.gl_foreign.format; + GLint gl_compressed = GL_FALSE; + GLenum gl_int_format = 0; + + if (!ctx->texture_driver->allows_foreign_gl_target (ctx, + GL_TEXTURE_RECTANGLE_ARB)) + { + _cogl_set_error (error, + COGL_SYSTEM_ERROR, + COGL_SYSTEM_ERROR_UNSUPPORTED, + "Foreign GL_TEXTURE_RECTANGLE textures are not " + "supported by your system"); + return FALSE; + } + + /* Make sure binding succeeds */ + _cogl_gl_util_clear_gl_errors (ctx); + + _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB, + loader->src.gl_foreign.gl_handle, TRUE); + if (_cogl_gl_util_get_error (ctx) != GL_NO_ERROR) + { + _cogl_set_error (error, + COGL_SYSTEM_ERROR, + COGL_SYSTEM_ERROR_UNSUPPORTED, + "Failed to bind foreign GL_TEXTURE_RECTANGLE texture"); + return FALSE; + } + + /* Obtain texture parameters */ + +#ifdef HAVE_COGL_GL + if (_cogl_has_private_feature + (ctx, COGL_PRIVATE_FEATURE_QUERY_TEXTURE_PARAMETERS)) + { + GLint val; + + GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_RECTANGLE_ARB, 0, + GL_TEXTURE_COMPRESSED, + &gl_compressed) ); + + GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_RECTANGLE_ARB, 0, + GL_TEXTURE_INTERNAL_FORMAT, + &val) ); + + gl_int_format = val; + + /* If we can query GL for the actual pixel format then we'll ignore + the passed in format and use that. */ + if (!ctx->driver_vtable->pixel_format_from_gl_internal (ctx, + gl_int_format, + &format)) + { + _cogl_set_error (error, + COGL_SYSTEM_ERROR, + COGL_SYSTEM_ERROR_UNSUPPORTED, + "Unsupported internal format for foreign texture"); + return FALSE; + } + } + else +#endif + { + /* Otherwise we'll assume we can derive the GL format from the + passed in format */ + ctx->driver_vtable->pixel_format_to_gl (ctx, + format, + &gl_int_format, + NULL, + NULL); + } + + /* Compressed texture images not supported */ + if (gl_compressed == GL_TRUE) + { + _cogl_set_error (error, + COGL_SYSTEM_ERROR, + COGL_SYSTEM_ERROR_UNSUPPORTED, + "Compressed foreign textures aren't currently supported"); + return FALSE; + } + + /* Setup bitmap info */ + tex_rect->is_foreign = TRUE; + + tex_rect->gl_texture = loader->src.gl_foreign.gl_handle; + tex_rect->gl_format = gl_int_format; + + /* Unknown filter */ + tex_rect->gl_legacy_texobj_min_filter = GL_FALSE; + tex_rect->gl_legacy_texobj_mag_filter = GL_FALSE; + + tex_rect->internal_format = format; + + _cogl_texture_set_allocated (COGL_TEXTURE (tex_rect), + format, + loader->src.gl_foreign.width, + loader->src.gl_foreign.height); + + return TRUE; +} + +static CoglBool +_cogl_texture_rectangle_allocate (CoglTexture *tex, + CoglError **error) +{ + CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex); + CoglTextureLoader *loader = tex->loader; + + _COGL_RETURN_VAL_IF_FAIL (loader, FALSE); + + switch (loader->src_type) + { + case COGL_TEXTURE_SOURCE_TYPE_SIZED: + return allocate_with_size (tex_rect, loader, error); + case COGL_TEXTURE_SOURCE_TYPE_BITMAP: + return allocate_from_bitmap (tex_rect, loader, error); + case COGL_TEXTURE_SOURCE_TYPE_GL_FOREIGN: + return allocate_from_gl_foreign (tex_rect, loader, error); + default: + break; + } + + g_return_val_if_reached (FALSE); +} + +CoglTextureRectangle * +cogl_texture_rectangle_new_from_bitmap (CoglBitmap *bmp) +{ + CoglTextureLoader *loader; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_bitmap (bmp), NULL); + + loader = _cogl_texture_create_loader (); + loader->src_type = COGL_TEXTURE_SOURCE_TYPE_BITMAP; + loader->src.bitmap.bitmap = cogl_object_ref (bmp); + loader->src.bitmap.can_convert_in_place = FALSE; /* TODO add api for this */ + + return _cogl_texture_rectangle_create_base (_cogl_bitmap_get_context (bmp), + cogl_bitmap_get_width (bmp), + cogl_bitmap_get_height (bmp), + cogl_bitmap_get_format (bmp), + loader); +} + +CoglTextureRectangle * +cogl_texture_rectangle_new_from_foreign (CoglContext *ctx, + unsigned int gl_handle, + int width, + int height, + CoglPixelFormat format) +{ + CoglTextureLoader *loader; + + /* NOTE: width, height and internal format are not queriable in + * GLES, hence such a function prototype. Also in the case of full + * opengl the user may be creating a Cogl texture for a + * texture_from_pixmap object where glTexImage2D may not have been + * called and the texture_from_pixmap spec doesn't clarify that it + * is reliable to query back the size from OpenGL. + */ + + /* Assert that it is a valid GL texture object */ + _COGL_RETURN_VAL_IF_FAIL (ctx->glIsTexture (gl_handle), NULL); + + /* Validate width and height */ + _COGL_RETURN_VAL_IF_FAIL (width > 0 && height > 0, NULL); + + loader = _cogl_texture_create_loader (); + loader->src_type = COGL_TEXTURE_SOURCE_TYPE_GL_FOREIGN; + loader->src.gl_foreign.gl_handle = gl_handle; + loader->src.gl_foreign.width = width; + loader->src.gl_foreign.height = height; + loader->src.gl_foreign.format = format; + + return _cogl_texture_rectangle_create_base (ctx, width, height, + format, loader); +} + +static int +_cogl_texture_rectangle_get_max_waste (CoglTexture *tex) +{ + return -1; +} + +static CoglBool +_cogl_texture_rectangle_is_sliced (CoglTexture *tex) +{ + return FALSE; +} + +static CoglBool +_cogl_texture_rectangle_can_hardware_repeat (CoglTexture *tex) +{ + return FALSE; +} + +static void +_cogl_texture_rectangle_transform_coords_to_gl (CoglTexture *tex, + float *s, + float *t) +{ + *s *= tex->width; + *t *= tex->height; +} + +static CoglTransformResult +_cogl_texture_rectangle_transform_quad_coords_to_gl (CoglTexture *tex, + float *coords) +{ + CoglBool need_repeat = FALSE; + int i; + + for (i = 0; i < 4; i++) + { + if (coords[i] < 0.0f || coords[i] > 1.0f) + need_repeat = TRUE; + coords[i] *= (i & 1) ? tex->height : tex->width; + } + + return (need_repeat ? COGL_TRANSFORM_SOFTWARE_REPEAT + : COGL_TRANSFORM_NO_REPEAT); +} + +static CoglBool +_cogl_texture_rectangle_get_gl_texture (CoglTexture *tex, + GLuint *out_gl_handle, + GLenum *out_gl_target) +{ + CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex); + + if (out_gl_handle) + *out_gl_handle = tex_rect->gl_texture; + + if (out_gl_target) + *out_gl_target = GL_TEXTURE_RECTANGLE_ARB; + + return TRUE; +} + +static void +_cogl_texture_rectangle_gl_flush_legacy_texobj_filters (CoglTexture *tex, + GLenum min_filter, + GLenum mag_filter) +{ + CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex); + CoglContext *ctx = tex->context; + + if (min_filter == tex_rect->gl_legacy_texobj_min_filter + && mag_filter == tex_rect->gl_legacy_texobj_mag_filter) + return; + + /* Rectangle textures don't support mipmapping */ + g_assert (min_filter == GL_LINEAR || min_filter == GL_NEAREST); + + /* Store new values */ + tex_rect->gl_legacy_texobj_min_filter = min_filter; + tex_rect->gl_legacy_texobj_mag_filter = mag_filter; + + /* Apply new filters to the texture */ + _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB, + tex_rect->gl_texture, + tex_rect->is_foreign); + GE( ctx, glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, + mag_filter) ); + GE( ctx, glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, + min_filter) ); +} + +static void +_cogl_texture_rectangle_pre_paint (CoglTexture *tex, + CoglTexturePrePaintFlags flags) +{ + /* Rectangle textures don't support mipmaps */ + g_assert ((flags & COGL_TEXTURE_NEEDS_MIPMAP) == 0); +} + +static void +_cogl_texture_rectangle_ensure_non_quad_rendering (CoglTexture *tex) +{ + /* Nothing needs to be done */ +} + +static CoglBool +_cogl_texture_rectangle_set_region (CoglTexture *tex, + int src_x, + int src_y, + int dst_x, + int dst_y, + int dst_width, + int dst_height, + int level, + CoglBitmap *bmp, + CoglError **error) +{ + CoglBitmap *upload_bmp; + GLenum gl_format; + GLenum gl_type; + CoglContext *ctx = tex->context; + CoglBool status; + + upload_bmp = + _cogl_bitmap_convert_for_upload (bmp, + _cogl_texture_get_format (tex), + FALSE, /* can't convert in place */ + error); + if (upload_bmp == NULL) + return FALSE; + + ctx->driver_vtable->pixel_format_to_gl (ctx, + cogl_bitmap_get_format (upload_bmp), + NULL, /* internal format */ + &gl_format, + &gl_type); + + /* Send data to GL */ + status = + ctx->texture_driver->upload_subregion_to_gl (ctx, + tex, + FALSE, + src_x, src_y, + dst_x, dst_y, + dst_width, dst_height, + level, + upload_bmp, + gl_format, + gl_type, + error); + + cogl_object_unref (upload_bmp); + + return status; +} + +static CoglBool +_cogl_texture_rectangle_get_data (CoglTexture *tex, + CoglPixelFormat format, + int rowstride, + uint8_t *data) +{ + CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex); + CoglContext *ctx = tex->context; + int bpp; + GLenum gl_format; + GLenum gl_type; + + bpp = _cogl_pixel_format_get_bytes_per_pixel (format); + + ctx->driver_vtable->pixel_format_to_gl (ctx, + format, + NULL, /* internal format */ + &gl_format, + &gl_type); + + ctx->texture_driver->prep_gl_for_pixels_download (ctx, + rowstride, + tex->width, + bpp); + + _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB, + tex_rect->gl_texture, + tex_rect->is_foreign); + return ctx->texture_driver->gl_get_tex_image (ctx, + GL_TEXTURE_RECTANGLE_ARB, + gl_format, + gl_type, + data); +} + +static CoglPixelFormat +_cogl_texture_rectangle_get_format (CoglTexture *tex) +{ + return COGL_TEXTURE_RECTANGLE (tex)->internal_format; +} + +static GLenum +_cogl_texture_rectangle_get_gl_format (CoglTexture *tex) +{ + return COGL_TEXTURE_RECTANGLE (tex)->gl_format; +} + +static CoglBool +_cogl_texture_rectangle_is_foreign (CoglTexture *tex) +{ + return COGL_TEXTURE_RECTANGLE (tex)->is_foreign; +} + +static CoglTextureType +_cogl_texture_rectangle_get_type (CoglTexture *tex) +{ + return COGL_TEXTURE_TYPE_RECTANGLE; +} + +static const CoglTextureVtable +cogl_texture_rectangle_vtable = + { + TRUE, /* primitive */ + _cogl_texture_rectangle_allocate, + _cogl_texture_rectangle_set_region, + _cogl_texture_rectangle_get_data, + NULL, /* foreach_sub_texture_in_region */ + _cogl_texture_rectangle_get_max_waste, + _cogl_texture_rectangle_is_sliced, + _cogl_texture_rectangle_can_hardware_repeat, + _cogl_texture_rectangle_transform_coords_to_gl, + _cogl_texture_rectangle_transform_quad_coords_to_gl, + _cogl_texture_rectangle_get_gl_texture, + _cogl_texture_rectangle_gl_flush_legacy_texobj_filters, + _cogl_texture_rectangle_pre_paint, + _cogl_texture_rectangle_ensure_non_quad_rendering, + _cogl_texture_rectangle_gl_flush_legacy_texobj_wrap_modes, + _cogl_texture_rectangle_get_format, + _cogl_texture_rectangle_get_gl_format, + _cogl_texture_rectangle_get_type, + _cogl_texture_rectangle_is_foreign, + _cogl_texture_rectangle_set_auto_mipmap + }; diff --git a/cogl/cogl/cogl-texture-rectangle.h b/cogl/cogl/cogl-texture-rectangle.h new file mode 100644 index 0000000..c71f0f8 --- /dev/null +++ b/cogl/cogl/cogl-texture-rectangle.h @@ -0,0 +1,216 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_TEXURE_RECTANGLE_H +#define __COGL_TEXURE_RECTANGLE_H + +#include "cogl-context.h" + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-texture-rectangle + * @short_description: Functions for creating and manipulating rectangle + * textures for use with non-normalized coordinates. + * + * These functions allow low-level "rectangle" textures to be allocated. + * These textures are never constrained to power-of-two sizes but they + * also don't support having a mipmap and can only be wrapped with + * %COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE. + * + * The most notable difference between rectangle textures and 2D + * textures is that rectangle textures are sampled using un-normalized + * texture coordinates, so instead of using coordinates (0,0) and + * (1,1) to map to the top-left and bottom right corners of the + * texture you would instead use (0,0) and (width,height). + * + * The use of non-normalized coordinates can be particularly + * convenient when writing glsl shaders that use a texture as a lookup + * table since you don't need to upload separate uniforms to map + * normalized coordinates to texels. + * + * If you want to sample from a rectangle texture from GLSL you should + * use the sampler2DRect sampler type. + * + * Applications wanting to use #CoglTextureRectangle should first check + * for the %COGL_FEATURE_ID_TEXTURE_RECTANGLE feature using + * cogl_has_feature(). + */ + +typedef struct _CoglTextureRectangle CoglTextureRectangle; +#define COGL_TEXTURE_RECTANGLE(X) ((CoglTextureRectangle *)X) + +/** + * cogl_texture_rectangle_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_texture_rectangle_get_gtype (void); + +/** + * cogl_is_texture_rectangle: + * @object: A #CoglObject + * + * Gets whether the given object references an existing + * #CoglTextureRectangle object. + * + * Return value: %TRUE if the object references a + * #CoglTextureRectangle, %FALSE otherwise. + */ +CoglBool +cogl_is_texture_rectangle (void *object); + +/** + * cogl_texture_rectangle_new_with_size: + * @ctx: A #CoglContext pointer + * @width: The texture width to allocate + * @height: The texture height to allocate + * + * Creates a new #CoglTextureRectangle texture with a given @width, + * and @height. This texture is a low-level texture that the GPU can + * sample from directly unlike high-level textures such as + * #CoglTexture2DSliced and #CoglAtlasTexture. + * + * Unlike for #CoglTexture2D textures, coordinates for + * #CoglTextureRectangle textures should not be normalized. So instead + * of using the coordinate (1, 1) to sample the bottom right corner of + * a rectangle texture you would use (@width, @height) where @width + * and @height are the width and height of the texture. + * + * If you want to sample from a rectangle texture from GLSL you + * should use the sampler2DRect sampler type. + * + * Applications wanting to use #CoglTextureRectangle should + * first check for the %COGL_FEATURE_ID_TEXTURE_RECTANGLE feature + * using cogl_has_feature(). + * + * The storage for the texture is not allocated before this function + * returns. You can call cogl_texture_allocate() to explicitly + * allocate the underlying storage or preferably let Cogl + * automatically allocate storage lazily when it may know more about + * how the texture is going to be used and can optimize how it is + * allocated. + * + * Returns value: (transfer full): A pointer to a new #CoglTextureRectangle + * object with no storage allocated yet. + * + * Since: 1.10 + * Stability: unstable + */ +CoglTextureRectangle * +cogl_texture_rectangle_new_with_size (CoglContext *ctx, + int width, + int height); + +/** + * cogl_texture_rectangle_new_from_bitmap: + * @bitmap: A #CoglBitmap + * + * Allocates a new #CoglTextureRectangle texture which will be + * initialized with the pixel data from @bitmap. This texture is a + * low-level texture that the GPU can sample from directly unlike + * high-level textures such as #CoglTexture2DSliced and + * #CoglAtlasTexture. + * + * Unlike for #CoglTexture2D textures, coordinates for + * #CoglTextureRectangle textures should not be normalized. So instead + * of using the coordinate (1, 1) to sample the bottom right corner of + * a rectangle texture you would use (@width, @height) where @width + * and @height are the width and height of the texture. + * + * If you want to sample from a rectangle texture from GLSL you + * should use the sampler2DRect sampler type. + * + * Applications wanting to use #CoglTextureRectangle should + * first check for the %COGL_FEATURE_ID_TEXTURE_RECTANGLE feature + * using cogl_has_feature(). + * + * The storage for the texture is not allocated before this function + * returns. You can call cogl_texture_allocate() to explicitly + * allocate the underlying storage or preferably let Cogl + * automatically allocate storage lazily when it may know more about + * how the texture is going to be used and can optimize how it is + * allocated. + * + * Return value: (transfer full): A pointer to a new + * #CoglTextureRectangle texture. + * Since: 2.0 + * Stability: unstable + */ +CoglTextureRectangle * +cogl_texture_rectangle_new_from_bitmap (CoglBitmap *bitmap); + +/** + * cogl_texture_rectangle_new_from_foreign: + * @ctx: A #CoglContext + * @gl_handle: A GL handle for a GL_TEXTURE_RECTANGLE texture object + * @width: Width of the foreign GL texture + * @height: Height of the foreign GL texture + * @format: The format of the texture + * + * Wraps an existing GL_TEXTURE_RECTANGLE texture object as a + * #CoglTextureRectangle. This can be used for integrating Cogl with + * software using OpenGL directly. + * + * Unlike for #CoglTexture2D textures, coordinates for + * #CoglTextureRectangle textures should not be normalized. So instead + * of using the coordinate (1, 1) to sample the bottom right corner of + * a rectangle texture you would use (@width, @height) where @width + * and @height are the width and height of the texture. + * + * The results are undefined for passing an invalid @gl_handle + * or if @width or @height don't have the correct texture + * geometry. + * + * If you want to sample from a rectangle texture from GLSL you + * should use the sampler2DRect sampler type. + * + * Applications wanting to use #CoglTextureRectangle should + * first check for the %COGL_FEATURE_ID_TEXTURE_RECTANGLE feature + * using cogl_has_feature(). + * + * The texture is still configurable until it has been allocated so + * for example you can declare whether the texture is premultiplied + * with cogl_texture_set_premultiplied(). + * + * Return value: (transfer full): A new #CoglTextureRectangle texture + */ +CoglTextureRectangle * +cogl_texture_rectangle_new_from_foreign (CoglContext *ctx, + unsigned int gl_handle, + int width, + int height, + CoglPixelFormat format); + +COGL_END_DECLS + +#endif /* __COGL_TEXURE_RECTANGLE_H */ diff --git a/cogl/cogl/cogl-texture.c b/cogl/cogl/cogl-texture.c new file mode 100644 index 0000000..40aaa3b --- /dev/null +++ b/cogl/cogl/cogl-texture.c @@ -0,0 +1,1540 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. + * Copyright (C) 2010 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Matthew Allum + * Neil Roberts + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-util.h" +#include "cogl-bitmap.h" +#include "cogl-bitmap-private.h" +#include "cogl-buffer-private.h" +#include "cogl-pixel-buffer-private.h" +#include "cogl-private.h" +#include "cogl-texture-private.h" +#include "cogl-texture-driver.h" +#include "cogl-texture-2d-sliced-private.h" +#include "cogl-texture-2d-private.h" +#include "cogl-texture-2d-gl.h" +#include "cogl-texture-3d-private.h" +#include "cogl-texture-rectangle-private.h" +#include "cogl-sub-texture-private.h" +#include "cogl-atlas-texture-private.h" +#include "cogl-pipeline.h" +#include "cogl-context-private.h" +#include "cogl-object-private.h" +#include "cogl-object-private.h" +#include "cogl-primitives.h" +#include "cogl-framebuffer-private.h" +#include "cogl1-context.h" +#include "cogl-sub-texture.h" +#include "cogl-primitive-texture.h" +#include "cogl-error-private.h" +#include "cogl-gtype-private.h" + +#include +#include +#include + +/* This isn't defined in the GLES headers */ +#ifndef GL_RED +#define GL_RED 0x1903 +#endif + +COGL_GTYPE_DEFINE_INTERFACE (Texture, texture); + +uint32_t +cogl_texture_error_quark (void) +{ + return g_quark_from_static_string ("cogl-texture-error-quark"); +} + +/* XXX: + * The CoglObject macros don't support any form of inheritance, so for + * now we implement the CoglObject support for the CoglTexture + * abstract class manually. + */ + +static GSList *_cogl_texture_types; + +void +_cogl_texture_register_texture_type (const CoglObjectClass *klass) +{ + _cogl_texture_types = g_slist_prepend (_cogl_texture_types, (void *) klass); +} + +CoglBool +cogl_is_texture (void *object) +{ + CoglObject *obj = (CoglObject *)object; + GSList *l; + + if (object == NULL) + return FALSE; + + for (l = _cogl_texture_types; l; l = l->next) + if (l->data == obj->klass) + return TRUE; + + return FALSE; +} + +void +_cogl_texture_init (CoglTexture *texture, + CoglContext *context, + int width, + int height, + CoglPixelFormat src_format, + CoglTextureLoader *loader, + const CoglTextureVtable *vtable) +{ + texture->context = context; + texture->max_level = 0; + texture->width = width; + texture->height = height; + texture->allocated = FALSE; + texture->vtable = vtable; + texture->framebuffers = NULL; + + texture->loader = loader; + + _cogl_texture_set_internal_format (texture, src_format); + + /* Although we want to initialize texture::components according + * to the source format, we always want the internal layout to + * be considered premultiplied by default. + * + * NB: this ->premultiplied state is user configurable so to avoid + * awkward documentation, setting this to 'true' does not depend on + * ->components having an alpha component (we will simply ignore the + * premultiplied status later if there is no alpha component). + * This way we don't have to worry about updating the + * ->premultiplied state in _set_components(). Similarly we don't + * have to worry about updating the ->components state in + * _set_premultiplied(). + */ + texture->premultiplied = TRUE; +} + +static void +_cogl_texture_free_loader (CoglTexture *texture) +{ + if (texture->loader) + { + CoglTextureLoader *loader = texture->loader; + switch (loader->src_type) + { + case COGL_TEXTURE_SOURCE_TYPE_SIZED: + case COGL_TEXTURE_SOURCE_TYPE_EGL_IMAGE: + case COGL_TEXTURE_SOURCE_TYPE_GL_FOREIGN: + break; + case COGL_TEXTURE_SOURCE_TYPE_BITMAP: + cogl_object_unref (loader->src.bitmap.bitmap); + break; + } + g_slice_free (CoglTextureLoader, loader); + texture->loader = NULL; + } +} + +CoglTextureLoader * +_cogl_texture_create_loader (void) +{ + return g_slice_new0 (CoglTextureLoader); +} + +void +_cogl_texture_free (CoglTexture *texture) +{ + _cogl_texture_free_loader (texture); + + g_free (texture); +} + +CoglBool +_cogl_texture_needs_premult_conversion (CoglPixelFormat src_format, + CoglPixelFormat dst_format) +{ + return ((src_format & dst_format & COGL_A_BIT) && + src_format != COGL_PIXEL_FORMAT_A_8 && + dst_format != COGL_PIXEL_FORMAT_A_8 && + (src_format & COGL_PREMULT_BIT) != + (dst_format & COGL_PREMULT_BIT)); +} + +CoglBool +_cogl_texture_is_foreign (CoglTexture *texture) +{ + if (texture->vtable->is_foreign) + return texture->vtable->is_foreign (texture); + else + return FALSE; +} + +unsigned int +cogl_texture_get_width (CoglTexture *texture) +{ + return texture->width; +} + +unsigned int +cogl_texture_get_height (CoglTexture *texture) +{ + return texture->height; +} + +CoglPixelFormat +_cogl_texture_get_format (CoglTexture *texture) +{ + if (!texture->allocated) + cogl_texture_allocate (texture, NULL); + return texture->vtable->get_format (texture); +} + +int +cogl_texture_get_max_waste (CoglTexture *texture) +{ + return texture->vtable->get_max_waste (texture); +} + +int +_cogl_texture_get_n_levels (CoglTexture *texture) +{ + int width = cogl_texture_get_width (texture); + int height = cogl_texture_get_height (texture); + int max_dimension = MAX (width, height); + + if (cogl_is_texture_3d (texture)) + { + CoglTexture3D *tex_3d = COGL_TEXTURE_3D (texture); + max_dimension = MAX (max_dimension, tex_3d->depth); + } + + return _cogl_util_fls (max_dimension); +} + +void +_cogl_texture_get_level_size (CoglTexture *texture, + int level, + int *width, + int *height, + int *depth) +{ + int current_width = cogl_texture_get_width (texture); + int current_height = cogl_texture_get_height (texture); + int current_depth; + int i; + + if (cogl_is_texture_3d (texture)) + { + CoglTexture3D *tex_3d = COGL_TEXTURE_3D (texture); + current_depth = tex_3d->depth; + } + else + current_depth = 0; + + /* NB: The OpenGL spec (like D3D) uses a floor() convention to + * round down the size of a mipmap level when dividing the size + * of the previous level results in a fraction... + */ + for (i = 0; i < level; i++) + { + current_width = MAX (1, current_width >> 1); + current_height = MAX (1, current_height >> 1); + current_depth = MAX (1, current_depth >> 1); + } + + if (width) + *width = current_width; + if (height) + *height = current_height; + if (depth) + *depth = current_depth; +} + +CoglBool +cogl_texture_is_sliced (CoglTexture *texture) +{ + if (!texture->allocated) + cogl_texture_allocate (texture, NULL); + return texture->vtable->is_sliced (texture); +} + +/* If this returns FALSE, that implies _foreach_sub_texture_in_region + * will be needed to iterate over multiple sub textures for regions whos + * texture coordinates extend out of the range [0,1] + */ +CoglBool +_cogl_texture_can_hardware_repeat (CoglTexture *texture) +{ + if (!texture->allocated) + cogl_texture_allocate (texture, NULL); + return texture->vtable->can_hardware_repeat (texture); +} + +/* NB: You can't use this with textures comprised of multiple sub textures (use + * cogl_texture_is_sliced() to check) since coordinate transformation for such + * textures will be different for each slice. */ +void +_cogl_texture_transform_coords_to_gl (CoglTexture *texture, + float *s, + float *t) +{ + texture->vtable->transform_coords_to_gl (texture, s, t); +} + +CoglTransformResult +_cogl_texture_transform_quad_coords_to_gl (CoglTexture *texture, + float *coords) +{ + return texture->vtable->transform_quad_coords_to_gl (texture, coords); +} + +CoglBool +cogl_texture_get_gl_texture (CoglTexture *texture, + GLuint *out_gl_handle, + GLenum *out_gl_target) +{ + if (!texture->allocated) + cogl_texture_allocate (texture, NULL); + + return texture->vtable->get_gl_texture (texture, + out_gl_handle, out_gl_target); +} + +CoglTextureType +_cogl_texture_get_type (CoglTexture *texture) +{ + return texture->vtable->get_type (texture); +} + +void +_cogl_texture_pre_paint (CoglTexture *texture, CoglTexturePrePaintFlags flags) +{ + /* Assert that the storage for the texture exists already if we're + * about to reference it for painting. + * + * Note: we abort on error here since it's a bit late to do anything + * about it if we fail to allocate the texture and the app could + * have explicitly allocated the texture earlier to handle problems + * gracefully. + * + * XXX: Maybe it could even be considered a programmer error if the + * texture hasn't been allocated by this point since it implies we + * are abount to paint with undefined texture contents? + */ + cogl_texture_allocate (texture, NULL); + + texture->vtable->pre_paint (texture, flags); +} + +void +_cogl_texture_ensure_non_quad_rendering (CoglTexture *texture) +{ + texture->vtable->ensure_non_quad_rendering (texture); +} + +CoglBool +_cogl_texture_set_region_from_bitmap (CoglTexture *texture, + int src_x, + int src_y, + int width, + int height, + CoglBitmap *bmp, + int dst_x, + int dst_y, + int level, + CoglError **error) +{ + _COGL_RETURN_VAL_IF_FAIL ((cogl_bitmap_get_width (bmp) - src_x) + >= width, FALSE); + _COGL_RETURN_VAL_IF_FAIL ((cogl_bitmap_get_height (bmp) - src_y) + >= height, FALSE); + _COGL_RETURN_VAL_IF_FAIL (width > 0, FALSE); + _COGL_RETURN_VAL_IF_FAIL (height > 0, FALSE); + + /* Assert that the storage for this texture has been allocated */ + if (!cogl_texture_allocate (texture, error)) + return FALSE; + + /* Note that we don't prepare the bitmap for upload here because + some backends may be internally using a different format for the + actual GL texture than that reported by + _cogl_texture_get_format. For example the atlas textures are + always stored in an RGBA texture even if the texture format is + advertised as RGB. */ + + return texture->vtable->set_region (texture, + src_x, src_y, + dst_x, dst_y, + width, height, + level, + bmp, + error); +} + +CoglBool +cogl_texture_set_region_from_bitmap (CoglTexture *texture, + int src_x, + int src_y, + int dst_x, + int dst_y, + unsigned int dst_width, + unsigned int dst_height, + CoglBitmap *bitmap) +{ + CoglError *ignore_error = NULL; + CoglBool status = + _cogl_texture_set_region_from_bitmap (texture, + src_x, src_y, + dst_width, dst_height, + bitmap, + dst_x, dst_y, + 0, /* level */ + &ignore_error); + + if (!status) + cogl_error_free (ignore_error); + return status; +} + +CoglBool +_cogl_texture_set_region (CoglTexture *texture, + int width, + int height, + CoglPixelFormat format, + int rowstride, + const uint8_t *data, + int dst_x, + int dst_y, + int level, + CoglError **error) +{ + CoglContext *ctx = texture->context; + CoglBitmap *source_bmp; + CoglBool ret; + + _COGL_RETURN_VAL_IF_FAIL (format != COGL_PIXEL_FORMAT_ANY, FALSE); + + /* Rowstride from width if none specified */ + if (rowstride == 0) + rowstride = _cogl_pixel_format_get_bytes_per_pixel (format) * width; + + /* Init source bitmap */ + source_bmp = cogl_bitmap_new_for_data (ctx, + width, height, + format, + rowstride, + (uint8_t *) data); + + ret = _cogl_texture_set_region_from_bitmap (texture, + 0, 0, + width, height, + source_bmp, + dst_x, dst_y, + level, + error); + + cogl_object_unref (source_bmp); + + return ret; +} + +CoglBool +cogl_texture_set_region (CoglTexture *texture, + int src_x, + int src_y, + int dst_x, + int dst_y, + unsigned int dst_width, + unsigned int dst_height, + int width, + int height, + CoglPixelFormat format, + unsigned int rowstride, + const uint8_t *data) +{ + CoglError *ignore_error = NULL; + const uint8_t *first_pixel; + int bytes_per_pixel = _cogl_pixel_format_get_bytes_per_pixel (format); + CoglBool status; + + /* Rowstride from width if none specified */ + if (rowstride == 0) + rowstride = bytes_per_pixel * width; + + first_pixel = data + rowstride * src_y + bytes_per_pixel * src_x; + + status = _cogl_texture_set_region (texture, + dst_width, + dst_height, + format, + rowstride, + first_pixel, + dst_x, + dst_y, + 0, + &ignore_error); + if (!status) + cogl_error_free (ignore_error); + return status; +} + +CoglBool +cogl_texture_set_data (CoglTexture *texture, + CoglPixelFormat format, + int rowstride, + const uint8_t *data, + int level, + CoglError **error) +{ + int level_width; + int level_height; + + _cogl_texture_get_level_size (texture, + level, + &level_width, + &level_height, + NULL); + + return _cogl_texture_set_region (texture, + level_width, + level_height, + format, + rowstride, + data, + 0, 0, /* dest x, y */ + level, + error); +} + +/* Reads back the contents of a texture by rendering it to the framebuffer + * and reading back the resulting pixels. + * + * It will perform multiple renders if the texture is larger than the + * current glViewport. + * + * It assumes the projection and modelview have already been setup so + * that rendering to 0,0 with the same width and height of the viewport + * will exactly cover the viewport. + * + * NB: Normally this approach isn't normally used since we can just use + * glGetTexImage, but may be used as a fallback in some circumstances. + */ +static CoglBool +do_texture_draw_and_read (CoglFramebuffer *fb, + CoglPipeline *pipeline, + CoglTexture *texture, + CoglBitmap *target_bmp, + float *viewport, + CoglError **error) +{ + float rx1, ry1; + float rx2, ry2; + float tx1, ty1; + float tx2, ty2; + int bw, bh; + CoglBitmap *rect_bmp; + unsigned int tex_width, tex_height; + CoglContext *ctx = fb->context; + + tex_width = cogl_texture_get_width (texture); + tex_height = cogl_texture_get_height (texture); + + ry2 = 0; + ty2 = 0; + + /* Walk Y axis until whole bitmap height consumed */ + for (bh = tex_height; bh > 0; bh -= viewport[3]) + { + /* Rectangle Y coords */ + ry1 = ry2; + ry2 += (bh < viewport[3]) ? bh : viewport[3]; + + /* Normalized texture Y coords */ + ty1 = ty2; + ty2 = (ry2 / (float) tex_height); + + rx2 = 0; + tx2 = 0; + + /* Walk X axis until whole bitmap width consumed */ + for (bw = tex_width; bw > 0; bw-=viewport[2]) + { + int width; + int height; + + /* Rectangle X coords */ + rx1 = rx2; + rx2 += (bw < viewport[2]) ? bw : viewport[2]; + + width = rx2 - rx1; + height = ry2 - ry1; + + /* Normalized texture X coords */ + tx1 = tx2; + tx2 = (rx2 / (float) tex_width); + + /* Draw a portion of texture */ + cogl_framebuffer_draw_textured_rectangle (fb, + pipeline, + 0, 0, + rx2 - rx1, + ry2 - ry1, + tx1, ty1, + tx2, ty2); + + /* Read into a temporary bitmap */ + rect_bmp = _cogl_bitmap_new_with_malloc_buffer + (ctx, + width, height, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + error); + if (!rect_bmp) + return FALSE; + + if (!_cogl_framebuffer_read_pixels_into_bitmap + (fb, + viewport[0], viewport[1], + COGL_READ_PIXELS_COLOR_BUFFER, + rect_bmp, + error)) + { + cogl_object_unref (rect_bmp); + return FALSE; + } + + /* Copy to target bitmap */ + if (!_cogl_bitmap_copy_subregion (rect_bmp, + target_bmp, + 0, 0, + rx1, ry1, + width, + height, + error)) + { + cogl_object_unref (rect_bmp); + return FALSE; + } + + /* Free temp bitmap */ + cogl_object_unref (rect_bmp); + } + } + + return TRUE; +} + +/* Reads back the contents of a texture by rendering it to the framebuffer + * and reading back the resulting pixels. + * + * NB: Normally this approach isn't normally used since we can just use + * glGetTexImage, but may be used as a fallback in some circumstances. + */ +static CoglBool +_cogl_texture_draw_and_read (CoglTexture *texture, + CoglBitmap *target_bmp, + GLuint target_gl_format, + GLuint target_gl_type, + CoglError **error) +{ + CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer (); + CoglContext *ctx = framebuffer->context; + float save_viewport[4]; + float viewport[4]; + CoglBool status = FALSE; + + viewport[0] = 0; + viewport[1] = 0; + viewport[2] = cogl_framebuffer_get_width (framebuffer); + viewport[3] = cogl_framebuffer_get_height (framebuffer); + + cogl_framebuffer_get_viewport4fv (framebuffer, save_viewport); + _cogl_framebuffer_push_projection (framebuffer); + cogl_framebuffer_orthographic (framebuffer, + 0, 0, + viewport[2], + viewport[3], + 0, 100); + + cogl_framebuffer_push_matrix (framebuffer); + cogl_framebuffer_identity_matrix (framebuffer); + + /* Direct copy operation */ + + if (ctx->texture_download_pipeline == NULL) + { + ctx->texture_download_pipeline = cogl_pipeline_new (ctx); + cogl_pipeline_set_blend (ctx->texture_download_pipeline, + "RGBA = ADD (SRC_COLOR, 0)", + NULL); + } + + cogl_pipeline_set_layer_texture (ctx->texture_download_pipeline, 0, texture); + + cogl_pipeline_set_layer_combine (ctx->texture_download_pipeline, + 0, /* layer */ + "RGBA = REPLACE (TEXTURE)", + NULL); + + cogl_pipeline_set_layer_filters (ctx->texture_download_pipeline, 0, + COGL_PIPELINE_FILTER_NEAREST, + COGL_PIPELINE_FILTER_NEAREST); + + if (!do_texture_draw_and_read (framebuffer, + ctx->texture_download_pipeline, + texture, target_bmp, viewport, + error)) + return FALSE; + + /* XXX: As an alleged PowerVR driver bug workaround where the driver + * is apparently not maintaining the alpha component of some + * framebuffers we render the alpha component of the texture + * separately to be sure we retrieve all components of the texture. + * + * TODO: verify if this is still an issue + */ + if ((_cogl_texture_get_format (texture) & COGL_A_BIT)/* && a_bits == 0*/) + { + uint8_t *srcdata; + uint8_t *dstdata; + uint8_t *srcpixel; + uint8_t *dstpixel; + int target_width = cogl_bitmap_get_width (target_bmp); + int target_height = cogl_bitmap_get_height (target_bmp); + int target_rowstride = cogl_bitmap_get_rowstride (target_bmp); + int bpp = _cogl_pixel_format_get_bytes_per_pixel (COGL_PIXEL_FORMAT_RGBA_8888); + int alpha_rowstride = bpp * target_width; + CoglBitmap *alpha_bmp; + int x,y; + + if ((dstdata = _cogl_bitmap_map (target_bmp, + COGL_BUFFER_ACCESS_WRITE, + COGL_BUFFER_MAP_HINT_DISCARD, + error)) == NULL) + goto EXIT; + + /* Create temp bitmap for alpha values */ + alpha_bmp = + _cogl_bitmap_new_with_malloc_buffer (ctx, + target_width, + target_height, + COGL_PIXEL_FORMAT_RGBA_8888, + error); + if (!alpha_bmp) + { + _cogl_bitmap_unmap (target_bmp); + goto EXIT; + } + + + /* Draw alpha values into RGB channels */ + cogl_pipeline_set_layer_combine (ctx->texture_download_pipeline, + 0, /* layer */ + "RGBA = REPLACE (TEXTURE[A])", + NULL); + + if (!do_texture_draw_and_read (framebuffer, + ctx->texture_download_pipeline, + texture, alpha_bmp, viewport, + error)) + { + cogl_object_unref (alpha_bmp); + _cogl_bitmap_unmap (target_bmp); + goto EXIT; + } + + /* Copy temp R to target A */ + + /* Note: we don't try to catch errors since "mapping" an + * malloc buffer should never fail */ + srcdata = _cogl_bitmap_map (alpha_bmp, + COGL_BUFFER_ACCESS_READ, + 0 /* hints */, + NULL); + + for (y=0; ycontext; + CoglOffscreen *offscreen; + CoglFramebuffer *framebuffer; + CoglBitmap *bitmap; + CoglBool ret; + CoglError *ignore_error = NULL; + CoglPixelFormat real_format; + + if (!cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN)) + return FALSE; + + offscreen = _cogl_offscreen_new_with_texture_full + (sub_texture, + COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL, + 0); + + framebuffer = COGL_FRAMEBUFFER (offscreen); + if (!cogl_framebuffer_allocate (framebuffer, &ignore_error)) + { + cogl_error_free (ignore_error); + return FALSE; + } + + /* Currently the framebuffer's internal format corresponds to the + * internal format of @sub_texture but in the case of atlas textures + * it's possible that this format doesn't reflect the correct + * premultiplied alpha status or what components are valid since + * atlas textures are always stored in a shared texture with a + * format of _RGBA_8888. + * + * Here we override the internal format to make sure the + * framebuffer's internal format matches the internal format of the + * parent meta_texture instead. + */ + real_format = _cogl_texture_get_format (meta_texture); + _cogl_framebuffer_set_internal_format (framebuffer, real_format); + + bitmap = cogl_bitmap_new_for_data (ctx, + width, height, + closest_format, + dst_rowstride, + dst_bits); + ret = _cogl_framebuffer_read_pixels_into_bitmap (framebuffer, + x, y, + COGL_READ_PIXELS_COLOR_BUFFER, + bitmap, + &ignore_error); + + if (!ret) + cogl_error_free (ignore_error); + + cogl_object_unref (bitmap); + + cogl_object_unref (framebuffer); + + return ret; +} + +static CoglBool +get_texture_bits_via_copy (CoglTexture *texture, + int x, + int y, + int width, + int height, + uint8_t *dst_bits, + unsigned int dst_rowstride, + CoglPixelFormat dst_format) +{ + unsigned int full_rowstride; + uint8_t *full_bits; + CoglBool ret = TRUE; + int bpp; + int full_tex_width, full_tex_height; + + full_tex_width = cogl_texture_get_width (texture); + full_tex_height = cogl_texture_get_height (texture); + + bpp = _cogl_pixel_format_get_bytes_per_pixel (dst_format); + + full_rowstride = bpp * full_tex_width; + full_bits = g_malloc (full_rowstride * full_tex_height); + + if (texture->vtable->get_data (texture, + dst_format, + full_rowstride, + full_bits)) + { + uint8_t *dst = dst_bits; + uint8_t *src = full_bits + x * bpp + y * full_rowstride; + int i; + + for (i = 0; i < height; i++) + { + memcpy (dst, src, bpp * width); + dst += dst_rowstride; + src += full_rowstride; + } + } + else + ret = FALSE; + + g_free (full_bits); + + return ret; +} + +typedef struct +{ + CoglTexture *meta_texture; + int orig_width; + int orig_height; + CoglBitmap *target_bmp; + uint8_t *target_bits; + CoglBool success; + CoglError *error; +} CoglTextureGetData; + +static void +texture_get_cb (CoglTexture *subtexture, + const float *subtexture_coords, + const float *virtual_coords, + void *user_data) +{ + CoglTextureGetData *tg_data = user_data; + CoglTexture *meta_texture = tg_data->meta_texture; + CoglPixelFormat closest_format = cogl_bitmap_get_format (tg_data->target_bmp); + int bpp = _cogl_pixel_format_get_bytes_per_pixel (closest_format); + unsigned int rowstride = cogl_bitmap_get_rowstride (tg_data->target_bmp); + int subtexture_width = cogl_texture_get_width (subtexture); + int subtexture_height = cogl_texture_get_height (subtexture); + + int x_in_subtexture = (int) (0.5 + subtexture_width * subtexture_coords[0]); + int y_in_subtexture = (int) (0.5 + subtexture_height * subtexture_coords[1]); + int width = ((int) (0.5 + subtexture_width * subtexture_coords[2]) + - x_in_subtexture); + int height = ((int) (0.5 + subtexture_height * subtexture_coords[3]) + - y_in_subtexture); + int x_in_bitmap = (int) (0.5 + tg_data->orig_width * virtual_coords[0]); + int y_in_bitmap = (int) (0.5 + tg_data->orig_height * virtual_coords[1]); + + uint8_t *dst_bits; + + if (!tg_data->success) + return; + + dst_bits = tg_data->target_bits + x_in_bitmap * bpp + y_in_bitmap * rowstride; + + /* If we can read everything as a single slice, then go ahead and do that + * to avoid allocating an FBO. We'll leave it up to the GL implementation to + * do glGetTexImage as efficiently as possible. (GLES doesn't have that, + * so we'll fall through) + */ + if (x_in_subtexture == 0 && y_in_subtexture == 0 && + width == subtexture_width && height == subtexture_height) + { + if (subtexture->vtable->get_data (subtexture, + closest_format, + rowstride, + dst_bits)) + return; + } + + /* Next best option is a FBO and glReadPixels */ + if (get_texture_bits_via_offscreen (meta_texture, + subtexture, + x_in_subtexture, y_in_subtexture, + width, height, + dst_bits, + rowstride, + closest_format)) + return; + + /* Getting ugly: read the entire texture, copy out the part we want */ + if (get_texture_bits_via_copy (subtexture, + x_in_subtexture, y_in_subtexture, + width, height, + dst_bits, + rowstride, + closest_format)) + return; + + /* No luck, the caller will fall back to the draw-to-backbuffer and + * read implementation */ + tg_data->success = FALSE; +} + +int +cogl_texture_get_data (CoglTexture *texture, + CoglPixelFormat format, + unsigned int rowstride, + uint8_t *data) +{ + CoglContext *ctx = texture->context; + int bpp; + int byte_size; + CoglPixelFormat closest_format; + GLenum closest_gl_format; + GLenum closest_gl_type; + CoglBitmap *target_bmp; + int tex_width; + int tex_height; + CoglPixelFormat texture_format; + CoglError *ignore_error = NULL; + + CoglTextureGetData tg_data; + + texture_format = _cogl_texture_get_format (texture); + + /* Default to internal format if none specified */ + if (format == COGL_PIXEL_FORMAT_ANY) + format = texture_format; + + tex_width = cogl_texture_get_width (texture); + tex_height = cogl_texture_get_height (texture); + + /* Rowstride from texture width if none specified */ + bpp = _cogl_pixel_format_get_bytes_per_pixel (format); + if (rowstride == 0) + rowstride = tex_width * bpp; + + /* Return byte size if only that requested */ + byte_size = tex_height * rowstride; + if (data == NULL) + return byte_size; + + closest_format = + ctx->texture_driver->find_best_gl_get_data_format (ctx, + format, + &closest_gl_format, + &closest_gl_type); + + /* We can assume that whatever data GL gives us will have the + premult status of the original texture */ + if (COGL_PIXEL_FORMAT_CAN_HAVE_PREMULT (closest_format)) + closest_format = ((closest_format & ~COGL_PREMULT_BIT) | + (texture_format & COGL_PREMULT_BIT)); + + /* If the application is requesting a conversion from a + * component-alpha texture and the driver doesn't support them + * natively then we can only read into an alpha-format buffer. In + * this case the driver will be faking the alpha textures with a + * red-component texture and it won't swizzle to the correct format + * while reading */ + if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_ALPHA_TEXTURES)) + { + if (texture_format == COGL_PIXEL_FORMAT_A_8) + { + closest_format = COGL_PIXEL_FORMAT_A_8; + closest_gl_format = GL_RED; + closest_gl_type = GL_UNSIGNED_BYTE; + } + else if (format == COGL_PIXEL_FORMAT_A_8) + { + /* If we are converting to a component-alpha texture then we + * need to read all of the components to a temporary buffer + * because there is no way to get just the 4th component. + * Note: it doesn't matter whether the texture is + * pre-multiplied here because we're only going to look at + * the alpha component */ + closest_format = COGL_PIXEL_FORMAT_RGBA_8888; + closest_gl_format = GL_RGBA; + closest_gl_type = GL_UNSIGNED_BYTE; + } + } + + /* Is the requested format supported? */ + if (closest_format == format) + /* Target user data directly */ + target_bmp = cogl_bitmap_new_for_data (ctx, + tex_width, + tex_height, + format, + rowstride, + data); + else + { + target_bmp = _cogl_bitmap_new_with_malloc_buffer (ctx, + tex_width, tex_height, + closest_format, + &ignore_error); + if (!target_bmp) + { + cogl_error_free (ignore_error); + return 0; + } + } + + tg_data.target_bits = _cogl_bitmap_map (target_bmp, COGL_BUFFER_ACCESS_WRITE, + COGL_BUFFER_MAP_HINT_DISCARD, + &ignore_error); + if (tg_data.target_bits) + { + tg_data.meta_texture = texture; + tg_data.orig_width = tex_width; + tg_data.orig_height = tex_height; + tg_data.target_bmp = target_bmp; + tg_data.error = NULL; + tg_data.success = TRUE; + + /* If there are any dependent framebuffers on the texture then we + need to flush their journals so the texture contents will be + up-to-date */ + _cogl_texture_flush_journal_rendering (texture); + + /* Iterating through the subtextures allows piecing together + * the data for a sliced texture, and allows us to do the + * read-from-framebuffer logic here in a simple fashion rather than + * passing offsets down through the code. */ + cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (texture), + 0, 0, 1, 1, + COGL_PIPELINE_WRAP_MODE_REPEAT, + COGL_PIPELINE_WRAP_MODE_REPEAT, + texture_get_cb, + &tg_data); + + _cogl_bitmap_unmap (target_bmp); + } + else + { + cogl_error_free (ignore_error); + tg_data.success = FALSE; + } + + /* XXX: In some cases _cogl_texture_2d_download_from_gl may fail + * to read back the texture data; such as for GLES which doesn't + * support glGetTexImage, so here we fallback to drawing the + * texture and reading the pixels from the framebuffer. */ + if (!tg_data.success) + { + if (!_cogl_texture_draw_and_read (texture, target_bmp, + closest_gl_format, + closest_gl_type, + &ignore_error)) + { + /* We have no more fallbacks so we just give up and + * hope for the best */ + g_warning ("Failed to read texture since draw-and-read " + "fallback failed: %s", ignore_error->message); + cogl_error_free (ignore_error); + cogl_object_unref (target_bmp); + return 0; + } + } + + /* Was intermediate used? */ + if (closest_format != format) + { + CoglBitmap *new_bmp; + CoglBool result; + CoglError *error = NULL; + + /* Convert to requested format directly into the user's buffer */ + new_bmp = cogl_bitmap_new_for_data (ctx, + tex_width, tex_height, + format, + rowstride, + data); + result = _cogl_bitmap_convert_into_bitmap (target_bmp, new_bmp, &error); + + if (!result) + { + cogl_error_free (error); + /* Return failure after cleaning up */ + byte_size = 0; + } + + cogl_object_unref (new_bmp); + } + + cogl_object_unref (target_bmp); + + return byte_size; +} + +static void +_cogl_texture_framebuffer_destroy_cb (void *user_data, + void *instance) +{ + CoglTexture *tex = user_data; + CoglFramebuffer *framebuffer = instance; + + tex->framebuffers = g_list_remove (tex->framebuffers, framebuffer); +} + +void +_cogl_texture_associate_framebuffer (CoglTexture *texture, + CoglFramebuffer *framebuffer) +{ + static CoglUserDataKey framebuffer_destroy_notify_key; + + /* Note: we don't take a reference on the framebuffer here because + * that would introduce a circular reference. */ + texture->framebuffers = g_list_prepend (texture->framebuffers, framebuffer); + + /* Since we haven't taken a reference on the framebuffer we setup + * some private data so we will be notified if it is destroyed... */ + _cogl_object_set_user_data (COGL_OBJECT (framebuffer), + &framebuffer_destroy_notify_key, + texture, + _cogl_texture_framebuffer_destroy_cb); +} + +const GList * +_cogl_texture_get_associated_framebuffers (CoglTexture *texture) +{ + return texture->framebuffers; +} + +void +_cogl_texture_flush_journal_rendering (CoglTexture *texture) +{ + GList *l; + + /* It could be that a referenced texture is part of a framebuffer + * which has an associated journal that must be flushed before it + * can be sampled from by the current primitive... */ + for (l = texture->framebuffers; l; l = l->next) + _cogl_framebuffer_flush_journal (l->data); +} + +/* This function lets you define a meta texture as a grid of textures + * whereby the x and y grid-lines are defined by an array of + * CoglSpans. With that grid based description this function can then + * iterate all the cells of the grid that lye within a region + * specified as virtual, meta-texture, coordinates. This function can + * also cope with regions that extend beyond the original meta-texture + * grid by iterating cells repeatedly according to the wrap_x/y + * arguments. + * + * To differentiate between texture coordinates of a specific, real, + * slice texture and the texture coordinates of a composite, meta + * texture, the coordinates of the meta texture are called "virtual" + * coordinates and the coordinates of spans are called "slice" + * coordinates. + * + * Note: no guarantee is given about the order in which the slices + * will be visited. + * + * Note: The slice coordinates passed to @callback are always + * normalized coordinates even if the span coordinates aren't + * normalized. + */ +void +_cogl_texture_spans_foreach_in_region (CoglSpan *x_spans, + int n_x_spans, + CoglSpan *y_spans, + int n_y_spans, + CoglTexture **textures, + float *virtual_coords, + float x_normalize_factor, + float y_normalize_factor, + CoglPipelineWrapMode wrap_x, + CoglPipelineWrapMode wrap_y, + CoglMetaTextureCallback callback, + void *user_data) +{ + CoglSpanIter iter_x; + CoglSpanIter iter_y; + float slice_coords[4]; + float span_virtual_coords[4]; + + /* Iterate the y axis of the virtual rectangle */ + for (_cogl_span_iter_begin (&iter_y, + y_spans, + n_y_spans, + y_normalize_factor, + virtual_coords[1], + virtual_coords[3], + wrap_y); + !_cogl_span_iter_end (&iter_y); + _cogl_span_iter_next (&iter_y)) + { + if (iter_y.flipped) + { + slice_coords[1] = iter_y.intersect_end; + slice_coords[3] = iter_y.intersect_start; + span_virtual_coords[1] = iter_y.intersect_end; + span_virtual_coords[3] = iter_y.intersect_start; + } + else + { + slice_coords[1] = iter_y.intersect_start; + slice_coords[3] = iter_y.intersect_end; + span_virtual_coords[1] = iter_y.intersect_start; + span_virtual_coords[3] = iter_y.intersect_end; + } + + /* Map the current intersection to normalized slice coordinates */ + slice_coords[1] = (slice_coords[1] - iter_y.pos) / iter_y.span->size; + slice_coords[3] = (slice_coords[3] - iter_y.pos) / iter_y.span->size; + + /* Iterate the x axis of the virtual rectangle */ + for (_cogl_span_iter_begin (&iter_x, + x_spans, + n_x_spans, + x_normalize_factor, + virtual_coords[0], + virtual_coords[2], + wrap_x); + !_cogl_span_iter_end (&iter_x); + _cogl_span_iter_next (&iter_x)) + { + CoglTexture *span_tex; + + if (iter_x.flipped) + { + slice_coords[0] = iter_x.intersect_end; + slice_coords[2] = iter_x.intersect_start; + span_virtual_coords[0] = iter_x.intersect_end; + span_virtual_coords[2] = iter_x.intersect_start; + } + else + { + slice_coords[0] = iter_x.intersect_start; + slice_coords[2] = iter_x.intersect_end; + span_virtual_coords[0] = iter_x.intersect_start; + span_virtual_coords[2] = iter_x.intersect_end; + } + + /* Map the current intersection to normalized slice coordinates */ + slice_coords[0] = (slice_coords[0] - iter_x.pos) / iter_x.span->size; + slice_coords[2] = (slice_coords[2] - iter_x.pos) / iter_x.span->size; + + /* Pluck out the cogl texture for this span */ + span_tex = textures[iter_y.index * n_x_spans + iter_x.index]; + + callback (COGL_TEXTURE (span_tex), + slice_coords, + span_virtual_coords, + user_data); + } + } +} + +void +_cogl_texture_set_allocated (CoglTexture *texture, + CoglPixelFormat internal_format, + int width, + int height) +{ + _cogl_texture_set_internal_format (texture, internal_format); + + texture->width = width; + texture->height = height; + texture->allocated = TRUE; + + _cogl_texture_free_loader (texture); +} + +CoglBool +cogl_texture_allocate (CoglTexture *texture, + CoglError **error) +{ + if (texture->allocated) + return TRUE; + + if (texture->components == COGL_TEXTURE_COMPONENTS_RG && + !cogl_has_feature (texture->context, COGL_FEATURE_ID_TEXTURE_RG)) + _cogl_set_error (error, + COGL_TEXTURE_ERROR, + COGL_TEXTURE_ERROR_FORMAT, + "A red-green texture was requested but the driver " + "does not support them"); + + texture->allocated = texture->vtable->allocate (texture, error); + + return texture->allocated; +} + +void +_cogl_texture_set_internal_format (CoglTexture *texture, + CoglPixelFormat internal_format) +{ + texture->premultiplied = FALSE; + + if (internal_format == COGL_PIXEL_FORMAT_ANY) + internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE; + + if (internal_format == COGL_PIXEL_FORMAT_A_8) + { + texture->components = COGL_TEXTURE_COMPONENTS_A; + return; + } + else if (internal_format == COGL_PIXEL_FORMAT_RG_88) + { + texture->components = COGL_TEXTURE_COMPONENTS_RG; + return; + } + else if (internal_format & COGL_DEPTH_BIT) + { + texture->components = COGL_TEXTURE_COMPONENTS_DEPTH; + return; + } + else if (internal_format & COGL_A_BIT) + { + texture->components = COGL_TEXTURE_COMPONENTS_RGBA; + if (internal_format & COGL_PREMULT_BIT) + texture->premultiplied = TRUE; + return; + } + else + texture->components = COGL_TEXTURE_COMPONENTS_RGB; +} + +CoglPixelFormat +_cogl_texture_determine_internal_format (CoglTexture *texture, + CoglPixelFormat src_format) +{ + switch (texture->components) + { + case COGL_TEXTURE_COMPONENTS_DEPTH: + if (src_format & COGL_DEPTH_BIT) + return src_format; + else + { + CoglContext *ctx = texture->context; + + if (_cogl_has_private_feature (ctx, + COGL_PRIVATE_FEATURE_EXT_PACKED_DEPTH_STENCIL) || + _cogl_has_private_feature (ctx, + COGL_PRIVATE_FEATURE_OES_PACKED_DEPTH_STENCIL)) + { + return COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8; + } + else + return COGL_PIXEL_FORMAT_DEPTH_16; + } + case COGL_TEXTURE_COMPONENTS_A: + return COGL_PIXEL_FORMAT_A_8; + case COGL_TEXTURE_COMPONENTS_RG: + return COGL_PIXEL_FORMAT_RG_88; + case COGL_TEXTURE_COMPONENTS_RGB: + if (src_format != COGL_PIXEL_FORMAT_ANY && + !(src_format & COGL_A_BIT) && !(src_format & COGL_DEPTH_BIT)) + return src_format; + else + return COGL_PIXEL_FORMAT_RGB_888; + case COGL_TEXTURE_COMPONENTS_RGBA: + { + CoglPixelFormat format; + + if (src_format != COGL_PIXEL_FORMAT_ANY && + (src_format & COGL_A_BIT) && src_format != COGL_PIXEL_FORMAT_A_8) + format = src_format; + else + format = COGL_PIXEL_FORMAT_RGBA_8888; + + if (texture->premultiplied) + { + if (COGL_PIXEL_FORMAT_CAN_HAVE_PREMULT (format)) + return format |= COGL_PREMULT_BIT; + else + return COGL_PIXEL_FORMAT_RGBA_8888_PRE; + } + else + return format & ~COGL_PREMULT_BIT; + } + } + + g_return_val_if_reached (COGL_PIXEL_FORMAT_RGBA_8888_PRE); +} + +void +cogl_texture_set_components (CoglTexture *texture, + CoglTextureComponents components) +{ + _COGL_RETURN_IF_FAIL (!texture->allocated); + + if (texture->components == components) + return; + + texture->components = components; +} + +CoglTextureComponents +cogl_texture_get_components (CoglTexture *texture) +{ + return texture->components; +} + +void +cogl_texture_set_premultiplied (CoglTexture *texture, + CoglBool premultiplied) +{ + _COGL_RETURN_IF_FAIL (!texture->allocated); + + premultiplied = !!premultiplied; + + if (texture->premultiplied == premultiplied) + return; + + texture->premultiplied = premultiplied; +} + +CoglBool +cogl_texture_get_premultiplied (CoglTexture *texture) +{ + return texture->premultiplied; +} + +void +_cogl_texture_copy_internal_format (CoglTexture *src, + CoglTexture *dest) +{ + cogl_texture_set_components (dest, src->components); + cogl_texture_set_premultiplied (dest, src->premultiplied); +} diff --git a/cogl/cogl/cogl-texture.h b/cogl/cogl/cogl-texture.h new file mode 100644 index 0000000..ef7d142 --- /dev/null +++ b/cogl/cogl/cogl-texture.h @@ -0,0 +1,516 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_TEXTURE_H__ +#define __COGL_TEXTURE_H__ + +/* We forward declare the CoglTexture type here to avoid some circular + * dependency issues with the following headers. + */ +#if defined(__COGL_H_INSIDE__) && !defined(COGL_ENABLE_MUTTER_API) && \ + !defined(COGL_GIR_SCANNING) +/* For the public C api we typedef interface types as void to avoid needing + * lots of casting in code and instead we will rely on runtime type checking + * for these objects. */ +typedef void CoglTexture; +#else +typedef struct _CoglTexture CoglTexture; +#define COGL_TEXTURE(X) ((CoglTexture *)X) +#endif + +#include +#include +#include +#include +#include + +#include + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-texture + * @short_description: Functions for creating and manipulating textures + * + * Cogl allows creating and manipulating textures using a uniform + * API that tries to hide all the various complexities of creating, + * loading and manipulating textures. + */ + +#define COGL_TEXTURE_MAX_WASTE 127 + +/** + * cogl_texture_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_texture_get_gtype (void); + +/** + * COGL_TEXTURE_ERROR: + * + * #CoglError domain for texture errors. + * + * Since: 1.8 + * Stability: Unstable + */ +#define COGL_TEXTURE_ERROR (cogl_texture_error_quark ()) + +/** + * CoglTextureError: + * @COGL_TEXTURE_ERROR_SIZE: Unsupported size + * @COGL_TEXTURE_ERROR_FORMAT: Unsupported format + * @COGL_TEXTURE_ERROR_TYPE: A primitive texture type that is + * unsupported by the driver was used + * + * Error codes that can be thrown when allocating textures. + * + * Since: 1.8 + * Stability: Unstable + */ +typedef enum { + COGL_TEXTURE_ERROR_SIZE, + COGL_TEXTURE_ERROR_FORMAT, + COGL_TEXTURE_ERROR_BAD_PARAMETER, + COGL_TEXTURE_ERROR_TYPE +} CoglTextureError; + +/** + * CoglTextureType: + * @COGL_TEXTURE_TYPE_2D: A #CoglTexture2D + * @COGL_TEXTURE_TYPE_3D: A #CoglTexture3D + * @COGL_TEXTURE_TYPE_RECTANGLE: A #CoglTextureRectangle + * + * Constants representing the underlying hardware texture type of a + * #CoglTexture. + * + * Stability: unstable + * Since: 1.10 + */ +typedef enum { + COGL_TEXTURE_TYPE_2D, + COGL_TEXTURE_TYPE_3D, + COGL_TEXTURE_TYPE_RECTANGLE +} CoglTextureType; + +uint32_t cogl_texture_error_quark (void); + +/** + * cogl_is_texture: + * @object: A #CoglObject pointer + * + * Gets whether the given object references a texture object. + * + * Return value: %TRUE if the @object references a texture, and + * %FALSE otherwise + */ +CoglBool +cogl_is_texture (void *object); + +/** + * CoglTextureComponents: + * @COGL_TEXTURE_COMPONENTS_A: Only the alpha component + * @COGL_TEXTURE_COMPONENTS_RG: Red and green components. Note that + * this can only be used if the %COGL_FEATURE_ID_TEXTURE_RG feature + * is advertised. + * @COGL_TEXTURE_COMPONENTS_RGB: Red, green and blue components + * @COGL_TEXTURE_COMPONENTS_RGBA: Red, green, blue and alpha components + * @COGL_TEXTURE_COMPONENTS_DEPTH: Only a depth component + * + * See cogl_texture_set_components(). + * + * Since: 1.18 + */ +typedef enum _CoglTextureComponents +{ + COGL_TEXTURE_COMPONENTS_A = 1, + COGL_TEXTURE_COMPONENTS_RG, + COGL_TEXTURE_COMPONENTS_RGB, + COGL_TEXTURE_COMPONENTS_RGBA, + COGL_TEXTURE_COMPONENTS_DEPTH +} CoglTextureComponents; + +/** + * cogl_texture_set_components: + * @texture: a #CoglTexture pointer. + * + * Affects the internal storage format for this texture by specifying + * what components will be required for sampling later. + * + * This api affects how data is uploaded to the GPU since unused + * components can potentially be discarded from source data. + * + * For textures created by the ‘_with_size’ constructors the default + * is %COGL_TEXTURE_COMPONENTS_RGBA. The other constructors which take + * a %CoglBitmap or a data pointer default to the same components as + * the pixel format of the data. + * + * Note that the %COGL_TEXTURE_COMPONENTS_RG format is not available + * on all drivers. The availability can be determined by checking for + * the %COGL_FEATURE_ID_TEXTURE_RG feature. If this format is used on + * a driver where it is not available then %COGL_TEXTURE_ERROR_FORMAT + * will be raised when the texture is allocated. Even if the feature + * is not available then %COGL_PIXEL_FORMAT_RG_88 can still be used as + * an image format as long as %COGL_TEXTURE_COMPONENTS_RG isn't used + * as the texture's components. + * + * Since: 1.18 + */ +void +cogl_texture_set_components (CoglTexture *texture, + CoglTextureComponents components); + +/** + * cogl_texture_get_components: + * @texture: a #CoglTexture pointer. + * + * Queries what components the given @texture stores internally as set + * via cogl_texture_set_components(). + * + * For textures created by the ‘_with_size’ constructors the default + * is %COGL_TEXTURE_COMPONENTS_RGBA. The other constructors which take + * a %CoglBitmap or a data pointer default to the same components as + * the pixel format of the data. + * + * Since: 1.18 + */ +CoglTextureComponents +cogl_texture_get_components (CoglTexture *texture); + +/** + * cogl_texture_set_premultiplied: + * @texture: a #CoglTexture pointer. + * @premultiplied: Whether any internally stored red, green or blue + * components are pre-multiplied by an alpha + * component. + * + * Affects the internal storage format for this texture by specifying + * whether red, green and blue color components should be stored as + * pre-multiplied alpha values. + * + * This api affects how data is uploaded to the GPU since Cogl will + * convert source data to have premultiplied or unpremultiplied + * components according to this state. + * + * For example if you create a texture via + * cogl_texture_2d_new_with_size() and then upload data via + * cogl_texture_set_data() passing a source format of + * %COGL_PIXEL_FORMAT_RGBA_8888 then Cogl will internally multiply the + * red, green and blue components of the source data by the alpha + * component, for each pixel so that the internally stored data has + * pre-multiplied alpha components. If you instead upload data that + * already has pre-multiplied components by passing + * %COGL_PIXEL_FORMAT_RGBA_8888_PRE as the source format to + * cogl_texture_set_data() then the data can be uploaded without being + * converted. + * + * By default the @premultipled state is @TRUE. + * + * Since: 1.18 + */ +void +cogl_texture_set_premultiplied (CoglTexture *texture, + CoglBool premultiplied); + +/** + * cogl_texture_get_premultiplied: + * @texture: a #CoglTexture pointer. + * + * Queries the pre-multiplied alpha status for internally stored red, + * green and blue components for the given @texture as set by + * cogl_texture_set_premultiplied(). + * + * By default the pre-multipled state is @TRUE. + * + * Return value: %TRUE if red, green and blue components are + * internally stored pre-multiplied by the alpha + * value or %FALSE if not. + * Since: 1.18 + */ +CoglBool +cogl_texture_get_premultiplied (CoglTexture *texture); + +/** + * cogl_texture_get_width: + * @texture: a #CoglTexture pointer. + * + * Queries the width of a cogl texture. + * + * Return value: the width of the GPU side texture in pixels + */ +unsigned int +cogl_texture_get_width (CoglTexture *texture); + +/** + * cogl_texture_get_height: + * @texture: a #CoglTexture pointer. + * + * Queries the height of a cogl texture. + * + * Return value: the height of the GPU side texture in pixels + */ +unsigned int +cogl_texture_get_height (CoglTexture *texture); + +/** + * cogl_texture_get_max_waste: + * @texture: a #CoglTexture pointer. + * + * Queries the maximum wasted (unused) pixels in one dimension of a GPU side + * texture. + * + * Return value: the maximum waste + */ +int +cogl_texture_get_max_waste (CoglTexture *texture); + +/** + * cogl_texture_is_sliced: + * @texture: a #CoglTexture pointer. + * + * Queries if a texture is sliced (stored as multiple GPU side tecture + * objects). + * + * Return value: %TRUE if the texture is sliced, %FALSE if the texture + * is stored as a single GPU texture + */ +CoglBool +cogl_texture_is_sliced (CoglTexture *texture); + +/** + * cogl_texture_get_gl_texture: + * @texture: a #CoglTexture pointer. + * @out_gl_handle: (out) (allow-none): pointer to return location for the + * textures GL handle, or %NULL. + * @out_gl_target: (out) (allow-none): pointer to return location for the + * GL target type, or %NULL. + * + * Queries the GL handles for a GPU side texture through its #CoglTexture. + * + * If the texture is spliced the data for the first sub texture will be + * queried. + * + * Return value: %TRUE if the handle was successfully retrieved, %FALSE + * if the handle was invalid + */ +CoglBool +cogl_texture_get_gl_texture (CoglTexture *texture, + unsigned int *out_gl_handle, + unsigned int *out_gl_target); + +/** + * cogl_texture_get_data: + * @texture: a #CoglTexture pointer. + * @format: the #CoglPixelFormat to store the texture as. + * @rowstride: the rowstride of @data in bytes or pass 0 to calculate + * from the bytes-per-pixel of @format multiplied by the + * @texture width. + * @data: memory location to write the @texture's contents, or %NULL + * to only query the data size through the return value. + * + * Copies the pixel data from a cogl texture to system memory. + * + * Don't pass the value of cogl_texture_get_rowstride() as the + * @rowstride argument, the rowstride should be the rowstride you + * want for the destination @data buffer not the rowstride of the + * source texture + * + * Return value: the size of the texture data in bytes + */ +int +cogl_texture_get_data (CoglTexture *texture, + CoglPixelFormat format, + unsigned int rowstride, + uint8_t *data); + +/** + * cogl_texture_set_region: + * @texture: a #CoglTexture. + * @src_x: upper left coordinate to use from source data. + * @src_y: upper left coordinate to use from source data. + * @dst_x: upper left destination horizontal coordinate. + * @dst_y: upper left destination vertical coordinate. + * @dst_width: width of destination region to write. (Must be less + * than or equal to @width) + * @dst_height: height of destination region to write. (Must be less + * than or equal to @height) + * @width: width of source data buffer. + * @height: height of source data buffer. + * @format: the #CoglPixelFormat used in the source buffer. + * @rowstride: rowstride of source buffer (computed from width if none + * specified) + * @data: the actual pixel data. + * + * Sets the pixels in a rectangular subregion of @texture from an in-memory + * buffer containing pixel data. + * + * The region set can't be larger than the source @data + * + * Return value: %TRUE if the subregion upload was successful, and + * %FALSE otherwise + */ +CoglBool +cogl_texture_set_region (CoglTexture *texture, + int src_x, + int src_y, + int dst_x, + int dst_y, + unsigned int dst_width, + unsigned int dst_height, + int width, + int height, + CoglPixelFormat format, + unsigned int rowstride, + const uint8_t *data); + +/** + * cogl_texture_set_data: + * @texture a #CoglTexture. + * @format: the #CoglPixelFormat used in the source @data buffer. + * @rowstride: rowstride of the source @data buffer (computed from + * the texture width and @format if it equals 0) + * @data: the source data, pointing to the first top-left pixel to set + * @level: The mipmap level to update (Normally 0 for the largest, + * base texture) + * @error: A #CoglError to return exceptional errors + * + * Sets all the pixels for a given mipmap @level by copying the pixel + * data pointed to by the @data argument into the given @texture. + * + * @data should point to the first pixel to copy corresponding + * to the top left of the mipmap @level being set. + * + * If @rowstride equals 0 then it will be automatically calculated + * from the width of the mipmap level and the bytes-per-pixel for the + * given @format. + * + * A mipmap @level of 0 corresponds to the largest, base image of a + * texture and @level 1 is half the width and height of level 0. If + * dividing any dimension of the previous level by two results in a + * fraction then round the number down (floor()), but clamp to 1 + * something like this: + * + * |[ + * next_width = MAX (1, floor (prev_width)); + * ]| + * + * You can determine the number of mipmap levels for a given texture + * like this: + * + * |[ + * n_levels = 1 + floor (log2 (max_dimension)); + * ]| + * + * Where %max_dimension is the larger of cogl_texture_get_width() and + * cogl_texture_get_height(). + * + * It is an error to pass a @level number >= the number of levels that + * @texture can have according to the above calculation. + * + * Since the storage for a #CoglTexture is allocated lazily then + * if the given @texture has not previously been allocated then this + * api can return %FALSE and throw an exceptional @error if there is + * not enough memory to allocate storage for @texture. + * + * Return value: %TRUE if the data upload was successful, and + * %FALSE otherwise + */ +CoglBool +cogl_texture_set_data (CoglTexture *texture, + CoglPixelFormat format, + int rowstride, + const uint8_t *data, + int level, + CoglError **error); + +/** + * cogl_texture_set_region_from_bitmap: + * @texture: a #CoglTexture pointer + * @src_x: upper left coordinate to use from the source bitmap. + * @src_y: upper left coordinate to use from the source bitmap + * @dst_x: upper left destination horizontal coordinate. + * @dst_y: upper left destination vertical coordinate. + * @dst_width: width of destination region to write. (Must be less + * than or equal to the bitmap width) + * @dst_height: height of destination region to write. (Must be less + * than or equal to the bitmap height) + * @bitmap: The source bitmap to read from + * + * Copies a specified source region from @bitmap to the position + * (@src_x, @src_y) of the given destination texture @handle. + * + * The region updated can't be larger than the source + * bitmap + * + * Return value: %TRUE if the subregion upload was successful, and + * %FALSE otherwise + * + * Since: 1.8 + * Stability: unstable + */ +CoglBool +cogl_texture_set_region_from_bitmap (CoglTexture *texture, + int src_x, + int src_y, + int dst_x, + int dst_y, + unsigned int dst_width, + unsigned int dst_height, + CoglBitmap *bitmap); + +/** + * cogl_texture_allocate: + * @texture: A #CoglTexture + * @error: A #CoglError to return exceptional errors or %NULL + * + * Explicitly allocates the storage for the given @texture which + * allows you to be sure that there is enough memory for the + * texture and if not then the error can be handled gracefully. + * + * Normally applications don't need to use this api directly + * since the texture will be implicitly allocated when data is set on + * the texture, or if the texture is attached to a #CoglOffscreen + * framebuffer and rendered too. + * + * Return value: %TRUE if the texture was successfully allocated, + * otherwise %FALSE and @error will be updated if it + * wasn't %NULL. + */ +CoglBool +cogl_texture_allocate (CoglTexture *texture, + CoglError **error); + +COGL_END_DECLS + +#endif /* __COGL_TEXTURE_H__ */ diff --git a/cogl/cogl/cogl-types.h b/cogl/cogl/cogl-types.h new file mode 100644 index 0000000..f67895d --- /dev/null +++ b/cogl/cogl/cogl-types.h @@ -0,0 +1,898 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_TYPES_H__ +#define __COGL_TYPES_H__ + +#include +#include + +#include + +#include +#include + +/* Guard C code in headers, while including them from C++ */ +#ifdef __cplusplus +#define COGL_BEGIN_DECLS extern "C" { +#define COGL_END_DECLS } +#else +#define COGL_BEGIN_DECLS +#define COGL_END_DECLS +#endif + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-types + * @short_description: Types used throughout the library + * + * General types used by various Cogl functions. +*/ + +/** + * CoglBool: + * + * A boolean data type used throughout the Cogl C api. This should be + * used in conjunction with the %TRUE and %FALSE macro defines for + * setting and testing boolean values. + * + * Since: 2.0 + * Stability: stable + */ +typedef int CoglBool; + +#if __GNUC__ >= 4 +#define COGL_GNUC_NULL_TERMINATED __attribute__((__sentinel__)) +#else +#define COGL_GNUC_NULL_TERMINATED +#endif + +#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) && \ + !defined (COGL_COMPILATION) +#define COGL_GNUC_DEPRECATED \ + __attribute__((__deprecated__)) +#else +#define COGL_GNUC_DEPRECATED +#endif /* __GNUC__ */ + +/* Some structures are meant to be opaque but they have public + definitions because we want the size to be public so they can be + allocated on the stack. This macro is used to ensure that users + don't accidentally access private members */ +#ifdef COGL_COMPILATION +#define COGL_PRIVATE(x) x +#else +#define COGL_PRIVATE(x) private_member_ ## x +#endif + +/* To help catch accidental changes to public structs that should + * be stack allocated we use this macro to compile time assert that + * a struct size is as expected. + */ +#define COGL_STRUCT_SIZE_ASSERT(TYPE, SIZE) \ +typedef struct { \ + char compile_time_assert_ ## TYPE ## _size[ \ + (sizeof (TYPE) == (SIZE)) ? 1 : -1]; \ + } _ ## TYPE ## SizeCheck + +/** + * CoglHandle: + * + * Type used for storing references to cogl objects, the CoglHandle is + * a fully opaque type without any public data members. + */ +typedef void * CoglHandle; + +/** + * COGL_INVALID_HANDLE: + * + * A COGL handle that is not valid, used for unitialized handles as well as + * error conditions. + */ +#define COGL_INVALID_HANDLE NULL + +#define COGL_TYPE_HANDLE (cogl_handle_get_type ()) +GType +cogl_handle_get_type (void) G_GNUC_CONST; + +/** + * cogl_handle_ref: + * @handle: a #CoglHandle + * + * Increases the reference count of @handle by 1 + * + * Return value: (transfer none): the handle, with its reference count increased + */ +CoglHandle +cogl_handle_ref (CoglHandle handle); + +/** + * cogl_handle_unref: + * @handle: a #CoglHandle + * + * Drecreases the reference count of @handle by 1; if the reference + * count reaches 0, the resources allocated by @handle will be freed + */ +void +cogl_handle_unref (CoglHandle handle); + +/** + * CoglFuncPtr: + * + * The type used by cogl for function pointers, note that this type + * is used as a generic catch-all cast for function pointers and the + * actual arguments and return type may be different. + */ +typedef void (* CoglFuncPtr) (void); + +/* We forward declare this in cogl-types to avoid circular dependencies + * between cogl-matrix.h, cogl-euler.h and cogl-quaterion.h */ +typedef struct _CoglMatrix CoglMatrix; + +/* Same as above we forward declared CoglQuaternion to avoid + * circular dependencies. */ +typedef struct _CoglQuaternion CoglQuaternion; + +/* Same as above we forward declared CoglEuler to avoid + * circular dependencies. */ +typedef struct _CoglEuler CoglEuler; + +/** + * CoglAngle: + * + * Integer representation of an angle such that 1024 corresponds to + * full circle (i.e., 2 * pi). + * + * Since: 1.0 + */ +typedef int32_t CoglAngle; + +typedef struct _CoglColor CoglColor; +typedef struct _CoglTextureVertex CoglTextureVertex; + +/* Enum declarations */ + +#define COGL_A_BIT (1 << 4) +#define COGL_BGR_BIT (1 << 5) +#define COGL_AFIRST_BIT (1 << 6) +#define COGL_PREMULT_BIT (1 << 7) +#define COGL_DEPTH_BIT (1 << 8) +#define COGL_STENCIL_BIT (1 << 9) + +/* XXX: Notes to those adding new formats here... + * + * First this diagram outlines how we allocate the 32bits of a + * CoglPixelFormat currently... + * + * 6 bits for flags + * |-----| + * enum unused 4 bits for the bytes-per-pixel + * and component alignment info + * |------| |-------------| |--| + * 00000000 xxxxxxxx xxxxxxSD PFBA0000 + * ^ stencil + * ^ depth + * ^ premult + * ^ alpha first + * ^ bgr order + * ^ has alpha + * + * The most awkward part about the formats is how we use the last 4 + * bits to encode the bytes per pixel and component alignment + * information. Ideally we should have had 3 bits for the bpp and a + * flag for alignment but we didn't plan for that in advance so we + * instead use a small lookup table to query the bpp and whether the + * components are byte aligned or not. + * + * The mapping is the following (see discussion on bug #660188): + * + * 0 = undefined + * 1, 8 = 1 bpp (e.g. A_8, G_8) + * 2 = 3 bpp, aligned (e.g. 888) + * 3 = 4 bpp, aligned (e.g. 8888) + * 4-6 = 2 bpp, not aligned (e.g. 565, 4444, 5551) + * 7 = YUV: undefined bpp, undefined alignment + * 9 = 2 bpp, aligned + * 10 = depth, aligned (8, 16, 24, 32, 32f) + * 11 = undefined + * 12 = 3 bpp, not aligned + * 13 = 4 bpp, not aligned (e.g. 2101010) + * 14-15 = undefined + * + * Note: the gap at 10-11 is just because we wanted to maintain that + * all non-aligned formats have the third bit set in case that's + * useful later. + * + * Since we don't want to waste bits adding more and more flags, we'd + * like to see most new pixel formats that can't be represented + * uniquely with the existing flags in the least significant byte + * simply be enumerated with sequential values in the most significant + * enum byte. + * + * Note: Cogl avoids exposing any padded XRGB or RGBX formats and + * instead we leave it up to applications to decided whether they + * consider the A component as padding or valid data. We shouldn't + * change this policy without good reasoning. + * + * So to add a new format: + * 1) Use the mapping table above to figure out what to but in + * the lowest nibble. + * 2) OR in the COGL_PREMULT_BIT, COGL_AFIRST_BIT, COGL_A_BIT and + * COGL_BGR_BIT flags as appropriate. + * 3) If the result is not yet unique then also combine with an + * increment of the last sequence number in the most significant + * byte. + * + * The last sequence number used was 0 (i.e. no formats currently need + * a sequence number) + * Update this note whenever a new sequence number is used. + */ +/** + * CoglPixelFormat: + * @COGL_PIXEL_FORMAT_ANY: Any format + * @COGL_PIXEL_FORMAT_A_8: 8 bits alpha mask + * @COGL_PIXEL_FORMAT_RG_88: RG, 16 bits. Note that red-green textures + * are only available if %COGL_FEATURE_ID_TEXTURE_RG is advertised. + * See cogl_texture_set_components() for details. + * @COGL_PIXEL_FORMAT_RGB_565: RGB, 16 bits + * @COGL_PIXEL_FORMAT_RGBA_4444: RGBA, 16 bits + * @COGL_PIXEL_FORMAT_RGBA_5551: RGBA, 16 bits + * @COGL_PIXEL_FORMAT_YUV: Not currently supported + * @COGL_PIXEL_FORMAT_G_8: Single luminance component + * @COGL_PIXEL_FORMAT_RGB_888: RGB, 24 bits + * @COGL_PIXEL_FORMAT_BGR_888: BGR, 24 bits + * @COGL_PIXEL_FORMAT_RGBA_8888: RGBA, 32 bits + * @COGL_PIXEL_FORMAT_BGRA_8888: BGRA, 32 bits + * @COGL_PIXEL_FORMAT_ARGB_8888: ARGB, 32 bits + * @COGL_PIXEL_FORMAT_ABGR_8888: ABGR, 32 bits + * @COGL_PIXEL_FORMAT_RGBA_1010102 : RGBA, 32 bits, 10 bpc + * @COGL_PIXEL_FORMAT_BGRA_1010102 : BGRA, 32 bits, 10 bpc + * @COGL_PIXEL_FORMAT_ARGB_2101010 : ARGB, 32 bits, 10 bpc + * @COGL_PIXEL_FORMAT_ABGR_2101010 : ABGR, 32 bits, 10 bpc + * @COGL_PIXEL_FORMAT_RGBA_8888_PRE: Premultiplied RGBA, 32 bits + * @COGL_PIXEL_FORMAT_BGRA_8888_PRE: Premultiplied BGRA, 32 bits + * @COGL_PIXEL_FORMAT_ARGB_8888_PRE: Premultiplied ARGB, 32 bits + * @COGL_PIXEL_FORMAT_ABGR_8888_PRE: Premultiplied ABGR, 32 bits + * @COGL_PIXEL_FORMAT_RGBA_4444_PRE: Premultiplied RGBA, 16 bits + * @COGL_PIXEL_FORMAT_RGBA_5551_PRE: Premultiplied RGBA, 16 bits + * @COGL_PIXEL_FORMAT_RGBA_1010102_PRE: Premultiplied RGBA, 32 bits, 10 bpc + * @COGL_PIXEL_FORMAT_BGRA_1010102_PRE: Premultiplied BGRA, 32 bits, 10 bpc + * @COGL_PIXEL_FORMAT_ARGB_2101010_PRE: Premultiplied ARGB, 32 bits, 10 bpc + * @COGL_PIXEL_FORMAT_ABGR_2101010_PRE: Premultiplied ABGR, 32 bits, 10 bpc + * + * Pixel formats used by Cogl. For the formats with a byte per + * component, the order of the components specify the order in + * increasing memory addresses. So for example + * %COGL_PIXEL_FORMAT_RGB_888 would have the red component in the + * lowest address, green in the next address and blue after that + * regardless of the endianness of the system. + * + * For the formats with non byte aligned components the component + * order specifies the order within a 16-bit or 32-bit number from + * most significant bit to least significant. So for + * %COGL_PIXEL_FORMAT_RGB_565, the red component would be in bits + * 11-15, the green component would be in 6-11 and the blue component + * would be in 1-5. Therefore the order in memory depends on the + * endianness of the system. + * + * When uploading a texture %COGL_PIXEL_FORMAT_ANY can be used as the + * internal format. Cogl will try to pick the best format to use + * internally and convert the texture data if necessary. + * + * Since: 0.8 + */ +typedef enum { /*< prefix=COGL_PIXEL_FORMAT >*/ + COGL_PIXEL_FORMAT_ANY = 0, + COGL_PIXEL_FORMAT_A_8 = 1 | COGL_A_BIT, + + COGL_PIXEL_FORMAT_RGB_565 = 4, + COGL_PIXEL_FORMAT_RGBA_4444 = 5 | COGL_A_BIT, + COGL_PIXEL_FORMAT_RGBA_5551 = 6 | COGL_A_BIT, + COGL_PIXEL_FORMAT_YUV = 7, + COGL_PIXEL_FORMAT_G_8 = 8, + + COGL_PIXEL_FORMAT_RG_88 = 9, + + COGL_PIXEL_FORMAT_RGB_888 = 2, + COGL_PIXEL_FORMAT_BGR_888 = (2 | COGL_BGR_BIT), + + COGL_PIXEL_FORMAT_RGBA_8888 = (3 | COGL_A_BIT), + COGL_PIXEL_FORMAT_BGRA_8888 = (3 | COGL_A_BIT | COGL_BGR_BIT), + COGL_PIXEL_FORMAT_ARGB_8888 = (3 | COGL_A_BIT | COGL_AFIRST_BIT), + COGL_PIXEL_FORMAT_ABGR_8888 = (3 | COGL_A_BIT | COGL_BGR_BIT | COGL_AFIRST_BIT), + + COGL_PIXEL_FORMAT_RGBA_1010102 = (13 | COGL_A_BIT), + COGL_PIXEL_FORMAT_BGRA_1010102 = (13 | COGL_A_BIT | COGL_BGR_BIT), + COGL_PIXEL_FORMAT_ARGB_2101010 = (13 | COGL_A_BIT | COGL_AFIRST_BIT), + COGL_PIXEL_FORMAT_ABGR_2101010 = (13 | COGL_A_BIT | COGL_BGR_BIT | COGL_AFIRST_BIT), + + COGL_PIXEL_FORMAT_RGBA_8888_PRE = (3 | COGL_A_BIT | COGL_PREMULT_BIT), + COGL_PIXEL_FORMAT_BGRA_8888_PRE = (3 | COGL_A_BIT | COGL_PREMULT_BIT | COGL_BGR_BIT), + COGL_PIXEL_FORMAT_ARGB_8888_PRE = (3 | COGL_A_BIT | COGL_PREMULT_BIT | COGL_AFIRST_BIT), + COGL_PIXEL_FORMAT_ABGR_8888_PRE = (3 | 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_1010102_PRE = (COGL_PIXEL_FORMAT_RGBA_1010102 | COGL_PREMULT_BIT), + COGL_PIXEL_FORMAT_BGRA_1010102_PRE = (COGL_PIXEL_FORMAT_BGRA_1010102 | COGL_PREMULT_BIT), + COGL_PIXEL_FORMAT_ARGB_2101010_PRE = (COGL_PIXEL_FORMAT_ARGB_2101010 | COGL_PREMULT_BIT), + COGL_PIXEL_FORMAT_ABGR_2101010_PRE = (COGL_PIXEL_FORMAT_ABGR_2101010 | COGL_PREMULT_BIT), + + COGL_PIXEL_FORMAT_DEPTH_16 = (9 | COGL_DEPTH_BIT), + COGL_PIXEL_FORMAT_DEPTH_32 = (3 | COGL_DEPTH_BIT), + + COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8 = (3 | COGL_DEPTH_BIT | COGL_STENCIL_BIT) +} CoglPixelFormat; + +/** + * CoglFeatureFlags: + * @COGL_FEATURE_TEXTURE_RECTANGLE: ARB_texture_rectangle support + * @COGL_FEATURE_TEXTURE_NPOT: Non power of two textures are supported + * by the hardware. This is a equivalent to the + * %COGL_FEATURE_TEXTURE_NPOT_BASIC, %COGL_FEATURE_TEXTURE_NPOT_MIPMAP + * and %COGL_FEATURE_TEXTURE_NPOT_REPEAT features combined. + * @COGL_FEATURE_TEXTURE_YUV: ycbcr conversion support + * @COGL_FEATURE_TEXTURE_READ_PIXELS: glReadPixels() support + * @COGL_FEATURE_SHADERS_GLSL: GLSL support + * @COGL_FEATURE_SHADERS_ARBFP: ARBFP support + * @COGL_FEATURE_OFFSCREEN: FBO support + * @COGL_FEATURE_OFFSCREEN_MULTISAMPLE: Multisample support on FBOs + * @COGL_FEATURE_OFFSCREEN_BLIT: Blit support on FBOs + * @COGL_FEATURE_FOUR_CLIP_PLANES: At least 4 clip planes available + * @COGL_FEATURE_STENCIL_BUFFER: Stencil buffer support + * @COGL_FEATURE_VBOS: VBO support + * @COGL_FEATURE_PBOS: PBO support + * @COGL_FEATURE_UNSIGNED_INT_INDICES: Set if + * %COGL_INDICES_TYPE_UNSIGNED_INT is supported in + * cogl_vertex_buffer_indices_new(). + * @COGL_FEATURE_DEPTH_RANGE: cogl_material_set_depth_range() support + * @COGL_FEATURE_TEXTURE_NPOT_BASIC: The hardware supports non power + * of two textures, but you also need to check the + * %COGL_FEATURE_TEXTURE_NPOT_MIPMAP and %COGL_FEATURE_TEXTURE_NPOT_REPEAT + * features to know if the hardware supports npot texture mipmaps + * or repeat modes other than + * %COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE respectively. + * @COGL_FEATURE_TEXTURE_NPOT_MIPMAP: Mipmapping is supported in + * conjuntion with non power of two textures. + * @COGL_FEATURE_TEXTURE_NPOT_REPEAT: Repeat modes other than + * %COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE are supported by the + * hardware. + * @COGL_FEATURE_POINT_SPRITE: Whether + * cogl_material_set_layer_point_sprite_coords_enabled() is supported. + * @COGL_FEATURE_TEXTURE_3D: 3D texture support + * @COGL_FEATURE_MAP_BUFFER_FOR_READ: Whether cogl_buffer_map() is + * supported with CoglBufferAccess including read support. + * @COGL_FEATURE_MAP_BUFFER_FOR_WRITE: Whether cogl_buffer_map() is + * supported with CoglBufferAccess including write support. + * @COGL_FEATURE_DEPTH_TEXTURE: Whether #CoglFramebuffer support rendering the + * depth buffer to a texture. + * + * Flags for the supported features. + * + * Since: 0.8 + */ +typedef enum +{ + COGL_FEATURE_TEXTURE_RECTANGLE = (1 << 1), + COGL_FEATURE_TEXTURE_NPOT = (1 << 2), + COGL_FEATURE_TEXTURE_YUV = (1 << 3), + COGL_FEATURE_TEXTURE_READ_PIXELS = (1 << 4), + COGL_FEATURE_SHADERS_GLSL = (1 << 5), + COGL_FEATURE_OFFSCREEN = (1 << 6), + COGL_FEATURE_OFFSCREEN_MULTISAMPLE = (1 << 7), + COGL_FEATURE_OFFSCREEN_BLIT = (1 << 8), + COGL_FEATURE_FOUR_CLIP_PLANES = (1 << 9), + COGL_FEATURE_STENCIL_BUFFER = (1 << 10), + COGL_FEATURE_VBOS = (1 << 11), + COGL_FEATURE_PBOS = (1 << 12), + COGL_FEATURE_UNSIGNED_INT_INDICES = (1 << 13), + COGL_FEATURE_DEPTH_RANGE = (1 << 14), + COGL_FEATURE_TEXTURE_NPOT_BASIC = (1 << 15), + COGL_FEATURE_TEXTURE_NPOT_MIPMAP = (1 << 16), + COGL_FEATURE_TEXTURE_NPOT_REPEAT = (1 << 17), + COGL_FEATURE_POINT_SPRITE = (1 << 18), + COGL_FEATURE_TEXTURE_3D = (1 << 19), + COGL_FEATURE_SHADERS_ARBFP = (1 << 20), + COGL_FEATURE_MAP_BUFFER_FOR_READ = (1 << 21), + COGL_FEATURE_MAP_BUFFER_FOR_WRITE = (1 << 22), + COGL_FEATURE_ONSCREEN_MULTIPLE = (1 << 23), + COGL_FEATURE_DEPTH_TEXTURE = (1 << 24) +} CoglFeatureFlags; + +/** + * CoglBufferTarget: + * @COGL_WINDOW_BUFFER: FIXME + * @COGL_OFFSCREEN_BUFFER: FIXME + * + * Target flags for FBOs. + * + * Since: 0.8 + */ +typedef enum +{ + COGL_WINDOW_BUFFER = (1 << 1), + COGL_OFFSCREEN_BUFFER = (1 << 2) +} CoglBufferTarget; + +/** + * CoglColor: + * @red: amount of red + * @green: amount of green + * @blue: amount of green + * @alpha: alpha + * + * A structure for holding a color definition. The contents of + * the CoglColor structure are private and should never by accessed + * directly. + * + * Since: 1.0 + */ +struct _CoglColor +{ + /*< private >*/ + uint8_t COGL_PRIVATE (red); + uint8_t COGL_PRIVATE (green); + uint8_t COGL_PRIVATE (blue); + + uint8_t COGL_PRIVATE (alpha); + + /* padding in case we want to change to floats at + * some point */ + uint32_t COGL_PRIVATE (padding0); + uint32_t COGL_PRIVATE (padding1); + uint32_t COGL_PRIVATE (padding2); +}; +COGL_STRUCT_SIZE_ASSERT (CoglColor, 16); + +/** + * CoglTextureVertex: + * @x: Model x-coordinate + * @y: Model y-coordinate + * @z: Model z-coordinate + * @tx: Texture x-coordinate + * @ty: Texture y-coordinate + * @color: The color to use at this vertex. This is ignored if + * use_color is %FALSE when calling cogl_polygon() + * + * Used to specify vertex information when calling cogl_polygon() + */ +struct _CoglTextureVertex +{ + float x, y, z; + float tx, ty; + + CoglColor color; +}; +COGL_STRUCT_SIZE_ASSERT (CoglTextureVertex, 36); + +/** + * CoglTextureFlags: + * @COGL_TEXTURE_NONE: No flags specified + * @COGL_TEXTURE_NO_AUTO_MIPMAP: Disables the automatic generation of + * the mipmap pyramid from the base level image whenever it is + * updated. The mipmaps are only generated when the texture is + * rendered with a mipmap filter so it should be free to leave out + * this flag when using other filtering modes + * @COGL_TEXTURE_NO_SLICING: Disables the slicing of the texture + * @COGL_TEXTURE_NO_ATLAS: Disables the insertion of the texture inside + * the texture atlas used by Cogl + * + * Flags to pass to the cogl_texture_new_* family of functions. + * + * Since: 1.0 + */ +typedef enum { + COGL_TEXTURE_NONE = 0, + COGL_TEXTURE_NO_AUTO_MIPMAP = 1 << 0, + COGL_TEXTURE_NO_SLICING = 1 << 1, + COGL_TEXTURE_NO_ATLAS = 1 << 2 +} CoglTextureFlags; + +/** + * CoglFogMode: + * @COGL_FOG_MODE_LINEAR: Calculates the fog blend factor as: + * |[ + * f = end - eye_distance / end - start + * ]| + * @COGL_FOG_MODE_EXPONENTIAL: Calculates the fog blend factor as: + * |[ + * f = e ^ -(density * eye_distance) + * ]| + * @COGL_FOG_MODE_EXPONENTIAL_SQUARED: Calculates the fog blend factor as: + * |[ + * f = e ^ -(density * eye_distance)^2 + * ]| + * + * The fog mode determines the equation used to calculate the fogging blend + * factor while fogging is enabled. The simplest %COGL_FOG_MODE_LINEAR mode + * determines f as: + * + * |[ + * f = end - eye_distance / end - start + * ]| + * + * Where eye_distance is the distance of the current fragment in eye + * coordinates from the origin. + * + * Since: 1.0 + */ +typedef enum { + COGL_FOG_MODE_LINEAR, + COGL_FOG_MODE_EXPONENTIAL, + COGL_FOG_MODE_EXPONENTIAL_SQUARED +} CoglFogMode; + +/** + * COGL_BLEND_STRING_ERROR: + * + * #CoglError domain for blend string parser errors + * + * Since: 1.0 + */ +#define COGL_BLEND_STRING_ERROR (cogl_blend_string_error_quark ()) + +/** + * CoglBlendStringError: + * @COGL_BLEND_STRING_ERROR_PARSE_ERROR: Generic parse error + * @COGL_BLEND_STRING_ERROR_ARGUMENT_PARSE_ERROR: Argument parse error + * @COGL_BLEND_STRING_ERROR_INVALID_ERROR: Internal parser error + * @COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR: Blend string not + * supported by the GPU + * + * Error enumeration for the blend strings parser + * + * Since: 1.0 + */ +typedef enum { /*< prefix=COGL_BLEND_STRING_ERROR >*/ + COGL_BLEND_STRING_ERROR_PARSE_ERROR, + COGL_BLEND_STRING_ERROR_ARGUMENT_PARSE_ERROR, + COGL_BLEND_STRING_ERROR_INVALID_ERROR, + COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR +} CoglBlendStringError; + +uint32_t +cogl_blend_string_error_quark (void); + +#define COGL_SYSTEM_ERROR (_cogl_system_error_quark ()) + +/** + * CoglSystemError: + * @COGL_SYSTEM_ERROR_UNSUPPORTED: You tried to use a feature or + * configuration not currently available. + * @COGL_SYSTEM_ERROR_NO_MEMORY: You tried to allocate a resource + * such as a texture and there wasn't enough memory. + * + * Error enumeration for Cogl + * + * The @COGL_SYSTEM_ERROR_UNSUPPORTED error can be thrown for a + * variety of reasons. For example: + * + * + * You've tried to use a feature that is not + * advertised by cogl_has_feature(). This could happen if you create + * a 2d texture with a non-power-of-two size when + * %COGL_FEATURE_ID_TEXTURE_NPOT is not advertised. + * The GPU can not handle the configuration you have + * requested. An example might be if you try to use too many texture + * layers in a single #CoglPipeline + * The driver does not support some + * configuration. + * + * + * Currently this is only used by Cogl API marked as experimental so + * this enum should also be considered experimental. + * + * Since: 1.4 + * Stability: unstable + */ +typedef enum { /*< prefix=COGL_ERROR >*/ + COGL_SYSTEM_ERROR_UNSUPPORTED, + COGL_SYSTEM_ERROR_NO_MEMORY +} CoglSystemError; + +uint32_t +_cogl_system_error_quark (void); + +/** + * CoglAttributeType: + * @COGL_ATTRIBUTE_TYPE_BYTE: Data is the same size of a byte + * @COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE: Data is the same size of an + * unsigned byte + * @COGL_ATTRIBUTE_TYPE_SHORT: Data is the same size of a short integer + * @COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT: Data is the same size of + * an unsigned short integer + * @COGL_ATTRIBUTE_TYPE_FLOAT: Data is the same size of a float + * + * Data types for the components of a vertex attribute. + * + * Since: 1.0 + */ +typedef enum { + COGL_ATTRIBUTE_TYPE_BYTE = 0x1400, + COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE = 0x1401, + COGL_ATTRIBUTE_TYPE_SHORT = 0x1402, + COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT = 0x1403, + COGL_ATTRIBUTE_TYPE_FLOAT = 0x1406 +} CoglAttributeType; + +/** + * CoglIndicesType: + * @COGL_INDICES_TYPE_UNSIGNED_BYTE: Your indices are unsigned bytes + * @COGL_INDICES_TYPE_UNSIGNED_SHORT: Your indices are unsigned shorts + * @COGL_INDICES_TYPE_UNSIGNED_INT: Your indices are unsigned ints + * + * You should aim to use the smallest data type that gives you enough + * range, since it reduces the size of your index array and can help + * reduce the demand on memory bandwidth. + * + * Note that %COGL_INDICES_TYPE_UNSIGNED_INT is only supported if the + * %COGL_FEATURE_ID_UNSIGNED_INT_INDICES feature is available. This + * should always be available on OpenGL but on OpenGL ES it will only + * be available if the GL_OES_element_index_uint extension is + * advertized. + */ +typedef enum { + COGL_INDICES_TYPE_UNSIGNED_BYTE, + COGL_INDICES_TYPE_UNSIGNED_SHORT, + COGL_INDICES_TYPE_UNSIGNED_INT +} CoglIndicesType; + +/** + * CoglVerticesMode: + * @COGL_VERTICES_MODE_POINTS: FIXME, equivalent to + * GL_POINTS + * @COGL_VERTICES_MODE_LINES: FIXME, equivalent to GL_LINES + * @COGL_VERTICES_MODE_LINE_LOOP: FIXME, equivalent to + * GL_LINE_LOOP + * @COGL_VERTICES_MODE_LINE_STRIP: FIXME, equivalent to + * GL_LINE_STRIP + * @COGL_VERTICES_MODE_TRIANGLES: FIXME, equivalent to + * GL_TRIANGLES + * @COGL_VERTICES_MODE_TRIANGLE_STRIP: FIXME, equivalent to + * GL_TRIANGLE_STRIP + * @COGL_VERTICES_MODE_TRIANGLE_FAN: FIXME, equivalent to GL_TRIANGLE_FAN + * + * Different ways of interpreting vertices when drawing. + * + * Since: 1.0 + */ +typedef enum { + COGL_VERTICES_MODE_POINTS = 0x0000, + COGL_VERTICES_MODE_LINES = 0x0001, + COGL_VERTICES_MODE_LINE_LOOP = 0x0002, + COGL_VERTICES_MODE_LINE_STRIP = 0x0003, + COGL_VERTICES_MODE_TRIANGLES = 0x0004, + COGL_VERTICES_MODE_TRIANGLE_STRIP = 0x0005, + COGL_VERTICES_MODE_TRIANGLE_FAN = 0x0006 +} CoglVerticesMode; + +/* NB: The above definitions are taken from gl.h equivalents */ + + +/* XXX: should this be CoglMaterialDepthTestFunction? + * It makes it very verbose but would be consistent with + * CoglMaterialWrapMode */ + +/** + * CoglDepthTestFunction: + * @COGL_DEPTH_TEST_FUNCTION_NEVER: Never passes. + * @COGL_DEPTH_TEST_FUNCTION_LESS: Passes if the fragment's depth + * value is less than the value currently in the depth buffer. + * @COGL_DEPTH_TEST_FUNCTION_EQUAL: Passes if the fragment's depth + * value is equal to the value currently in the depth buffer. + * @COGL_DEPTH_TEST_FUNCTION_LEQUAL: Passes if the fragment's depth + * value is less or equal to the value currently in the depth buffer. + * @COGL_DEPTH_TEST_FUNCTION_GREATER: Passes if the fragment's depth + * value is greater than the value currently in the depth buffer. + * @COGL_DEPTH_TEST_FUNCTION_NOTEQUAL: Passes if the fragment's depth + * value is not equal to the value currently in the depth buffer. + * @COGL_DEPTH_TEST_FUNCTION_GEQUAL: Passes if the fragment's depth + * value greater than or equal to the value currently in the depth buffer. + * @COGL_DEPTH_TEST_FUNCTION_ALWAYS: Always passes. + * + * When using depth testing one of these functions is used to compare + * the depth of an incoming fragment against the depth value currently + * stored in the depth buffer. The function is changed using + * cogl_depth_state_set_test_function(). + * + * The test is only done when depth testing is explicitly enabled. (See + * cogl_depth_state_set_test_enabled()) + */ +typedef enum { + COGL_DEPTH_TEST_FUNCTION_NEVER = 0x0200, + COGL_DEPTH_TEST_FUNCTION_LESS = 0x0201, + COGL_DEPTH_TEST_FUNCTION_EQUAL = 0x0202, + COGL_DEPTH_TEST_FUNCTION_LEQUAL = 0x0203, + COGL_DEPTH_TEST_FUNCTION_GREATER = 0x0204, + COGL_DEPTH_TEST_FUNCTION_NOTEQUAL = 0x0205, + COGL_DEPTH_TEST_FUNCTION_GEQUAL = 0x0206, + COGL_DEPTH_TEST_FUNCTION_ALWAYS = 0x0207 +} CoglDepthTestFunction; +/* NB: The above definitions are taken from gl.h equivalents */ + +typedef enum { /*< prefix=COGL_RENDERER_ERROR >*/ + COGL_RENDERER_ERROR_XLIB_DISPLAY_OPEN, + COGL_RENDERER_ERROR_BAD_CONSTRAINT +} CoglRendererError; + +/** + * CoglFilterReturn: + * @COGL_FILTER_CONTINUE: The event was not handled, continues the + * processing + * @COGL_FILTER_REMOVE: Remove the event, stops the processing + * + * Return values for the #CoglXlibFilterFunc and #CoglWin32FilterFunc functions. + * + * Stability: Unstable + */ +typedef enum _CoglFilterReturn { /*< prefix=COGL_FILTER >*/ + COGL_FILTER_CONTINUE, + COGL_FILTER_REMOVE +} CoglFilterReturn; + +typedef enum _CoglWinsysFeature +{ + /* Available if the window system can support multiple onscreen + * framebuffers at the same time. */ + COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN, + + /* Available if onscreen framebuffer swaps can be automatically + * throttled to the vblank frequency. */ + COGL_WINSYS_FEATURE_SWAP_THROTTLE, + + /* Available if its possible to query a counter that + * increments at each vblank. */ + COGL_WINSYS_FEATURE_VBLANK_COUNTER, + + /* Available if its possible to wait until the next vertical + * blank period */ + COGL_WINSYS_FEATURE_VBLANK_WAIT, + + /* Available if the window system supports mapping native + * pixmaps to textures. */ + COGL_WINSYS_FEATURE_TEXTURE_FROM_PIXMAP, + + /* Available if the window system supports reporting an event + * for swap buffer completions. */ + COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT, + + /* Available if it's possible to swap a list of sub rectangles + * from the back buffer to the front buffer */ + COGL_WINSYS_FEATURE_SWAP_REGION, + + /* Available if swap_region requests can be automatically throttled + * to the vblank frequency. */ + COGL_WINSYS_FEATURE_SWAP_REGION_THROTTLE, + + /* Available if the swap region implementation won't tear and thus + * only needs to be throttled to the framerate */ + COGL_WINSYS_FEATURE_SWAP_REGION_SYNCHRONIZED, + + /* Avaiable if the age of the back buffer can be queried */ + COGL_WINSYS_FEATURE_BUFFER_AGE, + + /* Avaiable if the winsys directly handles _SYNC and _COMPLETE events */ + COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT, + + COGL_WINSYS_FEATURE_N_FEATURES +} CoglWinsysFeature; + +/** + * CoglColorMask: + * @COGL_COLOR_MASK_NONE: None of the color channels are masked + * @COGL_COLOR_MASK_RED: Masks the red color channel + * @COGL_COLOR_MASK_GREEN: Masks the green color channel + * @COGL_COLOR_MASK_BLUE: Masks the blue color channel + * @COGL_COLOR_MASK_ALPHA: Masks the alpha color channel + * @COGL_COLOR_MASK_ALL: All of the color channels are masked + * + * Defines a bit mask of color channels. This can be used with + * cogl_pipeline_set_color_mask() for example to define which color + * channels should be written to the current framebuffer when + * drawing something. + */ +typedef enum +{ + COGL_COLOR_MASK_NONE = 0, + COGL_COLOR_MASK_RED = 1L<<0, + COGL_COLOR_MASK_GREEN = 1L<<1, + COGL_COLOR_MASK_BLUE = 1L<<2, + COGL_COLOR_MASK_ALPHA = 1L<<3, + /* XXX: glib-mkenums is a perl script that can't cope if we split + * this onto multiple lines! *sigh* */ + COGL_COLOR_MASK_ALL = (COGL_COLOR_MASK_RED | COGL_COLOR_MASK_GREEN | COGL_COLOR_MASK_BLUE | COGL_COLOR_MASK_ALPHA) +} CoglColorMask; + +/** + * CoglWinding: + * @COGL_WINDING_CLOCKWISE: Vertices are in a clockwise order + * @COGL_WINDING_COUNTER_CLOCKWISE: Vertices are in a counter-clockwise order + * + * Enum used to represent the two directions of rotation. This can be + * used to set the front face for culling by calling + * cogl_pipeline_set_front_face_winding(). + */ +typedef enum +{ + COGL_WINDING_CLOCKWISE, + COGL_WINDING_COUNTER_CLOCKWISE +} CoglWinding; + +/** + * CoglBufferBit: + * @COGL_BUFFER_BIT_COLOR: Selects the primary color buffer + * @COGL_BUFFER_BIT_DEPTH: Selects the depth buffer + * @COGL_BUFFER_BIT_STENCIL: Selects the stencil buffer + * + * Types of auxiliary buffers + * + * Since: 1.0 + */ +typedef enum { + COGL_BUFFER_BIT_COLOR = 1L<<0, + COGL_BUFFER_BIT_DEPTH = 1L<<1, + COGL_BUFFER_BIT_STENCIL = 1L<<2 +} CoglBufferBit; + +/** + * CoglReadPixelsFlags: + * @COGL_READ_PIXELS_COLOR_BUFFER: Read from the color buffer + * + * Flags for cogl_framebuffer_read_pixels_into_bitmap() + * + * Since: 1.0 + */ +typedef enum { /*< prefix=COGL_READ_PIXELS >*/ + COGL_READ_PIXELS_COLOR_BUFFER = 1L << 0 +} CoglReadPixelsFlags; + +/** + * CoglStereoMode: + * @COGL_STEREO_BOTH: draw to both stereo buffers + * @COGL_STEREO_LEFT: draw only to the left stereo buffer + * @COGL_STEREO_RIGHT: draw only to the left stereo buffer + * + * Represents how draw should affect the two buffers + * of a stereo framebuffer. See cogl_framebuffer_set_stereo_mode(). + */ +typedef enum { + COGL_STEREO_BOTH, + COGL_STEREO_LEFT, + COGL_STEREO_RIGHT +} CoglStereoMode; + +COGL_END_DECLS + +#endif /* __COGL_TYPES_H__ */ diff --git a/cogl/cogl/cogl-util.c b/cogl/cogl/cogl-util.c new file mode 100644 index 0000000..f26c896 --- /dev/null +++ b/cogl/cogl/cogl-util.c @@ -0,0 +1,286 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include + +#include "cogl-util.h" +#include "cogl-private.h" + +/* + * cogl_util_next_p2: + * @a: Value to get the next power of two + * + * Calculates the next power of two greater than or equal to @a. + * + * Return value: @a if @a is already a power of two, otherwise returns + * the next nearest power of two. + */ +int +_cogl_util_next_p2 (int a) +{ + int rval = 1; + + while (rval < a) + rval <<= 1; + + return rval; +} + +unsigned int +_cogl_util_one_at_a_time_mix (unsigned int hash) +{ + hash += ( hash << 3 ); + hash ^= ( hash >> 11 ); + hash += ( hash << 15 ); + + return hash; +} + +/* The 'ffs' function is part of C99 so it isn't always available */ +#ifndef HAVE_FFS + +int +_cogl_util_ffs (int num) +{ + int i = 1; + + if (num == 0) + return 0; + + while ((num & 1) == 0) + { + num >>= 1; + i++; + } + + return i; +} +#endif /* HAVE_FFS */ + +/* The 'ffsl' is non-standard but when building with GCC we'll use its + builtin instead */ +#ifndef COGL_UTIL_HAVE_BUILTIN_FFSL + +int +_cogl_util_ffsl_wrapper (long int num) +{ + int i = 1; + + if (num == 0) + return 0; + + while ((num & 1) == 0) + { + num >>= 1; + i++; + } + + return i; +} + +#endif /* COGL_UTIL_HAVE_BUILTIN_FFSL */ + +#ifndef COGL_UTIL_HAVE_BUILTIN_POPCOUNTL + +const unsigned char +_cogl_util_popcount_table[256] = + { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, + 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, + 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, + 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, + 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, + 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 + }; + +#endif /* COGL_UTIL_HAVE_BUILTIN_POPCOUNTL */ + +/* tests/conform/test-bitmask.c tests some cogl internals and includes this + * file directly but since these functions depend on other internal Cogl + * symbols we hide them from test-bitmask.c + * + * XXX: maybe there's a better way for us to handle internal testing + * to avoid needing hacks like this. + */ +#ifndef _COGL_IN_TEST_BITMASK + +/* Given a set of red, green and blue component masks, a depth and + * bits per pixel this function tries to determine a corresponding + * CoglPixelFormat. + * + * The depth is measured in bits not including padding for un-used + * alpha. The bits per pixel (bpp) does include padding for un-used + * alpha. + * + * This function firstly aims to match formats with RGB ordered + * components and only considers alpha coming first, in the most + * significant bits. If the function fails to match then it recurses + * by either switching the r and b masks around to check for BGR + * ordered formats or it recurses with the masks shifted to check for + * formats where the alpha component is the least significant bits. + */ +static CoglPixelFormat +_cogl_util_pixel_format_from_masks_real (unsigned long r_mask, + unsigned long g_mask, + unsigned long b_mask, + int depth, int bpp, + CoglBool check_bgr, + CoglBool check_afirst, + int recursion_depth) +{ + CoglPixelFormat image_format; + + if (depth == 24 && bpp == 24 && + r_mask == 0xff0000 && g_mask == 0xff00 && b_mask == 0xff) + { + return COGL_PIXEL_FORMAT_RGB_888; + } + else if ((depth == 24 || depth == 32) && bpp == 32 && + r_mask == 0xff0000 && g_mask == 0xff00 && b_mask == 0xff) + { + return COGL_PIXEL_FORMAT_ARGB_8888_PRE; + } + else if ((depth == 30 || depth == 32) && + r_mask == 0x3ff00000 && g_mask == 0xffc00 && b_mask == 0x3ff) + { + return COGL_PIXEL_FORMAT_ARGB_2101010_PRE; + } + else if (depth == 16 && bpp == 16 && + r_mask == 0xf800 && g_mask == 0x7e0 && b_mask == 0x1f) + { + return COGL_PIXEL_FORMAT_RGB_565; + } + + if (recursion_depth == 2) + return 0; + + /* Check for BGR ordering if we didn't find a match */ + if (check_bgr) + { + image_format = + _cogl_util_pixel_format_from_masks_real (b_mask, g_mask, r_mask, + depth, bpp, + FALSE, + TRUE, + recursion_depth + 1); + if (image_format) + return image_format ^ COGL_BGR_BIT; + } + + /* Check for alpha in the least significant bits if we still + * haven't found a match... */ + if (check_afirst && depth != bpp) + { + int shift = bpp - depth; + + image_format = + _cogl_util_pixel_format_from_masks_real (r_mask >> shift, + g_mask >> shift, + b_mask >> shift, + depth, bpp, + TRUE, + FALSE, + recursion_depth + 1); + if (image_format) + return image_format ^ COGL_AFIRST_BIT; + } + + return 0; +} + +CoglPixelFormat +_cogl_util_pixel_format_from_masks (unsigned long r_mask, + unsigned long g_mask, + unsigned long b_mask, + int depth, int bpp, + CoglBool byte_order_is_lsb_first) +{ + CoglPixelFormat image_format = + _cogl_util_pixel_format_from_masks_real (r_mask, g_mask, b_mask, + depth, bpp, + TRUE, + TRUE, + 0); + + if (!image_format) + { + const char *byte_order[] = { "MSB first", "LSB first" }; + g_warning ("Could not find a matching pixel format for red mask=0x%lx," + "green mask=0x%lx, blue mask=0x%lx at depth=%d, bpp=%d " + "and byte order=%s\n", r_mask, g_mask, b_mask, depth, bpp, + byte_order[!!byte_order_is_lsb_first]); + return 0; + } + + /* If the image is in little-endian then the order in memory is + reversed */ + if (byte_order_is_lsb_first && + _cogl_pixel_format_is_endian_dependant (image_format)) + { + image_format ^= COGL_BGR_BIT; + if (image_format & COGL_A_BIT) + image_format ^= COGL_AFIRST_BIT; + } + + return image_format; +} + +#ifndef HAVE_MEMMEM + +char * +_cogl_util_memmem (const void *haystack, + size_t haystack_len, + const void *needle, + size_t needle_len) +{ + size_t i; + + if (needle_len > haystack_len) + return NULL; + + for (i = 0; i <= haystack_len - needle_len; i++) + if (!memcmp ((const char *) haystack + i, needle, needle_len)) + return (char *) haystack + i; + + return NULL; +} + +#endif /* HAVE_MEMMEM */ + +#endif /* _COGL_IN_TEST_BITMASK */ diff --git a/cogl/cogl/cogl-util.h b/cogl/cogl/cogl-util.h new file mode 100644 index 0000000..376d177 --- /dev/null +++ b/cogl/cogl/cogl-util.h @@ -0,0 +1,258 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_UTIL_H +#define __COGL_UTIL_H + +#include +#include + +#include +#include "cogl-types.h" + +#include + +/* Double check that config.h has been included */ +#if (!defined (PACKAGE_NAME) && \ + !defined (_COGL_IN_TEST_BITMASK) && \ + !defined(COGL_ENABLE_MUTTER_API)) +#error "cogl-config.h must be included before including cogl-util.h" +#endif + +int +_cogl_util_next_p2 (int a); + +/* The signbit macro is defined by ISO C99 so it should be available, + however if it's not we can fallback to an evil hack */ +#ifdef signbit +#define cogl_util_float_signbit(x) signbit(x) +#else +/* This trick was stolen from here: + http://lists.boost.org/Archives/boost/2006/08/108731.php + + It xors the integer reinterpretations of -1.0f and 1.0f. In theory + they should only differ by the signbit so that gives a mask for the + sign which we can just test against the value */ +static inline CoglBool +cogl_util_float_signbit (float x) +{ + static const union { float f; uint32_t i; } negative_one = { -1.0f }; + static const union { float f; uint32_t i; } positive_one = { +1.0f }; + union { float f; uint32_t i; } value = { x }; + + return !!((negative_one.i ^ positive_one.i) & value.i); +} +#endif + +/* This is a replacement for the nearbyint function which always + rounds to the nearest integer. nearbyint is apparently a C99 + function so it might not always be available but also it seems in + glibc it is defined as a function call so this macro could end up + faster anyway. We can't just add 0.5f because it will break for + negative numbers. */ +#define COGL_UTIL_NEARBYINT(x) ((int) ((x) < 0.0f ? (x) - 0.5f : (x) + 0.5f)) + +/* Returns whether the given integer is a power of two */ +static inline CoglBool +_cogl_util_is_pot (unsigned int num) +{ + /* Make sure there is only one bit set */ + return (num & (num - 1)) == 0; +} + +/* Split Bob Jenkins' One-at-a-Time hash + * + * This uses the One-at-a-Time hash algorithm designed by Bob Jenkins + * but the mixing step is split out so the function can be used in a + * more incremental fashion. + */ +static inline unsigned int +_cogl_util_one_at_a_time_hash (unsigned int hash, + const void *key, + size_t bytes) +{ + const unsigned char *p = key; + size_t i; + + for (i = 0; i < bytes; i++) + { + hash += p[i]; + hash += (hash << 10); + hash ^= (hash >> 6); + } + + return hash; +} + +unsigned int +_cogl_util_one_at_a_time_mix (unsigned int hash); + +/* These two builtins are available since GCC 3.4 */ +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +#define COGL_UTIL_HAVE_BUILTIN_FFSL +#define COGL_UTIL_HAVE_BUILTIN_POPCOUNTL +#define COGL_UTIL_HAVE_BUILTIN_CLZ +#endif + +/* The 'ffs' function is part of C99 so it isn't always available */ +#ifdef HAVE_FFS +#define _cogl_util_ffs ffs +#else +int +_cogl_util_ffs (int num); +#endif + +/* The 'ffsl' function is non-standard but GCC has a builtin for it + since 3.4 which we can use */ +#ifdef COGL_UTIL_HAVE_BUILTIN_FFSL +#define _cogl_util_ffsl __builtin_ffsl +#else +/* If ints and longs are the same size we can just use ffs. Hopefully + the compiler will optimise away this conditional */ +#define _cogl_util_ffsl(x) \ + (sizeof (long int) == sizeof (int) ? _cogl_util_ffs ((int) x) : \ + _cogl_util_ffsl_wrapper (x)) +int +_cogl_util_ffsl_wrapper (long int num); +#endif /* COGL_UTIL_HAVE_BUILTIN_FFSL */ + +static inline unsigned int +_cogl_util_fls (unsigned int n) +{ +#ifdef COGL_UTIL_HAVE_BUILTIN_CLZ + return n == 0 ? 0 : sizeof (unsigned int) * 8 - __builtin_clz (n); +#else + unsigned int v = 1; + + if (n == 0) + return 0; + + while (n >>= 1) + v++; + + return v; +#endif +} + +#ifdef COGL_UTIL_HAVE_BUILTIN_POPCOUNTL +#define _cogl_util_popcountl __builtin_popcountl +#else +extern const unsigned char _cogl_util_popcount_table[256]; + +/* There are many ways of doing popcount but doing a table lookup + seems to be the most robust against different sizes for long. Some + pages seem to claim it's the fastest method anyway. */ +static inline int +_cogl_util_popcountl (unsigned long num) +{ + int i; + int sum = 0; + + /* Let's hope GCC will unroll this loop.. */ + for (i = 0; i < sizeof (num); i++) + sum += _cogl_util_popcount_table[(num >> (i * 8)) & 0xff]; + + return sum; +} + +#endif /* COGL_UTIL_HAVE_BUILTIN_POPCOUNTL */ + +#define _COGL_RETURN_IF_FAIL(EXPR) g_return_if_fail(EXPR) +#define _COGL_RETURN_VAL_IF_FAIL(EXPR, VAL) g_return_val_if_fail(EXPR, VAL) + +/* Match a CoglPixelFormat according to channel masks, color depth, + * bits per pixel and byte order. These information are provided by + * the Visual and XImage structures. + * + * If no specific pixel format could be found, COGL_PIXEL_FORMAT_ANY + * is returned. + */ +CoglPixelFormat +_cogl_util_pixel_format_from_masks (unsigned long r_mask, + unsigned long g_mask, + unsigned long b_mask, + int depth, int bpp, + int byte_order); + +/* Since we can't rely on _Static_assert always being available for + * all compilers we have limited static assert that can be used in + * C code but not in headers. + */ +#define _COGL_TYPEDEF_ASSERT(EXPRESSION) \ + typedef struct { char Compile_Time_Assertion[(EXPRESSION) ? 1 : -1]; } \ + G_PASTE (_GStaticAssert_, __LINE__) + +/* _COGL_STATIC_ASSERT: + * @expression: An expression to assert evaluates to true at compile + * time. + * @message: A message to print to the console if the assertion fails + * at compile time. + * + * Allows you to assert that an expression evaluates to true at + * compile time and aborts compilation if not. If possible message + * will also be printed if the assertion fails. + * + * Note: Only Gcc >= 4.6 supports the c11 _Static_assert which lets us + * print a nice message if the compile time assertion fails. + */ +#ifdef HAVE_STATIC_ASSERT +#define _COGL_STATIC_ASSERT(EXPRESSION, MESSAGE) \ + _Static_assert (EXPRESSION, MESSAGE); +#else +#define _COGL_STATIC_ASSERT(EXPRESSION, MESSAGE) +#endif + +#ifdef HAVE_MEMMEM +#define _cogl_util_memmem memmem +#else +char * +_cogl_util_memmem (const void *haystack, + size_t haystack_len, + const void *needle, + size_t needle_len); +#endif + +static inline void +_cogl_util_scissor_intersect (int rect_x0, + int rect_y0, + int rect_x1, + int rect_y1, + int *scissor_x0, + int *scissor_y0, + int *scissor_x1, + int *scissor_y1) +{ + *scissor_x0 = MAX (*scissor_x0, rect_x0); + *scissor_y0 = MAX (*scissor_y0, rect_y0); + *scissor_x1 = MIN (*scissor_x1, rect_x1); + *scissor_y1 = MIN (*scissor_y1, rect_y1); +} + +#endif /* __COGL_UTIL_H */ diff --git a/cogl/cogl/cogl-vector.c b/cogl/cogl/cogl-vector.c new file mode 100644 index 0000000..e98d01b --- /dev/null +++ b/cogl/cogl/cogl-vector.c @@ -0,0 +1,300 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include +#include + +#include +#include +#include + +#define X 0 +#define Y 1 +#define Z 2 +#define W 3 + +void +cogl_vector3_init (float *vector, float x, float y, float z) +{ + vector[X] = x; + vector[Y] = y; + vector[Z] = z; +} + +void +cogl_vector3_init_zero (float *vector) +{ + memset (vector, 0, sizeof (float) * 3); +} + +CoglBool +cogl_vector3_equal (const void *v1, const void *v2) +{ + float *vector0 = (float *)v1; + float *vector1 = (float *)v2; + + _COGL_RETURN_VAL_IF_FAIL (v1 != NULL, FALSE); + _COGL_RETURN_VAL_IF_FAIL (v2 != NULL, FALSE); + + /* There's no point picking an arbitrary epsilon that's appropriate + * for comparing the components so we just use == that will at least + * consider -0 and 0 to be equal. */ + return + vector0[X] == vector1[X] && + vector0[Y] == vector1[Y] && + vector0[Z] == vector1[Z]; +} + +CoglBool +cogl_vector3_equal_with_epsilon (const float *vector0, + const float *vector1, + float epsilon) +{ + _COGL_RETURN_VAL_IF_FAIL (vector0 != NULL, FALSE); + _COGL_RETURN_VAL_IF_FAIL (vector1 != NULL, FALSE); + + if (fabsf (vector0[X] - vector1[X]) < epsilon && + fabsf (vector0[Y] - vector1[Y]) < epsilon && + fabsf (vector0[Z] - vector1[Z]) < epsilon) + return TRUE; + else + return FALSE; +} + +float * +cogl_vector3_copy (const float *vector) +{ + if (vector) + return g_slice_copy (sizeof (float) * 3, vector); + return NULL; +} + +void +cogl_vector3_free (float *vector) +{ + g_slice_free1 (sizeof (float) * 3, vector); +} + +void +cogl_vector3_invert (float *vector) +{ + vector[X] = -vector[X]; + vector[Y] = -vector[Y]; + vector[Z] = -vector[Z]; +} + +void +cogl_vector3_add (float *result, + const float *a, + const float *b) +{ + result[X] = a[X] + b[X]; + result[Y] = a[Y] + b[Y]; + result[Z] = a[Z] + b[Z]; +} + +void +cogl_vector3_subtract (float *result, + const float *a, + const float *b) +{ + result[X] = a[X] - b[X]; + result[Y] = a[Y] - b[Y]; + result[Z] = a[Z] - b[Z]; +} + +void +cogl_vector3_multiply_scalar (float *vector, + float scalar) +{ + vector[X] *= scalar; + vector[Y] *= scalar; + vector[Z] *= scalar; +} + +void +cogl_vector3_divide_scalar (float *vector, + float scalar) +{ + float one_over_scalar = 1.0f / scalar; + vector[X] *= one_over_scalar; + vector[Y] *= one_over_scalar; + vector[Z] *= one_over_scalar; +} + +void +cogl_vector3_normalize (float *vector) +{ + float mag_squared = + vector[X] * vector[X] + + vector[Y] * vector[Y] + + vector[Z] * vector[Z]; + + if (mag_squared > 0.0f) + { + float one_over_mag = 1.0f / sqrtf (mag_squared); + vector[X] *= one_over_mag; + vector[Y] *= one_over_mag; + vector[Z] *= one_over_mag; + } +} + +float +cogl_vector3_magnitude (const float *vector) +{ + return sqrtf (vector[X] * vector[X] + + vector[Y] * vector[Y] + + vector[Z] * vector[Z]); +} + +void +cogl_vector3_cross_product (float *result, + const float *a, + const float *b) +{ + float tmp[3]; + + tmp[X] = a[Y] * b[Z] - a[Z] * b[Y]; + tmp[Y] = a[Z] * b[X] - a[X] * b[Z]; + tmp[Z] = a[X] * b[Y] - a[Y] * b[X]; + result[X] = tmp[X]; + result[Y] = tmp[Y]; + result[Z] = tmp[Z]; +} + +float +cogl_vector3_dot_product (const float *a, const float *b) +{ + return a[X] * b[X] + a[Y] * b[Y] + a[Z] * b[Z]; +} + +float +cogl_vector3_distance (const float *a, const float *b) +{ + float dx = b[X] - a[X]; + float dy = b[Y] - a[Y]; + float dz = b[Z] - a[Z]; + + return sqrtf (dx * dx + dy * dy + dz * dz); +} + +#if 0 +void +cogl_vector4_init (float *vector, float x, float y, float z) +{ + vector[X] = x; + vector[Y] = y; + vector[Z] = z; + vector[W] = w; +} + +void +cogl_vector4_init_zero (float *vector) +{ + memset (vector, 0, sizeof (CoglVector4)); +} + +void +cogl_vector4_init_from_vector4 (float *vector, float *src) +{ + *vector4 = *src; +} + +CoglBool +cogl_vector4_equal (const void *v0, const void *v1) +{ + _COGL_RETURN_VAL_IF_FAIL (v1 != NULL, FALSE); + _COGL_RETURN_VAL_IF_FAIL (v2 != NULL, FALSE); + + return memcmp (v1, v2, sizeof (float) * 4) == 0 ? TRUE : FALSE; +} + +float * +cogl_vector4_copy (float *vector) +{ + if (vector) + return g_slice_dup (CoglVector4, vector); + return NULL; +} + +void +cogl_vector4_free (float *vector) +{ + g_slice_free (CoglVector4, vector); +} + +void +cogl_vector4_invert (float *vector) +{ + vector.x = -vector.x; + vector.y = -vector.y; + vector.z = -vector.z; + vector.w = -vector.w; +} + +void +cogl_vector4_add (float *result, + float *a, + float *b) +{ + result.x = a.x + b.x; + result.y = a.y + b.y; + result.z = a.z + b.z; + result.w = a.w + b.w; +} + +void +cogl_vector4_subtract (float *result, + float *a, + float *b) +{ + result.x = a.x - b.x; + result.y = a.y - b.y; + result.z = a.z - b.z; + result.w = a.w - b.w; +} + +void +cogl_vector4_divide (float *vector, + float scalar) +{ + float one_over_scalar = 1.0f / scalar; + result.x *= one_over_scalar; + result.y *= one_over_scalar; + result.z *= one_over_scalar; + result.w *= one_over_scalar; +} + +#endif diff --git a/cogl/cogl/cogl-vector.h b/cogl/cogl/cogl-vector.h new file mode 100644 index 0000000..08cf017 --- /dev/null +++ b/cogl/cogl/cogl-vector.h @@ -0,0 +1,356 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Robert Bragg + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_VECTOR_H +#define __COGL_VECTOR_H + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-vector + * @short_description: Functions for handling single precision float + * vectors. + * + * This exposes a utility API that can be used for basic manipulation of 3 + * component float vectors. + */ + +/** + * cogl_vector3_init: + * @vector: The 3 component vector you want to initialize + * @x: The x component + * @y: The y component + * @z: The z component + * + * Initializes a 3 component, single precision float vector which can + * then be manipulated with the cogl_vector convenience APIs. Vectors + * can also be used in places where a "point" is often desired. + * + * Since: 1.4 + * Stability: Unstable + */ +void +cogl_vector3_init (float *vector, float x, float y, float z); + +/** + * cogl_vector3_init_zero: + * @vector: The 3 component vector you want to initialize + * + * Initializes a 3 component, single precision float vector with zero + * for each component. + * + * Since: 1.4 + * Stability: Unstable + */ +void +cogl_vector3_init_zero (float *vector); + +/** + * cogl_vector3_equal: + * @v1: The first 3 component vector you want to compare + * @v2: The second 3 component vector you want to compare + * + * Compares the components of two vectors and returns TRUE if they are + * the same. + * + * The comparison of the components is done with the '==' operator + * such that -0 is considered equal to 0, but otherwise there is no + * fuzziness such as an epsilon to consider vectors that are + * essentially identical except for some minor precision error + * differences due to the way they have been manipulated. + * + * Returns: TRUE if the vectors are equal else FALSE. + * + * Since: 1.4 + * Stability: Unstable + */ +CoglBool +cogl_vector3_equal (const void *v1, const void *v2); + +/** + * cogl_vector3_equal_with_epsilon: + * @vector0: The first 3 component vector you want to compare + * @vector1: The second 3 component vector you want to compare + * @epsilon: The allowable difference between components to still be + * considered equal + * + * Compares the components of two vectors using the given epsilon and + * returns TRUE if they are the same, using an internal epsilon for + * comparing the floats. + * + * Each component is compared against the epsilon value in this way: + * |[ + * if (fabsf (vector0->x - vector1->x) < epsilon) + * ]| + * + * Returns: TRUE if the vectors are equal else FALSE. + * + * Since: 1.4 + * Stability: Unstable + */ +CoglBool +cogl_vector3_equal_with_epsilon (const float *vector0, + const float *vector1, + float epsilon); + +/** + * cogl_vector3_copy: + * @vector: The 3 component vector you want to copy + * + * Allocates a new 3 component float vector on the heap initializing + * the components from the given @vector and returns a pointer to the + * newly allocated vector. You should free the memory using + * cogl_vector3_free() + * + * Returns: A newly allocated 3 component float vector + * + * Since: 1.4 + * Stability: Unstable + */ +float * +cogl_vector3_copy (const float *vector); + +/** + * cogl_vector3_free: + * @vector: The 3 component you want to free + * + * Frees a 3 component vector that was previously allocated with + * cogl_vector3_copy() + * + * Since: 1.4 + * Stability: Unstable + */ +void +cogl_vector3_free (float *vector); + +/** + * cogl_vector3_invert: + * @vector: The 3 component vector you want to manipulate + * + * Inverts/negates all the components of the given @vector. + * + * Since: 1.4 + * Stability: Unstable + */ +void +cogl_vector3_invert (float *vector); + +/** + * cogl_vector3_add: + * @result: Where you want the result written + * @a: The first vector operand + * @b: The second vector operand + * + * Adds each of the corresponding components in vectors @a and @b + * storing the results in @result. + * + * Since: 1.4 + * Stability: Unstable + */ +void +cogl_vector3_add (float *result, + const float *a, + const float *b); + +/** + * cogl_vector3_subtract: + * @result: Where you want the result written + * @a: The first vector operand + * @b: The second vector operand + * + * Subtracts each of the corresponding components in vector @b from + * @a storing the results in @result. + * + * Since: 1.4 + * Stability: Unstable + */ +void +cogl_vector3_subtract (float *result, + const float *a, + const float *b); + +/** + * cogl_vector3_multiply_scalar: + * @vector: The 3 component vector you want to manipulate + * @scalar: The scalar you want to multiply the vector components by + * + * Multiplies each of the @vector components by the given scalar. + * + * Since: 1.4 + * Stability: Unstable + */ +void +cogl_vector3_multiply_scalar (float *vector, + float scalar); + +/** + * cogl_vector3_divide_scalar: + * @vector: The 3 component vector you want to manipulate + * @scalar: The scalar you want to divide the vector components by + * + * Divides each of the @vector components by the given scalar. + * + * Since: 1.4 + * Stability: Unstable + */ +void +cogl_vector3_divide_scalar (float *vector, + float scalar); + +/** + * cogl_vector3_normalize: + * @vector: The 3 component vector you want to manipulate + * + * Updates the vector so it is a "unit vector" such that the + * @vectors magnitude or length is equal to 1. + * + * It's safe to use this function with the [0, 0, 0] vector, it will not + * try to divide components by 0 (its norm) and will leave the vector + * untouched. + * + * Since: 1.4 + * Stability: Unstable + */ +void +cogl_vector3_normalize (float *vector); + +/** + * cogl_vector3_magnitude: + * @vector: The 3 component vector you want the magnitude for + * + * Calculates the scalar magnitude or length of @vector. + * + * Returns: The magnitude of @vector. + * + * Since: 1.4 + * Stability: Unstable + */ +float +cogl_vector3_magnitude (const float *vector); + +/** + * cogl_vector3_cross_product: + * @result: Where you want the result written + * @u: Your first 3 component vector + * @v: Your second 3 component vector + * + * Calculates the cross product between the two vectors @u and @v. + * + * The cross product is a vector perpendicular to both @u and @v. This + * can be useful for calculating the normal of a polygon by creating + * two vectors in its plane using the polygons vertices and taking + * their cross product. + * + * If the two vectors are parallel then the cross product is 0. + * + * You can use a right hand rule to determine which direction the + * perpendicular vector will point: If you place the two vectors tail, + * to tail and imagine grabbing the perpendicular line that extends + * through the common tail with your right hand such that you fingers + * rotate in the direction from @u to @v then the resulting vector + * points along your extended thumb. + * + * Returns: The cross product between two vectors @u and @v. + * + * Since: 1.4 + * Stability: Unstable + */ +void +cogl_vector3_cross_product (float *result, + const float *u, + const float *v); + +/** + * cogl_vector3_dot_product: + * @a: Your first 3 component vector + * @b: Your second 3 component vector + * + * Calculates the dot product of the two 3 component vectors. This + * can be used to determine the magnitude of one vector projected onto + * another. (for example a surface normal) + * + * For example if you have a polygon with a given normal vector and + * some other point for which you want to calculate its distance from + * the polygon, you can create a vector between one of the polygon + * vertices and that point and use the dot product to calculate the + * magnitude for that vector but projected onto the normal of the + * polygon. This way you don't just get the distance from the point to + * the edge of the polygon you get the distance from the point to the + * nearest part of the polygon. + * + * If you don't use a unit length normal in the above example + * then you would then also have to divide the result by the magnitude + * of the normal + * + * The dot product is calculated as: + * |[ + * (a->x * b->x + a->y * b->y + a->z * b->z) + * ]| + * + * For reference, the dot product can also be calculated from the + * angle between two vectors as: + * |[ + * |a||b|cos𝜃 + * ]| + * + * Returns: The dot product of two vectors. + * + * Since: 1.4 + * Stability: Unstable + */ +float +cogl_vector3_dot_product (const float *a, const float *b); + +/** + * cogl_vector3_distance: + * @a: The first point + * @b: The second point + * + * If you consider the two given vectors as (x,y,z) points instead + * then this will compute the distance between those two points. + * + * Returns: The distance between two points given as 3 component + * vectors. + * + * Since: 1.4 + * Stability: Unstable + */ +float +cogl_vector3_distance (const float *a, const float *b); + +COGL_END_DECLS + +#endif /* __COGL_VECTOR_H */ + diff --git a/cogl/cogl/cogl-version.h b/cogl/cogl/cogl-version.h new file mode 100644 index 0000000..bc82437 --- /dev/null +++ b/cogl/cogl/cogl-version.h @@ -0,0 +1,358 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012,2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_VERSION_H__ +#define __COGL_VERSION_H__ + +#include + +/** + * SECTION:cogl-version + * @short_description: Macros for determining the version of Cogl being used + * + * Cogl offers a set of macros for checking the version of the library + * at compile time. + * + * Cogl adds version information to both API deprecations and additions; + * by definining the macros %COGL_VERSION_MIN_REQUIRED and + * %COGL_VERSION_MAX_ALLOWED, you can specify the range of Cogl versions + * whose API you want to use. Functions that were deprecated before, or + * introduced after, this range will trigger compiler warnings. For instance, + * if we define the following symbols: + * + * |[ + * COGL_VERSION_MIN_REQUIRED = COGL_VERSION_1_6 + * COGL_VERSION_MAX_ALLOWED = COGL_VERSION_1_8 + * ]| + * + * and we have the following functions annotated in the Cogl headers: + * + * |[ + * COGL_DEPRECATED_IN_1_4 void cogl_function_A (void); + * COGL_DEPRECATED_IN_1_6 void cogl_function_B (void); + * COGL_AVAILABLE_IN_1_8 void cogl_function_C (void); + * COGL_AVAILABLE_IN_1_10 void cogl_function_D (void); + * ]| + * + * then any application code using the functions above will get the output: + * + * |[ + * cogl_function_A: deprecation warning + * cogl_function_B: no warning + * cogl_function_C: no warning + * cogl_function_D: symbol not available warning + * ]| + * + * It is possible to disable the compiler warnings by defining the macro + * %COGL_DISABLE_DEPRECATION_WARNINGS before including the cogl.h + * header. + */ + +/** + * COGL_VERSION_MAJOR: + * + * The major version of the Cogl library (1, if %COGL_VERSION is 1.2.3) + * + * Since: 1.12.0 + */ +#define COGL_VERSION_MAJOR COGL_VERSION_MAJOR_INTERNAL + +/** + * COGL_VERSION_MINOR: + * + * The minor version of the Cogl library (2, if %COGL_VERSION is 1.2.3) + * + * Since: 1.12.0 + */ +#define COGL_VERSION_MINOR COGL_VERSION_MINOR_INTERNAL + +/** + * COGL_VERSION_MICRO: + * + * The micro version of the Cogl library (3, if %COGL_VERSION is 1.2.3) + * + * Since: 1.12.0 + */ +#define COGL_VERSION_MICRO COGL_VERSION_MICRO_INTERNAL + +/** + * COGL_VERSION_STRING: + * + * The full version of the Cogl library, in string form (suited for + * string concatenation) + * + * Since: 1.12.0 + */ +#define COGL_VERSION_STRING COGL_VERSION_STRING_INTERNAL + +/* Macros to handle compacting a 3-component version number into an + * int for quick comparison. This assumes all of the components are <= + * 1023 and that an int is >= 31 bits */ +#define COGL_VERSION_COMPONENT_BITS 10 +#define COGL_VERSION_MAX_COMPONENT_VALUE \ + ((1 << COGL_VERSION_COMPONENT_BITS) - 1) + +/** + * COGL_VERSION: + * + * The Cogl version encoded into a single integer using the + * COGL_VERSION_ENCODE() macro. This can be used for quick comparisons + * with particular versions. + * + * Since: 1.12.0 + */ +#define COGL_VERSION \ + COGL_VERSION_ENCODE (COGL_VERSION_MAJOR, \ + COGL_VERSION_MINOR, \ + COGL_VERSION_MICRO) + +/** + * COGL_VERSION_ENCODE: + * @major: The major part of a version number + * @minor: The minor part of a version number + * @micro: The micro part of a version number + * + * Encodes a 3 part version number into a single integer. This can be + * used to compare the Cogl version. For example if there is a known + * bug in Cogl versions between 1.3.2 and 1.3.4 you could use the + * following code to provide a workaround: + * + * |[ + * #if COGL_VERSION >= COGL_VERSION_ENCODE (1, 3, 2) && \ + * COGL_VERSION <= COGL_VERSION_ENCODE (1, 3, 4) + * /* Do the workaround */ + * #endif + * ]| + * + * Since: 1.12.0 + */ +#define COGL_VERSION_ENCODE(major, minor, micro) \ + (((major) << (COGL_VERSION_COMPONENT_BITS * 2)) | \ + ((minor) << COGL_VERSION_COMPONENT_BITS) \ + | (micro)) + +/** + * COGL_VERSION_GET_MAJOR: + * @version: An encoded version number + * + * Extracts the major part of an encoded version number. + * + * Since: 1.12.0 + */ +#define COGL_VERSION_GET_MAJOR(version) \ + (((version) >> (COGL_VERSION_COMPONENT_BITS * 2)) \ + & COGL_VERSION_MAX_COMPONENT_VALUE) + +/** + * COGL_VERSION_GET_MINOR: + * @version: An encoded version number + * + * Extracts the minor part of an encoded version number. + * + * Since: 1.12.0 + */ +#define COGL_VERSION_GET_MINOR(version) \ + (((version) >> COGL_VERSION_COMPONENT_BITS) & \ + COGL_VERSION_MAX_COMPONENT_VALUE) + +/** + * COGL_VERSION_GET_MICRO: + * @version: An encoded version number + * + * Extracts the micro part of an encoded version number. + * + * Since: 1.12.0 + */ +#define COGL_VERSION_GET_MICRO(version) \ + ((version) & COGL_VERSION_MAX_COMPONENT_VALUE) + +/** + * COGL_VERSION_CHECK: + * @major: The major part of a version number + * @minor: The minor part of a version number + * @micro: The micro part of a version number + * + * A convenient macro to check whether the Cogl version being compiled + * against is at least the given version number. For example if the + * function cogl_pipeline_frobnicate was added in version 2.0.1 and + * you want to conditionally use that function when it is available, + * you could write the following: + * + * |[ + * #if COGL_VERSION_CHECK (2, 0, 1) + * cogl_pipeline_frobnicate (pipeline); + * #else + * /* Frobnication is not supported. Use a red color instead */ + * cogl_pipeline_set_color_4f (pipeline, 1.0f, 0.0f, 0.0f, 1.0f); + * #endif + * ]| + * + * Return value: %TRUE if the Cogl version being compiled against is + * greater than or equal to the given three part version number. + * Since: 1.12.0 + */ +#define COGL_VERSION_CHECK(major, minor, micro) \ + (COGL_VERSION >= COGL_VERSION_ENCODE (major, minor, micro)) + +/** + * COGL_VERSION_1_0: + * + * A macro that evaluates to the 1.0 version of Cogl, in a format + * that can be used by the C pre-processor. + * + * Since: 1.16 + */ +#define COGL_VERSION_1_0 (COGL_VERSION_ENCODE (1, 0, 0)) + +/** + * COGL_VERSION_1_2: + * + * A macro that evaluates to the 1.2 version of Cogl, in a format + * that can be used by the C pre-processor. + * + * Since: 1.16 + */ +#define COGL_VERSION_1_2 (COGL_VERSION_ENCODE (1, 2, 0)) + +/** + * COGL_VERSION_1_4: + * + * A macro that evaluates to the 1.4 version of Cogl, in a format + * that can be used by the C pre-processor. + * + * Since: 1.16 + */ +#define COGL_VERSION_1_4 (COGL_VERSION_ENCODE (1, 4, 0)) + +/** + * COGL_VERSION_1_6: + * + * A macro that evaluates to the 1.6 version of Cogl, in a format + * that can be used by the C pre-processor. + * + * Since: 1.16 + */ +#define COGL_VERSION_1_6 (COGL_VERSION_ENCODE (1, 6, 0)) + +/** + * COGL_VERSION_1_8: + * + * A macro that evaluates to the 1.8 version of Cogl, in a format + * that can be used by the C pre-processor. + * + * Since: 1.16 + */ +#define COGL_VERSION_1_8 (COGL_VERSION_ENCODE (1, 8, 0)) + +/** + * COGL_VERSION_1_10: + * + * A macro that evaluates to the 1.10 version of Cogl, in a format + * that can be used by the C pre-processor. + * + * Since: 1.16 + */ +#define COGL_VERSION_1_10 (COGL_VERSION_ENCODE (1, 10, 0)) + +/** + * COGL_VERSION_1_12: + * + * A macro that evaluates to the 1.12 version of Cogl, in a format + * that can be used by the C pre-processor. + * + * Since: 1.16 + */ +#define COGL_VERSION_1_12 (COGL_VERSION_ENCODE (1, 12, 0)) + +/** + * COGL_VERSION_1_14: + * + * A macro that evaluates to the 1.14 version of Cogl, in a format + * that can be used by the C pre-processor. + * + * Since: 1.16 + */ +#define COGL_VERSION_1_14 (COGL_VERSION_ENCODE (1, 14, 0)) + +/** + * COGL_VERSION_1_16: + * + * A macro that evaluates to the 1.16 version of Cogl, in a format + * that can be used by the C pre-processor. + * + * Since: 1.16 + */ +#define COGL_VERSION_1_16 (COGL_VERSION_ENCODE (1, 16, 0)) + +/** + * COGL_VERSION_1_18: + * + * A macro that evaluates to the 1.18 version of Cogl, in a format + * that can be used by the C pre-processor. + * + * Since: 1.18 + */ +#define COGL_VERSION_1_18 (COGL_VERSION_ENCODE (1, 18, 0)) + +/** + * COGL_VERSION_1_20: + * + * A macro that evaluates to the 1.20 version of Cogl, in a format + * that can be used by the C pre-processor. + * + * Since: 1.20 + */ +#define COGL_VERSION_1_20 (COGL_VERSION_ENCODE (1, 20, 0)) + +/* evaluates to the current stable version; for development cycles, + * this means the next stable target + */ +#if (COGL_VERSION_MINOR_INTERNAL % 2) +#define COGL_VERSION_CURRENT_STABLE \ + (COGL_VERSION_ENCODE (COGL_VERSION_MAJOR_INTERNAL, \ + COGL_VERSION_MINOR_INTERNAL + 1, 0)) +#else +#define COGL_VERSION_CURRENT_STABLE \ + (COGL_VERSION_ENCODE (COGL_VERSION_MAJOR_INTERNAL, \ + COGL_VERSION_MINOR_INTERNAL, 0)) +#endif + +/* evaluates to the previous stable version */ +#if (COGL_VERSION_MINOR_INTERNAL % 2) +#define COGL_VERSION_PREVIOUS_STABLE \ + (COGL_VERSION_ENCODE (COGL_VERSION_MAJOR_INTERNAL, \ + COGL_VERSION_MINOR_INTERNAL - 1, 0)) +#else +#define COGL_VERSION_PREVIOUS_STABLE \ + (COGL_VERSION_ENCODE (COGL_VERSION_MAJOR_INTERNAL, \ + COGL_VERSION_MINOR_INTERNAL - 2, 0)) +#endif + +#endif /* __COGL_VERSION_H__ */ diff --git a/cogl/cogl/cogl-wayland-server.h b/cogl/cogl/cogl-wayland-server.h new file mode 100644 index 0000000..2712601 --- /dev/null +++ b/cogl/cogl/cogl-wayland-server.h @@ -0,0 +1,163 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef __COGL_WAYLAND_SERVER_H +#define __COGL_WAYLAND_SERVER_H + +#include + +/* NB: this is a top-level header that can be included directly but we + * want to be careful not to define __COGL_H_INSIDE__ when this is + * included internally while building Cogl itself since + * __COGL_H_INSIDE__ is used in headers to guard public vs private api + * definitions + */ +#ifndef COGL_COMPILATION + +/* Note: When building Cogl .gir we explicitly define + * __COGL_H_INSIDE__ */ +#ifndef __COGL_H_INSIDE__ +#define __COGL_H_INSIDE__ +#define __COGL_MUST_UNDEF_COGL_H_INSIDE_COGL_WAYLAND_SERVER_ +#endif + +#endif /* COGL_COMPILATION */ + +#include +#include + +COGL_BEGIN_DECLS + +/** + * cogl_wayland_display_set_compositor_display: + * @display: a #CoglDisplay + * @wayland_display: A compositor's Wayland display pointer + * + * Informs Cogl of a compositor's Wayland display pointer. This + * enables Cogl to register private wayland extensions required to + * pass buffers between the clients and compositor. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_wayland_display_set_compositor_display (CoglDisplay *display, + struct wl_display *wayland_display); + +/** + * cogl_wayland_texture_2d_new_from_buffer: + * @ctx: A #CoglContext + * @buffer: A Wayland resource for a buffer + * @error: A #CoglError for exceptions + * + * Uploads the @buffer referenced by the given Wayland resource to a + * #CoglTexture2D. The buffer resource may refer to a wl_buffer or a + * wl_shm_buffer. + * + * The results are undefined for passing an invalid @buffer + * pointer + * It is undefined if future updates to @buffer outside the + * control of Cogl will affect the allocated #CoglTexture2D. In some + * cases the contents of the buffer are copied (such as shm buffers), + * and in other cases the underlying storage is re-used directly (such + * as drm buffers) + * + * Returns: A newly allocated #CoglTexture2D, or if Cogl could not + * validate the @buffer in some way (perhaps because of + * an unsupported format) it will return %NULL and set + * @error. + * + * Since: 1.10 + * Stability: unstable + */ +CoglTexture2D * +cogl_wayland_texture_2d_new_from_buffer (CoglContext *ctx, + struct wl_resource *buffer, + CoglError **error); + +/** + * cogl_wayland_texture_set_region_from_shm_buffer: + * @texture: a #CoglTexture + * @width: The width of the region to copy + * @height: The height of the region to copy + * @shm_buffer: The source buffer + * @src_x: The X offset within the source bufer to copy from + * @src_y: The Y offset within the source bufer to copy from + * @dst_x: The X offset within the texture to copy to + * @dst_y: The Y offset within the texture to copy to + * @level: The mipmap level of the texture to copy to + * @error: A #CoglError to return exceptional errors + * + * Sets the pixels in a rectangular subregion of @texture from a + * Wayland SHM buffer. Generally this would be used in response to + * wl_surface.damage event in a compositor in order to update the + * texture with the damaged region. This is just a convenience wrapper + * around getting the SHM buffer pointer and calling + * cogl_texture_set_region(). See that function for a description of + * the level parameter. + * + * Since the storage for a #CoglTexture is allocated lazily then + * if the given @texture has not previously been allocated then this + * api can return %FALSE and throw an exceptional @error if there is + * not enough memory to allocate storage for @texture. + * + * Return value: %TRUE if the subregion upload was successful, and + * %FALSE otherwise + * Since: 1.18 + * Stability: unstable + */ +CoglBool +cogl_wayland_texture_set_region_from_shm_buffer (CoglTexture *texture, + int src_x, + int src_y, + int width, + int height, + struct wl_shm_buffer * + shm_buffer, + int dst_x, + int dst_y, + int level, + CoglError **error); + +COGL_END_DECLS + +/* The gobject introspection scanner seems to parse public headers in + * isolation which means we need to be extra careful about how we + * define and undefine __COGL_H_INSIDE__ used to detect when internal + * headers are incorrectly included by developers. In the gobject + * introspection case we have to manually define __COGL_H_INSIDE__ as + * a commandline argument for the scanner which means we must be + * careful not to undefine it in a header... + */ +#ifdef __COGL_MUST_UNDEF_COGL_H_INSIDE_COGL_WAYLAND_SERVER_ +#undef __COGL_H_INSIDE__ +#undef __COGL_MUST_UNDEF_COGL_H_INSIDE_COGL_WAYLAND_SERVER_ +#endif + +#endif /* __COGL_WAYLAND_SERVER_H */ diff --git a/cogl/cogl/cogl-x11-renderer-private.h b/cogl/cogl/cogl-x11-renderer-private.h new file mode 100644 index 0000000..17655da --- /dev/null +++ b/cogl/cogl/cogl-x11-renderer-private.h @@ -0,0 +1,40 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_RENDERER_X11_PRIVATE_H +#define __COGL_RENDERER_X11_PRIVATE_H + +typedef struct _CoglX11Renderer +{ + int damage_base; + int randr_base; +} CoglX11Renderer; + +#endif /* __COGL_RENDERER_X11_PRIVATE_H */ diff --git a/cogl/cogl/cogl-xlib-private.h b/cogl/cogl/cogl-xlib-private.h new file mode 100644 index 0000000..992a320 --- /dev/null +++ b/cogl/cogl/cogl-xlib-private.h @@ -0,0 +1,54 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010,2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_XLIB_PRIVATE_H +#define __COGL_XLIB_PRIVATE_H + +#include + +typedef struct _CoglXlibTrapState CoglXlibTrapState; + +struct _CoglXlibTrapState +{ + /* These values are intended to be internal to + * _cogl_xlib_{un,}trap_errors but they need to be in the header so + * that the struct can be allocated on the stack */ + int (* old_error_handler) (Display *, XErrorEvent *); + int trapped_error_code; + CoglXlibTrapState *old_state; +}; + +void +_cogl_xlib_query_damage_extension (void); + +int +_cogl_xlib_get_damage_base (void); + +#endif /* __COGL_XLIB_PRIVATE_H */ diff --git a/cogl/cogl/cogl-xlib-renderer-private.h b/cogl/cogl/cogl-xlib-renderer-private.h new file mode 100644 index 0000000..ea0ee90 --- /dev/null +++ b/cogl/cogl/cogl-xlib-renderer-private.h @@ -0,0 +1,103 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_RENDERER_XLIB_PRIVATE_H +#define __COGL_RENDERER_XLIB_PRIVATE_H + +#include "cogl-object-private.h" +#include "cogl-xlib-private.h" +#include "cogl-x11-renderer-private.h" +#include "cogl-context.h" +#include "cogl-output.h" + +typedef struct _CoglXlibRenderer +{ + CoglX11Renderer _parent; + + Display *xdpy; + + /* Current top of the XError trap state stack. The actual memory for + these is expected to be allocated on the stack by the caller */ + CoglXlibTrapState *trap_state; + + unsigned long outputs_update_serial; + + XVisualInfo *xvisinfo; +} CoglXlibRenderer; + +CoglBool +_cogl_xlib_renderer_connect (CoglRenderer *renderer, CoglError **error); + +void +_cogl_xlib_renderer_disconnect (CoglRenderer *renderer); + +/* + * cogl_xlib_renderer_trap_errors: + * @state: A temporary place to store data for the trap. + * + * Traps every X error until _cogl_xlib_renderer_untrap_errors() + * called. You should allocate an uninitialised CoglXlibTrapState + * struct on the stack to pass to this function. The same pointer + * should later be passed to _cogl_xlib_renderer_untrap_errors(). + * + * Calls to _cogl_xlib_renderer_trap_errors() can be nested as long as + * _cogl_xlib_renderer_untrap_errors() is called with the + * corresponding state pointers in reverse order. + */ +void +_cogl_xlib_renderer_trap_errors (CoglRenderer *renderer, + CoglXlibTrapState *state); + +/* + * cogl_xlib_renderer_untrap_errors: + * @state: The state that was passed to _cogl_xlib_renderer_trap_errors(). + * + * Removes the X error trap and returns the current status. + * + * Return value: the trapped error code, or 0 for success + */ +int +_cogl_xlib_renderer_untrap_errors (CoglRenderer *renderer, + CoglXlibTrapState *state); + +CoglXlibRenderer * +_cogl_xlib_renderer_get_data (CoglRenderer *renderer); + +int64_t +_cogl_xlib_renderer_get_dispatch_timeout (CoglRenderer *renderer); + +CoglOutput * +_cogl_xlib_renderer_output_for_rectangle (CoglRenderer *renderer, + int x, + int y, + int width, + int height); + +#endif /* __COGL_RENDERER_XLIB_PRIVATE_H */ diff --git a/cogl/cogl/cogl-xlib-renderer.c b/cogl/cogl/cogl-xlib-renderer.c new file mode 100644 index 0000000..66fe0e5 --- /dev/null +++ b/cogl/cogl/cogl-xlib-renderer.c @@ -0,0 +1,677 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-xlib-renderer.h" +#include "cogl-util.h" +#include "cogl-object.h" + +#include "cogl-output-private.h" +#include "cogl-renderer-private.h" +#include "cogl-xlib-renderer-private.h" +#include "cogl-x11-renderer-private.h" +#include "cogl-winsys-private.h" +#include "cogl-error-private.h" +#include "cogl-poll-private.h" + +#include +#include +#include + +#include +#include + +static char *_cogl_x11_display_name = NULL; +static GList *_cogl_xlib_renderers = NULL; + +static void +destroy_xlib_renderer_data (void *user_data) +{ + CoglXlibRenderer *data = user_data; + + if (data->xvisinfo) + XFree (data->xvisinfo); + + g_slice_free (CoglXlibRenderer, user_data); +} + +CoglXlibRenderer * +_cogl_xlib_renderer_get_data (CoglRenderer *renderer) +{ + static CoglUserDataKey key; + CoglXlibRenderer *data; + + /* Constructs a CoglXlibRenderer struct on demand and attaches it to + the object using user data. It's done this way instead of using a + subclassing hierarchy in the winsys data because all EGL winsys's + need the EGL winsys data but only one of them wants the Xlib + data. */ + + data = cogl_object_get_user_data (COGL_OBJECT (renderer), &key); + + if (data == NULL) + { + data = g_slice_new0 (CoglXlibRenderer); + + cogl_object_set_user_data (COGL_OBJECT (renderer), + &key, + data, + destroy_xlib_renderer_data); + } + + return data; +} + +static void +register_xlib_renderer (CoglRenderer *renderer) +{ + GList *l; + + for (l = _cogl_xlib_renderers; l; l = l->next) + if (l->data == renderer) + return; + + _cogl_xlib_renderers = g_list_prepend (_cogl_xlib_renderers, renderer); +} + +static void +unregister_xlib_renderer (CoglRenderer *renderer) +{ + _cogl_xlib_renderers = g_list_remove (_cogl_xlib_renderers, renderer); +} + +static CoglRenderer * +get_renderer_for_xdisplay (Display *xdpy) +{ + GList *l; + + for (l = _cogl_xlib_renderers; l; l = l->next) + { + CoglRenderer *renderer = l->data; + CoglXlibRenderer *xlib_renderer = + _cogl_xlib_renderer_get_data (renderer); + + if (xlib_renderer->xdpy == xdpy) + return renderer; + } + + return NULL; +} + +static int +error_handler (Display *xdpy, + XErrorEvent *error) +{ + CoglRenderer *renderer; + CoglXlibRenderer *xlib_renderer; + + renderer = get_renderer_for_xdisplay (xdpy); + + xlib_renderer = _cogl_xlib_renderer_get_data (renderer); + g_assert (xlib_renderer->trap_state); + + xlib_renderer->trap_state->trapped_error_code = error->error_code; + + return 0; +} + +void +_cogl_xlib_renderer_trap_errors (CoglRenderer *renderer, + CoglXlibTrapState *state) +{ + CoglXlibRenderer *xlib_renderer; + + xlib_renderer = _cogl_xlib_renderer_get_data (renderer); + + state->trapped_error_code = 0; + state->old_error_handler = XSetErrorHandler (error_handler); + + state->old_state = xlib_renderer->trap_state; + xlib_renderer->trap_state = state; +} + +int +_cogl_xlib_renderer_untrap_errors (CoglRenderer *renderer, + CoglXlibTrapState *state) +{ + CoglXlibRenderer *xlib_renderer; + + xlib_renderer = _cogl_xlib_renderer_get_data (renderer); + g_assert (state == xlib_renderer->trap_state); + + XSetErrorHandler (state->old_error_handler); + + xlib_renderer->trap_state = state->old_state; + + return state->trapped_error_code; +} + +static Display * +assert_xlib_display (CoglRenderer *renderer, CoglError **error) +{ + Display *xdpy = cogl_xlib_renderer_get_foreign_display (renderer); + CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (renderer); + + /* A foreign display may have already been set... */ + if (xdpy) + { + xlib_renderer->xdpy = xdpy; + return xdpy; + } + + xdpy = XOpenDisplay (_cogl_x11_display_name); + if (xdpy == NULL) + { + _cogl_set_error (error, + COGL_RENDERER_ERROR, + COGL_RENDERER_ERROR_XLIB_DISPLAY_OPEN, + "Failed to open X Display %s", _cogl_x11_display_name); + return NULL; + } + + xlib_renderer->xdpy = xdpy; + return xdpy; +} + +static int +compare_outputs (CoglOutput *a, + CoglOutput *b) +{ + return strcmp (a->name, b->name); +} + +#define CSO(X) COGL_SUBPIXEL_ORDER_ ## X +static CoglSubpixelOrder subpixel_map[6][6] = { + { CSO(UNKNOWN), CSO(NONE), CSO(HORIZONTAL_RGB), CSO(HORIZONTAL_BGR), + CSO(VERTICAL_RGB), CSO(VERTICAL_BGR) }, /* 0 */ + { CSO(UNKNOWN), CSO(NONE), CSO(VERTICAL_RGB), CSO(VERTICAL_BGR), + CSO(HORIZONTAL_BGR), CSO(HORIZONTAL_RGB) }, /* 90 */ + { CSO(UNKNOWN), CSO(NONE), CSO(HORIZONTAL_BGR), CSO(HORIZONTAL_RGB), + CSO(VERTICAL_BGR), CSO(VERTICAL_RGB) }, /* 180 */ + { CSO(UNKNOWN), CSO(NONE), CSO(VERTICAL_BGR), CSO(VERTICAL_RGB), + CSO(HORIZONTAL_RGB), CSO(HORIZONTAL_BGR) }, /* 270 */ + { CSO(UNKNOWN), CSO(NONE), CSO(HORIZONTAL_BGR), CSO(HORIZONTAL_RGB), + CSO(VERTICAL_RGB), CSO(VERTICAL_BGR) }, /* Reflect_X */ + { CSO(UNKNOWN), CSO(NONE), CSO(HORIZONTAL_RGB), CSO(HORIZONTAL_BGR), + CSO(VERTICAL_BGR), CSO(VERTICAL_RGB) }, /* Reflect_Y */ +}; +#undef CSO + +static void +update_outputs (CoglRenderer *renderer, + CoglBool notify) +{ + CoglXlibRenderer *xlib_renderer = + _cogl_xlib_renderer_get_data (renderer); + XRRScreenResources *resources; + CoglXlibTrapState state; + CoglBool error = FALSE; + GList *new_outputs = NULL; + GList *l, *m; + CoglBool changed = FALSE; + int i; + + xlib_renderer->outputs_update_serial = XNextRequest (xlib_renderer->xdpy); + + resources = XRRGetScreenResources (xlib_renderer->xdpy, + DefaultRootWindow (xlib_renderer->xdpy)); + + _cogl_xlib_renderer_trap_errors (renderer, &state); + + for (i = 0; resources && i < resources->ncrtc && !error; i++) + { + XRRCrtcInfo *crtc_info = NULL; + XRROutputInfo *output_info = NULL; + CoglOutput *output; + float refresh_rate = 0; + int j; + + crtc_info = XRRGetCrtcInfo (xlib_renderer->xdpy, + resources, resources->crtcs[i]); + if (crtc_info == NULL) + { + error = TRUE; + goto next; + } + + if (crtc_info->mode == None) + goto next; + + for (j = 0; j < resources->nmode; j++) + { + if (resources->modes[j].id == crtc_info->mode) + refresh_rate = (resources->modes[j].dotClock / + ((float)resources->modes[j].hTotal * + resources->modes[j].vTotal)); + } + + output_info = XRRGetOutputInfo (xlib_renderer->xdpy, + resources, + crtc_info->outputs[0]); + if (output_info == NULL) + { + error = TRUE; + goto next; + } + + output = _cogl_output_new (output_info->name); + output->x = crtc_info->x; + output->y = crtc_info->y; + output->width = crtc_info->width; + output->height = crtc_info->height; + if ((crtc_info->rotation & (RR_Rotate_90 | RR_Rotate_270)) != 0) + { + output->mm_width = output_info->mm_height; + output->mm_height = output_info->mm_width; + } + else + { + output->mm_width = output_info->mm_width; + output->mm_height = output_info->mm_height; + } + + output->refresh_rate = refresh_rate; + + switch (output_info->subpixel_order) + { + case SubPixelUnknown: + default: + output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN; + break; + case SubPixelNone: + output->subpixel_order = COGL_SUBPIXEL_ORDER_NONE; + break; + case SubPixelHorizontalRGB: + output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB; + break; + case SubPixelHorizontalBGR: + output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_BGR; + break; + case SubPixelVerticalRGB: + output->subpixel_order = COGL_SUBPIXEL_ORDER_VERTICAL_RGB; + break; + case SubPixelVerticalBGR: + output->subpixel_order = COGL_SUBPIXEL_ORDER_VERTICAL_BGR; + break; + } + + output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB; + + /* Handle the effect of rotation and reflection on subpixel order (ugh) */ + for (j = 0; j < 6; j++) + { + if ((crtc_info->rotation & (1 << j)) != 0) + output->subpixel_order = subpixel_map[j][output->subpixel_order]; + } + + new_outputs = g_list_prepend (new_outputs, output); + + next: + if (crtc_info != NULL) + XFree (crtc_info); + + if (output_info != NULL) + XFree (output_info); + } + + XFree (resources); + + if (!error) + { + new_outputs = g_list_sort (new_outputs, (GCompareFunc)compare_outputs); + + l = new_outputs; + m = renderer->outputs; + + while (l || m) + { + int cmp; + CoglOutput *output_l = l ? (CoglOutput *)l->data : NULL; + CoglOutput *output_m = m ? (CoglOutput *)m->data : NULL; + + if (l && m) + cmp = compare_outputs (output_l, output_m); + else if (l) + cmp = -1; + else + cmp = 1; + + if (cmp == 0) + { + GList *m_next = m->next; + + if (!_cogl_output_values_equal (output_l, output_m)) + { + renderer->outputs = g_list_remove_link (renderer->outputs, m); + renderer->outputs = g_list_insert_before (renderer->outputs, + m_next, output_l); + cogl_object_ref (output_l); + + changed = TRUE; + } + + l = l->next; + m = m_next; + } + else if (cmp < 0) + { + renderer->outputs = + g_list_insert_before (renderer->outputs, m, output_l); + cogl_object_ref (output_l); + changed = TRUE; + l = l->next; + } + else + { + GList *m_next = m->next; + renderer->outputs = g_list_remove_link (renderer->outputs, m); + changed = TRUE; + m = m_next; + } + } + } + + g_list_free_full (new_outputs, (GDestroyNotify)cogl_object_unref); + _cogl_xlib_renderer_untrap_errors (renderer, &state); + + if (changed) + { + const CoglWinsysVtable *winsys = renderer->winsys_vtable; + + if (notify) + COGL_NOTE (WINSYS, "Outputs changed:"); + else + COGL_NOTE (WINSYS, "Outputs:"); + + for (l = renderer->outputs; l; l = l->next) + { + CoglOutput *output = l->data; + const char *subpixel_string; + + switch (output->subpixel_order) + { + case COGL_SUBPIXEL_ORDER_UNKNOWN: + default: + subpixel_string = "unknown"; + break; + case COGL_SUBPIXEL_ORDER_NONE: + subpixel_string = "none"; + break; + case COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB: + subpixel_string = "horizontal_rgb"; + break; + case COGL_SUBPIXEL_ORDER_HORIZONTAL_BGR: + subpixel_string = "horizontal_bgr"; + break; + case COGL_SUBPIXEL_ORDER_VERTICAL_RGB: + subpixel_string = "vertical_rgb"; + break; + case COGL_SUBPIXEL_ORDER_VERTICAL_BGR: + subpixel_string = "vertical_bgr"; + break; + } + + COGL_NOTE (WINSYS, + " %10s: +%d+%dx%dx%d mm=%dx%d dpi=%.1fx%.1f " + "subpixel_order=%s refresh_rate=%.3f", + output->name, + output->x, output->y, output->width, output->height, + output->mm_width, output->mm_height, + output->width / (output->mm_width / 25.4), + output->height / (output->mm_height / 25.4), + subpixel_string, + output->refresh_rate); + } + + if (notify && winsys->renderer_outputs_changed != NULL) + winsys->renderer_outputs_changed (renderer); + } +} + +static CoglFilterReturn +randr_filter (XEvent *event, + void *data) +{ + CoglRenderer *renderer = data; + CoglXlibRenderer *xlib_renderer = + _cogl_xlib_renderer_get_data (renderer); + CoglX11Renderer *x11_renderer = + (CoglX11Renderer *) xlib_renderer; + + if (x11_renderer->randr_base != -1 && + (event->xany.type == x11_renderer->randr_base + RRScreenChangeNotify || + event->xany.type == x11_renderer->randr_base + RRNotify) && + event->xany.serial >= xlib_renderer->outputs_update_serial) + update_outputs (renderer, TRUE); + + return COGL_FILTER_CONTINUE; +} + +static int64_t +prepare_xlib_events_timeout (void *user_data) +{ + CoglRenderer *renderer = user_data; + CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (renderer); + + return XPending (xlib_renderer->xdpy) ? 0 : -1; +} + +static void +dispatch_xlib_events (void *user_data, int revents) +{ + CoglRenderer *renderer = user_data; + CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (renderer); + + if (renderer->xlib_enable_event_retrieval) + while (XPending (xlib_renderer->xdpy)) + { + XEvent xevent; + + XNextEvent (xlib_renderer->xdpy, &xevent); + + cogl_xlib_renderer_handle_event (renderer, &xevent); + } +} + +CoglBool +_cogl_xlib_renderer_connect (CoglRenderer *renderer, CoglError **error) +{ + CoglXlibRenderer *xlib_renderer = + _cogl_xlib_renderer_get_data (renderer); + CoglX11Renderer *x11_renderer = + (CoglX11Renderer *) xlib_renderer; + int damage_error; + int randr_error; + + if (!assert_xlib_display (renderer, error)) + return FALSE; + + if (getenv ("COGL_X11_SYNC")) + XSynchronize (xlib_renderer->xdpy, TRUE); + + /* Check whether damage events are supported on this display */ + if (!XDamageQueryExtension (xlib_renderer->xdpy, + &x11_renderer->damage_base, + &damage_error)) + x11_renderer->damage_base = -1; + + /* Check whether randr is supported on this display */ + if (!XRRQueryExtension (xlib_renderer->xdpy, + &x11_renderer->randr_base, + &randr_error)) + x11_renderer->randr_base = -1; + + xlib_renderer->trap_state = NULL; + + if (renderer->xlib_enable_event_retrieval) + { + _cogl_poll_renderer_add_fd (renderer, + ConnectionNumber (xlib_renderer->xdpy), + COGL_POLL_FD_EVENT_IN, + prepare_xlib_events_timeout, + dispatch_xlib_events, + renderer); + } + + XRRSelectInput(xlib_renderer->xdpy, + DefaultRootWindow (xlib_renderer->xdpy), + RRScreenChangeNotifyMask + | RRCrtcChangeNotifyMask + | RROutputPropertyNotifyMask); + update_outputs (renderer, FALSE); + + register_xlib_renderer (renderer); + + cogl_xlib_renderer_add_filter (renderer, + randr_filter, + renderer); + + return TRUE; +} + +void +_cogl_xlib_renderer_disconnect (CoglRenderer *renderer) +{ + CoglXlibRenderer *xlib_renderer = + _cogl_xlib_renderer_get_data (renderer); + + g_list_free_full (renderer->outputs, (GDestroyNotify)cogl_object_unref); + renderer->outputs = NULL; + + if (!renderer->foreign_xdpy && xlib_renderer->xdpy) + XCloseDisplay (xlib_renderer->xdpy); + + unregister_xlib_renderer (renderer); +} + +Display * +cogl_xlib_renderer_get_display (CoglRenderer *renderer) +{ + CoglXlibRenderer *xlib_renderer; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_renderer (renderer), NULL); + + xlib_renderer = _cogl_xlib_renderer_get_data (renderer); + + return xlib_renderer->xdpy; +} + +CoglFilterReturn +cogl_xlib_renderer_handle_event (CoglRenderer *renderer, + XEvent *event) +{ + return _cogl_renderer_handle_native_event (renderer, event); +} + +void +cogl_xlib_renderer_add_filter (CoglRenderer *renderer, + CoglXlibFilterFunc func, + void *data) +{ + _cogl_renderer_add_native_filter (renderer, + (CoglNativeFilterFunc)func, data); +} + +void +cogl_xlib_renderer_remove_filter (CoglRenderer *renderer, + CoglXlibFilterFunc func, + void *data) +{ + _cogl_renderer_remove_native_filter (renderer, + (CoglNativeFilterFunc)func, data); +} + +int64_t +_cogl_xlib_renderer_get_dispatch_timeout (CoglRenderer *renderer) +{ + CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (renderer); + + if (renderer->xlib_enable_event_retrieval) + { + if (XPending (xlib_renderer->xdpy)) + return 0; + else + return -1; + } + else + return -1; +} + +CoglOutput * +_cogl_xlib_renderer_output_for_rectangle (CoglRenderer *renderer, + int x, + int y, + int width, + int height) +{ + int max_overlap = 0; + CoglOutput *max_overlapped = NULL; + GList *l; + int xa1 = x, xa2 = x + width; + int ya1 = y, ya2 = y + height; + + for (l = renderer->outputs; l; l = l->next) + { + CoglOutput *output = l->data; + int xb1 = output->x, xb2 = output->x + output->width; + int yb1 = output->y, yb2 = output->y + output->height; + + int overlap_x = MIN(xa2, xb2) - MAX(xa1, xb1); + int overlap_y = MIN(ya2, yb2) - MAX(ya1, yb1); + + if (overlap_x > 0 && overlap_y > 0) + { + int overlap = overlap_x * overlap_y; + if (overlap > max_overlap) + { + max_overlap = overlap; + max_overlapped = output; + } + } + } + + return max_overlapped; +} + +XVisualInfo * +cogl_xlib_renderer_get_visual_info (CoglRenderer *renderer) +{ + CoglXlibRenderer *xlib_renderer; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_renderer (renderer), NULL); + + xlib_renderer = _cogl_xlib_renderer_get_data (renderer); + + return xlib_renderer->xvisinfo; +} diff --git a/cogl/cogl/cogl-xlib-renderer.h b/cogl/cogl/cogl-xlib-renderer.h new file mode 100644 index 0000000..f3c1d7c --- /dev/null +++ b/cogl/cogl/cogl-xlib-renderer.h @@ -0,0 +1,238 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#if !defined(__COGL_XLIB_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_XLIB_RENDERER_H__ +#define __COGL_XLIB_RENDERER_H__ + +#include +#include + +/* NB: this is a top-level header that can be included directly but we + * want to be careful not to define __COGL_H_INSIDE__ when this is + * included internally while building Cogl itself since + * __COGL_H_INSIDE__ is used in headers to guard public vs private api + * definitions + */ +#ifndef COGL_COMPILATION + +/* Note: When building Cogl .gir we explicitly define + * __COGL_H_INSIDE__ */ +#ifndef __COGL_H_INSIDE__ +#define __COGL_H_INSIDE__ +#define __COGL_XLIB_RENDERER_H_MUST_UNDEF_COGL_H_INSIDE_COGL_XLIB_RENDERER_ +#endif + +#endif /* COGL_COMPILATION */ + +#include + +COGL_BEGIN_DECLS + +/** + * cogl_xlib_renderer_handle_event: (skip) + * @renderer: a #CoglRenderer + * @event: pointer to an XEvent structure + * + * This function processes a single event; it can be used to hook into + * external event retrieval (for example that done by Clutter or + * GDK). + * + * Return value: #CoglFilterReturn. %COGL_FILTER_REMOVE indicates that + * Cogl has internally handled the event and the caller should do no + * further processing. %COGL_FILTER_CONTINUE indicates that Cogl is + * either not interested in the event, or has used the event to update + * internal state without taking any exclusive action. + */ +CoglFilterReturn +cogl_xlib_renderer_handle_event (CoglRenderer *renderer, + XEvent *event); + +/* + * CoglXlibFilterFunc: + * @event: pointer to an XEvent structure + * @data: the data that was given when the filter was added + * + * A callback function that can be registered with + * cogl_xlib_renderer_add_filter(). The function should return + * %COGL_FILTER_REMOVE if it wants to prevent further processing or + * %COGL_FILTER_CONTINUE otherwise. + */ +typedef CoglFilterReturn (* CoglXlibFilterFunc) (XEvent *event, + void *data); + +/** + * cogl_xlib_renderer_add_filter: (skip) + * @renderer: a #CoglRenderer + * @func: the callback function + * @data: user data passed to @func when called + * + * Adds a callback function that will receive all native events. The + * function can stop further processing of the event by return + * %COGL_FILTER_REMOVE. + */ +void +cogl_xlib_renderer_add_filter (CoglRenderer *renderer, + CoglXlibFilterFunc func, + void *data); + +/** + * cogl_xlib_renderer_remove_filter: (skip) + * @renderer: a #CoglRenderer + * @func: the callback function + * @data: user data given when the callback was installed + * + * Removes a callback that was previously added with + * cogl_xlib_renderer_add_filter(). + */ +void +cogl_xlib_renderer_remove_filter (CoglRenderer *renderer, + CoglXlibFilterFunc func, + void *data); + +/** + * cogl_xlib_renderer_get_foreign_display: (skip) + * @renderer: a #CoglRenderer + * + * Return value: the foreign Xlib display that will be used by any Xlib based + * winsys backend. The display needs to be set with + * cogl_xlib_renderer_set_foreign_display() before this function is called. + */ +Display * +cogl_xlib_renderer_get_foreign_display (CoglRenderer *renderer); + +/** + * cogl_xlib_renderer_set_foreign_display: (skip) + * @renderer: a #CoglRenderer + * + * Sets a foreign Xlib display that Cogl will use for and Xlib based winsys + * backend. + * + * Note that calling this function will automatically call + * cogl_xlib_renderer_set_event_retrieval_enabled() to disable Cogl's + * event retrieval. Cogl still needs to see all of the X events so the + * application should also use cogl_xlib_renderer_handle_event() if it + * uses this function. + */ +void +cogl_xlib_renderer_set_foreign_display (CoglRenderer *renderer, + Display *display); + +/** + * cogl_xlib_renderer_set_event_retrieval_enabled: (skip) + * @renderer: a #CoglRenderer + * @enable: The new value + * + * Sets whether Cogl should automatically retrieve events from the X + * display. This defaults to %TRUE unless + * cogl_xlib_renderer_set_foreign_display() is called. It can be set + * to %FALSE if the application wants to handle its own event + * retrieval. Note that Cogl still needs to see all of the X events to + * function properly so the application should call + * cogl_xlib_renderer_handle_event() for each event if it disables + * automatic event retrieval. + * + * Since: 1.10 + * Stability: unstable + */ +void +cogl_xlib_renderer_set_event_retrieval_enabled (CoglRenderer *renderer, + CoglBool enable); + +/** + * cogl_xlib_renderer_get_display: (skip) + */ +Display * +cogl_xlib_renderer_get_display (CoglRenderer *renderer); + +/** + * cogl_xlib_renderer_get_visual_info: (skip) + */ +XVisualInfo * +cogl_xlib_renderer_get_visual_info (CoglRenderer *renderer); + +/** + * cogl_xlib_renderer_request_reset_on_video_memory_purge: (skip) + * @renderer: a #CoglRenderer + * @enable: The new value + * + * Sets whether Cogl should make use of the + * NV_robustness_video_memory_purge extension, if exposed by the + * driver, by initializing the GLX context appropriately. + * + * The extension is only useful when running on certain versions of + * the NVIDIA driver. Quoting from the spec: + * + * "The NVIDIA OpenGL driver architecture on Linux has a limitation: + * resources located in video memory are not persistent across certain + * events. VT switches, suspend/resume events, and mode switching + * events may erase the contents of video memory. Any resource that + * is located exclusively in video memory, such as framebuffer objects + * (FBOs), will be lost." + * + * "This extension provides a way for applications to discover when video + * memory content has been lost, so that the application can re-populate + * the video memory content as necessary." + * + * "Any driver that exposes this extension is a driver that considers + * video memory to be volatile. Once the driver stack has been + * improved, the extension will no longer be exposed." + * + * cogl_get_graphics_reset_status() needs to be called at least once + * every frame to find out if video memory was purged. + * + * Note that this doesn't cause Cogl to enable robust buffer access + * but other context reset errors may still happen and be reported via + * cogl_get_graphics_reset_status() if external factors cause the + * driver to trigger them. + * + * This defaults to %FALSE and is effective only if called before + * cogl_display_setup() . + */ +void +cogl_xlib_renderer_request_reset_on_video_memory_purge (CoglRenderer *renderer, + CoglBool enable); +COGL_END_DECLS + +/* The gobject introspection scanner seems to parse public headers in + * isolation which means we need to be extra careful about how we + * define and undefine __COGL_H_INSIDE__ used to detect when internal + * headers are incorrectly included by developers. In the gobject + * introspection case we have to manually define __COGL_H_INSIDE__ as + * a commandline argument for the scanner which means we must be + * careful not to undefine it in a header... + */ +#ifdef __COGL_XLIB_RENDERER_H_MUST_UNDEF_COGL_H_INSIDE_COGL_XLIB_RENDERER_ +#undef __COGL_H_INSIDE__ +#undef __COGL_XLIB_RENDERER_H_MUST_UNDEF_COGL_H_INSIDE_COGL_XLIB_RENDERER_ +#endif + +#endif /* __COGL_XLIB_RENDERER_H__ */ diff --git a/cogl/cogl/cogl-xlib.c b/cogl/cogl/cogl-xlib.c new file mode 100644 index 0000000..c381035 --- /dev/null +++ b/cogl/cogl/cogl-xlib.c @@ -0,0 +1,112 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010,2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Robert Bragg + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "cogl-xlib.h" + +/* FIXME: when we remove the last X11 based Clutter backend then we + * will get rid of these functions and instead rely on the equivalent + * _cogl_xlib_renderer API + */ + +/* This can't be in the Cogl context because it can be set before + context is created */ +static Display *_cogl_xlib_display = NULL; + +Display * +cogl_xlib_get_display (void) +{ + _COGL_GET_CONTEXT (ctx, NULL); + + return cogl_xlib_renderer_get_display (ctx->display->renderer); +} + +void +cogl_xlib_set_display (Display *display) +{ + /* This can only be called once before the Cogl context is created */ + g_assert (_cogl_xlib_display == NULL); + + _cogl_xlib_display = display; +} + +/* These three functions are wrappers around the equivalent renderer + functions. They can be removed once all xlib-based backends in + Clutter know about the renderer */ +CoglFilterReturn +cogl_xlib_handle_event (XEvent *xevent) +{ + _COGL_GET_CONTEXT (ctx, COGL_FILTER_CONTINUE); + + /* Pass the event on to the renderer */ + return cogl_xlib_renderer_handle_event (ctx->display->renderer, xevent); +} + +void +_cogl_xlib_query_damage_extension (void) +{ + int damage_error; + Display *display; + + _COGL_GET_CONTEXT (ctxt, NO_RETVAL); + + /* Check whether damage events are supported on this display */ + display = cogl_xlib_renderer_get_display (ctxt->display->renderer); + if (!XDamageQueryExtension (display, &ctxt->damage_base, &damage_error)) + ctxt->damage_base = -1; +} + +int +_cogl_xlib_get_damage_base (void) +{ + CoglX11Renderer *x11_renderer; + _COGL_GET_CONTEXT (ctxt, -1); + + x11_renderer = + (CoglX11Renderer *) _cogl_xlib_renderer_get_data (ctxt->display->renderer); + return x11_renderer->damage_base; +} diff --git a/cogl/cogl/cogl-xlib.h b/cogl/cogl/cogl-xlib.h new file mode 100644 index 0000000..ac4a140 --- /dev/null +++ b/cogl/cogl/cogl-xlib.h @@ -0,0 +1,132 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __COGL_XLIB_H__ +#define __COGL_XLIB_H__ + +#include + +/* NB: this is a top-level header that can be included directly but we + * want to be careful not to define __COGL_H_INSIDE__ when this is + * included internally while building Cogl itself since + * __COGL_H_INSIDE__ is used in headers to guard public vs private api + * definitions + */ +#ifndef COGL_COMPILATION + +/* Note: When building Cogl .gir we explicitly define + * __COGL_XLIB_H_INSIDE__ */ +#ifndef __COGL_XLIB_H_INSIDE__ +#define __COGL_XLIB_H_INSIDE__ +#endif + +/* Note: When building Cogl .gir we explicitly define + * __COGL_H_INSIDE__ */ +#ifndef __COGL_H_INSIDE__ +#define __COGL_H_INSIDE__ +#define __COGL_XLIB_H_MUST_UNDEF_COGL_H_INSIDE__ +#endif + +#endif /* COGL_COMPILATION */ + +#include +#include +#include +#include + +COGL_BEGIN_DECLS + +/* + * cogl_xlib_get_display: + * + * Return value: the Xlib display that will be used by the Xlib winsys + * backend. The display needs to be set with _cogl_xlib_set_display() + * before this function is called. + * + * Stability: Unstable + * Deprecated: 1.16: Use cogl_xlib_renderer_get_display() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_xlib_renderer_get_display) +Display * +cogl_xlib_get_display (void); + +/* + * cogl_xlib_set_display: + * + * Sets the Xlib display that Cogl will use for the Xlib winsys + * backend. This function should eventually go away when Cogl gains a + * more complete winsys abstraction. + * + * Stability: Unstable + * Deprecated: 1.16: Use cogl_xlib_renderer_set_foreign_display() + * instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_xlib_renderer_set_foreign_display) +void +cogl_xlib_set_display (Display *display); + +/* + * cogl_xlib_handle_event: + * @xevent: pointer to XEvent structure + * + * This function processes a single X event; it can be used to hook + * into external X event retrieval (for example that done by Clutter + * or GDK). + * + * Return value: #CoglXlibFilterReturn. %COGL_XLIB_FILTER_REMOVE + * indicates that Cogl has internally handled the event and the + * caller should do no further processing. %COGL_XLIB_FILTER_CONTINUE + * indicates that Cogl is either not interested in the event, + * or has used the event to update internal state without taking + * any exclusive action. + * + * Stability: Unstable + * Deprecated: 1.16: Use cogl_xlib_renderer_handle_event() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_xlib_renderer_handle_event) +CoglFilterReturn +cogl_xlib_handle_event (XEvent *xevent); + +COGL_END_DECLS + + +/* The gobject introspection scanner seems to parse public headers in + * isolation which means we need to be extra careful about how we + * define and undefine __COGL_H_INSIDE__ used to detect when internal + * headers are incorrectly included by developers. In the gobject + * introspection case we have to manually define __COGL_H_INSIDE__ as + * a commandline argument for the scanner which means we must be + * careful not to undefine it in a header... + */ +#ifdef __COGL_XLIB_H_MUST_UNDEF_COGL_H_INSIDE__ +#undef __COGL_H_INSIDE__ +#undef __COGL_XLIB_H_INSIDE__ +#undef __COGL_XLIB_H_MUST_UNDEF_COGL_H_INSIDE__ +#endif + +#endif /* __COGL_XLIB_H__ */ diff --git a/cogl/cogl/cogl.c b/cogl/cogl/cogl.c new file mode 100644 index 0000000..a9ca3fe --- /dev/null +++ b/cogl/cogl/cogl.c @@ -0,0 +1,820 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#include "cogl-config.h" + +#include +#include +#include + +#define COGL_VERSION_MIN_REQUIRED COGL_VERSION_1_4 + +#include "cogl-i18n-private.h" +#include "cogl-debug.h" +#include "cogl-util.h" +#include "cogl-context-private.h" +#include "cogl-pipeline-private.h" +#include "cogl-pipeline-opengl-private.h" +#include "cogl-winsys-private.h" +#include "cogl-framebuffer-private.h" +#include "cogl-matrix-private.h" +#include "cogl-journal-private.h" +#include "cogl-bitmap-private.h" +#include "cogl-texture-private.h" +#include "cogl-texture-driver.h" +#include "cogl-attribute-private.h" +#include "cogl-framebuffer-private.h" +#include "cogl-renderer-private.h" +#include "cogl-config-private.h" +#include "cogl-private.h" +#include "cogl1-context.h" +#include "cogl-offscreen.h" +#include "cogl-attribute-gl-private.h" +#include "cogl-clutter.h" + +#include "deprecated/cogl-framebuffer-deprecated.h" + +CoglFuncPtr +cogl_get_proc_address (const char* name) +{ + _COGL_GET_CONTEXT (ctx, NULL); + + return _cogl_renderer_get_proc_address (ctx->display->renderer, name, FALSE); +} + +CoglBool +_cogl_check_extension (const char *name, char * const *ext) +{ + while (*ext) + if (!strcmp (name, *ext)) + return TRUE; + else + ext++; + + return FALSE; +} + +/* XXX: This has been deprecated as public API */ +CoglBool +cogl_check_extension (const char *name, const char *ext) +{ + return cogl_clutter_check_extension (name, ext); +} + +/* XXX: it's expected that we'll deprecated this with + * cogl_framebuffer_clear at some point. */ +void +cogl_clear (const CoglColor *color, unsigned long buffers) +{ + cogl_framebuffer_clear (cogl_get_draw_framebuffer (), buffers, color); +} + +/* XXX: This API has been deprecated */ +void +cogl_set_depth_test_enabled (CoglBool setting) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (ctx->legacy_depth_test_enabled == setting) + return; + + ctx->legacy_depth_test_enabled = setting; + if (ctx->legacy_depth_test_enabled) + ctx->legacy_state_set++; + else + ctx->legacy_state_set--; +} + +/* XXX: This API has been deprecated */ +CoglBool +cogl_get_depth_test_enabled (void) +{ + _COGL_GET_CONTEXT (ctx, FALSE); + return ctx->legacy_depth_test_enabled; +} + +void +cogl_set_backface_culling_enabled (CoglBool setting) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (ctx->legacy_backface_culling_enabled == setting) + return; + + ctx->legacy_backface_culling_enabled = setting; + + if (ctx->legacy_backface_culling_enabled) + ctx->legacy_state_set++; + else + ctx->legacy_state_set--; +} + +CoglBool +cogl_get_backface_culling_enabled (void) +{ + _COGL_GET_CONTEXT (ctx, FALSE); + + return ctx->legacy_backface_culling_enabled; +} + +void +cogl_set_source_color (const CoglColor *color) +{ + CoglPipeline *pipeline; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (cogl_color_get_alpha_byte (color) == 0xff) + { + cogl_pipeline_set_color (ctx->opaque_color_pipeline, color); + pipeline = ctx->opaque_color_pipeline; + } + else + { + CoglColor premultiplied = *color; + cogl_color_premultiply (&premultiplied); + cogl_pipeline_set_color (ctx->blended_color_pipeline, &premultiplied); + pipeline = ctx->blended_color_pipeline; + } + + cogl_set_source (pipeline); +} + +void +cogl_set_viewport (int x, + int y, + int width, + int height) +{ + CoglFramebuffer *framebuffer; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + framebuffer = cogl_get_draw_framebuffer (); + + cogl_framebuffer_set_viewport (framebuffer, + x, + y, + width, + height); +} + +/* XXX: This should be deprecated, and we should expose a way to also + * specify an x and y viewport offset */ +void +cogl_viewport (unsigned int width, + unsigned int height) +{ + cogl_set_viewport (0, 0, width, height); +} + +CoglFeatureFlags +cogl_get_features (void) +{ + _COGL_GET_CONTEXT (ctx, 0); + + return ctx->feature_flags; +} + +CoglBool +cogl_features_available (CoglFeatureFlags features) +{ + _COGL_GET_CONTEXT (ctx, 0); + + return (ctx->feature_flags & features) == features; +} + +CoglBool +cogl_has_feature (CoglContext *ctx, CoglFeatureID feature) +{ + return COGL_FLAGS_GET (ctx->features, feature); +} + +CoglBool +cogl_has_features (CoglContext *ctx, ...) +{ + va_list args; + CoglFeatureID feature; + + va_start (args, ctx); + while ((feature = va_arg (args, CoglFeatureID))) + if (!cogl_has_feature (ctx, feature)) + return FALSE; + va_end (args); + + return TRUE; +} + +void +cogl_foreach_feature (CoglContext *ctx, + CoglFeatureCallback callback, + void *user_data) +{ + int i; + for (i = 0; i < _COGL_N_FEATURE_IDS; i++) + if (COGL_FLAGS_GET (ctx->features, i)) + callback (i, user_data); +} + +/* XXX: This function should either be replaced with one returning + * integers, or removed/deprecated and make the + * _cogl_framebuffer_get_viewport* functions public. + */ +void +cogl_get_viewport (float viewport[4]) +{ + CoglFramebuffer *framebuffer; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + framebuffer = cogl_get_draw_framebuffer (); + cogl_framebuffer_get_viewport4fv (framebuffer, viewport); +} + +void +cogl_get_bitmasks (int *red, + int *green, + int *blue, + int *alpha) +{ + CoglFramebuffer *framebuffer; + + framebuffer = cogl_get_draw_framebuffer (); + + if (red) + *red = cogl_framebuffer_get_red_bits (framebuffer); + + if (green) + *green = cogl_framebuffer_get_green_bits (framebuffer); + + if (blue) + *blue = cogl_framebuffer_get_blue_bits (framebuffer); + + if (alpha) + *alpha = cogl_framebuffer_get_alpha_bits (framebuffer); +} + +void +cogl_set_fog (const CoglColor *fog_color, + CoglFogMode mode, + float density, + float z_near, + float z_far) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (ctx->legacy_fog_state.enabled == FALSE) + ctx->legacy_state_set++; + + ctx->legacy_fog_state.enabled = TRUE; + ctx->legacy_fog_state.color = *fog_color; + ctx->legacy_fog_state.mode = mode; + ctx->legacy_fog_state.density = density; + ctx->legacy_fog_state.z_near = z_near; + ctx->legacy_fog_state.z_far = z_far; +} + +void +cogl_disable_fog (void) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (ctx->legacy_fog_state.enabled == TRUE) + ctx->legacy_state_set--; + + ctx->legacy_fog_state.enabled = FALSE; +} + +void +cogl_flush (void) +{ + GList *l; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + for (l = ctx->framebuffers; l; l = l->next) + _cogl_framebuffer_flush_journal (l->data); +} + +void +cogl_read_pixels (int x, + int y, + int width, + int height, + CoglReadPixelsFlags source, + CoglPixelFormat format, + uint8_t *pixels) +{ + int bpp = _cogl_pixel_format_get_bytes_per_pixel (format); + CoglBitmap *bitmap; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + bitmap = cogl_bitmap_new_for_data (ctx, + width, height, + format, + bpp * width, /* rowstride */ + pixels); + cogl_framebuffer_read_pixels_into_bitmap (_cogl_get_read_framebuffer (), + x, y, + source, + bitmap); + cogl_object_unref (bitmap); +} + +void +cogl_begin_gl (void) +{ + CoglPipeline *pipeline; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (ctx->in_begin_gl_block) + { + static CoglBool shown = FALSE; + if (!shown) + g_warning ("You should not nest cogl_begin_gl/cogl_end_gl blocks"); + shown = TRUE; + return; + } + ctx->in_begin_gl_block = TRUE; + + /* Flush all batched primitives */ + cogl_flush (); + + /* Flush framebuffer state, including clip state, modelview and + * projection matrix state + * + * NB: _cogl_framebuffer_flush_state may disrupt various state (such + * as the pipeline state) when flushing the clip stack, so should + * always be done first when preparing to draw. */ + _cogl_framebuffer_flush_state (cogl_get_draw_framebuffer (), + _cogl_get_read_framebuffer (), + COGL_FRAMEBUFFER_STATE_ALL); + + /* Setup the state for the current pipeline */ + + /* We considered flushing a specific, minimal pipeline here to try and + * simplify the GL state, but decided to avoid special cases and second + * guessing what would be actually helpful. + * + * A user should instead call cogl_set_source_color4ub() before + * cogl_begin_gl() to simplify the state flushed. + * + * XXX: note defining n_tex_coord_attribs using + * cogl_pipeline_get_n_layers is a hack, but the problem is that + * n_tex_coord_attribs is usually defined when drawing a primitive + * which isn't happening here. + * + * Maybe it would be more useful if this code did flush the + * opaque_color_pipeline and then call into cogl-pipeline-opengl.c to then + * restore all state for the material's backend back to default OpenGL + * values. + */ + pipeline = cogl_get_source (); + _cogl_pipeline_flush_gl_state (ctx, + pipeline, + cogl_get_draw_framebuffer (), + FALSE, + FALSE); + + /* Disable any cached vertex arrays */ + _cogl_gl_disable_all_attributes (ctx); +} + +void +cogl_end_gl (void) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (!ctx->in_begin_gl_block) + { + static CoglBool shown = FALSE; + if (!shown) + g_warning ("cogl_end_gl is being called before cogl_begin_gl"); + shown = TRUE; + return; + } + ctx->in_begin_gl_block = FALSE; +} + +void +cogl_push_matrix (void) +{ + cogl_framebuffer_push_matrix (cogl_get_draw_framebuffer ()); +} + +void +cogl_pop_matrix (void) +{ + cogl_framebuffer_pop_matrix (cogl_get_draw_framebuffer ()); +} + +void +cogl_scale (float x, float y, float z) +{ + cogl_framebuffer_scale (cogl_get_draw_framebuffer (), x, y, z); +} + +void +cogl_translate (float x, float y, float z) +{ + cogl_framebuffer_translate (cogl_get_draw_framebuffer (), x, y, z); +} + +void +cogl_rotate (float angle, float x, float y, float z) +{ + cogl_framebuffer_rotate (cogl_get_draw_framebuffer (), angle, x, y, z); +} + +void +cogl_transform (const CoglMatrix *matrix) +{ + cogl_framebuffer_transform (cogl_get_draw_framebuffer (), matrix); +} + +void +cogl_perspective (float fov_y, + float aspect, + float z_near, + float z_far) +{ + cogl_framebuffer_perspective (cogl_get_draw_framebuffer (), + fov_y, aspect, z_near, z_far); +} + +void +cogl_frustum (float left, + float right, + float bottom, + float top, + float z_near, + float z_far) +{ + cogl_framebuffer_frustum (cogl_get_draw_framebuffer (), + left, right, bottom, top, z_near, z_far); +} + +void +cogl_ortho (float left, + float right, + float bottom, + float top, + float near, + float far) +{ + cogl_framebuffer_orthographic (cogl_get_draw_framebuffer (), + left, top, right, bottom, near, far); +} + +void +cogl_get_modelview_matrix (CoglMatrix *matrix) +{ + cogl_framebuffer_get_modelview_matrix (cogl_get_draw_framebuffer (), matrix); +} + +void +cogl_set_modelview_matrix (CoglMatrix *matrix) +{ + cogl_framebuffer_set_modelview_matrix (cogl_get_draw_framebuffer (), matrix); +} + +void +cogl_get_projection_matrix (CoglMatrix *matrix) +{ + cogl_framebuffer_get_projection_matrix (cogl_get_draw_framebuffer (), matrix); +} + +void +cogl_set_projection_matrix (CoglMatrix *matrix) +{ + cogl_framebuffer_set_projection_matrix (cogl_get_draw_framebuffer (), matrix); +} + +uint32_t +_cogl_driver_error_quark (void) +{ + return g_quark_from_static_string ("cogl-driver-error-quark"); +} + +typedef struct _CoglSourceState +{ + CoglPipeline *pipeline; + int push_count; + /* If this is TRUE then the pipeline will be copied and the legacy + state will be applied whenever the pipeline is used. This is + necessary because some internal Cogl code expects to be able to + push a temporary pipeline to put GL into a known state. For that + to work it also needs to prevent applying the legacy state */ + CoglBool enable_legacy; +} CoglSourceState; + +static void +_push_source_real (CoglPipeline *pipeline, CoglBool enable_legacy) +{ + CoglSourceState *top = g_slice_new (CoglSourceState); + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + top->pipeline = cogl_object_ref (pipeline); + top->enable_legacy = enable_legacy; + top->push_count = 1; + + ctx->source_stack = g_list_prepend (ctx->source_stack, top); +} + +/* FIXME: This should take a context pointer for Cogl 2.0 Technically + * we could make it so we can retrieve a context reference from the + * pipeline, but this would not by symmetric with cogl_pop_source. */ +void +cogl_push_source (void *material_or_pipeline) +{ + CoglPipeline *pipeline = COGL_PIPELINE (material_or_pipeline); + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + _cogl_push_source (pipeline, TRUE); +} + +/* This internal version of cogl_push_source is the same except it + never applies the legacy state. Some parts of Cogl use this + internally to set a temporary pipeline with a known state */ +void +_cogl_push_source (CoglPipeline *pipeline, CoglBool enable_legacy) +{ + CoglSourceState *top; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + if (ctx->source_stack) + { + top = ctx->source_stack->data; + if (top->pipeline == pipeline && top->enable_legacy == enable_legacy) + { + top->push_count++; + return; + } + else + _push_source_real (pipeline, enable_legacy); + } + else + _push_source_real (pipeline, enable_legacy); +} + +/* FIXME: This needs to take a context pointer for Cogl 2.0 */ +void +cogl_pop_source (void) +{ + CoglSourceState *top; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + _COGL_RETURN_IF_FAIL (ctx->source_stack); + + top = ctx->source_stack->data; + top->push_count--; + if (top->push_count == 0) + { + cogl_object_unref (top->pipeline); + g_slice_free (CoglSourceState, top); + ctx->source_stack = g_list_delete_link (ctx->source_stack, + ctx->source_stack); + } +} + +/* FIXME: This needs to take a context pointer for Cogl 2.0 */ +void * +cogl_get_source (void) +{ + CoglSourceState *top; + + _COGL_GET_CONTEXT (ctx, NULL); + + _COGL_RETURN_VAL_IF_FAIL (ctx->source_stack, NULL); + + top = ctx->source_stack->data; + return top->pipeline; +} + +CoglBool +_cogl_get_enable_legacy_state (void) +{ + CoglSourceState *top; + + _COGL_GET_CONTEXT (ctx, FALSE); + + _COGL_RETURN_VAL_IF_FAIL (ctx->source_stack, FALSE); + + top = ctx->source_stack->data; + return top->enable_legacy; +} + +void +cogl_set_source (void *material_or_pipeline) +{ + CoglSourceState *top; + CoglPipeline *pipeline = COGL_PIPELINE (material_or_pipeline); + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + _COGL_RETURN_IF_FAIL (ctx->source_stack); + + top = ctx->source_stack->data; + if (top->pipeline == pipeline && top->enable_legacy) + return; + + if (top->push_count == 1) + { + /* NB: top->pipeline may be only thing keeping pipeline + * alive currently so ref pipeline first... */ + cogl_object_ref (pipeline); + cogl_object_unref (top->pipeline); + top->pipeline = pipeline; + top->enable_legacy = TRUE; + } + else + { + top->push_count--; + cogl_push_source (pipeline); + } +} + +void +cogl_set_source_texture (CoglTexture *texture) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + _COGL_RETURN_IF_FAIL (texture != NULL); + + cogl_pipeline_set_layer_texture (ctx->texture_pipeline, 0, texture); + cogl_set_source (ctx->texture_pipeline); +} + +void +cogl_set_source_color4ub (uint8_t red, + uint8_t green, + uint8_t blue, + uint8_t alpha) +{ + CoglColor c = { 0, }; + + cogl_color_init_from_4ub (&c, red, green, blue, alpha); + cogl_set_source_color (&c); +} + +void +cogl_set_source_color4f (float red, + float green, + float blue, + float alpha) +{ + CoglColor c = { 0, }; + + cogl_color_init_from_4f (&c, red, green, blue, alpha); + cogl_set_source_color (&c); +} + +/* Scale from OpenGL normalized device coordinates (ranging from -1 to 1) + * to Cogl window/framebuffer coordinates (ranging from 0 to buffer-size) with + * (0,0) being top left. */ +#define VIEWPORT_TRANSFORM_X(x, vp_origin_x, vp_width) \ + ( ( ((x) + 1.0) * ((vp_width) / 2.0) ) + (vp_origin_x) ) +/* Note: for Y we first flip all coordinates around the X axis while in + * normalized device coodinates */ +#define VIEWPORT_TRANSFORM_Y(y, vp_origin_y, vp_height) \ + ( ( ((-(y)) + 1.0) * ((vp_height) / 2.0) ) + (vp_origin_y) ) + +/* Transform a homogeneous vertex position from model space to Cogl + * window coordinates (with 0,0 being top left) */ +void +_cogl_transform_point (const CoglMatrix *matrix_mv, + const CoglMatrix *matrix_p, + const float *viewport, + float *x, + float *y) +{ + float z = 0; + float w = 1; + + /* Apply the modelview matrix transform */ + cogl_matrix_transform_point (matrix_mv, x, y, &z, &w); + + /* Apply the projection matrix transform */ + cogl_matrix_transform_point (matrix_p, x, y, &z, &w); + + /* Perform perspective division */ + *x /= w; + *y /= w; + + /* Apply viewport transform */ + *x = VIEWPORT_TRANSFORM_X (*x, viewport[0], viewport[2]); + *y = VIEWPORT_TRANSFORM_Y (*y, viewport[1], viewport[3]); +} + +#undef VIEWPORT_TRANSFORM_X +#undef VIEWPORT_TRANSFORM_Y + +uint32_t +_cogl_system_error_quark (void) +{ + return g_quark_from_static_string ("cogl-system-error-quark"); +} + +void +_cogl_init (void) +{ + static CoglBool initialized = FALSE; + + if (initialized == FALSE) + { +#if !GLIB_CHECK_VERSION (2, 36, 0) + g_type_init (); +#endif + + _cogl_config_read (); + _cogl_debug_check_environment (); + initialized = TRUE; + } +} + +/* + * Returns the number of bytes-per-pixel of a given format. The bpp + * can be extracted from the least significant nibble of the pixel + * format (see CoglPixelFormat). + * + * The mapping is the following (see discussion on bug #660188): + * + * 0 = undefined + * 1, 8 = 1 bpp (e.g. A_8, G_8) + * 2 = 3 bpp, aligned (e.g. 888) + * 3 = 4 bpp, aligned (e.g. 8888) + * 4-6 = 2 bpp, not aligned (e.g. 565, 4444, 5551) + * 7 = undefined yuv + * 9 = 2 bpp, aligned + * 10 = undefined + * 11 = undefined + * 12 = 3 bpp, not aligned + * 13 = 4 bpp, not aligned (e.g. 2101010) + * 14-15 = undefined + */ +int +_cogl_pixel_format_get_bytes_per_pixel (CoglPixelFormat format) +{ + int bpp_lut[] = { 0, 1, 3, 4, + 2, 2, 2, 0, + 1, 2, 0, 0, + 3, 4, 0, 0 }; + + return bpp_lut [format & 0xf]; +} + +/* Note: this also refers to the mapping defined above for + * _cogl_pixel_format_get_bytes_per_pixel() */ +CoglBool +_cogl_pixel_format_is_endian_dependant (CoglPixelFormat format) +{ + int aligned_lut[] = { -1, 1, 1, 1, + 0, 0, 0, -1, + 1, 1, -1, -1, + 0, 0, -1, -1}; + int aligned = aligned_lut[format & 0xf]; + + _COGL_RETURN_VAL_IF_FAIL (aligned != -1, FALSE); + + /* NB: currently checking whether the format components are aligned + * or not determines whether the format is endian dependent or not. + * In the future though we might consider adding formats with + * aligned components that are also endian independant. */ + + return aligned; +} diff --git a/cogl/cogl/cogl.h b/cogl/cogl/cogl.h new file mode 100644 index 0000000..5210e3c --- /dev/null +++ b/cogl/cogl/cogl.h @@ -0,0 +1,177 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_H__ +#define __COGL_H__ + +#ifdef COGL_COMPILATION +#error " shouldn't be included internally" +#endif + +/* Note: When building Cogl .gir we explicitly define + * __COGL_H_INSIDE__ */ +#ifndef __COGL_H_INSIDE__ +#define __COGL_H_INSIDE__ +#define __COGL_MUST_UNDEF_COGL_H_INSIDE__ +#endif + +/* We currently keep gtype integration delimited in case we eventually + * want to split it out into a separate utility library when Cogl + * becomes a standalone project. (like cairo-gobject.so) + */ +#define _COGL_SUPPORTS_GTYPE_INTEGRATION + +/* + * API common to the 1.x and 2.0 api... + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * 1.x only api... + */ +#if 0 +#ifndef COGL_ENABLE_EXPERIMENTAL_2_0_API +#warning +#endif +#endif + +/* It would be good to move these casts up into 1.x only api if we can + * update Clutter, Mutter and GnomeShell to avoid redundant casts when + * they enable the experimental api... */ +#include + +#include +#include +#include +#include +#include + +#ifdef COGL_ENABLE_MUTTER_API +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* XXX: This will definitly go away once all the Clutter winsys + * code has been migrated down into Cogl! */ +#include + +/* + * API deprecations + */ +#include + +/* + * Cogl Path api compatability + * + * The cogl_path_ api used to be part of the core Cogl api so for + * compatability we include cogl-path.h via cogl.h + * + * Note: we have to make sure not to include cogl-path.h while + * building core cogl or generating the Cogl .gir data because + * cogl-path now gets built after cogl and some cogl-path headers are + * only generated at build time... + */ +#if defined (COGL_HAS_COGL_PATH_SUPPORT) && \ + !defined (COGL_COMPILATION) && \ + !defined (COGL_GIR_SCANNING) +#include +#endif + +/** + * SECTION:cogl + * @short_description: General purpose API + * + * General utility functions for COGL. + */ + +/* The gobject introspection scanner seems to parse public headers in + * isolation which means we need to be extra careful about how we + * define and undefine __COGL_H_INSIDE__ used to detect when internal + * headers are incorrectly included by developers. In the gobject + * introspection case we have to manually define __COGL_H_INSIDE__ as + * a commandline argument for the scanner which means we must be + * careful not to undefine it in a header... + */ +#ifdef __COGL_MUST_UNDEF_COGL_H_INSIDE__ +#undef __COGL_H_INSIDE__ +#undef __COGL_MUST_UNDEF_COGL_H_INSIDE__ +#endif + +#endif /* __COGL_H__ */ diff --git a/cogl/cogl/cogl.symbols b/cogl/cogl/cogl.symbols new file mode 100644 index 0000000..c1cd50e --- /dev/null +++ b/cogl/cogl/cogl.symbols @@ -0,0 +1,1087 @@ + + +#ifdef COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT +cogl_android_set_native_window +#endif + +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_atlas_texture_get_gtype +#endif +cogl_atlas_texture_new_with_size +cogl_atlas_texture_new_from_file +cogl_atlas_texture_new_from_data +cogl_atlas_texture_new_from_bitmap + +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_attribute_buffer_get_gtype +#endif +cogl_attribute_buffer_new_with_size + +cogl_attribute_buffer_new +cogl_attribute_get_buffer +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_attribute_get_gtype +#endif +cogl_attribute_get_normalized +cogl_attribute_new +cogl_attribute_new_const_1f +cogl_attribute_new_const_2f +cogl_attribute_new_const_2fv +cogl_attribute_new_const_2x2fv +cogl_attribute_new_const_3f +cogl_attribute_new_const_3fv +cogl_attribute_new_const_3x3fv +cogl_attribute_new_const_4f +cogl_attribute_new_const_4fv +cogl_attribute_new_const_4x4fv +cogl_attribute_set_buffer +cogl_attribute_set_normalized +cogl_attribute_type_get_type + +cogl_begin_gl + +cogl_bitmap_error_get_type +cogl_bitmap_get_buffer +cogl_bitmap_get_format +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_bitmap_get_gtype +#endif +cogl_bitmap_get_height +cogl_bitmap_get_rowstride +cogl_bitmap_get_size_from_file +cogl_bitmap_get_width +cogl_bitmap_new_for_data +cogl_bitmap_new_from_file +cogl_bitmap_new_from_buffer +cogl_bitmap_new_with_size +cogl_blend_string_error_get_type + +cogl_buffer_bit_get_type +cogl_buffer_get_size +cogl_buffer_get_update_hint +#if 0 +/* not implemented! */ +cogl_buffer_get_usage_hint +#endif +cogl_buffer_map +cogl_buffer_map_range +cogl_buffer_set_data +cogl_buffer_set_update_hint +#if 0 +/* not implemented! */ +cogl_buffer_set_usage_hint +#endif +cogl_buffer_target_get_type +cogl_buffer_unmap + +#ifndef COGL_DISABLE_DEPRECATED +cogl_check_extension +#endif + +cogl_clear + +#ifndef COGL_DISABLE_DEPRECATED +cogl_clip_ensure +#endif + +cogl_clip_pop + +#ifndef COGL_DISABLE_DEPRECATED +cogl_clip_push +#endif + +cogl_clip_push_rectangle + +cogl_clip_push_window_rect + +cogl_clip_push_primitive + +#ifndef COGL_DISABLE_DEPRECATED +cogl_clip_push_window_rectangle +cogl_clip_stack_restore +cogl_clip_stack_save +#endif + +#ifndef COGL_WINSYS_INTEGRATED +cogl_clutter_check_extension_CLUTTER +cogl_clutter_winsys_has_feature_CLUTTER +#ifdef COGL_HAS_XLIB +cogl_clutter_winsys_xlib_get_visual_info_CLUTTER +#endif +#endif + +cogl_color_copy +cogl_color_equal +cogl_color_free +cogl_color_get_alpha +cogl_color_get_alpha_byte +cogl_color_get_alpha_float +cogl_color_get_blue +cogl_color_get_blue_byte +cogl_color_get_blue_float +cogl_color_get_green +cogl_color_get_green_byte +cogl_color_get_green_float +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_color_get_gtype +#endif +cogl_color_get_red +cogl_color_get_red_byte +cogl_color_get_red_float +cogl_color_init_from_hsl +cogl_color_init_from_4f +cogl_color_init_from_4fv +cogl_color_init_from_4ub +cogl_color_mask_get_type +cogl_color_new +cogl_color_premultiply +cogl_color_set_alpha +cogl_color_set_alpha_byte +cogl_color_set_alpha_float +cogl_color_set_blue +cogl_color_set_blue_byte +cogl_color_set_blue_float +cogl_color_set_from_4f +cogl_color_set_from_4ub +cogl_color_set_green +cogl_color_set_green_byte +cogl_color_set_green_float +cogl_color_set_red +cogl_color_set_red_byte +cogl_color_set_red_float +cogl_color_to_hsl +cogl_color_unpremultiply + + +#ifdef COGL_HAS_EGL_SUPPORT +cogl_egl_context_get_egl_display +cogl_egl_context_get_egl_context +#endif + +#ifdef COGL_HAS_GLX_SUPPORT +cogl_glx_context_get_glx_context +#endif + +cogl_context_get_display +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_context_get_gtype +#endif +cogl_context_get_renderer +cogl_context_new + +cogl_create_program +cogl_create_shader + +cogl_debug_matrix_entry_print +cogl_debug_matrix_print +cogl_debug_object_foreach_type +cogl_debug_object_print_instances +cogl_depth_state_get_range +cogl_depth_state_get_test_enabled +cogl_depth_state_get_test_function +cogl_depth_state_get_write_enabled +cogl_depth_state_init +cogl_depth_state_set_test_enabled +cogl_depth_state_set_test_function +cogl_depth_state_set_range +cogl_depth_state_set_write_enabled +cogl_depth_test_function_get_type + +cogl_disable_fog + +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_display_get_gtype +#endif +cogl_display_get_renderer +cogl_display_new +cogl_display_setup +cogl_display_set_onscreen_template + +cogl_double_to_fixed + +cogl_end_gl + +cogl_error_copy +cogl_error_free +cogl_error_matches + +cogl_euler_copy +cogl_euler_equal +cogl_euler_free +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_euler_get_gtype +#endif +cogl_euler_init +cogl_euler_init_from_matrix +#if 0 +/* not yet implemented */ +cogl_euler_init_from_quaternion +#endif + +cogl_features_available +cogl_feature_flags_get_type +cogl_fence_closure_get_user_data +cogl_fixed_atan +cogl_fixed_atan2 +cogl_fixed_cos +cogl_fixed_get_type +cogl_fixed_log2 +cogl_fixed_pow +cogl_fixed_pow2 +cogl_fixed_sin +cogl_fixed_sqrt +cogl_fixed_tan + +cogl_fog_mode_get_type + +cogl_foreach_feature + +cogl_flush + +cogl_framebuffer_add_fence_callback +cogl_framebuffer_allocate +cogl_framebuffer_cancel_fence_callback +cogl_framebuffer_clear4f +cogl_framebuffer_clear +cogl_framebuffer_discard_buffers +cogl_framebuffer_draw_primitive +cogl_framebuffer_draw_rectangle +cogl_framebuffer_draw_rectangles +cogl_framebuffer_draw_textured_rectangle +cogl_framebuffer_draw_textured_rectangles +cogl_framebuffer_finish +cogl_framebuffer_frustum +cogl_framebuffer_get_alpha_bits +cogl_framebuffer_get_blue_bits +cogl_framebuffer_get_color_format +cogl_framebuffer_get_color_mask +cogl_framebuffer_get_context +cogl_framebuffer_get_depth_bits +cogl_framebuffer_get_depth_texture +cogl_framebuffer_get_depth_texture_enabled +cogl_framebuffer_get_depth_write_enabled +cogl_framebuffer_get_dither_enabled +cogl_framebuffer_get_green_bits +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_framebuffer_get_gtype +#endif +cogl_framebuffer_get_height +cogl_framebuffer_get_modelview_matrix +cogl_framebuffer_get_projection_matrix +cogl_framebuffer_get_red_bits +cogl_framebuffer_get_samples_per_pixel +cogl_framebuffer_get_viewport4fv +cogl_framebuffer_get_viewport_height +cogl_framebuffer_get_viewport_width +cogl_framebuffer_get_viewport_x +cogl_framebuffer_get_viewport_y +cogl_framebuffer_get_width +cogl_framebuffer_identity_matrix +cogl_framebuffer_orthographic +cogl_framebuffer_perspective +cogl_framebuffer_pop_clip +cogl_framebuffer_pop_matrix +cogl_framebuffer_push_matrix +cogl_framebuffer_push_primitive_clip +cogl_framebuffer_push_rectangle_clip +cogl_framebuffer_push_scissor_clip +cogl_framebuffer_read_pixels +cogl_framebuffer_read_pixels_into_bitmap +cogl_framebuffer_resolve_samples +cogl_framebuffer_resolve_samples_region +cogl_framebuffer_rotate + +#ifdef COGL_ENABLE_EXPERIMENTAL_API +cogl_framebuffer_rotate_euler +cogl_framebuffer_rotate_quaternion +#endif + +cogl_framebuffer_scale +cogl_framebuffer_set_color_mask +cogl_framebuffer_set_depth_texture_enabled +cogl_framebuffer_set_depth_write_enabled +cogl_framebuffer_set_dither_enabled +cogl_framebuffer_set_modelview_matrix +cogl_framebuffer_set_projection_matrix +cogl_framebuffer_set_samples_per_pixel +cogl_framebuffer_set_viewport +cogl_framebuffer_transform +cogl_framebuffer_translate +cogl_framebuffer_vdraw_attributes +/* cogl_framebuffer_vdraw_indexed_attributes */ /* Not Implemented! */ + +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_frame_closure_get_gtype +#endif +cogl_frame_info_get_frame_counter + +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_frame_info_get_gtype +#endif +cogl_frame_info_get_output +cogl_frame_info_get_presentation_time +cogl_frame_info_get_refresh_rate + +cogl_frustum + +cogl_get_backface_culling_enabled +cogl_get_bitmasks +cogl_get_clock_time +cogl_get_depth_test_enabled +cogl_get_draw_framebuffer +cogl_get_features +cogl_get_graphics_reset_status +cogl_get_modelview_matrix +cogl_get_option_group +cogl_get_proc_address +cogl_get_projection_matrix +cogl_get_rectangle_indices +cogl_get_source +cogl_get_static_identity_quaternion +cogl_get_static_zero_quaternion +cogl_get_viewport + +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_gles2_context_get_gtype +#endif +cogl_gles2_context_get_vtable +cogl_gles2_context_new +cogl_gles2_get_current_vtable +cogl_gles2_texture_get_handle +cogl_gles2_texture_2d_new_from_handle + +#ifdef COGL_HAS_GLIB_SUPPORT +cogl_glib_renderer_source_new +cogl_glib_source_new +#endif + +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_gtype_matrix_get_type +#endif + +cogl_handle_get_type +cogl_handle_ref +cogl_handle_unref + +cogl_has_feature +cogl_has_features + +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_index_buffer_get_gtype +#endif +cogl_index_buffer_new +cogl_indices_get_buffer +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_indices_get_gtype +#endif +cogl_indices_get_offset +cogl_indices_get_type +cogl_indices_new +cogl_indices_new_for_buffer +cogl_indices_set_offset +cogl_indices_type_get_type + +cogl_is_atlas_texture +cogl_is_attribute +cogl_is_attribute_buffer +cogl_is_bitmap +cogl_is_buffer +cogl_is_context +cogl_is_frame_info +cogl_is_gles2_context +cogl_is_index_buffer +#if 0 +/* not implemented! */ +cogl_is_indices_array +#endif +cogl_is_material +cogl_is_matrix_stack +cogl_is_offscreen +cogl_is_output +cogl_is_pipeline +cogl_is_pixel_buffer +cogl_is_primitive +cogl_is_primitive_texture +cogl_is_program +cogl_is_renderer +cogl_is_shader +cogl_is_snippet +cogl_is_sub_texture +cogl_is_texture +#ifdef COGL_HAS_X11 +cogl_is_texture_pixmap_x11 +#endif +cogl_is_texture_rectangle +cogl_is_texture_2d +cogl_is_texture_3d + +#ifdef COGL_HAS_EGL_PLATFORM_KMS_SUPPORT +cogl_kms_display_queue_modes_reset +cogl_kms_display_set_layout +cogl_kms_renderer_get_kms_fd +#endif + +cogl_material_alpha_func_get_type +cogl_material_copy +cogl_material_filter_get_type +cogl_material_foreach_layer +cogl_material_get_ambient +cogl_material_get_color +cogl_material_get_depth_state +cogl_material_get_diffuse +cogl_material_get_emission +cogl_material_get_layers +cogl_material_get_layer_point_sprite_coords_enabled +cogl_material_get_layer_wrap_mode_p +cogl_material_get_layer_wrap_mode_s +cogl_material_get_layer_wrap_mode_t +cogl_material_get_n_layers +cogl_material_get_point_size +cogl_material_get_shininess +cogl_material_get_specular +cogl_material_get_user_program +cogl_material_layer_get_mag_filter +cogl_material_layer_get_min_filter +cogl_material_layer_get_texture +cogl_material_layer_get_type +cogl_material_layer_get_wrap_mode_p +cogl_material_layer_get_wrap_mode_s +cogl_material_layer_get_wrap_mode_t +cogl_material_layer_type_get_type +cogl_material_new +cogl_material_remove_layer +#ifndef COGL_DISABLE_DEPRECATED +cogl_material_ref +#endif +cogl_material_set_alpha_test_function +cogl_material_set_ambient +cogl_material_set_ambient_and_diffuse +cogl_material_set_blend +cogl_material_set_blend_constant +cogl_material_set_color +cogl_material_set_color4f +cogl_material_set_color4ub +cogl_material_set_depth_state +cogl_material_set_diffuse +cogl_material_set_emission +cogl_material_set_layer +cogl_material_set_layer_combine +cogl_material_set_layer_combine_constant +cogl_material_set_layer_filters +cogl_material_set_layer_matrix +cogl_material_set_layer_point_sprite_coords_enabled +cogl_material_set_layer_wrap_mode +cogl_material_set_layer_wrap_mode_p +cogl_material_set_layer_wrap_mode_s +cogl_material_set_layer_wrap_mode_t +cogl_material_set_point_size +cogl_material_set_shininess +cogl_material_set_specular +cogl_material_set_user_program +#ifndef COGL_DISABLE_DEPRECATED +cogl_material_unref +#endif +cogl_material_wrap_mode_get_type + +cogl_matrix_copy +cogl_matrix_entry_calculate_translation +cogl_matrix_entry_equal +cogl_matrix_entry_get +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_matrix_entry_get_gtype +#endif +cogl_matrix_entry_is_identity +cogl_matrix_entry_ref +cogl_matrix_entry_unref +cogl_matrix_equal +cogl_matrix_free +cogl_matrix_frustum +cogl_matrix_get_array +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_matrix_get_gtype +#endif +cogl_matrix_get_inverse +cogl_matrix_init_from_array +cogl_matrix_init_translation +cogl_matrix_is_identity +cogl_matrix_init_from_euler +cogl_matrix_init_from_quaternion +cogl_matrix_init_identity +cogl_matrix_look_at +cogl_matrix_multiply +#ifndef COGL_DISABLE_DEPRECATED +cogl_matrix_ortho +#endif +cogl_matrix_orthographic +cogl_matrix_perspective +cogl_matrix_project_points +cogl_matrix_rotate + +#ifdef COGL_ENABLE_EXPERIMENTAL_API +cogl_matrix_rotate_euler +cogl_matrix_rotate_quaternion +#endif + +cogl_matrix_scale +cogl_matrix_stack_frustum +cogl_matrix_stack_get +cogl_matrix_stack_get_entry +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_matrix_stack_get_gtype +#endif +cogl_matrix_stack_get_inverse +cogl_matrix_stack_load_identity +cogl_matrix_stack_multiply +cogl_matrix_stack_new +cogl_matrix_stack_orthographic +cogl_matrix_stack_perspective +cogl_matrix_stack_pop +cogl_matrix_stack_push +cogl_matrix_stack_rotate +cogl_matrix_stack_rotate_euler +cogl_matrix_stack_rotate_quaternion +cogl_matrix_stack_scale +cogl_matrix_stack_set +cogl_matrix_stack_translate +cogl_matrix_transform_point +cogl_matrix_transform_points +cogl_matrix_translate +cogl_matrix_transpose +cogl_matrix_view_2d_in_frustum +cogl_matrix_view_2d_in_perspective + +cogl_meta_texture_foreach_in_region + +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_object_get_gtype +#endif +cogl_object_get_user_data +cogl_object_ref +cogl_object_set_user_data +cogl_object_unref + +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_offscreen_get_gtype +#endif +cogl_offscreen_new_to_texture +cogl_offscreen_new_with_texture + +cogl_onscreen_add_dirty_callback +cogl_onscreen_add_frame_callback +cogl_onscreen_add_resize_callback +cogl_onscreen_add_swap_buffers_callback +#ifndef COGL_WINSYS_INTEGRATED +cogl_onscreen_clutter_backend_set_size_CLUTTER +#endif +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_onscreen_dirty_closure_get_gtype +#endif +cogl_onscreen_get_buffer_age +cogl_onscreen_get_frame_counter +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_onscreen_get_gtype +#endif +cogl_onscreen_get_resizable +cogl_onscreen_hide +cogl_onscreen_new +cogl_onscreen_set_swap_throttled +cogl_onscreen_remove_dirty_callback +cogl_onscreen_remove_frame_callback +cogl_onscreen_remove_resize_callback +cogl_onscreen_remove_swap_buffers_callback +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_onscreen_resize_closure_get_gtype +#endif +cogl_onscreen_set_resizable +cogl_onscreen_set_swap_throttled +cogl_onscreen_show +cogl_onscreen_swap_buffers +cogl_onscreen_swap_buffers_with_damage +cogl_onscreen_swap_region +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_onscreen_template_get_gtype +#endif +cogl_onscreen_template_new +cogl_onscreen_template_set_samples_per_pixel +cogl_onscreen_template_set_swap_throttled + +cogl_ortho + +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_output_get_gtype +#endif +cogl_output_get_height +cogl_output_get_mm_height +cogl_output_get_mm_width +cogl_output_get_refresh_rate +cogl_output_get_subpixel_order +cogl_output_get_width +cogl_output_get_x +cogl_output_get_y + +cogl_perspective + +cogl_pipeline_add_layer_snippet +cogl_pipeline_add_snippet +cogl_pipeline_copy +cogl_pipeline_foreach_layer +cogl_pipeline_get_alpha_test_function +cogl_pipeline_get_alpha_test_reference +cogl_pipeline_get_ambient +cogl_pipeline_get_color +cogl_pipeline_get_color_mask +cogl_pipeline_get_cull_face_mode +cogl_pipeline_get_depth_state +cogl_pipeline_get_diffuse +cogl_pipeline_get_emission +cogl_pipeline_get_front_face_winding +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_pipeline_get_gtype +#endif +cogl_pipeline_get_layer_mag_filter +cogl_pipeline_get_layer_min_filter +cogl_pipeline_get_layer_point_sprite_coords_enabled +cogl_pipeline_get_layer_texture +cogl_pipeline_get_layer_wrap_mode_p +cogl_pipeline_get_layer_wrap_mode_s +cogl_pipeline_get_layer_wrap_mode_t +cogl_pipeline_get_n_layers +cogl_pipeline_get_per_vertex_point_size +cogl_pipeline_get_point_size +cogl_pipeline_get_shininess +cogl_pipeline_get_specular +cogl_pipeline_get_uniform_location +cogl_pipeline_get_user_program +cogl_pipeline_new +cogl_pipeline_set_alpha_test_function +cogl_pipeline_set_ambient +cogl_pipeline_set_ambient_and_diffuse +cogl_pipeline_set_blend +cogl_pipeline_set_blend_constant +cogl_pipeline_set_color +cogl_pipeline_set_color_mask +cogl_pipeline_set_color4f +cogl_pipeline_set_color4ub +cogl_pipeline_set_cull_face_mode +cogl_pipeline_set_depth_state +cogl_pipeline_set_diffuse +cogl_pipeline_set_emission +cogl_pipeline_set_front_face_winding +cogl_pipeline_set_layer_combine +cogl_pipeline_set_layer_combine_constant +cogl_pipeline_set_layer_filters +cogl_pipeline_set_layer_matrix +cogl_pipeline_set_layer_null_texture +cogl_pipeline_set_layer_point_sprite_coords_enabled +cogl_pipeline_set_layer_texture +cogl_pipeline_set_layer_wrap_mode +cogl_pipeline_set_layer_wrap_mode_p +cogl_pipeline_set_layer_wrap_mode_s +cogl_pipeline_set_layer_wrap_mode_t +cogl_pipeline_set_per_vertex_point_size +cogl_pipeline_set_point_size +cogl_pipeline_remove_layer +cogl_pipeline_set_shininess +cogl_pipeline_set_specular +cogl_pipeline_set_uniform_float +cogl_pipeline_set_uniform_int +cogl_pipeline_set_uniform_matrix +cogl_pipeline_set_uniform_1f +cogl_pipeline_set_uniform_1i +cogl_pipeline_set_user_program + +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_pixel_buffer_get_gtype +#endif +cogl_pixel_buffer_new +#if 0 +/* not exported in the main APIs for now */ +cogl_pixel_buffer_set_region +#endif +cogl_pixel_format_get_type + +cogl_poll_renderer_dispatch +cogl_poll_renderer_get_info + +cogl_polygon + +#ifndef COGL_DISABLE_DEPRECATED +cogl_pop_draw_buffer +#endif +cogl_pop_framebuffer +cogl_pop_gles2_context +cogl_pop_matrix +cogl_pop_source + +cogl_primitive_copy +cogl_primitive_foreach_attribute +cogl_primitive_get_first_vertex +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_primitive_get_gtype +#endif +cogl_primitive_get_indices +cogl_primitive_get_mode +cogl_primitive_get_n_vertices +cogl_primitive_new +cogl_primitive_new_p2 +cogl_primitive_new_p2c4 +cogl_primitive_new_p2t2 +cogl_primitive_new_p2t2c4 +cogl_primitive_new_p3 +cogl_primitive_new_p3c4 +cogl_primitive_new_p3t2 +cogl_primitive_new_p3t2c4 +cogl_primitive_new_with_attributes +cogl_primitive_set_attributes +cogl_primitive_set_first_vertex +cogl_primitive_set_indices +cogl_primitive_set_mode +cogl_primitive_set_n_vertices +cogl_primitive_draw + +cogl_primitive_texture_set_auto_mipmap + +cogl_program_attach_shader +cogl_program_get_uniform_location +cogl_program_link + +#ifndef COGL_DISABLE_DEPRECATED +cogl_program_ref +#endif + +cogl_program_set_uniform_float +cogl_program_set_uniform_int +cogl_program_set_uniform_matrix +cogl_program_set_uniform_1f +cogl_program_set_uniform_1i + +#ifndef COGL_DISABLE_DEPRECATED +cogl_program_uniform_float +cogl_program_uniform_int +cogl_program_uniform_matrix +cogl_program_uniform_1f +cogl_program_uniform_1i +cogl_program_unref +#endif + +cogl_program_use + +#ifndef COGL_DISABLE_DEPRECATED +cogl_push_draw_buffer +#endif + +cogl_push_framebuffer +cogl_push_gles2_context +cogl_push_matrix +cogl_push_source + +cogl_quaternion_copy +cogl_quaternion_dot_product +cogl_quaternion_equal +cogl_quaternion_free +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_quaternion_get_gtype +#endif +cogl_quaternion_get_rotation_angle +cogl_quaternion_get_rotation_axis +cogl_quaternion_init +cogl_quaternion_init_from_angle_vector +cogl_quaternion_init_from_array +cogl_quaternion_init_from_euler +cogl_quaternion_init_from_x_rotation +cogl_quaternion_init_from_y_rotation +cogl_quaternion_init_from_z_rotation +cogl_quaternion_init_identity +cogl_quaternion_invert +cogl_quaternion_multiply +cogl_quaternion_nlerp +cogl_quaternion_normalize +cogl_quaternion_pow +cogl_quaternion_slerp +cogl_quaternion_squad + +cogl_read_pixels +cogl_read_pixels_flags_get_type + +cogl_rectangle +cogl_rectangles +cogl_rectangles_with_texture_coords +cogl_rectangle_with_multitexture_coords +cogl_rectangle_with_texture_coords + +cogl_renderer_add_constraint +cogl_renderer_check_onscreen_template +cogl_renderer_connect +cogl_renderer_foreach_output +cogl_renderer_get_driver +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_renderer_get_gtype +#endif +cogl_renderer_get_n_fragment_texture_units +cogl_renderer_error_get_type +cogl_renderer_get_winsys_id +cogl_renderer_new +cogl_renderer_remove_constraint +cogl_renderer_set_driver +cogl_renderer_set_winsys_id + +cogl_rotate + +cogl_scale + +cogl_set_backface_culling_enabled +cogl_set_depth_test_enabled +#ifndef COGL_DISABLE_DEPRECATED +cogl_set_draw_buffer +#endif +cogl_set_fog +#ifdef COGL_HAS_SDL_SUPPORT +cogl_sdl_context_new +cogl_sdl_handle_event +cogl_sdl_idle +#if SDL_MAJOR_VERSION >= 2 +cogl_sdl_onscreen_get_window +#endif +cogl_sdl_renderer_get_event_type +cogl_sdl_renderer_set_event_type +#endif + +cogl_set_framebuffer +cogl_set_modelview_matrix +cogl_set_projection_matrix +cogl_set_source +cogl_set_source_color +cogl_set_source_color4f +cogl_set_source_color4ub +cogl_set_source_texture +cogl_set_viewport + +cogl_shader_compile +cogl_shader_get_info_log +cogl_shader_get_type +cogl_shader_is_compiled + +#ifndef COGL_DISABLE_DEPRECATED +cogl_shader_ref +#endif + +cogl_shader_source +cogl_shader_type_get_type + +#ifndef COGL_DISABLE_DEPRECATED +cogl_shader_unref +#endif + +cogl_snippet_get_declarations +cogl_snippet_get_hook +cogl_snippet_get_post +cogl_snippet_get_pre +cogl_snippet_get_replace +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_snippet_get_gtype +#endif +cogl_snippet_new +cogl_snippet_set_declarations +cogl_snippet_set_post +cogl_snippet_set_pre +cogl_snippet_set_replace + +cogl_sqrti + +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_sub_texture_get_gtype +#endif +cogl_sub_texture_get_parent +cogl_sub_texture_new + +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_swap_chain_get_gtype +#endif +cogl_swap_chain_new +cogl_swap_chain_set_has_alpha +cogl_swap_chain_set_length + +cogl_system_error_get_type + +cogl_texture_allocate +cogl_texture_components_get_type +cogl_texture_error_get_type +cogl_texture_flags_get_type +cogl_texture_get_components +cogl_texture_get_data +cogl_texture_get_format +cogl_texture_get_gl_texture +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_texture_get_gtype +#endif +cogl_texture_get_height +cogl_texture_get_max_waste +cogl_texture_get_premultiplied +cogl_texture_get_rowstride +cogl_texture_get_width +cogl_texture_is_sliced +cogl_texture_new_from_bitmap +cogl_texture_new_from_data +cogl_texture_new_from_file +cogl_texture_new_from_foreign +cogl_texture_new_from_sub_texture +cogl_texture_new_with_size +#ifdef COGL_HAS_X11 +cogl_texture_pixmap_x11_error_domain +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_texture_pixmap_x11_get_gtype +#endif +cogl_texture_pixmap_x11_is_using_tfp_extension +cogl_texture_pixmap_x11_new +cogl_texture_pixmap_x11_set_damage_object +cogl_texture_pixmap_x11_update_area +#endif +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_texture_rectangle_get_gtype +#endif +cogl_texture_rectangle_new_from_bitmap +cogl_texture_rectangle_new_from_foreign +cogl_texture_rectangle_new_with_size +#ifndef COGL_DISABLE_DEPRECATED +cogl_texture_ref +#endif +cogl_texture_set_components +cogl_texture_set_data +cogl_texture_set_premultiplied +cogl_texture_set_region +cogl_texture_set_region_from_bitmap +cogl_texture_type_get_type +#ifndef COGL_DISABLE_DEPRECATED +cogl_texture_unref +#endif +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_texture_2d_get_gtype +#endif +cogl_texture_2d_new_from_bitmap +cogl_texture_2d_new_from_data +cogl_texture_2d_new_from_file +cogl_texture_2d_new_with_size +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_texture_2d_sliced_get_gtype +#endif +cogl_texture_2d_sliced_new_from_bitmap +cogl_texture_2d_sliced_new_from_data +cogl_texture_2d_sliced_new_from_file +cogl_texture_2d_sliced_new_with_size +#ifdef COGL_HAS_GTYPE_SUPPORT +cogl_texture_3d_get_gtype +#endif +cogl_texture_3d_new_from_bitmap +cogl_texture_3d_new_from_data +cogl_texture_3d_new_with_size + +cogl_transform +cogl_translate + +cogl_vector3_add +cogl_vector3_copy +cogl_vector3_cross_product +cogl_vector3_distance +cogl_vector3_divide_scalar +cogl_vector3_dot_product +cogl_vector3_equal +cogl_vector3_equal_with_epsilon +cogl_vector3_free +cogl_vector3_init +cogl_vector3_init_zero +cogl_vector3_invert +cogl_vector3_magnitude +cogl_vector3_multiply_scalar +cogl_vector3_normalize +cogl_vector3_subtract + +cogl_vertex_buffer_add +cogl_vertex_buffer_delete +cogl_vertex_buffer_disable +cogl_vertex_buffer_draw +cogl_vertex_buffer_draw_elements +cogl_vertex_buffer_enable +cogl_vertex_buffer_get_n_vertices +cogl_vertex_buffer_indices_get_for_quads +cogl_vertex_buffer_indices_get_type +cogl_vertex_buffer_indices_new +cogl_vertex_buffer_new +#ifndef COGL_DISABLE_DEPRECATED +cogl_vertex_buffer_ref +#endif +cogl_vertex_buffer_submit +#ifndef COGL_DISABLE_DEPRECATED +cogl_vertex_buffer_unref +#endif + +cogl_vertices_mode_get_type + +#ifdef COGL_DISABLE_DEPRECATED +cogl_viewport +#endif + +cogl_winsys_feature_get_type + +#ifdef COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT +cogl_wayland_display_set_compositor_display +cogl_wayland_onscreen_resize +cogl_wayland_renderer_get_display +cogl_wayland_renderer_set_event_dispatch_enabled +cogl_wayland_renderer_set_foreign_display +cogl_wayland_texture_set_region_from_shm_buffer +cogl_wayland_texture_2d_new_from_buffer +#endif + +cogl_winding_get_type + +#ifdef COGL_HAS_XLIB +cogl_xlib_get_display +cogl_xlib_handle_event +cogl_xlib_renderer_add_filter +cogl_xlib_renderer_get_display +cogl_xlib_renderer_get_foreign_display +cogl_xlib_renderer_get_visual_info +cogl_xlib_renderer_handle_event +cogl_xlib_renderer_remove_filter +cogl_xlib_renderer_request_reset_on_video_memory_purge +cogl_xlib_renderer_set_event_retrieval_enabled +cogl_xlib_renderer_set_foreign_display +cogl_xlib_set_display +#endif + +#ifdef COGL_HAS_X11 +cogl_x11_onscreen_get_visual_xid +cogl_x11_onscreen_set_foreign_window_xid +#endif + +#ifndef COGL_NO_EXPORT_UNDERSCORE +/* probably these should not be exported at all, but anyways, for now... */ +/* eventually, this section should disappear (or cogl, cogl-pango, clutter et al */ +/* will link without the following) */ +_cogl_atlas_add_reorganize_callback +_cogl_atlas_new +_cogl_atlas_reserve_space +_cogl_atlas_texture_add_reorganize_callback +_cogl_atlas_texture_remove_reorganize_callback +_cogl_buffer_map_for_fill_or_fallback +_cogl_buffer_unmap_for_fill_or_fallback +_cogl_clip_stack_push_rectangle +_cogl_clip_stack_push_primitive +_cogl_context_get_default +_cogl_debug_instances +_cogl_framebuffer_get_modelview_stack +_cogl_framebuffer_get_projection_stack +_cogl_framebuffer_get_stencil_bits +_cogl_object_default_unref +_cogl_pipeline_foreach_layer_internal +_cogl_pipeline_layer_get_texture +_cogl_pipeline_prune_to_n_layers +_cogl_primitive_draw +_cogl_system_error_quark +_cogl_texture_can_hardware_repeat +_cogl_texture_get_format +#endif + +cogl_fence_closure_get_user_data +cogl_framebuffer_add_fence_callback +cogl_framebuffer_cancel_fence_callback diff --git a/cogl/cogl/cogl1-context.h b/cogl/cogl/cogl1-context.h new file mode 100644 index 0000000..0f43c19 --- /dev/null +++ b/cogl/cogl/cogl1-context.h @@ -0,0 +1,862 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Robert Bragg + * + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_1_CONTEXT_H__ +#define __COGL_1_CONTEXT_H__ + +#include +#include +#include +#include + +COGL_BEGIN_DECLS + +/** + * cogl_get_option_group: + * + * Retrieves the #GOptionGroup used by Cogl to parse the command + * line options. Clutter uses this to handle the Cogl command line + * options during its initialization process. + * + * Return value: a #GOptionGroup + * + * Since: 1.0 + * Deprecated: 1.16: Not replaced + */ +COGL_DEPRECATED_IN_1_16 +GOptionGroup * +cogl_get_option_group (void); + +/* Misc */ +/** + * cogl_get_features: + * + * Returns all of the features supported by COGL. + * + * Return value: A logical OR of all the supported COGL features. + * + * Since: 0.8 + * Deprecated: 1.10: Use cogl_foreach_feature() instead + */ +COGL_DEPRECATED_IN_1_10_FOR (cogl_foreach_feature) +CoglFeatureFlags +cogl_get_features (void); + +/** + * cogl_features_available: + * @features: A bitmask of features to check for + * + * Checks whether the given COGL features are available. Multiple + * features can be checked for by or-ing them together with the '|' + * operator. %TRUE is only returned if all of the requested features + * are available. + * + * Return value: %TRUE if the features are available, %FALSE otherwise. + * Deprecated: 1.10: Use cogl_has_feature() instead + */ +COGL_DEPRECATED_IN_1_10_FOR (cogl_has_feature) +CoglBool +cogl_features_available (CoglFeatureFlags features); + +/** + * cogl_get_proc_address: (skip) + * @name: the name of the function. + * + * Gets a pointer to a given GL or GL ES extension function. This acts + * as a wrapper around glXGetProcAddress() or whatever is the + * appropriate function for the current backend. + * + * This function should not be used to query core opengl API + * symbols since eglGetProcAddress for example doesn't allow this and + * and may return a junk pointer if you do. + * + * Return value: a pointer to the requested function or %NULL if the + * function is not available. + */ +CoglFuncPtr +cogl_get_proc_address (const char *name); + +/** + * cogl_check_extension: + * @name: extension to check for + * @ext: list of extensions + * + * Check whether @name occurs in list of extensions in @ext. + * + * Return value: %TRUE if the extension occurs in the list, %FALSE otherwise. + * + * Deprecated: 1.2: OpenGL is an implementation detail for Cogl and so it's + * not appropriate to expose OpenGL extensions through the Cogl API. This + * function can be replaced by the following equivalent code: + * |[ + * CoglBool retval = (strstr (ext, name) != NULL) ? TRUE : FALSE; + * ]| + */ +COGL_DEPRECATED +CoglBool +cogl_check_extension (const char *name, + const char *ext); + +/** + * cogl_get_bitmasks: + * @red: (out): Return location for the number of red bits or %NULL + * @green: (out): Return location for the number of green bits or %NULL + * @blue: (out): Return location for the number of blue bits or %NULL + * @alpha: (out): Return location for the number of alpha bits or %NULL + * + * Gets the number of bitplanes used for each of the color components + * in the color buffer. Pass %NULL for any of the arguments if the + * value is not required. + * + * Deprecated: 1.8: Use cogl_framebuffer_get_red/green/blue/alpha_bits() + * instead + */ +COGL_DEPRECATED_IN_1_8_FOR (cogl_framebuffer_get_red_OR_green_OR_blue_OR_alpha_bits) +void +cogl_get_bitmasks (int *red, + int *green, + int *blue, + int *alpha); + +/** + * cogl_perspective: + * @fovy: Vertical field of view angle in degrees. + * @aspect: The (width over height) aspect ratio for display + * @z_near: The distance to the near clipping plane (Must be positive) + * @z_far: The distance to the far clipping plane (Must be positive) + * + * Replaces the current projection matrix with a perspective matrix + * based on the provided values. + * + * 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. + * + * Deprecated: 1.10: Use cogl_framebuffer_perspective() instead + */ +COGL_DEPRECATED_IN_1_10_FOR (cogl_framebuffer_perspective) +void +cogl_perspective (float fovy, + float aspect, + float z_near, + float z_far); + +/** + * cogl_frustum: + * @left: X position of the left clipping plane where it + * intersects the near clipping plane + * @right: X position of the right clipping plane where it + * intersects the near clipping plane + * @bottom: Y position of the bottom clipping plane where it + * intersects the near clipping plane + * @top: Y position of the top clipping plane where it intersects + * the near clipping plane + * @z_near: The distance to the near clipping plane (Must be positive) + * @z_far: The distance to the far clipping plane (Must be positive) + * + * Replaces the current projection matrix with a perspective matrix + * for a given viewing frustum defined by 4 side clip planes that + * all cross through the origin and 2 near and far clip planes. + * + * Since: 0.8.2 + * Deprecated: 1.10: Use cogl_framebuffer_frustum() instead + */ +COGL_DEPRECATED_IN_1_10_FOR (cogl_framebuffer_frustum) +void +cogl_frustum (float left, + float right, + float bottom, + float top, + float z_near, + float z_far); + +/** + * cogl_ortho: + * @left: The coordinate for the left clipping plane + * @right: The coordinate for the right clipping plane + * @bottom: The coordinate for the bottom clipping plane + * @top: The coordinate for the top clipping plane + * @near: The distance to the near clipping + * plane (negative if the plane is behind the viewer) + * @far: The distance for the far clipping + * plane (negative if the plane is behind the viewer) + * + * Replaces the current projection matrix with an orthographic projection + * matrix. See to see how the matrix is + * calculated. + * + *
+ * + * + *
+ * + * This function copies the arguments from OpenGL's glOrtho() even + * though they are unnecessarily confusing due to the z near and z far + * arguments actually being a "distance" from the origin, where + * negative values are behind the viewer, instead of coordinates for + * the z clipping planes which would have been consistent with the + * left, right bottom and top arguments. + * + * Since: 1.0 + * Deprecated: 1.10: Use cogl_framebuffer_orthographic() instead + */ +COGL_DEPRECATED_IN_1_10_FOR (cogl_framebuffer_orthographic) +void +cogl_ortho (float left, + float right, + float bottom, + float top, + float near, + float far); + +/** + * cogl_viewport: + * @width: Width of the viewport + * @height: Height of the viewport + * + * Replace the current viewport with the given values. + * + * Since: 0.8.2 + * Deprecated: 1.8: Use cogl_framebuffer_set_viewport instead + */ +COGL_DEPRECATED_IN_1_8_FOR (cogl_framebuffer_set_viewport) +void +cogl_viewport (unsigned int width, + unsigned int height); + +/** + * cogl_set_viewport: + * @x: X offset of the viewport + * @y: Y offset of the viewport + * @width: Width of the viewport + * @height: Height of the viewport + * + * Replaces the current viewport with the given values. + * + * Since: 1.2 + * Deprecated: 1.8: Use cogl_framebuffer_set_viewport() instead + */ +COGL_DEPRECATED_IN_1_8_FOR (cogl_framebuffer_set_viewport) +void +cogl_set_viewport (int x, + int y, + int width, + int height); + +/** + * cogl_push_matrix: + * + * Stores the current model-view matrix on the matrix stack. The matrix + * can later be restored with cogl_pop_matrix(). + * + * Deprecated: 1.10: Use cogl_framebuffer_push_matrix() instead + */ +COGL_DEPRECATED_IN_1_10_FOR (cogl_framebuffer_push_matrix) +void +cogl_push_matrix (void); + +/** + * cogl_pop_matrix: + * + * Restores the current model-view matrix from the matrix stack. + * + * Deprecated: 1.10: Use cogl_framebuffer_pop_matrix() instead + */ +COGL_DEPRECATED_IN_1_10_FOR (cogl_framebuffer_push_matrix) +void +cogl_pop_matrix (void); + +/** + * cogl_scale: + * @x: Amount to scale along the x-axis + * @y: Amount to scale along the y-axis + * @z: Amount to scale along the z-axis + * + * Multiplies the current model-view matrix by one that scales the x, + * y and z axes by the given values. + * + * Deprecated: 1.10: Use cogl_framebuffer_pop_matrix() instead + */ +COGL_DEPRECATED_IN_1_10_FOR (cogl_framebuffer_scale) +void +cogl_scale (float x, + float y, + float z); + +/** + * cogl_translate: + * @x: Distance to translate along the x-axis + * @y: Distance to translate along the y-axis + * @z: Distance to translate along the z-axis + * + * Multiplies the current model-view matrix by one that translates the + * model along all three axes according to the given values. + * + * Deprecated: 1.10: Use cogl_framebuffer_translate() instead + */ +COGL_DEPRECATED_IN_1_10_FOR (cogl_framebuffer_translate) +void +cogl_translate (float x, + float y, + float z); + +/** + * cogl_rotate: + * @angle: Angle in degrees to rotate. + * @x: X-component of vertex to rotate around. + * @y: Y-component of vertex to rotate around. + * @z: Z-component of vertex to rotate around. + * + * Multiplies the current model-view matrix by one that rotates the + * model around the vertex specified by @x, @y and @z. The rotation + * follows the right-hand thumb rule so for example rotating by 10 + * degrees about the vertex (0, 0, 1) causes a small counter-clockwise + * rotation. + * + * Deprecated: 1.10: Use cogl_framebuffer_rotate() instead + */ +COGL_DEPRECATED_IN_1_10_FOR (cogl_framebuffer_rotate) +void +cogl_rotate (float angle, + float x, + float y, + float z); + +/** + * cogl_transform: + * @matrix: the matrix to multiply with the current model-view + * + * Multiplies the current model-view matrix by the given matrix. + * + * Since: 1.4 + * Deprecated: 1.10: Use cogl_framebuffer_transform() instead + */ +COGL_DEPRECATED_IN_1_10_FOR (cogl_framebuffer_transform) +void +cogl_transform (const CoglMatrix *matrix); + +/** + * cogl_get_modelview_matrix: + * @matrix: (out): return location for the model-view matrix + * + * Stores the current model-view matrix in @matrix. + * + * Deprecated: 1.10: Use cogl_framebuffer_get_modelview_matrix() + * instead + */ +COGL_DEPRECATED_IN_1_10_FOR (cogl_framebuffer_get_modelview_matrix) +void +cogl_get_modelview_matrix (CoglMatrix *matrix); + +/** + * cogl_set_modelview_matrix: + * @matrix: the new model-view matrix + * + * Loads @matrix as the new model-view matrix. + * + * Deprecated: 1.10: Use cogl_framebuffer_set_modelview_matrix() + * instead + */ +COGL_DEPRECATED_IN_1_10_FOR (cogl_framebuffer_set_modelview_matrix) +void +cogl_set_modelview_matrix (CoglMatrix *matrix); + +/** + * cogl_get_projection_matrix: + * @matrix: (out): return location for the projection matrix + * + * Stores the current projection matrix in @matrix. + * + * Deprecated: 1.10: Use cogl_framebuffer_get_projection_matrix() + * instead + */ +COGL_DEPRECATED_IN_1_10_FOR (cogl_framebuffer_get_projection_matrix) +void +cogl_get_projection_matrix (CoglMatrix *matrix); + +/** + * cogl_set_projection_matrix: + * @matrix: the new projection matrix + * + * Loads matrix as the new projection matrix. + * + * Deprecated: 1.10: Use cogl_framebuffer_set_projection_matrix() + * instead + */ +COGL_DEPRECATED_IN_1_10_FOR (cogl_framebuffer_set_projection_matrix) +void +cogl_set_projection_matrix (CoglMatrix *matrix); + +/** + * cogl_get_viewport: + * @v: (out) (array fixed-size=4): pointer to a 4 element array + * of #floats to receive the viewport dimensions. + * + * Stores the current viewport in @v. @v[0] and @v[1] get the x and y + * position of the viewport and @v[2] and @v[3] get the width and + * height. + * + * Deprecated: 1.10: Use cogl_framebuffer_get_viewport4fv() + * instead + */ +COGL_DEPRECATED_IN_1_10_FOR (cogl_framebuffer_get_viewport4fv) +void +cogl_get_viewport (float v[4]); + +/** + * cogl_set_depth_test_enabled: + * @setting: %TRUE to enable depth testing or %FALSE to disable. + * + * Sets whether depth testing is enabled. If it is disabled then the + * order that actors are layered on the screen depends solely on the + * order specified using clutter_actor_raise() and + * clutter_actor_lower(), otherwise it will also take into account the + * actor's depth. Depth testing is disabled by default. + * + * Deprecated: 1.16: Use cogl_pipeline_set_depth_state() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_set_depth_state) +void +cogl_set_depth_test_enabled (CoglBool setting); + +/** + * cogl_get_depth_test_enabled: + * + * Queries if depth testing has been enabled via cogl_set_depth_test_enable() + * + * Return value: %TRUE if depth testing is enabled, and %FALSE otherwise + * + * Deprecated: 1.16: Use cogl_pipeline_set_depth_state() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_set_depth_state) +CoglBool +cogl_get_depth_test_enabled (void); + +/** + * cogl_set_backface_culling_enabled: + * @setting: %TRUE to enable backface culling or %FALSE to disable. + * + * Sets whether textures positioned so that their backface is showing + * should be hidden. This can be used to efficiently draw two-sided + * textures or fully closed cubes without enabling depth testing. This + * only affects calls to the cogl_rectangle* family of functions and + * cogl_vertex_buffer_draw*. Backface culling is disabled by default. + * + * Deprecated: 1.16: Use cogl_pipeline_set_cull_face_mode() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_set_cull_face_mode) +void +cogl_set_backface_culling_enabled (CoglBool setting); + +/** + * cogl_get_backface_culling_enabled: + * + * Queries if backface culling has been enabled via + * cogl_set_backface_culling_enabled() + * + * Return value: %TRUE if backface culling is enabled, and %FALSE otherwise + * + * Deprecated: 1.16: Use cogl_pipeline_get_cull_face_mode() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_get_cull_face_mode) +CoglBool +cogl_get_backface_culling_enabled (void); + +/** + * cogl_set_fog: + * @fog_color: The color of the fog + * @mode: A #CoglFogMode that determines the equation used to calculate the + * fogging blend factor. + * @density: Used by %COGL_FOG_MODE_EXPONENTIAL and by + * %COGL_FOG_MODE_EXPONENTIAL_SQUARED equations. + * @z_near: Position along Z axis where no fogging should be applied + * @z_far: Position along Z axis where full fogging should be applied + * + * Enables fogging. Fogging causes vertices that are further away from the eye + * to be rendered with a different color. The color is determined according to + * the chosen fog mode; at it's simplest the color is linearly interpolated so + * that vertices at @z_near are drawn fully with their original color and + * vertices at @z_far are drawn fully with @fog_color. Fogging will remain + * enabled until you call cogl_disable_fog(). + * + * The fogging functions only work correctly when primitives use + * unmultiplied alpha colors. By default Cogl will premultiply textures + * and cogl_set_source_color() will premultiply colors, so unless you + * explicitly load your textures requesting an unmultiplied internal format + * and use cogl_material_set_color() you can only use fogging with fully + * opaque primitives. This might improve in the future when we can depend + * on fragment shaders. + * + * Deprecated: 1.16: Use #CoglSnippet shader api for fog + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_API) +void +cogl_set_fog (const CoglColor *fog_color, + CoglFogMode mode, + float density, + float z_near, + float z_far); + +/** + * cogl_disable_fog: + * + * This function disables fogging, so primitives drawn afterwards will not be + * blended with any previously set fog color. + * + * Deprecated: 1.16: Use #CoglSnippet shader api for fog + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_API) +void +cogl_disable_fog (void); + +/** + * cogl_clear: + * @color: Background color to clear to + * @buffers: A mask of #CoglBufferBit's identifying which auxiliary + * buffers to clear + * + * Clears all the auxiliary buffers identified in the @buffers mask, and if + * that includes the color buffer then the specified @color is used. + * + * Deprecated: 1.16: Use cogl_framebuffer_clear() api instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_framebuffer_clear) +void +cogl_clear (const CoglColor *color, + unsigned long buffers); + +/** + * cogl_set_source: + * @material: A #CoglMaterial + * + * This function changes the material at the top of the source stack. + * The material at the top of this stack defines the GPU state used to + * process subsequent primitives, such as rectangles drawn with + * cogl_rectangle() or vertices drawn using cogl_vertex_buffer_draw(). + * + * Since: 1.0 + * Deprecated: 1.16: Latest drawing apis all take an explicit + * #CoglPipeline argument so this stack of + * #CoglMaterials shouldn't be used. + */ +COGL_DEPRECATED_IN_1_16 +void +cogl_set_source (void *material); + +/** + * cogl_get_source: + * + * Returns the current source material as previously set using + * cogl_set_source(). + * + * You should typically consider the returned material immutable + * and not try to change any of its properties unless you own a + * reference to that material. At times you may be able to get a + * reference to an internally managed materials and the result of + * modifying such materials is undefined. + * + * Return value: The current source material. + * + * Since: 1.6 + * Deprecated: 1.16: Latest drawing apis all take an explicit + * #CoglPipeline argument so this stack of + * #CoglMaterials shouldn't be used. + */ +COGL_DEPRECATED_IN_1_16 +void * +cogl_get_source (void); + +/** + * cogl_push_source: + * @material: A #CoglMaterial + * + * Pushes the given @material to the top of the source stack. The + * material at the top of this stack defines the GPU state used to + * process later primitives as defined by cogl_set_source(). + * + * Since: 1.6 + * Deprecated: 1.16: Latest drawing apis all take an explicit + * #CoglPipeline argument so this stack of + * #CoglMaterials shouldn't be used. + */ +COGL_DEPRECATED_IN_1_16 +void +cogl_push_source (void *material); + +/** + * cogl_pop_source: + * + * Removes the material at the top of the source stack. The material + * at the top of this stack defines the GPU state used to process + * later primitives as defined by cogl_set_source(). + * + * Since: 1.6 + * Deprecated: 1.16: Latest drawing apis all take an explicit + * #CoglPipeline argument so this stack of + * #CoglMaterials shouldn't be used. + */ +COGL_DEPRECATED_IN_1_16 +void +cogl_pop_source (void); + +/** + * cogl_set_source_color: + * @color: a #CoglColor + * + * This is a convenience function for creating a solid fill source material + * from the given color. This color will be used for any subsequent drawing + * operation. + * + * The color will be premultiplied by Cogl, so the color should be + * non-premultiplied. For example: use (1.0, 0.0, 0.0, 0.5) for + * semi-transparent red. + * + * See also cogl_set_source_color4ub() and cogl_set_source_color4f() + * if you already have the color components. + * + * Since: 1.0 + * Deprecated: 1.16: Latest drawing apis all take an explicit + * #CoglPipeline argument so this stack of + * #CoglMaterials shouldn't be used. + */ +COGL_DEPRECATED_IN_1_16 +void +cogl_set_source_color (const CoglColor *color); + +/** + * cogl_set_source_color4ub: + * @red: value of the red channel, between 0 and 255 + * @green: value of the green channel, between 0 and 255 + * @blue: value of the blue channel, between 0 and 255 + * @alpha: value of the alpha channel, between 0 and 255 + * + * This is a convenience function for creating a solid fill source material + * from the given color using unsigned bytes for each component. This + * color will be used for any subsequent drawing operation. + * + * The value for each component is an unsigned byte in the range + * between 0 and 255. + * + * Since: 1.0 + * Deprecated: 1.16: Latest drawing apis all take an explicit + * #CoglPipeline argument so this stack of + * #CoglMaterials shouldn't be used. + */ +COGL_DEPRECATED_IN_1_16 +void +cogl_set_source_color4ub (uint8_t red, + uint8_t green, + uint8_t blue, + uint8_t alpha); + +/** + * cogl_set_source_color4f: + * @red: value of the red channel, between 0 and %1.0 + * @green: value of the green channel, between 0 and %1.0 + * @blue: value of the blue channel, between 0 and %1.0 + * @alpha: value of the alpha channel, between 0 and %1.0 + * + * This is a convenience function for creating a solid fill source material + * from the given color using normalized values for each component. This color + * will be used for any subsequent drawing operation. + * + * The value for each component is a fixed point number in the range + * between 0 and %1.0. If the values passed in are outside that + * range, they will be clamped. + * + * Since: 1.0 + * Deprecated: 1.16: Latest drawing apis all take an explicit + * #CoglPipeline argument so this stack of + * #CoglMaterials shouldn't be used. + */ +COGL_DEPRECATED_IN_1_16 +void +cogl_set_source_color4f (float red, + float green, + float blue, + float alpha); + +/** + * cogl_set_source_texture: + * @texture: The #CoglTexture you want as your source + * + * This is a convenience function for creating a material with the first + * layer set to @texture and setting that material as the source with + * cogl_set_source. + * + * Note: There is no interaction between calls to cogl_set_source_color + * and cogl_set_source_texture. If you need to blend a texture with a color then + * you can create a simple material like this: + * + * material = cogl_material_new (); + * cogl_material_set_color4ub (material, 0xff, 0x00, 0x00, 0x80); + * cogl_material_set_layer (material, 0, tex_handle); + * cogl_set_source (material); + * + * + * Since: 1.0 + * Deprecated: 1.16: Latest drawing apis all take an explicit + * #CoglPipeline argument so this stack of + * #CoglMaterials shouldn't be used. + */ +COGL_DEPRECATED_IN_1_16 +void +cogl_set_source_texture (CoglTexture *texture); + +/** + * cogl_flush: + * + * This function should only need to be called in exceptional circumstances. + * + * As an optimization Cogl drawing functions may batch up primitives + * internally, so if you are trying to use raw GL outside of Cogl you stand a + * better chance of being successful if you ask Cogl to flush any batched + * geometry before making your state changes. + * + * It only ensure that the underlying driver is issued all the commands + * necessary to draw the batched primitives. It provides no guarantees about + * when the driver will complete the rendering. + * + * This provides no guarantees about the GL state upon returning and to avoid + * confusing Cogl you should aim to restore any changes you make before + * resuming use of Cogl. + * + * If you are making state changes with the intention of affecting Cogl drawing + * primitives you are 100% on your own since you stand a good chance of + * conflicting with Cogl internals. For example clutter-gst which currently + * uses direct GL calls to bind ARBfp programs will very likely break when Cogl + * starts to use ARBfb programs itself for the material API. + * + * Since: 1.0 + */ +void +cogl_flush (void); + +/** + * cogl_begin_gl: + * + * We do not advise nor reliably support the interleaving of raw GL drawing and + * Cogl drawing functions, but if you insist, cogl_begin_gl() and cogl_end_gl() + * provide a simple mechanism that may at least give you a fighting chance of + * succeeding. + * + * Note: this doesn't help you modify the behaviour of Cogl drawing functions + * through the modification of GL state; that will never be reliably supported, + * but if you are trying to do something like: + * + * |[ + * { + * - setup some OpenGL state. + * - draw using OpenGL (e.g. glDrawArrays() ) + * - reset modified OpenGL state. + * - continue using Cogl to draw + * } + * ]| + * + * You should surround blocks of drawing using raw GL with cogl_begin_gl() + * and cogl_end_gl(): + * + * |[ + * { + * cogl_begin_gl (); + * - setup some OpenGL state. + * - draw using OpenGL (e.g. glDrawArrays() ) + * - reset modified OpenGL state. + * cogl_end_gl (); + * - continue using Cogl to draw + * } + * ]| + * + * Don't ever try and do: + * + * |[ + * { + * - setup some OpenGL state. + * - use Cogl to draw + * - reset modified OpenGL state. + * } + * ]| + * + * When the internals of Cogl evolves, this is very liable to break. + * + * This function will flush all batched primitives, and subsequently flush + * all internal Cogl state to OpenGL as if it were going to draw something + * itself. + * + * The result is that the OpenGL modelview matrix will be setup; the state + * corresponding to the current source material will be set up and other world + * state such as backface culling, depth and fogging enabledness will be sent + * to OpenGL. + * + * No special material state is flushed, so if you want Cogl to setup a + * simplified material state it is your responsibility to set a simple source + * material before calling cogl_begin_gl(). E.g. by calling + * cogl_set_source_color4ub(). + * + * It is your responsibility to restore any OpenGL state that you modify + * to how it was after calling cogl_begin_gl() if you don't do this then the + * result of further Cogl calls is undefined. + * + * You can not nest begin/end blocks. + * + * Again we would like to stress, we do not advise the use of this API and if + * possible we would prefer to improve Cogl than have developers require raw + * OpenGL. + * + * Since: 1.0 + * Deprecated: 1.16: Use the #CoglGLES2Context api instead + */ +COGL_DEPRECATED_IN_1_16_FOR (CoglGLES2Context_API) +void +cogl_begin_gl (void); + +/** + * cogl_end_gl: + * + * This is the counterpart to cogl_begin_gl() used to delimit blocks of drawing + * code using raw OpenGL. Please refer to cogl_begin_gl() for full details. + * + * Since: 1.0 + * Deprecated: 1.16: Use the #CoglGLES2Context api instead + */ +COGL_DEPRECATED_IN_1_16_FOR (CoglGLES2Context_API) +void +cogl_end_gl (void); + +COGL_END_DECLS + +#endif /* __COGL_1_CONTEXT_H__ */ diff --git a/cogl/cogl/deprecated/cogl-auto-texture.c b/cogl/cogl/deprecated/cogl-auto-texture.c new file mode 100644 index 0000000..29a5f73 --- /dev/null +++ b/cogl/cogl/deprecated/cogl-auto-texture.c @@ -0,0 +1,419 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2011,2012 Intel Corporation. + * Copyright (C) 2010 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Matthew Allum + * Neil Roberts + * Robert Bragg + */ + +#include "cogl-config.h" + +#include "cogl-context-private.h" +#include "cogl-texture.h" +#include "cogl-util.h" +#include "cogl-texture-2d.h" +#include "cogl-texture-2d-private.h" +#include "cogl-primitive-texture.h" +#include "cogl-texture-2d-sliced-private.h" +#include "cogl-private.h" +#include "cogl-object.h" +#include "cogl-bitmap-private.h" +#include "cogl-atlas-texture-private.h" +#include "cogl-error-private.h" +#include "cogl-texture-rectangle.h" +#include "cogl-sub-texture.h" +#include "cogl-texture-2d-gl.h" + +#include "deprecated/cogl-auto-texture.h" + +static CoglTexture * +_cogl_texture_new_from_bitmap (CoglBitmap *bitmap, + CoglTextureFlags flags, + CoglPixelFormat internal_format, + CoglBool can_convert_in_place, + CoglError **error); + +static void +set_auto_mipmap_cb (CoglTexture *sub_texture, + const float *sub_texture_coords, + const float *meta_coords, + void *user_data) +{ + cogl_primitive_texture_set_auto_mipmap (COGL_PRIMITIVE_TEXTURE (sub_texture), + FALSE); +} + +CoglTexture * +cogl_texture_new_with_size (unsigned int width, + unsigned int height, + CoglTextureFlags flags, + CoglPixelFormat internal_format) +{ + CoglTexture *tex; + CoglError *skip_error = NULL; + + _COGL_GET_CONTEXT (ctx, NULL); + + if ((_cogl_util_is_pot (width) && _cogl_util_is_pot (height)) || + (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC) && + cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP))) + { + /* First try creating a fast-path non-sliced texture */ + tex = COGL_TEXTURE (cogl_texture_2d_new_with_size (ctx, width, height)); + + _cogl_texture_set_internal_format (tex, internal_format); + + if (!cogl_texture_allocate (tex, &skip_error)) + { + cogl_error_free (skip_error); + cogl_object_unref (tex); + tex = NULL; + } + } + else + tex = NULL; + + if (!tex) + { + /* If it fails resort to sliced textures */ + int max_waste = flags & COGL_TEXTURE_NO_SLICING ? -1 : COGL_TEXTURE_MAX_WASTE; + tex = COGL_TEXTURE (cogl_texture_2d_sliced_new_with_size (ctx, + width, + height, + max_waste)); + + _cogl_texture_set_internal_format (tex, internal_format); + } + + /* NB: This api existed before Cogl introduced lazy allocation of + * textures and so we maintain its original synchronous allocation + * semantics and return NULL if allocation fails... */ + if (!cogl_texture_allocate (tex, &skip_error)) + { + cogl_error_free (skip_error); + cogl_object_unref (tex); + return NULL; + } + + if (tex && + flags & COGL_TEXTURE_NO_AUTO_MIPMAP) + { + cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (tex), + 0, 0, 1, 1, + COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE, + COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE, + set_auto_mipmap_cb, + NULL); + } + + return tex; +} + +static CoglTexture * +_cogl_texture_new_from_data (CoglContext *ctx, + int width, + int height, + CoglTextureFlags flags, + CoglPixelFormat format, + CoglPixelFormat internal_format, + int rowstride, + const uint8_t *data, + CoglError **error) +{ + CoglBitmap *bmp; + CoglTexture *tex; + + _COGL_RETURN_VAL_IF_FAIL (format != COGL_PIXEL_FORMAT_ANY, NULL); + _COGL_RETURN_VAL_IF_FAIL (data != NULL, NULL); + + /* Rowstride from width if not given */ + if (rowstride == 0) + rowstride = width * _cogl_pixel_format_get_bytes_per_pixel (format); + + /* Wrap the data into a bitmap */ + bmp = cogl_bitmap_new_for_data (ctx, + width, height, + format, + rowstride, + (uint8_t *) data); + + tex = _cogl_texture_new_from_bitmap (bmp, + flags, + internal_format, + FALSE, /* can't convert in place */ + error); + + cogl_object_unref (bmp); + + return tex; +} + +CoglTexture * +cogl_texture_new_from_data (int width, + int height, + CoglTextureFlags flags, + CoglPixelFormat format, + CoglPixelFormat internal_format, + int rowstride, + const uint8_t *data) +{ + CoglError *ignore_error = NULL; + CoglTexture *tex; + + _COGL_GET_CONTEXT (ctx, NULL); + + tex = _cogl_texture_new_from_data (ctx, + width, height, + flags, + format, internal_format, + rowstride, + data, + &ignore_error); + if (!tex) + cogl_error_free (ignore_error); + return tex; +} + +static CoglTexture * +_cogl_texture_new_from_bitmap (CoglBitmap *bitmap, + CoglTextureFlags flags, + CoglPixelFormat internal_format, + CoglBool can_convert_in_place, + CoglError **error) +{ + CoglContext *ctx = _cogl_bitmap_get_context (bitmap); + CoglTexture *tex; + CoglError *internal_error = NULL; + + if (!flags && + !COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_ATLAS)) + { + /* First try putting the texture in the atlas */ + CoglAtlasTexture *atlas_tex = + _cogl_atlas_texture_new_from_bitmap (bitmap, + can_convert_in_place); + + _cogl_texture_set_internal_format (COGL_TEXTURE (atlas_tex), + internal_format); + + if (cogl_texture_allocate (COGL_TEXTURE (atlas_tex), &internal_error)) + return COGL_TEXTURE (atlas_tex); + + cogl_error_free (internal_error); + internal_error = NULL; + cogl_object_unref (atlas_tex); + } + + /* If that doesn't work try a fast path 2D texture */ + if ((_cogl_util_is_pot (bitmap->width) && + _cogl_util_is_pot (bitmap->height)) || + (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC) && + cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP))) + { + tex = COGL_TEXTURE (_cogl_texture_2d_new_from_bitmap (bitmap, + can_convert_in_place)); + + _cogl_texture_set_internal_format (tex, internal_format); + + if (!cogl_texture_allocate (tex, &internal_error)) + { + cogl_error_free (internal_error); + internal_error = NULL; + cogl_object_unref (tex); + tex = NULL; + } + } + else + tex = NULL; + + if (!tex) + { + /* Otherwise create a sliced texture */ + int max_waste = flags & COGL_TEXTURE_NO_SLICING ? -1 : COGL_TEXTURE_MAX_WASTE; + tex = COGL_TEXTURE (_cogl_texture_2d_sliced_new_from_bitmap (bitmap, + max_waste, + can_convert_in_place)); + + _cogl_texture_set_internal_format (tex, internal_format); + + if (!cogl_texture_allocate (tex, error)) + { + cogl_object_unref (tex); + tex = NULL; + } + } + + if (tex && + flags & COGL_TEXTURE_NO_AUTO_MIPMAP) + { + cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (tex), + 0, 0, 1, 1, + COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE, + COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE, + set_auto_mipmap_cb, + NULL); + } + + return tex; +} + +CoglTexture * +cogl_texture_new_from_bitmap (CoglBitmap *bitmap, + CoglTextureFlags flags, + CoglPixelFormat internal_format) +{ + CoglError *ignore_error = NULL; + CoglTexture *tex = + _cogl_texture_new_from_bitmap (bitmap, + flags, + internal_format, + FALSE, /* can't convert in-place */ + &ignore_error); + if (!tex) + cogl_error_free (ignore_error); + return tex; +} + +CoglTexture * +cogl_texture_new_from_file (const char *filename, + CoglTextureFlags flags, + CoglPixelFormat internal_format, + CoglError **error) +{ + CoglBitmap *bmp; + CoglTexture *texture = NULL; + + _COGL_GET_CONTEXT (ctx, NULL); + + _COGL_RETURN_VAL_IF_FAIL (error == NULL || *error == NULL, NULL); + + bmp = cogl_bitmap_new_from_file (filename, error); + if (bmp == NULL) + return NULL; + + texture = _cogl_texture_new_from_bitmap (bmp, flags, + internal_format, + TRUE, /* can convert in-place */ + error); + + cogl_object_unref (bmp); + + return texture; +} + +CoglTexture * +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_GET_CONTEXT (ctx, NULL); + +#ifdef HAVE_COGL_GL + if (gl_target == GL_TEXTURE_RECTANGLE_ARB) + { + CoglTextureRectangle *texture_rectangle; + CoglSubTexture *sub_texture; + + if (x_pot_waste != 0 || y_pot_waste != 0) + { + /* It shouldn't be necessary to have waste in this case since + * the texture isn't limited to power of two sizes. */ + g_warning ("You can't create a foreign GL_TEXTURE_RECTANGLE cogl " + "texture with waste\n"); + return NULL; + } + + texture_rectangle = cogl_texture_rectangle_new_from_foreign (ctx, + gl_handle, + width, + height, + format); + _cogl_texture_set_internal_format (COGL_TEXTURE (texture_rectangle), + format); + + /* CoglTextureRectangle textures work with non-normalized + * coordinates, but the semantics for this function that people + * depend on are that all returned texture works with normalized + * coordinates so we wrap with a CoglSubTexture... */ + sub_texture = cogl_sub_texture_new (ctx, + COGL_TEXTURE (texture_rectangle), + 0, 0, width, height); + return COGL_TEXTURE (sub_texture); + } +#endif + + if (x_pot_waste != 0 || y_pot_waste != 0) + { + CoglTexture *tex = + COGL_TEXTURE (_cogl_texture_2d_sliced_new_from_foreign (ctx, + gl_handle, + gl_target, + width, + height, + x_pot_waste, + y_pot_waste, + format)); + _cogl_texture_set_internal_format (tex, format); + + cogl_texture_allocate (tex, NULL); + return tex; + } + else + { + CoglTexture *tex = + COGL_TEXTURE (cogl_texture_2d_gl_new_from_foreign (ctx, + gl_handle, + width, + height, + format)); + _cogl_texture_set_internal_format (tex, format); + + cogl_texture_allocate (tex, NULL); + return tex; + } +} + +CoglTexture * +cogl_texture_new_from_sub_texture (CoglTexture *full_texture, + int sub_x, + int sub_y, + int sub_width, + int sub_height) +{ + _COGL_GET_CONTEXT (ctx, NULL); + return COGL_TEXTURE (cogl_sub_texture_new (ctx, + full_texture, sub_x, sub_y, + sub_width, sub_height)); +} diff --git a/cogl/cogl/deprecated/cogl-auto-texture.h b/cogl/cogl/deprecated/cogl-auto-texture.h new file mode 100644 index 0000000..44e868d --- /dev/null +++ b/cogl/cogl/deprecated/cogl-auto-texture.h @@ -0,0 +1,223 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2014 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_AUTO_TEXTURE_H__ +#define __COGL_AUTO_TEXTURE_H__ + +COGL_BEGIN_DECLS + +#include + +/** + * cogl_texture_new_with_size: + * @width: width of texture in pixels. + * @height: height of texture in pixels. + * @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE + * @internal_format: the #CoglPixelFormat to use for the GPU storage of the + * texture. + * + * Creates a new #CoglTexture with the specified dimensions and pixel format. + * + * Return value: (transfer full): A newly created #CoglTexture or %NULL on failure + * + * Since: 0.8 + * Deprecated: 1.18: Use specific constructors such as + * cogl_texture_2d_new_with_size() + */ +COGL_DEPRECATED_IN_1_18_FOR(cogl_texture_2d_new_with_size__OR__cogl_texture_2d_sliced_new_with_size) +CoglTexture * +cogl_texture_new_with_size (unsigned int width, + unsigned int height, + CoglTextureFlags flags, + CoglPixelFormat internal_format); + +/** + * cogl_texture_new_from_file: + * @filename: the file to load + * @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE + * @internal_format: the #CoglPixelFormat to use for the GPU storage of the + * texture. If %COGL_PIXEL_FORMAT_ANY is given then a premultiplied + * format similar to the format of the source data will be used. The + * default blending equations of Cogl expect premultiplied color data; + * the main use of passing a non-premultiplied format here is if you + * have non-premultiplied source data and are going to adjust the blend + * mode (see cogl_material_set_blend()) or use the data for something + * other than straight blending. + * @error: return location for a #CoglError or %NULL + * + * Creates a #CoglTexture from an image file. + * + * Return value: (transfer full): A newly created #CoglTexture or + * %NULL on failure + * + * Since: 0.8 + * Deprecated: 1.18: Use specific constructors such as + * cogl_texture_2d_new_from_file() + */ +COGL_DEPRECATED_IN_1_18_FOR(cogl_texture_2d_new_from_file__OR__cogl_texture_2d_sliced_new_from_file) +CoglTexture * +cogl_texture_new_from_file (const char *filename, + CoglTextureFlags flags, + CoglPixelFormat internal_format, + CoglError **error); + +/** + * cogl_texture_new_from_data: + * @width: width of texture in pixels + * @height: height of texture in pixels + * @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE + * @format: the #CoglPixelFormat the buffer is stored in in RAM + * @internal_format: the #CoglPixelFormat that will be used for storing + * the buffer on the GPU. If COGL_PIXEL_FORMAT_ANY is given then a + * premultiplied format similar to the format of the source data will + * be used. The default blending equations of Cogl expect premultiplied + * color data; the main use of passing a non-premultiplied format here + * is if you have non-premultiplied source data and are going to adjust + * the blend mode (see cogl_material_set_blend()) or use the data for + * something other than straight blending. + * @rowstride: the memory offset in bytes between the starts of + * scanlines in @data + * @data: pointer the memory region where the source buffer resides + * + * Creates a new #CoglTexture based on data residing in memory. + * + * Return value: (transfer full): A newly created #CoglTexture or + * %NULL on failure + * + * Since: 0.8 + * Deprecated: 1.18: Use specific constructors such as + * cogl_texture_2d_new_from_data() + */ +COGL_DEPRECATED_IN_1_18_FOR(cogl_texture_2d_new_from_data__OR__cogl_texture_2d_sliced_new_from_data) +CoglTexture * +cogl_texture_new_from_data (int width, + int height, + CoglTextureFlags flags, + CoglPixelFormat format, + CoglPixelFormat internal_format, + int rowstride, + const uint8_t *data); + +/** + * cogl_texture_new_from_foreign: + * @gl_handle: opengl handle of foreign texture. + * @gl_target: opengl target type of foreign texture + * @width: width of foreign texture + * @height: height of foreign texture. + * @x_pot_waste: horizontal waste on the right hand edge of the texture. + * @y_pot_waste: vertical waste on the bottom edge of the texture. + * @format: format of the foreign texture. + * + * Creates a #CoglTexture based on an existing OpenGL texture; the + * width, height and format are passed along since it is not always + * possible to query these from OpenGL. + * + * The waste arguments allow you to create a Cogl texture that maps to + * a region smaller than the real OpenGL texture. For instance if your + * hardware only supports power-of-two textures you may load a + * non-power-of-two image into a larger power-of-two texture and use + * the waste arguments to tell Cogl which region should be mapped to + * the texture coordinate range [0:1]. + * + * Return value: (transfer full): A newly created #CoglTexture or + * %NULL on failure + * + * Since: 0.8 + * Deprecated: 1.18: Use specific constructors such as + * cogl_texture_2d_new_from_foreign() + */ +COGL_DEPRECATED_IN_1_18_FOR(cogl_texture_2d_new_from_foreign) +CoglTexture * +cogl_texture_new_from_foreign (unsigned int gl_handle, + unsigned int gl_target, + unsigned int width, + unsigned int height, + unsigned int x_pot_waste, + unsigned int y_pot_waste, + CoglPixelFormat format); + +/** + * cogl_texture_new_from_bitmap: + * @bitmap: A #CoglBitmap pointer + * @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE + * @internal_format: the #CoglPixelFormat to use for the GPU storage of the + * texture + * + * Creates a #CoglTexture from a #CoglBitmap. + * + * Return value: (transfer full): A newly created #CoglTexture or + * %NULL on failure + * + * Since: 1.0 + * Deprecated: 1.18: Use specific constructors such as + * cogl_texture_2d_new_from_bitmap() + */ +COGL_DEPRECATED_IN_1_18_FOR(cogl_texture_2d_new_from_bitmap__OR__cogl_texture_2d_sliced_new_from_bitmap) +CoglTexture * +cogl_texture_new_from_bitmap (CoglBitmap *bitmap, + CoglTextureFlags flags, + CoglPixelFormat internal_format); + +/** + * cogl_texture_new_from_sub_texture: + * @full_texture: a #CoglTexture pointer + * @sub_x: X coordinate of the top-left of the subregion + * @sub_y: Y coordinate of the top-left of the subregion + * @sub_width: Width in pixels of the subregion + * @sub_height: Height in pixels of the subregion + * + * Creates a new texture which represents a subregion of another + * texture. The GL resources will be shared so that no new texture + * data is actually allocated. + * + * Sub textures have undefined behaviour texture coordinates outside + * of the range [0,1] are used. They also do not work with + * CoglVertexBuffers. + * + * The sub texture will keep a reference to the full texture so you do + * not need to keep one separately if you only want to use the sub + * texture. + * + * Return value: (transfer full): A newly created #CoglTexture or + * %NULL on failure + * Since: 1.2 + * Deprecated: 1.18: Use cogl_sub_texture_new() + */ +COGL_DEPRECATED_IN_1_18_FOR(cogl_sub_texture_new) +CoglTexture * +cogl_texture_new_from_sub_texture (CoglTexture *full_texture, + int sub_x, + int sub_y, + int sub_width, + int sub_height); + +COGL_END_DECLS + +#endif /* __COGL_AUTO_TEXTURE_H__ */ diff --git a/cogl/cogl/deprecated/cogl-clutter-xlib.h b/cogl/cogl/deprecated/cogl-clutter-xlib.h new file mode 100644 index 0000000..dc7300a --- /dev/null +++ b/cogl/cogl/deprecated/cogl-clutter-xlib.h @@ -0,0 +1,50 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#if !defined(__COGL_XLIB_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_CLUTTER_XLIB_H__ +#define __COGL_CLUTTER_XLIB_H__ + +#include + +COGL_BEGIN_DECLS + +#define cogl_clutter_winsys_xlib_get_visual_info cogl_clutter_winsys_xlib_get_visual_info_CLUTTER + +/** + * cogl_clutter_winsys_xlib_get_visual_info_CLUTTER: (skip) + */ +XVisualInfo * +cogl_clutter_winsys_xlib_get_visual_info (void); + +COGL_END_DECLS + +#endif /* __COGL_CLUTTER_XLIB_H__ */ diff --git a/cogl/cogl/deprecated/cogl-clutter.c b/cogl/cogl/deprecated/cogl-clutter.c new file mode 100644 index 0000000..6c972f2 --- /dev/null +++ b/cogl/cogl/deprecated/cogl-clutter.c @@ -0,0 +1,114 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include +#include + +#include "cogl-util.h" +#include "cogl-types.h" +#include "cogl-private.h" +#include "cogl-context-private.h" +#include "cogl-winsys-private.h" +#include "cogl-winsys-stub-private.h" +#include "cogl-framebuffer-private.h" +#include "cogl-onscreen-private.h" +#ifdef COGL_HAS_XLIB_SUPPORT +#include "cogl-clutter-xlib.h" +#include "cogl-xlib-renderer.h" +#endif +#include "cogl-clutter.h" + +CoglBool +cogl_clutter_check_extension (const char *name, const char *ext) +{ + char *end; + int name_len, n; + + if (name == NULL || ext == NULL) + return FALSE; + + end = (char*)(ext + strlen(ext)); + + name_len = strlen(name); + + while (ext < end) + { + n = strcspn(ext, " "); + + if ((name_len == n) && (!strncmp(name, ext, n))) + return TRUE; + ext += (n + 1); + } + + return FALSE; +} + +CoglBool +cogl_clutter_winsys_has_feature (CoglWinsysFeature feature) +{ + return _cogl_winsys_has_feature (feature); +} + +void +cogl_onscreen_clutter_backend_set_size (int width, int height) +{ + CoglFramebuffer *framebuffer; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (_cogl_context_get_winsys (ctx) != _cogl_winsys_stub_get_vtable ()) + return; + + framebuffer = COGL_FRAMEBUFFER (ctx->window_buffer); + + _cogl_framebuffer_winsys_update_size (framebuffer, width, height); +} + +#ifdef COGL_HAS_XLIB_SUPPORT +XVisualInfo * +cogl_clutter_winsys_xlib_get_visual_info (void) +{ + CoglRenderer *renderer; + + _COGL_GET_CONTEXT (ctx, NULL); + + _COGL_RETURN_VAL_IF_FAIL (ctx->display != NULL, NULL); + + renderer = cogl_display_get_renderer (ctx->display); + _COGL_RETURN_VAL_IF_FAIL (renderer != NULL, NULL); + + return cogl_xlib_renderer_get_visual_info (renderer); +} +#endif diff --git a/cogl/cogl/deprecated/cogl-clutter.h b/cogl/cogl/deprecated/cogl-clutter.h new file mode 100644 index 0000000..cc6c446 --- /dev/null +++ b/cogl/cogl/deprecated/cogl-clutter.h @@ -0,0 +1,54 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_CLUTTER_H__ +#define __COGL_CLUTTER_H__ + +COGL_BEGIN_DECLS + +#define cogl_clutter_check_extension cogl_clutter_check_extension_CLUTTER +COGL_DEPRECATED_IN_1_16 +CoglBool +cogl_clutter_check_extension (const char *name, const char *ext); + +#define cogl_clutter_winsys_has_feature cogl_clutter_winsys_has_feature_CLUTTER +COGL_DEPRECATED_FOR (cogl_has_feature) +CoglBool +cogl_clutter_winsys_has_feature (CoglWinsysFeature feature); + +#define cogl_onscreen_clutter_backend_set_size cogl_onscreen_clutter_backend_set_size_CLUTTER +void +cogl_onscreen_clutter_backend_set_size (int width, int height); + +COGL_END_DECLS + +#endif /* __COGL_CLUTTER_H__ */ diff --git a/cogl/cogl/deprecated/cogl-framebuffer-deprecated.c b/cogl/cogl/deprecated/cogl-framebuffer-deprecated.c new file mode 100644 index 0000000..c1fb560 --- /dev/null +++ b/cogl/cogl/deprecated/cogl-framebuffer-deprecated.c @@ -0,0 +1,295 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2014 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#include "cogl-config.h" + +#include "cogl-types.h" +#include "cogl-context-private.h" +#include "cogl-framebuffer-private.h" +#include "cogl-framebuffer-deprecated.h" + +typedef struct _CoglFramebufferStackEntry +{ + CoglFramebuffer *draw_buffer; + CoglFramebuffer *read_buffer; +} CoglFramebufferStackEntry; + + +static CoglFramebufferStackEntry * +create_stack_entry (CoglFramebuffer *draw_buffer, + CoglFramebuffer *read_buffer) +{ + CoglFramebufferStackEntry *entry = g_slice_new (CoglFramebufferStackEntry); + + entry->draw_buffer = draw_buffer; + entry->read_buffer = read_buffer; + + return entry; +} + +GSList * +_cogl_create_framebuffer_stack (void) +{ + CoglFramebufferStackEntry *entry; + GSList *stack = NULL; + + entry = create_stack_entry (NULL, NULL); + + return g_slist_prepend (stack, entry); +} + +void +_cogl_free_framebuffer_stack (GSList *stack) +{ + GSList *l; + + for (l = stack; l != NULL; l = l->next) + { + CoglFramebufferStackEntry *entry = l->data; + + if (entry->draw_buffer) + cogl_object_unref (entry->draw_buffer); + + if (entry->read_buffer) + cogl_object_unref (entry->read_buffer); + + g_slice_free (CoglFramebufferStackEntry, entry); + } + g_slist_free (stack); +} + +static void +notify_buffers_changed (CoglFramebuffer *old_draw_buffer, + CoglFramebuffer *new_draw_buffer, + CoglFramebuffer *old_read_buffer, + CoglFramebuffer *new_read_buffer) +{ + /* XXX: To support the deprecated cogl_set_draw_buffer API we keep + * track of the last onscreen framebuffer that was set so that it + * can be restored if the COGL_WINDOW_BUFFER enum is used. A + * reference isn't taken to the framebuffer because otherwise we + * would have a circular reference between the context and the + * framebuffer. Instead the pointer is set to NULL in + * _cogl_onscreen_free as a kind of a cheap weak reference */ + if (new_draw_buffer && + new_draw_buffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN) + new_draw_buffer->context->window_buffer = new_draw_buffer; +} + +/* Set the current framebuffer without checking if it's already the + * current framebuffer. This is used by cogl_pop_framebuffer while + * the top of the stack is currently not up to date. */ +static void +_cogl_set_framebuffers_real (CoglFramebuffer *draw_buffer, + CoglFramebuffer *read_buffer) +{ + CoglFramebufferStackEntry *entry; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + _COGL_RETURN_IF_FAIL (ctx != NULL); + _COGL_RETURN_IF_FAIL (draw_buffer && read_buffer ? + draw_buffer->context == read_buffer->context : TRUE); + + entry = ctx->framebuffer_stack->data; + + notify_buffers_changed (entry->draw_buffer, + draw_buffer, + entry->read_buffer, + read_buffer); + + if (draw_buffer) + cogl_object_ref (draw_buffer); + if (entry->draw_buffer) + cogl_object_unref (entry->draw_buffer); + + if (read_buffer) + cogl_object_ref (read_buffer); + if (entry->read_buffer) + cogl_object_unref (entry->read_buffer); + + entry->draw_buffer = draw_buffer; + entry->read_buffer = read_buffer; +} + +static void +_cogl_set_framebuffers (CoglFramebuffer *draw_buffer, + CoglFramebuffer *read_buffer) +{ + CoglFramebuffer *current_draw_buffer; + CoglFramebuffer *current_read_buffer; + + _COGL_RETURN_IF_FAIL (cogl_is_framebuffer (draw_buffer)); + _COGL_RETURN_IF_FAIL (cogl_is_framebuffer (read_buffer)); + + current_draw_buffer = cogl_get_draw_framebuffer (); + current_read_buffer = _cogl_get_read_framebuffer (); + + if (current_draw_buffer != draw_buffer || + current_read_buffer != read_buffer) + _cogl_set_framebuffers_real (draw_buffer, read_buffer); +} + +void +cogl_set_framebuffer (CoglFramebuffer *framebuffer) +{ + _cogl_set_framebuffers (framebuffer, framebuffer); +} + +/* XXX: deprecated API */ +void +cogl_set_draw_buffer (CoglBufferTarget target, CoglHandle handle) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (target == COGL_WINDOW_BUFFER) + handle = ctx->window_buffer; + + /* This is deprecated public API. The public API doesn't currently + really expose the concept of separate draw and read buffers so + for the time being this actually just sets both buffers */ + cogl_set_framebuffer (handle); +} + +CoglFramebuffer * +cogl_get_draw_framebuffer (void) +{ + CoglFramebufferStackEntry *entry; + + _COGL_GET_CONTEXT (ctx, NULL); + + g_assert (ctx->framebuffer_stack); + + entry = ctx->framebuffer_stack->data; + + return entry->draw_buffer; +} + +CoglFramebuffer * +_cogl_get_read_framebuffer (void) +{ + CoglFramebufferStackEntry *entry; + + _COGL_GET_CONTEXT (ctx, NULL); + + g_assert (ctx->framebuffer_stack); + + entry = ctx->framebuffer_stack->data; + + return entry->read_buffer; +} + +void +_cogl_push_framebuffers (CoglFramebuffer *draw_buffer, + CoglFramebuffer *read_buffer) +{ + CoglContext *ctx; + CoglFramebuffer *old_draw_buffer, *old_read_buffer; + + _COGL_RETURN_IF_FAIL (cogl_is_framebuffer (draw_buffer)); + _COGL_RETURN_IF_FAIL (cogl_is_framebuffer (read_buffer)); + + ctx = draw_buffer->context; + _COGL_RETURN_IF_FAIL (ctx != NULL); + _COGL_RETURN_IF_FAIL (draw_buffer->context == read_buffer->context); + + _COGL_RETURN_IF_FAIL (ctx->framebuffer_stack != NULL); + + /* Copy the top of the stack so that when we call cogl_set_framebuffer + it will still know what the old framebuffer was */ + old_draw_buffer = cogl_get_draw_framebuffer (); + if (old_draw_buffer) + cogl_object_ref (old_draw_buffer); + old_read_buffer = _cogl_get_read_framebuffer (); + if (old_read_buffer) + cogl_object_ref (old_read_buffer); + ctx->framebuffer_stack = + g_slist_prepend (ctx->framebuffer_stack, + create_stack_entry (old_draw_buffer, + old_read_buffer)); + + _cogl_set_framebuffers (draw_buffer, read_buffer); +} + +void +cogl_push_framebuffer (CoglFramebuffer *buffer) +{ + _cogl_push_framebuffers (buffer, buffer); +} + +/* XXX: deprecated API */ +void +cogl_push_draw_buffer (void) +{ + cogl_push_framebuffer (cogl_get_draw_framebuffer ()); +} + +void +cogl_pop_framebuffer (void) +{ + CoglFramebufferStackEntry *to_pop; + CoglFramebufferStackEntry *to_restore; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + g_assert (ctx->framebuffer_stack != NULL); + g_assert (ctx->framebuffer_stack->next != NULL); + + to_pop = ctx->framebuffer_stack->data; + to_restore = ctx->framebuffer_stack->next->data; + + if (to_pop->draw_buffer != to_restore->draw_buffer || + to_pop->read_buffer != to_restore->read_buffer) + notify_buffers_changed (to_pop->draw_buffer, + to_restore->draw_buffer, + to_pop->read_buffer, + to_restore->read_buffer); + + cogl_object_unref (to_pop->draw_buffer); + cogl_object_unref (to_pop->read_buffer); + g_slice_free (CoglFramebufferStackEntry, to_pop); + + ctx->framebuffer_stack = + g_slist_delete_link (ctx->framebuffer_stack, + ctx->framebuffer_stack); +} + +/* XXX: deprecated API */ +void +cogl_pop_draw_buffer (void) +{ + cogl_pop_framebuffer (); +} + +CoglPixelFormat +cogl_framebuffer_get_color_format (CoglFramebuffer *framebuffer) +{ + return framebuffer->internal_format; +} diff --git a/cogl/cogl/deprecated/cogl-framebuffer-deprecated.h b/cogl/cogl/deprecated/cogl-framebuffer-deprecated.h new file mode 100644 index 0000000..64c3413 --- /dev/null +++ b/cogl/cogl/deprecated/cogl-framebuffer-deprecated.h @@ -0,0 +1,265 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2014 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_FRAMEBUFFER_DEPRECATED_H__ +#define __COGL_FRAMEBUFFER_DEPRECATED_H__ + +#include +#include + +COGL_BEGIN_DECLS + +/** + * cogl_set_framebuffer: (skip) + * @buffer: A #CoglFramebuffer object, either onscreen or offscreen. + * + * This redirects all subsequent drawing to the specified framebuffer. This can + * either be an offscreen buffer created with cogl_offscreen_new_to_texture () + * or in the future it may be an onscreen framebuffers too. + * + * Since: 1.2 + * Deprecated: 1.16: The latest drawing apis take explicit + * #CoglFramebuffer arguments so this stack of + * framebuffers shouldn't be used anymore. + */ +COGL_DEPRECATED_IN_1_16 +void +cogl_set_framebuffer (CoglFramebuffer *buffer); + +/** + * cogl_push_framebuffer: (skip) + * @buffer: A #CoglFramebuffer object, either onscreen or offscreen. + * + * Redirects all subsequent drawing to the specified framebuffer. This can + * either be an offscreen buffer created with cogl_offscreen_new_to_texture () + * or in the future it may be an onscreen framebuffer too. + * + * You should understand that a framebuffer owns the following state: + * + * The projection matrix + * The modelview matrix stack + * The viewport + * The clip stack + * + * So these items will automatically be saved and restored when you + * push and pop between different framebuffers. + * + * Also remember a newly allocated framebuffer will have an identity matrix for + * the projection and modelview matrices which gives you a coordinate space + * like OpenGL with (-1, -1) corresponding to the top left of the viewport, + * (1, 1) corresponding to the bottom right and +z coming out towards the + * viewer. + * + * If you want to set up a coordinate space like Clutter does with (0, 0) + * corresponding to the top left and (framebuffer_width, framebuffer_height) + * corresponding to the bottom right you can do so like this: + * + * |[ + * static void + * setup_viewport (unsigned int width, + * unsigned int height, + * float fovy, + * float aspect, + * float z_near, + * float z_far) + * { + * float z_camera; + * CoglMatrix projection_matrix; + * CoglMatrix mv_matrix; + * + * cogl_set_viewport (0, 0, width, height); + * cogl_perspective (fovy, aspect, z_near, z_far); + * + * cogl_get_projection_matrix (&projection_matrix); + * z_camera = 0.5 * projection_matrix.xx; + * + * cogl_matrix_init_identity (&mv_matrix); + * cogl_matrix_translate (&mv_matrix, -0.5f, -0.5f, -z_camera); + * cogl_matrix_scale (&mv_matrix, 1.0f / width, -1.0f / height, 1.0f / width); + * cogl_matrix_translate (&mv_matrix, 0.0f, -1.0 * height, 0.0f); + * cogl_set_modelview_matrix (&mv_matrix); + * } + * + * static void + * my_init_framebuffer (ClutterStage *stage, + * CoglFramebuffer *framebuffer, + * unsigned int framebuffer_width, + * unsigned int framebuffer_height) + * { + * ClutterPerspective perspective; + * + * clutter_stage_get_perspective (stage, &perspective); + * + * cogl_push_framebuffer (framebuffer); + * setup_viewport (framebuffer_width, + * framebuffer_height, + * perspective.fovy, + * perspective.aspect, + * perspective.z_near, + * perspective.z_far); + * } + * ]| + * + * The previous framebuffer can be restored by calling cogl_pop_framebuffer() + * + * Since: 1.2 + * Deprecated: 1.16: The latest drawing apis take explicit + * #CoglFramebuffer arguments so this stack of + * framebuffers shouldn't be used anymore. + */ +COGL_DEPRECATED_IN_1_16 +void +cogl_push_framebuffer (CoglFramebuffer *buffer); + +/** + * cogl_pop_framebuffer: (skip) + * + * Restores the framebuffer that was previously at the top of the stack. + * All subsequent drawing will be redirected to this framebuffer. + * + * Since: 1.2 + * Deprecated: 1.16: The latest drawing apis take explicit + * #CoglFramebuffer arguments so this stack of + * framebuffers shouldn't be used anymore. + */ +COGL_DEPRECATED_IN_1_16 +void +cogl_pop_framebuffer (void); + +/** + * cogl_set_draw_buffer: + * @target: A #CoglBufferTarget that specifies what kind of framebuffer you + * are setting as the render target. + * @offscreen: If you are setting a framebuffer of type COGL_OFFSCREEN_BUFFER + * then this is a CoglHandle for the offscreen buffer. + * + * Redirects all subsequent drawing to the specified framebuffer. This + * can either be an offscreen buffer created with + * cogl_offscreen_new_to_texture () or you can revert to your original + * on screen window buffer. + * + * Deprecated: 1.16: The latest drawing apis take explicit + * #CoglFramebuffer arguments so this stack of + * framebuffers shouldn't be used anymore. + */ +COGL_DEPRECATED_IN_1_16 +void +cogl_set_draw_buffer (CoglBufferTarget target, + CoglHandle offscreen); + +/** + * cogl_push_draw_buffer: + * + * Save cogl_set_draw_buffer() state. + * + * Deprecated: 1.16: The latest drawing apis take explicit + * #CoglFramebuffer arguments so this stack of + * framebuffers shouldn't be used anymore. + */ +COGL_DEPRECATED_IN_1_16 +void +cogl_push_draw_buffer (void); + +/** + * cogl_pop_draw_buffer: + * + * Restore cogl_set_draw_buffer() state. + * + * Deprecated: 1.16: The latest drawing apis take explicit + * #CoglFramebuffer arguments so this stack of + * framebuffers shouldn't be used anymore. + */ +COGL_DEPRECATED_IN_1_16 +void +cogl_pop_draw_buffer (void); + +/** + * cogl_read_pixels: + * @x: The window x position to start reading from + * @y: The window y position to start reading from + * @width: The width of the rectangle you want to read + * @height: The height of the rectangle you want to read + * @source: Identifies which auxillary buffer you want to read + * (only COGL_READ_PIXELS_COLOR_BUFFER supported currently) + * @format: The pixel format you want the result in + * (only COGL_PIXEL_FORMAT_RGBA_8888 supported currently) + * @pixels: The location to write the pixel data. + * + * This reads a rectangle of pixels from the current framebuffer where + * position (0, 0) is the top left. The pixel at (x, y) is the first + * read, and the data is returned with a rowstride of (width * 4). + * + * Currently Cogl assumes that the framebuffer is in a premultiplied + * format so if @format is non-premultiplied it will convert it. To + * read the pixel values without any conversion you should either + * specify a format that doesn't use an alpha channel or use one of + * the formats ending in PRE. + * + * Deprecated: 1.16: Use cogl_framebuffer_read_pixels() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_framebuffer_read_pixels) +void +cogl_read_pixels (int x, + int y, + int width, + int height, + CoglReadPixelsFlags source, + CoglPixelFormat format, + uint8_t *pixels); + + +/* XXX: Since this api was marked unstable, maybe we can just + * remove this api if we can't find anyone is using it. */ +/** + * cogl_framebuffer_get_color_format: (skip) + * @framebuffer: A #CoglFramebuffer framebuffer + * + * Queries the common #CoglPixelFormat of all color buffers attached + * to this framebuffer. For an offscreen framebuffer created with + * cogl_offscreen_new_with_texture() this will correspond to the format + * of the texture. + * + * This API is deprecated because it is missleading to report a + * #CoglPixelFormat for the internal format of the @framebuffer since + * #CoglPixelFormat is such a precise format description and it's + * only the set of components and the premultiplied alpha status + * that is really known. + * + * Since: 1.8 + * Stability: unstable + * Deprecated 1.18: Removed since it is misleading + */ +COGL_DEPRECATED_IN_1_18 +CoglPixelFormat +cogl_framebuffer_get_color_format (CoglFramebuffer *framebuffer); + +COGL_END_DECLS + +#endif /* __COGL_FRAMEBUFFER_DEPRECATED_H__ */ diff --git a/cogl/cogl/deprecated/cogl-material-compat.c b/cogl/cogl/deprecated/cogl-material-compat.c new file mode 100644 index 0000000..3084225 --- /dev/null +++ b/cogl/cogl/deprecated/cogl-material-compat.c @@ -0,0 +1,464 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include +#include +#include +#include +#include +#include + +G_DEFINE_BOXED_TYPE (CoglMaterial, cogl_material, + cogl_object_ref, cogl_object_unref) + +CoglMaterial * +cogl_material_new (void) +{ + _COGL_GET_CONTEXT(ctx, NULL); + return COGL_MATERIAL (cogl_pipeline_new (ctx)); +} + +CoglMaterial * +cogl_material_copy (CoglMaterial *source) +{ + return COGL_MATERIAL (cogl_pipeline_copy (COGL_PIPELINE (source))); +} + +CoglHandle +cogl_material_ref (CoglHandle handle) +{ + return cogl_object_ref (handle); +} + +void +cogl_material_unref (CoglHandle handle) +{ + cogl_object_unref (handle); +} + +CoglBool +cogl_is_material (CoglHandle handle) +{ + return cogl_is_pipeline (handle); +} + +void +cogl_material_set_color (CoglMaterial *material, + const CoglColor *color) +{ + cogl_pipeline_set_color (COGL_PIPELINE (material), color); +} + +void +cogl_material_set_color4ub (CoglMaterial *material, + uint8_t red, + uint8_t green, + uint8_t blue, + uint8_t alpha) +{ + cogl_pipeline_set_color4ub (COGL_PIPELINE (material), + red, green, blue, alpha); +} + +void +cogl_material_set_color4f (CoglMaterial *material, + float red, + float green, + float blue, + float alpha) +{ + cogl_pipeline_set_color4f (COGL_PIPELINE (material), + red, green, blue, alpha); +} + +void +cogl_material_get_color (CoglMaterial *material, + CoglColor *color) +{ + cogl_pipeline_get_color (COGL_PIPELINE (material), color); +} + +void +cogl_material_set_ambient (CoglMaterial *material, + const CoglColor *ambient) +{ + cogl_pipeline_set_ambient (COGL_PIPELINE (material), ambient); +} + +void +cogl_material_get_ambient (CoglMaterial *material, + CoglColor *ambient) +{ + cogl_pipeline_get_ambient (COGL_PIPELINE (material), ambient); +} + +void +cogl_material_set_diffuse (CoglMaterial *material, + const CoglColor *diffuse) +{ + cogl_pipeline_set_diffuse (COGL_PIPELINE (material), diffuse); +} + +void +cogl_material_get_diffuse (CoglMaterial *material, + CoglColor *diffuse) +{ + cogl_pipeline_get_diffuse (COGL_PIPELINE (material), diffuse); +} + +void +cogl_material_set_ambient_and_diffuse (CoglMaterial *material, + const CoglColor *color) +{ + cogl_pipeline_set_ambient_and_diffuse (COGL_PIPELINE (material), color); + +} + +void +cogl_material_set_specular (CoglMaterial *material, + const CoglColor *specular) +{ + cogl_pipeline_set_specular (COGL_PIPELINE (material), specular); +} + +void +cogl_material_get_specular (CoglMaterial *material, + CoglColor *specular) +{ + cogl_pipeline_get_specular (COGL_PIPELINE (material), specular); +} + +void +cogl_material_set_shininess (CoglMaterial *material, + float shininess) +{ + cogl_pipeline_set_shininess (COGL_PIPELINE (material), shininess); +} + +float +cogl_material_get_shininess (CoglMaterial *material) +{ + return cogl_pipeline_get_shininess (COGL_PIPELINE (material)); +} + +void +cogl_material_set_emission (CoglMaterial *material, + const CoglColor *emission) +{ + cogl_pipeline_set_emission (COGL_PIPELINE (material), emission); + +} + +void +cogl_material_get_emission (CoglMaterial *material, + CoglColor *emission) +{ + cogl_pipeline_get_emission (COGL_PIPELINE (material), emission); + +} + +void +cogl_material_set_alpha_test_function (CoglMaterial *material, + CoglMaterialAlphaFunc alpha_func, + float alpha_reference) +{ + cogl_pipeline_set_alpha_test_function (COGL_PIPELINE (material), + alpha_func, + alpha_reference); +} + +CoglBool +cogl_material_set_blend (CoglMaterial *material, + const char *blend_string, + CoglError **error) +{ + return cogl_pipeline_set_blend (COGL_PIPELINE (material), + blend_string, + error); +} + +void +cogl_material_set_blend_constant (CoglMaterial *material, + const CoglColor *constant_color) +{ + cogl_pipeline_set_blend_constant (COGL_PIPELINE (material), constant_color); +} + +void +cogl_material_set_point_size (CoglMaterial *material, + float point_size) +{ + cogl_pipeline_set_point_size (COGL_PIPELINE (material), point_size); +} + +float +cogl_material_get_point_size (CoglMaterial *material) +{ + return cogl_pipeline_get_point_size (COGL_PIPELINE (material)); +} + +CoglHandle +cogl_material_get_user_program (CoglMaterial *material) +{ + return cogl_pipeline_get_user_program (COGL_PIPELINE (material)); +} + +void +cogl_material_set_user_program (CoglMaterial *material, + CoglHandle program) +{ + cogl_pipeline_set_user_program (COGL_PIPELINE (material), program); +} + +void +cogl_material_set_layer (CoglMaterial *material, + int layer_index, + CoglHandle texture) +{ + cogl_pipeline_set_layer_texture (COGL_PIPELINE (material), + layer_index, texture); +} + +void +cogl_material_remove_layer (CoglMaterial *material, + int layer_index) +{ + cogl_pipeline_remove_layer (COGL_PIPELINE (material), layer_index); +} + +CoglBool +cogl_material_set_layer_combine (CoglMaterial *material, + int layer_index, + const char *blend_string, + CoglError **error) +{ + return cogl_pipeline_set_layer_combine (COGL_PIPELINE (material), + layer_index, + blend_string, + error); +} + +void +cogl_material_set_layer_combine_constant (CoglMaterial *material, + int layer_index, + const CoglColor *constant) +{ + cogl_pipeline_set_layer_combine_constant (COGL_PIPELINE (material), + layer_index, + constant); +} + +void +cogl_material_set_layer_matrix (CoglMaterial *material, + int layer_index, + const CoglMatrix *matrix) +{ + cogl_pipeline_set_layer_matrix (COGL_PIPELINE (material), + layer_index, matrix); +} + +const GList * +cogl_material_get_layers (CoglMaterial *material) +{ + return _cogl_pipeline_get_layers (COGL_PIPELINE (material)); +} + +int +cogl_material_get_n_layers (CoglMaterial *material) +{ + return cogl_pipeline_get_n_layers (COGL_PIPELINE (material)); +} + +CoglMaterialLayerType +cogl_material_layer_get_type (CoglMaterialLayer *layer) +{ + return COGL_MATERIAL_LAYER_TYPE_TEXTURE; +} + +CoglHandle +cogl_material_layer_get_texture (CoglMaterialLayer *layer) +{ + return _cogl_pipeline_layer_get_texture (COGL_PIPELINE_LAYER (layer)); +} + +CoglMaterialFilter +cogl_material_layer_get_min_filter (CoglMaterialLayer *layer) +{ + return _cogl_pipeline_layer_get_min_filter (COGL_PIPELINE_LAYER (layer)); +} + +CoglMaterialFilter +cogl_material_layer_get_mag_filter (CoglMaterialLayer *layer) +{ + return _cogl_pipeline_layer_get_mag_filter (COGL_PIPELINE_LAYER (layer)); +} + +void +cogl_material_set_layer_filters (CoglMaterial *material, + int layer_index, + CoglMaterialFilter min_filter, + CoglMaterialFilter mag_filter) +{ + cogl_pipeline_set_layer_filters (COGL_PIPELINE (material), + layer_index, + min_filter, + mag_filter); +} + +CoglBool +cogl_material_set_layer_point_sprite_coords_enabled (CoglMaterial *material, + int layer_index, + CoglBool enable, + CoglError **error) +{ + CoglPipeline *pipeline = COGL_PIPELINE (material); + return cogl_pipeline_set_layer_point_sprite_coords_enabled (pipeline, + layer_index, + enable, + error); +} + +CoglBool +cogl_material_get_layer_point_sprite_coords_enabled (CoglMaterial *material, + int layer_index) +{ + CoglPipeline *pipeline = COGL_PIPELINE (material); + return cogl_pipeline_get_layer_point_sprite_coords_enabled (pipeline, + layer_index); +} + +CoglMaterialWrapMode +cogl_material_get_layer_wrap_mode_s (CoglMaterial *material, + int layer_index) +{ + return cogl_pipeline_get_layer_wrap_mode_s (COGL_PIPELINE (material), + layer_index); +} + +void +cogl_material_set_layer_wrap_mode_s (CoglMaterial *material, + int layer_index, + CoglMaterialWrapMode mode) +{ + cogl_pipeline_set_layer_wrap_mode_s (COGL_PIPELINE (material), layer_index, + mode); +} + +CoglMaterialWrapMode +cogl_material_get_layer_wrap_mode_t (CoglMaterial *material, + int layer_index) +{ + return cogl_pipeline_get_layer_wrap_mode_t (COGL_PIPELINE (material), + layer_index); +} + +void +cogl_material_set_layer_wrap_mode_t (CoglMaterial *material, + int layer_index, + CoglMaterialWrapMode mode) +{ + cogl_pipeline_set_layer_wrap_mode_t (COGL_PIPELINE (material), layer_index, + mode); +} + +CoglMaterialWrapMode +cogl_material_get_layer_wrap_mode_p (CoglMaterial *material, + int layer_index) +{ + return cogl_pipeline_get_layer_wrap_mode_p (COGL_PIPELINE (material), + layer_index); +} + +void +cogl_material_set_layer_wrap_mode_p (CoglMaterial *material, + int layer_index, + CoglMaterialWrapMode mode) +{ + cogl_pipeline_set_layer_wrap_mode_p (COGL_PIPELINE (material), layer_index, + mode); +} + +void +cogl_material_set_layer_wrap_mode (CoglMaterial *material, + int layer_index, + CoglMaterialWrapMode mode) +{ + cogl_pipeline_set_layer_wrap_mode (COGL_PIPELINE (material), layer_index, + mode); +} + +CoglMaterialWrapMode +cogl_material_layer_get_wrap_mode_s (CoglMaterialLayer *layer) +{ + return _cogl_pipeline_layer_get_wrap_mode_s (COGL_PIPELINE_LAYER (layer)); +} + +CoglMaterialWrapMode +cogl_material_layer_get_wrap_mode_t (CoglMaterialLayer *layer) +{ + return _cogl_pipeline_layer_get_wrap_mode_t (COGL_PIPELINE_LAYER (layer)); +} + +CoglMaterialWrapMode +cogl_material_layer_get_wrap_mode_p (CoglMaterialLayer *layer) +{ + return _cogl_pipeline_layer_get_wrap_mode_p (COGL_PIPELINE_LAYER (layer)); +} + +void +cogl_material_foreach_layer (CoglMaterial *material, + CoglMaterialLayerCallback callback, + void *user_data) +{ + cogl_pipeline_foreach_layer (COGL_PIPELINE (material), + (CoglPipelineLayerCallback)callback, user_data); +} + +CoglBool +cogl_material_set_depth_state (CoglMaterial *material, + const CoglDepthState *state, + CoglError **error) +{ + return cogl_pipeline_set_depth_state (COGL_PIPELINE (material), + state, error); +} + +void +cogl_material_get_depth_state (CoglMaterial *material, + CoglDepthState *state_out) +{ + cogl_pipeline_get_depth_state (COGL_PIPELINE (material), state_out); +} + diff --git a/cogl/cogl/deprecated/cogl-material-compat.h b/cogl/cogl/deprecated/cogl-material-compat.h new file mode 100644 index 0000000..97f3e9c --- /dev/null +++ b/cogl/cogl/deprecated/cogl-material-compat.h @@ -0,0 +1,1391 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_MATERIAL_H__ +#define __COGL_MATERIAL_H__ + +#include +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +/** + * SECTION:cogl-material + * @short_description: Fuctions for creating and manipulating materials + * + * COGL allows creating and manipulating materials used to fill in + * geometry. Materials may simply be lighting attributes (such as an + * ambient and diffuse colour) or might represent one or more textures + * blended together. + */ + +typedef struct _CoglMaterial CoglMaterial; +typedef struct _CoglMaterialLayer CoglMaterialLayer; + +#define COGL_TYPE_MATERIAL (cogl_material_get_type ()) +GType cogl_material_get_type (void); + +#define COGL_MATERIAL(OBJECT) ((CoglMaterial *)OBJECT) + +/** + * CoglMaterialFilter: + * @COGL_MATERIAL_FILTER_NEAREST: Measuring in manhatten distance from the, + * current pixel center, use the nearest texture texel + * @COGL_MATERIAL_FILTER_LINEAR: Use the weighted average of the 4 texels + * nearest the current pixel center + * @COGL_MATERIAL_FILTER_NEAREST_MIPMAP_NEAREST: Select the mimap level whose + * texel size most closely matches the current pixel, and use the + * %COGL_MATERIAL_FILTER_NEAREST criterion + * @COGL_MATERIAL_FILTER_LINEAR_MIPMAP_NEAREST: Select the mimap level whose + * texel size most closely matches the current pixel, and use the + * %COGL_MATERIAL_FILTER_LINEAR criterion + * @COGL_MATERIAL_FILTER_NEAREST_MIPMAP_LINEAR: Select the two mimap levels + * whose texel size most closely matches the current pixel, use + * the %COGL_MATERIAL_FILTER_NEAREST criterion on each one and take + * their weighted average + * @COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR: Select the two mimap levels + * whose texel size most closely matches the current pixel, use + * the %COGL_MATERIAL_FILTER_LINEAR criterion on each one and take + * their weighted average + * + * Texture filtering is used whenever the current pixel maps either to more + * than one texture element (texel) or less than one. These filter enums + * correspond to different strategies used to come up with a pixel color, by + * possibly referring to multiple neighbouring texels and taking a weighted + * average or simply using the nearest texel. + */ +typedef enum { + COGL_MATERIAL_FILTER_NEAREST = 0x2600, + COGL_MATERIAL_FILTER_LINEAR = 0x2601, + COGL_MATERIAL_FILTER_NEAREST_MIPMAP_NEAREST = 0x2700, + COGL_MATERIAL_FILTER_LINEAR_MIPMAP_NEAREST = 0x2701, + COGL_MATERIAL_FILTER_NEAREST_MIPMAP_LINEAR = 0x2702, + COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR = 0x2703 +} CoglMaterialFilter; +/* NB: these values come from the equivalents in gl.h */ + +/** + * CoglMaterialWrapMode: + * @COGL_MATERIAL_WRAP_MODE_REPEAT: The texture will be repeated. This + * is useful for example to draw a tiled background. + * @COGL_MATERIAL_WRAP_MODE_CLAMP_TO_EDGE: The coordinates outside the + * range 0→1 will sample copies of the edge pixels of the + * texture. This is useful to avoid artifacts if only one copy of + * the texture is being rendered. + * @COGL_MATERIAL_WRAP_MODE_AUTOMATIC: Cogl will try to automatically + * decide which of the above two to use. For cogl_rectangle(), it + * will use repeat mode if any of the texture coordinates are + * outside the range 0→1, otherwise it will use clamp to edge. For + * cogl_polygon() it will always use repeat mode. For + * cogl_vertex_buffer_draw() it will use repeat mode except for + * layers that have point sprite coordinate generation enabled. This + * is the default value. + * + * The wrap mode specifies what happens when texture coordinates + * outside the range 0→1 are used. Note that if the filter mode is + * anything but %COGL_MATERIAL_FILTER_NEAREST then texels outside the + * range 0→1 might be used even when the coordinate is exactly 0 or 1 + * because OpenGL will try to sample neighbouring pixels. For example + * if you are trying to render the full texture then you may get + * artifacts around the edges when the pixels from the other side are + * merged in if the wrap mode is set to repeat. + * + * Since: 1.4 + */ +/* GL_ALWAYS is just used here as a value that is known not to clash + * with any valid GL wrap modes + * + * XXX: keep the values in sync with the CoglMaterialWrapModeInternal + * enum so no conversion is actually needed. + */ +typedef enum { + COGL_MATERIAL_WRAP_MODE_REPEAT = 0x2901, + COGL_MATERIAL_WRAP_MODE_CLAMP_TO_EDGE = 0x812F, + COGL_MATERIAL_WRAP_MODE_AUTOMATIC = 0x0207 +} CoglMaterialWrapMode; +/* NB: these values come from the equivalents in gl.h */ + +/** + * cogl_material_new: + * + * Allocates and initializes a blank white material + * + * Return value: a pointer to a new #CoglMaterial + * Deprecated: 1.16: Use cogl_pipeline_new() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_new) +CoglMaterial * +cogl_material_new (void); + +/** + * cogl_material_copy: + * @source: a #CoglMaterial object to copy + * + * Creates a new material with the configuration copied from the + * source material. + * + * We would strongly advise developers to always aim to use + * cogl_material_copy() instead of cogl_material_new() whenever there will + * be any similarity between two materials. Copying a material helps Cogl + * keep track of a materials ancestry which we may use to help minimize GPU + * state changes. + * + * Returns: a pointer to the newly allocated #CoglMaterial + * + * Since: 1.2 + * Deprecated: 1.16: Use cogl_pipeline_copy() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_copy) +CoglMaterial * +cogl_material_copy (CoglMaterial *source); + +/** + * cogl_material_ref: + * @material: a #CoglMaterial object. + * + * Increment the reference count for a #CoglMaterial. + * + * Return value: the @material. + * + * Since: 1.0 + * + * Deprecated: 1.2: Use cogl_object_ref() instead + */ +COGL_DEPRECATED +CoglHandle +cogl_material_ref (CoglHandle material); + +/** + * cogl_material_unref: + * @material: a #CoglMaterial object. + * + * Decrement the reference count for a #CoglMaterial. + * + * Since: 1.0 + * + * Deprecated: 1.2: Use cogl_object_unref() instead + */ +COGL_DEPRECATED +void +cogl_material_unref (CoglHandle material); + +/** + * cogl_is_material: + * @handle: A CoglHandle + * + * Gets whether the given handle references an existing material object. + * + * Return value: %TRUE if the handle references a #CoglMaterial, + * %FALSE otherwise + * Deprecated: 1.16: Use cogl_is_pipeline() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_is_pipeline) +CoglBool +cogl_is_material (CoglHandle handle); + +/** + * cogl_material_set_color: + * @material: A #CoglMaterial object + * @color: The components of the color + * + * Sets the basic color of the material, used when no lighting is enabled. + * + * Note that if you don't add any layers to the material then the color + * will be blended unmodified with the destination; the default blend + * expects premultiplied colors: for example, use (0.5, 0.0, 0.0, 0.5) for + * semi-transparent red. See cogl_color_premultiply(). + * + * The default value is (1.0, 1.0, 1.0, 1.0) + * + * Since: 1.0 + * Deprecated: 1.16: Use cogl_pipeline_set_color() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_set_color) +void +cogl_material_set_color (CoglMaterial *material, + const CoglColor *color); + +/** + * cogl_material_set_color4ub: + * @material: A #CoglMaterial object + * @red: The red component + * @green: The green component + * @blue: The blue component + * @alpha: The alpha component + * + * Sets the basic color of the material, used when no lighting is enabled. + * + * The default value is (0xff, 0xff, 0xff, 0xff) + * + * Since: 1.0 + * Deprecated: 1.16: Use cogl_pipeline_set_color4ub() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_set_color4ub) +void +cogl_material_set_color4ub (CoglMaterial *material, + uint8_t red, + uint8_t green, + uint8_t blue, + uint8_t alpha); + +/** + * cogl_material_set_color4f: + * @material: A #CoglMaterial object + * @red: The red component + * @green: The green component + * @blue: The blue component + * @alpha: The alpha component + * + * Sets the basic color of the material, used when no lighting is enabled. + * + * The default value is (1.0, 1.0, 1.0, 1.0) + * + * Since: 1.0 + * Deprecated: 1.16: Use cogl_pipeline_set_color4f() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_set_color4f) +void +cogl_material_set_color4f (CoglMaterial *material, + float red, + float green, + float blue, + float alpha); + +/** + * cogl_material_get_color: + * @material: A #CoglMaterial object + * @color: (out): The location to store the color + * + * Retrieves the current material color. + * + * Since: 1.0 + * Deprecated: 1.16: Use cogl_pipeline_get_color() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_get_color) +void +cogl_material_get_color (CoglMaterial *material, + CoglColor *color); + +/** + * cogl_material_set_ambient: + * @material: A #CoglMaterial object + * @ambient: The components of the desired ambient color + * + * Sets the material's ambient color, in the standard OpenGL lighting + * model. The ambient color affects the overall color of the object. + * + * Since the diffuse color will be intense when the light hits the surface + * directly, the ambient will be most apparent where the light hits at a + * slant. + * + * The default value is (0.2, 0.2, 0.2, 1.0) + * + * Since: 1.0 + * Deprecated: 1.16: Use the #CoglSnippet shader api for lighting + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_material_set_ambient (CoglMaterial *material, + const CoglColor *ambient); + +/** + * cogl_material_get_ambient: + * @material: A #CoglMaterial object + * @ambient: The location to store the ambient color + * + * Retrieves the current ambient color for @material + * + * Since: 1.0 + * Deprecated: 1.16: Use the #CoglSnippet shader api for lighting + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_material_get_ambient (CoglMaterial *material, + CoglColor *ambient); + +/** + * cogl_material_set_diffuse: + * @material: A #CoglMaterial object + * @diffuse: The components of the desired diffuse color + * + * Sets the material's diffuse color, in the standard OpenGL lighting + * model. The diffuse color is most intense where the light hits the + * surface directly - perpendicular to the surface. + * + * The default value is (0.8, 0.8, 0.8, 1.0) + * + * Since: 1.0 + * Deprecated: 1.16: Use the #CoglSnippet shader api for lighting + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_material_set_diffuse (CoglMaterial *material, + const CoglColor *diffuse); + +/** + * cogl_material_get_diffuse: + * @material: A #CoglMaterial object + * @diffuse: The location to store the diffuse color + * + * Retrieves the current diffuse color for @material + * + * Since: 1.0 + * Deprecated: 1.16: Use the #CoglSnippet shader api for lighting + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_material_get_diffuse (CoglMaterial *material, + CoglColor *diffuse); + +/** + * cogl_material_set_ambient_and_diffuse: + * @material: A #CoglMaterial object + * @color: The components of the desired ambient and diffuse colors + * + * Conveniently sets the diffuse and ambient color of @material at the same + * time. See cogl_material_set_ambient() and cogl_material_set_diffuse(). + * + * The default ambient color is (0.2, 0.2, 0.2, 1.0) + * + * The default diffuse color is (0.8, 0.8, 0.8, 1.0) + * + * Since: 1.0 + * Deprecated: 1.16: Use the #CoglSnippet shader api for lighting + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_material_set_ambient_and_diffuse (CoglMaterial *material, + const CoglColor *color); + +/** + * cogl_material_set_specular: + * @material: A #CoglMaterial object + * @specular: The components of the desired specular color + * + * Sets the material's specular color, in the standard OpenGL lighting + * model. The intensity of the specular color depends on the viewport + * position, and is brightest along the lines of reflection. + * + * The default value is (0.0, 0.0, 0.0, 1.0) + * + * Since: 1.0 + * Deprecated: 1.16: Use the #CoglSnippet shader api for lighting + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_material_set_specular (CoglMaterial *material, + const CoglColor *specular); + +/** + * cogl_material_get_specular: + * @material: A #CoglMaterial object + * @specular: The location to store the specular color + * + * Retrieves the materials current specular color. + * + * Since: 1.0 + * Deprecated: 1.16: Use the #CoglSnippet shader api for lighting + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_material_get_specular (CoglMaterial *material, + CoglColor *specular); + +/** + * cogl_material_set_shininess: + * @material: A #CoglMaterial object + * @shininess: The desired shininess; must be >= 0.0 + * + * Sets the shininess of the material, in the standard OpenGL lighting + * model, which determines the size of the specular highlights. A + * higher @shininess will produce smaller highlights which makes the + * object appear more shiny. + * + * The default value is 0.0 + * + * Since: 1.0 + * Deprecated: 1.16: Use the #CoglSnippet shader api for lighting + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_material_set_shininess (CoglMaterial *material, + float shininess); + +/** + * cogl_material_get_shininess: + * @material: A #CoglMaterial object + * + * Retrieves the materials current emission color. + * + * Return value: The materials current shininess value + * + * Since: 1.0 + * Deprecated: 1.16: Use the #CoglSnippet shader api for lighting + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +float +cogl_material_get_shininess (CoglMaterial *material); + +/** + * cogl_material_set_emission: + * @material: A #CoglMaterial object + * @emission: The components of the desired emissive color + * + * Sets the material's emissive color, in the standard OpenGL lighting + * model. It will look like the surface is a light source emitting this + * color. + * + * The default value is (0.0, 0.0, 0.0, 1.0) + * + * Since: 1.0 + * Deprecated: 1.16: Use the #CoglSnippet shader api for lighting + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_material_set_emission (CoglMaterial *material, + const CoglColor *emission); + +/** + * cogl_material_get_emission: + * @material: A #CoglMaterial object + * @emission: The location to store the emission color + * + * Retrieves the materials current emission color. + * + * Since: 1.0 + * Deprecated: 1.16: Use the #CoglSnippet shader api for lighting + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_material_get_emission (CoglMaterial *material, + CoglColor *emission); + +/** + * CoglMaterialAlphaFunc: + * @COGL_MATERIAL_ALPHA_FUNC_NEVER: Never let the fragment through. + * @COGL_MATERIAL_ALPHA_FUNC_LESS: Let the fragment through if the incoming + * alpha value is less than the reference alpha value + * @COGL_MATERIAL_ALPHA_FUNC_EQUAL: Let the fragment through if the incoming + * alpha value equals the reference alpha value + * @COGL_MATERIAL_ALPHA_FUNC_LEQUAL: Let the fragment through if the incoming + * alpha value is less than or equal to the reference alpha value + * @COGL_MATERIAL_ALPHA_FUNC_GREATER: Let the fragment through if the incoming + * alpha value is greater than the reference alpha value + * @COGL_MATERIAL_ALPHA_FUNC_NOTEQUAL: Let the fragment through if the incoming + * alpha value does not equal the reference alpha value + * @COGL_MATERIAL_ALPHA_FUNC_GEQUAL: Let the fragment through if the incoming + * alpha value is greater than or equal to the reference alpha value. + * @COGL_MATERIAL_ALPHA_FUNC_ALWAYS: Always let the fragment through. + * + * Alpha testing happens before blending primitives with the framebuffer and + * gives an opportunity to discard fragments based on a comparison with the + * incoming alpha value and a reference alpha value. The #CoglMaterialAlphaFunc + * determines how the comparison is done. + */ +typedef enum { + COGL_MATERIAL_ALPHA_FUNC_NEVER = 0x0200, + COGL_MATERIAL_ALPHA_FUNC_LESS = 0x0201, + COGL_MATERIAL_ALPHA_FUNC_EQUAL = 0x0202, + COGL_MATERIAL_ALPHA_FUNC_LEQUAL = 0x0203, + COGL_MATERIAL_ALPHA_FUNC_GREATER = 0x0204, + COGL_MATERIAL_ALPHA_FUNC_NOTEQUAL = 0x0205, + COGL_MATERIAL_ALPHA_FUNC_GEQUAL = 0x0206, + COGL_MATERIAL_ALPHA_FUNC_ALWAYS = 0x0207 +} CoglMaterialAlphaFunc; + +/** + * cogl_material_set_alpha_test_function: + * @material: A #CoglMaterial object + * @alpha_func: A @CoglMaterialAlphaFunc constant + * @alpha_reference: A reference point that the chosen alpha function uses + * to compare incoming fragments to. + * + * Before a primitive is blended with the framebuffer, it goes through an + * alpha test stage which lets you discard fragments based on the current + * alpha value. This function lets you change the function used to evaluate + * the alpha channel, and thus determine which fragments are discarded + * and which continue on to the blending stage. + * + * The default is %COGL_MATERIAL_ALPHA_FUNC_ALWAYS + * + * Since: 1.0 + * Deprecated: 1.16: Use cogl_pipeline_set_alpha_test_function() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_set_alpha_test_function) +void +cogl_material_set_alpha_test_function (CoglMaterial *material, + CoglMaterialAlphaFunc alpha_func, + float alpha_reference); + +/** + * cogl_material_set_blend: + * @material: A #CoglMaterial object + * @blend_string: A Cogl blend string + * describing the desired blend function. + * @error: return location for a #CoglError that may report lack of driver + * support if you give separate blend string statements for the alpha + * channel and RGB channels since some drivers, or backends such as + * GLES 1.1, don't support this feature. May be %NULL, in which case a + * warning will be printed out using GLib's logging facilities if an + * error is encountered. + * + * If not already familiar; please refer here + * for an overview of what blend strings are, and their syntax. + * + * Blending occurs after the alpha test function, and combines fragments with + * the framebuffer. + + * Currently the only blend function Cogl exposes is ADD(). So any valid + * blend statements will be of the form: + * + * |[ + * <channel-mask>=ADD(SRC_COLOR*(<factor>), DST_COLOR*(<factor>)) + * ]| + * + * The brackets around blend factors are currently not + * optional! + * + * This is the list of source-names usable as blend factors: + * + * SRC_COLOR: The color of the in comming fragment + * DST_COLOR: The color of the framebuffer + * CONSTANT: The constant set via cogl_material_set_blend_constant() + * + * + * The source names can be used according to the + * color-source and factor syntax, + * so for example "(1-SRC_COLOR[A])" would be a valid factor, as would + * "(CONSTANT[RGB])" + * + * These can also be used as factors: + * + * 0: (0, 0, 0, 0) + * 1: (1, 1, 1, 1) + * SRC_ALPHA_SATURATE_FACTOR: (f,f,f,1) where f = MIN(SRC_COLOR[A],1-DST_COLOR[A]) + * + * + * Remember; all color components are normalized to the range [0, 1] + * before computing the result of blending. + * + * + * Blend Strings/1 + * Blend a non-premultiplied source over a destination with + * premultiplied alpha: + * + * "RGB = ADD(SRC_COLOR*(SRC_COLOR[A]), DST_COLOR*(1-SRC_COLOR[A]))" + * "A = ADD(SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))" + * + * + * + * + * Blend Strings/2 + * Blend a premultiplied source over a destination with + * premultiplied alpha + * + * "RGBA = ADD(SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))" + * + * + * + * The default blend string is: + * |[ + * RGBA = ADD (SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A])) + * ]| + * + * That gives normal alpha-blending when the calculated color for the material + * is in premultiplied form. + * + * Return value: %TRUE if the blend string was successfully parsed, and the + * described blending is supported by the underlying driver/hardware. If + * there was an error, %FALSE is returned and @error is set accordingly (if + * present). + * + * Since: 1.0 + * Deprecated: 1.16: Use cogl_pipeline_set_blend() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_set_blend) +CoglBool +cogl_material_set_blend (CoglMaterial *material, + const char *blend_string, + CoglError **error); + +/** + * cogl_material_set_blend_constant: + * @material: A #CoglMaterial object + * @constant_color: The constant color you want + * + * When blending is setup to reference a CONSTANT blend factor then + * blending will depend on the constant set with this function. + * + * Since: 1.0 + * Deprecated: 1.16: Use cogl_pipeline_set_blend_constant() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_set_blend_constant) +void +cogl_material_set_blend_constant (CoglMaterial *material, + const CoglColor *constant_color); + +/** + * cogl_material_set_point_size: + * @material: a material. + * @point_size: the new point size. + * + * Changes the size of points drawn when %COGL_VERTICES_MODE_POINTS is + * used with the vertex buffer API. Note that typically the GPU will + * only support a limited minimum and maximum range of point sizes. If + * the chosen point size is outside that range then the nearest value + * within that range will be used instead. The size of a point is in + * screen space so it will be the same regardless of any + * transformations. The default point size is 1.0. + * + * Since: 1.4 + * Deprecated: 1.16: Use cogl_pipeline_set_point_size() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_set_point_size) +void +cogl_material_set_point_size (CoglMaterial *material, + float point_size); + +/** + * cogl_material_get_point_size: + * @material: a #CoglHandle to a material. + * + * Get the size of points drawn when %COGL_VERTICES_MODE_POINTS is + * used with the vertex buffer API. + * + * Return value: the point size of the material. + * + * Since: 1.4 + * Deprecated: 1.16: Use cogl_pipeline_get_point_size() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_get_point_size) +float +cogl_material_get_point_size (CoglMaterial *material); + +/** + * cogl_material_get_user_program: + * @material: a #CoglMaterial object. + * + * Queries what user program has been associated with the given + * @material using cogl_material_set_user_program(). + * + * Return value: (transfer none): The current user program + * or %COGL_INVALID_HANDLE. + * + * Since: 1.4 + * Deprecated: 1.16: Use #CoglSnippet api instead instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +CoglHandle +cogl_material_get_user_program (CoglMaterial *material); + +/** + * cogl_material_set_user_program: + * @material: a #CoglMaterial object. + * @program: A #CoglHandle to a linked CoglProgram + * + * Associates a linked CoglProgram with the given material so that the + * program can take full control of vertex and/or fragment processing. + * + * This is an example of how it can be used to associate an ARBfp + * program with a #CoglMaterial: + * |[ + * CoglHandle shader; + * CoglHandle program; + * CoglMaterial *material; + * + * shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT); + * cogl_shader_source (shader, + * "!!ARBfp1.0\n" + * "MOV result.color,fragment.color;\n" + * "END\n"); + * cogl_shader_compile (shader); + * + * program = cogl_create_program (); + * cogl_program_attach_shader (program, shader); + * cogl_program_link (program); + * + * material = cogl_material_new (); + * cogl_material_set_user_program (material, program); + * + * cogl_set_source_color4ub (0xff, 0x00, 0x00, 0xff); + * cogl_rectangle (0, 0, 100, 100); + * ]| + * + * It is possibly worth keeping in mind that this API is not part of + * the long term design for how we want to expose shaders to Cogl + * developers (We are planning on deprecating the cogl_program and + * cogl_shader APIs in favour of a "snippet" framework) but in the + * meantime we hope this will handle most practical GLSL and ARBfp + * requirements. + * + * Also remember you need to check for either the + * %COGL_FEATURE_SHADERS_GLSL or %COGL_FEATURE_SHADERS_ARBFP before + * using the cogl_program or cogl_shader API. + * + * Since: 1.4 + * Deprecated: 1.16: Use #CoglSnippet api instead instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_material_set_user_program (CoglMaterial *material, + CoglHandle program); + +/** + * cogl_material_set_layer: + * @material: A #CoglMaterial object + * @layer_index: the index of the layer + * @texture: a #CoglHandle for the layer object + * + * In addition to the standard OpenGL lighting model a Cogl material may have + * one or more layers comprised of textures that can be blended together in + * order, with a number of different texture combine modes. This function + * defines a new texture layer. + * + * The index values of multiple layers do not have to be consecutive; it is + * only their relative order that is important. + * + * In the future, we may define other types of material layers, such + * as purely GLSL based layers. + * + * Since: 1.0 + * Deprecated: 1.16: Use cogl_pipeline_set_layer() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_set_layer) +void +cogl_material_set_layer (CoglMaterial *material, + int layer_index, + CoglHandle texture); + +/** + * cogl_material_remove_layer: + * @material: A #CoglMaterial object + * @layer_index: Specifies the layer you want to remove + * + * This function removes a layer from your material + * Deprecated: 1.16: Use cogl_pipeline_remove_layer() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_remove_layer) +void +cogl_material_remove_layer (CoglMaterial *material, + int layer_index); + + +/** + * cogl_material_set_layer_combine: + * @material: A #CoglMaterial object + * @layer_index: Specifies the layer you want define a combine function for + * @blend_string: A Cogl blend string + * describing the desired texture combine function. + * @error: A #CoglError that may report parse errors or lack of GPU/driver + * support. May be %NULL, in which case a warning will be printed out if an + * error is encountered. + * + * If not already familiar; you can refer + * here for an overview of what blend + * strings are and there syntax. + * + * These are all the functions available for texture combining: + * + * REPLACE(arg0) = arg0 + * MODULATE(arg0, arg1) = arg0 x arg1 + * ADD(arg0, arg1) = arg0 + arg1 + * ADD_SIGNED(arg0, arg1) = arg0 + arg1 - 0.5 + * INTERPOLATE(arg0, arg1, arg2) = arg0 x arg2 + arg1 x (1 - arg2) + * SUBTRACT(arg0, arg1) = arg0 - arg1 + * + * + * DOT3_RGB(arg0, arg1) = 4 x ((arg0[R] - 0.5)) * (arg1[R] - 0.5) + + * (arg0[G] - 0.5)) * (arg1[G] - 0.5) + + * (arg0[B] - 0.5)) * (arg1[B] - 0.5)) + * + * + * + * + * DOT3_RGBA(arg0, arg1) = 4 x ((arg0[R] - 0.5)) * (arg1[R] - 0.5) + + * (arg0[G] - 0.5)) * (arg1[G] - 0.5) + + * (arg0[B] - 0.5)) * (arg1[B] - 0.5)) + * + * + * + * + * Refer to the + * color-source syntax for + * describing the arguments. The valid source names for texture combining + * are: + * + * + * TEXTURE + * Use the color from the current texture layer + * + * + * TEXTURE_0, TEXTURE_1, etc + * Use the color from the specified texture layer + * + * + * CONSTANT + * Use the color from the constant given with + * cogl_material_set_layer_constant() + * + * + * PRIMARY + * Use the color of the material as set with + * cogl_material_set_color() + * + * + * 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() + * + * + * + * + * Layer Combine Examples + * This is effectively what the default blending is: + * + * RGBA = MODULATE (PREVIOUS, TEXTURE) + * + * 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. + * + * RGBA = INTERPOLATE (PREVIOUS, TEXTURE, CONSTANT[A]) + * + * + * + * You can't give a multiplication factor for arguments as you can + * with blending. + * + * Return value: %TRUE if the blend string was successfully parsed, and the + * described texture combining is supported by the underlying driver and + * or hardware. On failure, %FALSE is returned and @error is set + * + * Since: 1.0 + * Deprecated: 1.16: Use cogl_pipeline_set_layer_combine() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_set_layer_combine) +CoglBool +cogl_material_set_layer_combine (CoglMaterial *material, + int layer_index, + const char *blend_string, + CoglError **error); + +/** + * cogl_material_set_layer_combine_constant: + * @material: A #CoglMaterial object + * @layer_index: Specifies the layer you want to specify a constant used + * for texture combining + * @constant: The constant color you want + * + * When you are using the 'CONSTANT' color source in a layer combine + * description then you can use this function to define its value. + * + * Since: 1.0 + * Deprecated: 1.16: Use cogl_pipeline_set_layer_combine_constant() + * instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_set_layer_combine_constant) +void +cogl_material_set_layer_combine_constant (CoglMaterial *material, + int layer_index, + const CoglColor *constant); + +/** + * cogl_material_set_layer_matrix: + * @material: A #CoglMaterial object + * @layer_index: the index for the layer inside @material + * @matrix: the transformation matrix for the layer + * + * This function lets you set a matrix that can be used to e.g. translate + * and rotate a single layer of a material used to fill your geometry. + * Deprecated: 1.16: Use cogl_pipeline_set_layer_matrix() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_set_layer_matrix) +void +cogl_material_set_layer_matrix (CoglMaterial *material, + int layer_index, + const CoglMatrix *matrix); + +/** + * cogl_material_get_layers: + * @material: A #CoglMaterial object + * + * This function lets you access a material's internal list of layers + * for iteration. + * + * You should avoid using this API if possible since it was only + * made public by mistake and will be deprecated when we have + * suitable alternative. + * + * It's important to understand that the list returned may not + * remain valid if you modify the material or any of the layers in any + * way and so you would have to re-get the list in that + * situation. + * + * Return value: (element-type CoglMaterialLayer) (transfer none): A + * list of #CoglMaterialLayer's that can be passed to the + * cogl_material_layer_* functions. The list is owned by Cogl and it + * should not be modified or freed + * Deprecated: 1.16: Use cogl_pipeline_get_layers() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_get_layers) +const GList * +cogl_material_get_layers (CoglMaterial *material); + +/** + * cogl_material_get_n_layers: + * @material: A #CoglMaterial object + * + * Retrieves the number of layers defined for the given @material + * + * Return value: the number of layers + * + * Since: 1.0 + * Deprecated: 1.16: Use cogl_pipeline_get_n_layers() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_get_n_layers) +int +cogl_material_get_n_layers (CoglMaterial *material); + +/** + * CoglMaterialLayerType: + * @COGL_MATERIAL_LAYER_TYPE_TEXTURE: The layer represents a + * texture + * + * Available types of layers for a #CoglMaterial. This enumeration + * might be expanded in later versions. + * + * Since: 1.0 + */ +typedef enum { + COGL_MATERIAL_LAYER_TYPE_TEXTURE +} CoglMaterialLayerType; + + +/** + * cogl_material_layer_get_type: + * @layer: A #CoglMaterialLayer object + * + * Retrieves the type of the layer + * + * Currently there is only one type of layer defined: + * %COGL_MATERIAL_LAYER_TYPE_TEXTURE, but considering we may add purely GLSL + * based layers in the future, you should write code that checks the type + * first. + * + * Return value: the type of the layer + * Deprecated: 1.16: No replacement + */ +COGL_DEPRECATED_IN_1_16 +CoglMaterialLayerType +cogl_material_layer_get_type (CoglMaterialLayer *layer); + +/** + * cogl_material_layer_get_texture: + * @layer: A #CoglMaterialLayer object + * + * Extracts a texture handle for a specific layer. + * + * In the future Cogl may support purely GLSL based layers; for those + * layers this function which will likely return %COGL_INVALID_HANDLE if you + * try to get the texture handle from them. Considering this scenario, you + * should call cogl_material_layer_get_type() first in order check it is of + * type %COGL_MATERIAL_LAYER_TYPE_TEXTURE before calling this function. + * + * Return value: (transfer none): a #CoglHandle for the texture inside the layer + * Deprecated: 1.16: No replacement + */ +COGL_DEPRECATED_IN_1_16 +CoglHandle +cogl_material_layer_get_texture (CoglMaterialLayer *layer); + +/** + * cogl_material_layer_get_min_filter: + * @layer: a #CoglHandle for a material layer + * + * Queries the currently set downscaling filter for a material layer + * + * Return value: the current downscaling filter + * Deprecated: 1.16: No replacement + */ +COGL_DEPRECATED_IN_1_16 +CoglMaterialFilter +cogl_material_layer_get_min_filter (CoglMaterialLayer *layer); + +/** + * cogl_material_layer_get_mag_filter: + * @layer: A #CoglMaterialLayer object + * + * Queries the currently set downscaling filter for a material later + * + * Return value: the current downscaling filter + * Deprecated: 1.16: No replacement + */ +COGL_DEPRECATED_IN_1_16 +CoglMaterialFilter +cogl_material_layer_get_mag_filter (CoglMaterialLayer *layer); + +/** + * cogl_material_set_layer_filters: + * @material: A #CoglMaterial object + * @layer_index: the layer number to change. + * @min_filter: the filter used when scaling a texture down. + * @mag_filter: the filter used when magnifying a texture. + * + * Changes the decimation and interpolation filters used when a texture is + * drawn at other scales than 100%. + * Deprecated: 1.16: Use cogl_pipeline_set_layer_filters() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_set_layer_filters) +void +cogl_material_set_layer_filters (CoglMaterial *material, + int layer_index, + CoglMaterialFilter min_filter, + CoglMaterialFilter mag_filter); + +/** + * cogl_material_set_layer_point_sprite_coords_enabled: + * @material: a #CoglHandle to a material. + * @layer_index: the layer number to change. + * @enable: whether to enable point sprite coord generation. + * @error: A return location for a CoglError, or NULL to ignore errors. + * + * When rendering points, if @enable is %TRUE then the texture + * coordinates for this layer will be replaced with coordinates that + * vary from 0.0 to 1.0 across the primitive. The top left of the + * point will have the coordinates 0.0,0.0 and the bottom right will + * have 1.0,1.0. If @enable is %FALSE then the coordinates will be + * fixed for the entire point. + * + * This function will only work if %COGL_FEATURE_POINT_SPRITE is + * available. If the feature is not available then the function will + * return %FALSE and set @error. + * + * Return value: %TRUE if the function succeeds, %FALSE otherwise. + * Since: 1.4 + * Deprecated: 1.16: Use cogl_pipeline_set_layer_point_sprite_coords_enabled() + * instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_set_layer_point_sprite_coords_enabled) +CoglBool +cogl_material_set_layer_point_sprite_coords_enabled (CoglMaterial *material, + int layer_index, + CoglBool enable, + CoglError **error); + +/** + * cogl_material_get_layer_point_sprite_coords_enabled: + * @material: a #CoglHandle to a material. + * @layer_index: the layer number to check. + * + * Gets whether point sprite coordinate generation is enabled for this + * texture layer. + * + * Return value: whether the texture coordinates will be replaced with + * point sprite coordinates. + * + * Since: 1.4 + * Deprecated: 1.16: Use cogl_pipeline_get_layer_point_sprite_coords_enabled() + * instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_get_layer_point_sprite_coords_enabled) +CoglBool +cogl_material_get_layer_point_sprite_coords_enabled (CoglMaterial *material, + int layer_index); + +/** + * cogl_material_get_layer_wrap_mode_s: + * @material: A #CoglMaterial object + * @layer_index: the layer number to change. + * + * Returns the wrap mode for the 's' coordinate of texture lookups on this + * layer. + * + * Return value: the wrap mode for the 's' coordinate of texture lookups on + * this layer. + * + * Since: 1.6 + * Deprecated: 1.16: Use cogl_pipeline_get_layer_wrap_mode_s() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_get_layer_wrap_mode_s) +CoglMaterialWrapMode +cogl_material_get_layer_wrap_mode_s (CoglMaterial *material, + int layer_index); + +/** + * cogl_material_set_layer_wrap_mode_s: + * @material: A #CoglMaterial object + * @layer_index: the layer number to change. + * @mode: the new wrap mode + * + * Sets the wrap mode for the 's' coordinate of texture lookups on this layer. + * + * Since: 1.4 + * Deprecated: 1.16: Use cogl_pipeline_set_layer_wrap_mode_s() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_set_layer_wrap_mode_s) +void +cogl_material_set_layer_wrap_mode_s (CoglMaterial *material, + int layer_index, + CoglMaterialWrapMode mode); + +/** + * cogl_material_get_layer_wrap_mode_t: + * @material: A #CoglMaterial object + * @layer_index: the layer number to change. + * + * Returns the wrap mode for the 't' coordinate of texture lookups on this + * layer. + * + * Return value: the wrap mode for the 't' coordinate of texture lookups on + * this layer. + * + * Since: 1.6 + * Deprecated: 1.16: Use cogl_pipeline_get_layer_wrap_mode_t() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_get_layer_wrap_mode_t) +CoglMaterialWrapMode +cogl_material_get_layer_wrap_mode_t (CoglMaterial *material, + int layer_index); + + +/** + * cogl_material_set_layer_wrap_mode_t: + * @material: A #CoglMaterial object + * @layer_index: the layer number to change. + * @mode: the new wrap mode + * + * Sets the wrap mode for the 't' coordinate of texture lookups on this layer. + * + * Since: 1.4 + * Deprecated: 1.16: Use cogl_pipeline_set_layer_wrap_mode_t() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_set_layer_wrap_mode_t) +void +cogl_material_set_layer_wrap_mode_t (CoglMaterial *material, + int layer_index, + CoglMaterialWrapMode mode); + +/** + * cogl_material_get_layer_wrap_mode_p: + * @material: A #CoglMaterial object + * @layer_index: the layer number to change. + * + * Returns the wrap mode for the 'p' coordinate of texture lookups on this + * layer. + * + * Return value: the wrap mode for the 'p' coordinate of texture lookups on + * this layer. + * + * Since: 1.6 + * Deprecated: 1.16: Use cogl_pipeline_get_layer_wrap_mode_p() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_get_layer_wrap_mode_p) +CoglMaterialWrapMode +cogl_material_get_layer_wrap_mode_p (CoglMaterial *material, + int layer_index); + +/** + * cogl_material_set_layer_wrap_mode_p: + * @material: A #CoglMaterial object + * @layer_index: the layer number to change. + * @mode: the new wrap mode + * + * Sets the wrap mode for the 'p' coordinate of texture lookups on + * this layer. 'p' is the third coordinate. + * + * Since: 1.4 + * Deprecated: 1.16: Use cogl_pipeline_set_layer_wrap_mode_p() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_set_layer_wrap_mode_p) +void +cogl_material_set_layer_wrap_mode_p (CoglMaterial *material, + int layer_index, + CoglMaterialWrapMode mode); + +/** + * cogl_material_set_layer_wrap_mode: + * @material: A #CoglMaterial object + * @layer_index: the layer number to change. + * @mode: the new wrap mode + * + * Sets the wrap mode for all three coordinates of texture lookups on + * this layer. This is equivalent to calling + * cogl_material_set_layer_wrap_mode_s(), + * cogl_material_set_layer_wrap_mode_t() and + * cogl_material_set_layer_wrap_mode_p() separately. + * + * Since: 1.4 + * Deprecated: 1.16: Use cogl_pipeline_set_layer_wrap_mode() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_set_layer_wrap_mode) +void +cogl_material_set_layer_wrap_mode (CoglMaterial *material, + int layer_index, + CoglMaterialWrapMode mode); + +/** + * cogl_material_layer_get_wrap_mode_s: + * @layer: A #CoglMaterialLayer object + * + * Gets the wrap mode for the 's' coordinate of texture lookups on this layer. + * + * Return value: the wrap mode value for the s coordinate. + * + * Since: 1.4 + * Deprecated: 1.16: Use cogl_pipeline_layer_get_wrap_mode_s() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_layer_get_wrap_mode_s) +CoglMaterialWrapMode +cogl_material_layer_get_wrap_mode_s (CoglMaterialLayer *layer); + +/** + * cogl_material_layer_get_wrap_mode_t: + * @layer: A #CoglMaterialLayer object + * + * Gets the wrap mode for the 't' coordinate of texture lookups on this layer. + * + * Return value: the wrap mode value for the t coordinate. + * + * Since: 1.4 + * Deprecated: 1.16: Use cogl_pipeline_layer_get_wrap_mode_t() instead + */ + +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_layer_get_wrap_mode_t) +CoglMaterialWrapMode +cogl_material_layer_get_wrap_mode_t (CoglMaterialLayer *layer); + +/** + * cogl_material_layer_get_wrap_mode_p: + * @layer: A #CoglMaterialLayer object + * + * Gets the wrap mode for the 'p' coordinate of texture lookups on + * this layer. 'p' is the third coordinate. + * + * Return value: the wrap mode value for the p coordinate. + * + * Since: 1.4 + * Deprecated: 1.16: Use cogl_pipeline_layer_get_wrap_mode_p() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_layer_get_wrap_mode_p) +CoglMaterialWrapMode +cogl_material_layer_get_wrap_mode_p (CoglMaterialLayer *layer); + +/** + * cogl_material_set_depth_state: (skip) + * @material: A #CoglMaterial object + * @state: A #CoglDepthState struct + * @error: A #CoglError to report failures to setup the given @state. + * + * This commits all the depth state configured in @state struct to the + * given @material. The configuration values are copied into the + * material so there is no requirement to keep the #CoglDepthState + * struct around if you don't need it any more. + * + * Note: Since some platforms do not support the depth range feature + * it is possible for this function to fail and report an @error. + * + * Returns: TRUE if the GPU supports all the given @state else %FALSE + * and returns an @error. + * + * Since: 1.8 + * Stability: Unstable + * Deprecated: 1.16: Use cogl_pipeline_set_depth_state() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_set_depth_state) +CoglBool +cogl_material_set_depth_state (CoglMaterial *material, + const CoglDepthState *state, + CoglError **error); + +/** + * cogl_material_get_depth_state: (skip) + * @material: A #CoglMaterial object + * @state_out: A destination #CoglDepthState struct + * + * Retrieves the current depth state configuration for the given + * @pipeline as previously set using cogl_pipeline_set_depth_state(). + * + * Since: 2.0 + * Stability: Unstable + * Deprecated: 1.16: Use cogl_pipeline_get_depth_state() instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_pipeline_get_depth_state) +void +cogl_material_get_depth_state (CoglMaterial *material, + CoglDepthState *state_out); + +/** + * CoglMaterialLayerCallback: + * @material: The #CoglMaterial whos layers are being iterated + * @layer_index: The current layer index + * @user_data: The private data passed to cogl_material_foreach_layer() + * + * The callback prototype used with cogl_material_foreach_layer() for + * iterating all the layers of a @material. + * + * Since: 1.4 + * Stability: Unstable + * Deprecated: 1.16 + */ +typedef CoglBool (*CoglMaterialLayerCallback) (CoglMaterial *material, + int layer_index, + void *user_data); + +/** + * cogl_material_foreach_layer: + * @material: A #CoglMaterial object + * @callback: (scope call): A #CoglMaterialLayerCallback to be called for each + * layer index + * @user_data: Private data that will be passed to the callback + * + * Iterates all the layer indices of the given @material. + * + * Since: 1.4 + * Stability: Unstable + * Deprecated: 1.16: No replacement + */ +COGL_DEPRECATED_IN_1_16 +void +cogl_material_foreach_layer (CoglMaterial *material, + CoglMaterialLayerCallback callback, + void *user_data); + +G_END_DECLS + +#endif /* __COGL_MATERIAL_H__ */ diff --git a/cogl/cogl/deprecated/cogl-program-private.h b/cogl/cogl/deprecated/cogl-program-private.h new file mode 100644 index 0000000..64ed72c --- /dev/null +++ b/cogl/cogl/deprecated/cogl-program-private.h @@ -0,0 +1,88 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_PROGRAM_H +#define __COGL_PROGRAM_H + +#include "cogl-object-private.h" +#include "cogl-shader-private.h" + +typedef struct _CoglProgram CoglProgram; + +struct _CoglProgram +{ + CoglHandleObject _parent; + + GSList *attached_shaders; + + GArray *custom_uniforms; + + /* An age counter that changes whenever the list of shaders is modified */ + unsigned int age; +}; + +typedef struct _CoglProgramUniform CoglProgramUniform; + +struct _CoglProgramUniform +{ + char *name; + CoglBoxedValue value; + /* The cached GL location for this uniform. This is only valid + between calls to _cogl_program_dirty_all_uniforms */ + GLint location; + /* Whether we have a location yet */ + unsigned int location_valid : 1; + /* Whether the uniform value has changed since the last time the + uniforms were flushed */ + unsigned int dirty : 1; +}; + +/* Internal function to flush the custom uniforms for the given use + program. This assumes the target GL program is already bound. The + gl_program still needs to be passed so that CoglProgram can query + the uniform locations. gl_program_changed should be set to TRUE if + we are flushing the uniforms against a different GL program from + the last time it was flushed. This will cause it to requery all of + the locations and assume that all uniforms are dirty */ +void +_cogl_program_flush_uniforms (CoglProgram *program, + GLuint gl_program, + CoglBool gl_program_changed); + +CoglShaderLanguage +_cogl_program_get_language (CoglHandle handle); + +CoglBool +_cogl_program_has_fragment_shader (CoglHandle handle); + +CoglBool +_cogl_program_has_vertex_shader (CoglHandle handle); + +#endif /* __COGL_PROGRAM_H */ diff --git a/cogl/cogl/deprecated/cogl-program.c b/cogl/cogl/deprecated/cogl-program.c new file mode 100644 index 0000000..fbf4f2c --- /dev/null +++ b/cogl/cogl/deprecated/cogl-program.c @@ -0,0 +1,503 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + + +#include "cogl-util.h" +#include "cogl-util-gl-private.h" +#include "cogl-context-private.h" +#include "cogl-object-private.h" + +#include "cogl-shader-private.h" +#include "cogl-program-private.h" + +#include + +static void _cogl_program_free (CoglProgram *program); + +COGL_HANDLE_DEFINE (Program, program); +COGL_OBJECT_DEFINE_DEPRECATED_REF_COUNTING (program); + +/* A CoglProgram is effectively just a list of shaders that will be + used together and a set of values for the custom uniforms. No + actual GL program is created - instead this is the responsibility + of the GLSL material backend. The uniform values are collected in + an array and then flushed whenever the material backend requests + it. */ + +static void +_cogl_program_free (CoglProgram *program) +{ + int i; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + /* Unref all of the attached shaders */ + g_slist_foreach (program->attached_shaders, (GFunc) cogl_handle_unref, NULL); + /* Destroy the list */ + g_slist_free (program->attached_shaders); + + for (i = 0; i < program->custom_uniforms->len; i++) + { + CoglProgramUniform *uniform = + &g_array_index (program->custom_uniforms, CoglProgramUniform, i); + + g_free (uniform->name); + + if (uniform->value.count > 1) + g_free (uniform->value.v.array); + } + + g_array_free (program->custom_uniforms, TRUE); + + g_slice_free (CoglProgram, program); +} + +CoglHandle +cogl_create_program (void) +{ + CoglProgram *program; + + program = g_slice_new0 (CoglProgram); + + program->custom_uniforms = + g_array_new (FALSE, FALSE, sizeof (CoglProgramUniform)); + program->age = 0; + + return _cogl_program_handle_new (program); +} + +void +cogl_program_attach_shader (CoglHandle program_handle, + CoglHandle shader_handle) +{ + CoglProgram *program; + CoglShader *shader; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (!cogl_is_program (program_handle) || !cogl_is_shader (shader_handle)) + return; + + program = program_handle; + shader = shader_handle; + + /* Only one shader is allowed if the type is ARBfp */ + if (shader->language == COGL_SHADER_LANGUAGE_ARBFP) + _COGL_RETURN_IF_FAIL (program->attached_shaders == NULL); + else if (shader->language == COGL_SHADER_LANGUAGE_GLSL) + _COGL_RETURN_IF_FAIL (_cogl_program_get_language (program) == + COGL_SHADER_LANGUAGE_GLSL); + + program->attached_shaders + = g_slist_prepend (program->attached_shaders, + cogl_handle_ref (shader_handle)); + + program->age++; +} + +void +cogl_program_link (CoglHandle handle) +{ + /* There's no point in linking the program here because it will have + to be relinked with a different fixed functionality shader + whenever the settings change */ +} + +void +cogl_program_use (CoglHandle handle) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + _COGL_RETURN_IF_FAIL (handle == COGL_INVALID_HANDLE || + cogl_is_program (handle)); + + if (ctx->current_program == 0 && handle != 0) + ctx->legacy_state_set++; + else if (handle == 0 && ctx->current_program != 0) + ctx->legacy_state_set--; + + if (handle != COGL_INVALID_HANDLE) + cogl_handle_ref (handle); + if (ctx->current_program != COGL_INVALID_HANDLE) + cogl_handle_unref (ctx->current_program); + ctx->current_program = handle; +} + +int +cogl_program_get_uniform_location (CoglHandle handle, + const char *uniform_name) +{ + int i; + CoglProgram *program; + CoglProgramUniform *uniform; + + if (!cogl_is_program (handle)) + return -1; + + program = handle; + + /* We can't just ask the GL program object for the uniform location + directly because it will change every time the program is linked + with a different shader. Instead we make our own mapping of + uniform numbers and cache the names */ + for (i = 0; i < program->custom_uniforms->len; i++) + { + uniform = &g_array_index (program->custom_uniforms, + CoglProgramUniform, i); + + if (!strcmp (uniform->name, uniform_name)) + return i; + } + + /* Create a new uniform with the given name */ + g_array_set_size (program->custom_uniforms, + program->custom_uniforms->len + 1); + uniform = &g_array_index (program->custom_uniforms, + CoglProgramUniform, + program->custom_uniforms->len - 1); + + uniform->name = g_strdup (uniform_name); + memset (&uniform->value, 0, sizeof (CoglBoxedValue)); + uniform->dirty = TRUE; + uniform->location_valid = FALSE; + + return program->custom_uniforms->len - 1; +} + +static CoglProgramUniform * +cogl_program_modify_uniform (CoglProgram *program, + int uniform_no) +{ + CoglProgramUniform *uniform; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_program (program), NULL); + _COGL_RETURN_VAL_IF_FAIL (uniform_no >= 0 && + uniform_no < program->custom_uniforms->len, + NULL); + + uniform = &g_array_index (program->custom_uniforms, + CoglProgramUniform, uniform_no); + uniform->dirty = TRUE; + + return uniform; +} + +void +cogl_program_uniform_1f (int uniform_no, + float value) +{ + CoglProgramUniform *uniform; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + uniform = cogl_program_modify_uniform (ctx->current_program, uniform_no); + _cogl_boxed_value_set_1f (&uniform->value, value); +} + +void +cogl_program_set_uniform_1f (CoglHandle handle, + int uniform_location, + float value) +{ + CoglProgramUniform *uniform; + + uniform = cogl_program_modify_uniform (handle, uniform_location); + _cogl_boxed_value_set_1f (&uniform->value, value); +} + +void +cogl_program_uniform_1i (int uniform_no, + int value) +{ + CoglProgramUniform *uniform; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + uniform = cogl_program_modify_uniform (ctx->current_program, uniform_no); + _cogl_boxed_value_set_1i (&uniform->value, value); +} + +void +cogl_program_set_uniform_1i (CoglHandle handle, + int uniform_location, + int value) +{ + CoglProgramUniform *uniform; + + uniform = cogl_program_modify_uniform (handle, uniform_location); + _cogl_boxed_value_set_1i (&uniform->value, value); +} + +void +cogl_program_uniform_float (int uniform_no, + int size, + int count, + const float *value) +{ + CoglProgramUniform *uniform; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + uniform = cogl_program_modify_uniform (ctx->current_program, uniform_no); + _cogl_boxed_value_set_float (&uniform->value, size, count, value); +} + +void +cogl_program_set_uniform_float (CoglHandle handle, + int uniform_location, + int n_components, + int count, + const float *value) +{ + CoglProgramUniform *uniform; + + uniform = cogl_program_modify_uniform (handle, uniform_location); + _cogl_boxed_value_set_float (&uniform->value, n_components, count, value); +} + +void +cogl_program_uniform_int (int uniform_no, + int size, + int count, + const int *value) +{ + CoglProgramUniform *uniform; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + uniform = cogl_program_modify_uniform (ctx->current_program, uniform_no); + _cogl_boxed_value_set_int (&uniform->value, size, count, value); +} + +void +cogl_program_set_uniform_int (CoglHandle handle, + int uniform_location, + int n_components, + int count, + const int *value) +{ + CoglProgramUniform *uniform; + + uniform = cogl_program_modify_uniform (handle, uniform_location); + _cogl_boxed_value_set_int (&uniform->value, n_components, count, value); +} + +void +cogl_program_set_uniform_matrix (CoglHandle handle, + int uniform_location, + int dimensions, + int count, + CoglBool transpose, + const float *value) +{ + CoglProgramUniform *uniform; + + uniform = cogl_program_modify_uniform (handle, uniform_location); + _cogl_boxed_value_set_matrix (&uniform->value, + dimensions, + count, + transpose, + value); +} + +void +cogl_program_uniform_matrix (int uniform_no, + int size, + int count, + CoglBool transpose, + const float *value) +{ + CoglProgramUniform *uniform; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + uniform = cogl_program_modify_uniform (ctx->current_program, uniform_no); + _cogl_boxed_value_set_matrix (&uniform->value, size, count, transpose, value); +} + +/* ARBfp local parameters can be referenced like: + * + * "program.local[5]" + * ^14char offset (after whitespace is stripped) + */ +static int +get_local_param_index (const char *uniform_name) +{ + char *input = g_strdup (uniform_name); + int i; + char *p = input; + char *endptr; + int _index; + + for (i = 0; input[i] != '\0'; i++) + if (input[i] != '_' && input[i] != '\t') + *p++ = input[i]; + input[i] = '\0'; + + _COGL_RETURN_VAL_IF_FAIL (strncmp ("program.local[", input, 14) == 0, -1); + + _index = g_ascii_strtoull (input + 14, &endptr, 10); + _COGL_RETURN_VAL_IF_FAIL (endptr != input + 14, -1); + _COGL_RETURN_VAL_IF_FAIL (*endptr == ']', -1); + + _COGL_RETURN_VAL_IF_FAIL (_index >= 0, -1); + + g_free (input); + + return _index; +} + +#ifdef HAVE_COGL_GL + +static void +_cogl_program_flush_uniform_arbfp (GLint location, + CoglBoxedValue *value) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (value->type != COGL_BOXED_NONE) + { + _COGL_RETURN_IF_FAIL (value->type == COGL_BOXED_FLOAT); + _COGL_RETURN_IF_FAIL (value->size == 4); + _COGL_RETURN_IF_FAIL (value->count == 1); + + GE( ctx, glProgramLocalParameter4fv (GL_FRAGMENT_PROGRAM_ARB, location, + value->v.float_value) ); + } +} + +#endif /* HAVE_COGL_GL */ + +void +_cogl_program_flush_uniforms (CoglProgram *program, + GLuint gl_program, + CoglBool gl_program_changed) +{ + CoglProgramUniform *uniform; + int i; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + _COGL_RETURN_IF_FAIL (ctx->driver != COGL_DRIVER_GLES1); + + for (i = 0; i < program->custom_uniforms->len; i++) + { + uniform = &g_array_index (program->custom_uniforms, + CoglProgramUniform, i); + + if (gl_program_changed || uniform->dirty) + { + if (gl_program_changed || !uniform->location_valid) + { + if (_cogl_program_get_language (program) == + COGL_SHADER_LANGUAGE_GLSL) + uniform->location = + ctx->glGetUniformLocation (gl_program, uniform->name); + else + uniform->location = + get_local_param_index (uniform->name); + + uniform->location_valid = TRUE; + } + + /* If the uniform isn't really in the program then there's + no need to actually set it */ + if (uniform->location != -1) + { + switch (_cogl_program_get_language (program)) + { + case COGL_SHADER_LANGUAGE_GLSL: + _cogl_boxed_value_set_uniform (ctx, + uniform->location, + &uniform->value); + break; + + case COGL_SHADER_LANGUAGE_ARBFP: +#ifdef HAVE_COGL_GL + _cogl_program_flush_uniform_arbfp (uniform->location, + &uniform->value); +#endif + break; + } + } + + uniform->dirty = FALSE; + } + } +} + +CoglShaderLanguage +_cogl_program_get_language (CoglHandle handle) +{ + CoglProgram *program = handle; + + /* Use the language of the first shader */ + + if (program->attached_shaders) + { + CoglShader *shader = program->attached_shaders->data; + return shader->language; + } + else + return COGL_SHADER_LANGUAGE_GLSL; +} + +static CoglBool +_cogl_program_has_shader_type (CoglProgram *program, + CoglShaderType type) +{ + GSList *l; + + for (l = program->attached_shaders; l; l = l->next) + { + CoglShader *shader = l->data; + + if (shader->type == type) + return TRUE; + } + + return FALSE; +} + +CoglBool +_cogl_program_has_fragment_shader (CoglHandle handle) +{ + return _cogl_program_has_shader_type (handle, COGL_SHADER_TYPE_FRAGMENT); +} + +CoglBool +_cogl_program_has_vertex_shader (CoglHandle handle) +{ + return _cogl_program_has_shader_type (handle, COGL_SHADER_TYPE_VERTEX); +} diff --git a/cogl/cogl/deprecated/cogl-shader-private.h b/cogl/cogl/deprecated/cogl-shader-private.h new file mode 100644 index 0000000..dcc16b9 --- /dev/null +++ b/cogl/cogl/deprecated/cogl-shader-private.h @@ -0,0 +1,72 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_SHADER_H +#define __COGL_SHADER_H + +#include "cogl-object-private.h" +#include "cogl-shader.h" +#include "cogl-gl-header.h" +#include "cogl-pipeline.h" + +typedef struct _CoglShader CoglShader; + +typedef enum +{ + COGL_SHADER_LANGUAGE_GLSL, + COGL_SHADER_LANGUAGE_ARBFP +} CoglShaderLanguage; + +struct _CoglShader +{ + CoglHandleObject _parent; + GLuint gl_handle; + CoglPipeline *compilation_pipeline; + CoglShaderType type; + CoglShaderLanguage language; + char *source; +}; + +void +_cogl_shader_compile_real (CoglHandle handle, + CoglPipeline *pipeline); + +CoglShaderLanguage +_cogl_program_get_language (CoglHandle handle); + +void +_cogl_shader_set_source_with_boilerplate (GLuint shader_gl_handle, + GLenum shader_gl_type, + int n_tex_coord_attribs, + GLsizei count_in, + const char **strings_in, + const GLint *lengths_in); + +#endif /* __COGL_SHADER_H */ diff --git a/cogl/cogl/deprecated/cogl-shader.c b/cogl/cogl/deprecated/cogl-shader.c new file mode 100644 index 0000000..4a2af04 --- /dev/null +++ b/cogl/cogl/deprecated/cogl-shader.c @@ -0,0 +1,376 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-shader-private.h" +#include "cogl-util-gl-private.h" +#include "cogl-context-private.h" +#include "cogl-object-private.h" +#include "cogl-glsl-shader-private.h" +#include "cogl-glsl-shader-boilerplate.h" + +#include + +#include + +static void _cogl_shader_free (CoglShader *shader); + +COGL_HANDLE_DEFINE (Shader, shader); +COGL_OBJECT_DEFINE_DEPRECATED_REF_COUNTING (shader); + +#ifndef GL_FRAGMENT_SHADER +#define GL_FRAGMENT_SHADER 0x8B30 +#endif +#ifndef GL_VERTEX_SHADER +#define GL_VERTEX_SHADER 0x8B31 +#endif + +static void +_cogl_shader_free (CoglShader *shader) +{ + /* Frees shader resources but its handle is not + released! Do that separately before this! */ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + +#ifdef HAVE_COGL_GL + if (shader->language == COGL_SHADER_LANGUAGE_ARBFP) + { + if (shader->gl_handle) + GE (ctx, glDeletePrograms (1, &shader->gl_handle)); + } + else +#endif + if (shader->gl_handle) + GE (ctx, glDeleteShader (shader->gl_handle)); + + g_slice_free (CoglShader, shader); +} + +CoglHandle +cogl_create_shader (CoglShaderType type) +{ + CoglShader *shader; + + _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE); + + switch (type) + { + case COGL_SHADER_TYPE_VERTEX: + case COGL_SHADER_TYPE_FRAGMENT: + break; + default: + g_warning ("Unexpected shader type (0x%08lX) given to " + "cogl_create_shader", (unsigned long) type); + return COGL_INVALID_HANDLE; + } + + shader = g_slice_new (CoglShader); + shader->language = COGL_SHADER_LANGUAGE_GLSL; + shader->gl_handle = 0; + shader->compilation_pipeline = NULL; + shader->type = type; + + return _cogl_shader_handle_new (shader); +} + +static void +delete_shader (CoglShader *shader) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + +#ifdef HAVE_COGL_GL + if (shader->language == COGL_SHADER_LANGUAGE_ARBFP) + { + if (shader->gl_handle) + GE (ctx, glDeletePrograms (1, &shader->gl_handle)); + } + else +#endif + { + if (shader->gl_handle) + GE (ctx, glDeleteShader (shader->gl_handle)); + } + + shader->gl_handle = 0; + + if (shader->compilation_pipeline) + { + cogl_object_unref (shader->compilation_pipeline); + shader->compilation_pipeline = NULL; + } +} + +void +cogl_shader_source (CoglHandle handle, + const char *source) +{ + CoglShader *shader; + CoglShaderLanguage language; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (!cogl_is_shader (handle)) + return; + + shader = handle; + +#ifdef HAVE_COGL_GL + if (strncmp (source, "!!ARBfp1.0", 10) == 0) + language = COGL_SHADER_LANGUAGE_ARBFP; + else +#endif + language = COGL_SHADER_LANGUAGE_GLSL; + + /* Delete the old object if the language is changing... */ + if (G_UNLIKELY (language != shader->language) && + shader->gl_handle) + delete_shader (shader); + + shader->source = g_strdup (source); + + shader->language = language; +} + +void +cogl_shader_compile (CoglHandle handle) +{ + CoglShader *shader; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (!cogl_is_shader (handle)) + return; + +#ifdef HAVE_COGL_GL + shader = handle; + if (shader->language == COGL_SHADER_LANGUAGE_ARBFP) + _cogl_shader_compile_real (handle, NULL); +#endif + + /* XXX: For GLSL we don't actually compile anything until the shader + * gets used so we have an opportunity to add some boilerplate to + * the shader. + * + * At the end of the day this is obviously a badly designed API + * given that we are having to lie to the user. It was a mistake to + * so thinly wrap the OpenGL shader API and the current plan is to + * replace it with a pipeline snippets API. */ +} + +void +_cogl_shader_compile_real (CoglHandle handle, + CoglPipeline *pipeline) +{ + CoglShader *shader = handle; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + +#ifdef HAVE_COGL_GL + if (shader->language == COGL_SHADER_LANGUAGE_ARBFP) + { +#ifdef COGL_GL_DEBUG + GLenum gl_error; +#endif + + if (shader->gl_handle) + return; + + GE (ctx, glGenPrograms (1, &shader->gl_handle)); + + GE (ctx, glBindProgram (GL_FRAGMENT_PROGRAM_ARB, shader->gl_handle)); + + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SHOW_SOURCE))) + g_message ("user ARBfp program:\n%s", shader->source); + +#ifdef COGL_GL_DEBUG + _cogl_gl_util_clear_gl_errors (ctx); +#endif + ctx->glProgramString (GL_FRAGMENT_PROGRAM_ARB, + GL_PROGRAM_FORMAT_ASCII_ARB, + strlen (shader->source), + shader->source); +#ifdef COGL_GL_DEBUG + gl_error = _cogl_gl_util_get_error (ctx); + if (gl_error != GL_NO_ERROR) + { + g_warning ("%s: GL error (%d): Failed to compile ARBfp:\n%s\n%s", + G_STRLOC, + gl_error, + shader->source, + ctx->glGetString (GL_PROGRAM_ERROR_STRING_ARB)); + } +#endif + } + else +#endif + { + GLenum gl_type; + GLint status; + + if (shader->gl_handle) + { + CoglPipeline *prev = shader->compilation_pipeline; + + /* XXX: currently the only things that will affect the + * boilerplate for user shaders, apart from driver features, + * are the pipeline layer-indices and texture-unit-indices + */ + if (pipeline == prev || + _cogl_pipeline_layer_and_unit_numbers_equal (prev, pipeline)) + return; + } + + if (shader->gl_handle) + delete_shader (shader); + + switch (shader->type) + { + case COGL_SHADER_TYPE_VERTEX: + gl_type = GL_VERTEX_SHADER; + break; + case COGL_SHADER_TYPE_FRAGMENT: + gl_type = GL_FRAGMENT_SHADER; + break; + default: + g_assert_not_reached (); + break; + } + + shader->gl_handle = ctx->glCreateShader (gl_type); + + _cogl_glsl_shader_set_source_with_boilerplate (ctx, + shader->gl_handle, + gl_type, + pipeline, + 1, + (const char **) + &shader->source, + NULL); + + GE (ctx, glCompileShader (shader->gl_handle)); + + shader->compilation_pipeline = cogl_object_ref (pipeline); + + GE (ctx, glGetShaderiv (shader->gl_handle, GL_COMPILE_STATUS, &status)); + if (!status) + { + char buffer[512]; + int len = 0; + + ctx->glGetShaderInfoLog (shader->gl_handle, 511, &len, buffer); + buffer[len] = '\0'; + + g_warning ("Failed to compile GLSL program:\n" + "src:\n%s\n" + "error:\n%s\n", + shader->source, + buffer); + } + } +} + +char * +cogl_shader_get_info_log (CoglHandle handle) +{ + if (!cogl_is_shader (handle)) + return NULL; + + /* XXX: This API doesn't really do anything! + * + * This API is purely for compatibility + * + * The reason we don't do anything is because a shader needs to + * be associated with a CoglPipeline for Cogl to be able to + * compile and link anything. + * + * The way this API was originally designed as a very thin wrapper + * over the GL api was a mistake and it's now very difficult to + * make the API work in a meaningful way given how the rest of Cogl + * has evolved. + * + * The CoglShader API is mostly deprecated by CoglSnippets and so + * these days we do the bare minimum to support the existing users + * of it until they are able to migrate to the snippets api. + */ + + return g_strdup (""); +} + +CoglShaderType +cogl_shader_get_type (CoglHandle handle) +{ + CoglShader *shader; + + _COGL_GET_CONTEXT (ctx, COGL_SHADER_TYPE_VERTEX); + + if (!cogl_is_shader (handle)) + { + g_warning ("Non shader handle type passed to cogl_shader_get_type"); + return COGL_SHADER_TYPE_VERTEX; + } + + shader = handle; + return shader->type; +} + +CoglBool +cogl_shader_is_compiled (CoglHandle handle) +{ +#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES2) + if (!cogl_is_shader (handle)) + return FALSE; + + /* XXX: This API doesn't really do anything! + * + * This API is purely for compatibility and blatantly lies to the + * user about whether their shader has been compiled. + * + * I suppose we could say we're stretching the definition of + * "compile" and are deferring any related errors to be "linker" + * errors. + * + * The reason we don't do anything is because a shader needs to + * be associated with a CoglPipeline for Cogl to be able to + * compile and link anything. + * + * The CoglShader API is mostly deprecated by CoglSnippets and so + * these days we do the bare minimum to support the existing users + * of it until they are able to migrate to the snippets api. + */ + + return TRUE; + +#else + return FALSE; +#endif +} diff --git a/cogl/cogl/deprecated/cogl-shader.h b/cogl/cogl/deprecated/cogl-shader.h new file mode 100644 index 0000000..d4b22e7 --- /dev/null +++ b/cogl/cogl/deprecated/cogl-shader.h @@ -0,0 +1,703 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_SHADER_H__ +#define __COGL_SHADER_H__ + +#include +#include +#include + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-shaders + * @short_description: Fuctions for accessing the programmable GL pipeline + * + * Cogl allows accessing the GL programmable pipeline in order to create + * vertex and fragment shaders. + * + * The shader source code can either be GLSL or ARBfp. If the source + * code is ARBfp, it must begin with the string “!!ARBfp1.0”. The + * application should check for the %COGL_FEATURE_SHADERS_GLSL or + * %COGL_FEATURE_SHADERS_ARBFP features before using shaders. + * + * When using GLSL Cogl provides replacement names for most of the + * builtin varyings and uniforms. It is recommended to use these names + * wherever possible to increase portability between OpenGL 2.0 and + * GLES 2.0. GLES 2.0 does not have most of the builtins under their + * original names so they will only work with the Cogl names. + * + * For use in all GLSL shaders, the Cogl builtins are as follows: + * + * + * + * + * uniform mat4 + * cogl_modelview_matrix + * + * The current modelview matrix. This is equivalent to + * #gl_ModelViewMatrix. + * + * + * + * uniform mat4 + * cogl_projection_matrix + * + * The current projection matrix. This is equivalent to + * #gl_ProjectionMatrix. + * + * + * + * uniform mat4 + * cogl_modelview_projection_matrix + * + * The combined modelview and projection matrix. A vertex shader + * would typically use this to transform the incoming vertex + * position. The separate modelview and projection matrices are + * usually only needed for lighting calculations. This is + * equivalent to #gl_ModelViewProjectionMatrix. + * + * + * + * uniform mat4 + * cogl_texture_matrix[] + * + * An array of matrices for transforming the texture + * coordinates. This is equivalent to #gl_TextureMatrix. + * + * + * + * + * + * In a vertex shader, the following are also available: + * + * + * + * + * attribute vec4 + * cogl_position_in + * + * The incoming vertex position. This is equivalent to #gl_Vertex. + * + * + * + * attribute vec4 + * cogl_color_in + * + * The incoming vertex color. This is equivalent to #gl_Color. + * + * + * + * attribute vec4 + * cogl_tex_coord_in + * + * The texture coordinate for the first texture unit. This is + * equivalent to #gl_MultiTexCoord0. + * + * + * + * attribute vec4 + * cogl_tex_coord0_in + * + * The texture coordinate for the first texture unit. This is + * equivalent to #gl_MultiTexCoord0. There is also + * #cogl_tex_coord1_in and so on. + * + * + * + * attribute vec3 + * cogl_normal_in + * + * The normal of the vertex. This is equivalent to #gl_Normal. + * + * + * + * vec4 + * cogl_position_out + * + * The calculated position of the vertex. This must be written to + * in all vertex shaders. This is equivalent to #gl_Position. + * + * + * + * float + * cogl_point_size_out + * + * The calculated size of a point. This is equivalent to #gl_PointSize. + * + * + * + * varying vec4 + * cogl_color_out + * + * The calculated color of a vertex. This is equivalent to #gl_FrontColor. + * + * + * + * varying vec4 + * cogl_tex_coord_out[] + * + * An array of calculated texture coordinates for a vertex. This is + * equivalent to #gl_TexCoord. + * + * + * + * + * + * In a fragment shader, the following are also available: + * + * + * + * + * varying vec4 cogl_color_in + * + * The calculated color of a vertex. This is equivalent to #gl_FrontColor. + * + * + * + * varying vec4 + * cogl_tex_coord_in[] + * + * An array of calculated texture coordinates for a vertex. This is + * equivalent to #gl_TexCoord. + * + * + * + * vec4 cogl_color_out + * + * The final calculated color of the fragment. All fragment shaders + * must write to this variable. This is equivalent to + * #gl_FrontColor. + * + * + * + * float cogl_depth_out + * + * An optional output variable specifying the depth value to use + * for this fragment. This is equivalent to #gl_FragDepth. + * + * + * + * bool cogl_front_facing + * + * A readonly variable that will be true if the current primitive + * is front facing. This can be used to implement two-sided + * coloring algorithms. This is equivalent to #gl_FrontFacing. + * + * + * + * + * + * It's worth nothing that this API isn't what Cogl would like to have + * in the long term and it may be removed in Cogl 2.0. The + * experimental #CoglShader API is the proposed replacement. + */ + +/** + * CoglShaderType: + * @COGL_SHADER_TYPE_VERTEX: A program for proccessing vertices + * @COGL_SHADER_TYPE_FRAGMENT: A program for processing fragments + * + * Types of shaders + * + * Since: 1.0 + */ +typedef enum { + COGL_SHADER_TYPE_VERTEX, + COGL_SHADER_TYPE_FRAGMENT +} CoglShaderType; + +/** + * cogl_create_shader: + * @shader_type: COGL_SHADER_TYPE_VERTEX or COGL_SHADER_TYPE_FRAGMENT. + * + * Create a new shader handle, use cogl_shader_source() to set the + * source code to be used on it. + * + * Returns: a new shader handle. + * Deprecated: 1.16: Use #CoglSnippet api + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +CoglHandle +cogl_create_shader (CoglShaderType shader_type); + +/** + * cogl_shader_ref: + * @handle: A #CoglHandle to a shader. + * + * Add an extra reference to a shader. + * + * Returns: @handle + * Deprecated: 1.16: Use #CoglSnippet api + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +CoglHandle +cogl_shader_ref (CoglHandle handle); + +/** + * cogl_shader_unref: + * @handle: A #CoglHandle to a shader. + * + * Removes a reference to a shader. If it was the last reference the + * shader object will be destroyed. + * + * Deprecated: 1.16: Use #CoglSnippet api + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_shader_unref (CoglHandle handle); + +/** + * cogl_is_shader: + * @handle: A CoglHandle + * + * Gets whether the given handle references an existing shader object. + * + * Returns: %TRUE if the handle references a shader, + * %FALSE otherwise + * Deprecated: 1.16: Use #CoglSnippet api + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +CoglBool +cogl_is_shader (CoglHandle handle); + +/** + * cogl_shader_source: + * @shader: #CoglHandle for a shader. + * @source: Shader source. + * + * Replaces the current source associated with a shader with a new + * one. + * + * Please see above + * for a description of the recommended format for the shader code. + * Deprecated: 1.16: Use #CoglSnippet api + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_shader_source (CoglHandle shader, + const char *source); + +/** + * cogl_shader_compile: + * @handle: #CoglHandle for a shader. + * + * Compiles the shader, no return value, but the shader is now ready + * for linking into a program. Note that calling this function is + * optional. If it is not called then the shader will be automatically + * compiled when it is linked. + * Deprecated: 1.16: Use #CoglSnippet api + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_shader_compile (CoglHandle handle); + +/** + * cogl_shader_get_info_log: + * @handle: #CoglHandle for a shader. + * + * Retrieves the information log for a coglobject, can be used in conjunction + * with cogl_shader_get_parameteriv() to retrieve the compiler warnings/error + * messages that caused a shader to not compile correctly, mainly useful for + * debugging purposes. + * + * Return value: a newly allocated string containing the info log. Use + * g_free() to free it + * Deprecated: 1.16: Use #CoglSnippet api + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +char * +cogl_shader_get_info_log (CoglHandle handle); + +/** + * cogl_shader_get_type: + * @handle: #CoglHandle for a shader. + * + * Retrieves the type of a shader #CoglHandle + * + * Return value: %COGL_SHADER_TYPE_VERTEX if the shader is a vertex processor + * or %COGL_SHADER_TYPE_FRAGMENT if the shader is a frament processor + * Deprecated: 1.16: Use #CoglSnippet api + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +CoglShaderType +cogl_shader_get_type (CoglHandle handle); + +/** + * cogl_shader_is_compiled: + * @handle: #CoglHandle for a shader. + * + * Retrieves whether a shader #CoglHandle has been compiled + * + * Return value: %TRUE if the shader object has sucessfully be compiled + * Deprecated: 1.16: Use #CoglSnippet api + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +CoglBool +cogl_shader_is_compiled (CoglHandle handle); + +/** + * cogl_create_program: + * + * Create a new cogl program object that can be used to replace parts of the GL + * rendering pipeline with custom code. + * + * Returns: a new cogl program. + * Deprecated: 1.16: Use #CoglSnippet api + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +CoglHandle +cogl_create_program (void); + +/** + * cogl_program_ref: + * @handle: A #CoglHandle to a program. + * + * Add an extra reference to a program. + * + * Deprecated: 1.0: Please use cogl_object_ref() instead. + * + * Returns: @handle + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +CoglHandle +cogl_program_ref (CoglHandle handle); + +/** + * cogl_program_unref: + * @handle: A #CoglHandle to a program. + * + * Removes a reference to a program. If it was the last reference the + * program object will be destroyed. + * + * Deprecated: 1.0: Please use cogl_object_unref() instead. + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_program_unref (CoglHandle handle); + +/** + * cogl_is_program: + * @handle: A CoglHandle + * + * Gets whether the given handle references an existing program object. + * + * Returns: %TRUE if the handle references a program, + * %FALSE otherwise + * + * Deprecated: 1.16: Use #CoglSnippet api + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +CoglBool +cogl_is_program (CoglHandle handle); + +/** + * cogl_program_attach_shader: + * @program_handle: a #CoglHandle for a shdaer program. + * @shader_handle: a #CoglHandle for a vertex of fragment shader. + * + * Attaches a shader to a program object. A program can have multiple + * vertex or fragment shaders but only one of them may provide a + * main() function. It is allowed to use a program with only a vertex + * shader or only a fragment shader. + * + * Deprecated: 1.16: Use #CoglSnippet api + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_program_attach_shader (CoglHandle program_handle, + CoglHandle shader_handle); + +/** + * cogl_program_link: + * @handle: a #CoglHandle for a shader program. + * + * Links a program making it ready for use. Note that calling this + * function is optional. If it is not called the program will + * automatically be linked the first time it is used. + * + * Deprecated: 1.16: Use #CoglSnippet api + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_program_link (CoglHandle handle); + +/** + * cogl_program_use: + * @handle: a #CoglHandle for a shader program or %COGL_INVALID_HANDLE. + * + * Activate a specific shader program replacing that part of the GL + * rendering pipeline, if passed in %COGL_INVALID_HANDLE the default + * behavior of GL is reinstated. + * + * This function affects the global state of the current Cogl + * context. It is much more efficient to attach the shader to a + * specific material used for rendering instead by calling + * cogl_material_set_user_program(). + * + * Deprecated: 1.16: Use #CoglSnippet api + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_program_use (CoglHandle handle); + +/** + * cogl_program_get_uniform_location: + * @handle: a #CoglHandle for a shader program. + * @uniform_name: the name of a uniform. + * + * Retrieve the location (offset) of a uniform variable in a shader program, + * a uniform is a variable that is constant for all vertices/fragments for a + * shader object and is possible to modify as an external parameter. + * + * Return value: the offset of a uniform in a specified program. + * This uniform can be set using cogl_program_uniform_1f() when the + * program is in use. + * Deprecated: 1.16: Use #CoglSnippet api instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +int +cogl_program_get_uniform_location (CoglHandle handle, + const char *uniform_name); + +/** + * cogl_program_set_uniform_1f: + * @program: A #CoglHandle for a linked program + * @uniform_location: the uniform location retrieved from + * cogl_program_get_uniform_location(). + * @value: the new value of the uniform. + * + * Changes the value of a floating point uniform for the given linked + * @program. + * + * Since: 1.4 + * Deprecated: 1.16: Use #CoglSnippet api instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_program_set_uniform_1f (CoglHandle program, + int uniform_location, + float value); + +/** + * cogl_program_set_uniform_1i: + * @program: A #CoglHandle for a linked program + * @uniform_location: the uniform location retrieved from + * cogl_program_get_uniform_location(). + * @value: the new value of the uniform. + * + * Changes the value of an integer uniform for the given linked + * @program. + * + * Since: 1.4 + * Deprecated: 1.16: Use #CoglSnippet api instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_program_set_uniform_1i (CoglHandle program, + int uniform_location, + int value); + +/** + * cogl_program_set_uniform_float: + * @program: A #CoglHandle for a linked program + * @uniform_location: the uniform location retrieved from + * cogl_program_get_uniform_location(). + * @n_components: The number of components for the uniform. For + * example with glsl you'd use 3 for a vec3 or 4 for a vec4. + * @count: For uniform arrays this is the array length otherwise just + * pass 1 + * @value: (array length=count): the new value of the uniform[s]. + * + * Changes the value of a float vector uniform, or uniform array for + * the given linked @program. + * + * Since: 1.4 + * Deprecated: 1.16: Use #CoglSnippet api instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_program_set_uniform_float (CoglHandle program, + int uniform_location, + int n_components, + int count, + const float *value); + +/** + * cogl_program_set_uniform_int: + * @program: A #CoglHandle for a linked program + * @uniform_location: the uniform location retrieved from + * cogl_program_get_uniform_location(). + * @n_components: The number of components for the uniform. For + * example with glsl you'd use 3 for a vec3 or 4 for a vec4. + * @count: For uniform arrays this is the array length otherwise just + * pass 1 + * @value: (array length=count): the new value of the uniform[s]. + * + * Changes the value of a int vector uniform, or uniform array for + * the given linked @program. + * + * Since: 1.4 + * Deprecated: 1.16: Use #CoglSnippet api instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_program_set_uniform_int (CoglHandle program, + int uniform_location, + int n_components, + int count, + const int *value); + +/** + * cogl_program_set_uniform_matrix: + * @program: A #CoglHandle for a linked program + * @uniform_location: the uniform location retrieved from + * cogl_program_get_uniform_location(). + * @dimensions: The dimensions of the matrix. So for for example pass + * 2 for a 2x2 matrix or 3 for 3x3. + * @count: For uniform arrays this is the array length otherwise just + * pass 1 + * @transpose: Whether to transpose the matrix when setting the uniform. + * @value: (array length=count): the new value of the uniform. + * + * Changes the value of a matrix uniform, or uniform array in the + * given linked @program. + * + * Since: 1.4 + * Deprecated: 1.16: Use #CoglSnippet api instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_program_set_uniform_matrix (CoglHandle program, + int uniform_location, + int dimensions, + int count, + CoglBool transpose, + const float *value); + +/** + * cogl_program_uniform_1f: + * @uniform_no: the uniform to set. + * @value: the new value of the uniform. + * + * Changes the value of a floating point uniform in the currently + * used (see cogl_program_use()) shader program. + * + * Deprecated: 1.16: Use #CoglSnippet api + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_program_uniform_1f (int uniform_no, + float value); + +/** + * cogl_program_uniform_1i: + * @uniform_no: the uniform to set. + * @value: the new value of the uniform. + * + * Changes the value of an integer uniform in the currently + * used (see cogl_program_use()) shader program. + * + * Deprecated: 1.16: Use #CoglSnippet api + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_program_uniform_1i (int uniform_no, + int value); + +/** + * cogl_program_uniform_float: + * @uniform_no: the uniform to set. + * @size: Size of float vector. + * @count: Size of array of uniforms. + * @value: (array length=count): the new value of the uniform. + * + * Changes the value of a float vector uniform, or uniform array in the + * currently used (see cogl_program_use()) shader program. + * + * Deprecated: 1.16: Use #CoglSnippet api + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_program_uniform_float (int uniform_no, + int size, + int count, + const float *value); + +/** + * cogl_program_uniform_int: + * @uniform_no: the uniform to set. + * @size: Size of int vector. + * @count: Size of array of uniforms. + * @value: (array length=count): the new value of the uniform. + * + * Changes the value of a int vector uniform, or uniform array in the + * currently used (see cogl_program_use()) shader program. + * + * Deprecated: 1.16: Use #CoglSnippet api + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_program_uniform_int (int uniform_no, + int size, + int count, + const int *value); + +/** + * cogl_program_uniform_matrix: + * @uniform_no: the uniform to set. + * @size: Size of matrix. + * @count: Size of array of uniforms. + * @transpose: Whether to transpose the matrix when setting the uniform. + * @value: (array length=count): the new value of the uniform. + * + * Changes the value of a matrix uniform, or uniform array in the + * currently used (see cogl_program_use()) shader program. The @size + * parameter is used to determine the square size of the matrix. + * + * Deprecated: 1.16: Use #CoglSnippet api + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_snippet_) +void +cogl_program_uniform_matrix (int uniform_no, + int size, + int count, + CoglBool transpose, + const float *value); + +COGL_END_DECLS + +#endif /* __COGL_SHADER_H__ */ diff --git a/cogl/cogl/deprecated/cogl-type-casts.h b/cogl/cogl/deprecated/cogl-type-casts.h new file mode 100644 index 0000000..c35ea05 --- /dev/null +++ b/cogl/cogl/deprecated/cogl-type-casts.h @@ -0,0 +1,55 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_TYPE_CASTS_H__ +#define __COGL_TYPE_CASTS_H__ + +/* The various interface types in Cogl used to be more strongly typed + * which required lots type casting by developers. We provided + * macros for performing these casts following a widely used Gnome + * coding style. Since we now consistently typedef these interfaces + * as void for the public C api and use runtime type checking to + * catch programming errors the casts have become redundant and + * so these macros are only kept for compatibility... + */ + +#if !defined(COGL_ENABLE_MUTTER_API) && !defined(COGL_GIR_SCANNING) +#define COGL_FRAMEBUFFER(X) (X) +#define COGL_BUFFER(X) (X) +#define COGL_TEXTURE(X) (X) +#define COGL_META_TEXTURE(X) (X) +#define COGL_PRIMITIVE_TEXTURE(X) (X) +#endif + +#endif /* __COGL_TYPE_CASTS_H__ */ diff --git a/cogl/cogl/deprecated/cogl-vertex-buffer-private.h b/cogl/cogl/deprecated/cogl-vertex-buffer-private.h new file mode 100644 index 0000000..f803bbb --- /dev/null +++ b/cogl/cogl/deprecated/cogl-vertex-buffer-private.h @@ -0,0 +1,165 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_VERTEX_BUFFER_H +#define __COGL_VERTEX_BUFFER_H + +#include "cogl-object-private.h" + +#include "cogl-primitive.h" + +#include + +/* Note we put quite a bit into the flags here to help keep + * the down size of the CoglVertexBufferAttrib struct below. */ +typedef enum _CoglVertexBufferAttribFlags +{ + /* Types */ + /* NB: update the _TYPE_MASK below if these are changed */ + COGL_VERTEX_BUFFER_ATTRIB_FLAG_COLOR_ARRAY = 1<<0, + COGL_VERTEX_BUFFER_ATTRIB_FLAG_NORMAL_ARRAY = 1<<1, + COGL_VERTEX_BUFFER_ATTRIB_FLAG_TEXTURE_COORD_ARRAY = 1<<2, + COGL_VERTEX_BUFFER_ATTRIB_FLAG_VERTEX_ARRAY = 1<<3, + COGL_VERTEX_BUFFER_ATTRIB_FLAG_CUSTOM_ARRAY = 1<<4, + COGL_VERTEX_BUFFER_ATTRIB_FLAG_INVALID = 1<<5, + + COGL_VERTEX_BUFFER_ATTRIB_FLAG_NORMALIZED = 1<<6, + COGL_VERTEX_BUFFER_ATTRIB_FLAG_ENABLED = 1<<7, + + /* Usage hints */ + /* FIXME - flatten into one flag, since its used as a boolean */ + COGL_VERTEX_BUFFER_ATTRIB_FLAG_INFREQUENT_RESUBMIT = 1<<8, + COGL_VERTEX_BUFFER_ATTRIB_FLAG_FREQUENT_RESUBMIT = 1<<9, + + /* GL Data types */ + /* NB: Update the _GL_TYPE_MASK below if these are changed */ + COGL_VERTEX_BUFFER_ATTRIB_FLAG_GL_TYPE_BYTE = 1<<10, + COGL_VERTEX_BUFFER_ATTRIB_FLAG_GL_TYPE_UNSIGNED_BYTE = 1<<11, + COGL_VERTEX_BUFFER_ATTRIB_FLAG_GL_TYPE_SHORT = 1<<12, + COGL_VERTEX_BUFFER_ATTRIB_FLAG_GL_TYPE_UNSIGNED_SHORT = 1<<13, + COGL_VERTEX_BUFFER_ATTRIB_FLAG_GL_TYPE_INT = 1<<14, + COGL_VERTEX_BUFFER_ATTRIB_FLAG_GL_TYPE_UNSIGNED_INT = 1<<15, + COGL_VERTEX_BUFFER_ATTRIB_FLAG_GL_TYPE_FLOAT = 1<<16, + COGL_VERTEX_BUFFER_ATTRIB_FLAG_GL_TYPE_DOUBLE = 1<<17, + + COGL_VERTEX_BUFFER_ATTRIB_FLAG_SUBMITTED = 1<<18, + COGL_VERTEX_BUFFER_ATTRIB_FLAG_UNUSED = 1<<19 + + /* XXX NB: If we need > 24 bits then look at changing the layout + * of struct _CoglVertexBufferAttrib below */ +} CoglVertexBufferAttribFlags; + +#define COGL_VERTEX_BUFFER_ATTRIB_FLAG_TYPE_MASK \ + (COGL_VERTEX_BUFFER_ATTRIB_FLAG_COLOR_ARRAY \ + | COGL_VERTEX_BUFFER_ATTRIB_FLAG_NORMAL_ARRAY \ + | COGL_VERTEX_BUFFER_ATTRIB_FLAG_TEXTURE_COORD_ARRAY \ + | COGL_VERTEX_BUFFER_ATTRIB_FLAG_VERTEX_ARRAY \ + | COGL_VERTEX_BUFFER_ATTRIB_FLAG_CUSTOM_ARRAY \ + | COGL_VERTEX_BUFFER_ATTRIB_FLAG_INVALID) + +typedef struct _CoglVertexBufferAttrib +{ + /* TODO: look at breaking up the flags into seperate + * bitfields and seperate enums */ + CoglVertexBufferAttribFlags flags:24; + uint8_t id; + GQuark name; + char *name_without_detail; + union _u + { + const void *pointer; + size_t vbo_offset; + } u; + CoglAttributeType type; + size_t span_bytes; + uint16_t stride; + uint8_t n_components; + uint8_t texture_unit; + + int attribute_first; + CoglAttribute *attribute; + +} CoglVertexBufferAttrib; + +typedef enum _CoglVertexBufferVBOFlags +{ + COGL_VERTEX_BUFFER_VBO_FLAG_STRIDED = 1<<0, + COGL_VERTEX_BUFFER_VBO_FLAG_MULTIPACK = 1<<1, + + /* FIXME - flatten into one flag, since its used as a boolean */ + COGL_VERTEX_BUFFER_VBO_FLAG_INFREQUENT_RESUBMIT = 1<<3, + COGL_VERTEX_BUFFER_VBO_FLAG_FREQUENT_RESUBMIT = 1<<4, + + COGL_VERTEX_BUFFER_VBO_FLAG_SUBMITTED = 1<<5 +} CoglVertexBufferVBOFlags; + +/* + * A CoglVertexBufferVBO represents one or more attributes in a single + * buffer object + */ +typedef struct _CoglVertexBufferVBO +{ + CoglVertexBufferVBOFlags flags; + + CoglAttributeBuffer *attribute_buffer; + size_t buffer_bytes; + + GList *attributes; +} CoglVertexBufferVBO; + +typedef struct _CoglVertexBufferIndices +{ + CoglHandleObject _parent; + + CoglIndices *indices; +} CoglVertexBufferIndices; + +typedef struct _CoglVertexBuffer +{ + CoglHandleObject _parent; + + int n_vertices; /*!< The number of vertices in the buffer */ + GList *submitted_vbos; /* The VBOs currently submitted to the GPU */ + + /* Note: new_attributes is normally NULL and only valid while + * modifying a buffer. */ + GList *new_attributes; /*!< attributes pending submission */ + + CoglBool dirty_attributes; + + CoglPrimitive *primitive; + +} CoglVertexBuffer; + +#endif /* __COGL_VERTEX_BUFFER_H */ + diff --git a/cogl/cogl/deprecated/cogl-vertex-buffer.c b/cogl/cogl/deprecated/cogl-vertex-buffer.c new file mode 100644 index 0000000..cf6e51e --- /dev/null +++ b/cogl/cogl/deprecated/cogl-vertex-buffer.c @@ -0,0 +1,1795 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +/* XXX: For an overview of the functionality implemented here, please + * see cogl-vertex-buffer.h, which contains the gtk-doc section overview + * for the Vertex Buffers API. + */ + +/* + * TODO: We need to do a better job of minimizing when we call glVertexPointer + * and pals in enable_state_for_drawing_buffer + * + * We should have an internal 2-tuple cache of (VBO, offset) for each of them + * so we can avoid some GL calls. We could have cogl wrappers for the + * gl*Pointer funcs that look like this: + * + * cogl_vertex_pointer (n_components, gl_type, stride, vbo, offset); + * cogl_color_pointer (n_components, gl_type, stride, vbo, offset); + * + * They would also accept NULL for the VBO handle to support old style vertex + * arrays. + * + * TODO: + * Actually hook this up to the cogl shaders infrastructure. The vertex + * buffer API has been designed to allow adding of arbitrary attributes for use + * with shaders, but this has yet to be actually plumbed together and tested. + * The bits we are missing: + * - cogl_program_use doesn't currently record within ctx-> which program + * is currently in use so a.t.m only Clutter knows the current shader. + * - We don't query the current shader program for the generic vertex indices + * (using glGetAttribLocation) so that we can call glEnableVertexAttribArray + * with those indices. + * (currently we just make up consecutive indices) + * - some dirty flag mechanims to know when the shader program has changed + * so we don't need to re-query it each time we draw a buffer. + * + * TODO + * Expose API that lets developers get back a buffer handle for a particular + * polygon so they may add custom attributes to them. + * - It should be possible to query/modify attributes efficiently, in place, + * avoiding copies. It would not be acceptable to simply require that + * developers must query back the n_vertices of a buffer and then the + * n_components, type and stride etc of each attribute since there + * would be too many combinations to realistically handle. + * + * - In practice, some cases might be best solved with a higher level + * EditableMesh API, (see futher below) but for many cases I think an + * API like this might be appropriate: + * + * cogl_vertex_buffer_foreach_vertex (buffer_handle, + * (AttributesBufferIteratorFunc)callback, + * "gl_Vertex", "gl_Color", NULL); + * static void callback (CoglVertexBufferVertex *vert) + * { + * GLfloat *pos = vert->attrib[0]; + * GLubyte *color = vert->attrib[1]; + * GLfloat *new_attrib = buf[vert->index]; + * + * new_attrib = pos*color; + * } + * + * TODO + * Think about a higher level Mesh API for building/modifying attribute buffers + * - E.g. look at Blender for inspiration here. They can build a mesh from + * "MVert", "MFace" and "MEdge" primitives. + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include +#include +#include + +#include "cogl-util.h" +#include "cogl-context-private.h" +#include "cogl-object-private.h" +#include "cogl-vertex-buffer-private.h" +#include "cogl-texture-private.h" +#include "cogl-pipeline.h" +#include "cogl-pipeline-private.h" +#include "cogl-primitives.h" +#include "cogl-framebuffer-private.h" +#include "cogl-primitive-private.h" +#include "cogl-journal-private.h" +#include "cogl1-context.h" +#include "cogl-vertex-buffer.h" + +#define PAD_FOR_ALIGNMENT(VAR, TYPE_SIZE) \ + (VAR = TYPE_SIZE + ((VAR - 1) & ~(TYPE_SIZE - 1))) + +static void _cogl_vertex_buffer_free (CoglVertexBuffer *buffer); +static void _cogl_vertex_buffer_indices_free (CoglVertexBufferIndices *buffer_indices); +static CoglUserDataKey _cogl_vertex_buffer_pipeline_priv_key; + +COGL_HANDLE_DEFINE (VertexBuffer, vertex_buffer); +COGL_OBJECT_DEFINE_DEPRECATED_REF_COUNTING (vertex_buffer); +COGL_HANDLE_DEFINE (VertexBufferIndices, vertex_buffer_indices); + +CoglHandle +cogl_vertex_buffer_new (unsigned int n_vertices) +{ + CoglVertexBuffer *buffer = g_slice_alloc (sizeof (CoglVertexBuffer)); + + buffer->n_vertices = n_vertices; + + buffer->submitted_vbos = NULL; + buffer->new_attributes = NULL; + buffer->primitive = cogl_primitive_new (COGL_VERTICES_MODE_TRIANGLES, + n_vertices, NULL); + + /* return COGL_INVALID_HANDLE; */ + return _cogl_vertex_buffer_handle_new (buffer); +} + +unsigned int +cogl_vertex_buffer_get_n_vertices (CoglHandle handle) +{ + CoglVertexBuffer *buffer; + + if (!cogl_is_vertex_buffer (handle)) + return 0; + + buffer = handle; + + return buffer->n_vertices; +} + +/* There are a number of standard OpenGL attributes that we deal with + * specially. These attributes are all namespaced with a "gl_" prefix + * so we should catch any typos instead of silently adding a custom + * attribute. + */ +static CoglVertexBufferAttribFlags +validate_gl_attribute (const char *gl_attribute, + uint8_t n_components, + uint8_t *texture_unit) +{ + CoglVertexBufferAttribFlags type; + char *detail_seperator = NULL; + int name_len; + + detail_seperator = strstr (gl_attribute, "::"); + if (detail_seperator) + name_len = detail_seperator - gl_attribute; + else + name_len = strlen (gl_attribute); + + if (strncmp (gl_attribute, "Vertex", name_len) == 0) + { + if (G_UNLIKELY (n_components == 1)) + g_critical ("glVertexPointer doesn't allow 1 component vertex " + "positions so we currently only support \"gl_Vertex\" " + "attributes where n_components == 2, 3 or 4"); + type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_VERTEX_ARRAY; + } + else if (strncmp (gl_attribute, "Color", name_len) == 0) + { + if (G_UNLIKELY (n_components != 3 && n_components != 4)) + g_critical ("glColorPointer expects 3 or 4 component colors so we " + "currently only support \"gl_Color\" attributes where " + "n_components == 3 or 4"); + type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_COLOR_ARRAY; + } + else if (strncmp (gl_attribute, + "MultiTexCoord", + strlen ("MultiTexCoord")) == 0) + { + unsigned int unit; + + if (sscanf (gl_attribute, "MultiTexCoord%u", &unit) != 1) + { + g_warning ("gl_MultiTexCoord attributes should include a\n" + "texture unit number, E.g. gl_MultiTexCoord0\n"); + unit = 0; + } + /* FIXME: validate any '::' delimiter for this case */ + *texture_unit = unit; + type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_TEXTURE_COORD_ARRAY; + } + else if (strncmp (gl_attribute, "Normal", name_len) == 0) + { + if (G_UNLIKELY (n_components != 3)) + g_critical ("glNormalPointer expects 3 component normals so we " + "currently only support \"gl_Normal\" attributes where " + "n_components == 3"); + type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_NORMAL_ARRAY; + } + else + { + g_warning ("Unknown gl_* attribute name gl_%s\n", gl_attribute); + type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_INVALID; + } + + return type; +} + +/* There are a number of standard OpenGL attributes that we deal with + * specially. These attributes are all namespaced with a "gl_" prefix + * so we should catch any typos instead of silently adding a custom + * attribute. + */ +static CoglVertexBufferAttribFlags +validate_cogl_attribute (const char *cogl_attribute, + uint8_t n_components, + uint8_t *texture_unit) +{ + CoglVertexBufferAttribFlags type; + char *detail_seperator = NULL; + int name_len; + + detail_seperator = strstr (cogl_attribute, "::"); + if (detail_seperator) + name_len = detail_seperator - cogl_attribute; + else + name_len = strlen (cogl_attribute); + + if (strncmp (cogl_attribute, "position_in", name_len) == 0) + { + if (G_UNLIKELY (n_components == 1)) + g_critical ("glVertexPointer doesn't allow 1 component vertex " + "positions so we currently only support " + "\"cogl_position_in\" attributes where " + "n_components == 2, 3 or 4"); + type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_VERTEX_ARRAY; + } + else if (strncmp (cogl_attribute, "color_in", name_len) == 0) + { + if (G_UNLIKELY (n_components != 3 && n_components != 4)) + g_critical ("glColorPointer expects 3 or 4 component colors so we " + "currently only support \"cogl_color_in\" attributes " + "where n_components == 3 or 4"); + type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_COLOR_ARRAY; + } + else if (strncmp (cogl_attribute, + "cogl_tex_coord", + strlen ("cogl_tex_coord")) == 0) + { + unsigned int unit; + + if (strcmp (cogl_attribute, "cogl_tex_coord_in") == 0) + unit = 0; + else if (sscanf (cogl_attribute, "cogl_tex_coord%u_in", &unit) != 1) + { + g_warning ("texture coordinate attributes should either be " + "referenced as \"cogl_tex_coord_in\" or with a" + "texture unit number like \"cogl_tex_coord1_in\""); + unit = 0; + } + /* FIXME: validate any '::' delimiter for this case */ + *texture_unit = unit; + type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_TEXTURE_COORD_ARRAY; + } + else if (strncmp (cogl_attribute, "normal_in", name_len) == 0) + { + if (G_UNLIKELY (n_components != 3)) + g_critical ("glNormalPointer expects 3 component normals so we " + "currently only support \"cogl_normal_in\" attributes " + "where n_components == 3"); + type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_NORMAL_ARRAY; + } + else + { + g_warning ("Unknown cogl_* attribute name cogl_%s\n", cogl_attribute); + type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_INVALID; + } + + return type; +} + +/* This validates that a custom attribute name is a valid GLSL variable name + * + * NB: attribute names may have a detail component delimited using '::' E.g. + * custom_attrib::foo or custom_attrib::bar + * + * maybe I should hang a compiled regex somewhere to handle this + */ +static CoglBool +validate_custom_attribute_name (const char *attribute_name) +{ + char *detail_seperator = NULL; + int name_len; + int i; + + detail_seperator = strstr (attribute_name, "::"); + if (detail_seperator) + name_len = detail_seperator - attribute_name; + else + name_len = strlen (attribute_name); + + if (name_len == 0 + || !g_ascii_isalpha (attribute_name[0]) + || attribute_name[0] != '_') + return FALSE; + + for (i = 1; i < name_len; i++) + if (!g_ascii_isalnum (attribute_name[i]) || attribute_name[i] != '_') + return FALSE; + + return TRUE; +} + +/* Iterates the CoglVertexBufferVBOs of a buffer and creates a flat list + * of all the submitted attributes + * + * Note: The CoglVertexBufferAttrib structs are deep copied, except the + * internal CoglAttribute pointer is set to NULL. + */ +static GList * +copy_submitted_attributes_list (CoglVertexBuffer *buffer) +{ + GList *tmp; + GList *submitted_attributes = NULL; + + for (tmp = buffer->submitted_vbos; tmp != NULL; tmp = tmp->next) + { + CoglVertexBufferVBO *cogl_vbo = tmp->data; + GList *tmp2; + + for (tmp2 = cogl_vbo->attributes; tmp2 != NULL; tmp2 = tmp2->next) + { + CoglVertexBufferAttrib *attribute = tmp2->data; + CoglVertexBufferAttrib *copy = + g_slice_alloc (sizeof (CoglVertexBufferAttrib)); + *copy = *attribute; + copy->name_without_detail = + g_strdup (attribute->name_without_detail); + copy->attribute = NULL; + submitted_attributes = g_list_prepend (submitted_attributes, copy); + } + } + return submitted_attributes; +} + +static size_t +sizeof_attribute_type (CoglAttributeType type) +{ + switch (type) + { + case COGL_ATTRIBUTE_TYPE_BYTE: + return 1; + case COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE: + return 1; + case COGL_ATTRIBUTE_TYPE_SHORT: + return 2; + case COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT: + return 2; + case COGL_ATTRIBUTE_TYPE_FLOAT: + return 4; + } + g_return_val_if_reached (0); +} + +static size_t +strideof (CoglAttributeType type, int n_components) +{ + return sizeof_attribute_type (type) * n_components; +} + +static char * +canonize_attribute_name (const char *attribute_name) +{ + char *detail_seperator = NULL; + int name_len; + + if (strncmp (attribute_name, "gl_", 3) != 0) + return g_strdup (attribute_name); + + /* skip past the "gl_" */ + attribute_name += 3; + + detail_seperator = strstr (attribute_name, "::"); + if (detail_seperator) + name_len = detail_seperator - attribute_name; + else + { + name_len = strlen (attribute_name); + detail_seperator = ""; + } + + if (strncmp (attribute_name, "Vertex", name_len) == 0) + return g_strconcat ("cogl_position_in", detail_seperator, NULL); + else if (strncmp (attribute_name, "Color", name_len) == 0) + return g_strconcat ("cogl_color_in", detail_seperator, NULL); + else if (strncmp (attribute_name, + "MultiTexCoord", + strlen ("MultiTexCoord")) == 0) + { + unsigned int unit; + + if (sscanf (attribute_name, "MultiTexCoord%u", &unit) != 1) + { + g_warning ("gl_MultiTexCoord attributes should include a\n" + "texture unit number, E.g. gl_MultiTexCoord0\n"); + unit = 0; + } + return g_strdup_printf ("cogl_tex_coord%u_in%s", + unit, detail_seperator); + } + else if (strncmp (attribute_name, "Normal", name_len) == 0) + return g_strconcat ("cogl_normal_in", detail_seperator, NULL); + else + { + g_warning ("Unknown gl_* attribute name gl_%s\n", attribute_name); + return g_strdup (attribute_name); + } +} + +void +cogl_vertex_buffer_add (CoglHandle handle, + const char *attribute_name, + uint8_t n_components, + CoglAttributeType type, + CoglBool normalized, + uint16_t stride, + const void *pointer) +{ + CoglVertexBuffer *buffer; + char *cogl_attribute_name; + GQuark name_quark; + CoglBool modifying_an_attrib = FALSE; + CoglVertexBufferAttrib *attribute; + CoglVertexBufferAttribFlags flags = 0; + uint8_t texture_unit = 0; + GList *tmp; + char *detail; + + if (!cogl_is_vertex_buffer (handle)) + return; + + buffer = handle; + buffer->dirty_attributes = TRUE; + + cogl_attribute_name = canonize_attribute_name (attribute_name); + name_quark = g_quark_from_string (cogl_attribute_name); + + /* The submit function works by diffing between submitted_attributes + * and new_attributes to minimize the upload bandwidth + cost of + * allocating new VBOs, so if there isn't already a list of new_attributes + * we create one: */ + if (!buffer->new_attributes) + buffer->new_attributes = copy_submitted_attributes_list (buffer); + + /* Note: we first look for an existing attribute that we are modifying + * so we may skip needing to validate the name */ + for (tmp = buffer->new_attributes; tmp != NULL; tmp = tmp->next) + { + CoglVertexBufferAttrib *submitted_attribute = tmp->data; + if (submitted_attribute->name == name_quark) + { + modifying_an_attrib = TRUE; + + attribute = submitted_attribute; + + /* since we will skip validate_gl/cogl_attribute in this case, we + * need to pluck out the attribute type before overwriting the + * flags: */ + flags |= + attribute->flags & COGL_VERTEX_BUFFER_ATTRIB_FLAG_TYPE_MASK; + break; + } + } + + if (!modifying_an_attrib) + { + /* Validate the attribute name, is suitable as a variable name */ + if (strncmp (attribute_name, "gl_", 3) == 0) + { + /* Note: we pass the original attribute name here so that + * any warning messages correspond to the users original + * attribute name... */ + flags |= validate_gl_attribute (attribute_name + 3, + n_components, + &texture_unit); + if (flags & COGL_VERTEX_BUFFER_ATTRIB_FLAG_INVALID) + return; + } + else if (strncmp (attribute_name, "cogl_", 5) == 0) + { + flags |= validate_cogl_attribute (attribute_name + 5, + n_components, + &texture_unit); + if (flags & COGL_VERTEX_BUFFER_ATTRIB_FLAG_INVALID) + return; + } + else + { + flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_CUSTOM_ARRAY; + if (validate_custom_attribute_name (attribute_name)) + return; + } + + attribute = g_slice_alloc0 (sizeof (CoglVertexBufferAttrib)); + } + + attribute->name = name_quark; + detail = strstr (cogl_attribute_name, "::"); + if (detail) + attribute->name_without_detail = g_strndup (cogl_attribute_name, + detail - cogl_attribute_name); + else + attribute->name_without_detail = g_strdup (cogl_attribute_name); + attribute->type = type; + attribute->n_components = n_components; + if (stride == 0) + stride = strideof (type, n_components); + attribute->stride = stride; + attribute->u.pointer = pointer; + attribute->texture_unit = texture_unit; + attribute->attribute = NULL; + + flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_ENABLED; + + /* Note: We currently just assume, if an attribute is *ever* updated + * then it should be taged as frequently changing. */ + if (modifying_an_attrib) + flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_FREQUENT_RESUBMIT; + else + flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_INFREQUENT_RESUBMIT; + + if (normalized) + flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_NORMALIZED; + attribute->flags = flags; + + attribute->span_bytes = buffer->n_vertices * attribute->stride; + + if (!modifying_an_attrib) + buffer->new_attributes = + g_list_prepend (buffer->new_attributes, attribute); + + g_free (cogl_attribute_name); +} + +static void +_cogl_vertex_buffer_attrib_free (CoglVertexBufferAttrib *attribute) +{ + if (attribute->attribute) + cogl_object_unref (attribute->attribute); + g_free (attribute->name_without_detail); + g_slice_free (CoglVertexBufferAttrib, attribute); +} + +void +cogl_vertex_buffer_delete (CoglHandle handle, + const char *attribute_name) +{ + CoglVertexBuffer *buffer; + char *cogl_attribute_name = canonize_attribute_name (attribute_name); + GQuark name = g_quark_from_string (cogl_attribute_name); + GList *tmp; + + g_free (cogl_attribute_name); + + if (!cogl_is_vertex_buffer (handle)) + return; + + buffer = handle; + buffer->dirty_attributes = TRUE; + + /* The submit function works by diffing between submitted_attributes + * and new_attributes to minimize the upload bandwidth + cost of + * allocating new VBOs, so if there isn't already a list of new_attributes + * we create one: */ + if (!buffer->new_attributes) + buffer->new_attributes = copy_submitted_attributes_list (buffer); + + for (tmp = buffer->new_attributes; tmp != NULL; tmp = tmp->next) + { + CoglVertexBufferAttrib *submitted_attribute = tmp->data; + if (submitted_attribute->name == name) + { + buffer->new_attributes = + g_list_delete_link (buffer->new_attributes, tmp); + _cogl_vertex_buffer_attrib_free (submitted_attribute); + return; + } + } + + g_warning ("Failed to find an attribute named %s to delete\n", + attribute_name); +} + +static void +set_attribute_enable (CoglHandle handle, + const char *attribute_name, + CoglBool state) +{ + CoglVertexBuffer *buffer; + char *cogl_attribute_name = canonize_attribute_name (attribute_name); + GQuark name_quark = g_quark_from_string (cogl_attribute_name); + GList *tmp; + + g_free (cogl_attribute_name); + + if (!cogl_is_vertex_buffer (handle)) + return; + + buffer = handle; + buffer->dirty_attributes = TRUE; + + /* NB: If a buffer is currently being edited, then there can be two seperate + * lists of attributes; those that are currently submitted and a new list yet + * to be submitted, we need to modify both. */ + + for (tmp = buffer->new_attributes; tmp != NULL; tmp = tmp->next) + { + CoglVertexBufferAttrib *attribute = tmp->data; + if (attribute->name == name_quark) + { + if (state) + attribute->flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_ENABLED; + else + attribute->flags &= ~COGL_VERTEX_BUFFER_ATTRIB_FLAG_ENABLED; + break; + } + } + + for (tmp = buffer->submitted_vbos; tmp != NULL; tmp = tmp->next) + { + CoglVertexBufferVBO *cogl_vbo = tmp->data; + GList *tmp2; + + for (tmp2 = cogl_vbo->attributes; tmp2 != NULL; tmp2 = tmp2->next) + { + CoglVertexBufferAttrib *attribute = tmp2->data; + if (attribute->name == name_quark) + { + if (state) + attribute->flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_ENABLED; + else + attribute->flags &= ~COGL_VERTEX_BUFFER_ATTRIB_FLAG_ENABLED; + return; + } + } + } + + g_warning ("Failed to %s attribute named %s/%s\n", + state == TRUE ? "enable" : "disable", + attribute_name, cogl_attribute_name); +} + +void +cogl_vertex_buffer_enable (CoglHandle handle, + const char *attribute_name) +{ + set_attribute_enable (handle, attribute_name, TRUE); +} + +void +cogl_vertex_buffer_disable (CoglHandle handle, + const char *attribute_name) +{ + set_attribute_enable (handle, attribute_name, FALSE); +} + +/* Given an attribute that we know has already been submitted before, this + * function looks for the existing VBO that contains it. + * + * Note: It will free redundant attribute struct once the corresponding + * VBO has been found. + */ +static void +filter_already_submitted_attribute (CoglVertexBufferAttrib *attribute, + GList **reuse_vbos, + GList **submitted_vbos) +{ + GList *tmp; + + /* First check the cogl_vbos we already know are being reused since we + * are more likley to get a match here */ + for (tmp = *reuse_vbos; tmp != NULL; tmp = tmp->next) + { + CoglVertexBufferVBO *cogl_vbo = tmp->data; + GList *tmp2; + + for (tmp2 = cogl_vbo->attributes; tmp2 != NULL; tmp2 = tmp2->next) + { + CoglVertexBufferAttrib *vbo_attribute = tmp2->data; + + if (vbo_attribute->name == attribute->name) + { + vbo_attribute->flags &= + ~COGL_VERTEX_BUFFER_ATTRIB_FLAG_UNUSED; + /* Note: we don't free the redundant attribute here, since it + * will be freed after all filtering in + * cogl_vertex_buffer_submit */ + return; + } + } + } + + for (tmp = *submitted_vbos; tmp != NULL; tmp = tmp->next) + { + CoglVertexBufferVBO *cogl_vbo = tmp->data; + CoglVertexBufferAttrib *reuse_attribute = NULL; + GList *tmp2; + + for (tmp2 = cogl_vbo->attributes; tmp2 != NULL; tmp2 = tmp2->next) + { + CoglVertexBufferAttrib *vbo_attribute = tmp2->data; + if (vbo_attribute->name == attribute->name) + { + reuse_attribute = vbo_attribute; + /* Note: we don't free the redundant attribute here, since it + * will be freed after all filtering in + * cogl_vertex_buffer_submit */ + + *submitted_vbos = g_list_remove_link (*submitted_vbos, tmp); + tmp->next = *reuse_vbos; + *reuse_vbos = tmp; + break; + } + } + + if (!reuse_attribute) + continue; + + /* Mark all but the matched attribute as UNUSED, so that when we + * finish filtering all our attributes any attrributes still + * marked as UNUSED can be removed from their cogl_vbo */ + for (tmp2 = cogl_vbo->attributes; tmp2 != NULL; tmp2 = tmp2->next) + { + CoglVertexBufferAttrib *vbo_attribute = tmp2->data; + if (vbo_attribute != reuse_attribute) + vbo_attribute->flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_UNUSED; + } + + return; + } + + g_critical ("Failed to find the cogl vbo that corresponds to an\n" + "attribute that had apparently already been submitted!"); +} + +/* When we first mark a CoglVertexBufferVBO to be reused, we mark the + * attributes as unsed, so that when filtering of attributes into VBOs is done + * we can then prune the now unsed attributes. */ +static void +remove_unused_attributes (CoglVertexBufferVBO *cogl_vbo) +{ + GList *tmp; + GList *next; + + for (tmp = cogl_vbo->attributes; tmp != NULL; tmp = next) + { + CoglVertexBufferAttrib *attribute = tmp->data; + next = tmp->next; + + if (attribute->flags & COGL_VERTEX_BUFFER_ATTRIB_FLAG_UNUSED) + { + cogl_vbo->attributes = + g_list_delete_link (cogl_vbo->attributes, tmp); + g_slice_free (CoglVertexBufferAttrib, attribute); + } + } +} + +/* Give a newly added, strided, attribute, this function looks for a + * CoglVertexBufferVBO that the attribute is interleved with. If it can't + * find one then a new CoglVertexBufferVBO is allocated and added to the + * list of new_strided_vbos. + */ +static void +filter_strided_attribute (CoglVertexBufferAttrib *attribute, + GList **new_vbos) +{ + GList *tmp; + CoglVertexBufferVBO *new_cogl_vbo; + + for (tmp = *new_vbos; tmp != NULL; tmp = tmp->next) + { + CoglVertexBufferVBO *cogl_vbo = tmp->data; + GList *tmp2; + + if (!(cogl_vbo->flags & COGL_VERTEX_BUFFER_VBO_FLAG_STRIDED)) + continue; + + for (tmp2 = cogl_vbo->attributes; tmp2 != NULL; tmp2 = tmp2->next) + { + CoglVertexBufferAttrib *vbo_attribute = tmp2->data; + const char *attribute_start = attribute->u.pointer; + const char *vbo_attribute_start = vbo_attribute->u.pointer; + + /* NB: All attributes have buffer->n_vertices values which + * simplifies determining which attributes are interleved + * since we assume they will start no farther than +- a + * stride away from each other: + */ + if (attribute_start <= (vbo_attribute_start - vbo_attribute->stride) + || attribute_start + >= (vbo_attribute_start + vbo_attribute->stride)) + continue; /* Not interleved */ + + cogl_vbo->attributes = + g_list_prepend (cogl_vbo->attributes, attribute); + + if (attribute->flags & + COGL_VERTEX_BUFFER_ATTRIB_FLAG_FREQUENT_RESUBMIT) + { + cogl_vbo->flags &= + ~COGL_VERTEX_BUFFER_VBO_FLAG_INFREQUENT_RESUBMIT; + cogl_vbo->flags |= + COGL_VERTEX_BUFFER_VBO_FLAG_FREQUENT_RESUBMIT; + } + return; + } + } + new_cogl_vbo = g_slice_alloc (sizeof (CoglVertexBufferVBO)); + new_cogl_vbo->attributes = NULL; + new_cogl_vbo->attributes = + g_list_prepend (new_cogl_vbo->attributes, attribute); + /* Any one of the interleved attributes will have the same span_bytes */ + new_cogl_vbo->attribute_buffer = NULL; + new_cogl_vbo->buffer_bytes = attribute->span_bytes; + new_cogl_vbo->flags = COGL_VERTEX_BUFFER_VBO_FLAG_STRIDED; + + if (attribute->flags & COGL_VERTEX_BUFFER_ATTRIB_FLAG_INFREQUENT_RESUBMIT) + new_cogl_vbo->flags |= COGL_VERTEX_BUFFER_VBO_FLAG_INFREQUENT_RESUBMIT; + else + new_cogl_vbo->flags |= COGL_VERTEX_BUFFER_VBO_FLAG_FREQUENT_RESUBMIT; + + *new_vbos = g_list_prepend (*new_vbos, new_cogl_vbo); + return; +} + +/* This iterates through the list of submitted VBOs looking for one that + * contains attribute. If found the list *link* is removed and returned */ +static GList * +unlink_submitted_vbo_containing_attribute (GList **submitted_vbos, + CoglVertexBufferAttrib *attribute) +{ + GList *tmp; + GList *next = NULL; + + for (tmp = *submitted_vbos; tmp != NULL; tmp = next) + { + CoglVertexBufferVBO *submitted_vbo = tmp->data; + GList *tmp2; + + next = tmp->next; + + for (tmp2 = submitted_vbo->attributes; tmp2 != NULL; tmp2 = tmp2->next) + { + CoglVertexBufferAttrib *submitted_attribute = tmp2->data; + + if (submitted_attribute->name == attribute->name) + { + *submitted_vbos = g_list_remove_link (*submitted_vbos, tmp); + return tmp; + } + } + } + + return NULL; +} + +/* Unlinks all the submitted VBOs that conflict with the new cogl_vbo and + * returns them as a list. */ +static GList * +get_submitted_vbo_conflicts (GList **submitted_vbos, + CoglVertexBufferVBO *cogl_vbo) +{ + GList *tmp; + GList *conflicts = NULL; + + for (tmp = cogl_vbo->attributes; tmp != NULL; tmp = tmp->next) + { + GList *link = + unlink_submitted_vbo_containing_attribute (submitted_vbos, + tmp->data); + if (link) + { + /* prepend the link to the list of conflicts: */ + link->next = conflicts; + conflicts = link; + } + } + return conflicts; +} + +/* Any attributes in cogl_vbo gets removed from conflict_vbo */ +static void +disassociate_conflicting_attributes (CoglVertexBufferVBO *conflict_vbo, + CoglVertexBufferVBO *cogl_vbo) +{ + GList *tmp; + + /* NB: The attributes list in conflict_vbo will be shrinking so + * we iterate those in the inner loop. */ + + for (tmp = cogl_vbo->attributes; tmp != NULL; tmp = tmp->next) + { + CoglVertexBufferAttrib *attribute = tmp->data; + GList *tmp2; + for (tmp2 = conflict_vbo->attributes; tmp2 != NULL; tmp2 = tmp2->next) + { + CoglVertexBufferAttrib *conflict_attribute = tmp2->data; + + if (conflict_attribute->name == attribute->name) + { + _cogl_vertex_buffer_attrib_free (conflict_attribute); + conflict_vbo->attributes = + g_list_delete_link (conflict_vbo->attributes, tmp2); + break; + } + } + } +} + +static void +cogl_vertex_buffer_vbo_free (CoglVertexBufferVBO *cogl_vbo) +{ + GList *tmp; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + for (tmp = cogl_vbo->attributes; tmp != NULL; tmp = tmp->next) + _cogl_vertex_buffer_attrib_free (tmp->data); + g_list_free (cogl_vbo->attributes); + + if (cogl_vbo->flags & COGL_VERTEX_BUFFER_VBO_FLAG_SUBMITTED) + cogl_object_unref (cogl_vbo->attribute_buffer); + + g_slice_free (CoglVertexBufferVBO, cogl_vbo); +} + +/* This figures out the lowest attribute client pointer. (This pointer is used + * to upload all the interleved attributes). + * + * In the process it also replaces the client pointer with the attributes + * offset, and marks the attribute as submitted. + */ +static const void * +prep_strided_vbo_for_upload (CoglVertexBufferVBO *cogl_vbo) +{ + GList *tmp; + const char *lowest_pointer = NULL; + + for (tmp = cogl_vbo->attributes; tmp != NULL; tmp = tmp->next) + { + CoglVertexBufferAttrib *attribute = tmp->data; + const char *client_pointer = attribute->u.pointer; + + if (!lowest_pointer || client_pointer < lowest_pointer) + lowest_pointer = client_pointer; + } + + for (tmp = cogl_vbo->attributes; tmp != NULL; tmp = tmp->next) + { + CoglVertexBufferAttrib *attribute = tmp->data; + const char *client_pointer = attribute->u.pointer; + attribute->u.vbo_offset = client_pointer - lowest_pointer; + attribute->flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_SUBMITTED; + } + + return lowest_pointer; +} + +static CoglBool +upload_multipack_vbo_via_map_buffer (CoglVertexBufferVBO *cogl_vbo) +{ + GList *tmp; + unsigned int offset = 0; + uint8_t *buf; + + _COGL_GET_CONTEXT (ctx, FALSE); + + buf = cogl_buffer_map (COGL_BUFFER (cogl_vbo->attribute_buffer), + COGL_BUFFER_ACCESS_WRITE, + COGL_BUFFER_MAP_HINT_DISCARD); + if (!buf) + return FALSE; + + for (tmp = cogl_vbo->attributes; tmp != NULL; tmp = tmp->next) + { + CoglVertexBufferAttrib *attribute = tmp->data; + gsize attribute_size = attribute->span_bytes; + gsize type_size = sizeof_attribute_type (attribute->type); + + PAD_FOR_ALIGNMENT (offset, type_size); + + memcpy (buf + offset, attribute->u.pointer, attribute_size); + + attribute->u.vbo_offset = offset; + attribute->flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_SUBMITTED; + offset += attribute_size; + } + + cogl_buffer_unmap (COGL_BUFFER (cogl_vbo->attribute_buffer)); + + return TRUE; +} + +static void +upload_multipack_vbo_via_buffer_sub_data (CoglVertexBufferVBO *cogl_vbo) +{ + GList *l; + unsigned int offset = 0; + + for (l = cogl_vbo->attributes; l != NULL; l = l->next) + { + CoglVertexBufferAttrib *attribute = l->data; + gsize attribute_size = attribute->span_bytes; + gsize type_size = sizeof_attribute_type (attribute->type); + + PAD_FOR_ALIGNMENT (offset, type_size); + + cogl_buffer_set_data (COGL_BUFFER (cogl_vbo->attribute_buffer), + offset, + attribute->u.pointer, + attribute_size); + + attribute->u.vbo_offset = offset; + attribute->flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_SUBMITTED; + offset += attribute_size; + } +} + +static void +upload_attributes (CoglVertexBufferVBO *cogl_vbo) +{ + CoglBufferUpdateHint usage; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (cogl_vbo->flags & COGL_VERTEX_BUFFER_VBO_FLAG_FREQUENT_RESUBMIT) + usage = COGL_BUFFER_UPDATE_HINT_DYNAMIC; + else + usage = COGL_BUFFER_UPDATE_HINT_STATIC; + cogl_buffer_set_update_hint (COGL_BUFFER (cogl_vbo->attribute_buffer), usage); + + if (cogl_vbo->flags & COGL_VERTEX_BUFFER_VBO_FLAG_STRIDED) + { + const void *pointer = prep_strided_vbo_for_upload (cogl_vbo); + cogl_buffer_set_data (COGL_BUFFER (cogl_vbo->attribute_buffer), + 0, /* offset */ + pointer, + cogl_vbo->buffer_bytes); + } + else /* MULTIPACK */ + { + /* I think it might depend on the specific driver/HW whether its better + * to use glMapBuffer here or glBufferSubData here. There is even a good + * thread about this topic here: + * http://www.mail-archive.com/dri-devel@lists.sourceforge.net/msg35004.html + * For now I have gone with glMapBuffer, but the jury is still out. + */ + + if (!upload_multipack_vbo_via_map_buffer (cogl_vbo)) + upload_multipack_vbo_via_buffer_sub_data (cogl_vbo); + } + + cogl_vbo->flags |= COGL_VERTEX_BUFFER_VBO_FLAG_SUBMITTED; +} + +/* Note: although there ends up being quite a few inner loops involved with + * resolving buffers, the number of attributes will be low so I don't expect + * them to cause a problem. */ +static void +cogl_vertex_buffer_vbo_resolve (CoglVertexBuffer *buffer, + CoglVertexBufferVBO *new_cogl_vbo, + GList **final_vbos) +{ + GList *conflicts; + GList *tmp; + GList *next; + CoglBool found_target_vbo = FALSE; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + conflicts = + get_submitted_vbo_conflicts (&buffer->submitted_vbos, new_cogl_vbo); + + for (tmp = conflicts; tmp != NULL; tmp = next) + { + CoglVertexBufferVBO *conflict_vbo = tmp->data; + + next = tmp->next; + + disassociate_conflicting_attributes (conflict_vbo, new_cogl_vbo); + + if (!conflict_vbo->attributes) + { + /* See if we can re-use this now empty VBO: */ + + if (!found_target_vbo + && conflict_vbo->buffer_bytes == new_cogl_vbo->buffer_bytes) + { + found_target_vbo = TRUE; + new_cogl_vbo->attribute_buffer = + cogl_object_ref (conflict_vbo->attribute_buffer); + cogl_vertex_buffer_vbo_free (conflict_vbo); + + upload_attributes (new_cogl_vbo); + + *final_vbos = g_list_prepend (*final_vbos, new_cogl_vbo); + } + else + cogl_vertex_buffer_vbo_free (conflict_vbo); + } + else + { + /* Relink the VBO back into buffer->submitted_vbos since it may + * be involved in other conflicts later */ + tmp->next = buffer->submitted_vbos; + tmp->prev = NULL; + buffer->submitted_vbos = tmp; + } + } + + if (!found_target_vbo) + { + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + new_cogl_vbo->attribute_buffer = + cogl_attribute_buffer_new (ctx, new_cogl_vbo->buffer_bytes, NULL); + + upload_attributes (new_cogl_vbo); + *final_vbos = g_list_prepend (*final_vbos, new_cogl_vbo); + } +} + +static void +update_primitive_attributes (CoglVertexBuffer *buffer) +{ + GList *l; + int n_attributes = 0; + CoglAttribute **attributes; + int i; + + if (!buffer->dirty_attributes) + return; + + buffer->dirty_attributes = FALSE; + + for (l = buffer->submitted_vbos; l; l = l->next) + { + CoglVertexBufferVBO *cogl_vbo = l->data; + GList *l2; + + for (l2 = cogl_vbo->attributes; l2; l2 = l2->next, n_attributes++) + ; + } + + _COGL_RETURN_IF_FAIL (n_attributes > 0); + + attributes = g_alloca (sizeof (CoglAttribute *) * n_attributes); + + i = 0; + for (l = buffer->submitted_vbos; l; l = l->next) + { + CoglVertexBufferVBO *cogl_vbo = l->data; + GList *l2; + + for (l2 = cogl_vbo->attributes; l2; l2 = l2->next) + { + CoglVertexBufferAttrib *attribute = l2->data; + if (G_LIKELY (attribute->flags & + COGL_VERTEX_BUFFER_ATTRIB_FLAG_ENABLED)) + { + if (G_UNLIKELY (!attribute->attribute)) + { + attribute->attribute = + cogl_attribute_new (cogl_vbo->attribute_buffer, + attribute->name_without_detail, + attribute->stride, + attribute->u.vbo_offset, + attribute->n_components, + attribute->type); + } + + attributes[i++] = attribute->attribute; + } + } + } + + cogl_primitive_set_attributes (buffer->primitive, attributes, i); +} + +static void +cogl_vertex_buffer_submit_real (CoglVertexBuffer *buffer) +{ + GList *tmp; + CoglVertexBufferVBO *new_multipack_vbo; + GList *new_multipack_vbo_link; + GList *new_vbos = NULL; + GList *reuse_vbos = NULL; + GList *final_vbos = NULL; + + if (!buffer->new_attributes) + goto done; + + /* The objective now is to copy the attribute data supplied by the client + * into buffer objects, but it's important to minimize the number of + * redundant data uploads. + * + * We obviously aim to group together the attributes that are interleved so + * that they can be delivered in one go to the driver. + * All BOs for interleved data are created as STATIC_DRAW_ARB. + * + * Non interleved attributes tagged as INFREQUENT_RESUBMIT will be grouped + * together back to back in a single BO created as STATIC_DRAW_ARB + * + * Non interleved attributes tagged as FREQUENT_RESUBMIT will be copied into + * individual buffer objects, and the BO itself created DYNAMIC_DRAW_ARB + * + * If we are modifying a previously submitted CoglVertexBuffer then we are + * carefull not to needlesly delete OpenGL buffer objects and replace with + * new ones, instead we upload new data to the existing buffers. + */ + + /* NB: We must forget attribute->pointer after submitting since the user + * is free to re-use that memory for other purposes now. */ + + /* Pseudo code: + * + * Broadly speaking we start with a list of unsorted attributes, and filter + * those into 'new' and 're-use' CoglVertexBufferVBO (CBO) lists. We then + * take the list of new CBO structs and compare with the CBOs that have + * already been submitted to the GPU (but ignoring those we already know will + * be re-used) to determine what other CBOs can be re-used, due to being + * superseded, and what new GL VBOs need to be created. + * + * We have two kinds of CBOs: + * - Multi Pack CBOs + * These contain multiple attributes tightly packed back to back) + * - Strided CBOs + * These typically contain multiple interleved sets of attributes, + * though they can contain just one attribute with a stride + * + * First create a new-CBOs entry "new-multipack-CBO" + * Tag "new-multipack-CBO" as MULTIPACK + INFREQUENT_RESUBMIT + * For each unsorted attrib: + * if already marked as submitted: + * iterate reuse-CBOs: + * if we find one that contains this attribute: + * free redundant unsorted attrib struct + * remove the UNUSED flag from the attrib found in the reuse-CBO + * continue to next unsorted attrib + * iterate submitted VBOs: + * if we find one that contains this attribute: + * free redundant unsorted attrib struct + * unlink the vbo and move it to the list of reuse-CBOs + * mark all attributes except the one just matched as UNUSED + * assert (found) + * continue to next unsorted attrib + * if strided: + * iterate the new, strided, CBOs, to see if the attribute is + * interleved with one of them, if found: + * add to the matched CBO + * else if not found: + * create a new-CBOs entry tagged STRIDED + INFREQUENT_RESUBMIT + * else if unstrided && tagged with FREQUENT_RESUBMIT: + * create a new-CBOs entry tagged MULTIPACK + FREQUENT_RESUBMIT + * else + * add to the new-multipack-CBO + * free list of unsorted-attribs + * + * Next compare the new list of CBOs with the submitted set and try to + * minimize the memory bandwidth required to upload the attributes and the + * overhead of creating new GL-BOs. + * + * We deal with four sets of CBOs: + * - The "new" CBOs + * (as determined above during filtering) + * - The "re-use" CBOs + * (as determined above during filtering) + * - The "submitted" CBOs + * (I.e. ones currently submitted to the GPU) + * - The "final" CBOs + * (The result of resolving the differences between the above sets) + * + * The re-use CBOs are dealt with first, and we simply delete any remaining + * attributes in these that are still marked as UNUSED, and move them + * to the list of final CBOs. + * + * Next we iterate through the "new" CBOs, searching for conflicts + * with the "submitted" CBOs and commit our decision to the "final" CBOs + * + * When searching for submitted entries we always unlink items from the + * submitted list once we make matches (before we make descisions + * based on the matches). If the CBO node is superseded it is freed, + * if it is modified but may be needed for more descisions later it is + * relinked back into the submitted list and if it's identical to a new + * CBO it will be linked into the final list. + * + * At the end the list of submitted CBOs represents the attributes that were + * deleted from the buffer. + * + * Iterate re-use-CBOs: + * Iterate attribs for each: + * if attrib UNUSED: + * remove the attrib from the CBO + free + * |Note: we could potentially mark this as a re-useable gap + * |if needs be later. + * add re-use CBO to the final-CBOs + * Iterate new-CBOs: + * List submitted CBOs conflicting with the this CBO (Unlinked items) + * found-target-BO=FALSE + * Iterate conflicting CBOs: + * Disassociate conflicting attribs from conflicting CBO struct + * If no attribs remain: + * If found-target-BO!=TRUE + * _AND_ If the total size of the conflicting CBO is compatible: + * |Note: We don't currently consider re-using oversized buffers + * found-target-BO=TRUE + * upload replacement data + * free submitted CBO struct + * add new CBO struct to final-CBOs + * else: + * delete conflict GL-BO + * delete conflict CBO struct + * else: + * relink CBO back into submitted-CBOs + * + * if found-target-BO == FALSE: + * create a new GL-BO + * upload data + * add new CBO struct to final-BOs + * + * Iterate through the remaining "submitted" CBOs: + * delete the submitted GL-BO + * free the submitted CBO struct + */ + + new_multipack_vbo = g_slice_alloc (sizeof (CoglVertexBufferVBO)); + new_multipack_vbo->attribute_buffer = NULL; + new_multipack_vbo->buffer_bytes = 0; + new_multipack_vbo->flags = + COGL_VERTEX_BUFFER_VBO_FLAG_MULTIPACK + | COGL_VERTEX_BUFFER_VBO_FLAG_INFREQUENT_RESUBMIT; + new_multipack_vbo->attributes = NULL; + new_vbos = g_list_prepend (new_vbos, new_multipack_vbo); + /* We save the link pointer here, just so we can do a fast removal later if + * no attributes get added to this vbo. */ + new_multipack_vbo_link = new_vbos; + + /* Start with a list of unsorted attributes, and filter those into + * potential new Cogl BO structs + */ + for (tmp = buffer->new_attributes; tmp != NULL; tmp = tmp->next) + { + CoglVertexBufferAttrib *attribute = tmp->data; + + if (attribute->flags & COGL_VERTEX_BUFFER_ATTRIB_FLAG_SUBMITTED) + { + /* If the attribute is already marked as submitted, then we need + * to find the existing VBO that contains it so we dont delete it. + * + * NB: this also frees the attribute struct since it's implicitly + * redundant in this case. + */ + filter_already_submitted_attribute (attribute, + &reuse_vbos, + &buffer->submitted_vbos); + } + else if (attribute->stride) + { + /* look for a CoglVertexBufferVBO that the attribute is + * interleved with. If one can't be found then a new + * CoglVertexBufferVBO is allocated and added to the list of + * new_vbos: */ + filter_strided_attribute (attribute, &new_vbos); + } + else if (attribute->flags & + COGL_VERTEX_BUFFER_ATTRIB_FLAG_FREQUENT_RESUBMIT) + { + CoglVertexBufferVBO *cogl_vbo = + g_slice_alloc (sizeof (CoglVertexBufferVBO)); + + /* attributes we expect will be frequently resubmitted are placed + * in their own VBO so that updates don't impact other attributes + */ + + cogl_vbo->flags = + COGL_VERTEX_BUFFER_VBO_FLAG_MULTIPACK + | COGL_VERTEX_BUFFER_VBO_FLAG_FREQUENT_RESUBMIT; + cogl_vbo->attributes = NULL; + cogl_vbo->attributes = g_list_prepend (cogl_vbo->attributes, + attribute); + cogl_vbo->attribute_buffer = NULL; + cogl_vbo->buffer_bytes = attribute->span_bytes; + new_vbos = g_list_prepend (new_vbos, cogl_vbo); + } + else + { + gsize type_size = sizeof_attribute_type (attribute->flags); + + /* Infrequently updated attributes just get packed back to back + * in a single VBO: */ + new_multipack_vbo->attributes = + g_list_prepend (new_multipack_vbo->attributes, + attribute); + + /* Note: we have to ensure that each run of attributes is + * naturally aligned according to its data type, which may + * require some padding bytes: */ + + /* XXX: We also have to be sure that the attributes aren't + * reorderd before being uploaded because the alignment padding + * is based on the adjacent attribute. + */ + + PAD_FOR_ALIGNMENT (new_multipack_vbo->buffer_bytes, type_size); + + new_multipack_vbo->buffer_bytes += attribute->span_bytes; + } + } + + /* At this point all buffer->new_attributes have been filtered into + * CoglVertexBufferVBOs... */ + g_list_free (buffer->new_attributes); + buffer->new_attributes = NULL; + + /* If the multipack vbo wasn't needed: */ + if (new_multipack_vbo->attributes == NULL) + { + new_vbos = g_list_delete_link (new_vbos, new_multipack_vbo_link); + g_slice_free (CoglVertexBufferVBO, new_multipack_vbo); + } + + for (tmp = reuse_vbos; tmp != NULL; tmp = tmp->next) + remove_unused_attributes (tmp->data); + final_vbos = g_list_concat (final_vbos, reuse_vbos); + + for (tmp = new_vbos; tmp != NULL; tmp = tmp->next) + cogl_vertex_buffer_vbo_resolve (buffer, tmp->data, &final_vbos); + + /* Anything left corresponds to deleted attributes: */ + for (tmp = buffer->submitted_vbos; tmp != NULL; tmp = tmp->next) + cogl_vertex_buffer_vbo_free (tmp->data); + g_list_free (buffer->submitted_vbos); + g_list_free (new_vbos); + + buffer->submitted_vbos = final_vbos; + +done: + update_primitive_attributes (buffer); +} + +void +cogl_vertex_buffer_submit (CoglHandle handle) +{ + CoglVertexBuffer *buffer; + + if (!cogl_is_vertex_buffer (handle)) + return; + + buffer = handle; + + cogl_vertex_buffer_submit_real (buffer); +} + +typedef struct +{ + /* We have a ref-count on this private structure because we need to + refer to it both from the private data on a pipeline and any weak + pipelines that we create from it. If we didn't have the ref count + then we would depend on the order of destruction of a + CoglPipeline and the weak materials to avoid a crash */ + unsigned int ref_count; + + CoglPipeline *real_source; +} VertexBufferMaterialPrivate; + +static void +unref_pipeline_priv (VertexBufferMaterialPrivate *priv) +{ + if (--priv->ref_count < 1) + g_slice_free (VertexBufferMaterialPrivate, priv); +} + +static void +weak_override_source_destroyed_cb (CoglPipeline *pipeline, + void *user_data) +{ + VertexBufferMaterialPrivate *pipeline_priv = user_data; + /* Unref the weak pipeline copy since it is no longer valid - probably because + * one of its ancestors has been changed. */ + cogl_object_unref (pipeline_priv->real_source); + pipeline_priv->real_source = NULL; + /* A reference was added when we copied the weak material so we need + to unref it here */ + unref_pipeline_priv (pipeline_priv); +} + +static CoglBool +validate_layer_cb (CoglPipeline *pipeline, + int layer_index, + void *user_data) +{ + VertexBufferMaterialPrivate *pipeline_priv = user_data; + CoglPipeline *source = pipeline_priv->real_source; + + if (!cogl_pipeline_get_layer_point_sprite_coords_enabled (source, + layer_index)) + { + CoglPipelineWrapMode wrap_s; + CoglPipelineWrapMode wrap_t; + CoglPipelineWrapMode wrap_p; + CoglBool need_override_source = FALSE; + + /* By default COGL_PIPELINE_WRAP_MODE_AUTOMATIC becomes + * GL_CLAMP_TO_EDGE but we want GL_REPEAT to maintain + * compatibility with older versions of Cogl so we'll override + * it. We don't want to do this for point sprites because in + * that case the whole texture is drawn so you would usually + * want clamp-to-edge. + */ + wrap_s = cogl_pipeline_get_layer_wrap_mode_s (source, layer_index); + if (wrap_s == COGL_PIPELINE_WRAP_MODE_AUTOMATIC) + { + need_override_source = TRUE; + wrap_s = COGL_PIPELINE_WRAP_MODE_REPEAT; + } + wrap_t = cogl_pipeline_get_layer_wrap_mode_t (source, layer_index); + if (wrap_t == COGL_PIPELINE_WRAP_MODE_AUTOMATIC) + { + need_override_source = TRUE; + wrap_t = COGL_PIPELINE_WRAP_MODE_REPEAT; + } + wrap_p = cogl_pipeline_get_layer_wrap_mode_p (source, layer_index); + if (wrap_p == COGL_PIPELINE_WRAP_MODE_AUTOMATIC) + { + need_override_source = TRUE; + wrap_p = COGL_PIPELINE_WRAP_MODE_REPEAT; + } + + if (need_override_source) + { + if (pipeline_priv->real_source == pipeline) + { + pipeline_priv->ref_count++; + pipeline_priv->real_source = source = + _cogl_pipeline_weak_copy (pipeline, + weak_override_source_destroyed_cb, + pipeline_priv); + } + + cogl_pipeline_set_layer_wrap_mode_s (source, layer_index, wrap_s); + cogl_pipeline_set_layer_wrap_mode_t (source, layer_index, wrap_t); + cogl_pipeline_set_layer_wrap_mode_p (source, layer_index, wrap_p); + } + } + + return TRUE; +} + +static void +destroy_pipeline_priv_cb (void *user_data) +{ + unref_pipeline_priv (user_data); +} + +static void +update_primitive_and_draw (CoglVertexBuffer *buffer, + CoglVerticesMode mode, + int first, + int count, + CoglVertexBufferIndices *buffer_indices) +{ + VertexBufferMaterialPrivate *pipeline_priv; + CoglPipeline *users_source; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + cogl_primitive_set_mode (buffer->primitive, mode); + cogl_primitive_set_first_vertex (buffer->primitive, first); + cogl_primitive_set_n_vertices (buffer->primitive, count); + + if (buffer_indices) + cogl_primitive_set_indices (buffer->primitive, buffer_indices->indices, count); + else + cogl_primitive_set_indices (buffer->primitive, NULL, count); + + cogl_vertex_buffer_submit_real (buffer); + + users_source = cogl_get_source (); + pipeline_priv = + cogl_object_get_user_data (COGL_OBJECT (users_source), + &_cogl_vertex_buffer_pipeline_priv_key); + if (G_UNLIKELY (!pipeline_priv)) + { + pipeline_priv = g_slice_new0 (VertexBufferMaterialPrivate); + pipeline_priv->ref_count = 1; + cogl_object_set_user_data (COGL_OBJECT (users_source), + &_cogl_vertex_buffer_pipeline_priv_key, + pipeline_priv, + destroy_pipeline_priv_cb); + } + + if (G_UNLIKELY (!pipeline_priv->real_source)) + { + pipeline_priv->real_source = users_source; + cogl_pipeline_foreach_layer (pipeline_priv->real_source, + validate_layer_cb, + pipeline_priv); + } + + /* XXX: although this may seem redundant, we need to do this since + * CoglVertexBuffers can be used with legacy state and its the source stack + * which track whether legacy state is enabled. + * + * (We only have a CoglDrawFlag to disable legacy state not one + * to enable it) */ + cogl_push_source (pipeline_priv->real_source); + + _cogl_primitive_draw (buffer->primitive, + cogl_get_draw_framebuffer (), + pipeline_priv->real_source, + 0 /* no draw flags */); + + cogl_pop_source (); +} + +void +cogl_vertex_buffer_draw (CoglHandle handle, + CoglVerticesMode mode, + int first, + int count) +{ + CoglVertexBuffer *buffer; + + if (!cogl_is_vertex_buffer (handle)) + return; + + buffer = handle; + + update_primitive_and_draw (buffer, mode, first, count, NULL); +} + +static CoglHandle +_cogl_vertex_buffer_indices_new_real (CoglIndices *indices) +{ + CoglVertexBufferIndices *buffer_indices = + g_slice_alloc (sizeof (CoglVertexBufferIndices)); + buffer_indices->indices = indices; + + return _cogl_vertex_buffer_indices_handle_new (buffer_indices); +} + +CoglHandle +cogl_vertex_buffer_indices_new (CoglIndicesType indices_type, + const void *indices_array, + int indices_len) +{ + CoglIndices *indices; + + _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE); + + indices = cogl_indices_new (ctx, indices_type, indices_array, indices_len); + return _cogl_vertex_buffer_indices_new_real (indices); +} + +CoglIndicesType +cogl_vertex_buffer_indices_get_type (CoglHandle indices_handle) +{ + CoglVertexBufferIndices *buffer_indices = NULL; + + if (!cogl_is_vertex_buffer_indices (indices_handle)) + return COGL_INDICES_TYPE_UNSIGNED_SHORT; + + buffer_indices = indices_handle; + + return cogl_indices_get_type (buffer_indices->indices); +} + +void +_cogl_vertex_buffer_indices_free (CoglVertexBufferIndices *buffer_indices) +{ + cogl_object_unref (buffer_indices->indices); + g_slice_free (CoglVertexBufferIndices, buffer_indices); +} + +void +cogl_vertex_buffer_draw_elements (CoglHandle handle, + CoglVerticesMode mode, + CoglHandle indices_handle, + int min_index, + int max_index, + int indices_offset, + int count) +{ + CoglVertexBuffer *buffer; + CoglVertexBufferIndices *buffer_indices; + + if (!cogl_is_vertex_buffer (handle)) + return; + + buffer = handle; + + if (!cogl_is_vertex_buffer_indices (indices_handle)) + return; + + buffer_indices = indices_handle; + + update_primitive_and_draw (buffer, mode, indices_offset, count, + buffer_indices); +} + +static void +_cogl_vertex_buffer_free (CoglVertexBuffer *buffer) +{ + GList *tmp; + + for (tmp = buffer->submitted_vbos; tmp != NULL; tmp = tmp->next) + cogl_vertex_buffer_vbo_free (tmp->data); + g_list_free (buffer->submitted_vbos); + + for (tmp = buffer->new_attributes; tmp != NULL; tmp = tmp->next) + _cogl_vertex_buffer_attrib_free (tmp->data); + g_list_free (buffer->new_attributes); + + if (buffer->primitive) + cogl_object_unref (buffer->primitive); + + g_slice_free (CoglVertexBuffer, buffer); +} + +CoglHandle +cogl_vertex_buffer_indices_get_for_quads (unsigned int n_indices) +{ + _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE); + + if (n_indices <= 256 / 4 * 6) + { + if (ctx->quad_buffer_indices_byte == COGL_INVALID_HANDLE) + { + /* NB: cogl_get_quad_indices takes n_quads not n_indices... */ + CoglIndices *indices = cogl_get_rectangle_indices (ctx, 256 / 4); + cogl_object_ref (indices); + ctx->quad_buffer_indices_byte = + _cogl_vertex_buffer_indices_new_real (indices); + } + + return ctx->quad_buffer_indices_byte; + } + else + { + if (ctx->quad_buffer_indices && + ctx->quad_buffer_indices_len < n_indices) + { + cogl_handle_unref (ctx->quad_buffer_indices); + ctx->quad_buffer_indices = COGL_INVALID_HANDLE; + } + + if (ctx->quad_buffer_indices == COGL_INVALID_HANDLE) + { + /* NB: cogl_get_quad_indices takes n_quads not n_indices... */ + CoglIndices *indices = + cogl_get_rectangle_indices (ctx, n_indices / 6); + cogl_object_ref (indices); + ctx->quad_buffer_indices = + _cogl_vertex_buffer_indices_new_real (indices); + } + + ctx->quad_buffer_indices_len = n_indices; + + return ctx->quad_buffer_indices; + } + + g_return_val_if_reached (NULL); +} + diff --git a/cogl/cogl/deprecated/cogl-vertex-buffer.h b/cogl/cogl/deprecated/cogl-vertex-buffer.h new file mode 100644 index 0000000..8b78022 --- /dev/null +++ b/cogl/cogl/deprecated/cogl-vertex-buffer.h @@ -0,0 +1,451 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __COGL_VERTEX_BUFFER_H__ +#define __COGL_VERTEX_BUFFER_H__ + +#include +#include +#include +#include + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-vertex-buffer + * @short_description: An API for submitting extensible arrays of vertex + * attributes to be mapped into the GPU for fast drawing. + * + * For example to describe a textured triangle, you could create a new cogl + * vertex buffer with 3 vertices, and then you might add 2 attributes for each + * vertex: + * + * + * a "gl_Position" describing the (x,y,z) position for each vertex. + * + * + * a "gl_MultiTexCoord0" describing the (tx,ty) texture coordinates for each + * vertex. + * + * + * + * The Vertex Buffer API is designed to be a fairly raw mechanism for + * developers to be able to submit geometry to Cogl in a format that can be + * directly consumed by an OpenGL driver and mapped into your GPU for fast + * re-use. It is designed to avoid repeated validation of the attributes by the + * driver; to minimize transport costs (e.g. considering indirect GLX + * use-cases) and to potentially avoid repeated format conversions when + * attributes are supplied in a format that is not natively supported by the + * GPU. + * + * Although this API does allow you to modify attributes after they have been + * submitted to the GPU you should be aware that modification is not that + * cheap, since it implies validating the new data and potentially the + * OpenGL driver will need to reformat it for the GPU. + * + * If at all possible think of tricks that let you re-use static attributes, + * and if you do need to repeatedly update attributes (e.g. for some kind of + * morphing geometry) then only update and re-submit the specific attributes + * that have changed. + */ + +/** + * cogl_vertex_buffer_new: + * @n_vertices: The number of vertices that your attributes will correspond to. + * + * Creates a new vertex buffer that you can use to add attributes. + * + * Return value: a new #CoglHandle + * Deprecated: 1.16: Use the #CoglPrimitive api instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_primitive_API) +CoglHandle +cogl_vertex_buffer_new (unsigned int n_vertices); + +/** + * cogl_vertex_buffer_get_n_vertices: + * @handle: A vertex buffer handle + * + * Retrieves the number of vertices that @handle represents + * + * Return value: the number of vertices + * Deprecated: 1.16: Use the #CoglPrimitive api instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_primitive_API) +unsigned int +cogl_vertex_buffer_get_n_vertices (CoglHandle handle); + +/** + * cogl_vertex_buffer_add: + * @handle: A vertex buffer handle + * @attribute_name: The name of your attribute. It should be a valid GLSL + * variable name and standard attribute types must use one of following + * built-in names: (Note: they correspond to the built-in names of GLSL) + * + * "gl_Color" + * "gl_Normal" + * "gl_MultiTexCoord0, gl_MultiTexCoord1, ..." + * "gl_Vertex" + * + * To support adding multiple variations of the same attribute the name + * can have a detail component, E.g. "gl_Color::active" or + * "gl_Color::inactive" + * @n_components: The number of components per attribute and must be 1, 2, + * 3 or 4 + * @type: a #CoglAttributeType specifying the data type of each component. + * @normalized: If %TRUE, this specifies that values stored in an integer + * format should be mapped into the range [-1.0, 1.0] or [0.0, 1.0] + * for unsigned values. If %FALSE they are converted to floats + * directly. + * @stride: This specifies the number of bytes from the start of one attribute + * value to the start of the next value (for the same attribute). So, for + * example, with a position interleved with color like this: + * XYRGBAXYRGBAXYRGBA, then if each letter represents a byte, the + * stride for both attributes is 6. The special value 0 means the + * values are stored sequentially in memory. + * @pointer: This addresses the first attribute in the vertex array. This + * must remain valid until you either call cogl_vertex_buffer_submit() or + * issue a draw call. + * + * Adds an attribute to a buffer, or replaces a previously added + * attribute with the same name. + * + * You either can use one of the built-in names such as "gl_Vertex", or + * "gl_MultiTexCoord0" to add standard attributes, like positions, colors + * and normals, or you can add custom attributes for use in shaders. + * + * The number of vertices declared when calling cogl_vertex_buffer_new() + * determines how many attribute values will be read from the supplied + * @pointer. + * + * The data for your attribute isn't copied anywhere until you call + * cogl_vertex_buffer_submit(), or issue a draw call which automatically + * submits pending attribute changes. so the supplied pointer must remain + * valid until then. If you are updating an existing attribute (done by + * re-adding it) then you still need to re-call cogl_vertex_buffer_submit() + * to commit the changes to the GPU. Be carefull to minimize the number + * of calls to cogl_vertex_buffer_submit(), though. + * + * If you are interleving attributes it is assumed that each interleaved + * attribute starts no farther than +- stride bytes from the other attributes + * it is interleved with. I.e. this is ok: + * + * |-0-0-0-0-0-0-0-0-0-0| + * + * This is not ok: + * + * |- - - - -0-0-0-0-0-0 0 0 0 0| + * + * (Though you can have multiple groups of interleved attributes) + * + * Deprecated: 1.16: Use the #CoglPrimitive api instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_primitive_API) +void +cogl_vertex_buffer_add (CoglHandle handle, + const char *attribute_name, + uint8_t n_components, + CoglAttributeType type, + CoglBool normalized, + uint16_t stride, + const void *pointer); + +/** + * cogl_vertex_buffer_delete: + * @handle: A vertex buffer handle + * @attribute_name: The name of a previously added attribute + * + * Deletes an attribute from a buffer. You will need to call + * cogl_vertex_buffer_submit() or issue a draw call to commit this + * change to the GPU. + * + * Deprecated: 1.16: Use the #CoglPrimitive api instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_primitive_API) +void +cogl_vertex_buffer_delete (CoglHandle handle, + const char *attribute_name); + +/** + * cogl_vertex_buffer_submit: + * @handle: A vertex buffer handle + * + * Submits all the user added attributes to the GPU; once submitted, the + * attributes can be used for drawing. + * + * You should aim to minimize calls to this function since it implies + * validating your data; it potentially incurs a transport cost (especially if + * you are using GLX indirect rendering) and potentially a format conversion + * cost if the GPU doesn't natively support any of the given attribute formats. + * + * Deprecated: 1.16: Use the #CoglPrimitive api instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_primitive_API) +void +cogl_vertex_buffer_submit (CoglHandle handle); + +/** + * cogl_vertex_buffer_disable: + * @handle: A vertex buffer handle + * @attribute_name: The name of the attribute you want to disable + * + * Disables a previosuly added attribute. + * + * Since it can be costly to add and remove new attributes to buffers; to make + * individual buffers more reuseable it is possible to enable and disable + * attributes before using a buffer for drawing. + * + * You don't need to call cogl_vertex_buffer_submit() after using this + * function. + * + * Deprecated: 1.16: Use the #CoglPrimitive api instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_primitive_API) +void +cogl_vertex_buffer_disable (CoglHandle handle, + const char *attribute_name); + +/** + * cogl_vertex_buffer_enable: + * @handle: A vertex buffer handle + * @attribute_name: The name of the attribute you want to enable + * + * Enables a previosuly disabled attribute. + * + * Since it can be costly to add and remove new attributes to buffers; to make + * individual buffers more reuseable it is possible to enable and disable + * attributes before using a buffer for drawing. + * + * You don't need to call cogl_vertex_buffer_submit() after using this function + * + * Deprecated: 1.16: Use the #CoglPrimitive api instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_primitive_API) +void +cogl_vertex_buffer_enable (CoglHandle handle, + const char *attribute_name); + +/** + * cogl_vertex_buffer_draw: + * @handle: A vertex buffer handle + * @mode: A #CoglVerticesMode specifying how the vertices should be + * interpreted. + * @first: Specifies the index of the first vertex you want to draw with + * @count: Specifies the number of vertices you want to draw. + * + * Allows you to draw geometry using all or a subset of the + * vertices in a vertex buffer. + * + * Any un-submitted attribute changes are automatically submitted before + * drawing. + * + * Deprecated: 1.16: Use the #CoglPrimitive api instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_primitive_API) +void +cogl_vertex_buffer_draw (CoglHandle handle, + CoglVerticesMode mode, + int first, + int count); + +/** + * cogl_vertex_buffer_indices_new: (skip) + * @indices_type: a #CoglIndicesType specifying the data type used for + * the indices. + * @indices_array: (array length=indices_len): Specifies the address of + * your array of indices + * @indices_len: The number of indices in indices_array + * + * Depending on how much geometry you are submitting it can be worthwhile + * optimizing the number of redundant vertices you submit. Using an index + * array allows you to reference vertices multiple times, for example + * during triangle strips. + * + * Return value: A CoglHandle for the indices which you can pass to + * cogl_vertex_buffer_draw_elements(). + * + * Deprecated: 1.16: Use the #CoglPrimitive api instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_primitive_API) +CoglHandle +cogl_vertex_buffer_indices_new (CoglIndicesType indices_type, + const void *indices_array, + int indices_len); + +/** + * cogl_vertex_buffer_indices_get_type: + * @indices: An indices handle + * + * Queries back the data type used for the given indices + * + * Returns: The CoglIndicesType used + * + * Deprecated: 1.16: Use the #CoglPrimitive api instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_primitive_API) +CoglIndicesType +cogl_vertex_buffer_indices_get_type (CoglHandle indices); + +/** + * cogl_vertex_buffer_draw_elements: + * @handle: A vertex buffer handle + * @mode: A #CoglVerticesMode specifying how the vertices should be + * interpreted. + * @indices: A CoglHandle for a set of indices allocated via + * cogl_vertex_buffer_indices_new () + * @min_index: Specifies the minimum vertex index contained in indices + * @max_index: Specifies the maximum vertex index contained in indices + * @indices_offset: An offset into named indices. The offset marks the first + * index to use for drawing. + * @count: Specifies the number of vertices you want to draw. + * + * This function lets you use an array of indices to specify the vertices + * within your vertex buffer that you want to draw. The indices themselves + * are created by calling cogl_vertex_buffer_indices_new () + * + * Any un-submitted attribute changes are automatically submitted before + * drawing. + * Deprecated: 1.16: Use the #CoglPrimitive api instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_primitive_API) +void +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: + * @handle: a @CoglHandle. + * + * Increment the reference count for a vertex buffer + * + * Return value: the @handle. + * + * Deprecated: 1.2: Use cogl_object_ref() instead + */ +COGL_DEPRECATED_FOR (cogl_object_ref) +CoglHandle +cogl_vertex_buffer_ref (CoglHandle handle); + +/** + * cogl_vertex_buffer_unref: + * @handle: a @CoglHandle. + * + * Decrement the reference count for a vertex buffer + * + * Deprecated: 1.2: Use cogl_object_unref() instead + */ +COGL_DEPRECATED_FOR (cogl_object_unref) +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 like that shown + * in then you can request 6 + * indices to render two triangles like those shown in . + * + *
+ * Example of vertices submitted to form a quad + * + *
+ * + *
+ * Illustration of the triangle indices that will be generated + * + *
+ * + * Returns: A %CoglHandle containing the indices. The handled is + * owned by Cogl and should not be modified or unref'd. + * + * Deprecated: 1.16: Use the #CoglPrimitive api instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_primitive_API) +CoglHandle +cogl_vertex_buffer_indices_get_for_quads (unsigned int n_indices); + +/** + * cogl_is_vertex_buffer: + * @handle: a #CoglHandle for a vertex buffer object + * + * Checks whether @handle is a Vertex Buffer Object + * + * Return value: %TRUE if the handle is a VBO, and %FALSE + * otherwise + * + * Since: 1.0 + * Deprecated: 1.16: Use the #CoglPrimitive api instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_primitive_API) +CoglBool +cogl_is_vertex_buffer (CoglHandle handle); + +/** + * cogl_is_vertex_buffer_indices: + * @handle: a #CoglHandle + * + * Checks whether @handle is a handle to the indices for a vertex + * buffer object + * + * Return value: %TRUE if the handle is indices, and %FALSE + * otherwise + * + * Since: 1.4 + * Deprecated: 1.16: Use the #CoglPrimitive api instead + */ +COGL_DEPRECATED_IN_1_16_FOR (cogl_primitive_API) +CoglBool +cogl_is_vertex_buffer_indices (CoglHandle handle); +COGL_END_DECLS + +#endif /* __COGL_VERTEX_BUFFER_H__ */ diff --git a/cogl/cogl/driver/gl/cogl-attribute-gl-private.h b/cogl/cogl/driver/gl/cogl-attribute-gl-private.h new file mode 100644 index 0000000..efb3c0e --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-attribute-gl-private.h @@ -0,0 +1,53 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef _COGL_ATTRIBUTE_GL_PRIVATE_H_ +#define _COGL_ATTRIBUTE_GL_PRIVATE_H_ + +#include "cogl-types.h" +#include "cogl-framebuffer.h" +#include "cogl-attribute.h" +#include "cogl-attribute-private.h" + +void +_cogl_gl_flush_attributes_state (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglFlushLayerState *layers_state, + CoglDrawFlags flags, + CoglAttribute **attributes, + int n_attributes); + +void +_cogl_gl_disable_all_attributes (CoglContext *ctx); + +#endif /* _COGL_ATTRIBUTE_GL_PRIVATE_H_ */ diff --git a/cogl/cogl/driver/gl/cogl-attribute-gl.c b/cogl/cogl/driver/gl/cogl-attribute-gl.c new file mode 100644 index 0000000..0599049 --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-attribute-gl.c @@ -0,0 +1,541 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010,2011,2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Neil Roberts + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include + +#include "cogl-private.h" +#include "cogl-util-gl-private.h" +#include "cogl-pipeline-opengl-private.h" +#include "cogl-error-private.h" +#include "cogl-context-private.h" +#include "cogl-attribute.h" +#include "cogl-attribute-private.h" +#include "cogl-attribute-gl-private.h" +#include "cogl-pipeline-progend-glsl-private.h" +#include "cogl-buffer-gl-private.h" + +typedef struct _ForeachChangedBitState +{ + CoglContext *context; + const CoglBitmask *new_bits; + CoglPipeline *pipeline; +} ForeachChangedBitState; + +static CoglBool +toggle_builtin_attribute_enabled_cb (int bit_num, void *user_data) +{ + ForeachChangedBitState *state = user_data; + CoglContext *context = state->context; + + _COGL_RETURN_VAL_IF_FAIL (_cogl_has_private_feature + (context, COGL_PRIVATE_FEATURE_GL_FIXED), + FALSE); + +#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) + { + CoglBool enabled = _cogl_bitmask_get (state->new_bits, bit_num); + GLenum cap; + + switch (bit_num) + { + case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY: + cap = GL_COLOR_ARRAY; + break; + case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY: + cap = GL_VERTEX_ARRAY; + break; + case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY: + cap = GL_NORMAL_ARRAY; + break; + default: + g_assert_not_reached (); + } + if (enabled) + GE (context, glEnableClientState (cap)); + else + GE (context, glDisableClientState (cap)); + } +#endif + + return TRUE; +} + +static CoglBool +toggle_texcood_attribute_enabled_cb (int bit_num, void *user_data) +{ + ForeachChangedBitState *state = user_data; + CoglContext *context = state->context; + + _COGL_RETURN_VAL_IF_FAIL (_cogl_has_private_feature + (context, COGL_PRIVATE_FEATURE_GL_FIXED), + FALSE); + +#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) + { + CoglBool enabled = _cogl_bitmask_get (state->new_bits, bit_num); + + GE( context, glClientActiveTexture (GL_TEXTURE0 + bit_num) ); + + if (enabled) + GE( context, glEnableClientState (GL_TEXTURE_COORD_ARRAY) ); + else + GE( context, glDisableClientState (GL_TEXTURE_COORD_ARRAY) ); + } +#endif + + return TRUE; +} + +static CoglBool +toggle_custom_attribute_enabled_cb (int bit_num, void *user_data) +{ + ForeachChangedBitState *state = user_data; + CoglBool enabled = _cogl_bitmask_get (state->new_bits, bit_num); + CoglContext *context = state->context; + + if (enabled) + GE( context, glEnableVertexAttribArray (bit_num) ); + else + GE( context, glDisableVertexAttribArray (bit_num) ); + + return TRUE; +} + +static void +foreach_changed_bit_and_save (CoglContext *context, + CoglBitmask *current_bits, + const CoglBitmask *new_bits, + CoglBitmaskForeachFunc callback, + ForeachChangedBitState *state) +{ + /* Get the list of bits that are different */ + _cogl_bitmask_clear_all (&context->changed_bits_tmp); + _cogl_bitmask_set_bits (&context->changed_bits_tmp, current_bits); + _cogl_bitmask_xor_bits (&context->changed_bits_tmp, new_bits); + + /* Iterate over each bit to change */ + state->new_bits = new_bits; + _cogl_bitmask_foreach (&context->changed_bits_tmp, + callback, + state); + + /* Store the new values */ + _cogl_bitmask_clear_all (current_bits); + _cogl_bitmask_set_bits (current_bits, new_bits); +} + +#ifdef COGL_PIPELINE_PROGEND_GLSL + +static void +setup_generic_buffered_attribute (CoglContext *context, + CoglPipeline *pipeline, + CoglAttribute *attribute, + uint8_t *base) +{ + int name_index = attribute->name_state->name_index; + int attrib_location = + _cogl_pipeline_progend_glsl_get_attrib_location (pipeline, name_index); + + if (attrib_location == -1) + return; + + GE( context, glVertexAttribPointer (attrib_location, + attribute->d.buffered.n_components, + attribute->d.buffered.type, + attribute->normalized, + attribute->d.buffered.stride, + base + attribute->d.buffered.offset) ); + _cogl_bitmask_set (&context->enable_custom_attributes_tmp, + attrib_location, TRUE); +} + +static void +setup_generic_const_attribute (CoglContext *context, + CoglPipeline *pipeline, + CoglAttribute *attribute) +{ + int name_index = attribute->name_state->name_index; + int attrib_location = + _cogl_pipeline_progend_glsl_get_attrib_location (pipeline, name_index); + int columns; + int i; + + if (attrib_location == -1) + return; + + if (attribute->d.constant.boxed.type == COGL_BOXED_MATRIX) + columns = attribute->d.constant.boxed.size; + else + columns = 1; + + /* Note: it's ok to access a COGL_BOXED_FLOAT as a matrix with only + * one column... */ + + switch (attribute->d.constant.boxed.size) + { + case 1: + GE( context, glVertexAttrib1fv (attrib_location, + attribute->d.constant.boxed.v.matrix)); + break; + case 2: + for (i = 0; i < columns; i++) + GE( context, glVertexAttrib2fv (attrib_location + i, + attribute->d.constant.boxed.v.matrix)); + break; + case 3: + for (i = 0; i < columns; i++) + GE( context, glVertexAttrib3fv (attrib_location + i, + attribute->d.constant.boxed.v.matrix)); + break; + case 4: + for (i = 0; i < columns; i++) + GE( context, glVertexAttrib4fv (attrib_location + i, + attribute->d.constant.boxed.v.matrix)); + break; + default: + g_warn_if_reached (); + } +} + +#endif /* COGL_PIPELINE_PROGEND_GLSL */ + +static void +setup_legacy_buffered_attribute (CoglContext *ctx, + CoglPipeline *pipeline, + CoglAttribute *attribute, + uint8_t *base) +{ + switch (attribute->name_state->name_id) + { + case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY: + _cogl_bitmask_set (&ctx->enable_builtin_attributes_tmp, + COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY, TRUE); + GE (ctx, glColorPointer (attribute->d.buffered.n_components, + attribute->d.buffered.type, + attribute->d.buffered.stride, + base + attribute->d.buffered.offset)); + break; + case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY: + _cogl_bitmask_set (&ctx->enable_builtin_attributes_tmp, + COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY, TRUE); + GE (ctx, glNormalPointer (attribute->d.buffered.type, + attribute->d.buffered.stride, + base + attribute->d.buffered.offset)); + break; + case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY: + { + int layer_number = attribute->name_state->layer_number; + const CoglPipelineGetLayerFlags flags = + COGL_PIPELINE_GET_LAYER_NO_CREATE; + CoglPipelineLayer *layer = + _cogl_pipeline_get_layer_with_flags (pipeline, layer_number, flags); + + if (layer) + { + int unit = _cogl_pipeline_layer_get_unit_index (layer); + + _cogl_bitmask_set (&ctx->enable_texcoord_attributes_tmp, + unit, + TRUE); + + GE (ctx, glClientActiveTexture (GL_TEXTURE0 + unit)); + GE (ctx, glTexCoordPointer (attribute->d.buffered.n_components, + attribute->d.buffered.type, + attribute->d.buffered.stride, + base + attribute->d.buffered.offset)); + } + break; + } + case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY: + _cogl_bitmask_set (&ctx->enable_builtin_attributes_tmp, + COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY, TRUE); + GE (ctx, glVertexPointer (attribute->d.buffered.n_components, + attribute->d.buffered.type, + attribute->d.buffered.stride, + base + attribute->d.buffered.offset)); + break; + case COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY: +#ifdef COGL_PIPELINE_PROGEND_GLSL + if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_GL_PROGRAMMABLE)) + setup_generic_buffered_attribute (ctx, pipeline, attribute, base); +#endif + break; + default: + g_warn_if_reached (); + } +} + +static void +setup_legacy_const_attribute (CoglContext *ctx, + CoglPipeline *pipeline, + CoglAttribute *attribute) +{ +#ifdef COGL_PIPELINE_PROGEND_GLSL + if (attribute->name_state->name_id == COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY) + { + if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_GL_PROGRAMMABLE)) + setup_generic_const_attribute (ctx, pipeline, attribute); + } + else +#endif + { + float vector[4] = { 0, 0, 0, 1 }; + float *boxed = attribute->d.constant.boxed.v.float_value; + int n_components = attribute->d.constant.boxed.size; + int i; + + for (i = 0; i < n_components; i++) + vector[i] = boxed[i]; + + switch (attribute->name_state->name_id) + { + case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY: + GE (ctx, glColor4f (vector[0], vector[1], vector[2], vector[3])); + break; + case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY: + GE (ctx, glNormal3f (vector[0], vector[1], vector[2])); + break; + case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY: + { + int layer_number = attribute->name_state->layer_number; + const CoglPipelineGetLayerFlags flags = + COGL_PIPELINE_GET_LAYER_NO_CREATE; + CoglPipelineLayer *layer = + _cogl_pipeline_get_layer_with_flags (pipeline, + layer_number, + flags); + + if (layer) + { + int unit = _cogl_pipeline_layer_get_unit_index (layer); + + GE (ctx, glClientActiveTexture (GL_TEXTURE0 + unit)); + + GE (ctx, glMultiTexCoord4f (vector[0], + vector[1], + vector[2], + vector[3])); + } + break; + } + case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY: + GE (ctx, glVertex4f (vector[0], vector[1], vector[2], vector[3])); + break; + default: + g_warn_if_reached (); + } + } +} + +static void +apply_attribute_enable_updates (CoglContext *context, + CoglPipeline *pipeline) +{ + ForeachChangedBitState changed_bits_state; + + changed_bits_state.context = context; + changed_bits_state.new_bits = &context->enable_builtin_attributes_tmp; + changed_bits_state.pipeline = pipeline; + + foreach_changed_bit_and_save (context, + &context->enabled_builtin_attributes, + &context->enable_builtin_attributes_tmp, + toggle_builtin_attribute_enabled_cb, + &changed_bits_state); + + changed_bits_state.new_bits = &context->enable_texcoord_attributes_tmp; + foreach_changed_bit_and_save (context, + &context->enabled_texcoord_attributes, + &context->enable_texcoord_attributes_tmp, + toggle_texcood_attribute_enabled_cb, + &changed_bits_state); + + changed_bits_state.new_bits = &context->enable_custom_attributes_tmp; + foreach_changed_bit_and_save (context, + &context->enabled_custom_attributes, + &context->enable_custom_attributes_tmp, + toggle_custom_attribute_enabled_cb, + &changed_bits_state); +} + +void +_cogl_gl_flush_attributes_state (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglFlushLayerState *layers_state, + CoglDrawFlags flags, + CoglAttribute **attributes, + int n_attributes) +{ + CoglContext *ctx = framebuffer->context; + int i; + CoglBool with_color_attrib = FALSE; + CoglBool unknown_color_alpha = FALSE; + CoglPipeline *copy = NULL; + + /* Iterate the attributes to see if we have a color attribute which + * may affect our decision to enable blending or not. + * + * We need to do this before flushing the pipeline. */ + for (i = 0; i < n_attributes; i++) + switch (attributes[i]->name_state->name_id) + { + case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY: + if ((flags & COGL_DRAW_COLOR_ATTRIBUTE_IS_OPAQUE) == 0 && + _cogl_attribute_get_n_components (attributes[i]) == 4) + unknown_color_alpha = TRUE; + with_color_attrib = TRUE; + break; + + default: + break; + } + + if (G_UNLIKELY (layers_state->options.flags)) + { + /* If we haven't already created a derived pipeline... */ + if (!copy) + { + copy = cogl_pipeline_copy (pipeline); + pipeline = copy; + } + _cogl_pipeline_apply_overrides (pipeline, &layers_state->options); + + /* TODO: + * overrides = cogl_pipeline_get_data (pipeline, + * last_overrides_key); + * if (overrides) + * { + * age = cogl_pipeline_get_age (pipeline); + * XXX: actually we also need to check for legacy_state + * and blending overrides for use of glColorPointer... + * if (overrides->ags != age || + * memcmp (&overrides->options, &options, + * sizeof (options) != 0) + * { + * cogl_object_unref (overrides->weak_pipeline); + * g_slice_free (Overrides, overrides); + * overrides = NULL; + * } + * } + * if (!overrides) + * { + * overrides = g_slice_new (Overrides); + * overrides->weak_pipeline = + * cogl_pipeline_weak_copy (pipeline); + * _cogl_pipeline_apply_overrides (overrides->weak_pipeline, + * &options); + * + * cogl_pipeline_set_data (pipeline, last_overrides_key, + * weak_overrides, + * free_overrides_cb, + * NULL); + * } + * pipeline = overrides->weak_pipeline; + */ + } + + _cogl_pipeline_flush_gl_state (ctx, + pipeline, + framebuffer, + with_color_attrib, + unknown_color_alpha); + + _cogl_bitmask_clear_all (&ctx->enable_builtin_attributes_tmp); + _cogl_bitmask_clear_all (&ctx->enable_texcoord_attributes_tmp); + _cogl_bitmask_clear_all (&ctx->enable_custom_attributes_tmp); + + /* Bind the attribute pointers. We need to do this after the + * pipeline is flushed because when using GLSL that is the only + * point when we can determine the attribute locations */ + + for (i = 0; i < n_attributes; i++) + { + CoglAttribute *attribute = attributes[i]; + CoglAttributeBuffer *attribute_buffer; + CoglBuffer *buffer; + uint8_t *base; + + if (attribute->is_buffered) + { + attribute_buffer = cogl_attribute_get_buffer (attribute); + buffer = COGL_BUFFER (attribute_buffer); + + /* Note: we don't try and catch errors with binding buffers + * here since OOM errors at this point indicate that nothing + * has yet been uploaded to attribute buffer which we + * consider to be a programmer error. + */ + base = + _cogl_buffer_gl_bind (buffer, + COGL_BUFFER_BIND_TARGET_ATTRIBUTE_BUFFER, + NULL); + + if (pipeline->progend == COGL_PIPELINE_PROGEND_GLSL) + setup_generic_buffered_attribute (ctx, pipeline, attribute, base); + else + setup_legacy_buffered_attribute (ctx, pipeline, attribute, base); + + _cogl_buffer_gl_unbind (buffer); + } + else + { + if (pipeline->progend == COGL_PIPELINE_PROGEND_GLSL) + setup_generic_const_attribute (ctx, pipeline, attribute); + else + setup_legacy_const_attribute (ctx, pipeline, attribute); + } + } + + apply_attribute_enable_updates (ctx, pipeline); + + if (copy) + cogl_object_unref (copy); +} + +void +_cogl_gl_disable_all_attributes (CoglContext *ctx) +{ + _cogl_bitmask_clear_all (&ctx->enable_builtin_attributes_tmp); + _cogl_bitmask_clear_all (&ctx->enable_texcoord_attributes_tmp); + _cogl_bitmask_clear_all (&ctx->enable_custom_attributes_tmp); + + /* XXX: we can pass a NULL source pipeline here because we know a + * source pipeline only needs to be referenced when enabling + * attributes. */ + apply_attribute_enable_updates (ctx, NULL); +} diff --git a/cogl/cogl/driver/gl/cogl-buffer-gl-private.h b/cogl/cogl/driver/gl/cogl-buffer-gl-private.h new file mode 100644 index 0000000..b8f0435 --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-buffer-gl-private.h @@ -0,0 +1,74 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef _COGL_BUFFER_GL_PRIVATE_H_ +#define _COGL_BUFFER_GL_PRIVATE_H_ + +#include "cogl-types.h" +#include "cogl-context.h" +#include "cogl-buffer.h" +#include "cogl-buffer-private.h" + +void +_cogl_buffer_gl_create (CoglBuffer *buffer); + +void +_cogl_buffer_gl_destroy (CoglBuffer *buffer); + +void * +_cogl_buffer_gl_map_range (CoglBuffer *buffer, + size_t offset, + size_t size, + CoglBufferAccess access, + CoglBufferMapHint hints, + CoglError **error); + +void +_cogl_buffer_gl_unmap (CoglBuffer *buffer); + +CoglBool +_cogl_buffer_gl_set_data (CoglBuffer *buffer, + unsigned int offset, + const void *data, + unsigned int size, + CoglError **error); + +void * +_cogl_buffer_gl_bind (CoglBuffer *buffer, + CoglBufferBindTarget target, + CoglError **error); + +void +_cogl_buffer_gl_unbind (CoglBuffer *buffer); + +#endif /* _COGL_BUFFER_GL_PRIVATE_H_ */ diff --git a/cogl/cogl/driver/gl/cogl-buffer-gl.c b/cogl/cogl/driver/gl/cogl-buffer-gl.c new file mode 100644 index 0000000..f3c134a --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-buffer-gl.c @@ -0,0 +1,435 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010,2011,2012,2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Damien Lespiau + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-context-private.h" +#include "cogl-buffer-gl-private.h" +#include "cogl-error-private.h" +#include "cogl-util-gl-private.h" + +/* + * GL/GLES compatibility defines for the buffer API: + */ + +#ifndef GL_PIXEL_PACK_BUFFER +#define GL_PIXEL_PACK_BUFFER 0x88EB +#endif +#ifndef GL_PIXEL_UNPACK_BUFFER +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#endif +#ifndef GL_ARRAY_BUFFER +#define GL_ARRAY_BUFFER 0x8892 +#endif +#ifndef GL_ELEMENT_ARRAY_BUFFER +#define GL_ARRAY_BUFFER 0x8893 +#endif +#ifndef GL_READ_ONLY +#define GL_READ_ONLY 0x88B8 +#endif +#ifndef GL_WRITE_ONLY +#define GL_WRITE_ONLY 0x88B9 +#endif +#ifndef GL_READ_WRITE +#define GL_READ_WRITE 0x88BA +#endif +#ifndef GL_MAP_READ_BIT +#define GL_MAP_READ_BIT 0x0001 +#endif +#ifndef GL_MAP_WRITE_BIT +#define GL_MAP_WRITE_BIT 0x0002 +#endif +#ifndef GL_MAP_INVALIDATE_RANGE_BIT +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#endif +#ifndef GL_MAP_INVALIDATE_BUFFER_BIT +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#endif + +void +_cogl_buffer_gl_create (CoglBuffer *buffer) +{ + CoglContext *ctx = buffer->context; + + GE (ctx, glGenBuffers (1, &buffer->gl_handle)); +} + +void +_cogl_buffer_gl_destroy (CoglBuffer *buffer) +{ + GE( buffer->context, glDeleteBuffers (1, &buffer->gl_handle) ); +} + +static GLenum +update_hints_to_gl_enum (CoglBuffer *buffer) +{ + /* usage hint is always DRAW for now */ + switch (buffer->update_hint) + { + case COGL_BUFFER_UPDATE_HINT_STATIC: + return GL_STATIC_DRAW; + case COGL_BUFFER_UPDATE_HINT_DYNAMIC: + return GL_DYNAMIC_DRAW; + + case COGL_BUFFER_UPDATE_HINT_STREAM: + /* OpenGL ES 1.1 only knows about STATIC_DRAW and DYNAMIC_DRAW */ +#if defined(HAVE_COGL_GL) || defined(HAVE_COGL_GLES2) + if (buffer->context->driver != COGL_DRIVER_GLES1) + return GL_STREAM_DRAW; +#else + return GL_DYNAMIC_DRAW; +#endif + } + + g_assert_not_reached (); +} + +static GLenum +convert_bind_target_to_gl_target (CoglBufferBindTarget target) +{ + switch (target) + { + case COGL_BUFFER_BIND_TARGET_PIXEL_PACK: + return GL_PIXEL_PACK_BUFFER; + case COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK: + return GL_PIXEL_UNPACK_BUFFER; + case COGL_BUFFER_BIND_TARGET_ATTRIBUTE_BUFFER: + return GL_ARRAY_BUFFER; + case COGL_BUFFER_BIND_TARGET_INDEX_BUFFER: + return GL_ELEMENT_ARRAY_BUFFER; + default: + g_return_val_if_reached (COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK); + } +} + +static CoglBool +recreate_store (CoglBuffer *buffer, + CoglError **error) +{ + CoglContext *ctx = buffer->context; + GLenum gl_target; + GLenum gl_enum; + + /* This assumes the buffer is already bound */ + + gl_target = convert_bind_target_to_gl_target (buffer->last_target); + gl_enum = update_hints_to_gl_enum (buffer); + + /* Clear any GL errors */ + _cogl_gl_util_clear_gl_errors (ctx); + + ctx->glBufferData (gl_target, + buffer->size, + NULL, + gl_enum); + + if (_cogl_gl_util_catch_out_of_memory (ctx, error)) + return FALSE; + + buffer->store_created = TRUE; + return TRUE; +} + +GLenum +_cogl_buffer_access_to_gl_enum (CoglBufferAccess access) +{ + if ((access & COGL_BUFFER_ACCESS_READ_WRITE) == COGL_BUFFER_ACCESS_READ_WRITE) + return GL_READ_WRITE; + else if (access & COGL_BUFFER_ACCESS_WRITE) + return GL_WRITE_ONLY; + else + return GL_READ_ONLY; +} + +static void * +_cogl_buffer_bind_no_create (CoglBuffer *buffer, + CoglBufferBindTarget target) +{ + CoglContext *ctx = buffer->context; + + _COGL_RETURN_VAL_IF_FAIL (buffer != NULL, NULL); + + /* Don't allow binding the buffer to multiple targets at the same time */ + _COGL_RETURN_VAL_IF_FAIL (ctx->current_buffer[buffer->last_target] != buffer, + NULL); + + /* Don't allow nesting binds to the same target */ + _COGL_RETURN_VAL_IF_FAIL (ctx->current_buffer[target] == NULL, NULL); + + buffer->last_target = target; + ctx->current_buffer[target] = buffer; + + if (buffer->flags & COGL_BUFFER_FLAG_BUFFER_OBJECT) + { + GLenum gl_target = convert_bind_target_to_gl_target (buffer->last_target); + GE( ctx, glBindBuffer (gl_target, buffer->gl_handle) ); + return NULL; + } + else + return buffer->data; +} + +void * +_cogl_buffer_gl_map_range (CoglBuffer *buffer, + size_t offset, + size_t size, + CoglBufferAccess access, + CoglBufferMapHint hints, + CoglError **error) +{ + uint8_t *data; + CoglBufferBindTarget target; + GLenum gl_target; + CoglContext *ctx = buffer->context; + + if (((access & COGL_BUFFER_ACCESS_READ) && + !cogl_has_feature (ctx, COGL_FEATURE_ID_MAP_BUFFER_FOR_READ)) || + ((access & COGL_BUFFER_ACCESS_WRITE) && + !cogl_has_feature (ctx, COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE))) + { + _cogl_set_error (error, + COGL_SYSTEM_ERROR, + COGL_SYSTEM_ERROR_UNSUPPORTED, + "Tried to map a buffer with unsupported access mode"); + return NULL; + } + + target = buffer->last_target; + _cogl_buffer_bind_no_create (buffer, target); + + gl_target = convert_bind_target_to_gl_target (target); + + if ((hints & COGL_BUFFER_MAP_HINT_DISCARD_RANGE) && + offset == 0 && size >= buffer->size) + hints |= COGL_BUFFER_MAP_HINT_DISCARD; + + /* If the map buffer range extension is supported then we will + * always use it even if we are mapping the full range because the + * normal mapping function doesn't support passing the discard + * hints */ + if (ctx->glMapBufferRange) + { + GLbitfield gl_access = 0; + CoglBool should_recreate_store = !buffer->store_created; + + if ((access & COGL_BUFFER_ACCESS_READ)) + gl_access |= GL_MAP_READ_BIT; + if ((access & COGL_BUFFER_ACCESS_WRITE)) + gl_access |= GL_MAP_WRITE_BIT; + + if ((hints & COGL_BUFFER_MAP_HINT_DISCARD)) + { + /* glMapBufferRange generates an error if you pass the + * discard hint along with asking for read access. However + * it can make sense to ask for both if write access is also + * requested so that the application can immediately read + * back what it just wrote. To work around the restriction + * in GL we just recreate the buffer storage in that case + * which is an alternative way to indicate that the buffer + * contents can be discarded. */ + if ((access & COGL_BUFFER_ACCESS_READ)) + should_recreate_store = TRUE; + else + gl_access |= GL_MAP_INVALIDATE_BUFFER_BIT; + } + else if ((hints & COGL_BUFFER_MAP_HINT_DISCARD_RANGE) && + !(access & COGL_BUFFER_ACCESS_READ)) + gl_access |= GL_MAP_INVALIDATE_RANGE_BIT; + + if (should_recreate_store) + { + if (!recreate_store (buffer, error)) + { + _cogl_buffer_gl_unbind (buffer); + return NULL; + } + } + + /* Clear any GL errors */ + _cogl_gl_util_clear_gl_errors (ctx); + + data = ctx->glMapBufferRange (gl_target, + offset, + size, + gl_access); + + if (_cogl_gl_util_catch_out_of_memory (ctx, error)) + { + _cogl_buffer_gl_unbind (buffer); + return NULL; + } + + _COGL_RETURN_VAL_IF_FAIL (data != NULL, NULL); + } + else + { + /* create an empty store if we don't have one yet. creating the store + * lazily allows the user of the CoglBuffer to set a hint before the + * store is created. */ + if (!buffer->store_created || + (hints & COGL_BUFFER_MAP_HINT_DISCARD)) + { + if (!recreate_store (buffer, error)) + { + _cogl_buffer_gl_unbind (buffer); + return NULL; + } + } + + /* Clear any GL errors */ + _cogl_gl_util_clear_gl_errors (ctx); + + data = ctx->glMapBuffer (gl_target, + _cogl_buffer_access_to_gl_enum (access)); + + if (_cogl_gl_util_catch_out_of_memory (ctx, error)) + { + _cogl_buffer_gl_unbind (buffer); + return NULL; + } + + _COGL_RETURN_VAL_IF_FAIL (data != NULL, NULL); + + data += offset; + } + + if (data) + buffer->flags |= COGL_BUFFER_FLAG_MAPPED; + + _cogl_buffer_gl_unbind (buffer); + + return data; +} + +void +_cogl_buffer_gl_unmap (CoglBuffer *buffer) +{ + CoglContext *ctx = buffer->context; + + _cogl_buffer_bind_no_create (buffer, buffer->last_target); + + GE( ctx, glUnmapBuffer (convert_bind_target_to_gl_target + (buffer->last_target)) ); + buffer->flags &= ~COGL_BUFFER_FLAG_MAPPED; + + _cogl_buffer_gl_unbind (buffer); +} + +CoglBool +_cogl_buffer_gl_set_data (CoglBuffer *buffer, + unsigned int offset, + const void *data, + unsigned int size, + CoglError **error) +{ + CoglBufferBindTarget target; + GLenum gl_target; + CoglContext *ctx = buffer->context; + CoglBool status = TRUE; + CoglError *internal_error = NULL; + + target = buffer->last_target; + + _cogl_buffer_gl_bind (buffer, target, &internal_error); + + /* NB: _cogl_buffer_gl_bind() may return NULL in non-error + * conditions so we have to explicity check internal_error + * to see if an exception was thrown. + */ + if (internal_error) + { + _cogl_propagate_error (error, internal_error); + return FALSE; + } + + gl_target = convert_bind_target_to_gl_target (target); + + /* Clear any GL errors */ + _cogl_gl_util_clear_gl_errors (ctx); + + ctx->glBufferSubData (gl_target, offset, size, data); + + if (_cogl_gl_util_catch_out_of_memory (ctx, error)) + status = FALSE; + + _cogl_buffer_gl_unbind (buffer); + + return status; +} + +void * +_cogl_buffer_gl_bind (CoglBuffer *buffer, + CoglBufferBindTarget target, + CoglError **error) +{ + void *ret; + + ret = _cogl_buffer_bind_no_create (buffer, target); + + /* create an empty store if we don't have one yet. creating the store + * lazily allows the user of the CoglBuffer to set a hint before the + * store is created. */ + if ((buffer->flags & COGL_BUFFER_FLAG_BUFFER_OBJECT) && + !buffer->store_created) + { + if (!recreate_store (buffer, error)) + { + _cogl_buffer_gl_unbind (buffer); + return NULL; + } + } + + return ret; +} + +void +_cogl_buffer_gl_unbind (CoglBuffer *buffer) +{ + CoglContext *ctx = buffer->context; + + _COGL_RETURN_IF_FAIL (buffer != NULL); + + /* the unbind should pair up with a previous bind */ + _COGL_RETURN_IF_FAIL (ctx->current_buffer[buffer->last_target] == buffer); + + if (buffer->flags & COGL_BUFFER_FLAG_BUFFER_OBJECT) + { + GLenum gl_target = convert_bind_target_to_gl_target (buffer->last_target); + GE( ctx, glBindBuffer (gl_target, 0) ); + } + + ctx->current_buffer[buffer->last_target] = NULL; +} diff --git a/cogl/cogl/driver/gl/cogl-clip-stack-gl-private.h b/cogl/cogl/driver/gl/cogl-clip-stack-gl-private.h new file mode 100644 index 0000000..ff22d26 --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-clip-stack-gl-private.h @@ -0,0 +1,45 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef _COGL_CLIP_STACK_GL_PRIVATE_H_ +#define _COGL_CLIP_STACK_GL_PRIVATE_H_ + +#include "cogl-types.h" +#include "cogl-framebuffer.h" +#include "cogl-clip-stack.h" + +void +_cogl_clip_stack_gl_flush (CoglClipStack *stack, + CoglFramebuffer *framebuffer); + +#endif /* _COGL_CLIP_STACK_GL_PRIVATE_H_ */ diff --git a/cogl/cogl/driver/gl/cogl-clip-stack-gl.c b/cogl/cogl/driver/gl/cogl-clip-stack-gl.c new file mode 100644 index 0000000..5c77e07 --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-clip-stack-gl.c @@ -0,0 +1,627 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2010,2011,2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Neil Roberts + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-context-private.h" +#include "cogl-util-gl-private.h" +#include "cogl-primitives-private.h" +#include "cogl-pipeline-opengl-private.h" +#include "cogl-clip-stack-gl-private.h" +#include "cogl-primitive-private.h" + +#ifndef GL_CLIP_PLANE0 +#define GL_CLIP_PLANE0 0x3000 +#define GL_CLIP_PLANE1 0x3001 +#define GL_CLIP_PLANE2 0x3002 +#define GL_CLIP_PLANE3 0x3003 +#define GL_CLIP_PLANE4 0x3004 +#define GL_CLIP_PLANE5 0x3005 +#endif + +static void +project_vertex (const CoglMatrix *modelview_projection, + float *vertex) +{ + int i; + + cogl_matrix_transform_point (modelview_projection, + &vertex[0], &vertex[1], + &vertex[2], &vertex[3]); + + /* Convert from homogenized coordinates */ + for (i = 0; i < 4; i++) + vertex[i] /= vertex[3]; +} + +static void +set_clip_plane (CoglFramebuffer *framebuffer, + int plane_num, + const float *vertex_a, + const float *vertex_b) +{ + CoglContext *ctx = framebuffer->context; + float planef[4]; + double planed[4]; + float angle; + CoglMatrixStack *modelview_stack = + _cogl_framebuffer_get_modelview_stack (framebuffer); + CoglMatrixStack *projection_stack = + _cogl_framebuffer_get_projection_stack (framebuffer); + CoglMatrix inverse_projection; + + cogl_matrix_stack_get_inverse (projection_stack, &inverse_projection); + + /* Calculate the angle between the axes and the line crossing the + two points */ + angle = atan2f (vertex_b[1] - vertex_a[1], + vertex_b[0] - vertex_a[0]) * (180.0/G_PI); + + cogl_matrix_stack_push (modelview_stack); + + /* Load the inverse of the projection matrix so we can specify the plane + * in screen coordinates */ + cogl_matrix_stack_set (modelview_stack, &inverse_projection); + + /* Rotate about point a */ + cogl_matrix_stack_translate (modelview_stack, + vertex_a[0], vertex_a[1], vertex_a[2]); + /* Rotate the plane by the calculated angle so that it will connect + the two points */ + cogl_matrix_stack_rotate (modelview_stack, angle, 0.0f, 0.0f, 1.0f); + cogl_matrix_stack_translate (modelview_stack, + -vertex_a[0], -vertex_a[1], -vertex_a[2]); + + /* Clip planes can only be used when a fixed function backend is in + use so we know we can directly push this matrix to the builtin + state */ + _cogl_matrix_entry_flush_to_gl_builtins (ctx, + modelview_stack->last_entry, + COGL_MATRIX_MODELVIEW, + framebuffer, + FALSE /* don't disable flip */); + + planef[0] = 0; + planef[1] = -1.0; + planef[2] = 0; + planef[3] = vertex_a[1]; + + switch (ctx->driver) + { + default: + g_assert_not_reached (); + break; + + case COGL_DRIVER_GLES1: + GE( ctx, glClipPlanef (plane_num, planef) ); + break; + + case COGL_DRIVER_GL: + case COGL_DRIVER_GL3: + planed[0] = planef[0]; + planed[1] = planef[1]; + planed[2] = planef[2]; + planed[3] = planef[3]; + GE( ctx, glClipPlane (plane_num, planed) ); + break; + } + + cogl_matrix_stack_pop (modelview_stack); +} + +static void +set_clip_planes (CoglFramebuffer *framebuffer, + CoglMatrixEntry *modelview_entry, + float x_1, + float y_1, + float x_2, + float y_2) +{ + CoglMatrix modelview_matrix; + CoglMatrixStack *projection_stack = + _cogl_framebuffer_get_projection_stack (framebuffer); + CoglMatrix projection_matrix; + CoglMatrix modelview_projection; + float signed_area; + + float vertex_tl[4] = { x_1, y_1, 0, 1.0 }; + float vertex_tr[4] = { x_2, y_1, 0, 1.0 }; + float vertex_bl[4] = { x_1, y_2, 0, 1.0 }; + float vertex_br[4] = { x_2, y_2, 0, 1.0 }; + + cogl_matrix_stack_get (projection_stack, &projection_matrix); + cogl_matrix_entry_get (modelview_entry, &modelview_matrix); + + cogl_matrix_multiply (&modelview_projection, + &projection_matrix, + &modelview_matrix); + + project_vertex (&modelview_projection, vertex_tl); + project_vertex (&modelview_projection, vertex_tr); + project_vertex (&modelview_projection, vertex_bl); + project_vertex (&modelview_projection, vertex_br); + + /* Calculate the signed area of the polygon formed by the four + vertices so that we can know its orientation */ + signed_area = (vertex_tl[0] * (vertex_tr[1] - vertex_bl[1]) + + vertex_tr[0] * (vertex_br[1] - vertex_tl[1]) + + vertex_br[0] * (vertex_bl[1] - vertex_tr[1]) + + vertex_bl[0] * (vertex_tl[1] - vertex_br[1])); + + /* Set the clip planes to form lines between all of the vertices + using the same orientation as we calculated */ + if (signed_area > 0.0f) + { + /* counter-clockwise */ + set_clip_plane (framebuffer, GL_CLIP_PLANE0, vertex_tl, vertex_bl); + set_clip_plane (framebuffer, GL_CLIP_PLANE1, vertex_bl, vertex_br); + set_clip_plane (framebuffer, GL_CLIP_PLANE2, vertex_br, vertex_tr); + set_clip_plane (framebuffer, GL_CLIP_PLANE3, vertex_tr, vertex_tl); + } + else + { + /* clockwise */ + set_clip_plane (framebuffer, GL_CLIP_PLANE0, vertex_tl, vertex_tr); + set_clip_plane (framebuffer, GL_CLIP_PLANE1, vertex_tr, vertex_br); + set_clip_plane (framebuffer, GL_CLIP_PLANE2, vertex_br, vertex_bl); + set_clip_plane (framebuffer, GL_CLIP_PLANE3, vertex_bl, vertex_tl); + } +} + +static void +add_stencil_clip_rectangle (CoglFramebuffer *framebuffer, + CoglMatrixEntry *modelview_entry, + float x_1, + float y_1, + float x_2, + float y_2, + CoglBool first) +{ + CoglMatrixStack *projection_stack = + _cogl_framebuffer_get_projection_stack (framebuffer); + CoglContext *ctx = cogl_framebuffer_get_context (framebuffer); + + /* NB: This can be called while flushing the journal so we need + * to be very conservative with what state we change. + */ + + _cogl_context_set_current_projection_entry (ctx, + projection_stack->last_entry); + _cogl_context_set_current_modelview_entry (ctx, modelview_entry); + + if (first) + { + GE( ctx, glEnable (GL_STENCIL_TEST) ); + + /* Initially disallow everything */ + GE( ctx, glClearStencil (0) ); + GE( ctx, glClear (GL_STENCIL_BUFFER_BIT) ); + + /* Punch out a hole to allow the rectangle */ + GE( ctx, glStencilFunc (GL_NEVER, 0x1, 0x1) ); + GE( ctx, glStencilOp (GL_REPLACE, GL_REPLACE, GL_REPLACE) ); + + _cogl_rectangle_immediate (framebuffer, + ctx->stencil_pipeline, + x_1, y_1, x_2, y_2); + } + else + { + /* Add one to every pixel of the stencil buffer in the + rectangle */ + GE( ctx, glStencilFunc (GL_NEVER, 0x1, 0x3) ); + GE( ctx, glStencilOp (GL_INCR, GL_INCR, GL_INCR) ); + _cogl_rectangle_immediate (framebuffer, + ctx->stencil_pipeline, + x_1, y_1, x_2, y_2); + + /* Subtract one from all pixels in the stencil buffer so that + only pixels where both the original stencil buffer and the + rectangle are set will be valid */ + GE( ctx, glStencilOp (GL_DECR, GL_DECR, GL_DECR) ); + + _cogl_context_set_current_projection_entry (ctx, &ctx->identity_entry); + _cogl_context_set_current_modelview_entry (ctx, &ctx->identity_entry); + + _cogl_rectangle_immediate (framebuffer, + ctx->stencil_pipeline, + -1.0, -1.0, 1.0, 1.0); + } + + /* Restore the stencil mode */ + GE( ctx, glStencilFunc (GL_EQUAL, 0x1, 0x1) ); + GE( ctx, glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP) ); +} + +typedef void (*SilhouettePaintCallback) (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + void *user_data); + +static void +add_stencil_clip_silhouette (CoglFramebuffer *framebuffer, + SilhouettePaintCallback silhouette_callback, + CoglMatrixEntry *modelview_entry, + float bounds_x1, + float bounds_y1, + float bounds_x2, + float bounds_y2, + CoglBool merge, + CoglBool need_clear, + void *user_data) +{ + CoglMatrixStack *projection_stack = + _cogl_framebuffer_get_projection_stack (framebuffer); + CoglContext *ctx = cogl_framebuffer_get_context (framebuffer); + + /* NB: This can be called while flushing the journal so we need + * to be very conservative with what state we change. + */ + + _cogl_context_set_current_projection_entry (ctx, + projection_stack->last_entry); + _cogl_context_set_current_modelview_entry (ctx, modelview_entry); + + _cogl_pipeline_flush_gl_state (ctx, ctx->stencil_pipeline, + framebuffer, FALSE, FALSE); + + GE( ctx, glEnable (GL_STENCIL_TEST) ); + + GE( ctx, glColorMask (FALSE, FALSE, FALSE, FALSE) ); + GE( ctx, glDepthMask (FALSE) ); + + if (merge) + { + GE (ctx, glStencilMask (2)); + GE (ctx, glStencilFunc (GL_LEQUAL, 0x2, 0x6)); + } + else + { + /* If we're not using the stencil buffer for clipping then we + don't need to clear the whole stencil buffer, just the area + that will be drawn */ + if (need_clear) + /* If this is being called from the clip stack code then it + will have set up a scissor for the minimum bounding box of + all of the clips. That box will likely mean that this + _cogl_clear won't need to clear the entire + buffer. _cogl_framebuffer_clear_without_flush4f is used instead + of cogl_clear because it won't try to flush the journal */ + _cogl_framebuffer_clear_without_flush4f (framebuffer, + COGL_BUFFER_BIT_STENCIL, + 0, 0, 0, 0); + else + { + /* Just clear the bounding box */ + GE( ctx, glStencilMask (~(GLuint) 0) ); + GE( ctx, glStencilOp (GL_ZERO, GL_ZERO, GL_ZERO) ); + _cogl_rectangle_immediate (framebuffer, + ctx->stencil_pipeline, + bounds_x1, bounds_y1, + bounds_x2, bounds_y2); + } + GE (ctx, glStencilMask (1)); + GE (ctx, glStencilFunc (GL_LEQUAL, 0x1, 0x3)); + } + + GE (ctx, glStencilOp (GL_INVERT, GL_INVERT, GL_INVERT)); + + silhouette_callback (framebuffer, ctx->stencil_pipeline, user_data); + + if (merge) + { + /* Now we have the new stencil buffer in bit 1 and the old + stencil buffer in bit 0 so we need to intersect them */ + GE (ctx, glStencilMask (3)); + GE (ctx, glStencilFunc (GL_NEVER, 0x2, 0x3)); + GE (ctx, glStencilOp (GL_DECR, GL_DECR, GL_DECR)); + /* Decrement all of the bits twice so that only pixels where the + value is 3 will remain */ + + _cogl_context_set_current_projection_entry (ctx, &ctx->identity_entry); + _cogl_context_set_current_modelview_entry (ctx, &ctx->identity_entry); + + _cogl_rectangle_immediate (framebuffer, ctx->stencil_pipeline, + -1.0, -1.0, 1.0, 1.0); + _cogl_rectangle_immediate (framebuffer, ctx->stencil_pipeline, + -1.0, -1.0, 1.0, 1.0); + } + + GE (ctx, glStencilMask (~(GLuint) 0)); + GE (ctx, glDepthMask (TRUE)); + GE (ctx, glColorMask (TRUE, TRUE, TRUE, TRUE)); + + GE (ctx, glStencilFunc (GL_EQUAL, 0x1, 0x1)); + GE (ctx, glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP)); +} + +static void +paint_primitive_silhouette (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + void *user_data) +{ + _cogl_primitive_draw (user_data, + framebuffer, + pipeline, + COGL_DRAW_SKIP_JOURNAL_FLUSH | + COGL_DRAW_SKIP_PIPELINE_VALIDATION | + COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH | + COGL_DRAW_SKIP_LEGACY_STATE); +} + +static void +add_stencil_clip_primitive (CoglFramebuffer *framebuffer, + CoglMatrixEntry *modelview_entry, + CoglPrimitive *primitive, + float bounds_x1, + float bounds_y1, + float bounds_x2, + float bounds_y2, + CoglBool merge, + CoglBool need_clear) +{ + add_stencil_clip_silhouette (framebuffer, + paint_primitive_silhouette, + modelview_entry, + bounds_x1, + bounds_y1, + bounds_x2, + bounds_y2, + merge, + need_clear, + primitive); +} + +static void +enable_clip_planes (CoglContext *ctx) +{ + GE( ctx, glEnable (GL_CLIP_PLANE0) ); + GE( ctx, glEnable (GL_CLIP_PLANE1) ); + GE( ctx, glEnable (GL_CLIP_PLANE2) ); + GE( ctx, glEnable (GL_CLIP_PLANE3) ); +} + +static void +disable_clip_planes (CoglContext *ctx) +{ + GE( ctx, glDisable (GL_CLIP_PLANE3) ); + GE( ctx, glDisable (GL_CLIP_PLANE2) ); + GE( ctx, glDisable (GL_CLIP_PLANE1) ); + GE( ctx, glDisable (GL_CLIP_PLANE0) ); +} + +void +_cogl_clip_stack_gl_flush (CoglClipStack *stack, + CoglFramebuffer *framebuffer) +{ + CoglContext *ctx = framebuffer->context; + int has_clip_planes; + CoglBool using_clip_planes = FALSE; + CoglBool using_stencil_buffer = FALSE; + int scissor_x0; + int scissor_y0; + int scissor_x1; + int scissor_y1; + CoglClipStack *entry; + int scissor_y_start; + + /* If we have already flushed this state then we don't need to do + anything */ + if (ctx->current_clip_stack_valid) + { + if (ctx->current_clip_stack == stack && + (ctx->needs_viewport_scissor_workaround == FALSE || + (framebuffer->viewport_age == + framebuffer->viewport_age_for_scissor_workaround && + ctx->viewport_scissor_workaround_framebuffer == + framebuffer))) + return; + + _cogl_clip_stack_unref (ctx->current_clip_stack); + } + + ctx->current_clip_stack_valid = TRUE; + ctx->current_clip_stack = _cogl_clip_stack_ref (stack); + + has_clip_planes = + _cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_FOUR_CLIP_PLANES); + + if (has_clip_planes) + disable_clip_planes (ctx); + GE( ctx, glDisable (GL_STENCIL_TEST) ); + + /* If the stack is empty then there's nothing else to do + * + * See comment below about ctx->needs_viewport_scissor_workaround + */ + if (stack == NULL && !ctx->needs_viewport_scissor_workaround) + { + COGL_NOTE (CLIPPING, "Flushed empty clip stack"); + + ctx->current_clip_stack_uses_stencil = FALSE; + GE (ctx, glDisable (GL_SCISSOR_TEST)); + return; + } + + /* Calculate the scissor rect first so that if we eventually have to + clear the stencil buffer then the clear will be clipped to the + intersection of all of the bounding boxes. This saves having to + clear the whole stencil buffer */ + _cogl_clip_stack_get_bounds (stack, + &scissor_x0, &scissor_y0, + &scissor_x1, &scissor_y1); + + /* XXX: ONGOING BUG: Intel viewport scissor + * + * Intel gen6 drivers don't correctly handle offset viewports, since + * primitives aren't clipped within the bounds of the viewport. To + * workaround this we push our own clip for the viewport that will + * use scissoring to ensure we clip as expected. + * + * TODO: file a bug upstream! + */ + if (ctx->needs_viewport_scissor_workaround) + { + _cogl_util_scissor_intersect (framebuffer->viewport_x, + framebuffer->viewport_y, + framebuffer->viewport_x + + framebuffer->viewport_width, + framebuffer->viewport_y + + framebuffer->viewport_height, + &scissor_x0, &scissor_y0, + &scissor_x1, &scissor_y1); + framebuffer->viewport_age_for_scissor_workaround = + framebuffer->viewport_age; + ctx->viewport_scissor_workaround_framebuffer = + framebuffer; + } + + /* Enable scissoring as soon as possible */ + if (scissor_x0 >= scissor_x1 || scissor_y0 >= scissor_y1) + scissor_x0 = scissor_y0 = scissor_x1 = scissor_y1 = scissor_y_start = 0; + else + { + /* We store the entry coordinates in Cogl coordinate space + * but OpenGL requires the window origin to be the bottom + * left so we may need to convert the incoming coordinates. + * + * NB: Cogl forces all offscreen rendering to be done upside + * down so in this case no conversion is needed. + */ + + if (cogl_is_offscreen (framebuffer)) + scissor_y_start = scissor_y0; + else + { + int framebuffer_height = + cogl_framebuffer_get_height (framebuffer); + + scissor_y_start = framebuffer_height - scissor_y1; + } + } + + COGL_NOTE (CLIPPING, "Flushing scissor to (%i, %i, %i, %i)", + scissor_x0, scissor_y0, + scissor_x1, scissor_y1); + + GE (ctx, glEnable (GL_SCISSOR_TEST)); + GE (ctx, glScissor (scissor_x0, scissor_y_start, + scissor_x1 - scissor_x0, + scissor_y1 - scissor_y0)); + + /* Add all of the entries. This will end up adding them in the + reverse order that they were specified but as all of the clips + are intersecting it should work out the same regardless of the + order */ + for (entry = stack; entry; entry = entry->parent) + { + switch (entry->type) + { + case COGL_CLIP_STACK_PRIMITIVE: + { + CoglClipStackPrimitive *primitive_entry = + (CoglClipStackPrimitive *) entry; + + COGL_NOTE (CLIPPING, "Adding stencil clip for primitive"); + + add_stencil_clip_primitive (framebuffer, + primitive_entry->matrix_entry, + primitive_entry->primitive, + primitive_entry->bounds_x1, + primitive_entry->bounds_y1, + primitive_entry->bounds_x2, + primitive_entry->bounds_y2, + using_stencil_buffer, + TRUE); + + using_stencil_buffer = TRUE; + break; + } + case COGL_CLIP_STACK_RECT: + { + CoglClipStackRect *rect = (CoglClipStackRect *) entry; + + /* We don't need to do anything extra if the clip for this + rectangle was entirely described by its scissor bounds */ + if (!rect->can_be_scissor) + { + /* If we support clip planes and we haven't already used + them then use that instead */ + if (has_clip_planes) + { + COGL_NOTE (CLIPPING, + "Adding clip planes clip for rectangle"); + + set_clip_planes (framebuffer, + rect->matrix_entry, + rect->x0, + rect->y0, + rect->x1, + rect->y1); + using_clip_planes = TRUE; + /* We can't use clip planes a second time */ + has_clip_planes = FALSE; + } + else + { + COGL_NOTE (CLIPPING, "Adding stencil clip for rectangle"); + + add_stencil_clip_rectangle (framebuffer, + rect->matrix_entry, + rect->x0, + rect->y0, + rect->x1, + rect->y1, + !using_stencil_buffer); + using_stencil_buffer = TRUE; + } + } + break; + } + case COGL_CLIP_STACK_WINDOW_RECT: + break; + /* We don't need to do anything for window space rectangles because + * their functionality is entirely implemented by the entry bounding + * box */ + } + } + + /* Enabling clip planes is delayed to now so that they won't affect + setting up the stencil buffer */ + if (using_clip_planes) + enable_clip_planes (ctx); + + ctx->current_clip_stack_uses_stencil = using_stencil_buffer; +} diff --git a/cogl/cogl/driver/gl/cogl-framebuffer-gl-private.h b/cogl/cogl/driver/gl/cogl-framebuffer-gl-private.h new file mode 100644 index 0000000..47a1c1c --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-framebuffer-gl-private.h @@ -0,0 +1,102 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009,2010,2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_FRAMEBUFFER_GL_PRIVATE_H__ +#define __COGL_FRAMEBUFFER_GL_PRIVATE_H__ + +CoglBool +_cogl_offscreen_gl_allocate (CoglOffscreen *offscreen, + CoglError **error); + +void +_cogl_offscreen_gl_free (CoglOffscreen *offscreen); + +void +_cogl_framebuffer_gl_flush_state (CoglFramebuffer *draw_buffer, + CoglFramebuffer *read_buffer, + CoglFramebufferState state); + +void +_cogl_framebuffer_gl_clear (CoglFramebuffer *framebuffer, + unsigned long buffers, + float red, + float green, + float blue, + float alpha); + +void +_cogl_framebuffer_gl_query_bits (CoglFramebuffer *framebuffer, + CoglFramebufferBits *bits); + +void +_cogl_framebuffer_gl_finish (CoglFramebuffer *framebuffer); + +void +_cogl_framebuffer_gl_discard_buffers (CoglFramebuffer *framebuffer, + unsigned long buffers); + +void +_cogl_framebuffer_gl_bind (CoglFramebuffer *framebuffer, GLenum target); + +void +_cogl_framebuffer_gl_draw_attributes (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglVerticesMode mode, + int first_vertex, + int n_vertices, + CoglAttribute **attributes, + int n_attributes, + CoglDrawFlags flags); + +void +_cogl_framebuffer_gl_draw_indexed_attributes (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglVerticesMode mode, + int first_vertex, + int n_vertices, + CoglIndices *indices, + CoglAttribute **attributes, + int n_attributes, + CoglDrawFlags flags); + +CoglBool +_cogl_framebuffer_gl_read_pixels_into_bitmap (CoglFramebuffer *framebuffer, + int x, + int y, + CoglReadPixelsFlags source, + CoglBitmap *bitmap, + CoglError **error); + +#endif /* __COGL_FRAMEBUFFER_GL_PRIVATE_H__ */ + + diff --git a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c new file mode 100644 index 0000000..18ba08a --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c @@ -0,0 +1,1624 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-context-private.h" +#include "cogl-util-gl-private.h" +#include "cogl-framebuffer-private.h" +#include "cogl-framebuffer-gl-private.h" +#include "cogl-buffer-gl-private.h" +#include "cogl-error-private.h" +#include "cogl-texture-gl-private.h" +#include "cogl-texture-private.h" + +#include +#include + +#ifndef GL_FRAMEBUFFER +#define GL_FRAMEBUFFER 0x8D40 +#endif +#ifndef GL_RENDERBUFFER +#define GL_RENDERBUFFER 0x8D41 +#endif +#ifndef GL_STENCIL_ATTACHMENT +#define GL_STENCIL_ATTACHMENT 0x8D00 +#endif +#ifndef GL_COLOR_ATTACHMENT0 +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#endif +#ifndef GL_FRAMEBUFFER_COMPLETE +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#endif +#ifndef GL_STENCIL_INDEX8 +#define GL_STENCIL_INDEX8 0x8D48 +#endif +#ifndef GL_DEPTH_STENCIL +#define GL_DEPTH_STENCIL 0x84F9 +#endif +#ifndef GL_DEPTH24_STENCIL8 +#define GL_DEPTH24_STENCIL8 0x88F0 +#endif +#ifndef GL_DEPTH_ATTACHMENT +#define GL_DEPTH_ATTACHMENT 0x8D00 +#endif +#ifndef GL_DEPTH_STENCIL_ATTACHMENT +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#endif +#ifndef GL_DEPTH_COMPONENT16 +#define GL_DEPTH_COMPONENT16 0x81A5 +#endif +#ifndef GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#endif +#ifndef GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE +#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 +#endif +#ifndef GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE +#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 +#endif +#ifndef GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE +#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 +#endif +#ifndef GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE +#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 +#endif +#ifndef GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#endif +#ifndef GL_READ_FRAMEBUFFER +#define GL_READ_FRAMEBUFFER 0x8CA8 +#endif +#ifndef GL_DRAW_FRAMEBUFFER +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#endif +#ifndef GL_TEXTURE_SAMPLES_IMG +#define GL_TEXTURE_SAMPLES_IMG 0x9136 +#endif +#ifndef GL_PACK_INVERT_MESA +#define GL_PACK_INVERT_MESA 0x8758 +#endif +#ifndef GL_BACK_LEFT +#define GL_BACK_LEFT 0x0402 +#endif +#ifndef GL_BACK_RIGHT +#define GL_BACK_RIGHT 0x0403 +#endif + +#ifndef GL_COLOR +#define GL_COLOR 0x1800 +#endif +#ifndef GL_DEPTH +#define GL_DEPTH 0x1801 +#endif +#ifndef GL_STENCIL +#define GL_STENCIL 0x1802 +#endif + + +static void +_cogl_framebuffer_gl_flush_viewport_state (CoglFramebuffer *framebuffer) +{ + float gl_viewport_y; + + g_assert (framebuffer->viewport_width >=0 && + framebuffer->viewport_height >=0); + + /* Convert the Cogl viewport y offset to an OpenGL viewport y offset + * NB: OpenGL defines its window and viewport origins to be bottom + * left, while Cogl defines them to be top left. + * NB: We render upside down to offscreen framebuffers so we don't + * need to convert the y offset in this case. */ + if (cogl_is_offscreen (framebuffer)) + gl_viewport_y = framebuffer->viewport_y; + else + gl_viewport_y = framebuffer->height - + (framebuffer->viewport_y + framebuffer->viewport_height); + + COGL_NOTE (OPENGL, "Calling glViewport(%f, %f, %f, %f)", + framebuffer->viewport_x, + gl_viewport_y, + framebuffer->viewport_width, + framebuffer->viewport_height); + + GE (framebuffer->context, + glViewport (framebuffer->viewport_x, + gl_viewport_y, + framebuffer->viewport_width, + framebuffer->viewport_height)); +} + +static void +_cogl_framebuffer_gl_flush_clip_state (CoglFramebuffer *framebuffer) +{ + _cogl_clip_stack_flush (framebuffer->clip_stack, framebuffer); +} + +static void +_cogl_framebuffer_gl_flush_dither_state (CoglFramebuffer *framebuffer) +{ + CoglContext *ctx = framebuffer->context; + + if (ctx->current_gl_dither_enabled != framebuffer->dither_enabled) + { + if (framebuffer->dither_enabled) + GE (ctx, glEnable (GL_DITHER)); + else + GE (ctx, glDisable (GL_DITHER)); + ctx->current_gl_dither_enabled = framebuffer->dither_enabled; + } +} + +static void +_cogl_framebuffer_gl_flush_modelview_state (CoglFramebuffer *framebuffer) +{ + CoglMatrixEntry *modelview_entry = + _cogl_framebuffer_get_modelview_entry (framebuffer); + _cogl_context_set_current_modelview_entry (framebuffer->context, + modelview_entry); +} + +static void +_cogl_framebuffer_gl_flush_projection_state (CoglFramebuffer *framebuffer) +{ + CoglMatrixEntry *projection_entry = + _cogl_framebuffer_get_projection_entry (framebuffer); + _cogl_context_set_current_projection_entry (framebuffer->context, + projection_entry); +} + +static void +_cogl_framebuffer_gl_flush_color_mask_state (CoglFramebuffer *framebuffer) +{ + CoglContext *context = framebuffer->context; + + /* The color mask state is really owned by a CoglPipeline so to + * ensure the color mask is updated the next time we draw something + * we need to make sure the logic ops for the pipeline are + * re-flushed... */ + context->current_pipeline_changes_since_flush |= + COGL_PIPELINE_STATE_LOGIC_OPS; + context->current_pipeline_age--; +} + +static void +_cogl_framebuffer_gl_flush_front_face_winding_state (CoglFramebuffer *framebuffer) +{ + CoglContext *context = framebuffer->context; + CoglPipelineCullFaceMode mode; + + /* NB: The face winding state is actually owned by the current + * CoglPipeline. + * + * If we don't have a current pipeline then we can just assume that + * when we later do flush a pipeline we will check the current + * framebuffer to know how to setup the winding */ + if (!context->current_pipeline) + return; + + mode = cogl_pipeline_get_cull_face_mode (context->current_pipeline); + + /* If the current CoglPipeline has a culling mode that doesn't care + * about the winding we can avoid forcing an update of the state and + * bail out. */ + if (mode == COGL_PIPELINE_CULL_FACE_MODE_NONE || + mode == COGL_PIPELINE_CULL_FACE_MODE_BOTH) + return; + + /* Since the winding state is really owned by the current pipeline + * the way we "flush" an updated winding is to dirty the pipeline + * state... */ + context->current_pipeline_changes_since_flush |= + COGL_PIPELINE_STATE_CULL_FACE; + context->current_pipeline_age--; +} + +static void +_cogl_framebuffer_gl_flush_stereo_mode_state (CoglFramebuffer *framebuffer) +{ + CoglContext *ctx = framebuffer->context; + GLenum draw_buffer = GL_BACK; + + if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN) + return; + + if (!ctx->glDrawBuffer) + return; + + /* The one-shot default draw buffer setting in _cogl_framebuffer_gl_bind + * must have already happened. If not it would override what we set here. */ + g_assert (ctx->was_bound_to_onscreen); + + switch (framebuffer->stereo_mode) + { + case COGL_STEREO_BOTH: + draw_buffer = GL_BACK; + break; + case COGL_STEREO_LEFT: + draw_buffer = GL_BACK_LEFT; + break; + case COGL_STEREO_RIGHT: + draw_buffer = GL_BACK_RIGHT; + break; + } + + if (ctx->current_gl_draw_buffer != draw_buffer) + { + GE (ctx, glDrawBuffer (draw_buffer)); + ctx->current_gl_draw_buffer = draw_buffer; + } +} + +void +_cogl_framebuffer_gl_bind (CoglFramebuffer *framebuffer, GLenum target) +{ + CoglContext *ctx = framebuffer->context; + + if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN) + { + CoglOffscreen *offscreen = COGL_OFFSCREEN (framebuffer); + GE (ctx, glBindFramebuffer (target, + offscreen->gl_framebuffer.fbo_handle)); + } + else + { + const CoglWinsysVtable *winsys = + _cogl_framebuffer_get_winsys (framebuffer); + winsys->onscreen_bind (COGL_ONSCREEN (framebuffer)); + /* glBindFramebuffer is an an extension with OpenGL ES 1.1 */ + if (cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN)) + GE (ctx, glBindFramebuffer (target, 0)); + + /* Initialise the glDrawBuffer state the first time the context + * is bound to the default framebuffer. If the winsys is using a + * surfaceless context for the initial make current then the + * default draw buffer will be GL_NONE so we need to correct + * that. We can't do it any earlier because binding GL_BACK when + * there is no default framebuffer won't work */ + if (!ctx->was_bound_to_onscreen) + { + if (ctx->glDrawBuffer) + { + GE (ctx, glDrawBuffer (GL_BACK)); + } + else if (ctx->glDrawBuffers) + { + /* glDrawBuffer isn't available on GLES 3.0 so we need + * to be able to use glDrawBuffers as well. On GLES 2 + * neither is available but the state should always be + * GL_BACK anyway so we don't need to set anything. On + * desktop GL this must be GL_BACK_LEFT instead of + * GL_BACK but as this code path will only be hit for + * GLES we can just use GL_BACK. */ + static const GLenum buffers[] = { GL_BACK }; + + GE (ctx, glDrawBuffers (G_N_ELEMENTS (buffers), buffers)); + } + + ctx->was_bound_to_onscreen = TRUE; + } + } +} + +void +_cogl_framebuffer_gl_flush_state (CoglFramebuffer *draw_buffer, + CoglFramebuffer *read_buffer, + CoglFramebufferState state) +{ + CoglContext *ctx = draw_buffer->context; + unsigned long differences; + int bit; + + /* We can assume that any state that has changed for the current + * framebuffer is different to the currently flushed value. */ + differences = ctx->current_draw_buffer_changes; + + /* Any state of the current framebuffer that hasn't already been + * flushed is assumed to be unknown so we will always flush that + * state if asked. */ + differences |= ~ctx->current_draw_buffer_state_flushed; + + /* We only need to consider the state we've been asked to flush */ + differences &= state; + + if (ctx->current_draw_buffer != draw_buffer) + { + /* If the previous draw buffer is NULL then we'll assume + everything has changed. This can happen if a framebuffer is + destroyed while it is the last flushed draw buffer. In that + case the framebuffer destructor will set + ctx->current_draw_buffer to NULL */ + if (ctx->current_draw_buffer == NULL) + differences |= state; + else + /* NB: we only need to compare the state we're being asked to flush + * and we don't need to compare the state we've already decided + * we will definitely flush... */ + differences |= _cogl_framebuffer_compare (ctx->current_draw_buffer, + draw_buffer, + state & ~differences); + + /* NB: we don't take a reference here, to avoid a circular + * reference. */ + ctx->current_draw_buffer = draw_buffer; + ctx->current_draw_buffer_state_flushed = 0; + } + + if (ctx->current_read_buffer != read_buffer && + state & COGL_FRAMEBUFFER_STATE_BIND) + { + differences |= COGL_FRAMEBUFFER_STATE_BIND; + /* NB: we don't take a reference here, to avoid a circular + * reference. */ + ctx->current_read_buffer = read_buffer; + } + + if (!differences) + return; + + /* Lazily ensure the framebuffers have been allocated */ + if (G_UNLIKELY (!draw_buffer->allocated)) + cogl_framebuffer_allocate (draw_buffer, NULL); + if (G_UNLIKELY (!read_buffer->allocated)) + cogl_framebuffer_allocate (read_buffer, NULL); + + /* We handle buffer binding separately since the method depends on whether + * we are binding the same buffer for read and write or not unlike all + * other state that only relates to the draw_buffer. */ + if (differences & COGL_FRAMEBUFFER_STATE_BIND) + { + if (draw_buffer == read_buffer) + _cogl_framebuffer_gl_bind (draw_buffer, GL_FRAMEBUFFER); + else + { + /* NB: Currently we only take advantage of binding separate + * read/write buffers for offscreen framebuffer blit + * purposes. */ + _COGL_RETURN_IF_FAIL (_cogl_has_private_feature + (ctx, COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT)); + _COGL_RETURN_IF_FAIL (draw_buffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN); + _COGL_RETURN_IF_FAIL (read_buffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN); + + _cogl_framebuffer_gl_bind (draw_buffer, GL_DRAW_FRAMEBUFFER); + _cogl_framebuffer_gl_bind (read_buffer, GL_READ_FRAMEBUFFER); + } + + differences &= ~COGL_FRAMEBUFFER_STATE_BIND; + } + + COGL_FLAGS_FOREACH_START (&differences, 1, bit) + { + /* XXX: We considered having an array of callbacks for each state index + * that we'd call here but decided that this way the compiler is more + * likely going to be able to in-line the flush functions and use the + * index to jump straight to the required code. */ + switch (bit) + { + case COGL_FRAMEBUFFER_STATE_INDEX_VIEWPORT: + _cogl_framebuffer_gl_flush_viewport_state (draw_buffer); + break; + case COGL_FRAMEBUFFER_STATE_INDEX_CLIP: + _cogl_framebuffer_gl_flush_clip_state (draw_buffer); + break; + case COGL_FRAMEBUFFER_STATE_INDEX_DITHER: + _cogl_framebuffer_gl_flush_dither_state (draw_buffer); + break; + case COGL_FRAMEBUFFER_STATE_INDEX_MODELVIEW: + _cogl_framebuffer_gl_flush_modelview_state (draw_buffer); + break; + case COGL_FRAMEBUFFER_STATE_INDEX_PROJECTION: + _cogl_framebuffer_gl_flush_projection_state (draw_buffer); + break; + case COGL_FRAMEBUFFER_STATE_INDEX_COLOR_MASK: + _cogl_framebuffer_gl_flush_color_mask_state (draw_buffer); + break; + case COGL_FRAMEBUFFER_STATE_INDEX_FRONT_FACE_WINDING: + _cogl_framebuffer_gl_flush_front_face_winding_state (draw_buffer); + break; + case COGL_FRAMEBUFFER_STATE_INDEX_DEPTH_WRITE: + /* Nothing to do for depth write state change; the state will always + * be taken into account when flushing the pipeline's depth state. */ + break; + case COGL_FRAMEBUFFER_STATE_INDEX_STEREO_MODE: + _cogl_framebuffer_gl_flush_stereo_mode_state (draw_buffer); + break; + default: + g_warn_if_reached (); + } + } + COGL_FLAGS_FOREACH_END; + + ctx->current_draw_buffer_state_flushed |= state; + ctx->current_draw_buffer_changes &= ~state; +} + +static CoglTexture * +create_depth_texture (CoglContext *ctx, + int width, + int height) +{ + CoglTexture2D *depth_texture = + cogl_texture_2d_new_with_size (ctx, width, height); + + cogl_texture_set_components (COGL_TEXTURE (depth_texture), + COGL_TEXTURE_COMPONENTS_DEPTH); + + return COGL_TEXTURE (depth_texture); +} + +static CoglTexture * +attach_depth_texture (CoglContext *ctx, + CoglTexture *depth_texture, + CoglOffscreenAllocateFlags flags) +{ + GLuint tex_gl_handle; + GLenum tex_gl_target; + + if (flags & COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH_STENCIL) + { + /* attach a GL_DEPTH_STENCIL texture to the GL_DEPTH_ATTACHMENT and + * GL_STENCIL_ATTACHMENT attachement points */ + g_assert (_cogl_texture_get_format (depth_texture) == + COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8); + + cogl_texture_get_gl_texture (depth_texture, + &tex_gl_handle, &tex_gl_target); + + GE (ctx, glFramebufferTexture2D (GL_FRAMEBUFFER, + GL_DEPTH_ATTACHMENT, + tex_gl_target, tex_gl_handle, + 0)); + GE (ctx, glFramebufferTexture2D (GL_FRAMEBUFFER, + GL_STENCIL_ATTACHMENT, + tex_gl_target, tex_gl_handle, + 0)); + } + else if (flags & COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH) + { + /* attach a newly created GL_DEPTH_COMPONENT16 texture to the + * GL_DEPTH_ATTACHMENT attachement point */ + g_assert (_cogl_texture_get_format (depth_texture) == + COGL_PIXEL_FORMAT_DEPTH_16); + + cogl_texture_get_gl_texture (COGL_TEXTURE (depth_texture), + &tex_gl_handle, &tex_gl_target); + + GE (ctx, glFramebufferTexture2D (GL_FRAMEBUFFER, + GL_DEPTH_ATTACHMENT, + tex_gl_target, tex_gl_handle, + 0)); + } + + return COGL_TEXTURE (depth_texture); +} + +static GList * +try_creating_renderbuffers (CoglContext *ctx, + int width, + int height, + CoglOffscreenAllocateFlags flags, + int n_samples) +{ + GList *renderbuffers = NULL; + GLuint gl_depth_stencil_handle; + + if (flags & COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH_STENCIL) + { + GLenum format; + + /* WebGL adds a GL_DEPTH_STENCIL_ATTACHMENT and requires that we + * use the GL_DEPTH_STENCIL format. */ +#ifdef HAVE_COGL_WEBGL + format = GL_DEPTH_STENCIL; +#else + /* Although GL_OES_packed_depth_stencil is mostly equivalent to + * GL_EXT_packed_depth_stencil, one notable difference is that + * GL_OES_packed_depth_stencil doesn't allow GL_DEPTH_STENCIL to + * be passed as an internal format to glRenderbufferStorage. + */ + if (_cogl_has_private_feature + (ctx, COGL_PRIVATE_FEATURE_EXT_PACKED_DEPTH_STENCIL)) + format = GL_DEPTH_STENCIL; + else + { + _COGL_RETURN_VAL_IF_FAIL ( + _cogl_has_private_feature (ctx, + COGL_PRIVATE_FEATURE_OES_PACKED_DEPTH_STENCIL), + NULL); + format = GL_DEPTH24_STENCIL8; + } +#endif + + /* Create a renderbuffer for depth and stenciling */ + GE (ctx, glGenRenderbuffers (1, &gl_depth_stencil_handle)); + GE (ctx, glBindRenderbuffer (GL_RENDERBUFFER, gl_depth_stencil_handle)); + if (n_samples) + GE (ctx, glRenderbufferStorageMultisampleIMG (GL_RENDERBUFFER, + n_samples, + format, + width, height)); + else + GE (ctx, glRenderbufferStorage (GL_RENDERBUFFER, format, + width, height)); + GE (ctx, glBindRenderbuffer (GL_RENDERBUFFER, 0)); + + +#ifdef HAVE_COGL_WEBGL + GE (ctx, glFramebufferRenderbuffer (GL_FRAMEBUFFER, + GL_DEPTH_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, + gl_depth_stencil_handle)); +#else + GE (ctx, glFramebufferRenderbuffer (GL_FRAMEBUFFER, + GL_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, + gl_depth_stencil_handle)); + GE (ctx, glFramebufferRenderbuffer (GL_FRAMEBUFFER, + GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, + gl_depth_stencil_handle)); +#endif + renderbuffers = + g_list_prepend (renderbuffers, + GUINT_TO_POINTER (gl_depth_stencil_handle)); + } + + if (flags & COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH) + { + GLuint gl_depth_handle; + + GE (ctx, glGenRenderbuffers (1, &gl_depth_handle)); + GE (ctx, glBindRenderbuffer (GL_RENDERBUFFER, gl_depth_handle)); + /* For now we just ask for GL_DEPTH_COMPONENT16 since this is all that's + * available under GLES */ + if (n_samples) + GE (ctx, glRenderbufferStorageMultisampleIMG (GL_RENDERBUFFER, + n_samples, + GL_DEPTH_COMPONENT16, + width, height)); + else + GE (ctx, glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, + width, height)); + GE (ctx, glBindRenderbuffer (GL_RENDERBUFFER, 0)); + GE (ctx, glFramebufferRenderbuffer (GL_FRAMEBUFFER, + GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, gl_depth_handle)); + renderbuffers = + g_list_prepend (renderbuffers, GUINT_TO_POINTER (gl_depth_handle)); + } + + if (flags & COGL_OFFSCREEN_ALLOCATE_FLAG_STENCIL) + { + GLuint gl_stencil_handle; + + GE (ctx, glGenRenderbuffers (1, &gl_stencil_handle)); + GE (ctx, glBindRenderbuffer (GL_RENDERBUFFER, gl_stencil_handle)); + if (n_samples) + GE (ctx, glRenderbufferStorageMultisampleIMG (GL_RENDERBUFFER, + n_samples, + GL_STENCIL_INDEX8, + width, height)); + else + GE (ctx, glRenderbufferStorage (GL_RENDERBUFFER, GL_STENCIL_INDEX8, + width, height)); + GE (ctx, glBindRenderbuffer (GL_RENDERBUFFER, 0)); + GE (ctx, glFramebufferRenderbuffer (GL_FRAMEBUFFER, + GL_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, gl_stencil_handle)); + renderbuffers = + g_list_prepend (renderbuffers, GUINT_TO_POINTER (gl_stencil_handle)); + } + + return renderbuffers; +} + +static void +delete_renderbuffers (CoglContext *ctx, GList *renderbuffers) +{ + GList *l; + + for (l = renderbuffers; l; l = l->next) + { + GLuint renderbuffer = GPOINTER_TO_UINT (l->data); + GE (ctx, glDeleteRenderbuffers (1, &renderbuffer)); + } + + g_list_free (renderbuffers); +} + +/* + * NB: This function may be called with a standalone GLES2 context + * bound so we can create a shadow framebuffer that wraps the same + * CoglTexture as the given CoglOffscreen. This function shouldn't + * modify anything in + */ +static CoglBool +try_creating_fbo (CoglContext *ctx, + CoglTexture *texture, + int texture_level, + int texture_level_width, + int texture_level_height, + CoglTexture *depth_texture, + CoglFramebufferConfig *config, + CoglOffscreenAllocateFlags flags, + CoglGLFramebuffer *gl_framebuffer) +{ + GLuint tex_gl_handle; + GLenum tex_gl_target; + GLenum status; + int n_samples; + + if (!cogl_texture_get_gl_texture (texture, &tex_gl_handle, &tex_gl_target)) + return FALSE; + + if (tex_gl_target != GL_TEXTURE_2D +#ifdef HAVE_COGL_GL + && tex_gl_target != GL_TEXTURE_RECTANGLE_ARB +#endif + ) + return FALSE; + + if (config->samples_per_pixel) + { + if (!ctx->glFramebufferTexture2DMultisampleIMG) + return FALSE; + n_samples = config->samples_per_pixel; + } + else + n_samples = 0; + + /* We are about to generate and bind a new fbo, so we pretend to + * change framebuffer state so that the old framebuffer will be + * rebound again before drawing. */ + ctx->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_BIND; + + /* Generate framebuffer */ + ctx->glGenFramebuffers (1, &gl_framebuffer->fbo_handle); + GE (ctx, glBindFramebuffer (GL_FRAMEBUFFER, gl_framebuffer->fbo_handle)); + + if (n_samples) + { + GE (ctx, glFramebufferTexture2DMultisampleIMG (GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + tex_gl_target, tex_gl_handle, + n_samples, + texture_level)); + } + else + GE (ctx, glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + tex_gl_target, tex_gl_handle, + texture_level)); + + /* attach either a depth/stencil texture, a depth texture or render buffers + * depending on what we've been asked to provide */ + + if (depth_texture && + flags & (COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH_STENCIL | + COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH)) + { + attach_depth_texture (ctx, depth_texture, flags); + + /* Let's clear the flags that are now fulfilled as we might need to + * create renderbuffers (for the ALLOCATE_FLAG_DEPTH | + * ALLOCATE_FLAG_STENCIL case) */ + flags &= ~(COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH_STENCIL | + COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH); + } + + if (flags) + { + gl_framebuffer->renderbuffers = + try_creating_renderbuffers (ctx, + texture_level_width, + texture_level_height, + flags, + n_samples); + } + + /* Make sure it's complete */ + status = ctx->glCheckFramebufferStatus (GL_FRAMEBUFFER); + + if (status != GL_FRAMEBUFFER_COMPLETE) + { + GE (ctx, glDeleteFramebuffers (1, &gl_framebuffer->fbo_handle)); + + delete_renderbuffers (ctx, gl_framebuffer->renderbuffers); + gl_framebuffer->renderbuffers = NULL; + + return FALSE; + } + + /* Update the real number of samples_per_pixel now that we have a + * complete framebuffer */ + if (n_samples) + { + GLenum attachment = GL_COLOR_ATTACHMENT0; + GLenum pname = GL_TEXTURE_SAMPLES_IMG; + int texture_samples; + + GE( ctx, glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, + attachment, + pname, + &texture_samples) ); + gl_framebuffer->samples_per_pixel = texture_samples; + } + + return TRUE; +} + +CoglBool +_cogl_framebuffer_try_creating_gl_fbo (CoglContext *ctx, + CoglTexture *texture, + int texture_level, + int texture_level_width, + int texture_level_height, + CoglTexture *depth_texture, + CoglFramebufferConfig *config, + CoglOffscreenAllocateFlags flags, + CoglGLFramebuffer *gl_framebuffer) +{ + return try_creating_fbo (ctx, + texture, + texture_level, + texture_level_width, + texture_level_height, + depth_texture, + config, + flags, + gl_framebuffer); +} + +CoglBool +_cogl_offscreen_gl_allocate (CoglOffscreen *offscreen, + CoglError **error) +{ + CoglFramebuffer *fb = COGL_FRAMEBUFFER (offscreen); + CoglContext *ctx = fb->context; + CoglOffscreenAllocateFlags flags; + CoglGLFramebuffer *gl_framebuffer = &offscreen->gl_framebuffer; + int level_width; + int level_height; + + _COGL_RETURN_VAL_IF_FAIL (offscreen->texture_level < + _cogl_texture_get_n_levels (offscreen->texture), + FALSE); + + _cogl_texture_get_level_size (offscreen->texture, + offscreen->texture_level, + &level_width, + &level_height, + NULL); + + if (fb->config.depth_texture_enabled && + offscreen->depth_texture == NULL) + { + offscreen->depth_texture = + create_depth_texture (ctx, + level_width, + level_height); + + if (!cogl_texture_allocate (offscreen->depth_texture, error)) + { + cogl_object_unref (offscreen->depth_texture); + offscreen->depth_texture = NULL; + return FALSE; + } + + _cogl_texture_associate_framebuffer (offscreen->depth_texture, fb); + } + + /* XXX: The framebuffer_object spec isn't clear in defining whether attaching + * a texture as a renderbuffer with mipmap filtering enabled while the + * mipmaps have not been uploaded should result in an incomplete framebuffer + * object. (different drivers make different decisions) + * + * To avoid an error with drivers that do consider this a problem we + * explicitly set non mipmapped filters here. These will later be reset when + * the texture is actually used for rendering according to the filters set on + * the corresponding CoglPipeline. + */ + _cogl_texture_gl_flush_legacy_texobj_filters (offscreen->texture, + GL_NEAREST, GL_NEAREST); + + if (((offscreen->create_flags & COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL) && + try_creating_fbo (ctx, + offscreen->texture, + offscreen->texture_level, + level_width, + level_height, + offscreen->depth_texture, + &fb->config, + flags = 0, + gl_framebuffer)) || + + (ctx->have_last_offscreen_allocate_flags && + try_creating_fbo (ctx, + offscreen->texture, + offscreen->texture_level, + level_width, + level_height, + offscreen->depth_texture, + &fb->config, + flags = ctx->last_offscreen_allocate_flags, + gl_framebuffer)) || + + ( + /* NB: WebGL introduces a DEPTH_STENCIL_ATTACHMENT and doesn't + * need an extension to handle _FLAG_DEPTH_STENCIL */ +#ifndef HAVE_COGL_WEBGL + (_cogl_has_private_feature + (ctx, COGL_PRIVATE_FEATURE_EXT_PACKED_DEPTH_STENCIL) || + _cogl_has_private_feature + (ctx, COGL_PRIVATE_FEATURE_OES_PACKED_DEPTH_STENCIL)) && +#endif + try_creating_fbo (ctx, + offscreen->texture, + offscreen->texture_level, + level_width, + level_height, + offscreen->depth_texture, + &fb->config, + flags = COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH_STENCIL, + gl_framebuffer)) || + + try_creating_fbo (ctx, + offscreen->texture, + offscreen->texture_level, + level_width, + level_height, + offscreen->depth_texture, + &fb->config, + flags = COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH | + COGL_OFFSCREEN_ALLOCATE_FLAG_STENCIL, + gl_framebuffer) || + + try_creating_fbo (ctx, + offscreen->texture, + offscreen->texture_level, + level_width, + level_height, + offscreen->depth_texture, + &fb->config, + flags = COGL_OFFSCREEN_ALLOCATE_FLAG_STENCIL, + gl_framebuffer) || + + try_creating_fbo (ctx, + offscreen->texture, + offscreen->texture_level, + level_width, + level_height, + offscreen->depth_texture, + &fb->config, + flags = COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH, + gl_framebuffer) || + + try_creating_fbo (ctx, + offscreen->texture, + offscreen->texture_level, + level_width, + level_height, + offscreen->depth_texture, + &fb->config, + flags = 0, + gl_framebuffer)) + { + fb->samples_per_pixel = gl_framebuffer->samples_per_pixel; + + if (!offscreen->create_flags & COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL) + { + /* Record that the last set of flags succeeded so that we can + try that set first next time */ + ctx->last_offscreen_allocate_flags = flags; + ctx->have_last_offscreen_allocate_flags = TRUE; + } + + /* Save the flags we managed to successfully allocate the + * renderbuffers with in case we need to make renderbuffers for a + * GLES2 context later */ + offscreen->allocation_flags = flags; + + return TRUE; + } + else + { + _cogl_set_error (error, COGL_FRAMEBUFFER_ERROR, + COGL_FRAMEBUFFER_ERROR_ALLOCATE, + "Failed to create an OpenGL framebuffer object"); + return FALSE; + } +} + +void +_cogl_offscreen_gl_free (CoglOffscreen *offscreen) +{ + CoglContext *ctx = COGL_FRAMEBUFFER (offscreen)->context; + + delete_renderbuffers (ctx, offscreen->gl_framebuffer.renderbuffers); + + GE (ctx, glDeleteFramebuffers (1, &offscreen->gl_framebuffer.fbo_handle)); +} + +void +_cogl_framebuffer_gl_clear (CoglFramebuffer *framebuffer, + unsigned long buffers, + float red, + float green, + float blue, + float alpha) +{ + CoglContext *ctx = framebuffer->context; + GLbitfield gl_buffers = 0; + + if (buffers & COGL_BUFFER_BIT_COLOR) + { + GE( ctx, glClearColor (red, green, blue, alpha) ); + gl_buffers |= GL_COLOR_BUFFER_BIT; + + if (ctx->current_gl_color_mask != framebuffer->color_mask) + { + CoglColorMask color_mask = framebuffer->color_mask; + GE( ctx, glColorMask (!!(color_mask & COGL_COLOR_MASK_RED), + !!(color_mask & COGL_COLOR_MASK_GREEN), + !!(color_mask & COGL_COLOR_MASK_BLUE), + !!(color_mask & COGL_COLOR_MASK_ALPHA))); + ctx->current_gl_color_mask = color_mask; + /* Make sure the ColorMask is updated when the next primitive is drawn */ + ctx->current_pipeline_changes_since_flush |= + COGL_PIPELINE_STATE_LOGIC_OPS; + ctx->current_pipeline_age--; + } + } + + if (buffers & COGL_BUFFER_BIT_DEPTH) + { + gl_buffers |= GL_DEPTH_BUFFER_BIT; + + if (ctx->depth_writing_enabled_cache != framebuffer->depth_writing_enabled) + { + GE( ctx, glDepthMask (framebuffer->depth_writing_enabled)); + + ctx->depth_writing_enabled_cache = framebuffer->depth_writing_enabled; + + /* Make sure the DepthMask is updated when the next primitive is drawn */ + ctx->current_pipeline_changes_since_flush |= + COGL_PIPELINE_STATE_DEPTH; + ctx->current_pipeline_age--; + } + } + + if (buffers & COGL_BUFFER_BIT_STENCIL) + gl_buffers |= GL_STENCIL_BUFFER_BIT; + + + GE (ctx, glClear (gl_buffers)); +} + +static inline void +_cogl_framebuffer_init_bits (CoglFramebuffer *framebuffer) +{ + CoglContext *ctx = framebuffer->context; + + if (G_LIKELY (!framebuffer->dirty_bitmasks)) + return; + + cogl_framebuffer_allocate (framebuffer, NULL); + + _cogl_framebuffer_flush_state (framebuffer, + framebuffer, + COGL_FRAMEBUFFER_STATE_BIND); + +#ifdef HAVE_COGL_GL + if ((ctx->driver == COGL_DRIVER_GL3 && + framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN) || + (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_QUERY_FRAMEBUFFER_BITS) && + framebuffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN)) + { + gboolean is_offscreen = framebuffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN; + const struct { + GLenum attachment, pname; + size_t offset; + } params[] = { + { is_offscreen ? GL_COLOR_ATTACHMENT0 : GL_BACK_LEFT, + GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, + offsetof (CoglFramebufferBits, red) }, + { is_offscreen ? GL_COLOR_ATTACHMENT0 : GL_BACK_LEFT, + GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE, + offsetof (CoglFramebufferBits, green) }, + { is_offscreen ? GL_COLOR_ATTACHMENT0 : GL_BACK_LEFT, + GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, + offsetof (CoglFramebufferBits, blue) }, + { is_offscreen ? GL_COLOR_ATTACHMENT0 : GL_BACK_LEFT, + GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, + offsetof (CoglFramebufferBits, alpha) }, + { is_offscreen ? GL_DEPTH_ATTACHMENT : GL_DEPTH, + GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, + offsetof (CoglFramebufferBits, depth) }, + { is_offscreen ? GL_STENCIL_ATTACHMENT : GL_STENCIL, + GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, + offsetof (CoglFramebufferBits, stencil) }, + }; + int i; + + for (i = 0; i < G_N_ELEMENTS (params); i++) + { + int *value = + (int *) ((uint8_t *) &framebuffer->bits + params[i].offset); + GE( ctx, glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, + params[i].attachment, + params[i].pname, + value) ); + } + } + else +#endif /* HAVE_COGL_GL */ + { + GE( ctx, glGetIntegerv (GL_RED_BITS, &framebuffer->bits.red) ); + GE( ctx, glGetIntegerv (GL_GREEN_BITS, &framebuffer->bits.green) ); + GE( ctx, glGetIntegerv (GL_BLUE_BITS, &framebuffer->bits.blue) ); + GE( ctx, glGetIntegerv (GL_ALPHA_BITS, &framebuffer->bits.alpha) ); + GE( ctx, glGetIntegerv (GL_DEPTH_BITS, &framebuffer->bits.depth) ); + GE( ctx, glGetIntegerv (GL_STENCIL_BITS, &framebuffer->bits.stencil) ); + } + + /* If we don't have alpha textures then the alpha bits are actually + * stored in the red component */ + if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_ALPHA_TEXTURES) && + framebuffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN && + framebuffer->internal_format == COGL_PIXEL_FORMAT_A_8) + { + framebuffer->bits.alpha = framebuffer->bits.red; + framebuffer->bits.red = 0; + } + + COGL_NOTE (OFFSCREEN, + "RGBA/D/S Bits for framebuffer[%p, %s]: %d, %d, %d, %d, %d, %d", + framebuffer, + framebuffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN + ? "offscreen" + : "onscreen", + framebuffer->bits.red, + framebuffer->bits.blue, + framebuffer->bits.green, + framebuffer->bits.alpha, + framebuffer->bits.depth, + framebuffer->bits.stencil); + + framebuffer->dirty_bitmasks = FALSE; +} + +void +_cogl_framebuffer_gl_query_bits (CoglFramebuffer *framebuffer, + CoglFramebufferBits *bits) +{ + _cogl_framebuffer_init_bits (framebuffer); + + /* TODO: cache these in some driver specific location not + * directly as part of CoglFramebuffer. */ + *bits = framebuffer->bits; +} + +void +_cogl_framebuffer_gl_finish (CoglFramebuffer *framebuffer) +{ + GE (framebuffer->context, glFinish ()); +} + +void +_cogl_framebuffer_gl_discard_buffers (CoglFramebuffer *framebuffer, + unsigned long buffers) +{ + CoglContext *ctx = framebuffer->context; + + if (ctx->glDiscardFramebuffer) + { + GLenum attachments[3]; + int i = 0; + + if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN) + { + if (buffers & COGL_BUFFER_BIT_COLOR) + attachments[i++] = GL_COLOR; + if (buffers & COGL_BUFFER_BIT_DEPTH) + attachments[i++] = GL_DEPTH; + if (buffers & COGL_BUFFER_BIT_STENCIL) + attachments[i++] = GL_STENCIL; + } + else + { + if (buffers & COGL_BUFFER_BIT_COLOR) + attachments[i++] = GL_COLOR_ATTACHMENT0; + if (buffers & COGL_BUFFER_BIT_DEPTH) + attachments[i++] = GL_DEPTH_ATTACHMENT; + if (buffers & COGL_BUFFER_BIT_STENCIL) + attachments[i++] = GL_STENCIL_ATTACHMENT; + } + + _cogl_framebuffer_flush_state (framebuffer, + framebuffer, + COGL_FRAMEBUFFER_STATE_BIND); + GE (ctx, glDiscardFramebuffer (GL_FRAMEBUFFER, i, attachments)); + } +} + +void +_cogl_framebuffer_gl_draw_attributes (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglVerticesMode mode, + int first_vertex, + int n_vertices, + CoglAttribute **attributes, + int n_attributes, + CoglDrawFlags flags) +{ + _cogl_flush_attributes_state (framebuffer, pipeline, flags, + attributes, n_attributes); + + GE (framebuffer->context, + glDrawArrays ((GLenum)mode, first_vertex, n_vertices)); +} + +static size_t +sizeof_index_type (CoglIndicesType type) +{ + switch (type) + { + case COGL_INDICES_TYPE_UNSIGNED_BYTE: + return 1; + case COGL_INDICES_TYPE_UNSIGNED_SHORT: + return 2; + case COGL_INDICES_TYPE_UNSIGNED_INT: + return 4; + } + g_return_val_if_reached (0); +} + +void +_cogl_framebuffer_gl_draw_indexed_attributes (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglVerticesMode mode, + int first_vertex, + int n_vertices, + CoglIndices *indices, + CoglAttribute **attributes, + int n_attributes, + CoglDrawFlags flags) +{ + CoglBuffer *buffer; + uint8_t *base; + size_t buffer_offset; + size_t index_size; + GLenum indices_gl_type = 0; + + _cogl_flush_attributes_state (framebuffer, pipeline, flags, + attributes, n_attributes); + + buffer = COGL_BUFFER (cogl_indices_get_buffer (indices)); + + /* Note: we don't try and catch errors with binding the index buffer + * here since OOM errors at this point indicate that nothing has yet + * been uploaded to the indices buffer which we consider to be a + * programmer error. + */ + base = _cogl_buffer_gl_bind (buffer, + COGL_BUFFER_BIND_TARGET_INDEX_BUFFER, NULL); + buffer_offset = cogl_indices_get_offset (indices); + index_size = sizeof_index_type (cogl_indices_get_type (indices)); + + switch (cogl_indices_get_type (indices)) + { + case COGL_INDICES_TYPE_UNSIGNED_BYTE: + indices_gl_type = GL_UNSIGNED_BYTE; + break; + case COGL_INDICES_TYPE_UNSIGNED_SHORT: + indices_gl_type = GL_UNSIGNED_SHORT; + break; + case COGL_INDICES_TYPE_UNSIGNED_INT: + indices_gl_type = GL_UNSIGNED_INT; + break; + } + + GE (framebuffer->context, + glDrawElements ((GLenum)mode, + n_vertices, + indices_gl_type, + base + buffer_offset + index_size * first_vertex)); + + _cogl_buffer_gl_unbind (buffer); +} + +static CoglBool +mesa_46631_slow_read_pixels_workaround (CoglFramebuffer *framebuffer, + int x, + int y, + CoglReadPixelsFlags source, + CoglBitmap *bitmap, + CoglError **error) +{ + CoglContext *ctx; + CoglPixelFormat format; + CoglBitmap *pbo; + int width; + int height; + CoglBool res; + uint8_t *dst; + const uint8_t *src; + + ctx = cogl_framebuffer_get_context (framebuffer); + + width = cogl_bitmap_get_width (bitmap); + height = cogl_bitmap_get_height (bitmap); + format = cogl_bitmap_get_format (bitmap); + + pbo = cogl_bitmap_new_with_size (ctx, width, height, format); + + /* Read into the pbo. We need to disable the flipping because the + blit fast path in the driver does not work with + GL_PACK_INVERT_MESA is set */ + res = _cogl_framebuffer_read_pixels_into_bitmap (framebuffer, + x, y, + source | + COGL_READ_PIXELS_NO_FLIP, + pbo, + error); + if (!res) + { + cogl_object_unref (pbo); + return FALSE; + } + + /* Copy the pixels back into application's buffer */ + dst = _cogl_bitmap_map (bitmap, + COGL_BUFFER_ACCESS_WRITE, + COGL_BUFFER_MAP_HINT_DISCARD, + error); + if (!dst) + { + cogl_object_unref (pbo); + return FALSE; + } + + src = _cogl_bitmap_map (pbo, + COGL_BUFFER_ACCESS_READ, + 0, /* hints */ + error); + if (src) + { + int src_rowstride = cogl_bitmap_get_rowstride (pbo); + int dst_rowstride = cogl_bitmap_get_rowstride (bitmap); + int to_copy = + _cogl_pixel_format_get_bytes_per_pixel (format) * width; + int y; + + /* If the framebuffer is onscreen we need to flip the + data while copying */ + if (!cogl_is_offscreen (framebuffer)) + { + src += src_rowstride * (height - 1); + src_rowstride = -src_rowstride; + } + + for (y = 0; y < height; y++) + { + memcpy (dst, src, to_copy); + dst += dst_rowstride; + src += src_rowstride; + } + + _cogl_bitmap_unmap (pbo); + } + else + res = FALSE; + + _cogl_bitmap_unmap (bitmap); + + cogl_object_unref (pbo); + + return res; +} + +CoglBool +_cogl_framebuffer_gl_read_pixels_into_bitmap (CoglFramebuffer *framebuffer, + int x, + int y, + CoglReadPixelsFlags source, + CoglBitmap *bitmap, + CoglError **error) +{ + CoglContext *ctx = framebuffer->context; + int framebuffer_height = cogl_framebuffer_get_height (framebuffer); + int width = cogl_bitmap_get_width (bitmap); + int height = cogl_bitmap_get_height (bitmap); + CoglPixelFormat format = cogl_bitmap_get_format (bitmap); + CoglPixelFormat required_format; + GLenum gl_intformat; + GLenum gl_format; + GLenum gl_type; + CoglBool pack_invert_set; + int status = FALSE; + + /* Workaround for cases where its faster to read into a temporary + * PBO. This is only worth doing if: + * + * • The GPU is an Intel GPU. In that case there is a known + * fast-path when reading into a PBO that will use the blitter + * instead of the Mesa fallback code. The driver bug will only be + * set if this is the case. + * • We're not already reading into a PBO. + * • The target format is BGRA. The fast-path blit does not get hit + * otherwise. + * • The size of the data is not trivially small. This isn't a + * requirement to hit the fast-path blit but intuitively it feels + * like if the amount of data is too small then the cost of + * allocating a PBO will outweigh the cost of temporarily + * converting the data to floats. + */ + if ((ctx->gpu.driver_bugs & + COGL_GPU_INFO_DRIVER_BUG_MESA_46631_SLOW_READ_PIXELS) && + (width > 8 || height > 8) && + (format & ~COGL_PREMULT_BIT) == COGL_PIXEL_FORMAT_BGRA_8888 && + cogl_bitmap_get_buffer (bitmap) == NULL) + { + CoglError *ignore_error = NULL; + + if (mesa_46631_slow_read_pixels_workaround (framebuffer, + x, y, + source, + bitmap, + &ignore_error)) + return TRUE; + else + cogl_error_free (ignore_error); + } + + _cogl_framebuffer_flush_state (framebuffer, + framebuffer, + COGL_FRAMEBUFFER_STATE_BIND); + + /* The y co-ordinate should be given in OpenGL's coordinate system + * so 0 is the bottom row + * + * NB: all offscreen rendering is done upside down so no conversion + * is necissary in this case. + */ + if (!cogl_is_offscreen (framebuffer)) + y = framebuffer_height - y - height; + + required_format = ctx->driver_vtable->pixel_format_to_gl (ctx, + format, + &gl_intformat, + &gl_format, + &gl_type); + + /* NB: All offscreen rendering is done upside down so there is no need + * to flip in this case... */ + if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_MESA_PACK_INVERT) && + (source & COGL_READ_PIXELS_NO_FLIP) == 0 && + !cogl_is_offscreen (framebuffer)) + { + GE (ctx, glPixelStorei (GL_PACK_INVERT_MESA, TRUE)); + pack_invert_set = TRUE; + } + else + pack_invert_set = FALSE; + + /* Under GLES only GL_RGBA with GL_UNSIGNED_BYTE as well as an + implementation specific format under + GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES and + GL_IMPLEMENTATION_COLOR_READ_TYPE_OES is supported. We could try + to be more clever and check if the requested type matches that + but we would need some reliable functions to convert from GL + types to Cogl types. For now, lets just always read in + GL_RGBA/GL_UNSIGNED_BYTE and convert if necessary. We also need + to use this intermediate buffer if the rowstride has padding + because GLES does not support setting GL_ROW_LENGTH */ + if ((!_cogl_has_private_feature + (ctx, COGL_PRIVATE_FEATURE_READ_PIXELS_ANY_FORMAT) && + (gl_format != GL_RGBA || gl_type != GL_UNSIGNED_BYTE || + cogl_bitmap_get_rowstride (bitmap) != 4 * width)) || + (required_format & ~COGL_PREMULT_BIT) != (format & ~COGL_PREMULT_BIT)) + { + CoglBitmap *tmp_bmp; + CoglPixelFormat read_format; + int bpp, rowstride; + uint8_t *tmp_data; + CoglBool succeeded; + + if (_cogl_has_private_feature + (ctx, COGL_PRIVATE_FEATURE_READ_PIXELS_ANY_FORMAT)) + read_format = required_format; + else + { + read_format = COGL_PIXEL_FORMAT_RGBA_8888; + gl_format = GL_RGBA; + gl_type = GL_UNSIGNED_BYTE; + } + + if (COGL_PIXEL_FORMAT_CAN_HAVE_PREMULT (read_format)) + read_format = ((read_format & ~COGL_PREMULT_BIT) | + (framebuffer->internal_format & COGL_PREMULT_BIT)); + + tmp_bmp = _cogl_bitmap_new_with_malloc_buffer (ctx, + width, height, + read_format, + error); + if (!tmp_bmp) + goto EXIT; + + bpp = _cogl_pixel_format_get_bytes_per_pixel (read_format); + rowstride = cogl_bitmap_get_rowstride (tmp_bmp); + + ctx->texture_driver->prep_gl_for_pixels_download (ctx, + rowstride, + width, + bpp); + + /* Note: we don't worry about catching errors here since we know + * we won't be lazily allocating storage for this buffer so it + * won't fail due to lack of memory. */ + tmp_data = _cogl_bitmap_gl_bind (tmp_bmp, + COGL_BUFFER_ACCESS_WRITE, + COGL_BUFFER_MAP_HINT_DISCARD, + NULL); + + GE( ctx, glReadPixels (x, y, width, height, + gl_format, gl_type, + tmp_data) ); + + _cogl_bitmap_gl_unbind (tmp_bmp); + + succeeded = _cogl_bitmap_convert_into_bitmap (tmp_bmp, bitmap, error); + + cogl_object_unref (tmp_bmp); + + if (!succeeded) + goto EXIT; + } + else + { + CoglBitmap *shared_bmp; + CoglPixelFormat bmp_format; + int bpp, rowstride; + CoglBool succeeded = FALSE; + uint8_t *pixels; + CoglError *internal_error = NULL; + + rowstride = cogl_bitmap_get_rowstride (bitmap); + + /* We match the premultiplied state of the target buffer to the + * premultiplied state of the framebuffer so that it will get + * converted to the right format below */ + if (COGL_PIXEL_FORMAT_CAN_HAVE_PREMULT (format)) + bmp_format = ((format & ~COGL_PREMULT_BIT) | + (framebuffer->internal_format & COGL_PREMULT_BIT)); + else + bmp_format = format; + + if (bmp_format != format) + shared_bmp = _cogl_bitmap_new_shared (bitmap, + bmp_format, + width, height, + rowstride); + else + shared_bmp = cogl_object_ref (bitmap); + + bpp = _cogl_pixel_format_get_bytes_per_pixel (bmp_format); + + ctx->texture_driver->prep_gl_for_pixels_download (ctx, + rowstride, + width, + bpp); + + pixels = _cogl_bitmap_gl_bind (shared_bmp, + COGL_BUFFER_ACCESS_WRITE, + 0, /* hints */ + &internal_error); + /* NB: _cogl_bitmap_gl_bind() can return NULL in sucessfull + * cases so we have to explicitly check the cogl error pointer + * to know if there was a problem */ + if (internal_error) + { + cogl_object_unref (shared_bmp); + _cogl_propagate_error (error, internal_error); + goto EXIT; + } + + GE( ctx, glReadPixels (x, y, + width, height, + gl_format, gl_type, + pixels) ); + + _cogl_bitmap_gl_unbind (shared_bmp); + + /* Convert to the premult format specified by the caller + in-place. This will do nothing if the premult status is already + correct. */ + if (_cogl_bitmap_convert_premult_status (shared_bmp, format, error)) + succeeded = TRUE; + + cogl_object_unref (shared_bmp); + + if (!succeeded) + goto EXIT; + } + + /* NB: All offscreen rendering is done upside down so there is no need + * to flip in this case... */ + if (!cogl_is_offscreen (framebuffer) && + (source & COGL_READ_PIXELS_NO_FLIP) == 0 && + !pack_invert_set) + { + uint8_t *temprow; + int rowstride; + uint8_t *pixels; + + rowstride = cogl_bitmap_get_rowstride (bitmap); + pixels = _cogl_bitmap_map (bitmap, + COGL_BUFFER_ACCESS_READ | + COGL_BUFFER_ACCESS_WRITE, + 0, /* hints */ + error); + + if (pixels == NULL) + goto EXIT; + + temprow = g_alloca (rowstride * sizeof (uint8_t)); + + /* vertically flip the buffer in-place */ + for (y = 0; y < height / 2; y++) + { + if (y != height - y - 1) /* skip center row */ + { + memcpy (temprow, + pixels + y * rowstride, rowstride); + memcpy (pixels + y * rowstride, + pixels + (height - y - 1) * rowstride, rowstride); + memcpy (pixels + (height - y - 1) * rowstride, + temprow, + rowstride); + } + } + + _cogl_bitmap_unmap (bitmap); + } + + status = TRUE; + +EXIT: + + /* Currently this function owns the pack_invert state and we don't want this + * to interfere with other Cogl components so all other code can assume that + * we leave the pack_invert state off. */ + if (pack_invert_set) + GE (ctx, glPixelStorei (GL_PACK_INVERT_MESA, FALSE)); + + return status; +} diff --git a/cogl/cogl/driver/gl/cogl-pipeline-fragend-fixed-private.h b/cogl/cogl/driver/gl/cogl-pipeline-fragend-fixed-private.h new file mode 100644 index 0000000..6f259f9 --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-pipeline-fragend-fixed-private.h @@ -0,0 +1,42 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_PIPELINE_FRAGEND_FIXED_PRIVATE_H +#define __COGL_PIPELINE_FRAGEND_FIXED_PRIVATE_H + +#include "cogl-pipeline-private.h" + +extern const CoglPipelineFragend _cogl_pipeline_fixed_fragend; + +#endif /* __COGL_PIPELINE_FRAGEND_FIXED_PRIVATE_H */ + diff --git a/cogl/cogl/driver/gl/cogl-pipeline-fragend-fixed.c b/cogl/cogl/driver/gl/cogl-pipeline-fragend-fixed.c new file mode 100644 index 0000000..b529122 --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-pipeline-fragend-fixed.c @@ -0,0 +1,435 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-context-private.h" +#include "cogl-util-gl-private.h" +#include "cogl-pipeline-private.h" +#include "cogl-pipeline-state-private.h" +#include "cogl-pipeline-opengl-private.h" + +#ifdef COGL_PIPELINE_FRAGEND_FIXED + +#include "cogl-context-private.h" +#include "cogl-object-private.h" + +#include "cogl-texture-private.h" +#include "cogl-blend-string.h" +#include "cogl-profile.h" +#include "cogl-program-private.h" + +#include +#include +#include + +#ifndef GL_TEXTURE_RECTANGLE_ARB +#define GL_TEXTURE_RECTANGLE_ARB 0x84F5 +#endif + +const CoglPipelineFragend _cogl_pipeline_fixed_fragend; + +static void +_cogl_disable_texture_unit (int unit_index) +{ + CoglTextureUnit *unit; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + unit = &g_array_index (ctx->texture_units, CoglTextureUnit, unit_index); + + if (unit->enabled_gl_target) + { + _cogl_set_active_texture_unit (unit_index); + GE (ctx, glDisable (unit->enabled_gl_target)); + unit->enabled_gl_target = 0; + } +} + +static int +get_max_texture_units (void) +{ + _COGL_GET_CONTEXT (ctx, 0); + + /* This function is called quite often so we cache the value to + avoid too many GL calls */ + if (ctx->max_texture_units == -1) + { + ctx->max_texture_units = 1; + GE (ctx, glGetIntegerv (GL_MAX_TEXTURE_UNITS, + &ctx->max_texture_units)); + } + + return ctx->max_texture_units; +} + +static void +_cogl_pipeline_fragend_fixed_start (CoglPipeline *pipeline, + int n_layers, + unsigned long pipelines_difference) +{ + _cogl_use_fragment_program (0, COGL_PIPELINE_PROGRAM_TYPE_FIXED); +} + +static void +translate_sources (CoglPipeline *pipeline, + int n_sources, + CoglPipelineCombineSource *source_in, + GLenum *source_out) +{ + int i; + + /* The texture source numbers specified in the layer combine are the + layer numbers so we need to map these to unit indices */ + + for (i = 0; i < n_sources; i++) + switch (source_in[i]) + { + case COGL_PIPELINE_COMBINE_SOURCE_TEXTURE: + source_out[i] = GL_TEXTURE; + break; + + case COGL_PIPELINE_COMBINE_SOURCE_CONSTANT: + source_out[i] = GL_CONSTANT; + break; + + case COGL_PIPELINE_COMBINE_SOURCE_PRIMARY_COLOR: + source_out[i] = GL_PRIMARY_COLOR; + break; + + case COGL_PIPELINE_COMBINE_SOURCE_PREVIOUS: + source_out[i] = GL_PREVIOUS; + break; + + default: + { + int layer_num = source_in[i] - COGL_PIPELINE_COMBINE_SOURCE_TEXTURE0; + CoglPipelineGetLayerFlags flags = COGL_PIPELINE_GET_LAYER_NO_CREATE; + CoglPipelineLayer *layer = + _cogl_pipeline_get_layer_with_flags (pipeline, layer_num, flags); + + if (layer == NULL) + { + static CoglBool warning_seen = FALSE; + if (!warning_seen) + { + g_warning ("The application is trying to use a texture " + "combine with a layer number that does not exist"); + warning_seen = TRUE; + } + source_out[i] = GL_PREVIOUS; + } + else + source_out[i] = (_cogl_pipeline_layer_get_unit_index (layer) + + GL_TEXTURE0); + } + } +} + +static CoglBool +_cogl_pipeline_fragend_fixed_add_layer (CoglPipeline *pipeline, + CoglPipelineLayer *layer, + unsigned long layers_difference) +{ + CoglTextureUnit *unit = + _cogl_get_texture_unit (_cogl_pipeline_layer_get_unit_index (layer)); + int unit_index = unit->index; + int n_rgb_func_args; + int n_alpha_func_args; + + _COGL_GET_CONTEXT (ctx, FALSE); + + /* XXX: Beware that since we are changing the active texture unit we + * must make sure we don't call into other Cogl components that may + * temporarily bind texture objects to query/modify parameters since + * they will end up binding texture unit 1. See + * _cogl_bind_gl_texture_transient for more details. + */ + _cogl_set_active_texture_unit (unit_index); + + if (G_UNLIKELY (unit_index >= get_max_texture_units ())) + { + _cogl_disable_texture_unit (unit_index); + /* TODO: although this isn't considered an error that + * warrants falling back to a different backend we + * should print a warning here. */ + return TRUE; + } + + /* Handle enabling or disabling the right texture type */ + if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE_TYPE) + { + CoglTextureType texture_type = + _cogl_pipeline_layer_get_texture_type (layer); + GLenum gl_target; + + switch (texture_type) + { + case COGL_TEXTURE_TYPE_2D: + gl_target = GL_TEXTURE_2D; + break; + + case COGL_TEXTURE_TYPE_3D: + gl_target = GL_TEXTURE_3D; + break; + + case COGL_TEXTURE_TYPE_RECTANGLE: + gl_target = GL_TEXTURE_RECTANGLE_ARB; + break; + + default: + g_assert_not_reached (); + } + + _cogl_set_active_texture_unit (unit_index); + + /* The common GL code handles binding the right texture so we + just need to handle enabling and disabling it */ + + if (unit->enabled_gl_target != gl_target) + { + /* Disable the previous target if it's still enabled */ + if (unit->enabled_gl_target) + GE (ctx, glDisable (unit->enabled_gl_target)); + + /* Enable the new target */ + if (!G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_TEXTURING))) + { + GE (ctx, glEnable (gl_target)); + unit->enabled_gl_target = gl_target; + } + } + } + else + { + /* Even though there may be no difference between the last flushed + * texture state and the current layers texture state it may be that the + * texture unit has been disabled for some time so we need to assert that + * it's enabled now. + */ + if (!G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_TEXTURING)) && + unit->enabled_gl_target == 0) + { + _cogl_set_active_texture_unit (unit_index); + GE (ctx, glEnable (unit->gl_target)); + unit->enabled_gl_target = unit->gl_target; + } + } + + if (layers_difference & COGL_PIPELINE_LAYER_STATE_COMBINE) + { + CoglPipelineLayer *authority = + _cogl_pipeline_layer_get_authority (layer, + COGL_PIPELINE_LAYER_STATE_COMBINE); + CoglPipelineLayerBigState *big_state = authority->big_state; + GLenum sources[3]; + + GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE)); + + /* Set the combiner functions... */ + GE (ctx, glTexEnvi (GL_TEXTURE_ENV, + GL_COMBINE_RGB, + big_state->texture_combine_rgb_func)); + GE (ctx, glTexEnvi (GL_TEXTURE_ENV, + GL_COMBINE_ALPHA, + big_state->texture_combine_alpha_func)); + + /* + * Setup the function arguments... + */ + + /* For the RGB components... */ + n_rgb_func_args = + _cogl_get_n_args_for_combine_func (big_state->texture_combine_rgb_func); + + translate_sources (pipeline, + n_rgb_func_args, + big_state->texture_combine_rgb_src, + sources); + + GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, + sources[0])); + GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, + big_state->texture_combine_rgb_op[0])); + if (n_rgb_func_args > 1) + { + GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB, + sources[1])); + GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB, + big_state->texture_combine_rgb_op[1])); + } + if (n_rgb_func_args > 2) + { + GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_SRC2_RGB, + sources[2])); + GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_RGB, + big_state->texture_combine_rgb_op[2])); + } + + /* For the Alpha component */ + n_alpha_func_args = + _cogl_get_n_args_for_combine_func (big_state->texture_combine_alpha_func); + + translate_sources (pipeline, + n_alpha_func_args, + big_state->texture_combine_alpha_src, + sources); + + GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, + sources[0])); + GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, + big_state->texture_combine_alpha_op[0])); + if (n_alpha_func_args > 1) + { + GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, + sources[1])); + GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, + big_state->texture_combine_alpha_op[1])); + } + if (n_alpha_func_args > 2) + { + GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_SRC2_ALPHA, + sources[2])); + GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, + big_state->texture_combine_alpha_op[2])); + } + } + + if (layers_difference & COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT) + { + CoglPipelineLayer *authority = + _cogl_pipeline_layer_get_authority + (layer, COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT); + CoglPipelineLayerBigState *big_state = authority->big_state; + + GE (ctx, glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, + big_state->texture_combine_constant)); + } + + return TRUE; +} + +static CoglBool +get_highest_unit_index_cb (CoglPipelineLayer *layer, + void *user_data) +{ + int unit_index = _cogl_pipeline_layer_get_unit_index (layer); + int *highest_index = user_data; + + *highest_index = unit_index; + + return TRUE; +} + +static CoglBool +_cogl_pipeline_fragend_fixed_end (CoglPipeline *pipeline, + unsigned long pipelines_difference) +{ + int highest_unit_index = -1; + int i; + + _COGL_GET_CONTEXT (ctx, FALSE); + + _cogl_pipeline_foreach_layer_internal (pipeline, + get_highest_unit_index_cb, + &highest_unit_index); + + /* Disable additional texture units that may have previously been in use.. */ + for (i = highest_unit_index + 1; i < ctx->texture_units->len; i++) + _cogl_disable_texture_unit (i); + + if (pipelines_difference & COGL_PIPELINE_STATE_FOG) + { + CoglPipeline *authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_FOG); + CoglPipelineFogState *fog_state = &authority->big_state->fog_state; + + if (fog_state->enabled) + { + GLfloat fogColor[4]; + GLenum gl_mode = GL_LINEAR; + + fogColor[0] = cogl_color_get_red_float (&fog_state->color); + fogColor[1] = cogl_color_get_green_float (&fog_state->color); + fogColor[2] = cogl_color_get_blue_float (&fog_state->color); + fogColor[3] = cogl_color_get_alpha_float (&fog_state->color); + + GE (ctx, glEnable (GL_FOG)); + + GE (ctx, glFogfv (GL_FOG_COLOR, fogColor)); + + if (ctx->driver == COGL_DRIVER_GLES1) + switch (fog_state->mode) + { + case COGL_FOG_MODE_LINEAR: + gl_mode = GL_LINEAR; + break; + case COGL_FOG_MODE_EXPONENTIAL: + gl_mode = GL_EXP; + break; + case COGL_FOG_MODE_EXPONENTIAL_SQUARED: + gl_mode = GL_EXP2; + break; + } + /* TODO: support other modes for GLES2 */ + + /* NB: GLES doesn't have glFogi */ + GE (ctx, glFogf (GL_FOG_MODE, gl_mode)); + GE (ctx, glHint (GL_FOG_HINT, GL_NICEST)); + + GE (ctx, glFogf (GL_FOG_DENSITY, fog_state->density)); + GE (ctx, glFogf (GL_FOG_START, fog_state->z_near)); + GE (ctx, glFogf (GL_FOG_END, fog_state->z_far)); + } + else + GE (ctx, glDisable (GL_FOG)); + } + + return TRUE; +} + +const CoglPipelineFragend _cogl_pipeline_fixed_fragend = +{ + _cogl_pipeline_fragend_fixed_start, + _cogl_pipeline_fragend_fixed_add_layer, + NULL, /* passthrough */ + _cogl_pipeline_fragend_fixed_end, + NULL, /* pipeline_change_notify */ + NULL, /* pipeline_set_parent_notify */ + NULL, /* layer_change_notify */ +}; + +#endif /* COGL_PIPELINE_FRAGEND_FIXED */ + diff --git a/cogl/cogl/driver/gl/cogl-pipeline-fragend-glsl-private.h b/cogl/cogl/driver/gl/cogl-pipeline-fragend-glsl-private.h new file mode 100644 index 0000000..72f5928 --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-pipeline-fragend-glsl-private.h @@ -0,0 +1,45 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_PIPELINE_FRAGEND_GLSL_PRIVATE_H +#define __COGL_PIPELINE_FRAGEND_GLSL_PRIVATE_H + +#include "cogl-pipeline-private.h" + +extern const CoglPipelineFragend _cogl_pipeline_glsl_fragend; + +GLuint +_cogl_pipeline_fragend_glsl_get_shader (CoglPipeline *pipeline); + +#endif /* __COGL_PIPELINE_FRAGEND_GLSL_PRIVATE_H */ + diff --git a/cogl/cogl/driver/gl/cogl-pipeline-fragend-glsl.c b/cogl/cogl/driver/gl/cogl-pipeline-fragend-glsl.c new file mode 100644 index 0000000..c255bf9 --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-pipeline-fragend-glsl.c @@ -0,0 +1,1149 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009,2010,2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + * Neil Roberts + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include + +#include "cogl-context-private.h" +#include "cogl-util-gl-private.h" +#include "cogl-pipeline-private.h" +#include "cogl-pipeline-layer-private.h" +#include "cogl-blend-string.h" +#include "cogl-snippet-private.h" +#include "cogl-list.h" + +#ifdef COGL_PIPELINE_FRAGEND_GLSL + +#include "cogl-context-private.h" +#include "cogl-object-private.h" +#include "cogl-shader-private.h" +#include "cogl-program-private.h" +#include "cogl-pipeline-cache.h" +#include "cogl-pipeline-fragend-glsl-private.h" +#include "cogl-glsl-shader-private.h" + +#include + +/* + * GL/GLES compatability defines for pipeline thingies: + */ + +/* This might not be defined on GLES */ +#ifndef GL_TEXTURE_3D +#define GL_TEXTURE_3D 0x806F +#endif + +const CoglPipelineFragend _cogl_pipeline_glsl_backend; + +typedef struct _UnitState +{ + unsigned int sampled:1; + unsigned int combine_constant_used:1; +} UnitState; + +typedef struct _LayerData +{ + CoglList link; + + /* Layer index for the for the previous layer. This isn't + necessarily the same as this layer's index - 1 because the + indices can have gaps. If this is the first layer then it will be + -1 */ + int previous_layer_index; + + CoglPipelineLayer *layer; +} LayerData; + +typedef struct +{ + int ref_count; + + GLuint gl_shader; + GString *header, *source; + UnitState *unit_state; + + /* List of layers that we haven't generated code for yet. These are + in reverse order. As soon as we're about to generate code for + layer we'll remove it from the list so we don't generate it + again */ + CoglList layers; + + CoglPipelineCacheEntry *cache_entry; +} CoglPipelineShaderState; + +static CoglUserDataKey shader_state_key; + +static void +ensure_layer_generated (CoglPipeline *pipeline, + int layer_num); + +static CoglPipelineShaderState * +shader_state_new (int n_layers, + CoglPipelineCacheEntry *cache_entry) +{ + CoglPipelineShaderState *shader_state; + + shader_state = g_slice_new0 (CoglPipelineShaderState); + shader_state->ref_count = 1; + shader_state->unit_state = g_new0 (UnitState, n_layers); + shader_state->cache_entry = cache_entry; + + return shader_state; +} + +static CoglPipelineShaderState * +get_shader_state (CoglPipeline *pipeline) +{ + return cogl_object_get_user_data (COGL_OBJECT (pipeline), &shader_state_key); +} + +static void +destroy_shader_state (void *user_data, + void *instance) +{ + CoglPipelineShaderState *shader_state = user_data; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (shader_state->cache_entry && + shader_state->cache_entry->pipeline != instance) + shader_state->cache_entry->usage_count--; + + if (--shader_state->ref_count == 0) + { + if (shader_state->gl_shader) + GE( ctx, glDeleteShader (shader_state->gl_shader) ); + + g_free (shader_state->unit_state); + + g_slice_free (CoglPipelineShaderState, shader_state); + } +} + +static void +set_shader_state (CoglPipeline *pipeline, CoglPipelineShaderState *shader_state) +{ + if (shader_state) + { + shader_state->ref_count++; + + /* If we're not setting the state on the template pipeline then + * mark it as a usage of the pipeline cache entry */ + if (shader_state->cache_entry && + shader_state->cache_entry->pipeline != pipeline) + shader_state->cache_entry->usage_count++; + } + + _cogl_object_set_user_data (COGL_OBJECT (pipeline), + &shader_state_key, + shader_state, + destroy_shader_state); +} + +static void +dirty_shader_state (CoglPipeline *pipeline) +{ + cogl_object_set_user_data (COGL_OBJECT (pipeline), + &shader_state_key, + NULL, + NULL); +} + +GLuint +_cogl_pipeline_fragend_glsl_get_shader (CoglPipeline *pipeline) +{ + CoglPipelineShaderState *shader_state = get_shader_state (pipeline); + + if (shader_state) + return shader_state->gl_shader; + else + return 0; +} + +static CoglPipelineSnippetList * +get_fragment_snippets (CoglPipeline *pipeline) +{ + pipeline = + _cogl_pipeline_get_authority (pipeline, + COGL_PIPELINE_STATE_FRAGMENT_SNIPPETS); + + return &pipeline->big_state->fragment_snippets; +} + +static CoglPipelineSnippetList * +get_layer_fragment_snippets (CoglPipelineLayer *layer) +{ + unsigned long state = COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS; + layer = _cogl_pipeline_layer_get_authority (layer, state); + + return &layer->big_state->fragment_snippets; +} + +static CoglBool +has_replace_hook (CoglPipelineLayer *layer, + CoglSnippetHook hook) +{ + GList *l; + + for (l = get_layer_fragment_snippets (layer)->entries; l; l = l->next) + { + CoglSnippet *snippet = l->data; + + if (snippet->hook == hook && snippet->replace) + return TRUE; + } + + return FALSE; +} + +static CoglBool +add_layer_declaration_cb (CoglPipelineLayer *layer, + void *user_data) +{ + CoglPipelineShaderState *shader_state = user_data; + CoglTextureType texture_type = + _cogl_pipeline_layer_get_texture_type (layer); + const char *target_string; + + _cogl_gl_util_get_texture_target_string (texture_type, &target_string, NULL); + + g_string_append_printf (shader_state->header, + "uniform sampler%s cogl_sampler%i;\n", + target_string, + layer->index); + + return TRUE; +} + +static void +add_layer_declarations (CoglPipeline *pipeline, + CoglPipelineShaderState *shader_state) +{ + /* We always emit sampler uniforms in case there will be custom + * layer snippets that want to sample arbitrary layers. */ + + _cogl_pipeline_foreach_layer_internal (pipeline, + add_layer_declaration_cb, + shader_state); +} + +static void +add_global_declarations (CoglPipeline *pipeline, + CoglPipelineShaderState *shader_state) +{ + CoglSnippetHook hook = COGL_SNIPPET_HOOK_FRAGMENT_GLOBALS; + CoglPipelineSnippetList *snippets = get_fragment_snippets (pipeline); + + /* Add the global data hooks. All of the code in these snippets is + * always added and only the declarations data is used */ + + _cogl_pipeline_snippet_generate_declarations (shader_state->header, + hook, + snippets); +} + +static void +_cogl_pipeline_fragend_glsl_start (CoglPipeline *pipeline, + int n_layers, + unsigned long pipelines_difference) +{ + CoglPipelineShaderState *shader_state; + CoglPipeline *authority; + CoglPipelineCacheEntry *cache_entry = NULL; + CoglProgram *user_program = cogl_pipeline_get_user_program (pipeline); + int i; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + /* Now lookup our glsl backend private state */ + shader_state = get_shader_state (pipeline); + + if (shader_state == NULL) + { + /* If we don't have an associated glsl shader yet then find the + * glsl-authority (the oldest ancestor whose state will result in + * the same shader being generated as for this pipeline). + * + * We always make sure to associate new shader with the + * glsl-authority to maximize the chance that other pipelines can + * share it. + */ + authority = _cogl_pipeline_find_equivalent_parent + (pipeline, + _cogl_pipeline_get_state_for_fragment_codegen (ctx) & + ~COGL_PIPELINE_STATE_LAYERS, + _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx)); + + shader_state = get_shader_state (authority); + + /* If we don't have an existing program associated with the + * glsl-authority then start generating code for a new shader... + */ + if (shader_state == NULL) + { + /* Check if there is already a similar cached pipeline whose + shader state we can share */ + if (G_LIKELY (!(COGL_DEBUG_ENABLED + (COGL_DEBUG_DISABLE_PROGRAM_CACHES)))) + { + cache_entry = + _cogl_pipeline_cache_get_fragment_template (ctx->pipeline_cache, + authority); + + shader_state = get_shader_state (cache_entry->pipeline); + } + + if (shader_state) + shader_state->ref_count++; + else + shader_state = shader_state_new (n_layers, cache_entry); + + set_shader_state (authority, shader_state); + + shader_state->ref_count--; + + if (cache_entry) + set_shader_state (cache_entry->pipeline, shader_state); + } + + /* If the pipeline isn't actually its own glsl-authority + * then take a reference to the program state associated + * with the glsl-authority... */ + if (authority != pipeline) + set_shader_state (pipeline, shader_state); + } + + if (user_program) + { + /* If the user program contains a fragment shader then we don't need + to generate one */ + if (_cogl_program_has_fragment_shader (user_program)) + { + if (shader_state->gl_shader) + { + GE( ctx, glDeleteShader (shader_state->gl_shader) ); + shader_state->gl_shader = 0; + } + return; + } + } + + if (shader_state->gl_shader) + return; + + /* If we make it here then we have a glsl_shader_state struct + without a gl_shader either because this is the first time we've + encountered it or because the user program has changed */ + + /* We reuse two grow-only GStrings for code-gen. One string + contains the uniform and attribute declarations while the + other contains the main function. We need two strings + because we need to dynamically declare attributes as the + add_layer callback is invoked */ + g_string_set_size (ctx->codegen_header_buffer, 0); + g_string_set_size (ctx->codegen_source_buffer, 0); + shader_state->header = ctx->codegen_header_buffer; + shader_state->source = ctx->codegen_source_buffer; + _cogl_list_init (&shader_state->layers); + + add_layer_declarations (pipeline, shader_state); + add_global_declarations (pipeline, shader_state); + + g_string_append (shader_state->source, + "void\n" + "cogl_generated_source ()\n" + "{\n"); + + for (i = 0; i < n_layers; i++) + { + shader_state->unit_state[i].sampled = FALSE; + shader_state->unit_state[i].combine_constant_used = FALSE; + } +} + +static void +add_constant_lookup (CoglPipelineShaderState *shader_state, + CoglPipeline *pipeline, + CoglPipelineLayer *layer, + const char *swizzle) +{ + g_string_append_printf (shader_state->header, + "_cogl_layer_constant_%i.%s", + layer->index, swizzle); +} + +static void +ensure_texture_lookup_generated (CoglPipelineShaderState *shader_state, + CoglPipeline *pipeline, + CoglPipelineLayer *layer) +{ + int unit_index = _cogl_pipeline_layer_get_unit_index (layer); + CoglPipelineSnippetData snippet_data; + CoglTextureType texture_type; + const char *target_string, *tex_coord_swizzle; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (shader_state->unit_state[unit_index].sampled) + return; + + texture_type = + _cogl_pipeline_layer_get_texture_type (layer); + _cogl_gl_util_get_texture_target_string (texture_type, + &target_string, + &tex_coord_swizzle); + + shader_state->unit_state[unit_index].sampled = TRUE; + + g_string_append_printf (shader_state->header, + "vec4 cogl_texel%i;\n", + layer->index); + + g_string_append_printf (shader_state->source, + " cogl_texel%i = cogl_texture_lookup%i (" + "cogl_sampler%i, ", + layer->index, + layer->index, + layer->index); + + if (cogl_pipeline_get_layer_point_sprite_coords_enabled (pipeline, + layer->index)) + g_string_append_printf (shader_state->source, + "vec4 (cogl_point_coord, 0.0, 1.0)"); + else + g_string_append_printf (shader_state->source, + "cogl_tex_coord%i_in", + layer->index); + + g_string_append (shader_state->source, ");\n"); + + /* There's no need to generate the real texture lookup if it's going + to be replaced */ + if (!has_replace_hook (layer, COGL_SNIPPET_HOOK_TEXTURE_LOOKUP)) + { + g_string_append_printf (shader_state->header, + "vec4\n" + "cogl_real_texture_lookup%i (sampler%s tex,\n" + " vec4 coords)\n" + "{\n" + " return ", + layer->index, + target_string); + + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_TEXTURING))) + g_string_append (shader_state->header, + "vec4 (1.0, 1.0, 1.0, 1.0);\n"); + else + g_string_append_printf (shader_state->header, + "texture%s (tex, coords.%s);\n", + target_string, tex_coord_swizzle); + + g_string_append (shader_state->header, "}\n"); + } + + /* Wrap the texture lookup in any snippets that have been hooked */ + memset (&snippet_data, 0, sizeof (snippet_data)); + snippet_data.snippets = get_layer_fragment_snippets (layer); + snippet_data.hook = COGL_SNIPPET_HOOK_TEXTURE_LOOKUP; + snippet_data.chain_function = g_strdup_printf ("cogl_real_texture_lookup%i", + layer->index); + snippet_data.final_name = g_strdup_printf ("cogl_texture_lookup%i", + layer->index); + snippet_data.function_prefix = g_strdup_printf ("cogl_texture_lookup_hook%i", + layer->index); + snippet_data.return_type = "vec4"; + snippet_data.return_variable = "cogl_texel"; + snippet_data.arguments = "cogl_sampler, cogl_tex_coord"; + snippet_data.argument_declarations = + g_strdup_printf ("sampler%s cogl_sampler, vec4 cogl_tex_coord", + target_string); + snippet_data.source_buf = shader_state->header; + + _cogl_pipeline_snippet_generate_code (&snippet_data); + + g_free ((char *) snippet_data.chain_function); + g_free ((char *) snippet_data.final_name); + g_free ((char *) snippet_data.function_prefix); + g_free ((char *) snippet_data.argument_declarations); +} + +static void +add_arg (CoglPipelineShaderState *shader_state, + CoglPipeline *pipeline, + CoglPipelineLayer *layer, + int previous_layer_index, + CoglPipelineCombineSource src, + CoglPipelineCombineOp operand, + const char *swizzle) +{ + GString *shader_source = shader_state->header; + char alpha_swizzle[5] = "aaaa"; + + g_string_append_c (shader_source, '('); + + if (operand == COGL_PIPELINE_COMBINE_OP_ONE_MINUS_SRC_COLOR || + operand == COGL_PIPELINE_COMBINE_OP_ONE_MINUS_SRC_ALPHA) + g_string_append_printf (shader_source, + "vec4(1.0, 1.0, 1.0, 1.0).%s - ", + swizzle); + + /* If the operand is reading from the alpha then replace the swizzle + with the same number of copies of the alpha */ + if (operand == COGL_PIPELINE_COMBINE_OP_SRC_ALPHA || + operand == COGL_PIPELINE_COMBINE_OP_ONE_MINUS_SRC_ALPHA) + { + alpha_swizzle[strlen (swizzle)] = '\0'; + swizzle = alpha_swizzle; + } + + switch (src) + { + case COGL_PIPELINE_COMBINE_SOURCE_TEXTURE: + g_string_append_printf (shader_source, + "cogl_texel%i.%s", + layer->index, + swizzle); + break; + + case COGL_PIPELINE_COMBINE_SOURCE_CONSTANT: + add_constant_lookup (shader_state, + pipeline, + layer, + swizzle); + break; + + case COGL_PIPELINE_COMBINE_SOURCE_PREVIOUS: + if (previous_layer_index >= 0) + { + g_string_append_printf (shader_source, + "cogl_layer%i.%s", + previous_layer_index, + swizzle); + break; + } + /* flow through */ + case COGL_PIPELINE_COMBINE_SOURCE_PRIMARY_COLOR: + g_string_append_printf (shader_source, "cogl_color_in.%s", swizzle); + break; + + default: + { + int layer_num = src - COGL_PIPELINE_COMBINE_SOURCE_TEXTURE0; + CoglPipelineGetLayerFlags flags = COGL_PIPELINE_GET_LAYER_NO_CREATE; + CoglPipelineLayer *other_layer = + _cogl_pipeline_get_layer_with_flags (pipeline, layer_num, flags); + + if (other_layer == NULL) + { + static CoglBool warning_seen = FALSE; + if (!warning_seen) + { + g_warning ("The application is trying to use a texture " + "combine with a layer number that does not exist"); + warning_seen = TRUE; + } + g_string_append_printf (shader_source, + "vec4 (1.0, 1.0, 1.0, 1.0).%s", + swizzle); + } + else + g_string_append_printf (shader_source, + "cogl_texel%i.%s", + other_layer->index, + swizzle); + } + break; + } + + g_string_append_c (shader_source, ')'); +} + +static void +ensure_arg_generated (CoglPipeline *pipeline, + CoglPipelineLayer *layer, + int previous_layer_index, + CoglPipelineCombineSource src) +{ + CoglPipelineShaderState *shader_state = get_shader_state (pipeline); + + switch (src) + { + case COGL_PIPELINE_COMBINE_SOURCE_PRIMARY_COLOR: + /* This doesn't involve any other layers */ + break; + + case COGL_PIPELINE_COMBINE_SOURCE_CONSTANT: + { + int unit_index = _cogl_pipeline_layer_get_unit_index (layer); + /* Create a sampler uniform for this layer if we haven't already */ + if (!shader_state->unit_state[unit_index].combine_constant_used) + { + g_string_append_printf (shader_state->header, + "uniform vec4 _cogl_layer_constant_%i;\n", + layer->index); + shader_state->unit_state[unit_index].combine_constant_used = TRUE; + } + } + break; + + case COGL_PIPELINE_COMBINE_SOURCE_PREVIOUS: + if (previous_layer_index >= 0) + ensure_layer_generated (pipeline, previous_layer_index); + break; + + case COGL_PIPELINE_COMBINE_SOURCE_TEXTURE: + ensure_texture_lookup_generated (shader_state, + pipeline, + layer); + break; + + default: + if (src >= COGL_PIPELINE_COMBINE_SOURCE_TEXTURE0) + { + int layer_num = src - COGL_PIPELINE_COMBINE_SOURCE_TEXTURE0; + CoglPipelineGetLayerFlags flags = COGL_PIPELINE_GET_LAYER_NO_CREATE; + CoglPipelineLayer *other_layer = + _cogl_pipeline_get_layer_with_flags (pipeline, layer_num, flags); + + if (other_layer) + ensure_texture_lookup_generated (shader_state, + pipeline, + other_layer); + } + break; + } +} + +static void +ensure_args_for_func (CoglPipeline *pipeline, + CoglPipelineLayer *layer, + int previous_layer_index, + CoglPipelineCombineFunc function, + CoglPipelineCombineSource *src) +{ + int n_args = _cogl_get_n_args_for_combine_func (function); + int i; + + for (i = 0; i < n_args; i++) + ensure_arg_generated (pipeline, layer, previous_layer_index, src[i]); +} + +static void +append_masked_combine (CoglPipeline *pipeline, + CoglPipelineLayer *layer, + int previous_layer_index, + const char *swizzle, + CoglPipelineCombineFunc function, + CoglPipelineCombineSource *src, + CoglPipelineCombineOp *op) +{ + CoglPipelineShaderState *shader_state = get_shader_state (pipeline); + GString *shader_source = shader_state->header; + + g_string_append_printf (shader_state->header, + " cogl_layer.%s = ", + swizzle); + + switch (function) + { + case COGL_PIPELINE_COMBINE_FUNC_REPLACE: + add_arg (shader_state, pipeline, layer, previous_layer_index, + src[0], op[0], swizzle); + break; + + case COGL_PIPELINE_COMBINE_FUNC_MODULATE: + add_arg (shader_state, pipeline, layer, previous_layer_index, + src[0], op[0], swizzle); + g_string_append (shader_source, " * "); + add_arg (shader_state, pipeline, layer, previous_layer_index, + src[1], op[1], swizzle); + break; + + case COGL_PIPELINE_COMBINE_FUNC_ADD: + add_arg (shader_state, pipeline, layer, previous_layer_index, + src[0], op[0], swizzle); + g_string_append (shader_source, " + "); + add_arg (shader_state, pipeline, layer, previous_layer_index, + src[1], op[1], swizzle); + break; + + case COGL_PIPELINE_COMBINE_FUNC_ADD_SIGNED: + add_arg (shader_state, pipeline, layer, previous_layer_index, + src[0], op[0], swizzle); + g_string_append (shader_source, " + "); + add_arg (shader_state, pipeline, layer, previous_layer_index, + src[1], op[1], swizzle); + g_string_append_printf (shader_source, + " - vec4(0.5, 0.5, 0.5, 0.5).%s", + swizzle); + break; + + case COGL_PIPELINE_COMBINE_FUNC_SUBTRACT: + add_arg (shader_state, pipeline, layer, previous_layer_index, + src[0], op[0], swizzle); + g_string_append (shader_source, " - "); + add_arg (shader_state, pipeline, layer, previous_layer_index, + src[1], op[1], swizzle); + break; + + case COGL_PIPELINE_COMBINE_FUNC_INTERPOLATE: + add_arg (shader_state, pipeline, layer, previous_layer_index, + src[0], op[0], swizzle); + g_string_append (shader_source, " * "); + add_arg (shader_state, pipeline, layer, previous_layer_index, + src[2], op[2], swizzle); + g_string_append (shader_source, " + "); + add_arg (shader_state, pipeline, layer, previous_layer_index, + src[1], op[1], swizzle); + g_string_append_printf (shader_source, + " * (vec4(1.0, 1.0, 1.0, 1.0).%s - ", + swizzle); + add_arg (shader_state, pipeline, layer, previous_layer_index, + src[2], op[2], swizzle); + g_string_append_c (shader_source, ')'); + break; + + case COGL_PIPELINE_COMBINE_FUNC_DOT3_RGB: + case COGL_PIPELINE_COMBINE_FUNC_DOT3_RGBA: + g_string_append (shader_source, "vec4(4.0 * (("); + add_arg (shader_state, pipeline, layer, previous_layer_index, + src[0], op[0], "r"); + g_string_append (shader_source, " - 0.5) * ("); + add_arg (shader_state, pipeline, layer, previous_layer_index, + src[1], op[1], "r"); + g_string_append (shader_source, " - 0.5) + ("); + add_arg (shader_state, pipeline, layer, previous_layer_index, + src[0], op[0], "g"); + g_string_append (shader_source, " - 0.5) * ("); + add_arg (shader_state, pipeline, layer, previous_layer_index, + src[1], op[1], "g"); + g_string_append (shader_source, " - 0.5) + ("); + add_arg (shader_state, pipeline, layer, previous_layer_index, + src[0], op[0], "b"); + g_string_append (shader_source, " - 0.5) * ("); + add_arg (shader_state, pipeline, layer, previous_layer_index, + src[1], op[1], "b"); + g_string_append_printf (shader_source, " - 0.5))).%s", swizzle); + break; + } + + g_string_append_printf (shader_source, ";\n"); +} + +static void +ensure_layer_generated (CoglPipeline *pipeline, + int layer_index) +{ + CoglPipelineShaderState *shader_state = get_shader_state (pipeline); + CoglPipelineLayer *combine_authority; + CoglPipelineLayerBigState *big_state; + CoglPipelineLayer *layer; + CoglPipelineSnippetData snippet_data; + LayerData *layer_data; + + /* Find the layer that corresponds to this layer_num */ + _cogl_list_for_each (layer_data, &shader_state->layers, link) + { + layer = layer_data->layer; + + if (layer->index == layer_index) + goto found; + } + + /* If we didn't find it then we can assume the layer has already + been generated */ + return; + + found: + + /* Remove the layer from the list so we don't generate it again */ + _cogl_list_remove (&layer_data->link); + + combine_authority = + _cogl_pipeline_layer_get_authority (layer, + COGL_PIPELINE_LAYER_STATE_COMBINE); + big_state = combine_authority->big_state; + + /* Make a global variable for the result of the layer code */ + g_string_append_printf (shader_state->header, + "vec4 cogl_layer%i;\n", + layer_index); + + /* Skip the layer generation if there is a snippet that replaces the + default layer code. This is important because generating this + code may cause the code for other layers to be generated and + stored in the global variable. If this code isn't actually used + then the global variables would be uninitialised and they may be + used from other layers */ + if (!has_replace_hook (layer, COGL_SNIPPET_HOOK_LAYER_FRAGMENT)) + { + ensure_args_for_func (pipeline, + layer, + layer_data->previous_layer_index, + big_state->texture_combine_rgb_func, + big_state->texture_combine_rgb_src); + ensure_args_for_func (pipeline, + layer, + layer_data->previous_layer_index, + big_state->texture_combine_alpha_func, + big_state->texture_combine_alpha_src); + + g_string_append_printf (shader_state->header, + "vec4\n" + "cogl_real_generate_layer%i ()\n" + "{\n" + " vec4 cogl_layer;\n", + layer_index); + + if (!_cogl_pipeline_layer_needs_combine_separate (combine_authority) || + /* GL_DOT3_RGBA Is a bit weird as a GL_COMBINE_RGB function + * since if you use it, it overrides your ALPHA function... + */ + big_state->texture_combine_rgb_func == + COGL_PIPELINE_COMBINE_FUNC_DOT3_RGBA) + append_masked_combine (pipeline, + layer, + layer_data->previous_layer_index, + "rgba", + big_state->texture_combine_rgb_func, + big_state->texture_combine_rgb_src, + big_state->texture_combine_rgb_op); + else + { + append_masked_combine (pipeline, + layer, + layer_data->previous_layer_index, + "rgb", + big_state->texture_combine_rgb_func, + big_state->texture_combine_rgb_src, + big_state->texture_combine_rgb_op); + append_masked_combine (pipeline, + layer, + layer_data->previous_layer_index, + "a", + big_state->texture_combine_alpha_func, + big_state->texture_combine_alpha_src, + big_state->texture_combine_alpha_op); + } + + g_string_append (shader_state->header, + " return cogl_layer;\n" + "}\n"); + } + + /* Wrap the layer code in any snippets that have been hooked */ + memset (&snippet_data, 0, sizeof (snippet_data)); + snippet_data.snippets = get_layer_fragment_snippets (layer); + snippet_data.hook = COGL_SNIPPET_HOOK_LAYER_FRAGMENT; + snippet_data.chain_function = g_strdup_printf ("cogl_real_generate_layer%i", + layer_index); + snippet_data.final_name = g_strdup_printf ("cogl_generate_layer%i", + layer_index); + snippet_data.function_prefix = g_strdup_printf ("cogl_generate_layer%i", + layer_index); + snippet_data.return_type = "vec4"; + snippet_data.return_variable = "cogl_layer"; + snippet_data.source_buf = shader_state->header; + + _cogl_pipeline_snippet_generate_code (&snippet_data); + + g_free ((char *) snippet_data.chain_function); + g_free ((char *) snippet_data.final_name); + g_free ((char *) snippet_data.function_prefix); + + g_string_append_printf (shader_state->source, + " cogl_layer%i = cogl_generate_layer%i ();\n", + layer_index, + layer_index); + + g_slice_free (LayerData, layer_data); +} + +static CoglBool +_cogl_pipeline_fragend_glsl_add_layer (CoglPipeline *pipeline, + CoglPipelineLayer *layer, + unsigned long layers_difference) +{ + CoglPipelineShaderState *shader_state = get_shader_state (pipeline); + LayerData *layer_data; + + if (!shader_state->source) + return TRUE; + + /* Store the layers in reverse order */ + layer_data = g_slice_new (LayerData); + layer_data->layer = layer; + + if (_cogl_list_empty (&shader_state->layers)) + { + layer_data->previous_layer_index = -1; + } + else + { + LayerData *first = + _cogl_container_of (shader_state->layers.next, LayerData, link); + layer_data->previous_layer_index = first->layer->index; + } + + _cogl_list_insert (&shader_state->layers, &layer_data->link); + + return TRUE; +} + +/* GLES2 and GL3 don't have alpha testing so we need to implement it + in the shader */ + +#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL) + +static void +add_alpha_test_snippet (CoglPipeline *pipeline, + CoglPipelineShaderState *shader_state) +{ + CoglPipelineAlphaFunc alpha_func; + + alpha_func = cogl_pipeline_get_alpha_test_function (pipeline); + + if (alpha_func == COGL_PIPELINE_ALPHA_FUNC_ALWAYS) + /* Do nothing */ + return; + + if (alpha_func == COGL_PIPELINE_ALPHA_FUNC_NEVER) + { + /* Always discard the fragment */ + g_string_append (shader_state->source, + " discard;\n"); + return; + } + + /* For all of the other alpha functions we need a uniform for the + reference */ + + g_string_append (shader_state->header, + "uniform float _cogl_alpha_test_ref;\n"); + + g_string_append (shader_state->source, + " if (cogl_color_out.a "); + + switch (alpha_func) + { + case COGL_PIPELINE_ALPHA_FUNC_LESS: + g_string_append (shader_state->source, ">="); + break; + case COGL_PIPELINE_ALPHA_FUNC_EQUAL: + g_string_append (shader_state->source, "!="); + break; + case COGL_PIPELINE_ALPHA_FUNC_LEQUAL: + g_string_append (shader_state->source, ">"); + break; + case COGL_PIPELINE_ALPHA_FUNC_GREATER: + g_string_append (shader_state->source, "<="); + break; + case COGL_PIPELINE_ALPHA_FUNC_NOTEQUAL: + g_string_append (shader_state->source, "=="); + break; + case COGL_PIPELINE_ALPHA_FUNC_GEQUAL: + g_string_append (shader_state->source, "< "); + break; + + case COGL_PIPELINE_ALPHA_FUNC_ALWAYS: + case COGL_PIPELINE_ALPHA_FUNC_NEVER: + g_assert_not_reached (); + break; + } + + g_string_append (shader_state->source, + " _cogl_alpha_test_ref)\n discard;\n"); +} + +#endif /* HAVE_COGL_GLES2 */ + +static CoglBool +_cogl_pipeline_fragend_glsl_end (CoglPipeline *pipeline, + unsigned long pipelines_difference) +{ + CoglPipelineShaderState *shader_state = get_shader_state (pipeline); + + _COGL_GET_CONTEXT (ctx, FALSE); + + if (shader_state->source) + { + const char *source_strings[2]; + GLint lengths[2]; + GLint compile_status; + GLuint shader; + CoglPipelineSnippetData snippet_data; + + COGL_STATIC_COUNTER (fragend_glsl_compile_counter, + "glsl fragment compile counter", + "Increments each time a new GLSL " + "fragment shader is compiled", + 0 /* no application private data */); + COGL_COUNTER_INC (_cogl_uprof_context, fragend_glsl_compile_counter); + + /* We only need to generate code to calculate the fragment value + for the last layer. If the value of this layer depends on any + previous layers then it will recursively generate the code + for those layers */ + if (!_cogl_list_empty (&shader_state->layers)) + { + CoglPipelineLayer *last_layer; + LayerData *layer_data, *tmp; + + layer_data = _cogl_container_of (shader_state->layers.next, + LayerData, + link); + last_layer = layer_data->layer; + + ensure_layer_generated (pipeline, last_layer->index); + g_string_append_printf (shader_state->source, + " cogl_color_out = cogl_layer%i;\n", + last_layer->index); + + _cogl_list_for_each_safe (layer_data, + tmp, + &shader_state->layers, + link) + g_slice_free (LayerData, layer_data); + } + else + g_string_append (shader_state->source, + " cogl_color_out = cogl_color_in;\n"); + +#if defined(HAVE_COGL_GLES2) || defined (HAVE_COGL_GL) + if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_ALPHA_TEST)) + add_alpha_test_snippet (pipeline, shader_state); +#endif + + /* Close the function surrounding the generated fragment processing */ + g_string_append (shader_state->source, "}\n"); + + /* Add all of the hooks for fragment processing */ + memset (&snippet_data, 0, sizeof (snippet_data)); + snippet_data.snippets = get_fragment_snippets (pipeline); + snippet_data.hook = COGL_SNIPPET_HOOK_FRAGMENT; + snippet_data.chain_function = "cogl_generated_source"; + snippet_data.final_name = "main"; + snippet_data.function_prefix = "cogl_fragment_hook"; + snippet_data.source_buf = shader_state->source; + _cogl_pipeline_snippet_generate_code (&snippet_data); + + GE_RET( shader, ctx, glCreateShader (GL_FRAGMENT_SHADER) ); + + lengths[0] = shader_state->header->len; + source_strings[0] = shader_state->header->str; + lengths[1] = shader_state->source->len; + source_strings[1] = shader_state->source->str; + + _cogl_glsl_shader_set_source_with_boilerplate (ctx, + shader, GL_FRAGMENT_SHADER, + pipeline, + 2, /* count */ + source_strings, lengths); + + GE( ctx, glCompileShader (shader) ); + GE( ctx, glGetShaderiv (shader, GL_COMPILE_STATUS, &compile_status) ); + + if (!compile_status) + { + GLint len = 0; + char *shader_log; + + GE( ctx, glGetShaderiv (shader, GL_INFO_LOG_LENGTH, &len) ); + shader_log = g_alloca (len); + GE( ctx, glGetShaderInfoLog (shader, len, &len, shader_log) ); + g_warning ("Shader compilation failed:\n%s", shader_log); + } + + shader_state->header = NULL; + shader_state->source = NULL; + shader_state->gl_shader = shader; + } + + return TRUE; +} + +static void +_cogl_pipeline_fragend_glsl_pre_change_notify (CoglPipeline *pipeline, + CoglPipelineState change, + const CoglColor *new_color) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if ((change & _cogl_pipeline_get_state_for_fragment_codegen (ctx))) + dirty_shader_state (pipeline); +} + +/* NB: layers are considered immutable once they have any dependants + * so although multiple pipelines can end up depending on a single + * static layer, we can guarantee that if a layer is being *changed* + * then it can only have one pipeline depending on it. + * + * XXX: Don't forget this is *pre* change, we can't read the new value + * yet! + */ +static void +_cogl_pipeline_fragend_glsl_layer_pre_change_notify ( + CoglPipeline *owner, + CoglPipelineLayer *layer, + CoglPipelineLayerState change) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if ((change & _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx))) + { + dirty_shader_state (owner); + return; + } + + /* TODO: we could be saving snippets of texture combine code along + * with each layer and then when a layer changes we would just free + * the snippet. */ +} + +const CoglPipelineFragend _cogl_pipeline_glsl_fragend = +{ + _cogl_pipeline_fragend_glsl_start, + _cogl_pipeline_fragend_glsl_add_layer, + NULL, /* passthrough */ + _cogl_pipeline_fragend_glsl_end, + _cogl_pipeline_fragend_glsl_pre_change_notify, + NULL, /* pipeline_set_parent_notify */ + _cogl_pipeline_fragend_glsl_layer_pre_change_notify +}; + +#endif /* COGL_PIPELINE_FRAGEND_GLSL */ + diff --git a/cogl/cogl/driver/gl/cogl-pipeline-opengl-private.h b/cogl/cogl/driver/gl/cogl-pipeline-opengl-private.h new file mode 100644 index 0000000..0a374be --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-pipeline-opengl-private.h @@ -0,0 +1,158 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_PIPELINE_OPENGL_PRIVATE_H +#define __COGL_PIPELINE_OPENGL_PRIVATE_H + +#include "cogl-pipeline-private.h" +#include "cogl-matrix-stack.h" + +/* + * cogl-pipeline.c owns the GPU's texture unit state so we have some + * private structures for describing the current state of a texture + * unit that we track in a per context array (ctx->texture_units) that + * grows according to the largest texture unit used so far... + * + * Roughly speaking the members in this structure are of two kinds: + * either they are a low level reflection of the state we send to + * OpenGL or they are for high level meta data assoicated with the + * texture unit when flushing CoglPipelineLayers that is typically + * used to optimize subsequent re-flushing of the same layer. + * + * The low level members are at the top, and the high level members + * start with the .layer member. + */ +typedef struct _CoglTextureUnit +{ + /* The base 0 texture unit index which can be used with + * glActiveTexture () */ + int index; + + /* The GL target currently glEnabled or 0 if nothing is + * enabled. This is only used by the fixed pipeline fragend */ + GLenum enabled_gl_target; + + /* The raw GL texture object name for which we called glBindTexture when + * we flushed the last layer. (NB: The CoglTexture associated + * with a layer may represent more than one GL texture) */ + GLuint gl_texture; + /* The target of the GL texture object. This is just used so that we + * can quickly determine the intended target to flush when + * dirty_gl_texture == TRUE */ + GLenum gl_target; + + /* Foreign textures are those not created or deleted by Cogl. If we ever + * call glBindTexture for a foreign texture then the next time we are + * asked to glBindTexture we can't try and optimize a redundant state + * change because we don't know if the original texture name was deleted + * and now we are being asked to bind a recycled name. */ + CoglBool is_foreign; + + /* We have many components in Cogl that need to temporarily bind arbitrary + * textures e.g. to query texture object parameters and since we don't + * want that to result in too much redundant reflushing of layer state + * when all that's needed is to re-bind the layer's gl_texture we use this + * to track when the unit->gl_texture state is out of sync with the GL + * texture object really bound too (GL_TEXTURE0+unit->index). + * + * XXX: as a further optimization cogl-pipeline.c uses a convention + * of always using texture unit 1 for these transient bindings so we + * can assume this is only ever TRUE for unit 1. + */ + CoglBool dirty_gl_texture; + + /* A matrix stack giving us the means to associate a texture + * transform matrix with the texture unit. */ + CoglMatrixStack *matrix_stack; + + /* + * Higher level layer state associated with the unit... + */ + + /* The CoglPipelineLayer whos state was flushed to update this + * texture unit last. + * + * This will be set to NULL if the layer is modified or freed which + * means when we come to flush a layer; if this pointer is still + * valid and == to the layer being flushed we don't need to update + * any texture unit state. */ + CoglPipelineLayer *layer; + + /* To help minimize the state changes required we track the + * difference flags associated with the layer whos state was last + * flushed to update this texture unit. + * + * Note: we track this explicitly because .layer may get invalidated + * if that layer is modified or deleted. Even if the layer is + * invalidated though these flags can be used to optimize the state + * flush of the next layer + */ + unsigned long layer_changes_since_flush; + + /* Whenever a CoglTexture's internal GL texture storage changes + * cogl-pipeline.c is notified with a call to + * _cogl_pipeline_texture_storage_change_notify which inturn sets + * this to TRUE for each texture unit that it is currently bound + * too. When we later come to flush some pipeline state then we will + * always check this to potentially force an update of the texture + * state even if the pipeline hasn't changed. */ + CoglBool texture_storage_changed; + +} CoglTextureUnit; + +CoglTextureUnit * +_cogl_get_texture_unit (int index_); + +void +_cogl_destroy_texture_units (void); + +void +_cogl_set_active_texture_unit (int unit_index); + +void +_cogl_bind_gl_texture_transient (GLenum gl_target, + GLuint gl_texture, + CoglBool is_foreign); + +void +_cogl_delete_gl_texture (GLuint gl_texture); + +void +_cogl_pipeline_flush_gl_state (CoglContext *context, + CoglPipeline *pipeline, + CoglFramebuffer *framebuffer, + CoglBool skip_gl_state, + CoglBool unknown_color_alpha); + +#endif /* __COGL_PIPELINE_OPENGL_PRIVATE_H */ + diff --git a/cogl/cogl/driver/gl/cogl-pipeline-opengl.c b/cogl/cogl/driver/gl/cogl-pipeline-opengl.c new file mode 100644 index 0000000..1782696 --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-pipeline-opengl.c @@ -0,0 +1,1481 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#include "cogl-config.h" + +#include "cogl-debug.h" +#include "cogl-util-gl-private.h" +#include "cogl-pipeline-opengl-private.h" +#include "cogl-pipeline-private.h" +#include "cogl-context-private.h" +#include "cogl-texture-private.h" +#include "cogl-framebuffer-private.h" +#include "cogl-offscreen.h" +#include "cogl-texture-gl-private.h" + +#include "cogl-pipeline-progend-glsl-private.h" + +#include + +#include +#include + +/* + * GL/GLES compatability defines for pipeline thingies: + */ + +/* These aren't defined in the GLES headers */ +#ifndef GL_POINT_SPRITE +#define GL_POINT_SPRITE 0x8861 +#endif +#ifndef GL_COORD_REPLACE +#define GL_COORD_REPLACE 0x8862 +#endif +#ifndef GL_CLAMP_TO_BORDER +#define GL_CLAMP_TO_BORDER 0x812d +#endif +#ifndef GL_PROGRAM_POINT_SIZE +#define GL_PROGRAM_POINT_SIZE 0x8642 +#endif + +static void +texture_unit_init (CoglContext *ctx, + CoglTextureUnit *unit, + int index_) +{ + unit->index = index_; + unit->enabled_gl_target = 0; + unit->gl_texture = 0; + unit->gl_target = 0; + unit->is_foreign = FALSE; + unit->dirty_gl_texture = FALSE; + unit->matrix_stack = cogl_matrix_stack_new (ctx); + + unit->layer = NULL; + unit->layer_changes_since_flush = 0; + unit->texture_storage_changed = FALSE; +} + +static void +texture_unit_free (CoglTextureUnit *unit) +{ + if (unit->layer) + cogl_object_unref (unit->layer); + cogl_object_unref (unit->matrix_stack); +} + +CoglTextureUnit * +_cogl_get_texture_unit (int index_) +{ + _COGL_GET_CONTEXT (ctx, NULL); + + if (ctx->texture_units->len < (index_ + 1)) + { + int i; + int prev_len = ctx->texture_units->len; + ctx->texture_units = g_array_set_size (ctx->texture_units, index_ + 1); + for (i = prev_len; i <= index_; i++) + { + CoglTextureUnit *unit = + &g_array_index (ctx->texture_units, CoglTextureUnit, i); + + texture_unit_init (ctx, unit, i); + } + } + + return &g_array_index (ctx->texture_units, CoglTextureUnit, index_); +} + +void +_cogl_destroy_texture_units (void) +{ + int i; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + for (i = 0; i < ctx->texture_units->len; i++) + { + CoglTextureUnit *unit = + &g_array_index (ctx->texture_units, CoglTextureUnit, i); + texture_unit_free (unit); + } + g_array_free (ctx->texture_units, TRUE); +} + +void +_cogl_set_active_texture_unit (int unit_index) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (ctx->active_texture_unit != unit_index) + { + GE (ctx, glActiveTexture (GL_TEXTURE0 + unit_index)); + ctx->active_texture_unit = unit_index; + } +} + +/* Note: _cogl_bind_gl_texture_transient conceptually has slightly + * different semantics to OpenGL's glBindTexture because Cogl never + * cares about tracking multiple textures bound to different targets + * on the same texture unit. + * + * glBindTexture lets you bind multiple textures to a single texture + * unit if they are bound to different targets. So it does something + * like: + * unit->current_texture[target] = texture; + * + * Cogl only lets you associate one texture with the currently active + * texture unit, so the target is basically a redundant parameter + * that's implicitly set on that texture. + * + * Technically this is just a thin wrapper around glBindTexture so + * actually it does have the GL semantics but it seems worth + * mentioning the conceptual difference in case anyone wonders why we + * don't associate the gl_texture with a gl_target in the + * CoglTextureUnit. + */ +void +_cogl_bind_gl_texture_transient (GLenum gl_target, + GLuint gl_texture, + CoglBool is_foreign) +{ + CoglTextureUnit *unit; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + /* We choose to always make texture unit 1 active for transient + * binds so that in the common case where multitexturing isn't used + * we can simply ignore the state of this texture unit. Notably we + * didn't use a large texture unit (.e.g. (GL_MAX_TEXTURE_UNITS - 1) + * in case the driver doesn't have a sparse data structure for + * texture units. + */ + _cogl_set_active_texture_unit (1); + unit = _cogl_get_texture_unit (1); + + /* NB: If we have previously bound a foreign texture to this texture + * unit we don't know if that texture has since been deleted and we + * are seeing the texture name recycled */ + if (unit->gl_texture == gl_texture && + !unit->dirty_gl_texture && + !unit->is_foreign) + return; + + GE (ctx, glBindTexture (gl_target, gl_texture)); + + unit->dirty_gl_texture = TRUE; + unit->is_foreign = is_foreign; +} + +void +_cogl_delete_gl_texture (GLuint gl_texture) +{ + int i; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + for (i = 0; i < ctx->texture_units->len; i++) + { + CoglTextureUnit *unit = + &g_array_index (ctx->texture_units, CoglTextureUnit, i); + + if (unit->gl_texture == gl_texture) + { + unit->gl_texture = 0; + unit->gl_target = 0; + unit->dirty_gl_texture = FALSE; + } + } + + GE (ctx, glDeleteTextures (1, &gl_texture)); +} + +/* Whenever the underlying GL texture storage of a CoglTexture is + * changed (e.g. due to migration out of a texture atlas) then we are + * notified. This lets us ensure that we reflush that texture's state + * if it is reused again with the same texture unit. + */ +void +_cogl_pipeline_texture_storage_change_notify (CoglTexture *texture) +{ + int i; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + for (i = 0; i < ctx->texture_units->len; i++) + { + CoglTextureUnit *unit = + &g_array_index (ctx->texture_units, CoglTextureUnit, i); + + if (unit->layer && + _cogl_pipeline_layer_get_texture (unit->layer) == texture) + unit->texture_storage_changed = TRUE; + + /* NB: the texture may be bound to multiple texture units so + * we continue to check the rest */ + } +} + +static void +set_glsl_program (GLuint gl_program) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (ctx->current_gl_program != gl_program) + { + _cogl_gl_util_clear_gl_errors (ctx); + ctx->glUseProgram (gl_program); + if (_cogl_gl_util_get_error (ctx) == GL_NO_ERROR) + ctx->current_gl_program = gl_program; + else + { + GE( ctx, glUseProgram (0) ); + ctx->current_gl_program = 0; + } + } +} + +void +_cogl_use_fragment_program (GLuint gl_program, CoglPipelineProgramType type) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + /* If we're changing program type... */ + if (type != ctx->current_fragment_program_type) + { + /* ... disable the old type */ + switch (ctx->current_fragment_program_type) + { + case COGL_PIPELINE_PROGRAM_TYPE_GLSL: + /* If the program contains a vertex shader then we shouldn't + disable it */ + if (ctx->current_vertex_program_type != + COGL_PIPELINE_PROGRAM_TYPE_GLSL) + set_glsl_program (0); + break; + + case COGL_PIPELINE_PROGRAM_TYPE_ARBFP: +#ifdef HAVE_COGL_GL + GE( ctx, glDisable (GL_FRAGMENT_PROGRAM_ARB) ); +#endif + break; + + case COGL_PIPELINE_PROGRAM_TYPE_FIXED: + /* don't need to to anything */ + break; + } + + /* ... and enable the new type */ + switch (type) + { + case COGL_PIPELINE_PROGRAM_TYPE_ARBFP: +#ifdef HAVE_COGL_GL + GE( ctx, glEnable (GL_FRAGMENT_PROGRAM_ARB) ); +#endif + break; + + case COGL_PIPELINE_PROGRAM_TYPE_GLSL: + case COGL_PIPELINE_PROGRAM_TYPE_FIXED: + /* don't need to to anything */ + break; + } + } + + if (type == COGL_PIPELINE_PROGRAM_TYPE_GLSL) + { +#ifdef COGL_PIPELINE_FRAGEND_GLSL + set_glsl_program (gl_program); + +#else + + g_warning ("Unexpected use of GLSL fragend!"); + +#endif /* COGL_PIPELINE_FRAGEND_GLSL */ + } +#ifndef COGL_PIPELINE_FRAGEND_ARBFP + else if (type == COGL_PIPELINE_PROGRAM_TYPE_ARBFP) + g_warning ("Unexpected use of ARBFP fragend!"); +#endif /* COGL_PIPELINE_FRAGEND_ARBFP */ + + ctx->current_fragment_program_type = type; +} + +void +_cogl_use_vertex_program (GLuint gl_program, CoglPipelineProgramType type) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + /* If we're changing program type... */ + if (type != ctx->current_vertex_program_type) + { + /* ... disable the old type */ + switch (ctx->current_vertex_program_type) + { + case COGL_PIPELINE_PROGRAM_TYPE_GLSL: + /* If the program contains a fragment shader then we shouldn't + disable it */ + if (ctx->current_fragment_program_type != + COGL_PIPELINE_PROGRAM_TYPE_GLSL) + set_glsl_program (0); + break; + + case COGL_PIPELINE_PROGRAM_TYPE_ARBFP: + /* It doesn't make sense to enable ARBfp for the vertex program */ + g_assert_not_reached (); + break; + + case COGL_PIPELINE_PROGRAM_TYPE_FIXED: + /* don't need to to anything */ + break; + } + + /* ... and enable the new type */ + switch (type) + { + case COGL_PIPELINE_PROGRAM_TYPE_ARBFP: + /* It doesn't make sense to enable ARBfp for the vertex program */ + g_assert_not_reached (); + break; + + case COGL_PIPELINE_PROGRAM_TYPE_GLSL: + case COGL_PIPELINE_PROGRAM_TYPE_FIXED: + /* don't need to to anything */ + break; + } + } + + if (type == COGL_PIPELINE_PROGRAM_TYPE_GLSL) + { +#ifdef COGL_PIPELINE_VERTEND_GLSL + set_glsl_program (gl_program); + +#else + + g_warning ("Unexpected use of GLSL vertend!"); + +#endif /* COGL_PIPELINE_VERTEND_GLSL */ + } +#ifndef COGL_PIPELINE_VERTEND_ARBFP + else if (type == COGL_PIPELINE_PROGRAM_TYPE_ARBFP) + g_warning ("Unexpected use of ARBFP vertend!"); +#endif /* COGL_PIPELINE_VERTEND_ARBFP */ + + ctx->current_vertex_program_type = type; +} + +#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL) + +static CoglBool +blend_factor_uses_constant (GLenum blend_factor) +{ + return (blend_factor == GL_CONSTANT_COLOR || + blend_factor == GL_ONE_MINUS_CONSTANT_COLOR || + blend_factor == GL_CONSTANT_ALPHA || + blend_factor == GL_ONE_MINUS_CONSTANT_ALPHA); +} + +#endif + +static void +flush_depth_state (CoglContext *ctx, + CoglDepthState *depth_state) +{ + CoglBool depth_writing_enabled = depth_state->write_enabled; + + if (ctx->current_draw_buffer) + depth_writing_enabled &= ctx->current_draw_buffer->depth_writing_enabled; + + if (ctx->depth_test_enabled_cache != depth_state->test_enabled) + { + if (depth_state->test_enabled == TRUE) + GE (ctx, glEnable (GL_DEPTH_TEST)); + else + GE (ctx, glDisable (GL_DEPTH_TEST)); + ctx->depth_test_enabled_cache = depth_state->test_enabled; + } + + if (ctx->depth_test_function_cache != depth_state->test_function && + depth_state->test_enabled == TRUE) + { + GE (ctx, glDepthFunc (depth_state->test_function)); + ctx->depth_test_function_cache = depth_state->test_function; + } + + if (ctx->depth_writing_enabled_cache != depth_writing_enabled) + { + GE (ctx, glDepthMask (depth_writing_enabled ? + GL_TRUE : GL_FALSE)); + ctx->depth_writing_enabled_cache = depth_writing_enabled; + } + + if (ctx->driver != COGL_DRIVER_GLES1 && + (ctx->depth_range_near_cache != depth_state->range_near || + ctx->depth_range_far_cache != depth_state->range_far)) + { + if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_GL_EMBEDDED)) + GE (ctx, glDepthRangef (depth_state->range_near, + depth_state->range_far)); + else + GE (ctx, glDepthRange (depth_state->range_near, + depth_state->range_far)); + + ctx->depth_range_near_cache = depth_state->range_near; + ctx->depth_range_far_cache = depth_state->range_far; + } +} + +UNIT_TEST (check_gl_blend_enable, + 0 /* no requirements */, + 0 /* no failure cases */) +{ + CoglPipeline *pipeline = cogl_pipeline_new (test_ctx); + + /* By default blending should be disabled */ + g_assert_cmpint (test_ctx->gl_blend_enable_cache, ==, 0); + + cogl_framebuffer_draw_rectangle (test_fb, pipeline, 0, 0, 1, 1); + _cogl_framebuffer_flush_journal (test_fb); + + /* After drawing an opaque rectangle blending should still be + * disabled */ + g_assert_cmpint (test_ctx->gl_blend_enable_cache, ==, 0); + + cogl_pipeline_set_color4f (pipeline, 0, 0, 0, 0); + cogl_framebuffer_draw_rectangle (test_fb, pipeline, 0, 0, 1, 1); + _cogl_framebuffer_flush_journal (test_fb); + + /* After drawing a transparent rectangle blending should be enabled */ + g_assert_cmpint (test_ctx->gl_blend_enable_cache, ==, 1); + + cogl_pipeline_set_blend (pipeline, "RGBA=ADD(SRC_COLOR, 0)", NULL); + cogl_framebuffer_draw_rectangle (test_fb, pipeline, 0, 0, 1, 1); + _cogl_framebuffer_flush_journal (test_fb); + + /* After setting a blend string that effectively disables blending + * then blending should be disabled */ + g_assert_cmpint (test_ctx->gl_blend_enable_cache, ==, 0); +} + +static void +_cogl_pipeline_flush_color_blend_alpha_depth_state ( + CoglPipeline *pipeline, + unsigned long pipelines_difference, + CoglBool with_color_attrib) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + /* On GLES2 we'll flush the color later */ + if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_GL_FIXED) && + !with_color_attrib) + { + if ((pipelines_difference & COGL_PIPELINE_STATE_COLOR) || + /* Assume if we were previously told to skip the color, then + * the current color needs updating... */ + ctx->current_pipeline_with_color_attrib) + { + CoglPipeline *authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_COLOR); + GE (ctx, glColor4ub (cogl_color_get_red_byte (&authority->color), + cogl_color_get_green_byte (&authority->color), + cogl_color_get_blue_byte (&authority->color), + cogl_color_get_alpha_byte (&authority->color))); + } + } + + if (pipelines_difference & COGL_PIPELINE_STATE_BLEND) + { + CoglPipeline *authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_BLEND); + CoglPipelineBlendState *blend_state = + &authority->big_state->blend_state; + + /* GLES 1 only has glBlendFunc */ + if (ctx->driver == COGL_DRIVER_GLES1) + { + GE (ctx, glBlendFunc (blend_state->blend_src_factor_rgb, + blend_state->blend_dst_factor_rgb)); + } +#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL) + else + { + if (blend_factor_uses_constant (blend_state->blend_src_factor_rgb) || + blend_factor_uses_constant (blend_state + ->blend_src_factor_alpha) || + blend_factor_uses_constant (blend_state->blend_dst_factor_rgb) || + blend_factor_uses_constant (blend_state->blend_dst_factor_alpha)) + { + float red = + cogl_color_get_red_float (&blend_state->blend_constant); + float green = + cogl_color_get_green_float (&blend_state->blend_constant); + float blue = + cogl_color_get_blue_float (&blend_state->blend_constant); + float alpha = + cogl_color_get_alpha_float (&blend_state->blend_constant); + + + GE (ctx, glBlendColor (red, green, blue, alpha)); + } + + if (ctx->glBlendEquationSeparate && + blend_state->blend_equation_rgb != + blend_state->blend_equation_alpha) + GE (ctx, + glBlendEquationSeparate (blend_state->blend_equation_rgb, + blend_state->blend_equation_alpha)); + else + GE (ctx, glBlendEquation (blend_state->blend_equation_rgb)); + + if (ctx->glBlendFuncSeparate && + (blend_state->blend_src_factor_rgb != + blend_state->blend_src_factor_alpha || + (blend_state->blend_dst_factor_rgb != + blend_state->blend_dst_factor_alpha))) + GE (ctx, glBlendFuncSeparate (blend_state->blend_src_factor_rgb, + blend_state->blend_dst_factor_rgb, + blend_state->blend_src_factor_alpha, + blend_state->blend_dst_factor_alpha)); + else + GE (ctx, glBlendFunc (blend_state->blend_src_factor_rgb, + blend_state->blend_dst_factor_rgb)); + } +#endif + } + +#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) + + if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_ALPHA_TEST)) + { + /* Under GLES2 the alpha function is implemented as part of the + fragment shader */ + if (pipelines_difference & (COGL_PIPELINE_STATE_ALPHA_FUNC | + COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE)) + { + CoglPipeline *authority = + _cogl_pipeline_get_authority (pipeline, + COGL_PIPELINE_STATE_ALPHA_FUNC); + CoglPipelineAlphaFuncState *alpha_state = + &authority->big_state->alpha_state; + + /* NB: Currently the Cogl defines are compatible with the GL ones: */ + GE (ctx, glAlphaFunc (alpha_state->alpha_func, + alpha_state->alpha_func_reference)); + } + + /* Under GLES2 the lighting parameters are implemented as uniforms + in the progend */ + if (pipelines_difference & COGL_PIPELINE_STATE_LIGHTING) + { + CoglPipeline *authority = + _cogl_pipeline_get_authority (pipeline, + COGL_PIPELINE_STATE_LIGHTING); + CoglPipelineLightingState *lighting_state = + &authority->big_state->lighting_state; + + GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, + lighting_state->ambient)); + GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, + lighting_state->diffuse)); + GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, + lighting_state->specular)); + GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION, + lighting_state->emission)); + GE (ctx, glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, + &lighting_state->shininess)); + } + } + +#endif + + if (pipelines_difference & COGL_PIPELINE_STATE_DEPTH) + { + CoglPipeline *authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_DEPTH); + CoglDepthState *depth_state = &authority->big_state->depth_state; + + flush_depth_state (ctx, depth_state); + } + + if (pipelines_difference & COGL_PIPELINE_STATE_LOGIC_OPS) + { + CoglPipeline *authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LOGIC_OPS); + CoglPipelineLogicOpsState *logic_ops_state = &authority->big_state->logic_ops_state; + CoglColorMask color_mask = logic_ops_state->color_mask; + + if (ctx->current_draw_buffer) + color_mask &= ctx->current_draw_buffer->color_mask; + + GE (ctx, glColorMask (!!(color_mask & COGL_COLOR_MASK_RED), + !!(color_mask & COGL_COLOR_MASK_GREEN), + !!(color_mask & COGL_COLOR_MASK_BLUE), + !!(color_mask & COGL_COLOR_MASK_ALPHA))); + ctx->current_gl_color_mask = color_mask; + } + + if (pipelines_difference & COGL_PIPELINE_STATE_CULL_FACE) + { + CoglPipeline *authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_CULL_FACE); + CoglPipelineCullFaceState *cull_face_state + = &authority->big_state->cull_face_state; + + if (cull_face_state->mode == COGL_PIPELINE_CULL_FACE_MODE_NONE) + GE( ctx, glDisable (GL_CULL_FACE) ); + else + { + CoglBool invert_winding; + + GE( ctx, glEnable (GL_CULL_FACE) ); + + switch (cull_face_state->mode) + { + case COGL_PIPELINE_CULL_FACE_MODE_NONE: + g_assert_not_reached (); + + case COGL_PIPELINE_CULL_FACE_MODE_FRONT: + GE( ctx, glCullFace (GL_FRONT) ); + break; + + case COGL_PIPELINE_CULL_FACE_MODE_BACK: + GE( ctx, glCullFace (GL_BACK) ); + break; + + case COGL_PIPELINE_CULL_FACE_MODE_BOTH: + GE( ctx, glCullFace (GL_FRONT_AND_BACK) ); + break; + } + + /* If we are painting to an offscreen framebuffer then we + need to invert the winding of the front face because + everything is painted upside down */ + invert_winding = cogl_is_offscreen (ctx->current_draw_buffer); + + switch (cull_face_state->front_winding) + { + case COGL_WINDING_CLOCKWISE: + GE( ctx, glFrontFace (invert_winding ? GL_CCW : GL_CW) ); + break; + + case COGL_WINDING_COUNTER_CLOCKWISE: + GE( ctx, glFrontFace (invert_winding ? GL_CW : GL_CCW) ); + break; + } + } + } + +#ifdef HAVE_COGL_GL + if (_cogl_has_private_feature + (ctx, COGL_PRIVATE_FEATURE_ENABLE_PROGRAM_POINT_SIZE) && + (pipelines_difference & COGL_PIPELINE_STATE_PER_VERTEX_POINT_SIZE)) + { + unsigned long state = COGL_PIPELINE_STATE_PER_VERTEX_POINT_SIZE; + CoglPipeline *authority = _cogl_pipeline_get_authority (pipeline, state); + + if (authority->big_state->per_vertex_point_size) + GE( ctx, glEnable (GL_PROGRAM_POINT_SIZE) ); + else + GE( ctx, glDisable (GL_PROGRAM_POINT_SIZE) ); + } +#endif + + if (pipeline->real_blend_enable != ctx->gl_blend_enable_cache) + { + if (pipeline->real_blend_enable) + GE (ctx, glEnable (GL_BLEND)); + else + GE (ctx, glDisable (GL_BLEND)); + /* XXX: we shouldn't update any other blend state if blending + * is disabled! */ + ctx->gl_blend_enable_cache = pipeline->real_blend_enable; + } +} + +static int +get_max_activateable_texture_units (void) +{ + _COGL_GET_CONTEXT (ctx, 0); + + if (G_UNLIKELY (ctx->max_activateable_texture_units == -1)) + { + GLint values[3]; + int n_values = 0; + int i; + +#ifdef HAVE_COGL_GL + if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_GL_EMBEDDED)) + { + /* GL_MAX_TEXTURE_COORDS is provided for both GLSL and ARBfp. It + defines the number of texture coordinates that can be + uploaded (but doesn't necessarily relate to how many texture + images can be sampled) */ + if (cogl_has_feature (ctx, COGL_FEATURE_ID_GLSL) || + cogl_has_feature (ctx, COGL_FEATURE_ID_ARBFP)) + /* Previously this code subtracted the value by one but there + was no explanation for why it did this and it doesn't seem + to make sense so it has been removed */ + GE (ctx, glGetIntegerv (GL_MAX_TEXTURE_COORDS, + values + n_values++)); + + /* GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS is defined for GLSL but + not ARBfp */ + if (cogl_has_feature (ctx, COGL_FEATURE_ID_GLSL)) + GE (ctx, glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, + values + n_values++)); + } +#endif /* HAVE_COGL_GL */ + +#ifdef HAVE_COGL_GLES2 + if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_GL_EMBEDDED) && + _cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_GL_PROGRAMMABLE)) + { + GE (ctx, glGetIntegerv (GL_MAX_VERTEX_ATTRIBS, values + n_values)); + /* Two of the vertex attribs need to be used for the position + and color */ + values[n_values++] -= 2; + + GE (ctx, glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, + values + n_values++)); + } +#endif + +#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) + if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_GL_FIXED)) + { + /* GL_MAX_TEXTURE_UNITS defines the number of units that are + usable from the fixed function pipeline, therefore it isn't + available in GLES2. These are also tied to the number of + texture coordinates that can be uploaded so it should be less + than that available from the shader extensions */ + GE (ctx, glGetIntegerv (GL_MAX_TEXTURE_UNITS, + values + n_values++)); + + } +#endif + + g_assert (n_values <= G_N_ELEMENTS (values) && + n_values > 0); + + /* Use the maximum value */ + ctx->max_activateable_texture_units = values[0]; + for (i = 1; i < n_values; i++) + ctx->max_activateable_texture_units = + MAX (values[i], ctx->max_activateable_texture_units); + } + + return ctx->max_activateable_texture_units; +} + +typedef struct +{ + int i; + unsigned long *layer_differences; +} CoglPipelineFlushLayerState; + +static CoglBool +flush_layers_common_gl_state_cb (CoglPipelineLayer *layer, void *user_data) +{ + CoglPipelineFlushLayerState *flush_state = user_data; + int unit_index = flush_state->i; + CoglTextureUnit *unit = _cogl_get_texture_unit (unit_index); + unsigned long layers_difference = + flush_state->layer_differences[unit_index]; + + _COGL_GET_CONTEXT (ctx, FALSE); + + /* There may not be enough texture units so we can bail out if + * that's the case... + */ + if (G_UNLIKELY (unit_index >= get_max_activateable_texture_units ())) + { + static CoglBool shown_warning = FALSE; + + if (!shown_warning) + { + g_warning ("Your hardware does not have enough texture units" + "to handle this many texture layers"); + shown_warning = TRUE; + } + return FALSE; + } + + if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA) + { + CoglTexture *texture = _cogl_pipeline_layer_get_texture_real (layer); + GLuint gl_texture; + GLenum gl_target; + + if (texture == NULL) + switch (_cogl_pipeline_layer_get_texture_type (layer)) + { + case COGL_TEXTURE_TYPE_2D: + texture = COGL_TEXTURE (ctx->default_gl_texture_2d_tex); + break; + case COGL_TEXTURE_TYPE_3D: + texture = COGL_TEXTURE (ctx->default_gl_texture_3d_tex); + break; + case COGL_TEXTURE_TYPE_RECTANGLE: + texture = COGL_TEXTURE (ctx->default_gl_texture_rect_tex); + break; + } + + cogl_texture_get_gl_texture (texture, + &gl_texture, + &gl_target); + + _cogl_set_active_texture_unit (unit_index); + + /* NB: There are several Cogl components and some code in + * Clutter that will temporarily bind arbitrary GL textures to + * query and modify texture object parameters. If you look at + * _cogl_bind_gl_texture_transient() you can see we make sure + * that such code always binds to texture unit 1 which means we + * can't rely on the unit->gl_texture state if unit->index == 1. + * + * Because texture unit 1 is a bit special we actually defer any + * necessary glBindTexture for it until the end of + * _cogl_pipeline_flush_gl_state(). + * + * NB: we get notified whenever glDeleteTextures is used (see + * _cogl_delete_gl_texture()) where we invalidate + * unit->gl_texture references to deleted textures so it's safe + * to compare unit->gl_texture with gl_texture. (Without the + * hook it would be possible to delete a GL texture and create a + * new one with the same name and comparing unit->gl_texture and + * gl_texture wouldn't detect that.) + * + * NB: for foreign textures we don't know how the deletion of + * the GL texture objects correspond to the deletion of the + * CoglTextures so if there was previously a foreign texture + * associated with the texture unit then we can't assume that we + * aren't seeing a recycled texture name so we have to bind. + */ + if (unit->gl_texture != gl_texture || unit->is_foreign) + { + if (unit_index == 1) + unit->dirty_gl_texture = TRUE; + else + GE (ctx, glBindTexture (gl_target, gl_texture)); + unit->gl_texture = gl_texture; + unit->gl_target = gl_target; + } + + unit->is_foreign = _cogl_texture_is_foreign (texture); + + /* The texture_storage_changed boolean indicates if the + * CoglTexture's underlying GL texture storage has changed since + * it was flushed to the texture unit. We've just flushed the + * latest state so we can reset this. */ + unit->texture_storage_changed = FALSE; + } + + if ((layers_difference & COGL_PIPELINE_LAYER_STATE_SAMPLER) && + _cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_SAMPLER_OBJECTS)) + { + const CoglSamplerCacheEntry *sampler_state; + + sampler_state = _cogl_pipeline_layer_get_sampler_state (layer); + + GE( ctx, glBindSampler (unit_index, sampler_state->sampler_object) ); + } + + /* FIXME: If using GLSL the progend we will use gl_PointCoord + * instead of us needing to replace the texture coordinates but at + * this point we can't currently tell if we are using the fixed or + * glsl progend. + */ +#if defined (HAVE_COGL_GLES) || defined (HAVE_COGL_GL) + if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_GL_FIXED) && + (layers_difference & COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS)) + { + CoglPipelineState change = COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS; + CoglPipelineLayer *authority = + _cogl_pipeline_layer_get_authority (layer, change); + CoglPipelineLayerBigState *big_state = authority->big_state; + + _cogl_set_active_texture_unit (unit_index); + + GE (ctx, glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE, + big_state->point_sprite_coords)); + } +#endif + + cogl_object_ref (layer); + if (unit->layer != NULL) + cogl_object_unref (unit->layer); + + unit->layer = layer; + unit->layer_changes_since_flush = 0; + + flush_state->i++; + + return TRUE; +} + +static void +_cogl_pipeline_flush_common_gl_state (CoglPipeline *pipeline, + unsigned long pipelines_difference, + unsigned long *layer_differences, + CoglBool with_color_attrib) +{ + CoglPipelineFlushLayerState state; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + _cogl_pipeline_flush_color_blend_alpha_depth_state (pipeline, + pipelines_difference, + with_color_attrib); + + state.i = 0; + state.layer_differences = layer_differences; + _cogl_pipeline_foreach_layer_internal (pipeline, + flush_layers_common_gl_state_cb, + &state); +} + +/* Re-assert the layer's wrap modes on the given CoglTexture. + * + * Note: we don't simply forward the wrap modes to layer->texture + * since the actual texture being used may have been overridden. + */ +static void +_cogl_pipeline_layer_forward_wrap_modes (CoglPipelineLayer *layer, + CoglTexture *texture) +{ + CoglSamplerCacheWrapMode wrap_mode_s, wrap_mode_t, wrap_mode_p; + GLenum gl_wrap_mode_s, gl_wrap_mode_t, gl_wrap_mode_p; + + if (texture == NULL) + return; + + _cogl_pipeline_layer_get_wrap_modes (layer, + &wrap_mode_s, + &wrap_mode_t, + &wrap_mode_p); + + /* Update the wrap mode on the texture object. The texture backend + should cache the value so that it will be a no-op if the object + already has the same wrap mode set. The backend is best placed to + do this because it knows how many of the coordinates will + actually be used (ie, a 1D texture only cares about the 's' + coordinate but a 3D texture would use all three). GL uses the + wrap mode as part of the texture object state but we are + pretending it's part of the per-layer environment state. This + will break if the application tries to use different modes in + different layers using the same texture. */ + + if (wrap_mode_s == COGL_SAMPLER_CACHE_WRAP_MODE_AUTOMATIC) + gl_wrap_mode_s = GL_CLAMP_TO_EDGE; + else + gl_wrap_mode_s = wrap_mode_s; + + if (wrap_mode_t == COGL_SAMPLER_CACHE_WRAP_MODE_AUTOMATIC) + gl_wrap_mode_t = GL_CLAMP_TO_EDGE; + else + gl_wrap_mode_t = wrap_mode_t; + + if (wrap_mode_p == COGL_SAMPLER_CACHE_WRAP_MODE_AUTOMATIC) + gl_wrap_mode_p = GL_CLAMP_TO_EDGE; + else + gl_wrap_mode_p = wrap_mode_p; + + _cogl_texture_gl_flush_legacy_texobj_wrap_modes (texture, + gl_wrap_mode_s, + gl_wrap_mode_t, + gl_wrap_mode_p); +} + +/* OpenGL associates the min/mag filters and repeat modes with the + * texture object not the texture unit so we always have to re-assert + * the filter and repeat modes whenever we use a texture since it may + * be referenced by multiple pipelines with different modes. + * + * This function is bypassed in favour of sampler objects if + * GL_ARB_sampler_objects is advertised. This fallback won't work if + * the same texture is bound to multiple layers with different sampler + * state. + */ +static void +foreach_texture_unit_update_filter_and_wrap_modes (void) +{ + int i; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + for (i = 0; i < ctx->texture_units->len; i++) + { + CoglTextureUnit *unit = + &g_array_index (ctx->texture_units, CoglTextureUnit, i); + + if (unit->layer) + { + CoglTexture *texture = _cogl_pipeline_layer_get_texture (unit->layer); + + if (texture != NULL) + { + CoglPipelineFilter min; + CoglPipelineFilter mag; + + _cogl_pipeline_layer_get_filters (unit->layer, &min, &mag); + _cogl_texture_gl_flush_legacy_texobj_filters (texture, min, mag); + + _cogl_pipeline_layer_forward_wrap_modes (unit->layer, texture); + } + } + } +} + +typedef struct +{ + int i; + unsigned long *layer_differences; +} CoglPipelineCompareLayersState; + +static CoglBool +compare_layer_differences_cb (CoglPipelineLayer *layer, void *user_data) +{ + CoglPipelineCompareLayersState *state = user_data; + CoglTextureUnit *unit = _cogl_get_texture_unit (state->i); + + if (unit->layer == layer) + state->layer_differences[state->i] = unit->layer_changes_since_flush; + else if (unit->layer) + { + state->layer_differences[state->i] = unit->layer_changes_since_flush; + state->layer_differences[state->i] |= + _cogl_pipeline_layer_compare_differences (layer, unit->layer); + } + else + state->layer_differences[state->i] = COGL_PIPELINE_LAYER_STATE_ALL_SPARSE; + + /* XXX: There is always a possibility that a CoglTexture's + * underlying GL texture storage has been changed since it was last + * bound to a texture unit which is why we have a callback into + * _cogl_pipeline_texture_storage_change_notify whenever a textures + * underlying GL texture storage changes which will set the + * unit->texture_intern_changed flag. If we see that's been set here + * then we force an update of the texture state... + */ + if (unit->texture_storage_changed) + state->layer_differences[state->i] |= + COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA; + + state->i++; + + return TRUE; +} + +typedef struct +{ + CoglFramebuffer *framebuffer; + const CoglPipelineVertend *vertend; + const CoglPipelineFragend *fragend; + CoglPipeline *pipeline; + unsigned long *layer_differences; + CoglBool error_adding_layer; + CoglBool added_layer; +} CoglPipelineAddLayerState; + +static CoglBool +vertend_add_layer_cb (CoglPipelineLayer *layer, + void *user_data) +{ + CoglPipelineAddLayerState *state = user_data; + const CoglPipelineVertend *vertend = state->vertend; + CoglPipeline *pipeline = state->pipeline; + int unit_index = _cogl_pipeline_layer_get_unit_index (layer); + + /* Either generate per layer code snippets or setup the + * fixed function glTexEnv for each layer... */ + if (G_LIKELY (vertend->add_layer (pipeline, + layer, + state->layer_differences[unit_index], + state->framebuffer))) + state->added_layer = TRUE; + else + { + state->error_adding_layer = TRUE; + return FALSE; + } + + return TRUE; +} + +static CoglBool +fragend_add_layer_cb (CoglPipelineLayer *layer, + void *user_data) +{ + CoglPipelineAddLayerState *state = user_data; + const CoglPipelineFragend *fragend = state->fragend; + CoglPipeline *pipeline = state->pipeline; + int unit_index = _cogl_pipeline_layer_get_unit_index (layer); + + /* Either generate per layer code snippets or setup the + * fixed function glTexEnv for each layer... */ + if (G_LIKELY (fragend->add_layer (pipeline, + layer, + state->layer_differences[unit_index]))) + state->added_layer = TRUE; + else + { + state->error_adding_layer = TRUE; + return FALSE; + } + + return TRUE; +} + +/* + * _cogl_pipeline_flush_gl_state: + * + * Details of override options: + * ->fallback_mask: is a bitmask of the pipeline layers that need to be + * replaced with the default, fallback textures. The fallback textures are + * fully transparent textures so they hopefully wont contribute to the + * texture combining. + * + * The intention of fallbacks is to try and preserve + * the number of layers the user is expecting so that texture coordinates + * they gave will mostly still correspond to the textures they intended, and + * have a fighting chance of looking close to their originally intended + * result. + * + * ->disable_mask: is a bitmask of the pipeline layers that will simply have + * texturing disabled. It's only really intended for disabling all layers + * > X; i.e. we'd expect to see a contiguous run of 0 starting from the LSB + * and at some point the remaining bits flip to 1. It might work to disable + * arbitrary layers; though I'm not sure a.t.m how OpenGL would take to + * that. + * + * The intention of the disable_mask is for emitting geometry when the user + * hasn't supplied enough texture coordinates for all the layers and it's + * not possible to auto generate default texture coordinates for those + * layers. + * + * ->layer0_override_texture: forcibly tells us to bind this GL texture name for + * layer 0 instead of plucking the gl_texture from the CoglTexture of layer + * 0. + * + * The intention of this is for any primitives that supports sliced textures. + * The code will can iterate each of the slices and re-flush the pipeline + * forcing the GL texture of each slice in turn. + * + * ->wrap_mode_overrides: overrides the wrap modes set on each + * layer. This is used to implement the automatic wrap mode. + * + * XXX: It might also help if we could specify a texture matrix for code + * dealing with slicing that would be multiplied with the users own matrix. + * + * Normaly texture coords in the range [0, 1] refer to the extents of the + * texture, but when your GL texture represents a slice of the real texture + * (from the users POV) then a texture matrix would be a neat way of + * transforming the mapping for each slice. + * + * Currently for textured rectangles we manually calculate the texture + * coords for each slice based on the users given coords, but this solution + * isn't ideal, and can't be used with CoglVertexBuffers. + */ +void +_cogl_pipeline_flush_gl_state (CoglContext *ctx, + CoglPipeline *pipeline, + CoglFramebuffer *framebuffer, + CoglBool with_color_attrib, + CoglBool unknown_color_alpha) +{ + CoglPipeline *current_pipeline = ctx->current_pipeline; + unsigned long pipelines_difference; + int n_layers; + unsigned long *layer_differences; + int i; + CoglTextureUnit *unit1; + const CoglPipelineProgend *progend; + + COGL_STATIC_TIMER (pipeline_flush_timer, + "Mainloop", /* parent */ + "Material Flush", + "The time spent flushing material state", + 0 /* no application private data */); + + COGL_TIMER_START (_cogl_uprof_context, pipeline_flush_timer); + + /* Bail out asap if we've been asked to re-flush the already current + * pipeline and we can see the pipeline hasn't changed */ + if (current_pipeline == pipeline && + ctx->current_pipeline_age == pipeline->age && + ctx->current_pipeline_with_color_attrib == with_color_attrib && + ctx->current_pipeline_unknown_color_alpha == unknown_color_alpha) + goto done; + else + { + /* Update derived state (currently just the 'real_blend_enable' + * state) and determine a mask of state that differs between the + * current pipeline and the one we are flushing. + * + * Note updating the derived state is done before doing any + * pipeline comparisons so that we can correctly compare the + * 'real_blend_enable' state itself. + */ + + if (current_pipeline == pipeline) + { + pipelines_difference = ctx->current_pipeline_changes_since_flush; + + if (pipelines_difference & COGL_PIPELINE_STATE_AFFECTS_BLENDING || + pipeline->unknown_color_alpha != unknown_color_alpha) + { + CoglBool save_real_blend_enable = pipeline->real_blend_enable; + + _cogl_pipeline_update_real_blend_enable (pipeline, + unknown_color_alpha); + + if (save_real_blend_enable != pipeline->real_blend_enable) + pipelines_difference |= COGL_PIPELINE_STATE_REAL_BLEND_ENABLE; + } + } + else if (current_pipeline) + { + pipelines_difference = ctx->current_pipeline_changes_since_flush; + + _cogl_pipeline_update_real_blend_enable (pipeline, + unknown_color_alpha); + + pipelines_difference |= + _cogl_pipeline_compare_differences (ctx->current_pipeline, + pipeline); + } + else + { + _cogl_pipeline_update_real_blend_enable (pipeline, + unknown_color_alpha); + + pipelines_difference = COGL_PIPELINE_STATE_ALL; + } + } + + /* Get a layer_differences mask for each layer to be flushed */ + n_layers = cogl_pipeline_get_n_layers (pipeline); + if (n_layers) + { + CoglPipelineCompareLayersState state; + layer_differences = g_alloca (sizeof (unsigned long) * n_layers); + memset (layer_differences, 0, sizeof (unsigned long) * n_layers); + state.i = 0; + state.layer_differences = layer_differences; + _cogl_pipeline_foreach_layer_internal (pipeline, + compare_layer_differences_cb, + &state); + } + else + layer_differences = NULL; + + /* First flush everything that's the same regardless of which + * pipeline backend is being used... + * + * 1) top level state: + * glColor (or skip if a vertex attribute is being used for color) + * blend state + * alpha test state (except for GLES 2.0) + * + * 2) then foreach layer: + * determine gl_target/gl_texture + * bind texture + * + * Note: After _cogl_pipeline_flush_common_gl_state you can expect + * all state of the layers corresponding texture unit to be + * updated. + */ + _cogl_pipeline_flush_common_gl_state (pipeline, + pipelines_difference, + layer_differences, + with_color_attrib); + + /* Now flush the fragment, vertex and program state according to the + * current progend backend. + * + * Note: Some backends may not support the current pipeline + * configuration and in that case it will report and error and we + * will look for a different backend. + * + * NB: if pipeline->progend != COGL_PIPELINE_PROGEND_UNDEFINED then + * we have previously managed to successfully flush this pipeline + * with the given progend so we will simply use that to avoid + * fallback code paths. + */ + if (pipeline->progend == COGL_PIPELINE_PROGEND_UNDEFINED) + _cogl_pipeline_set_progend (pipeline, COGL_PIPELINE_PROGEND_DEFAULT); + + for (i = pipeline->progend; + i < COGL_PIPELINE_N_PROGENDS; + i++, _cogl_pipeline_set_progend (pipeline, i)) + { + const CoglPipelineVertend *vertend; + const CoglPipelineFragend *fragend; + CoglPipelineAddLayerState state; + + progend = _cogl_pipeline_progends[i]; + + if (G_UNLIKELY (!progend->start (pipeline))) + continue; + + vertend = _cogl_pipeline_vertends[progend->vertend]; + + vertend->start (pipeline, + n_layers, + pipelines_difference); + + state.framebuffer = framebuffer; + state.vertend = vertend; + state.pipeline = pipeline; + state.layer_differences = layer_differences; + state.error_adding_layer = FALSE; + state.added_layer = FALSE; + + _cogl_pipeline_foreach_layer_internal (pipeline, + vertend_add_layer_cb, + &state); + + if (G_UNLIKELY (state.error_adding_layer)) + continue; + + if (G_UNLIKELY (!vertend->end (pipeline, pipelines_difference))) + continue; + + /* Now prepare the fragment processing state (fragend) + * + * NB: We can't combine the setup of the vertend and fragend + * since the backends that do code generation share + * ctx->codegen_source_buffer as a scratch buffer. + */ + + fragend = _cogl_pipeline_fragends[progend->fragend]; + state.fragend = fragend; + + fragend->start (pipeline, + n_layers, + pipelines_difference); + + _cogl_pipeline_foreach_layer_internal (pipeline, + fragend_add_layer_cb, + &state); + + if (G_UNLIKELY (state.error_adding_layer)) + continue; + + if (!state.added_layer) + { + if (fragend->passthrough && + G_UNLIKELY (!fragend->passthrough (pipeline))) + continue; + } + + if (G_UNLIKELY (!fragend->end (pipeline, pipelines_difference))) + continue; + + if (progend->end) + progend->end (pipeline, pipelines_difference); + break; + } + + /* FIXME: This reference is actually resulting in lots of + * copy-on-write reparenting because one-shot pipelines end up + * living for longer than necessary and so any later modification of + * the parent will cause a copy-on-write. + * + * XXX: The issue should largely go away when we switch to using + * weak pipelines for overrides. + */ + cogl_object_ref (pipeline); + if (ctx->current_pipeline != NULL) + cogl_object_unref (ctx->current_pipeline); + ctx->current_pipeline = pipeline; + ctx->current_pipeline_changes_since_flush = 0; + ctx->current_pipeline_with_color_attrib = with_color_attrib; + ctx->current_pipeline_unknown_color_alpha = unknown_color_alpha; + ctx->current_pipeline_age = pipeline->age; + +done: + + progend = _cogl_pipeline_progends[pipeline->progend]; + + /* We can't assume the color will be retained between flushes when + * using the glsl progend because the generic attribute values are + * not stored as part of the program object so they could be + * overridden by any attribute changes in another program */ + if (pipeline->progend == COGL_PIPELINE_PROGEND_GLSL && !with_color_attrib) + { + int attribute; + CoglPipeline *authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_COLOR); + int name_index = COGL_ATTRIBUTE_COLOR_NAME_INDEX; + + attribute = + _cogl_pipeline_progend_glsl_get_attrib_location (pipeline, name_index); + if (attribute != -1) + GE (ctx, + glVertexAttrib4f (attribute, + cogl_color_get_red_float (&authority->color), + cogl_color_get_green_float (&authority->color), + cogl_color_get_blue_float (&authority->color), + cogl_color_get_alpha_float (&authority->color))); + } + + /* Give the progend a chance to update any uniforms that might not + * depend on the material state. This is used on GLES2 to update the + * matrices */ + if (progend->pre_paint) + progend->pre_paint (pipeline, framebuffer); + + /* Handle the fact that OpenGL associates texture filter and wrap + * modes with the texture objects not the texture units... */ + if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_SAMPLER_OBJECTS)) + foreach_texture_unit_update_filter_and_wrap_modes (); + + /* If this pipeline has more than one layer then we always need + * to make sure we rebind the texture for unit 1. + * + * NB: various components of Cogl may temporarily bind arbitrary + * textures to texture unit 1 so they can query and modify texture + * object parameters. cogl-pipeline.c (See + * _cogl_bind_gl_texture_transient) + */ + unit1 = _cogl_get_texture_unit (1); + if (cogl_pipeline_get_n_layers (pipeline) > 1 && unit1->dirty_gl_texture) + { + _cogl_set_active_texture_unit (1); + GE (ctx, glBindTexture (unit1->gl_target, unit1->gl_texture)); + unit1->dirty_gl_texture = FALSE; + } + + COGL_TIMER_STOP (_cogl_uprof_context, pipeline_flush_timer); +} + diff --git a/cogl/cogl/driver/gl/cogl-pipeline-progend-fixed-private.h b/cogl/cogl/driver/gl/cogl-pipeline-progend-fixed-private.h new file mode 100644 index 0000000..f97e16a --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-pipeline-progend-fixed-private.h @@ -0,0 +1,42 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Neil Roberts + */ + +#ifndef __COGL_PIPELINE_PROGEND_FIXED_PRIVATE_H +#define __COGL_PIPELINE_PROGEND_FIXED_PRIVATE_H + +#include "cogl-pipeline-private.h" + +extern const CoglPipelineProgend _cogl_pipeline_fixed_progend; + +#endif /* __COGL_PIPELINE_PROGEND_FIXED_PRIVATE_H */ + diff --git a/cogl/cogl/driver/gl/cogl-pipeline-progend-fixed.c b/cogl/cogl/driver/gl/cogl-pipeline-progend-fixed.c new file mode 100644 index 0000000..4eb4191 --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-pipeline-progend-fixed.c @@ -0,0 +1,112 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Neil Roberts + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include + +#include "cogl-pipeline-private.h" +#include "cogl-pipeline-state-private.h" + +#ifdef COGL_PIPELINE_PROGEND_FIXED + +#include "cogl-context.h" +#include "cogl-context-private.h" +#include "cogl-framebuffer-private.h" + +static CoglBool +_cogl_pipeline_progend_fixed_start (CoglPipeline *pipeline) +{ + _COGL_GET_CONTEXT (ctx, FALSE); + + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_FIXED))) + return FALSE; + + if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_GL_FIXED)) + return FALSE; + + /* Vertex snippets are only supported in the GLSL fragend */ + if (_cogl_pipeline_has_vertex_snippets (pipeline)) + return FALSE; + + /* Fragment snippets are only supported in the GLSL fragend */ + if (_cogl_pipeline_has_fragment_snippets (pipeline)) + return FALSE; + + /* If there is a user program then the appropriate backend for that + * language should handle it. */ + if (cogl_pipeline_get_user_program (pipeline)) + return FALSE; + + /* The fixed progend can't handle the per-vertex point size + * attribute */ + if (cogl_pipeline_get_per_vertex_point_size (pipeline)) + return FALSE; + + return TRUE; +} + +static void +_cogl_pipeline_progend_fixed_pre_paint (CoglPipeline *pipeline, + CoglFramebuffer *framebuffer) +{ + CoglContext *ctx = framebuffer->context; + + if (ctx->current_projection_entry) + _cogl_matrix_entry_flush_to_gl_builtins (ctx, + ctx->current_projection_entry, + COGL_MATRIX_PROJECTION, + framebuffer, + FALSE /* enable flip */); + if (ctx->current_modelview_entry) + _cogl_matrix_entry_flush_to_gl_builtins (ctx, + ctx->current_modelview_entry, + COGL_MATRIX_MODELVIEW, + framebuffer, + FALSE /* enable flip */); +} + +const CoglPipelineProgend _cogl_pipeline_fixed_progend = + { + COGL_PIPELINE_VERTEND_FIXED, + COGL_PIPELINE_FRAGEND_FIXED, + _cogl_pipeline_progend_fixed_start, + NULL, /* end */ + NULL, /* pre_change_notify */ + NULL, /* layer_pre_change_notify */ + _cogl_pipeline_progend_fixed_pre_paint + }; + +#endif /* COGL_PIPELINE_PROGEND_FIXED */ diff --git a/cogl/cogl/driver/gl/cogl-pipeline-progend-glsl-private.h b/cogl/cogl/driver/gl/cogl-pipeline-progend-glsl-private.h new file mode 100644 index 0000000..d57519b --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-pipeline-progend-glsl-private.h @@ -0,0 +1,47 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Neil Roberts + */ + +#ifndef __COGL_PIPELINE_PROGEND_GLSL_PRIVATE_H +#define __COGL_PIPELINE_PROGEND_GLSL_PRIVATE_H + +#include "cogl-pipeline-private.h" +#include "cogl-attribute-private.h" + +extern const CoglPipelineProgend _cogl_pipeline_glsl_progend; + +int +_cogl_pipeline_progend_glsl_get_attrib_location (CoglPipeline *pipeline, + int name_index); + +#endif /* __COGL_PIPELINE_PROGEND_GLSL_PRIVATE_H */ + diff --git a/cogl/cogl/driver/gl/cogl-pipeline-progend-glsl.c b/cogl/cogl/driver/gl/cogl-pipeline-progend-glsl.c new file mode 100644 index 0000000..3db5342 --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-pipeline-progend-glsl.c @@ -0,0 +1,1074 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Neil Roberts + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include + +#include "cogl-util.h" +#include "cogl-context-private.h" +#include "cogl-util-gl-private.h" +#include "cogl-pipeline-private.h" +#include "cogl-pipeline-opengl-private.h" +#include "cogl-offscreen.h" + +#ifdef COGL_PIPELINE_PROGEND_GLSL + +#include "cogl-context-private.h" +#include "cogl-object-private.h" +#include "cogl-program-private.h" +#include "cogl-pipeline-fragend-glsl-private.h" +#include "cogl-pipeline-vertend-glsl-private.h" +#include "cogl-pipeline-cache.h" +#include "cogl-pipeline-state-private.h" +#include "cogl-attribute-private.h" +#include "cogl-framebuffer-private.h" +#include "cogl-pipeline-progend-glsl-private.h" + +/* These are used to generalise updating some uniforms that are + required when building for drivers missing some fixed function + state that we use */ + +typedef void (* UpdateUniformFunc) (CoglPipeline *pipeline, + int uniform_location, + void *getter_func); + +static void update_float_uniform (CoglPipeline *pipeline, + int uniform_location, + void *getter_func); + +typedef struct +{ + const char *uniform_name; + void *getter_func; + UpdateUniformFunc update_func; + CoglPipelineState change; + + /* This builtin is only necessary if the following private feature + * is not implemented in the driver */ + CoglPrivateFeature feature_replacement; +} BuiltinUniformData; + +static BuiltinUniformData builtin_uniforms[] = + { + { "cogl_point_size_in", + cogl_pipeline_get_point_size, update_float_uniform, + COGL_PIPELINE_STATE_POINT_SIZE, + COGL_PRIVATE_FEATURE_BUILTIN_POINT_SIZE_UNIFORM }, + { "_cogl_alpha_test_ref", + cogl_pipeline_get_alpha_test_reference, update_float_uniform, + COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE, + COGL_PRIVATE_FEATURE_ALPHA_TEST } + }; + +const CoglPipelineProgend _cogl_pipeline_glsl_progend; + +typedef struct _UnitState +{ + unsigned int dirty_combine_constant:1; + unsigned int dirty_texture_matrix:1; + + GLint combine_constant_uniform; + + GLint texture_matrix_uniform; +} UnitState; + +typedef struct +{ + unsigned int ref_count; + + /* Age that the user program had last time we generated a GL + program. If it's different then we need to relink the program */ + unsigned int user_program_age; + + GLuint program; + + unsigned long dirty_builtin_uniforms; + GLint builtin_uniform_locations[G_N_ELEMENTS (builtin_uniforms)]; + + GLint modelview_uniform; + GLint projection_uniform; + GLint mvp_uniform; + + CoglMatrixEntryCache projection_cache; + CoglMatrixEntryCache modelview_cache; + + /* We need to track the last pipeline that the program was used with + * so know if we need to update all of the uniforms */ + CoglPipeline *last_used_for_pipeline; + + /* Array of GL uniform locations indexed by Cogl's uniform + location. We are careful only to allocated this array if a custom + uniform is actually set */ + GArray *uniform_locations; + + /* Array of attribute locations. */ + GArray *attribute_locations; + + /* The 'flip' uniform is used to flip the geometry upside-down when + the framebuffer requires it only when there are vertex + snippets. Otherwise this is acheived using the projection + matrix */ + GLint flip_uniform; + int flushed_flip_state; + + UnitState *unit_state; + + CoglPipelineCacheEntry *cache_entry; +} CoglPipelineProgramState; + +static CoglUserDataKey program_state_key; + +static CoglPipelineProgramState * +get_program_state (CoglPipeline *pipeline) +{ + return cogl_object_get_user_data (COGL_OBJECT (pipeline), &program_state_key); +} + +#define UNIFORM_LOCATION_UNKNOWN -2 + +#define ATTRIBUTE_LOCATION_UNKNOWN -2 + +/* Under GLES2 the vertex attribute API needs to query the attribute + numbers because it can't used the fixed function API to set the + builtin attributes. We cache the attributes here because the + progend knows when the program is changed so it can clear the + cache. This should always be called after the pipeline is flushed + so they can assert that the gl program is valid */ + +/* All attributes names get internally mapped to a global set of + * sequential indices when they are setup which we need to need to + * then be able to map to a GL attribute location once we have + * a linked GLSL program */ + +int +_cogl_pipeline_progend_glsl_get_attrib_location (CoglPipeline *pipeline, + int name_index) +{ + CoglPipelineProgramState *program_state = get_program_state (pipeline); + int *locations; + + _COGL_GET_CONTEXT (ctx, -1); + + _COGL_RETURN_VAL_IF_FAIL (program_state != NULL, -1); + _COGL_RETURN_VAL_IF_FAIL (program_state->program != 0, -1); + + if (G_UNLIKELY (program_state->attribute_locations == NULL)) + program_state->attribute_locations = + g_array_new (FALSE, FALSE, sizeof (int)); + + if (G_UNLIKELY (program_state->attribute_locations->len <= name_index)) + { + int i = program_state->attribute_locations->len; + g_array_set_size (program_state->attribute_locations, name_index + 1); + for (; i < program_state->attribute_locations->len; i++) + g_array_index (program_state->attribute_locations, int, i) + = ATTRIBUTE_LOCATION_UNKNOWN; + } + + locations = &g_array_index (program_state->attribute_locations, int, 0); + + if (locations[name_index] == ATTRIBUTE_LOCATION_UNKNOWN) + { + CoglAttributeNameState *name_state = + g_array_index (ctx->attribute_name_index_map, + CoglAttributeNameState *, name_index); + + _COGL_RETURN_VAL_IF_FAIL (name_state != NULL, 0); + + GE_RET( locations[name_index], + ctx, glGetAttribLocation (program_state->program, + name_state->name) ); + } + + return locations[name_index]; +} + +static void +clear_attribute_cache (CoglPipelineProgramState *program_state) +{ + if (program_state->attribute_locations) + { + g_array_free (program_state->attribute_locations, TRUE); + program_state->attribute_locations = NULL; + } +} + +static void +clear_flushed_matrix_stacks (CoglPipelineProgramState *program_state) +{ + _cogl_matrix_entry_cache_destroy (&program_state->projection_cache); + _cogl_matrix_entry_cache_init (&program_state->projection_cache); + _cogl_matrix_entry_cache_destroy (&program_state->modelview_cache); + _cogl_matrix_entry_cache_init (&program_state->modelview_cache); +} + +static CoglPipelineProgramState * +program_state_new (int n_layers, + CoglPipelineCacheEntry *cache_entry) +{ + CoglPipelineProgramState *program_state; + + program_state = g_slice_new (CoglPipelineProgramState); + program_state->ref_count = 1; + program_state->program = 0; + program_state->unit_state = g_new (UnitState, n_layers); + program_state->uniform_locations = NULL; + program_state->attribute_locations = NULL; + program_state->cache_entry = cache_entry; + _cogl_matrix_entry_cache_init (&program_state->modelview_cache); + _cogl_matrix_entry_cache_init (&program_state->projection_cache); + + return program_state; +} + +static void +destroy_program_state (void *user_data, + void *instance) +{ + CoglPipelineProgramState *program_state = user_data; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + /* If the program state was last used for this pipeline then clear + it so that if same address gets used again for a new pipeline + then we won't think it's the same pipeline and avoid updating the + uniforms */ + if (program_state->last_used_for_pipeline == instance) + program_state->last_used_for_pipeline = NULL; + + if (program_state->cache_entry && + program_state->cache_entry->pipeline != instance) + program_state->cache_entry->usage_count--; + + if (--program_state->ref_count == 0) + { + clear_attribute_cache (program_state); + + _cogl_matrix_entry_cache_destroy (&program_state->projection_cache); + _cogl_matrix_entry_cache_destroy (&program_state->modelview_cache); + + if (program_state->program) + GE( ctx, glDeleteProgram (program_state->program) ); + + g_free (program_state->unit_state); + + if (program_state->uniform_locations) + g_array_free (program_state->uniform_locations, TRUE); + + g_slice_free (CoglPipelineProgramState, program_state); + } +} + +static void +set_program_state (CoglPipeline *pipeline, + CoglPipelineProgramState *program_state) +{ + if (program_state) + { + program_state->ref_count++; + + /* If we're not setting the state on the template pipeline then + * mark it as a usage of the pipeline cache entry */ + if (program_state->cache_entry && + program_state->cache_entry->pipeline != pipeline) + program_state->cache_entry->usage_count++; + } + + _cogl_object_set_user_data (COGL_OBJECT (pipeline), + &program_state_key, + program_state, + destroy_program_state); +} + +static void +dirty_program_state (CoglPipeline *pipeline) +{ + cogl_object_set_user_data (COGL_OBJECT (pipeline), + &program_state_key, + NULL, + NULL); +} + +static void +link_program (GLint gl_program) +{ + GLint link_status; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + GE( ctx, glLinkProgram (gl_program) ); + + GE( ctx, glGetProgramiv (gl_program, GL_LINK_STATUS, &link_status) ); + + if (!link_status) + { + GLint log_length; + GLsizei out_log_length; + char *log; + + GE( ctx, glGetProgramiv (gl_program, GL_INFO_LOG_LENGTH, &log_length) ); + + log = g_malloc (log_length); + + GE( ctx, glGetProgramInfoLog (gl_program, log_length, + &out_log_length, log) ); + + g_warning ("Failed to link GLSL program:\n%.*s\n", + log_length, log); + + g_free (log); + } +} + +typedef struct +{ + int unit; + GLuint gl_program; + CoglBool update_all; + CoglPipelineProgramState *program_state; +} UpdateUniformsState; + +static CoglBool +get_uniform_cb (CoglPipeline *pipeline, + int layer_index, + void *user_data) +{ + UpdateUniformsState *state = user_data; + CoglPipelineProgramState *program_state = state->program_state; + UnitState *unit_state = &program_state->unit_state[state->unit]; + GLint uniform_location; + + _COGL_GET_CONTEXT (ctx, FALSE); + + /* We can reuse the source buffer to create the uniform name because + the program has now been linked */ + g_string_set_size (ctx->codegen_source_buffer, 0); + g_string_append_printf (ctx->codegen_source_buffer, + "cogl_sampler%i", layer_index); + + GE_RET( uniform_location, + ctx, glGetUniformLocation (state->gl_program, + ctx->codegen_source_buffer->str) ); + + /* We can set the uniform immediately because the samplers are the + unit index not the texture object number so it will never + change. Unfortunately GL won't let us use a constant instead of a + uniform */ + if (uniform_location != -1) + GE( ctx, glUniform1i (uniform_location, state->unit) ); + + g_string_set_size (ctx->codegen_source_buffer, 0); + g_string_append_printf (ctx->codegen_source_buffer, + "_cogl_layer_constant_%i", layer_index); + + GE_RET( uniform_location, + ctx, glGetUniformLocation (state->gl_program, + ctx->codegen_source_buffer->str) ); + + unit_state->combine_constant_uniform = uniform_location; + + g_string_set_size (ctx->codegen_source_buffer, 0); + g_string_append_printf (ctx->codegen_source_buffer, + "cogl_texture_matrix[%i]", layer_index); + + GE_RET( uniform_location, + ctx, glGetUniformLocation (state->gl_program, + ctx->codegen_source_buffer->str) ); + + unit_state->texture_matrix_uniform = uniform_location; + + state->unit++; + + return TRUE; +} + +static CoglBool +update_constants_cb (CoglPipeline *pipeline, + int layer_index, + void *user_data) +{ + UpdateUniformsState *state = user_data; + CoglPipelineProgramState *program_state = state->program_state; + UnitState *unit_state = &program_state->unit_state[state->unit++]; + + _COGL_GET_CONTEXT (ctx, FALSE); + + if (unit_state->combine_constant_uniform != -1 && + (state->update_all || unit_state->dirty_combine_constant)) + { + float constant[4]; + _cogl_pipeline_get_layer_combine_constant (pipeline, + layer_index, + constant); + GE (ctx, glUniform4fv (unit_state->combine_constant_uniform, + 1, constant)); + unit_state->dirty_combine_constant = FALSE; + } + + if (unit_state->texture_matrix_uniform != -1 && + (state->update_all || unit_state->dirty_texture_matrix)) + { + const CoglMatrix *matrix; + const float *array; + + matrix = _cogl_pipeline_get_layer_matrix (pipeline, layer_index); + array = cogl_matrix_get_array (matrix); + GE (ctx, glUniformMatrix4fv (unit_state->texture_matrix_uniform, + 1, FALSE, array)); + unit_state->dirty_texture_matrix = FALSE; + } + + return TRUE; +} + +static void +update_builtin_uniforms (CoglContext *context, + CoglPipeline *pipeline, + GLuint gl_program, + CoglPipelineProgramState *program_state) +{ + int i; + + if (program_state->dirty_builtin_uniforms == 0) + return; + + for (i = 0; i < G_N_ELEMENTS (builtin_uniforms); i++) + if (!_cogl_has_private_feature (context, + builtin_uniforms[i].feature_replacement) && + (program_state->dirty_builtin_uniforms & (1 << i)) && + program_state->builtin_uniform_locations[i] != -1) + builtin_uniforms[i].update_func (pipeline, + program_state + ->builtin_uniform_locations[i], + builtin_uniforms[i].getter_func); + + program_state->dirty_builtin_uniforms = 0; +} + +typedef struct +{ + CoglPipelineProgramState *program_state; + unsigned long *uniform_differences; + int n_differences; + CoglContext *ctx; + const CoglBoxedValue *values; + int value_index; +} FlushUniformsClosure; + +static CoglBool +flush_uniform_cb (int uniform_num, void *user_data) +{ + FlushUniformsClosure *data = user_data; + + if (COGL_FLAGS_GET (data->uniform_differences, uniform_num)) + { + GArray *uniform_locations; + GLint uniform_location; + + if (data->program_state->uniform_locations == NULL) + data->program_state->uniform_locations = + g_array_new (FALSE, FALSE, sizeof (GLint)); + + uniform_locations = data->program_state->uniform_locations; + + if (uniform_locations->len <= uniform_num) + { + unsigned int old_len = uniform_locations->len; + + g_array_set_size (uniform_locations, uniform_num + 1); + + while (old_len <= uniform_num) + { + g_array_index (uniform_locations, GLint, old_len) = + UNIFORM_LOCATION_UNKNOWN; + old_len++; + } + } + + uniform_location = g_array_index (uniform_locations, GLint, uniform_num); + + if (uniform_location == UNIFORM_LOCATION_UNKNOWN) + { + const char *uniform_name = + g_ptr_array_index (data->ctx->uniform_names, uniform_num); + + uniform_location = + data->ctx->glGetUniformLocation (data->program_state->program, + uniform_name); + g_array_index (uniform_locations, GLint, uniform_num) = + uniform_location; + } + + if (uniform_location != -1) + _cogl_boxed_value_set_uniform (data->ctx, + uniform_location, + data->values + data->value_index); + + data->n_differences--; + COGL_FLAGS_SET (data->uniform_differences, uniform_num, FALSE); + } + + data->value_index++; + + return data->n_differences > 0; +} + +static void +_cogl_pipeline_progend_glsl_flush_uniforms (CoglPipeline *pipeline, + CoglPipelineProgramState * + program_state, + GLuint gl_program, + CoglBool program_changed) +{ + CoglPipelineUniformsState *uniforms_state; + FlushUniformsClosure data; + int n_uniform_longs; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (pipeline->differences & COGL_PIPELINE_STATE_UNIFORMS) + uniforms_state = &pipeline->big_state->uniforms_state; + else + uniforms_state = NULL; + + data.program_state = program_state; + data.ctx = ctx; + + n_uniform_longs = COGL_FLAGS_N_LONGS_FOR_SIZE (ctx->n_uniform_names); + + data.uniform_differences = g_newa (unsigned long, n_uniform_longs); + + /* Try to find a common ancestor for the values that were already + flushed on the pipeline that this program state was last used for + so we can avoid flushing those */ + + if (program_changed || program_state->last_used_for_pipeline == NULL) + { + if (program_changed) + { + /* The program has changed so all of the uniform locations + are invalid */ + if (program_state->uniform_locations) + g_array_set_size (program_state->uniform_locations, 0); + } + + /* We need to flush everything so mark all of the uniforms as + dirty */ + memset (data.uniform_differences, 0xff, + n_uniform_longs * sizeof (unsigned long)); + data.n_differences = G_MAXINT; + } + else if (program_state->last_used_for_pipeline) + { + int i; + + memset (data.uniform_differences, 0, + n_uniform_longs * sizeof (unsigned long)); + _cogl_pipeline_compare_uniform_differences + (data.uniform_differences, + program_state->last_used_for_pipeline, + pipeline); + + /* We need to be sure to flush any uniforms that have changed + since the last flush */ + if (uniforms_state) + _cogl_bitmask_set_flags (&uniforms_state->changed_mask, + data.uniform_differences); + + /* Count the number of differences. This is so we can stop early + when we've flushed all of them */ + data.n_differences = 0; + + for (i = 0; i < n_uniform_longs; i++) + data.n_differences += + _cogl_util_popcountl (data.uniform_differences[i]); + } + + while (pipeline && data.n_differences > 0) + { + if (pipeline->differences & COGL_PIPELINE_STATE_UNIFORMS) + { + const CoglPipelineUniformsState *parent_uniforms_state = + &pipeline->big_state->uniforms_state; + + data.values = parent_uniforms_state->override_values; + data.value_index = 0; + + _cogl_bitmask_foreach (&parent_uniforms_state->override_mask, + flush_uniform_cb, + &data); + } + + pipeline = _cogl_pipeline_get_parent (pipeline); + } + + if (uniforms_state) + _cogl_bitmask_clear_all (&uniforms_state->changed_mask); +} + +static CoglBool +_cogl_pipeline_progend_glsl_start (CoglPipeline *pipeline) +{ + CoglHandle user_program; + + _COGL_GET_CONTEXT (ctx, FALSE); + + if (!cogl_has_feature (ctx, COGL_FEATURE_ID_GLSL)) + return FALSE; + + user_program = cogl_pipeline_get_user_program (pipeline); + if (user_program && + _cogl_program_get_language (user_program) != COGL_SHADER_LANGUAGE_GLSL) + return FALSE; + + return TRUE; +} + +static void +_cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline, + unsigned long pipelines_difference) +{ + CoglPipelineProgramState *program_state; + GLuint gl_program; + CoglBool program_changed = FALSE; + UpdateUniformsState state; + CoglProgram *user_program; + CoglPipelineCacheEntry *cache_entry = NULL; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + program_state = get_program_state (pipeline); + + user_program = cogl_pipeline_get_user_program (pipeline); + + if (program_state == NULL) + { + CoglPipeline *authority; + + /* Get the authority for anything affecting program state. This + should include both fragment codegen state and vertex codegen + state */ + authority = _cogl_pipeline_find_equivalent_parent + (pipeline, + (_cogl_pipeline_get_state_for_vertex_codegen (ctx) | + _cogl_pipeline_get_state_for_fragment_codegen (ctx)) & + ~COGL_PIPELINE_STATE_LAYERS, + _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx) | + COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN); + + program_state = get_program_state (authority); + + if (program_state == NULL) + { + /* Check if there is already a similar cached pipeline whose + program state we can share */ + if (G_LIKELY (!(COGL_DEBUG_ENABLED + (COGL_DEBUG_DISABLE_PROGRAM_CACHES)))) + { + cache_entry = + _cogl_pipeline_cache_get_combined_template (ctx->pipeline_cache, + authority); + + program_state = get_program_state (cache_entry->pipeline); + } + + if (program_state) + program_state->ref_count++; + else + program_state + = program_state_new (cogl_pipeline_get_n_layers (authority), + cache_entry); + + set_program_state (authority, program_state); + + program_state->ref_count--; + + if (cache_entry) + set_program_state (cache_entry->pipeline, program_state); + } + + if (authority != pipeline) + set_program_state (pipeline, program_state); + } + + /* If the program has changed since the last link then we do + * need to relink */ + if (program_state->program && user_program && + user_program->age != program_state->user_program_age) + { + GE( ctx, glDeleteProgram (program_state->program) ); + program_state->program = 0; + } + + if (program_state->program == 0) + { + GLuint backend_shader; + GSList *l; + + GE_RET( program_state->program, ctx, glCreateProgram () ); + + /* Attach all of the shader from the user program */ + if (user_program) + { + for (l = user_program->attached_shaders; l; l = l->next) + { + CoglShader *shader = l->data; + + _cogl_shader_compile_real (shader, pipeline); + + g_assert (shader->language == COGL_SHADER_LANGUAGE_GLSL); + + GE( ctx, glAttachShader (program_state->program, + shader->gl_handle) ); + } + + program_state->user_program_age = user_program->age; + } + + /* Attach any shaders from the GLSL backends */ + if ((backend_shader = _cogl_pipeline_fragend_glsl_get_shader (pipeline))) + GE( ctx, glAttachShader (program_state->program, backend_shader) ); + if ((backend_shader = _cogl_pipeline_vertend_glsl_get_shader (pipeline))) + GE( ctx, glAttachShader (program_state->program, backend_shader) ); + + /* XXX: OpenGL as a special case requires the vertex position to + * be bound to generic attribute 0 so for simplicity we + * unconditionally bind the cogl_position_in attribute here... + */ + GE( ctx, glBindAttribLocation (program_state->program, + 0, "cogl_position_in")); + + link_program (program_state->program); + + program_changed = TRUE; + } + + gl_program = program_state->program; + + _cogl_use_fragment_program (gl_program, COGL_PIPELINE_PROGRAM_TYPE_GLSL); + _cogl_use_vertex_program (gl_program, COGL_PIPELINE_PROGRAM_TYPE_GLSL); + + state.unit = 0; + state.gl_program = gl_program; + state.program_state = program_state; + + if (program_changed) + { + cogl_pipeline_foreach_layer (pipeline, + get_uniform_cb, + &state); + clear_attribute_cache (program_state); + + GE_RET (program_state->flip_uniform, + ctx, glGetUniformLocation (gl_program, "_cogl_flip_vector")); + program_state->flushed_flip_state = -1; + } + + state.unit = 0; + state.update_all = (program_changed || + program_state->last_used_for_pipeline != pipeline); + + cogl_pipeline_foreach_layer (pipeline, + update_constants_cb, + &state); + + if (program_changed) + { + int i; + + clear_flushed_matrix_stacks (program_state); + + for (i = 0; i < G_N_ELEMENTS (builtin_uniforms); i++) + if (!_cogl_has_private_feature + (ctx, builtin_uniforms[i].feature_replacement)) + GE_RET( program_state->builtin_uniform_locations[i], ctx, + glGetUniformLocation (gl_program, + builtin_uniforms[i].uniform_name) ); + + GE_RET( program_state->modelview_uniform, ctx, + glGetUniformLocation (gl_program, + "cogl_modelview_matrix") ); + + GE_RET( program_state->projection_uniform, ctx, + glGetUniformLocation (gl_program, + "cogl_projection_matrix") ); + + GE_RET( program_state->mvp_uniform, ctx, + glGetUniformLocation (gl_program, + "cogl_modelview_projection_matrix") ); + } + + if (program_changed || + program_state->last_used_for_pipeline != pipeline) + program_state->dirty_builtin_uniforms = ~(unsigned long) 0; + + update_builtin_uniforms (ctx, pipeline, gl_program, program_state); + + _cogl_pipeline_progend_glsl_flush_uniforms (pipeline, + program_state, + gl_program, + program_changed); + + if (user_program) + _cogl_program_flush_uniforms (user_program, + gl_program, + program_changed); + + /* We need to track the last pipeline that the program was used with + * so know if we need to update all of the uniforms */ + program_state->last_used_for_pipeline = pipeline; +} + +static void +_cogl_pipeline_progend_glsl_pre_change_notify (CoglPipeline *pipeline, + CoglPipelineState change, + const CoglColor *new_color) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if ((change & (_cogl_pipeline_get_state_for_vertex_codegen (ctx) | + _cogl_pipeline_get_state_for_fragment_codegen (ctx)))) + { + dirty_program_state (pipeline); + } + else + { + int i; + + for (i = 0; i < G_N_ELEMENTS (builtin_uniforms); i++) + if (!_cogl_has_private_feature + (ctx, builtin_uniforms[i].feature_replacement) && + (change & builtin_uniforms[i].change)) + { + CoglPipelineProgramState *program_state + = get_program_state (pipeline); + if (program_state) + program_state->dirty_builtin_uniforms |= 1 << i; + return; + } + } +} + +/* NB: layers are considered immutable once they have any dependants + * so although multiple pipelines can end up depending on a single + * static layer, we can guarantee that if a layer is being *changed* + * then it can only have one pipeline depending on it. + * + * XXX: Don't forget this is *pre* change, we can't read the new value + * yet! + */ +static void +_cogl_pipeline_progend_glsl_layer_pre_change_notify ( + CoglPipeline *owner, + CoglPipelineLayer *layer, + CoglPipelineLayerState change) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if ((change & (_cogl_pipeline_get_layer_state_for_fragment_codegen (ctx) | + COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN))) + { + dirty_program_state (owner); + } + else if (change & COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT) + { + CoglPipelineProgramState *program_state = get_program_state (owner); + if (program_state) + { + int unit_index = _cogl_pipeline_layer_get_unit_index (layer); + program_state->unit_state[unit_index].dirty_combine_constant = TRUE; + } + } + else if (change & COGL_PIPELINE_LAYER_STATE_USER_MATRIX) + { + CoglPipelineProgramState *program_state = get_program_state (owner); + if (program_state) + { + int unit_index = _cogl_pipeline_layer_get_unit_index (layer); + program_state->unit_state[unit_index].dirty_texture_matrix = TRUE; + } + } +} + +static void +_cogl_pipeline_progend_glsl_pre_paint (CoglPipeline *pipeline, + CoglFramebuffer *framebuffer) +{ + CoglBool needs_flip; + CoglMatrixEntry *projection_entry; + CoglMatrixEntry *modelview_entry; + CoglPipelineProgramState *program_state; + CoglBool modelview_changed; + CoglBool projection_changed; + CoglBool need_modelview; + CoglBool need_projection; + CoglMatrix modelview, projection; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + program_state = get_program_state (pipeline); + + projection_entry = ctx->current_projection_entry; + modelview_entry = ctx->current_modelview_entry; + + /* An initial pipeline is flushed while creating the context. At + this point there are no matrices selected so we can't do + anything */ + if (modelview_entry == NULL || projection_entry == NULL) + return; + + needs_flip = cogl_is_offscreen (ctx->current_draw_buffer); + + projection_changed = + _cogl_matrix_entry_cache_maybe_update (&program_state->projection_cache, + projection_entry, + (needs_flip && + program_state->flip_uniform == + -1)); + + modelview_changed = + _cogl_matrix_entry_cache_maybe_update (&program_state->modelview_cache, + modelview_entry, + /* never flip modelview */ + FALSE); + + if (modelview_changed || projection_changed) + { + if (program_state->mvp_uniform != -1) + need_modelview = need_projection = TRUE; + else + { + need_projection = (program_state->projection_uniform != -1 && + projection_changed); + need_modelview = (program_state->modelview_uniform != -1 && + modelview_changed); + } + + if (need_modelview) + cogl_matrix_entry_get (modelview_entry, &modelview); + if (need_projection) + { + if (needs_flip && program_state->flip_uniform == -1) + { + CoglMatrix tmp_matrix; + cogl_matrix_entry_get (projection_entry, &tmp_matrix); + cogl_matrix_multiply (&projection, + &ctx->y_flip_matrix, + &tmp_matrix); + } + else + cogl_matrix_entry_get (projection_entry, &projection); + } + + if (projection_changed && program_state->projection_uniform != -1) + GE (ctx, glUniformMatrix4fv (program_state->projection_uniform, + 1, /* count */ + FALSE, /* transpose */ + cogl_matrix_get_array (&projection))); + + if (modelview_changed && program_state->modelview_uniform != -1) + GE (ctx, glUniformMatrix4fv (program_state->modelview_uniform, + 1, /* count */ + FALSE, /* transpose */ + cogl_matrix_get_array (&modelview))); + + if (program_state->mvp_uniform != -1) + { + /* The journal usually uses an identity matrix for the + modelview so we can optimise this common case by + avoiding the matrix multiplication */ + if (cogl_matrix_entry_is_identity (modelview_entry)) + { + GE (ctx, + glUniformMatrix4fv (program_state->mvp_uniform, + 1, /* count */ + FALSE, /* transpose */ + cogl_matrix_get_array (&projection))); + } + else + { + CoglMatrix combined; + + cogl_matrix_multiply (&combined, + &projection, + &modelview); + GE (ctx, + glUniformMatrix4fv (program_state->mvp_uniform, + 1, /* count */ + FALSE, /* transpose */ + cogl_matrix_get_array (&combined))); + } + } + } + + if (program_state->flip_uniform != -1 + && program_state->flushed_flip_state != needs_flip) + { + static const float do_flip[4] = { 1.0f, -1.0f, 1.0f, 1.0f }; + static const float dont_flip[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + GE( ctx, glUniform4fv (program_state->flip_uniform, + 1, /* count */ + needs_flip ? do_flip : dont_flip) ); + program_state->flushed_flip_state = needs_flip; + } +} + +static void +update_float_uniform (CoglPipeline *pipeline, + int uniform_location, + void *getter_func) +{ + float (* float_getter_func) (CoglPipeline *) = getter_func; + float value; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + value = float_getter_func (pipeline); + GE( ctx, glUniform1f (uniform_location, value) ); +} + +const CoglPipelineProgend _cogl_pipeline_glsl_progend = + { + COGL_PIPELINE_VERTEND_GLSL, + COGL_PIPELINE_FRAGEND_GLSL, + _cogl_pipeline_progend_glsl_start, + _cogl_pipeline_progend_glsl_end, + _cogl_pipeline_progend_glsl_pre_change_notify, + _cogl_pipeline_progend_glsl_layer_pre_change_notify, + _cogl_pipeline_progend_glsl_pre_paint + }; + +#endif /* COGL_PIPELINE_PROGEND_GLSL */ diff --git a/cogl/cogl/driver/gl/cogl-pipeline-vertend-fixed-private.h b/cogl/cogl/driver/gl/cogl-pipeline-vertend-fixed-private.h new file mode 100644 index 0000000..97dee54 --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-pipeline-vertend-fixed-private.h @@ -0,0 +1,42 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Neil Roberts + */ + +#ifndef __COGL_PIPELINE_VERTEND_FIXED_PRIVATE_H +#define __COGL_PIPELINE_VERTEND_FIXED_PRIVATE_H + +#include "cogl-pipeline-private.h" + +extern const CoglPipelineVertend _cogl_pipeline_fixed_vertend; + +#endif /* __COGL_PIPELINE_VERTEND_FIXED_PRIVATE_H */ + diff --git a/cogl/cogl/driver/gl/cogl-pipeline-vertend-fixed.c b/cogl/cogl/driver/gl/cogl-pipeline-vertend-fixed.c new file mode 100644 index 0000000..eec60d3 --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-pipeline-vertend-fixed.c @@ -0,0 +1,121 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Neil Roberts + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-context-private.h" +#include "cogl-util-gl-private.h" +#include "cogl-pipeline-private.h" +#include "cogl-pipeline-state-private.h" +#include "cogl-pipeline-opengl-private.h" +#include "cogl-framebuffer-private.h" + +#ifdef COGL_PIPELINE_VERTEND_FIXED + +#include "cogl-context-private.h" +#include "cogl-object-private.h" +#include "cogl-program-private.h" + +const CoglPipelineVertend _cogl_pipeline_fixed_vertend; + +static void +_cogl_pipeline_vertend_fixed_start (CoglPipeline *pipeline, + int n_layers, + unsigned long pipelines_difference) +{ + _cogl_use_vertex_program (0, COGL_PIPELINE_PROGRAM_TYPE_FIXED); +} + +static CoglBool +_cogl_pipeline_vertend_fixed_add_layer (CoglPipeline *pipeline, + CoglPipelineLayer *layer, + unsigned long layers_difference, + CoglFramebuffer *framebuffer) +{ + CoglContext *ctx = framebuffer->context; + int unit_index = _cogl_pipeline_layer_get_unit_index (layer); + CoglTextureUnit *unit = _cogl_get_texture_unit (unit_index); + + if (layers_difference & COGL_PIPELINE_LAYER_STATE_USER_MATRIX) + { + CoglPipelineLayerState state = COGL_PIPELINE_LAYER_STATE_USER_MATRIX; + CoglPipelineLayer *authority = + _cogl_pipeline_layer_get_authority (layer, state); + CoglMatrixEntry *matrix_entry; + + cogl_matrix_stack_set (unit->matrix_stack, + &authority->big_state->matrix); + + _cogl_set_active_texture_unit (unit_index); + + matrix_entry = unit->matrix_stack->last_entry; + _cogl_matrix_entry_flush_to_gl_builtins (ctx, matrix_entry, + COGL_MATRIX_TEXTURE, + framebuffer, + FALSE /* enable flip */); + } + + return TRUE; +} + +static CoglBool +_cogl_pipeline_vertend_fixed_end (CoglPipeline *pipeline, + unsigned long pipelines_difference) +{ + _COGL_GET_CONTEXT (ctx, FALSE); + + if (pipelines_difference & COGL_PIPELINE_STATE_POINT_SIZE) + { + CoglPipeline *authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_POINT_SIZE); + + if (authority->big_state->point_size > 0.0f) + GE( ctx, glPointSize (authority->big_state->point_size) ); + } + + return TRUE; +} + +const CoglPipelineVertend _cogl_pipeline_fixed_vertend = +{ + _cogl_pipeline_vertend_fixed_start, + _cogl_pipeline_vertend_fixed_add_layer, + _cogl_pipeline_vertend_fixed_end, + NULL, /* pipeline_change_notify */ + NULL /* layer_change_notify */ +}; + +#endif /* COGL_PIPELINE_VERTEND_FIXED */ + diff --git a/cogl/cogl/driver/gl/cogl-pipeline-vertend-glsl-private.h b/cogl/cogl/driver/gl/cogl-pipeline-vertend-glsl-private.h new file mode 100644 index 0000000..4bd3823 --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-pipeline-vertend-glsl-private.h @@ -0,0 +1,45 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_PIPELINE_VERTEND_GLSL_PRIVATE_H +#define __COGL_PIPELINE_VERTEND_GLSL_PRIVATE_H + +#include "cogl-pipeline-private.h" + +extern const CoglPipelineVertend _cogl_pipeline_glsl_vertend; + +GLuint +_cogl_pipeline_vertend_glsl_get_shader (CoglPipeline *pipeline); + +#endif /* __COGL_PIPELINE_VERTEND_GLSL_PRIVATE_H */ + diff --git a/cogl/cogl/driver/gl/cogl-pipeline-vertend-glsl.c b/cogl/cogl/driver/gl/cogl-pipeline-vertend-glsl.c new file mode 100644 index 0000000..6386110 --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-pipeline-vertend-glsl.c @@ -0,0 +1,680 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010,2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Neil Roberts + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include + +#include + +#include "cogl-context-private.h" +#include "cogl-util-gl-private.h" +#include "cogl-pipeline-private.h" +#include "cogl-pipeline-opengl-private.h" + +#ifdef COGL_PIPELINE_VERTEND_GLSL + +#include "cogl-context-private.h" +#include "cogl-object-private.h" +#include "cogl-program-private.h" +#include "cogl-pipeline-vertend-glsl-private.h" +#include "cogl-pipeline-state-private.h" +#include "cogl-glsl-shader-private.h" + +const CoglPipelineVertend _cogl_pipeline_glsl_vertend; + +typedef struct +{ + unsigned int ref_count; + + GLuint gl_shader; + GString *header, *source; + + CoglPipelineCacheEntry *cache_entry; +} CoglPipelineShaderState; + +static CoglUserDataKey shader_state_key; + +static CoglPipelineShaderState * +shader_state_new (CoglPipelineCacheEntry *cache_entry) +{ + CoglPipelineShaderState *shader_state; + + shader_state = g_slice_new0 (CoglPipelineShaderState); + shader_state->ref_count = 1; + shader_state->cache_entry = cache_entry; + + return shader_state; +} + +static CoglPipelineShaderState * +get_shader_state (CoglPipeline *pipeline) +{ + return cogl_object_get_user_data (COGL_OBJECT (pipeline), &shader_state_key); +} + +static void +destroy_shader_state (void *user_data, + void *instance) +{ + CoglPipelineShaderState *shader_state = user_data; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (shader_state->cache_entry && + shader_state->cache_entry->pipeline != instance) + shader_state->cache_entry->usage_count--; + + if (--shader_state->ref_count == 0) + { + if (shader_state->gl_shader) + GE( ctx, glDeleteShader (shader_state->gl_shader) ); + + g_slice_free (CoglPipelineShaderState, shader_state); + } +} + +static void +set_shader_state (CoglPipeline *pipeline, + CoglPipelineShaderState *shader_state) +{ + if (shader_state) + { + shader_state->ref_count++; + + /* If we're not setting the state on the template pipeline then + * mark it as a usage of the pipeline cache entry */ + if (shader_state->cache_entry && + shader_state->cache_entry->pipeline != pipeline) + shader_state->cache_entry->usage_count++; + } + + _cogl_object_set_user_data (COGL_OBJECT (pipeline), + &shader_state_key, + shader_state, + destroy_shader_state); +} + +static void +dirty_shader_state (CoglPipeline *pipeline) +{ + cogl_object_set_user_data (COGL_OBJECT (pipeline), + &shader_state_key, + NULL, + NULL); +} + +GLuint +_cogl_pipeline_vertend_glsl_get_shader (CoglPipeline *pipeline) +{ + CoglPipelineShaderState *shader_state = get_shader_state (pipeline); + + if (shader_state) + return shader_state->gl_shader; + else + return 0; +} + +static CoglPipelineSnippetList * +get_vertex_snippets (CoglPipeline *pipeline) +{ + pipeline = + _cogl_pipeline_get_authority (pipeline, + COGL_PIPELINE_STATE_VERTEX_SNIPPETS); + + return &pipeline->big_state->vertex_snippets; +} + +static CoglPipelineSnippetList * +get_layer_vertex_snippets (CoglPipelineLayer *layer) +{ + unsigned long state = COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS; + layer = _cogl_pipeline_layer_get_authority (layer, state); + + return &layer->big_state->vertex_snippets; +} + +static CoglBool +add_layer_declaration_cb (CoglPipelineLayer *layer, + void *user_data) +{ + CoglPipelineShaderState *shader_state = user_data; + CoglTextureType texture_type = + _cogl_pipeline_layer_get_texture_type (layer); + const char *target_string; + + _cogl_gl_util_get_texture_target_string (texture_type, &target_string, NULL); + + g_string_append_printf (shader_state->header, + "uniform sampler%s cogl_sampler%i;\n", + target_string, + layer->index); + + return TRUE; +} + +static void +add_layer_declarations (CoglPipeline *pipeline, + CoglPipelineShaderState *shader_state) +{ + /* We always emit sampler uniforms in case there will be custom + * layer snippets that want to sample arbitrary layers. */ + + _cogl_pipeline_foreach_layer_internal (pipeline, + add_layer_declaration_cb, + shader_state); +} + +static void +add_global_declarations (CoglPipeline *pipeline, + CoglPipelineShaderState *shader_state) +{ + CoglSnippetHook hook = COGL_SNIPPET_HOOK_VERTEX_GLOBALS; + CoglPipelineSnippetList *snippets = get_vertex_snippets (pipeline); + + /* Add the global data hooks. All of the code in these snippets is + * always added and only the declarations data is used */ + + _cogl_pipeline_snippet_generate_declarations (shader_state->header, + hook, + snippets); +} + +static void +_cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline, + int n_layers, + unsigned long pipelines_difference) +{ + CoglPipelineShaderState *shader_state; + CoglPipelineCacheEntry *cache_entry = NULL; + CoglProgram *user_program = cogl_pipeline_get_user_program (pipeline); + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + /* Now lookup our glsl backend private state (allocating if + * necessary) */ + shader_state = get_shader_state (pipeline); + + if (shader_state == NULL) + { + CoglPipeline *authority; + + /* Get the authority for anything affecting vertex shader + state */ + authority = _cogl_pipeline_find_equivalent_parent + (pipeline, + _cogl_pipeline_get_state_for_vertex_codegen (ctx) & + ~COGL_PIPELINE_STATE_LAYERS, + COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN); + + shader_state = get_shader_state (authority); + + if (shader_state == NULL) + { + /* Check if there is already a similar cached pipeline whose + shader state we can share */ + if (G_LIKELY (!(COGL_DEBUG_ENABLED + (COGL_DEBUG_DISABLE_PROGRAM_CACHES)))) + { + cache_entry = + _cogl_pipeline_cache_get_vertex_template (ctx->pipeline_cache, + authority); + + shader_state = get_shader_state (cache_entry->pipeline); + } + + if (shader_state) + shader_state->ref_count++; + else + shader_state = shader_state_new (cache_entry); + + set_shader_state (authority, shader_state); + + shader_state->ref_count--; + + if (cache_entry) + set_shader_state (cache_entry->pipeline, shader_state); + } + + if (authority != pipeline) + set_shader_state (pipeline, shader_state); + } + + if (user_program) + { + /* If the user program contains a vertex shader then we don't need + to generate one */ + if (_cogl_program_has_vertex_shader (user_program)) + { + if (shader_state->gl_shader) + { + GE( ctx, glDeleteShader (shader_state->gl_shader) ); + shader_state->gl_shader = 0; + } + return; + } + } + + if (shader_state->gl_shader) + return; + + /* If we make it here then we have a shader_state struct without a gl_shader + either because this is the first time we've encountered it or + because the user program has changed */ + + /* We reuse two grow-only GStrings for code-gen. One string + contains the uniform and attribute declarations while the + other contains the main function. We need two strings + because we need to dynamically declare attributes as the + add_layer callback is invoked */ + g_string_set_size (ctx->codegen_header_buffer, 0); + g_string_set_size (ctx->codegen_source_buffer, 0); + shader_state->header = ctx->codegen_header_buffer; + shader_state->source = ctx->codegen_source_buffer; + + add_layer_declarations (pipeline, shader_state); + add_global_declarations (pipeline, shader_state); + + g_string_append (shader_state->source, + "void\n" + "cogl_generated_source ()\n" + "{\n"); + + if (cogl_pipeline_get_per_vertex_point_size (pipeline)) + g_string_append (shader_state->header, + "attribute float cogl_point_size_in;\n"); + else if (!_cogl_has_private_feature + (ctx, COGL_PRIVATE_FEATURE_BUILTIN_POINT_SIZE_UNIFORM)) + { + /* There is no builtin uniform for the point size on GLES2 so we + need to copy it from the custom uniform in the vertex shader + if we're not using per-vertex point sizes, however we'll only + do this if the point-size is non-zero. Toggle the point size + between zero and non-zero causes a state change which + generates a new program */ + if (cogl_pipeline_get_point_size (pipeline) > 0.0f) + { + g_string_append (shader_state->header, + "uniform float cogl_point_size_in;\n"); + g_string_append (shader_state->source, + " cogl_point_size_out = cogl_point_size_in;\n"); + } + } +} + +static CoglBool +_cogl_pipeline_vertend_glsl_add_layer (CoglPipeline *pipeline, + CoglPipelineLayer *layer, + unsigned long layers_difference, + CoglFramebuffer *framebuffer) +{ + CoglPipelineShaderState *shader_state; + CoglPipelineSnippetData snippet_data; + int layer_index = layer->index; + + _COGL_GET_CONTEXT (ctx, FALSE); + + shader_state = get_shader_state (pipeline); + + if (shader_state->source == NULL) + return TRUE; + + /* Transform the texture coordinates by the layer's user matrix. + * + * FIXME: this should avoid doing the transform if there is no user + * matrix set. This might need a separate layer state flag for + * whether there is a user matrix + * + * FIXME: we could be more clever here and try to detect if the + * fragment program is going to use the texture coordinates and + * avoid setting them if not + */ + + g_string_append_printf (shader_state->header, + "vec4\n" + "cogl_real_transform_layer%i (mat4 matrix, " + "vec4 tex_coord)\n" + "{\n" + " return matrix * tex_coord;\n" + "}\n", + layer_index); + + /* Wrap the layer code in any snippets that have been hooked */ + memset (&snippet_data, 0, sizeof (snippet_data)); + snippet_data.snippets = get_layer_vertex_snippets (layer); + snippet_data.hook = COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM; + snippet_data.chain_function = g_strdup_printf ("cogl_real_transform_layer%i", + layer_index); + snippet_data.final_name = g_strdup_printf ("cogl_transform_layer%i", + layer_index); + snippet_data.function_prefix = g_strdup_printf ("cogl_transform_layer%i", + layer_index); + snippet_data.return_type = "vec4"; + snippet_data.return_variable = "cogl_tex_coord"; + snippet_data.return_variable_is_argument = TRUE; + snippet_data.arguments = "cogl_matrix, cogl_tex_coord"; + snippet_data.argument_declarations = "mat4 cogl_matrix, vec4 cogl_tex_coord"; + snippet_data.source_buf = shader_state->header; + + _cogl_pipeline_snippet_generate_code (&snippet_data); + + g_free ((char *) snippet_data.chain_function); + g_free ((char *) snippet_data.final_name); + g_free ((char *) snippet_data.function_prefix); + + g_string_append_printf (shader_state->source, + " cogl_tex_coord%i_out = " + "cogl_transform_layer%i (cogl_texture_matrix%i,\n" + " " + " cogl_tex_coord%i_in);\n", + layer_index, + layer_index, + layer_index, + layer_index); + + return TRUE; +} + +static CoglBool +_cogl_pipeline_vertend_glsl_end (CoglPipeline *pipeline, + unsigned long pipelines_difference) +{ + CoglPipelineShaderState *shader_state; + + _COGL_GET_CONTEXT (ctx, FALSE); + + shader_state = get_shader_state (pipeline); + + if (shader_state->source) + { + const char *source_strings[2]; + GLint lengths[2]; + GLint compile_status; + GLuint shader; + CoglPipelineSnippetData snippet_data; + CoglPipelineSnippetList *vertex_snippets; + CoglBool has_per_vertex_point_size = + cogl_pipeline_get_per_vertex_point_size (pipeline); + + COGL_STATIC_COUNTER (vertend_glsl_compile_counter, + "glsl vertex compile counter", + "Increments each time a new GLSL " + "vertex shader is compiled", + 0 /* no application private data */); + COGL_COUNTER_INC (_cogl_uprof_context, vertend_glsl_compile_counter); + + g_string_append (shader_state->header, + "void\n" + "cogl_real_vertex_transform ()\n" + "{\n" + " cogl_position_out = " + "cogl_modelview_projection_matrix * " + "cogl_position_in;\n" + "}\n"); + + g_string_append (shader_state->source, + " cogl_vertex_transform ();\n"); + + if (has_per_vertex_point_size) + { + g_string_append (shader_state->header, + "void\n" + "cogl_real_point_size_calculation ()\n" + "{\n" + " cogl_point_size_out = cogl_point_size_in;\n" + "}\n"); + g_string_append (shader_state->source, + " cogl_point_size_calculation ();\n"); + } + + g_string_append (shader_state->source, + " cogl_color_out = cogl_color_in;\n" + "}\n"); + + vertex_snippets = get_vertex_snippets (pipeline); + + /* Add hooks for the vertex transform part */ + memset (&snippet_data, 0, sizeof (snippet_data)); + snippet_data.snippets = vertex_snippets; + snippet_data.hook = COGL_SNIPPET_HOOK_VERTEX_TRANSFORM; + snippet_data.chain_function = "cogl_real_vertex_transform"; + snippet_data.final_name = "cogl_vertex_transform"; + snippet_data.function_prefix = "cogl_vertex_transform"; + snippet_data.source_buf = shader_state->header; + _cogl_pipeline_snippet_generate_code (&snippet_data); + + /* Add hooks for the point size calculation part */ + if (has_per_vertex_point_size) + { + memset (&snippet_data, 0, sizeof (snippet_data)); + snippet_data.snippets = vertex_snippets; + snippet_data.hook = COGL_SNIPPET_HOOK_POINT_SIZE; + snippet_data.chain_function = "cogl_real_point_size_calculation"; + snippet_data.final_name = "cogl_point_size_calculation"; + snippet_data.function_prefix = "cogl_point_size_calculation"; + snippet_data.source_buf = shader_state->header; + _cogl_pipeline_snippet_generate_code (&snippet_data); + } + + /* Add all of the hooks for vertex processing */ + memset (&snippet_data, 0, sizeof (snippet_data)); + snippet_data.snippets = vertex_snippets; + snippet_data.hook = COGL_SNIPPET_HOOK_VERTEX; + snippet_data.chain_function = "cogl_generated_source"; + snippet_data.final_name = "cogl_vertex_hook"; + snippet_data.function_prefix = "cogl_vertex_hook"; + snippet_data.source_buf = shader_state->source; + _cogl_pipeline_snippet_generate_code (&snippet_data); + + g_string_append (shader_state->source, + "void\n" + "main ()\n" + "{\n" + " cogl_vertex_hook ();\n"); + + /* If there are any snippets then we can't rely on the + projection matrix to flip the rendering for offscreen buffers + so we'll need to flip it using an extra statement and a + uniform */ + if (_cogl_pipeline_has_vertex_snippets (pipeline)) + { + g_string_append (shader_state->header, + "uniform vec4 _cogl_flip_vector;\n"); + g_string_append (shader_state->source, + " cogl_position_out *= _cogl_flip_vector;\n"); + } + + g_string_append (shader_state->source, + "}\n"); + + GE_RET( shader, ctx, glCreateShader (GL_VERTEX_SHADER) ); + + lengths[0] = shader_state->header->len; + source_strings[0] = shader_state->header->str; + lengths[1] = shader_state->source->len; + source_strings[1] = shader_state->source->str; + + _cogl_glsl_shader_set_source_with_boilerplate (ctx, + shader, GL_VERTEX_SHADER, + pipeline, + 2, /* count */ + source_strings, lengths); + + GE( ctx, glCompileShader (shader) ); + GE( ctx, glGetShaderiv (shader, GL_COMPILE_STATUS, &compile_status) ); + + if (!compile_status) + { + GLint len = 0; + char *shader_log; + + GE( ctx, glGetShaderiv (shader, GL_INFO_LOG_LENGTH, &len) ); + shader_log = g_alloca (len); + GE( ctx, glGetShaderInfoLog (shader, len, &len, shader_log) ); + g_warning ("Shader compilation failed:\n%s", shader_log); + } + + shader_state->header = NULL; + shader_state->source = NULL; + shader_state->gl_shader = shader; + } + +#ifdef HAVE_COGL_GL + if (_cogl_has_private_feature + (ctx, COGL_PRIVATE_FEATURE_BUILTIN_POINT_SIZE_UNIFORM) && + (pipelines_difference & COGL_PIPELINE_STATE_POINT_SIZE)) + { + CoglPipeline *authority = + _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_POINT_SIZE); + + if (authority->big_state->point_size > 0.0f) + GE( ctx, glPointSize (authority->big_state->point_size) ); + } +#endif /* HAVE_COGL_GL */ + + return TRUE; +} + +static void +_cogl_pipeline_vertend_glsl_pre_change_notify (CoglPipeline *pipeline, + CoglPipelineState change, + const CoglColor *new_color) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if ((change & _cogl_pipeline_get_state_for_vertex_codegen (ctx))) + dirty_shader_state (pipeline); +} + +/* NB: layers are considered immutable once they have any dependants + * so although multiple pipelines can end up depending on a single + * static layer, we can guarantee that if a layer is being *changed* + * then it can only have one pipeline depending on it. + * + * XXX: Don't forget this is *pre* change, we can't read the new value + * yet! + */ +static void +_cogl_pipeline_vertend_glsl_layer_pre_change_notify ( + CoglPipeline *owner, + CoglPipelineLayer *layer, + CoglPipelineLayerState change) +{ + CoglPipelineShaderState *shader_state; + + shader_state = get_shader_state (owner); + if (!shader_state) + return; + + if ((change & COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN)) + { + dirty_shader_state (owner); + return; + } + + /* TODO: we could be saving snippets of texture combine code along + * with each layer and then when a layer changes we would just free + * the snippet. */ +} + +const CoglPipelineVertend _cogl_pipeline_glsl_vertend = + { + _cogl_pipeline_vertend_glsl_start, + _cogl_pipeline_vertend_glsl_add_layer, + _cogl_pipeline_vertend_glsl_end, + _cogl_pipeline_vertend_glsl_pre_change_notify, + _cogl_pipeline_vertend_glsl_layer_pre_change_notify + }; + +UNIT_TEST (check_point_size_shader, + 0 /* no requirements */, + 0 /* no failure cases */) +{ + CoglPipeline *pipelines[4]; + CoglPipelineShaderState *shader_states[G_N_ELEMENTS (pipelines)]; + int i; + + /* Default pipeline with zero point size */ + pipelines[0] = cogl_pipeline_new (test_ctx); + + /* Point size 1 */ + pipelines[1] = cogl_pipeline_new (test_ctx); + cogl_pipeline_set_point_size (pipelines[1], 1.0f); + + /* Point size 2 */ + pipelines[2] = cogl_pipeline_new (test_ctx); + cogl_pipeline_set_point_size (pipelines[2], 2.0f); + + /* Same as the first pipeline, but reached by restoring the old + * state from a copy */ + pipelines[3] = cogl_pipeline_copy (pipelines[1]); + cogl_pipeline_set_point_size (pipelines[3], 0.0f); + + /* Draw something with all of the pipelines to make sure their state + * is flushed */ + for (i = 0; i < G_N_ELEMENTS (pipelines); i++) + cogl_framebuffer_draw_rectangle (test_fb, + pipelines[i], + 0.0f, 0.0f, + 10.0f, 10.0f); + cogl_framebuffer_finish (test_fb); + + /* Get all of the shader states. These might be NULL if the driver + * is not using GLSL */ + for (i = 0; i < G_N_ELEMENTS (pipelines); i++) + shader_states[i] = get_shader_state (pipelines[i]); + + /* If the first two pipelines are using GLSL then they should have + * the same shader unless there is no builtin uniform for the point + * size */ + if (shader_states[0]) + { + if (_cogl_has_private_feature + (test_ctx, COGL_PRIVATE_FEATURE_BUILTIN_POINT_SIZE_UNIFORM)) + g_assert (shader_states[0] == shader_states[1]); + else + g_assert (shader_states[0] != shader_states[1]); + } + + /* The second and third pipelines should always have the same shader + * state because only toggling between zero and non-zero should + * change the shader */ + g_assert (shader_states[1] == shader_states[2]); + + /* The fourth pipeline should be exactly the same as the first */ + g_assert (shader_states[0] == shader_states[3]); +} + +#endif /* COGL_PIPELINE_VERTEND_GLSL */ diff --git a/cogl/cogl/driver/gl/cogl-texture-2d-gl-private.h b/cogl/cogl/driver/gl/cogl-texture-2d-gl-private.h new file mode 100644 index 0000000..e5c6585 --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-texture-2d-gl-private.h @@ -0,0 +1,119 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef _COGL_TEXTURE_2D_GL_PRIVATE_H_ +#define _COGL_TEXTURE_2D_GL_PRIVATE_H_ + +#include "cogl-types.h" +#include "cogl-context-private.h" +#include "cogl-texture.h" + +void +_cogl_texture_2d_gl_free (CoglTexture2D *tex_2d); + +CoglBool +_cogl_texture_2d_gl_can_create (CoglContext *ctx, + int width, + int height, + CoglPixelFormat internal_format); + +void +_cogl_texture_2d_gl_init (CoglTexture2D *tex_2d); + +CoglBool +_cogl_texture_2d_gl_allocate (CoglTexture *tex, + CoglError **error); + +CoglTexture2D * +_cogl_texture_2d_gl_new_from_bitmap (CoglBitmap *bmp, + CoglPixelFormat internal_format, + CoglBool can_convert_in_place, + CoglError **error); + +#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base) +CoglTexture2D * +_cogl_egl_texture_2d_gl_new_from_image (CoglContext *ctx, + int width, + int height, + CoglPixelFormat format, + EGLImageKHR image, + CoglError **error); +#endif + +void +_cogl_texture_2d_gl_flush_legacy_texobj_filters (CoglTexture *tex, + GLenum min_filter, + GLenum mag_filter); + +void +_cogl_texture_2d_gl_flush_legacy_texobj_wrap_modes (CoglTexture *tex, + GLenum wrap_mode_s, + GLenum wrap_mode_t, + GLenum wrap_mode_p); + +void +_cogl_texture_2d_gl_copy_from_framebuffer (CoglTexture2D *tex_2d, + int src_x, + int src_y, + int width, + int height, + CoglFramebuffer *src_fb, + int dst_x, + int dst_y, + int level); + +unsigned int +_cogl_texture_2d_gl_get_gl_handle (CoglTexture2D *tex_2d); + +void +_cogl_texture_2d_gl_generate_mipmap (CoglTexture2D *tex_2d); + +CoglBool +_cogl_texture_2d_gl_copy_from_bitmap (CoglTexture2D *tex_2d, + int src_x, + int src_y, + int width, + int height, + CoglBitmap *bitmap, + int dst_x, + int dst_y, + int level, + CoglError **error); + +void +_cogl_texture_2d_gl_get_data (CoglTexture2D *tex_2d, + CoglPixelFormat format, + int rowstride, + uint8_t *data); + +#endif /* _COGL_TEXTURE_2D_GL_PRIVATE_H_ */ diff --git a/cogl/cogl/driver/gl/cogl-texture-2d-gl.c b/cogl/cogl/driver/gl/cogl-texture-2d-gl.c new file mode 100644 index 0000000..1193df4 --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-texture-2d-gl.c @@ -0,0 +1,750 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009,2010,2011,2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Neil Roberts + * Robert Bragg + */ + +#include "cogl-config.h" + +#include + +#include "cogl-private.h" +#include "cogl-texture-private.h" +#include "cogl-texture-2d-gl.h" +#include "cogl-texture-2d-gl-private.h" +#include "cogl-texture-2d-private.h" +#include "cogl-texture-gl-private.h" +#include "cogl-pipeline-opengl-private.h" +#include "cogl-error-private.h" +#include "cogl-util-gl-private.h" + +void +_cogl_texture_2d_gl_free (CoglTexture2D *tex_2d) +{ + if (!tex_2d->is_foreign && tex_2d->gl_texture) + _cogl_delete_gl_texture (tex_2d->gl_texture); +} + +CoglBool +_cogl_texture_2d_gl_can_create (CoglContext *ctx, + int width, + int height, + CoglPixelFormat internal_format) +{ + GLenum gl_intformat; + GLenum gl_format; + GLenum gl_type; + + /* If NPOT textures aren't supported then the size must be a power + of two */ + if (!cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC) && + (!_cogl_util_is_pot (width) || + !_cogl_util_is_pot (height))) + return FALSE; + + ctx->driver_vtable->pixel_format_to_gl (ctx, + internal_format, + &gl_intformat, + &gl_format, + &gl_type); + + /* Check that the driver can create a texture with that size */ + if (!ctx->texture_driver->size_supported (ctx, + GL_TEXTURE_2D, + gl_intformat, + gl_format, + gl_type, + width, + height)) + return FALSE; + + return TRUE; +} + +void +_cogl_texture_2d_gl_init (CoglTexture2D *tex_2d) +{ + tex_2d->gl_texture = 0; + + /* We default to GL_LINEAR for both filters */ + tex_2d->gl_legacy_texobj_min_filter = GL_LINEAR; + tex_2d->gl_legacy_texobj_mag_filter = GL_LINEAR; + + /* Wrap mode not yet set */ + tex_2d->gl_legacy_texobj_wrap_mode_s = GL_FALSE; + tex_2d->gl_legacy_texobj_wrap_mode_t = GL_FALSE; +} + +static CoglBool +allocate_with_size (CoglTexture2D *tex_2d, + CoglTextureLoader *loader, + CoglError **error) +{ + CoglTexture *tex = COGL_TEXTURE (tex_2d); + CoglPixelFormat internal_format; + int width = loader->src.sized.width; + int height = loader->src.sized.height; + CoglContext *ctx = tex->context; + GLenum gl_intformat; + GLenum gl_format; + GLenum gl_type; + GLenum gl_texture; + + internal_format = + _cogl_texture_determine_internal_format (tex, COGL_PIXEL_FORMAT_ANY); + + if (!_cogl_texture_2d_gl_can_create (ctx, + width, + height, + internal_format)) + { + _cogl_set_error (error, COGL_TEXTURE_ERROR, + COGL_TEXTURE_ERROR_SIZE, + "Failed to create texture 2d due to size/format" + " constraints"); + return FALSE; + } + + ctx->driver_vtable->pixel_format_to_gl (ctx, + internal_format, + &gl_intformat, + &gl_format, + &gl_type); + + gl_texture = ctx->texture_driver->gen (ctx, GL_TEXTURE_2D, internal_format); + + tex_2d->gl_internal_format = gl_intformat; + + _cogl_bind_gl_texture_transient (GL_TEXTURE_2D, + gl_texture, + tex_2d->is_foreign); + + /* Clear any GL errors */ + _cogl_gl_util_clear_gl_errors (ctx); + + ctx->glTexImage2D (GL_TEXTURE_2D, 0, gl_intformat, + width, height, 0, gl_format, gl_type, NULL); + + if (_cogl_gl_util_catch_out_of_memory (ctx, error)) + { + GE( ctx, glDeleteTextures (1, &gl_texture) ); + return FALSE; + } + + tex_2d->gl_texture = gl_texture; + tex_2d->gl_internal_format = gl_intformat; + + tex_2d->internal_format = internal_format; + + _cogl_texture_set_allocated (tex, internal_format, width, height); + + return TRUE; +} + +static CoglBool +allocate_from_bitmap (CoglTexture2D *tex_2d, + CoglTextureLoader *loader, + CoglError **error) +{ + CoglTexture *tex = COGL_TEXTURE (tex_2d); + CoglBitmap *bmp = loader->src.bitmap.bitmap; + CoglContext *ctx = _cogl_bitmap_get_context (bmp); + CoglPixelFormat internal_format; + int width = cogl_bitmap_get_width (bmp); + int height = cogl_bitmap_get_height (bmp); + CoglBool can_convert_in_place = loader->src.bitmap.can_convert_in_place; + CoglBitmap *upload_bmp; + GLenum gl_intformat; + GLenum gl_format; + GLenum gl_type; + + internal_format = + _cogl_texture_determine_internal_format (tex, cogl_bitmap_get_format (bmp)); + + if (!_cogl_texture_2d_gl_can_create (ctx, + width, + height, + internal_format)) + { + _cogl_set_error (error, COGL_TEXTURE_ERROR, + COGL_TEXTURE_ERROR_SIZE, + "Failed to create texture 2d due to size/format" + " constraints"); + return FALSE; + } + + upload_bmp = _cogl_bitmap_convert_for_upload (bmp, + internal_format, + can_convert_in_place, + error); + if (upload_bmp == NULL) + return FALSE; + + ctx->driver_vtable->pixel_format_to_gl (ctx, + cogl_bitmap_get_format (upload_bmp), + NULL, /* internal format */ + &gl_format, + &gl_type); + ctx->driver_vtable->pixel_format_to_gl (ctx, + internal_format, + &gl_intformat, + NULL, + NULL); + + /* Keep a copy of the first pixel so that if glGenerateMipmap isn't + supported we can fallback to using GL_GENERATE_MIPMAP */ + if (!cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN)) + { + CoglError *ignore = NULL; + uint8_t *data = _cogl_bitmap_map (upload_bmp, + COGL_BUFFER_ACCESS_READ, 0, + &ignore); + CoglPixelFormat format = cogl_bitmap_get_format (upload_bmp); + + tex_2d->first_pixel.gl_format = gl_format; + tex_2d->first_pixel.gl_type = gl_type; + + if (data) + { + memcpy (tex_2d->first_pixel.data, data, + _cogl_pixel_format_get_bytes_per_pixel (format)); + _cogl_bitmap_unmap (upload_bmp); + } + else + { + g_warning ("Failed to read first pixel of bitmap for " + "glGenerateMipmap fallback"); + cogl_error_free (ignore); + memset (tex_2d->first_pixel.data, 0, + _cogl_pixel_format_get_bytes_per_pixel (format)); + } + } + + tex_2d->gl_texture = + ctx->texture_driver->gen (ctx, GL_TEXTURE_2D, internal_format); + if (!ctx->texture_driver->upload_to_gl (ctx, + GL_TEXTURE_2D, + tex_2d->gl_texture, + FALSE, + upload_bmp, + gl_intformat, + gl_format, + gl_type, + error)) + { + cogl_object_unref (upload_bmp); + return FALSE; + } + + tex_2d->gl_internal_format = gl_intformat; + + cogl_object_unref (upload_bmp); + + tex_2d->internal_format = internal_format; + + _cogl_texture_set_allocated (tex, internal_format, width, height); + + return TRUE; +} + +#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base) +static CoglBool +allocate_from_egl_image (CoglTexture2D *tex_2d, + CoglTextureLoader *loader, + CoglError **error) +{ + CoglTexture *tex = COGL_TEXTURE (tex_2d); + CoglContext *ctx = tex->context; + CoglPixelFormat internal_format = loader->src.egl_image.format; + + tex_2d->gl_texture = + ctx->texture_driver->gen (ctx, GL_TEXTURE_2D, internal_format); + _cogl_bind_gl_texture_transient (GL_TEXTURE_2D, + tex_2d->gl_texture, + FALSE); + _cogl_gl_util_clear_gl_errors (ctx); + + ctx->glEGLImageTargetTexture2D (GL_TEXTURE_2D, loader->src.egl_image.image); + if (_cogl_gl_util_get_error (ctx) != GL_NO_ERROR) + { + _cogl_set_error (error, + COGL_TEXTURE_ERROR, + COGL_TEXTURE_ERROR_BAD_PARAMETER, + "Could not create a CoglTexture2D from a given " + "EGLImage"); + GE( ctx, glDeleteTextures (1, &tex_2d->gl_texture) ); + return FALSE; + } + + tex_2d->internal_format = internal_format; + + _cogl_texture_set_allocated (tex, + internal_format, + loader->src.egl_image.width, + loader->src.egl_image.height); + + return TRUE; +} +#endif + +static CoglBool +allocate_from_gl_foreign (CoglTexture2D *tex_2d, + CoglTextureLoader *loader, + CoglError **error) +{ + CoglTexture *tex = COGL_TEXTURE (tex_2d); + CoglContext *ctx = tex->context; + CoglPixelFormat format = loader->src.gl_foreign.format; + GLint gl_compressed = GL_FALSE; + GLenum gl_int_format = 0; + + if (!ctx->texture_driver->allows_foreign_gl_target (ctx, GL_TEXTURE_2D)) + { + _cogl_set_error (error, + COGL_SYSTEM_ERROR, + COGL_SYSTEM_ERROR_UNSUPPORTED, + "Foreign GL_TEXTURE_2D textures are not " + "supported by your system"); + return FALSE; + } + + /* Make sure binding succeeds */ + _cogl_gl_util_clear_gl_errors (ctx); + + _cogl_bind_gl_texture_transient (GL_TEXTURE_2D, + loader->src.gl_foreign.gl_handle, TRUE); + if (_cogl_gl_util_get_error (ctx) != GL_NO_ERROR) + { + _cogl_set_error (error, + COGL_SYSTEM_ERROR, + COGL_SYSTEM_ERROR_UNSUPPORTED, + "Failed to bind foreign GL_TEXTURE_2D texture"); + return FALSE; + } + + /* Obtain texture parameters + (only level 0 we are interested in) */ + +#ifdef HAVE_COGL_GL + if (_cogl_has_private_feature + (ctx, COGL_PRIVATE_FEATURE_QUERY_TEXTURE_PARAMETERS)) + { + GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, + GL_TEXTURE_COMPRESSED, + &gl_compressed) ); + + { + GLint val; + + GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, + GL_TEXTURE_INTERNAL_FORMAT, + &val) ); + + gl_int_format = val; + } + + /* If we can query GL for the actual pixel format then we'll ignore + the passed in format and use that. */ + if (!ctx->driver_vtable->pixel_format_from_gl_internal (ctx, + gl_int_format, + &format)) + { + _cogl_set_error (error, + COGL_SYSTEM_ERROR, + COGL_SYSTEM_ERROR_UNSUPPORTED, + "Unsupported internal format for foreign texture"); + return FALSE; + } + } + else +#endif + { + /* Otherwise we'll assume we can derive the GL format from the + passed in format */ + ctx->driver_vtable->pixel_format_to_gl (ctx, + format, + &gl_int_format, + NULL, + NULL); + } + + /* Compressed texture images not supported */ + if (gl_compressed == GL_TRUE) + { + _cogl_set_error (error, + COGL_SYSTEM_ERROR, + COGL_SYSTEM_ERROR_UNSUPPORTED, + "Compressed foreign textures aren't currently supported"); + return FALSE; + } + + /* Note: previously this code would query the texture object for + whether it has GL_GENERATE_MIPMAP enabled to determine whether to + auto-generate the mipmap. This doesn't make much sense any more + since Cogl switch to using glGenerateMipmap. Ideally I think + cogl_texture_2d_gl_new_from_foreign should take a flags parameter so + that the application can decide whether it wants + auto-mipmapping. To be compatible with existing code, Cogl now + disables its own auto-mipmapping but leaves the value of + GL_GENERATE_MIPMAP alone so that it would still work but without + the dirtiness tracking that Cogl would do. */ + + _cogl_texture_2d_set_auto_mipmap (COGL_TEXTURE (tex_2d), FALSE); + + /* Setup bitmap info */ + tex_2d->is_foreign = TRUE; + tex_2d->mipmaps_dirty = TRUE; + + tex_2d->gl_texture = loader->src.gl_foreign.gl_handle; + tex_2d->gl_internal_format = gl_int_format; + + /* Unknown filter */ + tex_2d->gl_legacy_texobj_min_filter = GL_FALSE; + tex_2d->gl_legacy_texobj_mag_filter = GL_FALSE; + + tex_2d->internal_format = format; + + _cogl_texture_set_allocated (tex, + format, + loader->src.gl_foreign.width, + loader->src.gl_foreign.height); + return TRUE; +} + +CoglBool +_cogl_texture_2d_gl_allocate (CoglTexture *tex, + CoglError **error) +{ + CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex); + CoglTextureLoader *loader = tex->loader; + + _COGL_RETURN_VAL_IF_FAIL (loader, FALSE); + + switch (loader->src_type) + { + case COGL_TEXTURE_SOURCE_TYPE_SIZED: + return allocate_with_size (tex_2d, loader, error); + case COGL_TEXTURE_SOURCE_TYPE_BITMAP: + return allocate_from_bitmap (tex_2d, loader, error); + case COGL_TEXTURE_SOURCE_TYPE_EGL_IMAGE: +#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base) + return allocate_from_egl_image (tex_2d, loader, error); +#else + g_return_val_if_reached (FALSE); +#endif + case COGL_TEXTURE_SOURCE_TYPE_GL_FOREIGN: + return allocate_from_gl_foreign (tex_2d, loader, error); + } + + g_return_val_if_reached (FALSE); +} + +void +_cogl_texture_2d_gl_flush_legacy_texobj_filters (CoglTexture *tex, + GLenum min_filter, + GLenum mag_filter) +{ + CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex); + CoglContext *ctx = tex->context; + + if (min_filter == tex_2d->gl_legacy_texobj_min_filter + && mag_filter == tex_2d->gl_legacy_texobj_mag_filter) + return; + + /* Store new values */ + tex_2d->gl_legacy_texobj_min_filter = min_filter; + tex_2d->gl_legacy_texobj_mag_filter = mag_filter; + + /* Apply new filters to the texture */ + _cogl_bind_gl_texture_transient (GL_TEXTURE_2D, + tex_2d->gl_texture, + tex_2d->is_foreign); + GE( ctx, glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter) ); + GE( ctx, glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter) ); +} + +void +_cogl_texture_2d_gl_flush_legacy_texobj_wrap_modes (CoglTexture *tex, + GLenum wrap_mode_s, + GLenum wrap_mode_t, + GLenum wrap_mode_p) +{ + CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex); + CoglContext *ctx = tex->context; + + /* Only set the wrap mode if it's different from the current value + to avoid too many GL calls. Texture 2D doesn't make use of the r + coordinate so we can ignore its wrap mode */ + if (tex_2d->gl_legacy_texobj_wrap_mode_s != wrap_mode_s || + tex_2d->gl_legacy_texobj_wrap_mode_t != wrap_mode_t) + { + _cogl_bind_gl_texture_transient (GL_TEXTURE_2D, + tex_2d->gl_texture, + tex_2d->is_foreign); + GE( ctx, glTexParameteri (GL_TEXTURE_2D, + GL_TEXTURE_WRAP_S, + wrap_mode_s) ); + GE( ctx, glTexParameteri (GL_TEXTURE_2D, + GL_TEXTURE_WRAP_T, + wrap_mode_t) ); + + tex_2d->gl_legacy_texobj_wrap_mode_s = wrap_mode_s; + tex_2d->gl_legacy_texobj_wrap_mode_t = wrap_mode_t; + } +} + +CoglTexture2D * +cogl_texture_2d_gl_new_from_foreign (CoglContext *ctx, + unsigned int gl_handle, + int width, + int height, + CoglPixelFormat format) +{ + CoglTextureLoader *loader; + + /* NOTE: width, height and internal format are not queriable + * in GLES, hence such a function prototype. + */ + + /* Note: We always trust the given width and height without querying + * the texture object because the user may be creating a Cogl + * texture for a texture_from_pixmap object where glTexImage2D may + * not have been called and the texture_from_pixmap spec doesn't + * clarify that it is reliable to query back the size from OpenGL. + */ + + /* Assert it is a valid GL texture object */ + _COGL_RETURN_VAL_IF_FAIL (ctx->glIsTexture (gl_handle), FALSE); + + /* Validate width and height */ + _COGL_RETURN_VAL_IF_FAIL (width > 0 && height > 0, NULL); + + loader = _cogl_texture_create_loader (); + loader->src_type = COGL_TEXTURE_SOURCE_TYPE_GL_FOREIGN; + loader->src.gl_foreign.gl_handle = gl_handle; + loader->src.gl_foreign.width = width; + loader->src.gl_foreign.height = height; + loader->src.gl_foreign.format = format; + + return _cogl_texture_2d_create_base (ctx, width, height, format, loader); +} + +void +_cogl_texture_2d_gl_copy_from_framebuffer (CoglTexture2D *tex_2d, + int src_x, + int src_y, + int width, + int height, + CoglFramebuffer *src_fb, + int dst_x, + int dst_y, + int level) +{ + CoglTexture *tex = COGL_TEXTURE (tex_2d); + CoglContext *ctx = tex->context; + + /* Make sure the current framebuffers are bound, though we don't need to + * flush the clip state here since we aren't going to draw to the + * framebuffer. */ + _cogl_framebuffer_flush_state (ctx->current_draw_buffer, + src_fb, + COGL_FRAMEBUFFER_STATE_ALL & + ~COGL_FRAMEBUFFER_STATE_CLIP); + + _cogl_bind_gl_texture_transient (GL_TEXTURE_2D, + tex_2d->gl_texture, + tex_2d->is_foreign); + + ctx->glCopyTexSubImage2D (GL_TEXTURE_2D, + 0, /* level */ + dst_x, dst_y, + src_x, src_y, + width, height); +} + +unsigned int +_cogl_texture_2d_gl_get_gl_handle (CoglTexture2D *tex_2d) +{ + return tex_2d->gl_texture; +} + +void +_cogl_texture_2d_gl_generate_mipmap (CoglTexture2D *tex_2d) +{ + CoglContext *ctx = COGL_TEXTURE (tex_2d)->context; + + /* glGenerateMipmap is defined in the FBO extension. If it's not + available we'll fallback to temporarily enabling + GL_GENERATE_MIPMAP and reuploading the first pixel */ + if (cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN)) + _cogl_texture_gl_generate_mipmaps (COGL_TEXTURE (tex_2d)); +#if defined(HAVE_COGL_GLES) || defined(HAVE_COGL_GL) + else + { + _cogl_bind_gl_texture_transient (GL_TEXTURE_2D, + tex_2d->gl_texture, + tex_2d->is_foreign); + + GE( ctx, glTexParameteri (GL_TEXTURE_2D, + GL_GENERATE_MIPMAP, + GL_TRUE) ); + GE( ctx, glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, 1, 1, + tex_2d->first_pixel.gl_format, + tex_2d->first_pixel.gl_type, + tex_2d->first_pixel.data) ); + GE( ctx, glTexParameteri (GL_TEXTURE_2D, + GL_GENERATE_MIPMAP, + GL_FALSE) ); + } +#endif +} + +CoglBool +_cogl_texture_2d_gl_copy_from_bitmap (CoglTexture2D *tex_2d, + int src_x, + int src_y, + int width, + int height, + CoglBitmap *bmp, + int dst_x, + int dst_y, + int level, + CoglError **error) +{ + CoglTexture *tex = COGL_TEXTURE (tex_2d); + CoglContext *ctx = tex->context; + CoglBitmap *upload_bmp; + CoglPixelFormat upload_format; + GLenum gl_format; + GLenum gl_type; + CoglBool status = TRUE; + + upload_bmp = + _cogl_bitmap_convert_for_upload (bmp, + _cogl_texture_get_format (tex), + FALSE, /* can't convert in place */ + error); + if (upload_bmp == NULL) + return FALSE; + + upload_format = cogl_bitmap_get_format (upload_bmp); + + ctx->driver_vtable->pixel_format_to_gl (ctx, + upload_format, + NULL, /* internal format */ + &gl_format, + &gl_type); + + /* If this touches the first pixel then we'll update our copy */ + if (dst_x == 0 && dst_y == 0 && + !cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN)) + { + CoglError *ignore = NULL; + uint8_t *data = + _cogl_bitmap_map (upload_bmp, COGL_BUFFER_ACCESS_READ, 0, &ignore); + CoglPixelFormat bpp = + _cogl_pixel_format_get_bytes_per_pixel (upload_format); + + tex_2d->first_pixel.gl_format = gl_format; + tex_2d->first_pixel.gl_type = gl_type; + + if (data) + { + memcpy (tex_2d->first_pixel.data, + (data + + cogl_bitmap_get_rowstride (upload_bmp) * src_y + + bpp * src_x), + bpp); + _cogl_bitmap_unmap (bmp); + } + else + { + g_warning ("Failed to read first bitmap pixel for " + "glGenerateMipmap fallback"); + cogl_error_free (ignore); + memset (tex_2d->first_pixel.data, 0, bpp); + } + } + + status = ctx->texture_driver->upload_subregion_to_gl (ctx, + tex, + FALSE, + src_x, src_y, + dst_x, dst_y, + width, height, + level, + upload_bmp, + gl_format, + gl_type, + error); + + cogl_object_unref (upload_bmp); + + _cogl_texture_gl_maybe_update_max_level (tex, level); + + return status; +} + +void +_cogl_texture_2d_gl_get_data (CoglTexture2D *tex_2d, + CoglPixelFormat format, + int rowstride, + uint8_t *data) +{ + CoglContext *ctx = COGL_TEXTURE (tex_2d)->context; + int bpp; + int width = COGL_TEXTURE (tex_2d)->width; + GLenum gl_format; + GLenum gl_type; + + bpp = _cogl_pixel_format_get_bytes_per_pixel (format); + + ctx->driver_vtable->pixel_format_to_gl (ctx, + format, + NULL, /* internal format */ + &gl_format, + &gl_type); + + ctx->texture_driver->prep_gl_for_pixels_download (ctx, + rowstride, + width, + bpp); + + _cogl_bind_gl_texture_transient (GL_TEXTURE_2D, + tex_2d->gl_texture, + tex_2d->is_foreign); + + ctx->texture_driver->gl_get_tex_image (ctx, + GL_TEXTURE_2D, + gl_format, + gl_type, + data); +} diff --git a/cogl/cogl/driver/gl/cogl-texture-gl-private.h b/cogl/cogl/driver/gl/cogl-texture-gl-private.h new file mode 100644 index 0000000..b5baac7 --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-texture-gl-private.h @@ -0,0 +1,66 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef _COGL_TEXTURE_GL_PRIVATE_H_ +#define _COGL_TEXTURE_GL_PRIVATE_H_ + +#include "cogl-context.h" + +void +_cogl_texture_gl_prep_alignment_for_pixels_upload (CoglContext *ctx, + int pixels_rowstride); + +void +_cogl_texture_gl_prep_alignment_for_pixels_download (CoglContext *ctx, + int bpp, + int width, + int rowstride); + +void +_cogl_texture_gl_flush_legacy_texobj_wrap_modes (CoglTexture *texture, + unsigned int wrap_mode_s, + unsigned int wrap_mode_t, + unsigned int wrap_mode_p); + +void +_cogl_texture_gl_flush_legacy_texobj_filters (CoglTexture *texture, + unsigned int min_filter, + unsigned int mag_filter); + +void +_cogl_texture_gl_maybe_update_max_level (CoglTexture *texture, + int max_level); + +void +_cogl_texture_gl_generate_mipmaps (CoglTexture *texture); + +GLenum +_cogl_texture_gl_get_format (CoglTexture *texture); + +#endif /* _COGL_TEXTURE_GL_PRIVATE_H_ */ diff --git a/cogl/cogl/driver/gl/cogl-texture-gl.c b/cogl/cogl/driver/gl/cogl-texture-gl.c new file mode 100644 index 0000000..0225341 --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-texture-gl.c @@ -0,0 +1,158 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#ifdef HAVE_STRINGS_H +#include +#endif + +#include "cogl-context-private.h" +#include "cogl-util-gl-private.h" +#include "cogl-texture-gl-private.h" +#include "cogl-texture-3d-private.h" +#include "cogl-util.h" +#include "cogl-pipeline-opengl-private.h" + +static inline int +calculate_alignment (int rowstride) +{ + int alignment = 1 << (_cogl_util_ffs (rowstride) - 1); + + return MIN (alignment, 8); +} + +void +_cogl_texture_gl_prep_alignment_for_pixels_upload (CoglContext *ctx, + int pixels_rowstride) +{ + GE( ctx, glPixelStorei (GL_UNPACK_ALIGNMENT, + calculate_alignment (pixels_rowstride)) ); +} + +void +_cogl_texture_gl_prep_alignment_for_pixels_download (CoglContext *ctx, + int bpp, + int width, + int rowstride) +{ + int alignment; + + /* If no padding is needed then we can always use an alignment of 1. + * We want to do this even though it is equivalent to the alignment + * of the rowstride because the Intel driver in Mesa currently has + * an optimisation when reading data into a PBO that only works if + * the alignment is exactly 1. + * + * https://bugs.freedesktop.org/show_bug.cgi?id=46632 + */ + + if (rowstride == bpp * width) + alignment = 1; + else + alignment = calculate_alignment (rowstride); + + GE( ctx, glPixelStorei (GL_PACK_ALIGNMENT, alignment) ); +} + +void +_cogl_texture_gl_flush_legacy_texobj_wrap_modes (CoglTexture *texture, + unsigned int wrap_mode_s, + unsigned int wrap_mode_t, + unsigned int wrap_mode_p) +{ + texture->vtable->gl_flush_legacy_texobj_wrap_modes (texture, + wrap_mode_s, + wrap_mode_t, + wrap_mode_p); +} + +void +_cogl_texture_gl_flush_legacy_texobj_filters (CoglTexture *texture, + unsigned int min_filter, + unsigned int mag_filter) +{ + texture->vtable->gl_flush_legacy_texobj_filters (texture, + min_filter, mag_filter); +} + +void +_cogl_texture_gl_maybe_update_max_level (CoglTexture *texture, + int max_level) +{ + /* This isn't supported on GLES */ +#ifdef HAVE_COGL_GL + CoglContext *ctx = texture->context; + + if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_TEXTURE_MAX_LEVEL) && + texture->max_level < max_level) + { + CoglContext *ctx = texture->context; + GLuint gl_handle; + GLenum gl_target; + + cogl_texture_get_gl_texture (texture, &gl_handle, &gl_target); + + texture->max_level = max_level; + + _cogl_bind_gl_texture_transient (gl_target, + gl_handle, + _cogl_texture_is_foreign (texture)); + + GE( ctx, glTexParameteri (gl_target, + GL_TEXTURE_MAX_LEVEL, texture->max_level)); + } +#endif /* HAVE_COGL_GL */ +} + +void +_cogl_texture_gl_generate_mipmaps (CoglTexture *texture) +{ + CoglContext *ctx = texture->context; + int n_levels = _cogl_texture_get_n_levels (texture); + GLuint gl_handle; + GLenum gl_target; + + _cogl_texture_gl_maybe_update_max_level (texture, n_levels - 1); + + cogl_texture_get_gl_texture (texture, &gl_handle, &gl_target); + + _cogl_bind_gl_texture_transient (gl_target, + gl_handle, + _cogl_texture_is_foreign (texture)); + GE( ctx, glGenerateMipmap (gl_target) ); +} + +GLenum +_cogl_texture_gl_get_format (CoglTexture *texture) +{ + return texture->vtable->get_gl_format (texture); +} diff --git a/cogl/cogl/driver/gl/cogl-util-gl-private.h b/cogl/cogl/driver/gl/cogl-util-gl-private.h new file mode 100644 index 0000000..1407e0f --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-util-gl-private.h @@ -0,0 +1,99 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012, 2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * Authors: + * Robert Bragg + */ + +#ifndef _COGL_UTIL_GL_PRIVATE_H_ + +#include "cogl-types.h" +#include "cogl-context.h" +#include "cogl-gl-header.h" +#include "cogl-texture.h" + +#ifdef COGL_GL_DEBUG + +const char * +_cogl_gl_error_to_string (GLenum error_code); + +#define GE(ctx, x) G_STMT_START { \ + GLenum __err; \ + (ctx)->x; \ + while ((__err = (ctx)->glGetError ()) != GL_NO_ERROR && __err != GL_CONTEXT_LOST) \ + { \ + g_warning ("%s: GL error (%d): %s\n", \ + G_STRLOC, \ + __err, \ + _cogl_gl_error_to_string (__err)); \ + } } G_STMT_END + +#define GE_RET(ret, ctx, x) G_STMT_START { \ + GLenum __err; \ + ret = (ctx)->x; \ + while ((__err = (ctx)->glGetError ()) != GL_NO_ERROR && __err != GL_CONTEXT_LOST) \ + { \ + g_warning ("%s: GL error (%d): %s\n", \ + G_STRLOC, \ + __err, \ + _cogl_gl_error_to_string (__err)); \ + } } G_STMT_END + +#else /* !COGL_GL_DEBUG */ + +#define GE(ctx, x) ((ctx)->x) +#define GE_RET(ret, ctx, x) (ret = ((ctx)->x)) + +#endif /* COGL_GL_DEBUG */ + +GLenum +_cogl_gl_util_get_error (CoglContext *ctx); + +void +_cogl_gl_util_clear_gl_errors (CoglContext *ctx); + +CoglBool +_cogl_gl_util_catch_out_of_memory (CoglContext *ctx, CoglError **error); + +void +_cogl_gl_util_get_texture_target_string (CoglTextureType texture_type, + const char **target_string_out, + const char **swizzle_out); + +/* Parses a GL version number stored in a string. @version_string must + * point to the beginning of the version number (ie, it can't point to + * the "OpenGL ES" part on GLES). The version number can be followed + * by the end of the string, a space or a full stop. Anything else + * will be treated as invalid. Returns TRUE and sets major_out and + * minor_out if it is succesfully parsed or FALSE otherwise. */ +CoglBool +_cogl_gl_util_parse_gl_version (const char *version_string, + int *major_out, + int *minor_out); + +#endif /* _COGL_UTIL_GL_PRIVATE_H_ */ diff --git a/cogl/cogl/driver/gl/cogl-util-gl.c b/cogl/cogl/driver/gl/cogl-util-gl.c new file mode 100644 index 0000000..25e4903 --- /dev/null +++ b/cogl/cogl/driver/gl/cogl-util-gl.c @@ -0,0 +1,206 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012, 2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-types.h" +#include "cogl-context-private.h" +#include "cogl-error-private.h" +#include "cogl-util-gl-private.h" + +#ifdef COGL_GL_DEBUG +/* GL error to string conversion */ +static const struct { + GLuint error_code; + const char *error_string; +} gl_errors[] = { + { GL_NO_ERROR, "No error" }, + { GL_INVALID_ENUM, "Invalid enumeration value" }, + { GL_INVALID_VALUE, "Invalid value" }, + { GL_INVALID_OPERATION, "Invalid operation" }, +#ifdef HAVE_COGL_GL + { GL_STACK_OVERFLOW, "Stack overflow" }, + { GL_STACK_UNDERFLOW, "Stack underflow" }, +#endif + { GL_OUT_OF_MEMORY, "Out of memory" }, + +#ifdef GL_INVALID_FRAMEBUFFER_OPERATION_EXT + { GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "Invalid framebuffer operation" } +#endif +}; + +static const unsigned int n_gl_errors = G_N_ELEMENTS (gl_errors); + +const char * +_cogl_gl_error_to_string (GLenum error_code) +{ + int i; + + for (i = 0; i < n_gl_errors; i++) + { + if (gl_errors[i].error_code == error_code) + return gl_errors[i].error_string; + } + + return "Unknown GL error"; +} +#endif /* COGL_GL_DEBUG */ + +GLenum +_cogl_gl_util_get_error (CoglContext *ctx) +{ + GLenum gl_error = ctx->glGetError (); + + if (gl_error != GL_NO_ERROR && gl_error != GL_CONTEXT_LOST) + return gl_error; + else + return GL_NO_ERROR; +} + +void +_cogl_gl_util_clear_gl_errors (CoglContext *ctx) +{ + GLenum gl_error; + + while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR && gl_error != GL_CONTEXT_LOST) + ; +} + +CoglBool +_cogl_gl_util_catch_out_of_memory (CoglContext *ctx, CoglError **error) +{ + GLenum gl_error; + CoglBool out_of_memory = FALSE; + + while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR && gl_error != GL_CONTEXT_LOST) + { + if (gl_error == GL_OUT_OF_MEMORY) + out_of_memory = TRUE; +#ifdef COGL_GL_DEBUG + else + { + g_warning ("%s: GL error (%d): %s\n", + G_STRLOC, + gl_error, + _cogl_gl_error_to_string (gl_error)); + } +#endif + } + + if (out_of_memory) + { + _cogl_set_error (error, COGL_SYSTEM_ERROR, + COGL_SYSTEM_ERROR_NO_MEMORY, + "Out of memory"); + return TRUE; + } + + return FALSE; +} + +void +_cogl_gl_util_get_texture_target_string (CoglTextureType texture_type, + const char **target_string_out, + const char **swizzle_out) +{ + const char *target_string, *tex_coord_swizzle; + + switch (texture_type) + { +#if 0 /* TODO */ + case COGL_TEXTURE_TYPE_1D: + target_string = "1D"; + tex_coord_swizzle = "s"; + break; +#endif + + case COGL_TEXTURE_TYPE_2D: + target_string = "2D"; + tex_coord_swizzle = "st"; + break; + + case COGL_TEXTURE_TYPE_3D: + target_string = "3D"; + tex_coord_swizzle = "stp"; + break; + + case COGL_TEXTURE_TYPE_RECTANGLE: + target_string = "2DRect"; + tex_coord_swizzle = "st"; + break; + + default: + target_string = "Unknown"; + tex_coord_swizzle = NULL; + g_assert_not_reached (); + } + + if (target_string_out) + *target_string_out = target_string; + if (swizzle_out) + *swizzle_out = tex_coord_swizzle; +} + +CoglBool +_cogl_gl_util_parse_gl_version (const char *version_string, + int *major_out, + int *minor_out) +{ + const char *major_end, *minor_end; + int major = 0, minor = 0; + + /* Extract the major number */ + for (major_end = version_string; *major_end >= '0' + && *major_end <= '9'; major_end++) + major = (major * 10) + *major_end - '0'; + /* If there were no digits or the major number isn't followed by a + dot then it is invalid */ + if (major_end == version_string || *major_end != '.') + return FALSE; + + /* Extract the minor number */ + for (minor_end = major_end + 1; *minor_end >= '0' + && *minor_end <= '9'; minor_end++) + minor = (minor * 10) + *minor_end - '0'; + /* If there were no digits or there is an unexpected character then + it is invalid */ + if (minor_end == major_end + 1 + || (*minor_end && *minor_end != ' ' && *minor_end != '.')) + return FALSE; + + *major_out = major; + *minor_out = minor; + + return TRUE; +} diff --git a/cogl/cogl/driver/gl/gl/cogl-driver-gl.c b/cogl/cogl/driver/gl/gl/cogl-driver-gl.c new file mode 100644 index 0000000..2b9a49c --- /dev/null +++ b/cogl/cogl/driver/gl/gl/cogl-driver-gl.c @@ -0,0 +1,699 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include + +#include "cogl-private.h" +#include "cogl-context-private.h" +#include "cogl-util-gl-private.h" +#include "cogl-feature-private.h" +#include "cogl-renderer-private.h" +#include "cogl-error-private.h" +#include "cogl-framebuffer-gl-private.h" +#include "cogl-texture-2d-gl-private.h" +#include "cogl-attribute-gl-private.h" +#include "cogl-clip-stack-gl-private.h" +#include "cogl-buffer-gl-private.h" + +static CoglBool +_cogl_driver_pixel_format_from_gl_internal (CoglContext *context, + GLenum gl_int_format, + CoglPixelFormat *out_format) +{ + /* It doesn't really matter we convert to exact same + format (some have no cogl match anyway) since format + is re-matched against cogl when getting or setting + texture image data. + */ + + switch (gl_int_format) + { + case GL_ALPHA: case GL_ALPHA4: case GL_ALPHA8: + case GL_ALPHA12: case GL_ALPHA16: + /* Cogl only supports one single-component texture so if we have + * ended up with a red texture then it is probably being used as + * a component-alpha texture */ + case GL_RED: + + *out_format = COGL_PIXEL_FORMAT_A_8; + return TRUE; + + case GL_LUMINANCE: case GL_LUMINANCE4: case GL_LUMINANCE8: + case GL_LUMINANCE12: case GL_LUMINANCE16: + + *out_format = COGL_PIXEL_FORMAT_G_8; + return TRUE; + + case GL_RG: + *out_format = COGL_PIXEL_FORMAT_RG_88; + return TRUE; + + case GL_RGB: case GL_RGB4: case GL_RGB5: case GL_RGB8: + case GL_RGB10: case GL_RGB12: case GL_RGB16: case GL_R3_G3_B2: + + *out_format = COGL_PIXEL_FORMAT_RGB_888; + return TRUE; + + case GL_RGBA: case GL_RGBA2: case GL_RGBA4: case GL_RGB5_A1: + case GL_RGBA8: case GL_RGB10_A2: case GL_RGBA12: case GL_RGBA16: + + *out_format = COGL_PIXEL_FORMAT_RGBA_8888; + return TRUE; + } + + return FALSE; +} + +static CoglPixelFormat +_cogl_driver_pixel_format_to_gl (CoglContext *context, + CoglPixelFormat format, + GLenum *out_glintformat, + GLenum *out_glformat, + GLenum *out_gltype) +{ + CoglPixelFormat required_format; + GLenum glintformat = 0; + GLenum glformat = 0; + GLenum gltype = 0; + + required_format = format; + + /* Find GL equivalents */ + switch (format) + { + case COGL_PIXEL_FORMAT_A_8: + /* If the driver doesn't natively support alpha textures then we + * will use a red component texture with a swizzle to implement + * the texture */ + if (_cogl_has_private_feature + (context, COGL_PRIVATE_FEATURE_ALPHA_TEXTURES) == 0) + { + glintformat = GL_RED; + glformat = GL_RED; + } + else + { + glintformat = GL_ALPHA; + glformat = GL_ALPHA; + } + gltype = GL_UNSIGNED_BYTE; + break; + case COGL_PIXEL_FORMAT_G_8: + glintformat = GL_LUMINANCE; + glformat = GL_LUMINANCE; + gltype = GL_UNSIGNED_BYTE; + break; + + case COGL_PIXEL_FORMAT_RG_88: + if (cogl_has_feature (context, COGL_FEATURE_ID_TEXTURE_RG)) + { + glintformat = GL_RG; + glformat = GL_RG; + } + else + { + /* If red-green textures aren't supported then we'll use RGB + * as an internal format. Note this should only end up + * mattering for downloading the data because Cogl will + * refuse to allocate a texture with RG components if RG + * textures aren't supported */ + glintformat = GL_RGB; + glformat = GL_RGB; + required_format = COGL_PIXEL_FORMAT_RGB_888; + } + gltype = GL_UNSIGNED_BYTE; + break; + + case COGL_PIXEL_FORMAT_RGB_888: + glintformat = GL_RGB; + glformat = GL_RGB; + gltype = GL_UNSIGNED_BYTE; + break; + case COGL_PIXEL_FORMAT_BGR_888: + glintformat = GL_RGB; + glformat = GL_BGR; + gltype = GL_UNSIGNED_BYTE; + break; + case COGL_PIXEL_FORMAT_RGBA_8888: + case COGL_PIXEL_FORMAT_RGBA_8888_PRE: + glintformat = GL_RGBA; + glformat = GL_RGBA; + gltype = GL_UNSIGNED_BYTE; + break; + case COGL_PIXEL_FORMAT_BGRA_8888: + case COGL_PIXEL_FORMAT_BGRA_8888_PRE: + glintformat = GL_RGBA; + glformat = GL_BGRA; + gltype = GL_UNSIGNED_BYTE; + break; + + /* The following two types of channel ordering + * have no GL equivalent unless defined using + * system word byte ordering */ + case COGL_PIXEL_FORMAT_ARGB_8888: + case COGL_PIXEL_FORMAT_ARGB_8888_PRE: + glintformat = GL_RGBA; + glformat = GL_BGRA; +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + gltype = GL_UNSIGNED_INT_8_8_8_8; +#else + gltype = GL_UNSIGNED_INT_8_8_8_8_REV; +#endif + break; + + case COGL_PIXEL_FORMAT_ABGR_8888: + case COGL_PIXEL_FORMAT_ABGR_8888_PRE: + glintformat = GL_RGBA; + glformat = GL_RGBA; +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + gltype = GL_UNSIGNED_INT_8_8_8_8; +#else + gltype = GL_UNSIGNED_INT_8_8_8_8_REV; +#endif + break; + + case COGL_PIXEL_FORMAT_RGBA_1010102: + case COGL_PIXEL_FORMAT_RGBA_1010102_PRE: + glintformat = GL_RGBA; + glformat = GL_RGBA; + gltype = GL_UNSIGNED_INT_10_10_10_2; + break; + + case COGL_PIXEL_FORMAT_BGRA_1010102: + case COGL_PIXEL_FORMAT_BGRA_1010102_PRE: + glintformat = GL_RGBA; + glformat = GL_BGRA; + gltype = GL_UNSIGNED_INT_10_10_10_2; + break; + + case COGL_PIXEL_FORMAT_ABGR_2101010: + case COGL_PIXEL_FORMAT_ABGR_2101010_PRE: + glintformat = GL_RGBA; + glformat = GL_RGBA; + gltype = GL_UNSIGNED_INT_2_10_10_10_REV; + break; + + case COGL_PIXEL_FORMAT_ARGB_2101010: + case COGL_PIXEL_FORMAT_ARGB_2101010_PRE: + glintformat = GL_RGBA; + glformat = GL_BGRA; + gltype = GL_UNSIGNED_INT_2_10_10_10_REV; + break; + + /* The following three types of channel ordering + * are always defined using system word byte + * ordering (even according to GLES spec) */ + case COGL_PIXEL_FORMAT_RGB_565: + glintformat = GL_RGB; + glformat = GL_RGB; + gltype = GL_UNSIGNED_SHORT_5_6_5; + break; + case COGL_PIXEL_FORMAT_RGBA_4444: + case COGL_PIXEL_FORMAT_RGBA_4444_PRE: + glintformat = GL_RGBA; + glformat = GL_RGBA; + gltype = GL_UNSIGNED_SHORT_4_4_4_4; + break; + case COGL_PIXEL_FORMAT_RGBA_5551: + case COGL_PIXEL_FORMAT_RGBA_5551_PRE: + glintformat = GL_RGBA; + glformat = GL_RGBA; + gltype = GL_UNSIGNED_SHORT_5_5_5_1; + break; + + case COGL_PIXEL_FORMAT_DEPTH_16: + glintformat = GL_DEPTH_COMPONENT16; + glformat = GL_DEPTH_COMPONENT; + gltype = GL_UNSIGNED_SHORT; + break; + case COGL_PIXEL_FORMAT_DEPTH_32: + glintformat = GL_DEPTH_COMPONENT32; + glformat = GL_DEPTH_COMPONENT; + gltype = GL_UNSIGNED_INT; + break; + + case COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8: + glintformat = GL_DEPTH_STENCIL; + glformat = GL_DEPTH_STENCIL; + gltype = GL_UNSIGNED_INT_24_8; + break; + + case COGL_PIXEL_FORMAT_ANY: + case COGL_PIXEL_FORMAT_YUV: + g_assert_not_reached (); + break; + } + + /* All of the pixel formats are handled above so if this hits then + we've been given an invalid pixel format */ + g_assert (glformat != 0); + + if (out_glintformat != NULL) + *out_glintformat = glintformat; + if (out_glformat != NULL) + *out_glformat = glformat; + if (out_gltype != NULL) + *out_gltype = gltype; + + return required_format; +} + +static CoglBool +_cogl_get_gl_version (CoglContext *ctx, + int *major_out, + int *minor_out) +{ + const char *version_string; + + /* Get the OpenGL version number */ + if ((version_string = _cogl_context_get_gl_version (ctx)) == NULL) + return FALSE; + + return _cogl_gl_util_parse_gl_version (version_string, major_out, minor_out); +} + +static CoglBool +check_gl_version (CoglContext *ctx, + char **gl_extensions, + CoglError **error) +{ + int major, minor; + + if (!_cogl_get_gl_version (ctx, &major, &minor)) + { + _cogl_set_error (error, + COGL_DRIVER_ERROR, + COGL_DRIVER_ERROR_UNKNOWN_VERSION, + "The OpenGL version could not be determined"); + return FALSE; + } + + /* GL 1.3 supports all of the required functionality in core */ + if (COGL_CHECK_GL_VERSION (major, minor, 1, 3)) + return TRUE; + + /* OpenGL 1.2 is only supported if we have the multitexturing + extension */ + if (!_cogl_check_extension ("GL_ARB_multitexture", gl_extensions)) + { + _cogl_set_error (error, + COGL_DRIVER_ERROR, + COGL_DRIVER_ERROR_INVALID_VERSION, + "The OpenGL driver is missing " + "the GL_ARB_multitexture extension"); + return FALSE; + } + + /* OpenGL 1.2 is required */ + if (!COGL_CHECK_GL_VERSION (major, minor, 1, 2)) + { + _cogl_set_error (error, + COGL_DRIVER_ERROR, + COGL_DRIVER_ERROR_INVALID_VERSION, + "The OpenGL version of your driver (%i.%i) " + "is not compatible with Cogl", + major, minor); + return FALSE; + } + + return TRUE; +} + +static CoglBool +_cogl_driver_update_features (CoglContext *ctx, + CoglError **error) +{ + CoglFeatureFlags flags = 0; + unsigned long private_features + [COGL_FLAGS_N_LONGS_FOR_SIZE (COGL_N_PRIVATE_FEATURES)] = { 0 }; + char **gl_extensions; + int gl_major = 0, gl_minor = 0; + int i; + + /* We have to special case getting the pointer to the glGetString* + functions because we need to use them to determine what functions + we can expect */ + ctx->glGetString = + (void *) _cogl_renderer_get_proc_address (ctx->display->renderer, + "glGetString", + TRUE); + ctx->glGetStringi = + (void *) _cogl_renderer_get_proc_address (ctx->display->renderer, + "glGetStringi", + TRUE); + ctx->glGetIntegerv = + (void *) _cogl_renderer_get_proc_address (ctx->display->renderer, + "glGetIntegerv", + TRUE); + + gl_extensions = _cogl_context_get_gl_extensions (ctx); + + if (!check_gl_version (ctx, gl_extensions, error)) + return FALSE; + + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_WINSYS))) + { + char *all_extensions = g_strjoinv (" ", gl_extensions); + + COGL_NOTE (WINSYS, + "Checking features\n" + " GL_VENDOR: %s\n" + " GL_RENDERER: %s\n" + " GL_VERSION: %s\n" + " GL_EXTENSIONS: %s", + ctx->glGetString (GL_VENDOR), + ctx->glGetString (GL_RENDERER), + _cogl_context_get_gl_version (ctx), + all_extensions); + + g_free (all_extensions); + } + + _cogl_get_gl_version (ctx, &gl_major, &gl_minor); + + _cogl_gpu_info_init (ctx, &ctx->gpu); + + ctx->glsl_major = 1; + ctx->glsl_minor = 1; + + if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 2, 0)) + { + const char *glsl_version = + (char *)ctx->glGetString (GL_SHADING_LANGUAGE_VERSION); + _cogl_gl_util_parse_gl_version (glsl_version, + &ctx->glsl_major, + &ctx->glsl_minor); + } + + if (COGL_CHECK_GL_VERSION (ctx->glsl_major, ctx->glsl_minor, 1, 2)) + /* We want to use version 120 if it is available so that the + * gl_PointCoord can be used. */ + ctx->glsl_version_to_use = 120; + else + ctx->glsl_version_to_use = 110; + + flags = (COGL_FEATURE_TEXTURE_READ_PIXELS + | COGL_FEATURE_UNSIGNED_INT_INDICES + | COGL_FEATURE_DEPTH_RANGE); + COGL_FLAGS_SET (ctx->features, + COGL_FEATURE_ID_UNSIGNED_INT_INDICES, TRUE); + COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_DEPTH_RANGE, TRUE); + + if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 1, 4)) + COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_MIRRORED_REPEAT, TRUE); + + _cogl_feature_check_ext_functions (ctx, + gl_major, + gl_minor, + gl_extensions); + + if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 2, 0) || + _cogl_check_extension ("GL_ARB_texture_non_power_of_two", gl_extensions)) + { + flags |= COGL_FEATURE_TEXTURE_NPOT + | COGL_FEATURE_TEXTURE_NPOT_BASIC + | COGL_FEATURE_TEXTURE_NPOT_MIPMAP + | COGL_FEATURE_TEXTURE_NPOT_REPEAT; + COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_TEXTURE_NPOT, TRUE); + COGL_FLAGS_SET (ctx->features, + COGL_FEATURE_ID_TEXTURE_NPOT_BASIC, TRUE); + COGL_FLAGS_SET (ctx->features, + COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP, TRUE); + COGL_FLAGS_SET (ctx->features, + COGL_FEATURE_ID_TEXTURE_NPOT_REPEAT, TRUE); + } + + if (_cogl_check_extension ("GL_MESA_pack_invert", gl_extensions)) + COGL_FLAGS_SET (private_features, + COGL_PRIVATE_FEATURE_MESA_PACK_INVERT, TRUE); + + if (ctx->glGenRenderbuffers) + { + flags |= COGL_FEATURE_OFFSCREEN; + COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_OFFSCREEN, TRUE); + COGL_FLAGS_SET (private_features, + COGL_PRIVATE_FEATURE_QUERY_FRAMEBUFFER_BITS, + TRUE); + } + + if (ctx->glBlitFramebuffer) + COGL_FLAGS_SET (private_features, + COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT, TRUE); + + if (ctx->glRenderbufferStorageMultisampleIMG) + { + flags |= COGL_FEATURE_OFFSCREEN_MULTISAMPLE; + COGL_FLAGS_SET (ctx->features, + COGL_FEATURE_ID_OFFSCREEN_MULTISAMPLE, TRUE); + } + + if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 3, 0) || + _cogl_check_extension ("GL_ARB_depth_texture", gl_extensions)) + { + flags |= COGL_FEATURE_DEPTH_TEXTURE; + COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_DEPTH_TEXTURE, TRUE); + } + + if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 2, 1) || + _cogl_check_extension ("GL_EXT_pixel_buffer_object", gl_extensions)) + COGL_FLAGS_SET (private_features, COGL_PRIVATE_FEATURE_PBOS, TRUE); + + if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 1, 4) || + _cogl_check_extension ("GL_EXT_blend_color", gl_extensions)) + COGL_FLAGS_SET (private_features, + COGL_PRIVATE_FEATURE_BLEND_CONSTANT, TRUE); + + if (ctx->glGenPrograms) + { + flags |= COGL_FEATURE_SHADERS_ARBFP; + COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_ARBFP, TRUE); + } + + if (ctx->glCreateProgram) + { + flags |= COGL_FEATURE_SHADERS_GLSL; + COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_GLSL, TRUE); + } + else + { + /* If all of the old GLSL extensions are available then we can fake + * the GL 2.0 GLSL support by diverting to the old function names */ + if (ctx->glCreateProgramObject && /* GL_ARB_shader_objects */ + ctx->glVertexAttribPointer && /* GL_ARB_vertex_shader */ + _cogl_check_extension ("GL_ARB_fragment_shader", gl_extensions)) + { + ctx->glCreateShader = ctx->glCreateShaderObject; + ctx->glCreateProgram = ctx->glCreateProgramObject; + ctx->glDeleteShader = ctx->glDeleteObject; + ctx->glDeleteProgram = ctx->glDeleteObject; + ctx->glAttachShader = ctx->glAttachObject; + ctx->glUseProgram = ctx->glUseProgramObject; + ctx->glGetProgramInfoLog = ctx->glGetInfoLog; + ctx->glGetShaderInfoLog = ctx->glGetInfoLog; + ctx->glGetShaderiv = ctx->glGetObjectParameteriv; + ctx->glGetProgramiv = ctx->glGetObjectParameteriv; + ctx->glDetachShader = ctx->glDetachObject; + ctx->glGetAttachedShaders = ctx->glGetAttachedObjects; + /* FIXME: there doesn't seem to be an equivalent for glIsShader + * and glIsProgram. This doesn't matter for now because Cogl + * doesn't use these but if we add support for simulating a + * GLES2 context on top of regular GL then we'll need to do + * something here */ + + flags |= COGL_FEATURE_SHADERS_GLSL; + COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_GLSL, TRUE); + } + } + + if ((COGL_CHECK_GL_VERSION (gl_major, gl_minor, 2, 0) || + _cogl_check_extension ("GL_ARB_point_sprite", gl_extensions)) && + + /* If GLSL is supported then we only enable point sprite support + * too if we have glsl >= 1.2 otherwise we don't have the + * gl_PointCoord builtin which we depend on in the glsl backend. + */ + (!COGL_FLAGS_GET (ctx->features, COGL_FEATURE_ID_GLSL) || + COGL_CHECK_GL_VERSION (ctx->glsl_major, ctx->glsl_minor, 1, 2))) + { + flags |= COGL_FEATURE_POINT_SPRITE; + COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_POINT_SPRITE, TRUE); + } + + if (ctx->glGenBuffers) + { + COGL_FLAGS_SET (private_features, COGL_PRIVATE_FEATURE_VBOS, TRUE); + flags |= (COGL_FEATURE_MAP_BUFFER_FOR_READ | + COGL_FEATURE_MAP_BUFFER_FOR_WRITE); + COGL_FLAGS_SET (ctx->features, + COGL_FEATURE_ID_MAP_BUFFER_FOR_READ, TRUE); + COGL_FLAGS_SET (ctx->features, + COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE, TRUE); + } + + if (_cogl_check_extension ("GL_ARB_texture_rectangle", gl_extensions)) + { + flags |= COGL_FEATURE_TEXTURE_RECTANGLE; + COGL_FLAGS_SET (ctx->features, + COGL_FEATURE_ID_TEXTURE_RECTANGLE, TRUE); + } + + if (ctx->glTexImage3D) + { + flags |= COGL_FEATURE_TEXTURE_3D; + COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_TEXTURE_3D, TRUE); + } + + if (ctx->glEGLImageTargetTexture2D) + COGL_FLAGS_SET (private_features, + COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE, TRUE); + + if (_cogl_check_extension ("GL_EXT_packed_depth_stencil", gl_extensions)) + COGL_FLAGS_SET (private_features, + COGL_PRIVATE_FEATURE_EXT_PACKED_DEPTH_STENCIL, TRUE); + + if (ctx->glGenSamplers) + COGL_FLAGS_SET (private_features, + COGL_PRIVATE_FEATURE_SAMPLER_OBJECTS, TRUE); + + if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 3, 3) || + _cogl_check_extension ("GL_ARB_texture_swizzle", gl_extensions) || + _cogl_check_extension ("GL_EXT_texture_swizzle", gl_extensions)) + COGL_FLAGS_SET (private_features, + COGL_PRIVATE_FEATURE_TEXTURE_SWIZZLE, TRUE); + + /* The per-vertex point size is only available via GLSL with the + * gl_PointSize builtin. This is only available in GL 2.0 (not the + * GLSL extensions) */ + if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 2, 0)) + { + COGL_FLAGS_SET (ctx->features, + COGL_FEATURE_ID_PER_VERTEX_POINT_SIZE, + TRUE); + COGL_FLAGS_SET (private_features, + COGL_PRIVATE_FEATURE_ENABLE_PROGRAM_POINT_SIZE, TRUE); + } + + if (ctx->driver == COGL_DRIVER_GL) + { + int max_clip_planes = 0; + + /* Features which are not available in GL 3 */ + COGL_FLAGS_SET (private_features, COGL_PRIVATE_FEATURE_GL_FIXED, TRUE); + COGL_FLAGS_SET (private_features, COGL_PRIVATE_FEATURE_ALPHA_TEST, TRUE); + COGL_FLAGS_SET (private_features, COGL_PRIVATE_FEATURE_QUADS, TRUE); + COGL_FLAGS_SET (private_features, + COGL_PRIVATE_FEATURE_ALPHA_TEXTURES, TRUE); + + GE( ctx, glGetIntegerv (GL_MAX_CLIP_PLANES, &max_clip_planes) ); + if (max_clip_planes >= 4) + COGL_FLAGS_SET (private_features, + COGL_PRIVATE_FEATURE_FOUR_CLIP_PLANES, TRUE); + } + + COGL_FLAGS_SET (private_features, + COGL_PRIVATE_FEATURE_READ_PIXELS_ANY_FORMAT, TRUE); + COGL_FLAGS_SET (private_features, COGL_PRIVATE_FEATURE_ANY_GL, TRUE); + COGL_FLAGS_SET (private_features, + COGL_PRIVATE_FEATURE_FORMAT_CONVERSION, TRUE); + COGL_FLAGS_SET (private_features, COGL_PRIVATE_FEATURE_BLEND_CONSTANT, TRUE); + COGL_FLAGS_SET (private_features, + COGL_PRIVATE_FEATURE_BUILTIN_POINT_SIZE_UNIFORM, TRUE); + COGL_FLAGS_SET (private_features, + COGL_PRIVATE_FEATURE_QUERY_TEXTURE_PARAMETERS, TRUE); + COGL_FLAGS_SET (private_features, + COGL_PRIVATE_FEATURE_TEXTURE_MAX_LEVEL, TRUE); + + if (ctx->glFenceSync) + COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_FENCE, TRUE); + + if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 3, 0) || + _cogl_check_extension ("GL_ARB_texture_rg", gl_extensions)) + COGL_FLAGS_SET (ctx->features, + COGL_FEATURE_ID_TEXTURE_RG, + TRUE); + + /* Cache features */ + for (i = 0; i < G_N_ELEMENTS (private_features); i++) + ctx->private_features[i] |= private_features[i]; + ctx->feature_flags |= flags; + + g_strfreev (gl_extensions); + + if (!COGL_FLAGS_GET (private_features, COGL_PRIVATE_FEATURE_ALPHA_TEXTURES) && + !COGL_FLAGS_GET (private_features, COGL_PRIVATE_FEATURE_TEXTURE_SWIZZLE)) + { + _cogl_set_error (error, + COGL_DRIVER_ERROR, + COGL_DRIVER_ERROR_NO_SUITABLE_DRIVER_FOUND, + "The GL_ARB_texture_swizzle extension is required " + "to use the GL3 driver"); + return FALSE; + } + + return TRUE; +} + +const CoglDriverVtable +_cogl_driver_gl = + { + _cogl_driver_pixel_format_from_gl_internal, + _cogl_driver_pixel_format_to_gl, + _cogl_driver_update_features, + _cogl_offscreen_gl_allocate, + _cogl_offscreen_gl_free, + _cogl_framebuffer_gl_flush_state, + _cogl_framebuffer_gl_clear, + _cogl_framebuffer_gl_query_bits, + _cogl_framebuffer_gl_finish, + _cogl_framebuffer_gl_discard_buffers, + _cogl_framebuffer_gl_draw_attributes, + _cogl_framebuffer_gl_draw_indexed_attributes, + _cogl_framebuffer_gl_read_pixels_into_bitmap, + _cogl_texture_2d_gl_free, + _cogl_texture_2d_gl_can_create, + _cogl_texture_2d_gl_init, + _cogl_texture_2d_gl_allocate, + _cogl_texture_2d_gl_copy_from_framebuffer, + _cogl_texture_2d_gl_get_gl_handle, + _cogl_texture_2d_gl_generate_mipmap, + _cogl_texture_2d_gl_copy_from_bitmap, + _cogl_texture_2d_gl_get_data, + _cogl_gl_flush_attributes_state, + _cogl_clip_stack_gl_flush, + _cogl_buffer_gl_create, + _cogl_buffer_gl_destroy, + _cogl_buffer_gl_map_range, + _cogl_buffer_gl_unmap, + _cogl_buffer_gl_set_data, + }; diff --git a/cogl/cogl/driver/gl/gl/cogl-pipeline-fragend-arbfp-private.h b/cogl/cogl/driver/gl/gl/cogl-pipeline-fragend-arbfp-private.h new file mode 100644 index 0000000..f054aad --- /dev/null +++ b/cogl/cogl/driver/gl/gl/cogl-pipeline-fragend-arbfp-private.h @@ -0,0 +1,42 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef __COGL_PIPELINE_FRAGEND_ARBFP_PRIVATE_H +#define __COGL_PIPELINE_FRAGEND_ARBFP_PRIVATE_H + +#include "cogl-pipeline-private.h" + +extern const CoglPipelineFragend _cogl_pipeline_arbfp_fragend; + +#endif /* __COGL_PIPELINE_ARBFP_PRIVATE_H */ + diff --git a/cogl/cogl/driver/gl/gl/cogl-pipeline-fragend-arbfp.c b/cogl/cogl/driver/gl/gl/cogl-pipeline-fragend-arbfp.c new file mode 100644 index 0000000..96ab3a3 --- /dev/null +++ b/cogl/cogl/driver/gl/gl/cogl-pipeline-fragend-arbfp.c @@ -0,0 +1,988 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-debug.h" +#include "cogl-context-private.h" +#include "cogl-util-gl-private.h" +#include "cogl-pipeline-private.h" +#include "cogl-pipeline-state-private.h" +#include "cogl-pipeline-layer-private.h" + +#ifdef COGL_PIPELINE_FRAGEND_ARBFP + +#include "cogl-context-private.h" +#include "cogl-object-private.h" + +#include "cogl-texture-private.h" +#include "cogl-blend-string.h" +#include "cogl-journal-private.h" +#include "cogl-color-private.h" +#include "cogl-profile.h" +#include "cogl-program-private.h" + +#include +#include +#include + +/* This might not be defined on GLES */ +#ifndef GL_TEXTURE_3D +#define GL_TEXTURE_3D 0x806F +#endif + +const CoglPipelineFragend _cogl_pipeline_arbfp_fragend; + +typedef struct _UnitState +{ + int constant_id; /* The program.local[] index */ + unsigned int dirty_combine_constant:1; + unsigned int has_combine_constant:1; + + unsigned int sampled:1; +} UnitState; + +typedef struct +{ + int ref_count; + + CoglHandle user_program; + /* XXX: only valid during codegen */ + GString *source; + GLuint gl_program; + UnitState *unit_state; + int next_constant_id; + + /* Age of the program the last time the uniforms were flushed. This + is used to detect when we need to flush all of the uniforms */ + unsigned int user_program_age; + + /* We need to track the last pipeline that an ARBfp program was used + * with so know if we need to update any program.local parameters. */ + CoglPipeline *last_used_for_pipeline; + + CoglPipelineCacheEntry *cache_entry; +} CoglPipelineShaderState; + +static CoglUserDataKey shader_state_key; + +static CoglPipelineShaderState * +shader_state_new (int n_layers, + CoglPipelineCacheEntry *cache_entry) +{ + CoglPipelineShaderState *shader_state; + + shader_state = g_slice_new0 (CoglPipelineShaderState); + shader_state->ref_count = 1; + shader_state->unit_state = g_new0 (UnitState, n_layers); + shader_state->cache_entry = cache_entry; + + return shader_state; +} + +static CoglPipelineShaderState * +get_shader_state (CoglPipeline *pipeline) +{ + return cogl_object_get_user_data (COGL_OBJECT (pipeline), &shader_state_key); +} + +static void +destroy_shader_state (void *user_data, + void *instance) +{ + CoglPipelineShaderState *shader_state = user_data; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + /* If the shader state was last used for this pipeline then clear it + so that if same address gets used again for a new pipeline then + we won't think it's the same pipeline and avoid updating the + constants */ + if (shader_state->last_used_for_pipeline == instance) + shader_state->last_used_for_pipeline = NULL; + + if (shader_state->cache_entry && + shader_state->cache_entry->pipeline != instance) + shader_state->cache_entry->usage_count--; + + if (--shader_state->ref_count == 0) + { + if (shader_state->gl_program) + { + GE (ctx, glDeletePrograms (1, &shader_state->gl_program)); + shader_state->gl_program = 0; + } + + g_free (shader_state->unit_state); + + g_slice_free (CoglPipelineShaderState, shader_state); + } +} + +static void +set_shader_state (CoglPipeline *pipeline, CoglPipelineShaderState *shader_state) +{ + if (shader_state) + { + shader_state->ref_count++; + + /* If we're not setting the state on the template pipeline then + * mark it as a usage of the pipeline cache entry */ + if (shader_state->cache_entry && + shader_state->cache_entry->pipeline != pipeline) + shader_state->cache_entry->usage_count++; + } + + _cogl_object_set_user_data (COGL_OBJECT (pipeline), + &shader_state_key, + shader_state, + destroy_shader_state); +} + +static void +dirty_shader_state (CoglPipeline *pipeline) +{ + cogl_object_set_user_data (COGL_OBJECT (pipeline), + &shader_state_key, + NULL, + NULL); +} + +static void +_cogl_pipeline_fragend_arbfp_start (CoglPipeline *pipeline, + int n_layers, + unsigned long pipelines_difference) +{ + CoglPipelineShaderState *shader_state; + CoglPipeline *authority; + CoglPipelineCacheEntry *cache_entry = NULL; + CoglProgram *user_program = cogl_pipeline_get_user_program (pipeline); + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + /* Now lookup our ARBfp backend private state */ + shader_state = get_shader_state (pipeline); + + /* If we have a valid shader_state then we are all set and don't + * need to generate a new program. */ + if (shader_state) + return; + + /* If we don't have an associated arbfp program yet then find the + * arbfp-authority (the oldest ancestor whose state will result in + * the same program being generated as for this pipeline). + * + * We always make sure to associate new programs with the + * arbfp-authority to maximize the chance that other pipelines can + * share it. + */ + authority = _cogl_pipeline_find_equivalent_parent + (pipeline, + _cogl_pipeline_get_state_for_fragment_codegen (ctx) & + ~COGL_PIPELINE_STATE_LAYERS, + _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx)); + shader_state = get_shader_state (authority); + if (shader_state) + { + /* If we are going to share our program state with an arbfp-authority + * then add a reference to the program state associated with that + * arbfp-authority... */ + set_shader_state (pipeline, shader_state); + return; + } + + /* If we haven't yet found an existing program then before we resort to + * generating a new arbfp program we see if we can find a suitable + * program in the pipeline_cache. */ + if (G_LIKELY (!(COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_PROGRAM_CACHES)))) + { + cache_entry = + _cogl_pipeline_cache_get_fragment_template (ctx->pipeline_cache, + authority); + + shader_state = get_shader_state (cache_entry->pipeline); + + if (shader_state) + shader_state->ref_count++; + } + + /* If we still haven't got a shader state then we'll have to create + a new one */ + if (shader_state == NULL) + { + shader_state = shader_state_new (n_layers, cache_entry); + + shader_state->user_program = user_program; + if (user_program == COGL_INVALID_HANDLE) + { + /* We reuse a single grow-only GString for code-gen */ + g_string_set_size (ctx->codegen_source_buffer, 0); + shader_state->source = ctx->codegen_source_buffer; + g_string_append (shader_state->source, + "!!ARBfp1.0\n" + "TEMP output;\n" + "TEMP tmp0, tmp1, tmp2, tmp3, tmp4;\n" + "PARAM half = {.5, .5, .5, .5};\n" + "PARAM one = {1, 1, 1, 1};\n" + "PARAM two = {2, 2, 2, 2};\n" + "PARAM minus_one = {-1, -1, -1, -1};\n"); + } + } + + set_shader_state (pipeline, shader_state); + + shader_state->ref_count--; + + /* Since we have already resolved the arbfp-authority at this point + * we might as well also associate any program we find from the cache + * with the authority too... */ + if (authority != pipeline) + set_shader_state (authority, shader_state); + + /* If we found a template then we'll attach it to that too so that + next time a similar pipeline is used it can use the same state */ + if (cache_entry) + set_shader_state (cache_entry->pipeline, shader_state); +} + +static const char * +texture_type_to_arbfp_string (CoglTextureType texture_type) +{ + switch (texture_type) + { +#if 0 /* TODO */ + case COGL_TEXTURE_TYPE_1D: + return "1D"; +#endif + case COGL_TEXTURE_TYPE_2D: + return "2D"; + case COGL_TEXTURE_TYPE_3D: + return "3D"; + case COGL_TEXTURE_TYPE_RECTANGLE: + return "RECT"; + } + + g_warn_if_reached (); + + return "2D"; +} + +static void +setup_texture_source (CoglPipelineShaderState *shader_state, + int unit_index, + CoglTextureType texture_type) +{ + if (!shader_state->unit_state[unit_index].sampled) + { + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_TEXTURING))) + g_string_append_printf (shader_state->source, + "TEMP texel%d;\n" + "MOV texel%d, one;\n", + unit_index, + unit_index); + else + g_string_append_printf (shader_state->source, + "TEMP texel%d;\n" + "TEX texel%d,fragment.texcoord[%d]," + "texture[%d],%s;\n", + unit_index, + unit_index, + unit_index, + unit_index, + texture_type_to_arbfp_string (texture_type)); + shader_state->unit_state[unit_index].sampled = TRUE; + } +} + +typedef enum _CoglPipelineFragendARBfpArgType +{ + COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_SIMPLE, + COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_CONSTANT, + COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_TEXTURE +} CoglPipelineFragendARBfpArgType; + +typedef struct _CoglPipelineFragendARBfpArg +{ + const char *name; + + CoglPipelineFragendARBfpArgType type; + + /* for type = TEXTURE */ + int texture_unit; + CoglTextureType texture_type; + + /* for type = CONSTANT */ + int constant_id; + + const char *swizzle; + +} CoglPipelineFragendARBfpArg; + +static void +append_arg (GString *source, const CoglPipelineFragendARBfpArg *arg) +{ + switch (arg->type) + { + case COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_TEXTURE: + g_string_append_printf (source, "texel%d%s", + arg->texture_unit, arg->swizzle); + break; + case COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_CONSTANT: + g_string_append_printf (source, "program.local[%d]%s", + arg->constant_id, arg->swizzle); + break; + case COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_SIMPLE: + g_string_append_printf (source, "%s%s", + arg->name, arg->swizzle); + break; + } +} + +/* Note: we are trying to avoid duplicating strings during codegen + * which is why we have the slightly awkward + * CoglPipelineFragendARBfpArg mechanism. */ +static void +setup_arg (CoglPipeline *pipeline, + CoglPipelineLayer *layer, + CoglBlendStringChannelMask mask, + int arg_index, + CoglPipelineCombineSource src, + GLint op, + CoglPipelineFragendARBfpArg *arg) +{ + CoglPipelineShaderState *shader_state = get_shader_state (pipeline); + static const char *tmp_name[3] = { "tmp0", "tmp1", "tmp2" }; + + switch (src) + { + case COGL_PIPELINE_COMBINE_SOURCE_TEXTURE: + arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_TEXTURE; + arg->name = "texel%d"; + arg->texture_unit = _cogl_pipeline_layer_get_unit_index (layer); + setup_texture_source (shader_state, + arg->texture_unit, + _cogl_pipeline_layer_get_texture_type (layer)); + break; + case COGL_PIPELINE_COMBINE_SOURCE_CONSTANT: + { + int unit_index = _cogl_pipeline_layer_get_unit_index (layer); + UnitState *unit_state = &shader_state->unit_state[unit_index]; + + unit_state->constant_id = shader_state->next_constant_id++; + unit_state->has_combine_constant = TRUE; + unit_state->dirty_combine_constant = TRUE; + + arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_CONSTANT; + arg->name = "program.local[%d]"; + arg->constant_id = unit_state->constant_id; + break; + } + case COGL_PIPELINE_COMBINE_SOURCE_PRIMARY_COLOR: + arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_SIMPLE; + arg->name = "fragment.color.primary"; + break; + case COGL_PIPELINE_COMBINE_SOURCE_PREVIOUS: + arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_SIMPLE; + if (_cogl_pipeline_layer_get_unit_index (layer) == 0) + arg->name = "fragment.color.primary"; + else + arg->name = "output"; + break; + default: /* Sample the texture attached to a specific layer */ + { + int layer_num = src - COGL_PIPELINE_COMBINE_SOURCE_TEXTURE0; + CoglPipelineGetLayerFlags flags = COGL_PIPELINE_GET_LAYER_NO_CREATE; + CoglPipelineLayer *other_layer = + _cogl_pipeline_get_layer_with_flags (pipeline, layer_num, flags); + + if (other_layer == NULL) + { + static CoglBool warning_seen = FALSE; + if (!warning_seen) + { + g_warning ("The application is trying to use a texture " + "combine with a layer number that does not exist"); + warning_seen = TRUE; + } + arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_SIMPLE; + arg->name = "output"; + } + else + { + CoglTextureType texture_type; + + arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_TEXTURE; + arg->name = "texture[%d]"; + arg->texture_unit = + _cogl_pipeline_layer_get_unit_index (other_layer); + texture_type = _cogl_pipeline_layer_get_texture_type (other_layer); + setup_texture_source (shader_state, + arg->texture_unit, + texture_type); + } + } + break; + } + + arg->swizzle = ""; + + switch (op) + { + case COGL_PIPELINE_COMBINE_OP_SRC_COLOR: + break; + case COGL_PIPELINE_COMBINE_OP_ONE_MINUS_SRC_COLOR: + g_string_append_printf (shader_state->source, + "SUB tmp%d, one, ", + arg_index); + append_arg (shader_state->source, arg); + g_string_append_printf (shader_state->source, ";\n"); + arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_SIMPLE; + arg->name = tmp_name[arg_index]; + arg->swizzle = ""; + break; + case COGL_PIPELINE_COMBINE_OP_SRC_ALPHA: + /* avoid a swizzle if we know RGB are going to be masked + * in the end anyway */ + if (mask != COGL_BLEND_STRING_CHANNEL_MASK_ALPHA) + arg->swizzle = ".a"; + break; + case COGL_PIPELINE_COMBINE_OP_ONE_MINUS_SRC_ALPHA: + g_string_append_printf (shader_state->source, + "SUB tmp%d, one, ", + arg_index); + append_arg (shader_state->source, arg); + /* avoid a swizzle if we know RGB are going to be masked + * in the end anyway */ + if (mask != COGL_BLEND_STRING_CHANNEL_MASK_ALPHA) + g_string_append_printf (shader_state->source, ".a;\n"); + else + g_string_append_printf (shader_state->source, ";\n"); + arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_SIMPLE; + arg->name = tmp_name[arg_index]; + break; + default: + g_error ("Unknown texture combine operator %d", op); + break; + } +} + +static CoglBool +fragend_arbfp_args_equal (CoglPipelineFragendARBfpArg *arg0, + CoglPipelineFragendARBfpArg *arg1) +{ + if (arg0->type != arg1->type) + return FALSE; + + if (arg0->name != arg1->name && + strcmp (arg0->name, arg1->name) != 0) + return FALSE; + + if (arg0->type == COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_TEXTURE && + arg0->texture_unit != arg1->texture_unit) + return FALSE; + /* Note we don't have to check the target; a texture unit can only + * have one target enabled at a time. */ + + if (arg0->type == COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_CONSTANT && + arg0->constant_id != arg1->constant_id) + return FALSE; + + if (arg0->swizzle != arg1->swizzle && + strcmp (arg0->swizzle, arg1->swizzle) != 0) + return FALSE; + + return TRUE; +} + +static void +append_function (CoglPipeline *pipeline, + CoglBlendStringChannelMask mask, + GLint function, + CoglPipelineFragendARBfpArg *args, + int n_args) +{ + CoglPipelineShaderState *shader_state = get_shader_state (pipeline); + const char *mask_name; + + switch (mask) + { + case COGL_BLEND_STRING_CHANNEL_MASK_RGB: + mask_name = ".rgb"; + break; + case COGL_BLEND_STRING_CHANNEL_MASK_ALPHA: + mask_name = ".a"; + break; + case COGL_BLEND_STRING_CHANNEL_MASK_RGBA: + mask_name = ""; + break; + default: + g_error ("Unknown channel mask %d", mask); + mask_name = ""; + } + + switch (function) + { + case COGL_PIPELINE_COMBINE_FUNC_ADD: + g_string_append_printf (shader_state->source, + "ADD_SAT output%s, ", + mask_name); + break; + case COGL_PIPELINE_COMBINE_FUNC_MODULATE: + /* Note: no need to saturate since we can assume operands + * have values in the range [0,1] */ + g_string_append_printf (shader_state->source, "MUL output%s, ", + mask_name); + break; + case COGL_PIPELINE_COMBINE_FUNC_REPLACE: + /* Note: no need to saturate since we can assume operand + * has a value in the range [0,1] */ + g_string_append_printf (shader_state->source, "MOV output%s, ", + mask_name); + break; + case COGL_PIPELINE_COMBINE_FUNC_SUBTRACT: + g_string_append_printf (shader_state->source, + "SUB_SAT output%s, ", + mask_name); + break; + case COGL_PIPELINE_COMBINE_FUNC_ADD_SIGNED: + g_string_append_printf (shader_state->source, "ADD tmp3%s, ", + mask_name); + append_arg (shader_state->source, &args[0]); + g_string_append (shader_state->source, ", "); + append_arg (shader_state->source, &args[1]); + g_string_append (shader_state->source, ";\n"); + g_string_append_printf (shader_state->source, + "SUB_SAT output%s, tmp3, half", + mask_name); + n_args = 0; + break; + case COGL_PIPELINE_COMBINE_FUNC_DOT3_RGB: + /* These functions are the same except that GL_DOT3_RGB never + * updates the alpha channel. + * + * NB: GL_DOT3_RGBA is a bit special because it effectively forces + * an RGBA mask and we end up ignoring any separate alpha channel + * function. + */ + case COGL_PIPELINE_COMBINE_FUNC_DOT3_RGBA: + { + const char *tmp4 = "tmp4"; + + /* The maths for this was taken from Mesa; + * apparently: + * + * tmp3 = 2*src0 - 1 + * tmp4 = 2*src1 - 1 + * output = DP3 (tmp3, tmp4) + * + * is the same as: + * + * output = 4 * DP3 (src0 - 0.5, src1 - 0.5) + */ + + g_string_append (shader_state->source, "MAD tmp3, two, "); + append_arg (shader_state->source, &args[0]); + g_string_append (shader_state->source, ", minus_one;\n"); + + if (!fragend_arbfp_args_equal (&args[0], &args[1])) + { + g_string_append (shader_state->source, "MAD tmp4, two, "); + append_arg (shader_state->source, &args[1]); + g_string_append (shader_state->source, ", minus_one;\n"); + } + else + tmp4 = "tmp3"; + + g_string_append_printf (shader_state->source, + "DP3_SAT output%s, tmp3, %s", + mask_name, tmp4); + n_args = 0; + } + break; + case COGL_PIPELINE_COMBINE_FUNC_INTERPOLATE: + /* Note: no need to saturate since we can assume operands + * have values in the range [0,1] */ + + /* NB: GL_INTERPOLATE = arg0*arg2 + arg1*(1-arg2) + * but LRP dst, a, b, c = b*a + c*(1-a) */ + g_string_append_printf (shader_state->source, "LRP output%s, ", + mask_name); + append_arg (shader_state->source, &args[2]); + g_string_append (shader_state->source, ", "); + append_arg (shader_state->source, &args[0]); + g_string_append (shader_state->source, ", "); + append_arg (shader_state->source, &args[1]); + n_args = 0; + break; + default: + g_error ("Unknown texture combine function %d", function); + g_string_append_printf (shader_state->source, "MUL_SAT output%s, ", + mask_name); + n_args = 2; + break; + } + + if (n_args > 0) + append_arg (shader_state->source, &args[0]); + if (n_args > 1) + { + g_string_append (shader_state->source, ", "); + append_arg (shader_state->source, &args[1]); + } + g_string_append (shader_state->source, ";\n"); +} + +static void +append_masked_combine (CoglPipeline *arbfp_authority, + CoglPipelineLayer *layer, + CoglBlendStringChannelMask mask, + CoglPipelineCombineFunc function, + CoglPipelineCombineSource *src, + CoglPipelineCombineOp *op) +{ + int i; + int n_args; + CoglPipelineFragendARBfpArg args[3]; + + n_args = _cogl_get_n_args_for_combine_func (function); + + for (i = 0; i < n_args; i++) + { + setup_arg (arbfp_authority, + layer, + mask, + i, + src[i], + op[i], + &args[i]); + } + + append_function (arbfp_authority, + mask, + function, + args, + n_args); +} + +static CoglBool +_cogl_pipeline_fragend_arbfp_add_layer (CoglPipeline *pipeline, + CoglPipelineLayer *layer, + unsigned long layers_difference) +{ + CoglPipelineShaderState *shader_state = get_shader_state (pipeline); + CoglPipelineLayer *combine_authority = + _cogl_pipeline_layer_get_authority (layer, + COGL_PIPELINE_LAYER_STATE_COMBINE); + CoglPipelineLayerBigState *big_state = combine_authority->big_state; + + /* Notes... + * + * We are ignoring the issue of texture indirection limits until + * someone complains (Ref Section 3.11.6 in the ARB_fragment_program + * spec) + * + * There always five TEMPs named tmp0, tmp1 and tmp2, tmp3 and tmp4 + * available and these constants: 'one' = {1, 1, 1, 1}, 'half' + * {.5, .5, .5, .5}, 'two' = {2, 2, 2, 2}, 'minus_one' = {-1, -1, + * -1, -1} + * + * tmp0-2 are intended for dealing with some of the texture combine + * operands (e.g. GL_ONE_MINUS_SRC_COLOR) tmp3/4 are for dealing + * with the GL_ADD_SIGNED texture combine and the GL_DOT3_RGB[A] + * functions. + * + * Each layer outputs to the TEMP called "output", and reads from + * output if it needs to refer to GL_PREVIOUS. (we detect if we are + * layer0 so we will read fragment.color for GL_PREVIOUS in that + * case) + * + * We aim to do all the channels together if the same function is + * used for RGB as for A. + * + * We aim to avoid string duplication / allocations during codegen. + * + * We are careful to only saturate when writing to output. + */ + + if (!shader_state->source) + return TRUE; + + if (!_cogl_pipeline_layer_needs_combine_separate (combine_authority)) + { + append_masked_combine (pipeline, + layer, + COGL_BLEND_STRING_CHANNEL_MASK_RGBA, + big_state->texture_combine_rgb_func, + big_state->texture_combine_rgb_src, + big_state->texture_combine_rgb_op); + } + else if (big_state->texture_combine_rgb_func == + COGL_PIPELINE_COMBINE_FUNC_DOT3_RGBA) + { + /* GL_DOT3_RGBA Is a bit weird as a GL_COMBINE_RGB function + * since if you use it, it overrides your ALPHA function... + */ + append_masked_combine (pipeline, + layer, + COGL_BLEND_STRING_CHANNEL_MASK_RGBA, + big_state->texture_combine_rgb_func, + big_state->texture_combine_rgb_src, + big_state->texture_combine_rgb_op); + } + else + { + append_masked_combine (pipeline, + layer, + COGL_BLEND_STRING_CHANNEL_MASK_RGB, + big_state->texture_combine_rgb_func, + big_state->texture_combine_rgb_src, + big_state->texture_combine_rgb_op); + append_masked_combine (pipeline, + layer, + COGL_BLEND_STRING_CHANNEL_MASK_ALPHA, + big_state->texture_combine_alpha_func, + big_state->texture_combine_alpha_src, + big_state->texture_combine_alpha_op); + } + + return TRUE; +} + +static CoglBool +_cogl_pipeline_fragend_arbfp_passthrough (CoglPipeline *pipeline) +{ + CoglPipelineShaderState *shader_state = get_shader_state (pipeline); + + if (!shader_state->source) + return TRUE; + + g_string_append (shader_state->source, + "MOV output, fragment.color.primary;\n"); + return TRUE; +} + +typedef struct _UpdateConstantsState +{ + int unit; + CoglBool update_all; + CoglPipelineShaderState *shader_state; +} UpdateConstantsState; + +static CoglBool +update_constants_cb (CoglPipeline *pipeline, + int layer_index, + void *user_data) +{ + UpdateConstantsState *state = user_data; + CoglPipelineShaderState *shader_state = state->shader_state; + UnitState *unit_state = &shader_state->unit_state[state->unit++]; + + _COGL_GET_CONTEXT (ctx, FALSE); + + if (unit_state->has_combine_constant && + (state->update_all || unit_state->dirty_combine_constant)) + { + float constant[4]; + _cogl_pipeline_get_layer_combine_constant (pipeline, + layer_index, + constant); + GE (ctx, glProgramLocalParameter4fv (GL_FRAGMENT_PROGRAM_ARB, + unit_state->constant_id, + constant)); + unit_state->dirty_combine_constant = FALSE; + } + return TRUE; +} + +static CoglBool +_cogl_pipeline_fragend_arbfp_end (CoglPipeline *pipeline, + unsigned long pipelines_difference) +{ + CoglPipelineShaderState *shader_state = get_shader_state (pipeline); + GLuint gl_program; + + _COGL_GET_CONTEXT (ctx, FALSE); + + if (shader_state->source) + { + COGL_STATIC_COUNTER (fragend_arbfp_compile_counter, + "arbfp compile counter", + "Increments each time a new ARBfp " + "program is compiled", + 0 /* no application private data */); + + COGL_COUNTER_INC (_cogl_uprof_context, fragend_arbfp_compile_counter); + + g_string_append (shader_state->source, + "MOV result.color,output;\n"); + g_string_append (shader_state->source, "END\n"); + + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SHOW_SOURCE))) + g_message ("pipeline program:\n%s", shader_state->source->str); + + GE (ctx, glGenPrograms (1, &shader_state->gl_program)); + + GE (ctx, glBindProgram (GL_FRAGMENT_PROGRAM_ARB, + shader_state->gl_program)); + _cogl_gl_util_clear_gl_errors (ctx); + + ctx->glProgramString (GL_FRAGMENT_PROGRAM_ARB, + GL_PROGRAM_FORMAT_ASCII_ARB, + shader_state->source->len, + shader_state->source->str); + if (_cogl_gl_util_get_error (ctx) != GL_NO_ERROR) + { + g_warning ("\n%s\n%s", + shader_state->source->str, + ctx->glGetString (GL_PROGRAM_ERROR_STRING_ARB)); + } + + shader_state->source = NULL; + } + + if (shader_state->user_program != COGL_INVALID_HANDLE) + { + /* An arbfp program should contain exactly one shader which we + can use directly */ + CoglProgram *program = shader_state->user_program; + CoglShader *shader = program->attached_shaders->data; + + gl_program = shader->gl_handle; + } + else + gl_program = shader_state->gl_program; + + GE (ctx, glBindProgram (GL_FRAGMENT_PROGRAM_ARB, gl_program)); + _cogl_use_fragment_program (0, COGL_PIPELINE_PROGRAM_TYPE_ARBFP); + + if (shader_state->user_program == COGL_INVALID_HANDLE) + { + UpdateConstantsState state; + state.unit = 0; + state.shader_state = shader_state; + /* If this arbfp program was last used with a different pipeline + * then we need to ensure we update all program.local params */ + state.update_all = + pipeline != shader_state->last_used_for_pipeline; + cogl_pipeline_foreach_layer (pipeline, + update_constants_cb, + &state); + } + else + { + CoglProgram *program = shader_state->user_program; + CoglBool program_changed; + + /* If the shader has changed since it was last flushed then we + need to update all uniforms */ + program_changed = program->age != shader_state->user_program_age; + + _cogl_program_flush_uniforms (program, gl_program, program_changed); + + shader_state->user_program_age = program->age; + } + + /* We need to track what pipeline used this arbfp program last since + * we will need to update program.local params when switching + * between different pipelines. */ + shader_state->last_used_for_pipeline = pipeline; + + return TRUE; +} + +static void +_cogl_pipeline_fragend_arbfp_pipeline_pre_change_notify ( + CoglPipeline *pipeline, + CoglPipelineState change, + const CoglColor *new_color) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if ((change & _cogl_pipeline_get_state_for_fragment_codegen (ctx))) + dirty_shader_state (pipeline); +} + +/* NB: layers are considered immutable once they have any dependants + * so although multiple pipelines can end up depending on a single + * static layer, we can guarantee that if a layer is being *changed* + * then it can only have one pipeline depending on it. + * + * XXX: Don't forget this is *pre* change, we can't read the new value + * yet! + */ +static void +_cogl_pipeline_fragend_arbfp_layer_pre_change_notify ( + CoglPipeline *owner, + CoglPipelineLayer *layer, + CoglPipelineLayerState change) +{ + CoglPipelineShaderState *shader_state = get_shader_state (owner); + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (!shader_state) + return; + + if ((change & _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx))) + { + dirty_shader_state (owner); + return; + } + + if (change & COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT) + { + int unit_index = _cogl_pipeline_layer_get_unit_index (layer); + shader_state->unit_state[unit_index].dirty_combine_constant = TRUE; + } + + /* TODO: we could be saving snippets of texture combine code along + * with each layer and then when a layer changes we would just free + * the snippet. */ + return; +} + +const CoglPipelineFragend _cogl_pipeline_arbfp_fragend = +{ + _cogl_pipeline_fragend_arbfp_start, + _cogl_pipeline_fragend_arbfp_add_layer, + _cogl_pipeline_fragend_arbfp_passthrough, + _cogl_pipeline_fragend_arbfp_end, + _cogl_pipeline_fragend_arbfp_pipeline_pre_change_notify, + NULL, + _cogl_pipeline_fragend_arbfp_layer_pre_change_notify +}; + +#endif /* COGL_PIPELINE_FRAGEND_ARBFP */ + diff --git a/cogl/cogl/driver/gl/gl/cogl-pipeline-progend-fixed-arbfp-private.h b/cogl/cogl/driver/gl/gl/cogl-pipeline-progend-fixed-arbfp-private.h new file mode 100644 index 0000000..ba0c713 --- /dev/null +++ b/cogl/cogl/driver/gl/gl/cogl-pipeline-progend-fixed-arbfp-private.h @@ -0,0 +1,42 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Neil Roberts + */ + +#ifndef __COGL_PIPELINE_PROGEND_FIXED_ARBFP_PRIVATE_H +#define __COGL_PIPELINE_PROGEND_FIXED_ARBFP_PRIVATE_H + +#include "cogl-pipeline-private.h" + +extern const CoglPipelineProgend _cogl_pipeline_fixed_arbfp_progend; + +#endif /* __COGL_PIPELINE_PROGEND_FIXED_ARBFP_PRIVATE_H */ + diff --git a/cogl/cogl/driver/gl/gl/cogl-pipeline-progend-fixed-arbfp.c b/cogl/cogl/driver/gl/gl/cogl-pipeline-progend-fixed-arbfp.c new file mode 100644 index 0000000..ac79500 --- /dev/null +++ b/cogl/cogl/driver/gl/gl/cogl-pipeline-progend-fixed-arbfp.c @@ -0,0 +1,121 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include + +#include "cogl-pipeline-private.h" +#include "cogl-pipeline-state-private.h" + +#ifdef COGL_PIPELINE_PROGEND_FIXED_ARBFP + +#include "cogl-context.h" +#include "cogl-context-private.h" +#include "cogl-framebuffer-private.h" +#include "cogl-program-private.h" + +static CoglBool +_cogl_pipeline_progend_fixed_arbfp_start (CoglPipeline *pipeline) +{ + CoglHandle user_program; + + _COGL_GET_CONTEXT (ctx, FALSE); + + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_FIXED))) + return FALSE; + + if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_GL_FIXED)) + return FALSE; + + /* Vertex snippets are only supported in the GLSL fragend */ + if (_cogl_pipeline_has_vertex_snippets (pipeline)) + return FALSE; + + /* Validate that we can handle the fragment state using ARBfp + */ + + if (!cogl_has_feature (ctx, COGL_FEATURE_ID_ARBFP)) + return FALSE; + + /* Fragment snippets are only supported in the GLSL fragend */ + if (_cogl_pipeline_has_fragment_snippets (pipeline)) + return FALSE; + + user_program = cogl_pipeline_get_user_program (pipeline); + if (user_program && + _cogl_program_get_language (user_program) != COGL_SHADER_LANGUAGE_ARBFP) + return FALSE; + + /* The ARBfp progend can't handle the per-vertex point size + * attribute */ + if (cogl_pipeline_get_per_vertex_point_size (pipeline)) + return FALSE; + + return TRUE; +} + +static void +_cogl_pipeline_progend_fixed_arbfp_pre_paint (CoglPipeline *pipeline, + CoglFramebuffer *framebuffer) +{ + CoglContext *ctx = framebuffer->context; + + if (ctx->current_projection_entry) + _cogl_matrix_entry_flush_to_gl_builtins (ctx, + ctx->current_projection_entry, + COGL_MATRIX_PROJECTION, + framebuffer, + FALSE /* enable flip */); + if (ctx->current_modelview_entry) + _cogl_matrix_entry_flush_to_gl_builtins (ctx, + ctx->current_modelview_entry, + COGL_MATRIX_MODELVIEW, + framebuffer, + FALSE /* enable flip */); +} + +const CoglPipelineProgend _cogl_pipeline_fixed_arbfp_progend = + { + COGL_PIPELINE_VERTEND_FIXED, + COGL_PIPELINE_FRAGEND_ARBFP, + _cogl_pipeline_progend_fixed_arbfp_start, + NULL, /* end */ + NULL, /* pre_change_notify */ + NULL, /* layer_pre_change_notify */ + _cogl_pipeline_progend_fixed_arbfp_pre_paint + }; + +#endif /* COGL_PIPELINE_PROGEND_FIXED_ARBFP */ diff --git a/cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c b/cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c new file mode 100644 index 0000000..c76a0cf --- /dev/null +++ b/cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c @@ -0,0 +1,549 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Matthew Allum + * Neil Roberts + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-private.h" +#include "cogl-util.h" +#include "cogl-bitmap.h" +#include "cogl-bitmap-private.h" +#include "cogl-texture-private.h" +#include "cogl-pipeline.h" +#include "cogl-context-private.h" +#include "cogl-object-private.h" +#include "cogl-primitives.h" +#include "cogl-pipeline-opengl-private.h" +#include "cogl-util-gl-private.h" +#include "cogl-error-private.h" +#include "cogl-texture-gl-private.h" + +#include +#include +#include + +#ifndef GL_TEXTURE_SWIZZLE_RGBA +#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46 +#endif + +static GLuint +_cogl_texture_driver_gen (CoglContext *ctx, + GLenum gl_target, + CoglPixelFormat internal_format) +{ + GLuint tex; + + GE (ctx, glGenTextures (1, &tex)); + + _cogl_bind_gl_texture_transient (gl_target, tex, FALSE); + + switch (gl_target) + { + case GL_TEXTURE_2D: + case GL_TEXTURE_3D: + /* In case automatic mipmap generation gets disabled for this + * texture but a minification filter depending on mipmap + * interpolation is selected then we initialize the max mipmap + * level to 0 so OpenGL will consider the texture storage to be + * "complete". + */ +#ifdef HAVE_COGL_GL + if (_cogl_has_private_feature + (ctx, COGL_PRIVATE_FEATURE_TEXTURE_MAX_LEVEL)) + GE( ctx, glTexParameteri (gl_target, GL_TEXTURE_MAX_LEVEL, 0)); +#endif + + /* GL_TEXTURE_MAG_FILTER defaults to GL_LINEAR, no need to set it */ + GE( ctx, glTexParameteri (gl_target, + GL_TEXTURE_MIN_FILTER, + GL_LINEAR) ); + break; + + case GL_TEXTURE_RECTANGLE_ARB: + /* Texture rectangles already default to GL_LINEAR so nothing + needs to be done */ + break; + + default: + g_assert_not_reached(); + } + + /* If the driver doesn't support alpha textures directly then we'll + * fake them by setting the swizzle parameters */ + if (internal_format == COGL_PIXEL_FORMAT_A_8 && + !_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_ALPHA_TEXTURES) && + _cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_TEXTURE_SWIZZLE)) + { + static const GLint red_swizzle[] = { GL_ZERO, GL_ZERO, GL_ZERO, GL_RED }; + + GE( ctx, glTexParameteriv (gl_target, + GL_TEXTURE_SWIZZLE_RGBA, + red_swizzle) ); + } + + return tex; +} + +/* OpenGL - unlike GLES - can upload a sub region of pixel data from a larger + * source buffer */ +static void +prep_gl_for_pixels_upload_full (CoglContext *ctx, + int pixels_rowstride, + int image_height, + int pixels_src_x, + int pixels_src_y, + int pixels_bpp) +{ + GE( ctx, glPixelStorei (GL_UNPACK_ROW_LENGTH, + pixels_rowstride / pixels_bpp) ); + + GE( ctx, glPixelStorei (GL_UNPACK_SKIP_PIXELS, pixels_src_x) ); + GE( ctx, glPixelStorei (GL_UNPACK_SKIP_ROWS, pixels_src_y) ); + + if (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_3D)) + GE( ctx, glPixelStorei (GL_UNPACK_IMAGE_HEIGHT, image_height) ); + + _cogl_texture_gl_prep_alignment_for_pixels_upload (ctx, pixels_rowstride); +} + +static void +_cogl_texture_driver_prep_gl_for_pixels_upload (CoglContext *ctx, + int pixels_rowstride, + int pixels_bpp) +{ + prep_gl_for_pixels_upload_full (ctx, pixels_rowstride, 0, 0, 0, pixels_bpp); +} + +/* OpenGL - unlike GLES - can download pixel data into a sub region of + * a larger destination buffer */ +static void +prep_gl_for_pixels_download_full (CoglContext *ctx, + int image_width, + int pixels_rowstride, + int image_height, + int pixels_src_x, + int pixels_src_y, + int pixels_bpp) +{ + GE( ctx, glPixelStorei (GL_PACK_ROW_LENGTH, pixels_rowstride / pixels_bpp) ); + + GE( ctx, glPixelStorei (GL_PACK_SKIP_PIXELS, pixels_src_x) ); + GE( ctx, glPixelStorei (GL_PACK_SKIP_ROWS, pixels_src_y) ); + + if (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_3D)) + GE( ctx, glPixelStorei (GL_PACK_IMAGE_HEIGHT, image_height) ); + + _cogl_texture_gl_prep_alignment_for_pixels_download (ctx, + pixels_bpp, + image_width, + pixels_rowstride); +} + +static void +_cogl_texture_driver_prep_gl_for_pixels_download (CoglContext *ctx, + int image_width, + int pixels_rowstride, + int pixels_bpp) +{ + prep_gl_for_pixels_download_full (ctx, + pixels_rowstride, + image_width, + 0 /* image height */, + 0, 0, /* pixels_src_x/y */ + pixels_bpp); +} + +static CoglBool +_cogl_texture_driver_upload_subregion_to_gl (CoglContext *ctx, + CoglTexture *texture, + CoglBool is_foreign, + int src_x, + int src_y, + int dst_x, + int dst_y, + int width, + int height, + int level, + CoglBitmap *source_bmp, + GLuint source_gl_format, + GLuint source_gl_type, + CoglError **error) +{ + GLenum gl_target; + GLuint gl_handle; + uint8_t *data; + CoglPixelFormat source_format = cogl_bitmap_get_format (source_bmp); + int bpp = _cogl_pixel_format_get_bytes_per_pixel (source_format); + CoglBool status = TRUE; + CoglError *internal_error = NULL; + int level_width; + int level_height; + + cogl_texture_get_gl_texture (texture, &gl_handle, &gl_target); + + data = _cogl_bitmap_gl_bind (source_bmp, COGL_BUFFER_ACCESS_READ, 0, &internal_error); + + /* NB: _cogl_bitmap_gl_bind() may return NULL when successfull so we + * have to explicitly check the cogl error pointer to catch + * problems... */ + if (internal_error) + { + _cogl_propagate_error (error, internal_error); + return FALSE; + } + + /* Setup gl alignment to match rowstride and top-left corner */ + prep_gl_for_pixels_upload_full (ctx, + cogl_bitmap_get_rowstride (source_bmp), + 0, + src_x, + src_y, + bpp); + + _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign); + + /* Clear any GL errors */ + _cogl_gl_util_clear_gl_errors (ctx); + + _cogl_texture_get_level_size (texture, + level, + &level_width, + &level_height, + NULL); + + if (level_width == width && level_height == height) + { + /* GL gets upset if you use glTexSubImage2D to initialize the + * contents of a mipmap level so we make sure to use + * glTexImage2D if we are uploading a full mipmap level. + */ + ctx->glTexImage2D (gl_target, + level, + _cogl_texture_gl_get_format (texture), + width, + height, + 0, + source_gl_format, + source_gl_type, + data); + + } + else + { + /* GL gets upset if you use glTexSubImage2D to initialize the + * contents of a mipmap level so if this is the first time + * we've seen a request to upload to this level we call + * glTexImage2D first to assert that the storage for this + * level exists. + */ + if (texture->max_level < level) + { + ctx->glTexImage2D (gl_target, + level, + _cogl_texture_gl_get_format (texture), + level_width, + level_height, + 0, + source_gl_format, + source_gl_type, + NULL); + } + + ctx->glTexSubImage2D (gl_target, + level, + dst_x, dst_y, + width, height, + source_gl_format, + source_gl_type, + data); + } + + if (_cogl_gl_util_catch_out_of_memory (ctx, error)) + status = FALSE; + + _cogl_bitmap_gl_unbind (source_bmp); + + return status; +} + +static CoglBool +_cogl_texture_driver_upload_to_gl (CoglContext *ctx, + GLenum gl_target, + GLuint gl_handle, + CoglBool is_foreign, + CoglBitmap *source_bmp, + GLint internal_gl_format, + GLuint source_gl_format, + GLuint source_gl_type, + CoglError **error) +{ + uint8_t *data; + CoglPixelFormat source_format = cogl_bitmap_get_format (source_bmp); + int bpp = _cogl_pixel_format_get_bytes_per_pixel (source_format); + CoglBool status = TRUE; + CoglError *internal_error = NULL; + + data = _cogl_bitmap_gl_bind (source_bmp, + COGL_BUFFER_ACCESS_READ, + 0, /* hints */ + &internal_error); + + /* NB: _cogl_bitmap_gl_bind() may return NULL when successful so we + * have to explicitly check the cogl error pointer to catch + * problems... */ + if (internal_error) + { + _cogl_propagate_error (error, internal_error); + return FALSE; + } + + /* Setup gl alignment to match rowstride and top-left corner */ + prep_gl_for_pixels_upload_full (ctx, + cogl_bitmap_get_rowstride (source_bmp), + 0, 0, 0, bpp); + + _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign); + + /* Clear any GL errors */ + _cogl_gl_util_clear_gl_errors (ctx); + + ctx->glTexImage2D (gl_target, 0, + internal_gl_format, + cogl_bitmap_get_width (source_bmp), + cogl_bitmap_get_height (source_bmp), + 0, + source_gl_format, + source_gl_type, + data); + + if (_cogl_gl_util_catch_out_of_memory (ctx, error)) + status = FALSE; + + _cogl_bitmap_gl_unbind (source_bmp); + + return status; +} + +static CoglBool +_cogl_texture_driver_upload_to_gl_3d (CoglContext *ctx, + GLenum gl_target, + GLuint gl_handle, + CoglBool is_foreign, + GLint height, + GLint depth, + CoglBitmap *source_bmp, + GLint internal_gl_format, + GLuint source_gl_format, + GLuint source_gl_type, + CoglError **error) +{ + uint8_t *data; + CoglPixelFormat source_format = cogl_bitmap_get_format (source_bmp); + int bpp = _cogl_pixel_format_get_bytes_per_pixel (source_format); + CoglBool status = TRUE; + + data = _cogl_bitmap_gl_bind (source_bmp, COGL_BUFFER_ACCESS_READ, 0, error); + if (!data) + return FALSE; + + /* Setup gl alignment to match rowstride and top-left corner */ + prep_gl_for_pixels_upload_full (ctx, + cogl_bitmap_get_rowstride (source_bmp), + (cogl_bitmap_get_height (source_bmp) / + depth), + 0, 0, bpp); + + _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign); + + /* Clear any GL errors */ + _cogl_gl_util_clear_gl_errors (ctx); + + ctx->glTexImage3D (gl_target, + 0, /* level */ + internal_gl_format, + cogl_bitmap_get_width (source_bmp), + height, + depth, + 0, + source_gl_format, + source_gl_type, + data); + + if (_cogl_gl_util_catch_out_of_memory (ctx, error)) + status = FALSE; + + _cogl_bitmap_gl_unbind (source_bmp); + + return status; +} + +static CoglBool +_cogl_texture_driver_gl_get_tex_image (CoglContext *ctx, + GLenum gl_target, + GLenum dest_gl_format, + GLenum dest_gl_type, + uint8_t *dest) +{ + GE (ctx, glGetTexImage (gl_target, + 0, /* level */ + dest_gl_format, + dest_gl_type, + (GLvoid *)dest)); + return TRUE; +} + +static CoglBool +_cogl_texture_driver_size_supported_3d (CoglContext *ctx, + GLenum gl_target, + GLenum gl_format, + GLenum gl_type, + int width, + int height, + int depth) +{ + GLenum proxy_target; + GLint new_width = 0; + + if (gl_target == GL_TEXTURE_3D) + proxy_target = GL_PROXY_TEXTURE_3D; + else + /* Unknown target, assume it's not supported */ + return FALSE; + + /* Proxy texture allows for a quick check for supported size */ + GE( ctx, glTexImage3D (proxy_target, 0, GL_RGBA, + width, height, depth, 0 /* border */, + gl_format, gl_type, NULL) ); + + GE( ctx, glGetTexLevelParameteriv (proxy_target, 0, + GL_TEXTURE_WIDTH, &new_width) ); + + return new_width != 0; +} + +static CoglBool +_cogl_texture_driver_size_supported (CoglContext *ctx, + GLenum gl_target, + GLenum gl_intformat, + GLenum gl_format, + GLenum gl_type, + int width, + int height) +{ + GLenum proxy_target; + GLint new_width = 0; + + if (gl_target == GL_TEXTURE_2D) + proxy_target = GL_PROXY_TEXTURE_2D; +#if HAVE_COGL_GL + else if (gl_target == GL_TEXTURE_RECTANGLE_ARB) + proxy_target = GL_PROXY_TEXTURE_RECTANGLE_ARB; +#endif + else + /* Unknown target, assume it's not supported */ + return FALSE; + + /* Proxy texture allows for a quick check for supported size */ + GE( ctx, glTexImage2D (proxy_target, 0, gl_intformat, + width, height, 0 /* border */, + gl_format, gl_type, NULL) ); + + GE( ctx, glGetTexLevelParameteriv (proxy_target, 0, + GL_TEXTURE_WIDTH, &new_width) ); + + return new_width != 0; +} + +static void +_cogl_texture_driver_try_setting_gl_border_color + (CoglContext *ctx, + GLuint gl_target, + const GLfloat *transparent_color) +{ + /* Use a transparent border color so that we can leave the + color buffer alone when using texture co-ordinates + outside of the texture */ + GE( ctx, glTexParameterfv (gl_target, GL_TEXTURE_BORDER_COLOR, + transparent_color) ); +} + +static CoglBool +_cogl_texture_driver_allows_foreign_gl_target (CoglContext *ctx, + GLenum gl_target) +{ + /* GL_ARB_texture_rectangle textures are supported if they are + created from foreign because some chipsets have trouble with + GL_ARB_texture_non_power_of_two. There is no Cogl call to create + them directly to emphasize the fact that they don't work fully + (for example, no mipmapping and complicated shader support) */ + + /* Allow 2-dimensional or rectangle textures only */ + if (gl_target != GL_TEXTURE_2D && gl_target != GL_TEXTURE_RECTANGLE_ARB) + return FALSE; + + return TRUE; +} + +static CoglPixelFormat +_cogl_texture_driver_find_best_gl_get_data_format + (CoglContext *context, + CoglPixelFormat format, + GLenum *closest_gl_format, + GLenum *closest_gl_type) +{ + return context->driver_vtable->pixel_format_to_gl (context, + format, + NULL, /* don't need */ + closest_gl_format, + closest_gl_type); +} + +const CoglTextureDriver +_cogl_texture_driver_gl = + { + _cogl_texture_driver_gen, + _cogl_texture_driver_prep_gl_for_pixels_upload, + _cogl_texture_driver_upload_subregion_to_gl, + _cogl_texture_driver_upload_to_gl, + _cogl_texture_driver_upload_to_gl_3d, + _cogl_texture_driver_prep_gl_for_pixels_download, + _cogl_texture_driver_gl_get_tex_image, + _cogl_texture_driver_size_supported, + _cogl_texture_driver_size_supported_3d, + _cogl_texture_driver_try_setting_gl_border_color, + _cogl_texture_driver_allows_foreign_gl_target, + _cogl_texture_driver_find_best_gl_get_data_format + }; diff --git a/cogl/cogl/driver/gl/gles/cogl-driver-gles.c b/cogl/cogl/driver/gl/gles/cogl-driver-gles.c new file mode 100644 index 0000000..bf63fcc --- /dev/null +++ b/cogl/cogl/driver/gl/gles/cogl-driver-gles.c @@ -0,0 +1,487 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include + +#include "cogl-context-private.h" +#include "cogl-util-gl-private.h" +#include "cogl-feature-private.h" +#include "cogl-renderer-private.h" +#include "cogl-private.h" +#include "cogl-framebuffer-gl-private.h" +#include "cogl-texture-2d-gl-private.h" +#include "cogl-attribute-gl-private.h" +#include "cogl-clip-stack-gl-private.h" +#include "cogl-buffer-gl-private.h" + +#ifndef GL_UNSIGNED_INT_24_8 +#define GL_UNSIGNED_INT_24_8 0x84FA +#endif +#ifndef GL_DEPTH_STENCIL +#define GL_DEPTH_STENCIL 0x84F9 +#endif +#ifndef GL_RG +#define GL_RG 0x8227 +#endif +#ifndef GL_RG8 +#define GL_RG8 0x822B +#endif + +static CoglBool +_cogl_driver_pixel_format_from_gl_internal (CoglContext *context, + GLenum gl_int_format, + CoglPixelFormat *out_format) +{ + return TRUE; +} + +static CoglPixelFormat +_cogl_driver_pixel_format_to_gl (CoglContext *context, + CoglPixelFormat format, + GLenum *out_glintformat, + GLenum *out_glformat, + GLenum *out_gltype) +{ + CoglPixelFormat required_format; + GLenum glintformat; + GLenum glformat = 0; + GLenum gltype; + + required_format = format; + + /* Find GL equivalents */ + switch (format) + { + case COGL_PIXEL_FORMAT_A_8: + glintformat = GL_ALPHA; + glformat = GL_ALPHA; + gltype = GL_UNSIGNED_BYTE; + break; + case COGL_PIXEL_FORMAT_G_8: + glintformat = GL_LUMINANCE; + glformat = GL_LUMINANCE; + gltype = GL_UNSIGNED_BYTE; + break; + + case COGL_PIXEL_FORMAT_RG_88: + if (cogl_has_feature (context, COGL_FEATURE_ID_TEXTURE_RG)) + { + glintformat = GL_RG8; + glformat = GL_RG; + } + else + { + /* If red-green textures aren't supported then we'll use RGB + * as an internal format. Note this should only end up + * mattering for downloading the data because Cogl will + * refuse to allocate a texture with RG components if RG + * textures aren't supported */ + glintformat = GL_RGB; + glformat = GL_RGB; + required_format = COGL_PIXEL_FORMAT_RGB_888; + } + gltype = GL_UNSIGNED_BYTE; + break; + + case COGL_PIXEL_FORMAT_BGRA_8888: + case COGL_PIXEL_FORMAT_BGRA_8888_PRE: + /* There is an extension to support this format */ + if (_cogl_has_private_feature + (context, COGL_PRIVATE_FEATURE_TEXTURE_FORMAT_BGRA8888)) + { + /* For some reason the extension says you have to specify + BGRA for the internal format too */ + glintformat = GL_BGRA_EXT; + glformat = GL_BGRA_EXT; + gltype = GL_UNSIGNED_BYTE; + required_format = format; + break; + } + /* flow through */ + + /* Just one 24-bit ordering supported */ + case COGL_PIXEL_FORMAT_RGB_888: + case COGL_PIXEL_FORMAT_BGR_888: + glintformat = GL_RGB; + glformat = GL_RGB; + gltype = GL_UNSIGNED_BYTE; + required_format = COGL_PIXEL_FORMAT_RGB_888; + break; + + /* Just one 32-bit ordering supported */ + case COGL_PIXEL_FORMAT_RGBA_8888: + case COGL_PIXEL_FORMAT_RGBA_8888_PRE: + case COGL_PIXEL_FORMAT_ARGB_8888: + case COGL_PIXEL_FORMAT_ARGB_8888_PRE: + case COGL_PIXEL_FORMAT_ABGR_8888: + case COGL_PIXEL_FORMAT_ABGR_8888_PRE: + case COGL_PIXEL_FORMAT_RGBA_1010102: + case COGL_PIXEL_FORMAT_RGBA_1010102_PRE: + case COGL_PIXEL_FORMAT_BGRA_1010102: + case COGL_PIXEL_FORMAT_BGRA_1010102_PRE: + case COGL_PIXEL_FORMAT_ABGR_2101010: + case COGL_PIXEL_FORMAT_ABGR_2101010_PRE: + case COGL_PIXEL_FORMAT_ARGB_2101010: + case COGL_PIXEL_FORMAT_ARGB_2101010_PRE: + glintformat = GL_RGBA; + glformat = GL_RGBA; + gltype = GL_UNSIGNED_BYTE; + required_format = COGL_PIXEL_FORMAT_RGBA_8888; + required_format |= (format & COGL_PREMULT_BIT); + break; + + /* The following three types of channel ordering + * are always defined using system word byte + * ordering (even according to GLES spec) */ + case COGL_PIXEL_FORMAT_RGB_565: + glintformat = GL_RGB; + glformat = GL_RGB; + gltype = GL_UNSIGNED_SHORT_5_6_5; + break; + case COGL_PIXEL_FORMAT_RGBA_4444: + case COGL_PIXEL_FORMAT_RGBA_4444_PRE: + glintformat = GL_RGBA; + glformat = GL_RGBA; + gltype = GL_UNSIGNED_SHORT_4_4_4_4; + break; + case COGL_PIXEL_FORMAT_RGBA_5551: + case COGL_PIXEL_FORMAT_RGBA_5551_PRE: + glintformat = GL_RGBA; + glformat = GL_RGBA; + gltype = GL_UNSIGNED_SHORT_5_5_5_1; + break; + + case COGL_PIXEL_FORMAT_DEPTH_16: + glintformat = GL_DEPTH_COMPONENT; + glformat = GL_DEPTH_COMPONENT; + gltype = GL_UNSIGNED_SHORT; + break; + case COGL_PIXEL_FORMAT_DEPTH_32: + glintformat = GL_DEPTH_COMPONENT; + glformat = GL_DEPTH_COMPONENT; + gltype = GL_UNSIGNED_INT; + break; + + case COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8: + glintformat = GL_DEPTH_STENCIL; + glformat = GL_DEPTH_STENCIL; + gltype = GL_UNSIGNED_INT_24_8; + break; + + case COGL_PIXEL_FORMAT_ANY: + case COGL_PIXEL_FORMAT_YUV: + g_assert_not_reached (); + break; + } + + /* All of the pixel formats are handled above so if this hits then + we've been given an invalid pixel format */ + g_assert (glformat != 0); + + if (out_glintformat != NULL) + *out_glintformat = glintformat; + if (out_glformat != NULL) + *out_glformat = glformat; + if (out_gltype != NULL) + *out_gltype = gltype; + + return required_format; +} + +static CoglBool +_cogl_get_gl_version (CoglContext *ctx, + int *major_out, + int *minor_out) +{ + const char *version_string; + + /* Get the OpenGL version number */ + if ((version_string = _cogl_context_get_gl_version (ctx)) == NULL) + return FALSE; + + if (!g_str_has_prefix (version_string, "OpenGL ES ")) + return FALSE; + + return _cogl_gl_util_parse_gl_version (version_string + 10, + major_out, + minor_out); +} + +static CoglBool +_cogl_driver_update_features (CoglContext *context, + CoglError **error) +{ + unsigned long private_features + [COGL_FLAGS_N_LONGS_FOR_SIZE (COGL_N_PRIVATE_FEATURES)] = { 0 }; + CoglFeatureFlags flags = 0; + char **gl_extensions; + int gl_major, gl_minor; + int i; + + /* We have to special case getting the pointer to the glGetString + function because we need to use it to determine what functions we + can expect */ + context->glGetString = + (void *) _cogl_renderer_get_proc_address (context->display->renderer, + "glGetString", + TRUE); + + gl_extensions = _cogl_context_get_gl_extensions (context); + + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_WINSYS))) + { + char *all_extensions = g_strjoinv (" ", gl_extensions); + + COGL_NOTE (WINSYS, + "Checking features\n" + " GL_VENDOR: %s\n" + " GL_RENDERER: %s\n" + " GL_VERSION: %s\n" + " GL_EXTENSIONS: %s", + context->glGetString (GL_VENDOR), + context->glGetString (GL_RENDERER), + _cogl_context_get_gl_version (context), + all_extensions); + + g_free (all_extensions); + } + + context->glsl_major = 1; + context->glsl_minor = 0; + context->glsl_version_to_use = 100; + + _cogl_gpu_info_init (context, &context->gpu); + + if (!_cogl_get_gl_version (context, &gl_major, &gl_minor)) + { + gl_major = 1; + gl_minor = 1; + } + + _cogl_feature_check_ext_functions (context, + gl_major, + gl_minor, + gl_extensions); + +#ifdef HAVE_COGL_GLES + if (context->driver == COGL_DRIVER_GLES1) + { + int max_clip_planes; + GE( context, glGetIntegerv (GL_MAX_CLIP_PLANES, &max_clip_planes) ); + if (max_clip_planes >= 4) + COGL_FLAGS_SET (private_features, + COGL_PRIVATE_FEATURE_FOUR_CLIP_PLANES, TRUE); + } +#endif + + if (context->driver == COGL_DRIVER_GLES2) + { + flags |= COGL_FEATURE_SHADERS_GLSL | COGL_FEATURE_OFFSCREEN; + /* Note GLES 2 core doesn't support mipmaps for npot textures or + * repeat modes other than CLAMP_TO_EDGE. */ + flags |= COGL_FEATURE_TEXTURE_NPOT_BASIC; + flags |= COGL_FEATURE_DEPTH_RANGE; + COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_GLSL, TRUE); + COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_OFFSCREEN, TRUE); + COGL_FLAGS_SET (context->features, + COGL_FEATURE_ID_TEXTURE_NPOT_BASIC, TRUE); + COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_DEPTH_RANGE, TRUE); + COGL_FLAGS_SET (context->features, + COGL_FEATURE_ID_MIRRORED_REPEAT, TRUE); + COGL_FLAGS_SET (context->features, + COGL_FEATURE_ID_PER_VERTEX_POINT_SIZE, TRUE); + + COGL_FLAGS_SET (private_features, + COGL_PRIVATE_FEATURE_BLEND_CONSTANT, TRUE); + } + else if (context->driver == COGL_DRIVER_GLES1) + { + COGL_FLAGS_SET (private_features, COGL_PRIVATE_FEATURE_GL_FIXED, TRUE); + COGL_FLAGS_SET (private_features, COGL_PRIVATE_FEATURE_ALPHA_TEST, TRUE); + COGL_FLAGS_SET (private_features, + COGL_PRIVATE_FEATURE_BUILTIN_POINT_SIZE_UNIFORM, TRUE); + } + + COGL_FLAGS_SET (private_features, COGL_PRIVATE_FEATURE_VBOS, TRUE); + COGL_FLAGS_SET (private_features, COGL_PRIVATE_FEATURE_ANY_GL, TRUE); + COGL_FLAGS_SET (private_features, COGL_PRIVATE_FEATURE_ALPHA_TEXTURES, TRUE); + + /* Both GLES 1.1 and GLES 2.0 support point sprites in core */ + flags |= COGL_FEATURE_POINT_SPRITE; + COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_POINT_SPRITE, TRUE); + + if (context->glGenRenderbuffers) + { + flags |= COGL_FEATURE_OFFSCREEN; + COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_OFFSCREEN, TRUE); + } + + if (context->glBlitFramebuffer) + COGL_FLAGS_SET (private_features, + COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT, TRUE); + + if (_cogl_check_extension ("GL_OES_element_index_uint", gl_extensions)) + { + flags |= COGL_FEATURE_UNSIGNED_INT_INDICES; + COGL_FLAGS_SET (context->features, + COGL_FEATURE_ID_UNSIGNED_INT_INDICES, TRUE); + } + + if (_cogl_check_extension ("GL_OES_depth_texture", gl_extensions)) + { + flags |= COGL_FEATURE_DEPTH_TEXTURE; + COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_DEPTH_TEXTURE, TRUE); + } + + if (_cogl_check_extension ("GL_OES_texture_npot", gl_extensions)) + { + flags |= (COGL_FEATURE_TEXTURE_NPOT | + COGL_FEATURE_TEXTURE_NPOT_BASIC | + COGL_FEATURE_TEXTURE_NPOT_MIPMAP | + COGL_FEATURE_TEXTURE_NPOT_REPEAT); + COGL_FLAGS_SET (context->features, + COGL_FEATURE_ID_TEXTURE_NPOT, TRUE); + COGL_FLAGS_SET (context->features, + COGL_FEATURE_ID_TEXTURE_NPOT_BASIC, TRUE); + COGL_FLAGS_SET (context->features, + COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP, TRUE); + COGL_FLAGS_SET (context->features, + COGL_FEATURE_ID_TEXTURE_NPOT_REPEAT, TRUE); + } + else if (_cogl_check_extension ("GL_IMG_texture_npot", gl_extensions)) + { + flags |= (COGL_FEATURE_TEXTURE_NPOT_BASIC | + COGL_FEATURE_TEXTURE_NPOT_MIPMAP); + COGL_FLAGS_SET (context->features, + COGL_FEATURE_ID_TEXTURE_NPOT_BASIC, TRUE); + COGL_FLAGS_SET (context->features, + COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP, TRUE); + } + + if (context->glTexImage3D) + { + flags |= COGL_FEATURE_TEXTURE_3D; + COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_TEXTURE_3D, TRUE); + } + + if (context->glMapBuffer) + { + /* The GL_OES_mapbuffer extension doesn't support mapping for + read */ + flags |= COGL_FEATURE_MAP_BUFFER_FOR_WRITE; + COGL_FLAGS_SET (context->features, + COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE, TRUE); + } + + if (context->glMapBufferRange) + { + /* MapBufferRange in ES3+ does support mapping for read */ + flags |= (COGL_FEATURE_MAP_BUFFER_FOR_WRITE | + COGL_FEATURE_MAP_BUFFER_FOR_READ); + COGL_FLAGS_SET(context->features, + COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE, TRUE); + COGL_FLAGS_SET(context->features, + COGL_FEATURE_ID_MAP_BUFFER_FOR_READ, TRUE); + } + + if (context->glEGLImageTargetTexture2D) + COGL_FLAGS_SET (private_features, + COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE, TRUE); + + if (_cogl_check_extension ("GL_OES_packed_depth_stencil", gl_extensions)) + COGL_FLAGS_SET (private_features, + COGL_PRIVATE_FEATURE_OES_PACKED_DEPTH_STENCIL, TRUE); + + if (_cogl_check_extension ("GL_EXT_texture_format_BGRA8888", gl_extensions)) + COGL_FLAGS_SET (private_features, + COGL_PRIVATE_FEATURE_TEXTURE_FORMAT_BGRA8888, TRUE); + + if (_cogl_check_extension ("GL_EXT_unpack_subimage", gl_extensions)) + COGL_FLAGS_SET (private_features, + COGL_PRIVATE_FEATURE_UNPACK_SUBIMAGE, TRUE); + + /* A nameless vendor implemented the extension, but got the case wrong + * per the spec. */ + if (_cogl_check_extension ("GL_OES_EGL_sync", gl_extensions) || + _cogl_check_extension ("GL_OES_egl_sync", gl_extensions)) + COGL_FLAGS_SET (private_features, COGL_PRIVATE_FEATURE_OES_EGL_SYNC, TRUE); + + if (_cogl_check_extension ("GL_EXT_texture_rg", gl_extensions)) + COGL_FLAGS_SET (context->features, + COGL_FEATURE_ID_TEXTURE_RG, + TRUE); + + /* Cache features */ + for (i = 0; i < G_N_ELEMENTS (private_features); i++) + context->private_features[i] |= private_features[i]; + context->feature_flags |= flags; + + g_strfreev (gl_extensions); + + return TRUE; +} + +const CoglDriverVtable +_cogl_driver_gles = + { + _cogl_driver_pixel_format_from_gl_internal, + _cogl_driver_pixel_format_to_gl, + _cogl_driver_update_features, + _cogl_offscreen_gl_allocate, + _cogl_offscreen_gl_free, + _cogl_framebuffer_gl_flush_state, + _cogl_framebuffer_gl_clear, + _cogl_framebuffer_gl_query_bits, + _cogl_framebuffer_gl_finish, + _cogl_framebuffer_gl_discard_buffers, + _cogl_framebuffer_gl_draw_attributes, + _cogl_framebuffer_gl_draw_indexed_attributes, + _cogl_framebuffer_gl_read_pixels_into_bitmap, + _cogl_texture_2d_gl_free, + _cogl_texture_2d_gl_can_create, + _cogl_texture_2d_gl_init, + _cogl_texture_2d_gl_allocate, + _cogl_texture_2d_gl_copy_from_framebuffer, + _cogl_texture_2d_gl_get_gl_handle, + _cogl_texture_2d_gl_generate_mipmap, + _cogl_texture_2d_gl_copy_from_bitmap, + NULL, /* texture_2d_get_data */ + _cogl_gl_flush_attributes_state, + _cogl_clip_stack_gl_flush, + _cogl_buffer_gl_create, + _cogl_buffer_gl_destroy, + _cogl_buffer_gl_map_range, + _cogl_buffer_gl_unmap, + _cogl_buffer_gl_set_data, + }; diff --git a/cogl/cogl/driver/gl/gles/cogl-texture-driver-gles.c b/cogl/cogl/driver/gl/gles/cogl-texture-driver-gles.c new file mode 100644 index 0000000..34ba57f --- /dev/null +++ b/cogl/cogl/driver/gl/gles/cogl-texture-driver-gles.c @@ -0,0 +1,644 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Matthew Allum + * Neil Roberts + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-private.h" +#include "cogl-util.h" +#include "cogl-bitmap.h" +#include "cogl-bitmap-private.h" +#include "cogl-texture-private.h" +#include "cogl-pipeline.h" +#include "cogl-pipeline-opengl-private.h" +#include "cogl-context-private.h" +#include "cogl-object-private.h" +#include "cogl-primitives.h" +#include "cogl-util-gl-private.h" +#include "cogl-error-private.h" +#include "cogl-texture-gl-private.h" + +#include +#include +#include + +#ifndef GL_TEXTURE_3D +#define GL_TEXTURE_3D 0x806F +#endif +#ifndef GL_MAX_3D_TEXTURE_SIZE_OES +#define GL_MAX_3D_TEXTURE_SIZE_OES 0x8073 +#endif + +/* This extension isn't available for GLES 1.1 so these won't be + defined */ +#ifndef GL_UNPACK_ROW_LENGTH +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#endif +#ifndef GL_UNPACK_SKIP_ROWS +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#endif +#ifndef GL_UNPACK_SKIP_PIXELS +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#endif + +static GLuint +_cogl_texture_driver_gen (CoglContext *ctx, + GLenum gl_target, + CoglPixelFormat internal_format) +{ + GLuint tex; + + GE (ctx, glGenTextures (1, &tex)); + + _cogl_bind_gl_texture_transient (gl_target, tex, FALSE); + + switch (gl_target) + { + case GL_TEXTURE_2D: + case GL_TEXTURE_3D: + /* GL_TEXTURE_MAG_FILTER defaults to GL_LINEAR, no need to set it */ + GE( ctx, glTexParameteri (gl_target, + GL_TEXTURE_MIN_FILTER, + GL_LINEAR) ); + break; + + default: + g_assert_not_reached(); + } + + return tex; +} + +static void +prep_gl_for_pixels_upload_full (CoglContext *ctx, + int pixels_rowstride, + int pixels_src_x, + int pixels_src_y, + int pixels_bpp) +{ + if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_UNPACK_SUBIMAGE)) + { + GE( ctx, glPixelStorei (GL_UNPACK_ROW_LENGTH, + pixels_rowstride / pixels_bpp) ); + + GE( ctx, glPixelStorei (GL_UNPACK_SKIP_PIXELS, pixels_src_x) ); + GE( ctx, glPixelStorei (GL_UNPACK_SKIP_ROWS, pixels_src_y) ); + } + else + { + g_assert (pixels_src_x == 0); + g_assert (pixels_src_y == 0); + } + + _cogl_texture_gl_prep_alignment_for_pixels_upload (ctx, pixels_rowstride); +} + +static void +_cogl_texture_driver_prep_gl_for_pixels_upload (CoglContext *ctx, + int pixels_rowstride, + int pixels_bpp) +{ + prep_gl_for_pixels_upload_full (ctx, + pixels_rowstride, + 0, 0, /* src_x/y */ + pixels_bpp); +} + +static void +_cogl_texture_driver_prep_gl_for_pixels_download (CoglContext *ctx, + int pixels_rowstride, + int image_width, + int pixels_bpp) +{ + _cogl_texture_gl_prep_alignment_for_pixels_download (ctx, + pixels_bpp, + image_width, + pixels_rowstride); +} + +static CoglBitmap * +prepare_bitmap_alignment_for_upload (CoglContext *ctx, + CoglBitmap *src_bmp, + CoglError **error) +{ + CoglPixelFormat format = cogl_bitmap_get_format (src_bmp); + int bpp = _cogl_pixel_format_get_bytes_per_pixel (format); + int src_rowstride = cogl_bitmap_get_rowstride (src_bmp); + int width = cogl_bitmap_get_width (src_bmp); + int alignment = 1; + + if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_UNPACK_SUBIMAGE) || + src_rowstride == 0) + return cogl_object_ref (src_bmp); + + /* Work out the alignment of the source rowstride */ + alignment = 1 << (_cogl_util_ffs (src_rowstride) - 1); + alignment = MIN (alignment, 8); + + /* If the aligned data equals the rowstride then we can upload from + the bitmap directly using GL_UNPACK_ALIGNMENT */ + if (((width * bpp + alignment - 1) & ~(alignment - 1)) == src_rowstride) + return cogl_object_ref (src_bmp); + /* Otherwise we need to copy the bitmap to pack the alignment + because GLES has no GL_ROW_LENGTH */ + else + return _cogl_bitmap_copy (src_bmp, error); +} + +static CoglBool +_cogl_texture_driver_upload_subregion_to_gl (CoglContext *ctx, + CoglTexture *texture, + CoglBool is_foreign, + int src_x, + int src_y, + int dst_x, + int dst_y, + int width, + int height, + int level, + CoglBitmap *source_bmp, + GLuint source_gl_format, + GLuint source_gl_type, + CoglError **error) +{ + GLenum gl_target; + GLuint gl_handle; + uint8_t *data; + CoglPixelFormat source_format = cogl_bitmap_get_format (source_bmp); + int bpp = _cogl_pixel_format_get_bytes_per_pixel (source_format); + CoglBitmap *slice_bmp; + int rowstride; + CoglBool status = TRUE; + CoglError *internal_error = NULL; + int level_width; + int level_height; + + cogl_texture_get_gl_texture (texture, &gl_handle, &gl_target); + + /* If we have the GL_EXT_unpack_subimage extension then we can + upload from subregions directly. Otherwise we may need to copy + the bitmap */ + if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_UNPACK_SUBIMAGE) && + (src_x != 0 || src_y != 0 || + width != cogl_bitmap_get_width (source_bmp) || + height != cogl_bitmap_get_height (source_bmp))) + { + slice_bmp = + _cogl_bitmap_new_with_malloc_buffer (ctx, + width, height, + source_format, + error); + if (!slice_bmp) + return FALSE; + + if (!_cogl_bitmap_copy_subregion (source_bmp, + slice_bmp, + src_x, src_y, + 0, 0, /* dst_x/y */ + width, height, + error)) + { + cogl_object_unref (slice_bmp); + return FALSE; + } + + src_x = src_y = 0; + } + else + { + slice_bmp = prepare_bitmap_alignment_for_upload (ctx, source_bmp, error); + if (!slice_bmp) + return FALSE; + } + + rowstride = cogl_bitmap_get_rowstride (slice_bmp); + + /* Setup gl alignment to match rowstride and top-left corner */ + prep_gl_for_pixels_upload_full (ctx, rowstride, src_x, src_y, bpp); + + data = _cogl_bitmap_gl_bind (slice_bmp, COGL_BUFFER_ACCESS_READ, 0, &internal_error); + + /* NB: _cogl_bitmap_gl_bind() may return NULL when successfull so we + * have to explicitly check the cogl error pointer to catch + * problems... */ + if (internal_error) + { + _cogl_propagate_error (error, internal_error); + cogl_object_unref (slice_bmp); + return FALSE; + } + + _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign); + + /* Clear any GL errors */ + _cogl_gl_util_clear_gl_errors (ctx); + + _cogl_texture_get_level_size (texture, + level, + &level_width, + &level_height, + NULL); + + if (level_width == width && level_height == height) + { + /* GL gets upset if you use glTexSubImage2D to define the + * contents of a mipmap level so we make sure to use + * glTexImage2D if we are uploading a full mipmap level. + */ + ctx->glTexImage2D (gl_target, + level, + _cogl_texture_gl_get_format (texture), + width, + height, + 0, + source_gl_format, + source_gl_type, + data); + } + else + { + /* GL gets upset if you use glTexSubImage2D to initialize the + * contents of a mipmap level so if this is the first time + * we've seen a request to upload to this level we call + * glTexImage2D first to assert that the storage for this + * level exists. + */ + if (texture->max_level < level) + { + ctx->glTexImage2D (gl_target, + level, + _cogl_texture_gl_get_format (texture), + level_width, + level_height, + 0, + source_gl_format, + source_gl_type, + NULL); + } + + ctx->glTexSubImage2D (gl_target, + level, + dst_x, dst_y, + width, height, + source_gl_format, + source_gl_type, + data); + } + + if (_cogl_gl_util_catch_out_of_memory (ctx, error)) + status = FALSE; + + _cogl_bitmap_gl_unbind (slice_bmp); + + cogl_object_unref (slice_bmp); + + return status; +} + +static CoglBool +_cogl_texture_driver_upload_to_gl (CoglContext *ctx, + GLenum gl_target, + GLuint gl_handle, + CoglBool is_foreign, + CoglBitmap *source_bmp, + GLint internal_gl_format, + GLuint source_gl_format, + GLuint source_gl_type, + CoglError **error) +{ + CoglPixelFormat source_format = cogl_bitmap_get_format (source_bmp); + int bpp = _cogl_pixel_format_get_bytes_per_pixel (source_format); + int rowstride; + int bmp_width = cogl_bitmap_get_width (source_bmp); + int bmp_height = cogl_bitmap_get_height (source_bmp); + CoglBitmap *bmp; + uint8_t *data; + CoglError *internal_error = NULL; + CoglBool status = TRUE; + + bmp = prepare_bitmap_alignment_for_upload (ctx, source_bmp, error); + if (!bmp) + return FALSE; + + rowstride = cogl_bitmap_get_rowstride (bmp); + + /* Setup gl alignment to match rowstride and top-left corner */ + _cogl_texture_driver_prep_gl_for_pixels_upload (ctx, rowstride, bpp); + + _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign); + + data = _cogl_bitmap_gl_bind (bmp, + COGL_BUFFER_ACCESS_READ, + 0, /* hints */ + &internal_error); + + /* NB: _cogl_bitmap_gl_bind() may return NULL when successful so we + * have to explicitly check the cogl error pointer to catch + * problems... */ + if (internal_error) + { + cogl_object_unref (bmp); + _cogl_propagate_error (error, internal_error); + return FALSE; + } + + /* Clear any GL errors */ + _cogl_gl_util_clear_gl_errors (ctx); + + ctx->glTexImage2D (gl_target, 0, + internal_gl_format, + bmp_width, bmp_height, + 0, + source_gl_format, + source_gl_type, + data); + + if (_cogl_gl_util_catch_out_of_memory (ctx, error)) + status = FALSE; + + _cogl_bitmap_gl_unbind (bmp); + + cogl_object_unref (bmp); + + return status; +} + +static CoglBool +_cogl_texture_driver_upload_to_gl_3d (CoglContext *ctx, + GLenum gl_target, + GLuint gl_handle, + CoglBool is_foreign, + GLint height, + GLint depth, + CoglBitmap *source_bmp, + GLint internal_gl_format, + GLuint source_gl_format, + GLuint source_gl_type, + CoglError **error) +{ + CoglPixelFormat source_format = cogl_bitmap_get_format (source_bmp); + int bpp = _cogl_pixel_format_get_bytes_per_pixel (source_format); + int rowstride = cogl_bitmap_get_rowstride (source_bmp); + int bmp_width = cogl_bitmap_get_width (source_bmp); + int bmp_height = cogl_bitmap_get_height (source_bmp); + uint8_t *data; + + _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign); + + /* If the rowstride or image height can't be specified with just + GL_ALIGNMENT alone then we need to copy the bitmap because there + is no GL_ROW_LENGTH */ + if (rowstride / bpp != bmp_width || + height != bmp_height / depth) + { + CoglBitmap *bmp; + int image_height = bmp_height / depth; + CoglPixelFormat source_bmp_format = cogl_bitmap_get_format (source_bmp); + int i; + + _cogl_texture_driver_prep_gl_for_pixels_upload (ctx, bmp_width * bpp, bpp); + + /* Initialize the texture with empty data and then upload each + image with a sub-region update */ + + /* Clear any GL errors */ + _cogl_gl_util_clear_gl_errors (ctx); + + ctx->glTexImage3D (gl_target, + 0, /* level */ + internal_gl_format, + bmp_width, + height, + depth, + 0, + source_gl_format, + source_gl_type, + NULL); + + if (_cogl_gl_util_catch_out_of_memory (ctx, error)) + return FALSE; + + bmp = _cogl_bitmap_new_with_malloc_buffer (ctx, + bmp_width, + height, + source_bmp_format, + error); + if (!bmp) + return FALSE; + + for (i = 0; i < depth; i++) + { + if (!_cogl_bitmap_copy_subregion (source_bmp, + bmp, + 0, image_height * i, + 0, 0, + bmp_width, + height, + error)) + { + cogl_object_unref (bmp); + return FALSE; + } + + data = _cogl_bitmap_gl_bind (bmp, + COGL_BUFFER_ACCESS_READ, 0, error); + if (!data) + { + cogl_object_unref (bmp); + return FALSE; + } + + /* Clear any GL errors */ + _cogl_gl_util_clear_gl_errors (ctx); + + ctx->glTexSubImage3D (gl_target, + 0, /* level */ + 0, /* xoffset */ + 0, /* yoffset */ + i, /* zoffset */ + bmp_width, /* width */ + height, /* height */ + 1, /* depth */ + source_gl_format, + source_gl_type, + data); + + if (_cogl_gl_util_catch_out_of_memory (ctx, error)) + { + cogl_object_unref (bmp); + _cogl_bitmap_gl_unbind (bmp); + return FALSE; + } + + _cogl_bitmap_gl_unbind (bmp); + } + + cogl_object_unref (bmp); + } + else + { + data = _cogl_bitmap_gl_bind (source_bmp, COGL_BUFFER_ACCESS_READ, 0, error); + if (!data) + return FALSE; + + _cogl_texture_driver_prep_gl_for_pixels_upload (ctx, rowstride, bpp); + + /* Clear any GL errors */ + _cogl_gl_util_clear_gl_errors (ctx); + + ctx->glTexImage3D (gl_target, + 0, /* level */ + internal_gl_format, + bmp_width, + height, + depth, + 0, + source_gl_format, + source_gl_type, + data); + + if (_cogl_gl_util_catch_out_of_memory (ctx, error)) + { + _cogl_bitmap_gl_unbind (source_bmp); + return FALSE; + } + + _cogl_bitmap_gl_unbind (source_bmp); + } + + return TRUE; +} + +/* NB: GLES doesn't support glGetTexImage2D, so cogl-texture will instead + * fallback to a generic render + readpixels approach to downloading + * texture data. (See _cogl_texture_draw_and_read() ) */ +static CoglBool +_cogl_texture_driver_gl_get_tex_image (CoglContext *ctx, + GLenum gl_target, + GLenum dest_gl_format, + GLenum dest_gl_type, + uint8_t *dest) +{ + return FALSE; +} + +static CoglBool +_cogl_texture_driver_size_supported_3d (CoglContext *ctx, + GLenum gl_target, + GLenum gl_format, + GLenum gl_type, + int width, + int height, + int depth) +{ + GLint max_size; + + /* GLES doesn't support a proxy texture target so let's at least + check whether the size is greater than + GL_MAX_3D_TEXTURE_SIZE_OES */ + GE( ctx, glGetIntegerv (GL_MAX_3D_TEXTURE_SIZE_OES, &max_size) ); + + return width <= max_size && height <= max_size && depth <= max_size; +} + +static CoglBool +_cogl_texture_driver_size_supported (CoglContext *ctx, + GLenum gl_target, + GLenum gl_intformat, + GLenum gl_format, + GLenum gl_type, + int width, + int height) +{ + GLint max_size; + + /* GLES doesn't support a proxy texture target so let's at least + check whether the size is greater than GL_MAX_TEXTURE_SIZE */ + GE( ctx, glGetIntegerv (GL_MAX_TEXTURE_SIZE, &max_size) ); + + return width <= max_size && height <= max_size; +} + +static void +_cogl_texture_driver_try_setting_gl_border_color + (CoglContext *ctx, + GLuint gl_target, + const GLfloat *transparent_color) +{ + /* FAIL! */ +} + +static CoglBool +_cogl_texture_driver_allows_foreign_gl_target (CoglContext *ctx, + GLenum gl_target) +{ + /* Allow 2-dimensional textures only */ + if (gl_target != GL_TEXTURE_2D) + return FALSE; + return TRUE; +} + +static CoglPixelFormat +_cogl_texture_driver_find_best_gl_get_data_format + (CoglContext *context, + CoglPixelFormat format, + GLenum *closest_gl_format, + GLenum *closest_gl_type) +{ + /* Find closest format that's supported by GL + (Can't use _cogl_pixel_format_to_gl since available formats + when reading pixels on GLES are severely limited) */ + *closest_gl_format = GL_RGBA; + *closest_gl_type = GL_UNSIGNED_BYTE; + return COGL_PIXEL_FORMAT_RGBA_8888; +} + +const CoglTextureDriver +_cogl_texture_driver_gles = + { + _cogl_texture_driver_gen, + _cogl_texture_driver_prep_gl_for_pixels_upload, + _cogl_texture_driver_upload_subregion_to_gl, + _cogl_texture_driver_upload_to_gl, + _cogl_texture_driver_upload_to_gl_3d, + _cogl_texture_driver_prep_gl_for_pixels_download, + _cogl_texture_driver_gl_get_tex_image, + _cogl_texture_driver_size_supported, + _cogl_texture_driver_size_supported_3d, + _cogl_texture_driver_try_setting_gl_border_color, + _cogl_texture_driver_allows_foreign_gl_target, + _cogl_texture_driver_find_best_gl_get_data_format + }; diff --git a/cogl/cogl/driver/nop/cogl-attribute-nop-private.h b/cogl/cogl/driver/nop/cogl-attribute-nop-private.h new file mode 100644 index 0000000..9c8547d --- /dev/null +++ b/cogl/cogl/driver/nop/cogl-attribute-nop-private.h @@ -0,0 +1,48 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef _COGL_ATTRIBUTE_NOP_PRIVATE_H_ +#define _COGL_ATTRIBUTE_NOP_PRIVATE_H_ + +#include "cogl-types.h" +#include "cogl-context-private.h" + +void +_cogl_nop_flush_attributes_state (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglFlushLayerState *layers_state, + CoglDrawFlags flags, + CoglAttribute **attributes, + int n_attributes); + +#endif /* _COGL_ATTRIBUTE_NOP_PRIVATE_H_ */ diff --git a/cogl/cogl/driver/nop/cogl-attribute-nop.c b/cogl/cogl/driver/nop/cogl-attribute-nop.c new file mode 100644 index 0000000..dcb6891 --- /dev/null +++ b/cogl/cogl/driver/nop/cogl-attribute-nop.c @@ -0,0 +1,49 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-types.h" +#include "cogl-framebuffer.h" +#include "cogl-attribute.h" +#include "cogl-attribute-private.h" +#include "cogl-attribute-nop-private.h" + +void +_cogl_nop_flush_attributes_state (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglFlushLayerState *layers_state, + CoglDrawFlags flags, + CoglAttribute **attributes, + int n_attributes) +{ +} diff --git a/cogl/cogl/driver/nop/cogl-clip-stack-nop-private.h b/cogl/cogl/driver/nop/cogl-clip-stack-nop-private.h new file mode 100644 index 0000000..4d8513b --- /dev/null +++ b/cogl/cogl/driver/nop/cogl-clip-stack-nop-private.h @@ -0,0 +1,44 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef _COGL_CLIP_STACK_NOP_PRIVATE_H_ +#define _COGL_CLIP_STACK_NOP_PRIVATE_H_ + +#include "cogl-types.h" +#include "cogl-context-private.h" + +void +_cogl_clip_stack_nop_flush (CoglClipStack *stack, + CoglFramebuffer *framebuffer); + +#endif /* _COGL_CLIP_STACK_NOP_PRIVATE_H_ */ diff --git a/cogl/cogl/driver/nop/cogl-clip-stack-nop.c b/cogl/cogl/driver/nop/cogl-clip-stack-nop.c new file mode 100644 index 0000000..441dd6e --- /dev/null +++ b/cogl/cogl/driver/nop/cogl-clip-stack-nop.c @@ -0,0 +1,43 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-clip-stack.h" +#include "cogl-clip-stack-nop-private.h" +#include "cogl-framebuffer-private.h" + +void +_cogl_clip_stack_nop_flush (CoglClipStack *stack, + CoglFramebuffer *framebuffer) +{ +} diff --git a/cogl/cogl/driver/nop/cogl-driver-nop.c b/cogl/cogl/driver/nop/cogl-driver-nop.c new file mode 100644 index 0000000..d9b1d0f --- /dev/null +++ b/cogl/cogl/driver/nop/cogl-driver-nop.c @@ -0,0 +1,86 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include + +#include "cogl-private.h" +#include "cogl-context-private.h" +#include "cogl-feature-private.h" +#include "cogl-renderer-private.h" +#include "cogl-error-private.h" +#include "cogl-framebuffer-nop-private.h" +#include "cogl-texture-2d-nop-private.h" +#include "cogl-attribute-nop-private.h" +#include "cogl-clip-stack-nop-private.h" + +static CoglBool +_cogl_driver_update_features (CoglContext *ctx, + CoglError **error) +{ + /* _cogl_gpu_info_init (ctx, &ctx->gpu); */ + + memset (ctx->private_features, 0, sizeof (ctx->private_features)); + ctx->feature_flags = 0; + + return TRUE; +} + +const CoglDriverVtable +_cogl_driver_nop = + { + NULL, /* pixel_format_from_gl_internal */ + NULL, /* pixel_format_to_gl */ + _cogl_driver_update_features, + _cogl_offscreen_nop_allocate, + _cogl_offscreen_nop_free, + _cogl_framebuffer_nop_flush_state, + _cogl_framebuffer_nop_clear, + _cogl_framebuffer_nop_query_bits, + _cogl_framebuffer_nop_finish, + _cogl_framebuffer_nop_discard_buffers, + _cogl_framebuffer_nop_draw_attributes, + _cogl_framebuffer_nop_draw_indexed_attributes, + _cogl_framebuffer_nop_read_pixels_into_bitmap, + _cogl_texture_2d_nop_free, + _cogl_texture_2d_nop_can_create, + _cogl_texture_2d_nop_init, + _cogl_texture_2d_nop_allocate, + _cogl_texture_2d_nop_copy_from_framebuffer, + _cogl_texture_2d_nop_get_gl_handle, + _cogl_texture_2d_nop_generate_mipmap, + _cogl_texture_2d_nop_copy_from_bitmap, + NULL, /* texture_2d_get_data */ + _cogl_nop_flush_attributes_state, + _cogl_clip_stack_nop_flush, + }; diff --git a/cogl/cogl/driver/nop/cogl-framebuffer-nop-private.h b/cogl/cogl/driver/nop/cogl-framebuffer-nop-private.h new file mode 100644 index 0000000..1e9630f --- /dev/null +++ b/cogl/cogl/driver/nop/cogl-framebuffer-nop-private.h @@ -0,0 +1,100 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef _COGL_FRAMEBUFFER_NOP_PRIVATE_H_ +#define _COGL_FRAMEBUFFER_NOP_PRIVATE_H_ + +#include "cogl-types.h" +#include "cogl-context-private.h" + +CoglBool +_cogl_offscreen_nop_allocate (CoglOffscreen *offscreen, + CoglError **error); + +void +_cogl_offscreen_nop_free (CoglOffscreen *offscreen); + +void +_cogl_framebuffer_nop_flush_state (CoglFramebuffer *draw_buffer, + CoglFramebuffer *read_buffer, + CoglFramebufferState state); + +void +_cogl_framebuffer_nop_clear (CoglFramebuffer *framebuffer, + unsigned long buffers, + float red, + float green, + float blue, + float alpha); + +void +_cogl_framebuffer_nop_query_bits (CoglFramebuffer *framebuffer, + CoglFramebufferBits *bits); + +void +_cogl_framebuffer_nop_finish (CoglFramebuffer *framebuffer); + +void +_cogl_framebuffer_nop_discard_buffers (CoglFramebuffer *framebuffer, + unsigned long buffers); + +void +_cogl_framebuffer_nop_draw_attributes (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglVerticesMode mode, + int first_vertex, + int n_vertices, + CoglAttribute **attributes, + int n_attributes, + CoglDrawFlags flags); + +void +_cogl_framebuffer_nop_draw_indexed_attributes (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglVerticesMode mode, + int first_vertex, + int n_vertices, + CoglIndices *indices, + CoglAttribute **attributes, + int n_attributes, + CoglDrawFlags flags); + +CoglBool +_cogl_framebuffer_nop_read_pixels_into_bitmap (CoglFramebuffer *framebuffer, + int x, + int y, + CoglReadPixelsFlags source, + CoglBitmap *bitmap, + CoglError **error); + +#endif /* _COGL_FRAMEBUFFER_NOP_PRIVATE_H_ */ diff --git a/cogl/cogl/driver/nop/cogl-framebuffer-nop.c b/cogl/cogl/driver/nop/cogl-framebuffer-nop.c new file mode 100644 index 0000000..2e730e4 --- /dev/null +++ b/cogl/cogl/driver/nop/cogl-framebuffer-nop.c @@ -0,0 +1,121 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-framebuffer-nop-private.h" + +#include +#include + +void +_cogl_framebuffer_nop_flush_state (CoglFramebuffer *draw_buffer, + CoglFramebuffer *read_buffer, + CoglFramebufferState state) +{ +} + +CoglBool +_cogl_offscreen_nop_allocate (CoglOffscreen *offscreen, + CoglError **error) +{ + return TRUE; +} + +void +_cogl_offscreen_nop_free (CoglOffscreen *offscreen) +{ +} + +void +_cogl_framebuffer_nop_clear (CoglFramebuffer *framebuffer, + unsigned long buffers, + float red, + float green, + float blue, + float alpha) +{ +} + +void +_cogl_framebuffer_nop_query_bits (CoglFramebuffer *framebuffer, + CoglFramebufferBits *bits) +{ + memset (bits, 0, sizeof (CoglFramebufferBits)); +} + +void +_cogl_framebuffer_nop_finish (CoglFramebuffer *framebuffer) +{ +} + +void +_cogl_framebuffer_nop_discard_buffers (CoglFramebuffer *framebuffer, + unsigned long buffers) +{ +} + +void +_cogl_framebuffer_nop_draw_attributes (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglVerticesMode mode, + int first_vertex, + int n_vertices, + CoglAttribute **attributes, + int n_attributes, + CoglDrawFlags flags) +{ +} + +void +_cogl_framebuffer_nop_draw_indexed_attributes (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglVerticesMode mode, + int first_vertex, + int n_vertices, + CoglIndices *indices, + CoglAttribute **attributes, + int n_attributes, + CoglDrawFlags flags) +{ +} + +CoglBool +_cogl_framebuffer_nop_read_pixels_into_bitmap (CoglFramebuffer *framebuffer, + int x, + int y, + CoglReadPixelsFlags source, + CoglBitmap *bitmap, + CoglError **error) +{ + return TRUE; +} diff --git a/cogl/cogl/driver/nop/cogl-texture-2d-nop-private.h b/cogl/cogl/driver/nop/cogl-texture-2d-nop-private.h new file mode 100644 index 0000000..51de1e3 --- /dev/null +++ b/cogl/cogl/driver/nop/cogl-texture-2d-nop-private.h @@ -0,0 +1,103 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef _COGL_TEXTURE_2D_NOP_PRIVATE_H_ +#define _COGL_TEXTURE_2D_NOP_PRIVATE_H_ + +#include "cogl-types.h" +#include "cogl-context-private.h" +#include "cogl-texture.h" + +void +_cogl_texture_2d_nop_free (CoglTexture2D *tex_2d); + +CoglBool +_cogl_texture_2d_nop_can_create (CoglContext *ctx, + int width, + int height, + CoglPixelFormat internal_format); + +void +_cogl_texture_2d_nop_init (CoglTexture2D *tex_2d); + +CoglBool +_cogl_texture_2d_nop_allocate (CoglTexture *tex, + CoglError **error); + +void +_cogl_texture_2d_nop_flush_legacy_texobj_filters (CoglTexture *tex, + GLenum min_filter, + GLenum mag_filter); + +void +_cogl_texture_2d_nop_flush_legacy_texobj_wrap_modes (CoglTexture *tex, + GLenum wrap_mode_s, + GLenum wrap_mode_t, + GLenum wrap_mode_p); + +void +_cogl_texture_2d_nop_copy_from_framebuffer (CoglTexture2D *tex_2d, + int src_x, + int src_y, + int width, + int height, + CoglFramebuffer *src_fb, + int dst_x, + int dst_y, + int level); + +unsigned int +_cogl_texture_2d_nop_get_gl_handle (CoglTexture2D *tex_2d); + +void +_cogl_texture_2d_nop_generate_mipmap (CoglTexture2D *tex_2d); + +CoglBool +_cogl_texture_2d_nop_copy_from_bitmap (CoglTexture2D *tex_2d, + int src_x, + int src_y, + int width, + int height, + CoglBitmap *bitmap, + int dst_x, + int dst_y, + int level, + CoglError **error); + +void +_cogl_texture_2d_nop_get_data (CoglTexture2D *tex_2d, + CoglPixelFormat format, + size_t rowstride, + uint8_t *data); + +#endif /* _COGL_TEXTURE_2D_NOP_PRIVATE_H_ */ diff --git a/cogl/cogl/driver/nop/cogl-texture-2d-nop.c b/cogl/cogl/driver/nop/cogl-texture-2d-nop.c new file mode 100644 index 0000000..539048a --- /dev/null +++ b/cogl/cogl/driver/nop/cogl-texture-2d-nop.c @@ -0,0 +1,132 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009,2010,2011,2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Neil Roberts + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include + +#include "cogl-private.h" +#include "cogl-texture-2d-nop-private.h" +#include "cogl-texture-2d-private.h" +#include "cogl-error-private.h" + +void +_cogl_texture_2d_nop_free (CoglTexture2D *tex_2d) +{ +} + +CoglBool +_cogl_texture_2d_nop_can_create (CoglContext *ctx, + int width, + int height, + CoglPixelFormat internal_format) +{ + return TRUE; +} + +void +_cogl_texture_2d_nop_init (CoglTexture2D *tex_2d) +{ +} + +CoglBool +_cogl_texture_2d_nop_allocate (CoglTexture *tex, + CoglError **error) +{ + return TRUE; +} + +void +_cogl_texture_2d_nop_flush_legacy_texobj_filters (CoglTexture *tex, + GLenum min_filter, + GLenum mag_filter) +{ +} + +void +_cogl_texture_2d_nop_flush_legacy_texobj_wrap_modes (CoglTexture *tex, + GLenum wrap_mode_s, + GLenum wrap_mode_t, + GLenum wrap_mode_p) +{ +} + +void +_cogl_texture_2d_nop_copy_from_framebuffer (CoglTexture2D *tex_2d, + int src_x, + int src_y, + int width, + int height, + CoglFramebuffer *src_fb, + int dst_x, + int dst_y, + int level) +{ +} + +unsigned int +_cogl_texture_2d_nop_get_gl_handle (CoglTexture2D *tex_2d) +{ + return 0; +} + +void +_cogl_texture_2d_nop_generate_mipmap (CoglTexture2D *tex_2d) +{ +} + +CoglBool +_cogl_texture_2d_nop_copy_from_bitmap (CoglTexture2D *tex_2d, + int src_x, + int src_y, + int width, + int height, + CoglBitmap *bitmap, + int dst_x, + int dst_y, + int level, + CoglError **error) +{ + return TRUE; +} + +void +_cogl_texture_2d_nop_get_data (CoglTexture2D *tex_2d, + CoglPixelFormat format, + size_t rowstride, + uint8_t *data) +{ +} diff --git a/cogl/cogl/gl-prototypes/cogl-all-functions.h b/cogl/cogl/gl-prototypes/cogl-all-functions.h new file mode 100644 index 0000000..0c80fbc --- /dev/null +++ b/cogl/cogl/gl-prototypes/cogl-all-functions.h @@ -0,0 +1,336 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009, 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +/* This is included multiple times with different definitions for + * these macros. The macros are given the following arguments: + * + * COGL_EXT_BEGIN: + * + * @name: a unique symbol name for this feature + * + * @min_gl_major: the major part of the minimum GL version where these + * functions are available in core, or 255 if it isn't available in + * any version. + * @min_gl_minor: the minor part of the minimum GL version where these + * functions are available in core, or 255 if it isn't available in + * any version. + * + * @gles_availability: flags to specify which versions of GLES the + * functions are available in. Should be a combination of + * COGL_EXT_IN_GLES and COGL_EXT_IN_GLES2. + * + * @extension_suffixes: A zero-separated list of suffixes in a + * string. These are appended to the extension name to get a complete + * extension name to try. The suffix is also appended to all of the + * function names. The suffix can optionally include a ':' to specify + * an alternate suffix for the function names. + * + * @extension_names: A list of extension names to try. If any of these + * extensions match then it will be used. + */ + +/* The functions in this file are part of the core GL,GLES1 and GLES2 apis */ +#include "cogl-core-functions.h" + +/* The functions in this file are core to GLES1 only but may also be + * extensions available for GLES2 and GL */ +#include "cogl-in-gles1-core-functions.h" + +/* The functions in this file are core to GLES2 only but + * may be extensions for GLES1 and GL */ +#include "cogl-in-gles2-core-functions.h" + +/* The functions in this file are core to GLES1 and GLES2 but not core + * to GL but they may be extensions available for GL */ +#include "cogl-in-gles-core-functions.h" + +/* These are fixed-function APIs core to GL and GLES1 */ +#include "cogl-fixed-functions.h" + +/* These are GLSL shader APIs core to GL 2.0 and GLES2 */ +#include "cogl-glsl-functions.h" + +/* These are the core GL functions which are only available in big + GL */ +COGL_EXT_BEGIN (only_in_big_gl, + 0, 0, + 0, /* not in GLES */ + "\0", + "\0") +COGL_EXT_FUNCTION (void, glGetTexLevelParameteriv, + (GLenum target, GLint level, + GLenum pname, GLint *params)) +COGL_EXT_FUNCTION (void, glGetTexImage, + (GLenum target, GLint level, + GLenum format, GLenum type, + GLvoid *pixels)) +COGL_EXT_FUNCTION (void, glClipPlane, + (GLenum plane, const double *equation)) +COGL_EXT_FUNCTION (void, glDepthRange, + (double near_val, double far_val)) +COGL_EXT_FUNCTION (void, glDrawBuffer, + (GLenum mode)) +COGL_EXT_END () + + +/* GLES doesn't support mapping buffers in core so this has to be a + separate check */ +COGL_EXT_BEGIN (map_vbos, 1, 5, + 0, /* not in GLES core */ + "ARB\0OES\0", + "vertex_buffer_object\0mapbuffer\0") +COGL_EXT_FUNCTION (void *, glMapBuffer, + (GLenum target, + GLenum access)) +COGL_EXT_FUNCTION (GLboolean, glUnmapBuffer, + (GLenum target)) +COGL_EXT_END () + +COGL_EXT_BEGIN (texture_3d, 1, 2, + 0, /* not in either GLES */ + "OES\0", + "texture_3D\0") +COGL_EXT_FUNCTION (void, glTexImage3D, + (GLenum target, GLint level, + GLint internalFormat, + GLsizei width, GLsizei height, + GLsizei depth, GLint border, + GLenum format, GLenum type, + const GLvoid *pixels)) +COGL_EXT_FUNCTION (void, glTexSubImage3D, + (GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint zoffset, GLsizei width, + GLsizei height, GLsizei depth, + GLenum format, + GLenum type, const GLvoid *pixels)) +COGL_EXT_END () + + + +COGL_EXT_BEGIN (offscreen_blit, 3, 0, + 0, /* not in either GLES */ + "EXT\0ANGLE\0", + "framebuffer_blit\0") +COGL_EXT_FUNCTION (void, glBlitFramebuffer, + (GLint srcX0, + GLint srcY0, + GLint srcX1, + GLint srcY1, + GLint dstX0, + GLint dstY0, + GLint dstX1, + GLint dstY1, + GLbitfield mask, + GLenum filter)) +COGL_EXT_END () + +/* ARB_fragment_program */ +COGL_EXT_BEGIN (arbfp, 255, 255, + 0, /* not in either GLES */ + "ARB\0", + "fragment_program\0") +COGL_EXT_FUNCTION (void, glGenPrograms, + (GLsizei n, + GLuint *programs)) +COGL_EXT_FUNCTION (void, glDeletePrograms, + (GLsizei n, + GLuint *programs)) +COGL_EXT_FUNCTION (void, glBindProgram, + (GLenum target, + GLuint program)) +COGL_EXT_FUNCTION (void, glProgramString, + (GLenum target, + GLenum format, + GLsizei len, + const void *program)) +COGL_EXT_FUNCTION (void, glProgramLocalParameter4fv, + (GLenum target, + GLuint index, + GLfloat *params)) +COGL_EXT_END () + +COGL_EXT_BEGIN (EGL_image, 255, 255, + 0, /* not in either GLES */ + "OES\0", + "EGL_image\0") +COGL_EXT_FUNCTION (void, glEGLImageTargetTexture2D, + (GLenum target, + GLeglImageOES image)) +COGL_EXT_FUNCTION (void, glEGLImageTargetRenderbufferStorage, + (GLenum target, + GLeglImageOES image)) +COGL_EXT_END () + +COGL_EXT_BEGIN (framebuffer_discard, 255, 255, + 0, /* not in either GLES */ + "EXT\0", + "framebuffer_discard\0") +COGL_EXT_FUNCTION (void, glDiscardFramebuffer, + (GLenum target, + GLsizei numAttachments, + const GLenum *attachments)) +COGL_EXT_END () + +COGL_EXT_BEGIN (IMG_multisampled_render_to_texture, 255, 255, + 0, /* not in either GLES */ + "\0", + "IMG_multisampled_render_to_texture\0") +COGL_EXT_FUNCTION (void, glRenderbufferStorageMultisampleIMG, + (GLenum target, + GLsizei samples, + GLenum internal_format, + GLsizei width, + GLsizei height)) +COGL_EXT_FUNCTION (void, glFramebufferTexture2DMultisampleIMG, + (GLenum target, + GLenum attachment, + GLenum textarget, + GLuint texture, + GLint level, + GLsizei samples)) +COGL_EXT_END () + +COGL_EXT_BEGIN (ARB_sampler_objects, 3, 3, + 0, /* not in either GLES */ + "ARB:\0", + "sampler_objects\0") +COGL_EXT_FUNCTION (void, glGenSamplers, + (GLsizei count, + GLuint *samplers)) +COGL_EXT_FUNCTION (void, glDeleteSamplers, + (GLsizei count, + const GLuint *samplers)) +COGL_EXT_FUNCTION (void, glBindSampler, + (GLuint unit, + GLuint sampler)) +COGL_EXT_FUNCTION (void, glSamplerParameteri, + (GLuint sampler, + GLenum pname, + GLint param)) +COGL_EXT_END () + +/* These only list functions that come from the old GLSL extensions. + * Functions that are common to the extensions and GLSL 2.0 should + * instead be listed in cogl-glsl-functions.h */ +COGL_EXT_BEGIN (shader_objects, 255, 255, + 0, /* not in either GLES */ + "ARB\0", + "shader_objects\0") +COGL_EXT_FUNCTION (GLuint, glCreateProgramObject, + (void)) +COGL_EXT_FUNCTION (GLuint, glCreateShaderObject, + (GLenum shaderType)) +COGL_EXT_FUNCTION (void, glDeleteObject, + (GLuint obj)) +COGL_EXT_FUNCTION (void, glAttachObject, + (GLuint container, GLuint obj)) +COGL_EXT_FUNCTION (void, glUseProgramObject, + (GLuint programObj)) +COGL_EXT_FUNCTION (void, glGetInfoLog, + (GLuint obj, + GLsizei maxLength, + GLsizei *length, + char *infoLog)) +COGL_EXT_FUNCTION (void, glGetObjectParameteriv, + (GLuint obj, + GLenum pname, + GLint *params)) +COGL_EXT_FUNCTION (void, glDetachObject, + (GLuint container, GLuint obj)) +COGL_EXT_FUNCTION (void, glGetAttachedObjects, + (GLuint program, + GLsizei maxcount, + GLsizei* count, + GLuint* shaders)) +COGL_EXT_END () + +COGL_EXT_BEGIN (only_gl3, 3, 0, + 0, /* not in either GLES */ + "\0", + "\0") +COGL_EXT_FUNCTION (const GLubyte *, glGetStringi, + (GLenum name, GLuint index)) +COGL_EXT_END () + +COGL_EXT_BEGIN (vertex_array_object, 3, 0, + 0, /* not in either GLES */ + "ARB\0OES\0", + "vertex_array_object\0") +COGL_EXT_FUNCTION (void, glBindVertexArray, + (GLuint array)) +COGL_EXT_FUNCTION (void, glDeleteVertexArrays, + (GLsizei n, + const GLuint *arrays)) +COGL_EXT_FUNCTION (void, glGenVertexArrays, + (GLsizei n, + GLuint *arrays)) +COGL_EXT_END () + +COGL_EXT_BEGIN (map_region, 3, 0, + COGL_EXT_IN_GLES3, + "ARB:\0", + "map_buffer_range\0") +COGL_EXT_FUNCTION (GLvoid *, glMapBufferRange, + (GLenum target, + GLintptr offset, + GLsizeiptr length, + GLbitfield access)) +COGL_EXT_END () + +#ifdef GL_ARB_sync +COGL_EXT_BEGIN (sync, 3, 2, + 0, /* not in either GLES */ + "ARB:\0", + "sync\0") +COGL_EXT_FUNCTION (GLsync, glFenceSync, + (GLenum condition, GLbitfield flags)) +COGL_EXT_FUNCTION (GLenum, glClientWaitSync, + (GLsync sync, GLbitfield flags, GLuint64 timeout)) +COGL_EXT_FUNCTION (void, glDeleteSync, + (GLsync sync)) +COGL_EXT_END () +#endif + +COGL_EXT_BEGIN (draw_buffers, 2, 0, + COGL_EXT_IN_GLES3, + "ARB\0EXT\0", + "draw_buffers\0") +COGL_EXT_FUNCTION (void, glDrawBuffers, + (GLsizei n, const GLenum *bufs)) +COGL_EXT_END () + +COGL_EXT_BEGIN (robustness, 255, 255, + 0, + "ARB\0", + "robustness\0") +COGL_EXT_FUNCTION (GLenum, glGetGraphicsResetStatus, + (void)) +COGL_EXT_END () diff --git a/cogl/cogl/gl-prototypes/cogl-core-functions.h b/cogl/cogl/gl-prototypes/cogl-core-functions.h new file mode 100644 index 0000000..f37041b --- /dev/null +++ b/cogl/cogl/gl-prototypes/cogl-core-functions.h @@ -0,0 +1,198 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009, 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +/* This is included multiple times with different definitions for + * these macros. The macros are given the following arguments: + * + * COGL_EXT_BEGIN: + * + * @name: a unique symbol name for this feature + * + * @min_gl_major: the major part of the minimum GL version where these + * functions are available in core, or 255 if it isn't available in + * any version. + * @min_gl_minor: the minor part of the minimum GL version where these + * functions are available in core, or 255 if it isn't available in + * any version. + * + * @gles_availability: flags to specify which versions of GLES the + * functions are available in. Should be a combination of + * COGL_EXT_IN_GLES and COGL_EXT_IN_GLES2. + * + * @extension_suffixes: A zero-separated list of suffixes in a + * string. These are appended to the extension name to get a complete + * extension name to try. The suffix is also appended to all of the + * function names. The suffix can optionally include a ':' to specify + * an alternate suffix for the function names. + * + * @extension_names: A list of extension names to try. If any of these + * extensions match then it will be used. + */ + +/* These are the core GL functions which we assume will always be + available */ +COGL_EXT_BEGIN (core, + 0, 0, + COGL_EXT_IN_GLES | COGL_EXT_IN_GLES2, + "\0", + "\0") +COGL_EXT_FUNCTION (void, glBindTexture, + (GLenum target, GLuint texture)) +COGL_EXT_FUNCTION (void, glBlendFunc, + (GLenum sfactor, GLenum dfactor)) +COGL_EXT_FUNCTION (void, glClear, + (GLbitfield mask)) +COGL_EXT_FUNCTION (void, glClearColor, + (GLclampf red, + GLclampf green, + GLclampf blue, + GLclampf alpha)) +COGL_EXT_FUNCTION (void, glClearStencil, + (GLint s)) +COGL_EXT_FUNCTION (void, glColorMask, + (GLboolean red, + GLboolean green, + GLboolean blue, + GLboolean alpha)) +COGL_EXT_FUNCTION (void, glCopyTexSubImage2D, + (GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height)) +COGL_EXT_FUNCTION (void, glDeleteTextures, + (GLsizei n, const GLuint* textures)) +COGL_EXT_FUNCTION (void, glDepthFunc, + (GLenum func)) +COGL_EXT_FUNCTION (void, glDepthMask, + (GLboolean flag)) +COGL_EXT_FUNCTION (void, glDisable, + (GLenum cap)) +COGL_EXT_FUNCTION (void, glDrawArrays, + (GLenum mode, GLint first, GLsizei count)) +COGL_EXT_FUNCTION (void, glDrawElements, + (GLenum mode, + GLsizei count, + GLenum type, + const GLvoid* indices)) +COGL_EXT_FUNCTION (void, glEnable, + (GLenum cap)) +COGL_EXT_FUNCTION (void, glFinish, + (void)) +COGL_EXT_FUNCTION (void, glFlush, + (void)) +COGL_EXT_FUNCTION (void, glFrontFace, + (GLenum mode)) +COGL_EXT_FUNCTION (void, glCullFace, + (GLenum mode)) +COGL_EXT_FUNCTION (void, glGenTextures, + (GLsizei n, GLuint* textures)) +COGL_EXT_FUNCTION (GLenum, glGetError, + (void)) +COGL_EXT_FUNCTION (void, glGetIntegerv, + (GLenum pname, GLint* params)) +COGL_EXT_FUNCTION (void, glGetBooleanv, + (GLenum pname, GLboolean* params)) +COGL_EXT_FUNCTION (void, glGetFloatv, + (GLenum pname, GLfloat* params)) +COGL_EXT_FUNCTION (const GLubyte*, glGetString, + (GLenum name)) +COGL_EXT_FUNCTION (void, glHint, + (GLenum target, GLenum mode)) +COGL_EXT_FUNCTION (GLboolean, glIsTexture, + (GLuint texture)) +COGL_EXT_FUNCTION (void, glPixelStorei, + (GLenum pname, GLint param)) +COGL_EXT_FUNCTION (void, glReadPixels, + (GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + GLvoid* pixels)) +COGL_EXT_FUNCTION (void, glScissor, + (GLint x, GLint y, GLsizei width, GLsizei height)) +COGL_EXT_FUNCTION (void, glStencilFunc, + (GLenum func, GLint ref, GLuint mask)) +COGL_EXT_FUNCTION (void, glStencilMask, + (GLuint mask)) +COGL_EXT_FUNCTION (void, glStencilOp, + (GLenum fail, GLenum zfail, GLenum zpass)) +COGL_EXT_FUNCTION (void, glTexImage2D, + (GLenum target, + GLint level, + GLint internalformat, + GLsizei width, + GLsizei height, + GLint border, + GLenum format, + GLenum type, + const GLvoid* pixels)) +COGL_EXT_FUNCTION (void, glTexParameterf, + (GLenum target, GLenum pname, GLfloat param)) +COGL_EXT_FUNCTION (void, glTexParameterfv, + (GLenum target, GLenum pname, const GLfloat* params)) +COGL_EXT_FUNCTION (void, glTexParameteri, + (GLenum target, GLenum pname, GLint param)) +COGL_EXT_FUNCTION (void, glTexParameteriv, + (GLenum target, GLenum pname, const GLint* params)) +COGL_EXT_FUNCTION (void, glGetTexParameterfv, + (GLenum target, GLenum pname, GLfloat* params)) +COGL_EXT_FUNCTION (void, glGetTexParameteriv, + (GLenum target, GLenum pname, GLint* params)) +COGL_EXT_FUNCTION (void, glTexSubImage2D, + (GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + const GLvoid* pixels)) +COGL_EXT_FUNCTION (void, glCopyTexImage2D, + (GLenum target, + GLint level, + GLenum internalformat, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLint border)) +COGL_EXT_FUNCTION (void, glViewport, + (GLint x, GLint y, GLsizei width, GLsizei height)) +COGL_EXT_FUNCTION (GLboolean, glIsEnabled, (GLenum cap)) +COGL_EXT_FUNCTION (void, glLineWidth, (GLfloat width)) +COGL_EXT_FUNCTION (void, glPolygonOffset, (GLfloat factor, GLfloat units)) +COGL_EXT_END () diff --git a/cogl/cogl/gl-prototypes/cogl-fixed-functions.h b/cogl/cogl/gl-prototypes/cogl-fixed-functions.h new file mode 100644 index 0000000..ce7b4e0 --- /dev/null +++ b/cogl/cogl/gl-prototypes/cogl-fixed-functions.h @@ -0,0 +1,119 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009, 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +/* This is included multiple times with different definitions for + * these macros. The macros are given the following arguments: + * + * COGL_EXT_BEGIN: + * + * @name: a unique symbol name for this feature + * + * @min_gl_major: the major part of the minimum GL version where these + * functions are available in core, or 255 if it isn't available in + * any version. + * @min_gl_minor: the minor part of the minimum GL version where these + * functions are available in core, or 255 if it isn't available in + * any version. + * + * @gles_availability: flags to specify which versions of GLES the + * functions are available in. Should be a combination of + * COGL_EXT_IN_GLES and COGL_EXT_IN_GLES2. + * + * @extension_suffixes: A zero-separated list of suffixes in a + * string. These are appended to the extension name to get a complete + * extension name to try. The suffix is also appended to all of the + * function names. The suffix can optionally include a ':' to specify + * an alternate suffix for the function names. + * + * @extension_names: A list of extension names to try. If any of these + * extensions match then it will be used. + */ + +/* These are the core GL functions which are available when the API + supports fixed-function (ie, GL and GLES1.1) */ +COGL_EXT_BEGIN (fixed_function_core, + 0, 0, + COGL_EXT_IN_GLES, + "\0", + "\0") +COGL_EXT_FUNCTION (void, glAlphaFunc, + (GLenum func, GLclampf ref)) +COGL_EXT_FUNCTION (void, glFogf, + (GLenum pname, GLfloat param)) +COGL_EXT_FUNCTION (void, glFogfv, + (GLenum pname, const GLfloat *params)) +COGL_EXT_FUNCTION (void, glLoadMatrixf, + (const GLfloat *m)) +COGL_EXT_FUNCTION (void, glMaterialfv, + (GLenum face, GLenum pname, const GLfloat *params)) +COGL_EXT_FUNCTION (void, glPointSize, + (GLfloat size)) +COGL_EXT_FUNCTION (void, glTexEnvfv, + (GLenum target, GLenum pname, const GLfloat *params)) +COGL_EXT_FUNCTION (void, glColor4ub, + (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha)) +COGL_EXT_FUNCTION (void, glColor4f, + (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)) +COGL_EXT_FUNCTION (void, glColorPointer, + (GLint size, + GLenum type, + GLsizei stride, + const GLvoid *pointer)) +COGL_EXT_FUNCTION (void, glDisableClientState, + (GLenum array)) +COGL_EXT_FUNCTION (void, glEnableClientState, + (GLenum array)) +COGL_EXT_FUNCTION (void, glLoadIdentity, + (void)) +COGL_EXT_FUNCTION (void, glMatrixMode, + (GLenum mode)) +COGL_EXT_FUNCTION (void, glNormal3f, + (GLfloat x, GLfloat y, GLfloat z)) +COGL_EXT_FUNCTION (void, glNormalPointer, + (GLenum type, GLsizei stride, const GLvoid *pointer)) +COGL_EXT_FUNCTION (void, glMultiTexCoord4f, + (GLfloat s, GLfloat t, GLfloat r, GLfloat q)) +COGL_EXT_FUNCTION (void, glTexCoordPointer, + (GLint size, + GLenum type, + GLsizei stride, + const GLvoid *pointer)) +COGL_EXT_FUNCTION (void, glTexEnvi, + (GLenum target, + GLenum pname, + GLint param)) +COGL_EXT_FUNCTION (void, glVertex4f, + (GLfloat x, GLfloat y, GLfloat z, GLfloat w)) +COGL_EXT_FUNCTION (void, glVertexPointer, + (GLint size, + GLenum type, + GLsizei stride, + const GLvoid *pointer)) +COGL_EXT_END () diff --git a/cogl/cogl/gl-prototypes/cogl-gles1-functions.h b/cogl/cogl/gl-prototypes/cogl-gles1-functions.h new file mode 100644 index 0000000..774b9b3 --- /dev/null +++ b/cogl/cogl/gl-prototypes/cogl-gles1-functions.h @@ -0,0 +1,43 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009, 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +/* The functions in this file are part of the core GL,GLES1 and GLES2 apis */ +#include "cogl-core-functions.h" + +/* The functions in this file are core to GLES1 and GLES2 but not core + * to GL but they may be extensions available for GL */ +#include "cogl-in-gles-core-functions.h" + +/* The functions in this file are core to GLES1 only but + * may be extensions for GLES2 and GL */ +#include "cogl-in-gles1-core-functions.h" + +/* These are fixed-function APIs core to GL and GLES1 */ +#include "cogl-fixed-functions.h" diff --git a/cogl/cogl/gl-prototypes/cogl-gles2-functions.h b/cogl/cogl/gl-prototypes/cogl-gles2-functions.h new file mode 100644 index 0000000..aeb57a4 --- /dev/null +++ b/cogl/cogl/gl-prototypes/cogl-gles2-functions.h @@ -0,0 +1,43 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009, 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +/* The functions in this file are part of the core GL,GLES1 and GLES2 apis */ +#include "cogl-core-functions.h" + +/* The functions in this file are core to GLES1 and GLES2 but not core + * to GL but they may be extensions available for GL */ +#include "cogl-in-gles-core-functions.h" + +/* The functions in this file are core to GLES2 only but + * may be extensions for GLES1 and GL */ +#include "cogl-in-gles2-core-functions.h" + +/* These are APIs for using GLSL used by GL and GLES2 */ +#include "cogl-glsl-functions.h" diff --git a/cogl/cogl/gl-prototypes/cogl-glsl-functions.h b/cogl/cogl/gl-prototypes/cogl-glsl-functions.h new file mode 100644 index 0000000..980f8ad --- /dev/null +++ b/cogl/cogl/gl-prototypes/cogl-glsl-functions.h @@ -0,0 +1,286 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009, 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +/* This is included multiple times with different definitions for + * these macros. The macros are given the following arguments: + * + * COGL_EXT_BEGIN: + * + * @name: a unique symbol name for this feature + * + * @min_gl_major: the major part of the minimum GL version where these + * functions are available in core, or 255 if it isn't available in + * any version. + * @min_gl_minor: the minor part of the minimum GL version where these + * functions are available in core, or 255 if it isn't available in + * any version. + * + * @gles_availability: flags to specify which versions of GLES the + * functions are available in. Should be a combination of + * COGL_EXT_IN_GLES and COGL_EXT_IN_GLES2. + * + * @extension_suffixes: A zero-separated list of suffixes in a + * string. These are appended to the extension name to get a complete + * extension name to try. The suffix is also appended to all of the + * function names. The suffix can optionally include a ':' to specify + * an alternate suffix for the function names. + * + * @extension_names: A list of extension names to try. If any of these + * extensions match then it will be used. + */ + +/* This lists functions that are unique to GL 2.0 or GLES 2.0 and are + * not in the old GLSL extensions */ +COGL_EXT_BEGIN (shaders_glsl_2_only, 2, 0, + COGL_EXT_IN_GLES2, + "\0", + "\0") +COGL_EXT_FUNCTION (GLuint, glCreateProgram, + (void)) +COGL_EXT_FUNCTION (GLuint, glCreateShader, + (GLenum shaderType)) +COGL_EXT_FUNCTION (void, glDeleteShader, + (GLuint shader)) +COGL_EXT_FUNCTION (void, glAttachShader, + (GLuint program, + GLuint shader)) +COGL_EXT_FUNCTION (void, glUseProgram, + (GLuint program)) +COGL_EXT_FUNCTION (void, glDeleteProgram, + (GLuint program)) +COGL_EXT_FUNCTION (void, glGetShaderInfoLog, + (GLuint shader, + GLsizei maxLength, + GLsizei *length, + char *infoLog)) +COGL_EXT_FUNCTION (void, glGetProgramInfoLog, + (GLuint program, + GLsizei bufSize, + GLsizei *length, + char *infoLog)) +COGL_EXT_FUNCTION (void, glGetShaderiv, + (GLuint shader, + GLenum pname, + GLint *params)) +COGL_EXT_FUNCTION (void, glGetProgramiv, + (GLuint program, + GLenum pname, + GLint *params)) +COGL_EXT_FUNCTION (void, glDetachShader, + (GLuint program, GLuint shader)) +COGL_EXT_FUNCTION (void, glGetAttachedShaders, + (GLuint program, + GLsizei maxcount, + GLsizei* count, + GLuint* shaders)) +COGL_EXT_FUNCTION (GLboolean, glIsShader, + (GLuint shader)) +COGL_EXT_FUNCTION (GLboolean, glIsProgram, + (GLuint program)) +COGL_EXT_END () + +/* These functions are provided by GL_ARB_shader_objects or are in GL + * 2.0 core */ +COGL_EXT_BEGIN (shader_objects_or_gl2, 2, 0, + COGL_EXT_IN_GLES2, + "ARB\0", + "shader_objects\0") +COGL_EXT_FUNCTION (void, glShaderSource, + (GLuint shader, + GLsizei count, + const char * const *string, + const GLint *length)) +COGL_EXT_FUNCTION (void, glCompileShader, + (GLuint shader)) +COGL_EXT_FUNCTION (void, glLinkProgram, + (GLuint program)) +COGL_EXT_FUNCTION (GLint, glGetUniformLocation, + (GLuint program, + const char *name)) +COGL_EXT_FUNCTION (void, glUniform1f, + (GLint location, + GLfloat v0)) +COGL_EXT_FUNCTION (void, glUniform2f, + (GLint location, + GLfloat v0, + GLfloat v1)) +COGL_EXT_FUNCTION (void, glUniform3f, + (GLint location, + GLfloat v0, + GLfloat v1, + GLfloat v2)) +COGL_EXT_FUNCTION (void, glUniform4f, + (GLint location, + GLfloat v0, + GLfloat v1, + GLfloat v2, + GLfloat v3)) +COGL_EXT_FUNCTION (void, glUniform1fv, + (GLint location, + GLsizei count, + const GLfloat * value)) +COGL_EXT_FUNCTION (void, glUniform2fv, + (GLint location, + GLsizei count, + const GLfloat * value)) +COGL_EXT_FUNCTION (void, glUniform3fv, + (GLint location, + GLsizei count, + const GLfloat * value)) +COGL_EXT_FUNCTION (void, glUniform4fv, + (GLint location, + GLsizei count, + const GLfloat * value)) +COGL_EXT_FUNCTION (void, glUniform1i, + (GLint location, + GLint v0)) +COGL_EXT_FUNCTION (void, glUniform2i, + (GLint location, + GLint v0, + GLint v1)) +COGL_EXT_FUNCTION (void, glUniform3i, + (GLint location, + GLint v0, + GLint v1, + GLint v2)) +COGL_EXT_FUNCTION (void, glUniform4i, + (GLint location, + GLint v0, + GLint v1, + GLint v2, + GLint v3)) +COGL_EXT_FUNCTION (void, glUniform1iv, + (GLint location, + GLsizei count, + const GLint * value)) +COGL_EXT_FUNCTION (void, glUniform2iv, + (GLint location, + GLsizei count, + const GLint * value)) +COGL_EXT_FUNCTION (void, glUniform3iv, + (GLint location, + GLsizei count, + const GLint * value)) +COGL_EXT_FUNCTION (void, glUniform4iv, + (GLint location, + GLsizei count, + const GLint * value)) +COGL_EXT_FUNCTION (void, glUniformMatrix2fv, + (GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value)) +COGL_EXT_FUNCTION (void, glUniformMatrix3fv, + (GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value)) +COGL_EXT_FUNCTION (void, glUniformMatrix4fv, + (GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value)) + +COGL_EXT_FUNCTION (void, glGetUniformfv, + (GLuint program, + GLint location, + GLfloat *params)) +COGL_EXT_FUNCTION (void, glGetUniformiv, + (GLuint program, + GLint location, + GLint *params)) +COGL_EXT_FUNCTION (void, glGetActiveUniform, + (GLuint program, + GLuint index, + GLsizei bufsize, + GLsizei* length, + GLint* size, + GLenum* type, + GLchar* name)) +COGL_EXT_FUNCTION (void, glGetShaderSource, + (GLuint shader, + GLsizei bufsize, + GLsizei* length, + GLchar* source)) +COGL_EXT_FUNCTION (void, glValidateProgram, (GLuint program)) +COGL_EXT_END () + +/* These functions are provided by GL_ARB_vertex_shader or are in GL + * 2.0 core */ +COGL_EXT_BEGIN (vertex_shaders, 2, 0, + COGL_EXT_IN_GLES2, + "ARB\0", + "vertex_shader\0") +COGL_EXT_FUNCTION (void, glVertexAttribPointer, + (GLuint index, + GLint size, + GLenum type, + GLboolean normalized, + GLsizei stride, + const GLvoid *pointer)) +COGL_EXT_FUNCTION (void, glEnableVertexAttribArray, + (GLuint index)) +COGL_EXT_FUNCTION (void, glDisableVertexAttribArray, + (GLuint index)) +COGL_EXT_FUNCTION (void, glVertexAttrib1f, (GLuint indx, GLfloat x)) +COGL_EXT_FUNCTION (void, glVertexAttrib1fv, + (GLuint indx, const GLfloat* values)) +COGL_EXT_FUNCTION (void, glVertexAttrib2f, (GLuint indx, GLfloat x, GLfloat y)) +COGL_EXT_FUNCTION (void, glVertexAttrib2fv, + (GLuint indx, const GLfloat* values)) +COGL_EXT_FUNCTION (void, glVertexAttrib3f, + (GLuint indx, GLfloat x, GLfloat y, GLfloat z)) +COGL_EXT_FUNCTION (void, glVertexAttrib3fv, + (GLuint indx, const GLfloat* values)) +COGL_EXT_FUNCTION (void, glVertexAttrib4f, + (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)) +COGL_EXT_FUNCTION (void, glVertexAttrib4fv, + (GLuint indx, const GLfloat* values)) +COGL_EXT_FUNCTION (void, glGetVertexAttribfv, + (GLuint index, GLenum pname, GLfloat* params)) +COGL_EXT_FUNCTION (void, glGetVertexAttribiv, + (GLuint index, GLenum pname, GLint* params)) +COGL_EXT_FUNCTION (void, glGetVertexAttribPointerv, + (GLuint index, GLenum pname, GLvoid** pointer)) +COGL_EXT_FUNCTION (GLint, glGetAttribLocation, + (GLuint program, const char *name)) +COGL_EXT_FUNCTION (void, glBindAttribLocation, + (GLuint program, + GLuint index, + const GLchar* name)) +COGL_EXT_FUNCTION (void, glGetActiveAttrib, + (GLuint program, + GLuint index, + GLsizei bufsize, + GLsizei* length, + GLint* size, + GLenum* type, + GLchar* name)) +COGL_EXT_END () diff --git a/cogl/cogl/gl-prototypes/cogl-in-gles-core-functions.h b/cogl/cogl/gl-prototypes/cogl-in-gles-core-functions.h new file mode 100644 index 0000000..5679e72 --- /dev/null +++ b/cogl/cogl/gl-prototypes/cogl-in-gles-core-functions.h @@ -0,0 +1,148 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009, 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +/* This is included multiple times with different definitions for + * these macros. The macros are given the following arguments: + * + * COGL_EXT_BEGIN: + * + * @name: a unique symbol name for this feature + * + * @min_gl_major: the major part of the minimum GL version where these + * functions are available in core, or 255 if it isn't available in + * any version. + * @min_gl_minor: the minor part of the minimum GL version where these + * functions are available in core, or 255 if it isn't available in + * any version. + * + * @gles_availability: flags to specify which versions of GLES the + * functions are available in. Should be a combination of + * COGL_EXT_IN_GLES and COGL_EXT_IN_GLES2. + * + * @extension_suffixes: A zero-separated list of suffixes in a + * string. These are appended to the extension name to get a complete + * extension name to try. The suffix is also appended to all of the + * function names. The suffix can optionally include a ':' to specify + * an alternate suffix for the function names. + * + * @extension_names: A list of extension names to try. If any of these + * extensions match then it will be used. + */ + +COGL_EXT_BEGIN (only_in_both_gles, + 4, 1, + COGL_EXT_IN_GLES | + COGL_EXT_IN_GLES2, + "ARB\0", + "ES2_compatibility\0") +COGL_EXT_FUNCTION (void, glDepthRangef, + (GLfloat near_val, GLfloat far_val)) +COGL_EXT_FUNCTION (void, glClearDepthf, + (GLclampf depth)) +COGL_EXT_END () + +COGL_EXT_BEGIN (only_in_both_gles_and_gl_1_3, + 1, 3, + COGL_EXT_IN_GLES | + COGL_EXT_IN_GLES2, + "\0", + "\0") +COGL_EXT_FUNCTION (void, glCompressedTexImage2D, + (GLenum target, + GLint level, + GLenum internalformat, + GLsizei width, + GLsizei height, + GLint border, + GLsizei imageSize, + const GLvoid* data)) +COGL_EXT_FUNCTION (void, glCompressedTexSubImage2D, + (GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLsizei width, + GLsizei height, + GLenum format, + GLsizei imageSize, + const GLvoid* data)) +COGL_EXT_FUNCTION (void, glSampleCoverage, + (GLclampf value, GLboolean invert)) +COGL_EXT_END () + +COGL_EXT_BEGIN (only_in_both_gles_and_gl_1_5, + 1, 5, + COGL_EXT_IN_GLES | + COGL_EXT_IN_GLES2, + "\0", + "\0") +COGL_EXT_FUNCTION (void, glGetBufferParameteriv, + (GLenum target, GLenum pname, GLint* params)) +COGL_EXT_END () + +COGL_EXT_BEGIN (vbos, 1, 5, + COGL_EXT_IN_GLES | + COGL_EXT_IN_GLES2, + "ARB\0", + "vertex_buffer_object\0") +COGL_EXT_FUNCTION (void, glGenBuffers, + (GLsizei n, + GLuint *buffers)) +COGL_EXT_FUNCTION (void, glBindBuffer, + (GLenum target, + GLuint buffer)) +COGL_EXT_FUNCTION (void, glBufferData, + (GLenum target, + GLsizeiptr size, + const GLvoid *data, + GLenum usage)) +COGL_EXT_FUNCTION (void, glBufferSubData, + (GLenum target, + GLintptr offset, + GLsizeiptr size, + const GLvoid *data)) +COGL_EXT_FUNCTION (void, glDeleteBuffers, + (GLsizei n, + const GLuint *buffers)) +COGL_EXT_FUNCTION (GLboolean, glIsBuffer, + (GLuint buffer)) +COGL_EXT_END () + +/* Available in GL 1.3, the multitexture extension or GLES. These are + required */ +COGL_EXT_BEGIN (multitexture_part0, 1, 3, + COGL_EXT_IN_GLES | + COGL_EXT_IN_GLES2, + "ARB\0", + "multitexture\0") +COGL_EXT_FUNCTION (void, glActiveTexture, + (GLenum texture)) +COGL_EXT_END () + diff --git a/cogl/cogl/gl-prototypes/cogl-in-gles1-core-functions.h b/cogl/cogl/gl-prototypes/cogl-in-gles1-core-functions.h new file mode 100644 index 0000000..20dc1a8 --- /dev/null +++ b/cogl/cogl/gl-prototypes/cogl-in-gles1-core-functions.h @@ -0,0 +1,78 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009, 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +/* This is included multiple times with different definitions for + * these macros. The macros are given the following arguments: + * + * COGL_EXT_BEGIN: + * + * @name: a unique symbol name for this feature + * + * @min_gl_major: the major part of the minimum GL version where these + * functions are available in core, or 255 if it isn't available in + * any version. + * @min_gl_minor: the minor part of the minimum GL version where these + * functions are available in core, or 255 if it isn't available in + * any version. + * + * @gles_availability: flags to specify which versions of GLES the + * functions are available in. Should be a combination of + * COGL_EXT_IN_GLES and COGL_EXT_IN_GLES2. + * + * @extension_suffixes: A zero-separated list of suffixes in a + * string. These are appended to the extension name to get a complete + * extension name to try. The suffix is also appended to all of the + * function names. The suffix can optionally include a ':' to specify + * an alternate suffix for the function names. + * + * @extension_names: A list of extension names to try. If any of these + * extensions match then it will be used. + */ + +/* These functions are only available in GLES and are used as + replacements for some GL equivalents that only accept double + arguments */ +COGL_EXT_BEGIN (only_in_gles1, + 255, 255, + COGL_EXT_IN_GLES, + "\0", + "\0") +COGL_EXT_FUNCTION (void, glClipPlanef, + (GLenum plane, const GLfloat *equation)) +COGL_EXT_END () + +COGL_EXT_BEGIN (multitexture_part1, 1, 3, + COGL_EXT_IN_GLES, + "ARB\0", + "multitexture\0") +COGL_EXT_FUNCTION (void, glClientActiveTexture, + (GLenum texture)) +COGL_EXT_END () + diff --git a/cogl/cogl/gl-prototypes/cogl-in-gles2-core-functions.h b/cogl/cogl/gl-prototypes/cogl-in-gles2-core-functions.h new file mode 100644 index 0000000..1e2f79e --- /dev/null +++ b/cogl/cogl/gl-prototypes/cogl-in-gles2-core-functions.h @@ -0,0 +1,186 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009, 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +/* This is included multiple times with different definitions for + * these macros. The macros are given the following arguments: + * + * COGL_EXT_BEGIN: + * + * @name: a unique symbol name for this feature + * + * @min_gl_major: the major part of the minimum GL version where these + * functions are available in core, or 255 if it isn't available in + * any version. + * @min_gl_minor: the minor part of the minimum GL version where these + * functions are available in core, or 255 if it isn't available in + * any version. + * + * @gles_availability: flags to specify which versions of GLES the + * functions are available in. Should be a combination of + * COGL_EXT_IN_GLES and COGL_EXT_IN_GLES2. + * + * @extension_suffixes: A zero-separated list of suffixes in a + * string. These are appended to the extension name to get a complete + * extension name to try. The suffix is also appended to all of the + * function names. The suffix can optionally include a ':' to specify + * an alternate suffix for the function names. + * + * @extension_names: A list of extension names to try. If any of these + * extensions match then it will be used. + */ + +COGL_EXT_BEGIN (offscreen, + 3, 0, + COGL_EXT_IN_GLES2, + /* for some reason the ARB version of this + extension doesn't have an ARB suffix for the + functions */ + "ARB:\0EXT\0OES\0", + "framebuffer_object\0") +COGL_EXT_FUNCTION (void, glGenRenderbuffers, + (GLsizei n, + GLuint *renderbuffers)) +COGL_EXT_FUNCTION (void, glDeleteRenderbuffers, + (GLsizei n, + const GLuint *renderbuffers)) +COGL_EXT_FUNCTION (void, glBindRenderbuffer, + (GLenum target, + GLuint renderbuffer)) +COGL_EXT_FUNCTION (void, glRenderbufferStorage, + (GLenum target, + GLenum internalformat, + GLsizei width, + GLsizei height)) +COGL_EXT_FUNCTION (void, glGenFramebuffers, + (GLsizei n, + GLuint *framebuffers)) +COGL_EXT_FUNCTION (void, glBindFramebuffer, + (GLenum target, + GLuint framebuffer)) +COGL_EXT_FUNCTION (void, glFramebufferTexture2D, + (GLenum target, + GLenum attachment, + GLenum textarget, + GLuint texture, + GLint level)) +COGL_EXT_FUNCTION (void, glFramebufferRenderbuffer, + (GLenum target, + GLenum attachment, + GLenum renderbuffertarget, + GLuint renderbuffer)) +COGL_EXT_FUNCTION (GLboolean, glIsRenderbuffer, + (GLuint renderbuffer)) +COGL_EXT_FUNCTION (GLenum, glCheckFramebufferStatus, + (GLenum target)) +COGL_EXT_FUNCTION (void, glDeleteFramebuffers, + (GLsizei n, + const GLuint *framebuffers)) +COGL_EXT_FUNCTION (void, glGenerateMipmap, + (GLenum target)) +COGL_EXT_FUNCTION (void, glGetFramebufferAttachmentParameteriv, + (GLenum target, + GLenum attachment, + GLenum pname, + GLint *params)) +COGL_EXT_FUNCTION (void, glGetRenderbufferParameteriv, + (GLenum target, + GLenum pname, + GLint *params)) +COGL_EXT_FUNCTION (GLboolean, glIsFramebuffer, + (GLuint framebuffer)) +COGL_EXT_END () + +COGL_EXT_BEGIN (blending, 1, 2, + COGL_EXT_IN_GLES2, + "\0", + "\0") +COGL_EXT_FUNCTION (void, glBlendEquation, + (GLenum mode)) +COGL_EXT_FUNCTION (void, glBlendColor, + (GLclampf red, + GLclampf green, + GLclampf blue, + GLclampf alpha)) +COGL_EXT_END () + +/* Optional, declared in 1.4 or GLES 1.2 */ +COGL_EXT_BEGIN (blend_func_separate, 1, 4, + COGL_EXT_IN_GLES2, + "EXT\0", + "blend_func_separate\0") +COGL_EXT_FUNCTION (void, glBlendFuncSeparate, + (GLenum srcRGB, + GLenum dstRGB, + GLenum srcAlpha, + GLenum dstAlpha)) +COGL_EXT_END () + +/* Optional, declared in 2.0 */ +COGL_EXT_BEGIN (blend_equation_separate, 2, 0, + COGL_EXT_IN_GLES2, + "EXT\0", + "blend_equation_separate\0") +COGL_EXT_FUNCTION (void, glBlendEquationSeparate, + (GLenum modeRGB, + GLenum modeAlpha)) +COGL_EXT_END () + +COGL_EXT_BEGIN (gles2_only_api, + 4, 1, + COGL_EXT_IN_GLES2, + "ARB:\0", + "ES2_compatibility\0") +COGL_EXT_FUNCTION (void, glReleaseShaderCompiler, (void)) +COGL_EXT_FUNCTION (void, glGetShaderPrecisionFormat, + (GLenum shadertype, + GLenum precisiontype, + GLint* range, + GLint* precision)) +COGL_EXT_FUNCTION (void, glShaderBinary, + (GLsizei n, + const GLuint* shaders, + GLenum binaryformat, + const GLvoid* binary, + GLsizei length)) +COGL_EXT_END () + +/* GL and GLES 2.0 apis */ +COGL_EXT_BEGIN (two_point_zero_api, + 2, 0, + COGL_EXT_IN_GLES2, + "\0", + "\0") +COGL_EXT_FUNCTION (void, glStencilFuncSeparate, + (GLenum face, GLenum func, GLint ref, GLuint mask)) +COGL_EXT_FUNCTION (void, glStencilMaskSeparate, + (GLenum face, GLuint mask)) +COGL_EXT_FUNCTION (void, glStencilOpSeparate, + (GLenum face, GLenum fail, GLenum zfail, GLenum zpass)) +COGL_EXT_END () diff --git a/cogl/cogl/mutter-cogl-1.0.pc.in b/cogl/cogl/mutter-cogl-1.0.pc.in new file mode 100644 index 0000000..92e3a43 --- /dev/null +++ b/cogl/cogl/mutter-cogl-1.0.pc.in @@ -0,0 +1,13 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@/mutter +includedir=@includedir@/mutter +apiversion=1.0 +requires=@COGL_PKG_REQUIRES@ + +Name: Cogl +Description: An object oriented GL/GLES Abstraction/Utility Layer +Version: @COGL_1_VERSION@ +Libs: -L${libdir} -lmutter-cogl +Cflags: -I${includedir}/cogl +Requires: ${requires} diff --git a/cogl/cogl/winsys/cogl-texture-pixmap-x11-private.h b/cogl/cogl/winsys/cogl-texture-pixmap-x11-private.h new file mode 100644 index 0000000..5da998f --- /dev/null +++ b/cogl/cogl/winsys/cogl-texture-pixmap-x11-private.h @@ -0,0 +1,103 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_TEXTURE_PIXMAP_X11_PRIVATE_H +#define __COGL_TEXTURE_PIXMAP_X11_PRIVATE_H + +#include +#include +#include + +#include + +#ifdef COGL_HAS_GLX_SUPPORT +#include +#endif + +#include "cogl-object-private.h" +#include "cogl-texture-private.h" +#include "cogl-texture-pixmap-x11.h" + +typedef struct _CoglDamageRectangle CoglDamageRectangle; + +struct _CoglDamageRectangle +{ + unsigned int x1; + unsigned int y1; + unsigned int x2; + unsigned int y2; +}; + +/* For stereo, there are a pair of textures, but we want to share most + * other state (the GLXPixmap, visual, etc.) The way we do this is that + * the left-eye texture has all the state (there is in fact, no internal + * difference between the a MONO and a LEFT texture ), and the + * right-eye texture simply points to the left eye texture, with all + * other fields ignored. + */ +typedef enum +{ + COGL_TEXTURE_PIXMAP_MONO, + COGL_TEXTURE_PIXMAP_LEFT, + COGL_TEXTURE_PIXMAP_RIGHT +} CoglTexturePixmapStereoMode; + +struct _CoglTexturePixmapX11 +{ + CoglTexture _parent; + + CoglTexturePixmapStereoMode stereo_mode; + CoglTexturePixmapX11 *left; /* Set only if stereo_mode=RIGHT */ + + Pixmap pixmap; + CoglTexture *tex; + + unsigned int depth; + Visual *visual; + + XImage *image; + + XShmSegmentInfo shm_info; + + Damage damage; + CoglTexturePixmapX11ReportLevel damage_report_level; + CoglBool damage_owned; + CoglDamageRectangle damage_rect; + + void *winsys; + + /* During the pre_paint method, this will be set to TRUE if we + should use the winsys texture, otherwise we will use the regular + texture */ + CoglBool use_winsys_texture; +}; + + +#endif /* __COGL_TEXTURE_PIXMAP_X11_PRIVATE_H */ diff --git a/cogl/cogl/winsys/cogl-texture-pixmap-x11.c b/cogl/cogl/winsys/cogl-texture-pixmap-x11.c new file mode 100644 index 0000000..d03040c --- /dev/null +++ b/cogl/cogl/winsys/cogl-texture-pixmap-x11.c @@ -0,0 +1,1184 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * + * Authors: + * Neil Roberts + * Johan Bilien + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-debug.h" +#include "cogl-util.h" +#include "cogl-texture-pixmap-x11.h" +#include "cogl-texture-pixmap-x11-private.h" +#include "cogl-bitmap-private.h" +#include "cogl-texture-private.h" +#include "cogl-texture-driver.h" +#include "cogl-texture-2d-private.h" +#include "cogl-texture-2d-sliced.h" +#include "cogl-texture-rectangle-private.h" +#include "cogl-context-private.h" +#include "cogl-display-private.h" +#include "cogl-renderer-private.h" +#include "cogl-object-private.h" +#include "cogl-winsys-private.h" +#include "cogl-pipeline-opengl-private.h" +#include "cogl-xlib.h" +#include "cogl-error-private.h" +#include "cogl-texture-gl-private.h" +#include "cogl-private.h" +#include "cogl-gtype-private.h" + +#include +#include + +#include +#include +#include + +#include +#include + +static void _cogl_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap); + +COGL_TEXTURE_DEFINE (TexturePixmapX11, texture_pixmap_x11); +COGL_GTYPE_DEFINE_CLASS (TexturePixmapX11, texture_pixmap_x11); + +static const CoglTextureVtable cogl_texture_pixmap_x11_vtable; + +uint32_t +cogl_texture_pixmap_x11_error_quark (void) +{ + return g_quark_from_static_string ("cogl-texture-pixmap-error-quark"); +} + +static void +cogl_damage_rectangle_union (CoglDamageRectangle *damage_rect, + int x, + int y, + int width, + int height) +{ + /* If the damage region is empty then we'll just copy the new + rectangle directly */ + if (damage_rect->x1 == damage_rect->x2 || + damage_rect->y1 == damage_rect->y2) + { + damage_rect->x1 = x; + damage_rect->y1 = y; + damage_rect->x2 = x + width; + damage_rect->y2 = y + height; + } + else + { + if (damage_rect->x1 > x) + damage_rect->x1 = x; + if (damage_rect->y1 > y) + damage_rect->y1 = y; + if (damage_rect->x2 < x + width) + damage_rect->x2 = x + width; + if (damage_rect->y2 < y + height) + damage_rect->y2 = y + height; + } +} + +static CoglBool +cogl_damage_rectangle_is_whole (const CoglDamageRectangle *damage_rect, + unsigned int width, + unsigned int height) +{ + return (damage_rect->x1 == 0 && damage_rect->y1 == 0 + && damage_rect->x2 == width && damage_rect->y2 == height); +} + +static const CoglWinsysVtable * +_cogl_texture_pixmap_x11_get_winsys (CoglTexturePixmapX11 *tex_pixmap) +{ + /* FIXME: A CoglContext should be reachable from a CoglTexture + * pointer */ + _COGL_GET_CONTEXT (ctx, NULL); + + return ctx->display->renderer->winsys_vtable; +} + +static void +process_damage_event (CoglTexturePixmapX11 *tex_pixmap, + XDamageNotifyEvent *damage_event) +{ + CoglTexture *tex = COGL_TEXTURE (tex_pixmap); + Display *display; + enum { DO_NOTHING, NEEDS_SUBTRACT, NEED_BOUNDING_BOX } handle_mode; + const CoglWinsysVtable *winsys; + + _COGL_GET_CONTEXT (ctxt, NO_RETVAL); + + display = cogl_xlib_renderer_get_display (ctxt->display->renderer); + + COGL_NOTE (TEXTURE_PIXMAP, "Damage event received for %p", tex_pixmap); + + switch (tex_pixmap->damage_report_level) + { + case COGL_TEXTURE_PIXMAP_X11_DAMAGE_RAW_RECTANGLES: + /* For raw rectangles we don't need do look at the damage region + at all because the damage area is directly given in the event + struct and the reporting of events is not affected by + clearing the damage region */ + handle_mode = DO_NOTHING; + break; + + case COGL_TEXTURE_PIXMAP_X11_DAMAGE_DELTA_RECTANGLES: + case COGL_TEXTURE_PIXMAP_X11_DAMAGE_NON_EMPTY: + /* For delta rectangles and non empty we'll query the damage + region for the bounding box */ + handle_mode = NEED_BOUNDING_BOX; + break; + + case COGL_TEXTURE_PIXMAP_X11_DAMAGE_BOUNDING_BOX: + /* For bounding box we need to clear the damage region but we + don't actually care what it was because the damage event + itself contains the bounding box of the region */ + handle_mode = NEEDS_SUBTRACT; + break; + + default: + g_assert_not_reached (); + } + + /* If the damage already covers the whole rectangle then we don't + need to request the bounding box of the region because we're + going to update the whole texture anyway. */ + if (cogl_damage_rectangle_is_whole (&tex_pixmap->damage_rect, + tex->width, + tex->height)) + { + if (handle_mode != DO_NOTHING) + XDamageSubtract (display, tex_pixmap->damage, None, None); + } + else if (handle_mode == NEED_BOUNDING_BOX) + { + XserverRegion parts; + int r_count; + XRectangle r_bounds; + XRectangle *r_damage; + + /* We need to extract the damage region so we can get the + bounding box */ + + parts = XFixesCreateRegion (display, 0, 0); + XDamageSubtract (display, tex_pixmap->damage, None, parts); + r_damage = XFixesFetchRegionAndBounds (display, + parts, + &r_count, + &r_bounds); + cogl_damage_rectangle_union (&tex_pixmap->damage_rect, + r_bounds.x, + r_bounds.y, + r_bounds.width, + r_bounds.height); + if (r_damage) + XFree (r_damage); + + XFixesDestroyRegion (display, parts); + } + else + { + if (handle_mode == NEEDS_SUBTRACT) + /* We still need to subtract from the damage region but we + don't care what the region actually was */ + XDamageSubtract (display, tex_pixmap->damage, None, None); + + cogl_damage_rectangle_union (&tex_pixmap->damage_rect, + damage_event->area.x, + damage_event->area.y, + damage_event->area.width, + damage_event->area.height); + } + + if (tex_pixmap->winsys) + { + /* If we're using the texture from pixmap extension then there's no + point in getting the region and we can just mark that the texture + needs updating */ + winsys = _cogl_texture_pixmap_x11_get_winsys (tex_pixmap); + winsys->texture_pixmap_x11_damage_notify (tex_pixmap); + } +} + +static CoglFilterReturn +_cogl_texture_pixmap_x11_filter (XEvent *event, void *data) +{ + CoglTexturePixmapX11 *tex_pixmap = data; + int damage_base; + + _COGL_GET_CONTEXT (ctxt, COGL_FILTER_CONTINUE); + + damage_base = _cogl_xlib_get_damage_base (); + if (event->type == damage_base + XDamageNotify) + { + XDamageNotifyEvent *damage_event = (XDamageNotifyEvent *) event; + + if (damage_event->damage == tex_pixmap->damage) + process_damage_event (tex_pixmap, damage_event); + } + + return COGL_FILTER_CONTINUE; +} + +static void +set_damage_object_internal (CoglContext *ctx, + CoglTexturePixmapX11 *tex_pixmap, + Damage damage, + CoglTexturePixmapX11ReportLevel report_level) +{ + Display *display = cogl_xlib_renderer_get_display (ctx->display->renderer); + + if (tex_pixmap->damage) + { + cogl_xlib_renderer_remove_filter (ctx->display->renderer, + _cogl_texture_pixmap_x11_filter, + tex_pixmap); + + if (tex_pixmap->damage_owned) + { + XDamageDestroy (display, tex_pixmap->damage); + tex_pixmap->damage_owned = FALSE; + } + } + + tex_pixmap->damage = damage; + tex_pixmap->damage_report_level = report_level; + + if (damage) + cogl_xlib_renderer_add_filter (ctx->display->renderer, + _cogl_texture_pixmap_x11_filter, + tex_pixmap); +} + +static CoglTexturePixmapX11 * +_cogl_texture_pixmap_x11_new (CoglContext *ctxt, + uint32_t pixmap, + CoglBool automatic_updates, + CoglTexturePixmapStereoMode stereo_mode, + CoglError **error) +{ + CoglTexturePixmapX11 *tex_pixmap = g_new (CoglTexturePixmapX11, 1); + Display *display = cogl_xlib_renderer_get_display (ctxt->display->renderer); + Window pixmap_root_window; + int pixmap_x, pixmap_y; + unsigned int pixmap_width, pixmap_height; + unsigned int pixmap_border_width; + CoglPixelFormat internal_format; + CoglTexture *tex = COGL_TEXTURE (tex_pixmap); + XWindowAttributes window_attributes; + int damage_base; + const CoglWinsysVtable *winsys; + + if (!XGetGeometry (display, pixmap, &pixmap_root_window, + &pixmap_x, &pixmap_y, + &pixmap_width, &pixmap_height, + &pixmap_border_width, &tex_pixmap->depth)) + { + g_free (tex_pixmap); + _cogl_set_error (error, + COGL_TEXTURE_PIXMAP_X11_ERROR, + COGL_TEXTURE_PIXMAP_X11_ERROR_X11, + "Unable to query pixmap size"); + return NULL; + } + + /* Note: the detailed pixel layout doesn't matter here, we are just + * interested in RGB vs RGBA... */ + internal_format = (tex_pixmap->depth >= 32 + ? COGL_PIXEL_FORMAT_RGBA_8888_PRE + : COGL_PIXEL_FORMAT_RGB_888); + + _cogl_texture_init (tex, ctxt, pixmap_width, pixmap_height, + internal_format, + NULL, /* no loader */ + &cogl_texture_pixmap_x11_vtable); + + tex_pixmap->pixmap = pixmap; + tex_pixmap->stereo_mode = stereo_mode; + tex_pixmap->left = NULL; + tex_pixmap->image = NULL; + tex_pixmap->shm_info.shmid = -1; + tex_pixmap->tex = NULL; + tex_pixmap->damage_owned = FALSE; + tex_pixmap->damage = 0; + + /* We need a visual to use for shared memory images so we'll query + it from the pixmap's root window */ + if (!XGetWindowAttributes (display, pixmap_root_window, &window_attributes)) + { + g_free (tex_pixmap); + _cogl_set_error (error, + COGL_TEXTURE_PIXMAP_X11_ERROR, + COGL_TEXTURE_PIXMAP_X11_ERROR_X11, + "Unable to query root window attributes"); + return NULL; + } + + tex_pixmap->visual = window_attributes.visual; + + /* If automatic updates are requested and the Xlib connection + supports damage events then we'll register a damage object on the + pixmap */ + damage_base = _cogl_xlib_get_damage_base (); + if (automatic_updates && damage_base >= 0) + { + Damage damage = XDamageCreate (display, + pixmap, + XDamageReportBoundingBox); + set_damage_object_internal (ctxt, + tex_pixmap, + damage, + COGL_TEXTURE_PIXMAP_X11_DAMAGE_BOUNDING_BOX); + tex_pixmap->damage_owned = TRUE; + } + + /* Assume the entire pixmap is damaged to begin with */ + tex_pixmap->damage_rect.x1 = 0; + tex_pixmap->damage_rect.x2 = pixmap_width; + tex_pixmap->damage_rect.y1 = 0; + tex_pixmap->damage_rect.y2 = pixmap_height; + + winsys = _cogl_texture_pixmap_x11_get_winsys (tex_pixmap); + if (winsys->texture_pixmap_x11_create) + { + tex_pixmap->use_winsys_texture = + winsys->texture_pixmap_x11_create (tex_pixmap); + } + else + tex_pixmap->use_winsys_texture = FALSE; + + if (!tex_pixmap->use_winsys_texture) + tex_pixmap->winsys = NULL; + + _cogl_texture_set_allocated (tex, internal_format, + pixmap_width, pixmap_height); + + return _cogl_texture_pixmap_x11_object_new (tex_pixmap); +} + +CoglTexturePixmapX11 * +cogl_texture_pixmap_x11_new (CoglContext *ctxt, + uint32_t pixmap, + CoglBool automatic_updates, + CoglError **error) + +{ + return _cogl_texture_pixmap_x11_new (ctxt, pixmap, + automatic_updates, COGL_TEXTURE_PIXMAP_MONO, + error); +} + +CoglTexturePixmapX11 * +cogl_texture_pixmap_x11_new_left (CoglContext *ctxt, + uint32_t pixmap, + CoglBool automatic_updates, + CoglError **error) +{ + return _cogl_texture_pixmap_x11_new (ctxt, pixmap, + automatic_updates, COGL_TEXTURE_PIXMAP_LEFT, + error); +} + +CoglTexturePixmapX11 * +cogl_texture_pixmap_x11_new_right (CoglTexturePixmapX11 *tfp_left) +{ + CoglTexture *texture_left = COGL_TEXTURE (tfp_left); + CoglTexturePixmapX11 *tfp_right; + CoglPixelFormat internal_format; + + g_return_val_if_fail (tfp_left->stereo_mode == COGL_TEXTURE_PIXMAP_LEFT, NULL); + + tfp_right = g_new0 (CoglTexturePixmapX11, 1); + tfp_right->stereo_mode = COGL_TEXTURE_PIXMAP_RIGHT; + tfp_right->left = cogl_object_ref (tfp_left); + + internal_format = (tfp_left->depth >= 32 + ? COGL_PIXEL_FORMAT_RGBA_8888_PRE + : COGL_PIXEL_FORMAT_RGB_888); + _cogl_texture_init (COGL_TEXTURE (tfp_right), + texture_left->context, + texture_left->width, + texture_left->height, + internal_format, + NULL, /* no loader */ + &cogl_texture_pixmap_x11_vtable); + + _cogl_texture_set_allocated (COGL_TEXTURE (tfp_right), internal_format, + texture_left->width, texture_left->height); + + return _cogl_texture_pixmap_x11_object_new (tfp_right); +} + +static CoglBool +_cogl_texture_pixmap_x11_allocate (CoglTexture *tex, + CoglError **error) +{ + return TRUE; +} + +/* Tries to allocate enough shared mem to handle a full size + * update size of the X Pixmap. */ +static void +try_alloc_shm (CoglTexturePixmapX11 *tex_pixmap) +{ + CoglTexture *tex = COGL_TEXTURE (tex_pixmap); + XImage *dummy_image; + Display *display; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + display = cogl_xlib_renderer_get_display (ctx->display->renderer); + + if (!XShmQueryExtension (display)) + return; + + /* We are creating a dummy_image so we can have Xlib calculate + * image->bytes_per_line - including any magic padding it may + * want - for the largest possible ximage we might need to use + * when handling updates to the texture. + * + * Note: we pass a NULL shminfo here, but that has no bearing + * on the setup of the XImage, except that ximage->obdata will + * == NULL. + */ + dummy_image = + XShmCreateImage (display, + tex_pixmap->visual, + tex_pixmap->depth, + ZPixmap, + NULL, + NULL, /* shminfo, */ + tex->width, + tex->height); + if (!dummy_image) + goto failed_image_create; + + tex_pixmap->shm_info.shmid = shmget (IPC_PRIVATE, + dummy_image->bytes_per_line + * dummy_image->height, + IPC_CREAT | 0777); + if (tex_pixmap->shm_info.shmid == -1) + goto failed_shmget; + + tex_pixmap->shm_info.shmaddr = shmat (tex_pixmap->shm_info.shmid, 0, 0); + if (tex_pixmap->shm_info.shmaddr == (void *) -1) + goto failed_shmat; + + tex_pixmap->shm_info.readOnly = False; + + if (XShmAttach (display, &tex_pixmap->shm_info) == 0) + goto failed_xshmattach; + + XDestroyImage (dummy_image); + + return; + + failed_xshmattach: + g_warning ("XShmAttach failed"); + shmdt (tex_pixmap->shm_info.shmaddr); + + failed_shmat: + g_warning ("shmat failed"); + shmctl (tex_pixmap->shm_info.shmid, IPC_RMID, 0); + + failed_shmget: + g_warning ("shmget failed"); + XDestroyImage (dummy_image); + + failed_image_create: + tex_pixmap->shm_info.shmid = -1; +} + +void +cogl_texture_pixmap_x11_update_area (CoglTexturePixmapX11 *tex_pixmap, + int x, + int y, + int width, + int height) +{ + /* We'll queue the update for both the GLX texture and the regular + texture because we can't determine which will be needed until we + actually render something */ + + if (tex_pixmap->stereo_mode == COGL_TEXTURE_PIXMAP_RIGHT) + tex_pixmap = tex_pixmap->left; + + if (tex_pixmap->winsys) + { + const CoglWinsysVtable *winsys; + winsys = _cogl_texture_pixmap_x11_get_winsys (tex_pixmap); + winsys->texture_pixmap_x11_damage_notify (tex_pixmap); + } + + cogl_damage_rectangle_union (&tex_pixmap->damage_rect, + x, y, width, height); +} + +CoglBool +cogl_texture_pixmap_x11_is_using_tfp_extension (CoglTexturePixmapX11 *tex_pixmap) +{ + if (tex_pixmap->stereo_mode == COGL_TEXTURE_PIXMAP_RIGHT) + tex_pixmap = tex_pixmap->left; + + return !!tex_pixmap->winsys; +} + +void +cogl_texture_pixmap_x11_set_damage_object (CoglTexturePixmapX11 *tex_pixmap, + uint32_t damage, + CoglTexturePixmapX11ReportLevel + report_level) +{ + int damage_base; + + _COGL_GET_CONTEXT (ctxt, NO_RETVAL); + + g_return_if_fail (tex_pixmap->stereo_mode != COGL_TEXTURE_PIXMAP_RIGHT); + + damage_base = _cogl_xlib_get_damage_base (); + if (damage_base >= 0) + set_damage_object_internal (ctxt, tex_pixmap, damage, report_level); +} + +static CoglTexture * +create_fallback_texture (CoglContext *ctx, + int width, + int height, + CoglPixelFormat internal_format) +{ + CoglTexture *tex; + CoglError *skip_error = NULL; + + if ((_cogl_util_is_pot (width) && _cogl_util_is_pot (height)) || + (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC) && + cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP))) + { + /* First try creating a fast-path non-sliced texture */ + tex = COGL_TEXTURE (cogl_texture_2d_new_with_size (ctx, + width, height)); + + _cogl_texture_set_internal_format (tex, internal_format); + + /* TODO: instead of allocating storage here it would be better + * if we had some api that let us just check that the size is + * supported by the hardware so storage could be allocated + * lazily when uploading data. */ + if (!cogl_texture_allocate (tex, &skip_error)) + { + cogl_error_free (skip_error); + cogl_object_unref (tex); + tex = NULL; + } + } + else + tex = NULL; + + if (!tex) + { + CoglTexture2DSliced *tex_2ds = + cogl_texture_2d_sliced_new_with_size (ctx, + width, + height, + COGL_TEXTURE_MAX_WASTE); + tex = COGL_TEXTURE (tex_2ds); + + _cogl_texture_set_internal_format (tex, internal_format); + } + + return tex; +} + +static void +_cogl_texture_pixmap_x11_update_image_texture (CoglTexturePixmapX11 *tex_pixmap) +{ + CoglTexture *tex = COGL_TEXTURE (tex_pixmap); + Display *display; + Visual *visual; + CoglPixelFormat image_format; + XImage *image; + int src_x, src_y; + int x, y, width, height; + int bpp; + int offset; + CoglError *ignore = NULL; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + display = cogl_xlib_renderer_get_display (ctx->display->renderer); + visual = tex_pixmap->visual; + + /* If the damage region is empty then there's nothing to do */ + if (tex_pixmap->damage_rect.x2 == tex_pixmap->damage_rect.x1) + return; + + x = tex_pixmap->damage_rect.x1; + y = tex_pixmap->damage_rect.y1; + width = tex_pixmap->damage_rect.x2 - x; + height = tex_pixmap->damage_rect.y2 - y; + + /* We lazily create the texture the first time it is needed in case + this texture can be entirely handled using the GLX texture + instead */ + if (tex_pixmap->tex == NULL) + { + CoglPixelFormat texture_format; + + texture_format = (tex_pixmap->depth >= 32 + ? COGL_PIXEL_FORMAT_RGBA_8888_PRE + : COGL_PIXEL_FORMAT_RGB_888); + + tex_pixmap->tex = create_fallback_texture (ctx, + tex->width, + tex->height, + texture_format); + } + + if (tex_pixmap->image == NULL) + { + /* If we also haven't got a shm segment then this must be the + first time we've tried to update, so lets try allocating shm + first */ + if (tex_pixmap->shm_info.shmid == -1) + try_alloc_shm (tex_pixmap); + + if (tex_pixmap->shm_info.shmid == -1) + { + COGL_NOTE (TEXTURE_PIXMAP, "Updating %p using XGetImage", tex_pixmap); + + /* We'll fallback to using a regular XImage. We'll download + the entire area instead of a sub region because presumably + if this is the first update then the entire pixmap is + needed anyway and it saves trying to manually allocate an + XImage at the right size */ + tex_pixmap->image = XGetImage (display, + tex_pixmap->pixmap, + 0, 0, + tex->width, tex->height, + AllPlanes, ZPixmap); + image = tex_pixmap->image; + src_x = x; + src_y = y; + } + else + { + COGL_NOTE (TEXTURE_PIXMAP, "Updating %p using XShmGetImage", + tex_pixmap); + + /* Create a temporary image using the beginning of the + shared memory segment and the right size for the region + we want to update. We need to reallocate the XImage every + time because there is no XShmGetSubImage. */ + image = XShmCreateImage (display, + tex_pixmap->visual, + tex_pixmap->depth, + ZPixmap, + NULL, + &tex_pixmap->shm_info, + width, + height); + image->data = tex_pixmap->shm_info.shmaddr; + src_x = 0; + src_y = 0; + + XShmGetImage (display, tex_pixmap->pixmap, image, x, y, AllPlanes); + } + } + else + { + COGL_NOTE (TEXTURE_PIXMAP, "Updating %p using XGetSubImage", tex_pixmap); + + image = tex_pixmap->image; + src_x = x; + src_y = y; + + XGetSubImage (display, + tex_pixmap->pixmap, + x, y, width, height, + AllPlanes, ZPixmap, + image, + x, y); + } + + image_format = + _cogl_util_pixel_format_from_masks (visual->red_mask, + visual->green_mask, + visual->blue_mask, + image->depth, + image->bits_per_pixel, + image->byte_order == LSBFirst); + + bpp = _cogl_pixel_format_get_bytes_per_pixel (image_format); + offset = image->bytes_per_line * src_y + bpp * src_x; + + _cogl_texture_set_region (tex_pixmap->tex, + width, + height, + image_format, + image->bytes_per_line, + ((const uint8_t *) image->data) + offset, + x, y, + 0, /* level */ + &ignore); + + /* If we have a shared memory segment then the XImage would be a + temporary one with no data allocated so we can just XFree it */ + if (tex_pixmap->shm_info.shmid != -1) + XFree (image); + + memset (&tex_pixmap->damage_rect, 0, sizeof (CoglDamageRectangle)); +} + +static void +_cogl_texture_pixmap_x11_set_use_winsys_texture (CoglTexturePixmapX11 *tex_pixmap, + CoglBool new_value) +{ + if (tex_pixmap->use_winsys_texture != new_value) + { + /* Notify cogl-pipeline.c that the texture's underlying GL texture + * storage is changing so it knows it may need to bind a new texture + * if the CoglTexture is reused with the same texture unit. */ + _cogl_pipeline_texture_storage_change_notify (COGL_TEXTURE (tex_pixmap)); + + tex_pixmap->use_winsys_texture = new_value; + } +} + +static void +_cogl_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap, + CoglBool needs_mipmap) +{ + CoglTexturePixmapStereoMode stereo_mode = tex_pixmap->stereo_mode; + if (stereo_mode == COGL_TEXTURE_PIXMAP_RIGHT) + tex_pixmap = tex_pixmap->left; + + if (tex_pixmap->winsys) + { + const CoglWinsysVtable *winsys = + _cogl_texture_pixmap_x11_get_winsys (tex_pixmap); + + if (winsys->texture_pixmap_x11_update (tex_pixmap, stereo_mode, needs_mipmap)) + { + _cogl_texture_pixmap_x11_set_use_winsys_texture (tex_pixmap, TRUE); + return; + } + } + + /* If it didn't work then fallback to using XGetImage. This may be + temporary */ + _cogl_texture_pixmap_x11_set_use_winsys_texture (tex_pixmap, FALSE); + + _cogl_texture_pixmap_x11_update_image_texture (tex_pixmap); +} + +static CoglTexture * +_cogl_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap) +{ + CoglTexturePixmapX11 *original_pixmap = tex_pixmap; + CoglTexture *tex; + int i; + CoglTexturePixmapStereoMode stereo_mode = tex_pixmap->stereo_mode; + + if (stereo_mode == COGL_TEXTURE_PIXMAP_RIGHT) + tex_pixmap = tex_pixmap->left; + + /* We try getting the texture twice, once without flushing the + updates and once with. If pre_paint has been called already then + we should have a good idea of which texture to use so we don't + want to mess with that by ensuring the updates. However, if we + couldn't find a texture then we'll just make a best guess by + flushing without expecting mipmap support and try again. This + would happen for example if an application calls + get_gl_texture before the first paint */ + + for (i = 0; i < 2; i++) + { + if (tex_pixmap->use_winsys_texture) + { + const CoglWinsysVtable *winsys = + _cogl_texture_pixmap_x11_get_winsys (tex_pixmap); + tex = winsys->texture_pixmap_x11_get_texture (tex_pixmap, stereo_mode); + } + else + tex = tex_pixmap->tex; + + if (tex) + return tex; + + _cogl_texture_pixmap_x11_update (original_pixmap, FALSE); + } + + g_assert_not_reached (); + + return NULL; +} + +static CoglBool +_cogl_texture_pixmap_x11_set_region (CoglTexture *tex, + int src_x, + int src_y, + int dst_x, + int dst_y, + int dst_width, + int dst_height, + int level, + CoglBitmap *bmp, + CoglError **error) +{ + /* This doesn't make much sense for texture from pixmap so it's not + supported */ + _cogl_set_error (error, + COGL_SYSTEM_ERROR, + COGL_SYSTEM_ERROR_UNSUPPORTED, + "Explicitly setting a region of a TFP texture unsupported"); + return FALSE; +} + +static CoglBool +_cogl_texture_pixmap_x11_get_data (CoglTexture *tex, + CoglPixelFormat format, + int rowstride, + uint8_t *data) +{ + CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex); + CoglTexture *child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap); + + /* Forward on to the child texture */ + return cogl_texture_get_data (child_tex, format, rowstride, data); +} + +typedef struct _NormalizeCoordsWrapperData +{ + int width; + int height; + CoglMetaTextureCallback callback; + void *user_data; +} NormalizeCoordsWrapperData; + +static void +normalize_coords_wrapper_cb (CoglTexture *child_texture, + const float *child_texture_coords, + const float *meta_coords, + void *user_data) +{ + NormalizeCoordsWrapperData *data = user_data; + float normalized_coords[4]; + + normalized_coords[0] = meta_coords[0] / data->width; + normalized_coords[1] = meta_coords[1] / data->height; + normalized_coords[2] = meta_coords[2] / data->width; + normalized_coords[3] = meta_coords[3] / data->height; + + data->callback (child_texture, + child_texture_coords, normalized_coords, + data->user_data); +} + +static void +_cogl_texture_pixmap_x11_foreach_sub_texture_in_region + (CoglTexture *tex, + float virtual_tx_1, + float virtual_ty_1, + float virtual_tx_2, + float virtual_ty_2, + CoglMetaTextureCallback callback, + void *user_data) +{ + CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex); + CoglTexture *child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap); + + /* Forward on to the child texture */ + + /* tfp textures may be implemented in terms of a + * CoglTextureRectangle texture which uses un-normalized texture + * coordinates but we want to consistently deal with normalized + * texture coordinates with CoglTexturePixmapX11... */ + if (cogl_is_texture_rectangle (child_tex)) + { + NormalizeCoordsWrapperData data; + int width = tex->width; + int height = tex->height; + + virtual_tx_1 *= width; + virtual_ty_1 *= height; + virtual_tx_2 *= width; + virtual_ty_2 *= height; + + data.width = width; + data.height = height; + data.callback = callback; + data.user_data = user_data; + + cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (child_tex), + virtual_tx_1, + virtual_ty_1, + virtual_tx_2, + virtual_ty_2, + COGL_PIPELINE_WRAP_MODE_REPEAT, + COGL_PIPELINE_WRAP_MODE_REPEAT, + normalize_coords_wrapper_cb, + &data); + } + else + cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (child_tex), + virtual_tx_1, + virtual_ty_1, + virtual_tx_2, + virtual_ty_2, + COGL_PIPELINE_WRAP_MODE_REPEAT, + COGL_PIPELINE_WRAP_MODE_REPEAT, + callback, + user_data); +} + +static int +_cogl_texture_pixmap_x11_get_max_waste (CoglTexture *tex) +{ + CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex); + CoglTexture *child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap); + + return cogl_texture_get_max_waste (child_tex); +} + +static CoglBool +_cogl_texture_pixmap_x11_is_sliced (CoglTexture *tex) +{ + CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex); + CoglTexture *child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap); + + return cogl_texture_is_sliced (child_tex); +} + +static CoglBool +_cogl_texture_pixmap_x11_can_hardware_repeat (CoglTexture *tex) +{ + CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex); + CoglTexture *child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap); + + return _cogl_texture_can_hardware_repeat (child_tex); +} + +static void +_cogl_texture_pixmap_x11_transform_coords_to_gl (CoglTexture *tex, + float *s, + float *t) +{ + CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex); + CoglTexture *child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap); + + /* Forward on to the child texture */ + _cogl_texture_transform_coords_to_gl (child_tex, s, t); +} + +static CoglTransformResult +_cogl_texture_pixmap_x11_transform_quad_coords_to_gl (CoglTexture *tex, + float *coords) +{ + CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex); + CoglTexture *child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap); + + /* Forward on to the child texture */ + return _cogl_texture_transform_quad_coords_to_gl (child_tex, coords); +} + +static CoglBool +_cogl_texture_pixmap_x11_get_gl_texture (CoglTexture *tex, + GLuint *out_gl_handle, + GLenum *out_gl_target) +{ + CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex); + CoglTexture *child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap); + + /* Forward on to the child texture */ + return cogl_texture_get_gl_texture (child_tex, + out_gl_handle, + out_gl_target); +} + +static void +_cogl_texture_pixmap_x11_gl_flush_legacy_texobj_filters (CoglTexture *tex, + GLenum min_filter, + GLenum mag_filter) +{ + CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex); + CoglTexture *child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap); + + /* Forward on to the child texture */ + _cogl_texture_gl_flush_legacy_texobj_filters (child_tex, + min_filter, mag_filter); +} + +static void +_cogl_texture_pixmap_x11_pre_paint (CoglTexture *tex, + CoglTexturePrePaintFlags flags) +{ + CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex); + CoglTexture *child_tex; + + _cogl_texture_pixmap_x11_update (tex_pixmap, + !!(flags & COGL_TEXTURE_NEEDS_MIPMAP)); + + child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap); + + _cogl_texture_pre_paint (child_tex, flags); +} + +static void +_cogl_texture_pixmap_x11_ensure_non_quad_rendering (CoglTexture *tex) +{ + CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex); + CoglTexture *child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap); + + /* Forward on to the child texture */ + _cogl_texture_ensure_non_quad_rendering (child_tex); +} + +static void +_cogl_texture_pixmap_x11_gl_flush_legacy_texobj_wrap_modes (CoglTexture *tex, + GLenum wrap_mode_s, + GLenum wrap_mode_t, + GLenum wrap_mode_p) +{ + CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex); + CoglTexture *child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap); + + /* Forward on to the child texture */ + _cogl_texture_gl_flush_legacy_texobj_wrap_modes (child_tex, + wrap_mode_s, + wrap_mode_t, + wrap_mode_p); +} + +static CoglPixelFormat +_cogl_texture_pixmap_x11_get_format (CoglTexture *tex) +{ + CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex); + CoglTexture *child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap); + + /* Forward on to the child texture */ + return _cogl_texture_get_format (child_tex); +} + +static GLenum +_cogl_texture_pixmap_x11_get_gl_format (CoglTexture *tex) +{ + CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex); + CoglTexture *child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap); + + return _cogl_texture_gl_get_format (child_tex); +} + +static CoglTextureType +_cogl_texture_pixmap_x11_get_type (CoglTexture *tex) +{ + CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex); + CoglTexture *child_tex; + + child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap); + + /* Forward on to the child texture */ + return _cogl_texture_get_type (child_tex); +} + +static void +_cogl_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap) +{ + Display *display; + + _COGL_GET_CONTEXT (ctxt, NO_RETVAL); + + if (tex_pixmap->stereo_mode == COGL_TEXTURE_PIXMAP_RIGHT) + { + cogl_object_unref (tex_pixmap->left); + + /* Chain up */ + _cogl_texture_free (COGL_TEXTURE (tex_pixmap)); + + return; + } + + display = cogl_xlib_renderer_get_display (ctxt->display->renderer); + + set_damage_object_internal (ctxt, tex_pixmap, 0, 0); + + if (tex_pixmap->image) + XDestroyImage (tex_pixmap->image); + + if (tex_pixmap->shm_info.shmid != -1) + { + XShmDetach (display, &tex_pixmap->shm_info); + shmdt (tex_pixmap->shm_info.shmaddr); + shmctl (tex_pixmap->shm_info.shmid, IPC_RMID, 0); + } + + if (tex_pixmap->tex) + cogl_object_unref (tex_pixmap->tex); + + if (tex_pixmap->winsys) + { + const CoglWinsysVtable *winsys = + _cogl_texture_pixmap_x11_get_winsys (tex_pixmap); + winsys->texture_pixmap_x11_free (tex_pixmap); + } + + /* Chain up */ + _cogl_texture_free (COGL_TEXTURE (tex_pixmap)); +} + +static const CoglTextureVtable +cogl_texture_pixmap_x11_vtable = + { + FALSE, /* not primitive */ + _cogl_texture_pixmap_x11_allocate, + _cogl_texture_pixmap_x11_set_region, + _cogl_texture_pixmap_x11_get_data, + _cogl_texture_pixmap_x11_foreach_sub_texture_in_region, + _cogl_texture_pixmap_x11_get_max_waste, + _cogl_texture_pixmap_x11_is_sliced, + _cogl_texture_pixmap_x11_can_hardware_repeat, + _cogl_texture_pixmap_x11_transform_coords_to_gl, + _cogl_texture_pixmap_x11_transform_quad_coords_to_gl, + _cogl_texture_pixmap_x11_get_gl_texture, + _cogl_texture_pixmap_x11_gl_flush_legacy_texobj_filters, + _cogl_texture_pixmap_x11_pre_paint, + _cogl_texture_pixmap_x11_ensure_non_quad_rendering, + _cogl_texture_pixmap_x11_gl_flush_legacy_texobj_wrap_modes, + _cogl_texture_pixmap_x11_get_format, + _cogl_texture_pixmap_x11_get_gl_format, + _cogl_texture_pixmap_x11_get_type, + NULL, /* is_foreign */ + NULL /* set_auto_mipmap */ + }; diff --git a/cogl/cogl/winsys/cogl-texture-pixmap-x11.h b/cogl/cogl/winsys/cogl-texture-pixmap-x11.h new file mode 100644 index 0000000..4c86c68 --- /dev/null +++ b/cogl/cogl/winsys/cogl-texture-pixmap-x11.h @@ -0,0 +1,286 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_TEXTURE_PIXMAP_X11_H +#define __COGL_TEXTURE_PIXMAP_X11_H + +/* NB: this is a top-level header that can be included directly but we + * want to be careful not to define __COGL_H_INSIDE__ when this is + * included internally while building Cogl itself since + * __COGL_H_INSIDE__ is used in headers to guard public vs private api + * definitions + */ +#ifndef COGL_COMPILATION + +/* Note: When building Cogl .gir we explicitly define + * __COGL_H_INSIDE__ */ +#ifndef __COGL_H_INSIDE__ +#define __COGL_H_INSIDE__ +#define __COGL_MUST_UNDEF_COGL_H_INSIDE_COGL_TEXTURE_PIXMAP_X11_ +#endif + +#endif /* COGL_COMPILATION */ + +#include + +#include + +COGL_BEGIN_DECLS + +/** + * SECTION:cogl-texture-pixmap-x11 + * @short_description: Functions for creating and manipulating 2D meta + * textures derived from X11 pixmaps. + * + * These functions allow high-level meta textures (See the + * #CoglMetaTexture interface) that derive their contents from an X11 + * pixmap. + */ + +typedef struct _CoglTexturePixmapX11 CoglTexturePixmapX11; + +#define COGL_TEXTURE_PIXMAP_X11(X) ((CoglTexturePixmapX11 *)X) + +/** + * cogl_texture_pixmap_x11_get_gtype: + * + * Returns: a #GType that can be used with the GLib type system. + */ +GType cogl_texture_pixmap_x11_get_gtype (void); + +typedef enum +{ + COGL_TEXTURE_PIXMAP_X11_DAMAGE_RAW_RECTANGLES, + COGL_TEXTURE_PIXMAP_X11_DAMAGE_DELTA_RECTANGLES, + COGL_TEXTURE_PIXMAP_X11_DAMAGE_BOUNDING_BOX, + COGL_TEXTURE_PIXMAP_X11_DAMAGE_NON_EMPTY +} CoglTexturePixmapX11ReportLevel; + +/** + * COGL_TEXTURE_PIXMAP_X11_ERROR: + * + * #CoglError domain for texture-pixmap-x11 errors. + * + * Since: 1.10 + */ +#define COGL_TEXTURE_PIXMAP_X11_ERROR (cogl_texture_pixmap_x11_error_quark ()) + +/** + * CoglTexturePixmapX11Error: + * @COGL_TEXTURE_PIXMAP_X11_ERROR_X11: An X11 protocol error + * + * Error codes that can be thrown when performing texture-pixmap-x11 + * operations. + * + * Since: 1.10 + */ +typedef enum { + COGL_TEXTURE_PIXMAP_X11_ERROR_X11, +} CoglTexturePixmapX11Error; + +uint32_t cogl_texture_pixmap_x11_error_quark (void); + +/** + * cogl_texture_pixmap_x11_new: + * @context: A #CoglContext + * @pixmap: A X11 pixmap ID + * @automatic_updates: Whether to automatically copy the contents of + * the pixmap to the texture. + * @error: A #CoglError for exceptions + * + * Creates a texture that contains the contents of @pixmap. If + * @automatic_updates is %TRUE then Cogl will attempt to listen for + * damage events on the pixmap and automatically update the texture + * when it changes. + * + * Return value: a new #CoglTexturePixmapX11 instance + * + * Since: 1.10 + * Stability: Unstable + */ +CoglTexturePixmapX11 * +cogl_texture_pixmap_x11_new (CoglContext *context, + uint32_t pixmap, + CoglBool automatic_updates, + CoglError **error); + +/** + * cogl_texture_pixmap_x11_new_left: + * @context: A #CoglContext + * @pixmap: A X11 pixmap ID + * @automatic_updates: Whether to automatically copy the contents of + * the pixmap to the texture. + * @error: A #CoglError for exceptions + * + * Creates one of a pair of textures to contain the contents of @pixmap, + * which has stereo content. (Different images for the right and left eyes.) + * The left image is drawn using this texture; the right image is drawn + * using a texture created by calling + * cogl_texture_pixmap_x11_new_right() and passing in this texture as an + * argument. + * + * In general, you should not use this function unless you have + * queried the %GLX_STEREO_TREE_EXT attribute of the corresponding + * window using glXQueryDrawable() and determined that the window is + * stereo. Note that this attribute can change over time and + * notification is also provided through events defined in the + * EXT_stereo_tree GLX extension. As long as the system has support for + * stereo content, drawing using the left and right pixmaps will not + * produce an error even if the window doesn't have stereo + * content any more, but drawing with the right pixmap will produce + * undefined output, so you need to listen for these events and + * re-render to avoid race conditions. (Recreating a non-stereo + * pixmap is not necessary, but may save resources.) + * + * Return value: a new #CoglTexturePixmapX11 instance + * + * Since: 1.20 + * Stability: Unstable + */ +CoglTexturePixmapX11 * +cogl_texture_pixmap_x11_new_left (CoglContext *context, + uint32_t pixmap, + CoglBool automatic_updates, + CoglError **error); + +/** + * cogl_texture_pixmap_x11_new_right: + * @left_texture: A #CoglTexturePixmapX11 instance created with + * cogl_texture_pixmap_x11_new_left(). + * + * Creates a texture object that corresponds to the right-eye image + * of a pixmap with stereo content. @left_texture must have been + * created using cogl_texture_pixmap_x11_new_left(). + * + * Return value: a new #CoglTexturePixmapX11 instance + * + * Since: 1.20 + * Stability: Unstable + */ +CoglTexturePixmapX11 * +cogl_texture_pixmap_x11_new_right (CoglTexturePixmapX11 *left_texture); + +/** + * cogl_texture_pixmap_x11_update_area: + * @texture: A #CoglTexturePixmapX11 instance + * @x: x coordinate of the area to update + * @y: y coordinate of the area to update + * @width: width of the area to update + * @height: height of the area to update + * + * Forces an update of the given @texture so that it is refreshed with + * the contents of the pixmap that was given to + * cogl_texture_pixmap_x11_new(). + * + * Since: 1.4 + * Stability: Unstable + */ +void +cogl_texture_pixmap_x11_update_area (CoglTexturePixmapX11 *texture, + int x, + int y, + int width, + int height); + +/** + * cogl_texture_pixmap_x11_is_using_tfp_extension: + * @texture: A #CoglTexturePixmapX11 instance + * + * Checks whether the given @texture is using the + * GLX_EXT_texture_from_pixmap or similar extension to copy the + * contents of the pixmap to the texture. This extension is usually + * implemented as zero-copy operation so it implies the updates are + * working efficiently. + * + * Return value: %TRUE if the texture is using an efficient extension + * and %FALSE otherwise + * + * Since: 1.4 + * Stability: Unstable + */ +CoglBool +cogl_texture_pixmap_x11_is_using_tfp_extension (CoglTexturePixmapX11 *texture); + +/** + * cogl_texture_pixmap_x11_set_damage_object: + * @texture: A #CoglTexturePixmapX11 instance + * @damage: A X11 Damage object or 0 + * @report_level: The report level which describes how to interpret + * the damage events. This should match the level that the damage + * object was created with. + * + * Sets the damage object that will be used to track automatic updates + * to the @texture. Damage tracking can be disabled by passing 0 for + * @damage. Otherwise this damage will replace the one used if %TRUE + * was passed for automatic_updates to cogl_texture_pixmap_x11_new(). + * + * Note that Cogl will subtract from the damage region as it processes + * damage events. + * + * Since: 1.4 + * Stability: Unstable + */ +void +cogl_texture_pixmap_x11_set_damage_object (CoglTexturePixmapX11 *texture, + uint32_t damage, + CoglTexturePixmapX11ReportLevel + report_level); + +/** + * cogl_is_texture_pixmap_x11: + * @object: A pointer to a #CoglObject + * + * Checks whether @object points to a #CoglTexturePixmapX11 instance. + * + * Return value: %TRUE if the object is a #CoglTexturePixmapX11, and + * %FALSE otherwise + * + * Since: 1.4 + * Stability: Unstable + */ +CoglBool +cogl_is_texture_pixmap_x11 (void *object); + +COGL_END_DECLS + +/* The gobject introspection scanner seems to parse public headers in + * isolation which means we need to be extra careful about how we + * define and undefine __COGL_H_INSIDE__ used to detect when internal + * headers are incorrectly included by developers. In the gobject + * introspection case we have to manually define __COGL_H_INSIDE__ as + * a commandline argument for the scanner which means we must be + * careful not to undefine it in a header... + */ +#ifdef __COGL_MUST_UNDEF_COGL_H_INSIDE_COGL_TEXTURE_PIXMAP_X11_ +#undef __COGL_H_INSIDE__ +#undef __COGL_MUST_UNDEF_COGL_H_INSIDE_COGL_TEXTURE_PIXMAP_X11_ +#endif + +#endif /* __COGL_TEXTURE_PIXMAP_X11_H */ diff --git a/cogl/cogl/winsys/cogl-winsys-egl-feature-functions.h b/cogl/cogl/winsys/cogl-winsys-egl-feature-functions.h new file mode 100644 index 0000000..17a99f2 --- /dev/null +++ b/cogl/cogl/winsys/cogl-winsys-egl-feature-functions.h @@ -0,0 +1,149 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +/* This can be included multiple times with different definitions for + * the COGL_WINSYS_FEATURE_* functions. + */ + +/* Macro prototypes: + * COGL_WINSYS_FEATURE_BEGIN (name, namespaces, extension_names, + * implied_private_egl_feature_flags) + * COGL_WINSYS_FEATURE_FUNCTION (return_type, function_name, + * (arguments)) + * ... + * COGL_WINSYS_FEATURE_END () + * + * Note: You can list multiple namespace and extension names if the + * corresponding _FEATURE_FUNCTIONS have the same semantics accross + * the different extension variants. + * + * XXX: NB: Don't add a trailing semicolon when using these macros + */ + +COGL_WINSYS_FEATURE_BEGIN (swap_region, + "NOK\0", + "swap_region\0", + COGL_EGL_WINSYS_FEATURE_SWAP_REGION) +COGL_WINSYS_FEATURE_FUNCTION (EGLBoolean, eglSwapBuffersRegion, + (EGLDisplay dpy, + EGLSurface surface, + EGLint numRects, + const EGLint *rects)) +COGL_WINSYS_FEATURE_END () +/* XXX: These macros can't handle falling back to looking for + * EGL_KHR_image if EGL_KHR_image_base and EGL_KHR_image_pixmap aren't + * found... */ +#ifdef EGL_KHR_image_base +COGL_WINSYS_FEATURE_BEGIN (image_base, + "KHR\0", + "image_base\0", + 0) +COGL_WINSYS_FEATURE_FUNCTION (EGLImageKHR, eglCreateImage, + (EGLDisplay dpy, + EGLContext ctx, + EGLenum target, + EGLClientBuffer buffer, + const EGLint *attrib_list)) +COGL_WINSYS_FEATURE_FUNCTION (EGLBoolean, eglDestroyImage, + (EGLDisplay dpy, + EGLImageKHR image)) +COGL_WINSYS_FEATURE_END () +#endif +COGL_WINSYS_FEATURE_BEGIN (image_pixmap, + "KHR\0", + "image_pixmap\0", + COGL_EGL_WINSYS_FEATURE_EGL_IMAGE_FROM_X11_PIXMAP) +COGL_WINSYS_FEATURE_END () +#ifdef EGL_WL_bind_wayland_display +COGL_WINSYS_FEATURE_BEGIN (bind_wayland_display, + "WL\0", + "bind_wayland_display\0", + COGL_EGL_WINSYS_FEATURE_EGL_IMAGE_FROM_WAYLAND_BUFFER) +COGL_WINSYS_FEATURE_FUNCTION (EGLImageKHR, eglBindWaylandDisplay, + (EGLDisplay dpy, + struct wl_display *wayland_display)) +COGL_WINSYS_FEATURE_FUNCTION (EGLBoolean, eglUnbindWaylandDisplay, + (EGLDisplay dpy, + struct wl_display *wayland_display)) +COGL_WINSYS_FEATURE_FUNCTION (EGLBoolean, eglQueryWaylandBuffer, + (EGLDisplay dpy, + struct wl_resource *buffer, + EGLint attribute, EGLint *value)) +COGL_WINSYS_FEATURE_END () +#endif /* EGL_WL_bind_wayland_display */ + +COGL_WINSYS_FEATURE_BEGIN (create_context, + "KHR\0", + "create_context\0", + COGL_EGL_WINSYS_FEATURE_CREATE_CONTEXT) +COGL_WINSYS_FEATURE_END () + +COGL_WINSYS_FEATURE_BEGIN (buffer_age, + "EXT\0", + "buffer_age\0", + COGL_EGL_WINSYS_FEATURE_BUFFER_AGE) +COGL_WINSYS_FEATURE_END () + +COGL_WINSYS_FEATURE_BEGIN (swap_buffers_with_damage, + "EXT\0", + "swap_buffers_with_damage\0", + 0) +COGL_WINSYS_FEATURE_FUNCTION (EGLBoolean, eglSwapBuffersWithDamage, + (EGLDisplay dpy, + EGLSurface surface, + const EGLint *rects, + EGLint n_rects)) +COGL_WINSYS_FEATURE_END () + +#if defined(EGL_KHR_fence_sync) || defined(EGL_KHR_reusable_sync) +COGL_WINSYS_FEATURE_BEGIN (fence_sync, + "KHR\0", + "fence_sync\0", + COGL_EGL_WINSYS_FEATURE_FENCE_SYNC) +COGL_WINSYS_FEATURE_FUNCTION (EGLSyncKHR, eglCreateSync, + (EGLDisplay dpy, + EGLenum type, + const EGLint *attrib_list)) +COGL_WINSYS_FEATURE_FUNCTION (EGLint, eglClientWaitSync, + (EGLDisplay dpy, + EGLSyncKHR sync, + EGLint flags, + EGLTimeKHR timeout)) +COGL_WINSYS_FEATURE_FUNCTION (EGLBoolean, eglDestroySync, + (EGLDisplay dpy, + EGLSyncKHR sync)) +COGL_WINSYS_FEATURE_END () +#endif + +COGL_WINSYS_FEATURE_BEGIN (surfaceless_context, + "KHR\0", + "surfaceless_context\0", + COGL_EGL_WINSYS_FEATURE_SURFACELESS_CONTEXT) +COGL_WINSYS_FEATURE_END () diff --git a/cogl/cogl/winsys/cogl-winsys-egl-private.h b/cogl/cogl/winsys/cogl-winsys-egl-private.h new file mode 100644 index 0000000..5d21b4f --- /dev/null +++ b/cogl/cogl/winsys/cogl-winsys-egl-private.h @@ -0,0 +1,203 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_WINSYS_EGL_PRIVATE_H +#define __COGL_WINSYS_EGL_PRIVATE_H + +#include "cogl-defines.h" +#include "cogl-winsys-private.h" +#include "cogl-context.h" +#include "cogl-context-private.h" +#include "cogl-framebuffer-private.h" + +/* XXX: depending on what version of Mesa you have then + * eglQueryWaylandBuffer may take a wl_buffer or wl_resource argument + * and the EGL header will only forward declare the corresponding + * type. + * + * The use of wl_buffer has been deprecated and so internally we + * assume that eglQueryWaylandBuffer takes a wl_resource but for + * compatibility we forward declare wl_resource in case we are + * building with EGL headers that still use wl_buffer. + * + * Placing the forward declaration here means it comes before we + * #include cogl-winsys-egl-feature-functions.h bellow which + * declares lots of function pointers for accessing EGL extensions + * and cogl-winsys-egl.c will include this header before it also + * includes cogl-winsys-egl-feature-functions.h that may depend + * on this type. + */ +#ifdef EGL_WL_bind_wayland_display +struct wl_resource; +#endif + +typedef struct _CoglWinsysEGLVtable +{ + CoglBool + (* display_setup) (CoglDisplay *display, + CoglError **error); + void + (* display_destroy) (CoglDisplay *display); + + CoglBool + (* context_created) (CoglDisplay *display, + CoglError **error); + + void + (* cleanup_context) (CoglDisplay *display); + + CoglBool + (* context_init) (CoglContext *context, CoglError **error); + + void + (* context_deinit) (CoglContext *context); + + CoglBool + (* onscreen_init) (CoglOnscreen *onscreen, + EGLConfig config, + CoglError **error); + void + (* onscreen_deinit) (CoglOnscreen *onscreen); + + int + (* add_config_attributes) (CoglDisplay *display, + CoglFramebufferConfig *config, + EGLint *attributes); +} CoglWinsysEGLVtable; + +typedef enum _CoglEGLWinsysFeature +{ + COGL_EGL_WINSYS_FEATURE_SWAP_REGION =1L<<0, + COGL_EGL_WINSYS_FEATURE_EGL_IMAGE_FROM_X11_PIXMAP =1L<<1, + COGL_EGL_WINSYS_FEATURE_EGL_IMAGE_FROM_WAYLAND_BUFFER =1L<<2, + COGL_EGL_WINSYS_FEATURE_CREATE_CONTEXT =1L<<3, + COGL_EGL_WINSYS_FEATURE_BUFFER_AGE =1L<<4, + COGL_EGL_WINSYS_FEATURE_FENCE_SYNC =1L<<5, + COGL_EGL_WINSYS_FEATURE_SURFACELESS_CONTEXT =1L<<6 +} CoglEGLWinsysFeature; + +typedef struct _CoglRendererEGL +{ + CoglEGLWinsysFeature private_features; + + EGLDisplay edpy; + + EGLint egl_version_major; + EGLint egl_version_minor; + + CoglClosure *resize_notify_idle; + + /* Data specific to the EGL platform */ + void *platform; + /* vtable for platform specific parts */ + const CoglWinsysEGLVtable *platform_vtable; + + /* Function pointers for EGL specific extensions */ +#define COGL_WINSYS_FEATURE_BEGIN(a, b, c, d) + +#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args) \ + ret (APIENTRY * pf_ ## name) args; + +#define COGL_WINSYS_FEATURE_END() + +#include "cogl-winsys-egl-feature-functions.h" + +#undef COGL_WINSYS_FEATURE_BEGIN +#undef COGL_WINSYS_FEATURE_FUNCTION +#undef COGL_WINSYS_FEATURE_END +} CoglRendererEGL; + +typedef struct _CoglDisplayEGL +{ + EGLContext egl_context; + EGLSurface dummy_surface; + EGLSurface egl_surface; + + EGLConfig egl_config; + CoglBool found_egl_config; + + EGLSurface current_read_surface; + EGLSurface current_draw_surface; + EGLContext current_context; + + /* Platform specific display data */ + void *platform; +} CoglDisplayEGL; + +typedef struct _CoglContextEGL +{ + EGLSurface saved_draw_surface; + EGLSurface saved_read_surface; +} CoglContextEGL; + +typedef struct _CoglOnscreenEGL +{ + EGLSurface egl_surface; + + CoglBool pending_resize_notify; + + /* Platform specific data */ + void *platform; +} CoglOnscreenEGL; + +const CoglWinsysVtable * +_cogl_winsys_egl_get_vtable (void); + +EGLBoolean +_cogl_winsys_egl_make_current (CoglDisplay *display, + EGLSurface draw, + EGLSurface read, + EGLContext context); + +#ifdef EGL_KHR_image_base +EGLImageKHR +_cogl_egl_create_image (CoglContext *ctx, + EGLenum target, + EGLClientBuffer buffer, + const EGLint *attribs); + +void +_cogl_egl_destroy_image (CoglContext *ctx, + EGLImageKHR image); +#endif + +#ifdef EGL_WL_bind_wayland_display +CoglBool +_cogl_egl_query_wayland_buffer (CoglContext *ctx, + struct wl_resource *buffer, + int attribute, + int *value); +#endif + +CoglBool +_cogl_winsys_egl_renderer_connect_common (CoglRenderer *renderer, + CoglError **error); + +#endif /* __COGL_WINSYS_EGL_PRIVATE_H */ diff --git a/cogl/cogl/winsys/cogl-winsys-egl-x11-private.h b/cogl/cogl/winsys/cogl-winsys-egl-x11-private.h new file mode 100644 index 0000000..206d485 --- /dev/null +++ b/cogl/cogl/winsys/cogl-winsys-egl-x11-private.h @@ -0,0 +1,39 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_WINSYS_EGL_X11_PRIVATE_H +#define __COGL_WINSYS_EGL_X11_PRIVATE_H + +#include "cogl-winsys-private.h" + +const CoglWinsysVtable * +_cogl_winsys_egl_xlib_get_vtable (void); + +#endif /* __COGL_WINSYS_EGL_X11_PRIVATE_H */ diff --git a/cogl/cogl/winsys/cogl-winsys-egl-x11.c b/cogl/cogl/winsys/cogl-winsys-egl-x11.c new file mode 100644 index 0000000..a7379a5 --- /dev/null +++ b/cogl/cogl/winsys/cogl-winsys-egl-x11.c @@ -0,0 +1,888 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011,2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * Authors: + * Robert Bragg + * Neil Roberts + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include + +#include "cogl-winsys-egl-x11-private.h" +#include "cogl-winsys-egl-private.h" +#include "cogl-xlib-renderer-private.h" +#include "cogl-xlib-renderer.h" +#include "cogl-framebuffer-private.h" +#include "cogl-onscreen-private.h" +#include "cogl-display-private.h" +#include "cogl-renderer-private.h" + +#include "cogl-texture-pixmap-x11-private.h" +#include "cogl-texture-2d-private.h" +#include "cogl-error-private.h" +#include "cogl-poll-private.h" + +#define COGL_ONSCREEN_X11_EVENT_MASK (StructureNotifyMask | ExposureMask) + +static const CoglWinsysEGLVtable _cogl_winsys_egl_vtable; + +typedef struct _CoglDisplayXlib +{ + Window dummy_xwin; +} CoglDisplayXlib; + +typedef struct _CoglOnscreenXlib +{ + Window xwin; + CoglBool is_foreign_xwin; +} CoglOnscreenXlib; + +#ifdef EGL_KHR_image_pixmap +typedef struct _CoglTexturePixmapEGL +{ + EGLImageKHR image; + CoglTexture *texture; +} CoglTexturePixmapEGL; +#endif + +static CoglOnscreen * +find_onscreen_for_xid (CoglContext *context, uint32_t xid) +{ + GList *l; + + for (l = context->framebuffers; l; l = l->next) + { + CoglFramebuffer *framebuffer = l->data; + CoglOnscreenEGL *egl_onscreen; + CoglOnscreenXlib *xlib_onscreen; + + if (!framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN) + continue; + + egl_onscreen = COGL_ONSCREEN (framebuffer)->winsys; + xlib_onscreen = egl_onscreen->platform; + if (xlib_onscreen->xwin == (Window)xid) + return COGL_ONSCREEN (framebuffer); + } + + return NULL; +} + +static void +flush_pending_resize_notifications_cb (void *data, + void *user_data) +{ + CoglFramebuffer *framebuffer = data; + + if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN) + { + CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); + CoglOnscreenEGL *egl_onscreen = onscreen->winsys; + + if (egl_onscreen->pending_resize_notify) + { + _cogl_onscreen_notify_resize (onscreen); + egl_onscreen->pending_resize_notify = FALSE; + } + } +} + +static void +flush_pending_resize_notifications_idle (void *user_data) +{ + CoglContext *context = user_data; + CoglRenderer *renderer = context->display->renderer; + CoglRendererEGL *egl_renderer = renderer->winsys; + + /* This needs to be disconnected before invoking the callbacks in + * case the callbacks cause it to be queued again */ + _cogl_closure_disconnect (egl_renderer->resize_notify_idle); + egl_renderer->resize_notify_idle = NULL; + + g_list_foreach (context->framebuffers, + flush_pending_resize_notifications_cb, + NULL); +} + +static void +notify_resize (CoglContext *context, + Window drawable, + int width, + int height) +{ + CoglRenderer *renderer = context->display->renderer; + CoglRendererEGL *egl_renderer = renderer->winsys; + CoglOnscreen *onscreen = find_onscreen_for_xid (context, drawable); + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + CoglOnscreenEGL *egl_onscreen; + + if (!onscreen) + return; + + egl_onscreen = onscreen->winsys; + + _cogl_framebuffer_winsys_update_size (framebuffer, width, height); + + /* We only want to notify that a resize happened when the + * application calls cogl_context_dispatch so instead of immediately + * notifying we queue an idle callback */ + if (!egl_renderer->resize_notify_idle) + { + egl_renderer->resize_notify_idle = + _cogl_poll_renderer_add_idle (renderer, + flush_pending_resize_notifications_idle, + context, + NULL); + } + + egl_onscreen->pending_resize_notify = TRUE; +} + +static CoglFilterReturn +event_filter_cb (XEvent *xevent, void *data) +{ + CoglContext *context = data; + + if (xevent->type == ConfigureNotify) + { + notify_resize (context, + xevent->xconfigure.window, + xevent->xconfigure.width, + xevent->xconfigure.height); + } + else if (xevent->type == Expose) + { + CoglOnscreen *onscreen = + find_onscreen_for_xid (context, xevent->xexpose.window); + + if (onscreen) + { + CoglOnscreenDirtyInfo info; + + info.x = xevent->xexpose.x; + info.y = xevent->xexpose.y; + info.width = xevent->xexpose.width; + info.height = xevent->xexpose.height; + + _cogl_onscreen_queue_dirty (onscreen, &info); + } + } + + return COGL_FILTER_CONTINUE; +} + +static XVisualInfo * +get_visual_info (CoglDisplay *display, EGLConfig egl_config) +{ + CoglXlibRenderer *xlib_renderer = + _cogl_xlib_renderer_get_data (display->renderer); + CoglRendererEGL *egl_renderer = display->renderer->winsys; + XVisualInfo visinfo_template; + int template_mask = 0; + XVisualInfo *visinfo = NULL; + int visinfos_count; + EGLint visualid, red_size, green_size, blue_size, alpha_size; + + eglGetConfigAttrib (egl_renderer->edpy, egl_config, + EGL_NATIVE_VISUAL_ID, &visualid); + + if (visualid != 0) + { + visinfo_template.visualid = visualid; + template_mask |= VisualIDMask; + } + else + { + /* some EGL drivers don't implement the EGL_NATIVE_VISUAL_ID + * attribute, so attempt to find the closest match. */ + + eglGetConfigAttrib (egl_renderer->edpy, egl_config, + EGL_RED_SIZE, &red_size); + eglGetConfigAttrib (egl_renderer->edpy, egl_config, + EGL_GREEN_SIZE, &green_size); + eglGetConfigAttrib (egl_renderer->edpy, egl_config, + EGL_BLUE_SIZE, &blue_size); + eglGetConfigAttrib (egl_renderer->edpy, egl_config, + EGL_ALPHA_SIZE, &alpha_size); + + visinfo_template.depth = red_size + green_size + blue_size + alpha_size; + template_mask |= VisualDepthMask; + + visinfo_template.screen = DefaultScreen (xlib_renderer->xdpy); + template_mask |= VisualScreenMask; + } + + visinfo = XGetVisualInfo (xlib_renderer->xdpy, + template_mask, + &visinfo_template, + &visinfos_count); + + return visinfo; +} + +static void +_cogl_winsys_renderer_disconnect (CoglRenderer *renderer) +{ + CoglRendererEGL *egl_renderer = renderer->winsys; + + _cogl_xlib_renderer_disconnect (renderer); + + eglTerminate (egl_renderer->edpy); + + g_slice_free (CoglRendererEGL, egl_renderer); +} + +static EGLDisplay +_cogl_winsys_egl_get_display (void *native) +{ + EGLDisplay dpy = NULL; + const char *client_exts = eglQueryString (NULL, EGL_EXTENSIONS); + + if (g_strstr_len (client_exts, -1, "EGL_KHR_platform_base")) + { + PFNEGLGETPLATFORMDISPLAYEXTPROC get_platform_display = + (void *) eglGetProcAddress ("eglGetPlatformDisplay"); + + if (get_platform_display) + dpy = get_platform_display (EGL_PLATFORM_X11_KHR, native, NULL); + + if (dpy) + return dpy; + } + + if (g_strstr_len (client_exts, -1, "EGL_EXT_platform_base")) + { + PFNEGLGETPLATFORMDISPLAYEXTPROC get_platform_display = + (void *) eglGetProcAddress ("eglGetPlatformDisplayEXT"); + + if (get_platform_display) + dpy = get_platform_display (EGL_PLATFORM_X11_KHR, native, NULL); + + if (dpy) + return dpy; + } + + return eglGetDisplay ((EGLNativeDisplayType) native); +} + +static CoglBool +_cogl_winsys_renderer_connect (CoglRenderer *renderer, + CoglError **error) +{ + CoglRendererEGL *egl_renderer; + CoglXlibRenderer *xlib_renderer; + + renderer->winsys = g_slice_new0 (CoglRendererEGL); + egl_renderer = renderer->winsys; + xlib_renderer = _cogl_xlib_renderer_get_data (renderer); + + egl_renderer->platform_vtable = &_cogl_winsys_egl_vtable; + + if (!_cogl_xlib_renderer_connect (renderer, error)) + goto error; + + egl_renderer->edpy = _cogl_winsys_egl_get_display (xlib_renderer->xdpy); + + if (!_cogl_winsys_egl_renderer_connect_common (renderer, error)) + goto error; + + return TRUE; + +error: + _cogl_winsys_renderer_disconnect (renderer); + return FALSE; +} + +static CoglBool +_cogl_winsys_egl_display_setup (CoglDisplay *display, + CoglError **error) +{ + CoglDisplayEGL *egl_display = display->winsys; + CoglDisplayXlib *xlib_display; + + xlib_display = g_slice_new0 (CoglDisplayXlib); + egl_display->platform = xlib_display; + + return TRUE; +} + +static void +_cogl_winsys_egl_display_destroy (CoglDisplay *display) +{ + CoglDisplayEGL *egl_display = display->winsys; + + g_slice_free (CoglDisplayXlib, egl_display->platform); +} + +static CoglBool +_cogl_winsys_egl_context_init (CoglContext *context, + CoglError **error) +{ + cogl_xlib_renderer_add_filter (context->display->renderer, + event_filter_cb, + context); + + context->feature_flags |= COGL_FEATURE_ONSCREEN_MULTIPLE; + COGL_FLAGS_SET (context->features, + COGL_FEATURE_ID_ONSCREEN_MULTIPLE, TRUE); + COGL_FLAGS_SET (context->winsys_features, + COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN, + TRUE); + + /* We'll manually handle queueing dirty events in response to + * Expose events from X */ + COGL_FLAGS_SET (context->private_features, + COGL_PRIVATE_FEATURE_DIRTY_EVENTS, + TRUE); + + return TRUE; +} + +static void +_cogl_winsys_egl_context_deinit (CoglContext *context) +{ + cogl_xlib_renderer_remove_filter (context->display->renderer, + event_filter_cb, + context); +} + +static CoglBool +_cogl_winsys_egl_onscreen_init (CoglOnscreen *onscreen, + EGLConfig egl_config, + CoglError **error) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + CoglContext *context = framebuffer->context; + CoglDisplay *display = context->display; + CoglRenderer *renderer = display->renderer; + CoglRendererEGL *egl_renderer = renderer->winsys; + CoglXlibRenderer *xlib_renderer = + _cogl_xlib_renderer_get_data (renderer); + CoglOnscreenXlib *xlib_onscreen; + CoglOnscreenEGL *egl_onscreen = onscreen->winsys; + Window xwin; + + /* FIXME: We need to explicitly Select for ConfigureNotify events. + * For foreign windows we need to be careful not to mess up any + * existing event mask. + * We need to document that for windows we create then toolkits + * must be careful not to clear event mask bits that we select. + */ + + /* XXX: Note we ignore the user's original width/height when + * given a foreign X window. */ + if (onscreen->foreign_xid) + { + Status status; + CoglXlibTrapState state; + XWindowAttributes attr; + int xerror; + + xwin = onscreen->foreign_xid; + + _cogl_xlib_renderer_trap_errors (display->renderer, &state); + + status = XGetWindowAttributes (xlib_renderer->xdpy, xwin, &attr); + xerror = _cogl_xlib_renderer_untrap_errors (display->renderer, + &state); + if (status == 0 || xerror) + { + char message[1000]; + XGetErrorText (xlib_renderer->xdpy, xerror, + message, sizeof (message)); + _cogl_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_CREATE_ONSCREEN, + "Unable to query geometry of foreign " + "xid 0x%08lX: %s", + xwin, message); + return FALSE; + } + + _cogl_framebuffer_winsys_update_size (framebuffer, + attr.width, attr.height); + + /* Make sure the app selects for the events we require... */ + onscreen->foreign_update_mask_callback (onscreen, + COGL_ONSCREEN_X11_EVENT_MASK, + onscreen-> + foreign_update_mask_data); + } + else + { + int width; + int height; + CoglXlibTrapState state; + XVisualInfo *xvisinfo; + XSetWindowAttributes xattr; + unsigned long mask; + int xerror; + + width = cogl_framebuffer_get_width (framebuffer); + height = cogl_framebuffer_get_height (framebuffer); + + _cogl_xlib_renderer_trap_errors (display->renderer, &state); + + xvisinfo = get_visual_info (display, egl_config); + if (xvisinfo == NULL) + { + _cogl_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_CREATE_ONSCREEN, + "Unable to retrieve the X11 visual of context's " + "fbconfig"); + return FALSE; + } + + /* window attributes */ + xattr.background_pixel = + WhitePixel (xlib_renderer->xdpy, + DefaultScreen (xlib_renderer->xdpy)); + xattr.border_pixel = 0; + /* XXX: is this an X resource that we are leaking‽... */ + xattr.colormap = + XCreateColormap (xlib_renderer->xdpy, + DefaultRootWindow (xlib_renderer->xdpy), + xvisinfo->visual, + AllocNone); + xattr.event_mask = COGL_ONSCREEN_X11_EVENT_MASK; + + mask = CWBorderPixel | CWColormap | CWEventMask; + + xwin = XCreateWindow (xlib_renderer->xdpy, + DefaultRootWindow (xlib_renderer->xdpy), + 0, 0, + width, height, + 0, + xvisinfo->depth, + InputOutput, + xvisinfo->visual, + mask, &xattr); + + XFree (xvisinfo); + + XSync (xlib_renderer->xdpy, False); + xerror = + _cogl_xlib_renderer_untrap_errors (display->renderer, &state); + if (xerror) + { + char message[1000]; + XGetErrorText (xlib_renderer->xdpy, xerror, + message, sizeof (message)); + _cogl_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_CREATE_ONSCREEN, + "X error while creating Window for CoglOnscreen: %s", + message); + return FALSE; + } + } + + xlib_onscreen = g_slice_new (CoglOnscreenXlib); + egl_onscreen->platform = xlib_onscreen; + + xlib_onscreen->xwin = xwin; + xlib_onscreen->is_foreign_xwin = onscreen->foreign_xid ? TRUE : FALSE; + + egl_onscreen->egl_surface = + eglCreateWindowSurface (egl_renderer->edpy, + egl_config, + (EGLNativeWindowType) xlib_onscreen->xwin, + NULL); + + return TRUE; +} + +static void +_cogl_winsys_egl_onscreen_deinit (CoglOnscreen *onscreen) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + CoglContext *context = framebuffer->context; + CoglRenderer *renderer = context->display->renderer; + CoglXlibRenderer *xlib_renderer = + _cogl_xlib_renderer_get_data (renderer); + CoglXlibTrapState old_state; + CoglOnscreenEGL *egl_onscreen = onscreen->winsys; + CoglOnscreenXlib *xlib_onscreen = egl_onscreen->platform; + + _cogl_xlib_renderer_trap_errors (renderer, &old_state); + + if (!xlib_onscreen->is_foreign_xwin && xlib_onscreen->xwin != None) + { + XDestroyWindow (xlib_renderer->xdpy, xlib_onscreen->xwin); + xlib_onscreen->xwin = None; + } + else + xlib_onscreen->xwin = None; + + XSync (xlib_renderer->xdpy, False); + + if (_cogl_xlib_renderer_untrap_errors (renderer, + &old_state) != Success) + g_warning ("X Error while destroying X window"); + + g_slice_free (CoglOnscreenXlib, xlib_onscreen); +} + +static void +_cogl_winsys_onscreen_set_visibility (CoglOnscreen *onscreen, + CoglBool visibility) +{ + CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context; + CoglRenderer *renderer = context->display->renderer; + CoglXlibRenderer *xlib_renderer = + _cogl_xlib_renderer_get_data (renderer); + CoglOnscreenEGL *onscreen_egl = onscreen->winsys; + CoglOnscreenXlib *xlib_onscreen = onscreen_egl->platform; + + if (visibility) + XMapWindow (xlib_renderer->xdpy, xlib_onscreen->xwin); + else + XUnmapWindow (xlib_renderer->xdpy, xlib_onscreen->xwin); +} + +static void +_cogl_winsys_onscreen_set_resizable (CoglOnscreen *onscreen, + CoglBool resizable) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + CoglContext *context = framebuffer->context; + CoglXlibRenderer *xlib_renderer = + _cogl_xlib_renderer_get_data (context->display->renderer); + CoglOnscreenEGL *egl_onscreen = onscreen->winsys; + CoglOnscreenXlib *xlib_onscreen = egl_onscreen->platform; + + XSizeHints *size_hints = XAllocSizeHints (); + + if (resizable) + { + /* TODO: Add cogl_onscreen_request_minimum_size () */ + size_hints->min_width = 1; + size_hints->min_height = 1; + + size_hints->max_width = INT_MAX; + size_hints->max_height = INT_MAX; + } + else + { + int width = cogl_framebuffer_get_width (framebuffer); + int height = cogl_framebuffer_get_height (framebuffer); + + size_hints->min_width = width; + size_hints->min_height = height; + + size_hints->max_width = width; + size_hints->max_height = height; + } + + XSetWMNormalHints (xlib_renderer->xdpy, xlib_onscreen->xwin, size_hints); + + XFree (size_hints); +} + +static uint32_t +_cogl_winsys_onscreen_x11_get_window_xid (CoglOnscreen *onscreen) +{ + CoglOnscreenEGL *egl_onscreen = onscreen->winsys; + CoglOnscreenXlib *xlib_onscreen = egl_onscreen->platform; + + return xlib_onscreen->xwin; +} + +static CoglBool +_cogl_winsys_egl_context_created (CoglDisplay *display, + CoglError **error) +{ + CoglRenderer *renderer = display->renderer; + CoglDisplayEGL *egl_display = display->winsys; + CoglRendererEGL *egl_renderer = renderer->winsys; + CoglXlibRenderer *xlib_renderer = + _cogl_xlib_renderer_get_data (renderer); + CoglDisplayXlib *xlib_display = egl_display->platform; + XVisualInfo *xvisinfo; + XSetWindowAttributes attrs; + const char *error_message; + + xvisinfo = get_visual_info (display, egl_display->egl_config); + if (xvisinfo == NULL) + { + error_message = "Unable to find suitable X visual"; + goto fail; + } + + attrs.override_redirect = True; + attrs.colormap = XCreateColormap (xlib_renderer->xdpy, + DefaultRootWindow (xlib_renderer->xdpy), + xvisinfo->visual, + AllocNone); + attrs.border_pixel = 0; + + if ((egl_renderer->private_features & + COGL_EGL_WINSYS_FEATURE_SURFACELESS_CONTEXT) == 0) + { + xlib_display->dummy_xwin = + XCreateWindow (xlib_renderer->xdpy, + DefaultRootWindow (xlib_renderer->xdpy), + -100, -100, 1, 1, + 0, + xvisinfo->depth, + CopyFromParent, + xvisinfo->visual, + CWOverrideRedirect | + CWColormap | + CWBorderPixel, + &attrs); + + egl_display->dummy_surface = + eglCreateWindowSurface (egl_renderer->edpy, + egl_display->egl_config, + (EGLNativeWindowType) xlib_display->dummy_xwin, + NULL); + + if (egl_display->dummy_surface == EGL_NO_SURFACE) + { + error_message = "Unable to create an EGL surface"; + XFree (xvisinfo); + goto fail; + } + } + + xlib_renderer->xvisinfo = xvisinfo; + + if (!_cogl_winsys_egl_make_current (display, + egl_display->dummy_surface, + egl_display->dummy_surface, + egl_display->egl_context)) + { + if (egl_display->dummy_surface == EGL_NO_SURFACE) + error_message = "Unable to eglMakeCurrent with no surface"; + else + error_message = "Unable to eglMakeCurrent with dummy surface"; + goto fail; + } + + return TRUE; + +fail: + _cogl_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_CREATE_CONTEXT, + "%s", error_message); + return FALSE; +} + +static void +_cogl_winsys_egl_cleanup_context (CoglDisplay *display) +{ + CoglDisplayEGL *egl_display = display->winsys; + CoglDisplayXlib *xlib_display = egl_display->platform; + CoglRenderer *renderer = display->renderer; + CoglXlibRenderer *xlib_renderer = + _cogl_xlib_renderer_get_data (renderer); + CoglRendererEGL *egl_renderer = renderer->winsys; + + if (egl_display->dummy_surface != EGL_NO_SURFACE) + { + eglDestroySurface (egl_renderer->edpy, egl_display->dummy_surface); + egl_display->dummy_surface = EGL_NO_SURFACE; + } + + if (xlib_display->dummy_xwin) + { + XDestroyWindow (xlib_renderer->xdpy, xlib_display->dummy_xwin); + xlib_display->dummy_xwin = None; + } +} + +#ifdef EGL_KHR_image_pixmap + +static CoglBool +_cogl_winsys_texture_pixmap_x11_create (CoglTexturePixmapX11 *tex_pixmap) +{ + CoglTexture *tex = COGL_TEXTURE (tex_pixmap); + CoglContext *ctx = tex->context; + CoglTexturePixmapEGL *egl_tex_pixmap; + EGLint attribs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; + CoglPixelFormat texture_format; + CoglRendererEGL *egl_renderer; + + egl_renderer = ctx->display->renderer->winsys; + + if (!(egl_renderer->private_features & + COGL_EGL_WINSYS_FEATURE_EGL_IMAGE_FROM_X11_PIXMAP) || + !_cogl_has_private_feature + (ctx, COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE)) + { + tex_pixmap->winsys = NULL; + return FALSE; + } + + egl_tex_pixmap = g_new0 (CoglTexturePixmapEGL, 1); + + egl_tex_pixmap->image = + _cogl_egl_create_image (ctx, + EGL_NATIVE_PIXMAP_KHR, + (EGLClientBuffer)tex_pixmap->pixmap, + attribs); + if (egl_tex_pixmap->image == EGL_NO_IMAGE_KHR) + { + g_free (egl_tex_pixmap); + return FALSE; + } + + texture_format = (tex_pixmap->depth >= 32 ? + COGL_PIXEL_FORMAT_RGBA_8888_PRE : + COGL_PIXEL_FORMAT_RGB_888); + + egl_tex_pixmap->texture = COGL_TEXTURE ( + _cogl_egl_texture_2d_new_from_image (ctx, + tex->width, + tex->height, + texture_format, + egl_tex_pixmap->image, + NULL)); + + tex_pixmap->winsys = egl_tex_pixmap; + + return TRUE; +} + +static void +_cogl_winsys_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap) +{ + CoglTexturePixmapEGL *egl_tex_pixmap; + + /* FIXME: It should be possible to get to a CoglContext from any + * CoglTexture pointer. */ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (!tex_pixmap->winsys) + return; + + egl_tex_pixmap = tex_pixmap->winsys; + + if (egl_tex_pixmap->texture) + cogl_object_unref (egl_tex_pixmap->texture); + + if (egl_tex_pixmap->image != EGL_NO_IMAGE_KHR) + _cogl_egl_destroy_image (ctx, egl_tex_pixmap->image); + + tex_pixmap->winsys = NULL; + g_free (egl_tex_pixmap); +} + +static CoglBool +_cogl_winsys_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap, + CoglTexturePixmapStereoMode stereo_mode, + CoglBool needs_mipmap) +{ + if (needs_mipmap) + return FALSE; + + return TRUE; +} + +static void +_cogl_winsys_texture_pixmap_x11_damage_notify (CoglTexturePixmapX11 *tex_pixmap) +{ +} + +static CoglTexture * +_cogl_winsys_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap, + CoglTexturePixmapStereoMode stereo_mode) +{ + CoglTexturePixmapEGL *egl_tex_pixmap = tex_pixmap->winsys; + + return egl_tex_pixmap->texture; +} + +#endif /* EGL_KHR_image_pixmap */ + +static const CoglWinsysEGLVtable +_cogl_winsys_egl_vtable = + { + .display_setup = _cogl_winsys_egl_display_setup, + .display_destroy = _cogl_winsys_egl_display_destroy, + .context_created = _cogl_winsys_egl_context_created, + .cleanup_context = _cogl_winsys_egl_cleanup_context, + .context_init = _cogl_winsys_egl_context_init, + .context_deinit = _cogl_winsys_egl_context_deinit, + .onscreen_init = _cogl_winsys_egl_onscreen_init, + .onscreen_deinit = _cogl_winsys_egl_onscreen_deinit + }; + +const CoglWinsysVtable * +_cogl_winsys_egl_xlib_get_vtable (void) +{ + static CoglBool vtable_inited = FALSE; + static CoglWinsysVtable vtable; + + if (!vtable_inited) + { + /* The EGL_X11 winsys is a subclass of the EGL winsys so we + start by copying its vtable */ + + vtable = *_cogl_winsys_egl_get_vtable (); + + vtable.id = COGL_WINSYS_ID_EGL_XLIB; + vtable.name = "EGL_XLIB"; + vtable.constraints |= (COGL_RENDERER_CONSTRAINT_USES_X11 | + COGL_RENDERER_CONSTRAINT_USES_XLIB); + + vtable.renderer_connect = _cogl_winsys_renderer_connect; + vtable.renderer_disconnect = _cogl_winsys_renderer_disconnect; + + vtable.onscreen_set_visibility = + _cogl_winsys_onscreen_set_visibility; + vtable.onscreen_set_resizable = + _cogl_winsys_onscreen_set_resizable; + + vtable.onscreen_x11_get_window_xid = + _cogl_winsys_onscreen_x11_get_window_xid; + +#ifdef EGL_KHR_image_pixmap + /* X11 tfp support... */ + /* XXX: instead of having a rather monolithic winsys vtable we could + * perhaps look for a way to separate these... */ + vtable.texture_pixmap_x11_create = + _cogl_winsys_texture_pixmap_x11_create; + vtable.texture_pixmap_x11_free = + _cogl_winsys_texture_pixmap_x11_free; + vtable.texture_pixmap_x11_update = + _cogl_winsys_texture_pixmap_x11_update; + vtable.texture_pixmap_x11_damage_notify = + _cogl_winsys_texture_pixmap_x11_damage_notify; + vtable.texture_pixmap_x11_get_texture = + _cogl_winsys_texture_pixmap_x11_get_texture; +#endif /* EGL_KHR_image_pixmap) */ + + vtable_inited = TRUE; + } + + return &vtable; +} diff --git a/cogl/cogl/winsys/cogl-winsys-egl.c b/cogl/cogl/winsys/cogl-winsys-egl.c new file mode 100644 index 0000000..dbf14f6 --- /dev/null +++ b/cogl/cogl/winsys/cogl-winsys-egl.c @@ -0,0 +1,1092 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2010,2011,2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-i18n-private.h" +#include "cogl-util.h" +#include "cogl-winsys-egl-private.h" +#include "cogl-winsys-private.h" +#include "cogl-feature-private.h" +#include "cogl-context-private.h" +#include "cogl-framebuffer.h" +#include "cogl-onscreen-private.h" +#include "cogl-swap-chain-private.h" +#include "cogl-renderer-private.h" +#include "cogl-onscreen-template-private.h" +#include "cogl-gles2-context-private.h" +#include "cogl-error-private.h" +#include "cogl-egl.h" + +#include "cogl-private.h" + +#include +#include +#include +#include +#include + + +#ifndef EGL_KHR_create_context +#define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098 +#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB +#define EGL_CONTEXT_FLAGS_KHR 0x30FC +#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD +#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31BD +#define EGL_OPENGL_ES3_BIT_KHR 0x0040 +#define EGL_NO_RESET_NOTIFICATION_KHR 0x31BE +#define EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31BF +#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001 +#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002 +#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004 +#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001 +#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002 +#endif + + +#define MAX_EGL_CONFIG_ATTRIBS 30 + +/* Define a set of arrays containing the functions required from GL + for each winsys feature */ +#define COGL_WINSYS_FEATURE_BEGIN(name, namespaces, extension_names, \ + egl_private_flags) \ + static const CoglFeatureFunction \ + cogl_egl_feature_ ## name ## _funcs[] = { +#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args) \ + { G_STRINGIFY (name), G_STRUCT_OFFSET (CoglRendererEGL, pf_ ## name) }, +#define COGL_WINSYS_FEATURE_END() \ + { NULL, 0 }, \ + }; +#include "cogl-winsys-egl-feature-functions.h" + +/* Define an array of features */ +#undef COGL_WINSYS_FEATURE_BEGIN +#define COGL_WINSYS_FEATURE_BEGIN(name, namespaces, extension_names, \ + egl_private_flags) \ + { 255, 255, 0, namespaces, extension_names, \ + 0, egl_private_flags, \ + 0, \ + cogl_egl_feature_ ## name ## _funcs }, +#undef COGL_WINSYS_FEATURE_FUNCTION +#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args) +#undef COGL_WINSYS_FEATURE_END +#define COGL_WINSYS_FEATURE_END() + +static const CoglFeatureData winsys_feature_data[] = + { +#include "cogl-winsys-egl-feature-functions.h" + }; + +static const char * +get_error_string (void) +{ + switch (eglGetError()){ + case EGL_BAD_DISPLAY: + return "Invalid display"; + case EGL_NOT_INITIALIZED: + return "Display not initialized"; + case EGL_BAD_ALLOC: + return "Not enough resources to allocate context"; + case EGL_BAD_ATTRIBUTE: + return "Invalid attribute"; + case EGL_BAD_CONFIG: + return "Invalid config"; + case EGL_BAD_CONTEXT: + return "Invalid context"; + case EGL_BAD_CURRENT_SURFACE: + return "Invalid current surface"; + case EGL_BAD_MATCH: + return "Bad match"; + case EGL_BAD_NATIVE_PIXMAP: + return "Invalid native pixmap"; + case EGL_BAD_NATIVE_WINDOW: + return "Invalid native window"; + case EGL_BAD_PARAMETER: + return "Invalid parameter"; + case EGL_BAD_SURFACE: + return "Invalid surface"; + default: + g_assert_not_reached (); + } +} + +static CoglFuncPtr +_cogl_winsys_renderer_get_proc_address (CoglRenderer *renderer, + const char *name, + CoglBool in_core) +{ + void *ptr = NULL; + + if (!in_core) + ptr = eglGetProcAddress (name); + + /* eglGetProcAddress doesn't support fetching core API so we need to + get that separately with GModule */ + if (ptr == NULL) + g_module_symbol (renderer->libgl_module, name, &ptr); + + return ptr; +} + +static void +_cogl_winsys_renderer_disconnect (CoglRenderer *renderer) +{ + /* This function must be overridden by a platform winsys */ + g_assert_not_reached (); +} + +/* Updates all the function pointers */ +static void +check_egl_extensions (CoglRenderer *renderer) +{ + CoglRendererEGL *egl_renderer = renderer->winsys; + const char *egl_extensions; + char **split_extensions; + int i; + + egl_extensions = eglQueryString (egl_renderer->edpy, EGL_EXTENSIONS); + split_extensions = g_strsplit (egl_extensions, " ", 0 /* max_tokens */); + + COGL_NOTE (WINSYS, " EGL Extensions: %s", egl_extensions); + + egl_renderer->private_features = 0; + for (i = 0; i < G_N_ELEMENTS (winsys_feature_data); i++) + if (_cogl_feature_check (renderer, + "EGL", winsys_feature_data + i, 0, 0, + COGL_DRIVER_GL, /* the driver isn't used */ + split_extensions, + egl_renderer)) + { + egl_renderer->private_features |= + winsys_feature_data[i].feature_flags_private; + } + + g_strfreev (split_extensions); +} + +CoglBool +_cogl_winsys_egl_renderer_connect_common (CoglRenderer *renderer, + CoglError **error) +{ + CoglRendererEGL *egl_renderer = renderer->winsys; + + if (!eglInitialize (egl_renderer->edpy, + &egl_renderer->egl_version_major, + &egl_renderer->egl_version_minor)) + { + _cogl_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_INIT, + "Couldn't initialize EGL"); + return FALSE; + } + + check_egl_extensions (renderer); + + return TRUE; +} + +static CoglBool +_cogl_winsys_renderer_connect (CoglRenderer *renderer, + CoglError **error) +{ + /* This function must be overridden by a platform winsys */ + g_assert_not_reached (); +} + +static void +egl_attributes_from_framebuffer_config (CoglDisplay *display, + CoglFramebufferConfig *config, + EGLint *attributes) +{ + CoglRenderer *renderer = display->renderer; + CoglRendererEGL *egl_renderer = renderer->winsys; + int i = 0; + + /* Let the platform add attributes first */ + if (egl_renderer->platform_vtable->add_config_attributes) + i = egl_renderer->platform_vtable->add_config_attributes (display, + config, + attributes); + + if (config->need_stencil) + { + attributes[i++] = EGL_STENCIL_SIZE; + attributes[i++] = 2; + } + + attributes[i++] = EGL_RED_SIZE; + attributes[i++] = 1; + attributes[i++] = EGL_GREEN_SIZE; + attributes[i++] = 1; + attributes[i++] = EGL_BLUE_SIZE; + attributes[i++] = 1; + + attributes[i++] = EGL_ALPHA_SIZE; + attributes[i++] = config->swap_chain->has_alpha ? 1 : EGL_DONT_CARE; + + attributes[i++] = EGL_DEPTH_SIZE; + attributes[i++] = 1; + + attributes[i++] = EGL_BUFFER_SIZE; + attributes[i++] = EGL_DONT_CARE; + + attributes[i++] = EGL_RENDERABLE_TYPE; + attributes[i++] = ((renderer->driver == COGL_DRIVER_GL || + renderer->driver == COGL_DRIVER_GL3) ? + EGL_OPENGL_BIT : + renderer->driver == COGL_DRIVER_GLES1 ? + EGL_OPENGL_ES_BIT : + EGL_OPENGL_ES2_BIT); + + attributes[i++] = EGL_SURFACE_TYPE; + attributes[i++] = EGL_WINDOW_BIT; + + if (config->samples_per_pixel) + { + attributes[i++] = EGL_SAMPLE_BUFFERS; + attributes[i++] = 1; + attributes[i++] = EGL_SAMPLES; + attributes[i++] = config->samples_per_pixel; + } + + attributes[i++] = EGL_NONE; + + g_assert (i < MAX_EGL_CONFIG_ATTRIBS); +} + +EGLBoolean +_cogl_winsys_egl_make_current (CoglDisplay *display, + EGLSurface draw, + EGLSurface read, + EGLContext context) +{ + CoglDisplayEGL *egl_display = display->winsys; + CoglRendererEGL *egl_renderer = display->renderer->winsys; + EGLBoolean ret; + + if (egl_display->current_draw_surface == draw && + egl_display->current_read_surface == read && + egl_display->current_context == context) + return EGL_TRUE; + + ret = eglMakeCurrent (egl_renderer->edpy, + draw, + read, + context); + + egl_display->current_draw_surface = draw; + egl_display->current_read_surface = read; + egl_display->current_context = context; + + return ret; +} + +static void +cleanup_context (CoglDisplay *display) +{ + CoglRenderer *renderer = display->renderer; + CoglDisplayEGL *egl_display = display->winsys; + CoglRendererEGL *egl_renderer = renderer->winsys; + + if (egl_display->egl_context != EGL_NO_CONTEXT) + { + _cogl_winsys_egl_make_current (display, + EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); + eglDestroyContext (egl_renderer->edpy, egl_display->egl_context); + egl_display->egl_context = EGL_NO_CONTEXT; + } + + if (egl_renderer->platform_vtable->cleanup_context) + egl_renderer->platform_vtable->cleanup_context (display); +} + +static CoglBool +try_create_context (CoglDisplay *display, + CoglError **error) +{ + CoglRenderer *renderer = display->renderer; + CoglDisplayEGL *egl_display = display->winsys; + CoglRendererEGL *egl_renderer = renderer->winsys; + EGLDisplay edpy; + EGLConfig config; + EGLint config_count = 0; + EGLBoolean status; + EGLint attribs[9]; + EGLint cfg_attribs[MAX_EGL_CONFIG_ATTRIBS]; + const char *error_message; + + _COGL_RETURN_VAL_IF_FAIL (egl_display->egl_context == NULL, TRUE); + + if (renderer->driver == COGL_DRIVER_GL || + renderer->driver == COGL_DRIVER_GL3) + eglBindAPI (EGL_OPENGL_API); + + egl_attributes_from_framebuffer_config (display, + &display->onscreen_template->config, + cfg_attribs); + + edpy = egl_renderer->edpy; + + status = eglChooseConfig (edpy, + cfg_attribs, + &config, 1, + &config_count); + if (status != EGL_TRUE || config_count == 0) + { + error_message = "Unable to find a usable EGL configuration"; + goto fail; + } + + egl_display->egl_config = config; + + if (display->renderer->driver == COGL_DRIVER_GL3) + { + if (!(egl_renderer->private_features & + COGL_EGL_WINSYS_FEATURE_CREATE_CONTEXT)) + { + error_message = "Driver does not support GL 3 contexts"; + goto fail; + } + + /* Try to get a core profile 3.1 context with no deprecated features */ + attribs[0] = EGL_CONTEXT_MAJOR_VERSION_KHR; + attribs[1] = 3; + attribs[2] = EGL_CONTEXT_MINOR_VERSION_KHR; + attribs[3] = 1; + attribs[4] = EGL_CONTEXT_FLAGS_KHR; + attribs[5] = EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; + attribs[6] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR; + attribs[7] = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; + attribs[8] = EGL_NONE; + } + else if (display->renderer->driver == COGL_DRIVER_GLES2) + { + attribs[0] = EGL_CONTEXT_CLIENT_VERSION; + attribs[1] = 2; + attribs[2] = EGL_NONE; + } + else + attribs[0] = EGL_NONE; + + egl_display->egl_context = eglCreateContext (edpy, + config, + EGL_NO_CONTEXT, + attribs); + + if (egl_display->egl_context == EGL_NO_CONTEXT) + { + error_message = "Unable to create a suitable EGL context"; + goto fail; + } + + if (egl_renderer->platform_vtable->context_created && + !egl_renderer->platform_vtable->context_created (display, error)) + return FALSE; + + return TRUE; + +fail: + _cogl_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_CREATE_CONTEXT, + "%s", error_message); + + cleanup_context (display); + + return FALSE; +} + +static void +_cogl_winsys_display_destroy (CoglDisplay *display) +{ + CoglRendererEGL *egl_renderer = display->renderer->winsys; + CoglDisplayEGL *egl_display = display->winsys; + + _COGL_RETURN_IF_FAIL (egl_display != NULL); + + cleanup_context (display); + + if (egl_renderer->platform_vtable->display_destroy) + egl_renderer->platform_vtable->display_destroy (display); + + g_slice_free (CoglDisplayEGL, display->winsys); + display->winsys = NULL; +} + +static CoglBool +_cogl_winsys_display_setup (CoglDisplay *display, + CoglError **error) +{ + CoglDisplayEGL *egl_display; + CoglRenderer *renderer = display->renderer; + CoglRendererEGL *egl_renderer = renderer->winsys; + + _COGL_RETURN_VAL_IF_FAIL (display->winsys == NULL, FALSE); + + egl_display = g_slice_new0 (CoglDisplayEGL); + display->winsys = egl_display; + +#ifdef COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT + if (display->wayland_compositor_display) + { + struct wl_display *wayland_display = display->wayland_compositor_display; + CoglRendererEGL *egl_renderer = display->renderer->winsys; + + if (egl_renderer->pf_eglBindWaylandDisplay) + egl_renderer->pf_eglBindWaylandDisplay (egl_renderer->edpy, + wayland_display); + } +#endif + + if (egl_renderer->platform_vtable->display_setup && + !egl_renderer->platform_vtable->display_setup (display, error)) + goto error; + + if (!try_create_context (display, error)) + goto error; + + egl_display->found_egl_config = TRUE; + + return TRUE; + +error: + _cogl_winsys_display_destroy (display); + return FALSE; +} + +static CoglBool +_cogl_winsys_context_init (CoglContext *context, CoglError **error) +{ + CoglRenderer *renderer = context->display->renderer; + CoglDisplayEGL *egl_display = context->display->winsys; + CoglRendererEGL *egl_renderer = renderer->winsys; + + context->winsys = g_new0 (CoglContextEGL, 1); + + _COGL_RETURN_VAL_IF_FAIL (egl_display->egl_context, FALSE); + + memset (context->winsys_features, 0, sizeof (context->winsys_features)); + + check_egl_extensions (renderer); + + if (!_cogl_context_update_features (context, error)) + return FALSE; + + if (egl_renderer->private_features & COGL_EGL_WINSYS_FEATURE_SWAP_REGION) + { + COGL_FLAGS_SET (context->winsys_features, + COGL_WINSYS_FEATURE_SWAP_REGION, TRUE); + COGL_FLAGS_SET (context->winsys_features, + COGL_WINSYS_FEATURE_SWAP_REGION_THROTTLE, TRUE); + } + + if ((egl_renderer->private_features & COGL_EGL_WINSYS_FEATURE_FENCE_SYNC) && + _cogl_has_private_feature (context, COGL_PRIVATE_FEATURE_OES_EGL_SYNC)) + COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_FENCE, TRUE); + + if (egl_renderer->private_features & COGL_EGL_WINSYS_FEATURE_BUFFER_AGE) + { + COGL_FLAGS_SET (context->winsys_features, + COGL_WINSYS_FEATURE_BUFFER_AGE, + TRUE); + COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_BUFFER_AGE, TRUE); + } + + /* NB: We currently only support creating standalone GLES2 contexts + * for offscreen rendering and so we need a dummy (non-visible) + * surface to be able to bind those contexts */ + if (egl_display->dummy_surface != EGL_NO_SURFACE && + context->driver == COGL_DRIVER_GLES2) + COGL_FLAGS_SET (context->features, + COGL_FEATURE_ID_GLES2_CONTEXT, TRUE); + + if (egl_renderer->platform_vtable->context_init && + !egl_renderer->platform_vtable->context_init (context, error)) + return FALSE; + + return TRUE; +} + +static void +_cogl_winsys_context_deinit (CoglContext *context) +{ + CoglRenderer *renderer = context->display->renderer; + CoglRendererEGL *egl_renderer = renderer->winsys; + + if (egl_renderer->platform_vtable->context_deinit) + egl_renderer->platform_vtable->context_deinit (context); + + g_free (context->winsys); +} + +typedef struct _CoglGLES2ContextEGL +{ + EGLContext egl_context; + EGLSurface dummy_surface; +} CoglGLES2ContextEGL; + +static void * +_cogl_winsys_context_create_gles2_context (CoglContext *ctx, CoglError **error) +{ + CoglRendererEGL *egl_renderer = ctx->display->renderer->winsys; + CoglDisplayEGL *egl_display = ctx->display->winsys; + EGLint attribs[3]; + EGLContext egl_context; + + attribs[0] = EGL_CONTEXT_CLIENT_VERSION; + attribs[1] = 2; + attribs[2] = EGL_NONE; + + egl_context = eglCreateContext (egl_renderer->edpy, + egl_display->egl_config, + egl_display->egl_context, + attribs); + if (egl_context == EGL_NO_CONTEXT) + { + _cogl_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_CREATE_GLES2_CONTEXT, + "%s", get_error_string ()); + return NULL; + } + + return (void *)egl_context; +} + +static void +_cogl_winsys_destroy_gles2_context (CoglGLES2Context *gles2_ctx) +{ + CoglContext *context = gles2_ctx->context; + CoglDisplay *display = context->display; + CoglDisplayEGL *egl_display = display->winsys; + CoglRenderer *renderer = display->renderer; + CoglRendererEGL *egl_renderer = renderer->winsys; + EGLContext egl_context = gles2_ctx->winsys; + + _COGL_RETURN_IF_FAIL (egl_display->current_context != egl_context); + + eglDestroyContext (egl_renderer->edpy, egl_context); +} + +static CoglBool +_cogl_winsys_onscreen_init (CoglOnscreen *onscreen, + CoglError **error) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + CoglContext *context = framebuffer->context; + CoglDisplay *display = context->display; + CoglDisplayEGL *egl_display = display->winsys; + CoglRenderer *renderer = display->renderer; + CoglRendererEGL *egl_renderer = renderer->winsys; + EGLint attributes[MAX_EGL_CONFIG_ATTRIBS]; + EGLConfig egl_config; + EGLint config_count = 0; + EGLBoolean status; + + _COGL_RETURN_VAL_IF_FAIL (egl_display->egl_context, FALSE); + + egl_attributes_from_framebuffer_config (display, + &framebuffer->config, + attributes); + + status = eglChooseConfig (egl_renderer->edpy, + attributes, + &egl_config, 1, + &config_count); + if (status != EGL_TRUE || config_count == 0) + { + _cogl_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_CREATE_ONSCREEN, + "Failed to find a suitable EGL configuration"); + return FALSE; + } + + /* Update the real number of samples_per_pixel now that we have + * found an egl_config... */ + if (framebuffer->config.samples_per_pixel) + { + EGLint samples; + status = eglGetConfigAttrib (egl_renderer->edpy, + egl_config, + EGL_SAMPLES, &samples); + g_return_val_if_fail (status == EGL_TRUE, TRUE); + framebuffer->samples_per_pixel = samples; + } + + onscreen->winsys = g_slice_new0 (CoglOnscreenEGL); + + if (egl_renderer->platform_vtable->onscreen_init && + !egl_renderer->platform_vtable->onscreen_init (onscreen, + egl_config, + error)) + { + g_slice_free (CoglOnscreenEGL, onscreen->winsys); + return FALSE; + } + + return TRUE; +} + +static void +_cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + CoglContext *context = framebuffer->context; + CoglDisplayEGL *egl_display = context->display->winsys; + CoglRenderer *renderer = context->display->renderer; + CoglRendererEGL *egl_renderer = renderer->winsys; + CoglOnscreenEGL *egl_onscreen = onscreen->winsys; + + /* If we never successfully allocated then there's nothing to do */ + if (egl_onscreen == NULL) + return; + + if (egl_onscreen->egl_surface != EGL_NO_SURFACE) + { + /* Cogl always needs a valid context bound to something so if we + * are destroying the onscreen that is currently bound we'll + * switch back to the dummy drawable. */ + if ((egl_display->dummy_surface != EGL_NO_SURFACE || + (egl_renderer->private_features & + COGL_EGL_WINSYS_FEATURE_SURFACELESS_CONTEXT) != 0) && + (egl_display->current_draw_surface == egl_onscreen->egl_surface || + egl_display->current_read_surface == egl_onscreen->egl_surface)) + { + _cogl_winsys_egl_make_current (context->display, + egl_display->dummy_surface, + egl_display->dummy_surface, + egl_display->current_context); + } + + if (eglDestroySurface (egl_renderer->edpy, egl_onscreen->egl_surface) + == EGL_FALSE) + g_warning ("Failed to destroy EGL surface"); + egl_onscreen->egl_surface = EGL_NO_SURFACE; + } + + if (egl_renderer->platform_vtable->onscreen_deinit) + egl_renderer->platform_vtable->onscreen_deinit (onscreen); + + g_slice_free (CoglOnscreenEGL, onscreen->winsys); + onscreen->winsys = NULL; +} + +static CoglBool +bind_onscreen_with_context (CoglOnscreen *onscreen, + EGLContext egl_context) +{ + CoglFramebuffer *fb = COGL_FRAMEBUFFER (onscreen); + CoglContext *context = fb->context; + CoglOnscreenEGL *egl_onscreen = onscreen->winsys; + + CoglBool status = _cogl_winsys_egl_make_current (context->display, + egl_onscreen->egl_surface, + egl_onscreen->egl_surface, + egl_context); + if (status) + { + CoglRenderer *renderer = context->display->renderer; + CoglRendererEGL *egl_renderer = renderer->winsys; + + if (fb->config.swap_throttled) + eglSwapInterval (egl_renderer->edpy, 1); + else + eglSwapInterval (egl_renderer->edpy, 0); + } + + return status; +} + +static CoglBool +bind_onscreen (CoglOnscreen *onscreen) +{ + CoglFramebuffer *fb = COGL_FRAMEBUFFER (onscreen); + CoglContext *context = fb->context; + CoglDisplayEGL *egl_display = context->display->winsys; + + return bind_onscreen_with_context (onscreen, egl_display->egl_context); +} + +static void +_cogl_winsys_onscreen_bind (CoglOnscreen *onscreen) +{ + bind_onscreen (onscreen); +} + +#ifndef EGL_BUFFER_AGE_EXT +#define EGL_BUFFER_AGE_EXT 0x313D +#endif + +static int +_cogl_winsys_onscreen_get_buffer_age (CoglOnscreen *onscreen) +{ + CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context; + CoglRenderer *renderer = context->display->renderer; + CoglRendererEGL *egl_renderer = renderer->winsys; + CoglOnscreenEGL *egl_onscreen = onscreen->winsys; + EGLSurface surface = egl_onscreen->egl_surface; + int age; + + if (!(egl_renderer->private_features & COGL_EGL_WINSYS_FEATURE_BUFFER_AGE)) + return 0; + + eglQuerySurface (egl_renderer->edpy, surface, EGL_BUFFER_AGE_EXT, &age); + + return age; +} + +static void +_cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen, + const int *user_rectangles, + int n_rectangles) +{ + CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context; + CoglRenderer *renderer = context->display->renderer; + CoglRendererEGL *egl_renderer = renderer->winsys; + CoglOnscreenEGL *egl_onscreen = onscreen->winsys; + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + int framebuffer_height = cogl_framebuffer_get_height (framebuffer); + int *rectangles = g_alloca (sizeof (int) * n_rectangles * 4); + int i; + + /* eglSwapBuffersRegion expects rectangles relative to the + * bottom left corner but we are given rectangles relative to + * the top left so we need to flip them... */ + memcpy (rectangles, user_rectangles, sizeof (int) * n_rectangles * 4); + for (i = 0; i < n_rectangles; i++) + { + int *rect = &rectangles[4 * i]; + rect[1] = framebuffer_height - rect[1] - rect[3]; + } + + /* At least for eglSwapBuffers the EGL spec says that the surface to + swap must be bound to the current context. It looks like Mesa + also validates that this is the case for eglSwapBuffersRegion so + we must bind here too */ + _cogl_framebuffer_flush_state (COGL_FRAMEBUFFER (onscreen), + COGL_FRAMEBUFFER (onscreen), + COGL_FRAMEBUFFER_STATE_BIND); + + if (egl_renderer->pf_eglSwapBuffersRegion (egl_renderer->edpy, + egl_onscreen->egl_surface, + n_rectangles, + rectangles) == EGL_FALSE) + g_warning ("Error reported by eglSwapBuffersRegion"); +} + +static void +_cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen, + const int *rectangles, + int n_rectangles) +{ + CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context; + CoglRenderer *renderer = context->display->renderer; + CoglRendererEGL *egl_renderer = renderer->winsys; + CoglOnscreenEGL *egl_onscreen = onscreen->winsys; + + /* The specification for EGL (at least in 1.4) says that the surface + needs to be bound to the current context for the swap to work + although it may change in future. Mesa explicitly checks for this + and just returns an error if this is not the case so we can't + just pretend this isn't in the spec. */ + _cogl_framebuffer_flush_state (COGL_FRAMEBUFFER (onscreen), + COGL_FRAMEBUFFER (onscreen), + COGL_FRAMEBUFFER_STATE_BIND); + + if (n_rectangles && egl_renderer->pf_eglSwapBuffersWithDamage) + { + CoglFramebuffer *fb = COGL_FRAMEBUFFER (onscreen); + size_t size = n_rectangles * sizeof (int) * 4; + int *flipped = alloca (size); + int i; + + memcpy (flipped, rectangles, size); + for (i = 0; i < n_rectangles; i++) + { + const int *rect = rectangles + 4 * i; + int *flip_rect = flipped + 4 * i; + flip_rect[1] = fb->height - rect[1] - rect[3]; + } + + if (egl_renderer->pf_eglSwapBuffersWithDamage (egl_renderer->edpy, + egl_onscreen->egl_surface, + flipped, + n_rectangles) == EGL_FALSE) + g_warning ("Error reported by eglSwapBuffersWithDamage"); + } + else + eglSwapBuffers (egl_renderer->edpy, egl_onscreen->egl_surface); +} + +static void +_cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen) +{ + CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context; + CoglDisplayEGL *egl_display = context->display->winsys; + CoglOnscreenEGL *egl_onscreen = onscreen->winsys; + + if (egl_display->current_draw_surface != egl_onscreen->egl_surface) + return; + + egl_display->current_draw_surface = EGL_NO_SURFACE; + + _cogl_winsys_onscreen_bind (onscreen); +} + +static void +_cogl_winsys_save_context (CoglContext *ctx) +{ + CoglContextEGL *egl_context = ctx->winsys; + CoglDisplayEGL *egl_display = ctx->display->winsys; + + egl_context->saved_draw_surface = egl_display->current_draw_surface; + egl_context->saved_read_surface = egl_display->current_read_surface; +} + +static CoglBool +_cogl_winsys_set_gles2_context (CoglGLES2Context *gles2_ctx, CoglError **error) +{ + CoglContext *ctx = gles2_ctx->context; + CoglDisplayEGL *egl_display = ctx->display->winsys; + CoglBool status; + + if (gles2_ctx->write_buffer && + cogl_is_onscreen (gles2_ctx->write_buffer)) + status = + bind_onscreen_with_context (COGL_ONSCREEN (gles2_ctx->write_buffer), + gles2_ctx->winsys); + else + status = _cogl_winsys_egl_make_current (ctx->display, + egl_display->dummy_surface, + egl_display->dummy_surface, + gles2_ctx->winsys); + + if (!status) + { + _cogl_set_error (error, + COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_MAKE_CURRENT, + "Failed to make gles2 context current"); + return FALSE; + } + + return TRUE; +} + +static void +_cogl_winsys_restore_context (CoglContext *ctx) +{ + CoglContextEGL *egl_context = ctx->winsys; + CoglDisplayEGL *egl_display = ctx->display->winsys; + + _cogl_winsys_egl_make_current (ctx->display, + egl_context->saved_draw_surface, + egl_context->saved_read_surface, + egl_display->egl_context); +} + +#if defined(EGL_KHR_fence_sync) || defined(EGL_KHR_reusable_sync) +static void * +_cogl_winsys_fence_add (CoglContext *context) +{ + CoglRendererEGL *renderer = context->display->renderer->winsys; + void *ret; + + if (renderer->pf_eglCreateSync) + ret = renderer->pf_eglCreateSync (renderer->edpy, + EGL_SYNC_FENCE_KHR, + NULL); + else + ret = NULL; + + return ret; +} + +static CoglBool +_cogl_winsys_fence_is_complete (CoglContext *context, void *fence) +{ + CoglRendererEGL *renderer = context->display->renderer->winsys; + EGLint ret; + + ret = renderer->pf_eglClientWaitSync (renderer->edpy, + fence, + EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, + 0); + return (ret == EGL_CONDITION_SATISFIED_KHR); +} + +static void +_cogl_winsys_fence_destroy (CoglContext *context, void *fence) +{ + CoglRendererEGL *renderer = context->display->renderer->winsys; + + renderer->pf_eglDestroySync (renderer->edpy, fence); +} +#endif + +static CoglWinsysVtable _cogl_winsys_vtable = + { + .constraints = COGL_RENDERER_CONSTRAINT_USES_EGL | + COGL_RENDERER_CONSTRAINT_SUPPORTS_COGL_GLES2, + + /* This winsys is only used as a base for the EGL-platform + winsys's so it does not have an ID or a name */ + + .renderer_get_proc_address = _cogl_winsys_renderer_get_proc_address, + .renderer_connect = _cogl_winsys_renderer_connect, + .renderer_disconnect = _cogl_winsys_renderer_disconnect, + .display_setup = _cogl_winsys_display_setup, + .display_destroy = _cogl_winsys_display_destroy, + .context_init = _cogl_winsys_context_init, + .context_deinit = _cogl_winsys_context_deinit, + .context_create_gles2_context = + _cogl_winsys_context_create_gles2_context, + .destroy_gles2_context = _cogl_winsys_destroy_gles2_context, + .onscreen_init = _cogl_winsys_onscreen_init, + .onscreen_deinit = _cogl_winsys_onscreen_deinit, + .onscreen_bind = _cogl_winsys_onscreen_bind, + .onscreen_swap_buffers_with_damage = + _cogl_winsys_onscreen_swap_buffers_with_damage, + .onscreen_swap_region = _cogl_winsys_onscreen_swap_region, + .onscreen_get_buffer_age = _cogl_winsys_onscreen_get_buffer_age, + .onscreen_update_swap_throttled = + _cogl_winsys_onscreen_update_swap_throttled, + + /* CoglGLES2Context related methods */ + .save_context = _cogl_winsys_save_context, + .set_gles2_context = _cogl_winsys_set_gles2_context, + .restore_context = _cogl_winsys_restore_context, + +#if defined(EGL_KHR_fence_sync) || defined(EGL_KHR_reusable_sync) + .fence_add = _cogl_winsys_fence_add, + .fence_is_complete = _cogl_winsys_fence_is_complete, + .fence_destroy = _cogl_winsys_fence_destroy, +#endif + }; + +/* XXX: we use a function because no doubt someone will complain + * about using c99 member initializers because they aren't portable + * to windows. We want to avoid having to rigidly follow the real + * order of members since some members are #ifdefd and we'd have + * to mirror the #ifdefing to add padding etc. For any winsys that + * can assume the platform has a sane compiler then we can just use + * c99 initializers for insane platforms they can initialize + * the members by name in a function. + */ +const CoglWinsysVtable * +_cogl_winsys_egl_get_vtable (void) +{ + return &_cogl_winsys_vtable; +} + +#ifdef EGL_KHR_image_base +EGLImageKHR +_cogl_egl_create_image (CoglContext *ctx, + EGLenum target, + EGLClientBuffer buffer, + const EGLint *attribs) +{ + CoglDisplayEGL *egl_display = ctx->display->winsys; + CoglRendererEGL *egl_renderer = ctx->display->renderer->winsys; + EGLContext egl_ctx; + + _COGL_RETURN_VAL_IF_FAIL (egl_renderer->pf_eglCreateImage, EGL_NO_IMAGE_KHR); + + /* The EGL_KHR_image_pixmap spec explicitly states that EGL_NO_CONTEXT must + * always be used in conjunction with the EGL_NATIVE_PIXMAP_KHR target */ +#ifdef EGL_KHR_image_pixmap + if (target == EGL_NATIVE_PIXMAP_KHR) + egl_ctx = EGL_NO_CONTEXT; + else +#endif +#ifdef COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT + /* The WL_bind_wayland_display spec states that EGL_NO_CONTEXT is to be used + * in conjunction with the EGL_WAYLAND_BUFFER_WL target */ + if (target == EGL_WAYLAND_BUFFER_WL) + egl_ctx = EGL_NO_CONTEXT; + else +#endif + egl_ctx = egl_display->egl_context; + + return egl_renderer->pf_eglCreateImage (egl_renderer->edpy, + egl_ctx, + target, + buffer, + attribs); +} + +void +_cogl_egl_destroy_image (CoglContext *ctx, + EGLImageKHR image) +{ + CoglRendererEGL *egl_renderer = ctx->display->renderer->winsys; + + _COGL_RETURN_IF_FAIL (egl_renderer->pf_eglDestroyImage); + + egl_renderer->pf_eglDestroyImage (egl_renderer->edpy, image); +} +#endif + +#ifdef EGL_WL_bind_wayland_display +CoglBool +_cogl_egl_query_wayland_buffer (CoglContext *ctx, + struct wl_resource *buffer, + int attribute, + int *value) +{ + CoglRendererEGL *egl_renderer = ctx->display->renderer->winsys; + + _COGL_RETURN_VAL_IF_FAIL (egl_renderer->pf_eglQueryWaylandBuffer, FALSE); + + return egl_renderer->pf_eglQueryWaylandBuffer (egl_renderer->edpy, + buffer, + attribute, + value); +} +#endif + +EGLDisplay +cogl_egl_context_get_egl_display (CoglContext *context) +{ + CoglRendererEGL *egl_renderer = context->display->renderer->winsys; + + return egl_renderer->edpy; +} + +EGLContext +cogl_egl_context_get_egl_context (CoglContext *context) +{ + CoglDisplayEGL *egl_display = context->display->winsys; + + return egl_display->egl_context; +} diff --git a/cogl/cogl/winsys/cogl-winsys-glx-feature-functions.h b/cogl/cogl/winsys/cogl-winsys-glx-feature-functions.h new file mode 100644 index 0000000..ed9df70 --- /dev/null +++ b/cogl/cogl/winsys/cogl-winsys-glx-feature-functions.h @@ -0,0 +1,210 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +/* This can be included multiple times with different definitions for + * the COGL_WINSYS_FEATURE_* functions. + */ + +/* Macro prototypes: + * COGL_WINSYS_FEATURE_BEGIN (major_glx_version, minor_glx_version, + * name, namespaces, extension_names, + * implied_legacy_feature_flags, + * implied_winsys_feature) + * COGL_WINSYS_FEATURE_FUNCTION (return_type, function_name, + * (arguments)) + * ... + * COGL_WINSYS_FEATURE_END () + * + * Note: You can list multiple namespace and extension names if the + * corresponding _FEATURE_FUNCTIONS have the same semantics accross + * the different extension variants. + * + * XXX: NB: Don't add a trailing semicolon when using these macros + */ + +/* Base functions that we assume are always available */ +COGL_WINSYS_FEATURE_BEGIN (0, 0, /* always available */ + base_glx_functions, + "\0", + "\0", + 0, /* no implied public feature */ + 0 /* no winsys feature */) +COGL_WINSYS_FEATURE_FUNCTION (void, glXDestroyContext, + (Display *dpy, GLXContext ctx)) +COGL_WINSYS_FEATURE_FUNCTION (void, glXSwapBuffers, + (Display *dpy, GLXDrawable drawable)) +COGL_WINSYS_FEATURE_FUNCTION (Bool, glXIsDirect, + (Display *dpy, GLXContext ctx)) +COGL_WINSYS_FEATURE_FUNCTION (int, glXGetFBConfigAttrib, + (Display *dpy, GLXFBConfig config, + int attribute, int *value)) +COGL_WINSYS_FEATURE_FUNCTION (GLXWindow, glXCreateWindow, + (Display *dpy, GLXFBConfig config, + Window win, const int *attribList)) +COGL_WINSYS_FEATURE_FUNCTION (void, glXDestroyWindow, + (Display *dpy, GLXWindow window)) +COGL_WINSYS_FEATURE_FUNCTION (GLXPixmap, glXCreatePixmap, + (Display *dpy, GLXFBConfig config, + Pixmap pixmap, const int *attribList)) +COGL_WINSYS_FEATURE_FUNCTION (void, glXDestroyPixmap, + (Display *dpy, GLXPixmap pixmap)) +COGL_WINSYS_FEATURE_FUNCTION (GLXContext, glXCreateNewContext, + (Display *dpy, GLXFBConfig config, + int renderType, GLXContext shareList, + Bool direct)) +COGL_WINSYS_FEATURE_FUNCTION (Bool, glXMakeContextCurrent, + (Display *dpy, GLXDrawable draw, + GLXDrawable read, GLXContext ctx)) +COGL_WINSYS_FEATURE_FUNCTION (void, glXSelectEvent, + (Display *dpy, GLXDrawable drawable, + unsigned long mask)) +COGL_WINSYS_FEATURE_FUNCTION (GLXFBConfig *, glXGetFBConfigs, + (Display *dpy, int screen, int *nelements)) +COGL_WINSYS_FEATURE_FUNCTION (GLXFBConfig *, glXChooseFBConfig, + (Display *dpy, int screen, + const int *attrib_list, int *nelements)) +COGL_WINSYS_FEATURE_FUNCTION (XVisualInfo *, glXGetVisualFromFBConfig, + (Display *dpy, GLXFBConfig config)) +COGL_WINSYS_FEATURE_END () + +COGL_WINSYS_FEATURE_BEGIN (255, 255, + texture_from_pixmap, + "EXT\0", + "texture_from_pixmap\0", + 0, + COGL_WINSYS_FEATURE_TEXTURE_FROM_PIXMAP) +COGL_WINSYS_FEATURE_FUNCTION (void, glXBindTexImage, + (Display *display, + GLXDrawable drawable, + int buffer, + int *attribList)) +COGL_WINSYS_FEATURE_FUNCTION (void, glXReleaseTexImage, + (Display *display, + GLXDrawable drawable, + int buffer)) +COGL_WINSYS_FEATURE_END () + +COGL_WINSYS_FEATURE_BEGIN (255, 255, + video_sync, + "SGI\0", + "video_sync\0", + 0, + COGL_WINSYS_FEATURE_VBLANK_COUNTER) +COGL_WINSYS_FEATURE_FUNCTION (int, glXGetVideoSync, + (unsigned int *count)) +COGL_WINSYS_FEATURE_FUNCTION (int, glXWaitVideoSync, + (int divisor, + int remainder, + unsigned int *count)) +COGL_WINSYS_FEATURE_END () + +COGL_WINSYS_FEATURE_BEGIN (255, 255, + swap_control, + "SGI\0", + "swap_control\0", + 0, + COGL_WINSYS_FEATURE_SWAP_THROTTLE) +COGL_WINSYS_FEATURE_FUNCTION (int, glXSwapInterval, + (int interval)) +COGL_WINSYS_FEATURE_END () + +COGL_WINSYS_FEATURE_BEGIN (255, 255, + sync_control, + "OML\0", + "sync_control\0", + 0, + 0) +COGL_WINSYS_FEATURE_FUNCTION (Bool, glXGetSyncValues, + (Display* dpy, + GLXDrawable drawable, + int64_t* ust, + int64_t* msc, + int64_t* sbc)) +COGL_WINSYS_FEATURE_FUNCTION (Bool, glXWaitForMsc, + (Display* dpy, + GLXDrawable drawable, + int64_t target_msc, + int64_t divisor, + int64_t remainder, + int64_t* ust, + int64_t* msc, + int64_t* sbc)) +COGL_WINSYS_FEATURE_END () + +COGL_WINSYS_FEATURE_BEGIN (255, 255, + copy_sub_buffer, + "MESA\0", + "copy_sub_buffer\0", + 0, +/* We initially assumed that copy_sub_buffer is synchronized on + * which is only the case for a subset of GPUs for example it is not + * synchronized on INTEL gen6 and gen7, so we remove this assumption + * for now + */ +#if 0 + COGL_WINSYS_FEATURE_SWAP_REGION_SYNCHRONIZED) +#endif + 0) +COGL_WINSYS_FEATURE_FUNCTION (void, glXCopySubBuffer, + (Display *dpy, + GLXDrawable drawable, + int x, int y, int width, int height)) +COGL_WINSYS_FEATURE_END () + +COGL_WINSYS_FEATURE_BEGIN (255, 255, + swap_event, + "INTEL\0", + "swap_event\0", + 0, + COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT) + +COGL_WINSYS_FEATURE_END () + +COGL_WINSYS_FEATURE_BEGIN (255, 255, + create_context, + "ARB\0", + "create_context", + 0, + 0) +COGL_WINSYS_FEATURE_FUNCTION (GLXContext, glXCreateContextAttribs, + (Display *dpy, + GLXFBConfig config, + GLXContext share_context, + Bool direct, + const int *attrib_list)) +COGL_WINSYS_FEATURE_END () + +COGL_WINSYS_FEATURE_BEGIN (255, 255, + buffer_age, + "EXT\0", + "buffer_age\0", + 0, + COGL_WINSYS_FEATURE_BUFFER_AGE) +COGL_WINSYS_FEATURE_END () diff --git a/cogl/cogl/winsys/cogl-winsys-glx-private.h b/cogl/cogl/winsys/cogl-winsys-glx-private.h new file mode 100644 index 0000000..9fb386f --- /dev/null +++ b/cogl/cogl/winsys/cogl-winsys-glx-private.h @@ -0,0 +1,37 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2012 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_WINSYS_GLX_PRIVATE_H +#define __COGL_WINSYS_GLX_PRIVATE_H + +const CoglWinsysVtable * +_cogl_winsys_glx_get_vtable (void); + +#endif /* __COGL_WINSYS_GLX_PRIVATE_H */ diff --git a/cogl/cogl/winsys/cogl-winsys-glx.c b/cogl/cogl/winsys/cogl-winsys-glx.c new file mode 100644 index 0000000..c50db3a --- /dev/null +++ b/cogl/cogl/winsys/cogl-winsys-glx.c @@ -0,0 +1,2791 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2010,2011,2013 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-i18n-private.h" +#include "cogl-util.h" +#include "cogl-winsys-private.h" +#include "cogl-feature-private.h" +#include "cogl-context-private.h" +#include "cogl-framebuffer.h" +#include "cogl-swap-chain-private.h" +#include "cogl-renderer-private.h" +#include "cogl-glx-renderer-private.h" +#include "cogl-onscreen-template-private.h" +#include "cogl-glx-display-private.h" +#include "cogl-private.h" +#include "cogl-texture-2d-private.h" +#include "cogl-texture-rectangle-private.h" +#include "cogl-pipeline-opengl-private.h" +#include "cogl-frame-info-private.h" +#include "cogl-framebuffer-private.h" +#include "cogl-onscreen-private.h" +#include "cogl-swap-chain-private.h" +#include "cogl-xlib-renderer.h" +#include "cogl-util.h" +#include "cogl-winsys-glx-private.h" +#include "cogl-error-private.h" +#include "cogl-poll-private.h" +#include "cogl-version.h" +#include "cogl-glx.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +/* This is a relatively new extension */ +#ifndef GLX_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV +#define GLX_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV 0x20F7 +#endif + +#define COGL_ONSCREEN_X11_EVENT_MASK (StructureNotifyMask | ExposureMask) +#define MAX_GLX_CONFIG_ATTRIBS 30 + +typedef struct _CoglContextGLX +{ + GLXDrawable current_drawable; +} CoglContextGLX; + +typedef struct _CoglOnscreenXlib +{ + Window xwin; + int x, y; + CoglBool is_foreign_xwin; + CoglOutput *output; +} CoglOnscreenXlib; + +typedef struct _CoglOnscreenGLX +{ + CoglOnscreenXlib _parent; + GLXDrawable glxwin; + uint32_t last_swap_vsync_counter; + CoglBool pending_sync_notify; + CoglBool pending_complete_notify; + CoglBool pending_resize_notify; +} CoglOnscreenGLX; + +typedef struct _CoglPixmapTextureEyeGLX +{ + CoglTexture *glx_tex; + CoglBool bind_tex_image_queued; + CoglBool pixmap_bound; +} CoglPixmapTextureEyeGLX; + +typedef struct _CoglTexturePixmapGLX +{ + GLXPixmap glx_pixmap; + CoglBool has_mipmap_space; + CoglBool can_mipmap; + + CoglPixmapTextureEyeGLX left; + CoglPixmapTextureEyeGLX right; +} CoglTexturePixmapGLX; + +/* Define a set of arrays containing the functions required from GL + for each winsys feature */ +#define COGL_WINSYS_FEATURE_BEGIN(major_version, minor_version, \ + name, namespaces, extension_names, \ + feature_flags, \ + winsys_feature) \ + static const CoglFeatureFunction \ + cogl_glx_feature_ ## name ## _funcs[] = { +#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args) \ + { G_STRINGIFY (name), G_STRUCT_OFFSET (CoglGLXRenderer, name) }, +#define COGL_WINSYS_FEATURE_END() \ + { NULL, 0 }, \ + }; +#include "cogl-winsys-glx-feature-functions.h" + +/* Define an array of features */ +#undef COGL_WINSYS_FEATURE_BEGIN +#define COGL_WINSYS_FEATURE_BEGIN(major_version, minor_version, \ + name, namespaces, extension_names, \ + feature_flags, \ + winsys_feature) \ + { major_version, minor_version, \ + 0, namespaces, extension_names, \ + feature_flags, \ + 0, \ + winsys_feature, \ + cogl_glx_feature_ ## name ## _funcs }, +#undef COGL_WINSYS_FEATURE_FUNCTION +#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args) +#undef COGL_WINSYS_FEATURE_END +#define COGL_WINSYS_FEATURE_END() + +static const CoglFeatureData winsys_feature_data[] = + { +#include "cogl-winsys-glx-feature-functions.h" + }; + +static CoglFuncPtr +_cogl_winsys_renderer_get_proc_address (CoglRenderer *renderer, + const char *name, + CoglBool in_core) +{ + CoglGLXRenderer *glx_renderer = renderer->winsys; + + /* The GLX_ARB_get_proc_address extension documents that this should + * work for core functions too so we don't need to do anything + * special with in_core */ + + return glx_renderer->glXGetProcAddress ((const GLubyte *) name); +} + +static CoglOnscreen * +find_onscreen_for_xid (CoglContext *context, uint32_t xid) +{ + GList *l; + + for (l = context->framebuffers; l; l = l->next) + { + CoglFramebuffer *framebuffer = l->data; + CoglOnscreenXlib *xlib_onscreen; + + if (framebuffer->type != COGL_FRAMEBUFFER_TYPE_ONSCREEN) + continue; + + /* Does the GLXEvent have the GLXDrawable or the X Window? */ + xlib_onscreen = COGL_ONSCREEN (framebuffer)->winsys; + if (xlib_onscreen != NULL && xlib_onscreen->xwin == (Window)xid) + return COGL_ONSCREEN (framebuffer); + } + + return NULL; +} + +static void +ensure_ust_type (CoglRenderer *renderer, + GLXDrawable drawable) +{ + CoglGLXRenderer *glx_renderer = renderer->winsys; + CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (renderer); + int64_t ust; + int64_t msc; + int64_t sbc; + struct timeval tv; + struct timespec ts; + int64_t current_system_time; + int64_t current_monotonic_time; + + if (glx_renderer->ust_type != COGL_GLX_UST_IS_UNKNOWN) + return; + + glx_renderer->ust_type = COGL_GLX_UST_IS_OTHER; + + if (glx_renderer->glXGetSyncValues == NULL) + goto out; + + if (!glx_renderer->glXGetSyncValues (xlib_renderer->xdpy, drawable, + &ust, &msc, &sbc)) + goto out; + + /* This is the time source that existing (buggy) linux drm drivers + * use */ + gettimeofday (&tv, NULL); + current_system_time = (tv.tv_sec * G_GINT64_CONSTANT (1000000)) + tv.tv_usec; + + if (current_system_time > ust - 1000000 && + current_system_time < ust + 1000000) + { + glx_renderer->ust_type = COGL_GLX_UST_IS_GETTIMEOFDAY; + goto out; + } + + /* This is the time source that the newer (fixed) linux drm + * drivers use (Linux >= 3.8) */ + clock_gettime (CLOCK_MONOTONIC, &ts); + current_monotonic_time = (ts.tv_sec * G_GINT64_CONSTANT (1000000)) + + (ts.tv_nsec / G_GINT64_CONSTANT (1000)); + + if (current_monotonic_time > ust - 1000000 && + current_monotonic_time < ust + 1000000) + { + glx_renderer->ust_type = COGL_GLX_UST_IS_MONOTONIC_TIME; + goto out; + } + + out: + COGL_NOTE (WINSYS, "Classified OML system time as: %s", + glx_renderer->ust_type == COGL_GLX_UST_IS_GETTIMEOFDAY ? "gettimeofday" : + (glx_renderer->ust_type == COGL_GLX_UST_IS_MONOTONIC_TIME ? "monotonic" : + "other")); + return; +} + +static int64_t +ust_to_nanoseconds (CoglRenderer *renderer, + GLXDrawable drawable, + int64_t ust) +{ + CoglGLXRenderer *glx_renderer = renderer->winsys; + + ensure_ust_type (renderer, drawable); + + switch (glx_renderer->ust_type) + { + case COGL_GLX_UST_IS_UNKNOWN: + g_assert_not_reached (); + break; + case COGL_GLX_UST_IS_GETTIMEOFDAY: + case COGL_GLX_UST_IS_MONOTONIC_TIME: + return 1000 * ust; + case COGL_GLX_UST_IS_OTHER: + /* In this case the scale of UST is undefined so we can't easily + * scale to nanoseconds. + * + * For example the driver may be reporting the rdtsc CPU counter + * as UST values and so the scale would need to be determined + * empirically. + * + * Potentially we could block for a known duration within + * ensure_ust_type() to measure the timescale of UST but for now + * we just ignore unknown time sources */ + return 0; + } + + return 0; +} + +static int64_t +_cogl_winsys_get_clock_time (CoglContext *context) +{ + CoglGLXRenderer *glx_renderer = context->display->renderer->winsys; + + /* We don't call ensure_ust_type() because we don't have a drawable + * to work with. cogl_get_clock_time() is documented to only work + * once a valid, non-zero, timestamp has been retrieved from Cogl. + */ + + switch (glx_renderer->ust_type) + { + case COGL_GLX_UST_IS_UNKNOWN: + case COGL_GLX_UST_IS_OTHER: + return 0; + case COGL_GLX_UST_IS_GETTIMEOFDAY: + { + struct timeval tv; + + gettimeofday(&tv, NULL); + return tv.tv_sec * G_GINT64_CONSTANT (1000000000) + + tv.tv_usec * G_GINT64_CONSTANT (1000); + } + case COGL_GLX_UST_IS_MONOTONIC_TIME: + { + struct timespec ts; + + clock_gettime (CLOCK_MONOTONIC, &ts); + return ts.tv_sec * G_GINT64_CONSTANT (1000000000) + ts.tv_nsec; + } + } + + g_assert_not_reached(); + return 0; +} + +static void +flush_pending_notifications_cb (void *data, + void *user_data) +{ + CoglFramebuffer *framebuffer = data; + + if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN) + { + CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); + CoglOnscreenGLX *glx_onscreen = onscreen->winsys; + CoglBool pending_sync_notify = glx_onscreen->pending_sync_notify; + CoglBool pending_complete_notify = glx_onscreen->pending_complete_notify; + + /* If swap_region is called then notifying the sync event could + * potentially immediately queue a subsequent pending notify so + * we need to clear the flag before invoking the callback */ + glx_onscreen->pending_sync_notify = FALSE; + glx_onscreen->pending_complete_notify = FALSE; + + if (pending_sync_notify) + { + CoglFrameInfo *info = g_queue_peek_head (&onscreen->pending_frame_infos); + + _cogl_onscreen_notify_frame_sync (onscreen, info); + } + + if (pending_complete_notify) + { + CoglFrameInfo *info = g_queue_pop_head (&onscreen->pending_frame_infos); + + _cogl_onscreen_notify_complete (onscreen, info); + + cogl_object_unref (info); + } + + if (glx_onscreen->pending_resize_notify) + { + _cogl_onscreen_notify_resize (onscreen); + glx_onscreen->pending_resize_notify = FALSE; + } + } +} + +static void +flush_pending_notifications_idle (void *user_data) +{ + CoglContext *context = user_data; + CoglRenderer *renderer = context->display->renderer; + CoglGLXRenderer *glx_renderer = renderer->winsys; + + /* This needs to be disconnected before invoking the callbacks in + * case the callbacks cause it to be queued again */ + _cogl_closure_disconnect (glx_renderer->flush_notifications_idle); + glx_renderer->flush_notifications_idle = NULL; + + g_list_foreach (context->framebuffers, + flush_pending_notifications_cb, + NULL); +} + +static void +set_sync_pending (CoglOnscreen *onscreen) +{ + CoglOnscreenGLX *glx_onscreen = onscreen->winsys; + CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context; + CoglRenderer *renderer = context->display->renderer; + CoglGLXRenderer *glx_renderer = renderer->winsys; + + /* We only want to dispatch sync events when the application calls + * cogl_context_dispatch so instead of immediately notifying we + * queue an idle callback */ + if (!glx_renderer->flush_notifications_idle) + { + glx_renderer->flush_notifications_idle = + _cogl_poll_renderer_add_idle (renderer, + flush_pending_notifications_idle, + context, + NULL); + } + + glx_onscreen->pending_sync_notify = TRUE; +} + +static void +set_complete_pending (CoglOnscreen *onscreen) +{ + CoglOnscreenGLX *glx_onscreen = onscreen->winsys; + CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context; + CoglRenderer *renderer = context->display->renderer; + CoglGLXRenderer *glx_renderer = renderer->winsys; + + /* We only want to notify swap completion when the application calls + * cogl_context_dispatch so instead of immediately notifying we + * queue an idle callback */ + if (!glx_renderer->flush_notifications_idle) + { + glx_renderer->flush_notifications_idle = + _cogl_poll_renderer_add_idle (renderer, + flush_pending_notifications_idle, + context, + NULL); + } + + glx_onscreen->pending_complete_notify = TRUE; +} + +static void +notify_swap_buffers (CoglContext *context, GLXBufferSwapComplete *swap_event) +{ + CoglOnscreen *onscreen = find_onscreen_for_xid (context, (uint32_t)swap_event->drawable); + CoglOnscreenGLX *glx_onscreen; + + if (!onscreen) + return; + glx_onscreen = onscreen->winsys; + + /* We only want to notify that the swap is complete when the + application calls cogl_context_dispatch so instead of immediately + notifying we'll set a flag to remember to notify later */ + set_sync_pending (onscreen); + + if (swap_event->ust != 0) + { + CoglFrameInfo *info = g_queue_peek_head (&onscreen->pending_frame_infos); + + info->presentation_time = + ust_to_nanoseconds (context->display->renderer, + glx_onscreen->glxwin, + swap_event->ust); + } + + set_complete_pending (onscreen); +} + +static void +update_output (CoglOnscreen *onscreen) +{ + CoglOnscreenXlib *xlib_onscreen = onscreen->winsys; + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + CoglContext *context = framebuffer->context; + CoglDisplay *display = context->display; + CoglOutput *output; + int width, height; + + width = cogl_framebuffer_get_width (framebuffer); + height = cogl_framebuffer_get_height (framebuffer); + output = _cogl_xlib_renderer_output_for_rectangle (display->renderer, + xlib_onscreen->x, + xlib_onscreen->y, + width, height); + if (xlib_onscreen->output != output) + { + if (xlib_onscreen->output) + cogl_object_unref (xlib_onscreen->output); + + xlib_onscreen->output = output; + + if (output) + cogl_object_ref (xlib_onscreen->output); + } +} + +static void +notify_resize (CoglContext *context, + XConfigureEvent *configure_event) +{ + CoglOnscreen *onscreen = find_onscreen_for_xid (context, + configure_event->window); + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + CoglRenderer *renderer = context->display->renderer; + CoglGLXRenderer *glx_renderer = renderer->winsys; + CoglOnscreenGLX *glx_onscreen; + CoglOnscreenXlib *xlib_onscreen; + + if (!onscreen) + return; + + glx_onscreen = onscreen->winsys; + xlib_onscreen = onscreen->winsys; + + _cogl_framebuffer_winsys_update_size (framebuffer, + configure_event->width, + configure_event->height); + + /* We only want to notify that a resize happened when the + * application calls cogl_context_dispatch so instead of immediately + * notifying we queue an idle callback */ + if (!glx_renderer->flush_notifications_idle) + { + glx_renderer->flush_notifications_idle = + _cogl_poll_renderer_add_idle (renderer, + flush_pending_notifications_idle, + context, + NULL); + } + + glx_onscreen->pending_resize_notify = TRUE; + + if (!xlib_onscreen->is_foreign_xwin) + { + int x, y; + + if (configure_event->send_event) + { + x = configure_event->x; + y = configure_event->y; + } + else + { + Window child; + XTranslateCoordinates (configure_event->display, + configure_event->window, + DefaultRootWindow (configure_event->display), + 0, 0, &x, &y, &child); + } + + xlib_onscreen->x = x; + xlib_onscreen->y = y; + + update_output (onscreen); + } +} + +static CoglFilterReturn +glx_event_filter_cb (XEvent *xevent, void *data) +{ + CoglContext *context = data; +#ifdef GLX_INTEL_swap_event + CoglGLXRenderer *glx_renderer; +#endif + + if (xevent->type == ConfigureNotify) + { + notify_resize (context, + &xevent->xconfigure); + + /* we let ConfigureNotify pass through */ + return COGL_FILTER_CONTINUE; + } + +#ifdef GLX_INTEL_swap_event + glx_renderer = context->display->renderer->winsys; + + if (xevent->type == (glx_renderer->glx_event_base + GLX_BufferSwapComplete)) + { + GLXBufferSwapComplete *swap_event = (GLXBufferSwapComplete *) xevent; + + notify_swap_buffers (context, swap_event); + + /* remove SwapComplete events from the queue */ + return COGL_FILTER_REMOVE; + } +#endif /* GLX_INTEL_swap_event */ + + if (xevent->type == Expose) + { + CoglOnscreen *onscreen = + find_onscreen_for_xid (context, xevent->xexpose.window); + + if (onscreen) + { + CoglOnscreenDirtyInfo info; + + info.x = xevent->xexpose.x; + info.y = xevent->xexpose.y; + info.width = xevent->xexpose.width; + info.height = xevent->xexpose.height; + + _cogl_onscreen_queue_dirty (onscreen, &info); + } + + return COGL_FILTER_CONTINUE; + } + + return COGL_FILTER_CONTINUE; +} + +static void +_cogl_winsys_renderer_disconnect (CoglRenderer *renderer) +{ + CoglGLXRenderer *glx_renderer = renderer->winsys; + + _cogl_xlib_renderer_disconnect (renderer); + + if (glx_renderer->libgl_module) + g_module_close (glx_renderer->libgl_module); + + g_slice_free (CoglGLXRenderer, renderer->winsys); +} + +static CoglBool +update_all_outputs (CoglRenderer *renderer) +{ + GList *l; + + _COGL_GET_CONTEXT (context, FALSE); + + if (context->display == NULL) /* during connection */ + return FALSE; + + if (context->display->renderer != renderer) + return FALSE; + + for (l = context->framebuffers; l; l = l->next) + { + CoglFramebuffer *framebuffer = l->data; + + if (framebuffer->type != COGL_FRAMEBUFFER_TYPE_ONSCREEN) + continue; + + update_output (COGL_ONSCREEN (framebuffer)); + } + + return TRUE; +} + +static void +_cogl_winsys_renderer_outputs_changed (CoglRenderer *renderer) +{ + update_all_outputs (renderer); +} + +static CoglBool +resolve_core_glx_functions (CoglRenderer *renderer, + CoglError **error) +{ + CoglGLXRenderer *glx_renderer; + + glx_renderer = renderer->winsys; + + if (!g_module_symbol (glx_renderer->libgl_module, "glXQueryExtension", + (void **) &glx_renderer->glXQueryExtension) || + !g_module_symbol (glx_renderer->libgl_module, "glXQueryVersion", + (void **) &glx_renderer->glXQueryVersion) || + !g_module_symbol (glx_renderer->libgl_module, "glXQueryExtensionsString", + (void **) &glx_renderer->glXQueryExtensionsString) || + (!g_module_symbol (glx_renderer->libgl_module, "glXGetProcAddress", + (void **) &glx_renderer->glXGetProcAddress) && + !g_module_symbol (glx_renderer->libgl_module, "glXGetProcAddressARB", + (void **) &glx_renderer->glXGetProcAddress)) || + !g_module_symbol (glx_renderer->libgl_module, "glXQueryDrawable", + (void **) &glx_renderer->glXQueryDrawable)) + { + _cogl_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_INIT, + "Failed to resolve required GLX symbol"); + return FALSE; + } + + return TRUE; +} + +static void +update_base_winsys_features (CoglRenderer *renderer) +{ + CoglGLXRenderer *glx_renderer = renderer->winsys; + CoglXlibRenderer *xlib_renderer = + _cogl_xlib_renderer_get_data (renderer); + const char *glx_extensions; + int default_screen; + char **split_extensions; + int i; + + default_screen = DefaultScreen (xlib_renderer->xdpy); + glx_extensions = + glx_renderer->glXQueryExtensionsString (xlib_renderer->xdpy, + default_screen); + + COGL_NOTE (WINSYS, " GLX Extensions: %s", glx_extensions); + + split_extensions = g_strsplit (glx_extensions, " ", 0 /* max_tokens */); + + for (i = 0; i < G_N_ELEMENTS (winsys_feature_data); i++) + if (_cogl_feature_check (renderer, + "GLX", winsys_feature_data + i, + glx_renderer->glx_major, + glx_renderer->glx_minor, + COGL_DRIVER_GL, /* the driver isn't used */ + split_extensions, + glx_renderer)) + { + glx_renderer->legacy_feature_flags |= + winsys_feature_data[i].feature_flags; + if (winsys_feature_data[i].winsys_feature) + COGL_FLAGS_SET (glx_renderer->base_winsys_features, + winsys_feature_data[i].winsys_feature, + TRUE); + } + + g_strfreev (split_extensions); + + /* Note: the GLX_SGI_video_sync spec explicitly states this extension + * only works for direct contexts. */ + if (!glx_renderer->is_direct) + { + glx_renderer->glXGetVideoSync = NULL; + glx_renderer->glXWaitVideoSync = NULL; + COGL_FLAGS_SET (glx_renderer->base_winsys_features, + COGL_WINSYS_FEATURE_VBLANK_COUNTER, + FALSE); + } + + COGL_FLAGS_SET (glx_renderer->base_winsys_features, + COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN, + TRUE); + + if (glx_renderer->glXWaitVideoSync || + glx_renderer->glXWaitForMsc) + COGL_FLAGS_SET (glx_renderer->base_winsys_features, + COGL_WINSYS_FEATURE_VBLANK_WAIT, + TRUE); +} + +static CoglBool +_cogl_winsys_renderer_connect (CoglRenderer *renderer, + CoglError **error) +{ + CoglGLXRenderer *glx_renderer; + CoglXlibRenderer *xlib_renderer; + + renderer->winsys = g_slice_new0 (CoglGLXRenderer); + + glx_renderer = renderer->winsys; + xlib_renderer = _cogl_xlib_renderer_get_data (renderer); + + if (!_cogl_xlib_renderer_connect (renderer, error)) + goto error; + + if (renderer->driver != COGL_DRIVER_GL && + renderer->driver != COGL_DRIVER_GL3) + { + _cogl_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_INIT, + "GLX Backend can only be used in conjunction with OpenGL"); + goto error; + } + + glx_renderer->libgl_module = g_module_open (COGL_GL_LIBNAME, + G_MODULE_BIND_LAZY); + + if (glx_renderer->libgl_module == NULL) + { + _cogl_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_INIT, + "Failed to dynamically open the OpenGL library"); + goto error; + } + + if (!resolve_core_glx_functions (renderer, error)) + goto error; + + if (!glx_renderer->glXQueryExtension (xlib_renderer->xdpy, + &glx_renderer->glx_error_base, + &glx_renderer->glx_event_base)) + { + _cogl_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_INIT, + "XServer appears to lack required GLX support"); + goto error; + } + + /* XXX: Note: For a long time Mesa exported a hybrid GLX, exporting + * extensions specified to require GLX 1.3, but still reporting 1.2 + * via glXQueryVersion. */ + if (!glx_renderer->glXQueryVersion (xlib_renderer->xdpy, + &glx_renderer->glx_major, + &glx_renderer->glx_minor) + || !(glx_renderer->glx_major == 1 && glx_renderer->glx_minor >= 2)) + { + _cogl_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_INIT, + "XServer appears to lack required GLX 1.2 support"); + goto error; + } + + update_base_winsys_features (renderer); + + glx_renderer->dri_fd = -1; + + return TRUE; + +error: + _cogl_winsys_renderer_disconnect (renderer); + return FALSE; +} + +static CoglBool +update_winsys_features (CoglContext *context, CoglError **error) +{ + CoglGLXDisplay *glx_display = context->display->winsys; + CoglGLXRenderer *glx_renderer = context->display->renderer->winsys; + + _COGL_RETURN_VAL_IF_FAIL (glx_display->glx_context, FALSE); + + if (!_cogl_context_update_features (context, error)) + return FALSE; + + memcpy (context->winsys_features, + glx_renderer->base_winsys_features, + sizeof (context->winsys_features)); + + context->feature_flags |= glx_renderer->legacy_feature_flags; + + context->feature_flags |= COGL_FEATURE_ONSCREEN_MULTIPLE; + COGL_FLAGS_SET (context->features, + COGL_FEATURE_ID_ONSCREEN_MULTIPLE, TRUE); + + if (glx_renderer->glXCopySubBuffer || context->glBlitFramebuffer) + { + CoglGpuInfo *info = &context->gpu; + CoglGpuInfoArchitecture arch = info->architecture; + + COGL_FLAGS_SET (context->winsys_features, COGL_WINSYS_FEATURE_SWAP_REGION, TRUE); + + /* + * "The "drisw" binding in Mesa for loading sofware renderers is + * broken, and neither glBlitFramebuffer nor glXCopySubBuffer + * work correctly." + * - ajax + * - https://bugzilla.gnome.org/show_bug.cgi?id=674208 + * + * This is broken in software Mesa at least as of 7.10 and got + * fixed in Mesa 10.1 + */ + + if (info->driver_package == COGL_GPU_INFO_DRIVER_PACKAGE_MESA && + info->driver_package_version < COGL_VERSION_ENCODE (10, 1, 0) && + (arch == COGL_GPU_INFO_ARCHITECTURE_LLVMPIPE || + arch == COGL_GPU_INFO_ARCHITECTURE_SOFTPIPE || + arch == COGL_GPU_INFO_ARCHITECTURE_SWRAST)) + { + COGL_FLAGS_SET (context->winsys_features, + COGL_WINSYS_FEATURE_SWAP_REGION, FALSE); + } + } + + /* Note: glXCopySubBuffer and glBlitFramebuffer won't be throttled + * by the SwapInterval so we have to throttle swap_region requests + * manually... */ + if (_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_REGION) && + _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_VBLANK_WAIT)) + COGL_FLAGS_SET (context->winsys_features, + COGL_WINSYS_FEATURE_SWAP_REGION_THROTTLE, TRUE); + + if (_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT)) + { + COGL_FLAGS_SET (context->winsys_features, + COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT, TRUE); + /* TODO: remove this deprecated feature */ + COGL_FLAGS_SET (context->features, + COGL_FEATURE_ID_SWAP_BUFFERS_EVENT, + TRUE); + COGL_FLAGS_SET (context->features, + COGL_FEATURE_ID_PRESENTATION_TIME, + TRUE); + } + + /* We'll manually handle queueing dirty events in response to + * Expose events from X */ + COGL_FLAGS_SET (context->private_features, + COGL_PRIVATE_FEATURE_DIRTY_EVENTS, + TRUE); + + if (_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_BUFFER_AGE)) + COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_BUFFER_AGE, TRUE); + + return TRUE; +} + +static void +glx_attributes_from_framebuffer_config (CoglDisplay *display, + CoglFramebufferConfig *config, + int *attributes) +{ + CoglGLXRenderer *glx_renderer = display->renderer->winsys; + int i = 0; + + attributes[i++] = GLX_DRAWABLE_TYPE; + attributes[i++] = GLX_WINDOW_BIT; + + attributes[i++] = GLX_RENDER_TYPE; + attributes[i++] = GLX_RGBA_BIT; + + attributes[i++] = GLX_DOUBLEBUFFER; + attributes[i++] = GL_TRUE; + + attributes[i++] = GLX_RED_SIZE; + attributes[i++] = 1; + attributes[i++] = GLX_GREEN_SIZE; + attributes[i++] = 1; + attributes[i++] = GLX_BLUE_SIZE; + attributes[i++] = 1; + attributes[i++] = GLX_ALPHA_SIZE; + attributes[i++] = config->swap_chain->has_alpha ? 1 : GLX_DONT_CARE; + attributes[i++] = GLX_DEPTH_SIZE; + attributes[i++] = 1; + attributes[i++] = GLX_STENCIL_SIZE; + attributes[i++] = config->need_stencil ? 1: GLX_DONT_CARE; + if (config->stereo_enabled) + { + attributes[i++] = GLX_STEREO; + attributes[i++] = TRUE; + } + + if (glx_renderer->glx_major == 1 && glx_renderer->glx_minor >= 4 && + config->samples_per_pixel) + { + attributes[i++] = GLX_SAMPLE_BUFFERS; + attributes[i++] = 1; + attributes[i++] = GLX_SAMPLES; + attributes[i++] = config->samples_per_pixel; + } + + attributes[i++] = None; + + g_assert (i < MAX_GLX_CONFIG_ATTRIBS); +} + +/* It seems the GLX spec never defined an invalid GLXFBConfig that + * we could overload as an indication of error, so we have to return + * an explicit boolean status. */ +static CoglBool +find_fbconfig (CoglDisplay *display, + CoglFramebufferConfig *config, + GLXFBConfig *config_ret, + CoglError **error) +{ + CoglXlibRenderer *xlib_renderer = + _cogl_xlib_renderer_get_data (display->renderer); + CoglGLXRenderer *glx_renderer = display->renderer->winsys; + GLXFBConfig *configs = NULL; + int n_configs; + static int attributes[MAX_GLX_CONFIG_ATTRIBS]; + CoglBool ret = TRUE; + int xscreen_num = DefaultScreen (xlib_renderer->xdpy); + + glx_attributes_from_framebuffer_config (display, config, attributes); + + configs = glx_renderer->glXChooseFBConfig (xlib_renderer->xdpy, + xscreen_num, + attributes, + &n_configs); + + if (!configs || n_configs == 0) + { + _cogl_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_CREATE_CONTEXT, + "Failed to find any compatible fbconfigs"); + ret = FALSE; + goto done; + } + + if (config->swap_chain->has_alpha) + { + int i; + + for (i = 0; i < n_configs; i++) + { + XVisualInfo *vinfo; + + vinfo = glx_renderer->glXGetVisualFromFBConfig (xlib_renderer->xdpy, + configs[i]); + if (vinfo == NULL) + continue; + + if (vinfo->depth == 32 && + (vinfo->red_mask | vinfo->green_mask | vinfo->blue_mask) + != 0xffffffff) + { + COGL_NOTE (WINSYS, "Found an ARGB FBConfig [index:%d]", i); + *config_ret = configs[i]; + goto done; + } + } + + _cogl_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_CREATE_CONTEXT, + "Unable to find fbconfig with rgba visual"); + ret = FALSE; + goto done; + } + else + { + COGL_NOTE (WINSYS, "Using the first available FBConfig"); + *config_ret = configs[0]; + } + +done: + XFree (configs); + return ret; +} + +static GLXContext +create_gl3_context (CoglDisplay *display, + GLXFBConfig fb_config) +{ + CoglXlibRenderer *xlib_renderer = + _cogl_xlib_renderer_get_data (display->renderer); + CoglGLXRenderer *glx_renderer = display->renderer->winsys; + + /* We want a core profile 3.1 context with no deprecated features */ + static const int attrib_list[] = + { + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 1, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, + None + }; + /* NV_robustness_video_memory_purge relies on GLX_ARB_create_context + and in part on ARB_robustness. Namely, it needs the notification + strategy to be set to GLX_LOSE_CONTEXT_ON_RESET_ARB and that the + driver exposes the GetGraphicsResetStatusARB function. This means + we don't actually enable robust buffer access. */ + static const int attrib_list_reset_on_purge[] = + { + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 1, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, + GLX_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV, + GL_TRUE, + GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, + GLX_LOSE_CONTEXT_ON_RESET_ARB, + None + }; + + /* Make sure that the display supports the GLX_ARB_create_context + extension */ + if (glx_renderer->glXCreateContextAttribs == NULL) + return NULL; + + /* We can't check the presence of this extension with the usual + COGL_WINSYS_FEATURE machinery because that only gets initialized + later when the CoglContext is created. */ + if (display->renderer->xlib_want_reset_on_video_memory_purge && + strstr (glx_renderer->glXQueryExtensionsString (xlib_renderer->xdpy, + DefaultScreen (xlib_renderer->xdpy)), + "GLX_NV_robustness_video_memory_purge")) + { + CoglXlibTrapState old_state; + GLXContext ctx; + + _cogl_xlib_renderer_trap_errors (display->renderer, &old_state); + ctx = glx_renderer->glXCreateContextAttribs (xlib_renderer->xdpy, + fb_config, + NULL /* share_context */, + True, /* direct */ + attrib_list_reset_on_purge); + if (!_cogl_xlib_renderer_untrap_errors (display->renderer, &old_state) && ctx) + return ctx; + } + + return glx_renderer->glXCreateContextAttribs (xlib_renderer->xdpy, + fb_config, + NULL /* share_context */, + True, /* direct */ + attrib_list); +} + +static CoglBool +create_context (CoglDisplay *display, CoglError **error) +{ + CoglGLXDisplay *glx_display = display->winsys; + CoglXlibRenderer *xlib_renderer = + _cogl_xlib_renderer_get_data (display->renderer); + CoglGLXRenderer *glx_renderer = display->renderer->winsys; + CoglBool support_transparent_windows = + display->onscreen_template->config.swap_chain->has_alpha; + GLXFBConfig config; + CoglError *fbconfig_error = NULL; + XSetWindowAttributes attrs; + XVisualInfo *xvisinfo; + GLXDrawable dummy_drawable; + CoglXlibTrapState old_state; + + _COGL_RETURN_VAL_IF_FAIL (glx_display->glx_context == NULL, TRUE); + + glx_display->found_fbconfig = + find_fbconfig (display, &display->onscreen_template->config, &config, + &fbconfig_error); + if (!glx_display->found_fbconfig) + { + _cogl_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_CREATE_CONTEXT, + "Unable to find suitable fbconfig for the GLX context: %s", + fbconfig_error->message); + cogl_error_free (fbconfig_error); + return FALSE; + } + + glx_display->fbconfig = config; + glx_display->fbconfig_has_rgba_visual = support_transparent_windows; + + COGL_NOTE (WINSYS, "Creating GLX Context (display: %p)", + xlib_renderer->xdpy); + + _cogl_xlib_renderer_trap_errors (display->renderer, &old_state); + + if (display->renderer->driver == COGL_DRIVER_GL3) + glx_display->glx_context = create_gl3_context (display, config); + else + glx_display->glx_context = + glx_renderer->glXCreateNewContext (xlib_renderer->xdpy, + config, + GLX_RGBA_TYPE, + NULL, + True); + + if (_cogl_xlib_renderer_untrap_errors (display->renderer, &old_state) || + glx_display->glx_context == NULL) + { + _cogl_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_CREATE_CONTEXT, + "Unable to create suitable GL context"); + return FALSE; + } + + glx_renderer->is_direct = + glx_renderer->glXIsDirect (xlib_renderer->xdpy, glx_display->glx_context); + + COGL_NOTE (WINSYS, "Setting %s context", + glx_renderer->is_direct ? "direct" : "indirect"); + + /* XXX: GLX doesn't let us make a context current without a window + * so we create a dummy window that we can use while no CoglOnscreen + * framebuffer is in use. + */ + + xvisinfo = glx_renderer->glXGetVisualFromFBConfig (xlib_renderer->xdpy, + config); + if (xvisinfo == NULL) + { + _cogl_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_CREATE_CONTEXT, + "Unable to retrieve the X11 visual"); + return FALSE; + } + + _cogl_xlib_renderer_trap_errors (display->renderer, &old_state); + + attrs.override_redirect = True; + attrs.colormap = XCreateColormap (xlib_renderer->xdpy, + DefaultRootWindow (xlib_renderer->xdpy), + xvisinfo->visual, + AllocNone); + attrs.border_pixel = 0; + + glx_display->dummy_xwin = + XCreateWindow (xlib_renderer->xdpy, + DefaultRootWindow (xlib_renderer->xdpy), + -100, -100, 1, 1, + 0, + xvisinfo->depth, + CopyFromParent, + xvisinfo->visual, + CWOverrideRedirect | CWColormap | CWBorderPixel, + &attrs); + + /* Try and create a GLXWindow to use with extensions dependent on + * GLX versions >= 1.3 that don't accept regular X Windows as GLX + * drawables. */ + if (glx_renderer->glx_major == 1 && glx_renderer->glx_minor >= 3) + { + glx_display->dummy_glxwin = + glx_renderer->glXCreateWindow (xlib_renderer->xdpy, + config, + glx_display->dummy_xwin, + NULL); + } + + if (glx_display->dummy_glxwin) + dummy_drawable = glx_display->dummy_glxwin; + else + dummy_drawable = glx_display->dummy_xwin; + + COGL_NOTE (WINSYS, "Selecting dummy 0x%x for the GLX context", + (unsigned int) dummy_drawable); + + glx_renderer->glXMakeContextCurrent (xlib_renderer->xdpy, + dummy_drawable, + dummy_drawable, + glx_display->glx_context); + + xlib_renderer->xvisinfo = xvisinfo; + + if (_cogl_xlib_renderer_untrap_errors (display->renderer, &old_state)) + { + _cogl_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_CREATE_CONTEXT, + "Unable to select the newly created GLX context"); + return FALSE; + } + + return TRUE; +} + +static void +_cogl_winsys_display_destroy (CoglDisplay *display) +{ + CoglGLXDisplay *glx_display = display->winsys; + CoglXlibRenderer *xlib_renderer = + _cogl_xlib_renderer_get_data (display->renderer); + CoglGLXRenderer *glx_renderer = display->renderer->winsys; + + _COGL_RETURN_IF_FAIL (glx_display != NULL); + + if (glx_display->glx_context) + { + glx_renderer->glXMakeContextCurrent (xlib_renderer->xdpy, + None, None, NULL); + glx_renderer->glXDestroyContext (xlib_renderer->xdpy, + glx_display->glx_context); + glx_display->glx_context = NULL; + } + + if (glx_display->dummy_glxwin) + { + glx_renderer->glXDestroyWindow (xlib_renderer->xdpy, + glx_display->dummy_glxwin); + glx_display->dummy_glxwin = None; + } + + if (glx_display->dummy_xwin) + { + XDestroyWindow (xlib_renderer->xdpy, glx_display->dummy_xwin); + glx_display->dummy_xwin = None; + } + + g_slice_free (CoglGLXDisplay, display->winsys); + display->winsys = NULL; +} + +static CoglBool +_cogl_winsys_display_setup (CoglDisplay *display, + CoglError **error) +{ + CoglGLXDisplay *glx_display; + int i; + + _COGL_RETURN_VAL_IF_FAIL (display->winsys == NULL, FALSE); + + glx_display = g_slice_new0 (CoglGLXDisplay); + display->winsys = glx_display; + + if (!create_context (display, error)) + goto error; + + for (i = 0; i < COGL_GLX_N_CACHED_CONFIGS; i++) + glx_display->glx_cached_configs[i].depth = -1; + + return TRUE; + +error: + _cogl_winsys_display_destroy (display); + return FALSE; +} + +static CoglBool +_cogl_winsys_context_init (CoglContext *context, CoglError **error) +{ + context->winsys = g_new0 (CoglContextGLX, 1); + + cogl_xlib_renderer_add_filter (context->display->renderer, + glx_event_filter_cb, + context); + return update_winsys_features (context, error); +} + +static void +_cogl_winsys_context_deinit (CoglContext *context) +{ + cogl_xlib_renderer_remove_filter (context->display->renderer, + glx_event_filter_cb, + context); + g_free (context->winsys); +} + +static CoglBool +_cogl_winsys_onscreen_init (CoglOnscreen *onscreen, + CoglError **error) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + CoglContext *context = framebuffer->context; + CoglDisplay *display = context->display; + CoglGLXDisplay *glx_display = display->winsys; + CoglXlibRenderer *xlib_renderer = + _cogl_xlib_renderer_get_data (display->renderer); + CoglGLXRenderer *glx_renderer = display->renderer->winsys; + Window xwin; + CoglOnscreenXlib *xlib_onscreen; + CoglOnscreenGLX *glx_onscreen; + GLXFBConfig fbconfig; + CoglError *fbconfig_error = NULL; + + _COGL_RETURN_VAL_IF_FAIL (glx_display->glx_context, FALSE); + + if (!find_fbconfig (display, &framebuffer->config, + &fbconfig, + &fbconfig_error)) + { + _cogl_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_CREATE_CONTEXT, + "Unable to find suitable fbconfig for the GLX context: %s", + fbconfig_error->message); + cogl_error_free (fbconfig_error); + return FALSE; + } + + /* Update the real number of samples_per_pixel now that we have + * found an fbconfig... */ + if (framebuffer->config.samples_per_pixel) + { + int samples; + int status = glx_renderer->glXGetFBConfigAttrib (xlib_renderer->xdpy, + fbconfig, + GLX_SAMPLES, + &samples); + g_return_val_if_fail (status == Success, TRUE); + framebuffer->samples_per_pixel = samples; + } + + /* FIXME: We need to explicitly Select for ConfigureNotify events. + * For foreign windows we need to be careful not to mess up any + * existing event mask. + * We need to document that for windows we create then toolkits + * must be careful not to clear event mask bits that we select. + */ + + /* XXX: Note we ignore the user's original width/height when + * given a foreign X window. */ + if (onscreen->foreign_xid) + { + Status status; + CoglXlibTrapState state; + XWindowAttributes attr; + int xerror; + + xwin = onscreen->foreign_xid; + + _cogl_xlib_renderer_trap_errors (display->renderer, &state); + + status = XGetWindowAttributes (xlib_renderer->xdpy, xwin, &attr); + XSync (xlib_renderer->xdpy, False); + xerror = _cogl_xlib_renderer_untrap_errors (display->renderer, &state); + if (status == 0 || xerror) + { + char message[1000]; + XGetErrorText (xlib_renderer->xdpy, xerror, message, sizeof(message)); + _cogl_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_CREATE_ONSCREEN, + "Unable to query geometry of foreign xid 0x%08lX: %s", + xwin, message); + return FALSE; + } + + _cogl_framebuffer_winsys_update_size (framebuffer, + attr.width, attr.height); + + /* Make sure the app selects for the events we require... */ + onscreen->foreign_update_mask_callback (onscreen, + COGL_ONSCREEN_X11_EVENT_MASK, + onscreen->foreign_update_mask_data); + } + else + { + int width; + int height; + CoglXlibTrapState state; + XVisualInfo *xvisinfo; + XSetWindowAttributes xattr; + unsigned long mask; + int xerror; + + width = cogl_framebuffer_get_width (framebuffer); + height = cogl_framebuffer_get_height (framebuffer); + + _cogl_xlib_renderer_trap_errors (display->renderer, &state); + + xvisinfo = glx_renderer->glXGetVisualFromFBConfig (xlib_renderer->xdpy, + fbconfig); + if (xvisinfo == NULL) + { + _cogl_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_CREATE_ONSCREEN, + "Unable to retrieve the X11 visual of context's " + "fbconfig"); + return FALSE; + } + + /* window attributes */ + xattr.background_pixel = WhitePixel (xlib_renderer->xdpy, + DefaultScreen (xlib_renderer->xdpy)); + xattr.border_pixel = 0; + /* XXX: is this an X resource that we are leaking‽... */ + xattr.colormap = XCreateColormap (xlib_renderer->xdpy, + DefaultRootWindow (xlib_renderer->xdpy), + xvisinfo->visual, + AllocNone); + xattr.event_mask = COGL_ONSCREEN_X11_EVENT_MASK; + + mask = CWBorderPixel | CWColormap | CWEventMask; + + xwin = XCreateWindow (xlib_renderer->xdpy, + DefaultRootWindow (xlib_renderer->xdpy), + 0, 0, + width, height, + 0, + xvisinfo->depth, + InputOutput, + xvisinfo->visual, + mask, &xattr); + + XFree (xvisinfo); + + XSync (xlib_renderer->xdpy, False); + xerror = _cogl_xlib_renderer_untrap_errors (display->renderer, &state); + if (xerror) + { + char message[1000]; + XGetErrorText (xlib_renderer->xdpy, xerror, + message, sizeof (message)); + _cogl_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_CREATE_ONSCREEN, + "X error while creating Window for CoglOnscreen: %s", + message); + return FALSE; + } + } + + onscreen->winsys = g_slice_new0 (CoglOnscreenGLX); + xlib_onscreen = onscreen->winsys; + glx_onscreen = onscreen->winsys; + + xlib_onscreen->xwin = xwin; + xlib_onscreen->is_foreign_xwin = onscreen->foreign_xid ? TRUE : FALSE; + + /* Try and create a GLXWindow to use with extensions dependent on + * GLX versions >= 1.3 that don't accept regular X Windows as GLX + * drawables. */ + if (glx_renderer->glx_major == 1 && glx_renderer->glx_minor >= 3) + { + glx_onscreen->glxwin = + glx_renderer->glXCreateWindow (xlib_renderer->xdpy, + fbconfig, + xlib_onscreen->xwin, + NULL); + } + +#ifdef GLX_INTEL_swap_event + if (_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT)) + { + GLXDrawable drawable = + glx_onscreen->glxwin ? glx_onscreen->glxwin : xlib_onscreen->xwin; + + /* similarly to above, we unconditionally select this event + * because we rely on it to advance the master clock, and + * drive redraw/relayout, animations and event handling. + */ + glx_renderer->glXSelectEvent (xlib_renderer->xdpy, + drawable, + GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK); + } +#endif /* GLX_INTEL_swap_event */ + + return TRUE; +} + +static void +_cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + CoglContext *context = framebuffer->context; + CoglContextGLX *glx_context = context->winsys; + CoglGLXDisplay *glx_display = context->display->winsys; + CoglXlibRenderer *xlib_renderer = + _cogl_xlib_renderer_get_data (context->display->renderer); + CoglGLXRenderer *glx_renderer = context->display->renderer->winsys; + CoglXlibTrapState old_state; + CoglOnscreenXlib *xlib_onscreen = onscreen->winsys; + CoglOnscreenGLX *glx_onscreen = onscreen->winsys; + GLXDrawable drawable; + + /* If we never successfully allocated then there's nothing to do */ + if (glx_onscreen == NULL) + return; + + if (xlib_onscreen->output != NULL) + { + cogl_object_unref (xlib_onscreen->output); + xlib_onscreen->output = NULL; + } + + _cogl_xlib_renderer_trap_errors (context->display->renderer, &old_state); + + drawable = + glx_onscreen->glxwin == None ? xlib_onscreen->xwin : glx_onscreen->glxwin; + + /* Cogl always needs a valid context bound to something so if we are + * destroying the onscreen that is currently bound we'll switch back + * to the dummy drawable. Although the documentation for + * glXDestroyWindow states that a currently bound window won't + * actually be destroyed until it is unbound, it looks like this + * doesn't work if the X window itself is destroyed */ + if (drawable == glx_context->current_drawable) + { + GLXDrawable dummy_drawable = (glx_display->dummy_glxwin == None ? + glx_display->dummy_xwin : + glx_display->dummy_glxwin); + + glx_renderer->glXMakeContextCurrent (xlib_renderer->xdpy, + dummy_drawable, + dummy_drawable, + glx_display->glx_context); + glx_context->current_drawable = dummy_drawable; + } + + if (glx_onscreen->glxwin != None) + { + glx_renderer->glXDestroyWindow (xlib_renderer->xdpy, + glx_onscreen->glxwin); + glx_onscreen->glxwin = None; + } + + if (!xlib_onscreen->is_foreign_xwin && xlib_onscreen->xwin != None) + { + XDestroyWindow (xlib_renderer->xdpy, xlib_onscreen->xwin); + xlib_onscreen->xwin = None; + } + else + xlib_onscreen->xwin = None; + + XSync (xlib_renderer->xdpy, False); + + _cogl_xlib_renderer_untrap_errors (context->display->renderer, &old_state); + + g_slice_free (CoglOnscreenGLX, onscreen->winsys); + onscreen->winsys = NULL; +} + +static void +_cogl_winsys_onscreen_bind (CoglOnscreen *onscreen) +{ + CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context; + CoglContextGLX *glx_context = context->winsys; + CoglGLXDisplay *glx_display = context->display->winsys; + CoglXlibRenderer *xlib_renderer = + _cogl_xlib_renderer_get_data (context->display->renderer); + CoglGLXRenderer *glx_renderer = context->display->renderer->winsys; + CoglOnscreenXlib *xlib_onscreen = onscreen->winsys; + CoglOnscreenGLX *glx_onscreen = onscreen->winsys; + CoglXlibTrapState old_state; + GLXDrawable drawable; + + drawable = + glx_onscreen->glxwin ? glx_onscreen->glxwin : xlib_onscreen->xwin; + + if (glx_context->current_drawable == drawable) + return; + + _cogl_xlib_renderer_trap_errors (context->display->renderer, &old_state); + + COGL_NOTE (WINSYS, + "MakeContextCurrent dpy: %p, window: 0x%x (%s), context: %p", + xlib_renderer->xdpy, + (unsigned int) drawable, + xlib_onscreen->is_foreign_xwin ? "foreign" : "native", + glx_display->glx_context); + + glx_renderer->glXMakeContextCurrent (xlib_renderer->xdpy, + drawable, + drawable, + glx_display->glx_context); + + /* In case we are using GLX_SGI_swap_control for vblank syncing + * we need call glXSwapIntervalSGI here to make sure that it + * affects the current drawable. + * + * Note: we explicitly set to 0 when we aren't using the swap + * interval to synchronize since some drivers have a default + * swap interval of 1. Sadly some drivers even ignore requests + * to disable the swap interval. + * + * NB: glXSwapIntervalSGI applies to the context not the + * drawable which is why we can't just do this once when the + * framebuffer is allocated. + * + * FIXME: We should check for GLX_EXT_swap_control which allows + * per framebuffer swap intervals. GLX_MESA_swap_control also + * allows per-framebuffer swap intervals but the semantics tend + * to be more muddled since Mesa drivers tend to expose both the + * MESA and SGI extensions which should technically be mutually + * exclusive. + */ + if (glx_renderer->glXSwapInterval) + { + CoglFramebuffer *fb = COGL_FRAMEBUFFER (onscreen); + if (fb->config.swap_throttled) + glx_renderer->glXSwapInterval (1); + else + glx_renderer->glXSwapInterval (0); + } + + XSync (xlib_renderer->xdpy, False); + + /* FIXME: We should be reporting a CoglError here + */ + if (_cogl_xlib_renderer_untrap_errors (context->display->renderer, + &old_state)) + { + g_warning ("X Error received while making drawable 0x%08lX current", + drawable); + return; + } + + glx_context->current_drawable = drawable; +} + +static void +_cogl_winsys_wait_for_gpu (CoglOnscreen *onscreen) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + CoglContext *ctx = framebuffer->context; + + ctx->glFinish (); +} + +static void +_cogl_winsys_wait_for_vblank (CoglOnscreen *onscreen) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + CoglContext *ctx = framebuffer->context; + CoglGLXRenderer *glx_renderer; + CoglXlibRenderer *xlib_renderer; + + glx_renderer = ctx->display->renderer->winsys; + xlib_renderer = _cogl_xlib_renderer_get_data (ctx->display->renderer); + + if (glx_renderer->glXWaitForMsc || + glx_renderer->glXGetVideoSync) + { + CoglFrameInfo *info = g_queue_peek_tail (&onscreen->pending_frame_infos); + + if (glx_renderer->glXWaitForMsc) + { + CoglOnscreenGLX *glx_onscreen = onscreen->winsys; + Drawable drawable = glx_onscreen->glxwin; + int64_t ust; + int64_t msc; + int64_t sbc; + + glx_renderer->glXWaitForMsc (xlib_renderer->xdpy, drawable, + 0, 1, 0, + &ust, &msc, &sbc); + info->presentation_time = ust_to_nanoseconds (ctx->display->renderer, + drawable, + ust); + } + else + { + uint32_t current_count; + struct timespec ts; + + glx_renderer->glXGetVideoSync (¤t_count); + glx_renderer->glXWaitVideoSync (2, + (current_count + 1) % 2, + ¤t_count); + + clock_gettime (CLOCK_MONOTONIC, &ts); + info->presentation_time = + ts.tv_sec * G_GINT64_CONSTANT (1000000000) + ts.tv_nsec; + } + } +} + +static uint32_t +_cogl_winsys_get_vsync_counter (CoglContext *ctx) +{ + uint32_t video_sync_count; + CoglGLXRenderer *glx_renderer; + + glx_renderer = ctx->display->renderer->winsys; + + glx_renderer->glXGetVideoSync (&video_sync_count); + + return video_sync_count; +} + +#ifndef GLX_BACK_BUFFER_AGE_EXT +#define GLX_BACK_BUFFER_AGE_EXT 0x20F4 +#endif + +static int +_cogl_winsys_onscreen_get_buffer_age (CoglOnscreen *onscreen) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + CoglContext *context = framebuffer->context; + CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (context->display->renderer); + CoglGLXRenderer *glx_renderer = context->display->renderer->winsys; + CoglOnscreenGLX *glx_onscreen = onscreen->winsys; + CoglOnscreenXlib *xlib_onscreen = onscreen->winsys; + GLXDrawable drawable = glx_onscreen->glxwin ? glx_onscreen->glxwin : xlib_onscreen->xwin; + unsigned int age; + + if (!_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_BUFFER_AGE)) + return 0; + + glx_renderer->glXQueryDrawable (xlib_renderer->xdpy, drawable, GLX_BACK_BUFFER_AGE_EXT, &age); + + return age; +} + +static void +set_frame_info_output (CoglOnscreen *onscreen, + CoglOutput *output) +{ + CoglFrameInfo *info = g_queue_peek_tail (&onscreen->pending_frame_infos); + + info->output = output; + + if (output) + { + float refresh_rate = cogl_output_get_refresh_rate (output); + if (refresh_rate != 0.0) + info->refresh_rate = refresh_rate; + } +} + +static void +_cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen, + const int *user_rectangles, + int n_rectangles) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + CoglContext *context = framebuffer->context; + CoglXlibRenderer *xlib_renderer = + _cogl_xlib_renderer_get_data (context->display->renderer); + CoglGLXRenderer *glx_renderer = context->display->renderer->winsys; + CoglOnscreenXlib *xlib_onscreen = onscreen->winsys; + CoglOnscreenGLX *glx_onscreen = onscreen->winsys; + GLXDrawable drawable = + glx_onscreen->glxwin ? glx_onscreen->glxwin : xlib_onscreen->xwin; + uint32_t end_frame_vsync_counter = 0; + CoglBool have_counter; + CoglBool can_wait; + int x_min = 0, x_max = 0, y_min = 0, y_max = 0; + + /* + * We assume that glXCopySubBuffer is synchronized which means it won't prevent multiple + * blits per retrace if they can all be performed in the blanking period. If that's the + * case then we still want to use the vblank sync menchanism but + * we only need it to throttle redraws. + */ + CoglBool blit_sub_buffer_is_synchronized = + _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_REGION_SYNCHRONIZED); + + int framebuffer_width = cogl_framebuffer_get_width (framebuffer); + int framebuffer_height = cogl_framebuffer_get_height (framebuffer); + int *rectangles = g_alloca (sizeof (int) * n_rectangles * 4); + int i; + + /* glXCopySubBuffer expects rectangles relative to the bottom left corner but + * we are given rectangles relative to the top left so we need to flip + * them... */ + memcpy (rectangles, user_rectangles, sizeof (int) * n_rectangles * 4); + for (i = 0; i < n_rectangles; i++) + { + int *rect = &rectangles[4 * i]; + + if (i == 0) + { + x_min = rect[0]; + x_max = rect[0] + rect[2]; + y_min = rect[1]; + y_max = rect[1] + rect[3]; + } + else + { + x_min = MIN (x_min, rect[0]); + x_max = MAX (x_max, rect[0] + rect[2]); + y_min = MIN (y_min, rect[1]); + y_max = MAX (y_max, rect[1] + rect[3]); + } + + rect[1] = framebuffer_height - rect[1] - rect[3]; + + } + + _cogl_framebuffer_flush_state (framebuffer, + framebuffer, + COGL_FRAMEBUFFER_STATE_BIND); + + if (framebuffer->config.swap_throttled) + { + have_counter = + _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_VBLANK_COUNTER); + can_wait = _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_VBLANK_WAIT); + } + else + { + have_counter = FALSE; + can_wait = FALSE; + } + + /* We need to ensure that all the rendering is done, otherwise + * redraw operations that are slower than the framerate can + * queue up in the pipeline during a heavy animation, causing a + * larger and larger backlog of rendering visible as lag to the + * user. + * + * For an exaggerated example consider rendering at 60fps (so 16ms + * per frame) and you have a really slow frame that takes 160ms to + * render, even though painting the scene and issuing the commands + * to the GPU takes no time at all. If all we did was use the + * video_sync extension to throttle the painting done by the CPU + * then every 16ms we would have another frame queued up even though + * the GPU has only rendered one tenth of the current frame. By the + * time the GPU would get to the 2nd frame there would be 9 frames + * waiting to be rendered. + * + * The problem is that we don't currently have a good way to throttle + * the GPU, only the CPU so we have to resort to synchronizing the + * GPU with the CPU to throttle it. + * + * Note: since calling glFinish() and synchronizing the CPU with + * the GPU is far from ideal, we hope that this is only a short + * term solution. + * - One idea is to using sync objects to track render + * completion so we can throttle the backlog (ideally with an + * additional extension that lets us get notifications in our + * mainloop instead of having to busy wait for the + * completion.) + * - Another option is to support clipped redraws by reusing the + * contents of old back buffers such that we can flip instead + * of using a blit and then we can use GLX_INTEL_swap_events + * to throttle. For this though we would still probably want an + * additional extension so we can report the limited region of + * the window damage to X/compositors. + */ + _cogl_winsys_wait_for_gpu (onscreen); + + if (blit_sub_buffer_is_synchronized && have_counter && can_wait) + { + end_frame_vsync_counter = _cogl_winsys_get_vsync_counter (context); + + /* If we have the GLX_SGI_video_sync extension then we can + * be a bit smarter about how we throttle blits by avoiding + * any waits if we can see that the video sync count has + * already progressed. */ + if (glx_onscreen->last_swap_vsync_counter == end_frame_vsync_counter) + _cogl_winsys_wait_for_vblank (onscreen); + } + else if (can_wait) + _cogl_winsys_wait_for_vblank (onscreen); + + if (glx_renderer->glXCopySubBuffer) + { + Display *xdpy = xlib_renderer->xdpy; + int i; + for (i = 0; i < n_rectangles; i++) + { + int *rect = &rectangles[4 * i]; + glx_renderer->glXCopySubBuffer (xdpy, drawable, + rect[0], rect[1], rect[2], rect[3]); + } + } + else if (context->glBlitFramebuffer) + { + int i; + /* XXX: checkout how this state interacts with the code to use + * glBlitFramebuffer in Neil's texture atlasing branch */ + + /* glBlitFramebuffer is affected by the scissor so we need to + * ensure we have flushed an empty clip stack to get rid of it. + * We also mark that the clip state is dirty so that it will be + * flushed to the correct state the next time something is + * drawn */ + _cogl_clip_stack_flush (NULL, framebuffer); + context->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_CLIP; + + context->glDrawBuffer (GL_FRONT); + for (i = 0; i < n_rectangles; i++) + { + int *rect = &rectangles[4 * i]; + int x2 = rect[0] + rect[2]; + int y2 = rect[1] + rect[3]; + context->glBlitFramebuffer (rect[0], rect[1], x2, y2, + rect[0], rect[1], x2, y2, + GL_COLOR_BUFFER_BIT, GL_NEAREST); + } + context->glDrawBuffer (context->current_gl_draw_buffer); + } + + /* NB: unlike glXSwapBuffers, glXCopySubBuffer and + * glBlitFramebuffer don't issue an implicit glFlush() so we + * have to flush ourselves if we want the request to complete in + * a finite amount of time since otherwise the driver can batch + * the command indefinitely. */ + context->glFlush (); + + /* NB: It's important we save the counter we read before acting on + * the swap request since if we are mixing and matching different + * swap methods between frames we don't want to read the timer e.g. + * after calling glFinish() some times and not for others. + * + * In other words; this way we consistently save the time at the end + * of the applications frame such that the counter isn't muddled by + * the varying costs of different swap methods. + */ + if (have_counter) + glx_onscreen->last_swap_vsync_counter = end_frame_vsync_counter; + + if (!xlib_onscreen->is_foreign_xwin) + { + CoglOutput *output; + + x_min = CLAMP (x_min, 0, framebuffer_width); + x_max = CLAMP (x_max, 0, framebuffer_width); + y_min = CLAMP (y_min, 0, framebuffer_width); + y_max = CLAMP (y_max, 0, framebuffer_height); + + output = + _cogl_xlib_renderer_output_for_rectangle (context->display->renderer, + xlib_onscreen->x + x_min, + xlib_onscreen->y + y_min, + x_max - x_min, + y_max - y_min); + + set_frame_info_output (onscreen, output); + } + + /* XXX: we don't get SwapComplete events based on how we implement + * the _swap_region() API but if cogl-onscreen.c knows we are + * handling _SYNC and _COMPLETE events in the winsys then we need to + * send fake events in this case. + */ + if (_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT)) + { + set_sync_pending (onscreen); + set_complete_pending (onscreen); + } +} + +static void +_cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen, + const int *rectangles, + int n_rectangles) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + CoglContext *context = framebuffer->context; + CoglXlibRenderer *xlib_renderer = + _cogl_xlib_renderer_get_data (context->display->renderer); + CoglGLXRenderer *glx_renderer = context->display->renderer->winsys; + CoglOnscreenXlib *xlib_onscreen = onscreen->winsys; + CoglOnscreenGLX *glx_onscreen = onscreen->winsys; + CoglBool have_counter; + GLXDrawable drawable; + + /* XXX: theoretically this shouldn't be necessary but at least with + * the Intel drivers we have see that if we don't call + * glXMakeContextCurrent for the drawable we are swapping then + * we get a BadDrawable error from the X server. */ + _cogl_framebuffer_flush_state (framebuffer, + framebuffer, + COGL_FRAMEBUFFER_STATE_BIND); + + drawable = glx_onscreen->glxwin ? glx_onscreen->glxwin : xlib_onscreen->xwin; + + if (framebuffer->config.swap_throttled) + { + uint32_t end_frame_vsync_counter = 0; + + have_counter = + _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_VBLANK_COUNTER); + + /* If the swap_region API is also being used then we need to track + * the vsync counter for each swap request so we can manually + * throttle swap_region requests. */ + if (have_counter) + end_frame_vsync_counter = _cogl_winsys_get_vsync_counter (context); + + if (!glx_renderer->glXSwapInterval) + { + CoglBool can_wait = + _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_VBLANK_WAIT); + + /* If we are going to wait for VBLANK manually, we not only + * need to flush out pending drawing to the GPU before we + * sleep, we need to wait for it to finish. Otherwise, we + * may end up with the situation: + * + * - We finish drawing - GPU drawing continues + * - We go to sleep - GPU drawing continues + * VBLANK - We call glXSwapBuffers - GPU drawing continues + * - GPU drawing continues + * - Swap buffers happens + * + * Producing a tear. Calling glFinish() first will cause us + * to properly wait for the next VBLANK before we swap. This + * obviously does not happen when we use _GLX_SWAP and let + * the driver do the right thing + */ + _cogl_winsys_wait_for_gpu (onscreen); + + if (have_counter && can_wait) + { + if (glx_onscreen->last_swap_vsync_counter == + end_frame_vsync_counter) + _cogl_winsys_wait_for_vblank (onscreen); + } + else if (can_wait) + _cogl_winsys_wait_for_vblank (onscreen); + } + } + else + have_counter = FALSE; + + glx_renderer->glXSwapBuffers (xlib_renderer->xdpy, drawable); + + if (have_counter) + glx_onscreen->last_swap_vsync_counter = + _cogl_winsys_get_vsync_counter (context); + + set_frame_info_output (onscreen, xlib_onscreen->output); +} + +static uint32_t +_cogl_winsys_onscreen_x11_get_window_xid (CoglOnscreen *onscreen) +{ + CoglOnscreenXlib *xlib_onscreen = onscreen->winsys; + return xlib_onscreen->xwin; +} + +static void +_cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen) +{ + CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context; + CoglContextGLX *glx_context = context->winsys; + CoglOnscreenGLX *glx_onscreen = onscreen->winsys; + CoglOnscreenXlib *xlib_onscreen = onscreen->winsys; + GLXDrawable drawable = + glx_onscreen->glxwin ? glx_onscreen->glxwin : xlib_onscreen->xwin; + + if (glx_context->current_drawable != drawable) + return; + + glx_context->current_drawable = 0; + _cogl_winsys_onscreen_bind (onscreen); +} + +static void +_cogl_winsys_onscreen_set_visibility (CoglOnscreen *onscreen, + CoglBool visibility) +{ + CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context; + CoglXlibRenderer *xlib_renderer = + _cogl_xlib_renderer_get_data (context->display->renderer); + CoglOnscreenXlib *xlib_onscreen = onscreen->winsys; + + if (visibility) + XMapWindow (xlib_renderer->xdpy, xlib_onscreen->xwin); + else + XUnmapWindow (xlib_renderer->xdpy, xlib_onscreen->xwin); +} + +static void +_cogl_winsys_onscreen_set_resizable (CoglOnscreen *onscreen, + CoglBool resizable) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + CoglContext *context = framebuffer->context; + CoglXlibRenderer *xlib_renderer = + _cogl_xlib_renderer_get_data (context->display->renderer); + CoglOnscreenXlib *xlib_onscreen = onscreen->winsys; + + XSizeHints *size_hints = XAllocSizeHints (); + + if (resizable) + { + /* TODO: Add cogl_onscreen_request_minimum_size () */ + size_hints->min_width = 1; + size_hints->min_height = 1; + + size_hints->max_width = INT_MAX; + size_hints->max_height = INT_MAX; + } + else + { + int width = cogl_framebuffer_get_width (framebuffer); + int height = cogl_framebuffer_get_height (framebuffer); + + size_hints->min_width = width; + size_hints->min_height = height; + + size_hints->max_width = width; + size_hints->max_height = height; + } + + XSetWMNormalHints (xlib_renderer->xdpy, xlib_onscreen->xwin, size_hints); + + XFree (size_hints); +} + +static CoglBool +get_fbconfig_for_depth (CoglContext *context, + unsigned int depth, + CoglBool stereo, + GLXFBConfig *fbconfig_ret, + CoglBool *can_mipmap_ret) +{ + CoglXlibRenderer *xlib_renderer; + CoglGLXRenderer *glx_renderer; + CoglGLXDisplay *glx_display; + Display *dpy; + GLXFBConfig *fbconfigs; + int n_elements, i; + int db, stencil, alpha, mipmap, rgba, value; + int spare_cache_slot = 0; + CoglBool found = FALSE; + + xlib_renderer = _cogl_xlib_renderer_get_data (context->display->renderer); + glx_renderer = context->display->renderer->winsys; + glx_display = context->display->winsys; + + /* Check if we've already got a cached config for this depth and stereo */ + for (i = 0; i < COGL_GLX_N_CACHED_CONFIGS; i++) + if (glx_display->glx_cached_configs[i].depth == -1) + spare_cache_slot = i; + else if (glx_display->glx_cached_configs[i].depth == depth && + glx_display->glx_cached_configs[i].stereo == stereo) + { + *fbconfig_ret = glx_display->glx_cached_configs[i].fb_config; + *can_mipmap_ret = glx_display->glx_cached_configs[i].can_mipmap; + return glx_display->glx_cached_configs[i].found; + } + + dpy = xlib_renderer->xdpy; + + fbconfigs = glx_renderer->glXGetFBConfigs (dpy, DefaultScreen (dpy), + &n_elements); + + db = G_MAXSHORT; + stencil = G_MAXSHORT; + mipmap = 0; + rgba = 0; + + for (i = 0; i < n_elements; i++) + { + XVisualInfo *vi; + int visual_depth; + + vi = glx_renderer->glXGetVisualFromFBConfig (dpy, fbconfigs[i]); + if (vi == NULL) + continue; + + visual_depth = vi->depth; + + XFree (vi); + + if (visual_depth != depth) + continue; + + glx_renderer->glXGetFBConfigAttrib (dpy, + fbconfigs[i], + GLX_ALPHA_SIZE, + &alpha); + glx_renderer->glXGetFBConfigAttrib (dpy, + fbconfigs[i], + GLX_BUFFER_SIZE, + &value); + if (value != depth && (value - alpha) != depth) + continue; + + glx_renderer->glXGetFBConfigAttrib (dpy, + fbconfigs[i], + GLX_STEREO, + &value); + if (!!value != !!stereo) + continue; + + if (glx_renderer->glx_major == 1 && glx_renderer->glx_minor >= 4) + { + glx_renderer->glXGetFBConfigAttrib (dpy, + fbconfigs[i], + GLX_SAMPLES, + &value); + if (value > 1) + continue; + } + + value = 0; + if (depth == 32) + { + glx_renderer->glXGetFBConfigAttrib (dpy, + fbconfigs[i], + GLX_BIND_TO_TEXTURE_RGBA_EXT, + &value); + if (value) + rgba = 1; + } + + if (!value) + { + if (rgba) + continue; + + glx_renderer->glXGetFBConfigAttrib (dpy, + fbconfigs[i], + GLX_BIND_TO_TEXTURE_RGB_EXT, + &value); + if (!value) + continue; + } + + glx_renderer->glXGetFBConfigAttrib (dpy, + fbconfigs[i], + GLX_DOUBLEBUFFER, + &value); + if (value > db) + continue; + + db = value; + + glx_renderer->glXGetFBConfigAttrib (dpy, + fbconfigs[i], + GLX_STENCIL_SIZE, + &value); + if (value > stencil) + continue; + + stencil = value; + + /* glGenerateMipmap is defined in the offscreen extension */ + if (cogl_has_feature (context, COGL_FEATURE_ID_OFFSCREEN)) + { + glx_renderer->glXGetFBConfigAttrib (dpy, + fbconfigs[i], + GLX_BIND_TO_MIPMAP_TEXTURE_EXT, + &value); + + if (value < mipmap) + continue; + + mipmap = value; + } + + *fbconfig_ret = fbconfigs[i]; + *can_mipmap_ret = mipmap; + found = TRUE; + } + + if (n_elements) + XFree (fbconfigs); + + glx_display->glx_cached_configs[spare_cache_slot].depth = depth; + glx_display->glx_cached_configs[spare_cache_slot].found = found; + glx_display->glx_cached_configs[spare_cache_slot].fb_config = *fbconfig_ret; + glx_display->glx_cached_configs[spare_cache_slot].can_mipmap = mipmap; + + return found; +} + +static CoglBool +should_use_rectangle (CoglContext *context) +{ + + if (context->rectangle_state == COGL_WINSYS_RECTANGLE_STATE_UNKNOWN) + { + if (cogl_has_feature (context, COGL_FEATURE_ID_TEXTURE_RECTANGLE)) + { + const char *rect_env; + + /* Use the rectangle only if it is available and either: + + the COGL_PIXMAP_TEXTURE_RECTANGLE environment variable is + set to 'force' + + *or* + + the env var is set to 'allow' or not set and NPOTs textures + are not available */ + + context->rectangle_state = + cogl_has_feature (context, COGL_FEATURE_ID_TEXTURE_NPOT) ? + COGL_WINSYS_RECTANGLE_STATE_DISABLE : + COGL_WINSYS_RECTANGLE_STATE_ENABLE; + + if ((rect_env = g_getenv ("COGL_PIXMAP_TEXTURE_RECTANGLE")) || + /* For compatibility, we'll also look at the old Clutter + environment variable */ + (rect_env = g_getenv ("CLUTTER_PIXMAP_TEXTURE_RECTANGLE"))) + { + if (g_ascii_strcasecmp (rect_env, "force") == 0) + context->rectangle_state = + COGL_WINSYS_RECTANGLE_STATE_ENABLE; + else if (g_ascii_strcasecmp (rect_env, "disable") == 0) + context->rectangle_state = + COGL_WINSYS_RECTANGLE_STATE_DISABLE; + else if (g_ascii_strcasecmp (rect_env, "allow")) + g_warning ("Unknown value for COGL_PIXMAP_TEXTURE_RECTANGLE, " + "should be 'force' or 'disable'"); + } + } + else + context->rectangle_state = COGL_WINSYS_RECTANGLE_STATE_DISABLE; + } + + return context->rectangle_state == COGL_WINSYS_RECTANGLE_STATE_ENABLE; +} + +static CoglBool +try_create_glx_pixmap (CoglContext *context, + CoglTexturePixmapX11 *tex_pixmap, + CoglBool mipmap) +{ + CoglTexturePixmapGLX *glx_tex_pixmap = tex_pixmap->winsys; + CoglRenderer *renderer; + CoglXlibRenderer *xlib_renderer; + CoglGLXRenderer *glx_renderer; + Display *dpy; + /* We have to initialize this *opaque* variable because gcc tries to + * be too smart for its own good and warns that the variable may be + * used uninitialized otherwise. */ + GLXFBConfig fb_config = (GLXFBConfig)0; + int attribs[7]; + int i = 0; + GLenum target; + CoglXlibTrapState trap_state; + + unsigned int depth = tex_pixmap->depth; + Visual* visual = tex_pixmap->visual; + + renderer = context->display->renderer; + xlib_renderer = _cogl_xlib_renderer_get_data (renderer); + glx_renderer = renderer->winsys; + dpy = xlib_renderer->xdpy; + + if (!get_fbconfig_for_depth (context, depth, + tex_pixmap->stereo_mode != COGL_TEXTURE_PIXMAP_MONO, + &fb_config, + &glx_tex_pixmap->can_mipmap)) + { + COGL_NOTE (TEXTURE_PIXMAP, "No suitable FBConfig found for depth %i", + depth); + return FALSE; + } + + if (should_use_rectangle (context)) + { + target = GLX_TEXTURE_RECTANGLE_EXT; + glx_tex_pixmap->can_mipmap = FALSE; + } + else + target = GLX_TEXTURE_2D_EXT; + + if (!glx_tex_pixmap->can_mipmap) + mipmap = FALSE; + + attribs[i++] = GLX_TEXTURE_FORMAT_EXT; + + /* Check whether an alpha channel is used by comparing the total + * number of 1-bits in color masks against the color depth requested + * by the client. + */ + if (_cogl_util_popcountl (visual->red_mask | + visual->green_mask | + visual->blue_mask) == depth) + attribs[i++] = GLX_TEXTURE_FORMAT_RGB_EXT; + else + attribs[i++] = GLX_TEXTURE_FORMAT_RGBA_EXT; + + attribs[i++] = GLX_MIPMAP_TEXTURE_EXT; + attribs[i++] = mipmap; + + attribs[i++] = GLX_TEXTURE_TARGET_EXT; + attribs[i++] = target; + + attribs[i++] = None; + + /* We need to trap errors from glXCreatePixmap because it can + * sometimes fail during normal usage. For example on NVidia it gets + * upset if you try to create two GLXPixmaps for the same drawable. + */ + + _cogl_xlib_renderer_trap_errors (renderer, &trap_state); + + glx_tex_pixmap->glx_pixmap = + glx_renderer->glXCreatePixmap (dpy, + fb_config, + tex_pixmap->pixmap, + attribs); + glx_tex_pixmap->has_mipmap_space = mipmap; + + XSync (dpy, False); + + if (_cogl_xlib_renderer_untrap_errors (renderer, &trap_state)) + { + COGL_NOTE (TEXTURE_PIXMAP, "Failed to create pixmap for %p", tex_pixmap); + _cogl_xlib_renderer_trap_errors (renderer, &trap_state); + glx_renderer->glXDestroyPixmap (dpy, glx_tex_pixmap->glx_pixmap); + XSync (dpy, False); + _cogl_xlib_renderer_untrap_errors (renderer, &trap_state); + + glx_tex_pixmap->glx_pixmap = None; + return FALSE; + } + + return TRUE; +} + +static CoglBool +_cogl_winsys_texture_pixmap_x11_create (CoglTexturePixmapX11 *tex_pixmap) +{ + CoglTexturePixmapGLX *glx_tex_pixmap; + CoglContext *ctx = COGL_TEXTURE (tex_pixmap)->context; + + if (!_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_TEXTURE_FROM_PIXMAP)) + { + tex_pixmap->winsys = NULL; + return FALSE; + } + + glx_tex_pixmap = g_new0 (CoglTexturePixmapGLX, 1); + + glx_tex_pixmap->glx_pixmap = None; + glx_tex_pixmap->can_mipmap = FALSE; + glx_tex_pixmap->has_mipmap_space = FALSE; + + glx_tex_pixmap->left.glx_tex = NULL; + glx_tex_pixmap->right.glx_tex = NULL; + + glx_tex_pixmap->left.bind_tex_image_queued = TRUE; + glx_tex_pixmap->right.bind_tex_image_queued = TRUE; + glx_tex_pixmap->left.pixmap_bound = FALSE; + glx_tex_pixmap->right.pixmap_bound = FALSE; + + tex_pixmap->winsys = glx_tex_pixmap; + + if (!try_create_glx_pixmap (ctx, tex_pixmap, FALSE)) + { + tex_pixmap->winsys = NULL; + g_free (glx_tex_pixmap); + return FALSE; + } + + return TRUE; +} + +static void +free_glx_pixmap (CoglContext *context, + CoglTexturePixmapGLX *glx_tex_pixmap) +{ + CoglXlibTrapState trap_state; + CoglRenderer *renderer; + CoglXlibRenderer *xlib_renderer; + CoglGLXRenderer *glx_renderer; + + renderer = context->display->renderer; + xlib_renderer = _cogl_xlib_renderer_get_data (renderer); + glx_renderer = renderer->winsys; + + if (glx_tex_pixmap->left.pixmap_bound) + glx_renderer->glXReleaseTexImage (xlib_renderer->xdpy, + glx_tex_pixmap->glx_pixmap, + GLX_FRONT_LEFT_EXT); + if (glx_tex_pixmap->right.pixmap_bound) + glx_renderer->glXReleaseTexImage (xlib_renderer->xdpy, + glx_tex_pixmap->glx_pixmap, + GLX_FRONT_RIGHT_EXT); + + /* FIXME - we need to trap errors and synchronize here because + * of ordering issues between the XPixmap destruction and the + * GLXPixmap destruction. + * + * If the X pixmap is destroyed, the GLX pixmap is destroyed as + * well immediately, and thus, when Cogl calls glXDestroyPixmap() + * it'll cause a BadDrawable error. + * + * this is technically a bug in the X server, which should not + * destroy either pixmaps until the call to glXDestroyPixmap(); so + * at some point we should revisit this code and remove the + * trap+sync after verifying that the destruction is indeed safe. + * + * for reference, see: + * http://bugzilla.clutter-project.org/show_bug.cgi?id=2324 + */ + _cogl_xlib_renderer_trap_errors (renderer, &trap_state); + glx_renderer->glXDestroyPixmap (xlib_renderer->xdpy, + glx_tex_pixmap->glx_pixmap); + XSync (xlib_renderer->xdpy, False); + _cogl_xlib_renderer_untrap_errors (renderer, &trap_state); + + glx_tex_pixmap->glx_pixmap = None; + glx_tex_pixmap->left.pixmap_bound = FALSE; + glx_tex_pixmap->right.pixmap_bound = FALSE; +} + +static void +_cogl_winsys_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap) +{ + CoglTexturePixmapGLX *glx_tex_pixmap; + + if (!tex_pixmap->winsys) + return; + + glx_tex_pixmap = tex_pixmap->winsys; + + free_glx_pixmap (COGL_TEXTURE (tex_pixmap)->context, glx_tex_pixmap); + + if (glx_tex_pixmap->left.glx_tex) + cogl_object_unref (glx_tex_pixmap->left.glx_tex); + + if (glx_tex_pixmap->right.glx_tex) + cogl_object_unref (glx_tex_pixmap->right.glx_tex); + + tex_pixmap->winsys = NULL; + g_free (glx_tex_pixmap); +} + +static CoglBool +_cogl_winsys_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap, + CoglTexturePixmapStereoMode stereo_mode, + CoglBool needs_mipmap) +{ + CoglTexture *tex = COGL_TEXTURE (tex_pixmap); + CoglContext *ctx = COGL_TEXTURE (tex_pixmap)->context; + CoglTexturePixmapGLX *glx_tex_pixmap = tex_pixmap->winsys; + CoglPixmapTextureEyeGLX *texture_info; + int buffer; + CoglGLXRenderer *glx_renderer; + + if (stereo_mode == COGL_TEXTURE_PIXMAP_RIGHT) + { + texture_info = &glx_tex_pixmap->right; + buffer = GLX_FRONT_RIGHT_EXT; + } + else + { + texture_info = &glx_tex_pixmap->left; + buffer = GLX_FRONT_LEFT_EXT; + } + + /* If we don't have a GLX pixmap then fallback */ + if (glx_tex_pixmap->glx_pixmap == None) + return FALSE; + + glx_renderer = ctx->display->renderer->winsys; + + /* Lazily create a texture to hold the pixmap */ + if (texture_info->glx_tex == NULL) + { + CoglPixelFormat texture_format; + CoglError *error = NULL; + + texture_format = (tex_pixmap->depth >= 32 ? + COGL_PIXEL_FORMAT_RGBA_8888_PRE : + COGL_PIXEL_FORMAT_RGB_888); + + if (should_use_rectangle (ctx)) + { + texture_info->glx_tex = COGL_TEXTURE ( + cogl_texture_rectangle_new_with_size (ctx, + tex->width, + tex->height)); + + _cogl_texture_set_internal_format (tex, texture_format); + + if (cogl_texture_allocate (texture_info->glx_tex, &error)) + COGL_NOTE (TEXTURE_PIXMAP, "Created a texture rectangle for %p", + tex_pixmap); + else + { + COGL_NOTE (TEXTURE_PIXMAP, "Falling back for %p because a " + "texture rectangle could not be created: %s", + tex_pixmap, error->message); + cogl_error_free (error); + free_glx_pixmap (ctx, glx_tex_pixmap); + return FALSE; + } + } + else + { + texture_info->glx_tex = COGL_TEXTURE ( + cogl_texture_2d_new_with_size (ctx, + tex->width, + tex->height)); + + _cogl_texture_set_internal_format (tex, texture_format); + + if (cogl_texture_allocate (texture_info->glx_tex, &error)) + COGL_NOTE (TEXTURE_PIXMAP, "Created a texture 2d for %p", + tex_pixmap); + else + { + COGL_NOTE (TEXTURE_PIXMAP, "Falling back for %p because a " + "texture 2d could not be created: %s", + tex_pixmap, error->message); + cogl_error_free (error); + free_glx_pixmap (ctx, glx_tex_pixmap); + return FALSE; + } + } + } + + if (needs_mipmap) + { + /* If we can't support mipmapping then temporarily fallback */ + if (!glx_tex_pixmap->can_mipmap) + return FALSE; + + /* Recreate the GLXPixmap if it wasn't previously created with a + * mipmap tree */ + if (!glx_tex_pixmap->has_mipmap_space) + { + free_glx_pixmap (ctx, glx_tex_pixmap); + + COGL_NOTE (TEXTURE_PIXMAP, "Recreating GLXPixmap with mipmap " + "support for %p", tex_pixmap); + if (!try_create_glx_pixmap (ctx, tex_pixmap, TRUE)) + + { + /* If the pixmap failed then we'll permanently fallback + * to using XImage. This shouldn't happen. */ + COGL_NOTE (TEXTURE_PIXMAP, "Falling back to XGetImage " + "updates for %p because creating the GLXPixmap " + "with mipmap support failed", tex_pixmap); + + if (texture_info->glx_tex) + cogl_object_unref (texture_info->glx_tex); + return FALSE; + } + + glx_tex_pixmap->left.bind_tex_image_queued = TRUE; + glx_tex_pixmap->right.bind_tex_image_queued = TRUE; + } + } + + if (texture_info->bind_tex_image_queued) + { + GLuint gl_handle, gl_target; + CoglXlibRenderer *xlib_renderer = + _cogl_xlib_renderer_get_data (ctx->display->renderer); + + cogl_texture_get_gl_texture (texture_info->glx_tex, + &gl_handle, &gl_target); + + COGL_NOTE (TEXTURE_PIXMAP, "Rebinding GLXPixmap for %p", tex_pixmap); + + _cogl_bind_gl_texture_transient (gl_target, gl_handle, FALSE); + + if (texture_info->pixmap_bound) + glx_renderer->glXReleaseTexImage (xlib_renderer->xdpy, + glx_tex_pixmap->glx_pixmap, + buffer); + + glx_renderer->glXBindTexImage (xlib_renderer->xdpy, + glx_tex_pixmap->glx_pixmap, + buffer, + NULL); + + /* According to the recommended usage in the spec for + * GLX_EXT_texture_pixmap we should release the texture after + * we've finished drawing with it and it is undefined what + * happens if you render to a pixmap that is bound to a texture. + * However that would require the texture backend to know when + * Cogl has finished painting and it may be more expensive to + * keep unbinding the texture. Leaving it bound appears to work + * on Mesa and NVidia drivers and it is also what Compiz does so + * it is probably ok */ + + texture_info->bind_tex_image_queued = FALSE; + texture_info->pixmap_bound = TRUE; + + _cogl_texture_2d_externally_modified (texture_info->glx_tex); + } + + return TRUE; +} + +static void +_cogl_winsys_texture_pixmap_x11_damage_notify (CoglTexturePixmapX11 *tex_pixmap) +{ + CoglTexturePixmapGLX *glx_tex_pixmap = tex_pixmap->winsys; + + glx_tex_pixmap->left.bind_tex_image_queued = TRUE; + glx_tex_pixmap->right.bind_tex_image_queued = TRUE; +} + +static CoglTexture * +_cogl_winsys_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap, + CoglTexturePixmapStereoMode stereo_mode) +{ + CoglTexturePixmapGLX *glx_tex_pixmap = tex_pixmap->winsys; + + if (stereo_mode == COGL_TEXTURE_PIXMAP_RIGHT) + return glx_tex_pixmap->right.glx_tex; + else + return glx_tex_pixmap->left.glx_tex; +} + +static CoglWinsysVtable _cogl_winsys_vtable = + { + .id = COGL_WINSYS_ID_GLX, + .name = "GLX", + .constraints = (COGL_RENDERER_CONSTRAINT_USES_X11 | + COGL_RENDERER_CONSTRAINT_USES_XLIB), + + .renderer_get_proc_address = _cogl_winsys_renderer_get_proc_address, + .renderer_connect = _cogl_winsys_renderer_connect, + .renderer_disconnect = _cogl_winsys_renderer_disconnect, + .renderer_outputs_changed = _cogl_winsys_renderer_outputs_changed, + .display_setup = _cogl_winsys_display_setup, + .display_destroy = _cogl_winsys_display_destroy, + .context_init = _cogl_winsys_context_init, + .context_deinit = _cogl_winsys_context_deinit, + .context_get_clock_time = _cogl_winsys_get_clock_time, + .onscreen_init = _cogl_winsys_onscreen_init, + .onscreen_deinit = _cogl_winsys_onscreen_deinit, + .onscreen_bind = _cogl_winsys_onscreen_bind, + .onscreen_swap_buffers_with_damage = + _cogl_winsys_onscreen_swap_buffers_with_damage, + .onscreen_swap_region = _cogl_winsys_onscreen_swap_region, + .onscreen_get_buffer_age = _cogl_winsys_onscreen_get_buffer_age, + .onscreen_update_swap_throttled = + _cogl_winsys_onscreen_update_swap_throttled, + .onscreen_x11_get_window_xid = + _cogl_winsys_onscreen_x11_get_window_xid, + .onscreen_set_visibility = _cogl_winsys_onscreen_set_visibility, + .onscreen_set_resizable = + _cogl_winsys_onscreen_set_resizable, + + /* X11 tfp support... */ + /* XXX: instead of having a rather monolithic winsys vtable we could + * perhaps look for a way to separate these... */ + .texture_pixmap_x11_create = + _cogl_winsys_texture_pixmap_x11_create, + .texture_pixmap_x11_free = + _cogl_winsys_texture_pixmap_x11_free, + .texture_pixmap_x11_update = + _cogl_winsys_texture_pixmap_x11_update, + .texture_pixmap_x11_damage_notify = + _cogl_winsys_texture_pixmap_x11_damage_notify, + .texture_pixmap_x11_get_texture = + _cogl_winsys_texture_pixmap_x11_get_texture, + }; + +/* XXX: we use a function because no doubt someone will complain + * about using c99 member initializers because they aren't portable + * to windows. We want to avoid having to rigidly follow the real + * order of members since some members are #ifdefd and we'd have + * to mirror the #ifdefing to add padding etc. For any winsys that + * can assume the platform has a sane compiler then we can just use + * c99 initializers for insane platforms they can initialize + * the members by name in a function. + */ +const CoglWinsysVtable * +_cogl_winsys_glx_get_vtable (void) +{ + return &_cogl_winsys_vtable; +} + +GLXContext +cogl_glx_context_get_glx_context (CoglContext *context) +{ + CoglGLXDisplay *glx_display = context->display->winsys; + + return glx_display->glx_context; +} diff --git a/cogl/cogl/winsys/cogl-winsys-private.h b/cogl/cogl/winsys/cogl-winsys-private.h new file mode 100644 index 0000000..a8e07a5 --- /dev/null +++ b/cogl/cogl/winsys/cogl-winsys-private.h @@ -0,0 +1,198 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_WINSYS_PRIVATE_H +#define __COGL_WINSYS_PRIVATE_H + +#include "cogl-renderer.h" +#include "cogl-onscreen.h" +#include "cogl-gles2.h" + +#ifdef COGL_HAS_XLIB_SUPPORT +#include "cogl-texture-pixmap-x11-private.h" +#endif + +#ifdef COGL_HAS_XLIB_SUPPORT +#include +#include "cogl-texture-pixmap-x11-private.h" +#endif + +#ifdef COGL_HAS_EGL_SUPPORT +#include "cogl-egl-private.h" +#endif + +#include "cogl-poll.h" + +uint32_t +_cogl_winsys_error_quark (void); + +#define COGL_WINSYS_ERROR (_cogl_winsys_error_quark ()) + +typedef enum { /*< prefix=COGL_WINSYS_ERROR >*/ + COGL_WINSYS_ERROR_INIT, + COGL_WINSYS_ERROR_CREATE_CONTEXT, + COGL_WINSYS_ERROR_CREATE_ONSCREEN, + COGL_WINSYS_ERROR_MAKE_CURRENT, + COGL_WINSYS_ERROR_CREATE_GLES2_CONTEXT, +} CoglWinsysError; + +typedef enum +{ + COGL_WINSYS_RECTANGLE_STATE_UNKNOWN, + COGL_WINSYS_RECTANGLE_STATE_DISABLE, + COGL_WINSYS_RECTANGLE_STATE_ENABLE +} CoglWinsysRectangleState; + +typedef struct _CoglWinsysVtable +{ + CoglWinsysID id; + CoglRendererConstraint constraints; + + const char *name; + + /* Required functions */ + + CoglFuncPtr + (*renderer_get_proc_address) (CoglRenderer *renderer, + const char *name, + CoglBool in_core); + + CoglBool + (*renderer_connect) (CoglRenderer *renderer, CoglError **error); + + void + (*renderer_disconnect) (CoglRenderer *renderer); + + void + (*renderer_outputs_changed) (CoglRenderer *renderer); + + CoglBool + (*display_setup) (CoglDisplay *display, CoglError **error); + + void + (*display_destroy) (CoglDisplay *display); + + CoglBool + (*context_init) (CoglContext *context, CoglError **error); + + void + (*context_deinit) (CoglContext *context); + + void * + (*context_create_gles2_context) (CoglContext *ctx, CoglError **error); + + CoglBool + (*onscreen_init) (CoglOnscreen *onscreen, CoglError **error); + + void + (*onscreen_deinit) (CoglOnscreen *onscreen); + + void + (*onscreen_bind) (CoglOnscreen *onscreen); + + void + (*onscreen_swap_buffers_with_damage) (CoglOnscreen *onscreen, + const int *rectangles, + int n_rectangles); + + void + (*onscreen_update_swap_throttled) (CoglOnscreen *onscreen); + + void + (*onscreen_set_visibility) (CoglOnscreen *onscreen, + CoglBool visibility); + + /* Optional functions */ + + int64_t + (*context_get_clock_time) (CoglContext *context); + + void + (*onscreen_swap_region) (CoglOnscreen *onscreen, + const int *rectangles, + int n_rectangles); + + void + (*onscreen_set_resizable) (CoglOnscreen *onscreen, CoglBool resizable); + + int + (*onscreen_get_buffer_age) (CoglOnscreen *onscreen); + + uint32_t + (*onscreen_x11_get_window_xid) (CoglOnscreen *onscreen); + +#ifdef COGL_HAS_XLIB_SUPPORT + CoglBool + (*texture_pixmap_x11_create) (CoglTexturePixmapX11 *tex_pixmap); + void + (*texture_pixmap_x11_free) (CoglTexturePixmapX11 *tex_pixmap); + + CoglBool + (*texture_pixmap_x11_update) (CoglTexturePixmapX11 *tex_pixmap, + CoglTexturePixmapStereoMode stereo_mode, + CoglBool needs_mipmap); + + void + (*texture_pixmap_x11_damage_notify) (CoglTexturePixmapX11 *tex_pixmap); + + CoglTexture * + (*texture_pixmap_x11_get_texture) (CoglTexturePixmapX11 *tex_pixmap, + CoglTexturePixmapStereoMode stereo_mode); +#endif + + void + (*save_context) (CoglContext *ctx); + + CoglBool + (*set_gles2_context) (CoglGLES2Context *gles2_ctx, CoglError **error); + + void + (*restore_context) (CoglContext *ctx); + + void + (*destroy_gles2_context) (CoglGLES2Context *gles2_ctx); + + void * + (*fence_add) (CoglContext *ctx); + + CoglBool + (*fence_is_complete) (CoglContext *ctx, void *fence); + + void + (*fence_destroy) (CoglContext *ctx, void *fence); + +} CoglWinsysVtable; + +typedef const CoglWinsysVtable *(*CoglWinsysVtableGetter) (void); + +CoglBool +_cogl_winsys_has_feature (CoglWinsysFeature feature); + +#endif /* __COGL_WINSYS_PRIVATE_H */ diff --git a/cogl/cogl/winsys/cogl-winsys-stub-private.h b/cogl/cogl/winsys/cogl-winsys-stub-private.h new file mode 100644 index 0000000..4aaf798 --- /dev/null +++ b/cogl/cogl/winsys/cogl-winsys-stub-private.h @@ -0,0 +1,37 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifndef __COGL_WINSYS_STUB_PRIVATE_H +#define __COGL_WINSYS_STUB_PRIVATE_H + +const CoglWinsysVtable * +_cogl_winsys_stub_get_vtable (void); + +#endif /* __COGL_WINSYS_STUB_PRIVATE_H */ diff --git a/cogl/cogl/winsys/cogl-winsys-stub.c b/cogl/cogl/winsys/cogl-winsys-stub.c new file mode 100644 index 0000000..ba49a94 --- /dev/null +++ b/cogl/cogl/winsys/cogl-winsys-stub.c @@ -0,0 +1,197 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + * Authors: + * Robert Bragg + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-renderer-private.h" +#include "cogl-display-private.h" +#include "cogl-context-private.h" +#include "cogl-framebuffer-private.h" +#include "cogl-private.h" +#include "cogl-winsys-stub-private.h" + +#include + +static int _cogl_winsys_stub_dummy_ptr; + +/* This provides a NOP winsys. This can be useful for debugging or for + * integrating with toolkits that already have window system + * integration code. + */ + +static CoglFuncPtr +_cogl_winsys_renderer_get_proc_address (CoglRenderer *renderer, + const char *name, + CoglBool in_core) +{ + static GModule *module = NULL; + + /* this should find the right function if the program is linked against a + * library providing it */ + if (G_UNLIKELY (module == NULL)) + module = g_module_open (NULL, 0); + + if (module) + { + void *symbol; + + if (g_module_symbol (module, name, &symbol)) + return symbol; + } + + return NULL; +} + +static void +_cogl_winsys_renderer_disconnect (CoglRenderer *renderer) +{ + renderer->winsys = NULL; +} + +static CoglBool +_cogl_winsys_renderer_connect (CoglRenderer *renderer, + CoglError **error) +{ + renderer->winsys = &_cogl_winsys_stub_dummy_ptr; + return TRUE; +} + +static void +_cogl_winsys_display_destroy (CoglDisplay *display) +{ + display->winsys = NULL; +} + +static CoglBool +_cogl_winsys_display_setup (CoglDisplay *display, + CoglError **error) +{ + display->winsys = &_cogl_winsys_stub_dummy_ptr; + return TRUE; +} + +static CoglBool +_cogl_winsys_context_init (CoglContext *context, CoglError **error) +{ + context->winsys = &_cogl_winsys_stub_dummy_ptr; + + if (!_cogl_context_update_features (context, error)) + return FALSE; + + memset (context->winsys_features, 0, sizeof (context->winsys_features)); + + return TRUE; +} + +static void +_cogl_winsys_context_deinit (CoglContext *context) +{ + context->winsys = NULL; +} + +static CoglBool +_cogl_winsys_onscreen_init (CoglOnscreen *onscreen, + CoglError **error) +{ + return TRUE; +} + +static void +_cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen) +{ +} + +static void +_cogl_winsys_onscreen_bind (CoglOnscreen *onscreen) +{ +} + +static void +_cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen, + const int *rectangles, + int n_rectangles) +{ +} + +static void +_cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen) +{ +} + +static void +_cogl_winsys_onscreen_set_visibility (CoglOnscreen *onscreen, + CoglBool visibility) +{ +} + +const CoglWinsysVtable * +_cogl_winsys_stub_get_vtable (void) +{ + static CoglBool vtable_inited = FALSE; + static CoglWinsysVtable vtable; + + /* It would be nice if we could use C99 struct initializers here + like the GLX backend does. However this code is more likely to be + compiled using Visual Studio which (still!) doesn't support them + so we initialize it in code instead */ + + if (!vtable_inited) + { + memset (&vtable, 0, sizeof (vtable)); + + vtable.id = COGL_WINSYS_ID_STUB; + vtable.name = "STUB"; + vtable.renderer_get_proc_address = _cogl_winsys_renderer_get_proc_address; + vtable.renderer_connect = _cogl_winsys_renderer_connect; + vtable.renderer_disconnect = _cogl_winsys_renderer_disconnect; + vtable.display_setup = _cogl_winsys_display_setup; + vtable.display_destroy = _cogl_winsys_display_destroy; + vtable.context_init = _cogl_winsys_context_init; + vtable.context_deinit = _cogl_winsys_context_deinit; + + vtable.onscreen_init = _cogl_winsys_onscreen_init; + vtable.onscreen_deinit = _cogl_winsys_onscreen_deinit; + vtable.onscreen_bind = _cogl_winsys_onscreen_bind; + vtable.onscreen_swap_buffers_with_damage = + _cogl_winsys_onscreen_swap_buffers_with_damage; + vtable.onscreen_update_swap_throttled = + _cogl_winsys_onscreen_update_swap_throttled; + vtable.onscreen_set_visibility = _cogl_winsys_onscreen_set_visibility; + + vtable_inited = TRUE; + } + + return &vtable; +} diff --git a/cogl/cogl/winsys/cogl-winsys.c b/cogl/cogl/winsys/cogl-winsys.c new file mode 100644 index 0000000..b0a7b68 --- /dev/null +++ b/cogl/cogl/winsys/cogl-winsys.c @@ -0,0 +1,52 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2010 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "cogl-config.h" +#endif + +#include "cogl-context-private.h" + +#include + +uint32_t +_cogl_winsys_error_quark (void) +{ + return g_quark_from_static_string ("cogl-winsys-error-quark"); +} + +/* FIXME: we should distinguish renderer and context features */ +CoglBool +_cogl_winsys_has_feature (CoglWinsysFeature feature) +{ + _COGL_GET_CONTEXT (ctx, FALSE); + + return COGL_FLAGS_GET (ctx->winsys_features, feature); +} diff --git a/cogl/config-custom.h b/cogl/config-custom.h new file mode 100644 index 0000000..08fb9a4 --- /dev/null +++ b/cogl/config-custom.h @@ -0,0 +1,32 @@ +/* + * Cogl + * + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* The contents of this file get #included by config.h so it is + intended for extra configuration that needs to be included by all + Cogl source files. */ + diff --git a/cogl/configure b/cogl/configure new file mode 100755 index 0000000..85ca51f --- /dev/null +++ b/cogl/configure @@ -0,0 +1,24416 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for cogl 1.22.1. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1 + + test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + +SHELL=${CONFIG_SHELL-/bin/sh} + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='cogl' +PACKAGE_TARNAME='cogl' +PACKAGE_VERSION='1.22.1' +PACKAGE_STRING='cogl 1.22.1' +PACKAGE_BUGREPORT='' +PACKAGE_URL='' + +ac_unique_file="cogl/cogl.h" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +LIBOBJS +MAINTAINER_CFLAGS +COGL_EXTRA_LDFLAGS +COGL_EXTRA_CFLAGS +COGL_GST_DEP_LIBS +COGL_GST_DEP_CFLAGS +COGL_GL_HEADER_INCLUDES +COGL_DEFINES +XMKMF +HAVE_INTROSPECTION_FALSE +HAVE_INTROSPECTION_TRUE +INTROSPECTION_MAKEFILE +INTROSPECTION_LIBS +INTROSPECTION_CFLAGS +INTROSPECTION_TYPELIBDIR +INTROSPECTION_GIRDIR +INTROSPECTION_GENERATE +INTROSPECTION_COMPILER +INTROSPECTION_SCANNER +BUILD_COGL_PATH_FALSE +BUILD_COGL_PATH_TRUE +BUILD_COGL_PANGO_FALSE +BUILD_COGL_PANGO_TRUE +COGL_PANGO_DEP_LIBS +COGL_PANGO_DEP_CFLAGS +COGL_PANGO_PKG_REQUIRES +COGL_DEP_GL_LIBS +COGL_DEP_GL_CFLAGS +COGL_DEP_LIBS +COGL_DEP_CFLAGS +COGL_PKG_REQUIRES +GDKPIXBUF_PREFIX +GLIB_PREFIX +SUPPORT_XLIB_FALSE +SUPPORT_XLIB_TRUE +SUPPORT_X11_FALSE +SUPPORT_X11_TRUE +X11_TESTS_FALSE +X11_TESTS_TRUE +DUMMY_LIBS +DUMMY_CFLAGS +SUPPORT_EGL_FALSE +SUPPORT_EGL_TRUE +SUPPORT_EGL_PLATFORM_XLIB_FALSE +SUPPORT_EGL_PLATFORM_XLIB_TRUE +SUPPORT_WAYLAND_EGL_SERVER_FALSE +SUPPORT_WAYLAND_EGL_SERVER_TRUE +WAYLAND_SERVER_LIBS +WAYLAND_SERVER_CFLAGS +SUPPORT_EGL_PLATFORM_KMS_FALSE +SUPPORT_EGL_PLATFORM_KMS_TRUE +SUPPORT_GLX_FALSE +SUPPORT_GLX_TRUE +BUILD_COGL_GLES2_FALSE +BUILD_COGL_GLES2_TRUE +COGL_DEFAULT_DRIVER +HAVE_GLES2 +COGL_GLES2_LIBNAME +HAVE_GLES1 +COGL_GLES1_LIBNAME +HAVE_GL +COGL_GL_LIBNAME +HAVE_COGL_DEFAULT_DRIVER_FALSE +HAVE_COGL_DEFAULT_DRIVER_TRUE +COGL_DRIVER_GLES_SUPPORTED_FALSE +COGL_DRIVER_GLES_SUPPORTED_TRUE +COGL_DRIVER_GL_SUPPORTED_FALSE +COGL_DRIVER_GL_SUPPORTED_TRUE +COGL_EGL_INCLUDES +GLIB_COMPILE_RESOURCES +GLIB_MKENUMS +GOBJECT_QUERY +GLIB_GENMARSHAL +GLIB_LIBS +GLIB_CFLAGS +PROFILE_FALSE +PROFILE_TRUE +PKG_CONFIG_LIBDIR +PKG_CONFIG_PATH +PKG_CONFIG +UNIT_TESTS_FALSE +UNIT_TESTS_TRUE +COGL_DEBUG_CFLAGS +ENABLE_INSTALLED_TESTS_FALSE +ENABLE_INSTALLED_TESTS_TRUE +LIBM +CXXCPP +LT_SYS_LIBRARY_PATH +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +MANIFEST_TOOL +RANLIB +ac_ct_AR +AR +DLLTOOL +OBJDUMP +LN_S +NM +ac_ct_DUMPBIN +DUMPBIN +LD +FGREP +SED +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +LIBTOOL +am__fastdepCXX_FALSE +am__fastdepCXX_TRUE +CXXDEPMODE +ac_ct_CXX +CXXFLAGS +CXX +COGL_RELEASE_STATUS +COGL_LT_RELEASE +COGL_LT_AGE +COGL_LT_REVISION +COGL_LT_CURRENT +COGL_1_VERSION +COGL_1_MICRO_VERSION +COGL_1_MINOR_VERSION +COGL_API_VERSION_AM +COGL_API_VERSION +COGL_VERSION +COGL_MICRO_VERSION +COGL_MINOR_VERSION +COGL_MAJOR_VERSION +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +AM_DEFAULT_V +AM_V +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +am__nodep +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +WAYLAND_SERVER_REQ_VERSION +UPROF_REQ_VERSION +GI_REQ_VERSION +XFIXES_REQ_VERSION +XCOMPOSITE_REQ_VERSION +PANGOCAIRO_REQ_VERSION +CAIRO_REQ_VERSION +GDK_PIXBUF_REQ_VERSION +GLIB_REQ_VERSION +EGREP +GREP +CPP +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_dependency_tracking +enable_silent_rules +enable_static +enable_shared +with_pic +enable_fast_install +with_aix_soname +with_gnu_ld +with_sysroot +enable_libtool_lock +enable_installed_tests +enable_debug +enable_unit_tests +enable_cairo +enable_profile +enable_maintainer_flags +enable_deprecated +enable_glibtest +enable_cogl_pango +enable_cogl_path +enable_gles1 +enable_gles2 +enable_gl +with_gl_libname +with_gles1_libname +with_gles2_libname +with_default_driver +enable_cogl_gles2 +enable_glx +enable_kms_egl_platform +enable_wayland_egl_server +enable_xlib_egl_platform +enable_introspection +with_x +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP +CXX +CXXFLAGS +CCC +LT_SYS_LIBRARY_PATH +CXXCPP +PKG_CONFIG +PKG_CONFIG_PATH +PKG_CONFIG_LIBDIR +WAYLAND_SERVER_CFLAGS +WAYLAND_SERVER_LIBS +DUMMY_CFLAGS +DUMMY_LIBS +COGL_DEP_CFLAGS +COGL_DEP_LIBS +COGL_DEP_GL_CFLAGS +COGL_DEP_GL_LIBS +COGL_PANGO_DEP_CFLAGS +COGL_PANGO_DEP_LIBS +XMKMF' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures cogl 1.22.1 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/cogl] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +X features: + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of cogl 1.22.1:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-dependency-tracking + do not reject slow dependency extractors + --disable-dependency-tracking + speeds up one-time build + --enable-silent-rules less verbose build output (undo: "make V=1") + --disable-silent-rules verbose build output (undo: "make V=0") + --enable-static[=PKGS] build static libraries [default=no] + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + --enable-installed-tests + Install test programs (default: no) + --enable-debug=[no/yes] Control Cogl debugging level [default=yes] + --enable-unit-tests=[no/yes] + Build Cogl unit tests [default=yes] + --enable-cairo=[no/yes] Control Cairo usage in Cogl debugging code + [default=auto] + --enable-profile=[no/yes] + Turn on uprof profiling support. yes; All UProf + profiling probe points are compiled in and may be + runtime enabled. no; No profiling support will built + into cogl. [default=no] + --enable-maintainer-flags=[no/yes/error] + Use strict compiler flags [default=yes] + --enable-deprecated=[no/yes] + Whether deprecated symbols should be disabled when + compiling Cogl [default=no] + --disable-glibtest do not try to compile and run a test GLIB program + --enable-cogl-pango=[no/yes] + Enable pango support [default=yes] + --enable-cogl-path=[no/yes] + Enable 2D path support [default=yes] + --enable-gles1=[no/yes] Enable support for OpenGL-ES 1.1 [default=no] + --enable-gles2=[no/yes] Enable support for OpenGL-ES 2.0 [default=no] + --enable-gl=[no/yes] Enable support for OpenGL [default=yes] + --enable-cogl-gles2=[no/yes] + Enable libcogl-gles2 frontend api for OpenGL-ES 2.0 + [default=auto] + --enable-glx=[no/yes] Enable support GLX [default=auto] + --enable-kms-egl-platform=[no/yes] + Enable support for the KMS egl platform [default=no] + --enable-wayland-egl-server=[no/yes] + Enable server side wayland support [default=no] + --enable-xlib-egl-platform=[no/yes] + Enable support for the Xlib egl platform + [default=auto] + --enable-introspection=[no/auto/yes] + Enable introspection for this build + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use + both] + --with-aix-soname=aix|svr4|both + shared library versioning (aka "SONAME") variant to + provide on AIX, [default=aix]. + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-sysroot[=DIR] Search for dependent libraries within DIR (or the + compiler's sysroot if not specified). + --with-gl-libname override the name of the GL library to dlopen + --with-gles1-libname override the name of the GLESv1 library to dlopen + --with-gles2-libname override the name of the GLESv2 library to dlopen + --with-default-driver specify a default cogl driver + --with-x use the X Window System + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + CXX C++ compiler command + CXXFLAGS C++ compiler flags + LT_SYS_LIBRARY_PATH + User-defined run-time library search path. + CXXCPP C++ preprocessor + PKG_CONFIG path to pkg-config utility + PKG_CONFIG_PATH + directories to add to pkg-config's search path + PKG_CONFIG_LIBDIR + path overriding pkg-config's built-in search path + WAYLAND_SERVER_CFLAGS + C compiler flags for WAYLAND_SERVER, overriding pkg-config + WAYLAND_SERVER_LIBS + linker flags for WAYLAND_SERVER, overriding pkg-config + DUMMY_CFLAGS + C compiler flags for DUMMY, overriding pkg-config + DUMMY_LIBS linker flags for DUMMY, overriding pkg-config + COGL_DEP_CFLAGS + C compiler flags for COGL_DEP, overriding pkg-config + COGL_DEP_LIBS + linker flags for COGL_DEP, overriding pkg-config + COGL_DEP_GL_CFLAGS + C compiler flags for COGL_DEP_GL, overriding pkg-config + COGL_DEP_GL_LIBS + linker flags for COGL_DEP_GL, overriding pkg-config + COGL_PANGO_DEP_CFLAGS + C compiler flags for COGL_PANGO_DEP, overriding pkg-config + COGL_PANGO_DEP_LIBS + linker flags for COGL_PANGO_DEP, overriding pkg-config + XMKMF Path to xmkmf, Makefile generator for X Window System + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +cogl configure 1.22.1 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_cxx_try_compile LINENO +# ---------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_cxx_try_cpp LINENO +# ------------------------ +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_cpp + +# ac_fn_cxx_try_link LINENO +# ------------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_link + +# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES +# --------------------------------------------- +# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR +# accordingly. +ac_fn_c_check_decl () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + as_decl_name=`echo $2|sed 's/ *(.*//'` + as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 +$as_echo_n "checking whether $as_decl_name is declared... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +#ifndef $as_decl_name +#ifdef __cplusplus + (void) $as_decl_use; +#else + (void) $as_decl_name; +#endif +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_decl + +# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES +# -------------------------------------------- +# Tries to find the compile-time value of EXPR in a program that includes +# INCLUDES, setting VAR accordingly. Returns whether the value could be +# computed +ac_fn_c_compute_int () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= 0)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=0 ac_mid=0 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid; break +else + as_fn_arith $ac_mid + 1 && ac_lo=$as_val + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) < 0)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=-1 ac_mid=-1 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=$ac_mid; break +else + as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + ac_lo= ac_hi= +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid +else + as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in #(( +?*) eval "$3=\$ac_lo"; ac_retval=0 ;; +'') ac_retval=1 ;; +esac + else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +static long int longval () { return $2; } +static unsigned long int ulongval () { return $2; } +#include +#include +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + return 1; + if (($2) < 0) + { + long int i = longval (); + if (i != ($2)) + return 1; + fprintf (f, "%ld", i); + } + else + { + unsigned long int i = ulongval (); + if (i != ($2)) + return 1; + fprintf (f, "%lu", i); + } + /* Do not output a trailing newline, as this causes \r\n confusion + on some platforms. */ + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + echo >>conftest.val; read $3 config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by cogl $as_me 1.22.1, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +ac_aux_dir= +for ac_dir in build "$srcdir"/build; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in build \"$srcdir\"/build" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + + +ac_config_headers="$ac_config_headers cogl-config.h" + +ac_config_headers="$ac_config_headers cogl-mutter-config.h" + +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default" +if test "x$ac_cv_header_minix_config_h" = xyes; then : + MINIX=yes +else + MINIX= +fi + + + if test "$MINIX" = yes; then + +$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h + + +$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h + + +$as_echo "#define _MINIX 1" >>confdefs.h + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5 +$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; } +if ${ac_cv_safe_to_define___extensions__+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +# define __EXTENSIONS__ 1 + $ac_includes_default +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_safe_to_define___extensions__=yes +else + ac_cv_safe_to_define___extensions__=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5 +$as_echo "$ac_cv_safe_to_define___extensions__" >&6; } + test $ac_cv_safe_to_define___extensions__ = yes && + $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h + + $as_echo "#define _ALL_SOURCE 1" >>confdefs.h + + $as_echo "#define _GNU_SOURCE 1" >>confdefs.h + + $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h + + $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h + + + + + + + + + + + + + + + + +GLIB_REQ_VERSION=2.32.0 + +GDK_PIXBUF_REQ_VERSION=2.0 + +CAIRO_REQ_VERSION=1.10 + +PANGOCAIRO_REQ_VERSION=1.20 + +XCOMPOSITE_REQ_VERSION=0.4 + +XFIXES_REQ_VERSION=3 + +GI_REQ_VERSION=0.9.5 + +UPROF_REQ_VERSION=0.3 + +WAYLAND_SERVER_REQ_VERSION=1.1.90 + + +# Save this value here, since automake will set cflags later and we +# want to know if the user specified custom cflags or not. +cflags_set=${CFLAGS+set} + +am__api_version='1.15' + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi + +rm -f conftest.file + +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 +$as_echo_n "checking for style of include used by $am_make... " >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 +$as_echo "$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=1;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='cogl' + VERSION='1.22.1' + + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +mkdir_p='$(MKDIR_P)' + +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar plaintar pax cpio none' + +# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether UID '$am_uid' is supported by ustar format" >&5 +$as_echo_n "checking whether UID '$am_uid' is supported by ustar format... " >&6; } + if test $am_uid -le $am_max_uid; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + _am_tools=none + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GID '$am_gid' is supported by ustar format" >&5 +$as_echo_n "checking whether GID '$am_gid' is supported by ustar format... " >&6; } + if test $am_gid -le $am_max_gid; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + _am_tools=none + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to create a ustar tar archive" >&5 +$as_echo_n "checking how to create a ustar tar archive... " >&6; } + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_ustar-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + { echo "$as_me:$LINENO: $_am_tar --version" >&5 + ($_am_tar --version) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && break + done + am__tar="$_am_tar --format=ustar -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=ustar -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x ustar -w "$$tardir"' + am__tar_='pax -L -x ustar -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H ustar -L' + am__tar_='find "$tardir" -print | cpio -o -H ustar -L' + am__untar='cpio -i -H ustar -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_ustar}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + { echo "$as_me:$LINENO: tardir=conftest.dir && eval $am__tar_ >conftest.tar" >&5 + (tardir=conftest.dir && eval $am__tar_ >conftest.tar) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + rm -rf conftest.dir + if test -s conftest.tar; then + { echo "$as_me:$LINENO: $am__untar &5 + ($am__untar &5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + { echo "$as_me:$LINENO: cat conftest.dir/file" >&5 + (cat conftest.dir/file) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + grep GrepMe conftest.dir/file >/dev/null 2>&1 && break + fi + done + rm -rf conftest.dir + + if ${am_cv_prog_tar_ustar+:} false; then : + $as_echo_n "(cached) " >&6 +else + am_cv_prog_tar_ustar=$_am_tool +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_tar_ustar" >&5 +$as_echo "$am_cv_prog_tar_ustar" >&6; } + + + + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 + fi +fi + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=0;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + + + + +COGL_MAJOR_VERSION=2 + +COGL_MINOR_VERSION=0 + +COGL_MICRO_VERSION=0 + +COGL_VERSION=2.0.0 + +COGL_API_VERSION=2.0 + +COGL_API_VERSION_AM=$COGL_MAJOR_VERSION\_0 + + +COGL_1_MINOR_VERSION=22 + +COGL_1_MICRO_VERSION=1 + +COGL_1_VERSION=1.22.1 + + + +COGL_LT_CURRENT=24 + +COGL_LT_REVISION=1 + +COGL_LT_AGE=4 + +COGL_LT_RELEASE=2.0.0 + + + +COGL_RELEASE_STATUS=git + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +$as_echo "$CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 +$as_echo "$ac_ct_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 +$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } +if ${ac_cv_cxx_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 +$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GXX=yes +else + GXX= +fi +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 +$as_echo_n "checking whether $CXX accepts -g... " >&6; } +if ${ac_cv_prog_cxx_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +else + CXXFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +else + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 +$as_echo "$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +depcc="$CXX" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CXX_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CXX_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CXX_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CXX_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } +CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then + am__fastdepCXX_TRUE= + am__fastdepCXX_FALSE='#' +else + am__fastdepCXX_TRUE='#' + am__fastdepCXX_FALSE= +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing strerror" >&5 +$as_echo_n "checking for library containing strerror... " >&6; } +if ${ac_cv_search_strerror+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char strerror (); +int +main () +{ +return strerror (); + ; + return 0; +} +_ACEOF +for ac_lib in '' cposix; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_strerror=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_strerror+:} false; then : + break +fi +done +if ${ac_cv_search_strerror+:} false; then : + +else + ac_cv_search_strerror=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_strerror" >&5 +$as_echo "$ac_cv_search_strerror" >&6; } +ac_res=$ac_cv_search_strerror +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 +$as_echo_n "checking for an ANSI C-conforming const... " >&6; } +if ${ac_cv_c_const+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#ifndef __cplusplus + /* Ultrix mips cc rejects this sort of thing. */ + typedef int charset[2]; + const charset cs = { 0, 0 }; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *pcpcc; + char **ppc; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + pcpcc = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++pcpcc; + ppc = (char**) pcpcc; + pcpcc = (char const *const *) ppc; + { /* SCO 3.2v4 cc rejects this sort of thing. */ + char tx; + char *t = &tx; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; } bx; + struct s *b = &bx; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !cs[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_const=yes +else + ac_cv_c_const=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 +$as_echo "$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +$as_echo "#define const /**/" >>confdefs.h + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _Static_assert" >&5 +$as_echo_n "checking for _Static_assert... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +_Static_assert (1, ""); +int +main () +{ +(void) 0 + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define HAVE_STATIC_ASSERT 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.4.6' +macro_revision='2.4.6' + + + + + + + + + + + + + +ltmain=$ac_aux_dir/ltmain.sh + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case $ECHO in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if ${ac_cv_path_FGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_FGREP" || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if ${lt_cv_path_NM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in dumpbin "link -dump" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if ${lt_cv_nm_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if ${lt_cv_sys_max_cmd_len+:} false; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n "$lt_cv_sys_max_cmd_len"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +$as_echo_n "checking how to convert $build file names to $host format... " >&6; } +if ${lt_cv_to_host_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac + +fi + +to_host_file_cmd=$lt_cv_to_host_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +$as_echo "$lt_cv_to_host_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } +if ${lt_cv_to_tool_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + #assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac + +fi + +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +$as_echo "$lt_cv_to_tool_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if ${lt_cv_ld_reload_flag+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test yes != "$GCC"; then + reload_cmds=false + fi + ;; + darwin*) + if test yes = "$GCC"; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if ${lt_cv_deplibs_check_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + + + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +$as_echo_n "checking how to associate runtime and link libraries... " >&6; } +if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + + + + + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} +: ${AR_FLAGS=cru} + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 +$as_echo_n "checking for archiver @FILE support... " >&6; } +if ${lt_cv_ar_at_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ar_at_file=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 +$as_echo "$lt_cv_ar_at_file" >&6; } + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if ${lt_cv_sys_global_symbol_pipe+:} false; then : + $as_echo_n "(cached) " >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[ABCDEGRST]' + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 +$as_echo_n "checking for sysroot... " >&6; } + +# Check whether --with-sysroot was given. +if test "${with_sysroot+set}" = set; then : + withval=$with_sysroot; +else + with_sysroot=no +fi + + +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 +$as_echo "$with_sysroot" >&6; } + as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 + ;; +esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 +$as_echo "${lt_sysroot:-no}" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 +$as_echo_n "checking for a working dd... " >&6; } +if ${ac_cv_path_lt_DD+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +if test -z "$lt_DD"; then + ac_path_lt_DD_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in dd; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_lt_DD" || continue +if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi + $ac_path_lt_DD_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_lt_DD"; then + : + fi +else + ac_cv_path_lt_DD=$lt_DD +fi + +rm -f conftest.i conftest2.i conftest.out +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 +$as_echo "$ac_cv_path_lt_DD" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 +$as_echo_n "checking how to truncate binary pipes... " >&6; } +if ${lt_cv_truncate_bin+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 +$as_echo "$lt_cv_truncate_bin" >&6; } + + + + + + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then : + enableval=$enable_libtool_lock; +fi + +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if ${lt_cv_cc_needs_belf+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$lt_cv_cc_needs_belf" >&6; } + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. +set dummy ${ac_tool_prefix}mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MANIFEST_TOOL"; then + ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL +if test -n "$MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 +$as_echo "$MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_MANIFEST_TOOL"; then + ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL + # Extract the first word of "mt", so it can be a program name with args. +set dummy mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_MANIFEST_TOOL"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL +if test -n "$ac_ct_MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 +$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_MANIFEST_TOOL" = x; then + MANIFEST_TOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL + fi +else + MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" +fi + +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 +$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } +if ${lt_cv_path_mainfest_tool+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&5 + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 +$as_echo "$lt_cv_path_mainfest_tool" >&6; } +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi + + + + + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_LIPO="lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL="otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if ${lt_cv_apple_cc_single_mod+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&5 + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if ${lt_cv_ld_exported_symbols_list+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if ${lt_cv_ld_force_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 + echo "$RANLIB libconftest.a" >&5 + $RANLIB libconftest.a 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&5 + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[012][,.]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + + +func_stripname_cnf () +{ + case $2 in + .*) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%\\\\$2\$%%"`;; + *) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%$2\$%%"`;; + esac +} # func_stripname_cnf + + + + + +# Set options +# Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_static=no +fi + + + + + + + + + + + enable_dlopen=no + + + enable_win32_dll=no + + + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + pic_mode=default +fi + + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_fast_install=yes +fi + + + + + + + + + shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[5-9]*,yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 +$as_echo_n "checking which variant of shared library versioning to provide... " >&6; } + +# Check whether --with-aix-soname was given. +if test "${with_aix_soname+set}" = set; then : + withval=$with_aix_soname; case $withval in + aix|svr4|both) + ;; + *) + as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname +else + if ${lt_cv_with_aix_soname+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_with_aix_soname=aix +fi + + with_aix_soname=$lt_cv_with_aix_soname +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 +$as_echo "$with_aix_soname" >&6; } + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if ${lt_cv_objdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +func_cc_basename $compiler +cc_basename=$func_cc_basename_result + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/${ac_tool_prefix}file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac +fi + +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac +fi + +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +lt_save_CC=$CC +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + + + + + + + lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + + + if test yes = "$GCC"; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + lt_prog_compiler_pic='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + if test -n "$lt_prog_compiler_pic"; then + lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + *Sun\ F* | *Sun*Fortran*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + *Intel*\ [CF]*Compiler*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + *Portland\ Group*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic=$lt_prog_compiler_pic +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 +$as_echo "$lt_cv_prog_compiler_pic" >&6; } +lt_prog_compiler_pic=$lt_cv_prog_compiler_pic + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if ${lt_cv_prog_compiler_pic_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test yes = "$lt_cv_prog_compiler_pic_works"; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi + + + + + + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test yes = "$lt_cv_prog_compiler_static_works"; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + +hard_links=nottested +if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test no = "$hard_links"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + esac + + ld_shlibs=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + export_dynamic_flag_spec='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='$wl--export-all-symbols' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + export_dynamic_flag_spec='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + ld_shlibs=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test no = "$ld_shlibs"; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix[4-9]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + hardcode_direct=no + hardcode_direct_absolute=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + export_dynamic_flag_spec='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' $wl-bernotok' + allow_undefined_flag=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi + archive_cmds_need_lc=yes + archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + always_export_symbols=yes + file_list_spec='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, )='true' + enable_shared_with_static_runtimes=yes + exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + old_postinstall_cmds='chmod 644 $oldlib' + postlink_cmds='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + enable_shared_with_static_runtimes=yes + ;; + esac + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + if test yes = "$lt_cv_ld_force_load"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + + else + whole_archive_flag_spec='' + fi + link_all_deplibs=yes + allow_undefined_flag=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + + else + ld_shlibs=no + fi + + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test yes = "$GCC"; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if ${lt_cv_prog_compiler__b+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -b" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test yes = "$lt_cv_prog_compiler__b"; then + archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +fi + + ;; + esac + fi + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 +$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } +if ${lt_cv_irix_exported_symbol+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo (void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_irix_exported_symbol=yes +else + lt_cv_irix_exported_symbol=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 +$as_echo "$lt_cv_irix_exported_symbol" >&6; } + if test yes = "$lt_cv_irix_exported_symbol"; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + link_all_deplibs=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + ld_shlibs=yes + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' + else + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + fi + else + ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + + osf3*) + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='$wl-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='$wl-z,text' + allow_undefined_flag='$wl-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='$wl-R,$libdir' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='$wl-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test no = "$ld_shlibs" && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([A-Za-z]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + + + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[4-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a(lib.so.V)' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[23].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + hardcode_libdir_flag_spec='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Add ABI-specific directories to the system library path. + sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test yes = "$hardcode_automatic"; then + + # We can hardcode non-existent directories. + if test no != "$hardcode_direct" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && + test no != "$hardcode_minus_L"; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test relink = "$hardcode_action" || + test yes = "$inherit_rpath"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else + + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : + lt_cv_dlopen=shl_load +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + lt_cv_dlopen=dlopen +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if ${ac_cv_lib_svld_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if ${ac_cv_lib_dld_dld_link+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : + lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test yes = "$cross_compiling"; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$lt_cv_dlopen_self" >&6; } + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self_static+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test yes = "$cross_compiling"; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +fi + + + + + + + + + + + + + # Report what library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[4-9]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC=$lt_save_CC + + if test -n "$CXX" && ( test no != "$CXX" && + ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || + (test g++ != "$CXX"))); then + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 +$as_echo_n "checking how to run the C++ preprocessor... " >&6; } +if test -z "$CXXCPP"; then + if ${ac_cv_prog_CXXCPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 +$as_echo "$CXXCPP" >&6; } +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +else + _lt_caught_CXX_error=yes +fi + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +archive_cmds_need_lc_CXX=no +allow_undefined_flag_CXX= +always_export_symbols_CXX=no +archive_expsym_cmds_CXX= +compiler_needs_object_CXX=no +export_dynamic_flag_spec_CXX= +hardcode_direct_CXX=no +hardcode_direct_absolute_CXX=no +hardcode_libdir_flag_spec_CXX= +hardcode_libdir_separator_CXX= +hardcode_minus_L_CXX=no +hardcode_shlibpath_var_CXX=unsupported +hardcode_automatic_CXX=no +inherit_rpath_CXX=no +module_cmds_CXX= +module_expsym_cmds_CXX= +link_all_deplibs_CXX=unknown +old_archive_cmds_CXX=$old_archive_cmds +reload_flag_CXX=$reload_flag +reload_cmds_CXX=$reload_cmds +no_undefined_flag_CXX= +whole_archive_flag_spec_CXX= +enable_shared_with_static_runtimes_CXX=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +objext_CXX=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_caught_CXX_error"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + + # save warnings/boilerplate of simple test code + ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + + ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + compiler_CXX=$CC + func_cc_basename $compiler +cc_basename=$func_cc_basename_result + + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test yes = "$GXX"; then + lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' + else + lt_prog_compiler_no_builtin_flag_CXX= + fi + + if test yes = "$GXX"; then + # Set up default GNU C++ configuration + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test yes = "$with_gnu_ld"; then + archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + + hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' + export_dynamic_flag_spec_CXX='$wl--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='$wl' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + whole_archive_flag_spec_CXX= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + ld_shlibs_CXX=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aix[4-9]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds_CXX='' + hardcode_direct_CXX=yes + hardcode_direct_absolute_CXX=yes + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + file_list_spec_CXX='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + hardcode_direct_CXX=no + hardcode_direct_absolute_CXX=no + ;; + esac + + if test yes = "$GXX"; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct_CXX=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_CXX=yes + hardcode_libdir_flag_spec_CXX='-L$libdir' + hardcode_libdir_separator_CXX= + fi + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag=$shared_flag' $wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + export_dynamic_flag_spec_CXX='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + always_export_symbols_CXX=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + # The "-G" linker flag allows undefined symbols. + no_undefined_flag_CXX='-bernotok' + # Determine the default libpath from the value encoded in an empty + # executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath__CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath__CXX +fi + + hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" + + archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + hardcode_libdir_flag_spec_CXX='$wl-R $libdir:/usr/lib:/lib' + allow_undefined_flag_CXX="-z nodefs" + archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath__CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath__CXX +fi + + hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag_CXX=' $wl-bernotok' + allow_undefined_flag_CXX=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_CXX='$convenience' + fi + archive_cmds_need_lc_CXX=yes + archive_expsym_cmds_CXX='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared + # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. + archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag_CXX=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + ld_shlibs_CXX=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec_CXX=' ' + allow_undefined_flag_CXX=unsupported + always_export_symbols_CXX=yes + file_list_spec_CXX='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true' + enable_shared_with_static_runtimes_CXX=yes + # Don't use ranlib + old_postinstall_cmds_CXX='chmod 644 $oldlib' + postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_CXX='-L$libdir' + export_dynamic_flag_spec_CXX='$wl--export-all-symbols' + allow_undefined_flag_CXX=unsupported + always_export_symbols_CXX=no + enable_shared_with_static_runtimes_CXX=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs_CXX=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + + + archive_cmds_need_lc_CXX=no + hardcode_direct_CXX=no + hardcode_automatic_CXX=yes + hardcode_shlibpath_var_CXX=unsupported + if test yes = "$lt_cv_ld_force_load"; then + whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + + else + whole_archive_flag_spec_CXX='' + fi + link_all_deplibs_CXX=yes + allow_undefined_flag_CXX=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + module_expsym_cmds_CXX="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + if test yes != "$lt_cv_apple_cc_single_mod"; then + archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" + archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" + fi + + else + ld_shlibs_CXX=no + fi + + ;; + + os2*) + hardcode_libdir_flag_spec_CXX='-L$libdir' + hardcode_minus_L_CXX=yes + allow_undefined_flag_CXX=unsupported + shrext_cmds=.dll + archive_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds_CXX='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes_CXX=yes + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + freebsd2.*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + ld_shlibs_CXX=no + ;; + + freebsd-elf*) + archive_cmds_need_lc_CXX=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + ld_shlibs_CXX=yes + ;; + + haiku*) + archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + link_all_deplibs_CXX=yes + ;; + + hpux9*) + hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' + hardcode_libdir_separator_CXX=: + export_dynamic_flag_spec_CXX='$wl-E' + hardcode_direct_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC*) + archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' + hardcode_libdir_separator_CXX=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + export_dynamic_flag_spec_CXX='$wl-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + ;; + *) + hardcode_direct_CXX=yes + hardcode_direct_absolute_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + + interix[3-9]*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' + export_dynamic_flag_spec_CXX='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_CXX='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' + fi + fi + link_all_deplibs_CXX=yes + ;; + esac + hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' + hardcode_libdir_separator_CXX=: + inherit_rpath_CXX=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' + export_dynamic_flag_spec_CXX='$wl--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + archive_cmds_need_lc_CXX=no + hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' + export_dynamic_flag_spec_CXX='$wl--export-dynamic' + whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [1-5].* | *pgcpp\ [1-5].*) + prelink_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + old_archive_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + archive_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + + hardcode_libdir_flag_spec_CXX='$wl--rpath $wl$libdir' + export_dynamic_flag_spec_CXX='$wl--export-dynamic' + whole_archive_flag_spec_CXX='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + ;; + cxx*) + # Compaq C++ + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' + export_dynamic_flag_spec_CXX='$wl--export-dynamic' + archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + no_undefined_flag_CXX=' -zdefs' + archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_expsym_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' + hardcode_libdir_flag_spec_CXX='-R$libdir' + whole_archive_flag_spec_CXX='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object_CXX=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + ld_shlibs_CXX=yes + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + hardcode_direct_absolute_CXX=yes + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' + export_dynamic_flag_spec_CXX='$wl-E' + whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + ld_shlibs_CXX=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' + hardcode_libdir_separator_CXX=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + cxx*) + case $host in + osf3*) + allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' + archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' + ;; + *) + allow_undefined_flag_CXX=' -expect_unresolved \*' + archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ + $RM $lib.exp' + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + ;; + esac + + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes,no = "$GXX,$with_gnu_ld"; then + allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' + case $host in + osf3*) + archive_cmds_CXX='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + *) + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + esac + + hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + archive_cmds_need_lc_CXX=yes + no_undefined_flag_CXX=' -zdefs' + archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_shlibpath_var_CXX=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' + ;; + esac + link_all_deplibs_CXX=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test yes,no = "$GXX,$with_gnu_ld"; then + no_undefined_flag_CXX=' $wl-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require '-G' NOT '-shared' on this + # platform. + archive_cmds_CXX='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + hardcode_libdir_flag_spec_CXX='$wl-R $wl$libdir' + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + whole_archive_flag_spec_CXX='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag_CXX='$wl-z,text' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag_CXX='$wl-z,text' + allow_undefined_flag_CXX='$wl-z,nodefs' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='$wl-R,$libdir' + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + export_dynamic_flag_spec_CXX='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~ + '"$old_archive_cmds_CXX" + reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~ + '"$reload_cmds_CXX" + ;; + *) + archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 +$as_echo "$ld_shlibs_CXX" >&6; } + test no = "$ld_shlibs_CXX" && can_build_shared=no + + GCC_CXX=$GXX + LD_CXX=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + # Dependencies to place before and after the object being linked: +predep_objects_CXX= +postdep_objects_CXX= +predeps_CXX= +postdeps_CXX= +compiler_lib_search_path_CXX= + +cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF + + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + +if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case $prev$p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test x-L = "$p" || + test x-R = "$p"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test no = "$pre_test_object_deps_done"; then + case $prev in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$compiler_lib_search_path_CXX"; then + compiler_lib_search_path_CXX=$prev$p + else + compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} $prev$p" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$postdeps_CXX"; then + postdeps_CXX=$prev$p + else + postdeps_CXX="${postdeps_CXX} $prev$p" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test no = "$pre_test_object_deps_done"; then + if test -z "$predep_objects_CXX"; then + predep_objects_CXX=$p + else + predep_objects_CXX="$predep_objects_CXX $p" + fi + else + if test -z "$postdep_objects_CXX"; then + postdep_objects_CXX=$p + else + postdep_objects_CXX="$postdep_objects_CXX $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling CXX test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +case $host_os in +interix[3-9]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + predep_objects_CXX= + postdep_objects_CXX= + postdeps_CXX= + ;; +esac + + +case " $postdeps_CXX " in +*" -lc "*) archive_cmds_need_lc_CXX=no ;; +esac + compiler_lib_search_dirs_CXX= +if test -n "${compiler_lib_search_path_CXX}"; then + compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | $SED -e 's! -L! !g' -e 's!^ !!'` +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + lt_prog_compiler_wl_CXX= +lt_prog_compiler_pic_CXX= +lt_prog_compiler_static_CXX= + + + # C++ specific cases for pic, static, wl, etc. + if test yes = "$GXX"; then + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + fi + lt_prog_compiler_pic_CXX='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic_CXX='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic_CXX='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static_CXX='$wl-static' + ;; + esac + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_CXX='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + lt_prog_compiler_pic_CXX= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static_CXX= + ;; + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_CXX=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic_CXX='-fPIC -shared' + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + else + case $host_os in + aix[4-9]*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + else + lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_CXX='-DDLL_EXPORT' + ;; + dgux*) + case $cc_basename in + ec++*) + lt_prog_compiler_pic_CXX='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='$wl-a ${wl}archive' + if test ia64 != "$host_cpu"; then + lt_prog_compiler_pic_CXX='+Z' + fi + ;; + aCC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='$wl-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_CXX='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + lt_prog_compiler_wl_CXX='--backend -Wl,' + lt_prog_compiler_pic_CXX='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64, which still supported -KPIC. + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-fPIC' + lt_prog_compiler_static_CXX='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-fpic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + xlc* | xlC* | bgxl[cC]* | mpixl[cC]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-qpic' + lt_prog_compiler_static_CXX='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + lt_prog_compiler_wl_CXX='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + lt_prog_compiler_pic_CXX='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic_CXX='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + lt_prog_compiler_wl_CXX='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + lt_prog_compiler_pic_CXX='-pic' + ;; + cxx*) + # Digital/Compaq C++ + lt_prog_compiler_wl_CXX='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + lt_prog_compiler_wl_CXX='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + lt_prog_compiler_pic_CXX='-pic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + lcc*) + # Lucid + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + lt_prog_compiler_pic_CXX='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + lt_prog_compiler_can_build_shared_CXX=no + ;; + esac + fi + +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic_CXX= + ;; + *) + lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_pic_CXX" >&6; } +lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; } +if ${lt_cv_prog_compiler_pic_works_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works_CXX=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works_CXX=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; } + +if test yes = "$lt_cv_prog_compiler_pic_works_CXX"; then + case $lt_prog_compiler_pic_CXX in + "" | " "*) ;; + *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; + esac +else + lt_prog_compiler_pic_CXX= + lt_prog_compiler_can_build_shared_CXX=no +fi + +fi + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works_CXX=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works_CXX=yes + fi + else + lt_cv_prog_compiler_static_works_CXX=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; } + +if test yes = "$lt_cv_prog_compiler_static_works_CXX"; then + : +else + lt_prog_compiler_static_CXX= +fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o_CXX=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_CXX=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o_CXX=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_CXX=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } + + + + +hard_links=nottested +if test no = "$lt_cv_prog_compiler_c_o_CXX" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test no = "$hard_links"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + case $host_os in + aix[4-9]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds_CXX='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + export_symbols_cmds_CXX=$ltdll_cmds + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) + exclude_expsyms_CXX='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms_CXX='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + ;; + esac + ;; + *) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 +$as_echo "$ld_shlibs_CXX" >&6; } +test no = "$ld_shlibs_CXX" && can_build_shared=no + +with_gnu_ld_CXX=$with_gnu_ld + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc_CXX" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc_CXX=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $archive_cmds_CXX in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_CXX + pic_flag=$lt_prog_compiler_pic_CXX + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_CXX + allow_undefined_flag_CXX= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc_CXX=no + else + lt_cv_archive_cmds_need_lc_CXX=yes + fi + allow_undefined_flag_CXX=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc_CXX" >&6; } + archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + + + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[4-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a(lib.so.V)' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[23].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + hardcode_libdir_flag_spec_CXX='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Add ABI-specific directories to the system library path. + sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action_CXX= +if test -n "$hardcode_libdir_flag_spec_CXX" || + test -n "$runpath_var_CXX" || + test yes = "$hardcode_automatic_CXX"; then + + # We can hardcode non-existent directories. + if test no != "$hardcode_direct_CXX" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" && + test no != "$hardcode_minus_L_CXX"; then + # Linking always hardcodes the temporary library directory. + hardcode_action_CXX=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action_CXX=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action_CXX=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5 +$as_echo "$hardcode_action_CXX" >&6; } + +if test relink = "$hardcode_action_CXX" || + test yes = "$inherit_rpath_CXX"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test yes != "$_lt_caught_CXX_error" + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + +: ${CONFIG_LT=./config.lt} +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_LT" >&5 +$as_echo "$as_me: creating $CONFIG_LT" >&6;} +as_write_fail=0 +cat >"$CONFIG_LT" <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate a libtool stub with the current configuration. +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>"$CONFIG_LT" <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## --------------------------------- ## +## Main body of "$CONFIG_LT" script. ## +## --------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x "$CONFIG_LT" + +cat >>"$CONFIG_LT" <<\_LTEOF +lt_cl_silent=false +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 + +lt_cl_help="\ +'$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $0 [OPTIONS] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to ." + +lt_cl_version="\ +cogl config.lt 1.22.1 +configured by $0, generated by GNU Autoconf 2.69. + +Copyright (C) 2011 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test 0 != $# +do + case $1 in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) as_fn_error $? "unrecognized option: $1 +Try '$0 --help' for more information." "$LINENO" 5 ;; + + *) as_fn_error $? "unrecognized argument: $1 +Try '$0 --help' for more information." "$LINENO" 5 ;; + esac + shift +done + +if $lt_cl_silent; then + exec 6>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' +lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' +want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' +nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' +lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' +configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`' +predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`' +postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`' +predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`' +postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`' +LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`' +reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`' +reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' +compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`' +GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`' +archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' +module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' +with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' +no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`' +inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`' +link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`' +always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`' +exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`' +include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`' +prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`' +postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`' +file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`' +predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`' +postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`' +predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`' +postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in SHELL \ +ECHO \ +PATH_SEPARATOR \ +SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +OBJDUMP \ +deplibs_check_method \ +file_magic_cmd \ +file_magic_glob \ +want_nocaseglob \ +DLLTOOL \ +sharedlib_from_linklib_cmd \ +AR \ +AR_FLAGS \ +archiver_list_spec \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_import \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +lt_cv_nm_interface \ +nm_file_list_spec \ +lt_cv_truncate_bin \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_pic \ +lt_prog_compiler_wl \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +MANIFEST_TOOL \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_separator \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +install_override_mode \ +finish_eval \ +old_striplib \ +striplib \ +compiler_lib_search_dirs \ +predep_objects \ +postdep_objects \ +predeps \ +postdeps \ +compiler_lib_search_path \ +LD_CXX \ +reload_flag_CXX \ +compiler_CXX \ +lt_prog_compiler_no_builtin_flag_CXX \ +lt_prog_compiler_pic_CXX \ +lt_prog_compiler_wl_CXX \ +lt_prog_compiler_static_CXX \ +lt_cv_prog_compiler_c_o_CXX \ +export_dynamic_flag_spec_CXX \ +whole_archive_flag_spec_CXX \ +compiler_needs_object_CXX \ +with_gnu_ld_CXX \ +allow_undefined_flag_CXX \ +no_undefined_flag_CXX \ +hardcode_libdir_flag_spec_CXX \ +hardcode_libdir_separator_CXX \ +exclude_expsyms_CXX \ +include_expsyms_CXX \ +file_list_spec_CXX \ +compiler_lib_search_dirs_CXX \ +predep_objects_CXX \ +postdep_objects_CXX \ +predeps_CXX \ +postdeps_CXX \ +compiler_lib_search_path_CXX; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postlink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +configure_time_dlsearch_path \ +configure_time_lt_sys_library_path \ +reload_cmds_CXX \ +old_archive_cmds_CXX \ +old_archive_from_new_cmds_CXX \ +old_archive_from_expsyms_cmds_CXX \ +archive_cmds_CXX \ +archive_expsym_cmds_CXX \ +module_cmds_CXX \ +module_expsym_cmds_CXX \ +export_symbols_cmds_CXX \ +prelink_cmds_CXX \ +postlink_cmds_CXX; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +ac_aux_dir='$ac_aux_dir' + +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile' + + + + + +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $ofile" >&5 +$as_echo "$as_me: creating $ofile" >&6;} + + + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +# The names of the tagged configurations supported by this script. +available_tags='CXX ' + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# Shared archive member basename,for filename based shared library versioning on AIX. +shared_archive_member_spec=$shared_archive_member_spec + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + +# The PATH separator for the build system. +PATH_SEPARATOR=$lt_PATH_SEPARATOR + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# convert \$build file names to \$host format. +to_host_file_cmd=$lt_cv_to_host_file_cmd + +# convert \$build files to toolchain format. +to_tool_file_cmd=$lt_cv_to_tool_file_cmd + +# An object symbol dumper. +OBJDUMP=$lt_OBJDUMP + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method = "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob=$lt_file_magic_glob + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob=$lt_want_nocaseglob + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd + +# The archiver. +AR=$lt_AR + +# Flags to create an archive. +AR_FLAGS=$lt_AR_FLAGS + +# How to feed a file listing to the archiver. +archiver_list_spec=$lt_archiver_list_spec + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm into a list of symbols to manually relocate. +global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# The name lister interface. +nm_interface=$lt_lt_cv_nm_interface + +# Specify filename containing input files for \$NM. +nm_file_list_spec=$lt_nm_file_list_spec + +# The root where to search for dependent libraries,and where our libraries should be installed. +lt_sysroot=$lt_sysroot + +# Command to truncate a binary pipe. +lt_truncate_bin=$lt_lt_cv_truncate_bin + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Manifest tool. +MANIFEST_TOOL=$lt_MANIFEST_TOOL + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Detected run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path + +# Explicit LT_SYS_LIBRARY_PATH set during ./configure time. +configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \$shlibpath_var if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# The directories searched by this compiler when creating a shared library. +compiler_lib_search_dirs=$lt_compiler_lib_search_dirs + +# Dependencies to place before and after the objects being linked to +# create a shared library. +predep_objects=$lt_predep_objects +postdep_objects=$lt_postdep_objects +predeps=$lt_predeps +postdeps=$lt_postdeps + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path + +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain=$ac_aux_dir/ltmain.sh + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + + cat <<_LT_EOF >> "$ofile" + +# ### BEGIN LIBTOOL TAG CONFIG: CXX + +# The linker used to build libraries. +LD=$lt_LD_CXX + +# How to create reloadable object files. +reload_flag=$lt_reload_flag_CXX +reload_cmds=$lt_reload_cmds_CXX + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds_CXX + +# A language specific compiler. +CC=$lt_compiler_CXX + +# Is the compiler the GNU compiler? +with_gcc=$GCC_CXX + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_CXX + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_CXX + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_CXX + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_CXX + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object_CXX + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds_CXX +archive_expsym_cmds=$lt_archive_expsym_cmds_CXX + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds_CXX +module_expsym_cmds=$lt_module_expsym_cmds_CXX + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld_CXX + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_CXX + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_CXX + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct_CXX + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \$shlibpath_var if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute_CXX + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L_CXX + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic_CXX + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath_CXX + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_CXX + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols_CXX + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_CXX + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_CXX + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_CXX + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds_CXX + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds_CXX + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec_CXX + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_CXX + +# The directories searched by this compiler when creating a shared library. +compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX + +# Dependencies to place before and after the objects being linked to +# create a shared library. +predep_objects=$lt_predep_objects_CXX +postdep_objects=$lt_postdep_objects_CXX +predeps=$lt_predeps_CXX +postdeps=$lt_postdeps_CXX + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_CXX + +# ### END LIBTOOL TAG CONFIG: CXX +_LT_EOF + + +as_fn_exit 0 +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +lt_cl_success=: +test yes = "$silent" && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec 5>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec 5>>config.log +$lt_cl_success || as_fn_exit 1 + + +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _mwvalidcheckl in -lmw" >&5 +$as_echo_n "checking for _mwvalidcheckl in -lmw... " >&6; } +if ${ac_cv_lib_mw__mwvalidcheckl+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lmw $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char _mwvalidcheckl (); +int +main () +{ +return _mwvalidcheckl (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_mw__mwvalidcheckl=yes +else + ac_cv_lib_mw__mwvalidcheckl=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mw__mwvalidcheckl" >&5 +$as_echo "$ac_cv_lib_mw__mwvalidcheckl" >&6; } +if test "x$ac_cv_lib_mw__mwvalidcheckl" = xyes; then : + LIBM=-lmw +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5 +$as_echo_n "checking for cos in -lm... " >&6; } +if ${ac_cv_lib_m_cos+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char cos (); +int +main () +{ +return cos (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_cos=yes +else + ac_cv_lib_m_cos=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_cos" >&5 +$as_echo "$ac_cv_lib_m_cos" >&6; } +if test "x$ac_cv_lib_m_cos" = xyes; then : + LIBM="$LIBM -lm" +fi + + ;; +*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5 +$as_echo_n "checking for cos in -lm... " >&6; } +if ${ac_cv_lib_m_cos+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char cos (); +int +main () +{ +return cos (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_cos=yes +else + ac_cv_lib_m_cos=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_cos" >&5 +$as_echo "$ac_cv_lib_m_cos" >&6; } +if test "x$ac_cv_lib_m_cos" = xyes; then : + LIBM=-lm +fi + + ;; +esac + + + + + + + +# Check whether --enable-installed_tests was given. +if test "${enable_installed_tests+set}" = set; then : + enableval=$enable_installed_tests; +else + enable_installed_tests=no +fi + + if test x$enable_installed_tests = xyes; then + ENABLE_INSTALLED_TESTS_TRUE= + ENABLE_INSTALLED_TESTS_FALSE='#' +else + ENABLE_INSTALLED_TESTS_TRUE='#' + ENABLE_INSTALLED_TESTS_FALSE= +fi + + + +# Check whether --enable-debug was given. +if test "${enable_debug+set}" = set; then : + enableval=$enable_debug; +else + enable_debug=yes + +fi + +case $enable_debug in #( + yes) : + + test "$cflags_set" = set || CFLAGS="$CFLAGS -g -O0" + COGL_EXTRA_CFLAGS="$COGL_EXTRA_CFLAGS -DCOGL_GL_DEBUG -DCOGL_OBJECT_DEBUG -DCOGL_ENABLE_DEBUG" + ;; #( + no) : + + COGL_EXTRA_CFLAGS="$COGL_EXTRA_CFLAGS -DG_DISABLE_CHECKS -DG_DISABLE_CAST_CHECKS" + ;; #( + *) : + as_fn_error $? "Unknown argument for --enable-debug" "$LINENO" 5 + ;; +esac + + + +# Check whether --enable-unit-tests was given. +if test "${enable_unit_tests+set}" = set; then : + enableval=$enable_unit_tests; +else + enable_unit_tests=yes + +fi + +if test "x$enable_unit_tests" = "xyes"; then : + + +$as_echo "#define ENABLE_UNIT_TESTS 1" >>confdefs.h + + + +fi + if test "x$enable_unit_tests" = "xyes"; then + UNIT_TESTS_TRUE= + UNIT_TESTS_FALSE='#' +else + UNIT_TESTS_TRUE='#' + UNIT_TESTS_FALSE= +fi + + + + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi +if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"CAIRO\""; } >&5 + ($PKG_CONFIG --exists --print-errors "CAIRO") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + cairo >= 1.10 +else + have_cairo=yes +fi +# Check whether --enable-cairo was given. +if test "${enable_cairo+set}" = set; then : + enableval=$enable_cairo; +else + + if test "x$enable_debug" = "xyes"; then : + enable_cairo=$have_cairo +else + enable_cairo=no +fi + + +fi + +if test "x$enable_cairo" = "xyes" && test "x$enable_debug" = "xyes"; then : + + if test "x$have_cairo" != "xyes"; then : + as_fn_error $? "Could not find Cairo" "$LINENO" 5 +fi + + COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES cairo >= 1.10" + +$as_echo "#define HAVE_CAIRO 1" >>confdefs.h + + +fi + + +# Check whether --enable-profile was given. +if test "${enable_profile+set}" = set; then : + enableval=$enable_profile; +else + enable_profile=no +fi + +if test "x$enable_profile" = "xyes"; then : + + if test "x$GCC" = "xyes"; then : + + COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES uprof-0.3" + COGL_EXTRA_CFLAGS="$COGL_EXTRA_CFLAGS -DCOGL_ENABLE_PROFILE" + if test "x$enable_debug" = "xyes"; then : + COGL_EXTRA_CFLAGS="$COGL_EXTRA_CFLAGS -DUPROF_DEBUG" +fi + +else + + as_fn_error $? "--enable-profile is currently only supported if using GCC" "$LINENO" 5 + +fi + +fi + if test "x$enable_profile" != "xno"; then + PROFILE_TRUE= + PROFILE_FALSE='#' +else + PROFILE_TRUE='#' + PROFILE_FALSE= +fi + + + + +# use strict compiler flags only when building from git; the rules for +# distcheck will take care of turning this on when making a release + +# Check whether --enable-maintainer-flags was given. +if test "${enable_maintainer_flags+set}" = set; then : + enableval=$enable_maintainer_flags; +else + enable_maintainer_flags=yes + +fi + + +MAINTAINER_COMPILER_FLAGS="-Wall -Wcast-align -Wformat -Wformat-security + -Werror=uninitialized -Werror=no-strict-aliasing + -Werror=empty-body -Werror=init-self -Werror=undef + -Werror=declaration-after-statement -Werror=vla + -Werror=pointer-arith -Werror=missing-declarations + -Werror=maybe-uninitialized" + +case $enable_maintainer_flags in #( + yes) : + + + list=$MAINTAINER_COMPILER_FLAGS + flags_supported="" + flags_unsupported="" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for supported compiler flags" >&5 +$as_echo_n "checking for supported compiler flags... " >&6; } + for each in $list + do + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $each" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + flag_ok=yes +else + flag_ok=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$save_CFLAGS" + + if test "X$flag_ok" = Xyes ; then + flags_supported="$flags_supported $each" + else + flags_unsupported="$flags_unsupported $each" + fi + done + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flags_supported" >&5 +$as_echo "$flags_supported" >&6; } + if test "X$flags_unsupported" != X ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unsupported compiler flags: $flags_unsupported" >&5 +$as_echo "$as_me: WARNING: unsupported compiler flags: $flags_unsupported" >&2;} + fi + MAINTAINER_CFLAGS="$MAINTAINER_CFLAGS $flags_supported" + + ;; #( + no) : + + ;; #( + error) : + + MAINTAINER_COMPILER_FLAGS="$MAINTAINER_COMPILER_FLAGS -Werror" + + list=$MAINTAINER_COMPILER_FLAGS + flags_supported="" + flags_unsupported="" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for supported compiler flags" >&5 +$as_echo_n "checking for supported compiler flags... " >&6; } + for each in $list + do + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $each" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + flag_ok=yes +else + flag_ok=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$save_CFLAGS" + + if test "X$flag_ok" = Xyes ; then + flags_supported="$flags_supported $each" + else + flags_unsupported="$flags_unsupported $each" + fi + done + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flags_supported" >&5 +$as_echo "$flags_supported" >&6; } + if test "X$flags_unsupported" != X ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unsupported compiler flags: $flags_unsupported" >&5 +$as_echo "$as_me: WARNING: unsupported compiler flags: $flags_unsupported" >&2;} + fi + MAINTAINER_CFLAGS="$MAINTAINER_CFLAGS $flags_supported" + + ;; #( + *) : + as_fn_error $? "Invalid option for --enable-maintainer-flags" "$LINENO" 5 + ;; #( + *) : + ;; +esac + +# strip leading spaces +COGL_EXTRA_CFLAGS="$COGL_EXTRA_CFLAGS ${MAINTAINER_CFLAGS#* }" +COGL_EXTRA_CFLAGS="$COGL_EXTRA_CFLAGS -Wno-error=sign-compare" + + + +# disable deprecated options from Glib only when building from git; +# the rules for distcheck will take care of turning this on when +# making a release + + +# Check whether --enable-deprecated was given. +if test "${enable_deprecated+set}" = set; then : + enableval=$enable_deprecated; +else + enable_deprecated=no +fi + + +case $enable_deprecated in #( + no) : + + DEPRECATED_CFLAGS="-DG_DISABLE_DEPRECATED -DG_DISABLE_SINGLE_INCLUDES" + ;; #( + yes) : + + DEPRECATED_CFLAGS="" + ;; #( + *) : + as_fn_error $? "Unknown argument for --enable-deprecated" "$LINENO" 5 + ;; +esac + +# strip leading spaces +COGL_EXTRA_CFLAGS="$COGL_EXTRA_CFLAGS ${DEPRECATED_CFLAGS#* }" + + +# Check whether --enable-glibtest was given. +if test "${enable_glibtest+set}" = set; then : + enableval=$enable_glibtest; +else + enable_glibtest=yes +fi + + + pkg_config_args=glib-2.0 + for module in . gobject gthread gmodule-no-export + do + case "$module" in + gmodule) + pkg_config_args="$pkg_config_args gmodule-2.0" + ;; + gmodule-no-export) + pkg_config_args="$pkg_config_args gmodule-no-export-2.0" + ;; + gobject) + pkg_config_args="$pkg_config_args gobject-2.0" + ;; + gthread) + pkg_config_args="$pkg_config_args gthread-2.0" + ;; + gio*) + pkg_config_args="$pkg_config_args $module-2.0" + ;; + esac + done + + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.16 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi + + no_glib="" + + if test "x$PKG_CONFIG" = x ; then + no_glib=yes + PKG_CONFIG=no + fi + + min_glib_version=2.32.0 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLIB - version >= $min_glib_version" >&5 +$as_echo_n "checking for GLIB - version >= $min_glib_version... " >&6; } + + if test x$PKG_CONFIG != xno ; then + ## don't try to run the test against uninstalled libtool libs + if $PKG_CONFIG --uninstalled $pkg_config_args; then + echo "Will use uninstalled version of GLib found in PKG_CONFIG_PATH" + enable_glibtest=no + fi + + if $PKG_CONFIG --atleast-version $min_glib_version $pkg_config_args; then + : + else + no_glib=yes + fi + fi + + if test x"$no_glib" = x ; then + GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0` + GOBJECT_QUERY=`$PKG_CONFIG --variable=gobject_query glib-2.0` + GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0` + GLIB_COMPILE_RESOURCES=`$PKG_CONFIG --variable=glib_compile_resources gio-2.0` + + GLIB_CFLAGS=`$PKG_CONFIG --cflags $pkg_config_args` + GLIB_LIBS=`$PKG_CONFIG --libs $pkg_config_args` + glib_config_major_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'` + glib_config_minor_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'` + glib_config_micro_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'` + if test "x$enable_glibtest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GLIB_CFLAGS" + LIBS="$GLIB_LIBS $LIBS" + rm -f conf.glibtest + if test "$cross_compiling" = yes; then : + echo $ac_n "cross compiling; assumed OK... $ac_c" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +#include + +int +main () +{ + unsigned int major, minor, micro; + + fclose (fopen ("conf.glibtest", "w")); + + if (sscanf("$min_glib_version", "%u.%u.%u", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_glib_version"); + exit(1); + } + + if ((glib_major_version != $glib_config_major_version) || + (glib_minor_version != $glib_config_minor_version) || + (glib_micro_version != $glib_config_micro_version)) + { + printf("\n*** 'pkg-config --modversion glib-2.0' returned %d.%d.%d, but GLIB (%d.%d.%d)\n", + $glib_config_major_version, $glib_config_minor_version, $glib_config_micro_version, + glib_major_version, glib_minor_version, glib_micro_version); + printf ("*** was found! If pkg-config was correct, then it is best\n"); + printf ("*** to remove the old version of GLib. You may also be able to fix the error\n"); + printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); + printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); + printf("*** required on your system.\n"); + printf("*** If pkg-config was wrong, set the environment variable PKG_CONFIG_PATH\n"); + printf("*** to point to the correct configuration files\n"); + } + else if ((glib_major_version != GLIB_MAJOR_VERSION) || + (glib_minor_version != GLIB_MINOR_VERSION) || + (glib_micro_version != GLIB_MICRO_VERSION)) + { + printf("*** GLIB header files (version %d.%d.%d) do not match\n", + GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION); + printf("*** library (version %d.%d.%d)\n", + glib_major_version, glib_minor_version, glib_micro_version); + } + else + { + if ((glib_major_version > major) || + ((glib_major_version == major) && (glib_minor_version > minor)) || + ((glib_major_version == major) && (glib_minor_version == minor) && (glib_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** An old version of GLIB (%u.%u.%u) was found.\n", + glib_major_version, glib_minor_version, glib_micro_version); + printf("*** You need a version of GLIB newer than %u.%u.%u. The latest version of\n", + major, minor, micro); + printf("*** GLIB is always available from ftp://ftp.gtk.org.\n"); + printf("***\n"); + printf("*** If you have already installed a sufficiently new version, this error\n"); + printf("*** probably means that the wrong copy of the pkg-config shell script is\n"); + printf("*** being found. The easiest way to fix this is to remove the old version\n"); + printf("*** of GLIB, but you can also set the PKG_CONFIG environment to point to the\n"); + printf("*** correct copy of pkg-config. (In this case, you will have to\n"); + printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); + printf("*** so that the correct libraries are found at run-time))\n"); + } + } + return 1; +} + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + no_glib=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_glib" = x ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (version $glib_config_major_version.$glib_config_minor_version.$glib_config_micro_version)" >&5 +$as_echo "yes (version $glib_config_major_version.$glib_config_minor_version.$glib_config_micro_version)" >&6; } + : + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + if test "$PKG_CONFIG" = "no" ; then + echo "*** A new enough version of pkg-config was not found." + echo "*** See http://www.freedesktop.org/software/pkgconfig/" + else + if test -f conf.glibtest ; then + : + else + echo "*** Could not run GLIB test program, checking why..." + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GLIB_CFLAGS" + LIBS="$LIBS $GLIB_LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include + +int +main () +{ + return ((glib_major_version) || (glib_minor_version) || (glib_micro_version)); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding GLIB or finding the wrong" + echo "*** version of GLIB. If it is not finding GLIB, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" +else + echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means GLIB is incorrectly installed." +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + GLIB_CFLAGS="" + GLIB_LIBS="" + GLIB_GENMARSHAL="" + GOBJECT_QUERY="" + GLIB_MKENUMS="" + GLIB_COMPILE_RESOURCES="" + as_fn_error $? "glib-2.0 is required" "$LINENO" 5 + fi + + + + + + + rm -f conf.glibtest + + +COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES gobject-2.0 gmodule-no-export-2.0" + + +# Check whether --enable-cogl-pango was given. +if test "${enable_cogl_pango+set}" = set; then : + enableval=$enable_cogl_pango; +else + enable_cogl_pango=yes + +fi + +if test "x$enable_cogl_pango" = "xyes"; then : + + COGL_PANGO_PKG_REQUIRES="$COGL_PANGO_PKG_REQUIRES pangocairo >= 1.20" + + +fi + + +# Check whether --enable-cogl-path was given. +if test "${enable_cogl_path+set}" = set; then : + enableval=$enable_cogl_path; +else + enable_cogl_path=yes + +fi + +if test "x$enable_cogl_path" = "xyes"; then : + + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_COGL_PATH_SUPPORT" + + +fi + +COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES gdk-pixbuf-2.0 >= 2.0" +COGL_IMAGE_BACKEND="gdk-pixbuf" + + +EGL_CHECKED=no + +enabled_drivers="" + +HAVE_GLES1=0 +# Check whether --enable-gles1 was given. +if test "${enable_gles1+set}" = set; then : + enableval=$enable_gles1; +else + enable_gles1=no + +fi + +if test "x$enable_gles1" = "xyes"; then : + + enabled_drivers="$enabled_drivers gles1" + + cogl_gl_headers="GLES/gl.h GLES/glext.h" + + +$as_echo "#define HAVE_COGL_GLES 1" >>confdefs.h + + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_GLES CLUTTER_COGL_HAS_GLES" + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_GLES1" + HAVE_GLES1=1 + + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glesv1_cm\""; } >&5 + ($PKG_CONFIG --exists --print-errors "glesv1_cm") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + COGL_PKG_REQUIRES_GL="$COGL_PKG_REQUIRES_GL glesv1_cm" + COGL_GLES1_LIBNAME="libGLESv1_CM.so" + +else + + # We have to check the two headers independently as GLES/glext.h + # needs to include GLES/gl.h to have the GL types defined (eg. + # GLenum). + ac_fn_c_check_header_mongrel "$LINENO" "GLES/gl.h" "ac_cv_header_GLES_gl_h" "$ac_includes_default" +if test "x$ac_cv_header_GLES_gl_h" = xyes; then : + +else + as_fn_error $? "Unable to locate GLES/gl.h" "$LINENO" 5 +fi + + + ac_fn_c_check_header_compile "$LINENO" "GLES/glext.h" "ac_cv_header_GLES_glext_h" "#include +" +if test "x$ac_cv_header_GLES_glext_h" = xyes; then : + +else + as_fn_error $? "Unable to locate GLES/glext.h" "$LINENO" 5 +fi + + + + # Early implementations provided only a GLES/egl.h while Khronos's + # implementer guide now states EGL/egl.h is the One. Some + # implementations keep a GLES/egl.h wrapper around EGL/egl.h for + # backward compatibility while others provide EGL/egl.h only. + for ac_header in GLES/egl.h EGL/egl.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + if test "x$ac_cv_header_GLES_egl_h" = "xyes"; then : + COGL_EGL_INCLUDES="#include " +elif test "x$ac_cv_header_EGL_egl_h" = "xyes"; then : + + COGL_EGL_INCLUDES="#include " + +else + as_fn_error $? "Unable to locate EGL header" "$LINENO" 5 +fi + + + for ac_header in EGL/eglext.h +do : + ac_fn_c_check_header_compile "$LINENO" "EGL/eglext.h" "ac_cv_header_EGL_eglext_h" "$COGL_EGL_INCLUDES +" +if test "x$ac_cv_header_EGL_eglext_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_EGL_EGLEXT_H 1 +_ACEOF + COGL_EGL_INCLUDES="$COGL_EGL_INCLUDE +#include " +fi + +done + + + # Check for a GLES 1.x Common Profile library with/without EGL. + # + # Note: historically GLES 1 libraries shipped with the + # EGL and GLES symbols all bundled in one library. Now + # the Khronos Implementers Guide defines two naming + # schemes: -lGLES_CM should be used for a library that + # bundles the GLES and EGL API together and -lGLESv1_CM + # would be used for a standalone GLES API. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for eglInitialize in -lGLES_CM" >&5 +$as_echo_n "checking for eglInitialize in -lGLES_CM... " >&6; } +if ${ac_cv_lib_GLES_CM_eglInitialize+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lGLES_CM $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char eglInitialize (); +int +main () +{ +return eglInitialize (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_GLES_CM_eglInitialize=yes +else + ac_cv_lib_GLES_CM_eglInitialize=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_GLES_CM_eglInitialize" >&5 +$as_echo "$ac_cv_lib_GLES_CM_eglInitialize" >&6; } +if test "x$ac_cv_lib_GLES_CM_eglInitialize" = xyes; then : + COGL_GLES1_LIBNAME="libGLES_CM.so" +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for glFlush in -lGLESv1_CM" >&5 +$as_echo_n "checking for glFlush in -lGLESv1_CM... " >&6; } +if ${ac_cv_lib_GLESv1_CM_glFlush+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lGLESv1_CM $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char glFlush (); +int +main () +{ +return glFlush (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_GLESv1_CM_glFlush=yes +else + ac_cv_lib_GLESv1_CM_glFlush=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_GLESv1_CM_glFlush" >&5 +$as_echo "$ac_cv_lib_GLESv1_CM_glFlush" >&6; } +if test "x$ac_cv_lib_GLESv1_CM_glFlush" = xyes; then : + COGL_GLES1_LIBNAME="libGLESv1_CM.so" + NEED_SEPARATE_EGL=yes + +else + as_fn_error $? "Unable to locate required GLES 1.x Common Profile library" "$LINENO" 5 +fi + + +fi + + + EGL_CHECKED=yes + +fi + +fi + +HAVE_GLES2=0 +# Check whether --enable-gles2 was given. +if test "${enable_gles2+set}" = set; then : + enableval=$enable_gles2; +else + enable_gles2=no + +fi + +if test "x$enable_gles2" = "xyes"; then : + + enabled_drivers="$enabled_drivers gles2" + + cogl_gl_headers="GLES2/gl2.h GLES2/gl2ext.h" + +$as_echo "#define HAVE_COGL_GLES2 1" >>confdefs.h + + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_GLES CLUTTER_COGL_HAS_GLES" + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_GLES2" + HAVE_GLES2=1 + + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glesv2\""; } >&5 + ($PKG_CONFIG --exists --print-errors "glesv2") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + COGL_PKG_REQUIRES_GL="$COGL_PKG_REQUIRES_GL glesv2" + COGL_GLES2_LIBNAME="libGLESv2.so" + +else + + # We have to check the two headers independently as GLES2/gl2ext.h + # needs to include GLES2/gl2.h to have the GL types defined (eg. + # GLenum). + ac_fn_c_check_header_mongrel "$LINENO" "GLES2/gl2.h" "ac_cv_header_GLES2_gl2_h" "$ac_includes_default" +if test "x$ac_cv_header_GLES2_gl2_h" = xyes; then : + +else + as_fn_error $? "Unable to locate GLES2/gl2.h" "$LINENO" 5 +fi + + + ac_fn_c_check_header_compile "$LINENO" "GLES2/gl2ext.h" "ac_cv_header_GLES2_gl2ext_h" "#include +" +if test "x$ac_cv_header_GLES2_gl2ext_h" = xyes; then : + +else + as_fn_error $? "Unable to locate GLES2/gl2ext.h" "$LINENO" 5 +fi + + + + COGL_GLES2_LIBNAME="libGLESv2.so" + +fi + +fi + +HAVE_GL=0 +# Check whether --enable-gl was given. +if test "${enable_gl+set}" = set; then : + enableval=$enable_gl; +else + enable_gl=yes + +fi + +if test "x$enable_gl" = "xyes"; then : + + enabled_drivers="$enabled_drivers gl" + + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"x11\""; } >&5 + ($PKG_CONFIG --exists --print-errors "x11") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + ALLOW_GLX=yes +fi + + cogl_gl_headers="GL/gl.h" + + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gl\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gl") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + COGL_PKG_REQUIRES_GL="$COGL_PKG_REQUIRES_GL gl" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for glGetString in -lGL" >&5 +$as_echo_n "checking for glGetString in -lGL... " >&6; } +if ${ac_cv_lib_GL_glGetString+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lGL $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char glGetString (); +int +main () +{ +return glGetString (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_GL_glGetString=yes +else + ac_cv_lib_GL_glGetString=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_GL_glGetString" >&5 +$as_echo "$ac_cv_lib_GL_glGetString" >&6; } +if test "x$ac_cv_lib_GL_glGetString" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBGL 1 +_ACEOF + + LIBS="-lGL $LIBS" + +else + as_fn_error $? "Unable to locate required GL library" "$LINENO" 5 +fi + + +fi + COGL_GL_LIBNAME="libGL.so.1" + + +$as_echo "#define HAVE_COGL_GL 1" >>confdefs.h + + + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_GL" + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS CLUTTER_COGL_HAS_GL" + HAVE_GL=1 + +fi + + if test "x$enable_gl" = "xyes"; then + COGL_DRIVER_GL_SUPPORTED_TRUE= + COGL_DRIVER_GL_SUPPORTED_FALSE='#' +else + COGL_DRIVER_GL_SUPPORTED_TRUE='#' + COGL_DRIVER_GL_SUPPORTED_FALSE= +fi + + if test "x$enable_gles1" = "xyes" || test "x$enable_gles2" = "xyes"; then + COGL_DRIVER_GLES_SUPPORTED_TRUE= + COGL_DRIVER_GLES_SUPPORTED_FALSE='#' +else + COGL_DRIVER_GLES_SUPPORTED_TRUE='#' + COGL_DRIVER_GLES_SUPPORTED_FALSE= +fi + + + +# Check whether --with-gl-libname was given. +if test "${with_gl_libname+set}" = set; then : + withval=$with_gl_libname; COGL_GL_LIBNAME="$withval" +fi + + +# Check whether --with-gles1-libname was given. +if test "${with_gles1_libname+set}" = set; then : + withval=$with_gles1_libname; COGL_GLES1_LIBNAME="$withval" +fi + + +# Check whether --with-gles2-libname was given. +if test "${with_gles2_libname+set}" = set; then : + withval=$with_gles2_libname; COGL_GLES2_LIBNAME="$withval" +fi + + +# Check whether --with-default-driver was given. +if test "${with_default_driver+set}" = set; then : + withval=$with_default_driver; COGL_DEFAULT_DRIVER="${withval}" +else + COGL_DEFAULT_DRIVER="" +fi + + + if test "x$COGL_DEFAULT_DRIVER" != "x" ; then + HAVE_COGL_DEFAULT_DRIVER_TRUE= + HAVE_COGL_DEFAULT_DRIVER_FALSE='#' +else + HAVE_COGL_DEFAULT_DRIVER_TRUE='#' + HAVE_COGL_DEFAULT_DRIVER_FALSE= +fi + + + + + + + + + + + +# Check whether --enable-cogl-gles2 was given. +if test "${enable_cogl_gles2+set}" = set; then : + enableval=$enable_cogl_gles2; +else + + if test "x$HAVE_GLES2" = "x1"; then : + enable_cogl_gles2=yes +else + enable_cogl_gles2=no +fi + + +fi + +if test "x$enable_cogl_gles2" = "xyes"; then : + + if test "x$HAVE_GLES2" != "x1"; then : + + as_fn_error $? "libcogl-gles2 is currently only supported on systems with a native GLES 2.0 library" "$LINENO" 5 + +fi + +fi + if test "x$enable_cogl_gles2" = "xyes"; then + BUILD_COGL_GLES2_TRUE= + BUILD_COGL_GLES2_FALSE='#' +else + BUILD_COGL_GLES2_TRUE='#' + BUILD_COGL_GLES2_FALSE= +fi + + + + +# Check whether --enable-glx was given. +if test "${enable_glx+set}" = set; then : + enableval=$enable_glx; +else + if test "x$ALLOW_GLX" = "xyes"; then : + enable_glx=yes +else + enable_glx=no +fi + +fi + +if test "x$enable_glx" = "xyes"; then : + + if test "x$ALLOW_GLX" != "xyes"; then : + as_fn_error $? "GLX not supported with this configuration" "$LINENO" 5 +fi + + NEED_XLIB=yes + SUPPORT_GLX=yes + GL_WINSYS_APIS="$GL_WINSYS_APIS glx" + + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_GLX_SUPPORT" + +fi + if test "x$SUPPORT_GLX" = "xyes"; then + SUPPORT_GLX_TRUE= + SUPPORT_GLX_FALSE='#' +else + SUPPORT_GLX_TRUE='#' + SUPPORT_GLX_FALSE= +fi + + +EGL_PLATFORM_COUNT=0 + +# Check whether --enable-kms-egl-platform was given. +if test "${enable_kms_egl_platform+set}" = set; then : + enableval=$enable_kms_egl_platform; +else + enable_kms_egl_platform=yes + +fi + +if test "x$enable_kms_egl_platform" = "xyes"; then : + + EGL_PLATFORM_COUNT=$((EGL_PLATFORM_COUNT+1)) + NEED_EGL=yes + EGL_PLATFORMS="$EGL_PLATFORMS kms" + + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gbm\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gbm") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + + COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES gbm" + COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES libdrm" + +else + as_fn_error $? "Unable to locate required libgbm library for the KMS egl platform" "$LINENO" 5 +fi + + GBM_VERSION=`$PKG_CONFIG --modversion gbm` + GBM_MAJOR=`echo $GBM_VERSION | cut -d'.' -f1` + GBM_MINOR=`echo $GBM_VERSION | cut -d'.' -f2` + GBM_MICRO=`echo $GBM_VERSION | cut -d'.' -f3 | sed 's/-.*//'` + + +cat >>confdefs.h <<_ACEOF +#define COGL_GBM_MAJOR $GBM_MAJOR +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define COGL_GBM_MINOR $GBM_MINOR +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define COGL_GBM_MICRO $GBM_MICRO +_ACEOF + + + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_EGL_PLATFORM_KMS_SUPPORT" + +fi + if test "x$enable_kms_egl_platform" = "xyes"; then + SUPPORT_EGL_PLATFORM_KMS_TRUE= + SUPPORT_EGL_PLATFORM_KMS_FALSE='#' +else + SUPPORT_EGL_PLATFORM_KMS_TRUE='#' + SUPPORT_EGL_PLATFORM_KMS_FALSE= +fi + + +# Check whether --enable-wayland-egl-server was given. +if test "${enable_wayland_egl_server+set}" = set; then : + enableval=$enable_wayland_egl_server; +else + enable_wayland_egl_server=yes + +fi + +if test "x$enable_wayland_egl_server" = "xyes"; then : + + NEED_EGL=yes + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for WAYLAND_SERVER" >&5 +$as_echo_n "checking for WAYLAND_SERVER... " >&6; } + +if test -n "$WAYLAND_SERVER_CFLAGS"; then + pkg_cv_WAYLAND_SERVER_CFLAGS="$WAYLAND_SERVER_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"wayland-server >= 1.1.90\""; } >&5 + ($PKG_CONFIG --exists --print-errors "wayland-server >= 1.1.90") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_WAYLAND_SERVER_CFLAGS=`$PKG_CONFIG --cflags "wayland-server >= 1.1.90" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$WAYLAND_SERVER_LIBS"; then + pkg_cv_WAYLAND_SERVER_LIBS="$WAYLAND_SERVER_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"wayland-server >= 1.1.90\""; } >&5 + ($PKG_CONFIG --exists --print-errors "wayland-server >= 1.1.90") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_WAYLAND_SERVER_LIBS=`$PKG_CONFIG --libs "wayland-server >= 1.1.90" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + WAYLAND_SERVER_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "wayland-server >= 1.1.90" 2>&1` + else + WAYLAND_SERVER_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "wayland-server >= 1.1.90" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$WAYLAND_SERVER_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (wayland-server >= 1.1.90) were not met: + +$WAYLAND_SERVER_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables WAYLAND_SERVER_CFLAGS +and WAYLAND_SERVER_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables WAYLAND_SERVER_CFLAGS +and WAYLAND_SERVER_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + WAYLAND_SERVER_CFLAGS=$pkg_cv_WAYLAND_SERVER_CFLAGS + WAYLAND_SERVER_LIBS=$pkg_cv_WAYLAND_SERVER_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES wayland-server >= 1.1.90" + + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT" + +fi + if test "x$enable_wayland_egl_server" = "xyes"; then + SUPPORT_WAYLAND_EGL_SERVER_TRUE= + SUPPORT_WAYLAND_EGL_SERVER_FALSE='#' +else + SUPPORT_WAYLAND_EGL_SERVER_TRUE='#' + SUPPORT_WAYLAND_EGL_SERVER_FALSE= +fi + + +# Check whether --enable-xlib-egl-platform was given. +if test "${enable_xlib_egl_platform+set}" = set; then : + enableval=$enable_xlib_egl_platform; +else + enable_xlib_egl_platform=yes + +fi + +if test "x$enable_xlib_egl_platform" = "xyes"; then : + + EGL_PLATFORM_COUNT=$((EGL_PLATFORM_COUNT+1)) + NEED_EGL=yes + NEED_XLIB=yes + EGL_PLATFORMS="$EGL_PLATFORMS xlib" + + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_EGL_PLATFORM_XLIB_SUPPORT" + +fi + if test "x$enable_xlib_egl_platform" = "xyes"; then + SUPPORT_EGL_PLATFORM_XLIB_TRUE= + SUPPORT_EGL_PLATFORM_XLIB_FALSE='#' +else + SUPPORT_EGL_PLATFORM_XLIB_TRUE='#' + SUPPORT_EGL_PLATFORM_XLIB_FALSE= +fi + + +if test "x$NEED_EGL" = "xyes" && test "x$EGL_CHECKED" != "xyes"; then : + + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"egl\""; } >&5 + ($PKG_CONFIG --exists --print-errors "egl") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES egl" +else + + for ac_header in EGL/egl.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "EGL/egl.h" "ac_cv_header_EGL_egl_h" "$ac_includes_default" +if test "x$ac_cv_header_EGL_egl_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_EGL_EGL_H 1 +_ACEOF + +else + as_fn_error $? "Unable to locate required EGL headers" "$LINENO" 5 +fi + +done + + for ac_header in EGL/eglext.h +do : + ac_fn_c_check_header_compile "$LINENO" "EGL/eglext.h" "ac_cv_header_EGL_eglext_h" "#include +" +if test "x$ac_cv_header_EGL_eglext_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_EGL_EGLEXT_H 1 +_ACEOF + +else + as_fn_error $? "Unable to locate required EGL headers" "$LINENO" 5 +fi + +done + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for eglInitialize in -lEGL" >&5 +$as_echo_n "checking for eglInitialize in -lEGL... " >&6; } +if ${ac_cv_lib_EGL_eglInitialize+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lEGL $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char eglInitialize (); +int +main () +{ +return eglInitialize (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_EGL_eglInitialize=yes +else + ac_cv_lib_EGL_eglInitialize=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_EGL_eglInitialize" >&5 +$as_echo "$ac_cv_lib_EGL_eglInitialize" >&6; } +if test "x$ac_cv_lib_EGL_eglInitialize" = xyes; then : + COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -lEGL" +else + as_fn_error $? "Unable to locate required EGL library" "$LINENO" 5 +fi + + + COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -lEGL" + + +fi + + COGL_EGL_INCLUDES="#include +#include " + + +fi + +if test "x$NEED_EGL" = "xyes"; then : + + SUPPORT_EGL=yes + GL_WINSYS_APIS="$GL_WINSYS_APIS egl" + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_EGL_SUPPORT" + +fi + + if test "x$SUPPORT_EGL" = "xyes"; then + SUPPORT_EGL_TRUE= + SUPPORT_EGL_FALSE='#' +else + SUPPORT_EGL_TRUE='#' + SUPPORT_EGL_FALSE= +fi + + +if test "x$NEED_XLIB" = "xyes"; then : + + X11_MODULES="x11 xext xfixes >= 3 xdamage xcomposite >= 0.4 xrandr >= 1.2" + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for DUMMY" >&5 +$as_echo_n "checking for DUMMY... " >&6; } + +if test -n "$DUMMY_CFLAGS"; then + pkg_cv_DUMMY_CFLAGS="$DUMMY_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$X11_MODULES\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$X11_MODULES") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_DUMMY_CFLAGS=`$PKG_CONFIG --cflags "$X11_MODULES" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$DUMMY_LIBS"; then + pkg_cv_DUMMY_LIBS="$DUMMY_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$X11_MODULES\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$X11_MODULES") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_DUMMY_LIBS=`$PKG_CONFIG --libs "$X11_MODULES" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + DUMMY_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$X11_MODULES" 2>&1` + else + DUMMY_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$X11_MODULES" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$DUMMY_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements ($X11_MODULES) were not met: + +$DUMMY_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables DUMMY_CFLAGS +and DUMMY_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables DUMMY_CFLAGS +and DUMMY_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + DUMMY_CFLAGS=$pkg_cv_DUMMY_CFLAGS + DUMMY_LIBS=$pkg_cv_DUMMY_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES $X11_MODULES" +fi + SUPPORT_X11=yes + SUPPORT_XLIB=yes + + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_X11" + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_X11_SUPPORT" + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_XLIB" + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_XLIB_SUPPORT" + +fi + + if test "x$SUPPORT_X11" = "xyes"; then + X11_TESTS_TRUE= + X11_TESTS_FALSE='#' +else + X11_TESTS_TRUE='#' + X11_TESTS_FALSE= +fi + + if test "x$SUPPORT_X11" = "xyes"; then + SUPPORT_X11_TRUE= + SUPPORT_X11_FALSE='#' +else + SUPPORT_X11_TRUE='#' + SUPPORT_X11_FALSE= +fi + + if test "x$SUPPORT_XLIB" = "xyes"; then + SUPPORT_XLIB_TRUE= + SUPPORT_XLIB_FALSE='#' +else + SUPPORT_XLIB_TRUE='#' + SUPPORT_XLIB_FALSE= +fi + + +GLIB_PREFIX="`$PKG_CONFIG --variable=prefix glib-2.0`" +GDKPIXBUF_PREFIX="`$PKG_CONFIG --variable=prefix gdk-pixbuf-2.0`" + + + + + +if test -n "$COGL_PKG_REQUIRES"; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for COGL_DEP" >&5 +$as_echo_n "checking for COGL_DEP... " >&6; } + +if test -n "$COGL_DEP_CFLAGS"; then + pkg_cv_COGL_DEP_CFLAGS="$COGL_DEP_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$COGL_PKG_REQUIRES\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$COGL_PKG_REQUIRES") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_COGL_DEP_CFLAGS=`$PKG_CONFIG --cflags "$COGL_PKG_REQUIRES" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$COGL_DEP_LIBS"; then + pkg_cv_COGL_DEP_LIBS="$COGL_DEP_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$COGL_PKG_REQUIRES\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$COGL_PKG_REQUIRES") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_COGL_DEP_LIBS=`$PKG_CONFIG --libs "$COGL_PKG_REQUIRES" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + COGL_DEP_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$COGL_PKG_REQUIRES" 2>&1` + else + COGL_DEP_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$COGL_PKG_REQUIRES" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$COGL_DEP_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements ($COGL_PKG_REQUIRES) were not met: + +$COGL_DEP_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables COGL_DEP_CFLAGS +and COGL_DEP_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables COGL_DEP_CFLAGS +and COGL_DEP_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + COGL_DEP_CFLAGS=$pkg_cv_COGL_DEP_CFLAGS + COGL_DEP_LIBS=$pkg_cv_COGL_DEP_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + + if test -n "$COGL_PKG_REQUIRES_GL"; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for COGL_DEP_GL" >&5 +$as_echo_n "checking for COGL_DEP_GL... " >&6; } + +if test -n "$COGL_DEP_GL_CFLAGS"; then + pkg_cv_COGL_DEP_GL_CFLAGS="$COGL_DEP_GL_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$COGL_PKG_REQUIRES_GL\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$COGL_PKG_REQUIRES_GL") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_COGL_DEP_GL_CFLAGS=`$PKG_CONFIG --cflags "$COGL_PKG_REQUIRES_GL" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$COGL_DEP_GL_LIBS"; then + pkg_cv_COGL_DEP_GL_LIBS="$COGL_DEP_GL_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$COGL_PKG_REQUIRES_GL\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$COGL_PKG_REQUIRES_GL") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_COGL_DEP_GL_LIBS=`$PKG_CONFIG --libs "$COGL_PKG_REQUIRES_GL" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + COGL_DEP_GL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$COGL_PKG_REQUIRES_GL" 2>&1` + else + COGL_DEP_GL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$COGL_PKG_REQUIRES_GL" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$COGL_DEP_GL_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements ($COGL_PKG_REQUIRES_GL) were not met: + +$COGL_DEP_GL_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables COGL_DEP_GL_CFLAGS +and COGL_DEP_GL_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables COGL_DEP_GL_CFLAGS +and COGL_DEP_GL_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + COGL_DEP_GL_CFLAGS=$pkg_cv_COGL_DEP_GL_CFLAGS + COGL_DEP_GL_LIBS=$pkg_cv_COGL_DEP_GL_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + + gl_libs="" + for x in $COGL_DEP_GL_LIBS; do + case $x in #( + -lGL) : + ;; #( + -lGLESv2) : + ;; #( + -lGLESv1_CM) : + ;; #( + *) : + gl_libs="$gl_libs $x" ;; #( + *) : + ;; +esac + done + COGL_DEP_CFLAGS="$COGL_DEP_CFLAGS $COGL_DEP_CFLAGS_GL" + COGL_DEP_LIBS="$COGL_DEP_LIBS $gl_libs" + fi +fi + + +if test "x$enable_cogl_pango" = "xyes"; then : + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for COGL_PANGO_DEP" >&5 +$as_echo_n "checking for COGL_PANGO_DEP... " >&6; } + +if test -n "$COGL_PANGO_DEP_CFLAGS"; then + pkg_cv_COGL_PANGO_DEP_CFLAGS="$COGL_PANGO_DEP_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$COGL_PANGO_PKG_REQUIRES\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$COGL_PANGO_PKG_REQUIRES") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_COGL_PANGO_DEP_CFLAGS=`$PKG_CONFIG --cflags "$COGL_PANGO_PKG_REQUIRES" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$COGL_PANGO_DEP_LIBS"; then + pkg_cv_COGL_PANGO_DEP_LIBS="$COGL_PANGO_DEP_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$COGL_PANGO_PKG_REQUIRES\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$COGL_PANGO_PKG_REQUIRES") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_COGL_PANGO_DEP_LIBS=`$PKG_CONFIG --libs "$COGL_PANGO_PKG_REQUIRES" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + COGL_PANGO_DEP_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$COGL_PANGO_PKG_REQUIRES" 2>&1` + else + COGL_PANGO_DEP_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$COGL_PANGO_PKG_REQUIRES" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$COGL_PANGO_DEP_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements ($COGL_PANGO_PKG_REQUIRES) were not met: + +$COGL_PANGO_DEP_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables COGL_PANGO_DEP_CFLAGS +and COGL_PANGO_DEP_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables COGL_PANGO_DEP_CFLAGS +and COGL_PANGO_DEP_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + COGL_PANGO_DEP_CFLAGS=$pkg_cv_COGL_PANGO_DEP_CFLAGS + COGL_PANGO_DEP_LIBS=$pkg_cv_COGL_PANGO_DEP_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + +fi + if test "x$enable_cogl_pango" = "xyes"; then + BUILD_COGL_PANGO_TRUE= + BUILD_COGL_PANGO_FALSE='#' +else + BUILD_COGL_PANGO_TRUE='#' + BUILD_COGL_PANGO_FALSE= +fi + + + if test "x$enable_cogl_path" = "xyes"; then + BUILD_COGL_PATH_TRUE= + BUILD_COGL_PATH_FALSE='#' +else + BUILD_COGL_PATH_TRUE='#' + BUILD_COGL_PATH_FALSE= +fi + + + + + + + + # Check whether --enable-introspection was given. +if test "${enable_introspection+set}" = set; then : + enableval=$enable_introspection; +else + enable_introspection=auto +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gobject-introspection" >&5 +$as_echo_n "checking for gobject-introspection... " >&6; } + + case $enable_introspection in #( + no) : + found_introspection="no (disabled, use --enable-introspection to enable)" + ;; #( + yes) : + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-introspection-1.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gobject-introspection-1.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + : +else + as_fn_error $? "gobject-introspection-1.0 is not installed" "$LINENO" 5 +fi + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-introspection-1.0 >= 0.9.5\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gobject-introspection-1.0 >= 0.9.5") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + found_introspection=yes +else + as_fn_error $? "You need to have gobject-introspection >= 0.9.5 installed to build cogl" "$LINENO" 5 +fi + ;; #( + auto) : + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-introspection-1.0 >= 0.9.5\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gobject-introspection-1.0 >= 0.9.5") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + found_introspection=yes +else + found_introspection=no +fi + ;; #( + *) : + as_fn_error $? "invalid argument passed to --enable-introspection, should be one of [no/auto/yes]" "$LINENO" 5 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $found_introspection" >&5 +$as_echo "$found_introspection" >&6; } + + INTROSPECTION_SCANNER= + INTROSPECTION_COMPILER= + INTROSPECTION_GENERATE= + INTROSPECTION_GIRDIR= + INTROSPECTION_TYPELIBDIR= + if test "x$found_introspection" = "xyes"; then + INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0` + INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0` + INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0` + INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0` + INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)" + INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0` + INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0` + INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection + fi + + + + + + + + + + if test "x$found_introspection" = "xyes"; then + HAVE_INTROSPECTION_TRUE= + HAVE_INTROSPECTION_FALSE='#' +else + HAVE_INTROSPECTION_TRUE='#' + HAVE_INTROSPECTION_FALSE= +fi + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for X" >&5 +$as_echo_n "checking for X... " >&6; } + + +# Check whether --with-x was given. +if test "${with_x+set}" = set; then : + withval=$with_x; +fi + +# $have_x is `yes', `no', `disabled', or empty when we do not yet know. +if test "x$with_x" = xno; then + # The user explicitly disabled X. + have_x=disabled +else + case $x_includes,$x_libraries in #( + *\'*) as_fn_error $? "cannot use X directory names containing '" "$LINENO" 5;; #( + *,NONE | NONE,*) if ${ac_cv_have_x+:} false; then : + $as_echo_n "(cached) " >&6 +else + # One or both of the vars are not set, and there is no cached value. +ac_x_includes=no ac_x_libraries=no +rm -f -r conftest.dir +if mkdir conftest.dir; then + cd conftest.dir + cat >Imakefile <<'_ACEOF' +incroot: + @echo incroot='${INCROOT}' +usrlibdir: + @echo usrlibdir='${USRLIBDIR}' +libdir: + @echo libdir='${LIBDIR}' +_ACEOF + if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then + # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. + for ac_var in incroot usrlibdir libdir; do + eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`" + done + # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. + for ac_extension in a so sl dylib la dll; do + if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" && + test -f "$ac_im_libdir/libX11.$ac_extension"; then + ac_im_usrlibdir=$ac_im_libdir; break + fi + done + # Screen out bogus values from the imake configuration. They are + # bogus both because they are the default anyway, and because + # using them would break gcc on systems where it needs fixed includes. + case $ac_im_incroot in + /usr/include) ac_x_includes= ;; + *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; + esac + case $ac_im_usrlibdir in + /usr/lib | /usr/lib64 | /lib | /lib64) ;; + *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; + esac + fi + cd .. + rm -f -r conftest.dir +fi + +# Standard set of common directories for X headers. +# Check X11 before X11Rn because it is often a symlink to the current release. +ac_x_header_dirs=' +/usr/X11/include +/usr/X11R7/include +/usr/X11R6/include +/usr/X11R5/include +/usr/X11R4/include + +/usr/include/X11 +/usr/include/X11R7 +/usr/include/X11R6 +/usr/include/X11R5 +/usr/include/X11R4 + +/usr/local/X11/include +/usr/local/X11R7/include +/usr/local/X11R6/include +/usr/local/X11R5/include +/usr/local/X11R4/include + +/usr/local/include/X11 +/usr/local/include/X11R7 +/usr/local/include/X11R6 +/usr/local/include/X11R5 +/usr/local/include/X11R4 + +/usr/X386/include +/usr/x386/include +/usr/XFree86/include/X11 + +/usr/include +/usr/local/include +/usr/unsupported/include +/usr/athena/include +/usr/local/x11r5/include +/usr/lpp/Xamples/include + +/usr/openwin/include +/usr/openwin/share/include' + +if test "$ac_x_includes" = no; then + # Guess where to find include files, by looking for Xlib.h. + # First, try using that file with no special directory specified. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # We can compile using X headers with no special include directory. +ac_x_includes= +else + for ac_dir in $ac_x_header_dirs; do + if test -r "$ac_dir/X11/Xlib.h"; then + ac_x_includes=$ac_dir + break + fi +done +fi +rm -f conftest.err conftest.i conftest.$ac_ext +fi # $ac_x_includes = no + +if test "$ac_x_libraries" = no; then + # Check for the libraries. + # See if we find them without any special options. + # Don't add to $LIBS permanently. + ac_save_LIBS=$LIBS + LIBS="-lX11 $LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +XrmInitialize () + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + LIBS=$ac_save_LIBS +# We can link X programs with no special library path. +ac_x_libraries= +else + LIBS=$ac_save_LIBS +for ac_dir in `$as_echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g` +do + # Don't even attempt the hair of trying to link an X program! + for ac_extension in a so sl dylib la dll; do + if test -r "$ac_dir/libX11.$ac_extension"; then + ac_x_libraries=$ac_dir + break 2 + fi + done +done +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi # $ac_x_libraries = no + +case $ac_x_includes,$ac_x_libraries in #( + no,* | *,no | *\'*) + # Didn't find X, or a directory has "'" in its name. + ac_cv_have_x="have_x=no";; #( + *) + # Record where we found X for the cache. + ac_cv_have_x="have_x=yes\ + ac_x_includes='$ac_x_includes'\ + ac_x_libraries='$ac_x_libraries'" +esac +fi +;; #( + *) have_x=yes;; + esac + eval "$ac_cv_have_x" +fi # $with_x != no + +if test "$have_x" != yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_x" >&5 +$as_echo "$have_x" >&6; } + no_x=yes +else + # If each of the values was on the command line, it overrides each guess. + test "x$x_includes" = xNONE && x_includes=$ac_x_includes + test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries + # Update the cache value to reflect the command line values. + ac_cv_have_x="have_x=yes\ + ac_x_includes='$x_includes'\ + ac_x_libraries='$x_libraries'" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: libraries $x_libraries, headers $x_includes" >&5 +$as_echo "libraries $x_libraries, headers $x_includes" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +for ac_header in fcntl.h limits.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +ac_fn_c_check_header_mongrel "$LINENO" "endian.h" "ac_cv_header_endian_h" "$ac_includes_default" +if test "x$ac_cv_header_endian_h" = xyes; then : + ac_fn_c_check_decl "$LINENO" "__FLOAT_WORD_ORDER" "ac_cv_have_decl___FLOAT_WORD_ORDER" "$ac_includes_default" +if test "x$ac_cv_have_decl___FLOAT_WORD_ORDER" = xyes; then : + +$as_echo "#define HAVE_FLOAT_WORD_ORDER 1" >>confdefs.h + +fi + +fi + + + + +for ac_func in ffs +do : + ac_fn_c_check_func "$LINENO" "ffs" "ac_cv_func_ffs" +if test "x$ac_cv_func_ffs" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_FFS 1 +_ACEOF + +fi +done + + +for ac_func in memmem +do : + ac_fn_c_check_func "$LINENO" "memmem" "ac_cv_func_memmem" +if test "x$ac_cv_func_memmem" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_MEMMEM 1 +_ACEOF + +fi +done + + +save_libs="$LIBS" +LIBS="$LIBS $LIBM" +for ac_func in sincos +do : + ac_fn_c_check_func "$LINENO" "sincos" "ac_cv_func_sincos" +if test "x$ac_cv_func_sincos" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SINCOS 1 +_ACEOF + +fi +done + +LIBS="$save_libs" + + +have_poll_h=no +ac_fn_c_check_header_mongrel "$LINENO" "poll.h" "ac_cv_header_poll_h" "$ac_includes_default" +if test "x$ac_cv_header_poll_h" = xyes; then : + + if ac_fn_c_compute_int "$LINENO" "POLLIN" "COGL_SYSDEF_POLLIN" "#include "; then : + +else + as_fn_error $? "Unable to get value of POLLIN" "$LINENO" 5 +fi + + if ac_fn_c_compute_int "$LINENO" "POLLPRI" "COGL_SYSDEF_POLLPRI" "#include "; then : + +else + as_fn_error $? "Unable to get value of POLLPRI" "$LINENO" 5 +fi + + if ac_fn_c_compute_int "$LINENO" "POLLOUT" "COGL_SYSDEF_POLLOUT" "#include "; then : + +else + as_fn_error $? "Unable to get value of POLLOUT" "$LINENO" 5 +fi + + if ac_fn_c_compute_int "$LINENO" "POLLERR" "COGL_SYSDEF_POLLERR" "#include "; then : + +else + as_fn_error $? "Unable to get value of POLLERR" "$LINENO" 5 +fi + + if ac_fn_c_compute_int "$LINENO" "POLLHUP" "COGL_SYSDEF_POLLHUP" "#include "; then : + +else + as_fn_error $? "Unable to get value of POLLHUP" "$LINENO" 5 +fi + + if ac_fn_c_compute_int "$LINENO" "POLLNVAL" "COGL_SYSDEF_POLLNVAL" "#include "; then : + +else + as_fn_error $? "Unable to get value of POLLNVAL" "$LINENO" 5 +fi + + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_POLL_SUPPORT" + have_poll_h=yes + +fi + + + +if test "x$have_poll_h" = "xno"; then : + + COGL_SYSDEF_POLLIN=1 + COGL_SYSDEF_POLLPRI=2 + COGL_SYSDEF_POLLOUT=4 + COGL_SYSDEF_POLLERR=8 + COGL_SYSDEF_POLLHUP=16 + COGL_SYSDEF_POLLNVAL=32 + +fi + +COGL_DEFINES_EXTRA="$COGL_DEFINES_EXTRA +#define COGL_SYSDEF_POLLIN $COGL_SYSDEF_POLLIN +#define COGL_SYSDEF_POLLPRI $COGL_SYSDEF_POLLPRI +#define COGL_SYSDEF_POLLOUT $COGL_SYSDEF_POLLOUT +#define COGL_SYSDEF_POLLERR $COGL_SYSDEF_POLLERR +#define COGL_SYSDEF_POLLHUP $COGL_SYSDEF_POLLHUP +#define COGL_SYSDEF_POLLNVAL $COGL_SYSDEF_POLLNVAL +" + +COGL_DEFINES="$COGL_DEFINES_EXTRA" +for x in $COGL_DEFINES_SYMBOLS; do + COGL_DEFINES="$COGL_DEFINES +#define $x 1" +done; + + + +if test "x$cogl_gl_headers" = "x"; then : + as_fn_error $? "Internal error: no GL header set" "$LINENO" 5 +fi +COGL_GL_HEADER_INCLUDES="" +for x in $cogl_gl_headers; do + COGL_GL_HEADER_INCLUDES="$COGL_GL_HEADER_INCLUDES +#include <$x>" +done; + + + + + + + + + + + + +# just for compatability with the clutter build... +MAINTAINER_CFLAGS= + + +ac_config_files="$ac_config_files Makefile test-fixtures/Makefile cogl/Makefile cogl/mutter-cogl-1.0.pc cogl/cogl-defines.h cogl/cogl-gl-header.h cogl/cogl-egl-defines.h cogl-pango/Makefile cogl-pango/mutter-cogl-pango-1.0.pc cogl-path/Makefile cogl-path/mutter-cogl-path-1.0.pc cogl-gles2/Makefile cogl-gles2/mutter-cogl-gles2-1.0.pc tests/Makefile tests/config.env tests/conform/Makefile tests/unit/Makefile tests/micro-perf/Makefile tests/data/Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 +$as_echo_n "checking that generated files are newer than configure... " >&6; } + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 +$as_echo "done" >&6; } +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ENABLE_INSTALLED_TESTS_TRUE}" && test -z "${ENABLE_INSTALLED_TESTS_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_INSTALLED_TESTS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${UNIT_TESTS_TRUE}" && test -z "${UNIT_TESTS_FALSE}"; then + as_fn_error $? "conditional \"UNIT_TESTS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${PROFILE_TRUE}" && test -z "${PROFILE_FALSE}"; then + as_fn_error $? "conditional \"PROFILE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${COGL_DRIVER_GL_SUPPORTED_TRUE}" && test -z "${COGL_DRIVER_GL_SUPPORTED_FALSE}"; then + as_fn_error $? "conditional \"COGL_DRIVER_GL_SUPPORTED\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${COGL_DRIVER_GLES_SUPPORTED_TRUE}" && test -z "${COGL_DRIVER_GLES_SUPPORTED_FALSE}"; then + as_fn_error $? "conditional \"COGL_DRIVER_GLES_SUPPORTED\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_COGL_DEFAULT_DRIVER_TRUE}" && test -z "${HAVE_COGL_DEFAULT_DRIVER_FALSE}"; then + as_fn_error $? "conditional \"HAVE_COGL_DEFAULT_DRIVER\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_COGL_GLES2_TRUE}" && test -z "${BUILD_COGL_GLES2_FALSE}"; then + as_fn_error $? "conditional \"BUILD_COGL_GLES2\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${SUPPORT_GLX_TRUE}" && test -z "${SUPPORT_GLX_FALSE}"; then + as_fn_error $? "conditional \"SUPPORT_GLX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${SUPPORT_EGL_PLATFORM_KMS_TRUE}" && test -z "${SUPPORT_EGL_PLATFORM_KMS_FALSE}"; then + as_fn_error $? "conditional \"SUPPORT_EGL_PLATFORM_KMS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${SUPPORT_WAYLAND_EGL_SERVER_TRUE}" && test -z "${SUPPORT_WAYLAND_EGL_SERVER_FALSE}"; then + as_fn_error $? "conditional \"SUPPORT_WAYLAND_EGL_SERVER\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${SUPPORT_EGL_PLATFORM_XLIB_TRUE}" && test -z "${SUPPORT_EGL_PLATFORM_XLIB_FALSE}"; then + as_fn_error $? "conditional \"SUPPORT_EGL_PLATFORM_XLIB\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${SUPPORT_EGL_TRUE}" && test -z "${SUPPORT_EGL_FALSE}"; then + as_fn_error $? "conditional \"SUPPORT_EGL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${X11_TESTS_TRUE}" && test -z "${X11_TESTS_FALSE}"; then + as_fn_error $? "conditional \"X11_TESTS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${SUPPORT_X11_TRUE}" && test -z "${SUPPORT_X11_FALSE}"; then + as_fn_error $? "conditional \"SUPPORT_X11\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${SUPPORT_XLIB_TRUE}" && test -z "${SUPPORT_XLIB_FALSE}"; then + as_fn_error $? "conditional \"SUPPORT_XLIB\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_COGL_PANGO_TRUE}" && test -z "${BUILD_COGL_PANGO_FALSE}"; then + as_fn_error $? "conditional \"BUILD_COGL_PANGO\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_COGL_PATH_TRUE}" && test -z "${BUILD_COGL_PATH_FALSE}"; then + as_fn_error $? "conditional \"BUILD_COGL_PATH\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_INTROSPECTION_TRUE}" && test -z "${HAVE_INTROSPECTION_FALSE}"; then + as_fn_error $? "conditional \"HAVE_INTROSPECTION\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by cogl $as_me 1.22.1, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to the package provider." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +cogl config.status 1.22.1 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' +lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' +want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' +nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' +lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' +configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`' +predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`' +postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`' +predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`' +postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`' +LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`' +reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`' +reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' +compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`' +GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`' +archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' +module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' +with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' +no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`' +inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`' +link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`' +always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`' +exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`' +include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`' +prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`' +postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`' +file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`' +predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`' +postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`' +predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`' +postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in SHELL \ +ECHO \ +PATH_SEPARATOR \ +SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +OBJDUMP \ +deplibs_check_method \ +file_magic_cmd \ +file_magic_glob \ +want_nocaseglob \ +DLLTOOL \ +sharedlib_from_linklib_cmd \ +AR \ +AR_FLAGS \ +archiver_list_spec \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_import \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +lt_cv_nm_interface \ +nm_file_list_spec \ +lt_cv_truncate_bin \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_pic \ +lt_prog_compiler_wl \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +MANIFEST_TOOL \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_separator \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +install_override_mode \ +finish_eval \ +old_striplib \ +striplib \ +compiler_lib_search_dirs \ +predep_objects \ +postdep_objects \ +predeps \ +postdeps \ +compiler_lib_search_path \ +LD_CXX \ +reload_flag_CXX \ +compiler_CXX \ +lt_prog_compiler_no_builtin_flag_CXX \ +lt_prog_compiler_pic_CXX \ +lt_prog_compiler_wl_CXX \ +lt_prog_compiler_static_CXX \ +lt_cv_prog_compiler_c_o_CXX \ +export_dynamic_flag_spec_CXX \ +whole_archive_flag_spec_CXX \ +compiler_needs_object_CXX \ +with_gnu_ld_CXX \ +allow_undefined_flag_CXX \ +no_undefined_flag_CXX \ +hardcode_libdir_flag_spec_CXX \ +hardcode_libdir_separator_CXX \ +exclude_expsyms_CXX \ +include_expsyms_CXX \ +file_list_spec_CXX \ +compiler_lib_search_dirs_CXX \ +predep_objects_CXX \ +postdep_objects_CXX \ +predeps_CXX \ +postdeps_CXX \ +compiler_lib_search_path_CXX; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postlink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +configure_time_dlsearch_path \ +configure_time_lt_sys_library_path \ +reload_cmds_CXX \ +old_archive_cmds_CXX \ +old_archive_from_new_cmds_CXX \ +old_archive_from_expsyms_cmds_CXX \ +archive_cmds_CXX \ +archive_expsym_cmds_CXX \ +module_cmds_CXX \ +module_expsym_cmds_CXX \ +export_symbols_cmds_CXX \ +prelink_cmds_CXX \ +postlink_cmds_CXX; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +ac_aux_dir='$ac_aux_dir' + +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile' + + + +ac_aux_dir='$ac_aux_dir' + + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "cogl-config.h") CONFIG_HEADERS="$CONFIG_HEADERS cogl-config.h" ;; + "cogl-mutter-config.h") CONFIG_HEADERS="$CONFIG_HEADERS cogl-mutter-config.h" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "test-fixtures/Makefile") CONFIG_FILES="$CONFIG_FILES test-fixtures/Makefile" ;; + "cogl/Makefile") CONFIG_FILES="$CONFIG_FILES cogl/Makefile" ;; + "cogl/mutter-cogl-1.0.pc") CONFIG_FILES="$CONFIG_FILES cogl/mutter-cogl-1.0.pc" ;; + "cogl/cogl-defines.h") CONFIG_FILES="$CONFIG_FILES cogl/cogl-defines.h" ;; + "cogl/cogl-gl-header.h") CONFIG_FILES="$CONFIG_FILES cogl/cogl-gl-header.h" ;; + "cogl/cogl-egl-defines.h") CONFIG_FILES="$CONFIG_FILES cogl/cogl-egl-defines.h" ;; + "cogl-pango/Makefile") CONFIG_FILES="$CONFIG_FILES cogl-pango/Makefile" ;; + "cogl-pango/mutter-cogl-pango-1.0.pc") CONFIG_FILES="$CONFIG_FILES cogl-pango/mutter-cogl-pango-1.0.pc" ;; + "cogl-path/Makefile") CONFIG_FILES="$CONFIG_FILES cogl-path/Makefile" ;; + "cogl-path/mutter-cogl-path-1.0.pc") CONFIG_FILES="$CONFIG_FILES cogl-path/mutter-cogl-path-1.0.pc" ;; + "cogl-gles2/Makefile") CONFIG_FILES="$CONFIG_FILES cogl-gles2/Makefile" ;; + "cogl-gles2/mutter-cogl-gles2-1.0.pc") CONFIG_FILES="$CONFIG_FILES cogl-gles2/mutter-cogl-gles2-1.0.pc" ;; + "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;; + "tests/config.env") CONFIG_FILES="$CONFIG_FILES tests/config.env" ;; + "tests/conform/Makefile") CONFIG_FILES="$CONFIG_FILES tests/conform/Makefile" ;; + "tests/unit/Makefile") CONFIG_FILES="$CONFIG_FILES tests/unit/Makefile" ;; + "tests/micro-perf/Makefile") CONFIG_FILES="$CONFIG_FILES tests/micro-perf/Makefile" ;; + "tests/data/Makefile") CONFIG_FILES="$CONFIG_FILES tests/data/Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "$am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + "libtool":C) + + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +# The names of the tagged configurations supported by this script. +available_tags='CXX ' + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# Shared archive member basename,for filename based shared library versioning on AIX. +shared_archive_member_spec=$shared_archive_member_spec + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + +# The PATH separator for the build system. +PATH_SEPARATOR=$lt_PATH_SEPARATOR + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# convert \$build file names to \$host format. +to_host_file_cmd=$lt_cv_to_host_file_cmd + +# convert \$build files to toolchain format. +to_tool_file_cmd=$lt_cv_to_tool_file_cmd + +# An object symbol dumper. +OBJDUMP=$lt_OBJDUMP + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method = "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob=$lt_file_magic_glob + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob=$lt_want_nocaseglob + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd + +# The archiver. +AR=$lt_AR + +# Flags to create an archive. +AR_FLAGS=$lt_AR_FLAGS + +# How to feed a file listing to the archiver. +archiver_list_spec=$lt_archiver_list_spec + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm into a list of symbols to manually relocate. +global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# The name lister interface. +nm_interface=$lt_lt_cv_nm_interface + +# Specify filename containing input files for \$NM. +nm_file_list_spec=$lt_nm_file_list_spec + +# The root where to search for dependent libraries,and where our libraries should be installed. +lt_sysroot=$lt_sysroot + +# Command to truncate a binary pipe. +lt_truncate_bin=$lt_lt_cv_truncate_bin + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Manifest tool. +MANIFEST_TOOL=$lt_MANIFEST_TOOL + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Detected run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path + +# Explicit LT_SYS_LIBRARY_PATH set during ./configure time. +configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \$shlibpath_var if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# The directories searched by this compiler when creating a shared library. +compiler_lib_search_dirs=$lt_compiler_lib_search_dirs + +# Dependencies to place before and after the objects being linked to +# create a shared library. +predep_objects=$lt_predep_objects +postdep_objects=$lt_postdep_objects +predeps=$lt_predeps +postdeps=$lt_postdeps + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path + +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain=$ac_aux_dir/ltmain.sh + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + + cat <<_LT_EOF >> "$ofile" + +# ### BEGIN LIBTOOL TAG CONFIG: CXX + +# The linker used to build libraries. +LD=$lt_LD_CXX + +# How to create reloadable object files. +reload_flag=$lt_reload_flag_CXX +reload_cmds=$lt_reload_cmds_CXX + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds_CXX + +# A language specific compiler. +CC=$lt_compiler_CXX + +# Is the compiler the GNU compiler? +with_gcc=$GCC_CXX + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_CXX + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_CXX + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_CXX + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_CXX + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object_CXX + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds_CXX +archive_expsym_cmds=$lt_archive_expsym_cmds_CXX + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds_CXX +module_expsym_cmds=$lt_module_expsym_cmds_CXX + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld_CXX + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_CXX + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_CXX + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct_CXX + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \$shlibpath_var if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute_CXX + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L_CXX + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic_CXX + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath_CXX + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_CXX + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols_CXX + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_CXX + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_CXX + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_CXX + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds_CXX + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds_CXX + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec_CXX + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_CXX + +# The directories searched by this compiler when creating a shared library. +compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX + +# Dependencies to place before and after the objects being linked to +# create a shared library. +predep_objects=$lt_predep_objects_CXX +postdep_objects=$lt_postdep_objects_CXX +predeps=$lt_predeps_CXX +postdeps=$lt_postdeps_CXX + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_CXX + +# ### END LIBTOOL TAG CONFIG: CXX +_LT_EOF + + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + +echo "" +echo "Cogl - $COGL_1_VERSION/$COGL_VERSION (${COGL_RELEASE_STATUS})" + +# Global flags +echo "" +echo " • Global:" +echo " Prefix: ${prefix}" +if test "x$COGL_DEFAULT_DRIVER" != "x"; then +echo " Default driver: ${COGL_DEFAULT_DRIVER}" +fi + +echo "" +# Features +echo " • Features:" +echo " Drivers: ${enabled_drivers}" +for driver in $enabled_drivers; do + driver=`echo $driver | tr "gles" "GLES"` + libname=`eval echo \\$COGL_${driver}_LIBNAME` + echo " Library name for $driver: $libname" +done +echo " GL Window System APIs:${GL_WINSYS_APIS}" +if test "x$SUPPORT_EGL" = "xyes"; then +echo " EGL Platforms:${EGL_PLATFORMS}" +echo " Wayland compositor support: ${enable_wayland_egl_server}" +fi +echo " Build libcogl-gles2 GLES 2.0 frontend api: ${enable_cogl_gles2}" +echo " Image backend: ${COGL_IMAGE_BACKEND}" +echo " Cogl Pango: ${enable_cogl_pango}" +echo " Cogl Path: ${enable_cogl_path}" + +# Compiler/Debug related flags +echo "" +echo " • Build options:" +echo " Debugging: ${enable_debug}" +echo " Profiling: ${enable_profile}" +echo " Enable deprecated symbols: ${enable_deprecated}" +echo " Compiler flags: ${CFLAGS} ${COGL_EXTRA_CFLAGS}" +echo " Linker flags: ${LDFLAGS} ${COGL_EXTRA_LDFLAGS}" + +# Miscellaneous +echo "" +echo " • Extra:" +echo " Build introspection data: ${enable_introspection}" +echo " Build unit tests: ${enable_unit_tests}" + +echo "" diff --git a/cogl/configure.ac b/cogl/configure.ac new file mode 100644 index 0000000..3ed761c --- /dev/null +++ b/cogl/configure.ac @@ -0,0 +1,1014 @@ +AC_PREREQ(2.59) + +dnl ================================================================ +dnl XXX: If you are making a release then you need to check these +dnl sections: +dnl » API versions (Only the 1.x version needs to change) +dnl (the pretty numbers that the users see) +dnl +dnl » Interface version details for libtool +dnl (the shared library versioning information) +dnl +dnl » Source code release status +dnl (mark the source code as being part of a "release" or from "git") +dnl ================================================================ + +dnl ================================================================ +dnl API versions (i.e. the pretty numbers that users see) +dnl ================================================================ +m4_define([cogl_major_version], [2]) +m4_define([cogl_minor_version], [0]) +m4_define([cogl_micro_version], [0]) +m4_define([cogl_version], + [cogl_major_version.cogl_minor_version.cogl_micro_version]) + +dnl Since the core Cogl library has to also maintain support for the +dnl Cogl 1.x API for Clutter then we track the 1.x version separately. +m4_define([cogl_1_minor_version], [22]) +m4_define([cogl_1_micro_version], [1]) +m4_define([cogl_1_version], [1.cogl_1_minor_version.cogl_1_micro_version]) + +dnl ================================================================ +dnl Interface version details for libtool +dnl ================================================================ +# Note: we don't automatically deduce the libtool version info from +# the pretty version number that users sees. This is because we want +# to update the pretty version number before making a release since it +# can affect the name of our pkg-config file and the naming or +# location of other installed files which we want to be able to verify +# as correct well before making a release. +# +# For reference on how the various numbers should be updated at +# release time these rules are adapted from the libtool info pages: +# +# 1. Update the version information only immediately before a public +# release. +# +# 2. If the library source code has changed at all since the last +# update, then increment REVISION (`C:R:A' becomes `C:r+1:A'). +# +# 3. If any interfaces have been added, removed, or changed since the +# last update, increment CURRENT, and set REVISION to 0. +# +# 4. If any interfaces have been added since the last public release, +# then increment AGE. +# +# 5. If any interfaces have been removed since the last public release, +# then set AGE to 0. +m4_define([cogl_lt_current], 24) +m4_define([cogl_lt_revision], 1) +m4_define([cogl_lt_age], 4) +# We do also tell libtool the pretty version: +m4_define([cogl_lt_release], [cogl_version]) + + +dnl ================================================================ +dnl Source code release status +dnl ================================================================ +# Finally we explicitly track when we are building development source +# from Git vs building source corresponding to a release. As with the +# libtool version info we don't automatically derive this from the +# pretty version number because we want to test the results of +# updating the version number in advance of a release. +# +# Possible status values are: git, snapshot or release +# +m4_define([cogl_release_status], [git]) + +AC_INIT(cogl, [cogl_1_version]) +AC_CONFIG_SRCDIR(cogl/cogl.h) +AC_CONFIG_AUX_DIR([build]) +AC_CONFIG_MACRO_DIR([build/autotools]) +AC_CONFIG_HEADERS(cogl-config.h) +AC_CONFIG_HEADERS(cogl-mutter-config.h) +AC_GNU_SOURCE + +dnl ================================================================ +dnl Required versions for dependencies +dnl ================================================================ +m4_define([glib_req_version], [2.32.0]) +m4_define([pangocairo_req_version], [1.20]) +m4_define([gi_req_version], [0.9.5]) +m4_define([gdk_pixbuf_req_version], [2.0]) +m4_define([uprof_req_version], [0.3]) +m4_define([xfixes_req_version], [3]) +m4_define([xcomposite_req_version], [0.4]) +m4_define([xrandr_req_version], [1.2]) +m4_define([cairo_req_version], [1.10]) +m4_define([wayland_server_req_version], [1.1.90]) +m4_define([mirclient_req_version], [0.9.0]) + +dnl These variables get copied into the generated README +AC_SUBST([GLIB_REQ_VERSION], [glib_req_version]) +AC_SUBST([GDK_PIXBUF_REQ_VERSION], [gdk_pixbuf_req_version]) +AC_SUBST([CAIRO_REQ_VERSION], [cairo_req_version]) +AC_SUBST([PANGOCAIRO_REQ_VERSION], [pangocairo_req_version]) +AC_SUBST([XCOMPOSITE_REQ_VERSION], [xcomposite_req_version]) +AC_SUBST([XFIXES_REQ_VERSION], [xfixes_req_version]) +AC_SUBST([GI_REQ_VERSION], [gi_req_version]) +AC_SUBST([UPROF_REQ_VERSION], [uprof_req_version]) +AC_SUBST([WAYLAND_SERVER_REQ_VERSION], [wayland_server_req_version]) + +# Save this value here, since automake will set cflags later and we +# want to know if the user specified custom cflags or not. +cflags_set=${CFLAGS+set} + +AM_INIT_AUTOMAKE([1.14 foreign -Wno-portability no-define no-dist-gzip dist-xz tar-ustar subdir-objects]) +AM_SILENT_RULES([yes]) + +AH_BOTTOM([#include "config-custom.h"]) + +dnl ================================================================ +dnl Export the API versioning +dnl ================================================================ +AC_SUBST([COGL_MAJOR_VERSION],[cogl_major_version]) +AC_SUBST([COGL_MINOR_VERSION],[cogl_minor_version]) +AC_SUBST([COGL_MICRO_VERSION],[cogl_micro_version]) +AC_SUBST([COGL_VERSION],[cogl_version]) +AC_SUBST([COGL_API_VERSION],[cogl_major_version.0]) +AC_SUBST([COGL_API_VERSION_AM],[$COGL_MAJOR_VERSION\_0]) + +AC_SUBST([COGL_1_MINOR_VERSION],[cogl_1_minor_version]) +AC_SUBST([COGL_1_MICRO_VERSION],[cogl_1_micro_version]) +AC_SUBST([COGL_1_VERSION],[cogl_1_version]) + + +dnl ================================================================ +dnl Export the libtool versioning +dnl ================================================================ +AC_SUBST([COGL_LT_CURRENT], [cogl_lt_current]) +AC_SUBST([COGL_LT_REVISION], [cogl_lt_revision]) +AC_SUBST([COGL_LT_AGE], [cogl_lt_age]) +AC_SUBST([COGL_LT_RELEASE], [cogl_lt_release]) + + +dnl ================================================================ +dnl Export the source code release status +dnl ================================================================ +AC_SUBST([COGL_RELEASE_STATUS], [cogl_release_status]) + +dnl ================================================================ +dnl Compiler stuff. +dnl ================================================================ +AC_PROG_CC +AC_PROG_CPP +AC_PROG_CXX +AM_PROG_CC_C_O +AC_ISC_POSIX +AC_C_CONST + +dnl ============================================================ +dnl Compiler features +dnl ============================================================ +AC_MSG_CHECKING([for _Static_assert]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([_Static_assert (1, "");], + [(void) 0])], + [AC_DEFINE([HAVE_STATIC_ASSERT], [1], + [Whether _Static_assert can be used or not]) + AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no])]) + +dnl ================================================================ +dnl Libtool stuff. +dnl ================================================================ +dnl AC_PROG_LIBTOOL +dnl LIBTOOL="$LIBTOOL --preserve-dup-deps" +LT_PREREQ([2.2.6]) +LT_INIT([disable-static]) +dnl when using libtool 2.x create libtool early, because it's used in the +dnl internal glib configure (as-glibconfig.m4) +m4_ifdef([LT_OUTPUT], [LT_OUTPUT]) + +dnl ================================================================ +dnl Find an appropriate libm, for sin() etc. +dnl ================================================================ +LT_LIB_M +AC_SUBST(LIBM) + +dnl ================================================================ +dnl See what platform we are building for +dnl ================================================================ +AC_CANONICAL_HOST + +dnl ============================================================ +dnl Installed tests +dnl ============================================================ + +AC_ARG_ENABLE(installed_tests, + AS_HELP_STRING([--enable-installed-tests], + [Install test programs (default: no)]),, + [enable_installed_tests=no]) +AM_CONDITIONAL(ENABLE_INSTALLED_TESTS, test x$enable_installed_tests = xyes) + +dnl ============================================================ +dnl Enable debugging +dnl ============================================================ +m4_define([debug_default], [m4_if(cogl_release_status, [git], [yes], [no])]) +AC_ARG_ENABLE( + [debug], + [AC_HELP_STRING([--enable-debug=@<:@no/yes@:>@], [Control Cogl debugging level @<:@default=]debug_default[@:>@])], + [], + enable_debug=debug_default +) +AS_CASE( + [$enable_debug], + [yes], + [ + test "$cflags_set" = set || CFLAGS="$CFLAGS -g -O0" + COGL_EXTRA_CFLAGS="$COGL_EXTRA_CFLAGS -DCOGL_GL_DEBUG -DCOGL_OBJECT_DEBUG -DCOGL_ENABLE_DEBUG" + ], + [no], + [ + COGL_EXTRA_CFLAGS="$COGL_EXTRA_CFLAGS -DG_DISABLE_CHECKS -DG_DISABLE_CAST_CHECKS" + ], + [AC_MSG_ERROR([Unknown argument for --enable-debug])] +) + +AC_SUBST(COGL_DEBUG_CFLAGS) + +AC_ARG_ENABLE( + [unit-tests], + [AC_HELP_STRING([--enable-unit-tests=@<:@no/yes@:>@], [Build Cogl unit tests @<:@default=yes@:>@])], + [], + enable_unit_tests=yes +) +AS_IF([test "x$enable_unit_tests" = "xyes"], + [ + AC_DEFINE([ENABLE_UNIT_TESTS], [1], [Whether to enable building unit tests]) + ] +) +AM_CONDITIONAL(UNIT_TESTS, test "x$enable_unit_tests" = "xyes") + +dnl ============================================================ +dnl Enable cairo usage for debugging +dnl (debugging code can use cairo to dump the atlas) +dnl ============================================================ + +PKG_CHECK_EXISTS([CAIRO], [cairo >= cairo_req_version], [have_cairo=yes]) +AC_ARG_ENABLE( + [cairo], + [AC_HELP_STRING([--enable-cairo=@<:@no/yes@:>@], [Control Cairo usage in Cogl debugging code @<:@default=auto@:>@])], + [], + [ + AS_IF([test "x$enable_debug" = "xyes"], + [enable_cairo=$have_cairo], + [enable_cairo=no]) + ] +) +AS_IF([test "x$enable_cairo" = "xyes" && test "x$enable_debug" = "xyes"], + [ + AS_IF([test "x$have_cairo" != "xyes"], + [AC_MSG_ERROR([Could not find Cairo])]) + + COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES cairo >= cairo_req_version" + AC_DEFINE([HAVE_CAIRO], [1], [Whether we have cairo or not]) + ]) + + +dnl ============================================================ +dnl Enable profiling +dnl ============================================================ +AC_ARG_ENABLE(profile, + [AC_HELP_STRING([--enable-profile=@<:@no/yes@:>@], + [Turn on uprof profiling support. yes; All UProf profiling probe points are compiled in and may be runtime enabled. no; No profiling support will built into cogl. @<:@default=no@:>@])], + [], + [enable_profile=no]) +AS_IF([test "x$enable_profile" = "xyes"], + [ + AS_IF([test "x$GCC" = "xyes"], + [ + COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES uprof-0.3" + COGL_EXTRA_CFLAGS="$COGL_EXTRA_CFLAGS -DCOGL_ENABLE_PROFILE" + AS_IF([test "x$enable_debug" = "xyes"], [COGL_EXTRA_CFLAGS="$COGL_EXTRA_CFLAGS -DUPROF_DEBUG"]) + ], + [ + AC_MSG_ERROR([--enable-profile is currently only supported if using GCC]) + ]) + ]) +AM_CONDITIONAL(PROFILE, test "x$enable_profile" != "xno") + + +dnl ============================================================ +dnl Enable strict compiler flags +dnl ============================================================ + +# use strict compiler flags only when building from git; the rules for +# distcheck will take care of turning this on when making a release +m4_define([maintainer_default], [m4_if(cogl_release_status, [git], [yes], [no])]) +AC_ARG_ENABLE( + [maintainer-flags], + [AC_HELP_STRING([--enable-maintainer-flags=@<:@no/yes/error@:>@], [Use strict compiler flags @<:@default=]maintainer_default[@:>@])], + [], + enable_maintainer_flags=maintainer_default +) + +MAINTAINER_COMPILER_FLAGS="-Wall -Wcast-align -Wformat -Wformat-security + -Werror=uninitialized -Werror=no-strict-aliasing + -Werror=empty-body -Werror=init-self -Werror=undef + -Werror=declaration-after-statement -Werror=vla + -Werror=pointer-arith -Werror=missing-declarations + -Werror=maybe-uninitialized" + +AS_CASE( + [$enable_maintainer_flags], + [yes], + [ + AS_COMPILER_FLAGS([MAINTAINER_CFLAGS], [$MAINTAINER_COMPILER_FLAGS]) + ], + [no], + [ + ], + [error], + [ + MAINTAINER_COMPILER_FLAGS="$MAINTAINER_COMPILER_FLAGS -Werror" + AS_COMPILER_FLAGS([MAINTAINER_CFLAGS], [$MAINTAINER_COMPILER_FLAGS]) + ], + [*], + [AC_MSG_ERROR([Invalid option for --enable-maintainer-flags])] +) + +# strip leading spaces +COGL_EXTRA_CFLAGS="$COGL_EXTRA_CFLAGS ${MAINTAINER_CFLAGS#* }" +COGL_EXTRA_CFLAGS="$COGL_EXTRA_CFLAGS -Wno-error=sign-compare" + + +dnl ============================================================ +dnl Enable deprecation guards +dnl ============================================================ + +# disable deprecated options from Glib only when building from git; +# the rules for distcheck will take care of turning this on when +# making a release +m4_define([deprecated_default], + [m4_if(cogl_release_status, [git], [no], [yes])]) + +AC_ARG_ENABLE([deprecated], + [AS_HELP_STRING([--enable-deprecated=@<:@no/yes@:>@], + [Whether deprecated symbols should be disabled when compiling Cogl @<:@default=]deprecated_default[@:>@])], + [], + [enable_deprecated=deprecated_default]) + +AS_CASE([$enable_deprecated], + + [no], + [ + DEPRECATED_CFLAGS="-DG_DISABLE_DEPRECATED -DG_DISABLE_SINGLE_INCLUDES" + ], + + [yes], + [ + DEPRECATED_CFLAGS="" + ], + + [AC_MSG_ERROR([Unknown argument for --enable-deprecated])] +) + +# strip leading spaces +COGL_EXTRA_CFLAGS="$COGL_EXTRA_CFLAGS ${DEPRECATED_CFLAGS#* }" + +dnl ================================================================ +dnl Check for dependency packages. +dnl ================================================================ + +AM_PATH_GLIB_2_0([glib_req_version], + [], + [AC_MSG_ERROR([glib-2.0 is required])], + [gobject gthread gmodule-no-export]) + +COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES gobject-2.0 gmodule-no-export-2.0" + +dnl ============================================================ +dnl Should cogl-pango be built? +dnl ============================================================ + +AC_ARG_ENABLE( + [cogl-pango], + [AC_HELP_STRING([--enable-cogl-pango=@<:@no/yes@:>@], [Enable pango support @<:@default=yes@:>@])], + [], + enable_cogl_pango=yes +) +AS_IF([test "x$enable_cogl_pango" = "xyes"], + [ + COGL_PANGO_PKG_REQUIRES="$COGL_PANGO_PKG_REQUIRES pangocairo >= pangocairo_req_version" + ] +) + +dnl ============================================================ +dnl Should cogl-path be built? +dnl ============================================================ + +AC_ARG_ENABLE( + [cogl-path], + [AC_HELP_STRING([--enable-cogl-path=@<:@no/yes@:>@], [Enable 2D path support @<:@default=yes@:>@])], + [], + enable_cogl_path=yes +) +AS_IF([test "x$enable_cogl_path" = "xyes"], + [ + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_COGL_PATH_SUPPORT" + ] +) + +dnl ============================================================ +dnl Choose image loading backend +dnl ============================================================ +COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES gdk-pixbuf-2.0 >= gdk_pixbuf_req_version" +COGL_IMAGE_BACKEND="gdk-pixbuf" + +dnl ============================================================ +dnl Determine which drivers and window systems we can support +dnl ============================================================ + +dnl ======================================================== +dnl Drivers first... +dnl ======================================================== +EGL_CHECKED=no + +enabled_drivers="" + +HAVE_GLES1=0 +AC_ARG_ENABLE( + [gles1], + [AC_HELP_STRING([--enable-gles1=@<:@no/yes@:>@], [Enable support for OpenGL-ES 1.1 @<:@default=no@:>@])], + [], + enable_gles1=no +) +AS_IF([test "x$enable_gles1" = "xyes"], + [ + enabled_drivers="$enabled_drivers gles1" + + cogl_gl_headers="GLES/gl.h GLES/glext.h" + + AC_DEFINE([HAVE_COGL_GLES], 1, [Have GLES 1.1 for rendering]) + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_GLES CLUTTER_COGL_HAS_GLES" + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_GLES1" + HAVE_GLES1=1 + + PKG_CHECK_EXISTS([glesv1_cm], + [COGL_PKG_REQUIRES_GL="$COGL_PKG_REQUIRES_GL glesv1_cm" + COGL_GLES1_LIBNAME="libGLESv1_CM.so" + ], + [ + # We have to check the two headers independently as GLES/glext.h + # needs to include GLES/gl.h to have the GL types defined (eg. + # GLenum). + AC_CHECK_HEADER([GLES/gl.h], + [], + [AC_MSG_ERROR([Unable to locate GLES/gl.h])]) + AC_CHECK_HEADER([GLES/glext.h], + [], + [AC_MSG_ERROR([Unable to locate GLES/glext.h])], + [#include ]) + + # Early implementations provided only a GLES/egl.h while Khronos's + # implementer guide now states EGL/egl.h is the One. Some + # implementations keep a GLES/egl.h wrapper around EGL/egl.h for + # backward compatibility while others provide EGL/egl.h only. + AC_CHECK_HEADERS([GLES/egl.h EGL/egl.h]) + + AS_IF([test "x$ac_cv_header_GLES_egl_h" = "xyes"], + [COGL_EGL_INCLUDES="#include "], + [test "x$ac_cv_header_EGL_egl_h" = "xyes"], + [ + COGL_EGL_INCLUDES="#include " + ], + [AC_MSG_ERROR([Unable to locate EGL header])]) + AC_SUBST([COGL_EGL_INCLUDES]) + + AC_CHECK_HEADERS([EGL/eglext.h], + [COGL_EGL_INCLUDES="$COGL_EGL_INCLUDE +#include "], + [], + [$COGL_EGL_INCLUDES]) + + # Check for a GLES 1.x Common Profile library with/without EGL. + # + # Note: historically GLES 1 libraries shipped with the + # EGL and GLES symbols all bundled in one library. Now + # the Khronos Implementers Guide defines two naming + # schemes: -lGLES_CM should be used for a library that + # bundles the GLES and EGL API together and -lGLESv1_CM + # would be used for a standalone GLES API. + AC_CHECK_LIB(GLES_CM, [eglInitialize], + [COGL_GLES1_LIBNAME="libGLES_CM.so"], + [ + AC_CHECK_LIB(GLESv1_CM, [glFlush], + [COGL_GLES1_LIBNAME="libGLESv1_CM.so" + NEED_SEPARATE_EGL=yes + ], + [AC_MSG_ERROR([Unable to locate required GLES 1.x Common Profile library])]) + ]) + + EGL_CHECKED=yes + ]) + ]) + +HAVE_GLES2=0 +AC_ARG_ENABLE( + [gles2], + [AC_HELP_STRING([--enable-gles2=@<:@no/yes@:>@], [Enable support for OpenGL-ES 2.0 @<:@default=no@:>@])], + [], + enable_gles2=no +) +AS_IF([test "x$enable_gles2" = "xyes"], + [ + enabled_drivers="$enabled_drivers gles2" + + cogl_gl_headers="GLES2/gl2.h GLES2/gl2ext.h" + AC_DEFINE([HAVE_COGL_GLES2], 1, [Have GLES 2.0 for rendering]) + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_GLES CLUTTER_COGL_HAS_GLES" + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_GLES2" + HAVE_GLES2=1 + + PKG_CHECK_EXISTS([glesv2], + [COGL_PKG_REQUIRES_GL="$COGL_PKG_REQUIRES_GL glesv2" + COGL_GLES2_LIBNAME="libGLESv2.so" + ], + [ + # We have to check the two headers independently as GLES2/gl2ext.h + # needs to include GLES2/gl2.h to have the GL types defined (eg. + # GLenum). + AC_CHECK_HEADER([GLES2/gl2.h], + [], + [AC_MSG_ERROR([Unable to locate GLES2/gl2.h])]) + AC_CHECK_HEADER([GLES2/gl2ext.h], + [], + [AC_MSG_ERROR([Unable to locate GLES2/gl2ext.h])], + [#include ]) + + COGL_GLES2_LIBNAME="libGLESv2.so" + ]) + ]) + +HAVE_GL=0 +AC_ARG_ENABLE( + [gl], + [AC_HELP_STRING([--enable-gl=@<:@no/yes@:>@], [Enable support for OpenGL @<:@default=yes@:>@])], + [], + [enable_gl=yes] +) +AS_IF([test "x$enable_gl" = "xyes"], + [ + enabled_drivers="$enabled_drivers gl" + + PKG_CHECK_EXISTS([x11], [ALLOW_GLX=yes]) + + cogl_gl_headers="GL/gl.h" + + PKG_CHECK_EXISTS([gl], + dnl We don't want to use COGL_PKG_REQUIRES here because we don't want to + dnl directly link against libGL + [COGL_PKG_REQUIRES_GL="$COGL_PKG_REQUIRES_GL gl"], + [AC_CHECK_LIB(GL, [glGetString], + , + [AC_MSG_ERROR([Unable to locate required GL library])]) + ]) + COGL_GL_LIBNAME="libGL.so.1" + + AC_DEFINE([HAVE_COGL_GL], [1], [Have GL for rendering]) + + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_GL" + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS CLUTTER_COGL_HAS_GL" + HAVE_GL=1 + ]) + +AM_CONDITIONAL([COGL_DRIVER_GL_SUPPORTED], [test "x$enable_gl" = "xyes"]) +AM_CONDITIONAL([COGL_DRIVER_GLES_SUPPORTED], + [test "x$enable_gles1" = "xyes" || test "x$enable_gles2" = "xyes"]) + +dnl Allow the GL library names and default driver to be overridden with configure options +AC_ARG_WITH([gl-libname], + [AS_HELP_STRING([--with-gl-libname], + override the name of the GL library to dlopen)], + [COGL_GL_LIBNAME="$withval"]) +AC_ARG_WITH([gles1-libname], + [AS_HELP_STRING([--with-gles1-libname], + override the name of the GLESv1 library to dlopen)], + [COGL_GLES1_LIBNAME="$withval"]) +AC_ARG_WITH([gles2-libname], + [AS_HELP_STRING([--with-gles2-libname], + override the name of the GLESv2 library to dlopen)], + [COGL_GLES2_LIBNAME="$withval"]) +AC_ARG_WITH([default-driver], + [AS_HELP_STRING([--with-default-driver], + specify a default cogl driver)], + [COGL_DEFAULT_DRIVER="${withval}"], + [COGL_DEFAULT_DRIVER="" ]) + +AM_CONDITIONAL(HAVE_COGL_DEFAULT_DRIVER, + [ test "x$COGL_DEFAULT_DRIVER" != "x" ]) + + +AC_SUBST([COGL_GL_LIBNAME]) +AC_SUBST([HAVE_GL]) +AC_SUBST([COGL_GLES1_LIBNAME]) +AC_SUBST([HAVE_GLES1]) +AC_SUBST([COGL_GLES2_LIBNAME]) +AC_SUBST([HAVE_GLES2]) +AC_SUBST([COGL_DEFAULT_DRIVER]) + +AC_ARG_ENABLE( + [cogl-gles2], + [AC_HELP_STRING([--enable-cogl-gles2=@<:@no/yes@:>@], + [Enable libcogl-gles2 frontend api for OpenGL-ES 2.0 @<:@default=auto@:>@])], + [], + [ + AS_IF([test "x$HAVE_GLES2" = "x1"], + [enable_cogl_gles2=yes], + [enable_cogl_gles2=no]) + ] +) +AS_IF([test "x$enable_cogl_gles2" = "xyes"], + [ + AS_IF([test "x$HAVE_GLES2" != "x1"], + [ + AC_MSG_ERROR([libcogl-gles2 is currently only supported on systems with a native GLES 2.0 library]) + ]) + ]) +AM_CONDITIONAL([BUILD_COGL_GLES2], [test "x$enable_cogl_gles2" = "xyes"]) + + +dnl ======================================================== +dnl Check window system integration libraries... +dnl ======================================================== + +AC_ARG_ENABLE( + [glx], + [AC_HELP_STRING([--enable-glx=@<:@no/yes@:>@], [Enable support GLX @<:@default=auto@:>@])], + [], + [AS_IF([test "x$ALLOW_GLX" = "xyes"], [enable_glx=yes], [enable_glx=no])] +) +AS_IF([test "x$enable_glx" = "xyes"], + [ + AS_IF([test "x$ALLOW_GLX" != "xyes"], + [AC_MSG_ERROR([GLX not supported with this configuration])]) + + NEED_XLIB=yes + SUPPORT_GLX=yes + GL_WINSYS_APIS="$GL_WINSYS_APIS glx" + + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_GLX_SUPPORT" + ]) +AM_CONDITIONAL(SUPPORT_GLX, [test "x$SUPPORT_GLX" = "xyes"]) + +EGL_PLATFORM_COUNT=0 + +AC_ARG_ENABLE( + [kms-egl-platform], + [AC_HELP_STRING([--enable-kms-egl-platform=@<:@no/yes@:>@], [Enable support for the KMS egl platform @<:@default=no@:>@])], + [], + enable_kms_egl_platform=yes +) +AS_IF([test "x$enable_kms_egl_platform" = "xyes"], + [ + EGL_PLATFORM_COUNT=$((EGL_PLATFORM_COUNT+1)) + NEED_EGL=yes + EGL_PLATFORMS="$EGL_PLATFORMS kms" + + PKG_CHECK_EXISTS([gbm], + [ + COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES gbm" + COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES libdrm" + ], + [AC_MSG_ERROR([Unable to locate required libgbm library for the KMS egl platform])]) + + GBM_VERSION=`$PKG_CONFIG --modversion gbm` + GBM_MAJOR=`echo $GBM_VERSION | cut -d'.' -f1` + GBM_MINOR=`echo $GBM_VERSION | cut -d'.' -f2` + GBM_MICRO=`echo $GBM_VERSION | cut -d'.' -f3 | sed 's/-.*//'` + + AC_DEFINE_UNQUOTED([COGL_GBM_MAJOR], [$GBM_MAJOR], [The major version for libgbm]) + AC_DEFINE_UNQUOTED([COGL_GBM_MINOR], [$GBM_MINOR], [The minor version for libgbm]) + AC_DEFINE_UNQUOTED([COGL_GBM_MICRO], [$GBM_MICRO], [The micro version for libgbm]) + + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_EGL_PLATFORM_KMS_SUPPORT" + ]) +AM_CONDITIONAL(SUPPORT_EGL_PLATFORM_KMS, + [test "x$enable_kms_egl_platform" = "xyes"]) + +AC_ARG_ENABLE( + [wayland-egl-server], + [AC_HELP_STRING([--enable-wayland-egl-server=@<:@no/yes@:>@], [Enable server side wayland support @<:@default=no@:>@])], + [], + enable_wayland_egl_server=yes +) +AS_IF([test "x$enable_wayland_egl_server" = "xyes"], + [ + NEED_EGL=yes + + PKG_CHECK_MODULES(WAYLAND_SERVER, + [wayland-server >= wayland_server_req_version]) + COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES wayland-server >= wayland_server_req_version" + + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT" + ]) +AM_CONDITIONAL(SUPPORT_WAYLAND_EGL_SERVER, + [test "x$enable_wayland_egl_server" = "xyes"]) + +dnl This should go last, since it's the default fallback and we need +dnl to check the value of $EGL_PLATFORM_COUNT here. +AC_ARG_ENABLE( + [xlib-egl-platform], + [AC_HELP_STRING([--enable-xlib-egl-platform=@<:@no/yes@:>@], [Enable support for the Xlib egl platform @<:@default=auto@:>@])], + [], + enable_xlib_egl_platform=yes +) +AS_IF([test "x$enable_xlib_egl_platform" = "xyes"], + [ + EGL_PLATFORM_COUNT=$((EGL_PLATFORM_COUNT+1)) + NEED_EGL=yes + NEED_XLIB=yes + EGL_PLATFORMS="$EGL_PLATFORMS xlib" + + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_EGL_PLATFORM_XLIB_SUPPORT" + ]) +AM_CONDITIONAL(SUPPORT_EGL_PLATFORM_XLIB, + [test "x$enable_xlib_egl_platform" = "xyes"]) + +AS_IF([test "x$NEED_EGL" = "xyes" && test "x$EGL_CHECKED" != "xyes"], + [ + PKG_CHECK_EXISTS([egl], + [COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES egl"], + [ + AC_CHECK_HEADERS( + [EGL/egl.h], + [], + [AC_MSG_ERROR([Unable to locate required EGL headers])]) + AC_CHECK_HEADERS( + [EGL/eglext.h], + [], + [AC_MSG_ERROR([Unable to locate required EGL headers])], + [#include ]) + + AC_CHECK_LIB(EGL, [eglInitialize], + [COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -lEGL"], + [AC_MSG_ERROR([Unable to locate required EGL library])]) + + COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -lEGL" + ] + ) + + COGL_EGL_INCLUDES="#include +#include " + AC_SUBST([COGL_EGL_INCLUDES]) + ]) + +AS_IF([test "x$NEED_EGL" = "xyes"], + [ + SUPPORT_EGL=yes + GL_WINSYS_APIS="$GL_WINSYS_APIS egl" + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_EGL_SUPPORT" + ]) + +AM_CONDITIONAL(SUPPORT_EGL, [test "x$SUPPORT_EGL" = "xyes"]) + +dnl ======================================================== +dnl Check X11 dependencies if required +dnl ======================================================== +AS_IF([test "x$NEED_XLIB" = "xyes"], + [ + X11_MODULES="x11 xext xfixes >= xfixes_req_version xdamage xcomposite >= xcomposite_req_version xrandr >= xrandr_req_version" + PKG_CHECK_MODULES(DUMMY, [$X11_MODULES], + [COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES $X11_MODULES"]) + SUPPORT_X11=yes + SUPPORT_XLIB=yes + + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_X11" + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_X11_SUPPORT" + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_XLIB" + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_XLIB_SUPPORT" + ]) + +AM_CONDITIONAL(X11_TESTS, [test "x$SUPPORT_X11" = "xyes"]) +AM_CONDITIONAL(SUPPORT_X11, [test "x$SUPPORT_X11" = "xyes"]) +AM_CONDITIONAL(SUPPORT_XLIB, [test "x$SUPPORT_XLIB" = "xyes"]) + +dnl ================================================================ +dnl Documentation stuff. +dnl ================================================================ +GLIB_PREFIX="`$PKG_CONFIG --variable=prefix glib-2.0`" +GDKPIXBUF_PREFIX="`$PKG_CONFIG --variable=prefix gdk-pixbuf-2.0`" +AC_SUBST(GLIB_PREFIX) +AC_SUBST(GDKPIXBUF_PREFIX) + + +AC_SUBST(COGL_PKG_REQUIRES) +if test -n "$COGL_PKG_REQUIRES"; then + PKG_CHECK_MODULES(COGL_DEP, [$COGL_PKG_REQUIRES]) + + if test -n "$COGL_PKG_REQUIRES_GL"; then + PKG_CHECK_MODULES(COGL_DEP_GL, [$COGL_PKG_REQUIRES_GL]) + + dnl Strip out the GL libraries from the GL pkg-config files so we can + dnl dynamically load them instead + gl_libs="" + for x in $COGL_DEP_GL_LIBS; do + AS_CASE([$x], + [-lGL], [], + [-lGLESv2], [], + [-lGLESv1_CM], [], + [*], [gl_libs="$gl_libs $x"]) + done + COGL_DEP_CFLAGS="$COGL_DEP_CFLAGS $COGL_DEP_CFLAGS_GL" + COGL_DEP_LIBS="$COGL_DEP_LIBS $gl_libs" + fi +fi +AC_SUBST(COGL_PANGO_PKG_REQUIRES) + +AS_IF([test "x$enable_cogl_pango" = "xyes"], + [PKG_CHECK_MODULES(COGL_PANGO_DEP, [$COGL_PANGO_PKG_REQUIRES])] +) +AM_CONDITIONAL([BUILD_COGL_PANGO], [test "x$enable_cogl_pango" = "xyes"]) + +AM_CONDITIONAL([BUILD_COGL_PATH], [test "x$enable_cogl_path" = "xyes"]) + +dnl ================================================================ +dnl Misc program dependencies. +dnl ================================================================ +AC_PROG_INSTALL + +dnl ================================================================ +dnl GObject-Introspection check +dnl ================================================================ +GOBJECT_INTROSPECTION_CHECK([gi_req_version]) + +dnl ================================================================ +dnl Checks for header files. +dnl ================================================================ +AC_PATH_X +AC_HEADER_STDC +AC_CHECK_HEADERS(fcntl.h limits.h unistd.h) +AC_CHECK_HEADER([endian.h], + [AC_CHECK_DECL([__FLOAT_WORD_ORDER], + AC_DEFINE([HAVE_FLOAT_WORD_ORDER], [1], + [Has the __FLOAT_WORD_ORDER macro]))]) + +dnl ================================================================ +dnl Checks for library functions. +dnl ================================================================ + +dnl The 'ffs' function is part of C99 so it isn't always +dnl available. Cogl has a fallback if needed. +AC_CHECK_FUNCS([ffs]) + +dnl 'memmem' is a GNU extension but we have a simple fallback +AC_CHECK_FUNCS([memmem]) + +dnl This is used in the cogl-gles2-gears example but it is a GNU extension +save_libs="$LIBS" +LIBS="$LIBS $LIBM" +AC_CHECK_FUNCS([sincos]) +LIBS="$save_libs" + +dnl ================================================================ +dnl Platform values +dnl ================================================================ + +dnl These are values from system headers that we want to copy into the +dnl public Cogl headers without having to include the system header +have_poll_h=no +AC_CHECK_HEADER(poll.h, + [ + AC_COMPUTE_INT(COGL_SYSDEF_POLLIN, POLLIN, [#include ], + AC_MSG_ERROR([Unable to get value of POLLIN])) + AC_COMPUTE_INT(COGL_SYSDEF_POLLPRI, POLLPRI, [#include ], + AC_MSG_ERROR([Unable to get value of POLLPRI])) + AC_COMPUTE_INT(COGL_SYSDEF_POLLOUT, POLLOUT, [#include ], + AC_MSG_ERROR([Unable to get value of POLLOUT])) + AC_COMPUTE_INT(COGL_SYSDEF_POLLERR, POLLERR, [#include ], + AC_MSG_ERROR([Unable to get value of POLLERR])) + AC_COMPUTE_INT(COGL_SYSDEF_POLLHUP, POLLHUP, [#include ], + AC_MSG_ERROR([Unable to get value of POLLHUP])) + AC_COMPUTE_INT(COGL_SYSDEF_POLLNVAL, POLLNVAL, [#include ], + AC_MSG_ERROR([Unable to get value of POLLNVAL])) + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_POLL_SUPPORT" + have_poll_h=yes + ]) + +AS_IF([test "x$have_poll_h" = "xno"], + [ + COGL_SYSDEF_POLLIN=1 + COGL_SYSDEF_POLLPRI=2 + COGL_SYSDEF_POLLOUT=4 + COGL_SYSDEF_POLLERR=8 + COGL_SYSDEF_POLLHUP=16 + COGL_SYSDEF_POLLNVAL=32 + ]) + +COGL_DEFINES_EXTRA="$COGL_DEFINES_EXTRA +#define COGL_SYSDEF_POLLIN $COGL_SYSDEF_POLLIN +#define COGL_SYSDEF_POLLPRI $COGL_SYSDEF_POLLPRI +#define COGL_SYSDEF_POLLOUT $COGL_SYSDEF_POLLOUT +#define COGL_SYSDEF_POLLERR $COGL_SYSDEF_POLLERR +#define COGL_SYSDEF_POLLHUP $COGL_SYSDEF_POLLHUP +#define COGL_SYSDEF_POLLNVAL $COGL_SYSDEF_POLLNVAL +" + +dnl ================================================================ +dnl What needs to be substituted in other files +dnl ================================================================ +COGL_DEFINES="$COGL_DEFINES_EXTRA" +for x in $COGL_DEFINES_SYMBOLS; do + COGL_DEFINES="$COGL_DEFINES +#define $x 1" +done; +AC_SUBST(COGL_DEFINES) +AM_SUBST_NOTMAKE(COGL_DEFINES) + +AS_IF([test "x$cogl_gl_headers" = "x"], + [AC_MSG_ERROR([Internal error: no GL header set])]) +dnl cogl_gl_headers is a space separate list of headers to +dnl include. We'll now convert them to a single variable with a +dnl #include line for each header +COGL_GL_HEADER_INCLUDES="" +for x in $cogl_gl_headers; do + COGL_GL_HEADER_INCLUDES="$COGL_GL_HEADER_INCLUDES +#include <$x>" +done; +AC_SUBST(COGL_GL_HEADER_INCLUDES) +AM_SUBST_NOTMAKE(COGL_GL_HEADER_INCLUDES) + +AC_SUBST(COGL_DEP_CFLAGS) +AC_SUBST(COGL_DEP_LIBS) +AC_SUBST(COGL_PANGO_DEP_CFLAGS) +AC_SUBST(COGL_PANGO_DEP_LIBS) +AC_SUBST(COGL_GST_DEP_CFLAGS) +AC_SUBST(COGL_GST_DEP_LIBS) +AC_SUBST(COGL_EXTRA_CFLAGS) +AC_SUBST(COGL_EXTRA_LDFLAGS) + +# just for compatability with the clutter build... +MAINTAINER_CFLAGS= +AC_SUBST(MAINTAINER_CFLAGS) + +AC_OUTPUT( +Makefile +test-fixtures/Makefile +cogl/Makefile +cogl/mutter-cogl-1.0.pc +cogl/cogl-defines.h +cogl/cogl-gl-header.h +cogl/cogl-egl-defines.h +cogl-pango/Makefile +cogl-pango/mutter-cogl-pango-1.0.pc +cogl-path/Makefile +cogl-path/mutter-cogl-path-1.0.pc +cogl-gles2/Makefile +cogl-gles2/mutter-cogl-gles2-1.0.pc +tests/Makefile +tests/config.env +tests/conform/Makefile +tests/unit/Makefile +tests/micro-perf/Makefile +tests/data/Makefile +) + +dnl ================================================================ +dnl Dah Da! +dnl ================================================================ +echo "" +echo "Cogl - $COGL_1_VERSION/$COGL_VERSION (${COGL_RELEASE_STATUS})" + +# Global flags +echo "" +echo " • Global:" +echo " Prefix: ${prefix}" +if test "x$COGL_DEFAULT_DRIVER" != "x"; then +echo " Default driver: ${COGL_DEFAULT_DRIVER}" +fi + +echo "" +# Features +echo " • Features:" +echo " Drivers: ${enabled_drivers}" +for driver in $enabled_drivers; do + driver=`echo $driver | tr "[gles]" "[GLES]"` + libname=`eval echo \\$COGL_${driver}_LIBNAME` + echo " Library name for $driver: $libname" +done +echo " GL Window System APIs:${GL_WINSYS_APIS}" +if test "x$SUPPORT_EGL" = "xyes"; then +echo " EGL Platforms:${EGL_PLATFORMS}" +echo " Wayland compositor support: ${enable_wayland_egl_server}" +fi +echo " Build libcogl-gles2 GLES 2.0 frontend api: ${enable_cogl_gles2}" +echo " Image backend: ${COGL_IMAGE_BACKEND}" +echo " Cogl Pango: ${enable_cogl_pango}" +echo " Cogl Path: ${enable_cogl_path}" + +# Compiler/Debug related flags +echo "" +echo " • Build options:" +echo " Debugging: ${enable_debug}" +echo " Profiling: ${enable_profile}" +echo " Enable deprecated symbols: ${enable_deprecated}" +echo " Compiler flags: ${CFLAGS} ${COGL_EXTRA_CFLAGS}" +echo " Linker flags: ${LDFLAGS} ${COGL_EXTRA_LDFLAGS}" + +# Miscellaneous +echo "" +echo " • Extra:" +echo " Build introspection data: ${enable_introspection}" +echo " Build unit tests: ${enable_unit_tests}" + +echo "" diff --git a/cogl/test-fixtures/Makefile.am b/cogl/test-fixtures/Makefile.am new file mode 100644 index 0000000..a5d312e --- /dev/null +++ b/cogl/test-fixtures/Makefile.am @@ -0,0 +1,21 @@ + +noinst_LTLIBRARIES = libtest-fixtures.la + +libtest_fixtures_la_CPPFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir)/cogl \ + -Wall \ + $(NULL) + +libtest_fixtures_la_CPPFLAGS += \ + -DCOGL_DISABLE_DEPRECATED \ + -DTESTS_DATADIR=\""$(top_srcdir)/tests/data"\" \ + -DCOGL_COMPILATION + +libtest_fixtures_la_CFLAGS = -g3 -O0 $(COGL_DEP_CFLAGS) $(COGL_EXTRA_CFLAGS) -Wno-error=maybe-uninitialized -Wno-error=nested-externs -Wno-error=missing-prototypes + +libtest_fixtures_la_SOURCES = \ + test-unit.h \ + test-utils.h \ + test-utils.c + diff --git a/cogl/test-fixtures/Makefile.in b/cogl/test-fixtures/Makefile.in new file mode 100644 index 0000000..e5660c8 --- /dev/null +++ b/cogl/test-fixtures/Makefile.in @@ -0,0 +1,686 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = test-fixtures +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/build/autotools/as-compiler-flag.m4 \ + $(top_srcdir)/build/autotools/introspection.m4 \ + $(top_srcdir)/build/autotools/libtool.m4 \ + $(top_srcdir)/build/autotools/ltoptions.m4 \ + $(top_srcdir)/build/autotools/ltsugar.m4 \ + $(top_srcdir)/build/autotools/ltversion.m4 \ + $(top_srcdir)/build/autotools/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/cogl-config.h \ + $(top_builddir)/cogl-mutter-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libtest_fixtures_la_LIBADD = +am_libtest_fixtures_la_OBJECTS = libtest_fixtures_la-test-utils.lo +libtest_fixtures_la_OBJECTS = $(am_libtest_fixtures_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libtest_fixtures_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libtest_fixtures_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libtest_fixtures_la_SOURCES) +DIST_SOURCES = $(libtest_fixtures_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/build/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_REQ_VERSION = @CAIRO_REQ_VERSION@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COGL_1_MICRO_VERSION = @COGL_1_MICRO_VERSION@ +COGL_1_MINOR_VERSION = @COGL_1_MINOR_VERSION@ +COGL_1_VERSION = @COGL_1_VERSION@ +COGL_API_VERSION = @COGL_API_VERSION@ +COGL_API_VERSION_AM = @COGL_API_VERSION_AM@ +COGL_DEBUG_CFLAGS = @COGL_DEBUG_CFLAGS@ +COGL_DEFAULT_DRIVER = @COGL_DEFAULT_DRIVER@ +COGL_DEP_CFLAGS = @COGL_DEP_CFLAGS@ +COGL_DEP_GL_CFLAGS = @COGL_DEP_GL_CFLAGS@ +COGL_DEP_GL_LIBS = @COGL_DEP_GL_LIBS@ +COGL_DEP_LIBS = @COGL_DEP_LIBS@ +COGL_EGL_INCLUDES = @COGL_EGL_INCLUDES@ +COGL_EXTRA_CFLAGS = @COGL_EXTRA_CFLAGS@ +COGL_EXTRA_LDFLAGS = @COGL_EXTRA_LDFLAGS@ +COGL_GLES1_LIBNAME = @COGL_GLES1_LIBNAME@ +COGL_GLES2_LIBNAME = @COGL_GLES2_LIBNAME@ +COGL_GL_LIBNAME = @COGL_GL_LIBNAME@ +COGL_GST_DEP_CFLAGS = @COGL_GST_DEP_CFLAGS@ +COGL_GST_DEP_LIBS = @COGL_GST_DEP_LIBS@ +COGL_LT_AGE = @COGL_LT_AGE@ +COGL_LT_CURRENT = @COGL_LT_CURRENT@ +COGL_LT_RELEASE = @COGL_LT_RELEASE@ +COGL_LT_REVISION = @COGL_LT_REVISION@ +COGL_MAJOR_VERSION = @COGL_MAJOR_VERSION@ +COGL_MICRO_VERSION = @COGL_MICRO_VERSION@ +COGL_MINOR_VERSION = @COGL_MINOR_VERSION@ +COGL_PANGO_DEP_CFLAGS = @COGL_PANGO_DEP_CFLAGS@ +COGL_PANGO_DEP_LIBS = @COGL_PANGO_DEP_LIBS@ +COGL_PANGO_PKG_REQUIRES = @COGL_PANGO_PKG_REQUIRES@ +COGL_PKG_REQUIRES = @COGL_PKG_REQUIRES@ +COGL_RELEASE_STATUS = @COGL_RELEASE_STATUS@ +COGL_VERSION = @COGL_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMMY_CFLAGS = @DUMMY_CFLAGS@ +DUMMY_LIBS = @DUMMY_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDKPIXBUF_PREFIX = @GDKPIXBUF_PREFIX@ +GDK_PIXBUF_REQ_VERSION = @GDK_PIXBUF_REQ_VERSION@ +GI_REQ_VERSION = @GI_REQ_VERSION@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ_VERSION = @GLIB_REQ_VERSION@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +HAVE_GL = @HAVE_GL@ +HAVE_GLES1 = @HAVE_GLES1@ +HAVE_GLES2 = @HAVE_GLES2@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINTAINER_CFLAGS = @MAINTAINER_CFLAGS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGOCAIRO_REQ_VERSION = @PANGOCAIRO_REQ_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +UPROF_REQ_VERSION = @UPROF_REQ_VERSION@ +VERSION = @VERSION@ +WAYLAND_SERVER_CFLAGS = @WAYLAND_SERVER_CFLAGS@ +WAYLAND_SERVER_LIBS = @WAYLAND_SERVER_LIBS@ +WAYLAND_SERVER_REQ_VERSION = @WAYLAND_SERVER_REQ_VERSION@ +XCOMPOSITE_REQ_VERSION = @XCOMPOSITE_REQ_VERSION@ +XFIXES_REQ_VERSION = @XFIXES_REQ_VERSION@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libtest-fixtures.la +libtest_fixtures_la_CPPFLAGS = -I$(top_srcdir) -I$(top_builddir)/cogl \ + -Wall $(NULL) -DCOGL_DISABLE_DEPRECATED \ + -DTESTS_DATADIR=\""$(top_srcdir)/tests/data"\" \ + -DCOGL_COMPILATION +libtest_fixtures_la_CFLAGS = -g3 -O0 $(COGL_DEP_CFLAGS) $(COGL_EXTRA_CFLAGS) -Wno-error=maybe-uninitialized -Wno-error=nested-externs -Wno-error=missing-prototypes +libtest_fixtures_la_SOURCES = \ + test-unit.h \ + test-utils.h \ + test-utils.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test-fixtures/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign test-fixtures/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libtest-fixtures.la: $(libtest_fixtures_la_OBJECTS) $(libtest_fixtures_la_DEPENDENCIES) $(EXTRA_libtest_fixtures_la_DEPENDENCIES) + $(AM_V_CCLD)$(libtest_fixtures_la_LINK) $(libtest_fixtures_la_OBJECTS) $(libtest_fixtures_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtest_fixtures_la-test-utils.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libtest_fixtures_la-test-utils.lo: test-utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_fixtures_la_CPPFLAGS) $(CPPFLAGS) $(libtest_fixtures_la_CFLAGS) $(CFLAGS) -MT libtest_fixtures_la-test-utils.lo -MD -MP -MF $(DEPDIR)/libtest_fixtures_la-test-utils.Tpo -c -o libtest_fixtures_la-test-utils.lo `test -f 'test-utils.c' || echo '$(srcdir)/'`test-utils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libtest_fixtures_la-test-utils.Tpo $(DEPDIR)/libtest_fixtures_la-test-utils.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-utils.c' object='libtest_fixtures_la-test-utils.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_fixtures_la_CPPFLAGS) $(CPPFLAGS) $(libtest_fixtures_la_CFLAGS) $(CFLAGS) -c -o libtest_fixtures_la-test-utils.lo `test -f 'test-utils.c' || echo '$(srcdir)/'`test-utils.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cogl/test-fixtures/test-unit.h b/cogl/test-fixtures/test-unit.h new file mode 100644 index 0000000..270a941 --- /dev/null +++ b/cogl/test-fixtures/test-unit.h @@ -0,0 +1,31 @@ +#ifndef _TEST_UNIT_H_ +#define _TEST_UNIT_H_ + +#include + +#ifdef ENABLE_UNIT_TESTS + +typedef struct _CoglUnitTest +{ + const char *name; + TestFlags requirement_flags; + TestFlags known_failure_flags; + void (*run) (void); +} CoglUnitTest; + +#define UNIT_TEST(NAME, REQUIREMENT_FLAGS, KNOWN_FAILURE_FLAGS) \ + static void NAME (void); \ + \ + const CoglUnitTest unit_test_##NAME = \ + { #NAME, REQUIREMENT_FLAGS, KNOWN_FAILURE_FLAGS, NAME }; \ + \ + static void NAME (void) + +#else /* ENABLE_UNIT_TESTS */ + +#define UNIT_TEST(NAME, REQUIREMENT_FLAGS, KNOWN_FAILURE_FLAGS) \ + static inline void NAME (void) + +#endif /* ENABLE_UNIT_TESTS */ + +#endif /* _TEST_UNIT_H_ */ diff --git a/cogl/test-fixtures/test-utils.c b/cogl/test-fixtures/test-utils.c new file mode 100644 index 0000000..e920dd8 --- /dev/null +++ b/cogl/test-fixtures/test-utils.c @@ -0,0 +1,535 @@ +#include "cogl-config.h" + +#include + +#include "test-unit.h" +#include "test-utils.h" + +#define FB_WIDTH 512 +#define FB_HEIGHT 512 + +static CoglBool cogl_test_is_verbose; + +CoglContext *test_ctx; +CoglFramebuffer *test_fb; + +static CoglBool +check_flags (TestFlags flags, + CoglRenderer *renderer) +{ + if (flags & TEST_REQUIREMENT_GL && + cogl_renderer_get_driver (renderer) != COGL_DRIVER_GL && + cogl_renderer_get_driver (renderer) != COGL_DRIVER_GL3) + { + return FALSE; + } + + if (flags & TEST_REQUIREMENT_NPOT && + !cogl_has_feature (test_ctx, COGL_FEATURE_ID_TEXTURE_NPOT)) + { + return FALSE; + } + + if (flags & TEST_REQUIREMENT_TEXTURE_3D && + !cogl_has_feature (test_ctx, COGL_FEATURE_ID_TEXTURE_3D)) + { + return FALSE; + } + + if (flags & TEST_REQUIREMENT_TEXTURE_RECTANGLE && + !cogl_has_feature (test_ctx, COGL_FEATURE_ID_TEXTURE_RECTANGLE)) + { + return FALSE; + } + + if (flags & TEST_REQUIREMENT_TEXTURE_RG && + !cogl_has_feature (test_ctx, COGL_FEATURE_ID_TEXTURE_RG)) + { + return FALSE; + } + + if (flags & TEST_REQUIREMENT_POINT_SPRITE && + !cogl_has_feature (test_ctx, COGL_FEATURE_ID_POINT_SPRITE)) + { + return FALSE; + } + + if (flags & TEST_REQUIREMENT_PER_VERTEX_POINT_SIZE && + !cogl_has_feature (test_ctx, COGL_FEATURE_ID_PER_VERTEX_POINT_SIZE)) + { + return FALSE; + } + + if (flags & TEST_REQUIREMENT_GLES2_CONTEXT && + !cogl_has_feature (test_ctx, COGL_FEATURE_ID_GLES2_CONTEXT)) + { + return FALSE; + } + + if (flags & TEST_REQUIREMENT_MAP_WRITE && + !cogl_has_feature (test_ctx, COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE)) + { + return FALSE; + } + + if (flags & TEST_REQUIREMENT_GLSL && + !cogl_has_feature (test_ctx, COGL_FEATURE_ID_GLSL)) + { + return FALSE; + } + + if (flags & TEST_REQUIREMENT_OFFSCREEN && + !cogl_has_feature (test_ctx, COGL_FEATURE_ID_OFFSCREEN)) + { + return FALSE; + } + + if (flags & TEST_REQUIREMENT_FENCE && + !cogl_has_feature (test_ctx, COGL_FEATURE_ID_FENCE)) + { + return FALSE; + } + + if (flags & TEST_KNOWN_FAILURE) + { + return FALSE; + } + + return TRUE; +} + +CoglBool +is_boolean_env_set (const char *variable) +{ + char *val = getenv (variable); + CoglBool ret; + + if (!val) + return FALSE; + + if (g_ascii_strcasecmp (val, "1") == 0 || + g_ascii_strcasecmp (val, "on") == 0 || + g_ascii_strcasecmp (val, "true") == 0) + ret = TRUE; + else if (g_ascii_strcasecmp (val, "0") == 0 || + g_ascii_strcasecmp (val, "off") == 0 || + g_ascii_strcasecmp (val, "false") == 0) + ret = FALSE; + else + { + g_critical ("Spurious boolean environment variable value (%s=%s)", + variable, val); + ret = TRUE; + } + + return ret; +} + +void +test_utils_init (TestFlags requirement_flags, + TestFlags known_failure_flags) +{ + static int counter = 0; + CoglError *error = NULL; + CoglOnscreen *onscreen = NULL; + CoglDisplay *display; + CoglRenderer *renderer; + CoglBool missing_requirement; + CoglBool known_failure; + + if (counter != 0) + g_critical ("We don't support running more than one test at a time\n" + "in a single test run due to the state leakage that can\n" + "cause subsequent tests to fail.\n" + "\n" + "If you want to run all the tests you should run\n" + "$ make test-report"); + counter++; + + if (is_boolean_env_set ("COGL_TEST_VERBOSE") || + is_boolean_env_set ("V")) + cogl_test_is_verbose = TRUE; + + /* NB: This doesn't have any effect since commit 47444dac of glib + * because the environment variable is read in a magic constructor + * so it is too late to set them here */ + if (g_getenv ("G_DEBUG")) + { + char *debug = g_strconcat (g_getenv ("G_DEBUG"), ",fatal-warnings", NULL); + g_setenv ("G_DEBUG", debug, TRUE); + g_free (debug); + } + else + g_setenv ("G_DEBUG", "fatal-warnings", TRUE); + + g_setenv ("COGL_X11_SYNC", "1", 0); + + test_ctx = cogl_context_new (NULL, &error); + if (!test_ctx) + g_critical ("Failed to create a CoglContext: %s", error->message); + + display = cogl_context_get_display (test_ctx); + renderer = cogl_display_get_renderer (display); + + missing_requirement = !check_flags (requirement_flags, renderer); + known_failure = !check_flags (known_failure_flags, renderer); + + if (is_boolean_env_set ("COGL_TEST_ONSCREEN")) + { + onscreen = cogl_onscreen_new (test_ctx, 640, 480); + test_fb = COGL_FRAMEBUFFER (onscreen); + } + else + { + CoglOffscreen *offscreen; + CoglTexture2D *tex = cogl_texture_2d_new_with_size (test_ctx, + FB_WIDTH, FB_HEIGHT); + offscreen = cogl_offscreen_new_with_texture (COGL_TEXTURE (tex)); + test_fb = COGL_FRAMEBUFFER (offscreen); + } + + if (!cogl_framebuffer_allocate (test_fb, &error)) + g_critical ("Failed to allocate framebuffer: %s", error->message); + + if (onscreen) + cogl_onscreen_show (onscreen); + + cogl_framebuffer_clear4f (test_fb, + COGL_BUFFER_BIT_COLOR | + COGL_BUFFER_BIT_DEPTH | + COGL_BUFFER_BIT_STENCIL, + 0, 0, 0, 1); + + if (missing_requirement) + g_print ("WARNING: Missing required feature[s] for this test\n"); + else if (known_failure) + g_print ("WARNING: Test is known to fail\n"); +} + +void +test_utils_fini (void) +{ + if (test_fb) + cogl_object_unref (test_fb); + + if (test_ctx) + cogl_object_unref (test_ctx); +} + +static CoglBool +compare_component (int a, int b) +{ + return ABS (a - b) <= 1; +} + +void +test_utils_compare_pixel_and_alpha (const uint8_t *screen_pixel, + uint32_t expected_pixel) +{ + /* Compare each component with a small fuzz factor */ + if (!compare_component (screen_pixel[0], expected_pixel >> 24) || + !compare_component (screen_pixel[1], (expected_pixel >> 16) & 0xff) || + !compare_component (screen_pixel[2], (expected_pixel >> 8) & 0xff) || + !compare_component (screen_pixel[3], (expected_pixel >> 0) & 0xff)) + { + uint32_t screen_pixel_num = GUINT32_FROM_BE (*(uint32_t *) screen_pixel); + char *screen_pixel_string = + g_strdup_printf ("#%08x", screen_pixel_num); + char *expected_pixel_string = + g_strdup_printf ("#%08x", expected_pixel); + + g_assert_cmpstr (screen_pixel_string, ==, expected_pixel_string); + + g_free (screen_pixel_string); + g_free (expected_pixel_string); + } +} + +void +test_utils_compare_pixel (const uint8_t *screen_pixel, uint32_t expected_pixel) +{ + /* Compare each component with a small fuzz factor */ + if (!compare_component (screen_pixel[0], expected_pixel >> 24) || + !compare_component (screen_pixel[1], (expected_pixel >> 16) & 0xff) || + !compare_component (screen_pixel[2], (expected_pixel >> 8) & 0xff)) + { + uint32_t screen_pixel_num = GUINT32_FROM_BE (*(uint32_t *) screen_pixel); + char *screen_pixel_string = + g_strdup_printf ("#%06x", screen_pixel_num >> 8); + char *expected_pixel_string = + g_strdup_printf ("#%06x", expected_pixel >> 8); + + g_assert_cmpstr (screen_pixel_string, ==, expected_pixel_string); + + g_free (screen_pixel_string); + g_free (expected_pixel_string); + } +} + +void +test_utils_check_pixel (CoglFramebuffer *test_fb, + int x, int y, uint32_t expected_pixel) +{ + uint8_t pixel[4]; + + cogl_framebuffer_read_pixels (test_fb, + x, y, 1, 1, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + pixel); + + test_utils_compare_pixel (pixel, expected_pixel); +} + +void +test_utils_check_pixel_and_alpha (CoglFramebuffer *test_fb, + int x, int y, uint32_t expected_pixel) +{ + uint8_t pixel[4]; + + cogl_framebuffer_read_pixels (test_fb, + x, y, 1, 1, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + pixel); + + test_utils_compare_pixel_and_alpha (pixel, expected_pixel); +} + +void +test_utils_check_pixel_rgb (CoglFramebuffer *test_fb, + int x, int y, int r, int g, int b) +{ + test_utils_check_pixel (test_fb, x, y, (r << 24) | (g << 16) | (b << 8)); +} + +void +test_utils_check_region (CoglFramebuffer *test_fb, + int x, int y, + int width, int height, + uint32_t expected_rgba) +{ + uint8_t *pixels, *p; + + pixels = p = g_malloc (width * height * 4); + cogl_framebuffer_read_pixels (test_fb, + x, + y, + width, + height, + COGL_PIXEL_FORMAT_RGBA_8888, + p); + + /* Check whether the center of each division is the right color */ + for (y = 0; y < height; y++) + for (x = 0; x < width; x++) + { + test_utils_compare_pixel (p, expected_rgba); + p += 4; + } + + g_free (pixels); +} + +CoglTexture * +test_utils_create_color_texture (CoglContext *context, + uint32_t color) +{ + CoglTexture2D *tex_2d; + + color = GUINT32_TO_BE (color); + + tex_2d = cogl_texture_2d_new_from_data (context, + 1, 1, /* width/height */ + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + 4, /* rowstride */ + (uint8_t *) &color, + NULL); + + return COGL_TEXTURE (tex_2d); +} + +CoglBool +cogl_test_verbose (void) +{ + return cogl_test_is_verbose; +} + +static void +set_auto_mipmap_cb (CoglTexture *sub_texture, + const float *sub_texture_coords, + const float *meta_coords, + void *user_data) +{ + cogl_primitive_texture_set_auto_mipmap (COGL_PRIMITIVE_TEXTURE (sub_texture), + FALSE); +} + +CoglTexture * +test_utils_texture_new_with_size (CoglContext *ctx, + int width, + int height, + TestUtilsTextureFlags flags, + CoglTextureComponents components) +{ + CoglTexture *tex; + CoglError *skip_error = NULL; + + if ((test_utils_is_pot (width) && test_utils_is_pot (height)) || + (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC) && + cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP))) + { + /* First try creating a fast-path non-sliced texture */ + tex = COGL_TEXTURE (cogl_texture_2d_new_with_size (ctx, + width, height)); + + cogl_texture_set_components (tex, components); + + if (!cogl_texture_allocate (tex, &skip_error)) + { + cogl_error_free (skip_error); + cogl_object_unref (tex); + tex = NULL; + } + } + else + tex = NULL; + + if (!tex) + { + /* If it fails resort to sliced textures */ + int max_waste = flags & TEST_UTILS_TEXTURE_NO_SLICING ? + -1 : COGL_TEXTURE_MAX_WASTE; + CoglTexture2DSliced *tex_2ds = + cogl_texture_2d_sliced_new_with_size (ctx, + width, + height, + max_waste); + tex = COGL_TEXTURE (tex_2ds); + + cogl_texture_set_components (tex, components); + } + + if (flags & TEST_UTILS_TEXTURE_NO_AUTO_MIPMAP) + { + /* To be able to iterate the slices of a #CoglTexture2DSliced we + * need to ensure the texture is allocated... */ + cogl_texture_allocate (tex, NULL); /* don't catch exceptions */ + + cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (tex), + 0, 0, 1, 1, + COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE, + COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE, + set_auto_mipmap_cb, + NULL); /* don't catch exceptions */ + } + + cogl_texture_allocate (tex, NULL); + + return tex; +} + +CoglTexture * +test_utils_texture_new_from_bitmap (CoglBitmap *bitmap, + TestUtilsTextureFlags flags, + CoglBool premultiplied) +{ + CoglAtlasTexture *atlas_tex; + CoglTexture *tex; + CoglError *internal_error = NULL; + + if (!flags) + { + /* First try putting the texture in the atlas */ + atlas_tex = cogl_atlas_texture_new_from_bitmap (bitmap); + + cogl_texture_set_premultiplied (COGL_TEXTURE (atlas_tex), premultiplied); + + if (cogl_texture_allocate (COGL_TEXTURE (atlas_tex), &internal_error)) + return COGL_TEXTURE (atlas_tex); + + cogl_error_free (internal_error); + cogl_object_unref (atlas_tex); + internal_error = NULL; + } + + /* If that doesn't work try a fast path 2D texture */ + if ((test_utils_is_pot (cogl_bitmap_get_width (bitmap)) && + test_utils_is_pot (cogl_bitmap_get_height (bitmap))) || + (cogl_has_feature (test_ctx, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC) && + cogl_has_feature (test_ctx, COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP))) + { + tex = COGL_TEXTURE (cogl_texture_2d_new_from_bitmap (bitmap)); + + cogl_texture_set_premultiplied (tex, premultiplied); + + if (cogl_error_matches (internal_error, + COGL_SYSTEM_ERROR, + COGL_SYSTEM_ERROR_NO_MEMORY)) + { + g_assert_not_reached (); + return NULL; + } + + if (!tex) + { + cogl_error_free (internal_error); + internal_error = NULL; + } + } + else + tex = NULL; + + if (!tex) + { + /* Otherwise create a sliced texture */ + int max_waste = flags & TEST_UTILS_TEXTURE_NO_SLICING ? + -1 : COGL_TEXTURE_MAX_WASTE; + CoglTexture2DSliced *tex_2ds = + cogl_texture_2d_sliced_new_from_bitmap (bitmap, max_waste); + tex = COGL_TEXTURE (tex_2ds); + + cogl_texture_set_premultiplied (tex, premultiplied); + } + + if (flags & TEST_UTILS_TEXTURE_NO_AUTO_MIPMAP) + { + cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (tex), + 0, 0, 1, 1, + COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE, + COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE, + set_auto_mipmap_cb, + NULL); /* don't catch exceptions */ + } + + cogl_texture_allocate (tex, NULL); + + return tex; +} + +CoglTexture * +test_utils_texture_new_from_data (CoglContext *ctx, + int width, + int height, + TestUtilsTextureFlags flags, + CoglPixelFormat format, + int rowstride, + const uint8_t *data) +{ + CoglBitmap *bmp; + CoglTexture *tex; + + g_assert_cmpint (format, !=, COGL_PIXEL_FORMAT_ANY); + g_assert (data != NULL); + + /* Wrap the data into a bitmap */ + bmp = cogl_bitmap_new_for_data (ctx, + width, height, + format, + rowstride, + (uint8_t *) data); + + tex = test_utils_texture_new_from_bitmap (bmp, flags, TRUE); + + cogl_object_unref (bmp); + + return tex; +} diff --git a/cogl/test-fixtures/test-utils.h b/cogl/test-fixtures/test-utils.h new file mode 100644 index 0000000..9c3ced9 --- /dev/null +++ b/cogl/test-fixtures/test-utils.h @@ -0,0 +1,287 @@ +#ifndef _TEST_UTILS_H_ +#define _TEST_UTILS_H_ + +/* NB: This header is for private and public api testing and so + * we need consider that if we are testing the public api we should + * just include but since that will only provide + * opaque typedefs we need to include the specific internal headers + * for testing private apis... + */ +#ifdef COGL_COMPILATION +#include +#include +#include +#include +#include +#include +#include +#include +#else +#include +#endif + +#include + +/* We don't really care about functions that are defined without a + header for the unit tests so we can just disable it here */ +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wmissing-declarations" +#endif + +typedef enum _TestFlags +{ + TEST_KNOWN_FAILURE = 1<<0, + TEST_REQUIREMENT_GL = 1<<1, + TEST_REQUIREMENT_NPOT = 1<<2, + TEST_REQUIREMENT_TEXTURE_3D = 1<<3, + TEST_REQUIREMENT_TEXTURE_RECTANGLE = 1<<4, + TEST_REQUIREMENT_TEXTURE_RG = 1<<5, + TEST_REQUIREMENT_POINT_SPRITE = 1<<6, + TEST_REQUIREMENT_GLES2_CONTEXT = 1<<7, + TEST_REQUIREMENT_MAP_WRITE = 1<<8, + TEST_REQUIREMENT_GLSL = 1<<9, + TEST_REQUIREMENT_OFFSCREEN = 1<<10, + TEST_REQUIREMENT_FENCE = 1<<11, + TEST_REQUIREMENT_PER_VERTEX_POINT_SIZE = 1<<12 +} TestFlags; + + /** + * TestUtilsTextureFlags: + * @TEST_UTILS_TEXTURE_NONE: No flags specified + * @TEST_UTILS_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 + * @TEST_UTILS_TEXTURE_NO_SLICING: Disables the slicing of the texture + * @TEST_UTILS_TEXTURE_NO_ATLAS: Disables the insertion of the texture inside + * the texture atlas used by Cogl + * + * Flags to pass to the test_utils_texture_new_* family of functions. + */ +typedef enum { + TEST_UTILS_TEXTURE_NONE = 0, + TEST_UTILS_TEXTURE_NO_AUTO_MIPMAP = 1 << 0, + TEST_UTILS_TEXTURE_NO_SLICING = 1 << 1, + TEST_UTILS_TEXTURE_NO_ATLAS = 1 << 2 +} TestUtilsTextureFlags; + +extern CoglContext *test_ctx; +extern CoglFramebuffer *test_fb; + +void +test_utils_init (TestFlags requirement_flags, + TestFlags known_failure_flags); + +void +test_utils_fini (void); + +/* + * test_utils_texture_new_with_size: + * @context: A #CoglContext + * @width: width of texture in pixels. + * @height: height of texture in pixels. + * @flags: Optional flags for the texture, or %TEST_UTILS_TEXTURE_NONE + * @components: What texture components are required + * + * Creates a new #CoglTexture with the specified dimensions and pixel format. + * + * The storage for the texture is not necesarily created before this + * function returns. The storage can be explicitly allocated using + * cogl_texture_allocate() or preferably you can let Cogl + * automatically allocate the storage lazily when uploading data when + * Cogl may know more about how the texture will be used and can + * optimize how it is allocated. + * + * Return value: A newly created #CoglTexture + */ +CoglTexture * +test_utils_texture_new_with_size (CoglContext *ctx, + int width, + int height, + TestUtilsTextureFlags flags, + CoglTextureComponents components); + +/* + * test_utils_texture_new_from_data: + * @context: A #CoglContext + * @width: width of texture in pixels + * @height: height of texture in pixels + * @flags: Optional flags for the texture, or %TEST_UTILS_TEXTURE_NONE + * @format: the #CoglPixelFormat the buffer is stored in in RAM + * @rowstride: the memory offset in bytes between the starts of + * scanlines in @data + * @data: pointer the memory region where the source buffer resides + * @error: A #CoglError to catch exceptional errors or %NULL + * + * Creates a new #CoglTexture based on data residing in memory. + * + * Note: If the given @format has an alpha channel then the data + * will be loaded into a premultiplied internal format. If you want + * to avoid having the source data be premultiplied then you can + * either specify that the data is already premultiplied or use + * test_utils_texture_new_from_bitmap which lets you explicitly + * request whether the data should internally be premultipled or not. + * + * Return value: A newly created #CoglTexture or %NULL on failure + */ +CoglTexture * +test_utils_texture_new_from_data (CoglContext *ctx, + int width, + int height, + TestUtilsTextureFlags flags, + CoglPixelFormat format, + int rowstride, + const uint8_t *data); + +/* + * test_utils_texture_new_from_bitmap: + * @bitmap: A #CoglBitmap pointer + * @flags: Optional flags for the texture, or %TEST_UTILS_TEXTURE_NONE + * @premultiplied: Whether the texture should hold premultipled data. + * (if the bitmap already holds premultiplied data + * and %TRUE is given then no premultiplication will + * be done. The data will be premultipled while + * uploading if the bitmap has an alpha channel but + * does not already have a premultiplied format.) + * + * Creates a #CoglTexture from a #CoglBitmap. + * + * Return value: A newly created #CoglTexture or %NULL on failure + */ +CoglTexture * +test_utils_texture_new_from_bitmap (CoglBitmap *bitmap, + TestUtilsTextureFlags flags, + CoglBool premultiplied); + +/* + * test_utils_check_pixel: + * @framebuffer: The #CoglFramebuffer to read from + * @x: x co-ordinate of the pixel to test + * @y: y co-ordinate of the pixel to test + * @pixel: An integer of the form 0xRRGGBBAA representing the expected + * pixel value + * + * This performs reads a pixel on the given cogl @framebuffer and + * asserts that it matches the given color. The alpha channel of the + * color is ignored. The pixels are converted to a string and compared + * with g_assert_cmpstr so that if the comparison fails then the + * assert will display a meaningful message + */ +void +test_utils_check_pixel (CoglFramebuffer *framebuffer, + int x, int y, uint32_t expected_pixel); + +/** + * @framebuffer: The #CoglFramebuffer to read from + * @x: x co-ordinate of the pixel to test + * @y: y co-ordinate of the pixel to test + * @pixel: An integer of the form 0xRRGGBBAA representing the expected + * pixel value + * + * This performs reads a pixel on the given cogl @framebuffer and + * asserts that it matches the given color. The alpha channel is also + * checked unlike with test_utils_check_pixel(). The pixels are + * converted to a string and compared with g_assert_cmpstr so that if + * the comparison fails then the assert will display a meaningful + * message. + */ +void +test_utils_check_pixel_and_alpha (CoglFramebuffer *fb, + int x, int y, uint32_t expected_pixel); + +/* + * test_utils_check_pixel: + * @framebuffer: The #CoglFramebuffer to read from + * @x: x co-ordinate of the pixel to test + * @y: y co-ordinate of the pixel to test + * @pixel: An integer of the form 0xrrggbb representing the expected pixel value + * + * This performs reads a pixel on the given cogl @framebuffer and + * asserts that it matches the given color. The alpha channel of the + * color is ignored. The pixels are converted to a string and compared + * with g_assert_cmpstr so that if the comparison fails then the + * assert will display a meaningful message + */ +void +test_utils_check_pixel_rgb (CoglFramebuffer *framebuffer, + int x, int y, int r, int g, int b); + +/* + * test_utils_check_region: + * @framebuffer: The #CoglFramebuffer to read from + * @x: x co-ordinate of the region to test + * @y: y co-ordinate of the region to test + * @width: width of the region to test + * @height: height of the region to test + * @pixel: An integer of the form 0xrrggbb representing the expected region color + * + * Performs a read pixel on the specified region of the given cogl + * @framebuffer and asserts that it matches the given color. The alpha + * channel of the color is ignored. The pixels are converted to a + * string and compared with g_assert_cmpstr so that if the comparison + * fails then the assert will display a meaningful message + */ +void +test_utils_check_region (CoglFramebuffer *framebuffer, + int x, int y, + int width, int height, + uint32_t expected_rgba); + +/* + * test_utils_compare_pixel: + * @screen_pixel: A pixel stored in memory + * @expected_pixel: The expected RGBA value + * + * Compares a pixel from a buffer to an expected value. The pixels are + * converted to a string and compared with g_assert_cmpstr so that if + * the comparison fails then the assert will display a meaningful + * message. + */ +void +test_utils_compare_pixel (const uint8_t *screen_pixel, uint32_t expected_pixel); + +/* + * test_utils_compare_pixel_and_alpha: + * @screen_pixel: A pixel stored in memory + * @expected_pixel: The expected RGBA value + * + * Compares a pixel from a buffer to an expected value. This is + * similar to test_utils_compare_pixel() except that it doesn't ignore + * the alpha component. + */ +void +test_utils_compare_pixel_and_alpha (const uint8_t *screen_pixel, + uint32_t expected_pixel); + +/* + * test_utils_create_color_texture: + * @context: A #CoglContext + * @color: A color to put in the texture + * + * Creates a 1x1-pixel RGBA texture filled with the given color. + */ +CoglTexture * +test_utils_create_color_texture (CoglContext *context, + uint32_t color); + +/* cogl_test_verbose: + * + * Queries if the user asked for verbose output or not. + */ +CoglBool +cogl_test_verbose (void); + +/* test_util_is_pot: + * @number: A number to test + * + * Returns whether the given integer is a power of two + */ +static inline CoglBool +test_utils_is_pot (unsigned int number) +{ + /* Make sure there is only one bit set */ + return (number & (number - 1)) == 0; +} + +#endif /* _TEST_UTILS_H_ */ diff --git a/cogl/tests/Makefile.am b/cogl/tests/Makefile.am new file mode 100644 index 0000000..7e48329 --- /dev/null +++ b/cogl/tests/Makefile.am @@ -0,0 +1,31 @@ +SUBDIRS = conform + +if UNIT_TESTS +SUBDIRS += unit +endif + +SUBDIRS += micro-perf data + +DIST_SUBDIRS = conform unit micro-perf data + +EXTRA_DIST = README test-launcher.sh run-tests.sh + +if UNIT_TESTS +test conform: + ( cd ./conform && $(MAKE) $(AM_MAKEFLAGS) $@ ) || exit $$? + ( cd ./unit && $(MAKE) $(AM_MAKEFLAGS) $@ ) || exit $$? +else +test conform: + ( cd ./conform && $(MAKE) $(AM_MAKEFLAGS) $@ ) || exit $$? +endif + +.PHONY: test conform + +# run make test as part of make check +check-local: test + +if ENABLE_INSTALLED_TESTS +insttestdir = $(libexecdir)/installed-tests/mutter-cogl +insttest_SCRIPTS = run-tests.sh +insttest_DATA = config.env +endif diff --git a/cogl/tests/Makefile.in b/cogl/tests/Makefile.in new file mode 100644 index 0000000..a487c40 --- /dev/null +++ b/cogl/tests/Makefile.in @@ -0,0 +1,809 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@UNIT_TESTS_TRUE@am__append_1 = unit +subdir = tests +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/build/autotools/as-compiler-flag.m4 \ + $(top_srcdir)/build/autotools/introspection.m4 \ + $(top_srcdir)/build/autotools/libtool.m4 \ + $(top_srcdir)/build/autotools/ltoptions.m4 \ + $(top_srcdir)/build/autotools/ltsugar.m4 \ + $(top_srcdir)/build/autotools/ltversion.m4 \ + $(top_srcdir)/build/autotools/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/cogl-config.h \ + $(top_builddir)/cogl-mutter-config.h +CONFIG_CLEAN_FILES = config.env +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(insttestdir)" \ + "$(DESTDIR)$(insttestdir)" +SCRIPTS = $(insttest_SCRIPTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(insttest_DATA) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.env.in README +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_REQ_VERSION = @CAIRO_REQ_VERSION@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COGL_1_MICRO_VERSION = @COGL_1_MICRO_VERSION@ +COGL_1_MINOR_VERSION = @COGL_1_MINOR_VERSION@ +COGL_1_VERSION = @COGL_1_VERSION@ +COGL_API_VERSION = @COGL_API_VERSION@ +COGL_API_VERSION_AM = @COGL_API_VERSION_AM@ +COGL_DEBUG_CFLAGS = @COGL_DEBUG_CFLAGS@ +COGL_DEFAULT_DRIVER = @COGL_DEFAULT_DRIVER@ +COGL_DEP_CFLAGS = @COGL_DEP_CFLAGS@ +COGL_DEP_GL_CFLAGS = @COGL_DEP_GL_CFLAGS@ +COGL_DEP_GL_LIBS = @COGL_DEP_GL_LIBS@ +COGL_DEP_LIBS = @COGL_DEP_LIBS@ +COGL_EGL_INCLUDES = @COGL_EGL_INCLUDES@ +COGL_EXTRA_CFLAGS = @COGL_EXTRA_CFLAGS@ +COGL_EXTRA_LDFLAGS = @COGL_EXTRA_LDFLAGS@ +COGL_GLES1_LIBNAME = @COGL_GLES1_LIBNAME@ +COGL_GLES2_LIBNAME = @COGL_GLES2_LIBNAME@ +COGL_GL_LIBNAME = @COGL_GL_LIBNAME@ +COGL_GST_DEP_CFLAGS = @COGL_GST_DEP_CFLAGS@ +COGL_GST_DEP_LIBS = @COGL_GST_DEP_LIBS@ +COGL_LT_AGE = @COGL_LT_AGE@ +COGL_LT_CURRENT = @COGL_LT_CURRENT@ +COGL_LT_RELEASE = @COGL_LT_RELEASE@ +COGL_LT_REVISION = @COGL_LT_REVISION@ +COGL_MAJOR_VERSION = @COGL_MAJOR_VERSION@ +COGL_MICRO_VERSION = @COGL_MICRO_VERSION@ +COGL_MINOR_VERSION = @COGL_MINOR_VERSION@ +COGL_PANGO_DEP_CFLAGS = @COGL_PANGO_DEP_CFLAGS@ +COGL_PANGO_DEP_LIBS = @COGL_PANGO_DEP_LIBS@ +COGL_PANGO_PKG_REQUIRES = @COGL_PANGO_PKG_REQUIRES@ +COGL_PKG_REQUIRES = @COGL_PKG_REQUIRES@ +COGL_RELEASE_STATUS = @COGL_RELEASE_STATUS@ +COGL_VERSION = @COGL_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMMY_CFLAGS = @DUMMY_CFLAGS@ +DUMMY_LIBS = @DUMMY_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDKPIXBUF_PREFIX = @GDKPIXBUF_PREFIX@ +GDK_PIXBUF_REQ_VERSION = @GDK_PIXBUF_REQ_VERSION@ +GI_REQ_VERSION = @GI_REQ_VERSION@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ_VERSION = @GLIB_REQ_VERSION@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +HAVE_GL = @HAVE_GL@ +HAVE_GLES1 = @HAVE_GLES1@ +HAVE_GLES2 = @HAVE_GLES2@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINTAINER_CFLAGS = @MAINTAINER_CFLAGS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGOCAIRO_REQ_VERSION = @PANGOCAIRO_REQ_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +UPROF_REQ_VERSION = @UPROF_REQ_VERSION@ +VERSION = @VERSION@ +WAYLAND_SERVER_CFLAGS = @WAYLAND_SERVER_CFLAGS@ +WAYLAND_SERVER_LIBS = @WAYLAND_SERVER_LIBS@ +WAYLAND_SERVER_REQ_VERSION = @WAYLAND_SERVER_REQ_VERSION@ +XCOMPOSITE_REQ_VERSION = @XCOMPOSITE_REQ_VERSION@ +XFIXES_REQ_VERSION = @XFIXES_REQ_VERSION@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = conform $(am__append_1) micro-perf data +DIST_SUBDIRS = conform unit micro-perf data +EXTRA_DIST = README test-launcher.sh run-tests.sh +@ENABLE_INSTALLED_TESTS_TRUE@insttestdir = $(libexecdir)/installed-tests/mutter-cogl +@ENABLE_INSTALLED_TESTS_TRUE@insttest_SCRIPTS = run-tests.sh +@ENABLE_INSTALLED_TESTS_TRUE@insttest_DATA = config.env +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +config.env: $(top_builddir)/config.status $(srcdir)/config.env.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +install-insttestSCRIPTS: $(insttest_SCRIPTS) + @$(NORMAL_INSTALL) + @list='$(insttest_SCRIPTS)'; test -n "$(insttestdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(insttestdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(insttestdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n' \ + -e 'h;s|.*|.|' \ + -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) { files[d] = files[d] " " $$1; \ + if (++n[d] == $(am__install_max)) { \ + print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ + else { print "f", d "/" $$4, $$1 } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(insttestdir)$$dir'"; \ + $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(insttestdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-insttestSCRIPTS: + @$(NORMAL_UNINSTALL) + @list='$(insttest_SCRIPTS)'; test -n "$(insttestdir)" || exit 0; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 's,.*/,,;$(transform)'`; \ + dir='$(DESTDIR)$(insttestdir)'; $(am__uninstall_files_from_dir) + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-insttestDATA: $(insttest_DATA) + @$(NORMAL_INSTALL) + @list='$(insttest_DATA)'; test -n "$(insttestdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(insttestdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(insttestdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(insttestdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(insttestdir)" || exit $$?; \ + done + +uninstall-insttestDATA: + @$(NORMAL_UNINSTALL) + @list='$(insttest_DATA)'; test -n "$(insttestdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(insttestdir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-local +check: check-recursive +all-am: Makefile $(SCRIPTS) $(DATA) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(insttestdir)" "$(DESTDIR)$(insttestdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-insttestDATA install-insttestSCRIPTS + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-insttestDATA uninstall-insttestSCRIPTS + +.MAKE: $(am__recursive_targets) check-am install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am check-local clean clean-generic clean-libtool \ + cscopelist-am ctags ctags-am distclean distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-insttestDATA install-insttestSCRIPTS \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-insttestDATA uninstall-insttestSCRIPTS + +.PRECIOUS: Makefile + + +@UNIT_TESTS_TRUE@test conform: +@UNIT_TESTS_TRUE@ ( cd ./conform && $(MAKE) $(AM_MAKEFLAGS) $@ ) || exit $$? +@UNIT_TESTS_TRUE@ ( cd ./unit && $(MAKE) $(AM_MAKEFLAGS) $@ ) || exit $$? +@UNIT_TESTS_FALSE@test conform: +@UNIT_TESTS_FALSE@ ( cd ./conform && $(MAKE) $(AM_MAKEFLAGS) $@ ) || exit $$? + +.PHONY: test conform + +# run make test as part of make check +check-local: test + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cogl/tests/README b/cogl/tests/README new file mode 100644 index 0000000..cc6dbb9 --- /dev/null +++ b/cogl/tests/README @@ -0,0 +1,63 @@ +Outline of test categories: + +The conform/ tests: +------------------- +These tests should be non-interactive unit-tests that verify a single +feature is behaving as documented. See conform/ADDING_NEW_TESTS for more +details. + +Although it may seem a bit awkward; all the tests are built into a +single binary because it makes building the tests *much* faster by avoiding +lots of linking. + +Each test has a wrapper script generated though so running the individual tests +should be convenient enough. Running the wrapper script will also print out for +convenience how you could run the test under gdb or valgrind like this for +example: + + NOTE: For debugging purposes, you can run this single test as follows: + $ libtool --mode=execute \ + gdb --eval-command="b test_cogl_depth_test" \ + --args ./test-conformance -p /conform/cogl/test_cogl_depth_test + or: + $ env G_SLICE=always-malloc \ + libtool --mode=execute \ + valgrind ./test-conformance -p /conform/cogl/test_cogl_depth_test + +By default the conformance tests are run offscreen. This makes the tests run +much faster and they also don't interfere with other work you may want to do by +constantly stealing focus. CoglOnscreen framebuffers obviously don't get tested +this way so it's important that the tests also get run onscreen every once in a +while, especially if changes are being made to CoglFramebuffer related code. +Onscreen testing can be enabled by setting COGL_TEST_ONSCREEN=1 in your +environment. + +The micro-bench/ tests: +----------------------- +These should be focused performance tests, ideally testing a +single metric. Please never forget that these tests are synthetic and if you +are using them then you understand what metric is being tested. They probably +don't reflect any real world application loads and the intention is that you +use these tests once you have already determined the crux of your problem and +need focused feedback that your changes are indeed improving matters. There is +no exit status requirements for these tests, but they should give clear +feedback as to their performance. If the framerate is the feedback metric, then +the test should forcibly enable FPS debugging. + +The data/ directory: +-------------------- +This contains optional data (like images) that can be referenced by a test. + + +Misc notes: +----------- +• All tests should ideally include a detailed description in the source +explaining exactly what the test is for, how the test was designed to work, +and possibly a rationale for the approach taken for testing. + +• When running tests under Valgrind, you should follow the instructions +available here: + + http://live.gnome.org/Valgrind + +and also use the suppression file available inside the data/ directory. diff --git a/cogl/tests/config.env.in b/cogl/tests/config.env.in new file mode 100644 index 0000000..d377756 --- /dev/null +++ b/cogl/tests/config.env.in @@ -0,0 +1,3 @@ +HAVE_GL=@HAVE_GL@ +HAVE_GLES1=@HAVE_GLES1@ +HAVE_GLES2=@HAVE_GLES2@ diff --git a/cogl/tests/conform/Makefile.am b/cogl/tests/conform/Makefile.am new file mode 100644 index 0000000..b2c5323 --- /dev/null +++ b/cogl/tests/conform/Makefile.am @@ -0,0 +1,177 @@ +NULL = + +noinst_PROGRAMS = test-conformance + +common_sources = \ + test-conform-main.c \ + $(NULL) + +unported_test_sources = \ + test-fixed.c \ + test-materials.c \ + test-viewport.c \ + test-multitexture.c \ + test-npot-texture.c \ + test-object.c \ + test-readpixels.c \ + test-texture-mipmaps.c \ + test-texture-pixmap-x11.c \ + test-texture-rectangle.c \ + test-vertex-buffer-contiguous.c \ + test-vertex-buffer-interleved.c \ + test-vertex-buffer-mutability.c \ + $(NULL) + +test_sources = \ + test-atlas-migration.c \ + test-blend-strings.c \ + test-blend.c \ + test-depth-test.c \ + test-color-hsl.c \ + test-color-mask.c \ + test-backface-culling.c \ + test-just-vertex-shader.c \ + test-pipeline-user-matrix.c \ + test-pipeline-uniforms.c \ + test-pixel-buffer.c \ + test-premult.c \ + test-snippets.c \ + test-wrap-modes.c \ + test-sub-texture.c \ + test-custom-attributes.c \ + test-offscreen.c \ + test-primitive.c \ + test-texture-3d.c \ + test-sparse-pipeline.c \ + test-read-texture-formats.c \ + test-write-texture-formats.c \ + test-point-size.c \ + test-point-size-attribute.c \ + test-point-sprite.c \ + test-no-gl-header.c \ + test-version.c \ + test-gles2-context.c \ + test-euler-quaternion.c \ + test-layer-remove.c \ + test-alpha-test.c \ + test-map-buffer-range.c \ + test-npot-texture.c \ + test-alpha-textures.c \ + test-wrap-rectangle-textures.c \ + test-texture-get-set-data.c \ + test-framebuffer-get-bits.c \ + test-primitive-and-journal.c \ + test-copy-replace-texture.c \ + test-pipeline-cache-unrefs-texture.c \ + test-texture-no-allocate.c \ + test-pipeline-shader-state.c \ + test-texture-rg.c \ + test-fence.c \ + $(NULL) + +if BUILD_COGL_PATH +test_sources += \ + test-path.c \ + test-path-clip.c +endif + +test_conformance_SOURCES = $(common_sources) $(test_sources) + +SHEXT = $(EXEEXT) + +# For convenience, this provides a way to easily run individual unit tests: +.PHONY: wrappers clean-wrappers + +wrappers: stamp-test-conformance + @true +stamp-test-conformance: Makefile $(srcdir)/test-conform-main.c + @mkdir -p wrappers + @sed -n -e 's/^ \{1,\}ADD_TEST *( *\([a-zA-Z0-9_]\{1,\}\).*/\1/p' $(srcdir)/test-conform-main.c > unit-tests + @chmod +x $(top_srcdir)/tests/test-launcher.sh + @( echo "/stamp-test-conformance" ; \ + echo "/test-conformance$(EXEEXT)" ; \ + echo "*.o" ; \ + echo ".gitignore" ; \ + echo "unit-tests" ; ) > .gitignore + @for i in `cat unit-tests`; \ + do \ + unit=`basename $$i | sed -e s/_/-/g`; \ + echo " GEN $$unit"; \ + ( echo "#!/bin/sh" ; echo "$(top_srcdir)/tests/test-launcher.sh $(abs_builddir)/test-conformance$(EXEEXT) '' '$$i' \"\$$@\"" ) > $$unit$(SHEXT) ; \ + chmod +x $$unit$(SHEXT); \ + echo "/$$unit$(SHEXT)" >> .gitignore; \ + done \ + && echo timestamp > $(@F) + +clean-wrappers: + @for i in `cat unit-tests`; \ + do \ + unit=`basename $$i | sed -e s/_/-/g`; \ + echo " RM $$unit"; \ + rm -f $$unit$(SHEXT) ; \ + done \ + && rm -f unit-tests \ + && rm -f stamp-test-conformance + +# NB: BUILT_SOURCES here a misnomer. We aren't building source, just inserting +# a phony rule that will generate symlink scripts for running individual tests +BUILT_SOURCES = wrappers + +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir)/cogl \ + -I$(top_srcdir)/test-fixtures + +AM_CPPFLAGS += \ + -DCOGL_ENABLE_EXPERIMENTAL_API \ + -DCOGL_DISABLE_DEPRECATED \ + -DCOGL_DISABLE_DEPRECATION_WARNINGS \ + -DTESTS_DATADIR=\""$(top_srcdir)/tests/data"\" + +test_conformance_CFLAGS = -g3 -O0 $(COGL_DEP_CFLAGS) $(COGL_EXTRA_CFLAGS) -Wno-error=maybe-uninitialized -Wno-error=nested-externs -Wno-error=missing-prototypes +test_conformance_LDADD = \ + $(COGL_DEP_LIBS) \ + $(top_builddir)/cogl/libmutter-cogl.la \ + $(LIBM) +if BUILD_COGL_PATH +test_conformance_LDADD += $(top_builddir)/cogl-path/libmutter-cogl-path.la +endif +test_conformance_LDFLAGS = -export-dynamic + +# XXX: uncomment when tests get fixed +#test: wrappers +# @$(top_srcdir)/tests/run-tests.sh $(abs_builddir)/../config.env $(abs_builddir)/test-conformance$(EXEEXT) + +# XXX: we could prevent the conformance test suite from running +# by simply defining this variable conditionally +TEST_PROGS = test-conformance + +.PHONY: test + +DISTCLEANFILES = .gitignore + +# we override the clean-generic target to clean up the wrappers so +# we cannot use CLEANFILES +clean-generic: clean-wrappers + $(QUIET_RM)rm -f .log + + +if ENABLE_INSTALLED_TESTS + +insttestdir = $(libexecdir)/installed-tests/mutter-cogl/conform +insttest_PROGRAMS = test-conformance +insttest_DATA = unit-tests + +testmetadir = $(datadir)/installed-tests/mutter-cogl +testmeta_DATA = conform.test + +conform.test: + echo " GEN $@"; \ + echo "[Test]" > $@.tmp; \ + echo "Type=session" >> $@.tmp; \ + echo "Exec=sh -c \"cd $(libexecdir)/installed-tests/mutter-cogl/conform; ../run-tests.sh ../config.env ./test-conformance\"" >> $@.tmp; \ + mv $@.tmp $@ + +CLEANFILES = conform.test + +endif diff --git a/cogl/tests/conform/Makefile.in b/cogl/tests/conform/Makefile.in new file mode 100644 index 0000000..061e759 --- /dev/null +++ b/cogl/tests/conform/Makefile.in @@ -0,0 +1,1703 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +noinst_PROGRAMS = test-conformance$(EXEEXT) +@BUILD_COGL_PATH_TRUE@am__append_1 = \ +@BUILD_COGL_PATH_TRUE@ test-path.c \ +@BUILD_COGL_PATH_TRUE@ test-path-clip.c + +@BUILD_COGL_PATH_TRUE@am__append_2 = $(top_builddir)/cogl-path/libmutter-cogl-path.la +@ENABLE_INSTALLED_TESTS_TRUE@insttest_PROGRAMS = \ +@ENABLE_INSTALLED_TESTS_TRUE@ test-conformance$(EXEEXT) +subdir = tests/conform +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/build/autotools/as-compiler-flag.m4 \ + $(top_srcdir)/build/autotools/introspection.m4 \ + $(top_srcdir)/build/autotools/libtool.m4 \ + $(top_srcdir)/build/autotools/ltoptions.m4 \ + $(top_srcdir)/build/autotools/ltsugar.m4 \ + $(top_srcdir)/build/autotools/ltversion.m4 \ + $(top_srcdir)/build/autotools/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/cogl-config.h \ + $(top_builddir)/cogl-mutter-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(insttestdir)" \ + "$(DESTDIR)$(insttestdir)" "$(DESTDIR)$(testmetadir)" +PROGRAMS = $(insttest_PROGRAMS) $(noinst_PROGRAMS) +am__test_conformance_SOURCES_DIST = test-conform-main.c \ + test-atlas-migration.c test-blend-strings.c test-blend.c \ + test-depth-test.c test-color-hsl.c test-color-mask.c \ + test-backface-culling.c test-just-vertex-shader.c \ + test-pipeline-user-matrix.c test-pipeline-uniforms.c \ + test-pixel-buffer.c test-premult.c test-snippets.c \ + test-wrap-modes.c test-sub-texture.c test-custom-attributes.c \ + test-offscreen.c test-primitive.c test-texture-3d.c \ + test-sparse-pipeline.c test-read-texture-formats.c \ + test-write-texture-formats.c test-point-size.c \ + test-point-size-attribute.c test-point-sprite.c \ + test-no-gl-header.c test-version.c test-gles2-context.c \ + test-euler-quaternion.c test-layer-remove.c test-alpha-test.c \ + test-map-buffer-range.c test-npot-texture.c \ + test-alpha-textures.c test-wrap-rectangle-textures.c \ + test-texture-get-set-data.c test-framebuffer-get-bits.c \ + test-primitive-and-journal.c test-copy-replace-texture.c \ + test-pipeline-cache-unrefs-texture.c \ + test-texture-no-allocate.c test-pipeline-shader-state.c \ + test-texture-rg.c test-fence.c test-path.c test-path-clip.c +am__objects_1 = +am__objects_2 = test_conformance-test-conform-main.$(OBJEXT) \ + $(am__objects_1) +@BUILD_COGL_PATH_TRUE@am__objects_3 = \ +@BUILD_COGL_PATH_TRUE@ test_conformance-test-path.$(OBJEXT) \ +@BUILD_COGL_PATH_TRUE@ test_conformance-test-path-clip.$(OBJEXT) +am__objects_4 = test_conformance-test-atlas-migration.$(OBJEXT) \ + test_conformance-test-blend-strings.$(OBJEXT) \ + test_conformance-test-blend.$(OBJEXT) \ + test_conformance-test-depth-test.$(OBJEXT) \ + test_conformance-test-color-hsl.$(OBJEXT) \ + test_conformance-test-color-mask.$(OBJEXT) \ + test_conformance-test-backface-culling.$(OBJEXT) \ + test_conformance-test-just-vertex-shader.$(OBJEXT) \ + test_conformance-test-pipeline-user-matrix.$(OBJEXT) \ + test_conformance-test-pipeline-uniforms.$(OBJEXT) \ + test_conformance-test-pixel-buffer.$(OBJEXT) \ + test_conformance-test-premult.$(OBJEXT) \ + test_conformance-test-snippets.$(OBJEXT) \ + test_conformance-test-wrap-modes.$(OBJEXT) \ + test_conformance-test-sub-texture.$(OBJEXT) \ + test_conformance-test-custom-attributes.$(OBJEXT) \ + test_conformance-test-offscreen.$(OBJEXT) \ + test_conformance-test-primitive.$(OBJEXT) \ + test_conformance-test-texture-3d.$(OBJEXT) \ + test_conformance-test-sparse-pipeline.$(OBJEXT) \ + test_conformance-test-read-texture-formats.$(OBJEXT) \ + test_conformance-test-write-texture-formats.$(OBJEXT) \ + test_conformance-test-point-size.$(OBJEXT) \ + test_conformance-test-point-size-attribute.$(OBJEXT) \ + test_conformance-test-point-sprite.$(OBJEXT) \ + test_conformance-test-no-gl-header.$(OBJEXT) \ + test_conformance-test-version.$(OBJEXT) \ + test_conformance-test-gles2-context.$(OBJEXT) \ + test_conformance-test-euler-quaternion.$(OBJEXT) \ + test_conformance-test-layer-remove.$(OBJEXT) \ + test_conformance-test-alpha-test.$(OBJEXT) \ + test_conformance-test-map-buffer-range.$(OBJEXT) \ + test_conformance-test-npot-texture.$(OBJEXT) \ + test_conformance-test-alpha-textures.$(OBJEXT) \ + test_conformance-test-wrap-rectangle-textures.$(OBJEXT) \ + test_conformance-test-texture-get-set-data.$(OBJEXT) \ + test_conformance-test-framebuffer-get-bits.$(OBJEXT) \ + test_conformance-test-primitive-and-journal.$(OBJEXT) \ + test_conformance-test-copy-replace-texture.$(OBJEXT) \ + test_conformance-test-pipeline-cache-unrefs-texture.$(OBJEXT) \ + test_conformance-test-texture-no-allocate.$(OBJEXT) \ + test_conformance-test-pipeline-shader-state.$(OBJEXT) \ + test_conformance-test-texture-rg.$(OBJEXT) \ + test_conformance-test-fence.$(OBJEXT) $(am__objects_1) \ + $(am__objects_3) +am_test_conformance_OBJECTS = $(am__objects_2) $(am__objects_4) +test_conformance_OBJECTS = $(am_test_conformance_OBJECTS) +am__DEPENDENCIES_1 = +test_conformance_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(top_builddir)/cogl/libmutter-cogl.la $(am__DEPENDENCIES_1) \ + $(am__append_2) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +test_conformance_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(test_conformance_CFLAGS) $(CFLAGS) \ + $(test_conformance_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(test_conformance_SOURCES) +DIST_SOURCES = $(am__test_conformance_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +DATA = $(insttest_DATA) $(testmeta_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/build/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_REQ_VERSION = @CAIRO_REQ_VERSION@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COGL_1_MICRO_VERSION = @COGL_1_MICRO_VERSION@ +COGL_1_MINOR_VERSION = @COGL_1_MINOR_VERSION@ +COGL_1_VERSION = @COGL_1_VERSION@ +COGL_API_VERSION = @COGL_API_VERSION@ +COGL_API_VERSION_AM = @COGL_API_VERSION_AM@ +COGL_DEBUG_CFLAGS = @COGL_DEBUG_CFLAGS@ +COGL_DEFAULT_DRIVER = @COGL_DEFAULT_DRIVER@ +COGL_DEP_CFLAGS = @COGL_DEP_CFLAGS@ +COGL_DEP_GL_CFLAGS = @COGL_DEP_GL_CFLAGS@ +COGL_DEP_GL_LIBS = @COGL_DEP_GL_LIBS@ +COGL_DEP_LIBS = @COGL_DEP_LIBS@ +COGL_EGL_INCLUDES = @COGL_EGL_INCLUDES@ +COGL_EXTRA_CFLAGS = @COGL_EXTRA_CFLAGS@ +COGL_EXTRA_LDFLAGS = @COGL_EXTRA_LDFLAGS@ +COGL_GLES1_LIBNAME = @COGL_GLES1_LIBNAME@ +COGL_GLES2_LIBNAME = @COGL_GLES2_LIBNAME@ +COGL_GL_LIBNAME = @COGL_GL_LIBNAME@ +COGL_GST_DEP_CFLAGS = @COGL_GST_DEP_CFLAGS@ +COGL_GST_DEP_LIBS = @COGL_GST_DEP_LIBS@ +COGL_LT_AGE = @COGL_LT_AGE@ +COGL_LT_CURRENT = @COGL_LT_CURRENT@ +COGL_LT_RELEASE = @COGL_LT_RELEASE@ +COGL_LT_REVISION = @COGL_LT_REVISION@ +COGL_MAJOR_VERSION = @COGL_MAJOR_VERSION@ +COGL_MICRO_VERSION = @COGL_MICRO_VERSION@ +COGL_MINOR_VERSION = @COGL_MINOR_VERSION@ +COGL_PANGO_DEP_CFLAGS = @COGL_PANGO_DEP_CFLAGS@ +COGL_PANGO_DEP_LIBS = @COGL_PANGO_DEP_LIBS@ +COGL_PANGO_PKG_REQUIRES = @COGL_PANGO_PKG_REQUIRES@ +COGL_PKG_REQUIRES = @COGL_PKG_REQUIRES@ +COGL_RELEASE_STATUS = @COGL_RELEASE_STATUS@ +COGL_VERSION = @COGL_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMMY_CFLAGS = @DUMMY_CFLAGS@ +DUMMY_LIBS = @DUMMY_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDKPIXBUF_PREFIX = @GDKPIXBUF_PREFIX@ +GDK_PIXBUF_REQ_VERSION = @GDK_PIXBUF_REQ_VERSION@ +GI_REQ_VERSION = @GI_REQ_VERSION@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ_VERSION = @GLIB_REQ_VERSION@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +HAVE_GL = @HAVE_GL@ +HAVE_GLES1 = @HAVE_GLES1@ +HAVE_GLES2 = @HAVE_GLES2@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINTAINER_CFLAGS = @MAINTAINER_CFLAGS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGOCAIRO_REQ_VERSION = @PANGOCAIRO_REQ_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +UPROF_REQ_VERSION = @UPROF_REQ_VERSION@ +VERSION = @VERSION@ +WAYLAND_SERVER_CFLAGS = @WAYLAND_SERVER_CFLAGS@ +WAYLAND_SERVER_LIBS = @WAYLAND_SERVER_LIBS@ +WAYLAND_SERVER_REQ_VERSION = @WAYLAND_SERVER_REQ_VERSION@ +XCOMPOSITE_REQ_VERSION = @XCOMPOSITE_REQ_VERSION@ +XFIXES_REQ_VERSION = @XFIXES_REQ_VERSION@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = +common_sources = \ + test-conform-main.c \ + $(NULL) + +unported_test_sources = \ + test-fixed.c \ + test-materials.c \ + test-viewport.c \ + test-multitexture.c \ + test-npot-texture.c \ + test-object.c \ + test-readpixels.c \ + test-texture-mipmaps.c \ + test-texture-pixmap-x11.c \ + test-texture-rectangle.c \ + test-vertex-buffer-contiguous.c \ + test-vertex-buffer-interleved.c \ + test-vertex-buffer-mutability.c \ + $(NULL) + +test_sources = test-atlas-migration.c test-blend-strings.c \ + test-blend.c test-depth-test.c test-color-hsl.c \ + test-color-mask.c test-backface-culling.c \ + test-just-vertex-shader.c test-pipeline-user-matrix.c \ + test-pipeline-uniforms.c test-pixel-buffer.c test-premult.c \ + test-snippets.c test-wrap-modes.c test-sub-texture.c \ + test-custom-attributes.c test-offscreen.c test-primitive.c \ + test-texture-3d.c test-sparse-pipeline.c \ + test-read-texture-formats.c test-write-texture-formats.c \ + test-point-size.c test-point-size-attribute.c \ + test-point-sprite.c test-no-gl-header.c test-version.c \ + test-gles2-context.c test-euler-quaternion.c \ + test-layer-remove.c test-alpha-test.c test-map-buffer-range.c \ + test-npot-texture.c test-alpha-textures.c \ + test-wrap-rectangle-textures.c test-texture-get-set-data.c \ + test-framebuffer-get-bits.c test-primitive-and-journal.c \ + test-copy-replace-texture.c \ + test-pipeline-cache-unrefs-texture.c \ + test-texture-no-allocate.c test-pipeline-shader-state.c \ + test-texture-rg.c test-fence.c $(NULL) $(am__append_1) +test_conformance_SOURCES = $(common_sources) $(test_sources) +SHEXT = $(EXEEXT) + +# NB: BUILT_SOURCES here a misnomer. We aren't building source, just inserting +# a phony rule that will generate symlink scripts for running individual tests +BUILT_SOURCES = wrappers +AM_CPPFLAGS = -I$(top_srcdir) -I$(top_builddir)/cogl \ + -I$(top_srcdir)/test-fixtures -DCOGL_ENABLE_EXPERIMENTAL_API \ + -DCOGL_DISABLE_DEPRECATED -DCOGL_DISABLE_DEPRECATION_WARNINGS \ + -DTESTS_DATADIR=\""$(top_srcdir)/tests/data"\" +test_conformance_CFLAGS = -g3 -O0 $(COGL_DEP_CFLAGS) $(COGL_EXTRA_CFLAGS) -Wno-error=maybe-uninitialized -Wno-error=nested-externs -Wno-error=missing-prototypes +test_conformance_LDADD = $(COGL_DEP_LIBS) \ + $(top_builddir)/cogl/libmutter-cogl.la $(LIBM) $(am__append_2) +test_conformance_LDFLAGS = -export-dynamic + +# XXX: uncomment when tests get fixed +#test: wrappers +# @$(top_srcdir)/tests/run-tests.sh $(abs_builddir)/../config.env $(abs_builddir)/test-conformance$(EXEEXT) + +# XXX: we could prevent the conformance test suite from running +# by simply defining this variable conditionally +TEST_PROGS = test-conformance +DISTCLEANFILES = .gitignore +@ENABLE_INSTALLED_TESTS_TRUE@insttestdir = $(libexecdir)/installed-tests/mutter-cogl/conform +@ENABLE_INSTALLED_TESTS_TRUE@insttest_DATA = unit-tests +@ENABLE_INSTALLED_TESTS_TRUE@testmetadir = $(datadir)/installed-tests/mutter-cogl +@ENABLE_INSTALLED_TESTS_TRUE@testmeta_DATA = conform.test +@ENABLE_INSTALLED_TESTS_TRUE@CLEANFILES = conform.test +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/conform/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/conform/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-insttestPROGRAMS: $(insttest_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(insttest_PROGRAMS)'; test -n "$(insttestdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(insttestdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(insttestdir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(insttestdir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(insttestdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-insttestPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(insttest_PROGRAMS)'; test -n "$(insttestdir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(insttestdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(insttestdir)" && rm -f $$files + +clean-insttestPROGRAMS: + @list='$(insttest_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +test-conformance$(EXEEXT): $(test_conformance_OBJECTS) $(test_conformance_DEPENDENCIES) $(EXTRA_test_conformance_DEPENDENCIES) + @rm -f test-conformance$(EXEEXT) + $(AM_V_CCLD)$(test_conformance_LINK) $(test_conformance_OBJECTS) $(test_conformance_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-alpha-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-alpha-textures.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-atlas-migration.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-backface-culling.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-blend-strings.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-blend.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-color-hsl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-color-mask.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-conform-main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-copy-replace-texture.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-custom-attributes.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-depth-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-euler-quaternion.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-fence.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-framebuffer-get-bits.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-gles2-context.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-just-vertex-shader.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-layer-remove.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-map-buffer-range.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-no-gl-header.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-npot-texture.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-offscreen.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-path-clip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-path.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-pipeline-cache-unrefs-texture.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-pipeline-shader-state.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-pipeline-uniforms.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-pipeline-user-matrix.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-pixel-buffer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-point-size-attribute.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-point-size.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-point-sprite.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-premult.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-primitive-and-journal.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-primitive.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-read-texture-formats.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-snippets.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-sparse-pipeline.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-sub-texture.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-texture-3d.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-texture-get-set-data.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-texture-no-allocate.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-texture-rg.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-version.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-wrap-modes.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-wrap-rectangle-textures.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conformance-test-write-texture-formats.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +test_conformance-test-conform-main.o: test-conform-main.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-conform-main.o -MD -MP -MF $(DEPDIR)/test_conformance-test-conform-main.Tpo -c -o test_conformance-test-conform-main.o `test -f 'test-conform-main.c' || echo '$(srcdir)/'`test-conform-main.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-conform-main.Tpo $(DEPDIR)/test_conformance-test-conform-main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-conform-main.c' object='test_conformance-test-conform-main.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-conform-main.o `test -f 'test-conform-main.c' || echo '$(srcdir)/'`test-conform-main.c + +test_conformance-test-conform-main.obj: test-conform-main.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-conform-main.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-conform-main.Tpo -c -o test_conformance-test-conform-main.obj `if test -f 'test-conform-main.c'; then $(CYGPATH_W) 'test-conform-main.c'; else $(CYGPATH_W) '$(srcdir)/test-conform-main.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-conform-main.Tpo $(DEPDIR)/test_conformance-test-conform-main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-conform-main.c' object='test_conformance-test-conform-main.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-conform-main.obj `if test -f 'test-conform-main.c'; then $(CYGPATH_W) 'test-conform-main.c'; else $(CYGPATH_W) '$(srcdir)/test-conform-main.c'; fi` + +test_conformance-test-atlas-migration.o: test-atlas-migration.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-atlas-migration.o -MD -MP -MF $(DEPDIR)/test_conformance-test-atlas-migration.Tpo -c -o test_conformance-test-atlas-migration.o `test -f 'test-atlas-migration.c' || echo '$(srcdir)/'`test-atlas-migration.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-atlas-migration.Tpo $(DEPDIR)/test_conformance-test-atlas-migration.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-atlas-migration.c' object='test_conformance-test-atlas-migration.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-atlas-migration.o `test -f 'test-atlas-migration.c' || echo '$(srcdir)/'`test-atlas-migration.c + +test_conformance-test-atlas-migration.obj: test-atlas-migration.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-atlas-migration.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-atlas-migration.Tpo -c -o test_conformance-test-atlas-migration.obj `if test -f 'test-atlas-migration.c'; then $(CYGPATH_W) 'test-atlas-migration.c'; else $(CYGPATH_W) '$(srcdir)/test-atlas-migration.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-atlas-migration.Tpo $(DEPDIR)/test_conformance-test-atlas-migration.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-atlas-migration.c' object='test_conformance-test-atlas-migration.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-atlas-migration.obj `if test -f 'test-atlas-migration.c'; then $(CYGPATH_W) 'test-atlas-migration.c'; else $(CYGPATH_W) '$(srcdir)/test-atlas-migration.c'; fi` + +test_conformance-test-blend-strings.o: test-blend-strings.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-blend-strings.o -MD -MP -MF $(DEPDIR)/test_conformance-test-blend-strings.Tpo -c -o test_conformance-test-blend-strings.o `test -f 'test-blend-strings.c' || echo '$(srcdir)/'`test-blend-strings.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-blend-strings.Tpo $(DEPDIR)/test_conformance-test-blend-strings.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-blend-strings.c' object='test_conformance-test-blend-strings.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-blend-strings.o `test -f 'test-blend-strings.c' || echo '$(srcdir)/'`test-blend-strings.c + +test_conformance-test-blend-strings.obj: test-blend-strings.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-blend-strings.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-blend-strings.Tpo -c -o test_conformance-test-blend-strings.obj `if test -f 'test-blend-strings.c'; then $(CYGPATH_W) 'test-blend-strings.c'; else $(CYGPATH_W) '$(srcdir)/test-blend-strings.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-blend-strings.Tpo $(DEPDIR)/test_conformance-test-blend-strings.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-blend-strings.c' object='test_conformance-test-blend-strings.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-blend-strings.obj `if test -f 'test-blend-strings.c'; then $(CYGPATH_W) 'test-blend-strings.c'; else $(CYGPATH_W) '$(srcdir)/test-blend-strings.c'; fi` + +test_conformance-test-blend.o: test-blend.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-blend.o -MD -MP -MF $(DEPDIR)/test_conformance-test-blend.Tpo -c -o test_conformance-test-blend.o `test -f 'test-blend.c' || echo '$(srcdir)/'`test-blend.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-blend.Tpo $(DEPDIR)/test_conformance-test-blend.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-blend.c' object='test_conformance-test-blend.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-blend.o `test -f 'test-blend.c' || echo '$(srcdir)/'`test-blend.c + +test_conformance-test-blend.obj: test-blend.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-blend.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-blend.Tpo -c -o test_conformance-test-blend.obj `if test -f 'test-blend.c'; then $(CYGPATH_W) 'test-blend.c'; else $(CYGPATH_W) '$(srcdir)/test-blend.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-blend.Tpo $(DEPDIR)/test_conformance-test-blend.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-blend.c' object='test_conformance-test-blend.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-blend.obj `if test -f 'test-blend.c'; then $(CYGPATH_W) 'test-blend.c'; else $(CYGPATH_W) '$(srcdir)/test-blend.c'; fi` + +test_conformance-test-depth-test.o: test-depth-test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-depth-test.o -MD -MP -MF $(DEPDIR)/test_conformance-test-depth-test.Tpo -c -o test_conformance-test-depth-test.o `test -f 'test-depth-test.c' || echo '$(srcdir)/'`test-depth-test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-depth-test.Tpo $(DEPDIR)/test_conformance-test-depth-test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-depth-test.c' object='test_conformance-test-depth-test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-depth-test.o `test -f 'test-depth-test.c' || echo '$(srcdir)/'`test-depth-test.c + +test_conformance-test-depth-test.obj: test-depth-test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-depth-test.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-depth-test.Tpo -c -o test_conformance-test-depth-test.obj `if test -f 'test-depth-test.c'; then $(CYGPATH_W) 'test-depth-test.c'; else $(CYGPATH_W) '$(srcdir)/test-depth-test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-depth-test.Tpo $(DEPDIR)/test_conformance-test-depth-test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-depth-test.c' object='test_conformance-test-depth-test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-depth-test.obj `if test -f 'test-depth-test.c'; then $(CYGPATH_W) 'test-depth-test.c'; else $(CYGPATH_W) '$(srcdir)/test-depth-test.c'; fi` + +test_conformance-test-color-hsl.o: test-color-hsl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-color-hsl.o -MD -MP -MF $(DEPDIR)/test_conformance-test-color-hsl.Tpo -c -o test_conformance-test-color-hsl.o `test -f 'test-color-hsl.c' || echo '$(srcdir)/'`test-color-hsl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-color-hsl.Tpo $(DEPDIR)/test_conformance-test-color-hsl.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-color-hsl.c' object='test_conformance-test-color-hsl.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-color-hsl.o `test -f 'test-color-hsl.c' || echo '$(srcdir)/'`test-color-hsl.c + +test_conformance-test-color-hsl.obj: test-color-hsl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-color-hsl.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-color-hsl.Tpo -c -o test_conformance-test-color-hsl.obj `if test -f 'test-color-hsl.c'; then $(CYGPATH_W) 'test-color-hsl.c'; else $(CYGPATH_W) '$(srcdir)/test-color-hsl.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-color-hsl.Tpo $(DEPDIR)/test_conformance-test-color-hsl.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-color-hsl.c' object='test_conformance-test-color-hsl.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-color-hsl.obj `if test -f 'test-color-hsl.c'; then $(CYGPATH_W) 'test-color-hsl.c'; else $(CYGPATH_W) '$(srcdir)/test-color-hsl.c'; fi` + +test_conformance-test-color-mask.o: test-color-mask.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-color-mask.o -MD -MP -MF $(DEPDIR)/test_conformance-test-color-mask.Tpo -c -o test_conformance-test-color-mask.o `test -f 'test-color-mask.c' || echo '$(srcdir)/'`test-color-mask.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-color-mask.Tpo $(DEPDIR)/test_conformance-test-color-mask.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-color-mask.c' object='test_conformance-test-color-mask.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-color-mask.o `test -f 'test-color-mask.c' || echo '$(srcdir)/'`test-color-mask.c + +test_conformance-test-color-mask.obj: test-color-mask.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-color-mask.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-color-mask.Tpo -c -o test_conformance-test-color-mask.obj `if test -f 'test-color-mask.c'; then $(CYGPATH_W) 'test-color-mask.c'; else $(CYGPATH_W) '$(srcdir)/test-color-mask.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-color-mask.Tpo $(DEPDIR)/test_conformance-test-color-mask.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-color-mask.c' object='test_conformance-test-color-mask.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-color-mask.obj `if test -f 'test-color-mask.c'; then $(CYGPATH_W) 'test-color-mask.c'; else $(CYGPATH_W) '$(srcdir)/test-color-mask.c'; fi` + +test_conformance-test-backface-culling.o: test-backface-culling.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-backface-culling.o -MD -MP -MF $(DEPDIR)/test_conformance-test-backface-culling.Tpo -c -o test_conformance-test-backface-culling.o `test -f 'test-backface-culling.c' || echo '$(srcdir)/'`test-backface-culling.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-backface-culling.Tpo $(DEPDIR)/test_conformance-test-backface-culling.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-backface-culling.c' object='test_conformance-test-backface-culling.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-backface-culling.o `test -f 'test-backface-culling.c' || echo '$(srcdir)/'`test-backface-culling.c + +test_conformance-test-backface-culling.obj: test-backface-culling.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-backface-culling.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-backface-culling.Tpo -c -o test_conformance-test-backface-culling.obj `if test -f 'test-backface-culling.c'; then $(CYGPATH_W) 'test-backface-culling.c'; else $(CYGPATH_W) '$(srcdir)/test-backface-culling.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-backface-culling.Tpo $(DEPDIR)/test_conformance-test-backface-culling.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-backface-culling.c' object='test_conformance-test-backface-culling.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-backface-culling.obj `if test -f 'test-backface-culling.c'; then $(CYGPATH_W) 'test-backface-culling.c'; else $(CYGPATH_W) '$(srcdir)/test-backface-culling.c'; fi` + +test_conformance-test-just-vertex-shader.o: test-just-vertex-shader.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-just-vertex-shader.o -MD -MP -MF $(DEPDIR)/test_conformance-test-just-vertex-shader.Tpo -c -o test_conformance-test-just-vertex-shader.o `test -f 'test-just-vertex-shader.c' || echo '$(srcdir)/'`test-just-vertex-shader.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-just-vertex-shader.Tpo $(DEPDIR)/test_conformance-test-just-vertex-shader.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-just-vertex-shader.c' object='test_conformance-test-just-vertex-shader.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-just-vertex-shader.o `test -f 'test-just-vertex-shader.c' || echo '$(srcdir)/'`test-just-vertex-shader.c + +test_conformance-test-just-vertex-shader.obj: test-just-vertex-shader.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-just-vertex-shader.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-just-vertex-shader.Tpo -c -o test_conformance-test-just-vertex-shader.obj `if test -f 'test-just-vertex-shader.c'; then $(CYGPATH_W) 'test-just-vertex-shader.c'; else $(CYGPATH_W) '$(srcdir)/test-just-vertex-shader.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-just-vertex-shader.Tpo $(DEPDIR)/test_conformance-test-just-vertex-shader.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-just-vertex-shader.c' object='test_conformance-test-just-vertex-shader.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-just-vertex-shader.obj `if test -f 'test-just-vertex-shader.c'; then $(CYGPATH_W) 'test-just-vertex-shader.c'; else $(CYGPATH_W) '$(srcdir)/test-just-vertex-shader.c'; fi` + +test_conformance-test-pipeline-user-matrix.o: test-pipeline-user-matrix.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-pipeline-user-matrix.o -MD -MP -MF $(DEPDIR)/test_conformance-test-pipeline-user-matrix.Tpo -c -o test_conformance-test-pipeline-user-matrix.o `test -f 'test-pipeline-user-matrix.c' || echo '$(srcdir)/'`test-pipeline-user-matrix.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-pipeline-user-matrix.Tpo $(DEPDIR)/test_conformance-test-pipeline-user-matrix.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-pipeline-user-matrix.c' object='test_conformance-test-pipeline-user-matrix.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-pipeline-user-matrix.o `test -f 'test-pipeline-user-matrix.c' || echo '$(srcdir)/'`test-pipeline-user-matrix.c + +test_conformance-test-pipeline-user-matrix.obj: test-pipeline-user-matrix.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-pipeline-user-matrix.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-pipeline-user-matrix.Tpo -c -o test_conformance-test-pipeline-user-matrix.obj `if test -f 'test-pipeline-user-matrix.c'; then $(CYGPATH_W) 'test-pipeline-user-matrix.c'; else $(CYGPATH_W) '$(srcdir)/test-pipeline-user-matrix.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-pipeline-user-matrix.Tpo $(DEPDIR)/test_conformance-test-pipeline-user-matrix.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-pipeline-user-matrix.c' object='test_conformance-test-pipeline-user-matrix.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-pipeline-user-matrix.obj `if test -f 'test-pipeline-user-matrix.c'; then $(CYGPATH_W) 'test-pipeline-user-matrix.c'; else $(CYGPATH_W) '$(srcdir)/test-pipeline-user-matrix.c'; fi` + +test_conformance-test-pipeline-uniforms.o: test-pipeline-uniforms.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-pipeline-uniforms.o -MD -MP -MF $(DEPDIR)/test_conformance-test-pipeline-uniforms.Tpo -c -o test_conformance-test-pipeline-uniforms.o `test -f 'test-pipeline-uniforms.c' || echo '$(srcdir)/'`test-pipeline-uniforms.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-pipeline-uniforms.Tpo $(DEPDIR)/test_conformance-test-pipeline-uniforms.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-pipeline-uniforms.c' object='test_conformance-test-pipeline-uniforms.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-pipeline-uniforms.o `test -f 'test-pipeline-uniforms.c' || echo '$(srcdir)/'`test-pipeline-uniforms.c + +test_conformance-test-pipeline-uniforms.obj: test-pipeline-uniforms.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-pipeline-uniforms.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-pipeline-uniforms.Tpo -c -o test_conformance-test-pipeline-uniforms.obj `if test -f 'test-pipeline-uniforms.c'; then $(CYGPATH_W) 'test-pipeline-uniforms.c'; else $(CYGPATH_W) '$(srcdir)/test-pipeline-uniforms.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-pipeline-uniforms.Tpo $(DEPDIR)/test_conformance-test-pipeline-uniforms.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-pipeline-uniforms.c' object='test_conformance-test-pipeline-uniforms.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-pipeline-uniforms.obj `if test -f 'test-pipeline-uniforms.c'; then $(CYGPATH_W) 'test-pipeline-uniforms.c'; else $(CYGPATH_W) '$(srcdir)/test-pipeline-uniforms.c'; fi` + +test_conformance-test-pixel-buffer.o: test-pixel-buffer.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-pixel-buffer.o -MD -MP -MF $(DEPDIR)/test_conformance-test-pixel-buffer.Tpo -c -o test_conformance-test-pixel-buffer.o `test -f 'test-pixel-buffer.c' || echo '$(srcdir)/'`test-pixel-buffer.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-pixel-buffer.Tpo $(DEPDIR)/test_conformance-test-pixel-buffer.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-pixel-buffer.c' object='test_conformance-test-pixel-buffer.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-pixel-buffer.o `test -f 'test-pixel-buffer.c' || echo '$(srcdir)/'`test-pixel-buffer.c + +test_conformance-test-pixel-buffer.obj: test-pixel-buffer.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-pixel-buffer.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-pixel-buffer.Tpo -c -o test_conformance-test-pixel-buffer.obj `if test -f 'test-pixel-buffer.c'; then $(CYGPATH_W) 'test-pixel-buffer.c'; else $(CYGPATH_W) '$(srcdir)/test-pixel-buffer.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-pixel-buffer.Tpo $(DEPDIR)/test_conformance-test-pixel-buffer.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-pixel-buffer.c' object='test_conformance-test-pixel-buffer.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-pixel-buffer.obj `if test -f 'test-pixel-buffer.c'; then $(CYGPATH_W) 'test-pixel-buffer.c'; else $(CYGPATH_W) '$(srcdir)/test-pixel-buffer.c'; fi` + +test_conformance-test-premult.o: test-premult.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-premult.o -MD -MP -MF $(DEPDIR)/test_conformance-test-premult.Tpo -c -o test_conformance-test-premult.o `test -f 'test-premult.c' || echo '$(srcdir)/'`test-premult.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-premult.Tpo $(DEPDIR)/test_conformance-test-premult.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-premult.c' object='test_conformance-test-premult.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-premult.o `test -f 'test-premult.c' || echo '$(srcdir)/'`test-premult.c + +test_conformance-test-premult.obj: test-premult.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-premult.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-premult.Tpo -c -o test_conformance-test-premult.obj `if test -f 'test-premult.c'; then $(CYGPATH_W) 'test-premult.c'; else $(CYGPATH_W) '$(srcdir)/test-premult.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-premult.Tpo $(DEPDIR)/test_conformance-test-premult.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-premult.c' object='test_conformance-test-premult.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-premult.obj `if test -f 'test-premult.c'; then $(CYGPATH_W) 'test-premult.c'; else $(CYGPATH_W) '$(srcdir)/test-premult.c'; fi` + +test_conformance-test-snippets.o: test-snippets.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-snippets.o -MD -MP -MF $(DEPDIR)/test_conformance-test-snippets.Tpo -c -o test_conformance-test-snippets.o `test -f 'test-snippets.c' || echo '$(srcdir)/'`test-snippets.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-snippets.Tpo $(DEPDIR)/test_conformance-test-snippets.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-snippets.c' object='test_conformance-test-snippets.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-snippets.o `test -f 'test-snippets.c' || echo '$(srcdir)/'`test-snippets.c + +test_conformance-test-snippets.obj: test-snippets.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-snippets.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-snippets.Tpo -c -o test_conformance-test-snippets.obj `if test -f 'test-snippets.c'; then $(CYGPATH_W) 'test-snippets.c'; else $(CYGPATH_W) '$(srcdir)/test-snippets.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-snippets.Tpo $(DEPDIR)/test_conformance-test-snippets.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-snippets.c' object='test_conformance-test-snippets.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-snippets.obj `if test -f 'test-snippets.c'; then $(CYGPATH_W) 'test-snippets.c'; else $(CYGPATH_W) '$(srcdir)/test-snippets.c'; fi` + +test_conformance-test-wrap-modes.o: test-wrap-modes.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-wrap-modes.o -MD -MP -MF $(DEPDIR)/test_conformance-test-wrap-modes.Tpo -c -o test_conformance-test-wrap-modes.o `test -f 'test-wrap-modes.c' || echo '$(srcdir)/'`test-wrap-modes.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-wrap-modes.Tpo $(DEPDIR)/test_conformance-test-wrap-modes.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-wrap-modes.c' object='test_conformance-test-wrap-modes.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-wrap-modes.o `test -f 'test-wrap-modes.c' || echo '$(srcdir)/'`test-wrap-modes.c + +test_conformance-test-wrap-modes.obj: test-wrap-modes.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-wrap-modes.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-wrap-modes.Tpo -c -o test_conformance-test-wrap-modes.obj `if test -f 'test-wrap-modes.c'; then $(CYGPATH_W) 'test-wrap-modes.c'; else $(CYGPATH_W) '$(srcdir)/test-wrap-modes.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-wrap-modes.Tpo $(DEPDIR)/test_conformance-test-wrap-modes.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-wrap-modes.c' object='test_conformance-test-wrap-modes.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-wrap-modes.obj `if test -f 'test-wrap-modes.c'; then $(CYGPATH_W) 'test-wrap-modes.c'; else $(CYGPATH_W) '$(srcdir)/test-wrap-modes.c'; fi` + +test_conformance-test-sub-texture.o: test-sub-texture.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-sub-texture.o -MD -MP -MF $(DEPDIR)/test_conformance-test-sub-texture.Tpo -c -o test_conformance-test-sub-texture.o `test -f 'test-sub-texture.c' || echo '$(srcdir)/'`test-sub-texture.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-sub-texture.Tpo $(DEPDIR)/test_conformance-test-sub-texture.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-sub-texture.c' object='test_conformance-test-sub-texture.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-sub-texture.o `test -f 'test-sub-texture.c' || echo '$(srcdir)/'`test-sub-texture.c + +test_conformance-test-sub-texture.obj: test-sub-texture.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-sub-texture.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-sub-texture.Tpo -c -o test_conformance-test-sub-texture.obj `if test -f 'test-sub-texture.c'; then $(CYGPATH_W) 'test-sub-texture.c'; else $(CYGPATH_W) '$(srcdir)/test-sub-texture.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-sub-texture.Tpo $(DEPDIR)/test_conformance-test-sub-texture.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-sub-texture.c' object='test_conformance-test-sub-texture.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-sub-texture.obj `if test -f 'test-sub-texture.c'; then $(CYGPATH_W) 'test-sub-texture.c'; else $(CYGPATH_W) '$(srcdir)/test-sub-texture.c'; fi` + +test_conformance-test-custom-attributes.o: test-custom-attributes.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-custom-attributes.o -MD -MP -MF $(DEPDIR)/test_conformance-test-custom-attributes.Tpo -c -o test_conformance-test-custom-attributes.o `test -f 'test-custom-attributes.c' || echo '$(srcdir)/'`test-custom-attributes.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-custom-attributes.Tpo $(DEPDIR)/test_conformance-test-custom-attributes.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-custom-attributes.c' object='test_conformance-test-custom-attributes.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-custom-attributes.o `test -f 'test-custom-attributes.c' || echo '$(srcdir)/'`test-custom-attributes.c + +test_conformance-test-custom-attributes.obj: test-custom-attributes.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-custom-attributes.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-custom-attributes.Tpo -c -o test_conformance-test-custom-attributes.obj `if test -f 'test-custom-attributes.c'; then $(CYGPATH_W) 'test-custom-attributes.c'; else $(CYGPATH_W) '$(srcdir)/test-custom-attributes.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-custom-attributes.Tpo $(DEPDIR)/test_conformance-test-custom-attributes.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-custom-attributes.c' object='test_conformance-test-custom-attributes.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-custom-attributes.obj `if test -f 'test-custom-attributes.c'; then $(CYGPATH_W) 'test-custom-attributes.c'; else $(CYGPATH_W) '$(srcdir)/test-custom-attributes.c'; fi` + +test_conformance-test-offscreen.o: test-offscreen.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-offscreen.o -MD -MP -MF $(DEPDIR)/test_conformance-test-offscreen.Tpo -c -o test_conformance-test-offscreen.o `test -f 'test-offscreen.c' || echo '$(srcdir)/'`test-offscreen.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-offscreen.Tpo $(DEPDIR)/test_conformance-test-offscreen.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-offscreen.c' object='test_conformance-test-offscreen.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-offscreen.o `test -f 'test-offscreen.c' || echo '$(srcdir)/'`test-offscreen.c + +test_conformance-test-offscreen.obj: test-offscreen.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-offscreen.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-offscreen.Tpo -c -o test_conformance-test-offscreen.obj `if test -f 'test-offscreen.c'; then $(CYGPATH_W) 'test-offscreen.c'; else $(CYGPATH_W) '$(srcdir)/test-offscreen.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-offscreen.Tpo $(DEPDIR)/test_conformance-test-offscreen.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-offscreen.c' object='test_conformance-test-offscreen.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-offscreen.obj `if test -f 'test-offscreen.c'; then $(CYGPATH_W) 'test-offscreen.c'; else $(CYGPATH_W) '$(srcdir)/test-offscreen.c'; fi` + +test_conformance-test-primitive.o: test-primitive.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-primitive.o -MD -MP -MF $(DEPDIR)/test_conformance-test-primitive.Tpo -c -o test_conformance-test-primitive.o `test -f 'test-primitive.c' || echo '$(srcdir)/'`test-primitive.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-primitive.Tpo $(DEPDIR)/test_conformance-test-primitive.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-primitive.c' object='test_conformance-test-primitive.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-primitive.o `test -f 'test-primitive.c' || echo '$(srcdir)/'`test-primitive.c + +test_conformance-test-primitive.obj: test-primitive.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-primitive.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-primitive.Tpo -c -o test_conformance-test-primitive.obj `if test -f 'test-primitive.c'; then $(CYGPATH_W) 'test-primitive.c'; else $(CYGPATH_W) '$(srcdir)/test-primitive.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-primitive.Tpo $(DEPDIR)/test_conformance-test-primitive.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-primitive.c' object='test_conformance-test-primitive.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-primitive.obj `if test -f 'test-primitive.c'; then $(CYGPATH_W) 'test-primitive.c'; else $(CYGPATH_W) '$(srcdir)/test-primitive.c'; fi` + +test_conformance-test-texture-3d.o: test-texture-3d.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-texture-3d.o -MD -MP -MF $(DEPDIR)/test_conformance-test-texture-3d.Tpo -c -o test_conformance-test-texture-3d.o `test -f 'test-texture-3d.c' || echo '$(srcdir)/'`test-texture-3d.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-texture-3d.Tpo $(DEPDIR)/test_conformance-test-texture-3d.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-texture-3d.c' object='test_conformance-test-texture-3d.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-texture-3d.o `test -f 'test-texture-3d.c' || echo '$(srcdir)/'`test-texture-3d.c + +test_conformance-test-texture-3d.obj: test-texture-3d.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-texture-3d.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-texture-3d.Tpo -c -o test_conformance-test-texture-3d.obj `if test -f 'test-texture-3d.c'; then $(CYGPATH_W) 'test-texture-3d.c'; else $(CYGPATH_W) '$(srcdir)/test-texture-3d.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-texture-3d.Tpo $(DEPDIR)/test_conformance-test-texture-3d.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-texture-3d.c' object='test_conformance-test-texture-3d.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-texture-3d.obj `if test -f 'test-texture-3d.c'; then $(CYGPATH_W) 'test-texture-3d.c'; else $(CYGPATH_W) '$(srcdir)/test-texture-3d.c'; fi` + +test_conformance-test-sparse-pipeline.o: test-sparse-pipeline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-sparse-pipeline.o -MD -MP -MF $(DEPDIR)/test_conformance-test-sparse-pipeline.Tpo -c -o test_conformance-test-sparse-pipeline.o `test -f 'test-sparse-pipeline.c' || echo '$(srcdir)/'`test-sparse-pipeline.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-sparse-pipeline.Tpo $(DEPDIR)/test_conformance-test-sparse-pipeline.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-sparse-pipeline.c' object='test_conformance-test-sparse-pipeline.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-sparse-pipeline.o `test -f 'test-sparse-pipeline.c' || echo '$(srcdir)/'`test-sparse-pipeline.c + +test_conformance-test-sparse-pipeline.obj: test-sparse-pipeline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-sparse-pipeline.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-sparse-pipeline.Tpo -c -o test_conformance-test-sparse-pipeline.obj `if test -f 'test-sparse-pipeline.c'; then $(CYGPATH_W) 'test-sparse-pipeline.c'; else $(CYGPATH_W) '$(srcdir)/test-sparse-pipeline.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-sparse-pipeline.Tpo $(DEPDIR)/test_conformance-test-sparse-pipeline.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-sparse-pipeline.c' object='test_conformance-test-sparse-pipeline.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-sparse-pipeline.obj `if test -f 'test-sparse-pipeline.c'; then $(CYGPATH_W) 'test-sparse-pipeline.c'; else $(CYGPATH_W) '$(srcdir)/test-sparse-pipeline.c'; fi` + +test_conformance-test-read-texture-formats.o: test-read-texture-formats.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-read-texture-formats.o -MD -MP -MF $(DEPDIR)/test_conformance-test-read-texture-formats.Tpo -c -o test_conformance-test-read-texture-formats.o `test -f 'test-read-texture-formats.c' || echo '$(srcdir)/'`test-read-texture-formats.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-read-texture-formats.Tpo $(DEPDIR)/test_conformance-test-read-texture-formats.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-read-texture-formats.c' object='test_conformance-test-read-texture-formats.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-read-texture-formats.o `test -f 'test-read-texture-formats.c' || echo '$(srcdir)/'`test-read-texture-formats.c + +test_conformance-test-read-texture-formats.obj: test-read-texture-formats.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-read-texture-formats.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-read-texture-formats.Tpo -c -o test_conformance-test-read-texture-formats.obj `if test -f 'test-read-texture-formats.c'; then $(CYGPATH_W) 'test-read-texture-formats.c'; else $(CYGPATH_W) '$(srcdir)/test-read-texture-formats.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-read-texture-formats.Tpo $(DEPDIR)/test_conformance-test-read-texture-formats.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-read-texture-formats.c' object='test_conformance-test-read-texture-formats.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-read-texture-formats.obj `if test -f 'test-read-texture-formats.c'; then $(CYGPATH_W) 'test-read-texture-formats.c'; else $(CYGPATH_W) '$(srcdir)/test-read-texture-formats.c'; fi` + +test_conformance-test-write-texture-formats.o: test-write-texture-formats.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-write-texture-formats.o -MD -MP -MF $(DEPDIR)/test_conformance-test-write-texture-formats.Tpo -c -o test_conformance-test-write-texture-formats.o `test -f 'test-write-texture-formats.c' || echo '$(srcdir)/'`test-write-texture-formats.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-write-texture-formats.Tpo $(DEPDIR)/test_conformance-test-write-texture-formats.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-write-texture-formats.c' object='test_conformance-test-write-texture-formats.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-write-texture-formats.o `test -f 'test-write-texture-formats.c' || echo '$(srcdir)/'`test-write-texture-formats.c + +test_conformance-test-write-texture-formats.obj: test-write-texture-formats.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-write-texture-formats.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-write-texture-formats.Tpo -c -o test_conformance-test-write-texture-formats.obj `if test -f 'test-write-texture-formats.c'; then $(CYGPATH_W) 'test-write-texture-formats.c'; else $(CYGPATH_W) '$(srcdir)/test-write-texture-formats.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-write-texture-formats.Tpo $(DEPDIR)/test_conformance-test-write-texture-formats.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-write-texture-formats.c' object='test_conformance-test-write-texture-formats.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-write-texture-formats.obj `if test -f 'test-write-texture-formats.c'; then $(CYGPATH_W) 'test-write-texture-formats.c'; else $(CYGPATH_W) '$(srcdir)/test-write-texture-formats.c'; fi` + +test_conformance-test-point-size.o: test-point-size.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-point-size.o -MD -MP -MF $(DEPDIR)/test_conformance-test-point-size.Tpo -c -o test_conformance-test-point-size.o `test -f 'test-point-size.c' || echo '$(srcdir)/'`test-point-size.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-point-size.Tpo $(DEPDIR)/test_conformance-test-point-size.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-point-size.c' object='test_conformance-test-point-size.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-point-size.o `test -f 'test-point-size.c' || echo '$(srcdir)/'`test-point-size.c + +test_conformance-test-point-size.obj: test-point-size.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-point-size.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-point-size.Tpo -c -o test_conformance-test-point-size.obj `if test -f 'test-point-size.c'; then $(CYGPATH_W) 'test-point-size.c'; else $(CYGPATH_W) '$(srcdir)/test-point-size.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-point-size.Tpo $(DEPDIR)/test_conformance-test-point-size.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-point-size.c' object='test_conformance-test-point-size.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-point-size.obj `if test -f 'test-point-size.c'; then $(CYGPATH_W) 'test-point-size.c'; else $(CYGPATH_W) '$(srcdir)/test-point-size.c'; fi` + +test_conformance-test-point-size-attribute.o: test-point-size-attribute.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-point-size-attribute.o -MD -MP -MF $(DEPDIR)/test_conformance-test-point-size-attribute.Tpo -c -o test_conformance-test-point-size-attribute.o `test -f 'test-point-size-attribute.c' || echo '$(srcdir)/'`test-point-size-attribute.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-point-size-attribute.Tpo $(DEPDIR)/test_conformance-test-point-size-attribute.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-point-size-attribute.c' object='test_conformance-test-point-size-attribute.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-point-size-attribute.o `test -f 'test-point-size-attribute.c' || echo '$(srcdir)/'`test-point-size-attribute.c + +test_conformance-test-point-size-attribute.obj: test-point-size-attribute.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-point-size-attribute.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-point-size-attribute.Tpo -c -o test_conformance-test-point-size-attribute.obj `if test -f 'test-point-size-attribute.c'; then $(CYGPATH_W) 'test-point-size-attribute.c'; else $(CYGPATH_W) '$(srcdir)/test-point-size-attribute.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-point-size-attribute.Tpo $(DEPDIR)/test_conformance-test-point-size-attribute.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-point-size-attribute.c' object='test_conformance-test-point-size-attribute.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-point-size-attribute.obj `if test -f 'test-point-size-attribute.c'; then $(CYGPATH_W) 'test-point-size-attribute.c'; else $(CYGPATH_W) '$(srcdir)/test-point-size-attribute.c'; fi` + +test_conformance-test-point-sprite.o: test-point-sprite.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-point-sprite.o -MD -MP -MF $(DEPDIR)/test_conformance-test-point-sprite.Tpo -c -o test_conformance-test-point-sprite.o `test -f 'test-point-sprite.c' || echo '$(srcdir)/'`test-point-sprite.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-point-sprite.Tpo $(DEPDIR)/test_conformance-test-point-sprite.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-point-sprite.c' object='test_conformance-test-point-sprite.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-point-sprite.o `test -f 'test-point-sprite.c' || echo '$(srcdir)/'`test-point-sprite.c + +test_conformance-test-point-sprite.obj: test-point-sprite.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-point-sprite.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-point-sprite.Tpo -c -o test_conformance-test-point-sprite.obj `if test -f 'test-point-sprite.c'; then $(CYGPATH_W) 'test-point-sprite.c'; else $(CYGPATH_W) '$(srcdir)/test-point-sprite.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-point-sprite.Tpo $(DEPDIR)/test_conformance-test-point-sprite.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-point-sprite.c' object='test_conformance-test-point-sprite.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-point-sprite.obj `if test -f 'test-point-sprite.c'; then $(CYGPATH_W) 'test-point-sprite.c'; else $(CYGPATH_W) '$(srcdir)/test-point-sprite.c'; fi` + +test_conformance-test-no-gl-header.o: test-no-gl-header.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-no-gl-header.o -MD -MP -MF $(DEPDIR)/test_conformance-test-no-gl-header.Tpo -c -o test_conformance-test-no-gl-header.o `test -f 'test-no-gl-header.c' || echo '$(srcdir)/'`test-no-gl-header.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-no-gl-header.Tpo $(DEPDIR)/test_conformance-test-no-gl-header.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-no-gl-header.c' object='test_conformance-test-no-gl-header.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-no-gl-header.o `test -f 'test-no-gl-header.c' || echo '$(srcdir)/'`test-no-gl-header.c + +test_conformance-test-no-gl-header.obj: test-no-gl-header.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-no-gl-header.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-no-gl-header.Tpo -c -o test_conformance-test-no-gl-header.obj `if test -f 'test-no-gl-header.c'; then $(CYGPATH_W) 'test-no-gl-header.c'; else $(CYGPATH_W) '$(srcdir)/test-no-gl-header.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-no-gl-header.Tpo $(DEPDIR)/test_conformance-test-no-gl-header.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-no-gl-header.c' object='test_conformance-test-no-gl-header.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-no-gl-header.obj `if test -f 'test-no-gl-header.c'; then $(CYGPATH_W) 'test-no-gl-header.c'; else $(CYGPATH_W) '$(srcdir)/test-no-gl-header.c'; fi` + +test_conformance-test-version.o: test-version.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-version.o -MD -MP -MF $(DEPDIR)/test_conformance-test-version.Tpo -c -o test_conformance-test-version.o `test -f 'test-version.c' || echo '$(srcdir)/'`test-version.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-version.Tpo $(DEPDIR)/test_conformance-test-version.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-version.c' object='test_conformance-test-version.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-version.o `test -f 'test-version.c' || echo '$(srcdir)/'`test-version.c + +test_conformance-test-version.obj: test-version.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-version.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-version.Tpo -c -o test_conformance-test-version.obj `if test -f 'test-version.c'; then $(CYGPATH_W) 'test-version.c'; else $(CYGPATH_W) '$(srcdir)/test-version.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-version.Tpo $(DEPDIR)/test_conformance-test-version.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-version.c' object='test_conformance-test-version.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-version.obj `if test -f 'test-version.c'; then $(CYGPATH_W) 'test-version.c'; else $(CYGPATH_W) '$(srcdir)/test-version.c'; fi` + +test_conformance-test-gles2-context.o: test-gles2-context.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-gles2-context.o -MD -MP -MF $(DEPDIR)/test_conformance-test-gles2-context.Tpo -c -o test_conformance-test-gles2-context.o `test -f 'test-gles2-context.c' || echo '$(srcdir)/'`test-gles2-context.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-gles2-context.Tpo $(DEPDIR)/test_conformance-test-gles2-context.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-gles2-context.c' object='test_conformance-test-gles2-context.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-gles2-context.o `test -f 'test-gles2-context.c' || echo '$(srcdir)/'`test-gles2-context.c + +test_conformance-test-gles2-context.obj: test-gles2-context.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-gles2-context.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-gles2-context.Tpo -c -o test_conformance-test-gles2-context.obj `if test -f 'test-gles2-context.c'; then $(CYGPATH_W) 'test-gles2-context.c'; else $(CYGPATH_W) '$(srcdir)/test-gles2-context.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-gles2-context.Tpo $(DEPDIR)/test_conformance-test-gles2-context.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-gles2-context.c' object='test_conformance-test-gles2-context.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-gles2-context.obj `if test -f 'test-gles2-context.c'; then $(CYGPATH_W) 'test-gles2-context.c'; else $(CYGPATH_W) '$(srcdir)/test-gles2-context.c'; fi` + +test_conformance-test-euler-quaternion.o: test-euler-quaternion.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-euler-quaternion.o -MD -MP -MF $(DEPDIR)/test_conformance-test-euler-quaternion.Tpo -c -o test_conformance-test-euler-quaternion.o `test -f 'test-euler-quaternion.c' || echo '$(srcdir)/'`test-euler-quaternion.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-euler-quaternion.Tpo $(DEPDIR)/test_conformance-test-euler-quaternion.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-euler-quaternion.c' object='test_conformance-test-euler-quaternion.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-euler-quaternion.o `test -f 'test-euler-quaternion.c' || echo '$(srcdir)/'`test-euler-quaternion.c + +test_conformance-test-euler-quaternion.obj: test-euler-quaternion.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-euler-quaternion.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-euler-quaternion.Tpo -c -o test_conformance-test-euler-quaternion.obj `if test -f 'test-euler-quaternion.c'; then $(CYGPATH_W) 'test-euler-quaternion.c'; else $(CYGPATH_W) '$(srcdir)/test-euler-quaternion.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-euler-quaternion.Tpo $(DEPDIR)/test_conformance-test-euler-quaternion.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-euler-quaternion.c' object='test_conformance-test-euler-quaternion.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-euler-quaternion.obj `if test -f 'test-euler-quaternion.c'; then $(CYGPATH_W) 'test-euler-quaternion.c'; else $(CYGPATH_W) '$(srcdir)/test-euler-quaternion.c'; fi` + +test_conformance-test-layer-remove.o: test-layer-remove.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-layer-remove.o -MD -MP -MF $(DEPDIR)/test_conformance-test-layer-remove.Tpo -c -o test_conformance-test-layer-remove.o `test -f 'test-layer-remove.c' || echo '$(srcdir)/'`test-layer-remove.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-layer-remove.Tpo $(DEPDIR)/test_conformance-test-layer-remove.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-layer-remove.c' object='test_conformance-test-layer-remove.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-layer-remove.o `test -f 'test-layer-remove.c' || echo '$(srcdir)/'`test-layer-remove.c + +test_conformance-test-layer-remove.obj: test-layer-remove.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-layer-remove.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-layer-remove.Tpo -c -o test_conformance-test-layer-remove.obj `if test -f 'test-layer-remove.c'; then $(CYGPATH_W) 'test-layer-remove.c'; else $(CYGPATH_W) '$(srcdir)/test-layer-remove.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-layer-remove.Tpo $(DEPDIR)/test_conformance-test-layer-remove.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-layer-remove.c' object='test_conformance-test-layer-remove.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-layer-remove.obj `if test -f 'test-layer-remove.c'; then $(CYGPATH_W) 'test-layer-remove.c'; else $(CYGPATH_W) '$(srcdir)/test-layer-remove.c'; fi` + +test_conformance-test-alpha-test.o: test-alpha-test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-alpha-test.o -MD -MP -MF $(DEPDIR)/test_conformance-test-alpha-test.Tpo -c -o test_conformance-test-alpha-test.o `test -f 'test-alpha-test.c' || echo '$(srcdir)/'`test-alpha-test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-alpha-test.Tpo $(DEPDIR)/test_conformance-test-alpha-test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-alpha-test.c' object='test_conformance-test-alpha-test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-alpha-test.o `test -f 'test-alpha-test.c' || echo '$(srcdir)/'`test-alpha-test.c + +test_conformance-test-alpha-test.obj: test-alpha-test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-alpha-test.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-alpha-test.Tpo -c -o test_conformance-test-alpha-test.obj `if test -f 'test-alpha-test.c'; then $(CYGPATH_W) 'test-alpha-test.c'; else $(CYGPATH_W) '$(srcdir)/test-alpha-test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-alpha-test.Tpo $(DEPDIR)/test_conformance-test-alpha-test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-alpha-test.c' object='test_conformance-test-alpha-test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-alpha-test.obj `if test -f 'test-alpha-test.c'; then $(CYGPATH_W) 'test-alpha-test.c'; else $(CYGPATH_W) '$(srcdir)/test-alpha-test.c'; fi` + +test_conformance-test-map-buffer-range.o: test-map-buffer-range.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-map-buffer-range.o -MD -MP -MF $(DEPDIR)/test_conformance-test-map-buffer-range.Tpo -c -o test_conformance-test-map-buffer-range.o `test -f 'test-map-buffer-range.c' || echo '$(srcdir)/'`test-map-buffer-range.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-map-buffer-range.Tpo $(DEPDIR)/test_conformance-test-map-buffer-range.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-map-buffer-range.c' object='test_conformance-test-map-buffer-range.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-map-buffer-range.o `test -f 'test-map-buffer-range.c' || echo '$(srcdir)/'`test-map-buffer-range.c + +test_conformance-test-map-buffer-range.obj: test-map-buffer-range.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-map-buffer-range.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-map-buffer-range.Tpo -c -o test_conformance-test-map-buffer-range.obj `if test -f 'test-map-buffer-range.c'; then $(CYGPATH_W) 'test-map-buffer-range.c'; else $(CYGPATH_W) '$(srcdir)/test-map-buffer-range.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-map-buffer-range.Tpo $(DEPDIR)/test_conformance-test-map-buffer-range.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-map-buffer-range.c' object='test_conformance-test-map-buffer-range.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-map-buffer-range.obj `if test -f 'test-map-buffer-range.c'; then $(CYGPATH_W) 'test-map-buffer-range.c'; else $(CYGPATH_W) '$(srcdir)/test-map-buffer-range.c'; fi` + +test_conformance-test-npot-texture.o: test-npot-texture.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-npot-texture.o -MD -MP -MF $(DEPDIR)/test_conformance-test-npot-texture.Tpo -c -o test_conformance-test-npot-texture.o `test -f 'test-npot-texture.c' || echo '$(srcdir)/'`test-npot-texture.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-npot-texture.Tpo $(DEPDIR)/test_conformance-test-npot-texture.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-npot-texture.c' object='test_conformance-test-npot-texture.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-npot-texture.o `test -f 'test-npot-texture.c' || echo '$(srcdir)/'`test-npot-texture.c + +test_conformance-test-npot-texture.obj: test-npot-texture.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-npot-texture.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-npot-texture.Tpo -c -o test_conformance-test-npot-texture.obj `if test -f 'test-npot-texture.c'; then $(CYGPATH_W) 'test-npot-texture.c'; else $(CYGPATH_W) '$(srcdir)/test-npot-texture.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-npot-texture.Tpo $(DEPDIR)/test_conformance-test-npot-texture.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-npot-texture.c' object='test_conformance-test-npot-texture.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-npot-texture.obj `if test -f 'test-npot-texture.c'; then $(CYGPATH_W) 'test-npot-texture.c'; else $(CYGPATH_W) '$(srcdir)/test-npot-texture.c'; fi` + +test_conformance-test-alpha-textures.o: test-alpha-textures.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-alpha-textures.o -MD -MP -MF $(DEPDIR)/test_conformance-test-alpha-textures.Tpo -c -o test_conformance-test-alpha-textures.o `test -f 'test-alpha-textures.c' || echo '$(srcdir)/'`test-alpha-textures.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-alpha-textures.Tpo $(DEPDIR)/test_conformance-test-alpha-textures.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-alpha-textures.c' object='test_conformance-test-alpha-textures.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-alpha-textures.o `test -f 'test-alpha-textures.c' || echo '$(srcdir)/'`test-alpha-textures.c + +test_conformance-test-alpha-textures.obj: test-alpha-textures.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-alpha-textures.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-alpha-textures.Tpo -c -o test_conformance-test-alpha-textures.obj `if test -f 'test-alpha-textures.c'; then $(CYGPATH_W) 'test-alpha-textures.c'; else $(CYGPATH_W) '$(srcdir)/test-alpha-textures.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-alpha-textures.Tpo $(DEPDIR)/test_conformance-test-alpha-textures.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-alpha-textures.c' object='test_conformance-test-alpha-textures.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-alpha-textures.obj `if test -f 'test-alpha-textures.c'; then $(CYGPATH_W) 'test-alpha-textures.c'; else $(CYGPATH_W) '$(srcdir)/test-alpha-textures.c'; fi` + +test_conformance-test-wrap-rectangle-textures.o: test-wrap-rectangle-textures.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-wrap-rectangle-textures.o -MD -MP -MF $(DEPDIR)/test_conformance-test-wrap-rectangle-textures.Tpo -c -o test_conformance-test-wrap-rectangle-textures.o `test -f 'test-wrap-rectangle-textures.c' || echo '$(srcdir)/'`test-wrap-rectangle-textures.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-wrap-rectangle-textures.Tpo $(DEPDIR)/test_conformance-test-wrap-rectangle-textures.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-wrap-rectangle-textures.c' object='test_conformance-test-wrap-rectangle-textures.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-wrap-rectangle-textures.o `test -f 'test-wrap-rectangle-textures.c' || echo '$(srcdir)/'`test-wrap-rectangle-textures.c + +test_conformance-test-wrap-rectangle-textures.obj: test-wrap-rectangle-textures.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-wrap-rectangle-textures.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-wrap-rectangle-textures.Tpo -c -o test_conformance-test-wrap-rectangle-textures.obj `if test -f 'test-wrap-rectangle-textures.c'; then $(CYGPATH_W) 'test-wrap-rectangle-textures.c'; else $(CYGPATH_W) '$(srcdir)/test-wrap-rectangle-textures.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-wrap-rectangle-textures.Tpo $(DEPDIR)/test_conformance-test-wrap-rectangle-textures.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-wrap-rectangle-textures.c' object='test_conformance-test-wrap-rectangle-textures.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-wrap-rectangle-textures.obj `if test -f 'test-wrap-rectangle-textures.c'; then $(CYGPATH_W) 'test-wrap-rectangle-textures.c'; else $(CYGPATH_W) '$(srcdir)/test-wrap-rectangle-textures.c'; fi` + +test_conformance-test-texture-get-set-data.o: test-texture-get-set-data.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-texture-get-set-data.o -MD -MP -MF $(DEPDIR)/test_conformance-test-texture-get-set-data.Tpo -c -o test_conformance-test-texture-get-set-data.o `test -f 'test-texture-get-set-data.c' || echo '$(srcdir)/'`test-texture-get-set-data.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-texture-get-set-data.Tpo $(DEPDIR)/test_conformance-test-texture-get-set-data.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-texture-get-set-data.c' object='test_conformance-test-texture-get-set-data.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-texture-get-set-data.o `test -f 'test-texture-get-set-data.c' || echo '$(srcdir)/'`test-texture-get-set-data.c + +test_conformance-test-texture-get-set-data.obj: test-texture-get-set-data.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-texture-get-set-data.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-texture-get-set-data.Tpo -c -o test_conformance-test-texture-get-set-data.obj `if test -f 'test-texture-get-set-data.c'; then $(CYGPATH_W) 'test-texture-get-set-data.c'; else $(CYGPATH_W) '$(srcdir)/test-texture-get-set-data.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-texture-get-set-data.Tpo $(DEPDIR)/test_conformance-test-texture-get-set-data.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-texture-get-set-data.c' object='test_conformance-test-texture-get-set-data.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-texture-get-set-data.obj `if test -f 'test-texture-get-set-data.c'; then $(CYGPATH_W) 'test-texture-get-set-data.c'; else $(CYGPATH_W) '$(srcdir)/test-texture-get-set-data.c'; fi` + +test_conformance-test-framebuffer-get-bits.o: test-framebuffer-get-bits.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-framebuffer-get-bits.o -MD -MP -MF $(DEPDIR)/test_conformance-test-framebuffer-get-bits.Tpo -c -o test_conformance-test-framebuffer-get-bits.o `test -f 'test-framebuffer-get-bits.c' || echo '$(srcdir)/'`test-framebuffer-get-bits.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-framebuffer-get-bits.Tpo $(DEPDIR)/test_conformance-test-framebuffer-get-bits.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-framebuffer-get-bits.c' object='test_conformance-test-framebuffer-get-bits.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-framebuffer-get-bits.o `test -f 'test-framebuffer-get-bits.c' || echo '$(srcdir)/'`test-framebuffer-get-bits.c + +test_conformance-test-framebuffer-get-bits.obj: test-framebuffer-get-bits.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-framebuffer-get-bits.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-framebuffer-get-bits.Tpo -c -o test_conformance-test-framebuffer-get-bits.obj `if test -f 'test-framebuffer-get-bits.c'; then $(CYGPATH_W) 'test-framebuffer-get-bits.c'; else $(CYGPATH_W) '$(srcdir)/test-framebuffer-get-bits.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-framebuffer-get-bits.Tpo $(DEPDIR)/test_conformance-test-framebuffer-get-bits.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-framebuffer-get-bits.c' object='test_conformance-test-framebuffer-get-bits.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-framebuffer-get-bits.obj `if test -f 'test-framebuffer-get-bits.c'; then $(CYGPATH_W) 'test-framebuffer-get-bits.c'; else $(CYGPATH_W) '$(srcdir)/test-framebuffer-get-bits.c'; fi` + +test_conformance-test-primitive-and-journal.o: test-primitive-and-journal.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-primitive-and-journal.o -MD -MP -MF $(DEPDIR)/test_conformance-test-primitive-and-journal.Tpo -c -o test_conformance-test-primitive-and-journal.o `test -f 'test-primitive-and-journal.c' || echo '$(srcdir)/'`test-primitive-and-journal.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-primitive-and-journal.Tpo $(DEPDIR)/test_conformance-test-primitive-and-journal.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-primitive-and-journal.c' object='test_conformance-test-primitive-and-journal.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-primitive-and-journal.o `test -f 'test-primitive-and-journal.c' || echo '$(srcdir)/'`test-primitive-and-journal.c + +test_conformance-test-primitive-and-journal.obj: test-primitive-and-journal.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-primitive-and-journal.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-primitive-and-journal.Tpo -c -o test_conformance-test-primitive-and-journal.obj `if test -f 'test-primitive-and-journal.c'; then $(CYGPATH_W) 'test-primitive-and-journal.c'; else $(CYGPATH_W) '$(srcdir)/test-primitive-and-journal.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-primitive-and-journal.Tpo $(DEPDIR)/test_conformance-test-primitive-and-journal.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-primitive-and-journal.c' object='test_conformance-test-primitive-and-journal.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-primitive-and-journal.obj `if test -f 'test-primitive-and-journal.c'; then $(CYGPATH_W) 'test-primitive-and-journal.c'; else $(CYGPATH_W) '$(srcdir)/test-primitive-and-journal.c'; fi` + +test_conformance-test-copy-replace-texture.o: test-copy-replace-texture.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-copy-replace-texture.o -MD -MP -MF $(DEPDIR)/test_conformance-test-copy-replace-texture.Tpo -c -o test_conformance-test-copy-replace-texture.o `test -f 'test-copy-replace-texture.c' || echo '$(srcdir)/'`test-copy-replace-texture.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-copy-replace-texture.Tpo $(DEPDIR)/test_conformance-test-copy-replace-texture.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-copy-replace-texture.c' object='test_conformance-test-copy-replace-texture.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-copy-replace-texture.o `test -f 'test-copy-replace-texture.c' || echo '$(srcdir)/'`test-copy-replace-texture.c + +test_conformance-test-copy-replace-texture.obj: test-copy-replace-texture.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-copy-replace-texture.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-copy-replace-texture.Tpo -c -o test_conformance-test-copy-replace-texture.obj `if test -f 'test-copy-replace-texture.c'; then $(CYGPATH_W) 'test-copy-replace-texture.c'; else $(CYGPATH_W) '$(srcdir)/test-copy-replace-texture.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-copy-replace-texture.Tpo $(DEPDIR)/test_conformance-test-copy-replace-texture.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-copy-replace-texture.c' object='test_conformance-test-copy-replace-texture.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-copy-replace-texture.obj `if test -f 'test-copy-replace-texture.c'; then $(CYGPATH_W) 'test-copy-replace-texture.c'; else $(CYGPATH_W) '$(srcdir)/test-copy-replace-texture.c'; fi` + +test_conformance-test-pipeline-cache-unrefs-texture.o: test-pipeline-cache-unrefs-texture.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-pipeline-cache-unrefs-texture.o -MD -MP -MF $(DEPDIR)/test_conformance-test-pipeline-cache-unrefs-texture.Tpo -c -o test_conformance-test-pipeline-cache-unrefs-texture.o `test -f 'test-pipeline-cache-unrefs-texture.c' || echo '$(srcdir)/'`test-pipeline-cache-unrefs-texture.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-pipeline-cache-unrefs-texture.Tpo $(DEPDIR)/test_conformance-test-pipeline-cache-unrefs-texture.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-pipeline-cache-unrefs-texture.c' object='test_conformance-test-pipeline-cache-unrefs-texture.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-pipeline-cache-unrefs-texture.o `test -f 'test-pipeline-cache-unrefs-texture.c' || echo '$(srcdir)/'`test-pipeline-cache-unrefs-texture.c + +test_conformance-test-pipeline-cache-unrefs-texture.obj: test-pipeline-cache-unrefs-texture.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-pipeline-cache-unrefs-texture.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-pipeline-cache-unrefs-texture.Tpo -c -o test_conformance-test-pipeline-cache-unrefs-texture.obj `if test -f 'test-pipeline-cache-unrefs-texture.c'; then $(CYGPATH_W) 'test-pipeline-cache-unrefs-texture.c'; else $(CYGPATH_W) '$(srcdir)/test-pipeline-cache-unrefs-texture.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-pipeline-cache-unrefs-texture.Tpo $(DEPDIR)/test_conformance-test-pipeline-cache-unrefs-texture.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-pipeline-cache-unrefs-texture.c' object='test_conformance-test-pipeline-cache-unrefs-texture.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-pipeline-cache-unrefs-texture.obj `if test -f 'test-pipeline-cache-unrefs-texture.c'; then $(CYGPATH_W) 'test-pipeline-cache-unrefs-texture.c'; else $(CYGPATH_W) '$(srcdir)/test-pipeline-cache-unrefs-texture.c'; fi` + +test_conformance-test-texture-no-allocate.o: test-texture-no-allocate.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-texture-no-allocate.o -MD -MP -MF $(DEPDIR)/test_conformance-test-texture-no-allocate.Tpo -c -o test_conformance-test-texture-no-allocate.o `test -f 'test-texture-no-allocate.c' || echo '$(srcdir)/'`test-texture-no-allocate.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-texture-no-allocate.Tpo $(DEPDIR)/test_conformance-test-texture-no-allocate.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-texture-no-allocate.c' object='test_conformance-test-texture-no-allocate.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-texture-no-allocate.o `test -f 'test-texture-no-allocate.c' || echo '$(srcdir)/'`test-texture-no-allocate.c + +test_conformance-test-texture-no-allocate.obj: test-texture-no-allocate.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-texture-no-allocate.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-texture-no-allocate.Tpo -c -o test_conformance-test-texture-no-allocate.obj `if test -f 'test-texture-no-allocate.c'; then $(CYGPATH_W) 'test-texture-no-allocate.c'; else $(CYGPATH_W) '$(srcdir)/test-texture-no-allocate.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-texture-no-allocate.Tpo $(DEPDIR)/test_conformance-test-texture-no-allocate.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-texture-no-allocate.c' object='test_conformance-test-texture-no-allocate.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-texture-no-allocate.obj `if test -f 'test-texture-no-allocate.c'; then $(CYGPATH_W) 'test-texture-no-allocate.c'; else $(CYGPATH_W) '$(srcdir)/test-texture-no-allocate.c'; fi` + +test_conformance-test-pipeline-shader-state.o: test-pipeline-shader-state.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-pipeline-shader-state.o -MD -MP -MF $(DEPDIR)/test_conformance-test-pipeline-shader-state.Tpo -c -o test_conformance-test-pipeline-shader-state.o `test -f 'test-pipeline-shader-state.c' || echo '$(srcdir)/'`test-pipeline-shader-state.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-pipeline-shader-state.Tpo $(DEPDIR)/test_conformance-test-pipeline-shader-state.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-pipeline-shader-state.c' object='test_conformance-test-pipeline-shader-state.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-pipeline-shader-state.o `test -f 'test-pipeline-shader-state.c' || echo '$(srcdir)/'`test-pipeline-shader-state.c + +test_conformance-test-pipeline-shader-state.obj: test-pipeline-shader-state.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-pipeline-shader-state.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-pipeline-shader-state.Tpo -c -o test_conformance-test-pipeline-shader-state.obj `if test -f 'test-pipeline-shader-state.c'; then $(CYGPATH_W) 'test-pipeline-shader-state.c'; else $(CYGPATH_W) '$(srcdir)/test-pipeline-shader-state.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-pipeline-shader-state.Tpo $(DEPDIR)/test_conformance-test-pipeline-shader-state.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-pipeline-shader-state.c' object='test_conformance-test-pipeline-shader-state.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-pipeline-shader-state.obj `if test -f 'test-pipeline-shader-state.c'; then $(CYGPATH_W) 'test-pipeline-shader-state.c'; else $(CYGPATH_W) '$(srcdir)/test-pipeline-shader-state.c'; fi` + +test_conformance-test-texture-rg.o: test-texture-rg.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-texture-rg.o -MD -MP -MF $(DEPDIR)/test_conformance-test-texture-rg.Tpo -c -o test_conformance-test-texture-rg.o `test -f 'test-texture-rg.c' || echo '$(srcdir)/'`test-texture-rg.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-texture-rg.Tpo $(DEPDIR)/test_conformance-test-texture-rg.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-texture-rg.c' object='test_conformance-test-texture-rg.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-texture-rg.o `test -f 'test-texture-rg.c' || echo '$(srcdir)/'`test-texture-rg.c + +test_conformance-test-texture-rg.obj: test-texture-rg.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-texture-rg.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-texture-rg.Tpo -c -o test_conformance-test-texture-rg.obj `if test -f 'test-texture-rg.c'; then $(CYGPATH_W) 'test-texture-rg.c'; else $(CYGPATH_W) '$(srcdir)/test-texture-rg.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-texture-rg.Tpo $(DEPDIR)/test_conformance-test-texture-rg.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-texture-rg.c' object='test_conformance-test-texture-rg.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-texture-rg.obj `if test -f 'test-texture-rg.c'; then $(CYGPATH_W) 'test-texture-rg.c'; else $(CYGPATH_W) '$(srcdir)/test-texture-rg.c'; fi` + +test_conformance-test-fence.o: test-fence.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-fence.o -MD -MP -MF $(DEPDIR)/test_conformance-test-fence.Tpo -c -o test_conformance-test-fence.o `test -f 'test-fence.c' || echo '$(srcdir)/'`test-fence.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-fence.Tpo $(DEPDIR)/test_conformance-test-fence.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-fence.c' object='test_conformance-test-fence.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-fence.o `test -f 'test-fence.c' || echo '$(srcdir)/'`test-fence.c + +test_conformance-test-fence.obj: test-fence.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-fence.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-fence.Tpo -c -o test_conformance-test-fence.obj `if test -f 'test-fence.c'; then $(CYGPATH_W) 'test-fence.c'; else $(CYGPATH_W) '$(srcdir)/test-fence.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-fence.Tpo $(DEPDIR)/test_conformance-test-fence.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-fence.c' object='test_conformance-test-fence.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-fence.obj `if test -f 'test-fence.c'; then $(CYGPATH_W) 'test-fence.c'; else $(CYGPATH_W) '$(srcdir)/test-fence.c'; fi` + +test_conformance-test-path.o: test-path.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-path.o -MD -MP -MF $(DEPDIR)/test_conformance-test-path.Tpo -c -o test_conformance-test-path.o `test -f 'test-path.c' || echo '$(srcdir)/'`test-path.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-path.Tpo $(DEPDIR)/test_conformance-test-path.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-path.c' object='test_conformance-test-path.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-path.o `test -f 'test-path.c' || echo '$(srcdir)/'`test-path.c + +test_conformance-test-path.obj: test-path.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-path.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-path.Tpo -c -o test_conformance-test-path.obj `if test -f 'test-path.c'; then $(CYGPATH_W) 'test-path.c'; else $(CYGPATH_W) '$(srcdir)/test-path.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-path.Tpo $(DEPDIR)/test_conformance-test-path.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-path.c' object='test_conformance-test-path.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-path.obj `if test -f 'test-path.c'; then $(CYGPATH_W) 'test-path.c'; else $(CYGPATH_W) '$(srcdir)/test-path.c'; fi` + +test_conformance-test-path-clip.o: test-path-clip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-path-clip.o -MD -MP -MF $(DEPDIR)/test_conformance-test-path-clip.Tpo -c -o test_conformance-test-path-clip.o `test -f 'test-path-clip.c' || echo '$(srcdir)/'`test-path-clip.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-path-clip.Tpo $(DEPDIR)/test_conformance-test-path-clip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-path-clip.c' object='test_conformance-test-path-clip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-path-clip.o `test -f 'test-path-clip.c' || echo '$(srcdir)/'`test-path-clip.c + +test_conformance-test-path-clip.obj: test-path-clip.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -MT test_conformance-test-path-clip.obj -MD -MP -MF $(DEPDIR)/test_conformance-test-path-clip.Tpo -c -o test_conformance-test-path-clip.obj `if test -f 'test-path-clip.c'; then $(CYGPATH_W) 'test-path-clip.c'; else $(CYGPATH_W) '$(srcdir)/test-path-clip.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_conformance-test-path-clip.Tpo $(DEPDIR)/test_conformance-test-path-clip.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-path-clip.c' object='test_conformance-test-path-clip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_conformance_CFLAGS) $(CFLAGS) -c -o test_conformance-test-path-clip.obj `if test -f 'test-path-clip.c'; then $(CYGPATH_W) 'test-path-clip.c'; else $(CYGPATH_W) '$(srcdir)/test-path-clip.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-insttestDATA: $(insttest_DATA) + @$(NORMAL_INSTALL) + @list='$(insttest_DATA)'; test -n "$(insttestdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(insttestdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(insttestdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(insttestdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(insttestdir)" || exit $$?; \ + done + +uninstall-insttestDATA: + @$(NORMAL_UNINSTALL) + @list='$(insttest_DATA)'; test -n "$(insttestdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(insttestdir)'; $(am__uninstall_files_from_dir) +install-testmetaDATA: $(testmeta_DATA) + @$(NORMAL_INSTALL) + @list='$(testmeta_DATA)'; test -n "$(testmetadir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(testmetadir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(testmetadir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(testmetadir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(testmetadir)" || exit $$?; \ + done + +uninstall-testmetaDATA: + @$(NORMAL_UNINSTALL) + @list='$(testmeta_DATA)'; test -n "$(testmetadir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(testmetadir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(PROGRAMS) $(DATA) +installdirs: + for dir in "$(DESTDIR)$(insttestdir)" "$(DESTDIR)$(insttestdir)" "$(DESTDIR)$(testmetadir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-insttestPROGRAMS clean-libtool \ + clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-insttestDATA install-insttestPROGRAMS \ + install-testmetaDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-insttestDATA uninstall-insttestPROGRAMS \ + uninstall-testmetaDATA + +.MAKE: all check install install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-insttestPROGRAMS clean-libtool clean-noinstPROGRAMS \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-insttestDATA \ + install-insttestPROGRAMS install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + install-testmetaDATA installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-insttestDATA uninstall-insttestPROGRAMS \ + uninstall-testmetaDATA + +.PRECIOUS: Makefile + + +# For convenience, this provides a way to easily run individual unit tests: +.PHONY: wrappers clean-wrappers + +wrappers: stamp-test-conformance + @true +stamp-test-conformance: Makefile $(srcdir)/test-conform-main.c + @mkdir -p wrappers + @sed -n -e 's/^ \{1,\}ADD_TEST *( *\([a-zA-Z0-9_]\{1,\}\).*/\1/p' $(srcdir)/test-conform-main.c > unit-tests + @chmod +x $(top_srcdir)/tests/test-launcher.sh + @( echo "/stamp-test-conformance" ; \ + echo "/test-conformance$(EXEEXT)" ; \ + echo "*.o" ; \ + echo ".gitignore" ; \ + echo "unit-tests" ; ) > .gitignore + @for i in `cat unit-tests`; \ + do \ + unit=`basename $$i | sed -e s/_/-/g`; \ + echo " GEN $$unit"; \ + ( echo "#!/bin/sh" ; echo "$(top_srcdir)/tests/test-launcher.sh $(abs_builddir)/test-conformance$(EXEEXT) '' '$$i' \"\$$@\"" ) > $$unit$(SHEXT) ; \ + chmod +x $$unit$(SHEXT); \ + echo "/$$unit$(SHEXT)" >> .gitignore; \ + done \ + && echo timestamp > $(@F) + +clean-wrappers: + @for i in `cat unit-tests`; \ + do \ + unit=`basename $$i | sed -e s/_/-/g`; \ + echo " RM $$unit"; \ + rm -f $$unit$(SHEXT) ; \ + done \ + && rm -f unit-tests \ + && rm -f stamp-test-conformance + +.PHONY: test + +# we override the clean-generic target to clean up the wrappers so +# we cannot use CLEANFILES +clean-generic: clean-wrappers + $(QUIET_RM)rm -f .log + +@ENABLE_INSTALLED_TESTS_TRUE@conform.test: +@ENABLE_INSTALLED_TESTS_TRUE@ echo " GEN $@"; \ +@ENABLE_INSTALLED_TESTS_TRUE@ echo "[Test]" > $@.tmp; \ +@ENABLE_INSTALLED_TESTS_TRUE@ echo "Type=session" >> $@.tmp; \ +@ENABLE_INSTALLED_TESTS_TRUE@ echo "Exec=sh -c \"cd $(libexecdir)/installed-tests/mutter-cogl/conform; ../run-tests.sh ../config.env ./test-conformance\"" >> $@.tmp; \ +@ENABLE_INSTALLED_TESTS_TRUE@ mv $@.tmp $@ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cogl/tests/conform/test-alpha-test.c b/cogl/tests/conform/test-alpha-test.c new file mode 100644 index 0000000..e74f6d8 --- /dev/null +++ b/cogl/tests/conform/test-alpha-test.c @@ -0,0 +1,73 @@ +#include +#include + +#include "test-utils.h" + +static CoglTexture2D * +create_texture (CoglContext *context) +{ + static const uint8_t data[] = + { + 0xff, 0x00, 0x00, 0xff, + 0x00, 0xfa, 0x00, 0xfa + }; + + return cogl_texture_2d_new_from_data (context, + 2, 1, /* width/height */ + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + 4, /* rowstride */ + data, + NULL /* error */); +} + +void +test_alpha_test (void) +{ + CoglTexture *tex = create_texture (test_ctx); + CoglPipeline *pipeline = cogl_pipeline_new (test_ctx); + int fb_width = cogl_framebuffer_get_width (test_fb); + int fb_height = cogl_framebuffer_get_height (test_fb); + CoglColor clear_color; + + cogl_pipeline_set_layer_texture (pipeline, 0, tex); + cogl_pipeline_set_layer_filters (pipeline, 0, + COGL_PIPELINE_FILTER_NEAREST, + COGL_PIPELINE_FILTER_NEAREST); + cogl_pipeline_set_alpha_test_function (pipeline, + COGL_PIPELINE_ALPHA_FUNC_GEQUAL, + 254 / 255.0f /* alpha reference */); + + cogl_color_init_from_4ub (&clear_color, 0x00, 0x00, 0xff, 0xff); + cogl_framebuffer_clear (test_fb, + COGL_BUFFER_BIT_COLOR, + &clear_color); + + cogl_framebuffer_draw_rectangle (test_fb, + pipeline, + -1, -1, + 1, 1); + + cogl_object_unref (pipeline); + cogl_object_unref (tex); + + /* The left side of the framebuffer should use the first pixel from + * the texture which is red */ + test_utils_check_region (test_fb, + 2, 2, + fb_width / 2 - 4, + fb_height - 4, + 0xff0000ff); + /* The right side of the framebuffer should use the clear color + * because the second pixel from the texture is clipped from the + * alpha test */ + test_utils_check_region (test_fb, + fb_width / 2 + 2, + 2, + fb_width / 2 - 4, + fb_height - 4, + 0x0000ffff); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} + diff --git a/cogl/tests/conform/test-alpha-textures.c b/cogl/tests/conform/test-alpha-textures.c new file mode 100644 index 0000000..dccd30e --- /dev/null +++ b/cogl/tests/conform/test-alpha-textures.c @@ -0,0 +1,123 @@ +#include + +#include + +#include "test-utils.h" + +static void +create_pipeline (CoglTexture **tex_out, + CoglPipeline **pipeline_out) +{ + CoglTexture2D *tex; + CoglPipeline *pipeline; + static const uint8_t tex_data[] = + { 0x00, 0x44, 0x88, 0xcc }; + + tex = cogl_texture_2d_new_from_data (test_ctx, + 2, 2, /* width/height */ + COGL_PIXEL_FORMAT_A_8, /* format */ + 2, /* rowstride */ + tex_data, + NULL); + + pipeline = cogl_pipeline_new (test_ctx); + + cogl_pipeline_set_layer_filters (pipeline, + 0, /* layer */ + COGL_PIPELINE_FILTER_NEAREST, + COGL_PIPELINE_FILTER_NEAREST); + cogl_pipeline_set_layer_wrap_mode (pipeline, + 0, /* layer */ + COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); + + /* This is the layer combine used by cogl-pango */ + cogl_pipeline_set_layer_combine (pipeline, + 0, /* layer */ + "RGBA = MODULATE (PREVIOUS, TEXTURE[A])", + NULL); + + cogl_pipeline_set_layer_texture (pipeline, + 0, /* layer */ + tex); + + *pipeline_out = pipeline; + *tex_out = tex; +} + +void +test_alpha_textures (void) +{ + CoglTexture *tex1, *tex2; + CoglPipeline *pipeline1, *pipeline2; + int fb_width = cogl_framebuffer_get_width (test_fb); + int fb_height = cogl_framebuffer_get_height (test_fb); + uint8_t replacement_data[1] = { 0xff }; + + create_pipeline (&tex1, &pipeline1); + + cogl_framebuffer_draw_rectangle (test_fb, + pipeline1, + -1.0f, 1.0f, /* x1/y1 */ + 1.0f, 0.0f /* x2/y2 */); + + create_pipeline (&tex2, &pipeline2); + + cogl_texture_set_region (tex2, + 0, 0, /* src_x/y */ + 1, 1, /* dst_x/y */ + 1, 1, /* dst_width / dst_height */ + 1, 1, /* width / height */ + COGL_PIXEL_FORMAT_A_8, + 1, /* rowstride */ + replacement_data); + + cogl_framebuffer_draw_rectangle (test_fb, + pipeline2, + -1.0f, 0.0f, /* x1/y1 */ + 1.0f, -1.0f /* x2/y2 */); + + cogl_object_unref (tex1); + cogl_object_unref (tex2); + cogl_object_unref (pipeline1); + cogl_object_unref (pipeline2); + + /* Unmodified texture */ + test_utils_check_pixel (test_fb, + fb_width / 4, + fb_height / 8, + 0x000000ff); + test_utils_check_pixel (test_fb, + fb_width * 3 / 4, + fb_height / 8, + 0x444444ff); + test_utils_check_pixel (test_fb, + fb_width / 4, + fb_height * 3 / 8, + 0x888888ff); + test_utils_check_pixel (test_fb, + fb_width * 3 / 4, + fb_height * 3 / 8, + 0xccccccff); + + /* Modified texture */ + test_utils_check_pixel (test_fb, + fb_width / 4, + fb_height * 5 / 8, + 0x000000ff); + test_utils_check_pixel (test_fb, + fb_width * 3 / 4, + fb_height * 5 / 8, + 0x444444ff); + test_utils_check_pixel (test_fb, + fb_width / 4, + fb_height * 7 / 8, + 0x888888ff); + test_utils_check_pixel (test_fb, + fb_width * 3 / 4, + fb_height * 7 / 8, + 0xffffffff); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} + diff --git a/cogl/tests/conform/test-atlas-migration.c b/cogl/tests/conform/test-atlas-migration.c new file mode 100644 index 0000000..39e8a3c --- /dev/null +++ b/cogl/tests/conform/test-atlas-migration.c @@ -0,0 +1,145 @@ +#include + +#include "test-utils.h" + +#define N_TEXTURES 128 + +#define OPACITY_FOR_ROW(y) \ + (0xff - ((y) & 0xf) * 0x10) + +#define COLOR_FOR_SIZE(size) \ + (colors + (size) % 3) + +typedef struct +{ + uint8_t red, green, blue, alpha; +} TestColor; + +static const TestColor colors[] = + { { 0xff, 0x00, 0x00, 0xff }, + { 0x00, 0xff, 0x00, 0xff }, + { 0x00, 0x00, 0xff, 0xff } }; + +static CoglTexture * +create_texture (int size) +{ + CoglTexture *texture; + const TestColor *color; + uint8_t *data, *p; + int x, y; + + /* Create a red, green or blue texture depending on the size */ + color = COLOR_FOR_SIZE (size); + + p = data = g_malloc (size * size * 4); + + /* Fill the data with the color but fade the opacity out with + increasing y coordinates so that we can see the blending it the + atlas migration accidentally blends with garbage in the + texture */ + for (y = 0; y < size; y++) + { + int opacity = OPACITY_FOR_ROW (y); + + for (x = 0; x < size; x++) + { + /* Store the colors premultiplied */ + p[0] = color->red * opacity / 255; + p[1] = color->green * opacity / 255; + p[2] = color->blue * opacity / 255; + p[3] = opacity; + + p += 4; + } + } + + texture = test_utils_texture_new_from_data (test_ctx, + size, /* width */ + size, /* height */ + TEST_UTILS_TEXTURE_NONE, /* flags */ + /* format */ + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + /* rowstride */ + size * 4, + data); + + g_free (data); + + return texture; +} + +static void +verify_texture (CoglTexture *texture, int size) +{ + uint8_t *data, *p; + int x, y; + const TestColor *color; + + color = COLOR_FOR_SIZE (size); + + p = data = g_malloc (size * size * 4); + + cogl_texture_get_data (texture, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + size * 4, + data); + + for (y = 0; y < size; y++) + { + int opacity = OPACITY_FOR_ROW (y); + + for (x = 0; x < size; x++) + { + TestColor real_color = + { + color->red * opacity / 255, + color->green * opacity / 255, + color->blue * opacity / 255 + }; + + test_utils_compare_pixel (p, + (real_color.red << 24) | + (real_color.green << 16) | + (real_color.blue << 8) | + opacity); + g_assert_cmpint (p[3], ==, opacity); + + p += 4; + } + } + + g_free (data); +} + +void +test_atlas_migration (void) +{ + CoglTexture *textures[N_TEXTURES]; + int i, tex_num; + + /* Create and destroy all of the textures a few times to increase + the chances that we'll end up reusing the buffers for previously + discarded atlases */ + for (i = 0; i < 5; i++) + { + for (tex_num = 0; tex_num < N_TEXTURES; tex_num++) + textures[tex_num] = create_texture (tex_num + 1); + for (tex_num = 0; tex_num < N_TEXTURES; tex_num++) + cogl_object_unref (textures[tex_num]); + } + + /* Create all the textures again */ + for (tex_num = 0; tex_num < N_TEXTURES; tex_num++) + textures[tex_num] = create_texture (tex_num + 1); + + /* Verify that they all still have the right data */ + for (tex_num = 0; tex_num < N_TEXTURES; tex_num++) + verify_texture (textures[tex_num], tex_num + 1); + + /* Destroy them all */ + for (tex_num = 0; tex_num < N_TEXTURES; tex_num++) + cogl_object_unref (textures[tex_num]); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} diff --git a/cogl/tests/conform/test-backface-culling.c b/cogl/tests/conform/test-backface-culling.c new file mode 100644 index 0000000..e90c2f5 --- /dev/null +++ b/cogl/tests/conform/test-backface-culling.c @@ -0,0 +1,311 @@ +#define COGL_VERSION_MIN_REQUIRED COGL_VERSION_1_0 + +#include + +#include + +#include "test-utils.h" + +/* Size the texture so that it is just off a power of two to encourage + it so use software tiling when NPOTs aren't available */ +#define TEXTURE_SIZE 257 + +/* Amount of pixels to skip off the top, bottom, left and right of the + texture when reading back the stage */ +#define TEST_INSET 2 + +/* Size to actually render the texture at */ +#define TEXTURE_RENDER_SIZE 8 + +typedef struct _TestState +{ + CoglTexture *texture; + CoglFramebuffer *offscreen; + CoglTexture *offscreen_tex; + int width, height; +} TestState; + +static void +validate_part (CoglFramebuffer *framebuffer, + int xnum, int ynum, CoglBool shown) +{ + test_utils_check_region (framebuffer, + xnum * TEXTURE_RENDER_SIZE + TEST_INSET, + ynum * TEXTURE_RENDER_SIZE + TEST_INSET, + TEXTURE_RENDER_SIZE - TEST_INSET * 2, + TEXTURE_RENDER_SIZE - TEST_INSET * 2, + shown ? 0xff0000ff : 0x000000ff); +} + +/* We draw everything 16 times. The draw number is used as a bitmask + to test all of the combinations of enabling legacy state, both + winding orders and all four culling modes */ + +#define USE_LEGACY_STATE(draw_num) (((draw_num) & 0x01) >> 0) +#define FRONT_WINDING(draw_num) (((draw_num) & 0x02) >> 1) +#define CULL_FACE_MODE(draw_num) (((draw_num) & 0x0c) >> 2) + +static void +paint_test_backface_culling (TestState *state, + CoglFramebuffer *framebuffer) +{ + int draw_num; + CoglPipeline *base_pipeline = cogl_pipeline_new (test_ctx); + + cogl_framebuffer_orthographic (framebuffer, + 0, 0, + state->width, + state->height, + -1, + 100); + + cogl_framebuffer_clear4f (framebuffer, + COGL_BUFFER_BIT_COLOR | COGL_BUFFER_BIT_STENCIL, + 0, 0, 0, 1); + + cogl_pipeline_set_layer_texture (base_pipeline, 0, state->texture); + + cogl_pipeline_set_layer_filters (base_pipeline, 0, + COGL_PIPELINE_FILTER_NEAREST, + COGL_PIPELINE_FILTER_NEAREST); + + cogl_push_framebuffer (framebuffer); + + /* Render the scene sixteen times to test all of the combinations of + cull face mode, legacy state and winding orders */ + for (draw_num = 0; draw_num < 16; draw_num++) + { + float x1 = 0, x2, y1 = 0, y2 = (float)(TEXTURE_RENDER_SIZE); + CoglTextureVertex verts[4]; + CoglPipeline *pipeline; + + cogl_push_matrix (); + cogl_translate (0, TEXTURE_RENDER_SIZE * draw_num, 0); + + pipeline = cogl_pipeline_copy (base_pipeline); + + cogl_set_backface_culling_enabled (USE_LEGACY_STATE (draw_num)); + cogl_pipeline_set_front_face_winding (pipeline, FRONT_WINDING (draw_num)); + cogl_pipeline_set_cull_face_mode (pipeline, CULL_FACE_MODE (draw_num)); + + cogl_push_source (pipeline); + + memset (verts, 0, sizeof (verts)); + + x2 = x1 + (float)(TEXTURE_RENDER_SIZE); + + /* Draw a front-facing texture */ + cogl_rectangle (x1, y1, x2, y2); + + x1 = x2; + x2 = x1 + (float)(TEXTURE_RENDER_SIZE); + + /* Draw a front-facing texture with flipped texcoords */ + cogl_rectangle_with_texture_coords (x1, y1, x2, y2, + 1.0, 0.0, 0.0, 1.0); + + x1 = x2; + x2 = x1 + (float)(TEXTURE_RENDER_SIZE); + + /* Draw a back-facing texture */ + cogl_rectangle (x2, y1, x1, y2); + + x1 = x2; + x2 = x1 + (float)(TEXTURE_RENDER_SIZE); + + /* If the texture is sliced then cogl_polygon doesn't work so + we'll just use a solid color instead */ + if (cogl_texture_is_sliced (state->texture)) + cogl_set_source_color4ub (255, 0, 0, 255); + + /* Draw a front-facing polygon */ + verts[0].x = x1; verts[0].y = y2; + verts[1].x = x2; verts[1].y = y2; + verts[2].x = x2; verts[2].y = y1; + verts[3].x = x1; verts[3].y = y1; + verts[0].tx = 0; verts[0].ty = 0; + verts[1].tx = 1.0; verts[1].ty = 0; + verts[2].tx = 1.0; verts[2].ty = 1.0; + verts[3].tx = 0; verts[3].ty = 1.0; + cogl_polygon (verts, 4, FALSE); + + x1 = x2; + x2 = x1 + (float)(TEXTURE_RENDER_SIZE); + + /* Draw a back-facing polygon */ + verts[0].x = x1; verts[0].y = y1; + verts[1].x = x2; verts[1].y = y1; + verts[2].x = x2; verts[2].y = y2; + verts[3].x = x1; verts[3].y = y2; + verts[0].tx = 0; verts[0].ty = 0; + verts[1].tx = 1.0; verts[1].ty = 0; + verts[2].tx = 1.0; verts[2].ty = 1.0; + verts[3].tx = 0; verts[3].ty = 1.0; + cogl_polygon (verts, 4, FALSE); + + x1 = x2; + x2 = x1 + (float)(TEXTURE_RENDER_SIZE); + + cogl_pop_matrix (); + + cogl_pop_source (); + cogl_object_unref (pipeline); + } + + cogl_pop_framebuffer (); + + cogl_object_unref (base_pipeline); +} + +static void +validate_result (CoglFramebuffer *framebuffer, int y_offset) +{ + int draw_num; + + for (draw_num = 0; draw_num < 16; draw_num++) + { + CoglBool cull_front, cull_back; + CoglPipelineCullFaceMode cull_mode; + + if (USE_LEGACY_STATE (draw_num)) + cull_mode = COGL_PIPELINE_CULL_FACE_MODE_BACK; + else + cull_mode = CULL_FACE_MODE (draw_num); + + switch (cull_mode) + { + case COGL_PIPELINE_CULL_FACE_MODE_NONE: + cull_front = FALSE; + cull_back = FALSE; + break; + + case COGL_PIPELINE_CULL_FACE_MODE_FRONT: + cull_front = TRUE; + cull_back = FALSE; + break; + + case COGL_PIPELINE_CULL_FACE_MODE_BACK: + cull_front = FALSE; + cull_back = TRUE; + break; + + case COGL_PIPELINE_CULL_FACE_MODE_BOTH: + cull_front = TRUE; + cull_back = TRUE; + break; + } + + if (FRONT_WINDING (draw_num) == COGL_WINDING_CLOCKWISE) + { + CoglBool tmp = cull_front; + cull_front = cull_back; + cull_back = tmp; + } + + /* Front-facing texture */ + validate_part (framebuffer, + 0, y_offset + draw_num, !cull_front); + /* Front-facing texture with flipped tex coords */ + validate_part (framebuffer, + 1, y_offset + draw_num, !cull_front); + /* Back-facing texture */ + validate_part (framebuffer, + 2, y_offset + draw_num, !cull_back); + /* Front-facing texture polygon */ + validate_part (framebuffer, + 3, y_offset + draw_num, !cull_front); + /* Back-facing texture polygon */ + validate_part (framebuffer, + 4, y_offset + draw_num, !cull_back); + } +} + +static void +paint (TestState *state) +{ + CoglPipeline *pipeline; + + paint_test_backface_culling (state, test_fb); + + /* + * Now repeat the test but rendered to an offscreen + * framebuffer. Note that by default the conformance tests are + * always run to an offscreen buffer but we might as well have this + * check anyway in case it is being run with COGL_TEST_ONSCREEN=1 + */ + paint_test_backface_culling (state, state->offscreen); + + /* Copy the result of the offscreen rendering for validation and + * also so we can have visual feedback. */ + pipeline = cogl_pipeline_new (test_ctx); + cogl_pipeline_set_layer_texture (pipeline, 0, state->offscreen_tex); + cogl_framebuffer_draw_rectangle (test_fb, + pipeline, + 0, TEXTURE_RENDER_SIZE * 16, + state->width, + state->height + TEXTURE_RENDER_SIZE * 16); + cogl_object_unref (pipeline); + + validate_result (test_fb, 0); + validate_result (test_fb, 16); +} + +static CoglTexture * +make_texture (void) +{ + guchar *tex_data, *p; + CoglTexture *tex; + + tex_data = g_malloc (TEXTURE_SIZE * TEXTURE_SIZE * 4); + + for (p = tex_data + TEXTURE_SIZE * TEXTURE_SIZE * 4; p > tex_data;) + { + *(--p) = 255; + *(--p) = 0; + *(--p) = 0; + *(--p) = 255; + } + + tex = test_utils_texture_new_from_data (test_ctx, + TEXTURE_SIZE, + TEXTURE_SIZE, + TEST_UTILS_TEXTURE_NO_ATLAS, + COGL_PIXEL_FORMAT_RGBA_8888, + TEXTURE_SIZE * 4, + tex_data); + + g_free (tex_data); + + return tex; +} + +void +test_backface_culling (void) +{ + TestState state; + CoglTexture *tex; + + state.width = cogl_framebuffer_get_width (test_fb); + state.height = cogl_framebuffer_get_height (test_fb); + + state.offscreen = NULL; + + state.texture = make_texture (); + + tex = test_utils_texture_new_with_size (test_ctx, + state.width, state.height, + TEST_UTILS_TEXTURE_NO_SLICING, + COGL_TEXTURE_COMPONENTS_RGBA); + state.offscreen = cogl_offscreen_new_with_texture (tex); + state.offscreen_tex = tex; + + paint (&state); + + cogl_object_unref (state.offscreen); + cogl_object_unref (state.offscreen_tex); + cogl_object_unref (state.texture); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} + diff --git a/cogl/tests/conform/test-blend-strings.c b/cogl/tests/conform/test-blend-strings.c new file mode 100644 index 0000000..f49c860 --- /dev/null +++ b/cogl/tests/conform/test-blend-strings.c @@ -0,0 +1,430 @@ +#include + +#include + +#include "test-utils.h" + +#define QUAD_WIDTH 20 + +#define RED 0 +#define GREEN 1 +#define BLUE 2 +#define ALPHA 3 + +#define MASK_RED(COLOR) ((COLOR & 0xff000000) >> 24) +#define MASK_GREEN(COLOR) ((COLOR & 0xff0000) >> 16) +#define MASK_BLUE(COLOR) ((COLOR & 0xff00) >> 8) +#define MASK_ALPHA(COLOR) (COLOR & 0xff) + +#define BLEND_CONSTANT_UNUSED 0xDEADBEEF +#define TEX_CONSTANT_UNUSED 0xDEADBEEF + +typedef struct _TestState +{ + CoglContext *ctx; +} TestState; + + +static void +test_blend (TestState *state, + int x, + int y, + uint32_t src_color, + uint32_t dst_color, + const char *blend_string, + uint32_t blend_constant, + uint32_t expected_result) +{ + /* src color */ + uint8_t Sr = MASK_RED (src_color); + uint8_t Sg = MASK_GREEN (src_color); + uint8_t Sb = MASK_BLUE (src_color); + uint8_t Sa = MASK_ALPHA (src_color); + /* dest color */ + uint8_t Dr = MASK_RED (dst_color); + uint8_t Dg = MASK_GREEN (dst_color); + uint8_t Db = MASK_BLUE (dst_color); + uint8_t Da = MASK_ALPHA (dst_color); + /* blend constant - when applicable */ + uint8_t Br = MASK_RED (blend_constant); + uint8_t Bg = MASK_GREEN (blend_constant); + uint8_t Bb = MASK_BLUE (blend_constant); + uint8_t Ba = MASK_ALPHA (blend_constant); + CoglColor blend_const_color; + + CoglHandle material; + CoglPipeline *pipeline; + CoglBool status; + CoglError *error = NULL; + int y_off; + int x_off; + + /* First write out the destination color without any blending... */ + pipeline = cogl_pipeline_new (test_ctx); + cogl_pipeline_set_color4ub (pipeline, Dr, Dg, Db, Da); + cogl_pipeline_set_blend (pipeline, "RGBA = ADD (SRC_COLOR, 0)", NULL); + cogl_set_source (pipeline); + cogl_rectangle (x * QUAD_WIDTH, + y * QUAD_WIDTH, + x * QUAD_WIDTH + QUAD_WIDTH, + y * QUAD_WIDTH + QUAD_WIDTH); + cogl_object_unref (pipeline); + + /* + * Now blend a rectangle over our well defined destination: + */ + + pipeline = cogl_pipeline_new (test_ctx); + cogl_pipeline_set_color4ub (pipeline, Sr, Sg, Sb, Sa); + + status = cogl_pipeline_set_blend (pipeline, blend_string, &error); + if (!status) + { + /* It's not strictly a test failure; you need a more capable GPU or + * driver to test this blend string. */ + if (cogl_test_verbose ()) + { + g_debug ("Failed to test blend string %s: %s", + blend_string, error->message); + g_print ("Skipping\n"); + } + return; + } + + cogl_color_init_from_4ub (&blend_const_color, Br, Bg, Bb, Ba); + cogl_pipeline_set_blend_constant (pipeline, &blend_const_color); + + cogl_set_source (pipeline); + cogl_rectangle (x * QUAD_WIDTH, + y * QUAD_WIDTH, + x * QUAD_WIDTH + QUAD_WIDTH, + y * QUAD_WIDTH + QUAD_WIDTH); + cogl_object_unref (pipeline); + + /* See what we got... */ + + y_off = y * QUAD_WIDTH + (QUAD_WIDTH / 2); + x_off = x * QUAD_WIDTH + (QUAD_WIDTH / 2); + + if (cogl_test_verbose ()) + { + g_print ("test_blend (%d, %d):\n%s\n", x, y, blend_string); + g_print (" src color = %02x, %02x, %02x, %02x\n", Sr, Sg, Sb, Sa); + g_print (" dst color = %02x, %02x, %02x, %02x\n", Dr, Dg, Db, Da); + if (blend_constant != BLEND_CONSTANT_UNUSED) + g_print (" blend constant = %02x, %02x, %02x, %02x\n", + Br, Bg, Bb, Ba); + else + g_print (" blend constant = UNUSED\n"); + } + + test_utils_check_pixel (test_fb, x_off, y_off, expected_result); + + + /* + * Test with legacy API + */ + + /* Clear previous work */ + cogl_set_source_color4ub (0, 0, 0, 0xff); + cogl_rectangle (x * QUAD_WIDTH, + y * QUAD_WIDTH, + x * QUAD_WIDTH + QUAD_WIDTH, + y * QUAD_WIDTH + QUAD_WIDTH); + + /* First write out the destination color without any blending... */ + material = cogl_material_new (); + cogl_material_set_color4ub (material, Dr, Dg, Db, Da); + cogl_material_set_blend (material, "RGBA = ADD (SRC_COLOR, 0)", NULL); + cogl_set_source (material); + cogl_rectangle (x * QUAD_WIDTH, + y * QUAD_WIDTH, + x * QUAD_WIDTH + QUAD_WIDTH, + y * QUAD_WIDTH + QUAD_WIDTH); + cogl_handle_unref (material); + + /* + * Now blend a rectangle over our well defined destination: + */ + + material = cogl_material_new (); + cogl_material_set_color4ub (material, Sr, Sg, Sb, Sa); + + status = cogl_material_set_blend (material, blend_string, &error); + if (!status) + { + /* This is a failure as it must be equivalent to the new API */ + g_warning ("Error setting blend string %s: %s", + blend_string, error->message); + g_assert_not_reached (); + } + + cogl_color_init_from_4ub (&blend_const_color, Br, Bg, Bb, Ba); + cogl_material_set_blend_constant (material, &blend_const_color); + + cogl_set_source (material); + cogl_rectangle (x * QUAD_WIDTH, + y * QUAD_WIDTH, + x * QUAD_WIDTH + QUAD_WIDTH, + y * QUAD_WIDTH + QUAD_WIDTH); + cogl_handle_unref (material); + + /* See what we got... */ + + test_utils_check_pixel (test_fb, x_off, y_off, expected_result); +} + +static CoglTexture * +make_texture (uint32_t color) +{ + guchar *tex_data, *p; + uint8_t r = MASK_RED (color); + uint8_t g = MASK_GREEN (color); + uint8_t b = MASK_BLUE (color); + uint8_t a = MASK_ALPHA (color); + CoglTexture *tex; + + tex_data = g_malloc (QUAD_WIDTH * QUAD_WIDTH * 4); + + for (p = tex_data + QUAD_WIDTH * QUAD_WIDTH * 4; p > tex_data;) + { + *(--p) = a; + *(--p) = b; + *(--p) = g; + *(--p) = r; + } + + /* Note: we claim that the data is premultiplied so that Cogl won't + * premultiply the data on upload */ + tex = test_utils_texture_new_from_data (test_ctx, + QUAD_WIDTH, + QUAD_WIDTH, + TEST_UTILS_TEXTURE_NONE, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + QUAD_WIDTH * 4, + tex_data); + + g_free (tex_data); + + return tex; +} + +static void +test_tex_combine (TestState *state, + int x, + int y, + uint32_t tex0_color, + uint32_t tex1_color, + uint32_t combine_constant, + const char *combine_string, + uint32_t expected_result) +{ + CoglTexture *tex0, *tex1; + + /* combine constant - when applicable */ + uint8_t Cr = MASK_RED (combine_constant); + uint8_t Cg = MASK_GREEN (combine_constant); + uint8_t Cb = MASK_BLUE (combine_constant); + uint8_t Ca = MASK_ALPHA (combine_constant); + CoglColor combine_const_color; + + CoglHandle material; + CoglBool status; + CoglError *error = NULL; + int y_off; + int x_off; + + + tex0 = make_texture (tex0_color); + tex1 = make_texture (tex1_color); + + material = cogl_material_new (); + + cogl_material_set_color4ub (material, 0x80, 0x80, 0x80, 0x80); + cogl_material_set_blend (material, "RGBA = ADD (SRC_COLOR, 0)", NULL); + + cogl_material_set_layer (material, 0, tex0); + cogl_material_set_layer_combine (material, 0, + "RGBA = REPLACE (TEXTURE)", NULL); + + cogl_material_set_layer (material, 1, tex1); + status = cogl_material_set_layer_combine (material, 1, + combine_string, &error); + if (!status) + { + /* It's not strictly a test failure; you need a more capable GPU or + * driver to test this texture combine string. */ + g_debug ("Failed to test texture combine string %s: %s", + combine_string, error->message); + } + + cogl_color_init_from_4ub (&combine_const_color, Cr, Cg, Cb, Ca); + cogl_material_set_layer_combine_constant (material, 1, &combine_const_color); + + cogl_set_source (material); + cogl_rectangle (x * QUAD_WIDTH, + y * QUAD_WIDTH, + x * QUAD_WIDTH + QUAD_WIDTH, + y * QUAD_WIDTH + QUAD_WIDTH); + + cogl_handle_unref (material); + cogl_object_unref (tex0); + cogl_object_unref (tex1); + + /* See what we got... */ + + y_off = y * QUAD_WIDTH + (QUAD_WIDTH / 2); + x_off = x * QUAD_WIDTH + (QUAD_WIDTH / 2); + + if (cogl_test_verbose ()) + { + g_print ("test_tex_combine (%d, %d):\n%s\n", x, y, combine_string); + g_print (" texture 0 color = 0x%08lX\n", (unsigned long)tex0_color); + g_print (" texture 1 color = 0x%08lX\n", (unsigned long)tex1_color); + if (combine_constant != TEX_CONSTANT_UNUSED) + g_print (" combine constant = %02x, %02x, %02x, %02x\n", + Cr, Cg, Cb, Ca); + else + g_print (" combine constant = UNUSED\n"); + } + + test_utils_check_pixel (test_fb, x_off, y_off, expected_result); +} + +static void +paint (TestState *state) +{ + test_blend (state, 0, 0, /* position */ + 0xff0000ff, /* src */ + 0xffffffff, /* dst */ + "RGBA = ADD (SRC_COLOR, 0)", + BLEND_CONSTANT_UNUSED, + 0xff0000ff); /* expected */ + + test_blend (state, 1, 0, /* position */ + 0x11223344, /* src */ + 0x11223344, /* dst */ + "RGBA = ADD (SRC_COLOR, DST_COLOR)", + BLEND_CONSTANT_UNUSED, + 0x22446688); /* expected */ + + test_blend (state, 2, 0, /* position */ + 0x80808080, /* src */ + 0xffffffff, /* dst */ + "RGBA = ADD (SRC_COLOR * (CONSTANT), 0)", + 0x80808080, /* constant (RGBA all = 0.5 when normalized) */ + 0x40404040); /* expected */ + + test_blend (state, 3, 0, /* position */ + 0x80000080, /* src (alpha = 0.5 when normalized) */ + 0x40000000, /* dst */ + "RGBA = ADD (SRC_COLOR * (SRC_COLOR[A])," + " DST_COLOR * (1-SRC_COLOR[A]))", + BLEND_CONSTANT_UNUSED, + 0x60000040); /* expected */ + + /* XXX: + * For all texture combine tests tex0 will use a combine mode of + * "RGBA = REPLACE (TEXTURE)" + */ + + test_tex_combine (state, 4, 0, /* position */ + 0x11111111, /* texture 0 color */ + 0x22222222, /* texture 1 color */ + TEX_CONSTANT_UNUSED, + "RGBA = ADD (PREVIOUS, TEXTURE)", /* tex combine */ + 0x33333333); /* expected */ + + test_tex_combine (state, 5, 0, /* position */ + 0x40404040, /* texture 0 color */ + 0x80808080, /* texture 1 color (RGBA all = 0.5) */ + TEX_CONSTANT_UNUSED, + "RGBA = MODULATE (PREVIOUS, TEXTURE)", /* tex combine */ + 0x20202020); /* expected */ + + test_tex_combine (state, 6, 0, /* position */ + 0xffffff80, /* texture 0 color (alpha = 0.5) */ + 0xDEADBE40, /* texture 1 color */ + TEX_CONSTANT_UNUSED, + "RGB = REPLACE (PREVIOUS)" + "A = MODULATE (PREVIOUS, TEXTURE)", /* tex combine */ + 0xffffff20); /* expected */ + + /* XXX: we are assuming test_tex_combine creates a material with + * a color of 0x80808080 (i.e. the "PRIMARY" color) */ + test_tex_combine (state, 7, 0, /* position */ + 0xffffff80, /* texture 0 color (alpha = 0.5) */ + 0xDEADBE20, /* texture 1 color */ + TEX_CONSTANT_UNUSED, + "RGB = REPLACE (PREVIOUS)" + "A = MODULATE (PRIMARY, TEXTURE)", /* tex combine */ + 0xffffff10); /* expected */ + + test_tex_combine (state, 8, 0, /* position */ + 0x11111111, /* texture 0 color */ + 0x22222222, /* texture 1 color */ + TEX_CONSTANT_UNUSED, + "RGBA = ADD (PREVIOUS, 1-TEXTURE)", /* tex combine */ + 0xeeeeeeee); /* expected */ + + /* this is again assuming a primary color of 0x80808080 */ + test_tex_combine (state, 9, 0, /* position */ + 0x10101010, /* texture 0 color */ + 0x20202020, /* texture 1 color */ + TEX_CONSTANT_UNUSED, + "RGBA = INTERPOLATE (PREVIOUS, TEXTURE, PRIMARY)", + 0x18181818); /* expected */ + +#if 0 /* using TEXTURE_N appears to be broken in cogl-blend-string.c */ + test_tex_combine (state, 0, 1, /* position */ + 0xDEADBEEF, /* texture 0 color (not used) */ + 0x11223344, /* texture 1 color */ + TEX_CONSTANT_UNUSED, + "RGBA = ADD (TEXTURE_1, TEXTURE)", /* tex combine */ + 0x22446688); /* expected */ +#endif + + test_tex_combine (state, 1, 1, /* position */ + 0x21314151, /* texture 0 color */ + 0x99999999, /* texture 1 color */ + TEX_CONSTANT_UNUSED, + "RGBA = ADD_SIGNED (PREVIOUS, TEXTURE)", /* tex combine */ + 0x3a4a5a6a); /* expected */ + + test_tex_combine (state, 2, 1, /* position */ + 0xfedcba98, /* texture 0 color */ + 0x11111111, /* texture 1 color */ + TEX_CONSTANT_UNUSED, + "RGBA = SUBTRACT (PREVIOUS, TEXTURE)", /* tex combine */ + 0xedcba987); /* expected */ + + test_tex_combine (state, 3, 1, /* position */ + 0x8899aabb, /* texture 0 color */ + 0xbbaa9988, /* texture 1 color */ + TEX_CONSTANT_UNUSED, + "RGB = DOT3_RGBA (PREVIOUS, TEXTURE)" + "A = REPLACE (PREVIOUS)", + 0x2a2a2abb); /* expected */ +} + +void +test_blend_strings (void) +{ + TestState state; + + cogl_framebuffer_orthographic (test_fb, 0, 0, + cogl_framebuffer_get_width (test_fb), + cogl_framebuffer_get_height (test_fb), + -1, + 100); + + /* XXX: we have to push/pop a framebuffer since this test currently + * uses the legacy cogl_rectangle() api. */ + cogl_push_framebuffer (test_fb); + paint (&state); + cogl_pop_framebuffer (); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} + diff --git a/cogl/tests/conform/test-blend.c b/cogl/tests/conform/test-blend.c new file mode 100644 index 0000000..3c6235b --- /dev/null +++ b/cogl/tests/conform/test-blend.c @@ -0,0 +1,64 @@ +#include + +#include + +#include "test-utils.h" + +static void +paint (void) +{ + CoglPipeline *pipeline = cogl_pipeline_new (test_ctx); + int width = cogl_framebuffer_get_width (test_fb); + int half_width = width / 2; + int height = cogl_framebuffer_get_height (test_fb); + CoglVertexP2 tri0_vertices[] = { + { 0, 0 }, + { 0, height }, + { half_width, height }, + }; + CoglVertexP2C4 tri1_vertices[] = { + { half_width, 0, 0x80, 0x80, 0x80, 0x80 }, + { half_width, height, 0x80, 0x80, 0x80, 0x80 }, + { width, height, 0x80, 0x80, 0x80, 0x80 }, + }; + CoglPrimitive *tri0; + CoglPrimitive *tri1; + + cogl_framebuffer_clear4f (test_fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 0); + + tri0 = cogl_primitive_new_p2 (test_ctx, COGL_VERTICES_MODE_TRIANGLES, + 3, tri0_vertices); + tri1 = cogl_primitive_new_p2c4 (test_ctx, COGL_VERTICES_MODE_TRIANGLES, + 3, tri1_vertices); + + /* Check that cogl correctly handles the case where we draw + * different primitives same pipeline and switch from using the + * opaque color associated with the pipeline and using a colour + * attribute with an alpha component which implies blending is + * required. + * + * If Cogl gets this wrong then then in all likelyhood the second + * primitive will be drawn with blending still disabled. + */ + + cogl_primitive_draw (tri0, test_fb, pipeline); + cogl_primitive_draw (tri1, test_fb, pipeline); + + test_utils_check_pixel_and_alpha (test_fb, + half_width + 5, + height - 5, + 0x80808080); +} + +void +test_blend (void) +{ + cogl_framebuffer_orthographic (test_fb, 0, 0, + cogl_framebuffer_get_width (test_fb), + cogl_framebuffer_get_height (test_fb), + -1, + 100); + + paint (); +} + diff --git a/cogl/tests/conform/test-color-hsl.c b/cogl/tests/conform/test-color-hsl.c new file mode 100644 index 0000000..651ce52 --- /dev/null +++ b/cogl/tests/conform/test-color-hsl.c @@ -0,0 +1,45 @@ +#include +#include + +#include + +#include "test-utils.h" + +#define cogl_assert_float(a, b) \ + do { \ + if (fabsf ((a) - (b)) >= 0.0001f) \ + g_assert_cmpfloat ((a), ==, (b)); \ + } while (0) + +void +test_color_hsl (void) +{ + CoglColor color; + float hue, saturation, luminance; + + cogl_color_init_from_4ub(&color, 108, 198, 78, 255); + cogl_color_to_hsl(&color, &hue, &saturation, &luminance); + + cogl_assert_float(hue, 105.f); + cogl_assert_float(saturation, 0.512821); + cogl_assert_float(luminance, 0.541176); + + memset(&color, 0, sizeof (CoglColor)); + cogl_color_init_from_hsl(&color, hue, saturation, luminance); + + g_assert_cmpint (cogl_color_get_red_byte (&color), ==, 108); + g_assert_cmpint (cogl_color_get_green_byte (&color), ==, 198); + g_assert_cmpint (cogl_color_get_blue_byte (&color), ==, 78); + g_assert_cmpint (cogl_color_get_alpha_byte (&color), ==, 255); + + memset(&color, 0, sizeof (CoglColor)); + cogl_color_init_from_hsl(&color, hue, 0, luminance); + + cogl_assert_float (cogl_color_get_red_float (&color), luminance); + cogl_assert_float (cogl_color_get_green_float (&color), luminance); + cogl_assert_float (cogl_color_get_blue_float (&color), luminance); + cogl_assert_float (cogl_color_get_alpha_float (&color), 1.0f); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} diff --git a/cogl/tests/conform/test-color-mask.c b/cogl/tests/conform/test-color-mask.c new file mode 100644 index 0000000..e80f46d --- /dev/null +++ b/cogl/tests/conform/test-color-mask.c @@ -0,0 +1,110 @@ +#include + +#include "test-utils.h" + +#define TEX_SIZE 128 + +#define NUM_FBOS 3 + +typedef struct _TestState +{ + int width; + int height; + + CoglTexture *tex[NUM_FBOS]; + CoglFramebuffer *fbo[NUM_FBOS]; +} TestState; + +static void +paint (TestState *state) +{ + CoglColor bg; + int i; + + cogl_set_source_color4ub (255, 255, 255, 255); + + /* We push the third framebuffer first so that later we can switch + back to it by popping to test that that works */ + cogl_push_framebuffer (state->fbo[2]); + + cogl_push_framebuffer (state->fbo[0]); + cogl_rectangle (-1.0, -1.0, 1.0, 1.0); + cogl_pop_framebuffer (); + + cogl_push_framebuffer (state->fbo[1]); + cogl_rectangle (-1.0, -1.0, 1.0, 1.0); + cogl_pop_framebuffer (); + + /* We should now be back on the third framebuffer */ + cogl_rectangle (-1.0, -1.0, 1.0, 1.0); + cogl_pop_framebuffer (); + + cogl_color_init_from_4ub (&bg, 128, 128, 128, 255); + cogl_clear (&bg, COGL_BUFFER_BIT_COLOR | COGL_BUFFER_BIT_DEPTH); + + /* Render all of the textures to the screen */ + for (i = 0; i < NUM_FBOS; i++) + { + CoglPipeline *pipeline = cogl_pipeline_new (test_ctx); + cogl_pipeline_set_layer_texture (pipeline, 0, state->tex[i]); + cogl_framebuffer_draw_rectangle (test_fb, pipeline, + 2.0f / NUM_FBOS * i - 1.0f, -1.0f, + 2.0f / NUM_FBOS * (i + 1) - 1.0f, 1.0f); + cogl_object_unref (pipeline); + } + + /* Verify all of the fbos drew the right color */ + for (i = 0; i < NUM_FBOS; i++) + { + uint8_t expected_colors[NUM_FBOS][4] = + { { 0xff, 0x00, 0x00, 0xff }, + { 0x00, 0xff, 0x00, 0xff }, + { 0x00, 0x00, 0xff, 0xff } }; + + test_utils_check_pixel_rgb (test_fb, + state->width * (i + 0.5f) / NUM_FBOS, + state->height / 2, + expected_colors[i][0], + expected_colors[i][1], + expected_colors[i][2]); + } +} + +void +test_color_mask (void) +{ + TestState state; + int i; + + state.width = cogl_framebuffer_get_width (test_fb); + state.height = cogl_framebuffer_get_height (test_fb); + + for (i = 0; i < NUM_FBOS; i++) + { + state.tex[i] = test_utils_texture_new_with_size (test_ctx, 128, 128, + TEST_UTILS_TEXTURE_NO_ATLAS, + COGL_TEXTURE_COMPONENTS_RGB); + + + state.fbo[i] = cogl_offscreen_new_with_texture (state.tex[i]); + + /* Clear the texture color bits */ + cogl_framebuffer_clear4f (state.fbo[i], + COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1); + + cogl_framebuffer_set_color_mask (state.fbo[i], + i == 0 ? COGL_COLOR_MASK_RED : + i == 1 ? COGL_COLOR_MASK_GREEN : + COGL_COLOR_MASK_BLUE); + } + + /* XXX: we have to push/pop a framebuffer since this test currently + * uses the legacy cogl_rectangle() api. */ + cogl_push_framebuffer (test_fb); + paint (&state); + cogl_pop_framebuffer (); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} + diff --git a/cogl/tests/conform/test-conform-main.c b/cogl/tests/conform/test-conform-main.c new file mode 100644 index 0000000..64fdfba --- /dev/null +++ b/cogl/tests/conform/test-conform-main.c @@ -0,0 +1,157 @@ +#include "cogl-config.h" + +#include + +#include +#include +#include +#include + +#include "test-utils.h" + +/* A bit of sugar for adding new conformance tests */ +#define ADD_TEST(FUNC, REQUIREMENTS, KNOWN_FAIL_REQUIREMENTS) \ + G_STMT_START { \ + extern void FUNC (void); \ + if (strcmp (#FUNC, argv[1]) == 0) \ + { \ + test_utils_init (REQUIREMENTS, KNOWN_FAIL_REQUIREMENTS); \ + FUNC (); \ + test_utils_fini (); \ + exit (0); \ + } \ + } G_STMT_END + +#define UNPORTED_TEST(FUNC) + +int +main (int argc, char **argv) +{ + int i; + + if (argc != 2) + { + g_printerr ("usage %s UNIT_TEST\n", argv[0]); + exit (1); + } + + /* Just for convenience in case people try passing the wrapper + * filenames for the UNIT_TEST argument we normalize '-' characters + * to '_' characters... */ + for (i = 0; argv[1][i]; i++) + { + if (argv[1][i] == '-') + argv[1][i] = '_'; + } + + /* This file is run through a sed script during the make step so the + * lines containing the tests need to be formatted on a single line + * each. + */ + + UNPORTED_TEST (test_object); + UNPORTED_TEST (test_fixed); + UNPORTED_TEST (test_materials); + ADD_TEST (test_pipeline_user_matrix, 0, 0); + ADD_TEST (test_blend_strings, 0, 0); + ADD_TEST (test_blend, 0, 0); + ADD_TEST (test_premult, 0, TEST_KNOWN_FAILURE); + UNPORTED_TEST (test_readpixels); +#ifdef COGL_HAS_COGL_PATH_SUPPORT + ADD_TEST (test_path, 0, 0); + ADD_TEST (test_path_clip, 0, 0); +#endif + ADD_TEST (test_depth_test, 0, 0); + ADD_TEST (test_color_mask, 0, 0); + ADD_TEST (test_backface_culling, 0, TEST_REQUIREMENT_NPOT); + ADD_TEST (test_layer_remove, 0, 0); + + ADD_TEST (test_sparse_pipeline, 0, 0); + + ADD_TEST (test_npot_texture, 0, 0); + UNPORTED_TEST (test_multitexture); + UNPORTED_TEST (test_texture_mipmaps); + ADD_TEST (test_sub_texture, 0, 0); + ADD_TEST (test_pixel_buffer_map, 0, 0); + ADD_TEST (test_pixel_buffer_set_data, 0, 0); + ADD_TEST (test_pixel_buffer_sub_region, 0, 0); + UNPORTED_TEST (test_texture_rectangle); + ADD_TEST (test_texture_3d, TEST_REQUIREMENT_TEXTURE_3D, 0); + ADD_TEST (test_wrap_modes, 0, 0); + UNPORTED_TEST (test_texture_pixmap_x11); + ADD_TEST (test_texture_get_set_data, 0, 0); + ADD_TEST (test_atlas_migration, 0, 0); + ADD_TEST (test_read_texture_formats, 0, TEST_KNOWN_FAILURE); + ADD_TEST (test_write_texture_formats, 0, 0); + ADD_TEST (test_alpha_textures, 0, 0); + ADD_TEST (test_wrap_rectangle_textures, + TEST_REQUIREMENT_TEXTURE_RECTANGLE, + TEST_KNOWN_FAILURE); + + UNPORTED_TEST (test_vertex_buffer_contiguous); + UNPORTED_TEST (test_vertex_buffer_interleved); + UNPORTED_TEST (test_vertex_buffer_mutability); + + ADD_TEST (test_primitive, 0, 0); + + ADD_TEST (test_just_vertex_shader, TEST_REQUIREMENT_GLSL, 0); + ADD_TEST (test_pipeline_uniforms, TEST_REQUIREMENT_GLSL, 0); + ADD_TEST (test_snippets, TEST_REQUIREMENT_GLSL, 0); + ADD_TEST (test_custom_attributes, TEST_REQUIREMENT_GLSL, 0); + + ADD_TEST (test_offscreen, 0, 0); + ADD_TEST (test_framebuffer_get_bits, + TEST_REQUIREMENT_OFFSCREEN | TEST_REQUIREMENT_GL, + 0); + + ADD_TEST (test_point_size, 0, 0); + ADD_TEST (test_point_size_attribute, + TEST_REQUIREMENT_PER_VERTEX_POINT_SIZE, 0); + ADD_TEST (test_point_size_attribute_snippet, + TEST_REQUIREMENT_PER_VERTEX_POINT_SIZE | + TEST_REQUIREMENT_GLSL, 0); + ADD_TEST (test_point_sprite, + TEST_REQUIREMENT_POINT_SPRITE, + 0); + ADD_TEST (test_point_sprite_orientation, + TEST_REQUIREMENT_POINT_SPRITE, + TEST_KNOWN_FAILURE); + ADD_TEST (test_point_sprite_glsl, + TEST_REQUIREMENT_POINT_SPRITE | + TEST_REQUIREMENT_GLSL, + 0); + + ADD_TEST (test_version, 0, 0); + + ADD_TEST (test_alpha_test, 0, 0); + + ADD_TEST (test_map_buffer_range, TEST_REQUIREMENT_MAP_WRITE, 0); + + ADD_TEST (test_primitive_and_journal, 0, 0); + + ADD_TEST (test_copy_replace_texture, 0, 0); + + ADD_TEST (test_pipeline_cache_unrefs_texture, 0, 0); + ADD_TEST (test_pipeline_shader_state, TEST_REQUIREMENT_GLSL, 0); + + UNPORTED_TEST (test_viewport); + + ADD_TEST (test_gles2_context, TEST_REQUIREMENT_GLES2_CONTEXT, 0); + ADD_TEST (test_gles2_context_fbo, TEST_REQUIREMENT_GLES2_CONTEXT, 0); + ADD_TEST (test_gles2_context_copy_tex_image, + TEST_REQUIREMENT_GLES2_CONTEXT, + 0); + + ADD_TEST (test_euler_quaternion, 0, 0); + ADD_TEST (test_color_hsl, 0, 0); + + ADD_TEST (test_fence, TEST_REQUIREMENT_FENCE, 0); + + ADD_TEST (test_texture_no_allocate, 0, 0); + + ADD_TEST (test_texture_rg, TEST_REQUIREMENT_TEXTURE_RG, 0); + + g_printerr ("Unknown test name \"%s\"\n", argv[1]); + + return 1; +} diff --git a/cogl/tests/conform/test-copy-replace-texture.c b/cogl/tests/conform/test-copy-replace-texture.c new file mode 100644 index 0000000..f11070e --- /dev/null +++ b/cogl/tests/conform/test-copy-replace-texture.c @@ -0,0 +1,120 @@ +#include +#include + +#include "test-utils.h" + +/* Keep track of the number of textures that we've created and are + * still alive */ +static int alive_texture_mask = 0; + +#define N_LAYERS 3 +#define N_PIPELINES 4 + +#define PIPELINE_LAYER_MASK(pipeline_num) \ + (((1 << N_LAYERS) - 1) << (N_LAYERS * (pipeline_num) + 1)) +#define LAST_PIPELINE_MASK PIPELINE_LAYER_MASK (N_PIPELINES - 1) +#define FIRST_PIPELINE_MASK PIPELINE_LAYER_MASK (0) + +static void +free_texture_cb (void *user_data) +{ + int texture_num = GPOINTER_TO_INT (user_data); + + alive_texture_mask &= ~(1 << texture_num); +} + +static CoglTexture * +create_texture (void) +{ + static const guint8 data[] = + { 0xff, 0xff, 0xff, 0xff }; + static CoglUserDataKey texture_data_key; + CoglTexture2D *tex_2d; + static int texture_num = 1; + + alive_texture_mask |= (1 << texture_num); + + tex_2d = cogl_texture_2d_new_from_data (test_ctx, + 1, 1, /* width / height */ + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + 4, /* rowstride */ + data, + NULL); + + /* Set some user data on the texture so we can track when it has + * been destroyed */ + cogl_object_set_user_data (COGL_OBJECT (tex_2d), + &texture_data_key, + GINT_TO_POINTER (texture_num), + free_texture_cb); + + texture_num++; + + return tex_2d; +} + +void +test_copy_replace_texture (void) +{ + CoglPipeline *pipelines[N_PIPELINES]; + int pipeline_num; + + /* Create a set of pipeline copies each with three of their own + * replacement textures */ + for (pipeline_num = 0; pipeline_num < N_PIPELINES; pipeline_num++) + { + int layer_num; + + if (pipeline_num == 0) + pipelines[pipeline_num] = cogl_pipeline_new (test_ctx); + else + pipelines[pipeline_num] = + cogl_pipeline_copy (pipelines[pipeline_num - 1]); + + for (layer_num = 0; layer_num < N_LAYERS; layer_num++) + { + CoglTexture *tex = create_texture (); + cogl_pipeline_set_layer_texture (pipelines[pipeline_num], + layer_num, + tex); + cogl_object_unref (tex); + } + } + + /* Unref everything but the last pipeline */ + for (pipeline_num = 0; pipeline_num < N_PIPELINES - 1; pipeline_num++) + cogl_object_unref (pipelines[pipeline_num]); + + if (alive_texture_mask && cogl_test_verbose ()) + { + int i; + + g_print ("Alive textures:"); + + for (i = 0; i < N_PIPELINES * N_LAYERS; i++) + if ((alive_texture_mask & (1 << (i + 1)))) + g_print (" %i", i); + + g_print ("\n"); + } + + /* Ideally there should only be the textures from the last pipeline + * left alive. We also let Cogl keep the textures from the first + * texture alive because currently the child of the third layer in + * the first pipeline will retain its authority on the unit index + * state so that it can set it to 2. If there are more textures then + * it means the pipeline isn't correctly pruning redundant + * ancestors */ + g_assert_cmpint (alive_texture_mask & ~FIRST_PIPELINE_MASK, + ==, + LAST_PIPELINE_MASK); + + /* Clean up the last pipeline */ + cogl_object_unref (pipelines[N_PIPELINES - 1]); + + /* That should get rid of the last of the textures */ + g_assert_cmpint (alive_texture_mask, ==, 0); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} diff --git a/cogl/tests/conform/test-custom-attributes.c b/cogl/tests/conform/test-custom-attributes.c new file mode 100644 index 0000000..633dc2a --- /dev/null +++ b/cogl/tests/conform/test-custom-attributes.c @@ -0,0 +1,301 @@ +#include + +#include + +#include "test-utils.h" + +typedef struct _TestState +{ + CoglPipeline *pipeline; +} TestState; + +typedef struct +{ + int16_t x, y; + float r, g, b, a; +} FloatVert; + +typedef struct +{ + int16_t x, y; + uint8_t r, g, b, a; +} ByteVert; + +typedef struct +{ + int16_t x, y; + int16_t r, g, b, a; +} ShortVert; + +static void +test_float_verts (TestState *state, int offset_x, int offset_y) +{ + CoglAttribute *attributes[2]; + CoglAttributeBuffer *buffer; + CoglPrimitive *primitive; + + static const FloatVert float_verts[] = + { + { 0, 10, /**/ 1, 0, 0, 1 }, + { 10, 10, /**/ 1, 0, 0, 1 }, + { 5, 0, /**/ 1, 0, 0, 1 }, + + { 10, 10, /**/ 0, 1, 0, 1 }, + { 20, 10, /**/ 0, 1, 0, 1 }, + { 15, 0, /**/ 0, 1, 0, 1 } + }; + + buffer = cogl_attribute_buffer_new (test_ctx, + sizeof (float_verts), float_verts); + attributes[0] = cogl_attribute_new (buffer, + "cogl_position_in", + sizeof (FloatVert), + G_STRUCT_OFFSET (FloatVert, x), + 2, /* n_components */ + COGL_ATTRIBUTE_TYPE_SHORT); + attributes[1] = cogl_attribute_new (buffer, + "color", + sizeof (FloatVert), + G_STRUCT_OFFSET (FloatVert, r), + 4, /* n_components */ + COGL_ATTRIBUTE_TYPE_FLOAT); + + cogl_framebuffer_push_matrix (test_fb); + cogl_framebuffer_translate (test_fb, offset_x, offset_y, 0.0f); + + primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, + 6, /* n_vertices */ + attributes, + 2); /* n_attributes */ + cogl_primitive_draw (primitive, test_fb, state->pipeline); + cogl_object_unref (primitive); + + cogl_framebuffer_pop_matrix (test_fb); + + cogl_object_unref (attributes[1]); + cogl_object_unref (attributes[0]); + cogl_object_unref (buffer); + + test_utils_check_pixel (test_fb, offset_x + 5, offset_y + 5, 0xff0000ff); + test_utils_check_pixel (test_fb, offset_x + 15, offset_y + 5, 0x00ff00ff); +} + +static void +test_byte_verts (TestState *state, int offset_x, int offset_y) +{ + CoglAttribute *attributes[2]; + CoglAttributeBuffer *buffer, *unnorm_buffer; + CoglPrimitive *primitive; + + static const ByteVert norm_verts[] = + { + { 0, 10, /**/ 255, 0, 0, 255 }, + { 10, 10, /**/ 255, 0, 0, 255 }, + { 5, 0, /**/ 255, 0, 0, 255 }, + + { 10, 10, /**/ 0, 255, 0, 255 }, + { 20, 10, /**/ 0, 255, 0, 255 }, + { 15, 0, /**/ 0, 255, 0, 255 } + }; + + static const ByteVert unnorm_verts[] = + { + { 0, 0, /**/ 0, 0, 1, 1 }, + { 0, 0, /**/ 0, 0, 1, 1 }, + { 0, 0, /**/ 0, 0, 1, 1 }, + }; + + buffer = cogl_attribute_buffer_new (test_ctx, + sizeof (norm_verts), norm_verts); + attributes[0] = cogl_attribute_new (buffer, + "cogl_position_in", + sizeof (ByteVert), + G_STRUCT_OFFSET (ByteVert, x), + 2, /* n_components */ + COGL_ATTRIBUTE_TYPE_SHORT); + attributes[1] = cogl_attribute_new (buffer, + "color", + sizeof (ByteVert), + G_STRUCT_OFFSET (ByteVert, r), + 4, /* n_components */ + COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE); + cogl_attribute_set_normalized (attributes[1], TRUE); + + cogl_framebuffer_push_matrix (test_fb); + cogl_framebuffer_translate (test_fb, offset_x, offset_y, 0.0f); + + primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, + 6, /* n_vertices */ + attributes, + 2); /* n_attributes */ + cogl_primitive_draw (primitive, test_fb, state->pipeline); + cogl_object_unref (primitive); + + cogl_object_unref (attributes[1]); + + /* Test again with unnormalized attributes */ + unnorm_buffer = cogl_attribute_buffer_new (test_ctx, + sizeof (unnorm_verts), + unnorm_verts); + attributes[1] = cogl_attribute_new (unnorm_buffer, + "color", + sizeof (ByteVert), + G_STRUCT_OFFSET (ByteVert, r), + 4, /* n_components */ + COGL_ATTRIBUTE_TYPE_BYTE); + + cogl_framebuffer_translate (test_fb, 20, 0, 0); + + primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, + 3, /* n_vertices */ + attributes, + 2); /* n_attributes */ + cogl_primitive_draw (primitive, test_fb, state->pipeline); + cogl_object_unref (primitive); + + cogl_framebuffer_pop_matrix (test_fb); + + cogl_object_unref (attributes[0]); + cogl_object_unref (attributes[1]); + cogl_object_unref (buffer); + cogl_object_unref (unnorm_buffer); + + test_utils_check_pixel (test_fb, offset_x + 5, offset_y + 5, 0xff0000ff); + test_utils_check_pixel (test_fb, offset_x + 15, offset_y + 5, 0x00ff00ff); + test_utils_check_pixel (test_fb, offset_x + 25, offset_y + 5, 0x0000ffff); +} + +static void +test_short_verts (TestState *state, int offset_x, int offset_y) +{ + CoglAttribute *attributes[2]; + CoglAttributeBuffer *buffer; + CoglPipeline *pipeline, *pipeline2; + CoglSnippet *snippet; + CoglPrimitive *primitive; + + static const ShortVert short_verts[] = + { + { -10, -10, /**/ 0xffff, 0, 0, 0xffff }, + { -1, -10, /**/ 0xffff, 0, 0, 0xffff }, + { -5, -1, /**/ 0xffff, 0, 0, 0xffff } + }; + + + pipeline = cogl_pipeline_copy (state->pipeline); + + cogl_pipeline_set_color4ub (pipeline, 255, 0, 0, 255); + + buffer = cogl_attribute_buffer_new (test_ctx, + sizeof (short_verts), short_verts); + attributes[0] = cogl_attribute_new (buffer, + "cogl_position_in", + sizeof (ShortVert), + G_STRUCT_OFFSET (ShortVert, x), + 2, /* n_components */ + COGL_ATTRIBUTE_TYPE_SHORT); + attributes[1] = cogl_attribute_new (buffer, + "color", + sizeof (ShortVert), + G_STRUCT_OFFSET (ShortVert, r), + 4, /* n_components */ + COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT); + cogl_attribute_set_normalized (attributes[1], TRUE); + + cogl_framebuffer_push_matrix (test_fb); + cogl_framebuffer_translate (test_fb, + offset_x + 10.0f, + offset_y + 10.0f, + 0.0f); + + primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, + 3, /* n_vertices */ + attributes, + 2); /* n_attributes */ + cogl_primitive_draw (primitive, test_fb, pipeline); + cogl_object_unref (primitive); + + cogl_framebuffer_pop_matrix (test_fb); + + cogl_object_unref (attributes[0]); + + /* Test again treating the attribute as unsigned */ + attributes[0] = cogl_attribute_new (buffer, + "cogl_position_in", + sizeof (ShortVert), + G_STRUCT_OFFSET (ShortVert, x), + 2, /* n_components */ + COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT); + + /* XXX: this is a hack to force the pipeline to use the glsl backend + * because we know it's not possible to test short vertex position + * components with the legacy GL backend since which might otherwise + * be used internally... */ + pipeline2 = cogl_pipeline_new (test_ctx); + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX, + "attribute vec4 color;", + "cogl_color_out = vec4 (0.0, 1.0, 0.0, 1.0);"); + cogl_pipeline_add_snippet (pipeline2, snippet); + + cogl_framebuffer_push_matrix (test_fb); + cogl_framebuffer_translate (test_fb, + offset_x + 10.0f - 65525.0f, + offset_y - 65525, + 0.0f); + + primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, + 3, /* n_vertices */ + attributes, + 1); /* n_attributes */ + cogl_primitive_draw (primitive, test_fb, pipeline2); + cogl_object_unref (primitive); + + cogl_framebuffer_pop_matrix (test_fb); + + cogl_object_unref (attributes[0]); + + cogl_object_unref (pipeline2); + cogl_object_unref (pipeline); + cogl_object_unref (buffer); + + test_utils_check_pixel (test_fb, offset_x + 5, offset_y + 5, 0xff0000ff); + test_utils_check_pixel (test_fb, offset_x + 15, offset_y + 5, 0x00ff00ff); +} + +static void +paint (TestState *state) +{ + cogl_framebuffer_clear4f (test_fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1); + + test_float_verts (state, 0, 0); + test_byte_verts (state, 0, 10); + test_short_verts (state, 0, 20); +} + +void +test_custom_attributes (void) +{ + CoglSnippet *snippet; + TestState state; + + cogl_framebuffer_orthographic (test_fb, + 0, 0, + cogl_framebuffer_get_width (test_fb), + cogl_framebuffer_get_height (test_fb), + -1, + 100); + + state.pipeline = cogl_pipeline_new (test_ctx); + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX, + "attribute vec4 color;", + "cogl_color_out = color;"); + cogl_pipeline_add_snippet (state.pipeline, snippet); + + paint (&state); + + cogl_object_unref (state.pipeline); + cogl_object_unref (snippet); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} diff --git a/cogl/tests/conform/test-depth-test.c b/cogl/tests/conform/test-depth-test.c new file mode 100644 index 0000000..bfa9d0e --- /dev/null +++ b/cogl/tests/conform/test-depth-test.c @@ -0,0 +1,301 @@ +#define COGL_VERSION_MIN_REQUIRED COGL_VERSION_1_0 + +#include + +#include + +#include "test-utils.h" + +#define QUAD_WIDTH 20 + +#define RED 0 +#define GREEN 1 +#define BLUE 2 +#define ALPHA 3 + +#define MASK_RED(COLOR) ((COLOR & 0xff000000) >> 24) +#define MASK_GREEN(COLOR) ((COLOR & 0xff0000) >> 16) +#define MASK_BLUE(COLOR) ((COLOR & 0xff00) >> 8) +#define MASK_ALPHA(COLOR) (COLOR & 0xff) + +typedef struct _TestState +{ + int padding; +} TestState; + +typedef struct +{ + uint32_t color; + float depth; + CoglBool test_enable; + CoglDepthTestFunction test_function; + CoglBool write_enable; + CoglBool fb_write_enable; + float range_near; + float range_far; +} TestDepthState; + +static CoglBool +draw_rectangle (TestState *state, + int x, + int y, + TestDepthState *rect_state, + CoglBool legacy_mode) +{ + uint8_t Cr = MASK_RED (rect_state->color); + uint8_t Cg = MASK_GREEN (rect_state->color); + uint8_t Cb = MASK_BLUE (rect_state->color); + uint8_t Ca = MASK_ALPHA (rect_state->color); + CoglPipeline *pipeline; + CoglDepthState depth_state; + + cogl_depth_state_init (&depth_state); + cogl_depth_state_set_test_enabled (&depth_state, rect_state->test_enable); + cogl_depth_state_set_test_function (&depth_state, rect_state->test_function); + cogl_depth_state_set_write_enabled (&depth_state, rect_state->write_enable); + cogl_depth_state_set_range (&depth_state, + rect_state->range_near, + rect_state->range_far); + + pipeline = cogl_pipeline_new (test_ctx); + if (!cogl_pipeline_set_depth_state (pipeline, &depth_state, NULL)) + { + cogl_object_unref (pipeline); + return FALSE; + } + + if (!legacy_mode) + { + cogl_pipeline_set_color4ub (pipeline, Cr, Cg, Cb, Ca); + + cogl_framebuffer_set_depth_write_enabled (test_fb, + rect_state->fb_write_enable); + cogl_framebuffer_push_matrix (test_fb); + cogl_framebuffer_translate (test_fb, 0, 0, rect_state->depth); + cogl_framebuffer_draw_rectangle (test_fb, + pipeline, + x * QUAD_WIDTH, + y * QUAD_WIDTH, + x * QUAD_WIDTH + QUAD_WIDTH, + y * QUAD_WIDTH + QUAD_WIDTH); + cogl_framebuffer_pop_matrix (test_fb); + } + else + { + cogl_push_framebuffer (test_fb); + cogl_push_matrix (); + cogl_set_source_color4ub (Cr, Cg, Cb, Ca); + cogl_translate (0, 0, rect_state->depth); + cogl_rectangle (x * QUAD_WIDTH, + y * QUAD_WIDTH, + x * QUAD_WIDTH + QUAD_WIDTH, + y * QUAD_WIDTH + QUAD_WIDTH); + cogl_pop_matrix (); + cogl_pop_framebuffer (); + } + + cogl_object_unref (pipeline); + + return TRUE; +} + +static void +test_depth (TestState *state, + int x, + int y, + TestDepthState *rect0_state, + TestDepthState *rect1_state, + TestDepthState *rect2_state, + CoglBool legacy_mode, + uint32_t expected_result) +{ + CoglBool missing_feature = FALSE; + + if (rect0_state) + missing_feature |= !draw_rectangle (state, x, y, rect0_state, legacy_mode); + if (rect1_state) + missing_feature |= !draw_rectangle (state, x, y, rect1_state, legacy_mode); + if (rect2_state) + missing_feature |= !draw_rectangle (state, x, y, rect2_state, legacy_mode); + + /* We don't consider it an error that we can't test something + * the driver doesn't support. */ + if (missing_feature) + return; + + test_utils_check_pixel (test_fb, + x * QUAD_WIDTH + (QUAD_WIDTH / 2), + y * QUAD_WIDTH + (QUAD_WIDTH / 2), + expected_result); +} + +static void +paint (TestState *state) +{ + /* Sanity check a few of the different depth test functions + * and that depth writing can be disabled... */ + + { + /* Closest */ + TestDepthState rect0_state = { + 0xff0000ff, /* rgba color */ + -10, /* depth */ + FALSE, /* depth test enable */ + COGL_DEPTH_TEST_FUNCTION_ALWAYS, + TRUE, /* depth write enable */ + TRUE, /* FB depth write enable */ + 0, 1 /* depth range */ + }; + /* Furthest */ + TestDepthState rect1_state = { + 0x00ff00ff, /* rgba color */ + -70, /* depth */ + TRUE, /* depth test enable */ + COGL_DEPTH_TEST_FUNCTION_ALWAYS, + TRUE, /* depth write enable */ + TRUE, /* FB depth write enable */ + 0, 1 /* depth range */ + }; + /* In the middle */ + TestDepthState rect2_state = { + 0x0000ffff, /* rgba color */ + -20, /* depth */ + TRUE, /* depth test enable */ + COGL_DEPTH_TEST_FUNCTION_NEVER, + TRUE, /* depth write enable */ + TRUE, /* FB depth write enable */ + 0, 1 /* depth range */ + }; + + test_depth (state, 0, 0, /* position */ + &rect0_state, &rect1_state, &rect2_state, + FALSE, /* legacy mode */ + 0x00ff00ff); /* expected */ + + rect2_state.test_function = COGL_DEPTH_TEST_FUNCTION_ALWAYS; + test_depth (state, 1, 0, /* position */ + &rect0_state, &rect1_state, &rect2_state, + FALSE, /* legacy mode */ + 0x0000ffff); /* expected */ + + rect2_state.test_function = COGL_DEPTH_TEST_FUNCTION_LESS; + test_depth (state, 2, 0, /* position */ + &rect0_state, &rect1_state, &rect2_state, + FALSE, /* legacy mode */ + 0x0000ffff); /* expected */ + + rect2_state.test_function = COGL_DEPTH_TEST_FUNCTION_GREATER; + test_depth (state, 3, 0, /* position */ + &rect0_state, &rect1_state, &rect2_state, + FALSE, /* legacy mode */ + 0x00ff00ff); /* expected */ + + rect0_state.test_enable = TRUE; + rect1_state.write_enable = FALSE; + test_depth (state, 4, 0, /* position */ + &rect0_state, &rect1_state, &rect2_state, + FALSE, /* legacy mode */ + 0x0000ffff); /* expected */ + + rect1_state.write_enable = TRUE; + rect1_state.fb_write_enable = FALSE; + test_depth (state, 4, 0, /* position */ + &rect0_state, &rect1_state, &rect2_state, + FALSE, /* legacy mode */ + 0x0000ffff); /* expected */ + + /* Re-enable FB depth writing to verify state flush */ + rect1_state.write_enable = TRUE; + rect1_state.fb_write_enable = TRUE; + test_depth (state, 4, 0, /* position */ + &rect0_state, &rect1_state, &rect2_state, + FALSE, /* legacy mode */ + 0x00ff00ff); /* expected */ + } + + /* Check that the depth buffer values can be mapped into different + * ranges... */ + + { + /* Closest by depth, furthest by depth range */ + TestDepthState rect0_state = { + 0xff0000ff, /* rgba color */ + -10, /* depth */ + TRUE, /* depth test enable */ + COGL_DEPTH_TEST_FUNCTION_ALWAYS, + TRUE, /* depth write enable */ + TRUE, /* FB depth write enable */ + 0.5, 1 /* depth range */ + }; + /* Furthest by depth, nearest by depth range */ + TestDepthState rect1_state = { + 0x00ff00ff, /* rgba color */ + -70, /* depth */ + TRUE, /* depth test enable */ + COGL_DEPTH_TEST_FUNCTION_GREATER, + TRUE, /* depth write enable */ + TRUE, /* FB depth write enable */ + 0, 0.5 /* depth range */ + }; + + test_depth (state, 0, 1, /* position */ + &rect0_state, &rect1_state, NULL, + FALSE, /* legacy mode */ + 0xff0000ff); /* expected */ + } + + /* Test that the legacy cogl_set_depth_test_enabled() API still + * works... */ + + { + /* Nearest */ + TestDepthState rect0_state = { + 0xff0000ff, /* rgba color */ + -10, /* depth */ + FALSE, /* depth test enable */ + COGL_DEPTH_TEST_FUNCTION_LESS, + TRUE, /* depth write enable */ + TRUE, /* FB depth write enable */ + 0, 1 /* depth range */ + }; + /* Furthest */ + TestDepthState rect1_state = { + 0x00ff00ff, /* rgba color */ + -70, /* depth */ + FALSE, /* depth test enable */ + COGL_DEPTH_TEST_FUNCTION_LESS, + TRUE, /* depth write enable */ + TRUE, /* FB depth write enable */ + 0, 1 /* depth range */ + }; + + cogl_set_depth_test_enabled (TRUE); + test_depth (state, 0, 2, /* position */ + &rect0_state, &rect1_state, NULL, + TRUE, /* legacy mode */ + 0xff0000ff); /* expected */ + cogl_set_depth_test_enabled (FALSE); + test_depth (state, 1, 2, /* position */ + &rect0_state, &rect1_state, NULL, + TRUE, /* legacy mode */ + 0x00ff00ff); /* expected */ + } +} + +void +test_depth_test (void) +{ + TestState state; + + cogl_framebuffer_orthographic (test_fb, 0, 0, + cogl_framebuffer_get_width (test_fb), + cogl_framebuffer_get_height (test_fb), + -1, + 100); + + paint (&state); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} + diff --git a/cogl/tests/conform/test-euler-quaternion.c b/cogl/tests/conform/test-euler-quaternion.c new file mode 100644 index 0000000..c250bec --- /dev/null +++ b/cogl/tests/conform/test-euler-quaternion.c @@ -0,0 +1,81 @@ +#include +#include +#include + +#include "test-utils.h" + +/* Macros are used here instead of functions so that the + * g_assert_cmpfloat will give a more interesting message when it + * fails */ + +#define COMPARE_FLOATS(a, b) \ + do { \ + if (fabsf ((a) - (b)) >= 0.0001f) \ + g_assert_cmpfloat ((a), ==, (b)); \ + } while (0) + +#define COMPARE_MATRICES(a, b) \ + do { \ + COMPARE_FLOATS ((a)->xx, (b)->xx); \ + COMPARE_FLOATS ((a)->yx, (b)->yx); \ + COMPARE_FLOATS ((a)->zx, (b)->zx); \ + COMPARE_FLOATS ((a)->wx, (b)->wx); \ + COMPARE_FLOATS ((a)->xy, (b)->xy); \ + COMPARE_FLOATS ((a)->yy, (b)->yy); \ + COMPARE_FLOATS ((a)->zy, (b)->zy); \ + COMPARE_FLOATS ((a)->wy, (b)->wy); \ + COMPARE_FLOATS ((a)->xz, (b)->xz); \ + COMPARE_FLOATS ((a)->yz, (b)->yz); \ + COMPARE_FLOATS ((a)->zz, (b)->zz); \ + COMPARE_FLOATS ((a)->wz, (b)->wz); \ + COMPARE_FLOATS ((a)->xw, (b)->xw); \ + COMPARE_FLOATS ((a)->yw, (b)->yw); \ + COMPARE_FLOATS ((a)->zw, (b)->zw); \ + COMPARE_FLOATS ((a)->ww, (b)->ww); \ + } while (0) + +void +test_euler_quaternion (void) +{ + CoglEuler euler; + CoglQuaternion quaternion; + CoglMatrix matrix_a, matrix_b; + + /* Try doing the rotation with three separate rotations */ + cogl_matrix_init_identity (&matrix_a); + cogl_matrix_rotate (&matrix_a, -30.0f, 0.0f, 1.0f, 0.0f); + cogl_matrix_rotate (&matrix_a, 40.0f, 1.0f, 0.0f, 0.0f); + cogl_matrix_rotate (&matrix_a, 50.0f, 0.0f, 0.0f, 1.0f); + + /* And try the same rotation with a euler */ + cogl_euler_init (&euler, -30, 40, 50); + cogl_matrix_init_from_euler (&matrix_b, &euler); + + /* Verify that the matrices are approximately the same */ + COMPARE_MATRICES (&matrix_a, &matrix_b); + + /* Try converting the euler to a matrix via a quaternion */ + cogl_quaternion_init_from_euler (&quaternion, &euler); + memset (&matrix_b, 0, sizeof (matrix_b)); + cogl_matrix_init_from_quaternion (&matrix_b, &quaternion); + COMPARE_MATRICES (&matrix_a, &matrix_b); + + /* Try applying the rotation from a euler to a framebuffer */ + cogl_framebuffer_identity_matrix (test_fb); + cogl_framebuffer_rotate_euler (test_fb, &euler); + memset (&matrix_b, 0, sizeof (matrix_b)); + cogl_framebuffer_get_modelview_matrix (test_fb, &matrix_b); + COMPARE_MATRICES (&matrix_a, &matrix_b); + + /* And again with a quaternion */ + cogl_framebuffer_identity_matrix (test_fb); + cogl_framebuffer_rotate_quaternion (test_fb, &quaternion); + memset (&matrix_b, 0, sizeof (matrix_b)); + cogl_framebuffer_get_modelview_matrix (test_fb, &matrix_b); + COMPARE_MATRICES (&matrix_a, &matrix_b); + + /* FIXME: This needs a lot more tests! */ + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} diff --git a/cogl/tests/conform/test-fence.c b/cogl/tests/conform/test-fence.c new file mode 100644 index 0000000..1386bce --- /dev/null +++ b/cogl/tests/conform/test-fence.c @@ -0,0 +1,59 @@ +#include + +#include "test-utils.h" +#include "cogl-config.h" + +/* I'm writing this on the train after having dinner at a churrascuria. */ +#define MAGIC_CHUNK_O_DATA ((void *) 0xdeadbeef) + +static GMainLoop *loop; + +gboolean +timeout (void *user_data) +{ + g_assert (!"timeout not reached"); + + return FALSE; +} + +void +callback (CoglFence *fence, + void *user_data) +{ + int fb_width = cogl_framebuffer_get_width (test_fb); + int fb_height = cogl_framebuffer_get_height (test_fb); + + test_utils_check_pixel (test_fb, fb_width - 1, fb_height - 1, 0x00ff0000); + g_assert (user_data == MAGIC_CHUNK_O_DATA && "callback data not mangled"); + + g_main_loop_quit (loop); +} + +void +test_fence (void) +{ + GSource *cogl_source; + int fb_width = cogl_framebuffer_get_width (test_fb); + int fb_height = cogl_framebuffer_get_height (test_fb); + CoglFenceClosure *closure; + + cogl_source = cogl_glib_source_new (test_ctx, G_PRIORITY_DEFAULT); + g_source_attach (cogl_source, NULL); + loop = g_main_loop_new (NULL, TRUE); + + cogl_framebuffer_orthographic (test_fb, 0, 0, fb_width, fb_height, -1, 100); + cogl_framebuffer_clear4f (test_fb, COGL_BUFFER_BIT_COLOR, + 0.0f, 1.0f, 0.0f, 0.0f); + + closure = cogl_framebuffer_add_fence_callback (test_fb, + callback, + MAGIC_CHUNK_O_DATA); + g_assert (closure != NULL); + + g_timeout_add_seconds (5, timeout, NULL); + + g_main_loop_run (loop); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} diff --git a/cogl/tests/conform/test-framebuffer-get-bits.c b/cogl/tests/conform/test-framebuffer-get-bits.c new file mode 100644 index 0000000..31c220d --- /dev/null +++ b/cogl/tests/conform/test-framebuffer-get-bits.c @@ -0,0 +1,40 @@ +#include + +#include "test-utils.h" + +void +test_framebuffer_get_bits (void) +{ + CoglTexture2D *tex_a = + cogl_texture_2d_new_with_size (test_ctx, + 16, 16); /* width/height */ + CoglOffscreen *offscreen_a = + cogl_offscreen_new_with_texture (tex_a); + CoglFramebuffer *fb_a = offscreen_a; + CoglTexture2D *tex_rgba = + cogl_texture_2d_new_with_size (test_ctx, + 16, 16); /* width/height */ + CoglOffscreen *offscreen_rgba = + cogl_offscreen_new_with_texture (tex_rgba); + CoglFramebuffer *fb_rgba = offscreen_rgba; + + cogl_texture_set_components (tex_a, + COGL_TEXTURE_COMPONENTS_A); + cogl_framebuffer_allocate (fb_a, NULL); + cogl_framebuffer_allocate (fb_rgba, NULL); + + g_assert_cmpint (cogl_framebuffer_get_red_bits (fb_a), ==, 0); + g_assert_cmpint (cogl_framebuffer_get_green_bits (fb_a), ==, 0); + g_assert_cmpint (cogl_framebuffer_get_blue_bits (fb_a), ==, 0); + g_assert_cmpint (cogl_framebuffer_get_alpha_bits (fb_a), >=, 1); + + g_assert_cmpint (cogl_framebuffer_get_red_bits (fb_rgba), >=, 1); + g_assert_cmpint (cogl_framebuffer_get_green_bits (fb_rgba), >=, 1); + g_assert_cmpint (cogl_framebuffer_get_blue_bits (fb_rgba), >=, 1); + g_assert_cmpint (cogl_framebuffer_get_alpha_bits (fb_rgba), >=, 1); + + cogl_object_unref (fb_rgba); + cogl_object_unref (tex_rgba); + cogl_object_unref (fb_a); + cogl_object_unref (tex_a); +} diff --git a/cogl/tests/conform/test-gles2-context.c b/cogl/tests/conform/test-gles2-context.c new file mode 100644 index 0000000..bedc30a --- /dev/null +++ b/cogl/tests/conform/test-gles2-context.c @@ -0,0 +1,962 @@ + +#include +#include +#include + +#include "test-utils.h" + +typedef struct _TestState +{ + CoglTexture *offscreen_texture; + CoglOffscreen *offscreen; + CoglGLES2Context *gles2_ctx; + const CoglGLES2Vtable *gles2; +} TestState; + +static void +test_push_pop_single_context (void) +{ + CoglTexture *offscreen_texture; + CoglOffscreen *offscreen; + CoglPipeline *pipeline; + CoglGLES2Context *gles2_ctx; + const CoglGLES2Vtable *gles2; + CoglError *error = NULL; + + offscreen_texture = + cogl_texture_2d_new_with_size (test_ctx, + cogl_framebuffer_get_width (test_fb), + cogl_framebuffer_get_height (test_fb)); + offscreen = cogl_offscreen_new_with_texture (offscreen_texture); + + pipeline = cogl_pipeline_new (test_ctx); + cogl_pipeline_set_layer_texture (pipeline, 0, offscreen_texture); + + gles2_ctx = cogl_gles2_context_new (test_ctx, &error); + if (!gles2_ctx) + g_error ("Failed to create GLES2 context: %s\n", error->message); + + gles2 = cogl_gles2_context_get_vtable (gles2_ctx); + + /* Clear onscreen to 0xffff00 using GLES2 */ + + if (!cogl_push_gles2_context (test_ctx, + gles2_ctx, + test_fb, + test_fb, + &error)) + { + g_error ("Failed to push gles2 context: %s\n", error->message); + } + + gles2->glClearColor (1, 1, 0, 1); + gles2->glClear (GL_COLOR_BUFFER_BIT); + + cogl_pop_gles2_context (test_ctx); + + test_utils_check_pixel (test_fb, 0, 0, 0xffff00ff); + + /* Clear offscreen to 0xff0000 using GLES2 and then copy the result + * onscreen. + * + * If we fail to bind the new context here then we'd probably end up + * clearing onscreen to 0xff0000 and copying 0xffff00 to onscreen + * instead. + */ + + if (!cogl_push_gles2_context (test_ctx, + gles2_ctx, + offscreen, + offscreen, + &error)) + { + g_error ("Failed to push gles2 context: %s\n", error->message); + } + + gles2->glClearColor (1, 0, 0, 1); + gles2->glClear (GL_COLOR_BUFFER_BIT); + + cogl_pop_gles2_context (test_ctx); + + cogl_framebuffer_draw_rectangle (test_fb, + pipeline, + -1, 1, 1, -1); + /* NB: Cogl doesn't automatically support mid-scene modifications + * of textures and so we explicitly flush the drawn rectangle to the + * framebuffer now otherwise it may be batched until after the + * offscreen texture has been modified again. */ + cogl_flush (); + + /* Clear the offscreen framebuffer to blue using GLES2 before + * reading back from the onscreen framebuffer in case we mistakenly + * read from the offscreen framebuffer and get a false positive + */ + if (!cogl_push_gles2_context (test_ctx, + gles2_ctx, + offscreen, + offscreen, + &error)) + { + g_error ("Failed to push gles2 context: %s\n", error->message); + } + + gles2->glClearColor (0, 0, 1, 1); + gles2->glClear (GL_COLOR_BUFFER_BIT); + + cogl_pop_gles2_context (test_ctx); + + test_utils_check_pixel (test_fb, 0, 0, 0xff0000ff); + + /* Now copy the offscreen blue clear to the onscreen framebufer and + * check that too */ + cogl_framebuffer_draw_rectangle (test_fb, + pipeline, + -1, 1, 1, -1); + + test_utils_check_pixel (test_fb, 0, 0, 0x0000ffff); + + if (!cogl_push_gles2_context (test_ctx, + gles2_ctx, + test_fb, + test_fb, + &error)) + { + g_error ("Failed to push gles2 context: %s\n", error->message); + } + + gles2->glClearColor (1, 0, 1, 1); + gles2->glClear (GL_COLOR_BUFFER_BIT); + + cogl_pop_gles2_context (test_ctx); + + test_utils_check_pixel (test_fb, 0, 0, 0xff00ffff); + + + cogl_object_unref (gles2_ctx); + + cogl_object_unref (pipeline); +} + +static void +create_gles2_context (CoglTexture **offscreen_texture, + CoglOffscreen **offscreen, + CoglPipeline **pipeline, + CoglGLES2Context **gles2_ctx, + const CoglGLES2Vtable **gles2) +{ + CoglError *error = NULL; + + *offscreen_texture = + cogl_texture_2d_new_with_size (test_ctx, + cogl_framebuffer_get_width (test_fb), + cogl_framebuffer_get_height (test_fb)); + *offscreen = cogl_offscreen_new_with_texture (*offscreen_texture); + + *pipeline = cogl_pipeline_new (test_ctx); + cogl_pipeline_set_layer_texture (*pipeline, 0, *offscreen_texture); + + *gles2_ctx = cogl_gles2_context_new (test_ctx, &error); + if (!*gles2_ctx) + g_error ("Failed to create GLES2 context: %s\n", error->message); + + *gles2 = cogl_gles2_context_get_vtable (*gles2_ctx); +} + +static void +test_push_pop_multi_context (void) +{ + CoglTexture *offscreen_texture0; + CoglOffscreen *offscreen0; + CoglPipeline *pipeline0; + CoglGLES2Context *gles2_ctx0; + const CoglGLES2Vtable *gles20; + CoglTexture *offscreen_texture1; + CoglOffscreen *offscreen1; + CoglPipeline *pipeline1; + CoglGLES2Context *gles2_ctx1; + const CoglGLES2Vtable *gles21; + CoglError *error = NULL; + + create_gles2_context (&offscreen_texture0, + &offscreen0, + &pipeline0, + &gles2_ctx0, + &gles20); + + create_gles2_context (&offscreen_texture1, + &offscreen1, + &pipeline1, + &gles2_ctx1, + &gles21); + + cogl_framebuffer_clear4f (test_fb, COGL_BUFFER_BIT_COLOR, 1, 1, 1, 1); + + if (!cogl_push_gles2_context (test_ctx, + gles2_ctx0, + offscreen0, + offscreen0, + &error)) + { + g_error ("Failed to push gles2 context 0: %s\n", error->message); + } + + gles20->glClearColor (1, 0, 0, 1); + gles20->glClear (GL_COLOR_BUFFER_BIT); + + if (!cogl_push_gles2_context (test_ctx, + gles2_ctx1, + offscreen1, + offscreen1, + &error)) + { + g_error ("Failed to push gles2 context 1: %s\n", error->message); + } + + gles21->glClearColor (0, 1, 0, 1); + gles21->glClear (GL_COLOR_BUFFER_BIT); + + cogl_pop_gles2_context (test_ctx); + cogl_pop_gles2_context (test_ctx); + + test_utils_check_pixel (test_fb, 0, 0, 0xffffffff); + + cogl_framebuffer_draw_rectangle (test_fb, + pipeline0, + -1, 1, 1, -1); + + test_utils_check_pixel (test_fb, 0, 0, 0xff0000ff); + + cogl_framebuffer_draw_rectangle (test_fb, + pipeline1, + -1, 1, 1, -1); + + test_utils_check_pixel (test_fb, 0, 0, 0x00ff00ff); +} + +static GLuint +create_gles2_framebuffer (const CoglGLES2Vtable *gles2, + int width, + int height) +{ + GLuint texture_handle; + GLuint fbo_handle; + GLenum status; + + gles2->glGenTextures (1, &texture_handle); + gles2->glGenFramebuffers (1, &fbo_handle); + + gles2->glBindTexture (GL_TEXTURE_2D, texture_handle); + gles2->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + gles2->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gles2->glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, + GL_UNSIGNED_BYTE, NULL); + gles2->glBindTexture (GL_TEXTURE_2D, 0); + + gles2->glBindFramebuffer (GL_FRAMEBUFFER, fbo_handle); + gles2->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, texture_handle, 0); + + status = gles2->glCheckFramebufferStatus (GL_FRAMEBUFFER); + if (cogl_test_verbose ()) + g_print ("status for gles2 framebuffer = 0x%x %s\n", + status, status == GL_FRAMEBUFFER_COMPLETE ? "(complete)" : "(?)"); + + gles2->glBindFramebuffer (GL_FRAMEBUFFER, 0); + + return fbo_handle; +} + +static void +test_gles2_read_pixels (void) +{ + CoglTexture *offscreen_texture; + CoglOffscreen *offscreen; + CoglPipeline *pipeline; + CoglGLES2Context *gles2_ctx; + const CoglGLES2Vtable *gles2; + CoglError *error = NULL; + GLubyte pixel[4]; + GLuint fbo_handle; + + create_gles2_context (&offscreen_texture, + &offscreen, + &pipeline, + &gles2_ctx, + &gles2); + + cogl_framebuffer_clear4f (test_fb, COGL_BUFFER_BIT_COLOR, 1, 1, 1, 1); + + if (!cogl_push_gles2_context (test_ctx, + gles2_ctx, + offscreen, + offscreen, + &error)) + { + g_error ("Failed to push gles2 context: %s\n", error->message); + } + + gles2->glClearColor (1, 0, 0, 1); + gles2->glClear (GL_COLOR_BUFFER_BIT); + gles2->glReadPixels (0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel); + + test_utils_compare_pixel (pixel, 0xff0000ff); + + fbo_handle = create_gles2_framebuffer (gles2, 256, 256); + + gles2->glBindFramebuffer (GL_FRAMEBUFFER, fbo_handle); + + gles2->glClearColor (0, 1, 0, 1); + gles2->glClear (GL_COLOR_BUFFER_BIT); + gles2->glReadPixels (0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel); + + test_utils_compare_pixel (pixel, 0x00ff00ff); + + gles2->glBindFramebuffer (GL_FRAMEBUFFER, 0); + + gles2->glClearColor (0, 1, 1, 1); + gles2->glClear (GL_COLOR_BUFFER_BIT); + gles2->glReadPixels (0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel); + + test_utils_compare_pixel (pixel, 0x00ffffff); + + cogl_pop_gles2_context (test_ctx); + + test_utils_check_pixel (test_fb, 0, 0, 0xffffffff); + + /* Bind different read and write buffers */ + if (!cogl_push_gles2_context (test_ctx, + gles2_ctx, + offscreen, + test_fb, + &error)) + { + g_error ("Failed to push gles2 context: %s\n", error->message); + } + + gles2->glReadPixels (0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel); + + test_utils_compare_pixel (pixel, 0x00ffffff); + + cogl_pop_gles2_context (test_ctx); + + test_utils_check_pixel (test_fb, 0, 0, 0xffffffff); + + /* Bind different read and write buffers (the other way around from + * before so when we test with COGL_TEST_ONSCREEN=1 we will read + * from an onscreen framebuffer) */ + if (!cogl_push_gles2_context (test_ctx, + gles2_ctx, + test_fb, + offscreen, + &error)) + { + g_error ("Failed to push gles2 context: %s\n", error->message); + } + + gles2->glReadPixels (0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel); + + test_utils_compare_pixel (pixel, 0xffffffff); + + cogl_pop_gles2_context (test_ctx); +} + +void +test_gles2_context (void) +{ + test_push_pop_single_context (); + test_push_pop_multi_context (); + test_gles2_read_pixels (); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} + +static GLuint +create_shader (const CoglGLES2Vtable *gles2, + GLenum type, + const char *source) +{ + GLuint shader; + GLint status; + int length = strlen (source); + + shader = gles2->glCreateShader (type); + gles2->glShaderSource (shader, 1, &source, &length); + gles2->glCompileShader (shader); + gles2->glGetShaderiv (shader, GL_COMPILE_STATUS, &status); + + if (!status) + { + char buf[512]; + + gles2->glGetShaderInfoLog (shader, sizeof (buf), NULL, buf); + + g_error ("Shader compilation failed:\n%s", buf); + } + + return shader; +} + +static GLuint +create_program (const CoglGLES2Vtable *gles2, + const char *vertex_shader_source, + const char *fragment_shader_source) +{ + GLuint fragment_shader, vertex_shader, program; + GLint status; + + vertex_shader = + create_shader (gles2, GL_VERTEX_SHADER, vertex_shader_source); + fragment_shader = + create_shader (gles2, GL_FRAGMENT_SHADER, fragment_shader_source); + + program = gles2->glCreateProgram (); + gles2->glAttachShader (program, vertex_shader); + gles2->glAttachShader (program, fragment_shader); + gles2->glLinkProgram (program); + + gles2->glGetProgramiv (program, GL_LINK_STATUS, &status); + + if (!status) + { + char buf[512]; + + gles2->glGetProgramInfoLog (program, sizeof (buf), NULL, buf); + + g_error ("Program linking failed:\n%s", buf); + } + + return program; +} + +typedef struct +{ + const CoglGLES2Vtable *gles2; + GLint color_location; + GLint pos_location; + int fb_width, fb_height; +} PaintData; + +typedef void (* PaintMethod) (PaintData *data); + +/* Top vertices are counter-clockwise */ +static const float top_vertices[] = + { + -1.0f, 0.0f, + 1.0f, 0.0f, + -1.0f, 1.0f, + 1.0f, 1.0f + }; +/* Bottom vertices are clockwise */ +static const float bottom_vertices[] = + { + 1.0f, 0.0f, + 1.0f, -1.0f, + -1.0f, 0.0f, + -1.0f, -1.0f + }; + +static void +paint_quads (PaintData *data) +{ + const CoglGLES2Vtable *gles2 = data->gles2; + + gles2->glEnableVertexAttribArray (data->pos_location); + + /* Paint the top half in red */ + gles2->glUniform4f (data->color_location, + 1.0f, 0.0f, 0.0f, 1.0f); + gles2->glVertexAttribPointer (data->pos_location, + 2, /* size */ + GL_FLOAT, + GL_FALSE, /* not normalized */ + sizeof (float) * 2, + top_vertices); + gles2->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); + + /* Paint the bottom half in blue */ + gles2->glUniform4f (data->color_location, + 0.0f, 0.0f, 1.0f, 1.0f); + gles2->glVertexAttribPointer (data->pos_location, + 2, /* size */ + GL_FLOAT, + GL_FALSE, /* not normalized */ + sizeof (float) * 2, + bottom_vertices); + gles2->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); +} + +static void +paint_viewport (PaintData *data) +{ + const CoglGLES2Vtable *gles2 = data->gles2; + int viewport[4]; + + /* Vertices to fill the entire framebuffer */ + static const float vertices[] = + { + -1.0f, -1.0f, + 1.0f, -1.0f, + -1.0f, 1.0f, + 1.0f, 1.0f + }; + + gles2->glEnableVertexAttribArray (data->pos_location); + gles2->glVertexAttribPointer (data->pos_location, + 2, /* size */ + GL_FLOAT, + GL_FALSE, /* not normalized */ + sizeof (float) * 2, + vertices); + + /* Paint the top half in red */ + gles2->glViewport (0, data->fb_height / 2, + data->fb_width, data->fb_height / 2); + gles2->glUniform4f (data->color_location, + 1.0f, 0.0f, 0.0f, 1.0f); + gles2->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); + + /* Paint the bottom half in blue */ + gles2->glViewport (0, 0, data->fb_width, data->fb_height / 2); + gles2->glUniform4f (data->color_location, + 0.0f, 0.0f, 1.0f, 1.0f); + gles2->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); + + gles2->glGetIntegerv (GL_VIEWPORT, viewport); + g_assert_cmpint (viewport[0], ==, 0.0f); + g_assert_cmpint (viewport[1], ==, 0.0f); + g_assert_cmpint (viewport[2], ==, data->fb_width); + g_assert_cmpint (viewport[3], ==, data->fb_height / 2); +} + +static void +paint_scissor (PaintData *data) +{ + const CoglGLES2Vtable *gles2 = data->gles2; + float scissor[4]; + + gles2->glEnable (GL_SCISSOR_TEST); + + /* Paint the top half in red */ + gles2->glScissor (0, data->fb_height / 2, + data->fb_width, data->fb_height / 2); + gles2->glClearColor (1.0, 0.0, 0.0, 1.0); + gles2->glClear (GL_COLOR_BUFFER_BIT); + + /* Paint the bottom half in blue */ + gles2->glScissor (0, 0, data->fb_width, data->fb_height / 2); + gles2->glClearColor (0.0, 0.0, 1.0, 1.0); + gles2->glClear (GL_COLOR_BUFFER_BIT); + + gles2->glGetFloatv (GL_SCISSOR_BOX, scissor); + g_assert_cmpfloat (scissor[0], ==, 0.0f); + g_assert_cmpfloat (scissor[1], ==, 0.0f); + g_assert_cmpfloat (scissor[2], ==, data->fb_width); + g_assert_cmpfloat (scissor[3], ==, data->fb_height / 2); +} + +static void +paint_cull (PaintData *data) +{ + const CoglGLES2Vtable *gles2 = data->gles2; + GLint front_face; + int i; + + gles2->glEnableVertexAttribArray (data->pos_location); + gles2->glEnable (GL_CULL_FACE); + + /* First time round we'll use GL_CCW as the front face so that the + * bottom quad will be culled */ + gles2->glFrontFace (GL_CCW); + gles2->glUniform4f (data->color_location, + 1.0f, 0.0f, 0.0f, 1.0f); + + gles2->glGetIntegerv (GL_FRONT_FACE, &front_face); + g_assert_cmpint (front_face, ==, GL_CCW); + + for (i = 0; i < 2; i++) + { + /* Paint both quads in the same color. One of these will be + * culled */ + gles2->glVertexAttribPointer (data->pos_location, + 2, /* size */ + GL_FLOAT, + GL_FALSE, /* not normalized */ + sizeof (float) * 2, + top_vertices); + gles2->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); + + gles2->glVertexAttribPointer (data->pos_location, + 2, /* size */ + GL_FLOAT, + GL_FALSE, /* not normalized */ + sizeof (float) * 2, + bottom_vertices); + gles2->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); + + /* Second time round we'll use GL_CW as the front face so that the + * top quad will be culled */ + gles2->glFrontFace (GL_CW); + gles2->glUniform4f (data->color_location, + 0.0f, 0.0f, 1.0f, 1.0f); + + gles2->glGetIntegerv (GL_FRONT_FACE, &front_face); + g_assert_cmpint (front_face, ==, GL_CW); + } +} + +static void +verify_read_pixels (const PaintData *data) +{ + int stride = data->fb_width * 4; + uint8_t *buf = g_malloc (data->fb_height * stride); + + data->gles2->glReadPixels (0, 0, /* x/y */ + data->fb_width, data->fb_height, + GL_RGBA, + GL_UNSIGNED_BYTE, + buf); + + /* In GL, the lines earlier in the buffer are the bottom */ + /* Bottom should be blue */ + test_utils_compare_pixel (buf + data->fb_width / 2 * 4 + + data->fb_height / 4 * stride, + 0x0000ffff); + /* Top should be red */ + test_utils_compare_pixel (buf + data->fb_width / 2 * 4 + + data->fb_height * 3 / 4 * stride, + 0xff0000ff); + + g_free (buf); +} + +void +test_gles2_context_fbo (void) +{ + static const char vertex_shader_source[] = + "attribute vec2 pos;\n" + "\n" + "void\n" + "main ()\n" + "{\n" + " gl_Position = vec4 (pos, 0.0, 1.0);\n" + "}\n"; + static const char fragment_shader_source[] = + "precision mediump float;\n" + "uniform vec4 color;\n" + "\n" + "void\n" + "main ()\n" + "{\n" + " gl_FragColor = color;\n" + "}\n"; + static const PaintMethod paint_methods[] = + { + paint_quads, + paint_viewport, + paint_scissor, + paint_cull + }; + int i; + PaintData data; + + data.fb_width = cogl_framebuffer_get_width (test_fb); + data.fb_height = cogl_framebuffer_get_height (test_fb); + + for (i = 0; i < G_N_ELEMENTS (paint_methods); i++) + { + CoglTexture *offscreen_texture; + CoglOffscreen *offscreen; + CoglPipeline *pipeline; + CoglGLES2Context *gles2_ctx; + GLuint program; + CoglError *error = NULL; + + create_gles2_context (&offscreen_texture, + &offscreen, + &pipeline, + &gles2_ctx, + &data.gles2); + + if (!cogl_push_gles2_context (test_ctx, + gles2_ctx, + offscreen, + offscreen, + &error)) + g_error ("Failed to push gles2 context: %s\n", error->message); + + program = create_program (data.gles2, + vertex_shader_source, + fragment_shader_source); + + data.gles2->glClearColor (1.0, 1.0, 0.0, 1.0); + data.gles2->glClear (GL_COLOR_BUFFER_BIT); + + data.gles2->glUseProgram (program); + + data.color_location = data.gles2->glGetUniformLocation (program, "color"); + if (data.color_location == -1) + g_error ("Couldn't find ‘color’ uniform"); + + data.pos_location = data.gles2->glGetAttribLocation (program, "pos"); + if (data.pos_location == -1) + g_error ("Couldn't find ‘pos’ attribute"); + + paint_methods[i] (&data); + + verify_read_pixels (&data); + + cogl_pop_gles2_context (test_ctx); + + cogl_object_unref (offscreen); + cogl_object_unref (gles2_ctx); + + cogl_framebuffer_draw_rectangle (test_fb, + pipeline, + -1.0f, 1.0f, + 1.0f, -1.0f); + + cogl_object_unref (pipeline); + cogl_object_unref (offscreen_texture); + + /* Top half of the framebuffer should be red */ + test_utils_check_pixel (test_fb, + data.fb_width / 2, data.fb_height / 4, + 0xff0000ff); + /* Bottom half should be blue */ + test_utils_check_pixel (test_fb, + data.fb_width / 2, data.fb_height * 3 / 4, + 0x0000ffff); + } +} + +/* Position to draw a rectangle in. The top half of this rectangle + * will be red, and the bottom will be blue */ +#define RECTANGLE_DRAW_X 10 +#define RECTANGLE_DRAW_Y 15 + +/* Position to copy the rectangle to in the destination texture */ +#define RECTANGLE_COPY_X 110 +#define RECTANGLE_COPY_Y 115 + +#define RECTANGLE_WIDTH 30 +#define RECTANGLE_HEIGHT 40 + +static void +verify_region (const CoglGLES2Vtable *gles2, + int x, + int y, + int width, + int height, + uint32_t expected_pixel) +{ + uint8_t *buf, *p; + + buf = g_malloc (width * height * 4); + + gles2->glReadPixels (x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buf); + + for (p = buf + width * height * 4; p > buf; p -= 4) + test_utils_compare_pixel (p - 4, expected_pixel); + + g_free (buf); +} + +void +test_gles2_context_copy_tex_image (void) +{ + static const char vertex_shader_source[] = + "attribute vec2 pos;\n" + "attribute vec2 tex_coord_attrib;\n" + "varying vec2 tex_coord_varying;\n" + "\n" + "void\n" + "main ()\n" + "{\n" + " gl_Position = vec4 (pos, 0.0, 1.0);\n" + " tex_coord_varying = tex_coord_attrib;\n" + "}\n"; + static const char fragment_shader_source[] = + "precision mediump float;\n" + "varying vec2 tex_coord_varying;\n" + "uniform sampler2D tex;\n" + "\n" + "void\n" + "main ()\n" + "{\n" + " gl_FragColor = texture2D (tex, tex_coord_varying);\n" + "}\n"; + static const float verts[] = + { + -1.0f, -1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, + -1.0f, 1.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f + }; + int fb_width = cogl_framebuffer_get_width (test_fb); + int fb_height = cogl_framebuffer_get_height (test_fb); + CoglTexture *offscreen_texture; + CoglOffscreen *offscreen; + CoglPipeline *pipeline; + CoglGLES2Context *gles2_ctx; + const CoglGLES2Vtable *gles2; + CoglError *error = NULL; + GLuint tex; + GLint tex_uniform_location; + GLint pos_location; + GLint tex_coord_location; + GLuint program; + + create_gles2_context (&offscreen_texture, + &offscreen, + &pipeline, + &gles2_ctx, + &gles2); + + if (!cogl_push_gles2_context (test_ctx, + gles2_ctx, + offscreen, + offscreen, + &error)) + g_error ("Failed to push gles2 context: %s\n", error->message); + + gles2->glClearColor (1.0, 1.0, 0.0, 1.0); + gles2->glClear (GL_COLOR_BUFFER_BIT); + + /* Draw a rectangle using clear and the scissor so that we don't + * have to create a shader */ + gles2->glEnable (GL_SCISSOR_TEST); + + /* Top half red */ + gles2->glScissor (RECTANGLE_DRAW_X, + RECTANGLE_DRAW_Y + RECTANGLE_HEIGHT / 2, + RECTANGLE_WIDTH, + RECTANGLE_HEIGHT / 2); + gles2->glClearColor (1.0, 0.0, 0.0, 1.0); + gles2->glClear (GL_COLOR_BUFFER_BIT); + /* Bottom half blue */ + gles2->glScissor (RECTANGLE_DRAW_X, + RECTANGLE_DRAW_Y, + RECTANGLE_WIDTH, + RECTANGLE_HEIGHT / 2); + gles2->glClearColor (0.0, 0.0, 1.0, 1.0); + gles2->glClear (GL_COLOR_BUFFER_BIT); + + /* Draw where the rectangle would be if the coordinates were flipped + * in white to make it obvious that that is the problem if the + * assertion fails */ + gles2->glScissor (RECTANGLE_DRAW_X, + fb_width - (RECTANGLE_DRAW_Y + RECTANGLE_HEIGHT), + RECTANGLE_WIDTH, + RECTANGLE_HEIGHT); + gles2->glClearColor (1.0, 1.0, 1.0, 1.0); + gles2->glClear (GL_COLOR_BUFFER_BIT); + + gles2->glDisable (GL_SCISSOR_TEST); + + /* Create a texture */ + gles2->glGenTextures (1, &tex); + gles2->glBindTexture (GL_TEXTURE_2D, tex); + gles2->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + gles2->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + /* Copy the entire framebuffer into the texture */ + gles2->glCopyTexImage2D (GL_TEXTURE_2D, + 0, /* level */ + GL_RGBA, + 0, 0, /* x/y */ + fb_width, fb_height, + 0 /* border */); + + /* Copy the rectangle into another part of the texture */ + gles2->glCopyTexSubImage2D (GL_TEXTURE_2D, + 0, /* level */ + RECTANGLE_COPY_X, + RECTANGLE_COPY_Y, + RECTANGLE_DRAW_X, + RECTANGLE_DRAW_Y, + RECTANGLE_WIDTH, + RECTANGLE_HEIGHT); + + /* Clear the framebuffer to make the test more thorough */ + gles2->glClearColor (1.0, 1.0, 0.0, 1.0); + gles2->glClear (GL_COLOR_BUFFER_BIT); + + /* Create a program to render the texture */ + program = create_program (gles2, + vertex_shader_source, + fragment_shader_source); + + pos_location = + gles2->glGetAttribLocation (program, "pos"); + if (pos_location == -1) + g_error ("Couldn't find ‘pos’ attribute"); + + tex_coord_location = + gles2->glGetAttribLocation (program, "tex_coord_attrib"); + if (tex_coord_location == -1) + g_error ("Couldn't find ‘tex_coord_attrib’ attribute"); + + tex_uniform_location = + gles2->glGetUniformLocation (program, "tex"); + if (tex_uniform_location == -1) + g_error ("Couldn't find ‘tex’ uniform"); + + gles2->glUseProgram (program); + + gles2->glUniform1i (tex_uniform_location, 0); + + /* Render the texture to fill the framebuffer */ + gles2->glEnableVertexAttribArray (pos_location); + gles2->glVertexAttribPointer (pos_location, + 2, /* n_components */ + GL_FLOAT, + FALSE, /* normalized */ + sizeof (float) * 4, + verts); + gles2->glEnableVertexAttribArray (tex_coord_location); + gles2->glVertexAttribPointer (tex_coord_location, + 2, /* n_components */ + GL_FLOAT, + FALSE, /* normalized */ + sizeof (float) * 4, + verts + 2); + + gles2->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); + + /* Verify top of drawn rectangle is red */ + verify_region (gles2, + RECTANGLE_DRAW_X, + RECTANGLE_DRAW_Y + RECTANGLE_HEIGHT / 2, + RECTANGLE_WIDTH, + RECTANGLE_HEIGHT / 2, + 0xff0000ff); + /* Verify bottom of drawn rectangle is blue */ + verify_region (gles2, + RECTANGLE_DRAW_X, + RECTANGLE_DRAW_Y, + RECTANGLE_WIDTH, + RECTANGLE_HEIGHT / 2, + 0x0000ffff); + /* Verify top of copied rectangle is red */ + verify_region (gles2, + RECTANGLE_COPY_X, + RECTANGLE_COPY_Y + RECTANGLE_HEIGHT / 2, + RECTANGLE_WIDTH, + RECTANGLE_HEIGHT / 2, + 0xff0000ff); + /* Verify bottom of copied rectangle is blue */ + verify_region (gles2, + RECTANGLE_COPY_X, + RECTANGLE_COPY_Y, + RECTANGLE_WIDTH, + RECTANGLE_HEIGHT / 2, + 0x0000ffff); + + cogl_pop_gles2_context (test_ctx); + + cogl_object_unref (offscreen); + cogl_object_unref (gles2_ctx); + cogl_object_unref (pipeline); + cogl_object_unref (offscreen_texture); +} diff --git a/cogl/tests/conform/test-just-vertex-shader.c b/cogl/tests/conform/test-just-vertex-shader.c new file mode 100644 index 0000000..60fcaf7 --- /dev/null +++ b/cogl/tests/conform/test-just-vertex-shader.c @@ -0,0 +1,205 @@ +#define COGL_VERSION_MIN_REQUIRED COGL_VERSION_1_0 + +#include + +#include + +#include "test-utils.h" + +typedef struct _TestState +{ + int paddiing; +} TestState; + +static CoglTexture * +create_dummy_texture (void) +{ + /* Create a dummy 1x1 green texture to replace the color from the + vertex shader */ + static const uint8_t data[4] = { 0x00, 0xff, 0x00, 0xff }; + + return test_utils_texture_new_from_data (test_ctx, + 1, 1, /* size */ + TEST_UTILS_TEXTURE_NONE, + COGL_PIXEL_FORMAT_RGB_888, + 4, /* rowstride */ + data); +} + +static void +paint_legacy (TestState *state) +{ + CoglHandle material = cogl_material_new (); + CoglTexture *tex; + CoglColor color; + CoglError *error = NULL; + CoglHandle shader, program; + + cogl_color_init_from_4ub (&color, 0, 0, 0, 255); + cogl_clear (&color, COGL_BUFFER_BIT_COLOR); + + /* Set the primary vertex color as red */ + cogl_color_set_from_4ub (&color, 0xff, 0x00, 0x00, 0xff); + cogl_material_set_color (material, &color); + + /* Override the vertex color in the texture environment with a + constant green color provided by a texture */ + tex = create_dummy_texture (); + cogl_material_set_layer (material, 0, tex); + cogl_object_unref (tex); + if (!cogl_material_set_layer_combine (material, 0, + "RGBA=REPLACE(TEXTURE)", + &error)) + { + g_warning ("Error setting layer combine: %s", error->message); + g_assert_not_reached (); + } + + /* Set up a dummy vertex shader that does nothing but the usual + fixed function transform */ + shader = cogl_create_shader (COGL_SHADER_TYPE_VERTEX); + cogl_shader_source (shader, + "void\n" + "main ()\n" + "{\n" + " cogl_position_out = " + "cogl_modelview_projection_matrix * " + "cogl_position_in;\n" + " cogl_color_out = cogl_color_in;\n" + " cogl_tex_coord_out[0] = cogl_tex_coord_in;\n" + "}\n"); + cogl_shader_compile (shader); + if (!cogl_shader_is_compiled (shader)) + { + char *log = cogl_shader_get_info_log (shader); + g_warning ("Shader compilation failed:\n%s", log); + g_free (log); + g_assert_not_reached (); + } + + program = cogl_create_program (); + cogl_program_attach_shader (program, shader); + cogl_program_link (program); + + cogl_handle_unref (shader); + + /* Draw something using the material */ + cogl_set_source (material); + cogl_rectangle (0, 0, 50, 50); + + /* Draw it again using the program. It should look exactly the same */ + cogl_program_use (program); + cogl_rectangle (50, 0, 100, 50); + cogl_program_use (COGL_INVALID_HANDLE); + + cogl_handle_unref (material); + cogl_handle_unref (program); +} + +static void +paint (TestState *state) +{ + CoglPipeline *pipeline = cogl_pipeline_new (test_ctx); + CoglTexture *tex; + CoglColor color; + CoglError *error = NULL; + CoglHandle shader, program; + + cogl_color_init_from_4ub (&color, 0, 0, 0, 255); + cogl_clear (&color, COGL_BUFFER_BIT_COLOR); + + /* Set the primary vertex color as red */ + cogl_color_set_from_4ub (&color, 0xff, 0x00, 0x00, 0xff); + cogl_pipeline_set_color (pipeline, &color); + + /* Override the vertex color in the texture environment with a + constant green color provided by a texture */ + tex = create_dummy_texture (); + cogl_pipeline_set_layer_texture (pipeline, 0, tex); + cogl_object_unref (tex); + if (!cogl_pipeline_set_layer_combine (pipeline, 0, + "RGBA=REPLACE(TEXTURE)", + &error)) + { + g_warning ("Error setting layer combine: %s", error->message); + g_assert_not_reached (); + } + + /* Set up a dummy vertex shader that does nothing but the usual + fixed function transform */ + shader = cogl_create_shader (COGL_SHADER_TYPE_VERTEX); + cogl_shader_source (shader, + "void\n" + "main ()\n" + "{\n" + " cogl_position_out = " + "cogl_modelview_projection_matrix * " + "cogl_position_in;\n" + " cogl_color_out = cogl_color_in;\n" + " cogl_tex_coord_out[0] = cogl_tex_coord_in;\n" + "}\n"); + cogl_shader_compile (shader); + if (!cogl_shader_is_compiled (shader)) + { + char *log = cogl_shader_get_info_log (shader); + g_warning ("Shader compilation failed:\n%s", log); + g_free (log); + g_assert_not_reached (); + } + + program = cogl_create_program (); + cogl_program_attach_shader (program, shader); + cogl_program_link (program); + + cogl_handle_unref (shader); + + /* Draw something without the program */ + cogl_set_source (pipeline); + cogl_rectangle (0, 0, 50, 50); + + /* Draw it again using the program. It should look exactly the same */ + cogl_pipeline_set_user_program (pipeline, program); + cogl_handle_unref (program); + + cogl_rectangle (50, 0, 100, 50); + cogl_pipeline_set_user_program (pipeline, COGL_INVALID_HANDLE); + + cogl_object_unref (pipeline); +} + +static void +validate_result (CoglFramebuffer *framebuffer) +{ + /* Non-shader version */ + test_utils_check_pixel (framebuffer, 25, 25, 0x00ff0000); + /* Shader version */ + test_utils_check_pixel (framebuffer, 75, 25, 0x00ff0000); +} + +void +test_just_vertex_shader (void) +{ + TestState state; + + cogl_framebuffer_orthographic (test_fb, + 0, 0, + cogl_framebuffer_get_width (test_fb), + cogl_framebuffer_get_height (test_fb), + -1, + 100); + + /* XXX: we have to push/pop a framebuffer since this test currently + * uses the legacy cogl_rectangle() api. */ + cogl_push_framebuffer (test_fb); + + paint_legacy (&state); + validate_result (test_fb); + + paint (&state); + validate_result (test_fb); + + cogl_pop_framebuffer (); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} diff --git a/cogl/tests/conform/test-layer-remove.c b/cogl/tests/conform/test-layer-remove.c new file mode 100644 index 0000000..de1efec --- /dev/null +++ b/cogl/tests/conform/test-layer-remove.c @@ -0,0 +1,145 @@ +#include + +#include "test-utils.h" + +#define TEST_SQUARE_SIZE 10 + +static CoglPipeline * +create_two_layer_pipeline (void) +{ + CoglPipeline *pipeline = cogl_pipeline_new (test_ctx); + CoglColor color; + + /* The pipeline is initially black */ + cogl_pipeline_set_color4ub (pipeline, 0, 0, 0, 255); + + /* The first layer adds a full red component */ + cogl_color_init_from_4ub (&color, 255, 0, 0, 255); + cogl_pipeline_set_layer_combine_constant (pipeline, 0, &color); + cogl_pipeline_set_layer_combine (pipeline, + 0, /* layer_num */ + "RGBA=ADD(PREVIOUS,CONSTANT)", + NULL); + + /* The second layer adds a full green component */ + cogl_color_init_from_4ub (&color, 0, 255, 0, 255); + cogl_pipeline_set_layer_combine_constant (pipeline, 1, &color); + cogl_pipeline_set_layer_combine (pipeline, + 1, /* layer_num */ + "RGBA=ADD(PREVIOUS,CONSTANT)", + NULL); + + return pipeline; +} + +static void +test_color (CoglPipeline *pipeline, + uint32_t color, + int pos) +{ + cogl_framebuffer_draw_rectangle (test_fb, + pipeline, + pos * TEST_SQUARE_SIZE, + 0, + pos * TEST_SQUARE_SIZE + TEST_SQUARE_SIZE, + TEST_SQUARE_SIZE); + test_utils_check_pixel (test_fb, + pos * TEST_SQUARE_SIZE + TEST_SQUARE_SIZE / 2, + TEST_SQUARE_SIZE / 2, + color); +} + +void +test_layer_remove (void) +{ + CoglPipeline *pipeline0, *pipeline1; + CoglColor color; + int pos = 0; + + cogl_framebuffer_orthographic (test_fb, + 0, 0, + cogl_framebuffer_get_width (test_fb), + cogl_framebuffer_get_height (test_fb), + -1, + 100); + + /** TEST 1 **/ + /* Basic sanity check that the pipeline combines the two colors + * together properly */ + pipeline0 = create_two_layer_pipeline (); + test_color (pipeline0, 0xffff00ff, pos++); + cogl_object_unref (pipeline0); + + /** TEST 2 **/ + /* Check that we can remove the second layer */ + pipeline0 = create_two_layer_pipeline (); + cogl_pipeline_remove_layer (pipeline0, 1); + test_color (pipeline0, 0xff0000ff, pos++); + cogl_object_unref (pipeline0); + + /** TEST 3 **/ + /* Check that we can remove the first layer */ + pipeline0 = create_two_layer_pipeline (); + cogl_pipeline_remove_layer (pipeline0, 0); + test_color (pipeline0, 0x00ff00ff, pos++); + cogl_object_unref (pipeline0); + + /** TEST 4 **/ + /* Check that we can make a copy and remove a layer from the + * original pipeline */ + pipeline0 = create_two_layer_pipeline (); + pipeline1 = cogl_pipeline_copy (pipeline0); + cogl_pipeline_remove_layer (pipeline0, 1); + test_color (pipeline0, 0xff0000ff, pos++); + test_color (pipeline1, 0xffff00ff, pos++); + cogl_object_unref (pipeline0); + cogl_object_unref (pipeline1); + + /** TEST 5 **/ + /* Check that we can make a copy and remove the second layer from the + * new pipeline */ + pipeline0 = create_two_layer_pipeline (); + pipeline1 = cogl_pipeline_copy (pipeline0); + cogl_pipeline_remove_layer (pipeline1, 1); + test_color (pipeline0, 0xffff00ff, pos++); + test_color (pipeline1, 0xff0000ff, pos++); + cogl_object_unref (pipeline0); + cogl_object_unref (pipeline1); + + /** TEST 6 **/ + /* Check that we can make a copy and remove the first layer from the + * new pipeline */ + pipeline0 = create_two_layer_pipeline (); + pipeline1 = cogl_pipeline_copy (pipeline0); + cogl_pipeline_remove_layer (pipeline1, 0); + test_color (pipeline0, 0xffff00ff, pos++); + test_color (pipeline1, 0x00ff00ff, pos++); + cogl_object_unref (pipeline0); + cogl_object_unref (pipeline1); + + /** TEST 7 **/ + /* Check that we can modify a layer in a child pipeline */ + pipeline0 = create_two_layer_pipeline (); + pipeline1 = cogl_pipeline_copy (pipeline0); + cogl_color_init_from_4ub (&color, 0, 0, 255, 255); + cogl_pipeline_set_layer_combine_constant (pipeline1, 0, &color); + test_color (pipeline0, 0xffff00ff, pos++); + test_color (pipeline1, 0x00ffffff, pos++); + cogl_object_unref (pipeline0); + cogl_object_unref (pipeline1); + + /** TEST 8 **/ + /* Check that we can modify a layer in a child pipeline but then remove it */ + pipeline0 = create_two_layer_pipeline (); + pipeline1 = cogl_pipeline_copy (pipeline0); + cogl_color_init_from_4ub (&color, 0, 0, 255, 255); + cogl_pipeline_set_layer_combine_constant (pipeline1, 0, &color); + cogl_pipeline_remove_layer (pipeline1, 0); + test_color (pipeline0, 0xffff00ff, pos++); + test_color (pipeline1, 0x00ff00ff, pos++); + cogl_object_unref (pipeline0); + cogl_object_unref (pipeline1); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} diff --git a/cogl/tests/conform/test-map-buffer-range.c b/cogl/tests/conform/test-map-buffer-range.c new file mode 100644 index 0000000..e979240 --- /dev/null +++ b/cogl/tests/conform/test-map-buffer-range.c @@ -0,0 +1,123 @@ +#include + +#include + +#include "test-utils.h" + +static uint8_t +tex_data[2 * 2 * 4] = + { + 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff + }; + +/* Vertex data for a quad with all of the texture coordinates set to + * the top left (red) pixel */ +static CoglVertexP2T2 +vertex_data[4] = + { + { -1, -1, 0, 0 }, + { 1, -1, 0, 0 }, + { -1, 1, 0, 0 }, + { 1, 1, 0, 0 } + }; + +void +test_map_buffer_range (void) +{ + CoglTexture2D *tex; + CoglPipeline *pipeline; + int fb_width, fb_height; + CoglAttributeBuffer *buffer; + CoglVertexP2T2 *data; + CoglAttribute *pos_attribute; + CoglAttribute *tex_coord_attribute; + CoglPrimitive *primitive; + + tex = cogl_texture_2d_new_from_data (test_ctx, + 2, 2, /* width/height */ + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + 2 * 4, /* rowstride */ + tex_data, + NULL /* error */); + + pipeline = cogl_pipeline_new (test_ctx); + + cogl_pipeline_set_layer_texture (pipeline, 0, tex); + cogl_pipeline_set_layer_filters (pipeline, + 0, /* layer */ + COGL_PIPELINE_FILTER_NEAREST, + COGL_PIPELINE_FILTER_NEAREST); + cogl_pipeline_set_layer_wrap_mode (pipeline, + 0, /* layer */ + COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); + + fb_width = cogl_framebuffer_get_width (test_fb); + fb_height = cogl_framebuffer_get_height (test_fb); + + buffer = cogl_attribute_buffer_new (test_ctx, + sizeof (vertex_data), + vertex_data); + + /* Replace the texture coordinates of the third vertex with the + * coordinates for a green texel */ + data = cogl_buffer_map_range (buffer, + sizeof (vertex_data[0]) * 2, + sizeof (vertex_data[0]), + COGL_BUFFER_ACCESS_WRITE, + COGL_BUFFER_MAP_HINT_DISCARD_RANGE, + NULL); /* don't catch errors */ + g_assert (data != NULL); + + data->x = vertex_data[2].x; + data->y = vertex_data[2].y; + data->s = 1.0f; + data->t = 0.0f; + + cogl_buffer_unmap (buffer); + + pos_attribute = + cogl_attribute_new (buffer, + "cogl_position_in", + sizeof (vertex_data[0]), + offsetof (CoglVertexP2T2, x), + 2, /* n_components */ + COGL_ATTRIBUTE_TYPE_FLOAT); + tex_coord_attribute = + cogl_attribute_new (buffer, + "cogl_tex_coord_in", + sizeof (vertex_data[0]), + offsetof (CoglVertexP2T2, s), + 2, /* n_components */ + COGL_ATTRIBUTE_TYPE_FLOAT); + + cogl_framebuffer_clear4f (test_fb, + COGL_BUFFER_BIT_COLOR, + 0, 0, 0, 1); + + primitive = + cogl_primitive_new (COGL_VERTICES_MODE_TRIANGLE_STRIP, + 4, /* n_vertices */ + pos_attribute, + tex_coord_attribute, + NULL); + cogl_primitive_draw (primitive, test_fb, pipeline); + cogl_object_unref (primitive); + + /* Top left pixel should be the one that is replaced to be green */ + test_utils_check_pixel (test_fb, 1, 1, 0x00ff00ff); + /* The other three corners should be left as red */ + test_utils_check_pixel (test_fb, fb_width - 2, 1, 0xff0000ff); + test_utils_check_pixel (test_fb, 1, fb_height - 2, 0xff0000ff); + test_utils_check_pixel (test_fb, fb_width - 2, fb_height - 2, 0xff0000ff); + + cogl_object_unref (buffer); + cogl_object_unref (pos_attribute); + cogl_object_unref (tex_coord_attribute); + + cogl_object_unref (pipeline); + cogl_object_unref (tex); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} diff --git a/cogl/tests/conform/test-no-gl-header.c b/cogl/tests/conform/test-no-gl-header.c new file mode 100644 index 0000000..9618d84 --- /dev/null +++ b/cogl/tests/conform/test-no-gl-header.c @@ -0,0 +1,16 @@ +#undef COGL_COMPILATION +#include + +/* If you just include cogl/cogl.h, you shouldn't end up including any + GL headers */ +#ifdef GL_TRUE +#error "Including cogl.h shouldn't be including any GL headers" +#endif + +void test_no_gl_header (void); + +void +test_no_gl_header (void) +{ +} + diff --git a/cogl/tests/conform/test-npot-texture.c b/cogl/tests/conform/test-npot-texture.c new file mode 100644 index 0000000..85c16c9 --- /dev/null +++ b/cogl/tests/conform/test-npot-texture.c @@ -0,0 +1,170 @@ +#include + +#include + +#include "test-utils.h" + +/* Non-power-of-two sized texture that should cause slicing */ +#define TEXTURE_SIZE 384 +/* Number of times to split the texture up on each axis */ +#define PARTS 2 +/* The texture is split into four parts, each with a different colour */ +#define PART_SIZE (TEXTURE_SIZE / PARTS) + +/* Amount of pixels to skip off the top, bottom, left and right of the + texture when reading back the stage */ +#define TEST_INSET 4 + +/* Size to actually render the texture at */ +#define TEXTURE_RENDER_SIZE TEXTURE_SIZE +/* The size of a part once rendered */ +#define PART_RENDER_SIZE (TEXTURE_RENDER_SIZE / PARTS) + +static const uint32_t corner_colors[PARTS * PARTS] = + { + /* Top left - red */ 0xff0000ff, + /* Top right - green */ 0x00ff00ff, + /* Bottom left - blue */ 0x0000ffff, + /* Bottom right - yellow */ 0xffff00ff + }; + +static void +validate_part (int xnum, + int ynum, + uint32_t color) +{ + test_utils_check_region (test_fb, + xnum * PART_RENDER_SIZE + TEST_INSET, + ynum * PART_RENDER_SIZE + TEST_INSET, + PART_RENDER_SIZE - TEST_INSET * 2, + PART_RENDER_SIZE - TEST_INSET * 2, + color); +} + +static void +validate_result (void) +{ + /* Validate that all four corners of the texture are drawn in the + right color */ + validate_part (0, 0, corner_colors[0]); + validate_part (1, 0, corner_colors[1]); + validate_part (0, 1, corner_colors[2]); + validate_part (1, 1, corner_colors[3]); +} + +static CoglTexture * +make_texture (void) +{ + void *tex_data; + uint32_t *p; + CoglTexture *tex; + int partx, party, width, height; + + p = tex_data = g_malloc (TEXTURE_SIZE * TEXTURE_SIZE * 4); + + /* Make a texture with a different color for each part */ + for (party = 0; party < PARTS; party++) + { + height = (party < PARTS - 1 + ? PART_SIZE + : TEXTURE_SIZE - PART_SIZE * (PARTS - 1)); + + for (partx = 0; partx < PARTS; partx++) + { + uint32_t color = corner_colors[party * PARTS + partx]; + width = (partx < PARTS - 1 + ? PART_SIZE + : TEXTURE_SIZE - PART_SIZE * (PARTS - 1)); + + while (width-- > 0) + *(p++) = GUINT32_TO_BE (color); + } + + while (--height > 0) + { + memcpy (p, p - TEXTURE_SIZE, TEXTURE_SIZE * 4); + p += TEXTURE_SIZE; + } + } + + tex = test_utils_texture_new_from_data (test_ctx, + TEXTURE_SIZE, + TEXTURE_SIZE, + TEST_UTILS_TEXTURE_NO_ATLAS, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + TEXTURE_SIZE * 4, + tex_data); + + g_free (tex_data); + + if (cogl_test_verbose ()) + { + if (cogl_texture_is_sliced (tex)) + g_print ("Texture is sliced\n"); + else + g_print ("Texture is not sliced\n"); + } + + /* The texture should be sliced unless NPOTs are supported */ + g_assert (cogl_has_feature (test_ctx, COGL_FEATURE_ID_TEXTURE_NPOT) + ? !cogl_texture_is_sliced (tex) + : cogl_texture_is_sliced (tex)); + + return tex; +} + +static void +paint (void) +{ + CoglPipeline *pipeline = cogl_pipeline_new (test_ctx); + CoglTexture *texture = make_texture (); + int y, x; + + cogl_pipeline_set_layer_texture (pipeline, 0, texture); + + /* Just render the texture in the top left corner */ + /* Render the texture using four separate rectangles */ + for (y = 0; y < 2; y++) + for (x = 0; x < 2; x++) + cogl_framebuffer_draw_textured_rectangle (test_fb, + pipeline, + x * TEXTURE_RENDER_SIZE / 2, + y * TEXTURE_RENDER_SIZE / 2, + (x + 1) * + TEXTURE_RENDER_SIZE / 2, + (y + 1) * + TEXTURE_RENDER_SIZE / 2, + x / 2.0f, + y / 2.0f, + (x + 1) / 2.0f, + (y + 1) / 2.0f); + + cogl_object_unref (pipeline); + cogl_object_unref (texture); +} + +void +test_npot_texture (void) +{ + if (cogl_test_verbose ()) + { + if (cogl_has_feature (test_ctx, COGL_FEATURE_ID_TEXTURE_NPOT)) + g_print ("NPOT textures are supported\n"); + else + g_print ("NPOT textures are not supported\n"); + } + + cogl_framebuffer_orthographic (test_fb, + 0, 0, + cogl_framebuffer_get_width (test_fb), + cogl_framebuffer_get_height (test_fb), + -1, + 100); + + paint (); + validate_result (); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} + diff --git a/cogl/tests/conform/test-offscreen.c b/cogl/tests/conform/test-offscreen.c new file mode 100644 index 0000000..9bc14b7 --- /dev/null +++ b/cogl/tests/conform/test-offscreen.c @@ -0,0 +1,199 @@ +#define COGL_VERSION_MIN_REQUIRED COGL_VERSION_1_0 + +#include + +#include "test-utils.h" + +#define RED 0 +#define GREEN 1 +#define BLUE 2 + +typedef struct _TestState +{ + int fb_width; + int fb_height; +} TestState; + +static void +check_quadrant (TestState *state, + int qx, + int qy, + uint32_t expected_rgba) +{ + /* The quadrants are all stuffed into the top right corner of the + framebuffer */ + int x = state->fb_width * qx / 4 + state->fb_width / 2; + int y = state->fb_height * qy / 4; + int width = state->fb_width / 4; + int height = state->fb_height / 4; + + /* Subtract a two-pixel gap around the edges to allow some rounding + differences */ + x += 2; + y += 2; + width -= 4; + height -= 4; + + test_utils_check_region (test_fb, x, y, width, height, expected_rgba); +} + +static void +test_paint (TestState *state) +{ + CoglTexture2D *tex_2d; + CoglTexture *tex; + CoglOffscreen *offscreen; + + tex_2d = cogl_texture_2d_new_with_size (test_ctx, + state->fb_width, + state->fb_height); + tex = tex_2d; + + offscreen = cogl_offscreen_new_with_texture (tex); + + /* Set a scale and translate transform on the window framebuffer + * before switching to the offscreen framebuffer so we can verify it + * gets restored when we switch back + * + * The test is going to draw a grid of 4 colors to a texture which + * we subsequently draw to the window with a fullscreen rectangle. + * This transform will flip the texture left to right, scale it to a + * quarter of the window size and slide it to the top right of the + * window. + */ + cogl_push_matrix (); + cogl_translate (0.5, 0.5, 0); + cogl_scale (-0.5, 0.5, 1); + + cogl_push_framebuffer (offscreen); + + /* Cogl should release the last reference when we call cogl_pop_framebuffer() + */ + cogl_object_unref (offscreen); + + /* Setup something other than the identity matrix for the modelview so we can + * verify it gets restored when we call cogl_pop_framebuffer () */ + cogl_scale (2, 2, 1); + + /* red, top left */ + cogl_set_source_color4ub (0xff, 0x00, 0x00, 0xff); + cogl_rectangle (-0.5, 0.5, 0, 0); + /* green, top right */ + cogl_set_source_color4ub (0x00, 0xff, 0x00, 0xff); + cogl_rectangle (0, 0.5, 0.5, 0); + /* blue, bottom left */ + cogl_set_source_color4ub (0x00, 0x00, 0xff, 0xff); + cogl_rectangle (-0.5, 0, 0, -0.5); + /* white, bottom right */ + cogl_set_source_color4ub (0xff, 0xff, 0xff, 0xff); + cogl_rectangle (0, 0, 0.5, -0.5); + + cogl_pop_framebuffer (); + + cogl_set_source_texture (tex); + cogl_rectangle (-1, 1, 1, -1); + + cogl_object_unref (tex_2d); + + cogl_pop_matrix (); + + /* NB: The texture is drawn flipped horizontally and scaled to fit in the + * top right corner of the window. */ + + /* red, top right */ + check_quadrant (state, 1, 0, 0xff0000ff); + /* green, top left */ + check_quadrant (state, 0, 0, 0x00ff00ff); + /* blue, bottom right */ + check_quadrant (state, 1, 1, 0x0000ffff); + /* white, bottom left */ + check_quadrant (state, 0, 1, 0xffffffff); +} + +static void +test_flush (TestState *state) +{ + CoglTexture2D *tex_2d; + CoglTexture *tex; + CoglOffscreen *offscreen; + CoglColor clear_color; + int i; + + for (i = 0; i < 3; i++) + { + /* This tests that rendering to a framebuffer and then reading back + the contents of the texture will automatically flush the + journal */ + + tex_2d = cogl_texture_2d_new_with_size (test_ctx, + 16, 16); /* width/height */ + tex = tex_2d; + + offscreen = cogl_offscreen_new_with_texture (tex); + + cogl_push_framebuffer (offscreen); + + cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 255); + cogl_clear (&clear_color, COGL_BUFFER_BIT_COLOR); + + cogl_set_source_color4ub (255, 0, 0, 255); + cogl_rectangle (-1, -1, 1, 1); + + if (i == 0) + /* First time check using read pixels on the offscreen */ + test_utils_check_region (offscreen, + 1, 1, 15, 15, 0xff0000ff); + else if (i == 1) + { + uint8_t data[16 * 4 * 16]; + int x, y; + + /* Second time try reading back the texture contents */ + cogl_texture_get_data (tex, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + 16 * 4, /* rowstride */ + data); + + for (y = 1; y < 15; y++) + for (x = 1; x < 15; x++) + test_utils_compare_pixel (data + x * 4 + y * 16 * 4, + 0xff0000ff); + } + + cogl_pop_framebuffer (); + + if (i == 2) + { + /* Third time try drawing the texture to the screen */ + cogl_set_source_texture (tex); + cogl_rectangle (-1, -1, 1, 1); + test_utils_check_region (test_fb, + 2, 2, /* x/y */ + state->fb_width - 4, + state->fb_height - 4, + 0xff0000ff); + } + + cogl_object_unref (tex_2d); + cogl_object_unref (offscreen); + } +} + +void +test_offscreen (void) +{ + TestState state; + + state.fb_width = cogl_framebuffer_get_width (test_fb); + state.fb_height = cogl_framebuffer_get_height (test_fb); + + /* XXX: we have to push/pop a framebuffer since this test currently + * uses the legacy cogl_rectangle() api. */ + cogl_push_framebuffer (test_fb); + test_paint (&state); + test_flush (&state); + cogl_pop_framebuffer (); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} diff --git a/cogl/tests/conform/test-path-clip.c b/cogl/tests/conform/test-path-clip.c new file mode 100644 index 0000000..ec21061 --- /dev/null +++ b/cogl/tests/conform/test-path-clip.c @@ -0,0 +1,67 @@ +#include +#include + +#include + +#include "test-utils.h" + +void +test_path_clip (void) +{ + CoglPath *path; + CoglPipeline *pipeline; + int fb_width, fb_height; + + fb_width = cogl_framebuffer_get_width (test_fb); + fb_height = cogl_framebuffer_get_height (test_fb); + + cogl_framebuffer_orthographic (test_fb, + 0, 0, fb_width, fb_height, -1, 100); + + path = cogl_path_new (); + + cogl_framebuffer_clear4f (test_fb, + COGL_BUFFER_BIT_COLOR, + 1.0f, 0.0f, 0.0f, 1.0f); + + /* Make an L-shape with the top right corner left untouched */ + cogl_path_move_to (path, 0, fb_height); + cogl_path_line_to (path, fb_width, fb_height); + cogl_path_line_to (path, fb_width, fb_height / 2); + cogl_path_line_to (path, fb_width / 2, fb_height / 2); + cogl_path_line_to (path, fb_width / 2, 0); + cogl_path_line_to (path, 0, 0); + cogl_path_close (path); + + cogl_framebuffer_push_path_clip (test_fb, path); + + /* Try to fill the framebuffer with a blue rectangle. This should be + * clipped to leave the top right quadrant as is */ + pipeline = cogl_pipeline_new (test_ctx); + cogl_pipeline_set_color4ub (pipeline, 0, 0, 255, 255); + cogl_framebuffer_draw_rectangle (test_fb, + pipeline, + 0, 0, fb_width, fb_height); + + cogl_framebuffer_pop_clip (test_fb); + + cogl_object_unref (pipeline); + cogl_object_unref (path); + + /* Check each of the four quadrants */ + test_utils_check_pixel (test_fb, + fb_width / 4, fb_height / 4, + 0x0000ffff); + test_utils_check_pixel (test_fb, + fb_width * 3 / 4, fb_height / 4, + 0xff0000ff); + test_utils_check_pixel (test_fb, + fb_width / 4, fb_height * 3 / 4, + 0x0000ffff); + test_utils_check_pixel (test_fb, + fb_width * 3 / 4, fb_height * 3 / 4, + 0x0000ffff); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} diff --git a/cogl/tests/conform/test-path.c b/cogl/tests/conform/test-path.c new file mode 100644 index 0000000..65cebfe --- /dev/null +++ b/cogl/tests/conform/test-path.c @@ -0,0 +1,214 @@ +#include +#include + +#include + +#include "test-utils.h" + +#define BLOCK_SIZE 16 + +/* Number of pixels at the border of a block quadrant to skip when verifying */ +#define TEST_INSET 1 + +typedef struct _TestState +{ + int dummy; +} TestState; + +static void +draw_path_at (CoglPath *path, CoglPipeline *pipeline, int x, int y) +{ + cogl_framebuffer_push_matrix (test_fb); + cogl_framebuffer_translate (test_fb, x * BLOCK_SIZE, y * BLOCK_SIZE, 0.0f); + + cogl_set_framebuffer (test_fb); + cogl_set_source (pipeline); + cogl_path_fill (path); + + cogl_framebuffer_pop_matrix (test_fb); +} + +static void +check_block (int block_x, int block_y, int block_mask) +{ + uint32_t data[BLOCK_SIZE * BLOCK_SIZE]; + int qx, qy; + + /* Block mask represents which quarters of the block should be + filled. The bits from 0->3 represent the top left, top right, + bottom left and bottom right respectively */ + + cogl_framebuffer_read_pixels (test_fb, + block_x * BLOCK_SIZE, + block_y * BLOCK_SIZE, + BLOCK_SIZE, BLOCK_SIZE, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + (uint8_t *)data); + + for (qy = 0; qy < 2; qy++) + for (qx = 0; qx < 2; qx++) + { + int bit = qx | (qy << 1); + const char *intended_pixel = ((block_mask & (1 << bit)) ? "#ffffff" : "#000000"); + int x, y; + + for (x = 0; x < BLOCK_SIZE / 2 - TEST_INSET * 2; x++) + for (y = 0; y < BLOCK_SIZE / 2 - TEST_INSET * 2; y++) + { + const uint32_t *p = data + (qx * BLOCK_SIZE / 2 + + qy * BLOCK_SIZE * BLOCK_SIZE / 2 + + (x + TEST_INSET) + + (y + TEST_INSET) * BLOCK_SIZE); + char *screen_pixel = g_strdup_printf ("#%06x", GUINT32_FROM_BE (*p) >> 8); + g_assert_cmpstr (screen_pixel, ==, intended_pixel); + g_free (screen_pixel); + } + } +} + +static void +paint (TestState *state) +{ + CoglPath *path_a, *path_b, *path_c; + CoglPipeline *white = cogl_pipeline_new (test_ctx); + + cogl_pipeline_set_color4f (white, 1, 1, 1, 1); + + /* Create a path filling just a quarter of a block. It will use two + rectangles so that we have a sub path in the path */ + path_a = cogl_path_new (); + cogl_path_rectangle (path_a, + BLOCK_SIZE * 3 / 4, BLOCK_SIZE / 2, + BLOCK_SIZE, BLOCK_SIZE); + cogl_path_rectangle (path_a, + BLOCK_SIZE / 2, BLOCK_SIZE / 2, + BLOCK_SIZE * 3 / 4, BLOCK_SIZE); + draw_path_at (path_a, white, 0, 0); + + /* Create another path filling the whole block */ + path_b = cogl_path_new (); + cogl_path_rectangle (path_b, 0, 0, BLOCK_SIZE, BLOCK_SIZE); + draw_path_at (path_b, white, 1, 0); + + /* Draw the first path again */ + draw_path_at (path_a, white, 2, 0); + + /* Draw a copy of path a */ + path_c = cogl_path_copy (path_a); + draw_path_at (path_c, white, 3, 0); + + /* Add another rectangle to path a. We'll use line_to's instead of + cogl_rectangle so that we don't create another sub-path because + that is more likely to break the copy */ + cogl_path_line_to (path_a, 0, BLOCK_SIZE / 2); + cogl_path_line_to (path_a, 0, 0); + cogl_path_line_to (path_a, BLOCK_SIZE / 2, 0); + cogl_path_line_to (path_a, BLOCK_SIZE / 2, BLOCK_SIZE / 2); + draw_path_at (path_a, white, 4, 0); + + /* Draw the copy again. It should not have changed */ + draw_path_at (path_c, white, 5, 0); + + /* Add another rectangle to path c. It will be added in two halves, + one as an extension of the previous path and the other as a new + sub path */ + cogl_path_line_to (path_c, BLOCK_SIZE / 2, 0); + cogl_path_line_to (path_c, BLOCK_SIZE * 3 / 4, 0); + cogl_path_line_to (path_c, BLOCK_SIZE * 3 / 4, BLOCK_SIZE / 2); + cogl_path_line_to (path_c, BLOCK_SIZE / 2, BLOCK_SIZE / 2); + cogl_path_rectangle (path_c, + BLOCK_SIZE * 3 / 4, 0, BLOCK_SIZE, BLOCK_SIZE / 2); + draw_path_at (path_c, white, 6, 0); + + /* Draw the original path again. It should not have changed */ + draw_path_at (path_a, white, 7, 0); + + cogl_object_unref (path_a); + cogl_object_unref (path_b); + cogl_object_unref (path_c); + + /* Draw a self-intersecting path. The part that intersects should be + inverted */ + path_a = cogl_path_new (); + cogl_path_rectangle (path_a, 0, 0, BLOCK_SIZE, BLOCK_SIZE); + cogl_path_line_to (path_a, 0, BLOCK_SIZE / 2); + cogl_path_line_to (path_a, BLOCK_SIZE / 2, BLOCK_SIZE / 2); + cogl_path_line_to (path_a, BLOCK_SIZE / 2, 0); + cogl_path_close (path_a); + draw_path_at (path_a, white, 8, 0); + cogl_object_unref (path_a); + + /* Draw two sub paths. Where the paths intersect it should be + inverted */ + path_a = cogl_path_new (); + cogl_path_rectangle (path_a, 0, 0, BLOCK_SIZE, BLOCK_SIZE); + cogl_path_rectangle (path_a, + BLOCK_SIZE / 2, BLOCK_SIZE / 2, BLOCK_SIZE, BLOCK_SIZE); + draw_path_at (path_a, white, 9, 0); + cogl_object_unref (path_a); + + /* Draw a clockwise outer path */ + path_a = cogl_path_new (); + cogl_path_move_to (path_a, 0, 0); + cogl_path_line_to (path_a, BLOCK_SIZE, 0); + cogl_path_line_to (path_a, BLOCK_SIZE, BLOCK_SIZE); + cogl_path_line_to (path_a, 0, BLOCK_SIZE); + cogl_path_close (path_a); + /* Add a clockwise sub path in the upper left quadrant */ + cogl_path_move_to (path_a, 0, 0); + cogl_path_line_to (path_a, BLOCK_SIZE / 2, 0); + cogl_path_line_to (path_a, BLOCK_SIZE / 2, BLOCK_SIZE / 2); + cogl_path_line_to (path_a, 0, BLOCK_SIZE / 2); + cogl_path_close (path_a); + /* Add a counter-clockwise sub path in the upper right quadrant */ + cogl_path_move_to (path_a, BLOCK_SIZE / 2, 0); + cogl_path_line_to (path_a, BLOCK_SIZE / 2, BLOCK_SIZE / 2); + cogl_path_line_to (path_a, BLOCK_SIZE, BLOCK_SIZE / 2); + cogl_path_line_to (path_a, BLOCK_SIZE, 0); + cogl_path_close (path_a); + /* Retain the path for the next test */ + draw_path_at (path_a, white, 10, 0); + + /* Draw the same path again with the other fill rule */ + cogl_path_set_fill_rule (path_a, COGL_PATH_FILL_RULE_NON_ZERO); + draw_path_at (path_a, white, 11, 0); + + cogl_object_unref (path_a); +} + +static void +validate_result () +{ + check_block (0, 0, 0x8 /* bottom right */); + check_block (1, 0, 0xf /* all of them */); + check_block (2, 0, 0x8 /* bottom right */); + check_block (3, 0, 0x8 /* bottom right */); + check_block (4, 0, 0x9 /* top left and bottom right */); + check_block (5, 0, 0x8 /* bottom right */); + check_block (6, 0, 0xa /* bottom right and top right */); + check_block (7, 0, 0x9 /* top_left and bottom right */); + check_block (8, 0, 0xe /* all but top left */); + check_block (9, 0, 0x7 /* all but bottom right */); + check_block (10, 0, 0xc /* bottom two */); + check_block (11, 0, 0xd /* all but top right */); +} + +void +test_path (void) +{ + TestState state; + + cogl_framebuffer_orthographic (test_fb, + 0, 0, + cogl_framebuffer_get_width (test_fb), + cogl_framebuffer_get_height (test_fb), + -1, + 100); + + paint (&state); + validate_result (); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} + diff --git a/cogl/tests/conform/test-pipeline-cache-unrefs-texture.c b/cogl/tests/conform/test-pipeline-cache-unrefs-texture.c new file mode 100644 index 0000000..5d278dc --- /dev/null +++ b/cogl/tests/conform/test-pipeline-cache-unrefs-texture.c @@ -0,0 +1,91 @@ +#include + +#include "test-utils.h" + +/* Keep track of the number of textures that we've created and are + * still alive */ +static int destroyed_texture_count = 0; + +#define N_TEXTURES 3 + +static void +free_texture_cb (void *user_data) +{ + destroyed_texture_count++; +} + +static CoglTexture * +create_texture (void) +{ + static const guint8 data[] = + { 0xff, 0xff, 0xff, 0xff }; + static CoglUserDataKey texture_data_key; + CoglTexture2D *tex_2d; + + tex_2d = cogl_texture_2d_new_from_data (test_ctx, + 1, 1, /* width / height */ + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + 4, /* rowstride */ + data, + NULL); + + /* Set some user data on the texture so we can track when it has + * been destroyed */ + cogl_object_set_user_data (COGL_OBJECT (tex_2d), + &texture_data_key, + GINT_TO_POINTER (1), + free_texture_cb); + + return tex_2d; +} + +void +test_pipeline_cache_unrefs_texture (void) +{ + CoglPipeline *pipeline = cogl_pipeline_new (test_ctx); + CoglPipeline *simple_pipeline; + int i; + + /* Create a pipeline with three texture layers. That way we can be + * pretty sure the pipeline will cause a unique shader to be + * generated in the cache */ + for (i = 0; i < N_TEXTURES; i++) + { + CoglTexture *tex = create_texture (); + cogl_pipeline_set_layer_texture (pipeline, i, tex); + cogl_object_unref (tex); + } + + /* Draw something with the pipeline to ensure it gets into the + * pipeline cache */ + cogl_framebuffer_draw_rectangle (test_fb, + pipeline, + 0, 0, 10, 10); + cogl_framebuffer_finish (test_fb); + + /* Draw something else so that it is no longer the current flushed + * pipeline, and the units have a different texture bound */ + simple_pipeline = cogl_pipeline_new (test_ctx); + for (i = 0; i < N_TEXTURES; i++) + { + CoglColor combine_constant; + cogl_color_init_from_4ub (&combine_constant, i, 0, 0, 255); + cogl_pipeline_set_layer_combine_constant (simple_pipeline, + i, + &combine_constant); + } + cogl_framebuffer_draw_rectangle (test_fb, simple_pipeline, 0, 0, 10, 10); + cogl_framebuffer_finish (test_fb); + cogl_object_unref (simple_pipeline); + + g_assert_cmpint (destroyed_texture_count, ==, 0); + + /* Destroy the pipeline. This should immediately cause the textures + * to be freed */ + cogl_object_unref (pipeline); + + g_assert_cmpint (destroyed_texture_count, ==, N_TEXTURES); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} diff --git a/cogl/tests/conform/test-pipeline-shader-state.c b/cogl/tests/conform/test-pipeline-shader-state.c new file mode 100644 index 0000000..4d1e5f2 --- /dev/null +++ b/cogl/tests/conform/test-pipeline-shader-state.c @@ -0,0 +1,93 @@ +#include + +#include + +#include "test-utils.h" + +void +test_pipeline_shader_state (void) +{ + CoglOffscreen *offscreen; + CoglFramebuffer *fb; + CoglPipeline *base_pipeline; + CoglPipeline *draw_pipeline; + CoglTexture2D *tex; + CoglSnippet *snippet; + + float width = cogl_framebuffer_get_width (test_fb); + float height = cogl_framebuffer_get_height (test_fb); + + cogl_framebuffer_orthographic (test_fb, + 0, 0, width, height, + -1, + 100); + + tex = cogl_texture_2d_new_with_size (test_ctx, 128, 128); + offscreen = cogl_offscreen_new_with_texture (tex); + fb = offscreen; + cogl_framebuffer_clear4f (fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1); + cogl_object_unref (offscreen); + + cogl_framebuffer_clear4f (test_fb, COGL_BUFFER_BIT_COLOR, 1, 1, 0, 1); + + + /* Setup a template pipeline... */ + + base_pipeline = cogl_pipeline_new (test_ctx); + cogl_pipeline_set_layer_texture (base_pipeline, 1, tex); + cogl_pipeline_set_color4f (base_pipeline, 1, 0, 0, 1); + + + /* Derive a pipeline from the template, making a change that affects + * fragment processing but making sure not to affect vertex + * processing... */ + + draw_pipeline = cogl_pipeline_copy (base_pipeline); + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, + NULL, /* declarations */ + "cogl_color_out = vec4 (0.0, 1.0, 0.1, 1.1);"); + cogl_pipeline_add_snippet (draw_pipeline, snippet); + cogl_object_unref (snippet); + + cogl_framebuffer_draw_rectangle (test_fb, draw_pipeline, + 0, 0, width, height); + + cogl_object_unref (draw_pipeline); + + cogl_framebuffer_finish (test_fb); + + + /* At this point we should have provoked cogl to cache some vertex + * shader state for the draw_pipeline with the base_pipeline because + * none of the changes made to the draw_pipeline affected vertex + * processing. (NB: cogl will cache shader state with the oldest + * ancestor that the state is still valid for to maximize the chance + * that it can be used with other derived pipelines) + * + * Now we make a change to the base_pipeline to make sure that this + * cached vertex shader gets invalidated. + */ + + cogl_pipeline_set_layer_texture (base_pipeline, 0, tex); + + + /* Now we derive another pipeline from base_pipeline to verify that + * it doesn't end up re-using the old cached state + */ + + draw_pipeline = cogl_pipeline_copy (base_pipeline); + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, + NULL, /* declarations */ + "cogl_color_out = vec4 (0.0, 0.0, 1.1, 1.1);"); + cogl_pipeline_add_snippet (draw_pipeline, snippet); + cogl_object_unref (snippet); + + cogl_framebuffer_draw_rectangle (test_fb, draw_pipeline, + 0, 0, width, height); + + cogl_object_unref (draw_pipeline); + + + test_utils_check_region (test_fb, 0, 0, width, height, + 0x0000ffff); +} diff --git a/cogl/tests/conform/test-pipeline-uniforms.c b/cogl/tests/conform/test-pipeline-uniforms.c new file mode 100644 index 0000000..4d27558 --- /dev/null +++ b/cogl/tests/conform/test-pipeline-uniforms.c @@ -0,0 +1,415 @@ +#include + +#include + +#include "test-utils.h" + +#define LONG_ARRAY_SIZE 128 + +typedef struct _TestState +{ + CoglPipeline *pipeline_red; + CoglPipeline *pipeline_green; + CoglPipeline *pipeline_blue; + + CoglPipeline *matrix_pipeline; + CoglPipeline *vector_pipeline; + CoglPipeline *int_pipeline; + + CoglPipeline *long_pipeline; + int long_uniform_locations[LONG_ARRAY_SIZE]; +} TestState; + +static const char +color_source[] = + "uniform float red, green, blue;\n" + "\n" + "void\n" + "main ()\n" + "{\n" + " cogl_color_out = vec4 (red, green, blue, 1.0);\n" + "}\n"; + +static const char +matrix_source[] = + "uniform mat4 matrix_array[4];\n" + "\n" + "void\n" + "main ()\n" + "{\n" + " vec4 color = vec4 (0.0, 0.0, 0.0, 1.0);\n" + " int i;\n" + "\n" + " for (i = 0; i < 4; i++)\n" + " color = matrix_array[i] * color;\n" + "\n" + " cogl_color_out = color;\n" + "}\n"; + +static const char +vector_source[] = + "uniform vec4 vector_array[2];\n" + "uniform vec3 short_vector;\n" + "\n" + "void\n" + "main ()\n" + "{\n" + " cogl_color_out = (vector_array[0] +\n" + " vector_array[1] +\n" + " vec4 (short_vector, 1.0));\n" + "}\n"; + +static const char +int_source[] = + "uniform ivec4 vector_array[2];\n" + "uniform int single_value;\n" + "\n" + "void\n" + "main ()\n" + "{\n" + " cogl_color_out = (vec4 (vector_array[0]) +\n" + " vec4 (vector_array[1]) +\n" + " vec4 (float (single_value), 0.0, 0.0, 255.0)) / 255.0;\n" + "}\n"; + +static const char +long_source[] = + "uniform int long_array[" G_STRINGIFY (LONG_ARRAY_SIZE) "];\n" + "const int last_index = " G_STRINGIFY (LONG_ARRAY_SIZE) " - 1;\n" + "\n" + "void\n" + "main ()\n" + "{\n" + " cogl_color_out = vec4 (float (long_array[last_index]), 0.0, 0.0, 1.0);\n" + "}\n"; + +static CoglPipeline * +create_pipeline_for_shader (TestState *state, const char *shader_source) +{ + CoglPipeline *pipeline; + CoglHandle shader; + CoglHandle program; + + pipeline = cogl_pipeline_new (test_ctx); + + shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT); + cogl_shader_source (shader, shader_source); + + program = cogl_create_program (); + cogl_program_attach_shader (program, shader); + + cogl_pipeline_set_user_program (pipeline, program); + + cogl_handle_unref (shader); + cogl_handle_unref (program); + + return pipeline; +} + +static void +init_state (TestState *state) +{ + int uniform_location; + + state->pipeline_red = create_pipeline_for_shader (state, color_source); + + uniform_location = + cogl_pipeline_get_uniform_location (state->pipeline_red, "red"); + cogl_pipeline_set_uniform_1f (state->pipeline_red, uniform_location, 1.0f); + uniform_location = + cogl_pipeline_get_uniform_location (state->pipeline_red, "green"); + cogl_pipeline_set_uniform_1f (state->pipeline_red, uniform_location, 0.0f); + uniform_location = + cogl_pipeline_get_uniform_location (state->pipeline_red, "blue"); + cogl_pipeline_set_uniform_1f (state->pipeline_red, uniform_location, 0.0f); + + state->pipeline_green = cogl_pipeline_copy (state->pipeline_red); + uniform_location = + cogl_pipeline_get_uniform_location (state->pipeline_green, "green"); + cogl_pipeline_set_uniform_1f (state->pipeline_green, uniform_location, 1.0f); + + state->pipeline_blue = cogl_pipeline_copy (state->pipeline_red); + uniform_location = + cogl_pipeline_get_uniform_location (state->pipeline_blue, "blue"); + cogl_pipeline_set_uniform_1f (state->pipeline_blue, uniform_location, 1.0f); + + state->matrix_pipeline = create_pipeline_for_shader (state, matrix_source); + state->vector_pipeline = create_pipeline_for_shader (state, vector_source); + state->int_pipeline = create_pipeline_for_shader (state, int_source); + + state->long_pipeline = NULL; +} + +static void +init_long_pipeline_state (TestState *state) +{ + int i; + + state->long_pipeline = create_pipeline_for_shader (state, long_source); + + /* This tries to lookup a large number of uniform names to make sure + that the bitmask of overriden uniforms flows over the size of a + single long so that it has to resort to allocating it */ + for (i = 0; i < LONG_ARRAY_SIZE; i++) + { + char *uniform_name = g_strdup_printf ("long_array[%i]", i); + state->long_uniform_locations[i] = + cogl_pipeline_get_uniform_location (state->long_pipeline, + uniform_name); + g_free (uniform_name); + } +} + +static void +destroy_state (TestState *state) +{ + cogl_object_unref (state->pipeline_red); + cogl_object_unref (state->pipeline_green); + cogl_object_unref (state->pipeline_blue); + cogl_object_unref (state->matrix_pipeline); + cogl_object_unref (state->vector_pipeline); + cogl_object_unref (state->int_pipeline); + + if (state->long_pipeline) + cogl_object_unref (state->long_pipeline); +} + +static void +paint_pipeline (CoglPipeline *pipeline, int pos) +{ + cogl_framebuffer_draw_rectangle (test_fb, pipeline, + pos * 10, 0, pos * 10 + 10, 10); +} + +static void +paint_color_pipelines (TestState *state) +{ + CoglPipeline *temp_pipeline; + int uniform_location; + int i; + + /* Paint with the first pipeline that sets the uniforms to bright + red */ + paint_pipeline (state->pipeline_red, 0); + + /* Paint with the two other pipelines. These inherit from the red + pipeline and only override one other component. The values for + the two other components should be inherited from the red + pipeline. */ + paint_pipeline (state->pipeline_green, 1); + paint_pipeline (state->pipeline_blue, 2); + + /* Try modifying a single pipeline for multiple rectangles */ + temp_pipeline = cogl_pipeline_copy (state->pipeline_green); + uniform_location = cogl_pipeline_get_uniform_location (temp_pipeline, + "green"); + + for (i = 0; i <= 8; i++) + { + cogl_pipeline_set_uniform_1f (temp_pipeline, uniform_location, + i / 8.0f); + paint_pipeline (temp_pipeline, i + 3); + } + + cogl_object_unref (temp_pipeline); +} + +static void +paint_matrix_pipeline (CoglPipeline *pipeline) +{ + CoglMatrix matrices[4]; + float matrix_floats[16 * 4]; + int uniform_location; + int i; + + for (i = 0; i < 4; i++) + cogl_matrix_init_identity (matrices + i); + + /* Use the first matrix to make the color red */ + cogl_matrix_translate (matrices + 0, 1.0f, 0.0f, 0.0f); + + /* Rotate the vertex so that it ends up green */ + cogl_matrix_rotate (matrices + 1, 90.0f, 0.0f, 0.0f, 1.0f); + + /* Scale the vertex so it ends up halved */ + cogl_matrix_scale (matrices + 2, 0.5f, 0.5f, 0.5f); + + /* Add a blue component in the final matrix. The final matrix is + uploaded as transposed so we need to transpose first to cancel + that out */ + cogl_matrix_translate (matrices + 3, 0.0f, 0.0f, 1.0f); + cogl_matrix_transpose (matrices + 3); + + for (i = 0; i < 4; i++) + memcpy (matrix_floats + i * 16, + cogl_matrix_get_array (matrices + i), + sizeof (float) * 16); + + /* Set the first three matrices as transposed */ + uniform_location = + cogl_pipeline_get_uniform_location (pipeline, "matrix_array"); + cogl_pipeline_set_uniform_matrix (pipeline, + uniform_location, + 4, /* dimensions */ + 3, /* count */ + FALSE, /* not transposed */ + matrix_floats); + + /* Set the last matrix as untransposed */ + uniform_location = + cogl_pipeline_get_uniform_location (pipeline, "matrix_array[3]"); + cogl_pipeline_set_uniform_matrix (pipeline, + uniform_location, + 4, /* dimensions */ + 1, /* count */ + TRUE, /* transposed */ + matrix_floats + 16 * 3); + + paint_pipeline (pipeline, 12); +} + +static void +paint_vector_pipeline (CoglPipeline *pipeline) +{ + float vector_array_values[] = { 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f }; + float short_vector_values[] = { 0.0f, 0.0f, 1.0f }; + int uniform_location; + + uniform_location = + cogl_pipeline_get_uniform_location (pipeline, "vector_array"); + cogl_pipeline_set_uniform_float (pipeline, + uniform_location, + 4, /* n_components */ + 2, /* count */ + vector_array_values); + + uniform_location = + cogl_pipeline_get_uniform_location (pipeline, "short_vector"); + cogl_pipeline_set_uniform_float (pipeline, + uniform_location, + 3, /* n_components */ + 1, /* count */ + short_vector_values); + + paint_pipeline (pipeline, 13); +} + +static void +paint_int_pipeline (CoglPipeline *pipeline) +{ + int vector_array_values[] = { 0x00, 0x00, 0xff, 0x00, + 0x00, 0xff, 0x00, 0x00 }; + int single_value = 0x80; + int uniform_location; + + uniform_location = + cogl_pipeline_get_uniform_location (pipeline, "vector_array"); + cogl_pipeline_set_uniform_int (pipeline, + uniform_location, + 4, /* n_components */ + 2, /* count */ + vector_array_values); + + uniform_location = + cogl_pipeline_get_uniform_location (pipeline, "single_value"); + cogl_pipeline_set_uniform_1i (pipeline, + uniform_location, + single_value); + + paint_pipeline (pipeline, 14); +} + +static void +paint_long_pipeline (TestState *state) +{ + int i; + + for (i = 0; i < LONG_ARRAY_SIZE; i++) + { + int location = state->long_uniform_locations[i]; + + cogl_pipeline_set_uniform_1i (state->long_pipeline, + location, + i == LONG_ARRAY_SIZE - 1); + } + + paint_pipeline (state->long_pipeline, 15); +} + +static void +paint (TestState *state) +{ + cogl_framebuffer_clear4f (test_fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1); + + paint_color_pipelines (state); + paint_matrix_pipeline (state->matrix_pipeline); + paint_vector_pipeline (state->vector_pipeline); + paint_int_pipeline (state->int_pipeline); +} + +static void +check_pos (int pos, uint32_t color) +{ + test_utils_check_pixel (test_fb, pos * 10 + 5, 5, color); +} + +static void +validate_result (void) +{ + int i; + + check_pos (0, 0xff0000ff); + check_pos (1, 0xffff00ff); + check_pos (2, 0xff00ffff); + + for (i = 0; i <= 8; i++) + { + int green_value = i / 8.0f * 255.0f + 0.5f; + check_pos (i + 3, 0xff0000ff + (green_value << 16)); + } + + check_pos (12, 0x0080ffff); + check_pos (13, 0xffffffff); + check_pos (14, 0x80ffffff); +} + +static void +validate_long_pipeline_result (void) +{ + check_pos (15, 0xff0000ff); +} + +void +test_pipeline_uniforms (void) +{ + TestState state; + + init_state (&state); + + cogl_framebuffer_orthographic (test_fb, + 0, 0, + cogl_framebuffer_get_width (test_fb), + cogl_framebuffer_get_height (test_fb), + -1, + 100); + + paint (&state); + validate_result (); + + /* Try the test again after querying the location of a large + number of uniforms. This should verify that the bitmasks + still work even if they have to allocate a separate array to + store the bits */ + + init_long_pipeline_state (&state); + paint (&state); + paint_long_pipeline (&state); + validate_result (); + validate_long_pipeline_result (); + + destroy_state (&state); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} diff --git a/cogl/tests/conform/test-pipeline-user-matrix.c b/cogl/tests/conform/test-pipeline-user-matrix.c new file mode 100644 index 0000000..f7cdee8 --- /dev/null +++ b/cogl/tests/conform/test-pipeline-user-matrix.c @@ -0,0 +1,140 @@ +#include + +#include + +#include "test-utils.h" + +typedef struct _TestState +{ + int width; + int height; +} TestState; + +static void +validate_result (TestState *state) +{ + uint32_t *pixels, *p; + char *screen_pixel; + const char *intended_pixel = "#ffffff"; + + /* The textures are setup so that when added together with the + correct matrices then all of the pixels should be white. We can + verify this by reading back the entire stage */ + pixels = g_malloc (state->width * state->height * 4); + + cogl_framebuffer_read_pixels (test_fb, 0, 0, state->width, state->height, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + (uint8_t *)pixels); + + for (p = pixels; p < pixels + state->width * state->height; p++) + { + screen_pixel = g_strdup_printf ("#%06x", GUINT32_FROM_BE (*p) >> 8); + g_assert_cmpstr (screen_pixel, ==, intended_pixel); + g_free (screen_pixel); + } +} + +static void +paint (TestState *state) +{ + /* This texture is painted mirrored around the x-axis */ + uint8_t data0[] = { + 0xff, 0x00, 0x00, /* red -> becomes bottom left */ + 0x00, 0xff, 0x00, /* green -> becomes bottom right */ + 0x00, 0x00, 0xff, /* blue -> becomes top left */ + 0xff, 0x00, 0xff /* magenta -> becomes top right */ + }; + /* This texture is painted mirrored about the y-axis */ + uint8_t data1[] = { + 0x00, 0xff, 0x00, /* green -> becomes top right */ + 0xff, 0xff, 0x00, /* yellow -> becomes top left */ + 0xff, 0x00, 0xff, /* magenta -> becomes bottom right */ + 0x00, 0xff, 0xff /* cyan -> becomes bottom left */ + }; + CoglTexture *tex0, *tex1; + CoglPipeline *pipeline; + CoglMatrix matrix; + CoglError *error = NULL; + + cogl_framebuffer_orthographic (test_fb, + 0, 0, + state->width, + state->height, + -1, + 100); + + cogl_framebuffer_clear4f (test_fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1); + + cogl_matrix_init_identity (&matrix); + cogl_framebuffer_set_modelview_matrix (test_fb, &matrix); + + tex0 = cogl_texture_new_from_data (2, 2, + COGL_TEXTURE_NO_ATLAS, + COGL_PIXEL_FORMAT_RGB_888, + COGL_PIXEL_FORMAT_ANY, + 6, + data0); + tex1 = cogl_texture_new_from_data (2, 2, + COGL_TEXTURE_NO_ATLAS, + COGL_PIXEL_FORMAT_RGB_888, + COGL_PIXEL_FORMAT_ANY, + 6, + data1); + + pipeline = cogl_pipeline_new (test_ctx); + + /* Set the two textures as layers */ + cogl_pipeline_set_layer_texture (pipeline, 0, tex0); + cogl_pipeline_set_layer_filters (pipeline, 0, + COGL_PIPELINE_FILTER_NEAREST, + COGL_PIPELINE_FILTER_NEAREST); + cogl_pipeline_set_layer_texture (pipeline, 1, tex1); + cogl_pipeline_set_layer_filters (pipeline, 1, + COGL_PIPELINE_FILTER_NEAREST, + COGL_PIPELINE_FILTER_NEAREST); + + /* Set a combine mode so that the two textures get added together */ + if (!cogl_pipeline_set_layer_combine (pipeline, 1, + "RGBA=ADD(PREVIOUS, TEXTURE)", + &error)) + { + g_warning ("Error setting blend string: %s", error->message); + g_assert_not_reached (); + } + + /* Set a matrix on the first layer so that it will mirror about the y-axis */ + cogl_matrix_init_identity (&matrix); + cogl_matrix_translate (&matrix, 0.0f, 1.0f, 0.0f); + cogl_matrix_scale (&matrix, 1.0f, -1.0f, 1.0f); + cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix); + + /* Set a matrix on the second layer so that it will mirror about the x-axis */ + cogl_matrix_init_identity (&matrix); + cogl_matrix_translate (&matrix, 1.0f, 0.0f, 0.0f); + cogl_matrix_scale (&matrix, -1.0f, 1.0f, 1.0f); + cogl_pipeline_set_layer_matrix (pipeline, 1, &matrix); + + cogl_framebuffer_draw_rectangle (test_fb, + pipeline, + 0, 0, + state->width, state->height); + + cogl_object_unref (tex1); + cogl_object_unref (tex0); + cogl_object_unref (pipeline); +} + +void +test_pipeline_user_matrix (void) +{ + TestState state; + + state.width = cogl_framebuffer_get_width (test_fb); + state.height = cogl_framebuffer_get_height (test_fb); + + paint (&state); + validate_result (&state); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} diff --git a/cogl/tests/conform/test-pixel-buffer.c b/cogl/tests/conform/test-pixel-buffer.c new file mode 100644 index 0000000..a78516d --- /dev/null +++ b/cogl/tests/conform/test-pixel-buffer.c @@ -0,0 +1,269 @@ +#include +#include + +#include "test-utils.h" + +#define BITMAP_SIZE 256 + +/* + * Creates a 256 x 256 with image data split into four quadrants. The + * colours of these in reading order will be: blue, green, cyan, + * red */ +static void +generate_bitmap_data (uint8_t *data, + int stride) +{ + int y, x; + + for (y = 0; y < BITMAP_SIZE; y++) + { + for (x = 0; x < BITMAP_SIZE; x++) + { + int color_num = x / (BITMAP_SIZE / 2) + y / (BITMAP_SIZE / 2) * 2 + 1; + *(data++) = (color_num & 4) ? 255 : 0; + *(data++) = (color_num & 2) ? 255 : 0; + *(data++) = (color_num & 1) ? 255 : 0; + *(data++) = 255; + } + data += stride - BITMAP_SIZE * 4; + } +} + +static CoglBitmap * +create_bitmap (void) +{ + CoglBitmap *bitmap; + CoglBuffer *buffer; + + bitmap = cogl_bitmap_new_with_size (test_ctx, + BITMAP_SIZE, + BITMAP_SIZE, + COGL_PIXEL_FORMAT_RGBA_8888); + buffer = cogl_bitmap_get_buffer (bitmap); + + g_assert (cogl_is_pixel_buffer (buffer)); + g_assert (cogl_is_buffer (buffer)); + + cogl_buffer_set_update_hint (buffer, COGL_BUFFER_UPDATE_HINT_DYNAMIC); + g_assert_cmpint (cogl_buffer_get_update_hint (buffer), + ==, + COGL_BUFFER_UPDATE_HINT_DYNAMIC); + + return bitmap; +} + +static CoglBitmap * +create_and_fill_bitmap (void) +{ + CoglBitmap *bitmap = create_bitmap (); + CoglBuffer *buffer = cogl_bitmap_get_buffer (bitmap); + uint8_t *map; + unsigned int stride; + + stride = cogl_bitmap_get_rowstride (bitmap); + + map = cogl_buffer_map (buffer, + COGL_BUFFER_ACCESS_WRITE, + COGL_BUFFER_MAP_HINT_DISCARD); + g_assert (map); + + generate_bitmap_data (map, stride); + + cogl_buffer_unmap (buffer); + + return bitmap; +} + +static CoglTexture * +create_texture_from_bitmap (CoglBitmap *bitmap) +{ + CoglTexture2D *texture; + + texture = cogl_texture_2d_new_from_bitmap (bitmap); + + g_assert (texture != NULL); + + return texture; +} + +static CoglPipeline * +create_pipeline_from_texture (CoglTexture *texture) +{ + CoglPipeline *pipeline = cogl_pipeline_new (test_ctx); + + cogl_pipeline_set_layer_texture (pipeline, 0, texture); + cogl_pipeline_set_layer_filters (pipeline, + 0, /* layer_num */ + COGL_PIPELINE_FILTER_NEAREST, + COGL_PIPELINE_FILTER_NEAREST); + + return pipeline; +} + +static void +check_colours (uint32_t color0, + uint32_t color1, + uint32_t color2, + uint32_t color3) +{ + int fb_width = cogl_framebuffer_get_width (test_fb); + int fb_height = cogl_framebuffer_get_height (test_fb); + + test_utils_check_region (test_fb, + 1, 1, /* x/y */ + fb_width / 2 - 2, /* width */ + fb_height / 2 - 2, /* height */ + color0); + test_utils_check_region (test_fb, + fb_width / 2 + 1, /* x */ + 1, /* y */ + fb_width / 2 - 2, /* width */ + fb_height / 2 - 2, /* height */ + color1); + test_utils_check_region (test_fb, + 1, /* x */ + fb_height / 2 + 1, /* y */ + fb_width / 2 - 2, /* width */ + fb_height / 2 - 2, /* height */ + color2); + test_utils_check_region (test_fb, + fb_width / 2 + 1, /* x */ + fb_height / 2 + 1, /* y */ + fb_width / 2 - 2, /* width */ + fb_height / 2 - 2, /* height */ + color3); +} + +void +test_pixel_buffer_map (void) +{ + CoglBitmap *bitmap = create_and_fill_bitmap (); + CoglPipeline *pipeline; + CoglTexture *texture; + + texture = create_texture_from_bitmap (bitmap); + pipeline = create_pipeline_from_texture (texture); + + cogl_framebuffer_draw_rectangle (test_fb, + pipeline, + -1.0f, 1.0f, + 1.0f, -1.0f); + + cogl_object_unref (bitmap); + cogl_object_unref (texture); + cogl_object_unref (pipeline); + + check_colours (0x0000ffff, + 0x00ff00ff, + 0x00ffffff, + 0xff0000ff); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} + +void +test_pixel_buffer_set_data (void) +{ + CoglBitmap *bitmap = create_bitmap (); + CoglBuffer *buffer = cogl_bitmap_get_buffer (bitmap); + CoglPipeline *pipeline; + CoglTexture *texture; + uint8_t *data; + unsigned int stride; + + stride = cogl_bitmap_get_rowstride (bitmap); + + data = g_malloc (stride * BITMAP_SIZE); + + generate_bitmap_data (data, stride); + + cogl_buffer_set_data (buffer, + 0, /* offset */ + data, + stride * (BITMAP_SIZE - 1) + + BITMAP_SIZE * 4); + + g_free (data); + + texture = create_texture_from_bitmap (bitmap); + pipeline = create_pipeline_from_texture (texture); + + cogl_framebuffer_draw_rectangle (test_fb, + pipeline, + -1.0f, 1.0f, + 1.0f, -1.0f); + + cogl_object_unref (bitmap); + cogl_object_unref (texture); + cogl_object_unref (pipeline); + + check_colours (0x0000ffff, + 0x00ff00ff, + 0x00ffffff, + 0xff0000ff); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} + +static CoglTexture * +create_white_texture (void) +{ + CoglTexture2D *texture; + uint8_t *data = g_malloc (BITMAP_SIZE * BITMAP_SIZE * 4); + + memset (data, 255, BITMAP_SIZE * BITMAP_SIZE * 4); + + texture = cogl_texture_2d_new_from_data (test_ctx, + BITMAP_SIZE, + BITMAP_SIZE, + COGL_PIXEL_FORMAT_RGBA_8888, + BITMAP_SIZE * 4, /* rowstride */ + data, + NULL); /* don't catch errors */ + + g_free (data); + + return texture; +} + +void +test_pixel_buffer_sub_region (void) +{ + CoglBitmap *bitmap = create_and_fill_bitmap (); + CoglPipeline *pipeline; + CoglTexture *texture; + + texture = create_white_texture (); + + /* Replace the top-right quadrant of the texture with the red part + * of the bitmap */ + cogl_texture_set_region_from_bitmap (texture, + BITMAP_SIZE / 2, /* src_x */ + BITMAP_SIZE / 2, /* src_y */ + BITMAP_SIZE / 2, /* dst_x */ + 0, /* dst_y */ + BITMAP_SIZE / 2, /* width */ + BITMAP_SIZE / 2, /* height */ + bitmap); + + pipeline = create_pipeline_from_texture (texture); + + cogl_framebuffer_draw_rectangle (test_fb, + pipeline, + -1.0f, 1.0f, + 1.0f, -1.0f); + + cogl_object_unref (bitmap); + cogl_object_unref (texture); + cogl_object_unref (pipeline); + + check_colours (0xffffffff, + 0xff0000ff, + 0xffffffff, + 0xffffffff); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} diff --git a/cogl/tests/conform/test-point-size-attribute.c b/cogl/tests/conform/test-point-size-attribute.c new file mode 100644 index 0000000..a08d1da --- /dev/null +++ b/cogl/tests/conform/test-point-size-attribute.c @@ -0,0 +1,166 @@ +#include + +#include "test-utils.h" + +/* This test assumes the GL driver supports point sizes up to 16 + pixels. Cogl should probably have some way of querying the size so + we start from that instead */ +#define MAX_POINT_SIZE 16 +#define MIN_POINT_SIZE 4 +#define N_POINTS (MAX_POINT_SIZE - MIN_POINT_SIZE + 1) +/* The size of the area that we'll paint each point in */ +#define POINT_BOX_SIZE (MAX_POINT_SIZE * 2) + +typedef struct +{ + float x, y; + float point_size; +} PointVertex; + +static int +calc_coord_offset (int pos, int pos_index, int point_size) +{ + switch (pos_index) + { + case 0: return pos - point_size / 2 - 2; + case 1: return pos - point_size / 2 + 2; + case 2: return pos + point_size / 2 - 2; + case 3: return pos + point_size / 2 + 2; + } + + g_assert_not_reached (); +} + +static void +verify_point_size (CoglFramebuffer *test_fb, + int x_pos, + int y_pos, + int point_size) +{ + int y, x; + + for (y = 0; y < 4; y++) + for (x = 0; x < 4; x++) + { + CoglBool in_point = x >= 1 && x <= 2 && y >= 1 && y <= 2; + uint32_t expected_pixel = in_point ? 0x00ff00ff : 0xff0000ff; + + test_utils_check_pixel (test_fb, + calc_coord_offset (x_pos, x, point_size), + calc_coord_offset (y_pos, y, point_size), + expected_pixel); + } +} + +static CoglPrimitive * +create_primitive (const char *attribute_name) +{ + PointVertex vertices[N_POINTS]; + CoglAttributeBuffer *buffer; + CoglAttribute *attributes[2]; + CoglPrimitive *prim; + int i; + + for (i = 0; i < N_POINTS; i++) + { + vertices[i].x = i * POINT_BOX_SIZE + POINT_BOX_SIZE / 2; + vertices[i].y = POINT_BOX_SIZE / 2; + vertices[i].point_size = MAX_POINT_SIZE - i; + } + + buffer = cogl_attribute_buffer_new (test_ctx, + sizeof (vertices), + vertices); + + attributes[0] = cogl_attribute_new (buffer, + "cogl_position_in", + sizeof (PointVertex), + G_STRUCT_OFFSET (PointVertex, x), + 2, /* n_components */ + COGL_ATTRIBUTE_TYPE_FLOAT); + attributes[1] = cogl_attribute_new (buffer, + attribute_name, + sizeof (PointVertex), + G_STRUCT_OFFSET (PointVertex, point_size), + 1, /* n_components */ + COGL_ATTRIBUTE_TYPE_FLOAT); + + prim = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_POINTS, + N_POINTS, + attributes, + 2 /* n_attributes */); + + for (i = 0; i < 2; i++) + cogl_object_unref (attributes[i]); + + return prim; +} + +static void +do_test (const char *attribute_name, + void (* pipeline_setup_func) (CoglPipeline *pipeline)) +{ + int fb_width = cogl_framebuffer_get_width (test_fb); + int fb_height = cogl_framebuffer_get_height (test_fb); + CoglPrimitive *primitive; + CoglPipeline *pipeline; + int i; + + cogl_framebuffer_orthographic (test_fb, + 0, 0, /* x_1, y_1 */ + fb_width, /* x_2 */ + fb_height /* y_2 */, + -1, 100 /* near/far */); + + cogl_framebuffer_clear4f (test_fb, + COGL_BUFFER_BIT_COLOR, + 1.0f, 0.0f, 0.0f, 1.0f); + + primitive = create_primitive (attribute_name); + pipeline = cogl_pipeline_new (test_ctx); + cogl_pipeline_set_color4ub (pipeline, 0x00, 0xff, 0x00, 0xff); + cogl_pipeline_set_per_vertex_point_size (pipeline, TRUE, NULL); + if (pipeline_setup_func) + pipeline_setup_func (pipeline); + cogl_primitive_draw (primitive, test_fb, pipeline); + cogl_object_unref (pipeline); + cogl_object_unref (primitive); + + /* Verify all of the points where drawn at the right size */ + for (i = 0; i < N_POINTS; i++) + verify_point_size (test_fb, + i * POINT_BOX_SIZE + POINT_BOX_SIZE / 2, /* x */ + POINT_BOX_SIZE / 2, /* y */ + MAX_POINT_SIZE - i /* point size */); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} + +void +test_point_size_attribute (void) +{ + do_test ("cogl_point_size_in", NULL); +} + +static void +setup_snippet (CoglPipeline *pipeline) +{ + CoglSnippet *snippet; + + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_POINT_SIZE, + "attribute float " + "my_super_duper_point_size_attrib;\n", + NULL); + cogl_snippet_set_replace (snippet, + "cogl_point_size_out = " + "my_super_duper_point_size_attrib;\n"); + cogl_pipeline_add_snippet (pipeline, snippet); + cogl_object_unref (snippet); +} + +void +test_point_size_attribute_snippet (void) +{ + do_test ("my_super_duper_point_size_attrib", setup_snippet); +} diff --git a/cogl/tests/conform/test-point-size.c b/cogl/tests/conform/test-point-size.c new file mode 100644 index 0000000..49d0833 --- /dev/null +++ b/cogl/tests/conform/test-point-size.c @@ -0,0 +1,99 @@ +#include + +#include "test-utils.h" + +/* This test assumes the GL driver supports point sizes up to 16 + pixels. Cogl should probably have some way of querying the size so + we start from that instead */ +#define MAX_POINT_SIZE 16 +/* The size of the area that we'll paint each point in */ +#define POINT_BOX_SIZE (MAX_POINT_SIZE * 2) + +static int +calc_coord_offset (int pos, int pos_index, int point_size) +{ + switch (pos_index) + { + case 0: return pos - point_size / 2 - 2; + case 1: return pos - point_size / 2 + 2; + case 2: return pos + point_size / 2 - 2; + case 3: return pos + point_size / 2 + 2; + } + + g_assert_not_reached (); +} + +static void +verify_point_size (CoglFramebuffer *test_fb, + int x_pos, + int y_pos, + int point_size) +{ + int y, x; + + for (y = 0; y < 4; y++) + for (x = 0; x < 4; x++) + { + CoglBool in_point = x >= 1 && x <= 2 && y >= 1 && y <= 2; + uint32_t expected_pixel = in_point ? 0x00ff00ff : 0xff0000ff; + + test_utils_check_pixel (test_fb, + calc_coord_offset (x_pos, x, point_size), + calc_coord_offset (y_pos, y, point_size), + expected_pixel); + } +} + +void +test_point_size (void) +{ + int fb_width = cogl_framebuffer_get_width (test_fb); + int fb_height = cogl_framebuffer_get_height (test_fb); + int point_size; + int x_pos; + + cogl_framebuffer_orthographic (test_fb, + 0, 0, /* x_1, y_1 */ + fb_width, /* x_2 */ + fb_height /* y_2 */, + -1, 100 /* near/far */); + + cogl_framebuffer_clear4f (test_fb, + COGL_BUFFER_BIT_COLOR, + 1.0f, 0.0f, 0.0f, 1.0f); + + /* Try a rendering a single point with a few different point + sizes */ + for (x_pos = 0, point_size = MAX_POINT_SIZE; + point_size >= 4; + x_pos += POINT_BOX_SIZE, point_size /= 2) + { + CoglPipeline *pipeline = cogl_pipeline_new (test_ctx); + CoglVertexP2 point = { x_pos + POINT_BOX_SIZE / 2, + POINT_BOX_SIZE / 2 }; + CoglPrimitive *prim = + cogl_primitive_new_p2 (test_ctx, + COGL_VERTICES_MODE_POINTS, + 1, /* n_vertices */ + &point); + + cogl_pipeline_set_point_size (pipeline, point_size); + cogl_pipeline_set_color4ub (pipeline, 0, 255, 0, 255); + cogl_primitive_draw (prim, test_fb, pipeline); + + cogl_object_unref (prim); + cogl_object_unref (pipeline); + } + + /* Verify all of the points where drawn at the right size */ + for (x_pos = 0, point_size = MAX_POINT_SIZE; + point_size >= 4; + x_pos += POINT_BOX_SIZE, point_size /= 2) + verify_point_size (test_fb, + x_pos + POINT_BOX_SIZE / 2, + POINT_BOX_SIZE / 2, + point_size); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} diff --git a/cogl/tests/conform/test-point-sprite.c b/cogl/tests/conform/test-point-sprite.c new file mode 100644 index 0000000..65ce9a8 --- /dev/null +++ b/cogl/tests/conform/test-point-sprite.c @@ -0,0 +1,194 @@ +#include + +#include "test-utils.h" + +#define POINT_SIZE 8 + +static const CoglVertexP2T2 +point = + { + POINT_SIZE, POINT_SIZE, + 0.0f, 0.0f + }; + +static const uint8_t +tex_data[3 * 2 * 2] = + { + 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, + 0x00, 0xff, 0xff, 0xff, 0x00, 0x00 + }; + +static void +do_test (CoglBool check_orientation, + CoglBool use_glsl) +{ + int fb_width = cogl_framebuffer_get_width (test_fb); + int fb_height = cogl_framebuffer_get_height (test_fb); + CoglPrimitive *prim; + CoglError *error = NULL; + CoglTexture2D *tex_2d; + CoglPipeline *pipeline, *solid_pipeline; + int tex_height; + + cogl_framebuffer_orthographic (test_fb, + 0, 0, /* x_1, y_1 */ + fb_width, /* x_2 */ + fb_height /* y_2 */, + -1, 100 /* near/far */); + + cogl_framebuffer_clear4f (test_fb, + COGL_BUFFER_BIT_COLOR, + 1.0f, 1.0f, 1.0f, 1.0f); + + /* If we're not checking the orientation of the point sprite then + * we'll set the height of the texture to 1 so that the vertical + * orientation does not matter */ + if (check_orientation) + tex_height = 2; + else + tex_height = 1; + + tex_2d = cogl_texture_2d_new_from_data (test_ctx, + 2, tex_height, /* width/height */ + COGL_PIXEL_FORMAT_RGB_888, + 6, /* row stride */ + tex_data, + &error); + g_assert (tex_2d != NULL); + g_assert (error == NULL); + + pipeline = cogl_pipeline_new (test_ctx); + cogl_pipeline_set_layer_texture (pipeline, 0, tex_2d); + + cogl_pipeline_set_layer_filters (pipeline, + 0, /* layer_index */ + COGL_PIPELINE_FILTER_NEAREST, + COGL_PIPELINE_FILTER_NEAREST); + cogl_pipeline_set_point_size (pipeline, POINT_SIZE); + + /* If we're using GLSL then we don't need to enable point sprite + * coords and we can just directly reference cogl_point_coord in the + * snippet */ + if (use_glsl) + { + CoglSnippet *snippet = + cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_LOOKUP, + NULL, /* declarations */ + NULL /* post */); + static const char source[] = + " cogl_texel = texture2D (cogl_sampler, cogl_point_coord);\n"; + + cogl_snippet_set_replace (snippet, source); + + /* Keep a reference to the original pipeline because there is no + * way to remove a snippet in order to recreate the solid + * pipeline */ + solid_pipeline = cogl_pipeline_copy (pipeline); + + cogl_pipeline_add_layer_snippet (pipeline, 0, snippet); + + cogl_object_unref (snippet); + } + else + { + CoglBool res = + cogl_pipeline_set_layer_point_sprite_coords_enabled (pipeline, + /* layer_index */ + 0, + /* enable */ + TRUE, + &error); + g_assert (res == TRUE); + g_assert (error == NULL); + + solid_pipeline = cogl_pipeline_copy (pipeline); + + res = + cogl_pipeline_set_layer_point_sprite_coords_enabled (solid_pipeline, + /* layer_index */ + 0, + /* enable */ + FALSE, + &error); + + g_assert (res == TRUE); + g_assert (error == NULL); + } + + prim = cogl_primitive_new_p2t2 (test_ctx, + COGL_VERTICES_MODE_POINTS, + 1, /* n_vertices */ + &point); + + cogl_primitive_draw (prim, test_fb, pipeline); + + /* Render the primitive again without point sprites to make sure + disabling it works */ + + cogl_framebuffer_push_matrix (test_fb); + cogl_framebuffer_translate (test_fb, + POINT_SIZE * 2, /* x */ + 0.0f, /* y */ + 0.0f /* z */); + cogl_primitive_draw (prim, test_fb, solid_pipeline); + cogl_framebuffer_pop_matrix (test_fb); + + cogl_object_unref (prim); + cogl_object_unref (solid_pipeline); + cogl_object_unref (pipeline); + cogl_object_unref (tex_2d); + + test_utils_check_pixel (test_fb, + POINT_SIZE - POINT_SIZE / 4, + POINT_SIZE - POINT_SIZE / 4, + 0x0000ffff); + test_utils_check_pixel (test_fb, + POINT_SIZE + POINT_SIZE / 4, + POINT_SIZE - POINT_SIZE / 4, + 0x00ff00ff); + test_utils_check_pixel (test_fb, + POINT_SIZE - POINT_SIZE / 4, + POINT_SIZE + POINT_SIZE / 4, + check_orientation ? + 0x00ffffff : + 0x0000ffff); + test_utils_check_pixel (test_fb, + POINT_SIZE + POINT_SIZE / 4, + POINT_SIZE + POINT_SIZE / 4, + check_orientation ? + 0xff0000ff : + 0x00ff00ff); + + /* When rendering without the point sprites all of the texture + coordinates should be 0,0 so it should get the top-left texel + which is blue */ + test_utils_check_region (test_fb, + POINT_SIZE * 3 - POINT_SIZE / 2 + 1, + POINT_SIZE - POINT_SIZE / 2 + 1, + POINT_SIZE - 2, POINT_SIZE - 2, + 0x0000ffff); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} + +void +test_point_sprite (void) +{ + do_test (FALSE /* don't check orientation */, + FALSE /* don't use GLSL */); +} + +void +test_point_sprite_orientation (void) +{ + do_test (TRUE /* check orientation */, + FALSE /* don't use GLSL */); +} + +void +test_point_sprite_glsl (void) +{ + do_test (FALSE /* don't check orientation */, + TRUE /* use GLSL */); +} diff --git a/cogl/tests/conform/test-premult.c b/cogl/tests/conform/test-premult.c new file mode 100644 index 0000000..fa60bdf --- /dev/null +++ b/cogl/tests/conform/test-premult.c @@ -0,0 +1,301 @@ +#include + +#include + +#include "test-utils.h" + +#define QUAD_WIDTH 32 + +#define RED 0 +#define GREEN 1 +#define BLUE 2 +#define ALPHA 3 + +#define MASK_RED(COLOR) ((COLOR & 0xff000000) >> 24) +#define MASK_GREEN(COLOR) ((COLOR & 0xff0000) >> 16) +#define MASK_BLUE(COLOR) ((COLOR & 0xff00) >> 8) +#define MASK_ALPHA(COLOR) (COLOR & 0xff) + +typedef enum _MakeTextureFlags +{ + TEXTURE_FLAG_SET_PREMULTIPLIED = 1, + TEXTURE_FLAG_SET_UNPREMULTIPLIED = 1<<1, +} MakeTextureFlags; + +static guchar * +gen_tex_data (uint32_t color) +{ + guchar *tex_data, *p; + uint8_t r = MASK_RED (color); + uint8_t g = MASK_GREEN (color); + uint8_t b = MASK_BLUE (color); + uint8_t a = MASK_ALPHA (color); + + tex_data = g_malloc (QUAD_WIDTH * QUAD_WIDTH * 4); + + for (p = tex_data + QUAD_WIDTH * QUAD_WIDTH * 4; p > tex_data;) + { + *(--p) = a; + *(--p) = b; + *(--p) = g; + *(--p) = r; + } + + return tex_data; +} + +static CoglTexture * +make_texture (uint32_t color, + CoglPixelFormat src_format, + MakeTextureFlags flags) +{ + CoglTexture2D *tex_2d; + guchar *tex_data = gen_tex_data (color); + CoglBitmap *bmp = cogl_bitmap_new_for_data (test_ctx, + QUAD_WIDTH, + QUAD_WIDTH, + src_format, + QUAD_WIDTH * 4, + tex_data); + + tex_2d = cogl_texture_2d_new_from_bitmap (bmp); + + if (flags & TEXTURE_FLAG_SET_PREMULTIPLIED) + cogl_texture_set_premultiplied (tex_2d, TRUE); + else if (flags & TEXTURE_FLAG_SET_UNPREMULTIPLIED) + cogl_texture_set_premultiplied (tex_2d, FALSE); + + cogl_object_unref (bmp); + g_free (tex_data); + + return tex_2d; +} + +static void +set_region (CoglTexture *tex, + uint32_t color, + CoglPixelFormat format) +{ + guchar *tex_data = gen_tex_data (color); + + cogl_texture_set_region (tex, + 0, 0, /* src x, y */ + 0, 0, /* dst x, y */ + QUAD_WIDTH, QUAD_WIDTH, /* dst width, height */ + QUAD_WIDTH, QUAD_WIDTH, /* src width, height */ + format, + 0, /* auto compute row stride */ + tex_data); +} + +static void +check_texture (CoglPipeline *pipeline, + CoglHandle material, + int x, + int y, + CoglTexture *tex, + uint32_t expected_result) +{ + /* Legacy */ + cogl_push_framebuffer (test_fb); + cogl_material_set_layer (material, 0, tex); + cogl_set_source (material); + cogl_rectangle (x * QUAD_WIDTH, + y * QUAD_WIDTH, + x * QUAD_WIDTH + QUAD_WIDTH, + y * QUAD_WIDTH + QUAD_WIDTH); + test_utils_check_pixel (test_fb, x * QUAD_WIDTH + QUAD_WIDTH / 2, y * QUAD_WIDTH + QUAD_WIDTH / 2, expected_result); + cogl_pop_framebuffer (); + + /* New API */ + cogl_pipeline_set_layer_texture (pipeline, 0, tex); + cogl_framebuffer_draw_rectangle (test_fb, pipeline, + x * QUAD_WIDTH, + y * QUAD_WIDTH, + x * QUAD_WIDTH + QUAD_WIDTH, + y * QUAD_WIDTH + QUAD_WIDTH); + test_utils_check_pixel (test_fb, x * QUAD_WIDTH + QUAD_WIDTH / 2, y * QUAD_WIDTH + QUAD_WIDTH / 2, expected_result); +} + +void +test_premult (void) +{ + CoglPipeline *pipeline; + CoglHandle material; + CoglTexture *tex; + + cogl_framebuffer_orthographic (test_fb, 0, 0, + cogl_framebuffer_get_width (test_fb), + cogl_framebuffer_get_height (test_fb), + -1, + 100); + + cogl_framebuffer_clear4f (test_fb, + COGL_BUFFER_BIT_COLOR, + 1.0f, 1.0f, 1.0f, 1.0f); + + /* Legacy */ + material = cogl_material_new (); + cogl_material_set_blend (material, + "RGBA = ADD (SRC_COLOR, 0)", NULL); + cogl_material_set_layer_combine (material, 0, + "RGBA = REPLACE (TEXTURE)", NULL); + + /* New API */ + pipeline = cogl_pipeline_new (test_ctx); + cogl_pipeline_set_blend (pipeline, + "RGBA = ADD (SRC_COLOR, 0)", NULL); + cogl_pipeline_set_layer_combine (pipeline, 0, + "RGBA = REPLACE (TEXTURE)", NULL); + + /* If the user explicitly specifies an unmultiplied internal format then + * Cogl shouldn't automatically premultiply the given texture data... */ + if (cogl_test_verbose ()) + g_print ("make_texture (0xff00ff80, " + "src = RGBA_8888, internal = RGBA_8888)\n"); + tex = make_texture (0xff00ff80, + COGL_PIXEL_FORMAT_RGBA_8888, /* src format */ + TEXTURE_FLAG_SET_UNPREMULTIPLIED); + check_texture (pipeline, material, 0, 0, /* position */ + tex, + 0xff00ff80); /* expected */ + + /* If the user explicitly requests a premultiplied internal format and + * gives unmultiplied src data then Cogl should always premultiply that + * for us */ + if (cogl_test_verbose ()) + g_print ("make_texture (0xff00ff80, " + "src = RGBA_8888, internal = RGBA_8888_PRE)\n"); + tex = make_texture (0xff00ff80, + COGL_PIXEL_FORMAT_RGBA_8888, /* src format */ + TEXTURE_FLAG_SET_PREMULTIPLIED); + check_texture (pipeline, material, 1, 0, /* position */ + tex, + 0x80008080); /* expected */ + + /* If the user doesn't explicitly declare that the texture is premultiplied + * then Cogl should assume it is by default should premultiply + * unpremultiplied texture data... + */ + if (cogl_test_verbose ()) + g_print ("make_texture (0xff00ff80, " + "src = RGBA_8888, internal = ANY)\n"); + tex = make_texture (0xff00ff80, + COGL_PIXEL_FORMAT_RGBA_8888, /* src format */ + 0); /* default premultiplied status */ + check_texture (pipeline, material, 2, 0, /* position */ + tex, + 0x80008080); /* expected */ + + /* If the user requests a premultiplied internal texture format and supplies + * premultiplied source data, Cogl should never modify that source data... + */ + if (cogl_test_verbose ()) + g_print ("make_texture (0x80008080, " + "src = RGBA_8888_PRE, " + "internal = RGBA_8888_PRE)\n"); + tex = make_texture (0x80008080, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, /* src format */ + TEXTURE_FLAG_SET_PREMULTIPLIED); + check_texture (pipeline, material, 3, 0, /* position */ + tex, + 0x80008080); /* expected */ + + /* If the user requests an unmultiplied internal texture format, but + * supplies premultiplied source data, then Cogl should always + * un-premultiply the source data... */ + if (cogl_test_verbose ()) + g_print ("make_texture (0x80008080, " + "src = RGBA_8888_PRE, internal = RGBA_8888)\n"); + tex = make_texture (0x80008080, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, /* src format */ + TEXTURE_FLAG_SET_UNPREMULTIPLIED); + check_texture (pipeline, material, 4, 0, /* position */ + tex, + 0xff00ff80); /* expected */ + + /* If the user allows any internal texture format and provides premultipled + * source data then by default Cogl shouldn't modify the source data... + * (In the future there will be additional Cogl API to control this + * behaviour) */ + if (cogl_test_verbose ()) + g_print ("make_texture (0x80008080, " + "src = RGBA_8888_PRE, internal = ANY)\n"); + tex = make_texture (0x80008080, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, /* src format */ + 0); /* default premultiplied status */ + check_texture (pipeline, material, 5, 0, /* position */ + tex, + 0x80008080); /* expected */ + + /* + * Test cogl_texture_set_region() .... + */ + + if (cogl_test_verbose ()) + g_print ("make_texture (0xDEADBEEF, " + "src = RGBA_8888, internal = RGBA_8888)\n"); + tex = make_texture (0xDEADBEEF, + COGL_PIXEL_FORMAT_RGBA_8888, /* src format */ + TEXTURE_FLAG_SET_UNPREMULTIPLIED); + if (cogl_test_verbose ()) + g_print ("set_region (0xff00ff80, RGBA_8888)\n"); + set_region (tex, 0xff00ff80, COGL_PIXEL_FORMAT_RGBA_8888); + check_texture (pipeline, material, 6, 0, /* position */ + tex, + 0xff00ff80); /* expected */ + + /* Updating a texture region for an unmultiplied texture using premultiplied + * region data should result in Cogl unmultiplying the given region data... + */ + if (cogl_test_verbose ()) + g_print ("make_texture (0xDEADBEEF, " + "src = RGBA_8888, internal = RGBA_8888)\n"); + tex = make_texture (0xDEADBEEF, + COGL_PIXEL_FORMAT_RGBA_8888, /* src format */ + TEXTURE_FLAG_SET_UNPREMULTIPLIED); + if (cogl_test_verbose ()) + g_print ("set_region (0x80008080, RGBA_8888_PRE)\n"); + set_region (tex, 0x80008080, COGL_PIXEL_FORMAT_RGBA_8888_PRE); + check_texture (pipeline, material, 7, 0, /* position */ + tex, + 0xff00ff80); /* expected */ + + + if (cogl_test_verbose ()) + g_print ("make_texture (0xDEADBEEF, " + "src = RGBA_8888_PRE, " + "internal = RGBA_8888_PRE)\n"); + tex = make_texture (0xDEADBEEF, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, /* src format */ + TEXTURE_FLAG_SET_PREMULTIPLIED); + if (cogl_test_verbose ()) + g_print ("set_region (0x80008080, RGBA_8888_PRE)\n"); + set_region (tex, 0x80008080, COGL_PIXEL_FORMAT_RGBA_8888_PRE); + check_texture (pipeline, material, 8, 0, /* position */ + tex, + 0x80008080); /* expected */ + + + /* Updating a texture region for a premultiplied texture using unmultiplied + * region data should result in Cogl premultiplying the given region data... + */ + if (cogl_test_verbose ()) + g_print ("make_texture (0xDEADBEEF, " + "src = RGBA_8888_PRE, " + "internal = RGBA_8888_PRE)\n"); + tex = make_texture (0xDEADBEEF, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, /* src format */ + TEXTURE_FLAG_SET_PREMULTIPLIED); + if (cogl_test_verbose ()) + g_print ("set_region (0xff00ff80, RGBA_8888)\n"); + set_region (tex, 0xff00ff80, COGL_PIXEL_FORMAT_RGBA_8888); + check_texture (pipeline, material, 9, 0, /* position */ + tex, + 0x80008080); /* expected */ + + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} + diff --git a/cogl/tests/conform/test-primitive-and-journal.c b/cogl/tests/conform/test-primitive-and-journal.c new file mode 100644 index 0000000..f978cd5 --- /dev/null +++ b/cogl/tests/conform/test-primitive-and-journal.c @@ -0,0 +1,122 @@ +#include + +#include "test-utils.h" + +typedef CoglVertexP2C4 Vertex; + +static void +setup_orthographic_modelview (void) +{ + CoglMatrix matrix; + int fb_width = cogl_framebuffer_get_width (test_fb); + int fb_height = cogl_framebuffer_get_height (test_fb); + + /* Set up a non-identity modelview matrix. When the journal is + * flushed it will usually flush the identity matrix. Using the + * non-default matrix ensures that we test that Cogl restores the + * matrix we asked for. The matrix sets up an orthographic transform + * in the modelview matrix */ + + cogl_matrix_init_identity (&matrix); + cogl_matrix_orthographic (&matrix, + 0.0f, 0.0f, /* x_1 y_1 */ + fb_width, + fb_height, + -1.0f, /* nearval */ + 1.0f /* farval */); + cogl_framebuffer_set_modelview_matrix (test_fb, &matrix); +} + +static void +create_primitives (CoglPrimitive *primitives[2]) +{ + static const Vertex vertex_data[8] = + { + /* triangle strip 1 */ + { 0, 0, 255, 0, 0, 255 }, + { 0, 100, 255, 0, 0, 255 }, + { 100, 0, 255, 0, 0, 255 }, + { 100, 100, 255, 0, 0, 255 }, + /* triangle strip 2 */ + { 200, 0, 0, 0, 255, 255 }, + { 200, 100, 0, 0, 255, 255 }, + { 300, 0, 0, 0, 255, 255 }, + { 300, 100, 0, 0, 255, 255 }, + }; + + primitives[0] = cogl_primitive_new_p2c4 (test_ctx, + COGL_VERTICES_MODE_TRIANGLE_STRIP, + G_N_ELEMENTS (vertex_data), + vertex_data); + cogl_primitive_set_n_vertices (primitives[0], 4); + + primitives[1] = cogl_primitive_copy (primitives[0]); + cogl_primitive_set_first_vertex (primitives[1], 4); + cogl_primitive_set_n_vertices (primitives[1], 4); +} + +static CoglPipeline * +create_pipeline (void) +{ + CoglPipeline *pipeline = cogl_pipeline_new (test_ctx); + + cogl_pipeline_set_color4ub (pipeline, 0, 255, 0, 255); + + return pipeline; +} + +void +test_primitive_and_journal (void) +{ + CoglPrimitive *primitives[2]; + CoglPipeline *pipeline; + + setup_orthographic_modelview (); + create_primitives (primitives); + pipeline = create_pipeline (); + + /* Set a clip to clip all three rectangles to just the bottom half. + * The journal flushes its own clip state so this verifies that the + * clip state is correctly restored for the second primitive. */ + cogl_framebuffer_push_rectangle_clip (test_fb, + 0, 50, 300, 100); + + cogl_primitive_draw (primitives[0], test_fb, pipeline); + + /* Draw a rectangle using the journal in-between the two primitives. + * This should test that the journal gets flushed correctly and that + * the modelview matrix is restored. Half of the rectangle should be + * overriden by the second primitive */ + cogl_framebuffer_draw_rectangle (test_fb, + pipeline, + 100, 0, /* x1/y1 */ + 300, 100 /* x2/y2 */); + + cogl_primitive_draw (primitives[1], test_fb, pipeline); + + /* Check the three rectangles */ + test_utils_check_region (test_fb, + 1, 51, + 98, 48, + 0xff0000ff); + test_utils_check_region (test_fb, + 101, 51, + 98, 48, + 0x00ff00ff); + test_utils_check_region (test_fb, + 201, 51, + 98, 48, + 0x0000ffff); + + /* Check that the top half of all of the rectangles was clipped */ + test_utils_check_region (test_fb, + 1, 1, + 298, 48, + 0x000000ff); + + cogl_framebuffer_pop_clip (test_fb); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} + diff --git a/cogl/tests/conform/test-primitive.c b/cogl/tests/conform/test-primitive.c new file mode 100644 index 0000000..db264fc --- /dev/null +++ b/cogl/tests/conform/test-primitive.c @@ -0,0 +1,334 @@ +#include +#include +#include + +#include "test-utils.h" + +typedef struct _TestState +{ + int fb_width; + int fb_height; +} TestState; + +#define PRIM_COLOR 0xff00ffff +#define TEX_COLOR 0x0000ffff + +#define N_ATTRIBS 8 + +typedef CoglPrimitive * (* TestPrimFunc) (CoglContext *ctx, uint32_t *expected_color); + +static CoglPrimitive * +test_prim_p2 (CoglContext *ctx, uint32_t *expected_color) +{ + static const CoglVertexP2 verts[] = + { { 0, 0 }, { 0, 10 }, { 10, 0 } }; + + return cogl_primitive_new_p2 (test_ctx, + COGL_VERTICES_MODE_TRIANGLES, + 3, /* n_vertices */ + verts); +} + +static CoglPrimitive * +test_prim_p3 (CoglContext *ctx, uint32_t *expected_color) +{ + static const CoglVertexP3 verts[] = + { { 0, 0, 0 }, { 0, 10, 0 }, { 10, 0, 0 } }; + + return cogl_primitive_new_p3 (test_ctx, + COGL_VERTICES_MODE_TRIANGLES, + 3, /* n_vertices */ + verts); +} + +static CoglPrimitive * +test_prim_p2c4 (CoglContext *ctx, uint32_t *expected_color) +{ + static const CoglVertexP2C4 verts[] = + { { 0, 0, 255, 255, 0, 255 }, + { 0, 10, 255, 255, 0, 255 }, + { 10, 0, 255, 255, 0, 255 } }; + + *expected_color = 0xffff00ff; + + return cogl_primitive_new_p2c4 (test_ctx, + COGL_VERTICES_MODE_TRIANGLES, + 3, /* n_vertices */ + verts); +} + +static CoglPrimitive * +test_prim_p3c4 (CoglContext *ctx, uint32_t *expected_color) +{ + static const CoglVertexP3C4 verts[] = + { { 0, 0, 0, 255, 255, 0, 255 }, + { 0, 10, 0, 255, 255, 0, 255 }, + { 10, 0, 0, 255, 255, 0, 255 } }; + + *expected_color = 0xffff00ff; + + return cogl_primitive_new_p3c4 (test_ctx, + COGL_VERTICES_MODE_TRIANGLES, + 3, /* n_vertices */ + verts); +} + +static CoglPrimitive * +test_prim_p2t2 (CoglContext *ctx, uint32_t *expected_color) +{ + static const CoglVertexP2T2 verts[] = + { { 0, 0, 1, 0 }, + { 0, 10, 1, 0 }, + { 10, 0, 1, 0 } }; + + *expected_color = TEX_COLOR; + + return cogl_primitive_new_p2t2 (test_ctx, + COGL_VERTICES_MODE_TRIANGLES, + 3, /* n_vertices */ + verts); +} + +static CoglPrimitive * +test_prim_p3t2 (CoglContext *ctx, uint32_t *expected_color) +{ + static const CoglVertexP3T2 verts[] = + { { 0, 0, 0, 1, 0 }, + { 0, 10, 0, 1, 0 }, + { 10, 0, 0, 1, 0 } }; + + *expected_color = TEX_COLOR; + + return cogl_primitive_new_p3t2 (test_ctx, + COGL_VERTICES_MODE_TRIANGLES, + 3, /* n_vertices */ + verts); +} + +static CoglPrimitive * +test_prim_p2t2c4 (CoglContext *ctx, uint32_t *expected_color) +{ + static const CoglVertexP2T2C4 verts[] = + { { 0, 0, 1, 0, 0xff, 0xff, 0xf0, 0xff }, + { 0, 10, 1, 0, 0xff, 0xff, 0xf0, 0xff }, + { 10, 0, 1, 0, 0xff, 0xff, 0xf0, 0xff } }; + + /* The blue component of the texture color should be replaced with 0xf0 */ + *expected_color = (TEX_COLOR & 0xffff00ff) | 0x0000f000; + + return cogl_primitive_new_p2t2c4 (test_ctx, + COGL_VERTICES_MODE_TRIANGLES, + 3, /* n_vertices */ + verts); +} + +static CoglPrimitive * +test_prim_p3t2c4 (CoglContext *ctx, uint32_t *expected_color) +{ + static const CoglVertexP3T2C4 verts[] = + { { 0, 0, 0, 1, 0, 0xff, 0xff, 0xf0, 0xff }, + { 0, 10, 0, 1, 0, 0xff, 0xff, 0xf0, 0xff }, + { 10, 0, 0, 1, 0, 0xff, 0xff, 0xf0, 0xff } }; + + /* The blue component of the texture color should be replaced with 0xf0 */ + *expected_color = (TEX_COLOR & 0xffff00ff) | 0x0000f000; + + return cogl_primitive_new_p3t2c4 (test_ctx, + COGL_VERTICES_MODE_TRIANGLES, + 3, /* n_vertices */ + verts); +} + +static const TestPrimFunc +test_prim_funcs[] = + { + test_prim_p2, + test_prim_p3, + test_prim_p2c4, + test_prim_p3c4, + test_prim_p2t2, + test_prim_p3t2, + test_prim_p2t2c4, + test_prim_p3t2c4 + }; + +static void +test_paint (TestState *state) +{ + CoglPipeline *pipeline; + CoglTexture *tex; + uint8_t tex_data[6]; + int i; + + /* Create a two pixel texture. The first pixel is white and the + second pixel is tex_color. The assumption is that if no texture + coordinates are specified then it will default to 0,0 and get + white */ + tex_data[0] = 255; + tex_data[1] = 255; + tex_data[2] = 255; + tex_data[3] = (TEX_COLOR >> 24) & 0xff; + tex_data[4] = (TEX_COLOR >> 16) & 0xff; + tex_data[5] = (TEX_COLOR >> 8) & 0xff; + tex = test_utils_texture_new_from_data (test_ctx, + 2, 1, /* size */ + TEST_UTILS_TEXTURE_NO_ATLAS, + COGL_PIXEL_FORMAT_RGB_888, + 6, /* rowstride */ + tex_data); + pipeline = cogl_pipeline_new (test_ctx); + cogl_pipeline_set_color4ub (pipeline, + (PRIM_COLOR >> 24) & 0xff, + (PRIM_COLOR >> 16) & 0xff, + (PRIM_COLOR >> 8) & 0xff, + (PRIM_COLOR >> 0) & 0xff); + cogl_pipeline_set_layer_texture (pipeline, 0, tex); + cogl_object_unref (tex); + + for (i = 0; i < G_N_ELEMENTS (test_prim_funcs); i++) + { + CoglPrimitive *prim; + uint32_t expected_color = PRIM_COLOR; + + prim = test_prim_funcs[i] (test_ctx, &expected_color); + + cogl_framebuffer_push_matrix (test_fb); + cogl_framebuffer_translate (test_fb, i * 10, 0, 0); + cogl_primitive_draw (prim, test_fb, pipeline); + cogl_framebuffer_pop_matrix (test_fb); + + test_utils_check_pixel (test_fb, i * 10 + 2, 2, expected_color); + + cogl_object_unref (prim); + } + + cogl_object_unref (pipeline); +} + +static CoglBool +get_attributes_cb (CoglPrimitive *prim, + CoglAttribute *attrib, + void *user_data) +{ + CoglAttribute ***p = user_data; + *((* p)++) = attrib; + return TRUE; +} + +static int +compare_pointers (const void *a, const void *b) +{ + CoglAttribute *pa = *(CoglAttribute **) a; + CoglAttribute *pb = *(CoglAttribute **) b; + + if (pa < pb) + return -1; + else if (pa > pb) + return 1; + else + return 0; +} + +static void +test_copy (TestState *state) +{ + static const uint16_t indices_data[2] = { 1, 2 }; + CoglAttributeBuffer *buffer = + cogl_attribute_buffer_new (test_ctx, 100, NULL); + CoglAttribute *attributes[N_ATTRIBS]; + CoglAttribute *attributes_a[N_ATTRIBS], *attributes_b[N_ATTRIBS]; + CoglAttribute **p; + CoglPrimitive *prim_a, *prim_b; + CoglIndices *indices; + int i; + + for (i = 0; i < N_ATTRIBS; i++) + { + char *name = g_strdup_printf ("foo_%i", i); + attributes[i] = cogl_attribute_new (buffer, + name, + 16, /* stride */ + 16, /* offset */ + 2, /* components */ + COGL_ATTRIBUTE_TYPE_FLOAT); + g_free (name); + } + + prim_a = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, + 8, /* n_vertices */ + attributes, + N_ATTRIBS); + + indices = cogl_indices_new (test_ctx, + COGL_INDICES_TYPE_UNSIGNED_SHORT, + indices_data, + 2 /* n_indices */); + + cogl_primitive_set_first_vertex (prim_a, 12); + cogl_primitive_set_indices (prim_a, indices, 2); + + prim_b = cogl_primitive_copy (prim_a); + + p = attributes_a; + cogl_primitive_foreach_attribute (prim_a, + get_attributes_cb, + &p); + g_assert_cmpint (p - attributes_a, ==, N_ATTRIBS); + + p = attributes_b; + cogl_primitive_foreach_attribute (prim_b, + get_attributes_cb, + &p); + g_assert_cmpint (p - attributes_b, ==, N_ATTRIBS); + + qsort (attributes_a, N_ATTRIBS, sizeof (CoglAttribute *), compare_pointers); + qsort (attributes_b, N_ATTRIBS, sizeof (CoglAttribute *), compare_pointers); + + g_assert (memcmp (attributes_a, attributes_b, sizeof (attributes_a)) == 0); + + g_assert_cmpint (cogl_primitive_get_first_vertex (prim_a), + ==, + cogl_primitive_get_first_vertex (prim_b)); + + g_assert_cmpint (cogl_primitive_get_n_vertices (prim_a), + ==, + cogl_primitive_get_n_vertices (prim_b)); + + g_assert_cmpint (cogl_primitive_get_mode (prim_a), + ==, + cogl_primitive_get_mode (prim_b)); + + g_assert (cogl_primitive_get_indices (prim_a) == + cogl_primitive_get_indices (prim_b)); + + cogl_object_unref (prim_a); + cogl_object_unref (prim_b); + cogl_object_unref (indices); + + for (i = 0; i < N_ATTRIBS; i++) + cogl_object_unref (attributes[i]); + + cogl_object_unref (buffer); +} + +void +test_primitive (void) +{ + TestState state; + + state.fb_width = cogl_framebuffer_get_width (test_fb); + state.fb_height = cogl_framebuffer_get_height (test_fb); + + cogl_framebuffer_orthographic (test_fb, + 0, 0, + state.fb_width, + state.fb_height, + -1, + 100); + + test_paint (&state); + test_copy (&state); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} diff --git a/cogl/tests/conform/test-read-texture-formats.c b/cogl/tests/conform/test-read-texture-formats.c new file mode 100644 index 0000000..b4e3b0f --- /dev/null +++ b/cogl/tests/conform/test-read-texture-formats.c @@ -0,0 +1,222 @@ +#include +#include + +#include "test-utils.h" + +/* + * This tests reading back an RGBA texture in all of the available + * pixel formats + */ + +static const uint8_t tex_data[4] = { 0x12, 0x34, 0x56, 0x78 }; + +static void +test_read_byte (CoglTexture2D *tex_2d, + CoglPixelFormat format, + uint8_t expected_byte) +{ + uint8_t received_byte; + + cogl_texture_get_data (tex_2d, + format, + 1, /* rowstride */ + &received_byte); + + g_assert_cmpint (expected_byte, ==, received_byte); +} + +static void +test_read_short (CoglTexture2D *tex_2d, + CoglPixelFormat format, + ...) +{ + va_list ap; + int bits; + uint16_t received_value; + uint16_t expected_value = 0; + char *received_value_str; + char *expected_value_str; + int bits_sum = 0; + + cogl_texture_get_data (tex_2d, + format, + 2, /* rowstride */ + (uint8_t *) &received_value); + + va_start (ap, format); + + /* Convert the va args into a single 16-bit expected value */ + while ((bits = va_arg (ap, int)) != -1) + { + int value = (va_arg (ap, int) * ((1 << bits) - 1) + 128) / 255; + + bits_sum += bits; + + expected_value |= value << (16 - bits_sum); + } + + va_end (ap); + + received_value_str = g_strdup_printf ("0x%04x", received_value); + expected_value_str = g_strdup_printf ("0x%04x", expected_value); + g_assert_cmpstr (received_value_str, ==, expected_value_str); + g_free (received_value_str); + g_free (expected_value_str); +} + +static void +test_read_888 (CoglTexture2D *tex_2d, + CoglPixelFormat format, + uint32_t expected_pixel) +{ + uint8_t pixel[4]; + + cogl_texture_get_data (tex_2d, + format, + 4, /* rowstride */ + pixel); + + test_utils_compare_pixel (pixel, expected_pixel); +} + +static void +test_read_88 (CoglTexture2D *tex_2d, + CoglPixelFormat format, + uint32_t expected_pixel) +{ + uint8_t pixel[4]; + + pixel[2] = 0x00; + + cogl_texture_get_data (tex_2d, + format, + 2, /* rowstride */ + pixel); + + test_utils_compare_pixel (pixel, expected_pixel); +} + +static void +test_read_8888 (CoglTexture2D *tex_2d, + CoglPixelFormat format, + uint32_t expected_pixel) +{ + uint32_t received_pixel; + char *received_value_str; + char *expected_value_str; + + cogl_texture_get_data (tex_2d, + format, + 4, /* rowstride */ + (uint8_t *) &received_pixel); + + received_pixel = GUINT32_FROM_BE (received_pixel); + + received_value_str = g_strdup_printf ("0x%08x", received_pixel); + expected_value_str = g_strdup_printf ("0x%08x", expected_pixel); + g_assert_cmpstr (received_value_str, ==, expected_value_str); + g_free (received_value_str); + g_free (expected_value_str); +} + +static void +test_read_int (CoglTexture2D *tex_2d, + CoglPixelFormat format, + ...) +{ + va_list ap; + int bits; + uint32_t received_value; + uint32_t expected_value = 0; + char *received_value_str; + char *expected_value_str; + int bits_sum = 0; + + cogl_texture_get_data (tex_2d, + format, + 4, /* rowstride */ + (uint8_t *) &received_value); + + va_start (ap, format); + + /* Convert the va args into a single 32-bit expected value */ + while ((bits = va_arg (ap, int)) != -1) + { + uint32_t value = (va_arg (ap, int) * ((1 << bits) - 1) + 128) / 255; + + bits_sum += bits; + + expected_value |= value << (32 - bits_sum); + } + + va_end (ap); + + received_value_str = g_strdup_printf ("0x%08x", received_value); + expected_value_str = g_strdup_printf ("0x%08x", expected_value); + g_assert_cmpstr (received_value_str, ==, expected_value_str); + g_free (received_value_str); + g_free (expected_value_str); +} + +void +test_read_texture_formats (void) +{ + CoglTexture2D *tex_2d; + + tex_2d = cogl_texture_2d_new_from_data (test_ctx, + 1, 1, /* width / height */ + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + 4, /* rowstride */ + tex_data, + NULL); + + test_read_byte (tex_2d, COGL_PIXEL_FORMAT_A_8, 0x78); + +#if 0 + /* I'm not sure what's the right value to put here because Nvidia + and Mesa seem to behave differently so one of them must be + wrong. */ + test_read_byte (tex_2d, COGL_PIXEL_FORMAT_G_8, 0x9c); +#endif + + /* We should always be able to read into an RG buffer regardless of + * whether RG textures are supported because Cogl will do the + * conversion for us */ + test_read_88 (tex_2d, COGL_PIXEL_FORMAT_RG_88, 0x123400ff); + + test_read_short (tex_2d, COGL_PIXEL_FORMAT_RGB_565, + 5, 0x12, 6, 0x34, 5, 0x56, + -1); + test_read_short (tex_2d, COGL_PIXEL_FORMAT_RGBA_4444_PRE, + 4, 0x12, 4, 0x34, 4, 0x56, 4, 0x78, + -1); + test_read_short (tex_2d, COGL_PIXEL_FORMAT_RGBA_5551_PRE, + 5, 0x12, 5, 0x34, 5, 0x56, 1, 0x78, + -1); + + test_read_888 (tex_2d, COGL_PIXEL_FORMAT_RGB_888, 0x123456ff); + test_read_888 (tex_2d, COGL_PIXEL_FORMAT_BGR_888, 0x563412ff); + + test_read_8888 (tex_2d, COGL_PIXEL_FORMAT_RGBA_8888_PRE, 0x12345678); + test_read_8888 (tex_2d, COGL_PIXEL_FORMAT_BGRA_8888_PRE, 0x56341278); + test_read_8888 (tex_2d, COGL_PIXEL_FORMAT_ARGB_8888_PRE, 0x78123456); + test_read_8888 (tex_2d, COGL_PIXEL_FORMAT_ABGR_8888_PRE, 0x78563412); + + test_read_int (tex_2d, COGL_PIXEL_FORMAT_RGBA_1010102_PRE, + 10, 0x12, 10, 0x34, 10, 0x56, 2, 0x78, + -1); + test_read_int (tex_2d, COGL_PIXEL_FORMAT_BGRA_1010102_PRE, + 10, 0x56, 10, 0x34, 10, 0x12, 2, 0x78, + -1); + test_read_int (tex_2d, COGL_PIXEL_FORMAT_ARGB_2101010_PRE, + 2, 0x78, 10, 0x12, 10, 0x34, 10, 0x56, + -1); + test_read_int (tex_2d, COGL_PIXEL_FORMAT_ABGR_2101010_PRE, + 2, 0x78, 10, 0x56, 10, 0x34, 10, 0x12, + -1); + + cogl_object_unref (tex_2d); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} diff --git a/cogl/tests/conform/test-snippets.c b/cogl/tests/conform/test-snippets.c new file mode 100644 index 0000000..a251fc1 --- /dev/null +++ b/cogl/tests/conform/test-snippets.c @@ -0,0 +1,815 @@ +#include + +#include + +#include "test-utils.h" + +typedef struct _TestState +{ + int fb_width, fb_height; +} TestState; + +typedef void (* SnippetTestFunc) (TestState *state); + +static CoglPipeline * +create_texture_pipeline (TestState *state) +{ + CoglPipeline *pipeline; + CoglTexture *tex; + static const uint8_t tex_data[] = + { + 0xff, 0x00, 0x00, 0xff, /* red */ 0x00, 0xff, 0x00, 0xff, /* green */ + 0x00, 0x00, 0xff, 0xff, /* blue */ 0xff, 0xff, 0x00, 0xff, /* yellow */ + }; + + tex = test_utils_texture_new_from_data (test_ctx, + 2, 2, /* width/height */ + TEST_UTILS_TEXTURE_NO_ATLAS, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + 8, /* rowstride */ + tex_data); + + pipeline = cogl_pipeline_new (test_ctx); + + cogl_pipeline_set_layer_texture (pipeline, 0, tex); + + cogl_pipeline_set_layer_filters (pipeline, 0, + COGL_PIPELINE_FILTER_NEAREST, + COGL_PIPELINE_FILTER_NEAREST); + + cogl_object_unref (tex); + + return pipeline; +} + +static void +simple_fragment_snippet (TestState *state) +{ + CoglPipeline *pipeline; + CoglSnippet *snippet; + + /* Simple fragment snippet */ + pipeline = cogl_pipeline_new (test_ctx); + + cogl_pipeline_set_color4ub (pipeline, 255, 0, 0, 255); + + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, + NULL, /* declarations */ + "cogl_color_out.g += 1.0;"); + cogl_pipeline_add_snippet (pipeline, snippet); + cogl_object_unref (snippet); + + cogl_framebuffer_draw_rectangle (test_fb, pipeline, 0, 0, 10, 10); + + cogl_object_unref (pipeline); + + test_utils_check_pixel (test_fb, 5, 5, 0xffff00ff); +} + +static void +simple_vertex_snippet (TestState *state) +{ + CoglPipeline *pipeline; + CoglSnippet *snippet; + + /* Simple vertex snippet */ + pipeline = cogl_pipeline_new (test_ctx); + + cogl_pipeline_set_color4ub (pipeline, 255, 0, 0, 255); + + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX, + NULL, + "cogl_color_out.b += 1.0;"); + cogl_pipeline_add_snippet (pipeline, snippet); + cogl_object_unref (snippet); + + cogl_framebuffer_draw_rectangle (test_fb, pipeline, 10, 0, 20, 10); + + cogl_object_unref (pipeline); + + test_utils_check_pixel (test_fb, 15, 5, 0xff00ffff); +} + +static void +shared_uniform (TestState *state) +{ + CoglPipeline *pipeline; + CoglSnippet *snippet; + int location; + + /* Snippets sharing a uniform across the vertex and fragment + hooks */ + pipeline = cogl_pipeline_new (test_ctx); + + location = cogl_pipeline_get_uniform_location (pipeline, "a_value"); + cogl_pipeline_set_uniform_1f (pipeline, location, 0.25f); + + cogl_pipeline_set_color4ub (pipeline, 255, 0, 0, 255); + + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX, + "uniform float a_value;", + "cogl_color_out.b += a_value;"); + cogl_pipeline_add_snippet (pipeline, snippet); + cogl_object_unref (snippet); + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, + "uniform float a_value;", + "cogl_color_out.b += a_value;"); + cogl_pipeline_add_snippet (pipeline, snippet); + cogl_object_unref (snippet); + + cogl_framebuffer_draw_rectangle (test_fb, + pipeline, + 20, 0, 30, 10); + + cogl_object_unref (pipeline); + + test_utils_check_pixel (test_fb, 25, 5, 0xff0080ff); +} + +static void +lots_snippets (TestState *state) +{ + CoglPipeline *pipeline; + CoglSnippet *snippet; + int location; + int i; + + /* Lots of snippets on one pipeline */ + pipeline = cogl_pipeline_new (test_ctx); + + cogl_pipeline_set_color4ub (pipeline, 0, 0, 0, 255); + + for (i = 0; i < 3; i++) + { + char letter = 'x' + i; + char *uniform_name = g_strdup_printf ("%c_value", letter); + char *declarations = g_strdup_printf ("uniform float %s;\n", + uniform_name); + char *code = g_strdup_printf ("cogl_color_out.%c = %s;\n", + letter, + uniform_name); + + location = cogl_pipeline_get_uniform_location (pipeline, uniform_name); + cogl_pipeline_set_uniform_1f (pipeline, location, (i + 1) * 0.1f); + + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, + declarations, + code); + cogl_pipeline_add_snippet (pipeline, snippet); + cogl_object_unref (snippet); + + g_free (code); + g_free (uniform_name); + g_free (declarations); + } + + cogl_framebuffer_draw_rectangle (test_fb, pipeline, 30, 0, 40, 10); + + cogl_object_unref (pipeline); + + test_utils_check_pixel (test_fb, 35, 5, 0x19334cff); +} + +static void +shared_variable_pre_post (TestState *state) +{ + CoglPipeline *pipeline; + CoglSnippet *snippet; + + /* Test that the pre string can declare variables used by the post + string */ + pipeline = cogl_pipeline_new (test_ctx); + + cogl_pipeline_set_color4ub (pipeline, 255, 255, 255, 255); + + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, + NULL, /* declarations */ + "cogl_color_out = redvec;"); + cogl_snippet_set_pre (snippet, "vec4 redvec = vec4 (1.0, 0.0, 0.0, 1.0);"); + cogl_pipeline_add_snippet (pipeline, snippet); + cogl_object_unref (snippet); + + cogl_framebuffer_draw_rectangle (test_fb, pipeline, 40, 0, 50, 10); + + cogl_object_unref (pipeline); + + test_utils_check_pixel (test_fb, 45, 5, 0xff0000ff); +} + +static void +test_pipeline_caching (TestState *state) +{ + CoglPipeline *pipeline; + CoglSnippet *snippet; + + /* Check that the pipeline caching works when unrelated pipelines + share snippets state. It's too hard to actually assert this in + the conformance test but at least it should be possible to see by + setting COGL_DEBUG=show-source to check whether this shader gets + generated twice */ + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, + "/* This comment should only be seen ONCE\n" + " when COGL_DEBUG=show-source is TRUE\n" + " even though it is used in two different\n" + " unrelated pipelines */", + "cogl_color_out = vec4 (0.0, 1.0, 0.0, 1.0);\n"); + + pipeline = cogl_pipeline_new (test_ctx); + cogl_pipeline_add_snippet (pipeline, snippet); + cogl_framebuffer_draw_rectangle (test_fb, pipeline, 50, 0, 60, 10); + cogl_object_unref (pipeline); + + pipeline = cogl_pipeline_new (test_ctx); + cogl_pipeline_add_snippet (pipeline, snippet); + cogl_framebuffer_draw_rectangle (test_fb, pipeline, 60, 0, 70, 10); + cogl_object_unref (pipeline); + + cogl_object_unref (snippet); + + test_utils_check_pixel (test_fb, 55, 5, 0x00ff00ff); + test_utils_check_pixel (test_fb, 65, 5, 0x00ff00ff); +} + +static void +test_replace_string (TestState *state) +{ + CoglPipeline *pipeline; + CoglSnippet *snippet; + + /* Check the replace string */ + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, NULL, NULL); + cogl_snippet_set_pre (snippet, + "cogl_color_out = vec4 (0.0, 0.5, 0.0, 1.0);"); + /* Remove the generated output. If the replace string isn't working + then the code from the pre string would get overwritten with + white */ + cogl_snippet_set_replace (snippet, "/* do nothing */"); + cogl_snippet_set_post (snippet, + "cogl_color_out += vec4 (0.5, 0.0, 0.0, 1.0);"); + + pipeline = cogl_pipeline_new (test_ctx); + cogl_pipeline_add_snippet (pipeline, snippet); + cogl_framebuffer_draw_rectangle (test_fb, pipeline, 70, 0, 80, 10); + cogl_object_unref (pipeline); + + cogl_object_unref (snippet); + + test_utils_check_pixel (test_fb, 75, 5, 0x808000ff); +} + +static void +test_texture_lookup_hook (TestState *state) +{ + CoglPipeline *pipeline; + CoglSnippet *snippet; + + /* Check the texture lookup hook */ + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_LOOKUP, + NULL, + "cogl_texel.b += 1.0;"); + /* Flip the texture coordinates around the y axis so that it will + get the green texel */ + cogl_snippet_set_pre (snippet, "cogl_tex_coord.x = 1.0 - cogl_tex_coord.x;"); + + pipeline = create_texture_pipeline (state); + cogl_pipeline_add_layer_snippet (pipeline, 0, snippet); + cogl_framebuffer_draw_textured_rectangle (test_fb, + pipeline, + 80, 0, 90, 10, + 0, 0, 0, 0); + cogl_object_unref (pipeline); + + cogl_object_unref (snippet); + + test_utils_check_pixel (test_fb, 85, 5, 0x00ffffff); +} + +static void +test_multiple_samples (TestState *state) +{ + CoglPipeline *pipeline; + CoglSnippet *snippet; + + /* Check that we can use the passed in sampler in the texture lookup + to sample multiple times */ + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_LOOKUP, + NULL, + NULL); + cogl_snippet_set_replace (snippet, + "cogl_texel = " + "texture2D (cogl_sampler, vec2 (0.25, 0.25)) + " + "texture2D (cogl_sampler, vec2 (0.75, 0.25));"); + + pipeline = create_texture_pipeline (state); + cogl_pipeline_add_layer_snippet (pipeline, 0, snippet); + cogl_framebuffer_draw_rectangle (test_fb, pipeline, 0, 0, 10, 10); + cogl_object_unref (pipeline); + + cogl_object_unref (snippet); + + test_utils_check_pixel (test_fb, 5, 5, 0xffff00ff); +} + +static void +test_replace_lookup_hook (TestState *state) +{ + CoglPipeline *pipeline; + CoglSnippet *snippet; + + /* Check replacing the texture lookup hook */ + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_LOOKUP, NULL, NULL); + cogl_snippet_set_replace (snippet, "cogl_texel = vec4 (0.0, 0.0, 1.0, 0.0);"); + + pipeline = create_texture_pipeline (state); + cogl_pipeline_add_layer_snippet (pipeline, 0, snippet); + cogl_framebuffer_draw_textured_rectangle (test_fb, + pipeline, + 90, 0, 100, 10, + 0, 0, 0, 0); + cogl_object_unref (pipeline); + + cogl_object_unref (snippet); + + test_utils_check_pixel (test_fb, 95, 5, 0x0000ffff); +} + +static void +test_replace_snippet (TestState *state) +{ + CoglPipeline *pipeline; + CoglSnippet *snippet; + + /* Test replacing a previous snippet */ + pipeline = create_texture_pipeline (state); + + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, + NULL, + "cogl_color_out = vec4 (0.5, 0.5, 0.5, 1.0);"); + cogl_pipeline_add_snippet (pipeline, snippet); + cogl_object_unref (snippet); + + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, NULL, NULL); + cogl_snippet_set_pre (snippet, "cogl_color_out = vec4 (1.0, 1.0, 1.0, 1.0);"); + cogl_snippet_set_replace (snippet, + "cogl_color_out *= vec4 (1.0, 0.0, 0.0, 1.0);"); + cogl_pipeline_add_snippet (pipeline, snippet); + cogl_object_unref (snippet); + + cogl_framebuffer_draw_textured_rectangle (test_fb, + pipeline, + 100, 0, 110, 10, + 0, 0, 0, 0); + cogl_object_unref (pipeline); + + test_utils_check_pixel (test_fb, 105, 5, 0xff0000ff); +} + +static void +test_replace_fragment_layer (TestState *state) +{ + CoglPipeline *pipeline; + CoglSnippet *snippet; + + /* Test replacing the fragment layer code */ + pipeline = create_texture_pipeline (state); + + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_LAYER_FRAGMENT, NULL, NULL); + cogl_snippet_set_replace (snippet, "cogl_layer = vec4 (0.0, 0.0, 1.0, 1.0);"); + cogl_pipeline_add_layer_snippet (pipeline, 0, snippet); + cogl_object_unref (snippet); + + /* Add a second layer which samples from the texture in the first + layer. The snippet override should cause the first layer not to + generate the code for the texture lookup but this second layer + should still be able to cause it to be generated */ + cogl_pipeline_set_layer_combine (pipeline, 1, + "RGB = ADD(TEXTURE_0, PREVIOUS)" + "A = REPLACE(PREVIOUS)", + NULL); + + cogl_framebuffer_draw_textured_rectangle (test_fb, + pipeline, + 110, 0, 120, 10, + 0, 0, 0, 0); + cogl_object_unref (pipeline); + + test_utils_check_pixel (test_fb, 115, 5, 0xff00ffff); +} + +static void +test_modify_fragment_layer (TestState *state) +{ + CoglPipeline *pipeline; + CoglSnippet *snippet; + + /* Test modifying the fragment layer code */ + pipeline = cogl_pipeline_new (test_ctx); + + cogl_pipeline_set_uniform_1f (pipeline, + cogl_pipeline_get_uniform_location (pipeline, + "a_value"), + 0.5); + + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_LAYER_FRAGMENT, + "uniform float a_value;", + "cogl_layer.g = a_value;"); + cogl_pipeline_add_layer_snippet (pipeline, 0, snippet); + cogl_object_unref (snippet); + + cogl_framebuffer_draw_textured_rectangle (test_fb, + pipeline, + 120, 0, 130, 10, + 0, 0, 0, 0); + cogl_object_unref (pipeline); + + test_utils_check_pixel (test_fb, 125, 5, 0xff80ffff); +} + +static void +test_modify_vertex_layer (TestState *state) +{ + CoglPipeline *pipeline; + CoglSnippet *snippet; + CoglMatrix matrix; + + /* Test modifying the vertex layer code */ + pipeline = create_texture_pipeline (state); + + cogl_matrix_init_identity (&matrix); + cogl_matrix_translate (&matrix, 0.0f, 1.0f, 0.0f); + cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix); + + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM, + NULL, + "cogl_tex_coord.x = 1.0;"); + cogl_pipeline_add_layer_snippet (pipeline, 0, snippet); + cogl_object_unref (snippet); + + cogl_framebuffer_draw_textured_rectangle (test_fb, + pipeline, + 130, 0, 140, 10, + 0, 0, 0, 0); + cogl_object_unref (pipeline); + + test_utils_check_pixel (test_fb, 135, 5, 0xffff00ff); +} + +static void +test_replace_vertex_layer (TestState *state) +{ + CoglPipeline *pipeline; + CoglSnippet *snippet; + CoglMatrix matrix; + + /* Test replacing the vertex layer code */ + pipeline = create_texture_pipeline (state); + + cogl_matrix_init_identity (&matrix); + cogl_matrix_translate (&matrix, 0.0f, 1.0f, 0.0f); + cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix); + + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM, + NULL, + NULL); + cogl_snippet_set_replace (snippet, "cogl_tex_coord.x = 1.0;\n"); + cogl_pipeline_add_layer_snippet (pipeline, 0, snippet); + cogl_object_unref (snippet); + + cogl_framebuffer_draw_textured_rectangle (test_fb, + pipeline, + 140, 0, 150, 10, + 0, 0, 0, 0); + cogl_object_unref (pipeline); + + test_utils_check_pixel (test_fb, 145, 5, 0x00ff00ff); +} + +static void +test_vertex_transform_hook (TestState *state) +{ + CoglPipeline *pipeline; + CoglSnippet *snippet; + CoglMatrix identity_matrix; + CoglMatrix matrix; + int location; + + /* Test the vertex transform hook */ + + cogl_matrix_init_identity (&identity_matrix); + + pipeline = cogl_pipeline_new (test_ctx); + + cogl_pipeline_set_color4ub (pipeline, 255, 0, 255, 255); + + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX_TRANSFORM, + "uniform mat4 pmat;", + NULL); + cogl_snippet_set_replace (snippet, "cogl_position_out = " + "pmat * cogl_position_in;"); + cogl_pipeline_add_snippet (pipeline, snippet); + cogl_object_unref (snippet); + + /* Copy the current projection matrix to a uniform */ + cogl_framebuffer_get_projection_matrix (test_fb, &matrix); + location = cogl_pipeline_get_uniform_location (pipeline, "pmat"); + cogl_pipeline_set_uniform_matrix (pipeline, + location, + 4, /* dimensions */ + 1, /* count */ + FALSE, /* don't transpose */ + cogl_matrix_get_array (&matrix)); + + /* Replace the real projection matrix with the identity. This should + mess up the drawing unless the snippet replacement is working */ + cogl_framebuffer_set_projection_matrix (test_fb, &identity_matrix); + + cogl_framebuffer_draw_rectangle (test_fb, pipeline, 150, 0, 160, 10); + cogl_object_unref (pipeline); + + /* Restore the projection matrix */ + cogl_framebuffer_set_projection_matrix (test_fb, &matrix); + + test_utils_check_pixel (test_fb, 155, 5, 0xff00ffff); +} + +static void +test_global_vertex_hook (TestState *state) +{ + CoglPipeline *pipeline; + CoglSnippet *snippet; + + pipeline = cogl_pipeline_new (test_ctx); + + /* Creates a function in the global declarations hook which is used + * by a subsequent snippet. The subsequent snippets replace any + * previous snippets but this shouldn't prevent the global + * declarations from being generated */ + + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX_GLOBALS, + /* declarations */ + "float\n" + "multiply_by_two (float number)\n" + "{\n" + " return number * 2.0;\n" + "}\n", + /* post */ + "This string shouldn't be used so " + "we can safely put garbage in here."); + cogl_snippet_set_pre (snippet, + "This string shouldn't be used so " + "we can safely put garbage in here."); + cogl_snippet_set_replace (snippet, + "This string shouldn't be used so " + "we can safely put garbage in here."); + cogl_pipeline_add_snippet (pipeline, snippet); + cogl_object_unref (snippet); + + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX, + NULL, /* declarations */ + NULL /* replace */); + cogl_snippet_set_replace (snippet, + "cogl_color_out.r = multiply_by_two (0.5);\n" + "cogl_color_out.gba = vec3 (0.0, 0.0, 1.0);\n" + "cogl_position_out = cogl_position_in;\n"); + cogl_pipeline_add_snippet (pipeline, snippet); + cogl_object_unref (snippet); + + cogl_framebuffer_draw_rectangle (test_fb, + pipeline, + -1, 1, + 10.0f * 2.0f / state->fb_width - 1.0f, + 10.0f * 2.0f / state->fb_height - 1.0f); + + cogl_object_unref (pipeline); + + test_utils_check_pixel (test_fb, 5, 5, 0xff0000ff); +} + +static void +test_global_fragment_hook (TestState *state) +{ + CoglPipeline *pipeline; + CoglSnippet *snippet; + + pipeline = cogl_pipeline_new (test_ctx); + + /* Creates a function in the global declarations hook which is used + * by a subsequent snippet. The subsequent snippets replace any + * previous snippets but this shouldn't prevent the global + * declarations from being generated */ + + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT_GLOBALS, + /* declarations */ + "float\n" + "multiply_by_four (float number)\n" + "{\n" + " return number * 4.0;\n" + "}\n", + /* post */ + "This string shouldn't be used so " + "we can safely put garbage in here."); + cogl_snippet_set_pre (snippet, + "This string shouldn't be used so " + "we can safely put garbage in here."); + cogl_snippet_set_replace (snippet, + "This string shouldn't be used so " + "we can safely put garbage in here."); + cogl_pipeline_add_snippet (pipeline, snippet); + cogl_object_unref (snippet); + + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, + NULL, /* declarations */ + NULL /* replace */); + cogl_snippet_set_replace (snippet, + "cogl_color_out.r = multiply_by_four (0.25);\n" + "cogl_color_out.gba = vec3 (0.0, 0.0, 1.0);\n"); + cogl_pipeline_add_snippet (pipeline, snippet); + cogl_object_unref (snippet); + + cogl_framebuffer_draw_rectangle (test_fb, + pipeline, + 0, 0, 10, 10); + + cogl_object_unref (pipeline); + + test_utils_check_pixel (test_fb, 5, 5, 0xff0000ff); +} + +static void +test_snippet_order (TestState *state) +{ + CoglPipeline *pipeline; + CoglSnippet *snippet; + + /* Verify that the snippets are executed in the right order. We'll + replace the r component of the color in the pre sections of the + snippets and the g component in the post. The pre sections should + be executed in the reverse order they were added and the post + sections in the same order as they were added. Therefore the r + component should be taken from the the second snippet and the g + component from the first */ + pipeline = cogl_pipeline_new (test_ctx); + + cogl_pipeline_set_color4ub (pipeline, 0, 0, 0, 255); + + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, + NULL, + "cogl_color_out.g = 0.5;\n"); + cogl_snippet_set_pre (snippet, "cogl_color_out.r = 0.5;\n"); + cogl_snippet_set_replace (snippet, "cogl_color_out.ba = vec2 (0.0, 1.0);"); + cogl_pipeline_add_snippet (pipeline, snippet); + cogl_object_unref (snippet); + + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, + NULL, + "cogl_color_out.g = 1.0;\n"); + cogl_snippet_set_pre (snippet, "cogl_color_out.r = 1.0;\n"); + cogl_pipeline_add_snippet (pipeline, snippet); + cogl_object_unref (snippet); + + cogl_framebuffer_draw_rectangle (test_fb, pipeline, 160, 0, 170, 10); + cogl_object_unref (pipeline); + + test_utils_check_pixel (test_fb, 165, 5, 0x80ff00ff); +} + +static void +test_naming_texture_units (TestState *state) +{ + CoglPipeline *pipeline; + CoglSnippet *snippet; + CoglTexture *tex1, *tex2; + + /* Test that we can sample from an arbitrary texture unit by naming + its layer number */ + + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, + NULL, + NULL); + cogl_snippet_set_replace (snippet, + "cogl_color_out = " + "texture2D (cogl_sampler100, vec2 (0.0, 0.0)) + " + "texture2D (cogl_sampler200, vec2 (0.0, 0.0));"); + + tex1 = test_utils_create_color_texture (test_ctx, 0xff0000ff); + tex2 = test_utils_create_color_texture (test_ctx, 0x00ff00ff); + + pipeline = cogl_pipeline_new (test_ctx); + + cogl_pipeline_set_layer_texture (pipeline, 100, tex1); + cogl_pipeline_set_layer_texture (pipeline, 200, tex2); + + cogl_pipeline_add_snippet (pipeline, snippet); + + cogl_framebuffer_draw_rectangle (test_fb, pipeline, 0, 0, 10, 10); + + cogl_object_unref (pipeline); + cogl_object_unref (snippet); + cogl_object_unref (tex1); + cogl_object_unref (tex2); + + test_utils_check_pixel (test_fb, 5, 5, 0xffff00ff); +} + +static void +test_snippet_properties (TestState *state) +{ + CoglSnippet *snippet; + + /* Sanity check modifying the snippet */ + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, "foo", "bar"); + g_assert_cmpstr (cogl_snippet_get_declarations (snippet), ==, "foo"); + g_assert_cmpstr (cogl_snippet_get_post (snippet), ==, "bar"); + g_assert_cmpstr (cogl_snippet_get_replace (snippet), ==, NULL); + g_assert_cmpstr (cogl_snippet_get_pre (snippet), ==, NULL); + + cogl_snippet_set_declarations (snippet, "fu"); + g_assert_cmpstr (cogl_snippet_get_declarations (snippet), ==, "fu"); + g_assert_cmpstr (cogl_snippet_get_post (snippet), ==, "bar"); + g_assert_cmpstr (cogl_snippet_get_replace (snippet), ==, NULL); + g_assert_cmpstr (cogl_snippet_get_pre (snippet), ==, NULL); + + cogl_snippet_set_post (snippet, "ba"); + g_assert_cmpstr (cogl_snippet_get_declarations (snippet), ==, "fu"); + g_assert_cmpstr (cogl_snippet_get_post (snippet), ==, "ba"); + g_assert_cmpstr (cogl_snippet_get_replace (snippet), ==, NULL); + g_assert_cmpstr (cogl_snippet_get_pre (snippet), ==, NULL); + + cogl_snippet_set_pre (snippet, "fuba"); + g_assert_cmpstr (cogl_snippet_get_declarations (snippet), ==, "fu"); + g_assert_cmpstr (cogl_snippet_get_post (snippet), ==, "ba"); + g_assert_cmpstr (cogl_snippet_get_replace (snippet), ==, NULL); + g_assert_cmpstr (cogl_snippet_get_pre (snippet), ==, "fuba"); + + cogl_snippet_set_replace (snippet, "baba"); + g_assert_cmpstr (cogl_snippet_get_declarations (snippet), ==, "fu"); + g_assert_cmpstr (cogl_snippet_get_post (snippet), ==, "ba"); + g_assert_cmpstr (cogl_snippet_get_replace (snippet), ==, "baba"); + g_assert_cmpstr (cogl_snippet_get_pre (snippet), ==, "fuba"); + + g_assert_cmpint (cogl_snippet_get_hook (snippet), + ==, + COGL_SNIPPET_HOOK_FRAGMENT); +} + +static SnippetTestFunc +tests[] = + { + simple_fragment_snippet, + simple_vertex_snippet, + shared_uniform, + lots_snippets, + shared_variable_pre_post, + test_pipeline_caching, + test_replace_string, + test_texture_lookup_hook, + test_multiple_samples, + test_replace_lookup_hook, + test_replace_snippet, + test_replace_fragment_layer, + test_modify_fragment_layer, + test_modify_vertex_layer, + test_replace_vertex_layer, + test_vertex_transform_hook, + test_global_fragment_hook, + test_global_vertex_hook, + test_snippet_order, + test_naming_texture_units, + test_snippet_properties + }; + +static void +run_tests (TestState *state) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS (tests); i++) + { + cogl_framebuffer_clear4f (test_fb, + COGL_BUFFER_BIT_COLOR, + 0, 0, 0, 1); + + tests[i] (state); + } +} + +void +test_snippets (void) +{ + TestState state; + + state.fb_width = cogl_framebuffer_get_width (test_fb); + state.fb_height = cogl_framebuffer_get_height (test_fb); + + cogl_framebuffer_orthographic (test_fb, + 0, 0, + state.fb_width, + state.fb_height, + -1, + 100); + + run_tests (&state); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} diff --git a/cogl/tests/conform/test-sparse-pipeline.c b/cogl/tests/conform/test-sparse-pipeline.c new file mode 100644 index 0000000..2b618dc --- /dev/null +++ b/cogl/tests/conform/test-sparse-pipeline.c @@ -0,0 +1,62 @@ +#include +#include + +#include "test-utils.h" + +typedef struct _TestState +{ + int fb_width; + int fb_height; +} TestState; + +static void +test_sparse_layer_combine (TestState *state) +{ + CoglPipeline *pipeline; + CoglTexture *tex1, *tex2; + + cogl_framebuffer_clear4f (test_fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1); + + /* This tests that the TEXTURE_* numbers used in the layer combine + string refer to the layer number rather than the unit numbers by + creating a pipeline with very large layer numbers. This should + end up being mapped to much smaller unit numbers */ + + tex1 = test_utils_create_color_texture (test_ctx, 0xff0000ff); + tex2 = test_utils_create_color_texture (test_ctx, 0x00ff00ff); + + pipeline = cogl_pipeline_new (test_ctx); + + cogl_pipeline_set_layer_texture (pipeline, 50, tex1); + cogl_pipeline_set_layer_texture (pipeline, 100, tex2); + cogl_pipeline_set_layer_combine (pipeline, 200, + "RGBA = ADD(TEXTURE_50, TEXTURE_100)", + NULL); + + cogl_framebuffer_draw_rectangle (test_fb, pipeline, -1, -1, 1, 1); + + test_utils_check_pixel (test_fb, 2, 2, 0xffff00ff); + + cogl_object_unref (pipeline); + cogl_object_unref (tex1); + cogl_object_unref (tex2); +} + +void +test_sparse_pipeline (void) +{ + TestState state; + + state.fb_width = cogl_framebuffer_get_width (test_fb); + state.fb_height = cogl_framebuffer_get_height (test_fb); + + test_sparse_layer_combine (&state); + + /* FIXME: This should have a lot more tests, for example testing + whether using an attribute with sparse texture coordinates will + work */ + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} + diff --git a/cogl/tests/conform/test-sub-texture.c b/cogl/tests/conform/test-sub-texture.c new file mode 100644 index 0000000..f049f3f --- /dev/null +++ b/cogl/tests/conform/test-sub-texture.c @@ -0,0 +1,325 @@ +#include +#include + +#include "test-utils.h" + +#define SOURCE_SIZE 32 +#define SOURCE_DIVISIONS_X 2 +#define SOURCE_DIVISIONS_Y 2 +#define DIVISION_WIDTH (SOURCE_SIZE / SOURCE_DIVISIONS_X) +#define DIVISION_HEIGHT (SOURCE_SIZE / SOURCE_DIVISIONS_Y) + +#define TEST_INSET 1 + +static const uint32_t +corner_colors[SOURCE_DIVISIONS_X * SOURCE_DIVISIONS_Y] = + { + 0xff0000ff, /* red top left */ + 0x00ff00ff, /* green top right */ + 0x0000ffff, /* blue bottom left */ + 0xff00ffff /* purple bottom right */ + }; + +typedef struct _TestState +{ + CoglTexture2D *tex; +} TestState; + +static CoglTexture2D * +create_source (TestState *state) +{ + int dx, dy; + uint8_t *data = g_malloc (SOURCE_SIZE * SOURCE_SIZE * 4); + CoglTexture2D *tex; + + /* Create a texture with a different coloured rectangle at each + corner */ + for (dy = 0; dy < SOURCE_DIVISIONS_Y; dy++) + for (dx = 0; dx < SOURCE_DIVISIONS_X; dx++) + { + uint8_t *p = (data + dy * DIVISION_HEIGHT * SOURCE_SIZE * 4 + + dx * DIVISION_WIDTH * 4); + int x, y; + + for (y = 0; y < DIVISION_HEIGHT; y++) + { + for (x = 0; x < DIVISION_WIDTH; x++) + { + uint32_t color = GUINT32_FROM_BE (corner_colors[dx + dy * SOURCE_DIVISIONS_X]); + memcpy (p, &color, 4); + p += 4; + } + + p += SOURCE_SIZE * 4 - DIVISION_WIDTH * 4; + } + } + + tex = cogl_texture_2d_new_from_data (test_ctx, + SOURCE_SIZE, SOURCE_SIZE, + COGL_PIXEL_FORMAT_RGBA_8888, + SOURCE_SIZE * 4, + data, + NULL); + return tex; +} + +static CoglTexture2D * +create_test_texture (TestState *state) +{ + CoglTexture2D *tex; + uint8_t *data = g_malloc (256 * 256 * 4), *p = data; + int x, y; + + /* Create a texture that is 256x256 where the red component ranges + from 0->255 along the x axis and the green component ranges from + 0->255 along the y axis. The blue and alpha components are all + 255 */ + for (y = 0; y < 256; y++) + for (x = 0; x < 256; x++) + { + *(p++) = x; + *(p++) = y; + *(p++) = 255; + *(p++) = 255; + } + + tex = cogl_texture_2d_new_from_data (test_ctx, + 256, 256, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + 256 * 4, + data, + NULL); + g_free (data); + + return tex; +} + +static void +paint (TestState *state) +{ + CoglTexture2D *full_texture; + CoglSubTexture *sub_texture, *sub_sub_texture; + CoglPipeline *pipeline = cogl_pipeline_new (test_ctx); + + /* Create a sub texture of the bottom right quarter of the texture */ + sub_texture = cogl_sub_texture_new (test_ctx, + state->tex, + DIVISION_WIDTH, + DIVISION_HEIGHT, + DIVISION_WIDTH, + DIVISION_HEIGHT); + + /* Paint it */ + cogl_pipeline_set_layer_texture (pipeline, 0, sub_texture); + cogl_object_unref (sub_texture); + cogl_framebuffer_draw_rectangle (test_fb, pipeline, + 0.0f, 0.0f, DIVISION_WIDTH, DIVISION_HEIGHT); + + + /* Repeat a sub texture of the top half of the full texture. This is + documented to be undefined so it doesn't technically have to work + but it will with the current implementation */ + sub_texture = cogl_sub_texture_new (test_ctx, + state->tex, + 0, 0, + SOURCE_SIZE, + DIVISION_HEIGHT); + cogl_pipeline_set_layer_texture (pipeline, 0, sub_texture); + cogl_object_unref (sub_texture); + cogl_framebuffer_draw_textured_rectangle (test_fb, pipeline, + 0.0f, + SOURCE_SIZE, + SOURCE_SIZE * 2.0f, + SOURCE_SIZE * 1.5f, + 0.0f, 0.0f, + 2.0f, 1.0f); + + /* Create a sub texture of a sub texture */ + full_texture = create_test_texture (state); + sub_texture = cogl_sub_texture_new (test_ctx, + full_texture, + 20, 10, 30, 20); + cogl_object_unref (full_texture); + sub_sub_texture = cogl_sub_texture_new (test_ctx, + sub_texture, + 20, 10, 10, 10); + cogl_object_unref (sub_texture); + cogl_pipeline_set_layer_texture (pipeline, 0, sub_sub_texture); + cogl_object_unref (sub_sub_texture); + cogl_framebuffer_draw_rectangle (test_fb, pipeline, + 0.0f, SOURCE_SIZE * 2.0f, + 10.0f, SOURCE_SIZE * 2.0f + 10.0f); + + cogl_object_unref (pipeline); +} + +static void +validate_part (int xpos, int ypos, + int width, int height, + uint32_t color) +{ + test_utils_check_region (test_fb, + xpos + TEST_INSET, + ypos + TEST_INSET, + width - TEST_INSET - 2, + height - TEST_INSET - 2, + color); +} + +static uint8_t * +create_update_data (void) +{ + uint8_t *data = g_malloc (256 * 256 * 4), *p = data; + int x, y; + + /* Create some image data that is 256x256 where the blue component + ranges from 0->255 along the x axis and the alpha component + ranges from 0->255 along the y axis. The red and green components + are all zero */ + for (y = 0; y < 256; y++) + for (x = 0; x < 256; x++) + { + *(p++) = 0; + *(p++) = 0; + *(p++) = x; + *(p++) = y; + } + + return data; +} + +static void +validate_result (TestState *state) +{ + int i, division_num, x, y; + CoglTexture2D *test_tex; + CoglSubTexture *sub_texture; + uint8_t *texture_data, *p; + int tex_width, tex_height; + + /* Sub texture of the bottom right corner of the texture */ + validate_part (0, 0, DIVISION_WIDTH, DIVISION_HEIGHT, + corner_colors[ + (SOURCE_DIVISIONS_Y - 1) * SOURCE_DIVISIONS_X + + SOURCE_DIVISIONS_X - 1]); + + /* Sub texture of the top half repeated horizontally */ + for (i = 0; i < 2; i++) + for (division_num = 0; division_num < SOURCE_DIVISIONS_X; division_num++) + validate_part (i * SOURCE_SIZE + division_num * DIVISION_WIDTH, + SOURCE_SIZE, + DIVISION_WIDTH, DIVISION_HEIGHT, + corner_colors[division_num]); + + /* Sub sub texture */ + p = texture_data = g_malloc (10 * 10 * 4); + cogl_flush (); + cogl_framebuffer_read_pixels (test_fb, + 0, SOURCE_SIZE * 2, 10, 10, + COGL_PIXEL_FORMAT_RGBA_8888, + p); + for (y = 0; y < 10; y++) + for (x = 0; x < 10; x++) + { + g_assert (*(p++) == x + 40); + g_assert (*(p++) == y + 20); + p += 2; + } + g_free (texture_data); + + /* Try reading back the texture data */ + sub_texture = cogl_sub_texture_new (test_ctx, + state->tex, + SOURCE_SIZE / 4, + SOURCE_SIZE / 4, + SOURCE_SIZE / 2, + SOURCE_SIZE / 2); + tex_width = cogl_texture_get_width (sub_texture); + tex_height = cogl_texture_get_height (sub_texture); + p = texture_data = g_malloc (tex_width * tex_height * 4); + cogl_texture_get_data (sub_texture, + COGL_PIXEL_FORMAT_RGBA_8888, + tex_width * 4, + texture_data); + for (y = 0; y < tex_height; y++) + for (x = 0; x < tex_width; x++) + { + int div_x = ((x * SOURCE_SIZE / 2 / tex_width + SOURCE_SIZE / 4) / + DIVISION_WIDTH); + int div_y = ((y * SOURCE_SIZE / 2 / tex_height + SOURCE_SIZE / 4) / + DIVISION_HEIGHT); + uint32_t reference = corner_colors[div_x + div_y * SOURCE_DIVISIONS_X] >> 8; + uint32_t color = GUINT32_FROM_BE (*((uint32_t *)p)) >> 8; + g_assert (color == reference); + p += 4; + } + g_free (texture_data); + cogl_object_unref (sub_texture); + + /* Create a 256x256 test texture */ + test_tex = create_test_texture (state); + /* Create a sub texture the views the center half of the texture */ + sub_texture = cogl_sub_texture_new (test_ctx, + test_tex, + 64, 64, 128, 128); + /* Update the center half of the sub texture */ + texture_data = create_update_data (); + cogl_texture_set_region (sub_texture, + 0, 0, 32, 32, 64, 64, 256, 256, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, 256 * 4, + texture_data); + g_free (texture_data); + cogl_object_unref (sub_texture); + /* Get the texture data */ + p = texture_data = g_malloc (256 * 256 * 4); + cogl_texture_get_data (test_tex, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + 256 * 4, texture_data); + + /* Verify the texture data */ + for (y = 0; y < 256; y++) + for (x = 0; x < 256; x++) + { + /* If we're in the center quarter */ + if (x >= 96 && x < 160 && y >= 96 && y < 160) + { + g_assert ((*p++) == 0); + g_assert ((*p++) == 0); + g_assert ((*p++) == x - 96); + g_assert ((*p++) == y - 96); + } + else + { + g_assert ((*p++) == x); + g_assert ((*p++) == y); + g_assert ((*p++) == 255); + g_assert ((*p++) == 255); + } + } + g_free (texture_data); + cogl_object_unref (test_tex); +} + +void +test_sub_texture (void) +{ + TestState state; + + state.tex = create_source (&state); + + cogl_framebuffer_orthographic (test_fb, + 0, 0, + cogl_framebuffer_get_width (test_fb), + cogl_framebuffer_get_height (test_fb), + -1, + 100); + + paint (&state); + validate_result (&state); + + cogl_object_unref (state.tex); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} + diff --git a/cogl/tests/conform/test-texture-3d.c b/cogl/tests/conform/test-texture-3d.c new file mode 100644 index 0000000..80d077a --- /dev/null +++ b/cogl/tests/conform/test-texture-3d.c @@ -0,0 +1,274 @@ +#include +#include + +#include "test-utils.h" + +#define TEX_WIDTH 4 +#define TEX_HEIGHT 8 +#define TEX_DEPTH 16 +/* Leave four bytes of padding between each row */ +#define TEX_ROWSTRIDE (TEX_WIDTH * 4 + 4) +/* Leave four rows of padding between each image */ +#define TEX_IMAGE_STRIDE ((TEX_HEIGHT + 4) * TEX_ROWSTRIDE) + +typedef struct _TestState +{ + int fb_width; + int fb_height; +} TestState; + +static CoglTexture3D * +create_texture_3d (CoglContext *context) +{ + int x, y, z; + uint8_t *data = g_malloc (TEX_IMAGE_STRIDE * TEX_DEPTH); + uint8_t *p = data; + CoglTexture3D *tex; + CoglError *error = NULL; + + for (z = 0; z < TEX_DEPTH; z++) + { + for (y = 0; y < TEX_HEIGHT; y++) + { + for (x = 0; x < TEX_WIDTH; x++) + { + /* Set red, green, blue to values based on x, y, z */ + *(p++) = 255 - x * 8; + *(p++) = y * 8; + *(p++) = 255 - z * 8; + /* Fully opaque */ + *(p++) = 0xff; + } + + /* Set the padding between rows to 0xde */ + memset (p, 0xde, TEX_ROWSTRIDE - (TEX_WIDTH * 4)); + p += TEX_ROWSTRIDE - (TEX_WIDTH * 4); + } + /* Set the padding between images to 0xad */ + memset (p, 0xba, TEX_IMAGE_STRIDE - (TEX_HEIGHT * TEX_ROWSTRIDE)); + p += TEX_IMAGE_STRIDE - (TEX_HEIGHT * TEX_ROWSTRIDE); + } + + tex = cogl_texture_3d_new_from_data (context, + TEX_WIDTH, TEX_HEIGHT, TEX_DEPTH, + COGL_PIXEL_FORMAT_RGBA_8888, + TEX_ROWSTRIDE, + TEX_IMAGE_STRIDE, + data, + &error); + + if (tex == NULL) + { + g_assert (error != NULL); + g_warning ("Failed to create 3D texture: %s", error->message); + g_assert_not_reached (); + } + + g_free (data); + + return tex; +} + +static void +draw_frame (TestState *state) +{ + CoglTexture *tex = create_texture_3d (test_ctx); + CoglPipeline *pipeline = cogl_pipeline_new (test_ctx); + typedef struct { float x, y, s, t, r; } Vert; + CoglPrimitive *primitive; + CoglAttributeBuffer *attribute_buffer; + CoglAttribute *attributes[2]; + Vert *verts, *v; + int i; + + cogl_pipeline_set_layer_texture (pipeline, 0, tex); + cogl_object_unref (tex); + cogl_pipeline_set_layer_filters (pipeline, 0, + COGL_PIPELINE_FILTER_NEAREST, + COGL_PIPELINE_FILTER_NEAREST); + + /* Render the texture repeated horizontally twice using a regular + cogl rectangle. This should end up with the r texture coordinates + as zero */ + cogl_framebuffer_draw_textured_rectangle (test_fb, pipeline, + 0.0f, 0.0f, TEX_WIDTH * 2, TEX_HEIGHT, + 0.0f, 0.0f, 2.0f, 1.0f); + + /* Render all of the images in the texture using coordinates from a + CoglPrimitive */ + v = verts = g_new (Vert, 4 * TEX_DEPTH); + for (i = 0; i < TEX_DEPTH; i++) + { + float r = (i + 0.5f) / TEX_DEPTH; + + v->x = i * TEX_WIDTH; + v->y = TEX_HEIGHT; + v->s = 0; + v->t = 0; + v->r = r; + v++; + + v->x = i * TEX_WIDTH; + v->y = TEX_HEIGHT * 2; + v->s = 0; + v->t = 1; + v->r = r; + v++; + + v->x = i * TEX_WIDTH + TEX_WIDTH; + v->y = TEX_HEIGHT * 2; + v->s = 1; + v->t = 1; + v->r = r; + v++; + + v->x = i * TEX_WIDTH + TEX_WIDTH; + v->y = TEX_HEIGHT; + v->s = 1; + v->t = 0; + v->r = r; + v++; + } + + attribute_buffer = cogl_attribute_buffer_new (test_ctx, + 4 * TEX_DEPTH * sizeof (Vert), + verts); + attributes[0] = cogl_attribute_new (attribute_buffer, + "cogl_position_in", + sizeof (Vert), + G_STRUCT_OFFSET (Vert, x), + 2, /* n_components */ + COGL_ATTRIBUTE_TYPE_FLOAT); + attributes[1] = cogl_attribute_new (attribute_buffer, + "cogl_tex_coord_in", + sizeof (Vert), + G_STRUCT_OFFSET (Vert, s), + 3, /* n_components */ + COGL_ATTRIBUTE_TYPE_FLOAT); + primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, + 6 * TEX_DEPTH, + attributes, + 2 /* n_attributes */); + + cogl_primitive_set_indices (primitive, + cogl_get_rectangle_indices (test_ctx, + TEX_DEPTH), + 6 * TEX_DEPTH); + + cogl_primitive_draw (primitive, test_fb, pipeline); + + g_free (verts); + + cogl_object_unref (primitive); + cogl_object_unref (attributes[0]); + cogl_object_unref (attributes[1]); + cogl_object_unref (attribute_buffer); + cogl_object_unref (pipeline); +} + +static void +validate_block (int block_x, int block_y, int z) +{ + int x, y; + + for (y = 0; y < TEX_HEIGHT; y++) + for (x = 0; x < TEX_WIDTH; x++) + test_utils_check_pixel_rgb (test_fb, + block_x * TEX_WIDTH + x, + block_y * TEX_HEIGHT + y, + 255 - x * 8, + y * 8, + 255 - z * 8); +} + +static void +validate_result (void) +{ + int i; + + validate_block (0, 0, 0); + + for (i = 0; i < TEX_DEPTH; i++) + validate_block (i, 1, i); +} + +static void +test_multi_texture (TestState *state) +{ + CoglPipeline *pipeline; + CoglTexture3D *tex_3d; + CoglTexture2D *tex_2d; + uint8_t tex_data[4]; + + cogl_framebuffer_clear4f (test_fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1); + + /* Tests a pipeline that is using multi-texturing to combine a 3D + texture with a 2D texture. The texture from another layer is + sampled with TEXTURE_? just to pick up a specific bug that was + happening with the ARBfp fragend */ + + pipeline = cogl_pipeline_new (test_ctx); + + tex_data[0] = 0xff; + tex_data[1] = 0x00; + tex_data[2] = 0x00; + tex_data[3] = 0xff; + tex_2d = cogl_texture_2d_new_from_data (test_ctx, + 1, 1, /* width/height */ + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + 4, /* rowstride */ + tex_data, + NULL); + cogl_pipeline_set_layer_texture (pipeline, 0, tex_2d); + + tex_data[0] = 0x00; + tex_data[1] = 0xff; + tex_data[2] = 0x00; + tex_data[3] = 0xff; + tex_3d = cogl_texture_3d_new_from_data (test_ctx, + 1, 1, 1, /* width/height/depth */ + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + 4, /* rowstride */ + 4, /* image_stride */ + tex_data, + NULL); + cogl_pipeline_set_layer_texture (pipeline, 1, tex_3d); + + cogl_pipeline_set_layer_combine (pipeline, 0, + "RGBA = REPLACE(PREVIOUS)", + NULL); + cogl_pipeline_set_layer_combine (pipeline, 1, + "RGBA = ADD(TEXTURE_0, TEXTURE_1)", + NULL); + + cogl_framebuffer_draw_rectangle (test_fb, pipeline, 0, 0, 10, 10); + + test_utils_check_pixel (test_fb, 5, 5, 0xffff00ff); + + cogl_object_unref (tex_2d); + cogl_object_unref (tex_3d); + cogl_object_unref (pipeline); +} + +void +test_texture_3d (void) +{ + TestState state; + + state.fb_width = cogl_framebuffer_get_width (test_fb); + state.fb_height = cogl_framebuffer_get_height (test_fb); + + cogl_framebuffer_orthographic (test_fb, + 0, 0, /* x_1, y_1 */ + state.fb_width, /* x_2 */ + state.fb_height /* y_2 */, + -1, 100 /* near/far */); + + draw_frame (&state); + validate_result (); + + test_multi_texture (&state); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} diff --git a/cogl/tests/conform/test-texture-get-set-data.c b/cogl/tests/conform/test-texture-get-set-data.c new file mode 100644 index 0000000..59bd0f6 --- /dev/null +++ b/cogl/tests/conform/test-texture-get-set-data.c @@ -0,0 +1,144 @@ +#include + +#include + +#include "test-utils.h" + +static void +check_texture (int width, int height, TestUtilsTextureFlags flags) +{ + CoglTexture *tex; + uint8_t *data, *p; + int y, x; + int rowstride; + CoglBitmap *bmp; + + p = data = g_malloc (width * height * 4); + for (y = 0; y < height; y++) + for (x = 0; x < width; x++) + { + *(p++) = x; + *(p++) = y; + *(p++) = 128; + *(p++) = (x ^ y); + } + + bmp = cogl_bitmap_new_for_data (test_ctx, + width, height, + COGL_PIXEL_FORMAT_RGBA_8888, + width * 4, + data); + + tex = test_utils_texture_new_from_bitmap (bmp, flags, + FALSE); + + /* Replace the bottom right quarter of the data with negated data to + test set_region */ + rowstride = width * 4; + p = data + (height / 2) * rowstride + rowstride / 2; + for (y = 0; y < height / 2; y++) + { + for (x = 0; x < width / 2; x++) + { + p[0] = ~p[0]; + p[1] = ~p[1]; + p[2] = ~p[2]; + p[3] = ~p[3]; + p += 4; + } + p += width * 2; + } + cogl_texture_set_region (tex, + width / 2, + height / 2, + width / 2, /* dest x */ + height / 2, /* dest y */ + width / 2, /* region width */ + height / 2, /* region height */ + width, /* src width */ + height, /* src height */ + COGL_PIXEL_FORMAT_RGBA_8888, + rowstride, + data); + + /* Check passing a NULL pointer and a zero rowstride. The texture + should calculate the needed data size and return it */ + g_assert_cmpint (cogl_texture_get_data (tex, COGL_PIXEL_FORMAT_ANY, 0, NULL), + ==, + width * height * 4); + + /* Try first receiving the data as RGB. This should cause a + * conversion */ + memset (data, 0, width * height * 4); + + cogl_texture_get_data (tex, COGL_PIXEL_FORMAT_RGB_888, + width * 3, data); + + p = data; + + for (y = 0; y < height; y++) + for (x = 0; x < width; x++) + { + if (x >= width / 2 && y >= height / 2) + { + g_assert_cmpint (p[0], ==, ~x & 0xff); + g_assert_cmpint (p[1], ==, ~y & 0xff); + g_assert_cmpint (p[2], ==, ~128 & 0xff); + } + else + { + g_assert_cmpint (p[0], ==, x & 0xff); + g_assert_cmpint (p[1], ==, y & 0xff); + g_assert_cmpint (p[2], ==, 128); + } + p += 3; + } + + /* Now try receiving the data as RGBA. This should not cause a + * conversion and no unpremultiplication because we explicitly set + * the internal format when we created the texture */ + memset (data, 0, width * height * 4); + + cogl_texture_get_data (tex, COGL_PIXEL_FORMAT_RGBA_8888, + width * 4, data); + + p = data; + + for (y = 0; y < height; y++) + for (x = 0; x < width; x++) + { + if (x >= width / 2 && y >= height / 2) + { + g_assert_cmpint (p[0], ==, ~x & 0xff); + g_assert_cmpint (p[1], ==, ~y & 0xff); + g_assert_cmpint (p[2], ==, ~128 & 0xff); + g_assert_cmpint (p[3], ==, ~(x ^ y) & 0xff); + } + else + { + g_assert_cmpint (p[0], ==, x & 0xff); + g_assert_cmpint (p[1], ==, y & 0xff); + g_assert_cmpint (p[2], ==, 128); + g_assert_cmpint (p[3], ==, (x ^ y) & 0xff); + } + p += 4; + } + + cogl_object_unref (tex); + g_free (data); +} + +void +test_texture_get_set_data (void) +{ + /* First try without atlasing */ + check_texture (256, 256, TEST_UTILS_TEXTURE_NO_ATLAS); + /* Try again with atlasing. This should end up testing the atlas + backend and the sub texture backend */ + check_texture (256, 256, 0); + /* Try with a really big texture in the hope that it will end up + sliced. */ + check_texture (4, 5128, TEST_UTILS_TEXTURE_NO_ATLAS); + /* And in the other direction. */ + check_texture (5128, 4, TEST_UTILS_TEXTURE_NO_ATLAS); +} diff --git a/cogl/tests/conform/test-texture-no-allocate.c b/cogl/tests/conform/test-texture-no-allocate.c new file mode 100644 index 0000000..b0199a9 --- /dev/null +++ b/cogl/tests/conform/test-texture-no-allocate.c @@ -0,0 +1,80 @@ +#include + +#include "test-utils.h" + +/* Tests that the various texture types can be freed without being + * allocated */ + +/* Texture size that is probably to big to fit within the texture + * limits */ +#define BIG_TEX_WIDTH 16384 +#define BIG_TEX_HEIGHT 128 + +void +test_texture_no_allocate (void) +{ + uint8_t *tex_data; + CoglTexture *texture; + CoglTexture2D *texture_2d; + GError *error = NULL; + + tex_data = g_malloc (BIG_TEX_WIDTH * BIG_TEX_HEIGHT * 4); + + /* NB: if we make the atlas and sliced texture APIs public then this + * could changed to explicitly use that instead of the magic texture + * API */ + + /* Try to create an atlas texture that is too big so it will + * internally be freed without allocating */ + texture = + cogl_atlas_texture_new_from_data (test_ctx, + BIG_TEX_WIDTH, + BIG_TEX_HEIGHT, + /* format */ + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + /* rowstride */ + BIG_TEX_WIDTH * 4, + tex_data, + &error); + + g_free (tex_data); + + /* It's ok if this causes an error, we just don't want it to + * crash */ + + if (texture == NULL) + cogl_error_free (error); + else + cogl_object_unref (texture); + + /* Try to create a sliced texture without allocating it */ + texture = + cogl_texture_2d_sliced_new_with_size (test_ctx, + BIG_TEX_WIDTH, + BIG_TEX_HEIGHT, + COGL_TEXTURE_MAX_WASTE); + cogl_object_unref (texture); + + /* 2D texture */ + texture_2d = cogl_texture_2d_new_with_size (test_ctx, + 64, 64); + cogl_object_unref (texture_2d); + + /* 3D texture */ + if (cogl_has_feature (test_ctx, COGL_FEATURE_ID_TEXTURE_3D)) + { + CoglTexture3D *texture_3d = + cogl_texture_3d_new_with_size (test_ctx, + 64, 64, 64); + cogl_object_unref (texture_3d); + } + + /* Rectangle texture */ + if (cogl_has_feature (test_ctx, COGL_FEATURE_ID_TEXTURE_RECTANGLE)) + { + CoglTextureRectangle *texture_rect = + cogl_texture_rectangle_new_with_size (test_ctx, + 64, 64); + cogl_object_unref (texture_rect); + } +} diff --git a/cogl/tests/conform/test-texture-rg.c b/cogl/tests/conform/test-texture-rg.c new file mode 100644 index 0000000..72a5ae9 --- /dev/null +++ b/cogl/tests/conform/test-texture-rg.c @@ -0,0 +1,74 @@ +#include + +#include + +#include "test-utils.h" + +#define TEX_WIDTH 8 +#define TEX_HEIGHT 8 + +static CoglTexture2D * +make_texture (void) +{ + uint8_t tex_data[TEX_WIDTH * TEX_HEIGHT * 2], *p = tex_data; + int x, y; + + for (y = 0; y < TEX_HEIGHT; y++) + for (x = 0; x < TEX_WIDTH; x++) + { + *(p++) = x * 256 / TEX_WIDTH; + *(p++) = y * 256 / TEX_HEIGHT; + } + + return cogl_texture_2d_new_from_data (test_ctx, + TEX_WIDTH, TEX_HEIGHT, + COGL_PIXEL_FORMAT_RG_88, + TEX_WIDTH * 2, + tex_data, + NULL); +} + +void +test_texture_rg (void) +{ + CoglPipeline *pipeline; + CoglTexture2D *tex; + int fb_width, fb_height; + int x, y; + + fb_width = cogl_framebuffer_get_width (test_fb); + fb_height = cogl_framebuffer_get_height (test_fb); + + tex = make_texture (); + + g_assert (cogl_texture_get_components (tex) == COGL_TEXTURE_COMPONENTS_RG); + + pipeline = cogl_pipeline_new (test_ctx); + + cogl_pipeline_set_layer_texture (pipeline, 0, tex); + cogl_pipeline_set_layer_filters (pipeline, + 0, + COGL_PIPELINE_FILTER_NEAREST, + COGL_PIPELINE_FILTER_NEAREST); + + cogl_framebuffer_draw_rectangle (test_fb, + pipeline, + -1.0f, 1.0f, + 1.0f, -1.0f); + + for (y = 0; y < TEX_HEIGHT; y++) + for (x = 0; x < TEX_WIDTH; x++) + { + test_utils_check_pixel_rgb (test_fb, + x * fb_width / TEX_WIDTH + + fb_width / (TEX_WIDTH * 2), + y * fb_height / TEX_HEIGHT + + fb_height / (TEX_HEIGHT * 2), + x * 256 / TEX_WIDTH, + y * 256 / TEX_HEIGHT, + 0); + } + + cogl_object_unref (pipeline); + cogl_object_unref (tex); +} diff --git a/cogl/tests/conform/test-version.c b/cogl/tests/conform/test-version.c new file mode 100644 index 0000000..c316de2 --- /dev/null +++ b/cogl/tests/conform/test-version.c @@ -0,0 +1,81 @@ +#include + +#include "test-utils.h" +#include "cogl-config.h" + +/* So we can use _COGL_STATIC_ASSERT we include the internal + * cogl-util.h header. Since internal headers explicitly guard against + * applications including them directly instead of including + * we define __COGL_H_INSIDE__ here to subvert those + * guards in this case... */ +#define __COGL_H_INSIDE__ +#include +#undef __COGL_H_INSIDE__ + +_COGL_STATIC_ASSERT (COGL_VERSION_ENCODE (COGL_VERSION_MAJOR, + COGL_VERSION_MINOR, + COGL_VERSION_MICRO) == + COGL_VERSION, + "The pre-encoded Cogl version does not match the version " + "encoding macro"); + +_COGL_STATIC_ASSERT (COGL_VERSION_GET_MAJOR (COGL_VERSION_ENCODE (100, + 200, + 300)) == + 100, + "Getting the major component out of a encoded version " + "does not work"); +_COGL_STATIC_ASSERT (COGL_VERSION_GET_MINOR (COGL_VERSION_ENCODE (100, + 200, + 300)) == + 200, + "Getting the minor component out of a encoded version " + "does not work"); +_COGL_STATIC_ASSERT (COGL_VERSION_GET_MICRO (COGL_VERSION_ENCODE (100, + 200, + 300)) == + 300, + "Getting the micro component out of a encoded version " + "does not work"); + +_COGL_STATIC_ASSERT (COGL_VERSION_CHECK (COGL_VERSION_MAJOR, + COGL_VERSION_MINOR, + COGL_VERSION_MICRO), + "Checking the Cogl version against the current version " + "does not pass"); +_COGL_STATIC_ASSERT (!COGL_VERSION_CHECK (COGL_VERSION_MAJOR, + COGL_VERSION_MINOR, + COGL_VERSION_MICRO + 1), + "Checking the Cogl version against a later micro version " + "should not pass"); +_COGL_STATIC_ASSERT (!COGL_VERSION_CHECK (COGL_VERSION_MAJOR, + COGL_VERSION_MINOR + 1, + COGL_VERSION_MICRO), + "Checking the Cogl version against a later minor version " + "should not pass"); +_COGL_STATIC_ASSERT (!COGL_VERSION_CHECK (COGL_VERSION_MAJOR + 1, + COGL_VERSION_MINOR, + COGL_VERSION_MICRO), + "Checking the Cogl version against a later major version " + "should not pass"); + +_COGL_STATIC_ASSERT (COGL_VERSION_CHECK (COGL_VERSION_MAJOR - 1, + COGL_VERSION_MINOR, + COGL_VERSION_MICRO), + "Checking the Cogl version against a older major version " + "should pass"); + +void +test_version (void) +{ + const char *version = g_strdup_printf ("version = %i.%i.%i", + COGL_VERSION_MAJOR, + COGL_VERSION_MINOR, + COGL_VERSION_MICRO); + + g_assert_cmpstr (version, ==, "version = " COGL_VERSION_STRING); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} + diff --git a/cogl/tests/conform/test-wrap-modes.c b/cogl/tests/conform/test-wrap-modes.c new file mode 100644 index 0000000..e5a2a1a --- /dev/null +++ b/cogl/tests/conform/test-wrap-modes.c @@ -0,0 +1,296 @@ +#define COGL_VERSION_MIN_REQUIRED COGL_VERSION_1_0 + +#include +#include + +#include "test-utils.h" + +#define TEX_SIZE 4 + +typedef struct _TestState +{ + int width; + int height; + CoglTexture *texture; +} TestState; + +static CoglTexture * +create_texture (TestUtilsTextureFlags flags) +{ + uint8_t *data = g_malloc (TEX_SIZE * TEX_SIZE * 4), *p = data; + CoglTexture *tex; + int x, y; + + for (y = 0; y < TEX_SIZE; y++) + for (x = 0; x < TEX_SIZE; x++) + { + *(p++) = 0; + *(p++) = (x & 1) * 255; + *(p++) = (y & 1) * 255; + *(p++) = 255; + } + + tex = test_utils_texture_new_from_data (test_ctx, + TEX_SIZE, TEX_SIZE, flags, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + TEX_SIZE * 4, + data); + g_free (data); + + return tex; +} + +static CoglPipeline * +create_pipeline (TestState *state, + CoglPipelineWrapMode wrap_mode_s, + CoglPipelineWrapMode wrap_mode_t) +{ + CoglPipeline *pipeline; + + pipeline = cogl_pipeline_new (test_ctx); + cogl_pipeline_set_layer_texture (pipeline, 0, state->texture); + cogl_pipeline_set_layer_filters (pipeline, 0, + COGL_PIPELINE_FILTER_NEAREST, + COGL_PIPELINE_FILTER_NEAREST); + cogl_pipeline_set_layer_wrap_mode_s (pipeline, 0, wrap_mode_s); + cogl_pipeline_set_layer_wrap_mode_t (pipeline, 0, wrap_mode_t); + + return pipeline; +} + +static CoglPipelineWrapMode +wrap_modes[] = + { + COGL_PIPELINE_WRAP_MODE_REPEAT, + COGL_PIPELINE_WRAP_MODE_REPEAT, + + COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE, + COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE, + + COGL_PIPELINE_WRAP_MODE_REPEAT, + COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE, + + COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE, + COGL_PIPELINE_WRAP_MODE_REPEAT, + + COGL_PIPELINE_WRAP_MODE_AUTOMATIC, + COGL_PIPELINE_WRAP_MODE_AUTOMATIC, + + COGL_PIPELINE_WRAP_MODE_AUTOMATIC, + COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE + }; + +static void +draw_tests (TestState *state) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS (wrap_modes); i += 2) + { + CoglPipelineWrapMode wrap_mode_s, wrap_mode_t; + CoglPipeline *pipeline; + + /* Create a separate pipeline for each pair of wrap modes so + that we can verify whether the batch splitting works */ + wrap_mode_s = wrap_modes[i]; + wrap_mode_t = wrap_modes[i + 1]; + pipeline = create_pipeline (state, wrap_mode_s, wrap_mode_t); + /* Render the pipeline at four times the size of the texture */ + cogl_framebuffer_draw_textured_rectangle (test_fb, + pipeline, + i * TEX_SIZE, + 0, + (i + 2) * TEX_SIZE, + TEX_SIZE * 2, + 0, 0, 2, 2); + cogl_object_unref (pipeline); + } +} + +static const CoglTextureVertex vertices[4] = + { + { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, TEX_SIZE * 2, 0.0f, 0.0f, 2.0f }, + { TEX_SIZE * 2, TEX_SIZE * 2, 0.0f, 2.0f, 2.0f }, + { TEX_SIZE * 2, 0.0f, 0.0f, 2.0f, 0.0f } + }; + +static void +draw_tests_polygon (TestState *state) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS (wrap_modes); i += 2) + { + CoglPipelineWrapMode wrap_mode_s, wrap_mode_t; + CoglPipeline *pipeline; + + wrap_mode_s = wrap_modes[i]; + wrap_mode_t = wrap_modes[i + 1]; + pipeline = create_pipeline (state, wrap_mode_s, wrap_mode_t); + cogl_set_source (pipeline); + cogl_object_unref (pipeline); + cogl_push_matrix (); + cogl_translate (TEX_SIZE * i, 0.0f, 0.0f); + /* Render the pipeline at four times the size of the texture */ + cogl_polygon (vertices, G_N_ELEMENTS (vertices), FALSE); + cogl_pop_matrix (); + } +} + +static void +draw_tests_vbo (TestState *state) +{ + CoglHandle vbo; + int i; + + vbo = cogl_vertex_buffer_new (4); + cogl_vertex_buffer_add (vbo, "gl_Vertex", 3, + COGL_ATTRIBUTE_TYPE_FLOAT, FALSE, + sizeof (vertices[0]), + &vertices[0].x); + cogl_vertex_buffer_add (vbo, "gl_MultiTexCoord0", 2, + COGL_ATTRIBUTE_TYPE_FLOAT, FALSE, + sizeof (vertices[0]), + &vertices[0].tx); + cogl_vertex_buffer_submit (vbo); + + for (i = 0; i < G_N_ELEMENTS (wrap_modes); i += 2) + { + CoglPipelineWrapMode wrap_mode_s, wrap_mode_t; + CoglPipeline *pipeline; + + wrap_mode_s = wrap_modes[i]; + wrap_mode_t = wrap_modes[i + 1]; + pipeline = create_pipeline (state, wrap_mode_s, wrap_mode_t); + cogl_set_source (pipeline); + cogl_object_unref (pipeline); + cogl_push_matrix (); + cogl_translate (TEX_SIZE * i, 0.0f, 0.0f); + /* Render the pipeline at four times the size of the texture */ + cogl_vertex_buffer_draw (vbo, COGL_VERTICES_MODE_TRIANGLE_FAN, 0, 4); + cogl_pop_matrix (); + } + + cogl_handle_unref (vbo); +} + +static void +validate_set (TestState *state, int offset) +{ + uint8_t data[TEX_SIZE * 2 * TEX_SIZE * 2 * 4], *p; + int x, y, i; + + for (i = 0; i < G_N_ELEMENTS (wrap_modes); i += 2) + { + CoglPipelineWrapMode wrap_mode_s, wrap_mode_t; + + wrap_mode_s = wrap_modes[i]; + wrap_mode_t = wrap_modes[i + 1]; + + cogl_framebuffer_read_pixels (test_fb, i * TEX_SIZE, offset * TEX_SIZE * 2, + TEX_SIZE * 2, TEX_SIZE * 2, + COGL_PIXEL_FORMAT_RGBA_8888, + data); + + p = data; + + for (y = 0; y < TEX_SIZE * 2; y++) + for (x = 0; x < TEX_SIZE * 2; x++) + { + uint8_t green, blue; + + if (x < TEX_SIZE || + wrap_mode_s == COGL_PIPELINE_WRAP_MODE_REPEAT || + wrap_mode_s == COGL_PIPELINE_WRAP_MODE_AUTOMATIC) + green = (x & 1) * 255; + else + green = ((TEX_SIZE - 1) & 1) * 255; + + if (y < TEX_SIZE || + wrap_mode_t == COGL_PIPELINE_WRAP_MODE_REPEAT || + wrap_mode_t == COGL_PIPELINE_WRAP_MODE_AUTOMATIC) + blue = (y & 1) * 255; + else + blue = ((TEX_SIZE - 1) & 1) * 255; + + g_assert_cmpint (p[0], ==, 0); + g_assert_cmpint (p[1], ==, green); + g_assert_cmpint (p[2], ==, blue); + + p += 4; + } + } +} + +static void +validate_result (TestState *state) +{ + validate_set (state, 0); /* non-atlased rectangle */ +#if 0 /* this doesn't currently work */ + validate_set (state, 1); /* atlased rectangle */ +#endif + validate_set (state, 2); /* cogl_polygon */ + validate_set (state, 3); /* vertex buffer */ +} + +static void +paint (TestState *state) +{ + /* Draw the tests first with a non atlased texture */ + state->texture = create_texture (TEST_UTILS_TEXTURE_NO_ATLAS); + draw_tests (state); + cogl_object_unref (state->texture); + + /* Draw the tests again with a possible atlased texture. This should + end up testing software repeats */ + state->texture = create_texture (TEST_UTILS_TEXTURE_NONE); + cogl_framebuffer_push_matrix (test_fb); + cogl_framebuffer_translate (test_fb, 0.0f, TEX_SIZE * 2.0f, 0.0f); + draw_tests (state); + cogl_pop_matrix (); + cogl_object_unref (state->texture); + + /* Draw the tests using cogl_polygon */ + state->texture = create_texture (COGL_TEXTURE_NO_ATLAS); + cogl_push_matrix (); + cogl_translate (0.0f, TEX_SIZE * 4.0f, 0.0f); + draw_tests_polygon (state); + cogl_pop_matrix (); + cogl_object_unref (state->texture); + + /* Draw the tests using a vertex buffer */ + state->texture = create_texture (COGL_TEXTURE_NO_ATLAS); + cogl_push_matrix (); + cogl_translate (0.0f, TEX_SIZE * 6.0f, 0.0f); + draw_tests_vbo (state); + cogl_pop_matrix (); + cogl_object_unref (state->texture); + + validate_result (state); +} + +void +test_wrap_modes (void) +{ + TestState state; + + state.width = cogl_framebuffer_get_width (test_fb); + state.height = cogl_framebuffer_get_height (test_fb); + + cogl_framebuffer_orthographic (test_fb, + 0, 0, + state.width, + state.height, + -1, + 100); + + /* XXX: we have to push/pop a framebuffer since this test currently + * uses the legacy cogl_vertex_buffer_draw() api. */ + cogl_push_framebuffer (test_fb); + paint (&state); + cogl_pop_framebuffer (); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} diff --git a/cogl/tests/conform/test-wrap-rectangle-textures.c b/cogl/tests/conform/test-wrap-rectangle-textures.c new file mode 100644 index 0000000..73b3575 --- /dev/null +++ b/cogl/tests/conform/test-wrap-rectangle-textures.c @@ -0,0 +1,175 @@ +#include + +#include + +#include "test-utils.h" + +#define DRAW_SIZE 64 + +static CoglPipeline * +create_base_pipeline (void) +{ + CoglBitmap *bmp; + CoglTextureRectangle *tex; + CoglPipeline *pipeline; + uint8_t tex_data[] = + { + 0x44, 0x44, 0x44, 0x88, 0x88, 0x88, + 0xcc, 0xcc, 0xcc, 0xff, 0xff, 0xff + }; + + bmp = cogl_bitmap_new_for_data (test_ctx, + 2, 2, /* width/height */ + COGL_PIXEL_FORMAT_RGB_888, + 2 * 3, /* rowstride */ + tex_data); + + tex = cogl_texture_rectangle_new_from_bitmap (bmp); + + cogl_object_unref (bmp); + + pipeline = cogl_pipeline_new (test_ctx); + + cogl_pipeline_set_layer_filters (pipeline, + 0, /* layer */ + COGL_PIPELINE_FILTER_NEAREST, + COGL_PIPELINE_FILTER_NEAREST); + + cogl_pipeline_set_layer_texture (pipeline, + 0, /* layer */ + tex); + + cogl_object_unref (tex); + + return pipeline; +} + +static void +check_colors (int x_offset, + int y_offset, + const uint8_t expected_colors[9]) +{ + int x, y; + + for (y = 0; y < 4; y++) + for (x = 0; x < 4; x++) + { + uint32_t color = expected_colors[x + y * 4]; + test_utils_check_region (test_fb, + x * DRAW_SIZE / 4 + 1 + x_offset, + y * DRAW_SIZE / 4 + 1 + y_offset, + DRAW_SIZE / 4 - 2, + DRAW_SIZE / 4 - 2, + 0xff | + (color << 8) | + (color << 16) | + (color << 24)); + } +} + +static void +test_pipeline (CoglPipeline *pipeline, + int x_offset, + int y_offset, + const uint8_t expected_colors[9]) +{ + float x1 = x_offset; + float y1 = y_offset; + float x2 = x1 + DRAW_SIZE; + float y2 = y1 + DRAW_SIZE; + int y, x; + + cogl_framebuffer_draw_textured_rectangle (test_fb, + pipeline, + x1, y1, + x2, y2, + -0.5f, /* s1 */ + -0.5f, /* t1 */ + 1.5f, /* s2 */ + 1.5f /* t2 */); + + check_colors (x_offset, y_offset, expected_colors); + + /* Also try drawing each quadrant of the rectangle with a small + * rectangle */ + + for (y = -1; y < 3; y++) + for (x = -1; x < 3; x++) + { + x1 = x_offset + (x + 1) * DRAW_SIZE / 4 + DRAW_SIZE; + y1 = y_offset + (y + 1) * DRAW_SIZE / 4; + x2 = x1 + DRAW_SIZE / 4; + y2 = y1 + DRAW_SIZE / 4; + + cogl_framebuffer_draw_textured_rectangle (test_fb, + pipeline, + x1, y1, + x2, y2, + x / 2.0f, /* s1 */ + y / 2.0f, /* t1 */ + (x + 1) / 2.0f, /* s2 */ + (y + 1) / 2.0f /* t2 */); + } + + check_colors (x_offset + DRAW_SIZE, y_offset, expected_colors); +} + +void +test_wrap_rectangle_textures (void) +{ + float fb_width = cogl_framebuffer_get_width (test_fb); + float fb_height = cogl_framebuffer_get_height (test_fb); + CoglPipeline *base_pipeline; + CoglPipeline *clamp_pipeline; + CoglPipeline *repeat_pipeline; + /* The textures are drawn with the texture coordinates from + * -0.5→1.5. That means we get one complete copy of the texture and + * an extra half of the texture surrounding it. The drawing is + * tested against a 4x4 grid of colors. The center 2x2 colours + * specify the normal texture colors and the other colours specify + * what the wrap mode should generate */ + static const uint8_t clamp_colors[] = + { + 0x44, 0x44, 0x88, 0x88, + 0x44, 0x44, 0x88, 0x88, + 0xcc, 0xcc, 0xff, 0xff, + 0xcc, 0xcc, 0xff, 0xff + }; + static const uint8_t repeat_colors[] = + { + 0xff, 0xcc, 0xff, 0xcc, + 0x88, 0x44, 0x88, 0x44, + 0xff, 0xcc, 0xff, 0xcc, + 0x88, 0x44, 0x88, 0x44 + }; + + cogl_framebuffer_orthographic (test_fb, + 0, 0, /* x_1, y_1 */ + fb_width, /* x_2 */ + fb_height /* y_2 */, + -1, 100 /* near/far */); + + base_pipeline = create_base_pipeline (); + + clamp_pipeline = cogl_pipeline_copy (base_pipeline); + cogl_pipeline_set_layer_wrap_mode (clamp_pipeline, + 0, /* layer */ + COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); + + repeat_pipeline = cogl_pipeline_copy (base_pipeline); + cogl_pipeline_set_layer_wrap_mode (repeat_pipeline, + 0, /* layer */ + COGL_PIPELINE_WRAP_MODE_REPEAT); + + test_pipeline (clamp_pipeline, + 0, 0, /* x/y offset */ + clamp_colors); + + test_pipeline (repeat_pipeline, + 0, DRAW_SIZE * 2, /* x/y offset */ + repeat_colors); + + cogl_object_unref (repeat_pipeline); + cogl_object_unref (clamp_pipeline); + cogl_object_unref (base_pipeline); +} diff --git a/cogl/tests/conform/test-write-texture-formats.c b/cogl/tests/conform/test-write-texture-formats.c new file mode 100644 index 0000000..76c4348 --- /dev/null +++ b/cogl/tests/conform/test-write-texture-formats.c @@ -0,0 +1,184 @@ +#include +#include + +#include "test-utils.h" + +/* + * This tests writing data to an RGBA texture in all of the available + * pixel formats + */ + +static void +test_color (CoglTexture *texture, + uint32_t expected_pixel) +{ + uint8_t received_pixel[4]; + + cogl_texture_get_data (texture, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + 4, /* rowstride */ + received_pixel); + + test_utils_compare_pixel_and_alpha (received_pixel, expected_pixel); +} + +static void +test_write_byte (CoglContext *context, + CoglPixelFormat format, + uint8_t byte, + uint32_t expected_pixel) +{ + CoglTexture *texture = test_utils_create_color_texture (context, 0); + + cogl_texture_set_region (texture, + 0, 0, /* src_x / src_y */ + 0, 0, /* dst_x / dst_y */ + 1, 1, /* dst_w / dst_h */ + 1, 1, /* width / height */ + format, + 1, /* rowstride */ + &byte); + + test_color (texture, expected_pixel); + + cogl_object_unref (texture); +} + +static void +test_write_short (CoglContext *context, + CoglPixelFormat format, + uint16_t value, + uint32_t expected_pixel) +{ + CoglTexture *texture = test_utils_create_color_texture (context, 0); + + cogl_texture_set_region (texture, + 0, 0, /* src_x / src_y */ + 0, 0, /* dst_x / dst_y */ + 1, 1, /* dst_w / dst_h */ + 1, 1, /* width / height */ + format, + 2, /* rowstride */ + (uint8_t *) &value); + + test_color (texture, expected_pixel); + + cogl_object_unref (texture); +} + +static void +test_write_bytes (CoglContext *context, + CoglPixelFormat format, + uint32_t value, + uint32_t expected_pixel) +{ + CoglTexture *texture = test_utils_create_color_texture (context, 0); + + value = GUINT32_TO_BE (value); + + cogl_texture_set_region (texture, + 0, 0, /* src_x / src_y */ + 0, 0, /* dst_x / dst_y */ + 1, 1, /* dst_w / dst_h */ + 1, 1, /* width / height */ + format, + 4, /* rowstride */ + (uint8_t *) &value); + + test_color (texture, expected_pixel); + + cogl_object_unref (texture); +} + +static void +test_write_int (CoglContext *context, + CoglPixelFormat format, + uint32_t expected_pixel, + ...) +{ + va_list ap; + int bits; + uint32_t tex_data = 0; + int bits_sum = 0; + CoglTexture *texture = test_utils_create_color_texture (context, 0); + + va_start (ap, expected_pixel); + + /* Convert the va args into a single 32-bit value */ + while ((bits = va_arg (ap, int)) != -1) + { + uint32_t value = (va_arg (ap, int) * ((1 << bits) - 1) + 127) / 255; + + bits_sum += bits; + + tex_data |= value << (32 - bits_sum); + } + + va_end (ap); + + cogl_texture_set_region (texture, + 0, 0, /* src_x / src_y */ + 0, 0, /* dst_x / dst_y */ + 1, 1, /* dst_w / dst_h */ + 1, 1, /* width / height */ + format, + 4, /* rowstride */ + (uint8_t *) &tex_data); + + test_color (texture, expected_pixel); + + cogl_object_unref (texture); +} + +void +test_write_texture_formats (void) +{ + test_write_byte (test_ctx, COGL_PIXEL_FORMAT_A_8, 0x34, 0x00000034); +#if 0 + /* I'm not sure what's the right value to put here because Nvidia + and Mesa seem to behave differently so one of them must be + wrong. */ + test_write_byte (test_ctx, COGL_PIXEL_FORMAT_G_8, 0x34, 0x340000ff); +#endif + + /* We should always be able to read from an RG buffer regardless of + * whether RG textures are supported because Cogl will do the + * conversion for us */ + test_write_bytes (test_ctx, COGL_PIXEL_FORMAT_RG_88, 0x123456ff, 0x123400ff); + + test_write_short (test_ctx, COGL_PIXEL_FORMAT_RGB_565, 0x0843, 0x080819ff); + test_write_short (test_ctx, COGL_PIXEL_FORMAT_RGBA_4444_PRE, 0x1234, 0x11223344); + test_write_short (test_ctx, COGL_PIXEL_FORMAT_RGBA_5551_PRE, 0x0887, 0x081019ff); + + test_write_bytes (test_ctx, COGL_PIXEL_FORMAT_RGB_888, 0x123456ff, 0x123456ff); + test_write_bytes (test_ctx, COGL_PIXEL_FORMAT_BGR_888, 0x563412ff, 0x123456ff); + + test_write_bytes (test_ctx, COGL_PIXEL_FORMAT_RGBA_8888_PRE, + 0x12345678, 0x12345678); + test_write_bytes (test_ctx, COGL_PIXEL_FORMAT_BGRA_8888_PRE, + 0x56341278, 0x12345678); + test_write_bytes (test_ctx, COGL_PIXEL_FORMAT_ARGB_8888_PRE, + 0x78123456, 0x12345678); + test_write_bytes (test_ctx, COGL_PIXEL_FORMAT_ABGR_8888_PRE, + 0x78563412, 0x12345678); + + test_write_int (test_ctx, COGL_PIXEL_FORMAT_RGBA_1010102_PRE, + 0x123456ff, + 10, 0x12, 10, 0x34, 10, 0x56, 2, 0xff, + -1); + test_write_int (test_ctx, COGL_PIXEL_FORMAT_BGRA_1010102_PRE, + 0x123456ff, + 10, 0x56, 10, 0x34, 10, 0x12, 2, 0xff, + -1); + test_write_int (test_ctx, COGL_PIXEL_FORMAT_ARGB_2101010_PRE, + 0x123456ff, + 2, 0xff, 10, 0x12, 10, 0x34, 10, 0x56, + -1); + test_write_int (test_ctx, COGL_PIXEL_FORMAT_ABGR_2101010_PRE, + 0x123456ff, + 2, 0xff, 10, 0x56, 10, 0x34, 10, 0x12, + -1); + + if (cogl_test_verbose ()) + g_print ("OK\n"); +} diff --git a/cogl/tests/data/Makefile.am b/cogl/tests/data/Makefile.am new file mode 100644 index 0000000..3a2030a --- /dev/null +++ b/cogl/tests/data/Makefile.am @@ -0,0 +1,3 @@ +NULL = + +EXTRA_DIST = valgrind.suppressions diff --git a/cogl/tests/data/Makefile.in b/cogl/tests/data/Makefile.in new file mode 100644 index 0000000..b21311b --- /dev/null +++ b/cogl/tests/data/Makefile.in @@ -0,0 +1,517 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = tests/data +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/build/autotools/as-compiler-flag.m4 \ + $(top_srcdir)/build/autotools/introspection.m4 \ + $(top_srcdir)/build/autotools/libtool.m4 \ + $(top_srcdir)/build/autotools/ltoptions.m4 \ + $(top_srcdir)/build/autotools/ltsugar.m4 \ + $(top_srcdir)/build/autotools/ltversion.m4 \ + $(top_srcdir)/build/autotools/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/cogl-config.h \ + $(top_builddir)/cogl-mutter-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_REQ_VERSION = @CAIRO_REQ_VERSION@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COGL_1_MICRO_VERSION = @COGL_1_MICRO_VERSION@ +COGL_1_MINOR_VERSION = @COGL_1_MINOR_VERSION@ +COGL_1_VERSION = @COGL_1_VERSION@ +COGL_API_VERSION = @COGL_API_VERSION@ +COGL_API_VERSION_AM = @COGL_API_VERSION_AM@ +COGL_DEBUG_CFLAGS = @COGL_DEBUG_CFLAGS@ +COGL_DEFAULT_DRIVER = @COGL_DEFAULT_DRIVER@ +COGL_DEP_CFLAGS = @COGL_DEP_CFLAGS@ +COGL_DEP_GL_CFLAGS = @COGL_DEP_GL_CFLAGS@ +COGL_DEP_GL_LIBS = @COGL_DEP_GL_LIBS@ +COGL_DEP_LIBS = @COGL_DEP_LIBS@ +COGL_EGL_INCLUDES = @COGL_EGL_INCLUDES@ +COGL_EXTRA_CFLAGS = @COGL_EXTRA_CFLAGS@ +COGL_EXTRA_LDFLAGS = @COGL_EXTRA_LDFLAGS@ +COGL_GLES1_LIBNAME = @COGL_GLES1_LIBNAME@ +COGL_GLES2_LIBNAME = @COGL_GLES2_LIBNAME@ +COGL_GL_LIBNAME = @COGL_GL_LIBNAME@ +COGL_GST_DEP_CFLAGS = @COGL_GST_DEP_CFLAGS@ +COGL_GST_DEP_LIBS = @COGL_GST_DEP_LIBS@ +COGL_LT_AGE = @COGL_LT_AGE@ +COGL_LT_CURRENT = @COGL_LT_CURRENT@ +COGL_LT_RELEASE = @COGL_LT_RELEASE@ +COGL_LT_REVISION = @COGL_LT_REVISION@ +COGL_MAJOR_VERSION = @COGL_MAJOR_VERSION@ +COGL_MICRO_VERSION = @COGL_MICRO_VERSION@ +COGL_MINOR_VERSION = @COGL_MINOR_VERSION@ +COGL_PANGO_DEP_CFLAGS = @COGL_PANGO_DEP_CFLAGS@ +COGL_PANGO_DEP_LIBS = @COGL_PANGO_DEP_LIBS@ +COGL_PANGO_PKG_REQUIRES = @COGL_PANGO_PKG_REQUIRES@ +COGL_PKG_REQUIRES = @COGL_PKG_REQUIRES@ +COGL_RELEASE_STATUS = @COGL_RELEASE_STATUS@ +COGL_VERSION = @COGL_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMMY_CFLAGS = @DUMMY_CFLAGS@ +DUMMY_LIBS = @DUMMY_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDKPIXBUF_PREFIX = @GDKPIXBUF_PREFIX@ +GDK_PIXBUF_REQ_VERSION = @GDK_PIXBUF_REQ_VERSION@ +GI_REQ_VERSION = @GI_REQ_VERSION@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ_VERSION = @GLIB_REQ_VERSION@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +HAVE_GL = @HAVE_GL@ +HAVE_GLES1 = @HAVE_GLES1@ +HAVE_GLES2 = @HAVE_GLES2@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINTAINER_CFLAGS = @MAINTAINER_CFLAGS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGOCAIRO_REQ_VERSION = @PANGOCAIRO_REQ_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +UPROF_REQ_VERSION = @UPROF_REQ_VERSION@ +VERSION = @VERSION@ +WAYLAND_SERVER_CFLAGS = @WAYLAND_SERVER_CFLAGS@ +WAYLAND_SERVER_LIBS = @WAYLAND_SERVER_LIBS@ +WAYLAND_SERVER_REQ_VERSION = @WAYLAND_SERVER_REQ_VERSION@ +XCOMPOSITE_REQ_VERSION = @XCOMPOSITE_REQ_VERSION@ +XFIXES_REQ_VERSION = @XFIXES_REQ_VERSION@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = +EXTRA_DIST = valgrind.suppressions +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/data/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/data/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cogl/tests/data/valgrind.suppressions b/cogl/tests/data/valgrind.suppressions new file mode 100644 index 0000000..f47498d --- /dev/null +++ b/cogl/tests/data/valgrind.suppressions @@ -0,0 +1,173 @@ +{ + ioctl_1 + Memcheck:Param + ioctl(generic) + fun:ioctl + fun:driDrawableInitVBlank + fun:intelMakeCurrent + fun:glXMakeContextCurrent +} + +{ + ioctl_2 + Memcheck:Param + ioctl(generic) + fun:ioctl + fun:driDrawableGetMSC32 + fun:clutter_backend_glx_redraw +} + +{ + ioctl_3 + Memcheck:Param + ioctl(generic) + fun:ioctl + fun:driWaitForMSC32 + fun:clutter_backend_glx_redraw +} + +{ + mesa_init_context + Memcheck:Leak + fun:*alloc + ... + fun:glXCreateNewContext +} + +{ + type_register + Memcheck:Leak + fun:*alloc + ... + fun:g_type_register_* +} + +{ + type_ref + Memcheck:Leak + fun:*alloc + ... + fun:g_type_class_ref +} + +{ + type_interface_prereq + Memcheck:Leak + fun:*alloc + ... + fun:g_type_interface_add_prerequisite +} + +{ + get_charset + Memcheck:Leak + fun:*alloc + ... + fun:g_get_charset +} + +{ + cogl_features + Memcheck:Leak + fun:*alloc + ... + fun:cogl_get_features +} + +{ + glx_query_version + Memcheck:Leak + fun:*alloc + ... + fun:glXQueryVersion +} + +{ + glx_create_context + Memcheck:Leak + fun:*alloc + ... + fun:glXCreateNewContext +} + +{ + glx_make_current + Memcheck:Leak + fun:*alloc + ... + fun:glXMakeContextCurrent +} + +{ + gl_draw_arrays + Memcheck:Leak + fun:*malloc + ... + fun:glDrawArrays +} + +{ + cogl_clear + Memcheck:Leak + fun:*alloc + ... + fun:cogl_clear +} + +{ + default_font + Memcheck:Leak + fun:*alloc + ... + fun:clutter_backend_get_font_name +} + +{ + id_pool + Memcheck:Leak + fun:*alloc + ... + fun:clutter_id_pool_new +} + +{ + x_open_display + Memcheck:Leak + fun:*alloc + ... + fun:XOpenDisplay +} + +# ... and font descriptions from every "sans 12" type string +{ + pango_font_description_from_string + Memcheck:Leak + fun:*alloc + ... + fun:pango_font_description_from_string +} + +# other lib init +{ + fontconfig_init + Memcheck:Leak + fun:*alloc + ... + fun:FcConfigParseAndLoad +} + +{ + freetype_init + Memcheck:Leak + fun:*alloc + ... + fun:FT_Open_Face +} + +{ + x_init_ext + Memcheck:Leak + fun:*alloc + ... + fun:XInitExtension +} diff --git a/cogl/tests/micro-perf/Makefile.am b/cogl/tests/micro-perf/Makefile.am new file mode 100644 index 0000000..5462f79 --- /dev/null +++ b/cogl/tests/micro-perf/Makefile.am @@ -0,0 +1,23 @@ +NULL = + +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + -DCOGL_DISABLE_DEPRECATED + +test_conformance_CPPFLAGS = \ + -DTESTS_DATADIR=\""$(top_srcdir)/tests/data"\" + + +noinst_PROGRAMS = + +noinst_PROGRAMS += test-journal + +AM_CFLAGS = $(COGL_DEP_CFLAGS) $(COGL_EXTRA_CFLAGS) + +common_ldadd = \ + $(COGL_DEP_LIBS) \ + $(top_builddir)/cogl/libmutter-cogl.la \ + $(LIBM) + +test_journal_SOURCES = test-journal.c +test_journal_LDADD = $(common_ldadd) diff --git a/cogl/tests/micro-perf/Makefile.in b/cogl/tests/micro-perf/Makefile.in new file mode 100644 index 0000000..a85d865 --- /dev/null +++ b/cogl/tests/micro-perf/Makefile.in @@ -0,0 +1,683 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +noinst_PROGRAMS = test-journal$(EXEEXT) +subdir = tests/micro-perf +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/build/autotools/as-compiler-flag.m4 \ + $(top_srcdir)/build/autotools/introspection.m4 \ + $(top_srcdir)/build/autotools/libtool.m4 \ + $(top_srcdir)/build/autotools/ltoptions.m4 \ + $(top_srcdir)/build/autotools/ltsugar.m4 \ + $(top_srcdir)/build/autotools/ltversion.m4 \ + $(top_srcdir)/build/autotools/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/cogl-config.h \ + $(top_builddir)/cogl-mutter-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +am_test_journal_OBJECTS = test-journal.$(OBJEXT) +test_journal_OBJECTS = $(am_test_journal_OBJECTS) +am__DEPENDENCIES_1 = +am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) \ + $(top_builddir)/cogl/libmutter-cogl.la $(am__DEPENDENCIES_1) +test_journal_DEPENDENCIES = $(am__DEPENDENCIES_2) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(test_journal_SOURCES) +DIST_SOURCES = $(test_journal_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/build/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_REQ_VERSION = @CAIRO_REQ_VERSION@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COGL_1_MICRO_VERSION = @COGL_1_MICRO_VERSION@ +COGL_1_MINOR_VERSION = @COGL_1_MINOR_VERSION@ +COGL_1_VERSION = @COGL_1_VERSION@ +COGL_API_VERSION = @COGL_API_VERSION@ +COGL_API_VERSION_AM = @COGL_API_VERSION_AM@ +COGL_DEBUG_CFLAGS = @COGL_DEBUG_CFLAGS@ +COGL_DEFAULT_DRIVER = @COGL_DEFAULT_DRIVER@ +COGL_DEP_CFLAGS = @COGL_DEP_CFLAGS@ +COGL_DEP_GL_CFLAGS = @COGL_DEP_GL_CFLAGS@ +COGL_DEP_GL_LIBS = @COGL_DEP_GL_LIBS@ +COGL_DEP_LIBS = @COGL_DEP_LIBS@ +COGL_EGL_INCLUDES = @COGL_EGL_INCLUDES@ +COGL_EXTRA_CFLAGS = @COGL_EXTRA_CFLAGS@ +COGL_EXTRA_LDFLAGS = @COGL_EXTRA_LDFLAGS@ +COGL_GLES1_LIBNAME = @COGL_GLES1_LIBNAME@ +COGL_GLES2_LIBNAME = @COGL_GLES2_LIBNAME@ +COGL_GL_LIBNAME = @COGL_GL_LIBNAME@ +COGL_GST_DEP_CFLAGS = @COGL_GST_DEP_CFLAGS@ +COGL_GST_DEP_LIBS = @COGL_GST_DEP_LIBS@ +COGL_LT_AGE = @COGL_LT_AGE@ +COGL_LT_CURRENT = @COGL_LT_CURRENT@ +COGL_LT_RELEASE = @COGL_LT_RELEASE@ +COGL_LT_REVISION = @COGL_LT_REVISION@ +COGL_MAJOR_VERSION = @COGL_MAJOR_VERSION@ +COGL_MICRO_VERSION = @COGL_MICRO_VERSION@ +COGL_MINOR_VERSION = @COGL_MINOR_VERSION@ +COGL_PANGO_DEP_CFLAGS = @COGL_PANGO_DEP_CFLAGS@ +COGL_PANGO_DEP_LIBS = @COGL_PANGO_DEP_LIBS@ +COGL_PANGO_PKG_REQUIRES = @COGL_PANGO_PKG_REQUIRES@ +COGL_PKG_REQUIRES = @COGL_PKG_REQUIRES@ +COGL_RELEASE_STATUS = @COGL_RELEASE_STATUS@ +COGL_VERSION = @COGL_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMMY_CFLAGS = @DUMMY_CFLAGS@ +DUMMY_LIBS = @DUMMY_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDKPIXBUF_PREFIX = @GDKPIXBUF_PREFIX@ +GDK_PIXBUF_REQ_VERSION = @GDK_PIXBUF_REQ_VERSION@ +GI_REQ_VERSION = @GI_REQ_VERSION@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ_VERSION = @GLIB_REQ_VERSION@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +HAVE_GL = @HAVE_GL@ +HAVE_GLES1 = @HAVE_GLES1@ +HAVE_GLES2 = @HAVE_GLES2@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINTAINER_CFLAGS = @MAINTAINER_CFLAGS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGOCAIRO_REQ_VERSION = @PANGOCAIRO_REQ_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +UPROF_REQ_VERSION = @UPROF_REQ_VERSION@ +VERSION = @VERSION@ +WAYLAND_SERVER_CFLAGS = @WAYLAND_SERVER_CFLAGS@ +WAYLAND_SERVER_LIBS = @WAYLAND_SERVER_LIBS@ +WAYLAND_SERVER_REQ_VERSION = @WAYLAND_SERVER_REQ_VERSION@ +XCOMPOSITE_REQ_VERSION = @XCOMPOSITE_REQ_VERSION@ +XFIXES_REQ_VERSION = @XFIXES_REQ_VERSION@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + -DCOGL_DISABLE_DEPRECATED + +test_conformance_CPPFLAGS = \ + -DTESTS_DATADIR=\""$(top_srcdir)/tests/data"\" + +AM_CFLAGS = $(COGL_DEP_CFLAGS) $(COGL_EXTRA_CFLAGS) +common_ldadd = \ + $(COGL_DEP_LIBS) \ + $(top_builddir)/cogl/libmutter-cogl.la \ + $(LIBM) + +test_journal_SOURCES = test-journal.c +test_journal_LDADD = $(common_ldadd) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/micro-perf/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/micro-perf/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +test-journal$(EXEEXT): $(test_journal_OBJECTS) $(test_journal_DEPENDENCIES) $(EXTRA_test_journal_DEPENDENCIES) + @rm -f test-journal$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_journal_OBJECTS) $(test_journal_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-journal.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cogl/tests/micro-perf/test-journal.c b/cogl/tests/micro-perf/test-journal.c new file mode 100644 index 0000000..7bfdcf7 --- /dev/null +++ b/cogl/tests/micro-perf/test-journal.c @@ -0,0 +1,190 @@ +#include +#include +#include + +#include "cogl/cogl-profile.h" + +#define FRAMEBUFFER_WIDTH 800 +#define FRAMEBUFFER_HEIGHT 600 + +CoglBool run_all = FALSE; + +typedef struct _Data +{ + CoglContext *ctx; + CoglFramebuffer *fb; + CoglPipeline *pipeline; + CoglPipeline *alpha_pipeline; + GTimer *timer; + int frame; +} Data; + +static void +test_rectangles (Data *data) +{ +#define RECT_WIDTH 5 +#define RECT_HEIGHT 5 + int x; + int y; + + cogl_framebuffer_clear4f (data->fb, COGL_BUFFER_BIT_COLOR, 1, 1, 1, 1); + + cogl_framebuffer_push_rectangle_clip (data->fb, + 10, + 10, + FRAMEBUFFER_WIDTH - 10, + FRAMEBUFFER_HEIGHT - 10); + + /* Should the rectangles be randomly positioned/colored/rotated? + * + * It could be good to develop equivalent GL and Cairo tests so we can + * have a sanity check for our Cogl performance. + * + * The color should vary to check that we correctly batch color changes + * The use of alpha should vary so we have a variation of which rectangles + * require blending. + * Should this be a random variation? + * It could be good to experiment with focibly enabling blending for + * rectangles that don't technically need it for the sake of extending + * batching. E.g. if you a long run of interleved rectangles with every + * other rectangle needing blending then it may be worth enabling blending + * for all the rectangles to avoid the state changes. + * The modelview should change between rectangles to check the software + * transform codepath. + * Should we group some rectangles under the same modelview? Potentially + * we could avoid software transform for long runs of rectangles with the + * same modelview. + * + */ + for (y = 0; y < FRAMEBUFFER_HEIGHT; y += RECT_HEIGHT) + { + for (x = 0; x < FRAMEBUFFER_WIDTH; x += RECT_WIDTH) + { + cogl_framebuffer_push_matrix (data->fb); + cogl_framebuffer_translate (data->fb, x, y, 0); + cogl_framebuffer_rotate (data->fb, 45, 0, 0, 1); + + cogl_pipeline_set_color4f (data->pipeline, + 1, + (1.0f/FRAMEBUFFER_WIDTH)*y, + (1.0f/FRAMEBUFFER_HEIGHT)*x, + 1); + cogl_framebuffer_draw_rectangle (data->fb, + data->pipeline, + 0, 0, RECT_WIDTH, RECT_HEIGHT); + + cogl_framebuffer_pop_matrix (data->fb); + } + } + + for (y = 0; y < FRAMEBUFFER_HEIGHT; y += RECT_HEIGHT) + { + for (x = 0; x < FRAMEBUFFER_WIDTH; x += RECT_WIDTH) + { + cogl_framebuffer_push_matrix (data->fb); + cogl_framebuffer_translate (data->fb, x, y, 0); + + cogl_pipeline_set_color4f (data->alpha_pipeline, + 1, + (1.0f/FRAMEBUFFER_WIDTH)*x, + (1.0f/FRAMEBUFFER_HEIGHT)*y, + (1.0f/FRAMEBUFFER_WIDTH)*x); + cogl_framebuffer_draw_rectangle (data->fb, + data->alpha_pipeline, + 0, 0, RECT_WIDTH, RECT_HEIGHT); + + cogl_framebuffer_pop_matrix (data->fb); + } + } + + cogl_framebuffer_pop_clip (data->fb); +} + +static CoglBool +paint_cb (void *user_data) +{ + Data *data = user_data; + double elapsed; + + data->frame++; + + test_rectangles (data); + + cogl_onscreen_swap_buffers (COGL_ONSCREEN (data->fb)); + + elapsed = g_timer_elapsed (data->timer, NULL); + if (elapsed > 1.0) + { + g_print ("fps = %f\n", data->frame / elapsed); + g_timer_start (data->timer); + data->frame = 0; + } + + return FALSE; /* remove the callback */ +} + +static void +frame_event_cb (CoglOnscreen *onscreen, + CoglFrameEvent event, + CoglFrameInfo *info, + void *user_data) +{ + if (event == COGL_FRAME_EVENT_SYNC) + paint_cb (user_data); +} + +int +main (int argc, char **argv) +{ + Data data; + CoglOnscreen *onscreen; + GSource *cogl_source; + GMainLoop *loop; + COGL_STATIC_TIMER (mainloop_timer, + NULL, //no parent + "Mainloop", + "The time spent in the glib mainloop", + 0); // no application private data + + data.ctx = cogl_context_new (NULL, NULL); + + onscreen = cogl_onscreen_new (data.ctx, + FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT); + cogl_onscreen_set_swap_throttled (onscreen, FALSE); + cogl_onscreen_show (onscreen); + + data.fb = onscreen; + cogl_framebuffer_orthographic (data.fb, + 0, 0, + FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT, + -1, + 100); + + data.pipeline = cogl_pipeline_new (data.ctx); + cogl_pipeline_set_color4f (data.pipeline, 1, 1, 1, 1); + data.alpha_pipeline = cogl_pipeline_new (data.ctx); + cogl_pipeline_set_color4f (data.alpha_pipeline, 1, 1, 1, 0.5); + + cogl_source = cogl_glib_source_new (data.ctx, G_PRIORITY_DEFAULT); + + g_source_attach (cogl_source, NULL); + + cogl_onscreen_add_frame_callback (COGL_ONSCREEN (data.fb), + frame_event_cb, + &data, + NULL); /* destroy notify */ + + g_idle_add (paint_cb, &data); + + data.frame = 0; + data.timer = g_timer_new (); + g_timer_start (data.timer); + + loop = g_main_loop_new (NULL, TRUE); + COGL_TIMER_START (uprof_get_mainloop_context (), mainloop_timer); + g_main_loop_run (loop); + COGL_TIMER_STOP (uprof_get_mainloop_context (), mainloop_timer); + + return 0; +} + diff --git a/cogl/tests/run-tests.sh b/cogl/tests/run-tests.sh new file mode 100755 index 0000000..7e62bf0 --- /dev/null +++ b/cogl/tests/run-tests.sh @@ -0,0 +1,157 @@ +#!/bin/bash + +if test -z "$G_DEBUG"; then + G_DEBUG=fatal-warnings +else + G_DEBUG="$G_DEBUG,fatal-warnings" +fi + +export G_DEBUG + +ENVIRONMENT_CONFIG=$1 +shift + +TEST_BINARY=$1 +shift + +. $ENVIRONMENT_CONFIG + +set +m + +trap "" ERR +trap "" SIGABRT +trap "" SIGFPE +trap "" SIGSEGV + +EXIT=0 +MISSING_FEATURE="WARNING: Missing required feature"; +KNOWN_FAILURE="WARNING: Test is known to fail"; + +echo "Key:" +echo "ok = Test passed" +echo "n/a = Driver is missing a feature required for the test" +echo "FAIL = Unexpected failure" +echo "FIXME = Test failed, but it was an expected failure" +echo "PASS! = Unexpected pass" +echo "" + +get_status() +{ + case $1 in + # Special value we use to indicate that the test failed + # but it was an expected failure so don't fail the + # overall test run as a result... + 300) + echo -n "FIXME";; + # Special value we use to indicate that the test passed + # but we weren't expecting it to pass‽ + 400) + echo -n 'PASS!';; + + # Special value to indicate the test is missing a required feature + 500) + echo -n "n/a";; + + 0) + echo -n "ok";; + + *) + echo -n "FAIL";; + esac +} + +run_test() +{ + $($TEST_BINARY $1 &>.log) + TMP=$? + var_name=$2_result + eval $var_name=$TMP + if grep -q "$MISSING_FEATURE" .log; then + if test $TMP -ne 0; then + eval $var_name=500 + else + eval $var_name=400 + fi + elif grep -q "$KNOWN_FAILURE" .log; then + if test $TMP -ne 0; then + eval $var_name=300 + else + eval $var_name=400 + fi + else + if test $TMP -ne 0; then EXIT=$TMP; fi + fi +} + +TITLE_FORMAT="%35s" +printf $TITLE_FORMAT "Test" + +if test $HAVE_GL -eq 1; then + GL_FORMAT=" %6s %8s %7s %6s %6s" + printf "$GL_FORMAT" "GL+FF" "GL+ARBFP" "GL+GLSL" "GL-NPT" "GL3" +fi +if test $HAVE_GLES2 -eq 1; then + GLES2_FORMAT=" %6s %7s" + printf "$GLES2_FORMAT" "ES2" "ES2-NPT" +fi + +echo "" +echo "" + +for test in `cat unit-tests` +do + export COGL_DEBUG= + + if test $HAVE_GL -eq 1; then + export COGL_DRIVER=gl + export COGL_DEBUG=disable-glsl,disable-arbfp + run_test $test gl_ff + + export COGL_DRIVER=gl + # NB: we can't explicitly disable fixed + glsl in this case since + # the arbfp code only supports fragment processing so we need either + # the fixed or glsl vertends + export COGL_DEBUG= + run_test $test gl_arbfp + + export COGL_DRIVER=gl + export COGL_DEBUG=disable-fixed,disable-arbfp + run_test $test gl_glsl + + export COGL_DRIVER=gl + export COGL_DEBUG=disable-npot-textures + run_test $test gl_npot + + export COGL_DRIVER=gl3 + export COGL_DEBUG= + run_test $test gl3 + fi + + if test $HAVE_GLES2 -eq 1; then + export COGL_DRIVER=gles2 + export COGL_DEBUG= + run_test $test gles2 + + export COGL_DRIVER=gles2 + export COGL_DEBUG=disable-npot-textures + run_test $test gles2_npot + fi + + printf $TITLE_FORMAT "$test:" + if test $HAVE_GL -eq 1; then + printf "$GL_FORMAT" \ + "`get_status $gl_ff_result`" \ + "`get_status $gl_arbfp_result`" \ + "`get_status $gl_glsl_result`" \ + "`get_status $gl_npot_result`" \ + "`get_status $gl3_result`" + fi + if test $HAVE_GLES2 -eq 1; then + printf "$GLES2_FORMAT" \ + "`get_status $gles2_result`" \ + "`get_status $gles2_npot_result`" + fi + echo "" +done + +exit $EXIT diff --git a/cogl/tests/test-launcher.sh b/cogl/tests/test-launcher.sh new file mode 100755 index 0000000..e159e2e --- /dev/null +++ b/cogl/tests/test-launcher.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +TEST_BINARY=$1 +shift + +SYMBOL_PREFIX=$1 +shift + +UNIT_TEST=$1 +shift + +test -z ${UNIT_TEST} && { + echo "Usage: $0 UNIT_TEST" + exit 1 +} + +BINARY_NAME=`basename $TEST_BINARY` +UNIT_TEST=`echo $UNIT_TEST|sed 's/-/_/g'` + +echo "Running: ./$BINARY_NAME ${UNIT_TEST} $@" +echo "" +COGL_TEST_VERBOSE=1 $TEST_BINARY ${UNIT_TEST} "$@" +exit_val=$? + +if test $exit_val -eq 0; then + echo "OK" +fi + +echo "" +echo "NOTE: For debugging purposes, you can run this single test as follows:" +echo "$ libtool --mode=execute \\" +echo " gdb --eval-command=\"start\" --eval-command=\"b ${UNIT_TEST#${SYMBOL_PREFIX}}\" \\" +echo " --args ./$BINARY_NAME ${UNIT_TEST}" +echo "or:" +echo "$ env G_SLICE=always-malloc \\" +echo " libtool --mode=execute \\" +echo " valgrind ./$BINARY_NAME ${UNIT_TEST}" + +exit $exit_val diff --git a/cogl/tests/unit/Makefile.am b/cogl/tests/unit/Makefile.am new file mode 100644 index 0000000..7851ace --- /dev/null +++ b/cogl/tests/unit/Makefile.am @@ -0,0 +1,84 @@ +NULL = + +noinst_PROGRAMS = test-unit + +test_unit_SOURCES = test-unit-main.c + +SHEXT = $(EXEEXT) + +# For convenience, this provides a way to easily run individual unit tests: +.PHONY: wrappers clean-wrappers + +wrappers: stamp-test-unit + @true +stamp-test-unit: Makefile test-unit$(EXEEXT) + @mkdir -p wrappers + . $(top_builddir)/cogl/libmutter-cogl.la ; \ + $(NM) $(top_builddir)/cogl/.libs/"$$dlname"| \ + grep '[DR] _\?unit_test_'|sed 's/.\+ [DR] _\?//' > unit-tests + @chmod +x $(top_srcdir)/tests/test-launcher.sh + @( echo "/stamp-test-unit" ; \ + echo "/test-unit$(EXEEXT)" ; \ + echo "*.o" ; \ + echo ".gitignore" ; \ + echo "unit-tests" ; ) > .gitignore + @for i in `cat unit-tests`; \ + do \ + unit=`echo $$i | sed -e s/_/-/g | sed s/unit-test-//`; \ + echo " GEN $$unit"; \ + ( echo "#!/bin/sh" ; echo "$(top_srcdir)/tests/test-launcher.sh $(abs_builddir)/test-unit$(EXEEXT) 'unit_test_' '$$i' \"\$$@\"" ) > $$unit$(SHEXT) ; \ + chmod +x $$unit$(SHEXT); \ + echo "/$$unit$(SHEXT)" >> .gitignore; \ + done \ + && echo timestamp > $(@F) + +clean-wrappers: + @for i in `cat unit-tests`; \ + do \ + unit=`echo $$i | sed -e s/_/-/g | sed s/unit-test-//`; \ + echo " RM $$unit"; \ + rm -f $$unit$(SHEXT) ; \ + done \ + && rm -f unit-tests \ + && rm -f stamp-test-unit + +# NB: BUILT_SOURCES here a misnomer. We aren't building source, just inserting +# a phony rule that will generate symlink scripts for running individual tests +BUILT_SOURCES = wrappers + +# The include of the $(buildir)/cogl directory here is to make it so +# that tests that directly include Cogl source code for whitebox +# testing (such as test-bitmask) will still compile +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + -I$(top_srcdir)/test-fixtures \ + -I$(top_builddir)/cogl + +AM_CPPFLAGS += \ + -DCOGL_DISABLE_DEPRECATED \ + -DTESTS_DATADIR=\""$(top_srcdir)/tests/data"\" \ + -DCOGL_COMPILATION + +test_unit_CFLAGS = -g3 -O0 $(COGL_DEP_CFLAGS) $(COGL_EXTRA_CFLAGS) +test_unit_LDADD = \ + $(COGL_DEP_LIBS) \ + $(top_builddir)/cogl/libmutter-cogl.la \ + $(LIBM) +test_unit_LDFLAGS = -export-dynamic + +# XXX: uncomment when tests get fixed +#test: wrappers +# @$(top_srcdir)/tests/run-tests.sh $(abs_builddir)/../config.env $(abs_builddir)/test-unit$(EXEEXT) + +# XXX: we could prevent the unit test suite from running +# by simply defining this variable conditionally +TEST_PROGS = test-unit + +.PHONY: test + +DISTCLEANFILES = .gitignore + +# we override the clean-generic target to clean up the wrappers so +# we cannot use CLEANFILES +clean-generic: clean-wrappers + $(QUIET_RM)rm -f .log diff --git a/cogl/tests/unit/Makefile.in b/cogl/tests/unit/Makefile.in new file mode 100644 index 0000000..947ca8e --- /dev/null +++ b/cogl/tests/unit/Makefile.in @@ -0,0 +1,760 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +noinst_PROGRAMS = test-unit$(EXEEXT) +subdir = tests/unit +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = \ + $(top_srcdir)/build/autotools/as-compiler-flag.m4 \ + $(top_srcdir)/build/autotools/introspection.m4 \ + $(top_srcdir)/build/autotools/libtool.m4 \ + $(top_srcdir)/build/autotools/ltoptions.m4 \ + $(top_srcdir)/build/autotools/ltsugar.m4 \ + $(top_srcdir)/build/autotools/ltversion.m4 \ + $(top_srcdir)/build/autotools/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/cogl-config.h \ + $(top_builddir)/cogl-mutter-config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +am_test_unit_OBJECTS = test_unit-test-unit-main.$(OBJEXT) +test_unit_OBJECTS = $(am_test_unit_OBJECTS) +am__DEPENDENCIES_1 = +test_unit_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(top_builddir)/cogl/libmutter-cogl.la $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +test_unit_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(test_unit_CFLAGS) \ + $(CFLAGS) $(test_unit_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(test_unit_SOURCES) +DIST_SOURCES = $(test_unit_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/build/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_REQ_VERSION = @CAIRO_REQ_VERSION@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COGL_1_MICRO_VERSION = @COGL_1_MICRO_VERSION@ +COGL_1_MINOR_VERSION = @COGL_1_MINOR_VERSION@ +COGL_1_VERSION = @COGL_1_VERSION@ +COGL_API_VERSION = @COGL_API_VERSION@ +COGL_API_VERSION_AM = @COGL_API_VERSION_AM@ +COGL_DEBUG_CFLAGS = @COGL_DEBUG_CFLAGS@ +COGL_DEFAULT_DRIVER = @COGL_DEFAULT_DRIVER@ +COGL_DEP_CFLAGS = @COGL_DEP_CFLAGS@ +COGL_DEP_GL_CFLAGS = @COGL_DEP_GL_CFLAGS@ +COGL_DEP_GL_LIBS = @COGL_DEP_GL_LIBS@ +COGL_DEP_LIBS = @COGL_DEP_LIBS@ +COGL_EGL_INCLUDES = @COGL_EGL_INCLUDES@ +COGL_EXTRA_CFLAGS = @COGL_EXTRA_CFLAGS@ +COGL_EXTRA_LDFLAGS = @COGL_EXTRA_LDFLAGS@ +COGL_GLES1_LIBNAME = @COGL_GLES1_LIBNAME@ +COGL_GLES2_LIBNAME = @COGL_GLES2_LIBNAME@ +COGL_GL_LIBNAME = @COGL_GL_LIBNAME@ +COGL_GST_DEP_CFLAGS = @COGL_GST_DEP_CFLAGS@ +COGL_GST_DEP_LIBS = @COGL_GST_DEP_LIBS@ +COGL_LT_AGE = @COGL_LT_AGE@ +COGL_LT_CURRENT = @COGL_LT_CURRENT@ +COGL_LT_RELEASE = @COGL_LT_RELEASE@ +COGL_LT_REVISION = @COGL_LT_REVISION@ +COGL_MAJOR_VERSION = @COGL_MAJOR_VERSION@ +COGL_MICRO_VERSION = @COGL_MICRO_VERSION@ +COGL_MINOR_VERSION = @COGL_MINOR_VERSION@ +COGL_PANGO_DEP_CFLAGS = @COGL_PANGO_DEP_CFLAGS@ +COGL_PANGO_DEP_LIBS = @COGL_PANGO_DEP_LIBS@ +COGL_PANGO_PKG_REQUIRES = @COGL_PANGO_PKG_REQUIRES@ +COGL_PKG_REQUIRES = @COGL_PKG_REQUIRES@ +COGL_RELEASE_STATUS = @COGL_RELEASE_STATUS@ +COGL_VERSION = @COGL_VERSION@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMMY_CFLAGS = @DUMMY_CFLAGS@ +DUMMY_LIBS = @DUMMY_LIBS@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GDKPIXBUF_PREFIX = @GDKPIXBUF_PREFIX@ +GDK_PIXBUF_REQ_VERSION = @GDK_PIXBUF_REQ_VERSION@ +GI_REQ_VERSION = @GI_REQ_VERSION@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_PREFIX = @GLIB_PREFIX@ +GLIB_REQ_VERSION = @GLIB_REQ_VERSION@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +HAVE_GL = @HAVE_GL@ +HAVE_GLES1 = @HAVE_GLES1@ +HAVE_GLES2 = @HAVE_GLES2@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINTAINER_CFLAGS = @MAINTAINER_CFLAGS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGOCAIRO_REQ_VERSION = @PANGOCAIRO_REQ_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +UPROF_REQ_VERSION = @UPROF_REQ_VERSION@ +VERSION = @VERSION@ +WAYLAND_SERVER_CFLAGS = @WAYLAND_SERVER_CFLAGS@ +WAYLAND_SERVER_LIBS = @WAYLAND_SERVER_LIBS@ +WAYLAND_SERVER_REQ_VERSION = @WAYLAND_SERVER_REQ_VERSION@ +XCOMPOSITE_REQ_VERSION = @XCOMPOSITE_REQ_VERSION@ +XFIXES_REQ_VERSION = @XFIXES_REQ_VERSION@ +XMKMF = @XMKMF@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = +test_unit_SOURCES = test-unit-main.c +SHEXT = $(EXEEXT) + +# NB: BUILT_SOURCES here a misnomer. We aren't building source, just inserting +# a phony rule that will generate symlink scripts for running individual tests +BUILT_SOURCES = wrappers + +# The include of the $(buildir)/cogl directory here is to make it so +# that tests that directly include Cogl source code for whitebox +# testing (such as test-bitmask) will still compile +AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/test-fixtures \ + -I$(top_builddir)/cogl -DCOGL_DISABLE_DEPRECATED \ + -DTESTS_DATADIR=\""$(top_srcdir)/tests/data"\" \ + -DCOGL_COMPILATION +test_unit_CFLAGS = -g3 -O0 $(COGL_DEP_CFLAGS) $(COGL_EXTRA_CFLAGS) +test_unit_LDADD = \ + $(COGL_DEP_LIBS) \ + $(top_builddir)/cogl/libmutter-cogl.la \ + $(LIBM) + +test_unit_LDFLAGS = -export-dynamic + +# XXX: uncomment when tests get fixed +#test: wrappers +# @$(top_srcdir)/tests/run-tests.sh $(abs_builddir)/../config.env $(abs_builddir)/test-unit$(EXEEXT) + +# XXX: we could prevent the unit test suite from running +# by simply defining this variable conditionally +TEST_PROGS = test-unit +DISTCLEANFILES = .gitignore +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/unit/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/unit/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +test-unit$(EXEEXT): $(test_unit_OBJECTS) $(test_unit_DEPENDENCIES) $(EXTRA_test_unit_DEPENDENCIES) + @rm -f test-unit$(EXEEXT) + $(AM_V_CCLD)$(test_unit_LINK) $(test_unit_OBJECTS) $(test_unit_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_unit-test-unit-main.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +test_unit-test-unit-main.o: test-unit-main.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_unit_CFLAGS) $(CFLAGS) -MT test_unit-test-unit-main.o -MD -MP -MF $(DEPDIR)/test_unit-test-unit-main.Tpo -c -o test_unit-test-unit-main.o `test -f 'test-unit-main.c' || echo '$(srcdir)/'`test-unit-main.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_unit-test-unit-main.Tpo $(DEPDIR)/test_unit-test-unit-main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-unit-main.c' object='test_unit-test-unit-main.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_unit_CFLAGS) $(CFLAGS) -c -o test_unit-test-unit-main.o `test -f 'test-unit-main.c' || echo '$(srcdir)/'`test-unit-main.c + +test_unit-test-unit-main.obj: test-unit-main.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_unit_CFLAGS) $(CFLAGS) -MT test_unit-test-unit-main.obj -MD -MP -MF $(DEPDIR)/test_unit-test-unit-main.Tpo -c -o test_unit-test-unit-main.obj `if test -f 'test-unit-main.c'; then $(CYGPATH_W) 'test-unit-main.c'; else $(CYGPATH_W) '$(srcdir)/test-unit-main.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_unit-test-unit-main.Tpo $(DEPDIR)/test_unit-test-unit-main.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-unit-main.c' object='test_unit-test-unit-main.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_unit_CFLAGS) $(CFLAGS) -c -o test_unit-test-unit-main.obj `if test -f 'test-unit-main.c'; then $(CYGPATH_W) 'test-unit-main.c'; else $(CYGPATH_W) '$(srcdir)/test-unit-main.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: all check install install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# For convenience, this provides a way to easily run individual unit tests: +.PHONY: wrappers clean-wrappers + +wrappers: stamp-test-unit + @true +stamp-test-unit: Makefile test-unit$(EXEEXT) + @mkdir -p wrappers + . $(top_builddir)/cogl/libmutter-cogl.la ; \ + $(NM) $(top_builddir)/cogl/.libs/"$$dlname"| \ + grep '[DR] _\?unit_test_'|sed 's/.\+ [DR] _\?//' > unit-tests + @chmod +x $(top_srcdir)/tests/test-launcher.sh + @( echo "/stamp-test-unit" ; \ + echo "/test-unit$(EXEEXT)" ; \ + echo "*.o" ; \ + echo ".gitignore" ; \ + echo "unit-tests" ; ) > .gitignore + @for i in `cat unit-tests`; \ + do \ + unit=`echo $$i | sed -e s/_/-/g | sed s/unit-test-//`; \ + echo " GEN $$unit"; \ + ( echo "#!/bin/sh" ; echo "$(top_srcdir)/tests/test-launcher.sh $(abs_builddir)/test-unit$(EXEEXT) 'unit_test_' '$$i' \"\$$@\"" ) > $$unit$(SHEXT) ; \ + chmod +x $$unit$(SHEXT); \ + echo "/$$unit$(SHEXT)" >> .gitignore; \ + done \ + && echo timestamp > $(@F) + +clean-wrappers: + @for i in `cat unit-tests`; \ + do \ + unit=`echo $$i | sed -e s/_/-/g | sed s/unit-test-//`; \ + echo " RM $$unit"; \ + rm -f $$unit$(SHEXT) ; \ + done \ + && rm -f unit-tests \ + && rm -f stamp-test-unit + +.PHONY: test + +# we override the clean-generic target to clean up the wrappers so +# we cannot use CLEANFILES +clean-generic: clean-wrappers + $(QUIET_RM)rm -f .log + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cogl/tests/unit/test-unit-main.c b/cogl/tests/unit/test-unit-main.c new file mode 100644 index 0000000..4be6700 --- /dev/null +++ b/cogl/tests/unit/test-unit-main.c @@ -0,0 +1,45 @@ +#include "cogl-config.h" + +#include + +#include +#include + +int +main (int argc, char **argv) +{ + GModule *main_module; + const CoglUnitTest *unit_test; + int i; + + if (argc != 2) + { + g_printerr ("usage %s UNIT_TEST\n", argv[0]); + exit (1); + } + + /* Just for convenience in case people try passing the wrapper + * filenames for the UNIT_TEST argument we normalize '-' characters + * to '_' characters... */ + for (i = 0; argv[1][i]; i++) + { + if (argv[1][i] == '-') + argv[1][i] = '_'; + } + + main_module = g_module_open (NULL, /* use main module */ + 0 /* flags */); + + if (!g_module_symbol (main_module, argv[1], (void **) &unit_test)) + { + g_printerr ("Unknown test name \"%s\"\n", argv[1]); + return 1; + } + + test_utils_init (unit_test->requirement_flags, + unit_test->known_failure_flags); + unit_test->run (); + test_utils_fini (); + + return 0; +} diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..73347da --- /dev/null +++ b/config.h.in @@ -0,0 +1,166 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if translation of program messages to the user's native + language is requested. */ +#undef ENABLE_NLS + +/* Name of default gettext domain */ +#undef GETTEXT_PACKAGE + +/* Define to 1 if you have the Mac OS X function CFLocaleCopyCurrent in the + CoreFoundation framework. */ +#undef HAVE_CFLOCALECOPYCURRENT + +/* Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in + the CoreFoundation framework. */ +#undef HAVE_CFPREFERENCESCOPYAPPVALUE + +/* Define if the GNU dcgettext() function is already present or preinstalled. + */ +#undef HAVE_DCGETTEXT + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define if the GNU gettext() function is already present or preinstalled. */ +#undef HAVE_GETTEXT + +/* Define if you have the iconv() function and it works. */ +#undef HAVE_ICONV + +/* Define if GObject introspection is available */ +#undef HAVE_INTROSPECTION + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Building with libcanberra for playing sounds */ +#undef HAVE_LIBCANBERRA + +/* Building with gudev for device type detection */ +#undef HAVE_LIBGUDEV + +/* Building with libwacom for advanced tablet management */ +#undef HAVE_LIBWACOM + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define if you want to enable the native (KMS) backend based on systemd */ +#undef HAVE_NATIVE_BACKEND + +/* Have the Xrandr extension library */ +#undef HAVE_RANDR + +/* Building with SM support */ +#undef HAVE_SM + +/* Building with startup notification support */ +#undef HAVE_STARTUP_NOTIFICATION + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define if you want to enable Wayland support */ +#undef HAVE_WAYLAND + +/* Define to 1 if you have the header file. */ +#undef HAVE_X11_SM_SMLIB_H + +/* Define if you have support for XInput 2.3 or greater */ +#undef HAVE_XI23 + +/* Define if you have support for XRandR 1.5 or greater */ +#undef HAVE_XRANDR15 + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#undef LT_OBJDIR + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +#undef NO_MINUS_C_MINUS_O + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# undef _POSIX_PTHREAD_SEMANTICS +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# undef _TANDEM_SOURCE +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# undef __EXTENSIONS__ +#endif + + +/* Version number of package */ +#undef VERSION + +/* Build with verbose mode support */ +#undef WITH_VERBOSE_MODE + +/* XKB base dir */ +#undef XKB_BASE + +/* Define to 1 if the X Window System is missing or not being used. */ +#undef X_DISPLAY_MISSING + +/* Define to 1 if on MINIX. */ +#undef _MINIX + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +#undef _POSIX_1_SOURCE + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +#undef _POSIX_SOURCE diff --git a/configure b/configure new file mode 100755 index 0000000..cc90f72 --- /dev/null +++ b/configure @@ -0,0 +1,20850 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for mutter 3.22.3. +# +# Report bugs to . +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1 + + test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org and +$0: http://bugzilla.gnome.org/enter_bug.cgi?product=mutter +$0: about your system, including any error possibly output +$0: before this message. Then install a modern shell, or +$0: manually run the script under such a shell if you do +$0: have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + +SHELL=${CONFIG_SHELL-/bin/sh} + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='mutter' +PACKAGE_TARNAME='mutter' +PACKAGE_VERSION='3.22.3' +PACKAGE_STRING='mutter 3.22.3' +PACKAGE_BUGREPORT='http://bugzilla.gnome.org/enter_bug.cgi?product=mutter' +PACKAGE_URL='' + +ac_unique_file="src/core/display.c" +enable_option_checking=no +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +gt_needs= +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +LIBOBJS +CVT +ZENITY +HAVE_SM_FALSE +HAVE_SM_TRUE +X_EXTRA_LIBS +X_LIBS +X_PRE_LIBS +X_CFLAGS +XMKMF +HAVE_WAYLAND_FALSE +HAVE_WAYLAND_TRUE +WAYLAND_PROTOCOLS_DATADIR +WAYLAND_PROTOCOLS_LIBS +WAYLAND_PROTOCOLS_CFLAGS +WAYLAND_SCANNER +MUTTER_WAYLAND_LIBS +MUTTER_WAYLAND_CFLAGS +HAVE_NATIVE_BACKEND_FALSE +HAVE_NATIVE_BACKEND_TRUE +MUTTER_NATIVE_BACKEND_LIBS +MUTTER_NATIVE_BACKEND_CFLAGS +MUTTER_LIBS +MUTTER_CFLAGS +XWAYLAND_PATH +META_GIR +HAVE_INTROSPECTION_FALSE +HAVE_INTROSPECTION_TRUE +INTROSPECTION_MAKEFILE +INTROSPECTION_LIBS +INTROSPECTION_CFLAGS +INTROSPECTION_TYPELIBDIR +INTROSPECTION_GIRDIR +INTROSPECTION_GENERATE +INTROSPECTION_COMPILER +INTROSPECTION_SCANNER +GNOME_KEYBINDINGS_KEYSDIR +BUILDOPT_INSTALL_TESTS_FALSE +BUILDOPT_INSTALL_TESTS_TRUE +GSETTINGS_RULES +GLIB_COMPILE_SCHEMAS +gsettingsschemadir +GSETTINGS_DISABLE_SCHEMAS_COMPILE +GLIB_COMPILE_RESOURCES +GLIB_MKENUMS +GOBJECT_QUERY +GLIB_GENMARSHAL +GLIB_LIBS +GLIB_CFLAGS +PKG_CONFIG_LIBDIR +PKG_CONFIG_PATH +PKG_CONFIG +LT_SYS_LIBRARY_PATH +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +MANIFEST_TOOL +RANLIB +ac_ct_AR +AR +DLLTOOL +OBJDUMP +LN_S +NM +ac_ct_DUMPBIN +DUMPBIN +LD +FGREP +LIBTOOL +POSUB +LTLIBINTL +LIBINTL +INTLLIBS +LTLIBICONV +LIBICONV +INTL_MACOSX_LIBS +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +XGETTEXT_EXTRA_OPTIONS +MSGMERGE +XGETTEXT_015 +XGETTEXT +GMSGFMT_015 +MSGFMT_015 +GMSGFMT +MSGFMT +GETTEXT_MACRO_VERSION +USE_NLS +SED +GETTEXT_PACKAGE +ACLOCAL_AMFLAGS +MUTTER_PLUGIN_DIR +MUTTER_PLUGIN_API_VERSION +MUTTER_MICRO_VERSION +MUTTER_MINOR_VERSION +MUTTER_MAJOR_VERSION +EGREP +GREP +CPP +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +am__nodep +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +MAINT +MAINTAINER_MODE_FALSE +MAINTAINER_MODE_TRUE +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +AM_DEFAULT_V +AM_V +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +subdirs +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_silent_rules +enable_maintainer_mode +enable_dependency_tracking +enable_nls +with_gnu_ld +enable_rpath +with_libiconv_prefix +with_libintl_prefix +enable_static +enable_shared +with_pic +enable_fast_install +with_aix_soname +with_sysroot +enable_libtool_lock +enable_glibtest +enable_schemas_compile +enable_verbose_mode +enable_sm +enable_startup_notification +with_libcanberra +with_libwacom +with_gudev +with_xwayland_path +enable_installed_tests +enable_introspection +enable_native_backend +enable_wayland +with_x +enable_debug +enable_compile_warnings +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP +LT_SYS_LIBRARY_PATH +PKG_CONFIG +PKG_CONFIG_PATH +PKG_CONFIG_LIBDIR +MUTTER_CFLAGS +MUTTER_LIBS +MUTTER_NATIVE_BACKEND_CFLAGS +MUTTER_NATIVE_BACKEND_LIBS +MUTTER_WAYLAND_CFLAGS +MUTTER_WAYLAND_LIBS +WAYLAND_PROTOCOLS_CFLAGS +WAYLAND_PROTOCOLS_LIBS +XMKMF' +ac_subdirs_all='cogl clutter' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures mutter 3.22.3 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/mutter] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +X features: + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of mutter 3.22.3:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-silent-rules less verbose build output (undo: "make V=1") + --disable-silent-rules verbose build output (undo: "make V=0") + --disable-maintainer-mode + disable make rules and dependencies not useful (and + sometimes confusing) to the casual installer + --enable-dependency-tracking + do not reject slow dependency extractors + --disable-dependency-tracking + speeds up one-time build + --disable-nls do not use Native Language Support + --disable-rpath do not hardcode runtime library paths + --enable-static[=PKGS] build static libraries [default=no] + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + --disable-glibtest do not try to compile and run a test GLIB program + --disable-schemas-compile + Disable regeneration of gschemas.compiled on install + --disable-verbose-mode disable mutter's ability to do verbose logging, for + embedded/size-sensitive custom builds + --disable-sm disable mutter's session management support, for + embedded/size-sensitive custom non-GNOME builds + --disable-startup-notification + disable mutter's startup notification support, for + embedded/size-sensitive custom non-GNOME builds + --enable-installed-tests + Install test programs (default: no) + --enable-introspection=[no/auto/yes] + Enable introspection for this build + --disable-native-backend + disable mutter native (KMS) backend + --disable-wayland disable mutter on wayland support + --enable-debug enable debugging + --enable-compile-warnings=[no/minimum/yes/maximum/error] + Turn on compiler warnings + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-libiconv-prefix[=DIR] search for libiconv in DIR/include and DIR/lib + --without-libiconv-prefix don't search for libiconv in includedir and libdir + --with-libintl-prefix[=DIR] search for libintl in DIR/include and DIR/lib + --without-libintl-prefix don't search for libintl in includedir and libdir + --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use + both] + --with-aix-soname=aix|svr4|both + shared library versioning (aka "SONAME") variant to + provide on AIX, [default=aix]. + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-sysroot[=DIR] Search for dependent libraries within DIR (or the + compiler's sysroot if not specified). + --without-libcanberra disable the use of libcanberra for playing sounds + --without-libwacom disable the use of libwacom for advanced tablet + management + --without-gudev disable the use of gudev for device type detection + --with-xwayland-path Absolute path for an X Wayland server + --with-x use the X Window System + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + LT_SYS_LIBRARY_PATH + User-defined run-time library search path. + PKG_CONFIG path to pkg-config utility + PKG_CONFIG_PATH + directories to add to pkg-config's search path + PKG_CONFIG_LIBDIR + path overriding pkg-config's built-in search path + MUTTER_CFLAGS + C compiler flags for MUTTER, overriding pkg-config + MUTTER_LIBS linker flags for MUTTER, overriding pkg-config + MUTTER_NATIVE_BACKEND_CFLAGS + C compiler flags for MUTTER_NATIVE_BACKEND, overriding + pkg-config + MUTTER_NATIVE_BACKEND_LIBS + linker flags for MUTTER_NATIVE_BACKEND, overriding pkg-config + MUTTER_WAYLAND_CFLAGS + C compiler flags for MUTTER_WAYLAND, overriding pkg-config + MUTTER_WAYLAND_LIBS + linker flags for MUTTER_WAYLAND, overriding pkg-config + WAYLAND_PROTOCOLS_CFLAGS + C compiler flags for WAYLAND_PROTOCOLS, overriding pkg-config + WAYLAND_PROTOCOLS_LIBS + linker flags for WAYLAND_PROTOCOLS, overriding pkg-config + XMKMF Path to xmkmf, Makefile generator for X Window System + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +mutter configure 3.22.3 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## --------------------------------------------------------------------- ## +## Report this to http://bugzilla.gnome.org/enter_bug.cgi?product=mutter ## +## --------------------------------------------------------------------- ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES +# --------------------------------------------- +# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR +# accordingly. +ac_fn_c_check_decl () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + as_decl_name=`echo $2|sed 's/ *(.*//'` + as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 +$as_echo_n "checking whether $as_decl_name is declared... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +#ifndef $as_decl_name +#ifdef __cplusplus + (void) $as_decl_use; +#else + (void) $as_decl_name; +#endif +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_decl +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by mutter $as_me 3.22.3, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +gt_needs="$gt_needs " +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + +ac_aux_dir= +for ac_dir in build-aux "$srcdir"/build-aux; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in build-aux \"$srcdir\"/build-aux" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + + +ac_config_headers="$ac_config_headers config.h" + + + +subdirs="$subdirs cogl clutter" + + +am__api_version='1.15' + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi + +rm -f conftest.file + +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=1;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='mutter' + VERSION='3.22.3' + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +mkdir_p='$(MKDIR_P)' + +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar plaintar pax cpio none' + +# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether UID '$am_uid' is supported by ustar format" >&5 +$as_echo_n "checking whether UID '$am_uid' is supported by ustar format... " >&6; } + if test $am_uid -le $am_max_uid; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + _am_tools=none + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GID '$am_gid' is supported by ustar format" >&5 +$as_echo_n "checking whether GID '$am_gid' is supported by ustar format... " >&6; } + if test $am_gid -le $am_max_gid; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + _am_tools=none + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to create a ustar tar archive" >&5 +$as_echo_n "checking how to create a ustar tar archive... " >&6; } + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_ustar-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + { echo "$as_me:$LINENO: $_am_tar --version" >&5 + ($_am_tar --version) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && break + done + am__tar="$_am_tar --format=ustar -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=ustar -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x ustar -w "$$tardir"' + am__tar_='pax -L -x ustar -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H ustar -L' + am__tar_='find "$tardir" -print | cpio -o -H ustar -L' + am__untar='cpio -i -H ustar -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_ustar}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + { echo "$as_me:$LINENO: tardir=conftest.dir && eval $am__tar_ >conftest.tar" >&5 + (tardir=conftest.dir && eval $am__tar_ >conftest.tar) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + rm -rf conftest.dir + if test -s conftest.tar; then + { echo "$as_me:$LINENO: $am__untar &5 + ($am__untar &5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + { echo "$as_me:$LINENO: cat conftest.dir/file" >&5 + (cat conftest.dir/file) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + grep GrepMe conftest.dir/file >/dev/null 2>&1 && break + fi + done + rm -rf conftest.dir + + if ${am_cv_prog_tar_ustar+:} false; then : + $as_echo_n "(cached) " >&6 +else + am_cv_prog_tar_ustar=$_am_tool +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_tar_ustar" >&5 +$as_echo "$am_cv_prog_tar_ustar" >&6; } + + + + + + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 + fi +fi + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=0;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 +$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } + # Check whether --enable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then : + enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval +else + USE_MAINTAINER_MODE=yes +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 +$as_echo "$USE_MAINTAINER_MODE" >&6; } + if test $USE_MAINTAINER_MODE = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi + + MAINT=$MAINTAINER_MODE_TRUE + + + +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 +$as_echo_n "checking for style of include used by $am_make... " >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 +$as_echo "$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default" +if test "x$ac_cv_header_minix_config_h" = xyes; then : + MINIX=yes +else + MINIX= +fi + + + if test "$MINIX" = yes; then + +$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h + + +$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h + + +$as_echo "#define _MINIX 1" >>confdefs.h + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5 +$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; } +if ${ac_cv_safe_to_define___extensions__+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +# define __EXTENSIONS__ 1 + $ac_includes_default +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_safe_to_define___extensions__=yes +else + ac_cv_safe_to_define___extensions__=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5 +$as_echo "$ac_cv_safe_to_define___extensions__" >&6; } + test $ac_cv_safe_to_define___extensions__ = yes && + $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h + + $as_echo "#define _ALL_SOURCE 1" >>confdefs.h + + $as_echo "#define _GNU_SOURCE 1" >>confdefs.h + + $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h + + $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h + + + + +MUTTER_MAJOR_VERSION=3 +MUTTER_MINOR_VERSION=22 +MUTTER_MICRO_VERSION=3 +MUTTER_PLUGIN_API_VERSION=3 + + + + + +MUTTER_PLUGIN_DIR="$libdir/$PACKAGE/plugins" + + +# Honor aclocal flags +ACLOCAL_AMFLAGS="\${ACLOCAL_FLAGS}" + + +GETTEXT_PACKAGE=mutter + + +cat >>confdefs.h <<_ACEOF +#define GETTEXT_PACKAGE "$GETTEXT_PACKAGE" +_ACEOF + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether NLS is requested" >&5 +$as_echo_n "checking whether NLS is requested... " >&6; } + # Check whether --enable-nls was given. +if test "${enable_nls+set}" = set; then : + enableval=$enable_nls; USE_NLS=$enableval +else + USE_NLS=yes +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_NLS" >&5 +$as_echo "$USE_NLS" >&6; } + + + + + GETTEXT_MACRO_VERSION=0.19 + + + + +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which + # contains only /bin. Note that ksh looks also at the FPATH variable, + # so we have to set that as well for the test. + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } +fi + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_MSGFMT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case "$MSGFMT" in + [\\/]* | ?:[\\/]*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&5 + if $ac_dir/$ac_word --statistics /dev/null >&5 2>&1 && + (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then + ac_cv_path_MSGFMT="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" + test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT=":" + ;; +esac +fi +MSGFMT="$ac_cv_path_MSGFMT" +if test "$MSGFMT" != ":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGFMT" >&5 +$as_echo "$MSGFMT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + # Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GMSGFMT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GMSGFMT in + [\\/]* | ?:[\\/]*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GMSGFMT="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT=$ac_cv_path_GMSGFMT +if test -n "$GMSGFMT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GMSGFMT" >&5 +$as_echo "$GMSGFMT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;; + *) MSGFMT_015=$MSGFMT ;; + esac + + case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;; + *) GMSGFMT_015=$GMSGFMT ;; + esac + + + +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which + # contains only /bin. Note that ksh looks also at the FPATH variable, + # so we have to set that as well for the test. + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } +fi + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_XGETTEXT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case "$XGETTEXT" in + [\\/]* | ?:[\\/]*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&5 + if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&5 2>&1 && + (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then + ac_cv_path_XGETTEXT="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" + test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" + ;; +esac +fi +XGETTEXT="$ac_cv_path_XGETTEXT" +if test "$XGETTEXT" != ":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XGETTEXT" >&5 +$as_echo "$XGETTEXT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + rm -f messages.po + + case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;; + *) XGETTEXT_015=$XGETTEXT ;; + esac + + + +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which + # contains only /bin. Note that ksh looks also at the FPATH variable, + # so we have to set that as well for the test. + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } +fi + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "msgmerge", so it can be a program name with args. +set dummy msgmerge; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_MSGMERGE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case "$MSGMERGE" in + [\\/]* | ?:[\\/]*) + ac_cv_path_MSGMERGE="$MSGMERGE" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&5 + if $ac_dir/$ac_word --update -q /dev/null /dev/null >&5 2>&1; then + ac_cv_path_MSGMERGE="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" + test -z "$ac_cv_path_MSGMERGE" && ac_cv_path_MSGMERGE=":" + ;; +esac +fi +MSGMERGE="$ac_cv_path_MSGMERGE" +if test "$MSGMERGE" != ":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGMERGE" >&5 +$as_echo "$MSGMERGE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$localedir" || localedir='${datadir}/locale' + + + test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS= + + + ac_config_commands="$ac_config_commands po-directories" + + + + if test "X$prefix" = "XNONE"; then + acl_final_prefix="$ac_default_prefix" + else + acl_final_prefix="$prefix" + fi + if test "X$exec_prefix" = "XNONE"; then + acl_final_exec_prefix='${prefix}' + else + acl_final_exec_prefix="$exec_prefix" + fi + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" + prefix="$acl_save_prefix" + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which + # contains only /bin. Note that ksh looks also at the FPATH variable, + # so we have to set that as well for the test. + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo "$ac_prog"| sed 's%\\\\%/%g'` + while echo "$ac_prog" | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${acl_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + acl_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$acl_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + acl_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$acl_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${acl_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$acl_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$acl_cv_prog_gnu_ld + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shared library run path origin" >&5 +$as_echo_n "checking for shared library run path origin... " >&6; } +if ${acl_cv_rpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + + CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ + ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh + . ./conftest.sh + rm -f ./conftest.sh + acl_cv_rpath=done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $acl_cv_rpath" >&5 +$as_echo "$acl_cv_rpath" >&6; } + wl="$acl_cv_wl" + acl_libext="$acl_cv_libext" + acl_shlibext="$acl_cv_shlibext" + acl_libname_spec="$acl_cv_libname_spec" + acl_library_names_spec="$acl_cv_library_names_spec" + acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" + acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" + acl_hardcode_direct="$acl_cv_hardcode_direct" + acl_hardcode_minus_L="$acl_cv_hardcode_minus_L" + # Check whether --enable-rpath was given. +if test "${enable_rpath+set}" = set; then : + enableval=$enable_rpath; : +else + enable_rpath=yes +fi + + + + + acl_libdirstem=lib + acl_libdirstem2= + case "$host_os" in + solaris*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit host" >&5 +$as_echo_n "checking for 64-bit host... " >&6; } +if ${gl_cv_solaris_64bit+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#ifdef _LP64 +sixtyfour bits +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "sixtyfour bits" >/dev/null 2>&1; then : + gl_cv_solaris_64bit=yes +else + gl_cv_solaris_64bit=no +fi +rm -f conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_solaris_64bit" >&5 +$as_echo "$gl_cv_solaris_64bit" >&6; } + if test $gl_cv_solaris_64bit = yes; then + acl_libdirstem=lib/64 + case "$host_cpu" in + sparc*) acl_libdirstem2=lib/sparcv9 ;; + i*86 | x86_64) acl_libdirstem2=lib/amd64 ;; + esac + fi + ;; + *) + searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` + if test -n "$searchpath"; then + acl_save_IFS="${IFS= }"; IFS=":" + for searchdir in $searchpath; do + if test -d "$searchdir"; then + case "$searchdir" in + */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; + */../ | */.. ) + # Better ignore directories of this form. They are misleading. + ;; + *) searchdir=`cd "$searchdir" && pwd` + case "$searchdir" in + */lib64 ) acl_libdirstem=lib64 ;; + esac ;; + esac + fi + done + IFS="$acl_save_IFS" + fi + ;; + esac + test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem" + + + + + + + + + + + + + use_additional=yes + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + +# Check whether --with-libiconv-prefix was given. +if test "${with_libiconv_prefix+set}" = set; then : + withval=$with_libiconv_prefix; + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + if test "$acl_libdirstem2" != "$acl_libdirstem" \ + && ! test -d "$withval/$acl_libdirstem"; then + additional_libdir="$withval/$acl_libdirstem2" + fi + fi + fi + +fi + + LIBICONV= + LTLIBICONV= + INCICONV= + LIBICONV_PREFIX= + HAVE_LIBICONV= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='iconv ' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./+-|ABCDEFGHIJKLMNOPQRSTUVWXYZ____|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIBICONV="${LIBICONV}${LIBICONV:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$value" + else + : + fi + else + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + if test "$enable_rpath" = no \ + || test "X$found_dir" = "X/usr/$acl_libdirstem" \ + || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + else + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + if test "$acl_hardcode_direct" = yes; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + haveit= + for x in $LDFLAGS $LIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + else + LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_a" + else + LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir -l$name" + fi + fi + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + if test "$name" = 'iconv'; then + LIBICONV_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + */$acl_libdirstem2 | */$acl_libdirstem2/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'` + if test "$name" = 'iconv'; then + LIBICONV_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INCICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + INCICONV="${INCICONV}${INCICONV:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + if test -n "$found_la"; then + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \ + && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \ + || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + LIBICONV="${LIBICONV}${LIBICONV:+ }$dep" + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$dep" + ;; + esac + done + fi + else + LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" + else + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + for found_dir in $ltrpathdirs; do + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-R$found_dir" + done + fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CFPreferencesCopyAppValue" >&5 +$as_echo_n "checking for CFPreferencesCopyAppValue... " >&6; } +if ${gt_cv_func_CFPreferencesCopyAppValue+:} false; then : + $as_echo_n "(cached) " >&6 +else + gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +CFPreferencesCopyAppValue(NULL, NULL) + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gt_cv_func_CFPreferencesCopyAppValue=yes +else + gt_cv_func_CFPreferencesCopyAppValue=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$gt_save_LIBS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_CFPreferencesCopyAppValue" >&5 +$as_echo "$gt_cv_func_CFPreferencesCopyAppValue" >&6; } + if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then + +$as_echo "#define HAVE_CFPREFERENCESCOPYAPPVALUE 1" >>confdefs.h + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CFLocaleCopyCurrent" >&5 +$as_echo_n "checking for CFLocaleCopyCurrent... " >&6; } +if ${gt_cv_func_CFLocaleCopyCurrent+:} false; then : + $as_echo_n "(cached) " >&6 +else + gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +CFLocaleCopyCurrent(); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gt_cv_func_CFLocaleCopyCurrent=yes +else + gt_cv_func_CFLocaleCopyCurrent=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$gt_save_LIBS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_CFLocaleCopyCurrent" >&5 +$as_echo "$gt_cv_func_CFLocaleCopyCurrent" >&6; } + if test $gt_cv_func_CFLocaleCopyCurrent = yes; then + +$as_echo "#define HAVE_CFLOCALECOPYCURRENT 1" >>confdefs.h + + fi + INTL_MACOSX_LIBS= + if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then + INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" + fi + + + + + + + LIBINTL= + LTLIBINTL= + POSUB= + + case " $gt_needs " in + *" need-formatstring-macros "*) gt_api_version=3 ;; + *" need-ngettext "*) gt_api_version=2 ;; + *) gt_api_version=1 ;; + esac + gt_func_gnugettext_libc="gt_cv_func_gnugettext${gt_api_version}_libc" + gt_func_gnugettext_libintl="gt_cv_func_gnugettext${gt_api_version}_libintl" + + if test "$USE_NLS" = "yes"; then + gt_use_preinstalled_gnugettext=no + + + if test $gt_api_version -ge 3; then + gt_revision_test_code=' +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) +#endif +typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; +' + else + gt_revision_test_code= + fi + if test $gt_api_version -ge 2; then + gt_expression_test_code=' + * ngettext ("", "", 0)' + else + gt_expression_test_code= + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU gettext in libc" >&5 +$as_echo_n "checking for GNU gettext in libc... " >&6; } +if eval \${$gt_func_gnugettext_libc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern int *_nl_domain_bindings; + +int +main () +{ + +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_bindings + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$gt_func_gnugettext_libc=yes" +else + eval "$gt_func_gnugettext_libc=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$gt_func_gnugettext_libc + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then + + + + + + am_save_CPPFLAGS="$CPPFLAGS" + + for element in $INCICONV; do + haveit= + for x in $CPPFLAGS; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" + fi + done + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv" >&5 +$as_echo_n "checking for iconv... " >&6; } +if ${am_cv_func_iconv+:} false; then : + $as_echo_n "(cached) " >&6 +else + + am_cv_func_iconv="no, consider installing GNU libiconv" + am_cv_lib_iconv=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include + +int +main () +{ +iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + am_cv_func_iconv=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test "$am_cv_func_iconv" != yes; then + am_save_LIBS="$LIBS" + LIBS="$LIBS $LIBICONV" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include + +int +main () +{ +iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + am_cv_lib_iconv=yes + am_cv_func_iconv=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$am_save_LIBS" + fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv" >&5 +$as_echo "$am_cv_func_iconv" >&6; } + if test "$am_cv_func_iconv" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working iconv" >&5 +$as_echo_n "checking for working iconv... " >&6; } +if ${am_cv_func_iconv_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + + am_save_LIBS="$LIBS" + if test $am_cv_lib_iconv = yes; then + LIBS="$LIBS $LIBICONV" + fi + am_cv_func_iconv_works=no + for ac_iconv_const in '' 'const'; do + if test "$cross_compiling" = yes; then : + case "$host_os" in + aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; + *) am_cv_func_iconv_works="guessing yes" ;; + esac +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include + +#ifndef ICONV_CONST +# define ICONV_CONST $ac_iconv_const +#endif + +int +main () +{ +int result = 0; + /* Test against AIX 5.1 bug: Failures are not distinguishable from successful + returns. */ + { + iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); + if (cd_utf8_to_88591 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\342\202\254"; /* EURO SIGN */ + char buf[10]; + ICONV_CONST char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_utf8_to_88591, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 1; + iconv_close (cd_utf8_to_88591); + } + } + /* Test against Solaris 10 bug: Failures are not distinguishable from + successful returns. */ + { + iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646"); + if (cd_ascii_to_88591 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\263"; + char buf[10]; + ICONV_CONST char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_ascii_to_88591, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 2; + iconv_close (cd_ascii_to_88591); + } + } + /* Test against AIX 6.1..7.1 bug: Buffer overrun. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\304"; + static char buf[2] = { (char)0xDE, (char)0xAD }; + ICONV_CONST char *inptr = input; + size_t inbytesleft = 1; + char *outptr = buf; + size_t outbytesleft = 1; + size_t res = iconv (cd_88591_to_utf8, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD) + result |= 4; + iconv_close (cd_88591_to_utf8); + } + } +#if 0 /* This bug could be worked around by the caller. */ + /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; + char buf[50]; + ICONV_CONST char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_88591_to_utf8, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if ((int)res > 0) + result |= 8; + iconv_close (cd_88591_to_utf8); + } + } +#endif + /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is + provided. */ + if (/* Try standardized names. */ + iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1) + /* Try IRIX, OSF/1 names. */ + && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1) + /* Try AIX names. */ + && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1) + /* Try HP-UX names. */ + && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) + result |= 16; + return result; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + am_cv_func_iconv_works=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + test "$am_cv_func_iconv_works" = no || break + done + LIBS="$am_save_LIBS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv_works" >&5 +$as_echo "$am_cv_func_iconv_works" >&6; } + case "$am_cv_func_iconv_works" in + *no) am_func_iconv=no am_cv_lib_iconv=no ;; + *) am_func_iconv=yes ;; + esac + else + am_func_iconv=no am_cv_lib_iconv=no + fi + if test "$am_func_iconv" = yes; then + +$as_echo "#define HAVE_ICONV 1" >>confdefs.h + + fi + if test "$am_cv_lib_iconv" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libiconv" >&5 +$as_echo_n "checking how to link with libiconv... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBICONV" >&5 +$as_echo "$LIBICONV" >&6; } + else + CPPFLAGS="$am_save_CPPFLAGS" + LIBICONV= + LTLIBICONV= + fi + + + + + + + + + + + + use_additional=yes + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + +# Check whether --with-libintl-prefix was given. +if test "${with_libintl_prefix+set}" = set; then : + withval=$with_libintl_prefix; + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + if test "$acl_libdirstem2" != "$acl_libdirstem" \ + && ! test -d "$withval/$acl_libdirstem"; then + additional_libdir="$withval/$acl_libdirstem2" + fi + fi + fi + +fi + + LIBINTL= + LTLIBINTL= + INCINTL= + LIBINTL_PREFIX= + HAVE_LIBINTL= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='intl ' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./+-|ABCDEFGHIJKLMNOPQRSTUVWXYZ____|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIBINTL="${LIBINTL}${LIBINTL:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$value" + else + : + fi + else + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIBINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + if test "$enable_rpath" = no \ + || test "X$found_dir" = "X/usr/$acl_libdirstem" \ + || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" + else + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + if test "$acl_hardcode_direct" = yes; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + haveit= + for x in $LDFLAGS $LIBINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIBINTL="${LIBINTL}${LIBINTL:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" + else + LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_a" + else + LIBINTL="${LIBINTL}${LIBINTL:+ }-L$found_dir -l$name" + fi + fi + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + if test "$name" = 'intl'; then + LIBINTL_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + */$acl_libdirstem2 | */$acl_libdirstem2/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'` + if test "$name" = 'intl'; then + LIBINTL_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INCINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + INCINTL="${INCINTL}${INCINTL:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + if test -n "$found_la"; then + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \ + && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \ + || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIBINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LIBINTL="${LIBINTL}${LIBINTL:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIBINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + LIBINTL="${LIBINTL}${LIBINTL:+ }$dep" + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$dep" + ;; + esac + done + fi + else + LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name" + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBINTL="${LIBINTL}${LIBINTL:+ }$flag" + else + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBINTL="${LIBINTL}${LIBINTL:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + for found_dir in $ltrpathdirs; do + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-R$found_dir" + done + fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU gettext in libintl" >&5 +$as_echo_n "checking for GNU gettext in libintl... " >&6; } +if eval \${$gt_func_gnugettext_libintl+:} false; then : + $as_echo_n "(cached) " >&6 +else + gt_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $INCINTL" + gt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBINTL" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *); + +int +main () +{ + +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$gt_func_gnugettext_libintl=yes" +else + eval "$gt_func_gnugettext_libintl=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" != yes; } && test -n "$LIBICONV"; then + LIBS="$LIBS $LIBICONV" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *); + +int +main () +{ + +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + LIBINTL="$LIBINTL $LIBICONV" + LTLIBINTL="$LTLIBINTL $LTLIBICONV" + eval "$gt_func_gnugettext_libintl=yes" + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + fi + CPPFLAGS="$gt_save_CPPFLAGS" + LIBS="$gt_save_LIBS" +fi +eval ac_res=\$$gt_func_gnugettext_libintl + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + fi + + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" = "yes"; } \ + || { { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; } \ + && test "$PACKAGE" != gettext-runtime \ + && test "$PACKAGE" != gettext-tools; }; then + gt_use_preinstalled_gnugettext=yes + else + LIBINTL= + LTLIBINTL= + INCINTL= + fi + + + + if test -n "$INTL_MACOSX_LIBS"; then + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" + LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" + fi + fi + + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + +$as_echo "#define ENABLE_NLS 1" >>confdefs.h + + else + USE_NLS=no + fi + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use NLS" >&5 +$as_echo_n "checking whether to use NLS... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_NLS" >&5 +$as_echo "$USE_NLS" >&6; } + if test "$USE_NLS" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking where the gettext function comes from" >&5 +$as_echo_n "checking where the gettext function comes from... " >&6; } + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + gt_source="external libintl" + else + gt_source="libc" + fi + else + gt_source="included intl directory" + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_source" >&5 +$as_echo "$gt_source" >&6; } + fi + + if test "$USE_NLS" = "yes"; then + + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libintl" >&5 +$as_echo_n "checking how to link with libintl... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBINTL" >&5 +$as_echo "$LIBINTL" >&6; } + + for element in $INCINTL; do + haveit= + for x in $CPPFLAGS; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" + fi + done + + fi + + +$as_echo "#define HAVE_GETTEXT 1" >>confdefs.h + + +$as_echo "#define HAVE_DCGETTEXT 1" >>confdefs.h + + fi + + POSUB=po + fi + + + + INTLLIBS="$LIBINTL" + + + + + + + + +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.4.6' +macro_revision='2.4.6' + + + + + + + + + + + + + +ltmain=$ac_aux_dir/ltmain.sh + +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case $ECHO in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if ${ac_cv_path_FGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_FGREP" || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if ${lt_cv_path_NM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in dumpbin "link -dump" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if ${lt_cv_nm_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if ${lt_cv_sys_max_cmd_len+:} false; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n "$lt_cv_sys_max_cmd_len"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +$as_echo_n "checking how to convert $build file names to $host format... " >&6; } +if ${lt_cv_to_host_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac + +fi + +to_host_file_cmd=$lt_cv_to_host_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +$as_echo "$lt_cv_to_host_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } +if ${lt_cv_to_tool_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + #assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac + +fi + +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +$as_echo "$lt_cv_to_tool_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if ${lt_cv_ld_reload_flag+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test yes != "$GCC"; then + reload_cmds=false + fi + ;; + darwin*) + if test yes = "$GCC"; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if ${lt_cv_deplibs_check_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + + + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +$as_echo_n "checking how to associate runtime and link libraries... " >&6; } +if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + + + + + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} +: ${AR_FLAGS=cru} + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 +$as_echo_n "checking for archiver @FILE support... " >&6; } +if ${lt_cv_ar_at_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ar_at_file=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 +$as_echo "$lt_cv_ar_at_file" >&6; } + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if ${lt_cv_sys_global_symbol_pipe+:} false; then : + $as_echo_n "(cached) " >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[ABCDEGRST]' + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 +$as_echo_n "checking for sysroot... " >&6; } + +# Check whether --with-sysroot was given. +if test "${with_sysroot+set}" = set; then : + withval=$with_sysroot; +else + with_sysroot=no +fi + + +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 +$as_echo "$with_sysroot" >&6; } + as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 + ;; +esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 +$as_echo "${lt_sysroot:-no}" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 +$as_echo_n "checking for a working dd... " >&6; } +if ${ac_cv_path_lt_DD+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +if test -z "$lt_DD"; then + ac_path_lt_DD_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in dd; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_lt_DD" || continue +if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi + $ac_path_lt_DD_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_lt_DD"; then + : + fi +else + ac_cv_path_lt_DD=$lt_DD +fi + +rm -f conftest.i conftest2.i conftest.out +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 +$as_echo "$ac_cv_path_lt_DD" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 +$as_echo_n "checking how to truncate binary pipes... " >&6; } +if ${lt_cv_truncate_bin+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 +$as_echo "$lt_cv_truncate_bin" >&6; } + + + + + + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then : + enableval=$enable_libtool_lock; +fi + +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if ${lt_cv_cc_needs_belf+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$lt_cv_cc_needs_belf" >&6; } + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. +set dummy ${ac_tool_prefix}mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MANIFEST_TOOL"; then + ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL +if test -n "$MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 +$as_echo "$MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_MANIFEST_TOOL"; then + ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL + # Extract the first word of "mt", so it can be a program name with args. +set dummy mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_MANIFEST_TOOL"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL +if test -n "$ac_ct_MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 +$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_MANIFEST_TOOL" = x; then + MANIFEST_TOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL + fi +else + MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" +fi + +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 +$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } +if ${lt_cv_path_mainfest_tool+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&5 + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 +$as_echo "$lt_cv_path_mainfest_tool" >&6; } +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi + + + + + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_LIPO="lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL="otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if ${lt_cv_apple_cc_single_mod+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&5 + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if ${lt_cv_ld_exported_symbols_list+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if ${lt_cv_ld_force_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 + echo "$RANLIB libconftest.a" >&5 + $RANLIB libconftest.a 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&5 + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[012][,.]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + + + +# Set options +# Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_static=no +fi + + + + + + + + + + + enable_dlopen=no + + + enable_win32_dll=no + + + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + pic_mode=default +fi + + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_fast_install=yes +fi + + + + + + + + + shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[5-9]*,yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 +$as_echo_n "checking which variant of shared library versioning to provide... " >&6; } + +# Check whether --with-aix-soname was given. +if test "${with_aix_soname+set}" = set; then : + withval=$with_aix_soname; case $withval in + aix|svr4|both) + ;; + *) + as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname +else + if ${lt_cv_with_aix_soname+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_with_aix_soname=aix +fi + + with_aix_soname=$lt_cv_with_aix_soname +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 +$as_echo "$with_aix_soname" >&6; } + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if ${lt_cv_objdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +func_cc_basename $compiler +cc_basename=$func_cc_basename_result + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/${ac_tool_prefix}file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac +fi + +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac +fi + +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +lt_save_CC=$CC +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + + + + + + + lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + + + if test yes = "$GCC"; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + lt_prog_compiler_pic='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + if test -n "$lt_prog_compiler_pic"; then + lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + *Sun\ F* | *Sun*Fortran*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + *Intel*\ [CF]*Compiler*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + *Portland\ Group*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic=$lt_prog_compiler_pic +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 +$as_echo "$lt_cv_prog_compiler_pic" >&6; } +lt_prog_compiler_pic=$lt_cv_prog_compiler_pic + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if ${lt_cv_prog_compiler_pic_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test yes = "$lt_cv_prog_compiler_pic_works"; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi + + + + + + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test yes = "$lt_cv_prog_compiler_static_works"; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + +hard_links=nottested +if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test no = "$hard_links"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + esac + + ld_shlibs=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + export_dynamic_flag_spec='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='$wl--export-all-symbols' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + export_dynamic_flag_spec='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + ld_shlibs=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test no = "$ld_shlibs"; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix[4-9]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + hardcode_direct=no + hardcode_direct_absolute=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + export_dynamic_flag_spec='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' $wl-bernotok' + allow_undefined_flag=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi + archive_cmds_need_lc=yes + archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + always_export_symbols=yes + file_list_spec='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, )='true' + enable_shared_with_static_runtimes=yes + exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + old_postinstall_cmds='chmod 644 $oldlib' + postlink_cmds='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + enable_shared_with_static_runtimes=yes + ;; + esac + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + if test yes = "$lt_cv_ld_force_load"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + + else + whole_archive_flag_spec='' + fi + link_all_deplibs=yes + allow_undefined_flag=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + + else + ld_shlibs=no + fi + + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test yes = "$GCC"; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if ${lt_cv_prog_compiler__b+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -b" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test yes = "$lt_cv_prog_compiler__b"; then + archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +fi + + ;; + esac + fi + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 +$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } +if ${lt_cv_irix_exported_symbol+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo (void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_irix_exported_symbol=yes +else + lt_cv_irix_exported_symbol=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 +$as_echo "$lt_cv_irix_exported_symbol" >&6; } + if test yes = "$lt_cv_irix_exported_symbol"; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + link_all_deplibs=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + ld_shlibs=yes + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' + else + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + fi + else + ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + + osf3*) + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='$wl-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='$wl-z,text' + allow_undefined_flag='$wl-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='$wl-R,$libdir' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='$wl-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test no = "$ld_shlibs" && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([A-Za-z]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + + + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[4-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a(lib.so.V)' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[23].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + hardcode_libdir_flag_spec='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Add ABI-specific directories to the system library path. + sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test yes = "$hardcode_automatic"; then + + # We can hardcode non-existent directories. + if test no != "$hardcode_direct" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && + test no != "$hardcode_minus_L"; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test relink = "$hardcode_action" || + test yes = "$inherit_rpath"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else + + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : + lt_cv_dlopen=shl_load +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + lt_cv_dlopen=dlopen +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if ${ac_cv_lib_svld_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if ${ac_cv_lib_dld_dld_link+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : + lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test yes = "$cross_compiling"; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$lt_cv_dlopen_self" >&6; } + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self_static+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test yes = "$cross_compiling"; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +fi + + + + + + + + + + + + + # Report what library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[4-9]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC=$lt_save_CC + + + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + +if test "x$CC" != xcc; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5 +$as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5 +$as_echo_n "checking whether cc understands -c and -o together... " >&6; } +fi +set dummy $CC; ac_cc=`$as_echo "$2" | + sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` +if eval \${ac_cv_prog_cc_${ac_cc}_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +# Make sure it works both with $CC and with simple cc. +# We do the test twice because some compilers refuse to overwrite an +# existing .o file with -o, though they will create one. +ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5' +rm -f conftest2.* +if { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && + test -f conftest2.$ac_objext && { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; +then + eval ac_cv_prog_cc_${ac_cc}_c_o=yes + if test "x$CC" != xcc; then + # Test first that cc exists at all. + if { ac_try='cc -c conftest.$ac_ext >&5' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5' + rm -f conftest2.* + if { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && + test -f conftest2.$ac_objext && { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; + then + # cc works too. + : + else + # cc exists but doesn't like -o. + eval ac_cv_prog_cc_${ac_cc}_c_o=no + fi + fi + fi +else + eval ac_cv_prog_cc_${ac_cc}_c_o=no +fi +rm -f core conftest* + +fi +if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +$as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.21 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi + +# Sets GLIB_GENMARSHAL and GLIB_MKENUMS +# Check whether --enable-glibtest was given. +if test "${enable_glibtest+set}" = set; then : + enableval=$enable_glibtest; +else + enable_glibtest=yes +fi + + + pkg_config_args=glib-2.0 + for module in . + do + case "$module" in + gmodule) + pkg_config_args="$pkg_config_args gmodule-2.0" + ;; + gmodule-no-export) + pkg_config_args="$pkg_config_args gmodule-no-export-2.0" + ;; + gobject) + pkg_config_args="$pkg_config_args gobject-2.0" + ;; + gthread) + pkg_config_args="$pkg_config_args gthread-2.0" + ;; + gio*) + pkg_config_args="$pkg_config_args $module-2.0" + ;; + esac + done + + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.16 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi + + no_glib="" + + if test "x$PKG_CONFIG" = x ; then + no_glib=yes + PKG_CONFIG=no + fi + + min_glib_version=2.49.0 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLIB - version >= $min_glib_version" >&5 +$as_echo_n "checking for GLIB - version >= $min_glib_version... " >&6; } + + if test x$PKG_CONFIG != xno ; then + ## don't try to run the test against uninstalled libtool libs + if $PKG_CONFIG --uninstalled $pkg_config_args; then + echo "Will use uninstalled version of GLib found in PKG_CONFIG_PATH" + enable_glibtest=no + fi + + if $PKG_CONFIG --atleast-version $min_glib_version $pkg_config_args; then + : + else + no_glib=yes + fi + fi + + if test x"$no_glib" = x ; then + GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0` + GOBJECT_QUERY=`$PKG_CONFIG --variable=gobject_query glib-2.0` + GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0` + GLIB_COMPILE_RESOURCES=`$PKG_CONFIG --variable=glib_compile_resources gio-2.0` + + GLIB_CFLAGS=`$PKG_CONFIG --cflags $pkg_config_args` + GLIB_LIBS=`$PKG_CONFIG --libs $pkg_config_args` + glib_config_major_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'` + glib_config_minor_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'` + glib_config_micro_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'` + if test "x$enable_glibtest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GLIB_CFLAGS" + LIBS="$GLIB_LIBS $LIBS" + rm -f conf.glibtest + if test "$cross_compiling" = yes; then : + echo $ac_n "cross compiling; assumed OK... $ac_c" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +#include + +int +main () +{ + unsigned int major, minor, micro; + + fclose (fopen ("conf.glibtest", "w")); + + if (sscanf("$min_glib_version", "%u.%u.%u", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_glib_version"); + exit(1); + } + + if ((glib_major_version != $glib_config_major_version) || + (glib_minor_version != $glib_config_minor_version) || + (glib_micro_version != $glib_config_micro_version)) + { + printf("\n*** 'pkg-config --modversion glib-2.0' returned %d.%d.%d, but GLIB (%d.%d.%d)\n", + $glib_config_major_version, $glib_config_minor_version, $glib_config_micro_version, + glib_major_version, glib_minor_version, glib_micro_version); + printf ("*** was found! If pkg-config was correct, then it is best\n"); + printf ("*** to remove the old version of GLib. You may also be able to fix the error\n"); + printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); + printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); + printf("*** required on your system.\n"); + printf("*** If pkg-config was wrong, set the environment variable PKG_CONFIG_PATH\n"); + printf("*** to point to the correct configuration files\n"); + } + else if ((glib_major_version != GLIB_MAJOR_VERSION) || + (glib_minor_version != GLIB_MINOR_VERSION) || + (glib_micro_version != GLIB_MICRO_VERSION)) + { + printf("*** GLIB header files (version %d.%d.%d) do not match\n", + GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION); + printf("*** library (version %d.%d.%d)\n", + glib_major_version, glib_minor_version, glib_micro_version); + } + else + { + if ((glib_major_version > major) || + ((glib_major_version == major) && (glib_minor_version > minor)) || + ((glib_major_version == major) && (glib_minor_version == minor) && (glib_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** An old version of GLIB (%u.%u.%u) was found.\n", + glib_major_version, glib_minor_version, glib_micro_version); + printf("*** You need a version of GLIB newer than %u.%u.%u. The latest version of\n", + major, minor, micro); + printf("*** GLIB is always available from ftp://ftp.gtk.org.\n"); + printf("***\n"); + printf("*** If you have already installed a sufficiently new version, this error\n"); + printf("*** probably means that the wrong copy of the pkg-config shell script is\n"); + printf("*** being found. The easiest way to fix this is to remove the old version\n"); + printf("*** of GLIB, but you can also set the PKG_CONFIG environment to point to the\n"); + printf("*** correct copy of pkg-config. (In this case, you will have to\n"); + printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); + printf("*** so that the correct libraries are found at run-time))\n"); + } + } + return 1; +} + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + no_glib=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_glib" = x ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (version $glib_config_major_version.$glib_config_minor_version.$glib_config_micro_version)" >&5 +$as_echo "yes (version $glib_config_major_version.$glib_config_minor_version.$glib_config_micro_version)" >&6; } + : + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + if test "$PKG_CONFIG" = "no" ; then + echo "*** A new enough version of pkg-config was not found." + echo "*** See http://www.freedesktop.org/software/pkgconfig/" + else + if test -f conf.glibtest ; then + : + else + echo "*** Could not run GLIB test program, checking why..." + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GLIB_CFLAGS" + LIBS="$LIBS $GLIB_LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include + +int +main () +{ + return ((glib_major_version) || (glib_minor_version) || (glib_micro_version)); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding GLIB or finding the wrong" + echo "*** version of GLIB. If it is not finding GLIB, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" +else + echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means GLIB is incorrectly installed." +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + GLIB_CFLAGS="" + GLIB_LIBS="" + GLIB_GENMARSHAL="" + GOBJECT_QUERY="" + GLIB_MKENUMS="" + GLIB_COMPILE_RESOURCES="" + : + fi + + + + + + + rm -f conf.glibtest + + +CANBERRA_GTK=libcanberra-gtk3 +CANBERRA_GTK_VERSION=0.26 + +LIBWACOM_VERSION=0.13 + +MUTTER_PC_MODULES=" + gtk+-3.0 >= 3.19.8 + gio-unix-2.0 >= 2.35.1 + pango >= 1.2.0 + cairo >= 1.10.0 + gsettings-desktop-schemas >= 3.21.4 + json-glib-1.0 + upower-glib >= 0.99.0 + gnome-desktop-3.0 + xcomposite >= 0.2 + xcursor + xdamage + xext + xfixes + xi >= 1.6.0 + xkbfile + xkeyboard-config + xkbcommon >= 0.4.3 + xkbcommon-x11 + xrender + x11-xcb + xcb-randr + xcb-res +" + + + + # Check whether --enable-schemas-compile was given. +if test "${enable_schemas_compile+set}" = set; then : + enableval=$enable_schemas_compile; case ${enableval} in + yes) GSETTINGS_DISABLE_SCHEMAS_COMPILE="" ;; + no) GSETTINGS_DISABLE_SCHEMAS_COMPILE="1" ;; + *) as_fn_error $? "bad value ${enableval} for --enable-schemas-compile" "$LINENO" 5 ;; + esac +fi + + + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.16 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi + gsettingsschemadir=${datadir}/glib-2.0/schemas + + if test x$cross_compiling != xyes; then + GLIB_COMPILE_SCHEMAS=`$PKG_CONFIG --variable glib_compile_schemas gio-2.0` + else + # Extract the first word of "glib-compile-schemas", so it can be a program name with args. +set dummy glib-compile-schemas; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GLIB_COMPILE_SCHEMAS+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GLIB_COMPILE_SCHEMAS in + [\\/]* | ?:[\\/]*) + ac_cv_path_GLIB_COMPILE_SCHEMAS="$GLIB_COMPILE_SCHEMAS" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GLIB_COMPILE_SCHEMAS="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +GLIB_COMPILE_SCHEMAS=$ac_cv_path_GLIB_COMPILE_SCHEMAS +if test -n "$GLIB_COMPILE_SCHEMAS"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GLIB_COMPILE_SCHEMAS" >&5 +$as_echo "$GLIB_COMPILE_SCHEMAS" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi + + if test "x$GLIB_COMPILE_SCHEMAS" = "x"; then + as_fn_error $? "glib-compile-schemas not found." "$LINENO" 5 + else + : + fi + + GSETTINGS_RULES=' +.PHONY : uninstall-gsettings-schemas install-gsettings-schemas clean-gsettings-schemas + +mostlyclean-am: clean-gsettings-schemas + +gsettings__enum_file = $(addsuffix .enums.xml,$(gsettings_ENUM_NAMESPACE)) + +%.gschema.valid: %.gschema.xml $(gsettings__enum_file) + $(AM_V_GEN) $(GLIB_COMPILE_SCHEMAS) --strict --dry-run $(addprefix --schema-file=,$(gsettings__enum_file)) --schema-file=$< && mkdir -p $(@D) && touch $@ + +all-am: $(gsettings_SCHEMAS:.xml=.valid) +uninstall-am: uninstall-gsettings-schemas +install-data-am: install-gsettings-schemas + +.SECONDARY: $(gsettings_SCHEMAS) + +install-gsettings-schemas: $(gsettings_SCHEMAS) $(gsettings__enum_file) + @$(NORMAL_INSTALL) + if test -n "$^"; then \ + test -z "$(gsettingsschemadir)" || $(MKDIR_P) "$(DESTDIR)$(gsettingsschemadir)"; \ + $(INSTALL_DATA) $^ "$(DESTDIR)$(gsettingsschemadir)"; \ + test -n "$(GSETTINGS_DISABLE_SCHEMAS_COMPILE)$(DESTDIR)" || $(GLIB_COMPILE_SCHEMAS) $(gsettingsschemadir); \ + fi + +uninstall-gsettings-schemas: + @$(NORMAL_UNINSTALL) + @list='\''$(gsettings_SCHEMAS) $(gsettings__enum_file)'\''; test -n "$(gsettingsschemadir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e '\''s|^.*/||'\''`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '\''$(DESTDIR)$(gsettingsschemadir)'\'' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(gsettingsschemadir)" && rm -f $$files + test -n "$(GSETTINGS_DISABLE_SCHEMAS_COMPILE)$(DESTDIR)" || $(GLIB_COMPILE_SCHEMAS) $(gsettingsschemadir) + +clean-gsettings-schemas: + rm -f $(gsettings_SCHEMAS:.xml=.valid) $(gsettings__enum_file) + +ifdef gsettings_ENUM_NAMESPACE +$(gsettings__enum_file): $(gsettings_ENUM_FILES) + $(AM_V_GEN) glib-mkenums --comments '\'''\'' --fhead "" --vhead " <@type@ id='\''$(gsettings_ENUM_NAMESPACE).@EnumName@'\''>" --vprod " " --vtail " " --ftail "" $^ > $@.tmp && mv $@.tmp $@ +endif +' + + + + + + + +# Check whether --enable-verbose-mode was given. +if test "${enable_verbose_mode+set}" = set; then : + enableval=$enable_verbose_mode; +else + enable_verbose_mode=yes +fi + + +if test x$enable_verbose_mode = xyes; then + +$as_echo "#define WITH_VERBOSE_MODE 1" >>confdefs.h + +fi + +# Check whether --enable-sm was given. +if test "${enable_sm+set}" = set; then : + enableval=$enable_sm; +else + enable_sm=auto +fi + + +# Check whether --enable-startup-notification was given. +if test "${enable_startup_notification+set}" = set; then : + enableval=$enable_startup_notification; +else + enable_startup_notification=auto +fi + + + +# Check whether --with-libcanberra was given. +if test "${with_libcanberra+set}" = set; then : + withval=$with_libcanberra; +else + with_libcanberra=auto +fi + + + +# Check whether --with-libwacom was given. +if test "${with_libwacom+set}" = set; then : + withval=$with_libwacom; +else + with_libwacom=auto +fi + + + +# Check whether --with-gudev was given. +if test "${with_gudev+set}" = set; then : + withval=$with_gudev; +else + with_gudev=auto +fi + + + +# Check whether --with-xwayland-path was given. +if test "${with_xwayland_path+set}" = set; then : + withval=$with_xwayland_path; XWAYLAND_PATH="$withval" +else + XWAYLAND_PATH="$bindir/Xwayland" +fi + + +# Check whether --enable-installed_tests was given. +if test "${enable_installed_tests+set}" = set; then : + enableval=$enable_installed_tests; +else + enable_installed_tests=no +fi + + if test x$enable_installed_tests = xyes; then + BUILDOPT_INSTALL_TESTS_TRUE= + BUILDOPT_INSTALL_TESTS_FALSE='#' +else + BUILDOPT_INSTALL_TESTS_TRUE='#' + BUILDOPT_INSTALL_TESTS_FALSE= +fi + + +## here we get the flags we'll actually use + +# Unconditionally use this dir to avoid a circular dep with gnomecc +GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings" + + +STARTUP_NOTIFICATION_VERSION=0.7 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking Startup notification library >= $STARTUP_NOTIFICATION_VERSION" >&5 +$as_echo_n "checking Startup notification library >= $STARTUP_NOTIFICATION_VERSION... " >&6; } +if $PKG_CONFIG --atleast-version $STARTUP_NOTIFICATION_VERSION libstartup-notification-1.0; then + have_startup_notification=yes +else + have_startup_notification=no +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_startup_notification" >&5 +$as_echo "$have_startup_notification" >&6; } + +if test x$enable_startup_notification = xyes; then + have_startup_notification=yes + echo "startup-notification support forced on" +elif test x$enable_startup_notification = xauto; then + true +else + have_startup_notification=no +fi + +if test x$have_startup_notification = xyes; then + echo "Building with libstartup-notification" + MUTTER_PC_MODULES="$MUTTER_PC_MODULES libstartup-notification-1.0 >= $STARTUP_NOTIFICATION_VERSION" + +$as_echo "#define HAVE_STARTUP_NOTIFICATION /**/" >>confdefs.h + +else + echo "Building without libstartup-notification" +fi + +have_libcanberra=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking libcanberra-gtk" >&5 +$as_echo_n "checking libcanberra-gtk... " >&6; } +if test x$with_libcanberra = xno ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 +$as_echo "disabled" >&6; } +else + if $PKG_CONFIG --exists $CANBERRA_GTK '>=' $CANBERRA_GTK_VERSION; then + have_libcanberra=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + MUTTER_PC_MODULES="$MUTTER_PC_MODULES $CANBERRA_GTK" + +$as_echo "#define HAVE_LIBCANBERRA 1" >>confdefs.h + + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + if test x$with_libcanberra = xyes ; then + as_fn_error $? "libcanberra forced and libcanberra-gtk was not found" "$LINENO" 5 + fi + fi +fi + +have_libwacom=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking libwacom" >&5 +$as_echo_n "checking libwacom... " >&6; } +if test x$with_libwacom = xno ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 +$as_echo "disabled" >&6; } +else + if $PKG_CONFIG --exists libwacom '>=' $LIBWACOM_VERSION; then + have_libwacom=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + MUTTER_PC_MODULES="$MUTTER_PC_MODULES libwacom" + +$as_echo "#define HAVE_LIBWACOM 1" >>confdefs.h + + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + if test x$with_libwacom = xyes ; then + as_fn_error $? "libwacom forced but not found" "$LINENO" 5 + fi + fi +fi + +have_gudev=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking gudev" >&5 +$as_echo_n "checking gudev... " >&6; } +if test x$with_gudev = xno ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 +$as_echo "disabled" >&6; } +else + if $PKG_CONFIG --exists gudev-1.0; then + have_gudev=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + MUTTER_PC_MODULES="$MUTTER_PC_MODULES gudev-1.0" + +$as_echo "#define HAVE_LIBGUDEV 1" >>confdefs.h + + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + if test x$with_gudev = xyes ; then + as_fn_error $? "gudev forced but not found" "$LINENO" 5 + fi + fi +fi + +INTROSPECTION_VERSION=0.9.5 + + + + # Check whether --enable-introspection was given. +if test "${enable_introspection+set}" = set; then : + enableval=$enable_introspection; +else + enable_introspection=auto +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gobject-introspection" >&5 +$as_echo_n "checking for gobject-introspection... " >&6; } + + case $enable_introspection in #( + no) : + found_introspection="no (disabled, use --enable-introspection to enable)" + ;; #( + yes) : + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-introspection-1.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gobject-introspection-1.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + : +else + as_fn_error $? "gobject-introspection-1.0 is not installed" "$LINENO" 5 +fi + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-introspection-1.0 >= \$INTROSPECTION_VERSION\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gobject-introspection-1.0 >= $INTROSPECTION_VERSION") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + found_introspection=yes +else + as_fn_error $? "You need to have gobject-introspection >= $INTROSPECTION_VERSION installed to build mutter" "$LINENO" 5 +fi + ;; #( + auto) : + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-introspection-1.0 >= \$INTROSPECTION_VERSION\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gobject-introspection-1.0 >= $INTROSPECTION_VERSION") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + found_introspection=yes +else + found_introspection=no +fi + enable_introspection=$found_introspection + ;; #( + *) : + as_fn_error $? "invalid argument passed to --enable-introspection, should be one of [no/auto/yes]" "$LINENO" 5 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $found_introspection" >&5 +$as_echo "$found_introspection" >&6; } + + INTROSPECTION_SCANNER= + INTROSPECTION_COMPILER= + INTROSPECTION_GENERATE= + INTROSPECTION_GIRDIR= + INTROSPECTION_TYPELIBDIR= + if test "x$found_introspection" = "xyes"; then + INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0` + INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0` + INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0` + INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0` + INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)" + INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0` + INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0` + INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection + fi + + + + + + + + + + if test "x$found_introspection" = "xyes"; then + HAVE_INTROSPECTION_TRUE= + HAVE_INTROSPECTION_FALSE='#' +else + HAVE_INTROSPECTION_TRUE='#' + HAVE_INTROSPECTION_FALSE= +fi + + + + +if test x$found_introspection != xno; then + +$as_echo "#define HAVE_INTROSPECTION 1" >>confdefs.h + + MUTTER_PC_MODULES="$MUTTER_PC_MODULES gobject-introspection-1.0" + # Since we don't make any guarantees about stability and we don't support + # parallel install, there's no real reason to change directories, filenames, + # etc. as we change the Mutter tarball version. Note that this must match + # api_version in src/Makefile.am + META_GIR=Meta_3_0_gir + # META_GIR=[Meta_]mutter_major_version[_]mutter_minor_version[_gir] + +fi + + + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for MUTTER" >&5 +$as_echo_n "checking for MUTTER... " >&6; } + +if test -n "$MUTTER_CFLAGS"; then + pkg_cv_MUTTER_CFLAGS="$MUTTER_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$MUTTER_PC_MODULES\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$MUTTER_PC_MODULES") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_MUTTER_CFLAGS=`$PKG_CONFIG --cflags "$MUTTER_PC_MODULES" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$MUTTER_LIBS"; then + pkg_cv_MUTTER_LIBS="$MUTTER_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$MUTTER_PC_MODULES\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$MUTTER_PC_MODULES") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_MUTTER_LIBS=`$PKG_CONFIG --libs "$MUTTER_PC_MODULES" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + MUTTER_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$MUTTER_PC_MODULES" 2>&1` + else + MUTTER_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$MUTTER_PC_MODULES" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$MUTTER_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements ($MUTTER_PC_MODULES) were not met: + +$MUTTER_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables MUTTER_CFLAGS +and MUTTER_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables MUTTER_CFLAGS +and MUTTER_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + MUTTER_CFLAGS=$pkg_cv_MUTTER_CFLAGS + MUTTER_LIBS=$pkg_cv_MUTTER_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + +MUTTER_NATIVE_BACKEND_MODULES="libdrm libsystemd libinput >= 1.4 gudev-1.0 gbm >= 10.3" + +# Check whether --enable-native-backend was given. +if test "${enable_native_backend+set}" = set; then : + enableval=$enable_native_backend; +else + enable_native_backend=auto + +fi + +have_native_backend="no" +if test "$enable_native_backend" = "yes"; then : + have_native_backend=yes +elif test "$enable_native_backend" = "auto"; then : + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$MUTTER_NATIVE_BACKEND_MODULES\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$MUTTER_NATIVE_BACKEND_MODULES") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + have_native_backend=yes +fi +fi + +if test "$have_native_backend" = "yes"; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for MUTTER_NATIVE_BACKEND" >&5 +$as_echo_n "checking for MUTTER_NATIVE_BACKEND... " >&6; } + +if test -n "$MUTTER_NATIVE_BACKEND_CFLAGS"; then + pkg_cv_MUTTER_NATIVE_BACKEND_CFLAGS="$MUTTER_NATIVE_BACKEND_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$MUTTER_NATIVE_BACKEND_MODULES\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$MUTTER_NATIVE_BACKEND_MODULES") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_MUTTER_NATIVE_BACKEND_CFLAGS=`$PKG_CONFIG --cflags "$MUTTER_NATIVE_BACKEND_MODULES" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$MUTTER_NATIVE_BACKEND_LIBS"; then + pkg_cv_MUTTER_NATIVE_BACKEND_LIBS="$MUTTER_NATIVE_BACKEND_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$MUTTER_NATIVE_BACKEND_MODULES\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$MUTTER_NATIVE_BACKEND_MODULES") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_MUTTER_NATIVE_BACKEND_LIBS=`$PKG_CONFIG --libs "$MUTTER_NATIVE_BACKEND_MODULES" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + MUTTER_NATIVE_BACKEND_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$MUTTER_NATIVE_BACKEND_MODULES" 2>&1` + else + MUTTER_NATIVE_BACKEND_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$MUTTER_NATIVE_BACKEND_MODULES" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$MUTTER_NATIVE_BACKEND_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements ($MUTTER_NATIVE_BACKEND_MODULES) were not met: + +$MUTTER_NATIVE_BACKEND_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables MUTTER_NATIVE_BACKEND_CFLAGS +and MUTTER_NATIVE_BACKEND_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables MUTTER_NATIVE_BACKEND_CFLAGS +and MUTTER_NATIVE_BACKEND_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + MUTTER_NATIVE_BACKEND_CFLAGS=$pkg_cv_MUTTER_NATIVE_BACKEND_CFLAGS + MUTTER_NATIVE_BACKEND_LIBS=$pkg_cv_MUTTER_NATIVE_BACKEND_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + +$as_echo "#define HAVE_NATIVE_BACKEND 1" >>confdefs.h + + +fi + if test "$have_native_backend" = "yes"; then + HAVE_NATIVE_BACKEND_TRUE= + HAVE_NATIVE_BACKEND_FALSE='#' +else + HAVE_NATIVE_BACKEND_TRUE='#' + HAVE_NATIVE_BACKEND_FALSE= +fi + + +MUTTER_WAYLAND_MODULES="wayland-server >= 1.6.90" + +# Check whether --enable-wayland was given. +if test "${enable_wayland+set}" = set; then : + enableval=$enable_wayland; +else + enable_wayland=auto + +fi + +if test "$enable_wayland" = "yes"; then : + have_wayland=yes +elif test "$enable_wayland" = "auto"; then : + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$MUTTER_WAYLAND_MODULES\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$MUTTER_WAYLAND_MODULES") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + have_wayland=yes +fi +fi + +if test "$have_wayland" = "yes"; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for MUTTER_WAYLAND" >&5 +$as_echo_n "checking for MUTTER_WAYLAND... " >&6; } + +if test -n "$MUTTER_WAYLAND_CFLAGS"; then + pkg_cv_MUTTER_WAYLAND_CFLAGS="$MUTTER_WAYLAND_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$MUTTER_WAYLAND_MODULES\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$MUTTER_WAYLAND_MODULES") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_MUTTER_WAYLAND_CFLAGS=`$PKG_CONFIG --cflags "$MUTTER_WAYLAND_MODULES" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$MUTTER_WAYLAND_LIBS"; then + pkg_cv_MUTTER_WAYLAND_LIBS="$MUTTER_WAYLAND_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$MUTTER_WAYLAND_MODULES\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$MUTTER_WAYLAND_MODULES") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_MUTTER_WAYLAND_LIBS=`$PKG_CONFIG --libs "$MUTTER_WAYLAND_MODULES" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + MUTTER_WAYLAND_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$MUTTER_WAYLAND_MODULES" 2>&1` + else + MUTTER_WAYLAND_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$MUTTER_WAYLAND_MODULES" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$MUTTER_WAYLAND_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements ($MUTTER_WAYLAND_MODULES) were not met: + +$MUTTER_WAYLAND_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables MUTTER_WAYLAND_CFLAGS +and MUTTER_WAYLAND_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables MUTTER_WAYLAND_CFLAGS +and MUTTER_WAYLAND_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + MUTTER_WAYLAND_CFLAGS=$pkg_cv_MUTTER_WAYLAND_CFLAGS + MUTTER_WAYLAND_LIBS=$pkg_cv_MUTTER_WAYLAND_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + # Extract the first word of "wayland-scanner", so it can be a program name with args. +set dummy wayland-scanner; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_WAYLAND_SCANNER+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $WAYLAND_SCANNER in + [\\/]* | ?:[\\/]*) + ac_cv_path_WAYLAND_SCANNER="$WAYLAND_SCANNER" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_WAYLAND_SCANNER="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_WAYLAND_SCANNER" && ac_cv_path_WAYLAND_SCANNER="no" + ;; +esac +fi +WAYLAND_SCANNER=$ac_cv_path_WAYLAND_SCANNER +if test -n "$WAYLAND_SCANNER"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WAYLAND_SCANNER" >&5 +$as_echo "$WAYLAND_SCANNER" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test $WAYLAND_SCANNER = "no"; then : + as_fn_error $? "Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols" "$LINENO" 5 +fi + + +$as_echo "#define HAVE_WAYLAND 1" >>confdefs.h + + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for WAYLAND_PROTOCOLS" >&5 +$as_echo_n "checking for WAYLAND_PROTOCOLS... " >&6; } + +if test -n "$WAYLAND_PROTOCOLS_CFLAGS"; then + pkg_cv_WAYLAND_PROTOCOLS_CFLAGS="$WAYLAND_PROTOCOLS_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"wayland-protocols >= 1.7\""; } >&5 + ($PKG_CONFIG --exists --print-errors "wayland-protocols >= 1.7") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_WAYLAND_PROTOCOLS_CFLAGS=`$PKG_CONFIG --cflags "wayland-protocols >= 1.7" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$WAYLAND_PROTOCOLS_LIBS"; then + pkg_cv_WAYLAND_PROTOCOLS_LIBS="$WAYLAND_PROTOCOLS_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"wayland-protocols >= 1.7\""; } >&5 + ($PKG_CONFIG --exists --print-errors "wayland-protocols >= 1.7") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_WAYLAND_PROTOCOLS_LIBS=`$PKG_CONFIG --libs "wayland-protocols >= 1.7" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + WAYLAND_PROTOCOLS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "wayland-protocols >= 1.7" 2>&1` + else + WAYLAND_PROTOCOLS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "wayland-protocols >= 1.7" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$WAYLAND_PROTOCOLS_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (wayland-protocols >= 1.7) were not met: + +$WAYLAND_PROTOCOLS_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables WAYLAND_PROTOCOLS_CFLAGS +and WAYLAND_PROTOCOLS_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables WAYLAND_PROTOCOLS_CFLAGS +and WAYLAND_PROTOCOLS_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + WAYLAND_PROTOCOLS_CFLAGS=$pkg_cv_WAYLAND_PROTOCOLS_CFLAGS + WAYLAND_PROTOCOLS_LIBS=$pkg_cv_WAYLAND_PROTOCOLS_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_wayland_protocols_pkgdatadir=`$PKG_CONFIG --variable=pkgdatadir wayland-protocols` +fi + WAYLAND_PROTOCOLS_DATADIR=$ac_wayland_protocols_pkgdatadir + + +fi + if test "$have_wayland" = "yes"; then + HAVE_WAYLAND_TRUE= + HAVE_WAYLAND_FALSE='#' +else + HAVE_WAYLAND_TRUE='#' + HAVE_WAYLAND_FALSE= +fi + + +if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"xi >= 1.6.99.1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "xi >= 1.6.99.1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + +$as_echo "#define HAVE_XI23 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for X" >&5 +$as_echo_n "checking for X... " >&6; } + + +# Check whether --with-x was given. +if test "${with_x+set}" = set; then : + withval=$with_x; +fi + +# $have_x is `yes', `no', `disabled', or empty when we do not yet know. +if test "x$with_x" = xno; then + # The user explicitly disabled X. + have_x=disabled +else + case $x_includes,$x_libraries in #( + *\'*) as_fn_error $? "cannot use X directory names containing '" "$LINENO" 5;; #( + *,NONE | NONE,*) if ${ac_cv_have_x+:} false; then : + $as_echo_n "(cached) " >&6 +else + # One or both of the vars are not set, and there is no cached value. +ac_x_includes=no ac_x_libraries=no +rm -f -r conftest.dir +if mkdir conftest.dir; then + cd conftest.dir + cat >Imakefile <<'_ACEOF' +incroot: + @echo incroot='${INCROOT}' +usrlibdir: + @echo usrlibdir='${USRLIBDIR}' +libdir: + @echo libdir='${LIBDIR}' +_ACEOF + if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then + # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. + for ac_var in incroot usrlibdir libdir; do + eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`" + done + # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. + for ac_extension in a so sl dylib la dll; do + if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" && + test -f "$ac_im_libdir/libX11.$ac_extension"; then + ac_im_usrlibdir=$ac_im_libdir; break + fi + done + # Screen out bogus values from the imake configuration. They are + # bogus both because they are the default anyway, and because + # using them would break gcc on systems where it needs fixed includes. + case $ac_im_incroot in + /usr/include) ac_x_includes= ;; + *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; + esac + case $ac_im_usrlibdir in + /usr/lib | /usr/lib64 | /lib | /lib64) ;; + *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; + esac + fi + cd .. + rm -f -r conftest.dir +fi + +# Standard set of common directories for X headers. +# Check X11 before X11Rn because it is often a symlink to the current release. +ac_x_header_dirs=' +/usr/X11/include +/usr/X11R7/include +/usr/X11R6/include +/usr/X11R5/include +/usr/X11R4/include + +/usr/include/X11 +/usr/include/X11R7 +/usr/include/X11R6 +/usr/include/X11R5 +/usr/include/X11R4 + +/usr/local/X11/include +/usr/local/X11R7/include +/usr/local/X11R6/include +/usr/local/X11R5/include +/usr/local/X11R4/include + +/usr/local/include/X11 +/usr/local/include/X11R7 +/usr/local/include/X11R6 +/usr/local/include/X11R5 +/usr/local/include/X11R4 + +/usr/X386/include +/usr/x386/include +/usr/XFree86/include/X11 + +/usr/include +/usr/local/include +/usr/unsupported/include +/usr/athena/include +/usr/local/x11r5/include +/usr/lpp/Xamples/include + +/usr/openwin/include +/usr/openwin/share/include' + +if test "$ac_x_includes" = no; then + # Guess where to find include files, by looking for Xlib.h. + # First, try using that file with no special directory specified. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # We can compile using X headers with no special include directory. +ac_x_includes= +else + for ac_dir in $ac_x_header_dirs; do + if test -r "$ac_dir/X11/Xlib.h"; then + ac_x_includes=$ac_dir + break + fi +done +fi +rm -f conftest.err conftest.i conftest.$ac_ext +fi # $ac_x_includes = no + +if test "$ac_x_libraries" = no; then + # Check for the libraries. + # See if we find them without any special options. + # Don't add to $LIBS permanently. + ac_save_LIBS=$LIBS + LIBS="-lX11 $LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +XrmInitialize () + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + LIBS=$ac_save_LIBS +# We can link X programs with no special library path. +ac_x_libraries= +else + LIBS=$ac_save_LIBS +for ac_dir in `$as_echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g` +do + # Don't even attempt the hair of trying to link an X program! + for ac_extension in a so sl dylib la dll; do + if test -r "$ac_dir/libX11.$ac_extension"; then + ac_x_libraries=$ac_dir + break 2 + fi + done +done +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi # $ac_x_libraries = no + +case $ac_x_includes,$ac_x_libraries in #( + no,* | *,no | *\'*) + # Didn't find X, or a directory has "'" in its name. + ac_cv_have_x="have_x=no";; #( + *) + # Record where we found X for the cache. + ac_cv_have_x="have_x=yes\ + ac_x_includes='$ac_x_includes'\ + ac_x_libraries='$ac_x_libraries'" +esac +fi +;; #( + *) have_x=yes;; + esac + eval "$ac_cv_have_x" +fi # $with_x != no + +if test "$have_x" != yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_x" >&5 +$as_echo "$have_x" >&6; } + no_x=yes +else + # If each of the values was on the command line, it overrides each guess. + test "x$x_includes" = xNONE && x_includes=$ac_x_includes + test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries + # Update the cache value to reflect the command line values. + ac_cv_have_x="have_x=yes\ + ac_x_includes='$x_includes'\ + ac_x_libraries='$x_libraries'" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: libraries $x_libraries, headers $x_includes" >&5 +$as_echo "libraries $x_libraries, headers $x_includes" >&6; } +fi + +if test "$no_x" = yes; then + # Not all programs may use this symbol, but it does not hurt to define it. + +$as_echo "#define X_DISPLAY_MISSING 1" >>confdefs.h + + X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS= +else + if test -n "$x_includes"; then + X_CFLAGS="$X_CFLAGS -I$x_includes" + fi + + # It would also be nice to do this for all -L options, not just this one. + if test -n "$x_libraries"; then + X_LIBS="$X_LIBS -L$x_libraries" + # For Solaris; some versions of Sun CC require a space after -R and + # others require no space. Words are not sufficient . . . . + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -R must be followed by a space" >&5 +$as_echo_n "checking whether -R must be followed by a space... " >&6; } + ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries" + ac_xsave_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + X_LIBS="$X_LIBS -R$x_libraries" +else + LIBS="$ac_xsave_LIBS -R $x_libraries" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + X_LIBS="$X_LIBS -R $x_libraries" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: neither works" >&5 +$as_echo "neither works" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_c_werror_flag=$ac_xsave_c_werror_flag + LIBS=$ac_xsave_LIBS + fi + + # Check for system-dependent libraries X programs must link with. + # Do this before checking for the system-independent R6 libraries + # (-lICE), since we may need -lsocket or whatever for X linking. + + if test "$ISC" = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet" + else + # Martyn Johnson says this is needed for Ultrix, if the X + # libraries were built with DECnet support. And Karl Berry says + # the Alpha needs dnet_stub (dnet does not exist). + ac_xsave_LIBS="$LIBS"; LIBS="$LIBS $X_LIBS -lX11" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XOpenDisplay (); +int +main () +{ +return XOpenDisplay (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet" >&5 +$as_echo_n "checking for dnet_ntoa in -ldnet... " >&6; } +if ${ac_cv_lib_dnet_dnet_ntoa+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldnet $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dnet_ntoa (); +int +main () +{ +return dnet_ntoa (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dnet_dnet_ntoa=yes +else + ac_cv_lib_dnet_dnet_ntoa=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_dnet_ntoa" >&5 +$as_echo "$ac_cv_lib_dnet_dnet_ntoa" >&6; } +if test "x$ac_cv_lib_dnet_dnet_ntoa" = xyes; then : + X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet" +fi + + if test $ac_cv_lib_dnet_dnet_ntoa = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet_stub" >&5 +$as_echo_n "checking for dnet_ntoa in -ldnet_stub... " >&6; } +if ${ac_cv_lib_dnet_stub_dnet_ntoa+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldnet_stub $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dnet_ntoa (); +int +main () +{ +return dnet_ntoa (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dnet_stub_dnet_ntoa=yes +else + ac_cv_lib_dnet_stub_dnet_ntoa=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5 +$as_echo "$ac_cv_lib_dnet_stub_dnet_ntoa" >&6; } +if test "x$ac_cv_lib_dnet_stub_dnet_ntoa" = xyes; then : + X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub" +fi + + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$ac_xsave_LIBS" + + # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT, + # to get the SysV transport functions. + # Chad R. Larson says the Pyramis MIS-ES running DC/OSx (SVR4) + # needs -lnsl. + # The nsl library prevents programs from opening the X display + # on Irix 5.2, according to T.E. Dickey. + # The functions gethostbyname, getservbyname, and inet_addr are + # in -lbsd on LynxOS 3.0.1/i386, according to Lars Hecking. + ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname" +if test "x$ac_cv_func_gethostbyname" = xyes; then : + +fi + + if test $ac_cv_func_gethostbyname = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5 +$as_echo_n "checking for gethostbyname in -lnsl... " >&6; } +if ${ac_cv_lib_nsl_gethostbyname+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnsl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gethostbyname (); +int +main () +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_nsl_gethostbyname=yes +else + ac_cv_lib_nsl_gethostbyname=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5 +$as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; } +if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then : + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl" +fi + + if test $ac_cv_lib_nsl_gethostbyname = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lbsd" >&5 +$as_echo_n "checking for gethostbyname in -lbsd... " >&6; } +if ${ac_cv_lib_bsd_gethostbyname+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbsd $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gethostbyname (); +int +main () +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_bsd_gethostbyname=yes +else + ac_cv_lib_bsd_gethostbyname=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_gethostbyname" >&5 +$as_echo "$ac_cv_lib_bsd_gethostbyname" >&6; } +if test "x$ac_cv_lib_bsd_gethostbyname" = xyes; then : + X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd" +fi + + fi + fi + + # lieder@skyler.mavd.honeywell.com says without -lsocket, + # socket/setsockopt and other routines are undefined under SCO ODT + # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary + # on later versions), says Simon Leinen: it contains gethostby* + # variants that don't use the name server (or something). -lsocket + # must be given before -lnsl if both are needed. We assume that + # if connect needs -lnsl, so does gethostbyname. + ac_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect" +if test "x$ac_cv_func_connect" = xyes; then : + +fi + + if test $ac_cv_func_connect = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for connect in -lsocket" >&5 +$as_echo_n "checking for connect in -lsocket... " >&6; } +if ${ac_cv_lib_socket_connect+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $X_EXTRA_LIBS $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char connect (); +int +main () +{ +return connect (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_socket_connect=yes +else + ac_cv_lib_socket_connect=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_connect" >&5 +$as_echo "$ac_cv_lib_socket_connect" >&6; } +if test "x$ac_cv_lib_socket_connect" = xyes; then : + X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS" +fi + + fi + + # Guillermo Gomez says -lposix is necessary on A/UX. + ac_fn_c_check_func "$LINENO" "remove" "ac_cv_func_remove" +if test "x$ac_cv_func_remove" = xyes; then : + +fi + + if test $ac_cv_func_remove = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for remove in -lposix" >&5 +$as_echo_n "checking for remove in -lposix... " >&6; } +if ${ac_cv_lib_posix_remove+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lposix $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char remove (); +int +main () +{ +return remove (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_posix_remove=yes +else + ac_cv_lib_posix_remove=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_posix_remove" >&5 +$as_echo "$ac_cv_lib_posix_remove" >&6; } +if test "x$ac_cv_lib_posix_remove" = xyes; then : + X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix" +fi + + fi + + # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. + ac_fn_c_check_func "$LINENO" "shmat" "ac_cv_func_shmat" +if test "x$ac_cv_func_shmat" = xyes; then : + +fi + + if test $ac_cv_func_shmat = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shmat in -lipc" >&5 +$as_echo_n "checking for shmat in -lipc... " >&6; } +if ${ac_cv_lib_ipc_shmat+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lipc $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shmat (); +int +main () +{ +return shmat (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ipc_shmat=yes +else + ac_cv_lib_ipc_shmat=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ipc_shmat" >&5 +$as_echo "$ac_cv_lib_ipc_shmat" >&6; } +if test "x$ac_cv_lib_ipc_shmat" = xyes; then : + X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc" +fi + + fi + fi + + # Check for libraries that X11R6 Xt/Xaw programs need. + ac_save_LDFLAGS=$LDFLAGS + test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries" + # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to + # check for ICE first), but we must link in the order -lSM -lICE or + # we get undefined symbols. So assume we have SM if we have ICE. + # These have to be linked with before -lX11, unlike the other + # libraries we check for below, so use a different variable. + # John Interrante, Karl Berry + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for IceConnectionNumber in -lICE" >&5 +$as_echo_n "checking for IceConnectionNumber in -lICE... " >&6; } +if ${ac_cv_lib_ICE_IceConnectionNumber+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lICE $X_EXTRA_LIBS $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char IceConnectionNumber (); +int +main () +{ +return IceConnectionNumber (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ICE_IceConnectionNumber=yes +else + ac_cv_lib_ICE_IceConnectionNumber=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5 +$as_echo "$ac_cv_lib_ICE_IceConnectionNumber" >&6; } +if test "x$ac_cv_lib_ICE_IceConnectionNumber" = xyes; then : + X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" +fi + + LDFLAGS=$ac_save_LDFLAGS + +fi + + +ALL_X_LIBS="$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS" + +# Check for Xinerama extension - we only support the "XFree86" style, +# and not the older Solaris-only version; recent Solaris supports the +# XFree86 style. +mutter_save_cppflags="$CPPFLAGS" +CPPFLAGS="$CPPFLAGS $X_CFLAGS" + +have_xinerama=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for XineramaQueryExtension in -lXinerama" >&5 +$as_echo_n "checking for XineramaQueryExtension in -lXinerama... " >&6; } +if ${ac_cv_lib_Xinerama_XineramaQueryExtension+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXinerama -lXext $ALL_X_LIBS $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XineramaQueryExtension (); +int +main () +{ +return XineramaQueryExtension (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_Xinerama_XineramaQueryExtension=yes +else + ac_cv_lib_Xinerama_XineramaQueryExtension=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xinerama_XineramaQueryExtension" >&5 +$as_echo "$ac_cv_lib_Xinerama_XineramaQueryExtension" >&6; } +if test "x$ac_cv_lib_Xinerama_XineramaQueryExtension" = xyes; then : + ac_fn_c_check_header_compile "$LINENO" "X11/extensions/Xinerama.h" "ac_cv_header_X11_extensions_Xinerama_h" "#include +" +if test "x$ac_cv_header_X11_extensions_Xinerama_h" = xyes; then : + X_EXTRA_LIBS="-lXinerama $X_EXTRA_LIBS" + if test -z "`echo $ALL_X_LIBS | grep "\-lXext" 2> /dev/null`"; then + X_EXTRA_LIBS="-lXext $X_EXTRA_LIBS" + fi +else + have_xinerama=no +fi + + +else + have_xinerama=no +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Xinerama support" >&5 +$as_echo_n "checking for Xinerama support... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_xinerama" >&5 +$as_echo "$have_xinerama" >&6; } + +CPPFLAGS="$mutter_save_cppflags" + +if test x$have_xinerama = xno; then + as_fn_error $? "Xinerama extension was not found" "$LINENO" 5 +fi + + +cat >>confdefs.h <<_ACEOF +#define XKB_BASE "`$PKG_CONFIG --variable xkb_base xkeyboard-config`" +_ACEOF + + +RANDR_LIBS= +found_randr=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for XRRUpdateConfiguration in -lXrandr" >&5 +$as_echo_n "checking for XRRUpdateConfiguration in -lXrandr... " >&6; } +if ${ac_cv_lib_Xrandr_XRRUpdateConfiguration+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXrandr -lXext $ALL_X_LIBS $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XRRUpdateConfiguration (); +int +main () +{ +return XRRUpdateConfiguration (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_Xrandr_XRRUpdateConfiguration=yes +else + ac_cv_lib_Xrandr_XRRUpdateConfiguration=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xrandr_XRRUpdateConfiguration" >&5 +$as_echo "$ac_cv_lib_Xrandr_XRRUpdateConfiguration" >&6; } +if test "x$ac_cv_lib_Xrandr_XRRUpdateConfiguration" = xyes; then : + ac_fn_c_check_header_compile "$LINENO" "X11/extensions/Xrandr.h" "ac_cv_header_X11_extensions_Xrandr_h" "#include +" +if test "x$ac_cv_header_X11_extensions_Xrandr_h" = xyes; then : + RANDR_LIBS=-lXrandr found_randr=yes +fi + + +fi + + +if test "x$found_randr" = "xyes"; then + +$as_echo "#define HAVE_RANDR /**/" >>confdefs.h + + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"xrandr >= 1.5.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "xrandr >= 1.5.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + +$as_echo "#define HAVE_XRANDR15 1" >>confdefs.h + +fi +fi + +MUTTER_LIBS="$MUTTER_LIBS $RANDR_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm" + +found_sm=no +case "$MUTTER_LIBS" in + *-lSM*) + found_sm=yes + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SmcSaveYourselfDone in -lSM" >&5 +$as_echo_n "checking for SmcSaveYourselfDone in -lSM... " >&6; } +if ${ac_cv_lib_SM_SmcSaveYourselfDone+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lSM $MUTTER_LIBS $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char SmcSaveYourselfDone (); +int +main () +{ +return SmcSaveYourselfDone (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_SM_SmcSaveYourselfDone=yes +else + ac_cv_lib_SM_SmcSaveYourselfDone=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_SM_SmcSaveYourselfDone" >&5 +$as_echo "$ac_cv_lib_SM_SmcSaveYourselfDone" >&6; } +if test "x$ac_cv_lib_SM_SmcSaveYourselfDone" = xyes; then : + for ac_header in X11/SM/SMlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "X11/SM/SMlib.h" "ac_cv_header_X11_SM_SMlib_h" "$ac_includes_default" +if test "x$ac_cv_header_X11_SM_SMlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_X11_SM_SMLIB_H 1 +_ACEOF + MUTTER_LIBS="-lSM -lICE $MUTTER_LIBS" found_sm=yes +fi + +done + +fi + + ;; +esac + +if test x$enable_sm = xno; then + found_sm=no +fi + +if test x$enable_sm = xyes; then + if test "$found_sm" = "no"; then + as_fn_error $? "--enable-sm forced and -lSM not found" "$LINENO" 5 + exit 1 + fi +fi + +if test "$found_sm" = "yes"; then + +$as_echo "#define HAVE_SM /**/" >>confdefs.h + +fi + + if test "$found_sm" = "yes"; then + HAVE_SM_TRUE= + HAVE_SM_FALSE='#' +else + HAVE_SM_TRUE='#' + HAVE_SM_FALSE= +fi + + +# Extract the first word of "zenity", so it can be a program name with args. +set dummy zenity; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ZENITY+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ZENITY in + [\\/]* | ?:[\\/]*) + ac_cv_path_ZENITY="$ZENITY" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ZENITY="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_ZENITY" && ac_cv_path_ZENITY="no" + ;; +esac +fi +ZENITY=$ac_cv_path_ZENITY +if test -n "$ZENITY"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ZENITY" >&5 +$as_echo "$ZENITY" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test x"$ZENITY" = xno; then + as_fn_error $? "zenity not found in your path - needed for dialogs" "$LINENO" 5 +fi + +# Check whether --enable-debug was given. +if test "${enable_debug+set}" = set; then : + enableval=$enable_debug; +else + enable_debug=no +fi + +if test "x$enable_debug" = "xyes"; then + CFLAGS="$CFLAGS -g -O" +fi + +ac_fn_c_check_decl "$LINENO" "GL_EXT_x11_sync_object" "ac_cv_have_decl_GL_EXT_x11_sync_object" "#include +" +if test "x$ac_cv_have_decl_GL_EXT_x11_sync_object" = xyes; then : + +else + as_fn_error $? "GL_EXT_x11_sync_object definition not found, please update your GL headers" "$LINENO" 5 +fi + + +# Extract the first word of "cvt", so it can be a program name with args. +set dummy cvt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_CVT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $CVT in + [\\/]* | ?:[\\/]*) + ac_cv_path_CVT="$CVT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_CVT="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +CVT=$ac_cv_path_CVT +if test -n "$CVT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CVT" >&5 +$as_echo "$CVT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + +#### Warnings (last since -Werror can disturb other tests) + +# Stay command-line compatible with the gnome-common configure option. Here +# minimum/yes/maximum are the same, however. +# Check whether --enable-compile_warnings was given. +if test "${enable_compile_warnings+set}" = set; then : + enableval=$enable_compile_warnings; +else + enable_compile_warnings=error +fi + + +if test "$enable_compile_warnings" != no ; then + if test "x$GCC" = "xyes"; then + case " $CFLAGS " in + *[\ \ ]-Wall[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wall" ;; + esac + +# case " $CFLAGS " in +# *[\ \ ]-Wshadow[\ \ ]*) ;; +# *) CFLAGS="$CFLAGS -Wshadow" ;; +# esac + + case " $CFLAGS " in + *[\ \ ]-Wchar-subscripts[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wchar-subscripts" ;; + esac + + case " $CFLAGS " in + *[\ \ ]-Wmissing-declarations[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wmissing-declarations" ;; + esac + + case " $CFLAGS " in + *[\ \ ]-Wmissing-prototypes[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wmissing-prototypes" ;; + esac + + case " $CFLAGS " in + *[\ \ ]-Wnested-externs[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wnested-externs" ;; + esac + + case " $CFLAGS " in + *[\ \ ]-Wpointer-arith[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wpointer-arith" ;; + esac + + case " $CFLAGS " in + *[\ \ ]-Wcast-align[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wcast-align" ;; + esac + + case " $CFLAGS " in + *[\ \ ]-Wsign-compare[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wsign-compare" ;; + esac + + if test "$enable_compile_warnings" = error; then + case " $CFLAGS " in + *[\ \ ]-Werror[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Werror -Wno-error=deprecated-declarations" ;; + esac + fi + fi +fi + +ac_config_files="$ac_config_files Makefile data/Makefile doc/Makefile doc/man/Makefile src/Makefile src/libmutter.pc src/compositor/plugins/Makefile src/meta/meta-version.h po/Makefile.in" + + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 +$as_echo_n "checking that generated files are newer than configure... " >&6; } + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 +$as_echo "done" >&6; } + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then + as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILDOPT_INSTALL_TESTS_TRUE}" && test -z "${BUILDOPT_INSTALL_TESTS_FALSE}"; then + as_fn_error $? "conditional \"BUILDOPT_INSTALL_TESTS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_INTROSPECTION_TRUE}" && test -z "${HAVE_INTROSPECTION_FALSE}"; then + as_fn_error $? "conditional \"HAVE_INTROSPECTION\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_NATIVE_BACKEND_TRUE}" && test -z "${HAVE_NATIVE_BACKEND_FALSE}"; then + as_fn_error $? "conditional \"HAVE_NATIVE_BACKEND\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_WAYLAND_TRUE}" && test -z "${HAVE_WAYLAND_FALSE}"; then + as_fn_error $? "conditional \"HAVE_WAYLAND\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_SM_TRUE}" && test -z "${HAVE_SM_FALSE}"; then + as_fn_error $? "conditional \"HAVE_SM\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by mutter $as_me 3.22.3, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +mutter config.status 3.22.3 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" +# Capture the value of obsolete ALL_LINGUAS because we need it to compute + # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it + # from automake < 1.5. + eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' + # Capture the value of LINGUAS because we need it to compute CATALOGS. + LINGUAS="${LINGUAS-%UNSET%}" + + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' +lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' +want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' +nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' +lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' +configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in SHELL \ +ECHO \ +PATH_SEPARATOR \ +SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +OBJDUMP \ +deplibs_check_method \ +file_magic_cmd \ +file_magic_glob \ +want_nocaseglob \ +DLLTOOL \ +sharedlib_from_linklib_cmd \ +AR \ +AR_FLAGS \ +archiver_list_spec \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_import \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +lt_cv_nm_interface \ +nm_file_list_spec \ +lt_cv_truncate_bin \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_pic \ +lt_prog_compiler_wl \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +MANIFEST_TOOL \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_separator \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +install_override_mode \ +finish_eval \ +old_striplib \ +striplib; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postlink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +configure_time_dlsearch_path \ +configure_time_lt_sys_library_path; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +ac_aux_dir='$ac_aux_dir' + +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile' + + + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "po-directories") CONFIG_COMMANDS="$CONFIG_COMMANDS po-directories" ;; + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "data/Makefile") CONFIG_FILES="$CONFIG_FILES data/Makefile" ;; + "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; + "doc/man/Makefile") CONFIG_FILES="$CONFIG_FILES doc/man/Makefile" ;; + "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + "src/libmutter.pc") CONFIG_FILES="$CONFIG_FILES src/libmutter.pc" ;; + "src/compositor/plugins/Makefile") CONFIG_FILES="$CONFIG_FILES src/compositor/plugins/Makefile" ;; + "src/meta/meta-version.h") CONFIG_FILES="$CONFIG_FILES src/meta/meta-version.h" ;; + "po/Makefile.in") CONFIG_FILES="$CONFIG_FILES po/Makefile.in" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "$am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + "po-directories":C) + for ac_file in $CONFIG_FILES; do + # Support "outfile[:infile[:infile...]]" + case "$ac_file" in + *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + esac + # PO directories have a Makefile.in generated from Makefile.in.in. + case "$ac_file" in */Makefile.in) + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix=/`echo "$ac_dir"|sed 's%^\./%%'` + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + # Treat a directory as a PO directory if and only if it has a + # POTFILES.in file. This allows packages to have multiple PO + # directories under different names or in different locations. + if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then + rm -f "$ac_dir/POTFILES" + test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" + gt_tab=`printf '\t'` + cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ${gt_tab}]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" + POMAKEFILEDEPS="POTFILES.in" + # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend + # on $ac_dir but don't depend on user-specified configuration + # parameters. + if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then + # The LINGUAS file contains the set of available languages. + if test -n "$OBSOLETE_ALL_LINGUAS"; then + test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" + fi + ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` + # Hide the ALL_LINGUAS assignment from automake < 1.5. + eval 'ALL_LINGUAS''=$ALL_LINGUAS_' + POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" + else + # The set of available languages was given in configure.in. + # Hide the ALL_LINGUAS assignment from automake < 1.5. + eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' + fi + # Compute POFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) + # Compute UPDATEPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) + # Compute DUMMYPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) + # Compute GMOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) + case "$ac_given_srcdir" in + .) srcdirpre= ;; + *) srcdirpre='$(srcdir)/' ;; + esac + POFILES= + UPDATEPOFILES= + DUMMYPOFILES= + GMOFILES= + for lang in $ALL_LINGUAS; do + POFILES="$POFILES $srcdirpre$lang.po" + UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" + DUMMYPOFILES="$DUMMYPOFILES $lang.nop" + GMOFILES="$GMOFILES $srcdirpre$lang.gmo" + done + # CATALOGS depends on both $ac_dir and the user's LINGUAS + # environment variable. + INST_LINGUAS= + if test -n "$ALL_LINGUAS"; then + for presentlang in $ALL_LINGUAS; do + useit=no + if test "%UNSET%" != "$LINGUAS"; then + desiredlanguages="$LINGUAS" + else + desiredlanguages="$ALL_LINGUAS" + fi + for desiredlang in $desiredlanguages; do + # Use the presentlang catalog if desiredlang is + # a. equal to presentlang, or + # b. a variant of presentlang (because in this case, + # presentlang can be used as a fallback for messages + # which are not translated in the desiredlang catalog). + case "$desiredlang" in + "$presentlang"*) useit=yes;; + esac + done + if test $useit = yes; then + INST_LINGUAS="$INST_LINGUAS $presentlang" + fi + done + fi + CATALOGS= + if test -n "$INST_LINGUAS"; then + for lang in $INST_LINGUAS; do + CATALOGS="$CATALOGS $lang.gmo" + done + fi + test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" + sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" + for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do + if test -f "$f"; then + case "$f" in + *.orig | *.bak | *~) ;; + *) cat "$f" >> "$ac_dir/Makefile" ;; + esac + fi + done + fi + ;; + esac + done ;; + "libtool":C) + + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +# The names of the tagged configurations supported by this script. +available_tags='' + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# Shared archive member basename,for filename based shared library versioning on AIX. +shared_archive_member_spec=$shared_archive_member_spec + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + +# The PATH separator for the build system. +PATH_SEPARATOR=$lt_PATH_SEPARATOR + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# convert \$build file names to \$host format. +to_host_file_cmd=$lt_cv_to_host_file_cmd + +# convert \$build files to toolchain format. +to_tool_file_cmd=$lt_cv_to_tool_file_cmd + +# An object symbol dumper. +OBJDUMP=$lt_OBJDUMP + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method = "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob=$lt_file_magic_glob + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob=$lt_want_nocaseglob + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd + +# The archiver. +AR=$lt_AR + +# Flags to create an archive. +AR_FLAGS=$lt_AR_FLAGS + +# How to feed a file listing to the archiver. +archiver_list_spec=$lt_archiver_list_spec + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm into a list of symbols to manually relocate. +global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# The name lister interface. +nm_interface=$lt_lt_cv_nm_interface + +# Specify filename containing input files for \$NM. +nm_file_list_spec=$lt_nm_file_list_spec + +# The root where to search for dependent libraries,and where our libraries should be installed. +lt_sysroot=$lt_sysroot + +# Command to truncate a binary pipe. +lt_truncate_bin=$lt_lt_cv_truncate_bin + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Manifest tool. +MANIFEST_TOOL=$lt_MANIFEST_TOOL + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Detected run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path + +# Explicit LT_SYS_LIBRARY_PATH set during ./configure time. +configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \$shlibpath_var if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain=$ac_aux_dir/ltmain.sh + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi + +# +# CONFIG_SUBDIRS section. +# +if test "$no_recursion" != yes; then + + # Remove --cache-file, --srcdir, and --disable-option-checking arguments + # so they do not pile up. + ac_sub_configure_args= + ac_prev= + eval "set x $ac_configure_args" + shift + for ac_arg + do + if test -n "$ac_prev"; then + ac_prev= + continue + fi + case $ac_arg in + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \ + | --c=*) + ;; + --config-cache | -C) + ;; + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + ;; + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + ;; + --disable-option-checking) + ;; + *) + case $ac_arg in + *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append ac_sub_configure_args " '$ac_arg'" ;; + esac + done + + # Always prepend --prefix to ensure using the same prefix + # in subdir configurations. + ac_arg="--prefix=$prefix" + case $ac_arg in + *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + ac_sub_configure_args="'$ac_arg' $ac_sub_configure_args" + + # Pass --silent + if test "$silent" = yes; then + ac_sub_configure_args="--silent $ac_sub_configure_args" + fi + + # Always prepend --disable-option-checking to silence warnings, since + # different subdirs can have different --enable and --with options. + ac_sub_configure_args="--disable-option-checking $ac_sub_configure_args" + + ac_popdir=`pwd` + for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue + + # Do not complain, so a configure script can configure whichever + # parts of a large source tree are present. + test -d "$srcdir/$ac_dir" || continue + + ac_msg="=== configuring in $ac_dir (`pwd`/$ac_dir)" + $as_echo "$as_me:${as_lineno-$LINENO}: $ac_msg" >&5 + $as_echo "$ac_msg" >&6 + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + cd "$ac_dir" + + # Check for guested configure; otherwise get Cygnus style configure. + if test -f "$ac_srcdir/configure.gnu"; then + ac_sub_configure=$ac_srcdir/configure.gnu + elif test -f "$ac_srcdir/configure"; then + ac_sub_configure=$ac_srcdir/configure + elif test -f "$ac_srcdir/configure.in"; then + # This should be Cygnus configure. + ac_sub_configure=$ac_aux_dir/configure + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: no configuration information is in $ac_dir" >&5 +$as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;} + ac_sub_configure= + fi + + # The recursion is here. + if test -n "$ac_sub_configure"; then + # Make the cache file name correct relative to the subdirectory. + case $cache_file in + [\\/]* | ?:[\\/]* ) ac_sub_cache_file=$cache_file ;; + *) # Relative name. + ac_sub_cache_file=$ac_top_build_prefix$cache_file ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5 +$as_echo "$as_me: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;} + # The eval makes quoting arguments work. + eval "\$SHELL \"\$ac_sub_configure\" $ac_sub_configure_args \ + --cache-file=\"\$ac_sub_cache_file\" --srcdir=\"\$ac_srcdir\"" || + as_fn_error $? "$ac_sub_configure failed for $ac_dir" "$LINENO" 5 + fi + + cd "$ac_popdir" + done +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + +if test x$enable_verbose_mode = xno; then + echo "*** WARNING WARNING WARNING WARNING WARNING" + echo "*** Building without verbose mode" + echo "*** This means there's no way to debug mutter problems." + echo "*** Please build normal desktop versions of mutter" + echo "*** with verbose mode enabled so users can use it when they report bugs." +fi + +echo " +mutter-$VERSION + + prefix: ${prefix} + source code location: ${srcdir} + compiler: ${CC} + + Startup notification: ${have_startup_notification} + libcanberra: ${have_libcanberra} + libwacom: ${have_libwacom} + gudev ${have_gudev} + Introspection: ${found_introspection} + Session management: ${found_sm} + Wayland: ${have_wayland} + Native (KMS) backend: ${have_native_backend} +" + + +MUTTER_MINOR_VERSION=22 +if expr $MUTTER_MINOR_VERSION % 2 > /dev/null ; then + stable_version=`expr $MUTTER_MINOR_VERSION - 1` + echo "This is the UNSTABLE branch of mutter" + echo -n "Use 3.$stable_version.x for stable " + echo "(gnome-3-$stable_version branch in git)" +else + echo "This is the stable branch of mutter" +fi diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..8dde793 --- /dev/null +++ b/configure.ac @@ -0,0 +1,497 @@ +AC_PREREQ(2.62) + +m4_define([mutter_major_version], [3]) +m4_define([mutter_minor_version], [22]) +m4_define([mutter_micro_version], [3]) + +m4_define([mutter_version], + [mutter_major_version.mutter_minor_version.mutter_micro_version]) + +m4_define([mutter_plugin_api_version], [3]) + +AC_INIT([mutter], [mutter_version], + [http://bugzilla.gnome.org/enter_bug.cgi?product=mutter]) + +AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_AUX_DIR([build-aux]) +AC_CONFIG_SRCDIR(src/core/display.c) +AC_CONFIG_HEADERS(config.h) +AC_CONFIG_SUBDIRS([cogl clutter]) + +AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz tar-ustar subdir-objects]) +m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],) +AM_MAINTAINER_MODE([enable]) + +AC_GNU_SOURCE + +MUTTER_MAJOR_VERSION=mutter_major_version +MUTTER_MINOR_VERSION=mutter_minor_version +MUTTER_MICRO_VERSION=mutter_micro_version +MUTTER_PLUGIN_API_VERSION=mutter_plugin_api_version +AC_SUBST(MUTTER_MAJOR_VERSION) +AC_SUBST(MUTTER_MINOR_VERSION) +AC_SUBST(MUTTER_MICRO_VERSION) +AC_SUBST(MUTTER_PLUGIN_API_VERSION) + +MUTTER_PLUGIN_DIR="$libdir/$PACKAGE/plugins" +AC_SUBST(MUTTER_PLUGIN_DIR) + +# Honor aclocal flags +AC_SUBST(ACLOCAL_AMFLAGS, "\${ACLOCAL_FLAGS}") + +GETTEXT_PACKAGE=mutter +AC_SUBST(GETTEXT_PACKAGE) +AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[Name of default gettext domain]) + +AM_GNU_GETTEXT_VERSION([0.19.6]) +AM_GNU_GETTEXT([external]) + +LT_PREREQ([2.2.6]) +LT_INIT([disable-static]) +AC_PROG_CC +AC_PROG_CC_C_O +AC_PROG_INSTALL +AC_PROG_SED +AC_HEADER_STDC +PKG_PROG_PKG_CONFIG([0.21]) + +# Sets GLIB_GENMARSHAL and GLIB_MKENUMS +AM_PATH_GLIB_2_0([2.49.0]) + +CANBERRA_GTK=libcanberra-gtk3 +CANBERRA_GTK_VERSION=0.26 + +LIBWACOM_VERSION=0.13 + +MUTTER_PC_MODULES=" + gtk+-3.0 >= 3.19.8 + gio-unix-2.0 >= 2.35.1 + pango >= 1.2.0 + cairo >= 1.10.0 + gsettings-desktop-schemas >= 3.21.4 + json-glib-1.0 + upower-glib >= 0.99.0 + gnome-desktop-3.0 + xcomposite >= 0.2 + xcursor + xdamage + xext + xfixes + xi >= 1.6.0 + xkbfile + xkeyboard-config + xkbcommon >= 0.4.3 + xkbcommon-x11 + xrender + x11-xcb + xcb-randr + xcb-res +" + +GLIB_GSETTINGS + +AC_ARG_ENABLE(verbose-mode, + AC_HELP_STRING([--disable-verbose-mode], + [disable mutter's ability to do verbose logging, for embedded/size-sensitive custom builds]),, + enable_verbose_mode=yes) + +if test x$enable_verbose_mode = xyes; then + AC_DEFINE(WITH_VERBOSE_MODE,1,[Build with verbose mode support]) +fi + +AC_ARG_ENABLE(sm, + AC_HELP_STRING([--disable-sm], + [disable mutter's session management support, for embedded/size-sensitive custom non-GNOME builds]),, + enable_sm=auto) + +AC_ARG_ENABLE(startup-notification, + AC_HELP_STRING([--disable-startup-notification], + [disable mutter's startup notification support, for embedded/size-sensitive custom non-GNOME builds]),, + enable_startup_notification=auto) + +AC_ARG_WITH(libcanberra, + AC_HELP_STRING([--without-libcanberra], + [disable the use of libcanberra for playing sounds]),, + with_libcanberra=auto) + +AC_ARG_WITH(libwacom, + AC_HELP_STRING([--without-libwacom], + [disable the use of libwacom for advanced tablet management]),, + with_libwacom=auto) + +AC_ARG_WITH(gudev, + AC_HELP_STRING([--without-gudev], + [disable the use of gudev for device type detection]),, + with_gudev=auto) + +AC_ARG_WITH([xwayland-path], + [AS_HELP_STRING([--with-xwayland-path], [Absolute path for an X Wayland server])], + [XWAYLAND_PATH="$withval"], + [XWAYLAND_PATH="$bindir/Xwayland"]) + +AC_ARG_ENABLE(installed_tests, + AS_HELP_STRING([--enable-installed-tests], + [Install test programs (default: no)]),, + [enable_installed_tests=no]) +AM_CONDITIONAL(BUILDOPT_INSTALL_TESTS, test x$enable_installed_tests = xyes) + +## here we get the flags we'll actually use + +# Unconditionally use this dir to avoid a circular dep with gnomecc +GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings" +AC_SUBST(GNOME_KEYBINDINGS_KEYSDIR) + +STARTUP_NOTIFICATION_VERSION=0.7 +AC_MSG_CHECKING([Startup notification library >= $STARTUP_NOTIFICATION_VERSION]) +if $PKG_CONFIG --atleast-version $STARTUP_NOTIFICATION_VERSION libstartup-notification-1.0; then + have_startup_notification=yes +else + have_startup_notification=no +fi +AC_MSG_RESULT($have_startup_notification) + +if test x$enable_startup_notification = xyes; then + have_startup_notification=yes + echo "startup-notification support forced on" +elif test x$enable_startup_notification = xauto; then + true +else + have_startup_notification=no +fi + +if test x$have_startup_notification = xyes; then + echo "Building with libstartup-notification" + MUTTER_PC_MODULES="$MUTTER_PC_MODULES libstartup-notification-1.0 >= $STARTUP_NOTIFICATION_VERSION" + AC_DEFINE(HAVE_STARTUP_NOTIFICATION, , [Building with startup notification support]) +else + echo "Building without libstartup-notification" +fi + +have_libcanberra=no +AC_MSG_CHECKING([libcanberra-gtk]) +if test x$with_libcanberra = xno ; then + AC_MSG_RESULT([disabled]) +else + if $PKG_CONFIG --exists $CANBERRA_GTK '>=' $CANBERRA_GTK_VERSION; then + have_libcanberra=yes + AC_MSG_RESULT(yes) + MUTTER_PC_MODULES="$MUTTER_PC_MODULES $CANBERRA_GTK" + AC_DEFINE([HAVE_LIBCANBERRA], 1, [Building with libcanberra for playing sounds]) + else + AC_MSG_RESULT(no) + if test x$with_libcanberra = xyes ; then + AC_MSG_ERROR([libcanberra forced and libcanberra-gtk was not found]) + fi + fi +fi + +have_libwacom=no +AC_MSG_CHECKING([libwacom]) +if test x$with_libwacom = xno ; then + AC_MSG_RESULT([disabled]) +else + if $PKG_CONFIG --exists libwacom '>=' $LIBWACOM_VERSION; then + have_libwacom=yes + AC_MSG_RESULT(yes) + MUTTER_PC_MODULES="$MUTTER_PC_MODULES libwacom" + AC_DEFINE([HAVE_LIBWACOM], 1, [Building with libwacom for advanced tablet management]) + else + AC_MSG_RESULT(no) + if test x$with_libwacom = xyes ; then + AC_MSG_ERROR([libwacom forced but not found]) + fi + fi +fi + +have_gudev=no +AC_MSG_CHECKING([gudev]) +if test x$with_gudev = xno ; then + AC_MSG_RESULT([disabled]) +else + if $PKG_CONFIG --exists gudev-1.0; then + have_gudev=yes + AC_MSG_RESULT(yes) + MUTTER_PC_MODULES="$MUTTER_PC_MODULES gudev-1.0" + AC_DEFINE([HAVE_LIBGUDEV], 1, [Building with gudev for device type detection]) + else + AC_MSG_RESULT(no) + if test x$with_gudev = xyes ; then + AC_MSG_ERROR([gudev forced but not found]) + fi + fi +fi + +INTROSPECTION_VERSION=0.9.5 +GOBJECT_INTROSPECTION_CHECK([$INTROSPECTION_VERSION]) + +if test x$found_introspection != xno; then + AC_DEFINE(HAVE_INTROSPECTION, 1, [Define if GObject introspection is available]) + MUTTER_PC_MODULES="$MUTTER_PC_MODULES gobject-introspection-1.0" + # Since we don't make any guarantees about stability and we don't support + # parallel install, there's no real reason to change directories, filenames, + # etc. as we change the Mutter tarball version. Note that this must match + # api_version in src/Makefile.am + META_GIR=Meta_3_0_gir + # META_GIR=[Meta_]mutter_major_version[_]mutter_minor_version[_gir] + AC_SUBST(META_GIR) +fi + +AC_SUBST(XWAYLAND_PATH) + +PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES) + +MUTTER_NATIVE_BACKEND_MODULES="libdrm libsystemd libinput >= 1.4 gudev-1.0 gbm >= 10.3" + +AC_ARG_ENABLE(native-backend, + AS_HELP_STRING([--disable-native-backend], [disable mutter native (KMS) backend]),, + enable_native_backend=auto +) +have_native_backend="no" +AS_IF([test "$enable_native_backend" = "yes"], [have_native_backend=yes], + [test "$enable_native_backend" = "auto"], PKG_CHECK_EXISTS([$MUTTER_NATIVE_BACKEND_MODULES], [have_native_backend=yes])) + +AS_IF([test "$have_native_backend" = "yes"], [ + PKG_CHECK_MODULES([MUTTER_NATIVE_BACKEND], [$MUTTER_NATIVE_BACKEND_MODULES]) + AC_DEFINE([HAVE_NATIVE_BACKEND],[1], [Define if you want to enable the native (KMS) backend based on systemd]) +]) +AM_CONDITIONAL([HAVE_NATIVE_BACKEND],[test "$have_native_backend" = "yes"]) + +MUTTER_WAYLAND_MODULES="wayland-server >= 1.6.90" + +AC_ARG_ENABLE(wayland, + AS_HELP_STRING([--disable-wayland], [disable mutter on wayland support]),, + enable_wayland=auto +) +AS_IF([test "$enable_wayland" = "yes"], [have_wayland=yes], + [test "$enable_wayland" = "auto"], PKG_CHECK_EXISTS([$MUTTER_WAYLAND_MODULES], [have_wayland=yes])) + +AS_IF([test "$have_wayland" = "yes"], [ + PKG_CHECK_MODULES([MUTTER_WAYLAND], [$MUTTER_WAYLAND_MODULES]) + AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no]) + AS_IF([test $WAYLAND_SCANNER = "no"], + [AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols])]) + AC_SUBST([WAYLAND_SCANNER]) + AC_DEFINE([HAVE_WAYLAND],[1],[Define if you want to enable Wayland support]) + + PKG_CHECK_MODULES(WAYLAND_PROTOCOLS, [wayland-protocols >= 1.7], + [ac_wayland_protocols_pkgdatadir=`$PKG_CONFIG --variable=pkgdatadir wayland-protocols`]) + AC_SUBST(WAYLAND_PROTOCOLS_DATADIR, $ac_wayland_protocols_pkgdatadir) +]) +AM_CONDITIONAL([HAVE_WAYLAND],[test "$have_wayland" = "yes"]) + +PKG_CHECK_EXISTS([xi >= 1.6.99.1], + AC_DEFINE([HAVE_XI23],[1],[Define if you have support for XInput 2.3 or greater])) + +AC_PATH_XTRA + +ALL_X_LIBS="$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS" + +# Check for Xinerama extension - we only support the "XFree86" style, +# and not the older Solaris-only version; recent Solaris supports the +# XFree86 style. +mutter_save_cppflags="$CPPFLAGS" +CPPFLAGS="$CPPFLAGS $X_CFLAGS" + +have_xinerama=yes +AC_CHECK_LIB(Xinerama, XineramaQueryExtension, + [AC_CHECK_HEADER(X11/extensions/Xinerama.h, + [X_EXTRA_LIBS="-lXinerama $X_EXTRA_LIBS" + if test -z "`echo $ALL_X_LIBS | grep "\-lXext" 2> /dev/null`"; then + X_EXTRA_LIBS="-lXext $X_EXTRA_LIBS" + fi], + have_xinerama=no, + [#include ])], + have_xinerama=no, -lXext $ALL_X_LIBS) +AC_MSG_CHECKING(for Xinerama support) +AC_MSG_RESULT($have_xinerama) + +CPPFLAGS="$mutter_save_cppflags" + +if test x$have_xinerama = xno; then + AC_MSG_ERROR([Xinerama extension was not found]) +fi + +AC_DEFINE_UNQUOTED([XKB_BASE], ["`$PKG_CONFIG --variable xkb_base xkeyboard-config`"], + [XKB base dir]) + +RANDR_LIBS= +found_randr=no +AC_CHECK_LIB(Xrandr, XRRUpdateConfiguration, + [AC_CHECK_HEADER(X11/extensions/Xrandr.h, + RANDR_LIBS=-lXrandr found_randr=yes,, + [#include ])], + , -lXext $ALL_X_LIBS) + +if test "x$found_randr" = "xyes"; then + AC_DEFINE(HAVE_RANDR, , [Have the Xrandr extension library]) + PKG_CHECK_EXISTS([xrandr >= 1.5.0], + AC_DEFINE([HAVE_XRANDR15],[1],[Define if you have support for XRandR 1.5 or greater])) +fi + +MUTTER_LIBS="$MUTTER_LIBS $RANDR_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm" + +found_sm=no +case "$MUTTER_LIBS" in + *-lSM*) + found_sm=yes + ;; + *) + AC_CHECK_LIB(SM, SmcSaveYourselfDone, + [AC_CHECK_HEADERS(X11/SM/SMlib.h, + MUTTER_LIBS="-lSM -lICE $MUTTER_LIBS" found_sm=yes)], + , $MUTTER_LIBS) + ;; +esac + +if test x$enable_sm = xno; then + found_sm=no +fi + +if test x$enable_sm = xyes; then + if test "$found_sm" = "no"; then + AC_MSG_ERROR([--enable-sm forced and -lSM not found]) + exit 1 + fi +fi + +if test "$found_sm" = "yes"; then + AC_DEFINE(HAVE_SM, , [Building with SM support]) +fi + +AM_CONDITIONAL(HAVE_SM, test "$found_sm" = "yes") + +AC_PATH_PROG(ZENITY, zenity, no) +if test x"$ZENITY" = xno; then + AC_MSG_ERROR([zenity not found in your path - needed for dialogs]) +fi + +AC_ARG_ENABLE(debug, + [ --enable-debug enable debugging],, + enable_debug=no) +if test "x$enable_debug" = "xyes"; then + CFLAGS="$CFLAGS -g -O" +fi + +AC_CHECK_DECL([GL_EXT_x11_sync_object], + [], + [AC_MSG_ERROR([GL_EXT_x11_sync_object definition not found, please update your GL headers])], + [#include ]) + +AC_PATH_PROG([CVT],[cvt],[]) + +#### Warnings (last since -Werror can disturb other tests) + +# Stay command-line compatible with the gnome-common configure option. Here +# minimum/yes/maximum are the same, however. +AC_ARG_ENABLE(compile_warnings, + AS_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@],[Turn on compiler warnings]),, + enable_compile_warnings=error) + +changequote(,)dnl +if test "$enable_compile_warnings" != no ; then + if test "x$GCC" = "xyes"; then + case " $CFLAGS " in + *[\ \ ]-Wall[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wall" ;; + esac + +# case " $CFLAGS " in +# *[\ \ ]-Wshadow[\ \ ]*) ;; +# *) CFLAGS="$CFLAGS -Wshadow" ;; +# esac + + case " $CFLAGS " in + *[\ \ ]-Wchar-subscripts[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wchar-subscripts" ;; + esac + + case " $CFLAGS " in + *[\ \ ]-Wmissing-declarations[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wmissing-declarations" ;; + esac + + case " $CFLAGS " in + *[\ \ ]-Wmissing-prototypes[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wmissing-prototypes" ;; + esac + + case " $CFLAGS " in + *[\ \ ]-Wnested-externs[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wnested-externs" ;; + esac + + case " $CFLAGS " in + *[\ \ ]-Wpointer-arith[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wpointer-arith" ;; + esac + + case " $CFLAGS " in + *[\ \ ]-Wcast-align[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wcast-align" ;; + esac + + case " $CFLAGS " in + *[\ \ ]-Wsign-compare[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wsign-compare" ;; + esac + + if test "$enable_compile_warnings" = error; then + case " $CFLAGS " in + *[\ \ ]-Werror[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Werror -Wno-error=deprecated-declarations" ;; + esac + fi + fi +fi +changequote([,])dnl + +AC_CONFIG_FILES([ +Makefile +data/Makefile +doc/Makefile +doc/man/Makefile +src/Makefile +src/libmutter.pc +src/compositor/plugins/Makefile +src/meta/meta-version.h +po/Makefile.in +]) + +AC_OUTPUT + +if test x$enable_verbose_mode = xno; then + echo "*** WARNING WARNING WARNING WARNING WARNING" + echo "*** Building without verbose mode" + echo "*** This means there's no way to debug mutter problems." + echo "*** Please build normal desktop versions of mutter" + echo "*** with verbose mode enabled so users can use it when they report bugs." +fi + +dnl ========================================================================== +echo " +mutter-$VERSION + + prefix: ${prefix} + source code location: ${srcdir} + compiler: ${CC} + + Startup notification: ${have_startup_notification} + libcanberra: ${have_libcanberra} + libwacom: ${have_libwacom} + gudev ${have_gudev} + Introspection: ${found_introspection} + Session management: ${found_sm} + Wayland: ${have_wayland} + Native (KMS) backend: ${have_native_backend} +" + + +MUTTER_MINOR_VERSION=mutter_minor_version +if expr $MUTTER_MINOR_VERSION % 2 > /dev/null ; then + stable_version=`expr $MUTTER_MINOR_VERSION - 1` + echo "This is the UNSTABLE branch of mutter" + echo -n "Use 3.$stable_version.x for stable " + echo "(gnome-3-$stable_version branch in git)" +else + echo "This is the stable branch of mutter" +fi diff --git a/data/50-mutter-navigation.xml b/data/50-mutter-navigation.xml new file mode 100644 index 0000000..1f9161b --- /dev/null +++ b/data/50-mutter-navigation.xml @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/50-mutter-system.xml b/data/50-mutter-system.xml new file mode 100644 index 0000000..07da17a --- /dev/null +++ b/data/50-mutter-system.xml @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/data/50-mutter-windows.xml b/data/50-mutter-windows.xml new file mode 100644 index 0000000..a9316d1 --- /dev/null +++ b/data/50-mutter-windows.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/Makefile.am b/data/Makefile.am new file mode 100644 index 0000000..5188765 --- /dev/null +++ b/data/Makefile.am @@ -0,0 +1,37 @@ +desktopfiles_in_files = \ + mutter.desktop.in +desktopfilesdir = $(datadir)/applications +desktopfiles_DATA = $(desktopfiles_in_files:.desktop.in=.desktop) + +%.desktop:%.desktop.in + $(AM_V_GET) $(MSGFMT) --desktop --template $< -d $(top_srcdir)/po -o $@ + +xmldir = $(GNOME_KEYBINDINGS_KEYSDIR) +xml_DATA = \ + 50-mutter-navigation.xml \ + 50-mutter-system.xml \ + 50-mutter-windows.xml + +gschema_in_files = \ + org.gnome.mutter.gschema.xml.in \ + org.gnome.mutter.wayland.gschema.xml.in +gsettings_SCHEMAS = $(gschema_in_files:.xml.in=.xml) + +%.gschema.xml: %.gschema.xml.in Makefile + $(AM_V_GEN) sed -e 's|@GETTEXT_DOMAIN[@]|$(GETTEXT_DOMAIN)|g' \ + $< > $@ || rm $@ + +@GSETTINGS_RULES@ + +convertdir = $(datadir)/GConf/gsettings +convert_DATA = mutter-schemas.convert + +CLEANFILES = \ + $(desktopfiles_DATA) \ + $(gsettings_SCHEMAS) + +EXTRA_DIST = \ + $(convert_DATA) \ + $(desktopfiles_in_files) \ + $(gschema_in_files) \ + $(xml_DATA) diff --git a/data/Makefile.in b/data/Makefile.in new file mode 100644 index 0000000..49be4fd --- /dev/null +++ b/data/Makefile.in @@ -0,0 +1,643 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = data +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(convertdir)" \ + "$(DESTDIR)$(desktopfilesdir)" "$(DESTDIR)$(xmldir)" +DATA = $(convert_DATA) $(desktopfiles_DATA) $(xml_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CVT = @CVT@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_COMPILE_SCHEMAS = @GLIB_COMPILE_SCHEMAS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNOME_KEYBINDINGS_KEYSDIR = @GNOME_KEYBINDINGS_KEYSDIR@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GSETTINGS_DISABLE_SCHEMAS_COMPILE = @GSETTINGS_DISABLE_SCHEMAS_COMPILE@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +META_GIR = @META_GIR@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +MUTTER_CFLAGS = @MUTTER_CFLAGS@ +MUTTER_LIBS = @MUTTER_LIBS@ +MUTTER_MAJOR_VERSION = @MUTTER_MAJOR_VERSION@ +MUTTER_MICRO_VERSION = @MUTTER_MICRO_VERSION@ +MUTTER_MINOR_VERSION = @MUTTER_MINOR_VERSION@ +MUTTER_NATIVE_BACKEND_CFLAGS = @MUTTER_NATIVE_BACKEND_CFLAGS@ +MUTTER_NATIVE_BACKEND_LIBS = @MUTTER_NATIVE_BACKEND_LIBS@ +MUTTER_PLUGIN_API_VERSION = @MUTTER_PLUGIN_API_VERSION@ +MUTTER_PLUGIN_DIR = @MUTTER_PLUGIN_DIR@ +MUTTER_WAYLAND_CFLAGS = @MUTTER_WAYLAND_CFLAGS@ +MUTTER_WAYLAND_LIBS = @MUTTER_WAYLAND_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WAYLAND_PROTOCOLS_CFLAGS = @WAYLAND_PROTOCOLS_CFLAGS@ +WAYLAND_PROTOCOLS_DATADIR = @WAYLAND_PROTOCOLS_DATADIR@ +WAYLAND_PROTOCOLS_LIBS = @WAYLAND_PROTOCOLS_LIBS@ +WAYLAND_SCANNER = @WAYLAND_SCANNER@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +XMKMF = @XMKMF@ +XWAYLAND_PATH = @XWAYLAND_PATH@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +ZENITY = @ZENITY@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gsettingsschemadir = @gsettingsschemadir@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +desktopfiles_in_files = \ + mutter.desktop.in + +desktopfilesdir = $(datadir)/applications +desktopfiles_DATA = $(desktopfiles_in_files:.desktop.in=.desktop) +xmldir = $(GNOME_KEYBINDINGS_KEYSDIR) +xml_DATA = \ + 50-mutter-navigation.xml \ + 50-mutter-system.xml \ + 50-mutter-windows.xml + +gschema_in_files = \ + org.gnome.mutter.gschema.xml.in \ + org.gnome.mutter.wayland.gschema.xml.in + +gsettings_SCHEMAS = $(gschema_in_files:.xml.in=.xml) +convertdir = $(datadir)/GConf/gsettings +convert_DATA = mutter-schemas.convert +CLEANFILES = \ + $(desktopfiles_DATA) \ + $(gsettings_SCHEMAS) + +EXTRA_DIST = \ + $(convert_DATA) \ + $(desktopfiles_in_files) \ + $(gschema_in_files) \ + $(xml_DATA) + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign data/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign data/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-convertDATA: $(convert_DATA) + @$(NORMAL_INSTALL) + @list='$(convert_DATA)'; test -n "$(convertdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(convertdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(convertdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(convertdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(convertdir)" || exit $$?; \ + done + +uninstall-convertDATA: + @$(NORMAL_UNINSTALL) + @list='$(convert_DATA)'; test -n "$(convertdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(convertdir)'; $(am__uninstall_files_from_dir) +install-desktopfilesDATA: $(desktopfiles_DATA) + @$(NORMAL_INSTALL) + @list='$(desktopfiles_DATA)'; test -n "$(desktopfilesdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(desktopfilesdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(desktopfilesdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(desktopfilesdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(desktopfilesdir)" || exit $$?; \ + done + +uninstall-desktopfilesDATA: + @$(NORMAL_UNINSTALL) + @list='$(desktopfiles_DATA)'; test -n "$(desktopfilesdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(desktopfilesdir)'; $(am__uninstall_files_from_dir) +install-xmlDATA: $(xml_DATA) + @$(NORMAL_INSTALL) + @list='$(xml_DATA)'; test -n "$(xmldir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(xmldir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(xmldir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(xmldir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(xmldir)" || exit $$?; \ + done + +uninstall-xmlDATA: + @$(NORMAL_UNINSTALL) + @list='$(xml_DATA)'; test -n "$(xmldir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(xmldir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(convertdir)" "$(DESTDIR)$(desktopfilesdir)" "$(DESTDIR)$(xmldir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-convertDATA install-desktopfilesDATA \ + install-xmlDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-convertDATA uninstall-desktopfilesDATA \ + uninstall-xmlDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-convertDATA install-data \ + install-data-am install-desktopfilesDATA install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip install-xmlDATA installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags-am uninstall uninstall-am uninstall-convertDATA \ + uninstall-desktopfilesDATA uninstall-xmlDATA + +.PRECIOUS: Makefile + + +%.desktop:%.desktop.in + $(AM_V_GET) $(MSGFMT) --desktop --template $< -d $(top_srcdir)/po -o $@ + +%.gschema.xml: %.gschema.xml.in Makefile + $(AM_V_GEN) sed -e 's|@GETTEXT_DOMAIN[@]|$(GETTEXT_DOMAIN)|g' \ + $< > $@ || rm $@ + +@GSETTINGS_RULES@ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/data/mutter-schemas.convert b/data/mutter-schemas.convert new file mode 100644 index 0000000..2551c59 --- /dev/null +++ b/data/mutter-schemas.convert @@ -0,0 +1,5 @@ +[org.gnome.mutter] +overlay-key = /apps/mutter/general/overlay_key +attach-modal-dialogs = /apps/mutter/general/attach_modal_dialogs +workspaces-only-on-primary = /apps/mutter/general/workspaces_only_on_primary +draggable-border-width = /apps/mutter/general/draggable_border_width diff --git a/data/mutter.desktop.in b/data/mutter.desktop.in new file mode 100644 index 0000000..e3ae070 --- /dev/null +++ b/data/mutter.desktop.in @@ -0,0 +1,17 @@ +[Desktop Entry] +Type=Application +Name=Mutter +Exec=mutter +NoDisplay=true +# name of loadable control center module +X-GNOME-WMSettingsModule=metacity +# name we put on the WM spec check window +X-GNOME-WMName=Mutter +# back compat only +X-GnomeWMSettingsLibrary=metacity +X-GNOME-Bugzilla-Bugzilla=GNOME +X-GNOME-Bugzilla-Product=mutter +X-GNOME-Bugzilla-Component=general +X-GNOME-Autostart-Phase=WindowManager +X-GNOME-Provides=windowmanager +X-GNOME-Autostart-Notify=true diff --git a/data/org.gnome.mutter.gschema.xml.in b/data/org.gnome.mutter.gschema.xml.in new file mode 100644 index 0000000..3e3f8f7 --- /dev/null +++ b/data/org.gnome.mutter.gschema.xml.in @@ -0,0 +1,129 @@ + + + + + 'Super_L' + Modifier to use for extended window management operations + + This key will initiate the "overlay", which is a combination window + overview and application launching system. The default is intended + to be the "Windows key" on PC hardware. + + It's expected that this binding either the default or set to + the empty string. + + + + + false + Attach modal dialogs + + When true, instead of having independent titlebars, modal dialogs + appear attached to the titlebar of the parent window and are moved + together with the parent window. + + + + + false + Enable edge tiling when dropping windows on screen edges + + If enabled, dropping windows on vertical screen edges maximizes them + vertically and resizes them horizontally to cover half of the available + area. Dropping windows on the top screen edge maximizes them completely. + + + + + false + Workspaces are managed dynamically + + Determines whether workspaces are managed dynamically or + whether there's a static number of workspaces (determined + by the num-workspaces key in org.gnome.desktop.wm.preferences). + + + + + false + Workspaces only on primary + + Determines whether workspace switching should happen for windows + on all monitors or only for windows on the primary monitor. + + + + + false + No tab popup + + Determines whether the use of popup and highlight frame should + be disabled for window cycling. + + + + + false + Delay focus changes until the pointer stops moving + + If set to true, and the focus mode is either "sloppy" or "mouse" + then the focus will not be changed immediately when entering a + window, but only after the pointer stops moving. + + + + + 10 + + Draggable border width + + The amount of total draggable borders. If the theme's visible + borders are not enough, invisible borders will be added to meet + this value. + + + + + true + Auto maximize nearly monitor sized windows + + If enabled, new windows that are initially the size of the monitor + automatically get maximized. + + + + + false + Place new windows in the center + + When true, the new windows will always be put in the center of the + active screen of the monitor. + + + + + + + + + + Left']]]> + + + + Right']]]> + + + + [] + Select window from tab popup + + + + [] + Cancel tab popup + + + + diff --git a/data/org.gnome.mutter.wayland.gschema.xml.in b/data/org.gnome.mutter.wayland.gschema.xml.in new file mode 100644 index 0000000..44334d6 --- /dev/null +++ b/data/org.gnome.mutter.wayland.gschema.xml.in @@ -0,0 +1,53 @@ + + + + F1']]]> + Switch to VT 1 + + + F2']]]> + Switch to VT 2 + + + F3']]]> + Switch to VT 3 + + + F4']]]> + Switch to VT 4 + + + F5']]]> + Switch to VT 5 + + + F6']]]> + Switch to VT 6 + + + F7']]]> + Switch to VT 7 + + + F8']]]> + Switch to VT 8 + + + F9']]]> + Switch to VT 9 + + + F10']]]> + Switch to VT 10 + + + F11']]]> + Switch to VT 11 + + + F12']]]> + Switch to VT 12 + + + diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..8605e2b --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,4 @@ +SUBDIRS = man + +EXTRA_DIST = dialogs.txt code-overview.txt \ + how-to-get-focus-right.txt rationales.txt diff --git a/doc/Makefile.in b/doc/Makefile.in new file mode 100644 index 0000000..4de0247 --- /dev/null +++ b/doc/Makefile.in @@ -0,0 +1,688 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = doc +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CVT = @CVT@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_COMPILE_SCHEMAS = @GLIB_COMPILE_SCHEMAS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNOME_KEYBINDINGS_KEYSDIR = @GNOME_KEYBINDINGS_KEYSDIR@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GSETTINGS_DISABLE_SCHEMAS_COMPILE = @GSETTINGS_DISABLE_SCHEMAS_COMPILE@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +META_GIR = @META_GIR@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +MUTTER_CFLAGS = @MUTTER_CFLAGS@ +MUTTER_LIBS = @MUTTER_LIBS@ +MUTTER_MAJOR_VERSION = @MUTTER_MAJOR_VERSION@ +MUTTER_MICRO_VERSION = @MUTTER_MICRO_VERSION@ +MUTTER_MINOR_VERSION = @MUTTER_MINOR_VERSION@ +MUTTER_NATIVE_BACKEND_CFLAGS = @MUTTER_NATIVE_BACKEND_CFLAGS@ +MUTTER_NATIVE_BACKEND_LIBS = @MUTTER_NATIVE_BACKEND_LIBS@ +MUTTER_PLUGIN_API_VERSION = @MUTTER_PLUGIN_API_VERSION@ +MUTTER_PLUGIN_DIR = @MUTTER_PLUGIN_DIR@ +MUTTER_WAYLAND_CFLAGS = @MUTTER_WAYLAND_CFLAGS@ +MUTTER_WAYLAND_LIBS = @MUTTER_WAYLAND_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WAYLAND_PROTOCOLS_CFLAGS = @WAYLAND_PROTOCOLS_CFLAGS@ +WAYLAND_PROTOCOLS_DATADIR = @WAYLAND_PROTOCOLS_DATADIR@ +WAYLAND_PROTOCOLS_LIBS = @WAYLAND_PROTOCOLS_LIBS@ +WAYLAND_SCANNER = @WAYLAND_SCANNER@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +XMKMF = @XMKMF@ +XWAYLAND_PATH = @XWAYLAND_PATH@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +ZENITY = @ZENITY@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gsettingsschemadir = @gsettingsschemadir@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = man +EXTRA_DIST = dialogs.txt code-overview.txt \ + how-to-get-focus-right.txt rationales.txt + +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign doc/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/doc/code-overview.txt b/doc/code-overview.txt new file mode 100644 index 0000000..450f7a8 --- /dev/null +++ b/doc/code-overview.txt @@ -0,0 +1,185 @@ +This is not meant to be comprehensive by any means. Rather it is +meant as just a brief overview of some of the bigger structures and +files, with guides for a variety of task categories providing places +to start looking in the code and things to look for. + +Overview + Jobs of various files + Major data structures and their relationships + Getting started -- where to look + + +Jobs of various files + src/window.c is where all the guts of the window manager live. This is + basically the only remotely scary file. + + src/frames.c is the GtkWidget that handles drawing window frames. + + src/core.h defines the interface used by the GTK portion of the window + manager to talk to the other portions. There's some cruft in here that's + unused, since nearly all window operations have moved out of this file so + frameless apps can have window operations. + + src/ui.h defines the interface the plain Xlib portion of the window + manager uses to talk to the GTK portion. + + src/theme.c and src/theme-parser.c have the theme system; this is + well-modularized from the rest of the code, since the theme viewer app + links to these files in addition to the WM itself. + +Major data structures and their relationships + Major structs have a "Meta" prefix, thus MetaDisplay, MetaScreen, + MetaWindow, etc. This serves as a way of namespacing in C. It also has + the side effect of avoiding conflicts with common names that X already + uses such as Display, Screen, Window, etc. Note that when I refer to a + display below, I'm meaning a MetaDisplay and not a Display. + + Don't confuse displays and screens. While Metacity can run with multiple + displays, it is kind of useless since you might as well just run two + copies of Metacity. However, having multiple screens per display is + useful and increasingly common (known as "multiscreen" and "xinerama" + setups, where users make use of more than one monitor). You should + basically think of a display as a combination of one or more monitors + with a single keyboard (...and usually only one mouse). + + There is also a significant difference between multiscreen and xinerama + as well. Basically, each MetaScreen is a root window (root node in the + tree of windows). With Xinerama, a single root window appears to span + multiple monitors, whereas with multiscreen a root window is confined to + a single monitor. To re-emphasize the distinction between a display and + a screen, the pointer and keyboard are shared between all root windows + for a given display. + + The display keeps track of a lot of various global quantities, but in + particular has a compositor and a list (GList) of screens. + + A compositor is an opaque structure (only defined in compositor.c), + meaning that you'll only reference the API for it. It handles (or will + handle) cool stuff with the new X extensions, such as smooth resizing and + alpha transparency. + + A screen keeps track of a number of quantities as well, in particular a + stack and a list of workspaces. + + A stack is basically a list of windows, and the depth order they have + relative to each other (which thus determines which windows are on top + and which are obscured). + + A workspace mostly contains a list of windows for the workspace, but also + has a few other quantities as well (a list of struts which are areas + where windows should not be placed and an mru_list or "most recently used + window list"). + + A window has a huge list of quantities for keeping track of things about + a window on the screen. (We want to avoid making this list larger + because the memory for all these quantities is per window.) One item in + particular that a window has, though, is a frame. + + A frame is the decorations that surround the window (i.e. the titlebar and + the minimize and close buttons and the part that you can use to resize), + and contains a handful of variables related to that, but no other major + structures. + +Getting started -- where to look + Getting started on developing free software projects can often be like + being dropped off in a town that is unknown to you and being told to make + a map, when various road and building signs are missing or fading. To + try to alleviate that initial difficulty in orientation, below I list a + variety of general task categories with file, function, variable, and x + property names that may be useful to fixing bugs or writing features that + fall within that category. + + First, though, it's useful to note that most event and message passing + goes through display.c:event_callback(), so that's often a good place to + start reading for general familiarity with the code (actually, I'd + suggest skipping down to the first switch statement within that + function). Of course, not all events go through that function, as there + are a few other places that handle events too such as frames.c. + + Anyway, without further ado, here are the categories and (hopefully) + useful things to look at for each: + + Focus issues (i.e. issues with which window is active): + doc/how-to-get-focus-right.txt + meta_workspace_focus_default_window + _NET_ACTIVE_WINDOW + _NET_WM_USER_TIME + meta_window_focus + meta_display_(set_input|focus_the_no)_focus_window + XSetInputFocus (only for purposes of understanding how X focus/input works) + CurrentTime (mostly, you should just think "Bad; don't use it") + + Compositor stuff (X extension for eye candy like transparency): + compositor.c + The luminocity module in CVS + + Window depth (i.e. stacking or lowering/raising) issues: + stack.c + _NET_CLIENT_LIST_STACKING + transient_for + WM_TRANSIENT_FOR + meta_window_(raise|lower) + _NET_WM_WINDOW_TYPE + _NET_WM_MOUSE_ACTION/_NET_WM_TAKE_ACTIVITY? (aren't yet in EWMH) + + Window placement issues: + place.c + constraints.c + _NET_WM_STRUT + WM_SIZE_HINTS + + Moving and resizing issues: + constraints.c + update_move + update_resize + meta_window_handle_mouse_grab_op_event + _NET_MOVERESIZE_WINDOW + _NET_WM_STRUT + + Drag and drop issues: + the XDND protocol (see http://www.newplanetsoftware.com/xdnd/ and + http://freedesktop.org/Standards/XDND) + _NET_WM_MOUSE_ACTION/_NET_WM_TAKE_ACTIVITY (aren't yet in EWMH) + A general pointer: what causes the difficulty here is that when the + application receives a mouse click to start a drag, it does a grab + so that the window manager doesn't get any further events; thus + correcting things require standards so that applications and window + managers can collaborate correctly + + Theme issues: ??? + doc/theme-format.txt + theme.c + theme-parser.c + (ui.c, core.c, frames.c, frame.c? I dunno...) + + Session management issues: ??? + session.c + http://www.x.org/X11R6.8.1/doc/SM/xsmp.pdf ? + http://www.x.org/X11R6.8.1/doc/SM/SMlib.pdf ? + meta_window_apply_session_info + + Tasklist and Workspace switcher issues: + window-props.c + various functions in screen.c (especially ones using XChangeProperty) + xprops.c + The libwnck module in cvs + meta_window_client_message + Lots of the EWMH + + Window and workspace selection/changing issues: + tabpopup.c + keybindings.c, functions: *_workspace*, *_tab_* + meta_screen_ensure_*_popup + display.c, functions: *_tab* + + Key and mouse binding actions: + keybindings.c + meta_frames_button_(press|release)_event + display.c: event_callback, but only the (Key|Button)_(Press|Release) cases + + Xinerama and multiscreen: ??? + In general, just search for Xinerama, but in particular see + screen.c + window.c + place.c + constraints.c diff --git a/doc/dialogs.txt b/doc/dialogs.txt new file mode 100644 index 0000000..1a28e6a --- /dev/null +++ b/doc/dialogs.txt @@ -0,0 +1,32 @@ +Dialogs which have no transient parent or root window being +their tranisent parent are the ones which will be visible in +the tasklist. + +All such dialogs will be *always* on top of the window +group i.e they would transients for the whole group. + + +1) Modal dialogs + + + * If you wish to open another window from a modal dialog + + open *only* a modal dialog and set it's transient parent. + + +2) Normal dialog + + + without transient parent + + * If you wish to open another window from a normal dialog + + open either a normal dialog or a modal dialog only. + Set the transient parent for the child dialog if you do not + want them to be transient for all the other windows in the group. + + with transient parent + + * If you wish to open another window from a normal dialog + + you could open any type of window. diff --git a/doc/how-to-get-focus-right.txt b/doc/how-to-get-focus-right.txt new file mode 100644 index 0000000..574a3a5 --- /dev/null +++ b/doc/how-to-get-focus-right.txt @@ -0,0 +1,252 @@ +To make choice of focus window consistent for each focus method, a +number of guidelines should be followed. (For purposes of discussion +here, I'm excluding things like the panel and the desktop from +"windows". It is technically incorrect to do this, but I'm lazy and +"windows" is shorter than something like "normal windows". See the +end of the discussion for how these special cases are handled.) The +basics are easy: + +Focus method Behavior + click When a user clicks on a window, focus it + sloppy When an EnterNotify is received, focus the window + mouse Same as sloppy, but also defocus when mouse enters DESKTOP + window + +Note that these choices (along with the choice that clicking on a +window raises it for the click focus method) introduces the following +invariants for focus from mouse activity: + +Focus method Invariant + click The window on top is focused + sloppy If the mouse is in a window, then it is focused; if the + mouse is not in a window, then the most recently used + window is focused. + mouse If the mouse is in a non-DESKTOP window, then it is focused; + otherwise, the designated "no_focus_window" is focused + +However, there are a number of cases where the current focus window +becomes invalid and another should be chosen. Some examples are when +a focused window is closed or minimized, or when the user changes +workspaces. In these cases, there needs to be a rule consistent with +the above about the new window to choose. + +Focus method Behavior + click Focus the window on top + sloppy Focus the window containing the pointer if there is such + a window, otherwise focus the most recently used window. + mouse Focus the non-DESKTOP window containing the pointer if + there is one, otherwise focus the designated + "no_focus_window". + +Note that "most recently used window", as used here, has a slightly +different connotation than "most recent to have keyboard focus". This +is because when a user activates a window that is a transient, its +ancestor(s) should be considered to be more recently used than other +windows that have had the keyboard focus more recently. (See bug +157360; this may mean that the alt-tab order should also change +simultaneously, although the current implementation does not do that.) + +Also, sometimes a new window will be mapped (e.g. unminimizing a +window or launching a new application). Most users want to interact +with new windows right away, so these should typically be focused. +This does conflict with the invariants for sloppy and mouse focus +modes, so this wouldn't be true for a strict-pointer-focus mode. For +all other modes (non-strict-pointer-focus modes), there are only two +cases in which a new window shouldn't be focused: + + 1) If the window takes a while to launch and the user starts + interacting with a different application, the new window should + not take focus. + 2) If the window that will appear was not launched by the user + (error dialogs, instant messaging windows, etc.), then the window + should not take focus when it appears. + +To handle these cases, Metacity compares timestamps of the event that +caused the launch and the timestamp of the last interaction with the +focused window. (Case 2 is handled by the application providing a +special timestamp of 0 for the launch time, which ensures that the +window that appears doesn't get focus) + +If the newly launched window isn't focused, some things should be done +to alert the user that there is a window to work with: + 1) The _NET_WM_DEMANDS_ATTENTION hint should be set + 2) If the new window isn't modal for the focused window, it should + appear below the focused window so that it doesn't obscure the + focused window that the user is interacting with. + 3) If the new window is modal to the focused window, the currently + focused window should lose focus but the modal window should + appear on top. + +Additionally, the user may decide to use the keyboard instead of the mouse +to navigate between windows (referred to as "keynav"). This poses no +problems for click-to-focus (because the same invariant can be +maintained), but for sloppy and mouse focus it requires extra work to +attempt to handle the INHERENTLY CONFLICTING CONSTRAINTS. Metacity does +this by having a mouse_mode boolean used to determine which of the two +sets of invariants holds. This mode is set according to which method was +most recently used to choose a focus window: + 1) When receiving EnterNotify events from mouse movement, set + mouse_mode to TRUE. + 2) When using keynav to choose a focus window (e.g. alt-tab, alt-esc, + alt-f2, move-window-to-workspace keybindings), set mouse_mode to FALSE. + 3) When handling events that don't choose a focus window but rather need + a focus_window chosen for them (e.g. switch-to-workspace keybindings), + don't change the mouse_mode and just use the current value. +Note that grabs present a special case since they can generate EnterNotify +and LeaveNotify events without using the mouse, thus these events should be +ignored when the crossing mode is NotifyGrab or NotifyUngrab. THIS +MOUSENAV/KEYNAV MODERATION METHOD IS NOT PERFECT--there are corner cases +when trying to mix-and-match between mousenav and keynav simultaneously +that cause problems; but it appears to be the most reasonable tradeoff and +works well in most cases, especially if the user sticks to just mousenav +for a long time or just keynav for a long time. + +Finally, windows of type WM_DOCK or WM_DESKTOP (e.g. the desktop and +the panel) present a special case, at least partially due to the lack +of decorations. For WM_DESKTOP windows, we only focus them if the +user explicitly requests it (e.g. clicks on the window, uses +Ctrl-Alt-Tab to navigate to it, uses a keybinding to show the desktop, +etc.). For WM_DOCK windows, we do not focus unless we receive a very +explicit request (e.g. Ctrl-Alt-Tab or a _NET_ACTIVE_WINDOW message; +not normal clicks). + + + + +To read more about the bugs that inspired these choices: + - When a focused window becomes invalid and another should be chosen + http://bugzilla.gnome.org/show_bug.cgi?id=135810 + - When a new window is mapped + http://bugzilla.gnome.org/show_bug.cgi?id=118372 + Also, the EWMH spec, especially the parts relating to _NET_WM_USER_TIME + - Modal vs. non-modal dialogs that get denied focus when mapped + http://bugzilla.gnome.org/show_bug.cgi?id=151996 + - Mousenav vs. Keynav in mouse and sloppy focus modes + http://bugzilla.gnome.org/show_bug.cgi?id=167545 + http://bugzilla.gnome.org/show_bug.cgi?id=101190 + http://bugzilla.gnome.org/show_bug.cgi?id=357695 + - Not focusing panels + http://bugzilla.gnome.org/show_bug.cgi?id=160470 + http://bugzilla.gnome.org/show_bug.cgi?id=120100 + +There were many bugs which had to be fixed to get all the above +working; they helped form these policies and/or show the difficulties +in implementing this policy (my apologies in advance for producing a +list heavily lopsided to what I've done; it's just that these bugs are +the ones I'm the most familiar with): + bug 72314 ignore LeaveNotify events from grabs + bug 82921 focus windows on map + bug 87531 only show focus for sticky windows on active workspace (pager) + bug 94545 focus window on workspace switch is non-deterministic + bug 95747 should ignore EnterNotify events with NotifyInferior detail set + bug 97635 sticky windows always keep focus when switching workspaces + bug 102665 a window unminimized from the tasklist should be focused + bug 107347 focus windows that manually position themselves too + bug 108643 focus in MRU order instead of stack order + bug 110970 moving a window to another workspace loses focus + bug 112031 closing a dialog can result in a strange focus window + bug 115650 add _NET_WM_USER_TIME support to gtk+ (see also 150502) + bug 120100 panel shouldn't be focused after workspace applet usage + bug 123803 need final EnterNotify after workspace switch (see also 124798) + bug 124981 focus clicked window in pager only if on current workspace + bug 125492 catch the xserver unfocusing everything and fix its braindeadedness + bug 128200 focus correct window on libwnck window minimize (see 107681 too) + bug 131582 fix race condition on window minimize/close + bug 133120 wrong window focused when changing workspaces + bug 135024 _NET_ACTIVE_WINDOW messages need timestamps + bug 135786 middle-clicking on focused window to lower it should defocus too + bug 136581 window minimization vs. activation for mouse focus + bug 144900 fix focus choice on "un-showing" the desktop + bug 147475 don't lock keyboard on workspace change + bug 148364 DEMANDS_ATTENTION support for metacity & libwnck (and other stuff) + bug 149028 focus-stealing-prevention for metacity-dialog (and other stuff) + bug 149366 windows denied focus on map occur in wrong order in alt-tab list + bug 149543 consistent focus window when unshowing desktop + bug 149589 race in focus choice from libwnck messages + bug 150271 make sure "run application" dialog gets focused + bug 150668 update gtk+ _NET_ACTIVE_WINDOW support + bug 151245 application startup notification forwarding (partially rejected) + bug 151984 Soeren's idea--backup timestamp when startup notification not used + bug 151990 prevent focus inconsistencies by only providing one focus method + bug 151996 modal dialogs denied focus should not be lowered + bug 152000 fix race on window close followed by rapid mouse movement + bug 152004 ways to handle new window versus mouse invariants + bug 153220 catch the root window getting focus and reset to default window + bug 157360 focus parents of dismissed transient windows in preference to + the window that most recently had focus + bug 159257 focus the desktop when showing it + bug 160470 don't focus panels on click + bug 163450 correct highlighting in workspace switcher popup + bug 164716 refuse to focus a window with a modal transient, and focus + the transient instead + bug 166524 avoid new windows being obscured by the focus window + bug 167545 mousenav vs. keynav in mouse and sloppy focus modes + + + +Addendum on sloppy and mouse focus + You may occasionally hear people refer to sloppy or mouse focus + modes as inherently buggy. This is what they mean by that: + + 1) Keynav doesn't maintain the same invariants as mouse navigation + for these focus modes; switching back and forth between + navigation methods, therefore, may have or appear to have + inconsistencies. Examples: + a) If the user uses Alt-Tab to change the window with focus, then + starts to move the mouse, at that moment the window where the + mouse is does not have focus. + b) Users expect that a workspace they previously used will not + change when the return to it. This means things like window + position and stacking order, but also the focus window. + Unfortunately, using the original focus window (which would be + the most recently used window on that workspace) will + sometimes conflict with the invariants for mouse and sloppy + focus modes. Users are much more surprised by the invariant + being broken than by having the focus window changed (see bug + 94545 and probably others), so we maintain the invariant. + This only matters when using Ctrl-Alt-Arrow to switch + workspaces instead of clicking in the workspace switcher, so + this really is a keynav vs mouse issue. Either that, or a + windows-are-being-mapped exception. ;-) + c) Opening a menu, then moving the mouse to a different window, + and then pressing escape to dismiss the menu will result in + the window containing the mouse not being focused. This is + actually correct behavior (because pressing escape shows that + the user is using key navigation to interact with the window + containing the menu) but is one of those hard-to-get-right + keynav and mouse focus mixture cases. (See bug 101190 for + more details) + d) Similar to (c), moving the mouse off the menu doesn't immediately + focus the window that the mouse goes over, due to an application + grab (we couldn't change this and wouldn't want to, but + technically it does break the invariant). + e) If mouse_mode is off and the user does something to cause focus to + change (e.g. switch workspaces, close or minimize a window, etc.) + and simultaneously tries to move the mouse, the choice of which + window to focus is inherently race-y. (You probably can't satisfy + both keynav and mousenav invariants simultaneously...) + 2) The sloppy/mouse invariants are often not strictly maintained; + for example, we provide an exception to the invariant for newly + mapped windows. (Most find that not allowing this exception is + confusing) + 3) There are an awful lot of little cases to handle to get any focus + mode right, even for click-to-focus. Since mouse and sloppy + focus have sometimes been hard to even determine what correct + behavior is, it is much harder to get them completely right. + Plus mouse and sloppy focus users are a minority, decreasing the + motivation of window manager implementors to get those focus + modes right. + 4) Because of -1-, -2-, and -3-, implementations are often buggy or + inconsistent and people form their opinions from usage of these + implementations. + 5) Sloppy focus suffers from a bit of a discoverability problem (for + example, I have seen a scientist sit down to a computer for which + sloppy focus was in use and take a few minutes before figuring + out how window activation worked; granted the layout of the + windows in that situation was a bit unusual but it still + illustrates that sloppy focus is harder than it should be to + figure out). Mouse focus solves this problem; however, people + that have experience with other computing environments are + accustomed to being able to move their mouse outside the window + they are working with and still continue interacting with that + window, which conflicts with mouse focus. diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am new file mode 100644 index 0000000..088967f --- /dev/null +++ b/doc/man/Makefile.am @@ -0,0 +1,3 @@ +man_MANS = mutter.1 + +EXTRA_DIST = $(man_MANS) diff --git a/doc/man/Makefile.in b/doc/man/Makefile.in new file mode 100644 index 0000000..d938619 --- /dev/null +++ b/doc/man/Makefile.in @@ -0,0 +1,586 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = doc/man +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +man1dir = $(mandir)/man1 +am__installdirs = "$(DESTDIR)$(man1dir)" +NROFF = nroff +MANS = $(man_MANS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CVT = @CVT@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_COMPILE_SCHEMAS = @GLIB_COMPILE_SCHEMAS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNOME_KEYBINDINGS_KEYSDIR = @GNOME_KEYBINDINGS_KEYSDIR@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GSETTINGS_DISABLE_SCHEMAS_COMPILE = @GSETTINGS_DISABLE_SCHEMAS_COMPILE@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +META_GIR = @META_GIR@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +MUTTER_CFLAGS = @MUTTER_CFLAGS@ +MUTTER_LIBS = @MUTTER_LIBS@ +MUTTER_MAJOR_VERSION = @MUTTER_MAJOR_VERSION@ +MUTTER_MICRO_VERSION = @MUTTER_MICRO_VERSION@ +MUTTER_MINOR_VERSION = @MUTTER_MINOR_VERSION@ +MUTTER_NATIVE_BACKEND_CFLAGS = @MUTTER_NATIVE_BACKEND_CFLAGS@ +MUTTER_NATIVE_BACKEND_LIBS = @MUTTER_NATIVE_BACKEND_LIBS@ +MUTTER_PLUGIN_API_VERSION = @MUTTER_PLUGIN_API_VERSION@ +MUTTER_PLUGIN_DIR = @MUTTER_PLUGIN_DIR@ +MUTTER_WAYLAND_CFLAGS = @MUTTER_WAYLAND_CFLAGS@ +MUTTER_WAYLAND_LIBS = @MUTTER_WAYLAND_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WAYLAND_PROTOCOLS_CFLAGS = @WAYLAND_PROTOCOLS_CFLAGS@ +WAYLAND_PROTOCOLS_DATADIR = @WAYLAND_PROTOCOLS_DATADIR@ +WAYLAND_PROTOCOLS_LIBS = @WAYLAND_PROTOCOLS_LIBS@ +WAYLAND_SCANNER = @WAYLAND_SCANNER@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +XMKMF = @XMKMF@ +XWAYLAND_PATH = @XWAYLAND_PATH@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +ZENITY = @ZENITY@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gsettingsschemadir = @gsettingsschemadir@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +man_MANS = mutter.1 +EXTRA_DIST = $(man_MANS) +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/man/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign doc/man/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-man1: $(man_MANS) + @$(NORMAL_INSTALL) + @list1=''; \ + list2='$(man_MANS)'; \ + test -n "$(man1dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.1[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ + done; } + +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list=''; test -n "$(man1dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.1[a-z]*$$/p'; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(MANS) +installdirs: + for dir in "$(DESTDIR)$(man1dir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-man + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: install-man1 + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-man + +uninstall-man: uninstall-man1 + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-man1 install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags-am uninstall uninstall-am uninstall-man \ + uninstall-man1 + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/doc/man/mutter.1 b/doc/man/mutter.1 new file mode 100644 index 0000000..998d0f8 --- /dev/null +++ b/doc/man/mutter.1 @@ -0,0 +1,60 @@ +.\" Hey, EMACS: -*- nroff -*- +.\" First parameter, NAME, should be all caps +.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection +.\" other parameters are allowed: see man(7), man(1) +.TH MUTTER 1 "11 February 2006" +.\" Please adjust this date whenever revising the manpage. +.\" +.\" Some roff macros, for reference: +.\" .nh disable hyphenation +.\" .hy enable hyphenation +.\" .ad l left justify +.\" .ad b justify to both left and right margins +.\" .nf disable filling +.\" .fi enable filling +.\" .br insert line break +.\" .sp insert n+1 empty lines +.\" for manpage-specific macros, see man(7) +.SH NAME +MUTTER \- Clutter based compositing GTK2 Window Manager +.SH SYNOPSIS +.B mutter +[\-\-display=\fIDISPLAY\fP] [\-\-replace] [\-\-sm\-client\-id=\fIID\fP] [\-\-sm\-disable] [\-\-sm\-save\-file=\fIFILENAME\fP] [\-\-version] [\-\-help] +.SH DESCRIPTION +This manual page documents briefly +.B mutter\fP. +.PP +.\" TeX users may be more comfortable with the \fB\fP and +.\" \fI\fP escape sequences to invode bold face and italics, +.\" respectively. +\fBmutter\fP is a minimal X window manager aimed at nontechnical users and is designed to integrate well with the GNOME desktop. \fBmutter\fP lacks some features that may be expected by traditional UNIX or other technical users; these users may want to investigate other available window managers for use with GNOME or standalone. +.SH OPTIONS +.TP +.B \-\-display=DISPLAY +Connect to X display \fIDISPLAY\fP. +.TP +.B \-\-replace +a window manager which is running is replaced by \fBmutter\fP. Users are encouraged to change the GNOME window manager by running the new WM with the --replace or -replace option, and subsequently saving the session. +.TP +.B \-\-sm\-client\-id=ID +Specify a session management \fIID\fP. +.TP +.B \-\-sm\-disable +Disable the session management. +.TP +.B \-\-sm\-save\-file=FILENAME +Load a session from \fIFILENAME\fP. +.TP +.B \-\-version +Print the version number. +.TP +.B \-?, \-\-help +Show summary of options. +.SH CONFIGURATION +\fBmutter\fP configuration can be found under \fIPreferences\fP->\fIWindows\fP and \fIPreferences\fP->\fIKeyboard Shortcuts\fP on the menu-panel. Advanced configuration can be achieved directly through gsettings. +.SH SEE ALSO +.BR mutter-message (1) +.SH AUTHOR +The original manual page was written by Thom May . It was updated by Akira TAGOH +for the Debian GNU/Linux system (with permission to use by others), and then updated by Luke Morton and Philip O'Brien +for inclusion in mutter. diff --git a/doc/rationales.txt b/doc/rationales.txt new file mode 100644 index 0000000..600d2d5 --- /dev/null +++ b/doc/rationales.txt @@ -0,0 +1,79 @@ + +History +==== + +Focus issues: + see doc/how-to-get-focus-right.txt + +Keep panel always on top: + http://bugzilla.gnome.org/show_bug.cgi?id=81551 + +Edge flipping: + http://bugzilla.gnome.org/show_bug.cgi?id=82917 + +Opaque resize: + http://bugzilla.gnome.org/show_bug.cgi?id=92618 + +Alt+click to move/resize: + http://bugzilla.gnome.org/show_bug.cgi?id=101151 + https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=80918 + +minimized windows in Alt+tab: + http://bugzilla.gnome.org/show_bug.cgi?id=89416 + +dialogs above entire app group: + http://bugzilla.gnome.org/show_bug.cgi?id=88926 + +display window size/position: + http://bugzilla.gnome.org/show_bug.cgi?id=85213 + http://bugzilla.gnome.org/show_bug.cgi?id=106645 + http://bugzilla.gnome.org/show_bug.cgi?id=130821 + +configure click actions, alt+click: + http://bugzilla.gnome.org/show_bug.cgi?id=83210 + +system modal dialogs: + http://bugzilla.gnome.org/show_bug.cgi?id=83357 + +workspace wrapping: + http://bugzilla.gnome.org/show_bug.cgi?id=89315 + +raise windows on click: + http://bugzilla.gnome.org/show_bug.cgi?id=326156 + http://bugzilla.gnome.org/show_bug.cgi?id=86108 + http://bugzilla.gnome.org/show_bug.cgi?id=115072 + http://bugzilla.gnome.org/show_bug.cgi?id=115753 + +Pointer warping: + http://bugzilla.gnome.org/show_bug.cgi?id=134353 + http://bugzilla.gnome.org/show_bug.cgi?id=134352 + (Think about tasklist & window selector too; this would be a very bad idea) + + +Bugs for easy dupe-finding that seem to be hard to find otherwise: +=== +Applications opening in wrong workspace: + http://bugzilla.gnome.org/show_bug.cgi?id=160687 + + +Tracking bugs +==== + + revise theme format: http://bugzilla.gnome.org/show_bug.cgi?id=102547 + session management: http://bugzilla.gnome.org/show_bug.cgi?id=107063 + focus-stealing-prevention: http://bugzilla.gnome.org/show_bug.cgi?id=149028 + other focus bugs: http://bugzilla.gnome.org/show_bug.cgi?id=155450 + drag-and-drop: http://bugzilla.gnome.org/show_bug.cgi?id=155451 + raising/stacking: http://bugzilla.gnome.org/show_bug.cgi?id=155452 + tasklist/workspace switcher: http://bugzilla.gnome.org/show_bug.cgi?id=155453 + window/workspace selection: http://bugzilla.gnome.org/show_bug.cgi?id=155456 + key/mouse-binding actions: http://bugzilla.gnome.org/show_bug.cgi?id=155457 +moving/resizing (constraints): http://bugzilla.gnome.org/show_bug.cgi?id=155458 + window placement: http://bugzilla.gnome.org/show_bug.cgi?id=155460 + logout/system-monitor keys: http://bugzilla.gnome.org/show_bug.cgi?id=155462 + modal dialogs: http://bugzilla.gnome.org/show_bug.cgi?id=164841 + multi-head sans xinerama: http://bugzilla.gnome.org/show_bug.cgi?id=324772 + xinerama: http://bugzilla.gnome.org/show_bug.cgi?id=324773 + output-only windows: http://bugzilla.gnome.org/show_bug.cgi?id=340584 + allowed actions/window-type: http://bugzilla.gnome.org/show_bug.cgi?id=340682 + EWMH/ICCCM compliance: http://bugzilla.gnome.org/show_bug.cgi?id=340691 diff --git a/m4/gettext.m4 b/m4/gettext.m4 new file mode 100644 index 0000000..b522a37 --- /dev/null +++ b/m4/gettext.m4 @@ -0,0 +1,405 @@ +# gettext.m4 serial 67 (gettext-0.19.6) +dnl Copyright (C) 1995-2014 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2006, 2008-2010. + +dnl Macro to add for using GNU gettext. + +dnl Usage: AM_GNU_GETTEXT([INTLSYMBOL], [NEEDSYMBOL], [INTLDIR]). +dnl INTLSYMBOL can be one of 'external', 'no-libtool', 'use-libtool'. The +dnl default (if it is not specified or empty) is 'no-libtool'. +dnl INTLSYMBOL should be 'external' for packages with no intl directory, +dnl and 'no-libtool' or 'use-libtool' for packages with an intl directory. +dnl If INTLSYMBOL is 'use-libtool', then a libtool library +dnl $(top_builddir)/intl/libintl.la will be created (shared and/or static, +dnl depending on --{enable,disable}-{shared,static} and on the presence of +dnl AM-DISABLE-SHARED). If INTLSYMBOL is 'no-libtool', a static library +dnl $(top_builddir)/intl/libintl.a will be created. +dnl If NEEDSYMBOL is specified and is 'need-ngettext', then GNU gettext +dnl implementations (in libc or libintl) without the ngettext() function +dnl will be ignored. If NEEDSYMBOL is specified and is +dnl 'need-formatstring-macros', then GNU gettext implementations that don't +dnl support the ISO C 99 formatstring macros will be ignored. +dnl INTLDIR is used to find the intl libraries. If empty, +dnl the value '$(top_builddir)/intl/' is used. +dnl +dnl The result of the configuration is one of three cases: +dnl 1) GNU gettext, as included in the intl subdirectory, will be compiled +dnl and used. +dnl Catalog format: GNU --> install in $(datadir) +dnl Catalog extension: .mo after installation, .gmo in source tree +dnl 2) GNU gettext has been found in the system's C library. +dnl Catalog format: GNU --> install in $(datadir) +dnl Catalog extension: .mo after installation, .gmo in source tree +dnl 3) No internationalization, always use English msgid. +dnl Catalog format: none +dnl Catalog extension: none +dnl If INTLSYMBOL is 'external', only cases 2 and 3 can occur. +dnl The use of .gmo is historical (it was needed to avoid overwriting the +dnl GNU format catalogs when building on a platform with an X/Open gettext), +dnl but we keep it in order not to force irrelevant filename changes on the +dnl maintainers. +dnl +AC_DEFUN([AM_GNU_GETTEXT], +[ + dnl Argument checking. + ifelse([$1], [], , [ifelse([$1], [external], , [ifelse([$1], [no-libtool], , [ifelse([$1], [use-libtool], , + [errprint([ERROR: invalid first argument to AM_GNU_GETTEXT +])])])])]) + ifelse(ifelse([$1], [], [old])[]ifelse([$1], [no-libtool], [old]), [old], + [AC_DIAGNOSE([obsolete], [Use of AM_GNU_GETTEXT without [external] argument is deprecated.])]) + ifelse([$2], [], , [ifelse([$2], [need-ngettext], , [ifelse([$2], [need-formatstring-macros], , + [errprint([ERROR: invalid second argument to AM_GNU_GETTEXT +])])])]) + define([gt_included_intl], + ifelse([$1], [external], + ifdef([AM_GNU_GETTEXT_][INTL_SUBDIR], [yes], [no]), + [yes])) + define([gt_libtool_suffix_prefix], ifelse([$1], [use-libtool], [l], [])) + gt_NEEDS_INIT + AM_GNU_GETTEXT_NEED([$2]) + + AC_REQUIRE([AM_PO_SUBDIRS])dnl + ifelse(gt_included_intl, yes, [ + AC_REQUIRE([AM_INTL_SUBDIR])dnl + ]) + + dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + + dnl Sometimes libintl requires libiconv, so first search for libiconv. + dnl Ideally we would do this search only after the + dnl if test "$USE_NLS" = "yes"; then + dnl if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then + dnl tests. But if configure.in invokes AM_ICONV after AM_GNU_GETTEXT + dnl the configure script would need to contain the same shell code + dnl again, outside any 'if'. There are two solutions: + dnl - Invoke AM_ICONV_LINKFLAGS_BODY here, outside any 'if'. + dnl - Control the expansions in more detail using AC_PROVIDE_IFELSE. + dnl Since AC_PROVIDE_IFELSE is only in autoconf >= 2.52 and not + dnl documented, we avoid it. + ifelse(gt_included_intl, yes, , [ + AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) + ]) + + dnl Sometimes, on Mac OS X, libintl requires linking with CoreFoundation. + gt_INTL_MACOSX + + dnl Set USE_NLS. + AC_REQUIRE([AM_NLS]) + + ifelse(gt_included_intl, yes, [ + BUILD_INCLUDED_LIBINTL=no + USE_INCLUDED_LIBINTL=no + ]) + LIBINTL= + LTLIBINTL= + POSUB= + + dnl Add a version number to the cache macros. + case " $gt_needs " in + *" need-formatstring-macros "*) gt_api_version=3 ;; + *" need-ngettext "*) gt_api_version=2 ;; + *) gt_api_version=1 ;; + esac + gt_func_gnugettext_libc="gt_cv_func_gnugettext${gt_api_version}_libc" + gt_func_gnugettext_libintl="gt_cv_func_gnugettext${gt_api_version}_libintl" + + dnl If we use NLS figure out what method + if test "$USE_NLS" = "yes"; then + gt_use_preinstalled_gnugettext=no + ifelse(gt_included_intl, yes, [ + AC_MSG_CHECKING([whether included gettext is requested]) + AC_ARG_WITH([included-gettext], + [ --with-included-gettext use the GNU gettext library included here], + nls_cv_force_use_gnu_gettext=$withval, + nls_cv_force_use_gnu_gettext=no) + AC_MSG_RESULT([$nls_cv_force_use_gnu_gettext]) + + nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" + if test "$nls_cv_force_use_gnu_gettext" != "yes"; then + ]) + dnl User does not insist on using GNU NLS library. Figure out what + dnl to use. If GNU gettext is available we use this. Else we have + dnl to fall back to GNU NLS library. + + if test $gt_api_version -ge 3; then + gt_revision_test_code=' +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) +#endif +changequote(,)dnl +typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; +changequote([,])dnl +' + else + gt_revision_test_code= + fi + if test $gt_api_version -ge 2; then + gt_expression_test_code=' + * ngettext ("", "", 0)' + else + gt_expression_test_code= + fi + + AC_CACHE_CHECK([for GNU gettext in libc], [$gt_func_gnugettext_libc], + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern int *_nl_domain_bindings; + ]], + [[ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_bindings + ]])], + [eval "$gt_func_gnugettext_libc=yes"], + [eval "$gt_func_gnugettext_libc=no"])]) + + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then + dnl Sometimes libintl requires libiconv, so first search for libiconv. + ifelse(gt_included_intl, yes, , [ + AM_ICONV_LINK + ]) + dnl Search for libintl and define LIBINTL, LTLIBINTL and INCINTL + dnl accordingly. Don't use AC_LIB_LINKFLAGS_BODY([intl],[iconv]) + dnl because that would add "-liconv" to LIBINTL and LTLIBINTL + dnl even if libiconv doesn't exist. + AC_LIB_LINKFLAGS_BODY([intl]) + AC_CACHE_CHECK([for GNU gettext in libintl], + [$gt_func_gnugettext_libintl], + [gt_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $INCINTL" + gt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBINTL" + dnl Now see whether libintl exists and does not depend on libiconv. + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *); + ]], + [[ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") + ]])], + [eval "$gt_func_gnugettext_libintl=yes"], + [eval "$gt_func_gnugettext_libintl=no"]) + dnl Now see whether libintl exists and depends on libiconv. + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" != yes; } && test -n "$LIBICONV"; then + LIBS="$LIBS $LIBICONV" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *); + ]], + [[ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") + ]])], + [LIBINTL="$LIBINTL $LIBICONV" + LTLIBINTL="$LTLIBINTL $LTLIBICONV" + eval "$gt_func_gnugettext_libintl=yes" + ]) + fi + CPPFLAGS="$gt_save_CPPFLAGS" + LIBS="$gt_save_LIBS"]) + fi + + dnl If an already present or preinstalled GNU gettext() is found, + dnl use it. But if this macro is used in GNU gettext, and GNU + dnl gettext is already preinstalled in libintl, we update this + dnl libintl. (Cf. the install rule in intl/Makefile.in.) + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" = "yes"; } \ + || { { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; } \ + && test "$PACKAGE" != gettext-runtime \ + && test "$PACKAGE" != gettext-tools; }; then + gt_use_preinstalled_gnugettext=yes + else + dnl Reset the values set by searching for libintl. + LIBINTL= + LTLIBINTL= + INCINTL= + fi + + ifelse(gt_included_intl, yes, [ + if test "$gt_use_preinstalled_gnugettext" != "yes"; then + dnl GNU gettext is not found in the C library. + dnl Fall back on included GNU gettext library. + nls_cv_use_gnu_gettext=yes + fi + fi + + if test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Mark actions used to generate GNU NLS library. + BUILD_INCLUDED_LIBINTL=yes + USE_INCLUDED_LIBINTL=yes + LIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LIBICONV $LIBTHREAD" + LTLIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LTLIBICONV $LTLIBTHREAD" + LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'` + fi + + CATOBJEXT= + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Mark actions to use GNU gettext tools. + CATOBJEXT=.gmo + fi + ]) + + if test -n "$INTL_MACOSX_LIBS"; then + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Some extra flags are needed during linking. + LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" + LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" + fi + fi + + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + AC_DEFINE([ENABLE_NLS], [1], + [Define to 1 if translation of program messages to the user's native language + is requested.]) + else + USE_NLS=no + fi + fi + + AC_MSG_CHECKING([whether to use NLS]) + AC_MSG_RESULT([$USE_NLS]) + if test "$USE_NLS" = "yes"; then + AC_MSG_CHECKING([where the gettext function comes from]) + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + gt_source="external libintl" + else + gt_source="libc" + fi + else + gt_source="included intl directory" + fi + AC_MSG_RESULT([$gt_source]) + fi + + if test "$USE_NLS" = "yes"; then + + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + AC_MSG_CHECKING([how to link with libintl]) + AC_MSG_RESULT([$LIBINTL]) + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCINTL]) + fi + + dnl For backward compatibility. Some packages may be using this. + AC_DEFINE([HAVE_GETTEXT], [1], + [Define if the GNU gettext() function is already present or preinstalled.]) + AC_DEFINE([HAVE_DCGETTEXT], [1], + [Define if the GNU dcgettext() function is already present or preinstalled.]) + fi + + dnl We need to process the po/ directory. + POSUB=po + fi + + ifelse(gt_included_intl, yes, [ + dnl If this is used in GNU gettext we have to set BUILD_INCLUDED_LIBINTL + dnl to 'yes' because some of the testsuite requires it. + if test "$PACKAGE" = gettext-runtime || test "$PACKAGE" = gettext-tools; then + BUILD_INCLUDED_LIBINTL=yes + fi + + dnl Make all variables we use known to autoconf. + AC_SUBST([BUILD_INCLUDED_LIBINTL]) + AC_SUBST([USE_INCLUDED_LIBINTL]) + AC_SUBST([CATOBJEXT]) + + dnl For backward compatibility. Some configure.ins may be using this. + nls_cv_header_intl= + nls_cv_header_libgt= + + dnl For backward compatibility. Some Makefiles may be using this. + DATADIRNAME=share + AC_SUBST([DATADIRNAME]) + + dnl For backward compatibility. Some Makefiles may be using this. + INSTOBJEXT=.mo + AC_SUBST([INSTOBJEXT]) + + dnl For backward compatibility. Some Makefiles may be using this. + GENCAT=gencat + AC_SUBST([GENCAT]) + + dnl For backward compatibility. Some Makefiles may be using this. + INTLOBJS= + if test "$USE_INCLUDED_LIBINTL" = yes; then + INTLOBJS="\$(GETTOBJS)" + fi + AC_SUBST([INTLOBJS]) + + dnl Enable libtool support if the surrounding package wishes it. + INTL_LIBTOOL_SUFFIX_PREFIX=gt_libtool_suffix_prefix + AC_SUBST([INTL_LIBTOOL_SUFFIX_PREFIX]) + ]) + + dnl For backward compatibility. Some Makefiles may be using this. + INTLLIBS="$LIBINTL" + AC_SUBST([INTLLIBS]) + + dnl Make all documented variables known to autoconf. + AC_SUBST([LIBINTL]) + AC_SUBST([LTLIBINTL]) + AC_SUBST([POSUB]) +]) + + +dnl gt_NEEDS_INIT ensures that the gt_needs variable is initialized. +m4_define([gt_NEEDS_INIT], +[ + m4_divert_text([DEFAULTS], [gt_needs=]) + m4_define([gt_NEEDS_INIT], []) +]) + + +dnl Usage: AM_GNU_GETTEXT_NEED([NEEDSYMBOL]) +AC_DEFUN([AM_GNU_GETTEXT_NEED], +[ + m4_divert_text([INIT_PREPARE], [gt_needs="$gt_needs $1"]) +]) + + +dnl Usage: AM_GNU_GETTEXT_VERSION([gettext-version]) +AC_DEFUN([AM_GNU_GETTEXT_VERSION], []) + + +dnl Usage: AM_GNU_GETTEXT_REQUIRE_VERSION([gettext-version]) +AC_DEFUN([AM_GNU_GETTEXT_REQUIRE_VERSION], []) diff --git a/m4/iconv.m4 b/m4/iconv.m4 new file mode 100644 index 0000000..4e37363 --- /dev/null +++ b/m4/iconv.m4 @@ -0,0 +1,271 @@ +# iconv.m4 serial 19 (gettext-0.18.2) +dnl Copyright (C) 2000-2002, 2007-2014 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([AM_ICONV_LINKFLAGS_BODY], +[ + dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + + dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV + dnl accordingly. + AC_LIB_LINKFLAGS_BODY([iconv]) +]) + +AC_DEFUN([AM_ICONV_LINK], +[ + dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and + dnl those with the standalone portable GNU libiconv installed). + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + + dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV + dnl accordingly. + AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) + + dnl Add $INCICONV to CPPFLAGS before performing the following checks, + dnl because if the user has installed libiconv and not disabled its use + dnl via --without-libiconv-prefix, he wants to use it. The first + dnl AC_LINK_IFELSE will then fail, the second AC_LINK_IFELSE will succeed. + am_save_CPPFLAGS="$CPPFLAGS" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV]) + + AC_CACHE_CHECK([for iconv], [am_cv_func_iconv], [ + am_cv_func_iconv="no, consider installing GNU libiconv" + am_cv_lib_iconv=no + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include + ]], + [[iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);]])], + [am_cv_func_iconv=yes]) + if test "$am_cv_func_iconv" != yes; then + am_save_LIBS="$LIBS" + LIBS="$LIBS $LIBICONV" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include + ]], + [[iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);]])], + [am_cv_lib_iconv=yes] + [am_cv_func_iconv=yes]) + LIBS="$am_save_LIBS" + fi + ]) + if test "$am_cv_func_iconv" = yes; then + AC_CACHE_CHECK([for working iconv], [am_cv_func_iconv_works], [ + dnl This tests against bugs in AIX 5.1, AIX 6.1..7.1, HP-UX 11.11, + dnl Solaris 10. + am_save_LIBS="$LIBS" + if test $am_cv_lib_iconv = yes; then + LIBS="$LIBS $LIBICONV" + fi + am_cv_func_iconv_works=no + for ac_iconv_const in '' 'const'; do + AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include + +#ifndef ICONV_CONST +# define ICONV_CONST $ac_iconv_const +#endif + ]], + [[int result = 0; + /* Test against AIX 5.1 bug: Failures are not distinguishable from successful + returns. */ + { + iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); + if (cd_utf8_to_88591 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\342\202\254"; /* EURO SIGN */ + char buf[10]; + ICONV_CONST char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_utf8_to_88591, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 1; + iconv_close (cd_utf8_to_88591); + } + } + /* Test against Solaris 10 bug: Failures are not distinguishable from + successful returns. */ + { + iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646"); + if (cd_ascii_to_88591 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\263"; + char buf[10]; + ICONV_CONST char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_ascii_to_88591, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 2; + iconv_close (cd_ascii_to_88591); + } + } + /* Test against AIX 6.1..7.1 bug: Buffer overrun. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\304"; + static char buf[2] = { (char)0xDE, (char)0xAD }; + ICONV_CONST char *inptr = input; + size_t inbytesleft = 1; + char *outptr = buf; + size_t outbytesleft = 1; + size_t res = iconv (cd_88591_to_utf8, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD) + result |= 4; + iconv_close (cd_88591_to_utf8); + } + } +#if 0 /* This bug could be worked around by the caller. */ + /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; + char buf[50]; + ICONV_CONST char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_88591_to_utf8, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if ((int)res > 0) + result |= 8; + iconv_close (cd_88591_to_utf8); + } + } +#endif + /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is + provided. */ + if (/* Try standardized names. */ + iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1) + /* Try IRIX, OSF/1 names. */ + && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1) + /* Try AIX names. */ + && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1) + /* Try HP-UX names. */ + && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) + result |= 16; + return result; +]])], + [am_cv_func_iconv_works=yes], , + [case "$host_os" in + aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; + *) am_cv_func_iconv_works="guessing yes" ;; + esac]) + test "$am_cv_func_iconv_works" = no || break + done + LIBS="$am_save_LIBS" + ]) + case "$am_cv_func_iconv_works" in + *no) am_func_iconv=no am_cv_lib_iconv=no ;; + *) am_func_iconv=yes ;; + esac + else + am_func_iconv=no am_cv_lib_iconv=no + fi + if test "$am_func_iconv" = yes; then + AC_DEFINE([HAVE_ICONV], [1], + [Define if you have the iconv() function and it works.]) + fi + if test "$am_cv_lib_iconv" = yes; then + AC_MSG_CHECKING([how to link with libiconv]) + AC_MSG_RESULT([$LIBICONV]) + else + dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV + dnl either. + CPPFLAGS="$am_save_CPPFLAGS" + LIBICONV= + LTLIBICONV= + fi + AC_SUBST([LIBICONV]) + AC_SUBST([LTLIBICONV]) +]) + +dnl Define AM_ICONV using AC_DEFUN_ONCE for Autoconf >= 2.64, in order to +dnl avoid warnings like +dnl "warning: AC_REQUIRE: `AM_ICONV' was expanded before it was required". +dnl This is tricky because of the way 'aclocal' is implemented: +dnl - It requires defining an auxiliary macro whose name ends in AC_DEFUN. +dnl Otherwise aclocal's initial scan pass would miss the macro definition. +dnl - It requires a line break inside the AC_DEFUN_ONCE and AC_DEFUN expansions. +dnl Otherwise aclocal would emit many "Use of uninitialized value $1" +dnl warnings. +m4_define([gl_iconv_AC_DEFUN], + m4_version_prereq([2.64], + [[AC_DEFUN_ONCE( + [$1], [$2])]], + [m4_ifdef([gl_00GNULIB], + [[AC_DEFUN_ONCE( + [$1], [$2])]], + [[AC_DEFUN( + [$1], [$2])]])])) +gl_iconv_AC_DEFUN([AM_ICONV], +[ + AM_ICONV_LINK + if test "$am_cv_func_iconv" = yes; then + AC_MSG_CHECKING([for iconv declaration]) + AC_CACHE_VAL([am_cv_proto_iconv], [ + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include +extern +#ifdef __cplusplus +"C" +#endif +#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) +size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); +#else +size_t iconv(); +#endif + ]], + [[]])], + [am_cv_proto_iconv_arg1=""], + [am_cv_proto_iconv_arg1="const"]) + am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"]) + am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` + AC_MSG_RESULT([ + $am_cv_proto_iconv]) + AC_DEFINE_UNQUOTED([ICONV_CONST], [$am_cv_proto_iconv_arg1], + [Define as const if the declaration of iconv() needs const.]) + dnl Also substitute ICONV_CONST in the gnulib generated . + m4_ifdef([gl_ICONV_H_DEFAULTS], + [AC_REQUIRE([gl_ICONV_H_DEFAULTS]) + if test -n "$am_cv_proto_iconv_arg1"; then + ICONV_CONST="const" + fi + ]) + fi +]) diff --git a/m4/intlmacosx.m4 b/m4/intlmacosx.m4 new file mode 100644 index 0000000..8a045f6 --- /dev/null +++ b/m4/intlmacosx.m4 @@ -0,0 +1,56 @@ +# intlmacosx.m4 serial 5 (gettext-0.18.2) +dnl Copyright (C) 2004-2014 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Checks for special options needed on Mac OS X. +dnl Defines INTL_MACOSX_LIBS. +AC_DEFUN([gt_INTL_MACOSX], +[ + dnl Check for API introduced in Mac OS X 10.2. + AC_CACHE_CHECK([for CFPreferencesCopyAppValue], + [gt_cv_func_CFPreferencesCopyAppValue], + [gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include ]], + [[CFPreferencesCopyAppValue(NULL, NULL)]])], + [gt_cv_func_CFPreferencesCopyAppValue=yes], + [gt_cv_func_CFPreferencesCopyAppValue=no]) + LIBS="$gt_save_LIBS"]) + if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then + AC_DEFINE([HAVE_CFPREFERENCESCOPYAPPVALUE], [1], + [Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in the CoreFoundation framework.]) + fi + dnl Check for API introduced in Mac OS X 10.3. + AC_CACHE_CHECK([for CFLocaleCopyCurrent], [gt_cv_func_CFLocaleCopyCurrent], + [gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include ]], + [[CFLocaleCopyCurrent();]])], + [gt_cv_func_CFLocaleCopyCurrent=yes], + [gt_cv_func_CFLocaleCopyCurrent=no]) + LIBS="$gt_save_LIBS"]) + if test $gt_cv_func_CFLocaleCopyCurrent = yes; then + AC_DEFINE([HAVE_CFLOCALECOPYCURRENT], [1], + [Define to 1 if you have the Mac OS X function CFLocaleCopyCurrent in the CoreFoundation framework.]) + fi + INTL_MACOSX_LIBS= + if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then + INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" + fi + AC_SUBST([INTL_MACOSX_LIBS]) +]) diff --git a/m4/lib-ld.m4 b/m4/lib-ld.m4 new file mode 100644 index 0000000..91ca911 --- /dev/null +++ b/m4/lib-ld.m4 @@ -0,0 +1,119 @@ +# lib-ld.m4 serial 6 +dnl Copyright (C) 1996-2003, 2009-2015 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Subroutines of libtool.m4, +dnl with replacements s/_*LT_PATH/AC_LIB_PROG/ and s/lt_/acl_/ to avoid +dnl collision with libtool.m4. + +dnl From libtool-2.4. Sets the variable with_gnu_ld to yes or no. +AC_DEFUN([AC_LIB_PROG_LD_GNU], +[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], [acl_cv_prog_gnu_ld], +[# I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 /dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo "$ac_prog"| sed 's%\\\\%/%g'` + while echo "$ac_prog" | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL([acl_cv_path_LD], +[if test -z "$LD"; then + acl_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$acl_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + acl_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$acl_cv_path_LD" -v 2>&1 = 1.10 to complain if config.rpath is missing. + m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])]) + AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS + AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld + AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host + AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir + AC_CACHE_CHECK([for shared library run path origin], [acl_cv_rpath], [ + CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ + ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh + . ./conftest.sh + rm -f ./conftest.sh + acl_cv_rpath=done + ]) + wl="$acl_cv_wl" + acl_libext="$acl_cv_libext" + acl_shlibext="$acl_cv_shlibext" + acl_libname_spec="$acl_cv_libname_spec" + acl_library_names_spec="$acl_cv_library_names_spec" + acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" + acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" + acl_hardcode_direct="$acl_cv_hardcode_direct" + acl_hardcode_minus_L="$acl_cv_hardcode_minus_L" + dnl Determine whether the user wants rpath handling at all. + AC_ARG_ENABLE([rpath], + [ --disable-rpath do not hardcode runtime library paths], + :, enable_rpath=yes) +]) + +dnl AC_LIB_FROMPACKAGE(name, package) +dnl declares that libname comes from the given package. The configure file +dnl will then not have a --with-libname-prefix option but a +dnl --with-package-prefix option. Several libraries can come from the same +dnl package. This declaration must occur before an AC_LIB_LINKFLAGS or similar +dnl macro call that searches for libname. +AC_DEFUN([AC_LIB_FROMPACKAGE], +[ + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + define([acl_frompackage_]NAME, [$2]) + popdef([NAME]) + pushdef([PACK],[$2]) + pushdef([PACKUP],[m4_translit(PACK,[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + define([acl_libsinpackage_]PACKUP, + m4_ifdef([acl_libsinpackage_]PACKUP, [m4_defn([acl_libsinpackage_]PACKUP)[, ]],)[lib$1]) + popdef([PACKUP]) + popdef([PACK]) +]) + +dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and +dnl the libraries corresponding to explicit and implicit dependencies. +dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables. +dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found +dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem. +AC_DEFUN([AC_LIB_LINKFLAGS_BODY], +[ + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + pushdef([PACK],[m4_ifdef([acl_frompackage_]NAME, [acl_frompackage_]NAME, lib[$1])]) + pushdef([PACKUP],[m4_translit(PACK,[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + pushdef([PACKLIBS],[m4_ifdef([acl_frompackage_]NAME, [acl_libsinpackage_]PACKUP, lib[$1])]) + dnl Autoconf >= 2.61 supports dots in --with options. + pushdef([P_A_C_K],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[m4_translit(PACK,[.],[_])],PACK)]) + dnl By default, look in $includedir and $libdir. + use_additional=yes + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + AC_ARG_WITH(P_A_C_K[-prefix], +[[ --with-]]P_A_C_K[[-prefix[=DIR] search for ]PACKLIBS[ in DIR/include and DIR/lib + --without-]]P_A_C_K[[-prefix don't search for ]PACKLIBS[ in includedir and libdir]], +[ + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + if test "$acl_libdirstem2" != "$acl_libdirstem" \ + && ! test -d "$withval/$acl_libdirstem"; then + additional_libdir="$withval/$acl_libdirstem2" + fi + fi + fi +]) + dnl Search the library and its dependencies in $additional_libdir and + dnl $LDFLAGS. Using breadth-first-seach. + LIB[]NAME= + LTLIB[]NAME= + INC[]NAME= + LIB[]NAME[]_PREFIX= + dnl HAVE_LIB${NAME} is an indicator that LIB${NAME}, LTLIB${NAME} have been + dnl computed. So it has to be reset here. + HAVE_LIB[]NAME= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='$1 $2' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + dnl See if it was already located by an earlier AC_LIB_LINKFLAGS + dnl or AC_LIB_HAVE_LINKFLAGS call. + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./+-|ABCDEFGHIJKLMNOPQRSTUVWXYZ____|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value" + else + dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined + dnl that this library doesn't exist. So just drop it. + : + fi + else + dnl Search the library lib$name in $additional_libdir and $LDFLAGS + dnl and the already constructed $LIBNAME/$LTLIBNAME. + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + dnl The same code as in the loop below: + dnl First look for a shared library. + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + dnl Then look for a static library. + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + dnl First look for a shared library. + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + dnl Then look for a static library. + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + dnl Found the library. + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + dnl Linking with a shared library. We attempt to hardcode its + dnl directory into the executable's runpath, unless it's the + dnl standard /usr/lib. + if test "$enable_rpath" = no \ + || test "X$found_dir" = "X/usr/$acl_libdirstem" \ + || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then + dnl No hardcoding is needed. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + dnl Use an explicit option to hardcode DIR into the resulting + dnl binary. + dnl Potentially add DIR to ltrpathdirs. + dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + dnl The hardcoding into $LIBNAME is system dependent. + if test "$acl_hardcode_direct" = yes; then + dnl Using DIR/libNAME.so during linking hardcodes DIR into the + dnl resulting binary. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + dnl Use an explicit option to hardcode DIR into the resulting + dnl binary. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + dnl Potentially add DIR to rpathdirs. + dnl The rpathdirs will be appended to $LIBNAME at the end. + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + dnl Rely on "-L$found_dir". + dnl But don't add it if it's already contained in the LDFLAGS + dnl or the already constructed $LIBNAME + haveit= + for x in $LDFLAGS $LIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + dnl FIXME: Not sure whether we should use + dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" + dnl here. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + dnl We cannot use $acl_hardcode_runpath_var and LD_RUN_PATH + dnl here, because this doesn't fit in flags passed to the + dnl compiler. So give up. No hardcoding. This affects only + dnl very old systems. + dnl FIXME: Not sure whether we should use + dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" + dnl here. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + dnl Linking with a static library. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a" + else + dnl We shouldn't come here, but anyway it's good to have a + dnl fallback. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name" + fi + fi + dnl Assume the include files are nearby. + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + if test "$name" = '$1'; then + LIB[]NAME[]_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + */$acl_libdirstem2 | */$acl_libdirstem2/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'` + if test "$name" = '$1'; then + LIB[]NAME[]_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + dnl Potentially add $additional_includedir to $INCNAME. + dnl But don't add it + dnl 1. if it's the standard /usr/include, + dnl 2. if it's /usr/local/include and we are using GCC on Linux, + dnl 3. if it's already present in $CPPFLAGS or the already + dnl constructed $INCNAME, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INC[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + dnl Really add $additional_includedir to $INCNAME. + INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + dnl Look for dependencies. + if test -n "$found_la"; then + dnl Read the .la file. It defines the variables + dnl dlname, library_names, old_library, dependency_libs, current, + dnl age, revision, installed, dlopen, dlpreopen, libdir. + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + dnl We use only dependency_libs. + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME. + dnl But don't add it + dnl 1. if it's the standard /usr/lib, + dnl 2. if it's /usr/local/lib and we are using GCC on Linux, + dnl 3. if it's already present in $LDFLAGS or the already + dnl constructed $LIBNAME, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \ + && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \ + || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LIBNAME. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LTLIBNAME. + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + dnl Potentially add DIR to rpathdirs. + dnl The rpathdirs will be appended to $LIBNAME at the end. + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + dnl Potentially add DIR to ltrpathdirs. + dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + dnl Handle this in the next round. + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + dnl Handle this in the next round. Throw away the .la's + dnl directory; it is already contained in a preceding -L + dnl option. + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + dnl Most likely an immediate library name. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep" + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep" + ;; + esac + done + fi + else + dnl Didn't find the library; assume it is in the system directories + dnl known to the linker and runtime loader. (All the system + dnl directories known to the linker should also be known to the + dnl runtime loader, otherwise the system is severely misconfigured.) + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + dnl Weird platform: only the last -rpath option counts, the user must + dnl pass all path elements in one option. We can arrange that for a + dnl single library, but not when more than one $LIBNAMEs are used. + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl. + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" + else + dnl The -rpath options are cumulative. + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + dnl When using libtool, the option that works for both libraries and + dnl executables is -R. The -R options are cumulative. + for found_dir in $ltrpathdirs; do + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir" + done + fi + popdef([P_A_C_K]) + popdef([PACKLIBS]) + popdef([PACKUP]) + popdef([PACK]) + popdef([NAME]) +]) + +dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR, +dnl unless already present in VAR. +dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes +dnl contains two or three consecutive elements that belong together. +AC_DEFUN([AC_LIB_APPENDTOVAR], +[ + for element in [$2]; do + haveit= + for x in $[$1]; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + [$1]="${[$1]}${[$1]:+ }$element" + fi + done +]) + +dnl For those cases where a variable contains several -L and -l options +dnl referring to unknown libraries and directories, this macro determines the +dnl necessary additional linker options for the runtime path. +dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL]) +dnl sets LDADDVAR to linker options needed together with LIBSVALUE. +dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed, +dnl otherwise linking without libtool is assumed. +AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS], +[ + AC_REQUIRE([AC_LIB_RPATH]) + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + $1= + if test "$enable_rpath" != no; then + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + dnl Use an explicit option to hardcode directories into the resulting + dnl binary. + rpathdirs= + next= + for opt in $2; do + if test -n "$next"; then + dir="$next" + dnl No need to hardcode the standard /usr/lib. + if test "X$dir" != "X/usr/$acl_libdirstem" \ + && test "X$dir" != "X/usr/$acl_libdirstem2"; then + rpathdirs="$rpathdirs $dir" + fi + next= + else + case $opt in + -L) next=yes ;; + -L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'` + dnl No need to hardcode the standard /usr/lib. + if test "X$dir" != "X/usr/$acl_libdirstem" \ + && test "X$dir" != "X/usr/$acl_libdirstem2"; then + rpathdirs="$rpathdirs $dir" + fi + next= ;; + *) next= ;; + esac + fi + done + if test "X$rpathdirs" != "X"; then + if test -n ""$3""; then + dnl libtool is used for linking. Use -R options. + for dir in $rpathdirs; do + $1="${$1}${$1:+ }-R$dir" + done + else + dnl The linker is used for linking directly. + if test -n "$acl_hardcode_libdir_separator"; then + dnl Weird platform: only the last -rpath option counts, the user + dnl must pass all path elements in one option. + alldirs= + for dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + $1="$flag" + else + dnl The -rpath options are cumulative. + for dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + $1="${$1}${$1:+ }$flag" + done + fi + fi + fi + fi + fi + AC_SUBST([$1]) +]) diff --git a/m4/lib-prefix.m4 b/m4/lib-prefix.m4 new file mode 100644 index 0000000..0465f47 --- /dev/null +++ b/m4/lib-prefix.m4 @@ -0,0 +1,224 @@ +# lib-prefix.m4 serial 7 (gettext-0.18) +dnl Copyright (C) 2001-2005, 2008-2015 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and +dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't +dnl require excessive bracketing. +ifdef([AC_HELP_STRING], +[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])], +[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])]) + +dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed +dnl to access previously installed libraries. The basic assumption is that +dnl a user will want packages to use other packages he previously installed +dnl with the same --prefix option. +dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate +dnl libraries, but is otherwise very convenient. +AC_DEFUN([AC_LIB_PREFIX], +[ + AC_BEFORE([$0], [AC_LIB_LINKFLAGS]) + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + dnl By default, look in $includedir and $libdir. + use_additional=yes + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + AC_LIB_ARG_WITH([lib-prefix], +[ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib + --without-lib-prefix don't search for libraries in includedir and libdir], +[ + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + fi + fi +]) + if test $use_additional = yes; then + dnl Potentially add $additional_includedir to $CPPFLAGS. + dnl But don't add it + dnl 1. if it's the standard /usr/include, + dnl 2. if it's already present in $CPPFLAGS, + dnl 3. if it's /usr/local/include and we are using GCC on Linux, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + for x in $CPPFLAGS; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + dnl Really add $additional_includedir to $CPPFLAGS. + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir" + fi + fi + fi + fi + dnl Potentially add $additional_libdir to $LDFLAGS. + dnl But don't add it + dnl 1. if it's the standard /usr/lib, + dnl 2. if it's already present in $LDFLAGS, + dnl 3. if it's /usr/local/lib and we are using GCC on Linux, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then + haveit= + for x in $LDFLAGS; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then + if test -n "$GCC"; then + case $host_os in + linux*) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LDFLAGS. + LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir" + fi + fi + fi + fi + fi +]) + +dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix, +dnl acl_final_exec_prefix, containing the values to which $prefix and +dnl $exec_prefix will expand at the end of the configure script. +AC_DEFUN([AC_LIB_PREPARE_PREFIX], +[ + dnl Unfortunately, prefix and exec_prefix get only finally determined + dnl at the end of configure. + if test "X$prefix" = "XNONE"; then + acl_final_prefix="$ac_default_prefix" + else + acl_final_prefix="$prefix" + fi + if test "X$exec_prefix" = "XNONE"; then + acl_final_exec_prefix='${prefix}' + else + acl_final_exec_prefix="$exec_prefix" + fi + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" + prefix="$acl_save_prefix" +]) + +dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the +dnl variables prefix and exec_prefix bound to the values they will have +dnl at the end of the configure script. +AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX], +[ + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + $1 + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" +]) + +dnl AC_LIB_PREPARE_MULTILIB creates +dnl - a variable acl_libdirstem, containing the basename of the libdir, either +dnl "lib" or "lib64" or "lib/64", +dnl - a variable acl_libdirstem2, as a secondary possible value for +dnl acl_libdirstem, either the same as acl_libdirstem or "lib/sparcv9" or +dnl "lib/amd64". +AC_DEFUN([AC_LIB_PREPARE_MULTILIB], +[ + dnl There is no formal standard regarding lib and lib64. + dnl On glibc systems, the current practice is that on a system supporting + dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under + dnl $prefix/lib64 and 32-bit libraries go under $prefix/lib. We determine + dnl the compiler's default mode by looking at the compiler's library search + dnl path. If at least one of its elements ends in /lib64 or points to a + dnl directory whose absolute pathname ends in /lib64, we assume a 64-bit ABI. + dnl Otherwise we use the default, namely "lib". + dnl On Solaris systems, the current practice is that on a system supporting + dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under + dnl $prefix/lib/64 (which is a symlink to either $prefix/lib/sparcv9 or + dnl $prefix/lib/amd64) and 32-bit libraries go under $prefix/lib. + AC_REQUIRE([AC_CANONICAL_HOST]) + acl_libdirstem=lib + acl_libdirstem2= + case "$host_os" in + solaris*) + dnl See Solaris 10 Software Developer Collection > Solaris 64-bit Developer's Guide > The Development Environment + dnl . + dnl "Portable Makefiles should refer to any library directories using the 64 symbolic link." + dnl But we want to recognize the sparcv9 or amd64 subdirectory also if the + dnl symlink is missing, so we set acl_libdirstem2 too. + AC_CACHE_CHECK([for 64-bit host], [gl_cv_solaris_64bit], + [AC_EGREP_CPP([sixtyfour bits], [ +#ifdef _LP64 +sixtyfour bits +#endif + ], [gl_cv_solaris_64bit=yes], [gl_cv_solaris_64bit=no]) + ]) + if test $gl_cv_solaris_64bit = yes; then + acl_libdirstem=lib/64 + case "$host_cpu" in + sparc*) acl_libdirstem2=lib/sparcv9 ;; + i*86 | x86_64) acl_libdirstem2=lib/amd64 ;; + esac + fi + ;; + *) + searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` + if test -n "$searchpath"; then + acl_save_IFS="${IFS= }"; IFS=":" + for searchdir in $searchpath; do + if test -d "$searchdir"; then + case "$searchdir" in + */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; + */../ | */.. ) + # Better ignore directories of this form. They are misleading. + ;; + *) searchdir=`cd "$searchdir" && pwd` + case "$searchdir" in + */lib64 ) acl_libdirstem=lib64 ;; + esac ;; + esac + fi + done + IFS="$acl_save_IFS" + fi + ;; + esac + test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem" +]) diff --git a/m4/libtool.m4 b/m4/libtool.m4 new file mode 100644 index 0000000..a644432 --- /dev/null +++ b/m4/libtool.m4 @@ -0,0 +1,8372 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +# +# Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +m4_define([_LT_COPYING], [dnl +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +]) + +# serial 58 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_PREPARE_CC_BASENAME +# ----------------------- +m4_defun([_LT_PREPARE_CC_BASENAME], [ +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in @S|@*""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} +])# _LT_PREPARE_CC_BASENAME + + +# _LT_CC_BASENAME(CC) +# ------------------- +# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, +# but that macro is also expanded into generated libtool script, which +# arranges for $SED and $ECHO to be set by different means. +m4_defun([_LT_CC_BASENAME], +[m4_require([_LT_PREPARE_CC_BASENAME])dnl +AC_REQUIRE([_LT_DECL_SED])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl +func_cc_basename $1 +cc_basename=$func_cc_basename_result +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + +_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl +dnl +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_WITH_SYSROOT])dnl +m4_require([_LT_CMD_TRUNCATE])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from 'configure', and 'config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# 'config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain=$ac_aux_dir/ltmain.sh +])# _LT_PROG_LTMAIN + + +## ------------------------------------- ## +## Accumulate code for creating libtool. ## +## ------------------------------------- ## + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the 'libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + +## ------------------------ ## +## FIXME: Eliminate VARNAME ## +## ------------------------ ## + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to 'config.status' so that its +# declaration there will have the same value as in 'configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags='_LT_TAGS'dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into 'config.status', and then the shell code to quote escape them in +# for loops in 'config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +_LT_OUTPUT_LIBTOOL_INIT +]) + +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# '#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test 0 = "$lt_write_fail" && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), incase it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) + +cat >>"$CONFIG_LT" <<\_LTEOF +lt_cl_silent=false +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +'$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to ." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2011 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test 0 != $[#] +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try '$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try '$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +lt_cl_success=: +test yes = "$silent" && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +_LT_COPYING +_LT_LIBTOOL_TAGS + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +_LT_PREPARE_MUNGE_PATH_LIST +_LT_PREPARE_CC_BASENAME + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Go], [_LT_LANG(GO)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +m4_ifndef([AC_PROG_GO], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_GO. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +m4_defun([AC_PROG_GO], +[AC_LANG_PUSH(Go)dnl +AC_ARG_VAR([GOC], [Go compiler command])dnl +AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl +_AC_ARG_VAR_LDFLAGS()dnl +AC_CHECK_TOOL(GOC, gccgo) +if test -z "$GOC"; then + if test -n "$ac_tool_prefix"; then + AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) + fi +fi +if test -z "$GOC"; then + AC_CHECK_PROG(GOC, gccgo, gccgo, false) +fi +])#m4_defun +])#m4_ifndef + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([AC_PROG_GO], + [LT_LANG(GO)], + [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS=$save_LDFLAGS + ]) + + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[[012]][[,.]]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES([TAG]) +# --------------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + if test yes = "$lt_cv_ld_force_load"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], + [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + m4_if([$1], [CXX], +[ if test yes != "$lt_cv_apple_cc_single_mod"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) +# ---------------------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +# Store the results from the different compilers for each TAGNAME. +# Allow to override them for all tags through lt_cv_aix_libpath. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], + [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ + lt_aix_libpath_sed='[ + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }]' + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi],[]) + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib + fi + ]) + aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) +fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script that will find a shell with a builtin +# printf (that we can use as an echo command). +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +case $ECHO in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac + +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) + +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_WITH_SYSROOT +# ---------------- +AC_DEFUN([_LT_WITH_SYSROOT], +[AC_MSG_CHECKING([for sysroot]) +AC_ARG_WITH([sysroot], +[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], + [Search for dependent libraries within DIR (or the compiler's sysroot + if not specified).])], +[], [with_sysroot=no]) + +dnl lt_sysroot will always be passed unquoted. We quote it here +dnl in case the user passed a directory name. +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + AC_MSG_RESULT([$with_sysroot]) + AC_MSG_ERROR([The sysroot must be an absolute path.]) + ;; +esac + + AC_MSG_RESULT([${lt_sysroot:-no}]) +_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl +[dependent libraries, and where our libraries should be installed.])]) + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock +])# _LT_ENABLE_LOCK + + +# _LT_PROG_AR +# ----------- +m4_defun([_LT_PROG_AR], +[AC_CHECK_TOOLS(AR, [ar], false) +: ${AR=ar} +: ${AR_FLAGS=cru} +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], + [lt_cv_ar_at_file=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([lt_ar_try]) + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + AC_TRY_EVAL([lt_ar_try]) + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + ]) + ]) + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi +_LT_DECL([], [archiver_list_spec], [1], + [How to feed a file listing to the archiver]) +])# _LT_PROG_AR + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[_LT_PROG_AR + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test yes = "[$]$2"; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS +]) + +if test yes = "[$]$2"; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n "$lt_cv_sys_max_cmd_len"; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes = "$cross_compiling"; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen=shl_load], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen=dlopen], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links=nottested +if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test no = "$hard_links"; then + AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", + [Define to the sub-directory where libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then + + # We can hardcode non-existent directories. + if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && + test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || + test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_PREPARE_MUNGE_PATH_LIST +# --------------------------- +# Make sure func_munge_path_list() is defined correctly. +m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], +[[# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x@S|@2 in + x) + ;; + *:) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" + ;; + x:*) + eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" + ;; + *) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + esac +} +]])# _LT_PREPARE_PATH_LIST + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +AC_ARG_VAR([LT_SYS_LIBRARY_PATH], +[User-defined run-time library search path.]) + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[[4-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a[(]lib.so.V[)]' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[23]].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[[3-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Add ABI-specific directories to the system library path. + sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[List of archive names. First name is the real one, the rest are links. + The last name is the one that the linker finds with -lNAME]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], + [Detected run-time system search path for libraries]) +_LT_DECL([], [configure_time_lt_sys_library_path], [2], + [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program that can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$1"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac]) +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program that can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test no = "$withval" || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], +[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi]) +rm -f conftest.i conftest2.i conftest.out]) +])# _LT_PATH_DD + + +# _LT_CMD_TRUNCATE +# ---------------- +# find command to truncate a binary pipe +m4_defun([_LT_CMD_TRUNCATE], +[m4_require([_LT_PATH_DD]) +AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], +[printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) +_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], + [Command to truncate a binary pipe]) +])# _LT_CMD_TRUNCATE + + +# _LT_CHECK_MAGIC_METHOD +# ---------------------- +# how to check for library dependencies +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_MAGIC_METHOD], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +AC_CACHE_CHECK([how to recognize dependent libraries], +lt_cv_deplibs_check_method, +[lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[[4-9]]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[[45]]*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method = "file_magic"]) +_LT_DECL([], [file_magic_glob], [1], + [How to find potential files when deplibs_check_method = "file_magic"]) +_LT_DECL([], [want_nocaseglob], [1], + [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi]) +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + AC_SUBST([DUMPBIN]) + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + +# _LT_CHECK_SHAREDLIB_FROM_LINKLIB +# -------------------------------- +# how to determine the name of the shared library +# associated with a specific link library. +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +m4_require([_LT_DECL_DLLTOOL]) +AC_CACHE_CHECK([how to associate runtime and link libraries], +lt_cv_sharedlib_from_linklib_cmd, +[lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac +]) +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + +_LT_DECL([], [sharedlib_from_linklib_cmd], [1], + [Command to associate shared and link libraries]) +])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB + + +# _LT_PATH_MANIFEST_TOOL +# ---------------------- +# locate the manifest tool +m4_defun([_LT_PATH_MANIFEST_TOOL], +[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], + [lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&AS_MESSAGE_LOG_FD + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest*]) +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi +_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl +])# _LT_PATH_MANIFEST_TOOL + + +# _LT_DLL_DEF_P([FILE]) +# --------------------- +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with func_dll_def_p in the libtool script +AC_DEFUN([_LT_DLL_DEF_P], +[dnl + test DEF = "`$SED -n dnl + -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace + -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments + -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl + -e q dnl Only consider the first "real" line + $1`" dnl +])# _LT_DLL_DEF_P + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM=-lm) + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[[ABCDEGRST]]' + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT@&t@_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT@&t@_DLSYM_CONST +#else +# define LT@&t@_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT@&t@_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], + [Transform the output of nm into a list of symbols to manually relocate]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([nm_interface], [lt_cv_nm_interface], [1], + [The name lister interface]) +_LT_DECL([], [nm_file_list_spec], [1], + [Specify filename containing input files for $NM]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64, which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test yes = "$GCC"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + *Sun\ F* | *Sun*Fortran*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + *Intel*\ [[CF]]*Compiler*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + *Portland\ Group*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +AC_CACHE_CHECK([for $compiler option to produce PIC], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + case $host_os in + aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + ;; + esac + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + esac + + _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + esac + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + ;; + esac + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], + [lt_cv_irix_exported_symbol], + [save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + AC_LINK_IFELSE( + [AC_LANG_SOURCE( + [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], + [C++], [[int foo (void) { return 0; }]], + [Fortran 77], [[ + subroutine foo + end]], + [Fortran], [[ + subroutine foo + end]])])], + [lt_cv_irix_exported_symbol=yes], + [lt_cv_irix_exported_symbol=no]) + LDFLAGS=$save_LDFLAGS]) + if test yes = "$lt_cv_irix_exported_symbol"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(ld_shlibs, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + osf3*) + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $_LT_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting $shlibpath_var if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [postlink_cmds], [2], + [Commands necessary for finishing linking programs]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC=$CC +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report what library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC=$lt_save_CC +])# _LT_LANG_C_CONFIG + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +if test -n "$CXX" && ( test no != "$CXX" && + ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || + (test g++ != "$CXX"))); then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_caught_CXX_error"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test yes = "$GXX"; then + # Set up default GNU C++ configuration + + LT_PATH_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test yes = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='$wl' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GXX"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag=$shared_flag' $wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + # The "-G" linker flag allows undefined symbols. + _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared + # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd2.*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ + $RM $lib.exp' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require '-G' NOT '-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + + _LT_TAGVAR(GCC, $1)=$GXX + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test yes != "$_lt_caught_CXX_error" + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_FUNC_STRIPNAME_CNF +# ---------------------- +# func_stripname_cnf prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# +# This function is identical to the (non-XSI) version of func_stripname, +# except this one can be used by m4 code that may be executed by configure, +# rather than the libtool script. +m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl +AC_REQUIRE([_LT_DECL_SED]) +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) +func_stripname_cnf () +{ + case @S|@2 in + .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; + *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; + esac +} # func_stripname_cnf +])# _LT_FUNC_STRIPNAME_CNF + + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF +package foo +func foo() { +} +_LT_EOF +]) + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case $prev$p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test x-L = "$p" || + test x-R = "$p"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test no = "$pre_test_object_deps_done"; then + case $prev in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)=$prev$p + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test no = "$pre_test_object_deps_done"; then + if test -z "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)=$p + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)=$p + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test no = "$F77"; then + _lt_disable_F77=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_F77"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${F77-"f77"} + CFLAGS=$FFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$G77 + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_F77" + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test no = "$FC"; then + _lt_disable_FC=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_FC"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${FC-"f95"} + CFLAGS=$FCFLAGS + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_FC" + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +CFLAGS=$GCJFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_GO_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Go compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GO_CONFIG], +[AC_REQUIRE([LT_PROG_GO])dnl +AC_LANG_SAVE + +# Source file extension for Go test sources. +ac_ext=go + +# Object file extension for compiled Go test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="package main; func main() { }" + +# Code to be used in simple link tests +lt_simple_link_test_code='package main; func main() { }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GOC-"gccgo"} +CFLAGS=$GOFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# Go did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GO_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code=$lt_simple_compile_test_code + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +CFLAGS= +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_GO +# ---------- +AC_DEFUN([LT_PROG_GO], +[AC_CHECK_TOOL(GOC, gccgo,) +]) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + +# _LT_DECL_DLLTOOL +# ---------------- +# Ensure DLLTOOL variable is set. +m4_defun([_LT_DECL_DLLTOOL], +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) +AC_SUBST([DLLTOOL]) +]) + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f "$lt_ac_sed" && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test 10 -lt "$lt_ac_count" && break + lt_ac_count=`expr $lt_ac_count + 1` + if test "$lt_ac_count" -gt "$lt_ac_max"; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PATH_CONVERSION_FUNCTIONS +# ----------------------------- +# Determine what file name conversion functions should be used by +# func_to_host_file (and, implicitly, by func_to_host_path). These are needed +# for certain cross-compile configurations and native mingw. +m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_MSG_CHECKING([how to convert $build file names to $host format]) +AC_CACHE_VAL(lt_cv_to_host_file_cmd, +[case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac +]) +to_host_file_cmd=$lt_cv_to_host_file_cmd +AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) +_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], + [0], [convert $build file names to $host format])dnl + +AC_MSG_CHECKING([how to convert $build file names to toolchain format]) +AC_CACHE_VAL(lt_cv_to_tool_file_cmd, +[#assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac +]) +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) +_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], + [0], [convert $build files to toolchain format])dnl +])# _LT_PATH_CONVERSION_FUNCTIONS diff --git a/m4/ltoptions.m4 b/m4/ltoptions.m4 new file mode 100644 index 0000000..94b0829 --- /dev/null +++ b/m4/ltoptions.m4 @@ -0,0 +1,437 @@ +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 8 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option '$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl 'shared' nor 'disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], + [_LT_WITH_AIX_SONAME([aix])]) + ]) +])# _LT_SET_OPTIONS + + +## --------------------------------- ## +## Macros to handle LT_INIT options. ## +## --------------------------------- ## + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [1], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the 'shared' and +# 'disable-shared' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the 'static' and +# 'disable-static' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the 'fast-install' +# and 'disable-fast-install' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_AIX_SONAME([DEFAULT]) +# ---------------------------------- +# implement the --with-aix-soname flag, and support the `aix-soname=aix' +# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT +# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. +m4_define([_LT_WITH_AIX_SONAME], +[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl +shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[[5-9]]*,yes) + AC_MSG_CHECKING([which variant of shared library versioning to provide]) + AC_ARG_WITH([aix-soname], + [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], + [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], + [case $withval in + aix|svr4|both) + ;; + *) + AC_MSG_ERROR([Unknown argument to --with-aix-soname]) + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname], + [AC_CACHE_VAL([lt_cv_with_aix_soname], + [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) + with_aix_soname=$lt_cv_with_aix_soname]) + AC_MSG_RESULT([$with_aix_soname]) + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + +_LT_DECL([], [shared_archive_member_spec], [0], + [Shared archive member basename, for filename based shared library versioning on AIX])dnl +])# _LT_WITH_AIX_SONAME + +LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the 'pic-only' and 'no-pic' +# LT_INIT options. +# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [pic_mode=m4_default([$1], [default])]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + +## ----------------- ## +## LTDL_INIT Options ## +## ----------------- ## + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) diff --git a/m4/ltsugar.m4 b/m4/ltsugar.m4 new file mode 100644 index 0000000..48bc934 --- /dev/null +++ b/m4/ltsugar.m4 @@ -0,0 +1,124 @@ +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59, which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) diff --git a/m4/ltversion.m4 b/m4/ltversion.m4 new file mode 100644 index 0000000..fa04b52 --- /dev/null +++ b/m4/ltversion.m4 @@ -0,0 +1,23 @@ +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# @configure_input@ + +# serial 4179 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.4.6]) +m4_define([LT_PACKAGE_REVISION], [2.4.6]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.4.6' +macro_revision='2.4.6' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) diff --git a/m4/lt~obsolete.m4 b/m4/lt~obsolete.m4 new file mode 100644 index 0000000..c6b26f8 --- /dev/null +++ b/m4/lt~obsolete.m4 @@ -0,0 +1,99 @@ +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 5 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) diff --git a/m4/nls.m4 b/m4/nls.m4 new file mode 100644 index 0000000..53cdc8b --- /dev/null +++ b/m4/nls.m4 @@ -0,0 +1,32 @@ +# nls.m4 serial 5 (gettext-0.18) +dnl Copyright (C) 1995-2003, 2005-2006, 2008-2014 Free Software Foundation, +dnl Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2003. + +AC_PREREQ([2.50]) + +AC_DEFUN([AM_NLS], +[ + AC_MSG_CHECKING([whether NLS is requested]) + dnl Default is enabled NLS + AC_ARG_ENABLE([nls], + [ --disable-nls do not use Native Language Support], + USE_NLS=$enableval, USE_NLS=yes) + AC_MSG_RESULT([$USE_NLS]) + AC_SUBST([USE_NLS]) +]) diff --git a/m4/po.m4 b/m4/po.m4 new file mode 100644 index 0000000..43012dc --- /dev/null +++ b/m4/po.m4 @@ -0,0 +1,453 @@ +# po.m4 serial 24 (gettext-0.19) +dnl Copyright (C) 1995-2014 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2003. + +AC_PREREQ([2.60]) + +dnl Checks for all prerequisites of the po subdirectory. +AC_DEFUN([AM_PO_SUBDIRS], +[ + AC_REQUIRE([AC_PROG_MAKE_SET])dnl + AC_REQUIRE([AC_PROG_INSTALL])dnl + AC_REQUIRE([AC_PROG_MKDIR_P])dnl + AC_REQUIRE([AC_PROG_SED])dnl + AC_REQUIRE([AM_NLS])dnl + + dnl Release version of the gettext macros. This is used to ensure that + dnl the gettext macros and po/Makefile.in.in are in sync. + AC_SUBST([GETTEXT_MACRO_VERSION], [0.19]) + + dnl Perform the following tests also if --disable-nls has been given, + dnl because they are needed for "make dist" to work. + + dnl Search for GNU msgfmt in the PATH. + dnl The first test excludes Solaris msgfmt and early GNU msgfmt versions. + dnl The second test excludes FreeBSD msgfmt. + AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [$ac_dir/$ac_word --statistics /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && + (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], + :) + AC_PATH_PROG([GMSGFMT], [gmsgfmt], [$MSGFMT]) + + dnl Test whether it is GNU msgfmt >= 0.15. +changequote(,)dnl + case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;; + *) MSGFMT_015=$MSGFMT ;; + esac +changequote([,])dnl + AC_SUBST([MSGFMT_015]) +changequote(,)dnl + case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;; + *) GMSGFMT_015=$GMSGFMT ;; + esac +changequote([,])dnl + AC_SUBST([GMSGFMT_015]) + + dnl Search for GNU xgettext 0.12 or newer in the PATH. + dnl The first test excludes Solaris xgettext and early GNU xgettext versions. + dnl The second test excludes FreeBSD xgettext. + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [$ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && + (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], + :) + dnl Remove leftover from FreeBSD xgettext call. + rm -f messages.po + + dnl Test whether it is GNU xgettext >= 0.15. +changequote(,)dnl + case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;; + *) XGETTEXT_015=$XGETTEXT ;; + esac +changequote([,])dnl + AC_SUBST([XGETTEXT_015]) + + dnl Search for GNU msgmerge 0.11 or newer in the PATH. + AM_PATH_PROG_WITH_TEST(MSGMERGE, msgmerge, + [$ac_dir/$ac_word --update -q /dev/null /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1], :) + + dnl Installation directories. + dnl Autoconf >= 2.60 defines localedir. For older versions of autoconf, we + dnl have to define it here, so that it can be used in po/Makefile. + test -n "$localedir" || localedir='${datadir}/locale' + AC_SUBST([localedir]) + + dnl Support for AM_XGETTEXT_OPTION. + test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS= + AC_SUBST([XGETTEXT_EXTRA_OPTIONS]) + + AC_CONFIG_COMMANDS([po-directories], [[ + for ac_file in $CONFIG_FILES; do + # Support "outfile[:infile[:infile...]]" + case "$ac_file" in + *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + esac + # PO directories have a Makefile.in generated from Makefile.in.in. + case "$ac_file" in */Makefile.in) + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix=/`echo "$ac_dir"|sed 's%^\./%%'` + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + # Treat a directory as a PO directory if and only if it has a + # POTFILES.in file. This allows packages to have multiple PO + # directories under different names or in different locations. + if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then + rm -f "$ac_dir/POTFILES" + test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" + gt_tab=`printf '\t'` + cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ${gt_tab}]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" + POMAKEFILEDEPS="POTFILES.in" + # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend + # on $ac_dir but don't depend on user-specified configuration + # parameters. + if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then + # The LINGUAS file contains the set of available languages. + if test -n "$OBSOLETE_ALL_LINGUAS"; then + test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" + fi + ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` + # Hide the ALL_LINGUAS assignment from automake < 1.5. + eval 'ALL_LINGUAS''=$ALL_LINGUAS_' + POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" + else + # The set of available languages was given in configure.in. + # Hide the ALL_LINGUAS assignment from automake < 1.5. + eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' + fi + # Compute POFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) + # Compute UPDATEPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) + # Compute DUMMYPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) + # Compute GMOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) + case "$ac_given_srcdir" in + .) srcdirpre= ;; + *) srcdirpre='$(srcdir)/' ;; + esac + POFILES= + UPDATEPOFILES= + DUMMYPOFILES= + GMOFILES= + for lang in $ALL_LINGUAS; do + POFILES="$POFILES $srcdirpre$lang.po" + UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" + DUMMYPOFILES="$DUMMYPOFILES $lang.nop" + GMOFILES="$GMOFILES $srcdirpre$lang.gmo" + done + # CATALOGS depends on both $ac_dir and the user's LINGUAS + # environment variable. + INST_LINGUAS= + if test -n "$ALL_LINGUAS"; then + for presentlang in $ALL_LINGUAS; do + useit=no + if test "%UNSET%" != "$LINGUAS"; then + desiredlanguages="$LINGUAS" + else + desiredlanguages="$ALL_LINGUAS" + fi + for desiredlang in $desiredlanguages; do + # Use the presentlang catalog if desiredlang is + # a. equal to presentlang, or + # b. a variant of presentlang (because in this case, + # presentlang can be used as a fallback for messages + # which are not translated in the desiredlang catalog). + case "$desiredlang" in + "$presentlang"*) useit=yes;; + esac + done + if test $useit = yes; then + INST_LINGUAS="$INST_LINGUAS $presentlang" + fi + done + fi + CATALOGS= + if test -n "$INST_LINGUAS"; then + for lang in $INST_LINGUAS; do + CATALOGS="$CATALOGS $lang.gmo" + done + fi + test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" + sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" + for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do + if test -f "$f"; then + case "$f" in + *.orig | *.bak | *~) ;; + *) cat "$f" >> "$ac_dir/Makefile" ;; + esac + fi + done + fi + ;; + esac + done]], + [# Capture the value of obsolete ALL_LINGUAS because we need it to compute + # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it + # from automake < 1.5. + eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' + # Capture the value of LINGUAS because we need it to compute CATALOGS. + LINGUAS="${LINGUAS-%UNSET%}" + ]) +]) + +dnl Postprocesses a Makefile in a directory containing PO files. +AC_DEFUN([AM_POSTPROCESS_PO_MAKEFILE], +[ + # When this code is run, in config.status, two variables have already been + # set: + # - OBSOLETE_ALL_LINGUAS is the value of LINGUAS set in configure.in, + # - LINGUAS is the value of the environment variable LINGUAS at configure + # time. + +changequote(,)dnl + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix=/`echo "$ac_dir"|sed 's%^\./%%'` + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + # Find a way to echo strings without interpreting backslash. + if test "X`(echo '\t') 2>/dev/null`" = 'X\t'; then + gt_echo='echo' + else + if test "X`(printf '%s\n' '\t') 2>/dev/null`" = 'X\t'; then + gt_echo='printf %s\n' + else + echo_func () { + cat < "$ac_file.tmp" + tab=`printf '\t'` + if grep -l '@TCLCATALOGS@' "$ac_file" > /dev/null; then + # Add dependencies that cannot be formulated as a simple suffix rule. + for lang in $ALL_LINGUAS; do + frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` + cat >> "$ac_file.tmp" < /dev/null; then + # Add dependencies that cannot be formulated as a simple suffix rule. + for lang in $ALL_LINGUAS; do + frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'` + cat >> "$ac_file.tmp" <> "$ac_file.tmp" <, 1996. + +AC_PREREQ([2.50]) + +# Search path for a program which passes the given test. + +dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, +dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN([AM_PATH_PROG_WITH_TEST], +[ +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which + # contains only /bin. Note that ksh looks also at the FPATH variable, + # so we have to set that as well for the test. + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } +fi + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL([ac_cv_path_$1], +[case "[$]$1" in + [[\\/]]* | ?:[[\\/]]*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in ifelse([$5], , $PATH, [$5]); do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&AS_MESSAGE_LOG_FD + if [$3]; then + ac_cv_path_$1="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" +dnl If no 4th arg is given, leave the cache variable unset, +dnl so AC_PATH_PROGS will keep looking. +ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" +])dnl + ;; +esac])dnl +$1="$ac_cv_path_$1" +if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then + AC_MSG_RESULT([$][$1]) +else + AC_MSG_RESULT([no]) +fi +AC_SUBST([$1])dnl +]) diff --git a/po/ChangeLog b/po/ChangeLog new file mode 100644 index 0000000..3e89bb9 --- /dev/null +++ b/po/ChangeLog @@ -0,0 +1,5062 @@ +2009-04-05 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + +2009-03-30 Baris Cicek + + * tr.po: Updated Turkish translation. + +2009-03-28 Simos Xenitellis + + * el.po: Updated Greek translation. + +2009-03-27 Simos Xenitellis + + * el.po: Updated Greek translation. + +2009-03-21 Goran Rakic + + * sr.po, sr@latin.po: Updated Serbian translation by Miloš Popović. + +2009-03-19 Tomasz Dominikowski + + * pl.po: Updated Polish translation + +2009-03-19 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + +2009-03-18 Ignacio Casal Quinteiro + + * gl.po: Updated Galician translation by Suso Baleato. + +2009-03-18 Kostas Papadimas + + * el.po: Updated Greek Translation by Fotis Tsamis. + +2009-03-18 Djihed Afifi + + * ar.po: Updated Arabic translation. + +2009-03-17 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Alexander Shopov + +2009-03-16 Amitakhya Phukan + + * as.po: Updated Assamese translations. + +2009-03-15 Rajesh Ranjan + + * mai.po: added Maithili translation. + * LINGUAS: Added Maithili (mai) to the list of Languages. + +2009-03-15 Ankitkumar Patel + + * gu.po: Updated Gujarati Translations. + +2009-03-14 Gintautas Miliauskas + + * lt.po: Updated Lithuanian translation. + +2009-03-14 Nickolay V. Shmyrev + + * ru.po: Updated Russian translation by Yuriy Penkin. + +2009-03-14 Sandeep Shedmake + + * mr.po: Updated Marathi Translations. + +2009-03-14 Rajesh Ranjan + + * hi.po: Updated Hindi Translation. + +2009-03-13 Kostas Papadimas + + * el.po: Updated Greek Translation by Jennie Petoumenou. + +2009-03-13 Priit Laes + + * et.po: Translation updated by Mattias Põldaru + +2009-03-12 Manoj Kumar Giri + + * or.po: Updated Oriya Translation. + +2009-03-11 Krishnababu K + + * te.po: Updated Telugu Translation. + * LINGUAS: Added Telugu [te] language. + +2009-03-10 Runa Bhattacharjee + + * bn_IN.po: Updated partial Bengali India Translation + +2009-03-08 Petr Kovar + + * cs.po: Updated Czech translation. + +2009-03-07 Mark Krapivner + + * he.po: Updated Hebrew translation. + +2009-03-06 Milo Casagrande + + * it.po: Updated Italian translation by Luca Ferretti. + +2009-03-04 Luca Ferretti + + * it.po: Updated Italian translation + +2009-03-02 Claude Paroz + + * fr.po: Updated French translation by Frédéric Peters and Claude Paroz. + +2009-03-02 I. Felix + + * ta.po: Tamil Translation updated by Tirumurthi Vasudevan + +2009-02-28 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2009-02-23 Philip Withnall + + * en_GB.po: Updated British English translation. + +2009-02-23 Gil Forcada + + * ca.po: Updated Catalan translation by David Planella. + +2009-02-23 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + +2009-02-21 Christian Kirbach + + * de.po: Updated German translation. + +2009-02-20 Og Maciel + + * pt_BR.po: Updated Brazilian Portuguese translation by + Vladimir Melo. + +2009-02-19 Jani Monoses + + * ro.po: Updated Romanian translation + by Adi Roiban + +2009-02-19 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + +2009-02-18 Chao-Hsiung Liao + + * zh_HK.po: Updated Traditional Chinese translation(Hong Kong). + * zh_TW.po: Updated Traditional Chinese translation(Taiwan). + +2009-02-18 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2009-02-17 Gabor Kelemen + + * hu.po: Translation updated. + +2009-02-16 Wouter Bolsterlee + + * nl.po: Updated Dutch translation by Wouter Bolsterlee. + +2009-02-15 Kenneth Nielsen + + * da.po: Updated Danish translation by Ask H. Larsen + +2009-02-15 Chao-Hsiung Liao + + * zh_HK.po: Updated Traditional Chinese translation(Hong Kong). + * zh_TW.po: Updated Traditional Chinese translation(Taiwan). + +2009-02-14 Ihar Hrachyshka + + * be@latin.po: Updated Belarusian Latin translation by Ihar Hrachyshka. + +2009-02-13 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2009-02-12 Inaki Larranaga Murgoitio + + * eu.po: Updated Basque translation. + +2009-02-11 Daniel Nylander + + * sv.po: Updated Swedish translation. + +2009-02-11 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2009-02-10 Gil Forcada + + * ast.po: Updated Asturian translation on behalf of Mikel González. + +2009-02-07 Clytie Siddall + + * vi.po: Updated Vietnamese translation. + +2009-02-03 Jorge Gonzalez + + * es.po: Updated Spanish translation. + +2009-02-01 Gil Forcada + + * ca.po: Updated Catalan translation by David Planella. + +2009-01-31 Jorge Gonzalez + + * es.po: Updated Spanish translation + +2009-01-31 Daniel Nylander + + * sv.po: Updated Swedish translation. + +2009-01-29 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + +2009-01-29 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2009-01-24 Raivis DEjus + + * lv.po: Updated Latvian translation. + +2009-01-22 Yair Hershkovitz + + * he.po: Updated Hebrew translation. + +2009-01-17 Thomas Thurman + + * ig.po: Added Igbo translation by Sylvester Onye. + * yo.po Added Yoruba translation by Sunday Ayo Fajuyitan. + * ha.po: Added Hausa translation by Saudat Mohammed. + * LINGUAS: added Igbo, Yoruba and Hausa. + +2009-01-17 Gabor Kelemen + + * hu.po: Translation updated. + +2009-01-09 Daniel Nylander + + * sv.po: Updated Swedish translation. + +2009-01-03 甘露(Gan Lu) + + * zh_CN.po: Updated Chinese Simplified translation + +2009-01-03 Priit Laes + + * et.po: Translation updated by Mattias Põldaru + +2008-12-26 Jorge Gonzalez + + * es.po: Updated Spanish translation. + +2008-12-12 Luca Ferretti + + * it.po: Imported updated translation from gnome-2-24 branch. + +2008-12-08 Priit Laes + + * et.po: Translation updated by Mattias Põldaru + +2008-11-23 Jorge Gonzalez + + * es.po: Updated Spanish translation + +2008-11-14 Thomas Thurman + + * la.po: Updated Latin translation + +2008-11-14 Jorge Gonzalez + + * es.po: Updated Spanish translation + +2008-11-09 Jorge Gonzalez + + * es.po: Updated Spanish translation + +2008-11-08 Jorge Gonzalez + + * es.po: Updated Spanish translation + +2008-11-03 Leonardo Ferreira Fontenelle + + * pt_BR.po: Merged from branch gnome-2-24. Minor capitalization fix in + the Brazilian Portuguese translation. + +2008-10-27 Og Maciel + + * pt_BR.po: Updated Brazilian Portuguese translation by + Og Maciel. + +2008-10-27 Daniel Nylander + + * sv.po: Updated Swedish translation. + +2008-10-23 Gil Forcada + + * LINGUAS: Added ast. + * ast.po: Added Asturian translation on behalf of Mikel González. + +2008-10-22 Jordi Mallach + + * ca@valencia.po: New Valencian (Southern Catalan) translation + based on the Catalan file. + * LINGUAS: Added Valencian (Southern Catalan) (ca@valencia). + +2008-10-22 Jordi Mallach + + * ca.po: Apply Catalan fixes from Robert Millan. + +2008-10-17 Thomas Thurman + + * la.po: Updated Latin translation. + +2008-10-16 Marcel Telka + + * sk.po: Updated Slovak translation by Pavol Šimo. + +2008-10-15 Thomas Thurman + + * la.po: Updated Latin translation. + +2008-10-15 Thomas Thurman + + * la.po: Updated Latin translation. + +2008-10-12 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + +2008-10-12 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation (merged from gnome-2-24 branch). + +2008-10-11 Claude Paroz + + * fr.po: Fixed minimize/unmaximize French translation (sync with 2.24) and + complete some other translations. + +2008-09-30 Og Maciel + + * pt_BR.po: Updated Brazilian Portuguese translation by Vladimir Melo. + +2008-09-29 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Alexander Shopov + +2008-09-27 Gil Forcada + + * ca.po: Updated Catalan translation. + +2008-09-27 Laurent Dhima + + * sq.po: Updated Albanian Translation. + +2008-09-24 Priit Laes + + * et.po: Translation updated by Ivar Smolin + +2008-09-22 Kenneth Nielsen + + * da.po: Updated Danish translation by Kenneth Nielsen + +2008-09-22 Kenneth Nielsen + + * da.po: Updated Danish translation by Kenneth Nielsen + +2008-09-22 Mugurel Tudor + + * ro.po: Updated Romanian translation by + Mişu Moldovan + +2008-09-21 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2008-09-21 Gintautas Miliauskas + + * lt.po: Updated Lithuanian translation. + +2008-09-20 Priit Laes + + * et.po: Translation updated by Ivar Smolin + +2008-09-17 Gabor Kelemen + + * hu.po: Translation updated. + +2008-09-14 Duarte Loreto + + * pt.po: Fixed Portuguese terminology. + +2008-09-12 Hendrik Richter + + * de.po: Updated German translation. + +2008-09-12 Goran Rakić + + * sr.po, sr@latin.po: Updated Serbian translation (by Miloš Popović). + +2008-09-09 Robert Sedak + + * hr.po: Updated Croatian translation. + +2008-09-08 Priit Laes + + * et.po: Translation updated by Mattias Põldaru + +2008-09-07 Seán de Búrca + + * ga.po: Updated Irish translation. + +2008-09-06 Funda Wang + + * zh_CN.po: Updated zh_CN translation. + +2008-09-06 Claude Paroz + + * fr.po: Updated French translation. + +2008-08-24 Gintautas Miliauskas + + * lt.po: Updated Lithuanian translation. + +2008-08-23 Inaki Larranaga Murgoitio + + * eu.po: Updated Basque translation. + +2008-08-21 Laurent Dhima + + * sq.po: Updated Albanian Translation. + +2008-08-14 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2008-08-13 Leonardo Ferreira Fontenelle + + * pt_BR.po: Brazilian Portuguese translation updated by Djavan + Fagundes. + +2008-08-13 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + +2008-08-09 Petr Kovar + + * cs.po: Updated Czech translation. + +2008-08-07 Ignacio Casal Quinteiro + + gl.po: Updated Galician translation + +2008-08-6 Djihed Afifi + + * ar.po: Updated Arabic Translation by Khaled Hosny. + +2008-08-02 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2008-07-29 Djihed Afifi + + * ar.po: Updated Arabic Translation by Khaled Hosny. + +2008-07-29 Wouter Bolsterlee + + * nl.po: Dutch translation updated by Wouter Bolsterlee. + +2008-07-25 Daniel Nylander + + * sv.po: Updated Swedish translation. + +2008-07-24 Leonardo Ferreira Fontenelle + + * pt_BR.po: Terminology fixes by Vladimir Melo. + +2008-07-17 Daniel Nylander + + * sv.po: Updated Swedish translation. + +2008-07-14 Luca Ferretti + + * it.po: Updated Italian translation. + +2008-07-10 Matej Urbančič + + * sl.po: Updated Slovenian Translation. + +2008-07-10 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2008-07-09 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + +2008-07-01 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + +2008-06-24 Daniel Nylander + + * sv.po: Updated Swedish translation. + +2008-06-21 Gabor Kelemen + + * hu.po: Translation updated. + +2008-06-16 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Yavor Doganov + +2008-06-15 Jorge Gonzalez + + * es.po: Updated Spanish translation + +2008-06-12 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2008-06-11 Djihed Afifi + + * ar.po: Updated Arabic Translation by Khaled Hosny. + +2008-06-11 Yannig Marchegay + + * oc.po: Updated Occitan translation. + +2008-06-08 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + +2008-06-01 Clytie Siddall + + * vi.po: Updated Vietnamese translation. + +2008-05-22 Djihed Afifi + + * ar.po: Updated Arabic Translation by Khaled Hosny. + +2008-05-20 Vincent van Adrighem + + * nl.po: Translation updated by Tino Meinen. + +2008-05-19 Djihed Afifi + + * ar.po: Updated Arabic Translation by Khaled Hosny. + +2008-05-18 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2008-05-14 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + +2008-05-13 Vincent van Adrighem + + * nl.po: Translation updated by Tino Meinen. + +2008-05-06 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + +2008-05-01 Gabor Kelemen + + * hu.po: Translation updated. + +2008-04-20 Yair Hershkovitz + + * he.po: Updated Hebrew translation. + +2008-04-10 Yair Hershkovitz + + * he.po: Updated Hebrew translation. + +2008-04-04 Eskild Hustvedt + + * nn.po: Updated Norwegian Nynorsk translation + +2008-03-31 Baris Cicek + + * tr.po: Updated Turkish translation + +2008-03-30 Jorge Gonzalez + + * es.po: Updated Spanish translation + +2008-03-23 Nguyễn Thái Ngọc Duy + + * vi.po: Update Vietnamese translation + +2008-03-20 Abel Cheung + + * zh_HK.po, zh_TW.po: Typo fix for traditional Chinese translations. + +2008-03-18 Gabor Kelemen + + * hu.po: Translation updated + +2008-03-09 Kenneth Nielsen + + * da.po: Updated Danish translation + +2008-03-09 Gabor Kelemen + + * hu.po: Translation updated + +2008-03-09 Daniel Nylander + + * sv.po: Updated Swedish translation. + +2008-03-09 Vasiliy Faronov + + * ru.po: Updated Russian translation. + +2008-03-07 Maxim Dziumanenko + + * uk.po: Updated Ukrainian translation. + +2008-03-03 Jorge Gonzalez + + * es.po: Updated Spanish translation + +2008-03-01 Chao-Hsiung Liao + + * zh_HK.po: Updated Traditional Chinese translation(Hong Kong). + * zh_TW.po: Updated Traditional Chinese translation(Taiwan). + +2008-02-27 Stéphane Raimbault + + * fr.po: Updated French translation (merged from gnome-2-22). + +2008-02-25 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2008-02-24 Ilkka Tuohela + + * fi.po: Updated Finnish translation (bug #518255). + +2008-02-23 Ihar Hrachyshka + + * be@latin.po: Updated Belarusian Latin translation. + +2008-02-20 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + +2008-02-18 Wouter Bolsterlee + + * nl.po: Updated Dutch translation by Wouter Bolsterlee. + +2008-02-18 Ihar Hrachyshka + + * be@latin.po: Updated Belarusian Latin translation. + +2008-02-15 Runa Bhattacharjee + + * kn.po: Added Kannada Translations by Shankar Prasad + * LINGUAS: Added Kannada (kn) to the List of Languages + +2008-02-14 Ignacio Casal Quinteiro + + * gl.po: Updated Galician Translation. + +2008-02-14 Pawan Chitrakar + + * ne.po: Updated Nepali Translation. + +2008-02-14 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + +2008-02-13 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + +2008-02-10 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2008-02-09 Hendrik Brandt + + * de.po: Updated German translation. + +2008-02-07 Artur Flinta + + * pl.po: Updated Polish translation by GNOME PL Team. + +2008-02-05 Rhys Jones + + * cy.po: Updated Welsh translation. + +2008-02-03 Amitakhya Phukan + + * LINGUAS: Added as to LINGUAS. + * as.po: Updated assamese translations. + +2008-02-03 Arangel Angov + + * mk.po: Updated Macedonian translation. + +2008-02-03 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2008-02-02 Luca Ferretti + + * it.po: Updated Italian translation. + +2008-02-01 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2008-01-31 Djihed Afifi + + * ar.po: Updated Arabic Translation by Khaled Hosny. + +2008-01-30 Rahul Bhalerao + + * mr.po: Updated Marathi translations by Sandeep Shedmake. + +2008-01-27 Baris Cicek + + * tr.po: Fixed typo in Turkish translation. + +2008-01-25 Petr Kovar + + * cs.po: Updated Czech translation. + +2008-01-22 Andre Klapper + + * de.po: Sync "beep" translation. + +2008-01-15 Daniel Nylander + + * sv.po: Updated Swedish translation. + +2008-01-14 Inaki Larranaga Murgoitio + + * eu.po: Updated Basque translation. + +2008-01-14 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + +2008-01-13 Jorge Gonzalez + + * es.po: Updated Spanish translation + +2008-01-09 Yair Hershkovitz + + * he.po: Updated Hebrew translation. + +2008-01-06 Ihar Hrachyshka + + * be@latin.po: Updated Belarusian Latin translation. + +2008-01-05 Clytie Siddall + + * vi.po: Updated Vietnamese translation. + +2007-12-31 Yannig Marchegay + + * oc.po: Updated Occitan translation. + +2007-12-31 Daniel Nylander + + * sv.po: Updated Swedish translation. + +2007-12-22 Seán de Búrca + + * ga.po: Updated Irish translation. + +2007-12-22 Seán de Búrca + + * POTFILES.in: Remove dead files. + +2007-12-20 Kjartan Maraas + + * POTFILES.in: Rearrange after stuff moved around. + * nb.po: Update + +2007-12-19 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + +2007-12-19 Jorge Gonzalez + + * es.po: Updated Spanish translation. + +2007-12-17 Daniel Nylander + + * sv.po: Updated Swedish translation. + +2007-12-15 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + +2007-12-10 Jorge Gonzalez + + * es.po: Updated Spanish translation, fixes bug #500562 and bug #500831 + +2007-12-10 Matej Urbančič + + * sl.po: Updated Slovenian Translation. + +2007-12-10 Jorge Gonzalez + + * es.po: Updated Spanish translation, fixes bug #500831 + +2007-12-09 Jorge Gonzalez + + * es.po: Updated Spanish translation, fixes bug #500562 + +2007-12-08 Jakub Friedl + + * cs.po: Czech Translation updated by Petr Kovar. + +2007-12-08 Ihar Hrachyshka + + * be@latin.po: Updated Belarusian Latin translation. + +2007-12-08 Leonardo Ferreira Fontenelle + + * pt_BR.po: Fixes in Brazilian Portuguese translation by Luiz Armesto. + +2007-12-07 Leonardo Ferreira Fontenelle + + * pt_BR.po: Fixed attributes in Brazilian Portuguese translation by + Rodrigo Flores. + +2007-12-02 Marcel Telka + + * sk.po: Updated Slovak translation by Pavol Šimo. + +2007-11-28 Ignacio Casal Quinteiro + + * gl.po: Updated Galician Translation. + +2007-11-12 Matej Urbančič + + * sl.po: Updated Slovenian translation. + +2007-11-08 Daniel Nylander + + * sv.po: Updated Swedish translation. + +2007-11-01 Jorge Gonzalez + + * es.po: Updated Spanish translation + +2007-10-25 Matej Urbančič + + * sl.po: Updated Slovenian translation. + +2007-10-23 Djihed Afifi + + * ar.po: Updated Arabic Translation by Djihed Afifi. + +2007-10-21 Djihed Afifi + + * ar.po: Updated Arabic Translation by Djihed Afifi. + +2007-09-30 Stéphane Raimbault + + * fr.po: Fixed French translation. + +2007-09-27 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2007-09-25 Gil Forcada + + * ca.po: Fixed a string in Catalan translation thanks to Sílvia Miranda. + +2007-09-21 Gil Forcada + + * ca.po: Updated Catalan translation by Joan Duran. + +2007-09-17 Artur Flinta + + * pl.po: Updated Polish translation by GNOME PL Team. + +2007-09-17 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Alexander Shopov + +2007-09-17 Wouter Bolsterlee + + * nl.po: Translation updated by Wouter Bolsterlee. + +2007-09-17 Djihed Afifi + + * ar.po: Updated Arabic Translation by Djihed Afifi. + +2007-09-16 Gil Forcada + + * ca.po: Updated Catalan translation. + +2007-09-16 Takeshi AIHANA + + * ja.po: Translation improved. + +2007-09-16 Mugurel Tudor + + * ro.po: Updated Romanian translation + +2007-09-15 Nickolay V. Shmyrev + + * ru.po: Updated Russian translation. + +2007-09-15 Stéphane Raimbault + + * fr.po: Fixed French translation by Vincent Untz and Stéphane + Raimbault. + +2007-09-15 Andre Klapper + + * sk.po: Updated Slovak translation on behalf of Peter Tuharsky + . + +2007-09-14 Clytie Siddall + + * vi.po: Updated Vietnamese translation. + +2007-09-14 Luca Ferretti + + * it.po: Updated Italian translation. + +2007-09-13 Djihed Afifi + + * ar.po: Updated Arabic Translation by Khaled Hosny. + +2007-09-14 Gabor Kelemen + + * hu.po: Translation updated. + +2007-09-13 Ihar Hrachyshka + + * be@latin.po: Updated Belarusian Latin translation. + +2007-09-12 Maxim Dziumanenko + + * uk.po: Update Ukrainian translation. + +2007-09-12 Goran Rakić + + * sr.po, sr@Latn.po: Updated Serbian translation. + +2007-09-09 Kenneth Nielsen + + * da.po: Updated Danish translation + +2007-09-08 Inaki Larranaga Murgoitio + + * eu.po: Fixed some typos in Basque translation. + +2007-09-05 Jovan Naumovski + + * mk.po: Updated Macedonian translation. + +2007-09-03 Clytie Siddall + + * vi.po: Updated Vietnamese translation. + +2007-09-03 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2007-09-03 Jovan Naumovski + + * mk.po: Updated Macedonian translation. + +2007-09-01 Jovan Naumovski + + * mk.po: Updated Macedonian translation. + +2007-09-01 Stéphane Raimbault + + * fr.po: Updated French translation. + +2007-08-30 Ani Peter + + * ml.po: Updated Malayalam Translation + +2007-08-29 I. Felix + + * ta.po: Tamil Translation updated by Tirumurthi Vasudevan + +2007-08-26 Raphael Higino + + * pt_BR.po: Updated Brazilian Portuguese translation + by Og Maciel . + +2007-08-15 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2007-08-13 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2007-08-13 Žygimantas Beručka + + * lt.po: Updated Lithuanian translation. + +2007-08-11 Daniel Nylander + + * sv.po: Updated Swedish translation. + +2007-08-10 I. Felix + + * ta.po: Tamil Translation updated by Tirumurthi Vasudevan + +2007-08-10 Ankit Patel + + * gu.po: Updated Gujarati Translation. + +2007-08-09 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + +2007-08-08 Ankit Patel + + * gu.po: Updated Gujarati Translation. + +2007-08-07 Jorge Gonzalez + + * es.po: Updated Spanish translation + +2007-08-07 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2007-08-06 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + +2007-08-05 Inaki Laranaga Murgoitio + + * eu.po: Updated Basque translation. + +2007-07-25 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Alexander Shopov + +2007-07-21 Gabor Kelemen + + * hu.po: Translation updated. + +2007-07-18 Vincent van Adrighem + + * nl.po: Translation updated. + +2007-07-17 Daniel Nylander + + * sv.po: Updated Swedish translation. + +2007-07-16 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + +2007-07-10 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2007-07-08 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2007-07-02 Nguyễn Thái Ngọc Duy + + * vi.po: Updated Vietnamese translation. + +2007-06-27 Clytie Siddall + + * vi.po: Updated Vietnamese translation. + +2007-06-25 Jorge Gonzalez + + * es.po: Updated Spanish translation + +2007-06-24 Kjartan Maraas + + * POTFILES.in: Add src/core.c + * nb.po: Updated Norwegian bokmål translation. + +2007-06-19 Jorge Gonzalez + + * es.po: Updated Spanish translation + +2007-06-16 Funda Wang + + * zh_CN.po: Updated Simplified Chinese translation + +2007-06-15 Jorge Gonzalez + + * es.po: Updated Spanish translation + +2007-06-13 Pema Geyleg + + * dz.po: Updated dzongkha translation + +2007-05-18 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2007-05-09 Jovan Naumovski + + * mk.po: Updated Macedonian translation. + +2007-05-2 Djihed Afifi + + * ar.po: Updated Arabic Translation by Khaled Hosny. + +2007-04-24 Ihar Hrachyshka + + * be@latin.po: Updated Belarusian Latin translation. + +2007-04-23 David Lodge + + * en_GB.po: Updated British English translation + +2007-04-22 Ignacio Casal Quinteiro + + * gl.po: Updated Galician Translation. + +2007-04-22 Jorge Gonzalez + + * es.po: Updated Spanish translation. + +2007-04-21 Daniel Nylander + + * sv.po: Updated Swedish translation. + +2007-04-14 Djihed Afifi + + * ar.po: Updated Arabic Translation by Khaled Hosny. + +2007-04-10 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + +2007-04-05 Bastien Nocera + + * POTFILES.in: add the XML keys definitions to the list + +2007-04-05 Raivis Dejus + + * lv.po: Updated Latvian Translation. + +2007-04-02 Alessio Frusciante + + * it.po: Fixed a typo in translation. Closes #420494. + +2007-03-30 Ihar Hrachyshka + + * be@latin.po: Added Belarusian Latin translation by Ales Navicki. + +2007-03-29 Priit Laes + + * et.po: Updated Estonian translation by Ivar Smolin . + +2007-03-27 Gabor Kelemen + + * hu.po: Translation updated. + +2007-03-17 Kjartan Maraas + + reviewed by: + + * nb.po: + +2007-03-14 David Lodge + + * en_GB.po: Updated English (British) translation + +2007-03-12 Jakub Friedl + + * cs.po: Updated Czech translation. + +2007-03-11 Goran Rakić + + * sr.po, sr@Latn.po: Updated Serbian translation. + +2007-03-11 Josep Puigdemont i Casamajó + + * ca.po: Updated Catalan translation by + Jordi Mallach . + +2007-03-10 Artur Flinta + + * pl.po: Updated Polish translation by GNOME PL Team. + +2007-03-09 Nickolay V. Shmyrev + + * ru.po: Updated Russian translation. + +2007-03-07 Artur Flinta + + * pl.po: Updated Polish translation by GNOME PL Team. + +2007-03-06 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2007-03-06 Jovan Naumovski + + * mk.po: Updated Macedonian translation. + +2007-03-05 Vincent van Adrighem + + * nl.po: Translation updated by Reinout van Schouwen. + +2007-03-04 Gintautas Miliauskas + + * lt.po: Updated Lithuanian translation. + +2007-03-04 Erdal Ronahi + + * ku.po: Updated Kurdish translations + +2007-03-04 Pema Geyleg + + * dz.po: Updated Dzongkha Translation. + +2007-03-04 Chao-Hsiung Liao + + * zh_HK.po: Updated Traditional Chinese translation(Hong Kong). + * zh_TW.po: Updated Traditional Chinese translation(Taiwan). + +2007-03-02 Leonardo Ferreira Fontenelle + + * pt_BR.po: Updated Brazilian Portuguese translation by Leonardo + Ferreira Fontenelle (me!) and Raul Pereira + . + +2007-02-27 Gintautas Miliauskas + + * lt.po: Updated Lithuanian translation. + +2007-02-26 Luca Ferretti + + * it.po: Updated Italian translation. + +2007-02-25 Gabor Kelemen + + * hu.po: Translation updated. + +2007-02-24 Raphael Higino + + * pt_BR.po: Updated Brazilian Portuguese translation. + +2007-02-24 Nguyễn Thái Ngọc Duy + + * vi.po: Updated Vietnamese translation. + +2007-02-22 Abel Cheung + + * zh_CN.po: Updated simplified Chinese translation on behalf of + Funda Wang. + +2007-02-21 Maxim Dziumanenko + + * uk.po: Update Ukrainian translation. + +2007-02-21 Artur Flinta + + * pl.po: Updated Polish translation by GNOME PL Team. + +2007-02-20 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Alexander Shopov + +2007-02-16 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + +2007-02-15 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2007-02-15 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2007-02-14 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + +2007-02-09 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2007-01-31 Stéphane Raimbault + + * fr.po: Updated French translation by Robert-André Mauchin. + +2007-01-27 Priit Laes + + * et.po: Updated Estonian translation by Ivar Smolin . + +2007-01-22 Jakub Friedl + + * cs.po: Updated Czech translation. + +2007-01-16 Hendrik Richter + + * de.po: Updated German translation. + +2007-01-15 Djihed Afifi + + * ar.po: Updated Arabic Translation by Khaled Hosny. + +2007-01-13 Daniel Nylander + + * sv.po: Updated Swedish translation. + +2007-01-05 Jakub Friedl + + * cs.po: Updated Czech translation. + +2007-01-3 Djihed Afifi + + * ar.po: Updated Arabic Translation by Djihed Afifi. + +2007-01-01 David Lodge + + * en_GB.po: Updated English (British) translation + +2006-12-29 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + +2006-12-29 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2006-12-27 Djihed Afifi + + * ar.po: Updated Arabic Translation. + +2006-12-24 Djihed Afifi + + * ar.po: Updated Arabic Translation. + +2006-12-23 Raivis Dejus + + * lv.po: Updated Latvian Translation. + +2006-12-18 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + +2006-12-18 Djihed Afifi + + * ar.po: Updated Arabic Translation. + +2006-12-18 Ales Nyakhaychyk + + * be.po: Updated Belarusian Translation by Ihar Hrachyshka. + +2006-12-15 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2006-12-13 Mugurel Tudor + + * ro.po: Updated Romanian translation. + +2006-12-11 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2006-12-11 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + +2006-12-04 Jakub Friedl + + * cs.po: Updated Czech translation. + +2006-11-22 Yair Hershkovitz + + * he.po: Updated Hebrew translation. + +2006-11-19 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2006-11-19 Duarte Loreto + + * pt.po: Partial updated Portuguese translation. + +2006-11-19 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2006-11-18 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2006-11-07 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2006-11-03 Jakub Friedl + + * cs.po: Updated Czech translation. + +2006-10-26 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2006-10-26 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + +2006-10-26 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + +2006-10-22 Christophe Merlet + + * fr.po: Updated French translation. + +2006-10-19 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + +2006-10-15 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + +2006-10-02 Josep Puigdemont i Casamajó + + * ca.po: Updated Catalan translation. + +2006-09-29 Alexander Shopov + + * bg.po: Updated Bulgarian translation with + bugfixes prompted by Yavor Doganov + +2006-09-21 Gabor Kelemen + + * hu.po: Translation updated. + +2006-09-19 Runa Bhattacharjee + + * bn_IN.po: Updated Bengali India Translation. + +2006-09-15 Wouter Bolsterlee + + * nl.po: Translation updated by Wouter Bolsterlee. + +2006-09-15 Matic Zgur + + * sl.po: Updated Slovenian translation. + +2006-09-14 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2006-09-14 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Alexander Shopov + +2006-09-13 Josep Puigdemont i Casamajó + + * ca.po: Updated Catalan translation. + +2006-09-13 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + - concistency fixes with libwnck + +2006-09-13 Rajesh Ranjan + + * hi.po: Updated Hindi Translation. + +2006-09-13 Abel Cheung + + * zh_HK.po: Updated Chinese (Hong Kong) translation. + * zh_TW.po: Updated Chinese (Taiwan) translation. + +2006-09-13 Ani Peter + + * ml.po: Updated Malayalam translation + +2006-09-13 I.Felix + + * ta.po: Updated Tamil Translation. + +2006-09-13 Ankit Patel + + * gu.po: Updated Gujarati Translation. + +2006-09-13 Ahmad Riza H Nst + + * id.po: Updated. + +2006-09-10 David Lodge + + * en_GB.po: Updated English (British) translation. + +2006-09-08 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2006-09-07 Matic Zgur + + * sl.po: Updated Slovenian translation. + +2006-09-04 Nickolay V. Shmyrev + + * ru.po: Updated Russian translation by + Vasiliy Faronov . + +2006-09-04 Rahul Bhalerao + + * mr.po: Updated Marathi translations. + +2006-09-04 Runa Bhattacharjee + + * bn_IN.po: Modified the accelerators to English. + +2006-09-04 Abel Cheung + + * zh_HK.po: Updated Chinese (Hong Kong) translation from + Woodman Tuen . + * zh_TW.po: Updated Chinese (Taiwan) translation from + Woodman Tuen . + +2006-09-04 Kostas Papadimas + + * el.po: Updated Greek translation. + +2006-09-04 Ani Peter + + * ml.po: Updated Malayalam translation + +2006-09-04 Rahul Bhalerao + + * mr.po: Added the file and updated Marathi translation. + * LINGUAS: Added an entry for Marathi(mr). + +2006-09-03 Christophe Merlet + + * fr.po: Updated French translation from + Jonathan Ernst . + +2006-09-03 Danilo Šegan + + * sr.po, sr@Latn.po: Updated by Goran Rakić. + +2006-09-03 Gabor Kelemen + + * hu.po: Translation updated. + +2006-09-03 Gabor Kelemen + + * hu.po: Translation updated. + +2006-09-01 Maxim Dziumanenko + + * uk.po: Update Ukrainian translation. + +2006-09-01 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2006-08-30 Josep Puigdemont i Casamajó + + * ca.po: Updated Catalan translation. + +2006-08-27 Gintautas Miliauskas + + * lt.po: Updated Lithuanian translation. + +2006-08-20 Daniel Nylander + + * sv.po: Updated Swedish translation. + +2006-08-19 Ahmad Riza H Nst + + * id.po: Updated. + +2006-08-18 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Alexander Shopov + +2006-08-17 Jordi Mas + + * ca.po: Fixes small mistakes in Catalan translation + +2006-08-16 Gabor Kelemen + + * hu.po: Translation updated. + +2006-08-13 Wouter Bolsterlee + + * nl.po: Translation updated by Wouter Bolsterlee. + +2006-08-09 Funda Wang + + * zh_CN.po: Updated Simplified Chinese translation. + +2006-08-08 Wouter Bolsterlee + + * nl.po: Translation updated by Wouter Bolsterlee. + +2006-08-07 Leonid Kanter + + * ru.po: Updated Russian translation + +2006-08-07 Inaki Larranaga + + * eu.po: Fixed some typos. + +2006-08-03 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + +2006-08-03 Yair Hershkovitz + + * he.po: Updated Hebrew translation. + +2006-08-02 Jovan Naumovski + + * mk.po: Updated Macedonian translation. + +2006-07-31 Jakub Friedl + + * cs.po: Updated Czech translation. + +2006-07-23 Satoru SATOH + + * ja.po: Updated Japanese translation. + +2006-07-22 Christophe Merlet + + * fr.po: Updated French translation from + Jonathan Ernst . + +2006-07-22 Kostas Papadimas + + * el.po: Updated Greek translation + +2006-07-21 Christophe Merlet + + * fr.po: Updated French translation from + Jonathan Ernst . + +2006-07-18 Hendrik Richter + + * de.po: Updated German translation. + +2006-07-03 Runa Bhattacharjee + + * bn_IN.po: Added Bengali India Translation + * LINGUAS: Added Bengali India (bn_IN) to the list of languages. + +2006-07-03 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + +2006-06-29 Thierry Randrianiriana + + * mg.po: Added Malagasy translation + +2006-06-28 Rajesh Ranjan + + * hi.po: Updated Hindi Translation. + +2006-06-27 Rajesh Ranjan + + * hi.po: Updated Hindi Translation. + +2006-06-26 Rajesh Ranjan + + * hi.po: Updated Hindi Translation. + +2006-05-28 Pema Geyleg + + * dz.po: Updated Dzongkha translation. + +2006-05-26 Clytie Siddall + + * vi.po: Updated Vietnamese translation. + +2006-05-25 Inaki Larranaga + + * eu.po: Updated Basque translation. + +2006-05-23 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2006-05-14 Chao-Hsiung Liao + + * zh_HK.po: Updated Traditional Chinese translation(Hong Kong). + * zh_TW.po: Updated Traditional Chinese translation(Taiwan). + +2006-05-10 Ignacio Casal Quinteiro + + * gl.po: Updated Galician Translation. + +2006-05-06 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2006-05-02 Funda Wang + + * zh_CN.po: Updated Simplified Chinese translation. + +2006-04-30 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + +2006-04-26 Gora Mohanty + + * lv.po: Updated Latvian translation by Raivis Dejus + +2006-04-21 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2006-04-20 Ankit Patel + + * gu.po: Updated Gujarati Translation. + +2006-04-19 Ankit Patel + + * gu.po: Updated Gujarati Translation. + +2006-04-17 Clytie Siddall + + * vi.po: Updated Vietnamese translation. + +2006-04-17 Josep Puigdemont Casamajó + + * ca.po: Updated Catalan translation. + +2006-04-16 Funda Wang + + * zh_CN.po: Updated Simplified Chinese translation. + +2006-04-14 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2006-04-14 Raphael Higino + + * pt_BR.po: Updated Brazilian Portuguese translation. + +2006-04-14 Åsmund Skjæveland + + * nn.po: Updated Norwegian Nynorsk translation. + +2006-04-14 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + +2006-04-14 Wouter Bolsterlee + + * nl.po: Translation updated by Wouter Bolsterlee. + +2006-04-14 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Alexander Shopov + +2006-04-09 Vincent van Adrighem + + * nl.po: Translation updated by Michiel Sikkes. + +2006-04-02 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + * no.po: Same. + +2006-03-24 Gora Mohanty + + * or.po: Updated Oriya translation. + +2006-03-21 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2006-03-17 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2006-03-15 Žygimantas Beručka + + * lt.po: Updated Lithuanian translation. + +2006-03-14 Mugurel Tudor + + * ro.po: Updated Romanian translation + +2006-03-14 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2006-03-13 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2006-03-13 Vincent van Adrighem + + * nl.po: Translation updated by Tino Meinen. + +2006-03-13 Danilo Šegan + + * sr.po, sr@Latn.po: Updated Serbian translation. + +2006-03-13 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Alexander Shopov + +2006-03-13 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2006-03-13 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2006-03-13 Maxim Dziumanenko + + * uk.po: Updated Ukrainian translation. + +2006-03-13 Rajesh Ranjan + + * hi.po: Updated Hindi Translation. + +2006-03-13 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation (merged from gnome-2-14 branch). + +2006-03-13 Satoru SATOH + + * ja.po: Updated Japanese translation. + +2006-03-13 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2006-03-12 Guilherme de S. Pastore + + * pt_BR.po: Updated Brazilian Portuguese translation. + +2006-03-13 Frank Arnold + + * de.po: Updated German translation. + +2006-03-13 Daniel Nylander + + * sv.po: Updated Swedish translation. + +2006-03-12 Ignacio Casal Quinteiro + + * gl.po: Updated Galician Translation. + +2006-03-12 Raphael Higino + + * pt_BR.po: Updated Brazilian Portuguese translation. + +2006-03-12 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2006-03-12 Miloslav Trmac + + * cs.po: Updated Czech translation by Petr Tomeš. + +2006-03-12 Roozbeh Pournader + + * fa.po: Updated Persian translation by Meelad Zakaria, + Elnaz Sarbar, and Farzaneh Sarafraz. + +2006-03-09 Hendrik Richter + + * de.po: Updated German translation. + +2006-03-09 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2006-03-08 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2006-03-08 Gabor Kelemen + + * hu.po: Hungarian translation updated. + +2006-03-06 Funda Wang + + * zh_CN.po: Updated Simplified Chinese translation. + +2006-03-06 Daniel Nylander + + * sv.po: Updated Swedish translation + +2006-03-05 Mugurel Tudor + + * ro.po: Updated Romanian translation + +2006-03-05 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Alexander Shopov + +2006-03-04 Hendrik Richter + + * de.po: Updated German translation. + +2006-03-03 Maxim Dziumanenko + + * uk.po: Updated Ukrainian translation. + +2006-03-02 Hendrik Richter + + * de.po: Updated German translation. + +2006-03-02 Hendrik Richter + + * de.po: Updated German translation. + +2006-03-02 Rhys Jones + + * cy.po: Updated Welsh translation. + +2006-03-01 Leonid Kanter + + * ru.po: Updated Russian translation + +2006-03-01 Josep Puigdemont i Casamajó + + * ca.po: Updated Catalan translation. + +2006-02-27 Leonid Kanter + + * ru.po: Updated Russian translation + +2006-02-27 Lasse Bang Mikkelsen + + * da.po: Updated Danish translation. + +2006-02-25 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2006-02-23 Inaki Larranaga + + * eu.po: Updated Basque translation. + +2006-02-23 Clytie Siddall + + * ka.po: Added Georgian translation by Alexander Didebulidze . + +2006-02-23 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2006-02-23 Žygimantas Beručka + + * lt.po: Updated Lithuanian translation. + +2006-02-21 Vincent van Adrighem + + * nl.po: Translation updated by Tino Meinen. + +2006-02-21 Clytie Siddall + + * vi.po: Updated Vietnamese translation. + +2006-02-21 Slobodan D. Sredojevic + + * sr.po, sr@Latn.po: Updated Serbian translation + +2006-02-21 Ignacio Casal Quinteiro + + * gl.po: Updated Galician Translation. + +2006-02-01 Ankit Patel + + * gu.po: Updated Gujarati Translation. + +2006-02-20 Kostas Papadimas + + * el.po: Updated Greek translation. + +2006-02-20 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + +2006-02-18 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2006-02-18 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2006-02-18 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + * no.po: Same. + +2006-02-13 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2006-02-06 Funda Wang + + * zh_CN.po: Updated Simplified Chinese translation. + +2006-02-03 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + * no.po: Same. + +2006-01-31 Vincent van Adrighem + + * nl.po: Translation updated by Tino Meinen. + +2006-01-31 Slobodan D. Sredojevic + + * sr.po, sr@Latn.po: Updated Serbian translation + +2006-01-28 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2006-01-27 Josep Puigdemont i Casamajó + + * ca.po: Updated Catalan translation. + +2006-01-26 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2006-01-26 Evandro Fernandes Giovanini + + * pt_BR.po: Updated Brazilian Portuguese translation. + +2006-01-24 Ignacio Casal Quinteiro + + * gl.po: Updated Galician Translation. + +2006-01-23 Ankit Patel + + * gu.po: Updated Gujarati Translation. + +2006-01-23 Funda Wang + + * zh_CN.po: Updated Simplified Chinese translation. + +2006-01-22 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + * no.po: Same. + +2006-01-21 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + +2006-01-22 Clytie Siddall + + * vi.po: Updated Vietnamese translation. + +2006-01-21 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + +2006-01-21 Francisco Javier F. Serrador + + * es.po: Updated Spanish tranlation. + +2006-01-21 Ignacio Casal Quinteiro + + * gl.po: Updated Galician Translation. + +2006-01-20 Vincent van Adrighem + + * nl.po: Translation updated by Tino Meinen. + +2006-01-18 Funda Wang + + * zh_CN.po: Updated Simplified Chinese translation. + +2006-01-17 Ignacio Casal Quinteiro + + * gl.po: Updated Galician Translation. + +2006-01-16 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + +2006-01-15 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2006-01-15 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2006-01-11 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2006-01-11 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2006-01-11 Ankit Patel + + * gu.po: Updated Gujarati Translation. + +2006-01-11 Clytie Siddall + + * vi.po: Updated Vietnamese translation. + +2005-12-30 Clytie Siddall + + * vi.po: Updated Vietnamese translation. + +2006-01-06 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + * no.po: Same + +2005-12-31 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + +2005-12-25 Kang Jeong-Hee + + * ko.po: Updated Korean translation. + +2005-12-11 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2005-12-11 Ankit Patel + + * gu.po: Updated Gujarati Translation. + +2005-12-03 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2005-12-03 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + * no.po: Same + +2005-11-22 Marcel Telka + + * sk.po: Updated Slovak translation. + +2005-11-22 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Alexander Shopov + +2005-11-22 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2005-11-21 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2005-11-20 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2005-11-20 Ignacio Casal Quinteiro + + * gl.po: Updated Galician Translation. + +2005-11-20 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2005-11-17 Vincent van Adrighem + + * nl.po: Translation updated by Wouter Bolsterlee. + +2005-11-13 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2005-11-03 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2005-10-28 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2005-10-28 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2005-10-27 Erdal Ronahi + + * ku.po: Added Kurdish translation. + +2005-10-17 Marcel Telka + + * sk.po: Updated Slovak translation. + +2005-10-15 Vincent van Adrighem + + * nl.po: Translation updated. + +2005-10-14 Vincent van Adrighem + + * nl.po: Translation updated. + +2005-10-14 Kostas Papadimas + + * el.po: Updated Greek translation. + +2005-10-10 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2005-10-04 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Alexander Shopov + +2005-10-04 Funda Wang + + * zh_CN.po: Updated Simplified Chinese translation. + +2005-10-04 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2005-10-03 Runa Bhattacharjee + * bn.po: Updated Bengali Translation by Mahay Alam Khan + +2005-10-02 Christian Rose + + * sv.po: Reverted unauthorized changes made by + user 'kloczek'. + +2005-09-26 Alessio Frusciante + + * it.po: Updated Italian translation by + Luca Ferretti . + +2005-09-24 Funda Wang + + * zh_CN.po: Updated Simplified Chinese translation. + +2005-09-21 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2005-09-20 Christian Rose + + * sv.po: Updated Swedish translation. + +2005-09-16 Clytie Siddall + + * vi.po: Updated Vietnamese translation. + +2005-09-08 Inaki Larranaga + + * eu.po: Updated Basque translation. + +2005-09-07 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2005-09-04 Danilo Šegan + + * hy.po: Added Armenian translation by Norayr Chilingaryan + . + +2005-09-04 Ignacio Casal Quinteiro + + * gl.po: Updated Galician Translation. + +2005-09-03 Danilo Šegan + + * sr.po, sr@Latn.po: Updated. + +2005-09-02 Leonid Kanter + + * ru.po: Updated Russian translation + +2005-09-01 Baris Cicek + + * tr.po: Updated Turkish Translation + +2005-08-31 Žygimantas Beručka + + * lt.po: Updated Lithuanian translation. + +2005-08-30 Hendrik Richter + + * de.po: Updated German translation. + +2005-08-30 Changwoo Ryu + + * ko.po: Updated Korean translation by Young-Ho Cha. + +2005-08-29 Telsa Gwynne + + * cy.po: Updated Welsh translation. + +2005-08-28 Christophe Merlet + + * fr.po: Updated French translation. + +2005-08-25 Vincent van Adrighem + + * nl.po: Translation updated by Michiel Sikkes. + +2005-08-20 Josep Puigdemont i Casamajó + + * ca.po: Updated Catalan translation. + +2005-08-19 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2005-08-17 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2005-08-15 Maxim Dziumanenko + + * uk.po: Updated Ukrainian translation. + +2005-08-15 Gabor Kelemen + + * hu.po: Hungarian translation updated. + +2005-08-15 Mugurel Tudor + + * ro.po: Updated Romanian translation + +2005-08-14 Mohammad DAMT + + * id.po: Updated Indonesian translation + +2005-08-13 Kostas Papadimas + + * el.po: Updated Greek translation. + +2005-08-11 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2005-08-10 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Rostislav Raykov + +2005-08-02 Chao-Hsiung Liao + + * zh_TW.po: Updated Traditional Chinese translation. + +2005-07-31 Yair Hershkovitz + + * he.po: Updated Hebrew translation by Yuval Tanai. + +2005-07-28 Artur Flinta + + * pl.po: Updated Polish translation by GNOME PL Team. + +2005-07-26 Raphael Higino + + * pt_BR.po: Converted to UTF-8. + +2005-07-26 Raphael Higino + + * pt_BR.po: Updated Brazilian Portuguese translation. + +2005-07-24 Ilkka Tuohela + + * fi.po: Updated Finnish translation. + +2005-07-24 Kjartan Maraas + + * nb.po: Updated Norwegian bokmål translation. + * no.po: Same + +2005-07-23 Clytie Siddall + + * vi.po: Updated Vietnamese translation. + +2005-07-23 Funda Wang + + * zh_CN.po: Updated Simplified Chinese translation. + +2005-07-21 Ankit Patel + + * gu.po: Updated Gujarati Translation. + +2005-07-20 Marcel Telka + + * sk.po: Updated Slovak translation. + +2005-07-18 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2005-07-17 Christophe Merlet + + * fr.po: Updated French translation. + +2005-07-17 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2005-07-17 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2005-07-17 Nikos Charonitakis + + * el.po: Updated Greek translation. + +2005-07-16 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2005-07-15 Ignacio Casal Quinteiro + + * gl.po: Updated Galician Translation. + +2005-07-14 Yair Hershkovitz + + * he.po: Updated Hebrew translation. + +2005-07-14 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2005-07-13 Marcel Telka + + * sk.po: Updated Slovak translation. + +2005-07-12 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2005-07-08 Clytie Siddall + + * vi.po: Updated Vietnamese translation. + +2004-07-06 Christian Rose + + * gl.po: Updated Galician translation by + Ignacio Casal Quinteiro . + +2005-07-04 Hendrik Richter + + * de.po: Fixed German translation by + Jens Seidel . + +2005-06-23 Ignacio Casal Quinteiro + + * gl.po: Updated Galician translation. + +2005-06-22 Abel Cheung + + * zh_TW.po: Fix language team reference. + +2005-06-05 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2005-06-01 Priit Laes + + * et.po: Translation updated. + +2005-05-19 Nikos Charonitakis + + * el.po: Updated Greek translation. + +2005-05-11 Kostas Papadimas + + * el.po: Updated Greek Translation. + +2005-05-10 Adi Attar + + * xh.po: Updated Xhosa translation. + +2005-04-28 Kostas Papadimas + + * el.po: Updated Greek translation + +2005-04-25 Priit Laes + + * et.po: Translation updated by Ivar Smolin. + +2005-04-17 Pauli Virtanen + + * fi.po: Fix a small mistranslation. + +2005-04-09 Christopher Orr + + * en_GB.po: Updated British English translation. + +2005-04-06 Roozbeh Pournader + + * fa.po: Updated Persian translation by + Elnaz Sarbar . + +2005-04-05 Pawan Chitrakar + + * ne.po: Added Nepali Translation. + +2005-04-03 Gabor Kelemen + + * hu.po: Hungarian translation updated. + +2005-03-31 Steve Murphy + + * rw.po: Added Kinyarwanda translation. + +2005-03-29 Adi Attar + + * xh.po: Updated Xhosa translation. + +2005-03-17 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2005-03-12 Baris Cicek + + * tr.po: Updated Turkish Translation + +2005-03-10 Adi Attar + + * xh.po: Added Xhosa translation. + +2005-03-07 Vincent van Adrighem + + * nl.po: Translation updated by Reinout van Schouwen. + +2005-03-07 Mugurel Tudor + + * ro.po: Updated Romanian translation. + +2005-03-04 Laszlo Dvornik + + * hu.po: Hungarian translation updated by Gabor Kelemen. + +2005-03-03 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Vladimir Petkov + +2005-03-03 Žygimantas Beručka + + * lt.po: Updated Lithuanian translation. + +2005-03-02 Danilo Šegan + + * sr.po, sr@Latn.po: Updated Serbian translation. + +2005-03-02 Abel Cheung + + * zh_TW.po: Updated traditional Chinese translation from GNOME HK Team + +2005-02-28 Vincent van Adrighem + + * nl.po: Translation updated by Reinout van Schouwen. + +2005-02-27 Alessio Frusciante + + * it.po: Updated Italian translation by + Luca Ferretti . + +2005-02-24 Artur Flinta + + * pl.po: Updated Polish translation by GNOME PL Team. + +2005-02-24 Ankit Patel + + * gu.po: Updated Gujarati Translation. + +2005-02-23 Vincent van Adrighem + + * nl.po: Translation updated by Michiel Sikkes. + +2004-02-22 Roozbeh Pournader + + * fa.po: Updated Persian translation by + Elnaz Sarbar . + +2005-02-22 Raphael Higino + + * pt_BR.po: Updated Brazilian Portuguese translation. + +2005-02-21 Christophe Merlet + + * fr.po: Updated French translation. + +2005-02-21 Bastien Nocera + + * en_GB.po: the file is actually in UTF-8 + +2005-02-21 Martin Willemoes Hansen + + * da.po: Updated Danish translation. + +2005-02-21 Priit Laes + + * et.po: Translation updated by Tõivo Leedjärv. + +2005-02-18 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2005-02-18 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2005-02-17 Vincent van Adrighem + + * nl.po: Translation updated by Tino Meinen. + +2005-02-17 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2005-02-16 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2005-02-15 Maxim Dziumanenko + + * uk.po: Updated Ukrainian translation. + +2005-02-15 Kjartan Maraas + + * nb.po: s/applikasjon/program + * no.po: Same + +2005-02-12 Marcel Telka + + * sk.po: Updated Slovak translation. + +2005-02-12 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2005-02-11 Kostas Papadimas + + * el.po: Updated Greek translation. + +2005-02-10 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2005-02-08 Leonid Kanter + + * ru.po: Updated Russian translation + +2005-02-08 Kjartan Maraas + + * nb.po: Update + * no.po: Update + +2005-02-07 David Lodge + + * en_GB.po: Updated British translation. + +2005-02-06 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2005-02-06 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2005-02-06 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Vladimir Petkov + +2005-02-06 Pauli Virtanen + + * fi.po: Updated Finnish translation. + +2005-02-05 Frank Arnold + + * de.po: Updated German translation. + +2005-02-05 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2005-02-05 Žygimantas Beručka + + * lt.po: Updated Lithuanian translation. + +2005-02-04 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2005-02-04 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2005-02-02 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2005-02-02 Frank Arnold + + * de.po: Updated German translation. + +2005-02-01 Kjartan Maraas + + * nb.po: Update + * no.po: Update + +2005-02-01 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2005-02-01 Žygimantas Beručka + + * lt.po: Updated Lithuanian translation. + +2005-01-31 Christian Rose + + * sv.po: Updated Swedish translation. + +2005-01-31 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2005-01-31 Christian Rose + + * sv.po: Updated Swedish translation. + +2005-01-30 Žygimantas Beručka + + * lt.po: Updated Lithuanian translation. + +2005-01-29 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2005-01-29 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2005-01-29 Marcel Telka + + * sk.po: Updated Slovak translation. + +2005-01-29 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2005-01-28 Kjartan Maraas + + * nb.po: Update + * no.po: Update + +2005-01-26 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2005-01-26 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2005-01-26 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2005-01-25 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2005-01-23 Funda Wang + + * zh_CN.po: Updated Simplified Chinese translation. + +2005-01-21 Kjartan Maraas + + * nb.po: Update this too while we're at it. + +2005-01-21 Kjartan Maraas + + * nn.po: Update + +2005-01-15 Frank Arnold + + * de.po: Updated German translation. + +2005-01-01 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2004-12-28 Christian Rose + + * sv.po: Updated Swedish translation. + +2004-12-25 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2004-12-21 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2004-12-20 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2004-12-16 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Vladimir Petkov + +2004-12-07 Martin Willemoes Hansen + + * da.po: Updated Danish translation. + +2004-11-23 Martin Willemoes Hansen + + * da.po: Updated Danish translation. + +2004-11-14 Christophe Merlet + + * fr.po: Updated French translation from + Baptiste Mille-Mathias . + +2004-11-13 Žygimantas Beručka + + * lt.po: Updated Lithuanian translation. + +2004-11-04 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2004-10-30 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2004-10-19 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2004-10-15 Danilo Šegan + + * sr.po, sr@Latn.po: Updated Serbian translation. + +2004-10-14 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2004-10-14 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2004-10-13 David Lodge + + * en_GB.po: Updated British English translation. + +2004-09-26 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2004-09-19 Alessio Frusciante + + * it.po: Updated Italian translation by + Luca Ferretti . + +2004-09-14 Gora Mohanty + + * or.po: Updated Oriya translation. + +2004-09-12 Paisa Seeluangsawat + + * th.po: Updated Thai translation. + +2004-09-12 Dafydd Harries + + * cy.po: Updated Welsh translation. + +2004-09-11 Abel Cheung + + * zh_TW.po: Updated traditional Chinese translation by GNOME HK Team. + +2004-09-10 Christophe Merlet + + * fr.po: Updated French translation. + +2004-09-08 Abel Cheung + + * zh_TW.po: Updated traditional Chinese translation by GNOME HK Team. + +2004-09-08 Raphael Higino + + * pt_BR.po: Updated Brazilian Portuguese translation. + +2004-09-08 Arafat Medini + + * ar.po: Updated Arabic translation + +2004-09-07 Mugurel Tudor + + * ro.po: Updated Romanian translation. + +2004-09-05 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2004-09-03 Baris Cicek + + * tr.po: Updated Turkish Translation + +2004-08-31 Åsmund Skjæveland + + * nn.po: Updated Norwegian Nynorsk translation. + +2004-08-29 Kostas Papadimas + + * el.po: Updated Greek translation. + +2004-08-28 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2004-08-26 Iñaki Larrañaga + + * eu.po: Updated Basque translation. + +2004-08-23 Maxim Dziumanenko + + * uk.po: Updated Ukrainian translation. + +2004-08-21 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2004-08-20 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2004-08-18 Pauli Virtanen + + * fi.po: Updated Finnish translation. + +2004-08-18 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2004-08-17 Christian Rose + + * bs.po: Added Bosnian translation by + Kemal Sanjta . + +2004-08-17 Metin Amiroff + + * az.po: Translation updated. + +2004-08-16 Kjartan Maraas + + * nb.po: Added this here. + +2004-08-15 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2004-08-13 Tommi Vainikainen + + * fi.po: Unified some fields in po headers for Finnish team. + +2004-08-13 Gurban M. Tewekgeli + + * tk.po: Added Turkmen translation. + +2004-08-11 Dmitry G. Mastrukov + + * ru.po: Updated Russian translation + from Russian team . + +2004-08-10 Artur Flinta + + * pl.po: Updated Polish translation by GNOME PL Team. + +2004-08-07 Danilo Šegan + + * sr.po, sr@Latn.po: Updated Serbian translation. + +2004-08-06 Funda Wang + + * zh_CN.po: Updated Simplified Chinese translation. + +2004-08-06 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2004-08-03 Vincent van Adrighem + + * nl.po: Translation updated by Michiel Sikkes. + +2004-08-02 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2004-08-02 Adam Weinberger + + * en_CA.po: Updated Canadian English translation. + +2004-08-01 Kjartan Maraas + + * no.po: Updated Norwegian translation. + +2004-07-30 Martin Willemoes Hansen + + * da.po: Reviewed and updated fuzzy messages. + +2004-07-30 Kartik Mistry + + * gu.po: Updated and added Gujarati translation. + +2004-07-29 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2004-07-28 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2004-07-27 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Rostislav "zbrox" Raykov + +2004-07-27 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2004-07-25 Christian Rose + + * sv.po: Updated Swedish translation. + +2004-07-25 Christian Neumair + + * de.po: Updated German translation. + +2004-07-25 David Lodge + + * en_GB.po: Added British translation. + +2004-07-24 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2004-07-23 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2004-07-23 Žygimantas Beručka + + * lt.po: Updated Lithuanian translation. + +2004-07-22 Gustavo Maciel Dias Vieira + + * pt_BR.po: Updated Brazilian Portuguese translation done by + Goedson Teixeira Paixao . + +2004-07-21 Guntupalli Karunakar + + * hi.po: Updated Hindi translation. + +2004-07-14 Christian Rose + + * sv.po: Updated Swedish translation. + +2004-07-12 Åsmund Skjæveland + + * nn.po: Updated Norwegian Nynorsk translation. + +2004-07-08 Alexander Shopov + + * bg.po: Updated Bulgarian translation by + Vladimir "Kaladan" Petkov + +2004-07-07 Laszlo Dvornik + + * hu.po: Updated Hungarian translation. + +2004-07-06 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2004-07-05 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2004-07-04 Vincent van Adrighem + + * nl.po: Translation updated by Tino Meinen. + +2004-07-02 Christian Neumair + + * de.po: Updated German translation. + +2004-06-29 Laurent Dhima + + * sq.po: Translation updated. + +2004-06-28 Laurent Dhima + + * sq.po: Translation updated. + +2004-06-25 Gareth Owen + + * en_GB.po: Updated British English translation + +2004-06-26 Funda Wang + + * zh_CN.po: Updated Simplified Chinese translation. + +2004-06-25 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2004-05-31 Alexander Shopov + * bg.po: Updated Bulgarian translation by + Vladimir Petkov + +2004-04-23 Dafydd Harries + + * ca.po: Updated Catalan translation from Jordi Mallach. + +2004-04-16 Iñaki Larrañaga + + * eu.po: Added Basque translation. + +2004-04-15 Andras Timar + + * hu.po: Updated Hungarian translation. + +2004-04-09 Guntupalli Karunakar + + * gu.po: Added Gujurati translation by + Gujarati Team . + +2004-04-06 Mohammad DAMT + + * id.po: Updated Indonesian translation + +2004-04-03 Mugurel Tudor + + * ro.po: Updated Romanian translation + +2004-03-29 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2004-03-27 Tõivo Leedjärv + + * et.po: Added Estonian translation. + +2004-03-24 Guntupalli Karunakar + + * pa.po: Added Punjabi translation by + Jaswinder Singh Phulewala . + +2004-03-20 Mugurel Tudor + + * ro.po: Updated Romanian translation. + +2004-03-20 Gareth Owen + + * en_GB.po: Updated British translation + +2004-03-19 Andras Timar + + * hu.po: Updated Hungarian translation. + +2004-03-18 Arafat Medini + + * ar.po: Updated Arabic translation. + +2004-03-17 Leonid Kanter + + * ru.po: Updated Russian translation + +2004-03-16 Dafydd Harries + + * cy.po: Updated Welsh translation. + +2004-03-15 Alessio Frusciante + + * it.po: Updated Italian translation by + Luca Ferretti . + +2004-03-15 Nikos Charonitakis + + * el.po: Updated Greek translation. + +2004-03-14 Christophe Merlet + + * fr.po: Updated French translation. + +2004-03-13 Christophe Merlet + + * fr.po: Updated French translation. + +2004-03-13 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2004-03-12 Funda Wang + + * zh_CN.po: Updated Simplified Chinese translation. + +2004-03-12 Yuriy Syrota + + * uk.po: Updated Ukrainian translation. + +2004-03-11 Alessio Frusciante + + * it.po: Updated Italian translation. + +2004-03-11 Christophe Merlet + + * fr.po: Updated French translation. + +2004-03-10 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2004-03-09 Alessio Frusciante + + * it.po: Updated Italian translation by + Luca Ferretti . + +2004-03-09 Kjartan Maraas + + * no.po: Updated Norwegian translation. + +2004-03-09 Francisco Javier F. Serrador + + * es.po: Updated Spansih translation. + +2004-03-08 Alastair McKinstry + + * ga.po: Updated Irish translation. + +2004-03-08 Theppitak Karoonboonyanan + + * th.po: Updated Thai translation. + +2004-03-06 Mətin Əmirov + + * az.po: Translation updated. + +2004-03-07 Funda Wang + + * zh_CN.po: Updated Simplified Chinese translation. + +2004-03-04 Paisa Seeluangsawat + + * th.po: Added Thai translation. + +2004-03-3 Arafat Medini + + * ar.po: Updated Arabic translation. + +2004-03-02 Stanislav Visnovsky + + * sk.po: Convert to UTF-8. + +2004-02-26 Guntupalli Karunakar + + * hi.po: Updated Hindi translations. + +2004-02-23 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2004-02-22 Christian Rose + + * en_CA.po: Added Canadian English translation by + Adam Weinberger . + +2004-02-17 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2004-02-11 Kjartan Maraas + + * no.po: Updated Norwegian translation. + +2004-02-07 Robert Sedak + + * hr.po: Updated Croatian translation. + +2004-02-08 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2004-02-05 Pauli Virtanen + + * fi.po: Updated Finnish translation. + +2004-02-03 Kostas Papadimas + + * el.po: Updated Greek translation. + +2004-02-02 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2004-02-01 Ole Laursen + + * da.po: Updated Danish translation. + +2004-01-31 Mətin Əmirov + + * az.po: Translation updated. + +2004-01-28 Miloslav Trmac + + * cs.po: Fixed Czech translation. + +2004-01-20 Artur Flinta + + * pl.po: Updated Polish translation by GNOME PL Team. + +2004-01-18 Christian Neumair + + * de.po: Updated German translation. + +2004-01-16 Hasbullah Bin Pit + + * ms.po: Updated Malay translation. + +2004-01-15 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2004-01-13 Kjartan Maraas + + * no.po: Updated Norwegian translation. + +2004-01-13 Artur Flinta + + * pl.po: Updated Polish translation by GNOME PL Team. + +2004-01-12 Žygimantas Beručka + + * lt.po: Updated Lithuanian translation by Tomas Kuliavas. + +2004-01-11 Christophe Merlet + + * fr.po: Updated French translation. + +2004-01-11 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2004-01-05 Vincent van Adrighem + + * nl.po: Translation updated by Tino Meinen. + +2004-01-04 Duarte Loreto + + * pt.po: Updated and revised Portuguese translation. + +2004-01-03 Sanlig Badral + + * mn.po: Updated Mongolian translation. + +2004-01-03 Robert Sedak + + * hr.po: Updated Croatian translation. + +2004-01-02 Sanlig Badral + + * mn.po: Updated Mongolian translation. + +2004-01-02 Taneem Ahmed + + * bn.po: Updated Bangla (Bengali) translation. + +2003-12-29 Christian Neumair + + * de.po: Updated German translation. + +2003-12-29 Åsmund Skjæveland + + * nn.po: Updated Norwegian Nynorsk translation. + +2003-12-24 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2003-12-23 Gustavo Noronha Silva + + * pt_BR.po: updated translation. + +2003-12-22 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2003-12-22 Danilo Šegan + + * sr.po, sr@Latn.po: Updated Serbian translation. + +2003-12-22 Christian Rose + + * sv.po: Updated Swedish translation. + +2003-12-21 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation. + +2003-12-21 Danilo Šegan + + * sr.po, sr@Latn.po: Updated Serbian translation. + +2003-12-20 Arafat Medini + + * ar.po: Added Arabic translation. + +2003-12-19 Gustavo Noronha Silva + + * pt_BR.po: updated translation. + +2003-12-18 Yukihiro Nakai + + * ja.po: Minor update. + +2003-12-14 Francisco Javier F. Serrador + + * es.po: Updated Spanish translation + +2003-12-04 Danilo Šegan + + * sr.po, sr@Latn.po: Cleared up Serbian translation. + +2003-12-03 Sanlig Badral + + * mn.po: Updated Mongolian translation. + +2003-12-02 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2003-11-29 Ole Laursen + + * da.po: Updated Danish translation. + +2003-11-26 Vincent van Adrighem + + * nl.po: Dutch translation updated by Vincent van Adrighem. + +2003-11-10 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation by + Francisco Javier F. Serrador . + +2003-11-08 Danilo Šegan + + * sr.po, sr@Latn.po: Updated Serbian translation. + +2003-10-30 Kostas Papadimas + + * el.po: Updated Greek translation. + +2003-10-20 Andras Timar + + * hu.po: Updated Hungarian translation. + +2003-10-15 Danilo Šegan + + * sr.po, sr@Latn.po: Updated Serbian translation. + +2003-10-15 Yukihiro Nakai + + * ja.pp: Update Japanese translation. + +2003-10-13 Danilo Šegan + + * sr.po, sr@Latn.po: Updated Serbian translation. + +2003-10-08 Andras Timar + + * hu.po: Updated Hungarian translation. + +2003-10-06 Žygimantas Beručka + + * lt.po: Added Lithuanian translation by Tomas Kuliavas + . + +2003-10-06 Mugurel Tudor + + * ro.po: Updated Romanian translation + +2003-09-30 Kjartan Maraas + + * no.po: Update Norwegian translation. + +2003-09-30 Christian Neumair + + * de.po: Updated German translation. + +2003-09-27 Metin Amiroff + + * az.po: Updated Azerbaijani translation. + +2003-09-27 Åsmund Skjæveland + + * nn.po: Updated Norwegian (nynorsk) translation. + +2003-09-24 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2003-09-22 Taneem Ahmed + + * bn.po: Added Bangla translation by Dr Anirban Mitra + of Ankur group . + +2003-09-23 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2003-09-21 Metin Amiroff + + * az.po: Updated Azerbaijani file + +2003-09-21 Åsmund Skjæveland + + * nn.po: Updated Norwegian (Nynorsk) translation. + +2003-09-21 Åsmund Skjaeveland + + * nn.po: Updated Norwegian (nynorsk) translation. + +2003-09-20 Åsmund Skjæveland + + * nn.po: Started Norwegian (nynorsk) translation. + +2003-09-17 Fatih Demir + + * ta.po: Committed new Tamil translation by Dinesh. + +2003-09-09 Guntupalli Karunakar + + * hi.po: Updated Hindi translation by + Ravishankar Shrivastava . + +2003-09-08 Pablo Saratxaga + + * vi.po: Updated Vietnamese file + * az.po,sq.po: Fixed syntax errors + +2003-09-07 Nikos Charonitakis + + * el.po: Review of Greek translation. + +2003-09-06 Takeshi AIHANA + + * ja.po: Fixed mistranslations for Japanese. + +2003-09-05 Kjartan Maraas + + * no.po: Updated Norwegian translation. + +2003-09-04 Laurent Dhima + + * sq.po: Updated Albanian translation. + +2003-09-03 Guntupalli Karunakar + + * hi.po: Updated Hindi translations. + +2003-09-03 Mugurel Tudor + + * ro.po: Updated Romanian translation + +2003-09-01 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2003-08-29 Dafydd Harries + + * cy.po: Updated Welsh translation. + +2003-08-27 Pablo Gonzalo del Campo + + * es.po: Revision of Spanish translation by + Francisco Javier F. Serrador . + +2003-08-26 Guntupalli Karunakar + + * hi.po: Added Hindi translation. + +2003-08-25 Duarte Loreto + + * pt.po: Fixed missing accel in Portuguese translation. + +2003-08-26 Changwoo Ryu + + * ko.po: Updated Korean translation by + Young-Ho Cha . + +2003-08-24 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2003-08-22 Stanislav Visnovsky + + * sk.po: Update Slovak translation. + +2003-08-20 Kjartan Maraas + + * no.po: Update Norwegian translation. + +2003-08-19 Dafydd Harries + + * cy.po: Updated Welsh translation. + +2003-08-18 Danilo Å egan + + * be.po: Updated Belarusian translation by Ales Nyakhaychyk + . + +2003-08-18 Metin Amiroff + + * az.po: Updated Azerbaijani translation. + +2003-08-16 Pauli Virtanen + + * fi.po: Updated Finnish translation. + +2003-08-13 Laurent Dhima + + * sq.po: Added Albanian file. + +2003-08-12 Dafydd Harries + + * cy.po: Updated Welsh translation. + +2003-08-09 Wang Jian + + * zh_CN.po: Updated Simplified Chinese translation by + Funda Wang . + +2003-08-09 Christophe Merlet + + * fr.po: Updated French translation. + +2003-08-08 Danilo Å egan + + * sr.po, sr@Latn.po: Updated Serbian translation. + +2003-08-07 Hasbullah Bin Pit + + * ms.po: Updated Malay translation. + +2003-08-06 Metin Amiroff + + * az.po: Updated Azerbaijani translation. + +2003-08-05 Ole Laursen + + * da.po: Updated Danish translation. + +2003-08-05 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2003-07-29 Andras Timar + + * hu.po: Updated Hungarian translation. + +2003-07-25 Dafydd Harries + + * cy.po: Updated Welsh translation. + +2003-07-24 Pablo Saratxaga + + * vi.po: Updated Vietnamese file + * is.po: fixed syntax error + +2003-07-20 Evandro Fernandes Giovanini + + * pt_BR.po: Updated Brazilian Portuguese translation. + +2003-07-20 Takeshi AIHANA + + * ja.po: Updated Japanese translation. + +2003-07-18 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2002-07-17 Kostas Papadimas + + * el.po: Updated Greek translation. + +2003-07-17 Vincent van Adrighem + + * nl.po: Dutch translation updated by Tino Meinen. + +2003-07-12 Christian Neumair + + * de.po: Updated German translation. + +2003-07-12 Pablo Saratxaga + + * wa.po: Added Walloon file + +2003-07-12 Alessio Frusciante + + * it.po: Updated Italian translation. + +2003-07-07 Vincent van Adrighem + + * nl.po: Dutch translation updated by Kees van den Broek. + +2003-07-07 Abel Cheung + + * zh_TW.po: Updated traditional Chinese translation. + +2003-07-06 Evandro Fernandes Giovanini + + * pt_BR.po: Updated Brazilian Portuguese translation. + +2003-07-02 Artur Flinta + + * pl.po: Updated Polish translation. + +2003-06-28 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2003-06-28 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2003-06-28 Christian Rose + + * sv.po: Updated Swedish translation. + +2003-06-27 Mohammad DAMT + + * id.po: Updated Indonesian translation + +2003-06-26 Ole Laursen + + * da.po: Updated Danish translation. + +2003-06-26 Mohammad DAMT + + * id.po: Added Indonesian translation + +2003-06-23 Vincent van Adrighem + + * nl.po: Dutch translation updated by Kees van den Broek. + +2003-06-22 Samúel Jón Gunnarsson + + * is.po: Added Icelandic translation + +2003-06-21 Christophe Merlet + + * fr.po: Updated French translation. + +2003-06-17 Pauli Virtanen + + * fi.po: Updated Finnish translation. + +2003-06-12 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2003-06-08 Christophe Merlet + + * fr.po: Updated French translation. + +2003-06-07 Christian Neumair + + * de.po: Updated German translation. + +2003-06-06 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2003-06-04 Dmitry G. Mastrukov + + * be.po: Updated Belarusian translation + from Belarusian team . + +2003-06-04 Dmitry G. Mastrukov + + * ru.po: Updated Russian translation + from Russian team . + + +2003-05-31 Dafydd Harries + + * cy.po: Updated Welsh translation. + +2003-05-30 Paul Duffy + + * ga.po: Updated Irish Translation. + +2003-05-30 Abel Cheung + + * zh_TW.po: Updated traditional Chinese translation. + +2003-05-26 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2003-05-21 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2003-05-20 Christian Rose + + * sv.po: Updated Swedish translation. + +2003-05-19 Telsa Gwymme + + * cy.po: Updated Welsh translation from + Dafydd Harries + +2003-05-19 Christophe Merlet + + * fr.po: Updated French translation. + +2003-05-16 Telsa Gwynne + + * cy.po: Added Welsh translation from + Dafydd Harries + +2003-05-16 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2003-05-12 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2003-05-10 KAMAGASAKO Masatoshi + + * ja.po: Updated Japanese translation. + +2003-05-10 Jordi Mallach + + * ca.po: Updated Catalan translation. + +2003-05-09 Evandro Fernandes Giovanini + + * pt_BR.po: Updated Brazilian Portuguese translation. + +2003-05-08 Christian Rose + + * sv.po: Updated Swedish translation. + +2003-05-08 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2003-05-06 Danilo Å egan + + * sr.po, sr@Latn.po: Added Serbian translation by + http://Prevod.org/. + +2003-04-29 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2003-04-15 Dmitry G. Mastrukov + + * ru.po: updated Russian translation + from Russian team . + +2003-04-03 Christophe Merlet + + * fr.po: Updated French translation. + +2003-03-27 Christophe Merlet + + * fr.po: Updated French translation. + +2003-03-13 Christian Rose + + * ml.po: Added Malayalam translation by + FSF-India . + +2003-03-11 Paul Duffy + + * ga.po: Added Irish translation + +2003-03-10 Roozbeh Pournader + + * fa.po: Added Persian translation. + +2003-02-26 Dmitry G. Mastrukov + + * be.po: Added Belarusian translation + from Belarusian team . + +2003-02-25 Pablo Gonzalo del Campo + + * es.po: Fixed a translation string to match with libwnck. + +2003-02-22 Rob Adams + + * *.po: change toggle_maximized to toggle_maximize and + toggle_shaded to toggle_shade in action_double_click_titlebar long + description to match the values used by metacity + +2003-02-12 Christian Rose + + * sv.po: Some fixes for problems catched in translation review. + +2003-02-11 Fatih Demir + + * tr.po: Branchy. + +2003-02-09 Fatih Demir + + * tr.po: Take over from branch... + +2003-02-08 Fatih Demir + + * tr.po: Committed updated Turkish translation by Sinan. + +2003-02-05 Abel Cheung + + * en_GB.po: Fix header. + * ko.po, pt_BR.po: Fix positional parameters. + +2003-02-05 Abel Cheung + + * zh_TW.po: Updated traditional Chinese translation. + +2003-02-03 Daniel Yacob + + * am.po: Updated Amharic translation. + +2003-01-30 Marius Andreiana + + * ro.po: updated ( thanks to Mugurel Tudor ) + +2003-01-25 Christophe Merlet + + * fr.po: Updated French translation from + Guy Clotilde . + +2003-01-25 Kjartan Maraas + + * no.po: Updated Norwegian (bokmal) translation. + +2003-01-23 He Qiangqiang + + * zh_CN.po: Updated Simplified Chinese translation by + Xiong Jiang . + +2003-01-23 Dmitry G. Mastrukov + + * ru.po: updated Russian translation + from Russian team . + +2003-01-23 Abel Cheung + + * zh_TW.po: Updated traditional Chinese translation. + +2003-01-22 Christian Rose + + * mn.po: Added Mongolian translation by + Ochirbat Batzaya . + +2003-01-21 Dmitry G. Mastrukov + + * ru.po: updated Russian translation + from Russian team . + +2003-01-21 Kjartan Maraas + + * no.po: Updated Norwegian (bokmal) translation. + +2003-01-20 Christian Neumair + + * de.po: Updated German translation. + +2003-01-20 Dmitry G. Mastrukov + + * ru.po: updated Russian translation + from Russian team . + +2003-01-20 Dmitry G. Mastrukov + + * ru.po: updated Russian translation + from Russian team . + +2003-01-20 Dmitry G. Mastrukov + + * ru.po: updated Russian translation + from Russian team . + +2003-01-19 Abel Cheung + + * zh_TW.po: Updated traditional Chinese translation, and replaced + copyright symbol with correct one. + +2003-01-17 Gustavo Noronha Silva + + * pt_BR.po: translation update + +2003-01-16 Vincent van Adrighem + + * nl.po: Dutch translation updated by Tino Meinen. + +2003-01-16 Vincent van Adrighem + + * nl.po: Dutch translation updated by Tino Meinen. + +2003-01-14 Yanko Kaneti + + * bg.po: Full Bulgarian translation by + Alexander Shopov . + +2003-01-11 Kjartan Maraas + + * no.po: Updated Norwegian (bokmal) translation. + +2003-01-10 Vincent van Adrighem + + * nl.po: Dutch translation updated by Tino Meinen. + +2003-01-10 Andras Timar + + * hu.po: Updated Hungarian translation. + +2003-01-10 Yukihiro Nakai + + * ja.po: Minor fix. + +2003-01-09 Vincent van Adrighem + + * nl.po: Dutch translation updated by Tino Meinen. + +2003-01-08 Pauli Virtanen + + * fi.po: Fixed a string that had an invalid printf format. + +2003-01-09 Abel Cheung + + * zh_TW.po: Updated traditional Chinese translation. + +2003-01-07 Daniel Yacob + + * am.po: Updated Amharic translation. + +2003-01-06 Vincent van Adrighem + + * nl.po: Dutch translation added by Tino Meinen. + +2003-01-05 Pablo Saratxaga + + * vi.po: Updated Vietnamese file + * pt_BR.po: fixed syntax errors + +2003-01-05 Pauli Virtanen + + * fi.po: Added Finnish translation. + +2003-01-05 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2003-01-03 Kjartan Maraas + + * no.po: Updated Norwegian (bokmal) translation. + +2003-01-02 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-12-29 Daniel Yacob + + * am.po: Updated Amharic translation. + +2002-12-29 Kostas Papadimas + + * el.po: Updated Greek translation. + +2002-12-25 Ole Laursen + + * da.po: Updated Danish translation. + +2002-12-25 Kostas Papadimas + + * el.po: Updated Greek translation. + +2002-12-22 Daniel Yacob + + * am.po: Updated Amharic translation. + +2002-12-22 Artis Trops + + * lv.po: Updated Latvian translation. + +2002-12-21 Daniel Yacob + + * am.po: Updated Amharic translation. + +2002-12-20 Christian Neumair + + * de.po: Updated German translation. + +2002-12-20 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2002-12-19 Hasbullah Bin Pit + + * ms.po: Updated Malay Translation. + +2002-12-19 Yanko Kaneti + + * bg.po (added): Added start of Bulgarian translation by + Alexander Shopov . + +2002-12-18 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-12-17 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2002-12-17 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-12-17 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-12-16 Christian Neumair + + * de.po: Updated German translation. + +2002-12-16 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2002-12-16 Ole Laursen + + * da.po: Updated Danish translation. + +2002-12-14 Kjartan Maraas + + * no.po: Updated Norwegian (bokmÃ¥l) translation. + +2002-12-13 Daniel Yacob + + * am.po: Added Amharic translation. + +2002-12-13 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-12-12 Ole Laursen + + * da.po: Updated Danish translation. + +2002-12-11 Christian Neumair + + * POTFILES.in: Added src/tools/metacity-message.c. + * de.po: Updated German translation. + +2002-12-11 Evandro Fernandes Giovanini + + * pt_BR.po: Updated Brazilian Portuguese translation. + +2002-12-09 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-12-09 Miloslav Trmac + + * cs.po: Updated Czech translation. + +2002-12-04 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-11-25 Kjartan Maraas + + * no.po: Updated Norwegian (bokmÃ¥l) translation. + +2002-11-25 Yanko Kaneti + + * *.po: Convert all to UTF-8. + +2002-11-24 Kostas Papadimas + + * el.po: Updated Greek translation. + +2002-11-23 Kostas Papadimas + + * el.po: Updated Greek translation. + +2002-11-19 Andras Timar + + * hu.po: Updated Hungarian translation. + +2002-11-15 Kjartan Maraas + + * no.po: Updated Norwegian (bokmÃ¥l) translation. + +2002-11-14 Gustavo Noronha Silva + + * pt_BR.po: Update translation. + +2002-11-14 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-11-13 Christian Neumair + + * de.po: Updated German translation. + +2002-11-11 Peteris Krisjanis + + * lv.po: Updated Latvian translation. + +2002-11-11 Changwoo Ryu + + * ko.po: Updated Korean translation by Young-Ho Cha + . + +2002-11-10 Ole Laursen + + * da.po: Updated Danish translation. + +2002-11-05 Hasbullah Bin Pit + + * ms.po: Updated Malay Translation. + +2002-11-05 Christian Rose + + * POTFILES.in: Added missing file. + * sv.po: Updated Swedish translation. + +2002-11-01 Christian Neumair + + * de.po: Updated German translation. + +2002-10-31 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-10-28 Ole Laursen + + * da.po: Updated Danish translation. + +2002-10-28 Peteris Krisjanis + + * lv.po: Updated Latvian translation. + +2002-10-24 Christian Rose + + * POTFILES.in: Added missing file. + * sv.po: Updated Swedish translation. + +2002-10-24 Pablo Saratxaga + + * vi.po: Updated Vietnamese file + +2002-10-22 Ole Laursen + + * da.po: Updated Danish translation. + +2002-10-21 Kjartan Maraas + + * no.po: Updated Norwegian (bokmÃ¥l) translation. + +2002-10-17 Andras Timar + + * hu.po: Added Hungarian translation. + +2002-10-17 Christophe Merlet + + * fr.po: Updated French translation. + +2002-10-16 Christian Neumair + + * de.po: Updated German translation. + +2002-10-16 Yukihiro Nakai + + * ja.po: Minor fix + +2002-10-16 Bastien Nocera + + * en_GB.po: added, more colours for your theme, time to upgrade! + +2002-10-15 Kjartan Maraas + + * no.po: Updated Norwegian (bokmÃ¥l) translation. + +2002-10-15 Ole Laursen + + * da.po: Updated Danish translation. + +2002-10-13 Hasbullah Bin Pit + + * ms.po: Updated Malay Translation. + +2002-10-11 Stanislav Brabec + + * cs.po: Updated Czech translation from Miloslav Trmac + . + +2002-10-10 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-10-06 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-10-01 Stanislav Brabec + + * cs.po: Added Czech translation from Miloslav Trmac + . + +2002-09-28 Ole Laursen + + * da.po: Updated Danish translation. + +2002-09-26 Christian Neumair + + * de.po: Updated German translation. + +2002-09-25 Christophe Merlet + + * fr.po: Updated French translation. + +2002-09-25 Christian Meyer + + * de.po: Updated German translation. + +2002-09-24 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-09-23 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-09-20 Christian Neumair + + * de.po: Updated German translation. + +2002-09-20 Pablo Saratxaga + + * vi.po: Updated Vietnamese file + +2002-09-11 Kjartan Maraas + + * no.po: Updated Norwegian (bokmÃ¥l) translation. + +2002-09-10 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-09-11 Duncan Mak + + * ro.po: Remove diff conflicts. + +2002-09-06 Frederic Crozat + + * fr.po: Updated French translation. + +2002-09-05 Ole Laursen + + * da.po: Updated Danish translation. + +2002-09-05 Christian Neumair + + * de.po: Updated German translation. + +2002-09-05 Akira TAGOH + + * ja.po: Updated Japanese translation. + +2002-09-04 Marius Andreiana + + * ro.po: added ( thanks to Mugurel Tudor ) + +2002-08-30 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-08-28 Hasbullah Bin Pit + + * ms.po: Updated Malay Translation. + +2002-08-27 Christian Neumair + + * de.po: Updated German translation. + +2002-08-26 Ole Laursen + + * da.po: Updated Danish translation. + +2002-08-26 Dmitry G. Mastrukov + + * ru.po: updated Russian translation. + +2002-08-26 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-08-24 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-08-23 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-08-23 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-08-22 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-08-21 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-08-21 Anders Carlsson + + * lv.po: Fix build. + +2002-08-21 Peteris Krisjanis + + * lv.po: Updated Latvian translation. + +2002-08-21 Akira TAGOH + + * ja.po: Updated Japanese translation. + +2002-08-19 Ole Laursen + + * da.po: Updated Danish translation. + +2002-08-19 Christian Rose + + * sv.po: Fixed a bug. Thanks to rhult for reporting it. + +2002-08-19 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-08-18 Hasbullah Bin Pit + + * ms.po: Updated Malay Translation. + +2002-08-18 Christian Neumair + + * de.po: Updated German translation. + +2002-08-18 Christian Neumair + + * de.po: Updated German translation. + +2002-08-17 Simos Xenitellis + + * el.po: Added initial Greek translation. + +2002-08-17 Evandro Fernandes Giovanini + + * pt_BR.po: Added Brazilian Portuguese translation. + +2002-08-17 Changwoo Ryu + + * ko.po: Updated Korean translation by Young-Ho Cha + . + +2002-08-16 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-08-16 Dmitry G. Mastrukov + + * ru.po: updated Russian translation. + +2002-08-13 Ole Laursen + + * da.po: Updated Danish translation. + +2002-08-12 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-08-12 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2002-08-11 Dmitry G. Mastrukov + + * ru.po: updated Russian translation. + +2002-08-10 He Qiangqiang + + * zh_CN.po: Fixed c-format specifiers position error. + +2002-08-08 Akira TAGOH + + * ja.po: Updated Japanese translation. + +2002-08-07 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-08-06 Manuel Borchers + + * de.po: Update German translation by + Christian Neumair + +2002-08-05 He Qiangqiang + + * zh_CN.po: Added simplified Chinese translation from + Sun G11n . + +2002-08-05 Christian Rose + + * sv.po: Fixed Swedish translation. + +2002-08-04 Kjartan Maraas + + * no.po: Updated Norwegian (bokmÃ¥l) translation. + +2002-07-30 Pablo Saratxaga + + * vi.po: Updated Vietnamese file + +2002-07-28 Christophe Merlet + + * fr.po: Updated French translation from contribution of + Sun G11n . + +2002-07-27 Hasbullah Bin Pit + + * ms.po: Updated Malay Translation. + +2002-07-25 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-07-25 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-07-25 Dmitry G. Mastrukov + + * ru.po: updated Russian translation with help from + SUN G11n . + +2002-07-25 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-07-25 Christian Rose + + * sv.po: Updated Swedish translation and merged the + Sun changes that are sane. + +2002-07-24 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2002-07-23 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-07-24 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-07-19 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-07-16 Kjartan Maraas + + * no.po: Updated Norwegian (bokmÃ¥l) translation. + +2002-07-15 Ole Laursen + + * da.po: Fixed a string. + +2002-07-13 Christophe Fergeau + + * fr.po: Added French translation. + +2002-07-13 Ole Laursen + + * da.po: Updated Danish translation. + +2002-07-12 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-07-11 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-07-11 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-07-08 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-07-02 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2002-06-24 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-06-24 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-06-25 Abel Cheung + + * zh_TW.po: Updated traditional Chinese translation. + +2002-06-23 Kjartan Maraas + + * no.po: Updated Norwegian (bokmÃ¥l) translation. + +2002-06-23 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-06-19 Ole Laursen + + * da.po: Updated Danish translation. + +2002-06-16 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-06-16 Christian Rose + + * POTFILES.in: Added missing file. + * sv.po: Updated Swedish translation. + +2002-06-15 Akira TAGOH + + * ja.po: Updated Japanese translation. + +2002-06-14 Changwoo Ryu + + * ko.po: Updated Korean translation. + +2002-06-10 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-06-10 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2002-06-09 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-06-09 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-06-07 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-06-06 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-06-06 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-06-05 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-06-05 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-06-04 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-06-04 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2002-06-04 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-06-03 Kjartan Maraas + + * no.po: Updated Norwegian (bokmÃ¥l) translation. + +2002-06-03 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2002-06-03 Changwoo Ryu + + * ko.po: Updated Korean translation by Young-Ho Cha + . + +2002-06-01 Ole Laursen + + * da.po: Updated Danish translation. + +2002-05-31 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-05-31 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2002-05-31 Kjartan Maraas + + * no.po: Updated Norwegian (bokmÃ¥l) translation. + +2002-05-28 Pablo Gonzalo del Campo + + * es.po: Updated Spanish translation. + +2002-05-28 Ole Laursen + + * da.po: Updated Danish translation. + +2002-05-28 Abel Cheung + + * zh_TW.po: New traditional Chinese translation. + +2002-05-27 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-05-26 Matthias Warkus + + * de.po: German translation added. + +2002-05-26 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-05-24 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2002-05-21 Changwoo Ryu + + * ko.po: Updated Korean translation by Young-Ho Cha + . + +2002-05-20 Alessio Frusciante + + * it.po: Added Italian translation. + +2002-05-20 Pablo Saratxaga + + * ca.po: Added Catalan file + * az.po,es.po,ms.po,lv.po: Corrected syntax errors + +2002-05-18 Kjartan Maraas + + * no.po: Updated Norwegian (bokmÃ¥l) translation. + +2002-05-18 Ole Laursen + + * da.po: Updated Danish translation. + +2002-05-16 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2002-05-06 Duarte Loreto + + * pt.po: Updated Portuguese translation and converted to UTF-8. + +2002-04-26 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-04-25 Changwoo Ryu + + * ko.po: Updated Korean translation from Young-Ho Cha + . + +2002-04-22 Kjartan Maraas + + * no.po: Updated Norwegian (bokmÃ¥l) translation. + +2002-04-19 Changwoo Ryu + + * ko.po: Updated Korean translation from Young-Ho Cha + . + +2002-04-17 Changwoo Ryu + + * ko.po: Added Korean translation from Young-Ho Cha + . + +2002-04-16 Akira TAGOH + + * ja.po: Add Japanese translation. + +2002-04-16 Abel Cheung + + * .cvsignore: Added some file(s). + * POTFILES.in: Synced with source tree. + +2002-04-15 Zbigniew Chyla + + * pl.po: Updated Polish translation by + GNOME PL Team . + +2002-03-28 Kjartan Maraas + + * no.po: Updated Norwegian (bokmÃ¥l) translation. + +2002-03-27 Kjartan Maraas + + * no.po: Updated Norwegian (bokmÃ¥l) translation. + +2002-03-22 Zbigniew Chyla + + * pl.po: Added Polish translation. + +2002-02-22 Kjartan Maraas + + * no.po: Updated Norwegian (bokmÃ¥l) translation. + +2002-02-17 Kjartan Maraas + + * no.po: Updated Norwegian (bokmÃ¥l) translation. + +2002-02-16 Kjartan Maraas + + * no.po: Updated Norwegian (bokmÃ¥l) translation. + +2002-02-12 Kjartan Maraas + + * no.po: Updated Norwegian (bokmÃ¥l) translation. + +2002-02-11 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2002-02-10 Hasbullah Bin Pit + + * ms.po: Updated Malay Translation. + +2002-02-10 Kjartan Maraas + + * no.po: Updated Norwegian (bokmÃ¥l) translation. + +2002-02-08 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-02-08 Christian Rose + + * POTFILES.in: Added missing file. + +2002-02-08 Havoc Pennington + + * da.po: fix a missing newline that made build fail once po was + added to subdirs + +2002-02-02 Kjartan Maraas + + * no.po: Updated Norwegian (bokmÃ¥l) translation. + +2002-01-31 Christian Rose + + * sv.po: Updated Swedish translation. + +2002-01-30 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2002-01-30 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2002-01-29 Kjartan Maraas + + * no.po: Updated Norwegian (bokmÃ¥l) translation. + +2002-01-27 Peteris Krisjanis + + * lv.po: Added Latvian translation. + +2002-01-22 Hasbullah Bin Pit + + * ms.po: Added Malay Translation. + +2002-01-11 Kjartan Maraas + + * no.po: Updated Norwegian (bokmÃ¥l) translation. + +2002-01-09 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2002-01-08 Duarte Loreto + + * pt.po: Updated Portuguese translation. + +2002-01-06 Fatih Demir + + * tr.po: Added Turkish translation by Görkem Cetin. + +2002-01-05 Christian Rose + + * POTFILES.in: Added missing files. + * sv.po: Updated Swedish translation. + +2001-12-27 Duarte Loreto + + * pt.po: Added portuguese translation + +2001-12-27 Jesus Bravo Alvarez + + * gl.po: Updated Galician translation from + Manuel A. Fernandez Montecelo + +2001-12-26 Vasif Ismailogu MD + + * az.po: updating Azerbaijani translation file + +2001-12-16 Kjartan Maraas + + * no.po: Updated Norwegian (bokmᅵ) translation. + +2001-12-15 Christian Rose + + * sv.po: Updated Swedish translation. + +2001-12-13 Stanislav Visnovsky + + * sk.po: Updated Slovak translation. + +2001-12-11 Stanislav Visnovsky + + * sk.po: Added Slovak translation. + +2001-11-27 Jesus Bravo Alvarez + + * gl.po: Added Galician translation from + Manuel A. Fernᅵdez Montecelo + +2001-10-29 Yuriy Syrota + + * uk.po: Added Ukrainian translation file. + +2001-10-28 Hᅵtor Garcᅵ ᅵvarez + + * es.po: Updated Spanish translation. + +2001-10-14 Hᅵtor Garcᅵ ᅵvarez + + * es.po: Added Spanish translation. + +2001-10-14 Valek Filippov + + * ru.po: Added russian translation. + +2001-10-11 Christian Rose + + * sv.po: Fixed some typos. Thanks to Tomas ᅵren + for spotting many of them. + +2001-10-11 Christian Rose + + * sv.po: Added Swedish translation. + * POTFILES.in: Added files. + * .cvsignore: Added messages and *.pot. diff --git a/po/LINGUAS b/po/LINGUAS new file mode 100644 index 0000000..f11ca49 --- /dev/null +++ b/po/LINGUAS @@ -0,0 +1,98 @@ +# please keep this list sorted alphabetically +# +am +ar +as +ast +az +be +be@latin +bg +bn +bn_IN +br +bs +ca +ca@valencia +cs +cy +da +de +dz +el +en_CA +en_GB +eo +es +et +eu +fa +fi +fr +fur +ga +gd +gl +gu +ha +he +hi +hr +hu +hy +id +ig +is +it +ja +ka +kk +kn +ko +ku +la +lt +lv +mai +mg +mk +ml +mn +mr +ms +nb +nds +ne +nl +nn +oc +or +pa +pl +pt +pt_BR +ro +ru +rw +si +sk +sl +sq +sr +sr@latin +sv +ta +te +tg +th +tk +tr +ug +uk +vi +wa +xh +yo +zh_CN +zh_HK +zh_TW diff --git a/po/Makefile.in.in b/po/Makefile.in.in new file mode 100644 index 0000000..fa59cf1 --- /dev/null +++ b/po/Makefile.in.in @@ -0,0 +1,478 @@ +# Makefile for PO directory in any package using GNU gettext. +# Copyright (C) 1995-1997, 2000-2007, 2009-2010 by Ulrich Drepper +# +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. This file is offered as-is, +# without any warranty. +# +# Origin: gettext-0.19.6 +GETTEXT_MACRO_VERSION = 0.19 + +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ + +SED = @SED@ +SHELL = /bin/sh +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +datarootdir = @datarootdir@ +datadir = @datadir@ +localedir = @localedir@ +gettextsrcdir = $(datadir)/gettext/po + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ + +# We use $(mkdir_p). +# In automake <= 1.9.x, $(mkdir_p) is defined either as "mkdir -p --" or as +# "$(mkinstalldirs)" or as "$(install_sh) -d". For these automake versions, +# @install_sh@ does not start with $(SHELL), so we add it. +# In automake >= 1.10, @mkdir_p@ is derived from ${MKDIR_P}, which is defined +# either as "/path/to/mkdir -p" or ".../install-sh -c -d". For these automake +# versions, $(mkinstalldirs) and $(install_sh) are unused. +mkinstalldirs = $(SHELL) @install_sh@ -d +install_sh = $(SHELL) @install_sh@ +MKDIR_P = @MKDIR_P@ +mkdir_p = @mkdir_p@ + +GMSGFMT_ = @GMSGFMT@ +GMSGFMT_no = @GMSGFMT@ +GMSGFMT_yes = @GMSGFMT_015@ +GMSGFMT = $(GMSGFMT_$(USE_MSGCTXT)) +MSGFMT_ = @MSGFMT@ +MSGFMT_no = @MSGFMT@ +MSGFMT_yes = @MSGFMT_015@ +MSGFMT = $(MSGFMT_$(USE_MSGCTXT)) +XGETTEXT_ = @XGETTEXT@ +XGETTEXT_no = @XGETTEXT@ +XGETTEXT_yes = @XGETTEXT_015@ +XGETTEXT = $(XGETTEXT_$(USE_MSGCTXT)) +MSGMERGE = msgmerge +MSGMERGE_UPDATE = @MSGMERGE@ --update +MSGINIT = msginit +MSGCONV = msgconv +MSGFILTER = msgfilter + +POFILES = @POFILES@ +GMOFILES = @GMOFILES@ +UPDATEPOFILES = @UPDATEPOFILES@ +DUMMYPOFILES = @DUMMYPOFILES@ +DISTFILES.common = Makefile.in.in remove-potcdate.sin \ +$(DISTFILES.common.extra1) $(DISTFILES.common.extra2) $(DISTFILES.common.extra3) +DISTFILES = $(DISTFILES.common) Makevars POTFILES.in \ +$(POFILES) $(GMOFILES) \ +$(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3) + +POTFILES = \ + +CATALOGS = @CATALOGS@ + +POFILESDEPS_ = $(srcdir)/$(DOMAIN).pot +POFILESDEPS_yes = $(POFILESDEPS_) +POFILESDEPS_no = +POFILESDEPS = $(POFILESDEPS_$(PO_DEPENDS_ON_POT)) + +DISTFILESDEPS_ = update-po +DISTFILESDEPS_yes = $(DISTFILESDEPS_) +DISTFILESDEPS_no = +DISTFILESDEPS = $(DISTFILESDEPS_$(DIST_DEPENDS_ON_UPDATE_PO)) + +# Makevars gets inserted here. (Don't remove this line!) + +.SUFFIXES: +.SUFFIXES: .po .gmo .mo .sed .sin .nop .po-create .po-update + +.po.mo: + @echo "$(MSGFMT) -c -o $@ $<"; \ + $(MSGFMT) -c -o t-$@ $< && mv t-$@ $@ + +.po.gmo: + @lang=`echo $* | sed -e 's,.*/,,'`; \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o $${lang}.gmo $${lang}.po"; \ + cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o t-$${lang}.gmo $${lang}.po && mv t-$${lang}.gmo $${lang}.gmo + +.sin.sed: + sed -e '/^#/d' $< > t-$@ + mv t-$@ $@ + + +all: all-@USE_NLS@ + +all-yes: stamp-po +all-no: + +# Ensure that the gettext macros and this Makefile.in.in are in sync. +CHECK_MACRO_VERSION = \ + test "$(GETTEXT_MACRO_VERSION)" = "@GETTEXT_MACRO_VERSION@" \ + || { echo "*** error: gettext infrastructure mismatch: using a Makefile.in.in from gettext version $(GETTEXT_MACRO_VERSION) but the autoconf macros are from gettext version @GETTEXT_MACRO_VERSION@" 1>&2; \ + exit 1; \ + } + +# $(srcdir)/$(DOMAIN).pot is only created when needed. When xgettext finds no +# internationalized messages, no $(srcdir)/$(DOMAIN).pot is created (because +# we don't want to bother translators with empty POT files). We assume that +# LINGUAS is empty in this case, i.e. $(POFILES) and $(GMOFILES) are empty. +# In this case, stamp-po is a nop (i.e. a phony target). + +# stamp-po is a timestamp denoting the last time at which the CATALOGS have +# been loosely updated. Its purpose is that when a developer or translator +# checks out the package via CVS, and the $(DOMAIN).pot file is not in CVS, +# "make" will update the $(DOMAIN).pot and the $(CATALOGS), but subsequent +# invocations of "make" will do nothing. This timestamp would not be necessary +# if updating the $(CATALOGS) would always touch them; however, the rule for +# $(POFILES) has been designed to not touch files that don't need to be +# changed. +stamp-po: $(srcdir)/$(DOMAIN).pot + @$(CHECK_MACRO_VERSION) + test ! -f $(srcdir)/$(DOMAIN).pot || \ + test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES) + @test ! -f $(srcdir)/$(DOMAIN).pot || { \ + echo "touch stamp-po" && \ + echo timestamp > stamp-poT && \ + mv stamp-poT stamp-po; \ + } + +# Note: Target 'all' must not depend on target '$(DOMAIN).pot-update', +# otherwise packages like GCC can not be built if only parts of the source +# have been downloaded. + +# This target rebuilds $(DOMAIN).pot; it is an expensive operation. +# Note that $(DOMAIN).pot is not touched if it doesn't need to be changed. +# The determination of whether the package xyz is a GNU one is based on the +# heuristic whether some file in the top level directory mentions "GNU xyz". +# If GNU 'find' is available, we avoid grepping through monster files. +$(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed + package_gnu="$(PACKAGE_GNU)"; \ + test -n "$$package_gnu" || { \ + if { if (LC_ALL=C find --version) 2>/dev/null | grep GNU >/dev/null; then \ + LC_ALL=C find -L $(top_srcdir) -maxdepth 1 -type f \ + -size -10000000c -exec grep 'GNU @PACKAGE@' \ + /dev/null '{}' ';' 2>/dev/null; \ + else \ + LC_ALL=C grep 'GNU @PACKAGE@' $(top_srcdir)/* 2>/dev/null; \ + fi; \ + } | grep -v 'libtool:' >/dev/null; then \ + package_gnu=yes; \ + else \ + package_gnu=no; \ + fi; \ + }; \ + if test "$$package_gnu" = "yes"; then \ + package_prefix='GNU '; \ + else \ + package_prefix=''; \ + fi; \ + if test -n '$(MSGID_BUGS_ADDRESS)' || test '$(PACKAGE_BUGREPORT)' = '@'PACKAGE_BUGREPORT'@'; then \ + msgid_bugs_address='$(MSGID_BUGS_ADDRESS)'; \ + else \ + msgid_bugs_address='$(PACKAGE_BUGREPORT)'; \ + fi; \ + case `$(XGETTEXT) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].* | 0.16 | 0.16.[0-1]*) \ + $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ + --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \ + --files-from=$(srcdir)/POTFILES.in \ + --copyright-holder='$(COPYRIGHT_HOLDER)' \ + --msgid-bugs-address="$$msgid_bugs_address" \ + ;; \ + *) \ + $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ + --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \ + --files-from=$(srcdir)/POTFILES.in \ + --copyright-holder='$(COPYRIGHT_HOLDER)' \ + --package-name="$${package_prefix}@PACKAGE@" \ + --package-version='@VERSION@' \ + --msgid-bugs-address="$$msgid_bugs_address" \ + ;; \ + esac + test ! -f $(DOMAIN).po || { \ + if test -f $(srcdir)/$(DOMAIN).pot-header; then \ + sed -e '1,/^#$$/d' < $(DOMAIN).po > $(DOMAIN).1po && \ + cat $(srcdir)/$(DOMAIN).pot-header $(DOMAIN).1po > $(DOMAIN).po; \ + rm -f $(DOMAIN).1po; \ + fi; \ + if test -f $(srcdir)/$(DOMAIN).pot; then \ + sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \ + sed -f remove-potcdate.sed < $(DOMAIN).po > $(DOMAIN).2po && \ + if cmp $(DOMAIN).1po $(DOMAIN).2po >/dev/null 2>&1; then \ + rm -f $(DOMAIN).1po $(DOMAIN).2po $(DOMAIN).po; \ + else \ + rm -f $(DOMAIN).1po $(DOMAIN).2po $(srcdir)/$(DOMAIN).pot && \ + mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ + fi; \ + else \ + mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ + fi; \ + } + +# This rule has no dependencies: we don't need to update $(DOMAIN).pot at +# every "make" invocation, only create it when it is missing. +# Only "make $(DOMAIN).pot-update" or "make dist" will force an update. +$(srcdir)/$(DOMAIN).pot: + $(MAKE) $(DOMAIN).pot-update + +# This target rebuilds a PO file if $(DOMAIN).pot has changed. +# Note that a PO file is not touched if it doesn't need to be changed. +$(POFILES): $(POFILESDEPS) + @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \ + if test -f "$(srcdir)/$${lang}.po"; then \ + test -f $(srcdir)/$(DOMAIN).pot || $(MAKE) $(srcdir)/$(DOMAIN).pot; \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot"; \ + cd $(srcdir) \ + && { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \ + $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \ + *) \ + $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot;; \ + esac; \ + }; \ + else \ + $(MAKE) $${lang}.po-create; \ + fi + + +install: install-exec install-data +install-exec: +install-data: install-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \ + for file in $(DISTFILES.common) Makevars.template; do \ + $(INSTALL_DATA) $(srcdir)/$$file \ + $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + for file in Makevars; do \ + rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + else \ + : ; \ + fi +install-data-no: all +install-data-yes: all + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + dir=$(localedir)/$$lang/LC_MESSAGES; \ + $(mkdir_p) $(DESTDIR)$$dir; \ + if test -r $$cat; then realcat=$$cat; else realcat=$(srcdir)/$$cat; fi; \ + $(INSTALL_DATA) $$realcat $(DESTDIR)$$dir/$(DOMAIN).mo; \ + echo "installing $$realcat as $(DESTDIR)$$dir/$(DOMAIN).mo"; \ + for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ + if test -n "$$lc"; then \ + if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ + link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ + mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ + for file in *; do \ + if test -f $$file; then \ + ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ + fi; \ + done); \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + else \ + if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ + :; \ + else \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + fi; \ + fi; \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + ln -s ../LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ + ln $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ + cp -p $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + echo "installing $$realcat link as $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo"; \ + fi; \ + done; \ + done + +install-strip: install + +installdirs: installdirs-exec installdirs-data +installdirs-exec: +installdirs-data: installdirs-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \ + else \ + : ; \ + fi +installdirs-data-no: +installdirs-data-yes: + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + dir=$(localedir)/$$lang/LC_MESSAGES; \ + $(mkdir_p) $(DESTDIR)$$dir; \ + for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ + if test -n "$$lc"; then \ + if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ + link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ + mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ + for file in *; do \ + if test -f $$file; then \ + ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ + fi; \ + done); \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + else \ + if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ + :; \ + else \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + fi; \ + fi; \ + fi; \ + done; \ + done + +# Define this as empty until I found a useful application. +installcheck: + +uninstall: uninstall-exec uninstall-data +uninstall-exec: +uninstall-data: uninstall-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + for file in $(DISTFILES.common) Makevars.template; do \ + rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + else \ + : ; \ + fi +uninstall-data-no: +uninstall-data-yes: + catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + for lc in LC_MESSAGES $(EXTRA_LOCALE_CATEGORIES); do \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + done; \ + done + +check: all + +info dvi ps pdf html tags TAGS ctags CTAGS ID: + +mostlyclean: + rm -f remove-potcdate.sed + rm -f stamp-poT + rm -f core core.* $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po + rm -fr *.o + +clean: mostlyclean + +distclean: clean + rm -f Makefile Makefile.in POTFILES *.mo + +maintainer-clean: distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + rm -f stamp-po $(GMOFILES) + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) +dist distdir: + test -z "$(DISTFILESDEPS)" || $(MAKE) $(DISTFILESDEPS) + @$(MAKE) dist2 +# This is a separate target because 'update-po' must be executed before. +dist2: stamp-po $(DISTFILES) + dists="$(DISTFILES)"; \ + if test "$(PACKAGE)" = "gettext-tools"; then \ + dists="$$dists Makevars.template"; \ + fi; \ + if test -f $(srcdir)/$(DOMAIN).pot; then \ + dists="$$dists $(DOMAIN).pot stamp-po"; \ + fi; \ + if test -f $(srcdir)/ChangeLog; then \ + dists="$$dists ChangeLog"; \ + fi; \ + for i in 0 1 2 3 4 5 6 7 8 9; do \ + if test -f $(srcdir)/ChangeLog.$$i; then \ + dists="$$dists ChangeLog.$$i"; \ + fi; \ + done; \ + if test -f $(srcdir)/LINGUAS; then dists="$$dists LINGUAS"; fi; \ + for file in $$dists; do \ + if test -f $$file; then \ + cp -p $$file $(distdir) || exit 1; \ + else \ + cp -p $(srcdir)/$$file $(distdir) || exit 1; \ + fi; \ + done + +update-po: Makefile + $(MAKE) $(DOMAIN).pot-update + test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES) + $(MAKE) update-gmo + +# General rule for creating PO files. + +.nop.po-create: + @lang=`echo $@ | sed -e 's/\.po-create$$//'`; \ + echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \ + exit 1 + +# General rule for updating PO files. + +.nop.po-update: + @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \ + if test "$(PACKAGE)" = "gettext-tools"; then PATH=`pwd`/../src:$$PATH; fi; \ + tmpdir=`pwd`; \ + echo "$$lang:"; \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}$(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \ + cd $(srcdir); \ + if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \ + $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \ + *) \ + $(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \ + esac; \ + }; then \ + if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ + rm -f $$tmpdir/$$lang.new.po; \ + else \ + if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ + :; \ + else \ + echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ + exit 1; \ + fi; \ + fi; \ + else \ + echo "msgmerge for $$lang.po failed!" 1>&2; \ + rm -f $$tmpdir/$$lang.new.po; \ + fi + +$(DUMMYPOFILES): + +update-gmo: Makefile $(GMOFILES) + @: + +# Recreate Makefile by invoking config.status. Explicitly invoke the shell, +# because execution permission bits may not work on the current file system. +# Use @SHELL@, which is the shell determined by autoconf for the use by its +# scripts, not $(SHELL) which is hardwired to /bin/sh and may be deficient. +Makefile: Makefile.in.in Makevars $(top_builddir)/config.status @POMAKEFILEDEPS@ + cd $(top_builddir) \ + && @SHELL@ ./config.status $(subdir)/$@.in po-directories + +force: + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/po/Makevars b/po/Makevars new file mode 100644 index 0000000..ebb8a73 --- /dev/null +++ b/po/Makevars @@ -0,0 +1,68 @@ +# Makefile variables for PO directory in any package using GNU gettext. + +# Usually the message domain is the same as the package name. +DOMAIN = $(PACKAGE) + +# These two variables depend on the location of this directory. +subdir = po +top_builddir = .. + +# These options get passed to xgettext. +XGETTEXT_OPTIONS = --from-code=UTF-8 --keyword=_ --keyword=N_ \ + --keyword=C_:1c,2 --keyword=NC_:1c,2 \ + --keyword=g_dngettext:2,3 --add-comments \ + --flag=g_dngettext:2:pass-c-format \ + --flag=g_strdup_printf:1:c-format \ + --flag=g_string_printf:2:c-format \ + --flag=g_string_append_printf:2:c-format \ + --flag=g_error_new:3:c-format \ + --flag=g_set_error:4:c-format \ + --flag=g_markup_printf_escaped:1:c-format \ + --flag=g_log:3:c-format \ + --flag=g_print:1:c-format \ + --flag=g_printerr:1:c-format \ + --flag=g_printf:1:c-format \ + --flag=g_fprintf:2:c-format \ + --flag=g_sprintf:2:c-format \ + --flag=g_snprintf:3:c-format + + +# This is the copyright holder that gets inserted into the header of the +# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding +# package. (Note that the msgstr strings, extracted from the package's +# sources, belong to the copyright holder of the package.) Translators are +# expected to transfer the copyright for their translations to this person +# or entity, or to disclaim their copyright. The empty string stands for +# the public domain; in this case the translators are expected to disclaim +# their copyright. +COPYRIGHT_HOLDER = Translation copyright holder +# This is the email address or URL to which the translators shall report +# bugs in the untranslated strings: +# - Strings which are not entire sentences, see the maintainer guidelines +# in the GNU gettext documentation, section 'Preparing Strings'. +# - Strings which use unclear terms or require additional context to be +# understood. +# - Strings which make invalid assumptions about notation of date, time or +# money. +# - Pluralisation problems. +# - Incorrect English spelling. +# - Incorrect formatting. +# It can be your email address, or a mailing list address where translators +# can write to without being subscribed, or the URL of a web page through +# which the translators can contact you. +MSGID_BUGS_ADDRESS = http://bugzilla.gnome.org/enter_bug.cgi?product=mutter&keywords=I18N+L10N&component=general + +# This is the list of locale categories, beyond LC_MESSAGES, for which the +# message catalogs shall be used. It is usually empty. +EXTRA_LOCALE_CATEGORIES = + +# Ignore the timestamp of the .pot file, as git clones do not have +# deterministic timestamps, and .po files are updated by translators +# (only) in GNOME projects. +PO_DEPENDS_ON_POT = no + +# This tells whether or not to forcibly update $(DOMAIN).pot and +# regenerate PO files on "make dist". Possible values are "yes" and +# "no". Set this to no if the POT file and PO files are maintained +# externally. +DIST_DEPENDS_ON_UPDATE_PO = no diff --git a/po/POTFILES.in b/po/POTFILES.in new file mode 100644 index 0000000..a463e64 --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1,30 @@ +# List of source files containing translatable strings. +# Please keep this file sorted alphabetically. +data/50-mutter-navigation.xml +data/50-mutter-system.xml +data/50-mutter-windows.xml +data/mutter.desktop.in +data/org.gnome.mutter.gschema.xml.in +data/org.gnome.mutter.wayland.gschema.xml.in +src/backends/meta-input-settings.c +src/backends/meta-monitor-manager.c +src/compositor/compositor.c +src/compositor/meta-background.c +src/core/bell.c +src/core/core.c +src/core/delete.c +src/core/display.c +src/core/errors.c +src/core/keybindings.c +src/core/main.c +src/core/mutter.c +src/core/prefs.c +src/core/screen.c +src/core/util.c +src/core/window.c +src/ui/frames.c +src/ui/theme.c +src/wayland/meta-wayland-tablet-pad.c +src/x11/session.c +src/x11/window-props.c +src/x11/xprops.c diff --git a/po/Rules-quot b/po/Rules-quot new file mode 100644 index 0000000..9dc9630 --- /dev/null +++ b/po/Rules-quot @@ -0,0 +1,58 @@ +# This file, Rules-quot, can be copied and used freely without restrictions. +# Special Makefile rules for English message catalogs with quotation marks. + +DISTFILES.common.extra1 = quot.sed boldquot.sed en@quot.header en@boldquot.header insert-header.sin Rules-quot + +.SUFFIXES: .insert-header .po-update-en + +en@quot.po-create: + $(MAKE) en@quot.po-update +en@boldquot.po-create: + $(MAKE) en@boldquot.po-update + +en@quot.po-update: en@quot.po-update-en +en@boldquot.po-update: en@boldquot.po-update-en + +.insert-header.po-update-en: + @lang=`echo $@ | sed -e 's/\.po-update-en$$//'`; \ + if test "$(PACKAGE)" = "gettext-tools"; then PATH=`pwd`/../src:$$PATH; GETTEXTLIBDIR=`cd $(top_srcdir)/src && pwd`; export GETTEXTLIBDIR; fi; \ + tmpdir=`pwd`; \ + echo "$$lang:"; \ + ll=`echo $$lang | sed -e 's/@.*//'`; \ + LC_ALL=C; export LC_ALL; \ + cd $(srcdir); \ + if $(MSGINIT) $(MSGINIT_OPTIONS) -i $(DOMAIN).pot --no-translator -l $$lang -o - 2>/dev/null \ + | $(SED) -f $$tmpdir/$$lang.insert-header | $(MSGCONV) -t UTF-8 | \ + { case `$(MSGFILTER) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-8] | 0.1[0-8].*) \ + $(MSGFILTER) $(SED) -f `echo $$lang | sed -e 's/.*@//'`.sed \ + ;; \ + *) \ + $(MSGFILTER) `echo $$lang | sed -e 's/.*@//'` \ + ;; \ + esac } 2>/dev/null > $$tmpdir/$$lang.new.po \ + ; then \ + if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ + rm -f $$tmpdir/$$lang.new.po; \ + else \ + if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ + :; \ + else \ + echo "creation of $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ + exit 1; \ + fi; \ + fi; \ + else \ + echo "creation of $$lang.po failed!" 1>&2; \ + rm -f $$tmpdir/$$lang.new.po; \ + fi + +en@quot.insert-header: insert-header.sin + sed -e '/^#/d' -e 's/HEADER/en@quot.header/g' $(srcdir)/insert-header.sin > en@quot.insert-header + +en@boldquot.insert-header: insert-header.sin + sed -e '/^#/d' -e 's/HEADER/en@boldquot.header/g' $(srcdir)/insert-header.sin > en@boldquot.insert-header + +mostlyclean: mostlyclean-quot +mostlyclean-quot: + rm -f *.insert-header diff --git a/po/am.gmo b/po/am.gmo new file mode 100644 index 0000000000000000000000000000000000000000..6fbbfb902d362ded10ddab76baa37f83501efdec GIT binary patch literal 4536 zcmbuBYitx%6vr^>x%b?2 z?(CI@`9~O97_uC4bsl5g;I}v9f_7~_W4D5TgQS|bfHC~o0$gqf7lG(v%fQ9p3UDFV z1l|F*sOK*A+zpa_4154gfDeMNDIQb2sQQ0W{7rG;EhWEIidz(4P|PU42i}Eo$H05Q z%iwL`k06F(zk*9a3Em6-rMLu(rRPSF`Zp`~C=MvTs`!!OsN(mEKZEq1t00Z{2e=4a zh)K}AmV!QT4M_SRcqjOT>hA_AzB;%BG(k*}y#ms>hd>O;@`@j*{!c-Q?H{e$A znqmhQN6*6`^hW@mlUrnZbDLd{oo4n2Uml?fHW@(4z05RB>ggQ4Y)-y zsratyzo>XcaRHK){MIY>Dh?~2Qv3nLkNu8|AN&Wr5AQDSrDD-vk@+d=zX2 zzf<}@!DV<}jL9PeY&A&Z1i=9K42U0l85b;(9R_LNk1L*5`cV+u$=V^qys|hpjvH%P{UHZ_86`RrxzcZGp6S42~xnT zJ*uMy$W4&DArx=gqqUF_g!YwU_b`NFLGh#*Jqn?=3Zg+Mp5;clNzD(T{A+?xK2qCI zf)`(;k=NEKQqI#^#~Ks-0B=mNZ7G*^rgX=_)p7*iW0(nRh;_PligjjeTbM3)2Si%1 zh#os&q>W*^E8UchBSy?rJx1wfvd2oau!yx^@F8zp?pl1vviCWIdR*|p99{l7`sVTr zR`;8uD^%U9xq8#uAasH_fFR9Du9D%v(z)V5UAwpP@(Rn)du)ON6_;id$OTFGQe z@cv9H<-~0vOrEw9g7ul{$^54KnHk>a=t&XgjgF6%3WP_5nJM3=braoon3okUy@~f* zrpxwBW;=>)+Jl3~m{)QvMg_uRJ;I^liuIW`wvg?$T-Qpol)xt1MsmPqt~JPZ+t!OB z?rJ*|+H=Bo49g7jv~cyf;U4t$h(XJCwTP26655lQq@zWxF!$~5j%uB@&|O$-+jSQU z3Htpln!iH}bnrkh9P&5$p@E^+Bla6K>Xcnb^9MD5hzI=PKxhd;&nKkwCKS>tjHAy+>L`N-7q)tIEHkD`*_Cf*V?D- zXvY1**1F8Nl`za?n78jWTpt~UGIz3k7|QG?vT$DJ&M>;mUXb}OW$r7PKf-0uwx}952YSQK^3dqd*IfT~$1k z1&#=usnh0$8PeRcm^Js*XJmF%7RIosvobfq1Ds}x(Q~iM>;z_o*ZePkf4u|LJ%eDK zGpN@;ROkDf>-2A_)4#P&|F$~)+w1i2sOXOpqzavt?o?XY6O0P<#$H)CEOVDp8E0hS zn9NZf9Fv6+Sv-vg)L!2@_1T=eo={1JahV;*TdJ2G%BCheR7XvANa9-TYBWPi*D@M1 zw-z%bXf0;Q!&=OcZnc;pt7zR?sqY<35bzOr^w3CN?Pbr&f~vi8 aIU#a6%(6Hlvtx|Hm8XJMrB=XJuzvv_c(LRF literal 0 HcmV?d00001 diff --git a/po/am.po b/po/am.po new file mode 100644 index 0000000..0e70973 --- /dev/null +++ b/po/am.po @@ -0,0 +1,2696 @@ +# Translations into the Amharic Language. +# Copyright (C) 2002 Free Software Foundation, Inc. +# This file is distributed under the same license as the metacity package. +# Ge'ez Frontier Foundation , 2002. +# +# +msgid "" +msgstr "" +"Project-Id-Version: metacity\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2005-09-19 12:30+0200\n" +"PO-Revision-Date: 2003-02-03 10:16+EDT\n" +"Last-Translator: Ge'ez Frontier Foundation \n" +"Language-Team: Amharic \n" +"Language: am\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../src/tools/metacity-message.c:150 +#, c-format +msgid "Usage: %s\n" +msgstr "አጠቃቀም፦ %s\n" + +#: ../src/tools/metacity-message.c:176 ../src/util.c:128 +msgid "Metacity was compiled without support for verbose mode\n" +msgstr "" + +#: ../src/delete.c:63 ../src/delete.c:90 ../src/metacity-dialog.c:70 +#: ../src/theme-parser.c:467 +#, c-format +msgid "Could not parse \"%s\" as an integer" +msgstr "" + +#: ../src/delete.c:70 ../src/delete.c:97 ../src/metacity-dialog.c:77 +#: ../src/theme-parser.c:476 ../src/theme-parser.c:530 +#, c-format +msgid "Did not understand trailing characters \"%s\" in string \"%s\"" +msgstr "" + +#: ../src/delete.c:128 +#, c-format +msgid "Failed to parse message \"%s\" from dialog process\n" +msgstr "" + +#: ../src/delete.c:263 +#, c-format +msgid "Error reading from dialog display process: %s\n" +msgstr "" + +#: ../src/delete.c:344 +#, c-format +msgid "" +"Error launching metacity-dialog to ask about killing an application: %s\n" +msgstr "" + +#: ../src/delete.c:452 +#, c-format +msgid "Failed to get hostname: %s\n" +msgstr "" + +#: ../src/display.c:319 +#, c-format +msgid "Failed to open X Window System display '%s'\n" +msgstr "" + +#: ../src/errors.c:231 +#, c-format +msgid "" +"Lost connection to the display '%s';\n" +"most likely the X server was shut down or you killed/destroyed\n" +"the window manager.\n" +msgstr "" + +#: ../src/errors.c:238 +#, c-format +msgid "Fatal IO error %d (%s) on display '%s'.\n" +msgstr "" + +#: ../src/frames.c:1125 +msgid "Close Window" +msgstr "መስኮቱን ዝጋ" + +#: ../src/frames.c:1128 +msgid "Window Menu" +msgstr "የመስኮት ሜኑ" + +#: ../src/frames.c:1131 +msgid "Minimize Window" +msgstr "መስኮቱን አሳንስ" + +#: ../src/frames.c:1134 +msgid "Maximize Window" +msgstr "መስኮቱን አስተልቅ" + +#: ../src/frames.c:1137 +msgid "Unmaximize Window" +msgstr "መስኮቱን አታስተልቅ" + +#: ../src/keybindings.c:994 +#, c-format +msgid "" +"Some other program is already using the key %s with modifiers %x as a " +"binding\n" +msgstr "" + +#: ../src/keybindings.c:2620 +#, c-format +msgid "Error launching metacity-dialog to print an error about a command: %s\n" +msgstr "" + +#: ../src/keybindings.c:2725 +#, c-format +msgid "No command %d has been defined.\n" +msgstr "" + +#: ../src/keybindings.c:3570 +msgid "No terminal command has been defined.\n" +msgstr "" + +#: ../src/main.c:69 +#, c-format +msgid "" +"metacity %s\n" +"Copyright (C) 2001-2002 Havoc Pennington, Red Hat, Inc., and others\n" +"This is free software; see the source for copying conditions.\n" +"There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A " +"PARTICULAR PURPOSE.\n" +msgstr "" + +#: ../src/main.c:257 +msgid "Disable connection to session manager" +msgstr "" + +#: ../src/main.c:263 +msgid "Replace the running window manager with Metacity" +msgstr "" + +#: ../src/main.c:269 +msgid "Specify session management ID" +msgstr "" + +#: ../src/main.c:274 +msgid "X Display to use" +msgstr "" + +#: ../src/main.c:280 +msgid "Initialize session from savefile" +msgstr "" + +#: ../src/main.c:286 +msgid "Print version" +msgstr "" + +#: ../src/main.c:440 +#, c-format +msgid "Failed to scan themes directory: %s\n" +msgstr "" + +#: ../src/main.c:456 +#, c-format +msgid "" +"Could not find a theme! Be sure %s exists and contains the usual themes." +msgstr "" + +#: ../src/main.c:518 +#, c-format +msgid "Failed to restart: %s\n" +msgstr "" + +#: ../src/menu.c:54 +msgid "Mi_nimize" +msgstr "መሳንስ (_N)" + +#: ../src/menu.c:55 +msgid "Ma_ximize" +msgstr "መተልቅ (_X)" + +#: ../src/menu.c:56 +msgid "Unma_ximize" +msgstr "መታስተልቅ (_X)" + +#: ../src/menu.c:57 +msgid "Roll _Up" +msgstr "ማውጣት (_U)" + +#: ../src/menu.c:58 +msgid "_Unroll" +msgstr "ማውረድ (_U)" + +#: ../src/menu.c:59 ../src/menu.c:60 +msgid "On _Top" +msgstr "" + +#: ../src/menu.c:61 +msgid "_Move" +msgstr "መንቀሳቅስ (_M)" + +#: ../src/menu.c:62 +msgid "_Resize" +msgstr "እንደገና መጧን ማስተሥከል (_R)" + +#. separator +#: ../src/menu.c:64 +msgid "_Close" +msgstr "ዝጋ (_C)" + +#. separator +#: ../src/menu.c:66 +#, fuzzy +msgid "_Always on Visible Workspace" +msgstr "በዚህ መሥሪያ ቦታ ላይ ብቻ (_U)" + +#: ../src/menu.c:67 +#, fuzzy +msgid "_Only on This Workspace" +msgstr "በዚህ መሥሪያ ቦታ ላይ ብቻ (_U)" + +#: ../src/menu.c:68 +#, fuzzy +msgid "Move to Workspace _Left" +msgstr "መስኮትን ወደ መሥሪያ ቦታ 9 አንቀሳቅስ" + +#: ../src/menu.c:69 +#, fuzzy +msgid "Move to Workspace R_ight" +msgstr "መስኮትን ወደ መሥሪያ ቦታ 1 አንቀሳቅስ" + +#: ../src/menu.c:70 +#, fuzzy +msgid "Move to Workspace _Up" +msgstr "መስኮትን ወደ መሥሪያ ቦታ 1 አንቀሳቅስ" + +#: ../src/menu.c:71 +#, fuzzy +msgid "Move to Workspace _Down" +msgstr "መስኮትን ወደ መሥሪያ ቦታ 9 አንቀሳቅስ" + +#: ../src/menu.c:162 ../src/prefs.c:2106 +#, c-format +msgid "Workspace %d" +msgstr "መሥሪያ ቦታ %d" + +#: ../src/menu.c:171 +#, fuzzy +msgid "Workspace 1_0" +msgstr "መሥሪያ ቦታ %d" + +#: ../src/menu.c:173 +#, c-format +msgid "Workspace %s%d" +msgstr "መሥሪያ ቦታ %s%d" + +#: ../src/menu.c:368 +#, fuzzy +msgid "Move to Another _Workspace" +msgstr "መስኮትን ወደ መሥሪያ ቦታ 1 አንቀሳቅስ" + +#. This is the text that should appear next to menu accelerators +#. * that use the shift key. If the text on this key isn't typically +#. * translated on keyboards used for your language, don't translate +#. * this. +#. +#: ../src/metaaccellabel.c:105 +msgid "Shift" +msgstr "Shift" + +#. This is the text that should appear next to menu accelerators +#. * that use the control key. If the text on this key isn't typically +#. * translated on keyboards used for your language, don't translate +#. * this. +#. +#: ../src/metaaccellabel.c:111 +msgid "Ctrl" +msgstr "Ctrl" + +#. This is the text that should appear next to menu accelerators +#. * that use the alt key. If the text on this key isn't typically +#. * translated on keyboards used for your language, don't translate +#. * this. +#. +#: ../src/metaaccellabel.c:117 +msgid "Alt" +msgstr "Alt" + +#. This is the text that should appear next to menu accelerators +#. * that use the meta key. If the text on this key isn't typically +#. * translated on keyboards used for your language, don't translate +#. * this. +#. +#: ../src/metaaccellabel.c:123 +msgid "Meta" +msgstr "" + +#. This is the text that should appear next to menu accelerators +#. * that use the super key. If the text on this key isn't typically +#. * translated on keyboards used for your language, don't translate +#. * this. +#. +#: ../src/metaaccellabel.c:129 +msgid "Super" +msgstr "" + +#. This is the text that should appear next to menu accelerators +#. * that use the hyper key. If the text on this key isn't typically +#. * translated on keyboards used for your language, don't translate +#. * this. +#. +#: ../src/metaaccellabel.c:135 +msgid "Hyper" +msgstr "" + +#. This is the text that should appear next to menu accelerators +#. * that use the mod2 key. If the text on this key isn't typically +#. * translated on keyboards used for your language, don't translate +#. * this. +#. +#: ../src/metaaccellabel.c:141 +msgid "Mod2" +msgstr "" + +#. This is the text that should appear next to menu accelerators +#. * that use the mod3 key. If the text on this key isn't typically +#. * translated on keyboards used for your language, don't translate +#. * this. +#. +#: ../src/metaaccellabel.c:147 +msgid "Mod3" +msgstr "" + +#. This is the text that should appear next to menu accelerators +#. * that use the mod4 key. If the text on this key isn't typically +#. * translated on keyboards used for your language, don't translate +#. * this. +#. +#: ../src/metaaccellabel.c:153 +msgid "Mod4" +msgstr "" + +#. This is the text that should appear next to menu accelerators +#. * that use the mod5 key. If the text on this key isn't typically +#. * translated on keyboards used for your language, don't translate +#. * this. +#. +#: ../src/metaaccellabel.c:159 +msgid "Mod5" +msgstr "Mod5" + +#: ../src/metacity-dialog.c:110 +#, c-format +msgid "The window \"%s\" is not responding." +msgstr "" + +#: ../src/metacity-dialog.c:118 +msgid "" +"Forcing this application to quit will cause you to lose any unsaved changes." +msgstr "" + +#: ../src/metacity-dialog.c:129 +msgid "_Force Quit" +msgstr "" + +#: ../src/metacity-dialog.c:226 +msgid "Title" +msgstr "አርእስት" + +#: ../src/metacity-dialog.c:238 +msgid "Class" +msgstr "መደብ" + +#: ../src/metacity-dialog.c:264 +msgid "" +"These windows do not support \"save current setup\" and will have to be " +"restarted manually next time you log in." +msgstr "" + +#: ../src/metacity-dialog.c:330 +#, c-format +msgid "" +"There was an error running \"%s\":\n" +"%s." +msgstr "" + +#: ../src/metacity.desktop.in.h:1 +msgid "Metacity" +msgstr "" + +#: ../src/metacity.schemas.in.h:1 +msgid "(Not implemented) Navigation works in terms of applications not windows" +msgstr "" + +#: ../src/metacity.schemas.in.h:2 +msgid "" +"A font description string describing a font for window titlebars. The size " +"from the description will only be used if the titlebar_font_size option is " +"set to 0, however. Also, this option is disabled if the " +"titlebar_uses_desktop_font option is set to true. By default, titlebar_font " +"is unset, causing Metacity to fall back to the desktop font even if " +"titlebar_uses_desktop_font is false." +msgstr "" + +#: ../src/metacity.schemas.in.h:3 +msgid "Action on title bar double-click" +msgstr "" + +#: ../src/metacity.schemas.in.h:4 +msgid "Activate window menu" +msgstr "" + +#: ../src/metacity.schemas.in.h:5 +msgid "Arrangement of buttons on the titlebar" +msgstr "" + +#: ../src/metacity.schemas.in.h:6 +msgid "" +"Arrangement of buttons on the titlebar. The value should be a string, such " +"as \"menu:minimize,maximize,close\"; the colon separates the left corner of " +"the window from the right corner, and the button names are comma-separated. " +"Duplicate buttons are not allowed. Unknown button names are silently ignored " +"so that buttons can be added in future metacity versions without breaking " +"older versions." +msgstr "" + +#: ../src/metacity.schemas.in.h:7 +msgid "Automatically raises the focused window" +msgstr "" + +#: ../src/metacity.schemas.in.h:8 +msgid "" +"Clicking a window while holding down this modifier key will move the window " +"(left click), resize the window (middle click), or show the window menu " +"(right click). Modifier is expressed as \"<Alt>\" or \"<Super>\" " +"for example." +msgstr "" + +#: ../src/metacity.schemas.in.h:9 +#, fuzzy +msgid "Close window" +msgstr "መስኮትን ዝጋ" + +#: ../src/metacity.schemas.in.h:10 +msgid "Commands to run in response to keybindings" +msgstr "" + +#: ../src/metacity.schemas.in.h:11 +msgid "Current theme" +msgstr "የአሁኑን ጭብጥ" + +#: ../src/metacity.schemas.in.h:12 +msgid "Delay in milliseconds for the auto raise option" +msgstr "" + +#: ../src/metacity.schemas.in.h:13 +msgid "" +"Determines whether applications or the system can generate audible 'beeps'; " +"may be used in conjunction with 'visual bell' to allow silent 'beeps'." +msgstr "" + +#: ../src/metacity.schemas.in.h:14 +msgid "Disable misfeatures that are required by old or broken applications" +msgstr "" + +#: ../src/metacity.schemas.in.h:15 +msgid "Enable Visual Bell" +msgstr "" + +#: ../src/metacity.schemas.in.h:16 +msgid "Hide all windows and focus desktop" +msgstr "" + +#: ../src/metacity.schemas.in.h:17 +msgid "" +"If true, and the focus mode is either \"sloppy\" or \"mouse\" then the " +"focused window will be automatically raised after a delay (the delay is " +"specified by the auto_raise_delay key)." +msgstr "" + +#: ../src/metacity.schemas.in.h:18 +msgid "" +"If true, ignore the titlebar_font option, and use the standard application " +"font for window titles." +msgstr "" + +#: ../src/metacity.schemas.in.h:19 +msgid "" +"If true, metacity will give the user less feedback and less sense of " +"\"direct manipulation\", by using wireframes, avoiding animations, or other " +"means. This is a significant reduction in usability for many users, but may " +"allow legacy applications and terminal servers to function when they would " +"otherwise be impractical. However, the wireframe feature is disabled when " +"accessibility is on to avoid weird desktop breakages." +msgstr "" + +#: ../src/metacity.schemas.in.h:20 +msgid "" +"If true, then Metacity works in terms of applications rather than windows. " +"The concept is a bit abstract, but in general an application-based setup is " +"more like the Mac and less like Windows. When you focus a window in " +"application-based mode, all the windows in the application will be raised. " +"Also, in application-based mode, focus clicks are not passed through to " +"windows in other applications. The existence of this setting is somewhat " +"questionable. But it's better than having settings for all the specific " +"details of application-based vs. window-based, e.g. whether to pass through " +"clicks. Also, application-based mode is largely unimplemented at the moment." +msgstr "" + +#: ../src/metacity.schemas.in.h:21 +msgid "If true, trade off usability for less resource usage" +msgstr "" + +#: ../src/metacity.schemas.in.h:22 +msgid "Lower window below other windows" +msgstr "" + +#: ../src/metacity.schemas.in.h:23 +#, fuzzy +msgid "Maximize window" +msgstr "መስኮትን አስተልቅ" + +#: ../src/metacity.schemas.in.h:24 +msgid "Maximize window horizontally" +msgstr "" + +#: ../src/metacity.schemas.in.h:25 +msgid "Maximize window vertically" +msgstr "" + +#: ../src/metacity.schemas.in.h:26 +#, fuzzy +msgid "Minimize window" +msgstr "መስኮትን አሳንስ" + +#: ../src/metacity.schemas.in.h:27 +msgid "Modifier to use for modified window click actions" +msgstr "" + +#: ../src/metacity.schemas.in.h:28 +msgid "Move backward between panels and the desktop immediately" +msgstr "" + +#: ../src/metacity.schemas.in.h:29 +msgid "Move backwards between panels and the desktop with popup" +msgstr "" + +#: ../src/metacity.schemas.in.h:30 +msgid "Move backwards between windows immediately" +msgstr "" + +#: ../src/metacity.schemas.in.h:31 +msgid "Move between panels and the desktop immediately" +msgstr "" + +#: ../src/metacity.schemas.in.h:32 +msgid "Move between panels and the desktop with popup" +msgstr "" + +#: ../src/metacity.schemas.in.h:33 +msgid "Move between windows immediately" +msgstr "" + +#: ../src/metacity.schemas.in.h:34 +msgid "Move between windows with popup" +msgstr "" + +#: ../src/metacity.schemas.in.h:35 +msgid "Move focus backwards between windows using popup display" +msgstr "" + +#: ../src/metacity.schemas.in.h:36 +#, fuzzy +msgid "Move window" +msgstr "መስኮትን አንቀሳቅስ" + +#: ../src/metacity.schemas.in.h:37 +msgid "Move window one workspace down" +msgstr "" + +#: ../src/metacity.schemas.in.h:38 +msgid "Move window one workspace to the left" +msgstr "" + +#: ../src/metacity.schemas.in.h:39 +msgid "Move window one workspace to the right" +msgstr "" + +#: ../src/metacity.schemas.in.h:40 +msgid "Move window one workspace up" +msgstr "" + +#: ../src/metacity.schemas.in.h:41 +msgid "Move window to workspace 1" +msgstr "መስኮትን ወደ መሥሪያ ቦታ 1 አንቀሳቅስ" + +#: ../src/metacity.schemas.in.h:42 +msgid "Move window to workspace 10" +msgstr "መስኮትን ወደ መሥሪያ ቦታ 10 አንቀሳቅስ" + +#: ../src/metacity.schemas.in.h:43 +msgid "Move window to workspace 11" +msgstr "መስኮትን ወደ መሥሪያ ቦታ 11 አንቀሳቅስ" + +#: ../src/metacity.schemas.in.h:44 +msgid "Move window to workspace 12" +msgstr "መስኮትን ወደ መሥሪያ ቦታ 12 አንቀሳቅስ" + +#: ../src/metacity.schemas.in.h:45 +msgid "Move window to workspace 2" +msgstr "መስኮትን ወደ መሥሪያ ቦታ 2 አንቀሳቅስ" + +#: ../src/metacity.schemas.in.h:46 +msgid "Move window to workspace 3" +msgstr "መስኮትን ወደ መሥሪያ ቦታ 3 አንቀሳቅስ" + +#: ../src/metacity.schemas.in.h:47 +msgid "Move window to workspace 4" +msgstr "መስኮትን ወደ መሥሪያ ቦታ 4 አንቀሳቅስ" + +#: ../src/metacity.schemas.in.h:48 +msgid "Move window to workspace 5" +msgstr "መስኮትን ወደ መሥሪያ ቦታ 5 አንቀሳቅስ" + +#: ../src/metacity.schemas.in.h:49 +msgid "Move window to workspace 6" +msgstr "መስኮትን ወደ መሥሪያ ቦታ 6 አንቀሳቅስ" + +#: ../src/metacity.schemas.in.h:50 +msgid "Move window to workspace 7" +msgstr "መስኮትን ወደ መሥሪያ ቦታ 7 አንቀሳቅስ" + +#: ../src/metacity.schemas.in.h:51 +msgid "Move window to workspace 8" +msgstr "መስኮትን ወደ መሥሪያ ቦታ 8 አንቀሳቅስ" + +#: ../src/metacity.schemas.in.h:52 +msgid "Move window to workspace 9" +msgstr "መስኮትን ወደ መሥሪያ ቦታ 9 አንቀሳቅስ" + +#: ../src/metacity.schemas.in.h:53 +msgid "Name of workspace" +msgstr "የመሥሪያ ቦታ ስም" + +#: ../src/metacity.schemas.in.h:54 +msgid "Number of workspaces" +msgstr "የመሥሪያ ቦታዎች ብዛት" + +#: ../src/metacity.schemas.in.h:55 +msgid "" +"Number of workspaces. Must be more than zero, and has a fixed maximum (to " +"prevent accidentally destroying your desktop by asking for 34 million " +"workspaces)." +msgstr "" + +#: ../src/metacity.schemas.in.h:56 +msgid "Raise obscured window, otherwise lower" +msgstr "" + +#: ../src/metacity.schemas.in.h:57 +msgid "Raise window above other windows" +msgstr "" + +#: ../src/metacity.schemas.in.h:58 +#, fuzzy +msgid "Resize window" +msgstr "መስኮትን አሳንስ" + +#: ../src/metacity.schemas.in.h:59 +msgid "Run a defined command" +msgstr "" + +#: ../src/metacity.schemas.in.h:60 +msgid "Run a terminal" +msgstr "" + +#: ../src/metacity.schemas.in.h:61 +msgid "Show the panel menu" +msgstr "" + +#: ../src/metacity.schemas.in.h:62 +msgid "Show the panel run application dialog" +msgstr "" + +#: ../src/metacity.schemas.in.h:63 +msgid "" +"Some applications break specifications in ways that result in window manager " +"misfeatures. For example, ideally Metacity would place all dialogs in a " +"consistent position with respect to their parent window. This requires " +"ignoring application-specified positions for dialogs. But some versions of " +"Java/Swing mark their popup menus as dialogs, so Metacity has to disable " +"dialog positioning to allow menus to work in broken Java applications. There " +"are several other examples like this. This option puts Metacity in full-on " +"Correct mode, which perhaps gives a moderately nicer UI if you don't need to " +"run any broken apps. Sadly, workarounds must be enabled by default; the real " +"world is an ugly place. Some of the workarounds are workarounds for " +"limitations in the specifications themselves, so sometimes a bug in no-" +"workarounds mode won't be fixable without amending a spec." +msgstr "" + +#: ../src/metacity.schemas.in.h:64 +msgid "Switch to workspace 1" +msgstr "ወደ መሥሪያ ቦታ 1 ቀይር" + +#: ../src/metacity.schemas.in.h:65 +msgid "Switch to workspace 10" +msgstr "ወደ መሥሪያ ቦታ 10 ቀይር" + +#: ../src/metacity.schemas.in.h:66 +msgid "Switch to workspace 11" +msgstr "ወደ መሥሪያ ቦታ 11 ቀይር" + +#: ../src/metacity.schemas.in.h:67 +msgid "Switch to workspace 12" +msgstr "ወደ መሥሪያ ቦታ 12 ቀይር" + +#: ../src/metacity.schemas.in.h:68 +msgid "Switch to workspace 2" +msgstr "ወደ መሥሪያ ቦታ 2 ቀይር" + +#: ../src/metacity.schemas.in.h:69 +msgid "Switch to workspace 3" +msgstr "ወደ መሥሪያ ቦታ 3 ቀይር" + +#: ../src/metacity.schemas.in.h:70 +msgid "Switch to workspace 4" +msgstr "ወደ መሥሪያ ቦታ 4 ቀይር" + +#: ../src/metacity.schemas.in.h:71 +msgid "Switch to workspace 5" +msgstr "ወደ መሥሪያ ቦታ 5 ቀይር" + +#: ../src/metacity.schemas.in.h:72 +msgid "Switch to workspace 6" +msgstr "ወደ መሥሪያ ቦታ 6 ቀይር" + +#: ../src/metacity.schemas.in.h:73 +msgid "Switch to workspace 7" +msgstr "ወደ መሥሪያ ቦታ 7 ቀይር" + +#: ../src/metacity.schemas.in.h:74 +msgid "Switch to workspace 8" +msgstr "ወደ መሥሪያ ቦታ 8 ቀይር" + +#: ../src/metacity.schemas.in.h:75 +msgid "Switch to workspace 9" +msgstr "ወደ መሥሪያ ቦታ 9 ቀይር" + +#: ../src/metacity.schemas.in.h:76 +msgid "Switch to workspace above this one" +msgstr "" + +#: ../src/metacity.schemas.in.h:77 +msgid "Switch to workspace below this one" +msgstr "" + +#: ../src/metacity.schemas.in.h:78 +msgid "Switch to workspace on the left" +msgstr "" + +#: ../src/metacity.schemas.in.h:79 +msgid "Switch to workspace on the right" +msgstr "" + +#: ../src/metacity.schemas.in.h:80 +msgid "System Bell is Audible" +msgstr "" + +#: ../src/metacity.schemas.in.h:81 +msgid "Take a screenshot" +msgstr "" + +#: ../src/metacity.schemas.in.h:82 +msgid "Take a screenshot of a window" +msgstr "" + +#: ../src/metacity.schemas.in.h:83 +msgid "" +"Tells Metacity how to implement the visual indication that the system bell " +"or another application 'bell' indicator has been rung. Currently there are " +"two valid values, \"fullscreen\", which causes a fullscreen white-black " +"flash, and \"frame_flash\" which causes the titlebar of the application " +"which sent the bell signal to flash. If the application which sent the bell " +"is unknown (as is usually the case for the default \"system beep\"), the " +"currently focused window's titlebar is flashed." +msgstr "" + +#: ../src/metacity.schemas.in.h:84 +msgid "" +"The /apps/metacity/global_keybindings/run_command_N keys define keybindings " +"that correspond to these commands. Pressing the keybinding for run_command_N " +"will execute command_N." +msgstr "" + +#: ../src/metacity.schemas.in.h:85 +msgid "" +"The /apps/metacity/global_keybindings/run_command_screenshot key defines a " +"keybinding which causes the command specified by this setting to be invoked." +msgstr "" + +#: ../src/metacity.schemas.in.h:86 +msgid "" +"The /apps/metacity/global_keybindings/run_command_window_screenshot key " +"defines a keybinding which causes the command specified by this setting to " +"be invoked." +msgstr "" + +#: ../src/metacity.schemas.in.h:87 +msgid "" +"The keybinding that runs the correspondingly-numbered command in /apps/" +"metacity/keybinding_commands The format looks like \"<Control>a\" or " +"\"<Shift><Alt>F1\". The parser is fairly liberal and allows " +"lower or upper case, and also abbreviations such as \"<Ctl>\" and " +"\"<Ctrl>\". If you set the option to the special string \"disabled\", " +"then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:88 +msgid "" +"The keybinding that switches to the workspace above the current workspace. " +"The format looks like \"<Control>a\" or \"<Shift><Alt>F1" +"\". The parser is fairly liberal and allows lower or upper case, and also " +"abbreviations such as \"<Ctl>\" and \"<Ctrl>\". If you set the " +"option to the special string \"disabled\", then there will be no keybinding " +"for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:89 +msgid "" +"The keybinding that switches to the workspace below the current workspace. " +"The format looks like \"<Control>a\" or \"<Shift><Alt>F1" +"\". The parser is fairly liberal and allows lower or upper case, and also " +"abbreviations such as \"<Ctl>\" and \"<Ctrl>\". If you set the " +"option to the special string \"disabled\", then there will be no keybinding " +"for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:90 +msgid "" +"The keybinding that switches to the workspace on the left of the current " +"workspace. The format looks like \"<Control>a\" or \"<Shift><" +"Alt>F1\". The parser is fairly liberal and allows lower or upper case, " +"and also abbreviations such as \"<Ctl>\" and \"<Ctrl>\". If you " +"set the option to the special string \"disabled\", then there will be no " +"keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:91 +msgid "" +"The keybinding that switches to the workspace on the right of the current " +"workspace. The format looks like \"<Control>a\" or \"<Shift><" +"Alt>F1\". The parser is fairly liberal and allows lower or upper case, " +"and also abbreviations such as \"<Ctl>\" and \"<Ctrl>\". If you " +"set the option to the special string \"disabled\", then there will be no " +"keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:92 +msgid "" +"The keybinding that switches to workspace 1. The format looks like \"<" +"Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:93 +msgid "" +"The keybinding that switches to workspace 10. The format looks like \"<" +"Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:94 +msgid "" +"The keybinding that switches to workspace 11. The format looks like \"<" +"Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:95 +msgid "" +"The keybinding that switches to workspace 12. The format looks like \"<" +"Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:96 +msgid "" +"The keybinding that switches to workspace 2. The format looks like \"<" +"Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:97 +msgid "" +"The keybinding that switches to workspace 3. The format looks like \"<" +"Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:98 +msgid "" +"The keybinding that switches to workspace 4. The format looks like \"<" +"Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:99 +msgid "" +"The keybinding that switches to workspace 5. The format looks like \"<" +"Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:100 +msgid "" +"The keybinding that switches to workspace 6. The format looks like \"<" +"Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:101 +msgid "" +"The keybinding that switches to workspace 7. The format looks like \"<" +"Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:102 +msgid "" +"The keybinding that switches to workspace 8. The format looks like \"<" +"Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:103 +msgid "" +"The keybinding that switches to workspace 9. The format looks like \"<" +"Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:104 +msgid "" +"The keybinding used to activate the window menu. The format looks like \"<" +"Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:105 +msgid "" +"The keybinding used to close a window. The format looks like \"<" +"Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:106 +msgid "" +"The keybinding used to enter \"move mode\" and begin moving a window using " +"the keyboard. The format looks like \"<Control>a\" or \"<Shift>" +"<Alt>F1\". The parser is fairly liberal and allows lower or upper " +"case, and also abbreviations such as \"<Ctl>\" and \"<Ctrl>\". " +"If you set the option to the special string \"disabled\", then there will be " +"no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:107 +msgid "" +"The keybinding used to enter \"resize mode\" and begin resizing a window " +"using the keyboard. The format looks like \"<Control>a\" or \"<" +"Shift><Alt>F1\". The parser is fairly liberal and allows lower or " +"upper case, and also abbreviations such as \"<Ctl>\" and \"<Ctrl>" +"\". If you set the option to the special string \"disabled\", then there " +"will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:108 +msgid "" +"The keybinding used to hide all normal windows and set the focus to the " +"desktop background. The format looks like \"<Control>a\" or \"<" +"Shift><Alt>F1\". The parser is fairly liberal and allows lower or " +"upper case, and also abbreviations such as \"<Ctl>\" and \"<Ctrl>" +"\". If you set the option to the special string \"disabled\", then there " +"will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:109 +msgid "" +"The keybinding used to maximize a window. The format looks like \"<" +"Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:110 +msgid "" +"The keybinding used to minimize a window. The format looks like \"<" +"Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:111 +msgid "" +"The keybinding used to move a window one workspace down. The format looks " +"like \"<Control>a\" or \"<Shift><Alt>F1\". The parser is " +"fairly liberal and allows lower or upper case, and also abbreviations such " +"as \"<Ctl>\" and \"<Ctrl>\". If you set the option to the " +"special string \"disabled\", then there will be no keybinding for this " +"action." +msgstr "" + +#: ../src/metacity.schemas.in.h:112 +msgid "" +"The keybinding used to move a window one workspace to the left. The format " +"looks like \"<Control>a\" or \"<Shift><Alt>F1\". The " +"parser is fairly liberal and allows lower or upper case, and also " +"abbreviations such as \"<Ctl>\" and \"<Ctrl>\". If you set the " +"option to the special string \"disabled\", then there will be no keybinding " +"for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:113 +msgid "" +"The keybinding used to move a window one workspace to the right. The format " +"looks like \"<Control>a\" or \"<Shift><Alt>F1\". The " +"parser is fairly liberal and allows lower or upper case, and also " +"abbreviations such as \"<Ctl>\" and \"<Ctrl>\". If you set the " +"option to the special string \"disabled\", then there will be no keybinding " +"for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:114 +msgid "" +"The keybinding used to move a window one workspace up. The format looks like " +"\"<Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:115 +msgid "" +"The keybinding used to move a window to workspace 1. The format looks like " +"\"<Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:116 +msgid "" +"The keybinding used to move a window to workspace 10. The format looks like " +"\"<Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:117 +msgid "" +"The keybinding used to move a window to workspace 11. The format looks like " +"\"<Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:118 +msgid "" +"The keybinding used to move a window to workspace 12. The format looks like " +"\"<Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:119 +msgid "" +"The keybinding used to move a window to workspace 2. The format looks like " +"\"<Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:120 +msgid "" +"The keybinding used to move a window to workspace 3. The format looks like " +"\"<Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:121 +msgid "" +"The keybinding used to move a window to workspace 4. The format looks like " +"\"<Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:122 +msgid "" +"The keybinding used to move a window to workspace 5. The format looks like " +"\"<Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:123 +msgid "" +"The keybinding used to move a window to workspace 6. The format looks like " +"\"<Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:124 +msgid "" +"The keybinding used to move a window to workspace 7. The format looks like " +"\"<Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:125 +msgid "" +"The keybinding used to move a window to workspace 8. The format looks like " +"\"<Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:126 +msgid "" +"The keybinding used to move a window to workspace 9. The format looks like " +"\"<Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:127 +msgid "" +"The keybinding used to move focus backwards between panels and the desktop, " +"using a popup window. The format looks like \"<Control>a\" or \"<" +"Shift><Alt>F1\". The parser is fairly liberal and allows lower or " +"upper case, and also abbreviations such as \"<Ctl>\" and \"<Ctrl>" +"\". If you set the option to the special string \"disabled\", then there " +"will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:128 +msgid "" +"The keybinding used to move focus backwards between panels and the desktop, " +"without a popup window. The format looks like \"<Control>a\" or \"<" +"Shift><Alt>F1\". The parser is fairly liberal and allows lower or " +"upper case, and also abbreviations such as \"<Ctl>\" and \"<Ctrl>" +"\". If you set the option to the special string \"disabled\", then there " +"will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:129 +msgid "" +"The keybinding used to move focus backwards between windows without a popup " +"window. Holding \"shift\" together with this binding makes the direction go " +"forward again. The format looks like \"<Control>a\" or \"<Shift>" +"<Alt>F1\". The parser is fairly liberal and allows lower or upper " +"case, and also abbreviations such as \"<Ctl>\" and \"<Ctrl>\". " +"If you set the option to the special string \"disabled\", then there will be " +"no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:130 +msgid "" +"The keybinding used to move focus backwards between windows, using a popup " +"window. Holding \"shift\" together with this binding makes the direction go " +"forward again. The format looks like \"<Control>a\" or \"<Shift>" +"<Alt>F1\". The parser is fairly liberal and allows lower or upper " +"case, and also abbreviations such as \"<Ctl>\" and \"<Ctrl>\". " +"If you set the option to the special string \"disabled\", then there will be " +"no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:131 +msgid "" +"The keybinding used to move focus between panels and the desktop, using a " +"popup window. The format looks like \"<Control>a\" or \"<Shift>" +"<Alt>F1\". The parser is fairly liberal and allows lower or upper " +"case, and also abbreviations such as \"<Ctl>\" and \"<Ctrl>\". " +"If you set the option to the special string \"disabled\", then there will be " +"no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:132 +msgid "" +"The keybinding used to move focus between panels and the desktop, without a " +"popup window. The format looks like \"<Control>a\" or \"<Shift>" +"<Alt>F1\". The parser is fairly liberal and allows lower or upper " +"case, and also abbreviations such as \"<Ctl>\" and \"<Ctrl>\". " +"If you set the option to the special string \"disabled\", then there will be " +"no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:133 +msgid "" +"The keybinding used to move focus between windows without a popup window. " +"(Traditionally <Alt>Escape) Holding the \"shift\" key while using this " +"binding reverses the direction of movement. The format looks like \"<" +"Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:134 +msgid "" +"The keybinding used to move focus between windows, using a popup window. " +"(Traditionally <Alt>Tab) Holding the \"shift\" key while using this " +"binding reverses the direction of movement. The format looks like \"<" +"Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:135 +msgid "" +"The keybinding used to toggle always on top. A window that is always on top " +"will always be visible over other overlapping windows. The format looks like " +"\"<Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:136 +msgid "" +"The keybinding used to toggle fullscreen mode. The format looks like \"<" +"Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:137 +msgid "" +"The keybinding used to toggle maximization. The format looks like \"<" +"Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:138 +msgid "" +"The keybinding used to toggle shaded/unshaded state. The format looks like " +"\"<Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:139 +msgid "" +"The keybinding used to toggle whether the window is on all workspaces or " +"just one. The format looks like \"<Control>a\" or \"<Shift><" +"Alt>F1\". The parser is fairly liberal and allows lower or upper case, " +"and also abbreviations such as \"<Ctl>\" and \"<Ctrl>\". If you " +"set the option to the special string \"disabled\", then there will be no " +"keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:140 +msgid "" +"The keybinding used to unmaximize a window. The format looks like \"<" +"Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:141 +msgid "" +"The keybinding which display's the panel's \"Run Application\" dialog box. " +"The format looks like \"<Control>a\" or \"<Shift><Alt>F1" +"\". The parser is fairly liberal and allows lower or upper case, and also " +"abbreviations such as \"<Ctl>\" and \"<Ctrl>\". If you set the " +"option to the special string \"disabled\", then there will be no keybinding " +"for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:142 +msgid "" +"The keybinding which invokes a terminal. The format looks like \"<" +"Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:143 +msgid "" +"The keybinding which invokes the panel's screenshot utility to take a " +"screenshot of a window. The format looks like \"<Control>a\" or \"<" +"Shift><Alt>F1\". The parser is fairly liberal and allows lower or " +"upper case, and also abbreviations such as \"<Ctl>\" and \"<Ctrl>" +"\". If you set the option to the special string \"disabled\", then there " +"will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:144 +msgid "" +"The keybinding which invokes the panel's screenshot utility. The format " +"looks like \"<Control>a\" or \"<Shift><Alt>F1\". The " +"parser is fairly liberal and allows lower or upper case, and also " +"abbreviations such as \"<Ctl>\" and \"<Ctrl>\". If you set the " +"option to the special string \"disabled\", then there will be no keybinding " +"for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:145 +msgid "" +"The keybinding which shows the panel's main menu. The format looks like " +"\"<Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:146 +msgid "The name of a workspace." +msgstr "" + +#: ../src/metacity.schemas.in.h:147 +msgid "The screenshot command" +msgstr "" + +#: ../src/metacity.schemas.in.h:148 +msgid "" +"The theme determines the appearance of window borders, titlebar, and so " +"forth." +msgstr "" + +#: ../src/metacity.schemas.in.h:149 +msgid "" +"The time delay before raising a window if auto_raise is set to true. The " +"delay is given in thousandths of a second." +msgstr "" + +#: ../src/metacity.schemas.in.h:150 +msgid "" +"The window focus mode indicates how windows are activated. It has three " +"possible values; \"click\" means windows must be clicked in order to focus " +"them, \"sloppy\" means windows are focused when the mouse enters the window, " +"and \"mouse\" means windows are focused when the mouse enters the window and " +"unfocused when the mouse leaves the window." +msgstr "" + +#: ../src/metacity.schemas.in.h:151 +msgid "The window screenshot command" +msgstr "" + +#: ../src/metacity.schemas.in.h:152 +msgid "" +"This keybinding changes whether a window is above or below other windows. If " +"the window is covered by another window, it raises the window above other " +"windows. If the window is already fully visible, it lowers the window below " +"other windows. The format looks like \"<Control>a\" or \"<Shift>" +"<Alt>F1\". The parser is fairly liberal and allows lower or upper " +"case, and also abbreviations such as \"<Ctl>\" and \"<Ctrl>\". " +"If you set the option to the special string \"disabled\", then there will be " +"no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:153 +msgid "" +"This keybinding lowers a window below other windows. The format looks like " +"\"<Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:154 +msgid "" +"This keybinding raises the window above other windows. The format looks like " +"\"<Control>a\" or \"<Shift><Alt>F1\". The parser is fairly " +"liberal and allows lower or upper case, and also abbreviations such as \"<" +"Ctl>\" and \"<Ctrl>\". If you set the option to the special string " +"\"disabled\", then there will be no keybinding for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:155 +msgid "" +"This keybinding resizes a window to fill available horizontal space. The " +"format looks like \"<Control>a\" or \"<Shift><Alt>F1\". " +"The parser is fairly liberal and allows lower or upper case, and also " +"abbreviations such as \"<Ctl>\" and \"<Ctrl>\". If you set the " +"option to the special string \"disabled\", then there will be no keybinding " +"for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:156 +msgid "" +"This keybinding resizes a window to fill available vertical space. The " +"format looks like \"<Control>a\" or \"<Shift><Alt>F1\". " +"The parser is fairly liberal and allows lower or upper case, and also " +"abbreviations such as \"<Ctl>\" and \"<Ctrl>\". If you set the " +"option to the special string \"disabled\", then there will be no keybinding " +"for this action." +msgstr "" + +#: ../src/metacity.schemas.in.h:157 +msgid "" +"This option determines the effects of double-clicking on the title bar. " +"Current valid options are 'toggle_shade', which will shade/unshade the " +"window, and 'toggle_maximize' which will maximize/unmaximize the window." +msgstr "" + +#: ../src/metacity.schemas.in.h:158 +msgid "Toggle always on top state" +msgstr "" + +#: ../src/metacity.schemas.in.h:159 +msgid "Toggle fullscreen mode" +msgstr "የሙሉ እስክሪን ዘዴን ቀያይሩ" + +#: ../src/metacity.schemas.in.h:160 +msgid "Toggle maximization state" +msgstr "" + +#: ../src/metacity.schemas.in.h:161 +msgid "Toggle shaded state" +msgstr "" + +#: ../src/metacity.schemas.in.h:162 +msgid "Toggle window on all workspaces" +msgstr "" + +#: ../src/metacity.schemas.in.h:163 +msgid "" +"Turns on a visual indication when an application or the system issues a " +"'bell' or 'beep'; useful for the hard-of-hearing and for use in noisy " +"environments, or when 'audible bell' is off." +msgstr "" + +#: ../src/metacity.schemas.in.h:164 +#, fuzzy +msgid "Unmaximize window" +msgstr "መስኮቱን አታስተልቅ" + +#: ../src/metacity.schemas.in.h:165 +msgid "Use standard system font in window titles" +msgstr "" + +#: ../src/metacity.schemas.in.h:166 +msgid "Visual Bell Type" +msgstr "" + +#: ../src/metacity.schemas.in.h:167 +msgid "Window focus mode" +msgstr "" + +#: ../src/metacity.schemas.in.h:168 +msgid "Window title font" +msgstr "የመስኮት አርእስት የፊደል ቅርጽ" + +#: ../src/prefs.c:528 ../src/prefs.c:544 ../src/prefs.c:560 ../src/prefs.c:576 +#: ../src/prefs.c:592 ../src/prefs.c:612 ../src/prefs.c:628 ../src/prefs.c:644 +#: ../src/prefs.c:660 ../src/prefs.c:676 ../src/prefs.c:692 ../src/prefs.c:708 +#: ../src/prefs.c:724 ../src/prefs.c:741 ../src/prefs.c:757 ../src/prefs.c:773 +#: ../src/prefs.c:789 ../src/prefs.c:805 ../src/prefs.c:820 ../src/prefs.c:835 +#: ../src/prefs.c:850 ../src/prefs.c:866 ../src/prefs.c:882 ../src/prefs.c:898 +#, c-format +msgid "GConf key \"%s\" is set to an invalid type\n" +msgstr "" + +#: ../src/prefs.c:943 +#, c-format +msgid "" +"\"%s\" found in configuration database is not a valid value for mouse button " +"modifier\n" +msgstr "" + +#: ../src/prefs.c:967 ../src/prefs.c:1428 +#, c-format +msgid "GConf key '%s' is set to an invalid value\n" +msgstr "" + +#: ../src/prefs.c:1145 +#, c-format +msgid "Could not parse font description \"%s\" from GConf key %s\n" +msgstr "" + +#: ../src/prefs.c:1330 +#, c-format +msgid "" +"%d stored in GConf key %s is not a reasonable number of workspaces, current " +"maximum is %d\n" +msgstr "" + +#: ../src/prefs.c:1390 +msgid "" +"Workarounds for broken applications disabled. Some applications may not " +"behave properly.\n" +msgstr "" + +#: ../src/prefs.c:1455 +#, c-format +msgid "%d stored in GConf key %s is out of range 0 to %d\n" +msgstr "" + +#: ../src/prefs.c:1589 +#, c-format +msgid "Error setting number of workspaces to %d: %s\n" +msgstr "" + +#: ../src/prefs.c:1833 +#, c-format +msgid "" +"\"%s\" found in configuration database is not a valid value for keybinding " +"\"%s\"\n" +msgstr "" + +#: ../src/prefs.c:2187 +#, c-format +msgid "Error setting name for workspace %d to \"%s\": %s\n" +msgstr "" + +#: ../src/resizepopup.c:126 +#, c-format +msgid "%d x %d" +msgstr "%d በ %d" + +#: ../src/screen.c:408 +#, c-format +msgid "Screen %d on display '%s' is invalid\n" +msgstr "" + +#: ../src/screen.c:424 +#, c-format +msgid "" +"Screen %d on display \"%s\" already has a window manager; try using the --" +"replace option to replace the current window manager.\n" +msgstr "" + +#: ../src/screen.c:448 +#, c-format +msgid "" +"Could not acquire window manager selection on screen %d display \"%s\"\n" +msgstr "" + +#: ../src/screen.c:506 +#, c-format +msgid "Screen %d on display \"%s\" already has a window manager\n" +msgstr "" + +#: ../src/screen.c:716 +#, c-format +msgid "Could not release screen %d on display \"%s\"\n" +msgstr "" + +#: ../src/session.c:884 ../src/session.c:891 +#, c-format +msgid "Could not create directory '%s': %s\n" +msgstr "" + +#: ../src/session.c:901 +#, c-format +msgid "Could not open session file '%s' for writing: %s\n" +msgstr "" + +#: ../src/session.c:1053 +#, c-format +msgid "Error writing session file '%s': %s\n" +msgstr "" + +#: ../src/session.c:1058 +#, c-format +msgid "Error closing session file '%s': %s\n" +msgstr "" + +#: ../src/session.c:1133 +#, c-format +msgid "Failed to read saved session file %s: %s\n" +msgstr "" + +#: ../src/session.c:1168 +#, c-format +msgid "Failed to parse saved session file: %s\n" +msgstr "" + +#: ../src/session.c:1217 +msgid " attribute seen but we already have the session ID" +msgstr "" + +#: ../src/session.c:1230 +#, c-format +msgid "Unknown attribute %s on element" +msgstr "" + +#: ../src/session.c:1247 +msgid "nested tag" +msgstr "" + +#: ../src/session.c:1305 ../src/session.c:1337 +#, c-format +msgid "Unknown attribute %s on element" +msgstr "" + +#: ../src/session.c:1409 +#, c-format +msgid "Unknown attribute %s on element" +msgstr "" + +#: ../src/session.c:1469 +#, c-format +msgid "Unknown attribute %s on element" +msgstr "" + +#: ../src/session.c:1489 +#, c-format +msgid "Unknown element %s" +msgstr "" + +#: ../src/session.c:1961 +#, c-format +msgid "" +"Error launching metacity-dialog to warn about apps that don't support " +"session management: %s\n" +msgstr "" + +#: ../src/theme-parser.c:224 ../src/theme-parser.c:242 +#, c-format +msgid "Line %d character %d: %s" +msgstr "" + +#: ../src/theme-parser.c:396 +#, c-format +msgid "Attribute \"%s\" repeated twice on the same <%s> element" +msgstr "" + +#: ../src/theme-parser.c:414 ../src/theme-parser.c:439 +#, c-format +msgid "Attribute \"%s\" is invalid on <%s> element in this context" +msgstr "" + +#: ../src/theme-parser.c:485 +#, c-format +msgid "Integer %ld must be positive" +msgstr "" + +#: ../src/theme-parser.c:493 +#, c-format +msgid "Integer %ld is too large, current max is %d" +msgstr "" + +#: ../src/theme-parser.c:521 ../src/theme-parser.c:602 +#: ../src/theme-parser.c:626 +#, c-format +msgid "Could not parse \"%s\" as a floating point number" +msgstr "" + +#: ../src/theme-parser.c:552 +#, c-format +msgid "Boolean values must be \"true\" or \"false\" not \"%s\"" +msgstr "" + +#: ../src/theme-parser.c:572 +#, c-format +msgid "Angle must be between 0.0 and 360.0, was %g\n" +msgstr "" + +#: ../src/theme-parser.c:638 +#, c-format +msgid "Alpha must be between 0.0 (invisible) and 1.0 (fully opaque), was %g\n" +msgstr "" + +#: ../src/theme-parser.c:684 +#, c-format +msgid "" +"Invalid title scale \"%s\" (must be one of xx-small,x-small,small,medium," +"large,x-large,xx-large)\n" +msgstr "" + +#: ../src/theme-parser.c:729 ../src/theme-parser.c:737 +#: ../src/theme-parser.c:807 ../src/theme-parser.c:897 +#: ../src/theme-parser.c:935 ../src/theme-parser.c:1012 +#: ../src/theme-parser.c:1062 ../src/theme-parser.c:1070 +#: ../src/theme-parser.c:1126 ../src/theme-parser.c:1134 +#: ../src/theme-parser.c:2936 ../src/theme-parser.c:3025 +#: ../src/theme-parser.c:3032 ../src/theme-parser.c:3039 +#, c-format +msgid "No \"%s\" attribute on <%s> element" +msgstr "" + +#: ../src/theme-parser.c:837 ../src/theme-parser.c:905 +#: ../src/theme-parser.c:943 ../src/theme-parser.c:1020 +#, c-format +msgid "<%s> name \"%s\" used a second time" +msgstr "" + +#: ../src/theme-parser.c:849 ../src/theme-parser.c:955 +#: ../src/theme-parser.c:1032 +#, c-format +msgid "<%s> parent \"%s\" has not been defined" +msgstr "" + +#: ../src/theme-parser.c:968 +#, c-format +msgid "<%s> geometry \"%s\" has not been defined" +msgstr "" + +#: ../src/theme-parser.c:981 +#, c-format +msgid "<%s> must specify either a geometry or a parent that has a geometry" +msgstr "" + +#: ../src/theme-parser.c:1080 +#, c-format +msgid "Unknown type \"%s\" on <%s> element" +msgstr "" + +#: ../src/theme-parser.c:1091 +#, c-format +msgid "Unknown style_set \"%s\" on <%s> element" +msgstr "" + +#: ../src/theme-parser.c:1099 +#, c-format +msgid "Window type \"%s\" has already been assigned a style set" +msgstr "" + +#: ../src/theme-parser.c:1143 +#, c-format +msgid "Unknown function \"%s\" for menu icon" +msgstr "" + +#: ../src/theme-parser.c:1152 +#, c-format +msgid "Unknown state \"%s\" for menu icon" +msgstr "" + +#: ../src/theme-parser.c:1160 +#, c-format +msgid "Theme already has a menu icon for function %s state %s" +msgstr "" + +#: ../src/theme-parser.c:1177 ../src/theme-parser.c:3244 +#: ../src/theme-parser.c:3323 +#, c-format +msgid "No with the name \"%s\" has been defined" +msgstr "" + +#: ../src/theme-parser.c:1192 ../src/theme-parser.c:1256 +#: ../src/theme-parser.c:1545 ../src/theme-parser.c:3124 +#: ../src/theme-parser.c:3178 ../src/theme-parser.c:3338 +#: ../src/theme-parser.c:3515 ../src/theme-parser.c:3553 +#: ../src/theme-parser.c:3591 ../src/theme-parser.c:3629 +#, c-format +msgid "Element <%s> is not allowed below <%s>" +msgstr "" + +#: ../src/theme-parser.c:1282 ../src/theme-parser.c:1369 +#: ../src/theme-parser.c:1439 +#, c-format +msgid "No \"name\" attribute on element <%s>" +msgstr "" + +#: ../src/theme-parser.c:1289 ../src/theme-parser.c:1376 +#, c-format +msgid "No \"value\" attribute on element <%s>" +msgstr "" + +#: ../src/theme-parser.c:1320 ../src/theme-parser.c:1334 +#: ../src/theme-parser.c:1393 +msgid "" +"Cannot specify both button_width/button_height and aspect ratio for buttons" +msgstr "" + +#: ../src/theme-parser.c:1343 +#, c-format +msgid "Distance \"%s\" is unknown" +msgstr "" + +#: ../src/theme-parser.c:1402 +#, c-format +msgid "Aspect ratio \"%s\" is unknown" +msgstr "" + +#: ../src/theme-parser.c:1446 +#, c-format +msgid "No \"top\" attribute on element <%s>" +msgstr "" + +#: ../src/theme-parser.c:1453 +#, c-format +msgid "No \"bottom\" attribute on element <%s>" +msgstr "" + +#: ../src/theme-parser.c:1460 +#, c-format +msgid "No \"left\" attribute on element <%s>" +msgstr "" + +#: ../src/theme-parser.c:1467 +#, c-format +msgid "No \"right\" attribute on element <%s>" +msgstr "" + +#: ../src/theme-parser.c:1499 +#, c-format +msgid "Border \"%s\" is unknown" +msgstr "" + +#: ../src/theme-parser.c:1655 ../src/theme-parser.c:1765 +#: ../src/theme-parser.c:1868 ../src/theme-parser.c:2055 +#: ../src/theme-parser.c:2869 +#, c-format +msgid "No \"color\" attribute on element <%s>" +msgstr "" + +#: ../src/theme-parser.c:1662 +#, c-format +msgid "No \"x1\" attribute on element <%s>" +msgstr "" + +#: ../src/theme-parser.c:1669 ../src/theme-parser.c:2714 +#, c-format +msgid "No \"y1\" attribute on element <%s>" +msgstr "" + +#: ../src/theme-parser.c:1676 +#, c-format +msgid "No \"x2\" attribute on element <%s>" +msgstr "" + +#: ../src/theme-parser.c:1683 ../src/theme-parser.c:2721 +#, c-format +msgid "No \"y2\" attribute on element <%s>" +msgstr "" + +#: ../src/theme-parser.c:1772 ../src/theme-parser.c:1875 +#: ../src/theme-parser.c:1981 ../src/theme-parser.c:2062 +#: ../src/theme-parser.c:2168 ../src/theme-parser.c:2266 +#: ../src/theme-parser.c:2483 ../src/theme-parser.c:2609 +#: ../src/theme-parser.c:2707 ../src/theme-parser.c:2781 +#: ../src/theme-parser.c:2876 +#, c-format +msgid "No \"x\" attribute on element <%s>" +msgstr "" + +#: ../src/theme-parser.c:1779 ../src/theme-parser.c:1882 +#: ../src/theme-parser.c:1988 ../src/theme-parser.c:2069 +#: ../src/theme-parser.c:2175 ../src/theme-parser.c:2273 +#: ../src/theme-parser.c:2490 ../src/theme-parser.c:2616 +#: ../src/theme-parser.c:2788 ../src/theme-parser.c:2883 +#, c-format +msgid "No \"y\" attribute on element <%s>" +msgstr "" + +#: ../src/theme-parser.c:1786 ../src/theme-parser.c:1889 +#: ../src/theme-parser.c:1995 ../src/theme-parser.c:2076 +#: ../src/theme-parser.c:2182 ../src/theme-parser.c:2280 +#: ../src/theme-parser.c:2497 ../src/theme-parser.c:2623 +#: ../src/theme-parser.c:2795 +#, c-format +msgid "No \"width\" attribute on element <%s>" +msgstr "" + +#: ../src/theme-parser.c:1793 ../src/theme-parser.c:1896 +#: ../src/theme-parser.c:2002 ../src/theme-parser.c:2083 +#: ../src/theme-parser.c:2189 ../src/theme-parser.c:2287 +#: ../src/theme-parser.c:2504 ../src/theme-parser.c:2630 +#: ../src/theme-parser.c:2802 +#, c-format +msgid "No \"height\" attribute on element <%s>" +msgstr "" + +#: ../src/theme-parser.c:1903 +#, c-format +msgid "No \"start_angle\" attribute on element <%s>" +msgstr "" + +#: ../src/theme-parser.c:1910 +#, c-format +msgid "No \"extent_angle\" attribute on element <%s>" +msgstr "" + +#: ../src/theme-parser.c:2090 +#, c-format +msgid "No \"alpha\" attribute on element <%s>" +msgstr "" + +#: ../src/theme-parser.c:2161 +#, c-format +msgid "No \"type\" attribute on element <%s>" +msgstr "" + +#: ../src/theme-parser.c:2209 +#, c-format +msgid "Did not understand value \"%s\" for type of gradient" +msgstr "" + +#: ../src/theme-parser.c:2294 +#, c-format +msgid "No \"filename\" attribute on element <%s>" +msgstr "" + +#: ../src/theme-parser.c:2319 ../src/theme-parser.c:2827 +#, c-format +msgid "Did not understand fill type \"%s\" for <%s> element" +msgstr "" + +#: ../src/theme-parser.c:2462 ../src/theme-parser.c:2595 +#: ../src/theme-parser.c:2700 +#, c-format +msgid "No \"state\" attribute on element <%s>" +msgstr "" + +#: ../src/theme-parser.c:2469 ../src/theme-parser.c:2602 +#, c-format +msgid "No \"shadow\" attribute on element <%s>" +msgstr "" + +#: ../src/theme-parser.c:2476 +#, c-format +msgid "No \"arrow\" attribute on element <%s>" +msgstr "" + +#: ../src/theme-parser.c:2529 ../src/theme-parser.c:2651 +#: ../src/theme-parser.c:2739 +#, c-format +msgid "Did not understand state \"%s\" for <%s> element" +msgstr "" + +#: ../src/theme-parser.c:2539 ../src/theme-parser.c:2661 +#, c-format +msgid "Did not understand shadow \"%s\" for <%s> element" +msgstr "" + +#: ../src/theme-parser.c:2549 +#, c-format +msgid "Did not understand arrow \"%s\" for <%s> element" +msgstr "" + +#: ../src/theme-parser.c:2962 ../src/theme-parser.c:3078 +#, c-format +msgid "No called \"%s\" has been defined" +msgstr "" + +#: ../src/theme-parser.c:2974 ../src/theme-parser.c:3090 +#, c-format +msgid "Including draw_ops \"%s\" here would create a circular reference" +msgstr "" + +#: ../src/theme-parser.c:3153 +#, c-format +msgid "No \"value\" attribute on <%s> element" +msgstr "" + +#: ../src/theme-parser.c:3210 +#, c-format +msgid "No \"position\" attribute on <%s> element" +msgstr "" + +#: ../src/theme-parser.c:3219 +#, c-format +msgid "Unknown position \"%s\" for frame piece" +msgstr "" + +#: ../src/theme-parser.c:3227 +#, c-format +msgid "Frame style already has a piece at position %s" +msgstr "" + +#: ../src/theme-parser.c:3272 +#, c-format +msgid "No \"function\" attribute on <%s> element" +msgstr "" + +#: ../src/theme-parser.c:3280 ../src/theme-parser.c:3384 +#, c-format +msgid "No \"state\" attribute on <%s> element" +msgstr "" + +#: ../src/theme-parser.c:3289 +#, c-format +msgid "Unknown function \"%s\" for button" +msgstr "" + +#: ../src/theme-parser.c:3298 +#, c-format +msgid "Unknown state \"%s\" for button" +msgstr "" + +#: ../src/theme-parser.c:3306 +#, c-format +msgid "Frame style already has a button for function %s state %s" +msgstr "" + +#: ../src/theme-parser.c:3376 +#, c-format +msgid "No \"focus\" attribute on <%s> element" +msgstr "" + +#: ../src/theme-parser.c:3392 +#, c-format +msgid "No \"style\" attribute on <%s> element" +msgstr "" + +#: ../src/theme-parser.c:3401 +#, c-format +msgid "\"%s\" is not a valid value for focus attribute" +msgstr "" + +#: ../src/theme-parser.c:3410 +#, c-format +msgid "\"%s\" is not a valid value for state attribute" +msgstr "" + +#: ../src/theme-parser.c:3420 +#, c-format +msgid "A style called \"%s\" has not been defined" +msgstr "" + +#: ../src/theme-parser.c:3430 +#, c-format +msgid "No \"resize\" attribute on <%s> element" +msgstr "" + +#: ../src/theme-parser.c:3440 +#, c-format +msgid "\"%s\" is not a valid value for resize attribute" +msgstr "" + +#: ../src/theme-parser.c:3450 +#, c-format +msgid "" +"Should not have \"resize\" attribute on <%s> element for maximized/shaded " +"states" +msgstr "" + +#: ../src/theme-parser.c:3464 +#, c-format +msgid "Style has already been specified for state %s resize %s focus %s" +msgstr "" + +#: ../src/theme-parser.c:3475 ../src/theme-parser.c:3486 +#: ../src/theme-parser.c:3497 +#, c-format +msgid "Style has already been specified for state %s focus %s" +msgstr "" + +#: ../src/theme-parser.c:3536 +msgid "" +"Can't have a two draw_ops for a element (theme specified a draw_ops " +"attribute and also a element, or specified two elements)" +msgstr "" + +#: ../src/theme-parser.c:3574 +msgid "" +"Can't have a two draw_ops for a